From 2dcea79d1b58053e4453f618f4962bc603bdf5d2 Mon Sep 17 00:00:00 2001 From: Yuchen Pei Date: Wed, 24 Jun 2026 15:20:09 +1000 Subject: [PATCH] MDEV-39558 Merge VECTOR into BLOB/MEDIUMBLOB/LONGBLOB in type inference aggregation VECTOR, as a subtype of VARCHAR, has max length 65532, i.e. maximum dimension of 16383. BLOB/MEDIUMBLOB/LONGBLOB (and corresponding TEXT types) each has length exceeding 65532. Therefore, when aggregating VECTOR with one of these BLOB/TEXT types, the aggregated type has length exceeding the max length of VECTOR, so it should be the BLOB/TEXT type rather than VECTOR. --- mysql-test/main/vector2.result | 67 ++++++++++++++++++++++++++++++++++ mysql-test/main/vector2.test | 64 ++++++++++++++++++++++++++++++++ sql/sql_type_vector.cc | 6 ++- 3 files changed, 135 insertions(+), 2 deletions(-) diff --git a/mysql-test/main/vector2.result b/mysql-test/main/vector2.result index 81160e8eb18dd..5b614c9dc7fc0 100644 --- a/mysql-test/main/vector2.result +++ b/mysql-test/main/vector2.result @@ -498,4 +498,71 @@ vec_totext(0x03CA397B) select vec_distance_euclidean(0x03CA397B, vec_fromtext('[0]')); vec_distance_euclidean(0x03CA397B, vec_fromtext('[0]')) 9.64672e35 +# +# MDEV-39558 SIGSEGV in collect_indexed_vcols_for_table, memory corruption by my_copy_8bit from charset_info_st::copy_fix +# +set @old_sql_mode=@@sql_mode; +set sql_mode=''; +# original case +CREATE TABLE t (c FLOAT(2,2) ZEROFILL,c2 SET('') CHARACTER SET'BINARY' COLLATE'BINARY',c3 DATE,KEY(c)); +ALTER TABLE t MODIFY c2 LONGTEXT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; +REPLACE INTO t (c,c2,c3) VALUES ('','r:$u4[Z3y[HmHZ5r{FCU*0#LJOZVb][s;rm7j3N - xca *^ kt-(LE (4UP~IC:%l9/','=DpF=s=G@=d_rqbvtsjhwtgai.N.P7u}3={qDy[Un=LPeqllXoQM % fs=&mXT=e:'); +Warnings: +Warning 1366 Incorrect double value: '' for column `test`.`t`.`c` at row 1 +Warning 1265 Data truncated for column 'c3' at row 1 +RENAME TABLE IF EXISTS t TO t4; +CREATE TABLE t (c INT KEY,c2 VECTOR (4) NOT NULL,VECTOR INDEX (c2) M=4); +(SELECT c2 FROM t) INTERSECT ALL (SELECT c2 FROM t4); +c2 +drop table t, t4; +# simplified cases +CREATE TABLE t1(c LONGTEXT); +insert INTO t1 VALUES('1234567890123456789012345678901234567890123456789012345'); +CREATE TABLE t2(d VECTOR(4)); +create table tmp as (SELECT * FROM t1) INTERSECT (SELECT * FROM t2); +show create table tmp; +Table Create Table +tmp CREATE TABLE `tmp` ( + `c` longblob DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci +(SELECT * FROM t1) INTERSECT (SELECT * FROM t2); +c +drop table tmp, t1, t2; +CREATE TABLE t1(c MEDIUMTEXT); +insert INTO t1 VALUES('1234567890123456789012345678901234567890123456789012345'); +CREATE TABLE t2(d VECTOR(4)); +create table tmp as (SELECT * FROM t1) INTERSECT (SELECT * FROM t2); +show create table tmp; +Table Create Table +tmp CREATE TABLE `tmp` ( + `c` mediumblob DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci +(SELECT * FROM t1) INTERSECT (SELECT * FROM t2); +c +drop table tmp, t1, t2; +CREATE TABLE t1(c TEXT); +insert INTO t1 VALUES('1234567890123456789012345678901234567890123456789012345'); +CREATE TABLE t2(d VECTOR(4)); +create table tmp as (SELECT * FROM t1) INTERSECT (SELECT * FROM t2); +show create table tmp; +Table Create Table +tmp CREATE TABLE `tmp` ( + `c` blob DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci +(SELECT * FROM t1) INTERSECT (SELECT * FROM t2); +c +drop table tmp, t1, t2; +CREATE TABLE t1(c TINYTEXT); +insert INTO t1 VALUES('1234567890123456789012345678901234567890123456789012345'); +CREATE TABLE t2(d VECTOR(4)); +create table tmp as (SELECT * FROM t1) INTERSECT (SELECT * FROM t2); +show create table tmp; +Table Create Table +tmp CREATE TABLE `tmp` ( + `c` vector(63) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci +(SELECT * FROM t1) INTERSECT (SELECT * FROM t2); +c +drop table tmp, t1, t2; +set sql_mode=@old_sql_mode; # End of 11.8 tests diff --git a/mysql-test/main/vector2.test b/mysql-test/main/vector2.test index e41a2f408ef52..81c41afd41652 100644 --- a/mysql-test/main/vector2.test +++ b/mysql-test/main/vector2.test @@ -368,4 +368,68 @@ select vec_totext(0x03CA397B); --replace_regex /(\.\d{5})\d+/\1/ select vec_distance_euclidean(0x03CA397B, vec_fromtext('[0]')); +--echo # +--echo # MDEV-39558 SIGSEGV in collect_indexed_vcols_for_table, memory corruption by my_copy_8bit from charset_info_st::copy_fix +--echo # + +set @old_sql_mode=@@sql_mode; +set sql_mode=''; + +--echo # original case +CREATE TABLE t (c FLOAT(2,2) ZEROFILL,c2 SET('') CHARACTER SET'BINARY' COLLATE'BINARY',c3 DATE,KEY(c)); +ALTER TABLE t MODIFY c2 LONGTEXT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; +REPLACE INTO t (c,c2,c3) VALUES ('','r:$u4[Z3y[HmHZ5r{FCU*0#LJOZVb][s;rm7j3N - xca *^ kt-(LE (4UP~IC:%l9/','=DpF=s=G@=d_rqbvtsjhwtgai.N.P7u}3={qDy[Un=LPeqllXoQM % fs=&mXT=e:'); +RENAME TABLE IF EXISTS t TO t4; +CREATE TABLE t (c INT KEY,c2 VECTOR (4) NOT NULL,VECTOR INDEX (c2) M=4); +(SELECT c2 FROM t) INTERSECT ALL (SELECT c2 FROM t4); + +drop table t, t4; + +--echo # simplified cases +CREATE TABLE t1(c LONGTEXT); +insert INTO t1 VALUES('1234567890123456789012345678901234567890123456789012345'); +CREATE TABLE t2(d VECTOR(4)); + +create table tmp as (SELECT * FROM t1) INTERSECT (SELECT * FROM t2); +show create table tmp; + +(SELECT * FROM t1) INTERSECT (SELECT * FROM t2); + +drop table tmp, t1, t2; + +CREATE TABLE t1(c MEDIUMTEXT); +insert INTO t1 VALUES('1234567890123456789012345678901234567890123456789012345'); +CREATE TABLE t2(d VECTOR(4)); + +create table tmp as (SELECT * FROM t1) INTERSECT (SELECT * FROM t2); +show create table tmp; + +(SELECT * FROM t1) INTERSECT (SELECT * FROM t2); + +drop table tmp, t1, t2; + +CREATE TABLE t1(c TEXT); +insert INTO t1 VALUES('1234567890123456789012345678901234567890123456789012345'); +CREATE TABLE t2(d VECTOR(4)); + +create table tmp as (SELECT * FROM t1) INTERSECT (SELECT * FROM t2); +show create table tmp; + +(SELECT * FROM t1) INTERSECT (SELECT * FROM t2); + +drop table tmp, t1, t2; + +CREATE TABLE t1(c TINYTEXT); +insert INTO t1 VALUES('1234567890123456789012345678901234567890123456789012345'); +CREATE TABLE t2(d VECTOR(4)); + +create table tmp as (SELECT * FROM t1) INTERSECT (SELECT * FROM t2); +show create table tmp; + +(SELECT * FROM t1) INTERSECT (SELECT * FROM t2); + +drop table tmp, t1, t2; + +set sql_mode=@old_sql_mode; + --echo # End of 11.8 tests diff --git a/sql/sql_type_vector.cc b/sql/sql_type_vector.cc index 609fdd2fa5886..24d25bd220a17 100644 --- a/sql/sql_type_vector.cc +++ b/sql/sql_type_vector.cc @@ -32,11 +32,13 @@ const Type_handler *Type_collection_vector::aggregate_for_comparison( if (a->type_collection() == this) swap_variables(const Type_handler *, a, b); if (a == &type_handler_vector || a == &type_handler_hex_hybrid || - a == &type_handler_tiny_blob || a == &type_handler_blob || - a == &type_handler_medium_blob || a == &type_handler_long_blob || + a == &type_handler_tiny_blob || a == &type_handler_varchar || a == &type_handler_string || a == &type_handler_null) return b; + if (a == &type_handler_medium_blob || a == &type_handler_blob || + a == &type_handler_long_blob) + return a; return NULL; }