Fix for Bug #2423618
[csql.git] / src / sql / dmlyacc.yxx
blob1cdad79d36262be87116fbed9696087fdcf99f19
1 %{
2 #include <CSql.h>
3 #include <stdlib.h>
4 #include "Parser.h"
6 class Predicate;
7 ParsedData *parsedData;
8 extern char yytext[];
9 int yylex( void );
10 void yyerror(const char* Msg);
14 %union
16    char *stringval;
17    void *predicate;
18    void *Expression;
21 %left OR 
22 %left AND
23 %left '+' '-'
24 %left '*' '/' '%'
25 %nonassoc UMINUS
26 %token <stringval> STRING FIELD NUMBER_STRING BINARY_STRING DOUBLE OPERATOR PARAMETER
27 %token <stringval> SELECT FROM WHERE BETWEEN IN AND OR NOT
28 %token <stringval> INSERT INTO VALUES
29 %token <stringval> DELETE UPDATE SET NULL_VALUE
30 %token <stringval> CREATE TABLE PRIMARY KEY DEFAULT INDEX ON HASH TREE UNIQUE DROP
31 %token <stringval> INT_TYPE LONG_TYPE SHORT_TYPE DOUBLE_TYPE TIMESTAMP_TYPE DATE_TYPE CHAR_TYPE TIME_TYPE BIGINT_TYPE FLOAT_TYPE TINYINT_TYPE BINARY_TYPE
32 %token <stringval> MIN MAX AVG SUM COUNT GROUP BY
33 %token ';' ',' '(' ')'
34 %type <stringval> ident field value not_opt doub_value num_value
35 %type <predicate> conditions condition 
36 %type <Expression> stmt_exp atom
38 command:  select_statement { YYACCEPT; }
39         | insert_statement { YYACCEPT; }
40         | delete_statement { YYACCEPT; }
41         | update_statement { YYACCEPT; }
42         | ddl_statement { YYACCEPT; }
43         ;
44         
45 select_statement: SELECT field_list FROM table_list where_clause_opt group_by_opt semicolon_opt
46         {
47             parsedData->setStmtType(SelectStatement);
48             //parsedData->setTableName($4); 
49             //free($4);
50         }
51         ;
53 field_list: field_list field_list_L
54         | field 
55         ;
56 field_list_L: ',' field
57         ;
58 table_list: table_list table_list_L
59         | table 
60         ;
61 table_list_L: ',' table
62         ;
63         
64 insert_statement: INSERT INTO ident field_list_opt VALUES '(' value_list ')' semicolon_opt
65         {
66             parsedData->setStmtType(InsertStatement);
67             parsedData->setTableName($3); 
68             free($3);
69         }
70         ;
72 field_list_opt:
73         | '(' field_list ')'
74         ;
76 value_list: value_list value_list_L
77         | value
78         {
79             parsedData->insertValue((char*)$1);
80             free($1);
81         }
82         ;
83 value_list_L: ',' value 
84         {
85             parsedData->insertValue((char*)$2);
86             free($2);
87         }
88         ;
89         
90 invalue_list: invalue_list invalue_list_L
91         | value
92         {
93             parsedData->insertInValue((char*)$1);
94             free($1);
95         }
96         ;
97 invalue_list_L: ',' value 
98         {
99             parsedData->insertInValue((char*)$2);
100             free($2);
101         }
102         ;
103         
104 delete_statement: DELETE FROM ident where_clause_opt semicolon_opt
105         {
106             parsedData->setStmtType(DeleteStatement);
107             parsedData->setTableName($3); 
108             free($3);
109         }
110         ;
111         
112 update_statement: UPDATE ident SET assign_list where_clause_opt semicolon_opt
113         {
114             parsedData->setStmtType(UpdateStatement);
115             parsedData->setTableName($2); 
116             free( $2 );
117         }
118         ;
120 semicolon_opt: ';'
121         |
122         ;
124 assign_list: assign_list assign_list_L
125         | assign_stmt
126         ;
128 assign_list_L: ',' assign_stmt
129         ;
130 assign_stmt: ident  OPERATOR stmt_exp
131         {
132            parsedData->insertUpdateExpression( (char*) $1, (Expression* ) $3);
133            free( $1 ); free($2);
134         }
135         | ident OPERATOR value 
136         { 
137             parsedData->insertUpdateValue( (char*) $1, (char*) $3);
138             free( $1 ); free($2);free( $3 ); 
139         }
140         | ident OPERATOR NULL_VALUE 
141         {
142             parsedData->insertUpdateValue( (char*) $1, (char*) $3);
143             free( $1 ); free($2);free( $3 );
144         }
145         ; 
146 stmt_exp: stmt_exp '/' stmt_exp
147         {
148             Expression* exp;
149             exp=parsedData->insertExpression((Expression *)$1, division, (Expression *)$3);
150             $$=exp;
151         } 
152         | stmt_exp '%' stmt_exp
153         {
154             Expression* exp;
155             exp=parsedData->insertExpression((Expression *)$1, modulus, (Expression *)$3);
156             $$=exp;
157         }
158         | stmt_exp '*' stmt_exp
159         {
160             Expression* exp;
161             exp=parsedData->insertExpression((Expression *)$1, multiplication, (Expression *)$3);
162             $$=exp;
163         }
164         | stmt_exp '+' stmt_exp
165         {
166             Expression* exp;
167             exp=parsedData->insertExpression((Expression *)$1, addition, (Expression *)$3);
168             $$=exp;
169         }
170         | stmt_exp '-' stmt_exp
171         {
172             Expression* exp;
173             exp=parsedData->insertExpression((Expression *)$1, subtraction, (Expression *)$3);
174             $$=exp;
175         }
176         | '(' stmt_exp ')'
177         {
178             $$=$2;
179         }
180         | '-' stmt_exp %prec UMINUS
181         {
182             $$ = $2;
183         }
184         | '+' stmt_exp %prec UMINUS
185         {
186             $$ = $2;
187         }
188         | atom
189         ;
190 atom    :  ident
191         {
192             Expression* exp;
193             exp=parsedData->insertExpression((char *)$1);
194             free($1);
195             $$=exp;
196         }
197         | value
198         {
199             Expression* exp;
200             bool flag = false;
201             exp=parsedData->insertExpression((char *)$1, flag);
202             free($1);
203             $$=exp;
204         }
205         ;
206      
207 where_clause_opt:  WHERE conditions
208         |
209         ;
210 group_by_opt:  GROUP BY group_field_list
211         |
212         ;
213 group_field_list: group_field_list group_field_list_L
214         | group_field 
215         ;
216 group_field_list_L: ',' group_field
217         ;
218 group_field:   ident
219         {
220             parsedData->insertGroupField((char*)$1);
221             free( $1 );
222         }
223         ;
224 conditions: conditions OR conditions
225         {
226             Predicate *pred;
227             pred = parsedData->insertPredicate((Predicate*) $1, OpOr, (Predicate*) $3);
228             parsedData->setCondition((Predicate*)pred);
229             $$= pred;
231         }
232         | conditions AND conditions
233         {
234             Predicate *pred;
235             pred = parsedData->insertPredicate((Predicate*) $1, OpAnd, (Predicate*) $3);
236             parsedData->setCondition((Predicate*)pred);
237             $$= pred;
238         }
239         | '(' conditions ')' { $$=$2; }
240         | NOT '(' conditions ')'
241         {
242             Predicate *pred;
243             pred = parsedData->insertPredicate((Predicate*) $3, OpNot, NULL);
244             parsedData->setCondition((Predicate*)pred);
245             $$= pred;
247         }
248         | not_opt condition
249         {
250             if( $1 == (char*) 1 )
251             {
252                 Predicate *pred;
253                 pred = parsedData->insertPredicate((Predicate*) $2, OpNot, NULL);
254                 parsedData->setCondition((Predicate*)pred);
255                 $$= pred;
256             }
257             else
258             {
259                 parsedData->setCondition((Predicate*)$2);
260                 $$=$2;
261             }
262         }
263         ;
264 condition: ident OPERATOR value 
265         {
266             ComparisionOp  op = AllDataType::getComparisionOperator((char*)$2);
267                         bool opLike = false;
268             if (op == OpLike) {
269                 char *c = (char *)$3;
270                 while (*c != '\0') {
271                     if (*c == '_') *c = '?';
272                     else if(*c == '%') *c = '*';
273                     c++;
274                             }
275                                 opLike = true;
276             }
277             Predicate *pred;
278             void **ptr = parsedData->insertCondValueAndGetPtr((char*)$1, (char*)$3, opLike);
279             pred = parsedData->insertPredicate((char*) $1, op, ptr);
280             free( $1 ); free($2); free( $3 ); 
281             $$=pred;
282         }
283         | ident OPERATOR ident
284         {
285             ComparisionOp  op = AllDataType::getComparisionOperator((char*)$2);
286             Predicate *pred;
287             pred = parsedData->insertPredicate((char*) $1, op, (char*) $3);
288             free( $1 ); free($2); free( $3 );
289             $$=pred;
290         }
292         | ident not_opt BETWEEN value AND value
293         {
294             void **ptr1 = parsedData->insertCondValueAndGetPtr((char*)$1, (char*)$4);
295             void **ptr2 = parsedData->insertCondValueAndGetPtr((char*)$1, (char*)$6);
296             Predicate *pred1, *pred2, *pred3, *finalPred;
297             pred1 = parsedData->insertPredicate((char*) $1, OpGreaterThanEquals, ptr1);
298             pred2 = parsedData->insertPredicate((char*) $1, OpLessThanEquals, ptr2);
299             finalPred = parsedData->insertPredicate(pred1, OpAnd, pred2);
300             if( $2 == (char*) 1 )
301                 finalPred = parsedData->insertPredicate(finalPred, OpNot, NULL);
302             free( $1 );  free( $4 );  free( $6 );
303             $$= finalPred;
304         }
305         | ident not_opt IN '(' invalue_list ')'
306         {
307             ListIterator valIter = parsedData->getInValueList().getIterator();
308             FieldValue *value1, *value2;
309             Predicate *pred1, *pred2, *finalPred;
310             void **ptr1, **ptr2;
311             if (valIter.hasElement()) {
312                value1 = (FieldValue*) valIter.nextElement();
313                ptr1 = parsedData->insertCondValueAndGetPtr((char*)$1, value1->parsedString);
314                pred1 = parsedData->insertPredicate((char*) $1, OpEquals, ptr1);
315                finalPred=pred1;
316             }
317             while (valIter.hasElement()) {
318                value2 = (FieldValue*) valIter.nextElement();
319                ptr2 = parsedData->insertCondValueAndGetPtr((char*)$1, value2->parsedString);
320                pred2 = parsedData->insertPredicate((char*) $1, OpEquals, ptr2);
321                finalPred = parsedData->insertPredicate(pred1, OpOr, pred2);
322                pred1= finalPred;     
323             }
324             if( $2 == (char*)1)
325                 finalPred = parsedData->insertPredicate(finalPred, OpNot, NULL);
327             free( $1 );  
328             $$= finalPred;
329         }
330         ;
331 not_opt: NOT
332         { $$=(char*) 1;
333         }
334         | 
335         { $$=(char*) 0; }
336         ;
337 table:   ident
338         {
339             parsedData->insertTableName((char*)$1);
340             free( $1 );
341         }
342         ;
343 field:   ident
344         {
345             parsedData->insertField((char*)$1);
346             free( $1 );
347             
348         }
349         | MIN  '(' ident ')'
350         { 
351             parsedData->insertField((char*)$3, AGG_MIN);
352             free( $1 );
353         }
354         | MAX  '(' ident ')'
355         { 
356             parsedData->insertField((char*)$3, AGG_MAX);
357             free( $1 );
358         }
359         | SUM  '(' ident ')'
360         { 
361             parsedData->insertField((char*)$3, AGG_SUM);
362             free( $1 );
363         }
364         | AVG  '(' ident ')'
365         { 
366             parsedData->insertField((char*)$3, AGG_AVG);
367             free( $1 );
368         }
369         | COUNT  '(' ident ')'
370         { 
371             parsedData->insertField((char*)$3, AGG_COUNT);
372             free( $1 );
373         }
374         | COUNT  '(' '*' ')'
375         { 
376             parsedData->insertField("*", AGG_COUNT);
377             free( $1 );
378         }
379         | '*'
380         { 
381             parsedData->insertField("*");
382         }
383         ;
384 ident:    FIELD { $$ = $1; }
385         ;
386 value:    STRING { $$ = $1; }
387         | num_value
388         | BINARY_STRING { $$ = $1; }
389         | doub_value
390         | PARAMETER { $$ = $1; }
391         | NULL_VALUE { $$ = (char*) 0; }
392         ;
393 num_value: NUMBER_STRING { $$ =  $1; }
394         | '-' NUMBER_STRING %prec UMINUS
395         {
396              char *n;
397              n=(char*)malloc(30);
398              strcpy(n,"-");
399              strcat(n,(char*)$2);
400              $$=n;
401              free($2);
402         }
403         | '+' NUMBER_STRING %prec UMINUS{ $$ =  $2; }
404         ;
405 doub_value : DOUBLE { $$ = $1; }
406         | '-' DOUBLE %prec UMINUS
407         {
408              char *d;
409              d=(char*)malloc(30);
410              strcpy(d,"-");
411              strcat(d,(char*)$2);
412              $$=d;
413              free($2);
414         }
415         | '+' DOUBLE %prec UMINUS{ $$ = $2; }
416         ;
418 ddl_statement: CREATE TABLE ident '(' create_defn_list_con ')' semicolon_opt
419         {
420             parsedData->setStmtType(CreateTableStatement);
421             parsedData->setTableName($3); 
422             free($3);
423         }
424         | CREATE INDEX ident ON ident '(' field_list ')' opt_constr_type opt_ind_type  semicolon_opt
425         {
426             parsedData->setStmtType(CreateIndexStatement);
427             parsedData->setIndexName($3); 
428             parsedData->setTableName($5); 
429             free($3);
430             free($5);
431         }
432         | DROP TABLE ident
433         {
434             parsedData->setStmtType(DropTableStatement);
435             parsedData->setTableName($3); 
436             free($3);
437         }
438         | DROP INDEX ident
439         {
440             parsedData->setStmtType(DropIndexStatement);
441             parsedData->setIndexName($3); 
442             free($3);
443         }
444         ;
445 opt_ind_type:
446         | HASH  opt_constr_type
447         {
448             parsedData->setIndexType(hashIndex);
449         }
450         | TREE  opt_constr_type
451         {
452             parsedData->setIndexType(treeIndex);
453         }
454         |
455         {
456             parsedData->setIndexType(hashIndex);
457         }
458         ;
459 opt_constr_type:
460         | UNIQUE 
461         {
462             parsedData->setUnique(true);
463         }
464         | PRIMARY 
465         {
466             parsedData->setUnique(true);
467             parsedData->setPrimary(true);
468         }
469         |
470         {
471             parsedData->setUnique(false);
472             parsedData->setPrimary(false);
473         }
474         ;
475 create_defn_list_con:create_defn_list
476         |create_defn_list ',' constraint_defn
477         ;
478 create_defn_list: create_defn_list create_defn_list_L
479         | create_defn
480         ;
482 create_defn_list_L: ',' create_defn
483         ;
485 create_defn: field_defn
486         {
487             parsedData->insertFldDef();
488         }
489         ;
491 field_defn: field_name field_type size_opt null_expr_opt default_expr_opt
492         ;
494 field_name: ident
495         {
496             parsedData->setFldName($1);
497             free($1);
498         }
499 size_opt:
500         | '(' NUMBER_STRING ')'
501         {
502             DbRetVal rv = parsedData->setFldLength(atoi($2)+1);
503             if (rv != OK) {
504                 yyerror("Binary field length < 256");
505                 free($2);
506                 YYABORT;
507             }
508             free($2);
509         }
510         ;
512 default_expr_opt:
513         | DEFAULT value
514         {
515             parsedData->setDefaultValue($2);
516             free($2);
517         }
518         ;
520 null_expr_opt:
521         | NOT NULL_VALUE
522         {
523             parsedData->setFldNotNull(true);
524         }
525         ;
526 constraint_defn: primary_key_constraint
527         ;
529 primary_key_constraint: PRIMARY KEY '(' field_list ')'
530         {
531            parsedData->setPrimary(true);
532         }
533         ;
535 field_type: INT_TYPE
536         {
537             parsedData->setFldType(typeInt);
538         }
539         | LONG_TYPE
540         {
541             parsedData->setFldType(typeLong);
542         }
543         | SHORT_TYPE
544         {
545             parsedData->setFldType(typeShort);
546         }
547         | BIGINT_TYPE
548         {
549             parsedData->setFldType(typeLongLong);
550         }
551         | TINYINT_TYPE
552         {
553             parsedData->setFldType(typeByteInt);
554         }
555         | FLOAT_TYPE
556         {
557             parsedData->setFldType(typeFloat);
558         }
559         | DOUBLE_TYPE
560         {
561             parsedData->setFldType(typeDouble);
562         }
563         ;
564         | DATE_TYPE
565         {
566             parsedData->setFldType(typeDate);
567         }
568         ;
569         | TIME_TYPE
570         {
571             parsedData->setFldType(typeTime);
572         }
573         ;
574         | TIMESTAMP_TYPE
575         {
576             parsedData->setFldType(typeTimeStamp);
577         }
578         ;
579         | CHAR_TYPE
580         {
581             parsedData->setFldType(typeString);
582             parsedData->setFldLength(2);
583         }
584         ;
585         | BINARY_TYPE
586         {
587             parsedData->setFldType(typeBinary);
588             parsedData->setFldLength(1);
589         }
590         ;
593 extern int lexEof;
594 void yyerror(const char* Msg) { 
595     if( lexEof == 0 )
596         fprintf(stderr, "[Parser: %s] %s\n", Msg, yytext);
598     return;