1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-21 00:42:43 +03:00

Phrase full text search.

Patch introduces new text search operator (<-> or <DISTANCE>) into tsquery.
On-disk and binary in/out format of tsquery are backward compatible.
It has two side effect:
- change order for tsquery, so, users, who has a btree index over tsquery,
  should reindex it
- less number of parenthesis in tsquery output, and tsquery becomes more
  readable

Authors: Teodor Sigaev, Oleg Bartunov, Dmitry Ivanov
Reviewers: Alexander Korotkov, Artur Zakirov
This commit is contained in:
Teodor Sigaev
2016-04-07 18:44:18 +03:00
parent 015e88942a
commit bb140506df
30 changed files with 2542 additions and 450 deletions

View File

@@ -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];
@@ -195,16 +197,22 @@ checkcondition_gin(void *checkval, QueryOperand *val)
return gcv->check[j];
}
/*
* 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;