From 9706e7f8fc373d8f0b4d1474c8adaa3a7230ce4e Mon Sep 17 00:00:00 2001 From: Nathan Bossart Date: Thu, 8 Aug 2024 10:43:29 -0500 Subject: [PATCH v5 1/1] Add user-callable CRC functions. We've had code for CRC-32 and CRC-32C for some time (for WAL records, etc.), but there was no way for users to call it, despite apparent popular demand. The new crc32() and crc32c() functions both accept bytea and return bigint (to avoid returning negative values). XXX: NEEDS CATVERSION BUMP Author: Aleksander Alekseev Reviewed-by: Peter Eisentraut, Tom Lane Discussion: https://postgr.es/m/CAJ7c6TNMTGnqnG%3DyXXUQh9E88JDckmR45H2Q%2B%3DucaCLMOW1QQw%40mail.gmail.com --- doc/src/sgml/func.sgml | 34 +++++++++++++++++++++++ src/backend/utils/hash/pg_crc.c | 35 +++++++++++++++++++++++- src/include/catalog/pg_proc.dat | 8 ++++++ src/test/regress/expected/opr_sanity.out | 2 ++ src/test/regress/expected/strings.out | 27 ++++++++++++++++++ src/test/regress/sql/strings.sql | 9 ++++++ 6 files changed, 114 insertions(+), 1 deletion(-) diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml index 0f7154b76a..2a87668f4c 100644 --- a/doc/src/sgml/func.sgml +++ b/doc/src/sgml/func.sgml @@ -4490,6 +4490,40 @@ SELECT format('Testing %3$s, %2$s, %s', 'one', 'two', 'three'); + + + + crc32 + + crc32 ( bytea ) + bigint + + + Computes the CRC-32 value of the binary string. + + + crc32('abc'::bytea) + 891568578 + + + + + + + crc32c + + crc32c ( bytea ) + bigint + + + Computes the CRC-32C value of the binary string. + + + crc32c('abc'::bytea) + 910901175 + + + diff --git a/src/backend/utils/hash/pg_crc.c b/src/backend/utils/hash/pg_crc.c index 3595938dc4..e4a976a080 100644 --- a/src/backend/utils/hash/pg_crc.c +++ b/src/backend/utils/hash/pg_crc.c @@ -17,9 +17,12 @@ *------------------------------------------------------------------------- */ -#include "c.h" +#include "postgres.h" +#include "port/pg_crc32c.h" +#include "utils/builtins.h" #include "utils/pg_crc.h" +#include "varatt.h" /* * Lookup table for calculating CRC-32 using Sarwate's algorithm. @@ -95,3 +98,33 @@ const uint32 pg_crc32_table[256] = { 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D }; + +/* + * CRC variants + */ + +Datum +crc32_bytea(PG_FUNCTION_ARGS) +{ + bytea *in = PG_GETARG_BYTEA_PP(0); + pg_crc32 crc; + + INIT_TRADITIONAL_CRC32(crc); + COMP_TRADITIONAL_CRC32(crc, VARDATA_ANY(in), VARSIZE_ANY_EXHDR(in)); + FIN_TRADITIONAL_CRC32(crc); + + PG_RETURN_INT64(crc); +} + +Datum +crc32c_bytea(PG_FUNCTION_ARGS) +{ + bytea *in = PG_GETARG_BYTEA_PP(0); + pg_crc32c crc; + + INIT_CRC32C(crc); + COMP_CRC32C(crc, VARDATA_ANY(in), VARSIZE_ANY_EXHDR(in)); + FIN_CRC32C(crc); + + PG_RETURN_INT64(crc); +} diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat index d36f6001bb..ab29b581b0 100644 --- a/src/include/catalog/pg_proc.dat +++ b/src/include/catalog/pg_proc.dat @@ -7743,6 +7743,14 @@ proname => 'system', provolatile => 'v', prorettype => 'tsm_handler', proargtypes => 'internal', prosrc => 'tsm_system_handler' }, +# CRC variants +{ oid => '8571', descr => 'CRC-32 value', + proname => 'crc32', proleakproof => 't', prorettype => 'int8', + proargtypes => 'bytea', prosrc => 'crc32_bytea' }, +{ oid => '8572', descr => 'CRC-32C value', + proname => 'crc32c', proleakproof => 't', prorettype => 'int8', + proargtypes => 'bytea', prosrc => 'crc32c_bytea' }, + # cryptographic { oid => '2311', descr => 'MD5 hash', proname => 'md5', proleakproof => 't', prorettype => 'text', diff --git a/src/test/regress/expected/opr_sanity.out b/src/test/regress/expected/opr_sanity.out index 9d047b21b8..0d734169f1 100644 --- a/src/test/regress/expected/opr_sanity.out +++ b/src/test/regress/expected/opr_sanity.out @@ -874,6 +874,8 @@ xid8ne(xid8,xid8) xid8cmp(xid8,xid8) uuid_extract_timestamp(uuid) uuid_extract_version(uuid) +crc32(bytea) +crc32c(bytea) -- restore normal output mode \a\t -- List of functions used by libpq's fe-lobj.c diff --git a/src/test/regress/expected/strings.out b/src/test/regress/expected/strings.out index 52b69a107f..b65bb2d536 100644 --- a/src/test/regress/expected/strings.out +++ b/src/test/regress/expected/strings.out @@ -2255,6 +2255,33 @@ SELECT sha512('The quick brown fox jumps over the lazy dog.'); \x91ea1245f20d46ae9a037a989f54f1f790f0a47607eeb8a14d12890cea77a1bbc6c7ed9cf205e67b7f2b8fd4c7dfd3a7a8617e45f3c463d481c7e586c39ac1ed (1 row) +-- +-- CRC +-- +SELECT crc32(''); + crc32 +------- + 0 +(1 row) + +SELECT crc32('The quick brown fox jumps over the lazy dog.'); + crc32 +------------ + 1368401385 +(1 row) + +SELECT crc32c(''); + crc32c +-------- + 0 +(1 row) + +SELECT crc32c('The quick brown fox jumps over the lazy dog.'); + crc32c +----------- + 419469235 +(1 row) + -- -- encode/decode -- diff --git a/src/test/regress/sql/strings.sql b/src/test/regress/sql/strings.sql index 3959678992..8e0f3a0e75 100644 --- a/src/test/regress/sql/strings.sql +++ b/src/test/regress/sql/strings.sql @@ -719,6 +719,15 @@ SELECT sha384('The quick brown fox jumps over the lazy dog.'); SELECT sha512(''); SELECT sha512('The quick brown fox jumps over the lazy dog.'); +-- +-- CRC +-- +SELECT crc32(''); +SELECT crc32('The quick brown fox jumps over the lazy dog.'); + +SELECT crc32c(''); +SELECT crc32c('The quick brown fox jumps over the lazy dog.'); + -- -- encode/decode -- -- 2.39.3 (Apple Git-146)