/*
* 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)
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;
/*
* 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 */
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;
#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 Datum tsvector_update_trigger(PG_FUNCTION_ARGS, bool config_column);
+
/*
* Order: haspos, len, word, for all positions (pos, weight)
* Loffset and Roffset should not be negative, else we risk trying to output
* negative positions, which won't fit into WordEntryPos.
*
- * Returns true if any positions were emitted to *data; or if data is NULL,
- * returns true if any positions would have been emitted.
+ * The result is boolean (TS_YES or TS_NO), but for the caller's convenience
+ * 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_R_ONLY 0x02 /* emit positions appearing only in R */
#define TSPO_BOTH 0x04 /* emit positions appearing in both L&R */
-static bool
+static TSTernaryValue
TS_phrase_output(ExecPhraseData *data,
ExecPhraseData *Ldata,
ExecPhraseData *Rdata,
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.
*/
- return true;
+ return TS_YES;
}
}
}
{
/* Let's assert we didn't overrun the array */
Assert(data->npos <= max_npos);
- return true;
+ return TS_YES;
}
- return false;
+ return TS_NO;
}
/*
* 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
- * "true" (successful match, or possible match), are:
+ * TS_YES (successful match), are:
*
* npos > 0, negate = false:
* query is matched at specified position(s) (and only those positions)
* npos > 0, negate = true:
* 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:
* 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
* lexemes, less one. Hence, "width" is zero for simple one-lexeme matches,
* the starts. (This unintuitive rule is needed to avoid possibly generating
* 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
* "width" output in such cases is undefined.
*/
-static bool
+static TSTernaryValue
TS_phrase_execute(QueryItem *curitem, void *arg, uint32 flags,
TSExecuteCallback chkcond,
ExecPhraseData *data)
{
ExecPhraseData Ldata,
Rdata;
- bool lmatch,
+ TSTernaryValue lmatch,
rmatch;
int Loffset,
Roffset,
check_stack_depth();
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)
{
case OP_NOT:
/*
- * Because a "true" result with no specific positions is taken as
- * uncertain, we need no special care here for !TS_EXEC_CALC_NOT.
- * 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.
+ * 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)
- {
- /* 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" */
+ /* without CALC_NOT, report NOT as "match everywhere" */
Assert(data->npos == 0 && !data->negate);
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_AND:
memset(&Ldata, 0, sizeof(Ldata));
memset(&Rdata, 0, sizeof(Rdata));
- if (!TS_phrase_execute(curitem + curitem->qoperator.left,
- arg, flags, chkcond, &Ldata))
- return false;
+ lmatch = TS_phrase_execute(curitem + curitem->qoperator.left,
+ arg, flags, chkcond, &Ldata);
+ if (lmatch == TS_NO)
+ return TS_NO;
- if (!TS_phrase_execute(curitem + 1,
- arg, flags, chkcond, &Rdata))
- return false;
+ rmatch = TS_phrase_execute(curitem + 1,
+ arg, flags, chkcond, &Rdata);
+ if (rmatch == TS_NO)
+ return TS_NO;
/*
* If either operand has no position information, then we can't
- * return position data, only a "possible match" result. "Possible
- * match" answers are only wanted when TS_EXEC_PHRASE_NO_POS flag
- * is set, otherwise return false.
+ * return reliable position data, only a MAYBE result.
*/
- if ((Ldata.npos == 0 && !Ldata.negate) ||
- (Rdata.npos == 0 && !Rdata.negate))
- return (flags & TS_EXEC_PHRASE_NO_POS) ? true : false;
+ if (lmatch == TS_MAYBE || rmatch == TS_MAYBE)
+ return TS_MAYBE;
if (curitem->qoperator.oper == OP_PHRASE)
{
Ldata.npos + Rdata.npos);
if (data)
data->negate = true;
- return true;
+ return TS_YES;
}
else if (Ldata.negate)
{
rmatch = TS_phrase_execute(curitem + 1,
arg, flags, chkcond, &Rdata);
- if (!lmatch && !rmatch)
- return false;
+ if (lmatch == TS_NO && rmatch == TS_NO)
+ return TS_NO;
/*
- * If a valid operand has no position information, then we can't
- * return position data, only a "possible match" result. "Possible
- * match" answers are only wanted when TS_EXEC_PHRASE_NO_POS flag
- * is set, otherwise return false.
+ * If either operand has no position information, then we can't
+ * return reliable position data, only a MAYBE result.
*/
- if ((lmatch && Ldata.npos == 0 && !Ldata.negate) ||
- (rmatch && Rdata.npos == 0 && !Rdata.negate))
- return (flags & TS_EXEC_PHRASE_NO_POS) ? true : false;
+ if (lmatch == TS_MAYBE || rmatch == TS_MAYBE)
+ return TS_MAYBE;
/*
* Cope with undefined output width from failed submatch. (This
* takes less code than trying to ensure that all failure returns
* set data->width to zero.)
*/
- if (!lmatch)
+ if (lmatch == TS_NO)
Ldata.width = 0;
- if (!rmatch)
+ if (rmatch == TS_NO)
Rdata.width = 0;
/*
Loffset, Roffset,
Min(Ldata.npos, Rdata.npos));
data->negate = true;
- return true;
+ return TS_YES;
}
else if (Ldata.negate)
{
Loffset, Roffset,
Ldata.npos);
data->negate = true;
- return true;
+ return TS_YES;
}
else if (Rdata.negate)
{
Loffset, Roffset,
Rdata.npos);
data->negate = true;
- return true;
+ return TS_YES;
}
else
{
}
/* not reachable, but keep compiler quiet */
- return false;
+ return TS_NO;
}
* arg: opaque value to pass through to callback function
* flags: bitmask of flag bits shown in ts_utils.h
* 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
TS_execute(QueryItem *curitem, void *arg, uint32 flags,
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 */
check_stack_depth();
if (curitem->type == QI_VAL)
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)
{
case OP_NOT:
- if (flags & TS_EXEC_CALC_NOT)
- return !TS_execute(curitem + 1, arg, flags, chkcond);
- else
- return true;
+ if (!(flags & TS_EXEC_CALC_NOT))
+ return TS_YES;
+ switch (TS_execute_recurse(curitem + 1, arg, flags, chkcond))
+ {
+ case TS_NO:
+ return TS_YES;
+ case TS_YES:
+ return TS_NO;
+ case TS_MAYBE:
+ return TS_MAYBE;
+ }
+ break;
case OP_AND:
- if (TS_execute(curitem + curitem->qoperator.left, arg, flags, chkcond))
- return TS_execute(curitem + 1, arg, flags, chkcond);
- else
- return false;
+ lmatch = TS_execute_recurse(curitem + curitem->qoperator.left, arg,
+ flags, chkcond);
+ if (lmatch == TS_NO)
+ 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:
- if (TS_execute(curitem + curitem->qoperator.left, arg, flags, chkcond))
- return true;
- else
- return TS_execute(curitem + 1, arg, flags, chkcond);
+ lmatch = TS_execute_recurse(curitem + curitem->qoperator.left, arg,
+ flags, chkcond);
+ if (lmatch == TS_YES)
+ 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:
- 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:
elog(ERROR, "unrecognized operator: %d", curitem->qoperator.oper);
}
/* not reachable, but keep compiler quiet */
- return false;
+ return TS_NO;
}
/*
\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 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 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 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 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 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 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 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 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 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 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 hv fu ca q8 mt la r3 pl yh to sy yh tv x4 tg yp ov wn ze sp
-\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 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 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 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 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 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 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 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 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 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: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: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: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: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: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: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: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: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: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: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: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: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: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: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: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: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: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: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: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
508
(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);
SET enable_seqscan=OFF;
SET enable_indexscan=ON;
508
(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_bitmapscan=ON;
explain (costs off) SELECT count(*) FROM test_tsvector WHERE a @@ 'wr|qh';
508
(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_indexscan;
RESET enable_bitmapscan;
508
(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;
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;
------+------+--------
qq | 108 | 108
qt | 102 | 102
- qe | 100 | 100
- qh | 98 | 98
+ qe | 100 | 101
+ qh | 98 | 99
qw | 98 | 98
qa | 97 | 97
ql | 94 | 94
qs | 94 | 94
+ qr | 92 | 93
qi | 92 | 92
- qr | 92 | 92
(10 rows)
SELECT * FROM ts_stat('SELECT a FROM test_tsvector', 'AB') ORDER BY ndoc DESC, nentry DESC, word;
t
(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";
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 "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";
true
------
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 @@ '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);
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 @@ '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_bitmapscan=ON;
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 @@ '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_indexscan;
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 @@ '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;
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', '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 "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', '') @@ '!foo' AS "true";