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 %token TOK_SUBKEY
24 %token TOK_DOT_NUMBER
25
26 %token TOK_ADD
27 %token TOK_AGENT
28 %token TOK_ALTER
29 %token TOK_AS
30 %token TOK_ASC
31 %token TOK_ATTACH
32 %token TOK_ATTRIBUTES
33 %token TOK_AVG
34 %token TOK_BEGIN
35 %token TOK_BETWEEN
36 %token TOK_BIGINT
37 %token TOK_BOOL
38 %token TOK_BY
39 %token TOK_CALL
40 %token TOK_CHARACTER
41 %token TOK_CHUNK
42 %token TOK_COLLATION
43 %token TOK_COLUMN
44 %token TOK_COMMIT
45 %token TOK_COMMITTED
46 %token TOK_COUNT
47 %token TOK_CREATE
48 %token TOK_DATABASES
49 %token TOK_DELETE
50 %token TOK_DESC
51 %token TOK_DESCRIBE
52 %token TOK_DISTINCT
53 %token TOK_DIV
54 %token TOK_DOUBLE
55 %token TOK_DROP
56 %token TOK_FACET
57 %token TOK_FALSE
58 %token TOK_FLOAT
59 %token TOK_FLUSH
60 %token TOK_FOR
61 %token TOK_FROM
62 %token TOK_FUNCTION
63 %token TOK_GLOBAL
64 %token TOK_GROUP
65 %token TOK_GROUPBY
66 %token TOK_GROUP_CONCAT
67 %token TOK_HAVING
68 %token TOK_ID
69 %token TOK_IN
70 %token TOK_INDEX
71 %token TOK_INSERT
72 %token TOK_INT
73 %token TOK_INTEGER
74 %token TOK_INTO
75 %token TOK_IS
76 %token TOK_ISOLATION
77 %token TOK_JSON
78 %token TOK_LEVEL
79 %token TOK_LIKE
80 %token TOK_LIMIT
81 %token TOK_MATCH
82 %token TOK_MAX
83 %token TOK_META
84 %token TOK_MIN
85 %token TOK_MOD
86 %token TOK_MULTI
87 %token TOK_MULTI64
88 %token TOK_NAMES
89 %token TOK_NULL
90 %token TOK_OPTION
91 %token TOK_ORDER
92 %token TOK_OPTIMIZE
93 %token TOK_PLAN
94 %token TOK_PLUGIN
95 %token TOK_PLUGINS
96 %token TOK_PROFILE
97 %token TOK_RAND
98 %token TOK_RAMCHUNK
99 %token TOK_READ
100 %token TOK_RECONFIGURE
101 %token TOK_REPEATABLE
102 %token TOK_REPLACE
103 %token TOK_REMAP
104 %token TOK_RETURNS
105 %token TOK_ROLLBACK
106 %token TOK_RTINDEX
107 %token TOK_SELECT
108 %token TOK_SERIALIZABLE
109 %token TOK_SET
110 %token TOK_SETTINGS
111 %token TOK_SESSION
112 %token TOK_SHOW
113 %token TOK_SONAME
114 %token TOK_START
115 %token TOK_STATUS
116 %token TOK_STRING
117 %token TOK_SUM
118 %token TOK_TABLE
119 %token TOK_TABLES
120 %token TOK_THREADS
121 %token TOK_TO
122 %token TOK_TRANSACTION
123 %token TOK_TRUE
124 %token TOK_TRUNCATE
125 %token TOK_TYPE
126 %token TOK_UNCOMMITTED
127 %token TOK_UPDATE
128 %token TOK_VALUES
129 %token TOK_VARIABLES
130 %token TOK_WARNINGS
131 %token TOK_WEIGHT
132 %token TOK_WHERE
133 %token TOK_WITHIN
134
135 %left TOK_OR
136 %left TOK_AND
137 %left '|'
138 %left '&'
139 %left '=' TOK_NE
140 %left '<' '>' TOK_LTE TOK_GTE
141 %left '+' '-'
142 %left '*' '/' '%' TOK_DIV TOK_MOD
143 %nonassoc TOK_NOT
144 %nonassoc TOK_NEG
145
146 %{
147
148 // some helpers
149 #include <float.h> // for FLT_MAX
150
AddInsval(SqlParser_c * pParser,CSphVector<SqlInsert_t> & dVec,const SqlNode_t & tNode)151 static void AddInsval ( SqlParser_c * pParser, CSphVector<SqlInsert_t> & dVec, const SqlNode_t & tNode )
152 {
153 SqlInsert_t & tIns = dVec.Add();
154 tIns.m_iType = tNode.m_iType;
155 tIns.m_iVal = tNode.m_iValue; // OPTIMIZE? copy conditionally based on type?
156 tIns.m_fVal = tNode.m_fValue;
157 if ( tIns.m_iType==TOK_QUOTED_STRING )
158 pParser->ToStringUnescape ( tIns.m_sVal, tNode );
159 tIns.m_pVals = tNode.m_pValues;
160 }
161
162 #define TRACK_BOUNDS(_res,_left,_right) \
163 _res = _left; \
164 if ( _res.m_iStart>0 && pParser->m_pBuf[_res.m_iStart-1]=='`' ) \
165 _res.m_iStart--; \
166 _res.m_iEnd = _right.m_iEnd; \
167 _res.m_iType = 0;
168
169 %}
170
171 %%
172
173 request:
174 statement { pParser->PushQuery(); }
175 | multi_stmt_list
176 | multi_stmt_list ';'
177 ;
178
179 statement:
180 insert_into
181 | delete_from
182 | set_global_stmt
183 | transact_op
184 | call_proc
185 | describe
186 | show_tables
187 | show_databases
188 | update
189 | show_variables
190 | show_collation
191 | show_character_set
192 | create_function
193 | drop_function
194 | attach_index
195 | flush_rtindex
196 | flush_ramchunk
197 | flush_index
198 | set_transaction
199 | select_sysvar
200 | select_dual
201 | truncate
202 | optimize_index
203 | alter
204 | create_plugin
205 | drop_plugin
206 ;
207
208 //////////////////////////////////////////////////////////////////////////
209
210 // many known keywords are also allowed as column or index names
211 //
212 // FROM conflicts with select_expr opt_alias
213 // NAMES, TRANSACTION conflicts with SET
214 //
215 // more known conflicts (but rather crappy ideas for a name anyway) are:
216 // AND, AS, BY, DIV, FACET, FALSE, ID, IN, IS, LIMIT, MOD, NOT, NULL,
217 // OR, ORDER, SELECT, TRUE
218
219 ident_set:
220 TOK_IDENT
221 | TOK_ADD | TOK_AGENT | TOK_ALTER | TOK_ASC | TOK_ATTACH | TOK_ATTRIBUTES
222 | TOK_AVG | TOK_BEGIN | TOK_BETWEEN | TOK_BIGINT | TOK_BOOL| TOK_CALL
223 | TOK_CHARACTER | TOK_CHUNK | TOK_COLLATION | TOK_COLUMN | TOK_COMMIT
224 | TOK_COMMITTED | TOK_COUNT | TOK_CREATE | TOK_DATABASES | TOK_DELETE
225 | TOK_DESC | TOK_DESCRIBE | TOK_DISTINCT | TOK_DOUBLE | TOK_DROP
226 | TOK_FLOAT | TOK_FLUSH | TOK_FOR| TOK_FUNCTION | TOK_GLOBAL | TOK_GROUP
227 | TOK_GROUP_CONCAT | TOK_GROUPBY | TOK_HAVING | TOK_INDEX | TOK_INSERT
228 | TOK_INT | TOK_INTEGER | TOK_INTO | TOK_ISOLATION | TOK_JSON | TOK_LEVEL
229 | TOK_LIKE | TOK_MATCH | TOK_MAX | TOK_META | TOK_MIN | TOK_MULTI
230 | TOK_MULTI64 | TOK_OPTIMIZE | TOK_OPTION | TOK_PLAN | TOK_PLUGIN
231 | TOK_PLUGINS | TOK_PROFILE | TOK_RAMCHUNK | TOK_RAND | TOK_READ
232 | TOK_RECONFIGURE | TOK_REMAP | TOK_REPEATABLE | TOK_REPLACE | TOK_RETURNS
233 | TOK_ROLLBACK | TOK_RTINDEX | TOK_SERIALIZABLE | TOK_SESSION | TOK_SET
234 | TOK_SETTINGS | TOK_SHOW | TOK_SONAME | TOK_START | TOK_STATUS | TOK_STRING
235 | TOK_SUM | TOK_TABLE | TOK_TABLES | TOK_THREADS | TOK_TO | TOK_TRUNCATE
236 | TOK_TYPE | TOK_UNCOMMITTED | TOK_UPDATE | TOK_VALUES | TOK_VARIABLES
237 | TOK_WARNINGS | TOK_WEIGHT | TOK_WHERE | TOK_WITHIN
238 ;
239
240 ident:
241 ident_set | TOK_NAMES | TOK_TRANSACTION
242 ;
243
244 //////////////////////////////////////////////////////////////////////////
245
246 multi_stmt_list:
247 multi_stmt { pParser->PushQuery(); }
248 | multi_stmt_list ';' multi_stmt { pParser->PushQuery(); }
249 | multi_stmt_list facet_stmt { pParser->PushQuery(); }
250 ;
251
252 multi_stmt:
253 select
254 | show_stmt
255 | set_stmt
256 ;
257
258 select:
259 select1
260 | TOK_SELECT TOK_IDENT '(' '(' select1 ')' opt_tablefunc_args ')'
261 {
262 assert ( pParser->m_pStmt->m_eStmt==STMT_SELECT ); // set by table argument
263 pParser->ToString ( pParser->m_pStmt->m_sTableFunc, $2 );
264 }
265 ;
266
267 select1:
268 select_from
269 | TOK_SELECT select_items_list TOK_FROM '(' subselect_start select_from ')'
270 opt_outer_order opt_outer_limit
271 {
272 assert ( pParser->m_pStmt->m_eStmt==STMT_SELECT ); // set by subselect
273 }
274 ;
275
276 opt_tablefunc_args:
277 // nothing
278 | ',' tablefunc_args_list
279 ;
280
281 tablefunc_args_list:
282 tablefunc_arg
283 {
284 pParser->ToString ( pParser->m_pStmt->m_dTableFuncArgs.Add(), $1 );
285 }
286 | tablefunc_args_list ',' tablefunc_arg
287 {
288 pParser->ToString ( pParser->m_pStmt->m_dTableFuncArgs.Add(), $3 );
289 }
290 ;
291
292 tablefunc_arg:
293 ident
294 | TOK_CONST_INT
295 | TOK_ID
296 ;
297
298 subselect_start:
299 {
300 CSphVector<CSphQueryItem> & dItems = pParser->m_pQuery->m_dItems;
301 if ( dItems.GetLength()!=1 || dItems[0].m_sExpr!="*" )
302 {
303 yyerror ( pParser, "outer select list must be a single star" );
304 YYERROR;
305 }
306 dItems.Reset();
307 pParser->ResetSelect();
308 };
309
310
311 opt_outer_order:
312 TOK_ORDER TOK_BY order_items_list
313 {
314 pParser->ToString ( pParser->m_pQuery->m_sOuterOrderBy, $3 );
315 pParser->m_pQuery->m_bHasOuter = true;
316 }
317 ;
318
319 opt_outer_limit:
320 // nothing
321 | TOK_LIMIT TOK_CONST_INT
322 {
323 pParser->m_pQuery->m_iOuterLimit = $2.m_iValue;
324 pParser->m_pQuery->m_bHasOuter = true;
325 }
326 | TOK_LIMIT TOK_CONST_INT ',' TOK_CONST_INT
327 {
328 pParser->m_pQuery->m_iOuterOffset = $2.m_iValue;
329 pParser->m_pQuery->m_iOuterLimit = $4.m_iValue;
330 pParser->m_pQuery->m_bHasOuter = true;
331 }
332 ;
333
334 select_from:
335 TOK_SELECT select_items_list
336 TOK_FROM ident_list
337 opt_where_clause
338 opt_group_clause
339 opt_group_order_clause
340 opt_having_clause
341 opt_order_clause
342 opt_limit_clause
343 opt_option_clause
344 {
345 pParser->m_pStmt->m_eStmt = STMT_SELECT;
346 pParser->ToString ( pParser->m_pQuery->m_sIndexes, $4 );
347 }
348 ;
349
350 select_items_list:
351 select_item
352 | select_items_list ',' select_item
353 ;
354
355 select_item:
356 '*' { pParser->AddItem ( &$1 ); }
357 | select_expr opt_alias
358 ;
359
360 opt_alias:
361 // empty
362 | ident { pParser->AliasLastItem ( &$1 ); }
363 | TOK_AS ident { pParser->AliasLastItem ( &$2 ); }
364 ;
365
366 select_expr:
367 expr { pParser->AddItem ( &$1 ); }
368 | TOK_AVG '(' expr ')' { pParser->AddItem ( &$3, SPH_AGGR_AVG, &$1, &$4 ); }
369 | TOK_MAX '(' expr ')' { pParser->AddItem ( &$3, SPH_AGGR_MAX, &$1, &$4 ); }
370 | TOK_MIN '(' expr ')' { pParser->AddItem ( &$3, SPH_AGGR_MIN, &$1, &$4 ); }
371 | TOK_SUM '(' expr ')' { pParser->AddItem ( &$3, SPH_AGGR_SUM, &$1, &$4 ); }
372 | TOK_GROUP_CONCAT '(' expr ')' { pParser->AddItem ( &$3, SPH_AGGR_CAT, &$1, &$4 ); }
373 | TOK_COUNT '(' '*' ')' { if ( !pParser->AddItem ( "count(*)", &$1, &$4 ) ) YYERROR; }
374 | TOK_GROUPBY '(' ')' { if ( !pParser->AddItem ( "groupby()", &$1, &$3 ) ) YYERROR; }
375 | TOK_COUNT '(' TOK_DISTINCT ident')' { if ( !pParser->AddDistinct ( &$4, &$1, &$5 ) ) YYERROR; }
376 ;
377
378 ident_list:
379 ident
380 | ident_list ',' ident { TRACK_BOUNDS ( $$, $1, $3 ); }
381 ;
382
383 opt_where_clause:
384 // empty
385 | where_clause
386 ;
387
388 where_clause:
389 TOK_WHERE where_expr
390 ;
391
392 where_expr:
393 where_item
394 | where_expr TOK_AND where_expr
395 | '(' where_expr ')'
396 ;
397
398 where_item:
399 TOK_MATCH '(' TOK_QUOTED_STRING ')'
400 {
401 if ( !pParser->SetMatch($3) )
402 YYERROR;
403 }
404 | filter_item
405 ;
406
407 filter_item:
408 expr_ident '=' const_int
409 {
410 CSphFilterSettings * pFilter = pParser->AddValuesFilter ( $1 );
411 if ( !pFilter )
412 YYERROR;
413 pFilter->m_dValues.Add ( $3.m_iValue );
414 }
415 | expr_ident TOK_NE const_int
416 {
417 CSphFilterSettings * pFilter = pParser->AddValuesFilter ( $1 );
418 if ( !pFilter )
419 YYERROR;
420 pFilter->m_dValues.Add ( $3.m_iValue );
421 pFilter->m_bExclude = true;
422 }
423 | expr_ident TOK_IN '(' const_list ')'
424 {
425 CSphFilterSettings * pFilter = pParser->AddValuesFilter ( $1 );
426 if ( !pFilter )
427 YYERROR;
428 pFilter->m_dValues = *$4.m_pValues.Ptr();
429 pFilter->m_dValues.Uniq();
430 }
431 | expr_ident TOK_NOT TOK_IN '(' const_list ')'
432 {
433 CSphFilterSettings * pFilter = pParser->AddValuesFilter ( $1 );
434 if ( !pFilter )
435 YYERROR;
436 pFilter->m_dValues = *$5.m_pValues.Ptr();
437 pFilter->m_dValues.Uniq();
438 pFilter->m_bExclude = true;
439 }
440 | expr_ident TOK_IN '(' string_list ')'
441 {
442 if ( !pParser->AddStringListFilter ( $1, $4, false ) )
443 YYERROR;
444 }
445 | expr_ident TOK_NOT TOK_IN '(' string_list ')'
446 {
447 if ( !pParser->AddStringListFilter ( $1, $5, true ) )
448 YYERROR;
449 }
450 | expr_ident TOK_IN TOK_USERVAR
451 {
452 if ( !pParser->AddUservarFilter ( $1, $3, false ) )
453 YYERROR;
454 }
455 | expr_ident TOK_NOT TOK_IN TOK_USERVAR
456 {
457 if ( !pParser->AddUservarFilter ( $1, $4, true ) )
458 YYERROR;
459 }
460 | expr_ident TOK_BETWEEN const_int TOK_AND const_int
461 {
462 if ( !pParser->AddIntRangeFilter ( $1, $3.m_iValue, $5.m_iValue ) )
463 YYERROR;
464 }
465 | expr_ident '>' const_int
466 {
467 if ( !pParser->AddIntFilterGreater ( $1, $3.m_iValue, false ) )
468 YYERROR;
469 }
470 | expr_ident '<' const_int
471 {
472 if ( !pParser->AddIntFilterLesser ( $1, $3.m_iValue, false ) )
473 YYERROR;
474 }
475 | expr_ident TOK_GTE const_int
476 {
477 if ( !pParser->AddIntFilterGreater ( $1, $3.m_iValue, true ) )
478 YYERROR;
479 }
480 | expr_ident TOK_LTE const_int
481 {
482 if ( !pParser->AddIntFilterLesser ( $1, $3.m_iValue, true ) )
483 YYERROR;
484 }
485 | expr_ident '=' const_float
486 {
487 if ( !pParser->AddFloatRangeFilter ( $1, $3.m_fValue, $3.m_fValue, true ) )
488 YYERROR;
489 }
490 | expr_ident TOK_NE const_float
491 {
492 if ( !pParser->AddFloatRangeFilter ( $1, $3.m_fValue, $3.m_fValue, true, true ) )
493 YYERROR;
494 }
495 | expr_ident TOK_BETWEEN const_float TOK_AND const_float
496 {
497 if ( !pParser->AddFloatRangeFilter ( $1, $3.m_fValue, $5.m_fValue, true ) )
498 YYERROR;
499 }
500 | expr_ident TOK_BETWEEN const_int TOK_AND const_float
501 {
502 if ( !pParser->AddFloatRangeFilter ( $1, $3.m_iValue, $5.m_fValue, true ) )
503 YYERROR;
504 }
505 | expr_ident TOK_BETWEEN const_float TOK_AND const_int
506 {
507 if ( !pParser->AddFloatRangeFilter ( $1, $3.m_fValue, $5.m_iValue, true ) )
508 YYERROR;
509 }
510 | expr_ident '>' const_float
511 {
512 if ( !pParser->AddFloatRangeFilter ( $1, $3.m_fValue, FLT_MAX, false ) )
513 YYERROR;
514 }
515 | expr_ident '<' const_float
516 {
517 if ( !pParser->AddFloatRangeFilter ( $1, -FLT_MAX, $3.m_fValue, false ) )
518 YYERROR;
519 }
520 | expr_ident TOK_GTE const_float
521 {
522 if ( !pParser->AddFloatRangeFilter ( $1, $3.m_fValue, FLT_MAX, true ) )
523 YYERROR;
524 }
525 | expr_ident TOK_LTE const_float
526 {
527 if ( !pParser->AddFloatRangeFilter ( $1, -FLT_MAX, $3.m_fValue, true ) )
528 YYERROR;
529 }
530 | expr_ident '=' TOK_QUOTED_STRING
531 {
532 if ( !pParser->AddStringFilter ( $1, $3, false ) )
533 YYERROR;
534 }
535 | expr_ident TOK_NE TOK_QUOTED_STRING
536 {
537 if ( !pParser->AddStringFilter ( $1, $3, true ) )
538 YYERROR;
539 }
540 | expr_ident TOK_IS TOK_NULL
541 {
542 if ( !pParser->AddNullFilter ( $1, true ) )
543 YYERROR;
544 }
545 | expr_ident TOK_IS TOK_NOT TOK_NULL
546 {
547 if ( !pParser->AddNullFilter ( $1, false ) )
548 YYERROR;
549 }
550 ;
551
552 expr_ident:
553 ident
554 | TOK_ATIDENT
555 {
556 if ( !pParser->SetOldSyntax() )
557 YYERROR;
558 }
559 | TOK_COUNT '(' '*' ')'
560 {
561 $$.m_iType = SPHINXQL_TOK_COUNT;
562 if ( !pParser->SetNewSyntax() )
563 YYERROR;
564 }
565 | TOK_GROUPBY '(' ')'
566 {
567 $$.m_iType = SPHINXQL_TOK_GROUPBY;
568 if ( !pParser->SetNewSyntax() )
569 YYERROR;
570 }
571 | TOK_WEIGHT '(' ')'
572 {
573 $$.m_iType = SPHINXQL_TOK_WEIGHT;
574 if ( !pParser->SetNewSyntax() )
575 YYERROR;
576 }
577 | TOK_ID
578 {
579 $$.m_iType = SPHINXQL_TOK_ID;
580 if ( !pParser->SetNewSyntax() )
581 YYERROR;
582 }
583 | json_expr
584 | TOK_INTEGER '(' json_expr ')'
585 | TOK_DOUBLE '(' json_expr ')'
586 | TOK_BIGINT '(' json_expr ')'
587 | TOK_FACET '(' ')'
588 ;
589
590 const_int:
591 TOK_CONST_INT { $$.m_iType = TOK_CONST_INT; $$.m_iValue = $1.m_iValue; }
592 | '-' TOK_CONST_INT
593 {
594 $$.m_iType = TOK_CONST_INT;
595 if ( (uint64_t)$2.m_iValue > (uint64_t)LLONG_MAX )
596 $$.m_iValue = LLONG_MIN;
597 else
598 $$.m_iValue = -$2.m_iValue;
599 }
600 ;
601
602 const_float:
603 TOK_CONST_FLOAT { $$.m_iType = TOK_CONST_FLOAT; $$.m_fValue = $1.m_fValue; }
604 | '-' TOK_CONST_FLOAT { $$.m_iType = TOK_CONST_FLOAT; $$.m_fValue = -$2.m_fValue; }
605 | TOK_DOT_NUMBER { $$.m_iType = TOK_CONST_FLOAT; $$.m_fValue = $1.m_fValue; }
606 ;
607
608 const_list:
609 const_int
610 {
611 assert ( !$$.m_pValues.Ptr() );
612 $$.m_pValues = new RefcountedVector_c<SphAttr_t> ();
613 $$.m_pValues->Add ( $1.m_iValue );
614 }
615 | const_list ',' const_int
616 {
617 $$.m_pValues->Add ( $3.m_iValue );
618 }
619 ;
620
621 string_list:
622 TOK_QUOTED_STRING
623 {
624 assert ( !$$.m_pValues.Ptr() );
625 $$.m_pValues = new RefcountedVector_c<SphAttr_t> ();
626 $$.m_pValues->Add ( $1.m_iValue );
627 }
628 | string_list ',' TOK_QUOTED_STRING
629 {
630 $$.m_pValues->Add ( $3.m_iValue );
631 }
632 ;
633
634 opt_group_clause:
635 // empty
636 | TOK_GROUP opt_int TOK_BY group_items_list
637 ;
638
639 opt_int:
640 // empty
641 | TOK_CONST_INT
642 {
643 pParser->SetGroupbyLimit ( $1.m_iValue );
644 }
645 ;
646
647 group_items_list:
648 expr_ident
649 {
650 pParser->AddGroupBy ( $1 );
651 }
652 | group_items_list ',' expr_ident
653 {
654 pParser->AddGroupBy ( $3 );
655 }
656 ;
657
658 opt_having_clause:
659 // empty
660 | TOK_HAVING filter_item
661 {
662 pParser->AddHaving();
663 }
664 ;
665
666 opt_group_order_clause:
667 // empty
668 | group_order_clause
669 ;
670
671 group_order_clause:
672 TOK_WITHIN TOK_GROUP TOK_ORDER TOK_BY order_items_list
673 {
674 if ( pParser->m_pQuery->m_sGroupBy.IsEmpty() )
675 {
676 yyerror ( pParser, "you must specify GROUP BY element in order to use WITHIN GROUP ORDER BY clause" );
677 YYERROR;
678 }
679 pParser->ToString ( pParser->m_pQuery->m_sSortBy, $5 );
680 }
681 ;
682
683 opt_order_clause:
684 // empty
685 | order_clause
686 ;
687
688 order_clause:
689 TOK_ORDER TOK_BY order_items_list
690 {
691 pParser->ToString ( pParser->m_pQuery->m_sOrderBy, $3 );
692 }
693 | TOK_ORDER TOK_BY TOK_RAND '(' ')'
694 {
695 pParser->m_pQuery->m_sOrderBy = "@random";
696 }
697 ;
698
699 order_items_list:
700 order_item
701 | order_items_list ',' order_item { TRACK_BOUNDS ( $$, $1, $3 ); }
702 ;
703
704 order_item:
705 expr_ident
706 | expr_ident TOK_ASC { TRACK_BOUNDS ( $$, $1, $2 ); }
707 | expr_ident TOK_DESC { TRACK_BOUNDS ( $$, $1, $2 ); }
708 ;
709
710 opt_limit_clause:
711 // empty
712 | limit_clause
713 ;
714
715 limit_clause:
716 TOK_LIMIT TOK_CONST_INT
717 {
718 pParser->m_pQuery->m_iOffset = 0;
719 pParser->m_pQuery->m_iLimit = $2.m_iValue;
720 }
721 | TOK_LIMIT TOK_CONST_INT ',' TOK_CONST_INT
722 {
723 pParser->m_pQuery->m_iOffset = $2.m_iValue;
724 pParser->m_pQuery->m_iLimit = $4.m_iValue;
725 }
726 ;
727
728 opt_option_clause:
729 // empty
730 | option_clause
731 ;
732
733 option_clause:
734 TOK_OPTION option_list
735 ;
736
737 option_list:
738 option_item
739 | option_list ',' option_item
740 ;
741
742 option_item:
743 ident '=' ident
744 {
745 if ( !pParser->AddOption ( $1, $3 ) )
746 YYERROR;
747 }
748 | ident '=' TOK_CONST_INT
749 {
750 if ( !pParser->AddOption ( $1, $3 ) )
751 YYERROR;
752 }
753 | ident '=' '(' named_const_list ')'
754 {
755 if ( !pParser->AddOption ( $1, pParser->GetNamedVec ( $4.m_iValue ) ) )
756 YYERROR;
757 pParser->FreeNamedVec ( $4.m_iValue );
758 }
759 | ident '=' ident '(' TOK_QUOTED_STRING ')'
760 {
761 if ( !pParser->AddOption ( $1, $3, $5 ) )
762 YYERROR;
763 }
764 | ident '=' TOK_QUOTED_STRING
765 {
766 if ( !pParser->AddOption ( $1, $3 ) )
767 YYERROR;
768 }
769 ;
770
771 named_const_list:
772 named_const
773 {
774 $$.m_iValue = pParser->AllocNamedVec ();
775 pParser->AddConst ( $$.m_iValue, $1 );
776 }
777 | named_const_list ',' named_const
778 {
779 pParser->AddConst( $$.m_iValue, $3 );
780 }
781 ;
782
783 named_const:
784 ident '=' const_int
785 {
786 $$ = $1;
787 $$.m_iValue = $3.m_iValue;
788 }
789 ;
790
791 //////////////////////////////////////////////////////////////////////////
792
793 expr:
794 ident
795 | TOK_ATIDENT { if ( !pParser->SetOldSyntax() ) YYERROR; }
796 | TOK_ID { if ( !pParser->SetNewSyntax() ) YYERROR; }
797 | TOK_CONST_INT
798 | TOK_CONST_FLOAT
799 | TOK_DOT_NUMBER
800 | TOK_USERVAR
801 | '-' expr %prec TOK_NEG { TRACK_BOUNDS ( $$, $1, $2 ); }
802 | TOK_NOT expr { TRACK_BOUNDS ( $$, $1, $2 ); }
803
804 | expr '+' expr { TRACK_BOUNDS ( $$, $1, $3 ); }
805 | expr '-' expr { TRACK_BOUNDS ( $$, $1, $3 ); }
806 | expr '*' expr { TRACK_BOUNDS ( $$, $1, $3 ); }
807 | expr '/' expr { TRACK_BOUNDS ( $$, $1, $3 ); }
808 | expr '<' expr { TRACK_BOUNDS ( $$, $1, $3 ); }
809 | expr '>' expr { TRACK_BOUNDS ( $$, $1, $3 ); }
810 | expr '&' expr { TRACK_BOUNDS ( $$, $1, $3 ); }
811 | expr '|' expr { TRACK_BOUNDS ( $$, $1, $3 ); }
812 | expr '%' expr { TRACK_BOUNDS ( $$, $1, $3 ); }
813 | expr TOK_DIV expr { TRACK_BOUNDS ( $$, $1, $3 ); }
814 | expr TOK_MOD expr { TRACK_BOUNDS ( $$, $1, $3 ); }
815 | expr TOK_LTE expr { TRACK_BOUNDS ( $$, $1, $3 ); }
816 | expr TOK_GTE expr { TRACK_BOUNDS ( $$, $1, $3 ); }
817 | expr '=' expr { TRACK_BOUNDS ( $$, $1, $3 ); }
818 | expr TOK_NE expr { TRACK_BOUNDS ( $$, $1, $3 ); }
819 | expr TOK_AND expr { TRACK_BOUNDS ( $$, $1, $3 ); }
820 | expr TOK_OR expr { TRACK_BOUNDS ( $$, $1, $3 ); }
821 | '(' expr ')' { TRACK_BOUNDS ( $$, $1, $3 ); }
822 | '{' consthash '}' { TRACK_BOUNDS ( $$, $1, $3 ); }
823 | function
824 | json_expr
825 | streq
826 | json_field TOK_IS TOK_NULL { TRACK_BOUNDS ( $$, $1, $3 ); }
827 | json_field TOK_IS TOK_NOT TOK_NULL { TRACK_BOUNDS ( $$, $1, $4 ); }
828 ;
829
830 function:
831 TOK_IDENT '(' arglist ')' { TRACK_BOUNDS ( $$, $1, $4 ); }
832 | TOK_IN '(' arglist ')' { TRACK_BOUNDS ( $$, $1, $4 ); } // handle exception from 'ident' rule
833 | TOK_INTEGER '(' arglist ')' { TRACK_BOUNDS ( $$, $1, $4 ); }
834 | TOK_BIGINT '(' arglist ')' { TRACK_BOUNDS ( $$, $1, $4 ); }
835 | TOK_FLOAT '(' arglist ')' { TRACK_BOUNDS ( $$, $1, $4 ); }
836 | TOK_DOUBLE '(' arglist ')' { TRACK_BOUNDS ( $$, $1, $4 ); }
837 | TOK_IDENT '(' ')' { TRACK_BOUNDS ( $$, $1, $3 ); }
838 | TOK_MIN '(' expr ',' expr ')' { TRACK_BOUNDS ( $$, $1, $6 ); } // handle clash with aggregate functions
839 | TOK_MAX '(' expr ',' expr ')' { TRACK_BOUNDS ( $$, $1, $6 ); }
840 | TOK_WEIGHT '(' ')' { TRACK_BOUNDS ( $$, $1, $3 ); }
841 | TOK_IDENT '(' expr TOK_FOR ident TOK_IN json_field ')' { TRACK_BOUNDS ( $$, $1, $8 ); }
842 | TOK_REMAP '(' expr ',' expr ',' '(' arglist ')' ',' '(' arglist ')' ')' { TRACK_BOUNDS ( $$, $1, $14 ); }
843 ;
844
845 arglist:
846 arg
847 | arglist ',' arg
848 ;
849
850 arg:
851 expr
852 | TOK_QUOTED_STRING
853 ;
854
855 consthash:
856 hash_key '=' hash_val { TRACK_BOUNDS ( $$, $1, $3 ); }
857 | consthash ',' hash_key '=' hash_val { TRACK_BOUNDS ( $$, $1, $5 ); }
858 ;
859
860 hash_key:
861 ident
862 | TOK_IN
863 ;
864
865 hash_val:
866 const_int
867 | ident
868 ;
869
870 //////////////////////////////////////////////////////////////////////////
871
872 show_stmt:
873 TOK_SHOW show_what
874 ;
875
876 like_filter:
877 // empty
878 | TOK_LIKE TOK_QUOTED_STRING { pParser->ToStringUnescape ( pParser->m_pStmt->m_sStringParam, $2 ); }
879 ;
880
881 show_what:
882 TOK_WARNINGS { pParser->m_pStmt->m_eStmt = STMT_SHOW_WARNINGS; }
883 | TOK_STATUS like_filter { pParser->m_pStmt->m_eStmt = STMT_SHOW_STATUS; }
884 | TOK_META like_filter { pParser->m_pStmt->m_eStmt = STMT_SHOW_META; }
885 | TOK_AGENT TOK_STATUS like_filter { pParser->m_pStmt->m_eStmt = STMT_SHOW_AGENT_STATUS; }
886 | TOK_PROFILE { pParser->m_pStmt->m_eStmt = STMT_SHOW_PROFILE; }
887 | TOK_PLAN { pParser->m_pStmt->m_eStmt = STMT_SHOW_PLAN; }
888 | TOK_PLUGINS { pParser->m_pStmt->m_eStmt = STMT_SHOW_PLUGINS; }
889 | TOK_THREADS opt_option_clause { pParser->m_pStmt->m_eStmt = STMT_SHOW_THREADS; }
890 | TOK_AGENT TOK_QUOTED_STRING TOK_STATUS like_filter
891 {
892 pParser->m_pStmt->m_eStmt = STMT_SHOW_AGENT_STATUS;
893 pParser->ToStringUnescape ( pParser->m_pStmt->m_sIndex, $2 );
894 }
895 | TOK_AGENT ident TOK_STATUS like_filter
896 {
897 pParser->m_pStmt->m_eStmt = STMT_SHOW_AGENT_STATUS;
898 pParser->ToString ( pParser->m_pStmt->m_sIndex, $2 );
899 }
900 | index_or_table ident TOK_STATUS
901 {
902 pParser->m_pStmt->m_eStmt = STMT_SHOW_INDEX_STATUS;
903 pParser->ToString ( pParser->m_pStmt->m_sIndex, $2 );
904 }
905 | index_or_table ident opt_chunk TOK_SETTINGS
906 {
907 pParser->m_pStmt->m_eStmt = STMT_SHOW_INDEX_SETTINGS;
908 pParser->ToString ( pParser->m_pStmt->m_sIndex, $2 );
909 }
910 | index_or_table ident TOK_DOT_NUMBER TOK_SETTINGS
911 {
912 pParser->m_pStmt->m_eStmt = STMT_SHOW_INDEX_SETTINGS;
913 pParser->ToString ( pParser->m_pStmt->m_sIndex, $2 );
914 pParser->m_pStmt->m_iIntParam = int($3.m_fValue*10);
915 }
916 ;
917
918 index_or_table:
919 TOK_INDEX
920 | TOK_TABLE
921 ;
922
923 opt_chunk:
924 // empty
925 | TOK_CHUNK TOK_CONST_INT
926 {
927 pParser->m_pStmt->m_iIntParam = $2.m_iValue;
928 };
929
930 //////////////////////////////////////////////////////////////////////////
931
932 set_stmt:
933 TOK_SET ident_set '=' boolean_value
934 {
935 pParser->SetStatement ( $2, SET_LOCAL );
936 pParser->m_pStmt->m_iSetValue = $4.m_iValue;
937 }
938 | TOK_SET ident_set '=' set_string_value
939 {
940 pParser->SetStatement ( $2, SET_LOCAL );
941 pParser->ToString ( pParser->m_pStmt->m_sSetValue, $4 );
942 }
943 | TOK_SET ident_set '=' TOK_NULL
944 {
945 pParser->SetStatement ( $2, SET_LOCAL );
946 pParser->m_pStmt->m_bSetNull = true;
947 }
948 | TOK_SET TOK_NAMES set_value { pParser->m_pStmt->m_eStmt = STMT_DUMMY; }
949 | TOK_SET TOK_SYSVAR '=' set_value { pParser->m_pStmt->m_eStmt = STMT_DUMMY; }
950 | TOK_SET TOK_CHARACTER TOK_SET set_value { pParser->m_pStmt->m_eStmt = STMT_DUMMY; }
951 ;
952
953 set_global_stmt:
954 TOK_SET TOK_GLOBAL TOK_USERVAR '=' '(' const_list ')'
955 {
956 pParser->SetStatement ( $3, SET_GLOBAL_UVAR );
957 pParser->m_pStmt->m_dSetValues = *$6.m_pValues.Ptr();
958 }
959 | TOK_SET TOK_GLOBAL ident_set '=' set_string_value
960 {
961 pParser->SetStatement ( $3, SET_GLOBAL_SVAR );
962 pParser->ToString ( pParser->m_pStmt->m_sSetValue, $5 ).Unquote();
963 }
964 | TOK_SET TOK_GLOBAL ident_set '=' TOK_CONST_INT
965 {
966 pParser->SetStatement ( $3, SET_GLOBAL_SVAR );
967 pParser->m_pStmt->m_iSetValue = $5.m_iValue;
968 }
969 | TOK_SET TOK_INDEX ident TOK_GLOBAL TOK_USERVAR '=' '(' const_list ')'
970 {
971 pParser->SetStatement ( $5, SET_INDEX_UVAR );
972 pParser->m_pStmt->m_dSetValues = *$8.m_pValues.Ptr();
973 pParser->ToString ( pParser->m_pStmt->m_sIndex, $3 );
974 }
975 ;
976
977 set_string_value:
978 ident
979 | TOK_QUOTED_STRING
980 ;
981
982 boolean_value:
983 TOK_TRUE { $$.m_iValue = 1; }
984 | TOK_FALSE { $$.m_iValue = 0; }
985 | const_int
986 {
987 $$.m_iValue = $1.m_iValue;
988 if ( $$.m_iValue!=0 && $$.m_iValue!=1 )
989 {
990 yyerror ( pParser, "only 0 and 1 could be used as boolean values" );
991 YYERROR;
992 }
993 }
994 ;
995
996 set_value:
997 simple_set_value
998 | set_value '-' simple_set_value
999 ;
1000
1001 simple_set_value:
1002 ident
1003 | TOK_NULL
1004 | TOK_QUOTED_STRING
1005 | TOK_CONST_INT
1006 | TOK_CONST_FLOAT
1007 ;
1008
1009
1010 //////////////////////////////////////////////////////////////////////////
1011
1012 transact_op:
1013 TOK_COMMIT { pParser->m_pStmt->m_eStmt = STMT_COMMIT; }
1014 | TOK_ROLLBACK { pParser->m_pStmt->m_eStmt = STMT_ROLLBACK; }
1015 | start_transaction { pParser->m_pStmt->m_eStmt = STMT_BEGIN; }
1016 ;
1017
1018 start_transaction:
1019 TOK_BEGIN
1020 | TOK_START TOK_TRANSACTION
1021 ;
1022
1023 //////////////////////////////////////////////////////////////////////////
1024
1025 insert_into:
1026 insert_or_replace TOK_INTO ident opt_column_list TOK_VALUES insert_rows_list opt_insert_options
1027 {
1028 // everything else is pushed directly into parser within the rules
1029 pParser->ToString ( pParser->m_pStmt->m_sIndex, $3 );
1030 }
1031 ;
1032
1033 insert_or_replace:
1034 TOK_INSERT { pParser->m_pStmt->m_eStmt = STMT_INSERT; }
1035 | TOK_REPLACE { pParser->m_pStmt->m_eStmt = STMT_REPLACE; }
1036 ;
1037
1038 opt_column_list:
1039 // empty
1040 | '(' column_list ')'
1041 ;
1042
1043 column_ident:
1044 ident
1045 | TOK_ID
1046 ;
1047
1048 column_list:
1049 column_ident { if ( !pParser->AddSchemaItem ( &$1 ) ) { yyerror ( pParser, "unknown field" ); YYERROR; } }
1050 | column_list ',' column_ident { if ( !pParser->AddSchemaItem ( &$3 ) ) { yyerror ( pParser, "unknown field" ); YYERROR; } }
1051 ;
1052
1053 insert_rows_list:
1054 insert_row
1055 | insert_rows_list ',' insert_row
1056 ;
1057
1058 insert_row:
1059 '(' insert_vals_list ')' { if ( !pParser->m_pStmt->CheckInsertIntegrity() ) { yyerror ( pParser, "wrong number of values here" ); YYERROR; } }
1060 ;
1061
1062 insert_vals_list:
1063 insert_val { AddInsval ( pParser, pParser->m_pStmt->m_dInsertValues, $1 ); }
1064 | insert_vals_list ',' insert_val { AddInsval ( pParser, pParser->m_pStmt->m_dInsertValues, $3 ); }
1065 ;
1066
1067 insert_val:
1068 const_int { $$.m_iType = TOK_CONST_INT; $$.m_iValue = $1.m_iValue; }
1069 | const_float { $$.m_iType = TOK_CONST_FLOAT; $$.m_fValue = $1.m_fValue; }
1070 | TOK_QUOTED_STRING { $$.m_iType = TOK_QUOTED_STRING; $$.m_iStart = $1.m_iStart; $$.m_iEnd = $1.m_iEnd; }
1071 | '(' const_list ')' { $$.m_iType = TOK_CONST_MVA; $$.m_pValues = $2.m_pValues; }
1072 | '(' ')' { $$.m_iType = TOK_CONST_MVA; }
1073 ;
1074
1075 opt_insert_options:
1076 | TOK_OPTION insert_options_list
1077 ;
1078
1079 insert_options_list:
1080 insert_option
1081 | insert_options_list ',' insert_option
1082 ;
1083
1084 insert_option:
1085 TOK_IDENT '=' TOK_QUOTED_STRING { if ( !pParser->AddInsertOption ( $1, $3 ) ) YYERROR; }
1086 ;
1087
1088 //////////////////////////////////////////////////////////////////////////
1089
1090 delete_from:
1091 TOK_DELETE TOK_FROM ident_list where_clause
1092 {
1093 if ( !pParser->DeleteStatement ( &$3 ) )
1094 YYERROR;
1095 }
1096 ;
1097
1098 //////////////////////////////////////////////////////////////////////////
1099
1100 call_proc:
1101 TOK_CALL ident '(' call_args_list opt_call_opts_list ')'
1102 {
1103 pParser->m_pStmt->m_eStmt = STMT_CALL;
1104 pParser->ToString ( pParser->m_pStmt->m_sCallProc, $2 );
1105 }
1106 ;
1107
1108 call_args_list:
1109 call_arg
1110 {
1111 AddInsval ( pParser, pParser->m_pStmt->m_dInsertValues, $1 );
1112 }
1113 | call_args_list ',' call_arg
1114 {
1115 AddInsval ( pParser, pParser->m_pStmt->m_dInsertValues, $3 );
1116 }
1117 ;
1118
1119 call_arg:
1120 insert_val
1121 | '(' const_string_list ')'
1122 {
1123 $$.m_iType = TOK_CONST_STRINGS;
1124 }
1125 ;
1126
1127 const_string_list:
1128 TOK_QUOTED_STRING
1129 {
1130 // FIXME? for now, one such array per CALL statement, tops
1131 if ( pParser->m_pStmt->m_dCallStrings.GetLength() )
1132 {
1133 yyerror ( pParser, "unexpected constant string list" );
1134 YYERROR;
1135 }
1136 pParser->ToStringUnescape ( pParser->m_pStmt->m_dCallStrings.Add(), $1 );
1137 }
1138 | const_string_list ',' TOK_QUOTED_STRING
1139 {
1140 pParser->ToStringUnescape ( pParser->m_pStmt->m_dCallStrings.Add(), $3 );
1141 }
1142 ;
1143
1144 opt_call_opts_list:
1145 // empty
1146 | ',' call_opts_list
1147 ;
1148
1149 call_opts_list:
1150 call_opt
1151 {
1152 assert ( pParser->m_pStmt->m_dCallOptNames.GetLength()==1 );
1153 assert ( pParser->m_pStmt->m_dCallOptValues.GetLength()==1 );
1154 }
1155 | call_opts_list ',' call_opt
1156 ;
1157
1158 call_opt:
1159 insert_val opt_as call_opt_name
1160 {
1161 pParser->ToString ( pParser->m_pStmt->m_dCallOptNames.Add(), $3 );
1162 AddInsval ( pParser, pParser->m_pStmt->m_dCallOptValues, $1 );
1163 }
1164 ;
1165
1166 opt_as:
1167 // empty
1168 | TOK_AS
1169 ;
1170
1171 call_opt_name:
1172 ident
1173 | TOK_LIMIT
1174 ;
1175
1176 //////////////////////////////////////////////////////////////////////////
1177
1178 describe:
1179 describe_tok ident like_filter
1180 {
1181 pParser->m_pStmt->m_eStmt = STMT_DESCRIBE;
1182 pParser->ToString ( pParser->m_pStmt->m_sIndex, $2 );
1183 }
1184 ;
1185
1186 describe_tok:
1187 TOK_DESCRIBE
1188 | TOK_DESC
1189 ;
1190
1191 //////////////////////////////////////////////////////////////////////////
1192
1193 show_tables:
1194 TOK_SHOW TOK_TABLES like_filter { pParser->m_pStmt->m_eStmt = STMT_SHOW_TABLES; }
1195 ;
1196
1197 show_databases:
1198 TOK_SHOW TOK_DATABASES like_filter { pParser->m_pStmt->m_eStmt = STMT_SHOW_DATABASES; }
1199 ;
1200
1201 //////////////////////////////////////////////////////////////////////////
1202
1203 update:
1204 TOK_UPDATE ident_list TOK_SET update_items_list where_clause opt_option_clause
1205 {
1206 if ( !pParser->UpdateStatement ( &$2 ) )
1207 YYERROR;
1208 }
1209 ;
1210
1211 update_items_list:
1212 update_item
1213 | update_items_list ',' update_item
1214 ;
1215
1216 update_item:
1217 ident '=' const_int
1218 {
1219 // it is performance-critical to forcibly inline this
1220 pParser->m_pStmt->m_tUpdate.m_dPool.Add ( (DWORD)$3.m_iValue );
1221 DWORD uHi = (DWORD)( $3.m_iValue>>32 );
1222 if ( uHi )
1223 {
1224 pParser->m_pStmt->m_tUpdate.m_dPool.Add ( uHi );
1225 pParser->AddUpdatedAttr ( $1, SPH_ATTR_BIGINT );
1226 } else
1227 {
1228 pParser->AddUpdatedAttr ( $1, SPH_ATTR_INTEGER );
1229 }
1230 }
1231 | ident '=' const_float
1232 {
1233 // it is performance-critical to forcibly inline this
1234 pParser->m_pStmt->m_tUpdate.m_dPool.Add ( sphF2DW ( $3.m_fValue ) );
1235 pParser->AddUpdatedAttr ( $1, SPH_ATTR_FLOAT );
1236 }
1237 | ident '=' '(' const_list ')'
1238 {
1239 pParser->UpdateMVAAttr ( $1, $4 );
1240 }
1241 | ident '=' '(' ')' // special case () means delete mva
1242 {
1243 SqlNode_t tNoValues;
1244 pParser->UpdateMVAAttr ( $1, tNoValues );
1245 }
1246 | json_expr '=' const_int // duplicate ident code (avoiding s/r conflict)
1247 {
1248 // it is performance-critical to forcibly inline this
1249 pParser->m_pStmt->m_tUpdate.m_dPool.Add ( (DWORD)$3.m_iValue );
1250 DWORD uHi = (DWORD)( $3.m_iValue>>32 );
1251 if ( uHi )
1252 {
1253 pParser->m_pStmt->m_tUpdate.m_dPool.Add ( uHi );
1254 pParser->AddUpdatedAttr ( $1, SPH_ATTR_BIGINT );
1255 } else
1256 {
1257 pParser->AddUpdatedAttr ( $1, SPH_ATTR_INTEGER );
1258 }
1259 }
1260 | json_expr '=' const_float
1261 {
1262 // it is performance-critical to forcibly inline this
1263 pParser->m_pStmt->m_tUpdate.m_dPool.Add ( sphF2DW ( $3.m_fValue ) );
1264 pParser->AddUpdatedAttr ( $1, SPH_ATTR_FLOAT );
1265 }
1266 ;
1267
1268 //////////////////////////////////////////////////////////////////////////
1269
1270 alter_col_type:
1271 TOK_INTEGER { $$.m_iValue = SPH_ATTR_INTEGER; }
1272 | TOK_BIGINT { $$.m_iValue = SPH_ATTR_BIGINT; }
1273 | TOK_FLOAT { $$.m_iValue = SPH_ATTR_FLOAT; }
1274 | TOK_BOOL { $$.m_iValue = SPH_ATTR_BOOL; }
1275 | TOK_MULTI { $$.m_iValue = SPH_ATTR_UINT32SET; }
1276 | TOK_MULTI64 { $$.m_iValue = SPH_ATTR_INT64SET; }
1277 | TOK_JSON { $$.m_iValue = SPH_ATTR_JSON; }
1278 | TOK_STRING { $$.m_iValue = SPH_ATTR_STRING; }
1279 | TOK_INT { $$.m_iValue = SPH_ATTR_INTEGER; }
1280 ;
1281
1282 alter:
1283 TOK_ALTER TOK_TABLE ident TOK_ADD TOK_COLUMN ident alter_col_type
1284 {
1285 SqlStmt_t & tStmt = *pParser->m_pStmt;
1286 tStmt.m_eStmt = STMT_ALTER_ADD;
1287 pParser->ToString ( tStmt.m_sIndex, $3 );
1288 pParser->ToString ( tStmt.m_sAlterAttr, $6 );
1289 tStmt.m_eAlterColType = (ESphAttr)$7.m_iValue;
1290 }
1291 | TOK_ALTER TOK_TABLE ident TOK_DROP TOK_COLUMN ident
1292 {
1293 SqlStmt_t & tStmt = *pParser->m_pStmt;
1294 tStmt.m_eStmt = STMT_ALTER_DROP;
1295 pParser->ToString ( tStmt.m_sIndex, $3 );
1296 pParser->ToString ( tStmt.m_sAlterAttr, $6 );
1297 }
1298 | TOK_ALTER TOK_RTINDEX ident TOK_RECONFIGURE
1299 {
1300 SqlStmt_t & tStmt = *pParser->m_pStmt;
1301 tStmt.m_eStmt = STMT_ALTER_RECONFIGURE;
1302 pParser->ToString ( tStmt.m_sIndex, $3 );
1303 }
1304 ;
1305
1306 //////////////////////////////////////////////////////////////////////////
1307
1308 show_variables:
1309 TOK_SHOW opt_scope TOK_VARIABLES opt_show_variables_where
1310 {
1311 pParser->m_pStmt->m_eStmt = STMT_SHOW_VARIABLES;
1312 }
1313 | TOK_SHOW opt_scope TOK_VARIABLES TOK_LIKE TOK_QUOTED_STRING
1314 {
1315 pParser->m_pStmt->m_eStmt = STMT_SHOW_VARIABLES;
1316 pParser->ToStringUnescape ( pParser->m_pStmt->m_sStringParam, $5 );
1317 }
1318 ;
1319
1320 opt_show_variables_where:
1321 | show_variables_where
1322 ;
1323
1324 show_variables_where:
1325 TOK_WHERE show_variables_where_list
1326 ;
1327
1328 show_variables_where_list:
1329 show_variables_where_entry
1330 | show_variables_where_list TOK_OR show_variables_where_entry
1331 ;
1332
1333 show_variables_where_entry:
1334 ident '=' TOK_QUOTED_STRING // for example, Variable_name = 'character_set'
1335 ;
1336
1337 show_collation:
1338 TOK_SHOW TOK_COLLATION
1339 {
1340 pParser->m_pStmt->m_eStmt = STMT_SHOW_COLLATION;
1341 }
1342 ;
1343
1344 show_character_set:
1345 TOK_SHOW TOK_CHARACTER TOK_SET
1346 {
1347 pParser->m_pStmt->m_eStmt = STMT_SHOW_CHARACTER_SET;
1348 }
1349 ;
1350
1351 set_transaction:
1352 TOK_SET opt_scope TOK_TRANSACTION TOK_ISOLATION TOK_LEVEL isolation_level
1353 {
1354 pParser->m_pStmt->m_eStmt = STMT_DUMMY;
1355 }
1356 ;
1357
1358 opt_scope:
1359 | TOK_GLOBAL
1360 | TOK_SESSION
1361 ;
1362
1363 isolation_level:
1364 TOK_READ TOK_UNCOMMITTED
1365 | TOK_READ TOK_COMMITTED
1366 | TOK_REPEATABLE TOK_READ
1367 | TOK_SERIALIZABLE
1368 ;
1369
1370 //////////////////////////////////////////////////////////////////////////
1371
1372 create_function:
1373 TOK_CREATE TOK_FUNCTION ident TOK_RETURNS udf_type TOK_SONAME TOK_QUOTED_STRING
1374 {
1375 SqlStmt_t & tStmt = *pParser->m_pStmt;
1376 tStmt.m_eStmt = STMT_CREATE_FUNCTION;
1377 pParser->ToString ( tStmt.m_sUdfName, $3 );
1378 pParser->ToStringUnescape ( tStmt.m_sUdfLib, $7 );
1379 tStmt.m_eUdfType = (ESphAttr) $5.m_iValue;
1380 }
1381 ;
1382
1383 udf_type:
1384 TOK_INT { $$.m_iValue = SPH_ATTR_INTEGER; }
1385 | TOK_BIGINT { $$.m_iValue = SPH_ATTR_BIGINT; }
1386 | TOK_FLOAT { $$.m_iValue = SPH_ATTR_FLOAT; }
1387 | TOK_STRING { $$.m_iValue = SPH_ATTR_STRINGPTR; }
1388 | TOK_INTEGER { $$.m_iValue = SPH_ATTR_INTEGER; }
1389 ;
1390
1391
1392 drop_function:
1393 TOK_DROP TOK_FUNCTION ident
1394 {
1395 SqlStmt_t & tStmt = *pParser->m_pStmt;
1396 tStmt.m_eStmt = STMT_DROP_FUNCTION;
1397 pParser->ToString ( tStmt.m_sUdfName, $3 );
1398 }
1399 ;
1400
1401 ////////////////////////////////////////////////////////////
1402
1403 attach_index:
1404 TOK_ATTACH TOK_INDEX ident TOK_TO TOK_RTINDEX ident
1405 {
1406 SqlStmt_t & tStmt = *pParser->m_pStmt;
1407 tStmt.m_eStmt = STMT_ATTACH_INDEX;
1408 pParser->ToString ( tStmt.m_sIndex, $3 );
1409 pParser->ToString ( tStmt.m_sStringParam, $6 );
1410 }
1411 ;
1412
1413 //////////////////////////////////////////////////////////////////////////
1414
1415 flush_rtindex:
1416 TOK_FLUSH TOK_RTINDEX ident
1417 {
1418 SqlStmt_t & tStmt = *pParser->m_pStmt;
1419 tStmt.m_eStmt = STMT_FLUSH_RTINDEX;
1420 pParser->ToString ( tStmt.m_sIndex, $3 );
1421 }
1422 ;
1423
1424 flush_ramchunk:
1425 TOK_FLUSH TOK_RAMCHUNK ident
1426 {
1427 SqlStmt_t & tStmt = *pParser->m_pStmt;
1428 tStmt.m_eStmt = STMT_FLUSH_RAMCHUNK;
1429 pParser->ToString ( tStmt.m_sIndex, $3 );
1430 }
1431 ;
1432
1433 flush_index:
1434 TOK_FLUSH TOK_ATTRIBUTES
1435 {
1436 SqlStmt_t & tStmt = *pParser->m_pStmt;
1437 tStmt.m_eStmt = STMT_FLUSH_INDEX;
1438 }
1439 ;
1440
1441 //////////////////////////////////////////////////////////////////////////
1442
1443 select_sysvar:
1444 TOK_SELECT sysvar_list opt_limit_clause
1445 {
1446 pParser->m_pStmt->m_eStmt = STMT_SELECT_SYSVAR;
1447 pParser->ToString ( pParser->m_pStmt->m_tQuery.m_sQuery, $2 );
1448 }
1449 ;
1450
1451 sysvar_list:
1452 sysvar_item
1453 | sysvar_list ',' sysvar_item
1454 ;
1455
1456 sysvar_item:
1457 sysvar_name opt_alias
1458 ;
1459
1460 sysvar_name:
1461 TOK_SYSVAR { pParser->AddItem ( &$1 ); }
1462 ;
1463
1464 select_dual:
1465 TOK_SELECT expr
1466 {
1467 pParser->m_pStmt->m_eStmt = STMT_SELECT_DUAL;
1468 pParser->ToString ( pParser->m_pStmt->m_tQuery.m_sQuery, $2 );
1469 }
1470 ;
1471
1472 //////////////////////////////////////////////////////////////////////////
1473
1474 truncate:
1475 TOK_TRUNCATE TOK_RTINDEX ident
1476 {
1477 SqlStmt_t & tStmt = *pParser->m_pStmt;
1478 tStmt.m_eStmt = STMT_TRUNCATE_RTINDEX;
1479 pParser->ToString ( tStmt.m_sIndex, $3 );
1480 }
1481 ;
1482
1483 //////////////////////////////////////////////////////////////////////////
1484
1485 optimize_index:
1486 TOK_OPTIMIZE TOK_INDEX ident
1487 {
1488 SqlStmt_t & tStmt = *pParser->m_pStmt;
1489 tStmt.m_eStmt = STMT_OPTIMIZE_INDEX;
1490 pParser->ToString ( tStmt.m_sIndex, $3 );
1491 }
1492 ;
1493
1494 //////////////////////////////////////////////////////////////////////////
1495
1496 create_plugin:
1497 TOK_CREATE TOK_PLUGIN ident TOK_TYPE TOK_QUOTED_STRING TOK_SONAME TOK_QUOTED_STRING
1498 {
1499 SqlStmt_t & s = *pParser->m_pStmt;
1500 s.m_eStmt = STMT_CREATE_PLUGIN;
1501 pParser->ToString ( s.m_sUdfName, $3 );
1502 pParser->ToStringUnescape ( s.m_sStringParam, $5 );
1503 pParser->ToStringUnescape ( s.m_sUdfLib, $7 );
1504 }
1505 ;
1506
1507 drop_plugin:
1508 TOK_DROP TOK_PLUGIN ident TOK_TYPE TOK_QUOTED_STRING
1509 {
1510 SqlStmt_t & s = *pParser->m_pStmt;
1511 s.m_eStmt = STMT_DROP_PLUGIN;
1512 pParser->ToString ( s.m_sUdfName, $3 );
1513 pParser->ToStringUnescape ( s.m_sStringParam, $5 );
1514 }
1515 ;
1516 //////////////////////////////////////////////////////////////////////////
1517
1518 json_field:
1519 json_expr
1520 | ident
1521 ;
1522
1523 json_expr:
1524 ident subscript { $$ = $1; $$.m_iEnd = $2.m_iEnd; }
1525
1526 subscript:
1527 subkey
1528 | subscript subkey { $$ = $1; $$.m_iEnd = $2.m_iEnd; }
1529 ;
1530
1531 subkey:
1532 TOK_SUBKEY { $$ = $1; $$.m_iEnd = $1.m_iEnd; }
1533 | TOK_DOT_NUMBER { $$ = $1; $$.m_iEnd = $1.m_iEnd; }
1534 | '[' expr ']' { $$ = $1; $$.m_iEnd = $3.m_iEnd; }
1535 | '[' TOK_QUOTED_STRING ']' { $$ = $1; $$.m_iEnd = $3.m_iEnd; }
1536 ;
1537
1538 streq:
1539 expr '=' strval { TRACK_BOUNDS ( $$, $1, $3 ); }
1540 | strval '=' expr { TRACK_BOUNDS ( $$, $1, $3 ); }
1541 ;
1542
1543 strval:
1544 TOK_QUOTED_STRING
1545 ;
1546
1547 //////////////////////////////////////////////////////////////////////////
1548
1549 opt_facet_by_items_list:
1550 // empty
1551 | facet_by facet_items_list
1552 ;
1553
1554 facet_by:
1555 TOK_BY
1556 {
1557 pParser->m_pQuery->m_sFacetBy = pParser->m_pQuery->m_sGroupBy;
1558 pParser->m_pQuery->m_sGroupBy = "";
1559 pParser->AddCount ();
1560 }
1561 ;
1562
1563 facet_item:
1564 facet_expr opt_alias
1565 ;
1566
1567 facet_expr:
1568 expr
1569 {
1570 pParser->AddItem ( &$1 );
1571 pParser->AddGroupBy ( $1 );
1572 }
1573 ;
1574
1575 facet_items_list:
1576 facet_item
1577 | facet_items_list ',' facet_item
1578 ;
1579
1580 facet_stmt:
1581 TOK_FACET facet_items_list opt_facet_by_items_list opt_order_clause opt_limit_clause
1582 {
1583 pParser->m_pStmt->m_eStmt = STMT_FACET;
1584 if ( pParser->m_pQuery->m_sFacetBy.IsEmpty() )
1585 {
1586 pParser->m_pQuery->m_sFacetBy = pParser->m_pQuery->m_sGroupBy;
1587 pParser->AddCount ();
1588 }
1589 }
1590 ;
1591
1592 %%
1593
1594 #if USE_WINDOWS
1595 #pragma warning(pop)
1596 #endif
1597