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