mirror of
https://github.com/postgres/postgres.git
synced 2025-07-09 22:41:56 +03:00
Allow opclasses to provide tri-valued GIN consistent functions.
With the GIN "fast scan" feature, GIN can skip items without fetching all the keys for them, if it can prove that they don't match regardless of those keys. So far, it has done the proving by calling the boolean consistent function with all combinations of TRUE/FALSE for the unfetched keys, but since that's O(n^2), it becomes unfeasible with more than a few keys. We can avoid calling consistent with all the combinations, if we can tell the operator class implementation directly which keys are unknown. This commit includes a triConsistent function for the built-in array and tsvector opclasses. Alexander Korotkov, with some changes by me.
This commit is contained in:
@ -61,7 +61,7 @@ trueTriConsistentFn(GinScanKey key)
|
||||
* A helper function for calling a regular, binary logic, consistent function.
|
||||
*/
|
||||
static bool
|
||||
normalBoolConsistentFn(GinScanKey key)
|
||||
directBoolConsistentFn(GinScanKey key)
|
||||
{
|
||||
/*
|
||||
* Initialize recheckCurItem in case the consistentFn doesn't know it
|
||||
@ -81,6 +81,53 @@ normalBoolConsistentFn(GinScanKey key)
|
||||
PointerGetDatum(key->queryCategories)));
|
||||
}
|
||||
|
||||
/*
|
||||
* A helper function for calling a native ternary logic consistent function.
|
||||
*/
|
||||
static GinLogicValue
|
||||
directTriConsistentFn(GinScanKey key)
|
||||
{
|
||||
return DatumGetGinLogicValue(FunctionCall7Coll(key->triConsistentFmgrInfo,
|
||||
key->collation,
|
||||
PointerGetDatum(key->entryRes),
|
||||
UInt16GetDatum(key->strategy),
|
||||
key->query,
|
||||
UInt32GetDatum(key->nuserentries),
|
||||
PointerGetDatum(key->extra_data),
|
||||
PointerGetDatum(key->queryValues),
|
||||
PointerGetDatum(key->queryCategories)));
|
||||
}
|
||||
|
||||
/*
|
||||
* This function implements a binary logic consistency check, using a ternary
|
||||
* logic consistent function provided by the opclass. GIN_MAYBE return value
|
||||
* is interpreted as true with recheck flag.
|
||||
*/
|
||||
static bool
|
||||
shimBoolConsistentFn(GinScanKey key)
|
||||
{
|
||||
GinLogicValue result;
|
||||
result = DatumGetGinLogicValue(FunctionCall7Coll(key->triConsistentFmgrInfo,
|
||||
key->collation,
|
||||
PointerGetDatum(key->entryRes),
|
||||
UInt16GetDatum(key->strategy),
|
||||
key->query,
|
||||
UInt32GetDatum(key->nuserentries),
|
||||
PointerGetDatum(key->extra_data),
|
||||
PointerGetDatum(key->queryValues),
|
||||
PointerGetDatum(key->queryCategories)));
|
||||
if (result == GIN_MAYBE)
|
||||
{
|
||||
key->recheckCurItem = true;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
key->recheckCurItem = false;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This function implements a tri-state consistency check, using a boolean
|
||||
* consistent function provided by the opclass.
|
||||
@ -124,12 +171,12 @@ shimTriConsistentFn(GinScanKey key)
|
||||
* function as is.
|
||||
*/
|
||||
if (nmaybe == 0)
|
||||
return normalBoolConsistentFn(key);
|
||||
return directBoolConsistentFn(key);
|
||||
|
||||
/* First call consistent function with all the maybe-inputs set FALSE */
|
||||
for (i = 0; i < nmaybe; i++)
|
||||
key->entryRes[maybeEntries[i]] = GIN_FALSE;
|
||||
curResult = normalBoolConsistentFn(key);
|
||||
curResult = directBoolConsistentFn(key);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
@ -147,7 +194,7 @@ shimTriConsistentFn(GinScanKey key)
|
||||
if (i == nmaybe)
|
||||
break;
|
||||
|
||||
boolResult = normalBoolConsistentFn(key);
|
||||
boolResult = directBoolConsistentFn(key);
|
||||
recheck |= key->recheckCurItem;
|
||||
|
||||
if (curResult != boolResult)
|
||||
@ -175,8 +222,17 @@ ginInitConsistentFunction(GinState *ginstate, GinScanKey key)
|
||||
else
|
||||
{
|
||||
key->consistentFmgrInfo = &ginstate->consistentFn[key->attnum - 1];
|
||||
key->triConsistentFmgrInfo = &ginstate->triConsistentFn[key->attnum - 1];
|
||||
key->collation = ginstate->supportCollation[key->attnum - 1];
|
||||
key->boolConsistentFn = normalBoolConsistentFn;
|
||||
key->triConsistentFn = shimTriConsistentFn;
|
||||
|
||||
if (OidIsValid(ginstate->consistentFn[key->attnum - 1].fn_oid))
|
||||
key->boolConsistentFn = directBoolConsistentFn;
|
||||
else
|
||||
key->boolConsistentFn = shimBoolConsistentFn;
|
||||
|
||||
if (OidIsValid(ginstate->triConsistentFn[key->attnum - 1].fn_oid))
|
||||
key->triConsistentFn = directTriConsistentFn;
|
||||
else
|
||||
key->triConsistentFn = shimTriConsistentFn;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user