diff --git a/plugin/type_assoc_array/mysql-test/type_assoc_array/sp-assoc-array-pack-debug.opt b/plugin/type_assoc_array/mysql-test/type_assoc_array/sp-assoc-array-pack-debug.opt new file mode 100644 index 00000000000..4c2d0298d59 --- /dev/null +++ b/plugin/type_assoc_array/mysql-test/type_assoc_array/sp-assoc-array-pack-debug.opt @@ -0,0 +1 @@ +--max-allowed-packet=33554432 diff --git a/plugin/type_assoc_array/mysql-test/type_assoc_array/sp-assoc-array-pack-debug.result b/plugin/type_assoc_array/mysql-test/type_assoc_array/sp-assoc-array-pack-debug.result new file mode 100644 index 00000000000..5955f41ed75 --- /dev/null +++ b/plugin/type_assoc_array/mysql-test/type_assoc_array/sp-assoc-array-pack-debug.result @@ -0,0 +1,486 @@ +set sql_mode=oracle; +SET NAMES utf8mb4; +SELECT @@SESSION.max_allowed_packet; +@@SESSION.max_allowed_packet +33554432 +# +# MDEV-34319 DECLARE TYPE .. TABLE OF .. INDEX BY in stored routines +# +SET debug_dbug='d,assoc_array_pack'; +CREATE TABLE dtypes +( +id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, +dtype VARCHAR(128), +val LONGTEXT +); +INSERT INTO dtypes (dtype, val) VALUES +('bit(1)', 'bit:1'), +('bit(8)', 'bit:255'), +('bit(16)', 'bit:65535'), +('bit(64)', 'bit:18446744073709551615'), +('tinyint', '123'), +('tinyint unsigned', '123'), +('smallint', '123'), +('smallint unsigned', '123'), +('int', '123'), +('int unsigned', '123'), +('mediumint', '123'), +('mediumint unsigned', '123'), +('bigint', '123'), +('bigint unsigned', '123'), +('decimal(10,2)', '123.45'), +('float', '123e5'), +('double', '123e5'), +('mariadb_schema.date', '2001-01-01'), +('time', '800:59:59'), +('time(6)', '800:59:59.123456'), +('datetime', '2001-01-01 23:59:59'), +('datetime(6)', '2001-01-01 23:59:59.123456'), +('timestamp', '2001-01-01 23:59:59'), +('timestamp(6)', '2001-01-01 23:59:59.123456'), +('binary(10)', 'test'), +('binary(20)', 'test'), +('binary(10)', 'test test'), +('binary(20)', 'test test'), +('char(10) character set latin1', 'test'), +('char(10) character set utf8mb4', 'test'), +('varchar(10) character set latin1', 'test'), +('varchar(10) character set utf8mb4', 'test'), +('tinytext character set latin1', 'test'), +('tinytext character set utf8mb4', 'test'), +('text character set latin1', 'test'), +('text character set utf8mb4', 'test'), +('mediumtext character set latin1', 'test'), +('mediumtext character set utf8mb4', 'test'), +('longtext character set latin1', 'test'), +('longtext character set utf8mb4', 'test'), +('char(255) character set latin1', REPEAT('test ',50)), +('char(255) character set utf8mb4', REPEAT('test ',50)), +('varchar(255) character set latin1', REPEAT('test ',50)), +('varchar(255) character set utf8mb4', REPEAT('test ',50)), +('tinytext character set latin1', REPEAT('test ',50)), +('tinytext character set utf8mb4', REPEAT('test ',50)), +('text character set latin1', REPEAT('test ',50)), +('text character set utf8mb4', REPEAT('test ',50)), +('mediumtext character set latin1', REPEAT('test ',50)), +('mediumtext character set utf8mb4', REPEAT('test ',50)), +('longtext character set latin1', REPEAT('test ',50)), +('longtext character set utf8mb4', REPEAT('test ',50)), +('text character set latin1', REPEAT('test ',(256*256-1)/5)), +('text character set utf8mb4', REPEAT('test ',(256*256-1)/5)), +('mediumtext character set latin1', REPEAT('test ',(256*256-1)/5)), +('mediumtext character set utf8mb4', REPEAT('test ',(256*256-1)/5)), +('longtext character set latin1', REPEAT('test ',(256*256-1)/5)), +('longtext character set utf8mb4', REPEAT('test ',(256*256-1)/5)), +('mediumtext character set utf8mb4', REPEAT('test ',(256*256*256-1)/5)), +('longtext character set utf8mb4', REPEAT('test ',(256*256*256-1)/5 + 1)); +CREATE PROCEDURE test_type(rec dtypes%ROWTYPE) AS +TYPE assoc_t IS TABLE OF t1.val%TYPE INDEX BY INTEGER; +assoc assoc_t; +val LONGTEXT; +BEGIN +IF rec.val LIKE 'bit:%' + THEN +assoc(0) := CAST(REPLACE(rec.val,'bit:','') AS UNSIGNED); +SHOW WARNINGS; +SELECT assoc(0)+0 AS `assoc(0)`; +ELSIF rec.dtype LIKE 'binary%' + THEN +assoc(0):= rec.val; +SHOW WARNINGS; +SELECT HEX(assoc(0)), LENGTH(assoc(0)); +ELSE +assoc(0) := rec.val; +SHOW WARNINGS; +IF LENGTH(rec.val) > 64 +THEN +SELECT LEFT(assoc(0),30) || +'..' || LENGTH(assoc(0)) || '.. ' || +RIGHT(assoc(0),30) AS `assoc(0)`; +ELSE +SELECT assoc(0); +END IF; +END IF; +END; +$$ +CREATE PROCEDURE test_types AS +BEGIN +FOR rec IN (SELECT * FROM dtypes) +LOOP +EXECUTE IMMEDIATE REPLACE('CREATE TABLE t1 (val DTYPE)','DTYPE',rec.dtype); +SELECT +COLUMN_TYPE AS ``, COALESCE(CHARACTER_SET_NAME,'') AS `` + FROM +INFORMATION_SCHEMA.COLUMNS +WHERE +TABLE_SCHEMA='test' AND TABLE_NAME='t1' AND COLUMN_NAME='val'; +INSERT INTO t1 VALUES (rec.val); +CALL test_type(rec); +DROP TABLE t1; +END LOOP; +END; +$$ +CALL test_types; + +bit(1) +Level Code Message +Note 1003 pack=1 plen=1 ; mdlen=1 flen=1 ; `assoc` bit(1) +assoc(0) +1 + +bit(8) +Level Code Message +Note 1003 pack=1 plen=1 ; mdlen=1 flen=8 ; `assoc` bit(8) +assoc(0) +255 + +bit(16) +Level Code Message +Note 1003 pack=2 plen=2 ; mdlen=2 flen=16 ; `assoc` bit(16) +assoc(0) +65535 + +bit(64) +Level Code Message +Note 1003 pack=8 plen=8 ; mdlen=8 flen=64 ; `assoc` bit(64) +assoc(0) +18446744073709551615 + +tinyint(4) +Level Code Message +Note 1003 pack=1 plen=1 ; mdlen=1 flen=4 ; `assoc` tinyint(4) +assoc(0) +123 + +tinyint(3) unsigned +Level Code Message +Note 1003 pack=1 plen=1 ; mdlen=1 flen=3 ; `assoc` tinyint(3) unsigned +assoc(0) +123 + +smallint(6) +Level Code Message +Note 1003 pack=2 plen=2 ; mdlen=2 flen=6 ; `assoc` smallint(6) +assoc(0) +123 + +smallint(5) unsigned +Level Code Message +Note 1003 pack=2 plen=2 ; mdlen=2 flen=5 ; `assoc` smallint(5) unsigned +assoc(0) +123 + +int(11) +Level Code Message +Note 1003 pack=4 plen=4 ; mdlen=4 flen=11 ; `assoc` int(11) +assoc(0) +123 + +int(10) unsigned +Level Code Message +Note 1003 pack=4 plen=4 ; mdlen=4 flen=10 ; `assoc` int(10) unsigned +assoc(0) +123 + +mediumint(9) +Level Code Message +Note 1003 pack=3 plen=3 ; mdlen=3 flen=9 ; `assoc` mediumint(9) +assoc(0) +123 + +mediumint(8) unsigned +Level Code Message +Note 1003 pack=3 plen=3 ; mdlen=3 flen=8 ; `assoc` mediumint(8) unsigned +assoc(0) +123 + +bigint(20) +Level Code Message +Note 1003 pack=8 plen=8 ; mdlen=8 flen=20 ; `assoc` bigint(20) +assoc(0) +123 + +bigint(20) unsigned +Level Code Message +Note 1003 pack=8 plen=8 ; mdlen=8 flen=20 ; `assoc` bigint(20) unsigned +assoc(0) +123 + +decimal(10,2) +Level Code Message +Note 1003 pack=5 plen=5 ; mdlen=5 flen=12 ; `assoc` decimal(10,2) +assoc(0) +123.45 + +float +Level Code Message +Note 1003 pack=4 plen=4 ; mdlen=4 flen=12 ; `assoc` float +assoc(0) +12300000 + +double +Level Code Message +Note 1003 pack=8 plen=8 ; mdlen=8 flen=22 ; `assoc` double +assoc(0) +12300000 + +date +Level Code Message +Note 1003 pack=3 plen=3 ; mdlen=3 flen=10 ; `assoc` date +assoc(0) +2001-01-01 + +time +Level Code Message +Note 1003 pack=3 plen=3 ; mdlen=3 flen=10 ; `assoc` time +assoc(0) +800:59:59 + +time(6) +Level Code Message +Note 1003 pack=6 plen=6 ; mdlen=6 flen=17 ; `assoc` time(6) +assoc(0) +800:59:59.123456 + +datetime +Level Code Message +Note 1003 pack=5 plen=5 ; mdlen=5 flen=19 ; `assoc` datetime +assoc(0) +2001-01-01 23:59:59 + +datetime(6) +Level Code Message +Note 1003 pack=8 plen=8 ; mdlen=8 flen=26 ; `assoc` datetime(6) +assoc(0) +2001-01-01 23:59:59.123456 + +timestamp +Level Code Message +Note 1003 pack=4 plen=4 ; mdlen=4 flen=19 ; `assoc` timestamp +assoc(0) +2001-01-01 23:59:59 + +timestamp(6) +Level Code Message +Note 1003 pack=7 plen=7 ; mdlen=7 flen=26 ; `assoc` timestamp(6) +assoc(0) +2001-01-01 23:59:59.123456 + +binary(10) +Level Code Message +Note 1003 pack=5 plen=5 ; mdlen=10 flen=10 ; `assoc` binary(10) +HEX(assoc(0)) LENGTH(assoc(0)) +74657374000000000000 10 + +binary(20) +Level Code Message +Note 1003 pack=5 plen=5 ; mdlen=20 flen=20 ; `assoc` binary(20) +HEX(assoc(0)) LENGTH(assoc(0)) +7465737400000000000000000000000000000000 20 + +binary(10) +Level Code Message +Note 1003 pack=10 plen=10 ; mdlen=10 flen=10 ; `assoc` binary(10) +HEX(assoc(0)) LENGTH(assoc(0)) +74657374207465737400 10 + +binary(20) +Level Code Message +Note 1003 pack=10 plen=10 ; mdlen=20 flen=20 ; `assoc` binary(20) +HEX(assoc(0)) LENGTH(assoc(0)) +7465737420746573740000000000000000000000 20 + +char(10) latin1 +Level Code Message +Note 1003 pack=5 plen=5 ; mdlen=10 flen=10 ; `assoc` char(10) +assoc(0) +test + +char(10) utf8mb4 +Level Code Message +Note 1003 pack=5 plen=5 ; mdlen=40 flen=40 ; `assoc` char(10) +assoc(0) +test + +varchar(10) latin1 +Level Code Message +Note 1003 pack=5 plen=5 ; mdlen=11 flen=10 ; `assoc` varchar(10) +assoc(0) +test + +varchar(10) utf8mb4 +Level Code Message +Note 1003 pack=5 plen=5 ; mdlen=41 flen=40 ; `assoc` varchar(10) +assoc(0) +test + +tinytext latin1 +Level Code Message +Note 1003 pack=5 plen=5 ; mdlen=255 flen=255 ; `assoc` tinytext +assoc(0) +test + +tinytext utf8mb4 +Level Code Message +Note 1003 pack=5 plen=5 ; mdlen=255 flen=255 ; `assoc` tinytext +assoc(0) +test + +text latin1 +Level Code Message +Note 1003 pack=6 plen=6 ; mdlen=65535 flen=65535 ; `assoc` text +assoc(0) +test + +text utf8mb4 +Level Code Message +Note 1003 pack=6 plen=6 ; mdlen=65535 flen=65535 ; `assoc` text +assoc(0) +test + +mediumtext latin1 +Level Code Message +Note 1003 pack=7 plen=7 ; mdlen=16777215 flen=16777215 ; `assoc` mediumtext +assoc(0) +test + +mediumtext utf8mb4 +Level Code Message +Note 1003 pack=7 plen=7 ; mdlen=16777215 flen=16777215 ; `assoc` mediumtext +assoc(0) +test + +longtext latin1 +Level Code Message +Note 1003 pack=8 plen=8 ; mdlen=4294967295 flen=4294967295 ; `assoc` longtext +assoc(0) +test + +longtext utf8mb4 +Level Code Message +Note 1003 pack=8 plen=8 ; mdlen=4294967295 flen=4294967295 ; `assoc` longtext +assoc(0) +test + +char(255) latin1 +Level Code Message +Note 1003 pack=250 plen=250 ; mdlen=255 flen=255 ; `assoc` char(255) +assoc(0) +test test test test test test ..249.. test test test test test test + +char(255) utf8mb4 +Level Code Message +Note 1003 pack=251 plen=251 ; mdlen=1020 flen=1020 ; `assoc` char(255) +assoc(0) +test test test test test test ..249.. test test test test test test + +varchar(255) latin1 +Level Code Message +Note 1003 pack=251 plen=251 ; mdlen=256 flen=255 ; `assoc` varchar(255) +assoc(0) +test test test test test test ..250.. test test test test test test + +varchar(255) utf8mb4 +Level Code Message +Note 1003 pack=252 plen=252 ; mdlen=1022 flen=1020 ; `assoc` varchar(255) +assoc(0) +test test test test test test ..250.. test test test test test test + +tinytext latin1 +Level Code Message +Note 1003 pack=251 plen=251 ; mdlen=255 flen=255 ; `assoc` tinytext +assoc(0) +test test test test test test ..250.. test test test test test test + +tinytext utf8mb4 +Level Code Message +Note 1003 pack=251 plen=251 ; mdlen=255 flen=255 ; `assoc` tinytext +assoc(0) +test test test test test test ..250.. test test test test test test + +text latin1 +Level Code Message +Note 1003 pack=252 plen=252 ; mdlen=65535 flen=65535 ; `assoc` text +assoc(0) +test test test test test test ..250.. test test test test test test + +text utf8mb4 +Level Code Message +Note 1003 pack=252 plen=252 ; mdlen=65535 flen=65535 ; `assoc` text +assoc(0) +test test test test test test ..250.. test test test test test test + +mediumtext latin1 +Level Code Message +Note 1003 pack=253 plen=253 ; mdlen=16777215 flen=16777215 ; `assoc` mediumtext +assoc(0) +test test test test test test ..250.. test test test test test test + +mediumtext utf8mb4 +Level Code Message +Note 1003 pack=253 plen=253 ; mdlen=16777215 flen=16777215 ; `assoc` mediumtext +assoc(0) +test test test test test test ..250.. test test test test test test + +longtext latin1 +Level Code Message +Note 1003 pack=254 plen=254 ; mdlen=4294967295 flen=4294967295 ; `assoc` longtext +assoc(0) +test test test test test test ..250.. test test test test test test + +longtext utf8mb4 +Level Code Message +Note 1003 pack=254 plen=254 ; mdlen=4294967295 flen=4294967295 ; `assoc` longtext +assoc(0) +test test test test test test ..250.. test test test test test test + +text latin1 +Level Code Message +Note 1003 pack=65537 plen=65537 ; mdlen=65535 flen=65535 ; `assoc` text +assoc(0) +test test test test test test ..65535.. test test test test test test + +text utf8mb4 +Level Code Message +Note 1003 pack=65537 plen=65537 ; mdlen=65535 flen=65535 ; `assoc` text +assoc(0) +test test test test test test ..65535.. test test test test test test + +mediumtext latin1 +Level Code Message +Note 1003 pack=65538 plen=65538 ; mdlen=16777215 flen=16777215 ; `assoc` mediumtext +assoc(0) +test test test test test test ..65535.. test test test test test test + +mediumtext utf8mb4 +Level Code Message +Note 1003 pack=65538 plen=65538 ; mdlen=16777215 flen=16777215 ; `assoc` mediumtext +assoc(0) +test test test test test test ..65535.. test test test test test test + +longtext latin1 +Level Code Message +Note 1003 pack=65539 plen=65539 ; mdlen=4294967295 flen=4294967295 ; `assoc` longtext +assoc(0) +test test test test test test ..65535.. test test test test test test + +longtext utf8mb4 +Level Code Message +Note 1003 pack=65539 plen=65539 ; mdlen=4294967295 flen=4294967295 ; `assoc` longtext +assoc(0) +test test test test test test ..65535.. test test test test test test + +mediumtext utf8mb4 +Level Code Message +Note 1003 pack=16777218 plen=16777218 ; mdlen=16777215 flen=16777215 ; `assoc` mediumtext +assoc(0) +test test test test test test ..16777215.. test test test test test test + +longtext utf8mb4 +Level Code Message +Note 1003 pack=16777224 plen=16777224 ; mdlen=4294967295 flen=4294967295 ; `assoc` longtext +assoc(0) +test test test test test test ..16777220.. test test test test test test +DROP PROCEDURE test_type; +DROP PROCEDURE test_types; +DROP TABLE dtypes; diff --git a/plugin/type_assoc_array/mysql-test/type_assoc_array/sp-assoc-array-pack-debug.test b/plugin/type_assoc_array/mysql-test/type_assoc_array/sp-assoc-array-pack-debug.test new file mode 100644 index 00000000000..d791ae57bef --- /dev/null +++ b/plugin/type_assoc_array/mysql-test/type_assoc_array/sp-assoc-array-pack-debug.test @@ -0,0 +1,144 @@ +-- source include/have_debug.inc + +set sql_mode=oracle; +SET NAMES utf8mb4; +SELECT @@SESSION.max_allowed_packet; + +--echo # +--echo # MDEV-34319 DECLARE TYPE .. TABLE OF .. INDEX BY in stored routines +--echo # + +SET debug_dbug='d,assoc_array_pack'; + +CREATE TABLE dtypes +( + id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, + dtype VARCHAR(128), + val LONGTEXT +); +INSERT INTO dtypes (dtype, val) VALUES + +('bit(1)', 'bit:1'), +('bit(8)', 'bit:255'), +('bit(16)', 'bit:65535'), +('bit(64)', 'bit:18446744073709551615'), +('tinyint', '123'), +('tinyint unsigned', '123'), +('smallint', '123'), +('smallint unsigned', '123'), +('int', '123'), +('int unsigned', '123'), +('mediumint', '123'), +('mediumint unsigned', '123'), +('bigint', '123'), +('bigint unsigned', '123'), +('decimal(10,2)', '123.45'), +('float', '123e5'), +('double', '123e5'), +('mariadb_schema.date', '2001-01-01'), +('time', '800:59:59'), +('time(6)', '800:59:59.123456'), +('datetime', '2001-01-01 23:59:59'), +('datetime(6)', '2001-01-01 23:59:59.123456'), +('timestamp', '2001-01-01 23:59:59'), +('timestamp(6)', '2001-01-01 23:59:59.123456'), + +('binary(10)', 'test'), +('binary(20)', 'test'), +('binary(10)', 'test test'), +('binary(20)', 'test test'), + +('char(10) character set latin1', 'test'), +('char(10) character set utf8mb4', 'test'), +('varchar(10) character set latin1', 'test'), +('varchar(10) character set utf8mb4', 'test'), +('tinytext character set latin1', 'test'), +('tinytext character set utf8mb4', 'test'), +('text character set latin1', 'test'), +('text character set utf8mb4', 'test'), +('mediumtext character set latin1', 'test'), +('mediumtext character set utf8mb4', 'test'), +('longtext character set latin1', 'test'), +('longtext character set utf8mb4', 'test'), + +('char(255) character set latin1', REPEAT('test ',50)), +('char(255) character set utf8mb4', REPEAT('test ',50)), +('varchar(255) character set latin1', REPEAT('test ',50)), +('varchar(255) character set utf8mb4', REPEAT('test ',50)), +('tinytext character set latin1', REPEAT('test ',50)), +('tinytext character set utf8mb4', REPEAT('test ',50)), +('text character set latin1', REPEAT('test ',50)), +('text character set utf8mb4', REPEAT('test ',50)), +('mediumtext character set latin1', REPEAT('test ',50)), +('mediumtext character set utf8mb4', REPEAT('test ',50)), +('longtext character set latin1', REPEAT('test ',50)), +('longtext character set utf8mb4', REPEAT('test ',50)), + +('text character set latin1', REPEAT('test ',(256*256-1)/5)), +('text character set utf8mb4', REPEAT('test ',(256*256-1)/5)), +('mediumtext character set latin1', REPEAT('test ',(256*256-1)/5)), +('mediumtext character set utf8mb4', REPEAT('test ',(256*256-1)/5)), +('longtext character set latin1', REPEAT('test ',(256*256-1)/5)), +('longtext character set utf8mb4', REPEAT('test ',(256*256-1)/5)), + +('mediumtext character set utf8mb4', REPEAT('test ',(256*256*256-1)/5)), +('longtext character set utf8mb4', REPEAT('test ',(256*256*256-1)/5 + 1)); + + +DELIMITER $$; +CREATE PROCEDURE test_type(rec dtypes%ROWTYPE) AS + TYPE assoc_t IS TABLE OF t1.val%TYPE INDEX BY INTEGER; + assoc assoc_t; + val LONGTEXT; +BEGIN + IF rec.val LIKE 'bit:%' + THEN + assoc(0) := CAST(REPLACE(rec.val,'bit:','') AS UNSIGNED); + SHOW WARNINGS; + SELECT assoc(0)+0 AS `assoc(0)`; + ELSIF rec.dtype LIKE 'binary%' + THEN + assoc(0):= rec.val; + SHOW WARNINGS; + SELECT HEX(assoc(0)), LENGTH(assoc(0)); + ELSE + assoc(0) := rec.val; + SHOW WARNINGS; + IF LENGTH(rec.val) > 64 + THEN + SELECT LEFT(assoc(0),30) || + '..' || LENGTH(assoc(0)) || '.. ' || + RIGHT(assoc(0),30) AS `assoc(0)`; + ELSE + SELECT assoc(0); + END IF; + END IF; +END; +$$ +DELIMITER ;$$ + +DELIMITER $$; +CREATE PROCEDURE test_types AS +BEGIN + FOR rec IN (SELECT * FROM dtypes) + LOOP + EXECUTE IMMEDIATE REPLACE('CREATE TABLE t1 (val DTYPE)','DTYPE',rec.dtype); + SELECT + COLUMN_TYPE AS ``, COALESCE(CHARACTER_SET_NAME,'') AS `` + FROM + INFORMATION_SCHEMA.COLUMNS + WHERE + TABLE_SCHEMA='test' AND TABLE_NAME='t1' AND COLUMN_NAME='val'; + INSERT INTO t1 VALUES (rec.val); + CALL test_type(rec); + DROP TABLE t1; + END LOOP; +END; +$$ +DELIMITER ;$$ + +CALL test_types; + +DROP PROCEDURE test_type; +DROP PROCEDURE test_types; +DROP TABLE dtypes; diff --git a/plugin/type_assoc_array/mysql-test/type_assoc_array/sp-assoc-array-type-propagation.test b/plugin/type_assoc_array/mysql-test/type_assoc_array/sp-assoc-array-type-propagation.test index 177ba5f2dba..927abcc944f 100644 --- a/plugin/type_assoc_array/mysql-test/type_assoc_array/sp-assoc-array-type-propagation.test +++ b/plugin/type_assoc_array/mysql-test/type_assoc_array/sp-assoc-array-type-propagation.test @@ -1,6 +1,9 @@ SET sql_mode=ORACLE; SET NAMES utf8mb4; +# Needed for mtr --cursor +--enable_prepare_warnings + --echo # --echo # MDEV-34319 DECLARE TYPE .. TABLE OF .. INDEX BY in stored routines --echo # diff --git a/plugin/type_assoc_array/mysql-test/type_assoc_array/sp-assoc-array.result b/plugin/type_assoc_array/mysql-test/type_assoc_array/sp-assoc-array.result index 30a099da521..5d04450c5f1 100644 --- a/plugin/type_assoc_array/mysql-test/type_assoc_array/sp-assoc-array.result +++ b/plugin/type_assoc_array/mysql-test/type_assoc_array/sp-assoc-array.result @@ -1522,7 +1522,7 @@ marks(1) := 1; SELECT marks(1).name; END; $$ -ERROR 42S22: Unknown column '1' in 'SELECT' +ERROR 42S22: Unknown column 'name' in 'marks' # # Field assignment # diff --git a/plugin/type_assoc_array/sql_type_assoc_array.cc b/plugin/type_assoc_array/sql_type_assoc_array.cc index aa00f632122..942bb060950 100644 --- a/plugin/type_assoc_array/sql_type_assoc_array.cc +++ b/plugin/type_assoc_array/sql_type_assoc_array.cc @@ -128,12 +128,26 @@ public: DBUG_ASSERT(field); DBUG_ASSERT(m_buffer); - auto length= field->packed_col_length(field->ptr, - field->value_length()) + 1; - if (unlikely(m_buffer->realloc(length))) + uint length= field->packed_col_length(); + if (unlikely(m_buffer->realloc(length + 1/*QQ: is +1 needed?*/))) return true; +#ifndef DBUG_OFF + StringBuffer<64> type; + field->sql_type(type); + const uchar *pend= +#endif field->pack(ptr(), field->ptr); + DBUG_ASSERT((uint) (pend - ptr()) == length); + DBUG_EXECUTE_IF("assoc_array_pack", + push_warning_printf(current_thd, + Sql_condition::WARN_LEVEL_NOTE, + ER_YES, "pack=%u plen=%u ; mdlen=%u flen=%u ; `%s` %s", + (uint) (pend - ptr()), length, + field->max_data_length(), + field->field_length, + field->field_name.str, + type.c_ptr());); return false; } @@ -271,8 +285,7 @@ public: for (uint i= 0; i < vtable.s->fields; i++) { auto field= vtable.field[i]; - length+= field->packed_col_length(field->ptr, - field->value_length()) + 1; + length+= field->packed_col_length() + 1; } return length; @@ -1532,8 +1545,7 @@ bool Field_assoc_array::create_element_buffer(THD *thd, Binary_string *buffer) return buffer->alloc(length); } - uint length= m_element_field->packed_col_length(m_element_field->ptr, - m_element_field->value_length()) + 1; + uint length= m_element_field->packed_col_length() + 1; return buffer->alloc(length); } @@ -2005,7 +2017,7 @@ bool Item_splocal_assoc_array_element_field::fix_fields(THD *thd, Item **ref) m_field_name, m_field_idx)) { - my_error(ER_BAD_FIELD_ERROR, MYF(0), str->c_ptr(), thd_where(thd)); + my_error(ER_BAD_FIELD_ERROR, MYF(0), m_field_name.str, m_name.str); return true; } diff --git a/plugin/type_uuid/sql_type_uuid.h b/plugin/type_uuid/sql_type_uuid.h index fa493350350..f61e1b0cebb 100644 --- a/plugin/type_uuid/sql_type_uuid.h +++ b/plugin/type_uuid/sql_type_uuid.h @@ -294,12 +294,11 @@ public: extending the binary log format to put the extact data type name into the column metadata. */ - static uchar *pack(uchar *to, const uchar *from, uint max_length) + static uchar *pack(uchar *to, const uchar *from) { uchar buf[binary_length()]; record_to_memory((char *) buf, (const char *) from); - return StringPack(&my_charset_bin, binary_length()). - pack(to, buf, max_length); + return StringPack(&my_charset_bin, binary_length()).pack(to, buf); } // Convert binlog representation to in-record representation diff --git a/sql/field.cc b/sql/field.cc index ba758d51171..64a3a59843a 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -2126,19 +2126,11 @@ int Field_blob::store_from_statistical_minmax_field(Field *stat_field, @param from Pointer to memory area where record representation of field is stored. - - @param max_length - Maximum length of the field, as given in the column definition. For - example, for CHAR(1000), the max_length - is 1000. This information is sometimes needed to decide how to pack - the data. - */ uchar * -Field::pack(uchar *to, const uchar *from, uint max_length) +Field::pack(uchar *to, const uchar *from) const { uint32 length= pack_length(); - set_if_smaller(length, max_length); memcpy(to, from, length); return to+length; } @@ -7608,12 +7600,6 @@ int Field_longstr::store_decimal(const my_decimal *d) return store(str.ptr(), str.length(), str.charset()); } -uint32 Field_longstr::max_data_length() const -{ - return field_length + (field_length > 255 ? 2 : 1); -} - - Data_type_compatibility Field_longstr::cmp_to_string_with_same_collation(const Item_bool_func *cond, const Item *item) const @@ -7917,10 +7903,10 @@ void Field_string::sql_rpl_type(String *res) const Field_string::sql_type(*res); } -uchar *Field_string::pack(uchar *to, const uchar *from, uint max_length) +uchar *Field_string::pack(uchar *to, const uchar *from) const { DBUG_PRINT("debug", ("Packing field '%s'", field_name.str)); - return StringPack(field_charset(), field_length).pack(to, from, max_length); + return StringPack(field_charset(), field_length).pack(to, from); } @@ -8004,13 +7990,14 @@ Binlog_type_info Field_string::binlog_type_info() const } -uint Field_string::packed_col_length(const uchar *data_ptr, uint length) +uint Field_string::packed_col_length() const { - return StringPack::packed_col_length(data_ptr, length); + return StringPack(field_charset(), field_length). + packed_col_length(ptr); } -uint Field_string::max_packed_col_length(uint max_length) +uint Field_string::max_packed_col_length(uint max_length) const { return StringPack::max_packed_col_length(max_length); } @@ -8395,19 +8382,16 @@ uint32 Field_varstring::data_length() /* Functions to create a packed row. - Here the number of length bytes are depending on the given max_length */ -uchar *Field_varstring::pack(uchar *to, const uchar *from, uint max_length) +uchar *Field_varstring::pack(uchar *to, const uchar *from) const { uint length= length_bytes == 1 ? (uint) *from : uint2korr(from); - set_if_smaller(max_length, field_length); - if (length > max_length) - length=max_length; + DBUG_ASSERT(length <= field_length); /* Length always stored little-endian */ *to++= length & 0xFF; - if (max_length > 255) + if (field_length > 255) *to++= (length >> 8) & 0xFF; /* Store bytes of string */ @@ -8466,15 +8450,15 @@ Field_varstring::unpack(uchar *to, const uchar *from, const uchar *from_end, } -uint Field_varstring::packed_col_length(const uchar *data_ptr, uint length) +uint Field_varstring::packed_col_length() const { - if (length > 255) - return uint2korr(data_ptr)+2; - return (uint) *data_ptr + 1; + if (field_length > 255) + return uint2korr(ptr) + 2; + return (uint) *ptr + 1; } -uint Field_varstring::max_packed_col_length(uint max_length) +uint Field_varstring::max_packed_col_length(uint max_length) const { return (max_length > 255 ? 2 : 1)+max_length; } @@ -8823,6 +8807,7 @@ Field_blob::Field_blob(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg, void Field_blob::store_length(uchar *i_ptr, uint i_packlength, uint32 i_number) + const { store_lowendian(i_number, i_ptr, i_packlength); } @@ -9287,7 +9272,7 @@ void Field_blob::sql_type(String &res) const } } -uchar *Field_blob::pack(uchar *to, const uchar *from, uint max_length) +uchar *Field_blob::pack(uchar *to, const uchar *from) const { uint32 length=get_length(from, packlength); // Length of from string @@ -9296,7 +9281,7 @@ uchar *Field_blob::pack(uchar *to, const uchar *from, uint max_length) length given is smaller than the actual length of the blob, we just store the initial bytes of the blob. */ - store_length(to, packlength, MY_MIN(length, max_length)); + store_length(to, packlength, length); /* Store the actual blob data, which will occupy 'length' bytes. @@ -9347,15 +9332,13 @@ const uchar *Field_blob::unpack(uchar *to, const uchar *from, } -uint Field_blob::packed_col_length(const uchar *data_ptr, uint length) +uint Field_blob::packed_col_length() const { - if (length > 255) - return uint2korr(data_ptr)+2; - return (uint) *data_ptr + 1; + return (uint) read_lowendian(ptr, packlength) + packlength; } -uint Field_blob::max_packed_col_length(uint max_length) +uint Field_blob::max_packed_col_length(uint max_length) const { return (max_length > 255 ? 2 : 1)+max_length; } @@ -9891,7 +9874,7 @@ bool Field_enum::is_equal(const Column_definition &new_field) const } -uchar *Field_enum::pack(uchar *to, const uchar *from, uint max_length) +uchar *Field_enum::pack(uchar *to, const uchar *from) const { DBUG_ENTER("Field_enum::pack"); DBUG_PRINT("debug", ("packlength: %d", packlength)); @@ -10389,10 +10372,8 @@ void Field_bit::sql_type(String &res) const uchar * -Field_bit::pack(uchar *to, const uchar *from, uint max_length) +Field_bit::pack(uchar *to, const uchar *from) const { - DBUG_ASSERT(max_length > 0); - uint length; if (bit_len > 0) { /* @@ -10417,9 +10398,8 @@ Field_bit::pack(uchar *to, const uchar *from, uint max_length) uchar bits= get_rec_bits(bit_ptr + (from - ptr), bit_ofs, bit_len); *to++= bits; } - length= MY_MIN(bytes_in_rec, max_length - (bit_len > 0)); - memcpy(to, from, length); - return to + length; + memcpy(to, from, bytes_in_rec); + return to + bytes_in_rec; } diff --git a/sql/field.h b/sql/field.h index f1c6b6c23b7..0f6184161d3 100644 --- a/sql/field.h +++ b/sql/field.h @@ -1717,23 +1717,14 @@ public: } virtual bool send(Protocol *protocol); - virtual uchar *pack(uchar *to, const uchar *from, uint max_length); - /** - @overload Field::pack(uchar*, const uchar*, uint, bool) - */ - uchar *pack(uchar *to, const uchar *from) - { - DBUG_ENTER("Field::pack"); - uchar *result= this->pack(to, from, UINT_MAX); - DBUG_RETURN(result); - } + virtual uchar *pack(uchar *to, const uchar *from) const; virtual const uchar *unpack(uchar* to, const uchar *from, const uchar *from_end, uint param_data=0); - virtual uint packed_col_length(const uchar *to, uint length) - { return length;} - virtual uint max_packed_col_length(uint max_length) + virtual uint packed_col_length() const + { return pack_length(); } + virtual uint max_packed_col_length(uint max_length) const { return max_length;} virtual bool is_packable() const { return false; } @@ -2118,14 +2109,14 @@ private: virtual size_t do_last_null_byte() const; protected: - uchar *pack_int(uchar *to, const uchar *from, size_t size) + static uchar *pack_int(uchar *to, const uchar *from, size_t size) { memcpy(to, from, size); return to + size; } - const uchar *unpack_int(uchar* to, const uchar *from, - const uchar *from_end, size_t size) + static const uchar *unpack_int(uchar* to, const uchar *from, + const uchar *from_end, size_t size) { if (from + size > from_end) return 0; @@ -2133,21 +2124,25 @@ protected: return from + size; } - uchar *pack_int16(uchar *to, const uchar *from) + static uchar *pack_int16(uchar *to, const uchar *from) { return pack_int(to, from, 2); } - const uchar *unpack_int16(uchar* to, const uchar *from, const uchar *from_end) + static const uchar *unpack_int16(uchar* to, + const uchar *from, const uchar *from_end) { return unpack_int(to, from, from_end, 2); } - uchar *pack_int24(uchar *to, const uchar *from) + static uchar *pack_int24(uchar *to, const uchar *from) { return pack_int(to, from, 3); } - const uchar *unpack_int24(uchar* to, const uchar *from, const uchar *from_end) + static const uchar *unpack_int24(uchar* to, + const uchar *from, const uchar *from_end) { return unpack_int(to, from, from_end, 3); } - uchar *pack_int32(uchar *to, const uchar *from) + static uchar *pack_int32(uchar *to, const uchar *from) { return pack_int(to, from, 4); } - const uchar *unpack_int32(uchar* to, const uchar *from, const uchar *from_end) + static const uchar *unpack_int32(uchar* to, + const uchar *from, const uchar *from_end) { return unpack_int(to, from, from_end, 4); } - uchar *pack_int64(uchar* to, const uchar *from) + static uchar *pack_int64(uchar* to, const uchar *from) { return pack_int(to, from, 8); } - const uchar *unpack_int64(uchar* to, const uchar *from, const uchar *from_end) + static const uchar *unpack_int64(uchar* to, + const uchar *from, const uchar *from_end) { return unpack_int(to, from, from_end, 8); } double pos_in_interval_val_real(Field *min, Field *max); @@ -2379,7 +2374,8 @@ public: const Relay_log_info *rli, const Conv_param ¶m) const override; int store_decimal(const my_decimal *d) override; - uint32 max_data_length() const override; + uint32 max_data_length() const override= 0; + uint packed_col_length() const override= 0; void make_send_field(Send_field *) override; bool send(Protocol *protocol) override; bool val_bool() override; @@ -2503,9 +2499,9 @@ public: void overflow(bool negative); bool zero_pack() const override { return false; } void sql_type(String &str) const override; - uchar *pack(uchar* to, const uchar *from, uint max_length) override + uchar *pack(uchar* to, const uchar *from) const override { - return Field::pack(to, from, max_length); + return Field::pack(to, from); } }; @@ -2720,7 +2716,7 @@ public: return type_handler_priv()->type_limits_int(); } - uchar *pack(uchar* to, const uchar *from, uint max_length) override + uchar *pack(uchar* to, const uchar *from) const override { *to= *from; return to + 1; @@ -2782,7 +2778,7 @@ public: { return type_handler_priv()->type_limits_int(); } - uchar *pack(uchar* to, const uchar *from, uint) override + uchar *pack(uchar* to, const uchar *from) const override { return pack_int16(to, from); } const uchar *unpack(uchar* to, const uchar *from, @@ -2829,9 +2825,9 @@ public: { return type_handler_priv()->type_limits_int(); } - uchar *pack(uchar* to, const uchar *from, uint max_length) override + uchar *pack(uchar* to, const uchar *from) const override { - return Field::pack(to, from, max_length); + return Field::pack(to, from); } ulonglong get_max_int_value() const override { @@ -2881,7 +2877,7 @@ public: { return type_handler_priv()->type_limits_int(); } - uchar *pack(uchar* to, const uchar *from, uint) override + uchar *pack(uchar* to, const uchar *from) const override { return pack_int32(to, from); } @@ -2942,7 +2938,7 @@ public: { return type_handler_priv()->type_limits_int(); } - uchar *pack(uchar* to, const uchar *from, uint) override + uchar *pack(uchar* to, const uchar *from) const override { return pack_int64(to, from); } @@ -3404,7 +3400,7 @@ public: /* Get TIMESTAMP field value as seconds since begging of Unix Epoch */ my_time_t get_timestamp(const uchar *pos, ulong *sec_part) const override; bool val_native(Native *to) override; - uchar *pack(uchar *to, const uchar *from, uint) override + uchar *pack(uchar *to, const uchar *from) const override { return pack_int32(to, from); } @@ -3441,8 +3437,8 @@ public: } decimal_digits_t decimals() const override { return dec; } enum ha_base_keytype key_type() const override { return HA_KEYTYPE_BINARY; } - uchar *pack(uchar *to, const uchar *from, uint max_length) override - { return Field::pack(to, from, max_length); } + uchar *pack(uchar *to, const uchar *from) const override + { return Field::pack(to, from); } const uchar *unpack(uchar* to, const uchar *from, const uchar *from_end, uint param_data) override { return Field::unpack(to, from, from_end, param_data); } @@ -3654,7 +3650,7 @@ public: void sort_string(uchar *buff,uint length) override; uint32 pack_length() const override { return 4; } void sql_type(String &str) const override; - uchar *pack(uchar* to, const uchar *from, uint) override + uchar *pack(uchar* to, const uchar *from) const override { return pack_int32(to, from); } @@ -3975,7 +3971,7 @@ public: uint32 pack_length() const override { return 8; } bool get_date(MYSQL_TIME *ltime, date_mode_t fuzzydate) override { return Field_datetime0::get_TIME(ltime, ptr, fuzzydate); } - uchar *pack(uchar* to, const uchar *from, uint) override + uchar *pack(uchar* to, const uchar *from) const override { return pack_int64(to, from); } @@ -4010,8 +4006,8 @@ public: enum ha_base_keytype key_type() const override final { return HA_KEYTYPE_BINARY; } void make_send_field(Send_field *field) override final; bool send(Protocol *protocol) override final; - uchar *pack(uchar *to, const uchar *from, uint max_length) override final - { return Field::pack(to, from, max_length); } + uchar *pack(uchar *to, const uchar *from) const override final + { return Field::pack(to, from); } const uchar *unpack(uchar* to, const uchar *from, const uchar *from_end, uint param_data) override final { return Field::unpack(to, from, from_end, param_data); } @@ -4216,7 +4212,7 @@ public: void sql_type(String &str) const override; void sql_rpl_type(String*) const override; bool is_equal(const Column_definition &new_field) const override; - uchar *pack(uchar *to, const uchar *from, uint max_length) override; + uchar *pack(uchar *to, const uchar *from) const override; const uchar *unpack(uchar* to, const uchar *from, const uchar *from_end, uint param_data) override; uint pack_length_from_metadata(uint field_metadata) const override @@ -4229,8 +4225,12 @@ public: bool compatible_field_size(uint field_metadata, const Relay_log_info *rli, uint16 mflags, int *order_var) const override; uint row_pack_length() const override { return field_length; } - uint packed_col_length(const uchar *to, uint length) override; - uint max_packed_col_length(uint max_length) override; + uint32 max_data_length() const override + { + return field_length; + } + uint packed_col_length() const override; + uint max_packed_col_length(uint max_length) const override; uint size_of() const override { return sizeof *this; } bool has_charset() const override { return charset() != &my_charset_bin; } Field *make_new_field(MEM_ROOT *root, TABLE *new_table, bool keep_type) @@ -4263,7 +4263,7 @@ public: return length_bytes == 1 ? (uint) *ptr_arg : uint2korr(ptr_arg); } protected: - void store_length(uint32 number) + void store_length(uint32 number) const { if (length_bytes == 1) *ptr= (uchar) number; @@ -4311,6 +4311,10 @@ public: uint row_pack_length() const override { return field_length; } bool zero_pack() const override { return false; } int reset() override { bzero(ptr,field_length+length_bytes); return 0; } + uint32 max_data_length() const override + { + return field_length + (field_length > 255 ? 2 : 1); + } uint32 pack_length() const override { return (uint32) field_length+length_bytes; } uint32 key_length() const override { return (uint32) field_length; } @@ -4348,15 +4352,15 @@ public: void set_key_image(const uchar *buff,uint length) override; void sql_type(String &str) const override; void sql_rpl_type(String*) const override; - uchar *pack(uchar *to, const uchar *from, uint max_length) override; + uchar *pack(uchar *to, const uchar *from) const override; const uchar *unpack(uchar* to, const uchar *from, const uchar *from_end, uint param_data) override; int cmp_binary(const uchar *a,const uchar *b, uint32 max_length=~0U) const override; int key_cmp(const uchar *,const uchar*) const override; int key_cmp(const uchar *str, uint length) const override; - uint packed_col_length(const uchar *to, uint length) override; - uint max_packed_col_length(uint max_length) override; + uint packed_col_length() const override; + uint max_packed_col_length(uint max_length) const override; uint32 data_length() override; uint size_of() const override { return sizeof *this; } bool has_charset() const override @@ -4677,8 +4681,8 @@ public: bzero((uchar*) &read_value, sizeof read_value); } uint32 get_field_buffer_size() { return value.alloced_length(); } - void store_length(uchar *i_ptr, uint i_packlength, uint32 i_number); - void store_length(size_t number) + void store_length(uchar *i_ptr, uint i_packlength, uint32 i_number) const; + void store_length(size_t number) const { DBUG_ASSERT(number < UINT_MAX32); store_length(ptr, packlength, (uint32)number); @@ -4778,11 +4782,11 @@ public: /* Set value pointer. Lengths are not important */ value.reset((char*) data, 1, 1, &my_charset_bin); } - uchar *pack(uchar *to, const uchar *from, uint max_length) override; + uchar *pack(uchar *to, const uchar *from) const override; const uchar *unpack(uchar *to, const uchar *from, const uchar *from_end, uint param_data) override; - uint packed_col_length(const uchar *col_ptr, uint length) override; - uint max_packed_col_length(uint max_length) override; + uint packed_col_length() const override; + uint max_packed_col_length(uint max_length) const override; void free() override { value.free(); @@ -4972,7 +4976,7 @@ public: { return Type_extra_attributes(m_typelib); } - uchar *pack(uchar *to, const uchar *from, uint max_length) override; + uchar *pack(uchar *to, const uchar *from) const override; const uchar *unpack(uchar *to, const uchar *from, const uchar *from_end, uint param_data) override; @@ -5177,7 +5181,7 @@ public: bool compatible_field_size(uint metadata, const Relay_log_info *rli, uint16 mflags, int *order_var) const override; void sql_type(String &str) const override; - uchar *pack(uchar *to, const uchar *from, uint max_length) override; + uchar *pack(uchar *to, const uchar *from) const override; const uchar *unpack(uchar *to, const uchar *from, const uchar *from_end, uint param_data) override; int set_default() override; diff --git a/sql/rpl_record.cc b/sql/rpl_record.cc index dd02d97236f..be0eb7b6df3 100644 --- a/sql/rpl_record.cc +++ b/sql/rpl_record.cc @@ -103,8 +103,7 @@ pack_row(TABLE *table, MY_BITMAP const* cols, #ifndef DBUG_OFF const uchar *old_pack_ptr= pack_ptr; #endif - pack_ptr= field->pack(pack_ptr, field->ptr + offset, - field->max_data_length()); + pack_ptr= field->pack(pack_ptr, field->ptr + offset); DBUG_PRINT("debug", ("field: %s; real_type: %d, pack_ptr: %p;" " pack_ptr':%p; bytes: %d", field->field_name.str, field->real_type(), diff --git a/sql/sql_type_fixedbin.h b/sql/sql_type_fixedbin.h index 8fb991944b0..c31e6ac395e 100644 --- a/sql/sql_type_fixedbin.h +++ b/sql/sql_type_fixedbin.h @@ -719,10 +719,10 @@ public: FbtImpl::binary_length(), &my_charset_bin); } - uchar *pack(uchar *to, const uchar *from, uint max_length) override + uchar *pack(uchar *to, const uchar *from) const override { DBUG_PRINT("debug", ("Packing field '%s'", field_name.str)); - return FbtImpl::pack(to, from, max_length); + return FbtImpl::pack(to, from); } const uchar *unpack(uchar *to, const uchar *from, const uchar *from_end, @@ -731,14 +731,15 @@ public: return FbtImpl::unpack(to, from, from_end, param_data); } - uint max_packed_col_length(uint max_length) override + uint max_packed_col_length(uint max_length) const override { return StringPack::max_packed_col_length(max_length); } - uint packed_col_length(const uchar *fbt_ptr, uint length) override + uint packed_col_length() const override { - return StringPack::packed_col_length(fbt_ptr, length); + return StringPack(&my_charset_bin, pack_length()). + packed_col_length(ptr); } uint size_of() const override { return sizeof(*this); } diff --git a/sql/sql_type_fixedbin_storage.h b/sql/sql_type_fixedbin_storage.h index 3a4e74a8cdb..3d4872f52f1 100644 --- a/sql/sql_type_fixedbin_storage.h +++ b/sql/sql_type_fixedbin_storage.h @@ -150,9 +150,9 @@ public: Used in Field::pack(), and in filesort to store the addon fields. By default, do what BINARY(N) does. */ - static uchar *pack(uchar *to, const uchar *from, uint max_length) + static uchar *pack(uchar *to, const uchar *from) { - return StringPack(&my_charset_bin, binary_length()).pack(to, from, max_length); + return StringPack(&my_charset_bin, binary_length()).pack(to, from); } /* diff --git a/sql/sql_type_string.cc b/sql/sql_type_string.cc index df46ef744f0..8a824b8bc10 100644 --- a/sql/sql_type_string.cc +++ b/sql/sql_type_string.cc @@ -20,31 +20,52 @@ #include "sql_type_string.h" -uchar * -StringPack::pack(uchar *to, const uchar *from, uint max_length) const +// Trim trailing spaces for CHAR or 0x00 bytes for BINARY +uint StringPack::rtrimmed_length(const char *from) const { - size_t length= MY_MIN(m_octet_length, max_length); - size_t local_char_length= char_length(); - DBUG_PRINT("debug", ("length: %zu ", length)); + DBUG_PRINT("debug", ("length: %u ", (uint) m_octet_length)); + + if (mbmaxlen() > 1) + { + /* + Suppose we have CHAR(100) CHARACTER SET utf8mb4. + Its octet_length is 400. + - In case of ASCII characters only, the leftmost 100 bytes + contain real data, the other 300 bytes are padding spaces. + - In case of 100 2-byte characters, the leftmost 200 bytes + contain real data, the other 200 bytes are padding spaces. + - All 400 bytes contain real data (without padding spaces) + only in case of 100 4-byte characters, which is a rare scenario. + + There are two approaches possible to trim the data: + 1. Left-to-right: call charpos() to find the end of the 100th + character, then switch to a right-to-left loop to trim trailing spaces. + 2. Right-to-left: trim characters from the position "from+400" towards + the beginning. + + N1 should be faster in an average case, and is much faster for pure ASCII. + */ + size_t length= charset()->charpos(from, from+m_octet_length, char_length()); + return (uint) charset()->lengthsp((const char*) from, length); + } - if (length > local_char_length) - local_char_length= charset()->charpos(from, from + length, - local_char_length); - set_if_smaller(length, local_char_length); - /* TODO: change charset interface to add a new function that does the following or add a flag to lengthsp to do it itself (this is for not packing padding adding bytes in BINARY fields). */ - if (mbmaxlen() == 1) - { - while (length && from[length-1] == charset()->pad_char) - length --; - } - else - length= charset()->lengthsp((const char*) from, length); + size_t length= m_octet_length; + while (length && from[length - 1] == charset()->pad_char) + length --; + return (uint) length; +} + + +uchar * +StringPack::pack(uchar *to, const uchar *from) const +{ + size_t length= rtrimmed_length((const char *) from); // Length always stored little-endian *to++= (uchar) length; diff --git a/sql/sql_type_string.h b/sql/sql_type_string.h index fca46e91394..496d91df1cc 100644 --- a/sql/sql_type_string.h +++ b/sql/sql_type_string.h @@ -23,24 +23,29 @@ class StringPack CHARSET_INFO *charset() const { return m_cs; } uint mbmaxlen() const { return m_cs->mbmaxlen; }; uint32 char_length() const { return m_octet_length / mbmaxlen(); } + // Trim trailing spaces for CHAR or 0x00 bytes for BINARY + uint rtrimmed_length(const char *from) const; + static uint length_bytes(uint max_length) + { + return max_length > 255 ? 2 : 1; + } public: StringPack(CHARSET_INFO *cs, uint32 octet_length) :m_cs(cs), m_octet_length(octet_length) { } - uchar *pack(uchar *to, const uchar *from, uint max_length) const; + uchar *pack(uchar *to, const uchar *from) const; const uchar *unpack(uchar *to, const uchar *from, const uchar *from_end, uint param_data) const; public: static uint max_packed_col_length(uint max_length) { - return (max_length > 255 ? 2 : 1) + max_length; + return length_bytes(max_length) + max_length; } - static uint packed_col_length(const uchar *data_ptr, uint length) + uint packed_col_length(const uchar *data_ptr) const { - if (length > 255) - return uint2korr(data_ptr)+2; - return (uint) *data_ptr + 1; + return length_bytes(m_octet_length) + + rtrimmed_length((const char *) data_ptr); } };