From: Alvaro Herrera Date: Thu, 7 May 2015 16:02:22 +0000 (-0300) Subject: Improve BRIN infra, minmax opclass and regression test X-Git-Tag: REL9_5_ALPHA1~322 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=db5f98ab4f;p=postgresql Improve BRIN infra, minmax opclass and regression test The minmax opclass was using the wrong support functions when cross-datatypes queries were run. Instead of trying to fix the pg_amproc definitions (which apparently is not possible), use the already correct pg_amop entries instead. This requires jumping through more hoops (read: extra syscache lookups) to obtain the underlying functions to execute, but it is necessary for correctness. Author: Emre Hasegeli, tweaked by Álvaro Review: Andreas Karlsson Also change BrinOpcInfo to record each stored type's typecache entry instead of just the OID. Turns out that the full type cache is necessary in brin_deform_tuple: the original code used the indexed type's byval and typlen properties to extract the stored tuple, which is correct in Minmax; but in other implementations that want to store something different, that's wrong. The realization that this is a bug comes from Emre also, but I did not use his patch. I also adopted Emre's regression test code (with smallish changes), which is more complete. --- diff --git a/contrib/pageinspect/brinfuncs.c b/contrib/pageinspect/brinfuncs.c index 1b15a7bdfe..bd3191d5d2 100644 --- a/contrib/pageinspect/brinfuncs.c +++ b/contrib/pageinspect/brinfuncs.c @@ -181,7 +181,7 @@ brin_page_items(PG_FUNCTION_ARGS) column->nstored = opcinfo->oi_nstored; for (i = 0; i < opcinfo->oi_nstored; i++) { - getTypeOutputInfo(opcinfo->oi_typids[i], &output, &isVarlena); + getTypeOutputInfo(opcinfo->oi_typcache[i]->type_id, &output, &isVarlena); fmgr_info(output, &column->outputFn[i]); } diff --git a/doc/src/sgml/brin.sgml b/doc/src/sgml/brin.sgml index 1ac282c57a..92dac7c60b 100644 --- a/doc/src/sgml/brin.sgml +++ b/doc/src/sgml/brin.sgml @@ -428,8 +428,8 @@ typedef struct BrinOpcInfo /* Opaque pointer for the opclass' private use */ void *oi_opaque; - /* Type IDs of the stored columns */ - Oid oi_typids[FLEXIBLE_ARRAY_MEMBER]; + /* Type cache entries of the stored columns */ + TypeCacheEntry *oi_typcache[FLEXIBLE_ARRAY_MEMBER]; } BrinOpcInfo; BrinOpcInfo.oi_opaque can be used by the diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c index 299d6f7bf6..d9fa9cd597 100644 --- a/src/backend/access/brin/brin_minmax.c +++ b/src/backend/access/brin/brin_minmax.c @@ -15,35 +15,21 @@ #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" -/* - * Procedure numbers must not collide with BRIN_PROCNUM defines in - * brin_internal.h. Note we only need inequality functions. - */ -#define MINMAX_NUM_PROCNUMS 4 /* # support procs we need */ -#define PROCNUM_LESS 11 -#define PROCNUM_LESSEQUAL 12 -#define PROCNUM_GREATEREQUAL 13 -#define PROCNUM_GREATER 14 - -/* - * Subtract this from procnum to obtain index in MinmaxOpaque arrays - * (Must be equal to minimum of private procnums) - */ -#define PROCNUM_BASE 11 - typedef struct MinmaxOpaque { - FmgrInfo operators[MINMAX_NUM_PROCNUMS]; - bool inited[MINMAX_NUM_PROCNUMS]; + Oid cached_subtype; + FmgrInfo strategy_procinfos[BTMaxStrategyNumber]; } MinmaxOpaque; -static FmgrInfo *minmax_get_procinfo(BrinDesc *bdesc, uint16 attno, - uint16 procnum); +static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno, + Oid subtype, uint16 strategynum); Datum @@ -53,8 +39,8 @@ brin_minmax_opcinfo(PG_FUNCTION_ARGS) BrinOpcInfo *result; /* - * opaque->operators is initialized lazily, as indicated by 'inited' which - * is initialized to all false by palloc0. + * opaque->strategy_procinfos is initialized lazily; here it is set to + * all-uninitialized by palloc0 which sets fn_oid to InvalidOid. */ result = palloc0(MAXALIGN(SizeofBrinOpcInfo(2)) + @@ -62,8 +48,8 @@ brin_minmax_opcinfo(PG_FUNCTION_ARGS) result->oi_nstored = 2; result->oi_opaque = (MinmaxOpaque *) MAXALIGN((char *) result + SizeofBrinOpcInfo(2)); - result->oi_typids[0] = typoid; - result->oi_typids[1] = typoid; + result->oi_typcache[0] = result->oi_typcache[1] = + lookup_type_cache(typoid, 0); PG_RETURN_POINTER(result); } @@ -122,7 +108,8 @@ brin_minmax_add_value(PG_FUNCTION_ARGS) * and update them accordingly. First check if it's less than the * existing minimum. */ - cmpFn = minmax_get_procinfo(bdesc, attno, PROCNUM_LESS); + cmpFn = minmax_get_strategy_procinfo(bdesc, attno, attr->atttypid, + BTLessStrategyNumber); compar = FunctionCall2Coll(cmpFn, colloid, newval, column->bv_values[0]); if (DatumGetBool(compar)) { @@ -135,7 +122,8 @@ brin_minmax_add_value(PG_FUNCTION_ARGS) /* * And now compare it to the existing maximum. */ - cmpFn = minmax_get_procinfo(bdesc, attno, PROCNUM_GREATER); + cmpFn = minmax_get_strategy_procinfo(bdesc, attno, attr->atttypid, + BTGreaterStrategyNumber); compar = FunctionCall2Coll(cmpFn, colloid, newval, column->bv_values[1]); if (DatumGetBool(compar)) { @@ -159,10 +147,12 @@ brin_minmax_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(); + Oid colloid = PG_GET_COLLATION(), + subtype; AttrNumber attno; Datum value; Datum matches; + FmgrInfo *finfo; Assert(key->sk_attno == column->bv_attno); @@ -189,18 +179,16 @@ brin_minmax_consistent(PG_FUNCTION_ARGS) PG_RETURN_BOOL(false); attno = key->sk_attno; + subtype = key->sk_subtype; value = key->sk_argument; switch (key->sk_strategy) { case BTLessStrategyNumber: - matches = FunctionCall2Coll(minmax_get_procinfo(bdesc, attno, - PROCNUM_LESS), - colloid, column->bv_values[0], value); - break; case BTLessEqualStrategyNumber: - matches = FunctionCall2Coll(minmax_get_procinfo(bdesc, attno, - PROCNUM_LESSEQUAL), - colloid, column->bv_values[0], value); + finfo = minmax_get_strategy_procinfo(bdesc, attno, subtype, + key->sk_strategy); + matches = FunctionCall2Coll(finfo, colloid, column->bv_values[0], + value); break; case BTEqualStrategyNumber: @@ -209,25 +197,24 @@ brin_minmax_consistent(PG_FUNCTION_ARGS) * the current page range if the minimum value in the range <= * scan key, and the maximum value >= scan key. */ - matches = FunctionCall2Coll(minmax_get_procinfo(bdesc, attno, - PROCNUM_LESSEQUAL), - colloid, column->bv_values[0], value); + finfo = minmax_get_strategy_procinfo(bdesc, attno, subtype, + BTLessEqualStrategyNumber); + matches = FunctionCall2Coll(finfo, colloid, column->bv_values[0], + value); if (!DatumGetBool(matches)) break; /* max() >= scankey */ - matches = FunctionCall2Coll(minmax_get_procinfo(bdesc, attno, - PROCNUM_GREATEREQUAL), - colloid, column->bv_values[1], value); + finfo = minmax_get_strategy_procinfo(bdesc, attno, subtype, + BTGreaterEqualStrategyNumber); + matches = FunctionCall2Coll(finfo, colloid, column->bv_values[1], + value); break; case BTGreaterEqualStrategyNumber: - matches = FunctionCall2Coll(minmax_get_procinfo(bdesc, attno, - PROCNUM_GREATEREQUAL), - colloid, column->bv_values[1], value); - break; case BTGreaterStrategyNumber: - matches = FunctionCall2Coll(minmax_get_procinfo(bdesc, attno, - PROCNUM_GREATER), - colloid, column->bv_values[1], value); + finfo = minmax_get_strategy_procinfo(bdesc, attno, subtype, + key->sk_strategy); + matches = FunctionCall2Coll(finfo, colloid, column->bv_values[1], + value); break; default: /* shouldn't happen */ @@ -252,6 +239,7 @@ brin_minmax_union(PG_FUNCTION_ARGS) Oid colloid = PG_GET_COLLATION(); AttrNumber attno; Form_pg_attribute attr; + FmgrInfo *finfo; bool needsadj; Assert(col_a->bv_attno == col_b->bv_attno); @@ -284,9 +272,10 @@ brin_minmax_union(PG_FUNCTION_ARGS) } /* Adjust minimum, if B's min is less than A's min */ - needsadj = FunctionCall2Coll(minmax_get_procinfo(bdesc, attno, - PROCNUM_LESS), - colloid, col_b->bv_values[0], col_a->bv_values[0]); + finfo = minmax_get_strategy_procinfo(bdesc, attno, attr->atttypid, + BTLessStrategyNumber); + needsadj = FunctionCall2Coll(finfo, colloid, col_b->bv_values[0], + col_a->bv_values[0]); if (needsadj) { if (!attr->attbyval) @@ -296,9 +285,10 @@ brin_minmax_union(PG_FUNCTION_ARGS) } /* Adjust maximum, if B's max is greater than A's max */ - needsadj = FunctionCall2Coll(minmax_get_procinfo(bdesc, attno, - PROCNUM_GREATER), - colloid, col_b->bv_values[1], col_a->bv_values[1]); + finfo = minmax_get_strategy_procinfo(bdesc, attno, attr->atttypid, + BTGreaterStrategyNumber); + needsadj = FunctionCall2Coll(finfo, colloid, col_b->bv_values[1], + col_a->bv_values[1]); if (needsadj) { if (!attr->attbyval) @@ -311,27 +301,61 @@ brin_minmax_union(PG_FUNCTION_ARGS) } /* - * Return the procedure corresponding to the given function support number. + * Cache and return the procedure for the given strategy. */ -static FmgrInfo * -minmax_get_procinfo(BrinDesc *bdesc, uint16 attno, uint16 procnum) +FmgrInfo * +minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno, Oid subtype, + uint16 strategynum) { MinmaxOpaque *opaque; - uint16 basenum = procnum - PROCNUM_BASE; + + Assert(strategynum >= 1 && + strategynum <= BTMaxStrategyNumber); opaque = (MinmaxOpaque *) bdesc->bd_info[attno - 1]->oi_opaque; /* - * We cache these in the opaque struct, to avoid repetitive syscache - * lookups. + * We cache the procedures for the previous subtype in the opaque struct, + * to avoid repetitive syscache lookups. If the subtype changed, + * invalidate all the cached entries. */ - if (!opaque->inited[basenum]) + if (opaque->cached_subtype != subtype) + { + uint16 i; + + for (i = 1; i <= BTMaxStrategyNumber; i++) + opaque->strategy_procinfos[i - 1].fn_oid = InvalidOid; + opaque->cached_subtype = subtype; + } + + if (opaque->strategy_procinfos[strategynum - 1].fn_oid == InvalidOid) { - fmgr_info_copy(&opaque->operators[basenum], - index_getprocinfo(bdesc->bd_index, attno, procnum), - bdesc->bd_context); - opaque->inited[basenum] = true; + Form_pg_attribute attr; + HeapTuple tuple; + Oid opfamily, + oprid; + 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 operator %d(%u,%u) in opfamily %u", + strategynum, attr->atttypid, subtype, opfamily); + + oprid = DatumGetObjectId(SysCacheGetAttr(AMOPSTRATEGY, tuple, + Anum_pg_amop_amopopr, &isNull)); + ReleaseSysCache(tuple); + Assert(!isNull && RegProcedureIsValid(oprid)); + + fmgr_info_cxt(get_opcode(oprid), + &opaque->strategy_procinfos[strategynum - 1], + bdesc->bd_context); } - return &opaque->operators[basenum]; + return &opaque->strategy_procinfos[strategynum - 1]; } diff --git a/src/backend/access/brin/brin_tuple.c b/src/backend/access/brin/brin_tuple.c index 08fa998a52..22ce74a4f4 100644 --- a/src/backend/access/brin/brin_tuple.c +++ b/src/backend/access/brin/brin_tuple.c @@ -68,7 +68,7 @@ brtuple_disk_tupdesc(BrinDesc *brdesc) { for (j = 0; j < brdesc->bd_info[i]->oi_nstored; j++) TupleDescInitEntry(tupdesc, attno++, NULL, - brdesc->bd_info[i]->oi_typids[j], + brdesc->bd_info[i]->oi_typcache[j]->type_id, -1, 0); } @@ -444,8 +444,8 @@ brin_deform_tuple(BrinDesc *brdesc, BrinTuple *tuple) for (i = 0; i < brdesc->bd_info[keyno]->oi_nstored; i++) dtup->bt_columns[keyno].bv_values[i] = datumCopy(values[valueno++], - brdesc->bd_tupdesc->attrs[keyno]->attbyval, - brdesc->bd_tupdesc->attrs[keyno]->attlen); + brdesc->bd_info[keyno]->oi_typcache[i]->typbyval, + brdesc->bd_info[keyno]->oi_typcache[i]->typlen); dtup->bt_columns[keyno].bv_hasnulls = hasnulls[keyno]; dtup->bt_columns[keyno].bv_allnulls = false; diff --git a/src/include/access/brin_internal.h b/src/include/access/brin_internal.h index 84eed6127d..1486d04693 100644 --- a/src/include/access/brin_internal.h +++ b/src/include/access/brin_internal.h @@ -16,6 +16,7 @@ #include "storage/bufpage.h" #include "storage/off.h" #include "utils/relcache.h" +#include "utils/typcache.h" /* @@ -32,13 +33,13 @@ typedef struct BrinOpcInfo /* Opaque pointer for the opclass' private use */ void *oi_opaque; - /* Type IDs of the stored columns */ - Oid oi_typids[FLEXIBLE_ARRAY_MEMBER]; + /* Type cache entries of the stored columns */ + TypeCacheEntry *oi_typcache[FLEXIBLE_ARRAY_MEMBER]; } BrinOpcInfo; /* the size of a BrinOpcInfo for the given number of columns */ #define SizeofBrinOpcInfo(ncols) \ - (offsetof(BrinOpcInfo, oi_typids) + sizeof(Oid) * ncols) + (offsetof(BrinOpcInfo, oi_typcache) + sizeof(TypeCacheEntry *) * ncols) typedef struct BrinDesc { diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h index e8320daedb..2444e543a7 100644 --- a/src/include/catalog/catversion.h +++ b/src/include/catalog/catversion.h @@ -53,6 +53,6 @@ */ /* yyyymmddN */ -#define CATALOG_VERSION_NO 201505051 +#define CATALOG_VERSION_NO 201505071 #endif diff --git a/src/include/catalog/pg_amproc.h b/src/include/catalog/pg_amproc.h index a54d11fdbd..e3de3b57e7 100644 --- a/src/include/catalog/pg_amproc.h +++ b/src/include/catalog/pg_amproc.h @@ -443,360 +443,196 @@ DATA(insert ( 4064 17 17 1 3383 )); DATA(insert ( 4064 17 17 2 3384 )); DATA(insert ( 4064 17 17 3 3385 )); DATA(insert ( 4064 17 17 4 3386 )); -DATA(insert ( 4064 17 17 11 1949 )); -DATA(insert ( 4064 17 17 12 1950 )); -DATA(insert ( 4064 17 17 13 1952 )); -DATA(insert ( 4064 17 17 14 1951 )); /* minmax "char" */ DATA(insert ( 4062 18 18 1 3383 )); DATA(insert ( 4062 18 18 2 3384 )); DATA(insert ( 4062 18 18 3 3385 )); DATA(insert ( 4062 18 18 4 3386 )); -DATA(insert ( 4062 18 18 11 1246 )); -DATA(insert ( 4062 18 18 12 72 )); -DATA(insert ( 4062 18 18 13 74 )); -DATA(insert ( 4062 18 18 14 73 )); /* minmax name */ DATA(insert ( 4065 19 19 1 3383 )); DATA(insert ( 4065 19 19 2 3384 )); DATA(insert ( 4065 19 19 3 3385 )); DATA(insert ( 4065 19 19 4 3386 )); -DATA(insert ( 4065 19 19 11 655 )); -DATA(insert ( 4065 19 19 12 656 )); -DATA(insert ( 4065 19 19 13 658 )); -DATA(insert ( 4065 19 19 14 657 )); /* minmax integer: int2, int4, int8 */ DATA(insert ( 4054 20 20 1 3383 )); DATA(insert ( 4054 20 20 2 3384 )); DATA(insert ( 4054 20 20 3 3385 )); DATA(insert ( 4054 20 20 4 3386 )); -DATA(insert ( 4054 20 20 11 469 )); -DATA(insert ( 4054 20 20 12 471 )); -DATA(insert ( 4054 20 20 13 472 )); -DATA(insert ( 4054 20 20 14 470 )); DATA(insert ( 4054 20 21 1 3383 )); DATA(insert ( 4054 20 21 2 3384 )); DATA(insert ( 4054 20 21 3 3385 )); DATA(insert ( 4054 20 21 4 3386 )); -DATA(insert ( 4054 20 21 11 1858 )); -DATA(insert ( 4054 20 21 12 1860 )); -DATA(insert ( 4054 20 21 13 1861 )); -DATA(insert ( 4054 20 21 14 1859 )); DATA(insert ( 4054 20 23 1 3383 )); DATA(insert ( 4054 20 23 2 3384 )); DATA(insert ( 4054 20 23 3 3385 )); DATA(insert ( 4054 20 23 4 3386 )); -DATA(insert ( 4054 20 23 11 476 )); -DATA(insert ( 4054 20 23 12 478 )); -DATA(insert ( 4054 20 23 13 479 )); -DATA(insert ( 4054 20 23 14 477 )); DATA(insert ( 4054 21 21 1 3383 )); DATA(insert ( 4054 21 21 2 3384 )); DATA(insert ( 4054 21 21 3 3385 )); DATA(insert ( 4054 21 21 4 3386 )); -DATA(insert ( 4054 21 21 11 64 )); -DATA(insert ( 4054 21 21 12 148 )); -DATA(insert ( 4054 21 21 13 151 )); -DATA(insert ( 4054 21 21 14 146 )); DATA(insert ( 4054 21 20 1 3383 )); DATA(insert ( 4054 21 20 2 3384 )); DATA(insert ( 4054 21 20 3 3385 )); DATA(insert ( 4054 21 20 4 3386 )); -DATA(insert ( 4054 21 20 11 1852 )); -DATA(insert ( 4054 21 20 12 1854 )); -DATA(insert ( 4054 21 20 13 1855 )); -DATA(insert ( 4054 21 20 14 1853 )); DATA(insert ( 4054 21 23 1 3383 )); DATA(insert ( 4054 21 23 2 3384 )); DATA(insert ( 4054 21 23 3 3385 )); DATA(insert ( 4054 21 23 4 3386 )); -DATA(insert ( 4054 21 23 11 160 )); -DATA(insert ( 4054 21 23 12 166 )); -DATA(insert ( 4054 21 23 13 168 )); -DATA(insert ( 4054 21 23 14 162 )); DATA(insert ( 4054 23 23 1 3383 )); DATA(insert ( 4054 23 23 2 3384 )); DATA(insert ( 4054 23 23 3 3385 )); DATA(insert ( 4054 23 23 4 3386 )); -DATA(insert ( 4054 23 23 11 66 )); -DATA(insert ( 4054 23 23 12 149 )); -DATA(insert ( 4054 23 23 13 150 )); -DATA(insert ( 4054 23 23 14 147 )); DATA(insert ( 4054 23 20 1 3383 )); DATA(insert ( 4054 23 20 2 3384 )); DATA(insert ( 4054 23 20 3 3385 )); DATA(insert ( 4054 23 20 4 3386 )); -DATA(insert ( 4054 23 20 11 854 )); -DATA(insert ( 4054 23 20 12 856 )); -DATA(insert ( 4054 23 20 13 857 )); -DATA(insert ( 4054 23 20 14 855 )); DATA(insert ( 4054 23 21 1 3383 )); DATA(insert ( 4054 23 21 2 3384 )); DATA(insert ( 4054 23 21 3 3385 )); DATA(insert ( 4054 23 21 4 3386 )); -DATA(insert ( 4054 23 21 11 161 )); -DATA(insert ( 4054 23 21 12 167 )); -DATA(insert ( 4054 23 21 13 169 )); -DATA(insert ( 4054 23 21 14 163 )); /* minmax text */ DATA(insert ( 4056 25 25 1 3383 )); DATA(insert ( 4056 25 25 2 3384 )); DATA(insert ( 4056 25 25 3 3385 )); DATA(insert ( 4056 25 25 4 3386 )); -DATA(insert ( 4056 25 25 11 740 )); -DATA(insert ( 4056 25 25 12 741 )); -DATA(insert ( 4056 25 25 13 743 )); -DATA(insert ( 4056 25 25 14 742 )); /* minmax oid */ DATA(insert ( 4068 26 26 1 3383 )); DATA(insert ( 4068 26 26 2 3384 )); DATA(insert ( 4068 26 26 3 3385 )); DATA(insert ( 4068 26 26 4 3386 )); -DATA(insert ( 4068 26 26 11 716 )); -DATA(insert ( 4068 26 26 12 717 )); -DATA(insert ( 4068 26 26 13 1639 )); -DATA(insert ( 4068 26 26 14 1638 )); /* minmax tid */ DATA(insert ( 4069 27 27 1 3383 )); DATA(insert ( 4069 27 27 2 3384 )); DATA(insert ( 4069 27 27 3 3385 )); DATA(insert ( 4069 27 27 4 3386 )); -DATA(insert ( 4069 27 27 11 2791 )); -DATA(insert ( 4069 27 27 12 2793 )); -DATA(insert ( 4069 27 27 13 2792 )); -DATA(insert ( 4069 27 27 14 2790 )); /* minmax float */ DATA(insert ( 4070 700 700 1 3383 )); DATA(insert ( 4070 700 700 2 3384 )); DATA(insert ( 4070 700 700 3 3385 )); DATA(insert ( 4070 700 700 4 3386 )); -DATA(insert ( 4070 700 700 11 289 )); -DATA(insert ( 4070 700 700 12 290 )); -DATA(insert ( 4070 700 700 13 292 )); -DATA(insert ( 4070 700 700 14 291 )); DATA(insert ( 4070 700 701 1 3383 )); DATA(insert ( 4070 700 701 2 3384 )); DATA(insert ( 4070 700 701 3 3385 )); DATA(insert ( 4070 700 701 4 3386 )); -DATA(insert ( 4070 700 701 11 301 )); -DATA(insert ( 4070 700 701 12 303 )); -DATA(insert ( 4070 700 701 13 304 )); -DATA(insert ( 4070 700 701 14 303 )); DATA(insert ( 4070 701 701 1 3383 )); DATA(insert ( 4070 701 701 2 3384 )); DATA(insert ( 4070 701 701 3 3385 )); DATA(insert ( 4070 701 701 4 3386 )); -DATA(insert ( 4070 701 701 11 295 )); -DATA(insert ( 4070 701 701 12 296 )); -DATA(insert ( 4070 701 701 13 298 )); -DATA(insert ( 4070 701 701 14 297 )); DATA(insert ( 4070 701 700 1 3383 )); DATA(insert ( 4070 701 700 2 3384 )); DATA(insert ( 4070 701 700 3 3385 )); DATA(insert ( 4070 701 700 4 3386 )); -DATA(insert ( 4070 701 700 11 307 )); -DATA(insert ( 4070 701 700 12 308 )); -DATA(insert ( 4070 701 700 13 310 )); -DATA(insert ( 4070 701 700 14 309 )); /* minmax abstime */ DATA(insert ( 4072 702 702 1 3383 )); DATA(insert ( 4072 702 702 2 3384 )); DATA(insert ( 4072 702 702 3 3385 )); DATA(insert ( 4072 702 702 4 3386 )); -DATA(insert ( 4072 702 702 11 253 )); -DATA(insert ( 4072 702 702 12 255 )); -DATA(insert ( 4072 702 702 13 256 )); -DATA(insert ( 4072 702 702 14 254 )); /* minmax reltime */ DATA(insert ( 4073 703 703 1 3383 )); DATA(insert ( 4073 703 703 2 3384 )); DATA(insert ( 4073 703 703 3 3385 )); DATA(insert ( 4073 703 703 4 3386 )); -DATA(insert ( 4073 703 703 11 259 )); -DATA(insert ( 4073 703 703 12 261 )); -DATA(insert ( 4073 703 703 13 262 )); -DATA(insert ( 4073 703 703 14 260 )); /* minmax macaddr */ DATA(insert ( 4074 829 829 1 3383 )); DATA(insert ( 4074 829 829 2 3384 )); DATA(insert ( 4074 829 829 3 3385 )); DATA(insert ( 4074 829 829 4 3386 )); -DATA(insert ( 4074 829 829 11 831 )); -DATA(insert ( 4074 829 829 12 832 )); -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 )); /* 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 */ DATA(insert ( 4077 1083 1083 1 3383 )); DATA(insert ( 4077 1083 1083 2 3384 )); DATA(insert ( 4077 1083 1083 3 3385 )); DATA(insert ( 4077 1083 1083 4 3386 )); -DATA(insert ( 4077 1083 1083 11 1102 )); -DATA(insert ( 4077 1083 1083 12 1103 )); -DATA(insert ( 4077 1083 1083 13 1105 )); -DATA(insert ( 4077 1083 1083 14 1104 )); /* minmax datetime (date, timestamp, timestamptz) */ DATA(insert ( 4059 1114 1114 1 3383 )); DATA(insert ( 4059 1114 1114 2 3384 )); DATA(insert ( 4059 1114 1114 3 3385 )); DATA(insert ( 4059 1114 1114 4 3386 )); -DATA(insert ( 4059 1114 1114 11 2054 )); -DATA(insert ( 4059 1114 1114 12 2055 )); -DATA(insert ( 4059 1114 1114 13 2056 )); -DATA(insert ( 4059 1114 1114 14 2057 )); DATA(insert ( 4059 1114 1184 1 3383 )); DATA(insert ( 4059 1114 1184 2 3384 )); DATA(insert ( 4059 1114 1184 3 3385 )); DATA(insert ( 4059 1114 1184 4 3386 )); -DATA(insert ( 4059 1114 1184 11 2520 )); -DATA(insert ( 4059 1114 1184 12 2521 )); -DATA(insert ( 4059 1114 1184 13 2524 )); -DATA(insert ( 4059 1114 1184 14 2523 )); DATA(insert ( 4059 1114 1082 1 3383 )); DATA(insert ( 4059 1114 1082 2 3384 )); DATA(insert ( 4059 1114 1082 3 3385 )); DATA(insert ( 4059 1114 1082 4 3386 )); -DATA(insert ( 4059 1114 1082 11 2364 )); -DATA(insert ( 4059 1114 1082 12 2365 )); -DATA(insert ( 4059 1114 1082 13 2368 )); -DATA(insert ( 4059 1114 1082 14 2367 )); DATA(insert ( 4059 1184 1184 1 3383 )); DATA(insert ( 4059 1184 1184 2 3384 )); DATA(insert ( 4059 1184 1184 3 3385 )); DATA(insert ( 4059 1184 1184 4 3386 )); -DATA(insert ( 4059 1184 1184 11 1154 )); -DATA(insert ( 4059 1184 1184 12 1155 )); -DATA(insert ( 4059 1184 1184 13 1156 )); -DATA(insert ( 4059 1184 1184 14 1157 )); DATA(insert ( 4059 1184 1114 1 3383 )); DATA(insert ( 4059 1184 1114 2 3384 )); DATA(insert ( 4059 1184 1114 3 3385 )); DATA(insert ( 4059 1184 1114 4 3386 )); -DATA(insert ( 4059 1184 1114 11 2527 )); -DATA(insert ( 4059 1184 1114 12 2528 )); -DATA(insert ( 4059 1184 1114 13 2531 )); -DATA(insert ( 4059 1184 1114 14 2530 )); DATA(insert ( 4059 1184 1082 1 3383 )); DATA(insert ( 4059 1184 1082 2 3384 )); DATA(insert ( 4059 1184 1082 3 3385 )); DATA(insert ( 4059 1184 1082 4 3386 )); -DATA(insert ( 4059 1184 1082 11 2377 )); -DATA(insert ( 4059 1184 1082 12 2378 )); -DATA(insert ( 4059 1184 1082 13 2381 )); -DATA(insert ( 4059 1184 1082 14 2379 )); DATA(insert ( 4059 1082 1082 1 3383 )); DATA(insert ( 4059 1082 1082 2 3384 )); DATA(insert ( 4059 1082 1082 3 3385 )); DATA(insert ( 4059 1082 1082 4 3386 )); -DATA(insert ( 4059 1082 1082 11 1087 )); -DATA(insert ( 4059 1082 1082 12 1088 )); -DATA(insert ( 4059 1082 1082 13 1090 )); -DATA(insert ( 4059 1082 1082 14 1089 )); DATA(insert ( 4059 1082 1114 1 3383 )); DATA(insert ( 4059 1082 1114 2 3384 )); DATA(insert ( 4059 1082 1114 3 3385 )); DATA(insert ( 4059 1082 1114 4 3386 )); -DATA(insert ( 4059 1082 1114 11 2338 )); -DATA(insert ( 4059 1082 1114 12 2339 )); -DATA(insert ( 4059 1082 1114 13 2342 )); -DATA(insert ( 4059 1082 1114 14 2341 )); DATA(insert ( 4059 1082 1184 1 3383 )); DATA(insert ( 4059 1082 1184 2 3384 )); DATA(insert ( 4059 1082 1184 3 3385 )); DATA(insert ( 4059 1082 1184 4 3386 )); -DATA(insert ( 4059 1082 1184 11 2351 )); -DATA(insert ( 4059 1082 1184 12 2352 )); -DATA(insert ( 4059 1082 1184 13 2354 )); -DATA(insert ( 4059 1082 1184 14 2353 )); /* minmax interval */ DATA(insert ( 4078 1186 1186 1 3383 )); DATA(insert ( 4078 1186 1186 2 3384 )); DATA(insert ( 4078 1186 1186 3 3385 )); DATA(insert ( 4078 1186 1186 4 3386 )); -DATA(insert ( 4078 1186 1186 11 1164 )); -DATA(insert ( 4078 1186 1186 12 1165 )); -DATA(insert ( 4078 1186 1186 13 1166 )); -DATA(insert ( 4078 1186 1186 14 1167 )); /* minmax time with time zone */ DATA(insert ( 4058 1266 1266 1 3383 )); DATA(insert ( 4058 1266 1266 2 3384 )); DATA(insert ( 4058 1266 1266 3 3385 )); DATA(insert ( 4058 1266 1266 4 3386 )); -DATA(insert ( 4058 1266 1266 11 1354 )); -DATA(insert ( 4058 1266 1266 12 1355 )); -DATA(insert ( 4058 1266 1266 13 1356 )); -DATA(insert ( 4058 1266 1266 14 1357 )); /* minmax bit */ DATA(insert ( 4079 1560 1560 1 3383 )); DATA(insert ( 4079 1560 1560 2 3384 )); DATA(insert ( 4079 1560 1560 3 3385 )); DATA(insert ( 4079 1560 1560 4 3386 )); -DATA(insert ( 4079 1560 1560 11 1595 )); -DATA(insert ( 4079 1560 1560 12 1594 )); -DATA(insert ( 4079 1560 1560 13 1592 )); -DATA(insert ( 4079 1560 1560 14 1593 )); /* minmax bit varying */ DATA(insert ( 4080 1562 1562 1 3383 )); DATA(insert ( 4080 1562 1562 2 3384 )); DATA(insert ( 4080 1562 1562 3 3385 )); DATA(insert ( 4080 1562 1562 4 3386 )); -DATA(insert ( 4080 1562 1562 11 1671 )); -DATA(insert ( 4080 1562 1562 12 1670 )); -DATA(insert ( 4080 1562 1562 13 1668 )); -DATA(insert ( 4080 1562 1562 14 1669 )); /* minmax numeric */ DATA(insert ( 4055 1700 1700 1 3383 )); DATA(insert ( 4055 1700 1700 2 3384 )); DATA(insert ( 4055 1700 1700 3 3385 )); DATA(insert ( 4055 1700 1700 4 3386 )); -DATA(insert ( 4055 1700 1700 11 1722 )); -DATA(insert ( 4055 1700 1700 12 1723 )); -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 )); /* 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 )); #endif /* PG_AMPROC_H */ diff --git a/src/include/catalog/pg_opclass.h b/src/include/catalog/pg_opclass.h index b3acef66de..f9469375be 100644 --- a/src/include/catalog/pg_opclass.h +++ b/src/include/catalog/pg_opclass.h @@ -238,34 +238,34 @@ DATA(insert ( 2742 jsonb_path_ops PGNSP PGUID 4037 3802 f 23 )); /* BRIN operator classes */ /* no brin opclass for bool */ -DATA(insert ( 3580 bytea_minmax_ops PGNSP PGUID 4064 17 t 0 )); -DATA(insert ( 3580 char_minmax_ops PGNSP PGUID 4062 18 t 0 )); -DATA(insert ( 3580 name_minmax_ops PGNSP PGUID 4065 19 t 0 )); -DATA(insert ( 3580 int8_minmax_ops PGNSP PGUID 4054 20 t 0 )); -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 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 )); +DATA(insert ( 3580 bytea_minmax_ops PGNSP PGUID 4064 17 t 17 )); +DATA(insert ( 3580 char_minmax_ops PGNSP PGUID 4062 18 t 18 )); +DATA(insert ( 3580 name_minmax_ops PGNSP PGUID 4065 19 t 19 )); +DATA(insert ( 3580 int8_minmax_ops PGNSP PGUID 4054 20 t 20 )); +DATA(insert ( 3580 int2_minmax_ops PGNSP PGUID 4054 21 t 21 )); +DATA(insert ( 3580 int4_minmax_ops PGNSP PGUID 4054 23 t 23 )); +DATA(insert ( 3580 text_minmax_ops PGNSP PGUID 4056 25 t 25 )); +DATA(insert ( 3580 oid_minmax_ops PGNSP PGUID 4068 26 t 26 )); +DATA(insert ( 3580 tid_minmax_ops PGNSP PGUID 4069 27 t 27 )); +DATA(insert ( 3580 float4_minmax_ops PGNSP PGUID 4070 700 t 700 )); +DATA(insert ( 3580 float8_minmax_ops PGNSP PGUID 4070 701 t 701 )); +DATA(insert ( 3580 abstime_minmax_ops PGNSP PGUID 4072 702 t 702 )); +DATA(insert ( 3580 reltime_minmax_ops PGNSP PGUID 4073 703 t 703 )); +DATA(insert ( 3580 macaddr_minmax_ops PGNSP PGUID 4074 829 t 829 )); +DATA(insert ( 3580 inet_minmax_ops PGNSP PGUID 4075 869 f 869 )); +DATA(insert ( 3580 bpchar_minmax_ops PGNSP PGUID 4076 1042 t 1042 )); +DATA(insert ( 3580 time_minmax_ops PGNSP PGUID 4077 1083 t 1083 )); +DATA(insert ( 3580 date_minmax_ops PGNSP PGUID 4059 1082 t 1082 )); +DATA(insert ( 3580 timestamp_minmax_ops PGNSP PGUID 4059 1114 t 1114 )); +DATA(insert ( 3580 timestamptz_minmax_ops PGNSP PGUID 4059 1184 t 1184 )); +DATA(insert ( 3580 interval_minmax_ops PGNSP PGUID 4078 1186 t 1186 )); +DATA(insert ( 3580 timetz_minmax_ops PGNSP PGUID 4058 1266 t 1266 )); +DATA(insert ( 3580 bit_minmax_ops PGNSP PGUID 4079 1560 t 1560 )); +DATA(insert ( 3580 varbit_minmax_ops PGNSP PGUID 4080 1562 t 1562 )); +DATA(insert ( 3580 numeric_minmax_ops PGNSP PGUID 4055 1700 t 1700 )); /* no brin opclass for record, anyarray */ -DATA(insert ( 3580 uuid_minmax_ops PGNSP PGUID 4081 2950 t 0 )); -DATA(insert ( 3580 pg_lsn_minmax_ops PGNSP PGUID 4082 3220 t 0 )); +DATA(insert ( 3580 uuid_minmax_ops PGNSP PGUID 4081 2950 t 2950 )); +DATA(insert ( 3580 pg_lsn_minmax_ops PGNSP PGUID 4082 3220 t 3220 )); /* no brin opclass for enum, tsvector, tsquery, jsonb, range */ #endif /* PG_OPCLASS_H */ diff --git a/src/test/regress/expected/brin.out b/src/test/regress/expected/brin.out index f47f366375..4fe6f07194 100644 --- a/src/test/regress/expected/brin.out +++ b/src/test/regress/expected/brin.out @@ -11,6 +11,7 @@ CREATE TABLE brintest (byteacol bytea, float8col double precision, macaddrcol macaddr, inetcol inet, + cidrcol cidr, bpcharcol character, datecol date, timecol time without time zone, @@ -23,35 +24,39 @@ CREATE TABLE brintest (byteacol bytea, numericcol numeric, uuidcol uuid, lsncol pg_lsn -) WITH (fillfactor=10); +) WITH (fillfactor=10, autovacuum_enabled=off); 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, + cidr '10.2.3/24' + tenthous, substr(stringu1, 1, 1)::bpchar, date '1995-08-15' + tenthous, time '01:20:30' + thousand * interval '18.5 second', timestamp '1942-07-23 03:05:09' + tenthous * interval '36.38 hours', timestamptz '1972-10-10 03:00' + thousand * interval '1 hour', justify_days(justify_hours(tenthous * interval '12 minutes')), - timetz '01:30:20' + hundred * interval '15 seconds', + timetz '01:30:20+02' + hundred * interval '15 seconds', thousand::bit(10), tenthous::bit(16)::varbit, tenthous::numeric(36,30) * fivethous * even / (hundred + 1), format('%s%s-%s-%s-%s-%s%s%s', to_char(tenthous, 'FM0000'), to_char(tenthous, 'FM0000'), to_char(tenthous, 'FM0000'), to_char(tenthous, 'FM0000'), to_char(tenthous, 'FM0000'), to_char(tenthous, 'FM0000'), to_char(tenthous, 'FM0000'), to_char(tenthous, 'FM0000'))::uuid, format('%s/%s%s', odd, even, tenthous)::pg_lsn -FROM tenk1 LIMIT 5; --- throw in some NULL-only tuples too -INSERT INTO brintest SELECT NULL FROM tenk1 LIMIT 25; +FROM tenk1 LIMIT 25; +-- throw in some NULL's and different values +INSERT INTO brintest (inetcol, cidrcol) SELECT + inet 'fe80::6e40:8ff:fea9:8c46' + tenthous, + cidr 'fe80::6e40:8ff:fea9:8c46' + tenthous +FROM tenk1 LIMIT 25; CREATE INDEX brinidx ON brintest USING brin ( byteacol, charcol, @@ -79,72 +84,118 @@ CREATE INDEX brinidx ON brintest USING brin ( uuidcol, lsncol ) with (pages_per_range = 1); -BEGIN; -CREATE TABLE brinopers (colname name, op text[], value text[], +CREATE TABLE brinopers (colname name, typ text, 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}'); -COMMIT; +INSERT INTO brinopers VALUES + ('byteacol', 'bytea', '{>, >=, =, <=, <}', '{AAAAAA, AAAAAA, BNAAAABNAAAABNAAAABNAAAABNAAAABNAAAABNAAAABNAAAA, ZZZZZZ, ZZZZZZ}'), + ('charcol', 'char', '{>, >=, =, <=, <}', '{A, A, M, Z, Z}'), + ('namecol', 'name', '{>, >=, =, <=, <}', '{AAAAAA, AAAAAA, MAAAAA, ZZAAAA, ZZAAAA}'), + ('int2col', 'int2', '{>, >=, =, <=, <}', '{0, 0, 800, 999, 999}'), + ('int2col', 'int4', '{>, >=, =, <=, <}', '{0, 0, 800, 999, 1999}'), + ('int2col', 'int8', '{>, >=, =, <=, <}', '{0, 0, 800, 999, 1428427143}'), + ('int4col', 'int2', '{>, >=, =, <=, <}', '{0, 0, 800, 1999, 1999}'), + ('int4col', 'int4', '{>, >=, =, <=, <}', '{0, 0, 800, 1999, 1999}'), + ('int4col', 'int8', '{>, >=, =, <=, <}', '{0, 0, 800, 1999, 1428427143}'), + ('int8col', 'int2', '{>, >=}', '{0, 0}'), + ('int8col', 'int4', '{>, >=}', '{0, 0}'), + ('int8col', 'int8', '{>, >=, =, <=, <}', '{0, 0, 1257141600, 1428427143, 1428427143}'), + ('textcol', 'text', '{>, >=, =, <=, <}', '{AAAAAA, AAAAAA, BNAAAABNAAAABNAAAABNAAAABNAAAABNAAAABNAAAABNAAAA, ZZAAAA, ZZAAAA}'), + ('oidcol', 'oid', '{>, >=, =, <=, <}', '{0, 0, 8800, 9999, 9999}'), + ('tidcol', 'tid', '{>, >=, =, <=, <}', '{"(0,0)", "(0,0)", "(8800,0)", "(9999,19)", "(9999,19)"}'), + ('float4col', 'float4', '{>, >=, =, <=, <}', '{0.0103093, 0.0103093, 1, 1, 1}'), + ('float4col', 'float8', '{>, >=, =, <=, <}', '{0.0103093, 0.0103093, 1, 1, 1}'), + ('float8col', 'float4', '{>, >=, =, <=, <}', '{0, 0, 0, 1.98, 1.98}'), + ('float8col', 'float8', '{>, >=, =, <=, <}', '{0, 0, 0, 1.98, 1.98}'), + ('macaddrcol', 'macaddr', '{>, >=, =, <=, <}', '{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}'), + ('inetcol', 'inet', '{&&, =, <, <=, >, >=, >>=, >>, <<=, <<}', '{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', 'inet', '{&&, >>=, <<=, =}', '{fe80::6e40:8ff:fea9:a673/32, fe80::6e40:8ff:fea9:8c46, fe80::6e40:8ff:fea9:a673/32, fe80::6e40:8ff:fea9:8c46}'), + ('inetcol', 'cidr', '{&&, <, <=, >, >=, >>=, >>, <<=, <<}', '{10/8, 255.255.255.255, 255.255.255.255, 0.0.0.0, 0.0.0.0, 10.2.14/24, 10.2.14/25, 10/8, 0/0}'), + ('inetcol', 'cidr', '{&&, >>=, <<=, =}', '{fe80::/32, fe80::6e40:8ff:fea9:8c46, fe80::/32, fe80::6e40:8ff:fea9:8c46}'), + ('cidrcol', 'inet', '{&&, =, <, <=, >, >=, >>=, >>, <<=, <<}', '{10/8, 10.2.14/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}'), + ('cidrcol', 'inet', '{&&, >>=, <<=, =}', '{fe80::6e40:8ff:fea9:a673/32, fe80::6e40:8ff:fea9:8c46, fe80::6e40:8ff:fea9:a673/32, fe80::6e40:8ff:fea9:8c46}'), + ('cidrcol', 'cidr', '{&&, =, <, <=, >, >=, >>=, >>, <<=, <<}', '{10/8, 10.2.14/24, 255.255.255.255, 255.255.255.255, 0.0.0.0, 0.0.0.0, 10.2.14/24, 10.2.14/25, 10/8, 0/0}'), + ('cidrcol', 'cidr', '{&&, >>=, <<=, =}', '{fe80::/32, fe80::6e40:8ff:fea9:8c46, fe80::/32, fe80::6e40:8ff:fea9:8c46}'), + ('bpcharcol', 'bpchar', '{>, >=, =, <=, <}', '{A, A, W, Z, Z}'), + ('datecol', 'date', '{>, >=, =, <=, <}', '{1995-08-15, 1995-08-15, 2009-12-01, 2022-12-30, 2022-12-30}'), + ('timecol', 'time', '{>, >=, =, <=, <}', '{01:20:30, 01:20:30, 02:28:57, 06:28:31.5, 06:28:31.5}'), + ('timestampcol', 'timestamp', '{>, >=, =, <=, <}', '{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}'), + ('timestampcol', 'timestamptz', '{>, >=, =, <=, <}', '{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}'), + ('timestampcol', 'timestamptz', '{>, >=, =, <=, <}', '{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', 'timestamptz', '{>, >=, =, <=, <}', '{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', 'interval', '{>, >=, =, <=, <}', '{00:00:00, 00:00:00, 1 mons 13 days 12:24, 2 mons 23 days 07:48:00, 1 year}'), + ('timetzcol', 'timetz', '{>, >=, =, <=, <}', '{01:30:20+02, 01:30:20+02, 01:35:50+02, 23:55:05+02, 23:55:05+02}'), + ('bitcol', 'bit(10)', '{>, >=, =, <=, <}', '{0000000010, 0000000010, 0011011110, 1111111000, 1111111000}'), + ('varbitcol', 'varbit(16)', '{>, >=, =, <=, <}', '{0000000000000100, 0000000000000100, 0001010001100110, 1111111111111000, 1111111111111000}'), + ('numericcol', 'numeric', '{>, >=, =, <=, <}', '{0.00, 0.01, 2268164.347826086956521739130434782609, 99470151.9, 99470151.9}'), + ('uuidcol', 'uuid', '{>, >=, =, <=, <}', '{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}'), + ('lsncol', 'pg_lsn', '{>, >=, =, <=, <, IS, IS NOT}', '{0/1200, 0/1200, 44/455222, 198/1999799, 198/1999799, NULL, NULL}'); DO $x$ DECLARE - r record; - tabname text; - tabname_ss text; - count int; - query text; - plan text; + r record; + r2 record; + cond text; + count int; + mismatch bool; 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); - -- run the query using the brin index - SET enable_seqscan = 0; - SET enable_bitmapscan = 1; - EXECUTE format('create temp table %s (tid tid) ON COMMIT DROP', tabname); - EXECUTE query; + FOR r IN SELECT colname, oper, typ, value[ordinality] FROM brinopers, unnest(op) WITH ORDINALITY AS oper LOOP + mismatch := false; + + -- prepare the condition + IF r.value 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($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; + EXECUTE format($y$INSERT INTO brin_result_ss SELECT ctid FROM brintest WHERE %s $y$, cond); + + -- make sure both return the same results + PERFORM * FROM brin_result EXCEPT ALL SELECT * FROM brin_result_ss; + GET DIAGNOSTICS count = ROW_COUNT; + IF count <> 0 THEN + mismatch = true; + END IF; + PERFORM * FROM brin_result_ss EXCEPT ALL SELECT * FROM brin_result; + GET DIAGNOSTICS count = ROW_COUNT; + IF count <> 0 THEN + mismatch = true; + END IF; + + -- report the results of each scan to make the differences obvious + IF mismatch THEN + RAISE WARNING 'something not right in %: count %', r, count; + SET enable_seqscan = 1; + SET enable_bitmapscan = 0; + FOR r2 IN EXECUTE 'SELECT ' || r.colname || ' FROM brintest WHERE ' || cond LOOP + RAISE NOTICE 'seqscan: %', r2; + END LOOP; + + SET enable_seqscan = 0; + SET enable_bitmapscan = 1; + FOR r2 IN EXECUTE 'SELECT ' || r.colname || ' FROM brintest WHERE ' || cond LOOP + RAISE NOTICE 'bitmapscan: %', r2; + END LOOP; + END IF; - -- run the query using a seqscan - 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; + -- make sure it was a sensible test case + SELECT count(*) INTO count FROM brin_result; + IF count = 0 THEN RAISE WARNING '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); - 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); - 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, @@ -159,6 +210,7 @@ INSERT INTO brintest SELECT 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, + cidr '10.2.3/24' + tenthous, substr(stringu1, 1, 1)::bpchar, date '1995-08-15' + tenthous, time '01:20:30' + thousand * interval '18.5 second', diff --git a/src/test/regress/sql/brin.sql b/src/test/regress/sql/brin.sql index 3aff92529a..6a695bbd20 100644 --- a/src/test/regress/sql/brin.sql +++ b/src/test/regress/sql/brin.sql @@ -11,6 +11,7 @@ CREATE TABLE brintest (byteacol bytea, float8col double precision, macaddrcol macaddr, inetcol inet, + cidrcol cidr, bpcharcol character, datecol date, timecol time without time zone, @@ -23,37 +24,41 @@ CREATE TABLE brintest (byteacol bytea, numericcol numeric, uuidcol uuid, lsncol pg_lsn -) WITH (fillfactor=10); +) WITH (fillfactor=10, autovacuum_enabled=off); 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, + cidr '10.2.3/24' + tenthous, substr(stringu1, 1, 1)::bpchar, date '1995-08-15' + tenthous, time '01:20:30' + thousand * interval '18.5 second', timestamp '1942-07-23 03:05:09' + tenthous * interval '36.38 hours', timestamptz '1972-10-10 03:00' + thousand * interval '1 hour', justify_days(justify_hours(tenthous * interval '12 minutes')), - timetz '01:30:20' + hundred * interval '15 seconds', + timetz '01:30:20+02' + hundred * interval '15 seconds', thousand::bit(10), tenthous::bit(16)::varbit, tenthous::numeric(36,30) * fivethous * even / (hundred + 1), format('%s%s-%s-%s-%s-%s%s%s', to_char(tenthous, 'FM0000'), to_char(tenthous, 'FM0000'), to_char(tenthous, 'FM0000'), to_char(tenthous, 'FM0000'), to_char(tenthous, 'FM0000'), to_char(tenthous, 'FM0000'), to_char(tenthous, 'FM0000'), to_char(tenthous, 'FM0000'))::uuid, format('%s/%s%s', odd, even, tenthous)::pg_lsn -FROM tenk1 LIMIT 5; +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, cidrcol) SELECT + inet 'fe80::6e40:8ff:fea9:8c46' + tenthous, + cidr 'fe80::6e40:8ff:fea9:8c46' + tenthous +FROM tenk1 LIMIT 25; CREATE INDEX brinidx ON brintest USING brin ( byteacol, @@ -83,74 +88,120 @@ CREATE INDEX brinidx ON brintest USING brin ( lsncol ) with (pages_per_range = 1); -BEGIN; -CREATE TABLE brinopers (colname name, op text[], value text[], +CREATE TABLE brinopers (colname name, typ text, 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}'); -COMMIT; +INSERT INTO brinopers VALUES + ('byteacol', 'bytea', '{>, >=, =, <=, <}', '{AAAAAA, AAAAAA, BNAAAABNAAAABNAAAABNAAAABNAAAABNAAAABNAAAABNAAAA, ZZZZZZ, ZZZZZZ}'), + ('charcol', 'char', '{>, >=, =, <=, <}', '{A, A, M, Z, Z}'), + ('namecol', 'name', '{>, >=, =, <=, <}', '{AAAAAA, AAAAAA, MAAAAA, ZZAAAA, ZZAAAA}'), + ('int2col', 'int2', '{>, >=, =, <=, <}', '{0, 0, 800, 999, 999}'), + ('int2col', 'int4', '{>, >=, =, <=, <}', '{0, 0, 800, 999, 1999}'), + ('int2col', 'int8', '{>, >=, =, <=, <}', '{0, 0, 800, 999, 1428427143}'), + ('int4col', 'int2', '{>, >=, =, <=, <}', '{0, 0, 800, 1999, 1999}'), + ('int4col', 'int4', '{>, >=, =, <=, <}', '{0, 0, 800, 1999, 1999}'), + ('int4col', 'int8', '{>, >=, =, <=, <}', '{0, 0, 800, 1999, 1428427143}'), + ('int8col', 'int2', '{>, >=}', '{0, 0}'), + ('int8col', 'int4', '{>, >=}', '{0, 0}'), + ('int8col', 'int8', '{>, >=, =, <=, <}', '{0, 0, 1257141600, 1428427143, 1428427143}'), + ('textcol', 'text', '{>, >=, =, <=, <}', '{AAAAAA, AAAAAA, BNAAAABNAAAABNAAAABNAAAABNAAAABNAAAABNAAAABNAAAA, ZZAAAA, ZZAAAA}'), + ('oidcol', 'oid', '{>, >=, =, <=, <}', '{0, 0, 8800, 9999, 9999}'), + ('tidcol', 'tid', '{>, >=, =, <=, <}', '{"(0,0)", "(0,0)", "(8800,0)", "(9999,19)", "(9999,19)"}'), + ('float4col', 'float4', '{>, >=, =, <=, <}', '{0.0103093, 0.0103093, 1, 1, 1}'), + ('float4col', 'float8', '{>, >=, =, <=, <}', '{0.0103093, 0.0103093, 1, 1, 1}'), + ('float8col', 'float4', '{>, >=, =, <=, <}', '{0, 0, 0, 1.98, 1.98}'), + ('float8col', 'float8', '{>, >=, =, <=, <}', '{0, 0, 0, 1.98, 1.98}'), + ('macaddrcol', 'macaddr', '{>, >=, =, <=, <}', '{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}'), + ('inetcol', 'inet', '{&&, =, <, <=, >, >=, >>=, >>, <<=, <<}', '{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', 'inet', '{&&, >>=, <<=, =}', '{fe80::6e40:8ff:fea9:a673/32, fe80::6e40:8ff:fea9:8c46, fe80::6e40:8ff:fea9:a673/32, fe80::6e40:8ff:fea9:8c46}'), + ('inetcol', 'cidr', '{&&, <, <=, >, >=, >>=, >>, <<=, <<}', '{10/8, 255.255.255.255, 255.255.255.255, 0.0.0.0, 0.0.0.0, 10.2.14/24, 10.2.14/25, 10/8, 0/0}'), + ('inetcol', 'cidr', '{&&, >>=, <<=, =}', '{fe80::/32, fe80::6e40:8ff:fea9:8c46, fe80::/32, fe80::6e40:8ff:fea9:8c46}'), + ('cidrcol', 'inet', '{&&, =, <, <=, >, >=, >>=, >>, <<=, <<}', '{10/8, 10.2.14/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}'), + ('cidrcol', 'inet', '{&&, >>=, <<=, =}', '{fe80::6e40:8ff:fea9:a673/32, fe80::6e40:8ff:fea9:8c46, fe80::6e40:8ff:fea9:a673/32, fe80::6e40:8ff:fea9:8c46}'), + ('cidrcol', 'cidr', '{&&, =, <, <=, >, >=, >>=, >>, <<=, <<}', '{10/8, 10.2.14/24, 255.255.255.255, 255.255.255.255, 0.0.0.0, 0.0.0.0, 10.2.14/24, 10.2.14/25, 10/8, 0/0}'), + ('cidrcol', 'cidr', '{&&, >>=, <<=, =}', '{fe80::/32, fe80::6e40:8ff:fea9:8c46, fe80::/32, fe80::6e40:8ff:fea9:8c46}'), + ('bpcharcol', 'bpchar', '{>, >=, =, <=, <}', '{A, A, W, Z, Z}'), + ('datecol', 'date', '{>, >=, =, <=, <}', '{1995-08-15, 1995-08-15, 2009-12-01, 2022-12-30, 2022-12-30}'), + ('timecol', 'time', '{>, >=, =, <=, <}', '{01:20:30, 01:20:30, 02:28:57, 06:28:31.5, 06:28:31.5}'), + ('timestampcol', 'timestamp', '{>, >=, =, <=, <}', '{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}'), + ('timestampcol', 'timestamptz', '{>, >=, =, <=, <}', '{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}'), + ('timestampcol', 'timestamptz', '{>, >=, =, <=, <}', '{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', 'timestamptz', '{>, >=, =, <=, <}', '{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', 'interval', '{>, >=, =, <=, <}', '{00:00:00, 00:00:00, 1 mons 13 days 12:24, 2 mons 23 days 07:48:00, 1 year}'), + ('timetzcol', 'timetz', '{>, >=, =, <=, <}', '{01:30:20+02, 01:30:20+02, 01:35:50+02, 23:55:05+02, 23:55:05+02}'), + ('bitcol', 'bit(10)', '{>, >=, =, <=, <}', '{0000000010, 0000000010, 0011011110, 1111111000, 1111111000}'), + ('varbitcol', 'varbit(16)', '{>, >=, =, <=, <}', '{0000000000000100, 0000000000000100, 0001010001100110, 1111111111111000, 1111111111111000}'), + ('numericcol', 'numeric', '{>, >=, =, <=, <}', '{0.00, 0.01, 2268164.347826086956521739130434782609, 99470151.9, 99470151.9}'), + ('uuidcol', 'uuid', '{>, >=, =, <=, <}', '{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}'), + ('lsncol', 'pg_lsn', '{>, >=, =, <=, <, IS, IS NOT}', '{0/1200, 0/1200, 44/455222, 198/1999799, 198/1999799, NULL, NULL}'); DO $x$ DECLARE - r record; - tabname text; - tabname_ss text; - count int; - query text; - plan text; + r record; + r2 record; + cond text; + count int; + mismatch bool; 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); - -- run the query using the brin index - SET enable_seqscan = 0; - SET enable_bitmapscan = 1; - EXECUTE format('create temp table %s (tid tid) ON COMMIT DROP', tabname); - EXECUTE query; - - -- run the query using a seqscan - 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; - - -- make sure both return the same results - EXECUTE format('SELECT * from %s EXCEPT ALL SELECT * FROM %s', tabname, tabname_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); - GET DIAGNOSTICS count = ROW_COUNT; - IF count <> 0 THEN RAISE EXCEPTION 'something not right in %: count %', r, count; END IF; - end loop; -end; + FOR r IN SELECT colname, oper, typ, value[ordinality] FROM brinopers, unnest(op) WITH ORDINALITY AS oper LOOP + mismatch := false; + + -- prepare the condition + IF r.value 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($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; + EXECUTE format($y$INSERT INTO brin_result_ss SELECT ctid FROM brintest WHERE %s $y$, cond); + + -- make sure both return the same results + PERFORM * FROM brin_result EXCEPT ALL SELECT * FROM brin_result_ss; + GET DIAGNOSTICS count = ROW_COUNT; + IF count <> 0 THEN + mismatch = true; + END IF; + PERFORM * FROM brin_result_ss EXCEPT ALL SELECT * FROM brin_result; + GET DIAGNOSTICS count = ROW_COUNT; + IF count <> 0 THEN + mismatch = true; + END IF; + + -- report the results of each scan to make the differences obvious + IF mismatch THEN + RAISE WARNING 'something not right in %: count %', r, count; + SET enable_seqscan = 1; + SET enable_bitmapscan = 0; + FOR r2 IN EXECUTE 'SELECT ' || r.colname || ' FROM brintest WHERE ' || cond LOOP + RAISE NOTICE 'seqscan: %', r2; + END LOOP; + + SET enable_seqscan = 0; + SET enable_bitmapscan = 1; + FOR r2 IN EXECUTE 'SELECT ' || r.colname || ' FROM brintest WHERE ' || cond LOOP + RAISE NOTICE 'bitmapscan: %', r2; + END LOOP; + END IF; + + -- make sure it was a sensible test case + SELECT count(*) INTO count FROM brin_result; + IF count = 0 THEN RAISE WARNING 'no results for %', r; END IF; + + -- drop the temporary tables + DROP TABLE brin_result; + DROP TABLE brin_result_ss; + END LOOP; +END; $x$; INSERT INTO brintest SELECT @@ -166,6 +217,7 @@ INSERT INTO brintest SELECT 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, + cidr '10.2.3/24' + tenthous, substr(stringu1, 1, 1)::bpchar, date '1995-08-15' + tenthous, time '01:20:30' + thousand * interval '18.5 second',