Below is the list of changes that have just been committed into a local
5.0 repository of dlenev. When dlenev does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html
ChangeSet@stripped, 2007-01-10 17:16:51+03:00, dlenev@stripped +3 -0
Proposed fix for bug#24491 "using alias from source table in insert ...
on duplicate key".
INSERT ... SELECT ... ON DUPLICATE KEY UPDATE which was used in
stored routine or as prepared statement and which in its ON DUPLICATE
KEY clause erroneously tried to assign value to a column mentioned only
in its SELECT part was properly emitting error on the first execution
but succeeded on the second and following executions.
Code which is responsible for name resolution of fields mentioned in
UPDATE clause (e.g. see select_insert::prepare()) modifies table list
and Name_resolution_context used in this process. It uses
Name_resolution_context_state::save_state/restore_state() to revert
these modifications. Unfortunately those two methods failed to revert
properly modifications to TABLE_LIST::next_name_resolution_table
and this broke name resolution process for successive executions.
This patch fixes Name_resolution_context_state::save_state/restore_state()
in such way that it properly handles TABLE_LIST::next_name_resolution_table.
mysql-test/r/ps.result@stripped, 2007-01-10 17:16:48+03:00, dlenev@stripped +16 -0
Added test case for bug#24491 "using alias from source table in insert ...
on duplicate key"
mysql-test/t/ps.test@stripped, 2007-01-10 17:16:48+03:00, dlenev@stripped +30 -0
Added test case for bug#24491 "using alias from source table in insert ...
on duplicate key"
sql/item.h@stripped, 2007-01-10 17:16:48+03:00, dlenev@stripped +6 -11
Name_resolution_context::save_state/restore_state():
Code which uses these methods (and ATM this is only code related to INSERT)
modifies 'next_name_resolution_table' member of table list element pointed
by 'table_list' argument (which corresponds to target table of insert) and
not the member of table list element pointed by 'first_name_resolution_table'
(which corresponds to the first table of SELECT clause).
Changed these methods to reflect this.
# This is a BitKeeper patch. What follows are the unified diffs for the
# set of deltas contained in the patch. The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User: dlenev
# Host: mockturtle.local
# Root: /home/dlenev/src/mysql-5.0-bg24491
--- 1.212/sql/item.h 2007-01-10 17:16:57 +03:00
+++ 1.213/sql/item.h 2007-01-10 17:16:57 +03:00
@@ -337,24 +337,19 @@
{
save_table_list= context->table_list;
save_first_name_resolution_table= context->first_name_resolution_table;
- save_next_name_resolution_table= (context->first_name_resolution_table) ?
- context->first_name_resolution_table->
- next_name_resolution_table :
- NULL;
save_resolve_in_select_list= context->resolve_in_select_list;
save_next_local= table_list->next_local;
+ save_next_name_resolution_table= table_list->next_name_resolution_table;
}
/* Restore a name resolution context from saved state. */
void restore_state(Name_resolution_context *context, TABLE_LIST *table_list)
{
- table_list->next_local= save_next_local;
- context->table_list= save_table_list;
- context->first_name_resolution_table= save_first_name_resolution_table;
- if (context->first_name_resolution_table)
- context->first_name_resolution_table->
- next_name_resolution_table= save_next_name_resolution_table;
- context->resolve_in_select_list= save_resolve_in_select_list;
+ table_list->next_local= save_next_local;
+ table_list->next_name_resolution_table= save_next_name_resolution_table;
+ context->table_list= save_table_list;
+ context->first_name_resolution_table= save_first_name_resolution_table;
+ context->resolve_in_select_list= save_resolve_in_select_list;
}
};
--- 1.82/mysql-test/r/ps.result 2007-01-10 17:16:57 +03:00
+++ 1.83/mysql-test/r/ps.result 2007-01-10 17:16:57 +03:00
@@ -1496,4 +1496,20 @@
Slow_queries 1
deallocate prepare no_index;
deallocate prepare sq;
+drop table if exists t1;
+create table t1 (id int primary key auto_increment, value varchar(10));
+insert into t1 (id, value) values (1, 'FIRST'), (2, 'SECOND'), (3, 'THIRD');
+prepare stmt from "insert into t1 (id, value) select * from (select 4 as i, 'FOURTH' as
v) as y on duplicate key update v = 'DUP'";
+execute stmt;
+ERROR 42S22: Unknown column 'v' in 'field list'
+execute stmt;
+ERROR 42S22: Unknown column 'v' in 'field list'
+deallocate prepare stmt;
+prepare stmt from "insert into t1 (id, value) select * from (select 4 as id, 'FOURTH' as
value) as y on duplicate key update y.value = 'DUP'";
+execute stmt;
+ERROR 42S22: Unknown column 'y.value' in 'field list'
+execute stmt;
+ERROR 42S22: Unknown column 'y.value' in 'field list'
+deallocate prepare stmt;
+drop table t1;
End of 5.0 tests.
--- 1.79/mysql-test/t/ps.test 2007-01-10 17:16:57 +03:00
+++ 1.80/mysql-test/t/ps.test 2007-01-10 17:16:57 +03:00
@@ -1540,4 +1540,34 @@
deallocate prepare no_index;
deallocate prepare sq;
+
+#
+# BUG#24491 "using alias from source table in insert ... on duplicate key"
+#
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+create table t1 (id int primary key auto_increment, value varchar(10));
+insert into t1 (id, value) values (1, 'FIRST'), (2, 'SECOND'), (3, 'THIRD');
+# Let us prepare INSERT ... SELECT ... ON DUPLICATE KEY UPDATE statement
+# which in its ON DUPLICATE KEY clause erroneously tries to assign value
+# to a column which is mentioned only in SELECT part.
+prepare stmt from "insert into t1 (id, value) select * from (select 4 as i, 'FOURTH' as
v) as y on duplicate key update v = 'DUP'";
+# Both first and second attempts to execute it should fail
+--error ER_BAD_FIELD_ERROR
+execute stmt;
+--error ER_BAD_FIELD_ERROR
+execute stmt;
+deallocate prepare stmt;
+# And now the same test for more complex case which is more close
+# to the one that was reported originally.
+prepare stmt from "insert into t1 (id, value) select * from (select 4 as id, 'FOURTH' as
value) as y on duplicate key update y.value = 'DUP'";
+--error ER_BAD_FIELD_ERROR
+execute stmt;
+--error ER_BAD_FIELD_ERROR
+execute stmt;
+deallocate prepare stmt;
+drop table t1;
+
+
--echo End of 5.0 tests.
| Thread |
|---|
| • bk commit into 5.0 tree (dlenev:1.2322) BUG#24491 | dlenev | 10 Jan |