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