Commit 6b7f9c0a authored by Tor Didriksen's avatar Tor Didriksen

Bug#13633383 63183: SMALL SORT_BUFFER_SIZE CRASH IN MERGE_BUFFERS

This patch is a backport of some of the cleanups/refactorings that were done
as part of WL#1393 Optimizing filesort with small limit.


mysql-test/t/bug13633383.test:
  New test case.
mysql-test/valgrind.supp:
  Changed signature for find_all_keys
parent 59185bd6
#
# Bug#13633383 63183: SMALL SORT_BUFFER_SIZE CRASH IN MERGE_BUFFERS
#
CREATE TABLE t1 (
`a` int(11) DEFAULT NULL,
`col432` bit(8) DEFAULT NULL,
`col433` multipoint DEFAULT NULL,
`col434` polygon DEFAULT NULL,
`col435` decimal(50,17) unsigned DEFAULT NULL,
`col436` geometry NOT NULL,
`col437` tinyblob NOT NULL,
`col438` multipolygon DEFAULT NULL,
`col439` mediumblob NOT NULL,
`col440` tinyblob NOT NULL,
`col441` double unsigned DEFAULT NULL
);
CREATE TABLE t2 (
`a` multipoint DEFAULT NULL,
`col460` date DEFAULT NULL,
`col461` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`col462` date NOT NULL,
`col463` varbinary(89) NOT NULL,
`col464` year(4) DEFAULT NULL,
`col465` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
`col466` varchar(236) CHARACTER SET utf8 NOT NULL,
`col467` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00'
);
CREATE TABLE t3 (
`FTS_DOC_ID` bigint(20) unsigned NOT NULL,
`col577` datetime DEFAULT NULL,
`col579` bit(38) NOT NULL,
`col580` varchar(93) NOT NULL,
`col581` datetime DEFAULT NULL,
`col583` multipolygon DEFAULT NULL,
`col584` bit(47) NOT NULL
);
set session sort_buffer_size= 32768;
select col435
from t3
natural right outer join t1
natural right outer join t2 a
left outer join t2 b on 1
group by
repeat('a',10000) desc,
repeat('a',10000)
with rollup
;
col435
0.00000000000000000
0.00000000000000000
0.00000000000000000
set session sort_buffer_size= default;
DROP TABLE t1, t2, t3;
--echo #
--echo # Bug#13633383 63183: SMALL SORT_BUFFER_SIZE CRASH IN MERGE_BUFFERS
--echo #
CREATE TABLE t1 (
`a` int(11) DEFAULT NULL,
`col432` bit(8) DEFAULT NULL,
`col433` multipoint DEFAULT NULL,
`col434` polygon DEFAULT NULL,
`col435` decimal(50,17) unsigned DEFAULT NULL,
`col436` geometry NOT NULL,
`col437` tinyblob NOT NULL,
`col438` multipolygon DEFAULT NULL,
`col439` mediumblob NOT NULL,
`col440` tinyblob NOT NULL,
`col441` double unsigned DEFAULT NULL
);
CREATE TABLE t2 (
`a` multipoint DEFAULT NULL,
`col460` date DEFAULT NULL,
`col461` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`col462` date NOT NULL,
`col463` varbinary(89) NOT NULL,
`col464` year(4) DEFAULT NULL,
`col465` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
`col466` varchar(236) CHARACTER SET utf8 NOT NULL,
`col467` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00'
);
CREATE TABLE t3 (
`FTS_DOC_ID` bigint(20) unsigned NOT NULL,
`col577` datetime DEFAULT NULL,
`col579` bit(38) NOT NULL,
`col580` varchar(93) NOT NULL,
`col581` datetime DEFAULT NULL,
`col583` multipolygon DEFAULT NULL,
`col584` bit(47) NOT NULL
);
--disable_query_log
INSERT INTO t1 VALUES (0,0xFF,'\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0 J',NULL,0.00000000000000000,'\0\0\0\0\0\0\0\0\0\0 \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0 \0\0\0\0\0C\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0 \0\0\0\0\0C\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0',0xB623A952C5,'\0\0\0\0\0\0\0\0\0\0\0i\0\0\0\0j',0x22,0xD81F72A9,56403);
INSERT INTO t1 VALUES (-32768,0x00,'\0\0\0\0\0\0\0\0\0\0\0r@\0\0\0\0j','\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0j',NULL,'\0\0\0\0\0\0\0\0\0\0\06@\0\0\0\0\0j',0xC80876AF04,'\0\0\0\0\0\0\0\0\0\0\0[\0\0\0\0i',0x016C576E34,0x1B,0);
INSERT INTO t1 VALUES (-2147483648,0x17,'\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0]',NULL,0.00000000000000000,'\0\0\0\0\0\0\0\0\0\0\0iFQC',0x68D352,'\0\0\0\0\0\0\0\n\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0 \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0 \0\0\0\0\0C\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0 \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0 \0\0\0\0\0C \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0','','',0);
INSERT INTO t1 VALUES (1,0xFF,'\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0','\0\0\0\0\0\0\0\0\0\0\0`6@\0\0\0\0@',32767.00000000000000000,'\0\0\0\0\0\0\0\0\0\0\0i@{',0x1406B0C524,'\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0 \0\0\0\0\0 \0\0\0\0\0C \0\0\0\0\0C',0xC04B75CCFD,0xC4CD,1);
INSERT INTO t1 VALUES (0,0xFF,NULL,'\0\0\0\0\0\0\0\0\0\0\0\0j@\0\0\0\0\0(',0.06140000000000000,'\0\0\0\0\0\0\0\0\0\0\0i@$7H#1',0x3F,'\0\0\0\0\0\0\0\0\0\0\0jCHK$',0x1E87C5DA,0xCC870E,NULL);
INSERT INTO t2 VALUES ('\0\0\0\0\0\0\0\0\0\0\0\0k\0\0\0\0\0j@','2011-02-19','2011-08-10 14:21:44','2012-09-25',0xCCC3,0000,'2012-07-28 16:25:23','idpapxbfjrigkfqnhnfmhvtewlvxfmjhfqizhhsowbetimmkhukpzeixbfyzmsalaafssdovflpvxldldmuamfoulanivuxigbjwkzbapcxmmprpyasaozdqwqjuixajzmiepkcvnvtewdvyodupziffgzbcmsfhikbuehyhzfnxlsdzulbsrqmtszzzupcmxlvcpxahuiotgadwhpcuqmyzgrbkxzxwriqkymdaqnzz','2012-01-20 09:01:25');
INSERT INTO t2 VALUES (NULL,'2011-05-14','2012-10-17 04:33:30','2012-01-20','',0000,'2012-05-08 11:06:53','otbywkbfwwtgpfgurtqwgfcwmmntsdxkounuzueoclrpnadghfzmbrh','2012-03-24 21:01:09');
INSERT INTO t2 VALUES ('\0\0\0\0\0\0\06PVh,;bº$','2012-07-21','2011-11-21 04:23:27','2011-06-18',0x21,0000,'2011-09-10 14:01:05','goybgohrexhfqwerpknkbyiqowvcdpyxvbklkbeeuvfbjtkmontmkmgcjutkjphewnvvobzilamtjqjbtvqgczozqcmvbbzvoxkycsvplfykmzpwljdcromsilspjuoyhxwduymxkymvmijehtutftqmpfpbesonppacogyogjqhyonizbsgzwubzgeoehryqswzkftgzhzssnlstuszpwauxmdhgjcawabnjcynzrrh','2012-11-19 18:30:51');
INSERT INTO t2 VALUES ('\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0','2012-09-01','2012-01-20 09:01:34','2011-02-12',0x1FDF59DC65,0000,'2011-07-07 19:48:34','xohwzrslzxbpxdvqfsumavjwwmsdcgczlmxrtxavsqtnpggxesvekbcelnnrxkvvlwqwbydlhwzltwaurkfltafeijstmzueiqddjdxzddymhsungndmojndbspkezvdfhqxijxxrwiolqgnsedenszkiljgropmcbxsjntjmnonnltyiysuejsznuurmonebslawybppziavystrylwunselezpbslmkzggpziffrud','2012-01-19 22:00:00');
INSERT INTO t2 VALUES ('\0\0\0\0\0\0\0\0\0\0\0\0j@\0\0\0\0\0\0\0\0','0000-00-00','2012-05-21 09:59:10','2011-04-17',0x02307EDF,0000,'2012-01-20 09:01:34','vjcwlxxeydntegsdqhxgriarmbvzwzwdexcalvacxhilaejpmxdpkuvblukchagzoellbdndelfednqktzobyhjqweqaugqnfikdalmaytyunjqvxcsirhaqnvqsstgrgfscnsemseebdemfditoswccsxthnddzslgjkyujxoqsvzrssymoovqmibcmbboruyxlvopengdqqgqwekrflhvjcpondxivnshvhrnqvfls','2012-09-23 23:54:02');
INSERT INTO t3 VALUES (11787,'2012-07-24 15:22:50',0x00000000FF,'qbdydwxepydtonqnghurnuntughjwfygzttqwtmfzfbtifjcearpatksofbrfgnaccvapahywhsstdplphrxbcubhktov','2011-08-27 19:28:03',NULL,0x00000000001C);
INSERT INTO t3 VALUES (11788,'2012-05-17 08:38:13',0x3FFFFFFFFF,'jkvkjxaikruljqalyvnbfjptxgbpsgnxlzthhcrswwdcfrhilwwgqmxynxjnehwmyfzdyywjzfyasuvjbrevkxtnyodiu','2012-05-09 11:09:52',NULL,0x0000000000B8);
INSERT INTO t3 VALUES (1,'2011-02-17 19:55:19',0x000098FAF3,'rnzhemtrqjdrappwbmxnzkfatcgtvqklrpfpdqiwjnjbeaxpcbhqqunbzmtmitdszxyrdvkeedqwpbiefqnwvhiznwfyq','2012-11-10 18:00:25','\0\0\0\0\0\0\0\0\0\0\0\0j\0\0\0\01@',0x7FFFFFFFFFFF);
INSERT INTO t3 VALUES (11789,'2011-12-26 01:30:56',0x0000000001,'dhryqjghgixymqywclxpovwnlgnltuzdvggmlaxtzrsbpxkahkiahpkrddpoeftqqwejbjxrdzfgvkzvhcalopgumspgg','2011-03-21 06:25:44',NULL,0x00000000293A);
INSERT INTO t3 VALUES (4294967296,'2011-04-12 21:05:37',0x0000CE3238,'xwcplgaxcpgfsmcjftxffxgmjwabpmrcycbxmwjvqtlvtlwuipuwgbuygnxomjplqohyuqyzsoiggroigcnchzpiilyhe','2012-03-20 05:35:39',NULL,0x00000000006E);
--enable_query_log
set session sort_buffer_size= 32768;
select col435
from t3
natural right outer join t1
natural right outer join t2 a
left outer join t2 b on 1
group by
repeat('a',10000) desc,
repeat('a',10000)
with rollup
;
set session sort_buffer_size= default;
DROP TABLE t1, t2, t3;
...@@ -893,7 +893,7 @@ ...@@ -893,7 +893,7 @@
fun:my_b_flush_io_cache fun:my_b_flush_io_cache
fun:_my_b_write fun:_my_b_write
fun:_Z*10write_keysP13st_sort_paramPPhjP11st_io_cacheS4_ fun:_Z*10write_keysP13st_sort_paramPPhjP11st_io_cacheS4_
fun:_Z*13find_all_keysP13st_sort_paramP10SQL_SELECTPPhP11st_io_cacheS6_S6_ fun:_Z*13find_all_keysP13st_sort_paramP10SQL_SELECTPPhP11st_io_cacheS6_
fun:_Z8filesortP3THDP5TABLEP13st_sort_fieldjP10SQL_SELECTybPy fun:_Z8filesortP3THDP5TABLEP13st_sort_fieldjP10SQL_SELECTybPy
} }
......
...@@ -48,7 +48,7 @@ static uchar *read_buffpek_from_file(IO_CACHE *buffer_file, uint count, ...@@ -48,7 +48,7 @@ static uchar *read_buffpek_from_file(IO_CACHE *buffer_file, uint count,
uchar *buf); uchar *buf);
static ha_rows find_all_keys(SORTPARAM *param,SQL_SELECT *select, static ha_rows find_all_keys(SORTPARAM *param,SQL_SELECT *select,
uchar * *sort_keys, IO_CACHE *buffer_file, uchar * *sort_keys, IO_CACHE *buffer_file,
IO_CACHE *tempfile,IO_CACHE *indexfile); IO_CACHE *tempfile);
static int write_keys(SORTPARAM *param,uchar * *sort_keys, static int write_keys(SORTPARAM *param,uchar * *sort_keys,
uint count, IO_CACHE *buffer_file, IO_CACHE *tempfile); uint count, IO_CACHE *buffer_file, IO_CACHE *tempfile);
static void make_sortkey(SORTPARAM *param,uchar *to, uchar *ref_pos); static void make_sortkey(SORTPARAM *param,uchar *to, uchar *ref_pos);
...@@ -88,8 +88,6 @@ static void unpack_addon_fields(struct st_sort_addon_field *addon_field, ...@@ -88,8 +88,6 @@ static void unpack_addon_fields(struct st_sort_addon_field *addon_field,
(Needed by UPDATE/INSERT or ALTER TABLE) (Needed by UPDATE/INSERT or ALTER TABLE)
@param examined_rows Store number of examined rows here @param examined_rows Store number of examined rows here
@todo
check why we do this (param.keys--)
@note @note
If we sort by position (like if sort_positions is 1) filesort() will If we sort by position (like if sort_positions is 1) filesort() will
call table->prepare_for_position(). call table->prepare_for_position().
...@@ -107,12 +105,12 @@ ha_rows filesort(THD *thd, TABLE *table, SORT_FIELD *sortorder, uint s_length, ...@@ -107,12 +105,12 @@ ha_rows filesort(THD *thd, TABLE *table, SORT_FIELD *sortorder, uint s_length,
bool sort_positions, ha_rows *examined_rows) bool sort_positions, ha_rows *examined_rows)
{ {
int error; int error;
ulong memavl, min_sort_memory; ulong memory_available= thd->variables.sortbuff_size;
uint maxbuffer; uint maxbuffer;
BUFFPEK *buffpek; BUFFPEK *buffpek;
ha_rows records= HA_POS_ERROR; ha_rows num_rows= HA_POS_ERROR;
uchar **sort_keys= 0; uchar **sort_keys= 0;
IO_CACHE tempfile, buffpek_pointers, *selected_records_file, *outfile; IO_CACHE tempfile, buffpek_pointers, *outfile;
SORTPARAM param; SORTPARAM param;
bool multi_byte_charset; bool multi_byte_charset;
DBUG_ENTER("filesort"); DBUG_ENTER("filesort");
...@@ -187,86 +185,71 @@ ha_rows filesort(THD *thd, TABLE *table, SORT_FIELD *sortorder, uint s_length, ...@@ -187,86 +185,71 @@ ha_rows filesort(THD *thd, TABLE *table, SORT_FIELD *sortorder, uint s_length,
param.max_rows= max_rows; param.max_rows= max_rows;
if (select && select->quick) if (select && select->quick)
{
status_var_increment(thd->status_var.filesort_range_count); status_var_increment(thd->status_var.filesort_range_count);
}
else else
{
status_var_increment(thd->status_var.filesort_scan_count); status_var_increment(thd->status_var.filesort_scan_count);
}
#ifdef CAN_TRUST_RANGE // If number of rows is not known, use as much of sort buffer as possible.
if (select && select->quick && select->quick->records > 0L) num_rows= table->file->estimate_rows_upper_bound();
{
records=min((ha_rows) (select->quick->records*2+EXTRA_RECORDS*2),
table->file->stats.records)+EXTRA_RECORDS;
selected_records_file=0;
}
else
#endif
{
records= table->file->estimate_rows_upper_bound();
/*
If number of records is not known, use as much of sort buffer
as possible.
*/
if (records == HA_POS_ERROR)
records--; // we use 'records+1' below.
selected_records_file= 0;
}
if (multi_byte_charset && if (multi_byte_charset &&
!(param.tmp_buffer= (char*) my_malloc(param.sort_length,MYF(MY_WME)))) !(param.tmp_buffer= (char*) my_malloc(param.sort_length,MYF(MY_WME))))
goto err; goto err;
memavl= thd->variables.sortbuff_size;
min_sort_memory= max(MIN_SORT_MEMORY, param.sort_length*MERGEBUFF2);
while (memavl >= min_sort_memory)
{ {
ulong old_memavl; const ulong min_sort_memory=
ulong keys= memavl/(param.rec_length+sizeof(char*)); max(MIN_SORT_MEMORY, param.sort_length * MERGEBUFF2);
param.keys=(uint) min(records+1, keys); while (memory_available >= min_sort_memory)
if (table_sort.sort_keys &&
table_sort.sort_keys_size != char_array_size(param.keys,
param.rec_length))
{ {
my_free(table_sort.sort_keys); ulong keys= memory_available / (param.rec_length + sizeof(char*));
table_sort.sort_keys= NULL; param.keys=(uint) min(num_rows, keys);
table_sort.sort_keys_size= 0; if (table_sort.sort_keys &&
table_sort.sort_keys_size != char_array_size(param.keys,
param.rec_length))
{
my_free(table_sort.sort_keys);
table_sort.sort_keys= NULL;
table_sort.sort_keys_size= 0;
}
if ((table_sort.sort_keys=
make_char_array(table_sort.sort_keys,
param.keys, param.rec_length, MYF(0))))
{
table_sort.sort_keys_size=
char_array_size(param.keys, param.rec_length);
break;
}
ulong old_memory_available= memory_available;
memory_available= memory_available/4*3;
if (memory_available < min_sort_memory &&
old_memory_available > min_sort_memory)
memory_available= min_sort_memory;
} }
if ((table_sort.sort_keys= sort_keys= table_sort.sort_keys;
make_char_array(table_sort.sort_keys, if (memory_available < min_sort_memory)
param.keys, param.rec_length, MYF(0))))
{ {
table_sort.sort_keys_size= char_array_size(param.keys, param.rec_length); my_error(ER_OUT_OF_SORTMEMORY,MYF(ME_ERROR+ME_WAITTANG));
break; goto err;
} }
old_memavl=memavl;
if ((memavl=memavl/4*3) < min_sort_memory && old_memavl > min_sort_memory)
memavl= min_sort_memory;
}
sort_keys= table_sort.sort_keys;
if (memavl < min_sort_memory)
{
my_error(ER_OUT_OF_SORTMEMORY,MYF(ME_ERROR+ME_WAITTANG));
goto err;
} }
if (open_cached_file(&buffpek_pointers,mysql_tmpdir,TEMP_PREFIX, if (open_cached_file(&buffpek_pointers,mysql_tmpdir,TEMP_PREFIX,
DISK_BUFFER_SIZE, MYF(MY_WME))) DISK_BUFFER_SIZE, MYF(MY_WME)))
goto err; goto err;
param.keys--; /* TODO: check why we do this */
param.sort_form= table; param.sort_form= table;
param.end=(param.local_sortorder=sortorder)+s_length; param.end=(param.local_sortorder=sortorder)+s_length;
if ((records=find_all_keys(&param,select,sort_keys, &buffpek_pointers, num_rows= find_all_keys(&param,
&tempfile, selected_records_file)) == select,
HA_POS_ERROR) sort_keys,
&buffpek_pointers,
&tempfile);
if (num_rows == HA_POS_ERROR)
goto err; goto err;
maxbuffer= (uint) (my_b_tell(&buffpek_pointers)/sizeof(*buffpek)); maxbuffer= (uint) (my_b_tell(&buffpek_pointers)/sizeof(*buffpek));
if (maxbuffer == 0) // The whole set is in memory if (maxbuffer == 0) // The whole set is in memory
{ {
if (save_index(&param,sort_keys,(uint) records, &table_sort)) if (save_index(&param,sort_keys,(uint) num_rows, &table_sort))
goto err; goto err;
} }
else else
...@@ -298,8 +281,9 @@ ha_rows filesort(THD *thd, TABLE *table, SORT_FIELD *sortorder, uint s_length, ...@@ -298,8 +281,9 @@ ha_rows filesort(THD *thd, TABLE *table, SORT_FIELD *sortorder, uint s_length,
Use also the space previously used by string pointers in sort_buffer Use also the space previously used by string pointers in sort_buffer
for temporary key storage. for temporary key storage.
*/ */
param.keys=((param.keys*(param.rec_length+sizeof(char*))) / param.keys=((param.keys *
param.rec_length-1); (param.rec_length+sizeof(char*))) /
param.rec_length - 1);
maxbuffer--; // Offset from 0 maxbuffer--; // Offset from 0
if (merge_many_buff(&param,(uchar*) sort_keys,buffpek,&maxbuffer, if (merge_many_buff(&param,(uchar*) sort_keys,buffpek,&maxbuffer,
&tempfile)) &tempfile))
...@@ -307,13 +291,21 @@ ha_rows filesort(THD *thd, TABLE *table, SORT_FIELD *sortorder, uint s_length, ...@@ -307,13 +291,21 @@ ha_rows filesort(THD *thd, TABLE *table, SORT_FIELD *sortorder, uint s_length,
if (flush_io_cache(&tempfile) || if (flush_io_cache(&tempfile) ||
reinit_io_cache(&tempfile,READ_CACHE,0L,0,0)) reinit_io_cache(&tempfile,READ_CACHE,0L,0,0))
goto err; goto err;
if (merge_index(&param,(uchar*) sort_keys,buffpek,maxbuffer,&tempfile, if (merge_index(&param,
(uchar*) sort_keys,
buffpek,
maxbuffer,
&tempfile,
outfile)) outfile))
goto err; goto err;
} }
if (records > param.max_rows)
records=param.max_rows; if (num_rows > param.max_rows)
error =0; {
// If find_all_keys() produced more results than the query LIMIT.
num_rows= param.max_rows;
}
error= 0;
err: err:
my_free(param.tmp_buffer); my_free(param.tmp_buffer);
...@@ -362,15 +354,15 @@ ha_rows filesort(THD *thd, TABLE *table, SORT_FIELD *sortorder, uint s_length, ...@@ -362,15 +354,15 @@ ha_rows filesort(THD *thd, TABLE *table, SORT_FIELD *sortorder, uint s_length,
} }
else else
statistic_add(thd->status_var.filesort_rows, statistic_add(thd->status_var.filesort_rows,
(ulong) records, &LOCK_status); (ulong) num_rows, &LOCK_status);
*examined_rows= param.examined_rows; *examined_rows= param.examined_rows;
#ifdef SKIP_DBUG_IN_FILESORT #ifdef SKIP_DBUG_IN_FILESORT
DBUG_POP(); /* Ok to DBUG */ DBUG_POP(); /* Ok to DBUG */
#endif #endif
memcpy(&table->sort, &table_sort, sizeof(FILESORT_INFO)); memcpy(&table->sort, &table_sort, sizeof(FILESORT_INFO));
DBUG_PRINT("exit",("records: %ld", (long) records)); DBUG_PRINT("exit",("num_rows: %ld", (long) num_rows));
MYSQL_FILESORT_DONE(error, records); MYSQL_FILESORT_DONE(error, num_rows);
DBUG_RETURN(error ? HA_POS_ERROR : records); DBUG_RETURN(error ? HA_POS_ERROR : num_rows);
} /* filesort */ } /* filesort */
...@@ -513,7 +505,6 @@ static void dbug_print_record(TABLE *table, bool print_rowid) ...@@ -513,7 +505,6 @@ static void dbug_print_record(TABLE *table, bool print_rowid)
@param buffpek_pointers File to write BUFFPEKs describing sorted segments @param buffpek_pointers File to write BUFFPEKs describing sorted segments
in tempfile. in tempfile.
@param tempfile File to write sorted sequences of sortkeys to. @param tempfile File to write sorted sequences of sortkeys to.
@param indexfile If !NULL, use it for source data (contains rowids)
@note @note
Basic idea: Basic idea:
...@@ -543,7 +534,7 @@ static void dbug_print_record(TABLE *table, bool print_rowid) ...@@ -543,7 +534,7 @@ static void dbug_print_record(TABLE *table, bool print_rowid)
static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select, static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select,
uchar **sort_keys, uchar **sort_keys,
IO_CACHE *buffpek_pointers, IO_CACHE *buffpek_pointers,
IO_CACHE *tempfile, IO_CACHE *indexfile) IO_CACHE *tempfile)
{ {
int error,flag,quick_select; int error,flag,quick_select;
uint idx,indexpos,ref_length; uint idx,indexpos,ref_length;
...@@ -568,12 +559,11 @@ static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select, ...@@ -568,12 +559,11 @@ static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select,
ref_pos= ref_buff; ref_pos= ref_buff;
quick_select=select && select->quick; quick_select=select && select->quick;
record=0; record=0;
flag= ((!indexfile && file->ha_table_flags() & HA_REC_NOT_IN_SEQ) flag= ((file->ha_table_flags() & HA_REC_NOT_IN_SEQ) || quick_select);
|| quick_select); if (flag)
if (indexfile || flag)
ref_pos= &file->ref[0]; ref_pos= &file->ref[0];
next_pos=ref_pos; next_pos=ref_pos;
if (! indexfile && ! quick_select) if (!quick_select)
{ {
next_pos=(uchar*) 0; /* Find records in sequence */ next_pos=(uchar*) 0; /* Find records in sequence */
file->ha_rnd_init(1); file->ha_rnd_init(1);
...@@ -611,18 +601,8 @@ static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select, ...@@ -611,18 +601,8 @@ static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select,
} }
else /* Not quick-select */ else /* Not quick-select */
{ {
if (indexfile)
{
if (my_b_read(indexfile,(uchar*) ref_pos,ref_length)) /* purecov: deadcode */
{
error= my_errno ? my_errno : -1; /* Abort */
break;
}
error=file->rnd_pos(sort_form->record[0],next_pos);
}
else
{ {
error=file->rnd_next(sort_form->record[0]); error= file->rnd_next(sort_form->record[0]);
if (!flag) if (!flag)
{ {
my_store_ptr(ref_pos,ref_length,record); // Position to row my_store_ptr(ref_pos,ref_length,record); // Position to row
...@@ -638,7 +618,7 @@ static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select, ...@@ -638,7 +618,7 @@ static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select,
if (*killed) if (*killed)
{ {
DBUG_PRINT("info",("Sort killed by user")); DBUG_PRINT("info",("Sort killed by user"));
if (!indexfile && !quick_select) if (!quick_select)
{ {
(void) file->extra(HA_EXTRA_NO_CACHE); (void) file->extra(HA_EXTRA_NO_CACHE);
file->ha_rnd_end(); file->ha_rnd_end();
...@@ -652,9 +632,10 @@ static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select, ...@@ -652,9 +632,10 @@ static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select,
{ {
if (idx == param->keys) if (idx == param->keys)
{ {
if (write_keys(param,sort_keys,idx,buffpek_pointers,tempfile)) if (write_keys(param, sort_keys,
idx, buffpek_pointers, tempfile))
DBUG_RETURN(HA_POS_ERROR); DBUG_RETURN(HA_POS_ERROR);
idx=0; idx= 0;
indexpos++; indexpos++;
} }
make_sortkey(param,sort_keys[idx++],ref_pos); make_sortkey(param,sort_keys[idx++],ref_pos);
...@@ -681,15 +662,17 @@ static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select, ...@@ -681,15 +662,17 @@ static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select,
DBUG_PRINT("test",("error: %d indexpos: %d",error,indexpos)); DBUG_PRINT("test",("error: %d indexpos: %d",error,indexpos));
if (error != HA_ERR_END_OF_FILE) if (error != HA_ERR_END_OF_FILE)
{ {
file->print_error(error,MYF(ME_ERROR | ME_WAITTANG)); /* purecov: inspected */ file->print_error(error,MYF(ME_ERROR | ME_WAITTANG)); // purecov: inspected
DBUG_RETURN(HA_POS_ERROR); /* purecov: inspected */ DBUG_RETURN(HA_POS_ERROR); /* purecov: inspected */
} }
if (indexpos && idx && if (indexpos && idx &&
write_keys(param,sort_keys,idx,buffpek_pointers,tempfile)) write_keys(param, sort_keys,
idx, buffpek_pointers, tempfile))
DBUG_RETURN(HA_POS_ERROR); /* purecov: inspected */ DBUG_RETURN(HA_POS_ERROR); /* purecov: inspected */
DBUG_RETURN(my_b_inited(tempfile) ? const ha_rows retval=
(ha_rows) (my_b_tell(tempfile)/param->rec_length) : my_b_inited(tempfile) ?
idx); (ha_rows) (my_b_tell(tempfile)/param->rec_length) : idx;
DBUG_RETURN(retval);
} /* find_all_keys */ } /* find_all_keys */
...@@ -1269,8 +1252,8 @@ int merge_buffers(SORTPARAM *param, IO_CACHE *from_file, ...@@ -1269,8 +1252,8 @@ int merge_buffers(SORTPARAM *param, IO_CACHE *from_file,
{ {
buffpek->base= strpos; buffpek->base= strpos;
buffpek->max_keys= maxcount; buffpek->max_keys= maxcount;
strpos+= (uint) (error= (int) read_to_buffer(from_file, buffpek, strpos+=
rec_length)); (uint) (error= (int) read_to_buffer(from_file, buffpek, rec_length));
if (error == -1) if (error == -1)
goto err; /* purecov: inspected */ goto err; /* purecov: inspected */
buffpek->max_keys= buffpek->mem_count; // If less data in buffers than expected buffpek->max_keys= buffpek->mem_count; // If less data in buffers than expected
......
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