diff options
author | unknown <ingo@mysql.com> | 2005-05-18 19:40:39 +0200 |
---|---|---|
committer | unknown <ingo@mysql.com> | 2005-05-18 19:40:39 +0200 |
commit | 6f0ea859b2ef9c545970b732d10205d568609295 (patch) | |
tree | eed6d6e4fb1b732cbfe4e1d82ab99868c7ac0e3e | |
parent | d16f9433c1bf5a6c213cc258700e5bda015f1ce3 (diff) | |
download | mariadb-git-6f0ea859b2ef9c545970b732d10205d568609295.tar.gz |
Bug#10400 - Improperly-defined MERGE table crashes with INSERT ... ON DUPLICATE KEY UPDATE
After review version.
Added a condition for MERGE tables. These do not have unique
indexes. But every key could be a unique key on the underlying
MyISAM table. So get the maximum key length for MERGE tables
instead of the maximum unique key length. This is used for
buffer allocation in write_record().
mysql-test/r/merge.result:
Bug#10400 - Improperly-defined MERGE table crashes with INSERT ... ON DUPLICATE KEY UPDATE
The test result.
mysql-test/t/merge.test:
Bug#10400 - Improperly-defined MERGE table crashes with INSERT ... ON DUPLICATE KEY UPDATE
The test case does not in all cases show the problem
without the bugfix. The improper memory allocation
might get through undetected in many cases.
sql/ha_myisammrg.h:
Bug#10400 - Improperly-defined MERGE table crashes with INSERT ... ON DUPLICATE KEY UPDATE
Set a table_flag for the MERGE engine telling that any index
might be unique without being specified as such.
sql/handler.h:
Bug#10400 - Improperly-defined MERGE table crashes with INSERT ... ON DUPLICATE KEY UPDATE
Added a new table_flag telling that any index
might be unique without being specified as such.
sql/sql_insert.cc:
Bug#10400 - Improperly-defined MERGE table crashes with INSERT ... ON DUPLICATE KEY UPDATE
Changed the freeing of the memory to be symmetric to its
allocation (my_safe_alloc -> my_safe_afree).
This is not directly related to the bug.
sql/table.cc:
Bug#10400 - Improperly-defined MERGE table crashes with INSERT ... ON DUPLICATE KEY UPDATE
Added a condition for MERGE tables. These do not have unique
indexes. But every key could be a unique key on the underlying
MyISAM table. So get the maximum key length for MERGE tables
instead of the maximum unique key length. This is used for
buffer allocation in write_record().
-rw-r--r-- | mysql-test/r/merge.result | 10 | ||||
-rw-r--r-- | mysql-test/t/merge.test | 12 | ||||
-rw-r--r-- | sql/ha_myisammrg.h | 2 | ||||
-rw-r--r-- | sql/handler.h | 1 | ||||
-rw-r--r-- | sql/sql_insert.cc | 2 | ||||
-rw-r--r-- | sql/table.cc | 7 |
6 files changed, 31 insertions, 3 deletions
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 && |