diff options
author | Teodor Sigaev <teodor@sigaev.ru> | 2016-06-27 20:41:00 +0300 |
---|---|---|
committer | Teodor Sigaev <teodor@sigaev.ru> | 2016-06-27 20:41:00 +0300 |
commit | 028350f619f7688e0453fcd2c4b25abe9ba30fa7 (patch) | |
tree | 5381d262fe10bf48a855ba92f50265a7f1c8a94c /src/backend/utils/adt/tsvector_op.c | |
parent | f1993038a4f0ce5fbeb7b562b2acd571bf6b567b (diff) | |
download | postgresql-028350f619f7688e0453fcd2c4b25abe9ba30fa7.tar.gz postgresql-028350f619f7688e0453fcd2c4b25abe9ba30fa7.zip |
Make exact distance match for FTS phrase operator
Phrase operator now requires exact distance betweens lexems instead of
less-or-equal.
Per discussion c19fcfec308e6ccd952cdde9e648b505@mail.gmail.com
Diffstat (limited to 'src/backend/utils/adt/tsvector_op.c')
-rw-r--r-- | src/backend/utils/adt/tsvector_op.c | 67 |
1 files changed, 38 insertions, 29 deletions
diff --git a/src/backend/utils/adt/tsvector_op.c b/src/backend/utils/adt/tsvector_op.c index 6117ba9b3e4..04718829a0b 100644 --- a/src/backend/utils/adt/tsvector_op.c +++ b/src/backend/utils/adt/tsvector_op.c @@ -1375,6 +1375,7 @@ TS_phrase_execute(QueryItem *curitem, ExecPhraseData Ldata = {0, false, NULL}, Rdata = {0, false, NULL}; WordEntryPos *Lpos, + *LposStart, *Rpos, *pos_iter = NULL; @@ -1416,52 +1417,60 @@ TS_phrase_execute(QueryItem *curitem, pos_iter = data->pos; } - Lpos = Ldata.pos; - Rpos = Rdata.pos; - /* * Find matches by distance, WEP_GETPOS() is needed because * ExecPhraseData->data can point to the tsvector's WordEntryPosVector */ + Rpos = Rdata.pos; + LposStart = Ldata.pos; while (Rpos < Rdata.pos + Rdata.npos) { + /* + * We need to check all possible distances, so reset Lpos + * to guranteed not yet satisfied position. + */ + Lpos = LposStart; while (Lpos < Ldata.pos + Ldata.npos) { - if (WEP_GETPOS(*Lpos) <= WEP_GETPOS(*Rpos)) + if (WEP_GETPOS(*Rpos) - WEP_GETPOS(*Lpos) == + curitem->qoperator.distance) { - /* - * Lpos is behind the Rpos, so we have to check the - * distance condition - */ - if (WEP_GETPOS(*Rpos) - WEP_GETPOS(*Lpos) <= curitem->qoperator.distance) + /* MATCH! */ + if (data) { - /* MATCH! */ - if (data) - { - *pos_iter = WEP_GETPOS(*Rpos); - pos_iter++; - - break; /* We need to build a unique result - * array, so go to the next Rpos */ - } - else - { - /* - * We are in the root of the phrase tree and hence - * we don't have to store the resulting positions - */ - return true; - } + /* Store position for upper phrase operator */ + *pos_iter = WEP_GETPOS(*Rpos); + pos_iter++; + + /* + * Set left start position to next, because current one + * could not satisfy distance for any other right + * position + */ + LposStart = Lpos + 1; + break; + } + else + { + /* + * We are in the root of the phrase tree and hence + * we don't have to store the resulting positions + */ + return true; } + } - else + else if (WEP_GETPOS(*Rpos) <= WEP_GETPOS(*Lpos) || + WEP_GETPOS(*Rpos) - WEP_GETPOS(*Lpos) < + curitem->qoperator.distance) { /* - * Go to the next Rpos, because Lpos is ahead of the - * current Rpos + * Go to the next Rpos, because Lpos is ahead or on less + * distance than required by current operator */ break; + } Lpos++; |