From 36ba58cb759e2a78ee1492d995e4e45a4b23fe03 Mon Sep 17 00:00:00 2001 From: Monty Date: Wed, 3 Jan 2018 00:12:36 +0200 Subject: [PATCH] Fixed that sequences and default works with ps-protocol The bug was that for prepared statments the new TABLE_LIST was allocated in the wrong arena. --- mysql-test/suite/sql_sequence/default.result | 16 +++++++ mysql-test/suite/sql_sequence/default.test | 14 ++++++ sql/sql_base.cc | 45 ++++++++++++++++---- 3 files changed, 67 insertions(+), 8 deletions(-) diff --git a/mysql-test/suite/sql_sequence/default.result b/mysql-test/suite/sql_sequence/default.result index 3c22ea296ca..37d536d9020 100644 --- a/mysql-test/suite/sql_sequence/default.result +++ b/mysql-test/suite/sql_sequence/default.result @@ -152,6 +152,22 @@ UNLOCK TABLES; drop table t1; drop sequence s1; # +# Testing prepared statements +# +CREATE or replace SEQUENCE s1 nocache engine=myisam; +CREATE or replace table t1 (a int default next value for s1, b int); +PREPARE stmt FROM "insert into t1 (b) values(?)"; +execute stmt using 1; +execute stmt using 2; +execute stmt using 3; +select * from t1; +a b +1 1 +2 2 +3 3 +drop table t1,s1; +deallocate prepare stmt; +# # Wrong usage of default # CREATE table t1 (a int default next value for s1, b int); diff --git a/mysql-test/suite/sql_sequence/default.test b/mysql-test/suite/sql_sequence/default.test index 2c527246eff..017165c1a80 100644 --- a/mysql-test/suite/sql_sequence/default.test +++ b/mysql-test/suite/sql_sequence/default.test @@ -90,6 +90,20 @@ UNLOCK TABLES; drop table t1; drop sequence s1; +--echo # +--echo # Testing prepared statements +--echo # + +CREATE or replace SEQUENCE s1 nocache engine=myisam; +CREATE or replace table t1 (a int default next value for s1, b int); +PREPARE stmt FROM "insert into t1 (b) values(?)"; +execute stmt using 1; +execute stmt using 2; +execute stmt using 3; +select * from t1; +drop table t1,s1; +deallocate prepare stmt; + --echo # --echo # Wrong usage of default --echo # diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 31cb973551f..af6012a3e2b 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -4243,12 +4243,33 @@ static bool table_already_fk_prelocked(TABLE_LIST *tl, LEX_CSTRING *db, } -static bool -add_internal_tables(THD *thd, Query_tables_list *prelocking_ctx, - TABLE_LIST *global_table_list, TABLE_LIST *tables) +static bool internal_table_exists(TABLE_LIST *global_list, + const char *table_name) { do { + if (global_list->table_name == table_name) + return 1; + } while ((global_list= global_list->next_global)); + return 0; +} + + +static bool +add_internal_tables(THD *thd, Query_tables_list *prelocking_ctx, + TABLE_LIST *tables) +{ + TABLE_LIST *global_table_list= prelocking_ctx->query_tables; + + do + { + /* + Skip table if already in the list. Can happen with prepared statements + */ + if (tables->next_local && + internal_table_exists(global_table_list, tables->table_name)) + continue; + TABLE_LIST *tl= (TABLE_LIST *) thd->alloc(sizeof(TABLE_LIST)); if (!tl) return TRUE; @@ -4368,12 +4389,20 @@ handle_table(THD *thd, Query_tables_list *prelocking_ctx, /* Open any tables used by DEFAULT (like sequence tables) */ if (table->internal_tables && ((sql_command_flags[thd->lex->sql_command] & CF_INSERTS_DATA) || - thd->lex->default_used) && - add_internal_tables(thd, prelocking_ctx, table_list, - table->internal_tables)) + thd->lex->default_used)) { - *need_prelocking= TRUE; - return TRUE; + Query_arena *arena, backup; + bool error; + arena= thd->activate_stmt_arena_if_needed(&backup); + error= add_internal_tables(thd, prelocking_ctx, + table->internal_tables); + if (arena) + thd->restore_active_arena(arena, &backup); + if (error) + { + *need_prelocking= TRUE; + return TRUE; + } } return FALSE; }