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