diff --git a/mysql-test/main/func_misc.result b/mysql-test/main/func_misc.result index 91cc4bc206a..37102e7dd88 100644 --- a/mysql-test/main/func_misc.result +++ b/mysql-test/main/func_misc.result @@ -118,8 +118,8 @@ create table t1 as select uuid(), length(uuid()); show create table t1; Table Create Table t1 CREATE TABLE `t1` ( - `uuid()` uuid DEFAULT NULL, - `length(uuid())` int(10) DEFAULT NULL + `uuid()` uuid NOT NULL, + `length(uuid())` int(10) NOT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci select length(`uuid()`) from t1; length(`uuid()`) diff --git a/mysql-test/suite/vcol/r/binlog.result b/mysql-test/suite/vcol/r/binlog.result index 1f66a632697..5671c49a35f 100644 --- a/mysql-test/suite/vcol/r/binlog.result +++ b/mysql-test/suite/vcol/r/binlog.result @@ -88,7 +88,7 @@ CREATE TEMPORARY TABLE t1 SELECT UUID(); show create table t1; Table Create Table t1 CREATE TEMPORARY TABLE `t1` ( - `UUID()` uuid DEFAULT NULL + `UUID()` uuid NOT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci CREATE TABLE t2 (a INT PRIMARY KEY, b TEXT, c INT GENERATED ALWAYS AS(b)); INSERT INTO t2 (a,b) VALUES (1,1); diff --git a/plugin/type_uuid/item_uuidfunc.cc b/plugin/type_uuid/item_uuidfunc.cc index 3f2b7434f73..2189e36d57f 100644 --- a/plugin/type_uuid/item_uuidfunc.cc +++ b/plugin/type_uuid/item_uuidfunc.cc @@ -16,7 +16,6 @@ #define MYSQL_SERVER #include "mariadb.h" #include "item_uuidfunc.h" -#include "sql_type_uuid.h" String *Item_func_sys_guid::val_str(String *str) { @@ -27,20 +26,6 @@ String *Item_func_sys_guid::val_str(String *str) uchar buf[MY_UUID_SIZE]; my_uuid(buf); - my_uuid2str(buf, const_cast(str->ptr()), with_dashes); + my_uuid2str(buf, const_cast(str->ptr()), 0); return str; } - -const Type_handler *Item_func_uuid::type_handler() const -{ - return Type_handler_uuid_new::singleton(); -} - -bool Item_func_uuid::val_native(THD *, Native *to) -{ - DBUG_ASSERT(fixed()); - to->alloc(MY_UUID_SIZE); - to->length(MY_UUID_SIZE); - my_uuid((uchar*)to->ptr()); - return 0; -} diff --git a/plugin/type_uuid/item_uuidfunc.h b/plugin/type_uuid/item_uuidfunc.h index aa6ff999b99..1ac93177a0b 100644 --- a/plugin/type_uuid/item_uuidfunc.h +++ b/plugin/type_uuid/item_uuidfunc.h @@ -18,15 +18,15 @@ #include "item.h" +#include "sql_type_uuid.h" class Item_func_sys_guid: public Item_str_func { protected: - bool with_dashes; - size_t uuid_len() const - { return MY_UUID_BARE_STRING_LENGTH + with_dashes*MY_UUID_SEPARATORS; } + static size_t uuid_len() + { return MY_UUID_BARE_STRING_LENGTH; } public: - Item_func_sys_guid(THD *thd): Item_str_func(thd), with_dashes(false) {} + Item_func_sys_guid(THD *thd): Item_str_func(thd) {} bool fix_length_and_dec(THD *thd) override { collation.set(DTCollation_numeric()); @@ -49,17 +49,31 @@ public: { return get_item_copy(thd, this); } }; -class Item_func_uuid: public Item_func_sys_guid +class Item_func_uuid: public Type_handler_uuid_new::Item_fbt_func { public: - Item_func_uuid(THD *thd): Item_func_sys_guid(thd) { with_dashes= true; } - const Type_handler *type_handler() const override; + Item_func_uuid(THD *thd): Item_fbt_func(thd) { } + bool const_item() const override { return false; } + table_map used_tables() const override { return RAND_TABLE_BIT; } + bool check_vcol_func_processor(void *arg) override + { + return mark_unsupported_function(func_name(), "()", arg, VCOL_NON_DETERMINISTIC); + } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("uuid") }; return name; } - bool val_native(THD *thd, Native *to) override; + String *val_str(String *str) override + { + DBUG_ASSERT(fixed()); + return UUIDv1().to_string(str) ? NULL : str; + } + bool val_native(THD *thd, Native *to) override + { + DBUG_ASSERT(fixed()); + return UUIDv1::construct_native(to); + } Item *get_copy(THD *thd) override { return get_item_copy(thd, this); } }; diff --git a/plugin/type_uuid/mysql-test/type_uuid/func_uuid.result b/plugin/type_uuid/mysql-test/type_uuid/func_uuid.result new file mode 100644 index 00000000000..466eec508c3 --- /dev/null +++ b/plugin/type_uuid/mysql-test/type_uuid/func_uuid.result @@ -0,0 +1,10 @@ +# +# MDEV-33827 UUID() returns a NULL-able result +# +CREATE TABLE t1 AS SELECT UUID(); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `UUID()` uuid NOT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +DROP TABLE t1; diff --git a/plugin/type_uuid/mysql-test/type_uuid/func_uuid.test b/plugin/type_uuid/mysql-test/type_uuid/func_uuid.test new file mode 100644 index 00000000000..2ee634be095 --- /dev/null +++ b/plugin/type_uuid/mysql-test/type_uuid/func_uuid.test @@ -0,0 +1,7 @@ +--echo # +--echo # MDEV-33827 UUID() returns a NULL-able result +--echo # + +CREATE TABLE t1 AS SELECT UUID(); +SHOW CREATE TABLE t1; +DROP TABLE t1; diff --git a/plugin/type_uuid/sql_type_uuid.h b/plugin/type_uuid/sql_type_uuid.h index 3ca310ff0b6..d744e0a1133 100644 --- a/plugin/type_uuid/sql_type_uuid.h +++ b/plugin/type_uuid/sql_type_uuid.h @@ -327,4 +327,22 @@ public: typedef Type_handler_fbt, Type_collection_uuid> Type_handler_uuid_old; typedef Type_handler_fbt, Type_collection_uuid> Type_handler_uuid_new; + +class UUIDv1: public Type_handler_uuid_new::Fbt +{ +public: + UUIDv1() + { + my_uuid((uchar*) m_buffer); + } + static bool construct_native(Native *to) + { + to->alloc(MY_UUID_SIZE); + to->length(MY_UUID_SIZE); + my_uuid((uchar*)to->ptr()); + return 0; + } +}; + + #endif // SQL_TYPE_UUID_INCLUDED diff --git a/sql/sql_type_fixedbin.h b/sql/sql_type_fixedbin.h index 201bd09d965..42c8da5e656 100644 --- a/sql/sql_type_fixedbin.h +++ b/sql/sql_type_fixedbin.h @@ -896,48 +896,15 @@ public: } }; - class Item_typecast_fbt: public Item_func + class Item_fbt_func: public Item_func { public: - Item_typecast_fbt(THD *thd, Item *a) :Item_func(thd, a) {} - + using Item_func::Item_func; const Type_handler *type_handler() const override { return singleton(); } - - enum Functype functype() const override { return CHAR_TYPECAST_FUNC; } - bool eq(const Item *item, bool binary_cmp) const override - { - if (this == item) - return true; - if (item->type() != FUNC_ITEM || - functype() != ((Item_func*)item)->functype()) - return false; - if (type_handler() != item->type_handler()) - return false; - Item_typecast_fbt *cast= (Item_typecast_fbt*) item; - return args[0]->eq(cast->args[0], binary_cmp); - } - LEX_CSTRING func_name_cstring() const override - { - static Name name= singleton()->name(); - size_t len= 9+name.length()+1; - char *buf= (char*)current_thd->alloc(len); - strmov(strmov(buf, "cast_as_"), name.ptr()); - return { buf, len }; - } - void print(String *str, enum_query_type query_type) override - { - str->append(STRING_WITH_LEN("cast(")); - args[0]->print(str, query_type); - str->append(STRING_WITH_LEN(" as ")); - str->append(singleton()->name().lex_cstring()); - str->append(')'); - } bool fix_length_and_dec(THD *thd) override { Type_std_attributes::operator=(Type_std_attributes_fbt()); - if (Fbt::fix_fields_maybe_null_on_conversion_to_fbt(args[0])) - set_maybe_null(); return false; } String *val_str(String *to) override @@ -963,10 +930,55 @@ public: set_zero_time(ltime, MYSQL_TIMESTAMP_TIME); return false; } + }; + + class Item_typecast_fbt: public Item_fbt_func + { + public: + Item_typecast_fbt(THD *thd, Item *a) :Item_fbt_func(thd, a) {} + + Item_func::Functype functype() const override + { return Item_func::CHAR_TYPECAST_FUNC; } + bool eq(const Item *item, bool binary_cmp) const override + { + if (this == item) + return true; + if (item->type() != Item_fbt_func::FUNC_ITEM || + functype() != ((Item_func*)item)->functype()) + return false; + if (Item_fbt_func::type_handler() != item->type_handler()) + return false; + Item_typecast_fbt *cast= (Item_typecast_fbt*) item; + return Item_fbt_func::args[0]->eq(cast->args[0], binary_cmp); + } + LEX_CSTRING func_name_cstring() const override + { + static Name name= singleton()->name(); + size_t len= 9+name.length()+1; + char *buf= (char*)current_thd->alloc(len); + strmov(strmov(buf, "cast_as_"), name.ptr()); + return { buf, len }; + } + void print(String *str, enum_query_type query_type) override + { + str->append(STRING_WITH_LEN("cast(")); + Item_fbt_func::args[0]->print(str, query_type); + str->append(STRING_WITH_LEN(" as ")); + str->append(singleton()->name().lex_cstring()); + str->append(')'); + } + bool fix_length_and_dec(THD *thd) override + { + Item_fbt_func::fix_length_and_dec(thd); + if (Fbt::fix_fields_maybe_null_on_conversion_to_fbt( + Item_fbt_func::args[0])) + Item_fbt_func::set_maybe_null(); + return false; + } bool val_native(THD *thd, Native *to) override { - Fbt_null tmp(args[0]); - return null_value= tmp.is_null() || tmp.to_native(to); + Fbt_null tmp(Item_fbt_func::args[0]); + return Item_fbt_func::null_value= tmp.is_null() || tmp.to_native(to); } Item *get_copy(THD *thd) override { return get_item_copy(thd, this); }