%{ #include #include #include #include "flib.h" #include "const.h" #include "..\db\db.h" #include "sfl.h" #include "table.h" #include "expsfl.h" #include "ssgen.h" #include "insert.h" #include "condtree.h" #include "cond.h" #include "query.h" #include "queryf.h" #define MAX_LINE 100 enum modes { PLAIN_SELECT_FIELD = 1, AGGREGATE_SELECT_FIELD = 2 }; int mode = PLAIN_SELECT_FIELD; enum query_part { UNDEFINED = 0,SELECT_PART = 1, TABLE_PART = 2, GROUP_BY_PART = 3, ORDER_BY_PART = 4}; int query_part = SELECT_PART; int delete2 = 0; char dbDir[MAX_LINE],workDir[MAX_LINE]; char opFile[MAX_LINE],opFilet[MAX_LINE]; int beautify = 0; int constType; /* What is the type of the constant */ extern char *yytext; ConditionTree *rootCondition; int first = 1; /* Used for sub queries */ %} %union { char str[MAX_LINE]; ConditionTree *cond; } %right NOT AND OR %left '*' '/' '+' '-' %left EQUAL NOTEQ GREAT LESS GREATEQ LESSEQ %token OPEN CLOSE DATABASE %token SELECT FROM WHERE EXISTS IN BETWEEN LIKE IS UNION %token HAVING GROUP ORDER BY %token EXISTS %token ASC DESC %token DISTINCT ALL %token COUNT SUM AVG MIN MAX %token SNULL %token INSERT INTO VALUES %token UPDATE %token DELETE %token IDENTIFIER FIELD_IDENTIFIER %token COMMA SEMICOLON %token AND OR NOT %token EQUAL GREATEQ LESSEQ LESS GREAT NOTEQ %token CONST_NUM CONST_REAL CONST_DATE %token CONST_STR %token DBDIR WORKDIR OPFILE OPFILET PRINT BEAUTIFY ON OFF %type const const_str const_num const_real const_date %type cfield ifield %type field_oper_field %type field_oper_const %type field_oper_subquery %type field_exists_subquery %type simple_condition %type condition %% start : sql_stmt_list { puts("parse sql_stmt_list"); } sql_stmt_list : sql_stmt_list sql_statement { puts("parse sql_stmt_list sql_statement"); } | sql_statement { puts("parse sql_statement"); } sql_statement : sql_stmt sql_stmt_term { /* The end of the query parsing */ query_part = UNDEFINED; /*InitialiseSelectField(); InitialiseTableList();*/ #ifdef DEBUG puts("************** Parsed over ************"); #endif } | error { puts("Syntax error"); throw_away(); yyerrok; yyclearin; } sql_stmt_term : SEMICOLON sql_stmt : select_query { /* SQL statement over */ TraverseQuery(); ResetQuery(); } | insert_stmt | update_stmt | delete_stmt { delete2 = 1; TraverseQuery(); ResetQuery(); delete2 = 0; /* delete is also reset from GenerateBody */ } | open_stmt | close_stmt | misc_stmt open_stmt : OPEN DATABASE CONST_STR { puts("Loading the database"); printf("database %s\n",$3); LoadDataBase($3); } close_stmt : CLOSE DATABASE select_query : SELECT { puts("SELECT"); query_part = SELECT_PART; if (!first) AddSubQuery(); else { first = 0; InitRootQuery(); } } f_list FROM { query_part = TABLE_PART; #ifdef DEBUG puts("Query Table"); #endif } table_list where_part | select_query UNION select_query | select_query UNION ALL select_query where_part : /* Nothing */ | WHERE condition rest_select { rootCondition = $2; } | rest_select rest_select : /* Nothing */ | group_by having order | order group_by : GROUP BY { query_part = GROUP_BY_PART; #ifdef DEBUG puts("Query Group"); #endif } plain_field_list having : /* Nothing */ | HAVING condition order : /* Nothing */ | ORDER BY { query_part = ORDER_BY_PART; #ifdef DEBUG puts("Query Order"); #endif } order_list order_list : field sort_type COMMA order_list | field sort_type sort_type : /* NOTHING */ | ASC | DESC f_list : DISTINCT field_list | ALL field_list | field_list | '*' agg_field_list : DISTINCT agg_plain_field_list | ALL agg_plain_field_list | agg_plain_field_list | '*' agg_plain_field_list : agg_plain_field_list COMMA plain_field { } | plain_field { } plain_field_list : plain_field_list COMMA plain_field { } | plain_field { } field_list : field_list COMMA field { } | field { } table_list : table_list COMMA table | table condition : '(' condition ')' { $$ = $2; } | condition AND condition { $$ = MakeBoolCondition(AND); $$->leftCondition = $1; $$->rightCondition = $3; } | condition OR condition { $$ = MakeBoolCondition(OR); $$->leftCondition = $1; $$->rightCondition = $3; } | NOT condition { $$ = MakeBoolCondition(NOT); $$->rightCondition = $2; } | simple_condition { $$ = $1; } simple_condition : field_oper_const /* sico 1 */ { $$ = $1; } | field_oper_field /* sico 2 */ { $$ = $1; } | field_oper_subquery /* sico 3 */ { $$ = $1; } | cfield IN '(' sub_select_query ')' /* sico 4 */ { $$ = MakeCondition4($1); } | cfield IN '(' const_list ')' /* sico 7 */ { $$ = MakeCondition7($1); } | const IN '(' const_list ')' /* sico 8 */ { $$ = MakeCondition8($1,constType); } | const IN '(' sub_select_query ')' /* sico 9 */ { $$ = MakeCondition9($1,constType); } | field_exists_subquery { $$ = $1; } | field BETWEEN const AND const { $$ = NULL; } | field LIKE const_str { $$ = NULL; } | field IS SNULL { $$ = NULL; } field_exists_subquery : EXISTS '(' sub_select_query ')' { $$ = MakeCondition5(); } | NOT EXISTS '(' sub_select_query ')' { $$ = MakeCondition6(); } field_oper_subquery : cfield EQUAL '(' sub_select_query ')' { $$ = MakeCondition3($1,EQUAL); } | cfield LESSEQ '(' sub_select_query ')' { $$ = MakeCondition3($1,LESSEQ); } | cfield GREATEQ '(' sub_select_query ')' { $$ = MakeCondition3($1,GREATEQ); } | cfield NOTEQ '(' sub_select_query ')' { $$ = MakeCondition3($1,NOTEQ); } | cfield GREAT '(' sub_select_query ')' { $$ = MakeCondition3($1,GREAT); } | cfield LESS '(' sub_select_query ')' { $$ = MakeCondition3($1,LESS); } sub_select_query : select_query { ReturnSubQuery(); } /* Simple condition 1 */ field_oper_const : cfield EQUAL const { $$ = MakeCondition1($1,EQUAL,$3,constType); } | cfield LESSEQ const { $$ = MakeCondition1($1,LESSEQ,$3,constType); } | cfield GREATEQ const { $$ = MakeCondition1($1,GREATEQ,$3,constType); } | cfield NOTEQ const { $$ = MakeCondition1($1,NOTEQ,$3,constType); } | cfield GREAT const { $$ = MakeCondition1($1,GREAT,$3,constType); } | cfield LESS const { $$ = MakeCondition1($1,LESS,$3,constType); } /* Simple Condition 2 */ field_oper_field : cfield EQUAL cfield { $$ = MakeCondition2($1,EQUAL,$3); } | cfield LESSEQ cfield { $$ = MakeCondition2($1,LESSEQ,$3); } | cfield GREATEQ cfield { $$ = MakeCondition2($1,LESSEQ,$3); } | cfield NOTEQ cfield { $$ = MakeCondition2($1,NOTEQ,$3); } | cfield GREAT cfield { $$ = MakeCondition2($1,GREAT,$3); } | cfield LESS cfield { $$ = MakeCondition2($1,LESS,$3); } cfield : IDENTIFIER { strcpy($$,$1); } | FIELD_IDENTIFIER { strcpy($$,$1); } ifield : IDENTIFIER { strcpy($$,$1); } const : const_str { strcpy($$,$1); } | const_date { strcpy($$,$1); } | const_num { strcpy($$,$1); } | const_real { strcpy($$,$1); } const_str : CONST_STR { constType = CONST_STR; strcpy($$,$1); } const_num : CONST_NUM { constType = CONST_NUM; strcpy($$,$1); } const_real : CONST_REAL { constType = CONST_REAL; strcpy($$,$1); } const_date : CONST_DATE { constType = CONST_DATE; strcpy($$,$1); } /* Cannot determine wether all constants are of same type to do so would require different productions for string type, int type */ const_list : const_list COMMA const { AddConst($3,constType); } | const { AddConst($1,constType); } plain_field : actual_field actual_field : IDENTIFIER { AddIdentifierField($1); } | FIELD_IDENTIFIER { AddIdentifierField($1); } field : actual_field /* string */ { } | COUNT { CreateAggregateSelectField(AGGREGATE_COUNT); mode = AGGREGATE_SELECT_FIELD; } '(' agg_field_list ')' { mode = PLAIN_SELECT_FIELD; } | SUM { CreateAggregateSelectField(AGGREGATE_SUM); mode = AGGREGATE_SELECT_FIELD; } '(' agg_field_list ')' { mode = PLAIN_SELECT_FIELD; } | AVG { CreateAggregateSelectField(AGGREGATE_AVG); mode = AGGREGATE_SELECT_FIELD; } '(' agg_field_list ')' { mode = PLAIN_SELECT_FIELD; } | MAX { CreateAggregateSelectField(AGGREGATE_MAX); mode = AGGREGATE_SELECT_FIELD; } '(' agg_field_list ')' { mode = PLAIN_SELECT_FIELD; } | MIN { CreateAggregateSelectField(AGGREGATE_MIN); mode = AGGREGATE_SELECT_FIELD; } '(' agg_field_list ')' { mode = PLAIN_SELECT_FIELD; } | format_field format_field : actual_field comp_oper CONST_NUM | CONST_STR comp_oper : '+' | '*' | '/' | '-' table : IDENTIFIER { AddTable1($1); } | IDENTIFIER IDENTIFIER { AddTable2($1,$2); } insert_stmt : insert_stmt1 insert_stmt1 : INSERT { CreateInsertScript(); } INTO itable insert_field_list value_list { extern FILE *gssfp; /* All over */ fclose(gssfp); } itable : IDENTIFIER { SetInsertTable($1); } insert_field_list : /* Nothing */ | '(' ins_field_list ')' ins_field_list : ins_field_list COMMA ifield { AddInsertField($3); } | ifield { AddInsertField($1); } value_list : VALUES data_list data_list : data_list COMMA data_item | data_item data_item : '(' const_list ')' { char record[255]; extern STableList *tableList; extern FILE *gssfp; /* Insert const_list into table */ AddInsertRecord(record); fprintf(gssfp,"addrec %s\\%s.d \"%s\"\n", dbDir,InsertTableName(), record); } update_stmt : UPDATE delete_stmt : DELETE { extern SelectFieldList *selectFieldList; first = 0; InitRootQuery(); /* $3 will be automatically added */ /* selectFieldList = NULL; */ } FROM delete_where | DELETE { extern SelectFieldList *selectFieldList; first = 0; InitRootQuery(); /* $3 will be automatically added */ /* selectFieldList = NULL; */ } FROM table delete_where : table WHERE condition { rootCondition = $3; } misc_stmt : DBDIR EQUAL CONST_STR { strcpy(dbDir,$3); } | WORKDIR EQUAL CONST_STR { strcpy(workDir,$3); } | OPFILE EQUAL CONST_STR { strcpy(opFile,$3); } | OPFILET EQUAL CONST_STR { strcpy(opFilet,$3); } | PRINT CONST_STR { fprintf(stderr,$2); } | BEAUTIFY ON { beautify = 1; } | BEAUTIFY OFF { beautify = 0; } %% yyerror(char* str) { printf("There is a syntax error in the query : %s",str); exit(2); } void throw_away(void) { while (yytext[0] != ';') yylex(); } void AddIdentifierField(char *id) { char id1[30]; char id2[30]; int i; switch (query_part) { case SELECT_PART : if (strchr(id,'.')) { i = 0; for (i = 0; id[i] != '.'; ++i) id1[i] = id[i]; id1[i] = '\0'; strcpy(id2,id+i+1); } switch (mode) { case PLAIN_SELECT_FIELD : if (strchr(id,'.')) AddPlainSelectField(id2,id1); else AddPlainSelectField(id,""); break; case AGGREGATE_SELECT_FIELD : if (strchr(id,'.')) AddAggregateSelectField(id2,id1); else AddAggregateSelectField(id,""); break; } break; case GROUP_BY_PART : break; } } /******************** End of sql.y ***************/