v63-0001-Add-range_get_constructor2.patch

application/octet-stream

Filename: v63-0001-Add-range_get_constructor2.patch
Type: application/octet-stream
Part: 0
Message: Re: SQL:2011 Application Time Update & Delete
From 7527408f142ab61d8e68bfc52601185d18f42d47 Mon Sep 17 00:00:00 2001
From: "Paul A. Jungwirth" <pj@illuminatedcomputing.com>
Date: Tue, 2 Dec 2025 21:30:13 -0800
Subject: [PATCH v63 1/8] Add range_get_constructor2

Look up the two-arg constructor for a given rangetype. We need this for
UPDATE/DELETE FOR PORTION OF, so that we can build a range from the FROM/TO
bounds.

There doesn't seem to be an easy way to find the constructor. The rule is that
the function has the same name as the rangetype, with arguments making the
range's subtype. Ideally we could just use the range's type oid, but I see a way
to do that. There are no pg_depend entries for built-in rangetypes, only
user-defined ones.

Author: Paul A. Jungwirth <pj@illuminatedcomputing.com>
---
 src/backend/utils/cache/lsyscache.c | 68 +++++++++++++++++++++++++++++
 src/include/utils/lsyscache.h       |  1 +
 2 files changed, 69 insertions(+)

diff --git a/src/backend/utils/cache/lsyscache.c b/src/backend/utils/cache/lsyscache.c
index fa7cd7e06a7..102692884bb 100644
--- a/src/backend/utils/cache/lsyscache.c
+++ b/src/backend/utils/cache/lsyscache.c
@@ -3615,6 +3615,74 @@ get_range_collation(Oid rangeOid)
 		return InvalidOid;
 }
 
+/*
+ * get_range_constructor2
+ *		Gets the 2-arg constructor for the given rangetype.
+ *
+ * It should be the function whose name and namespace match the rangetype,
+ * has 2 args matching the subtype, and returns the rangetype. To be extra sure,
+ * we make sure that prosrc is 'range_constructor2' and probin IS NULL.
+ *
+ * We can't use pg_depend, because built-in rangetypes don't have entries there.
+ *
+ * Domains on rangetypes don't define their own constructors,
+ * so caller should pass the basetype oid.
+ */
+Oid
+get_range_constructor2(Oid rngtypid)
+{
+	Oid			range_typelem = get_range_subtype(rngtypid);
+	char	   *rngname;
+	Oid			rngnamespace;
+	Oid			argoids[2];
+	oidvector  *argtypes;
+	HeapTuple	tp;
+
+	/* Is it really a rangetype? */
+	if (!OidIsValid(range_typelem))
+		elog(ERROR, "cache lookup failed for range %u", rngtypid);
+
+	/* Get the range's name and namespace */
+	tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(rngtypid));
+	if (HeapTupleIsValid(tp))
+	{
+		Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
+
+		rngname = pstrdup(NameStr(typtup->typname));
+		rngnamespace = typtup->typnamespace;
+		ReleaseSysCache(tp);
+	}
+	else
+		elog(ERROR, "cache lookup failed for type %u", rngtypid);
+
+	/* Find the constructor */
+	argoids[0] = range_typelem;
+	argoids[1] = range_typelem;
+	argtypes = buildoidvector(argoids, 2);
+	tp = SearchSysCache3(PROCNAMEARGSNSP,
+						 PointerGetDatum(rngname),
+						 PointerGetDatum(argtypes),
+						 ObjectIdGetDatum(rngnamespace));
+	if (HeapTupleIsValid(tp))
+	{
+		Form_pg_proc proctup = (Form_pg_proc) GETSTRUCT(tp);
+		Oid			result;
+		Datum		prosrc = SysCacheGetAttrNotNull(PROCNAMEARGSNSP, tp,
+													Anum_pg_proc_prosrc);
+
+		/* Sanity-checking */
+		if (proctup->prorettype == rngtypid &&
+			strcmp(TextDatumGetCString(prosrc), "range_constructor2") == 0 &&
+			heap_attisnull(tp, Anum_pg_proc_probin, NULL))
+		{
+			result = proctup->oid;
+			ReleaseSysCache(tp);
+			return result;
+		}
+	}
+	elog(ERROR, "cache lookup failed for procedure %s", rngname);
+}
+
 /*
  * get_range_multirange
  *		Returns the multirange type of a given range type
diff --git a/src/include/utils/lsyscache.h b/src/include/utils/lsyscache.h
index 50fb149e9ac..ad3d5f33b5e 100644
--- a/src/include/utils/lsyscache.h
+++ b/src/include/utils/lsyscache.h
@@ -200,6 +200,7 @@ extern char *get_namespace_name(Oid nspid);
 extern char *get_namespace_name_or_temp(Oid nspid);
 extern Oid	get_range_subtype(Oid rangeOid);
 extern Oid	get_range_collation(Oid rangeOid);
+extern Oid	get_range_constructor2(Oid rangeOid);
 extern Oid	get_range_multirange(Oid rangeOid);
 extern Oid	get_multirange_range(Oid multirangeOid);
 extern Oid	get_index_column_opclass(Oid index_oid, int attno);
-- 
2.47.3