mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-09-08 14:49:23 +02:00
Fix full text search to handle NOT above a phrase search correctly.
Queries such as '!(foo<->bar)' failed to find matching rows when implemented as a GiST or GIN index search. That's because of failing to handle phrase searches as tri-valued when considering a query without any position information for the target tsvector. We can only say that the phrase operator might match, not that it does match; and therefore its NOT also might match. The previous coding incorrectly inverted the approximate phrase result to decide that there was certainly no match. To fix, we need to make TS_phrase_execute return a real ternary result, and then bubble that up accurately in TS_execute. As long as we have to do that anyway, we can simplify the baroque things TS_phrase_execute was doing internally to manage tri-valued searching with only a bool as explicit result. For now, I left the externally-visible result of TS_execute as a plain bool. There do not appear to be any outside callers that need to distinguish a three-way result, given that they passed in a flag saying what to do in the absence of position data. This might need to change someday, but we wouldn't want to back-patch such a change. Although tsginidx.c has its own TS_execute_ternary implementation for use at upper index levels, that sadly managed to get this case wrong as well :-(. Fixing it is a lot easier fortunately. Per bug #16388 from Charles Offenbacher. Back-patch to 9.6 where phrase search was introduced. Discussion: https://postgr.es/m/16388-98cffba38d0b7e6e@postgresql.org
This commit is contained in:
parent
0f4970d1a9
commit
98a4d6950b
@ -210,6 +210,11 @@ checkcondition_gin(void *checkval, QueryOperand *val, ExecPhraseData *data)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Evaluate tsquery boolean expression using ternary logic.
|
* 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
|
static GinTernaryValue
|
||||||
TS_execute_ternary(GinChkVal *gcv, QueryItem *curitem, bool in_phrase)
|
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)
|
switch (curitem->qoperator.oper)
|
||||||
{
|
{
|
||||||
case OP_NOT:
|
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)
|
if (in_phrase)
|
||||||
return GIN_MAYBE;
|
return GIN_MAYBE;
|
||||||
|
|
||||||
result = TS_execute_ternary(gcv, curitem + 1, in_phrase);
|
result = TS_execute_ternary(gcv, curitem + 1, in_phrase);
|
||||||
if (result == GIN_MAYBE)
|
if (result == GIN_MAYBE)
|
||||||
return result;
|
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
|
* 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;
|
*(gcv->need_recheck) = true;
|
||||||
/* Pass down in_phrase == true in case there's a NOT below */
|
/* 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);
|
val2 = TS_execute_ternary(gcv, curitem + 1, in_phrase);
|
||||||
if (val2 == GIN_FALSE)
|
if (val2 == GIN_FALSE)
|
||||||
return 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;
|
return GIN_TRUE;
|
||||||
else
|
else
|
||||||
return GIN_MAYBE;
|
return GIN_MAYBE;
|
||||||
|
@ -67,8 +67,21 @@ typedef struct
|
|||||||
|
|
||||||
#define STATHDRSIZE (offsetof(TSVectorStat, data))
|
#define STATHDRSIZE (offsetof(TSVectorStat, data))
|
||||||
|
|
||||||
static Datum tsvector_update_trigger(PG_FUNCTION_ARGS, bool config_column);
|
/* TS_execute requires ternary logic to handle NOT with phrase matches */
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
TS_NO, /* definitely no match */
|
||||||
|
TS_YES, /* definitely does match */
|
||||||
|
TS_MAYBE /* can't verify match for lack of pos data */
|
||||||
|
} TSTernaryValue;
|
||||||
|
|
||||||
|
|
||||||
|
static TSTernaryValue TS_execute_recurse(QueryItem *curitem, void *arg,
|
||||||
|
uint32 flags,
|
||||||
|
TSExecuteCallback chkcond);
|
||||||
static int tsvector_bsearch(const TSVector tsv, char *lexeme, int lexeme_len);
|
static int tsvector_bsearch(const TSVector tsv, char *lexeme, int lexeme_len);
|
||||||
|
static Datum tsvector_update_trigger(PG_FUNCTION_ARGS, bool config_column);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Order: haspos, len, word, for all positions (pos, weight)
|
* Order: haspos, len, word, for all positions (pos, weight)
|
||||||
@ -1423,14 +1436,17 @@ checkcondition_str(void *checkval, QueryOperand *val, ExecPhraseData *data)
|
|||||||
* Loffset and Roffset should not be negative, else we risk trying to output
|
* Loffset and Roffset should not be negative, else we risk trying to output
|
||||||
* negative positions, which won't fit into WordEntryPos.
|
* negative positions, which won't fit into WordEntryPos.
|
||||||
*
|
*
|
||||||
* Returns true if any positions were emitted to *data; or if data is NULL,
|
* The result is boolean (TS_YES or TS_NO), but for the caller's convenience
|
||||||
* returns true if any positions would have been emitted.
|
* we return it as TSTernaryValue.
|
||||||
|
*
|
||||||
|
* Returns TS_YES if any positions were emitted to *data; or if data is NULL,
|
||||||
|
* returns TS_YES if any positions would have been emitted.
|
||||||
*/
|
*/
|
||||||
#define TSPO_L_ONLY 0x01 /* emit positions appearing only in L */
|
#define TSPO_L_ONLY 0x01 /* emit positions appearing only in L */
|
||||||
#define TSPO_R_ONLY 0x02 /* emit positions appearing only in R */
|
#define TSPO_R_ONLY 0x02 /* emit positions appearing only in R */
|
||||||
#define TSPO_BOTH 0x04 /* emit positions appearing in both L&R */
|
#define TSPO_BOTH 0x04 /* emit positions appearing in both L&R */
|
||||||
|
|
||||||
static bool
|
static TSTernaryValue
|
||||||
TS_phrase_output(ExecPhraseData *data,
|
TS_phrase_output(ExecPhraseData *data,
|
||||||
ExecPhraseData *Ldata,
|
ExecPhraseData *Ldata,
|
||||||
ExecPhraseData *Rdata,
|
ExecPhraseData *Rdata,
|
||||||
@ -1513,10 +1529,10 @@ TS_phrase_output(ExecPhraseData *data,
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Exact positions not needed, so return true as soon as we
|
* Exact positions not needed, so return TS_YES as soon as we
|
||||||
* know there is at least one.
|
* know there is at least one.
|
||||||
*/
|
*/
|
||||||
return true;
|
return TS_YES;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1525,9 +1541,9 @@ TS_phrase_output(ExecPhraseData *data,
|
|||||||
{
|
{
|
||||||
/* Let's assert we didn't overrun the array */
|
/* Let's assert we didn't overrun the array */
|
||||||
Assert(data->npos <= max_npos);
|
Assert(data->npos <= max_npos);
|
||||||
return true;
|
return TS_YES;
|
||||||
}
|
}
|
||||||
return false;
|
return TS_NO;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1545,17 +1561,16 @@ TS_phrase_output(ExecPhraseData *data,
|
|||||||
* This is OK because an outside call always starts from an OP_PHRASE node.
|
* This is OK because an outside call always starts from an OP_PHRASE node.
|
||||||
*
|
*
|
||||||
* The detailed semantics of the match data, given that the function returned
|
* The detailed semantics of the match data, given that the function returned
|
||||||
* "true" (successful match, or possible match), are:
|
* TS_YES (successful match), are:
|
||||||
*
|
*
|
||||||
* npos > 0, negate = false:
|
* npos > 0, negate = false:
|
||||||
* query is matched at specified position(s) (and only those positions)
|
* query is matched at specified position(s) (and only those positions)
|
||||||
* npos > 0, negate = true:
|
* npos > 0, negate = true:
|
||||||
* query is matched at all positions *except* specified position(s)
|
* query is matched at all positions *except* specified position(s)
|
||||||
* npos = 0, negate = false:
|
|
||||||
* query is possibly matched, matching position(s) are unknown
|
|
||||||
* (this should only be returned when TS_EXEC_PHRASE_NO_POS flag is set)
|
|
||||||
* npos = 0, negate = true:
|
* npos = 0, negate = true:
|
||||||
* query is matched at all positions
|
* query is matched at all positions
|
||||||
|
* npos = 0, negate = false:
|
||||||
|
* disallowed (this should result in TS_NO or TS_MAYBE, as appropriate)
|
||||||
*
|
*
|
||||||
* Successful matches also return a "width" value which is the match width in
|
* Successful matches also return a "width" value which is the match width in
|
||||||
* lexemes, less one. Hence, "width" is zero for simple one-lexeme matches,
|
* lexemes, less one. Hence, "width" is zero for simple one-lexeme matches,
|
||||||
@ -1564,18 +1579,22 @@ TS_phrase_output(ExecPhraseData *data,
|
|||||||
* the starts. (This unintuitive rule is needed to avoid possibly generating
|
* the starts. (This unintuitive rule is needed to avoid possibly generating
|
||||||
* negative positions, which wouldn't fit into the WordEntryPos arrays.)
|
* negative positions, which wouldn't fit into the WordEntryPos arrays.)
|
||||||
*
|
*
|
||||||
* When the function returns "false" (no match), it must return npos = 0,
|
* If the TSExecuteCallback function reports that an operand is present
|
||||||
|
* but fails to provide position(s) for it, we will return TS_MAYBE when
|
||||||
|
* it is possible but not certain that the query is matched.
|
||||||
|
*
|
||||||
|
* When the function returns TS_NO or TS_MAYBE, it must return npos = 0,
|
||||||
* negate = false (which is the state initialized by the caller); but the
|
* negate = false (which is the state initialized by the caller); but the
|
||||||
* "width" output in such cases is undefined.
|
* "width" output in such cases is undefined.
|
||||||
*/
|
*/
|
||||||
static bool
|
static TSTernaryValue
|
||||||
TS_phrase_execute(QueryItem *curitem, void *arg, uint32 flags,
|
TS_phrase_execute(QueryItem *curitem, void *arg, uint32 flags,
|
||||||
TSExecuteCallback chkcond,
|
TSExecuteCallback chkcond,
|
||||||
ExecPhraseData *data)
|
ExecPhraseData *data)
|
||||||
{
|
{
|
||||||
ExecPhraseData Ldata,
|
ExecPhraseData Ldata,
|
||||||
Rdata;
|
Rdata;
|
||||||
bool lmatch,
|
TSTernaryValue lmatch,
|
||||||
rmatch;
|
rmatch;
|
||||||
int Loffset,
|
int Loffset,
|
||||||
Roffset,
|
Roffset,
|
||||||
@ -1585,67 +1604,80 @@ TS_phrase_execute(QueryItem *curitem, void *arg, uint32 flags,
|
|||||||
check_stack_depth();
|
check_stack_depth();
|
||||||
|
|
||||||
if (curitem->type == QI_VAL)
|
if (curitem->type == QI_VAL)
|
||||||
return chkcond(arg, (QueryOperand *) curitem, data);
|
{
|
||||||
|
if (!chkcond(arg, (QueryOperand *) curitem, data))
|
||||||
|
return TS_NO;
|
||||||
|
if (data->npos > 0 || data->negate)
|
||||||
|
return TS_YES;
|
||||||
|
/* If we have no position data, we must return TS_MAYBE */
|
||||||
|
return TS_MAYBE;
|
||||||
|
}
|
||||||
|
|
||||||
switch (curitem->qoperator.oper)
|
switch (curitem->qoperator.oper)
|
||||||
{
|
{
|
||||||
case OP_NOT:
|
case OP_NOT:
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Because a "true" result with no specific positions is taken as
|
* We need not touch data->width, since a NOT operation does not
|
||||||
* uncertain, we need no special care here for !TS_EXEC_CALC_NOT.
|
* change the match width.
|
||||||
* If it's a false positive, the right things happen anyway.
|
|
||||||
*
|
|
||||||
* Also, we need not touch data->width, since a NOT operation does
|
|
||||||
* not change the match width.
|
|
||||||
*/
|
*/
|
||||||
if (TS_phrase_execute(curitem + 1, arg, flags, chkcond, data))
|
if (!(flags & TS_EXEC_CALC_NOT))
|
||||||
{
|
{
|
||||||
if (data->npos > 0)
|
/* without CALC_NOT, report NOT as "match everywhere" */
|
||||||
{
|
|
||||||
/* we have some positions, invert negate flag */
|
|
||||||
data->negate = !data->negate;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else if (data->negate)
|
|
||||||
{
|
|
||||||
/* change "match everywhere" to "match nowhere" */
|
|
||||||
data->negate = false;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
/* match positions are, and remain, uncertain */
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* change "match nowhere" to "match everywhere" */
|
|
||||||
Assert(data->npos == 0 && !data->negate);
|
Assert(data->npos == 0 && !data->negate);
|
||||||
data->negate = true;
|
data->negate = true;
|
||||||
return true;
|
return TS_YES;
|
||||||
}
|
}
|
||||||
|
switch (TS_phrase_execute(curitem + 1, arg, flags, chkcond, data))
|
||||||
|
{
|
||||||
|
case TS_NO:
|
||||||
|
/* change "match nowhere" to "match everywhere" */
|
||||||
|
Assert(data->npos == 0 && !data->negate);
|
||||||
|
data->negate = true;
|
||||||
|
return TS_YES;
|
||||||
|
case TS_YES:
|
||||||
|
if (data->npos > 0)
|
||||||
|
{
|
||||||
|
/* we have some positions, invert negate flag */
|
||||||
|
data->negate = !data->negate;
|
||||||
|
return TS_YES;
|
||||||
|
}
|
||||||
|
else if (data->negate)
|
||||||
|
{
|
||||||
|
/* change "match everywhere" to "match nowhere" */
|
||||||
|
data->negate = false;
|
||||||
|
return TS_NO;
|
||||||
|
}
|
||||||
|
/* Should not get here if result was TS_YES */
|
||||||
|
Assert(false);
|
||||||
|
break;
|
||||||
|
case TS_MAYBE:
|
||||||
|
/* match positions are, and remain, uncertain */
|
||||||
|
return TS_MAYBE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case OP_PHRASE:
|
case OP_PHRASE:
|
||||||
case OP_AND:
|
case OP_AND:
|
||||||
memset(&Ldata, 0, sizeof(Ldata));
|
memset(&Ldata, 0, sizeof(Ldata));
|
||||||
memset(&Rdata, 0, sizeof(Rdata));
|
memset(&Rdata, 0, sizeof(Rdata));
|
||||||
|
|
||||||
if (!TS_phrase_execute(curitem + curitem->qoperator.left,
|
lmatch = TS_phrase_execute(curitem + curitem->qoperator.left,
|
||||||
arg, flags, chkcond, &Ldata))
|
arg, flags, chkcond, &Ldata);
|
||||||
return false;
|
if (lmatch == TS_NO)
|
||||||
|
return TS_NO;
|
||||||
|
|
||||||
if (!TS_phrase_execute(curitem + 1,
|
rmatch = TS_phrase_execute(curitem + 1,
|
||||||
arg, flags, chkcond, &Rdata))
|
arg, flags, chkcond, &Rdata);
|
||||||
return false;
|
if (rmatch == TS_NO)
|
||||||
|
return TS_NO;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If either operand has no position information, then we can't
|
* If either operand has no position information, then we can't
|
||||||
* return position data, only a "possible match" result. "Possible
|
* return reliable position data, only a MAYBE result.
|
||||||
* match" answers are only wanted when TS_EXEC_PHRASE_NO_POS flag
|
|
||||||
* is set, otherwise return false.
|
|
||||||
*/
|
*/
|
||||||
if ((Ldata.npos == 0 && !Ldata.negate) ||
|
if (lmatch == TS_MAYBE || rmatch == TS_MAYBE)
|
||||||
(Rdata.npos == 0 && !Rdata.negate))
|
return TS_MAYBE;
|
||||||
return (flags & TS_EXEC_PHRASE_NO_POS) ? true : false;
|
|
||||||
|
|
||||||
if (curitem->qoperator.oper == OP_PHRASE)
|
if (curitem->qoperator.oper == OP_PHRASE)
|
||||||
{
|
{
|
||||||
@ -1681,7 +1713,7 @@ TS_phrase_execute(QueryItem *curitem, void *arg, uint32 flags,
|
|||||||
Ldata.npos + Rdata.npos);
|
Ldata.npos + Rdata.npos);
|
||||||
if (data)
|
if (data)
|
||||||
data->negate = true;
|
data->negate = true;
|
||||||
return true;
|
return TS_YES;
|
||||||
}
|
}
|
||||||
else if (Ldata.negate)
|
else if (Ldata.negate)
|
||||||
{
|
{
|
||||||
@ -1717,27 +1749,24 @@ TS_phrase_execute(QueryItem *curitem, void *arg, uint32 flags,
|
|||||||
rmatch = TS_phrase_execute(curitem + 1,
|
rmatch = TS_phrase_execute(curitem + 1,
|
||||||
arg, flags, chkcond, &Rdata);
|
arg, flags, chkcond, &Rdata);
|
||||||
|
|
||||||
if (!lmatch && !rmatch)
|
if (lmatch == TS_NO && rmatch == TS_NO)
|
||||||
return false;
|
return TS_NO;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If a valid operand has no position information, then we can't
|
* If either operand has no position information, then we can't
|
||||||
* return position data, only a "possible match" result. "Possible
|
* return reliable position data, only a MAYBE result.
|
||||||
* match" answers are only wanted when TS_EXEC_PHRASE_NO_POS flag
|
|
||||||
* is set, otherwise return false.
|
|
||||||
*/
|
*/
|
||||||
if ((lmatch && Ldata.npos == 0 && !Ldata.negate) ||
|
if (lmatch == TS_MAYBE || rmatch == TS_MAYBE)
|
||||||
(rmatch && Rdata.npos == 0 && !Rdata.negate))
|
return TS_MAYBE;
|
||||||
return (flags & TS_EXEC_PHRASE_NO_POS) ? true : false;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Cope with undefined output width from failed submatch. (This
|
* Cope with undefined output width from failed submatch. (This
|
||||||
* takes less code than trying to ensure that all failure returns
|
* takes less code than trying to ensure that all failure returns
|
||||||
* set data->width to zero.)
|
* set data->width to zero.)
|
||||||
*/
|
*/
|
||||||
if (!lmatch)
|
if (lmatch == TS_NO)
|
||||||
Ldata.width = 0;
|
Ldata.width = 0;
|
||||||
if (!rmatch)
|
if (rmatch == TS_NO)
|
||||||
Rdata.width = 0;
|
Rdata.width = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1759,7 +1788,7 @@ TS_phrase_execute(QueryItem *curitem, void *arg, uint32 flags,
|
|||||||
Loffset, Roffset,
|
Loffset, Roffset,
|
||||||
Min(Ldata.npos, Rdata.npos));
|
Min(Ldata.npos, Rdata.npos));
|
||||||
data->negate = true;
|
data->negate = true;
|
||||||
return true;
|
return TS_YES;
|
||||||
}
|
}
|
||||||
else if (Ldata.negate)
|
else if (Ldata.negate)
|
||||||
{
|
{
|
||||||
@ -1769,7 +1798,7 @@ TS_phrase_execute(QueryItem *curitem, void *arg, uint32 flags,
|
|||||||
Loffset, Roffset,
|
Loffset, Roffset,
|
||||||
Ldata.npos);
|
Ldata.npos);
|
||||||
data->negate = true;
|
data->negate = true;
|
||||||
return true;
|
return TS_YES;
|
||||||
}
|
}
|
||||||
else if (Rdata.negate)
|
else if (Rdata.negate)
|
||||||
{
|
{
|
||||||
@ -1779,7 +1808,7 @@ TS_phrase_execute(QueryItem *curitem, void *arg, uint32 flags,
|
|||||||
Loffset, Roffset,
|
Loffset, Roffset,
|
||||||
Rdata.npos);
|
Rdata.npos);
|
||||||
data->negate = true;
|
data->negate = true;
|
||||||
return true;
|
return TS_YES;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -1795,7 +1824,7 @@ TS_phrase_execute(QueryItem *curitem, void *arg, uint32 flags,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* not reachable, but keep compiler quiet */
|
/* not reachable, but keep compiler quiet */
|
||||||
return false;
|
return TS_NO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1806,51 +1835,113 @@ TS_phrase_execute(QueryItem *curitem, void *arg, uint32 flags,
|
|||||||
* arg: opaque value to pass through to callback function
|
* arg: opaque value to pass through to callback function
|
||||||
* flags: bitmask of flag bits shown in ts_utils.h
|
* flags: bitmask of flag bits shown in ts_utils.h
|
||||||
* chkcond: callback function to check whether a primitive value is present
|
* chkcond: callback function to check whether a primitive value is present
|
||||||
*
|
|
||||||
* The logic here deals only with operators above any phrase operator, for
|
|
||||||
* which we do not need to worry about lexeme positions. As soon as we hit an
|
|
||||||
* OP_PHRASE operator, we pass it off to TS_phrase_execute which does worry.
|
|
||||||
*/
|
*/
|
||||||
bool
|
bool
|
||||||
TS_execute(QueryItem *curitem, void *arg, uint32 flags,
|
TS_execute(QueryItem *curitem, void *arg, uint32 flags,
|
||||||
TSExecuteCallback chkcond)
|
TSExecuteCallback chkcond)
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
* If we get TS_MAYBE from the recursion, return true. We could only see
|
||||||
|
* that result if the caller passed TS_EXEC_PHRASE_NO_POS, so there's no
|
||||||
|
* need to check again.
|
||||||
|
*/
|
||||||
|
return TS_execute_recurse(curitem, arg, flags, chkcond) != TS_NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TS_execute recursion for operators above any phrase operator. Here we do
|
||||||
|
* not need to worry about lexeme positions. As soon as we hit an OP_PHRASE
|
||||||
|
* operator, we pass it off to TS_phrase_execute which does worry.
|
||||||
|
*/
|
||||||
|
static TSTernaryValue
|
||||||
|
TS_execute_recurse(QueryItem *curitem, void *arg, uint32 flags,
|
||||||
|
TSExecuteCallback chkcond)
|
||||||
|
{
|
||||||
|
TSTernaryValue lmatch;
|
||||||
|
|
||||||
/* since this function recurses, it could be driven to stack overflow */
|
/* since this function recurses, it could be driven to stack overflow */
|
||||||
check_stack_depth();
|
check_stack_depth();
|
||||||
|
|
||||||
if (curitem->type == QI_VAL)
|
if (curitem->type == QI_VAL)
|
||||||
return chkcond(arg, (QueryOperand *) curitem,
|
return chkcond(arg, (QueryOperand *) curitem,
|
||||||
NULL /* we don't need position info */ );
|
NULL /* don't need position info */ ) ? TS_YES : TS_NO;
|
||||||
|
|
||||||
switch (curitem->qoperator.oper)
|
switch (curitem->qoperator.oper)
|
||||||
{
|
{
|
||||||
case OP_NOT:
|
case OP_NOT:
|
||||||
if (flags & TS_EXEC_CALC_NOT)
|
if (!(flags & TS_EXEC_CALC_NOT))
|
||||||
return !TS_execute(curitem + 1, arg, flags, chkcond);
|
return TS_YES;
|
||||||
else
|
switch (TS_execute_recurse(curitem + 1, arg, flags, chkcond))
|
||||||
return true;
|
{
|
||||||
|
case TS_NO:
|
||||||
|
return TS_YES;
|
||||||
|
case TS_YES:
|
||||||
|
return TS_NO;
|
||||||
|
case TS_MAYBE:
|
||||||
|
return TS_MAYBE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case OP_AND:
|
case OP_AND:
|
||||||
if (TS_execute(curitem + curitem->qoperator.left, arg, flags, chkcond))
|
lmatch = TS_execute_recurse(curitem + curitem->qoperator.left, arg,
|
||||||
return TS_execute(curitem + 1, arg, flags, chkcond);
|
flags, chkcond);
|
||||||
else
|
if (lmatch == TS_NO)
|
||||||
return false;
|
return TS_NO;
|
||||||
|
switch (TS_execute_recurse(curitem + 1, arg, flags, chkcond))
|
||||||
|
{
|
||||||
|
case TS_NO:
|
||||||
|
return TS_NO;
|
||||||
|
case TS_YES:
|
||||||
|
return lmatch;
|
||||||
|
case TS_MAYBE:
|
||||||
|
return TS_MAYBE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case OP_OR:
|
case OP_OR:
|
||||||
if (TS_execute(curitem + curitem->qoperator.left, arg, flags, chkcond))
|
lmatch = TS_execute_recurse(curitem + curitem->qoperator.left, arg,
|
||||||
return true;
|
flags, chkcond);
|
||||||
else
|
if (lmatch == TS_YES)
|
||||||
return TS_execute(curitem + 1, arg, flags, chkcond);
|
return TS_YES;
|
||||||
|
switch (TS_execute_recurse(curitem + 1, arg, flags, chkcond))
|
||||||
|
{
|
||||||
|
case TS_NO:
|
||||||
|
return lmatch;
|
||||||
|
case TS_YES:
|
||||||
|
return TS_YES;
|
||||||
|
case TS_MAYBE:
|
||||||
|
return TS_MAYBE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case OP_PHRASE:
|
case OP_PHRASE:
|
||||||
return TS_phrase_execute(curitem, arg, flags, chkcond, NULL);
|
|
||||||
|
/*
|
||||||
|
* If we get a MAYBE result, and the caller doesn't want that,
|
||||||
|
* convert it to NO. It would be more consistent, perhaps, to
|
||||||
|
* return the result of TS_phrase_execute() verbatim and then
|
||||||
|
* convert MAYBE results at the top of the recursion. But
|
||||||
|
* converting at the topmost phrase operator gives results that
|
||||||
|
* are bug-compatible with the old implementation, so do it like
|
||||||
|
* this for now.
|
||||||
|
*/
|
||||||
|
switch (TS_phrase_execute(curitem, arg, flags, chkcond, NULL))
|
||||||
|
{
|
||||||
|
case TS_NO:
|
||||||
|
return TS_NO;
|
||||||
|
case TS_YES:
|
||||||
|
return TS_YES;
|
||||||
|
case TS_MAYBE:
|
||||||
|
return (flags & TS_EXEC_PHRASE_NO_POS) ? TS_MAYBE : TS_NO;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
elog(ERROR, "unrecognized operator: %d", curitem->qoperator.oper);
|
elog(ERROR, "unrecognized operator: %d", curitem->qoperator.oper);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* not reachable, but keep compiler quiet */
|
/* not reachable, but keep compiler quiet */
|
||||||
return false;
|
return TS_NO;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -486,23 +486,23 @@
|
|||||||
\n fu uq co qk jl cg ld lg wo vr gc bd rj r3 yd rz iu ew d6 io to sh y7 jp db dn qn qm si xg qr ls jo lr wy rk wn m7 qu bb es op qp ru en ta e3 in hy dy hl vc gc gt jw ke 2t wh rk lj hg oy e6 yo ev em fz rw pq re dg qk ku oi qz k4 qv li rq n8 ec 4d yb wb e1 iw id o6 ir do ux pi ep
|
\n fu uq co qk jl cg ld lg wo vr gc bd rj r3 yd rz iu ew d6 io to sh y7 jp db dn qn qm si xg qr ls jo lr wy rk wn m7 qu bb es op qp ru en ta e3 in hy dy hl vc gc gt jw ke 2t wh rk lj hg oy e6 yo ev em fz rw pq re dg qk ku oi qz k4 qv li rq n8 ec 4d yb wb e1 iw id o6 ir do ux pi ep
|
||||||
\n a2 wu jd ef dc mn 5e qp pl xd ag ay
|
\n a2 wu jd ef dc mn 5e qp pl xd ag ay
|
||||||
\n yv o9 al a5 uq qg jw pi z2 jt cd q5 3m zl ez vu rg jl rz yf ix sj fp d0 tq ff ha hs zw om ni m0 xg c8 a7 ki qw cc ei xg j3 tt tu il p6 ix tp tx ib sp hg p0 fc pj su qu jv sj lk qp ws qs gm 1x mx lv wj qu l1 dt wh wv un aq fg rg e6 uo ar ie up it sw tx f6 o2 h3 qc qa ho vj u3 kd zy n6 my ww vc lr em w2 se rt o4 yc a1 te
|
\n yv o9 al a5 uq qg jw pi z2 jt cd q5 3m zl ez vu rg jl rz yf ix sj fp d0 tq ff ha hs zw om ni m0 xg c8 a7 ki qw cc ei xg j3 tt tu il p6 ix tp tx ib sp hg p0 fc pj su qu jv sj lk qp ws qs gm 1x mx lv wj qu l1 dt wh wv un aq fg rg e6 uo ar ie up it sw tx f6 o2 h3 qc qa ho vj u3 kd zy n6 my ww vc lr em w2 se rt o4 yc a1 te
|
||||||
\n qs dv pa ty iz uw qh jj z3 tn jc eg e4 qq w7 ut r3 uu kb up g1 fo iv if fd gd sc qm qe xg ia wb he ky hu tv rw qu rr es p3 ue s2 as i0 dt qt hz jm j0 gy ci fi hw nv ea kk vf rx 68 ti rp wl oi vp at om io uk pt qh qj dl cf lr cx wq ku ki w2 yh af ul sp yc it
|
\n qs:1 dv:2 pa:3 ty:4 iz:5 uw:6 qh:7 jj:8 z3:9 tn:10 jc:11 eg:12 e4:13 qq:14 w7:15 ut:16 r3:17 uu:18 kb:19 up:20 g1:21 fo:22 iv:23 if:24 fd:25 gd:26 sc:27 qm:28 qe:29 xg:30 ia:31 wb:32 he:33 ky:34 hu:35 tv:36 rw:37 qu:38 rr:39 es:40 p3:41 ue:42 s2:43 as:44 i0:45 dt:46 qt:47 hz:48 jm:49 j0:50 gy:51 ci:52 fi:53 hw:54 nv:55 ea:56 kk:57 vf:58 rx:59 68:60 ti:61 rp:62 wl:63 oi:64 vp:65 at:66 om:67 io:68 uk:69 pt:70 qh:71 qj:72 dl:73 cf:74 lr:75 cx:76 wq:77 ku:78 ki:79 w2:80 yh:81 af:82 ul:83 sp:84 yc:85
|
||||||
\n ub yb dc ty gm dm go nv we ql by la o1 ju o3 jx fm aj wa rg e4 vi a6 r4 xo tz oe ip pv dk tq a0 tf fg tg i4 pz sd ry ky mg hy g7 eu qy yi rw qp eg yw hw sm uc i7 dw fx s3 sf zo m9 xs vn rf ci nz kr qt 9y pj lk ee pz ef rk e0 fx uf az fc qg jr oy lq cg qp um ad wc zn bw n6 my xr mp tu en o3 iq ir ro
|
\n ub:1 yb:2 dc:3 ty:4 gm:5 dm:6 go:7 nv:8 we:9 ql:10 by:11 la:12 o1:13 ju:14 o3:15 jx:16 fm:17 aj:18 wa:19 rg:20 e4:21 vi:22 a6:23 r4:24 xo:25 tz:26 oe:27 ip:28 pv:29 dk:30 tq:31 a0:32 tf:33 fg:34 tg:35 i4:36 pz:37 sd:38 ry:39 ky:40 mg:41 hy:42 g7:43 eu:44 qy:45 yi:46 rw:47 qp:48 eg:49 yw:50 hw:51 sm:52 uc:53 i7:54 dw:55 fx:56 s3:57 sf:58 zo:59 m9:60 xs:61 vn:62 rf:63 ci:64 nz:65 kr:66 qt:67 9y:68 pj:69 lk:70 ee:71 pz:72 ef:73 rk:74 e0:75 fx:76 uf:77 az:78 fc:79 qg:80 jr:81 oy:82 lq:83 cg:84 qp:85 um:86 ad:87 wc:88 zn:89 bw:90 n6:91 my:92 xr:93 mp:94 tu:95 en:96 o3:97 iq:98 ir:99
|
||||||
\n da a3 d1 jr dz ca ql nu q3 cf o6 nr mt lk yr rs lp w7 a5 pj ys ym r8 ey to fs dz im ih sw qx qv zn gl j1 xe lc zc vw 6a mh b9 qt rm re oo qp p4 tk ix p7 og tz yr sp aa hk ih lx qd mx 4n kk vf el oo td ae yo fj uf pr hl qj qk wr qc qv kf yz my wq hn zs dr ee u8 rv et ru ie ag tw
|
\n da:1 a3:2 d1:3 jr:4 dz:5 ca:6 ql:7 nu:8 q3:9 cf:10 o6:11 nr:12 mt:13 lk:14 yr:15 rs:16 lp:17 w7:18 a5:19 pj:20 ys:21 ym:22 r8:23 ey:24 to:25 fs:26 dz:27 im:28 ih:29 sw:30 qx:31 qv:32 zn:33 gl:34 j1:35 xe:36 lc:37 zc:38 vw:39 6a:40 mh:41 b9:42 qt:43 rm:44 re:45 oo:46 qp:47 p4:48 tk:49 ix:50 p7:51 og:52 tz:53 yr:54 sp:55 aa:56 hk:57 ih:58 lx:59 qd:60 mx:61 4n:62 kk:63 vf:64 el:65 oo:66 td:67 ae:68 yo:69 fj:70 uf:71 pr:72 hl:73 qj:74 qk:75 wr:76 qc:77 qv:78 kf:79 yz:80 my:81 wq:82 hn:83 zs:84 dr:85 ee:86 u8:87 rv:88 et:89 ru:90 ie:91 ag:92
|
||||||
\n gt ph z0 zl mu ui av zm om ui vh qr he qr es fl ws w6 nc ra rk kp ol wm yu it
|
\n gt:1 ph:2 z0:3 zl:4 mu:5 ui:6 av:7 zm:8 om:9 ui:10 vh:11 qr:12 he:13 qr:14 es:15 fl:16 ws:17 w6:18 nc:19 ra:20 rk:21 kp:22 ol:23 wm:24 yu:25
|
||||||
\n dd df jq jd ux ql el 3r ya uu iu ee eh g3 sj us ib pp qc jv hd bh zt uo d8 b3 xu bc rq te uh ex tt eb il qu pc ge sj qp ih xf 3r gr yh qx tu wl wn sz up ay it ab jt qz v7 wn li za 6o w3 fn yk eu ie gz ro
|
\n dd:1 df:2 jq:3 jd:4 ux:5 ql:6 el:7 3r:8 ya:9 uu:10 iu:11 ee:12 eh:13 g3:14 sj:15 us:16 ib:17 pp:18 qc:19 jv:20 hd:21 bh:22 zt:23 uo:24 d8:25 b3:26 xu:27 bc:28 rq:29 te:30 uh:31 ex:32 tt:33 eb:34 il:35 qu:36 pc:37 ge:38 sj:39 qp:40 ih:41 xf:42 3r:43 gr:44 yh:45 qx:46 tu:47 wl:48 wn:49 sz:50 up:51 ay:52 it:53 ab:54 jt:55 qz:56 v7:57 wn:58 li:59 za:60 6o:61 w3:62 fn:63 yk:64 eu:65 ie:66 gz:67
|
||||||
\n yv o9 qf eg eh mh jh rh r3 rv ix y3 a0 sr qc qq qr wr qe bx ki m8 mk qi lm uk eb ai ur e2 xd nc ca eo mb ed uv rs up ya of hn lw wz qz et qh wm zr rc o3 r2
|
\n yv:1 o9:2 qf:3 eg:4 eh:5 mh:6 jh:7 rh:8 r3:9 rv:10 ix:11 y3:12 a0:13 sr:14 qc:15 qq:16 qr:17 wr:18 qe:19 bx:20 ki:21 m8:22 mk:23 qi:24 lm:25 uk:26 eb:27 ai:28 ur:29 e2:30 xd:31 nc:32 ca:33 eo:34 mb:35 ed:36 uv:37 rs:38 up:39 ya:40 of:41 hn:42 lw:43 wz:44 qz:45 et:46 qh:47 wm:48 zr:49 rc:50 o3:51
|
||||||
\n ss qg qj ph qk q2 cs z4 bi qc cj q8 qn w7 rj ys ea r4 uy om rc ii fp sj ej yz el qx qv zn gk q9 hs m2 ii d7 nk c8 j4 qq dl gg pp ei qo yc od fo eh fp ta hy ok tv uu us dp qf sb zg ks sg n3 wh x2 nr cs wk kh wk wf ew 7h 7k oy t6 gi rg yp s9 ya e9 pb tc dt dh hk h2 pt qh h7 wz n1 qv kd pm cc xr kp yk tm ge
|
\n ss:1 qg:2 qj:3 ph:4 qk:5 q2:6 cs:7 z4:8 bi:9 qc:10 cj:11 q8:12 qn:13 w7:14 rj:15 ys:16 ea:17 r4:18 uy:19 om:20 rc:21 ii:22 fp:23 sj:24 ej:25 yz:26 el:27 qx:28 qv:29 zn:30 gk:31 q9:32 hs:33 m2:34 ii:35 d7:36 nk:37 c8:38 j4:39 qq:40 dl:41 gg:42 pp:43 ei:44 qo:45 yc:46 od:47 fo:48 eh:49 fp:50 ta:51 hy:52 ok:53 tv:54 uu:55 us:56 dp:57 qf:58 sb:59 zg:60 ks:61 sg:62 n3:63 wh:64 x2:65 nr:66 cs:67 wk:68 kh:69 wk:70 wf:71 ew:72 7h:73 7k:74 oy:75 t6:76 gi:77 rg:78 yp:79 s9:80 ya:81 e9:82 pb:83 tc:84 dt:85 dh:86 hk:87 h2:88 pt:89 qh:90 h7:91 wz:92 n1:93 qv:94 kd:95 pm:96 cc:97 xr:98 kp:99 yk:100 tm:101
|
||||||
\n gr qa ft tt gn qs pw pu ca ph ls cg cn zf bz q7 z0 c3 qn gv w7 rg ut e8 ii er ip sg y3 oy ek ht gd qx g0 qv db su jn qq lz uu jo ru an wi kn sq nh qr qy yx eo qi xz y9 ru pd au p7 dq he ut ok fd jz ui hc j9 l3 hb xd jq gy kh wf xs sl rs aq ez y4 ts um yi e0 gh dk py v5 qk ql ko jq wc nk v0 wb qv br iu wm 6p sr gk yp pu
|
\n gr:1 qa:2 ft:3 tt:4 gn:5 qs:6 pw:7 pu:8 ca:9 ph:10 ls:11 cg:12 cn:13 zf:14 bz:15 q7:16 z0:17 c3:18 qn:19 gv:20 w7:21 rg:22 ut:23 e8:24 ii:25 er:26 ip:27 sg:28 y3:29 oy:30 ek:31 ht:32 gd:33 qx:34 g0:35 qv:36 db:37 su:38 jn:39 qq:40 lz:41 uu:42 jo:43 ru:44 an:45 wi:46 kn:47 sq:48 nh:49 qr:50 qy:51 yx:52 eo:53 qi:54 xz:55 y9:56 ru:57 pd:58 au:59 p7:60 dq:61 he:62 ut:63 ok:64 fd:65 jz:66 ui:67 hc:68 j9:69 l3:70 hb:71 xd:72 jq:73 gy:74 kh:75 wf:76 xs:77 sl:78 rs:79 aq:80 ez:81 y4:82 ts:83 um:84 yi:85 e0:86 gh:87 dk:88 py:89 v5:90 qk:91 ql:92 ko:93 jq:94 wc:95 nk:96 v0:97 wb:98 qv:99 br:100 iu:101 wm:102 6p:103 sr:104 gk:105 yp:106
|
||||||
\n o0 pa pf z3 jt jy z7 cm ne w8 yz fd fg zn qq ll vg wr wb ia xx yj ty eh e1 so ts tc s4 i0 tn wo wp wa op va wk x3 vg qx rs sn au f3 tz sq hn rr o2 fv un k2 vj ey dj
|
\n o0:1 pa:2 pf:3 z3:4 jt:5 jy:6 z7:7 cm:8 ne:9 w8:10 yz:11 fd:12 fg:13 zn:14 qq:15 ll:16 vg:17 wr:18 wb:19 ia:20 xx:21 yj:22 ty:23 eh:24 e1:25 so:26 ts:27 tc:28 s4:29 i0:30 tn:31 wo:32 wp:33 wa:34 op:35 va:36 wk:37 x3:38 vg:39 qx:40 rs:41 sn:42 au:43 f3:44 tz:45 sq:46 hn:47 rr:48 o2:49 fv:50 un:51 k2:52 vj:53 ey:54
|
||||||
\n iy ra ij ty a4 un rf qg dm jr kj uv we cv gk wy z8 oc wp mo jl mz ev ch rv tu ax y2 g3 oy y6 im uq qv hp qb hd iy lp nk w2 bb ho ep tr os en sm p8 p9 hy ss ui gm qi oo vn ae qd w6 ps dn wd wg ro mr yt ol oz rg s7 u5 tl yd rr ax f0 cq ku qx ze n4 wn kt ca jy bg yc zs yw rz w1 eu rm r1
|
\n iy:1 ra:2 ij:3 ty:4 a4:5 un:6 rf:7 qg:8 dm:9 jr:10 kj:11 uv:12 we:13 cv:14 gk:15 wy:16 z8:17 oc:18 wp:19 mo:20 jl:21 mz:22 ev:23 ch:24 rv:25 tu:26 ax:27 y2:28 g3:29 oy:30 y6:31 im:32 uq:33 qv:34 hp:35 qb:36 hd:37 iy:38 lp:39 nk:40 w2:41 bb:42 ho:43 ep:44 tr:45 os:46 en:47 sm:48 p8:49 p9:50 hy:51 ss:52 ui:53 gm:54 qi:55 oo:56 vn:57 ae:58 qd:59 w6:60 ps:61 dn:62 wd:63 wg:64 ro:65 mr:66 yt:67 ol:68 oz:69 rg:70 s7:71 u5:72 tl:73 yd:74 rr:75 ax:76 f0:77 cq:78 ku:79 qx:80 ze:81 n4:82 wn:83 kt:84 ca:85 jy:86 bg:87 yc:88 zs:89 yw:90 rz:91 w1:92 eu:93 rm:94
|
||||||
\n hv fu ca q8 mt la r3 pl yh to sy yh tv x4 tg yp ov wn ze sp
|
\n hv:1 fu:2 ca:3 q8:4 mt:5 la:6 r3:7 pl:8 yh:9 to:10 sy:11 yh:12 tv:13 x4:14 tg:15 yp:16 ov:17 wn:18 ze:19
|
||||||
\n o9 qa az gm qd pw hq pd ga qj cd q3 jk pd du c2 zk xf t8 eq om es rc ua y3 pu ig qx se qv db st qn ii lx qe wt xk nx ku br qe qr qt rm eu xf xb rn qu qi ep qo rr ex xk p5 ym fi uq to ux ix ai hj gn zi oq qf kd wf xn kr w8 rl kk mq rp rf u1 s7 oa fh e7 yp e0 pr ql sx ck ag kg kt mp eb rl em ee w6 du rm yz if ep
|
\n o9:1 qa:2 az:3 gm:4 qd:5 pw:6 hq:7 pd:8 ga:9 qj:10 cd:11 q3:12 jk:13 pd:14 du:15 c2:16 zk:17 xf:18 t8:19 eq:20 om:21 es:22 rc:23 ua:24 y3:25 pu:26 ig:27 qx:28 se:29 qv:30 db:31 st:32 qn:33 ii:34 lx:35 qe:36 wt:37 xk:38 nx:39 ku:40 br:41 qe:42 qr:43 qt:44 rm:45 eu:46 xf:47 xb:48 rn:49 qu:50 qi:51 ep:52 qo:53 rr:54 ex:55 xk:56 p5:57 ym:58 fi:59 uq:60 to:61 ux:62 ix:63 ai:64 hj:65 gn:66 zi:67 oq:68 qf:69 kd:70 wf:71 xn:72 kr:73 w8:74 rl:75 kk:76 mq:77 rp:78 rf:79 u1:80 s7:81 oa:82 fh:83 e7:84 yp:85 e0:86 pr:87 ql:88 sx:89 ck:90 ag:91 kg:92 kt:93 mp:94 eb:95 rl:96 em:97 ee:98 w6:99 du:100 rm:101 yz:102 if:103
|
||||||
\n qs pi am 6a ut r4 ii sd ua ib y6 pa kt pb wm qq dz qt qp y0 he p8 ue tb qu or qo wh 40 8j t4 sl rf iu gh hh qc iq bf rl wm mf oh ew is dp
|
\n qs:1 pi:2 am:3 6a:4 ut:5 r4:6 ii:7 sd:8 ua:9 ib:10 y6:11 pa:12 kt:13 pb:14 wm:15 qq:16 dz:17 qt:18 qp:19 y0:20 he:21 p8:22 ue:23 tb:24 qu:25 or:26 qo:27 wh:28 40:29 8j:30 t4:31 sl:32 rf:33 iu:34 gh:35 hh:36 qc:37 iq:38 bf:39 rl:40 wm:41 mf:42 oh:43 ew:44 is:45
|
||||||
\n da ps a7 jr z4 q3 bu xt ip jx q6 np z7 bp lg bz ye wo ig bb ww rf om uu ef r8 ey pt ta pn y7 gg th dn pg qb ri qq 42 qw zw b9 b0 xb qt qy yl wh xk ft at yw i7 sp de pz fn qy si m0 ik wf sg cq ql hk er eg lc ek na wc iw ir rk ua e0 ak iu sw ap uj av ab hl uv zc qa wc jw vj qv vk ay kg xw on rw 1b wn rl eb vm eq h4 yt oz eu uz
|
\n da:1 ps:2 a7:3 jr:4 z4:5 q3:6 bu:7 xt:8 ip:9 jx:10 q6:11 np:12 z7:13 bp:14 lg:15 bz:16 ye:17 wo:18 ig:19 bb:20 ww:21 rf:22 om:23 uu:24 ef:25 r8:26 ey:27 pt:28 ta:29 pn:30 y7:31 gg:32 th:33 dn:34 pg:35 qb:36 ri:37 qq:38 42:39 qw:40 zw:41 b9:42 b0:43 xb:44 qt:45 qy:46 yl:47 wh:48 xk:49 ft:50 at:51 yw:52 i7:53 sp:54 de:55 pz:56 fn:57 qy:58 si:59 m0:60 ik:61 wf:62 sg:63 cq:64 ql:65 hk:66 er:67 eg:68 lc:69 ek:70 na:71 wc:72 iw:73 ir:74 rk:75 ua:76 e0:77 ak:78 iu:79 sw:80 ap:81 uj:82 av:83 ab:84 hl:85 uv:86 zc:87 qa:88 wc:89 jw:90 vj:91 qv:92 vk:93 ay:94 kg:95 xw:96 on:97 rw:98 1b:99 wn:100 rl:101 eb:102 vm:103 eq:104 h4:105 yt:106 oz:107 eu:108
|
||||||
\n a2 qa rd cp qh ub vg ws u0 4g bp da yo ev kz eq uu ee ef yk pr sj sk fe oi lt uy j2 gn io vk ns 27 ln wu ve yr l2 qu qi ry il ul tj eg ux i5 yr tx ph oj gq or zp wa qs gy iz v0 qt wj ic ca lh yb np ej sl td l8 yi iw s8 e8 ys yd sq al dt pt tg te yb eu tq r1 ir fe
|
\n a2:1 qa:2 rd:3 cp:4 qh:5 ub:6 vg:7 ws:8 u0:9 4g:10 bp:11 da:12 yo:13 ev:14 kz:15 eq:16 uu:17 ee:18 ef:19 yk:20 pr:21 sj:22 sk:23 fe:24 oi:25 lt:26 uy:27 j2:28 gn:29 io:30 vk:31 ns:32 27:33 ln:34 wu:35 ve:36 yr:37 l2:38 qu:39 qi:40 ry:41 il:42 ul:43 tj:44 eg:45 ux:46 i5:47 yr:48 tx:49 ph:50 oj:51 gq:52 or:53 zp:54 wa:55 qs:56 gy:57 iz:58 v0:59 qt:60 wj:61 ic:62 ca:63 lh:64 yb:65 np:66 ej:67 sl:68 td:69 l8:70 yi:71 iw:72 s8:73 e8:74 ys:75 yd:76 sq:77 al:78 dt:79 pt:80 tg:81 te:82 yb:83 eu:84 tq:85 r1:86 ir:87
|
||||||
\n tr h9 go qj b1 wu q7 zh el tg mb ys ed ii er r8 xs pe r0 sw db ov m7 d3 re no nu zr pq ji wr lc or qw ee yy qr rn rm re qi te ea qo yb yn y0 uz uq iz tl yr i0 fm wp qs qd he wk kl ew as hl ez oo ox ie s0 f4 dl wq wl ww lr qc qv vk mt my kn ep em yt sy am so rp sp
|
\n tr:1 h9:2 go:3 qj:4 b1:5 wu:6 q7:7 zh:8 el:9 tg:10 mb:11 ys:12 ed:13 ii:14 er:15 r8:16 xs:17 pe:18 r0:19 sw:20 db:21 ov:22 m7:23 d3:24 re:25 no:26 nu:27 zr:28 pq:29 ji:30 wr:31 lc:32 or:33 qw:34 ee:35 yy:36 qr:37 rn:38 rm:39 re:40 qi:41 te:42 ea:43 qo:44 yb:45 yn:46 y0:47 uz:48 uq:49 iz:50 tl:51 yr:52 i0:53 fm:54 wp:55 qs:56 qd:57 he:58 wk:59 kl:60 ew:61 as:62 hl:63 ez:64 oo:65 ox:66 ie:67 s0:68 f4:69 dl:70 wq:71 wl:72 ww:73 lr:74 qc:75 qv:76 vk:77 mt:78 my:79 kn:80 ep:81 em:82 yt:83 sy:84 am:85 so:86 rp:87
|
||||||
\n ak ft qg bg ji q6 bk xi tf mo ur pj yk ua qv wq gc qe ke ef eb tk uq i6 oh iv gb qs rx el yo rr pe wz wx ho xq tc mo yk du r1 tq oc hc te
|
\n ak:1 ft:2 qg:3 bg:4 ji:5 q6:6 bk:7 xi:8 tf:9 mo:10 ur:11 pj:12 yk:13 ua:14 qv:15 wq:16 gc:17 qe:18 ke:19 ef:20 eb:21 tk:22 uq:23 i6:24 oh:25 iv:26 gb:27 qs:28 rx:29 el:30 yo:31 rr:32 pe:33 wz:34 wx:35 ho:36 xq:37 tc:38 mo:39 yk:40 du:41 r1:42 tq:43 oc:44 hc:45
|
||||||
\n ra ub qj jh jt dx ql q6 da tf r3 ew iu sg tp yl el gc 6n tt ry pd ye ff lz kt yp fl yf dl rn
|
\n ra:1 ub:2 qj:3 jh:4 jt:5 dx:6 ql:7 q6:8 da:9 tf:10 r3:11 ew:12 iu:13 sg:14 tp:15 yl:16 el:17 gc:18 6n:19 tt:20 ry:21 pd:22 ye:23 ff:24 lz:25 kt:26 yp:27 fl:28 yf:29 dl:30
|
||||||
\n o9 hb h9 qd dh qg q1 qj jy se q5 wt nr qv ge c5 el 6y uo rv ax pe et r0 fe y6 dx qx ha qq lo we zy v1 wy dl vr wa qr rm qi qp yn tz pg ph de p0 do qp wp wf bw xh ky xz wh hl to ek rd sv rj rq re h1 qg qh kl f1 zm 18 ez xe vm en 5j o3 rn fw fe it
|
\n o9:1 hb:2 h9:3 qd:4 dh:5 qg:6 q1:7 qj:8 jy:9 se:10 q5:11 wt:12 nr:13 qv:14 ge:15 c5:16 el:17 6y:18 uo:19 rv:20 ax:21 pe:22 et:23 r0:24 fe:25 y6:26 dx:27 qx:28 ha:29 qq:30 lo:31 we:32 zy:33 v1:34 wy:35 dl:36 vr:37 wa:38 qr:39 rm:40 qi:41 qp:42 yn:43 tz:44 pg:45 ph:46 de:47 p0:48 do:49 qp:50 wp:51 wf:52 bw:53 xh:54 ky:55 xz:56 wh:57 hl:58 to:59 ek:60 rd:61 sv:62 rj:63 rq:64 re:65 h1:66 qg:67 qh:68 kl:69 f1:70 zm:71 18:72 ez:73 xe:74 vm:75 en:76 5j:77 o3:78 rn:79 fw:80 fe:81
|
||||||
\n db c2 bb o0 w8 kl kc y4 qx zm pk cw id ve mh lp rq jb fl x1 qi wd lx f3 cy bq dd ye fn ig
|
\n db:1 c2:2 bb:3 o0:4 w8:5 kl:6 kc:7 y4:8 qx:9 zm:10 pk:11 cw:12 id:13 ve:14 mh:15 lp:16 rq:17 jb:18 fl:19 x1:20 qi:21 wd:22 lx:23 f3:24 cy:25 bq:26 dd:27 ye:28 fn:29
|
||||||
|
@ -116,6 +116,66 @@ SELECT count(*) FROM test_tsvector WHERE a @@ '!no_such_lexeme';
|
|||||||
508
|
508
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
|
SELECT count(*) FROM test_tsvector WHERE a @@ 'pl <-> yh';
|
||||||
|
count
|
||||||
|
-------
|
||||||
|
1
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT count(*) FROM test_tsvector WHERE a @@ 'yh <-> pl';
|
||||||
|
count
|
||||||
|
-------
|
||||||
|
0
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT count(*) FROM test_tsvector WHERE a @@ 'qe <2> qt';
|
||||||
|
count
|
||||||
|
-------
|
||||||
|
1
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT count(*) FROM test_tsvector WHERE a @@ '!pl <-> yh';
|
||||||
|
count
|
||||||
|
-------
|
||||||
|
3
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT count(*) FROM test_tsvector WHERE a @@ '!pl <-> !yh';
|
||||||
|
count
|
||||||
|
-------
|
||||||
|
432
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT count(*) FROM test_tsvector WHERE a @@ '!yh <-> pl';
|
||||||
|
count
|
||||||
|
-------
|
||||||
|
1
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT count(*) FROM test_tsvector WHERE a @@ '!qe <2> qt';
|
||||||
|
count
|
||||||
|
-------
|
||||||
|
6
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT count(*) FROM test_tsvector WHERE a @@ '!(pl <-> yh)';
|
||||||
|
count
|
||||||
|
-------
|
||||||
|
507
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT count(*) FROM test_tsvector WHERE a @@ '!(yh <-> pl)';
|
||||||
|
count
|
||||||
|
-------
|
||||||
|
508
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT count(*) FROM test_tsvector WHERE a @@ '!(qe <2> qt)';
|
||||||
|
count
|
||||||
|
-------
|
||||||
|
507
|
||||||
|
(1 row)
|
||||||
|
|
||||||
create index wowidx on test_tsvector using gist (a);
|
create index wowidx on test_tsvector using gist (a);
|
||||||
SET enable_seqscan=OFF;
|
SET enable_seqscan=OFF;
|
||||||
SET enable_indexscan=ON;
|
SET enable_indexscan=ON;
|
||||||
@ -188,6 +248,66 @@ SELECT count(*) FROM test_tsvector WHERE a @@ '!no_such_lexeme';
|
|||||||
508
|
508
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
|
SELECT count(*) FROM test_tsvector WHERE a @@ 'pl <-> yh';
|
||||||
|
count
|
||||||
|
-------
|
||||||
|
1
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT count(*) FROM test_tsvector WHERE a @@ 'yh <-> pl';
|
||||||
|
count
|
||||||
|
-------
|
||||||
|
0
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT count(*) FROM test_tsvector WHERE a @@ 'qe <2> qt';
|
||||||
|
count
|
||||||
|
-------
|
||||||
|
1
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT count(*) FROM test_tsvector WHERE a @@ '!pl <-> yh';
|
||||||
|
count
|
||||||
|
-------
|
||||||
|
3
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT count(*) FROM test_tsvector WHERE a @@ '!pl <-> !yh';
|
||||||
|
count
|
||||||
|
-------
|
||||||
|
432
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT count(*) FROM test_tsvector WHERE a @@ '!yh <-> pl';
|
||||||
|
count
|
||||||
|
-------
|
||||||
|
1
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT count(*) FROM test_tsvector WHERE a @@ '!qe <2> qt';
|
||||||
|
count
|
||||||
|
-------
|
||||||
|
6
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT count(*) FROM test_tsvector WHERE a @@ '!(pl <-> yh)';
|
||||||
|
count
|
||||||
|
-------
|
||||||
|
507
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT count(*) FROM test_tsvector WHERE a @@ '!(yh <-> pl)';
|
||||||
|
count
|
||||||
|
-------
|
||||||
|
508
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT count(*) FROM test_tsvector WHERE a @@ '!(qe <2> qt)';
|
||||||
|
count
|
||||||
|
-------
|
||||||
|
507
|
||||||
|
(1 row)
|
||||||
|
|
||||||
SET enable_indexscan=OFF;
|
SET enable_indexscan=OFF;
|
||||||
SET enable_bitmapscan=ON;
|
SET enable_bitmapscan=ON;
|
||||||
explain (costs off) SELECT count(*) FROM test_tsvector WHERE a @@ 'wr|qh';
|
explain (costs off) SELECT count(*) FROM test_tsvector WHERE a @@ 'wr|qh';
|
||||||
@ -260,6 +380,66 @@ SELECT count(*) FROM test_tsvector WHERE a @@ '!no_such_lexeme';
|
|||||||
508
|
508
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
|
SELECT count(*) FROM test_tsvector WHERE a @@ 'pl <-> yh';
|
||||||
|
count
|
||||||
|
-------
|
||||||
|
1
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT count(*) FROM test_tsvector WHERE a @@ 'yh <-> pl';
|
||||||
|
count
|
||||||
|
-------
|
||||||
|
0
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT count(*) FROM test_tsvector WHERE a @@ 'qe <2> qt';
|
||||||
|
count
|
||||||
|
-------
|
||||||
|
1
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT count(*) FROM test_tsvector WHERE a @@ '!pl <-> yh';
|
||||||
|
count
|
||||||
|
-------
|
||||||
|
3
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT count(*) FROM test_tsvector WHERE a @@ '!pl <-> !yh';
|
||||||
|
count
|
||||||
|
-------
|
||||||
|
432
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT count(*) FROM test_tsvector WHERE a @@ '!yh <-> pl';
|
||||||
|
count
|
||||||
|
-------
|
||||||
|
1
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT count(*) FROM test_tsvector WHERE a @@ '!qe <2> qt';
|
||||||
|
count
|
||||||
|
-------
|
||||||
|
6
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT count(*) FROM test_tsvector WHERE a @@ '!(pl <-> yh)';
|
||||||
|
count
|
||||||
|
-------
|
||||||
|
507
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT count(*) FROM test_tsvector WHERE a @@ '!(yh <-> pl)';
|
||||||
|
count
|
||||||
|
-------
|
||||||
|
508
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT count(*) FROM test_tsvector WHERE a @@ '!(qe <2> qt)';
|
||||||
|
count
|
||||||
|
-------
|
||||||
|
507
|
||||||
|
(1 row)
|
||||||
|
|
||||||
RESET enable_seqscan;
|
RESET enable_seqscan;
|
||||||
RESET enable_indexscan;
|
RESET enable_indexscan;
|
||||||
RESET enable_bitmapscan;
|
RESET enable_bitmapscan;
|
||||||
@ -337,6 +517,66 @@ SELECT count(*) FROM test_tsvector WHERE a @@ '!no_such_lexeme';
|
|||||||
508
|
508
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
|
SELECT count(*) FROM test_tsvector WHERE a @@ 'pl <-> yh';
|
||||||
|
count
|
||||||
|
-------
|
||||||
|
1
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT count(*) FROM test_tsvector WHERE a @@ 'yh <-> pl';
|
||||||
|
count
|
||||||
|
-------
|
||||||
|
0
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT count(*) FROM test_tsvector WHERE a @@ 'qe <2> qt';
|
||||||
|
count
|
||||||
|
-------
|
||||||
|
1
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT count(*) FROM test_tsvector WHERE a @@ '!pl <-> yh';
|
||||||
|
count
|
||||||
|
-------
|
||||||
|
3
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT count(*) FROM test_tsvector WHERE a @@ '!pl <-> !yh';
|
||||||
|
count
|
||||||
|
-------
|
||||||
|
432
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT count(*) FROM test_tsvector WHERE a @@ '!yh <-> pl';
|
||||||
|
count
|
||||||
|
-------
|
||||||
|
1
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT count(*) FROM test_tsvector WHERE a @@ '!qe <2> qt';
|
||||||
|
count
|
||||||
|
-------
|
||||||
|
6
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT count(*) FROM test_tsvector WHERE a @@ '!(pl <-> yh)';
|
||||||
|
count
|
||||||
|
-------
|
||||||
|
507
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT count(*) FROM test_tsvector WHERE a @@ '!(yh <-> pl)';
|
||||||
|
count
|
||||||
|
-------
|
||||||
|
508
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT count(*) FROM test_tsvector WHERE a @@ '!(qe <2> qt)';
|
||||||
|
count
|
||||||
|
-------
|
||||||
|
507
|
||||||
|
(1 row)
|
||||||
|
|
||||||
RESET enable_seqscan;
|
RESET enable_seqscan;
|
||||||
INSERT INTO test_tsvector VALUES ('???', 'DFG:1A,2B,6C,10 FGH');
|
INSERT INTO test_tsvector VALUES ('???', 'DFG:1A,2B,6C,10 FGH');
|
||||||
SELECT * FROM ts_stat('SELECT a FROM test_tsvector') ORDER BY ndoc DESC, nentry DESC, word LIMIT 10;
|
SELECT * FROM ts_stat('SELECT a FROM test_tsvector') ORDER BY ndoc DESC, nentry DESC, word LIMIT 10;
|
||||||
@ -344,14 +584,14 @@ SELECT * FROM ts_stat('SELECT a FROM test_tsvector') ORDER BY ndoc DESC, nentry
|
|||||||
------+------+--------
|
------+------+--------
|
||||||
qq | 108 | 108
|
qq | 108 | 108
|
||||||
qt | 102 | 102
|
qt | 102 | 102
|
||||||
qe | 100 | 100
|
qe | 100 | 101
|
||||||
qh | 98 | 98
|
qh | 98 | 99
|
||||||
qw | 98 | 98
|
qw | 98 | 98
|
||||||
qa | 97 | 97
|
qa | 97 | 97
|
||||||
ql | 94 | 94
|
ql | 94 | 94
|
||||||
qs | 94 | 94
|
qs | 94 | 94
|
||||||
|
qr | 92 | 93
|
||||||
qi | 92 | 92
|
qi | 92 | 92
|
||||||
qr | 92 | 92
|
|
||||||
(10 rows)
|
(10 rows)
|
||||||
|
|
||||||
SELECT * FROM ts_stat('SELECT a FROM test_tsvector', 'AB') ORDER BY ndoc DESC, nentry DESC, word;
|
SELECT * FROM ts_stat('SELECT a FROM test_tsvector', 'AB') ORDER BY ndoc DESC, nentry DESC, word;
|
||||||
|
@ -767,12 +767,90 @@ select to_tsvector('simple', 'z q') @@ '(!x | y <-> z) <-> q' AS "true";
|
|||||||
t
|
t
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
|
select to_tsvector('simple', 'x y q') @@ '(!x | y) <-> y <-> q' AS "false";
|
||||||
|
false
|
||||||
|
-------
|
||||||
|
f
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
select to_tsvector('simple', 'x y q') @@ '(!x | !y) <-> y <-> q' AS "true";
|
||||||
|
true
|
||||||
|
------
|
||||||
|
t
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
select to_tsvector('simple', 'x y q') @@ '(x | !y) <-> y <-> q' AS "true";
|
||||||
|
true
|
||||||
|
------
|
||||||
|
t
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
select to_tsvector('simple', 'x y q') @@ '(x | !!z) <-> y <-> q' AS "true";
|
||||||
|
true
|
||||||
|
------
|
||||||
|
t
|
||||||
|
(1 row)
|
||||||
|
|
||||||
select to_tsvector('simple', 'x y q y') @@ '!x <-> y' AS "true";
|
select to_tsvector('simple', 'x y q y') @@ '!x <-> y' AS "true";
|
||||||
true
|
true
|
||||||
------
|
------
|
||||||
t
|
t
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
|
select to_tsvector('simple', 'x y q y') @@ '!x <-> !y' AS "true";
|
||||||
|
true
|
||||||
|
------
|
||||||
|
t
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
select to_tsvector('simple', 'x y q y') @@ '!x <-> !!y' AS "true";
|
||||||
|
true
|
||||||
|
------
|
||||||
|
t
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
select to_tsvector('simple', 'x y q y') @@ '!(x <-> y)' AS "false";
|
||||||
|
false
|
||||||
|
-------
|
||||||
|
f
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
select to_tsvector('simple', 'x y q y') @@ '!(x <2> y)' AS "true";
|
||||||
|
true
|
||||||
|
------
|
||||||
|
t
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
select strip(to_tsvector('simple', 'x y q y')) @@ '!x <-> y' AS "false";
|
||||||
|
false
|
||||||
|
-------
|
||||||
|
f
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
select strip(to_tsvector('simple', 'x y q y')) @@ '!x <-> !y' AS "false";
|
||||||
|
false
|
||||||
|
-------
|
||||||
|
f
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
select strip(to_tsvector('simple', 'x y q y')) @@ '!x <-> !!y' AS "false";
|
||||||
|
false
|
||||||
|
-------
|
||||||
|
f
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
select strip(to_tsvector('simple', 'x y q y')) @@ '!(x <-> y)' AS "true";
|
||||||
|
true
|
||||||
|
------
|
||||||
|
t
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
select strip(to_tsvector('simple', 'x y q y')) @@ '!(x <2> y)' AS "true";
|
||||||
|
true
|
||||||
|
------
|
||||||
|
t
|
||||||
|
(1 row)
|
||||||
|
|
||||||
select to_tsvector('simple', 'x y q y') @@ '!foo' AS "true";
|
select to_tsvector('simple', 'x y q y') @@ '!foo' AS "true";
|
||||||
true
|
true
|
||||||
------
|
------
|
||||||
|
@ -51,6 +51,16 @@ SELECT count(*) FROM test_tsvector WHERE a @@ 'w:*|q:*';
|
|||||||
SELECT count(*) FROM test_tsvector WHERE a @@ any ('{wr,qh}');
|
SELECT count(*) FROM test_tsvector WHERE a @@ any ('{wr,qh}');
|
||||||
SELECT count(*) FROM test_tsvector WHERE a @@ 'no_such_lexeme';
|
SELECT count(*) FROM test_tsvector WHERE a @@ 'no_such_lexeme';
|
||||||
SELECT count(*) FROM test_tsvector WHERE a @@ '!no_such_lexeme';
|
SELECT count(*) FROM test_tsvector WHERE a @@ '!no_such_lexeme';
|
||||||
|
SELECT count(*) FROM test_tsvector WHERE a @@ 'pl <-> yh';
|
||||||
|
SELECT count(*) FROM test_tsvector WHERE a @@ 'yh <-> pl';
|
||||||
|
SELECT count(*) FROM test_tsvector WHERE a @@ 'qe <2> qt';
|
||||||
|
SELECT count(*) FROM test_tsvector WHERE a @@ '!pl <-> yh';
|
||||||
|
SELECT count(*) FROM test_tsvector WHERE a @@ '!pl <-> !yh';
|
||||||
|
SELECT count(*) FROM test_tsvector WHERE a @@ '!yh <-> pl';
|
||||||
|
SELECT count(*) FROM test_tsvector WHERE a @@ '!qe <2> qt';
|
||||||
|
SELECT count(*) FROM test_tsvector WHERE a @@ '!(pl <-> yh)';
|
||||||
|
SELECT count(*) FROM test_tsvector WHERE a @@ '!(yh <-> pl)';
|
||||||
|
SELECT count(*) FROM test_tsvector WHERE a @@ '!(qe <2> qt)';
|
||||||
|
|
||||||
create index wowidx on test_tsvector using gist (a);
|
create index wowidx on test_tsvector using gist (a);
|
||||||
|
|
||||||
@ -70,6 +80,16 @@ SELECT count(*) FROM test_tsvector WHERE a @@ 'w:*|q:*';
|
|||||||
SELECT count(*) FROM test_tsvector WHERE a @@ any ('{wr,qh}');
|
SELECT count(*) FROM test_tsvector WHERE a @@ any ('{wr,qh}');
|
||||||
SELECT count(*) FROM test_tsvector WHERE a @@ 'no_such_lexeme';
|
SELECT count(*) FROM test_tsvector WHERE a @@ 'no_such_lexeme';
|
||||||
SELECT count(*) FROM test_tsvector WHERE a @@ '!no_such_lexeme';
|
SELECT count(*) FROM test_tsvector WHERE a @@ '!no_such_lexeme';
|
||||||
|
SELECT count(*) FROM test_tsvector WHERE a @@ 'pl <-> yh';
|
||||||
|
SELECT count(*) FROM test_tsvector WHERE a @@ 'yh <-> pl';
|
||||||
|
SELECT count(*) FROM test_tsvector WHERE a @@ 'qe <2> qt';
|
||||||
|
SELECT count(*) FROM test_tsvector WHERE a @@ '!pl <-> yh';
|
||||||
|
SELECT count(*) FROM test_tsvector WHERE a @@ '!pl <-> !yh';
|
||||||
|
SELECT count(*) FROM test_tsvector WHERE a @@ '!yh <-> pl';
|
||||||
|
SELECT count(*) FROM test_tsvector WHERE a @@ '!qe <2> qt';
|
||||||
|
SELECT count(*) FROM test_tsvector WHERE a @@ '!(pl <-> yh)';
|
||||||
|
SELECT count(*) FROM test_tsvector WHERE a @@ '!(yh <-> pl)';
|
||||||
|
SELECT count(*) FROM test_tsvector WHERE a @@ '!(qe <2> qt)';
|
||||||
|
|
||||||
SET enable_indexscan=OFF;
|
SET enable_indexscan=OFF;
|
||||||
SET enable_bitmapscan=ON;
|
SET enable_bitmapscan=ON;
|
||||||
@ -86,6 +106,16 @@ SELECT count(*) FROM test_tsvector WHERE a @@ 'w:*|q:*';
|
|||||||
SELECT count(*) FROM test_tsvector WHERE a @@ any ('{wr,qh}');
|
SELECT count(*) FROM test_tsvector WHERE a @@ any ('{wr,qh}');
|
||||||
SELECT count(*) FROM test_tsvector WHERE a @@ 'no_such_lexeme';
|
SELECT count(*) FROM test_tsvector WHERE a @@ 'no_such_lexeme';
|
||||||
SELECT count(*) FROM test_tsvector WHERE a @@ '!no_such_lexeme';
|
SELECT count(*) FROM test_tsvector WHERE a @@ '!no_such_lexeme';
|
||||||
|
SELECT count(*) FROM test_tsvector WHERE a @@ 'pl <-> yh';
|
||||||
|
SELECT count(*) FROM test_tsvector WHERE a @@ 'yh <-> pl';
|
||||||
|
SELECT count(*) FROM test_tsvector WHERE a @@ 'qe <2> qt';
|
||||||
|
SELECT count(*) FROM test_tsvector WHERE a @@ '!pl <-> yh';
|
||||||
|
SELECT count(*) FROM test_tsvector WHERE a @@ '!pl <-> !yh';
|
||||||
|
SELECT count(*) FROM test_tsvector WHERE a @@ '!yh <-> pl';
|
||||||
|
SELECT count(*) FROM test_tsvector WHERE a @@ '!qe <2> qt';
|
||||||
|
SELECT count(*) FROM test_tsvector WHERE a @@ '!(pl <-> yh)';
|
||||||
|
SELECT count(*) FROM test_tsvector WHERE a @@ '!(yh <-> pl)';
|
||||||
|
SELECT count(*) FROM test_tsvector WHERE a @@ '!(qe <2> qt)';
|
||||||
|
|
||||||
RESET enable_seqscan;
|
RESET enable_seqscan;
|
||||||
RESET enable_indexscan;
|
RESET enable_indexscan;
|
||||||
@ -110,6 +140,16 @@ SELECT count(*) FROM test_tsvector WHERE a @@ 'w:*|q:*';
|
|||||||
SELECT count(*) FROM test_tsvector WHERE a @@ any ('{wr,qh}');
|
SELECT count(*) FROM test_tsvector WHERE a @@ any ('{wr,qh}');
|
||||||
SELECT count(*) FROM test_tsvector WHERE a @@ 'no_such_lexeme';
|
SELECT count(*) FROM test_tsvector WHERE a @@ 'no_such_lexeme';
|
||||||
SELECT count(*) FROM test_tsvector WHERE a @@ '!no_such_lexeme';
|
SELECT count(*) FROM test_tsvector WHERE a @@ '!no_such_lexeme';
|
||||||
|
SELECT count(*) FROM test_tsvector WHERE a @@ 'pl <-> yh';
|
||||||
|
SELECT count(*) FROM test_tsvector WHERE a @@ 'yh <-> pl';
|
||||||
|
SELECT count(*) FROM test_tsvector WHERE a @@ 'qe <2> qt';
|
||||||
|
SELECT count(*) FROM test_tsvector WHERE a @@ '!pl <-> yh';
|
||||||
|
SELECT count(*) FROM test_tsvector WHERE a @@ '!pl <-> !yh';
|
||||||
|
SELECT count(*) FROM test_tsvector WHERE a @@ '!yh <-> pl';
|
||||||
|
SELECT count(*) FROM test_tsvector WHERE a @@ '!qe <2> qt';
|
||||||
|
SELECT count(*) FROM test_tsvector WHERE a @@ '!(pl <-> yh)';
|
||||||
|
SELECT count(*) FROM test_tsvector WHERE a @@ '!(yh <-> pl)';
|
||||||
|
SELECT count(*) FROM test_tsvector WHERE a @@ '!(qe <2> qt)';
|
||||||
|
|
||||||
RESET enable_seqscan;
|
RESET enable_seqscan;
|
||||||
|
|
||||||
|
@ -144,7 +144,20 @@ select to_tsvector('simple', 'y y q') @@ '(x | y <-> !z) <-> q' AS "true";
|
|||||||
select to_tsvector('simple', 'x q') @@ '(x | y <-> !z) <-> q' AS "true";
|
select to_tsvector('simple', 'x q') @@ '(x | y <-> !z) <-> q' AS "true";
|
||||||
select to_tsvector('simple', 'x q') @@ '(!x | y <-> z) <-> q' AS "false";
|
select to_tsvector('simple', 'x q') @@ '(!x | y <-> z) <-> q' AS "false";
|
||||||
select to_tsvector('simple', 'z q') @@ '(!x | y <-> z) <-> q' AS "true";
|
select to_tsvector('simple', 'z q') @@ '(!x | y <-> z) <-> q' AS "true";
|
||||||
|
select to_tsvector('simple', 'x y q') @@ '(!x | y) <-> y <-> q' AS "false";
|
||||||
|
select to_tsvector('simple', 'x y q') @@ '(!x | !y) <-> y <-> q' AS "true";
|
||||||
|
select to_tsvector('simple', 'x y q') @@ '(x | !y) <-> y <-> q' AS "true";
|
||||||
|
select to_tsvector('simple', 'x y q') @@ '(x | !!z) <-> y <-> q' AS "true";
|
||||||
select to_tsvector('simple', 'x y q y') @@ '!x <-> y' AS "true";
|
select to_tsvector('simple', 'x y q y') @@ '!x <-> y' AS "true";
|
||||||
|
select to_tsvector('simple', 'x y q y') @@ '!x <-> !y' AS "true";
|
||||||
|
select to_tsvector('simple', 'x y q y') @@ '!x <-> !!y' AS "true";
|
||||||
|
select to_tsvector('simple', 'x y q y') @@ '!(x <-> y)' AS "false";
|
||||||
|
select to_tsvector('simple', 'x y q y') @@ '!(x <2> y)' AS "true";
|
||||||
|
select strip(to_tsvector('simple', 'x y q y')) @@ '!x <-> y' AS "false";
|
||||||
|
select strip(to_tsvector('simple', 'x y q y')) @@ '!x <-> !y' AS "false";
|
||||||
|
select strip(to_tsvector('simple', 'x y q y')) @@ '!x <-> !!y' AS "false";
|
||||||
|
select strip(to_tsvector('simple', 'x y q y')) @@ '!(x <-> y)' AS "true";
|
||||||
|
select strip(to_tsvector('simple', 'x y q y')) @@ '!(x <2> y)' AS "true";
|
||||||
select to_tsvector('simple', 'x y q y') @@ '!foo' AS "true";
|
select to_tsvector('simple', 'x y q y') @@ '!foo' AS "true";
|
||||||
select to_tsvector('simple', '') @@ '!foo' AS "true";
|
select to_tsvector('simple', '') @@ '!foo' AS "true";
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user