mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
Merge gbichot3.local:/home/mysql_src/mysql-5.1-interval-move-next-insert-id
into gbichot3.local:/home/mysql_src/mysql-5.1
This commit is contained in:
@ -411,7 +411,6 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
|
||||
table->next_number_field=table->found_next_number_field;
|
||||
|
||||
error=0;
|
||||
id=0;
|
||||
thd->proc_info="update";
|
||||
if (duplic != DUP_ERROR || ignore)
|
||||
table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
|
||||
@ -518,16 +517,6 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
|
||||
else
|
||||
#endif
|
||||
error=write_record(thd, table ,&info);
|
||||
/*
|
||||
If auto_increment values are used, save the first one
|
||||
for LAST_INSERT_ID() and for the update log.
|
||||
We can't use insert_id() as we don't want to touch the
|
||||
last_insert_id_used flag.
|
||||
*/
|
||||
if (! id && thd->insert_id_used)
|
||||
{ // Get auto increment value
|
||||
id= thd->last_insert_id;
|
||||
}
|
||||
if (error)
|
||||
break;
|
||||
thd->row_count++;
|
||||
@ -535,6 +524,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
|
||||
|
||||
free_underlaid_joins(thd, &thd->lex->select_lex);
|
||||
joins_freed= TRUE;
|
||||
table->file->ha_release_auto_increment();
|
||||
|
||||
/*
|
||||
Now all rows are inserted. Time to update logs and sends response to
|
||||
@ -545,7 +535,6 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
|
||||
{
|
||||
if (!error)
|
||||
{
|
||||
id=0; // No auto_increment id
|
||||
info.copied=values_list.elements;
|
||||
end_delayed_insert(thd);
|
||||
}
|
||||
@ -559,11 +548,6 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
|
||||
table->file->print_error(my_errno,MYF(0));
|
||||
error=1;
|
||||
}
|
||||
if (id && values_list.elements != 1)
|
||||
thd->insert_id(id); // For update log
|
||||
else if (table->next_number_field && info.copied)
|
||||
id=table->next_number_field->val_int(); // Return auto_increment value
|
||||
|
||||
transactional_table= table->file->has_transactions();
|
||||
|
||||
if ((changed= (info.copied || info.deleted || info.updated)))
|
||||
@ -612,18 +596,27 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
|
||||
}
|
||||
}
|
||||
thd->proc_info="end";
|
||||
/*
|
||||
We'll report to the client this id:
|
||||
- if the table contains an autoincrement column and we successfully
|
||||
inserted an autogenerated value, the autogenerated value.
|
||||
- if the table contains no autoincrement column and LAST_INSERT_ID(X) was
|
||||
called, X.
|
||||
- if the table contains an autoincrement column, and some rows were
|
||||
inserted, the id of the last "inserted" row (if IGNORE, that value may not
|
||||
have been really inserted but ignored).
|
||||
*/
|
||||
id= (thd->first_successful_insert_id_in_cur_stmt > 0) ?
|
||||
thd->first_successful_insert_id_in_cur_stmt :
|
||||
(thd->arg_of_last_insert_id_function ?
|
||||
thd->first_successful_insert_id_in_prev_stmt :
|
||||
((table->next_number_field && info.copied) ?
|
||||
table->next_number_field->val_int() : 0));
|
||||
table->next_number_field=0;
|
||||
thd->count_cuted_fields= CHECK_FIELD_IGNORE;
|
||||
thd->next_insert_id=0; // Reset this if wrongly used
|
||||
if (duplic != DUP_ERROR || ignore)
|
||||
table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
|
||||
|
||||
/* Reset value of LAST_INSERT_ID if no rows where inserted */
|
||||
if (!info.copied && thd->insert_id_used)
|
||||
{
|
||||
thd->insert_id(0);
|
||||
id=0;
|
||||
}
|
||||
if (error)
|
||||
goto abort;
|
||||
if (values_list.elements == 1 && (!(thd->options & OPTION_WARNINGS) ||
|
||||
@ -645,8 +638,6 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
|
||||
thd->row_count_func= info.copied+info.deleted+info.updated;
|
||||
::send_ok(thd, (ulong) thd->row_count_func, id, buff);
|
||||
}
|
||||
if (table != NULL)
|
||||
table->file->release_auto_increment();
|
||||
thd->abort_on_warning= 0;
|
||||
DBUG_RETURN(FALSE);
|
||||
|
||||
@ -656,7 +647,7 @@ abort:
|
||||
end_delayed_insert(thd);
|
||||
#endif
|
||||
if (table != NULL)
|
||||
table->file->release_auto_increment();
|
||||
table->file->ha_release_auto_increment();
|
||||
if (!joins_freed)
|
||||
free_underlaid_joins(thd, &thd->lex->select_lex);
|
||||
thd->abort_on_warning= 0;
|
||||
@ -965,6 +956,8 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
|
||||
int error, trg_error= 0;
|
||||
char *key=0;
|
||||
MY_BITMAP *save_read_set, *save_write_set;
|
||||
ulonglong prev_insert_id= table->file->next_insert_id;
|
||||
ulonglong insert_id_for_cur_row= 0;
|
||||
DBUG_ENTER("write_record");
|
||||
|
||||
info->records++;
|
||||
@ -977,6 +970,17 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
|
||||
while ((error=table->file->ha_write_row(table->record[0])))
|
||||
{
|
||||
uint key_nr;
|
||||
/*
|
||||
If we do more than one iteration of this loop, from the second one the
|
||||
row will have an explicit value in the autoinc field, which was set at
|
||||
the first call of handler::update_auto_increment(). So we must save
|
||||
the autogenerated value to avoid thd->insert_id_for_cur_row to become
|
||||
0.
|
||||
*/
|
||||
if (table->file->insert_id_for_cur_row > 0)
|
||||
insert_id_for_cur_row= table->file->insert_id_for_cur_row;
|
||||
else
|
||||
table->file->insert_id_for_cur_row= insert_id_for_cur_row;
|
||||
bool is_duplicate_key_error;
|
||||
if (table->file->is_fatal_error(error, HA_CHECK_DUP))
|
||||
goto err;
|
||||
@ -1007,7 +1011,7 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
|
||||
if (info->handle_duplicates == DUP_REPLACE &&
|
||||
table->next_number_field &&
|
||||
key_nr == table->s->next_number_index &&
|
||||
table->file->auto_increment_column_changed)
|
||||
(insert_id_for_cur_row > 0))
|
||||
goto err;
|
||||
if (table->file->ha_table_flags() & HA_DUPLICATE_POS)
|
||||
{
|
||||
@ -1078,15 +1082,21 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
|
||||
goto err;
|
||||
}
|
||||
info->updated++;
|
||||
|
||||
/*
|
||||
If ON DUP KEY UPDATE updates a row instead of inserting one, and
|
||||
there is an auto_increment column, then SELECT LAST_INSERT_ID()
|
||||
returns the id of the updated row:
|
||||
*/
|
||||
if (table->next_number_field)
|
||||
table->file->adjust_next_insert_id_after_explicit_value(table->next_number_field->val_int());
|
||||
|
||||
{
|
||||
longlong field_val= table->next_number_field->val_int();
|
||||
thd->record_first_successful_insert_id_in_cur_stmt(field_val);
|
||||
table->file->adjust_next_insert_id_after_explicit_value(field_val);
|
||||
}
|
||||
trg_error= (table->triggers &&
|
||||
table->triggers->process_triggers(thd, TRG_EVENT_UPDATE,
|
||||
TRG_ACTION_AFTER, TRUE));
|
||||
info->copied++;
|
||||
goto ok_or_after_trg_err;
|
||||
info->copiedgoto ok_or_after_trg_err;
|
||||
}
|
||||
else /* DUP_REPLACE */
|
||||
{
|
||||
@ -1114,6 +1124,7 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
|
||||
table->record[0])))
|
||||
goto err;
|
||||
info->deleted++;
|
||||
thd->record_first_successful_insert_id_in_cur_stmt(table->file->insert_id_for_cur_row);
|
||||
/*
|
||||
Since we pretend that we have done insert we should call
|
||||
its after triggers.
|
||||
@ -1142,6 +1153,7 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
|
||||
}
|
||||
}
|
||||
}
|
||||
thd->record_first_successful_insert_id_in_cur_stmt(table->file->insert_id_for_cur_row);
|
||||
/*
|
||||
Restore column maps if they where replaced during an duplicate key
|
||||
problem.
|
||||
@ -1155,12 +1167,13 @@ 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->restore_auto_increment();
|
||||
table->file->restore_auto_increment(prev_insert_id);
|
||||
goto ok_or_after_trg_err;
|
||||
}
|
||||
|
||||
after_trg_n_copied_inc:
|
||||
info->copied++;
|
||||
thd->record_first_successful_insert_id_in_cur_stmt(table->file->insert_id_for_cur_row);
|
||||
trg_error= (table->triggers &&
|
||||
table->triggers->process_triggers(thd, TRG_EVENT_INSERT,
|
||||
TRG_ACTION_AFTER, TRUE));
|
||||
@ -1243,8 +1256,9 @@ public:
|
||||
char *record;
|
||||
enum_duplicates dup;
|
||||
time_t start_time;
|
||||
bool query_start_used,last_insert_id_used,insert_id_used, ignore, log_query;
|
||||
ulonglong last_insert_id;
|
||||
bool query_start_used, ignore, log_query;
|
||||
bool stmt_depends_on_first_successful_insert_id_in_prev_stmt;
|
||||
ulonglong first_successful_insert_id_in_prev_stmt;
|
||||
timestamp_auto_set_type timestamp_field_type;
|
||||
LEX_STRING query;
|
||||
|
||||
@ -1655,9 +1669,16 @@ write_delayed(THD *thd,TABLE *table, enum_duplicates duplic,
|
||||
memcpy(row->record, table->record[0], table->s->reclength);
|
||||
row->start_time= thd->start_time;
|
||||
row->query_start_used= thd->query_start_used;
|
||||
row->last_insert_id_used= thd->last_insert_id_used;
|
||||
row->insert_id_used= thd->insert_id_used;
|
||||
row->last_insert_id= thd->last_insert_id;
|
||||
/*
|
||||
those are for the binlog: LAST_INSERT_ID() has been evaluated at this
|
||||
time, so record does not need it, but statement-based binlogging of the
|
||||
INSERT will need when the row is actually inserted.
|
||||
As for SET INSERT_ID, DELAYED does not honour it (BUG#20830).
|
||||
*/
|
||||
row->stmt_depends_on_first_successful_insert_id_in_prev_stmt=
|
||||
thd->stmt_depends_on_first_successful_insert_id_in_prev_stmt;
|
||||
row->first_successful_insert_id_in_prev_stmt=
|
||||
thd->first_successful_insert_id_in_prev_stmt;
|
||||
row->timestamp_field_type= table->timestamp_field_type;
|
||||
|
||||
di->rows.push_back(row);
|
||||
@ -1911,6 +1932,7 @@ pthread_handler_t handle_delayed_insert(void *arg)
|
||||
MYSQL_LOCK *lock=thd->lock;
|
||||
thd->lock=0;
|
||||
pthread_mutex_unlock(&di->mutex);
|
||||
di->table->file->ha_release_auto_increment();
|
||||
mysql_unlock_tables(thd, lock);
|
||||
di->group_count=0;
|
||||
pthread_mutex_lock(&di->mutex);
|
||||
@ -2023,13 +2045,6 @@ bool delayed_insert::handle_inserts(void)
|
||||
table->file->extra(HA_EXTRA_WRITE_CACHE);
|
||||
pthread_mutex_lock(&mutex);
|
||||
|
||||
/* Reset auto-increment cacheing */
|
||||
if (thd.clear_next_insert_id)
|
||||
{
|
||||
thd.next_insert_id= 0;
|
||||
thd.clear_next_insert_id= 0;
|
||||
}
|
||||
|
||||
while ((row=rows.get()))
|
||||
{
|
||||
stacked_inserts--;
|
||||
@ -2038,9 +2053,12 @@ bool delayed_insert::handle_inserts(void)
|
||||
|
||||
thd.start_time=row->start_time;
|
||||
thd.query_start_used=row->query_start_used;
|
||||
thd.last_insert_id=row->last_insert_id;
|
||||
thd.last_insert_id_used=row->last_insert_id_used;
|
||||
thd.insert_id_used=row->insert_id_used;
|
||||
/* for the binlog, forget auto_increment ids generated by previous rows */
|
||||
thd.auto_inc_intervals_in_cur_stmt_for_binlog.empty();
|
||||
thd.first_successful_insert_id_in_prev_stmt=
|
||||
row->first_successful_insert_id_in_prev_stmt;
|
||||
thd.stmt_depends_on_first_successful_insert_id_in_prev_stmt=
|
||||
row->stmt_depends_on_first_successful_insert_id_in_prev_stmt;
|
||||
table->timestamp_field_type= row->timestamp_field_type;
|
||||
|
||||
info.ignore= row->ignore;
|
||||
@ -2232,7 +2250,7 @@ select_insert::select_insert(TABLE_LIST *table_list_par, TABLE *table_par,
|
||||
enum_duplicates duplic,
|
||||
bool ignore_check_option_errors)
|
||||
:table_list(table_list_par), table(table_par), fields(fields_par),
|
||||
last_insert_id(0),
|
||||
autoinc_value_of_last_inserted_row(0),
|
||||
insert_into_view(table_list_par && table_list_par->view != 0)
|
||||
{
|
||||
bzero((char*) &info,sizeof(info));
|
||||
@ -2440,16 +2458,21 @@ bool select_insert::send_data(List<Item> &values)
|
||||
}
|
||||
if (table->next_number_field)
|
||||
{
|
||||
/*
|
||||
If no value has been autogenerated so far, we need to remember the
|
||||
value we just saw, we may need to send it to client in the end.
|
||||
*/
|
||||
if (thd->first_successful_insert_id_in_cur_stmt == 0) // optimization
|
||||
autoinc_value_of_last_inserted_row=
|
||||
table->next_number_field->val_int();
|
||||
/*
|
||||
Clear auto-increment field for the next record, if triggers are used
|
||||
we will clear it twice, but this should be cheap.
|
||||
*/
|
||||
table->next_number_field->reset();
|
||||
if (!last_insert_id && thd->insert_id_used)
|
||||
last_insert_id= thd->insert_id();
|
||||
}
|
||||
}
|
||||
table->file->release_auto_increment();
|
||||
table->file->ha_release_auto_increment();
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
|
||||
@ -2511,8 +2534,6 @@ void select_insert::send_error(uint errcode,const char *err)
|
||||
{
|
||||
if (!table->file->has_transactions())
|
||||
{
|
||||
if (last_insert_id)
|
||||
thd->insert_id(last_insert_id); // For binary log
|
||||
if (mysql_bin_log.is_open())
|
||||
{
|
||||
thd->binlog_query(THD::ROW_QUERY_TYPE, thd->query, thd->query_length,
|
||||
@ -2532,6 +2553,7 @@ void select_insert::send_error(uint errcode,const char *err)
|
||||
bool select_insert::send_eof()
|
||||
{
|
||||
int error,error2;
|
||||
ulonglong id;
|
||||
DBUG_ENTER("select_insert::send_eof");
|
||||
|
||||
error= (!thd->prelocked_mode) ? table->file->ha_end_bulk_insert():0;
|
||||
@ -2557,8 +2579,6 @@ bool select_insert::send_eof()
|
||||
thd->options|= OPTION_STATUS_NO_TRANS_UPDATE;
|
||||
}
|
||||
|
||||
if (last_insert_id)
|
||||
thd->insert_id(last_insert_id); // For binary log
|
||||
/*
|
||||
Write to binlog before commiting transaction. No statement will
|
||||
be written by the binlog_query() below in RBR mode. All the
|
||||
@ -2588,7 +2608,13 @@ bool select_insert::send_eof()
|
||||
sprintf(buff, ER(ER_INSERT_INFO), (ulong) info.records,
|
||||
(ulong) (info.deleted+info.updated), (ulong) thd->cuted_fields);
|
||||
thd->row_count_func= info.copied+info.deleted+info.updated;
|
||||
::send_ok(thd, (ulong) thd->row_count_func, last_insert_id, buff);
|
||||
|
||||
id= (thd->first_successful_insert_id_in_cur_stmt > 0) ?
|
||||
thd->first_successful_insert_id_in_cur_stmt :
|
||||
(thd->arg_of_last_insert_id_function ?
|
||||
thd->first_successful_insert_id_in_prev_stmt :
|
||||
(info.copied ? autoinc_value_of_last_inserted_row : 0));
|
||||
::send_ok(thd, (ulong) thd->row_count_func, id, buff);
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user