diff --git a/include/m_ctype.h b/include/m_ctype.h index 55d3cc0aeca..ab2f84656ef 100644 --- a/include/m_ctype.h +++ b/include/m_ctype.h @@ -630,10 +630,6 @@ struct my_charset_handler_st int (*ctype)(CHARSET_INFO *cs, int *ctype, const uchar *s, const uchar *e); - /* Functions for case and sort conversion */ - size_t (*caseup_str)(CHARSET_INFO *, char *); - size_t (*casedn_str)(CHARSET_INFO *, char *); - my_charset_conv_case caseup; my_charset_conv_case casedn; @@ -849,6 +845,39 @@ struct charset_info_st return (cset->casedn)(this, src, srclen, dst, dstlen); } + size_t opt_casedn(const char *src, size_t srclen, + char *dst, size_t dstlen, my_bool opt_casedn) const + { + if (opt_casedn) + return casedn(src, srclen, dst, dstlen); + if (srclen > dstlen) + srclen= dstlen; + memcpy(dst, src, srclen); + return srclen; + } + + /* Convert to a lower-cased 0-terminated string */ + size_t casedn_z(const char *src, size_t srclen, + char *dst, size_t dstlen) const + { + DBUG_ASSERT(dstlen); + DBUG_ASSERT(src != dst); + size_t len= casedn(src, srclen, dst, dstlen - 1); + dst[len]= '\0'; + return len; + } + + /* Convert to a upper-cased 0-terminated string */ + size_t caseup_z(const char *src, size_t srclen, + char *dst, size_t dstlen) const + { + DBUG_ASSERT(dstlen); + DBUG_ASSERT(src != dst); + size_t len= caseup(src, srclen, dst, dstlen - 1); + dst[len]= '\0'; + return len; + } + uint caseup_multiply() const { return (cset->caseup_multiply)(this); @@ -1513,6 +1542,14 @@ size_t my_copy_fix_mb(CHARSET_INFO *cs, /* Functions for 8bit */ extern size_t my_caseup_str_8bit(CHARSET_INFO *, char *); extern size_t my_casedn_str_8bit(CHARSET_INFO *, char *); +static inline size_t my_caseup_str_latin1(char *str) +{ + return my_caseup_str_8bit(&my_charset_latin1, str); +} +static inline size_t my_casedn_str_latin1(char *str) +{ + return my_casedn_str_8bit(&my_charset_latin1, str); +} extern size_t my_caseup_8bit(CHARSET_INFO *, const char *src, size_t srclen, char *dst, size_t dstlen); @@ -1609,8 +1646,6 @@ int my_charlen_8bit(CHARSET_INFO *, const uchar *str, const uchar *end); /* Functions for multibyte charsets */ -extern size_t my_caseup_str_mb(CHARSET_INFO *, char *); -extern size_t my_casedn_str_mb(CHARSET_INFO *, char *); extern size_t my_caseup_mb(CHARSET_INFO *, const char *src, size_t srclen, char *dst, size_t dstlen); @@ -1857,9 +1892,6 @@ my_well_formed_length(CHARSET_INFO *cs, const char *b, const char *e, } -#define my_caseup_str(s, a) ((s)->cset->caseup_str((s), (a))) -#define my_casedn_str(s, a) ((s)->cset->casedn_str((s), (a))) - /* XXX: still need to take care of this one */ #ifdef MY_CHARSET_TIS620 #error The TIS620 charset is broken at the moment. Tell tim to fix it. diff --git a/mysql-test/main/ctype_utf16.result b/mysql-test/main/ctype_utf16.result index 64de622be51..89d5283b63c 100644 --- a/mysql-test/main/ctype_utf16.result +++ b/mysql-test/main/ctype_utf16.result @@ -1584,7 +1584,7 @@ ORDER BY l DESC; id l a 512 Warnings: -Warning 1260 Row 1 was cut by GROUP_CONCAT() +Warning 1260 Row 1 was cut by group_concat() SET STATEMENT group_concat_max_len=1024 FOR SELECT id, CHAR_LENGTH(GROUP_CONCAT(body)) AS l FROM (SELECT 'a' AS id, REPEAT('foo bar', 100) AS body @@ -1593,7 +1593,7 @@ SELECT 'a' AS id, REPEAT('bla bla', 100) AS body) t1; id l a 512 Warnings: -Warning 1260 Row 1 was cut by GROUP_CONCAT() +Warning 1260 Row 1 was cut by group_concat() # # MDEV-6865 Merge Bug#18935421 RPAD DIES WITH CERTAIN PADSTR INTPUTS.. # diff --git a/mysql-test/main/ctype_utf32.result b/mysql-test/main/ctype_utf32.result index f9523a783ea..7806b90b081 100644 --- a/mysql-test/main/ctype_utf32.result +++ b/mysql-test/main/ctype_utf32.result @@ -1638,7 +1638,7 @@ ORDER BY l DESC; id l a 256 Warnings: -Warning 1260 Row 1 was cut by GROUP_CONCAT() +Warning 1260 Row 1 was cut by group_concat() # # incorrect charset for val_str_ascii # diff --git a/mysql-test/main/foreign_key.result b/mysql-test/main/foreign_key.result index d673b77d613..a470b15b1c3 100644 --- a/mysql-test/main/foreign_key.result +++ b/mysql-test/main/foreign_key.result @@ -108,3 +108,12 @@ ALTER TABLE tfk ADD CONSTRAINT sid UNIQUE(c2); ERROR 42000: Duplicate key name 'sid' DROP TABLE tfk; DROP TABLE tpk; +# +# MDEV-33223 Assertion `dst_size > 4' failed in size_t Identifier_chain2::make_sep_name_opt_casedn(char*, size_t, int, bool) const +# +CREATE DATABASE x; +USE x; +CREATE TABLE t (i INT, j INT, CONSTRAINT fk2 FOREIGN KEY(i) REFERENCES p (i)) ENGINE=InnoDB; +ERROR HY000: Can't create table `x`.`t` (errno: 150 "Foreign key constraint is incorrectly formed") +DROP DATABASE x; +USE test; diff --git a/mysql-test/main/foreign_key.test b/mysql-test/main/foreign_key.test index 8f42d43718e..8248dd6fb42 100644 --- a/mysql-test/main/foreign_key.test +++ b/mysql-test/main/foreign_key.test @@ -142,3 +142,13 @@ DROP TABLE tfk; DROP TABLE tpk; +--echo # +--echo # MDEV-33223 Assertion `dst_size > 4' failed in size_t Identifier_chain2::make_sep_name_opt_casedn(char*, size_t, int, bool) const +--echo # + +CREATE DATABASE x; +USE x; +--error ER_CANT_CREATE_TABLE +CREATE TABLE t (i INT, j INT, CONSTRAINT fk2 FOREIGN KEY(i) REFERENCES p (i)) ENGINE=InnoDB; +DROP DATABASE x; +USE test; diff --git a/mysql-test/main/func_gconcat.result b/mysql-test/main/func_gconcat.result index fea25124941..fe3f2d296da 100644 --- a/mysql-test/main/func_gconcat.result +++ b/mysql-test/main/func_gconcat.result @@ -152,10 +152,10 @@ grp group_concat(c) 4 5 NULL Warnings: -Warning 1260 Row 4 was cut by GROUP_CONCAT() +Warning 1260 Row 4 was cut by group_concat() show warnings; Level Code Message -Warning 1260 Row 4 was cut by GROUP_CONCAT() +Warning 1260 Row 4 was cut by group_concat() set group_concat_max_len = 1024; select group_concat(sum(c)) from t1 group by grp; ERROR HY000: Invalid use of group function @@ -379,29 +379,29 @@ group_concat(b) bb,c BB,C Warnings: -Warning 1260 Row 2 was cut by GROUP_CONCAT() -Warning 1260 Row 4 was cut by GROUP_CONCAT() +Warning 1260 Row 2 was cut by group_concat() +Warning 1260 Row 4 was cut by group_concat() select group_concat(distinct b) from t1 group by a; group_concat(distinct b) a,bb A,BB Warnings: -Warning 1260 Row 3 was cut by GROUP_CONCAT() -Warning 1260 Row 6 was cut by GROUP_CONCAT() +Warning 1260 Row 3 was cut by group_concat() +Warning 1260 Row 6 was cut by group_concat() select group_concat(b order by b) from t1 group by a; group_concat(b order by b) a,bb A,BB Warnings: -Warning 1260 Row 3 was cut by GROUP_CONCAT() -Warning 1260 Row 6 was cut by GROUP_CONCAT() +Warning 1260 Row 3 was cut by group_concat() +Warning 1260 Row 6 was cut by group_concat() select group_concat(distinct b order by b) from t1 group by a; group_concat(distinct b order by b) a,bb A,BB Warnings: -Warning 1260 Row 3 was cut by GROUP_CONCAT() -Warning 1260 Row 6 was cut by GROUP_CONCAT() +Warning 1260 Row 3 was cut by group_concat() +Warning 1260 Row 6 was cut by group_concat() insert into t1 values (1, concat(repeat('1', 300), '2')), (1, concat(repeat('1', 300), '2')), (1, concat(repeat('0', 300), '1')), (2, concat(repeat('1', 300), '2')), (2, concat(repeat('1', 300), '2')), @@ -429,29 +429,29 @@ group_concat(b) bb,ccc,a,bb,ccc,1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111112,1111111111111111111111111111111111111111111111111111111111111111111111111111111111 BB,CCC,A,BB,CCC,1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111112,1111111111111111111111111111111111111111111111111111111111111111111111111111111111 Warnings: -Warning 1260 Row 7 was cut by GROUP_CONCAT() -Warning 1260 Row 14 was cut by GROUP_CONCAT() +Warning 1260 Row 7 was cut by group_concat() +Warning 1260 Row 14 was cut by group_concat() select group_concat(distinct b) from t1 group by a; group_concat(distinct b) 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001,11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001,11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 Warnings: -Warning 1260 Row 2 was cut by GROUP_CONCAT() -Warning 1260 Row 4 was cut by GROUP_CONCAT() +Warning 1260 Row 2 was cut by group_concat() +Warning 1260 Row 4 was cut by group_concat() select group_concat(b order by b) from t1 group by a; group_concat(b order by b) 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001,11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001,11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 Warnings: -Warning 1260 Row 2 was cut by GROUP_CONCAT() -Warning 1260 Row 4 was cut by GROUP_CONCAT() +Warning 1260 Row 2 was cut by group_concat() +Warning 1260 Row 4 was cut by group_concat() select group_concat(distinct b order by b) from t1 group by a; group_concat(distinct b order by b) 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001,11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001,11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 Warnings: -Warning 1260 Row 2 was cut by GROUP_CONCAT() -Warning 1260 Row 4 was cut by GROUP_CONCAT() +Warning 1260 Row 2 was cut by group_concat() +Warning 1260 Row 4 was cut by group_concat() drop table t1; create table t1 (a varchar(255) character set cp1250 collate cp1250_general_ci, b varchar(255) character set koi8r); @@ -758,22 +758,22 @@ SELECT GROUP_CONCAT( a ) FROM t1; GROUP_CONCAT( a ) aaaaaaaaaa,bbbbbbbbb Warnings: -Warning 1260 Row 2 was cut by GROUP_CONCAT() +Warning 1260 Row 2 was cut by group_concat() SELECT GROUP_CONCAT( DISTINCT a ) FROM t1; GROUP_CONCAT( DISTINCT a ) aaaaaaaaaa,bbbbbbbbb Warnings: -Warning 1260 Row 2 was cut by GROUP_CONCAT() +Warning 1260 Row 2 was cut by group_concat() SELECT GROUP_CONCAT( a ORDER BY b ) FROM t1; GROUP_CONCAT( a ORDER BY b ) aaaaaaaaaa,bbbbbbbbb Warnings: -Warning 1260 Row 2 was cut by GROUP_CONCAT() +Warning 1260 Row 2 was cut by group_concat() SELECT GROUP_CONCAT( DISTINCT a ORDER BY b ) FROM t1; GROUP_CONCAT( DISTINCT a ORDER BY b ) aaaaaaaaaa,bbbbbbbbb Warnings: -Warning 1260 Row 2 was cut by GROUP_CONCAT() +Warning 1260 Row 2 was cut by group_concat() SET group_concat_max_len = DEFAULT; DROP TABLE t1; SET group_concat_max_len= 65535; @@ -1073,15 +1073,15 @@ GROUP_CONCAT(a) b 22222 2 33333 3 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 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() INSERT INTO t2 SELECT GROUP_CONCAT(a), b FROM t1 GROUP BY b; -ERROR HY000: Row 1 was cut by GROUP_CONCAT() +ERROR HY000: Row 1 was cut by group_concat() UPDATE t1 SET a = '11111' WHERE b = 1; UPDATE t1 SET a = '22222' WHERE b = 2; INSERT INTO t2 SELECT GROUP_CONCAT(a), b FROM t1 GROUP BY b; -ERROR HY000: Row 3 was cut by GROUP_CONCAT() +ERROR HY000: Row 3 was cut by group_concat() SET group_concat_max_len = DEFAULT; SET @@sql_mode = @old_sql_mode; DROP TABLE t1, t2; @@ -1168,22 +1168,22 @@ SELECT LENGTH(GROUP_CONCAT(f1 ORDER BY f2)) FROM t1; LENGTH(GROUP_CONCAT(f1 ORDER BY f2)) 1024 Warnings: -Warning 1260 Row 2 was cut by GROUP_CONCAT() +Warning 1260 Row 2 was cut by group_concat() SET group_concat_max_len= 499999; SELECT LENGTH(GROUP_CONCAT(f1 ORDER BY f2)) FROM t1 WHERE f2 = 0; LENGTH(GROUP_CONCAT(f1 ORDER BY f2)) 499999 Warnings: -Warning 1260 Row 1 was cut by GROUP_CONCAT() +Warning 1260 Row 1 was cut by group_concat() SELECT LENGTH(GROUP_CONCAT(f1 ORDER BY f2)) FROM t1 GROUP BY f2; LENGTH(GROUP_CONCAT(f1 ORDER BY f2)) 499999 499999 499999 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 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() INSERT INTO t1 VALUES (REPEAT('a', 499999), 3), (REPEAT('b', 500000), 4); SELECT LENGTH(GROUP_CONCAT(f1 ORDER BY f2)) FROM t1 GROUP BY f2; LENGTH(GROUP_CONCAT(f1 ORDER BY f2)) @@ -1193,10 +1193,10 @@ LENGTH(GROUP_CONCAT(f1 ORDER BY f2)) 499999 499999 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 1260 Row 5 was cut by GROUP_CONCAT() +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 1260 Row 5 was cut by group_concat() DROP TABLE t1; SET group_concat_max_len= DEFAULT; set session group_concat_max_len=1024; @@ -1206,7 +1206,7 @@ FROM seq_1_to_200000; c 0.90910.90910.90910.90910.90910.90910.90910.9091,1.81821.81821.81821.81821.81821.81821.81821.8182,10.000010.000010.000010.000010.000010.000010.000010.0000,10.909110.909110.909110.909110.909110.909110.909110.9091,100.0000100.0000100.0000100.0000100.0000100.0000100.0000100.0000,100.9091100.9091100.9091100.9091100.9091100.9091100.9091100.9091,1000.00001000.00001000.00001000.00001000.00001000.00001000.00001000.0000,1000.90911000.90911000.90911000.90911000.90911000.90911000.90911000.9091,10000.000010000.000010000.000010000.000010000.000010000.000010000.000010000.0000,10000.909110000.909110000.909110000.909110000.909110000.909110000.909110000.9091,100000.0000100000.0000100000.0000100000.0000100000.0000100000.0000100000.0000100000.0000,100000.9091100000.9091100000.9091100000.9091100000.9091100000.9091100000.9091100000.9091,100001.8182100001.8182100001.8182100001.8182100001.8182100001.8182100001.8182100001.8182,100002.7273100002.7273100002.7273100002.7273100002.7273100002.7273100002.7273100002.7273,100003.6364100003. Warnings: -Warning 1260 Row 15 was cut by GROUP_CONCAT() +Warning 1260 Row 15 was cut by group_concat() set max_session_mem_used=default; set session group_concat_max_len=default; SET group_concat_max_len= 8; @@ -1225,7 +1225,7 @@ GROUP BY f; f gc 2 2019-12- Warnings: -Warning 1260 Row 1 was cut by GROUP_CONCAT() +Warning 1260 Row 1 was cut by group_concat() DROP TABLE t1, t2, t3, t4; SET group_concat_max_len= default; # diff --git a/mysql-test/main/func_json.result b/mysql-test/main/func_json.result index ccb68431716..c4e66cf5dcb 100644 --- a/mysql-test/main/func_json.result +++ b/mysql-test/main/func_json.result @@ -1599,7 +1599,7 @@ select json_arrayagg(a) from t1; json_arrayagg(a) ["x64-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"] Warnings: -Warning 1260 Row 1 was cut by JSON_ARRAYAGG() +Warning 1260 Row 1 was cut by json_arrayagg() drop table t1; SET group_concat_max_len= default; create table t1 (col1 json); diff --git a/mysql-test/main/join_outer.result b/mysql-test/main/join_outer.result index c4ea5bc4517..03453b0eba8 100644 --- a/mysql-test/main/join_outer.result +++ b/mysql-test/main/join_outer.result @@ -944,29 +944,29 @@ group_concat(t1.b,t2.c) aaaaa bbbbb Warnings: -Warning 1260 Row 1 was cut by GROUP_CONCAT() -Warning 1260 Row 2 was cut by GROUP_CONCAT() +Warning 1260 Row 1 was cut by group_concat() +Warning 1260 Row 2 was cut by group_concat() select group_concat(t1.b,t2.c) from t1 inner join t2 using(a) group by t1.a; group_concat(t1.b,t2.c) aaaaa bbbbb Warnings: -Warning 1260 Row 1 was cut by GROUP_CONCAT() -Warning 1260 Row 2 was cut by GROUP_CONCAT() +Warning 1260 Row 1 was cut by group_concat() +Warning 1260 Row 2 was cut by group_concat() select group_concat(t1.b,t2.c) from t1 left join t2 using(a) group by a; group_concat(t1.b,t2.c) aaaaa bbbbb Warnings: -Warning 1260 Row 1 was cut by GROUP_CONCAT() -Warning 1260 Row 2 was cut by GROUP_CONCAT() +Warning 1260 Row 1 was cut by group_concat() +Warning 1260 Row 2 was cut by group_concat() select group_concat(t1.b,t2.c) from t1 inner join t2 using(a) group by a; group_concat(t1.b,t2.c) aaaaa bbbbb Warnings: -Warning 1260 Row 1 was cut by GROUP_CONCAT() -Warning 1260 Row 2 was cut by GROUP_CONCAT() +Warning 1260 Row 1 was cut by group_concat() +Warning 1260 Row 2 was cut by group_concat() drop table t1, t2; set group_concat_max_len=default; create table t1 (gid smallint(5) unsigned not null, x int(11) not null, y int(11) not null, art int(11) not null, primary key (gid,x,y)); diff --git a/mysql-test/main/join_outer_jcl6.result b/mysql-test/main/join_outer_jcl6.result index bdaab88e01f..58b08196f67 100644 --- a/mysql-test/main/join_outer_jcl6.result +++ b/mysql-test/main/join_outer_jcl6.result @@ -951,29 +951,29 @@ group_concat(t1.b,t2.c) aaaaa bbbbb Warnings: -Warning 1260 Row 1 was cut by GROUP_CONCAT() -Warning 1260 Row 2 was cut by GROUP_CONCAT() +Warning 1260 Row 1 was cut by group_concat() +Warning 1260 Row 2 was cut by group_concat() select group_concat(t1.b,t2.c) from t1 inner join t2 using(a) group by t1.a; group_concat(t1.b,t2.c) aaaaa bbbbb Warnings: -Warning 1260 Row 1 was cut by GROUP_CONCAT() -Warning 1260 Row 2 was cut by GROUP_CONCAT() +Warning 1260 Row 1 was cut by group_concat() +Warning 1260 Row 2 was cut by group_concat() select group_concat(t1.b,t2.c) from t1 left join t2 using(a) group by a; group_concat(t1.b,t2.c) aaaaa bbbbb Warnings: -Warning 1260 Row 1 was cut by GROUP_CONCAT() -Warning 1260 Row 2 was cut by GROUP_CONCAT() +Warning 1260 Row 1 was cut by group_concat() +Warning 1260 Row 2 was cut by group_concat() select group_concat(t1.b,t2.c) from t1 inner join t2 using(a) group by a; group_concat(t1.b,t2.c) aaaaa bbbbb Warnings: -Warning 1260 Row 1 was cut by GROUP_CONCAT() -Warning 1260 Row 2 was cut by GROUP_CONCAT() +Warning 1260 Row 1 was cut by group_concat() +Warning 1260 Row 2 was cut by group_concat() drop table t1, t2; set group_concat_max_len=default; create table t1 (gid smallint(5) unsigned not null, x int(11) not null, y int(11) not null, art int(11) not null, primary key (gid,x,y)); diff --git a/mysql-test/main/query_cache.result b/mysql-test/main/query_cache.result index e73f219e1b0..8c211e1853f 100644 --- a/mysql-test/main/query_cache.result +++ b/mysql-test/main/query_cache.result @@ -864,7 +864,7 @@ select group_concat(a) FROM t1 group by b; group_concat(a) 1234567890 Warnings: -Warning 1260 Row 1 was cut by GROUP_CONCAT() +Warning 1260 Row 1 was cut by group_concat() set group_concat_max_len=1024; select group_concat(a) FROM t1 group by b; group_concat(a) diff --git a/mysql-test/main/subselect_mat.result b/mysql-test/main/subselect_mat.result index e964413d60d..18fc94e1040 100644 --- a/mysql-test/main/subselect_mat.result +++ b/mysql-test/main/subselect_mat.result @@ -795,9 +795,9 @@ from t1_512 where a1 in (select group_concat(b1) from t2_512 group by b2); left(a1,7) left(a2,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 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() set @@group_concat_max_len = 256; explain extended select left(a1,7), left(a2,7) from t1_512 @@ -812,9 +812,9 @@ from t1_512 where a1 in (select group_concat(b1) from t2_512 group by b2); left(a1,7) left(a2,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 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() drop table t1_512, t2_512, t3_512; set @blob_len = 1024; set @suffix_len = @blob_len - @prefix_len; @@ -896,9 +896,9 @@ from t1_1024 where a1 in (select group_concat(b1) from t2_1024 group by b2); left(a1,7) left(a2,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 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() set @@group_concat_max_len = 256; explain extended select left(a1,7), left(a2,7) from t1_1024 @@ -913,9 +913,9 @@ from t1_1024 where a1 in (select group_concat(b1) from t2_1024 group by b2); left(a1,7) left(a2,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 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() drop table t1_1024, t2_1024, t3_1024; set @blob_len = 1025; set @suffix_len = @blob_len - @prefix_len; @@ -997,9 +997,9 @@ from t1_1025 where a1 in (select group_concat(b1) from t2_1025 group by b2); left(a1,7) left(a2,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 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() set @@group_concat_max_len = 256; explain extended select left(a1,7), left(a2,7) from t1_1025 @@ -1014,9 +1014,9 @@ from t1_1025 where a1 in (select group_concat(b1) from t2_1025 group by b2); left(a1,7) left(a2,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 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() 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)); diff --git a/mysql-test/main/subselect_sj_mat.result b/mysql-test/main/subselect_sj_mat.result index e8d42228f67..90b727e52d3 100644 --- a/mysql-test/main/subselect_sj_mat.result +++ b/mysql-test/main/subselect_sj_mat.result @@ -813,9 +813,9 @@ from t1_512 where a1 in (select group_concat(b1) from t2_512 group by b2); left(a1,7) left(a2,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 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() set @@group_concat_max_len = 256; explain extended select left(a1,7), left(a2,7) from t1_512 @@ -831,9 +831,9 @@ from t1_512 where a1 in (select group_concat(b1) from t2_512 group by b2); left(a1,7) left(a2,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 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() drop table t1_512, t2_512, t3_512; set @blob_len = 1024; set @suffix_len = @blob_len - @prefix_len; @@ -916,9 +916,9 @@ from t1_1024 where a1 in (select group_concat(b1) from t2_1024 group by b2); left(a1,7) left(a2,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 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() set @@group_concat_max_len = 256; explain extended select left(a1,7), left(a2,7) from t1_1024 @@ -934,9 +934,9 @@ from t1_1024 where a1 in (select group_concat(b1) from t2_1024 group by b2); left(a1,7) left(a2,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 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() drop table t1_1024, t2_1024, t3_1024; set @blob_len = 1025; set @suffix_len = @blob_len - @prefix_len; @@ -1019,9 +1019,9 @@ from t1_1025 where a1 in (select group_concat(b1) from t2_1025 group by b2); left(a1,7) left(a2,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 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() set @@group_concat_max_len = 256; explain extended select left(a1,7), left(a2,7) from t1_1025 @@ -1037,9 +1037,9 @@ from t1_1025 where a1 in (select group_concat(b1) from t2_1025 group by b2); left(a1,7) left(a2,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 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() 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)); diff --git a/mysql-test/suite/perfschema/r/lowercase_fs_off.result b/mysql-test/suite/perfschema/r/lowercase_fs_off.result new file mode 100644 index 00000000000..03981a86514 --- /dev/null +++ b/mysql-test/suite/perfschema/r/lowercase_fs_off.result @@ -0,0 +1,22 @@ +# +# MDEV-33020 The database part is not case sensitive in SP names in PERFORMANCE_SCHEMA +# +CREATE OR REPLACE DATABASE DB1; +CREATE OR REPLACE DATABASE db1; +CREATE PROCEDURE DB1.sp() SELECT 'This is DB1.sp'; +CREATE PROCEDURE db1.sp() SELECT 'This is db1.sp'; +CALL DB1.sp(); +This is DB1.sp +This is DB1.sp +CREATE PROCEDURE DB1.sp2() SELECT 'This is DB1.sp2'; +CALL db1.sp(); +This is db1.sp +This is db1.sp +SELECT object_type, object_schema, object_name, count_star, count_statements, sum_rows_sent +FROM performance_schema.events_statements_summary_by_program +WHERE object_type='procedure' AND LOWER(object_schema)='db1'; +object_type object_schema object_name count_star count_statements sum_rows_sent +PROCEDURE DB1 sp 1 1 1 +PROCEDURE db1 sp 1 1 1 +DROP DATABASE db1; +DROP DATABASE DB1; diff --git a/mysql-test/suite/perfschema/t/lowercase_fs_off.test b/mysql-test/suite/perfschema/t/lowercase_fs_off.test new file mode 100644 index 00000000000..1132ce274eb --- /dev/null +++ b/mysql-test/suite/perfschema/t/lowercase_fs_off.test @@ -0,0 +1,27 @@ +# +# Specific tests for case sensitive file systems +# i.e. lower_case_filesystem=OFF +# +--source include/have_case_sensitive_file_system.inc +--source include/have_perfschema.inc +--source include/not_embedded.inc + +--echo # +--echo # MDEV-33020 The database part is not case sensitive in SP names in PERFORMANCE_SCHEMA +--echo # + +CREATE OR REPLACE DATABASE DB1; +CREATE OR REPLACE DATABASE db1; +CREATE PROCEDURE DB1.sp() SELECT 'This is DB1.sp'; +CREATE PROCEDURE db1.sp() SELECT 'This is db1.sp'; +CALL DB1.sp(); +# This is needed to reset the SP cache (a MDEV-33019 workaround) +CREATE PROCEDURE DB1.sp2() SELECT 'This is DB1.sp2'; +CALL db1.sp(); + +SELECT object_type, object_schema, object_name, count_star, count_statements, sum_rows_sent +FROM performance_schema.events_statements_summary_by_program +WHERE object_type='procedure' AND LOWER(object_schema)='db1'; + +DROP DATABASE db1; +DROP DATABASE DB1; diff --git a/mysql-test/suite/sys_vars/r/group_concat_max_len_func.result b/mysql-test/suite/sys_vars/r/group_concat_max_len_func.result index 01f44ae51be..fc75d644c21 100644 --- a/mysql-test/suite/sys_vars/r/group_concat_max_len_func.result +++ b/mysql-test/suite/sys_vars/r/group_concat_max_len_func.result @@ -42,10 +42,10 @@ id rollno GROUP_CONCAT(name) 4 3 Reco 7 4 Reco 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 1260 Row 4 was cut by GROUP_CONCAT() +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 1260 Row 4 was cut by group_concat() ## Changing session value of variable and verifying its behavior, ## ## warning should come here ## SET @@session.group_concat_max_len = 10; @@ -56,9 +56,9 @@ id rollno GROUP_CONCAT(name) 4 3 Record_4,R 7 4 Record_7,R Warnings: -Warning 1260 Row 2 was cut by GROUP_CONCAT() -Warning 1260 Row 5 was cut by GROUP_CONCAT() -Warning 1260 Row 7 was cut by GROUP_CONCAT() +Warning 1260 Row 2 was cut by group_concat() +Warning 1260 Row 5 was cut by group_concat() +Warning 1260 Row 7 was cut by group_concat() '#--------------------FN_DYNVARS_034_03-------------------------#' connection test_con2; ## Verifying initial value of variable. It should be 4 ## @@ -77,7 +77,7 @@ id rollno GROUP_CONCAT(name) 4 3 Record_4,Record_6 7 4 Record_7,Record_8 Warnings: -Warning 1260 Row 3 was cut by GROUP_CONCAT() +Warning 1260 Row 3 was cut by group_concat() '#--------------------FN_DYNVARS_034_04-------------------------#' ## Setting session value of variable to 26. No warning should appear here ## ## because the value after concatination is less than 30 ## diff --git a/mysql-test/suite/sysschema/r/fn_ps_thread_trx_info.result b/mysql-test/suite/sysschema/r/fn_ps_thread_trx_info.result index fe11e70203a..7c46c9ba980 100644 --- a/mysql-test/suite/sysschema/r/fn_ps_thread_trx_info.result +++ b/mysql-test/suite/sysschema/r/fn_ps_thread_trx_info.result @@ -83,7 +83,7 @@ JSON_CONTAINS(@json_doc, '"COMMIT"', '$[0].statements_executed[1].sql_text') SET @sys.ps_thread_trx_info.max_length = 100; SELECT sys.ps_thread_trx_info(@ps_thread_id); sys.ps_thread_trx_info(@ps_thread_id) -{ "error": "Trx info truncated: Row 1X was cut by GROUP_CONCAT()" } +{ "error": "Trx info truncated: Row 1X was cut by group_concat()" } SET @sys.ps_thread_trx_info.max_length = NULL; SELECT JSON_VALID(sys.ps_thread_trx_info(@ps_thread_id)); JSON_VALID(sys.ps_thread_trx_info(@ps_thread_id)) diff --git a/plugin/type_inet/mysql-test/type_inet/type_inet4.result b/plugin/type_inet/mysql-test/type_inet/type_inet4.result index a8786e07a76..c44ac7ee34a 100644 --- a/plugin/type_inet/mysql-test/type_inet/type_inet4.result +++ b/plugin/type_inet/mysql-test/type_inet/type_inet4.result @@ -1302,7 +1302,7 @@ EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=COALESCE(CAST('0.0.0.1' AS INET4)) AND id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where Warnings: -Note 1003 select `test`.`t1`.`id` AS `id`,`test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = INET4'0.0.0.1' and `test`.`t1`.`id` > 0 +Note 1003 select `test`.`t1`.`id` AS `id`,`test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = inet4'0.0.0.1' and `test`.`t1`.`id` > 0 DROP TABLE t1; # # Optimizer: equal field propagation @@ -1315,14 +1315,14 @@ AND LENGTH(CONCAT(a,RAND()))>1; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where Warnings: -Note 1003 select `test`.`t1`.`id` AS `id`,`test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = INET4'0.0.0.1' and octet_length(concat(INET4'0.0.0.1',rand())) > 1 +Note 1003 select `test`.`t1`.`id` AS `id`,`test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = inet4'0.0.0.1' and octet_length(concat(inet4'0.0.0.1',rand())) > 1 EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=COALESCE(CAST('0.0.0.1' AS INET4)) AND LENGTH(a)>1; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where Warnings: -Note 1003 select `test`.`t1`.`id` AS `id`,`test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = INET4'0.0.0.1' +Note 1003 select `test`.`t1`.`id` AS `id`,`test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = inet4'0.0.0.1' DROP TABLE t1; # # Optimizer: equal expression propagation diff --git a/plugin/type_inet/mysql-test/type_inet/type_inet4_innodb.result b/plugin/type_inet/mysql-test/type_inet/type_inet4_innodb.result index 536ceda6d18..5f30611632c 100644 --- a/plugin/type_inet/mysql-test/type_inet/type_inet4_innodb.result +++ b/plugin/type_inet/mysql-test/type_inet/type_inet4_innodb.result @@ -85,7 +85,7 @@ EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=CAST('0.0.0.255' AS INET4); id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ref a a 5 const 1 100.00 Using where; Using index Warnings: -Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = INET4'0.0.0.255' +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = inet4'0.0.0.255' DROP TABLE t1; # # MDEV-26742 Assertion `field->type_handler() == this' failed in FixedBinTypeBundle::Type_handler_fbt::stored_field_cmp_to_item diff --git a/plugin/type_inet/mysql-test/type_inet/type_inet4_memory.result b/plugin/type_inet/mysql-test/type_inet/type_inet4_memory.result index d48ab70cce8..3ca636301ea 100644 --- a/plugin/type_inet/mysql-test/type_inet/type_inet4_memory.result +++ b/plugin/type_inet/mysql-test/type_inet/type_inet4_memory.result @@ -152,7 +152,7 @@ EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=CAST('0.0.0.255' AS INET4); id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ref a a 5 const 2 100.00 Using where Warnings: -Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = INET4'0.0.0.255' +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = inet4'0.0.0.255' DROP TABLE t1; # # End of 10.10 tests diff --git a/plugin/type_inet/mysql-test/type_inet/type_inet4_myisam.result b/plugin/type_inet/mysql-test/type_inet/type_inet4_myisam.result index aaf66b34524..5fda6ac04f1 100644 --- a/plugin/type_inet/mysql-test/type_inet/type_inet4_myisam.result +++ b/plugin/type_inet/mysql-test/type_inet/type_inet4_myisam.result @@ -85,7 +85,7 @@ EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=CAST('0.0.0.255' AS INET4); id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ref a a 5 const 1 100.00 Using where; Using index Warnings: -Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = INET4'0.0.0.255' +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = inet4'0.0.0.255' DROP TABLE t1; # # MDEV-26742 Assertion `field->type_handler() == this' failed in FixedBinTypeBundle::Type_handler_fbt::stored_field_cmp_to_item diff --git a/plugin/type_inet/mysql-test/type_inet/type_inet6.result b/plugin/type_inet/mysql-test/type_inet/type_inet6.result index 8322e67a413..16e37e8aa2b 100644 --- a/plugin/type_inet/mysql-test/type_inet/type_inet6.result +++ b/plugin/type_inet/mysql-test/type_inet/type_inet6.result @@ -1295,7 +1295,7 @@ EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=COALESCE(CAST('::1' AS INET6)) AND id> id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where Warnings: -Note 1003 select `test`.`t1`.`id` AS `id`,`test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = INET6'::1' and `test`.`t1`.`id` > 0 +Note 1003 select `test`.`t1`.`id` AS `id`,`test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = inet6'::1' and `test`.`t1`.`id` > 0 DROP TABLE t1; # # Optimizer: equal field propagation @@ -1308,14 +1308,14 @@ AND LENGTH(CONCAT(a,RAND()))>1; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where Warnings: -Note 1003 select `test`.`t1`.`id` AS `id`,`test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = INET6'::1' and octet_length(concat(INET6'::1',rand())) > 1 +Note 1003 select `test`.`t1`.`id` AS `id`,`test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = inet6'::1' and octet_length(concat(inet6'::1',rand())) > 1 EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=COALESCE(CAST('::1' AS INET6)) AND LENGTH(a)>1; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where Warnings: -Note 1003 select `test`.`t1`.`id` AS `id`,`test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = INET6'::1' +Note 1003 select `test`.`t1`.`id` AS `id`,`test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = inet6'::1' DROP TABLE t1; # # Optimizer: equal expression propagation diff --git a/plugin/type_inet/mysql-test/type_inet/type_inet6_innodb.result b/plugin/type_inet/mysql-test/type_inet/type_inet6_innodb.result index deb1c718b49..abb92582189 100644 --- a/plugin/type_inet/mysql-test/type_inet/type_inet6_innodb.result +++ b/plugin/type_inet/mysql-test/type_inet/type_inet6_innodb.result @@ -85,7 +85,7 @@ EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=CAST('::ff' AS INET6); id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ref a a 17 const 1 100.00 Using where; Using index Warnings: -Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = INET6'::ff' +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = inet6'::ff' DROP TABLE t1; # # MDEV-26742 Assertion `field->type_handler() == this' failed in FixedBinTypeBundle::Type_handler_fbt::stored_field_cmp_to_item diff --git a/plugin/type_inet/mysql-test/type_inet/type_inet6_memory.result b/plugin/type_inet/mysql-test/type_inet/type_inet6_memory.result index e805b167136..c1c2c5c9bfa 100644 --- a/plugin/type_inet/mysql-test/type_inet/type_inet6_memory.result +++ b/plugin/type_inet/mysql-test/type_inet/type_inet6_memory.result @@ -152,7 +152,7 @@ EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=CAST('::ff' AS INET6); id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ref a a 17 const 2 100.00 Using where Warnings: -Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = INET6'::ff' +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = inet6'::ff' DROP TABLE t1; # # End of 10.5 tests diff --git a/plugin/type_inet/mysql-test/type_inet/type_inet6_myisam.result b/plugin/type_inet/mysql-test/type_inet/type_inet6_myisam.result index 0f20e16db9c..531d9456fe2 100644 --- a/plugin/type_inet/mysql-test/type_inet/type_inet6_myisam.result +++ b/plugin/type_inet/mysql-test/type_inet/type_inet6_myisam.result @@ -85,7 +85,7 @@ EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=CAST('::ff' AS INET6); id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ref a a 17 const 1 100.00 Using where; Using index Warnings: -Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = INET6'::ff' +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = inet6'::ff' DROP TABLE t1; # # MDEV-26742 Assertion `field->type_handler() == this' failed in FixedBinTypeBundle::Type_handler_fbt::stored_field_cmp_to_item diff --git a/plugin/type_uuid/mysql-test/type_uuid/type_uuid.result b/plugin/type_uuid/mysql-test/type_uuid/type_uuid.result index d8603f56105..7fb9d912c10 100644 --- a/plugin/type_uuid/mysql-test/type_uuid/type_uuid.result +++ b/plugin/type_uuid/mysql-test/type_uuid/type_uuid.result @@ -2477,7 +2477,7 @@ EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=COALESCE(CAST('00000000-0000-0000-0000 id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where Warnings: -Note 1003 select `test`.`t1`.`id` AS `id`,`test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = UUID'00000000-0000-0000-0000-000000000001' and `test`.`t1`.`id` > 0 +Note 1003 select `test`.`t1`.`id` AS `id`,`test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = uuid'00000000-0000-0000-0000-000000000001' and `test`.`t1`.`id` > 0 DROP TABLE t1; # # Optimizer: equal field propagation @@ -2492,14 +2492,14 @@ AND LENGTH(CONCAT(a,RAND()))>1; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where Warnings: -Note 1003 select `test`.`t1`.`id` AS `id`,`test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = UUID'00000000-0000-0000-0000-000000000001' and octet_length(concat(UUID'00000000-0000-0000-0000-000000000001',rand())) > 1 +Note 1003 select `test`.`t1`.`id` AS `id`,`test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = uuid'00000000-0000-0000-0000-000000000001' and octet_length(concat(uuid'00000000-0000-0000-0000-000000000001',rand())) > 1 EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=COALESCE(CAST('00000000-0000-0000-0000-000000000001' AS UUID)) AND LENGTH(a)>1; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where Warnings: -Note 1003 select `test`.`t1`.`id` AS `id`,`test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = UUID'00000000-0000-0000-0000-000000000001' +Note 1003 select `test`.`t1`.`id` AS `id`,`test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = uuid'00000000-0000-0000-0000-000000000001' DROP TABLE t1; # # Optimizer: equal expression propagation diff --git a/plugin/type_uuid/mysql-test/type_uuid/type_uuid_innodb.result b/plugin/type_uuid/mysql-test/type_uuid/type_uuid_innodb.result index 37710ab1008..92af0dfe7d1 100644 --- a/plugin/type_uuid/mysql-test/type_uuid/type_uuid_innodb.result +++ b/plugin/type_uuid/mysql-test/type_uuid/type_uuid_innodb.result @@ -113,7 +113,7 @@ EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=CAST('00000000-0000-0000-0000-00000000 id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ref a a 17 const 1 100.00 Using where; Using index Warnings: -Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = UUID'00000000-0000-0000-0000-0000000000ff' +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = uuid'00000000-0000-0000-0000-0000000000ff' DROP TABLE t1; CREATE OR REPLACE TABLE t1 (a UUID,KEY(a)); SHOW CREATE TABLE t1; diff --git a/plugin/type_uuid/mysql-test/type_uuid/type_uuid_memory.result b/plugin/type_uuid/mysql-test/type_uuid/type_uuid_memory.result index 21086fef2cb..43a4e58881c 100644 --- a/plugin/type_uuid/mysql-test/type_uuid/type_uuid_memory.result +++ b/plugin/type_uuid/mysql-test/type_uuid/type_uuid_memory.result @@ -180,7 +180,7 @@ EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=CAST('00000000-0000-0000-0000-00000000 id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ref a a 17 const 2 100.00 Using where Warnings: -Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = UUID'00000000-0000-0000-0000-0000000000ff' +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = uuid'00000000-0000-0000-0000-0000000000ff' DROP TABLE t1; CREATE OR REPLACE TABLE t1 (a UUID,KEY(a)); SHOW CREATE TABLE t1; diff --git a/plugin/type_uuid/mysql-test/type_uuid/type_uuid_myisam.result b/plugin/type_uuid/mysql-test/type_uuid/type_uuid_myisam.result index 736aea4555f..7b41e99b8b4 100644 --- a/plugin/type_uuid/mysql-test/type_uuid/type_uuid_myisam.result +++ b/plugin/type_uuid/mysql-test/type_uuid/type_uuid_myisam.result @@ -113,7 +113,7 @@ EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=CAST('00000000-0000-0000-0000-00000000 id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ref a a 17 const 7 100.00 Using where; Using index Warnings: -Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = UUID'00000000-0000-0000-0000-0000000000ff' +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = uuid'00000000-0000-0000-0000-0000000000ff' DROP TABLE t1; CREATE OR REPLACE TABLE t1 (a UUID,KEY(a)); SHOW CREATE TABLE t1; diff --git a/sql/char_buffer.h b/sql/char_buffer.h index 7b855f5401c..de8c368bf12 100644 --- a/sql/char_buffer.h +++ b/sql/char_buffer.h @@ -46,12 +46,17 @@ public: { return buff_sz; // The maximum data size, without the trailing '\0' byte. } + size_t available_size() const + { + DBUG_ASSERT(is_sane()); + return buff_sz - m_length; + } CharBuffer() :m_length(0) { m_buff[0]= '\0'; } - CharBuffer & copy_bin(const LEX_CSTRING &str) + CharBuffer & copy(const LEX_CSTRING &str) { DBUG_ASSERT(!buffer_overlaps(str)); m_length= MY_MIN(buff_sz, str.length); @@ -71,25 +76,92 @@ public: m_buff[m_length]= '\0'; return *this; } + CharBuffer & copy_caseup(CHARSET_INFO *cs, const LEX_CSTRING &str) + { + DBUG_ASSERT(!buffer_overlaps(str)); + m_length= cs->cset->caseup(cs, str.str, str.length, m_buff, buff_sz); + DBUG_ASSERT(is_sane()); + m_buff[m_length]= '\0'; // See comments in copy_casedn() + return *this; + } CharBuffer & copy_casedn(CHARSET_INFO *cs, const LEX_CSTRING &str, bool casedn) { - casedn ? copy_casedn(cs, str) : copy_bin(str); + casedn ? copy_casedn(cs, str) : copy(str); return *this; } + + // Append one character + CharBuffer & append_char(char ch) + { + DBUG_ASSERT(is_sane()); + if (available_size()) + { + m_buff[m_length++]= ch; + m_buff[m_length]= '\0'; + } + DBUG_ASSERT(is_sane()); + return *this; + } + + // Append a string + CharBuffer & append(const LEX_CSTRING &str) + { + DBUG_ASSERT(is_sane()); + DBUG_ASSERT(!buffer_overlaps(str)); + size_t len= MY_MIN(available_size(), str.length); + memcpy(m_buff + m_length, str.str, len); + m_length+= len; + DBUG_ASSERT(is_sane()); + m_buff[m_length]= '\0'; + return *this; + } + // Append a string with casedn conversion CharBuffer & append_casedn(CHARSET_INFO *cs, const LEX_CSTRING &str) { DBUG_ASSERT(is_sane()); DBUG_ASSERT(!buffer_overlaps(str)); size_t casedn_length= cs->casedn(str.str, str.length, - m_buff + m_length, buff_sz - m_length); + m_buff + m_length, available_size()); m_length+= casedn_length; DBUG_ASSERT(is_sane()); m_buff[m_length]= '\0'; return *this; } + CharBuffer & append_opt_casedn(CHARSET_INFO *cs, + const LEX_CSTRING &str, + bool casedn) + { + return casedn ? append_casedn(cs, str) : append(str); + } + + // Append a string with caseup conversion + CharBuffer & append_caseup(CHARSET_INFO *cs, const LEX_CSTRING &str) + { + DBUG_ASSERT(is_sane()); + DBUG_ASSERT(!buffer_overlaps(str)); + size_t casedn_length= cs->caseup(str.str, str.length, + m_buff + m_length, available_size()); + m_length+= casedn_length; + DBUG_ASSERT(is_sane()); + m_buff[m_length]= '\0'; + return *this; + } + + CharBuffer & truncate(size_t length) + { + DBUG_ASSERT(is_sane()); + if (m_length > length) + { + m_length= length; + m_buff[m_length]= '\0'; + DBUG_ASSERT(is_sane()); + } + return *this; + } + LEX_CSTRING to_lex_cstring() const { return LEX_CSTRING{m_buff, m_length}; @@ -97,6 +169,7 @@ public: const char *ptr() const { return m_buff; } size_t length() const { return m_length; } + const char *end() const { return m_buff + m_length; } }; diff --git a/sql/handler.h b/sql/handler.h index f7fade0c5bd..00419f4dc39 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -3146,7 +3146,7 @@ public: const Lex_cstring &db_and_table) { DBUG_ASSERT(homedir.length + db_and_table.length <= max_data_size()); - copy_bin(homedir); + copy(homedir); append_casedn(db_and_table_charset, db_and_table); return *this; } diff --git a/sql/item_create.cc b/sql/item_create.cc index 1db89b24847..bc4fa3816de 100644 --- a/sql/item_create.cc +++ b/sql/item_create.cc @@ -68,8 +68,8 @@ class Create_sp_func : public Create_qfunc { public: virtual Item *create_with_db(THD *thd, - const LEX_CSTRING *db, - const LEX_CSTRING *name, + const Lex_ident_db_normalized &db, + const LEX_CSTRING &name, bool use_explicit_name, List *item_list); static Create_sp_func s_singleton; @@ -2828,8 +2828,6 @@ Item* Create_qfunc::create_func(THD *thd, const LEX_CSTRING *name, List *item_list) { - LEX_CSTRING db; - if (unlikely(! thd->db.str && ! thd->lex->sphead)) { /* @@ -2848,10 +2846,11 @@ Create_qfunc::create_func(THD *thd, const LEX_CSTRING *name, return NULL; } - if (thd->lex->copy_db_to(&db)) - return NULL; + Lex_ident_db_normalized db= thd->lex->copy_db_normalized(); + if (!db.str) + return NULL; /*No db or EOM, error was already sent */ - return create_with_db(thd, &db, name, false, item_list); + return create_with_db(thd, db, *name, false, item_list); } @@ -2971,8 +2970,8 @@ Create_sp_func Create_sp_func::s_singleton; Item* Create_sp_func::create_with_db(THD *thd, - const LEX_CSTRING *db, - const LEX_CSTRING *name, + const Lex_ident_db_normalized &db, + const LEX_CSTRING &name, bool use_explicit_name, List *item_list) { int arg_count= 0; @@ -2993,7 +2992,7 @@ Create_sp_func::create_with_db(THD *thd, because it can refer to a User Defined Function call. For a Stored Function however, this has no semantic. */ - my_error(ER_WRONG_PARAMETERS_TO_STORED_FCT, MYF(0), name->str); + my_error(ER_WRONG_PARAMETERS_TO_STORED_FCT, MYF(0), name.str); return NULL; } diff --git a/sql/item_create.h b/sql/item_create.h index ea32d6616f2..71ee0bc186d 100644 --- a/sql/item_create.h +++ b/sql/item_create.h @@ -239,8 +239,8 @@ public: @return An item representing the parsed function call */ virtual Item *create_with_db(THD *thd, - const LEX_CSTRING *db, - const LEX_CSTRING *name, + const Lex_ident_db_normalized &db, + const LEX_CSTRING &name, bool use_explicit_name, List *item_list) = 0; diff --git a/sql/item_sum.cc b/sql/item_sum.cc index bcaf229dd15..64ccf8440cd 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -3776,18 +3776,10 @@ int group_concat_key_cmp_with_order_with_nulls(void *arg, const void *key1_arg, static void report_cut_value_error(THD *thd, uint row_count, const char *fname) { - size_t fn_len= strlen(fname); - char *fname_upper= (char *) my_alloca(fn_len + 1); - if (!fname_upper) - fname_upper= (char*) fname; // Out of memory - else - memcpy(fname_upper, fname, fn_len+1); - my_caseup_str(&my_charset_latin1, fname_upper); push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, ER_CUT_VALUE_GROUP_CONCAT, ER_THD(thd, ER_CUT_VALUE_GROUP_CONCAT), - row_count, fname_upper); - my_afree(fname_upper); + row_count, fname); } diff --git a/sql/lex_ident.h b/sql/lex_ident.h index f39273b7da5..4486cd63ec0 100644 --- a/sql/lex_ident.h +++ b/sql/lex_ident.h @@ -19,6 +19,7 @@ */ #include "char_buffer.h" +#include "lex_string.h" /* @@ -45,6 +46,10 @@ public: bool is_in_lower_case() const; bool ok_for_lower_case_names() const; #endif + bool check_db_name_quick() const + { + return !length || length > NAME_LEN || str[length-1] == ' '; + } }; @@ -56,6 +61,10 @@ public: */ class Lex_ident_db: public Lex_ident_fs { + bool is_null() const + { + return length == 0 && str == NULL; + } // {empty_c_string,0} is used by derived tables bool is_empty() const { @@ -68,7 +77,7 @@ public: Lex_ident_db(const char *str, size_t length) :Lex_ident_fs(str, length) { - DBUG_SLOW_ASSERT(is_empty() || !check_db_name()); + DBUG_SLOW_ASSERT(is_null() || is_empty() || !check_db_name()); } }; @@ -81,6 +90,8 @@ public: class Lex_ident_db_normalized: public Lex_ident_db { public: + Lex_ident_db_normalized() + { } Lex_ident_db_normalized(const char *str, size_t length) :Lex_ident_db(str, length) { @@ -160,4 +171,172 @@ public: }; +class Identifier_chain2 +{ + LEX_CSTRING m_name[2]; +public: + Identifier_chain2() + :m_name{Lex_cstring(), Lex_cstring()} + { } + Identifier_chain2(const LEX_CSTRING &a, const LEX_CSTRING &b) + :m_name{a, b} + { } + + const LEX_CSTRING& operator [] (size_t i) const + { + return m_name[i]; + } + + static Identifier_chain2 split(const LEX_CSTRING &txt) + { + DBUG_ASSERT(txt.str[txt.length] == '\0'); // Expect 0-terminated input + const char *dot= strchr(txt.str, '.'); + if (!dot) + return Identifier_chain2(Lex_cstring(), txt); + size_t length0= dot - txt.str; + Lex_cstring name0(txt.str, length0); + Lex_cstring name1(txt.str + length0 + 1, txt.length - length0 - 1); + return Identifier_chain2(name0, name1); + } + + // The minimum possible buffer size for the make_sep_name*() functions + static constexpr size_t min_sep_name_size() + { + /* + The minimal possible buffer is 4 bytes: 'd/t\0' + where 'd' is the database name, 't' is the table name. + Callers should never pass a smaller buffer. + */ + return 4; + } + + // Export as a qualified name string: 'db.name' + size_t make_sep_name(char *dst, size_t dstlen, int sep) const + { + DBUG_ASSERT(dstlen >= min_sep_name_size()); + return my_snprintf(dst, dstlen, "%.*s%c%.*s", + (int) m_name[0].length, m_name[0].str, sep, + (int) m_name[1].length, m_name[1].str); + } + + // Export as a qualified name string 'db.name', lower-casing 'db' and 'name' + size_t make_sep_name_casedn(char *dst, size_t dst_size, int sep) const + { + DBUG_ASSERT(dst_size >= min_sep_name_size()); + CHARSET_INFO *cs= &my_charset_utf8mb3_general_ci; + char *ptr= dst, *end= dst + dst_size; + ptr+= cs->casedn(m_name[0].str, m_name[0].length, ptr, end - ptr - 2); + *ptr++= (char) sep; + ptr+= cs->casedn_z(m_name[1].str, m_name[1].length, ptr, end - ptr); + return ptr - dst; + } + + // Export as a qualified name, optionally lower-casing only the 'name' part + size_t make_sep_name_casedn_part1(char *dst, size_t dst_size, int sep) const + { + DBUG_ASSERT(dst_size >= min_sep_name_size()); + CHARSET_INFO *cs= &my_charset_utf8mb3_general_ci; + char *ptr= dst, *end= dst + dst_size; + ptr+= cs->opt_casedn(m_name[0].str, m_name[0].length, + ptr, end - ptr - 2, false); + *ptr++= (char) sep; + ptr+= cs->casedn_z(m_name[1].str, m_name[1].length, ptr, end - ptr); + return ptr - dst; + } + + /* + Export as a qualified name, e.g. 'db.name', 0-terminated, + optionally lower-casing both 'db' and 'name' parts. + + @param [OUT] dst - the destination + @param dst_size - number of bytes available in dst + @param sep - the separator character + @param casedn - whether to convert components to lower case + @return - number of bytes written to "dst", not counting + the trailing '\0' byte. + */ + size_t make_sep_name_opt_casedn(char *dst, size_t dst_size, + int sep, bool casedn) const + { + DBUG_ASSERT(m_name[0].length + m_name[1].length + 2 < FN_REFLEN - 1); + return casedn ? make_sep_name_casedn(dst, dst_size, sep) : + make_sep_name(dst, dst_size, sep); + } + + /* + Export as a qualified name string 'db.name', + using the dot character as a separator, + optionally cover-casing the 'name' part. + */ + size_t make_sep_name_opt_casedn_part1(char *dst, size_t dst_size, + int sep, + bool casedn_part1) const + { + return casedn_part1 ? make_sep_name_casedn_part1(dst, dst_size, sep) : + make_sep_name(dst, dst_size, sep); + } + + /* + Export as a qualified name string, allocated on mem_root, + using the dot character as a separator, + optionally lower-casing the 'name' part. + */ + LEX_CSTRING make_sep_name_opt_casedn_part1(MEM_ROOT *mem_root, + int sep, + bool casedn_part1) const + { + LEX_STRING dst; + /* format: [pkg + dot] + name + '\0' */ + size_t dst_size= m_name[0].length + 1 /*dot*/ + m_name[1].length + 1/*\0*/; + if (unlikely(!(dst.str= (char*) alloc_root(mem_root, dst_size)))) + return {NULL, 0}; + if (!m_name[0].length) + { + DBUG_ASSERT(!casedn_part1); // Should not be called this way + dst.length= my_snprintf(dst.str, dst_size, "%.*s", + (int) m_name[1].length, m_name[1].str); + return {dst.str, dst.length}; + } + dst.length= make_sep_name_opt_casedn_part1(dst.str, dst_size, + sep, casedn_part1); + return {dst.str, dst.length}; + } + + /* + Export as a qualified name string 'db.name', + using the dot character as a separator, + lower-casing the 'name' part. + */ + size_t make_qname_casedn_part1(char *dst, size_t dst_size) const + { + return make_sep_name_casedn_part1(dst, dst_size, '.'); + } + + // Export as a qualified name string: 'db.name' using the dot character. + size_t make_qname(char *dst, size_t dstlen) const + { + return make_sep_name(dst, dstlen, '.'); + } + + /* + Export as a qualified name string 'db.name', allocated on mem_root, + using the dot character as a separator. + */ + LEX_CSTRING make_qname(MEM_ROOT *mem_root) const + { + return make_sep_name_opt_casedn_part1(mem_root, '.', false); + } + + /* + Export as a qualified name string 'db.name', allocated on mem_root, + using the dot character as a separator, + lower-casing the 'name' part. + */ + LEX_CSTRING make_qname_casedn_part1(MEM_ROOT *mem_root) const + { + return make_sep_name_opt_casedn_part1(mem_root, '.', true); + } +}; + + #endif // LEX_IDENT_INCLUDED diff --git a/sql/log_event_server.cc b/sql/log_event_server.cc index 169f78b5c00..8ad49247423 100644 --- a/sql/log_event_server.cc +++ b/sql/log_event_server.cc @@ -5800,6 +5800,12 @@ int Table_map_log_event::do_apply_event(rpl_group_info *rgi) RPL_TABLE_LIST *table_list; char *db_mem, *tname_mem, *ptr; size_t dummy_len, db_mem_length, tname_mem_length; + /* + The database name can be changed to a longer name after get_rewrite_db(). + Allocate the maximum possible size. + */ + const size_t db_mem_alloced= NAME_LEN + 1; + const size_t tname_mem_alloced= NAME_LEN + 1; void *memory; Rpl_filter *filter; Relay_log_info const *rli= rgi->rli; @@ -5810,17 +5816,23 @@ int Table_map_log_event::do_apply_event(rpl_group_info *rgi) if (!(memory= my_multi_malloc(PSI_INSTRUMENT_ME, MYF(MY_WME), &table_list, (uint) sizeof(RPL_TABLE_LIST), - &db_mem, (uint) NAME_LEN + 1, - &tname_mem, (uint) NAME_LEN + 1, + &db_mem, (uint) db_mem_alloced, + &tname_mem, (uint) tname_mem_alloced, NullS))) DBUG_RETURN(HA_ERR_OUT_OF_MEM); - db_mem_length= strmov(db_mem, m_dbnam) - db_mem; - tname_mem_length= strmov(tname_mem, m_tblnam) - tname_mem; if (lower_case_table_names) { - my_casedn_str(files_charset_info, (char*)tname_mem); - my_casedn_str(files_charset_info, (char*)db_mem); + db_mem_length= files_charset_info->casedn_z(m_dbnam, m_dblen, + db_mem, db_mem_alloced); + tname_mem_length= files_charset_info->casedn_z(m_tblnam, m_tbllen, + tname_mem, + tname_mem_alloced); + } + else + { + db_mem_length= strmov(db_mem, m_dbnam) - db_mem; + tname_mem_length= strmov(tname_mem, m_tblnam) - tname_mem; } /* call from mysql_client_binlog_statement() will not set rli->mi */ diff --git a/sql/mysqld.h b/sql/mysqld.h index 4548a247ac1..385e56b0d93 100644 --- a/sql/mysqld.h +++ b/sql/mysqld.h @@ -967,12 +967,6 @@ extern "C" void unireg_clear(int exit_code); #define unireg_abort(exit_code) do { unireg_clear(exit_code); DBUG_RETURN(exit_code); } while(0) #endif -inline void table_case_convert(char * name, uint length) -{ - if (lower_case_table_names) - files_charset_info->casedn(name, length, name, length); -} - extern void set_server_version(char *buf, size_t size); #define current_thd _current_thd() diff --git a/sql/rpl_mi.cc b/sql/rpl_mi.cc index 89a35129a2d..66983c88a1c 100644 --- a/sql/rpl_mi.cc +++ b/sql/rpl_mi.cc @@ -56,16 +56,22 @@ Master_info::Master_info(LEX_CSTRING *connection_name_arg, Store connection name and lower case connection name It's safe to ignore any OMM errors as this is checked by error() */ - connection_name.length= cmp_connection_name.length= - connection_name_arg->length; + connection_name.length= connection_name_arg->length; + size_t cmp_connection_name_nbytes= connection_name_arg->length * + system_charset_info->casedn_multiply() + + 1; if ((connection_name.str= tmp= (char*) - my_malloc(PSI_INSTRUMENT_ME, connection_name_arg->length*2+2, MYF(MY_WME)))) + my_malloc(PSI_INSTRUMENT_ME, connection_name_arg->length + 1 + + cmp_connection_name_nbytes, + MYF(MY_WME)))) { strmake(tmp, connection_name_arg->str, connection_name.length); tmp+= connection_name_arg->length+1; cmp_connection_name.str= tmp; - memcpy(tmp, connection_name_arg->str, connection_name.length+1); - my_casedn_str(system_charset_info, tmp); + cmp_connection_name.length= + system_charset_info->casedn_z(connection_name_arg->str, + connection_name_arg->length, + tmp, cmp_connection_name_nbytes); } /* When MySQL restarted, all Rpl_filter settings which aren't in the my.cnf diff --git a/sql/rpl_rli.cc b/sql/rpl_rli.cc index 9adf75228de..f433fb514d7 100644 --- a/sql/rpl_rli.cc +++ b/sql/rpl_rli.cc @@ -1802,9 +1802,8 @@ gtid_pos_auto_create_tables(rpl_slave_state::gtid_pos_table **list_ptr) ++auto_engines) { void *hton= plugin_hton(*auto_engines); - char buf[FN_REFLEN+1]; + CharBuffer buf; LEX_CSTRING table_name; - char *p; rpl_slave_state::gtid_pos_table *entry, **next_ptr; /* See if this engine is already in the list. */ @@ -1821,13 +1820,12 @@ gtid_pos_auto_create_tables(rpl_slave_state::gtid_pos_table **list_ptr) continue; /* Add an auto-create entry for this engine at end of list. */ - p= strmake(buf, rpl_gtid_slave_state_table_name.str, FN_REFLEN); - p= strmake(p, "_", FN_REFLEN - (p - buf)); - p= strmake(p, plugin_name(*auto_engines)->str, FN_REFLEN - (p - buf)); - table_name.str= buf; - table_name.length= p - buf; - table_case_convert(const_cast(table_name.str), - static_cast(table_name.length)); + buf.append_opt_casedn(files_charset_info, rpl_gtid_slave_state_table_name, + lower_case_table_names) + .append({STRING_WITH_LEN("_")}) + .append_opt_casedn(files_charset_info, *plugin_name(*auto_engines), + lower_case_table_names); + table_name= buf.to_lex_cstring(); entry= rpl_global_gtid_slave_state->alloc_gtid_pos_table (&table_name, hton, rpl_slave_state::GTID_POS_AUTO_CREATE); if (!entry) diff --git a/sql/set_var.cc b/sql/set_var.cc index 61528b45de6..da638e1b5cb 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -1075,7 +1075,6 @@ static void store_var(Field *field, sys_var *var, enum_var_type scope, int fill_sysvars(THD *thd, TABLE_LIST *tables, COND *cond) { - char name_buffer[NAME_CHAR_LEN]; bool res= 1; CHARSET_INFO *scs= system_charset_info; StringBuffer strbuf(scs); @@ -1091,15 +1090,14 @@ int fill_sysvars(THD *thd, TABLE_LIST *tables, COND *cond) for (uint i= 0; i < system_variable_hash.records; i++) { sys_var *var= (sys_var*) my_hash_element(&system_variable_hash, i); - - strmake_buf(name_buffer, var->name.str); - my_caseup_str(system_charset_info, name_buffer); + CharBuffer name_buffer; + name_buffer.copy_caseup(scs, var->name); /* this must be done before evaluating cond */ restore_record(tables->table, s->default_values); - fields[0]->store(name_buffer, strlen(name_buffer), scs); + fields[0]->store(name_buffer.to_lex_cstring(), scs); - if ((wild && wild_case_compare(system_charset_info, name_buffer, wild)) + if ((wild && wild_case_compare(scs, name_buffer.ptr(), wild)) || (cond && !cond->val_int())) continue; diff --git a/sql/sp.cc b/sql/sp.cc index ddaeeb8cb7a..95de3ef04cf 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -2281,12 +2281,20 @@ Sp_handler::sp_exist_routines(THD *thd, TABLE_LIST *routines) const for (routine= routines; routine; routine= routine->next_global) { sp_name *name; - LEX_CSTRING lex_db; - LEX_CSTRING lex_name; - thd->make_lex_string(&lex_db, routine->db.str, routine->db.length); - thd->make_lex_string(&lex_name, routine->table_name.str, - routine->table_name.length); - name= new sp_name(&lex_db, &lex_name, true); + LEX_CSTRING lex_db= thd->make_ident_opt_casedn(routine->db, + lower_case_table_names); + if (!lex_db.str) + DBUG_RETURN(TRUE); // EOM, error was already sent + LEX_CSTRING lex_name= thd->strmake_lex_cstring(routine->table_name); + if (!lex_name.str) + DBUG_RETURN(TRUE); // EOM, error was already sent + /* + routine->db was earlier tested with check_db_name(). + Now it's lower-cased according to lower_case_table_names. + It's safe to make a Lex_ident_db_normalized. + */ + name= new (thd->mem_root) sp_name(Lex_ident_db_normalized(lex_db), + lex_name, true); sp_object_found= sp_find_routine(thd, name, false) != NULL; thd->get_stmt_da()->clear_warning_info(thd->query_id); if (! sp_object_found) @@ -2915,7 +2923,16 @@ Sp_handler::sp_cache_package_routine(THD *thd, { DBUG_ENTER("sp_cache_package_routine"); DBUG_ASSERT(type() == SP_TYPE_FUNCTION || type() == SP_TYPE_PROCEDURE); - sp_name pkgname(&name->m_db, &pkgname_cstr, false); + LEX_CSTRING db= lower_case_table_names ? thd->make_ident_casedn(name->m_db) : + name->m_db; + if (!db.str) + DBUG_RETURN(true); // EOM, error was already sent + /* + name->m_db was earlier tested with check_db_name(). + Now it's lower-cased according to lower_case_table_names. + It's safe to make a Lex_ident_db_normalized. + */ + sp_name pkgname(Lex_ident_db_normalized(db), pkgname_cstr, false); sp_head *ph= NULL; int ret= sp_handler_package_body.sp_cache_routine(thd, &pkgname, lookup_only, @@ -3079,7 +3096,21 @@ Sp_handler::sp_load_for_information_schema(THD *thd, TABLE *proc_table, const AUTHID definer= {{STRING_WITH_LEN("")}, {STRING_WITH_LEN("")}}; sp_head *sp; sp_cache **spc= get_cache(thd); - sp_name sp_name_obj(&db, &name, true); // This can change "name" + DBUG_ASSERT(db.str); + LEX_CSTRING dbn= lower_case_table_names ? thd->make_ident_casedn(db) : db; + if (!dbn.str) + return 0; // EOM, error was already sent + if (Lex_ident_fs(dbn).check_db_name()) + { + my_error(ER_SP_WRONG_NAME, MYF(0), dbn.str); + return 0; + } + /* + db was earlier tested with check_db_name(). + Now it's lower-cased according to lower_case_table_names. + It's safe make a Lex_ident_db_normalized. + */ + sp_name sp_name_obj(Lex_ident_db_normalized(dbn), name, true); *free_sp_head= 0; sp= sp_cache_lookup(spc, &sp_name_obj); diff --git a/sql/sp_cache.cc b/sql/sp_cache.cc index d005f6adb89..2f635ab2034 100644 --- a/sql/sp_cache.cc +++ b/sql/sp_cache.cc @@ -195,7 +195,8 @@ sp_head *sp_cache_lookup(sp_cache **cp, const Database_qualified_name *name) sp_cache *c= *cp; if (! c) return NULL; - return c->lookup(buf, name->make_qname(buf, sizeof(buf), true)); + return c->lookup(buf, name->to_identifier_chain2(). + make_qname_casedn_part1(buf, sizeof(buf))); } diff --git a/sql/sp_head.h b/sql/sp_head.h index d115ae60159..6a07e22401b 100644 --- a/sql/sp_head.h +++ b/sql/sp_head.h @@ -113,12 +113,16 @@ class sp_name : public Sql_alloc, public: bool m_explicit_name; /**< Prepend the db name? */ - sp_name(const LEX_CSTRING *db, const LEX_CSTRING *name, + sp_name(const Lex_ident_db_normalized &db, const LEX_CSTRING &name, bool use_explicit_name) : Database_qualified_name(db, name), m_explicit_name(use_explicit_name) { - if (lower_case_table_names && m_db.length) - m_db.length= my_casedn_str(files_charset_info, (char*) m_db.str); + /* + "db" can be {NULL,0} in case of a "DROP FUNCTION udf" statement. + Otherwise, a valid normalized non-NULL database name is expected. + */ + DBUG_ASSERT((!db.str && !db.length) || + !Lex_ident_fs(db).check_db_name_quick()); } /** Create temporary sp_name object from MDL key. Store in qname_buff */ diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 846b6dd27cf..14450a5a610 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -627,8 +627,6 @@ bool ROLE_GRANT_PAIR::init(MEM_ROOT *mem, const char *username, } #define IP_ADDR_STRLEN (3 + 1 + 3 + 1 + 3 + 1 + 3) -#define ACL_KEY_LENGTH (IP_ADDR_STRLEN + 1 + NAME_LEN + \ - 1 + USERNAME_LENGTH + 1) #if defined(HAVE_OPENSSL) /* @@ -2548,6 +2546,37 @@ static void push_new_user(const ACL_USER &user) } +/** + Make a database name on mem_root from a String, + apply lower-case conversion if lower_case_table_names says so. + Perform database name length limit validation. + + @param thd - the THD, to get the warning text from + @param mem_root - allocate the result on this memory root + @param dbstr - the String, e.g. with Field::val_str() result + + @return - {NULL,0} in case of EOM or a bad database name, + or a good database name otherwise. +*/ +static LEX_STRING make_and_check_db_name(MEM_ROOT *mem_root, + const String &dbstr) +{ + LEX_STRING dbls= lower_case_table_names ? + lex_string_casedn_root(mem_root, files_charset_info, + dbstr.ptr(), dbstr.length()) : + lex_string_strmake_root(mem_root, + dbstr.ptr(), dbstr.length()); + if (!dbls.str) + return LEX_STRING{NULL, 0}; // EOM + if (dbls.length > SAFE_NAME_LEN) + { + sql_print_warning(ER_DEFAULT(ER_WRONG_DB_NAME), dbls.str); + return LEX_STRING{NULL, 0}; // Bad name + } + return dbls; // Good name +} + + /* Initialize structures responsible for user/db-level privilege checking and load information about grants from open privilege tables. @@ -2567,7 +2596,6 @@ static void push_new_user(const ACL_USER &user) static bool acl_load(THD *thd, const Grant_tables& tables) { READ_RECORD read_record_info; - char tmp_name[SAFE_NAME_LEN+1]; Sql_mode_save old_mode_save(thd); DBUG_ENTER("acl_load"); @@ -2585,28 +2613,25 @@ static bool acl_load(THD *thd, const Grant_tables& tables) { ACL_HOST host; update_hostname(&host.host, get_field(&acl_memroot, host_table.host())); - host.db= get_field(&acl_memroot, host_table.db()); - if (lower_case_table_names && host.db) + StringBuffer dbstr; + host_table.db()->val_str(&dbstr); + if (dbstr.length()) { + const LEX_STRING dbls= make_and_check_db_name(&acl_memroot, dbstr); + if (!(host.db= dbls.str)) + continue; // EOM or a bad database name /* - convert db to lower case and give a warning if the db wasn't - already in lower case + Issue a warning if lower case conversion happened + and it changed the database name. */ - char *end = strnmov(tmp_name, host.db, sizeof(tmp_name)); - if (end >= tmp_name + sizeof(tmp_name)) - { - sql_print_warning(ER_THD(thd, ER_WRONG_DB_NAME), host.db); - continue; - } - my_casedn_str(files_charset_info, host.db); - if (strcmp(host.db, tmp_name) != 0) + if (lower_case_table_names && cmp(dbls, dbstr.to_lex_cstring())) sql_print_warning("'host' entry '%s|%s' had database in mixed " "case that has been forced to lowercase because " "lower_case_table_names is set. It will not be " "possible to remove this privilege using REVOKE.", host.host.hostname, host.db); } - else if (!host.db) + else host.db= const_cast(host_not_specified.str); host.access= host_table.get_access(); host.access= fix_rights_for_db(host.access); @@ -2733,18 +2758,35 @@ static bool acl_load(THD *thd, const Grant_tables& tables) while (!(read_record_info.read_record())) { ACL_DB db; - char *db_name; db.user=safe_str(get_field(&acl_memroot, db_table.user())); const char *hostname= get_field(&acl_memroot, db_table.host()); if (!hostname && find_acl_role(db.user, true)) hostname= ""; update_hostname(&db.host, hostname); - db.db= db_name= get_field(&acl_memroot, db_table.db()); - if (!db.db) + + StringBuffer dbstr; + db_table.db()->val_str(&dbstr); + if (!dbstr.length()) { sql_print_warning("Found an entry in the 'db' table with empty database name; Skipped"); continue; } + const LEX_STRING dbls= make_and_check_db_name(&acl_memroot, dbstr); + if (!(db.db= dbls.str)) // EOM or a bad database name + continue; + /* + Issue a warning if lower case conversion happened + and it changed the database name. + */ + if (lower_case_table_names && cmp(dbls, dbstr.to_lex_cstring())) + { + sql_print_warning("'db' entry '%s %s@%s' had database in mixed " + "case that has been forced to lowercase because " + "lower_case_table_names is set. It will not be " + "possible to remove this privilege using REVOKE.", + db.db, db.user, safe_str(db.host.hostname)); + } + if (opt_skip_name_resolve && hostname_requires_resolving(db.host.hostname)) { sql_print_warning("'db' entry '%s %s@%s' " @@ -2755,28 +2797,6 @@ static bool acl_load(THD *thd, const Grant_tables& tables) db.access= db_table.get_access(); db.access=fix_rights_for_db(db.access); db.initial_access= db.access; - if (lower_case_table_names) - { - /* - convert db to lower case and give a warning if the db wasn't - already in lower case - */ - char *end = strnmov(tmp_name, db.db, sizeof(tmp_name)); - if (end >= tmp_name + sizeof(tmp_name)) - { - sql_print_warning(ER_THD(thd, ER_WRONG_DB_NAME), db.db); - continue; - } - my_casedn_str(files_charset_info, db_name); - if (strcmp(db_name, tmp_name) != 0) - { - sql_print_warning("'db' entry '%s %s@%s' had database in mixed " - "case that has been forced to lowercase because " - "lower_case_table_names is set. It will not be " - "possible to remove this privilege using REVOKE.", - db.db, db.user, safe_str(db.host.hostname)); - } - } db.sort=get_magic_sort("hdu", db.host.hostname, db.db, db.user); #ifndef TO_BE_REMOVED if (db_table.num_fields() <= 9) @@ -3696,26 +3716,34 @@ privilege_t acl_get(const char *host, const char *ip, { privilege_t host_access(ALL_KNOWN_ACL), db_access(NO_ACL); uint i; - size_t key_length; - char key[ACL_KEY_LENGTH],*tmp_db,*end; + const char *tmp_db; acl_entry *entry; DBUG_ENTER("acl_get"); - tmp_db= strmov(strmov(key, safe_str(ip)) + 1, user) + 1; - end= strnmov(tmp_db, db, key + sizeof(key) - tmp_db); + // Key length, without the trailing '\0' byte + constexpr size_t key_data_size= IP_ADDR_STRLEN + 1/*'\0'*/ + + USERNAME_LENGTH + 1/*'\0'*/ + + NAME_LEN/*database*/; + /* + Let's reserve extra MY_CS_MBMAXLEN bytes in the buffer. + This is to catch cases when a too long database name gets truncated: + key.length() will return a length in the range: + [key_data_size + 1, key_data_size + MY_CS_MBMAXLEN]. + */ + CharBuffer key; + key.append(Lex_cstring_strlen(safe_str(ip))).append_char('\0') + .append(Lex_cstring_strlen(user)).append_char('\0'); + tmp_db= key.end(); + key.append_opt_casedn(files_charset_info, Lex_cstring_strlen(db), + lower_case_table_names); + db= tmp_db; - if (end >= key + sizeof(key)) // db name was truncated + if (key.length() > key_data_size) // db name was truncated DBUG_RETURN(NO_ACL); // no privileges for an invalid db name - if (lower_case_table_names) - { - my_casedn_str(files_charset_info, tmp_db); - db=tmp_db; - } - key_length= (size_t) (end-key); - mysql_mutex_lock(&acl_cache->lock); - if (!db_is_pattern && (entry=acl_cache->search((uchar*) key, key_length))) + if (!db_is_pattern && + (entry= acl_cache->search((uchar*) key.ptr(), key.length()))) { db_access=entry->access; mysql_mutex_unlock(&acl_cache->lock); @@ -3760,12 +3788,13 @@ exit: /* Save entry in cache for quick retrieval */ if (!db_is_pattern && (entry= (acl_entry*) my_malloc(key_memory_acl_cache, - sizeof(acl_entry)+key_length, MYF(MY_WME)))) + sizeof(acl_entry) + key.length(), + MYF(MY_WME)))) { entry->access=(db_access & host_access); - DBUG_ASSERT(key_length < 0xffff); - entry->length=(uint16)key_length; - memcpy((uchar*) entry->key,key,key_length); + DBUG_ASSERT(key.length() < 0xffff); + entry->length= (uint16) key.length(); + memcpy((uchar*) entry->key, key.ptr(), key.length()); acl_cache->add(entry); } mysql_mutex_unlock(&acl_cache->lock); @@ -5472,17 +5501,21 @@ void GRANT_NAME::set_user_details(const char *h, const char *d, update_hostname(&host, strdup_root(&grant_memroot, h)); if (db != d) { - db= strdup_root(&grant_memroot, d); - if (lower_case_table_names) - my_casedn_str(files_charset_info, db); + DBUG_ASSERT(d); + db= lower_case_table_names ? + lex_string_casedn_root(&grant_memroot, files_charset_info, + d, strlen(d)).str : + strdup_root(&grant_memroot, d); } user = strdup_root(&grant_memroot,u); sort= get_magic_sort("hdu", host.hostname, db, user); if (tname != t) { - tname= strdup_root(&grant_memroot, t); - if (lower_case_table_names || is_routine) - my_casedn_str(files_charset_info, tname); + DBUG_ASSERT(t); + tname= lower_case_table_names || is_routine ? + lex_string_casedn_root(&grant_memroot, files_charset_info, + t, strlen(t)).str : + strdup_root(&grant_memroot, t); } key_length= strlen(d) + strlen(u)+ strlen(t)+3; hash_key= (char*) alloc_root(&grant_memroot,key_length); @@ -5529,11 +5562,15 @@ GRANT_NAME::GRANT_NAME(TABLE *form, bool is_routine) sort= get_magic_sort("hdu", host.hostname, db, user); if (lower_case_table_names) { - my_casedn_str(files_charset_info, db); + DBUG_ASSERT(db); + db= lex_string_casedn_root(&grant_memroot, files_charset_info, + db, strlen(db)).str; } if (lower_case_table_names || is_routine) { - my_casedn_str(files_charset_info, tname); + DBUG_ASSERT(tname); + tname= lex_string_casedn_root(&grant_memroot, files_charset_info, + tname, strlen(tname)).str; } key_length= (strlen(db) + strlen(user) + strlen(tname) + 3); hash_key= (char*) alloc_root(&grant_memroot, key_length); @@ -5657,28 +5694,25 @@ static GRANT_NAME *name_hash_search(HASH *name_hash, const char *user, const char *tname, bool exact, bool name_tolower) { - char helping[SAFE_NAME_LEN*2+USERNAME_LENGTH+3]; - char *hend = helping + sizeof(helping); - uint len; + constexpr size_t key_data_size= SAFE_NAME_LEN * 2 + USERNAME_LENGTH + 1; + // See earlier comments on MY_CS_MBMAXLEN above + CharBuffer key; GRANT_NAME *grant_name,*found=0; HASH_SEARCH_STATE state; - char *db_ptr= strmov(helping, user) + 1; - char *tname_ptr= strnmov(db_ptr, db, hend - db_ptr) + 1; - if (tname_ptr > hend) - return 0; // invalid name = not found - char *end= strnmov(tname_ptr, tname, hend - tname_ptr) + 1; - if (end > hend) + key.append(Lex_cstring_strlen(user)).append_char('\0') + .append(Lex_cstring_strlen(db)).append_char('\0') + .append_opt_casedn(files_charset_info, Lex_cstring_strlen(tname), + name_tolower); + key.append_char('\0'); + if (key.length() > key_data_size) return 0; // invalid name = not found - len = (uint) (end - helping); - if (name_tolower) - my_casedn_str(files_charset_info, tname_ptr); - for (grant_name= (GRANT_NAME*) my_hash_first(name_hash, (uchar*) helping, - len, &state); + for (grant_name= (GRANT_NAME*) my_hash_first(name_hash, (uchar*) key.ptr(), + key.length(), &state); grant_name ; - grant_name= (GRANT_NAME*) my_hash_next(name_hash,(uchar*) helping, - len, &state)) + grant_name= (GRANT_NAME*) my_hash_next(name_hash, (uchar*) key.ptr(), + key.length(), &state)) { if (exact) { @@ -8848,33 +8882,28 @@ static bool check_grant_db_routine(THD *thd, const char *db, HASH *hash) bool check_grant_db(THD *thd, const char *db) { Security_context *sctx= thd->security_ctx; - char helping [SAFE_NAME_LEN + USERNAME_LENGTH+2], *end; - char helping2 [SAFE_NAME_LEN + USERNAME_LENGTH+2], *tmp_db; - uint len, UNINIT_VAR(len2); + constexpr size_t key_data_size= SAFE_NAME_LEN + USERNAME_LENGTH + 1; + // See earlier comments on MY_CS_MBMAXLEN above + CharBuffer key, key2; bool error= TRUE; - tmp_db= strmov(helping, sctx->priv_user) + 1; - end= strnmov(tmp_db, db, helping + sizeof(helping) - tmp_db); + key.append(Lex_cstring_strlen(sctx->priv_user)).append_char('\0') + .append_opt_casedn(files_charset_info, Lex_cstring_strlen(db), + lower_case_table_names) + .append_char('\0'); - if (end >= helping + sizeof(helping)) // db name was truncated - return 1; // no privileges for an invalid db name - - if (lower_case_table_names) - { - end = tmp_db + my_casedn_str(files_charset_info, tmp_db); - db=tmp_db; - } - - len= (uint) (end - helping) + 1; + if (key.length() > key_data_size) // db name was truncated + return 1; // no privileges for an invalid db name /* If a role is set, we need to check for privileges here as well. */ if (sctx->priv_role[0]) { - end= strmov(helping2, sctx->priv_role) + 1; - end= strnmov(end, db, helping2 + sizeof(helping2) - end); - len2= (uint) (end - helping2) + 1; + key2.append(Lex_cstring_strlen(sctx->priv_role)).append_char('\0') + .append_opt_casedn(files_charset_info, Lex_cstring_strlen(db), + lower_case_table_names) + .append_char('\0'); } @@ -8884,16 +8913,16 @@ bool check_grant_db(THD *thd, const char *db) { GRANT_TABLE *grant_table= (GRANT_TABLE*) my_hash_element(&column_priv_hash, idx); - if (len < grant_table->key_length && - !memcmp(grant_table->hash_key, helping, len) && + if (key.length() < grant_table->key_length && + !memcmp(grant_table->hash_key, key.ptr(), key.length()) && compare_hostname(&grant_table->host, sctx->host, sctx->ip)) { error= FALSE; /* Found match. */ break; } if (sctx->priv_role[0] && - len2 < grant_table->key_length && - !memcmp(grant_table->hash_key, helping2, len2) && + key2.length() < grant_table->key_length && + !memcmp(grant_table->hash_key, key2.ptr(), key2.length()) && (!grant_table->host.hostname || !grant_table->host.hostname[0])) { error= FALSE; /* Found role match */ diff --git a/sql/sql_alter.cc b/sql/sql_alter.cc index 288327cd504..86af7919d99 100644 --- a/sql/sql_alter.cc +++ b/sql/sql_alter.cc @@ -424,16 +424,15 @@ Alter_table_ctx::Alter_table_ctx(THD *thd, TABLE_LIST *table_list, if (lower_case_table_names == 1) // Convert new_name/new_alias to lower { - new_name.length= my_casedn_str(files_charset_info, (char*) new_name.str); + new_name= new_name_buff.copy_casedn(files_charset_info, new_name). + to_lex_cstring(); new_alias= new_name; } else if (lower_case_table_names == 2) // Convert new_name to lower case { - new_alias.str= new_alias_buff; - new_alias.length= new_name.length; - strmov(new_alias_buff, new_name.str); - new_name.length= my_casedn_str(files_charset_info, (char*) new_name.str); - + new_alias= new_name; + new_name= new_name_buff.copy_casedn(files_charset_info, new_name). + to_lex_cstring(); } else new_alias= new_name; // LCTN=0 => case sensitive + case preserving @@ -461,7 +460,10 @@ Alter_table_ctx::Alter_table_ctx(THD *thd, TABLE_LIST *table_list, tmp_file_prefix, current_pid, thd->thread_id); /* Safety fix for InnoDB */ if (lower_case_table_names) - tmp_name.length= my_casedn_str(files_charset_info, tmp_name_buff); + { + // Ok to latin1, as the file name is in the form '#sql-alter-abc-def' + tmp_name.length= my_casedn_str_latin1(tmp_name_buff); + } if (table_list->table->s->tmp_table == NO_TMP_TABLE) { diff --git a/sql/sql_alter.h b/sql/sql_alter.h index c5e4e8120f1..8ffac83b7c0 100644 --- a/sql/sql_alter.h +++ b/sql/sql_alter.h @@ -437,7 +437,7 @@ public: private: char new_filename[FN_REFLEN + 1]; - char new_alias_buff[NAME_LEN + 1]; + CharBuffer new_name_buff; char tmp_name_buff[NAME_LEN + 1]; char path[FN_REFLEN + 1]; char new_path[FN_REFLEN + 1]; diff --git a/sql/sql_class.cc b/sql/sql_class.cc index aa22aa73ada..40569c67d72 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -4039,26 +4039,27 @@ Query_arena::Type Statement::type() const /* - Return an internal database name: + Return a valid database name: - validated with Lex_ident_db::check_db_name() - - optionally converted to lower-case when lower_case_table_names==1 + - optionally converted to lower-case The lower-cased copy is made on mem_root when needed. An error is raised in case of EOM or a bad database name. - @param src - the database name - @returns - {NULL,0} on EOM or a bad database name, - or a good database name otherwise + @param src - the database name + @param casedn - if the name should be lower-cased + @returns - {NULL,0} on EOM or a bad database name, + or a good database name otherwise */ Lex_ident_db -Query_arena::to_ident_db_internal_with_error(const LEX_CSTRING &src) +Query_arena::to_ident_db_opt_casedn_with_error(const LEX_CSTRING &src, + bool casedn) { DBUG_ASSERT(src.str); if (src.str == any_db.str) // e.g. JSON table return any_db; // preserve any_db - it has a special meaning - bool casedn= lower_case_table_names == 1; const LEX_CSTRING tmp= casedn ? make_ident_casedn(src) : src; if (!tmp.str /*EOM*/ || Lex_ident_fs(tmp).check_db_name_with_error()) diff --git a/sql/sql_class.h b/sql/sql_class.h index 12e3e856cca..c1efb49f6da 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -1287,13 +1287,17 @@ public: Methods to copy a string to the memory root and return the value as a LEX_CSTRING. */ - LEX_CSTRING strmake_lex_cstring(const char *str, size_t length) const + LEX_STRING strmake_lex_string(const char *str, size_t length) const { - const char *tmp= strmake_root(mem_root, str, length); + char *tmp= strmake_root(mem_root, str, length); if (!tmp) return {0,0}; return {tmp, length}; } + LEX_CSTRING strmake_lex_cstring(const char *str, size_t length) const + { + return strmake_lex_string(str, length); + } LEX_CSTRING strmake_lex_cstring(const LEX_CSTRING &from) const { return strmake_lex_cstring(from.str, from.length); @@ -1415,6 +1419,21 @@ public: lex_string_strmake_root(mem_root, src.str, src.length); } + /* + Convert a LEX_CSTRING to a valid database name: + - validated with Lex_ident_fs::check_db_name() + - optionally lower-cased + The lower-cased copy is created on Query_arena::mem_root, when needed. + + @param name - The name to normalize. Must not be {NULL,0}. + @param casedn - If the name should be lower-cased. + @return - {NULL,0} on EOM or a bad database name + (with an errror is raised, + or a good database name otherwise. + */ + Lex_ident_db to_ident_db_opt_casedn_with_error(const LEX_CSTRING &name, + bool casedn); + /* Convert a LEX_CSTRING to a valid internal database name: - validated with Lex_ident_fs::check_db_name() @@ -1426,7 +1445,29 @@ public: (with an errror is raised, or a good database name otherwise. */ - Lex_ident_db to_ident_db_internal_with_error(const LEX_CSTRING &name); + Lex_ident_db to_ident_db_internal_with_error(const LEX_CSTRING &name) + { + return to_ident_db_opt_casedn_with_error(name, lower_case_table_names == 1); + } + + /* + Convert a LEX_CSTRING to a valid normalized database name: + - validated with Lex_ident_fs::check_db_name() + - optionally lower-cased when lower_case_table_names>0 + The lower-cased copy is created on Query_arena::mem_root, when needed. + + @param name - The name to normalize. Must not be {NULL,0}. + @return - {NULL,0} on EOM or a bad database name + (with an errror is raised, + or a good database name otherwise. + */ + Lex_ident_db_normalized to_ident_db_normalized_with_error( + const LEX_CSTRING &name) + { + Lex_ident_db tmp= to_ident_db_opt_casedn_with_error(name, + lower_case_table_names > 0); + return Lex_ident_db_normalized(tmp); + } void set_query_arena(Query_arena *set); @@ -4927,14 +4968,7 @@ public: /** Set the current database, without copying */ void reset_db(const LEX_CSTRING *new_db); - /* - Copy the current database to the argument. Use the current arena to - allocate memory for a deep copy: current database may be freed after - a statement is parsed but before it's executed. - - Can only be called by owner of thd (no mutex protection) - */ - bool copy_db_to(LEX_CSTRING *to) + bool check_if_current_db_is_set_with_error() const { if (db.str == NULL) { @@ -4950,11 +4984,46 @@ public: my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0)); return TRUE; } + return false; + } + + /* + Copy the current database to the argument. Use the current arena to + allocate memory for a deep copy: current database may be freed after + a statement is parsed but before it's executed. + + Can only be called by owner of thd (no mutex protection) + */ + bool copy_db_to(LEX_CSTRING *to) + { + if (check_if_current_db_is_set_with_error()) + return true; to->str= strmake(db.str, db.length); to->length= db.length; return to->str == NULL; /* True on error */ } + + /* + Make a normalized copy of the current database. + Raise an error if no current database is set. + Note, in case of lower_case_table_names==2, thd->db can contain the + name in arbitrary case typed by the user, so it must be lower-cased. + For other lower_case_table_names values the name is already in + its normalized case, so it's copied as is. + */ + Lex_ident_db_normalized copy_db_normalized() + { + if (check_if_current_db_is_set_with_error()) + return Lex_ident_db_normalized(); + LEX_CSTRING ident= make_ident_opt_casedn(db, lower_case_table_names == 2); + /* + A non-empty thd->db is always known to satisfy check_db_name(). + So after optional lower-casing above it's safe to + make Lex_ident_db_normalized. + */ + return Lex_ident_db_normalized(ident); + } /* Get db name or "". Use for printing current db */ const char *get_db() { return safe_str(db.str); } @@ -7233,7 +7302,7 @@ public: inline Table_ident(SELECT_LEX_UNIT *s) : sel(s) { /* We must have a table name here as this is used with add_table_to_list */ - db.str= empty_c_string; /* a subject to casedn_str */ + db.str= empty_c_string; db.length= 0; table.str= internal_table_name; table.length=1; @@ -8021,66 +8090,6 @@ public: }; -class Identifier_chain2 -{ - LEX_CSTRING m_name[2]; -public: - Identifier_chain2() - :m_name{Lex_cstring(), Lex_cstring()} - { } - Identifier_chain2(const LEX_CSTRING &a, const LEX_CSTRING &b) - :m_name{a, b} - { } - - const LEX_CSTRING& operator [] (size_t i) const - { - return m_name[i]; - } - - static Identifier_chain2 split(const LEX_CSTRING &txt) - { - DBUG_ASSERT(txt.str[txt.length] == '\0'); // Expect 0-terminated input - const char *dot= strchr(txt.str, '.'); - if (!dot) - return Identifier_chain2(Lex_cstring(), txt); - size_t length0= dot - txt.str; - Lex_cstring name0(txt.str, length0); - Lex_cstring name1(txt.str + length0 + 1, txt.length - length0 - 1); - return Identifier_chain2(name0, name1); - } - - // Export as a qualified name string: 'db.name' - size_t make_qname(char *dst, size_t dstlen, bool casedn_part1) const - { - size_t res= my_snprintf(dst, dstlen, "%.*s.%.*s", - (int) m_name[0].length, m_name[0].str, - (int) m_name[1].length, m_name[1].str); - if (casedn_part1 && dstlen > m_name[0].length) - my_casedn_str(system_charset_info, dst + m_name[0].length + 1); - return res; - } - - // Export as a qualified name string, allocate on mem_root. - LEX_CSTRING make_qname(MEM_ROOT *mem_root, bool casedn_part1) const - { - LEX_STRING dst; - /* format: [pkg + dot] + name + '\0' */ - size_t dst_size= m_name[0].length + 1 /*dot*/ + m_name[1].length + 1/*\0*/; - if (unlikely(!(dst.str= (char*) alloc_root(mem_root, dst_size)))) - return {NULL, 0}; - if (!m_name[0].length) - { - DBUG_ASSERT(!casedn_part1); // Should not be called this way - dst.length= my_snprintf(dst.str, dst_size, "%.*s", - (int) m_name[1].length, m_name[1].str); - return {dst.str, dst.length}; - } - dst.length= make_qname(dst.str, dst_size, casedn_part1); - return {dst.str, dst.length}; - } -}; - - /** This class resembles the SQL Standard schema qualified object name: ::= [ ] @@ -8105,6 +8114,11 @@ public: m_name.length= name_length; } + Identifier_chain2 to_identifier_chain2() const + { + return Identifier_chain2(m_db, m_name); + } + bool eq(const Database_qualified_name *other) const { CHARSET_INFO *cs= lower_case_table_names ? @@ -8126,17 +8140,6 @@ public: bool copy_sp_name_internal(MEM_ROOT *mem_root, const LEX_CSTRING &db, const LEX_CSTRING &name); - // Export db and name as a qualified name string: 'db.name' - size_t make_qname(char *dst, size_t dstlen, bool casedn_name) const - { - return Identifier_chain2(m_db, m_name).make_qname(dst, dstlen, casedn_name); - } - // Export db and name as a qualified name string, allocate on mem_root. - LEX_CSTRING make_qname(MEM_ROOT *mem_root, bool casedn_name) const - { - return Identifier_chain2(m_db, m_name).make_qname(mem_root, casedn_name); - } - bool make_package_routine_name(MEM_ROOT *mem_root, const LEX_CSTRING &package, const LEX_CSTRING &routine) @@ -8145,8 +8148,7 @@ public: size_t length= package.length + 1 + routine.length + 1; if (unlikely(!(tmp= (char *) alloc_root(mem_root, length)))) return true; - m_name.length= Identifier_chain2(package, routine).make_qname(tmp, length, - false); + m_name.length= Identifier_chain2(package, routine).make_qname(tmp, length); m_name.str= tmp; return false; } @@ -8175,7 +8177,8 @@ public: { } LEX_CSTRING lex_cstring() const override { - size_t length= m_name->make_qname(err_buffer, sizeof(err_buffer), false); + size_t length= m_name->to_identifier_chain2().make_qname(err_buffer, + sizeof(err_buffer)); return {err_buffer, length}; } }; diff --git a/sql/sql_db.cc b/sql/sql_db.cc index 08441d9f067..484861512e4 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -1340,17 +1340,16 @@ static bool find_db_tables_and_rm_known_files(THD *thd, MY_DIR *dirp, if (!table_list) DBUG_RETURN(true); table_list->db= db; - table_list->table_name= *table; - table_list->open_type= OT_BASE_ONLY; - /* On the case-insensitive file systems table is opened with the lowercased file name. So we should lowercase as well to look up the cache properly. */ - if (lower_case_file_system) - table_list->table_name.length= my_casedn_str(files_charset_info, - (char*) table_list->table_name.str); + table_list->table_name= lower_case_file_system ? + thd->make_ident_casedn(*table) : + *table; + + table_list->open_type= OT_BASE_ONLY; table_list->alias= table_list->table_name; // If lower_case_table_names=2 MDL_REQUEST_INIT(&table_list->mdl_request, MDL_key::TABLE, diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 587205a5c12..ac2fe5f4537 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -4279,7 +4279,8 @@ bool LEX::copy_db_to(LEX_CSTRING *to) { if (sphead && sphead->m_name.str) { - DBUG_ASSERT(sphead->m_db.str && sphead->m_db.length); + DBUG_ASSERT(sphead->m_db.str); + DBUG_ASSERT(sphead->m_db.length); /* It is safe to assign the string by-pointer, both sphead and its statements reside in the same memory root. @@ -4290,6 +4291,19 @@ bool LEX::copy_db_to(LEX_CSTRING *to) return thd->copy_db_to(to); } + +Lex_ident_db_normalized LEX::copy_db_normalized() +{ + if (sphead && sphead->m_name.str) + { + DBUG_ASSERT(sphead->m_db.str); + DBUG_ASSERT(sphead->m_db.length); + return thd->to_ident_db_normalized_with_error(sphead->m_db); + } + return thd->copy_db_normalized(); +} + + /** Initialize offset and limit counters. @@ -7431,10 +7445,10 @@ bool LEX::sp_block_finalize(THD *thd, const Lex_spblock_st spblock, sp_name *LEX::make_sp_name(THD *thd, const Lex_ident_sys_st &name) { sp_name *res; - LEX_CSTRING db; + Lex_ident_db_normalized db; if (unlikely(check_routine_name(&name)) || - unlikely(copy_db_to(&db)) || - unlikely((!(res= new (thd->mem_root) sp_name(&db, &name, false))))) + unlikely(!(db= copy_db_normalized()).str) || + unlikely((!(res= new (thd->mem_root) sp_name(db, name, false))))) return NULL; return res; } @@ -7471,10 +7485,11 @@ sp_name *LEX::make_sp_name(THD *thd, const Lex_ident_sys_st &name1, { DBUG_ASSERT(name1.str); sp_name *res; - const Lex_ident_db norm_name1= thd->to_ident_db_internal_with_error(name1); + const Lex_ident_db_normalized norm_name1= + thd->to_ident_db_normalized_with_error(name1); if (unlikely(!norm_name1.str) || unlikely(check_routine_name(&name2)) || - unlikely(!(res= new (thd->mem_root) sp_name(&norm_name1, &name2, true)))) + unlikely(!(res= new (thd->mem_root) sp_name(norm_name1, name2, true)))) return NULL; return res; } @@ -7530,7 +7545,9 @@ sp_head *LEX::make_sp_head(THD *thd, const sp_name *name, name->m_name); else sp->init_sp_name(name); - if (!(sp->m_qname= sp->make_qname(sp->get_main_mem_root(), true)).str) + if (!(sp->m_qname= + sp->to_identifier_chain2(). + make_qname_casedn_part1(sp->get_main_mem_root())).str) return NULL; } sphead= sp; @@ -9432,17 +9449,17 @@ bool LEX::call_statement_start(THD *thd, sql_command= SQLCOM_CALL; - const Lex_ident_db db_int= thd->to_ident_db_internal_with_error(*db); - if (!db_int.str || + const Lex_ident_db_normalized dbn= thd->to_ident_db_normalized_with_error(*db); + if (!dbn.str || check_routine_name(pkg) || check_routine_name(proc)) return true; // Concat `pkg` and `name` to `pkg.name` LEX_CSTRING pkg_dot_proc; - if (!(pkg_dot_proc= q_pkg_proc.make_qname(thd->mem_root, false)).str || + if (!(pkg_dot_proc= q_pkg_proc.make_qname(thd->mem_root)).str || check_ident_length(&pkg_dot_proc) || - !(spname= new (thd->mem_root) sp_name(&db_int, &pkg_dot_proc, true))) + !(spname= new (thd->mem_root) sp_name(dbn, pkg_dot_proc, true))) return true; sp_handler_package_function.add_used_routine(thd->lex, thd, spname); @@ -9507,7 +9524,8 @@ sp_package *LEX::create_package_start(THD *thd, return NULL; pkg->reset_thd_mem_root(thd); pkg->init(this); - if (!(pkg->m_qname= pkg->make_qname(pkg->get_main_mem_root(), true)).str) + if (!(pkg->m_qname= pkg->to_identifier_chain2(). + make_qname_casedn_part1(pkg->get_main_mem_root())).str) return NULL; pkg->set_c_chistics(chistics); sphead= pkg; @@ -9801,12 +9819,7 @@ Item *LEX::make_item_func_call_generic(THD *thd, - MySQL.version() is the SQL 2003 syntax for the native function version() (a vendor can specify any schema). */ - - const Lex_ident_db db_int= thd->to_ident_db_internal_with_error(db); - if (!db_int.str || check_routine_name(&name)) - return NULL; - - return make_item_func_call_generic(thd, Lex_ident_sys(db_int.str, db_int.length), name, args); + return make_item_func_call_generic(thd, db, name, args); } @@ -9821,7 +9834,12 @@ Item *LEX::make_item_func_call_generic(THD *thd, Create_qfunc *builder= find_qualified_function_builder(thd); DBUG_ASSERT(builder); - return builder->create_with_db(thd, &db, &name, true, args); + + const Lex_ident_db_normalized dbn= thd->to_ident_db_normalized_with_error(db); + if (!dbn.str || check_routine_name(&name)) + return NULL; + + return builder->create_with_db(thd, dbn, name, true, args); } @@ -9845,17 +9863,17 @@ Item *LEX::make_item_func_call_generic(THD *thd, if (db.is_null() || pkg.is_null() || func.is_null()) return NULL; // EOM - const Lex_ident_db db_int= thd->to_ident_db_internal_with_error(db); - if (!db_int.str || + const Lex_ident_db_normalized dbn= thd->to_ident_db_normalized_with_error(db); + if (!dbn.str || check_routine_name(&pkg) || check_routine_name(&func)) return NULL; // Concat `pkg` and `name` to `pkg.name` LEX_CSTRING pkg_dot_func; - if (!(pkg_dot_func= q_pkg_func.make_qname(thd->mem_root, false)).str || + if (!(pkg_dot_func= q_pkg_func.make_qname(thd->mem_root)).str || check_ident_length(&pkg_dot_func) || - !(qname= new (thd->mem_root) sp_name(&db_int, &pkg_dot_func, true))) + !(qname= new (thd->mem_root) sp_name(dbn, pkg_dot_func, true))) return NULL; sp_handler_package_function.add_used_routine(thd->lex, thd, qname); @@ -11838,11 +11856,11 @@ bool LEX::stmt_drop_routine(const Sp_handler *sph, if (check_routine_name(&name)) return true; enum_sql_command sqlcom= sph->sqlcom_drop(); - LEX_CSTRING db_int= {0, 0}; + Lex_ident_db_normalized dbn; if (db.str) { // An explicit database name is given - if (!(db_int= thd->to_ident_db_internal_with_error(db)).str) + if (!(dbn= thd->to_ident_db_normalized_with_error(db)).str) return true; } else if (thd->db.str || sqlcom != SQLCOM_DROP_FUNCTION) @@ -11856,9 +11874,9 @@ bool LEX::stmt_drop_routine(const Sp_handler *sph, - DROP PACKAGE - DROP PACKAGE BODY - DROP PROCEDURE - copy_db_to() raises ER_NO_DB_ERROR. + copy_db_normalized() raises ER_NO_DB_ERROR. */ - if (copy_db_to(&db_int)) + if (!(dbn= copy_db_normalized()).str) return true; } else @@ -11868,11 +11886,11 @@ bool LEX::stmt_drop_routine(const Sp_handler *sph, There is no an explicit database name given. The current database is not set. It can still be a valid DROP FUNCTION - for an UDF. - Keep db_int=={NULL,0}. + Keep dbn=={NULL,0}. */ } set_command(sqlcom, options); - spname= new (thd->mem_root) sp_name(&db_int, &name, db.str != NULL); + spname= new (thd->mem_root) sp_name(dbn, name, db.str != NULL); return false; } diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 13e4020017a..eda162dba7f 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -3826,6 +3826,7 @@ public: } bool copy_db_to(LEX_CSTRING *to); + Lex_ident_db_normalized copy_db_normalized(); void inc_select_stack_outer_barrier() { diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index db99dfe6d21..819c5df8291 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -126,7 +126,7 @@ static int show_create_db(THD *thd, LEX *lex); static bool alter_routine(THD *thd, LEX *lex); static bool drop_routine(THD *thd, LEX *lex); -const Lex_ident_db any_db(STRING_WITH_LEN("*any*")); +const Lex_ident_db_normalized any_db(STRING_WITH_LEN("*any*")); const LEX_CSTRING command_name[257]={ { STRING_WITH_LEN("Sleep") }, //0 @@ -2045,8 +2045,8 @@ dispatch_command_return dispatch_command(enum enum_server_command command, THD * /* Must be before we init the table list. */ if (lower_case_table_names) { - table_name.length= my_casedn_str(files_charset_info, table_name.str); - db.length= my_casedn_str(files_charset_info, (char*) db.str); + table_name= thd->make_ident_casedn(table_name); + db= thd->make_ident_casedn(db); } table_list.init_one_table(&db, (LEX_CSTRING*) &table_name, 0, TL_READ); /* diff --git a/sql/sql_parse.h b/sql/sql_parse.h index 94dc19094ca..f280d3cce8a 100644 --- a/sql/sql_parse.h +++ b/sql/sql_parse.h @@ -129,7 +129,7 @@ bool check_stack_overrun(THD *thd, long margin, uchar *dummy); /* Variables */ -extern const Lex_ident_db any_db; +extern const Lex_ident_db_normalized any_db; extern uint sql_command_flags[]; extern uint server_command_flags[]; extern const LEX_CSTRING command_name[]; diff --git a/sql/sql_partition_admin.cc b/sql/sql_partition_admin.cc index d290d0f5534..2f2eb3f7a1e 100644 --- a/sql/sql_partition_admin.cc +++ b/sql/sql_partition_admin.cc @@ -657,7 +657,10 @@ bool Sql_cmd_alter_table_exchange_partition:: my_snprintf(temp_name, sizeof(temp_name), "%s-exchange-%lx-%llx", tmp_file_prefix, current_pid, thd->thread_id); if (lower_case_table_names) - my_casedn_str(files_charset_info, temp_name); + { + // Ok to use latin1 as the file name is in the form '#sql-exchange-abc-def' + my_casedn_str_latin1(temp_name); + } build_table_filename(temp_file_name, sizeof(temp_file_name), table_list->next_local->db.str, temp_name, "", FN_IS_TMP); diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc index fca16ffa369..fce94459603 100644 --- a/sql/sql_plugin.cc +++ b/sql/sql_plugin.cc @@ -3865,7 +3865,7 @@ static int construct_options(MEM_ROOT *mem_root, struct st_plugin_int *tmp, plugin_name_ptr= (char*) alloc_root(mem_root, plugin_name_len + 1); strcpy(plugin_name_ptr, plugin_name); - my_casedn_str(&my_charset_latin1, plugin_name_ptr); + my_casedn_str_latin1(plugin_name_ptr); // Plugin names are pure ASCII convert_underscore_to_dash(plugin_name_ptr, plugin_name_len); plugin_name_with_prefix_ptr= (char*) alloc_root(mem_root, plugin_name_len + @@ -4234,7 +4234,8 @@ static int test_plugin_options(MEM_ROOT *tmp_root, struct st_plugin_int *tmp, len= tmp->name.length + strlen(o->name) + 2; varname= (char*) alloc_root(mem_root, len); strxmov(varname, tmp->name.str, "-", o->name, NullS); - my_casedn_str(&my_charset_latin1, varname); + // Ok to use latin1, as the variable name is pure ASCII + my_casedn_str_latin1(varname); convert_dash_to_underscore(varname, len-1); } if (o->flags & PLUGIN_VAR_NOSYSVAR) diff --git a/sql/sql_show.cc b/sql/sql_show.cc index de7d894a2a7..c9ca801ae73 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -3831,24 +3831,27 @@ static bool show_status_array(THD *thd, const char *wild, SHOW_VAR *variables, enum enum_var_type scope, struct system_status_var *status_var, - const char *prefix, TABLE *table, + const LEX_CSTRING &prefix, TABLE *table, bool ucase_names, COND *cond) { my_aligned_storage buffer; char * const buff= buffer.data; - char *prefix_end; - char name_buffer[NAME_CHAR_LEN]; - int len; + CharBuffer name_buffer; SHOW_VAR tmp, *var; bool res= FALSE; CHARSET_INFO *charset= system_charset_info; DBUG_ENTER("show_status_array"); - prefix_end=strnmov(name_buffer, prefix, sizeof(name_buffer)-1); - if (*prefix) - *prefix_end++= '_'; - len=(int)(name_buffer + sizeof(name_buffer) - prefix_end); + if (prefix.length) + { + if (ucase_names) + name_buffer.copy_caseup(system_charset_info, prefix); + else + name_buffer.copy_casedn(system_charset_info, prefix); + name_buffer.append(Lex_cstring("_", 1)); + } + size_t prefix_length= name_buffer.length(); #ifdef WITH_WSREP bool is_wsrep_var= FALSE; @@ -3858,7 +3861,7 @@ static bool show_status_array(THD *thd, const char *wild, for status variables defined under wsrep plugin. TODO: remove once lp:1306875 has been addressed. */ - if (*prefix && !my_strcasecmp(system_charset_info, prefix, "wsrep")) + if (prefix.length && !my_strcasecmp(system_charset_info, prefix.str, "wsrep")) { is_wsrep_var= TRUE; } @@ -3867,8 +3870,8 @@ static bool show_status_array(THD *thd, const char *wild, for (; variables->name; variables++) { bool wild_checked= false; - strnmov(prefix_end, variables->name, len); - name_buffer[sizeof(name_buffer)-1]=0; /* Safety */ + Lex_cstring_strlen var_name(variables->name); + name_buffer.truncate(prefix_length); #ifdef WITH_WSREP /* @@ -3877,30 +3880,31 @@ static bool show_status_array(THD *thd, const char *wild, names until lp:1306875 has been fixed. TODO: remove once lp:1306875 has been addressed. */ - if (!(*prefix) && !strncasecmp(name_buffer, "wsrep", strlen("wsrep"))) + if (!prefix.length && + !strncasecmp(name_buffer.ptr(), "wsrep", strlen("wsrep"))) { is_wsrep_var= TRUE; } #endif /* WITH_WSREP */ if (ucase_names) - my_caseup_str(system_charset_info, name_buffer); + name_buffer.append_caseup(system_charset_info, var_name); else { - my_casedn_str(system_charset_info, name_buffer); - DBUG_ASSERT(name_buffer[0] >= 'a'); - DBUG_ASSERT(name_buffer[0] <= 'z'); - + name_buffer.append_casedn(system_charset_info, var_name); // WSREP_TODO: remove once lp:1306875 has been addressed. if (IF_WSREP(is_wsrep_var == FALSE, 1) && status_var) - name_buffer[0]-= 'a' - 'A'; + { + char *ptr= (char*) name_buffer.ptr(); + if (ptr[0] >= 'a' && ptr[0] <= 'z') + ptr[0]-= 'a' - 'A'; + } } restore_record(table, s->default_values); - table->field[0]->store(name_buffer, strlen(name_buffer), - system_charset_info); + table->field[0]->store(name_buffer.to_lex_cstring(), system_charset_info); /* Compare name for types that can't return arrays. We do this to not @@ -3909,7 +3913,7 @@ static bool show_status_array(THD *thd, const char *wild, if ((variables->type != SHOW_FUNC && variables->type != SHOW_ARRAY)) { if (wild && wild[0] && wild_case_compare(system_charset_info, - name_buffer, wild)) + name_buffer.ptr(), wild)) continue; wild_checked= 1; // Avoid checking it again } @@ -3927,13 +3931,15 @@ static bool show_status_array(THD *thd, const char *wild, if (show_type == SHOW_ARRAY) { show_status_array(thd, wild, (SHOW_VAR *) var->value, scope, - status_var, name_buffer, table, ucase_names, cond); + status_var, name_buffer.to_lex_cstring(), + table, ucase_names, cond); } else { if ((wild_checked || !(wild && wild[0] && wild_case_compare(system_charset_info, - name_buffer, wild))) && + name_buffer.ptr(), + wild))) && (!cond || cond->val_int())) { const char *pos; // We assign a lot of const's @@ -4376,18 +4382,15 @@ bool get_lookup_field_values(THD *thd, COND *cond, bool fix_table_name_case, if (lower_case_table_names && !rc) { - /* - We can safely do in-place upgrades here since all of the above cases - are allocating a new memory buffer for these strings. - */ if (lookup_field_values->db_value.str && lookup_field_values->db_value.str[0]) - my_casedn_str(system_charset_info, - (char*) lookup_field_values->db_value.str); + lookup_field_values->db_value= thd->make_ident_casedn( + lookup_field_values->db_value); + if (fix_table_name_case && lookup_field_values->table_value.str && lookup_field_values->table_value.str[0]) - my_casedn_str(system_charset_info, - (char*) lookup_field_values->table_value.str); + lookup_field_values->table_value= thd->make_ident_casedn( + lookup_field_values->table_value); } return rc; @@ -8443,7 +8446,7 @@ int fill_variables(THD *thd, TABLE_LIST *tables, COND *cond) sync_dynamic_session_variables(thd, true); res= show_status_array(thd, wild, enumerate_sys_vars(thd, sorted_vars, scope), - scope, NULL, "", tables->table, + scope, NULL, empty_clex_str, tables->table, upper_case_names, partial_cond); mysql_prlock_unlock(&LOCK_system_variables_hash); DBUG_RETURN(res); @@ -8543,7 +8546,7 @@ int fill_status(THD *thd, TABLE_LIST *tables, COND *cond) mysql_rwlock_rdlock(&LOCK_all_status_vars); res= show_status_array(thd, wild, (SHOW_VAR *)all_status_vars.buffer, - scope, tmp1, "", tables->table, + scope, tmp1, empty_clex_str, tables->table, upper_case_names, partial_cond); mysql_rwlock_unlock(&LOCK_all_status_vars); DBUG_RETURN(res); @@ -10760,11 +10763,7 @@ TABLE_LIST *get_trigger_table(THD *thd, const sp_name *trg_name) if (!(table= (TABLE_LIST*) thd->alloc(sizeof(TABLE_LIST)))) return NULL; - db= trg_name->m_db; - - db.str= thd->strmake(db.str, db.length); - if (lower_case_table_names) - db.length= my_casedn_str(files_charset_info, (char*) db.str); + db= thd->make_ident_opt_casedn(trg_name->m_db, lower_case_table_names); tbl_name.str= thd->strmake(tbl_name.str, tbl_name.length); diff --git a/sql/sql_string.h b/sql/sql_string.h index 6d8d4acdad9..befb1acd93c 100644 --- a/sql/sql_string.h +++ b/sql/sql_string.h @@ -1030,6 +1030,24 @@ public: set_charset(tocs); return false; } + bool copy_casedn(CHARSET_INFO *cs, const LEX_CSTRING &str) + { + size_t nbytes= str.length * cs->casedn_multiply(); + DBUG_ASSERT(nbytes + 1 <= UINT_MAX32); + if (alloc(nbytes)) + return true; + str_length= (uint32) cs->casedn_z(str.str, str.length, Ptr, nbytes + 1); + return false; + } + bool copy_caseup(CHARSET_INFO *cs, const LEX_CSTRING &str) + { + size_t nbytes= str.length * cs->caseup_multiply(); + DBUG_ASSERT(nbytes + 1 <= UINT_MAX32); + if (alloc(nbytes)) + return true; + str_length= (uint32) cs->caseup_z(str.str, str.length, Ptr, nbytes + 1); + return false; + } // Append without character set conversion bool append(const String &s) { diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 55319a2242f..6803c335615 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -657,7 +657,7 @@ uint build_tmptable_filename(THD* thd, char *buff, size_t bufflen) if (lower_case_table_names) { /* Convert all except tmpdir to lower case */ - my_casedn_str(files_charset_info, p); + my_casedn_str_latin1(p); } size_t length= unpack_filename(buff, buff); diff --git a/sql/sql_type_fixedbin.h b/sql/sql_type_fixedbin.h index 698d9843e8a..201bd09d965 100644 --- a/sql/sql_type_fixedbin.h +++ b/sql/sql_type_fixedbin.h @@ -282,9 +282,7 @@ public: void print(String *str, enum_query_type query_type) override { StringBuffer tmp; - tmp.append(singleton()->name().lex_cstring()); - my_caseup_str(&my_charset_latin1, tmp.c_ptr()); - str->append(tmp); + str->append(singleton()->name().lex_cstring()); str->append('\''); m_value.to_string(&tmp); str->append(tmp); diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 564325bc9ab..16835192d3e 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -15790,12 +15790,7 @@ user_maybe_role: MYSQL_YYABORT; if ($$->host.str[0]) { - /* - Convert hostname part of username to lowercase. - It's OK to use in-place lowercase as long as - the character set is utf8. - */ - my_casedn_str(system_charset_info, (char*) $$->host.str); + $$->host= thd->make_ident_casedn($$->host); } else { diff --git a/storage/connect/connect.cc b/storage/connect/connect.cc index 72b12552b95..093eaeb9a5e 100644 --- a/storage/connect/connect.cc +++ b/storage/connect/connect.cc @@ -45,8 +45,6 @@ #include "catalog.h" #include "ha_connect.h" -#define my_strupr(p) my_caseup_str(default_charset_info, (p)); -#define my_strlwr(p) my_casedn_str(default_charset_info, (p)); #define my_stricmp(a, b) my_strcasecmp(default_charset_info, (a), (b)) /***********************************************************************/ diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc index 0d4fb857598..fc5011c63b1 100644 --- a/storage/connect/ha_connect.cc +++ b/storage/connect/ha_connect.cc @@ -156,8 +156,6 @@ #include "tabpivot.h" #include "tabfix.h" -#define my_strupr(p) my_caseup_str(default_charset_info, (p)); -#define my_strlwr(p) my_casedn_str(default_charset_info, (p)); #define my_stricmp(a,b) my_strcasecmp(default_charset_info, (a), (b)) diff --git a/storage/federatedx/ha_federatedx.cc b/storage/federatedx/ha_federatedx.cc index e4c5bf8d13d..e3ae71335a1 100644 --- a/storage/federatedx/ha_federatedx.cc +++ b/storage/federatedx/ha_federatedx.cc @@ -1459,28 +1459,23 @@ static void fill_server(MEM_ROOT *mem_root, FEDERATEDX_SERVER *server, char buffer[STRING_BUFFER_USUAL_SIZE]; const char *socket_arg= share->socket ? share->socket : ""; const char *password_arg= share->password ? share->password : ""; + const Lex_cstring_strlen ls_database(share->database); + const Lex_cstring_strlen ls_socket(socket_arg); String key(buffer, sizeof(buffer), &my_charset_bin); - String scheme(share->scheme, strlen(share->scheme), &my_charset_latin1); - String hostname(share->hostname, strlen(share->hostname), &my_charset_latin1); - String database(share->database, strlen(share->database), system_charset_info); + String scheme, hostname; + String database(ls_database.str, ls_database.length, system_charset_info); String username(share->username, strlen(share->username), system_charset_info); - String socket(socket_arg, strlen(socket_arg), files_charset_info); + String socket(ls_socket.str, ls_socket.length, files_charset_info); String password(password_arg, strlen(password_arg), &my_charset_bin); DBUG_ENTER("fill_server"); /* Do some case conversions */ - scheme.reserve(scheme.length()); - scheme.length(my_casedn_str(&my_charset_latin1, scheme.c_ptr_safe())); - - hostname.reserve(hostname.length()); - hostname.length(my_casedn_str(&my_charset_latin1, hostname.c_ptr_safe())); - + scheme.copy_casedn(&my_charset_latin1, Lex_cstring_strlen(share->scheme)); + hostname.copy_casedn(&my_charset_latin1, Lex_cstring_strlen(share->hostname)); + if (lower_case_table_names) - { - database.reserve(database.length()); - database.length(my_casedn_str(system_charset_info, database.c_ptr_safe())); - } + database.copy_casedn(system_charset_info, ls_database); #ifndef _WIN32 /* @@ -1488,10 +1483,7 @@ static void fill_server(MEM_ROOT *mem_root, FEDERATEDX_SERVER *server, revised about using sockets in such environment. */ if (lower_case_file_system && socket.length()) - { - socket.reserve(socket.length()); - socket.length(my_casedn_str(files_charset_info, socket.c_ptr_safe())); - } + socket.copy_casedn(files_charset_info, ls_socket); #endif /* start with all bytes zeroed */ diff --git a/storage/innobase/dict/dict0dict.cc b/storage/innobase/dict/dict0dict.cc index c93fc9f814a..b49c76093c9 100644 --- a/storage/innobase/dict/dict0dict.cc +++ b/storage/innobase/dict/dict0dict.cc @@ -1599,19 +1599,13 @@ dict_table_rename_in_cache( foreign->referenced_table->referenced_set.erase(foreign); } - if (strlen(foreign->foreign_table_name) - < strlen(table->name.m_name)) { - /* Allocate a longer name buffer; - TODO: store buf len to save memory */ + /* Allocate a name buffer; + TODO: store buf len to save memory */ + + foreign->foreign_table_name = mem_heap_strdup( + foreign->heap, table->name.m_name); + foreign->foreign_table_name_lookup_set(); - foreign->foreign_table_name = mem_heap_strdup( - foreign->heap, table->name.m_name); - dict_mem_foreign_table_name_lookup_set(foreign, TRUE); - } else { - strcpy(foreign->foreign_table_name, - table->name.m_name); - dict_mem_foreign_table_name_lookup_set(foreign, FALSE); - } if (strchr(foreign->id, '/')) { /* This is a >= 4.0.18 format id */ @@ -1772,24 +1766,13 @@ dict_table_rename_in_cache( foreign = *it; - if (strlen(foreign->referenced_table_name) - < strlen(table->name.m_name)) { - /* Allocate a longer name buffer; - TODO: store buf len to save memory */ + /* Allocate a name buffer; + TODO: store buf len to save memory */ - foreign->referenced_table_name = mem_heap_strdup( - foreign->heap, table->name.m_name); + foreign->referenced_table_name = mem_heap_strdup( + foreign->heap, table->name.m_name); - dict_mem_referenced_table_name_lookup_set( - foreign, TRUE); - } else { - /* Use the same buffer */ - strcpy(foreign->referenced_table_name, - table->name.m_name); - - dict_mem_referenced_table_name_lookup_set( - foreign, FALSE); - } + foreign->referenced_table_name_lookup_set(); } return(DB_SUCCESS); @@ -3237,7 +3220,6 @@ dict_get_referenced_table( mem_heap_t* heap, /*!< in/out: heap memory */ CHARSET_INFO* from_cs) /*!< in: table name charset */ { - char* ref; char db_name[MAX_DATABASE_NAME_LEN]; char tbl_name[MAX_TABLE_NAME_LEN]; CHARSET_INFO* to_cs = &my_charset_filename; @@ -3283,31 +3265,22 @@ dict_get_referenced_table( } /* Copy database_name, '/', table_name, '\0' */ - const size_t len = database_name_len + table_name_len + 1; - ref = static_cast(mem_heap_alloc(heap, len + 1)); - memcpy(ref, database_name, database_name_len); - ref[database_name_len] = '/'; - memcpy(ref + database_name_len + 1, table_name, table_name_len + 1); + Identifier_chain2 ident({database_name, database_name_len}, + {table_name, table_name_len}); + size_t ref_nbytes= (database_name_len + table_name_len) * + system_charset_info->casedn_multiply() + 2; + char *ref = static_cast(mem_heap_alloc(heap, ref_nbytes)); /* Values; 0 = Store and compare as given; case sensitive 1 = Store and compare in lower; case insensitive 2 = Store as given, compare in lower; case semi-sensitive */ - if (lower_case_table_names == 2) { - innobase_casedn_str(ref); - *table = dict_sys.load_table({ref, len}); - memcpy(ref, database_name, database_name_len); - ref[database_name_len] = '/'; - memcpy(ref + database_name_len + 1, table_name, table_name_len + 1); - } else { -#ifndef _WIN32 - if (lower_case_table_names == 1) { - innobase_casedn_str(ref); - } -#else - innobase_casedn_str(ref); -#endif /* !_WIN32 */ - *table = dict_sys.load_table({ref, len}); + size_t len= ident.make_sep_name_opt_casedn(ref, ref_nbytes, + '/', lower_case_table_names > 0); + *table = dict_sys.load_table({ref, len}); + + if (lower_case_table_names == 2) { + ident.make_sep_name_opt_casedn(ref, ref_nbytes, '/', false); } return(ref); diff --git a/storage/innobase/dict/dict0load.cc b/storage/innobase/dict/dict0load.cc index 645e0c79490..8bf496f5e6a 100644 --- a/storage/innobase/dict/dict0load.cc +++ b/storage/innobase/dict/dict0load.cc @@ -2976,7 +2976,7 @@ err_exit: foreign->foreign_table_name = mem_heap_strdupl( foreign->heap, (char*) field, len); - dict_mem_foreign_table_name_lookup_set(foreign, TRUE); + foreign->foreign_table_name_lookup_set(); const size_t foreign_table_name_len = len; const size_t table_name_len = strlen(table_name); @@ -2997,7 +2997,7 @@ err_exit: foreign->referenced_table_name = mem_heap_strdupl( foreign->heap, (const char*) field, len); - dict_mem_referenced_table_name_lookup_set(foreign, TRUE); + foreign->referenced_table_name_lookup_set(); mtr.commit(); if (UNIV_LIKELY_NULL(heap)) { diff --git a/storage/innobase/dict/dict0mem.cc b/storage/innobase/dict/dict0mem.cc index b8b2d583c24..3e419765868 100644 --- a/storage/innobase/dict/dict0mem.cc +++ b/storage/innobase/dict/dict0mem.cc @@ -816,27 +816,15 @@ lower_case_table_names. If that is 0 or 1, foreign_table_name_lookup will point to foreign_table_name. If 2, then another string is allocated from foreign->heap and set to lower case. */ void -dict_mem_foreign_table_name_lookup_set( -/*===================================*/ - dict_foreign_t* foreign, /*!< in/out: foreign struct */ - ibool do_alloc) /*!< in: is an alloc needed */ +dict_foreign_t::foreign_table_name_lookup_set() { if (lower_case_table_names == 2) { - if (do_alloc) { - ulint len; - - len = strlen(foreign->foreign_table_name) + 1; - - foreign->foreign_table_name_lookup = - static_cast( - mem_heap_alloc(foreign->heap, len)); - } - strcpy(foreign->foreign_table_name_lookup, - foreign->foreign_table_name); - innobase_casedn_str(foreign->foreign_table_name_lookup); + LEX_STRING str= mem_heap_alloc_casedn_z(heap, + system_charset_info, + Lex_cstring_strlen(foreign_table_name)); + foreign_table_name_lookup= str.str; } else { - foreign->foreign_table_name_lookup - = foreign->foreign_table_name; + foreign_table_name_lookup = foreign_table_name; } } @@ -846,27 +834,15 @@ lower_case_table_names. If that is 0 or 1, referenced_table_name_lookup will point to referenced_table_name. If 2, then another string is allocated from foreign->heap and set to lower case. */ void -dict_mem_referenced_table_name_lookup_set( -/*======================================*/ - dict_foreign_t* foreign, /*!< in/out: foreign struct */ - ibool do_alloc) /*!< in: is an alloc needed */ +dict_foreign_t::referenced_table_name_lookup_set() { if (lower_case_table_names == 2) { - if (do_alloc) { - ulint len; - - len = strlen(foreign->referenced_table_name) + 1; - - foreign->referenced_table_name_lookup = - static_cast( - mem_heap_alloc(foreign->heap, len)); - } - strcpy(foreign->referenced_table_name_lookup, - foreign->referenced_table_name); - innobase_casedn_str(foreign->referenced_table_name_lookup); + LEX_STRING str= mem_heap_alloc_casedn_z(heap, + system_charset_info, + Lex_cstring_strlen(referenced_table_name)); + referenced_table_name_lookup = str.str; } else { - foreign->referenced_table_name_lookup - = foreign->referenced_table_name; + referenced_table_name_lookup = referenced_table_name; } } diff --git a/storage/innobase/fts/fts0fts.cc b/storage/innobase/fts/fts0fts.cc index 0775d939002..0c033ef0354 100644 --- a/storage/innobase/fts/fts0fts.cc +++ b/storage/innobase/fts/fts0fts.cc @@ -4427,7 +4427,6 @@ fts_add_token( fts_string_t t_str; fts_token_t* token; ib_rbt_bound_t parent; - ulint newlen; heap = static_cast(result_doc->self_heap->arg); @@ -4443,24 +4442,19 @@ fts_add_token( if (my_binary_compare(result_doc->charset)) { memcpy(t_str.f_str, str.f_str, str.f_len); t_str.f_str[str.f_len]= 0; - newlen= str.f_len; + t_str.f_len= str.f_len; } else { - newlen = innobase_fts_casedn_str( - result_doc->charset, (char*) str.f_str, str.f_len, - (char*) t_str.f_str, t_str.f_len); + t_str.f_len= result_doc->charset->casedn_z( + (const char*) str.f_str, str.f_len, + (char *) t_str.f_str, t_str.f_len); } - t_str.f_len = newlen; - t_str.f_str[newlen] = 0; - /* Add the word to the document statistics. If the word hasn't been seen before we create a new entry for it. */ if (rbt_search(result_doc->tokens, &parent, &t_str) != 0) { fts_token_t new_token; - new_token.text.f_len = newlen; - new_token.text.f_str = t_str.f_str; - new_token.text.f_n_char = t_str.f_n_char; + new_token.text = t_str; new_token.positions = ib_vector_create( result_doc->self_heap, sizeof(ulint), 32); diff --git a/storage/innobase/fts/fts0que.cc b/storage/innobase/fts/fts0que.cc index 9c92a1171cf..825740ea344 100644 --- a/storage/innobase/fts/fts0que.cc +++ b/storage/innobase/fts/fts0que.cc @@ -1641,9 +1641,10 @@ fts_query_match_phrase_terms( token = static_cast( ib_vector_get_const(tokens, i)); - fts_string_dup(&cmp_str, &match, heap); + cmp_str = fts_string_dup_casedn(phrase->charset, + match, heap); - result = innobase_fts_text_case_cmp( + result = innobase_fts_text_cmp( phrase->charset, token, &cmp_str); /* Skip the rest of the tokens if this one doesn't @@ -1797,9 +1798,9 @@ fts_query_match_phrase_add_word_for_parser( token = static_cast( ib_vector_get_const(tokens, phrase_param->token_index)); - fts_string_dup(&cmp_str, &match, heap); + cmp_str = fts_string_dup_casedn(phrase->charset, match, heap); - result = innobase_fts_text_case_cmp( + result = innobase_fts_text_cmp( phrase->charset, token, &cmp_str); if (result == 0) { @@ -1938,9 +1939,10 @@ fts_query_match_phrase( break; } - fts_string_dup(&cmp_str, &match, heap); + cmp_str = fts_string_dup_casedn(phrase->charset, + match, heap); - if (innobase_fts_text_case_cmp( + if (innobase_fts_text_cmp( phrase->charset, first, &cmp_str) == 0) { /* This is the case for the single word @@ -4053,15 +4055,13 @@ fts_query( lc_query_str[query_len]= 0; result_len= query_len; } else { - result_len = innobase_fts_casedn_str( - charset, (char*)( query_str), query_len, - (char*)(lc_query_str), lc_query_str_len); + result_len = charset->casedn_z( + (const char*) query_str, query_len, + (char*) lc_query_str, lc_query_str_len); } ut_ad(result_len < lc_query_str_len); - lc_query_str[result_len] = 0; - query.heap = mem_heap_create(128); /* Create the rb tree for the doc id (current) set. */ diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 147bd180cc8..4461e279530 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -39,6 +39,7 @@ this program; if not, write to the Free Software Foundation, Inc., #include #include #include +#include #include #include #include @@ -1294,18 +1295,19 @@ static void innodb_drop_database(handlerton*, char *path) len++; ptr++; + size_t casedn_nbytes= len * system_charset_info->casedn_multiply(); char *namebuf= static_cast - (my_malloc(PSI_INSTRUMENT_ME, len + 2, MYF(0))); + (my_malloc(PSI_INSTRUMENT_ME, casedn_nbytes + 2, MYF(0))); if (!namebuf) return; +#ifndef _WIN32 memcpy(namebuf, ptr, len); +#else /*_WIN32*/ + len= system_charset_info->casedn(ptr, len, namebuf, casedn_nbytes); +#endif /* _WIN32 */ namebuf[len] = '/'; namebuf[len + 1] = '\0'; -#ifdef _WIN32 - innobase_casedn_str(namebuf); -#endif /* _WIN32 */ - THD * const thd= current_thd; trx_t *trx= innobase_trx_allocate(thd); dberr_t err= DB_SUCCESS; @@ -1904,8 +1906,17 @@ static int innobase_wsrep_set_checkpoint(handlerton *hton, const XID *xid); static int innobase_wsrep_get_checkpoint(handlerton* hton, XID* xid); #endif /* WITH_WSREP */ -#define normalize_table_name(a,b) \ - normalize_table_name_c_low(a,b,IF_WIN(true,false)) + +static inline size_t +normalize_table_name( + char* norm_name, + size_t norm_name_size, + const char* name) +{ + return normalize_table_name_c_low(norm_name, norm_name_size, + name, IF_WIN(true,false)); +} + ulonglong ha_innobase::table_version() const { @@ -1931,7 +1942,7 @@ static int innodb_check_version(handlerton *hton, const char *path, DBUG_RETURN(0); char norm_path[FN_REFLEN]; - normalize_table_name(norm_path, path); + normalize_table_name(norm_path, sizeof(norm_path), path); if (dict_table_t *table= dict_table_open_on_name(norm_path, false, DICT_ERR_IGNORE_NONE)) @@ -2462,16 +2473,6 @@ innobase_basename( return((name) ? name : "null"); } -/******************************************************************//** -Makes all characters in a NUL-terminated UTF-8 string lower case. */ -void -innobase_casedn_str( -/*================*/ - char* a) /*!< in/out: string to put in lower case */ -{ - my_casedn_str(system_charset_info, a); -} - /** Determines the current SQL statement. Thread unsafe, can only be called from the thread owning the THD. @param[in] thd MySQL thread handle @@ -3280,7 +3281,7 @@ innobase_query_caching_of_table_permitted( } /* Normalize the table name to InnoDB format */ - normalize_table_name(norm_name, full_name); + normalize_table_name(norm_name, sizeof(norm_name), full_name); innobase_register_trx(innodb_hton_ptr, thd, trx); @@ -5197,21 +5198,22 @@ table name always to lower case if "set_lower_case" is set to TRUE. @param[out] norm_name Normalized name, null-terminated. @param[in] name Name to normalize. @param[in] set_lower_case True if we also should fold to lower case. */ -void +size_t normalize_table_name_c_low( /*=======================*/ char* norm_name, /* out: normalized name as a null-terminated string */ + size_t norm_name_size, /*!< in: number of bytes available + in norm_name*/ const char* name, /* in: table name string */ bool set_lower_case) /* in: TRUE if we want to set name to lower case */ { - char* name_ptr; + const char* name_ptr; ulint name_len; - char* db_ptr; + const char* db_ptr; ulint db_len; - char* ptr; - ulint norm_len; + const char* ptr; /* Scan name from the end */ @@ -5241,28 +5243,15 @@ normalize_table_name_c_low( } db_ptr = ptr + 1; - - norm_len = db_len + name_len + sizeof "/"; - ut_a(norm_len < FN_REFLEN - 1); - - memcpy(norm_name, db_ptr, db_len); - - norm_name[db_len] = '/'; - - /* Copy the name and null-byte. */ - memcpy(norm_name + db_len + 1, name_ptr, name_len + 1); - - if (set_lower_case) { - innobase_casedn_str(norm_name); - } + return Identifier_chain2({db_ptr, db_len}, {name_ptr, name_len}). + make_sep_name_opt_casedn(norm_name, norm_name_size, '/', + set_lower_case); } create_table_info_t::create_table_info_t( THD* thd, const TABLE* form, HA_CREATE_INFO* create_info, - char* table_name, - char* remote_path, bool file_per_table, trx_t* trx) : m_thd(thd), @@ -5270,11 +5259,12 @@ create_table_info_t::create_table_info_t( m_form(form), m_default_row_format(innodb_default_row_format), m_create_info(create_info), - m_table_name(table_name), m_table(NULL), - m_remote_path(remote_path), + m_table(NULL), m_innodb_file_per_table(file_per_table), m_creating_stub(thd_ddl_options(thd)->import_tablespace()) { + m_table_name[0]= '\0'; + m_remote_path[0]= '\0'; } #if !defined(DBUG_OFF) @@ -5332,7 +5322,7 @@ test_normalize_table_name_low() test_data[i][0], test_data[i][1]); normalize_table_name_c_low( - norm_name, test_data[i][0], FALSE); + norm_name, sizeof(norm_name), test_data[i][0], FALSE); if (strcmp(norm_name, test_data[i][1]) == 0) { printf("ok\n"); @@ -5880,7 +5870,7 @@ ha_innobase::open(const char* name, int, uint) DBUG_ENTER("ha_innobase::open"); - normalize_table_name(norm_name, name); + normalize_table_name(norm_name, sizeof(norm_name), name); m_user_thd = NULL; @@ -6213,15 +6203,17 @@ ha_innobase::open_dict_table( /* Check for the table using lower case name, including the partition separator "P" */ - strcpy(par_case_name, norm_name); - innobase_casedn_str(par_case_name); + system_charset_info->casedn_z( + norm_name, strlen(norm_name), + par_case_name, sizeof(par_case_name)); #else /* On Windows platfrom, check whether there exists table name in system table whose name is not being normalized to lower case */ normalize_table_name_c_low( - par_case_name, table_name, false); + par_case_name, sizeof(par_case_name), + table_name, false); #endif /* FIXME: try_drop_aborted */ ib_table = dict_table_open_on_name( @@ -6437,29 +6429,6 @@ innobase_fts_text_cmp( s2->f_str, static_cast(s2->f_len))); } -/******************************************************************//** -compare two character string case insensitively according to their charset. */ -int -innobase_fts_text_case_cmp( -/*=======================*/ - const void* cs, /*!< in: Character set */ - const void* p1, /*!< in: key */ - const void* p2) /*!< in: node */ -{ - const CHARSET_INFO* charset = (const CHARSET_INFO*) cs; - const fts_string_t* s1 = (const fts_string_t*) p1; - const fts_string_t* s2 = (const fts_string_t*) p2; - ulint newlen; - - my_casedn_str(charset, (char*) s2->f_str); - - newlen = strlen((const char*) s2->f_str); - - return(ha_compare_word(charset, - s1->f_str, static_cast(s1->f_len), - s2->f_str, static_cast(newlen))); -} - /******************************************************************//** Get the first character's code position for FTS index partition. */ ulint @@ -6511,28 +6480,6 @@ innobase_fts_text_cmp_prefix( return(-result); } -/******************************************************************//** -Makes all characters in a string lower case. */ -size_t -innobase_fts_casedn_str( -/*====================*/ - CHARSET_INFO* cs, /*!< in: Character set */ - char* src, /*!< in: string to put in lower case */ - size_t src_len,/*!< in: input string length */ - char* dst, /*!< in: buffer for result string */ - size_t dst_len)/*!< in: buffer size */ -{ - if (cs->casedn_multiply() == 1) { - memcpy(dst, src, src_len); - dst[src_len] = 0; - my_casedn_str(cs, dst); - - return(strlen(dst)); - } else { - return(cs->casedn(src, src_len, dst, dst_len)); - } -} - #define true_word_char(c, ch) ((c) & (_MY_U | _MY_L | _MY_NMR) || (ch) == '_') #define misc_word_char(X) 0 @@ -12079,7 +12026,7 @@ int create_table_info_t::prepare_create_table(const char* name, bool strict) set_tablespace_type(false); - normalize_table_name(m_table_name, name); + normalize_table_name(m_table_name, sizeof(m_table_name), name); /* Validate table options not handled by the SQL-parser */ if (check_table_options()) { @@ -12481,7 +12428,7 @@ create_table_info_t::create_foreign_keys() return (DB_OUT_OF_MEMORY); } - dict_mem_foreign_table_name_lookup_set(foreign, TRUE); + foreign->foreign_table_name_lookup_set(); foreign->foreign_index = index; foreign->n_fields = i & dict_index_t::MAX_N_FIELDS; @@ -12588,7 +12535,7 @@ create_table_info_t::create_foreign_keys() } foreign->referenced_index = index; - dict_mem_referenced_table_name_lookup_set(foreign, TRUE); + foreign->referenced_table_name_lookup_set(); foreign->referenced_col_names = static_cast( mem_heap_alloc(foreign->heap, i * sizeof(void*))); @@ -13203,16 +13150,12 @@ int ha_innobase::create(const char *name, TABLE *form, HA_CREATE_INFO *create_info, bool file_per_table, trx_t *trx= nullptr) { - char norm_name[FN_REFLEN]; /* {database}/{tablename} */ - char remote_path[FN_REFLEN]; /* Absolute path of table */ - DBUG_ENTER("ha_innobase::create"); DBUG_ASSERT(form->s == table_share); DBUG_ASSERT(table_share->table_type == TABLE_TYPE_SEQUENCE || table_share->table_type == TABLE_TYPE_NORMAL); - create_table_info_t info(ha_thd(), form, create_info, norm_name, - remote_path, file_per_table, trx); + create_table_info_t info(ha_thd(), form, create_info, file_per_table, trx); int error= info.initialize(); if (!error) @@ -13435,16 +13378,18 @@ int ha_innobase::delete_table(const char *name) { char norm_name[FN_REFLEN]; - normalize_table_name(norm_name, name); - span n{norm_name, strlen(norm_name)}; + size_t norm_len= normalize_table_name_c_low(norm_name, sizeof(norm_name), + name, IF_WIN(true,false)); + span n{norm_name, norm_len}; dict_sys.lock(SRW_LOCK_CALL); table= dict_sys.load_table(n, DICT_ERR_IGNORE_DROP); #ifdef WITH_PARTITION_STORAGE_ENGINE if (!table && lower_case_table_names == 1 && is_partition(norm_name)) { - IF_WIN(normalize_table_name_c_low(norm_name, name, false), - innobase_casedn_str(norm_name)); + norm_len= normalize_table_name_c_low(norm_name, sizeof(norm_name), + name, IF_WIN(false, true)); + n= {norm_name, norm_len}; table= dict_sys.load_table(n, DICT_ERR_IGNORE_DROP); } #endif @@ -13752,8 +13697,8 @@ static dberr_t innobase_rename_table(trx_t *trx, const char *from, ut_ad(!srv_read_only_mode); - normalize_table_name(norm_to, to); - normalize_table_name(norm_from, from); + normalize_table_name(norm_to, sizeof(norm_to), to); + normalize_table_name(norm_from, sizeof(norm_from), from); DEBUG_SYNC_C("innodb_rename_table_ready"); @@ -13772,15 +13717,17 @@ static dberr_t innobase_rename_table(trx_t *trx, const char *from, /* Check for the table using lower case name, including the partition separator "P" */ - strcpy(par_case_name, norm_from); - innobase_casedn_str(par_case_name); + system_charset_info->casedn_z( + norm_from, strlen(norm_from), + par_case_name, sizeof(par_case_name)); #else /* On Windows platfrom, check whether there exists table name in system table whose name is not being normalized to lower case */ normalize_table_name_c_low( - par_case_name, from, false); + par_case_name, sizeof(par_case_name), + from, false); #endif /* _WIN32 */ trx_start_if_not_started(trx, true); error = row_rename_table_for_mysql( @@ -14091,8 +14038,8 @@ ha_innobase::rename_table( char norm_from[MAX_FULL_NAME_LEN]; char norm_to[MAX_FULL_NAME_LEN]; - normalize_table_name(norm_from, from); - normalize_table_name(norm_to, to); + normalize_table_name(norm_from, sizeof(norm_from), from); + normalize_table_name(norm_to, sizeof(norm_to), to); dberr_t error = DB_SUCCESS; const bool from_temp = dict_table_t::is_temporary_name(norm_from); diff --git a/storage/innobase/handler/ha_innodb.h b/storage/innobase/handler/ha_innodb.h index 914f363720a..eb6960fac8e 100644 --- a/storage/innobase/handler/ha_innodb.h +++ b/storage/innobase/handler/ha_innodb.h @@ -625,8 +625,6 @@ public: THD* thd, const TABLE* form, HA_CREATE_INFO* create_info, - char* table_name, - char* remote_path, bool file_per_table, trx_t* trx = NULL); @@ -740,13 +738,13 @@ private: /** Create options. */ HA_CREATE_INFO* m_create_info; - /** Table name */ - char* m_table_name; + /** Table name: {database}/{tablename} */ + char m_table_name[FN_REFLEN]; /** Table */ dict_table_t* m_table; /** Remote path (DATA DIRECTORY) or zero length-string */ - char* m_remote_path; + char m_remote_path[FN_REFLEN]; // Absolute path of the table /** Local copy of srv_file_per_table. */ bool m_innodb_file_per_table; diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index 4e8e7d26d02..ba974a7a2f8 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -2897,7 +2897,7 @@ innobase_init_foreign( foreign->foreign_table = table; foreign->foreign_table_name = mem_heap_strdup( foreign->heap, table->name.m_name); - dict_mem_foreign_table_name_lookup_set(foreign, TRUE); + foreign->foreign_table_name_lookup_set(); foreign->foreign_index = index; foreign->n_fields = static_cast(num_field) @@ -2916,7 +2916,7 @@ innobase_init_foreign( foreign->referenced_table_name = mem_heap_strdup( foreign->heap, referenced_table_name); - dict_mem_referenced_table_name_lookup_set(foreign, TRUE); + foreign->referenced_table_name_lookup_set(); foreign->referenced_col_names = static_cast( mem_heap_alloc(foreign->heap, @@ -6493,7 +6493,7 @@ prepare_inplace_alter_table_dict( new_clustered = (DICT_CLUSTERED & index_defs[0].ind_type) != 0; create_table_info_t info(ctx->prebuilt->trx->mysql_thd, altered_table, - ha_alter_info->create_info, NULL, NULL, + ha_alter_info->create_info, srv_file_per_table); /* The primary index would be rebuilt if a FTS Doc ID @@ -7904,8 +7904,6 @@ ha_innobase::prepare_inplace_alter_table( create_table_info_t info(m_user_thd, altered_table, ha_alter_info->create_info, - NULL, - NULL, srv_file_per_table); info.set_tablespace_type(indexed_table->space != fil_system.sys_space); diff --git a/storage/innobase/include/dict0mem.h b/storage/innobase/include/dict0mem.h index b06328d7382..37d6fb3c8a5 100644 --- a/storage/innobase/include/dict0mem.h +++ b/storage/innobase/include/dict0mem.h @@ -411,28 +411,6 @@ dict_foreign_t* dict_mem_foreign_create(void); /*=========================*/ -/**********************************************************************//** -Sets the foreign_table_name_lookup pointer based on the value of -lower_case_table_names. If that is 0 or 1, foreign_table_name_lookup -will point to foreign_table_name. If 2, then another string is -allocated from the heap and set to lower case. */ -void -dict_mem_foreign_table_name_lookup_set( -/*===================================*/ - dict_foreign_t* foreign, /*!< in/out: foreign struct */ - ibool do_alloc); /*!< in: is an alloc needed */ - -/**********************************************************************//** -Sets the referenced_table_name_lookup pointer based on the value of -lower_case_table_names. If that is 0 or 1, referenced_table_name_lookup -will point to referenced_table_name. If 2, then another string is -allocated from the heap and set to lower case. */ -void -dict_mem_referenced_table_name_lookup_set( -/*======================================*/ - dict_foreign_t* foreign, /*!< in/out: foreign struct */ - ibool do_alloc); /*!< in: is an alloc needed */ - /** Fills the dependent virtual columns in a set. Reason for being dependent are 1) FK can be present on base column of virtual columns @@ -1522,6 +1500,20 @@ struct dict_foreign_t{ /** Check whether the fulltext index gets affected by foreign key constraint */ bool affects_fulltext() const; + + /**********************************************************************//** + Sets the foreign_table_name_lookup pointer based on the value of + lower_case_table_names. If that is 0 or 1, foreign_table_name_lookup + will point to foreign_table_name. If 2, then another string is + allocated from the heap and set to lower case. */ + void foreign_table_name_lookup_set(); + + /**********************************************************************//** + Sets the referenced_table_name_lookup pointer based on the value of + lower_case_table_names. If that is 0 or 1, referenced_table_name_lookup + will point to referenced_table_name. If 2, then another string is + allocated from the heap and set to lower case. */ + void referenced_table_name_lookup_set(); }; std::ostream& diff --git a/storage/innobase/include/fts0fts.h b/storage/innobase/include/fts0fts.h index c0151b44063..9dbc3235255 100644 --- a/storage/innobase/include/fts0fts.h +++ b/storage/innobase/include/fts0fts.h @@ -737,21 +737,6 @@ innobase_fts_text_cmp( const void* p1, /*!< in: key */ const void* p2); /*!< in: node */ -/******************************************************************//** -Makes all characters in a string lower case. */ -extern -size_t -innobase_fts_casedn_str( -/*====================*/ - CHARSET_INFO* cs, /*!< in: Character set */ - char* src, /*!< in: string to put in - lower case */ - size_t src_len, /*!< in: input string length */ - char* dst, /*!< in: buffer for result - string */ - size_t dst_len); /*!< in: buffer size */ - - /******************************************************************//** compare two character string according to their charset. */ extern diff --git a/storage/innobase/include/fts0types.h b/storage/innobase/include/fts0types.h index fb278d543c4..ef7c99760f8 100644 --- a/storage/innobase/include/fts0types.h +++ b/storage/innobase/include/fts0types.h @@ -329,6 +329,16 @@ fts_string_dup( const fts_string_t* src, /*!< in: src string */ mem_heap_t* heap); /*!< in: heap to use */ +/******************************************************************//** +Duplicate a string with lower case conversion. */ +UNIV_INLINE +fts_string_t +fts_string_dup_casedn( +/*===========*/ + CHARSET_INFO *cs, + const fts_string_t& src, /*!< in: src string */ + mem_heap_t* heap); /*!< in: heap to use */ + /******************************************************************//** Get the selected FTS aux INDEX suffix. */ UNIV_INLINE diff --git a/storage/innobase/include/fts0types.inl b/storage/innobase/include/fts0types.inl index facc1e5c40b..ecec333cdfe 100644 --- a/storage/innobase/include/fts0types.inl +++ b/storage/innobase/include/fts0types.inl @@ -46,6 +46,25 @@ fts_string_dup( dst->f_n_char = src->f_n_char; } +/******************************************************************//** +Duplicate a string with lower case conversion */ +UNIV_INLINE +fts_string_t +fts_string_dup_casedn( +/*===========*/ + CHARSET_INFO *cs, /*!< in: the character set */ + const fts_string_t& src, /*!< in: src string */ + mem_heap_t* heap) /*!< in: heap to use */ +{ + size_t dst_nbytes = src.f_len * cs->casedn_multiply() + 1; + fts_string_t dst; + dst.f_str = (byte*)mem_heap_alloc(heap, dst_nbytes); + dst.f_len = cs->casedn_z((const char *) src.f_str, src.f_len, + (char *) dst.f_str, dst_nbytes); + dst.f_n_char = src.f_n_char; + return dst; +} + /******************************************************************//** Compare two fts_trx_row_t doc_ids. @return < 0 if n1 < n2, 0 if n1 == n2, > 0 if n1 > n2 */ diff --git a/storage/innobase/include/ha_prototypes.h b/storage/innobase/include/ha_prototypes.h index d5239ec3f9a..3c693a1cac5 100644 --- a/storage/innobase/include/ha_prototypes.h +++ b/storage/innobase/include/ha_prototypes.h @@ -175,12 +175,6 @@ innobase_convert_from_id( const char* from, /*!< in: identifier to convert */ ulint len); /*!< in: length of 'to', in bytes; should be at least 3 * strlen(to) + 1 */ -/******************************************************************//** -Makes all characters in a NUL-terminated UTF-8 string lower case. */ -void -innobase_casedn_str( -/*================*/ - char* a); /*!< in/out: string to put in lower case */ #ifdef WITH_WSREP ulint wsrep_innobase_mysql_sort(int mysql_type, uint charset_number, @@ -240,15 +234,6 @@ thd_lock_wait_timeout( THD* thd); /*!< in: thread handle, or NULL to query the global innodb_lock_wait_timeout */ -/******************************************************************//** -compare two character string case insensitively according to their charset. */ -int -innobase_fts_text_case_cmp( -/*=======================*/ - const void* cs, /*!< in: Character set */ - const void* p1, /*!< in: key */ - const void* p2); /*!< in: node */ - /******************************************************************//** Returns true if transaction should be flagged as read-only. @return true if the thd is marked as read-only */ @@ -439,11 +424,13 @@ Normalizes a table name string. A normalized name consists of the database name catenated to '/' and table name. An example: test/mytable. On Windows normalization puts both the database name and the table name always to lower case if "set_lower_case" is set to TRUE. */ -void +size_t normalize_table_name_c_low( /*=======================*/ char* norm_name, /*!< out: normalized name as a null-terminated string */ + size_t norm_name_size, /*!< in: number of bytes available + in norm_name*/ const char* name, /*!< in: table name string */ bool set_lower_case); /*!< in: true if we want to set name to lower case */ diff --git a/storage/innobase/include/mem0mem.h b/storage/innobase/include/mem0mem.h index 959147a61fc..241cbfaf6ed 100644 --- a/storage/innobase/include/mem0mem.h +++ b/storage/innobase/include/mem0mem.h @@ -266,6 +266,24 @@ mem_heap_strdupl(mem_heap_t* heap, const char* str, size_t len) return(static_cast(memcpy(s, str, len))); } +/** Duplicate a string to a memory heap, with lower-case conversion +@param[in] heap memory heap where string is allocated +@param[in] cs the character set of the string +@param[in] str the source string +@return own: a NUL-terminated lower-cased copy of str */ +inline +LEX_STRING +mem_heap_alloc_casedn_z(mem_heap_t *heap, + CHARSET_INFO *cs, + const LEX_CSTRING &str) +{ + size_t nbytes= str.length * cs->casedn_multiply() + 1; + LEX_STRING res; + res.str= static_cast(mem_heap_alloc(heap, nbytes)); + res.length= cs->casedn_z(str.str, str.length, res.str, nbytes); + return res; +} + /**********************************************************************//** Concatenate two strings and return the result, using a memory heap. @return own: the result */ diff --git a/storage/innobase/row/row0ftsort.cc b/storage/innobase/row/row0ftsort.cc index 9d85e2b1b70..80a93116cb4 100644 --- a/storage/innobase/row/row0ftsort.cc +++ b/storage/innobase/row/row0ftsort.cc @@ -472,14 +472,12 @@ row_merge_fts_doc_tokenize( ulint len; row_merge_buf_t* buf; dfield_t* field; - fts_string_t t_str; ibool buf_full = FALSE; - byte str_buf[FTS_MAX_WORD_LEN + 1]; + CharBuffer str_buf; ulint data_size[FTS_NUM_AUX_INDEX]; ulint n_tuple[FTS_NUM_AUX_INDEX]; st_mysql_ftparser* parser; - t_str.f_n_char = 0; t_ctx->buf_used = 0; memset(n_tuple, 0, FTS_NUM_AUX_INDEX * sizeof(ulint)); @@ -544,11 +542,8 @@ row_merge_fts_doc_tokenize( continue; } - t_str.f_len = innobase_fts_casedn_str( - doc->charset, (char*) str.f_str, str.f_len, - (char*) &str_buf, FTS_MAX_WORD_LEN + 1); - - t_str.f_str = (byte*) &str_buf; + str_buf.copy_casedn(doc->charset, + LEX_CSTRING{(const char *) str.f_str, str.f_len}); /* if "cached_stopword" is defined, ignore words in the stopword list */ @@ -566,8 +561,8 @@ row_merge_fts_doc_tokenize( /* There are FTS_NUM_AUX_INDEX auxiliary tables, find out which sort buffer to put this word record in */ - t_ctx->buf_used = fts_select_index( - doc->charset, t_str.f_str, t_str.f_len); + t_ctx->buf_used = fts_select_index(doc->charset, + (const byte*) str_buf.ptr(), str_buf.length()); buf = sort_buf[t_ctx->buf_used]; @@ -581,7 +576,7 @@ row_merge_fts_doc_tokenize( FTS_NUM_FIELDS_SORT * sizeof *field)); /* The first field is the tokenized word */ - dfield_set_data(field, t_str.f_str, t_str.f_len); + dfield_set_data(field, str_buf.ptr(), str_buf.length()); len = dfield_get_len(field); dict_col_copy_type(dict_index_get_nth_col(buf->index, 0), &field->type); diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc index b7ff6ce46dc..417b8672247 100644 --- a/storage/innobase/row/row0mysql.cc +++ b/storage/innobase/row/row0mysql.cc @@ -2595,17 +2595,16 @@ row_rename_table_for_mysql( /* Check for the table using lower case name, including the partition separator "P" */ - memcpy(par_case_name, old_name, - strlen(old_name)); - par_case_name[strlen(old_name)] = 0; - innobase_casedn_str(par_case_name); + system_charset_info->casedn_z( + old_name, strlen(old_name), + par_case_name, sizeof(par_case_name)); #else /* On Windows platfrom, check whether there exists table name in system table whose name is not being normalized to lower case */ normalize_table_name_c_low( - par_case_name, old_name, FALSE); + par_case_name, sizeof(par_case_name), old_name, FALSE); #endif table = dict_table_open_on_name(par_case_name, true, DICT_ERR_IGNORE_FK_NOKEY); diff --git a/storage/maria/aria_ftdump.c b/storage/maria/aria_ftdump.c index 677d0221529..89c8b2fb793 100644 --- a/storage/maria/aria_ftdump.c +++ b/storage/maria/aria_ftdump.c @@ -120,8 +120,9 @@ int main(int argc,char *argv[]) if (subkeys.i >= 0) weight= subkeys.f; - snprintf(buf,MAX_LEN,"%.*s",(int) keylen,info->lastkey_buff+1); - my_casedn_str(default_charset_info,buf); + keylen= (uint) my_ci_casedn(default_charset_info, buf, sizeof(buf) - 1, + (char *) info->lastkey_buff + 1, keylen); + buf[keylen]= '\0'; total++; lengths[keylen]++; diff --git a/storage/myisam/myisam_ftdump.c b/storage/myisam/myisam_ftdump.c index f2dc19c520a..a2e951a8fe2 100644 --- a/storage/myisam/myisam_ftdump.c +++ b/storage/myisam/myisam_ftdump.c @@ -118,8 +118,9 @@ int main(int argc,char *argv[]) if (subkeys.i >= 0) weight= subkeys.f; - snprintf(buf,MAX_LEN,"%.*s",(int) keylen,info->lastkey+1); - my_casedn_str(default_charset_info,buf); + keylen= (uint) my_ci_casedn(default_charset_info, buf, sizeof(buf) - 1, + (char *) info->lastkey + 1, keylen); + buf[keylen]= '\0'; total++; lengths[keylen]++; diff --git a/storage/myisammrg/ha_myisammrg.cc b/storage/myisammrg/ha_myisammrg.cc index b46d0312d31..7087bb1df4b 100644 --- a/storage/myisammrg/ha_myisammrg.cc +++ b/storage/myisammrg/ha_myisammrg.cc @@ -231,13 +231,8 @@ extern "C" int myisammrg_parent_open_callback(void *callback_param, ha_myisammrg *ha_myrg= (ha_myisammrg*) callback_param; TABLE *parent= ha_myrg->table_ptr(); Mrg_child_def *mrg_child_def; - char *db; - char *table_name; - size_t dirlen; - size_t db_length; - size_t table_name_length; + LEX_STRING db, table_name; char dir_path[FN_REFLEN]; - char name_buf[NAME_LEN]; DBUG_ENTER("myisammrg_parent_open_callback"); /* @@ -249,70 +244,51 @@ extern "C" int myisammrg_parent_open_callback(void *callback_param, if (!has_path(filename)) { /* Child is in the same database as parent. */ - db_length= parent->s->db.length; - db= strmake_root(&ha_myrg->children_mem_root, parent->s->db.str, db_length); + db= ha_myrg->make_child_ident(parent->s->db); /* Child table name is encoded in parent dot-MRG starting with 5.1.46. */ - if (parent->s->mysql_version >= 50146) - { - table_name_length= filename_to_tablename(filename, name_buf, - sizeof(name_buf)); - table_name= strmake_root(&ha_myrg->children_mem_root, name_buf, - table_name_length); - } - else - { - table_name_length= strlen(filename); - table_name= strmake_root(&ha_myrg->children_mem_root, filename, - table_name_length); - } + table_name= (parent->s->mysql_version >= 50146) ? + ha_myrg->make_child_ident_filename_to_tablename(filename, + lower_case_table_names) : + ha_myrg->make_child_ident_opt_casedn(Lex_cstring_strlen(filename), + lower_case_table_names); } else { DBUG_ASSERT(strlen(filename) < sizeof(dir_path)); fn_format(dir_path, filename, "", "", 0); /* Extract child table name and database name from filename. */ - dirlen= dirname_length(dir_path); + size_t dirlen= dirname_length(dir_path); /* Child db/table name is encoded in parent dot-MRG starting with 5.1.6. */ if (parent->s->mysql_version >= 50106) { - table_name_length= filename_to_tablename(dir_path + dirlen, name_buf, - sizeof(name_buf)); - table_name= strmake_root(&ha_myrg->children_mem_root, name_buf, - table_name_length); + table_name= ha_myrg->make_child_ident_filename_to_tablename( + dir_path + dirlen, + lower_case_table_names); dir_path[dirlen - 1]= 0; dirlen= dirname_length(dir_path); - db_length= filename_to_tablename(dir_path + dirlen, name_buf, sizeof(name_buf)); - db= strmake_root(&ha_myrg->children_mem_root, name_buf, db_length); + db= ha_myrg->make_child_ident_filename_to_tablename(dir_path + dirlen, + false); } else { - table_name_length= strlen(dir_path + dirlen); - table_name= strmake_root(&ha_myrg->children_mem_root, dir_path + dirlen, - table_name_length); + table_name= ha_myrg->make_child_ident_opt_casedn( + Lex_cstring_strlen(dir_path + dirlen), + lower_case_table_names); dir_path[dirlen - 1]= 0; dirlen= dirname_length(dir_path); - db_length= strlen(dir_path + dirlen); - db= strmake_root(&ha_myrg->children_mem_root, dir_path + dirlen, - db_length); + db= ha_myrg->make_child_ident(Lex_cstring_strlen(dir_path + dirlen)); } } - if (! db || ! table_name) + if (! db.str || ! table_name.str) DBUG_RETURN(1); - DBUG_PRINT("myrg", ("open: '%.*s'.'%.*s'", (int) db_length, db, - (int) table_name_length, table_name)); - - /* Convert to lowercase if required. */ - if (lower_case_table_names && table_name_length) - { - /* purecov: begin tested */ - table_name_length= my_casedn_str(files_charset_info, table_name); - /* purecov: end */ - } + DBUG_PRINT("myrg", ("open: '%.*s'.'%.*s'", (int) db.length, db.str, + (int) table_name.length, table_name.str)); mrg_child_def= new (&ha_myrg->children_mem_root) - Mrg_child_def(db, db_length, table_name, table_name_length); + Mrg_child_def(db.str, db.length, + table_name.str, table_name.length); if (! mrg_child_def || ha_myrg->child_def_list.push_back(mrg_child_def, diff --git a/storage/myisammrg/ha_myisammrg.h b/storage/myisammrg/ha_myisammrg.h index 12189b79dc9..8605ffb70d9 100644 --- a/storage/myisammrg/ha_myisammrg.h +++ b/storage/myisammrg/ha_myisammrg.h @@ -170,4 +170,45 @@ public: int create_mrg(const char *name, HA_CREATE_INFO *create_info); MYRG_INFO *myrg_info() { return file; } TABLE *table_ptr() { return table; } + + /* + Make an exact copy an identifier on children_mem_root. + + @param src - The original identifier + @return - {NULL,0} in case of EOM, + or a non-NULL LEX_STRING with the identifier copy. + */ + LEX_STRING make_child_ident(const LEX_CSTRING &src) + { + return lex_string_strmake_root(&children_mem_root, src.str, src.length); + } + + /* + Make an exact copy or a lower-cased copy of an identifier + on children mem_root. + + @param src - The original identifier + @param casedn - If the name should be converted to lower case + @return - {NULL,0} in case of EOM, + or a non-NULL LEX_STRING with the identifier copy. + */ + LEX_STRING make_child_ident_opt_casedn(const LEX_CSTRING &src, bool casedn) + { + return casedn ? lex_string_casedn_root(&children_mem_root, + &my_charset_utf8mb3_general_ci, + src.str, src.length) : + make_child_ident(src); + } + + /* + Make an optionally lower-cases filename_to_tablename-decoded identifier + in chirdren mem_root. + */ + LEX_STRING make_child_ident_filename_to_tablename(const char *src, + bool casedn) + { + char buf[NAME_LEN]; + size_t len= filename_to_tablename(src, buf, sizeof(buf)); + return make_child_ident_opt_casedn({buf, len}, casedn); + } }; diff --git a/storage/perfschema/pfs_instr_class.cc b/storage/perfschema/pfs_instr_class.cc index 2b1a80d3e11..1300a81b1d0 100644 --- a/storage/perfschema/pfs_instr_class.cc +++ b/storage/perfschema/pfs_instr_class.cc @@ -466,36 +466,22 @@ LF_PINS* get_table_share_hash_pins(PFS_thread *thread) @param table_name The table name. @param table_name_length The table name length. */ -static void set_table_share_key(PFS_table_share_key *key, - bool temporary, - const char *schema_name, size_t schema_name_length, - const char *table_name, size_t table_name_length) +void PFS_table_share_key::set(bool temporary, + const char *schema_name, + size_t schema_name_length, + const char *table_name, + size_t table_name_length) { assert(schema_name_length <= NAME_LEN); assert(table_name_length <= NAME_LEN); - char *saved_schema_name; - char *saved_table_name; - char *ptr= &key->m_hash_key[0]; - ptr[0]= (temporary ? OBJECT_TYPE_TEMPORARY_TABLE : OBJECT_TYPE_TABLE); - ptr++; - saved_schema_name= ptr; - memcpy(ptr, schema_name, schema_name_length); - ptr+= schema_name_length; - ptr[0]= 0; - ptr++; - saved_table_name= ptr; - memcpy(ptr, table_name, table_name_length); - ptr+= table_name_length; - ptr[0]= 0; - ptr++; - key->m_key_length= (uint)(ptr - &key->m_hash_key[0]); + m_hash_key[0]= (temporary ? OBJECT_TYPE_TEMPORARY_TABLE : OBJECT_TYPE_TABLE); + m_key_length= 1; - if (lower_case_table_names) - { - my_casedn_str(files_charset_info, saved_schema_name); - my_casedn_str(files_charset_info, saved_table_name); - } + append_opt_casedn_z(files_charset_info, schema_name, schema_name_length, + lower_case_table_names); + append_opt_casedn_z(files_charset_info, table_name, table_name_length, + lower_case_table_names); } /** @@ -1740,9 +1726,8 @@ PFS_table_share* find_or_create_table_share(PFS_thread *thread, const char *table_name= share->table_name.str; size_t table_name_length= share->table_name.length; - set_table_share_key(&key, temporary, - schema_name, schema_name_length, - table_name, table_name_length); + key.set(temporary, schema_name, schema_name_length, + table_name, table_name_length); PFS_table_share **entry; uint retry_count= 0; @@ -1953,8 +1938,8 @@ void drop_table_share(PFS_thread *thread, LF_PINS* pins= get_table_share_hash_pins(thread); if (unlikely(pins == NULL)) return; - set_table_share_key(&key, temporary, schema_name, schema_name_length, - table_name, table_name_length); + key.set(temporary, schema_name, schema_name_length, + table_name, table_name_length); PFS_table_share **entry; entry= reinterpret_cast (lf_hash_search(&table_share_hash, pins, diff --git a/storage/perfschema/pfs_instr_class.h b/storage/perfschema/pfs_instr_class.h index f353c410d4c..6f39e75beff 100644 --- a/storage/perfschema/pfs_instr_class.h +++ b/storage/perfschema/pfs_instr_class.h @@ -265,6 +265,46 @@ struct PFS_table_share_key char m_hash_key[PFS_TABLESHARE_HASHKEY_SIZE]; /** Length in bytes of @c m_hash_key. */ uint m_key_length; + + size_t available_length() const + { + return sizeof(m_hash_key) - m_key_length; + } + + char *end() + { + return m_hash_key + m_key_length; + } + + void set(bool temporary, + const char *schema_name, size_t schema_name_length, + const char *table_name, size_t table_name_length); + +private: + // Append and 0-terminate a string with an optional lower-case conversion + void append_opt_casedn_z(CHARSET_INFO *cs, + const char *str, size_t length, + bool casedn) + { + DBUG_ASSERT(length <= sizeof(m_hash_key)); // Expect valid db/tbl names + size_t dst_length= available_length(); + if (dst_length > 0) + { + dst_length--; + DBUG_ASSERT(dst_length >= length); + if (casedn) + { + m_key_length+= (uint) cs->casedn(str, length, end(), dst_length); + } + else + { + set_if_smaller(length, dst_length); // Safety for release builds + memcpy(end(), str, length); + m_key_length+= (uint) length; + } + m_hash_key[m_key_length++]= '\0'; + } + } }; /** Table index or 'key' */ diff --git a/storage/perfschema/pfs_program.cc b/storage/perfschema/pfs_program.cc index de456610519..f3734cb383b 100644 --- a/storage/perfschema/pfs_program.cc +++ b/storage/perfschema/pfs_program.cc @@ -118,31 +118,21 @@ static void set_program_key(PFS_program_key *key, */ char *ptr= &key->m_hash_key[0]; + const char *end= ptr + sizeof(key->m_hash_key) - 1; ptr[0]= object_type; ptr++; if (object_name_length > 0) - { - char tmp_object_name[COL_OBJECT_NAME_SIZE + 1]; - memcpy(tmp_object_name, object_name, object_name_length); - tmp_object_name[object_name_length]= '\0'; - my_casedn_str(system_charset_info, tmp_object_name); - memcpy(ptr, tmp_object_name, object_name_length); - ptr+= object_name_length; - } + ptr+= system_charset_info->casedn(object_name, object_name_length, + ptr, end - ptr); ptr[0]= 0; ptr++; if (schema_name_length > 0) - { - char tmp_schema_name[COL_OBJECT_SCHEMA_SIZE + 1]; - memcpy(tmp_schema_name, schema_name, schema_name_length); - tmp_schema_name[schema_name_length]='\0'; - my_casedn_str(system_charset_info, tmp_schema_name); - memcpy(ptr, tmp_schema_name, schema_name_length); - ptr+= schema_name_length; - } + ptr+= system_charset_info->opt_casedn(schema_name, schema_name_length, + ptr, end - ptr, + lower_case_table_names); ptr[0]= 0; ptr++; diff --git a/storage/perfschema/unittest/pfs_instr_class-oom-t.cc b/storage/perfschema/unittest/pfs_instr_class-oom-t.cc index b7c17d06bae..4a68ad48c0d 100644 --- a/storage/perfschema/unittest/pfs_instr_class-oom-t.cc +++ b/storage/perfschema/unittest/pfs_instr_class-oom-t.cc @@ -40,6 +40,8 @@ void test_oom() PFS_thread pfs_thread; PFS_table_share *pfs_table_share; + files_charset_info= &my_charset_utf8mb3_general_ci; + rc= init_sync_class(1000, 0, 0); ok(rc == 1, "oom (mutex)"); rc= init_sync_class(0, 1000, 0); diff --git a/strings/CHARSET_INFO.txt b/strings/CHARSET_INFO.txt index 922a372495b..a1591ac5e88 100644 --- a/strings/CHARSET_INFO.txt +++ b/strings/CHARSET_INFO.txt @@ -225,8 +225,6 @@ mc_mb - converts the given Unicode code into multi-byte sequence. Case and sort conversion ------------------------ -caseup_str - converts the given 0-terminated string to uppercase -casedn_str - converts the given 0-terminated string to lowercase caseup - converts the given string to lowercase using length casedn - converts the given string to lowercase using length diff --git a/strings/ctype-big5.c b/strings/ctype-big5.c index aaf6769989b..c74e88c3b73 100644 --- a/strings/ctype-big5.c +++ b/strings/ctype-big5.c @@ -6807,8 +6807,6 @@ static MY_CHARSET_HANDLER my_charset_big5_handler= my_mb_wc_big5, /* mb_wc */ my_wc_mb_big5, /* wc_mb */ my_mb_ctype_mb, - my_caseup_str_mb, - my_casedn_str_mb, my_caseup_mb, my_casedn_mb, my_snprintf_8bit, diff --git a/strings/ctype-bin.c b/strings/ctype-bin.c index 81593e837e8..2c6dddff78c 100644 --- a/strings/ctype-bin.c +++ b/strings/ctype-bin.c @@ -236,15 +236,6 @@ static int my_strnncollsp_8bit_nopad_bin(CHARSET_INFO * cs } -/* This function is used for all conversion functions */ - -static size_t my_case_str_bin(CHARSET_INFO *cs __attribute__((unused)), - char *str __attribute__((unused))) -{ - return 0; -} - - static size_t my_case_bin(CHARSET_INFO *cs __attribute__((unused)), const char *src, size_t srclen, char *dst, size_t dstlen __attribute__((unused))) @@ -583,8 +574,6 @@ static MY_CHARSET_HANDLER my_charset_handler= my_mb_wc_bin, my_wc_mb_bin, my_mb_ctype_8bit, - my_case_str_bin, - my_case_str_bin, my_case_bin, my_case_bin, my_snprintf_8bit, diff --git a/strings/ctype-cp932.c b/strings/ctype-cp932.c index f01909d4f65..0767f7db91f 100644 --- a/strings/ctype-cp932.c +++ b/strings/ctype-cp932.c @@ -34764,8 +34764,6 @@ static MY_CHARSET_HANDLER my_charset_handler= my_mb_wc_cp932, /* mb_wc */ my_wc_mb_cp932, /* wc_mb */ my_mb_ctype_mb, - my_caseup_str_mb, - my_casedn_str_mb, my_caseup_mb, my_casedn_mb, my_snprintf_8bit, diff --git a/strings/ctype-euc_kr.c b/strings/ctype-euc_kr.c index dd6ab60bd3a..51bbb589dad 100644 --- a/strings/ctype-euc_kr.c +++ b/strings/ctype-euc_kr.c @@ -10054,8 +10054,6 @@ static MY_CHARSET_HANDLER my_charset_handler= my_mb_wc_euc_kr, /* mb_wc */ my_wc_mb_euc_kr, /* wc_mb */ my_mb_ctype_mb, - my_caseup_str_mb, - my_casedn_str_mb, my_caseup_mb, /* UPPER() can reduce length: Turkish DOTLESS i -> I */ my_casedn_mb, /* LOWER() does not change length */ my_snprintf_8bit, diff --git a/strings/ctype-eucjpms.c b/strings/ctype-eucjpms.c index a5f727551aa..6e0045366da 100644 --- a/strings/ctype-eucjpms.c +++ b/strings/ctype-eucjpms.c @@ -67592,8 +67592,6 @@ static MY_CHARSET_HANDLER my_charset_handler= my_mb_wc_eucjpms, /* mb_wc */ my_wc_mb_eucjpms, /* wc_mb */ my_mb_ctype_mb, - my_caseup_str_mb, - my_casedn_str_mb, my_caseup_ujis, my_casedn_ujis, my_snprintf_8bit, diff --git a/strings/ctype-gb2312.c b/strings/ctype-gb2312.c index f3e9c902389..c474ec390ea 100644 --- a/strings/ctype-gb2312.c +++ b/strings/ctype-gb2312.c @@ -6458,8 +6458,6 @@ static MY_CHARSET_HANDLER my_charset_handler= my_mb_wc_gb2312, /* mb_wc */ my_wc_mb_gb2312, /* wc_mb */ my_mb_ctype_mb, - my_caseup_str_mb, - my_casedn_str_mb, my_caseup_mb, my_casedn_mb, my_snprintf_8bit, diff --git a/strings/ctype-gbk.c b/strings/ctype-gbk.c index a22e6aa8d84..b1f53999402 100644 --- a/strings/ctype-gbk.c +++ b/strings/ctype-gbk.c @@ -10739,8 +10739,6 @@ static MY_CHARSET_HANDLER my_charset_handler= my_mb_wc_gbk, my_wc_mb_gbk, my_mb_ctype_mb, - my_caseup_str_mb, - my_casedn_str_mb, my_caseup_mb, my_casedn_mb, my_snprintf_8bit, diff --git a/strings/ctype-latin1.c b/strings/ctype-latin1.c index 5d763c6a561..0488aaebe67 100644 --- a/strings/ctype-latin1.c +++ b/strings/ctype-latin1.c @@ -407,8 +407,6 @@ static MY_CHARSET_HANDLER my_charset_handler= my_mb_wc_latin1, my_wc_mb_latin1, my_mb_ctype_8bit, - my_caseup_str_8bit, - my_casedn_str_8bit, my_caseup_8bit, my_casedn_8bit, my_snprintf_8bit, diff --git a/strings/ctype-mb.c b/strings/ctype-mb.c index 88dd36312ea..2711b089582 100644 --- a/strings/ctype-mb.c +++ b/strings/ctype-mb.c @@ -21,48 +21,6 @@ #ifdef USE_MB -size_t my_caseup_str_mb(CHARSET_INFO * cs, char *str) -{ - register uint32 l; - register const uchar *map= cs->to_upper; - char *str_orig= str; - - while (*str) - { - /* Pointing after the '\0' is safe here. */ - if ((l= my_ismbchar(cs, str, str + cs->mbmaxlen))) - str+= l; - else - { - *str= (char) map[(uchar)*str]; - str++; - } - } - return (size_t) (str - str_orig); -} - - -size_t my_casedn_str_mb(CHARSET_INFO * cs, char *str) -{ - register uint32 l; - register const uchar *map= cs->to_lower; - char *str_orig= str; - - while (*str) - { - /* Pointing after the '\0' is safe here. */ - if ((l= my_ismbchar(cs, str, str + cs->mbmaxlen))) - str+= l; - else - { - *str= (char) map[(uchar)*str]; - str++; - } - } - return (size_t) (str - str_orig); -} - - static inline const MY_CASEFOLD_CHARACTER* get_case_info_for_ch(CHARSET_INFO *cs, uint page, uint offs) { diff --git a/strings/ctype-simple.c b/strings/ctype-simple.c index 83a366028ca..a77139139e5 100644 --- a/strings/ctype-simple.c +++ b/strings/ctype-simple.c @@ -2143,8 +2143,6 @@ MY_CHARSET_HANDLER my_charset_8bit_handler= my_mb_wc_8bit, my_wc_mb_8bit, my_mb_ctype_8bit, - my_caseup_str_8bit, - my_casedn_str_8bit, my_caseup_8bit, my_casedn_8bit, my_snprintf_8bit, diff --git a/strings/ctype-sjis.c b/strings/ctype-sjis.c index a5fed41b964..807c2fa7bcd 100644 --- a/strings/ctype-sjis.c +++ b/strings/ctype-sjis.c @@ -34152,8 +34152,6 @@ static MY_CHARSET_HANDLER my_charset_handler= my_mb_wc_sjis, /* mb_wc */ my_wc_mb_sjis, /* wc_mb */ my_mb_ctype_mb, - my_caseup_str_mb, - my_casedn_str_mb, my_caseup_mb, my_casedn_mb, my_snprintf_8bit, diff --git a/strings/ctype-tis620.c b/strings/ctype-tis620.c index 0b728346f6a..f6a2dd30819 100644 --- a/strings/ctype-tis620.c +++ b/strings/ctype-tis620.c @@ -914,8 +914,6 @@ static MY_CHARSET_HANDLER my_charset_handler= my_mb_wc_tis620, /* mb_wc */ my_wc_mb_tis620, /* wc_mb */ my_mb_ctype_8bit, - my_caseup_str_8bit, - my_casedn_str_8bit, my_caseup_8bit, my_casedn_8bit, my_snprintf_8bit, diff --git a/strings/ctype-ucs2.c b/strings/ctype-ucs2.c index 8637f6406e7..c8da32a87af 100644 --- a/strings/ctype-ucs2.c +++ b/strings/ctype-ucs2.c @@ -55,23 +55,6 @@ static unsigned long lfactor[9]= #ifdef HAVE_CHARSET_mb2_or_mb4 -static size_t -my_caseup_str_mb2_or_mb4(CHARSET_INFO * cs __attribute__((unused)), - char * s __attribute__((unused))) -{ - DBUG_ASSERT(0); - return 0; -} - - -static size_t -my_casedn_str_mb2_or_mb4(CHARSET_INFO *cs __attribute__((unused)), - char * s __attribute__((unused))) -{ - DBUG_ASSERT(0); - return 0; -} - static int my_strcasecmp_mb2_or_mb4(CHARSET_INFO *cs __attribute__((unused)), @@ -1567,8 +1550,6 @@ MY_CHARSET_HANDLER my_charset_utf16_handler= my_utf16_uni, /* mb_wc */ my_uni_utf16, /* wc_mb */ my_mb_ctype_mb, - my_caseup_str_mb2_or_mb4, - my_casedn_str_mb2_or_mb4, my_caseup_utf16, my_casedn_utf16, my_snprintf_mb2, @@ -1920,8 +1901,6 @@ static MY_CHARSET_HANDLER my_charset_utf16le_handler= my_utf16le_uni, /* mb_wc */ my_uni_utf16le, /* wc_mb */ my_mb_ctype_mb, - my_caseup_str_mb2_or_mb4, - my_casedn_str_mb2_or_mb4, my_caseup_utf16, my_casedn_utf16, my_snprintf_mb2, @@ -2719,8 +2698,6 @@ MY_CHARSET_HANDLER my_charset_utf32_handler= my_utf32_uni, my_uni_utf32, my_mb_ctype_mb, - my_caseup_str_mb2_or_mb4, - my_casedn_str_mb2_or_mb4, my_caseup_utf32, my_casedn_utf32, my_snprintf_utf32, @@ -3334,8 +3311,6 @@ MY_CHARSET_HANDLER my_charset_ucs2_handler= my_ucs2_uni, /* mb_wc */ my_uni_ucs2, /* wc_mb */ my_mb_ctype_mb, - my_caseup_str_mb2_or_mb4, - my_casedn_str_mb2_or_mb4, my_caseup_ucs2, my_casedn_ucs2, my_snprintf_mb2, diff --git a/strings/ctype-ujis.c b/strings/ctype-ujis.c index a5624a8c341..06b3d307530 100644 --- a/strings/ctype-ujis.c +++ b/strings/ctype-ujis.c @@ -67336,8 +67336,6 @@ static MY_CHARSET_HANDLER my_charset_handler= my_mb_wc_euc_jp, /* mb_wc */ my_wc_mb_euc_jp, /* wc_mb */ my_mb_ctype_mb, - my_caseup_str_mb, - my_casedn_str_mb, my_caseup_ujis, my_casedn_ujis, my_snprintf_8bit, diff --git a/strings/ctype-utf8.c b/strings/ctype-utf8.c index b7bdd0e98b0..d4a5c5be0d8 100644 --- a/strings/ctype-utf8.c +++ b/strings/ctype-utf8.c @@ -565,46 +565,6 @@ static int my_utf8mb3_uni(CHARSET_INFO *cs __attribute__((unused)), } -/* - The same as above, but without range check - for example, for a null-terminated string -*/ -static int my_utf8mb3_uni_no_range(CHARSET_INFO *cs __attribute__((unused)), - my_wc_t * pwc, const uchar *s) -{ - uchar c; - - c= s[0]; - if (c < 0x80) - { - *pwc = c; - return 1; - } - - if (c < 0xc2) - return MY_CS_ILSEQ; - - if (c < 0xe0) - { - if (!((s[1] ^ 0x80) < 0x40)) - return MY_CS_ILSEQ; - - *pwc= UTF8MB2_CODE(c, s[1]); - return 2; - } - - if (c < 0xf0) - { - if (!IS_UTF8MB3_STEP2(c, s[1], s[2])) - return MY_CS_ILSEQ; - - *pwc= UTF8MB3_CODE(c, s[1], s[2]); - return 3; - } - return MY_CS_ILSEQ; -} - - static int my_uni_utf8mb3(CHARSET_INFO *cs __attribute__((unused)), my_wc_t wc, uchar *r, uchar *e) { @@ -638,35 +598,6 @@ static int my_uni_utf8mb3(CHARSET_INFO *cs __attribute__((unused)), } -/* - The same as above, but without range check. -*/ -static int my_uni_utf8mb3_no_range(CHARSET_INFO *cs __attribute__((unused)), - my_wc_t wc, uchar *r) -{ - int count; - - if (wc < 0x80) - count= 1; - else if (wc < 0x800) - count= 2; - else if (wc < 0x10000) - count= 3; - else - return MY_CS_ILUNI; - - switch (count) - { - case 3: r[2]= (uchar) (0x80 | (wc & 0x3f)); wc= wc >> 6; wc |= 0x800; - /* fall through */ - case 2: r[1]= (uchar) (0x80 | (wc & 0x3f)); wc= wc >> 6; wc |= 0xc0; - /* fall through */ - case 1: r[0]= (uchar) wc; - } - return count; -} - - static size_t my_caseup_utf8mb3(CHARSET_INFO *cs, const char *src, size_t srclen, char *dst, size_t dstlen) @@ -723,28 +654,6 @@ static void my_hash_sort_utf8mb3(CHARSET_INFO *cs, const uchar *s, size_t slen, } -static size_t my_caseup_str_utf8mb3(CHARSET_INFO *cs, char *src) -{ - my_wc_t wc; - int srcres, dstres; - char *dst= src, *dst0= src; - MY_CASEFOLD_INFO *uni_plane= cs->casefold; - DBUG_ASSERT(cs->cset->caseup_multiply(cs) == 1); - - while (*src && - (srcres= my_utf8mb3_uni_no_range(cs, &wc, (uchar *) src)) > 0) - { - my_toupper_unicode_bmp(uni_plane, &wc); - if ((dstres= my_uni_utf8mb3_no_range(cs, wc, (uchar*) dst)) <= 0) - break; - src+= srcres; - dst+= dstres; - } - *dst= '\0'; - return (size_t) (dst - dst0); -} - - static size_t my_casedn_utf8mb3(CHARSET_INFO *cs, const char *src, size_t srclen, char *dst, size_t dstlen) @@ -769,44 +678,6 @@ static size_t my_casedn_utf8mb3(CHARSET_INFO *cs, } -static size_t my_casedn_str_utf8mb3(CHARSET_INFO *cs, char *src) -{ - my_wc_t wc; - int srcres, dstres; - char *dst= src, *dst0= src; - MY_CASEFOLD_INFO *uni_plane= cs->casefold; - DBUG_ASSERT(cs->cset->casedn_multiply(cs) == 1); - - while (*src && - (srcres= my_utf8mb3_uni_no_range(cs, &wc, (uchar *) src)) > 0) - { - my_tolower_unicode_bmp(uni_plane, &wc); - if ((dstres= my_uni_utf8mb3_no_range(cs, wc, (uchar*) dst)) <= 0) - break; - src+= srcres; - dst+= dstres; - } - - /* - In rare cases lower string can be shorter than - the original string, for example: - - "U+0130 LATIN CAPITAL LETTER I WITH DOT ABOVE" - (which is 0xC4B0 in utf8mb3, i.e. two bytes) - - is converted into - - "U+0069 LATIN SMALL LETTER I" - (which is 0x69 in utf8mb3, i.e. one byte) - - So, we need to put '\0' terminator after converting. - */ - - *dst= '\0'; - return (size_t) (dst - dst0); -} - - /* Compare 0-terminated UTF8 strings. @@ -1213,8 +1084,6 @@ MY_CHARSET_HANDLER my_charset_utf8mb3_handler= my_utf8mb3_uni, my_uni_utf8mb3, my_mb_ctype_mb, - my_caseup_str_utf8mb3, - my_casedn_str_utf8mb3, my_caseup_utf8mb3, my_casedn_utf8mb3, my_snprintf_8bit, @@ -2857,8 +2726,6 @@ static MY_CHARSET_HANDLER my_charset_filename_handler= my_mb_wc_filename, my_wc_mb_filename, my_mb_ctype_mb, - my_caseup_str_utf8mb3, - my_casedn_str_utf8mb3, my_caseup_utf8mb3, my_casedn_utf8mb3, my_snprintf_8bit, @@ -3081,40 +2948,6 @@ my_wc_mb_utf8mb4(CHARSET_INFO *cs __attribute__((unused)), } -/* - The same as above, but without range check. -*/ -static int -my_wc_mb_utf8mb4_no_range(CHARSET_INFO *cs __attribute__((unused)), - my_wc_t wc, uchar *r) -{ - int count; - - if (wc < 0x80) - count= 1; - else if (wc < 0x800) - count= 2; - else if (wc < 0x10000) - count= 3; - else if (wc < 0x200000) - count= 4; - else - return MY_CS_ILUNI; - - switch (count) - { - case 4: r[3]= (uchar) (0x80 | (wc & 0x3f)); wc= wc >> 6; wc |= 0x10000; - /* fall through */ - case 3: r[2]= (uchar) (0x80 | (wc & 0x3f)); wc= wc >> 6; wc |= 0x800; - /* fall through */ - case 2: r[1]= (uchar) (0x80 | (wc & 0x3f)); wc= wc >> 6; wc |= 0xc0; - /* fall through */ - case 1: r[0]= (uchar) wc; - } - return count; -} - - static size_t my_caseup_utf8mb4(CHARSET_INFO *cs, const char *src, size_t srclen, char *dst, size_t dstlen) @@ -3185,29 +3018,6 @@ my_hash_sort_utf8mb4(CHARSET_INFO *cs, const uchar *s, size_t slen, } -static size_t -my_caseup_str_utf8mb4(CHARSET_INFO *cs, char *src) -{ - my_wc_t wc; - int srcres, dstres; - char *dst= src, *dst0= src; - MY_CASEFOLD_INFO *uni_plane= cs->casefold; - DBUG_ASSERT(cs->cset->caseup_multiply(cs) == 1); - - while (*src && - (srcres= my_mb_wc_utf8mb4_no_range(cs, &wc, (uchar *) src)) > 0) - { - my_toupper_unicode(uni_plane, &wc); - if ((dstres= my_wc_mb_utf8mb4_no_range(cs, wc, (uchar*) dst)) <= 0) - break; - src+= srcres; - dst+= dstres; - } - *dst= '\0'; - return (size_t) (dst - dst0); -} - - static size_t my_casedn_utf8mb4(CHARSET_INFO *cs, const char *src, size_t srclen, @@ -3234,45 +3044,6 @@ my_casedn_utf8mb4(CHARSET_INFO *cs, } -static size_t -my_casedn_str_utf8mb4(CHARSET_INFO *cs, char *src) -{ - my_wc_t wc; - int srcres, dstres; - char *dst= src, *dst0= src; - MY_CASEFOLD_INFO *uni_plane= cs->casefold; - DBUG_ASSERT(cs->cset->casedn_multiply(cs) == 1); - - while (*src && - (srcres= my_mb_wc_utf8mb4_no_range(cs, &wc, (uchar *) src)) > 0) - { - my_tolower_unicode(uni_plane, &wc); - if ((dstres= my_wc_mb_utf8mb4_no_range(cs, wc, (uchar*) dst)) <= 0) - break; - src+= srcres; - dst+= dstres; - } - - /* - In rare cases lower string can be shorter than - the original string, for example: - - "U+0130 LATIN CAPITAL LETTER I WITH DOT ABOVE" - (which is 0xC4B0 in utf8mb3, i.e. two bytes) - - is converted into - - "U+0069 LATIN SMALL LETTER I" - (which is 0x69 in utf8mb3, i.e. one byte) - - So, we need to put '\0' terminator after converting. - */ - - *dst= '\0'; - return (size_t) (dst - dst0); -} - - /** Compare 0-terminated UTF8 strings. @@ -3544,8 +3315,6 @@ MY_CHARSET_HANDLER my_charset_utf8mb4_handler= my_mb_wc_utf8mb4, my_wc_mb_utf8mb4, my_mb_ctype_mb, - my_caseup_str_utf8mb4, - my_casedn_str_utf8mb4, my_caseup_utf8mb4, my_casedn_utf8mb4, my_snprintf_8bit, diff --git a/strings/string.doc b/strings/string.doc index 4050f6afb66..fc5153eb693 100644 --- a/strings/string.doc +++ b/strings/string.doc @@ -133,8 +133,6 @@ I mysys: void caseup _A((string str,uint length)); void casedn _A((string str,uint length)); - void caseup_str _A((string str)); - void casedn_str _A((string str)); Converts strings or part of string to upper or lower-case. void case_sort _A((string str,uint length));