break;
}
+ /*
+ * Collation from the first key (has to be the same for
+ * all keys for the same attribue).
+ */
+ collation = keys[attno - 1][0]->sk_collation;
+
/*
* Check whether the scan key is consistent with the page
* range values; if so, have the pages in the range added
* to the output bitmap.
*
- * XXX We simply use the collation from the first key (it
- * has to be the same for all keys for the same attribue).
+ * The opclass may or may not support processing of multiple
+ * scan keys. We can determine that based on the number of
+ * arguments - functions with extra parameter (number of scan
+ * keys) do support this, otherwise we have to simply pass the
+ * scan keys one by one.
*/
- collation = keys[attno - 1][0]->sk_collation;
-
- /* Check all keys at once */
- add = FunctionCall4Coll(&consistentFn[attno - 1],
- collation,
- PointerGetDatum(bdesc),
- PointerGetDatum(bval),
- PointerGetDatum(keys[attno - 1]),
- Int32GetDatum(nkeys[attno - 1]));
- addrange = DatumGetBool(add);
- if (!addrange)
- break;
+ if (consistentFn[attno - 1].fn_nargs >= 4)
+ {
+ /* Check all keys at once */
+ add = FunctionCall4Coll(&consistentFn[attno - 1],
+ collation,
+ PointerGetDatum(bdesc),
+ PointerGetDatum(bval),
+ PointerGetDatum(keys[attno - 1]),
+ Int32GetDatum(nkeys[attno - 1]));
+ addrange = DatumGetBool(add);
+ }
+ else
+ {
+ /*
+ * Check keys one by one
+ *
+ * When there are multiple scan keys, failure to meet the
+ * criteria for a single one of them is enough to discard
+ * the range as a whole, so break out of the loop as soon
+ * as a false return value is obtained.
+ */
+ int keyno;
+
+ for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+ {
+ add = FunctionCall3Coll(&consistentFn[attno - 1],
+ keys[attno - 1][keyno]->sk_collation,
+ PointerGetDatum(bdesc),
+ PointerGetDatum(bval),
+ PointerGetDatum(keys[attno - 1][keyno]));
+ addrange = DatumGetBool(add);
+ if (!addrange)
+ break;
+ }
+ }
}
}
}
uint16 procnum);
static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
Oid subtype, uint16 strategynum);
-static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
- ScanKey key, Oid colloid);
/*
/*
* BRIN inclusion consistent function
*
- * We inspect the IS NULL scan keys first, which allows us to make a decision
- * without looking at the contents of the page range. Only when the page range
- * matches the IS NULL keys, we check the regular scan keys.
+ * We're no longer dealing with NULL keys in the consistent function, that is
+ * now handled by the AM code. That means we should not get any all-NULL ranges
+ * either, because those can't be consistent with regular (not [IS] NULL) keys.
*
* All of the strategies are optional.
*/
{
BrinDesc *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
- ScanKey *keys = (ScanKey *) PG_GETARG_POINTER(2);
- int nkeys = PG_GETARG_INT32(3);
- Oid colloid = PG_GET_COLLATION();
- int keyno;
+ ScanKey key = (ScanKey) PG_GETARG_POINTER(2);
+ Oid colloid = PG_GET_COLLATION(),
+ subtype;
+ Datum unionval;
+ AttrNumber attno;
+ Datum query;
+ FmgrInfo *finfo;
+ Datum result;
- /* make sure we got some scan keys */
- Assert((nkeys > 0) && (keys != NULL));
+ /* This opclass uses the old signature with only three arguments. */
+ Assert(PG_NARGS() == 3);
- /*
- * If is all nulls, it cannot possibly be consistent (at this point we
- * know there are at least some regular scan keys).
- */
- if (column->bv_allnulls)
- PG_RETURN_BOOL(false);
+ /* Should not be dealing with all-NULL ranges. */
+ Assert(!column->bv_allnulls);
/* It has to be checked, if it contains elements that are not mergeable. */
if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
PG_RETURN_BOOL(true);
- /* Check that the range is consistent with all regular scan keys. */
- for (keyno = 0; keyno < nkeys; keyno++)
- {
- ScanKey key = keys[keyno];
-
- /* NULL keys are handled and filtered-out in bringetbitmap */
- Assert(!(key->sk_flags & SK_ISNULL));
-
- /*
- * When there are multiple scan keys, failure to meet the criteria for
- * a single one of them is enough to discard the range as a whole, so
- * break out of the loop as soon as a false return value is obtained.
- */
- if (!inclusion_consistent_key(bdesc, column, key, colloid))
- PG_RETURN_BOOL(false);
- }
-
- PG_RETURN_BOOL(true);
-}
-
-/*
- * inclusion_consistent_key
- * Determine if the range is consistent with a single scan key.
- */
-static bool
-inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
- Oid colloid)
-{
- FmgrInfo *finfo;
- AttrNumber attno = key->sk_attno;
- Oid subtype = key->sk_subtype;
- Datum query = key->sk_argument;
- Datum unionval = column->bv_values[INCLUSION_UNION];
- Datum result;
-
- /* This should be called only for regular keys, not for IS [NOT] NULL. */
- Assert(!(key->sk_flags & SK_ISNULL));
-
+ attno = key->sk_attno;
+ subtype = key->sk_subtype;
+ query = key->sk_argument;
+ unionval = column->bv_values[INCLUSION_UNION];
switch (key->sk_strategy)
{
/*
finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
RTOverRightStrategyNumber);
result = FunctionCall2Coll(finfo, colloid, unionval, query);
- return !DatumGetBool(result);
+ PG_RETURN_BOOL(!DatumGetBool(result));
case RTOverLeftStrategyNumber:
finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
RTRightStrategyNumber);
result = FunctionCall2Coll(finfo, colloid, unionval, query);
- return !DatumGetBool(result);
+ PG_RETURN_BOOL(!DatumGetBool(result));
case RTOverRightStrategyNumber:
finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
RTLeftStrategyNumber);
result = FunctionCall2Coll(finfo, colloid, unionval, query);
- return !DatumGetBool(result);
+ PG_RETURN_BOOL(!DatumGetBool(result));
case RTRightStrategyNumber:
finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
RTOverLeftStrategyNumber);
result = FunctionCall2Coll(finfo, colloid, unionval, query);
- return !DatumGetBool(result);
+ PG_RETURN_BOOL(!DatumGetBool(result));
case RTBelowStrategyNumber:
finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
RTOverAboveStrategyNumber);
result = FunctionCall2Coll(finfo, colloid, unionval, query);
- return !DatumGetBool(result);
+ PG_RETURN_BOOL(!DatumGetBool(result));
case RTOverBelowStrategyNumber:
finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
RTAboveStrategyNumber);
result = FunctionCall2Coll(finfo, colloid, unionval, query);
- return !DatumGetBool(result);
+ PG_RETURN_BOOL(!DatumGetBool(result));
case RTOverAboveStrategyNumber:
finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
RTBelowStrategyNumber);
result = FunctionCall2Coll(finfo, colloid, unionval, query);
- return !DatumGetBool(result);
+ PG_RETURN_BOOL(!DatumGetBool(result));
case RTAboveStrategyNumber:
finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
RTOverBelowStrategyNumber);
result = FunctionCall2Coll(finfo, colloid, unionval, query);
- return !DatumGetBool(result);
+ PG_RETURN_BOOL(!DatumGetBool(result));
/*
* Overlap and contains strategies
finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
key->sk_strategy);
result = FunctionCall2Coll(finfo, colloid, unionval, query);
- return DatumGetBool(result);
+ PG_RETURN_DATUM(result);
/*
* Contained by strategies
RTOverlapStrategyNumber);
result = FunctionCall2Coll(finfo, colloid, unionval, query);
if (DatumGetBool(result))
- return true;
+ PG_RETURN_BOOL(true);
- return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+ PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
/*
* Adjacent strategy
RTOverlapStrategyNumber);
result = FunctionCall2Coll(finfo, colloid, unionval, query);
if (DatumGetBool(result))
- return true;
+ PG_RETURN_BOOL(true);
finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
RTAdjacentStrategyNumber);
result = FunctionCall2Coll(finfo, colloid, unionval, query);
- return DatumGetBool(result);
+ PG_RETURN_DATUM(result);
/*
* Basic comparison strategies
RTRightStrategyNumber);
result = FunctionCall2Coll(finfo, colloid, unionval, query);
if (!DatumGetBool(result))
- return true;
+ PG_RETURN_BOOL(true);
- return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+ PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
case RTSameStrategyNumber:
case RTEqualStrategyNumber:
RTContainsStrategyNumber);
result = FunctionCall2Coll(finfo, colloid, unionval, query);
if (DatumGetBool(result))
- return true;
+ PG_RETURN_BOOL(true);
- return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+ PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
case RTGreaterEqualStrategyNumber:
finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
RTLeftStrategyNumber);
result = FunctionCall2Coll(finfo, colloid, unionval, query);
if (!DatumGetBool(result))
- return true;
+ PG_RETURN_BOOL(true);
- return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+ PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
case RTGreaterStrategyNumber:
/* no need to check for empty elements */
finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
RTLeftStrategyNumber);
result = FunctionCall2Coll(finfo, colloid, unionval, query);
- return !DatumGetBool(result);
+ PG_RETURN_BOOL(!DatumGetBool(result));
default:
/* shouldn't happen */
elog(ERROR, "invalid strategy number %d", key->sk_strategy);
- return false;
+ PG_RETURN_BOOL(false);
}
}
static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
Oid subtype, uint16 strategynum);
-static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
- ScanKey key, Oid colloid);
Datum
* return whether the scan key is consistent with the index tuple's min/max
* values. Return true if so, false otherwise.
*
- * We inspect the IS NULL scan keys first, which allows us to make a decision
- * without looking at the contents of the page range. Only when the page range
- * matches all those keys, we check the regular scan keys.
+ * We're no longer dealing with NULL keys in the consistent function, that is
+ * now handled by the AM code. That means we should not get any all-NULL ranges
+ * either, because those can't be consistent with regular (not [IS] NULL) keys.
*/
Datum
brin_minmax_consistent(PG_FUNCTION_ARGS)
{
BrinDesc *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
- ScanKey *keys = (ScanKey *) PG_GETARG_POINTER(2);
- int nkeys = PG_GETARG_INT32(3);
- Oid colloid = PG_GET_COLLATION();
- int keyno;
-
- /* make sure we got some scan keys */
- Assert((nkeys > 0) && (keys != NULL));
-
- /*
- * If is all nulls, it cannot possibly be consistent (at this point we
- * know there are at least some regular scan keys).
- */
- if (column->bv_allnulls)
- PG_RETURN_BOOL(false);
-
- /* Check that the range is consistent with all scan keys. */
- for (keyno = 0; keyno < nkeys; keyno++)
- {
- ScanKey key = keys[keyno];
-
- /* NULL keys are handled and filtered-out in bringetbitmap */
- Assert(!(key->sk_flags & SK_ISNULL));
-
- /*
- * When there are multiple scan keys, failure to meet the criteria for
- * a single one of them is enough to discard the range as a whole, so
- * break out of the loop as soon as a false return value is obtained.
- */
- if (!minmax_consistent_key(bdesc, column, key, colloid))
- PG_RETURN_DATUM(false);
- }
+ ScanKey key = (ScanKey) PG_GETARG_POINTER(2);
+ Oid colloid = PG_GET_COLLATION(),
+ subtype;
+ AttrNumber attno;
+ Datum value;
+ Datum matches;
+ FmgrInfo *finfo;
- PG_RETURN_DATUM(true);
-}
+ /* This opclass uses the old signature with only three arguments. */
+ Assert(PG_NARGS() == 3);
-/*
- * minmax_consistent_key
- * Determine if the range is consistent with a single scan key.
- */
-static bool
-minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
- Oid colloid)
-{
- FmgrInfo *finfo;
- AttrNumber attno = key->sk_attno;
- Oid subtype = key->sk_subtype;
- Datum value = key->sk_argument;
- Datum matches;
+ /* Should not be dealing with all-NULL ranges. */
+ Assert(!column->bv_allnulls);
+ attno = key->sk_attno;
+ subtype = key->sk_subtype;
+ value = key->sk_argument;
switch (key->sk_strategy)
{
case BTLessStrategyNumber:
break;
}
- return DatumGetBool(matches);
+ PG_RETURN_DATUM(matches);
}
/*