mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
Merge gkodinov@bk-internal.mysql.com:/home/bk/mysql-5.0-opt
into rakia.gmz:/home/kgeorge/mysql/autopush/B19717-5.0-opt
This commit is contained in:
@ -219,3 +219,20 @@ SELECT * FROM t1;
|
|||||||
a b
|
a b
|
||||||
45 2
|
45 2
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
|
CREATE TABLE t1 (i INT PRIMARY KEY, j INT);
|
||||||
|
INSERT INTO t1 SELECT 1, j;
|
||||||
|
ERROR 42S22: Unknown column 'j' in 'field list'
|
||||||
|
DROP TABLE t1;
|
||||||
|
CREATE TABLE t1 (i INT PRIMARY KEY, j INT);
|
||||||
|
CREATE TABLE t2 (a INT, b INT);
|
||||||
|
CREATE TABLE t3 (a INT, c INT);
|
||||||
|
INSERT INTO t1 SELECT 1, a FROM t2 NATURAL JOIN t3
|
||||||
|
ON DUPLICATE KEY UPDATE j= a;
|
||||||
|
DROP TABLE t1,t2,t3;
|
||||||
|
CREATE TABLE t1 (i INT PRIMARY KEY, j INT);
|
||||||
|
CREATE TABLE t2 (a INT);
|
||||||
|
INSERT INTO t1 VALUES (1, 1);
|
||||||
|
INSERT INTO t2 VALUES (1), (3);
|
||||||
|
INSERT INTO t1 SELECT 1, COUNT(*) FROM t2 ON DUPLICATE KEY UPDATE j= a;
|
||||||
|
ERROR 42S22: Unknown column 'a' in 'field list'
|
||||||
|
DROP TABLE t1,t2;
|
||||||
|
@ -139,3 +139,26 @@ INSERT INTO t1 VALUES (45, 1) ON DUPLICATE KEY UPDATE b =
|
|||||||
SELECT * FROM t1;
|
SELECT * FROM t1;
|
||||||
|
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
#
|
||||||
|
# Bug#25831: Deficiencies in INSERT ... SELECT ... field name resolving.
|
||||||
|
#
|
||||||
|
CREATE TABLE t1 (i INT PRIMARY KEY, j INT);
|
||||||
|
--error ER_BAD_FIELD_ERROR
|
||||||
|
INSERT INTO t1 SELECT 1, j;
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
CREATE TABLE t1 (i INT PRIMARY KEY, j INT);
|
||||||
|
CREATE TABLE t2 (a INT, b INT);
|
||||||
|
CREATE TABLE t3 (a INT, c INT);
|
||||||
|
INSERT INTO t1 SELECT 1, a FROM t2 NATURAL JOIN t3
|
||||||
|
ON DUPLICATE KEY UPDATE j= a;
|
||||||
|
DROP TABLE t1,t2,t3;
|
||||||
|
|
||||||
|
CREATE TABLE t1 (i INT PRIMARY KEY, j INT);
|
||||||
|
CREATE TABLE t2 (a INT);
|
||||||
|
INSERT INTO t1 VALUES (1, 1);
|
||||||
|
INSERT INTO t2 VALUES (1), (3);
|
||||||
|
--error ER_BAD_FIELD_ERROR
|
||||||
|
INSERT INTO t1 SELECT 1, COUNT(*) FROM t2 ON DUPLICATE KEY UPDATE j= a;
|
||||||
|
DROP TABLE t1,t2;
|
||||||
|
@ -325,10 +325,10 @@ private:
|
|||||||
TABLE_LIST *save_first_name_resolution_table;
|
TABLE_LIST *save_first_name_resolution_table;
|
||||||
TABLE_LIST *save_next_name_resolution_table;
|
TABLE_LIST *save_next_name_resolution_table;
|
||||||
bool save_resolve_in_select_list;
|
bool save_resolve_in_select_list;
|
||||||
|
TABLE_LIST *save_next_local;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Name_resolution_context_state() {} /* Remove gcc warning */
|
Name_resolution_context_state() {} /* Remove gcc warning */
|
||||||
TABLE_LIST *save_next_local;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/* Save the state of a name resolution context. */
|
/* Save the state of a name resolution context. */
|
||||||
@ -350,6 +350,11 @@ public:
|
|||||||
context->first_name_resolution_table= save_first_name_resolution_table;
|
context->first_name_resolution_table= save_first_name_resolution_table;
|
||||||
context->resolve_in_select_list= save_resolve_in_select_list;
|
context->resolve_in_select_list= save_resolve_in_select_list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TABLE_LIST *get_first_name_resolution_table()
|
||||||
|
{
|
||||||
|
return save_first_name_resolution_table;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/*************************************************************************/
|
/*************************************************************************/
|
||||||
|
@ -4527,21 +4527,8 @@ bool setup_tables(THD *thd, Name_resolution_context *context,
|
|||||||
uint tablenr= 0;
|
uint tablenr= 0;
|
||||||
DBUG_ENTER("setup_tables");
|
DBUG_ENTER("setup_tables");
|
||||||
|
|
||||||
/*
|
DBUG_ASSERT ((select_insert && !tables->next_name_resolution_table) || !tables ||
|
||||||
Due to the various call paths that lead to setup_tables() it may happen
|
(context->table_list && context->first_name_resolution_table));
|
||||||
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.
|
||||||
For select we setup tables except first (and its underlying tables)
|
For select we setup tables except first (and its underlying tables)
|
||||||
|
@ -656,6 +656,8 @@ bool mysqld_help(THD *thd, const char *mask)
|
|||||||
Init tables and fields to be usable from items
|
Init tables and fields to be usable from items
|
||||||
tables do not contain VIEWs => we can pass 0 as conds
|
tables do not contain VIEWs => we can pass 0 as conds
|
||||||
*/
|
*/
|
||||||
|
thd->lex->select_lex.context.table_list=
|
||||||
|
thd->lex->select_lex.context.first_name_resolution_table= &tables[0];
|
||||||
setup_tables(thd, &thd->lex->select_lex.context,
|
setup_tables(thd, &thd->lex->select_lex.context,
|
||||||
&thd->lex->select_lex.top_join_list,
|
&thd->lex->select_lex.top_join_list,
|
||||||
tables, 0, &leaves, FALSE);
|
tables, 0, &leaves, FALSE);
|
||||||
|
@ -966,6 +966,8 @@ bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list,
|
|||||||
DBUG_PRINT("enter", ("table_list 0x%lx, table 0x%lx, view %d",
|
DBUG_PRINT("enter", ("table_list 0x%lx, table 0x%lx, view %d",
|
||||||
(ulong)table_list, (ulong)table,
|
(ulong)table_list, (ulong)table,
|
||||||
(int)insert_into_view));
|
(int)insert_into_view));
|
||||||
|
/* INSERT should have a SELECT or VALUES clause */
|
||||||
|
DBUG_ASSERT (!select_insert || !values);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
For subqueries in VALUES() we should not see the table in which we are
|
For subqueries in VALUES() we should not see the table in which we are
|
||||||
@ -998,44 +1000,40 @@ bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list,
|
|||||||
select_insert))
|
select_insert))
|
||||||
DBUG_RETURN(TRUE);
|
DBUG_RETURN(TRUE);
|
||||||
|
|
||||||
/* Save the state of the current name resolution context. */
|
|
||||||
ctx_state.save_state(context, table_list);
|
|
||||||
|
|
||||||
/*
|
|
||||||
Perform name resolution only in the first table - 'table_list',
|
|
||||||
which is the table that is inserted into.
|
|
||||||
*/
|
|
||||||
table_list->next_local= 0;
|
|
||||||
context->resolve_in_table_list_only(table_list);
|
|
||||||
|
|
||||||
/* Prepare the fields in the statement. */
|
/* Prepare the fields in the statement. */
|
||||||
if (values &&
|
if (values)
|
||||||
!(res= check_insert_fields(thd, context->table_list, fields, *values,
|
|
||||||
!insert_into_view, &map) ||
|
|
||||||
setup_fields(thd, 0, *values, 0, 0, 0)) &&
|
|
||||||
duplic == DUP_UPDATE)
|
|
||||||
{
|
{
|
||||||
select_lex->no_wrap_view_item= TRUE;
|
/* if we have INSERT ... VALUES () we cannot have a GROUP BY clause */
|
||||||
res= check_update_fields(thd, context->table_list, update_fields, &map);
|
DBUG_ASSERT (!select_lex->group_list.elements);
|
||||||
select_lex->no_wrap_view_item= FALSE;
|
|
||||||
|
/* Save the state of the current name resolution context. */
|
||||||
|
ctx_state.save_state(context, table_list);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
When we are not using GROUP BY we can refer to other tables in the
|
Perform name resolution only in the first table - 'table_list',
|
||||||
ON DUPLICATE KEY part.
|
which is the table that is inserted into.
|
||||||
*/
|
*/
|
||||||
if (select_lex->group_list.elements == 0)
|
table_list->next_local= 0;
|
||||||
|
context->resolve_in_table_list_only(table_list);
|
||||||
|
|
||||||
|
if (!(res= check_insert_fields(thd, context->table_list, fields, *values,
|
||||||
|
!insert_into_view, &map) ||
|
||||||
|
setup_fields(thd, 0, *values, 0, 0, 0))
|
||||||
|
&& duplic == DUP_UPDATE)
|
||||||
{
|
{
|
||||||
context->table_list->next_local= ctx_state.save_next_local;
|
select_lex->no_wrap_view_item= TRUE;
|
||||||
/* first_name_resolution_table was set by resolve_in_table_list_only() */
|
res= check_update_fields(thd, context->table_list, update_fields, &map);
|
||||||
context->first_name_resolution_table->
|
select_lex->no_wrap_view_item= FALSE;
|
||||||
next_name_resolution_table= ctx_state.save_next_local;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Restore the current context. */
|
||||||
|
ctx_state.restore_state(context, table_list);
|
||||||
|
|
||||||
if (!res)
|
if (!res)
|
||||||
res= setup_fields(thd, 0, update_values, 1, 0, 0);
|
res= setup_fields(thd, 0, update_values, 1, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Restore the current context. */
|
|
||||||
ctx_state.restore_state(context, table_list);
|
|
||||||
|
|
||||||
if (res)
|
if (res)
|
||||||
DBUG_RETURN(res);
|
DBUG_RETURN(res);
|
||||||
|
|
||||||
@ -2361,7 +2359,6 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
|
|||||||
|
|
||||||
if (info.handle_duplicates == DUP_UPDATE)
|
if (info.handle_duplicates == DUP_UPDATE)
|
||||||
{
|
{
|
||||||
/* Save the state of the current name resolution context. */
|
|
||||||
Name_resolution_context *context= &lex->select_lex.context;
|
Name_resolution_context *context= &lex->select_lex.context;
|
||||||
Name_resolution_context_state ctx_state;
|
Name_resolution_context_state ctx_state;
|
||||||
|
|
||||||
@ -2377,16 +2374,20 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
|
|||||||
*info.update_fields, &map);
|
*info.update_fields, &map);
|
||||||
lex->select_lex.no_wrap_view_item= FALSE;
|
lex->select_lex.no_wrap_view_item= FALSE;
|
||||||
/*
|
/*
|
||||||
When we are not using GROUP BY we can refer to other tables in the
|
When we are not using GROUP BY and there are no ungrouped aggregate functions
|
||||||
ON DUPLICATE KEY part
|
we can refer to other tables in the ON DUPLICATE KEY part.
|
||||||
|
We use next_name_resolution_table descructively, so check it first (views?)
|
||||||
*/
|
*/
|
||||||
if (lex->select_lex.group_list.elements == 0)
|
DBUG_ASSERT (!table_list->next_name_resolution_table);
|
||||||
{
|
if (lex->select_lex.group_list.elements == 0 &&
|
||||||
context->table_list->next_local= ctx_state.save_next_local;
|
!lex->select_lex.with_sum_func)
|
||||||
/* first_name_resolution_table was set by resolve_in_table_list_only() */
|
/*
|
||||||
context->first_name_resolution_table->
|
We must make a single context out of the two separate name resolution contexts :
|
||||||
next_name_resolution_table= ctx_state.save_next_local;
|
the INSERT table and the tables in the SELECT part of INSERT ... SELECT.
|
||||||
}
|
To do that we must concatenate the two lists
|
||||||
|
*/
|
||||||
|
table_list->next_name_resolution_table= ctx_state.get_first_name_resolution_table();
|
||||||
|
|
||||||
res= res || setup_fields(thd, 0, *info.update_values, 1, 0, 0);
|
res= res || setup_fields(thd, 0, *info.update_values, 1, 0, 0);
|
||||||
if (!res)
|
if (!res)
|
||||||
{
|
{
|
||||||
|
@ -1571,21 +1571,16 @@ error:
|
|||||||
|
|
||||||
static bool mysql_insert_select_prepare_tester(THD *thd)
|
static bool mysql_insert_select_prepare_tester(THD *thd)
|
||||||
{
|
{
|
||||||
TABLE_LIST *first;
|
|
||||||
bool res;
|
|
||||||
SELECT_LEX *first_select= &thd->lex->select_lex;
|
SELECT_LEX *first_select= &thd->lex->select_lex;
|
||||||
|
TABLE_LIST *second_table= ((TABLE_LIST*)first_select->table_list.first)->
|
||||||
|
next_local;
|
||||||
|
|
||||||
/* Skip first table, which is the table we are inserting in */
|
/* Skip first table, which is the table we are inserting in */
|
||||||
first_select->table_list.first= (byte*)(first=
|
first_select->table_list.first= (byte *) second_table;
|
||||||
((TABLE_LIST*)first_select->
|
thd->lex->select_lex.context.table_list=
|
||||||
table_list.first)->next_local);
|
thd->lex->select_lex.context.first_name_resolution_table= second_table;
|
||||||
res= mysql_insert_select_prepare(thd);
|
|
||||||
/*
|
return mysql_insert_select_prepare(thd);
|
||||||
insert/replace from SELECT give its SELECT_LEX for SELECT,
|
|
||||||
and item_list belong to SELECT
|
|
||||||
*/
|
|
||||||
thd->lex->select_lex.context.resolve_in_select_list= TRUE;
|
|
||||||
thd->lex->select_lex.context.table_list= first;
|
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -147,6 +147,8 @@ st_select_lex_unit::init_prepare_fake_select_lex(THD *thd)
|
|||||||
fake_select_lex->table_list.link_in_list((byte *)&result_table_list,
|
fake_select_lex->table_list.link_in_list((byte *)&result_table_list,
|
||||||
(byte **)
|
(byte **)
|
||||||
&result_table_list.next_local);
|
&result_table_list.next_local);
|
||||||
|
fake_select_lex->context.table_list= fake_select_lex->context.first_name_resolution_table=
|
||||||
|
fake_select_lex->get_table_list();
|
||||||
for (ORDER *order= (ORDER *)global_parameters->order_list.first;
|
for (ORDER *order= (ORDER *)global_parameters->order_list.first;
|
||||||
order;
|
order;
|
||||||
order=order->next)
|
order=order->next)
|
||||||
|
@ -4188,8 +4188,13 @@ select_into:
|
|||||||
| select_from into;
|
| select_from into;
|
||||||
|
|
||||||
select_from:
|
select_from:
|
||||||
FROM join_table_list where_clause group_clause having_clause
|
FROM join_table_list where_clause group_clause having_clause
|
||||||
opt_order_clause opt_limit_clause procedure_clause
|
opt_order_clause opt_limit_clause procedure_clause
|
||||||
|
{
|
||||||
|
Select->context.table_list=
|
||||||
|
Select->context.first_name_resolution_table=
|
||||||
|
(TABLE_LIST *) Select->table_list.first;
|
||||||
|
}
|
||||||
| FROM DUAL_SYM where_clause opt_limit_clause
|
| FROM DUAL_SYM where_clause opt_limit_clause
|
||||||
/* oracle compatibility: oracle always requires FROM clause,
|
/* oracle compatibility: oracle always requires FROM clause,
|
||||||
and DUAL is system table without fields.
|
and DUAL is system table without fields.
|
||||||
|
Reference in New Issue
Block a user