1
0
mirror of https://github.com/postgres/postgres.git synced 2025-08-21 10:42:50 +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:
Heikki Linnakangas
2014-03-12 17:13:22 +02:00
parent fecfc2b913
commit c5608ea26a
16 changed files with 467 additions and 101 deletions

View File

@@ -218,3 +218,87 @@ ginarrayconsistent(PG_FUNCTION_ARGS)
PG_RETURN_BOOL(res);
}
/*
* triconsistent support function
*/
Datum
ginarraytriconsistent(PG_FUNCTION_ARGS)
{
GinLogicValue *check = (GinLogicValue *) PG_GETARG_POINTER(0);
StrategyNumber strategy = PG_GETARG_UINT16(1);
/* ArrayType *query = PG_GETARG_ARRAYTYPE_P(2); */
int32 nkeys = PG_GETARG_INT32(3);
/* Pointer *extra_data = (Pointer *) PG_GETARG_POINTER(4); */
/* Datum *queryKeys = (Datum *) PG_GETARG_POINTER(5); */
bool *nullFlags = (bool *) PG_GETARG_POINTER(6);
GinLogicValue res;
int32 i;
switch (strategy)
{
case GinOverlapStrategy:
/* must have a match for at least one non-null element */
res = GIN_FALSE;
for (i = 0; i < nkeys; i++)
{
if (!nullFlags[i])
{
if (check[i] == GIN_TRUE)
{
res = GIN_TRUE;
break;
}
else if (check[i] == GIN_MAYBE && res == GIN_FALSE)
{
res = GIN_MAYBE;
}
}
}
break;
case GinContainsStrategy:
/* must have all elements in check[] true, and no nulls */
res = GIN_TRUE;
for (i = 0; i < nkeys; i++)
{
if (check[i] == GIN_FALSE || nullFlags[i])
{
res = GIN_FALSE;
break;
}
if (check[i] == GIN_MAYBE)
{
res = GIN_MAYBE;
}
}
break;
case GinContainedStrategy:
/* can't do anything else useful here */
res = GIN_MAYBE;
break;
case GinEqualStrategy:
/*
* Must have all elements in check[] true; no discrimination
* against nulls here. This is because array_contain_compare and
* array_eq handle nulls differently ...
*/
res = GIN_MAYBE;
for (i = 0; i < nkeys; i++)
{
if (check[i] == GIN_FALSE)
{
res = GIN_FALSE;
break;
}
}
break;
default:
elog(ERROR, "ginarrayconsistent: unknown strategy number: %d",
strategy);
res = false;
}
PG_RETURN_GIN_LOGIC_VALUE(res);
}