summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/r/join.result40
-rw-r--r--mysql-test/t/join.test52
-rw-r--r--sql/sql_base.cc12
-rw-r--r--sql/table.cc6
4 files changed, 102 insertions, 8 deletions
diff --git a/mysql-test/r/join.result b/mysql-test/r/join.result
index 1e51d55f012..7b0e7807e39 100644
--- a/mysql-test/r/join.result
+++ b/mysql-test/r/join.result
@@ -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
+#
diff --git a/mysql-test/t/join.test b/mysql-test/t/join.test
index 203a7d377a5..feafac57a7e 100644
--- a/mysql-test/t/join.test
+++ b/mysql-test/t/join.test
@@ -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 #
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 71bbb538b5c..8ffb7bc118b 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -7687,6 +7687,7 @@ 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);
@@ -7694,7 +7695,7 @@ store_natural_using_join_columns(THD *thd, TABLE_LIST *natural_using_join,
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);
}
diff --git a/sql/table.cc b/sql/table.cc
index 87a249defa0..48aa445e1aa 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -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;
}