diff options
author | unknown <dkatz@damien-katzs-computer.local> | 2007-07-16 14:53:05 -0400 |
---|---|---|
committer | unknown <dkatz@damien-katzs-computer.local> | 2007-07-16 14:53:05 -0400 |
commit | fcc51efc4df3814d1ea21cc92dc0fe719bddb613 (patch) | |
tree | ae6011049845b705082b3dbb8bdb41958fab225f | |
parent | f3fd6168ffc3c2d10d479aed088c1b01f5242d06 (diff) | |
download | mariadb-git-fcc51efc4df3814d1ea21cc92dc0fe719bddb613.tar.gz |
Bug #29692 Single row inserts can incorrectly report a huge number of row insertions
This bug was caused by unitialized value that was the result of a bad 5.0 merge.
sql/sql_class.h:
Readded comments lost in a bad merge.
sql/sql_insert.cc:
Fixed code to completely initialize (zero) the "COPY_INFO info" var in the same manner as the delayed write code.
Readded a change that was lost in a bad merge.
tests/mysql_client_test.c:
Test case added for bug#29692.
-rw-r--r-- | sql/sql_class.h | 20 | ||||
-rw-r--r-- | sql/sql_insert.cc | 9 | ||||
-rw-r--r-- | tests/mysql_client_test.c | 33 |
3 files changed, 54 insertions, 8 deletions
diff --git a/sql/sql_class.h b/sql/sql_class.h index 004c4aa4f5a..52feee47499 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -65,11 +65,23 @@ typedef struct st_user_var_events #define RP_LOCK_LOG_IS_ALREADY_LOCKED 1 #define RP_FORCE_ROTATE 2 +/* + The COPY_INFO structure is used by INSERT/REPLACE code. + The schema of the row counting by the INSERT/INSERT ... ON DUPLICATE KEY + UPDATE code: + If a row is inserted then the copied variable is incremented. + If a row is updated by the INSERT ... ON DUPLICATE KEY UPDATE and the + new data differs from the old one then the copied and the updated + variables are incremented. + The touched variable is incremented if a row was touched by the update part + of the INSERT ... ON DUPLICATE KEY UPDATE no matter whether the row + was actually changed or not. +*/ typedef struct st_copy_info { - ha_rows records; - ha_rows deleted; - ha_rows updated; - ha_rows copied; + ha_rows records; /* Number of processed records */ + ha_rows deleted; /* Number of deleted records */ + ha_rows updated; /* Number of updated records */ + ha_rows copied; /* Number of copied records */ ha_rows error_count; ha_rows touched; /* Number of touched records */ enum enum_duplicates handle_duplicates; diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 11db88d8f5e..b4cf5231827 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -661,7 +661,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, /* Fill in the given fields and dump it to the table file */ - info.records= info.deleted= info.copied= info.updated= 0; + bzero((char*) &info,sizeof(info)); info.ignore= ignore; info.handle_duplicates=duplic; info.update_fields= &update_fields; @@ -1421,6 +1421,10 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info) goto before_trg_err; table->file->restore_auto_increment(prev_insert_id); + if (table->next_number_field) + table->file->adjust_next_insert_id_after_explicit_value( + table->next_number_field->val_int()); + info->touched++; if ((table->file->ha_table_flags() & HA_PARTIAL_COLUMN_READ) || compare_record(table)) { @@ -1448,9 +1452,6 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info) handled separately by THD::arg_of_last_insert_id_function. */ insert_id_for_cur_row= table->file->insert_id_for_cur_row= 0; - if (table->next_number_field) - table->file->adjust_next_insert_id_after_explicit_value( - table->next_number_field->val_int()); trg_error= (table->triggers && table->triggers->process_triggers(thd, TRG_EVENT_UPDATE, TRG_ACTION_AFTER, TRUE)); diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index cb1561ad6f5..51f627a16de 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -16272,6 +16272,38 @@ static void test_bug27592() /* + Bug #29692 Single row inserts can incorrectly report a huge number of + row insertions +*/ + +static void test_bug29692() +{ + MYSQL* conn; + + if (!(conn= mysql_init(NULL))) + { + myerror("test_bug29692 init failed"); + exit(1); + } + + if (!(mysql_real_connect(conn, opt_host, opt_user, + opt_password, opt_db ? opt_db:"test", opt_port, + opt_unix_socket, CLIENT_FOUND_ROWS))) + { + myerror("test_bug29692 connection failed"); + mysql_close(mysql); + exit(1); + } + myquery(mysql_query(conn, "drop table if exists t1")); + myquery(mysql_query(conn, "create table t1(f1 int)")); + myquery(mysql_query(conn, "insert into t1 values(1)")); + DIE_UNLESS(1 == mysql_affected_rows(conn)); + myquery(mysql_query(conn, "drop table t1")); + mysql_close(conn); +} + + +/* Read and parse arguments and MySQL options from my.cnf */ @@ -16560,6 +16592,7 @@ static struct my_tests_st my_tests[]= { { "test_bug28505", test_bug28505 }, { "test_bug28934", test_bug28934 }, { "test_bug27592", test_bug27592 }, + { "test_bug29692", test_bug29692 }, { 0, 0 } }; |