Implement NtAccessCheck.
[wine/gsoc-2012-control.git] / dlls / msi / sql.y
blob41d91cfd6f6a8281fcc441d01696f711d62f7c9d
1 %{
3 /*
4 * Implementation of the Microsoft Installer (msi.dll)
6 * Copyright 2002-2004 Mike McCormack for CodeWeavers
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.
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.
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 #include "config.h"
26 #include <stdarg.h>
27 #include <stdio.h>
28 #include <stdlib.h>
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"
37 #define YYLEX_PARAM info
38 #define YYPARSE_PARAM info
40 extern int SQL_error(const char *str);
42 WINE_DEFAULT_DEBUG_CHANNEL(msi);
44 typedef struct tag_SQL_input
46 MSIDATABASE *db;
47 LPCWSTR command;
48 DWORD n, len;
49 MSIVIEW **view; /* view structure for the resulting query */
50 struct list *mem;
51 } SQL_input;
53 static LPWSTR SQL_getstring( void *info, struct sql_str *str );
54 static INT SQL_getint( void *info );
55 static int SQL_lex( void *SQL_lval, SQL_input *info );
57 static void *parser_alloc( void *info, unsigned int sz );
59 static BOOL SQL_MarkPrimaryKeys( create_col_info *cols, string_list *keys);
61 static struct expr * EXPR_complex( void *info, struct expr *l, UINT op, struct expr *r );
62 static struct expr * EXPR_column( void *info, LPWSTR column );
63 static struct expr * EXPR_ival( void *info, struct sql_str *, int sign );
64 static struct expr * EXPR_sval( void *info, struct sql_str * );
65 static struct expr * EXPR_wildcard( void *info );
69 %pure-parser
71 %union
73 struct sql_str str;
74 LPWSTR string;
75 string_list *column_list;
76 value_list *val_list;
77 MSIVIEW *query;
78 struct expr *expr;
79 USHORT column_type;
80 create_col_info *column_info;
81 column_assignment update_col_info;
84 %token TK_ABORT TK_AFTER TK_AGG_FUNCTION TK_ALL TK_AND TK_AS TK_ASC
85 %token TK_BEFORE TK_BEGIN TK_BETWEEN TK_BITAND TK_BITNOT TK_BITOR TK_BY
86 %token TK_CASCADE TK_CASE TK_CHAR TK_CHECK TK_CLUSTER TK_COLLATE TK_COLUMN
87 %token TK_COMMA TK_COMMENT TK_COMMIT TK_CONCAT TK_CONFLICT
88 %token TK_CONSTRAINT TK_COPY TK_CREATE
89 %token TK_DEFAULT TK_DEFERRABLE TK_DEFERRED TK_DELETE TK_DELIMITERS TK_DESC
90 %token TK_DISTINCT TK_DOT TK_DROP TK_EACH
91 %token TK_ELSE TK_END TK_END_OF_FILE TK_EQ TK_EXCEPT TK_EXPLAIN
92 %token TK_FAIL TK_FLOAT TK_FOR TK_FOREIGN TK_FROM TK_FUNCTION
93 %token TK_GE TK_GLOB TK_GROUP TK_GT
94 %token TK_HAVING TK_HOLD
95 %token TK_IGNORE TK_ILLEGAL TK_IMMEDIATE TK_IN TK_INDEX TK_INITIALLY
96 %token <str> TK_ID
97 %token TK_INSERT TK_INSTEAD TK_INT
98 %token <str> TK_INTEGER
99 %token TK_INTERSECT TK_INTO TK_IS
100 %token TK_ISNULL
101 %token TK_JOIN TK_JOIN_KW
102 %token TK_KEY
103 %token TK_LE TK_LIKE TK_LIMIT TK_LONG TK_LONGCHAR TK_LP TK_LSHIFT TK_LT
104 %token TK_LOCALIZABLE
105 %token TK_MATCH TK_MINUS
106 %token TK_NE TK_NOT TK_NOTNULL TK_NULL
107 %token TK_OBJECT TK_OF TK_OFFSET TK_ON TK_OR TK_ORACLE_OUTER_JOIN TK_ORDER
108 %token TK_PLUS TK_PRAGMA TK_PRIMARY
109 %token TK_RAISE TK_REFERENCES TK_REM TK_REPLACE TK_RESTRICT TK_ROLLBACK
110 %token TK_ROW TK_RP TK_RSHIFT
111 %token TK_SELECT TK_SEMI TK_SET TK_SHORT TK_SLASH TK_SPACE TK_STAR TK_STATEMENT
112 %token <str> TK_STRING
113 %token TK_TABLE TK_TEMP TK_THEN TK_TRANSACTION TK_TRIGGER
114 %token TK_UMINUS TK_UNCLOSED_STRING TK_UNION TK_UNIQUE
115 %token TK_UPDATE TK_UPLUS TK_USING
116 %token TK_VACUUM TK_VALUES TK_VIEW
117 %token TK_WHEN TK_WHERE TK_WILDCARD
120 * These are extra tokens used by the lexer but never seen by the
121 * parser. We put them in a rule so that the parser generator will
122 * add them to the parse.h output file.
125 %nonassoc END_OF_FILE ILLEGAL SPACE UNCLOSED_STRING COMMENT FUNCTION
126 COLUMN AGG_FUNCTION.
128 %type <string> column table id
129 %type <column_list> selcollist
130 %type <query> query from fromtable unorderedsel selectfrom
131 %type <query> oneupdate onedelete oneselect onequery onecreate oneinsert
132 %type <expr> expr val column_val const_val
133 %type <column_type> column_type data_type data_type_l data_count
134 %type <column_info> column_def table_def
135 %type <val_list> constlist
136 %type <update_col_info> column_assignment update_assign_list
140 query:
141 onequery
143 SQL_input* sql = (SQL_input*) info;
144 *sql->view = $1;
148 onequery:
149 oneselect
150 | onecreate
151 | oneinsert
152 | oneupdate
153 | onedelete
156 oneinsert:
157 TK_INSERT TK_INTO table TK_LP selcollist TK_RP TK_VALUES TK_LP constlist TK_RP
159 SQL_input *sql = (SQL_input*) info;
160 MSIVIEW *insert = NULL;
161 UINT r;
163 r = INSERT_CreateView( sql->db, &insert, $3, $5, $9, FALSE );
164 if( !insert )
165 YYABORT;
166 $$ = insert;
168 | TK_INSERT TK_INTO table TK_LP selcollist TK_RP TK_VALUES TK_LP constlist TK_RP TK_TEMP
170 SQL_input *sql = (SQL_input*) info;
171 MSIVIEW *insert = NULL;
173 INSERT_CreateView( sql->db, &insert, $3, $5, $9, TRUE );
174 if( !insert )
175 YYABORT;
176 $$ = insert;
180 onecreate:
181 TK_CREATE TK_TABLE table TK_LP table_def TK_RP
183 SQL_input* sql = (SQL_input*) info;
184 MSIVIEW *create = NULL;
186 if( !$5 )
187 YYABORT;
188 CREATE_CreateView( sql->db, &create, $3, $5, FALSE );
189 if( !create )
190 YYABORT;
191 $$ = create;
193 | TK_CREATE TK_TABLE table TK_LP table_def TK_RP TK_HOLD
195 SQL_input* sql = (SQL_input*) info;
196 MSIVIEW *create = NULL;
198 if( !$5 )
199 YYABORT;
200 CREATE_CreateView( sql->db, &create, $3, $5, TRUE );
201 if( !create )
202 YYABORT;
203 $$ = create;
207 oneupdate:
208 TK_UPDATE table TK_SET update_assign_list TK_WHERE expr
210 SQL_input* sql = (SQL_input*) info;
211 MSIVIEW *update = NULL;
213 UPDATE_CreateView( sql->db, &update, $2, &$4, $6 );
214 if( !update )
215 YYABORT;
216 $$ = update;
220 onedelete:
221 TK_DELETE from
223 SQL_input* sql = (SQL_input*) info;
224 MSIVIEW *delete = NULL;
226 DELETE_CreateView( sql->db, &delete, $2 );
227 if( !delete )
228 YYABORT;
229 $$ = delete;
233 table_def:
234 column_def TK_PRIMARY TK_KEY selcollist
236 if( SQL_MarkPrimaryKeys( $1, $4 ) )
237 $$ = $1;
238 else
239 $$ = NULL;
243 column_def:
244 column_def TK_COMMA column column_type
246 create_col_info *ci;
248 for( ci = $1; ci->next; ci = ci->next )
251 ci->next = HeapAlloc( GetProcessHeap(), 0, sizeof *$$ );
252 if( !ci->next )
254 /* FIXME: free $1 */
255 YYABORT;
257 ci->next->colname = $3;
258 ci->next->type = $4;
259 ci->next->next = NULL;
261 $$ = $1;
263 | column column_type
265 $$ = HeapAlloc( GetProcessHeap(), 0, sizeof *$$ );
266 if( ! $$ )
267 YYABORT;
268 $$->colname = $1;
269 $$->type = $2;
270 $$->next = NULL;
274 column_type:
275 data_type_l
277 $$ = $1 | MSITYPE_VALID;
279 | data_type_l TK_LOCALIZABLE
281 FIXME("LOCALIZABLE ignored\n");
282 $$ = $1 | MSITYPE_VALID;
286 data_type_l:
287 data_type
289 $$ |= MSITYPE_NULLABLE;
291 | data_type TK_NOT TK_NULL
293 $$ = $1;
297 data_type:
298 TK_CHAR
300 $$ = MSITYPE_STRING | 1;
302 | TK_CHAR TK_LP data_count TK_RP
304 $$ = MSITYPE_STRING | 0x400 | $3;
306 | TK_LONGCHAR
308 $$ = 2;
310 | TK_SHORT
312 $$ = 2;
314 | TK_INT
316 $$ = 2;
318 | TK_LONG
320 $$ = 4;
322 | TK_OBJECT
324 $$ = 0;
328 data_count:
329 TK_INTEGER
331 SQL_input* sql = (SQL_input*) info;
332 int val = SQL_getint(sql);
333 if( ( val > 255 ) || ( val < 0 ) )
334 YYABORT;
335 $$ = val;
339 oneselect:
340 unorderedsel TK_ORDER TK_BY selcollist
342 SQL_input* sql = (SQL_input*) info;
344 $$ = NULL;
345 if( $4 )
346 ORDER_CreateView( sql->db, &$$, $1, $4 );
347 else
348 $$ = $1;
349 if( !$$ )
350 YYABORT;
352 | unorderedsel
355 unorderedsel:
356 TK_SELECT selectfrom
358 $$ = $2;
360 | TK_SELECT TK_DISTINCT selectfrom
362 SQL_input* sql = (SQL_input*) info;
364 $$ = NULL;
365 DISTINCT_CreateView( sql->db, &$$, $3 );
366 if( !$$ )
367 YYABORT;
371 selectfrom:
372 selcollist from
374 SQL_input* sql = (SQL_input*) info;
376 $$ = NULL;
377 if( $1 )
378 SELECT_CreateView( sql->db, &$$, $2, $1 );
379 else
380 $$ = $2;
382 if( !$$ )
383 YYABORT;
387 selcollist:
388 column
390 string_list *list;
392 list = HeapAlloc( GetProcessHeap(), 0, sizeof *list );
393 if( !list )
394 YYABORT;
395 list->string = $1;
396 list->next = NULL;
398 $$ = list;
399 TRACE("Collist %s\n",debugstr_w($$->string));
401 | column TK_COMMA selcollist
403 string_list *list;
405 list = HeapAlloc( GetProcessHeap(), 0, sizeof *list );
406 if( !list )
407 YYABORT;
408 list->string = $1;
409 list->next = $3;
411 $$ = list;
412 TRACE("From table: %s\n",debugstr_w($$->string));
414 | TK_STAR
416 $$ = NULL;
420 from:
421 fromtable
422 | fromtable TK_WHERE expr
424 SQL_input* sql = (SQL_input*) info;
425 UINT r;
427 $$ = NULL;
428 r = WHERE_CreateView( sql->db, &$$, $1, $3 );
429 if( r != ERROR_SUCCESS || !$$ )
430 YYABORT;
434 fromtable:
435 TK_FROM table
437 SQL_input* sql = (SQL_input*) info;
438 UINT r;
440 $$ = NULL;
441 r = TABLE_CreateView( sql->db, $2, &$$ );
442 if( r != ERROR_SUCCESS || !$$ )
443 YYABORT;
447 expr:
448 TK_LP expr TK_RP
450 $$ = $2;
451 if( !$$ )
452 YYABORT;
454 | column_val TK_EQ column_val
456 $$ = EXPR_complex( info, $1, OP_EQ, $3 );
457 if( !$$ )
458 YYABORT;
460 | expr TK_AND expr
462 $$ = EXPR_complex( info, $1, OP_AND, $3 );
463 if( !$$ )
464 YYABORT;
466 | expr TK_OR expr
468 $$ = EXPR_complex( info, $1, OP_OR, $3 );
469 if( !$$ )
470 YYABORT;
472 | column_val TK_EQ val
474 $$ = EXPR_complex( info, $1, OP_EQ, $3 );
475 if( !$$ )
476 YYABORT;
478 | column_val TK_GT val
480 $$ = EXPR_complex( info, $1, OP_GT, $3 );
481 if( !$$ )
482 YYABORT;
484 | column_val TK_LT val
486 $$ = EXPR_complex( info, $1, OP_LT, $3 );
487 if( !$$ )
488 YYABORT;
490 | column_val TK_LE val
492 $$ = EXPR_complex( info, $1, OP_LE, $3 );
493 if( !$$ )
494 YYABORT;
496 | column_val TK_GE val
498 $$ = EXPR_complex( info, $1, OP_GE, $3 );
499 if( !$$ )
500 YYABORT;
502 | column_val TK_NE val
504 $$ = EXPR_complex( info, $1, OP_NE, $3 );
505 if( !$$ )
506 YYABORT;
508 | column_val TK_IS TK_NULL
510 $$ = EXPR_complex( info, $1, OP_ISNULL, NULL );
511 if( !$$ )
512 YYABORT;
514 | column_val TK_IS TK_NOT TK_NULL
516 $$ = EXPR_complex( info, $1, OP_NOTNULL, NULL );
517 if( !$$ )
518 YYABORT;
522 val:
523 column_val
524 | const_val
527 constlist:
528 const_val
530 value_list *vals;
532 vals = parser_alloc( info, sizeof *vals );
533 if( !vals )
534 YYABORT;
535 vals->val = $1;
536 vals->next = NULL;
537 $$ = vals;
539 | const_val TK_COMMA constlist
541 value_list *vals;
543 vals = parser_alloc( info, sizeof *vals );
544 if( !vals )
545 YYABORT;
546 vals->val = $1;
547 vals->next = $3;
548 $$ = vals;
552 update_assign_list:
553 column_assignment
554 | column_assignment TK_COMMA update_assign_list
556 $1.col_list->next = $3.col_list;
557 $1.val_list->next = $3.val_list;
558 $$ = $1;
562 column_assignment:
563 column TK_EQ const_val
565 $$.col_list = HeapAlloc( GetProcessHeap(), 0, sizeof *$$.col_list );
566 if( !$$.col_list )
567 YYABORT;
568 $$.col_list->string = $1;
569 $$.col_list->next = NULL;
570 $$.val_list = HeapAlloc( GetProcessHeap(), 0, sizeof *$$.val_list );
571 if( !$$.val_list )
572 YYABORT;
573 $$.val_list->val = $3;
574 $$.val_list->next = 0;
578 const_val:
579 TK_INTEGER
581 $$ = EXPR_ival( info, &$1, 1 );
582 if( !$$ )
583 YYABORT;
585 | TK_MINUS TK_INTEGER
587 $$ = EXPR_ival( info, &$2, -1 );
588 if( !$$ )
589 YYABORT;
591 | TK_STRING
593 $$ = EXPR_sval( info, &$1 );
594 if( !$$ )
595 YYABORT;
597 | TK_WILDCARD
599 $$ = EXPR_wildcard( info );
600 if( !$$ )
601 YYABORT;
605 column_val:
606 column
608 $$ = EXPR_column( info, $1 );
609 if( !$$ )
610 YYABORT;
614 column:
615 table TK_DOT id
617 $$ = $3; /* FIXME */
619 | id
621 $$ = $1;
625 table:
628 $$ = $1;
633 TK_ID
635 $$ = SQL_getstring( info, &$1 );
636 if( !$$ )
637 YYABORT;
643 static void *parser_alloc( void *info, unsigned int sz )
645 SQL_input* sql = (SQL_input*) info;
646 struct list *mem;
648 mem = HeapAlloc( GetProcessHeap(), 0, sizeof (struct list) + sz );
649 list_add_tail( sql->mem, mem );
650 return &mem[1];
653 int SQL_lex( void *SQL_lval, SQL_input *sql )
655 int token;
656 struct sql_str * str = SQL_lval;
660 sql->n += sql->len;
661 if( ! sql->command[sql->n] )
662 return 0; /* end of input */
664 TRACE("string : %s\n", debugstr_w(&sql->command[sql->n]));
665 sql->len = sqliteGetToken( &sql->command[sql->n], &token );
666 if( sql->len==0 )
667 break;
668 str->data = &sql->command[sql->n];
669 str->len = sql->len;
671 while( token == TK_SPACE );
673 TRACE("token : %d (%s)\n", token, debugstr_wn(&sql->command[sql->n], sql->len));
675 return token;
678 LPWSTR SQL_getstring( void *info, struct sql_str *strdata )
680 LPCWSTR p = strdata->data;
681 UINT len = strdata->len;
682 LPWSTR str;
684 /* if there's quotes, remove them */
685 if( ( (p[0]=='`') && (p[len-1]=='`') ) ||
686 ( (p[0]=='\'') && (p[len-1]=='\'') ) )
688 p++;
689 len -= 2;
691 str = parser_alloc( info, (len + 1)*sizeof(WCHAR) );
692 if( !str )
693 return str;
694 memcpy( str, p, len*sizeof(WCHAR) );
695 str[len]=0;
697 return str;
700 INT SQL_getint( void *info )
702 SQL_input* sql = (SQL_input*) info;
703 LPCWSTR p = &sql->command[sql->n];
705 return atoiW( p );
708 int SQL_error( const char *str )
710 return 0;
713 static struct expr * EXPR_wildcard( void *info )
715 struct expr *e = parser_alloc( info, sizeof *e );
716 if( e )
718 e->type = EXPR_WILDCARD;
720 return e;
723 static struct expr * EXPR_complex( void *info, struct expr *l, UINT op, struct expr *r )
725 struct expr *e = parser_alloc( info, sizeof *e );
726 if( e )
728 e->type = EXPR_COMPLEX;
729 e->u.expr.left = l;
730 e->u.expr.op = op;
731 e->u.expr.right = r;
733 return e;
736 static struct expr * EXPR_column( void *info, LPWSTR column )
738 struct expr *e = parser_alloc( info, sizeof *e );
739 if( e )
741 e->type = EXPR_COLUMN;
742 e->u.sval = column;
744 return e;
747 static struct expr * EXPR_ival( void *info, struct sql_str *str, int sign )
749 struct expr *e = parser_alloc( info, sizeof *e );
750 if( e )
752 e->type = EXPR_IVAL;
753 e->u.ival = atoiW( str->data ) * sign;
755 return e;
758 static struct expr * EXPR_sval( void *info, struct sql_str *str )
760 struct expr *e = parser_alloc( info, sizeof *e );
761 if( e )
763 e->type = EXPR_SVAL;
764 e->u.sval = SQL_getstring( info, str );
766 return e;
769 static BOOL SQL_MarkPrimaryKeys( create_col_info *cols, string_list *keys)
771 string_list *k;
772 BOOL found = TRUE;
774 for( k = keys; k && found; k = k->next )
776 create_col_info *c;
778 found = FALSE;
779 for( c = cols; c && !found; c = c->next )
781 if( lstrcmpW( k->string, c->colname ) )
782 continue;
783 c->type |= MSITYPE_KEY;
784 found = TRUE;
788 return found;
791 UINT MSI_ParseSQL( MSIDATABASE *db, LPCWSTR command, MSIVIEW **phview,
792 struct list *mem )
794 SQL_input sql;
795 int r;
797 *phview = NULL;
799 sql.db = db;
800 sql.command = command;
801 sql.n = 0;
802 sql.len = 0;
803 sql.view = phview;
804 sql.mem = mem;
806 r = SQL_parse(&sql);
808 TRACE("Parse returned %d\n", r);
809 if( r )
811 if( *sql.view )
812 (*sql.view)->ops->delete( *sql.view );
813 *sql.view = NULL;
814 return ERROR_BAD_QUERY_SYNTAX;
817 return ERROR_SUCCESS;