From 1fbe1bc6cd152e86f53c7306c01e12a295c9476c Mon Sep 17 00:00:00 2001 From: AbhinavMishra32 Date: Sat, 27 Dec 2025 00:49:37 +0530 Subject: [PATCH] Added XXH3 and XXH32 (64 bit) sql functions --- mysql-test/main/func_xxh.result | 31 ++++++++++++++ mysql-test/main/func_xxh.test | 13 ++++++ sql/item_create.cc | 72 +++++++++++++++++++++++++++++++++ sql/item_strfunc.cc | 39 ++++++++++++++++++ sql/item_strfunc.h | 40 ++++++++++++++++++ 5 files changed, 195 insertions(+) create mode 100644 mysql-test/main/func_xxh.result create mode 100644 mysql-test/main/func_xxh.test diff --git a/mysql-test/main/func_xxh.result b/mysql-test/main/func_xxh.result new file mode 100644 index 0000000000000..609df35b33edb --- /dev/null +++ b/mysql-test/main/func_xxh.result @@ -0,0 +1,31 @@ +# Testing XXH SQL functions +SELECT XXH32('abc') = 852579327 AS xxh32_expected; +xxh32_expected +1 +SELECT XXH32(11223344) = 408040606 AS xxh32_expected; +xxh32_expected +1 +SELECT XXH32('abc') = XXH32('abc') AS xxh32_eq; +xxh32_eq +1 +SELECT XXH32(NULL) IS NULL AS xxh32_null; +xxh32_null +1 +SELECT XXH32('') IS NULL AS xxh32_null; +xxh32_null +1 +SELECT XXH3('abc') = 8696274497037089104 AS xxh3_expected; +xxh3_expected +1 +SELECT XXH3(11223344) = 9329478082249925753 AS xxh3_expected; +xxh3_expected +1 +SELECT XXH3('abc') = XXH32('abc') AS xxh3_eq; +xxh3_eq +0 +SELECT XXH3(NULL) IS NULL AS xxh3_null; +xxh3_null +1 +SELECT XXH3('') IS NULL AS xxh3_null; +xxh3_null +1 diff --git a/mysql-test/main/func_xxh.test b/mysql-test/main/func_xxh.test new file mode 100644 index 0000000000000..b84426c27db09 --- /dev/null +++ b/mysql-test/main/func_xxh.test @@ -0,0 +1,13 @@ +--echo # Testing XXH SQL functions + +SELECT XXH32('abc') = 852579327 AS xxh32_expected; +SELECT XXH32(11223344) = 408040606 AS xxh32_expected; +SELECT XXH32('abc') = XXH32('abc') AS xxh32_eq; +SELECT XXH32(NULL) IS NULL AS xxh32_null; +SELECT XXH32('') IS NULL AS xxh32_null; + +SELECT XXH3('abc') = 8696274497037089104 AS xxh3_expected; +SELECT XXH3(11223344) = 9329478082249925753 AS xxh3_expected; +SELECT XXH3('abc') = XXH32('abc') AS xxh3_eq; +SELECT XXH3(NULL) IS NULL AS xxh3_null; +SELECT XXH3('') IS NULL AS xxh3_null; \ No newline at end of file diff --git a/sql/item_create.cc b/sql/item_create.cc index 7e4d21584e0a1..6a5550b0e9529 100644 --- a/sql/item_create.cc +++ b/sql/item_create.cc @@ -634,6 +634,32 @@ class Create_func_crc32c : public Create_native_func }; +class Create_func_xxh32 : public Create_native_func +{ +public: + Item *create_native(THD *thd, const LEX_CSTRING *name, List *item_list) + override; + + static Create_func_xxh32 s_singleton; + +protected: + Create_func_xxh32() = default; + ~Create_func_xxh32() override = default; +}; + +class Create_func_xxh3 : public Create_native_func +{ +public: + Item *create_native(THD *thd, const LEX_CSTRING *name, List *item_list) + override; + + static Create_func_xxh3 s_singleton; + +protected: + Create_func_xxh3() = default; + ~Create_func_xxh3() override = default; +}; + class Create_func_datediff : public Create_func_arg2 { public: @@ -3719,6 +3745,50 @@ Create_func_crc32c::create_native(THD *thd, const LEX_CSTRING *name, } +Create_func_xxh32 Create_func_xxh32::s_singleton; + +Item* +Create_func_xxh32::create_native(THD *thd, const LEX_CSTRING *name, + List *item_list) +{ + int argc= item_list ? item_list->elements : 0; + + if (unlikely(argc != 1)) + { + my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name->str); + return nullptr; + } + + Item *arg1= item_list->pop(); + + /* This was checked in Create_native_func::create_func() */ + DBUG_ASSERT(!arg1->is_explicit_name()); + + return new (thd->mem_root) Item_func_xxh32(thd, arg1); +} + +Create_func_xxh3 Create_func_xxh3::s_singleton; + +Item* +Create_func_xxh3::create_native(THD *thd, const LEX_CSTRING *name, + List *item_list) +{ + int argc= item_list ? item_list->elements : 0; + + if (unlikely(argc != 1)) + { + my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name->str); + return nullptr; + } + + Item *arg1= item_list->pop(); + + /* This was checked in Create_native_func::create_func() */ + DBUG_ASSERT(!arg1->is_explicit_name()); + + return new (thd->mem_root) Item_func_xxh3_64(thd, arg1); +} + Create_func_datediff Create_func_datediff::s_singleton; Item* @@ -6448,6 +6518,8 @@ const Native_func_registry func_array[] = { { STRING_WITH_LEN("COT") }, BUILDER(Create_func_cot)}, { { STRING_WITH_LEN("CRC32") }, BUILDER(Create_func_crc32)}, { { STRING_WITH_LEN("CRC32C") }, BUILDER(Create_func_crc32c)}, + { { STRING_WITH_LEN("XXH32") }, BUILDER(Create_func_xxh32)}, + { { STRING_WITH_LEN("XXH3") }, BUILDER(Create_func_xxh3)}, { { STRING_WITH_LEN("DATABASE") }, BUILDER(Create_func_database)}, { { STRING_WITH_LEN("DATEDIFF") }, BUILDER(Create_func_datediff)}, { { STRING_WITH_LEN("DATE_FORMAT") }, BUILDER(Create_func_date_format)}, diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 9925842f52fb4..50fa915c71846 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -44,6 +44,7 @@ // my_make_scrambled_password_323 #include #include +#include "../mysys/xxhash.h" C_MODE_START #include "../mysys/my_static.h" // For soundex_map C_MODE_END @@ -4770,6 +4771,44 @@ longlong Item_func_crc32::val_int() (ulonglong{crc_func(uint32_t(crc), res->ptr(), res->length())}); } +longlong Item_func_xxh32::val_int() +{ + DBUG_ASSERT(fixed()); + DBUG_ASSERT(arg_count == 1); + String *res; + + null_value= 0; + res= args[0]->val_str(&value); + + if (!res || res->length() == 0) + { + null_value=1; + return 0; + } + + uint32_t h= XXH32((const void*) res->ptr(), res->length(), 0); + return static_cast((ulonglong) h); +} + +longlong Item_func_xxh3_64::val_int() +{ + DBUG_ASSERT(fixed()); + DBUG_ASSERT(arg_count == 1); + String *res; + + null_value= 0; + res= args[0]->val_str(&value); + + if (!res || res->length() == 0) + { + null_value=1; + return 0; + } + + uint64_t h= XXH3_64bits((const void*) res->ptr(), res->length()); + return static_cast((ulonglong) h); +} + #ifdef HAVE_COMPRESS #include "zlib.h" diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index 51816e3eb5255..045c5d9828455 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -2200,6 +2200,46 @@ class Item_func_crc32 :public Item_long_func { return get_item_copy(thd, this); } }; +class Item_func_xxh32 : public Item_long_func +{ + bool check_arguments() const override + { + return args[0]->check_type_can_return_str(func_name_cstring()); + } + String value; +public: + Item_func_xxh32(THD *thd, Item *a) : Item_long_func(thd, a) { unsigned_flag=1; } + LEX_CSTRING func_name_cstring() const override + { + static LEX_CSTRING name= {STRING_WITH_LEN("XXH32") }; + return name; + } + bool fix_length_and_dec(THD *thd) override { max_length=10; set_maybe_null(); return FALSE; } + longlong val_int() override; + Item *do_get_copy(THD *thd) const override + { return get_item_copy(thd, this); } +}; + +class Item_func_xxh3_64 : public Item_longlong_func +{ + bool check_arguments() const override + { + return args[0]->check_type_can_return_str(func_name_cstring()); + } + String value; +public: + Item_func_xxh3_64(THD *thd, Item *a) : Item_longlong_func(thd, a) { unsigned_flag=1; } + LEX_CSTRING func_name_cstring() const override + { + static LEX_CSTRING name= {STRING_WITH_LEN("XXH3") }; + return name; + } + bool fix_length_and_dec(THD *thd) override { max_length=20; set_maybe_null(); return FALSE; } + longlong val_int() override; + Item *do_get_copy(THD *thd) const override + { return get_item_copy(thd, this); } +}; + class Item_func_uncompressed_length : public Item_long_func_length { String value;