brin-inclusion-v05-inclusion-opclasses.patch
application/octet-stream
Filename: brin-inclusion-v05-inclusion-opclasses.patch
Type: application/octet-stream
Part: 2
Message:
Re: BRIN range operator class
Patch
Format: format-patch
Series: patch v5-0006
Subject: inclusion opclasses
| File | + | − |
|---|---|---|
| doc/src/sgml/brin.sgml | 71 | 1 |
| src/backend/access/brin/brin_inclusion.c | 643 | 0 |
| src/backend/access/brin/Makefile | 1 | 1 |
| src/include/access/brin_internal.h | 6 | 0 |
| src/include/catalog/pg_am.h | 2 | 1 |
| src/include/catalog/pg_amop.h | 55 | 0 |
| src/include/catalog/pg_amproc.h | 31 | 0 |
| src/include/catalog/pg_opclass.h | 6 | 1 |
| src/include/catalog/pg_opfamily.h | 3 | 0 |
| src/include/catalog/pg_proc.h | 10 | 0 |
| src/test/regress/expected/brin.out | 88 | 56 |
| src/test/regress/expected/opr_sanity.out | 28 | 1 |
| src/test/regress/sql/brin.sql | 88 | 56 |
From e9bd85a3e03cf40443043ddfbc3388d6e66f5457 Mon Sep 17 00:00:00 2001
From: Emre Hasegeli <emre@hasegeli.com>
Date: Sun, 29 Mar 2015 21:59:21 +0200
Subject: [PATCH 6/8] inclusion opclasses
---
doc/src/sgml/brin.sgml | 72 +++-
src/backend/access/brin/Makefile | 2 +-
src/backend/access/brin/brin_inclusion.c | 643 +++++++++++++++++++++++++++++++
src/include/access/brin_internal.h | 6 +
src/include/catalog/pg_am.h | 3 +-
src/include/catalog/pg_amop.h | 55 +++
src/include/catalog/pg_amproc.h | 31 ++
src/include/catalog/pg_opclass.h | 7 +-
src/include/catalog/pg_opfamily.h | 3 +
src/include/catalog/pg_proc.h | 10 +
src/test/regress/expected/brin.out | 144 ++++---
src/test/regress/expected/opr_sanity.out | 29 +-
src/test/regress/sql/brin.sql | 144 ++++---
13 files changed, 1032 insertions(+), 117 deletions(-)
create mode 100644 src/backend/access/brin/brin_inclusion.c
diff --git a/doc/src/sgml/brin.sgml b/doc/src/sgml/brin.sgml
index 1ac282c..6495ff8 100644
--- a/doc/src/sgml/brin.sgml
+++ b/doc/src/sgml/brin.sgml
@@ -65,21 +65,23 @@
<para>
The core <productname>PostgreSQL</productname> distribution
includes the <acronym>BRIN</acronym> operator classes shown in
<xref linkend="brin-builtin-opclasses-table">.
</para>
<para>
The <firstterm>minmax</>
operator classes store the minimum and the maximum values appearing
- in the indexed column within the range.
+ in the indexed column within the range. The <firstterm>inclusion</>
+ operator classes store the union of the values in the indexed column
+ within the range.
</para>
<table id="brin-builtin-opclasses-table">
<title>Built-in <acronym>BRIN</acronym> Operator Classes</title>
<tgroup cols="3">
<thead>
<row>
<entry>Name</entry>
<entry>Indexed Data Type</entry>
<entry>Indexable Operators</entry>
@@ -245,20 +247,32 @@
<entry><type>inet</type></entry>
<entry>
<literal><</literal>
<literal><=</literal>
<literal>=</literal>
<literal>>=</literal>
<literal>></literal>
</entry>
</row>
<row>
+ <entry><literal>inet_inclusion_ops</literal></entry>
+ <entry><type>inet</type></entry>
+ <entry>
+ <literal>&&</>
+ <literal>>></>
+ <literal>>>=</>
+ <literal><<</literal>
+ <literal><<=</literal>
+ <literal>=</literal>
+ </entry>
+ </row>
+ <row>
<entry><literal>bpchar_minmax_ops</literal></entry>
<entry><type>character</type></entry>
<entry>
<literal><</literal>
<literal><=</literal>
<literal>=</literal>
<literal>>=</literal>
<literal>></literal>
</entry>
</row>
@@ -366,30 +380,86 @@
<entry><type>uuid</type></entry>
<entry>
<literal><</literal>
<literal><=</literal>
<literal>=</literal>
<literal>>=</literal>
<literal>></literal>
</entry>
</row>
<row>
+ <entry><literal>range_inclusion_ops</></entry>
+ <entry><type>any range type</type></entry>
+ <entry>
+ <literal>&&</>
+ <literal>&></>
+ <literal>&<</>
+ <literal>>></>
+ <literal><<</>
+ <literal><@</>
+ <literal>=</>
+ <literal>@></>
+ <literal><</literal>
+ <literal><=</literal>
+ <literal>=</literal>
+ <literal>>=</literal>
+ <literal>></literal>
+ </entry>
+ </row>
+ <row>
<entry><literal>pg_lsn_minmax_ops</literal></entry>
<entry><type>pg_lsn</type></entry>
<entry>
<literal><</literal>
<literal><=</literal>
<literal>=</literal>
<literal>>=</literal>
<literal>></literal>
</entry>
</row>
+ <row>
+ <entry><literal>box_inclusion_ops</></entry>
+ <entry><type>box</type></entry>
+ <entry>
+ <literal>&&</>
+ <literal>&></>
+ <literal>&<</>
+ <literal>>></>
+ <literal><<</>
+ <literal><@</>
+ <literal>~=</>
+ <literal>@></>
+ <literal>&>|</>
+ <literal>|&<</>
+ <literal>>>|</>
+ <literal>|<<</literal>
+ </entry>
+ </row>
+ <row>
+ <entry><literal>point_box_inclusion_ops</></entry>
+ <entry><type>point</type></entry>
+ <entry>
+ <literal>&&</>
+ <literal>&></>
+ <literal>&<</>
+ <literal>>></>
+ <literal><<</>
+ <literal><@</>
+ <literal>~=</>
+ <literal>&>|</>
+ <literal>|&<</>
+ <literal>>>|</>
+ <literal>|<<</literal>
+ <literal>>^</>
+ <literal>|<^</literal>
+ </entry>
+ </row>
</tbody>
</tgroup>
</table>
</sect1>
<sect1 id="brin-extensibility">
<title>Extensibility</title>
<para>
The <acronym>BRIN</acronym> interface has a high level of abstraction,
diff --git a/src/backend/access/brin/Makefile b/src/backend/access/brin/Makefile
index ac44fcd..fb36882 100644
--- a/src/backend/access/brin/Makefile
+++ b/src/backend/access/brin/Makefile
@@ -6,13 +6,13 @@
# IDENTIFICATION
# src/backend/access/brin/Makefile
#
#-------------------------------------------------------------------------
subdir = src/backend/access/brin
top_builddir = ../../../..
include $(top_builddir)/src/Makefile.global
OBJS = brin.o brin_pageops.o brin_revmap.o brin_tuple.o brin_xlog.o \
- brin_minmax.o
+ brin_minmax.o brin_inclusion.o
include $(top_srcdir)/src/backend/common.mk
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
new file mode 100644
index 0000000..c24cc17
--- /dev/null
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -0,0 +1,643 @@
+/*
+ * brin_inclusion.c
+ * Implementation of inclusion opclasses for BRIN
+ *
+ * This module provides C level BRIN support functions for the *_inclusion_ops
+ * operator classes. A few SQL level support functions are also required to
+ * the opclasses.
+ *
+ * Portions Copyright (c) 1996-2015, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ * src/backend/access/brin/brin_inclusion.c
+ */
+#include "postgres.h"
+
+#include "access/genam.h"
+#include "access/brin_internal.h"
+#include "access/brin_tuple.h"
+#include "access/skey.h"
+#include "catalog/pg_type.h"
+#include "catalog/pg_amop.h"
+#include "utils/datum.h"
+#include "utils/lsyscache.h"
+#include "utils/rel.h"
+#include "utils/syscache.h"
+
+
+/*
+ * Additional SQL level support functions
+ *
+ * Procedure numbers must not collide with BRIN_PROCNUM defines in
+ * brin_internal.h.
+ */
+#define INCLUSION_MAX_PROCNUMS 5 /* maximum support procs we need */
+#define PROCNUM_MERGE 11
+#define PROCNUM_MERGEABLE 12 /* optional */
+#define PROCNUM_CAST 13 /* optional */
+#define PROCNUM_CONTAINS 14 /* optional */
+#define PROCNUM_EMPTY 15 /* optional */
+
+
+/*
+ * Subtract this from procnum to obtain index in InclusionOpaque arrays
+ * (Must be equal to minimum of private procnums)
+ */
+#define PROCNUM_BASE 11
+
+typedef struct InclusionOpaque
+{
+ FmgrInfo procinfos[INCLUSION_MAX_PROCNUMS];
+ bool exists[INCLUSION_MAX_PROCNUMS];
+ bool inited[INCLUSION_MAX_PROCNUMS];
+ Oid last_subtype;
+ FmgrInfo strategy_procinfos[RTMaxStrategyNumber];
+ bool strategy_inited[RTMaxStrategyNumber];
+} InclusionOpaque;
+
+static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
+ uint16 procnum);
+static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
+ Oid subtype, uint16 strategynum);
+
+
+/*
+ * BRIN inclusion OpcInfo function
+ */
+Datum
+brin_inclusion_opcinfo(PG_FUNCTION_ARGS)
+{
+ Oid typoid = PG_GETARG_OID(0);
+ BrinOpcInfo *result;
+
+ /*
+ * opaque->procinfos is initialized lazily, as indicated by 'inited'
+ * which is initialized to all false by palloc0.
+ */
+ result = palloc0(MAXALIGN(SizeofBrinOpcInfo(3)) + sizeof(InclusionOpaque));
+ result->oi_nstored = 3;
+ result->oi_opaque = (InclusionOpaque *)
+ MAXALIGN((char *) result + SizeofBrinOpcInfo(3));
+ result->oi_typids[0] = typoid; /* the union */
+ result->oi_typids[1] = BOOLOID; /* includes elements that are not mergeable */
+ result->oi_typids[2] = BOOLOID; /* includes empty element */
+
+ PG_RETURN_POINTER(result);
+}
+
+/*
+ * BRIN inclusion add value function
+ *
+ * Examine the given index tuple (which contains partial status of a certain
+ * page range) by comparing it to the given value that comes from another heap
+ * tuple. If the new value is outside the union specified by the
+ * existing tuple values, update the index tuple and return true. Otherwise,
+ * return false and do not modify in this case.
+ */
+Datum
+brin_inclusion_add_value(PG_FUNCTION_ARGS)
+{
+ BrinDesc *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
+ BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
+ Datum newval = PG_GETARG_DATUM(2);
+ bool isnull = PG_GETARG_BOOL(3);
+ Oid colloid = PG_GET_COLLATION();
+ FmgrInfo *frmg;
+ Datum result;
+ bool new = false;
+ AttrNumber attno;
+ Form_pg_attribute attr;
+
+ /*
+ * If the new value is null, we record that we saw it if it's the first
+ * one; otherwise, there's nothing to do.
+ */
+ if (isnull)
+ {
+ if (column->bv_hasnulls)
+ PG_RETURN_BOOL(false);
+
+ column->bv_hasnulls = true;
+ PG_RETURN_BOOL(true);
+ }
+
+ attno = column->bv_attno;
+ attr = bdesc->bd_tupdesc->attrs[attno - 1];
+
+ /*
+ * If the recorded value is null, cast or copy the new value (which we
+ * know to be not null), and we're almost done.
+ */
+ if (column->bv_allnulls)
+ {
+ frmg = inclusion_get_procinfo(bdesc, attno, PROCNUM_CAST);
+ if (frmg != NULL)
+ column->bv_values[0] = FunctionCall1Coll(frmg, colloid, newval);
+ else
+ column->bv_values[0] = datumCopy(newval, attr->attbyval, attr->attlen);
+ column->bv_values[1] = BoolGetDatum(false);
+ column->bv_values[2] = BoolGetDatum(false);
+ column->bv_allnulls = false;
+ new = true;
+ }
+
+ /* Stop if it already contains elements that are not mergeable. */
+ if (DatumGetBool(column->bv_values[1]))
+ PG_RETURN_BOOL(false);
+
+ /* Check if the new value is empty. */
+ frmg = inclusion_get_procinfo(bdesc, attno, PROCNUM_EMPTY);
+ if (frmg != NULL && DatumGetBool(FunctionCall1Coll(frmg, colloid, newval)))
+ {
+ if (!DatumGetBool(column->bv_values[2]))
+ {
+ column->bv_values[2] = BoolGetDatum(true);
+ PG_RETURN_BOOL(true);
+ }
+
+ PG_RETURN_BOOL(false);
+ }
+
+ if (new)
+ PG_RETURN_BOOL(true);
+
+ /* Check if the new value is already contained. */
+ frmg = inclusion_get_procinfo(bdesc, attno, PROCNUM_CONTAINS);
+ if (frmg != NULL &&
+ DatumGetBool(FunctionCall2Coll(frmg, colloid, column->bv_values[0],
+ newval)))
+ PG_RETURN_BOOL(false);
+
+ /* Cast the new value if storage type is different. */
+ frmg = inclusion_get_procinfo(bdesc, attno, PROCNUM_CAST);
+ if (frmg != NULL)
+ newval = FunctionCall1Coll(frmg, colloid, newval);
+
+ /* Check if the new value is mergeable to the union. */
+ frmg = inclusion_get_procinfo(bdesc, attno, PROCNUM_MERGEABLE);
+ if (frmg != NULL &&
+ !DatumGetBool(FunctionCall2Coll(frmg, colloid, column->bv_values[0],
+ newval)))
+ {
+ column->bv_values[1] = BoolGetDatum(true);
+ PG_RETURN_BOOL(true);
+ }
+
+ /* Finally, merge the new value to the union. */
+ frmg = inclusion_get_procinfo(bdesc, attno, PROCNUM_MERGE);
+ Assert(frmg != NULL);
+ result = FunctionCall2Coll(frmg, colloid, column->bv_values[0], newval);
+ if (!attr->attbyval)
+ pfree(DatumGetPointer(column->bv_values[0]));
+ column->bv_values[0] = result;
+
+ PG_RETURN_BOOL(true);
+}
+
+/*
+ * BRIN inclusion consistent function
+ *
+ * All of the strategies are optional.
+ */
+Datum
+brin_inclusion_consistent(PG_FUNCTION_ARGS)
+{
+ BrinDesc *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
+ BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
+ ScanKey key = (ScanKey) PG_GETARG_POINTER(2);
+ Oid colloid = PG_GET_COLLATION(),
+ subtype;
+ AttrNumber attno;
+ Datum query;
+ FmgrInfo *frmg;
+ Datum result;
+
+ Assert(key->sk_attno == column->bv_attno);
+
+ /* Handle IS NULL/IS NOT NULL tests. */
+ if (key->sk_flags & SK_ISNULL)
+ {
+ if (key->sk_flags & SK_SEARCHNULL)
+ {
+ if (column->bv_allnulls || column->bv_hasnulls)
+ PG_RETURN_BOOL(true);
+ PG_RETURN_BOOL(false);
+ }
+
+ /*
+ * For IS NOT NULL, we can only skip ranges that are known to have
+ * only nulls.
+ */
+ Assert(key->sk_flags & SK_SEARCHNOTNULL);
+ PG_RETURN_BOOL(!column->bv_allnulls);
+ }
+
+ /* If it is all nulls, it cannot possibly be consistent. */
+ if (column->bv_allnulls)
+ PG_RETURN_BOOL(false);
+
+ /* It has to be checked, if it contains elements that are not mergeable. */
+ if (DatumGetBool(column->bv_values[1]))
+ PG_RETURN_BOOL(true);
+
+ attno = key->sk_attno;
+ subtype = key->sk_subtype;
+ query = key->sk_argument;
+ switch (key->sk_strategy)
+ {
+ /*
+ * Placement strategies
+ *
+ * They are implemented by using logical negation of the other
+ * placement operators. So the other strategies are required for
+ * them to be used. An error will be thrown by index_getstrategyprocinfo()
+ * if the required strategy does not exists.
+ *
+ * These all return false if either argument is empty, so there is
+ * no need to check for empty elements.
+ */
+
+ case RTLeftStrategyNumber:
+ frmg = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
+ RTOverRightStrategyNumber);
+ result = FunctionCall2Coll(frmg, colloid, column->bv_values[0],
+ query);
+ PG_RETURN_BOOL(!DatumGetBool(result));
+
+ case RTOverLeftStrategyNumber:
+ frmg = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
+ RTRightStrategyNumber);
+ result = FunctionCall2Coll(frmg, colloid, column->bv_values[0],
+ query);
+ PG_RETURN_BOOL(!DatumGetBool(result));
+
+ case RTOverRightStrategyNumber:
+ frmg = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
+ RTLeftStrategyNumber);
+ result = FunctionCall2Coll(frmg, colloid, column->bv_values[0],
+ query);
+ PG_RETURN_BOOL(!DatumGetBool(result));
+
+ case RTRightStrategyNumber:
+ frmg = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
+ RTOverLeftStrategyNumber);
+ result = FunctionCall2Coll(frmg, colloid, column->bv_values[0],
+ query);
+ PG_RETURN_BOOL(!DatumGetBool(result));
+
+ case RTBelowStrategyNumber:
+ frmg = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
+ RTOverAboveStrategyNumber);
+ result = FunctionCall2Coll(frmg, colloid, column->bv_values[0],
+ query);
+ PG_RETURN_BOOL(!DatumGetBool(result));
+
+ case RTOverBelowStrategyNumber:
+ frmg = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
+ RTAboveStrategyNumber);
+ result = FunctionCall2Coll(frmg, colloid, column->bv_values[0],
+ query);
+ PG_RETURN_BOOL(!DatumGetBool(result));
+
+ case RTOverAboveStrategyNumber:
+ frmg = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
+ RTBelowStrategyNumber);
+ result = FunctionCall2Coll(frmg, colloid, column->bv_values[0],
+ query);
+ PG_RETURN_BOOL(!DatumGetBool(result));
+
+ case RTAboveStrategyNumber:
+ frmg = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
+ RTOverBelowStrategyNumber);
+ result = FunctionCall2Coll(frmg, colloid, column->bv_values[0],
+ query);
+ PG_RETURN_BOOL(!DatumGetBool(result));
+
+ /*
+ * Overlaps and contains strategies
+ *
+ * These strategies are simple enough that we will call the operator
+ * of the strategy. Empty element doesn't change their the results.
+ */
+
+ case RTOverlapStrategyNumber:
+ case RTContainsStrategyNumber:
+ case RTOldContainsStrategyNumber:
+ case RTContainsElemStrategyNumber:
+ case RTContainsNotEqualStrategyNumber:
+ frmg = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
+ key->sk_strategy);
+ result = FunctionCall2Coll(frmg, colloid, column->bv_values[0],
+ query);
+ PG_RETURN_DATUM(result);
+
+ /*
+ * Contained by strategies
+ *
+ * We cannot just call the original operator for the contained by
+ * strategies because some elements can be contained even thought
+ * the union is not.
+ *
+ * Also, we will check for empty elements as they are not merged to
+ * the union but contained by everything.
+ */
+
+ case RTContainedByStrategyNumber:
+ case RTOldContainedByStrategyNumber:
+ case RTContainedByNotEqualStrategyNumber:
+ frmg = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
+ RTOverlapStrategyNumber);
+ result = FunctionCall2Coll(frmg, colloid, column->bv_values[0],
+ query);
+ if (DatumGetBool(result))
+ PG_RETURN_BOOL(true);
+
+ PG_RETURN_DATUM(column->bv_values[2]);
+
+ /*
+ * Adjacent strategy
+ *
+ * To be adjacent with an element in the query most likely to overlap
+ * with the union. We will call the actual adjacent procedure in
+ * case it is not.
+ *
+ * An empty element cannot be adjacent to any other, so there is
+ * no need to check for it.
+ */
+
+ case RTAdjacentStrategyNumber:
+ frmg = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
+ RTOverlapStrategyNumber);
+ result = FunctionCall2Coll(frmg, colloid, column->bv_values[0],
+ query);
+ if (DatumGetBool(result))
+ PG_RETURN_BOOL(true);
+
+ frmg = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
+ RTAdjacentStrategyNumber);
+ result = FunctionCall2Coll(frmg, colloid, column->bv_values[0],
+ query);
+ PG_RETURN_DATUM(result);
+
+ /*
+ * Basic comparison strategies
+ *
+ * It is straightforward to support the equality strategies with
+ * the contains operator. Generally, inequality strategies do not
+ * make much sense for the types which will be used with the inclusion
+ * operator class, but is is possible to implement them with logical
+ * negation of the left of and right of operator.
+ *
+ * Note that, these strategies except the same strategy are not
+ * suitable for the geometric types which use basic comparison
+ * operators for their areas.
+ *
+ * Empty elements are considered to be less than the others. We
+ * cannot use the empty support function to check the query is
+ * an empty element, because the query can be another data type than
+ * the empty support function argument. So we will return true,
+ * if there is a possibility that empty elements will change
+ * the result.
+ */
+
+ case RTLessStrategyNumber:
+ case RTLessEqualStrategyNumber:
+ frmg = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
+ RTRightStrategyNumber);
+ result = FunctionCall2Coll(frmg, colloid, column->bv_values[0],
+ query);
+ if (!DatumGetBool(result))
+ PG_RETURN_BOOL(true);
+
+ PG_RETURN_DATUM(column->bv_values[2]);
+
+ case RTSameStrategyNumber:
+ case RTEqualStrategyNumber:
+ frmg = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
+ RTContainsStrategyNumber);
+ result = FunctionCall2Coll(frmg, colloid, column->bv_values[0],
+ query);
+ if (DatumGetBool(result))
+ PG_RETURN_BOOL(true);
+
+ PG_RETURN_DATUM(column->bv_values[2]);
+
+
+ case RTGreaterEqualStrategyNumber:
+ frmg = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
+ RTLeftStrategyNumber);
+ result = FunctionCall2Coll(frmg, colloid, column->bv_values[0],
+ query);
+ if (!DatumGetBool(result))
+ PG_RETURN_BOOL(true);
+
+ PG_RETURN_DATUM(column->bv_values[2]);
+
+ case RTGreaterStrategyNumber:
+ frmg = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
+ RTLeftStrategyNumber);
+ result = FunctionCall2Coll(frmg, colloid, column->bv_values[0],
+ query);
+ PG_RETURN_BOOL(!DatumGetBool(result));
+
+ default:
+ /* shouldn't happen */
+ elog(ERROR, "invalid strategy number %d", key->sk_strategy);
+ PG_RETURN_BOOL(false);
+ }
+}
+
+/*
+ * BRIN inclusion union function
+ *
+ * Given two BrinValues, update the first of them as a union of the summary
+ * values contained in both. The second one is untouched.
+ */
+Datum
+brin_inclusion_union(PG_FUNCTION_ARGS)
+{
+ BrinDesc *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
+ BrinValues *col_a = (BrinValues *) PG_GETARG_POINTER(1);
+ BrinValues *col_b = (BrinValues *) PG_GETARG_POINTER(2);
+ Oid colloid = PG_GET_COLLATION();
+ AttrNumber attno;
+ Form_pg_attribute attr;
+ FmgrInfo *frmg;
+ Datum result;
+
+ Assert(col_a->bv_attno == col_b->bv_attno);
+
+ /* Adjust "hasnulls". */
+ if (!col_a->bv_hasnulls && col_b->bv_hasnulls)
+ col_a->bv_hasnulls = true;
+
+ /* If there are no values in B, there's nothing left to do. */
+ if (col_b->bv_allnulls)
+ PG_RETURN_VOID();
+
+ attno = col_a->bv_attno;
+ attr = bdesc->bd_tupdesc->attrs[attno - 1];
+
+ /*
+ * Adjust "allnulls". If A doesn't have values, just copy the values
+ * from B into A, and we're done. We cannot run the operators in this
+ * case, because values in A might contain garbage. Note we already
+ * established that B contains values.
+ */
+ if (col_a->bv_allnulls)
+ {
+ col_a->bv_allnulls = false;
+ col_a->bv_values[0] = datumCopy(col_b->bv_values[0],
+ attr->attbyval, attr->attlen);
+ col_a->bv_values[2] = col_b->bv_values[2];
+ col_a->bv_values[1] = col_b->bv_values[1];
+ PG_RETURN_VOID();
+ }
+
+ /* Check if B includes empty elements. */
+ if (!DatumGetBool(col_a->bv_values[2]) &&
+ DatumGetBool(col_b->bv_values[2]))
+ col_a->bv_values[2] = BoolGetDatum(true);
+
+ /* Check if A includes elements that are not mergeable. */
+ if (DatumGetBool(col_a->bv_values[1]))
+ PG_RETURN_VOID();
+
+ /* Check if B includes elements that are not mergeable. */
+ if (DatumGetBool(col_b->bv_values[1]))
+ {
+ col_a->bv_values[1] = BoolGetDatum(true);
+ PG_RETURN_VOID();
+ }
+
+ /* Check if A and B are mergeable. */
+ frmg = inclusion_get_procinfo(bdesc, attno, PROCNUM_MERGEABLE);
+ if (frmg != NULL &&
+ !DatumGetBool(FunctionCall2Coll(frmg, colloid, col_a->bv_values[0],
+ col_b->bv_values[0])))
+ {
+ col_a->bv_values[1] = BoolGetDatum(true);
+ PG_RETURN_VOID();
+ }
+
+ /* Finally, merge B to A. */
+ frmg = inclusion_get_procinfo(bdesc, attno, PROCNUM_MERGE);
+ Assert(frmg != NULL);
+ result = FunctionCall2Coll(frmg, colloid, col_a->bv_values[0],
+ col_b->bv_values[0]);
+ if (!attr->attbyval)
+ pfree(DatumGetPointer(col_a->bv_values[0]));
+ col_a->bv_values[0] = result;
+
+ PG_RETURN_VOID();
+}
+
+/*
+ * Get inclusion opclass support procedure
+ *
+ * Return the procedure corresponding to the given function support number
+ * or null if it is not exists.
+ */
+static FmgrInfo *
+inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno, uint16 procnum)
+{
+ InclusionOpaque *opaque;
+ uint16 basenum = procnum - PROCNUM_BASE;
+
+ opaque = (InclusionOpaque *) bdesc->bd_info[attno - 1]->oi_opaque;
+
+ /*
+ * We cache these in the opaque struct, to avoid repetitive syscache
+ * lookups.
+ */
+ if (!opaque->inited[basenum])
+ {
+ if (RegProcedureIsValid(index_getprocid(bdesc->bd_index, attno,
+ procnum)))
+ {
+ fmgr_info_copy(&opaque->procinfos[basenum],
+ index_getprocinfo(bdesc->bd_index, attno, procnum),
+ bdesc->bd_context);
+
+ opaque->exists[basenum] = true;
+ }
+
+ opaque->inited[basenum] = true;
+ }
+
+ if (opaque->exists[basenum])
+ return &opaque->procinfos[basenum];
+ else
+ return NULL;
+}
+
+/*
+ * Get the procedure of the given strategy
+ *
+ * Return the procedure corresponding to the given sub-type and strategy
+ * number. The data type of the index will be used as the left hand side
+ * of the operator and the given sub-type will be used as the right hand side.
+ * Throws an error, if the pg_amop row is not exists, but it should not happen
+ * on a properly configured opclass.
+ *
+ * It always throws an error when the data type of the opclass is different
+ * from the data type of the column or the expression. It happens when
+ * the column data type has implicit cast to the opclass data type. We don't
+ * bother casting types, because this situation can easily be avoided by
+ * setting storage data type to the opclass. Same problem does not apply
+ * to the data type of the right hand side, because the type from ScanKey
+ * is always the one which fits the opclass.
+ */
+FmgrInfo *
+inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno, Oid subtype,
+ uint16 strategynum)
+{
+ InclusionOpaque *opaque;
+ uint16 basenum = strategynum - 1,
+ i;
+
+ opaque = (InclusionOpaque *) bdesc->bd_info[attno - 1]->oi_opaque;
+
+ /*
+ * We cache the procedures for the last sub-type in the opaque struct,
+ * to avoid repetitive syscache lookups. If the sub-type is changed,
+ * we cannot use any of them anymore.
+ */
+ if (opaque->last_subtype != subtype && opaque->strategy_inited)
+ for (i = 0; i < RTMaxStrategyNumber; i++)
+ opaque->strategy_inited[i] = false;
+
+ if (!opaque->strategy_inited[basenum])
+ {
+ HeapTuple tuple;
+ Datum oprDatum;
+ Oid opfamily;
+ Form_pg_attribute attr;
+ bool isNull;
+
+ opfamily = bdesc->bd_index->rd_opfamily[attno - 1];
+ attr = bdesc->bd_tupdesc->attrs[attno - 1];
+ tuple = SearchSysCache4(AMOPSTRATEGY, ObjectIdGetDatum(opfamily),
+ ObjectIdGetDatum(attr->atttypid),
+ ObjectIdGetDatum(subtype),
+ Int16GetDatum(strategynum));
+
+ if (!HeapTupleIsValid(tuple))
+ elog(ERROR, "missing strategy %d for attribute %d of index \"%s\"",
+ strategynum, attno, RelationGetRelationName(bdesc->bd_index));
+
+ oprDatum = SysCacheGetAttr(AMOPSTRATEGY, tuple,
+ Anum_pg_amop_amopopr, &isNull);
+ ReleaseSysCache(tuple);
+
+ Assert(!isNull && RegProcedureIsValid(DatumGetObjectId(oprDatum)));
+
+ fmgr_info_cxt(get_opcode(DatumGetObjectId(oprDatum)),
+ &opaque->strategy_procinfos[basenum],
+ bdesc->bd_context);
+ opaque->strategy_inited[basenum] = true;
+ }
+
+ return &opaque->strategy_procinfos[basenum];
+}
diff --git a/src/include/access/brin_internal.h b/src/include/access/brin_internal.h
index 84eed61..9dca259 100644
--- a/src/include/access/brin_internal.h
+++ b/src/include/access/brin_internal.h
@@ -84,11 +84,17 @@ typedef struct BrinDesc
extern BrinDesc *brin_build_desc(Relation rel);
extern void brin_free_desc(BrinDesc *bdesc);
extern Datum brin_summarize_new_values(PG_FUNCTION_ARGS);
/* brin_minmax.c */
extern Datum brin_minmax_opcinfo(PG_FUNCTION_ARGS);
extern Datum brin_minmax_add_value(PG_FUNCTION_ARGS);
extern Datum brin_minmax_consistent(PG_FUNCTION_ARGS);
extern Datum brin_minmax_union(PG_FUNCTION_ARGS);
+/* brin_inclusion.c */
+extern Datum brin_inclusion_opcinfo(PG_FUNCTION_ARGS);
+extern Datum brin_inclusion_add_value(PG_FUNCTION_ARGS);
+extern Datum brin_inclusion_consistent(PG_FUNCTION_ARGS);
+extern Datum brin_inclusion_union(PG_FUNCTION_ARGS);
+
#endif /* BRIN_INTERNAL_H */
diff --git a/src/include/catalog/pg_am.h b/src/include/catalog/pg_am.h
index 79609f7..8a28b8e 100644
--- a/src/include/catalog/pg_am.h
+++ b/src/include/catalog/pg_am.h
@@ -125,14 +125,15 @@ DESCR("hash index access method");
#define HASH_AM_OID 405
DATA(insert OID = 783 ( gist 0 9 f t f f t t f t t t f 0 gistinsert gistbeginscan gistgettuple gistgetbitmap gistrescan gistendscan gistmarkpos gistrestrpos gistbuild gistbuildempty gistbulkdelete gistvacuumcleanup gistcanreturn gistcostestimate gistoptions ));
DESCR("GiST index access method");
#define GIST_AM_OID 783
DATA(insert OID = 2742 ( gin 0 6 f f f f t t f f t f f 0 gininsert ginbeginscan - gingetbitmap ginrescan ginendscan ginmarkpos ginrestrpos ginbuild ginbuildempty ginbulkdelete ginvacuumcleanup - gincostestimate ginoptions ));
DESCR("GIN index access method");
#define GIN_AM_OID 2742
DATA(insert OID = 4000 ( spgist 0 5 f f f f f t f t f f f 0 spginsert spgbeginscan spggettuple spggetbitmap spgrescan spgendscan spgmarkpos spgrestrpos spgbuild spgbuildempty spgbulkdelete spgvacuumcleanup spgcanreturn spgcostestimate spgoptions ));
DESCR("SP-GiST index access method");
#define SPGIST_AM_OID 4000
-DATA(insert OID = 3580 ( brin 5 14 f f f f t t f t t f f 0 brininsert brinbeginscan - bringetbitmap brinrescan brinendscan brinmarkpos brinrestrpos brinbuild brinbuildempty brinbulkdelete brinvacuumcleanup - brincostestimate brinoptions ));
+DATA(insert OID = 3580 ( brin 0 15 f f f f t t f t t f f 0 brininsert brinbeginscan - bringetbitmap brinrescan brinendscan brinmarkpos brinrestrpos brinbuild brinbuildempty brinbulkdelete brinvacuumcleanup - brincostestimate brinoptions ));
+DESCR("block range index (BRIN) access method");
#define BRIN_AM_OID 3580
#endif /* PG_AM_H */
diff --git a/src/include/catalog/pg_amop.h b/src/include/catalog/pg_amop.h
index 5aab896..413198f 100644
--- a/src/include/catalog/pg_amop.h
+++ b/src/include/catalog/pg_amop.h
@@ -968,20 +968,27 @@ DATA(insert ( 4074 829 829 1 s 1222 3580 0 ));
DATA(insert ( 4074 829 829 2 s 1223 3580 0 ));
DATA(insert ( 4074 829 829 3 s 1220 3580 0 ));
DATA(insert ( 4074 829 829 4 s 1225 3580 0 ));
DATA(insert ( 4074 829 829 5 s 1224 3580 0 ));
/* minmax inet */
DATA(insert ( 4075 869 869 1 s 1203 3580 0 ));
DATA(insert ( 4075 869 869 2 s 1204 3580 0 ));
DATA(insert ( 4075 869 869 3 s 1201 3580 0 ));
DATA(insert ( 4075 869 869 4 s 1206 3580 0 ));
DATA(insert ( 4075 869 869 5 s 1205 3580 0 ));
+/* inclusion inet */
+DATA(insert ( 3589 869 869 3 s 3552 3580 0 ));
+DATA(insert ( 3589 869 869 7 s 934 3580 0 ));
+DATA(insert ( 3589 869 869 8 s 932 3580 0 ));
+DATA(insert ( 3589 869 869 18 s 1201 3580 0 ));
+DATA(insert ( 3589 869 869 24 s 933 3580 0 ));
+DATA(insert ( 3589 869 869 26 s 931 3580 0 ));
/* minmax character */
DATA(insert ( 4076 1042 1042 1 s 1058 3580 0 ));
DATA(insert ( 4076 1042 1042 2 s 1059 3580 0 ));
DATA(insert ( 4076 1042 1042 3 s 1054 3580 0 ));
DATA(insert ( 4076 1042 1042 4 s 1061 3580 0 ));
DATA(insert ( 4076 1042 1042 5 s 1060 3580 0 ));
/* minmax time without time zone */
DATA(insert ( 4077 1083 1083 1 s 1110 3580 0 ));
DATA(insert ( 4077 1083 1083 2 s 1111 3580 0 ));
DATA(insert ( 4077 1083 1083 3 s 1108 3580 0 ));
@@ -1063,18 +1070,66 @@ DATA(insert ( 4055 1700 1700 1 s 1754 3580 0 ));
DATA(insert ( 4055 1700 1700 2 s 1755 3580 0 ));
DATA(insert ( 4055 1700 1700 3 s 1752 3580 0 ));
DATA(insert ( 4055 1700 1700 4 s 1757 3580 0 ));
DATA(insert ( 4055 1700 1700 5 s 1756 3580 0 ));
/* minmax uuid */
DATA(insert ( 4081 2950 2950 1 s 2974 3580 0 ));
DATA(insert ( 4081 2950 2950 2 s 2976 3580 0 ));
DATA(insert ( 4081 2950 2950 3 s 2972 3580 0 ));
DATA(insert ( 4081 2950 2950 4 s 2977 3580 0 ));
DATA(insert ( 4081 2950 2950 5 s 2975 3580 0 ));
+/* inclusion range types */
+DATA(insert ( 3590 3831 3831 1 s 3893 3580 0 ));
+DATA(insert ( 3590 3831 3831 2 s 3895 3580 0 ));
+DATA(insert ( 3590 3831 3831 3 s 3888 3580 0 ));
+DATA(insert ( 3590 3831 3831 4 s 3896 3580 0 ));
+DATA(insert ( 3590 3831 3831 5 s 3894 3580 0 ));
+DATA(insert ( 3590 3831 3831 7 s 3890 3580 0 ));
+DATA(insert ( 3590 3831 3831 8 s 3892 3580 0 ));
+DATA(insert ( 3590 3831 2283 16 s 3889 3580 0 ));
+DATA(insert ( 3590 3831 3831 17 s 3897 3580 0 ));
+DATA(insert ( 3590 3831 3831 18 s 3882 3580 0 ));
+DATA(insert ( 3590 3831 3831 20 s 3884 3580 0 ));
+DATA(insert ( 3590 3831 3831 21 s 3885 3580 0 ));
+DATA(insert ( 3590 3831 3831 22 s 3887 3580 0 ));
+DATA(insert ( 3590 3831 3831 23 s 3886 3580 0 ));
/* minmax pg_lsn */
DATA(insert ( 4082 3220 3220 1 s 3224 3580 0 ));
DATA(insert ( 4082 3220 3220 2 s 3226 3580 0 ));
DATA(insert ( 4082 3220 3220 3 s 3222 3580 0 ));
DATA(insert ( 4082 3220 3220 4 s 3227 3580 0 ));
DATA(insert ( 4082 3220 3220 5 s 3225 3580 0 ));
+/* inclusion box */
+DATA(insert ( 3591 603 603 1 s 493 3580 0 ));
+DATA(insert ( 3591 603 603 2 s 494 3580 0 ));
+DATA(insert ( 3591 603 603 3 s 500 3580 0 ));
+DATA(insert ( 3591 603 603 4 s 495 3580 0 ));
+DATA(insert ( 3591 603 603 5 s 496 3580 0 ));
+DATA(insert ( 3591 603 603 6 s 499 3580 0 ));
+DATA(insert ( 3591 603 603 7 s 498 3580 0 ));
+DATA(insert ( 3591 603 603 8 s 497 3580 0 ));
+DATA(insert ( 3591 603 603 9 s 2571 3580 0 ));
+DATA(insert ( 3591 603 603 10 s 2570 3580 0 ));
+DATA(insert ( 3591 603 603 11 s 2573 3580 0 ));
+DATA(insert ( 3591 603 603 12 s 2572 3580 0 ));
+DATA(insert ( 3591 603 603 13 s 2863 3580 0 ));
+DATA(insert ( 3591 603 603 14 s 2862 3580 0 ));
+DATA(insert ( 3591 603 600 1 s 4092 3580 0 ));
+DATA(insert ( 3591 603 600 2 s 4093 3580 0 ));
+DATA(insert ( 3591 603 600 3 s 4100 3580 0 ));
+DATA(insert ( 3591 603 600 4 s 4095 3580 0 ));
+DATA(insert ( 3591 603 600 5 s 4094 3580 0 ));
+DATA(insert ( 3591 603 600 7 s 433 3580 0 ));
+DATA(insert ( 3591 603 600 9 s 4097 3580 0 ));
+DATA(insert ( 3591 603 600 10 s 4096 3580 0 ));
+DATA(insert ( 3591 603 600 11 s 4098 3580 0 ));
+DATA(insert ( 3591 603 600 12 s 4099 3580 0 ));
+/* inclusion point */
+DATA(insert ( 3591 600 600 1 s 507 3580 0 ));
+DATA(insert ( 3591 600 600 5 s 508 3580 0 ));
+DATA(insert ( 3591 600 600 6 s 510 3580 0 ));
+DATA(insert ( 3591 600 600 10 s 509 3580 0 ));
+DATA(insert ( 3591 600 600 11 s 506 3580 0 ));
+DATA(insert ( 3591 600 603 3 s 4101 3580 0 ));
+DATA(insert ( 3591 600 603 8 s 511 3580 0 ));
#endif /* PG_AMOP_H */
diff --git a/src/include/catalog/pg_amproc.h b/src/include/catalog/pg_amproc.h
index a54d11f..0fdc3cd 100644
--- a/src/include/catalog/pg_amproc.h
+++ b/src/include/catalog/pg_amproc.h
@@ -634,20 +634,28 @@ DATA(insert ( 4074 829 829 13 834 ));
DATA(insert ( 4074 829 829 14 833 ));
/* minmax inet */
DATA(insert ( 4075 869 869 1 3383 ));
DATA(insert ( 4075 869 869 2 3384 ));
DATA(insert ( 4075 869 869 3 3385 ));
DATA(insert ( 4075 869 869 4 3386 ));
DATA(insert ( 4075 869 869 11 921 ));
DATA(insert ( 4075 869 869 12 922 ));
DATA(insert ( 4075 869 869 13 924 ));
DATA(insert ( 4075 869 869 14 923 ));
+/* inclusion inet */
+DATA(insert ( 3589 869 869 1 3585 ));
+DATA(insert ( 3589 869 869 2 3586 ));
+DATA(insert ( 3589 869 869 3 3587 ));
+DATA(insert ( 3589 869 869 4 3588 ));
+DATA(insert ( 3589 869 869 11 3582 ));
+DATA(insert ( 3589 869 869 12 4071 ));
+DATA(insert ( 3589 869 869 14 930 ));
/* minmax character */
DATA(insert ( 4076 1042 1042 1 3383 ));
DATA(insert ( 4076 1042 1042 2 3384 ));
DATA(insert ( 4076 1042 1042 3 3385 ));
DATA(insert ( 4076 1042 1042 4 3386 ));
DATA(insert ( 4076 1042 1042 11 1049 ));
DATA(insert ( 4076 1042 1042 12 1050 ));
DATA(insert ( 4076 1042 1042 13 1052 ));
DATA(insert ( 4076 1042 1042 14 1051 ));
/* minmax time without time zone */
@@ -782,21 +790,44 @@ DATA(insert ( 4055 1700 1700 13 1721 ));
DATA(insert ( 4055 1700 1700 14 1720 ));
/* minmax uuid */
DATA(insert ( 4081 2950 2950 1 3383 ));
DATA(insert ( 4081 2950 2950 2 3384 ));
DATA(insert ( 4081 2950 2950 3 3385 ));
DATA(insert ( 4081 2950 2950 4 3386 ));
DATA(insert ( 4081 2950 2950 11 2954 ));
DATA(insert ( 4081 2950 2950 12 2955 ));
DATA(insert ( 4081 2950 2950 13 2957 ));
DATA(insert ( 4081 2950 2950 14 2958 ));
+/* inclusion range types */
+DATA(insert ( 3590 3831 3831 1 3585 ));
+DATA(insert ( 3590 3831 3831 2 3586 ));
+DATA(insert ( 3590 3831 3831 3 3587 ));
+DATA(insert ( 3590 3831 3831 4 3588 ));
+DATA(insert ( 3590 3831 3831 11 4057 ));
+DATA(insert ( 3590 3831 3831 14 3859 ));
+DATA(insert ( 3590 3831 3831 15 3850 ));
/* minmax pg_lsn */
DATA(insert ( 4082 3220 3220 1 3383 ));
DATA(insert ( 4082 3220 3220 2 3384 ));
DATA(insert ( 4082 3220 3220 3 3385 ));
DATA(insert ( 4082 3220 3220 4 3386 ));
DATA(insert ( 4082 3220 3220 11 3231 ));
DATA(insert ( 4082 3220 3220 12 3232 ));
DATA(insert ( 4082 3220 3220 13 3234 ));
DATA(insert ( 4082 3220 3220 14 3235 ));
+/* inclusion box */
+DATA(insert ( 3591 603 603 1 3585 ));
+DATA(insert ( 3591 603 603 2 3586 ));
+DATA(insert ( 3591 603 603 3 3587 ));
+DATA(insert ( 3591 603 603 4 3588 ));
+DATA(insert ( 3591 603 603 11 4067 ));
+DATA(insert ( 3591 603 603 14 187 ));
+/* inclusion point */
+DATA(insert ( 3591 600 600 1 3585 ));
+DATA(insert ( 3591 600 600 2 3586 ));
+DATA(insert ( 3591 600 600 3 3587 ));
+DATA(insert ( 3591 600 600 4 3588 ));
+DATA(insert ( 3591 600 600 11 4067 ));
+DATA(insert ( 3591 600 600 13 4091 ));
+DATA(insert ( 3591 600 600 14 193 ));
#endif /* PG_AMPROC_H */
diff --git a/src/include/catalog/pg_opclass.h b/src/include/catalog/pg_opclass.h
index b3acef6..d5ecc3b 100644
--- a/src/include/catalog/pg_opclass.h
+++ b/src/include/catalog/pg_opclass.h
@@ -246,26 +246,31 @@ DATA(insert ( 3580 int2_minmax_ops PGNSP PGUID 4054 21 t 0 ));
DATA(insert ( 3580 int4_minmax_ops PGNSP PGUID 4054 23 t 0 ));
DATA(insert ( 3580 text_minmax_ops PGNSP PGUID 4056 25 t 0 ));
DATA(insert ( 3580 oid_minmax_ops PGNSP PGUID 4068 26 t 0 ));
DATA(insert ( 3580 tid_minmax_ops PGNSP PGUID 4069 27 t 0 ));
DATA(insert ( 3580 float4_minmax_ops PGNSP PGUID 4070 700 t 0 ));
DATA(insert ( 3580 float8_minmax_ops PGNSP PGUID 4070 701 t 0 ));
DATA(insert ( 3580 abstime_minmax_ops PGNSP PGUID 4072 702 t 0 ));
DATA(insert ( 3580 reltime_minmax_ops PGNSP PGUID 4073 703 t 0 ));
DATA(insert ( 3580 macaddr_minmax_ops PGNSP PGUID 4074 829 t 0 ));
DATA(insert ( 3580 inet_minmax_ops PGNSP PGUID 4075 869 f 0 ));
+DATA(insert ( 3580 inet_inclusion_ops PGNSP PGUID 3589 869 t 869 ));
DATA(insert ( 3580 bpchar_minmax_ops PGNSP PGUID 4076 1042 t 0 ));
DATA(insert ( 3580 time_minmax_ops PGNSP PGUID 4077 1083 t 0 ));
DATA(insert ( 3580 date_minmax_ops PGNSP PGUID 4059 1082 t 0 ));
DATA(insert ( 3580 timestamp_minmax_ops PGNSP PGUID 4059 1114 t 0 ));
DATA(insert ( 3580 timestamptz_minmax_ops PGNSP PGUID 4059 1184 t 0 ));
DATA(insert ( 3580 interval_minmax_ops PGNSP PGUID 4078 1186 t 0 ));
DATA(insert ( 3580 timetz_minmax_ops PGNSP PGUID 4058 1266 t 0 ));
DATA(insert ( 3580 bit_minmax_ops PGNSP PGUID 4079 1560 t 0 ));
DATA(insert ( 3580 varbit_minmax_ops PGNSP PGUID 4080 1562 t 0 ));
DATA(insert ( 3580 numeric_minmax_ops PGNSP PGUID 4055 1700 t 0 ));
/* no brin opclass for record, anyarray */
DATA(insert ( 3580 uuid_minmax_ops PGNSP PGUID 4081 2950 t 0 ));
+DATA(insert ( 3580 range_inclusion_ops PGNSP PGUID 3590 3831 t 3831 ));
DATA(insert ( 3580 pg_lsn_minmax_ops PGNSP PGUID 4082 3220 t 0 ));
-/* no brin opclass for enum, tsvector, tsquery, jsonb, range */
+/* no brin opclass for enum, tsvector, tsquery, jsonb */
+DATA(insert ( 3580 box_inclusion_ops PGNSP PGUID 3591 603 t 603 ));
+DATA(insert ( 3580 point_box_inclusion_ops PGNSP PGUID 3591 600 t 603 ));
+/* no brin opclass for the geometric types except box and point*/
#endif /* PG_OPCLASS_H */
diff --git a/src/include/catalog/pg_opfamily.h b/src/include/catalog/pg_opfamily.h
index 97ffa32..cbba2dc 100644
--- a/src/include/catalog/pg_opfamily.h
+++ b/src/include/catalog/pg_opfamily.h
@@ -165,19 +165,22 @@ DATA(insert OID = 4059 ( 3580 datetime_minmax_ops PGNSP PGUID ));
DATA(insert OID = 4062 ( 3580 char_minmax_ops PGNSP PGUID ));
DATA(insert OID = 4064 ( 3580 bytea_minmax_ops PGNSP PGUID ));
DATA(insert OID = 4065 ( 3580 name_minmax_ops PGNSP PGUID ));
DATA(insert OID = 4068 ( 3580 oid_minmax_ops PGNSP PGUID ));
DATA(insert OID = 4069 ( 3580 tid_minmax_ops PGNSP PGUID ));
DATA(insert OID = 4070 ( 3580 float_minmax_ops PGNSP PGUID ));
DATA(insert OID = 4072 ( 3580 abstime_minmax_ops PGNSP PGUID ));
DATA(insert OID = 4073 ( 3580 reltime_minmax_ops PGNSP PGUID ));
DATA(insert OID = 4074 ( 3580 macaddr_minmax_ops PGNSP PGUID ));
DATA(insert OID = 4075 ( 3580 network_minmax_ops PGNSP PGUID ));
+DATA(insert OID = 3589 ( 3580 network_inclusion_ops PGNSP PGUID ));
DATA(insert OID = 4076 ( 3580 bpchar_minmax_ops PGNSP PGUID ));
DATA(insert OID = 4077 ( 3580 time_minmax_ops PGNSP PGUID ));
DATA(insert OID = 4078 ( 3580 interval_minmax_ops PGNSP PGUID ));
DATA(insert OID = 4079 ( 3580 bit_minmax_ops PGNSP PGUID ));
DATA(insert OID = 4080 ( 3580 varbit_minmax_ops PGNSP PGUID ));
DATA(insert OID = 4081 ( 3580 uuid_minmax_ops PGNSP PGUID ));
+DATA(insert OID = 3590 ( 3580 range_inclusion_ops PGNSP PGUID ));
DATA(insert OID = 4082 ( 3580 pg_lsn_minmax_ops PGNSP PGUID ));
+DATA(insert OID = 3591 ( 3580 box_inclusion_ops PGNSP PGUID ));
#endif /* PG_OPFAMILY_H */
diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h
index 55d165b..7d09dc5 100644
--- a/src/include/catalog/pg_proc.h
+++ b/src/include/catalog/pg_proc.h
@@ -4186,20 +4186,30 @@ DATA(insert OID = 2749 ( arraycontained PGNSP PGUID 12 1 0 0 0 f f f f t f i
/* BRIN minmax */
DATA(insert OID = 3383 ( brin_minmax_opcinfo PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 2281 "2281" _null_ _null_ _null_ _null_ brin_minmax_opcinfo _null_ _null_ _null_ ));
DESCR("BRIN minmax support");
DATA(insert OID = 3384 ( brin_minmax_add_value PGNSP PGUID 12 1 0 0 0 f f f f t f i 4 0 16 "2281 2281 2281 2281" _null_ _null_ _null_ _null_ brin_minmax_add_value _null_ _null_ _null_ ));
DESCR("BRIN minmax support");
DATA(insert OID = 3385 ( brin_minmax_consistent PGNSP PGUID 12 1 0 0 0 f f f f t f i 3 0 16 "2281 2281 2281" _null_ _null_ _null_ _null_ brin_minmax_consistent _null_ _null_ _null_ ));
DESCR("BRIN minmax support");
DATA(insert OID = 3386 ( brin_minmax_union PGNSP PGUID 12 1 0 0 0 f f f f t f i 3 0 16 "2281 2281 2281" _null_ _null_ _null_ _null_ brin_minmax_union _null_ _null_ _null_ ));
DESCR("BRIN minmax support");
+/* BRIN inclusion */
+DATA(insert OID = 3585 ( brin_inclusion_opcinfo PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 2281 "2281" _null_ _null_ _null_ _null_ brin_inclusion_opcinfo _null_ _null_ _null_ ));
+DESCR("BRIN inclusion support");
+DATA(insert OID = 3586 ( brin_inclusion_add_value PGNSP PGUID 12 1 0 0 0 f f f f t f i 4 0 16 "2281 2281 2281 2281" _null_ _null_ _null_ _null_ brin_inclusion_add_value _null_ _null_ _null_ ));
+DESCR("BRIN inclusion support");
+DATA(insert OID = 3587 ( brin_inclusion_consistent PGNSP PGUID 12 1 0 0 0 f f f f t f i 3 0 16 "2281 2281 2281" _null_ _null_ _null_ _null_ brin_inclusion_consistent _null_ _null_ _null_ ));
+DESCR("BRIN inclusion support");
+DATA(insert OID = 3588 ( brin_inclusion_union PGNSP PGUID 12 1 0 0 0 f f f f t f i 3 0 16 "2281 2281 2281" _null_ _null_ _null_ _null_ brin_inclusion_union _null_ _null_ _null_ ));
+DESCR("BRIN inclusion support");
+
/* userlock replacements */
DATA(insert OID = 2880 ( pg_advisory_lock PGNSP PGUID 12 1 0 0 0 f f f f t f v 1 0 2278 "20" _null_ _null_ _null_ _null_ pg_advisory_lock_int8 _null_ _null_ _null_ ));
DESCR("obtain exclusive advisory lock");
DATA(insert OID = 3089 ( pg_advisory_xact_lock PGNSP PGUID 12 1 0 0 0 f f f f t f v 1 0 2278 "20" _null_ _null_ _null_ _null_ pg_advisory_xact_lock_int8 _null_ _null_ _null_ ));
DESCR("obtain exclusive advisory lock");
DATA(insert OID = 2881 ( pg_advisory_lock_shared PGNSP PGUID 12 1 0 0 0 f f f f t f v 1 0 2278 "20" _null_ _null_ _null_ _null_ pg_advisory_lock_shared_int8 _null_ _null_ _null_ ));
DESCR("obtain shared advisory lock");
DATA(insert OID = 3090 ( pg_advisory_xact_lock_shared PGNSP PGUID 12 1 0 0 0 f f f f t f v 1 0 2278 "20" _null_ _null_ _null_ _null_ pg_advisory_xact_lock_shared_int8 _null_ _null_ _null_ ));
DESCR("obtain shared advisory lock");
DATA(insert OID = 2882 ( pg_try_advisory_lock PGNSP PGUID 12 1 0 0 0 f f f f t f v 1 0 16 "20" _null_ _null_ _null_ _null_ pg_try_advisory_lock_int8 _null_ _null_ _null_ ));
diff --git a/src/test/regress/expected/brin.out b/src/test/regress/expected/brin.out
index f47f366..e174378 100644
--- a/src/test/regress/expected/brin.out
+++ b/src/test/regress/expected/brin.out
@@ -15,143 +15,172 @@ CREATE TABLE brintest (byteacol bytea,
datecol date,
timecol time without time zone,
timestampcol timestamp without time zone,
timestamptzcol timestamp with time zone,
intervalcol interval,
timetzcol time with time zone,
bitcol bit(10),
varbitcol bit varying(16),
numericcol numeric,
uuidcol uuid,
- lsncol pg_lsn
+ int4rangecol int4range,
+ lsncol pg_lsn,
+ boxcol box,
+ pointcol point
) WITH (fillfactor=10);
INSERT INTO brintest SELECT
- repeat(stringu1, 42)::bytea,
+ repeat(stringu1, 8)::bytea,
substr(stringu1, 1, 1)::"char",
stringu1::name, 142857 * tenthous,
thousand,
twothousand,
- repeat(stringu1, 42),
+ repeat(stringu1, 8),
unique1::oid,
format('(%s,%s)', tenthous, twenty)::tid,
(four + 1.0)/(hundred+1),
odd::float8 / (tenthous + 1),
format('%s:00:%s:00:%s:00', to_hex(odd), to_hex(even), to_hex(hundred))::macaddr,
- inet '10.2.3.4' + tenthous,
+ inet '10.2.3.4/24' + tenthous,
substr(stringu1, 1, 1)::bpchar,
date '1995-08-15' + tenthous,
time '01:20:30' + thousand * interval '18.5 second',
timestamp '1942-07-23 03:05:09' + tenthous * interval '36.38 hours',
timestamptz '1972-10-10 03:00' + thousand * interval '1 hour',
justify_days(justify_hours(tenthous * interval '12 minutes')),
- timetz '01:30:20' + hundred * interval '15 seconds',
+ timetz '01:30:20+02' + hundred * interval '15 seconds',
thousand::bit(10),
tenthous::bit(16)::varbit,
tenthous::numeric(36,30) * fivethous * even / (hundred + 1),
format('%s%s-%s-%s-%s-%s%s%s', to_char(tenthous, 'FM0000'), to_char(tenthous, 'FM0000'), to_char(tenthous, 'FM0000'), to_char(tenthous, 'FM0000'), to_char(tenthous, 'FM0000'), to_char(tenthous, 'FM0000'), to_char(tenthous, 'FM0000'), to_char(tenthous, 'FM0000'))::uuid,
- format('%s/%s%s', odd, even, tenthous)::pg_lsn
-FROM tenk1 LIMIT 5;
--- throw in some NULL-only tuples too
-INSERT INTO brintest SELECT NULL FROM tenk1 LIMIT 25;
+ int4range(thousand, twothousand),
+ format('%s/%s%s', odd, even, tenthous)::pg_lsn,
+ box(point(odd, even), point(thousand, twothousand)),
+ point(thousand, twothousand)
+FROM tenk1 LIMIT 25;
+-- throw in some NULL's and different values
+INSERT INTO brintest (inetcol, int4rangecol) SELECT
+ inet 'fe80::6e40:8ff:fea9:8c46' + tenthous,
+ 'empty'::int4range
+FROM tenk1 LIMIT 25;
CREATE INDEX brinidx ON brintest USING brin (
byteacol,
charcol,
namecol,
int8col,
int2col,
int4col,
textcol,
oidcol,
tidcol,
float4col,
float8col,
macaddrcol,
+ inetcol inet_inclusion_ops,
inetcol inet_minmax_ops,
bpcharcol,
datecol,
timecol,
timestampcol,
timestamptzcol,
intervalcol,
timetzcol,
bitcol,
varbitcol,
numericcol,
uuidcol,
- lsncol
+ int4rangecol,
+ lsncol,
+ boxcol,
+ pointcol
) with (pages_per_range = 1);
BEGIN;
-CREATE TABLE brinopers (colname name, op text[], value text[],
+CREATE TABLE brinopers (colname name, typ regtype, op text[], value text[],
check (cardinality(op) = cardinality(value)));
-INSERT INTO brinopers VALUES ('byteacol', '{>, >=, =, <=, <}', '{ZZAAAA, ZZAAAA, AAAAAA, AAAAAA, AAAAAA}');
-INSERT INTO brinopers VALUES ('charcol', '{>, >=, =, <=, <}', '{Z, Z, A, A, A}');
-INSERT INTO brinopers VALUES ('namecol', '{>, >=, =, <=, <}', '{ZZAAAA, ZZAAAA, AAAAAA, AAAAAA, AAAAAA}');
-INSERT INTO brinopers VALUES ('int8col', '{>, >=, =, <=, <}', '{1428427143, 1428427143, 0, 0, 0}');
-INSERT INTO brinopers VALUES ('int2col', '{>, >=, =, <=, <}', '{999, 999, 0, 0, 0}');
-INSERT INTO brinopers VALUES ('int4col', '{>, >=, =, <=, <}', '{1999, 1999, 0, 0, 0}');
-INSERT INTO brinopers VALUES ('textcol', '{>, >=, =, <=, <}', '{ZZAAAA, ZZAAAA, AAAAA, AAAAA, AAAAA}');
-INSERT INTO brinopers VALUES ('oidcol', '{>, >=, =, <=, <}', '{9999, 9999, 0, 0, 0}');
-INSERT INTO brinopers VALUES ('tidcol', '{>, >=, =, <=, <}', '{"(9999,19)", "(9999,19)", "(0,0)", "(0,0)", "(0,0)"}');
-INSERT INTO brinopers VALUES ('float4col', '{>, >=, =, <=, <}', '{1, 1, 0.0103093, 0.0103093, 0.0103093}');
-INSERT INTO brinopers VALUES ('float8col', '{>, >=, =, <=, <}', '{1.98, 1.98, 0, 0, 0}');
-INSERT INTO brinopers VALUES ('inetcol', '{>, >=, =, <=, <}', '{10.2.42.19, 10.2.42.19, 10.2.3.4, 10.2.3.4, 10.2.3.4}');
-INSERT INTO brinopers VALUES ('bpcharcol', '{>, >=, =, <=, <}', '{Z, Z, A, A, A}');
-INSERT INTO brinopers VALUES ('datecol', '{>, >=, =, <=, <}', '{2022-12-30, 2022-12-30, 1995-08-15, 1995-08-15, 1995-08-15}');
-INSERT INTO brinopers VALUES ('timecol', '{>, >=, =, <=, <}', '{06:28:31.5, 06:28:31.5, 01:20:30, 01:20:30, 01:20:30}');
-INSERT INTO brinopers VALUES ('timestampcol', '{>, >=, =, <=, <}', '{1984-01-20 22:42:21, 1984-01-20 22:42:21, 1942-07-23 03:05:09, 1942-07-23 03:05:09, 1942-07-23 03:05:09}');
-INSERT INTO brinopers VALUES ('timestamptzcol', '{>, >=, =, <=, <}', '{1972-11-20 19:00:00-03, 1972-11-20 19:00:00-03, 1972-10-10 03:00:00-04, 1972-10-10 03:00:00-04, 1972-10-10 03:00:00-04}');
-INSERT INTO brinopers VALUES ('intervalcol', '{>, >=, =, <=, <}', '{2 mons 23 days 07:48:00, 2 mons 23 days 07:48:00, 00:00:00, 00:00:00, 00:00:00}');
-INSERT INTO brinopers VALUES ('timetzcol', '{>, >=, =, <=, <}', '{01:55:05-03, 01:55:05-03, 01:30:20-03, 01:30:20-03, 01:30:20-03}');
-INSERT INTO brinopers VALUES ('numericcol', '{>, >=, =, <=, <}', '{99470151.9, 99470151.9, 0.00, 0.01, 0.01}');
-INSERT INTO brinopers VALUES ('macaddrcol', '{>, >=, =, <=, <}', '{ff:fe:00:00:00:00, ff:fe:00:00:00:00, 00:00:01:00:00:00, 00:00:01:00:00:00, 00:00:01:00:00:00}');
-INSERT INTO brinopers VALUES ('bitcol', '{>, >=, =, <=, <}', '{1111111000, 1111111000, 0000000010, 0000000010, 0000000010}');
-INSERT INTO brinopers VALUES ('varbitcol', '{>, >=, =, <=, <}', '{1111111111111000, 1111111111111000, 0000000000000100, 0000000000000100, 0000000000000100}');
-INSERT INTO brinopers VALUES ('uuidcol', '{>, >=, =, <=, <}', '{99989998-9998-9998-9998-999899989998, 99989998-9998-9998-9998-999899989998, 00040004-0004-0004-0004-000400040004, 00040004-0004-0004-0004-000400040004, 00040004-0004-0004-0004-000400040005}');
-INSERT INTO brinopers VALUES ('lsncol', '{>, >=, =, <=, <, IS, IS NOT}', '{198/1999799, 198/1999799, 30/312815, 0/1200, 0/1200, NULL, NULL}');
+INSERT INTO brinopers VALUES
+ ('byteacol', NULL, '{>, >=, =, <=, <}', '{AAAAAA, AAAAAA, BNAAAABNAAAABNAAAABNAAAABNAAAABNAAAABNAAAABNAAAA, ZZZZZZ, ZZZZZZ}'),
+ ('charcol', NULL, '{>, >=, =, <=, <}', '{A, A, M, Z, Z}'),
+ ('namecol', NULL, '{>, >=, =, <=, <}', '{AAAAAA, AAAAAA, MAAAAA, ZZAAAA, ZZAAAA}'),
+ ('int8col', NULL, '{>, >=, =, <=, <}', '{0, 0, 1257141600, 1428427143, 1428427143}'),
+ ('int2col', NULL, '{>, >=, =, <=, <}', '{0, 0, 800, 999, 999}'),
+ ('int4col', NULL, '{>, >=, =, <=, <}', '{0, 0, 800, 1999, 1999}'),
+ ('textcol', NULL, '{>, >=, =, <=, <}', '{AAAAAA, AAAAAA, BNAAAABNAAAABNAAAABNAAAABNAAAABNAAAABNAAAABNAAAA, ZZAAAA, ZZAAAA}'),
+ ('oidcol', NULL, '{>, >=, =, <=, <}', '{0, 0, 8800, 9999, 9999}'),
+ ('tidcol', NULL, '{>, >=, =, <=, <}', '{"(0,0)", "(0,0)", "(8800,0)", "(9999,19)", "(9999,19)"}'),
+ ('float4col', NULL, '{>, >=, =, <=, <}', '{0.0103093, 0.0103093, 1, 1, 1}'),
+ ('float8col', NULL, '{>, >=, =, <=, <}', '{0, 0, 0, 1.98, 1.98}'),
+ ('inetcol', NULL, '{&&, =, <, <=, >, >=, >>=, >>, <<=, <<}', '{10/8, 10.2.14.231/24, 255.255.255.255, 255.255.255.255, 0.0.0.0, 0.0.0.0, 10.2.14.231/24, 10.2.14.231/25, 10.2.14.231/8, 0/0}'),
+ ('inetcol', NULL, '{&&, >>=, <<=, =}', '{fe80::6e40:8ff:fea9:a673/32, fe80::6e40:8ff:fea9:8c46, fe80::6e40:8ff:fea9:a673/32, fe80::6e40:8ff:fea9:8c46}'),
+ ('inetcol', 'cidr', '{<<=}', '{0/0}'),
+ ('bpcharcol', NULL, '{>, >=, =, <=, <}', '{A, A, W, Z, Z}'),
+ ('datecol', NULL, '{>, >=, =, <=, <}', '{1995-08-15, 1995-08-15, 2009-12-01, 2022-12-30, 2022-12-30}'),
+ ('timecol', NULL, '{>, >=, =, <=, <}', '{01:20:30, 01:20:30, 02:28:57, 06:28:31.5, 06:28:31.5}'),
+ ('timestampcol', NULL, '{>, >=, =, <=, <}', '{1942-07-23 03:05:09, 1942-07-23 03:05:09, 1964-03-24 19:26:45, 1984-01-20 22:42:21, 1984-01-20 22:42:21}'),
+ ('timestamptzcol', NULL, '{>, >=, =, <=, <}', '{1972-10-10 03:00:00-04, 1972-10-10 03:00:00-04, 1972-10-19 09:00:00-07, 1972-11-20 19:00:00-03, 1972-11-20 19:00:00-03}'),
+ ('intervalcol', NULL, '{>, >=, =, <=, <}', '{00:00:00, 00:00:00, 1 mons 13 days 12:24, 2 mons 23 days 07:48:00, 1 year}'),
+ ('timetzcol', NULL, '{>, >=, =, <=, <}', '{01:30:20+02, 01:30:20+02, 01:35:50+02, 23:55:05+02, 23:55:05+02}'),
+ ('numericcol', NULL, '{>, >=, =, <=, <}', '{0.00, 0.01, 2268164.347826086956521739130434782609, 99470151.9, 99470151.9}'),
+ ('macaddrcol', NULL, '{>, >=, =, <=, <}', '{00:00:01:00:00:00, 00:00:01:00:00:00, 2c:00:2d:00:16:00, ff:fe:00:00:00:00, ff:fe:00:00:00:00}'),
+ ('bitcol', NULL, '{>, >=, =, <=, <}', '{0000000010, 0000000010, 0011011110, 1111111000, 1111111000}'),
+ ('varbitcol', NULL, '{>, >=, =, <=, <}', '{0000000000000100, 0000000000000100, 0001010001100110, 1111111111111000, 1111111111111000}'),
+ ('uuidcol', NULL, '{>, >=, =, <=, <}', '{00040004-0004-0004-0004-000400040004, 00040004-0004-0004-0004-000400040004, 52225222-5222-5222-5222-522252225222, 99989998-9998-9998-9998-999899989998, 99989998-9998-9998-9998-999899989998}'),
+ ('int4rangecol', NULL, '{<<, &<, &&, &>, >>, @>, <@, =, <, <=, >, >=}', '{"[10000,)","[10000,)","(,]","[3,4)","[36,44)","(1500,1501]","[3,4)","[222,1222)","[36,44)","[43,1043)","[367,4466)","[519,)"}'),
+ ('int4rangecol', NULL, '{@>, <@, =, <=, >, >=}', '{empty, empty, empty, empty, empty, empty}'),
+ ('int4rangecol', 'int4', '{@>}', '{1500}'),
+ ('lsncol', NULL, '{>, >=, =, <=, <, IS, IS NOT}', '{0/1200, 0/1200, 44/455222, 198/1999799, 198/1999799, NULL, NULL}'),
+ ('boxcol', NULL, '{<<, &<, &&, &>, >>, <<|, &<|, |&>, |>>, @>, <@, ~=}', '{"((1000,2000),(3000,4000))","((1,2),(3000,4000))","((1,2),(3000,4000))","((1,2),(3000,4000))","((1,2),(3,4))","((1000,2000),(3000,4000))","((1,2000),(3,4000))","((1000,2),(3000,4))","((1,2),(3,4))","((1,2),(300,400))","((1,2),(3000,4000))","((222,1222),(44,45))"}'),
+ ('boxcol', 'point', '{<<, &<, &&, &>, >>, <<|, &<|, |&>, |>>, @>}', '{"(1000,2000)","(3000,4000)","(500,43)","(1,2)","(3,4)","(3000,4000)","(3000,4000)","(1,2)","(1,2)","(500,43)"}'),
+ ('pointcol', NULL, '{<<, >>, <^, >^, ~=}', '{"(3000,4000)","(3,4)","(5000,15000)","(1,2)","(222,1222)"}'),
+ ('pointcol', 'box', '{<@, &&}', '{"((0,0),(5000,5000))","((0,0),(3000,4000))"}');
COMMIT;
DO $x$
DECLARE
r record;
- tabname text;
- tabname_ss text;
+ cond text;
count int;
- query text;
- plan text;
BEGIN
- FOR r IN SELECT row_number() OVER (), colname, oper, value[ordinality] FROM brinopers, unnest(op) WITH ORDINALITY AS oper LOOP
- tabname := format('qry_%s', r.row_number);
- tabname_ss := tabname || '_ss';
- query = format($y$INSERT INTO %s SELECT ctid FROM brintest WHERE %s %s %L $y$,
- tabname, r.colname, r.oper, r.value);
+ FOR r IN SELECT colname, oper, typ, value[ordinality] FROM brinopers, unnest(op) WITH ORDINALITY AS oper LOOP
+ -- prepare the condition
+ IF r.typ IS NULL THEN
+ cond := format('%I %s %L', r.colname, r.oper, r.value);
+ ELSE
+ cond := format('%I %s %L::%s', r.colname, r.oper, r.value, r.typ);
+ END IF;
+
-- run the query using the brin index
+ CREATE TEMP TABLE brin_result (cid tid);
SET enable_seqscan = 0;
SET enable_bitmapscan = 1;
- EXECUTE format('create temp table %s (tid tid) ON COMMIT DROP', tabname);
- EXECUTE query;
+ EXECUTE format($y$INSERT INTO brin_result SELECT ctid FROM brintest WHERE %s $y$, cond);
-- run the query using a seqscan
+ CREATE TEMP TABLE brin_result_ss (cid tid);
SET enable_seqscan = 1;
SET enable_bitmapscan = 0;
- query = format($y$INSERT INTO %s SELECT ctid FROM brintest WHERE %s %s %L $y$,
- tabname_ss, r.colname, r.oper, r.value);
- EXECUTE format('create temp table %s (tid tid) ON COMMIT DROP', tabname_ss);
- EXECUTE query;
+ EXECUTE format($y$INSERT INTO brin_result_ss SELECT ctid FROM brintest WHERE %s $y$, cond);
-- make sure both return the same results
- EXECUTE format('SELECT * from %s EXCEPT ALL SELECT * FROM %s', tabname, tabname_ss);
+ PERFORM * FROM brin_result EXCEPT ALL SELECT * FROM brin_result_ss;
GET DIAGNOSTICS count = ROW_COUNT;
IF count <> 0 THEN RAISE EXCEPTION 'something not right in %: count %', r, count; END IF;
- EXECUTE format('SELECT * from %s EXCEPT ALL SELECT * FROM %s', tabname_ss, tabname);
+ PERFORM * FROM brin_result_ss EXCEPT ALL SELECT * FROM brin_result;
GET DIAGNOSTICS count = ROW_COUNT;
IF count <> 0 THEN RAISE EXCEPTION 'something not right in %: count %', r, count; END IF;
- end loop;
-end;
+
+ -- make sure it was a sensible test case
+ SELECT count(*) INTO count FROM brin_result;
+ IF count = 0 THEN RAISE EXCEPTION 'no results for %', r; END IF;
+
+ -- drop the temporary tables
+ DROP TABLE brin_result;
+ DROP TABLE brin_result_ss;
+ END LOOP;
+END;
$x$;
INSERT INTO brintest SELECT
repeat(stringu1, 42)::bytea,
substr(stringu1, 1, 1)::"char",
stringu1::name, 142857 * tenthous,
thousand,
twothousand,
repeat(stringu1, 42),
unique1::oid,
format('(%s,%s)', tenthous, twenty)::tid,
@@ -163,20 +192,23 @@ INSERT INTO brintest SELECT
date '1995-08-15' + tenthous,
time '01:20:30' + thousand * interval '18.5 second',
timestamp '1942-07-23 03:05:09' + tenthous * interval '36.38 hours',
timestamptz '1972-10-10 03:00' + thousand * interval '1 hour',
justify_days(justify_hours(tenthous * interval '12 minutes')),
timetz '01:30:20' + hundred * interval '15 seconds',
thousand::bit(10),
tenthous::bit(16)::varbit,
tenthous::numeric(36,30) * fivethous * even / (hundred + 1),
format('%s%s-%s-%s-%s-%s%s%s', to_char(tenthous, 'FM0000'), to_char(tenthous, 'FM0000'), to_char(tenthous, 'FM0000'), to_char(tenthous, 'FM0000'), to_char(tenthous, 'FM0000'), to_char(tenthous, 'FM0000'), to_char(tenthous, 'FM0000'), to_char(tenthous, 'FM0000'))::uuid,
- format('%s/%s%s', odd, even, tenthous)::pg_lsn
+ int4range(thousand, twothousand),
+ format('%s/%s%s', odd, even, tenthous)::pg_lsn,
+ box(point(odd, even), point(thousand, twothousand)),
+ point(thousand, twothousand)
FROM tenk1 LIMIT 5 OFFSET 5;
SELECT brin_summarize_new_values('brinidx'::regclass);
brin_summarize_new_values
---------------------------
5
(1 row)
UPDATE brintest SET int8col = int8col * int4col;
UPDATE brintest SET textcol = '' WHERE textcol IS NOT NULL;
diff --git a/src/test/regress/expected/opr_sanity.out b/src/test/regress/expected/opr_sanity.out
index 200fd58..81d2073 100644
--- a/src/test/regress/expected/opr_sanity.out
+++ b/src/test/regress/expected/opr_sanity.out
@@ -1652,24 +1652,51 @@ ORDER BY 1, 2, 3;
2742 | 1 | @@
2742 | 2 | @>
2742 | 2 | @@@
2742 | 3 | <@
2742 | 4 | =
2742 | 7 | @>
2742 | 9 | ?
2742 | 10 | ?|
2742 | 11 | ?&
3580 | 1 | <
+ 3580 | 1 | <<
+ 3580 | 2 | &<
3580 | 2 | <=
+ 3580 | 3 | &&
3580 | 3 | =
+ 3580 | 4 | &>
3580 | 4 | >=
3580 | 5 | >
+ 3580 | 5 | >>
+ 3580 | 6 | ~=
+ 3580 | 7 | >>=
+ 3580 | 7 | @>
+ 3580 | 8 | <<=
+ 3580 | 8 | <@
+ 3580 | 9 | &<|
+ 3580 | 10 | <<|
+ 3580 | 10 | <^
+ 3580 | 11 | >^
+ 3580 | 11 | |>>
+ 3580 | 12 | |&>
+ 3580 | 13 | ~
+ 3580 | 14 | @
+ 3580 | 16 | @>
+ 3580 | 17 | -|-
+ 3580 | 18 | =
+ 3580 | 20 | <
+ 3580 | 21 | <=
+ 3580 | 22 | >
+ 3580 | 23 | >=
+ 3580 | 24 | >>
+ 3580 | 26 | <<
4000 | 1 | <<
4000 | 1 | ~<~
4000 | 2 | &<
4000 | 2 | ~<=~
4000 | 3 | &&
4000 | 3 | =
4000 | 4 | &>
4000 | 4 | ~>=~
4000 | 5 | >>
4000 | 5 | ~>~
@@ -1678,21 +1705,21 @@ ORDER BY 1, 2, 3;
4000 | 7 | @>
4000 | 8 | <@
4000 | 10 | <^
4000 | 11 | <
4000 | 11 | >^
4000 | 12 | <=
4000 | 14 | >=
4000 | 15 | >
4000 | 16 | @>
4000 | 18 | =
-(85 rows)
+(112 rows)
-- Check that all opclass search operators have selectivity estimators.
-- This is not absolutely required, but it seems a reasonable thing
-- to insist on for all standard datatypes.
SELECT p1.amopfamily, p1.amopopr, p2.oid, p2.oprname
FROM pg_amop AS p1, pg_operator AS p2
WHERE p1.amopopr = p2.oid AND p1.amoppurpose = 's' AND
(p2.oprrest = 0 OR p2.oprjoin = 0);
amopfamily | amopopr | oid | oprname
------------+---------+-----+---------
diff --git a/src/test/regress/sql/brin.sql b/src/test/regress/sql/brin.sql
index 3aff925..a8cbdf8 100644
--- a/src/test/regress/sql/brin.sql
+++ b/src/test/regress/sql/brin.sql
@@ -15,149 +15,178 @@ CREATE TABLE brintest (byteacol bytea,
datecol date,
timecol time without time zone,
timestampcol timestamp without time zone,
timestamptzcol timestamp with time zone,
intervalcol interval,
timetzcol time with time zone,
bitcol bit(10),
varbitcol bit varying(16),
numericcol numeric,
uuidcol uuid,
- lsncol pg_lsn
+ int4rangecol int4range,
+ lsncol pg_lsn,
+ boxcol box,
+ pointcol point
) WITH (fillfactor=10);
INSERT INTO brintest SELECT
- repeat(stringu1, 42)::bytea,
+ repeat(stringu1, 8)::bytea,
substr(stringu1, 1, 1)::"char",
stringu1::name, 142857 * tenthous,
thousand,
twothousand,
- repeat(stringu1, 42),
+ repeat(stringu1, 8),
unique1::oid,
format('(%s,%s)', tenthous, twenty)::tid,
(four + 1.0)/(hundred+1),
odd::float8 / (tenthous + 1),
format('%s:00:%s:00:%s:00', to_hex(odd), to_hex(even), to_hex(hundred))::macaddr,
- inet '10.2.3.4' + tenthous,
+ inet '10.2.3.4/24' + tenthous,
substr(stringu1, 1, 1)::bpchar,
date '1995-08-15' + tenthous,
time '01:20:30' + thousand * interval '18.5 second',
timestamp '1942-07-23 03:05:09' + tenthous * interval '36.38 hours',
timestamptz '1972-10-10 03:00' + thousand * interval '1 hour',
justify_days(justify_hours(tenthous * interval '12 minutes')),
- timetz '01:30:20' + hundred * interval '15 seconds',
+ timetz '01:30:20+02' + hundred * interval '15 seconds',
thousand::bit(10),
tenthous::bit(16)::varbit,
tenthous::numeric(36,30) * fivethous * even / (hundred + 1),
format('%s%s-%s-%s-%s-%s%s%s', to_char(tenthous, 'FM0000'), to_char(tenthous, 'FM0000'), to_char(tenthous, 'FM0000'), to_char(tenthous, 'FM0000'), to_char(tenthous, 'FM0000'), to_char(tenthous, 'FM0000'), to_char(tenthous, 'FM0000'), to_char(tenthous, 'FM0000'))::uuid,
- format('%s/%s%s', odd, even, tenthous)::pg_lsn
-FROM tenk1 LIMIT 5;
+ int4range(thousand, twothousand),
+ format('%s/%s%s', odd, even, tenthous)::pg_lsn,
+ box(point(odd, even), point(thousand, twothousand)),
+ point(thousand, twothousand)
+FROM tenk1 LIMIT 25;
--- throw in some NULL-only tuples too
-INSERT INTO brintest SELECT NULL FROM tenk1 LIMIT 25;
+-- throw in some NULL's and different values
+INSERT INTO brintest (inetcol, int4rangecol) SELECT
+ inet 'fe80::6e40:8ff:fea9:8c46' + tenthous,
+ 'empty'::int4range
+FROM tenk1 LIMIT 25;
CREATE INDEX brinidx ON brintest USING brin (
byteacol,
charcol,
namecol,
int8col,
int2col,
int4col,
textcol,
oidcol,
tidcol,
float4col,
float8col,
macaddrcol,
+ inetcol inet_inclusion_ops,
inetcol inet_minmax_ops,
bpcharcol,
datecol,
timecol,
timestampcol,
timestamptzcol,
intervalcol,
timetzcol,
bitcol,
varbitcol,
numericcol,
uuidcol,
- lsncol
+ int4rangecol,
+ lsncol,
+ boxcol,
+ pointcol
) with (pages_per_range = 1);
BEGIN;
-CREATE TABLE brinopers (colname name, op text[], value text[],
+CREATE TABLE brinopers (colname name, typ regtype, op text[], value text[],
check (cardinality(op) = cardinality(value)));
-INSERT INTO brinopers VALUES ('byteacol', '{>, >=, =, <=, <}', '{ZZAAAA, ZZAAAA, AAAAAA, AAAAAA, AAAAAA}');
-INSERT INTO brinopers VALUES ('charcol', '{>, >=, =, <=, <}', '{Z, Z, A, A, A}');
-INSERT INTO brinopers VALUES ('namecol', '{>, >=, =, <=, <}', '{ZZAAAA, ZZAAAA, AAAAAA, AAAAAA, AAAAAA}');
-INSERT INTO brinopers VALUES ('int8col', '{>, >=, =, <=, <}', '{1428427143, 1428427143, 0, 0, 0}');
-INSERT INTO brinopers VALUES ('int2col', '{>, >=, =, <=, <}', '{999, 999, 0, 0, 0}');
-INSERT INTO brinopers VALUES ('int4col', '{>, >=, =, <=, <}', '{1999, 1999, 0, 0, 0}');
-INSERT INTO brinopers VALUES ('textcol', '{>, >=, =, <=, <}', '{ZZAAAA, ZZAAAA, AAAAA, AAAAA, AAAAA}');
-INSERT INTO brinopers VALUES ('oidcol', '{>, >=, =, <=, <}', '{9999, 9999, 0, 0, 0}');
-INSERT INTO brinopers VALUES ('tidcol', '{>, >=, =, <=, <}', '{"(9999,19)", "(9999,19)", "(0,0)", "(0,0)", "(0,0)"}');
-INSERT INTO brinopers VALUES ('float4col', '{>, >=, =, <=, <}', '{1, 1, 0.0103093, 0.0103093, 0.0103093}');
-INSERT INTO brinopers VALUES ('float8col', '{>, >=, =, <=, <}', '{1.98, 1.98, 0, 0, 0}');
-INSERT INTO brinopers VALUES ('inetcol', '{>, >=, =, <=, <}', '{10.2.42.19, 10.2.42.19, 10.2.3.4, 10.2.3.4, 10.2.3.4}');
-INSERT INTO brinopers VALUES ('bpcharcol', '{>, >=, =, <=, <}', '{Z, Z, A, A, A}');
-INSERT INTO brinopers VALUES ('datecol', '{>, >=, =, <=, <}', '{2022-12-30, 2022-12-30, 1995-08-15, 1995-08-15, 1995-08-15}');
-INSERT INTO brinopers VALUES ('timecol', '{>, >=, =, <=, <}', '{06:28:31.5, 06:28:31.5, 01:20:30, 01:20:30, 01:20:30}');
-INSERT INTO brinopers VALUES ('timestampcol', '{>, >=, =, <=, <}', '{1984-01-20 22:42:21, 1984-01-20 22:42:21, 1942-07-23 03:05:09, 1942-07-23 03:05:09, 1942-07-23 03:05:09}');
-INSERT INTO brinopers VALUES ('timestamptzcol', '{>, >=, =, <=, <}', '{1972-11-20 19:00:00-03, 1972-11-20 19:00:00-03, 1972-10-10 03:00:00-04, 1972-10-10 03:00:00-04, 1972-10-10 03:00:00-04}');
-INSERT INTO brinopers VALUES ('intervalcol', '{>, >=, =, <=, <}', '{2 mons 23 days 07:48:00, 2 mons 23 days 07:48:00, 00:00:00, 00:00:00, 00:00:00}');
-INSERT INTO brinopers VALUES ('timetzcol', '{>, >=, =, <=, <}', '{01:55:05-03, 01:55:05-03, 01:30:20-03, 01:30:20-03, 01:30:20-03}');
-INSERT INTO brinopers VALUES ('numericcol', '{>, >=, =, <=, <}', '{99470151.9, 99470151.9, 0.00, 0.01, 0.01}');
-INSERT INTO brinopers VALUES ('macaddrcol', '{>, >=, =, <=, <}', '{ff:fe:00:00:00:00, ff:fe:00:00:00:00, 00:00:01:00:00:00, 00:00:01:00:00:00, 00:00:01:00:00:00}');
-INSERT INTO brinopers VALUES ('bitcol', '{>, >=, =, <=, <}', '{1111111000, 1111111000, 0000000010, 0000000010, 0000000010}');
-INSERT INTO brinopers VALUES ('varbitcol', '{>, >=, =, <=, <}', '{1111111111111000, 1111111111111000, 0000000000000100, 0000000000000100, 0000000000000100}');
-INSERT INTO brinopers VALUES ('uuidcol', '{>, >=, =, <=, <}', '{99989998-9998-9998-9998-999899989998, 99989998-9998-9998-9998-999899989998, 00040004-0004-0004-0004-000400040004, 00040004-0004-0004-0004-000400040004, 00040004-0004-0004-0004-000400040005}');
-INSERT INTO brinopers VALUES ('lsncol', '{>, >=, =, <=, <, IS, IS NOT}', '{198/1999799, 198/1999799, 30/312815, 0/1200, 0/1200, NULL, NULL}');
+INSERT INTO brinopers VALUES
+ ('byteacol', NULL, '{>, >=, =, <=, <}', '{AAAAAA, AAAAAA, BNAAAABNAAAABNAAAABNAAAABNAAAABNAAAABNAAAABNAAAA, ZZZZZZ, ZZZZZZ}'),
+ ('charcol', NULL, '{>, >=, =, <=, <}', '{A, A, M, Z, Z}'),
+ ('namecol', NULL, '{>, >=, =, <=, <}', '{AAAAAA, AAAAAA, MAAAAA, ZZAAAA, ZZAAAA}'),
+ ('int8col', NULL, '{>, >=, =, <=, <}', '{0, 0, 1257141600, 1428427143, 1428427143}'),
+ ('int2col', NULL, '{>, >=, =, <=, <}', '{0, 0, 800, 999, 999}'),
+ ('int4col', NULL, '{>, >=, =, <=, <}', '{0, 0, 800, 1999, 1999}'),
+ ('textcol', NULL, '{>, >=, =, <=, <}', '{AAAAAA, AAAAAA, BNAAAABNAAAABNAAAABNAAAABNAAAABNAAAABNAAAABNAAAA, ZZAAAA, ZZAAAA}'),
+ ('oidcol', NULL, '{>, >=, =, <=, <}', '{0, 0, 8800, 9999, 9999}'),
+ ('tidcol', NULL, '{>, >=, =, <=, <}', '{"(0,0)", "(0,0)", "(8800,0)", "(9999,19)", "(9999,19)"}'),
+ ('float4col', NULL, '{>, >=, =, <=, <}', '{0.0103093, 0.0103093, 1, 1, 1}'),
+ ('float8col', NULL, '{>, >=, =, <=, <}', '{0, 0, 0, 1.98, 1.98}'),
+ ('inetcol', NULL, '{&&, =, <, <=, >, >=, >>=, >>, <<=, <<}', '{10/8, 10.2.14.231/24, 255.255.255.255, 255.255.255.255, 0.0.0.0, 0.0.0.0, 10.2.14.231/24, 10.2.14.231/25, 10.2.14.231/8, 0/0}'),
+ ('inetcol', NULL, '{&&, >>=, <<=, =}', '{fe80::6e40:8ff:fea9:a673/32, fe80::6e40:8ff:fea9:8c46, fe80::6e40:8ff:fea9:a673/32, fe80::6e40:8ff:fea9:8c46}'),
+ ('inetcol', 'cidr', '{<<=}', '{0/0}'),
+ ('bpcharcol', NULL, '{>, >=, =, <=, <}', '{A, A, W, Z, Z}'),
+ ('datecol', NULL, '{>, >=, =, <=, <}', '{1995-08-15, 1995-08-15, 2009-12-01, 2022-12-30, 2022-12-30}'),
+ ('timecol', NULL, '{>, >=, =, <=, <}', '{01:20:30, 01:20:30, 02:28:57, 06:28:31.5, 06:28:31.5}'),
+ ('timestampcol', NULL, '{>, >=, =, <=, <}', '{1942-07-23 03:05:09, 1942-07-23 03:05:09, 1964-03-24 19:26:45, 1984-01-20 22:42:21, 1984-01-20 22:42:21}'),
+ ('timestamptzcol', NULL, '{>, >=, =, <=, <}', '{1972-10-10 03:00:00-04, 1972-10-10 03:00:00-04, 1972-10-19 09:00:00-07, 1972-11-20 19:00:00-03, 1972-11-20 19:00:00-03}'),
+ ('intervalcol', NULL, '{>, >=, =, <=, <}', '{00:00:00, 00:00:00, 1 mons 13 days 12:24, 2 mons 23 days 07:48:00, 1 year}'),
+ ('timetzcol', NULL, '{>, >=, =, <=, <}', '{01:30:20+02, 01:30:20+02, 01:35:50+02, 23:55:05+02, 23:55:05+02}'),
+ ('numericcol', NULL, '{>, >=, =, <=, <}', '{0.00, 0.01, 2268164.347826086956521739130434782609, 99470151.9, 99470151.9}'),
+ ('macaddrcol', NULL, '{>, >=, =, <=, <}', '{00:00:01:00:00:00, 00:00:01:00:00:00, 2c:00:2d:00:16:00, ff:fe:00:00:00:00, ff:fe:00:00:00:00}'),
+ ('bitcol', NULL, '{>, >=, =, <=, <}', '{0000000010, 0000000010, 0011011110, 1111111000, 1111111000}'),
+ ('varbitcol', NULL, '{>, >=, =, <=, <}', '{0000000000000100, 0000000000000100, 0001010001100110, 1111111111111000, 1111111111111000}'),
+ ('uuidcol', NULL, '{>, >=, =, <=, <}', '{00040004-0004-0004-0004-000400040004, 00040004-0004-0004-0004-000400040004, 52225222-5222-5222-5222-522252225222, 99989998-9998-9998-9998-999899989998, 99989998-9998-9998-9998-999899989998}'),
+ ('int4rangecol', NULL, '{<<, &<, &&, &>, >>, @>, <@, =, <, <=, >, >=}', '{"[10000,)","[10000,)","(,]","[3,4)","[36,44)","(1500,1501]","[3,4)","[222,1222)","[36,44)","[43,1043)","[367,4466)","[519,)"}'),
+ ('int4rangecol', NULL, '{@>, <@, =, <=, >, >=}', '{empty, empty, empty, empty, empty, empty}'),
+ ('int4rangecol', 'int4', '{@>}', '{1500}'),
+ ('lsncol', NULL, '{>, >=, =, <=, <, IS, IS NOT}', '{0/1200, 0/1200, 44/455222, 198/1999799, 198/1999799, NULL, NULL}'),
+ ('boxcol', NULL, '{<<, &<, &&, &>, >>, <<|, &<|, |&>, |>>, @>, <@, ~=}', '{"((1000,2000),(3000,4000))","((1,2),(3000,4000))","((1,2),(3000,4000))","((1,2),(3000,4000))","((1,2),(3,4))","((1000,2000),(3000,4000))","((1,2000),(3,4000))","((1000,2),(3000,4))","((1,2),(3,4))","((1,2),(300,400))","((1,2),(3000,4000))","((222,1222),(44,45))"}'),
+ ('boxcol', 'point', '{<<, &<, &&, &>, >>, <<|, &<|, |&>, |>>, @>}', '{"(1000,2000)","(3000,4000)","(500,43)","(1,2)","(3,4)","(3000,4000)","(3000,4000)","(1,2)","(1,2)","(500,43)"}'),
+ ('pointcol', NULL, '{<<, >>, <^, >^, ~=}', '{"(3000,4000)","(3,4)","(5000,15000)","(1,2)","(222,1222)"}'),
+ ('pointcol', 'box', '{<@, &&}', '{"((0,0),(5000,5000))","((0,0),(3000,4000))"}');
COMMIT;
DO $x$
DECLARE
r record;
- tabname text;
- tabname_ss text;
+ cond text;
count int;
- query text;
- plan text;
BEGIN
- FOR r IN SELECT row_number() OVER (), colname, oper, value[ordinality] FROM brinopers, unnest(op) WITH ORDINALITY AS oper LOOP
- tabname := format('qry_%s', r.row_number);
- tabname_ss := tabname || '_ss';
- query = format($y$INSERT INTO %s SELECT ctid FROM brintest WHERE %s %s %L $y$,
- tabname, r.colname, r.oper, r.value);
+ FOR r IN SELECT colname, oper, typ, value[ordinality] FROM brinopers, unnest(op) WITH ORDINALITY AS oper LOOP
+ -- prepare the condition
+ IF r.typ IS NULL THEN
+ cond := format('%I %s %L', r.colname, r.oper, r.value);
+ ELSE
+ cond := format('%I %s %L::%s', r.colname, r.oper, r.value, r.typ);
+ END IF;
+
-- run the query using the brin index
+ CREATE TEMP TABLE brin_result (cid tid);
SET enable_seqscan = 0;
SET enable_bitmapscan = 1;
- EXECUTE format('create temp table %s (tid tid) ON COMMIT DROP', tabname);
- EXECUTE query;
+ EXECUTE format($y$INSERT INTO brin_result SELECT ctid FROM brintest WHERE %s $y$, cond);
-- run the query using a seqscan
+ CREATE TEMP TABLE brin_result_ss (cid tid);
SET enable_seqscan = 1;
SET enable_bitmapscan = 0;
- query = format($y$INSERT INTO %s SELECT ctid FROM brintest WHERE %s %s %L $y$,
- tabname_ss, r.colname, r.oper, r.value);
- EXECUTE format('create temp table %s (tid tid) ON COMMIT DROP', tabname_ss);
- EXECUTE query;
+ EXECUTE format($y$INSERT INTO brin_result_ss SELECT ctid FROM brintest WHERE %s $y$, cond);
-- make sure both return the same results
- EXECUTE format('SELECT * from %s EXCEPT ALL SELECT * FROM %s', tabname, tabname_ss);
+ PERFORM * FROM brin_result EXCEPT ALL SELECT * FROM brin_result_ss;
GET DIAGNOSTICS count = ROW_COUNT;
IF count <> 0 THEN RAISE EXCEPTION 'something not right in %: count %', r, count; END IF;
- EXECUTE format('SELECT * from %s EXCEPT ALL SELECT * FROM %s', tabname_ss, tabname);
+ PERFORM * FROM brin_result_ss EXCEPT ALL SELECT * FROM brin_result;
GET DIAGNOSTICS count = ROW_COUNT;
IF count <> 0 THEN RAISE EXCEPTION 'something not right in %: count %', r, count; END IF;
- end loop;
-end;
+
+ -- make sure it was a sensible test case
+ SELECT count(*) INTO count FROM brin_result;
+ IF count = 0 THEN RAISE EXCEPTION 'no results for %', r; END IF;
+
+ -- drop the temporary tables
+ DROP TABLE brin_result;
+ DROP TABLE brin_result_ss;
+ END LOOP;
+END;
$x$;
INSERT INTO brintest SELECT
repeat(stringu1, 42)::bytea,
substr(stringu1, 1, 1)::"char",
stringu1::name, 142857 * tenthous,
thousand,
twothousand,
repeat(stringu1, 42),
unique1::oid,
@@ -170,17 +199,20 @@ INSERT INTO brintest SELECT
date '1995-08-15' + tenthous,
time '01:20:30' + thousand * interval '18.5 second',
timestamp '1942-07-23 03:05:09' + tenthous * interval '36.38 hours',
timestamptz '1972-10-10 03:00' + thousand * interval '1 hour',
justify_days(justify_hours(tenthous * interval '12 minutes')),
timetz '01:30:20' + hundred * interval '15 seconds',
thousand::bit(10),
tenthous::bit(16)::varbit,
tenthous::numeric(36,30) * fivethous * even / (hundred + 1),
format('%s%s-%s-%s-%s-%s%s%s', to_char(tenthous, 'FM0000'), to_char(tenthous, 'FM0000'), to_char(tenthous, 'FM0000'), to_char(tenthous, 'FM0000'), to_char(tenthous, 'FM0000'), to_char(tenthous, 'FM0000'), to_char(tenthous, 'FM0000'), to_char(tenthous, 'FM0000'))::uuid,
- format('%s/%s%s', odd, even, tenthous)::pg_lsn
+ int4range(thousand, twothousand),
+ format('%s/%s%s', odd, even, tenthous)::pg_lsn,
+ box(point(odd, even), point(thousand, twothousand)),
+ point(thousand, twothousand)
FROM tenk1 LIMIT 5 OFFSET 5;
SELECT brin_summarize_new_values('brinidx'::regclass);
UPDATE brintest SET int8col = int8col * int4col;
UPDATE brintest SET textcol = '' WHERE textcol IS NOT NULL;
--
2.2.1