diff options
Diffstat (limited to 'src/backend/access')
| -rw-r--r-- | src/backend/access/gin/ginarrayproc.c | 84 | ||||
| -rw-r--r-- | src/backend/access/gin/ginlogic.c | 68 | ||||
| -rw-r--r-- | src/backend/access/gin/ginutil.c | 28 |
3 files changed, 171 insertions, 9 deletions
diff --git a/src/backend/access/gin/ginarrayproc.c b/src/backend/access/gin/ginarrayproc.c index e02a91b82d..d04b851e3c 100644 --- a/src/backend/access/gin/ginarrayproc.c +++ b/src/backend/access/gin/ginarrayproc.c @@ -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); +} diff --git a/src/backend/access/gin/ginlogic.c b/src/backend/access/gin/ginlogic.c index dc8e6304a2..4c8d706361 100644 --- a/src/backend/access/gin/ginlogic.c +++ b/src/backend/access/gin/ginlogic.c @@ -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 @@ -82,6 +82,53 @@ normalBoolConsistentFn(GinScanKey key) } /* + * 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; } } diff --git a/src/backend/access/gin/ginutil.c b/src/backend/access/gin/ginutil.c index 486f2ef1f1..4dadb50dca 100644 --- a/src/backend/access/gin/ginutil.c +++ b/src/backend/access/gin/ginutil.c @@ -67,9 +67,31 @@ initGinState(GinState *state, Relation index) fmgr_info_copy(&(state->extractQueryFn[i]), index_getprocinfo(index, i + 1, GIN_EXTRACTQUERY_PROC), CurrentMemoryContext); - fmgr_info_copy(&(state->consistentFn[i]), - index_getprocinfo(index, i + 1, GIN_CONSISTENT_PROC), - CurrentMemoryContext); + /* + * Check opclass capability to do tri-state or binary logic consistent + * check. + */ + if (index_getprocid(index, i + 1, GIN_TRICONSISTENT_PROC) != InvalidOid) + { + fmgr_info_copy(&(state->triConsistentFn[i]), + index_getprocinfo(index, i + 1, GIN_TRICONSISTENT_PROC), + CurrentMemoryContext); + } + + if (index_getprocid(index, i + 1, GIN_CONSISTENT_PROC) != InvalidOid) + { + fmgr_info_copy(&(state->consistentFn[i]), + index_getprocinfo(index, i + 1, GIN_CONSISTENT_PROC), + CurrentMemoryContext); + } + + if (state->consistentFn[i].fn_oid == InvalidOid && + state->triConsistentFn[i].fn_oid == InvalidOid) + { + elog(ERROR, "missing GIN support function (%d or %d) for attribute %d of index \"%s\"", + GIN_CONSISTENT_PROC, GIN_TRICONSISTENT_PROC, + i + 1, RelationGetRelationName(index)); + } /* * Check opclass capability to do partial match. |
