diff --git a/mysql-test/r/merge.result b/mysql-test/r/merge.result index 79d8f019ce3..6e14e9a56a8 100644 --- a/mysql-test/r/merge.result +++ b/mysql-test/r/merge.result @@ -681,3 +681,13 @@ t3 1 a 1 a A NULL NULL NULL YES BTREE t3 1 a 2 b A NULL NULL NULL YES BTREE t3 1 a 3 c A NULL NULL NULL YES BTREE drop table t1, t2, t3; +CREATE TABLE t1 ( a INT AUTO_INCREMENT PRIMARY KEY, b VARCHAR(10), UNIQUE (b) ) +ENGINE=MyISAM; +CREATE TABLE t2 ( a INT AUTO_INCREMENT, b VARCHAR(10), INDEX (a), INDEX (b) ) +ENGINE=MERGE UNION (t1) INSERT_METHOD=FIRST; +INSERT INTO t2 (b) VALUES (1) ON DUPLICATE KEY UPDATE b=2; +INSERT INTO t2 (b) VALUES (1) ON DUPLICATE KEY UPDATE b=3; +SELECT b FROM t2; +b +3 +DROP TABLE t1, t2; diff --git a/mysql-test/t/merge.test b/mysql-test/t/merge.test index 508f9da225e..999dd2bed9b 100644 --- a/mysql-test/t/merge.test +++ b/mysql-test/t/merge.test @@ -306,3 +306,15 @@ show index from t3; drop table t1, t2, t3; +# +# Bug#10400 - Improperly-defined MERGE table crashes with INSERT ... ON DUPLICATE KEY UPDATE +# +CREATE TABLE t1 ( a INT AUTO_INCREMENT PRIMARY KEY, b VARCHAR(10), UNIQUE (b) ) + ENGINE=MyISAM; +CREATE TABLE t2 ( a INT AUTO_INCREMENT, b VARCHAR(10), INDEX (a), INDEX (b) ) + ENGINE=MERGE UNION (t1) INSERT_METHOD=FIRST; +INSERT INTO t2 (b) VALUES (1) ON DUPLICATE KEY UPDATE b=2; +INSERT INTO t2 (b) VALUES (1) ON DUPLICATE KEY UPDATE b=3; +SELECT b FROM t2; +DROP TABLE t1, t2; + diff --git a/sql/ha_myisammrg.h b/sql/ha_myisammrg.h index 3bc9c11d4be..7348096b695 100644 --- a/sql/ha_myisammrg.h +++ b/sql/ha_myisammrg.h @@ -37,7 +37,7 @@ class ha_myisammrg: public handler { return (HA_REC_NOT_IN_SEQ | HA_AUTO_PART_KEY | HA_READ_RND_SAME | HA_NULL_IN_KEY | HA_CAN_INDEX_BLOBS | HA_FILE_BASED | - HA_CAN_INSERT_DELAYED); + HA_CAN_INSERT_DELAYED | HA_ANY_INDEX_MAY_BE_UNIQUE); } ulong index_flags(uint inx, uint part, bool all_parts) const { diff --git a/sql/handler.h b/sql/handler.h index de932cd51a4..75e83082d10 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -73,6 +73,7 @@ #define HA_HAS_CHECKSUM (1 << 24) /* Table data are stored in separate files (for lower_case_table_names) */ #define HA_FILE_BASED (1 << 26) +#define HA_ANY_INDEX_MAY_BE_UNIQUE (1 << 30) /* bits in index_flags(index_number) for what you can do with index */ diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index a3a42ce385d..0258f2c3e07 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -682,7 +682,7 @@ int write_record(TABLE *table,COPY_INFO *info) err: if (key) - my_afree(key); + my_safe_afree(key,table->max_unique_length,MAX_KEY_LENGTH); info->last_errno= error; table->file->print_error(error,MYF(0)); DBUG_RETURN(1); diff --git a/sql/table.cc b/sql/table.cc index 012defa116d..d9000933ee0 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -688,7 +688,12 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag, set_if_bigger(outparam->max_key_length,keyinfo->key_length+ keyinfo->key_parts); outparam->total_key_length+= keyinfo->key_length; - if (keyinfo->flags & HA_NOSAME) + /* + MERGE tables do not have unique indexes. But every key could be + an unique index on the underlying MyISAM table. (Bug #10400) + */ + if ((keyinfo->flags & HA_NOSAME) || + (ha_option & HA_ANY_INDEX_MAY_BE_UNIQUE)) set_if_bigger(outparam->max_unique_length,keyinfo->key_length); } if (primary_key < MAX_KEY &&