Loading mysql-test/r/insert_update.result +62 −0 Original line number Diff line number Diff line Loading @@ -105,3 +105,65 @@ a b 8 28 9 29 drop table t1; CREATE TABLE t1 (a INT, b INT, c INT, UNIQUE (A), UNIQUE(B)); INSERT t1 VALUES (1,2,10), (3,4,20); INSERT t1 SELECT 5,6,30 FROM DUAL ON DUPLICATE KEY UPDATE c=c+100; SELECT * FROM t1; a b c 1 2 10 3 4 20 5 6 30 INSERT t1 SELECT 5,7,40 FROM DUAL ON DUPLICATE KEY UPDATE c=c+100; SELECT * FROM t1; a b c 1 2 10 3 4 20 5 6 130 INSERT t1 SELECT 8,4,50 FROM DUAL ON DUPLICATE KEY UPDATE c=c+1000; SELECT * FROM t1; a b c 1 2 10 3 4 1020 5 6 130 INSERT t1 SELECT 1,4,60 FROM DUAL ON DUPLICATE KEY UPDATE c=c+10000; SELECT * FROM t1; a b c 1 2 10010 3 4 1020 5 6 130 INSERT t1 SELECT 1,9,70 FROM DUAL ON DUPLICATE KEY UPDATE c=c+100000, b=4; ERROR 23000: Duplicate entry '4' for key 2 SELECT * FROM t1; a b c 1 2 10010 3 4 1020 5 6 130 TRUNCATE TABLE t1; INSERT t1 VALUES (1,2,10), (3,4,20); CREATE TABLE t2 (x INT, y INT, z INT, d INT); INSERT t2 VALUES (5,6,30,1), (7,4,40,1), (8,9,60,1); INSERT t2 VALUES (2,1,11,2), (7,4,40,2); INSERT t1 SELECT x,y,z FROM t2 WHERE d=1 ON DUPLICATE KEY UPDATE c=c+100; SELECT * FROM t1; a b c 1 2 10 3 4 120 5 6 30 8 9 60 INSERT t1 SET a=5 ON DUPLICATE KEY UPDATE b=0; SELECT * FROM t1; a b c 1 2 10 3 4 120 5 0 30 8 9 60 INSERT t1 SELECT x,y,z FROM t2 WHERE d=2 ON DUPLICATE KEY UPDATE c=c+VALUES(a); SELECT *, VALUES(a) FROM t1; a b c VALUES(a) 1 2 10 NULL 3 4 127 NULL 5 0 30 NULL 8 9 60 NULL 2 1 11 NULL DROP TABLE t1; DROP TABLE t2; mysql-test/t/insert_update.test +31 −0 Original line number Diff line number Diff line Loading @@ -48,3 +48,34 @@ disable_info; select * from t1; drop table t1; # WorkLog #2274 - enable INSERT .. SELECT .. UPDATE syntax # Same tests as beginning of this test except that insert source # is a result from a select statement # CREATE TABLE t1 (a INT, b INT, c INT, UNIQUE (A), UNIQUE(B)); INSERT t1 VALUES (1,2,10), (3,4,20); INSERT t1 SELECT 5,6,30 FROM DUAL ON DUPLICATE KEY UPDATE c=c+100; SELECT * FROM t1; INSERT t1 SELECT 5,7,40 FROM DUAL ON DUPLICATE KEY UPDATE c=c+100; SELECT * FROM t1; INSERT t1 SELECT 8,4,50 FROM DUAL ON DUPLICATE KEY UPDATE c=c+1000; SELECT * FROM t1; INSERT t1 SELECT 1,4,60 FROM DUAL ON DUPLICATE KEY UPDATE c=c+10000; SELECT * FROM t1; -- error 1062 INSERT t1 SELECT 1,9,70 FROM DUAL ON DUPLICATE KEY UPDATE c=c+100000, b=4; SELECT * FROM t1; TRUNCATE TABLE t1; INSERT t1 VALUES (1,2,10), (3,4,20); CREATE TABLE t2 (x INT, y INT, z INT, d INT); INSERT t2 VALUES (5,6,30,1), (7,4,40,1), (8,9,60,1); INSERT t2 VALUES (2,1,11,2), (7,4,40,2); INSERT t1 SELECT x,y,z FROM t2 WHERE d=1 ON DUPLICATE KEY UPDATE c=c+100; SELECT * FROM t1; INSERT t1 SET a=5 ON DUPLICATE KEY UPDATE b=0; SELECT * FROM t1; INSERT t1 SELECT x,y,z FROM t2 WHERE d=2 ON DUPLICATE KEY UPDATE c=c+VALUES(a); SELECT *, VALUES(a) FROM t1; DROP TABLE t1; DROP TABLE t2; sql/mysql_priv.h +0 −1 Original line number Diff line number Diff line Loading @@ -362,7 +362,6 @@ bool check_merge_table_access(THD *thd, char *db, TABLE_LIST *table_list); int multi_update_precheck(THD *thd, TABLE_LIST *tables); int multi_delete_precheck(THD *thd, TABLE_LIST *tables, uint *table_count); int insert_select_precheck(THD *thd, TABLE_LIST *tables); int update_precheck(THD *thd, TABLE_LIST *tables); int delete_precheck(THD *thd, TABLE_LIST *tables); int insert_precheck(THD *thd, TABLE_LIST *tables); Loading sql/sql_class.h +10 −0 Original line number Diff line number Diff line Loading @@ -1238,6 +1238,16 @@ class select_insert :public select_result_interceptor { bzero((char*) &info,sizeof(info)); info.handle_duplicates=duplic; } select_insert(TABLE *table_par, List<Item> *fields_par, List<Item> *update_fields, List<Item> *update_values, enum_duplicates duplic) :table(table_par), fields(fields_par), last_insert_id(0) { bzero((char*) &info,sizeof(info)); info.handle_duplicates=duplic; info.update_fields= update_fields; info.update_values= update_values; } ~select_insert(); int prepare(List<Item> &list, SELECT_LEX_UNIT *u); bool send_data(List<Item> &items); Loading sql/sql_insert.cc +15 −12 Original line number Diff line number Diff line Loading @@ -197,15 +197,6 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, thd->used_tables=0; values= its++; if (duplic == DUP_UPDATE && !table->insert_values) { /* it should be allocated before Item::fix_fields() */ table->insert_values= (byte *)alloc_root(thd->mem_root, table->rec_buff_length); if (!table->insert_values) goto abort; } if (mysql_prepare_insert(thd, table_list, insert_table_list, table, fields, values, update_fields, update_values, duplic)) Loading Loading @@ -448,14 +439,24 @@ int mysql_prepare_insert(THD *thd, TABLE_LIST *table_list, enum_duplicates duplic) { DBUG_ENTER("mysql_prepare_insert"); if (check_insert_fields(thd, table, fields, *values, 1) || if (duplic == DUP_UPDATE && !table->insert_values) { /* it should be allocated before Item::fix_fields() */ table->insert_values= (byte *)alloc_root(thd->mem_root, table->rec_buff_length); if (!table->insert_values) DBUG_RETURN(-1); } if ((values && check_insert_fields(thd, table, fields, *values, 1)) || setup_tables(insert_table_list) || setup_fields(thd, 0, insert_table_list, *values, 0, 0, 0) || (values && setup_fields(thd, 0, insert_table_list, *values, 0, 0, 0)) || (duplic == DUP_UPDATE && (setup_fields(thd, 0, insert_table_list, update_fields, 1, 0, 0) || setup_fields(thd, 0, insert_table_list, update_values, 1, 0, 0)))) DBUG_RETURN(-1); if (find_real_table_in_list(table_list->next, if ((thd->lex->sql_command==SQLCOM_INSERT || thd->lex->sql_command==SQLCOM_REPLACE) && find_real_table_in_list(table_list->next, table_list->db, table_list->real_name)) { my_error(ER_UPDATE_TABLE_USED, MYF(0), table_list->real_name); Loading Loading @@ -550,8 +551,10 @@ int write_record(TABLE *table,COPY_INFO *info) that matches, is updated. If update causes a conflict again, an error is returned */ DBUG_ASSERT(table->insert_values != NULL); store_record(table,insert_values); restore_record(table,record[1]); DBUG_ASSERT(info->update_fields->elements==info->update_values->elements); if (fill_record(*info->update_fields, *info->update_values, 0)) goto err; if ((error=table->file->update_row(table->record[1],table->record[0]))) Loading Loading
mysql-test/r/insert_update.result +62 −0 Original line number Diff line number Diff line Loading @@ -105,3 +105,65 @@ a b 8 28 9 29 drop table t1; CREATE TABLE t1 (a INT, b INT, c INT, UNIQUE (A), UNIQUE(B)); INSERT t1 VALUES (1,2,10), (3,4,20); INSERT t1 SELECT 5,6,30 FROM DUAL ON DUPLICATE KEY UPDATE c=c+100; SELECT * FROM t1; a b c 1 2 10 3 4 20 5 6 30 INSERT t1 SELECT 5,7,40 FROM DUAL ON DUPLICATE KEY UPDATE c=c+100; SELECT * FROM t1; a b c 1 2 10 3 4 20 5 6 130 INSERT t1 SELECT 8,4,50 FROM DUAL ON DUPLICATE KEY UPDATE c=c+1000; SELECT * FROM t1; a b c 1 2 10 3 4 1020 5 6 130 INSERT t1 SELECT 1,4,60 FROM DUAL ON DUPLICATE KEY UPDATE c=c+10000; SELECT * FROM t1; a b c 1 2 10010 3 4 1020 5 6 130 INSERT t1 SELECT 1,9,70 FROM DUAL ON DUPLICATE KEY UPDATE c=c+100000, b=4; ERROR 23000: Duplicate entry '4' for key 2 SELECT * FROM t1; a b c 1 2 10010 3 4 1020 5 6 130 TRUNCATE TABLE t1; INSERT t1 VALUES (1,2,10), (3,4,20); CREATE TABLE t2 (x INT, y INT, z INT, d INT); INSERT t2 VALUES (5,6,30,1), (7,4,40,1), (8,9,60,1); INSERT t2 VALUES (2,1,11,2), (7,4,40,2); INSERT t1 SELECT x,y,z FROM t2 WHERE d=1 ON DUPLICATE KEY UPDATE c=c+100; SELECT * FROM t1; a b c 1 2 10 3 4 120 5 6 30 8 9 60 INSERT t1 SET a=5 ON DUPLICATE KEY UPDATE b=0; SELECT * FROM t1; a b c 1 2 10 3 4 120 5 0 30 8 9 60 INSERT t1 SELECT x,y,z FROM t2 WHERE d=2 ON DUPLICATE KEY UPDATE c=c+VALUES(a); SELECT *, VALUES(a) FROM t1; a b c VALUES(a) 1 2 10 NULL 3 4 127 NULL 5 0 30 NULL 8 9 60 NULL 2 1 11 NULL DROP TABLE t1; DROP TABLE t2;
mysql-test/t/insert_update.test +31 −0 Original line number Diff line number Diff line Loading @@ -48,3 +48,34 @@ disable_info; select * from t1; drop table t1; # WorkLog #2274 - enable INSERT .. SELECT .. UPDATE syntax # Same tests as beginning of this test except that insert source # is a result from a select statement # CREATE TABLE t1 (a INT, b INT, c INT, UNIQUE (A), UNIQUE(B)); INSERT t1 VALUES (1,2,10), (3,4,20); INSERT t1 SELECT 5,6,30 FROM DUAL ON DUPLICATE KEY UPDATE c=c+100; SELECT * FROM t1; INSERT t1 SELECT 5,7,40 FROM DUAL ON DUPLICATE KEY UPDATE c=c+100; SELECT * FROM t1; INSERT t1 SELECT 8,4,50 FROM DUAL ON DUPLICATE KEY UPDATE c=c+1000; SELECT * FROM t1; INSERT t1 SELECT 1,4,60 FROM DUAL ON DUPLICATE KEY UPDATE c=c+10000; SELECT * FROM t1; -- error 1062 INSERT t1 SELECT 1,9,70 FROM DUAL ON DUPLICATE KEY UPDATE c=c+100000, b=4; SELECT * FROM t1; TRUNCATE TABLE t1; INSERT t1 VALUES (1,2,10), (3,4,20); CREATE TABLE t2 (x INT, y INT, z INT, d INT); INSERT t2 VALUES (5,6,30,1), (7,4,40,1), (8,9,60,1); INSERT t2 VALUES (2,1,11,2), (7,4,40,2); INSERT t1 SELECT x,y,z FROM t2 WHERE d=1 ON DUPLICATE KEY UPDATE c=c+100; SELECT * FROM t1; INSERT t1 SET a=5 ON DUPLICATE KEY UPDATE b=0; SELECT * FROM t1; INSERT t1 SELECT x,y,z FROM t2 WHERE d=2 ON DUPLICATE KEY UPDATE c=c+VALUES(a); SELECT *, VALUES(a) FROM t1; DROP TABLE t1; DROP TABLE t2;
sql/mysql_priv.h +0 −1 Original line number Diff line number Diff line Loading @@ -362,7 +362,6 @@ bool check_merge_table_access(THD *thd, char *db, TABLE_LIST *table_list); int multi_update_precheck(THD *thd, TABLE_LIST *tables); int multi_delete_precheck(THD *thd, TABLE_LIST *tables, uint *table_count); int insert_select_precheck(THD *thd, TABLE_LIST *tables); int update_precheck(THD *thd, TABLE_LIST *tables); int delete_precheck(THD *thd, TABLE_LIST *tables); int insert_precheck(THD *thd, TABLE_LIST *tables); Loading
sql/sql_class.h +10 −0 Original line number Diff line number Diff line Loading @@ -1238,6 +1238,16 @@ class select_insert :public select_result_interceptor { bzero((char*) &info,sizeof(info)); info.handle_duplicates=duplic; } select_insert(TABLE *table_par, List<Item> *fields_par, List<Item> *update_fields, List<Item> *update_values, enum_duplicates duplic) :table(table_par), fields(fields_par), last_insert_id(0) { bzero((char*) &info,sizeof(info)); info.handle_duplicates=duplic; info.update_fields= update_fields; info.update_values= update_values; } ~select_insert(); int prepare(List<Item> &list, SELECT_LEX_UNIT *u); bool send_data(List<Item> &items); Loading
sql/sql_insert.cc +15 −12 Original line number Diff line number Diff line Loading @@ -197,15 +197,6 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, thd->used_tables=0; values= its++; if (duplic == DUP_UPDATE && !table->insert_values) { /* it should be allocated before Item::fix_fields() */ table->insert_values= (byte *)alloc_root(thd->mem_root, table->rec_buff_length); if (!table->insert_values) goto abort; } if (mysql_prepare_insert(thd, table_list, insert_table_list, table, fields, values, update_fields, update_values, duplic)) Loading Loading @@ -448,14 +439,24 @@ int mysql_prepare_insert(THD *thd, TABLE_LIST *table_list, enum_duplicates duplic) { DBUG_ENTER("mysql_prepare_insert"); if (check_insert_fields(thd, table, fields, *values, 1) || if (duplic == DUP_UPDATE && !table->insert_values) { /* it should be allocated before Item::fix_fields() */ table->insert_values= (byte *)alloc_root(thd->mem_root, table->rec_buff_length); if (!table->insert_values) DBUG_RETURN(-1); } if ((values && check_insert_fields(thd, table, fields, *values, 1)) || setup_tables(insert_table_list) || setup_fields(thd, 0, insert_table_list, *values, 0, 0, 0) || (values && setup_fields(thd, 0, insert_table_list, *values, 0, 0, 0)) || (duplic == DUP_UPDATE && (setup_fields(thd, 0, insert_table_list, update_fields, 1, 0, 0) || setup_fields(thd, 0, insert_table_list, update_values, 1, 0, 0)))) DBUG_RETURN(-1); if (find_real_table_in_list(table_list->next, if ((thd->lex->sql_command==SQLCOM_INSERT || thd->lex->sql_command==SQLCOM_REPLACE) && find_real_table_in_list(table_list->next, table_list->db, table_list->real_name)) { my_error(ER_UPDATE_TABLE_USED, MYF(0), table_list->real_name); Loading Loading @@ -550,8 +551,10 @@ int write_record(TABLE *table,COPY_INFO *info) that matches, is updated. If update causes a conflict again, an error is returned */ DBUG_ASSERT(table->insert_values != NULL); store_record(table,insert_values); restore_record(table,record[1]); DBUG_ASSERT(info->update_fields->elements==info->update_values->elements); if (fill_record(*info->update_fields, *info->update_values, 0)) goto err; if ((error=table->file->update_row(table->record[1],table->record[0]))) Loading