Commit d225b8d1 authored by Oleg Smirnov's avatar Oleg Smirnov

MDEV-27277 Add a warning when max_sort_length is reached

During a query execution some sorting and grouping operations
on strings may be involved. System variable max_sort_length defines
the maximum number of bytes to use when comparing strings during
sorting/grouping. Thus, the comparable parts of strings may be less
than their actual size, so the results of the query may be not
sorted/grouped properly.
To indicate that some comparisons were done on a truncated lengths,
a new warning has been introduced with this commit.
parent cf08f44d
......@@ -680,7 +680,11 @@ b MEDIUMTEXT CHARACTER SET big5);
INSERT INTO t1 VALUES
(REPEAT(0x1125,200000), REPEAT(0x1125,200000)), ('', ''), ('', '');
SELECT a FROM t1 GROUP BY 1 LIMIT 1 INTO @nullll;
Warnings:
Warning 4201 1 strings were longer than max_sort_length. Sorting used only the first 1024 bytes
SELECT b FROM t1 GROUP BY 1 LIMIT 1 INTO @nullll;
Warnings:
Warning 4201 1 strings were longer than max_sort_length. Sorting used only the first 1024 bytes
DROP TABLES t1;
End of 5.0 tests
#
......
......@@ -1918,6 +1918,8 @@ Extra Using filesort
SELECT SUBSTRING(a,1,10), LENGTH(a), GROUP_CONCAT(b) FROM t1 GROUP BY a;
SUBSTRING(a,1,10) LENGTH(a) GROUP_CONCAT(b)
1111111111 1300 one,two
Warnings:
Warning 4201 2 strings were longer than max_sort_length. Sorting used only the first 1024 bytes
EXPLAIN
SELECT SUBSTRING(a,1,10), LENGTH(a) FROM t1 GROUP BY a;
id 1
......@@ -1933,6 +1935,8 @@ Extra Using temporary; Using filesort
SELECT SUBSTRING(a,1,10), LENGTH(a) FROM t1 GROUP BY a;
SUBSTRING(a,1,10) LENGTH(a)
1111111111 1300
Warnings:
Warning 4201 1 strings were longer than max_sort_length. Sorting used only the first 1024 bytes
DROP TABLE t1;
#
# Bug#57688 Assertion `!table || (!table->write_set || bitmap_is_set(table->write_set, field
......@@ -2728,6 +2732,8 @@ f1 f2
NULL
NULL NULL
Warnings:
Warning 4201 116 strings were longer than max_sort_length. Sorting used only the first 1024 bytes
SET @@sort_buffer_size = @old_sort_buff_size;
DROP TABLE t1;
#
......
......@@ -859,6 +859,8 @@ xxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxab
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxaa
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxz
Warnings:
Warning 4201 2 strings were longer than max_sort_length. Sorting used only the first 64 bytes
drop table t1;
create table t1 (
`sid` decimal(8,0) default null,
......@@ -4122,6 +4124,8 @@ a substr(b, @save_max_sort_length+1)
3 ABE
2 AB
1 A
Warnings:
Warning 4201 5 strings were longer than max_sort_length. Sorting used only the first 1024 bytes
analyze format=json
select a, substr(b, @save_max_sort_length+1) from t1 order by b desc;
ANALYZE
......@@ -4167,6 +4171,8 @@ ANALYZE
]
}
}
Warnings:
Warning 4201 5 strings were longer than max_sort_length. Sorting used only the first 1024 bytes
drop table t1;
#
# Packing sort keys with complex collations
......
......@@ -826,6 +826,8 @@ xxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxw
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxy
Warnings:
Warning 4201 4 strings were longer than max_sort_length. Sorting used only the first 200 bytes
reset query cache;
set max_sort_length=64;
select c from t1 order by c, id;
......@@ -834,6 +836,8 @@ xxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxw
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxy
Warnings:
Warning 4201 4 strings were longer than max_sort_length. Sorting used only the first 64 bytes
set max_sort_length=200;
select c from t1 order by c, id;
c
......@@ -841,6 +845,8 @@ xxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxw
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxy
Warnings:
Warning 4201 4 strings were longer than max_sort_length. Sorting used only the first 200 bytes
set max_sort_length=default;
select '1' || '3' from t1;
'1' || '3'
......@@ -877,7 +883,7 @@ Variable_name Value
Qcache_queries_in_cache 0
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 19
Qcache_inserts 16
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 6
......@@ -890,7 +896,7 @@ Variable_name Value
Qcache_queries_in_cache 1
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 20
Qcache_inserts 17
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 7
......
......@@ -899,6 +899,7 @@ Warnings:
Warning 1260 Row 1 was cut by group_concat()
Warning 1260 Row 2 was cut by group_concat()
Warning 1260 Row 3 was cut by group_concat()
Warning 4201 3 strings were longer than max_sort_length. Sorting used only the first 1024 bytes
set @@group_concat_max_len = 256;
explain extended select left(a1,7), left(a2,7)
from t1_1024
......@@ -916,6 +917,7 @@ Warnings:
Warning 1260 Row 1 was cut by group_concat()
Warning 1260 Row 2 was cut by group_concat()
Warning 1260 Row 3 was cut by group_concat()
Warning 4201 3 strings were longer than max_sort_length. Sorting used only the first 1024 bytes
drop table t1_1024, t2_1024, t3_1024;
set @blob_len = 1025;
set @suffix_len = @blob_len - @prefix_len;
......@@ -1000,6 +1002,7 @@ Warnings:
Warning 1260 Row 1 was cut by group_concat()
Warning 1260 Row 2 was cut by group_concat()
Warning 1260 Row 3 was cut by group_concat()
Warning 4201 3 strings were longer than max_sort_length. Sorting used only the first 1024 bytes
set @@group_concat_max_len = 256;
explain extended select left(a1,7), left(a2,7)
from t1_1025
......@@ -1017,6 +1020,7 @@ Warnings:
Warning 1260 Row 1 was cut by group_concat()
Warning 1260 Row 2 was cut by group_concat()
Warning 1260 Row 3 was cut by group_concat()
Warning 4201 3 strings were longer than max_sort_length. Sorting used only the first 1024 bytes
drop table t1_1025, t2_1025, t3_1025;
create table t1bit (a1 bit(3), a2 bit(3));
create table t2bit (b1 bit(3), b2 bit(3));
......
......@@ -919,6 +919,7 @@ Warnings:
Warning 1260 Row 1 was cut by group_concat()
Warning 1260 Row 2 was cut by group_concat()
Warning 1260 Row 3 was cut by group_concat()
Warning 4201 3 strings were longer than max_sort_length. Sorting used only the first 1024 bytes
set @@group_concat_max_len = 256;
explain extended select left(a1,7), left(a2,7)
from t1_1024
......@@ -937,6 +938,7 @@ Warnings:
Warning 1260 Row 1 was cut by group_concat()
Warning 1260 Row 2 was cut by group_concat()
Warning 1260 Row 3 was cut by group_concat()
Warning 4201 3 strings were longer than max_sort_length. Sorting used only the first 1024 bytes
drop table t1_1024, t2_1024, t3_1024;
set @blob_len = 1025;
set @suffix_len = @blob_len - @prefix_len;
......@@ -1022,6 +1024,7 @@ Warnings:
Warning 1260 Row 1 was cut by group_concat()
Warning 1260 Row 2 was cut by group_concat()
Warning 1260 Row 3 was cut by group_concat()
Warning 4201 3 strings were longer than max_sort_length. Sorting used only the first 1024 bytes
set @@group_concat_max_len = 256;
explain extended select left(a1,7), left(a2,7)
from t1_1025
......@@ -1040,6 +1043,7 @@ Warnings:
Warning 1260 Row 1 was cut by group_concat()
Warning 1260 Row 2 was cut by group_concat()
Warning 1260 Row 3 was cut by group_concat()
Warning 4201 3 strings were longer than max_sort_length. Sorting used only the first 1024 bytes
drop table t1_1025, t2_1025, t3_1025;
create table t1bit (a1 bit(3), a2 bit(3));
create table t2bit (b1 bit(3), b2 bit(3));
......
......@@ -97,7 +97,9 @@ eval UPDATE t2, t1 SET t2.data = CONCAT($data, $data, $data, $data),
--source include/wait_for_slave_sql_error_and_skip.inc
--let $diff_tables= master:t1,slave:t1
--disable_warnings # To hide warning 4201 "strings were longer than max_sort_length"
--source include/diff_tables.inc
--enable_warnings
--echo ########################################################################################
--echo # 2 - BEGIN - IMPLICIT COMMIT by DDL
......@@ -180,7 +182,9 @@ CREATE TABLE t5 (a int);
--sync_slave_with_master
--let $diff_tables= master:t1,slave:t1
--disable_warnings # To hide warning 4201 "strings were longer than max_sort_length"
--source include/diff_tables.inc
--enable_warnings
--echo ########################################################################################
--echo # 3 - BEGIN - COMMIT
......@@ -210,7 +214,9 @@ COMMIT;
--sync_slave_with_master
--let $diff_tables= master:t1,slave:t1
--disable_warnings # To hide warning 4201 "strings were longer than max_sort_length"
--source include/diff_tables.inc
--enable_warnings
--echo ########################################################################################
--echo # 4 - BEGIN - ROLLBACK
......@@ -240,7 +246,9 @@ ROLLBACK;
--sync_slave_with_master
--let $diff_tables= master:t1,slave:t1
--disable_warnings # To hide warning 4201 "strings were longer than max_sort_length"
--source include/diff_tables.inc
--enable_warnings
--echo ########################################################################################
--echo # 5 - PROCEDURE
......@@ -290,7 +298,9 @@ ROLLBACK;
--sync_slave_with_master
--let $diff_tables= master:t1,slave:t1
--disable_warnings # To hide warning 4201 "strings were longer than max_sort_length"
--source include/diff_tables.inc
--enable_warnings
--echo ########################################################################################
--echo # 6 - XID
......@@ -322,7 +332,9 @@ COMMIT;
--sync_slave_with_master
--let $diff_tables= master:t1,slave:t1
--disable_warnings # To hide warning 4201 "strings were longer than max_sort_length"
--source include/diff_tables.inc
--enable_warnings
--echo ########################################################################################
--echo # 7 - NON-TRANS TABLE
......@@ -366,7 +378,9 @@ COMMIT;
--sync_slave_with_master
--let $diff_tables= master:t1,slave:t1
--disable_warnings # To hide warning 4201 "strings were longer than max_sort_length"
--source include/diff_tables.inc
--enable_warnings
--echo ########################################################################
--echo # 8 - Bug#55375(Regression Bug) Transaction bigger than
......
......@@ -132,8 +132,10 @@ show status like "binlog_cache_disk_use";
sync_slave_with_master;
--disable_warnings # To hide warning 4197 "Comparison limited during sorting/grouping"
let $diff_tables=master:test.t2, slave:test.t2;
source include/diff_tables.inc;
--enable_warnings
# undoing changes with verifying the above once again
connection master;
......@@ -175,7 +177,9 @@ show status like "binlog_cache_disk_use";
sync_slave_with_master;
let $diff_tables=master:test.t3, slave:test.t3;
--disable_warnings # To hide warning 4197 "Comparison limited during sorting/grouping"
source include/diff_tables.inc;
--enable_warnings
# undoing changes with verifying the above once again
connection master;
......@@ -233,6 +237,7 @@ show status like "binlog_cache_disk_use";
sync_slave_with_master;
--disable_warnings # To hide warning 4197 "Comparison limited during sorting/grouping"
let $diff_tables=master:test.t1, slave:test.t1;
source include/diff_tables.inc;
......@@ -241,7 +246,7 @@ source include/diff_tables.inc;
let $diff_tables=master:test.t3, slave:test.t3;
source include/diff_tables.inc;
--enable_warnings
--echo *** Test switching checksum algorithm while ongoing transactions have pre-computed checksum in their binlog cache ***
......
......@@ -124,7 +124,9 @@ if(`SELECT COUNT(*)!=1 FROM t2`)
--source include/sync_with_master_gtid.inc
--echo # Validating the first insert into t2 replicated to slave..
--let $diff_tables= master:test.t2,slave:test.t2
--disable_warnings # To hide warning 4197 "Comparison limited during sorting/grouping"
--source include/diff_tables.inc
--enable_warnings
--echo # ..success
# Testing mixed engine UPDATE statement scenario. In the following multi
......
......@@ -141,7 +141,9 @@ SHOW VARIABLES LIKE 'gtid_binlog_pos';
SHOW VARIABLES LIKE 'gtid_binlog_state';
--let $diff_tables=server_1:t1, server_2:t1
--disable_warnings # To hide warning 4197 "Comparison limited during sorting/grouping"
--source include/diff_tables.inc
--enable_warnings
--connection server_1
--let $case = 3
......
......@@ -195,6 +195,87 @@ INSERT INTO t2 set c = concat(repeat('x',68),'g','w');
SELECT c from t2 ORDER BY c, id;
--echo ** Results should not be sorted **
DROP TABLE t, t1, t2;
--echo #
--echo # MDEV-27277 Add a warning when max_sort_length is reached
--echo #
set max_sort_length = 70;
--echo # Table having a fixed-length string field
create table t1(a char(100));
insert into t1 values
(concat(repeat('Str', 25), 'zzz')), (concat(repeat('Str', 25), 'yyy')),
(concat(repeat('Str', 25), 'xxx')),
('shortString89'), ('shortString51');
select a from t1 order by a;
--echo # Long strings are not sorted properly due to truncation to max_sort_length.
--echo # Warning shows 3 strings out of 5 since the short strings are not truncated.
--echo # Table having a variable-length string field and UTF16 encoding (2 bytes per char):
create table t2(a varchar(100)) character set 'utf16';
insert into t2 values
(concat(repeat('Str', 15), 'zzz')), (concat(repeat('Str', 15), 'yyy')),
(concat(repeat('Str', 15), 'xxx')),
('shortString89'),
('shortString51');
set max_sort_length = 64;
select * from t2 order by a;
--echo # Table having text blobs
create table t3(a text, b mediumtext, c longtext) character set 'utf16';
insert into t3 values
(concat(repeat('Text', 20), '999'), concat(repeat('Medium', 15), '99'), concat(repeat('Long', 20), '99')),
(concat(repeat('Text', 20), '888'), concat(repeat('Medium', 15), '88'), concat(repeat('Long', 20), '88')),
(concat(repeat('Text', 20), '777'), concat(repeat('Medium', 15), '77'), concat(repeat('Long', 20), '77')),
('shortString89', 'short123', 'short456'),
('shortString51', 'short777', 'short897');
select * from t3 order by a;
select * from t3 order by b desc;
select * from t3 order by c;
select * from t3 order by c, a desc;
--echo # Packing of sort keys will be applied here:
select * from t3 order by a, c, b;
select * from t3 order by a;
--echo # Test a prepared statement re-execution (expecting warnings at both executions)
prepare stmt from "select * from t2 order by a";
execute stmt;
execute stmt;
--echo # Test a stored procedure
create procedure p1() select * from t2 order by a;
call p1();
call p1();
drop procedure p1;
--echo # Test a stored function
create function f1 () returns char(100) return (select a from t1 order by a limit 1);
--disable_view_protocol # Because warnings display different number of strings
select f1() as f1_res from t1 order by f1_res;
--enable_view_protocol
--echo # Test a view
create view v1 as select f1() as f1_res from t1 order by f1_res;
select * from v1;
drop function f1;
drop view v1;
drop table t1, t2, t3;
#
# Cleanup
#
......@@ -204,6 +285,4 @@ connection default;
disconnect test_con1;
disconnect test_con2;
DROP TABLE t, t1, t2;
SET @@global.max_sort_length= @start_value;
......@@ -91,6 +91,8 @@ x left(b, 10) left(v, 10)
44 zzzzzzzzzz zzzzzzzzzz
50 zzzzzzzzzz zzzzzzzzzz
56 zzzzzzzzzz zzzzzzzzzz
Warnings:
Warning 4197 29 strings were longer than max_sort_length. Sorting used only the first 1024 bytes
update t1 set b= 'bar' where v > 'a' limit 20;
drop table t1;
# Cover return_top_record() in ha_partition::handle_ordered_index_scan()
......
......@@ -257,12 +257,16 @@ select x, left(y, 4), length(y), check_row(row_start, row_end) from t1 for syste
x left(y, 4) length(y) check_row(row_start, row_end)
1 LONG 8192 HISTORICAL ROW
2 LONG 8192 CURRENT ROW
Warnings:
Warning 4197 2 strings were longer than max_sort_length. Sorting used only the first 1024 bytes
update t1 set y= 'SHORT';
select x, left(y, 4), length(y), check_row(row_start, row_end) from t1 for system_time all order by x, y;
x left(y, 4) length(y) check_row(row_start, row_end)
1 LONG 8192 HISTORICAL ROW
2 LONG 8192 HISTORICAL ROW
2 SHOR 5 CURRENT ROW
Warnings:
Warning 4197 2 strings were longer than max_sort_length. Sorting used only the first 1024 bytes
drop tables t1;
### Issue tempesta-tech/mariadb#365, bug 7 (duplicate of historical row)
create or replace table t1 (a int primary key, b int)
......
......@@ -1062,11 +1062,12 @@ CPP_UNNAMED_NS_END
@brief
Create a fixed size sort key part
@param buff buffer where values are written
@param length fixed size of the sort column
@param buff buffer where values are written
@param length fixed size of the sort column
@param original_length original size of the field
*/
void Field::make_sort_key_part(uchar *buff,uint length)
void Field::make_sort_key_part(uchar *buff,uint length, uint original_length)
{
if (maybe_null())
{
......@@ -1077,7 +1078,7 @@ void Field::make_sort_key_part(uchar *buff,uint length)
}
*buff++= 1;
}
sort_string(buff, length);
sort_string(buff, length, original_length);
}
......@@ -1132,7 +1133,8 @@ Field_longstr::pack_sort_string(uchar *to, const SORT_FIELD_ATTR *sort_field)
{
StringBuffer<LONGLONG_BUFFER_SIZE+1> buf;
val_str(&buf, &buf);
return to + sort_field->pack_sort_string(to, &buf, field_charset());
return to + sort_field->pack_sort_string(to, &buf,
field_charset());
}
......@@ -3335,7 +3337,7 @@ int Field_decimal::cmp(const uchar *a_ptr,const uchar *b_ptr) const
}
void Field_decimal::sort_string(uchar *to,uint length)
void Field_decimal::sort_string(uchar *to,uint length, uint original_length)
{
uchar *str,*end;
for (str=ptr,end=ptr+length;
......@@ -3689,7 +3691,8 @@ int Field_new_decimal::cmp(const uchar *a,const uchar*b) const
}
void Field_new_decimal::sort_string(uchar *buff, uint length)
void Field_new_decimal::sort_string(uchar *buff, uint length,
uint original_length)
{
memcpy(buff, ptr, length);
}
......@@ -4030,7 +4033,8 @@ int Field_tiny::cmp(const uchar *a_ptr, const uchar *b_ptr) const
return (a < b) ? -1 : (a > b) ? 1 : 0;
}
void Field_tiny::sort_string(uchar *to,uint length __attribute__((unused)))
void Field_tiny::sort_string(uchar *to,uint length __attribute__((unused)),
uint original_length)
{
if (unsigned_flag)
*to= *ptr;
......@@ -4198,7 +4202,8 @@ int Field_short::cmp(const uchar *a_ptr, const uchar *b_ptr) const
return (a < b) ? -1 : (a > b) ? 1 : 0;
}
void Field_short::sort_string(uchar *to,uint length __attribute__((unused)))
void Field_short::sort_string(uchar *to,uint length __attribute__((unused)),
uint original_length)
{
if (unsigned_flag)
to[0] = ptr[1];
......@@ -4389,7 +4394,8 @@ int Field_medium::cmp(const uchar *a_ptr, const uchar *b_ptr) const
return (a < b) ? -1 : (a > b) ? 1 : 0;
}
void Field_medium::sort_string(uchar *to,uint length __attribute__((unused)))
void Field_medium::sort_string(uchar *to,uint length __attribute__((unused)),
uint original_length)
{
if (unsigned_flag)
to[0] = ptr[2];
......@@ -4557,7 +4563,8 @@ int Field_long::cmp(const uchar *a_ptr, const uchar *b_ptr) const
return (a < b) ? -1 : (a > b) ? 1 : 0;
}
void Field_long::sort_string(uchar *to,uint length __attribute__((unused)))
void Field_long::sort_string(uchar *to,uint length __attribute__((unused)),
uint original_length)
{
if (unsigned_flag)
to[0] = ptr[3];
......@@ -4699,7 +4706,8 @@ int Field_longlong::cmp(const uchar *a_ptr, const uchar *b_ptr) const
return (a < b) ? -1 : (a > b) ? 1 : 0;
}
void Field_longlong::sort_string(uchar *to,uint length __attribute__((unused)))
void Field_longlong::sort_string(uchar *to,uint length __attribute__((unused)),
uint original_length)
{
if (unsigned_flag)
to[0] = ptr[7];
......@@ -4825,7 +4833,8 @@ int Field_float::cmp(const uchar *a_ptr, const uchar *b_ptr) const
#define FLT_EXP_DIG (sizeof(float)*8-FLT_MANT_DIG)
void Field_float::sort_string(uchar *to,uint length __attribute__((unused)))
void Field_float::sort_string(uchar *to,uint length __attribute__((unused)),
uint original_length)
{
float nr;
float4get(nr,ptr);
......@@ -5181,7 +5190,8 @@ int Field_double::cmp(const uchar *a_ptr, const uchar *b_ptr) const
/* The following should work for IEEE */
void Field_double::sort_string(uchar *to,uint length __attribute__((unused)))
void Field_double::sort_string(uchar *to,uint length __attribute__((unused)),
uint original_length)
{
double nr;
float8get(nr,ptr);
......@@ -5595,7 +5605,8 @@ int Field_timestamp0::cmp(const uchar *a_ptr, const uchar *b_ptr) const
}
void Field_timestamp0::sort_string(uchar *to,uint length __attribute__((unused)))
void Field_timestamp0::sort_string(uchar *to,uint length __attribute__((unused)),
uint original_length)
{
to[0] = ptr[3];
to[1] = ptr[2];
......@@ -6288,7 +6299,8 @@ int Field_time0::cmp(const uchar *a_ptr, const uchar *b_ptr) const
return (a < b) ? -1 : (a > b) ? 1 : 0;
}
void Field_time0::sort_string(uchar *to,uint length __attribute__((unused)))
void Field_time0::sort_string(uchar *to,uint length __attribute__((unused)),
uint original_length)
{
to[0] = (uchar) (ptr[2] ^ 128);
to[1] = ptr[1];
......@@ -6463,7 +6475,8 @@ int Field_time_hires::cmp(const uchar *a_ptr, const uchar *b_ptr) const
return (a < b) ? -1 : (a > b) ? 1 : 0;
}
void Field_time_hires::sort_string(uchar *to,uint length __attribute__((unused)))
void Field_time_hires::sort_string(uchar *to,uint length __attribute__((unused)),
uint original_length)
{
DBUG_ASSERT(length == Field_time_hires::pack_length());
memcpy(to, ptr, length);
......@@ -6835,7 +6848,8 @@ int Field_date::cmp(const uchar *a_ptr, const uchar *b_ptr) const
}
void Field_date::sort_string(uchar *to,uint length __attribute__((unused)))
void Field_date::sort_string(uchar *to,uint length __attribute__((unused)),
uint original_length)
{
to[0] = ptr[3];
to[1] = ptr[2];
......@@ -6947,7 +6961,8 @@ int Field_newdate::cmp(const uchar *a_ptr, const uchar *b_ptr) const
}
void Field_newdate::sort_string(uchar *to,uint length __attribute__((unused)))
void Field_newdate::sort_string(uchar *to,uint length __attribute__((unused)),
uint original_length)
{
to[0] = ptr[2];
to[1] = ptr[1];
......@@ -7136,7 +7151,8 @@ int Field_datetime0::cmp(const uchar *a_ptr, const uchar *b_ptr) const
((ulonglong) a > (ulonglong) b) ? 1 : 0;
}
void Field_datetime0::sort_string(uchar *to,uint length __attribute__((unused)))
void Field_datetime0::sort_string(uchar *to,uint length __attribute__((unused)),
uint original_length)
{
to[0] = ptr[7];
to[1] = ptr[6];
......@@ -7734,7 +7750,7 @@ int Field_string::cmp_prefix(const uchar *a_ptr, const uchar *b_ptr,
}
void Field_string::sort_string(uchar *to,uint length)
void Field_string::sort_string(uchar *to,uint length, uint original_length)
{
#ifdef DBUG_ASSERT_EXISTS
size_t tmp=
......@@ -7745,6 +7761,8 @@ void Field_string::sort_string(uchar *to,uint length)
MY_STRXFRM_PAD_WITH_SPACE |
MY_STRXFRM_PAD_TO_MAXLEN);
DBUG_ASSERT(tmp == length);
if (original_length < value_length())
get_thd()->num_of_strings_sorted_on_truncated_length++;
}
......@@ -8176,7 +8194,7 @@ int Field_varstring::key_cmp(const uchar *a,const uchar *b) const
}
void Field_varstring::sort_string(uchar *to,uint length)
void Field_varstring::sort_string(uchar *to,uint length, uint original_length)
{
String buf;
......@@ -8201,6 +8219,8 @@ void Field_varstring::sort_string(uchar *to,uint length)
MY_STRXFRM_PAD_WITH_SPACE |
MY_STRXFRM_PAD_TO_MAXLEN);
DBUG_ASSERT(rc == length);
if (original_length < value_length())
get_thd()->num_of_strings_sorted_on_truncated_length++;
}
......@@ -9064,7 +9084,7 @@ uint32 Field_blob::sort_suffix_length() const
}
void Field_blob::sort_string(uchar *to,uint length)
void Field_blob::sort_string(uchar *to,uint length, uint original_length)
{
String buf;
......@@ -9090,6 +9110,8 @@ void Field_blob::sort_string(uchar *to,uint length)
MY_STRXFRM_PAD_WITH_SPACE |
MY_STRXFRM_PAD_TO_MAXLEN);
DBUG_ASSERT(rc == length);
if (original_length < value_length())
get_thd()->num_of_strings_sorted_on_truncated_length++;
}
}
......@@ -9481,7 +9503,8 @@ int Field_enum::cmp(const uchar *a_ptr, const uchar *b_ptr) const
return (a < b) ? -1 : (a > b) ? 1 : 0;
}
void Field_enum::sort_string(uchar *to,uint length __attribute__((unused)))
void Field_enum::sort_string(uchar *to,uint length __attribute__((unused)),
uint original_length)
{
ulonglong value=Field_enum::val_int();
to+=packlength-1;
......
This diff is collapsed.
......@@ -2903,9 +2903,14 @@ SORT_FIELD_ATTR::pack_sort_string(uchar *to, const Binary_string *str,
length= (uint32) str->length();
if (length + suffix_length <= original_length)
{
data_length= length;
}
else
{
data_length= original_length - suffix_length;
current_thd->num_of_strings_sorted_on_truncated_length++;
}
// length stored in lowendian form
store_key_part_length(data_length + suffix_length, to, length_bytes);
......@@ -2949,7 +2954,8 @@ static uint make_sortkey(Sort_param *param, uchar *to)
if ((field=sort_field->field))
{
// Field
field->make_sort_key_part(to, sort_field->length);
field->make_sort_key_part(to, sort_field->length,
sort_field->original_length);
if ((maybe_null= field->maybe_null()))
to++;
}
......
......@@ -12280,3 +12280,8 @@ ER_SEQUENCE_TABLE_ORDER_BY
eng "ORDER BY"
ER_VARIABLE_IGNORED
eng "The variable '%s' is ignored. It only exists for compatibility with old installations and will be removed in a future release"
WARN_SORTING_ON_TRUNCATED_LENGTH
eng "%llu strings were longer than max_sort_length. Sorting used only the first %lu bytes"
ger "%llu Zeichenketten waren länger als max_sort_length. Sie wurden anhand der ersten %lu Bytes verglichen"
rus "%llu строк были длиннее, чем max_sort_length. Их сортировка проведена по первым %lu байтам"
swe "%llu sträng var längre än max_sort_length=%lu"
......@@ -1386,6 +1386,7 @@ void THD::init()
first_successful_insert_id_in_cur_stmt= 0;
current_backup_stage= BACKUP_FINISHED;
backup_commit_lock= 0;
num_of_strings_sorted_on_truncated_length= 0;
#ifdef WITH_WSREP
wsrep_last_query_id= 0;
wsrep_xid.null();
......
......@@ -5849,6 +5849,13 @@ class THD: public THD_count, /* this must be first */
/* Handling of timeouts for commands */
thr_timer_t query_timer;
/*
Number of strings which were involved in sorting or grouping and whose
lengths were truncated according to the max_sort_length system variable
setting
*/
ulonglong num_of_strings_sorted_on_truncated_length;
public:
void set_query_timer()
{
......@@ -6049,6 +6056,23 @@ class THD: public THD_count, /* this must be first */
bool need_report_unit_results();
bool report_collected_unit_results();
bool init_collecting_unit_results();
/*
Push post-execution warnings, which may be some kinds of aggregate messages
like number of times max_sort_length was reached during sorting/grouping
*/
void push_final_warnings()
{
if (num_of_strings_sorted_on_truncated_length)
{
push_warning_printf(this, Sql_condition::WARN_LEVEL_WARN,
WARN_SORTING_ON_TRUNCATED_LENGTH,
ER_THD(this, WARN_SORTING_ON_TRUNCATED_LENGTH),
num_of_strings_sorted_on_truncated_length,
variables.max_sort_length);
num_of_strings_sorted_on_truncated_length= 0;
}
}
};
......
......@@ -5348,7 +5348,7 @@ mysql_select(THD *thd, TABLE_LIST *tables, List<Item> &fields, COND *conds,
}
err:
thd->push_final_warnings();
if (select_lex->pushdown_select)
{
delete select_lex->pushdown_select;
......@@ -27598,7 +27598,7 @@ static int remove_dup_with_hash_index(THD *thd, TABLE *table,
field_length=field_lengths;
for (Field **ptr= first_field ; *ptr ; ptr++)
{
(*ptr)->make_sort_key_part(key_pos, *field_length);
(*ptr)->make_sort_key_part(key_pos, *field_length, *field_length);
key_pos+= (*ptr)->maybe_null() + *field_length++;
}
/* Copy result fields not stored in table to key buffer */
......@@ -398,7 +398,7 @@ a) void make_sort_key(uchar *buff, uint length);
make_sort_key is a non-virtual function which handles encoding of
SQL null values.
b) virtual void sort_string(uchar *buff,uint length)=0;
b) virtual void sort_string(uchar *buff,uint length, uint original_length)=0;
sort_string produces mem-comparable image of the field value
for each datatype.
......
......@@ -391,7 +391,7 @@ class Type_handler_fbt: public Type_handler
int cmp(const uchar *a, const uchar *b) const override
{ return memcmp(a, b, pack_length()); }
void sort_string(uchar *to, uint length) override
void sort_string(uchar *to, uint length, uint original_length) override
{
DBUG_ASSERT(length == pack_length());
memcpy(to, ptr, length);
......
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