summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <ingo@mysql.com>2005-05-18 19:40:39 +0200
committerunknown <ingo@mysql.com>2005-05-18 19:40:39 +0200
commit6f0ea859b2ef9c545970b732d10205d568609295 (patch)
treeeed6d6e4fb1b732cbfe4e1d82ab99868c7ac0e3e
parentd16f9433c1bf5a6c213cc258700e5bda015f1ce3 (diff)
downloadmariadb-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.result10
-rw-r--r--mysql-test/t/merge.test12
-rw-r--r--sql/ha_myisammrg.h2
-rw-r--r--sql/handler.h1
-rw-r--r--sql/sql_insert.cc2
-rw-r--r--sql/table.cc7
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 &&