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