diff options
Diffstat (limited to 'sql/sql_insert.cc')
-rw-r--r-- | sql/sql_insert.cc | 70 |
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 |