statement caching for select statement with no parameter and with predicates. Bu
[csql.git] / src / sql / dmlyacc.yxx
blob12312873e35abc379a91e349f3805e71582298c9
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 ALLTABLE DESCRIBE PRIMARYINFO AUTO_INCREMENT GETCATALOGS GETDATATYPES GETTABLETYPES IMPORTEDKEY EXPORTEDKEY
27 %token <stringval> SELECT FROM WHERE BETWEEN IN AND OR NOT AS LIMIT OFFSET INNER OUTER CROSS JOIN LEFT IS
28 %token <stringval> INSERT INTO VALUES EXPLAIN PLAN
29 %token <stringval> DELETE UPDATE SET NULL_VALUE
30 %token <stringval> CREATE TABLE PRIMARY KEY DEFAULT INDEX ON HASH TREE UNIQUE DROP SIZE FOREIGN REFERENCES COMPACT 
31 %token <stringval> CACHE CONDITION FIELDLIST PK DIRECT DSN UNCACHE NOSCHEMA
32 %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
33 %token <stringval> USER PASSWORD ALTER FLUSH
34 %token <stringval> MIN MAX AVG SUM COUNT GROUP BY HAVING ORDER ASC DESC DISTINCT
35 %token ';' ',' '(' ')'
36 %type <stringval> ident field value not_opt doub_value num_value 
37 /*%type <stringval> foreign_key_constraint foreign_key_create foreign_key_constraint_L*/
38 %type <predicate> conditions condition hconditions hcondition 
39 %type <Expression> stmt_exp atom
41 command:  select_statement { YYACCEPT; }
42         | insert_statement { YYACCEPT; }
43         | delete_statement { YYACCEPT; }
44         | update_statement { YYACCEPT; }
45         | ddl_statement { YYACCEPT; }
46         | internal_statement { YYACCEPT; }
47         | cache_statement { YYACCEPT; }
48         | copy_table_statement { YYACCEPT; }
49         | user_manager_statement { YYACCEPT; }
50         | management_statement { YYACCEPT; }
51         | other {YYACCEPT;}
52         ;
53 management_statement: FLUSH CACHE semicolon_opt
54         {
55            parsedData->setStmtType(MgmtStatement);
56         }
57         ;
58 user_manager_statement: CREATE USER ident PASSWORD STRING semicolon_opt
59         {
60             parsedData->setStmtType(UserStatement);
61             parsedData->createUserNode((char*)$3,(char*)$5);
62             free($3);
63             free($5);
64         }
65         |DROP USER ident semicolon_opt
66         {
67             parsedData->setStmtType(UserStatement);
68             parsedData->dropUserNode((char*)$3);
69             free($3);
70         }
71         | ALTER USER ident SET PASSWORD STRING semicolon_opt
72         {
73             parsedData->setStmtType(UserStatement);
74             parsedData->alterUserNode((char*)$3,(char*)$6);
75             free($3);
76             free($6);
77         }
78         ;
79 copy_table_statement: CREATE TABLE ident AS SELECT opt_distinct field_list FROM table_list where_clause_opt group_by_opt having_opt order_by_opt limit_opt semicolon_opt
80         {
81             parsedData->setStmtType(CopyTableStatement);
82             parsedData->setPKTableName($3);
83             parsedData->setCreateTbl();
84             free($3);
85         }
86         | INSERT  INTO ident AS SELECT opt_distinct field_list FROM table_list where_clause_opt group_by_opt having_opt order_by_opt limit_opt semicolon_opt
87         {
88             parsedData->setStmtType(CopyTableStatement);
89             parsedData->setPKTableName($3);
90             free($3);
91         }
92         ;
93 internal_statement: COMPACT TABLE ident
94         {
95             parsedData->setStmtType(CompactTableStatement);
96             parsedData->setTableName($3);
97             free($3);
98         }
99         ;
100 other: ALLTABLE
101         {
102             parsedData->setStmtType(MetaStatement);
103             parsedData->setResultSetPlan(GetTables);
104         }
105         | DESCRIBE table 
106         {
107             parsedData->setStmtType(MetaStatement);
108             parsedData->setResultSetPlan(GetColumns);
109         }
110         | DESCRIBE INDEX table
111         {
112             parsedData->setStmtType(MetaStatement);
113             parsedData->setResultSetPlan(GetIndexes);
114                    
115         }
116         | PRIMARYINFO table
117         {
118             parsedData->setStmtType(MetaStatement);
119             parsedData->setResultSetPlan(GetPriIndex);
120         }
121         | GETCATALOGS
122         {
123             parsedData->setStmtType(MetaStatement);
124             parsedData->setResultSetPlan(GetCatalogs);
125         }
126         | GETTABLETYPES
127         {
128             parsedData->setStmtType(MetaStatement);
129             parsedData->setResultSetPlan(GetTableType);
130         }
131         | GETDATATYPES 
132         {
133             parsedData->setStmtType(MetaStatement);
134             parsedData->setResultSetPlan(GetDataType);
135         }
136         | IMPORTEDKEY table
137         {
138             parsedData->setStmtType(MetaStatement);
139             parsedData->setResultSetPlan(GetImportKey);
140         }
141         | EXPORTEDKEY table
142         {
143             parsedData->setStmtType(MetaStatement);
144             parsedData->setResultSetPlan(GetExportKey);
145         }
146         ;
147 select_statement: opt_explain SELECT opt_distinct field_list FROM table_list where_clause_opt group_by_opt having_opt order_by_opt limit_opt semicolon_opt
148         {
149             parsedData->setStmtType(SelectStatement);
150             parsedData->setCacheWorthy(true);
151         }
152         ;
153 opt_explain: EXPLAIN PLAN
154         {
155            parsedData->setExplain();
156         }
157         |
158         ;
159 opt_distinct: DISTINCT 
160         { 
161             parsedData->setDistinct();
162         }
163         |
164         ;
165 field_list: field_list field_list_L
166         | field_with_as
167         ;
168 field_list_L: ',' field_with_as 
169         ;
170 field_with_as: field
171         | field AS ident
172         {
173             parsedData->insertFieldAlias((char*)$3);
174             free((char*)$3);
175         }
176         ;
177 table_list: table_list table_list_L
178         | table 
179         | table join_exp
180         ;
181 join_exp: INNER opt_join table ON conditions join_exp
182         {
183            parsedData->insertJoinType(INNER_JOIN);
185            Condition *cond = parsedData->getCondition();
186            Predicate *pred = cond->getPredicate();
187            if (pred == NULL) parsedData->setCondition((Predicate*)$5);
188            else {
189                 Predicate *newPred;
190                 newPred = parsedData->insertPredicate(pred, OpAnd, (Predicate*)$5);
191                 parsedData->setCondition(newPred);
192            }
194         }
195         | LEFT opt_outer opt_join table ON conditions join_exp
196         {
197            parsedData->insertJoinType(LEFT_JOIN);
198            Condition *cond = parsedData->getCondition();
199            Predicate *pred = cond->getPredicate();
200            if (pred == NULL) parsedData->setCondition((Predicate*)$6);
201            else {
202                 Predicate *newPred;
203                 newPred = parsedData->insertPredicate(pred, OpAnd, (Predicate*)$6);
204                 parsedData->setCondition(newPred);
205            }
206         }
207         | CROSS opt_join table join_exp
208         {
209             parsedData->insertJoinType(INNER_JOIN);
210         }
211         |
212         ;
213 opt_outer: 
214        |OUTER
215        ;
216 opt_join: 
217        |JOIN
218        ;
219 table_list_L: ',' table
220         {
221             parsedData->insertJoinType(INNER_JOIN);
222         }
223         ;
224         
225 insert_statement: INSERT INTO ident field_list_opt VALUES '(' value_list ')' semicolon_opt
226         {
227             parsedData->setStmtType(InsertStatement);
228             parsedData->setTableName($3); 
229             free($3);
230         }
231         ;
233 field_list_opt:
234         | '(' field_list ')'
235         ;
237 value_list: value_list value_list_L
238         | value
239         {
240             parsedData->insertValue((char*)$1);
241             free($1);
242         }
243         ;
244 value_list_L: ',' value 
245         {
246             parsedData->insertValue((char*)$2);
247             free($2);
248         }
249         ;
250         
251 invalue_list: invalue_list invalue_list_L
252         | value
253         {
254             parsedData->insertInValue((char*)$1);
255             free($1);
256         }
257         ;
258 invalue_list_L: ',' value 
259         {
260             parsedData->insertInValue((char*)$2);
261             free($2);
262         }
263         ;
264         
265 delete_statement: DELETE FROM ident where_clause_opt semicolon_opt
266         {
267             parsedData->setStmtType(DeleteStatement);
268             parsedData->setTableName($3); 
269             free($3);
270         }
271         ;
272         
273 update_statement: UPDATE ident SET assign_list where_clause_opt semicolon_opt
274         {
275             parsedData->setStmtType(UpdateStatement);
276             parsedData->setTableName($2); 
277             free( $2 );
278         }
279         ;
281 semicolon_opt: ';'
282         |
283         ;
285 assign_list: assign_list assign_list_L
286         | assign_stmt
287         ;
289 assign_list_L: ',' assign_stmt
290         ;
291 assign_stmt: ident  OPERATOR stmt_exp
292         {
293            parsedData->insertUpdateExpression( (char*) $1, (Expression* ) $3);
294            free( $1 ); free($2);
295         }
296         | ident OPERATOR value 
297         { 
298             parsedData->insertUpdateValue( (char*) $1, (char*) $3);
299             free( $1 ); free($2);free( $3 ); 
300         }
301         | ident OPERATOR NULL_VALUE 
302         {
303             parsedData->insertUpdateValue( (char*) $1, (char*) $3);
304             free( $1 ); free($2);free( $3 );
305         }
306         ; 
307 stmt_exp: stmt_exp '/' stmt_exp
308         {
309             Expression* exp;
310             exp=parsedData->insertExpression((Expression *)$1, division, (Expression *)$3);
311             $$=exp;
312         } 
313         | stmt_exp '%' stmt_exp
314         {
315             Expression* exp;
316             exp=parsedData->insertExpression((Expression *)$1, modulus, (Expression *)$3);
317             $$=exp;
318         }
319         | stmt_exp '*' stmt_exp
320         {
321             Expression* exp;
322             exp=parsedData->insertExpression((Expression *)$1, multiplication, (Expression *)$3);
323             $$=exp;
324         }
325         | stmt_exp '+' stmt_exp
326         {
327             Expression* exp;
328             exp=parsedData->insertExpression((Expression *)$1, addition, (Expression *)$3);
329             $$=exp;
330         }
331         | stmt_exp '-' stmt_exp
332         {
333             Expression* exp;
334             exp=parsedData->insertExpression((Expression *)$1, subtraction, (Expression *)$3);
335             $$=exp;
336         }
337         | '(' stmt_exp ')'
338         {
339             $$=$2;
340         }
341         | '-' stmt_exp %prec UMINUS
342         {
343             $$ = $2;
344         }
345         | '+' stmt_exp %prec UMINUS
346         {
347             $$ = $2;
348         }
349         | atom
350         ;
351 atom    :  ident
352         {
353             Expression* exp;
354             exp=parsedData->insertExpression((char *)$1);
355             free($1);
356             $$=exp;
357         }
358         | value
359         {
360             Expression* exp;
361             bool flag = false;
362             exp=parsedData->insertExpression((char *)$1, flag);
363             free($1);
364             $$=exp;
365         }
366         | NULL_VALUE
367         {
368             Expression* exp;
369             exp=parsedData->insertExpression("NULL");
370             free($1);
371             $$=exp;
372         }
373         ;
374      
375 where_clause_opt:  WHERE conditions
376         {
377            parsedData->setCondition((Predicate*)$2);
378         }
379         |
380         ;
381 group_by_opt:  GROUP BY group_field_list
382         |
383         ;
384 order_by_opt:  ORDER BY order_field_list
385         |
386         ;
387 limit_opt:  LIMIT NUMBER_STRING
388         {
389             parsedData->setLimit(atoi($2), 0);
390         }
391         | LIMIT NUMBER_STRING OFFSET NUMBER_STRING
392         {
393             parsedData->setLimit(atoi($2), atoi($4));
394         }
395         |
396         ;
397 having_opt:  HAVING hconditions
398         |
399         ;
400 group_field_list: group_field_list group_field_list_L
401         | group_field 
402         ;
403 group_field_list_L: ',' group_field
404         ;
405 group_field:   ident
406         {
407             parsedData->insertGroupField((char*)$1);
408             free( $1 );
409         }
410         ;
411 order_field_list: order_field_list order_field_list_L
412         | order_field
413         ;
414 order_field_list_L: ',' order_field
415         ;
416 order_field:   ident
417         {
418             parsedData->insertOrderByField((char*)$1);
419             free( $1 );
420         }
421         | ident ASC
422         {
423             parsedData->insertOrderByField((char*)$1);
424             free( $1 );
425         }
426         | ident DESC
427         {
428             parsedData->insertOrderByField((char*)$1, true);
429             free( $1 );
430         }
431         ;
432 conditions: conditions OR conditions
433         {
434             Predicate *pred;
435             pred = parsedData->insertPredicate((Predicate*) $1, OpOr, (Predicate*) $3);
436             //parsedData->setCondition((Predicate*)pred);
437             $$= pred;
439         }
440         | conditions AND conditions
441         {
442             Predicate *pred;
443             pred = parsedData->insertPredicate((Predicate*) $1, OpAnd, (Predicate*) $3);
444             //parsedData->setCondition((Predicate*)pred);
445             $$= pred;
446         }
447         | '(' conditions ')' { $$=$2; }
448         | NOT '(' conditions ')'
449         {
450             Predicate *pred;
451             pred = parsedData->insertPredicate((Predicate*) $3, OpNot, NULL);
452             //parsedData->setCondition((Predicate*)pred);
453             $$= pred;
455         }
456         | not_opt condition
457         {
458             if( $1 == (char*) 1 )
459             {
460                 Predicate *pred;
461                 pred = parsedData->insertPredicate((Predicate*) $2, OpNot, NULL);
462                 //parsedData->setCondition((Predicate*)pred);
463                 $$= pred;
464             }
465             else
466             {
467                 //parsedData->setCondition((Predicate*)$2);
468                 $$=$2;
469             }
470         }
471         ;
472 hconditions: hconditions OR hconditions
473         {
474             Predicate *pred;
475             pred = parsedData->insertPredicate((Predicate*) $1, OpOr, (Predicate*) $3);
476             parsedData->setHavingCondition((Predicate*)pred);
477             $$= pred;
479         }
480         | hconditions AND hconditions
481         {
482             Predicate *pred;
483             pred = parsedData->insertPredicate((Predicate*) $1, OpAnd, (Predicate*) $3);
484             parsedData->setHavingCondition((Predicate*)pred);
485             $$= pred;
486         }
487         | '(' hconditions ')' { $$=$2; }
488         | NOT '(' hconditions ')'
489         {
490             Predicate *pred;
491             pred = parsedData->insertPredicate((Predicate*) $3, OpNot, NULL);
492             parsedData->setHavingCondition((Predicate*)pred);
493             $$= pred;
495         }
496         | not_opt hcondition
497         {
498             if( $1 == (char*) 1 )
499             {
500                 Predicate *pred;
501                 pred = parsedData->insertPredicate((Predicate*) $2, OpNot, NULL);
502                 parsedData->setHavingCondition((Predicate*)pred);
503                 $$= pred;
504             }
505             else
506             {
507                 parsedData->setHavingCondition((Predicate*)$2);
508                 $$=$2;
509             }
510         }
511         ;
512 hcondition: MIN  '(' ident ')' OPERATOR value
513         {
514             ComparisionOp  op = AllDataType::getComparisionOperator((char*)$5);
515             Predicate *pred;
516             void **ptr = parsedData->insertCondValueAndGetPtr((char*)$3, (char*)$6, false, AGG_MIN, true);
517             pred = parsedData->insertPredicate((char*) $3, op, ptr, AGG_MIN);
518             free( $1 ); free ($3); free ($5); free ($6);
519             $$=pred;
520         }
521         | MAX  '(' ident ')' OPERATOR value
522         {
523             ComparisionOp  op = AllDataType::getComparisionOperator((char*)$5);
524             Predicate *pred;
525             void **ptr = parsedData->insertCondValueAndGetPtr((char*)$3, (char*)$6, false, AGG_MAX, true);
526             pred = parsedData->insertPredicate((char*) $3, op, ptr, AGG_MAX);
527             free( $1 ); free ($3); free ($5); free ($6);
528             $$=pred;
529         }
530         | SUM  '(' ident ')' OPERATOR value
531         {
532             ComparisionOp  op = AllDataType::getComparisionOperator((char*)$5);
533             Predicate *pred;
534             void **ptr = parsedData->insertCondValueAndGetPtr((char*)$3, (char*)$6, false, AGG_SUM, true);
535             pred = parsedData->insertPredicate((char*) $3, op, ptr, AGG_SUM);
536             free( $1 ); free ($3); free ($5); free ($6);
537             $$=pred;
538         }
539         | AVG  '(' ident ')' OPERATOR value
540         {
541             ComparisionOp  op = AllDataType::getComparisionOperator((char*)$5);
542             Predicate *pred;
543             void **ptr = parsedData->insertCondValueAndGetPtr((char*)$3, (char*)$6, false, AGG_AVG, true);
544             pred = parsedData->insertPredicate((char*) $3, op, ptr, AGG_AVG);
545             free( $1 ); free ($3); free ($5); free ($6);
546             $$=pred;
547         }
548         | COUNT  '(' ident ')' OPERATOR value
549         {
550             ComparisionOp  op = AllDataType::getComparisionOperator((char*)$5);
551             Predicate *pred;
552             void **ptr = parsedData->insertCondValueAndGetPtr((char*)$3, (char*)$6, false, AGG_COUNT, true);
553             pred = parsedData->insertPredicate((char*) $3, op, ptr, AGG_COUNT);
554             free( $1 ); free ($3); free ($5); free ($6);
555             $$=pred;
556         }
557         ;
559 condition: ident OPERATOR value 
560         {
561             ComparisionOp  op = AllDataType::getComparisionOperator((char*)$2);
562                         bool opLike = false;
563             if (op == OpLike) {
564                 char *c = (char *)$3;
565                 //if (*c == '%' && *(c+1) == '\0')  
566                 Util::changeWildcardChar(c);
567                 opLike = true;
568             }
569             Predicate *pred;
570             void **ptr = parsedData->insertCondValueAndGetPtr((char*)$1, (char*)$3, opLike);
571             pred = parsedData->insertPredicate((char*) $1, op, ptr);
572             free( $1 ); free($2); free( $3 ); 
573             $$=pred;
574         }
575         | ident OPERATOR ident
576         {
577             ComparisionOp  op = AllDataType::getComparisionOperator((char*)$2);
578             Predicate *pred;
579             parsedData->insertCondValue((char*) $1);
580             parsedData->insertCondValue((char*) $3);
581             pred = parsedData->insertPredicate((char*) $1, op, (char*) $3);
582             free( $1 ); free($2); free( $3 );
583             $$=pred;
584         }
586         | ident not_opt BETWEEN value AND value
587         {
588             void **ptr1 = parsedData->insertCondValueAndGetPtr((char*)$1, (char*)$4);
589             void **ptr2 = parsedData->insertCondValueAndGetPtr((char*)$1, (char*)$6);
590             Predicate *finalPred;
591  //           pred1 = parsedData->insertPredicate((char*) $1, OpGreaterThanEquals, ptr1);
592 //            pred2 = parsedData->insertPredicate((char*) $1, OpLessThanEquals, ptr2);
593             finalPred = parsedData->insertBetPredicate((char*) $1, 
594                         OpGreaterThanEquals, ptr1, OpLessThanEquals, ptr2);
595                         //OpLessThanEquals, ptr2, OpGreaterThanEquals, ptr1);
597             if( $2 == (char*) 1 )
598                 finalPred = parsedData->insertPredicate(finalPred, OpNot, NULL);
599             free( $1 );  free( $4 );  free( $6 );
600             $$= finalPred;
601         }
602         | ident not_opt IN '(' invalue_list ')'
603         {
604             ListIterator valIter = parsedData->getInValueList().getIterator();
605             FieldValue *value1, *value2;
606             Predicate *pred1, *pred2, *finalPred;
607             void **ptr1, **ptr2;
608             if (valIter.hasElement()) {
609                value1 = (FieldValue*) valIter.nextElement();
610                ptr1 = parsedData->insertCondValueAndGetPtr((char*)$1, value1->parsedString);
611                pred1 = parsedData->insertPredicate((char*) $1, OpEquals, ptr1);
612                finalPred=pred1;
613             }
614             while (valIter.hasElement()) {
615                value2 = (FieldValue*) valIter.nextElement();
616                ptr2 = parsedData->insertCondValueAndGetPtr((char*)$1, value2->parsedString);
617                pred2 = parsedData->insertPredicate((char*) $1, OpEquals, ptr2);
618                finalPred = parsedData->insertPredicate(pred1, OpOr, pred2);
619                pred1= finalPred;     
620             }
621             if( $2 == (char*)1)
622                 finalPred = parsedData->insertPredicate(finalPred, OpNot, NULL);
624             free( $1 );  
625             $$= finalPred;
626         }
627         | ident IS NOT NULL_VALUE
628         {
629             Predicate *pred;
630             parsedData->insertCondValue((char*) $1);
631             pred = parsedData->insertNullPredicate((char*) $1, OpIsNull, false);
632             free( $1 ); free($2); free( $3 );
633             $$=pred;  
634         }
635         | ident IS NULL_VALUE
636         {
637             Predicate *pred;
638             parsedData->insertCondValue((char*) $1);
639             pred = parsedData->insertNullPredicate((char*) $1, OpIsNull, true);
640             free( $1 ); free($2); free( $3 );
641             $$=pred;  
642         }
643         ;
644 not_opt: NOT
645         { $$=(char*) 1;
646         }
647         | 
648         { $$=(char*) 0; }
649         ;
650 table:   ident
651         {
652             parsedData->insertTableName((char*)$1);
653             free( $1 );
654         }
655         | ident AS ident
656         {
657             parsedData->insertTableName((char*)$1, (char*)$3);
658             free( $1 ); free($3);
659         }
660         | ident ident
661         {
662             parsedData->insertTableName((char*)$1, (char*)$2);
663             free( $1 ); free($2);
664         }
665         ;
666 field:   ident
667         {
668             parsedData->insertField((char*)$1);
669             free( $1 );
670             
671         }
672         | MIN  '(' ident ')'
673         { 
674             parsedData->insertField((char*)$3, AGG_MIN);
675             free( $1 );
676         }
677         | MAX  '(' ident ')'
678         { 
679             parsedData->insertField((char*)$3, AGG_MAX);
680             free( $1 );
681         }
682         | SUM  '(' ident ')'
683         { 
684             parsedData->insertField((char*)$3, AGG_SUM);
685             free( $1 );
686         }
687         | AVG  '(' ident ')'
688         { 
689             parsedData->insertField((char*)$3, AGG_AVG);
690             free( $1 );
691         }
692         | COUNT  '(' ident ')'
693         { 
694             parsedData->insertField((char*)$3, AGG_COUNT);
695             free( $1 );
696         }
697         | COUNT  '(' '*' ')'
698         { 
699             parsedData->insertField("*", AGG_COUNT);
700             free( $1 );
701         }
702         | '*'
703         { 
704             parsedData->insertField("*");
705         }
706         |ident'*'
707         {
708             parsedData->insertField("*");
709         }
710         ;
711 ident:    FIELD { $$ = $1; }
712         | '`'FIELD'`' { $$ = $2; }
713         ;
714 value:    STRING { $$ = $1; }
715         | num_value
716         | BINARY_STRING { $$ = $1; }
717         | doub_value
718         | PARAMETER { $$ = $1; }
719         | NULL_VALUE { $$ = (char*) 0; }
720         ;
721 num_value: NUMBER_STRING { $$ =  $1; }
722         | '-' NUMBER_STRING %prec UMINUS
723         {
724              char *n;
725              n=(char*)malloc(30);
726              strcpy(n,"-");
727              strcat(n,(char*)$2);
728              $$=n;
729              free($2);
730         }
731         | '+' NUMBER_STRING %prec UMINUS{ $$ =  $2; }
732         ;
733 doub_value : DOUBLE { $$ = $1; }
734         | '-' DOUBLE %prec UMINUS
735         {
736              char *d;
737              d=(char*)malloc(30);
738              strcpy(d,"-");
739              strcat(d,(char*)$2);
740              $$=d;
741              free($2);
742         }
743         | '+' DOUBLE %prec UMINUS{ $$ = $2; }
744         ;
745 cache_statement: CACHE TABLE ident cache_opt semicolon_opt
746         {
747             if (!Conf::config.useCache())
748             {
749               printf("CACHE_TABLE is set to FALSE in csql.conf file.\n");
750               free($3);
751               YYABORT;
752             }
753             parsedData->setStmtType(CacheTableStatement);
754             parsedData->setTableName($3); 
755         }
756         | UNCACHE TABLE ident semicolon_opt
757         {
758             parsedData->setStmtType(CacheTableStatement);
759             parsedData->setUnCache(true);
760             parsedData->setTableName($3); 
761         }
762         ; 
763 cache_opt: hcond_cache vcond_cache pk_cache direct_opt dsn_opt no_schema
764          ;
765 hcond_cache: 
766          | CONDITION value 
767          {
768             parsedData->setHCondFld(true);
769             parsedData->setHCondition((char*)$2);
770          }
771          ;
772 vcond_cache:
773          | FIELDLIST value
774          {
775             parsedData->setVCondFld(true);
776             parsedData->setVCondition((char*)$2);
777             free($2);
778          }
779          ;
780 pk_cache:
781          | PK ident
782          {
783             parsedData->setPkFld(true);
784             parsedData->setIndexName((char*)$2);
785             free($2);
786          }
787          ;
788 direct_opt:
789          | DIRECT
790          {
791             parsedData->setDirect(true);
792          }
793          ;
794 dsn_opt:
795          | DSN value
796          {
797              parsedData->setDSN(true);
798              parsedData->setPKTableName((char*)$2);
799              free($2);
800          }
801 no_schema:
802          | NOSCHEMA
803          {
804              parsedData->setNoSchema(true);
805          }
806          ;
807 ddl_statement: CREATE TABLE ident '(' create_defn_list_con ')' semicolon_opt
808         {
809             parsedData->setStmtType(CreateTableStatement);
810             parsedData->setTableName($3); 
811             free($3);
812         }
813         | CREATE INDEX ident ON ident '(' field_list ')' opt_constr_type opt_ind_type opt_bucket semicolon_opt
814         {
815             parsedData->setStmtType(CreateIndexStatement);
816             parsedData->setIndexName($3); 
817             parsedData->setTableName($5); 
818             free($3);
819             free($5);
820         }
821         | DROP TABLE ident
822         {
823             parsedData->setStmtType(DropTableStatement);
824             parsedData->setTableName($3); 
825             free($3);
826         }
827         | DROP INDEX ident
828         {
829             parsedData->setStmtType(DropIndexStatement);
830             parsedData->setIndexName($3); 
831             free($3);
832         }
833         ;
834 opt_ind_type:
835         | HASH  opt_constr_type
836         {
837             parsedData->setIndexType(hashIndex);
838         }
839         | TREE  opt_constr_type
840         {
841             parsedData->setIndexType(treeIndex);
842         }
843         |
844         {
845             parsedData->setIndexType(hashIndex);
846         }
847         ;
848 opt_constr_type:
849         | UNIQUE 
850         {
851             parsedData->setUnique(true);
852         }
853         | PRIMARY 
854         {
855             parsedData->setUnique(true);
856             parsedData->setPrimary(true);
857         }
858         |
859         {
860             parsedData->setUnique(false);
861             parsedData->setPrimary(false);
862         }
863         ;
864 opt_bucket:
865         | SIZE NUMBER_STRING
866         {
867             parsedData->setBucketSize(atoi($2));
868             free($2);
869         }
870         ;
871 create_defn_list_con:create_defn_list
872         |create_defn_list ',' constraint_defn
873         ;
874 create_defn_list: create_defn_list create_defn_list_L
875         | create_defn
876         ;
878 create_defn_list_L: ',' create_defn
879         ;
881 create_defn: field_defn
882         {
883             parsedData->insertFldDef();
884         }
885         ;
887 field_defn: field_name field_type size_opt null_expr_opt default_expr_opt auto_increment_key 
888         ;
890 field_name: ident
891         {
892             parsedData->setFldName($1);
893             free($1);
894         }
895 size_opt:
896         | '(' NUMBER_STRING ')'
897         {
898             DbRetVal rv = parsedData->setFldLength(atoi($2));
899             if (rv != OK) {
900                 yyerror("Binary field length < 256");
901                 free($2);
902                 YYABORT;
903             }
904             free($2);
905         }
906         ;
908 default_expr_opt:
909         | DEFAULT value
910         {
911             parsedData->setDefaultValue($2);
912             free($2);
913         }
914         ;
916 null_expr_opt:
917         | NOT NULL_VALUE
918         {
919             parsedData->setFldNotNull(true);
920         }
921         ;
922 constraint_defn : primary_key_constraint
923         | foreign_key_constraint
924         | primary_key_constraint ',' foreign_key_constraint
925         ;
926 foreign_key_constraint: foreign_key_constraint foreign_key_constraint_L
927         | foreign_key_create
928         ;
929 foreign_key_constraint_L: ',' foreign_key_create
930         ;
931 foreign_key_create: FOREIGN KEY '(' fkField_list ')' REFERENCES ident'(' pkField_list ')'
932         {
933             parsedData->setForeign(true);
934             parsedData->setPKTableName((char*)$7);
935             parsedData->insertForeignKeyList();
936         }
937         ;
938 fkField_list: fkField_list fkField_list_L
939         | fkField
940         ;
941 fkField_list_L: ',' fkField
942         ;
943 fkField: ident
944         {
945            parsedData->insertFKField((char*)$1);
946            free($1);
947         }
948         ;
949 pkField_list: pkField_list pkField_list_L
950         | pkField
951         ;
952 pkField_list_L: ',' pkField
953         ;
954 pkField: ident
955         {
956            parsedData->insertPKField((char*)$1);
957            free($1);
958         }
959         ;
961 primary_key_constraint: PRIMARY KEY '(' field_list ')' opt_bucket
962         {
963            parsedData->setPrimary(true);
964         }
965         ;
966 auto_increment_key:
967         | AUTO_INCREMENT
968         {
969            DataType type = parsedData->getFldType();
970            if(type > 4)
971            {
972                yyerror("AUTO_INCREMENT KEY can't be created other than INTEGER field ");
973                free($1);
974                YYABORT;
975            }
976            DbRetVal ret = parsedData->setAutoIncreament(true);
977            if(ret != OK){
978                yyerror("A table should have ony one AUTO_INCREMENT KEY ");
979                free($1);
980                YYABORT;
981            }
982            parsedData->setFldNotNull(true);
983            parsedData->setAutoFldName(parsedData->getFldName());
984            parsedData->setPrimary(true);
985         }
986         ;
988 field_type: INT_TYPE
989         {
990             parsedData->setFldType(typeInt);
991         }
992         | LONG_TYPE
993         {
994             parsedData->setFldType(typeLong);
995         }
996         | SHORT_TYPE
997         {
998             parsedData->setFldType(typeShort);
999         }
1000         | BIGINT_TYPE
1001         {
1002             parsedData->setFldType(typeLongLong);
1003         }
1004         | TINYINT_TYPE
1005         {
1006             parsedData->setFldType(typeByteInt);
1007         }
1008         | FLOAT_TYPE
1009         {
1010             parsedData->setFldType(typeFloat);
1011         }
1012         | DOUBLE_TYPE
1013         {
1014             parsedData->setFldType(typeDouble);
1015         }
1016         ;
1017         | DATE_TYPE
1018         {
1019             parsedData->setFldType(typeDate);
1020         }
1021         ;
1022         | TIME_TYPE
1023         {
1024             parsedData->setFldType(typeTime);
1025         }
1026         ;
1027         | TIMESTAMP_TYPE
1028         {
1029             parsedData->setFldType(typeTimeStamp);
1030         }
1031         ;
1032         | CHAR_TYPE
1033         {
1034             parsedData->setFldType(typeString);
1035             parsedData->setFldLength(2);
1036         }
1037         ;
1038         | BINARY_TYPE
1039         {
1040             parsedData->setFldType(typeBinary);
1041             parsedData->setFldLength(1);
1042         }
1043         ;
1046 extern int lexEof;
1047 void yyerror(const char* Msg) { 
1048     if( lexEof == 0 )
1049         fprintf(stderr, "[Parser: %s] %s\n", Msg, yytext);
1051     return;