diff --git a/mysql-test/main/vector2.result b/mysql-test/main/vector2.result index 5dbe71c8adf1b..9be4ffa3e5a51 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,96 @@ 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 length: no underflow and not allowed for table creation +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 +SELECT VEC_FROMTEXT('') AS f; +ERROR HY000: Incorrect arguments to VEC_FromText +CREATE TABLE tt AS SELECT VEC_FROMTEXT('') AS f; +ERROR HY000: Incorrect arguments to VEC_FromText +CREATE TABLE t1 (a CHAR(1)); +CREATE TABLE t2 AS SELECT VEC_FROMTEXT(a) AS f FROM t1; +ERROR HY000: Incorrect arguments to VEC_FromText +DROP TABLE t1; +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); +ERROR HY000: Incorrect arguments to VEC_FromText +select vec_fromtext(NULL + NULL); +vec_fromtext(NULL + NULL) +NULL +create table t1 select vec_fromtext(NULL) as c; +ERROR HY000: Incorrect arguments to VEC_FromText +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: Incorrect arguments to VEC_FromText +create table t1 select vec_fromtext(c) from (select NULL as c) d; +ERROR HY000: Incorrect arguments to VEC_FromText +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; +ERROR HY000: Incorrect arguments to VEC_FromText +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; +ERROR HY000: Incorrect arguments to VEC_FromText +execute p1 using '[]'; +ERROR 22007: Incorrect vector value: '' for column `test`.`t1`.`vec_fromtext(?)` at row 1 +execute p1 using ''; +ERROR HY000: Incorrect arguments to 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..edf35bac3ef95 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,99 @@ 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 length: no underflow and not allowed for table creation +SELECT VEC_FROMTEXT('[]') as f; +--error ER_TRUNCATED_WRONG_VALUE +CREATE TABLE t1 SELECT VEC_FROMTEXT('[]'); +--error ER_WRONG_ARGUMENTS +SELECT VEC_FROMTEXT('') AS f; +--error ER_WRONG_ARGUMENTS +CREATE TABLE tt AS SELECT VEC_FROMTEXT('') AS f; + +CREATE TABLE t1 (a CHAR(1)); +--error ER_WRONG_ARGUMENTS +CREATE TABLE t2 AS SELECT VEC_FROMTEXT(a) AS f FROM t1; +DROP TABLE t1; + +--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 +--error ER_WRONG_ARGUMENTS +select vec_fromtext(NULL); +select vec_fromtext(NULL + NULL); +--error ER_WRONG_ARGUMENTS +create table t1 select vec_fromtext(NULL) as c; +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_WRONG_ARGUMENTS +create table t1 select vec_fromtext(c) from (select '' as c) d; +--error ER_WRONG_ARGUMENTS +create table t1 select vec_fromtext(c) from (select NULL as c) d; + +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 +--error ER_WRONG_ARGUMENTS +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; +--error ER_WRONG_ARGUMENTS +execute p1 using NULL; +--error ER_TRUNCATED_WRONG_VALUE +execute p1 using '[]'; +--error ER_WRONG_ARGUMENTS +execute p1 using ''; +deallocate prepare p1; + --echo # End of 11.8 tests diff --git a/mysql-test/main/vector_funcs.result b/mysql-test/main/vector_funcs.result index 6aba9df0b055c..a609893f4bdd0 100644 --- a/mysql-test/main/vector_funcs.result +++ b/mysql-test/main/vector_funcs.result @@ -119,8 +119,7 @@ drop table t1; # MDEV-35212 Server crashes in Item_func_vec_fromtext::val_str upon query from empty table # select vec_fromtext(NULL); -vec_fromtext(NULL) -NULL +ERROR HY000: Incorrect arguments to VEC_FromText # # MDEV-35210 Vector type cannot store values which VEC_FromText produces and VEC_ToText accepts # diff --git a/mysql-test/main/vector_funcs.test b/mysql-test/main/vector_funcs.test index b0ada0fa61fbf..3bcad70535dc6 100644 --- a/mysql-test/main/vector_funcs.test +++ b/mysql-test/main/vector_funcs.test @@ -49,6 +49,7 @@ drop table t1; --echo # --echo # MDEV-35212 Server crashes in Item_func_vec_fromtext::val_str upon query from empty table --echo # +--error ER_WRONG_ARGUMENTS select vec_fromtext(NULL); --echo # diff --git a/sql/item_vectorfunc.cc b/sql/item_vectorfunc.cc index 13e458d7675d6..ad1b9e24a904b 100644 --- a/sql/item_vectorfunc.cc +++ b/sql/item_vectorfunc.cc @@ -181,12 +181,25 @@ 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 ? (maxlen - 1) * 2 : 0, &my_charset_bin); + /* Zero-length vectors are not allowed to be table fields */ + if (max_length == 0 && args[0]->type() != PARAM_ITEM) + { + my_error(ER_WRONG_ARGUMENTS, MYF(0), func_name()); + return true; + } + 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; }