summaryrefslogtreecommitdiff
path: root/sql/sql_insert.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/sql_insert.cc')
-rw-r--r--sql/sql_insert.cc70
1 files changed, 58 insertions, 12 deletions
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index 023792dddd0..599a892da9f 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -329,7 +329,7 @@ static int check_insert_fields(THD *thd, TABLE_LIST *table_list,
/*
- Check update fields for the timestamp field.
+ Check update fields for the timestamp and auto_increment fields.
SYNOPSIS
check_update_fields()
@@ -342,6 +342,9 @@ static int check_insert_fields(THD *thd, TABLE_LIST *table_list,
If the update fields include the timestamp field,
remove TIMESTAMP_AUTO_SET_ON_UPDATE from table->timestamp_field_type.
+ If the update fields include an autoinc field, set the
+ table->next_number_field_updated flag.
+
RETURN
0 OK
-1 Error
@@ -353,7 +356,9 @@ static int check_update_fields(THD *thd, TABLE_LIST *insert_table_list,
{
TABLE *table= insert_table_list->table;
my_bool timestamp_mark;
+ my_bool autoinc_mark;
LINT_INIT(timestamp_mark);
+ LINT_INIT(autoinc_mark);
if (table->timestamp_field)
{
@@ -365,6 +370,19 @@ static int check_update_fields(THD *thd, TABLE_LIST *insert_table_list,
table->timestamp_field->field_index);
}
+ table->next_number_field_updated= FALSE;
+
+ if (table->found_next_number_field)
+ {
+ /*
+ Unmark the auto_increment field so that we can check if this is modified
+ by update_fields
+ */
+ autoinc_mark= bitmap_test_and_clear(table->write_set,
+ table->found_next_number_field->
+ field_index);
+ }
+
/* Check the fields we are going to modify */
if (setup_fields(thd, 0, update_fields, MARK_COLUMNS_WRITE, 0, 0))
return -1;
@@ -386,6 +404,18 @@ static int check_update_fields(THD *thd, TABLE_LIST *insert_table_list,
bitmap_set_bit(table->write_set,
table->timestamp_field->field_index);
}
+
+ if (table->found_next_number_field)
+ {
+ if (bitmap_is_set(table->write_set,
+ table->found_next_number_field->field_index))
+ table->next_number_field_updated= TRUE;
+
+ if (autoinc_mark)
+ bitmap_set_bit(table->write_set,
+ table->found_next_number_field->field_index);
+ }
+
return 0;
}
@@ -827,10 +857,10 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
table->next_number_field=table->found_next_number_field;
#ifdef HAVE_REPLICATION
- if (thd->slave_thread &&
+ if (thd->rli_slave &&
(info.handle_duplicates == DUP_UPDATE) &&
(table->next_number_field != NULL) &&
- rpl_master_has_bug(&active_mi->rli, 24432, TRUE, NULL, NULL))
+ rpl_master_has_bug(thd->rli_slave, 24432, TRUE, NULL, NULL))
goto abort;
#endif
@@ -1570,6 +1600,7 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
MY_BITMAP *save_read_set, *save_write_set;
ulonglong prev_insert_id= table->file->next_insert_id;
ulonglong insert_id_for_cur_row= 0;
+ ulonglong prev_insert_id_for_cur_row= 0;
DBUG_ENTER("write_record");
info->records++;
@@ -1605,7 +1636,10 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
report error as usual. We will not do any duplicate key processing.
*/
if (info->ignore)
+ {
+ table->file->print_error(error, MYF(ME_JUST_WARNING));
goto ok_or_after_trg_err; /* Ignoring a not fatal error, return 0 */
+ }
goto err;
}
if ((int) (key_nr = table->file->get_dup_key(error)) < 0)
@@ -1695,6 +1729,7 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
if (info->ignore &&
!table->file->is_fatal_error(error, HA_CHECK_DUP_KEY))
{
+ table->file->print_error(error, MYF(ME_JUST_WARNING));
goto ok_or_after_trg_err;
}
goto err;
@@ -1712,6 +1747,7 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
INSERT query, which is handled separately by
THD::arg_of_last_insert_id_function.
*/
+ prev_insert_id_for_cur_row= table->file->insert_id_for_cur_row;
insert_id_for_cur_row= table->file->insert_id_for_cur_row= 0;
trg_error= (table->triggers &&
table->triggers->process_triggers(thd, TRG_EVENT_UPDATE,
@@ -1719,9 +1755,22 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
info->copied++;
}
- if (table->next_number_field)
- table->file->adjust_next_insert_id_after_explicit_value(
- table->next_number_field->val_int());
+ /*
+ Only update next_insert_id if the AUTO_INCREMENT value was explicitly
+ updated, so we don't update next_insert_id with the value from the
+ row being updated. Otherwise reset next_insert_id to what it was
+ before the duplicate key error, since that value is unused.
+ */
+ if (table->next_number_field_updated)
+ {
+ DBUG_ASSERT(table->next_number_field != NULL);
+
+ table->file->adjust_next_insert_id_after_explicit_value(table->next_number_field->val_int());
+ }
+ else
+ {
+ table->file->restore_auto_increment(prev_insert_id_for_cur_row);
+ }
goto ok_or_after_trg_err;
}
else /* DUP_REPLACE */
@@ -1810,6 +1859,7 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
if (!info->ignore ||
table->file->is_fatal_error(error, HA_CHECK_DUP))
goto err;
+ table->file->print_error(error, MYF(ME_JUST_WARNING));
table->file->restore_auto_increment(prev_insert_id);
goto ok_or_after_trg_err;
}
@@ -2788,9 +2838,6 @@ pthread_handler_t handle_delayed_insert(void *arg)
{
int error;
mysql_audit_release(thd);
-#if defined(HAVE_BROKEN_COND_TIMEDWAIT)
- error= mysql_cond_wait(&di->cond, &di->mutex);
-#else
error= mysql_cond_timedwait(&di->cond, &di->mutex, &abstime);
#ifdef EXTRA_DEBUG
if (error && error != EINTR && error != ETIMEDOUT)
@@ -2800,7 +2847,6 @@ pthread_handler_t handle_delayed_insert(void *arg)
error));
}
#endif
-#endif
if (error == ETIMEDOUT || error == ETIME)
thd->killed= KILL_CONNECTION;
}
@@ -3395,10 +3441,10 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
table->next_number_field=table->found_next_number_field;
#ifdef HAVE_REPLICATION
- if (thd->slave_thread &&
+ if (thd->rli_slave &&
(info.handle_duplicates == DUP_UPDATE) &&
(table->next_number_field != NULL) &&
- rpl_master_has_bug(&active_mi->rli, 24432, TRUE, NULL, NULL))
+ rpl_master_has_bug(thd->rli_slave, 24432, TRUE, NULL, NULL))
DBUG_RETURN(1);
#endif