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