diff --git a/src/backend/utils/adt/tsginidx.c b/src/backend/utils/adt/tsginidx.c index 00e32b2570..ade1514d57 100644 --- a/src/backend/utils/adt/tsginidx.c +++ b/src/backend/utils/adt/tsginidx.c @@ -210,6 +210,11 @@ checkcondition_gin(void *checkval, QueryOperand *val, ExecPhraseData *data) /* * Evaluate tsquery boolean expression using ternary logic. + * + * Note: the reason we can't use TS_execute() for this is that its API + * for the checkcondition callback doesn't allow a MAYBE result to be + * returned, but we might have MAYBEs in the gcv->check array. + * Perhaps we should change that API. */ static GinTernaryValue TS_execute_ternary(GinChkVal *gcv, QueryItem *curitem, bool in_phrase) @@ -230,9 +235,19 @@ TS_execute_ternary(GinChkVal *gcv, QueryItem *curitem, bool in_phrase) switch (curitem->qoperator.oper) { case OP_NOT: - /* In phrase search, always return MAYBE since we lack positions */ + + /* + * Below a phrase search, force NOT's result to MAYBE. We cannot + * invert a TRUE result from the subexpression to FALSE, since + * TRUE only says that the subexpression matches somewhere, not + * that it matches everywhere, so there might be positions where + * the NOT will match. We could invert FALSE to TRUE, but there's + * little point in distinguishing TRUE from MAYBE, since a recheck + * will have been forced already. + */ if (in_phrase) return GIN_MAYBE; + result = TS_execute_ternary(gcv, curitem + 1, in_phrase); if (result == GIN_MAYBE) return result; @@ -242,7 +257,8 @@ TS_execute_ternary(GinChkVal *gcv, QueryItem *curitem, bool in_phrase) /* * GIN doesn't contain any information about positions, so treat - * OP_PHRASE as OP_AND with recheck requirement + * OP_PHRASE as OP_AND with recheck requirement, and always + * reporting MAYBE not TRUE. */ *(gcv->need_recheck) = true; /* Pass down in_phrase == true in case there's a NOT below */ @@ -258,7 +274,8 @@ TS_execute_ternary(GinChkVal *gcv, QueryItem *curitem, bool in_phrase) val2 = TS_execute_ternary(gcv, curitem + 1, in_phrase); if (val2 == GIN_FALSE) return GIN_FALSE; - if (val1 == GIN_TRUE && val2 == GIN_TRUE) + if (val1 == GIN_TRUE && val2 == GIN_TRUE && + curitem->qoperator.oper != OP_PHRASE) return GIN_TRUE; else return GIN_MAYBE; diff --git a/src/backend/utils/adt/tsvector_op.c b/src/backend/utils/adt/tsvector_op.c index 258fe47a24..3cd1dfbb6c 100644 --- a/src/backend/utils/adt/tsvector_op.c +++ b/src/backend/utils/adt/tsvector_op.c @@ -67,8 +67,21 @@ typedef struct #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) @@ -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 * 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, @@ -1513,10 +1529,10 @@ TS_phrase_output(ExecPhraseData *data, 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; } } } @@ -1525,9 +1541,9 @@ TS_phrase_output(ExecPhraseData *data, { /* Let's assert we didn't overrun the array */ 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. * * 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, @@ -1564,18 +1579,22 @@ TS_phrase_output(ExecPhraseData *data, * 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, @@ -1585,67 +1604,80 @@ TS_phrase_execute(QueryItem *curitem, void *arg, uint32 flags, 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) { @@ -1681,7 +1713,7 @@ TS_phrase_execute(QueryItem *curitem, void *arg, uint32 flags, Ldata.npos + Rdata.npos); if (data) data->negate = true; - return true; + return TS_YES; } else if (Ldata.negate) { @@ -1717,27 +1749,24 @@ TS_phrase_execute(QueryItem *curitem, void *arg, uint32 flags, 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; /* @@ -1759,7 +1788,7 @@ TS_phrase_execute(QueryItem *curitem, void *arg, uint32 flags, Loffset, Roffset, Min(Ldata.npos, Rdata.npos)); data->negate = true; - return true; + return TS_YES; } else if (Ldata.negate) { @@ -1769,7 +1798,7 @@ TS_phrase_execute(QueryItem *curitem, void *arg, uint32 flags, Loffset, Roffset, Ldata.npos); data->negate = true; - return true; + return TS_YES; } else if (Rdata.negate) { @@ -1779,7 +1808,7 @@ TS_phrase_execute(QueryItem *curitem, void *arg, uint32 flags, Loffset, Roffset, Rdata.npos); data->negate = true; - return true; + return TS_YES; } else { @@ -1795,7 +1824,7 @@ TS_phrase_execute(QueryItem *curitem, void *arg, uint32 flags, } /* 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 * 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; } /* diff --git a/src/test/regress/data/tsearch.data b/src/test/regress/data/tsearch.data index 29a26f2428..a60f39b234 100644 --- a/src/test/regress/data/tsearch.data +++ b/src/test/regress/data/tsearch.data @@ -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 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 diff --git a/src/test/regress/expected/tsearch.out b/src/test/regress/expected/tsearch.out index 02e1b12b85..bbee01047d 100644 --- a/src/test/regress/expected/tsearch.out +++ b/src/test/regress/expected/tsearch.out @@ -116,6 +116,66 @@ SELECT count(*) FROM test_tsvector WHERE a @@ '!no_such_lexeme'; 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; @@ -188,6 +248,66 @@ SELECT count(*) FROM test_tsvector WHERE a @@ '!no_such_lexeme'; 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'; @@ -260,6 +380,66 @@ SELECT count(*) FROM test_tsvector WHERE a @@ '!no_such_lexeme'; 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; @@ -337,6 +517,66 @@ SELECT count(*) FROM test_tsvector WHERE a @@ '!no_such_lexeme'; 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; @@ -344,14 +584,14 @@ SELECT * FROM ts_stat('SELECT a FROM test_tsvector') ORDER BY ndoc DESC, nentry ------+------+-------- 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; diff --git a/src/test/regress/expected/tstypes.out b/src/test/regress/expected/tstypes.out index 6272e70e09..8ff0d0496e 100644 --- a/src/test/regress/expected/tstypes.out +++ b/src/test/regress/expected/tstypes.out @@ -767,12 +767,90 @@ select to_tsvector('simple', 'z q') @@ '(!x | y <-> z) <-> q' AS "true"; 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 ------ diff --git a/src/test/regress/sql/tsearch.sql b/src/test/regress/sql/tsearch.sql index 6cadffd985..677fb1efaa 100644 --- a/src/test/regress/sql/tsearch.sql +++ b/src/test/regress/sql/tsearch.sql @@ -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 @@ '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); @@ -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 @@ '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; @@ -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 @@ '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; @@ -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 @@ '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; diff --git a/src/test/regress/sql/tstypes.sql b/src/test/regress/sql/tstypes.sql index 0a40ec9350..4c60f602e5 100644 --- a/src/test/regress/sql/tstypes.sql +++ b/src/test/regress/sql/tstypes.sql @@ -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 "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";