v47-0005-Add-intersect-support-func-for-FOR-PORTION-OF.patch
text/x-patch
Filename: v47-0005-Add-intersect-support-func-for-FOR-PORTION-OF.patch
Type: text/x-patch
Part: 4
Message:
Re: SQL:2011 application time
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: format-patch
Series: patch v47-0005
Subject: Add intersect support func for FOR PORTION OF
| File | + | − |
|---|---|---|
| doc/src/sgml/gist.sgml | 54 | 3 |
| doc/src/sgml/xindex.sgml | 7 | 1 |
| src/backend/access/gist/gistvalidate.c | 7 | 1 |
| src/include/access/gist.h | 2 | 1 |
| src/include/catalog/pg_amproc.dat | 9 | 0 |
From f5af7d685e717c17c0179aa1e0cb805252017237 Mon Sep 17 00:00:00 2001
From: "Paul A. Jungwirth" <pj@illuminatedcomputing.com>
Date: Sat, 30 Dec 2023 23:10:59 -0800
Subject: [PATCH v47 5/9] Add intersect support func for FOR PORTION OF
- Adds intersect support procs.
These just call the existing intersect functions,
but they let us compute the portion of a row that is updated/deleted
in a FOR PORTION command.
---
doc/src/sgml/gist.sgml | 57 ++++++++++++++++++++++++--
doc/src/sgml/xindex.sgml | 8 +++-
src/backend/access/gist/gistvalidate.c | 8 +++-
src/include/access/gist.h | 3 +-
src/include/catalog/pg_amproc.dat | 9 ++++
5 files changed, 79 insertions(+), 6 deletions(-)
diff --git a/doc/src/sgml/gist.sgml b/doc/src/sgml/gist.sgml
index 1fbddf1bfb0..f3314eccb9e 100644
--- a/doc/src/sgml/gist.sgml
+++ b/doc/src/sgml/gist.sgml
@@ -266,7 +266,7 @@ CREATE INDEX ON my_table USING GIST (my_inet_column inet_ops);
<para>
There are five methods that an index operator class for
- <acronym>GiST</acronym> must provide, and eight that are optional.
+ <acronym>GiST</acronym> must provide, and nine that are optional.
Correctness of the index is ensured
by proper implementation of the <function>same</function>, <function>consistent</function>
and <function>union</function> methods, while efficiency (size and speed) of the
@@ -296,7 +296,11 @@ CREATE INDEX ON my_table USING GIST (my_inet_column inet_ops);
temporal constraint indexes.
The optional thirteenth method <function>without_portion</function> is used by
<literal>RESTRICT</literal> foreign keys to compute the portion of history
- that was lost.
+ that was lost and also by <literal>FOR PORTION OF</literal> to compute the
+ leftover records outside the targeted bounds.
+ The optional fourteenth method <function>intersect</function> is used by
+ <literal>FOR PORTION OF</literal> to compute the new bounds of the updated/
+ deleted record.
</para>
<variablelist>
@@ -1247,7 +1251,8 @@ my_stratnum(PG_FUNCTION_ARGS)
</para>
<para>
This is used by temporal foreign keys to compute the part
- of history that was lost by an update.
+ of history that was lost by an update and also by temporal update/delete
+ commands to compute the bounds of the untouched duration.
</para>
<para>
@@ -1336,6 +1341,52 @@ my_range_without_portion(PG_FUNCTION_ARGS)
/* do when there is no more left */
SRF_RETURN_DONE(funcctx);
}
+</programlisting>
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><function>intersect</function></term>
+ <listitem>
+ <para>
+ Given two values of this opclass, it returns their intersection.
+ </para>
+ <para>
+ This is used for temporal update commands to compute the
+ new bounds of the changed row.
+ </para>
+
+ <para>
+ The <acronym>SQL</acronym> declaration of the function must look like
+ this (using <literal>my_intersect</literal> as an example):
+
+<programlisting>
+CREATE OR REPLACE FUNCTION my_range_intersect(anyrange, anyrange)
+RETURNS anyrange
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT;
+</programlisting>
+ </para>
+
+ <para>
+ The matching code in the C module could then follow this example:
+
+<programlisting>
+Datum
+my_range_intersect(PG_FUNCTION_ARGS)
+{
+ RangeType *r1 = PG_GETARG_RANGE_P(0);
+ RangeType *r2 = PG_GETARG_RANGE_P(1);
+ TypeCacheEntry *typcache;
+
+ /* Different types should be prevented by ANYRANGE matching rules */
+ if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
+ elog(ERROR, "range types do not match");
+
+ typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
+
+ PG_RETURN_RANGE_P(range_intersect_internal(typcache, r1, r2));
+}
</programlisting>
</para>
</listitem>
diff --git a/doc/src/sgml/xindex.sgml b/doc/src/sgml/xindex.sgml
index 85ef539d07c..d2fac08d742 100644
--- a/doc/src/sgml/xindex.sgml
+++ b/doc/src/sgml/xindex.sgml
@@ -508,7 +508,7 @@
</table>
<para>
- GiST indexes have thirteen support functions, eight of which are optional,
+ GiST indexes have fourteen support functions, nine of which are optional,
as shown in <xref linkend="xindex-gist-support-table"/>.
(For more information see <xref linkend="gist"/>.)
</para>
@@ -602,6 +602,12 @@
second parameter from first (optional)</entry>
<entry>13</entry>
</row>
+ <row>
+ <entry><function>intersect</function></entry>
+ <entry>computes intersection with <literal>FOR PORTION OF</literal>
+ bounds (optional)</entry>
+ <entry>14</entry>
+ </row>
</tbody>
</tgroup>
</table>
diff --git a/src/backend/access/gist/gistvalidate.c b/src/backend/access/gist/gistvalidate.c
index 0cdbea7484d..92aa559d4b3 100644
--- a/src/backend/access/gist/gistvalidate.c
+++ b/src/backend/access/gist/gistvalidate.c
@@ -154,6 +154,10 @@ gistvalidate(Oid opclassoid)
ok = check_amproc_signature(procform->amproc, opcintype, true, true,
2, 2, opcintype, opcintype);
break;
+ case GIST_INTERSECT_PROC:
+ ok = check_amproc_signature(procform->amproc, InvalidOid, false, true,
+ 2, 2, opcintype, opcintype);
+ break;
default:
ereport(INFO,
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
@@ -275,7 +279,8 @@ gistvalidate(Oid opclassoid)
if (i == GIST_DISTANCE_PROC || i == GIST_FETCH_PROC ||
i == GIST_COMPRESS_PROC || i == GIST_DECOMPRESS_PROC ||
i == GIST_OPTIONS_PROC || i == GIST_SORTSUPPORT_PROC ||
- i == GIST_STRATNUM_PROC || i == GIST_WITHOUT_PORTION_PROC)
+ i == GIST_STRATNUM_PROC || i == GIST_WITHOUT_PORTION_PROC ||
+ i == GIST_INTERSECT_PROC)
continue; /* optional methods */
ereport(INFO,
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
@@ -349,6 +354,7 @@ gistadjustmembers(Oid opfamilyoid,
case GIST_SORTSUPPORT_PROC:
case GIST_STRATNUM_PROC:
case GIST_WITHOUT_PORTION_PROC:
+ case GIST_INTERSECT_PROC:
/* Optional, so force it to be a soft family dependency */
op->ref_is_hard = false;
op->ref_is_family = true;
diff --git a/src/include/access/gist.h b/src/include/access/gist.h
index 37c2f0a50ec..84fbbdd59da 100644
--- a/src/include/access/gist.h
+++ b/src/include/access/gist.h
@@ -41,7 +41,8 @@
#define GIST_SORTSUPPORT_PROC 11
#define GIST_STRATNUM_PROC 12
#define GIST_WITHOUT_PORTION_PROC 13
-#define GISTNProcs 13
+#define GIST_INTERSECT_PROC 14
+#define GISTNProcs 14
/*
* Page opaque data in a GiST index page.
diff --git a/src/include/catalog/pg_amproc.dat b/src/include/catalog/pg_amproc.dat
index ad58bb56c79..33f4a5cb8d0 100644
--- a/src/include/catalog/pg_amproc.dat
+++ b/src/include/catalog/pg_amproc.dat
@@ -509,6 +509,9 @@
{ amprocfamily => 'gist/box_ops', amproclefttype => 'box',
amprocrighttype => 'box', amprocnum => '12',
amproc => 'gist_stratnum_identity' },
+{ amprocfamily => 'gist/box_ops', amproclefttype => 'box',
+ amprocrighttype => 'box', amprocnum => '14',
+ amproc => 'box_intersect(box,box)' },
{ amprocfamily => 'gist/poly_ops', amproclefttype => 'polygon',
amprocrighttype => 'polygon', amprocnum => '1',
amproc => 'gist_poly_consistent' },
@@ -612,6 +615,9 @@
{ amprocfamily => 'gist/range_ops', amproclefttype => 'anyrange',
amprocrighttype => 'anyrange', amprocnum => '13',
amproc => 'range_without_portion(anyrange,anyrange)' },
+{ amprocfamily => 'gist/range_ops', amproclefttype => 'anyrange',
+ amprocrighttype => 'anyrange', amprocnum => '14',
+ amproc => 'range_intersect(anyrange,anyrange)' },
{ amprocfamily => 'gist/network_ops', amproclefttype => 'inet',
amprocrighttype => 'inet', amprocnum => '1',
amproc => 'inet_gist_consistent' },
@@ -655,6 +661,9 @@
{ amprocfamily => 'gist/multirange_ops', amproclefttype => 'anymultirange',
amprocrighttype => 'anymultirange', amprocnum => '13',
amproc => 'multirange_without_portion(anymultirange,anymultirange)' },
+{ amprocfamily => 'gist/multirange_ops', amproclefttype => 'anymultirange',
+ amprocrighttype => 'anymultirange', amprocnum => '14',
+ amproc => 'multirange_intersect(anymultirange,anymultirange)' },
# gin
{ amprocfamily => 'gin/array_ops', amproclefttype => 'anyarray',
--
2.42.0