diff --git a/mysql-test/suite/sql_sequence/default.result b/mysql-test/suite/sql_sequence/default.result index d767b5fb030..abed796cb75 100644 --- a/mysql-test/suite/sql_sequence/default.result +++ b/mysql-test/suite/sql_sequence/default.result @@ -195,3 +195,105 @@ INSERT INTO t1 () values (); EXECUTE stmt; DROP TABLE t1; DROP SEQUENCE s; +# +# MDEV-29540 Incorrect sequence values in INSERT SELECT +# +CREATE SEQUENCE s1; +CREATE TABLE t1 ( +a BIGINT UNSIGNED NOT NULL PRIMARY KEY +DEFAULT (NEXT VALUE FOR s1), +b CHAR(1) NOT NULL +); +INSERT INTO t1 (b) VALUES ('a'); +INSERT INTO t1 (b) VALUES ('b'), ('c'); +INSERT INTO t1 (b) VALUES ('d'); +INSERT INTO t1 (b) SELECT c FROM ( +SELECT 'e' as c +UNION +SELECT 'f' + UNION +SELECT 'g' +) der; +SELECT a, b FROM t1; +a b +1 a +2 b +3 c +4 d +5 e +6 f +7 g +ALTER SEQUENCE s1 RESTART; +INSERT INTO t1 (b) SELECT c FROM ( +SELECT 'a' as c +UNION +SELECT 'b' + UNION +SELECT 'c' + UNION +SELECT 'd' + UNION +SELECT 'e' + UNION +SELECT 'f' + UNION +SELECT 'g' +) der; +ERROR 23000: Duplicate entry '1' for key 'PRIMARY' +ALTER SEQUENCE s1 RESTART; +INSERT IGNORE INTO t1 (b) SELECT c FROM ( +SELECT 'a' as c +UNION +SELECT 'b' + UNION +SELECT 'c' + UNION +SELECT 'd' + UNION +SELECT 'e' + UNION +SELECT 'f' + UNION +SELECT 'g' +) der; +Warnings: +Warning 1062 Duplicate entry '1' for key 'PRIMARY' +Warning 1062 Duplicate entry '2' for key 'PRIMARY' +Warning 1062 Duplicate entry '3' for key 'PRIMARY' +Warning 1062 Duplicate entry '4' for key 'PRIMARY' +Warning 1062 Duplicate entry '5' for key 'PRIMARY' +Warning 1062 Duplicate entry '6' for key 'PRIMARY' +Warning 1062 Duplicate entry '7' for key 'PRIMARY' +SELECT a, b FROM t1; +a b +1 a +2 b +3 c +4 d +5 e +6 f +7 g +INSERT IGNORE INTO t1 (b) SELECT c FROM ( +SELECT 'h' as c +UNION +SELECT 'i' + UNION +SELECT 'j' +) der; +SELECT a, b FROM t1; +a b +1 a +2 b +3 c +4 d +5 e +6 f +7 g +8 h +9 i +10 j +DROP TABLE t1; +DROP SEQUENCE s1; +# +# End of 10.3 tests +# diff --git a/mysql-test/suite/sql_sequence/default.test b/mysql-test/suite/sql_sequence/default.test index e7c13211013..28eb71e39cc 100644 --- a/mysql-test/suite/sql_sequence/default.test +++ b/mysql-test/suite/sql_sequence/default.test @@ -135,3 +135,83 @@ EXECUTE stmt; # Cleanup DROP TABLE t1; DROP SEQUENCE s; + +--echo # +--echo # MDEV-29540 Incorrect sequence values in INSERT SELECT +--echo # + +CREATE SEQUENCE s1; +CREATE TABLE t1 ( + a BIGINT UNSIGNED NOT NULL PRIMARY KEY + DEFAULT (NEXT VALUE FOR s1), + b CHAR(1) NOT NULL +); + +INSERT INTO t1 (b) VALUES ('a'); +INSERT INTO t1 (b) VALUES ('b'), ('c'); +INSERT INTO t1 (b) VALUES ('d'); +INSERT INTO t1 (b) SELECT c FROM ( + SELECT 'e' as c + UNION + SELECT 'f' + UNION + SELECT 'g' +) der; + +SELECT a, b FROM t1; + +ALTER SEQUENCE s1 RESTART; + +--error ER_DUP_ENTRY +INSERT INTO t1 (b) SELECT c FROM ( + SELECT 'a' as c + UNION + SELECT 'b' + UNION + SELECT 'c' + UNION + SELECT 'd' + UNION + SELECT 'e' + UNION + SELECT 'f' + UNION + SELECT 'g' +) der; + +ALTER SEQUENCE s1 RESTART; + +INSERT IGNORE INTO t1 (b) SELECT c FROM ( + SELECT 'a' as c + UNION + SELECT 'b' + UNION + SELECT 'c' + UNION + SELECT 'd' + UNION + SELECT 'e' + UNION + SELECT 'f' + UNION + SELECT 'g' +) der; + +SELECT a, b FROM t1; + +INSERT IGNORE INTO t1 (b) SELECT c FROM ( + SELECT 'h' as c + UNION + SELECT 'i' + UNION + SELECT 'j' +) der; + +SELECT a, b FROM t1; + +DROP TABLE t1; +DROP SEQUENCE s1; + +--echo # +--echo # End of 10.3 tests +--echo # diff --git a/sql/sql_class.h b/sql/sql_class.h index 4d1f5b40db5..9ac973dc640 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -5455,7 +5455,7 @@ class select_insert :public select_result_interceptor { int prepare(List &list, SELECT_LEX_UNIT *u); virtual int prepare2(JOIN *join); virtual int send_data(List &items); - virtual void store_values(List &values); + virtual bool store_values(List &values, bool ignore_errors); virtual bool can_rollback_data() { return 0; } bool prepare_eof(); bool send_ok_packet(); @@ -5497,7 +5497,7 @@ public: int prepare(List &list, SELECT_LEX_UNIT *u); int binlog_show_create_table(TABLE **tables, uint count); - void store_values(List &values); + bool store_values(List &values, bool ignore_errors); bool send_eof(); virtual void abort_result_set(); virtual bool can_rollback_data() { return 1; } diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index a180147190b..43007b2243a 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -3928,9 +3928,7 @@ int select_insert::send_data(List &values) DBUG_RETURN(0); thd->count_cuted_fields= CHECK_FIELD_WARN; // Calculate cuted fields - store_values(values); - if (table->default_field && - unlikely(table->update_default_fields(info.ignore))) + if (store_values(values, info.ignore)) DBUG_RETURN(1); thd->count_cuted_fields= CHECK_FIELD_ERROR_FOR_NULL; if (unlikely(thd->is_error())) @@ -3988,18 +3986,19 @@ int select_insert::send_data(List &values) } -void select_insert::store_values(List &values) +bool select_insert::store_values(List &values, bool ignore_errors) { DBUG_ENTER("select_insert::store_values"); + bool error; if (fields->elements) - fill_record_n_invoke_before_triggers(thd, table, *fields, values, 1, - TRG_EVENT_INSERT); + error= fill_record_n_invoke_before_triggers(thd, table, *fields, values, + ignore_errors, TRG_EVENT_INSERT); else - fill_record_n_invoke_before_triggers(thd, table, table->field_to_fill(), - values, 1, TRG_EVENT_INSERT); + error= fill_record_n_invoke_before_triggers(thd, table, table->field_to_fill(), + values, ignore_errors, TRG_EVENT_INSERT); - DBUG_VOID_RETURN; + DBUG_RETURN(error); } bool select_insert::prepare_eof() @@ -4670,10 +4669,10 @@ select_create::binlog_show_create_table(TABLE **tables, uint count) return result; } -void select_create::store_values(List &values) +bool select_create::store_values(List &values, bool ignore_errors) { - fill_record_n_invoke_before_triggers(thd, table, field, values, 1, - TRG_EVENT_INSERT); + return fill_record_n_invoke_before_triggers(thd, table, field, values, + ignore_errors, TRG_EVENT_INSERT); }