server: Convert the server start time to the abs_time_t type.
[wine] / dlls / msi / sql.y
1 %{
2
3 /*
4  * Implementation of the Microsoft Installer (msi.dll)
5  *
6  * Copyright 2002-2004 Mike McCormack for CodeWeavers
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21  */
22
23
24 #include "config.h"
25
26 #include <stdarg.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29
30 #include "windef.h"
31 #include "winbase.h"
32 #include "query.h"
33 #include "wine/list.h"
34 #include "wine/debug.h"
35
36 #define YYLEX_PARAM info
37 #define YYPARSE_PARAM info
38
39 extern int SQL_error(const char *str);
40
41 WINE_DEFAULT_DEBUG_CHANNEL(msi);
42
43 typedef struct tag_SQL_input
44 {
45     MSIDATABASE *db;
46     LPCWSTR command;
47     DWORD n, len;
48     MSIVIEW **view;  /* view structure for the resulting query */
49     struct list *mem;
50 } SQL_input;
51
52 static LPWSTR SQL_getstring( void *info, struct sql_str *str );
53 static INT SQL_getint( void *info );
54 static int SQL_lex( void *SQL_lval, SQL_input *info );
55
56 static void *parser_alloc( void *info, unsigned int sz );
57 static column_info *parser_alloc_column( void *info, LPCWSTR table, LPCWSTR column );
58
59 static BOOL SQL_MarkPrimaryKeys( column_info *cols, column_info *keys);
60
61 static struct expr * EXPR_complex( void *info, struct expr *l, UINT op, struct expr *r );
62 static struct expr * EXPR_column( void *info, column_info *column );
63 static struct expr * EXPR_ival( void *info, int val );
64 static struct expr * EXPR_sval( void *info, struct sql_str * );
65 static struct expr * EXPR_wildcard( void *info );
66
67 %}
68
69 %pure-parser
70
71 %union
72 {
73     struct sql_str str;
74     LPWSTR string;
75     column_info *column_list;
76     MSIVIEW *query;
77     struct expr *expr;
78     USHORT column_type;
79     int integer;
80 }
81
82 %token TK_ABORT TK_AFTER TK_AGG_FUNCTION TK_ALL TK_AND TK_AS TK_ASC
83 %token TK_BEFORE TK_BEGIN TK_BETWEEN TK_BITAND TK_BITNOT TK_BITOR TK_BY
84 %token TK_CASCADE TK_CASE TK_CHAR TK_CHECK TK_CLUSTER TK_COLLATE TK_COLUMN
85 %token TK_COMMA TK_COMMENT TK_COMMIT TK_CONCAT TK_CONFLICT 
86 %token TK_CONSTRAINT TK_COPY TK_CREATE
87 %token TK_DEFAULT TK_DEFERRABLE TK_DEFERRED TK_DELETE TK_DELIMITERS TK_DESC
88 %token TK_DISTINCT TK_DOT TK_DROP TK_EACH
89 %token TK_ELSE TK_END TK_END_OF_FILE TK_EQ TK_EXCEPT TK_EXPLAIN
90 %token TK_FAIL TK_FLOAT TK_FOR TK_FOREIGN TK_FROM TK_FUNCTION
91 %token TK_GE TK_GLOB TK_GROUP TK_GT
92 %token TK_HAVING TK_HOLD
93 %token TK_IGNORE TK_ILLEGAL TK_IMMEDIATE TK_IN TK_INDEX TK_INITIALLY
94 %token <str> TK_ID 
95 %token TK_INSERT TK_INSTEAD TK_INT 
96 %token <str> TK_INTEGER
97 %token TK_INTERSECT TK_INTO TK_IS
98 %token TK_ISNULL
99 %token TK_JOIN TK_JOIN_KW
100 %token TK_KEY
101 %token TK_LE TK_LIKE TK_LIMIT TK_LONG TK_LONGCHAR TK_LP TK_LSHIFT TK_LT
102 %token TK_LOCALIZABLE
103 %token TK_MATCH TK_MINUS
104 %token TK_NE TK_NOT TK_NOTNULL TK_NULL
105 %token TK_OBJECT TK_OF TK_OFFSET TK_ON TK_OR TK_ORACLE_OUTER_JOIN TK_ORDER
106 %token TK_PLUS TK_PRAGMA TK_PRIMARY
107 %token TK_RAISE TK_REFERENCES TK_REM TK_REPLACE TK_RESTRICT TK_ROLLBACK
108 %token TK_ROW TK_RP TK_RSHIFT
109 %token TK_SELECT TK_SEMI TK_SET TK_SHORT TK_SLASH TK_SPACE TK_STAR TK_STATEMENT 
110 %token <str> TK_STRING
111 %token TK_TABLE TK_TEMP TK_THEN TK_TRANSACTION TK_TRIGGER
112 %token TK_UMINUS TK_UNCLOSED_STRING TK_UNION TK_UNIQUE
113 %token TK_UPDATE TK_UPLUS TK_USING
114 %token TK_VACUUM TK_VALUES TK_VIEW
115 %token TK_WHEN TK_WHERE TK_WILDCARD
116
117 /*
118  * These are extra tokens used by the lexer but never seen by the
119  * parser.  We put them in a rule so that the parser generator will
120  * add them to the parse.h output file.
121  *
122  */
123 %nonassoc END_OF_FILE ILLEGAL SPACE UNCLOSED_STRING COMMENT FUNCTION
124           COLUMN AGG_FUNCTION.
125
126 %type <string> table id
127 %type <column_list> selcollist column column_and_type column_def table_def
128 %type <column_list> column_assignment update_assign_list constlist
129 %type <query> query multifrom from fromtable selectfrom unorderedsel
130 %type <query> oneupdate onedelete oneselect onequery onecreate oneinsert
131 %type <expr> expr val column_val const_val
132 %type <column_type> column_type data_type data_type_l data_count
133 %type <integer> number
134
135 /* Reference: http://mates.ms.mff.cuni.cz/oracle/doc/ora815nt/server.815/a67779/operator.htm */
136 %left TK_OR
137 %left TK_AND
138 %left TK_NOT
139 %left TK_EQ TK_NE TK_LT TK_GT TK_LE TK_GE TK_ISNULL TK_LIKE TK_BETWEEN TK_IN
140 %left TK_PLUS TK_MINUS TK_CONCAT
141 %right TK_NEGATION
142
143 %%
144
145 query:
146     onequery
147     {
148         SQL_input* sql = (SQL_input*) info;
149         *sql->view = $1;
150     }
151     ;
152
153 onequery:
154     oneselect
155   | onecreate
156   | oneinsert
157   | oneupdate
158   | onedelete
159     ;
160
161 oneinsert:
162     TK_INSERT TK_INTO table TK_LP selcollist TK_RP TK_VALUES TK_LP constlist TK_RP
163         {
164             SQL_input *sql = (SQL_input*) info;
165             MSIVIEW *insert = NULL; 
166             UINT r;
167
168             r = INSERT_CreateView( sql->db, &insert, $3, $5, $9, FALSE ); 
169             if( !insert )
170                 YYABORT;
171             $$ = insert;
172         }
173   | TK_INSERT TK_INTO table TK_LP selcollist TK_RP TK_VALUES TK_LP constlist TK_RP TK_TEMP
174         {
175             SQL_input *sql = (SQL_input*) info;
176             MSIVIEW *insert = NULL; 
177
178             INSERT_CreateView( sql->db, &insert, $3, $5, $9, TRUE ); 
179             if( !insert )
180                 YYABORT;
181             $$ = insert;
182         }
183     ;
184
185 onecreate:
186     TK_CREATE TK_TABLE table TK_LP table_def TK_RP
187         {
188             SQL_input* sql = (SQL_input*) info;
189             MSIVIEW *create = NULL; 
190
191             if( !$5 )
192                 YYABORT;
193             CREATE_CreateView( sql->db, &create, $3, $5, FALSE );
194             if( !create )
195                 YYABORT;
196             $$ = create;
197         }
198   | TK_CREATE TK_TABLE table TK_LP table_def TK_RP TK_HOLD
199         {
200             SQL_input* sql = (SQL_input*) info;
201             MSIVIEW *create = NULL; 
202
203             if( !$5 )
204                 YYABORT;
205             CREATE_CreateView( sql->db, &create, $3, $5, TRUE );
206             if( !create )
207                 YYABORT;
208             $$ = create;
209         }
210     ;
211
212 oneupdate:
213     TK_UPDATE table TK_SET update_assign_list TK_WHERE expr
214         {
215             SQL_input* sql = (SQL_input*) info;
216             MSIVIEW *update = NULL; 
217
218             UPDATE_CreateView( sql->db, &update, $2, $4, $6 );
219             if( !update )
220                 YYABORT;
221             $$ = update;
222         }
223     ;
224
225 onedelete:
226     TK_DELETE from
227         {
228             SQL_input* sql = (SQL_input*) info;
229             MSIVIEW *delete = NULL; 
230
231             DELETE_CreateView( sql->db, &delete, $2 );
232             if( !delete )
233                 YYABORT;
234             $$ = delete;
235         }
236     ;
237
238 table_def:
239     column_def TK_PRIMARY TK_KEY selcollist
240         {
241             if( SQL_MarkPrimaryKeys( $1, $4 ) )
242                 $$ = $1;
243             else
244                 $$ = NULL;
245         }
246     ;
247
248 column_def:
249     column_def TK_COMMA column_and_type
250         {
251             column_info *ci;
252
253             for( ci = $1; ci->next; ci = ci->next )
254                 ;
255
256             ci->next = $3;
257             $$ = $1;
258         }
259   | column_and_type
260         {
261             $$ = $1;
262         }
263     ;
264
265 column_and_type:
266     column column_type
267         {
268             $$ = $1;
269             $$->type = $2 | MSITYPE_VALID;
270         }
271     ;
272
273 column_type:
274     data_type_l
275         {
276             $$ = $1;
277         }
278   | data_type_l TK_LOCALIZABLE
279         {
280             $$ = $1 | MSITYPE_LOCALIZABLE;
281         }
282     ;
283
284 data_type_l:
285     data_type
286         {
287             $$ |= MSITYPE_NULLABLE;
288         }
289   | data_type TK_NOT TK_NULL
290         {
291             $$ = $1;
292         }
293     ;
294
295 data_type:
296     TK_CHAR
297         {
298             $$ = MSITYPE_STRING | 1;
299         }
300   | TK_CHAR TK_LP data_count TK_RP
301         {
302             $$ = MSITYPE_STRING | 0x400 | $3;
303         }
304   | TK_LONGCHAR
305         {
306             $$ = 2;
307         }
308   | TK_SHORT
309         {
310             $$ = 2;
311         }
312   | TK_INT
313         {
314             $$ = 2;
315         }
316   | TK_LONG
317         {
318             $$ = 4;
319         }
320   | TK_OBJECT
321         {
322             $$ = MSITYPE_STRING | MSITYPE_VALID;
323         }
324     ;
325
326 data_count:
327     number
328         {
329             if( ( $1 > 255 ) || ( $1 < 0 ) )
330                 YYABORT;
331             $$ = $1;
332         }
333     ;
334
335 oneselect:
336     unorderedsel TK_ORDER TK_BY selcollist
337         {
338             SQL_input* sql = (SQL_input*) info;
339
340             $$ = NULL;
341             if( $4 )
342                 ORDER_CreateView( sql->db, &$$, $1, $4 );
343             else
344                 $$ = $1;
345             if( !$$ )
346                 YYABORT;
347         }
348   | unorderedsel
349     ;
350
351 unorderedsel:
352     TK_SELECT selectfrom
353         {
354             $$ = $2;
355         }
356   | TK_SELECT TK_DISTINCT selectfrom
357         {
358             SQL_input* sql = (SQL_input*) info;
359             UINT r;
360
361             $$ = NULL;
362             r = DISTINCT_CreateView( sql->db, &$$, $3 );
363             if (r != ERROR_SUCCESS)
364             {
365                 $3->ops->delete($3);
366                 YYABORT;
367             }
368         }
369     ;
370
371 selectfrom:
372     selcollist multifrom 
373         {
374             SQL_input* sql = (SQL_input*) info;
375             UINT r;
376
377             $$ = NULL;
378             if( $1 )
379             {
380                 r = SELECT_CreateView( sql->db, &$$, $2, $1 );
381                 if (r != ERROR_SUCCESS)
382                 {
383                     $2->ops->delete($2);
384                     YYABORT;
385                 }
386             }
387             else
388                 $$ = $2;
389         }
390     ;
391
392 selcollist:
393     column 
394   | column TK_COMMA selcollist
395         { 
396             $1->next = $3;
397         }
398   | TK_STAR
399         {
400             $$ = NULL;
401         }
402     ;
403
404 multifrom:
405     from
406   | TK_FROM table TK_COMMA table TK_WHERE expr
407         {
408             SQL_input* sql = (SQL_input*) info;
409             FIXME("join query %s\n", debugstr_w(sql->command));
410             YYABORT;
411         }
412     ;
413
414 from:
415     fromtable
416   | fromtable TK_WHERE expr
417         { 
418             SQL_input* sql = (SQL_input*) info;
419             UINT r;
420
421             $$ = NULL;
422             r = WHERE_CreateView( sql->db, &$$, $1, $3 );
423             if( r != ERROR_SUCCESS )
424             {
425                 $1->ops->delete( $1 );
426                 YYABORT;
427             }
428         }
429     ;
430
431 fromtable:
432     TK_FROM table
433         {
434             SQL_input* sql = (SQL_input*) info;
435             UINT r;
436
437             $$ = NULL;
438             r = TABLE_CreateView( sql->db, $2, &$$ );
439             if( r != ERROR_SUCCESS || !$$ )
440                 YYABORT;
441         }
442     ;
443
444 expr:
445     TK_LP expr TK_RP
446         {
447             $$ = $2;
448             if( !$$ )
449                 YYABORT;
450         }
451   | expr TK_AND expr
452         {
453             $$ = EXPR_complex( info, $1, OP_AND, $3 );
454             if( !$$ )
455                 YYABORT;
456         }
457   | expr TK_OR expr
458         {
459             $$ = EXPR_complex( info, $1, OP_OR, $3 );
460             if( !$$ )
461                 YYABORT;
462         }
463   | column_val TK_EQ val
464         {
465             $$ = EXPR_complex( info, $1, OP_EQ, $3 );
466             if( !$$ )
467                 YYABORT;
468         }
469   | column_val TK_GT val
470         {
471             $$ = EXPR_complex( info, $1, OP_GT, $3 );
472             if( !$$ )
473                 YYABORT;
474         }
475   | column_val TK_LT val
476         {
477             $$ = EXPR_complex( info, $1, OP_LT, $3 );
478             if( !$$ )
479                 YYABORT;
480         }
481   | column_val TK_LE val
482         {
483             $$ = EXPR_complex( info, $1, OP_LE, $3 );
484             if( !$$ )
485                 YYABORT;
486         }
487   | column_val TK_GE val
488         {
489             $$ = EXPR_complex( info, $1, OP_GE, $3 );
490             if( !$$ )
491                 YYABORT;
492         }
493   | column_val TK_NE val
494         {
495             $$ = EXPR_complex( info, $1, OP_NE, $3 );
496             if( !$$ )
497                 YYABORT;
498         }
499   | column_val TK_IS TK_NULL
500         {
501             $$ = EXPR_complex( info, $1, OP_ISNULL, NULL );
502             if( !$$ )
503                 YYABORT;
504         }
505   | column_val TK_IS TK_NOT TK_NULL
506         {
507             $$ = EXPR_complex( info, $1, OP_NOTNULL, NULL );
508             if( !$$ )
509                 YYABORT;
510         }
511     ;
512
513 val:
514     column_val
515   | const_val
516     ;
517
518 constlist:
519     const_val
520         {
521             $$ = parser_alloc_column( info, NULL, NULL );
522             if( !$$ )
523                 YYABORT;
524             $$->val = $1;
525         }
526   | const_val TK_COMMA constlist
527         {
528             $$ = parser_alloc_column( info, NULL, NULL );
529             if( !$$ )
530                 YYABORT;
531             $$->val = $1;
532             $$->next = $3;
533         }
534     ;
535
536 update_assign_list:
537     column_assignment
538   | column_assignment TK_COMMA update_assign_list
539         {
540             $$ = $1;
541             $$->next = $3;
542         }
543     ;
544
545 column_assignment:
546     column TK_EQ const_val
547         {
548             $$ = $1;
549             $$->val = $3;
550         }
551     ;
552
553 const_val:
554     number
555         {
556             $$ = EXPR_ival( info, $1 );
557             if( !$$ )
558                 YYABORT;
559         }
560   | TK_MINUS number %prec TK_NEGATION
561         {
562             $$ = EXPR_ival( info, -$2 );
563             if( !$$ )
564                 YYABORT;
565         }
566   | TK_STRING
567         {
568             $$ = EXPR_sval( info, &$1 );
569             if( !$$ )
570                 YYABORT;
571         }
572   | TK_WILDCARD
573         {
574             $$ = EXPR_wildcard( info );
575             if( !$$ )
576                 YYABORT;
577         }
578     ;
579
580 column_val:
581     column 
582         {
583             $$ = EXPR_column( info, $1 );
584             if( !$$ )
585                 YYABORT;
586         }
587     ;
588
589 column:
590     table TK_DOT id
591         {
592             $$ = parser_alloc_column( info, $1, $3 );
593             if( !$$ )
594                 YYABORT;
595         }
596   | id
597         {
598             $$ = parser_alloc_column( info, NULL, $1 );
599             if( !$$ )
600                 YYABORT;
601         }
602     ;
603
604 table:
605     id
606         {
607             $$ = $1;
608         }
609     ;
610
611 id:
612     TK_ID
613         {
614             $$ = SQL_getstring( info, &$1 );
615             if( !$$ )
616                 YYABORT;
617         }
618     ;
619
620 number:
621     TK_INTEGER
622         {
623             $$ = SQL_getint( info );
624         }
625     ;
626
627 %%
628
629 static void *parser_alloc( void *info, unsigned int sz )
630 {
631     SQL_input* sql = (SQL_input*) info;
632     struct list *mem;
633
634     mem = msi_alloc( sizeof (struct list) + sz );
635     list_add_tail( sql->mem, mem );
636     return &mem[1];
637 }
638
639 static column_info *parser_alloc_column( void *info, LPCWSTR table, LPCWSTR column )
640 {
641     column_info *col;
642
643     col = parser_alloc( info, sizeof (*col) );
644     if( col )
645     {
646         col->table = table;
647         col->column = column;
648         col->val = NULL;
649         col->type = 0;
650         col->next = NULL;
651     }
652
653     return col;
654 }
655
656 int SQL_lex( void *SQL_lval, SQL_input *sql )
657 {
658     int token;
659     struct sql_str * str = SQL_lval;
660
661     do
662     {
663         sql->n += sql->len;
664         if( ! sql->command[sql->n] )
665             return 0;  /* end of input */
666
667         /* TRACE("string : %s\n", debugstr_w(&sql->command[sql->n])); */
668         sql->len = sqliteGetToken( &sql->command[sql->n], &token );
669         if( sql->len==0 )
670             break;
671         str->data = &sql->command[sql->n];
672         str->len = sql->len;
673     }
674     while( token == TK_SPACE );
675
676     /* TRACE("token : %d (%s)\n", token, debugstr_wn(&sql->command[sql->n], sql->len)); */
677     
678     return token;
679 }
680
681 LPWSTR SQL_getstring( void *info, struct sql_str *strdata )
682 {
683     LPCWSTR p = strdata->data;
684     UINT len = strdata->len;
685     LPWSTR str;
686
687     /* if there's quotes, remove them */
688     if( ( (p[0]=='`') && (p[len-1]=='`') ) || 
689         ( (p[0]=='\'') && (p[len-1]=='\'') ) )
690     {
691         p++;
692         len -= 2;
693     }
694     str = parser_alloc( info, (len + 1)*sizeof(WCHAR) );
695     if( !str )
696         return str;
697     memcpy( str, p, len*sizeof(WCHAR) );
698     str[len]=0;
699
700     return str;
701 }
702
703 INT SQL_getint( void *info )
704 {
705     SQL_input* sql = (SQL_input*) info;
706     LPCWSTR p = &sql->command[sql->n];
707     INT i, r = 0;
708
709     for( i=0; i<sql->len; i++ )
710     {
711         if( '0' > p[i] || '9' < p[i] )
712         {
713             ERR("should only be numbers here!\n");
714             break;
715         }
716         r = (p[i]-'0') + r*10;
717     }
718
719     return r;
720 }
721
722 int SQL_error( const char *str )
723 {
724     return 0;
725 }
726
727 static struct expr * EXPR_wildcard( void *info )
728 {
729     struct expr *e = parser_alloc( info, sizeof *e );
730     if( e )
731     {
732         e->type = EXPR_WILDCARD;
733     }
734     return e;
735 }
736
737 static struct expr * EXPR_complex( void *info, struct expr *l, UINT op, struct expr *r )
738 {
739     struct expr *e = parser_alloc( info, sizeof *e );
740     if( e )
741     {
742         e->type = EXPR_COMPLEX;
743         e->u.expr.left = l;
744         e->u.expr.op = op;
745         e->u.expr.right = r;
746     }
747     return e;
748 }
749
750 static struct expr * EXPR_column( void *info, column_info *column )
751 {
752     struct expr *e = parser_alloc( info, sizeof *e );
753     if( e )
754     {
755         e->type = EXPR_COLUMN;
756         e->u.sval = column->column;
757     }
758     return e;
759 }
760
761 static struct expr * EXPR_ival( void *info, int val )
762 {
763     struct expr *e = parser_alloc( info, sizeof *e );
764     if( e )
765     {
766         e->type = EXPR_IVAL;
767         e->u.ival = val;
768     }
769     return e;
770 }
771
772 static struct expr * EXPR_sval( void *info, struct sql_str *str )
773 {
774     struct expr *e = parser_alloc( info, sizeof *e );
775     if( e )
776     {
777         e->type = EXPR_SVAL;
778         e->u.sval = SQL_getstring( info, str );
779     }
780     return e;
781 }
782
783 static BOOL SQL_MarkPrimaryKeys( column_info *cols,
784                                  column_info *keys )
785 {
786     column_info *k;
787     BOOL found = TRUE;
788
789     for( k = keys; k && found; k = k->next )
790     {
791         column_info *c;
792
793         found = FALSE;
794         for( c = cols; c && !found; c = c->next )
795         {
796              if( lstrcmpW( k->column, c->column ) )
797                  continue;
798              c->type |= MSITYPE_KEY;
799              found = TRUE;
800         }
801     }
802
803     return found;
804 }
805
806 UINT MSI_ParseSQL( MSIDATABASE *db, LPCWSTR command, MSIVIEW **phview,
807                    struct list *mem )
808 {
809     SQL_input sql;
810     int r;
811
812     *phview = NULL;
813
814     sql.db = db;
815     sql.command = command;
816     sql.n = 0;
817     sql.len = 0;
818     sql.view = phview;
819     sql.mem = mem;
820
821     r = SQL_parse(&sql);
822
823     TRACE("Parse returned %d\n", r);
824     if( r )
825     {
826         *sql.view = NULL;
827         return ERROR_BAD_QUERY_SYNTAX;
828     }
829
830     return ERROR_SUCCESS;
831 }