diff options
author | Marko Mäkelä <marko.makela@mariadb.com> | 2021-12-10 13:14:31 +0200 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2021-12-10 13:14:31 +0200 |
commit | 8a847f1bc97f94fda47856bbb0464b68949add86 (patch) | |
tree | 2fcc3d2f30fdd61f063b4414464f44412a1df634 | |
parent | ccdf5711a8fff0cd610a91fdcf37c8ff1182878c (diff) | |
download | mariadb-git-bb-10.8-MDEV-27208.tar.gz |
MDEV-27208: Implement the CRC32C() functionbb-10.8-MDEV-27208
The SQL parser defines the function crc32() that computes the CRC-32
of a string using the ISO 3309 polynomial that is being used by zlib
and many others.
InnoDB and MyRocks use a different polynomial, which was implemented
in SSE4.2 instructions that were introduced in the
Intel Nehalem microarchitecture. This is commonly called CRC-32C.
Defining a SQL built-in function CRC32C() would for example allow
the definition of a simple SQL function that would generate a logically
empty InnoDB redo log corresponding to a particular checkpoint LSN.
-rw-r--r-- | mysql-test/main/func_math.result | 29 | ||||
-rw-r--r-- | mysql-test/main/func_math.test | 7 | ||||
-rw-r--r-- | sql/item_create.cc | 24 | ||||
-rw-r--r-- | sql/item_strfunc.cc | 13 | ||||
-rw-r--r-- | sql/item_strfunc.h | 19 |
5 files changed, 76 insertions, 16 deletions
diff --git a/mysql-test/main/func_math.result b/mysql-test/main/func_math.result index ec2521bcfd7..7e3e7afdf44 100644 --- a/mysql-test/main/func_math.result +++ b/mysql-test/main/func_math.result @@ -1840,24 +1840,27 @@ CRC32(99999999999999999999999999999999) SELECT CRC32(-99999999999999999999999999999999); CRC32(-99999999999999999999999999999999) 1052326872 +SELECT CRC32C(NULL), CRC32C(''), CRC32C('MariaDB'), CRC32C('mariadb'); +CRC32C(NULL) CRC32C('') CRC32C('MariaDB') CRC32C('mariadb') +NULL 0 809606978 1378644259 DROP TABLE IF EXISTS t; Warnings: Note 1051 Unknown table 'test.t' CREATE TABLE t(a INT, b VARCHAR(2)); INSERT INTO t VALUES (1,'a'), (2,'qw'), (1,'t'), (3,'t'); -SELECT crc32(SUM(a)) FROM t; -crc32(SUM(a)) -1790921346 -SELECT crc32(AVG(a)) FROM t GROUP BY b; -crc32(AVG(a)) -768278432 -2875100430 -2875100430 -SELECT crc32(MAX(b)) FROM t GROUP BY a; -crc32(MAX(b)) -2238339752 -3114057431 -2238339752 +SELECT crc32(SUM(a)),crc32c(SUM(a)) FROM t; +crc32(SUM(a)) crc32c(SUM(a)) +1790921346 3058990603 +SELECT crc32(AVG(a)),crc32c(AVG(a)) FROM t GROUP BY b; +crc32(AVG(a)) crc32c(AVG(a)) +768278432 1816172052 +2875100430 1492934094 +2875100430 1492934094 +SELECT crc32(MAX(b)),crc32c(MAX(b)) FROM t GROUP BY a; +crc32(MAX(b)) crc32c(MAX(b)) +2238339752 3833565251 +3114057431 4173859780 +2238339752 3833565251 SELECT a, b, crc32(a) FROM t GROUP BY a,b HAVING crc32(MAX(a))=450215437; a b crc32(a) 2 qw 450215437 diff --git a/mysql-test/main/func_math.test b/mysql-test/main/func_math.test index 572e0fd0f6b..9fd95279974 100644 --- a/mysql-test/main/func_math.test +++ b/mysql-test/main/func_math.test @@ -849,15 +849,16 @@ SELECT CRC32('01234567'), CRC32('012345678'); SELECT CRC32('~!@$%^*'), CRC32('-0.0001'); SELECT CRC32(99999999999999999999999999999999); SELECT CRC32(-99999999999999999999999999999999); +SELECT CRC32C(NULL), CRC32C(''), CRC32C('MariaDB'), CRC32C('mariadb'); # Test cases for using the function in aggregate functions, group-by, having # and order-by clauses DROP TABLE IF EXISTS t; CREATE TABLE t(a INT, b VARCHAR(2)); INSERT INTO t VALUES (1,'a'), (2,'qw'), (1,'t'), (3,'t'); -SELECT crc32(SUM(a)) FROM t; -SELECT crc32(AVG(a)) FROM t GROUP BY b; -SELECT crc32(MAX(b)) FROM t GROUP BY a; +SELECT crc32(SUM(a)),crc32c(SUM(a)) FROM t; +SELECT crc32(AVG(a)),crc32c(AVG(a)) FROM t GROUP BY b; +SELECT crc32(MAX(b)),crc32c(MAX(b)) FROM t GROUP BY a; SELECT a, b, crc32(a) FROM t GROUP BY a,b HAVING crc32(MAX(a))=450215437; SELECT a,b,concat(a,b),crc32(concat(a,b)) FROM t ORDER BY crc32(concat(a,b)); DROP TABLE t; diff --git a/sql/item_create.cc b/sql/item_create.cc index 1aa7d02e76b..e8921b274ad 100644 --- a/sql/item_create.cc +++ b/sql/item_create.cc @@ -525,6 +525,19 @@ protected: }; +class Create_func_crc32c : public Create_func_arg1 +{ +public: + virtual Item *create_1_arg(THD *thd, Item *arg1); + + static Create_func_crc32c s_singleton; + +protected: + Create_func_crc32c() {} + virtual ~Create_func_crc32c() {} +}; + + class Create_func_datediff : public Create_func_arg2 { public: @@ -3123,6 +3136,16 @@ Create_func_crc32::create_1_arg(THD *thd, Item *arg1) return new (thd->mem_root) Item_func_crc32(thd, arg1); } + +Create_func_crc32c Create_func_crc32c::s_singleton; + +Item* +Create_func_crc32c::create_1_arg(THD *thd, Item *arg1) +{ + return new (thd->mem_root) Item_func_crc32c(thd, arg1); +} + + Create_func_datediff Create_func_datediff::s_singleton; Item* @@ -5555,6 +5578,7 @@ Native_func_registry func_array[] = { { STRING_WITH_LEN("COS") }, BUILDER(Create_func_cos)}, { { 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("DATEDIFF") }, BUILDER(Create_func_datediff)}, { { STRING_WITH_LEN("DAYNAME") }, BUILDER(Create_func_dayname)}, { { STRING_WITH_LEN("DAYOFMONTH") }, BUILDER(Create_func_dayofmonth)}, diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index d4bf28a9c21..a29580b7a54 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -4387,6 +4387,19 @@ longlong Item_func_crc32::val_int() return (longlong) my_checksum(0L, (uchar*)res->ptr(), res->length()); } +longlong Item_func_crc32c::val_int() +{ + DBUG_ASSERT(fixed()); + String *res=args[0]->val_str(&value); + if (!res) + { + null_value=1; + return 0; /* purecov: inspected */ + } + null_value=0; + return my_crc32c(0, res->ptr(), res->length()); +} + #ifdef HAVE_COMPRESS #include "zlib.h" diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index ba61206d8d9..c455a2b642a 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -1961,6 +1961,25 @@ public: { return get_item_copy<Item_func_crc32>(thd, this); } }; +class Item_func_crc32c :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_crc32c(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("crc32c") }; + return name; + } + bool fix_length_and_dec() override { max_length=10; return FALSE; } + longlong val_int() override; + Item *get_copy(THD *thd) override + { return get_item_copy<Item_func_crc32c>(thd, this); } +}; + class Item_func_uncompressed_length : public Item_long_func_length { String value; |