diff --git a/mysql-test/main/vector2.result b/mysql-test/main/vector2.result index 5dbe71c8adf1b..850347dbd38c4 100644 --- a/mysql-test/main/vector2.result +++ b/mysql-test/main/vector2.result @@ -160,7 +160,7 @@ drop table t; # MDEV-35141 Server crashes in Field_vector::report_wrong_value upon statistic collection # create table t1 (v vector(64) not null); -insert into t1 select vec_fromtext(concat('[',group_concat(1),']')) from seq_1_to_64; +insert into t1 select vec_fromtext(cast(concat('[',group_concat(1),']') as char(130))) from seq_1_to_64; analyze table t1 persistent for all; Table Op Msg_type Msg_text test.t1 analyze status Engine-independent statistics collected @@ -565,4 +565,129 @@ tmp CREATE TABLE `tmp` ( c drop table tmp, t1, t2; set sql_mode=@old_sql_mode; +# +# MDEV-40486 ER_TOO_BIG_FIELDLENGTH or assertion failure upon creating vector from blob +# +## Original testcase +CREATE TABLE t (a TEXT) AS SELECT '[1]' AS a; +CREATE TABLE tt AS SELECT VEC_FROMTEXT(a) AS f FROM t; +ERROR 42000: Column length too big for column 'f' (max = 16383); use BLOB or TEXT instead +DROP TABLE t; +## Another case, which would have failed with ERROR 1292 +## without the fix +CREATE TABLE t SELECT VEC_FROMTEXT('[1]'); +DROP TABLE t; +## Conversion from max varchar length +CREATE TABLE t (a VARCHAR(16383)) AS +SELECT concat('[1', repeat(',1', 8190), ']') AS a; +CREATE TABLE tt AS SELECT VEC_FROMTEXT(a) AS f FROM t; +DROP TABLE t,tt; +## Conversion to max vector dimension +CREATE TABLE tt AS +SELECT VEC_FROMTEXT(concat('[1', repeat(',1', 16382), ']')) AS f; +DROP TABLE tt; +CREATE TABLE tt AS +SELECT VEC_FROMTEXT(concat('[1', repeat(',1', 16383), ']')) AS f; +ERROR 42000: Column length too big for column 'f' (max = 16383); use BLOB or TEXT instead +## "Zero-dimensional" argument, no change in behaviour after fix +SELECT VEC_FROMTEXT('[]') as f; +f + +CREATE TABLE t1 SELECT VEC_FROMTEXT('[]'); +ERROR 22007: Incorrect vector value: '' for column `test`.`t1`.`VEC_FROMTEXT('[]')` at row 1 +## Zero length: no underflow +SELECT VEC_FROMTEXT('') AS f; +f +NULL +Warnings: +Warning 4037 Unexpected end of JSON text in argument 1 to function 'VEC_FromText' +CREATE TABLE tt AS SELECT VEC_FROMTEXT('') AS f; +ERROR HY000: Unexpected end of JSON text in argument 1 to function 'VEC_FromText' +CREATE TABLE t1 (a CHAR(1)); +CREATE TABLE t2 AS SELECT VEC_FROMTEXT(a) AS f FROM t1; +show create table t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `f` vector(1) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci +DROP TABLE t1, t2; +CREATE TABLE t1 (a CHAR(2)); +CREATE TABLE t2 AS SELECT VEC_FROMTEXT(a) AS f FROM t1; +show create table t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `f` vector(1) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci +DROP TABLE t1, t2; +CREATE TABLE t3 (f VECTOR(0)); +ERROR 42000: Incorrect column specifier for column 'f' +## Fails because concat('[',group_concat(1),']') is mediumblob +create view v1 as select vec_fromtext(concat('[',group_concat(1),']')) from seq_1_to_64; +ERROR 42000: Column length too big for column 'vec_fromtext(concat('[',group_concat(1),']'))' (max = 16383); use BLOB or TEXT instead +## NULLs +select vec_fromtext(NULL); +vec_fromtext(NULL) +NULL +select vec_fromtext(NULL + NULL); +vec_fromtext(NULL + NULL) +NULL +create table t1 select vec_fromtext(NULL) as c; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c` vector(1) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci +DROP TABLE t1; +create table t1 select vec_fromtext(NULL + NULL) as c; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c` vector(8) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci +drop table t1; +create table t1 select vec_fromtext(c) from (select '[1,2]' as c) d; +DROP TABLE t1; +create table t1 select vec_fromtext(c) from (select '' as c) d; +ERROR HY000: Unexpected end of JSON text in argument 1 to function 'VEC_FromText' +create table t1 select vec_fromtext(c) from (select NULL as c) d; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `vec_fromtext(c)` vector(1) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci +DROP TABLE t1; +create table t2 (c varchar(5)); +insert into t2 values (NULL); +create table t1 select vec_fromtext(c) from t2; +drop table t1, t2; +## Prepared statements with placeholders +prepare p1 from 'select vec_fromtext(?)'; +execute p1 using '[1,2]'; +execute p1 using NULL; +vec_fromtext(?) +NULL +execute p1 using '[]'; +vec_fromtext(?) + +deallocate prepare p1; +prepare p1 from 'create table t1 select vec_fromtext(?)'; +execute p1 using '[1,2]'; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `vec_fromtext(?)` vector(2) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci +DROP TABLE t1; +execute p1 using NULL; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `vec_fromtext(?)` vector(1) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci +DROP TABLE t1; +execute p1 using '[]'; +ERROR 22007: Incorrect vector value: '' for column `test`.`t1`.`vec_fromtext(?)` at row 1 +execute p1 using ''; +ERROR HY000: Unexpected end of JSON text in argument 1 to function 'VEC_FromText' +deallocate prepare p1; # End of 11.8 tests diff --git a/mysql-test/main/vector2.test b/mysql-test/main/vector2.test index be2493011aacd..f64b065569fa8 100644 --- a/mysql-test/main/vector2.test +++ b/mysql-test/main/vector2.test @@ -125,7 +125,7 @@ drop table t; --echo # MDEV-35141 Server crashes in Field_vector::report_wrong_value upon statistic collection --echo # create table t1 (v vector(64) not null); -insert into t1 select vec_fromtext(concat('[',group_concat(1),']')) from seq_1_to_64; +insert into t1 select vec_fromtext(cast(concat('[',group_concat(1),']') as char(130))) from seq_1_to_64; analyze table t1 persistent for all; drop table t1; @@ -447,4 +447,104 @@ drop table tmp, t1, t2; set sql_mode=@old_sql_mode; +--echo # +--echo # MDEV-40486 ER_TOO_BIG_FIELDLENGTH or assertion failure upon creating vector from blob +--echo # + +--echo ## Original testcase +CREATE TABLE t (a TEXT) AS SELECT '[1]' AS a; +--error ER_TOO_BIG_FIELDLENGTH +CREATE TABLE tt AS SELECT VEC_FROMTEXT(a) AS f FROM t; +DROP TABLE t; + +--echo ## Another case, which would have failed with ERROR 1292 +--echo ## without the fix +CREATE TABLE t SELECT VEC_FROMTEXT('[1]'); +DROP TABLE t; + +--echo ## Conversion from max varchar length +CREATE TABLE t (a VARCHAR(16383)) AS + SELECT concat('[1', repeat(',1', 8190), ']') AS a; +CREATE TABLE tt AS SELECT VEC_FROMTEXT(a) AS f FROM t; +DROP TABLE t,tt; + +--echo ## Conversion to max vector dimension +CREATE TABLE tt AS + SELECT VEC_FROMTEXT(concat('[1', repeat(',1', 16382), ']')) AS f; +DROP TABLE tt; + +--error ER_TOO_BIG_FIELDLENGTH +CREATE TABLE tt AS + SELECT VEC_FROMTEXT(concat('[1', repeat(',1', 16383), ']')) AS f; + +--echo ## "Zero-dimensional" argument, no change in behaviour after fix +SELECT VEC_FROMTEXT('[]') as f; +--error ER_TRUNCATED_WRONG_VALUE +CREATE TABLE t1 SELECT VEC_FROMTEXT('[]'); +--echo ## Zero length: no underflow +SELECT VEC_FROMTEXT('') AS f; +--error ER_JSON_EOS +CREATE TABLE tt AS SELECT VEC_FROMTEXT('') AS f; + +CREATE TABLE t1 (a CHAR(1)); +CREATE TABLE t2 AS SELECT VEC_FROMTEXT(a) AS f FROM t1; +show create table t2; +DROP TABLE t1, t2; +CREATE TABLE t1 (a CHAR(2)); +CREATE TABLE t2 AS SELECT VEC_FROMTEXT(a) AS f FROM t1; +show create table t2; +DROP TABLE t1, t2; + +--error ER_WRONG_FIELD_SPEC +CREATE TABLE t3 (f VECTOR(0)); + +--echo ## Fails because concat('[',group_concat(1),']') is mediumblob +--error ER_TOO_BIG_FIELDLENGTH +create view v1 as select vec_fromtext(concat('[',group_concat(1),']')) from seq_1_to_64; + +--echo ## NULLs +select vec_fromtext(NULL); +select vec_fromtext(NULL + NULL); +create table t1 select vec_fromtext(NULL) as c; +show create table t1; +DROP TABLE t1; +create table t1 select vec_fromtext(NULL + NULL) as c; +show create table t1; +drop table t1; + +create table t1 select vec_fromtext(c) from (select '[1,2]' as c) d; +DROP TABLE t1; +--error ER_JSON_EOS +create table t1 select vec_fromtext(c) from (select '' as c) d; +create table t1 select vec_fromtext(c) from (select NULL as c) d; +show create table t1; +DROP TABLE t1; + +create table t2 (c varchar(5)); +insert into t2 values (NULL); +create table t1 select vec_fromtext(c) from t2; +drop table t1, t2; + +--echo ## Prepared statements with placeholders +prepare p1 from 'select vec_fromtext(?)'; +--disable_result_log +execute p1 using '[1,2]'; +--enable_result_log +execute p1 using NULL; +execute p1 using '[]'; +deallocate prepare p1; + +prepare p1 from 'create table t1 select vec_fromtext(?)'; +execute p1 using '[1,2]'; +show create table t1; +DROP TABLE t1; +execute p1 using NULL; +show create table t1; +DROP TABLE t1; +--error ER_TRUNCATED_WRONG_VALUE +execute p1 using '[]'; +--error ER_JSON_EOS +execute p1 using ''; +deallocate prepare p1; + --echo # End of 11.8 tests diff --git a/sql/item_vectorfunc.cc b/sql/item_vectorfunc.cc index 13e458d7675d6..35c3a63ad8145 100644 --- a/sql/item_vectorfunc.cc +++ b/sql/item_vectorfunc.cc @@ -181,12 +181,19 @@ Item_func_vec_fromtext::Item_func_vec_fromtext(THD *thd, Item *a) bool Item_func_vec_fromtext::fix_length_and_dec(THD *thd) { + uint maxlen= args[0]->max_char_length(); decimals= 0; /* Worst case scenario, for a valid input we have a string of the form: [1,2,3,4,5,...] single digit numbers. - This means we can have (max_length - 1) / 2 floats. - Each float takes 4 bytes, so we do (max_length - 1) * 2. */ - fix_length_and_charset((args[0]->max_length - 1) * 2, &my_charset_bin); + This means we can have (maxlen - 1) / 2 floats. + Each float takes 4 bytes, so we do (maxlen - 1) * 2. */ + fix_length_and_charset(maxlen > 2 ? (maxlen - 1) * 2 : 4, &my_charset_bin); + if (max_length > MAX_FIELD_VARCHARLENGTH) + { + my_error(ER_TOO_BIG_FIELDLENGTH, MYF(0), name.str, + static_cast(MAX_FIELD_VARCHARLENGTH / sizeof(float))); + return true; + } set_maybe_null(); return false; }