mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
MDEV-22303: Incorrect ordering with REGEXP_REPLACE and OFFSET/LIMIT
For character sets and collation where character to weight mapping > 1, there we need to make sure while creating a sort key, a temporary buffer is created to store the value of the item by val_str function and then copy that value back to the sort buffer. In this case when using a priority queue Sort_param::tmp_buffer was not allocated. Minor refactoring: Changed Sort_param::tmp_buffer from char* to String
This commit is contained in:
@ -3866,3 +3866,22 @@ cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
|
|||||||
dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
|
dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
|
||||||
NULL
|
NULL
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
|
#
|
||||||
|
# MDEV-22303: Incorrect ordering with REGEXP_REPLACE and OFFSET/LIMIT
|
||||||
|
#
|
||||||
|
CREATE TABLE t1 (name VARCHAR(20) CHARACTER SET utf8 NOT NULL);
|
||||||
|
INSERT INTO t1 (name) VALUES ('Charles Dickens'), ('Roald Dahl');
|
||||||
|
SELECT name, REGEXP_REPLACE(name, '^(.*) (.*)$', '\\2, \\1') AS surname_first FROM t1
|
||||||
|
ORDER BY surname_first ASC;
|
||||||
|
name surname_first
|
||||||
|
Roald Dahl Dahl, Roald
|
||||||
|
Charles Dickens Dickens, Charles
|
||||||
|
SELECT name, REGEXP_REPLACE(name, '^(.*) (.*)$', '\\2, \\1') AS surname_first FROM t1
|
||||||
|
ORDER BY surname_first ASC LIMIT 1;
|
||||||
|
name surname_first
|
||||||
|
Roald Dahl Dahl, Roald
|
||||||
|
SELECT name, REGEXP_REPLACE(name, '^(.*) (.*)$', '\\2, \\1') AS surname_first FROM t1
|
||||||
|
ORDER BY surname_first ASC LIMIT 1 OFFSET 1;
|
||||||
|
name surname_first
|
||||||
|
Charles Dickens Dickens, Charles
|
||||||
|
DROP TABLE t1;
|
||||||
|
@ -2413,3 +2413,21 @@ insert into t1 select repeat('d', 256);
|
|||||||
|
|
||||||
SELECT IF( 0, NULL, a ) AS f FROM t1 GROUP BY f WITH ROLLUP;
|
SELECT IF( 0, NULL, a ) AS f FROM t1 GROUP BY f WITH ROLLUP;
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # MDEV-22303: Incorrect ordering with REGEXP_REPLACE and OFFSET/LIMIT
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
CREATE TABLE t1 (name VARCHAR(20) CHARACTER SET utf8 NOT NULL);
|
||||||
|
INSERT INTO t1 (name) VALUES ('Charles Dickens'), ('Roald Dahl');
|
||||||
|
|
||||||
|
SELECT name, REGEXP_REPLACE(name, '^(.*) (.*)$', '\\2, \\1') AS surname_first FROM t1
|
||||||
|
ORDER BY surname_first ASC;
|
||||||
|
|
||||||
|
SELECT name, REGEXP_REPLACE(name, '^(.*) (.*)$', '\\2, \\1') AS surname_first FROM t1
|
||||||
|
ORDER BY surname_first ASC LIMIT 1;
|
||||||
|
|
||||||
|
SELECT name, REGEXP_REPLACE(name, '^(.*) (.*)$', '\\2, \\1') AS surname_first FROM t1
|
||||||
|
ORDER BY surname_first ASC LIMIT 1 OFFSET 1;
|
||||||
|
|
||||||
|
DROP TABLE t1;
|
||||||
|
@ -58,7 +58,6 @@ static bool save_index(Sort_param *param, uint count,
|
|||||||
SORT_INFO *table_sort);
|
SORT_INFO *table_sort);
|
||||||
static uint suffix_length(ulong string_length);
|
static uint suffix_length(ulong string_length);
|
||||||
static uint sortlength(THD *thd, Sort_keys *sortorder,
|
static uint sortlength(THD *thd, Sort_keys *sortorder,
|
||||||
bool *multi_byte_charset,
|
|
||||||
bool *allow_packing_for_sortkeys);
|
bool *allow_packing_for_sortkeys);
|
||||||
static Addon_fields *get_addon_fields(TABLE *table, uint sortlength,
|
static Addon_fields *get_addon_fields(TABLE *table, uint sortlength,
|
||||||
uint *addon_length,
|
uint *addon_length,
|
||||||
@ -200,7 +199,7 @@ SORT_INFO *filesort(THD *thd, TABLE *table, Filesort *filesort,
|
|||||||
ha_rows num_rows= HA_POS_ERROR;
|
ha_rows num_rows= HA_POS_ERROR;
|
||||||
IO_CACHE tempfile, buffpek_pointers, *outfile;
|
IO_CACHE tempfile, buffpek_pointers, *outfile;
|
||||||
Sort_param param;
|
Sort_param param;
|
||||||
bool multi_byte_charset, allow_packing_for_sortkeys;
|
bool allow_packing_for_sortkeys;
|
||||||
Bounded_queue<uchar, uchar> pq;
|
Bounded_queue<uchar, uchar> pq;
|
||||||
SQL_SELECT *const select= filesort->select;
|
SQL_SELECT *const select= filesort->select;
|
||||||
ha_rows max_rows= filesort->limit;
|
ha_rows max_rows= filesort->limit;
|
||||||
@ -248,8 +247,7 @@ SORT_INFO *filesort(THD *thd, TABLE *table, Filesort *filesort,
|
|||||||
sort->found_rows= HA_POS_ERROR;
|
sort->found_rows= HA_POS_ERROR;
|
||||||
|
|
||||||
param.sort_keys= sort_keys;
|
param.sort_keys= sort_keys;
|
||||||
uint sort_len= sortlength(thd, sort_keys, &multi_byte_charset,
|
uint sort_len= sortlength(thd, sort_keys, &allow_packing_for_sortkeys);
|
||||||
&allow_packing_for_sortkeys);
|
|
||||||
|
|
||||||
param.init_for_filesort(sort_len, table, max_rows, filesort->sort_positions);
|
param.init_for_filesort(sort_len, table, max_rows, filesort->sort_positions);
|
||||||
|
|
||||||
@ -309,12 +307,6 @@ SORT_INFO *filesort(THD *thd, TABLE *table, Filesort *filesort,
|
|||||||
tracker->report_sort_keys_format(param.using_packed_sortkeys());
|
tracker->report_sort_keys_format(param.using_packed_sortkeys());
|
||||||
param.using_pq= false;
|
param.using_pq= false;
|
||||||
|
|
||||||
if ((multi_byte_charset || param.using_packed_sortkeys()) &&
|
|
||||||
!(param.tmp_buffer= (char*) my_malloc(key_memory_Sort_param_tmp_buffer, param.sort_length,
|
|
||||||
MYF(MY_WME | MY_THREAD_SPECIFIC))))
|
|
||||||
goto err;
|
|
||||||
|
|
||||||
|
|
||||||
size_t min_sort_memory= MY_MAX(MIN_SORT_MEMORY,
|
size_t min_sort_memory= MY_MAX(MIN_SORT_MEMORY,
|
||||||
param.sort_length*MERGEBUFF2);
|
param.sort_length*MERGEBUFF2);
|
||||||
set_if_bigger(min_sort_memory, sizeof(Merge_chunk*)*MERGEBUFF2);
|
set_if_bigger(min_sort_memory, sizeof(Merge_chunk*)*MERGEBUFF2);
|
||||||
@ -345,6 +337,9 @@ SORT_INFO *filesort(THD *thd, TABLE *table, Filesort *filesort,
|
|||||||
tracker->report_addon_fields_format(param.using_packed_addons());
|
tracker->report_addon_fields_format(param.using_packed_addons());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (param.tmp_buffer.alloc(param.sort_length))
|
||||||
|
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;
|
||||||
@ -438,7 +433,6 @@ SORT_INFO *filesort(THD *thd, TABLE *table, Filesort *filesort,
|
|||||||
error= 0;
|
error= 0;
|
||||||
|
|
||||||
err:
|
err:
|
||||||
my_free(param.tmp_buffer);
|
|
||||||
if (!subselect || !subselect->is_uncacheable())
|
if (!subselect || !subselect->is_uncacheable())
|
||||||
{
|
{
|
||||||
if (!param.using_addon_fields())
|
if (!param.using_addon_fields())
|
||||||
@ -1101,10 +1095,8 @@ Type_handler_string_result::make_sort_key_part(uchar *to, Item *item,
|
|||||||
|
|
||||||
if (maybe_null)
|
if (maybe_null)
|
||||||
*to++= 1;
|
*to++= 1;
|
||||||
char *tmp_buffer= param->tmp_buffer ? param->tmp_buffer : (char*) to;
|
|
||||||
String tmp(tmp_buffer, param->tmp_buffer ? param->sort_length :
|
String *res= item->str_result(¶m->tmp_buffer);
|
||||||
sort_field->length, cs);
|
|
||||||
String *res= item->str_result(&tmp);
|
|
||||||
if (!res)
|
if (!res)
|
||||||
{
|
{
|
||||||
if (maybe_null)
|
if (maybe_null)
|
||||||
@ -2181,8 +2173,6 @@ Type_handler_decimal_result::sort_length(THD *thd,
|
|||||||
@param thd Thread handler
|
@param thd Thread handler
|
||||||
@param sortorder Order of items to sort
|
@param sortorder Order of items to sort
|
||||||
@param s_length Number of items to sort
|
@param s_length Number of items to sort
|
||||||
@param[out] multi_byte_charset Set to 1 if we are using multi-byte charset
|
|
||||||
(In which case we have to use strxnfrm())
|
|
||||||
@param allow_packing_for_sortkeys [out] set to false if packing sort keys is not
|
@param allow_packing_for_sortkeys [out] set to false if packing sort keys is not
|
||||||
allowed
|
allowed
|
||||||
|
|
||||||
@ -2196,11 +2186,9 @@ Type_handler_decimal_result::sort_length(THD *thd,
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
static uint
|
static uint
|
||||||
sortlength(THD *thd, Sort_keys *sort_keys, bool *multi_byte_charset,
|
sortlength(THD *thd, Sort_keys *sort_keys, bool *allow_packing_for_sortkeys)
|
||||||
bool *allow_packing_for_sortkeys)
|
|
||||||
{
|
{
|
||||||
uint length;
|
uint length;
|
||||||
*multi_byte_charset= 0;
|
|
||||||
*allow_packing_for_sortkeys= true;
|
*allow_packing_for_sortkeys= true;
|
||||||
bool allow_packing_for_keys= true;
|
bool allow_packing_for_keys= true;
|
||||||
|
|
||||||
@ -2226,10 +2214,8 @@ sortlength(THD *thd, Sort_keys *sort_keys, bool *multi_byte_charset,
|
|||||||
sortorder->cs= cs;
|
sortorder->cs= cs;
|
||||||
|
|
||||||
if (use_strnxfrm((cs=sortorder->field->sort_charset())))
|
if (use_strnxfrm((cs=sortorder->field->sort_charset())))
|
||||||
{
|
|
||||||
*multi_byte_charset= true;
|
|
||||||
sortorder->length= (uint) cs->strnxfrmlen(sortorder->length);
|
sortorder->length= (uint) cs->strnxfrmlen(sortorder->length);
|
||||||
}
|
|
||||||
if (sortorder->is_variable_sized() && allow_packing_for_keys)
|
if (sortorder->is_variable_sized() && allow_packing_for_keys)
|
||||||
{
|
{
|
||||||
allow_packing_for_keys= sortorder->check_if_packing_possible(thd);
|
allow_packing_for_keys= sortorder->check_if_packing_possible(thd);
|
||||||
@ -2243,17 +2229,12 @@ sortlength(THD *thd, Sort_keys *sort_keys, bool *multi_byte_charset,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
CHARSET_INFO *cs;
|
|
||||||
sortorder->item->type_handler()->sort_length(thd, sortorder->item,
|
sortorder->item->type_handler()->sort_length(thd, sortorder->item,
|
||||||
sortorder);
|
sortorder);
|
||||||
sortorder->type= sortorder->item->type_handler()->is_packable() ?
|
sortorder->type= sortorder->item->type_handler()->is_packable() ?
|
||||||
SORT_FIELD_ATTR::VARIABLE_SIZE :
|
SORT_FIELD_ATTR::VARIABLE_SIZE :
|
||||||
SORT_FIELD_ATTR::FIXED_SIZE;
|
SORT_FIELD_ATTR::FIXED_SIZE;
|
||||||
if (use_strnxfrm((cs=sortorder->item->collation.collation)))
|
sortorder->cs= sortorder->item->collation.collation;
|
||||||
{
|
|
||||||
*multi_byte_charset= true;
|
|
||||||
}
|
|
||||||
sortorder->cs= cs;
|
|
||||||
if (sortorder->is_variable_sized() && allow_packing_for_keys)
|
if (sortorder->is_variable_sized() && allow_packing_for_keys)
|
||||||
{
|
{
|
||||||
allow_packing_for_keys= sortorder->check_if_packing_possible(thd);
|
allow_packing_for_keys= sortorder->check_if_packing_possible(thd);
|
||||||
@ -2565,8 +2546,7 @@ Type_handler_string_result::make_packed_sort_key_part(uchar *to, Item *item,
|
|||||||
if (maybe_null)
|
if (maybe_null)
|
||||||
*to++= 1;
|
*to++= 1;
|
||||||
|
|
||||||
String tmp(param->tmp_buffer, param->sort_length, cs);
|
String *res= item->str_result(¶m->tmp_buffer);
|
||||||
String *res= item->str_result(&tmp);
|
|
||||||
if (!res)
|
if (!res)
|
||||||
{
|
{
|
||||||
if (maybe_null)
|
if (maybe_null)
|
||||||
|
@ -536,7 +536,7 @@ public:
|
|||||||
|
|
||||||
uchar *unique_buff;
|
uchar *unique_buff;
|
||||||
bool not_killable;
|
bool not_killable;
|
||||||
char* tmp_buffer;
|
String tmp_buffer;
|
||||||
// The fields below are used only by Unique class.
|
// The fields below are used only by Unique class.
|
||||||
qsort2_cmp compare;
|
qsort2_cmp compare;
|
||||||
BUFFPEK_COMPARE_CONTEXT cmp_context;
|
BUFFPEK_COMPARE_CONTEXT cmp_context;
|
||||||
@ -544,6 +544,7 @@ public:
|
|||||||
Sort_param()
|
Sort_param()
|
||||||
{
|
{
|
||||||
memset(reinterpret_cast<void*>(this), 0, sizeof(*this));
|
memset(reinterpret_cast<void*>(this), 0, sizeof(*this));
|
||||||
|
tmp_buffer.set_thread_specific();
|
||||||
}
|
}
|
||||||
void init_for_filesort(uint sortlen, TABLE *table,
|
void init_for_filesort(uint sortlen, TABLE *table,
|
||||||
ha_rows maxrows, bool sort_positions);
|
ha_rows maxrows, bool sort_positions);
|
||||||
|
Reference in New Issue
Block a user