Commit 4185869e authored by Jorgen Loland's avatar Jorgen Loland

BUG#11766234: ASSERT (TABLE_REF->TABLE || TABLE_REF->VIEW)

              FAILS IN SET_FIELD_ITERATOR

(Former 59299)

When a PROCEDURE does a natural join, resolving of which columns are
used in the join is done only once; consecutive CALLs to the procedure
will reuse this information:

CREATE PROCEDURE proc() SELECT * FROM t1 NATURAL JOIN v1;
CALL proc();   <- natural join columns resolved here
CALL proc();   <- reuse resolved NJ columns from first CALL

The second CALL knows that it can reuse the resolved NJ columns because
the first CALL sets st_select_lex::first_natural_join_processing=false.
The problem in this bug was that the table the view v1 depends on 
changed between CREATE PROCEDURE and the first CALL: 

CREATE PROCEDURE...
ALTER TABLE t2 CHANGE COLUMN a b CHAR;
CALL proc();   <- error when resolving natural join columns
CALL proc();   <- tries to reuse from first CALL => crash

The fix for this bug is to set first_natural_join_processing= FALSE iff
the natural join columns resolving was successful.


mysql-test/r/sp.result:
  Add test for bug 11766234
mysql-test/t/sp.test:
  Add test for bug 11766234
sql/sql_base.cc:
  Set first_natural_join_processing= FALSE iff the natural join columns resolving was successful.
parent 20b382ed
...@@ -7452,4 +7452,22 @@ c1 ...@@ -7452,4 +7452,22 @@ c1
# Cleanup # Cleanup
drop table t1; drop table t1;
drop procedure p1; drop procedure p1;
#
# BUG#11766234: 59299: ASSERT (TABLE_REF->TABLE || TABLE_REF->VIEW)
# FAILS IN SET_FIELD_ITERATOR
#
CREATE TABLE t1 (a INT);
CREATE TABLE t2 (a INT);
CREATE VIEW v1 AS SELECT a FROM t2;
CREATE PROCEDURE proc() SELECT * FROM t1 NATURAL JOIN v1;
ALTER TABLE t2 CHANGE COLUMN a b CHAR;
CALL proc();
ERROR HY000: View 'test.v1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them
CALL proc();
ERROR HY000: View 'test.v1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them
DROP TABLE t1,t2;
DROP VIEW v1;
DROP PROCEDURE proc;
# End of 5.5 test # End of 5.5 test
...@@ -8713,4 +8713,26 @@ call p1(3, 2); ...@@ -8713,4 +8713,26 @@ call p1(3, 2);
drop table t1; drop table t1;
drop procedure p1; drop procedure p1;
--echo #
--echo # BUG#11766234: 59299: ASSERT (TABLE_REF->TABLE || TABLE_REF->VIEW)
--echo # FAILS IN SET_FIELD_ITERATOR
--echo #
CREATE TABLE t1 (a INT);
CREATE TABLE t2 (a INT);
CREATE VIEW v1 AS SELECT a FROM t2;
CREATE PROCEDURE proc() SELECT * FROM t1 NATURAL JOIN v1;
ALTER TABLE t2 CHANGE COLUMN a b CHAR;
--echo
--error ER_VIEW_INVALID
CALL proc();
--error ER_VIEW_INVALID
CALL proc();
--echo
DROP TABLE t1,t2;
DROP VIEW v1;
DROP PROCEDURE proc;
--echo # End of 5.5 test --echo # End of 5.5 test
...@@ -7594,9 +7594,10 @@ static bool setup_natural_join_row_types(THD *thd, ...@@ -7594,9 +7594,10 @@ static bool setup_natural_join_row_types(THD *thd,
List<TABLE_LIST> *from_clause, List<TABLE_LIST> *from_clause,
Name_resolution_context *context) Name_resolution_context *context)
{ {
DBUG_ENTER("setup_natural_join_row_types");
thd->where= "from clause"; thd->where= "from clause";
if (from_clause->elements == 0) if (from_clause->elements == 0)
return FALSE; /* We come here in the case of UNIONs. */ DBUG_RETURN(false); /* We come here in the case of UNIONs. */
List_iterator_fast<TABLE_LIST> table_ref_it(*from_clause); List_iterator_fast<TABLE_LIST> table_ref_it(*from_clause);
TABLE_LIST *table_ref; /* Current table reference. */ TABLE_LIST *table_ref; /* Current table reference. */
...@@ -7604,10 +7605,6 @@ static bool setup_natural_join_row_types(THD *thd, ...@@ -7604,10 +7605,6 @@ static bool setup_natural_join_row_types(THD *thd,
TABLE_LIST *left_neighbor; TABLE_LIST *left_neighbor;
/* Table reference to the right of the current. */ /* Table reference to the right of the current. */
TABLE_LIST *right_neighbor= NULL; TABLE_LIST *right_neighbor= NULL;
bool save_first_natural_join_processing=
context->select_lex->first_natural_join_processing;
context->select_lex->first_natural_join_processing= FALSE;
/* Note that tables in the list are in reversed order */ /* Note that tables in the list are in reversed order */
for (left_neighbor= table_ref_it++; left_neighbor ; ) for (left_neighbor= table_ref_it++; left_neighbor ; )
...@@ -7619,12 +7616,11 @@ static bool setup_natural_join_row_types(THD *thd, ...@@ -7619,12 +7616,11 @@ static bool setup_natural_join_row_types(THD *thd,
1) for stored procedures, 1) for stored procedures,
2) for multitable update after lock failure and table reopening. 2) for multitable update after lock failure and table reopening.
*/ */
if (save_first_natural_join_processing) if (context->select_lex->first_natural_join_processing)
{ {
context->select_lex->first_natural_join_processing= FALSE;
if (store_top_level_join_columns(thd, table_ref, if (store_top_level_join_columns(thd, table_ref,
left_neighbor, right_neighbor)) left_neighbor, right_neighbor))
return TRUE; DBUG_RETURN(true);
if (left_neighbor) if (left_neighbor)
{ {
TABLE_LIST *first_leaf_on_the_right; TABLE_LIST *first_leaf_on_the_right;
...@@ -7644,8 +7640,9 @@ static bool setup_natural_join_row_types(THD *thd, ...@@ -7644,8 +7640,9 @@ static bool setup_natural_join_row_types(THD *thd,
DBUG_ASSERT(right_neighbor); DBUG_ASSERT(right_neighbor);
context->first_name_resolution_table= context->first_name_resolution_table=
right_neighbor->first_leaf_for_name_resolution(); right_neighbor->first_leaf_for_name_resolution();
context->select_lex->first_natural_join_processing= false;
return FALSE; DBUG_RETURN (false);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment