diff --git a/doc/src/sgml/brin.sgml b/doc/src/sgml/brin.sgml index 1ac282c..c8b8f62 100644 --- a/doc/src/sgml/brin.sgml +++ b/doc/src/sgml/brin.sgml @@ -65,21 +65,23 @@ The core PostgreSQL distribution includes the BRIN operator classes shown in . The 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 inclusion + operator classes store the union of the values in the indexed column + withing the range. Built-in <acronym>BRIN</acronym> Operator Classes Name Indexed Data Type Indexable Operators @@ -245,20 +247,32 @@ inet < <= = >= > + inet_inclusion_ops + inet + + && + >> + >>= + << + <<= + = + + + bpchar_minmax_ops character < <= = >= > @@ -366,30 +380,86 @@ uuid < <= = >= > + range_inclusion_ops + any range type + + && + &> + &< + >> + << + <@ + = + @> + < + <= + = + >= + > + + + pg_lsn_minmax_ops pg_lsn < <= = >= > + + box_inclusion_ops + box + + && + &> + &< + >> + << + <@ + ~= + @> + &>| + |&< + >>| + |<< + + + + point_box_inclusion_ops + point + + && + &> + &< + >> + << + <@ + ~= + &>| + |&< + >>| + |<< + >^ + |<^ + +
Extensibility The BRIN interface has a high level of abstraction, diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml index d57243a..4f0fb4c 100644 --- a/doc/src/sgml/func.sgml +++ b/doc/src/sgml/func.sgml @@ -8726,20 +8726,44 @@ CREATE TYPE rainbow AS ENUM ('red', 'orange', 'yellow', 'green', 'blue', 'purple text text(inet) text extract IP address and netmask length as text text(inet '192.168.1.5') 192.168.1.5/32 + + + + inet_same_family + + inet_same_family(inet, inet) + + boolean + are the addresses from the same family? + inet_same_family('192.168.1.5/24', '::1') + false + + + + + inet_merge + + inet_merge(inet, inet) + + cidr + the smallest network which includes both of the given networks + inet_merge('192.168.1.5/24', '192.168.2.5/24') + 192.168.0.0/22 + Any cidr value can be cast to inet implicitly or explicitly; therefore, the functions shown above as operating on inet also work on cidr values. (Where there are separate functions for inet and cidr, it is because the behavior should be different for the two cases.) @@ -12027,20 +12051,31 @@ NULL baz(3 rows) upper_inf(anyrange) boolean is the upper bound infinite? upper_inf('(,)'::daterange) true + + + + range_merge(anyrange, anyrange) + + + anyrange + the smallest range which includes both of the given ranges + range_merge('[1,2)'::int4range, '[3,4)'::int4range) + [1,4) + The lower and upper functions return null if the range is empty or the requested bound is infinite. The lower_inc, upper_inc, lower_inf, and upper_inf functions all return false for an empty range. 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.c b/src/backend/access/brin/brin.c index 2b5fb8d..a6dd4bf 100644 --- a/src/backend/access/brin/brin.c +++ b/src/backend/access/brin/brin.c @@ -98,25 +98,20 @@ brininsert(PG_FUNCTION_ARGS) revmap = brinRevmapInitialize(idxRel, &pagesPerRange); for (;;) { bool need_insert = false; OffsetNumber off; BrinTuple *brtup; BrinMemTuple *dtup; BlockNumber heapBlk; int keyno; -#ifdef USE_ASSERT_CHECKING - BrinTuple *tmptup; - BrinMemTuple *tmpdtup; - Size tmpsiz; -#endif CHECK_FOR_INTERRUPTS(); heapBlk = ItemPointerGetBlockNumber(heaptid); /* normalize the block number to be the first block in the range */ heapBlk = (heapBlk / pagesPerRange) * pagesPerRange; brtup = brinGetTupleForHeapBlock(revmap, heapBlk, &buf, &off, NULL, BUFFER_LOCK_SHARE); /* if range is unsummarized, there's nothing to do */ @@ -130,59 +125,20 @@ brininsert(PG_FUNCTION_ARGS) tupcxt = AllocSetContextCreate(CurrentMemoryContext, "brininsert cxt", ALLOCSET_DEFAULT_MINSIZE, ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE); oldcxt = MemoryContextSwitchTo(tupcxt); } dtup = brin_deform_tuple(bdesc, brtup); -#ifdef USE_ASSERT_CHECKING - { - /* - * When assertions are enabled, we use this as an opportunity to - * test the "union" method, which would otherwise be used very - * rarely: first create a placeholder tuple, and addValue the - * value we just got into it. Then union the existing index tuple - * with the updated placeholder tuple. The tuple resulting from - * that union should be identical to the one resulting from the - * regular operation (straight addValue) below. - * - * Here we create the tuple to compare with; the actual comparison - * is below. - */ - tmptup = brin_form_placeholder_tuple(bdesc, heapBlk, &tmpsiz); - tmpdtup = brin_deform_tuple(bdesc, tmptup); - for (keyno = 0; keyno < bdesc->bd_tupdesc->natts; keyno++) - { - BrinValues *bval; - FmgrInfo *addValue; - - bval = &tmpdtup->bt_columns[keyno]; - addValue = index_getprocinfo(idxRel, keyno + 1, - BRIN_PROCNUM_ADDVALUE); - FunctionCall4Coll(addValue, - idxRel->rd_indcollation[keyno], - PointerGetDatum(bdesc), - PointerGetDatum(bval), - values[keyno], - nulls[keyno]); - } - - union_tuples(bdesc, tmpdtup, brtup); - - tmpdtup->bt_placeholder = dtup->bt_placeholder; - tmptup = brin_form_tuple(bdesc, heapBlk, tmpdtup, &tmpsiz); - } -#endif - /* * Compare the key values of the new tuple to the stored index values; * our deformed tuple will get updated if the new tuple doesn't fit * the original range (note this means we can't break out of the loop * early). Make a note of whether this happens, so that we know to * insert the modified tuple later. */ for (keyno = 0; keyno < bdesc->bd_tupdesc->natts; keyno++) { Datum result; @@ -195,34 +151,20 @@ brininsert(PG_FUNCTION_ARGS) result = FunctionCall4Coll(addValue, idxRel->rd_indcollation[keyno], PointerGetDatum(bdesc), PointerGetDatum(bval), values[keyno], nulls[keyno]); /* if that returned true, we need to insert the updated tuple */ need_insert |= DatumGetBool(result); } -#ifdef USE_ASSERT_CHECKING - { - /* - * Now we can compare the tuple produced by the union function - * with the one from plain addValue. - */ - BrinTuple *cmptup; - Size cmpsz; - - cmptup = brin_form_tuple(bdesc, heapBlk, dtup, &cmpsz); - Assert(brin_tuples_equal(tmptup, tmpsiz, cmptup, cmpsz)); - } -#endif - if (!need_insert) { /* * The tuple is consistent with the new values, so there's nothing * to do. */ LockBuffer(buf, BUFFER_LOCK_UNLOCK); } else { diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c new file mode 100644 index 0000000..d68db41 --- /dev/null +++ b/src/backend/access/brin/brin_inclusion.c @@ -0,0 +1,631 @@ +/* + * 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; + Oid last_strategynum; + FmgrInfo last_strategy_procinfo; +} 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 or not */ + + 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 that 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 that 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 that 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 the 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)); + + /* + * 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: + case RTContainedByEqualStrategyNumber: + if (DatumGetBool(column->bv_values[2])) + PG_RETURN_BOOL(true); + + frmg = inclusion_get_strategy_procinfo(bdesc, attno, subtype, + RTOverlapStrategyNumber); + result = FunctionCall2Coll(frmg, colloid, column->bv_values[0], + query); + PG_RETURN_DATUM(result); + + /* + * 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 does 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 this strategies except the same strategy are not suitable + * for the geometric types which uses 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: + if (DatumGetBool(column->bv_values[2])) + PG_RETURN_BOOL(true); + + frmg = inclusion_get_strategy_procinfo(bdesc, attno, subtype, + RTRightStrategyNumber); + result = FunctionCall2Coll(frmg, colloid, column->bv_values[0], + query); + PG_RETURN_BOOL(!DatumGetBool(result)); + + case RTSameStrategyNumber: + case RTEqualStrategyNumber: + if (DatumGetBool(column->bv_values[2])) + PG_RETURN_BOOL(true); + + frmg = inclusion_get_strategy_procinfo(bdesc, attno, subtype, + RTContainsStrategyNumber); + result = FunctionCall2Coll(frmg, colloid, column->bv_values[0], + query); + PG_RETURN_DATUM(result); + + case RTGreaterEqualStrategyNumber: + if (DatumGetBool(column->bv_values[2])) + PG_RETURN_BOOL(true); + + frmg = inclusion_get_strategy_procinfo(bdesc, attno, subtype, + RTLeftStrategyNumber); + result = FunctionCall2Coll(frmg, colloid, column->bv_values[0], + query); + PG_RETURN_BOOL(!DatumGetBool(result)); + + 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)); + + /* + * Other strategies + * + * By default, we will call the operator of the strategy. + * + * We assume that empty element will not change the result. It is + * true for the contains strategies which will be handled by + * the default case as empty elements cannot contain anything but + * is contained in everything. + */ + + default: + frmg = inclusion_get_strategy_procinfo(bdesc, attno, subtype, + key->sk_strategy); + result = FunctionCall2Coll(frmg, colloid, column->bv_values[0], + query); + PG_RETURN_DATUM(result); + } +} + +/* + * 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 that B includes empty elements or not. */ + if (!DatumGetBool(col_a->bv_values[2]) && + DatumGetBool(col_b->bv_values[2])) + col_a->bv_values[2] = BoolGetDatum(true); + + /* Check that A includes elements that are not mergeable. */ + if (DatumGetBool(col_a->bv_values[1])) + PG_RETURN_VOID(); + + /* Check that 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 that 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 as 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. Some 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; + + opaque = (InclusionOpaque *) bdesc->bd_info[attno - 1]->oi_opaque; + + /* + * We cache the last procedure in the opaque struct, to avoid repetitive + * syscache lookups. It is enough to cache only the last one, because + * none of the strategies need to lookup for the second one. + */ + if (opaque->last_subtype != subtype || + opaque->last_strategynum != strategynum) + { + 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->last_strategy_procinfo, bdesc->bd_context); + } + + return &opaque->last_strategy_procinfo; +} diff --git a/src/backend/access/brin/brin_tuple.c b/src/backend/access/brin/brin_tuple.c index 93f00f6..be09c0f 100644 --- a/src/backend/access/brin/brin_tuple.c +++ b/src/backend/access/brin/brin_tuple.c @@ -30,20 +30,21 @@ * src/backend/access/brin/brin_tuple.c */ #include "postgres.h" #include "access/htup_details.h" #include "access/brin_tuple.h" #include "access/tupdesc.h" #include "access/tupmacs.h" #include "utils/datum.h" #include "utils/memutils.h" +#include "utils/typcache.h" static inline void brin_deconstruct_tuple(BrinDesc *brdesc, char *tp, bits8 *nullbits, bool nulls, Datum *values, bool *allnulls, bool *hasnulls); /* * Return a tuple descriptor used for on-disk storage of BRIN tuples. */ @@ -423,36 +424,41 @@ brin_deform_tuple(BrinDesc *brdesc, BrinTuple *tuple) values, allnulls, hasnulls); /* * Iterate to assign each of the values to the corresponding item in the * values array of each column. The copies occur in the tuple's context. */ oldcxt = MemoryContextSwitchTo(dtup->bt_context); for (valueno = 0, keyno = 0; keyno < brdesc->bd_tupdesc->natts; keyno++) { int i; + TypeCacheEntry *typcache; if (allnulls[keyno]) { valueno += brdesc->bd_info[keyno]->oi_nstored; continue; } /* * We would like to skip datumCopy'ing the values datum in some cases, * caller permitting ... */ for (i = 0; i < brdesc->bd_info[keyno]->oi_nstored; i++) + { + typcache = lookup_type_cache(brdesc->bd_info[keyno]->oi_typids[i], + 0); + dtup->bt_columns[keyno].bv_values[i] = - datumCopy(values[valueno++], - brdesc->bd_tupdesc->attrs[keyno]->attbyval, - brdesc->bd_tupdesc->attrs[keyno]->attlen); + datumCopy(values[valueno++], typcache->typbyval, + typcache->typlen); + } dtup->bt_columns[keyno].bv_hasnulls = hasnulls[keyno]; dtup->bt_columns[keyno].bv_allnulls = false; } MemoryContextSwitchTo(oldcxt); pfree(values); pfree(allnulls); pfree(hasnulls); diff --git a/src/backend/utils/adt/geo_ops.c b/src/backend/utils/adt/geo_ops.c index 6b6510e..6ff61ee 100644 --- a/src/backend/utils/adt/geo_ops.c +++ b/src/backend/utils/adt/geo_ops.c @@ -526,21 +526,21 @@ box_copy(BOX *box) BOX *result = (BOX *) palloc(sizeof(BOX)); memcpy((char *) result, (char *) box, sizeof(BOX)); return result; } /*---------------------------------------------------------- * Relational operators for BOXes. - * <, >, <=, >=, and == are based on box area. + * <, >, <=, >=, and = are based on box area. *---------------------------------------------------------*/ /* box_same - are two boxes identical? */ Datum box_same(PG_FUNCTION_ARGS) { BOX *box1 = PG_GETARG_BOX_P(0); BOX *box2 = PG_GETARG_BOX_P(1); @@ -767,20 +767,125 @@ Datum box_ge(PG_FUNCTION_ARGS) { BOX *box1 = PG_GETARG_BOX_P(0); BOX *box2 = PG_GETARG_BOX_P(1); PG_RETURN_BOOL(FPge(box_ar(box1), box_ar(box2))); } /*---------------------------------------------------------- + * Relational operators for BOX vs Point + *---------------------------------------------------------*/ + +/* box_left_pt - is box strictly left of point? + */ +Datum +box_left_pt(PG_FUNCTION_ARGS) +{ + BOX *box = PG_GETARG_BOX_P(0); + Point *pt = PG_GETARG_POINT_P(1); + + PG_RETURN_BOOL(box->high.x < pt->x); +} + +/* box_overleft_pt - is the right edge of box at or left of point? + */ +Datum +box_overleft_pt(PG_FUNCTION_ARGS) +{ + BOX *box = PG_GETARG_BOX_P(0); + Point *pt = PG_GETARG_POINT_P(1); + + PG_RETURN_BOOL(box->low.x <= pt->x); +} + +/* box_right_pt - is box strictly right of point? + */ +Datum +box_right_pt(PG_FUNCTION_ARGS) +{ + BOX *box = PG_GETARG_BOX_P(0); + Point *pt = PG_GETARG_POINT_P(1); + + PG_RETURN_BOOL(box->low.x > pt->x); +} + +/* box_overright_pt - is the left edge of box at or right of point? + */ +Datum +box_overright_pt(PG_FUNCTION_ARGS) +{ + BOX *box = PG_GETARG_BOX_P(0); + Point *pt = PG_GETARG_POINT_P(1); + + PG_RETURN_BOOL(box->high.x >= pt->x); +} + +/* box_below_pt - is box strictly below point? + */ +Datum +box_below_pt(PG_FUNCTION_ARGS) +{ + BOX *box = PG_GETARG_BOX_P(0); + Point *pt = PG_GETARG_POINT_P(1); + + PG_RETURN_BOOL(box->high.y < pt->y); +} + +/* box_overbelow_pt - is the upper edge of box at or below point? + */ +Datum +box_overbelow_pt(PG_FUNCTION_ARGS) +{ + BOX *box = PG_GETARG_BOX_P(0); + Point *pt = PG_GETARG_POINT_P(1); + + PG_RETURN_BOOL(box->low.y <= pt->y); +} + +/* box_above_pt - is box strictly above point? + */ +Datum +box_above_pt(PG_FUNCTION_ARGS) +{ + BOX *box = PG_GETARG_BOX_P(0); + Point *pt = PG_GETARG_POINT_P(1); + + PG_RETURN_BOOL(box->low.y > pt->y); +} + +/* box_overabove_pt - is the lower edge of box at or above point? + */ +Datum +box_overabove_pt(PG_FUNCTION_ARGS) +{ + BOX *box = PG_GETARG_BOX_P(0); + Point *pt = PG_GETARG_POINT_P(1); + + PG_RETURN_BOOL(box->high.y >= pt->y); +} + +/* box_contain_pt - does box contain point? + */ +Datum +box_contain_pt(PG_FUNCTION_ARGS) +{ + BOX *box = PG_GETARG_BOX_P(0); + Point *pt = PG_GETARG_POINT_P(1); + + PG_RETURN_BOOL(pt->x <= box->high.x && pt->x >= box->low.x && + pt->y <= box->high.y && pt->y >= box->low.y); +} + + +/*---------------------------------------------------------- * "Arithmetic" operators on boxes. *---------------------------------------------------------*/ /* box_area - returns the area of the box. */ Datum box_area(PG_FUNCTION_ARGS) { BOX *box = PG_GETARG_BOX_P(0); @@ -904,20 +1009,41 @@ box_intersect(PG_FUNCTION_ARGS) result = (BOX *) palloc(sizeof(BOX)); result->high.x = Min(box1->high.x, box2->high.x); result->low.x = Max(box1->low.x, box2->low.x); result->high.y = Min(box1->high.y, box2->high.y); result->low.y = Max(box1->low.y, box2->low.y); PG_RETURN_BOX_P(result); } +/* boxes_bound_box - + * returns the smallest bounding box that + * includes both of the given boxes. + */ +Datum +boxes_bound_box(PG_FUNCTION_ARGS) +{ + BOX *box1 = PG_GETARG_BOX_P(0), + *box2 = PG_GETARG_BOX_P(1), + *container; + + container = (BOX *) palloc(sizeof(BOX)); + + container->high.x = Max(box1->high.x, box2->high.x); + container->low.x = Min(box1->low.x, box2->low.x); + container->high.y = Max(box1->high.y, box2->high.y); + container->low.y = Min(box1->low.y, box2->low.y); + + PG_RETURN_BOX_P(container); +} + /* box_diagonal - * returns a line segment which happens to be the * positive-slope diagonal of "box". */ Datum box_diagonal(PG_FUNCTION_ARGS) { BOX *box = PG_GETARG_BOX_P(0); LSEG *result = (LSEG *) palloc(sizeof(LSEG)); @@ -3205,30 +3331,20 @@ on_ps_internal(Point *pt, LSEG *lseg) Datum on_pb(PG_FUNCTION_ARGS) { Point *pt = PG_GETARG_POINT_P(0); BOX *box = PG_GETARG_BOX_P(1); PG_RETURN_BOOL(pt->x <= box->high.x && pt->x >= box->low.x && pt->y <= box->high.y && pt->y >= box->low.y); } -Datum -box_contain_pt(PG_FUNCTION_ARGS) -{ - BOX *box = PG_GETARG_BOX_P(0); - Point *pt = PG_GETARG_POINT_P(1); - - PG_RETURN_BOOL(pt->x <= box->high.x && pt->x >= box->low.x && - pt->y <= box->high.y && pt->y >= box->low.y); -} - /* on_ppath - * Whether a point lies within (on) a polyline. * If open, we have to (groan) check each segment. * (uses same algorithm as for point intersecting segment - tgl 1997-07-09) * If closed, we use the old O(n) ray method for point-in-polygon. * The ray is horizontal, from pt out to the right. * Each segment that crosses the ray counts as an * intersection; note that an endpoint or edge may touch * but not cross. * (we can do p-in-p in lg(n), but it takes preprocessing) @@ -4666,24 +4782,42 @@ circle_send(PG_FUNCTION_ARGS) CIRCLE *circle = PG_GETARG_CIRCLE_P(0); StringInfoData buf; pq_begintypsend(&buf); pq_sendfloat8(&buf, circle->center.x); pq_sendfloat8(&buf, circle->center.y); pq_sendfloat8(&buf, circle->radius); PG_RETURN_BYTEA_P(pq_endtypsend(&buf)); } +/* cr_circle - make circle from point of center and distance + */ +Datum +cr_circle(PG_FUNCTION_ARGS) +{ + Point *center = PG_GETARG_POINT_P(0); + float8 radius = PG_GETARG_FLOAT8(1); + CIRCLE *result; + + result = (CIRCLE *) palloc(sizeof(CIRCLE)); + + result->center.x = center->x; + result->center.y = center->y; + result->radius = radius; + + PG_RETURN_CIRCLE_P(result); +} + /*---------------------------------------------------------- * Relational operators for CIRCLEs. - * <, >, <=, >=, and == are based on circle area. + * <, >, <=, >=, and = are based on circle area. *---------------------------------------------------------*/ /* circles identical? */ Datum circle_same(PG_FUNCTION_ARGS) { CIRCLE *circle1 = PG_GETARG_CIRCLE_P(0); CIRCLE *circle2 = PG_GETARG_CIRCLE_P(1); @@ -5093,78 +5227,82 @@ circle_center(PG_FUNCTION_ARGS) /* circle_ar - returns the area of the circle. */ static double circle_ar(CIRCLE *circle) { return M_PI * (circle->radius * circle->radius); } /*---------------------------------------------------------- - * Conversion operators. + * Type conversions *---------------------------------------------------------*/ +/* point_box - convert point to empty box + */ Datum -cr_circle(PG_FUNCTION_ARGS) +point_box(PG_FUNCTION_ARGS) { - Point *center = PG_GETARG_POINT_P(0); - float8 radius = PG_GETARG_FLOAT8(1); - CIRCLE *result; + Point *pt = PG_GETARG_POINT_P(0); + BOX *box; - result = (CIRCLE *) palloc(sizeof(CIRCLE)); + box = (BOX *) palloc(sizeof(BOX)); - result->center.x = center->x; - result->center.y = center->y; - result->radius = radius; + box->high.x = pt->x; + box->low.x = pt->x; + box->high.y = pt->y; + box->low.y = pt->y; - PG_RETURN_CIRCLE_P(result); + PG_RETURN_BOX_P(box); } +/* circle_box - convert circle to box + */ Datum circle_box(PG_FUNCTION_ARGS) { CIRCLE *circle = PG_GETARG_CIRCLE_P(0); BOX *box; double delta; box = (BOX *) palloc(sizeof(BOX)); delta = circle->radius / sqrt(2.0); box->high.x = circle->center.x + delta; box->low.x = circle->center.x - delta; box->high.y = circle->center.y + delta; box->low.y = circle->center.y - delta; PG_RETURN_BOX_P(box); } -/* box_circle() - * Convert a box to a circle. +/* box_circle - convert box to circle */ Datum box_circle(PG_FUNCTION_ARGS) { BOX *box = PG_GETARG_BOX_P(0); CIRCLE *circle; circle = (CIRCLE *) palloc(sizeof(CIRCLE)); circle->center.x = (box->high.x + box->low.x) / 2; circle->center.y = (box->high.y + box->low.y) / 2; circle->radius = point_dt(&circle->center, &box->high); PG_RETURN_CIRCLE_P(circle); } - +/* circle_poly - convert circle to polygon + */ Datum circle_poly(PG_FUNCTION_ARGS) { int32 npts = PG_GETARG_INT32(0); CIRCLE *circle = PG_GETARG_CIRCLE_P(1); POLYGON *poly; int base_size, size; int i; double angle; diff --git a/src/backend/utils/adt/network.c b/src/backend/utils/adt/network.c index 3a705da..fa9efcd 100644 --- a/src/backend/utils/adt/network.c +++ b/src/backend/utils/adt/network.c @@ -881,20 +881,72 @@ network_hostmask(PG_FUNCTION_ARGS) } ip_family(dst) = ip_family(ip); ip_bits(dst) = ip_maxbits(ip); SET_INET_VARSIZE(dst); PG_RETURN_INET_P(dst); } /* + * Returns true if the addresses are from the same family, or false. Used to + * determine the addresses have a common union or not. + */ +Datum +inet_same_family(PG_FUNCTION_ARGS) +{ + inet *a1 = PG_GETARG_INET_PP(0); + inet *a2 = PG_GETARG_INET_PP(1); + + PG_RETURN_BOOL(ip_family(a1) == ip_family(a2)); +} + +/* + * Returns the smallest CIDR which contains both of the inputs. + */ +Datum +inet_merge(PG_FUNCTION_ARGS) +{ + inet *a1 = PG_GETARG_INET_PP(0), + *a2 = PG_GETARG_INET_PP(1), + *result; + int commonbits; + + if (ip_family(a1) != ip_family(a2)) + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("cannot merge addresses from different families"))); + + commonbits = bitncommon(ip_addr(a1), ip_addr(a2), + Min(ip_bits(a1), ip_bits(a2))); + + /* Make sure any unused bits are zeroed. */ + result = (inet *) palloc0(sizeof(inet)); + + ip_family(result) = ip_family(a1); + ip_bits(result) = commonbits; + + /* Clone appropriate bytes of the address. */ + if (commonbits > 0) + memcpy(ip_addr(result), ip_addr(a1), (commonbits + 7) / 8); + + /* Clean any unwanted bits in the last partial byte. */ + if (commonbits % 8 != 0) + ip_addr(result)[commonbits / 8] &= ~(0xFF >> (commonbits % 8)); + + /* Set varlena header correctly. */ + SET_INET_VARSIZE(result); + + PG_RETURN_INET_P(result); +} + +/* * Convert a value of a network datatype to an approximate scalar value. * This is used for estimating selectivities of inequality operators * involving network types. */ double convert_network_to_scalar(Datum value, Oid typid) { switch (typid) { case INETOID: diff --git a/src/backend/utils/adt/rangetypes.c b/src/backend/utils/adt/rangetypes.c index c037b05..5f052ee 100644 --- a/src/backend/utils/adt/rangetypes.c +++ b/src/backend/utils/adt/rangetypes.c @@ -1000,67 +1000,88 @@ range_minus(PG_FUNCTION_ARGS) upper2.inclusive = !upper2.inclusive; upper2.lower = true; /* it will become the lower bound */ PG_RETURN_RANGE(make_range(typcache, &upper2, &upper1, false)); } elog(ERROR, "unexpected case in range_minus"); PG_RETURN_NULL(); } /* set union */ -Datum -range_union(PG_FUNCTION_ARGS) +static RangeType * +range_union_internal(TypeCacheEntry *typcache, RangeType *r1, RangeType *r2, + bool strict) { - RangeType *r1 = PG_GETARG_RANGE(0); - RangeType *r2 = PG_GETARG_RANGE(1); - TypeCacheEntry *typcache; RangeBound lower1, lower2; RangeBound upper1, upper2; bool empty1, empty2; RangeBound *result_lower; RangeBound *result_upper; /* 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)); - range_deserialize(typcache, r1, &lower1, &upper1, &empty1); range_deserialize(typcache, r2, &lower2, &upper2, &empty2); /* if either is empty, the other is the correct answer */ if (empty1) - PG_RETURN_RANGE(r2); + return r2; if (empty2) - PG_RETURN_RANGE(r1); + return r1; - if (!DatumGetBool(range_overlaps(fcinfo)) && - !DatumGetBool(range_adjacent(fcinfo))) + if (strict && + !DatumGetBool(range_overlaps_internal(typcache, r1, r2)) && + !DatumGetBool(range_adjacent_internal(typcache, r1, r2))) ereport(ERROR, (errcode(ERRCODE_DATA_EXCEPTION), errmsg("result of range union would not be contiguous"))); if (range_cmp_bounds(typcache, &lower1, &lower2) < 0) result_lower = &lower1; else result_lower = &lower2; if (range_cmp_bounds(typcache, &upper1, &upper2) > 0) result_upper = &upper1; else result_upper = &upper2; - PG_RETURN_RANGE(make_range(typcache, result_lower, result_upper, false)); + return make_range(typcache, result_lower, result_upper, false); +} + +Datum +range_union(PG_FUNCTION_ARGS) +{ + RangeType *r1 = PG_GETARG_RANGE(0); + RangeType *r2 = PG_GETARG_RANGE(1); + TypeCacheEntry *typcache; + + typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1)); + + PG_RETURN_RANGE(range_union_internal(typcache, r1, r2, true)); +} + +Datum +range_merge(PG_FUNCTION_ARGS) +{ + RangeType *r1 = PG_GETARG_RANGE(0); + RangeType *r2 = PG_GETARG_RANGE(1); + TypeCacheEntry *typcache; + + typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1)); + + PG_RETURN_RANGE(range_union_internal(typcache, r1, r2, false)); } /* set intersection */ Datum range_intersect(PG_FUNCTION_ARGS) { RangeType *r1 = PG_GETARG_RANGE(0); RangeType *r2 = PG_GETARG_RANGE(1); TypeCacheEntry *typcache; RangeBound lower1, diff --git a/src/bin/initdb/initdb.c b/src/bin/initdb/initdb.c index 18614e7..a21c3fa 100644 --- a/src/bin/initdb/initdb.c +++ b/src/bin/initdb/initdb.c @@ -1884,20 +1884,21 @@ setup_description(void) /* Create default descriptions for operator implementation functions */ PG_CMD_PUTS("WITH funcdescs AS ( " "SELECT p.oid as p_oid, oprname, " "coalesce(obj_description(o.oid, 'pg_operator'),'') as opdesc " "FROM pg_proc p JOIN pg_operator o ON oprcode = p.oid ) " "INSERT INTO pg_description " " SELECT p_oid, 'pg_proc'::regclass, 0, " " 'implementation of ' || oprname || ' operator' " " FROM funcdescs " " WHERE opdesc NOT LIKE 'deprecated%' AND " + " opdesc NOT LIKE 'same as %' AND " " NOT EXISTS (SELECT 1 FROM pg_description " " WHERE objoid = p_oid AND classoid = 'pg_proc'::regclass);\n"); PG_CMD_CLOSE; check_ok(); } #ifdef HAVE_LOCALE_T /* 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/access/gist.h b/src/include/access/gist.h index 01f0a70..dd773c1 100644 --- a/src/include/access/gist.h +++ b/src/include/access/gist.h @@ -29,40 +29,20 @@ #define GIST_UNION_PROC 2 #define GIST_COMPRESS_PROC 3 #define GIST_DECOMPRESS_PROC 4 #define GIST_PENALTY_PROC 5 #define GIST_PICKSPLIT_PROC 6 #define GIST_EQUAL_PROC 7 #define GIST_DISTANCE_PROC 8 #define GISTNProcs 8 /* - * strategy numbers for GiST opclasses that want to implement the old - * RTREE behavior. - */ -#define RTLeftStrategyNumber 1 -#define RTOverLeftStrategyNumber 2 -#define RTOverlapStrategyNumber 3 -#define RTOverRightStrategyNumber 4 -#define RTRightStrategyNumber 5 -#define RTSameStrategyNumber 6 -#define RTContainsStrategyNumber 7 /* for @> */ -#define RTContainedByStrategyNumber 8 /* for <@ */ -#define RTOverBelowStrategyNumber 9 -#define RTBelowStrategyNumber 10 -#define RTAboveStrategyNumber 11 -#define RTOverAboveStrategyNumber 12 -#define RTOldContainsStrategyNumber 13 /* for old spelling of @> */ -#define RTOldContainedByStrategyNumber 14 /* for old spelling of <@ */ -#define RTKNNSearchStrategyNumber 15 - -/* * Page opaque data in a GiST index page. */ #define F_LEAF (1 << 0) /* leaf page */ #define F_DELETED (1 << 1) /* the page has been deleted */ #define F_TUPLES_DELETED (1 << 2) /* some tuples on the page are dead */ #define F_FOLLOW_RIGHT (1 << 3) /* page to the right has no downlink */ typedef XLogRecPtr GistNSN; /* diff --git a/src/include/access/skey.h b/src/include/access/skey.h index eeee1f4..c5ac298 100644 --- a/src/include/access/skey.h +++ b/src/include/access/skey.h @@ -34,20 +34,54 @@ typedef uint16 StrategyNumber; #define BTLessStrategyNumber 1 #define BTLessEqualStrategyNumber 2 #define BTEqualStrategyNumber 3 #define BTGreaterEqualStrategyNumber 4 #define BTGreaterStrategyNumber 5 #define BTMaxStrategyNumber 5 /* + * Strategy numbers for opclasses that want to implement the old RTREE behavior. + * Operator strategy numbers used in the GiST, SP-GiST, GIN, BRIN opclasses. + * New numbers are chosen to match up operator names with existing usages. + */ +#define RTLeftStrategyNumber 1 /* for << */ +#define RTOverLeftStrategyNumber 2 /* for &< */ +#define RTOverlapStrategyNumber 3 /* for && */ +#define RTOverRightStrategyNumber 4 /* for &> */ +#define RTRightStrategyNumber 5 /* for >> */ +#define RTSameStrategyNumber 6 /* for ~= */ +#define RTContainsStrategyNumber 7 /* for @> */ +#define RTContainedByStrategyNumber 8 /* for <@ */ +#define RTOverBelowStrategyNumber 9 /* for &<| */ +#define RTBelowStrategyNumber 10 /* for <<| */ +#define RTAboveStrategyNumber 11 /* for |>> */ +#define RTOverAboveStrategyNumber 12 /* for |&> */ +#define RTOldContainsStrategyNumber 13 /* for old spelling of @> */ +#define RTOldContainedByStrategyNumber 14 /* for old spelling of <@ */ +#define RTKNNSearchStrategyNumber 15 +#define RTContainsElemStrategyNumber 16 /* for range types @> elem */ +#define RTAdjacentStrategyNumber 17 /* for -|- */ +#define RTEqualStrategyNumber 18 /* for = */ +#define RTNotEqualStrategyNumber 19 /* for != */ +#define RTLessStrategyNumber 20 /* for < */ +#define RTLessEqualStrategyNumber 21 /* for <= */ +#define RTGreaterStrategyNumber 22 /* for > */ +#define RTGreaterEqualStrategyNumber 23 /* for >= */ +#define RTContainsNotEqualStrategyNumber 24 /* for inet >> */ +#define RTContainsEqualStrategyNumber 25 /* for inet >>= */ +#define RTContainedByNotEqualStrategyNumber 26 /* for inet << */ +#define RTContainedByEqualStrategyNumber 27 /* for inet <<= */ + + +/* * A ScanKey represents the application of a comparison operator between * a table or index column and a constant. When it's part of an array of * ScanKeys, the comparison conditions are implicitly ANDed. The index * column is the left argument of the operator, if it's a binary operator. * (The data structure can support unary indexable operators too; in that * case sk_argument would go unused. This is not currently implemented.) * * For an index scan, sk_strategy and sk_subtype must be set correctly for * the operator. When using a ScanKey in a heap scan, these fields are not * used and may be set to InvalidStrategy/InvalidOid. diff --git a/src/include/catalog/pg_am.h b/src/include/catalog/pg_am.h index 0531222..4d8007e 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 8 f t f f t t f t t t f 0 gistinsert gistbeginscan gistgettuple gistgetbitmap gistrescan gistendscan gistmarkpos gistrestrpos gistbuild gistbuildempty gistbulkdelete gistvacuumcleanup - 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..d3a6360 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 ( 4060 869 869 3 s 3552 3580 0 )); +DATA(insert ( 4060 869 869 18 s 1201 3580 0 )); +DATA(insert ( 4060 869 869 24 s 933 3580 0 )); +DATA(insert ( 4060 869 869 25 s 934 3580 0 )); +DATA(insert ( 4060 869 869 26 s 931 3580 0 )); +DATA(insert ( 4060 869 869 27 s 932 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 ( 4063 3831 3831 1 s 3893 3580 0 )); +DATA(insert ( 4063 3831 3831 2 s 3895 3580 0 )); +DATA(insert ( 4063 3831 3831 3 s 3888 3580 0 )); +DATA(insert ( 4063 3831 3831 4 s 3896 3580 0 )); +DATA(insert ( 4063 3831 3831 5 s 3894 3580 0 )); +DATA(insert ( 4063 3831 3831 7 s 3890 3580 0 )); +DATA(insert ( 4063 3831 3831 8 s 3892 3580 0 )); +DATA(insert ( 4063 3831 2283 16 s 3889 3580 0 )); +DATA(insert ( 4063 3831 3831 17 s 3897 3580 0 )); +DATA(insert ( 4063 3831 3831 18 s 3882 3580 0 )); +DATA(insert ( 4063 3831 3831 20 s 3884 3580 0 )); +DATA(insert ( 4063 3831 3831 21 s 3885 3580 0 )); +DATA(insert ( 4063 3831 3831 22 s 3887 3580 0 )); +DATA(insert ( 4063 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 ( 4066 603 603 1 s 493 3580 0 )); +DATA(insert ( 4066 603 603 2 s 494 3580 0 )); +DATA(insert ( 4066 603 603 3 s 500 3580 0 )); +DATA(insert ( 4066 603 603 4 s 495 3580 0 )); +DATA(insert ( 4066 603 603 5 s 496 3580 0 )); +DATA(insert ( 4066 603 603 6 s 499 3580 0 )); +DATA(insert ( 4066 603 603 7 s 498 3580 0 )); +DATA(insert ( 4066 603 603 8 s 497 3580 0 )); +DATA(insert ( 4066 603 603 9 s 2571 3580 0 )); +DATA(insert ( 4066 603 603 10 s 2570 3580 0 )); +DATA(insert ( 4066 603 603 11 s 2573 3580 0 )); +DATA(insert ( 4066 603 603 12 s 2572 3580 0 )); +DATA(insert ( 4066 603 603 13 s 2863 3580 0 )); +DATA(insert ( 4066 603 603 14 s 2862 3580 0 )); +DATA(insert ( 4066 603 600 1 s 4092 3580 0 )); +DATA(insert ( 4066 603 600 2 s 4093 3580 0 )); +DATA(insert ( 4066 603 600 3 s 4100 3580 0 )); +DATA(insert ( 4066 603 600 4 s 4095 3580 0 )); +DATA(insert ( 4066 603 600 5 s 4094 3580 0 )); +DATA(insert ( 4066 603 600 7 s 433 3580 0 )); +DATA(insert ( 4066 603 600 9 s 4097 3580 0 )); +DATA(insert ( 4066 603 600 10 s 4096 3580 0 )); +DATA(insert ( 4066 603 600 11 s 4098 3580 0 )); +DATA(insert ( 4066 603 600 12 s 4099 3580 0 )); +/* inclusion point */ +DATA(insert ( 4066 600 600 1 s 507 3580 0 )); +DATA(insert ( 4066 600 600 5 s 508 3580 0 )); +DATA(insert ( 4066 600 600 6 s 510 3580 0 )); +DATA(insert ( 4066 600 600 10 s 509 3580 0 )); +DATA(insert ( 4066 600 600 11 s 506 3580 0 )); +DATA(insert ( 4066 600 603 3 s 4101 3580 0 )); +DATA(insert ( 4066 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 49d3d13..5e557e5 100644 --- a/src/include/catalog/pg_amproc.h +++ b/src/include/catalog/pg_amproc.h @@ -629,20 +629,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 ( 4060 869 869 1 3387 )); +DATA(insert ( 4060 869 869 2 3388 )); +DATA(insert ( 4060 869 869 3 3389 )); +DATA(insert ( 4060 869 869 4 3390 )); +DATA(insert ( 4060 869 869 11 4061 )); +DATA(insert ( 4060 869 869 12 4071 )); +DATA(insert ( 4060 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 */ @@ -777,21 +785,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 ( 4063 3831 3831 1 3387 )); +DATA(insert ( 4063 3831 3831 2 3388 )); +DATA(insert ( 4063 3831 3831 3 3389 )); +DATA(insert ( 4063 3831 3831 4 3390 )); +DATA(insert ( 4063 3831 3831 11 4057 )); +DATA(insert ( 4063 3831 3831 14 3859 )); +DATA(insert ( 4063 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 ( 4066 603 603 1 3387 )); +DATA(insert ( 4066 603 603 2 3388 )); +DATA(insert ( 4066 603 603 3 3389 )); +DATA(insert ( 4066 603 603 4 3390 )); +DATA(insert ( 4066 603 603 11 4067 )); +DATA(insert ( 4066 603 603 14 187 )); +/* inclusion point */ +DATA(insert ( 4066 600 600 1 3387 )); +DATA(insert ( 4066 600 600 2 3388 )); +DATA(insert ( 4066 600 600 3 3389 )); +DATA(insert ( 4066 600 600 4 3390 )); +DATA(insert ( 4066 600 600 11 4067 )); +DATA(insert ( 4066 600 600 13 4091 )); +DATA(insert ( 4066 600 600 14 193 )); #endif /* PG_AMPROC_H */ diff --git a/src/include/catalog/pg_cast.h b/src/include/catalog/pg_cast.h index b314369..6d54c15 100644 --- a/src/include/catalog/pg_cast.h +++ b/src/include/catalog/pg_cast.h @@ -266,20 +266,21 @@ DATA(insert ( 1186 1083 1419 a f )); DATA(insert ( 1266 1083 2046 a f )); /* Cross-category casts between int4 and abstime, reltime */ DATA(insert ( 23 702 0 e b )); DATA(insert ( 702 23 0 e b )); DATA(insert ( 23 703 0 e b )); DATA(insert ( 703 23 0 e b )); /* * Geometric category */ +DATA(insert ( 600 603 4091 a f )); DATA(insert ( 601 600 1532 e f )); DATA(insert ( 602 600 1533 e f )); DATA(insert ( 602 604 1449 a f )); DATA(insert ( 603 600 1534 e f )); DATA(insert ( 603 601 1541 e f )); DATA(insert ( 603 604 1448 a f )); DATA(insert ( 603 718 1479 e f )); DATA(insert ( 604 600 1540 e f )); DATA(insert ( 604 602 1447 a f )); DATA(insert ( 604 603 1446 e f )); diff --git a/src/include/catalog/pg_opclass.h b/src/include/catalog/pg_opclass.h index b3acef6..b3b2a91 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 4060 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 4063 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 4066 603 t 0 )); +DATA(insert ( 3580 point_box_inclusion_ops PGNSP PGUID 4066 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_operator.h b/src/include/catalog/pg_operator.h index af991d3..f7fdbb2 100644 --- a/src/include/catalog/pg_operator.h +++ b/src/include/catalog/pg_operator.h @@ -251,22 +251,42 @@ DESCR("is above"); DATA(insert OID = 507 ( "<<" PGNSP PGUID b f f 600 600 16 0 0 point_left positionsel positionjoinsel )); DESCR("is left of"); DATA(insert OID = 508 ( ">>" PGNSP PGUID b f f 600 600 16 0 0 point_right positionsel positionjoinsel )); DESCR("is right of"); DATA(insert OID = 509 ( "<^" PGNSP PGUID b f f 600 600 16 0 0 point_below positionsel positionjoinsel )); DESCR("is below"); DATA(insert OID = 510 ( "~=" PGNSP PGUID b f f 600 600 16 510 713 point_eq eqsel eqjoinsel )); DESCR("same as"); DATA(insert OID = 511 ( "<@" PGNSP PGUID b f f 600 603 16 433 0 on_pb contsel contjoinsel )); DESCR("point inside box"); +DATA(insert OID = 4092 ( "<<" PGNSP PGUID b f f 603 600 16 0 0 box_left_pt positionsel positionjoinsel )); +DESCR("is left of"); +DATA(insert OID = 4093 ( "&<" PGNSP PGUID b f f 603 600 16 0 0 box_overleft_pt positionsel positionjoinsel )); +DESCR("overlaps or is left of"); +DATA(insert OID = 4094 ( ">>" PGNSP PGUID b f f 603 600 16 0 0 box_right_pt positionsel positionjoinsel )); +DESCR("is right of"); +DATA(insert OID = 4095 ( "&>" PGNSP PGUID b f f 603 600 16 0 0 box_overright_pt positionsel positionjoinsel )); +DESCR("overlaps or is right of"); +DATA(insert OID = 4096 ( "<<|" PGNSP PGUID b f f 603 600 16 0 0 box_below_pt positionsel positionjoinsel )); +DESCR("is below"); +DATA(insert OID = 4097 ( "&<|" PGNSP PGUID b f f 603 600 16 0 0 box_overbelow_pt positionsel positionjoinsel )); +DESCR("overlaps or is below"); +DATA(insert OID = 4098 ( "|>>" PGNSP PGUID b f f 603 600 16 0 0 box_above_pt positionsel positionjoinsel )); +DESCR("is above"); +DATA(insert OID = 4099 ( "|&>" PGNSP PGUID b f f 603 600 16 0 0 box_overabove_pt positionsel positionjoinsel )); +DESCR("overlaps or is above"); DATA(insert OID = 433 ( "@>" PGNSP PGUID b f f 603 600 16 511 0 box_contain_pt contsel contjoinsel )); DESCR("contains"); +DATA(insert OID = 4100 ( "&&" PGNSP PGUID b f f 603 600 16 4101 0 box_contain_pt contsel contjoinsel )); +DESCR("same as @>"); +DATA(insert OID = 4101 ( "&&" PGNSP PGUID b f f 600 603 16 4100 0 on_pb contsel contjoinsel )); +DESCR("same as <@"); DATA(insert OID = 512 ( "<@" PGNSP PGUID b f f 600 602 16 755 0 on_ppath - - )); DESCR("point within closed path, or point on open path"); DATA(insert OID = 513 ( "@@" PGNSP PGUID l f f 0 603 600 0 0 box_center - - )); DESCR("center of"); DATA(insert OID = 514 ( "*" PGNSP PGUID b f f 23 23 23 514 0 int4mul - - )); DESCR("multiply"); DATA(insert OID = 517 ( "<->" PGNSP PGUID b f f 600 600 701 517 0 point_distance - - )); DESCR("distance between"); DATA(insert OID = 518 ( "<>" PGNSP PGUID b f f 23 23 16 518 96 int4ne neqsel neqjoinsel )); DESCR("not equal"); diff --git a/src/include/catalog/pg_opfamily.h b/src/include/catalog/pg_opfamily.h index 97ffa32..7d0eb8b 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 = 4060 ( 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 = 4063 ( 3580 range_inclusion_ops PGNSP PGUID )); DATA(insert OID = 4082 ( 3580 pg_lsn_minmax_ops PGNSP PGUID )); +DATA(insert OID = 4066 ( 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 9edfdb8..c6f33c3 100644 --- a/src/include/catalog/pg_proc.h +++ b/src/include/catalog/pg_proc.h @@ -334,20 +334,28 @@ DATA(insert OID = 182 ( int24mi PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 23 DATA(insert OID = 183 ( int42mi PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 23 "23 21" _null_ _null_ _null_ _null_ int42mi _null_ _null_ _null_ )); DATA(insert OID = 184 ( oideq PGNSP PGUID 12 1 0 0 0 f f f t t f i 2 0 16 "26 26" _null_ _null_ _null_ _null_ oideq _null_ _null_ _null_ )); DATA(insert OID = 185 ( oidne PGNSP PGUID 12 1 0 0 0 f f f t t f i 2 0 16 "26 26" _null_ _null_ _null_ _null_ oidne _null_ _null_ _null_ )); DATA(insert OID = 186 ( box_same PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "603 603" _null_ _null_ _null_ _null_ box_same _null_ _null_ _null_ )); DATA(insert OID = 187 ( box_contain PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "603 603" _null_ _null_ _null_ _null_ box_contain _null_ _null_ _null_ )); DATA(insert OID = 188 ( box_left PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "603 603" _null_ _null_ _null_ _null_ box_left _null_ _null_ _null_ )); DATA(insert OID = 189 ( box_overleft PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "603 603" _null_ _null_ _null_ _null_ box_overleft _null_ _null_ _null_ )); DATA(insert OID = 190 ( box_overright PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "603 603" _null_ _null_ _null_ _null_ box_overright _null_ _null_ _null_ )); DATA(insert OID = 191 ( box_right PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "603 603" _null_ _null_ _null_ _null_ box_right _null_ _null_ _null_ )); DATA(insert OID = 192 ( box_contained PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "603 603" _null_ _null_ _null_ _null_ box_contained _null_ _null_ _null_ )); +DATA(insert OID = 4083 ( box_left_pt PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "603 600" _null_ _null_ _null_ _null_ box_left_pt _null_ _null_ _null_ )); +DATA(insert OID = 4084 ( box_overleft_pt PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "603 600" _null_ _null_ _null_ _null_ box_overleft_pt _null_ _null_ _null_ )); +DATA(insert OID = 4085 ( box_right_pt PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "603 600" _null_ _null_ _null_ _null_ box_right_pt _null_ _null_ _null_ )); +DATA(insert OID = 4086 ( box_overright_pt PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "603 600" _null_ _null_ _null_ _null_ box_overright_pt _null_ _null_ _null_ )); +DATA(insert OID = 4087 ( box_below_pt PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "603 600" _null_ _null_ _null_ _null_ box_below_pt _null_ _null_ _null_ )); +DATA(insert OID = 4088 ( box_overbelow_pt PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "603 600" _null_ _null_ _null_ _null_ box_overbelow_pt _null_ _null_ _null_ )); +DATA(insert OID = 4089 ( box_above_pt PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "603 600" _null_ _null_ _null_ _null_ box_above_pt _null_ _null_ _null_ )); +DATA(insert OID = 4090 ( box_overabove_pt PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "603 600" _null_ _null_ _null_ _null_ box_overabove_pt _null_ _null_ _null_ )); DATA(insert OID = 193 ( box_contain_pt PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "603 600" _null_ _null_ _null_ _null_ box_contain_pt _null_ _null_ _null_ )); DATA(insert OID = 195 ( pg_node_tree_in PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 194 "2275" _null_ _null_ _null_ _null_ pg_node_tree_in _null_ _null_ _null_ )); DESCR("I/O"); DATA(insert OID = 196 ( pg_node_tree_out PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 2275 "194" _null_ _null_ _null_ _null_ pg_node_tree_out _null_ _null_ _null_ )); DESCR("I/O"); DATA(insert OID = 197 ( pg_node_tree_recv PGNSP PGUID 12 1 0 0 0 f f f f t f s 1 0 194 "2281" _null_ _null_ _null_ _null_ pg_node_tree_recv _null_ _null_ _null_ )); DESCR("I/O"); DATA(insert OID = 198 ( pg_node_tree_send PGNSP PGUID 12 1 0 0 0 f f f f t f s 1 0 17 "194" _null_ _null_ _null_ _null_ pg_node_tree_send _null_ _null_ _null_ )); DESCR("I/O"); @@ -1123,20 +1131,22 @@ DATA(insert OID = 973 ( path_inter PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 DATA(insert OID = 975 ( area PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 701 "603" _null_ _null_ _null_ _null_ box_area _null_ _null_ _null_ )); DESCR("box area"); DATA(insert OID = 976 ( width PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 701 "603" _null_ _null_ _null_ _null_ box_width _null_ _null_ _null_ )); DESCR("box width"); DATA(insert OID = 977 ( height PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 701 "603" _null_ _null_ _null_ _null_ box_height _null_ _null_ _null_ )); DESCR("box height"); DATA(insert OID = 978 ( box_distance PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 701 "603 603" _null_ _null_ _null_ _null_ box_distance _null_ _null_ _null_ )); DATA(insert OID = 979 ( area PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 701 "602" _null_ _null_ _null_ _null_ path_area _null_ _null_ _null_ )); DESCR("area of a closed path"); DATA(insert OID = 980 ( box_intersect PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 603 "603 603" _null_ _null_ _null_ _null_ box_intersect _null_ _null_ _null_ )); +DATA(insert OID = 4067 ( boxes_bound_box PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 603 "603 603" _null_ _null_ _null_ _null_ boxes_bound_box _null_ _null_ _null_ )); +DESCR("bounding box of two boxes"); DATA(insert OID = 981 ( diagonal PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 601 "603" _null_ _null_ _null_ _null_ box_diagonal _null_ _null_ _null_ )); DESCR("box diagonal"); DATA(insert OID = 982 ( path_n_lt PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "602 602" _null_ _null_ _null_ _null_ path_n_lt _null_ _null_ _null_ )); DATA(insert OID = 983 ( path_n_gt PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "602 602" _null_ _null_ _null_ _null_ path_n_gt _null_ _null_ _null_ )); DATA(insert OID = 984 ( path_n_eq PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "602 602" _null_ _null_ _null_ _null_ path_n_eq _null_ _null_ _null_ )); DATA(insert OID = 985 ( path_n_le PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "602 602" _null_ _null_ _null_ _null_ path_n_le _null_ _null_ _null_ )); DATA(insert OID = 986 ( path_n_ge PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "602 602" _null_ _null_ _null_ _null_ path_n_ge _null_ _null_ _null_ )); DATA(insert OID = 987 ( path_length PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 701 "602" _null_ _null_ _null_ _null_ path_length _null_ _null_ _null_ )); DATA(insert OID = 988 ( point_ne PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "600 600" _null_ _null_ _null_ _null_ point_ne _null_ _null_ _null_ )); DATA(insert OID = 989 ( point_vert PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "600 600" _null_ _null_ _null_ _null_ point_vert _null_ _null_ _null_ )); @@ -1723,20 +1733,22 @@ DATA(insert OID = 1471 ( circle_distance PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 DATA(insert OID = 1472 ( circle_center PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 600 "718" _null_ _null_ _null_ _null_ circle_center _null_ _null_ _null_ )); DATA(insert OID = 1473 ( circle PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 718 "600 701" _null_ _null_ _null_ _null_ cr_circle _null_ _null_ _null_ )); DESCR("convert point and radius to circle"); DATA(insert OID = 1474 ( circle PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 718 "604" _null_ _null_ _null_ _null_ poly_circle _null_ _null_ _null_ )); DESCR("convert polygon to circle"); DATA(insert OID = 1475 ( polygon PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 604 "23 718" _null_ _null_ _null_ _null_ circle_poly _null_ _null_ _null_ )); DESCR("convert vertex count and circle to polygon"); DATA(insert OID = 1476 ( dist_pc PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 701 "600 718" _null_ _null_ _null_ _null_ dist_pc _null_ _null_ _null_ )); DATA(insert OID = 1477 ( circle_contain_pt PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "718 600" _null_ _null_ _null_ _null_ circle_contain_pt _null_ _null_ _null_ )); DATA(insert OID = 1478 ( pt_contained_circle PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "600 718" _null_ _null_ _null_ _null_ pt_contained_circle _null_ _null_ _null_ )); +DATA(insert OID = 4091 ( box PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 603 "600" _null_ _null_ _null_ _null_ point_box _null_ _null_ _null_ )); +DESCR("convert point to empty box"); DATA(insert OID = 1479 ( circle PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 718 "603" _null_ _null_ _null_ _null_ box_circle _null_ _null_ _null_ )); DESCR("convert box to circle"); DATA(insert OID = 1480 ( box PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 603 "718" _null_ _null_ _null_ _null_ circle_box _null_ _null_ _null_ )); DESCR("convert circle to box"); DATA(insert OID = 1481 ( tinterval PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 704 "702 702" _null_ _null_ _null_ _null_ mktinterval _null_ _null_ _null_ )); DESCR("convert to tinterval"); DATA(insert OID = 1482 ( lseg_ne PGNSP PGUID 12 1 0 0 0 f f f t t f i 2 0 16 "601 601" _null_ _null_ _null_ _null_ lseg_ne _null_ _null_ _null_ )); DATA(insert OID = 1483 ( lseg_lt PGNSP PGUID 12 1 0 0 0 f f f t t f i 2 0 16 "601 601" _null_ _null_ _null_ _null_ lseg_lt _null_ _null_ _null_ )); DATA(insert OID = 1484 ( lseg_le PGNSP PGUID 12 1 0 0 0 f f f t t f i 2 0 16 "601 601" _null_ _null_ _null_ _null_ lseg_le _null_ _null_ _null_ )); @@ -2211,20 +2223,24 @@ DESCR("inet address of the server"); DATA(insert OID = 2199 ( inet_server_port PGNSP PGUID 12 1 0 0 0 f f f f f f s 0 0 23 "" _null_ _null_ _null_ _null_ inet_server_port _null_ _null_ _null_ )); DESCR("server's port number for this connection"); DATA(insert OID = 2627 ( inetnot PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 869 "869" _null_ _null_ _null_ _null_ inetnot _null_ _null_ _null_ )); DATA(insert OID = 2628 ( inetand PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 869 "869 869" _null_ _null_ _null_ _null_ inetand _null_ _null_ _null_ )); DATA(insert OID = 2629 ( inetor PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 869 "869 869" _null_ _null_ _null_ _null_ inetor _null_ _null_ _null_ )); DATA(insert OID = 2630 ( inetpl PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 869 "869 20" _null_ _null_ _null_ _null_ inetpl _null_ _null_ _null_ )); DATA(insert OID = 2631 ( int8pl_inet PGNSP PGUID 14 1 0 0 0 f f f f t f i 2 0 869 "20 869" _null_ _null_ _null_ _null_ "select $2 + $1" _null_ _null_ _null_ )); DATA(insert OID = 2632 ( inetmi_int8 PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 869 "869 20" _null_ _null_ _null_ _null_ inetmi_int8 _null_ _null_ _null_ )); DATA(insert OID = 2633 ( inetmi PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 20 "869 869" _null_ _null_ _null_ _null_ inetmi _null_ _null_ _null_ )); +DATA(insert OID = 4071 ( inet_same_family PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "869 869" _null_ _null_ _null_ _null_ inet_same_family _null_ _null_ _null_ )); +DESCR("are the addresses from the same family?"); +DATA(insert OID = 4061 ( inet_merge PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 650 "869 869" _null_ _null_ _null_ _null_ inet_merge _null_ _null_ _null_ )); +DESCR("the smallest network which includes both of the given networks"); /* GiST support for inet and cidr */ DATA(insert OID = 3553 ( inet_gist_consistent PGNSP PGUID 12 1 0 0 0 f f f f t f i 5 0 16 "2281 869 23 26 2281" _null_ _null_ _null_ _null_ inet_gist_consistent _null_ _null_ _null_ )); DESCR("GiST support"); DATA(insert OID = 3554 ( inet_gist_union PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 2281 "2281 2281" _null_ _null_ _null_ _null_ inet_gist_union _null_ _null_ _null_ )); DESCR("GiST support"); DATA(insert OID = 3555 ( inet_gist_compress PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 2281 "2281" _null_ _null_ _null_ _null_ inet_gist_compress _null_ _null_ _null_ )); DESCR("GiST support"); DATA(insert OID = 3556 ( inet_gist_decompress PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 2281 "2281" _null_ _null_ _null_ _null_ inet_gist_decompress _null_ _null_ _null_ )); DESCR("GiST support"); @@ -4133,20 +4149,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 = 3387 ( 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 = 3388 ( 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 = 3389 ( 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 = 3390 ( 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_ )); @@ -4891,20 +4917,22 @@ DESCR("implementation of -|- operator"); DATA(insert OID = 3863 ( range_before PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "3831 3831" _null_ _null_ _null_ _null_ range_before _null_ _null_ _null_ )); DESCR("implementation of << operator"); DATA(insert OID = 3864 ( range_after PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "3831 3831" _null_ _null_ _null_ _null_ range_after _null_ _null_ _null_ )); DESCR("implementation of >> operator"); DATA(insert OID = 3865 ( range_overleft PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "3831 3831" _null_ _null_ _null_ _null_ range_overleft _null_ _null_ _null_ )); DESCR("implementation of &< operator"); DATA(insert OID = 3866 ( range_overright PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "3831 3831" _null_ _null_ _null_ _null_ range_overright _null_ _null_ _null_ )); DESCR("implementation of &> operator"); DATA(insert OID = 3867 ( range_union PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 3831 "3831 3831" _null_ _null_ _null_ _null_ range_union _null_ _null_ _null_ )); DESCR("implementation of + operator"); +DATA(insert OID = 4057 ( range_merge PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 3831 "3831 3831" _null_ _null_ _null_ _null_ range_merge _null_ _null_ _null_ )); +DESCR("the smallest range which includes both of the given ranges"); DATA(insert OID = 3868 ( range_intersect PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 3831 "3831 3831" _null_ _null_ _null_ _null_ range_intersect _null_ _null_ _null_ )); DESCR("implementation of * operator"); DATA(insert OID = 3869 ( range_minus PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 3831 "3831 3831" _null_ _null_ _null_ _null_ range_minus _null_ _null_ _null_ )); DESCR("implementation of - operator"); DATA(insert OID = 3870 ( range_cmp PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 23 "3831 3831" _null_ _null_ _null_ _null_ range_cmp _null_ _null_ _null_ )); DESCR("less-equal-greater"); DATA(insert OID = 3871 ( range_lt PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "3831 3831" _null_ _null_ _null_ _null_ range_lt _null_ _null_ _null_ )); DATA(insert OID = 3872 ( range_le PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "3831 3831" _null_ _null_ _null_ _null_ range_le _null_ _null_ _null_ )); DATA(insert OID = 3873 ( range_ge PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "3831 3831" _null_ _null_ _null_ _null_ range_ge _null_ _null_ _null_ )); DATA(insert OID = 3874 ( range_gt PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "3831 3831" _null_ _null_ _null_ _null_ range_gt _null_ _null_ _null_ )); diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h index bc4517d..4a20e9a 100644 --- a/src/include/utils/builtins.h +++ b/src/include/utils/builtins.h @@ -935,20 +935,22 @@ extern Datum inet_client_addr(PG_FUNCTION_ARGS); extern Datum inet_client_port(PG_FUNCTION_ARGS); extern Datum inet_server_addr(PG_FUNCTION_ARGS); extern Datum inet_server_port(PG_FUNCTION_ARGS); extern Datum inetnot(PG_FUNCTION_ARGS); extern Datum inetand(PG_FUNCTION_ARGS); extern Datum inetor(PG_FUNCTION_ARGS); extern Datum inetpl(PG_FUNCTION_ARGS); extern Datum inetmi_int8(PG_FUNCTION_ARGS); extern Datum inetmi(PG_FUNCTION_ARGS); extern void clean_ipv6_addr(int addr_family, char *addr); +extern Datum inet_same_family(PG_FUNCTION_ARGS); +extern Datum inet_merge(PG_FUNCTION_ARGS); /* mac.c */ extern Datum macaddr_in(PG_FUNCTION_ARGS); extern Datum macaddr_out(PG_FUNCTION_ARGS); extern Datum macaddr_recv(PG_FUNCTION_ARGS); extern Datum macaddr_send(PG_FUNCTION_ARGS); extern Datum macaddr_cmp(PG_FUNCTION_ARGS); extern Datum macaddr_lt(PG_FUNCTION_ARGS); extern Datum macaddr_le(PG_FUNCTION_ARGS); extern Datum macaddr_eq(PG_FUNCTION_ARGS); diff --git a/src/include/utils/geo_decls.h b/src/include/utils/geo_decls.h index 0b6d3c3..256079c 100644 --- a/src/include/utils/geo_decls.h +++ b/src/include/utils/geo_decls.h @@ -275,34 +275,43 @@ extern Datum box_overlap(PG_FUNCTION_ARGS); extern Datum box_left(PG_FUNCTION_ARGS); extern Datum box_overleft(PG_FUNCTION_ARGS); extern Datum box_right(PG_FUNCTION_ARGS); extern Datum box_overright(PG_FUNCTION_ARGS); extern Datum box_below(PG_FUNCTION_ARGS); extern Datum box_overbelow(PG_FUNCTION_ARGS); extern Datum box_above(PG_FUNCTION_ARGS); extern Datum box_overabove(PG_FUNCTION_ARGS); extern Datum box_contained(PG_FUNCTION_ARGS); extern Datum box_contain(PG_FUNCTION_ARGS); +extern Datum box_left_pt(PG_FUNCTION_ARGS); +extern Datum box_overleft_pt(PG_FUNCTION_ARGS); +extern Datum box_right_pt(PG_FUNCTION_ARGS); +extern Datum box_overright_pt(PG_FUNCTION_ARGS); +extern Datum box_below_pt(PG_FUNCTION_ARGS); +extern Datum box_overbelow_pt(PG_FUNCTION_ARGS); +extern Datum box_above_pt(PG_FUNCTION_ARGS); +extern Datum box_overabove_pt(PG_FUNCTION_ARGS); extern Datum box_contain_pt(PG_FUNCTION_ARGS); extern Datum box_below_eq(PG_FUNCTION_ARGS); extern Datum box_above_eq(PG_FUNCTION_ARGS); extern Datum box_lt(PG_FUNCTION_ARGS); extern Datum box_gt(PG_FUNCTION_ARGS); extern Datum box_eq(PG_FUNCTION_ARGS); extern Datum box_le(PG_FUNCTION_ARGS); extern Datum box_ge(PG_FUNCTION_ARGS); extern Datum box_area(PG_FUNCTION_ARGS); extern Datum box_width(PG_FUNCTION_ARGS); extern Datum box_height(PG_FUNCTION_ARGS); extern Datum box_distance(PG_FUNCTION_ARGS); extern Datum box_center(PG_FUNCTION_ARGS); extern Datum box_intersect(PG_FUNCTION_ARGS); +extern Datum boxes_bound_box(PG_FUNCTION_ARGS); extern Datum box_diagonal(PG_FUNCTION_ARGS); extern Datum points_box(PG_FUNCTION_ARGS); extern Datum box_add(PG_FUNCTION_ARGS); extern Datum box_sub(PG_FUNCTION_ARGS); extern Datum box_mul(PG_FUNCTION_ARGS); extern Datum box_div(PG_FUNCTION_ARGS); /* public path routines */ extern Datum path_area(PG_FUNCTION_ARGS); extern Datum path_in(PG_FUNCTION_ARGS); @@ -389,20 +398,21 @@ extern Datum circle_sub_pt(PG_FUNCTION_ARGS); extern Datum circle_mul_pt(PG_FUNCTION_ARGS); extern Datum circle_div_pt(PG_FUNCTION_ARGS); extern Datum circle_diameter(PG_FUNCTION_ARGS); extern Datum circle_radius(PG_FUNCTION_ARGS); extern Datum circle_distance(PG_FUNCTION_ARGS); extern Datum dist_pc(PG_FUNCTION_ARGS); extern Datum dist_cpoly(PG_FUNCTION_ARGS); extern Datum dist_ppoly(PG_FUNCTION_ARGS); extern Datum circle_center(PG_FUNCTION_ARGS); extern Datum cr_circle(PG_FUNCTION_ARGS); +extern Datum point_box(PG_FUNCTION_ARGS); extern Datum box_circle(PG_FUNCTION_ARGS); extern Datum circle_box(PG_FUNCTION_ARGS); extern Datum poly_circle(PG_FUNCTION_ARGS); extern Datum circle_poly(PG_FUNCTION_ARGS); extern Datum circle_area(PG_FUNCTION_ARGS); /* support routines for the GiST access method (access/gist/gistproc.c) */ extern Datum gist_box_compress(PG_FUNCTION_ARGS); extern Datum gist_box_decompress(PG_FUNCTION_ARGS); extern Datum gist_box_union(PG_FUNCTION_ARGS); diff --git a/src/include/utils/rangetypes.h b/src/include/utils/rangetypes.h index 173bf74..2c0e050 100644 --- a/src/include/utils/rangetypes.h +++ b/src/include/utils/rangetypes.h @@ -203,15 +203,16 @@ extern int range_cmp_bound_values(TypeCacheEntry *typcache, RangeBound *b1, RangeBound *b2); extern bool bounds_adjacent(TypeCacheEntry *typcache, RangeBound bound1, RangeBound bound2); extern RangeType *make_empty_range(TypeCacheEntry *typcache); /* GiST support (in rangetypes_gist.c) */ extern Datum range_gist_consistent(PG_FUNCTION_ARGS); extern Datum range_gist_compress(PG_FUNCTION_ARGS); extern Datum range_gist_decompress(PG_FUNCTION_ARGS); extern Datum range_gist_union(PG_FUNCTION_ARGS); +extern Datum range_merge(PG_FUNCTION_ARGS); extern Datum range_gist_penalty(PG_FUNCTION_ARGS); extern Datum range_gist_picksplit(PG_FUNCTION_ARGS); extern Datum range_gist_same(PG_FUNCTION_ARGS); #endif /* RANGETYPES_H */ diff --git a/src/test/regress/expected/brin.out b/src/test/regress/expected/brin.out index f47f366..47f081f 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', 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_minmax_ops, + inetcol inet_inclusion_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-03, 01:30:20-03, 01:35:50-08, 23:55:05-03, 23:55:05-03}'), + ('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 we have a sensible test case + SELECT count(*) INTO count FROM brin_result; + IF count = 0 THEN RAISE EXCEPTION 'no results for %', r; END IF; -- 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; + + -- 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/inet.out b/src/test/regress/expected/inet.out index d58bf01..ad76766 100644 --- a/src/test/regress/expected/inet.out +++ b/src/test/regress/expected/inet.out @@ -588,10 +588,38 @@ SELECT '127::1'::inet + 10000000000; ------------------ 127::2:540b:e401 (1 row) SELECT '127::1'::inet - '127::2'::inet; ?column? ---------- -1 (1 row) +-- insert one more row with addressed from different families +INSERT INTO INET_TBL (c, i) VALUES ('10', '10::/8'); +-- now, this one should fail +SELECT inet_merge(c, i) FROM INET_TBL; +ERROR: cannot merge addresses from different families +-- fix it by inet_same_family() condition +SELECT inet_merge(c, i) FROM INET_TBL WHERE inet_same_family(c, i); + inet_merge +----------------- + 192.168.1.0/24 + 192.168.1.0/24 + 192.168.1.0/24 + 192.168.1.0/24 + 192.168.1.0/24 + 192.168.1.0/24 + 10.0.0.0/8 + 10.0.0.0/8 + 10.1.2.3/32 + 10.1.2.0/24 + 10.1.0.0/16 + 10.0.0.0/8 + 10.0.0.0/7 + 8.0.0.0/6 + 10:23::/64 + 10:23::8000/113 + ::/24 +(17 rows) + diff --git a/src/test/regress/expected/opr_sanity.out b/src/test/regress/expected/opr_sanity.out index 9870bfa..993c8eb 100644 --- a/src/test/regress/expected/opr_sanity.out +++ b/src/test/regress/expected/opr_sanity.out @@ -1070,54 +1070,56 @@ FROM pg_operator as p1 LEFT JOIN pg_description as d WHERE d.classoid IS NULL AND p1.oid <= 9999; oid | oprname -----+--------- (0 rows) -- Check that operators' underlying functions have suitable comments, -- namely 'implementation of XXX operator'. (Note: it's not necessary to -- put such comments into pg_proc.h; initdb will generate them as needed.) -- In some cases involving legacy names for operators, there are multiple -- operators referencing the same pg_proc entry, so ignore operators whose --- comments say they are deprecated. +-- comments say they are deprecated or same as other operator. -- We also have a few functions that are both operator support and meant to -- be called directly; those should have comments matching their operator. WITH funcdescs AS ( SELECT p.oid as p_oid, proname, o.oid as o_oid, obj_description(p.oid, 'pg_proc') as prodesc, 'implementation of ' || oprname || ' operator' as expecteddesc, obj_description(o.oid, 'pg_operator') as oprdesc FROM pg_proc p JOIN pg_operator o ON oprcode = p.oid WHERE o.oid <= 9999 ) SELECT * FROM funcdescs WHERE prodesc IS DISTINCT FROM expecteddesc AND oprdesc NOT LIKE 'deprecated%' + AND oprdesc NOT LIKE 'same as %' AND prodesc IS DISTINCT FROM oprdesc; p_oid | proname | o_oid | prodesc | expecteddesc | oprdesc -------+---------+-------+---------+--------------+--------- (0 rows) -- Show all the operator-implementation functions that have their own -- comments. This should happen only in cases where the function and -- operator syntaxes are both documented at the user level. -- This should be a pretty short list; it's mostly legacy cases. WITH funcdescs AS ( SELECT p.oid as p_oid, proname, o.oid as o_oid, obj_description(p.oid, 'pg_proc') as prodesc, 'implementation of ' || oprname || ' operator' as expecteddesc, obj_description(o.oid, 'pg_operator') as oprdesc FROM pg_proc p JOIN pg_operator o ON oprcode = p.oid WHERE o.oid <= 9999 ) SELECT p_oid, proname, prodesc FROM funcdescs WHERE prodesc IS DISTINCT FROM expecteddesc AND oprdesc NOT LIKE 'deprecated%' + AND oprdesc NOT LIKE 'same as %' ORDER BY 1; p_oid | proname | prodesc -------+-------------------------+------------------------------------------------- 378 | array_append | append element onto end of array 379 | array_prepend | prepend element onto front of array 1035 | aclinsert | add/update ACL item 1036 | aclremove | remove ACL item 1037 | aclcontains | contains 3217 | jsonb_extract_path | get value from jsonb with path elements 3940 | jsonb_extract_path_text | get value from jsonb as text with path elements @@ -1652,24 +1654,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 | 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 | 25 | >>= + 3580 | 26 | << + 3580 | 27 | <<= 4000 | 1 | << 4000 | 1 | ~<~ 4000 | 2 | &< 4000 | 2 | ~<=~ 4000 | 3 | && 4000 | 3 | = 4000 | 4 | &> 4000 | 4 | ~>=~ 4000 | 5 | >> 4000 | 5 | ~>~ @@ -1678,21 +1707,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/expected/rangetypes.out b/src/test/regress/expected/rangetypes.out index 35d0dd3..556486e 100644 --- a/src/test/regress/expected/rangetypes.out +++ b/src/test/regress/expected/rangetypes.out @@ -473,22 +473,40 @@ select numrange(1.0, 2.0) + numrange(2.0, 3.0); ----------- [1.0,3.0) (1 row) select numrange(1.0, 2.0) + numrange(1.5, 3.0); ?column? ----------- [1.0,3.0) (1 row) -select numrange(1.0, 2.0) + numrange(2.5, 3.0); +select numrange(1.0, 2.0) + numrange(2.5, 3.0); -- should fail ERROR: result of range union would not be contiguous +select range_merge(numrange(1.0, 2.0), numrange(2.0, 3.0)); + range_merge +------------- + [1.0,3.0) +(1 row) + +select range_merge(numrange(1.0, 2.0), numrange(1.5, 3.0)); + range_merge +------------- + [1.0,3.0) +(1 row) + +select range_merge(numrange(1.0, 2.0), numrange(2.5, 3.0)); -- shouldn't fail + range_merge +------------- + [1.0,3.0) +(1 row) + select numrange(1.0, 2.0) * numrange(2.0, 3.0); ?column? ---------- empty (1 row) select numrange(1.0, 2.0) * numrange(1.5, 3.0); ?column? ----------- [1.5,2.0) diff --git a/src/test/regress/sql/brin.sql b/src/test/regress/sql/brin.sql index 3aff925..758f560 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', 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_minmax_ops, + inetcol inet_inclusion_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-03, 01:30:20-03, 01:35:50-08, 23:55:05-03, 23:55:05-03}'), + ('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 we have a sensible test case + SELECT count(*) INTO count FROM brin_result; + IF count = 0 THEN RAISE EXCEPTION 'no results for %', r; END IF; -- 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; + + -- 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; diff --git a/src/test/regress/sql/inet.sql b/src/test/regress/sql/inet.sql index c9792b7..09a446c 100644 --- a/src/test/regress/sql/inet.sql +++ b/src/test/regress/sql/inet.sql @@ -103,10 +103,17 @@ SELECT '127.0.0.2'::inet - ('127.0.0.2'::inet - 500); SELECT '127::2'::inet - ('127::2'::inet + 500); SELECT '127::2'::inet - ('127::2'::inet - 500); -- these should give overflow errors: SELECT '127.0.0.1'::inet + 10000000000; SELECT '127.0.0.1'::inet - 10000000000; SELECT '126::1'::inet - '127::2'::inet; SELECT '127::1'::inet - '126::2'::inet; -- but not these SELECT '127::1'::inet + 10000000000; SELECT '127::1'::inet - '127::2'::inet; + +-- insert one more row with addressed from different families +INSERT INTO INET_TBL (c, i) VALUES ('10', '10::/8'); +-- now, this one should fail +SELECT inet_merge(c, i) FROM INET_TBL; +-- fix it by inet_same_family() condition +SELECT inet_merge(c, i) FROM INET_TBL WHERE inet_same_family(c, i); diff --git a/src/test/regress/sql/opr_sanity.sql b/src/test/regress/sql/opr_sanity.sql index 7159a83..2c20763 100644 --- a/src/test/regress/sql/opr_sanity.sql +++ b/src/test/regress/sql/opr_sanity.sql @@ -628,51 +628,53 @@ WHERE p1.oprjoin = p2.oid AND SELECT p1.oid, p1.oprname FROM pg_operator as p1 LEFT JOIN pg_description as d ON p1.tableoid = d.classoid and p1.oid = d.objoid and d.objsubid = 0 WHERE d.classoid IS NULL AND p1.oid <= 9999; -- Check that operators' underlying functions have suitable comments, -- namely 'implementation of XXX operator'. (Note: it's not necessary to -- put such comments into pg_proc.h; initdb will generate them as needed.) -- In some cases involving legacy names for operators, there are multiple -- operators referencing the same pg_proc entry, so ignore operators whose --- comments say they are deprecated. +-- comments say they are deprecated or same as other operator. -- We also have a few functions that are both operator support and meant to -- be called directly; those should have comments matching their operator. WITH funcdescs AS ( SELECT p.oid as p_oid, proname, o.oid as o_oid, obj_description(p.oid, 'pg_proc') as prodesc, 'implementation of ' || oprname || ' operator' as expecteddesc, obj_description(o.oid, 'pg_operator') as oprdesc FROM pg_proc p JOIN pg_operator o ON oprcode = p.oid WHERE o.oid <= 9999 ) SELECT * FROM funcdescs WHERE prodesc IS DISTINCT FROM expecteddesc AND oprdesc NOT LIKE 'deprecated%' + AND oprdesc NOT LIKE 'same as %' AND prodesc IS DISTINCT FROM oprdesc; -- Show all the operator-implementation functions that have their own -- comments. This should happen only in cases where the function and -- operator syntaxes are both documented at the user level. -- This should be a pretty short list; it's mostly legacy cases. WITH funcdescs AS ( SELECT p.oid as p_oid, proname, o.oid as o_oid, obj_description(p.oid, 'pg_proc') as prodesc, 'implementation of ' || oprname || ' operator' as expecteddesc, obj_description(o.oid, 'pg_operator') as oprdesc FROM pg_proc p JOIN pg_operator o ON oprcode = p.oid WHERE o.oid <= 9999 ) SELECT p_oid, proname, prodesc FROM funcdescs WHERE prodesc IS DISTINCT FROM expecteddesc AND oprdesc NOT LIKE 'deprecated%' + AND oprdesc NOT LIKE 'same as %' ORDER BY 1; -- **************** pg_aggregate **************** -- Look for illegal values in pg_aggregate fields. SELECT ctid, aggfnoid::oid FROM pg_aggregate as p1 WHERE aggfnoid = 0 OR aggtransfn = 0 OR diff --git a/src/test/regress/sql/rangetypes.sql b/src/test/regress/sql/rangetypes.sql index aa026ca..6a9abac 100644 --- a/src/test/regress/sql/rangetypes.sql +++ b/src/test/regress/sql/rangetypes.sql @@ -101,21 +101,25 @@ select numrange(1.0, 2.0) << numrange(3.0, 4.0); select numrange(1.0, 3.0,'[]') << numrange(3.0, 4.0,'[]'); select numrange(1.0, 3.0,'()') << numrange(3.0, 4.0,'()'); select numrange(1.0, 2.0) >> numrange(3.0, 4.0); select numrange(3.0, 70.0) &< numrange(6.6, 100.0); select numrange(1.1, 2.2) < numrange(1.0, 200.2); select numrange(1.1, 2.2) < numrange(1.1, 1.2); select numrange(1.0, 2.0) + numrange(2.0, 3.0); select numrange(1.0, 2.0) + numrange(1.5, 3.0); -select numrange(1.0, 2.0) + numrange(2.5, 3.0); +select numrange(1.0, 2.0) + numrange(2.5, 3.0); -- should fail + +select range_merge(numrange(1.0, 2.0), numrange(2.0, 3.0)); +select range_merge(numrange(1.0, 2.0), numrange(1.5, 3.0)); +select range_merge(numrange(1.0, 2.0), numrange(2.5, 3.0)); -- shouldn't fail select numrange(1.0, 2.0) * numrange(2.0, 3.0); select numrange(1.0, 2.0) * numrange(1.5, 3.0); select numrange(1.0, 2.0) * numrange(2.5, 3.0); create table numrange_test2(nr numrange); create index numrange_test2_hash_idx on numrange_test2 (nr); INSERT INTO numrange_test2 VALUES('[, 5)'); INSERT INTO numrange_test2 VALUES(numrange(1.1, 2.2));