mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
Merge ibabaev@bk-internal.mysql.com:/home/bk/mysql-5.0-opt
into olga.mysql.com:/home/igor/mysql-5.0-opt
This commit is contained in:
@ -731,3 +731,16 @@ select @@identity;
|
|||||||
@@identity
|
@@identity
|
||||||
0
|
0
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
CREATE TABLE t1 (f1 INT, f2 INT );
|
||||||
|
CREATE TABLE t2 (f1 INT PRIMARY KEY, f2 INT);
|
||||||
|
INSERT INTO t1 VALUES (1,1),(2,2),(10,10);
|
||||||
|
INSERT INTO t2 (f1, f2) SELECT f1, f2 FROM t1;
|
||||||
|
INSERT INTO t2 (f1, f2)
|
||||||
|
SELECT f1, f1 FROM t2 src WHERE f1 < 2
|
||||||
|
ON DUPLICATE KEY UPDATE f1 = 100 + src.f1;
|
||||||
|
SELECT * FROM t2;
|
||||||
|
f1 f2
|
||||||
|
101 1
|
||||||
|
2 2
|
||||||
|
10 10
|
||||||
|
DROP TABLE t1, t2;
|
||||||
|
@ -292,3 +292,18 @@ select @@identity;
|
|||||||
insert ignore t1(f2) select 1;
|
insert ignore t1(f2) select 1;
|
||||||
select @@identity;
|
select @@identity;
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
|
||||||
|
#
|
||||||
|
# Bug#16630: wrong result, when INSERT t1 SELECT ... FROM t1 ON DUPLICATE
|
||||||
|
#
|
||||||
|
CREATE TABLE t1 (f1 INT, f2 INT );
|
||||||
|
CREATE TABLE t2 (f1 INT PRIMARY KEY, f2 INT);
|
||||||
|
INSERT INTO t1 VALUES (1,1),(2,2),(10,10);
|
||||||
|
INSERT INTO t2 (f1, f2) SELECT f1, f2 FROM t1;
|
||||||
|
INSERT INTO t2 (f1, f2)
|
||||||
|
SELECT f1, f1 FROM t2 src WHERE f1 < 2
|
||||||
|
ON DUPLICATE KEY UPDATE f1 = 100 + src.f1;
|
||||||
|
SELECT * FROM t2;
|
||||||
|
DROP TABLE t1, t2;
|
||||||
|
|
||||||
|
|
||||||
|
45
sql/item.cc
45
sql/item.cc
@ -4809,6 +4809,51 @@ void Item_field::update_null_value()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Add the field to the select list and substitute it for the reference to
|
||||||
|
the field.
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
Item_field::update_value_transformer()
|
||||||
|
select_arg current select
|
||||||
|
|
||||||
|
DESCRIPTION
|
||||||
|
If the field doesn't belong to the table being inserted into then it is
|
||||||
|
added to the select list, pointer to it is stored in the ref_pointer_array
|
||||||
|
of the select and the field itself is substituted for the Item_ref object.
|
||||||
|
This is done in order to get correct values from update fields that
|
||||||
|
belongs to the SELECT part in the INSERT .. SELECT .. ON DUPLICATE KEY
|
||||||
|
UPDATE statement.
|
||||||
|
|
||||||
|
RETURN
|
||||||
|
0 if error occured
|
||||||
|
ref if all conditions are met
|
||||||
|
this field otherwise
|
||||||
|
*/
|
||||||
|
|
||||||
|
Item *Item_field::update_value_transformer(byte *select_arg)
|
||||||
|
{
|
||||||
|
SELECT_LEX *select= (SELECT_LEX*)select_arg;
|
||||||
|
DBUG_ASSERT(fixed);
|
||||||
|
|
||||||
|
if (field->table != select->context.table_list->table &&
|
||||||
|
type() != Item::TRIGGER_FIELD_ITEM)
|
||||||
|
{
|
||||||
|
List<Item> *all_fields= &select->join->all_fields;
|
||||||
|
Item **ref_pointer_array= select->ref_pointer_array;
|
||||||
|
int el= all_fields->elements;
|
||||||
|
Item_ref *ref;
|
||||||
|
|
||||||
|
ref_pointer_array[el]= (Item*)this;
|
||||||
|
all_fields->push_front((Item*)this);
|
||||||
|
ref= new Item_ref(&select->context, ref_pointer_array + el,
|
||||||
|
table_name, field_name);
|
||||||
|
return ref;
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Item_ref::Item_ref(Name_resolution_context *context_arg,
|
Item_ref::Item_ref(Name_resolution_context *context_arg,
|
||||||
Item **item, const char *table_name_arg,
|
Item **item, const char *table_name_arg,
|
||||||
const char *field_name_arg)
|
const char *field_name_arg)
|
||||||
|
@ -817,6 +817,7 @@ public:
|
|||||||
virtual Item_field *filed_for_view_update() { return 0; }
|
virtual Item_field *filed_for_view_update() { return 0; }
|
||||||
|
|
||||||
virtual Item *neg_transformer(THD *thd) { return NULL; }
|
virtual Item *neg_transformer(THD *thd) { return NULL; }
|
||||||
|
virtual Item *update_value_transformer(byte *select_arg) { return this; }
|
||||||
virtual Item *safe_charset_converter(CHARSET_INFO *tocs);
|
virtual Item *safe_charset_converter(CHARSET_INFO *tocs);
|
||||||
void delete_self()
|
void delete_self()
|
||||||
{
|
{
|
||||||
@ -1295,6 +1296,7 @@ public:
|
|||||||
Item_field *filed_for_view_update() { return this; }
|
Item_field *filed_for_view_update() { return this; }
|
||||||
Item *safe_charset_converter(CHARSET_INFO *tocs);
|
Item *safe_charset_converter(CHARSET_INFO *tocs);
|
||||||
int fix_outer_field(THD *thd, Field **field, Item **reference);
|
int fix_outer_field(THD *thd, Field **field, Item **reference);
|
||||||
|
virtual Item *update_value_transformer(byte *select_arg);
|
||||||
friend class Item_default_value;
|
friend class Item_default_value;
|
||||||
friend class Item_insert_value;
|
friend class Item_insert_value;
|
||||||
friend class st_select_lex_unit;
|
friend class st_select_lex_unit;
|
||||||
|
@ -2388,7 +2388,23 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
|
|||||||
next_name_resolution_table= ctx_state.save_next_local;
|
next_name_resolution_table= ctx_state.save_next_local;
|
||||||
}
|
}
|
||||||
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)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Traverse the update values list and substitute fields from the
|
||||||
|
select for references (Item_ref objects) to them. This is done in
|
||||||
|
order to get correct values from those fields when the select
|
||||||
|
employs a temporary table.
|
||||||
|
*/
|
||||||
|
List_iterator<Item> li(*info.update_values);
|
||||||
|
Item *item;
|
||||||
|
|
||||||
|
while ((item= li++))
|
||||||
|
{
|
||||||
|
item->transform(&Item::update_value_transformer,
|
||||||
|
(byte*)lex->current_select);
|
||||||
|
}
|
||||||
|
}
|
||||||
/* Restore the current context. */
|
/* Restore the current context. */
|
||||||
ctx_state.restore_state(context, table_list);
|
ctx_state.restore_state(context, table_list);
|
||||||
}
|
}
|
||||||
|
@ -482,6 +482,9 @@ JOIN::prepare(Item ***rref_pointer_array,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!procedure && result && result->prepare(fields_list, unit_arg))
|
||||||
|
goto err; /* purecov: inspected */
|
||||||
|
|
||||||
/* Init join struct */
|
/* Init join struct */
|
||||||
count_field_types(&tmp_table_param, all_fields, 0);
|
count_field_types(&tmp_table_param, all_fields, 0);
|
||||||
ref_pointer_array_size= all_fields.elements*sizeof(Item*);
|
ref_pointer_array_size= all_fields.elements*sizeof(Item*);
|
||||||
@ -495,9 +498,6 @@ JOIN::prepare(Item ***rref_pointer_array,
|
|||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (!procedure && result && result->prepare(fields_list, unit_arg))
|
|
||||||
goto err; /* purecov: inspected */
|
|
||||||
|
|
||||||
if (select_lex->olap == ROLLUP_TYPE && rollup_init())
|
if (select_lex->olap == ROLLUP_TYPE && rollup_init())
|
||||||
goto err;
|
goto err;
|
||||||
if (alloc_func_list())
|
if (alloc_func_list())
|
||||||
|
Reference in New Issue
Block a user