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);
}
};