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