1 /* Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. 2 3 This program is free software; you can redistribute it and/or modify 4 it under the terms of the GNU General Public License as published by 5 the Free Software Foundation; version 2 of the License. 6 7 This program is distributed in the hope that it will be useful, 8 but WITHOUT ANY WARRANTY; without even the implied warranty of 9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 GNU General Public License for more details. 11 12 You should have received a copy of the GNU General Public License 13 along with this program; if not, write to the Free Software 14 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ 15 16 #include "mariadb.h" 17 #include "sql_priv.h" 18 #include "unireg.h" 19 #ifdef USE_PRAGMA_IMPLEMENTATION 20 #pragma implementation 21 #endif 22 23 #include "sp_pcontext.h" 24 #include "sp_head.h" 25 26 bool sp_condition_value::equals(const sp_condition_value *cv) const 27 { 28 DBUG_ASSERT(cv); 29 30 /* 31 The following test disallows duplicate handlers, 32 including user defined exceptions with the same WHEN clause: 33 DECLARE 34 a EXCEPTION; 35 b EXCEPTION; 36 BEGIN 37 RAUSE a; 38 EXCEPTION 39 WHEN a THEN RETURN 'a0'; 40 WHEN a THEN RETURN 'a1'; 41 END 42 */ 43 if (this == cv) 44 return true; 45 46 /* 47 The test below considers two conditions of the same type as equal 48 (except for the user defined exceptions) to avoid declaring duplicate 49 handlers. 50 51 All user defined conditions have type==SQLSTATE 52 with the same SQL state and error code. 53 It's OK to have multiple user defined conditions: 54 DECLARE 55 a EXCEPTION; 56 b EXCEPTION; 57 BEGIN 58 RAISE a; 59 EXCEPTION 60 WHEN a THEN RETURN 'a'; 61 WHEN b THEN RETURN 'b'; 62 END; 63 */ 64 if (type != cv->type || m_is_user_defined || cv->m_is_user_defined) 65 return false; 66 67 switch (type) 68 { 69 case sp_condition_value::ERROR_CODE: 70 return (get_sql_errno() == cv->get_sql_errno()); 71 72 case sp_condition_value::SQLSTATE: 73 return Sql_state::eq(cv); 74 75 default: 76 return true; 77 } 78 } 79 80 81 void sp_pcontext::init(uint var_offset, 82 uint cursor_offset, 83 int num_case_expressions) 84 { 85 m_var_offset= var_offset; 86 m_cursor_offset= cursor_offset; 87 m_num_case_exprs= num_case_expressions; 88 89 m_labels.empty(); 90 m_goto_labels.empty(); 91 } 92 93 94 sp_pcontext::sp_pcontext() 95 : Sql_alloc(), 96 m_max_var_index(0), m_max_cursor_index(0), 97 m_parent(NULL), m_pboundary(0), 98 m_scope(REGULAR_SCOPE) 99 { 100 init(0, 0, 0); 101 } 102 103 104 sp_pcontext::sp_pcontext(sp_pcontext *prev, sp_pcontext::enum_scope scope) 105 : Sql_alloc(), 106 m_max_var_index(0), m_max_cursor_index(0), 107 m_parent(prev), m_pboundary(0), 108 m_scope(scope) 109 { 110 init(prev->m_var_offset + prev->m_max_var_index, 111 prev->current_cursor_count(), 112 prev->get_num_case_exprs()); 113 } 114 115 116 sp_pcontext::~sp_pcontext() 117 { 118 for (size_t i= 0; i < m_children.elements(); ++i) 119 delete m_children.at(i); 120 } 121 122 123 sp_pcontext *sp_pcontext::push_context(THD *thd, sp_pcontext::enum_scope scope) 124 { 125 sp_pcontext *child= new (thd->mem_root) sp_pcontext(this, scope); 126 127 if (child) 128 m_children.append(child); 129 return child; 130 } 131 132 133 bool cmp_labels(sp_label *a, sp_label *b) 134 { 135 return (lex_string_cmp(system_charset_info, &a->name, &b->name) == 0 && 136 a->type == b->type); 137 } 138 139 sp_pcontext *sp_pcontext::pop_context() 140 { 141 m_parent->m_max_var_index+= m_max_var_index; 142 143 uint submax= max_cursor_index(); 144 if (submax > m_parent->m_max_cursor_index) 145 m_parent->m_max_cursor_index= submax; 146 147 if (m_num_case_exprs > m_parent->m_num_case_exprs) 148 m_parent->m_num_case_exprs= m_num_case_exprs; 149 150 /* 151 ** Push unresolved goto label to parent context 152 */ 153 sp_label *label; 154 List_iterator_fast<sp_label> li(m_goto_labels); 155 while ((label= li++)) 156 { 157 if (label->ip == 0) 158 { 159 m_parent->m_goto_labels.add_unique(label, &cmp_labels); 160 } 161 } 162 return m_parent; 163 } 164 165 166 uint sp_pcontext::diff_handlers(const sp_pcontext *ctx, bool exclusive) const 167 { 168 uint n= 0; 169 const sp_pcontext *pctx= this; 170 const sp_pcontext *last_ctx= NULL; 171 172 while (pctx && pctx != ctx) 173 { 174 n+= (uint)pctx->m_handlers.elements(); 175 last_ctx= pctx; 176 pctx= pctx->parent_context(); 177 } 178 if (pctx) 179 return (exclusive && last_ctx ? n -(uint) last_ctx->m_handlers.elements() : n); 180 return 0; // Didn't find ctx 181 } 182 183 184 uint sp_pcontext::diff_cursors(const sp_pcontext *ctx, bool exclusive) const 185 { 186 uint n= 0; 187 const sp_pcontext *pctx= this; 188 const sp_pcontext *last_ctx= NULL; 189 190 while (pctx && pctx != ctx) 191 { 192 n+= (uint)pctx->m_cursors.elements(); 193 last_ctx= pctx; 194 pctx= pctx->parent_context(); 195 } 196 if (pctx) 197 return (exclusive && last_ctx ? (uint)(n - last_ctx->m_cursors.elements()) : n); 198 return 0; // Didn't find ctx 199 } 200 201 202 sp_variable *sp_pcontext::find_variable(const LEX_CSTRING *name, 203 bool current_scope_only) const 204 { 205 size_t i= m_vars.elements() - m_pboundary; 206 207 while (i--) 208 { 209 sp_variable *p= m_vars.at(i); 210 211 if (my_strnncoll(system_charset_info, 212 (const uchar *)name->str, name->length, 213 (const uchar *)p->name.str, p->name.length) == 0) 214 { 215 return p; 216 } 217 } 218 219 return (!current_scope_only && m_parent) ? 220 m_parent->find_variable(name, false) : 221 NULL; 222 } 223 224 225 /* 226 Find a variable by its run-time offset. 227 If the variable with a desired run-time offset is not found in this 228 context frame, it's recursively searched on parent context frames. 229 230 Note, context frames can have holes: 231 CREATE PROCEDURE p1() AS 232 x0 INT:=100; 233 CURSOR cur(p0 INT, p1 INT) IS SELECT p0, p1; 234 x1 INT:=101; 235 BEGIN 236 ... 237 END; 238 The variables (x0 and x1) and the cursor parameters (p0 and p1) 239 reside in separate parse context frames. 240 241 The variables reside on the top level parse context frame: 242 - x0 has frame offset 0 and run-time offset 0 243 - x1 has frame offset 1 and run-time offset 3 244 245 The cursor parameters reside on the second level parse context frame: 246 - p0 has frame offset 0 and run-time offset 1 247 - p1 has frame offset 1 and run-time offset 2 248 249 Run-time offsets on a frame can have holes, but offsets monotonocally grow, 250 so run-time offsets of all variables are not greater than the run-time offset 251 of the very last variable in this frame. 252 */ 253 sp_variable *sp_pcontext::find_variable(uint offset) const 254 { 255 if (m_var_offset <= offset && 256 m_vars.elements() && 257 offset <= get_last_context_variable()->offset) 258 { 259 for (uint i= 0; i < m_vars.elements(); i++) 260 { 261 if (m_vars.at(i)->offset == offset) 262 return m_vars.at(i); // This frame 263 } 264 } 265 266 return m_parent ? 267 m_parent->find_variable(offset) : // Some previous frame 268 NULL; // Index out of bounds 269 } 270 271 272 sp_variable *sp_pcontext::add_variable(THD *thd, const LEX_CSTRING *name) 273 { 274 sp_variable *p= 275 new (thd->mem_root) sp_variable(name, m_var_offset + m_max_var_index); 276 277 if (!p) 278 return NULL; 279 280 ++m_max_var_index; 281 282 return m_vars.append(p) ? NULL : p; 283 } 284 285 sp_label *sp_pcontext::push_label(THD *thd, const LEX_CSTRING *name, uint ip, 286 sp_label::enum_type type, 287 List<sp_label> *list) 288 { 289 sp_label *label= 290 new (thd->mem_root) sp_label(name, ip, type, this); 291 292 if (!label) 293 return NULL; 294 295 list->push_front(label, thd->mem_root); 296 297 return label; 298 } 299 300 sp_label *sp_pcontext::find_goto_label(const LEX_CSTRING *name, bool recusive) 301 { 302 List_iterator_fast<sp_label> li(m_goto_labels); 303 sp_label *lab; 304 305 while ((lab= li++)) 306 { 307 if (lex_string_cmp(system_charset_info, name, &lab->name) == 0) 308 return lab; 309 } 310 311 if (!recusive) 312 return NULL; 313 314 /* 315 Note about exception handlers. 316 See SQL:2003 SQL/PSM (ISO/IEC 9075-4:2003), 317 section 13.1 <compound statement>, 318 syntax rule 4. 319 In short, a DECLARE HANDLER block can not refer 320 to labels from the parent context, as they are out of scope. 321 */ 322 if (m_scope == HANDLER_SCOPE && m_parent) 323 { 324 if (m_parent->m_parent) 325 { 326 // Skip the parent context 327 return m_parent->m_parent->find_goto_label(name); 328 } 329 } 330 331 return m_parent && (m_scope == REGULAR_SCOPE) ? 332 m_parent->find_goto_label(name) : 333 NULL; 334 } 335 336 337 sp_label *sp_pcontext::find_label(const LEX_CSTRING *name) 338 { 339 List_iterator_fast<sp_label> li(m_labels); 340 sp_label *lab; 341 342 while ((lab= li++)) 343 { 344 if (lex_string_cmp(system_charset_info, name, &lab->name) == 0) 345 return lab; 346 } 347 348 /* 349 Note about exception handlers. 350 See SQL:2003 SQL/PSM (ISO/IEC 9075-4:2003), 351 section 13.1 <compound statement>, 352 syntax rule 4. 353 In short, a DECLARE HANDLER block can not refer 354 to labels from the parent context, as they are out of scope. 355 */ 356 return (m_parent && (m_scope == REGULAR_SCOPE)) ? 357 m_parent->find_label(name) : 358 NULL; 359 } 360 361 362 sp_label *sp_pcontext::find_label_current_loop_start() 363 { 364 List_iterator_fast<sp_label> li(m_labels); 365 sp_label *lab; 366 367 while ((lab= li++)) 368 { 369 if (lab->type == sp_label::ITERATION) 370 return lab; 371 } 372 // See a comment in sp_pcontext::find_label() 373 return (m_parent && (m_scope == REGULAR_SCOPE)) ? 374 m_parent->find_label_current_loop_start() : 375 NULL; 376 } 377 378 379 bool sp_pcontext::add_condition(THD *thd, 380 const LEX_CSTRING *name, 381 sp_condition_value *value) 382 { 383 sp_condition *p= new (thd->mem_root) sp_condition(name, value); 384 385 if (p == NULL) 386 return true; 387 388 return m_conditions.append(p); 389 } 390 391 392 sp_condition_value *sp_pcontext::find_condition(const LEX_CSTRING *name, 393 bool current_scope_only) const 394 { 395 size_t i= m_conditions.elements(); 396 397 while (i--) 398 { 399 sp_condition *p= m_conditions.at(i); 400 401 if (p->eq_name(name)) 402 { 403 return p->value; 404 } 405 } 406 407 return (!current_scope_only && m_parent) ? 408 m_parent->find_condition(name, false) : 409 NULL; 410 } 411 412 sp_condition_value * 413 sp_pcontext::find_declared_or_predefined_condition(THD *thd, 414 const LEX_CSTRING *name) 415 const 416 { 417 sp_condition_value *p= find_condition(name, false); 418 if (p) 419 return p; 420 if (thd->variables.sql_mode & MODE_ORACLE) 421 return find_predefined_condition(name); 422 return NULL; 423 } 424 425 426 static sp_condition_value 427 // Warnings 428 cond_no_data_found(ER_SP_FETCH_NO_DATA, "01000"), 429 // Errors 430 cond_invalid_cursor(ER_SP_CURSOR_NOT_OPEN, "24000"), 431 cond_dup_val_on_index(ER_DUP_ENTRY, "23000"), 432 cond_dup_val_on_index2(ER_DUP_ENTRY_WITH_KEY_NAME, "23000"), 433 cond_too_many_rows(ER_TOO_MANY_ROWS, "42000"); 434 435 436 static sp_condition sp_predefined_conditions[]= 437 { 438 // Warnings 439 sp_condition(STRING_WITH_LEN("NO_DATA_FOUND"), &cond_no_data_found), 440 // Errors 441 sp_condition(STRING_WITH_LEN("INVALID_CURSOR"), &cond_invalid_cursor), 442 sp_condition(STRING_WITH_LEN("DUP_VAL_ON_INDEX"), &cond_dup_val_on_index), 443 sp_condition(STRING_WITH_LEN("DUP_VAL_ON_INDEX"), &cond_dup_val_on_index2), 444 sp_condition(STRING_WITH_LEN("TOO_MANY_ROWS"), &cond_too_many_rows) 445 }; 446 447 448 sp_condition_value * 449 sp_pcontext::find_predefined_condition(const LEX_CSTRING *name) const 450 { 451 for (uint i= 0; i < array_elements(sp_predefined_conditions) ; i++) 452 { 453 if (sp_predefined_conditions[i].eq_name(name)) 454 return sp_predefined_conditions[i].value; 455 } 456 return NULL; 457 } 458 459 460 sp_handler *sp_pcontext::add_handler(THD *thd, 461 sp_handler::enum_type type) 462 { 463 sp_handler *h= new (thd->mem_root) sp_handler(type); 464 465 if (!h) 466 return NULL; 467 468 return m_handlers.append(h) ? NULL : h; 469 } 470 471 472 bool sp_pcontext::check_duplicate_handler( 473 const sp_condition_value *cond_value) const 474 { 475 for (size_t i= 0; i < m_handlers.elements(); ++i) 476 { 477 sp_handler *h= m_handlers.at(i); 478 479 List_iterator_fast<sp_condition_value> li(h->condition_values); 480 sp_condition_value *cv; 481 482 while ((cv= li++)) 483 { 484 if (cond_value->equals(cv)) 485 return true; 486 } 487 } 488 489 return false; 490 } 491 492 493 bool sp_condition_value::matches(const Sql_condition_identity &value, 494 const sp_condition_value *found_cv) const 495 { 496 bool user_value_matched= !value.get_user_condition_value() || 497 this == value.get_user_condition_value(); 498 499 switch (type) 500 { 501 case sp_condition_value::ERROR_CODE: 502 return user_value_matched && 503 value.get_sql_errno() == get_sql_errno() && 504 (!found_cv || found_cv->type > sp_condition_value::ERROR_CODE); 505 506 case sp_condition_value::SQLSTATE: 507 return user_value_matched && 508 Sql_state::eq(&value) && 509 (!found_cv || found_cv->type > sp_condition_value::SQLSTATE); 510 511 case sp_condition_value::WARNING: 512 return user_value_matched && 513 (value.Sql_state::is_warning() || 514 value.get_level() == Sql_condition::WARN_LEVEL_WARN) && 515 !found_cv; 516 517 case sp_condition_value::NOT_FOUND: 518 return user_value_matched && 519 value.Sql_state::is_not_found() && 520 !found_cv; 521 522 case sp_condition_value::EXCEPTION: 523 /* 524 In sql_mode=ORACLE this construct should catch both errors and warnings: 525 EXCEPTION 526 WHEN OTHERS THEN ...; 527 E.g. NO_DATA_FOUND is more like a warning than an error, 528 and it should be caught. 529 530 We don't check user_value_matched here. 531 "WHEN OTHERS" catches all user defined exception. 532 */ 533 return (((current_thd->variables.sql_mode & MODE_ORACLE) || 534 (value.Sql_state::is_exception() && 535 value.get_level() == Sql_condition::WARN_LEVEL_ERROR)) && 536 !found_cv); 537 } 538 return false; 539 } 540 541 542 sp_handler* 543 sp_pcontext::find_handler(const Sql_condition_identity &value) const 544 { 545 sp_handler *found_handler= NULL; 546 sp_condition_value *found_cv= NULL; 547 548 for (size_t i= 0; i < m_handlers.elements(); ++i) 549 { 550 sp_handler *h= m_handlers.at(i); 551 552 List_iterator_fast<sp_condition_value> li(h->condition_values); 553 sp_condition_value *cv; 554 555 while ((cv= li++)) 556 { 557 if (cv->matches(value, found_cv)) 558 { 559 found_cv= cv; 560 found_handler= h; 561 } 562 } 563 } 564 565 if (found_handler) 566 return found_handler; 567 568 569 // There is no appropriate handler in this parsing context. We need to look up 570 // in parent contexts. There might be two cases here: 571 // 572 // 1. The current context has REGULAR_SCOPE. That means, it's a simple 573 // BEGIN..END block: 574 // ... 575 // BEGIN 576 // ... # We're here. 577 // END 578 // ... 579 // In this case we simply call find_handler() on parent's context recursively. 580 // 581 // 2. The current context has HANDLER_SCOPE. That means, we're inside an 582 // SQL-handler block: 583 // ... 584 // DECLARE ... HANDLER FOR ... 585 // BEGIN 586 // ... # We're here. 587 // END 588 // ... 589 // In this case we can not just call parent's find_handler(), because 590 // parent's handler don't catch conditions from this scope. Instead, we should 591 // try to find first parent context (we might have nested handler 592 // declarations), which has REGULAR_SCOPE (i.e. which is regular BEGIN..END 593 // block). 594 595 const sp_pcontext *p= this; 596 597 while (p && p->m_scope == HANDLER_SCOPE) 598 p= p->m_parent; 599 600 if (!p || !p->m_parent) 601 return NULL; 602 603 return p->m_parent->find_handler(value); 604 } 605 606 607 bool sp_pcontext::add_cursor(const LEX_CSTRING *name, sp_pcontext *param_ctx, 608 sp_lex_cursor *lex) 609 { 610 if (m_cursors.elements() == m_max_cursor_index) 611 ++m_max_cursor_index; 612 613 return m_cursors.append(sp_pcursor(name, param_ctx, lex)); 614 } 615 616 617 const sp_pcursor *sp_pcontext::find_cursor(const LEX_CSTRING *name, 618 uint *poff, 619 bool current_scope_only) const 620 { 621 uint i= (uint)m_cursors.elements(); 622 623 while (i--) 624 { 625 LEX_CSTRING n= m_cursors.at(i); 626 627 if (my_strnncoll(system_charset_info, 628 (const uchar *) name->str, name->length, 629 (const uchar *) n.str, n.length) == 0) 630 { 631 *poff= m_cursor_offset + i; 632 return &m_cursors.at(i); 633 } 634 } 635 636 return (!current_scope_only && m_parent) ? 637 m_parent->find_cursor(name, poff, false) : 638 NULL; 639 } 640 641 642 void sp_pcontext::retrieve_field_definitions( 643 List<Spvar_definition> *field_def_lst) const 644 { 645 /* Put local/context fields in the result list. */ 646 647 size_t next_child= 0; 648 for (size_t i= 0; i < m_vars.elements(); ++i) 649 { 650 sp_variable *var_def= m_vars.at(i); 651 652 /* 653 The context can have holes in run-time offsets, 654 the missing offsets reside on the children contexts in such cases. 655 Example: 656 CREATE PROCEDURE p1() AS 657 x0 INT:=100; -- context 0, position 0, run-time 0 658 CURSOR cur( 659 p0 INT, -- context 1, position 0, run-time 1 660 p1 INT -- context 1, position 1, run-time 2 661 ) IS SELECT p0, p1; 662 x1 INT:=101; -- context 0, position 1, run-time 3 663 BEGIN 664 ... 665 END; 666 See more comments in sp_pcontext::find_variable(). 667 We must retrieve the definitions in the order of their run-time offsets. 668 Check that there are children that should go before the current variable. 669 */ 670 for ( ; next_child < m_children.elements(); next_child++) 671 { 672 sp_pcontext *child= m_children.at(next_child); 673 if (!child->context_var_count() || 674 child->get_context_variable(0)->offset > var_def->offset) 675 break; 676 /* 677 All variables on the embedded context (that fills holes of the parent) 678 should have the run-time offset strictly less than var_def. 679 */ 680 DBUG_ASSERT(child->get_context_variable(0)->offset < var_def->offset); 681 DBUG_ASSERT(child->get_last_context_variable()->offset < var_def->offset); 682 child->retrieve_field_definitions(field_def_lst); 683 } 684 field_def_lst->push_back(&var_def->field_def); 685 } 686 687 /* Put the fields of the remaining enclosed contexts in the result list. */ 688 689 for (size_t i= next_child; i < m_children.elements(); ++i) 690 m_children.at(i)->retrieve_field_definitions(field_def_lst); 691 } 692 693 694 const sp_pcursor *sp_pcontext::find_cursor(uint offset) const 695 { 696 if (m_cursor_offset <= offset && 697 offset < m_cursor_offset + m_cursors.elements()) 698 { 699 return &m_cursors.at(offset - m_cursor_offset); // This frame 700 } 701 702 return m_parent ? 703 m_parent->find_cursor(offset) : // Some previous frame 704 NULL; // Index out of bounds 705 } 706 707 708 bool sp_pcursor::check_param_count_with_error(uint param_count) const 709 { 710 if (param_count != (m_param_context ? 711 m_param_context->context_var_count() : 0)) 712 { 713 my_error(ER_WRONG_PARAMCOUNT_TO_CURSOR, MYF(0), LEX_CSTRING::str); 714 return true; 715 } 716 return false; 717 } 718 719 720 const Spvar_definition * 721 sp_variable::find_row_field(const LEX_CSTRING *var_name, 722 const LEX_CSTRING *field_name, 723 uint *row_field_offset) 724 { 725 if (!field_def.is_row()) 726 { 727 my_printf_error(ER_UNKNOWN_ERROR, 728 "'%s' is not a row variable", MYF(0), var_name->str); 729 return NULL; 730 } 731 const Spvar_definition *def; 732 if ((def= field_def.find_row_field_by_name(field_name, row_field_offset))) 733 return def; 734 my_error(ER_ROW_VARIABLE_DOES_NOT_HAVE_FIELD, MYF(0), 735 var_name->str, field_name->str); 736 return NULL; 737 } 738