mirror of
https://github.com/MariaDB/server.git
synced 2025-08-17 06:42:17 +03:00
MDEV-26664 Store UUIDs in a more efficient manner
UUID values llllllll-mmmm-Vhhh-vsss-nnnnnnnnnnnn are now stored as nnnnnnnnnnnn-vsss-Vhhh-mmmm-llllllll inside the record: - the groups (segments separated by dash) are reordered right-to-left. - the bytes inside the groups are not reordered (stored as before, in big-endian format). This provides a better sorting order: the earlier UUID was generated, the higher it appears in the ORDER BY output. Also, this change enables a good key prefix compression, because the constant part is now in the beginning, while the non-constant part (the timestamp) is in the end.
This commit is contained in:
committed by
Sergei Golubchik
parent
50bcda010f
commit
b9f19f7eae
BIN
plugin/type_uuid/mysql-test/type_uuid/std_data/t1nopackkey.frm
Normal file
BIN
plugin/type_uuid/mysql-test/type_uuid/std_data/t1nopackkey.frm
Normal file
Binary file not shown.
BIN
plugin/type_uuid/mysql-test/type_uuid/std_data/t1packkey.frm
Normal file
BIN
plugin/type_uuid/mysql-test/type_uuid/std_data/t1packkey.frm
Normal file
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@@ -138,6 +138,50 @@ SELECT * FROM t1 WHERE a IN ('::', 10);
|
|||||||
|
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # ORDER BY
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
CREATE TABLE t1 (a UUID);
|
||||||
|
DELIMITER $$;
|
||||||
|
FOR i IN 0..15
|
||||||
|
DO
|
||||||
|
INSERT INTO t1 VALUES (REPLACE('XX000000-0000-0000-0000-000000000000','XX',LPAD(HEX(i),2,'0')));
|
||||||
|
INSERT INTO t1 VALUES (REPLACE('00XX0000-0000-0000-0000-000000000000','XX',LPAD(HEX(i),2,'0')));
|
||||||
|
INSERT INTO t1 VALUES (REPLACE('0000XX00-0000-0000-0000-000000000000','XX',LPAD(HEX(i),2,'0')));
|
||||||
|
INSERT INTO t1 VALUES (REPLACE('000000XX-0000-0000-0000-000000000000','XX',LPAD(HEX(i),2,'0')));
|
||||||
|
INSERT INTO t1 VALUES (REPLACE('00000000-XX00-0000-0000-000000000000','XX',LPAD(HEX(i),2,'0')));
|
||||||
|
INSERT INTO t1 VALUES (REPLACE('00000000-00XX-0000-0000-000000000000','XX',LPAD(HEX(i),2,'0')));
|
||||||
|
INSERT INTO t1 VALUES (REPLACE('00000000-0000-XX00-0000-000000000000','XX',LPAD(HEX(i),2,'0')));
|
||||||
|
INSERT INTO t1 VALUES (REPLACE('00000000-0000-00XX-0000-000000000000','XX',LPAD(HEX(i),2,'0')));
|
||||||
|
INSERT INTO t1 VALUES (REPLACE('00000000-0000-0000-XX00-000000000000','XX',LPAD(HEX(i),2,'0')));
|
||||||
|
INSERT INTO t1 VALUES (REPLACE('00000000-0000-0000-00XX-000000000000','XX',LPAD(HEX(i),2,'0')));
|
||||||
|
INSERT INTO t1 VALUES (REPLACE('00000000-0000-0000-0000-XX0000000000','XX',LPAD(HEX(i),2,'0')));
|
||||||
|
INSERT INTO t1 VALUES (REPLACE('00000000-0000-0000-0000-00XX00000000','XX',LPAD(HEX(i),2,'0')));
|
||||||
|
INSERT INTO t1 VALUES (REPLACE('00000000-0000-0000-0000-0000XX000000','XX',LPAD(HEX(i),2,'0')));
|
||||||
|
INSERT INTO t1 VALUES (REPLACE('00000000-0000-0000-0000-000000XX0000','XX',LPAD(HEX(i),2,'0')));
|
||||||
|
INSERT INTO t1 VALUES (REPLACE('00000000-0000-0000-0000-00000000XX00','XX',LPAD(HEX(i),2,'0')));
|
||||||
|
INSERT INTO t1 VALUES (REPLACE('00000000-0000-0000-0000-0000000000XX','XX',LPAD(HEX(i),2,'0')));
|
||||||
|
END FOR;
|
||||||
|
$$
|
||||||
|
DELIMITER ;$$
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # Logical ORDER BY
|
||||||
|
--echo #
|
||||||
|
SELECT * FROM t1 ORDER BY a;
|
||||||
|
SELECT COALESCE(NULL, a) FROM t1 ORDER BY a;
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # Lexicographical ORDER BY
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
SELECT * FROM t1 ORDER BY CAST(a AS BINARY(16));
|
||||||
|
SELECT * FROM t1 ORDER BY CAST(COALESCE(NULL,a) AS BINARY(16));
|
||||||
|
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
|
||||||
--echo #
|
--echo #
|
||||||
--echo # cmp_item_uuid: IN for non-constants
|
--echo # cmp_item_uuid: IN for non-constants
|
||||||
--echo #
|
--echo #
|
||||||
|
@@ -66,3 +66,43 @@ SELECT * FROM t1 WHERE a=CAST('00000000-0000-0000-0000-0000000000ff' AS UUID);
|
|||||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=CAST('00000000-0000-0000-0000-0000000000ff' AS UUID);
|
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=CAST('00000000-0000-0000-0000-0000000000ff' AS UUID);
|
||||||
|
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
|
||||||
|
CREATE OR REPLACE TABLE t1 (a UUID,KEY(a));
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
BEGIN;
|
||||||
|
DELIMITER $$;
|
||||||
|
FOR i IN 0..255
|
||||||
|
DO
|
||||||
|
INSERT INTO t1 VALUES (REPLACE('XX000000-0000-0000-0000-000000000000','XX',LPAD(HEX(i),2,'0')));
|
||||||
|
INSERT INTO t1 VALUES (REPLACE('00XX0000-0000-0000-0000-000000000000','XX',LPAD(HEX(i),2,'0')));
|
||||||
|
INSERT INTO t1 VALUES (REPLACE('0000XX00-0000-0000-0000-000000000000','XX',LPAD(HEX(i),2,'0')));
|
||||||
|
INSERT INTO t1 VALUES (REPLACE('000000XX-0000-0000-0000-000000000000','XX',LPAD(HEX(i),2,'0')));
|
||||||
|
INSERT INTO t1 VALUES (REPLACE('00000000-XX00-0000-0000-000000000000','XX',LPAD(HEX(i),2,'0')));
|
||||||
|
INSERT INTO t1 VALUES (REPLACE('00000000-00XX-0000-0000-000000000000','XX',LPAD(HEX(i),2,'0')));
|
||||||
|
INSERT INTO t1 VALUES (REPLACE('00000000-0000-XX00-0000-000000000000','XX',LPAD(HEX(i),2,'0')));
|
||||||
|
INSERT INTO t1 VALUES (REPLACE('00000000-0000-00XX-0000-000000000000','XX',LPAD(HEX(i),2,'0')));
|
||||||
|
INSERT INTO t1 VALUES (REPLACE('00000000-0000-0000-XX00-000000000000','XX',LPAD(HEX(i),2,'0')));
|
||||||
|
INSERT INTO t1 VALUES (REPLACE('00000000-0000-0000-00XX-000000000000','XX',LPAD(HEX(i),2,'0')));
|
||||||
|
INSERT INTO t1 VALUES (REPLACE('00000000-0000-0000-0000-XX0000000000','XX',LPAD(HEX(i),2,'0')));
|
||||||
|
INSERT INTO t1 VALUES (REPLACE('00000000-0000-0000-0000-00XX00000000','XX',LPAD(HEX(i),2,'0')));
|
||||||
|
INSERT INTO t1 VALUES (REPLACE('00000000-0000-0000-0000-0000XX000000','XX',LPAD(HEX(i),2,'0')));
|
||||||
|
INSERT INTO t1 VALUES (REPLACE('00000000-0000-0000-0000-000000XX0000','XX',LPAD(HEX(i),2,'0')));
|
||||||
|
INSERT INTO t1 VALUES (REPLACE('00000000-0000-0000-0000-00000000XX00','XX',LPAD(HEX(i),2,'0')));
|
||||||
|
INSERT INTO t1 VALUES (REPLACE('00000000-0000-0000-0000-0000000000XX','XX',LPAD(HEX(i),2,'0')));
|
||||||
|
END FOR;
|
||||||
|
$$
|
||||||
|
DELIMITER ;$$
|
||||||
|
COMMIT;
|
||||||
|
EXPLAIN SELECT * FROM t1 WHERE a='ff000000-0000-0000-0000-000000000000';
|
||||||
|
EXPLAIN SELECT * FROM t1 WHERE a='00ff0000-0000-0000-0000-000000000000';
|
||||||
|
EXPLAIN SELECT * FROM t1 WHERE a='0000ff00-0000-0000-0000-000000000000';
|
||||||
|
EXPLAIN SELECT * FROM t1 WHERE a='000000ff-0000-0000-0000-000000000000';
|
||||||
|
EXPLAIN SELECT * FROM t1 WHERE a='00000000-ff00-0000-0000-000000000000';
|
||||||
|
EXPLAIN SELECT * FROM t1 WHERE a='00000000-00ff-0000-0000-000000000000';
|
||||||
|
EXPLAIN SELECT * FROM t1 WHERE a='00000000-0000-ff00-0000-000000000000';
|
||||||
|
EXPLAIN SELECT * FROM t1 WHERE a='00000000-0000-00ff-0000-000000000000';
|
||||||
|
EXPLAIN SELECT * FROM t1 WHERE a='00000000-0000-0000-ff00-000000000000';
|
||||||
|
EXPLAIN SELECT * FROM t1 WHERE a='00000000-0000-0000-00ff-000000000000';
|
||||||
|
EXPLAIN SELECT * FROM t1 WHERE a='00000000-0000-0000-0000-ff0000000000';
|
||||||
|
DROP TABLE t1;
|
||||||
|
@@ -115,6 +115,69 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
|
|||||||
Warnings:
|
Warnings:
|
||||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = UUID'00000000-0000-0000-0000-0000000000ff'
|
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = UUID'00000000-0000-0000-0000-0000000000ff'
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
|
CREATE OR REPLACE TABLE t1 (a UUID,KEY(a));
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
Table Create Table
|
||||||
|
t1 CREATE TABLE `t1` (
|
||||||
|
`a` uuid DEFAULT NULL,
|
||||||
|
KEY `a` (`a`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=latin1
|
||||||
|
BEGIN;
|
||||||
|
FOR i IN 0..255
|
||||||
|
DO
|
||||||
|
INSERT INTO t1 VALUES (REPLACE('XX000000-0000-0000-0000-000000000000','XX',LPAD(HEX(i),2,'0')));
|
||||||
|
INSERT INTO t1 VALUES (REPLACE('00XX0000-0000-0000-0000-000000000000','XX',LPAD(HEX(i),2,'0')));
|
||||||
|
INSERT INTO t1 VALUES (REPLACE('0000XX00-0000-0000-0000-000000000000','XX',LPAD(HEX(i),2,'0')));
|
||||||
|
INSERT INTO t1 VALUES (REPLACE('000000XX-0000-0000-0000-000000000000','XX',LPAD(HEX(i),2,'0')));
|
||||||
|
INSERT INTO t1 VALUES (REPLACE('00000000-XX00-0000-0000-000000000000','XX',LPAD(HEX(i),2,'0')));
|
||||||
|
INSERT INTO t1 VALUES (REPLACE('00000000-00XX-0000-0000-000000000000','XX',LPAD(HEX(i),2,'0')));
|
||||||
|
INSERT INTO t1 VALUES (REPLACE('00000000-0000-XX00-0000-000000000000','XX',LPAD(HEX(i),2,'0')));
|
||||||
|
INSERT INTO t1 VALUES (REPLACE('00000000-0000-00XX-0000-000000000000','XX',LPAD(HEX(i),2,'0')));
|
||||||
|
INSERT INTO t1 VALUES (REPLACE('00000000-0000-0000-XX00-000000000000','XX',LPAD(HEX(i),2,'0')));
|
||||||
|
INSERT INTO t1 VALUES (REPLACE('00000000-0000-0000-00XX-000000000000','XX',LPAD(HEX(i),2,'0')));
|
||||||
|
INSERT INTO t1 VALUES (REPLACE('00000000-0000-0000-0000-XX0000000000','XX',LPAD(HEX(i),2,'0')));
|
||||||
|
INSERT INTO t1 VALUES (REPLACE('00000000-0000-0000-0000-00XX00000000','XX',LPAD(HEX(i),2,'0')));
|
||||||
|
INSERT INTO t1 VALUES (REPLACE('00000000-0000-0000-0000-0000XX000000','XX',LPAD(HEX(i),2,'0')));
|
||||||
|
INSERT INTO t1 VALUES (REPLACE('00000000-0000-0000-0000-000000XX0000','XX',LPAD(HEX(i),2,'0')));
|
||||||
|
INSERT INTO t1 VALUES (REPLACE('00000000-0000-0000-0000-00000000XX00','XX',LPAD(HEX(i),2,'0')));
|
||||||
|
INSERT INTO t1 VALUES (REPLACE('00000000-0000-0000-0000-0000000000XX','XX',LPAD(HEX(i),2,'0')));
|
||||||
|
END FOR;
|
||||||
|
$$
|
||||||
|
COMMIT;
|
||||||
|
EXPLAIN SELECT * FROM t1 WHERE a='ff000000-0000-0000-0000-000000000000';
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 SIMPLE t1 ref a a 17 const 1 Using where; Using index
|
||||||
|
EXPLAIN SELECT * FROM t1 WHERE a='00ff0000-0000-0000-0000-000000000000';
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 SIMPLE t1 ref a a 17 const 1 Using where; Using index
|
||||||
|
EXPLAIN SELECT * FROM t1 WHERE a='0000ff00-0000-0000-0000-000000000000';
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 SIMPLE t1 ref a a 17 const 1 Using where; Using index
|
||||||
|
EXPLAIN SELECT * FROM t1 WHERE a='000000ff-0000-0000-0000-000000000000';
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 SIMPLE t1 ref a a 17 const 1 Using where; Using index
|
||||||
|
EXPLAIN SELECT * FROM t1 WHERE a='00000000-ff00-0000-0000-000000000000';
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 SIMPLE t1 ref a a 17 const 1 Using where; Using index
|
||||||
|
EXPLAIN SELECT * FROM t1 WHERE a='00000000-00ff-0000-0000-000000000000';
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 SIMPLE t1 ref a a 17 const 1 Using where; Using index
|
||||||
|
EXPLAIN SELECT * FROM t1 WHERE a='00000000-0000-ff00-0000-000000000000';
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 SIMPLE t1 ref a a 17 const 1 Using where; Using index
|
||||||
|
EXPLAIN SELECT * FROM t1 WHERE a='00000000-0000-00ff-0000-000000000000';
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 SIMPLE t1 ref a a 17 const 1 Using where; Using index
|
||||||
|
EXPLAIN SELECT * FROM t1 WHERE a='00000000-0000-0000-ff00-000000000000';
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 SIMPLE t1 ref a a 17 const 1 Using where; Using index
|
||||||
|
EXPLAIN SELECT * FROM t1 WHERE a='00000000-0000-0000-00ff-000000000000';
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 SIMPLE t1 ref a a 17 const 1 Using where; Using index
|
||||||
|
EXPLAIN SELECT * FROM t1 WHERE a='00000000-0000-0000-0000-ff0000000000';
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 SIMPLE t1 ref a a 17 const 1 Using where; Using index
|
||||||
|
DROP TABLE t1;
|
||||||
#
|
#
|
||||||
# End of 10.5 tests
|
# End of 10.5 tests
|
||||||
#
|
#
|
||||||
|
@@ -25,7 +25,7 @@ a
|
|||||||
00000000-0000-0000-0000-0000000000ff
|
00000000-0000-0000-0000-0000000000ff
|
||||||
EXPLAIN SELECT * FROM t1 WHERE a='00000000-0000-0000-0000-0000000000ff';
|
EXPLAIN SELECT * FROM t1 WHERE a='00000000-0000-0000-0000-0000000000ff';
|
||||||
id select_type table type possible_keys key key_len ref rows Extra
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
1 SIMPLE t1 ref a a 17 const 2 Using where
|
1 SIMPLE t1 ref a a 17 const 4 Using where
|
||||||
SELECT * FROM t1 WHERE a='garbage';
|
SELECT * FROM t1 WHERE a='garbage';
|
||||||
a
|
a
|
||||||
Warnings:
|
Warnings:
|
||||||
@@ -66,7 +66,7 @@ EXPLAIN SELECT * FROM t1 WHERE a IN
|
|||||||
'00000000-0000-0000-0000-0000000000f0'
|
'00000000-0000-0000-0000-0000000000f0'
|
||||||
);
|
);
|
||||||
id select_type table type possible_keys key key_len ref rows Extra
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
1 SIMPLE t1 range a a 17 NULL 6 Using where
|
1 SIMPLE t1 range a a 17 NULL 12 Using where
|
||||||
SELECT * FROM t1 WHERE a IN
|
SELECT * FROM t1 WHERE a IN
|
||||||
(
|
(
|
||||||
'00000000-0000-0000-0000-000000000080',
|
'00000000-0000-0000-0000-000000000080',
|
||||||
@@ -85,7 +85,7 @@ EXPLAIN SELECT * FROM t1 WHERE a IN
|
|||||||
'garbage'
|
'garbage'
|
||||||
);
|
);
|
||||||
id select_type table type possible_keys key key_len ref rows Extra
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
1 SIMPLE t1 range a a 17 NULL 4 Using where
|
1 SIMPLE t1 range a a 17 NULL 8 Using where
|
||||||
Warnings:
|
Warnings:
|
||||||
Warning 1292 Incorrect uuid value: 'garbage'
|
Warning 1292 Incorrect uuid value: 'garbage'
|
||||||
SELECT * FROM t1 WHERE a BETWEEN
|
SELECT * FROM t1 WHERE a BETWEEN
|
||||||
@@ -178,10 +178,73 @@ a
|
|||||||
00000000-0000-0000-0000-0000000000ff
|
00000000-0000-0000-0000-0000000000ff
|
||||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=CAST('00000000-0000-0000-0000-0000000000ff' AS UUID);
|
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=CAST('00000000-0000-0000-0000-0000000000ff' AS UUID);
|
||||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||||
1 SIMPLE t1 ref a a 17 const 2 100.00 Using where
|
1 SIMPLE t1 ref a a 17 const 4 100.00 Using where
|
||||||
Warnings:
|
Warnings:
|
||||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = UUID'00000000-0000-0000-0000-0000000000ff'
|
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = UUID'00000000-0000-0000-0000-0000000000ff'
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
|
CREATE OR REPLACE TABLE t1 (a UUID,KEY(a));
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
Table Create Table
|
||||||
|
t1 CREATE TABLE `t1` (
|
||||||
|
`a` uuid DEFAULT NULL,
|
||||||
|
KEY `a` (`a`)
|
||||||
|
) ENGINE=MEMORY DEFAULT CHARSET=latin1
|
||||||
|
BEGIN;
|
||||||
|
FOR i IN 0..255
|
||||||
|
DO
|
||||||
|
INSERT INTO t1 VALUES (REPLACE('XX000000-0000-0000-0000-000000000000','XX',LPAD(HEX(i),2,'0')));
|
||||||
|
INSERT INTO t1 VALUES (REPLACE('00XX0000-0000-0000-0000-000000000000','XX',LPAD(HEX(i),2,'0')));
|
||||||
|
INSERT INTO t1 VALUES (REPLACE('0000XX00-0000-0000-0000-000000000000','XX',LPAD(HEX(i),2,'0')));
|
||||||
|
INSERT INTO t1 VALUES (REPLACE('000000XX-0000-0000-0000-000000000000','XX',LPAD(HEX(i),2,'0')));
|
||||||
|
INSERT INTO t1 VALUES (REPLACE('00000000-XX00-0000-0000-000000000000','XX',LPAD(HEX(i),2,'0')));
|
||||||
|
INSERT INTO t1 VALUES (REPLACE('00000000-00XX-0000-0000-000000000000','XX',LPAD(HEX(i),2,'0')));
|
||||||
|
INSERT INTO t1 VALUES (REPLACE('00000000-0000-XX00-0000-000000000000','XX',LPAD(HEX(i),2,'0')));
|
||||||
|
INSERT INTO t1 VALUES (REPLACE('00000000-0000-00XX-0000-000000000000','XX',LPAD(HEX(i),2,'0')));
|
||||||
|
INSERT INTO t1 VALUES (REPLACE('00000000-0000-0000-XX00-000000000000','XX',LPAD(HEX(i),2,'0')));
|
||||||
|
INSERT INTO t1 VALUES (REPLACE('00000000-0000-0000-00XX-000000000000','XX',LPAD(HEX(i),2,'0')));
|
||||||
|
INSERT INTO t1 VALUES (REPLACE('00000000-0000-0000-0000-XX0000000000','XX',LPAD(HEX(i),2,'0')));
|
||||||
|
INSERT INTO t1 VALUES (REPLACE('00000000-0000-0000-0000-00XX00000000','XX',LPAD(HEX(i),2,'0')));
|
||||||
|
INSERT INTO t1 VALUES (REPLACE('00000000-0000-0000-0000-0000XX000000','XX',LPAD(HEX(i),2,'0')));
|
||||||
|
INSERT INTO t1 VALUES (REPLACE('00000000-0000-0000-0000-000000XX0000','XX',LPAD(HEX(i),2,'0')));
|
||||||
|
INSERT INTO t1 VALUES (REPLACE('00000000-0000-0000-0000-00000000XX00','XX',LPAD(HEX(i),2,'0')));
|
||||||
|
INSERT INTO t1 VALUES (REPLACE('00000000-0000-0000-0000-0000000000XX','XX',LPAD(HEX(i),2,'0')));
|
||||||
|
END FOR;
|
||||||
|
$$
|
||||||
|
COMMIT;
|
||||||
|
EXPLAIN SELECT * FROM t1 WHERE a='ff000000-0000-0000-0000-000000000000';
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 SIMPLE t1 ref a a 17 const 2 Using where
|
||||||
|
EXPLAIN SELECT * FROM t1 WHERE a='00ff0000-0000-0000-0000-000000000000';
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 SIMPLE t1 ref a a 17 const 2 Using where
|
||||||
|
EXPLAIN SELECT * FROM t1 WHERE a='0000ff00-0000-0000-0000-000000000000';
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 SIMPLE t1 ref a a 17 const 2 Using where
|
||||||
|
EXPLAIN SELECT * FROM t1 WHERE a='000000ff-0000-0000-0000-000000000000';
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 SIMPLE t1 ref a a 17 const 2 Using where
|
||||||
|
EXPLAIN SELECT * FROM t1 WHERE a='00000000-ff00-0000-0000-000000000000';
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 SIMPLE t1 ref a a 17 const 2 Using where
|
||||||
|
EXPLAIN SELECT * FROM t1 WHERE a='00000000-00ff-0000-0000-000000000000';
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 SIMPLE t1 ref a a 17 const 2 Using where
|
||||||
|
EXPLAIN SELECT * FROM t1 WHERE a='00000000-0000-ff00-0000-000000000000';
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 SIMPLE t1 ref a a 17 const 2 Using where
|
||||||
|
EXPLAIN SELECT * FROM t1 WHERE a='00000000-0000-00ff-0000-000000000000';
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 SIMPLE t1 ref a a 17 const 2 Using where
|
||||||
|
EXPLAIN SELECT * FROM t1 WHERE a='00000000-0000-0000-ff00-000000000000';
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 SIMPLE t1 ref a a 17 const 2 Using where
|
||||||
|
EXPLAIN SELECT * FROM t1 WHERE a='00000000-0000-0000-00ff-000000000000';
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 SIMPLE t1 ref a a 17 const 2 Using where
|
||||||
|
EXPLAIN SELECT * FROM t1 WHERE a='00000000-0000-0000-0000-ff0000000000';
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 SIMPLE t1 ref a a 17 const 2 Using where
|
||||||
|
DROP TABLE t1;
|
||||||
#
|
#
|
||||||
# End of 10.5 tests
|
# End of 10.5 tests
|
||||||
#
|
#
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# Start of 10.5 tests
|
# Start of 10.7 tests
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
# MDEV-4958 Adding datatype UUID
|
# MDEV-4958 Adding datatype UUID
|
||||||
@@ -41,7 +41,7 @@ a
|
|||||||
00000000-0000-0000-0000-0000000000ff
|
00000000-0000-0000-0000-0000000000ff
|
||||||
EXPLAIN SELECT * FROM t1 WHERE a>='00000000-0000-0000-0000-0000000000fe';
|
EXPLAIN SELECT * FROM t1 WHERE a>='00000000-0000-0000-0000-0000000000fe';
|
||||||
id select_type table type possible_keys key key_len ref rows Extra
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
1 SIMPLE t1 range a a 17 NULL 2 Using where; Using index
|
1 SIMPLE t1 range a a 17 NULL 3 Using where; Using index
|
||||||
SELECT * FROM t1 WHERE a>='garbage';
|
SELECT * FROM t1 WHERE a>='garbage';
|
||||||
a
|
a
|
||||||
EXPLAIN SELECT * FROM t1 WHERE a>='garbage';
|
EXPLAIN SELECT * FROM t1 WHERE a>='garbage';
|
||||||
@@ -64,7 +64,7 @@ EXPLAIN SELECT * FROM t1 WHERE a IN
|
|||||||
'00000000-0000-0000-0000-0000000000f0'
|
'00000000-0000-0000-0000-0000000000f0'
|
||||||
);
|
);
|
||||||
id select_type table type possible_keys key key_len ref rows Extra
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
1 SIMPLE t1 range a a 17 NULL 3 Using where; Using index
|
1 SIMPLE t1 range a a 17 NULL 4 Using where; Using index
|
||||||
SELECT * FROM t1 WHERE a IN
|
SELECT * FROM t1 WHERE a IN
|
||||||
(
|
(
|
||||||
'00000000-0000-0000-0000-000000000080',
|
'00000000-0000-0000-0000-000000000080',
|
||||||
@@ -115,6 +115,123 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
|
|||||||
Warnings:
|
Warnings:
|
||||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = UUID'00000000-0000-0000-0000-0000000000ff'
|
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = UUID'00000000-0000-0000-0000-0000000000ff'
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
|
CREATE OR REPLACE TABLE t1 (a UUID,KEY(a));
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
Table Create Table
|
||||||
|
t1 CREATE TABLE `t1` (
|
||||||
|
`a` uuid DEFAULT NULL,
|
||||||
|
KEY `a` (`a`)
|
||||||
|
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||||
|
BEGIN;
|
||||||
|
FOR i IN 0..255
|
||||||
|
DO
|
||||||
|
INSERT INTO t1 VALUES (REPLACE('XX000000-0000-0000-0000-000000000000','XX',LPAD(HEX(i),2,'0')));
|
||||||
|
INSERT INTO t1 VALUES (REPLACE('00XX0000-0000-0000-0000-000000000000','XX',LPAD(HEX(i),2,'0')));
|
||||||
|
INSERT INTO t1 VALUES (REPLACE('0000XX00-0000-0000-0000-000000000000','XX',LPAD(HEX(i),2,'0')));
|
||||||
|
INSERT INTO t1 VALUES (REPLACE('000000XX-0000-0000-0000-000000000000','XX',LPAD(HEX(i),2,'0')));
|
||||||
|
INSERT INTO t1 VALUES (REPLACE('00000000-XX00-0000-0000-000000000000','XX',LPAD(HEX(i),2,'0')));
|
||||||
|
INSERT INTO t1 VALUES (REPLACE('00000000-00XX-0000-0000-000000000000','XX',LPAD(HEX(i),2,'0')));
|
||||||
|
INSERT INTO t1 VALUES (REPLACE('00000000-0000-XX00-0000-000000000000','XX',LPAD(HEX(i),2,'0')));
|
||||||
|
INSERT INTO t1 VALUES (REPLACE('00000000-0000-00XX-0000-000000000000','XX',LPAD(HEX(i),2,'0')));
|
||||||
|
INSERT INTO t1 VALUES (REPLACE('00000000-0000-0000-XX00-000000000000','XX',LPAD(HEX(i),2,'0')));
|
||||||
|
INSERT INTO t1 VALUES (REPLACE('00000000-0000-0000-00XX-000000000000','XX',LPAD(HEX(i),2,'0')));
|
||||||
|
INSERT INTO t1 VALUES (REPLACE('00000000-0000-0000-0000-XX0000000000','XX',LPAD(HEX(i),2,'0')));
|
||||||
|
INSERT INTO t1 VALUES (REPLACE('00000000-0000-0000-0000-00XX00000000','XX',LPAD(HEX(i),2,'0')));
|
||||||
|
INSERT INTO t1 VALUES (REPLACE('00000000-0000-0000-0000-0000XX000000','XX',LPAD(HEX(i),2,'0')));
|
||||||
|
INSERT INTO t1 VALUES (REPLACE('00000000-0000-0000-0000-000000XX0000','XX',LPAD(HEX(i),2,'0')));
|
||||||
|
INSERT INTO t1 VALUES (REPLACE('00000000-0000-0000-0000-00000000XX00','XX',LPAD(HEX(i),2,'0')));
|
||||||
|
INSERT INTO t1 VALUES (REPLACE('00000000-0000-0000-0000-0000000000XX','XX',LPAD(HEX(i),2,'0')));
|
||||||
|
END FOR;
|
||||||
|
$$
|
||||||
|
COMMIT;
|
||||||
|
EXPLAIN SELECT * FROM t1 WHERE a='ff000000-0000-0000-0000-000000000000';
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 SIMPLE t1 ref a a 17 const 1 Using where; Using index
|
||||||
|
EXPLAIN SELECT * FROM t1 WHERE a='00ff0000-0000-0000-0000-000000000000';
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 SIMPLE t1 ref a a 17 const 1 Using where; Using index
|
||||||
|
EXPLAIN SELECT * FROM t1 WHERE a='0000ff00-0000-0000-0000-000000000000';
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 SIMPLE t1 ref a a 17 const 1 Using where; Using index
|
||||||
|
EXPLAIN SELECT * FROM t1 WHERE a='000000ff-0000-0000-0000-000000000000';
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 SIMPLE t1 ref a a 17 const 1 Using where; Using index
|
||||||
|
EXPLAIN SELECT * FROM t1 WHERE a='00000000-ff00-0000-0000-000000000000';
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 SIMPLE t1 ref a a 17 const 1 Using where; Using index
|
||||||
|
EXPLAIN SELECT * FROM t1 WHERE a='00000000-00ff-0000-0000-000000000000';
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 SIMPLE t1 ref a a 17 const 1 Using where; Using index
|
||||||
|
EXPLAIN SELECT * FROM t1 WHERE a='00000000-0000-ff00-0000-000000000000';
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 SIMPLE t1 ref a a 17 const 1 Using where; Using index
|
||||||
|
EXPLAIN SELECT * FROM t1 WHERE a='00000000-0000-00ff-0000-000000000000';
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 SIMPLE t1 ref a a 17 const 1 Using where; Using index
|
||||||
|
EXPLAIN SELECT * FROM t1 WHERE a='00000000-0000-0000-ff00-000000000000';
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 SIMPLE t1 ref a a 17 const 1 Using where; Using index
|
||||||
|
EXPLAIN SELECT * FROM t1 WHERE a='00000000-0000-0000-00ff-000000000000';
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 SIMPLE t1 ref a a 17 const 1 Using where; Using index
|
||||||
|
EXPLAIN SELECT * FROM t1 WHERE a='00000000-0000-0000-0000-ff0000000000';
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 SIMPLE t1 ref a a 17 const 1 Using where; Using index
|
||||||
|
DROP TABLE t1;
|
||||||
#
|
#
|
||||||
# End of 10.5 tests
|
# Testing index prefix compression
|
||||||
|
#
|
||||||
|
CREATE PROCEDURE test_pack_key()
|
||||||
|
BEGIN
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
FOR i IN 0..0x1FFF
|
||||||
|
DO
|
||||||
|
INSERT INTO t1 VALUES (UUID());
|
||||||
|
END FOR;
|
||||||
|
SELECT
|
||||||
|
CASE
|
||||||
|
WHEN INDEX_LENGTH/DATA_LENGTH < 0.7 THEN 'PACKED'
|
||||||
|
WHEN INDEX_LENGTH/DATA_LENGTH > 1.2 THEN 'NOT PACKED'
|
||||||
|
ELSE CONCAT('UNKNOWN ', INDEX_LENGTH/DATA_LENGTH)
|
||||||
|
END AS PackKey
|
||||||
|
FROM INFORMATION_SCHEMA.TABLES
|
||||||
|
WHERE TABLE_SCHEMA='test' AND TABLE_NAME='t1';
|
||||||
|
END;
|
||||||
|
$$
|
||||||
|
"------------------ CREATE TABLE"
|
||||||
|
CREATE TABLE t1 (a UUID, KEY(a));
|
||||||
|
CALL test_pack_key();
|
||||||
|
Table Create Table
|
||||||
|
t1 CREATE TABLE `t1` (
|
||||||
|
`a` uuid DEFAULT NULL,
|
||||||
|
KEY `a` (`a`)
|
||||||
|
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||||
|
PackKey
|
||||||
|
PACKED
|
||||||
|
DROP TABLE t1;
|
||||||
|
"------------------ t1packkey.frm"
|
||||||
|
TRUNCATE TABLE t1;
|
||||||
|
CALL test_pack_key();
|
||||||
|
Table Create Table
|
||||||
|
t1 CREATE TABLE `t1` (
|
||||||
|
`a` uuid DEFAULT NULL,
|
||||||
|
KEY `a` (`a`)
|
||||||
|
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||||
|
PackKey
|
||||||
|
PACKED
|
||||||
|
DROP TABLE t1;
|
||||||
|
"------------------ t1nopackkey.frm"
|
||||||
|
TRUNCATE TABLE t1;
|
||||||
|
CALL test_pack_key();
|
||||||
|
Table Create Table
|
||||||
|
t1 CREATE TABLE `t1` (
|
||||||
|
`a` uuid DEFAULT NULL,
|
||||||
|
KEY `a` (`a`)
|
||||||
|
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||||
|
PackKey
|
||||||
|
NOT PACKED
|
||||||
|
DROP TABLE t1;
|
||||||
|
DROP PROCEDURE test_pack_key;
|
||||||
|
#
|
||||||
|
# End of 10.7 tests
|
||||||
#
|
#
|
||||||
|
@@ -1,5 +1,7 @@
|
|||||||
|
let $MYSQLD_DATADIR= `select @@datadir`;
|
||||||
|
|
||||||
--echo #
|
--echo #
|
||||||
--echo # Start of 10.5 tests
|
--echo # Start of 10.7 tests
|
||||||
--echo #
|
--echo #
|
||||||
|
|
||||||
--echo #
|
--echo #
|
||||||
@@ -10,7 +12,50 @@
|
|||||||
SET default_storage_engine=MyISAM;
|
SET default_storage_engine=MyISAM;
|
||||||
--source type_uuid_engines.inc
|
--source type_uuid_engines.inc
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # Testing index prefix compression
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
DELIMITER $$;
|
||||||
|
CREATE PROCEDURE test_pack_key()
|
||||||
|
BEGIN
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
FOR i IN 0..0x1FFF
|
||||||
|
DO
|
||||||
|
INSERT INTO t1 VALUES (UUID());
|
||||||
|
END FOR;
|
||||||
|
SELECT
|
||||||
|
CASE
|
||||||
|
WHEN INDEX_LENGTH/DATA_LENGTH < 0.7 THEN 'PACKED'
|
||||||
|
WHEN INDEX_LENGTH/DATA_LENGTH > 1.2 THEN 'NOT PACKED'
|
||||||
|
ELSE CONCAT('UNKNOWN ', INDEX_LENGTH/DATA_LENGTH)
|
||||||
|
END AS PackKey
|
||||||
|
FROM INFORMATION_SCHEMA.TABLES
|
||||||
|
WHERE TABLE_SCHEMA='test' AND TABLE_NAME='t1';
|
||||||
|
END;
|
||||||
|
$$
|
||||||
|
DELIMITER ;$$
|
||||||
|
|
||||||
|
--echo "------------------ CREATE TABLE"
|
||||||
|
CREATE TABLE t1 (a UUID, KEY(a));
|
||||||
|
CALL test_pack_key();
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
--echo "------------------ t1packkey.frm"
|
||||||
|
--copy_file $MTR_SUITE_DIR/std_data/t1packkey.frm $MYSQLD_DATADIR/test/t1.frm
|
||||||
|
TRUNCATE TABLE t1;
|
||||||
|
CALL test_pack_key();
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
--echo "------------------ t1nopackkey.frm"
|
||||||
|
--copy_file $MTR_SUITE_DIR/std_data/t1nopackkey.frm $MYSQLD_DATADIR/test/t1.frm
|
||||||
|
TRUNCATE TABLE t1;
|
||||||
|
CALL test_pack_key();
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
|
||||||
|
DROP PROCEDURE test_pack_key;
|
||||||
|
|
||||||
--echo #
|
--echo #
|
||||||
--echo # End of 10.5 tests
|
--echo # End of 10.7 tests
|
||||||
--echo #
|
--echo #
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -30,3 +30,75 @@ INSERT INTO t1 VALUES ('ffff0000-0000-0000-0000-00000000ffff');
|
|||||||
SELECT * FROM t1 PARTITION (p00);
|
SELECT * FROM t1 PARTITION (p00);
|
||||||
SELECT * FROM t1 PARTITION (pFF);
|
SELECT * FROM t1 PARTITION (pFF);
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
|
||||||
|
CREATE TABLE t0 (a UUID);
|
||||||
|
DELIMITER $$;
|
||||||
|
FOR i IN 0..255
|
||||||
|
DO
|
||||||
|
INSERT INTO t0 VALUES (REPLACE('XXfd306d-307f-11ec-8d10-d20bbc909b57','XX',LPAD(HEX(i),2,'0')));
|
||||||
|
INSERT INTO t0 VALUES (REPLACE('9cfd306d-XX7f-12ec-8d10-d20bbc909b57','XX',LPAD(HEX(i),2,'0')));
|
||||||
|
INSERT INTO t0 VALUES (REPLACE('9cfd306d-307f-13XX-8d10-d20bbc909b57','XX',LPAD(HEX(i),2,'0')));
|
||||||
|
INSERT INTO t0 VALUES (REPLACE('9cfd306d-307f-14ec-8dXX-d20bbc909b57','XX',LPAD(HEX(i),2,'0')));
|
||||||
|
INSERT INTO t0 VALUES (REPLACE('9cfd306d-307f-15ec-8d10-XX0bbc909b57','XX',LPAD(HEX(i),2,'0')));
|
||||||
|
INSERT INTO t0 VALUES (REPLACE('9cfd306d-307f-16ec-8d10-d20bbc909bXX','XX',LPAD(HEX(i),2,'0')));
|
||||||
|
END FOR;
|
||||||
|
$$
|
||||||
|
--echo # Test that UUID and BINARY(16) implement the same distribution by key
|
||||||
|
CREATE PROCEDURE test_partition_by_key_uuid_vs_binary(parts INT)
|
||||||
|
BEGIN
|
||||||
|
EXECUTE IMMEDIATE REPLACE('CREATE TABLE t1 (a UUID) PARTITION BY KEY (a) PARTITIONS 7','7',parts);
|
||||||
|
EXECUTE IMMEDIATE REPLACE('CREATE TABLE t2 (a BINARY(16)) PARTITION BY KEY (a) PARTITIONS 7','7',parts);
|
||||||
|
INSERT INTO t1 SELECT * FROM t0;
|
||||||
|
INSERT INTO t2 SELECT * FROM t0;
|
||||||
|
FOR i IN 0..(parts-1)
|
||||||
|
DO
|
||||||
|
BEGIN
|
||||||
|
DECLARE query_template TEXT DEFAULT 'SELECT a_p0, COUNT(*) FROM ('
|
||||||
|
'SELECT a AS a_p0 FROM t1 PARTITION(p0) '
|
||||||
|
'UNION ALL '
|
||||||
|
'SELECT CAST(a AS UUID) AS a_p0 FROM t2 PARTITION(p0)) td '
|
||||||
|
'GROUP BY a_p0';
|
||||||
|
DECLARE query TEXT DEFAULT REPLACE(query_template,'p0',CONCAT('p',i));
|
||||||
|
SELECT query;
|
||||||
|
EXECUTE IMMEDIATE query;
|
||||||
|
END;
|
||||||
|
END FOR;
|
||||||
|
DROP TABLE t1,t2;
|
||||||
|
END;
|
||||||
|
$$
|
||||||
|
--echo # Display statistics how records are distributed between partitions
|
||||||
|
CREATE PROCEDURE test_partition_by_key_pstat(parts INT)
|
||||||
|
BEGIN
|
||||||
|
EXECUTE IMMEDIATE REPLACE('CREATE TABLE t1 (a UUID) PARTITION BY KEY (a) PARTITIONS 7','7',parts);
|
||||||
|
CREATE TABLE t1_pstat (pname VARCHAR(32), pcount int);
|
||||||
|
INSERT INTO t1 SELECT * FROM t0;
|
||||||
|
FOR i IN 0..(parts-1)
|
||||||
|
DO
|
||||||
|
BEGIN
|
||||||
|
DECLARE query_template TEXT DEFAULT 'INSERT INTO t1_pstat VALUES (''p0'',(SELECT COUNT(*) FROM t1 PARTITION (p0)))';
|
||||||
|
EXECUTE IMMEDIATE REPLACE(query_template,'p0',CONCAT('p',i));
|
||||||
|
END;
|
||||||
|
END FOR;
|
||||||
|
SELECT * FROM t1_pstat ORDER BY CAST(SUBSTR(pname,2,100) AS UNSIGNED);
|
||||||
|
DROP TABLE t1,t1_pstat;
|
||||||
|
END;
|
||||||
|
$$
|
||||||
|
DELIMITER ;$$
|
||||||
|
CALL test_partition_by_key_uuid_vs_binary(7);
|
||||||
|
CALL test_partition_by_key_pstat(7);
|
||||||
|
CALL test_partition_by_key_pstat(4);
|
||||||
|
CALL test_partition_by_key_pstat(5);
|
||||||
|
CALL test_partition_by_key_pstat(6);
|
||||||
|
CALL test_partition_by_key_pstat(8);
|
||||||
|
CALL test_partition_by_key_pstat(9);
|
||||||
|
CALL test_partition_by_key_pstat(10);
|
||||||
|
CALL test_partition_by_key_pstat(11);
|
||||||
|
CALL test_partition_by_key_pstat(12);
|
||||||
|
CALL test_partition_by_key_pstat(13);
|
||||||
|
CALL test_partition_by_key_pstat(14);
|
||||||
|
CALL test_partition_by_key_pstat(15);
|
||||||
|
CALL test_partition_by_key_pstat(16);
|
||||||
|
DROP PROCEDURE test_partition_by_key_uuid_vs_binary;
|
||||||
|
DROP PROCEDURE test_partition_by_key_pstat;
|
||||||
|
DROP TABLE t0;
|
||||||
|
@@ -24,8 +24,162 @@ public:
|
|||||||
bool ascii_to_fbt(const char *str, size_t str_length);
|
bool ascii_to_fbt(const char *str, size_t str_length);
|
||||||
size_t to_string(char *dst, size_t dstsize) const;
|
size_t to_string(char *dst, size_t dstsize) const;
|
||||||
static const Name &default_value();
|
static const Name &default_value();
|
||||||
|
|
||||||
|
/*
|
||||||
|
Binary (in-memory) UUIDv1 representation:
|
||||||
|
|
||||||
|
llllllll-mmmm-Vhhh-vsss-nnnnnnnnnnnn
|
||||||
|
|
||||||
|
Binary sortable (in-record) representation:
|
||||||
|
|
||||||
|
nnnnnnnnnnnn-vsss-Vhhh-mmmm-llllllll
|
||||||
|
|
||||||
|
Sign Section Bits Bytes Pos PosBinSortable
|
||||||
|
------------- ------- ---- ----- --- --------------
|
||||||
|
llllllll time low 32 4 0 12
|
||||||
|
mmmm time mid 16 2 4 10
|
||||||
|
Vhhh version and time hi 16 2 6 8
|
||||||
|
vsss variant and clock seq 16 2 8 6
|
||||||
|
nnnnnnnnnnnn node ID 48 6 10 0
|
||||||
|
*/
|
||||||
|
|
||||||
|
class Segment
|
||||||
|
{
|
||||||
|
size_t m_memory_pos;
|
||||||
|
size_t m_record_pos;
|
||||||
|
size_t m_length;
|
||||||
|
public:
|
||||||
|
constexpr Segment(size_t memory_pos, size_t record_pos, size_t length)
|
||||||
|
:m_memory_pos(memory_pos), m_record_pos(record_pos), m_length(length)
|
||||||
|
{ }
|
||||||
|
void memory_to_record(char *to, const char *from) const
|
||||||
|
{
|
||||||
|
memcpy(to + m_record_pos, from + m_memory_pos, m_length);
|
||||||
|
}
|
||||||
|
void record_to_memory(char *to, const char * from) const
|
||||||
|
{
|
||||||
|
memcpy(to + m_memory_pos, from + m_record_pos, m_length);
|
||||||
|
}
|
||||||
|
int cmp_memory(const char *a, const char *b) const
|
||||||
|
{
|
||||||
|
return memcmp(a + m_memory_pos, b + m_memory_pos, m_length);
|
||||||
|
}
|
||||||
|
void hash_record(const uchar *ptr, ulong *nr, ulong *nr2) const
|
||||||
|
{
|
||||||
|
my_charset_bin.hash_sort(ptr + m_record_pos, m_length, nr, nr2);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static const Segment & segment(uint i)
|
||||||
|
{
|
||||||
|
static Segment segments[]=
|
||||||
|
{
|
||||||
|
{0, 12, 4}, // llllllll
|
||||||
|
{4, 10, 2}, // mmmm
|
||||||
|
{6, 8, 2}, // Vhhh
|
||||||
|
{8, 6, 2}, // vsss
|
||||||
|
{10, 0, 6} // nnnnnnnnnnnn
|
||||||
|
};
|
||||||
|
return segments[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert the in-memory representation to the in-record representation
|
||||||
|
static void memory_to_record(char *to, const char *from)
|
||||||
|
{
|
||||||
|
segment(0).memory_to_record(to, from);
|
||||||
|
segment(1).memory_to_record(to, from);
|
||||||
|
segment(2).memory_to_record(to, from);
|
||||||
|
segment(3).memory_to_record(to, from);
|
||||||
|
segment(4).memory_to_record(to, from);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert the in-record representation to the in-memory representation
|
||||||
|
static void record_to_memory(char *to, const char *from)
|
||||||
|
{
|
||||||
|
segment(0).record_to_memory(to, from);
|
||||||
|
segment(1).record_to_memory(to, from);
|
||||||
|
segment(2).record_to_memory(to, from);
|
||||||
|
segment(3).record_to_memory(to, from);
|
||||||
|
segment(4).record_to_memory(to, from);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Calculate a hash of the in-record representation.
|
||||||
|
Used in Field_uuid::hash(), e.g. for KEY partitioning. This
|
||||||
|
makes partition distribution for UUID and BINARY(16) equal,
|
||||||
|
so for example:
|
||||||
|
|
||||||
|
CREATE OR REPLACE TABLE t1 (c1 UUID) PARTITION BY KEY(c1) PARTITIONS 5;
|
||||||
|
INSERT INTO t1 (c1) VALUES (UUID());
|
||||||
|
|
||||||
|
and
|
||||||
|
|
||||||
|
CREATE OR REPLACE TABLE t1 (c1 BINARY(16)) PARTITION BY KEY(c1) PARTITIONS 5;
|
||||||
|
INSERT INTO t1 (c1) VALUES (UUID());
|
||||||
|
|
||||||
|
put values into the same partition.
|
||||||
|
*/
|
||||||
|
static void hash_record(const uchar *ptr, ulong *nr, ulong *nr2)
|
||||||
|
{
|
||||||
|
segment(0).hash_record(ptr, nr, nr2);
|
||||||
|
segment(1).hash_record(ptr, nr, nr2);
|
||||||
|
segment(2).hash_record(ptr, nr, nr2);
|
||||||
|
segment(3).hash_record(ptr, nr, nr2);
|
||||||
|
segment(4).hash_record(ptr, nr, nr2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compare two in-memory values
|
||||||
|
static int cmp(const LEX_CSTRING &a, const LEX_CSTRING &b)
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(a.length == binary_length());
|
||||||
|
DBUG_ASSERT(b.length == binary_length());
|
||||||
|
int res;
|
||||||
|
if ((res= segment(4).cmp_memory(a.str, b.str)) ||
|
||||||
|
(res= segment(3).cmp_memory(a.str, b.str)) ||
|
||||||
|
(res= segment(2).cmp_memory(a.str, b.str)) ||
|
||||||
|
(res= segment(1).cmp_memory(a.str, b.str)) ||
|
||||||
|
(res= segment(0).cmp_memory(a.str, b.str)))
|
||||||
|
return res;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ulong KEY_pack_flags(uint column_nr)
|
||||||
|
{
|
||||||
|
return HA_PACK_KEY;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Convert in-record representation to binlog representation.
|
||||||
|
We tranfer UUID values in binlog by compressing in-memory representation.
|
||||||
|
This makes replication between UUID and BINARY(16) simpler:
|
||||||
|
|
||||||
|
Transferring by compressing the in-record representation would require
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
uchar buf[binary_length()];
|
||||||
|
record_to_memory((char *) buf, (const char *) from);
|
||||||
|
return StringPack(&my_charset_bin, binary_length()).
|
||||||
|
pack(to, buf, max_length);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert binlog representation to in-record representation
|
||||||
|
static const uchar *unpack(uchar *to,
|
||||||
|
const uchar *from, const uchar *from_end,
|
||||||
|
uint param_data)
|
||||||
|
{
|
||||||
|
uchar buf[binary_length()];
|
||||||
|
const uchar *rc= StringPack(&my_charset_bin, binary_length()).
|
||||||
|
unpack(buf, from, from_end, param_data);
|
||||||
|
memory_to_record((char *) to, (const char *) buf);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#include "sql_type_fixedbin.h"
|
#include "sql_type_fixedbin.h"
|
||||||
typedef FixedBinTypeBundle<UUID> UUIDBundle;
|
typedef FixedBinTypeBundle<UUID> UUIDBundle;
|
||||||
|
|
||||||
|
@@ -484,6 +484,11 @@ public:
|
|||||||
if (str.Alloced_length)
|
if (str.Alloced_length)
|
||||||
Alloced_length= (uint32) (str.Alloced_length - offset);
|
Alloced_length= (uint32) (str.Alloced_length - offset);
|
||||||
}
|
}
|
||||||
|
LEX_CSTRING to_lex_cstring() const
|
||||||
|
{
|
||||||
|
LEX_CSTRING tmp= {Ptr, str_length};
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
inline LEX_CSTRING *get_value(LEX_CSTRING *res)
|
inline LEX_CSTRING *get_value(LEX_CSTRING *res)
|
||||||
{
|
{
|
||||||
res->str= Ptr;
|
res->str= Ptr;
|
||||||
|
@@ -111,6 +111,12 @@ public:
|
|||||||
return fbt;
|
return fbt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Fbt record_to_memory(const char *ptr)
|
||||||
|
{
|
||||||
|
Fbt fbt;
|
||||||
|
FbtImpl::record_to_memory(fbt.m_buffer, ptr);
|
||||||
|
return fbt;
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
Check at Item's fix_fields() time if "item" can return a nullable value
|
Check at Item's fix_fields() time if "item" can return a nullable value
|
||||||
on conversion to Fbt, or conversion produces a NOT NULL Fbt value.
|
on conversion to Fbt, or conversion produces a NOT NULL Fbt value.
|
||||||
@@ -132,10 +138,10 @@ public:
|
|||||||
{
|
{
|
||||||
*error= make_from_item(item, warn);
|
*error= make_from_item(item, warn);
|
||||||
}
|
}
|
||||||
void to_binary(char *str, size_t str_size) const
|
void to_record(char *str, size_t str_size) const
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(str_size >= sizeof(m_buffer));
|
DBUG_ASSERT(str_size >= sizeof(m_buffer));
|
||||||
memcpy(str, m_buffer, sizeof(m_buffer));
|
FbtImpl::memory_to_record(str, m_buffer);
|
||||||
}
|
}
|
||||||
bool to_binary(String *to) const
|
bool to_binary(String *to) const
|
||||||
{
|
{
|
||||||
@@ -154,18 +160,13 @@ public:
|
|||||||
FbtImpl::max_char_length()+1));
|
FbtImpl::max_char_length()+1));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
int cmp(const char *str, size_t length) const
|
|
||||||
{
|
|
||||||
DBUG_ASSERT(length == sizeof(m_buffer));
|
|
||||||
return memcmp(m_buffer, str, length);
|
|
||||||
}
|
|
||||||
int cmp(const Binary_string &other) const
|
int cmp(const Binary_string &other) const
|
||||||
{
|
{
|
||||||
return cmp(other.ptr(), other.length());
|
return FbtImpl::cmp(FbtImpl::to_lex_cstring(), other.to_lex_cstring());
|
||||||
}
|
}
|
||||||
int cmp(const Fbt &other) const
|
int cmp(const Fbt &other) const
|
||||||
{
|
{
|
||||||
return memcmp(m_buffer, other.m_buffer, sizeof(m_buffer));
|
return FbtImpl::cmp(FbtImpl::to_lex_cstring(), other.to_lex_cstring());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -191,9 +192,9 @@ public:
|
|||||||
DBUG_ASSERT(!is_null());
|
DBUG_ASSERT(!is_null());
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
void to_binary(char *str, size_t str_size) const
|
void to_record(char *str, size_t str_size) const
|
||||||
{
|
{
|
||||||
to_fbt().to_binary(str, str_size);
|
to_fbt().to_record(str, str_size);
|
||||||
}
|
}
|
||||||
bool to_binary(String *to) const
|
bool to_binary(String *to) const
|
||||||
{
|
{
|
||||||
@@ -257,6 +258,10 @@ public:
|
|||||||
{
|
{
|
||||||
return FbtImpl::default_value();
|
return FbtImpl::default_value();
|
||||||
}
|
}
|
||||||
|
ulong KEY_pack_flags(uint column_nr) const override
|
||||||
|
{
|
||||||
|
return FbtImpl::KEY_pack_flags(column_nr);
|
||||||
|
}
|
||||||
protocol_send_type_t protocol_send_type() const override
|
protocol_send_type_t protocol_send_type() const override
|
||||||
{
|
{
|
||||||
return PROTOCOL_SEND_STRING;
|
return PROTOCOL_SEND_STRING;
|
||||||
@@ -480,7 +485,7 @@ public:
|
|||||||
DBUG_ASSERT(!item->null_value);
|
DBUG_ASSERT(!item->null_value);
|
||||||
DBUG_ASSERT(FbtImpl::binary_length() == tmp.length());
|
DBUG_ASSERT(FbtImpl::binary_length() == tmp.length());
|
||||||
DBUG_ASSERT(FbtImpl::binary_length() == sort_field->length);
|
DBUG_ASSERT(FbtImpl::binary_length() == sort_field->length);
|
||||||
memcpy(to, tmp.ptr(), tmp.length());
|
FbtImpl::memory_to_record((char*) to, tmp.ptr());
|
||||||
}
|
}
|
||||||
uint make_packed_sort_key_part(uchar *to, Item *item,
|
uint make_packed_sort_key_part(uchar *to, Item *item,
|
||||||
const SORT_FIELD_ATTR *sort_field,
|
const SORT_FIELD_ATTR *sort_field,
|
||||||
@@ -501,7 +506,7 @@ public:
|
|||||||
DBUG_ASSERT(!item->null_value);
|
DBUG_ASSERT(!item->null_value);
|
||||||
DBUG_ASSERT(FbtImpl::binary_length() == tmp.length());
|
DBUG_ASSERT(FbtImpl::binary_length() == tmp.length());
|
||||||
DBUG_ASSERT(FbtImpl::binary_length() == sort_field->length);
|
DBUG_ASSERT(FbtImpl::binary_length() == sort_field->length);
|
||||||
memcpy(to, tmp.ptr(), tmp.length());
|
FbtImpl::memory_to_record((char*) to, tmp.ptr());
|
||||||
return tmp.length();
|
return tmp.length();
|
||||||
}
|
}
|
||||||
void sort_length(THD *thd, const Type_std_attributes *item,
|
void sort_length(THD *thd, const Type_std_attributes *item,
|
||||||
@@ -700,9 +705,7 @@ public:
|
|||||||
}
|
}
|
||||||
int cmp_native(const Native &a, const Native &b) const override
|
int cmp_native(const Native &a, const Native &b) const override
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(a.length() == FbtImpl::binary_length());
|
return FbtImpl::cmp(a.to_lex_cstring(), b.to_lex_cstring());
|
||||||
DBUG_ASSERT(b.length() == FbtImpl::binary_length());
|
|
||||||
return memcmp(a.ptr(), b.ptr(), FbtImpl::binary_length());
|
|
||||||
}
|
}
|
||||||
bool set_comparator_func(THD *thd, Arg_comparator *cmp) const override
|
bool set_comparator_func(THD *thd, Arg_comparator *cmp) const override
|
||||||
{
|
{
|
||||||
@@ -1107,7 +1110,7 @@ public:
|
|||||||
if (fbt.is_null())
|
if (fbt.is_null())
|
||||||
return maybe_null() ? set_null_with_warn(err)
|
return maybe_null() ? set_null_with_warn(err)
|
||||||
: set_min_value_with_warn(err);
|
: set_min_value_with_warn(err);
|
||||||
fbt.to_binary((char *) ptr, FbtImpl::binary_length());
|
fbt.to_record((char *) ptr, FbtImpl::binary_length());
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1184,11 +1187,27 @@ public:
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
String *val_str(String *val_buffer, String *) override
|
bool val_native(Native *to) override
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(marked_for_read());
|
DBUG_ASSERT(marked_for_read());
|
||||||
Fbt_null tmp((const char *) ptr, pack_length());
|
DBUG_ASSERT(!is_null());
|
||||||
return tmp.to_string(val_buffer) ? NULL : val_buffer;
|
if (to->alloc(FbtImpl::binary_length()))
|
||||||
|
return true;
|
||||||
|
to->length(FbtImpl::binary_length());
|
||||||
|
FbtImpl::record_to_memory((char*) to->ptr(), (const char*) ptr);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Fbt to_fbt() const
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(marked_for_read());
|
||||||
|
DBUG_ASSERT(!is_null());
|
||||||
|
return Fbt::record_to_memory((const char*) ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
String *val_str(String *val_buffer, String *) override
|
||||||
|
{
|
||||||
|
return to_fbt().to_string(val_buffer) ? NULL : val_buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
my_decimal *val_decimal(my_decimal *to) override
|
my_decimal *val_decimal(my_decimal *to) override
|
||||||
@@ -1227,7 +1246,7 @@ public:
|
|||||||
{
|
{
|
||||||
DBUG_ASSERT(marked_for_write_or_computed());
|
DBUG_ASSERT(marked_for_write_or_computed());
|
||||||
DBUG_ASSERT(value.length() == FbtImpl::binary_length());
|
DBUG_ASSERT(value.length() == FbtImpl::binary_length());
|
||||||
memcpy(ptr, value.ptr(), value.length());
|
FbtImpl::memory_to_record((char*) ptr, value.ptr());
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1409,6 +1428,13 @@ public:
|
|||||||
item->type_handler() == type_handler());
|
item->type_handler() == type_handler());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
void hash(ulong *nr, ulong *nr2)
|
||||||
|
{
|
||||||
|
if (is_null())
|
||||||
|
*nr^= (*nr << 1) | 1;
|
||||||
|
else
|
||||||
|
FbtImpl::hash_record(ptr, nr, nr2);
|
||||||
|
}
|
||||||
SEL_ARG *get_mm_leaf(RANGE_OPT_PARAM *prm, KEY_PART *key_part,
|
SEL_ARG *get_mm_leaf(RANGE_OPT_PARAM *prm, KEY_PART *key_part,
|
||||||
const Item_bool_func *cond,
|
const Item_bool_func *cond,
|
||||||
scalar_comparison_op op, Item *value) override
|
scalar_comparison_op op, Item *value) override
|
||||||
@@ -1450,13 +1476,13 @@ public:
|
|||||||
uchar *pack(uchar *to, const uchar *from, uint max_length) override
|
uchar *pack(uchar *to, const uchar *from, uint max_length) override
|
||||||
{
|
{
|
||||||
DBUG_PRINT("debug", ("Packing field '%s'", field_name.str));
|
DBUG_PRINT("debug", ("Packing field '%s'", field_name.str));
|
||||||
return StringPack(&my_charset_bin, FbtImpl::binary_length()).pack(to, from, max_length);
|
return FbtImpl::pack(to, from, max_length);
|
||||||
}
|
}
|
||||||
|
|
||||||
const uchar *unpack(uchar *to, const uchar *from, const uchar *from_end,
|
const uchar *unpack(uchar *to, const uchar *from, const uchar *from_end,
|
||||||
uint param_data) override
|
uint param_data) override
|
||||||
{
|
{
|
||||||
return StringPack(&my_charset_bin, FbtImpl::binary_length()).unpack(to, from, from_end, param_data);
|
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) override
|
||||||
|
@@ -21,6 +21,38 @@
|
|||||||
format and their own (variable size) canonical string representation.
|
format and their own (variable size) canonical string representation.
|
||||||
|
|
||||||
Examples are INET6 and UUID types.
|
Examples are INET6 and UUID types.
|
||||||
|
|
||||||
|
The MariaDB server uses three binary representations of a data type:
|
||||||
|
|
||||||
|
1. In-memory binary representation (user visible)
|
||||||
|
This representation:
|
||||||
|
- can be used in INSERT..VALUES (X'AABBCC')
|
||||||
|
- can be used in WHERE conditions: WHERE c1=X'AABBCC'
|
||||||
|
- is returned by CAST(x AS BINARY(N))
|
||||||
|
- is returned by Field::val_native() and Item::val_native()
|
||||||
|
|
||||||
|
2. In-record binary representation (user invisible)
|
||||||
|
This representation:
|
||||||
|
- is used in records (is pointed by Field::ptr)
|
||||||
|
- must be comparable by memcmp()
|
||||||
|
|
||||||
|
3. Binlog binary (row) representation
|
||||||
|
Usually, for string data types the binlog representation
|
||||||
|
is based on the in-record representation with trailing byte compression:
|
||||||
|
- trailing space compression for text string data types
|
||||||
|
- trailing zero compression for binary string data types
|
||||||
|
|
||||||
|
We have to have separate in-memory and in-record representations
|
||||||
|
because we use HA_KEYTYPE_BINARY for indexing. The engine API
|
||||||
|
does not have a way to pass a comparison function as a parameter.
|
||||||
|
|
||||||
|
The default implementation below assumes that:
|
||||||
|
- the in-memory and in-record representations are equal
|
||||||
|
- the binlog representation is compatible with BINARY(N)
|
||||||
|
This is OK for simple data types, like INET6.
|
||||||
|
|
||||||
|
Data type implementations that need different representations
|
||||||
|
can override the default implementation (like e.g. UUID does).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
@@ -29,6 +61,7 @@ template<size_t NATIVE_LEN, size_t MAX_CHAR_LEN>
|
|||||||
class FixedBinTypeStorage
|
class FixedBinTypeStorage
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
|
// The buffer that stores the in-memory binary representation
|
||||||
char m_buffer[NATIVE_LEN];
|
char m_buffer[NATIVE_LEN];
|
||||||
|
|
||||||
// Non-initializing constructor
|
// Non-initializing constructor
|
||||||
@@ -42,7 +75,7 @@ protected:
|
|||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
|
|
||||||
// Initialize from binary representation
|
// Initialize from the in-memory binary representation
|
||||||
FixedBinTypeStorage(const char *str, size_t length)
|
FixedBinTypeStorage(const char *str, size_t length)
|
||||||
{
|
{
|
||||||
if (length != binary_length())
|
if (length != binary_length())
|
||||||
@@ -51,9 +84,49 @@ public:
|
|||||||
memcpy(&m_buffer, str, sizeof(m_buffer));
|
memcpy(&m_buffer, str, sizeof(m_buffer));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Return the buffer with the in-memory representation
|
||||||
|
Lex_cstring to_lex_cstring() const
|
||||||
|
{
|
||||||
|
return Lex_cstring(m_buffer, sizeof(m_buffer));
|
||||||
|
}
|
||||||
|
|
||||||
static constexpr uint binary_length() { return NATIVE_LEN; }
|
static constexpr uint binary_length() { return NATIVE_LEN; }
|
||||||
static constexpr uint max_char_length() { return MAX_CHAR_LEN; }
|
static constexpr uint max_char_length() { return MAX_CHAR_LEN; }
|
||||||
|
|
||||||
|
// Compare the in-memory binary representations of two values
|
||||||
|
static int cmp(const LEX_CSTRING &a, const LEX_CSTRING &b)
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(a.length == binary_length());
|
||||||
|
DBUG_ASSERT(b.length == binary_length());
|
||||||
|
return memcmp(a.str, b.str, b.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Convert from the in-memory to the in-record representation.
|
||||||
|
Used in Field::store_native().
|
||||||
|
*/
|
||||||
|
static void memory_to_record(char *to, const char *from)
|
||||||
|
{
|
||||||
|
memcpy(to, from, NATIVE_LEN);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
Convert from the in-record to the in-memory representation
|
||||||
|
Used in Field::val_native().
|
||||||
|
*/
|
||||||
|
static void record_to_memory(char *to, const char *from)
|
||||||
|
{
|
||||||
|
memcpy(to, from, NATIVE_LEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Hash the in-record representation
|
||||||
|
Used in Field::hash().
|
||||||
|
*/
|
||||||
|
static void hash_record(const uchar *ptr, ulong *nr, ulong *nr2)
|
||||||
|
{
|
||||||
|
my_charset_bin.hash_sort(ptr, binary_length(), nr, nr2);
|
||||||
|
}
|
||||||
|
|
||||||
static bool only_zero_bytes(const char *ptr, size_t length)
|
static bool only_zero_bytes(const char *ptr, size_t length)
|
||||||
{
|
{
|
||||||
for (uint i= 0 ; i < length; i++)
|
for (uint i= 0 ; i < length; i++)
|
||||||
@@ -64,5 +137,37 @@ public:
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ulong KEY_pack_flags(uint column_nr)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Return zero by default. A particular data type can override
|
||||||
|
this method return some flags, e.g. HA_PACK_KEY to enable
|
||||||
|
key prefix compression.
|
||||||
|
*/
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Convert from the in-record to the binlog representation.
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
return StringPack(&my_charset_bin, binary_length()).pack(to, from, max_length);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Convert from the in-binary-log to the in-record representation.
|
||||||
|
Used in Field::unpack().
|
||||||
|
By default, do what BINARY(N) does.
|
||||||
|
*/
|
||||||
|
static const uchar *unpack(uchar *to, const uchar *from, const uchar *from_end,
|
||||||
|
uint param_data)
|
||||||
|
{
|
||||||
|
return StringPack(&my_charset_bin, binary_length()).unpack(to, from, from_end,
|
||||||
|
param_data);
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
#endif /* SQL_TYPE_FIXEDBIN_STORAGE */
|
#endif /* SQL_TYPE_FIXEDBIN_STORAGE */
|
||||||
|
Reference in New Issue
Block a user