v1-0001-Add-SQL-level-datum-equality-tests.patch
application/octet-stream
Filename: v1-0001-Add-SQL-level-datum-equality-tests.patch
Type: application/octet-stream
Part: 0
Message:
SQL-level pg_datum_image_equal
From f5264368a05bb49b4ce0e4ff586fb5da6b1f5cc4 Mon Sep 17 00:00:00 2001
From: Matthias van de Meent <boekewurm+postgres@gmail.com>
Date: Wed, 10 Dec 2025 18:45:19 +0100
Subject: [PATCH v1] Add SQL-level datum equality tests
This enables improved performance for users that need to test for
exact bytewise differences in SQL; e.g. to see if an UPDATE is
really necessary for externally provided values.
A workaround around this limitation was possible through various
methods, but a generic method was not available for all types.
---
src/backend/utils/adt/pseudotypes.c | 51 ++++++++++++++++++++++++
src/include/catalog/pg_proc.dat | 7 ++++
src/test/regress/expected/opr_sanity.out | 1 +
3 files changed, 59 insertions(+)
diff --git a/src/backend/utils/adt/pseudotypes.c b/src/backend/utils/adt/pseudotypes.c
index 317a1f2b282..216d895d2f7 100644
--- a/src/backend/utils/adt/pseudotypes.c
+++ b/src/backend/utils/adt/pseudotypes.c
@@ -23,7 +23,9 @@
#include "postgres.h"
#include "libpq/pqformat.h"
+#include "utils/datum.h"
#include "utils/fmgrprotos.h"
+#include "utils/lsyscache.h"
/*
@@ -375,3 +377,52 @@ PSEUDOTYPE_DUMMY_IO_FUNCS(anyelement);
PSEUDOTYPE_DUMMY_IO_FUNCS(anynonarray);
PSEUDOTYPE_DUMMY_IO_FUNCS(anycompatible);
PSEUDOTYPE_DUMMY_IO_FUNCS(anycompatiblenonarray);
+
+/*
+ * Compares two datums of the same (any) type, and returns whether they have
+ * the same binary representation.
+ */
+Datum
+pg_datum_image_equal(PG_FUNCTION_ARGS)
+{
+ bool eq;
+
+ if (PG_ARGISNULL(0) != PG_ARGISNULL(1))
+ {
+ eq = false;
+ }
+ else if (PG_ARGISNULL(0))
+ {
+ /* both NULL */
+ eq = true;
+ }
+ else
+ {
+ Oid typ;
+ Datum arg0;
+ Datum arg1;
+ bool typbyval;
+ char typalign;
+ int16 typlen;
+
+ typ = get_fn_expr_argtype(fcinfo->flinfo, 0);
+
+ if (!OidIsValid(typ))
+ {
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("could not determine type")));
+ }
+
+ Assert(typ == get_fn_expr_argtype(fcinfo->flinfo, 1));
+
+ arg0 = PG_GETARG_DATUM(0);
+ arg1 = PG_GETARG_DATUM(1);
+
+ get_typlenbyvalalign(typ, &typlen, &typbyval, &typalign);
+
+ eq = datum_image_eq(arg0, arg1, typbyval, typlen);
+ }
+
+ PG_RETURN_BOOL(eq);
+}
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index fd9448ec7b9..2f1b1ba8370 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -12612,4 +12612,11 @@
proargnames => '{pid,io_id,io_generation,state,operation,off,length,target,handle_data_len,raw_result,result,target_desc,f_sync,f_localmem,f_buffered}',
prosrc => 'pg_get_aios' },
+{ oid => '9200',
+ descr => 'test if two values have the same binary representation',
+ proname => 'pg_datum_image_equal', proisstrict => 'f',
+ proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'anyelement anyelement',
+ prosrc => 'pg_datum_image_equal' },
+
]
diff --git a/src/test/regress/expected/opr_sanity.out b/src/test/regress/expected/opr_sanity.out
index a357e1d0c0e..57fe8d6ede8 100644
--- a/src/test/regress/expected/opr_sanity.out
+++ b/src/test/regress/expected/opr_sanity.out
@@ -880,6 +880,7 @@ bytea(integer)
bytea(bigint)
bytea_larger(bytea,bytea)
bytea_smaller(bytea,bytea)
+pg_datum_image_equal(anyelement,anyelement)
-- Check that functions without argument are not marked as leakproof.
SELECT p1.oid::regprocedure
FROM pg_proc p1 JOIN pg_namespace pn
--
2.50.1 (Apple Git-155)