Add user-callable CRC functions.
authorNathan Bossart <[email protected]>
Mon, 12 Aug 2024 15:35:06 +0000 (10:35 -0500)
committerNathan Bossart <[email protected]>
Mon, 12 Aug 2024 15:35:06 +0000 (10:35 -0500)
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
src/backend/utils/hash/pg_crc.c
src/include/catalog/catversion.h
src/include/catalog/pg_proc.dat
src/test/regress/expected/opr_sanity.out
src/test/regress/expected/strings.out
src/test/regress/sql/strings.sql

index 968a998552735537cc922ba92d12e040cffad64c..cdde647513563fc6742b535f119bcd2842b558ce 100644 (file)
@@ -4490,6 +4490,40 @@ SELECT format('Testing %3$s, %2$s, %s', 'one', 'two', 'three');
        </para></entry>
       </row>
 
+      <row>
+       <entry role="func_table_entry"><para role="func_signature">
+        <indexterm>
+         <primary>crc32</primary>
+        </indexterm>
+        <function>crc32</function> ( <type>bytea</type> )
+        <returnvalue>bigint</returnvalue>
+       </para>
+       <para>
+        Computes the CRC-32 value of the binary string.
+       </para>
+       <para>
+        <literal>crc32('abc'::bytea)</literal>
+        <returnvalue>891568578</returnvalue>
+       </para></entry>
+      </row>
+
+      <row>
+       <entry role="func_table_entry"><para role="func_signature">
+        <indexterm>
+         <primary>crc32c</primary>
+        </indexterm>
+        <function>crc32c</function> ( <type>bytea</type> )
+        <returnvalue>bigint</returnvalue>
+       </para>
+       <para>
+        Computes the CRC-32C value of the binary string.
+       </para>
+       <para>
+        <literal>crc32c('abc'::bytea)</literal>
+        <returnvalue>910901175</returnvalue>
+       </para></entry>
+      </row>
+
       <row>
        <entry role="func_table_entry"><para role="func_signature">
         <indexterm>
index 3595938dc4fb29058d16fbfc03ae1b31ef572566..a85e61718645cf8bda5273d188d646a224d3320f 100644 (file)
  *-------------------------------------------------------------------------
  */
 
-#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);
+}
index 37c0354ab913c502d504abcbb51c86d9caa81126..9a0ae278239a2130cd825f78c9747510a9b21bfd 100644 (file)
@@ -57,6 +57,6 @@
  */
 
 /*                         yyyymmddN */
-#define CATALOG_VERSION_NO 202408121
+#define CATALOG_VERSION_NO 202408122
 
 #endif
index be37576a34a57629526785477357190af7f57f58..4abc6d95262cc33f7cf3b60fa2595dc7e262d700 100644 (file)
   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',
index 9d047b21b88ee165c06770ac55aeae59682990d4..0d734169f11c74a9a994735f05bf660611550046 100644 (file)
@@ -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
index 52b69a107fb7aeed106f6d33f14f16a477450e02..b65bb2d5368baab70593cddd66931e196dac8ecc 100644 (file)
@@ -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
 --
index 395967899290b6b1b9d035a3aaea84833244e156..8e0f3a0e75f86fe539220cce509c2ff580991372 100644 (file)
@@ -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
 --