diff options
Diffstat (limited to 'src/backend/utils/adt/tsginidx.c')
-rw-r--r-- | src/backend/utils/adt/tsginidx.c | 57 |
1 files changed, 35 insertions, 22 deletions
diff --git a/src/backend/utils/adt/tsginidx.c b/src/backend/utils/adt/tsginidx.c index fef594700aa..fc0686ee66b 100644 --- a/src/backend/utils/adt/tsginidx.c +++ b/src/backend/utils/adt/tsginidx.c @@ -179,14 +179,16 @@ typedef struct } GinChkVal; static GinTernaryValue -checkcondition_gin(void *checkval, QueryOperand *val) +checkcondition_gin_internal(GinChkVal *gcv, QueryOperand *val, ExecPhraseData *data) { - GinChkVal *gcv = (GinChkVal *) checkval; int j; - /* if any val requiring a weight is used, set recheck flag */ - if (val->weight != 0) - *(gcv->need_recheck) = true; + /* + * if any val requiring a weight is used or caller + * needs position information then set recheck flag + */ + if (val->weight != 0 || data != NULL) + *gcv->need_recheck = true; /* convert item's number to corresponding entry's (operand's) number */ j = gcv->map_item_operand[((QueryItem *) val) - gcv->first_item]; @@ -196,15 +198,21 @@ checkcondition_gin(void *checkval, QueryOperand *val) } /* + * Wrapper of check condition function for TS_execute. + */ +static bool +checkcondition_gin(void *checkval, QueryOperand *val, ExecPhraseData *data) +{ + return checkcondition_gin_internal((GinChkVal *) checkval, + val, + data) != GIN_FALSE; +} + +/* * Evaluate tsquery boolean expression using ternary logic. - * - * chkcond is a callback function used to evaluate each VAL node in the query. - * checkval can be used to pass information to the callback. TS_execute doesn't - * do anything with it. */ static GinTernaryValue -TS_execute_ternary(QueryItem *curitem, void *checkval, - GinTernaryValue (*chkcond) (void *checkval, QueryOperand *val)) +TS_execute_ternary(GinChkVal *gcv, QueryItem *curitem) { GinTernaryValue val1, val2, @@ -214,22 +222,30 @@ TS_execute_ternary(QueryItem *curitem, void *checkval, check_stack_depth(); if (curitem->type == QI_VAL) - return chkcond(checkval, (QueryOperand *) curitem); + return checkcondition_gin_internal(gcv, + (QueryOperand *) curitem, + NULL /* don't have any position info */); switch (curitem->qoperator.oper) { case OP_NOT: - result = TS_execute_ternary(curitem + 1, checkval, chkcond); + result = TS_execute_ternary(gcv, curitem + 1); if (result == GIN_MAYBE) return result; return !result; + case OP_PHRASE: + /* + * GIN doesn't contain any information about positions, + * treat OP_PHRASE as OP_AND with recheck requirement + */ + *gcv->need_recheck = true; + case OP_AND: - val1 = TS_execute_ternary(curitem + curitem->qoperator.left, - checkval, chkcond); + val1 = TS_execute_ternary(gcv, curitem + curitem->qoperator.left); if (val1 == GIN_FALSE) return GIN_FALSE; - val2 = TS_execute_ternary(curitem + 1, checkval, chkcond); + val2 = TS_execute_ternary(gcv, curitem + 1); if (val2 == GIN_FALSE) return GIN_FALSE; if (val1 == GIN_TRUE && val2 == GIN_TRUE) @@ -238,11 +254,10 @@ TS_execute_ternary(QueryItem *curitem, void *checkval, return GIN_MAYBE; case OP_OR: - val1 = TS_execute_ternary(curitem + curitem->qoperator.left, - checkval, chkcond); + val1 = TS_execute_ternary(gcv, curitem + curitem->qoperator.left); if (val1 == GIN_TRUE) return GIN_TRUE; - val2 = TS_execute_ternary(curitem + 1, checkval, chkcond); + val2 = TS_execute_ternary(gcv, curitem + 1); if (val2 == GIN_TRUE) return GIN_TRUE; if (val1 == GIN_FALSE && val2 == GIN_FALSE) @@ -327,9 +342,7 @@ gin_tsquery_triconsistent(PG_FUNCTION_ARGS) gcv.map_item_operand = (int *) (extra_data[0]); gcv.need_recheck = &recheck; - res = TS_execute_ternary(GETQUERY(query), - &gcv, - checkcondition_gin); + res = TS_execute_ternary(&gcv, GETQUERY(query)); if (res == GIN_TRUE && recheck) res = GIN_MAYBE; |