Commit 0461b482 authored by unknown's avatar unknown
Browse files

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().
parent 2598faaf
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -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;
+12 −0
Original line number Diff line number Diff line
@@ -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;
+1 −1
Original line number Diff line number Diff line
@@ -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
  {
+1 −0
Original line number Diff line number Diff line
@@ -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 */
+1 −1
Original line number Diff line number Diff line
@@ -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);
Loading