Commit 4cdbe25a authored by evgen@moonbone.local's avatar evgen@moonbone.local

Bug#28904: INSERT .. ON DUPLICATE was silently updating rows when it shouldn't.

When the INSERT .. ON DUPLICATE KEY UPDATE has to update a matched row but
the new data is the same as in the record then it returns as if
no rows were inserted or updated. Nevertheless the row is silently
updated. This leads to a situation when zero updated rows are reported 
in the case when data has actually been changed.

Now the write_record function updates a row only if new data differs from
that in the record.
parent c25c1781
...@@ -393,3 +393,17 @@ id c1 cnt ...@@ -393,3 +393,17 @@ id c1 cnt
1 0 3 1 0 3
2 2 1 2 2 1
DROP TABLE t1; DROP TABLE t1;
create table t1(f1 int primary key,
f2 timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP);
insert into t1(f1) values(1);
select @stamp1:=f2 from t1;
@stamp1:=f2
#
insert into t1(f1) values(1) on duplicate key update f1=1;
select @stamp2:=f2 from t1;
@stamp2:=f2
#
select if( @stamp1 = @stamp2, "correct", "wrong");
if( @stamp1 = @stamp2, "correct", "wrong")
correct
drop table t1;
...@@ -290,3 +290,19 @@ INSERT IGNORE INTO t1 (id,c1) SELECT * FROM t2 ...@@ -290,3 +290,19 @@ INSERT IGNORE INTO t1 (id,c1) SELECT * FROM t2
SELECT * FROM t1; SELECT * FROM t1;
DROP TABLE t1; DROP TABLE t1;
#
# Bug#28904: INSERT .. ON DUPLICATE was silently updating rows when it
# shouldn't.
#
create table t1(f1 int primary key,
f2 timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP);
insert into t1(f1) values(1);
--replace_column 1 #
select @stamp1:=f2 from t1;
--sleep 2
insert into t1(f1) values(1) on duplicate key update f1=1;
--replace_column 1 #
select @stamp2:=f2 from t1;
select if( @stamp1 = @stamp2, "correct", "wrong");
drop table t1;
...@@ -1404,23 +1404,18 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info) ...@@ -1404,23 +1404,18 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
goto before_trg_err; goto before_trg_err;
table->file->restore_auto_increment(); table->file->restore_auto_increment();
if ((error=table->file->update_row(table->record[1],table->record[0]))) if ((table->file->table_flags() & HA_PARTIAL_COLUMN_READ) ||
compare_record(table, thd->query_id))
{ {
if ((error == HA_ERR_FOUND_DUPP_KEY) && info->ignore) if ((error=table->file->update_row(table->record[1],table->record[0])))
{ {
goto ok_or_after_trg_err; if ((error == HA_ERR_FOUND_DUPP_KEY) && info->ignore)
{
goto ok_or_after_trg_err;
}
goto err;
} }
goto err;
}
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->table_flags() & HA_PARTIAL_COLUMN_READ) ||
compare_record(table, thd->query_id))
{
info->updated++; info->updated++;
trg_error= (table->triggers && trg_error= (table->triggers &&
table->triggers->process_triggers(thd, TRG_EVENT_UPDATE, table->triggers->process_triggers(thd, TRG_EVENT_UPDATE,
...@@ -1429,6 +1424,11 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info) ...@@ -1429,6 +1424,11 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
info->copied++; info->copied++;
} }
if (table->next_number_field)
table->file->adjust_next_insert_id_after_explicit_value(
table->next_number_field->val_int());
info->touched++;
goto ok_or_after_trg_err; goto ok_or_after_trg_err;
} }
else /* DUP_REPLACE */ else /* DUP_REPLACE */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment