Initialize a bunch of dc values to their default before enumerating an
[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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  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 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 %%
136
137 query:
138     onequery
139     {
140         SQL_input* sql = (SQL_input*) info;
141         *sql->view = $1;
142     }
143     ;
144
145 onequery:
146     oneselect
147   | onecreate
148   | oneinsert
149   | oneupdate
150   | onedelete
151     ;
152
153 oneinsert:
154     TK_INSERT TK_INTO table TK_LP selcollist TK_RP TK_VALUES TK_LP constlist TK_RP
155         {
156             SQL_input *sql = (SQL_input*) info;
157             MSIVIEW *insert = NULL; 
158             UINT r;
159
160             r = INSERT_CreateView( sql->db, &insert, $3, $5, $9, FALSE ); 
161             if( !insert )
162                 YYABORT;
163             $$ = insert;
164         }
165   | TK_INSERT TK_INTO table TK_LP selcollist TK_RP TK_VALUES TK_LP constlist TK_RP TK_TEMP
166         {
167             SQL_input *sql = (SQL_input*) info;
168             MSIVIEW *insert = NULL; 
169
170             INSERT_CreateView( sql->db, &insert, $3, $5, $9, TRUE ); 
171             if( !insert )
172                 YYABORT;
173             $$ = insert;
174         }
175     ;
176
177 onecreate:
178     TK_CREATE TK_TABLE table TK_LP table_def TK_RP
179         {
180             SQL_input* sql = (SQL_input*) info;
181             MSIVIEW *create = NULL; 
182
183             if( !$5 )
184                 YYABORT;
185             CREATE_CreateView( sql->db, &create, $3, $5, FALSE );
186             if( !create )
187                 YYABORT;
188             $$ = create;
189         }
190   | TK_CREATE TK_TABLE table TK_LP table_def TK_RP TK_HOLD
191         {
192             SQL_input* sql = (SQL_input*) info;
193             MSIVIEW *create = NULL; 
194
195             if( !$5 )
196                 YYABORT;
197             CREATE_CreateView( sql->db, &create, $3, $5, TRUE );
198             if( !create )
199                 YYABORT;
200             $$ = create;
201         }
202     ;
203
204 oneupdate:
205     TK_UPDATE table TK_SET update_assign_list TK_WHERE expr
206         {
207             SQL_input* sql = (SQL_input*) info;
208             MSIVIEW *update = NULL; 
209
210             UPDATE_CreateView( sql->db, &update, $2, $4, $6 );
211             if( !update )
212                 YYABORT;
213             $$ = update;
214         }
215     ;
216
217 onedelete:
218     TK_DELETE from
219         {
220             SQL_input* sql = (SQL_input*) info;
221             MSIVIEW *delete = NULL; 
222
223             DELETE_CreateView( sql->db, &delete, $2 );
224             if( !delete )
225                 YYABORT;
226             $$ = delete;
227         }
228     ;
229
230 table_def:
231     column_def TK_PRIMARY TK_KEY selcollist
232         {
233             if( SQL_MarkPrimaryKeys( $1, $4 ) )
234                 $$ = $1;
235             else
236                 $$ = NULL;
237         }
238     ;
239
240 column_def:
241     column_def TK_COMMA column_and_type
242         {
243             column_info *ci;
244
245             for( ci = $1; ci->next; ci = ci->next )
246                 ;
247
248             ci->next = $3;
249             $$ = $1;
250         }
251   | column_and_type
252         {
253             $$ = $1;
254         }
255     ;
256
257 column_and_type:
258     column column_type
259         {
260             $$ = $1;
261             $$->type = $2 | MSITYPE_VALID;
262         }
263     ;
264
265 column_type:
266     data_type_l
267         {
268             $$ = $1;
269         }
270   | data_type_l TK_LOCALIZABLE
271         {
272             $$ = $1 | MSITYPE_LOCALIZABLE;
273         }
274     ;
275
276 data_type_l:
277     data_type
278         {
279             $$ |= MSITYPE_NULLABLE;
280         }
281   | data_type TK_NOT TK_NULL
282         {
283             $$ = $1;
284         }
285     ;
286
287 data_type:
288     TK_CHAR
289         {
290             $$ = MSITYPE_STRING | 1;
291         }
292   | TK_CHAR TK_LP data_count TK_RP
293         {
294             $$ = MSITYPE_STRING | 0x400 | $3;
295         }
296   | TK_LONGCHAR
297         {
298             $$ = 2;
299         }
300   | TK_SHORT
301         {
302             $$ = 2;
303         }
304   | TK_INT
305         {
306             $$ = 2;
307         }
308   | TK_LONG
309         {
310             $$ = 4;
311         }
312   | TK_OBJECT
313         {
314             $$ = MSITYPE_STRING | MSITYPE_VALID;
315         }
316     ;
317
318 data_count:
319     number
320         {
321             if( ( $1 > 255 ) || ( $1 < 0 ) )
322                 YYABORT;
323             $$ = $1;
324         }
325     ;
326
327 oneselect:
328     unorderedsel TK_ORDER TK_BY selcollist
329         {
330             SQL_input* sql = (SQL_input*) info;
331
332             $$ = NULL;
333             if( $4 )
334                 ORDER_CreateView( sql->db, &$$, $1, $4 );
335             else
336                 $$ = $1;
337             if( !$$ )
338                 YYABORT;
339         }
340   | unorderedsel
341     ;
342
343 unorderedsel:
344     TK_SELECT selectfrom
345         {
346             $$ = $2;
347         }
348   | TK_SELECT TK_DISTINCT selectfrom
349         {
350             SQL_input* sql = (SQL_input*) info;
351             UINT r;
352
353             $$ = NULL;
354             r = DISTINCT_CreateView( sql->db, &$$, $3 );
355             if (r != ERROR_SUCCESS)
356             {
357                 $3->ops->delete($3);
358                 YYABORT;
359             }
360         }
361     ;
362
363 selectfrom:
364     selcollist from 
365         {
366             SQL_input* sql = (SQL_input*) info;
367             UINT r;
368
369             $$ = NULL;
370             if( $1 )
371             {
372                 r = SELECT_CreateView( sql->db, &$$, $2, $1 );
373                 if (r != ERROR_SUCCESS)
374                 {
375                     $2->ops->delete($2);
376                     YYABORT;
377                 }
378             }
379             else
380                 $$ = $2;
381         }
382     ;
383
384 selcollist:
385     column 
386   | column TK_COMMA selcollist
387         { 
388             $1->next = $3;
389         }
390   | TK_STAR
391         {
392             $$ = NULL;
393         }
394     ;
395
396 from:
397     fromtable
398   | fromtable TK_WHERE expr
399         { 
400             SQL_input* sql = (SQL_input*) info;
401             UINT r;
402
403             $$ = NULL;
404             r = WHERE_CreateView( sql->db, &$$, $1, $3 );
405             if( r != ERROR_SUCCESS )
406             {
407                 $1->ops->delete( $1 );
408                 YYABORT;
409             }
410         }
411     ;
412
413 fromtable:
414     TK_FROM table
415         {
416             SQL_input* sql = (SQL_input*) info;
417             UINT r;
418
419             $$ = NULL;
420             r = TABLE_CreateView( sql->db, $2, &$$ );
421             if( r != ERROR_SUCCESS || !$$ )
422                 YYABORT;
423         }
424     ;
425
426 expr:
427     TK_LP expr TK_RP
428         {
429             $$ = $2;
430             if( !$$ )
431                 YYABORT;
432         }
433   | column_val TK_EQ column_val
434         {
435             $$ = EXPR_complex( info, $1, OP_EQ, $3 );
436             if( !$$ )
437                 YYABORT;
438         }
439   | expr TK_AND expr
440         {
441             $$ = EXPR_complex( info, $1, OP_AND, $3 );
442             if( !$$ )
443                 YYABORT;
444         }
445   | expr TK_OR expr
446         {
447             $$ = EXPR_complex( info, $1, OP_OR, $3 );
448             if( !$$ )
449                 YYABORT;
450         }
451   | column_val TK_EQ val
452         {
453             $$ = EXPR_complex( info, $1, OP_EQ, $3 );
454             if( !$$ )
455                 YYABORT;
456         }
457   | column_val TK_GT val
458         {
459             $$ = EXPR_complex( info, $1, OP_GT, $3 );
460             if( !$$ )
461                 YYABORT;
462         }
463   | column_val TK_LT val
464         {
465             $$ = EXPR_complex( info, $1, OP_LT, $3 );
466             if( !$$ )
467                 YYABORT;
468         }
469   | column_val TK_LE val
470         {
471             $$ = EXPR_complex( info, $1, OP_LE, $3 );
472             if( !$$ )
473                 YYABORT;
474         }
475   | column_val TK_GE val
476         {
477             $$ = EXPR_complex( info, $1, OP_GE, $3 );
478             if( !$$ )
479                 YYABORT;
480         }
481   | column_val TK_NE val
482         {
483             $$ = EXPR_complex( info, $1, OP_NE, $3 );
484             if( !$$ )
485                 YYABORT;
486         }
487   | column_val TK_IS TK_NULL
488         {
489             $$ = EXPR_complex( info, $1, OP_ISNULL, NULL );
490             if( !$$ )
491                 YYABORT;
492         }
493   | column_val TK_IS TK_NOT TK_NULL
494         {
495             $$ = EXPR_complex( info, $1, OP_NOTNULL, NULL );
496             if( !$$ )
497                 YYABORT;
498         }
499     ;
500
501 val:
502     column_val
503   | const_val
504     ;
505
506 constlist:
507     const_val
508         {
509             $$ = parser_alloc_column( info, NULL, NULL );
510             if( !$$ )
511                 YYABORT;
512             $$->val = $1;
513         }
514   | const_val TK_COMMA constlist
515         {
516             $$ = parser_alloc_column( info, NULL, NULL );
517             if( !$$ )
518                 YYABORT;
519             $$->val = $1;
520             $$->next = $3;
521         }
522     ;
523
524 update_assign_list:
525     column_assignment
526   | column_assignment TK_COMMA update_assign_list
527         {
528             $$ = $1;
529             $$->next = $3;
530         }
531     ;
532
533 column_assignment:
534     column TK_EQ const_val
535         {
536             $$ = $1;
537             $$->val = $3;
538         }
539     ;
540
541 const_val:
542     number
543         {
544             $$ = EXPR_ival( info, $1 );
545             if( !$$ )
546                 YYABORT;
547         }
548   | TK_MINUS number
549         {
550             $$ = EXPR_ival( info, -$2 );
551             if( !$$ )
552                 YYABORT;
553         }
554   | TK_STRING
555         {
556             $$ = EXPR_sval( info, &$1 );
557             if( !$$ )
558                 YYABORT;
559         }
560   | TK_WILDCARD
561         {
562             $$ = EXPR_wildcard( info );
563             if( !$$ )
564                 YYABORT;
565         }
566     ;
567
568 column_val:
569     column 
570         {
571             $$ = EXPR_column( info, $1 );
572             if( !$$ )
573                 YYABORT;
574         }
575     ;
576
577 column:
578     table TK_DOT id
579         {
580             $$ = parser_alloc_column( info, $1, $3 );
581             if( !$$ )
582                 YYABORT;
583         }
584   | id
585         {
586             $$ = parser_alloc_column( info, NULL, $1 );
587             if( !$$ )
588                 YYABORT;
589         }
590     ;
591
592 table:
593     id
594         {
595             $$ = $1;
596         }
597     ;
598
599 id:
600     TK_ID
601         {
602             $$ = SQL_getstring( info, &$1 );
603             if( !$$ )
604                 YYABORT;
605         }
606     ;
607
608 number:
609     TK_INTEGER
610         {
611             $$ = SQL_getint( info );
612         }
613     ;
614
615 %%
616
617 static void *parser_alloc( void *info, unsigned int sz )
618 {
619     SQL_input* sql = (SQL_input*) info;
620     struct list *mem;
621
622     mem = msi_alloc( sizeof (struct list) + sz );
623     list_add_tail( sql->mem, mem );
624     return &mem[1];
625 }
626
627 static column_info *parser_alloc_column( void *info, LPCWSTR table, LPCWSTR column )
628 {
629     column_info *col;
630
631     col = parser_alloc( info, sizeof (*col) );
632     if( col )
633     {
634         col->table = table;
635         col->column = column;
636         col->val = NULL;
637         col->type = 0;
638         col->next = NULL;
639     }
640
641     return col;
642 }
643
644 int SQL_lex( void *SQL_lval, SQL_input *sql )
645 {
646     int token;
647     struct sql_str * str = SQL_lval;
648
649     do
650     {
651         sql->n += sql->len;
652         if( ! sql->command[sql->n] )
653             return 0;  /* end of input */
654
655         /* TRACE("string : %s\n", debugstr_w(&sql->command[sql->n])); */
656         sql->len = sqliteGetToken( &sql->command[sql->n], &token );
657         if( sql->len==0 )
658             break;
659         str->data = &sql->command[sql->n];
660         str->len = sql->len;
661     }
662     while( token == TK_SPACE );
663
664     /* TRACE("token : %d (%s)\n", token, debugstr_wn(&sql->command[sql->n], sql->len)); */
665     
666     return token;
667 }
668
669 LPWSTR SQL_getstring( void *info, struct sql_str *strdata )
670 {
671     LPCWSTR p = strdata->data;
672     UINT len = strdata->len;
673     LPWSTR str;
674
675     /* if there's quotes, remove them */
676     if( ( (p[0]=='`') && (p[len-1]=='`') ) || 
677         ( (p[0]=='\'') && (p[len-1]=='\'') ) )
678     {
679         p++;
680         len -= 2;
681     }
682     str = parser_alloc( info, (len + 1)*sizeof(WCHAR) );
683     if( !str )
684         return str;
685     memcpy( str, p, len*sizeof(WCHAR) );
686     str[len]=0;
687
688     return str;
689 }
690
691 INT SQL_getint( void *info )
692 {
693     SQL_input* sql = (SQL_input*) info;
694     LPCWSTR p = &sql->command[sql->n];
695     INT i, r = 0;
696
697     for( i=0; i<sql->len; i++ )
698     {
699         if( '0' > p[i] || '9' < p[i] )
700         {
701             ERR("should only be numbers here!\n");
702             break;
703         }
704         r = (p[i]-'0') + r*10;
705     }
706
707     return r;
708 }
709
710 int SQL_error( const char *str )
711 {
712     return 0;
713 }
714
715 static struct expr * EXPR_wildcard( void *info )
716 {
717     struct expr *e = parser_alloc( info, sizeof *e );
718     if( e )
719     {
720         e->type = EXPR_WILDCARD;
721     }
722     return e;
723 }
724
725 static struct expr * EXPR_complex( void *info, struct expr *l, UINT op, struct expr *r )
726 {
727     struct expr *e = parser_alloc( info, sizeof *e );
728     if( e )
729     {
730         e->type = EXPR_COMPLEX;
731         e->u.expr.left = l;
732         e->u.expr.op = op;
733         e->u.expr.right = r;
734     }
735     return e;
736 }
737
738 static struct expr * EXPR_column( void *info, column_info *column )
739 {
740     struct expr *e = parser_alloc( info, sizeof *e );
741     if( e )
742     {
743         e->type = EXPR_COLUMN;
744         e->u.sval = column->column;
745     }
746     return e;
747 }
748
749 static struct expr * EXPR_ival( void *info, int val )
750 {
751     struct expr *e = parser_alloc( info, sizeof *e );
752     if( e )
753     {
754         e->type = EXPR_IVAL;
755         e->u.ival = val;
756     }
757     return e;
758 }
759
760 static struct expr * EXPR_sval( void *info, struct sql_str *str )
761 {
762     struct expr *e = parser_alloc( info, sizeof *e );
763     if( e )
764     {
765         e->type = EXPR_SVAL;
766         e->u.sval = SQL_getstring( info, str );
767     }
768     return e;
769 }
770
771 static BOOL SQL_MarkPrimaryKeys( column_info *cols,
772                                  column_info *keys )
773 {
774     column_info *k;
775     BOOL found = TRUE;
776
777     for( k = keys; k && found; k = k->next )
778     {
779         column_info *c;
780
781         found = FALSE;
782         for( c = cols; c && !found; c = c->next )
783         {
784              if( lstrcmpW( k->column, c->column ) )
785                  continue;
786              c->type |= MSITYPE_KEY;
787              found = TRUE;
788         }
789     }
790
791     return found;
792 }
793
794 UINT MSI_ParseSQL( MSIDATABASE *db, LPCWSTR command, MSIVIEW **phview,
795                    struct list *mem )
796 {
797     SQL_input sql;
798     int r;
799
800     *phview = NULL;
801
802     sql.db = db;
803     sql.command = command;
804     sql.n = 0;
805     sql.len = 0;
806     sql.view = phview;
807     sql.mem = mem;
808
809     r = SQL_parse(&sql);
810
811     TRACE("Parse returned %d\n", r);
812     if( r )
813     {
814         *sql.view = NULL;
815         return ERROR_BAD_QUERY_SYNTAX;
816     }
817
818     return ERROR_SUCCESS;
819 }