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