xref: /reactos/dll/win32/msi/sql.y (revision f4be6dc3)
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 #include <stdarg.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 
27 #include "windef.h"
28 #include "winbase.h"
29 #include "query.h"
30 #include "wine/list.h"
31 #include "wine/debug.h"
32 
33 WINE_DEFAULT_DEBUG_CHANNEL(msi);
34 
35 static UINT SQL_getstring( void *info, const struct sql_str *strdata, LPWSTR *str );
36 static INT SQL_getint( void *info );
37 static int sql_lex( void *SQL_lval, SQL_input *info );
38 static int sql_error( SQL_input *info, const char *str);
39 
40 static LPWSTR parser_add_table( void *info, LPCWSTR list, LPCWSTR table );
41 static void *parser_alloc( void *info, unsigned int sz );
42 static column_info *parser_alloc_column( void *info, LPCWSTR table, LPCWSTR column );
43 
44 static BOOL SQL_MarkPrimaryKeys( column_info **cols, column_info *keys);
45 
46 static struct expr * EXPR_complex( void *info, struct expr *l, UINT op, struct expr *r );
47 static struct expr * EXPR_unary( void *info, struct expr *l, UINT op );
48 static struct expr * EXPR_column( void *info, const column_info *column );
49 static struct expr * EXPR_ival( void *info, int val );
50 static struct expr * EXPR_sval( void *info, const struct sql_str *str );
51 static struct expr * EXPR_wildcard( void *info );
52 
53 #define PARSER_BUBBLE_UP_VIEW( sql, result, current_view ) \
54     *sql->view = current_view; \
55     result = current_view
56 
57 %}
58 
59 %lex-param { SQL_input *info }
60 %parse-param { SQL_input *info }
61 %define api.prefix {sql_}
62 %define api.pure
63 
64 %union
65 {
66     struct sql_str str;
67     LPWSTR string;
68     column_info *column_list;
69     MSIVIEW *query;
70     struct expr *expr;
71     USHORT column_type;
72     int integer;
73 }
74 
75 %token TK_ALTER TK_AND TK_BY TK_CHAR TK_COMMA TK_CREATE TK_DELETE TK_DROP
76 %token TK_DISTINCT TK_DOT TK_EQ TK_FREE TK_FROM TK_GE TK_GT TK_HOLD TK_ADD
77 %token <str> TK_ID
78 %token TK_ILLEGAL TK_INSERT TK_INT
79 %token <str> TK_INTEGER
80 %token TK_INTO TK_IS TK_KEY TK_LE TK_LONG TK_LONGCHAR TK_LP TK_LT
81 %token TK_LOCALIZABLE TK_MINUS TK_NE TK_NOT TK_NULL
82 %token TK_OBJECT TK_OR TK_ORDER TK_PRIMARY TK_RP
83 %token TK_SELECT TK_SET TK_SHORT TK_SPACE TK_STAR
84 %token <str> TK_STRING
85 %token TK_TABLE TK_TEMPORARY TK_UPDATE TK_VALUES TK_WHERE TK_WILDCARD
86 
87 /*
88  * These are extra tokens used by the lexer but never seen by the
89  * parser.  We put them in a rule so that the parser generator will
90  * add them to the parse.h output file.
91  *
92  */
93 %nonassoc END_OF_FILE ILLEGAL SPACE UNCLOSED_STRING COMMENT FUNCTION
94           COLUMN AGG_FUNCTION.
95 
96 %type <string> table tablelist id string
97 %type <column_list> selcollist collist selcolumn column column_and_type column_def table_def
98 %type <column_list> column_assignment update_assign_list constlist
99 %type <query> query from selectfrom unorderdfrom
100 %type <query> oneupdate onedelete oneselect onequery onecreate oneinsert onealter onedrop
101 %type <expr> expr val column_val const_val
102 %type <column_type> column_type data_type data_type_l data_count
103 %type <integer> number alterop
104 
105 %left TK_OR
106 %left TK_AND
107 %left TK_NOT
108 %left TK_EQ TK_NE TK_LT TK_GT TK_LE TK_GE TK_LIKE
109 %right TK_NEGATION
110 
111 %%
112 
113 query:
114     onequery
115     {
116         SQL_input* sql = (SQL_input*) info;
117         *sql->view = $1;
118     }
119     ;
120 
121 onequery:
122     oneselect
123   | onecreate
124   | oneinsert
125   | oneupdate
126   | onedelete
127   | onealter
128   | onedrop
129     ;
130 
131 oneinsert:
132     TK_INSERT TK_INTO table TK_LP collist TK_RP TK_VALUES TK_LP constlist TK_RP
133         {
134             SQL_input *sql = (SQL_input*) info;
135             MSIVIEW *insert = NULL;
136 
137             INSERT_CreateView( sql->db, &insert, $3, $5, $9, FALSE );
138             if( !insert )
139                 YYABORT;
140 
141             PARSER_BUBBLE_UP_VIEW( sql, $$,  insert );
142         }
143   | TK_INSERT TK_INTO table TK_LP collist TK_RP TK_VALUES TK_LP constlist TK_RP TK_TEMPORARY
144         {
145             SQL_input *sql = (SQL_input*) info;
146             MSIVIEW *insert = NULL;
147 
148             INSERT_CreateView( sql->db, &insert, $3, $5, $9, TRUE );
149             if( !insert )
150                 YYABORT;
151 
152             PARSER_BUBBLE_UP_VIEW( sql, $$,  insert );
153         }
154     ;
155 
156 onecreate:
157     TK_CREATE TK_TABLE table TK_LP table_def TK_RP
158         {
159             SQL_input* sql = (SQL_input*) info;
160             MSIVIEW *create = NULL;
161             UINT r;
162 
163             if( !$5 )
164                 YYABORT;
165             r = CREATE_CreateView( sql->db, &create, $3, $5, FALSE );
166             if( !create )
167             {
168                 sql->r = r;
169                 YYABORT;
170             }
171 
172             PARSER_BUBBLE_UP_VIEW( sql, $$,  create );
173         }
174   | TK_CREATE TK_TABLE table TK_LP table_def TK_RP TK_HOLD
175         {
176             SQL_input* sql = (SQL_input*) info;
177             MSIVIEW *create = NULL;
178 
179             if( !$5 )
180                 YYABORT;
181             CREATE_CreateView( sql->db, &create, $3, $5, TRUE );
182             if( !create )
183                 YYABORT;
184 
185             PARSER_BUBBLE_UP_VIEW( sql, $$,  create );
186         }
187     ;
188 
189 oneupdate:
190     TK_UPDATE table TK_SET update_assign_list TK_WHERE expr
191         {
192             SQL_input* sql = (SQL_input*) info;
193             MSIVIEW *update = NULL;
194 
195             UPDATE_CreateView( sql->db, &update, $2, $4, $6 );
196             if( !update )
197                 YYABORT;
198 
199             PARSER_BUBBLE_UP_VIEW( sql, $$,  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 
210             PARSER_BUBBLE_UP_VIEW( sql, $$,  update );
211         }
212     ;
213 
214 onedelete:
215     TK_DELETE from
216         {
217             SQL_input* sql = (SQL_input*) info;
218             MSIVIEW *delete = NULL;
219 
220             DELETE_CreateView( sql->db, &delete, $2 );
221             if( !delete )
222                 YYABORT;
223 
224             PARSER_BUBBLE_UP_VIEW( sql, $$, 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, NULL, $4 );
235             if( !alter )
236                 YYABORT;
237 
238             PARSER_BUBBLE_UP_VIEW( sql, $$, alter );
239         }
240   | TK_ALTER TK_TABLE table TK_ADD column_and_type
241         {
242             SQL_input *sql = (SQL_input *)info;
243             MSIVIEW *alter = NULL;
244 
245             ALTER_CreateView( sql->db, &alter, $3, $5, 0 );
246             if (!alter)
247                 YYABORT;
248 
249             PARSER_BUBBLE_UP_VIEW( sql, $$, alter );
250         }
251   | TK_ALTER TK_TABLE table TK_ADD column_and_type TK_HOLD
252         {
253             SQL_input *sql = (SQL_input *)info;
254             MSIVIEW *alter = NULL;
255 
256             ALTER_CreateView( sql->db, &alter, $3, $5, 1 );
257             if (!alter)
258                 YYABORT;
259 
260             PARSER_BUBBLE_UP_VIEW( sql, $$, alter );
261         }
262     ;
263 
264 alterop:
265     TK_HOLD
266         {
267             $$ = 1;
268         }
269   | TK_FREE
270         {
271             $$ = -1;
272         }
273   ;
274 
275 onedrop:
276     TK_DROP TK_TABLE table
277         {
278             SQL_input* sql = (SQL_input*) info;
279             MSIVIEW* drop = NULL;
280             UINT r;
281 
282             r = DROP_CreateView( sql->db, &drop, $3 );
283             if( r != ERROR_SUCCESS || !$$ )
284                 YYABORT;
285 
286             PARSER_BUBBLE_UP_VIEW( sql, $$, drop );
287         }
288   ;
289 
290 table_def:
291     column_def TK_PRIMARY TK_KEY collist
292         {
293             if( SQL_MarkPrimaryKeys( &$1, $4 ) )
294                 $$ = $1;
295             else
296                 $$ = NULL;
297         }
298     ;
299 
300 column_def:
301     column_def TK_COMMA column_and_type
302         {
303             column_info *ci;
304 
305             for( ci = $1; ci->next; ci = ci->next )
306                 ;
307 
308             ci->next = $3;
309             $$ = $1;
310         }
311   | column_and_type
312         {
313             $$ = $1;
314         }
315     ;
316 
317 column_and_type:
318     column column_type
319         {
320             $$ = $1;
321             $$->type = ($2 | MSITYPE_VALID);
322         }
323     ;
324 
325 column_type:
326     data_type_l
327         {
328             $$ = $1;
329         }
330   | data_type_l TK_LOCALIZABLE
331         {
332             $$ = $1 | MSITYPE_LOCALIZABLE;
333         }
334   | data_type_l TK_TEMPORARY
335         {
336             $$ = $1 | MSITYPE_TEMPORARY;
337         }
338     ;
339 
340 data_type_l:
341     data_type
342         {
343             $$ |= MSITYPE_NULLABLE;
344         }
345   | data_type TK_NOT TK_NULL
346         {
347             $$ = $1;
348         }
349     ;
350 
351 data_type:
352     TK_CHAR
353         {
354             $$ = MSITYPE_STRING | 0x400;
355         }
356   | TK_CHAR TK_LP data_count TK_RP
357         {
358             $$ = MSITYPE_STRING | 0x400 | $3;
359         }
360   | TK_LONGCHAR
361         {
362             $$ = MSITYPE_STRING | 0x400;
363         }
364   | TK_SHORT
365         {
366             $$ = 2 | 0x400;
367         }
368   | TK_INT
369         {
370             $$ = 2 | 0x400;
371         }
372   | TK_LONG
373         {
374             $$ = 4;
375         }
376   | TK_OBJECT
377         {
378             $$ = MSITYPE_STRING | MSITYPE_VALID;
379         }
380     ;
381 
382 data_count:
383     number
384         {
385             if( ( $1 > 255 ) || ( $1 < 0 ) )
386                 YYABORT;
387             $$ = $1;
388         }
389     ;
390 
391 oneselect:
392     TK_SELECT selectfrom
393         {
394             $$ = $2;
395         }
396   | TK_SELECT TK_DISTINCT selectfrom
397         {
398             SQL_input* sql = (SQL_input*) info;
399             MSIVIEW* distinct = NULL;
400             UINT r;
401 
402             r = DISTINCT_CreateView( sql->db, &distinct, $3 );
403             if (r != ERROR_SUCCESS)
404                 YYABORT;
405 
406             PARSER_BUBBLE_UP_VIEW( sql, $$, distinct );
407         }
408     ;
409 
410 selectfrom:
411     selcollist from
412         {
413             SQL_input* sql = (SQL_input*) info;
414             MSIVIEW* select = NULL;
415             UINT r;
416 
417             if( $1 )
418             {
419                 r = SELECT_CreateView( sql->db, &select, $2, $1 );
420                 if (r != ERROR_SUCCESS)
421                     YYABORT;
422 
423                 PARSER_BUBBLE_UP_VIEW( sql, $$, select );
424             }
425             else
426                 $$ = $2;
427         }
428     ;
429 
430 selcollist:
431     selcolumn
432   | selcolumn TK_COMMA selcollist
433         {
434             $1->next = $3;
435         }
436   | TK_STAR
437         {
438             $$ = NULL;
439         }
440     ;
441 
442 collist:
443     column
444   | column TK_COMMA collist
445         {
446             $1->next = $3;
447         }
448   | TK_STAR
449         {
450             $$ = NULL;
451         }
452     ;
453 
454 from:
455     TK_FROM table
456         {
457             SQL_input* sql = (SQL_input*) info;
458             MSIVIEW* table = NULL;
459             UINT r;
460 
461             r = TABLE_CreateView( sql->db, $2, &table );
462             if( r != ERROR_SUCCESS || !$$ )
463                 YYABORT;
464 
465             PARSER_BUBBLE_UP_VIEW( sql, $$, table );
466         }
467   | unorderdfrom TK_ORDER TK_BY collist
468         {
469             UINT r;
470 
471             if( $4 )
472             {
473                 r = $1->ops->sort( $1, $4 );
474                 if ( r != ERROR_SUCCESS)
475                     YYABORT;
476             }
477 
478             $$ = $1;
479         }
480   | unorderdfrom
481   ;
482 
483 unorderdfrom:
484     TK_FROM tablelist
485         {
486             SQL_input* sql = (SQL_input*) info;
487             MSIVIEW* where = NULL;
488             UINT r;
489 
490             r = WHERE_CreateView( sql->db, &where, $2, NULL );
491             if( r != ERROR_SUCCESS )
492                 YYABORT;
493 
494             PARSER_BUBBLE_UP_VIEW( sql, $$, where );
495         }
496   | TK_FROM tablelist TK_WHERE expr
497         {
498             SQL_input* sql = (SQL_input*) info;
499             MSIVIEW* where = NULL;
500             UINT r;
501 
502             r = WHERE_CreateView( sql->db, &where, $2, $4 );
503             if( r != ERROR_SUCCESS )
504                 YYABORT;
505 
506             PARSER_BUBBLE_UP_VIEW( sql, $$, where );
507         }
508     ;
509 
510 tablelist:
511     table
512         {
513             $$ = $1;
514         }
515   | table TK_COMMA tablelist
516         {
517             $$ = parser_add_table( info, $3, $1 );
518             if (!$$)
519                 YYABORT;
520         }
521     ;
522 
523 expr:
524     TK_LP expr TK_RP
525         {
526             $$ = $2;
527             if( !$$ )
528                 YYABORT;
529         }
530   | expr TK_AND expr
531         {
532             $$ = EXPR_complex( info, $1, OP_AND, $3 );
533             if( !$$ )
534                 YYABORT;
535         }
536   | expr TK_OR expr
537         {
538             $$ = EXPR_complex( info, $1, OP_OR, $3 );
539             if( !$$ )
540                 YYABORT;
541         }
542   | column_val TK_EQ val
543         {
544             $$ = EXPR_complex( info, $1, OP_EQ, $3 );
545             if( !$$ )
546                 YYABORT;
547         }
548   | column_val TK_GT val
549         {
550             $$ = EXPR_complex( info, $1, OP_GT, $3 );
551             if( !$$ )
552                 YYABORT;
553         }
554   | column_val TK_LT val
555         {
556             $$ = EXPR_complex( info, $1, OP_LT, $3 );
557             if( !$$ )
558                 YYABORT;
559         }
560   | column_val TK_LE val
561         {
562             $$ = EXPR_complex( info, $1, OP_LE, $3 );
563             if( !$$ )
564                 YYABORT;
565         }
566   | column_val TK_GE val
567         {
568             $$ = EXPR_complex( info, $1, OP_GE, $3 );
569             if( !$$ )
570                 YYABORT;
571         }
572   | column_val TK_NE val
573         {
574             $$ = EXPR_complex( info, $1, OP_NE, $3 );
575             if( !$$ )
576                 YYABORT;
577         }
578   | column_val TK_IS TK_NULL
579         {
580             $$ = EXPR_unary( info, $1, OP_ISNULL );
581             if( !$$ )
582                 YYABORT;
583         }
584   | column_val TK_IS TK_NOT TK_NULL
585         {
586             $$ = EXPR_unary( info, $1, OP_NOTNULL );
587             if( !$$ )
588                 YYABORT;
589         }
590     ;
591 
592 val:
593     column_val
594   | const_val
595     ;
596 
597 constlist:
598     const_val
599         {
600             $$ = parser_alloc_column( info, NULL, NULL );
601             if( !$$ )
602                 YYABORT;
603             $$->val = $1;
604         }
605   | const_val TK_COMMA constlist
606         {
607             $$ = parser_alloc_column( info, NULL, NULL );
608             if( !$$ )
609                 YYABORT;
610             $$->val = $1;
611             $$->next = $3;
612         }
613     ;
614 
615 update_assign_list:
616     column_assignment
617   | column_assignment TK_COMMA update_assign_list
618         {
619             $$ = $1;
620             $$->next = $3;
621         }
622     ;
623 
624 column_assignment:
625     column TK_EQ const_val
626         {
627             $$ = $1;
628             $$->val = $3;
629         }
630     ;
631 
632 const_val:
633     number
634         {
635             $$ = EXPR_ival( info, $1 );
636             if( !$$ )
637                 YYABORT;
638         }
639   | TK_MINUS number %prec TK_NEGATION
640         {
641             $$ = EXPR_ival( info, -$2 );
642             if( !$$ )
643                 YYABORT;
644         }
645   | TK_STRING
646         {
647             $$ = EXPR_sval( info, &$1 );
648             if( !$$ )
649                 YYABORT;
650         }
651   | TK_WILDCARD
652         {
653             $$ = EXPR_wildcard( info );
654             if( !$$ )
655                 YYABORT;
656         }
657    | TK_NULL
658         {
659             $$ = EXPR_sval( info, NULL );
660             if ( !$$ )
661                 YYABORT;
662         }
663     ;
664 
665 column_val:
666     column
667         {
668             $$ = EXPR_column( info, $1 );
669             if( !$$ )
670                 YYABORT;
671         }
672     ;
673 
674 column:
675     table TK_DOT id
676         {
677             $$ = parser_alloc_column( info, $1, $3 );
678             if( !$$ )
679                 YYABORT;
680         }
681   | id
682         {
683             $$ = parser_alloc_column( info, NULL, $1 );
684             if( !$$ )
685                 YYABORT;
686         }
687     ;
688 
689 selcolumn:
690     table TK_DOT id
691         {
692             $$ = parser_alloc_column( info, $1, $3 );
693             if( !$$ )
694                 YYABORT;
695         }
696   | id
697         {
698             $$ = parser_alloc_column( info, NULL, $1 );
699             if( !$$ )
700                 YYABORT;
701         }
702   | string
703         {
704             $$ = parser_alloc_column( info, NULL, $1 );
705             if( !$$ )
706                 YYABORT;
707         }
708     ;
709 
710 table:
711     id
712         {
713             $$ = $1;
714         }
715     ;
716 
717 id:
718     TK_ID
719         {
720             if ( SQL_getstring( info, &$1, &$$ ) != ERROR_SUCCESS || !$$ )
721                 YYABORT;
722         }
723     ;
724 
725 string:
726     TK_STRING
727         {
728             if ( SQL_getstring( info, &$1, &$$ ) != ERROR_SUCCESS || !$$ )
729                 YYABORT;
730         }
731     ;
732 
733 number:
734     TK_INTEGER
735         {
736             $$ = SQL_getint( info );
737         }
738     ;
739 
740 %%
741 
742 static LPWSTR parser_add_table( void *info, LPCWSTR list, LPCWSTR table )
743 {
744     DWORD len = lstrlenW( list ) + lstrlenW( table ) + 2;
745     LPWSTR ret;
746 
747     ret = parser_alloc( info, len * sizeof(WCHAR) );
748     if( ret )
749     {
750         lstrcpyW( ret, list );
751         lstrcatW( ret, L" " );
752         lstrcatW( ret, table );
753     }
754     return ret;
755 }
756 
parser_alloc(void * info,unsigned int sz)757 static void *parser_alloc( void *info, unsigned int sz )
758 {
759     SQL_input* sql = (SQL_input*) info;
760     struct list *mem;
761 
762     mem = malloc( sizeof (struct list) + sz );
763     list_add_tail( sql->mem, mem );
764     return &mem[1];
765 }
766 
parser_alloc_column(void * info,LPCWSTR table,LPCWSTR column)767 static column_info *parser_alloc_column( void *info, LPCWSTR table, LPCWSTR column )
768 {
769     column_info *col;
770 
771     col = parser_alloc( info, sizeof (*col) );
772     if( col )
773     {
774         col->table = table;
775         col->column = column;
776         col->val = NULL;
777         col->type = 0;
778         col->next = NULL;
779     }
780 
781     return col;
782 }
783 
sql_lex(void * SQL_lval,SQL_input * sql)784 static int sql_lex( void *SQL_lval, SQL_input *sql )
785 {
786     int token, skip;
787     struct sql_str * str = SQL_lval;
788 
789     do
790     {
791         sql->n += sql->len;
792         if( ! sql->command[sql->n] )
793             return 0;  /* end of input */
794 
795         /* TRACE("string : %s\n", debugstr_w(&sql->command[sql->n])); */
796         sql->len = sqliteGetToken( &sql->command[sql->n], &token, &skip );
797         if( sql->len==0 )
798             break;
799         str->data = &sql->command[sql->n];
800         str->len = sql->len;
801         sql->n += skip;
802     }
803     while( token == TK_SPACE );
804 
805     /* TRACE("token : %d (%s)\n", token, debugstr_wn(&sql->command[sql->n], sql->len)); */
806 
807     return token;
808 }
809 
SQL_getstring(void * info,const struct sql_str * strdata,LPWSTR * str)810 UINT SQL_getstring( void *info, const struct sql_str *strdata, LPWSTR *str )
811 {
812     LPCWSTR p = strdata->data;
813     UINT len = strdata->len;
814 
815     /* match quotes */
816     if( ( (p[0]=='`') && (p[len-1]!='`') ) ||
817         ( (p[0]=='\'') && (p[len-1]!='\'') ) )
818         return ERROR_FUNCTION_FAILED;
819 
820     /* if there are quotes, remove them */
821     if( ( (p[0]=='`') && (p[len-1]=='`') ) ||
822         ( (p[0]=='\'') && (p[len-1]=='\'') ) )
823     {
824         p++;
825         len -= 2;
826     }
827     *str = parser_alloc( info, (len + 1)*sizeof(WCHAR) );
828     if( !*str )
829         return ERROR_OUTOFMEMORY;
830     memcpy( *str, p, len*sizeof(WCHAR) );
831     (*str)[len]=0;
832 
833     return ERROR_SUCCESS;
834 }
835 
SQL_getint(void * info)836 INT SQL_getint( void *info )
837 {
838     SQL_input* sql = (SQL_input*) info;
839     LPCWSTR p = &sql->command[sql->n];
840     INT i, r = 0;
841 
842     for( i=0; i<sql->len; i++ )
843     {
844         if( '0' > p[i] || '9' < p[i] )
845         {
846             ERR("should only be numbers here!\n");
847             break;
848         }
849         r = (p[i]-'0') + r*10;
850     }
851 
852     return r;
853 }
854 
sql_error(SQL_input * info,const char * str)855 static int sql_error( SQL_input *info, const char *str )
856 {
857     return 0;
858 }
859 
EXPR_wildcard(void * info)860 static struct expr * EXPR_wildcard( void *info )
861 {
862     struct expr *e = parser_alloc( info, sizeof *e );
863     if( e )
864     {
865         e->type = EXPR_WILDCARD;
866     }
867     return e;
868 }
869 
EXPR_complex(void * info,struct expr * l,UINT op,struct expr * r)870 static struct expr * EXPR_complex( void *info, struct expr *l, UINT op, struct expr *r )
871 {
872     struct expr *e = parser_alloc( info, sizeof *e );
873     if( e )
874     {
875         e->type = EXPR_COMPLEX;
876         e->u.expr.left = l;
877         e->u.expr.op = op;
878         e->u.expr.right = r;
879     }
880     return e;
881 }
882 
EXPR_unary(void * info,struct expr * l,UINT op)883 static struct expr * EXPR_unary( void *info, struct expr *l, UINT op )
884 {
885     struct expr *e = parser_alloc( info, sizeof *e );
886     if( e )
887     {
888         e->type = EXPR_UNARY;
889         e->u.expr.left = l;
890         e->u.expr.op = op;
891         e->u.expr.right = NULL;
892     }
893     return e;
894 }
895 
EXPR_column(void * info,const column_info * column)896 static struct expr * EXPR_column( void *info, const column_info *column )
897 {
898     struct expr *e = parser_alloc( info, sizeof *e );
899     if( e )
900     {
901         e->type = EXPR_COLUMN;
902         e->u.column.unparsed.column = column->column;
903         e->u.column.unparsed.table = column->table;
904     }
905     return e;
906 }
907 
EXPR_ival(void * info,int val)908 static struct expr * EXPR_ival( void *info, int val )
909 {
910     struct expr *e = parser_alloc( info, sizeof *e );
911     if( e )
912     {
913         e->type = EXPR_IVAL;
914         e->u.ival = val;
915     }
916     return e;
917 }
918 
EXPR_sval(void * info,const struct sql_str * str)919 static struct expr * EXPR_sval( void *info, const struct sql_str *str )
920 {
921     struct expr *e = parser_alloc( info, sizeof *e );
922     if( e )
923     {
924         e->type = EXPR_SVAL;
925         if( !str) e->u.sval = NULL;
926         else if( SQL_getstring( info, str, (LPWSTR *)&e->u.sval ) != ERROR_SUCCESS )
927             return NULL; /* e will be freed by query destructor */
928     }
929     return e;
930 }
931 
swap_columns(column_info ** cols,column_info * A,int idx)932 static void swap_columns( column_info **cols, column_info *A, int idx )
933 {
934     column_info *preA = NULL, *preB = NULL, *B, *ptr;
935     int i = 0;
936 
937     B = NULL;
938     ptr = *cols;
939     while( ptr )
940     {
941         if( i++ == idx )
942             B = ptr;
943         else if( !B )
944             preB = ptr;
945 
946         if( ptr->next == A )
947             preA = ptr;
948 
949         ptr = ptr->next;
950     }
951 
952     if( preB ) preB->next = A;
953     if( preA ) preA->next = B;
954     ptr = A->next;
955     A->next = B->next;
956     B->next = ptr;
957     if( idx == 0 )
958       *cols = A;
959 }
960 
SQL_MarkPrimaryKeys(column_info ** cols,column_info * keys)961 static BOOL SQL_MarkPrimaryKeys( column_info **cols,
962                                  column_info *keys )
963 {
964     column_info *k;
965     BOOL found = TRUE;
966     int count;
967 
968     for( k = keys, count = 0; k && found; k = k->next, count++ )
969     {
970         column_info *c;
971         int idx;
972 
973         found = FALSE;
974         for( c = *cols, idx = 0; c && !found; c = c->next, idx++ )
975         {
976             if( wcscmp( k->column, c->column ) )
977                 continue;
978             c->type |= MSITYPE_KEY;
979             found = TRUE;
980             if (idx != count)
981                 swap_columns( cols, c, count );
982         }
983     }
984 
985     return found;
986 }
987 
MSI_ParseSQL(MSIDATABASE * db,LPCWSTR command,MSIVIEW ** phview,struct list * mem)988 UINT MSI_ParseSQL( MSIDATABASE *db, LPCWSTR command, MSIVIEW **phview,
989                    struct list *mem )
990 {
991     SQL_input sql;
992     int r;
993 
994     *phview = NULL;
995 
996     sql.db = db;
997     sql.command = command;
998     sql.n = 0;
999     sql.len = 0;
1000     sql.r = ERROR_BAD_QUERY_SYNTAX;
1001     sql.view = phview;
1002     sql.mem = mem;
1003 
1004     r = sql_parse(&sql);
1005 
1006     TRACE("Parse returned %d\n", r);
1007     if( r )
1008     {
1009         if (*sql.view)
1010         {
1011             (*sql.view)->ops->delete(*sql.view);
1012             *sql.view = NULL;
1013         }
1014         return sql.r;
1015     }
1016 
1017     return ERROR_SUCCESS;
1018 }
1019