diff options
author | Oleksandr Byelkin <sanja@sanjaLaptopT> | 2017-12-20 13:52:27 +0100 |
---|---|---|
committer | Oleksandr Byelkin <sanja@mariadb.com> | 2017-12-27 16:01:37 +0100 |
commit | 462808f3b65b60958eaf8013b80857e341cc9f6c (patch) | |
tree | 24af784d839c132fb74c3cd99d46d6fd86ce8161 | |
parent | 924db8b4ed3f268cbe91a1734611f4dc2311c7be (diff) | |
download | mariadb-git-462808f3b65b60958eaf8013b80857e341cc9f6c.tar.gz |
MDEV-10657: incorrect result returned with binary protocol (prepared statements)
If translation table present when we materialize the derived table then
change it to point to the materialized table.
Added debug info to see really what happens with what derived.
-rw-r--r-- | mysql-test/r/ps.result | 18 | ||||
-rw-r--r-- | mysql-test/t/ps.test | 15 | ||||
-rw-r--r-- | sql/sql_class.cc | 9 | ||||
-rw-r--r-- | sql/sql_derived.cc | 48 | ||||
-rw-r--r-- | sql/table.cc | 3 | ||||
-rw-r--r-- | sql/table.h | 6 |
6 files changed, 96 insertions, 3 deletions
diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result index 3fed0a5b0d1..209d3d85108 100644 --- a/mysql-test/r/ps.result +++ b/mysql-test/r/ps.result @@ -4316,4 +4316,22 @@ set join_cache_level=@join_cache_level_save; deallocate prepare stmt; drop view v1,v2,v3; drop table t1,t2,t3; +# +# MDEV-10657: incorrect result returned with binary protocol +# (prepared statements) +# +create table t1 (code varchar(10) primary key); +INSERT INTO t1(code) VALUES ('LINE1'), ('LINE2'), ('LINE3'); +SELECT X.* +FROM +(SELECT CODE, RN +FROM +(SELECT A.CODE, @cnt := @cnt + 1 AS RN +FROM t1 A, (SELECT @cnt := 0) C) T +) X; +CODE RN +LINE1 1 +LINE2 2 +LINE3 3 +drop table t1; # End of 5.5 tests diff --git a/mysql-test/t/ps.test b/mysql-test/t/ps.test index 4431f722ae0..ea67e1074f9 100644 --- a/mysql-test/t/ps.test +++ b/mysql-test/t/ps.test @@ -3843,4 +3843,19 @@ deallocate prepare stmt; drop view v1,v2,v3; drop table t1,t2,t3; +--echo # +--echo # MDEV-10657: incorrect result returned with binary protocol +--echo # (prepared statements) +--echo # + +create table t1 (code varchar(10) primary key); +INSERT INTO t1(code) VALUES ('LINE1'), ('LINE2'), ('LINE3'); +SELECT X.* +FROM + (SELECT CODE, RN + FROM + (SELECT A.CODE, @cnt := @cnt + 1 AS RN + FROM t1 A, (SELECT @cnt := 0) C) T + ) X; +drop table t1; --echo # End of 5.5 tests diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 00d860e7887..b007729494e 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -2192,6 +2192,8 @@ void THD::nocheck_register_item_tree_change(Item **place, Item *old_value, MEM_ROOT *runtime_memroot) { Item_change_record *change; + DBUG_ENTER("THD::nocheck_register_item_tree_change"); + DBUG_PRINT("enter", ("Register %p <- %p", old_value, (*place))); /* Now we use one node per change, which adds some memory overhead, but still is rather fast as we use alloc_root for allocations. @@ -2204,12 +2206,13 @@ void THD::nocheck_register_item_tree_change(Item **place, Item *old_value, OOM, thd->fatal_error() is called by the error handler of the memroot. Just return. */ - return; + DBUG_VOID_RETURN; } change= new (change_mem) Item_change_record; change->place= place; change->old_value= old_value; change_list.append(change); + DBUG_VOID_RETURN; } /** @@ -2250,7 +2253,11 @@ void THD::rollback_item_tree_changes() DBUG_ENTER("rollback_item_tree_changes"); while ((change= it++)) + { + DBUG_PRINT("info", ("revert %p -> %p", + change->old_value, (*change->place))); *change->place= change->old_value; + } /* We can forget about changes memory: it's allocated in runtime memroot */ change_list.empty(); DBUG_VOID_RETURN; diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc index 6cd4547aaf9..2a6d82c161a 100644 --- a/sql/sql_derived.cc +++ b/sql/sql_derived.cc @@ -361,6 +361,9 @@ bool mysql_derived_merge(THD *thd, LEX *lex, TABLE_LIST *derived) SELECT_LEX *parent_lex= derived->select_lex; Query_arena *arena, backup; DBUG_ENTER("mysql_derived_merge"); + DBUG_PRINT("enter", ("Alias: '%s' Unit: %p", + (derived->alias ? derived->alias : "<NULL>"), + derived->get_unit())); if (derived->merged) DBUG_RETURN(FALSE); @@ -508,6 +511,9 @@ unconditional_materialization: bool mysql_derived_merge_for_insert(THD *thd, LEX *lex, TABLE_LIST *derived) { DBUG_ENTER("mysql_derived_merge_for_insert"); + DBUG_PRINT("enter", ("Alias: '%s' Unit: %p", + (derived->alias ? derived->alias : "<NULL>"), + derived->get_unit())); if (derived->merged_for_insert) DBUG_RETURN(FALSE); if (derived->init_derived(thd, FALSE)) @@ -554,6 +560,9 @@ bool mysql_derived_init(THD *thd, LEX *lex, TABLE_LIST *derived) { SELECT_LEX_UNIT *unit= derived->get_unit(); DBUG_ENTER("mysql_derived_init"); + DBUG_PRINT("enter", ("Alias: '%s' Unit: %p", + (derived->alias ? derived->alias : "<NULL>"), + derived->get_unit())); // Skip already prepared views/DT if (!unit || unit->prepared) @@ -624,7 +633,9 @@ bool mysql_derived_prepare(THD *thd, LEX *lex, TABLE_LIST *derived) SELECT_LEX_UNIT *unit= derived->get_unit(); DBUG_ENTER("mysql_derived_prepare"); bool res= FALSE; - DBUG_PRINT("enter", ("unit 0x%lx", (ulong) unit)); + DBUG_PRINT("enter", ("Alias: '%s' Unit: %p", + (derived->alias ? derived->alias : "<NULL>"), + derived->get_unit())); // Skip already prepared views/DT if (!unit || unit->prepared || @@ -781,6 +792,9 @@ bool mysql_derived_optimize(THD *thd, LEX *lex, TABLE_LIST *derived) bool res= FALSE; DBUG_ENTER("mysql_derived_optimize"); + DBUG_PRINT("enter", ("Alias: '%s' Unit: %p", + (derived->alias ? derived->alias : "<NULL>"), + derived->get_unit())); if (unit->optimized) DBUG_RETURN(FALSE); @@ -846,6 +860,9 @@ err: bool mysql_derived_create(THD *thd, LEX *lex, TABLE_LIST *derived) { DBUG_ENTER("mysql_derived_create"); + DBUG_PRINT("enter", ("Alias: '%s' Unit: %p", + (derived->alias ? derived->alias : "<NULL>"), + derived->get_unit())); TABLE *table= derived->table; SELECT_LEX_UNIT *unit= derived->get_unit(); @@ -895,9 +912,13 @@ bool mysql_derived_create(THD *thd, LEX *lex, TABLE_LIST *derived) bool mysql_derived_fill(THD *thd, LEX *lex, TABLE_LIST *derived) { - DBUG_ENTER("mysql_derived_fill"); + Field_iterator_table field_iterator; SELECT_LEX_UNIT *unit= derived->get_unit(); bool res= FALSE; + DBUG_ENTER("mysql_derived_fill"); + DBUG_PRINT("enter", ("Alias: '%s' Unit: %p", + (derived->alias ? derived->alias : "<NULL>"), + derived->get_unit())); if (unit->executed && !unit->uncacheable && !unit->describe) DBUG_RETURN(FALSE); @@ -937,7 +958,27 @@ bool mysql_derived_fill(THD *thd, LEX *lex, TABLE_LIST *derived) if (derived_result->flush()) res= TRUE; unit->executed= TRUE; + + if (derived->field_translation) + { + /* reset translation table to materialized table */ + field_iterator.set_table(derived->table); + for (uint i= 0; + !field_iterator.end_of_fields(); + field_iterator.next(), i= i + 1) + { + Item *item; + + if (!(item= field_iterator.create_item(thd))) + { + res= TRUE; + break; + } + thd->change_item_tree(&derived->field_translation[i].item, item); + } + } } + if (res || !lex->describe) unit->cleanup(); lex->current_select= save_current_select; @@ -966,6 +1007,9 @@ bool mysql_derived_fill(THD *thd, LEX *lex, TABLE_LIST *derived) bool mysql_derived_reinit(THD *thd, LEX *lex, TABLE_LIST *derived) { DBUG_ENTER("mysql_derived_reinit"); + DBUG_PRINT("enter", ("Alias: '%s' Unit: %p", + (derived->alias ? derived->alias : "<NULL>"), + derived->get_unit())); st_select_lex_unit *unit= derived->get_unit(); if (derived->table) diff --git a/sql/table.cc b/sql/table.cc index fbcd91f5326..9cade76cb78 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -4108,6 +4108,9 @@ bool TABLE_LIST::create_field_translation(THD *thd) Query_arena *arena, backup; bool res= FALSE; DBUG_ENTER("TABLE_LIST::create_field_translation"); + DBUG_PRINT("enter", ("Alias: '%s' Unit: %p", + (alias ? alias : "<NULL>"), + get_unit())); if (thd->stmt_arena->is_conventional() || thd->stmt_arena->is_stmt_prepare_or_first_sp_execute()) diff --git a/sql/table.h b/sql/table.h index c981243f28c..98f8c7ad73f 100644 --- a/sql/table.h +++ b/sql/table.h @@ -2107,6 +2107,9 @@ struct TABLE_LIST inline void set_merged_derived() { DBUG_ENTER("set_merged_derived"); + DBUG_PRINT("enter", ("Alias: '%s' Unit: %p", + (alias ? alias : "<NULL>"), + get_unit())); derived_type= ((derived_type & DTYPE_MASK) | DTYPE_TABLE | DTYPE_MERGE); set_check_merged(); @@ -2119,6 +2122,9 @@ struct TABLE_LIST void set_materialized_derived() { DBUG_ENTER("set_materialized_derived"); + DBUG_PRINT("enter", ("Alias: '%s' Unit: %p", + (alias ? alias : "<NULL>"), + get_unit())); derived_type= ((derived_type & (derived ? DTYPE_MASK : DTYPE_VIEW)) | DTYPE_TABLE | DTYPE_MATERIALIZE); set_check_materialized(); |