From: dan Date: Sat, 5 Dec 2009 11:37:19 +0000 (+0000) Subject: Fix some problems with FTS3 and 3-way NEAR queries. X-Git-Tag: version-3.7.2~747 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=6e053f9c23a301e5180f857799ddc914c2b29e01;p=thirdparty%2Fsqlite.git Fix some problems with FTS3 and 3-way NEAR queries. FossilOrigin-Name: 23dc6fb5b28712d1ba18dc7ddb3f2ef3b469d611 --- diff --git a/ext/fts3/fts3.c b/ext/fts3/fts3.c index 0ca6d41503..d41f10ea30 100644 --- a/ext/fts3/fts3.c +++ b/ext/fts3/fts3.c @@ -1064,6 +1064,54 @@ static void fts3ColumnlistCopy(char **pp, char **ppPoslist){ *ppPoslist = pEnd; } +/* +** Value used to signify the end of an offset-list. This is safe because +** it is not possible to have a document with 2^31 terms. +*/ +#define OFFSET_LIST_END 0x7fffffff + +/* +** This function is used to help parse offset-lists. When this function is +** called, *pp may point to the start of the next varint in the offset-list +** being parsed, or it may point to 1 byte past the end of the offset-list +** (in which case **pp will be 0x00 or 0x01). +** +** If *pp points past the end of the current offset list, set *pi to +** OFFSET_LIST_END and return. Otherwise, read the next varint from *pp, +** increment the current value of *pi by the value read, and set *pp to +** point to the next value before returning. +*/ +static void fts3ReadNextPos( + char **pp, /* IN/OUT: Pointer into offset-list buffer */ + sqlite3_int64 *pi /* IN/OUT: Value read from offset-list */ +){ + if( **pp&0xFE ){ + fts3GetDeltaVarint(pp, pi); + *pi -= 2; + }else{ + *pi = OFFSET_LIST_END; + } +} + +/* +** If parameter iCol is not 0, write an 0x01 byte followed by the value of +** iCol encoded as a varint to *pp. +** +** Set *pp to point to the byte just after the last byte written before +** returning (do not modify it if iCol==0). Return the total number of bytes +** written (0 if iCol==0). +*/ +static int fts3PutColNumber(char **pp, int iCol){ + int n = 0; /* Number of bytes written */ + if( iCol ){ + char *p = *pp; /* Output pointer */ + n = 1 + sqlite3Fts3PutVarint(&p[1], iCol); + *p = 0x01; + *pp = &p[n]; + } + return n; +} + /* ** */ @@ -1086,42 +1134,37 @@ static void fts3PoslistMerge( sqlite3_int64 i1 = 0; sqlite3_int64 i2 = 0; sqlite3_int64 iPrev = 0; - if( iCol1!=0 ){ - int n; - *p++ = 0x01; - n = sqlite3Fts3PutVarint(p, iCol1); - p += n; - p1 += 1 + n; - p2 += 1 + n; - } - while( (*p1&0xFE) || (*p2&0xFE) ){ + int n = fts3PutColNumber(&p, iCol1); + p1 += n; + p2 += n; + + /* At this point, both p1 and p2 point to the start of offset-lists. + ** An offset-list is a list of non-negative delta-encoded varints, each + ** incremented by 2 before being stored. Each list is terminated by a 0 + ** or 1 value (0x00 or 0x01). The following block merges the two lists + ** and writes the results to buffer p. p is left pointing to the byte + ** after the list written. No terminator (0x00 or 0x01) is written to + ** the output. + */ + fts3GetDeltaVarint(&p1, &i1); + fts3GetDeltaVarint(&p2, &i2); + do { + fts3PutDeltaVarint(&p, &iPrev, (i1