From 760162fedb4f7ee6f0167cc6acfadee6ccb6be66 Mon Sep 17 00:00:00 2001 From: Nathan Bossart Date: Mon, 12 Aug 2024 10:35:06 -0500 Subject: [PATCH] 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 accept bytea input and return bigint (to avoid returning negative values). Bumps catversion. 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/catversion.h | 2 +- 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 ++++++ 7 files changed, 115 insertions(+), 2 deletions(-) diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml index 968a998552..cdde647513 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..a85e617186 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 }; + +/* + * SQL-callable functions + */ + +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/catversion.h b/src/include/catalog/catversion.h index 37c0354ab9..9a0ae27823 100644 --- a/src/include/catalog/catversion.h +++ b/src/include/catalog/catversion.h @@ -57,6 +57,6 @@ */ /* yyyymmddN */ -#define CATALOG_VERSION_NO 202408121 +#define CATALOG_VERSION_NO 202408122 #endif diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat index be37576a34..4abc6d9526 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 --