aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/adt/tsginidx.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/utils/adt/tsginidx.c')
-rw-r--r--src/backend/utils/adt/tsginidx.c23
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;