Commit 900e66f8 authored by unknown's avatar unknown

Fix for BUG#21774: Column count doesn't match value count at row x

The cause of the bug was an incomplete fix for bug 18080.
The problem was that setup_tables() unconditionally reset the
name resolution context to its 'tables' argument, which pointed
to the first table of an SQL statement.

The bug fix limits resetting of the name resolution context in
setup_tables() only in the cases when the context was not set
by earlier parser/optimizer phases.


mysql-test/r/insert_select.result:
  Test for BUG#21774.
mysql-test/t/insert_select.test:
  Test for BUG#21774.
sql/sql_base.cc:
  Do not reset the name resolution contect unconditionally.
  Instead set the context to 'tables' only if it was not
  set before calling setup_tables().
sql/sql_insert.cc:
  Added asserts to make sure that in the case of INSERT ... VALUES ...
  statements it is not necessary to reset the name resolution context
  to the first table, because there is only one table in the list of
  tables anyway. The actual code is not removed in order not to
  confuse it with the actual bug fix.
sql/sql_parse.cc:
  Removed unnecessary reset of the name resolution context.
  The context is anyway unconditionally reset in mysql_insert()
  and mysql_prepare_insert().
parent 01ec88dc
...@@ -695,6 +695,16 @@ CREATE TABLE t2 (z int, y int); ...@@ -695,6 +695,16 @@ CREATE TABLE t2 (z int, y int);
CREATE TABLE t3 (a int, b int); CREATE TABLE t3 (a int, b int);
INSERT INTO t3 (SELECT x, y FROM t1 JOIN t2 USING (y) WHERE z = 1); INSERT INTO t3 (SELECT x, y FROM t1 JOIN t2 USING (y) WHERE z = 1);
DROP TABLE IF EXISTS t1,t2,t3; DROP TABLE IF EXISTS t1,t2,t3;
CREATE DATABASE bug21774_1;
CREATE DATABASE bug21774_2;
CREATE TABLE bug21774_1.t1(id VARCHAR(10) NOT NULL,label VARCHAR(255));
CREATE TABLE bug21774_2.t1(id VARCHAR(10) NOT NULL,label VARCHAR(255));
CREATE TABLE bug21774_1.t2(id VARCHAR(10) NOT NULL,label VARCHAR(255));
INSERT INTO bug21774_2.t1 SELECT t1.* FROM bug21774_1.t1;
use bug21774_1;
INSERT INTO bug21774_2.t1 SELECT t1.* FROM t1;
DROP DATABASE bug21774_1;
DROP DATABASE bug21774_2;
CREATE DATABASE meow; CREATE DATABASE meow;
CREATE TABLE table_target ( mexs_id CHAR(8), messzeit TIMESTAMP, PRIMARY KEY (mexs_id)); CREATE TABLE table_target ( mexs_id CHAR(8), messzeit TIMESTAMP, PRIMARY KEY (mexs_id));
CREATE TABLE table_target2 ( mexs_id CHAR(8), messzeit TIMESTAMP, PRIMARY KEY (mexs_id)); CREATE TABLE table_target2 ( mexs_id CHAR(8), messzeit TIMESTAMP, PRIMARY KEY (mexs_id));
......
...@@ -248,6 +248,24 @@ CREATE TABLE t3 (a int, b int); ...@@ -248,6 +248,24 @@ CREATE TABLE t3 (a int, b int);
INSERT INTO t3 (SELECT x, y FROM t1 JOIN t2 USING (y) WHERE z = 1); INSERT INTO t3 (SELECT x, y FROM t1 JOIN t2 USING (y) WHERE z = 1);
DROP TABLE IF EXISTS t1,t2,t3; DROP TABLE IF EXISTS t1,t2,t3;
#
# Bug #21774: Column count doesn't match value count at row x
#
CREATE DATABASE bug21774_1;
CREATE DATABASE bug21774_2;
CREATE TABLE bug21774_1.t1(id VARCHAR(10) NOT NULL,label VARCHAR(255));
CREATE TABLE bug21774_2.t1(id VARCHAR(10) NOT NULL,label VARCHAR(255));
CREATE TABLE bug21774_1.t2(id VARCHAR(10) NOT NULL,label VARCHAR(255));
INSERT INTO bug21774_2.t1 SELECT t1.* FROM bug21774_1.t1;
use bug21774_1;
INSERT INTO bug21774_2.t1 SELECT t1.* FROM t1;
DROP DATABASE bug21774_1;
DROP DATABASE bug21774_2;
# #
# Bug #20989: View '(null).(null)' references invalid table(s)... on # Bug #20989: View '(null).(null)' references invalid table(s)... on
# SQL SECURITY INVOKER # SQL SECURITY INVOKER
......
...@@ -4453,7 +4453,20 @@ bool setup_tables(THD *thd, Name_resolution_context *context, ...@@ -4453,7 +4453,20 @@ bool setup_tables(THD *thd, Name_resolution_context *context,
uint tablenr= 0; uint tablenr= 0;
DBUG_ENTER("setup_tables"); DBUG_ENTER("setup_tables");
context->table_list= context->first_name_resolution_table= tables; /*
Due to the various call paths that lead to setup_tables() it may happen
that context->table_list and context->first_name_resolution_table can be
NULL (this is typically done when creating TABLE_LISTs internally).
TODO:
Investigate all cases when this my happen, initialize the name resolution
context correctly in all those places, and remove the context reset below.
*/
if (!context->table_list || !context->first_name_resolution_table)
{
/* Test whether the context is in a consistent state. */
DBUG_ASSERT(!context->first_name_resolution_table && !context->table_list);
context->table_list= context->first_name_resolution_table= tables;
}
/* /*
this is used for INSERT ... SELECT. this is used for INSERT ... SELECT.
......
...@@ -411,6 +411,15 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, ...@@ -411,6 +411,15 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
table= table_list->table; table= table_list->table;
context= &thd->lex->select_lex.context; context= &thd->lex->select_lex.context;
/*
These three asserts test the hypothesis that the resetting of the name
resolution context below is not necessary at all since the list of local
tables for INSERT always consists of one table.
*/
DBUG_ASSERT(!table_list->next_local);
DBUG_ASSERT(!context->table_list->next_local);
DBUG_ASSERT(!context->first_name_resolution_table->next_name_resolution_table);
/* Save the state of the current name resolution context. */ /* Save the state of the current name resolution context. */
ctx_state.save_state(context, table_list); ctx_state.save_state(context, table_list);
......
...@@ -3344,8 +3344,6 @@ end_with_restore_list: ...@@ -3344,8 +3344,6 @@ end_with_restore_list:
DBUG_ASSERT(first_table == all_tables && first_table != 0); DBUG_ASSERT(first_table == all_tables && first_table != 0);
if ((res= insert_precheck(thd, all_tables))) if ((res= insert_precheck(thd, all_tables)))
break; break;
/* Skip first table, which is the table we are inserting in */
select_lex->context.table_list= first_table->next_local;
if (!thd->locked_tables && if (!thd->locked_tables &&
!(need_start_waiting= !wait_if_global_read_lock(thd, 0, 1))) !(need_start_waiting= !wait_if_global_read_lock(thd, 0, 1)))
......
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