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