Skip to content

Commit 9f862ce

Browse files
committed
MDEV#7383: engine-independent-stats column_stats has limited values for max/min values
Patch from Daniel Black: - Change the charset of mysql.column_stats.{min_value, max_value} from utf8_bin varchar to varbinary - Adjust the code that saves/reads the data accordingly. - Also provide upgrade statement in mysql_system_tables_fix.sql
1 parent 1694d81 commit 9f862ce

File tree

5 files changed

+46
-9
lines changed

5 files changed

+46
-9
lines changed

mysql-test/r/statistics.result

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1622,3 +1622,22 @@ test t2 id 1 1024 0.0000 8.0000 63 SINGLE_PREC_HB 03070B0F13171B1F23272B2F33373B
16221622
set histogram_size=default;
16231623
drop table t1, t2;
16241624
set use_stat_tables=@save_use_stat_tables;
1625+
#
1626+
# Bug MDEV-7383: min/max value for a column not utf8 compatible
1627+
#
1628+
create table t1 (a varchar(100)) engine=MyISAM;
1629+
insert into t1 values(unhex('D879626AF872675F73E662F8'));
1630+
analyze table t1 persistent for all;
1631+
Table Op Msg_type Msg_text
1632+
test.t1 analyze status Engine-independent statistics collected
1633+
test.t1 analyze status OK
1634+
show warnings;
1635+
Level Code Message
1636+
select db_name, table_name, column_name,
1637+
HEX(min_value), HEX(max_value),
1638+
nulls_ratio, avg_frequency,
1639+
hist_size, hist_type, HEX(histogram)
1640+
FROM mysql.column_stats;
1641+
db_name table_name column_name HEX(min_value) HEX(max_value) nulls_ratio avg_frequency hist_size hist_type HEX(histogram)
1642+
test t1 a D879626AF872675F73E662F8 D879626AF872675F73E662F8 0.0000 1.0000 0 NULL NULL
1643+
drop table t1;

mysql-test/t/statistics.test

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -701,3 +701,19 @@ drop table t1, t2;
701701

702702
set use_stat_tables=@save_use_stat_tables;
703703

704+
--echo #
705+
--echo # Bug MDEV-7383: min/max value for a column not utf8 compatible
706+
--echo #
707+
708+
create table t1 (a varchar(100)) engine=MyISAM;
709+
insert into t1 values(unhex('D879626AF872675F73E662F8'));
710+
analyze table t1 persistent for all;
711+
show warnings;
712+
713+
select db_name, table_name, column_name,
714+
HEX(min_value), HEX(max_value),
715+
nulls_ratio, avg_frequency,
716+
hist_size, hist_type, HEX(histogram)
717+
FROM mysql.column_stats;
718+
719+
drop table t1;

scripts/mysql_system_tables.sql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,7 @@ set @had_proxies_priv_table= @@warning_count != 0;
220220

221221
CREATE TABLE IF NOT EXISTS table_stats (db_name varchar(64) NOT NULL, table_name varchar(64) NOT NULL, cardinality bigint(21) unsigned DEFAULT NULL, PRIMARY KEY (db_name,table_name) ) ENGINE=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Statistics on Tables';
222222

223-
CREATE TABLE IF NOT EXISTS column_stats (db_name varchar(64) NOT NULL, table_name varchar(64) NOT NULL, column_name varchar(64) NOT NULL, min_value varchar(255) DEFAULT NULL, max_value varchar(255) DEFAULT NULL, nulls_ratio decimal(12,4) DEFAULT NULL, avg_length decimal(12,4) DEFAULT NULL, avg_frequency decimal(12,4) DEFAULT NULL, hist_size tinyint unsigned, hist_type enum('SINGLE_PREC_HB','DOUBLE_PREC_HB'), histogram varbinary(255), PRIMARY KEY (db_name,table_name,column_name) ) ENGINE=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Statistics on Columns';
223+
CREATE TABLE IF NOT EXISTS column_stats (db_name varchar(64) NOT NULL, table_name varchar(64) NOT NULL, column_name varchar(64) NOT NULL, min_value varbinary(255) DEFAULT NULL, max_value varbinary(255) DEFAULT NULL, nulls_ratio decimal(12,4) DEFAULT NULL, avg_length decimal(12,4) DEFAULT NULL, avg_frequency decimal(12,4) DEFAULT NULL, hist_size tinyint unsigned, hist_type enum('SINGLE_PREC_HB','DOUBLE_PREC_HB'), histogram varbinary(255), PRIMARY KEY (db_name,table_name,column_name) ) ENGINE=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Statistics on Columns';
224224

225225
CREATE TABLE IF NOT EXISTS index_stats (db_name varchar(64) NOT NULL, table_name varchar(64) NOT NULL, index_name varchar(64) NOT NULL, prefix_arity int(11) unsigned NOT NULL, avg_frequency decimal(12,4) DEFAULT NULL, PRIMARY KEY (db_name,table_name,index_name,prefix_arity) ) ENGINE=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Statistics on Indexes';
226226

scripts/mysql_system_tables_fix.sql

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -711,3 +711,5 @@ flush privileges;
711711
ALTER TABLE help_category MODIFY url TEXT NOT NULL;
712712
ALTER TABLE help_topic MODIFY url TEXT NOT NULL;
713713

714+
# MDEV-7383 - varbinary on mix/max of column_stats
715+
alter table column_stats modify min_value varbinary(255) DEFAULT NULL, modify max_value varbinary(255) DEFAULT NULL;

sql/sql_statistics.cc

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -888,15 +888,15 @@ class Column_stat: public Stat_table
888888
889889
@note
890890
A value from the field min_value/max_value is always converted
891-
into a utf8 string. If the length of the column 'min_value'/'max_value'
891+
into a varbinary string. If the length of the column 'min_value'/'max_value'
892892
is less than the length of the string the string is trimmed to fit the
893893
length of the column.
894894
*/
895895

896896
void store_stat_fields()
897897
{
898898
char buff[MAX_FIELD_WIDTH];
899-
String val(buff, sizeof(buff), &my_charset_utf8_bin);
899+
String val(buff, sizeof(buff), &my_charset_bin);
900900

901901
for (uint i= COLUMN_STAT_MIN_VALUE; i <= COLUMN_STAT_HISTOGRAM; i++)
902902
{
@@ -913,7 +913,7 @@ class Column_stat: public Stat_table
913913
else
914914
{
915915
table_field->collected_stats->min_value->val_str(&val);
916-
stat_field->store(val.ptr(), val.length(), &my_charset_utf8_bin);
916+
stat_field->store(val.ptr(), val.length(), &my_charset_bin);
917917
}
918918
break;
919919
case COLUMN_STAT_MAX_VALUE:
@@ -922,7 +922,7 @@ class Column_stat: public Stat_table
922922
else
923923
{
924924
table_field->collected_stats->max_value->val_str(&val);
925-
stat_field->store(val.ptr(), val.length(), &my_charset_utf8_bin);
925+
stat_field->store(val.ptr(), val.length(), &my_charset_bin);
926926
}
927927
break;
928928
case COLUMN_STAT_NULLS_RATIO:
@@ -983,7 +983,7 @@ class Column_stat: public Stat_table
983983
if (find_stat())
984984
{
985985
char buff[MAX_FIELD_WIDTH];
986-
String val(buff, sizeof(buff), &my_charset_utf8_bin);
986+
String val(buff, sizeof(buff), &my_charset_bin);
987987

988988
for (uint i= COLUMN_STAT_MIN_VALUE; i <= COLUMN_STAT_HIST_TYPE; i++)
989989
{
@@ -1002,12 +1002,12 @@ class Column_stat: public Stat_table
10021002
case COLUMN_STAT_MIN_VALUE:
10031003
stat_field->val_str(&val);
10041004
table_field->read_stats->min_value->store(val.ptr(), val.length(),
1005-
&my_charset_utf8_bin);
1005+
&my_charset_bin);
10061006
break;
10071007
case COLUMN_STAT_MAX_VALUE:
10081008
stat_field->val_str(&val);
10091009
table_field->read_stats->max_value->store(val.ptr(), val.length(),
1010-
&my_charset_utf8_bin);
1010+
&my_charset_bin);
10111011
break;
10121012
case COLUMN_STAT_NULLS_RATIO:
10131013
table_field->read_stats->set_nulls_ratio(stat_field->val_real());
@@ -1053,7 +1053,7 @@ class Column_stat: public Stat_table
10531053
if (find_stat())
10541054
{
10551055
char buff[MAX_FIELD_WIDTH];
1056-
String val(buff, sizeof(buff), &my_charset_utf8_bin);
1056+
String val(buff, sizeof(buff), &my_charset_bin);
10571057
uint fldno= COLUMN_STAT_HISTOGRAM;
10581058
Field *stat_field= stat_table->field[fldno];
10591059
table_field->read_stats->set_not_null(fldno);

0 commit comments

Comments
 (0)