msi/tests: Write-strings warnings fix.
[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             UINT r;
410
411             /* only support inner joins on two tables */
412             r = JOIN_CreateView( sql->db, &$$, $2, $4, $6 );
413             if( r != ERROR_SUCCESS )
414                 YYABORT;
415         }
416     ;
417
418 from:
419     fromtable
420   | fromtable TK_WHERE expr
421         { 
422             SQL_input* sql = (SQL_input*) info;
423             UINT r;
424
425             $$ = NULL;
426             r = WHERE_CreateView( sql->db, &$$, $1, $3 );
427             if( r != ERROR_SUCCESS )
428             {
429                 $1->ops->delete( $1 );
430                 YYABORT;
431             }
432         }
433     ;
434
435 fromtable:
436     TK_FROM table
437         {
438             SQL_input* sql = (SQL_input*) info;
439             UINT r;
440
441             $$ = NULL;
442             r = TABLE_CreateView( sql->db, $2, &$$ );
443             if( r != ERROR_SUCCESS || !$$ )
444                 YYABORT;
445         }
446     ;
447
448 expr:
449     TK_LP expr TK_RP
450         {
451             $$ = $2;
452             if( !$$ )
453                 YYABORT;
454         }
455   | expr TK_AND expr
456         {
457             $$ = EXPR_complex( info, $1, OP_AND, $3 );
458             if( !$$ )
459                 YYABORT;
460         }
461   | expr TK_OR expr
462         {
463             $$ = EXPR_complex( info, $1, OP_OR, $3 );
464             if( !$$ )
465                 YYABORT;
466         }
467   | column_val TK_EQ val
468         {
469             $$ = EXPR_complex( info, $1, OP_EQ, $3 );
470             if( !$$ )
471                 YYABORT;
472         }
473   | column_val TK_GT val
474         {
475             $$ = EXPR_complex( info, $1, OP_GT, $3 );
476             if( !$$ )
477                 YYABORT;
478         }
479   | column_val TK_LT val
480         {
481             $$ = EXPR_complex( info, $1, OP_LT, $3 );
482             if( !$$ )
483                 YYABORT;
484         }
485   | column_val TK_LE val
486         {
487             $$ = EXPR_complex( info, $1, OP_LE, $3 );
488             if( !$$ )
489                 YYABORT;
490         }
491   | column_val TK_GE val
492         {
493             $$ = EXPR_complex( info, $1, OP_GE, $3 );
494             if( !$$ )
495                 YYABORT;
496         }
497   | column_val TK_NE val
498         {
499             $$ = EXPR_complex( info, $1, OP_NE, $3 );
500             if( !$$ )
501                 YYABORT;
502         }
503   | column_val TK_IS TK_NULL
504         {
505             $$ = EXPR_complex( info, $1, OP_ISNULL, NULL );
506             if( !$$ )
507                 YYABORT;
508         }
509   | column_val TK_IS TK_NOT TK_NULL
510         {
511             $$ = EXPR_complex( info, $1, OP_NOTNULL, NULL );
512             if( !$$ )
513                 YYABORT;
514         }
515     ;
516
517 val:
518     column_val
519   | const_val
520     ;
521
522 constlist:
523     const_val
524         {
525             $$ = parser_alloc_column( info, NULL, NULL );
526             if( !$$ )
527                 YYABORT;
528             $$->val = $1;
529         }
530   | const_val TK_COMMA constlist
531         {
532             $$ = parser_alloc_column( info, NULL, NULL );
533             if( !$$ )
534                 YYABORT;
535             $$->val = $1;
536             $$->next = $3;
537         }
538     ;
539
540 update_assign_list:
541     column_assignment
542   | column_assignment TK_COMMA update_assign_list
543         {
544             $$ = $1;
545             $$->next = $3;
546         }
547     ;
548
549 column_assignment:
550     column TK_EQ const_val
551         {
552             $$ = $1;
553             $$->val = $3;
554         }
555     ;
556
557 const_val:
558     number
559         {
560             $$ = EXPR_ival( info, $1 );
561             if( !$$ )
562                 YYABORT;
563         }
564   | TK_MINUS number %prec TK_NEGATION
565         {
566             $$ = EXPR_ival( info, -$2 );
567             if( !$$ )
568                 YYABORT;
569         }
570   | TK_STRING
571         {
572             $$ = EXPR_sval( info, &$1 );
573             if( !$$ )
574                 YYABORT;
575         }
576   | TK_WILDCARD
577         {
578             $$ = EXPR_wildcard( info );
579             if( !$$ )
580                 YYABORT;
581         }
582     ;
583
584 column_val:
585     column 
586         {
587             $$ = EXPR_column( info, $1 );
588             if( !$$ )
589                 YYABORT;
590         }
591     ;
592
593 column:
594     table TK_DOT id
595         {
596             $$ = parser_alloc_column( info, $1, $3 );
597             if( !$$ )
598                 YYABORT;
599         }
600   | id
601         {
602             $$ = parser_alloc_column( info, NULL, $1 );
603             if( !$$ )
604                 YYABORT;
605         }
606     ;
607
608 table:
609     id
610         {
611             $$ = $1;
612         }
613     ;
614
615 id:
616     TK_ID
617         {
618             $$ = SQL_getstring( info, &$1 );
619             if( !$$ )
620                 YYABORT;
621         }
622     ;
623
624 number:
625     TK_INTEGER
626         {
627             $$ = SQL_getint( info );
628         }
629     ;
630
631 %%
632
633 static void *parser_alloc( void *info, unsigned int sz )
634 {
635     SQL_input* sql = (SQL_input*) info;
636     struct list *mem;
637
638     mem = msi_alloc( sizeof (struct list) + sz );
639     list_add_tail( sql->mem, mem );
640     return &mem[1];
641 }
642
643 static column_info *parser_alloc_column( void *info, LPCWSTR table, LPCWSTR column )
644 {
645     column_info *col;
646
647     col = parser_alloc( info, sizeof (*col) );
648     if( col )
649     {
650         col->table = table;
651         col->column = column;
652         col->val = NULL;
653         col->type = 0;
654         col->next = NULL;
655     }
656
657     return col;
658 }
659
660 int SQL_lex( void *SQL_lval, SQL_input *sql )
661 {
662     int token;
663     struct sql_str * str = SQL_lval;
664
665     do
666     {
667         sql->n += sql->len;
668         if( ! sql->command[sql->n] )
669             return 0;  /* end of input */
670
671         /* TRACE("string : %s\n", debugstr_w(&sql->command[sql->n])); */
672         sql->len = sqliteGetToken( &sql->command[sql->n], &token );
673         if( sql->len==0 )
674             break;
675         str->data = &sql->command[sql->n];
676         str->len = sql->len;
677     }
678     while( token == TK_SPACE );
679
680     /* TRACE("token : %d (%s)\n", token, debugstr_wn(&sql->command[sql->n], sql->len)); */
681     
682     return token;
683 }
684
685 LPWSTR SQL_getstring( void *info, struct sql_str *strdata )
686 {
687     LPCWSTR p = strdata->data;
688     UINT len = strdata->len;
689     LPWSTR str;
690
691     /* if there's quotes, remove them */
692     if( ( (p[0]=='`') && (p[len-1]=='`') ) || 
693         ( (p[0]=='\'') && (p[len-1]=='\'') ) )
694     {
695         p++;
696         len -= 2;
697     }
698     str = parser_alloc( info, (len + 1)*sizeof(WCHAR) );
699     if( !str )
700         return str;
701     memcpy( str, p, len*sizeof(WCHAR) );
702     str[len]=0;
703
704     return str;
705 }
706
707 INT SQL_getint( void *info )
708 {
709     SQL_input* sql = (SQL_input*) info;
710     LPCWSTR p = &sql->command[sql->n];
711     INT i, r = 0;
712
713     for( i=0; i<sql->len; i++ )
714     {
715         if( '0' > p[i] || '9' < p[i] )
716         {
717             ERR("should only be numbers here!\n");
718             break;
719         }
720         r = (p[i]-'0') + r*10;
721     }
722
723     return r;
724 }
725
726 int SQL_error( const char *str )
727 {
728     return 0;
729 }
730
731 static struct expr * EXPR_wildcard( void *info )
732 {
733     struct expr *e = parser_alloc( info, sizeof *e );
734     if( e )
735     {
736         e->type = EXPR_WILDCARD;
737     }
738     return e;
739 }
740
741 static struct expr * EXPR_complex( void *info, struct expr *l, UINT op, struct expr *r )
742 {
743     struct expr *e = parser_alloc( info, sizeof *e );
744     if( e )
745     {
746         e->type = EXPR_COMPLEX;
747         e->u.expr.left = l;
748         e->u.expr.op = op;
749         e->u.expr.right = r;
750     }
751     return e;
752 }
753
754 static struct expr * EXPR_column( void *info, column_info *column )
755 {
756     struct expr *e = parser_alloc( info, sizeof *e );
757     if( e )
758     {
759         e->type = EXPR_COLUMN;
760         e->u.sval = column->column;
761     }
762     return e;
763 }
764
765 static struct expr * EXPR_ival( void *info, int val )
766 {
767     struct expr *e = parser_alloc( info, sizeof *e );
768     if( e )
769     {
770         e->type = EXPR_IVAL;
771         e->u.ival = val;
772     }
773     return e;
774 }
775
776 static struct expr * EXPR_sval( void *info, struct sql_str *str )
777 {
778     struct expr *e = parser_alloc( info, sizeof *e );
779     if( e )
780     {
781         e->type = EXPR_SVAL;
782         e->u.sval = SQL_getstring( info, str );
783     }
784     return e;
785 }
786
787 static BOOL SQL_MarkPrimaryKeys( column_info *cols,
788                                  column_info *keys )
789 {
790     column_info *k;
791     BOOL found = TRUE;
792
793     for( k = keys; k && found; k = k->next )
794     {
795         column_info *c;
796
797         found = FALSE;
798         for( c = cols; c && !found; c = c->next )
799         {
800              if( lstrcmpW( k->column, c->column ) )
801                  continue;
802              c->type |= MSITYPE_KEY;
803              found = TRUE;
804         }
805     }
806
807     return found;
808 }
809
810 UINT MSI_ParseSQL( MSIDATABASE *db, LPCWSTR command, MSIVIEW **phview,
811                    struct list *mem )
812 {
813     SQL_input sql;
814     int r;
815
816     *phview = NULL;
817
818     sql.db = db;
819     sql.command = command;
820     sql.n = 0;
821     sql.len = 0;
822     sql.view = phview;
823     sql.mem = mem;
824
825     r = SQL_parse(&sql);
826
827     TRACE("Parse returned %d\n", r);
828     if( r )
829     {
830         *sql.view = NULL;
831         return ERROR_BAD_QUERY_SYNTAX;
832     }
833
834     return ERROR_SUCCESS;
835 }