Commit 56996041 authored by igor@olga.mysql.com's avatar igor@olga.mysql.com

Fixed bug #28449: a crash may happen at some rare conditions when

a temporary table has grown out of heap memory reserved for it and 
the remaining disk space is not big enough to store the table as
a MyISAM table.

The crash happens because the function create_myisam_from_heap
does not handle safely the mem_root structure associated 
with the converted table in the case when an error has occurred.
parent b9090113
DROP TABLE IF EXISTS t1;
Warnings:
Note 1051 Unknown table 't1'
CREATE TABLE t1 (
a varchar(32) character set utf8 collate utf8_bin NOT NULL,
b varchar(32) character set utf8 collate utf8_bin NOT NULL )
ENGINE=MyISAM DEFAULT CHARSET=utf8;
INSERT INTO t1 VALUES
('AAAAAAAAAA','AAAAAAAAAA'), ('AAAAAAAAAB','AAAAAAAAAB '),
('AAAAAAAAAB','AAAAAAAAAB'), ('AAAAAAAAAC','AAAAAAAAAC'),
('AAAAAAAAAD','AAAAAAAAAD'), ('AAAAAAAAAE','AAAAAAAAAE'),
('AAAAAAAAAF','AAAAAAAAAF'), ('AAAAAAAAAG','AAAAAAAAAG'),
('AAAAAAAAAH','AAAAAAAAAH'), ('AAAAAAAAAI','AAAAAAAAAI'),
('AAAAAAAAAJ','AAAAAAAAAJ'), ('AAAAAAAAAK','AAAAAAAAAK');
set tmp_table_size=1024;
SELECT MAX(a) FROM t1 GROUP BY a,b;
ERROR 23000: Can't write; duplicate key in table ''
set tmp_table_size=default;
DROP TABLE t1;
-- source include/have_debug.inc
#
# Bug #28499: crash for grouping query when tmp_table_size is too small
#
DROP TABLE IF EXISTS t1;
CREATE TABLE t1 (
a varchar(32) character set utf8 collate utf8_bin NOT NULL,
b varchar(32) character set utf8 collate utf8_bin NOT NULL )
ENGINE=MyISAM DEFAULT CHARSET=utf8;
INSERT INTO t1 VALUES
('AAAAAAAAAA','AAAAAAAAAA'), ('AAAAAAAAAB','AAAAAAAAAB '),
('AAAAAAAAAB','AAAAAAAAAB'), ('AAAAAAAAAC','AAAAAAAAAC'),
('AAAAAAAAAD','AAAAAAAAAD'), ('AAAAAAAAAE','AAAAAAAAAE'),
('AAAAAAAAAF','AAAAAAAAAF'), ('AAAAAAAAAG','AAAAAAAAAG'),
('AAAAAAAAAH','AAAAAAAAAH'), ('AAAAAAAAAI','AAAAAAAAAI'),
('AAAAAAAAAJ','AAAAAAAAAJ'), ('AAAAAAAAAK','AAAAAAAAAK');
set tmp_table_size=1024;
--error ER_DUP_KEY
SELECT MAX(a) FROM t1 GROUP BY a,b;
set tmp_table_size=default;
DROP TABLE t1;
...@@ -10147,7 +10147,9 @@ bool create_myisam_from_heap(THD *thd, TABLE *table, TMP_TABLE_PARAM *param, ...@@ -10147,7 +10147,9 @@ bool create_myisam_from_heap(THD *thd, TABLE *table, TMP_TABLE_PARAM *param,
/* copy all old rows */ /* copy all old rows */
while (!table->file->rnd_next(new_table.record[1])) while (!table->file->rnd_next(new_table.record[1]))
{ {
if ((write_err=new_table.file->write_row(new_table.record[1]))) write_err=new_table.file->write_row(new_table.record[1]);
DBUG_EXECUTE_IF("raise_error", write_err= HA_ERR_FOUND_DUPP_KEY ;);
if (write_err)
goto err; goto err;
} }
/* copy row that filled HEAP table */ /* copy row that filled HEAP table */
...@@ -10174,7 +10176,7 @@ bool create_myisam_from_heap(THD *thd, TABLE *table, TMP_TABLE_PARAM *param, ...@@ -10174,7 +10176,7 @@ bool create_myisam_from_heap(THD *thd, TABLE *table, TMP_TABLE_PARAM *param,
err: err:
DBUG_PRINT("error",("Got error: %d",write_err)); DBUG_PRINT("error",("Got error: %d",write_err));
table->file->print_error(error,MYF(0)); // Give table is full error table->file->print_error(write_err, MYF(0)); // Give table is full error
(void) table->file->ha_rnd_end(); (void) table->file->ha_rnd_end();
(void) new_table.file->close(); (void) new_table.file->close();
err1: err1:
...@@ -10182,6 +10184,7 @@ bool create_myisam_from_heap(THD *thd, TABLE *table, TMP_TABLE_PARAM *param, ...@@ -10182,6 +10184,7 @@ bool create_myisam_from_heap(THD *thd, TABLE *table, TMP_TABLE_PARAM *param,
delete new_table.file; delete new_table.file;
err2: err2:
thd->proc_info=save_proc_info; thd->proc_info=save_proc_info;
table->mem_root= new_table.mem_root;
DBUG_RETURN(1); DBUG_RETURN(1);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment