Commit c9cba597 authored by Aleksey Midenkov's avatar Aleksey Midenkov

MDEV-17333 Assertion in update_auto_increment() upon exotic LOAD

While `handler::next_insert_id` is restored on duplicate key errors
`part_share->next_auto_inc_val` is not restored which causes
discrepancy.
parent a92f3146
...@@ -238,3 +238,23 @@ delete from t1 where a=32767; ...@@ -238,3 +238,23 @@ delete from t1 where a=32767;
--error HA_ERR_AUTOINC_ERANGE --error HA_ERR_AUTOINC_ERANGE
insert into t1 values(NULL); insert into t1 values(NULL);
drop table t1; drop table t1;
--echo #
--echo # MDEV-17333 Assertion in update_auto_increment() upon exotic LOAD
--echo #
--source include/have_partition.inc
let $mysqld_datadir= `select @@datadir`;
--write_file $mysqld_datadir/test/load.data
1 1
0 2
3 3
4 1
0 1
6 6
EOF
create or replace table t1 (pk int auto_increment, x int, primary key(pk), unique key(x))
with system versioning partition by system_time interval 2 day
(partition p1 history, partition pn current);
load data infile 'load.data' ignore into table t1;
--remove_file $mysqld_datadir/test/load.data
drop table t1;
...@@ -264,6 +264,17 @@ delete from t1 where a=32767; ...@@ -264,6 +264,17 @@ delete from t1 where a=32767;
insert into t1 values(NULL); insert into t1 values(NULL);
ERROR 22003: Out of range value for column 'a' at row 1 ERROR 22003: Out of range value for column 'a' at row 1
drop table t1; drop table t1;
#
# MDEV-17333 Assertion in update_auto_increment() upon exotic LOAD
#
create or replace table t1 (pk int auto_increment, x int, primary key(pk), unique key(x))
with system versioning partition by system_time interval 2 day
(partition p1 history, partition pn current);
load data infile 'load.data' ignore into table t1;
Warnings:
Warning 1062 Duplicate entry '1' for key 'x'
Warning 1062 Duplicate entry '1' for key 'x'
drop table t1;
create table t1 (pk int auto_increment primary key, f varchar(20)); create table t1 (pk int auto_increment primary key, f varchar(20));
insert t1 (f) values ('a'), ('b'), ('c'), ('d'); insert t1 (f) values ('a'), ('b'), ('c'), ('d');
select null, f into outfile 'load.data' from t1 limit 1; select null, f into outfile 'load.data' from t1 limit 1;
......
...@@ -270,3 +270,14 @@ delete from t1 where a=32767; ...@@ -270,3 +270,14 @@ delete from t1 where a=32767;
insert into t1 values(NULL); insert into t1 values(NULL);
ERROR 22003: Out of range value for column 'a' at row 1 ERROR 22003: Out of range value for column 'a' at row 1
drop table t1; drop table t1;
#
# MDEV-17333 Assertion in update_auto_increment() upon exotic LOAD
#
create or replace table t1 (pk int auto_increment, x int, primary key(pk), unique key(x))
with system versioning partition by system_time interval 2 day
(partition p1 history, partition pn current);
load data infile 'load.data' ignore into table t1;
Warnings:
Warning 1062 Duplicate entry '1' for key 'x'
Warning 1062 Duplicate entry '1' for key 'x'
drop table t1;
...@@ -92,6 +92,7 @@ class Partition_share : public Handler_share ...@@ -92,6 +92,7 @@ class Partition_share : public Handler_share
bool auto_inc_initialized; bool auto_inc_initialized;
mysql_mutex_t auto_inc_mutex; /**< protecting auto_inc val */ mysql_mutex_t auto_inc_mutex; /**< protecting auto_inc val */
ulonglong next_auto_inc_val; /**< first non reserved value */ ulonglong next_auto_inc_val; /**< first non reserved value */
ulonglong prev_auto_inc_val; /**< stored next_auto_inc_val */
/** /**
Hash of partition names. Initialized in the first ha_partition::open() Hash of partition names. Initialized in the first ha_partition::open()
for the table_share. After that it is read-only, i.e. no locking required. for the table_share. After that it is read-only, i.e. no locking required.
...@@ -103,6 +104,7 @@ class Partition_share : public Handler_share ...@@ -103,6 +104,7 @@ class Partition_share : public Handler_share
Partition_share() Partition_share()
: auto_inc_initialized(false), : auto_inc_initialized(false),
next_auto_inc_val(0), next_auto_inc_val(0),
prev_auto_inc_val(0),
partition_name_hash_initialized(false), partition_name_hash_initialized(false),
partition_names(NULL) partition_names(NULL)
{ {
...@@ -371,6 +373,19 @@ class ha_partition :public handler ...@@ -371,6 +373,19 @@ class ha_partition :public handler
MY_BITMAP m_locked_partitions; MY_BITMAP m_locked_partitions;
/** Stores shared auto_increment etc. */ /** Stores shared auto_increment etc. */
Partition_share *part_share; Partition_share *part_share;
/** Store and restore next_auto_inc_val over duplicate key errors. */
virtual void store_auto_increment()
{
DBUG_ASSERT(part_share);
part_share->prev_auto_inc_val= part_share->next_auto_inc_val;
handler::store_auto_increment();
}
virtual void restore_auto_increment()
{
DBUG_ASSERT(part_share);
part_share->next_auto_inc_val= part_share->prev_auto_inc_val;
handler::restore_auto_increment();
}
/** Temporary storage for new partitions Handler_shares during ALTER */ /** Temporary storage for new partitions Handler_shares during ALTER */
List<Parts_share_refs> m_new_partitions_share_refs; List<Parts_share_refs> m_new_partitions_share_refs;
/** Sorted array of partition ids in descending order of number of rows. */ /** Sorted array of partition ids in descending order of number of rows. */
......
...@@ -3008,6 +3008,10 @@ class handler :public Sql_alloc ...@@ -3008,6 +3008,10 @@ class handler :public Sql_alloc
*/ */
Handler_share **ha_share; Handler_share **ha_share;
/** Stores next_insert_id for handling duplicate key errors. */
ulonglong m_prev_insert_id;
public: public:
handler(handlerton *ht_arg, TABLE_SHARE *share_arg) handler(handlerton *ht_arg, TABLE_SHARE *share_arg)
:table_share(share_arg), table(0), :table_share(share_arg), table(0),
...@@ -3030,7 +3034,7 @@ class handler :public Sql_alloc ...@@ -3030,7 +3034,7 @@ class handler :public Sql_alloc
auto_inc_intervals_count(0), auto_inc_intervals_count(0),
m_psi(NULL), set_top_table_fields(FALSE), top_table(0), m_psi(NULL), set_top_table_fields(FALSE), top_table(0),
top_table_field(0), top_table_fields(0), top_table_field(0), top_table_fields(0),
m_lock_type(F_UNLCK), ha_share(NULL) m_lock_type(F_UNLCK), ha_share(NULL), m_prev_insert_id(0)
{ {
DBUG_PRINT("info", DBUG_PRINT("info",
("handler created F_UNLCK %d F_RDLCK %d F_WRLCK %d", ("handler created F_UNLCK %d F_RDLCK %d F_WRLCK %d",
...@@ -3700,6 +3704,16 @@ class handler :public Sql_alloc ...@@ -3700,6 +3704,16 @@ class handler :public Sql_alloc
insert_id_for_cur_row; insert_id_for_cur_row;
} }
/** Store and restore next_insert_id over duplicate key errors. */
virtual void store_auto_increment()
{
m_prev_insert_id= next_insert_id;
}
virtual void restore_auto_increment()
{
restore_auto_increment(m_prev_insert_id);
}
virtual void update_create_info(HA_CREATE_INFO *create_info) {} virtual void update_create_info(HA_CREATE_INFO *create_info) {}
int check_old_types(); int check_old_types();
virtual int assign_to_keycache(THD* thd, HA_CHECK_OPT* check_opt) virtual int assign_to_keycache(THD* thd, HA_CHECK_OPT* check_opt)
......
...@@ -1691,7 +1691,7 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info) ...@@ -1691,7 +1691,7 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
int error, trg_error= 0; int error, trg_error= 0;
char *key=0; char *key=0;
MY_BITMAP *save_read_set, *save_write_set; MY_BITMAP *save_read_set, *save_write_set;
ulonglong prev_insert_id= table->file->next_insert_id; table->file->store_auto_increment();
ulonglong insert_id_for_cur_row= 0; ulonglong insert_id_for_cur_row= 0;
ulonglong prev_insert_id_for_cur_row= 0; ulonglong prev_insert_id_for_cur_row= 0;
DBUG_ENTER("write_record"); DBUG_ENTER("write_record");
...@@ -1844,7 +1844,7 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info) ...@@ -1844,7 +1844,7 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
if (res == VIEW_CHECK_ERROR) if (res == VIEW_CHECK_ERROR)
goto before_trg_err; goto before_trg_err;
table->file->restore_auto_increment(prev_insert_id); table->file->restore_auto_increment();
info->touched++; info->touched++;
if (different_records) if (different_records)
{ {
...@@ -2038,7 +2038,7 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info) ...@@ -2038,7 +2038,7 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
if (!(thd->variables.old_behavior & if (!(thd->variables.old_behavior &
OLD_MODE_NO_DUP_KEY_WARNINGS_WITH_IGNORE)) OLD_MODE_NO_DUP_KEY_WARNINGS_WITH_IGNORE))
table->file->print_error(error, MYF(ME_JUST_WARNING)); table->file->print_error(error, MYF(ME_JUST_WARNING));
table->file->restore_auto_increment(prev_insert_id); table->file->restore_auto_increment();
goto ok_or_after_trg_err; goto ok_or_after_trg_err;
} }
...@@ -2061,7 +2061,7 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info) ...@@ -2061,7 +2061,7 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
table->file->print_error(error,MYF(0)); table->file->print_error(error,MYF(0));
before_trg_err: before_trg_err:
table->file->restore_auto_increment(prev_insert_id); table->file->restore_auto_increment();
if (key) if (key)
my_safe_afree(key, table->s->max_unique_length); my_safe_afree(key, table->s->max_unique_length);
table->column_bitmaps_set(save_read_set, save_write_set); table->column_bitmaps_set(save_read_set, save_write_set);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment