1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-27 18:02:13 +03:00

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.
This commit is contained in:
Oleksandr Byelkin
2017-12-20 13:52:27 +01:00
committed by Oleksandr Byelkin
parent 924db8b4ed
commit 462808f3b6
6 changed files with 96 additions and 3 deletions

View File

@ -4316,4 +4316,22 @@ set join_cache_level=@join_cache_level_save;
deallocate prepare stmt; deallocate prepare stmt;
drop view v1,v2,v3; drop view v1,v2,v3;
drop table t1,t2,t3; 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 # End of 5.5 tests

View File

@ -3843,4 +3843,19 @@ deallocate prepare stmt;
drop view v1,v2,v3; drop view v1,v2,v3;
drop table t1,t2,t3; 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 --echo # End of 5.5 tests

View File

@ -2192,6 +2192,8 @@ void THD::nocheck_register_item_tree_change(Item **place, Item *old_value,
MEM_ROOT *runtime_memroot) MEM_ROOT *runtime_memroot)
{ {
Item_change_record *change; 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, Now we use one node per change, which adds some memory overhead,
but still is rather fast as we use alloc_root for allocations. 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 OOM, thd->fatal_error() is called by the error handler of the
memroot. Just return. memroot. Just return.
*/ */
return; DBUG_VOID_RETURN;
} }
change= new (change_mem) Item_change_record; change= new (change_mem) Item_change_record;
change->place= place; change->place= place;
change->old_value= old_value; change->old_value= old_value;
change_list.append(change); change_list.append(change);
DBUG_VOID_RETURN;
} }
/** /**
@ -2250,7 +2253,11 @@ void THD::rollback_item_tree_changes()
DBUG_ENTER("rollback_item_tree_changes"); DBUG_ENTER("rollback_item_tree_changes");
while ((change= it++)) while ((change= it++))
{
DBUG_PRINT("info", ("revert %p -> %p",
change->old_value, (*change->place)));
*change->place= change->old_value; *change->place= change->old_value;
}
/* We can forget about changes memory: it's allocated in runtime memroot */ /* We can forget about changes memory: it's allocated in runtime memroot */
change_list.empty(); change_list.empty();
DBUG_VOID_RETURN; DBUG_VOID_RETURN;

View File

@ -361,6 +361,9 @@ bool mysql_derived_merge(THD *thd, LEX *lex, TABLE_LIST *derived)
SELECT_LEX *parent_lex= derived->select_lex; SELECT_LEX *parent_lex= derived->select_lex;
Query_arena *arena, backup; Query_arena *arena, backup;
DBUG_ENTER("mysql_derived_merge"); DBUG_ENTER("mysql_derived_merge");
DBUG_PRINT("enter", ("Alias: '%s' Unit: %p",
(derived->alias ? derived->alias : "<NULL>"),
derived->get_unit()));
if (derived->merged) if (derived->merged)
DBUG_RETURN(FALSE); DBUG_RETURN(FALSE);
@ -508,6 +511,9 @@ unconditional_materialization:
bool mysql_derived_merge_for_insert(THD *thd, LEX *lex, TABLE_LIST *derived) bool mysql_derived_merge_for_insert(THD *thd, LEX *lex, TABLE_LIST *derived)
{ {
DBUG_ENTER("mysql_derived_merge_for_insert"); 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) if (derived->merged_for_insert)
DBUG_RETURN(FALSE); DBUG_RETURN(FALSE);
if (derived->init_derived(thd, 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(); SELECT_LEX_UNIT *unit= derived->get_unit();
DBUG_ENTER("mysql_derived_init"); 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 // Skip already prepared views/DT
if (!unit || unit->prepared) 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(); SELECT_LEX_UNIT *unit= derived->get_unit();
DBUG_ENTER("mysql_derived_prepare"); DBUG_ENTER("mysql_derived_prepare");
bool res= FALSE; 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 // Skip already prepared views/DT
if (!unit || unit->prepared || if (!unit || unit->prepared ||
@ -781,6 +792,9 @@ bool mysql_derived_optimize(THD *thd, LEX *lex, TABLE_LIST *derived)
bool res= FALSE; bool res= FALSE;
DBUG_ENTER("mysql_derived_optimize"); DBUG_ENTER("mysql_derived_optimize");
DBUG_PRINT("enter", ("Alias: '%s' Unit: %p",
(derived->alias ? derived->alias : "<NULL>"),
derived->get_unit()));
if (unit->optimized) if (unit->optimized)
DBUG_RETURN(FALSE); DBUG_RETURN(FALSE);
@ -846,6 +860,9 @@ err:
bool mysql_derived_create(THD *thd, LEX *lex, TABLE_LIST *derived) bool mysql_derived_create(THD *thd, LEX *lex, TABLE_LIST *derived)
{ {
DBUG_ENTER("mysql_derived_create"); DBUG_ENTER("mysql_derived_create");
DBUG_PRINT("enter", ("Alias: '%s' Unit: %p",
(derived->alias ? derived->alias : "<NULL>"),
derived->get_unit()));
TABLE *table= derived->table; TABLE *table= derived->table;
SELECT_LEX_UNIT *unit= derived->get_unit(); 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) 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(); SELECT_LEX_UNIT *unit= derived->get_unit();
bool res= FALSE; 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) if (unit->executed && !unit->uncacheable && !unit->describe)
DBUG_RETURN(FALSE); DBUG_RETURN(FALSE);
@ -937,7 +958,27 @@ bool mysql_derived_fill(THD *thd, LEX *lex, TABLE_LIST *derived)
if (derived_result->flush()) if (derived_result->flush())
res= TRUE; res= TRUE;
unit->executed= 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) if (res || !lex->describe)
unit->cleanup(); unit->cleanup();
lex->current_select= save_current_select; 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) bool mysql_derived_reinit(THD *thd, LEX *lex, TABLE_LIST *derived)
{ {
DBUG_ENTER("mysql_derived_reinit"); 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(); st_select_lex_unit *unit= derived->get_unit();
if (derived->table) if (derived->table)

View File

@ -4108,6 +4108,9 @@ bool TABLE_LIST::create_field_translation(THD *thd)
Query_arena *arena, backup; Query_arena *arena, backup;
bool res= FALSE; bool res= FALSE;
DBUG_ENTER("TABLE_LIST::create_field_translation"); 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() || if (thd->stmt_arena->is_conventional() ||
thd->stmt_arena->is_stmt_prepare_or_first_sp_execute()) thd->stmt_arena->is_stmt_prepare_or_first_sp_execute())

View File

@ -2107,6 +2107,9 @@ struct TABLE_LIST
inline void set_merged_derived() inline void set_merged_derived()
{ {
DBUG_ENTER("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) | derived_type= ((derived_type & DTYPE_MASK) |
DTYPE_TABLE | DTYPE_MERGE); DTYPE_TABLE | DTYPE_MERGE);
set_check_merged(); set_check_merged();
@ -2119,6 +2122,9 @@ struct TABLE_LIST
void set_materialized_derived() void set_materialized_derived()
{ {
DBUG_ENTER("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)) | derived_type= ((derived_type & (derived ? DTYPE_MASK : DTYPE_VIEW)) |
DTYPE_TABLE | DTYPE_MATERIALIZE); DTYPE_TABLE | DTYPE_MATERIALIZE);
set_check_materialized(); set_check_materialized();