1 %{
2 #if USE_WINDOWS
3 #pragma warning(push,1)
4 #pragma warning(disable:4702) // unreachable code
5 #endif
6 %}
7 
8 %lex-param	{ SqlParser_c * pParser }
9 %parse-param	{ SqlParser_c * pParser }
10 %pure-parser
11 %error-verbose
12 
13 %token	TOK_IDENT
14 %token	TOK_ATIDENT
15 %token	TOK_CONST_INT
16 %token	TOK_CONST_FLOAT
17 %token	TOK_CONST_MVA
18 %token	TOK_QUOTED_STRING
19 %token	TOK_USERVAR
20 %token	TOK_SYSVAR
21 %token	TOK_CONST_STRINGS
22 %token	TOK_BAD_NUMERIC
23 
24 %token	TOK_AS
25 %token	TOK_ASC
26 %token	TOK_ATTACH
27 %token	TOK_AVG
28 %token	TOK_BEGIN
29 %token	TOK_BETWEEN
30 %token	TOK_BIGINT
31 %token	TOK_BY
32 %token	TOK_CALL
33 %token	TOK_COLLATION
34 %token	TOK_COMMIT
35 %token	TOK_COMMITTED
36 %token	TOK_COUNT
37 %token	TOK_CREATE
38 %token	TOK_DELETE
39 %token	TOK_DESC
40 %token	TOK_DESCRIBE
41 %token	TOK_DISTINCT
42 %token	TOK_DIV
43 %token	TOK_DROP
44 %token	TOK_FALSE
45 %token	TOK_FLOAT
46 %token	TOK_FLUSH
47 %token	TOK_FROM
48 %token	TOK_FUNCTION
49 %token	TOK_GLOBAL
50 %token	TOK_GROUP
51 %token	TOK_ID
52 %token	TOK_IN
53 %token	TOK_INDEX
54 %token	TOK_INSERT
55 %token	TOK_INT
56 %token	TOK_INTO
57 %token	TOK_ISOLATION
58 %token	TOK_LEVEL
59 %token	TOK_LIMIT
60 %token	TOK_MATCH
61 %token	TOK_MAX
62 %token	TOK_META
63 %token	TOK_MIN
64 %token	TOK_MOD
65 %token	TOK_NAMES
66 %token	TOK_NULL
67 %token	TOK_OPTION
68 %token	TOK_ORDER
69 %token	TOK_RAND
70 %token	TOK_READ
71 %token	TOK_REPEATABLE
72 %token	TOK_REPLACE
73 %token	TOK_RETURNS
74 %token	TOK_ROLLBACK
75 %token	TOK_RTINDEX
76 %token	TOK_SELECT
77 %token	TOK_SERIALIZABLE
78 %token	TOK_SET
79 %token	TOK_SESSION
80 %token	TOK_SHOW
81 %token	TOK_SONAME
82 %token	TOK_START
83 %token	TOK_STATUS
84 %token	TOK_SUM
85 %token	TOK_TABLES
86 %token	TOK_TO
87 %token	TOK_TRANSACTION
88 %token	TOK_TRUE
89 %token	TOK_UNCOMMITTED
90 %token	TOK_UPDATE
91 %token	TOK_VALUES
92 %token	TOK_VARIABLES
93 %token	TOK_WARNINGS
94 %token	TOK_WEIGHT
95 %token	TOK_WHERE
96 %token	TOK_WITHIN
97 
98 %type	<m_iValue>		named_const_list
99 %type	<m_iValue>		udf_type
100 
101 %left TOK_OR
102 %left TOK_AND
103 %left '|'
104 %left '&'
105 %left '=' TOK_NE
106 %left '<' '>' TOK_LTE TOK_GTE
107 %left '+' '-'
108 %left '*' '/' '%' TOK_DIV TOK_MOD
109 %nonassoc TOK_NOT
110 %nonassoc TOK_NEG
111 
112 %{
113 // some helpers
114 #include <float.h> // for FLT_MAX
115 
116 %}
117 
118 %%
119 
120 request:
121    statement							{ pParser->PushQuery(); }
122    | multi_stmt_list
123    | multi_stmt_list ';'
124    ;
125 
126 statement:
127 	insert_into
128 	| delete_from
129 	| set_stmt
130 	| set_global_stmt
131 	| transact_op
132 	| call_proc
133 	| describe
134 	| show_tables
135 	| update
136 	| show_variables
137 	| show_collation
138 	| create_function
139 	| drop_function
140 	| attach_index
141 	| flush_rtindex
142 	| set_transaction
143 	| select_sysvar
144 	;
145 
146 //////////////////////////////////////////////////////////////////////////
147 
148 multi_stmt_list:
149 	multi_stmt							{ pParser->PushQuery(); }
150 	| multi_stmt_list ';' multi_stmt	{ pParser->PushQuery(); }
151 	;
152 
153 multi_stmt:
154 	select_from
155 	| show_stmt
156 	;
157 
158 select_from:
159 	TOK_SELECT select_items_list
160 	TOK_FROM ident_list
161 	opt_where_clause
162 	opt_group_clause
163 	opt_group_order_clause
164 	opt_order_clause
165 	opt_limit_clause
166 	opt_option_clause
167 		{
168 			pParser->m_pStmt->m_eStmt = STMT_SELECT;
169 			pParser->m_pQuery->m_sIndexes.SetBinary ( pParser->m_pBuf+$4.m_iStart, $4.m_iEnd-$4.m_iStart );
170 		}
171 	;
172 
173 select_items_list:
174 	select_item
175 	| select_items_list ',' select_item
176 	;
177 
178 select_item:
179 	'*'						{ pParser->AddItem ( &$1 ); }
180 	| select_expr opt_alias
181 	;
182 
183 opt_alias:
184 	// empty
185 	| TOK_IDENT					{ pParser->AliasLastItem ( &$1 ); }
186 	| TOK_AS TOK_IDENT				{ pParser->AliasLastItem ( &$2 ); }
187 	;
188 
189 select_expr:
190 	expr						{ pParser->AddItem ( &$1 ); }
191 	| TOK_AVG '(' expr ')'				{ pParser->AddItem ( &$3, SPH_AGGR_AVG, &$1, &$4 ); }
192 	| TOK_MAX '(' expr ')'				{ pParser->AddItem ( &$3, SPH_AGGR_MAX, &$1, &$4 ); }
193 	| TOK_MIN '(' expr ')'				{ pParser->AddItem ( &$3, SPH_AGGR_MIN, &$1, &$4 ); }
194 	| TOK_SUM '(' expr ')'				{ pParser->AddItem ( &$3, SPH_AGGR_SUM, &$1, &$4 ); }
195 	| TOK_COUNT '(' '*' ')'				{ if ( !pParser->AddItem ( "count(*)", &$1, &$4 ) ) YYERROR; }
196 	| TOK_WEIGHT '(' ')'				{ if ( !pParser->AddItem ( "weight()", &$1, &$3 ) ) YYERROR; }
197 	| TOK_COUNT '(' TOK_DISTINCT TOK_IDENT ')' 	{ if ( !pParser->AddDistinct ( &$4, &$1, &$5 ) ) YYERROR; }
198 	;
199 
200 ident_list:
201 	TOK_IDENT
202 	| ident_list ',' TOK_IDENT			{ $$ = $1; $$.m_iEnd = $3.m_iEnd; }
203 	;
204 
205 opt_where_clause:
206 	// empty
207 	| where_clause
208 	;
209 
210 where_clause:
211 	TOK_WHERE where_expr
212 	;
213 
214 where_expr:
215 	where_item
216 	| where_expr TOK_AND where_expr
217 	| '(' where_expr ')'
218 	;
219 
220 expr_float_unhandled:
221 	expr_ident '=' const_float
222 	| expr_ident TOK_NE const_float
223 	| expr_ident '>' const_float
224 	| expr_ident '<' const_float
225 	;
226 
227 where_item:
228 	TOK_MATCH '(' TOK_QUOTED_STRING ')'
229 		{
230 			if ( !pParser->SetMatch($3) )
231 				YYERROR;
232 		}
233 	| expr_ident '=' const_int
234 		{
235 			CSphFilterSettings * pFilter = pParser->AddValuesFilter ( $1 );
236 			if ( !pFilter )
237 				YYERROR;
238 			pFilter->m_dValues.Add ( $3.m_iValue );
239 		}
240 	| expr_ident TOK_NE const_int
241 		{
242 			CSphFilterSettings * pFilter = pParser->AddValuesFilter ( $1 );
243 			if ( !pFilter )
244 				YYERROR;
245 			pFilter->m_dValues.Add ( $3.m_iValue );
246 			pFilter->m_bExclude = true;
247 		}
248 	| expr_ident TOK_IN '(' const_list ')'
249 		{
250 			CSphFilterSettings * pFilter = pParser->AddValuesFilter ( $1 );
251 			if ( !pFilter )
252 				YYERROR;
253 			pFilter->m_dValues = *$4.m_pValues.Ptr();
254 			pFilter->m_dValues.Uniq();
255 		}
256 	| expr_ident TOK_NOT TOK_IN '(' const_list ')'
257 		{
258 			CSphFilterSettings * pFilter = pParser->AddValuesFilter ( $1 );
259 			if ( !pFilter )
260 				YYERROR;
261 			pFilter->m_dValues = *$5.m_pValues.Ptr();
262 			pFilter->m_bExclude = true;
263 			pFilter->m_dValues.Uniq();
264 		}
265 	| expr_ident TOK_IN TOK_USERVAR
266 		{
267 			if ( !pParser->AddUservarFilter ( $1.m_sValue, $3.m_sValue, false ) )
268 				YYERROR;
269 		}
270 	| expr_ident TOK_NOT TOK_IN TOK_USERVAR
271 		{
272 			if ( !pParser->AddUservarFilter ( $1.m_sValue, $4.m_sValue, true ) )
273 				YYERROR;
274 		}
275 	| expr_ident TOK_BETWEEN const_int TOK_AND const_int
276 		{
277 			if ( !pParser->AddIntRangeFilter ( $1.m_sValue, $3.m_iValue, $5.m_iValue ) )
278 				YYERROR;
279 		}
280 	| expr_ident '>' const_int
281 		{
282 			if ( !pParser->AddIntFilterGTE ( $1.m_sValue, $3.m_iValue+1 ) )
283 				YYERROR;
284 		}
285 	| expr_ident '<' const_int
286 		{
287 			if ( !pParser->AddIntFilterLTE ( $1.m_sValue, $3.m_iValue-1 ) )
288 				YYERROR;
289 		}
290 	| expr_ident TOK_GTE const_int
291 		{
292 			if ( !pParser->AddIntFilterGTE ( $1.m_sValue, $3.m_iValue ) )
293 				YYERROR;
294 		}
295 	| expr_ident TOK_LTE const_int
296 		{
297 			if ( !pParser->AddIntFilterLTE ( $1.m_sValue, $3.m_iValue ) )
298 				YYERROR;
299 		}
300 	| expr_float_unhandled
301 		{
302 			yyerror ( pParser, "only >=, <=, and BETWEEN floating-point filter types are supported in this version" );
303 			YYERROR;
304 		}
305 	| expr_ident TOK_BETWEEN const_float TOK_AND const_float
306 		{
307 			if ( !pParser->AddFloatRangeFilter ( $1.m_sValue, $3.m_fValue, $5.m_fValue ) )
308 				YYERROR;
309 		}
310 	| expr_ident TOK_BETWEEN const_int TOK_AND const_float
311 		{
312 			if ( !pParser->AddFloatRangeFilter ( $1.m_sValue, $3.m_iValue, $5.m_fValue ) )
313 				YYERROR;
314 		}
315 	| expr_ident TOK_BETWEEN const_float TOK_AND const_int
316 		{
317 			if ( !pParser->AddFloatRangeFilter ( $1.m_sValue, $3.m_fValue, $5.m_iValue ) )
318 				YYERROR;
319 		}
320 	| expr_ident TOK_GTE const_float
321 		{
322 			if ( !pParser->AddFloatRangeFilter ( $1.m_sValue, $3.m_fValue, FLT_MAX ) )
323 				YYERROR;
324 		}
325 	| expr_ident TOK_LTE const_float
326 		{
327 			if ( !pParser->AddFloatRangeFilter ( $1.m_sValue, -FLT_MAX, $3.m_fValue ) )
328 				YYERROR;
329 		}
330 	;
331 
332 expr_ident:
333 	TOK_IDENT
334 	| TOK_ATIDENT
335 		{
336 			if ( !pParser->SetOldSyntax() )
337 				YYERROR;
338 		}
339 	| TOK_COUNT '(' '*' ')'
340 		{
341 			$$.m_sValue = "@count";
342 			if ( !pParser->SetNewSyntax() )
343 				YYERROR;
344 		}
345 	| TOK_WEIGHT '(' ')'
346 		{
347 			$$.m_sValue = "@weight";
348 			if ( !pParser->SetNewSyntax() )
349 				YYERROR;
350 		}
351 	| TOK_ID
352 		{
353 			$$.m_sValue = "@id";
354 			if ( !pParser->SetNewSyntax() )
355 				YYERROR;
356 		}
357 	;
358 
359 const_int:
360 	TOK_CONST_INT			{ $$.m_iInstype = TOK_CONST_INT; $$.m_iValue = $1.m_iValue; }
361 	| '-' TOK_CONST_INT
362 		{
363 			$$.m_iInstype = TOK_CONST_INT;
364 			if ( (uint64_t)$2.m_iValue > (uint64_t)LLONG_MAX )
365 				$$.m_iValue = LLONG_MIN;
366 			else
367 				$$.m_iValue = -$2.m_iValue;
368 		}
369 	;
370 
371 const_float:
372 	TOK_CONST_FLOAT			{ $$.m_iInstype = TOK_CONST_FLOAT; $$.m_fValue = $1.m_fValue; }
373 	| '-' TOK_CONST_FLOAT	{ $$.m_iInstype = TOK_CONST_FLOAT; $$.m_fValue = -$2.m_fValue; }
374 	;
375 
376 const_list:
377 	const_int
378 		{
379 			assert ( !$$.m_pValues.Ptr() );
380 			$$.m_pValues = new RefcountedVector_c<SphAttr_t> ();
381 			$$.m_pValues->Add ( $1.m_iValue );
382 		}
383 	| const_list ',' const_int
384 		{
385 			$$.m_pValues->Add ( $3.m_iValue );
386 		}
387 	;
388 
389 opt_group_clause:
390 	// empty
391 	| group_clause
392 	;
393 
394 group_clause:
395 	TOK_GROUP TOK_BY expr_ident
396 		{
397 			pParser->SetGroupBy ( $3.m_sValue );
398 		}
399 	;
400 
401 opt_group_order_clause:
402 	// empty
403 	| group_order_clause
404 	;
405 
406 group_order_clause:
407 	TOK_WITHIN TOK_GROUP TOK_ORDER TOK_BY order_items_list
408 		{
409 			pParser->m_pQuery->m_sSortBy.SetBinary ( pParser->m_pBuf+$5.m_iStart, $5.m_iEnd-$5.m_iStart );
410 		}
411 	;
412 
413 opt_order_clause:
414 	// empty
415 	| order_clause
416 	;
417 
418 order_clause:
419 	TOK_ORDER TOK_BY order_items_list
420 		{
421 			pParser->m_pQuery->m_sOrderBy.SetBinary ( pParser->m_pBuf+$3.m_iStart, $3.m_iEnd-$3.m_iStart );
422 		}
423 	| TOK_ORDER TOK_BY TOK_RAND '(' ')'
424 		{
425 			pParser->m_pQuery->m_sOrderBy = "@random";
426 		}
427 	;
428 
429 order_items_list:
430 	order_item
431 	| order_items_list ',' order_item	{ $$ = $1; $$.m_iEnd = $3.m_iEnd; }
432 	;
433 
434 order_item:
435 	expr_ident
436 	| expr_ident TOK_ASC				{ $$ = $1; $$.m_iEnd = $2.m_iEnd; }
437 	| expr_ident TOK_DESC				{ $$ = $1; $$.m_iEnd = $2.m_iEnd; }
438 	;
439 
440 opt_limit_clause:
441 	// empty
442 	| limit_clause
443 	;
444 
445 limit_clause:
446 	TOK_LIMIT TOK_CONST_INT
447 		{
448 			pParser->m_pQuery->m_iOffset = 0;
449 			pParser->m_pQuery->m_iLimit = $2.m_iValue;
450 		}
451 	| TOK_LIMIT TOK_CONST_INT ',' TOK_CONST_INT
452 		{
453 			pParser->m_pQuery->m_iOffset = $2.m_iValue;
454 			pParser->m_pQuery->m_iLimit = $4.m_iValue;
455 		}
456 	;
457 
458 opt_option_clause:
459 	// empty
460 	| option_clause
461 	;
462 
463 option_clause:
464 	TOK_OPTION option_list
465 	;
466 
467 option_list:
468 	option_item
469 	| option_list ',' option_item
470 	;
471 
472 option_item:
473 	TOK_IDENT '=' TOK_IDENT
474 		{
475 			if ( !pParser->AddOption ( $1, $3 ) )
476 				YYERROR;
477 		}
478 	| TOK_IDENT '=' TOK_CONST_INT
479 		{
480 			if ( !pParser->AddOption ( $1, $3 ) )
481 				YYERROR;
482 		}
483 	| TOK_IDENT '=' '(' named_const_list ')'
484 		{
485 			if ( !pParser->AddOption ( $1, pParser->GetNamedVec ( $4 ) ) )
486 				YYERROR;
487 			pParser->FreeNamedVec ( $4 );
488 		}
489 	| TOK_IDENT '=' TOK_IDENT '(' TOK_QUOTED_STRING ')'
490 		{
491 			if ( !pParser->AddOption ( $1, $4, $5.m_sValue ) )
492 				YYERROR;
493 		}
494 	| TOK_IDENT '=' TOK_QUOTED_STRING
495 		{
496 			if ( !pParser->AddOption ( $1, $3 ) )
497 				YYERROR;
498 		}
499 	;
500 
501 named_const_list:
502 	named_const
503 		{
504 			$$ = pParser->AllocNamedVec ();
505 			pParser->AddConst ( $$, $1 );
506 		}
507 	| named_const_list ',' named_const
508 		{
509 			pParser->AddConst( $$, $3 );
510 		}
511 	;
512 
513 named_const:
514 	TOK_IDENT '=' const_int
515 		{
516 			$$.m_sValue = $1.m_sValue;
517 			$$.m_iValue = $3.m_iValue;
518 		}
519 	;
520 
521 //////////////////////////////////////////////////////////////////////////
522 
523 expr:
524 	TOK_IDENT
525 	| TOK_ATIDENT	{ if ( !pParser->SetOldSyntax() ) YYERROR; }
526 	| TOK_ID	{ if ( !pParser->SetNewSyntax() ) YYERROR; }
527 	| TOK_CONST_INT
528 	| TOK_CONST_FLOAT
529 	| TOK_USERVAR
530 	| '-' expr %prec TOK_NEG	{ $$ = $1; $$.m_iEnd = $2.m_iEnd; }
531 	| TOK_NOT expr				{ $$ = $1; $$.m_iEnd = $2.m_iEnd; }
532 	| expr '+' expr				{ $$ = $1; $$.m_iEnd = $3.m_iEnd; }
533 	| expr '-' expr				{ $$ = $1; $$.m_iEnd = $3.m_iEnd; }
534 	| expr '*' expr				{ $$ = $1; $$.m_iEnd = $3.m_iEnd; }
535 	| expr '/' expr				{ $$ = $1; $$.m_iEnd = $3.m_iEnd; }
536 	| expr '<' expr				{ $$ = $1; $$.m_iEnd = $3.m_iEnd; }
537 	| expr '>' expr				{ $$ = $1; $$.m_iEnd = $3.m_iEnd; }
538 	| expr '&' expr				{ $$ = $1; $$.m_iEnd = $3.m_iEnd; }
539 	| expr '|' expr				{ $$ = $1; $$.m_iEnd = $3.m_iEnd; }
540 	| expr '%' expr				{ $$ = $1; $$.m_iEnd = $3.m_iEnd; }
541 	| expr TOK_DIV expr			{ $$ = $1; $$.m_iEnd = $3.m_iEnd; }
542 	| expr TOK_MOD expr			{ $$ = $1; $$.m_iEnd = $3.m_iEnd; }
543 	| expr TOK_LTE expr			{ $$ = $1; $$.m_iEnd = $3.m_iEnd; }
544 	| expr TOK_GTE expr			{ $$ = $1; $$.m_iEnd = $3.m_iEnd; }
545 	| expr '=' expr				{ $$ = $1; $$.m_iEnd = $3.m_iEnd; }
546 	| expr TOK_NE expr			{ $$ = $1; $$.m_iEnd = $3.m_iEnd; }
547 	| expr TOK_AND expr			{ $$ = $1; $$.m_iEnd = $3.m_iEnd; }
548 	| expr TOK_OR expr			{ $$ = $1; $$.m_iEnd = $3.m_iEnd; }
549 	| '(' expr ')'				{ $$ = $1; $$.m_iEnd = $3.m_iEnd; }
550 	| function
551 	;
552 
553 function:
554 	TOK_IDENT '(' arglist ')'	{ $$ = $1; $$.m_iEnd = $4.m_iEnd; }
555 	| TOK_IN '(' arglist ')'	{ $$ = $1; $$.m_iEnd = $4.m_iEnd; }			// handle exception from 'ident' rule
556 	| TOK_BIGINT '(' arglist ')'	{ $$ = $1; $$.m_iEnd = $4.m_iEnd; }
557 	| TOK_IDENT '(' ')'			{ $$ = $1; $$.m_iEnd = $3.m_iEnd }
558 	| TOK_MIN '(' expr ',' expr ')'		{ $$ = $1; $$.m_iEnd = $6.m_iEnd }	// handle clash with aggregate functions
559 	| TOK_MAX '(' expr ',' expr ')'		{ $$ = $1; $$.m_iEnd = $6.m_iEnd }
560 	;
561 
562 arglist:
563 	arg
564 	| arglist ',' arg
565 	;
566 
567 arg:
568 	expr
569 	| TOK_QUOTED_STRING
570 	;
571 
572 //////////////////////////////////////////////////////////////////////////
573 
574 show_stmt:
575 	TOK_SHOW show_what
576 	;
577 
578 show_what:
579 	TOK_WARNINGS		{ pParser->m_pStmt->m_eStmt = STMT_SHOW_WARNINGS; }
580 	| TOK_STATUS		{ pParser->m_pStmt->m_eStmt = STMT_SHOW_STATUS; }
581 	| TOK_META			{ pParser->m_pStmt->m_eStmt = STMT_SHOW_META; }
582 	;
583 
584 //////////////////////////////////////////////////////////////////////////
585 
586 simple_set_value:
587 	TOK_IDENT
588 	| TOK_NULL
589 	| TOK_QUOTED_STRING
590 	| TOK_CONST_INT
591 	| TOK_CONST_FLOAT
592 	;
593 
594 set_value:
595 	simple_set_value
596 	| set_value '-' simple_set_value
597 	;
598 
599 set_stmt:
600 	TOK_SET TOK_IDENT '=' boolean_value
601 		{
602 			pParser->SetStatement ( $2, SET_LOCAL );
603 			pParser->m_pStmt->m_iSetValue = $4.m_iValue;
604 		}
605 	| TOK_SET TOK_IDENT '=' set_string_value
606 		{
607 			pParser->SetStatement ( $2, SET_LOCAL );
608 			pParser->m_pStmt->m_sSetValue = $4.m_sValue;
609 		}
610 	| TOK_SET TOK_IDENT '=' TOK_NULL
611 		{
612 			pParser->SetStatement ( $2, SET_LOCAL );
613 			pParser->m_pStmt->m_bSetNull = true;
614 		}
615 	| TOK_SET TOK_NAMES set_value		{ pParser->m_pStmt->m_eStmt = STMT_DUMMY; }
616 	| TOK_SET TOK_SYSVAR '=' set_value	{ pParser->m_pStmt->m_eStmt = STMT_DUMMY; }
617 	;
618 
619 set_global_stmt:
620 	TOK_SET TOK_GLOBAL TOK_USERVAR '=' '(' const_list ')'
621 		{
622 			pParser->SetStatement ( $3, SET_GLOBAL_UVAR );
623 			pParser->m_pStmt->m_dSetValues = *$6.m_pValues.Ptr();
624 		}
625 	| TOK_SET TOK_GLOBAL TOK_IDENT '=' set_string_value
626 		{
627 			pParser->SetStatement ( $3, SET_GLOBAL_SVAR );
628 			pParser->m_pStmt->m_sSetValue = $5.m_sValue;
629 		}
630 	;
631 
632 set_string_value:
633 	TOK_IDENT
634 	| TOK_QUOTED_STRING
635 	;
636 
637 boolean_value:
638 	TOK_TRUE			{ $$.m_iValue = 1; }
639 	| TOK_FALSE			{ $$.m_iValue = 0; }
640 	| const_int
641 		{
642 			$$.m_iValue = $1.m_iValue;
643 			if ( $$.m_iValue!=0 && $$.m_iValue!=1 )
644 			{
645 				yyerror ( pParser, "only 0 and 1 could be used as boolean values" );
646 				YYERROR;
647 			}
648 		}
649 	;
650 
651 //////////////////////////////////////////////////////////////////////////
652 
653 transact_op:
654 	TOK_COMMIT			{ pParser->m_pStmt->m_eStmt = STMT_COMMIT; }
655 	| TOK_ROLLBACK			{ pParser->m_pStmt->m_eStmt = STMT_ROLLBACK; }
656 	| start_transaction		{ pParser->m_pStmt->m_eStmt = STMT_BEGIN; }
657 	;
658 
659 start_transaction:
660 	TOK_BEGIN
661 	| TOK_START TOK_TRANSACTION
662 	;
663 
664 //////////////////////////////////////////////////////////////////////////
665 
666 insert_into:
667 	insert_or_replace TOK_INTO TOK_IDENT opt_column_list TOK_VALUES insert_rows_list
668 		{
669 			// everything else is pushed directly into parser within the rules
670 			pParser->m_pStmt->m_sIndex = $3.m_sValue;
671 		}
672 	;
673 
674 insert_or_replace:
675 	TOK_INSERT		{ pParser->m_pStmt->m_eStmt = STMT_INSERT; }
676 	| TOK_REPLACE	{ pParser->m_pStmt->m_eStmt = STMT_REPLACE; }
677 	;
678 
679 opt_column_list:
680 	// empty
681 	| '(' column_list ')'
682 	;
683 
684 column_list:
685 	expr_ident							{ if ( !pParser->AddSchemaItem ( &$1 ) ) { yyerror ( pParser, "unknown field" ); YYERROR; } }
686 	| column_list ',' expr_ident		{ if ( !pParser->AddSchemaItem ( &$3 ) ) { yyerror ( pParser, "unknown field" ); YYERROR; } }
687 	;
688 
689 insert_rows_list:
690 	insert_row
691 	| insert_rows_list ',' insert_row
692 	;
693 
694 insert_row:
695 	'(' insert_vals_list ')'			{ if ( !pParser->m_pStmt->CheckInsertIntegrity() ) { yyerror ( pParser, "wrong number of values here" ); YYERROR; } }
696 	;
697 
698 insert_vals_list:
699 	insert_val							{ AddInsval ( pParser->m_pStmt->m_dInsertValues, $1 ); }
700 	| insert_vals_list ',' insert_val	{ AddInsval ( pParser->m_pStmt->m_dInsertValues, $3 ); }
701 	;
702 
703 insert_val:
704 	const_int				{ $$.m_iInstype = TOK_CONST_INT; $$.m_iValue = $1.m_iValue; }
705 	| const_float			{ $$.m_iInstype = TOK_CONST_FLOAT; $$.m_fValue = $1.m_fValue; }
706 	| TOK_QUOTED_STRING		{ $$.m_iInstype = TOK_QUOTED_STRING; $$.m_sValue = $1.m_sValue; }
707 	| '(' const_list ')'	{ $$.m_iInstype = TOK_CONST_MVA; $$.m_pValues = $2.m_pValues; }
708 	| '(' ')'				{ $$.m_iInstype = TOK_CONST_MVA; }
709 	;
710 
711 //////////////////////////////////////////////////////////////////////////
712 
713 delete_from:
714 	TOK_DELETE TOK_FROM TOK_IDENT TOK_WHERE TOK_ID '=' const_int
715 		{
716 			pParser->m_pStmt->m_eStmt = STMT_DELETE;
717 			pParser->m_pStmt->m_sIndex = $3.m_sValue;
718 			pParser->m_pStmt->m_dDeleteIds.Add ( $7.m_iValue );
719 		}
720 	| TOK_DELETE TOK_FROM TOK_IDENT TOK_WHERE TOK_ID TOK_IN '(' const_list ')'
721 		{
722 			pParser->m_pStmt->m_eStmt = STMT_DELETE;
723 			pParser->m_pStmt->m_sIndex = $3.m_sValue;
724 			for ( int i=0; i<$8.m_pValues.Ptr()->GetLength(); i++ )
725 				pParser->m_pStmt->m_dDeleteIds.Add ( (*$8.m_pValues.Ptr())[i] );
726 		}
727 	;
728 
729 //////////////////////////////////////////////////////////////////////////
730 
731 call_proc:
732 	TOK_CALL TOK_IDENT '(' call_args_list opt_call_opts_list ')'
733 		{
734 			pParser->m_pStmt->m_eStmt = STMT_CALL;
735 			pParser->m_pStmt->m_sCallProc = $2.m_sValue;
736 		}
737 	;
738 
739 call_args_list:
740 	call_arg
741 		{
742 			AddInsval ( pParser->m_pStmt->m_dInsertValues, $1 );
743 		}
744 	| call_args_list ',' call_arg
745 		{
746 			AddInsval ( pParser->m_pStmt->m_dInsertValues, $3 );
747 		}
748 	;
749 
750 call_arg:
751 	insert_val
752 	| '(' const_string_list ')'
753 		{
754 			$$.m_iInstype = TOK_CONST_STRINGS;
755 		}
756 	;
757 
758 const_string_list:
759 	TOK_QUOTED_STRING
760 		{
761 			// FIXME? for now, one such array per CALL statement, tops
762 			if ( pParser->m_pStmt->m_dCallStrings.GetLength() )
763 			{
764 				yyerror ( pParser, "unexpected constant string list" );
765 				YYERROR;
766 			}
767 			pParser->m_pStmt->m_dCallStrings.Add ( $1.m_sValue );
768 		}
769 	| const_string_list ',' TOK_QUOTED_STRING
770 		{
771 			pParser->m_pStmt->m_dCallStrings.Add ( $3.m_sValue );
772 		}
773 	;
774 
775 opt_call_opts_list:
776 	// empty
777 	| ',' call_opts_list
778 	;
779 
780 call_opts_list:
781 	call_opt
782 		{
783 			assert ( pParser->m_pStmt->m_dCallOptNames.GetLength()==1 );
784 			assert ( pParser->m_pStmt->m_dCallOptValues.GetLength()==1 );
785 		}
786 	| call_opts_list ',' call_opt
787 	;
788 
789 call_opt:
790 	insert_val opt_as call_opt_name
791 		{
792 			pParser->m_pStmt->m_dCallOptNames.Add ( $3.m_sValue );
793 			AddInsval ( pParser->m_pStmt->m_dCallOptValues, $1 );
794 		}
795 	;
796 
797 opt_as:
798 	// empty
799 	| TOK_AS
800 	;
801 
802 call_opt_name:
803 	TOK_IDENT
804 	| TOK_LIMIT		{ $$.m_sValue = "limit"; }
805 	;
806 
807 //////////////////////////////////////////////////////////////////////////
808 
809 describe:
810 	describe_tok TOK_IDENT
811 		{
812 			pParser->m_pStmt->m_eStmt = STMT_DESC;
813 			pParser->m_pStmt->m_sIndex = $2.m_sValue;
814 		}
815 	;
816 
817 describe_tok:
818 	TOK_DESCRIBE
819 	| TOK_DESC
820 	;
821 
822 //////////////////////////////////////////////////////////////////////////
823 
824 show_tables:
825 	TOK_SHOW TOK_TABLES		{ pParser->m_pStmt->m_eStmt = STMT_SHOW_TABLES; }
826 	;
827 
828 //////////////////////////////////////////////////////////////////////////
829 
830 update:
831 	TOK_UPDATE ident_list TOK_SET update_items_list where_clause
832 		{
833 			if ( !pParser->UpdateStatement ( &$2 ) )
834 				YYERROR;
835 		}
836 	;
837 
838 update_items_list:
839 	update_item
840 	| update_items_list ',' update_item
841 	;
842 
843 update_item:
844 	TOK_IDENT '=' const_int
845 		{
846 			pParser->UpdateAttr ( $1.m_sValue, &$3 );
847 		}
848 	| TOK_IDENT '=' const_float
849 		{
850 			pParser->UpdateAttr ( $1.m_sValue, &$3, SPH_ATTR_FLOAT);
851 		}
852 	| TOK_IDENT '='  '(' const_list ')'
853 		{
854 			pParser->UpdateMVAAttr ( $1.m_sValue, $4 );
855 		}
856 	| TOK_IDENT '='  '(' ')' // special case () means delete mva
857 		{
858 			SqlNode_t tNoValues;
859 			pParser->UpdateMVAAttr ( $1.m_sValue, tNoValues );
860 		}
861 	;
862 
863 //////////////////////////////////////////////////////////////////////////
864 
865 show_variables:
866 	TOK_SHOW opt_scope TOK_VARIABLES opt_show_variables_where
867 		{
868 			pParser->m_pStmt->m_eStmt = STMT_SHOW_VARIABLES;
869 		}
870 	;
871 
872 opt_show_variables_where:
873 	| show_variables_where
874 	;
875 
876 show_variables_where:
877 	TOK_WHERE show_variables_where_list
878 	;
879 
880 show_variables_where_list:
881 	show_variables_where_entry
882 	| show_variables_where_list TOK_OR show_variables_where_entry
883 	;
884 
885 show_variables_where_entry:
886 	TOK_IDENT '=' TOK_QUOTED_STRING // for example, Variable_name = 'character_set'
887 	;
888 
889 show_collation:
890 	TOK_SHOW TOK_COLLATION
891 		{
892 			pParser->m_pStmt->m_eStmt = STMT_DUMMY;
893 		}
894 	;
895 
896 set_transaction:
897 	TOK_SET opt_scope TOK_TRANSACTION TOK_ISOLATION TOK_LEVEL isolation_level
898 		{
899 			pParser->m_pStmt->m_eStmt = STMT_DUMMY;
900 		}
901 	;
902 
903 opt_scope:
904 	| TOK_GLOBAL
905 	| TOK_SESSION
906 	;
907 
908 isolation_level:
909 	TOK_READ TOK_UNCOMMITTED
910 	| TOK_READ TOK_COMMITTED
911 	| TOK_REPEATABLE TOK_READ
912 	| TOK_SERIALIZABLE
913 	;
914 
915 //////////////////////////////////////////////////////////////////////////
916 
917 create_function:
918 	TOK_CREATE TOK_FUNCTION TOK_IDENT TOK_RETURNS udf_type TOK_SONAME TOK_QUOTED_STRING
919 		{
920 			SqlStmt_t & tStmt = *pParser->m_pStmt;
921 			tStmt.m_eStmt = STMT_CREATE_FUNC;
922 			tStmt.m_sUdfName = $3.m_sValue;
923 			tStmt.m_sUdfLib = $7.m_sValue;
924 			tStmt.m_eUdfType = (ESphAttr) $5;
925 		}
926 	;
927 
928 udf_type:
929 	TOK_INT			{ $$ = SPH_ATTR_INTEGER; }
930 	| TOK_BIGINT	{ $$ = SPH_ATTR_BIGINT; }
931 	| TOK_FLOAT		{ $$ = SPH_ATTR_FLOAT; }
932 	;
933 
934 drop_function:
935 	TOK_DROP TOK_FUNCTION TOK_IDENT
936 		{
937 			SqlStmt_t & tStmt = *pParser->m_pStmt;
938 			tStmt.m_eStmt = STMT_DROP_FUNC;
939 			tStmt.m_sUdfName = $3.m_sValue;
940 		}
941 	;
942 
943 ////////////////////////////////////////////////////////////
944 
945 attach_index:
946 	TOK_ATTACH TOK_INDEX TOK_IDENT TOK_TO TOK_RTINDEX TOK_IDENT
947 		{
948 			SqlStmt_t & tStmt = *pParser->m_pStmt;
949 			tStmt.m_eStmt = STMT_ATTACH_INDEX;
950 			tStmt.m_sIndex = $3.m_sValue;
951 			tStmt.m_sSetName = $6.m_sValue;
952 		}
953 	;
954 
955 //////////////////////////////////////////////////////////////////////////
956 
957 flush_rtindex:
958 	TOK_FLUSH TOK_RTINDEX TOK_IDENT
959 		{
960 			SqlStmt_t & tStmt = *pParser->m_pStmt;
961 			tStmt.m_eStmt = STMT_FLUSH_RTINDEX;
962 			tStmt.m_sIndex = $3.m_sValue;
963 		}
964 	;
965 
966 //////////////////////////////////////////////////////////////////////////
967 
968 select_sysvar:
969 	TOK_SELECT TOK_SYSVAR opt_limit_clause
970 		{
971 			pParser->m_pStmt->m_eStmt = STMT_DUMMY;
972 		}
973 	;
974 
975 %%
976 
977 #if USE_WINDOWS
978 #pragma warning(pop)
979 #endif
980