|
1 |
| -/* Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. |
| 1 | +/* Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved. |
2 | 2 |
|
3 | 3 | This program is free software; you can redistribute it and/or modify
|
4 | 4 | it under the terms of the GNU General Public License as published by
|
@@ -422,14 +422,49 @@ bool sp_lex_instr::reset_lex_and_exec_core(THD *thd,
|
422 | 422 | thd->rollback_item_tree_changes();
|
423 | 423 |
|
424 | 424 | /*
|
425 |
| - Update the state of the active arena if no errors on |
426 |
| - open_tables stage. |
| 425 | + Change state of current arena according to outcome of execution. |
| 426 | +
|
| 427 | + When entering this function, state is STMT_INITIALIZED_FOR_SP if this is |
| 428 | + the first execution, otherwise it is STMT_EXECUTED. |
| 429 | +
|
| 430 | + When an error occurs during opening tables, no execution takes place and |
| 431 | + no state change will take place. |
| 432 | +
|
| 433 | + When a re-prepare error is raised, the next execution will re-prepare the |
| 434 | + statement. To make sure that items are created in the statement mem_root, |
| 435 | + change state to STMT_INITIALIZED_FOR_SP. |
| 436 | +
|
| 437 | + In other cases, the state should become (or remain) STMT_EXECUTED. |
| 438 | + See Query_arena->state definition for explanation. |
| 439 | +
|
| 440 | + Some special handling of CREATE TABLE .... SELECT in an SP is required. The |
| 441 | + state is always set to STMT_INITIALIZED_FOR_SP in such a case. |
| 442 | +
|
| 443 | + Why is this necessary? A useful pointer would be to note how |
| 444 | + PREPARE/EXECUTE uses functions like select_like_stmt_test to implement |
| 445 | + CREATE TABLE .... SELECT. The SELECT part of the DDL is resolved first. |
| 446 | + Then there is an attempt to create the table. So in the execution phase, |
| 447 | + if "table exists" error occurs or flush table preceeds the execute, the |
| 448 | + item tree of the select is re-created and followed by an attempt to create |
| 449 | + the table. |
| 450 | +
|
| 451 | + But SP uses mysql_execute_command (which is used by the conventional |
| 452 | + execute) after doing a parse. This creates a problem for SP since it |
| 453 | + tries to preserve the item tree from the previous execution. |
427 | 454 | */
|
428 | 455 |
|
429 |
| - if (!rc || !thd->is_error() || |
430 |
| - (thd->get_stmt_da()->sql_errno() != ER_CANT_REOPEN_TABLE && |
431 |
| - thd->get_stmt_da()->sql_errno() != ER_NO_SUCH_TABLE && |
432 |
| - thd->get_stmt_da()->sql_errno() != ER_UPDATE_TABLE_USED)) |
| 456 | + bool reprepare_error= |
| 457 | + rc && thd->get_stmt_da()->sql_errno() == ER_NEED_REPREPARE; |
| 458 | + bool is_create_table_select= |
| 459 | + thd->lex && thd->lex->sql_command == SQLCOM_CREATE_TABLE && |
| 460 | + thd->lex->select_lex.item_list.elements > 0; |
| 461 | + |
| 462 | + if (reprepare_error || is_create_table_select) |
| 463 | + thd->stmt_arena->state= Query_arena::STMT_INITIALIZED_FOR_SP; |
| 464 | + else if (!rc || !thd->is_error() || |
| 465 | + (thd->get_stmt_da()->sql_errno() != ER_CANT_REOPEN_TABLE && |
| 466 | + thd->get_stmt_da()->sql_errno() != ER_NO_SUCH_TABLE && |
| 467 | + thd->get_stmt_da()->sql_errno() != ER_UPDATE_TABLE_USED)) |
433 | 468 | thd->stmt_arena->state= Query_arena::STMT_EXECUTED;
|
434 | 469 |
|
435 | 470 | /*
|
@@ -493,7 +528,7 @@ LEX *sp_lex_instr::parse_expr(THD *thd, sp_head *sp)
|
493 | 528 | initiated. Also set the statement query arena to the lex mem_root.
|
494 | 529 | */
|
495 | 530 | MEM_ROOT *execution_mem_root= thd->mem_root;
|
496 |
| - Query_arena parse_arena(&m_lex_mem_root, STMT_INITIALIZED_FOR_SP); |
| 531 | + Query_arena parse_arena(&m_lex_mem_root, thd->stmt_arena->state); |
497 | 532 |
|
498 | 533 | thd->mem_root= &m_lex_mem_root;
|
499 | 534 | thd->stmt_arena->set_query_arena(&parse_arena);
|
|
0 commit comments