Below is the list of changes that have just been committed into a local
5.0 repository of evgen. When evgen 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, 2006-12-24 00:18:42+03:00, evgen@stripped +3 -0
Bug#25123: ON DUPLICATE KEY clause allows fields not from the insert table.
When inserting into a join-based view update fields from the ON DUPLICATE
KEY UPDATE wasn't checked to be from the table being inserted into and was
silently ignored.
The new check_view_single_update() function is added. It performs check for
insert/update fields being from the same single table of the view.
mysql-test/r/insert.result@stripped, 2006-12-24 00:15:24+03:00, evgen@stripped +21 -0
Added a test case for bug#25123: ON DUPLICATE KEY clause allows fields not from the
insert table.
mysql-test/t/insert.test@stripped, 2006-12-24 00:14:52+03:00, evgen@stripped +18 -0
Added a test case for bug#25123: ON DUPLICATE KEY clause allows fields not from the
insert table.
sql/sql_insert.cc@stripped, 2006-12-24 00:15:38+03:00, evgen@stripped +74 -20
Bug#25123: ON DUPLICATE KEY clause allows fields not from the insert table.
The new check_view_single_update() function is added. It performs check for
insert/update fields being from the same single table of the view.
# 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: evgen
# Host: moonbone.local
# Root: /work/25123-bug-5.0-opt-mysql
--- 1.206/sql/sql_insert.cc 2006-10-23 11:50:46 +04:00
+++ 1.207/sql/sql_insert.cc 2006-12-24 00:15:38 +03:00
@@ -81,6 +81,66 @@
#define my_safe_afree(ptr, size, min_length) if (size > min_length)
my_free(ptr,MYF(0))
#endif
+/*
+ Check if insert/update fields are from the same single table of a view.
+
+ SYNOPSIS
+ check_view_single_update()
+ fields The insert/update fields to be checked.
+ view The view for insert.
+ map [in/out] The insert table map.
+
+ NOTE
+ This function is called in 2 cases:
+ 1) to check insert fields. In this case *map will be set to 0.
+ Insert fields are checked to be all from the same single underlying
+ table of the given view. Otherwise the error is thrown. Found table
+ map is returned in the map parameter.
+ 2) to check update fields of the ON DUPLICATE KEY UPDATE clause.
+ In this case *map contains table_map found on the previous call.
+ Update fields are checked to be from the same table as the insert
+ fields.
+
+ RETURN
+ 0 OK
+ 1 Error
+*/
+
+bool check_view_single_update(List<Item> &fields, TABLE_LIST *view,
+ table_map *map)
+{
+ /* it is join view => we need to find table for update */
+ List_iterator_fast<Item> it(fields);
+ Item *item;
+ TABLE_LIST *tbl= 0; // reset for call to check_single_table()
+ table_map tables= 0;
+
+ while ((item= it++))
+ tables|= item->used_tables();
+
+ /* Check found map against provided map */
+ if (*map)
+ {
+ if (tables != *map)
+ goto error;
+ /* Already checked */
+ return FALSE;
+ }
+
+ if (view->check_single_table(&tbl, tables, view) || tbl == 0)
+ goto error;
+
+ view->table= tbl->table;
+ *map= tables;
+
+ return FALSE;
+
+error:
+ my_error(ER_VIEW_MULTIUPDATE, MYF(0),
+ view->view_db.str, view->view_name.str);
+ return TRUE;
+}
+
/*
Check if insert fields are correct.
@@ -105,7 +165,7 @@
static int check_insert_fields(THD *thd, TABLE_LIST *table_list,
List<Item> &fields, List<Item>
&values,
- bool check_unique)
+ bool check_unique, table_map *map)
{
TABLE *table= table_list->table;
@@ -178,21 +238,9 @@
if (table_list->effective_algorithm == VIEW_ALGORITHM_MERGE)
{
- /* it is join view => we need to find table for update */
- List_iterator_fast<Item> it(fields);
- Item *item;
- TABLE_LIST *tbl= 0; // reset for call to check_single_table()
- table_map map= 0;
-
- while ((item= it++))
- map|= item->used_tables();
- if (table_list->check_single_table(&tbl, map, table_list) || tbl == 0)
- {
- my_error(ER_VIEW_MULTIUPDATE, MYF(0),
- table_list->view_db.str, table_list->view_name.str);
+ if (check_view_single_update(fields, table_list, map))
return -1;
- }
- table_list->table= table= tbl->table;
+ table= table_list->table;
}
if (check_unique && thd->dupp_field)
@@ -242,7 +290,7 @@
*/
static int check_update_fields(THD *thd, TABLE_LIST *insert_table_list,
- List<Item> &update_fields)
+ List<Item> &update_fields, table_map *map)
{
TABLE *table= insert_table_list->table;
query_id_t timestamp_query_id;
@@ -265,6 +313,10 @@
if (setup_fields(thd, 0, update_fields, 1, 0, 0))
return -1;
+ if (insert_table_list->effective_algorithm == VIEW_ALGORITHM_MERGE &&
+ check_view_single_update(update_fields, insert_table_list, map))
+ return -1;
+
if (table->timestamp_field)
{
/* Don't set timestamp column if this is modified. */
@@ -911,6 +963,7 @@
Name_resolution_context_state ctx_state;
bool insert_into_view= (table_list->view != 0);
bool res= 0;
+ table_map map= 0;
DBUG_ENTER("mysql_prepare_insert");
DBUG_PRINT("enter", ("table_list 0x%lx, table 0x%lx, view %d",
(ulong)table_list, (ulong)table,
@@ -960,12 +1013,12 @@
/* Prepare the fields in the statement. */
if (values &&
!(res= check_insert_fields(thd, context->table_list, fields, *values,
- !insert_into_view) ||
+ !insert_into_view, &map) ||
setup_fields(thd, 0, *values, 0, 0, 0)) &&
duplic == DUP_UPDATE)
{
select_lex->no_wrap_view_item= TRUE;
- res= check_update_fields(thd, context->table_list, update_fields);
+ res= check_update_fields(thd, context->table_list, update_fields, &map);
select_lex->no_wrap_view_item= FALSE;
/*
When we are not using GROUP BY we can refer to other tables in the
@@ -2290,6 +2343,7 @@
{
LEX *lex= thd->lex;
int res;
+ table_map map= 0;
SELECT_LEX *lex_current_select_save= lex->current_select;
DBUG_ENTER("select_insert::prepare");
@@ -2301,7 +2355,7 @@
*/
lex->current_select= &lex->select_lex;
res= check_insert_fields(thd, table_list, *fields, values,
- !insert_into_view) ||
+ !insert_into_view, &map) ||
setup_fields(thd, 0, values, 0, 0, 0);
if (info.handle_duplicates == DUP_UPDATE)
@@ -2319,7 +2373,7 @@
lex->select_lex.no_wrap_view_item= TRUE;
res= res || check_update_fields(thd, context->table_list,
- *info.update_fields);
+ *info.update_fields, &map);
lex->select_lex.no_wrap_view_item= FALSE;
/*
When we are not using GROUP BY we can refer to other tables in the
--- 1.25/mysql-test/r/insert.result 2006-08-02 16:15:46 +04:00
+++ 1.26/mysql-test/r/insert.result 2006-12-24 00:15:24 +03:00
@@ -331,3 +331,24 @@
row_count()
1
drop table t1;
+create table t1 (f1 int unique, f2 int);
+create table t2 (f3 int, f4 int);
+create view v1 as select * from t1, t2 where f1= f3;
+insert into t1 values (1,11), (2,22);
+insert into t2 values (1,12), (2,24);
+insert into v1 (f1) values (3) on duplicate key update f3= f3 + 10;
+ERROR HY000: Can not modify more than one base table through a join view 'test.v1'
+insert into v1 (f1) values (3) on duplicate key update f1= f3 + 10;
+select * from t1;
+f1 f2
+1 11
+2 22
+3 NULL
+insert into v1 (f1) values (3) on duplicate key update f1= f3 + 10;
+select * from t1;
+f1 f2
+1 11
+2 22
+12 NULL
+drop view v1;
+drop table t1,t2;
--- 1.23/mysql-test/t/insert.test 2006-06-16 20:21:21 +04:00
+++ 1.24/mysql-test/t/insert.test 2006-12-24 00:14:52 +03:00
@@ -210,3 +210,21 @@
insert into t1 values (5, 5) on duplicate key update data= data + 10;
select row_count();
drop table t1;
+
+#
+# Bug#25123: ON DUPLICATE KEY clause allows fields not from the insert table
+#
+create table t1 (f1 int unique, f2 int);
+create table t2 (f3 int, f4 int);
+create view v1 as select * from t1, t2 where f1= f3;
+insert into t1 values (1,11), (2,22);
+insert into t2 values (1,12), (2,24);
+--error 1393
+insert into v1 (f1) values (3) on duplicate key update f3= f3 + 10;
+insert into v1 (f1) values (3) on duplicate key update f1= f3 + 10;
+select * from t1;
+insert into v1 (f1) values (3) on duplicate key update f1= f3 + 10;
+select * from t1;
+drop view v1;
+drop table t1,t2;
+
| Thread |
|---|
| • bk commit into 5.0 tree (evgen:1.2351) BUG#25123 | eugene | 23 Dec |