diff options
Diffstat (limited to 'src/backend/utils/adt/tsginidx.c')
-rw-r--r-- | src/backend/utils/adt/tsginidx.c | 23 |
1 files changed, 20 insertions, 3 deletions
diff --git a/src/backend/utils/adt/tsginidx.c b/src/backend/utils/adt/tsginidx.c index c96f1f7216b..2d656168fca 100644 --- a/src/backend/utils/adt/tsginidx.c +++ b/src/backend/utils/adt/tsginidx.c @@ -210,6 +210,11 @@ checkcondition_gin(void *checkval, QueryOperand *val, ExecPhraseData *data) /* * Evaluate tsquery boolean expression using ternary logic. + * + * Note: the reason we can't use TS_execute() for this is that its API + * for the checkcondition callback doesn't allow a MAYBE result to be + * returned, but we might have MAYBEs in the gcv->check array. + * Perhaps we should change that API. */ static GinTernaryValue TS_execute_ternary(GinChkVal *gcv, QueryItem *curitem, bool in_phrase) @@ -230,9 +235,19 @@ TS_execute_ternary(GinChkVal *gcv, QueryItem *curitem, bool in_phrase) switch (curitem->qoperator.oper) { case OP_NOT: - /* In phrase search, always return MAYBE since we lack positions */ + + /* + * Below a phrase search, force NOT's result to MAYBE. We cannot + * invert a TRUE result from the subexpression to FALSE, since + * TRUE only says that the subexpression matches somewhere, not + * that it matches everywhere, so there might be positions where + * the NOT will match. We could invert FALSE to TRUE, but there's + * little point in distinguishing TRUE from MAYBE, since a recheck + * will have been forced already. + */ if (in_phrase) return GIN_MAYBE; + result = TS_execute_ternary(gcv, curitem + 1, in_phrase); if (result == GIN_MAYBE) return result; @@ -242,7 +257,8 @@ TS_execute_ternary(GinChkVal *gcv, QueryItem *curitem, bool in_phrase) /* * GIN doesn't contain any information about positions, so treat - * OP_PHRASE as OP_AND with recheck requirement + * OP_PHRASE as OP_AND with recheck requirement, and always + * reporting MAYBE not TRUE. */ *(gcv->need_recheck) = true; /* Pass down in_phrase == true in case there's a NOT below */ @@ -258,7 +274,8 @@ TS_execute_ternary(GinChkVal *gcv, QueryItem *curitem, bool in_phrase) val2 = TS_execute_ternary(gcv, curitem + 1, in_phrase); if (val2 == GIN_FALSE) return GIN_FALSE; - if (val1 == GIN_TRUE && val2 == GIN_TRUE) + if (val1 == GIN_TRUE && val2 == GIN_TRUE && + curitem->qoperator.oper != OP_PHRASE) return GIN_TRUE; else return GIN_MAYBE; |