Skip to content
Permalink
Browse files
Fixed MDEV-16512, crashing on re-execution of failing SP
MDEV-16512 Server crashes in find_field_in_table_ref on 2nd
execution of SP referring to non-existing field

Problem was in the natural join code that it changed TABLE_LIST and
Item_fields but didn't restore changed things if things goes wrong
and was not able to re-execute after failure.
Some of the problems could have been avoided if we would have run
fix_fields before doing natural join transformations.

Fixed by marking functions complete AFTER they had executed, instead at
start.
I had also to change some tests that checked if Item_fields are usable.

This doesn't fix all known problems, but at least avoids some crashes.
What should be done in the near future is to mark the statement in the SP
as 'not re-executable' and force a reparse of it on next execution.

Reviewer: Sergei Petrunia <psergey@askmonty.org>
  • Loading branch information
montywi committed Jun 27, 2018
1 parent faef2e6 commit 937c193
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 8 deletions.
@@ -1497,3 +1497,43 @@ Note 1003 select NULL AS `i1`,`v2`.`i2` AS `i2`,`v2`.`a` AS `a`,`v2`.`b` AS `b`
DROP VIEW v2;
DROP TABLE t1,t2;
SET optimizer_switch=@save_optimizer_switch;
#
# MDEV-16512
# Server crashes in find_field_in_table_ref on 2nd execution of SP referring to
# non-existing field
#
CREATE TABLE t (i INT);
CREATE PROCEDURE p() SELECT t1.f FROM t AS t1 JOIN t AS t2 USING (f);
CALL p;
ERROR 42S22: Unknown column 'f' in 'from clause'
CALL p;
ERROR 42S22: Unknown column 'f' in 'from clause'
FLUSH TABLES;
CALL p;
ERROR 42S22: Unknown column 'f' in 'from clause'
DROP TABLE t;
CREATE TABLE t (f INT);
CALL p;
ERROR 42S22: Unknown column 'f' in 'from clause'
DROP TABLE t;
CREATE TABLE t (i INT);
CALL p;
ERROR 42S22: Unknown column 'f' in 'from clause'
DROP PROCEDURE p;
DROP TABLE t;
CREATE TABLE t1 (a INT, b INT);
CREATE TABLE t2 (a INT);
CREATE TABLE t3 (a INT, c INT);
CREATE TABLE t4 (a INT, c INT);
CREATE TABLE t5 (a INT, c INT);
CREATE PROCEDURE p1() SELECT c FROM t1 JOIN (t2 LEFT JOIN t3 USING (a) LEFT JOIN t4 USING (a)
LEFT JOIN t5 USING (a)) USING (a);
CALL p1;
ERROR 23000: Column 'c' in field list is ambiguous
CALL p1;
ERROR 23000: Column 'c' in field list is ambiguous
DROP PROCEDURE p1;
DROP TABLE t1,t2,t3,t4,t5;
#
# End of MariaDB 5.5 tests
#
@@ -1159,3 +1159,55 @@ DROP VIEW v2;
DROP TABLE t1,t2;

SET optimizer_switch=@save_optimizer_switch;

--echo #
--echo # MDEV-16512
--echo # Server crashes in find_field_in_table_ref on 2nd execution of SP referring to
--echo # non-existing field
--echo #

CREATE TABLE t (i INT);
CREATE PROCEDURE p() SELECT t1.f FROM t AS t1 JOIN t AS t2 USING (f);
--error ER_BAD_FIELD_ERROR
CALL p;
--error ER_BAD_FIELD_ERROR
CALL p;
FLUSH TABLES;
--error ER_BAD_FIELD_ERROR
CALL p;
DROP TABLE t;

#
# Fix the table definition to match the using
#

CREATE TABLE t (f INT);
#
# The following shouldn't fail as the table is now matching the using
#
--error ER_BAD_FIELD_ERROR
CALL p;
DROP TABLE t;
CREATE TABLE t (i INT);
--error ER_BAD_FIELD_ERROR
CALL p;
DROP PROCEDURE p;
DROP TABLE t;

CREATE TABLE t1 (a INT, b INT);
CREATE TABLE t2 (a INT);
CREATE TABLE t3 (a INT, c INT);
CREATE TABLE t4 (a INT, c INT);
CREATE TABLE t5 (a INT, c INT);
CREATE PROCEDURE p1() SELECT c FROM t1 JOIN (t2 LEFT JOIN t3 USING (a) LEFT JOIN t4 USING (a)
LEFT JOIN t5 USING (a)) USING (a);
--error ER_NON_UNIQ_ERROR
CALL p1;
--error ER_NON_UNIQ_ERROR
CALL p1;
DROP PROCEDURE p1;
DROP TABLE t1,t2,t3,t4,t5;

--echo #
--echo # End of MariaDB 5.5 tests
--echo #
@@ -7687,14 +7687,15 @@ store_natural_using_join_columns(THD *thd, TABLE_LIST *natural_using_join,
Query_arena *arena, backup;
bool result= TRUE;
List<Natural_join_column> *non_join_columns;
List<Natural_join_column> *join_columns;
DBUG_ENTER("store_natural_using_join_columns");

DBUG_ASSERT(!natural_using_join->join_columns);

arena= thd->activate_stmt_arena_if_needed(&backup);

if (!(non_join_columns= new List<Natural_join_column>) ||
!(natural_using_join->join_columns= new List<Natural_join_column>))
!(join_columns= new List<Natural_join_column>))
goto err;

/* Append the columns of the first join operand. */
@@ -7703,7 +7704,7 @@ store_natural_using_join_columns(THD *thd, TABLE_LIST *natural_using_join,
nj_col_1= it_1.get_natural_column_ref();
if (nj_col_1->is_common)
{
natural_using_join->join_columns->push_back(nj_col_1);
join_columns->push_back(nj_col_1);
/* Reset the common columns for the next call to mark_common_columns. */
nj_col_1->is_common= FALSE;
}
@@ -7724,7 +7725,7 @@ store_natural_using_join_columns(THD *thd, TABLE_LIST *natural_using_join,
{
const char *using_field_name_ptr= using_field_name->c_ptr();
List_iterator_fast<Natural_join_column>
it(*(natural_using_join->join_columns));
it(*join_columns);
Natural_join_column *common_field;

for (;;)
@@ -7757,7 +7758,8 @@ store_natural_using_join_columns(THD *thd, TABLE_LIST *natural_using_join,
}

if (non_join_columns->elements > 0)
natural_using_join->join_columns->concat(non_join_columns);
join_columns->concat(non_join_columns);
natural_using_join->join_columns= join_columns;
natural_using_join->is_join_columns_complete= TRUE;

result= FALSE;
@@ -7989,7 +7991,6 @@ static bool setup_natural_join_row_types(THD *thd,
DBUG_PRINT("info", ("using cached setup_natural_join_row_types"));
DBUG_RETURN(false);
}
context->select_lex->first_natural_join_processing= false;

List_iterator_fast<TABLE_LIST> table_ref_it(*from_clause);
TABLE_LIST *table_ref; /* Current table reference. */
@@ -8034,6 +8035,7 @@ static bool setup_natural_join_row_types(THD *thd,
change on re-execution
*/
context->natural_join_first_table= context->first_name_resolution_table;
context->select_lex->first_natural_join_processing= false;
DBUG_RETURN (false);
}

@@ -5487,7 +5487,7 @@ Field_iterator_table_ref::get_or_create_column_ref(THD *thd, TABLE_LIST *parent_
nj_col= natural_join_it.column_ref();
DBUG_ASSERT(nj_col);
}
DBUG_ASSERT(!nj_col->table_field ||
DBUG_ASSERT(!nj_col->table_field || !nj_col->table_field->field ||
nj_col->table_ref->table == nj_col->table_field->field->table);

/*
@@ -5536,7 +5536,7 @@ Field_iterator_table_ref::get_or_create_column_ref(THD *thd, TABLE_LIST *parent_
RETURN
# Pointer to a column of a natural join (or its operand)
NULL No memory to allocate the column
NULL We didn't originally have memory to allocate the column
*/

Natural_join_column *
@@ -5552,7 +5552,7 @@ Field_iterator_table_ref::get_natural_column_ref()
*/
nj_col= natural_join_it.column_ref();
DBUG_ASSERT(nj_col &&
(!nj_col->table_field ||
(!nj_col->table_field || !nj_col->table_field->field ||
nj_col->table_ref->table == nj_col->table_field->field->table));
return nj_col;
}

0 comments on commit 937c193

Please sign in to comment.