Cleanup#2 for MDEV-34319: DECLARE TYPE .. TABLE OF .. INDEX BY - packed_col_length
Additional small cleanup (forgoten in the previous commit): - Item_splocal_assoc_array_element_field::fix_fields() Fixing the error message for: SELECT marks('a').name; -- marks is a TABLE OF VARCHAR(10) From: ERROR 42S22: Unknown column '1' in 'SELECT' To: ERROR 42S22: Unknown column 'name' in 'marks' Fixing wrong results of packed_col_length(): it returned a wrong result for: - CHAR(N) - BINARY(N) - MEDIUMBLOB - LONGBLOB Note, this method was not used. Now it's used by the assoc array data type. Details: - Cleanup: adding "const" qualifier to: * Field::pack() * Field::max_packed_col_length() * Field::packed_col_length() - Removing the "max_length" argument from Field::pack(). The caller passed either UINT_MAX or Field::max_data_length() to it. So it was never used to limit the destination size and only made the code more complicated and confusing. - Removing arguments from packed_col_length(). Now it calculates the value for the Field, using its "ptr", and assuming the entire value will be packed, without limiting the destination size. - Fixing Field_blob::packed_col_length(). It worked fine only for TINYBLOB and BLOB, and did not work for MEDIUMBLOB and LONGBLOB. - Overriding Field_char::packed_col_length(). Using the inherited method was wrong - it implemented variable length data behavior. - Overriding Field_string::max_data_length(). It was also incorrect. Implementing fixed size behavior. Moving the old implementation of Field_longstring::max_data_length() to Field_varstring::max_data_length(). - Fixing class StringPack: * Removing the "length" argument from StringPack::packed_col_length(). It now assumes that the packed length for the entire data buffer is needed, without limiting the destination size. * Fixing StringPack::packed_col_length() to implement fixed dat size behavior. It erroneously implemented VARCHAR style behavor (assumed that the length was stored in the leading 1 or 2 bytes). * Adding a helper method length_bytes(). Reusing it in packed_col_length() and max_packed_col_length(). * Moving a part the method pack() into a new method trimmed_length(). Reusing it in pack() and packed_col_length(). * Rewriting the code in trimmed_length() in a more straightforward way. It was hard to understand what it was doing. Adding a comment. - Adding a test sp-assoc-array-pack-debug.test covering packed_col_length() and pack() for various data types.
This commit is contained in:
parent
3acda17aa9
commit
f9b330e0b4
@ -0,0 +1 @@
|
||||
--max-allowed-packet=33554432
|
@ -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;
|
@ -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;
|
@ -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 #
|
||||
|
@ -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
|
||||
#
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
70
sql/field.cc
70
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 <code>CHAR(1000)</code>, the <code>max_length</code>
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
112
sql/field.h
112
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;
|
||||
|
@ -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(),
|
||||
|
@ -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); }
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user