summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorunknown <kaa@polly.(none)>2007-11-26 18:36:05 +0300
committerunknown <kaa@polly.(none)>2007-11-26 18:36:05 +0300
commit1836b736000595b3b63c03b1a6db01003b01e395 (patch)
treeca57ddca0c31ed0d9dd2165d21390fb5e10f30df /sql
parentac0612f5599a8a0038dcf4031a85e92b67bac1d0 (diff)
downloadmariadb-git-1836b736000595b3b63c03b1a6db01003b01e395.tar.gz
5.0 version of the fix for bug #9481: mysql_insert_id() returns 0 after
insert ... select. The 5.0 manual page for mysql_insert_id() does not mention anything about INSERT ... SELECT, though its current behavior is incosistent with what the manual says about the plain INSERT. Fixed by changing the AUTO_INCREMENT and mysql_insert_id() handling logic in INSERT ... SELECT to be consistent with the INSERT behavior, the manual, and the changes in 5.1 introduced by WL3146: - mysql_insert_id() now returns the first automatically generated AUTO_INCREMENT value that was successfully inserted by INSERT ... SELECT - if an INSERT ... SELECT statement is executed, and no automatically generated value is successfully inserted, mysql_insert_id() now returns the ID of the last inserted row. sql/sql_class.h: Replaced last_insert_id with autoinc_value_of_last_inserted_row to be consistent with 5.1 code. sql/sql_insert.cc: Revised the AUTO_INCREMENT and mysql_insert_id() handling logic in INSERT ... SELECT to be consistent with INSERT behavior, the manual, and changes in 5.1 introduced by WL3146: - mysql_insert_id() now returns the first automatically generated AUTO_INCREMENT value that was successfully inserted; - if an INSERT ... SELECT statement is executed, and no automatically generated value is successfully inserted, mysql_insert_id() now returns the ID of the last inserted row. tests/mysql_client_test.c: Backported the test cases related to INSERT ... SELECT and mysql_insert_id() from WL3146 patch to 5.0.
Diffstat (limited to 'sql')
-rw-r--r--sql/sql_class.h3
-rw-r--r--sql/sql_insert.cc48
2 files changed, 42 insertions, 9 deletions
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 93a9d4d6da2..5a5607469d9 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -2048,7 +2048,8 @@ class select_insert :public select_result_interceptor {
TABLE_LIST *table_list;
TABLE *table;
List<Item> *fields;
- ulonglong last_insert_id;
+ ulonglong autoinc_value_of_last_inserted_row; // not autogenerated
+ ulonglong autoinc_value_of_first_inserted_row; // autogenerated
COPY_INFO info;
bool insert_into_view;
bool is_bulk_insert_mode;
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index 770bbd1349d..70f73f90be4 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -2644,7 +2644,8 @@ 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),
+ autoinc_value_of_first_inserted_row(0),
insert_into_view(table_list_par && table_list_par->view != 0),
is_bulk_insert_mode(FALSE)
{
@@ -2902,14 +2903,24 @@ 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->insert_id_used)
+ 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->last_insert_id;
+ if (!autoinc_value_of_last_inserted_row && thd->insert_id_used)
+ autoinc_value_of_last_inserted_row= thd->last_insert_id;
}
}
+
+ if (thd->insert_id_used && !autoinc_value_of_first_inserted_row)
+ autoinc_value_of_first_inserted_row= thd->last_insert_id;
+
DBUG_RETURN(error);
}
@@ -2938,6 +2949,7 @@ bool select_insert::send_eof()
{
int error, error2;
bool changed, transactional_table= table->file->has_transactions();
+ ulonglong id;
DBUG_ENTER("select_insert::send_eof");
error= (!thd->prelocked_mode) ? table->file->end_bulk_insert():0;
@@ -2959,8 +2971,17 @@ bool select_insert::send_eof()
DBUG_ASSERT(transactional_table || !changed ||
thd->transaction.stmt.modified_non_trans_table);
- if (last_insert_id)
- thd->insert_id(info.copied ? last_insert_id : 0); // For binary log
+ // For binary log
+ if (autoinc_value_of_last_inserted_row)
+ {
+ if (info.copied)
+ thd->insert_id(autoinc_value_of_last_inserted_row);
+ else
+ {
+ autoinc_value_of_first_inserted_row= 0;
+ thd->insert_id(0);
+ }
+ }
/* Write to binlog before commiting transaction */
if (mysql_bin_log.is_open())
{
@@ -2987,7 +3008,9 @@ bool select_insert::send_eof()
thd->row_count_func= info.copied + info.deleted +
((thd->client_capabilities & CLIENT_FOUND_ROWS) ?
info.touched : info.updated);
- ::send_ok(thd, (ulong) thd->row_count_func, last_insert_id, buff);
+ id= autoinc_value_of_first_inserted_row > 0 ?
+ autoinc_value_of_first_inserted_row : thd->last_insert_id;
+ ::send_ok(thd, (ulong) thd->row_count_func, id, buff);
DBUG_RETURN(0);
}
@@ -3016,8 +3039,17 @@ void select_insert::abort()
if ((changed= info.copied || info.deleted || info.updated) &&
!transactional_table)
{
- if (last_insert_id)
- thd->insert_id(last_insert_id); // For binary log
+ // For binary log
+ if (autoinc_value_of_last_inserted_row)
+ {
+ if (info.copied)
+ thd->insert_id(autoinc_value_of_last_inserted_row);
+ else
+ {
+ autoinc_value_of_first_inserted_row= 0;
+ thd->insert_id(0);
+ }
+ }
if (mysql_bin_log.is_open())
{
Query_log_event qinfo(thd, thd->query, thd->query_length,