summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/r/multi_update.result38
-rw-r--r--mysql-test/r/multi_update_innodb.result40
-rw-r--r--mysql-test/t/multi_update.test48
-rw-r--r--mysql-test/t/multi_update_innodb.test44
-rw-r--r--sql/sql_update.cc30
-rw-r--r--sql/table.h4
6 files changed, 190 insertions, 14 deletions
diff --git a/mysql-test/r/multi_update.result b/mysql-test/r/multi_update.result
index 5a3e7938121..c6ee170eef7 100644
--- a/mysql-test/r/multi_update.result
+++ b/mysql-test/r/multi_update.result
@@ -697,4 +697,40 @@ SELECT * FROM t1;
pk a
1 2
DROP TABLE t1;
-end of tests
+#
+# BUG#11882110: UPDATE REPORTS ER_KEY_NOT_FOUND IF TABLE IS
+# UPDATED TWICE
+#
+CREATE TABLE t1 (
+col_int_key int,
+pk int,
+col_int int,
+key(col_int_key),
+primary key (pk)
+) ENGINE=MyISAM;
+INSERT INTO t1 VALUES (1,2,3);
+
+CREATE TABLE t2 (
+col_int_key int,
+pk_1 int,
+pk_2 int,
+col_int int,
+key(col_int_key),
+primary key (pk_1,pk_2)
+) ENGINE=MyISAM;
+INSERT INTO t2 VALUES (1,2,3,4);
+
+UPDATE t1 AS A NATURAL JOIN t1 B SET A.pk=5,B.pk=7;
+
+SELECT * FROM t1;
+col_int_key pk col_int
+1 7 3
+
+UPDATE t2 AS A NATURAL JOIN t2 B SET A.pk_1=5,B.pk_1=7;
+
+UPDATE t2 AS A NATURAL JOIN t2 B SET A.pk_2=10,B.pk_2=11;
+
+SELECT * FROM t2;
+col_int_key pk_1 pk_2 col_int
+1 7 11 4
+DROP TABLE t1,t2;
diff --git a/mysql-test/r/multi_update_innodb.result b/mysql-test/r/multi_update_innodb.result
index 12a94accc1f..643287c3a93 100644
--- a/mysql-test/r/multi_update_innodb.result
+++ b/mysql-test/r/multi_update_innodb.result
@@ -27,3 +27,43 @@ pk a b
0 1 2
DROP VIEW v1;
DROP TABLE t1;
+#
+# BUG#11882110: UPDATE REPORTS ER_KEY_NOT_FOUND IF TABLE IS
+# UPDATED TWICE
+#
+CREATE TABLE t1 (
+col_int_key int,
+pk int,
+col_int int,
+key(col_int_key),
+primary key (pk)
+) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1,2,3);
+
+CREATE TABLE t2 (
+col_int_key int,
+pk_1 int,
+pk_2 int,
+col_int int,
+key(col_int_key),
+primary key (pk_1,pk_2)
+) ENGINE=InnoDB;
+INSERT INTO t2 VALUES (1,2,3,4);
+
+UPDATE t1 AS A NATURAL JOIN t1 B SET A.pk=5,B.pk=7;
+ERROR HY000: Primary key/partition key update is not allowed since the table is updated both as 'A' and 'B'.
+
+SELECT * FROM t1;
+col_int_key pk col_int
+1 2 3
+
+UPDATE t2 AS A NATURAL JOIN t2 B SET A.pk_1=5,B.pk_1=7;
+ERROR HY000: Primary key/partition key update is not allowed since the table is updated both as 'A' and 'B'.
+
+UPDATE t2 AS A NATURAL JOIN t2 B SET A.pk_2=10,B.pk_2=11;
+ERROR HY000: Primary key/partition key update is not allowed since the table is updated both as 'A' and 'B'.
+
+SELECT * FROM t2;
+col_int_key pk_1 pk_2 col_int
+1 2 3 4
+DROP TABLE t1,t2;
diff --git a/mysql-test/t/multi_update.test b/mysql-test/t/multi_update.test
index 496d045075a..4de574fbb0d 100644
--- a/mysql-test/t/multi_update.test
+++ b/mysql-test/t/multi_update.test
@@ -703,4 +703,50 @@ UPDATE t1 AS A, t1 AS B SET A.pk = 1, B.a = 2;
SELECT * FROM t1;
DROP TABLE t1;
---echo end of tests
+--echo #
+--echo # BUG#11882110: UPDATE REPORTS ER_KEY_NOT_FOUND IF TABLE IS
+--echo # UPDATED TWICE
+--echo #
+
+# Results differ between storage engines. This test is to verify that
+# the bugfix did NOT change behavior for MyISAM.
+# See multi_update_innodb.test for the InnoDB variant of this test
+CREATE TABLE t1 (
+ col_int_key int,
+ pk int,
+ col_int int,
+ key(col_int_key),
+ primary key (pk)
+) ENGINE=MyISAM;
+INSERT INTO t1 VALUES (1,2,3);
+
+--echo
+CREATE TABLE t2 (
+ col_int_key int,
+ pk_1 int,
+ pk_2 int,
+ col_int int,
+ key(col_int_key),
+ primary key (pk_1,pk_2)
+) ENGINE=MyISAM;
+INSERT INTO t2 VALUES (1,2,3,4);
+
+--echo
+UPDATE t1 AS A NATURAL JOIN t1 B SET A.pk=5,B.pk=7;
+
+--echo
+SELECT * FROM t1;
+
+--echo
+UPDATE t2 AS A NATURAL JOIN t2 B SET A.pk_1=5,B.pk_1=7;
+--echo
+UPDATE t2 AS A NATURAL JOIN t2 B SET A.pk_2=10,B.pk_2=11;
+
+--echo
+SELECT * FROM t2;
+
+DROP TABLE t1,t2;
+
+
+
+
diff --git a/mysql-test/t/multi_update_innodb.test b/mysql-test/t/multi_update_innodb.test
index 3148d009cef..51757c29553 100644
--- a/mysql-test/t/multi_update_innodb.test
+++ b/mysql-test/t/multi_update_innodb.test
@@ -31,3 +31,47 @@ SELECT * FROM t1;
DROP VIEW v1;
DROP TABLE t1;
+--echo #
+--echo # BUG#11882110: UPDATE REPORTS ER_KEY_NOT_FOUND IF TABLE IS
+--echo # UPDATED TWICE
+--echo #
+
+# Results differ between storage engines.
+# See multi_update.test for the MyISAM variant of this test
+CREATE TABLE t1 (
+ col_int_key int,
+ pk int,
+ col_int int,
+ key(col_int_key),
+ primary key (pk)
+) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1,2,3);
+
+--echo
+CREATE TABLE t2 (
+ col_int_key int,
+ pk_1 int,
+ pk_2 int,
+ col_int int,
+ key(col_int_key),
+ primary key (pk_1,pk_2)
+) ENGINE=InnoDB;
+INSERT INTO t2 VALUES (1,2,3,4);
+
+--echo
+--error ER_MULTI_UPDATE_KEY_CONFLICT
+UPDATE t1 AS A NATURAL JOIN t1 B SET A.pk=5,B.pk=7;
+--echo
+SELECT * FROM t1;
+
+--echo
+--error ER_MULTI_UPDATE_KEY_CONFLICT
+UPDATE t2 AS A NATURAL JOIN t2 B SET A.pk_1=5,B.pk_1=7;
+--echo
+--error ER_MULTI_UPDATE_KEY_CONFLICT
+UPDATE t2 AS A NATURAL JOIN t2 B SET A.pk_2=10,B.pk_2=11;
+
+--echo
+SELECT * FROM t2;
+
+DROP TABLE t1,t2;
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index 59356540201..90c4697d663 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -1071,17 +1071,27 @@ bool unsafe_key_update(TABLE_LIST *leaves, table_map tables_for_update)
return true;
}
- if (primkey_clustered &&
- (bitmap_is_set(table1->write_set, table1->s->primary_key) ||
- bitmap_is_set(table2->write_set, table2->s->primary_key)))
+ if (primkey_clustered)
{
- // Clustered primary key is updated
- my_error(ER_MULTI_UPDATE_KEY_CONFLICT, MYF(0),
- tl->belong_to_view ? tl->belong_to_view->alias
- : tl->alias,
- tl2->belong_to_view ? tl2->belong_to_view->alias
- : tl2->alias);
- return true;
+ // The primary key can cover multiple columns
+ KEY key_info= table1->key_info[table1->s->primary_key];
+ KEY_PART_INFO *key_part= key_info.key_part;
+ KEY_PART_INFO *key_part_end= key_part + key_info.key_parts;
+
+ for (;key_part != key_part_end; ++key_part)
+ {
+ if (bitmap_is_set(table1->write_set, key_part->fieldnr-1) ||
+ bitmap_is_set(table2->write_set, key_part->fieldnr-1))
+ {
+ // Clustered primary key is updated
+ my_error(ER_MULTI_UPDATE_KEY_CONFLICT, MYF(0),
+ tl->belong_to_view ? tl->belong_to_view->alias
+ : tl->alias,
+ tl2->belong_to_view ? tl2->belong_to_view->alias
+ : tl2->alias);
+ return true;
+ }
+ }
}
}
}
diff --git a/sql/table.h b/sql/table.h
index afdf4f7baa9..81b42c5b013 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -627,8 +627,8 @@ struct TABLE_SHARE
uint db_options_in_use; /* Options in use */
uint db_record_offset; /* if HA_REC_IN_SEQ */
uint rowid_field_offset; /* Field_nr +1 to rowid field */
- /* Index of auto-updated TIMESTAMP field in field array */
- uint primary_key;
+ /* Primary key index number, used in TABLE::key_info[] */
+ uint primary_key;
uint next_number_index; /* autoincrement key number */
uint next_number_key_offset; /* autoinc keypart offset in a key */
uint next_number_keypart; /* autoinc keypart number in a key */