mirror of
https://github.com/MariaDB/server.git
synced 2025-01-28 17:54:16 +01:00
MDEV-32637 Implement native UUID7 function
This commit is contained in:
parent
ae69ac204a
commit
2fe269fdcb
19 changed files with 549 additions and 4 deletions
42
mysql-test/suite/rpl/r/rpl_row_UUIDv7.result
Normal file
42
mysql-test/suite/rpl/r/rpl_row_UUIDv7.result
Normal file
|
@ -0,0 +1,42 @@
|
|||
include/master-slave.inc
|
||||
[connection master]
|
||||
#
|
||||
# MDEV-32637 Implement native UUID7 function
|
||||
#
|
||||
connection master;
|
||||
CREATE TABLE test.t1 (a INT, blob_column LONGBLOB, vchar_column VARCHAR(100), PRIMARY KEY(a)) engine=myisam;
|
||||
INSERT INTO test.t1 VALUES(1,UUIDv7(),UUIDv7());
|
||||
create procedure test.p1()
|
||||
begin
|
||||
INSERT INTO test.t1 VALUES(2,UUIDv7(),UUIDv7());
|
||||
INSERT INTO test.t1 VALUES(3,UUIDv7(),UUIDv7());
|
||||
end|
|
||||
CALL test.p1();
|
||||
create function test.fn1(x int)
|
||||
returns int
|
||||
begin
|
||||
insert into t1 values (4+x,UUIDv7(),UUIDv7());
|
||||
insert into t1 values (5+x,UUIDv7(),UUIDv7());
|
||||
return 0;
|
||||
end|
|
||||
select fn1(0);
|
||||
fn1(0)
|
||||
0
|
||||
create table t2 (a int) engine=myisam;
|
||||
insert into t2 values(fn1(2));
|
||||
connection slave;
|
||||
SHOW CREATE TABLE test.t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`a` int(11) NOT NULL,
|
||||
`blob_column` longblob DEFAULT NULL,
|
||||
`vchar_column` varchar(100) DEFAULT NULL,
|
||||
PRIMARY KEY (`a`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci
|
||||
connection master;
|
||||
DROP PROCEDURE test.p1;
|
||||
DROP FUNCTION test.fn1;
|
||||
DROP TABLE test.t1;
|
||||
DROP TABLE test.t2;
|
||||
# End of 11.7 tests
|
||||
include/rpl_end.inc
|
71
mysql-test/suite/rpl/t/rpl_row_UUIDv7.test
Normal file
71
mysql-test/suite/rpl/t/rpl_row_UUIDv7.test
Normal file
|
@ -0,0 +1,71 @@
|
|||
--source include/have_binlog_format_row.inc
|
||||
--source include/master-slave.inc
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-32637 Implement native UUID7 function
|
||||
--echo #
|
||||
|
||||
connection master;
|
||||
|
||||
# Start the actual test
|
||||
|
||||
CREATE TABLE test.t1 (a INT, blob_column LONGBLOB, vchar_column VARCHAR(100), PRIMARY KEY(a)) engine=myisam;
|
||||
INSERT INTO test.t1 VALUES(1,UUIDv7(),UUIDv7());
|
||||
delimiter |;
|
||||
create procedure test.p1()
|
||||
begin
|
||||
INSERT INTO test.t1 VALUES(2,UUIDv7(),UUIDv7());
|
||||
INSERT INTO test.t1 VALUES(3,UUIDv7(),UUIDv7());
|
||||
end|
|
||||
delimiter ;|
|
||||
|
||||
CALL test.p1();
|
||||
|
||||
delimiter |;
|
||||
create function test.fn1(x int)
|
||||
returns int
|
||||
begin
|
||||
insert into t1 values (4+x,UUIDv7(),UUIDv7());
|
||||
insert into t1 values (5+x,UUIDv7(),UUIDv7());
|
||||
return 0;
|
||||
end|
|
||||
|
||||
delimiter ;|
|
||||
# test both in SELECT and in INSERT
|
||||
--disable_ps2_protocol
|
||||
select fn1(0);
|
||||
--enable_ps2_protocol
|
||||
create table t2 (a int) engine=myisam;
|
||||
insert into t2 values(fn1(2));
|
||||
|
||||
sync_slave_with_master;
|
||||
SHOW CREATE TABLE test.t1;
|
||||
|
||||
# Dump the databases and so we can see if they match
|
||||
# Another method would be to use SELECT INTO OUTFILE on master,
|
||||
# then LOAD DATA INFILE in slave, and use a query to compare.
|
||||
# This would have the advantage that it would not assume
|
||||
# the system has a 'diff'
|
||||
--exec $MYSQL_DUMP --compact --order-by-primary --skip-extended-insert --no-create-info test > $MYSQLTEST_VARDIR/tmp/rpl_row_UUIDv7_master.sql
|
||||
--exec $MYSQL_DUMP_SLAVE --compact --order-by-primary --skip-extended-insert --no-create-info test > $MYSQLTEST_VARDIR/tmp/rpl_row_UUIDv7_slave.sql
|
||||
|
||||
connection master;
|
||||
|
||||
DROP PROCEDURE test.p1;
|
||||
DROP FUNCTION test.fn1;
|
||||
DROP TABLE test.t1;
|
||||
DROP TABLE test.t2;
|
||||
|
||||
# Let's compare. Note: If they match test will pass, if they do not match
|
||||
# the test will show that the diff statement failed and not reject file
|
||||
# will be created. You will need to go to the mysql-test dir and diff
|
||||
# the files your self to see what is not matching :-)
|
||||
|
||||
diff_files $MYSQLTEST_VARDIR/tmp/rpl_row_UUIDv7_master.sql $MYSQLTEST_VARDIR/tmp/rpl_row_UUIDv7_slave.sql;
|
||||
|
||||
remove_file $MYSQLTEST_VARDIR/tmp/rpl_row_UUIDv7_master.sql;
|
||||
remove_file $MYSQLTEST_VARDIR/tmp/rpl_row_UUIDv7_slave.sql;
|
||||
|
||||
--echo # End of 11.7 tests
|
||||
|
||||
--source include/rpl_end.inc
|
|
@ -469,7 +469,8 @@ PSI_mutex_key key_BITMAP_mutex, key_IO_CACHE_append_buffer_lock,
|
|||
key_THR_LOCK_lock, key_THR_LOCK_malloc,
|
||||
key_THR_LOCK_mutex, key_THR_LOCK_myisam, key_THR_LOCK_net,
|
||||
key_THR_LOCK_open, key_THR_LOCK_threads,
|
||||
key_TMPDIR_mutex, key_THR_LOCK_myisam_mmap, key_LOCK_uuid_generator;
|
||||
key_TMPDIR_mutex, key_THR_LOCK_myisam_mmap, key_LOCK_uuid_generator,
|
||||
key_LOCK_uuid_v7_generator;
|
||||
|
||||
static PSI_mutex_info all_mysys_mutexes[]=
|
||||
{
|
||||
|
@ -496,7 +497,8 @@ static PSI_mutex_info all_mysys_mutexes[]=
|
|||
{ &key_THR_LOCK_threads, "THR_LOCK_threads", PSI_FLAG_GLOBAL},
|
||||
{ &key_TMPDIR_mutex, "TMPDIR_mutex", PSI_FLAG_GLOBAL},
|
||||
{ &key_THR_LOCK_myisam_mmap, "THR_LOCK_myisam_mmap", PSI_FLAG_GLOBAL},
|
||||
{ &key_LOCK_uuid_generator, "LOCK_uuid_generator", PSI_FLAG_GLOBAL }
|
||||
{ &key_LOCK_uuid_generator, "LOCK_uuid_generator", PSI_FLAG_GLOBAL },
|
||||
{ &key_LOCK_uuid_v7_generator, "LOCK_uuid_v7_generator", PSI_FLAG_GLOBAL }
|
||||
};
|
||||
|
||||
PSI_cond_key key_COND_timer, key_IO_CACHE_SHARE_cond,
|
||||
|
|
|
@ -48,7 +48,8 @@ extern PSI_mutex_key key_BITMAP_mutex, key_IO_CACHE_append_buffer_lock,
|
|||
key_THR_LOCK_lock, key_THR_LOCK_malloc,
|
||||
key_THR_LOCK_mutex, key_THR_LOCK_myisam, key_THR_LOCK_net,
|
||||
key_THR_LOCK_open, key_THR_LOCK_threads, key_LOCK_uuid_generator,
|
||||
key_TMPDIR_mutex, key_THR_LOCK_myisam_mmap, key_LOCK_timer;
|
||||
key_LOCK_uuid_v7_generator, key_TMPDIR_mutex, key_THR_LOCK_myisam_mmap,
|
||||
key_LOCK_timer;
|
||||
|
||||
extern PSI_cond_key key_COND_timer, key_IO_CACHE_SHARE_cond,
|
||||
key_IO_CACHE_SHARE_cond_writer, key_my_thread_var_suspend,
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "item.h"
|
||||
#include "sql_type_uuid_v1.h"
|
||||
#include "sql_type_uuid_v4.h"
|
||||
#include "sql_type_uuid_v7.h"
|
||||
|
||||
class Item_func_sys_guid: public Item_str_func
|
||||
{
|
||||
|
@ -102,4 +103,16 @@ public:
|
|||
{ return get_item_copy<Item_func_uuid_v4>(thd, this); }
|
||||
};
|
||||
|
||||
class Item_func_uuid_v7: public Item_func_uuid_vx<UUIDv7>
|
||||
{
|
||||
public:
|
||||
using Item_func_uuid_vx::Item_func_uuid_vx;
|
||||
LEX_CSTRING func_name_cstring() const override
|
||||
{
|
||||
static LEX_CSTRING name= {STRING_WITH_LEN("uuidv7") };
|
||||
return name;
|
||||
}
|
||||
Item *do_get_copy(THD *thd) const override
|
||||
{ return get_item_copy<Item_func_uuid_v7>(thd, this); }
|
||||
};
|
||||
#endif // ITEM_UUIDFUNC_INCLUDED
|
||||
|
|
10
plugin/type_uuid/mysql-test/type_uuid/func_uuid_v7.result
Normal file
10
plugin/type_uuid/mysql-test/type_uuid/func_uuid_v7.result
Normal file
|
@ -0,0 +1,10 @@
|
|||
#
|
||||
# MDEV-33827 UUID() returns a NULL-able result
|
||||
#
|
||||
CREATE TABLE t1 AS SELECT UUIDv7();
|
||||
SHOW CREATE TABLE t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`UUIDv7()` uuid NOT NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci
|
||||
DROP TABLE t1;
|
7
plugin/type_uuid/mysql-test/type_uuid/func_uuid_v7.test
Normal file
7
plugin/type_uuid/mysql-test/type_uuid/func_uuid_v7.test
Normal file
|
@ -0,0 +1,7 @@
|
|||
--echo #
|
||||
--echo # MDEV-33827 UUID() returns a NULL-able result
|
||||
--echo #
|
||||
|
||||
CREATE TABLE t1 AS SELECT UUIDv7();
|
||||
SHOW CREATE TABLE t1;
|
||||
DROP TABLE t1;
|
|
@ -0,0 +1,44 @@
|
|||
SET debug_dbug="+d,simulate_uuidv7_my_random_bytes_failure";
|
||||
#
|
||||
# Start of 11.7 tests
|
||||
#
|
||||
#
|
||||
# MDEV-32637 Implement native UUID7 function
|
||||
#
|
||||
CREATE TABLE t1 (
|
||||
a int primary key not null,
|
||||
u UUID DEFAULT UUIDv7(),
|
||||
unique key(u)
|
||||
);
|
||||
INSERT INTO t1(a) SELECT seq FROM seq_1_to_16;
|
||||
Warnings:
|
||||
Note 1105 UUIDv7 generation failed; using a my_rnd fallback
|
||||
Note 1105 UUIDv7 generation failed; using a my_rnd fallback
|
||||
Note 1105 UUIDv7 generation failed; using a my_rnd fallback
|
||||
Note 1105 UUIDv7 generation failed; using a my_rnd fallback
|
||||
Note 1105 UUIDv7 generation failed; using a my_rnd fallback
|
||||
Note 1105 UUIDv7 generation failed; using a my_rnd fallback
|
||||
Note 1105 UUIDv7 generation failed; using a my_rnd fallback
|
||||
Note 1105 UUIDv7 generation failed; using a my_rnd fallback
|
||||
Note 1105 UUIDv7 generation failed; using a my_rnd fallback
|
||||
Note 1105 UUIDv7 generation failed; using a my_rnd fallback
|
||||
Note 1105 UUIDv7 generation failed; using a my_rnd fallback
|
||||
Note 1105 UUIDv7 generation failed; using a my_rnd fallback
|
||||
Note 1105 UUIDv7 generation failed; using a my_rnd fallback
|
||||
Note 1105 UUIDv7 generation failed; using a my_rnd fallback
|
||||
Note 1105 UUIDv7 generation failed; using a my_rnd fallback
|
||||
Note 1105 UUIDv7 generation failed; using a my_rnd fallback
|
||||
SELECT COUNT(DISTINCT u) AS distinct_uuid_count FROM t1;
|
||||
distinct_uuid_count
|
||||
16
|
||||
SELECT
|
||||
u REGEXP '[a-f0-9]{8}-[a-f0-9]{4}-7[a-f0-9]{3}-[89aAbB][a-f0-9]{3}-[a-f0-9]{12}' AS is_correct_version_and_revision,
|
||||
COUNT(*)
|
||||
FROM t1 GROUP BY is_correct_version_and_revision;
|
||||
is_correct_version_and_revision COUNT(*)
|
||||
1 16
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# End of 11.7 tests
|
||||
#
|
||||
SET debug_dbug="";
|
32
plugin/type_uuid/mysql-test/type_uuid/func_uuidv7_debug.test
Normal file
32
plugin/type_uuid/mysql-test/type_uuid/func_uuidv7_debug.test
Normal file
|
@ -0,0 +1,32 @@
|
|||
--source include/have_debug.inc
|
||||
|
||||
SET debug_dbug="+d,simulate_uuidv7_my_random_bytes_failure";
|
||||
|
||||
source include/have_sequence.inc;
|
||||
|
||||
--echo #
|
||||
--echo # Start of 11.7 tests
|
||||
--echo #
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-32637 Implement native UUID7 function
|
||||
--echo #
|
||||
|
||||
CREATE TABLE t1 (
|
||||
a int primary key not null,
|
||||
u UUID DEFAULT UUIDv7(),
|
||||
unique key(u)
|
||||
);
|
||||
INSERT INTO t1(a) SELECT seq FROM seq_1_to_16;
|
||||
SELECT COUNT(DISTINCT u) AS distinct_uuid_count FROM t1;
|
||||
SELECT
|
||||
u REGEXP '[a-f0-9]{8}-[a-f0-9]{4}-7[a-f0-9]{3}-[89aAbB][a-f0-9]{3}-[a-f0-9]{12}' AS is_correct_version_and_revision,
|
||||
COUNT(*)
|
||||
FROM t1 GROUP BY is_correct_version_and_revision;
|
||||
DROP TABLE t1;
|
||||
|
||||
--echo #
|
||||
--echo # End of 11.7 tests
|
||||
--echo #
|
||||
|
||||
SET debug_dbug="";
|
|
@ -0,0 +1,35 @@
|
|||
#
|
||||
# Start of 11.7 tests
|
||||
#
|
||||
#
|
||||
# MDEV-32637 Implement native UUID7 function
|
||||
#
|
||||
SELECT
|
||||
'----' AS `----`,
|
||||
PLUGIN_NAME,
|
||||
PLUGIN_VERSION,
|
||||
PLUGIN_STATUS,
|
||||
PLUGIN_TYPE,
|
||||
PLUGIN_AUTHOR,
|
||||
PLUGIN_DESCRIPTION,
|
||||
PLUGIN_LICENSE,
|
||||
PLUGIN_MATURITY,
|
||||
PLUGIN_AUTH_VERSION
|
||||
FROM INFORMATION_SCHEMA.PLUGINS
|
||||
WHERE PLUGIN_TYPE='FUNCTION'
|
||||
AND PLUGIN_NAME IN
|
||||
('uuidv7')
|
||||
ORDER BY PLUGIN_NAME;
|
||||
---- ----
|
||||
PLUGIN_NAME uuidv7
|
||||
PLUGIN_VERSION 1.0
|
||||
PLUGIN_STATUS ACTIVE
|
||||
PLUGIN_TYPE FUNCTION
|
||||
PLUGIN_AUTHOR Stefano Petrilli
|
||||
PLUGIN_DESCRIPTION Function UUIDv7()
|
||||
PLUGIN_LICENSE GPL
|
||||
PLUGIN_MATURITY Experimental
|
||||
PLUGIN_AUTH_VERSION 1.0
|
||||
#
|
||||
# End of 11.7 tests
|
||||
#
|
|
@ -0,0 +1,30 @@
|
|||
--echo #
|
||||
--echo # Start of 11.7 tests
|
||||
--echo #
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-32637 Implement native UUID7 function
|
||||
--echo #
|
||||
|
||||
--vertical_results
|
||||
SELECT
|
||||
'----' AS `----`,
|
||||
PLUGIN_NAME,
|
||||
PLUGIN_VERSION,
|
||||
PLUGIN_STATUS,
|
||||
PLUGIN_TYPE,
|
||||
PLUGIN_AUTHOR,
|
||||
PLUGIN_DESCRIPTION,
|
||||
PLUGIN_LICENSE,
|
||||
PLUGIN_MATURITY,
|
||||
PLUGIN_AUTH_VERSION
|
||||
FROM INFORMATION_SCHEMA.PLUGINS
|
||||
WHERE PLUGIN_TYPE='FUNCTION'
|
||||
AND PLUGIN_NAME IN
|
||||
('uuidv7')
|
||||
ORDER BY PLUGIN_NAME;
|
||||
--horizontal_results
|
||||
|
||||
--echo #
|
||||
--echo # End of 11.7 tests
|
||||
--echo #
|
|
@ -0,0 +1,15 @@
|
|||
#
|
||||
# Start of 11.7 tests
|
||||
#
|
||||
#
|
||||
# MDEV-32637 Implement native UUID7 function
|
||||
#
|
||||
CREATE TABLE t1 (a int primary key not null, u UUID DEFAULT UUIDv7(), unique key(u));
|
||||
insert into t1(a) select seq from seq_1_to_100;
|
||||
select count(distinct u) AS distinct_uuid_count from t1;
|
||||
distinct_uuid_count
|
||||
100
|
||||
drop table t1;
|
||||
#
|
||||
# End of 11.7 tests
|
||||
#
|
|
@ -0,0 +1,18 @@
|
|||
source include/have_sequence.inc;
|
||||
|
||||
--echo #
|
||||
--echo # Start of 11.7 tests
|
||||
--echo #
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-32637 Implement native UUID7 function
|
||||
--echo #
|
||||
|
||||
CREATE TABLE t1 (a int primary key not null, u UUID DEFAULT UUIDv7(), unique key(u));
|
||||
insert into t1(a) select seq from seq_1_to_100;
|
||||
select count(distinct u) AS distinct_uuid_count from t1;
|
||||
drop table t1;
|
||||
|
||||
--echo #
|
||||
--echo # End of 11.7 tests
|
||||
--echo #
|
|
@ -0,0 +1,12 @@
|
|||
#
|
||||
# Start of 11.7 tests
|
||||
#
|
||||
#
|
||||
# MDEV-32637 Implement native UUID7 function
|
||||
#
|
||||
SELECT UUIDv7() REGEXP '[a-f0-9]{8}-[a-f0-9]{4}-7[a-f0-9]{3}-[89aAbB][a-f0-9]{3}-[a-f0-9]{12}' AS is_correct_version_and_revision;
|
||||
is_correct_version_and_revision
|
||||
1
|
||||
#
|
||||
# End of 11.7 tests
|
||||
#
|
|
@ -0,0 +1,13 @@
|
|||
--echo #
|
||||
--echo # Start of 11.7 tests
|
||||
--echo #
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-32637 Implement native UUID7 function
|
||||
--echo #
|
||||
|
||||
SELECT UUIDv7() REGEXP '[a-f0-9]{8}-[a-f0-9]{4}-7[a-f0-9]{3}-[89aAbB][a-f0-9]{3}-[a-f0-9]{12}' AS is_correct_version_and_revision;
|
||||
|
||||
--echo #
|
||||
--echo # End of 11.7 tests
|
||||
--echo #
|
|
@ -831,3 +831,21 @@ a b a b
|
|||
13101234-5566-7777-e888-99aabbccddee 31 12701234-5566-6777-e888-99aabbccddee 27
|
||||
13101234-5566-7777-e888-99aabbccddee 31 12901234-5566-7777-8888-99aabbccddee 29
|
||||
drop table t1;
|
||||
#
|
||||
# MDEV-32637 Implement native UUID7 function
|
||||
#
|
||||
CREATE TABLE t1 (a int primary key not null, u UUID DEFAULT UUIDv7(), unique key(u));
|
||||
insert into t1(a) select seq from seq_1_to_10;
|
||||
select a from t1 order by u asc;
|
||||
a
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8
|
||||
9
|
||||
10
|
||||
drop table t1;
|
||||
|
|
|
@ -60,3 +60,14 @@ drop table t2;
|
|||
select * from t1, t1 t where t1.b div 4 in (6,7) and t.b div 4 in (6,7) and concat(t1.a) > concat(t.a);
|
||||
|
||||
drop table t1;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-32637 Implement native UUID7 function
|
||||
--echo #
|
||||
|
||||
# Verify that UUIDv7 are time-ordered and unique
|
||||
|
||||
CREATE TABLE t1 (a int primary key not null, u UUID DEFAULT UUIDv7(), unique key(u));
|
||||
insert into t1(a) select seq from seq_1_to_10;
|
||||
select a from t1 order by u asc;
|
||||
drop table t1;
|
||||
|
|
|
@ -160,14 +160,36 @@ protected:
|
|||
virtual ~Create_func_uuid_v4() {}
|
||||
};
|
||||
|
||||
uint64 last_uuidv7_timestamp= 0;
|
||||
mysql_mutex_t LOCK_uuid_v7_generator;
|
||||
|
||||
class Create_func_uuid_v7 : public Create_func_arg0
|
||||
{
|
||||
public:
|
||||
Item *create_builder(THD *thd) override
|
||||
{
|
||||
DBUG_ENTER("Create_func_uuid_v7::create");
|
||||
thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_FUNCTION);
|
||||
thd->lex->uncacheable(UNCACHEABLE_RAND);
|
||||
DBUG_RETURN(new (thd->mem_root) Item_func_uuid_v7(thd));
|
||||
}
|
||||
static Create_func_uuid_v7 s_singleton;
|
||||
|
||||
protected:
|
||||
Create_func_uuid_v7() {}
|
||||
virtual ~Create_func_uuid_v7() {}
|
||||
};
|
||||
|
||||
Create_func_uuid Create_func_uuid::s_singleton;
|
||||
Create_func_sys_guid Create_func_sys_guid::s_singleton;
|
||||
Create_func_uuid_v4 Create_func_uuid_v4::s_singleton;
|
||||
Create_func_uuid_v7 Create_func_uuid_v7::s_singleton;
|
||||
|
||||
static Plugin_function
|
||||
plugin_descriptor_function_uuid(&Create_func_uuid::s_singleton),
|
||||
plugin_descriptor_function_sys_guid(&Create_func_sys_guid::s_singleton),
|
||||
plugin_descriptor_function_uuid_v4(&Create_func_uuid_v4::s_singleton);
|
||||
plugin_descriptor_function_uuid_v4(&Create_func_uuid_v4::s_singleton),
|
||||
plugin_descriptor_function_uuid_v7(&Create_func_uuid_v7::s_singleton);
|
||||
|
||||
static constexpr Name type_name={STRING_WITH_LEN("uuid")};
|
||||
|
||||
|
@ -178,6 +200,18 @@ int uuid_init(void*)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int uuidv7_init(void*)
|
||||
{
|
||||
mysql_mutex_init(0, &LOCK_uuid_v7_generator, MY_MUTEX_INIT_FAST);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uuidv7_terminate(void*)
|
||||
{
|
||||
mysql_mutex_destroy(&LOCK_uuid_v7_generator);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
maria_declare_plugin(type_uuid)
|
||||
|
@ -240,5 +274,20 @@ maria_declare_plugin(type_uuid)
|
|||
NULL, // System variables
|
||||
"1.0", // String version representation
|
||||
MariaDB_PLUGIN_MATURITY_EXPERIMENTAL// Maturity(see include/mysql/plugin.h)*/
|
||||
},
|
||||
{
|
||||
MariaDB_FUNCTION_PLUGIN, // the plugin type (see include/mysql/plugin.h)
|
||||
&plugin_descriptor_function_uuid_v7, // pointer to type-specific plugin descriptor
|
||||
"uuidv7", // plugin name
|
||||
"Stefano Petrilli", // plugin author
|
||||
"Function UUIDv7()", // the plugin description
|
||||
PLUGIN_LICENSE_GPL, // the plugin license (see include/mysql/plugin.h)
|
||||
uuidv7_init, // Pointer to plugin initialization function
|
||||
uuidv7_terminate, // Pointer to plugin deinitialization function
|
||||
0x0100, // Numeric version 0xAABB means AA.BB version
|
||||
NULL, // Status variables
|
||||
NULL, // System variables
|
||||
"1.0", // String version representation
|
||||
MariaDB_PLUGIN_MATURITY_EXPERIMENTAL// Maturity(see include/mysql/plugin.h)*/
|
||||
}
|
||||
maria_declare_plugin_end;
|
||||
|
|
122
plugin/type_uuid/sql_type_uuid_v7.h
Normal file
122
plugin/type_uuid/sql_type_uuid_v7.h
Normal file
|
@ -0,0 +1,122 @@
|
|||
#ifndef SQL_TYPE_UUID_V7_INCLUDED
|
||||
#define SQL_TYPE_UUID_V7_INCLUDED
|
||||
|
||||
/* Copyright (c) 2024, Stefano Petrilli
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */
|
||||
|
||||
/*
|
||||
implements Universal Universally Unique Identifier version 7, as described in
|
||||
RFC 9562.
|
||||
|
||||
A UUIDv7 has the following structure:
|
||||
|
||||
Field Octet # Note
|
||||
unix_ts_ms 0-5 Big-endian unsigned number of
|
||||
Unix epoch timestamp in
|
||||
milliseconds.
|
||||
ver 6 The 4 bit version field, set to
|
||||
0b0100. Occupies bits 48 through 51 of
|
||||
octet 6.
|
||||
sub_ms_precision 6-7 Sub millisecond clock precision
|
||||
encoded to fill all the possible
|
||||
values in 12 bits.
|
||||
var 8 The 2 bit variant field, set to 0b10.
|
||||
Occupies bits 64 and 65 of octet 8.
|
||||
rand 8-15 CSPRNG 62 bits multiplexed
|
||||
with the version number.
|
||||
|
||||
The structure of an UUIDv7 is: mmmmmmmm-mmmm-Vsss-vrrr-rrrrrrrrrrrr
|
||||
*/
|
||||
|
||||
#include "sql_type_uuid.h"
|
||||
#include <my_rnd.h>
|
||||
#include <m_string.h>
|
||||
#include <myisampack.h> /* mi_int2store, mi_int6store */
|
||||
#include <errmsg.h>
|
||||
|
||||
extern uint64 last_uuidv7_timestamp;
|
||||
extern mysql_mutex_t LOCK_uuid_v7_generator;
|
||||
|
||||
class UUIDv7: public Type_handler_uuid_new::Fbt
|
||||
{
|
||||
static constexpr uchar UUID_VERSION() { return 0x70; }
|
||||
static constexpr uchar UUID_VERSION_MASK() { return 0x0F; }
|
||||
static constexpr uchar UUID_VARIANT() { return 0x80; }
|
||||
static constexpr uchar UUID_VARIANT_MASK() { return 0x3F; }
|
||||
static constexpr double MICROSECONDS_TO_12BIT_MAPPING_FACTOR() { return 4.096; }
|
||||
|
||||
static void inject_version_and_variant(uchar *to)
|
||||
{
|
||||
to[6]= ((to[6] & UUID_VERSION_MASK()) | UUID_VERSION());
|
||||
to[8]= ((to[8] & UUID_VARIANT_MASK()) | UUID_VARIANT());
|
||||
}
|
||||
|
||||
// Construct using a my_rnd()-based fallback method
|
||||
static void construct_fallback(char *to)
|
||||
{
|
||||
for (uint i= 0; i < 4; i++)
|
||||
int4store(&to[i * 4], (uint32) (my_rnd(&sql_rand)*0xFFFFFFFF));
|
||||
}
|
||||
|
||||
static void construct(char *to)
|
||||
{
|
||||
bool error= my_random_bytes((uchar*) to+8, 8) != MY_AES_OK;
|
||||
DBUG_EXECUTE_IF("simulate_uuidv7_my_random_bytes_failure", error= true; );
|
||||
|
||||
if (error) // A very unlikely failure happened.
|
||||
{
|
||||
push_warning_printf(current_thd, Sql_condition::WARN_LEVEL_NOTE,
|
||||
ER_UNKNOWN_ERROR,
|
||||
"UUIDv7 generation failed; using a my_rnd fallback");
|
||||
construct_fallback(to);
|
||||
}
|
||||
|
||||
uint64 tv= my_hrtime().val;
|
||||
mysql_mutex_lock(&LOCK_uuid_v7_generator);
|
||||
last_uuidv7_timestamp= tv= MY_MAX(last_uuidv7_timestamp+1, tv);
|
||||
mysql_mutex_unlock(&LOCK_uuid_v7_generator);
|
||||
|
||||
mi_int6store(to, tv / 1000);
|
||||
|
||||
/**
|
||||
Map all the possible microseconds values (from 0 to 999) to all the
|
||||
values that can be represented in 12 bits (from 0 to 4095) as
|
||||
described in section 6.2, Method 3 of RFC 9562.
|
||||
*/
|
||||
mi_int2store(to+6, MICROSECONDS_TO_12BIT_MAPPING_FACTOR() * (tv % 1000));
|
||||
|
||||
/*
|
||||
Let's inject proper version and variant to make it good UUIDv7.
|
||||
*/
|
||||
inject_version_and_variant((uchar*) to);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
UUIDv7()
|
||||
{
|
||||
construct(m_buffer);
|
||||
}
|
||||
static bool construct_native(Native *to)
|
||||
{
|
||||
to->alloc(MY_UUID_SIZE);
|
||||
to->length(MY_UUID_SIZE);
|
||||
construct((char*)to->ptr());
|
||||
return 0;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif // SQL_TYPE_UUID_V7_INCLUDED
|
Loading…
Add table
Reference in a new issue