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