4 * Implementation of the Microsoft Installer (msi.dll)
6 * Copyright 2002 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
33 #include "wine/debug.h"
34 #include "wine/unicode.h"
36 #define YYLEX_PARAM info
37 #define YYPARSE_PARAM info
39 extern
int yyerror(char *str
);
41 WINE_DEFAULT_DEBUG_CHANNEL
(msi
);
43 typedef
struct tag_yyinput
48 MSIVIEW
**view
; /* view structure for the resulting query */
54 struct string_list
*next
;
57 static LPWSTR yygetstring
( yyinput
*info
);
58 static INT yygetint
( yyinput
*sql
);
59 static int yylex( void *yylval, yyinput
*info
);
61 static MSIVIEW
*do_one_select
( MSIDATABASE
*db
, MSIVIEW
*in
,
62 struct string_list
*columns
);
63 static MSIVIEW
*do_order_by
( MSIDATABASE
*db
, MSIVIEW
*in
,
64 struct string_list
*columns
);
66 static struct expr
* EXPR_complex
( struct expr
*l
, UINT op
, struct expr
*r
);
67 static struct expr
* EXPR_column
( LPWSTR column
);
68 static struct expr
* EXPR_ival
( INT ival
);
69 static struct expr
* EXPR_sval
( LPWSTR
string );
78 struct string_list
*column_list
;
83 %token TK_ABORT TK_AFTER TK_AGG_FUNCTION TK_ALL TK_AND TK_AS TK_ASC
84 %token TK_BEFORE TK_BEGIN TK_BETWEEN TK_BITAND TK_BITNOT TK_BITOR TK_BY
85 %token TK_CASCADE TK_CASE TK_CHECK TK_CLUSTER TK_COLLATE TK_COLUMN TK_COMMA
86 %token TK_COMMENT TK_COMMIT TK_CONCAT TK_CONFLICT
87 %token TK_CONSTRAINT TK_COPY TK_CREATE
88 %token TK_DEFAULT TK_DEFERRABLE TK_DEFERRED TK_DELETE TK_DELIMITERS TK_DESC
89 %token TK_DISTINCT TK_DOT TK_DROP TK_EACH
90 %token TK_ELSE TK_END TK_END_OF_FILE TK_EQ TK_EXCEPT TK_EXPLAIN
91 %token TK_FAIL TK_FLOAT TK_FOR TK_FOREIGN TK_FROM TK_FUNCTION
92 %token TK_GE TK_GLOB TK_GROUP TK_GT
94 %token TK_IGNORE TK_ILLEGAL TK_IMMEDIATE TK_IN TK_INDEX TK_INITIALLY
96 %token TK_INSERT TK_INSTEAD TK_INTEGER TK_INTERSECT TK_INTO TK_IS TK_ISNULL
97 %token TK_JOIN TK_JOIN_KW
99 %token TK_LE TK_LIKE TK_LIMIT TK_LP TK_LSHIFT TK_LT
100 %token TK_MATCH TK_MINUS
101 %token TK_NE TK_NOT TK_NOTNULL TK_NULL
102 %token TK_OF TK_OFFSET TK_ON TK_OR TK_ORACLE_OUTER_JOIN TK_ORDER
103 %token TK_PLUS TK_PRAGMA TK_PRIMARY
104 %token TK_RAISE TK_REFERENCES TK_REM TK_REPLACE TK_RESTRICT TK_ROLLBACK
105 %token TK_ROW TK_RP TK_RSHIFT
106 %token TK_SELECT TK_SEMI TK_SET TK_SLASH TK_SPACE TK_STAR TK_STATEMENT
107 %token
<string> TK_STRING
108 %token TK_TABLE TK_TEMP TK_THEN TK_TRANSACTION TK_TRIGGER
109 %token TK_UMINUS TK_UNCLOSED_STRING TK_UNION TK_UNIQUE
110 %token TK_UPDATE TK_UPLUS TK_USING
111 %token TK_VACUUM TK_VALUES TK_VIEW
112 %token TK_WHEN TK_WHERE
115 * These are extra tokens used by the lexer but never seen by the
116 * parser. We put them in a rule so that the parser generator will
117 * add them to the parse.h output file.
120 %nonassoc END_OF_FILE ILLEGAL SPACE UNCLOSED_STRING COMMENT FUNCTION
123 %type
<query
> oneselect
124 %type
<string> column table string_or_id
125 %type
<column_list
> selcollist
126 %type
<table
> from unorderedsel
127 %type
<expr
> expr val column_val
132 unorderedsel TK_ORDER TK_BY selcollist
134 yyinput
* sql
= (yyinput
*) info
;
139 *sql
->view
= do_order_by
( sql
->db
, $1, $4 );
145 yyinput
* sql
= (yyinput
*) info
;
152 TK_SELECT selcollist from
154 yyinput
* sql
= (yyinput
*) info
;
158 $$
= do_one_select
( sql
->db
, $3, $2 );
162 | TK_SELECT TK_DISTINCT selcollist from
164 yyinput
* sql
= (yyinput
*) info
;
170 view
= do_one_select
( sql
->db
, view
, $3 );
171 DISTINCT_CreateView
( sql
->db
, & $$
, view
);
178 struct string_list
*list
;
180 list
= HeapAlloc
( GetProcessHeap
(), 0, sizeof
*list
);
187 TRACE
("Collist %s\n",debugstr_w
($$
->string));
189 | column TK_COMMA selcollist
191 struct string_list
*list
;
193 list
= HeapAlloc
( GetProcessHeap
(), 0, sizeof
*list
);
200 TRACE
("From table: %s\n",debugstr_w
($$
->string));
211 yyinput
* sql
= (yyinput
*) info
;
214 TRACE
("From table: %s\n",debugstr_w
($2));
215 TABLE_CreateView
( sql
->db
, $2, & $$
);
217 | TK_FROM table TK_WHERE expr
219 yyinput
* sql
= (yyinput
*) info
;
220 MSIVIEW
*view
= NULL
;
224 TRACE
("From table: %s\n",debugstr_w
($2));
225 r
= TABLE_CreateView
( sql
->db
, $2, &view
);
226 if
( r
!= ERROR_SUCCESS
)
228 r
= WHERE_CreateView
( sql
->db
, &view
, view
);
229 if
( r
!= ERROR_SUCCESS
)
231 r
= WHERE_AddCondition
( view
, $4 );
232 if
( r
!= ERROR_SUCCESS
)
243 | column_val TK_EQ column_val
245 $$
= EXPR_complex
( $1, OP_EQ
, $3 );
249 $$
= EXPR_complex
( $1, OP_AND
, $3 );
253 $$
= EXPR_complex
( $1, OP_OR
, $3 );
255 | column_val TK_EQ val
257 $$
= EXPR_complex
( $1, OP_EQ
, $3 );
259 | column_val TK_GT val
261 $$
= EXPR_complex
( $1, OP_GT
, $3 );
263 | column_val TK_LT val
265 $$
= EXPR_complex
( $1, OP_LT
, $3 );
267 | column_val TK_LE val
269 $$
= EXPR_complex
( $1, OP_LE
, $3 );
271 | column_val TK_GE val
273 $$
= EXPR_complex
( $1, OP_GE
, $3 );
275 | column_val TK_NE val
277 $$
= EXPR_complex
( $1, OP_NE
, $3 );
279 | column_val TK_IS TK_NULL
281 $$
= EXPR_complex
( $1, OP_ISNULL
, NULL
);
283 | column_val TK_IS TK_NOT TK_NULL
285 $$
= EXPR_complex
( $1, OP_NOTNULL
, NULL
);
296 yyinput
* sql
= (yyinput
*) info
;
297 $$
= EXPR_ival
( yygetint
(sql
) );
301 $$
= EXPR_sval
( $1 );
308 $$
= EXPR_column
( $1 );
313 table TK_DOT string_or_id
333 yyinput
* sql
= (yyinput
*) info
;
334 $$
= yygetstring
(sql
);
338 yyinput
* sql
= (yyinput
*) info
;
339 $$
= yygetstring
(sql
);
345 int yylex( void *yylval, yyinput
*sql
)
352 if
( ! sql
->command
[sql
->n
] )
353 return
0; /* end of input */
355 TRACE
("string : %s\n", debugstr_w
(&sql
->command
[sql
->n
]));
356 sql
->len
= sqliteGetToken
( &sql
->command
[sql
->n
], &token
);
360 while
( token
== TK_SPACE
);
362 TRACE
("token : %d (%s)\n", token
, debugstr_wn
(&sql
->command
[sql
->n
], sql
->len
));
367 LPWSTR yygetstring
( yyinput
*sql
)
369 LPCWSTR p
= &sql
->command
[sql
->n
];
373 /* if there's quotes, remove them */
374 if
( (p
[0]=='`') && (p
[len
-1]=='`') )
379 str
= HeapAlloc
( GetProcessHeap
(), 0, (len
+ 1)*sizeof
(WCHAR
));
382 memcpy
(str
, p
, len
*sizeof
(WCHAR
) );
388 INT yygetint
( yyinput
*sql
)
390 LPCWSTR p
= &sql
->command
[sql
->n
];
395 int yyerror(char *str
)
400 static MSIVIEW
*do_one_select
( MSIDATABASE
*db
, MSIVIEW
*in
,
401 struct string_list
*columns
)
403 MSIVIEW
*view
= NULL
;
405 SELECT_CreateView
( db
, &view
, in
);
408 struct string_list
*x
= columns
;
412 struct string_list
*t
= x
->next
;
413 SELECT_AddColumn
( view
, x
->string );
414 HeapFree
( GetProcessHeap
(), 0, x
->string );
415 HeapFree
( GetProcessHeap
(), 0, x
);
420 ERR
("Error creating select query\n");
424 static MSIVIEW
*do_order_by
( MSIDATABASE
*db
, MSIVIEW
*in
,
425 struct string_list
*columns
)
427 MSIVIEW
*view
= NULL
;
429 ORDER_CreateView
( db
, &view
, in
);
432 struct string_list
*x
= columns
;
436 struct string_list
*t
= x
->next
;
437 ORDER_AddColumn
( view
, x
->string );
438 HeapFree
( GetProcessHeap
(), 0, x
->string );
439 HeapFree
( GetProcessHeap
(), 0, x
);
444 ERR
("Error creating select query\n");
448 static struct expr
* EXPR_complex
( struct expr
*l
, UINT op
, struct expr
*r
)
450 struct expr
*e
= HeapAlloc
( GetProcessHeap
(), 0, sizeof
*e
);
453 e
->type
= EXPR_COMPLEX
;
461 static struct expr
* EXPR_column
( LPWSTR column
)
463 struct expr
*e
= HeapAlloc
( GetProcessHeap
(), 0, sizeof
*e
);
466 e
->type
= EXPR_COLUMN
;
467 e
->u.column
= column
;
472 static struct expr
* EXPR_ival
( INT ival
)
474 struct expr
*e
= HeapAlloc
( GetProcessHeap
(), 0, sizeof
*e
);
483 static struct expr
* EXPR_sval
( LPWSTR
string )
485 struct expr
*e
= HeapAlloc
( GetProcessHeap
(), 0, sizeof
*e
);
494 UINT MSI_ParseSQL
( MSIDATABASE
*db
, LPCWSTR command
, MSIVIEW
**phview
)
502 sql.command
= command
;
509 TRACE
("Parse returned %d\n", r
);
513 (*sql.view
)->ops
->delete
( *sql.view
);
514 return ERROR_BAD_QUERY_SYNTAX
;
517 return ERROR_SUCCESS
;