From 7bbafab1085dea175ef7e54ac8513c633fe77461 Mon Sep 17 00:00:00 2001 From: Tomas Vondra Date: Sat, 11 Feb 2023 19:43:38 +0100 Subject: [PATCH 6/9] Support SK_SEARCHARRAY in BRIN minmax-multi Similar approach to minmax, but the issues with deconstructing the array over and over are even more serious. --- src/backend/access/brin/brin_minmax_multi.c | 439 +++++++++++++++++--- src/include/catalog/pg_amproc.dat | 57 +++ src/include/catalog/pg_proc.dat | 4 + 3 files changed, 434 insertions(+), 66 deletions(-) diff --git a/src/backend/access/brin/brin_minmax_multi.c b/src/backend/access/brin/brin_minmax_multi.c index 859e0022fb..b70116d33b 100644 --- a/src/backend/access/brin/brin_minmax_multi.c +++ b/src/backend/access/brin/brin_minmax_multi.c @@ -109,6 +109,14 @@ #define MINMAX_BUFFER_MAX 8192 #define MINMAX_BUFFER_LOAD_FACTOR 0.5 +/* + * We use some private sk_flags bits in preprocessed scan keys. We're allowed + * to use bits 16-31 (see skey.h). The uppermost bits are copied from the + * index's indoption[] array entry for the index attribute. + */ +#define SK_BRIN_SORTED 0x00010000 /* deconstructed and sorted array */ + + typedef struct MinmaxMultiOpaque { FmgrInfo extra_procinfos[MINMAX_MAX_PROCNUMS]; @@ -2562,6 +2570,132 @@ brin_minmax_multi_add_value(PG_FUNCTION_ARGS) PG_RETURN_BOOL(modified); } + +static int +compare_array_values(const void *a, const void *b, void *arg) +{ + Datum da = * (Datum *) a; + Datum db = * (Datum *) b; + SortSupport ssup = (SortSupport) arg; + + return ApplySortComparator(da, false, db, false, ssup); +} + +/* + * lower_boundary + * Determine lowest index so that (values[index] >= minvalue). + * + * The array of values is expected to be sorted, so this is the first value + * that may fall into the [minvalue, maxvalue] range, as it exceeds minval. + * It's not guaranteed, though, as it might exceed maxvalue too. + */ +static int +lower_boundary(Datum *values, int nvalues, Datum minvalue, SortSupport ssup) +{ + int start = 0, + end = (nvalues - 1); + + /* everything exceeds minval and might match */ + if (compare_array_values(&minvalue, &values[start], ssup) <= 0) + return 0; + + /* nothing could match */ + if (compare_array_values(&minvalue, &values[end], ssup) > 0) + return nvalues; + + while ((end - start) > 0) + { + int midpoint; + int r; + + midpoint = start + (end - start) / 2; + + r = compare_array_values(&minvalue, &values[midpoint], ssup); + + if (r > 0) + start = Max(midpoint, start + 1); + else + end = midpoint; + } + + /* the value should meet the (v >=minvalue) requirement */ + Assert(compare_array_values(&values[start], &minvalue, ssup) >= 0); + + /* we know start can't be 0, so it's legal to subtract 1 */ + Assert(compare_array_values(&values[start-1], &minvalue, ssup) < 0); + + return start; +} + +typedef struct ScanKeyArray { + Oid typeid; + int nelements; + Datum *elements; +} ScanKeyArray; + +Datum +brin_minmax_multi_preprocess(PG_FUNCTION_ARGS) +{ + // BrinDesc *bdesc = (BrinDesc *) PG_GETARG_POINTER(0); + ScanKey key = (ScanKey) PG_GETARG_POINTER(1); + ScanKey newkey; + ScanKeyArray *scanarray; + + ArrayType *arrayval; + int16 elmlen; + bool elmbyval; + char elmalign; + int num_elems; + Datum *elem_values; + bool *elem_nulls; + TypeCacheEntry *type; + SortSupportData ssup; + + /* ignore scalar keys */ + if (!(key->sk_flags & SK_SEARCHARRAY)) + PG_RETURN_POINTER(key); + + arrayval = DatumGetArrayTypeP(key->sk_argument); + + get_typlenbyvalalign(ARR_ELEMTYPE(arrayval), + &elmlen, &elmbyval, &elmalign); + + deconstruct_array(arrayval, + ARR_ELEMTYPE(arrayval), + elmlen, elmbyval, elmalign, + &elem_values, &elem_nulls, &num_elems); + + type = lookup_type_cache(ARR_ELEMTYPE(arrayval), TYPECACHE_LT_OPR); + + memset(&ssup, 0, sizeof(SortSupportData)); + + ssup.ssup_collation = key->sk_collation; + ssup.ssup_cxt = CurrentMemoryContext; + + PrepareSortSupportFromOrderingOp(type->lt_opr, &ssup); + + qsort_interruptible(elem_values, num_elems, sizeof(Datum), + compare_array_values, &ssup); + + scanarray = palloc0(sizeof(ScanKeyArray)); + scanarray->typeid = ARR_ELEMTYPE(arrayval); + scanarray->nelements = num_elems; + scanarray->elements = elem_values; + + newkey = palloc0(sizeof(ScanKeyData)); + + ScanKeyEntryInitializeWithInfo(newkey, + (key->sk_flags | SK_BRIN_SORTED), + key->sk_attno, + key->sk_strategy, + key->sk_subtype, + key->sk_collation, + &key->sk_func, + PointerGetDatum(scanarray)); + + PG_RETURN_POINTER(newkey); +} + /* * Given an index tuple corresponding to a certain page range and a scan key, * return whether the scan key is consistent with the index tuple's min/max @@ -2591,6 +2725,15 @@ brin_minmax_multi_consistent(PG_FUNCTION_ARGS) serialized = (SerializedRanges *) PG_DETOAST_DATUM(column->bv_values[0]); ranges = brin_range_deserialize(serialized->maxvalues, serialized); + /* + * XXX Would it make sense to have a quick initial check on the whole + * summary? We know most page ranges are not expected to match, and we + * know the ranges/values are sorted so we could check global min/max + * (essentially what regular minmax is doing) and bail if no match is + * possible. That should be cheap and might save a lot on inspecting + * the individual ranges/values. + */ + /* inspect the ranges, and for each one evaluate the scan keys */ for (rangeno = 0; rangeno < ranges->nranges; rangeno++) { @@ -2611,67 +2754,179 @@ brin_minmax_multi_consistent(PG_FUNCTION_ARGS) attno = key->sk_attno; subtype = key->sk_subtype; value = key->sk_argument; - switch (key->sk_strategy) - { - case BTLessStrategyNumber: - case BTLessEqualStrategyNumber: - finfo = minmax_multi_get_strategy_procinfo(bdesc, attno, subtype, - key->sk_strategy); - /* first value from the array */ - matches = FunctionCall2Coll(finfo, colloid, minval, value); - break; - case BTEqualStrategyNumber: - { - Datum compar; - FmgrInfo *cmpFn; + if (likely(!(key->sk_flags & SK_BRIN_SORTED))) + { + switch (key->sk_strategy) + { + case BTLessStrategyNumber: + case BTLessEqualStrategyNumber: + finfo = minmax_multi_get_strategy_procinfo(bdesc, attno, subtype, + key->sk_strategy); + /* first value from the array */ + matches = FunctionCall2Coll(finfo, colloid, minval, value); + break; - /* by default this range does not match */ - matches = BoolGetDatum(false); + case BTEqualStrategyNumber: + { + Datum compar; + FmgrInfo *cmpFn; + + /* by default this range does not match */ + matches = BoolGetDatum(false); + + /* + * Otherwise, need to compare the new value with + * boundaries of all the ranges. First check if it's + * less than the absolute minimum, which is the first + * value in the array. + */ + cmpFn = minmax_multi_get_strategy_procinfo(bdesc, attno, subtype, + BTGreaterStrategyNumber); + compar = FunctionCall2Coll(cmpFn, colloid, minval, value); + + /* smaller than the smallest value in this range */ + if (DatumGetBool(compar)) + break; + + cmpFn = minmax_multi_get_strategy_procinfo(bdesc, attno, subtype, + BTLessStrategyNumber); + compar = FunctionCall2Coll(cmpFn, colloid, maxval, value); + + /* larger than the largest value in this range */ + if (DatumGetBool(compar)) + break; + + /* + * We haven't managed to eliminate this range, so + * consider it matching. + */ + matches = BoolGetDatum(true); - /* - * Otherwise, need to compare the new value with - * boundaries of all the ranges. First check if it's - * less than the absolute minimum, which is the first - * value in the array. - */ - cmpFn = minmax_multi_get_strategy_procinfo(bdesc, attno, subtype, - BTGreaterStrategyNumber); - compar = FunctionCall2Coll(cmpFn, colloid, minval, value); - - /* smaller than the smallest value in this range */ - if (DatumGetBool(compar)) break; + } + case BTGreaterEqualStrategyNumber: + case BTGreaterStrategyNumber: + finfo = minmax_multi_get_strategy_procinfo(bdesc, attno, subtype, + key->sk_strategy); + /* last value from the array */ + matches = FunctionCall2Coll(finfo, colloid, maxval, value); + break; - cmpFn = minmax_multi_get_strategy_procinfo(bdesc, attno, subtype, - BTLessStrategyNumber); - compar = FunctionCall2Coll(cmpFn, colloid, maxval, value); + default: + /* shouldn't happen */ + elog(ERROR, "invalid strategy number %d", key->sk_strategy); + matches = BoolGetDatum(false); + break; + } + } + else + { + ScanKeyArray *array = (ScanKeyArray *) value; - /* larger than the largest value in this range */ - if (DatumGetBool(compar)) - break; + switch (key->sk_strategy) + { + case BTLessStrategyNumber: + case BTLessEqualStrategyNumber: + finfo = minmax_multi_get_strategy_procinfo(bdesc, attno, subtype, + key->sk_strategy); + /* first value from the array */ + matches = FunctionCall2Coll(finfo, colloid, minval, + array->elements[array->nelements-1]); + break; + + case BTEqualStrategyNumber: /* - * We haven't managed to eliminate this range, so - * consider it matching. + * See brin_minmax.c for description of what this is doing. */ - matches = BoolGetDatum(true); - + { + Datum val; + SortSupportData ssup; + int lower; + TypeCacheEntry *type; + + /* Is the first (smallest) value after the BRIN range? */ + val = array->elements[0]; + + finfo = minmax_multi_get_strategy_procinfo(bdesc, attno, subtype, + BTLessEqualStrategyNumber); + matches = FunctionCall2Coll(finfo, colloid, val, maxval); + + /* minval > max(range values) */ + if (!DatumGetBool(matches)) + break; + + /* Is the last (largest) value before the BRIN range? */ + val = array->elements[array->nelements-1]; + + finfo = minmax_multi_get_strategy_procinfo(bdesc, attno, subtype, + BTGreaterEqualStrategyNumber); + matches = FunctionCall2Coll(finfo, colloid, val, minval); + + /* maxval < min(range values) */ + if (!DatumGetBool(matches)) + break; + + /* + * OK, there might be some values matching the range. We have + * to search them one by one, or perhaps try binsearch. + */ + type = lookup_type_cache(array->typeid, TYPECACHE_LT_OPR); + + memset(&ssup, 0, sizeof(SortSupportData)); + + ssup.ssup_collation = key->sk_collation; + ssup.ssup_cxt = CurrentMemoryContext; + + PrepareSortSupportFromOrderingOp(type->lt_opr, &ssup); + + lower = lower_boundary(array->elements, array->nelements, minval, &ssup); + + /* no elements can possibly match */ + if (lower == array->nelements) + { + matches = BoolGetDatum(false); + break; + } + + /* + * OK, the first element must match the upper boundary too + * (if it does not, no following elements can). + */ + val = array->elements[lower]; + + /* + * In the equality case (WHERE col = someval), we want to return + * the current page range if the minimum value in the range <= + * scan key, and the maximum value >= scan key. + */ + finfo = minmax_multi_get_strategy_procinfo(bdesc, attno, subtype, + BTLessEqualStrategyNumber); + matches = FunctionCall2Coll(finfo, colloid, minval, val); + if (!DatumGetBool(matches)) + break; + /* max() >= scankey */ + finfo = minmax_multi_get_strategy_procinfo(bdesc, attno, subtype, + BTGreaterEqualStrategyNumber); + matches = FunctionCall2Coll(finfo, colloid, maxval, val); + break; + } + case BTGreaterEqualStrategyNumber: + case BTGreaterStrategyNumber: + finfo = minmax_multi_get_strategy_procinfo(bdesc, attno, subtype, + key->sk_strategy); + /* last value from the array */ + matches = FunctionCall2Coll(finfo, colloid, maxval, + array->elements[0]); break; - } - case BTGreaterEqualStrategyNumber: - case BTGreaterStrategyNumber: - finfo = minmax_multi_get_strategy_procinfo(bdesc, attno, subtype, - key->sk_strategy); - /* last value from the array */ - matches = FunctionCall2Coll(finfo, colloid, maxval, value); - break; - default: - /* shouldn't happen */ - elog(ERROR, "invalid strategy number %d", key->sk_strategy); - matches = BoolGetDatum(false); - break; + default: + /* shouldn't happen */ + elog(ERROR, "invalid strategy number %d", key->sk_strategy); + matches = BoolGetDatum(false); + break; + } } /* the range has to match all the scan keys */ @@ -2713,24 +2968,76 @@ brin_minmax_multi_consistent(PG_FUNCTION_ARGS) attno = key->sk_attno; subtype = key->sk_subtype; value = key->sk_argument; - switch (key->sk_strategy) + if (likely(!(key->sk_flags & SK_SEARCHARRAY))) { - case BTLessStrategyNumber: - case BTLessEqualStrategyNumber: - case BTEqualStrategyNumber: - case BTGreaterEqualStrategyNumber: - case BTGreaterStrategyNumber: - - finfo = minmax_multi_get_strategy_procinfo(bdesc, attno, subtype, - key->sk_strategy); - matches = FunctionCall2Coll(finfo, colloid, val, value); - break; + switch (key->sk_strategy) + { + case BTLessStrategyNumber: + case BTLessEqualStrategyNumber: + case BTEqualStrategyNumber: + case BTGreaterEqualStrategyNumber: + case BTGreaterStrategyNumber: + + finfo = minmax_multi_get_strategy_procinfo(bdesc, attno, subtype, + key->sk_strategy); + matches = FunctionCall2Coll(finfo, colloid, val, value); + break; - default: - /* shouldn't happen */ - elog(ERROR, "invalid strategy number %d", key->sk_strategy); - matches = BoolGetDatum(false); - break; + default: + /* shouldn't happen */ + elog(ERROR, "invalid strategy number %d", key->sk_strategy); + matches = BoolGetDatum(false); + break; + } + } + else + { + /* + * FIXME This is really wrong, because it deserializes the + * array over and over for each value in the minmax-multi + * summary. + */ + ArrayType *arrayval; + int16 elmlen; + bool elmbyval; + char elmalign; + int num_elems; + Datum *elem_values; + bool *elem_nulls; + + SortSupportData ssup; + int lower; + TypeCacheEntry *type; + + arrayval = DatumGetArrayTypeP(key->sk_argument); + + get_typlenbyvalalign(ARR_ELEMTYPE(arrayval), + &elmlen, &elmbyval, &elmalign); + + deconstruct_array(arrayval, + ARR_ELEMTYPE(arrayval), + elmlen, elmbyval, elmalign, + &elem_values, &elem_nulls, &num_elems); + + /* assume not maches */ + matches = BoolGetDatum(false); + + /* + * OK, there might be some values matching the range. We have + * to search them one by one, or perhaps try binsearch. + */ + type = lookup_type_cache(ARR_ELEMTYPE(arrayval), TYPECACHE_LT_OPR); + + memset(&ssup, 0, sizeof(SortSupportData)); + PrepareSortSupportFromOrderingOp(type->lt_opr, &ssup); + + lower = lower_boundary(elem_values, num_elems, value, &ssup); + + if ((lower < num_elems) && + (compare_array_values(&elem_values[lower], &value, &ssup) == 0)) + { + matches = BoolGetDatum(true); + } } /* the range has to match all the scan keys */ diff --git a/src/include/catalog/pg_amproc.dat b/src/include/catalog/pg_amproc.dat index 166681c31e..4f17f0d58c 100644 --- a/src/include/catalog/pg_amproc.dat +++ b/src/include/catalog/pg_amproc.dat @@ -946,6 +946,9 @@ { amprocfamily => 'brin/integer_minmax_multi_ops', amproclefttype => 'int2', amprocrighttype => 'int2', amprocnum => '5', amproc => 'brin_minmax_multi_options' }, +{ amprocfamily => 'brin/integer_minmax_multi_ops', amproclefttype => 'int2', + amprocrighttype => 'int2', amprocnum => '6', + amproc => 'brin_minmax_multi_preprocess' }, { amprocfamily => 'brin/integer_minmax_multi_ops', amproclefttype => 'int2', amprocrighttype => 'int2', amprocnum => '11', amproc => 'brin_minmax_multi_distance_int2' }, @@ -965,6 +968,9 @@ { amprocfamily => 'brin/integer_minmax_multi_ops', amproclefttype => 'int4', amprocrighttype => 'int4', amprocnum => '5', amproc => 'brin_minmax_multi_options' }, +{ amprocfamily => 'brin/integer_minmax_multi_ops', amproclefttype => 'int4', + amprocrighttype => 'int4', amprocnum => '6', + amproc => 'brin_minmax_multi_preprocess' }, { amprocfamily => 'brin/integer_minmax_multi_ops', amproclefttype => 'int4', amprocrighttype => 'int4', amprocnum => '11', amproc => 'brin_minmax_multi_distance_int4' }, @@ -984,6 +990,9 @@ { amprocfamily => 'brin/integer_minmax_multi_ops', amproclefttype => 'int8', amprocrighttype => 'int8', amprocnum => '5', amproc => 'brin_minmax_multi_options' }, +{ amprocfamily => 'brin/integer_minmax_multi_ops', amproclefttype => 'int8', + amprocrighttype => 'int8', amprocnum => '6', + amproc => 'brin_minmax_multi_preprocess' }, { amprocfamily => 'brin/integer_minmax_multi_ops', amproclefttype => 'int8', amprocrighttype => 'int8', amprocnum => '11', amproc => 'brin_minmax_multi_distance_int8' }, @@ -1095,6 +1104,9 @@ { amprocfamily => 'brin/oid_minmax_multi_ops', amproclefttype => 'oid', amprocrighttype => 'oid', amprocnum => '5', amproc => 'brin_minmax_multi_options' }, +{ amprocfamily => 'brin/oid_minmax_multi_ops', amproclefttype => 'oid', + amprocrighttype => 'oid', amprocnum => '6', + amproc => 'brin_minmax_multi_preprocess' }, { amprocfamily => 'brin/oid_minmax_multi_ops', amproclefttype => 'oid', amprocrighttype => 'oid', amprocnum => '11', amproc => 'brin_minmax_multi_distance_int4' }, @@ -1161,6 +1173,9 @@ { amprocfamily => 'brin/tid_minmax_multi_ops', amproclefttype => 'tid', amprocrighttype => 'tid', amprocnum => '5', amproc => 'brin_minmax_multi_options' }, +{ amprocfamily => 'brin/tid_minmax_multi_ops', amproclefttype => 'tid', + amprocrighttype => 'tid', amprocnum => '6', + amproc => 'brin_minmax_multi_preprocess' }, { amprocfamily => 'brin/tid_minmax_multi_ops', amproclefttype => 'tid', amprocrighttype => 'tid', amprocnum => '11', amproc => 'brin_minmax_multi_distance_tid' }, @@ -1214,6 +1229,9 @@ { amprocfamily => 'brin/float_minmax_multi_ops', amproclefttype => 'float4', amprocrighttype => 'float4', amprocnum => '5', amproc => 'brin_minmax_multi_options' }, +{ amprocfamily => 'brin/float_minmax_multi_ops', amproclefttype => 'float4', + amprocrighttype => 'float4', amprocnum => '6', + amproc => 'brin_minmax_multi_preprocess' }, { amprocfamily => 'brin/float_minmax_multi_ops', amproclefttype => 'float4', amprocrighttype => 'float4', amprocnum => '11', amproc => 'brin_minmax_multi_distance_float4' }, @@ -1233,6 +1251,9 @@ { amprocfamily => 'brin/float_minmax_multi_ops', amproclefttype => 'float8', amprocrighttype => 'float8', amprocnum => '5', amproc => 'brin_minmax_multi_options' }, +{ amprocfamily => 'brin/float_minmax_multi_ops', amproclefttype => 'float8', + amprocrighttype => 'float8', amprocnum => '6', + amproc => 'brin_minmax_multi_preprocess' }, { amprocfamily => 'brin/float_minmax_multi_ops', amproclefttype => 'float8', amprocrighttype => 'float8', amprocnum => '11', amproc => 'brin_minmax_multi_distance_float8' }, @@ -1305,6 +1326,9 @@ { amprocfamily => 'brin/macaddr_minmax_multi_ops', amproclefttype => 'macaddr', amprocrighttype => 'macaddr', amprocnum => '5', amproc => 'brin_minmax_multi_options' }, +{ amprocfamily => 'brin/macaddr_minmax_multi_ops', amproclefttype => 'macaddr', + amprocrighttype => 'macaddr', amprocnum => '6', + amproc => 'brin_minmax_multi_preprocess' }, { amprocfamily => 'brin/macaddr_minmax_multi_ops', amproclefttype => 'macaddr', amprocrighttype => 'macaddr', amprocnum => '11', amproc => 'brin_minmax_multi_distance_macaddr' }, @@ -1361,6 +1385,9 @@ { amprocfamily => 'brin/macaddr8_minmax_multi_ops', amproclefttype => 'macaddr8', amprocrighttype => 'macaddr8', amprocnum => '5', amproc => 'brin_minmax_multi_options' }, +{ amprocfamily => 'brin/macaddr8_minmax_multi_ops', + amproclefttype => 'macaddr8', amprocrighttype => 'macaddr8', amprocnum => '6', + amproc => 'brin_minmax_multi_preprocess' }, { amprocfamily => 'brin/macaddr8_minmax_multi_ops', amproclefttype => 'macaddr8', amprocrighttype => 'macaddr8', amprocnum => '11', amproc => 'brin_minmax_multi_distance_macaddr8' }, @@ -1415,6 +1442,9 @@ { amprocfamily => 'brin/network_minmax_multi_ops', amproclefttype => 'inet', amprocrighttype => 'inet', amprocnum => '5', amproc => 'brin_minmax_multi_options' }, +{ amprocfamily => 'brin/network_minmax_multi_ops', amproclefttype => 'inet', + amprocrighttype => 'inet', amprocnum => '6', + amproc => 'brin_minmax_multi_preprocess' }, { amprocfamily => 'brin/network_minmax_multi_ops', amproclefttype => 'inet', amprocrighttype => 'inet', amprocnum => '11', amproc => 'brin_minmax_multi_distance_inet' }, @@ -1521,6 +1551,9 @@ { amprocfamily => 'brin/time_minmax_multi_ops', amproclefttype => 'time', amprocrighttype => 'time', amprocnum => '5', amproc => 'brin_minmax_multi_options' }, +{ amprocfamily => 'brin/time_minmax_multi_ops', amproclefttype => 'time', + amprocrighttype => 'time', amprocnum => '6', + amproc => 'brin_minmax_multi_preprocess' }, { amprocfamily => 'brin/time_minmax_multi_ops', amproclefttype => 'time', amprocrighttype => 'time', amprocnum => '11', amproc => 'brin_minmax_multi_distance_time' }, @@ -1604,6 +1637,9 @@ { amprocfamily => 'brin/datetime_minmax_multi_ops', amproclefttype => 'timestamp', amprocrighttype => 'timestamp', amprocnum => '5', amproc => 'brin_minmax_multi_options' }, +{ amprocfamily => 'brin/datetime_minmax_multi_ops', + amproclefttype => 'timestamp', amprocrighttype => 'timestamp', + amprocnum => '6', amproc => 'brin_minmax_multi_preprocess' }, { amprocfamily => 'brin/datetime_minmax_multi_ops', amproclefttype => 'timestamp', amprocrighttype => 'timestamp', amprocnum => '11', amproc => 'brin_minmax_multi_distance_timestamp' }, @@ -1623,6 +1659,9 @@ { amprocfamily => 'brin/datetime_minmax_multi_ops', amproclefttype => 'timestamptz', amprocrighttype => 'timestamptz', amprocnum => '5', amproc => 'brin_minmax_multi_options' }, +{ amprocfamily => 'brin/datetime_minmax_multi_ops', + amproclefttype => 'timestamptz', amprocrighttype => 'timestamptz', + amprocnum => '6', amproc => 'brin_minmax_multi_preprocess' }, { amprocfamily => 'brin/datetime_minmax_multi_ops', amproclefttype => 'timestamptz', amprocrighttype => 'timestamptz', amprocnum => '11', amproc => 'brin_minmax_multi_distance_timestamp' }, @@ -1642,6 +1681,9 @@ { amprocfamily => 'brin/datetime_minmax_multi_ops', amproclefttype => 'date', amprocrighttype => 'date', amprocnum => '5', amproc => 'brin_minmax_multi_options' }, +{ amprocfamily => 'brin/datetime_minmax_multi_ops', amproclefttype => 'date', + amprocrighttype => 'date', amprocnum => '6', + amproc => 'brin_minmax_multi_preprocess' }, { amprocfamily => 'brin/datetime_minmax_multi_ops', amproclefttype => 'date', amprocrighttype => 'date', amprocnum => '11', amproc => 'brin_minmax_multi_distance_date' }, @@ -1733,6 +1775,9 @@ { amprocfamily => 'brin/interval_minmax_multi_ops', amproclefttype => 'interval', amprocrighttype => 'interval', amprocnum => '5', amproc => 'brin_minmax_multi_options' }, +{ amprocfamily => 'brin/interval_minmax_multi_ops', + amproclefttype => 'interval', amprocrighttype => 'interval', amprocnum => '6', + amproc => 'brin_minmax_multi_preprocess' }, { amprocfamily => 'brin/interval_minmax_multi_ops', amproclefttype => 'interval', amprocrighttype => 'interval', amprocnum => '11', amproc => 'brin_minmax_multi_distance_interval' }, @@ -1789,6 +1834,9 @@ { amprocfamily => 'brin/timetz_minmax_multi_ops', amproclefttype => 'timetz', amprocrighttype => 'timetz', amprocnum => '5', amproc => 'brin_minmax_multi_options' }, +{ amprocfamily => 'brin/timetz_minmax_multi_ops', amproclefttype => 'timetz', + amprocrighttype => 'timetz', amprocnum => '6', + amproc => 'brin_minmax_multi_preprocess' }, { amprocfamily => 'brin/timetz_minmax_multi_ops', amproclefttype => 'timetz', amprocrighttype => 'timetz', amprocnum => '11', amproc => 'brin_minmax_multi_distance_timetz' }, @@ -1875,6 +1923,9 @@ { amprocfamily => 'brin/numeric_minmax_multi_ops', amproclefttype => 'numeric', amprocrighttype => 'numeric', amprocnum => '5', amproc => 'brin_minmax_multi_options' }, +{ amprocfamily => 'brin/numeric_minmax_multi_ops', amproclefttype => 'numeric', + amprocrighttype => 'numeric', amprocnum => '6', + amproc => 'brin_minmax_multi_preprocess' }, { amprocfamily => 'brin/numeric_minmax_multi_ops', amproclefttype => 'numeric', amprocrighttype => 'numeric', amprocnum => '11', amproc => 'brin_minmax_multi_distance_numeric' }, @@ -1929,6 +1980,9 @@ { amprocfamily => 'brin/uuid_minmax_multi_ops', amproclefttype => 'uuid', amprocrighttype => 'uuid', amprocnum => '5', amproc => 'brin_minmax_multi_options' }, +{ amprocfamily => 'brin/uuid_minmax_multi_ops', amproclefttype => 'uuid', + amprocrighttype => 'uuid', amprocnum => '6', + amproc => 'brin_minmax_multi_preprocess' }, { amprocfamily => 'brin/uuid_minmax_multi_ops', amproclefttype => 'uuid', amprocrighttype => 'uuid', amprocnum => '11', amproc => 'brin_minmax_multi_distance_uuid' }, @@ -2005,6 +2059,9 @@ { amprocfamily => 'brin/pg_lsn_minmax_multi_ops', amproclefttype => 'pg_lsn', amprocrighttype => 'pg_lsn', amprocnum => '5', amproc => 'brin_minmax_multi_options' }, +{ amprocfamily => 'brin/pg_lsn_minmax_multi_ops', amproclefttype => 'pg_lsn', + amprocrighttype => 'pg_lsn', amprocnum => '6', + amproc => 'brin_minmax_multi_preprocess' }, { amprocfamily => 'brin/pg_lsn_minmax_multi_ops', amproclefttype => 'pg_lsn', amprocrighttype => 'pg_lsn', amprocnum => '11', amproc => 'brin_minmax_multi_distance_pg_lsn' }, diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat index 6638552bd0..4e8d666864 100644 --- a/src/include/catalog/pg_proc.dat +++ b/src/include/catalog/pg_proc.dat @@ -8520,6 +8520,10 @@ proname => 'brin_minmax_multi_options', proisstrict => 'f', prorettype => 'void', proargtypes => 'internal', prosrc => 'brin_minmax_multi_options' }, +{ oid => '9326', descr => 'BRIN multi minmax support', + proname => 'brin_minmax_multi_preprocess', proisstrict => 'f', + prorettype => 'internal', proargtypes => 'internal internal', + prosrc => 'brin_minmax_multi_preprocess' }, { oid => '4621', descr => 'BRIN multi minmax int2 distance', proname => 'brin_minmax_multi_distance_int2', prorettype => 'float8', -- 2.39.1