Fossil SCM
Update SQLite to version 3.6.21 final.
Commit
9f654b99840423c091ac06e15f64da27e413954e
Parent
6f0df6c741887ef…
2 files changed
+151
-54
+1
-1
+151
-54
| --- src/sqlite3.c | ||
| +++ src/sqlite3.c | ||
| @@ -643,11 +643,11 @@ | ||
| 643 | 643 | ** |
| 644 | 644 | ** Requirements: [H10011] [H10014] |
| 645 | 645 | */ |
| 646 | 646 | #define SQLITE_VERSION "3.6.21" |
| 647 | 647 | #define SQLITE_VERSION_NUMBER 3006021 |
| 648 | -#define SQLITE_SOURCE_ID "2009-12-04 14:25:19 082b8da005128f47f63e95b6b702bf4517221b2a" | |
| 648 | +#define SQLITE_SOURCE_ID "2009-12-07 16:39:13 1ed88e9d01e9eda5cbc622e7614277f29bcc551c" | |
| 649 | 649 | |
| 650 | 650 | /* |
| 651 | 651 | ** CAPI3REF: Run-Time Library Version Numbers {H10020} <S60100> |
| 652 | 652 | ** KEYWORDS: sqlite3_version |
| 653 | 653 | ** |
| @@ -6755,13 +6755,23 @@ | ||
| 6755 | 6755 | ** Round down to the nearest multiple of 8 |
| 6756 | 6756 | */ |
| 6757 | 6757 | #define ROUNDDOWN8(x) ((x)&~7) |
| 6758 | 6758 | |
| 6759 | 6759 | /* |
| 6760 | -** Assert that the pointer X is aligned to an 8-byte boundary. | |
| 6760 | +** Assert that the pointer X is aligned to an 8-byte boundary. This | |
| 6761 | +** macro is used only within assert() to verify that the code gets | |
| 6762 | +** all alignment restrictions correct. | |
| 6763 | +** | |
| 6764 | +** Except, if SQLITE_4_BYTE_ALIGNED_MALLOC is defined, then the | |
| 6765 | +** underlying malloc() implemention might return us 4-byte aligned | |
| 6766 | +** pointers. In that case, only verify 4-byte alignment. | |
| 6761 | 6767 | */ |
| 6762 | -#define EIGHT_BYTE_ALIGNMENT(X) ((((char*)(X) - (char*)0)&7)==0) | |
| 6768 | +#ifdef SQLITE_4_BYTE_ALIGNED_MALLOC | |
| 6769 | +# define EIGHT_BYTE_ALIGNMENT(X) ((((char*)(X) - (char*)0)&3)==0) | |
| 6770 | +#else | |
| 6771 | +# define EIGHT_BYTE_ALIGNMENT(X) ((((char*)(X) - (char*)0)&7)==0) | |
| 6772 | +#endif | |
| 6763 | 6773 | |
| 6764 | 6774 | |
| 6765 | 6775 | /* |
| 6766 | 6776 | ** An instance of the following structure is used to store the busy-handler |
| 6767 | 6777 | ** callback for a given sqlite handle. |
| @@ -38775,18 +38785,20 @@ | ||
| 38775 | 38785 | u8 * const data = pPage->aData; /* Local cache of pPage->aData */ |
| 38776 | 38786 | int nFrag; /* Number of fragmented bytes on pPage */ |
| 38777 | 38787 | int top; /* First byte of cell content area */ |
| 38778 | 38788 | int gap; /* First byte of gap between cell pointers and cell content */ |
| 38779 | 38789 | int rc; /* Integer return code */ |
| 38790 | + int usableSize; /* Usable size of the page */ | |
| 38780 | 38791 | |
| 38781 | 38792 | assert( sqlite3PagerIswriteable(pPage->pDbPage) ); |
| 38782 | 38793 | assert( pPage->pBt ); |
| 38783 | 38794 | assert( sqlite3_mutex_held(pPage->pBt->mutex) ); |
| 38784 | 38795 | assert( nByte>=0 ); /* Minimum cell size is 4 */ |
| 38785 | 38796 | assert( pPage->nFree>=nByte ); |
| 38786 | 38797 | assert( pPage->nOverflow==0 ); |
| 38787 | - assert( nByte<pPage->pBt->usableSize-8 ); | |
| 38798 | + usableSize = pPage->pBt->usableSize; | |
| 38799 | + assert( nByte < usableSize-8 ); | |
| 38788 | 38800 | |
| 38789 | 38801 | nFrag = data[hdr+7]; |
| 38790 | 38802 | assert( pPage->cellOffset == hdr + 12 - 4*pPage->leaf ); |
| 38791 | 38803 | gap = pPage->cellOffset + 2*pPage->nCell; |
| 38792 | 38804 | top = get2byte(&data[hdr+5]); |
| @@ -38805,20 +38817,26 @@ | ||
| 38805 | 38817 | ** the request. The allocation is made from the first free slot in |
| 38806 | 38818 | ** the list that is large enough to accomadate it. |
| 38807 | 38819 | */ |
| 38808 | 38820 | int pc, addr; |
| 38809 | 38821 | for(addr=hdr+1; (pc = get2byte(&data[addr]))>0; addr=pc){ |
| 38810 | - int size = get2byte(&data[pc+2]); /* Size of free slot */ | |
| 38822 | + int size; /* Size of the free slot */ | |
| 38823 | + if( pc>usableSize-4 || pc<addr+4 ){ | |
| 38824 | + return SQLITE_CORRUPT_BKPT; | |
| 38825 | + } | |
| 38826 | + size = get2byte(&data[pc+2]); | |
| 38811 | 38827 | if( size>=nByte ){ |
| 38812 | 38828 | int x = size - nByte; |
| 38813 | 38829 | testcase( x==4 ); |
| 38814 | 38830 | testcase( x==3 ); |
| 38815 | 38831 | if( x<4 ){ |
| 38816 | 38832 | /* Remove the slot from the free-list. Update the number of |
| 38817 | 38833 | ** fragmented bytes within the page. */ |
| 38818 | 38834 | memcpy(&data[addr], &data[pc], 2); |
| 38819 | 38835 | data[hdr+7] = (u8)(nFrag + x); |
| 38836 | + }else if( size+pc > usableSize ){ | |
| 38837 | + return SQLITE_CORRUPT_BKPT; | |
| 38820 | 38838 | }else{ |
| 38821 | 38839 | /* The slot remains on the free-list. Reduce its size to account |
| 38822 | 38840 | ** for the portion used by the new allocation. */ |
| 38823 | 38841 | put2byte(&data[pc+2], x); |
| 38824 | 38842 | } |
| @@ -39238,11 +39256,10 @@ | ||
| 39238 | 39256 | ** Release a MemPage. This should be called once for each prior |
| 39239 | 39257 | ** call to btreeGetPage. |
| 39240 | 39258 | */ |
| 39241 | 39259 | static void releasePage(MemPage *pPage){ |
| 39242 | 39260 | if( pPage ){ |
| 39243 | - assert( pPage->nOverflow==0 || sqlite3PagerPageRefcount(pPage->pDbPage)>1 ); | |
| 39244 | 39261 | assert( pPage->aData ); |
| 39245 | 39262 | assert( pPage->pBt ); |
| 39246 | 39263 | assert( sqlite3PagerGetExtra(pPage->pDbPage) == (void*)pPage ); |
| 39247 | 39264 | assert( sqlite3PagerGetData(pPage->pDbPage)==pPage->aData ); |
| 39248 | 39265 | assert( sqlite3_mutex_held(pPage->pBt->mutex) ); |
| @@ -43212,11 +43229,11 @@ | ||
| 43212 | 43229 | BtShared * const pBt = pFrom->pBt; |
| 43213 | 43230 | u8 * const aFrom = pFrom->aData; |
| 43214 | 43231 | u8 * const aTo = pTo->aData; |
| 43215 | 43232 | int const iFromHdr = pFrom->hdrOffset; |
| 43216 | 43233 | int const iToHdr = ((pTo->pgno==1) ? 100 : 0); |
| 43217 | - TESTONLY(int rc;) | |
| 43234 | + int rc; | |
| 43218 | 43235 | int iData; |
| 43219 | 43236 | |
| 43220 | 43237 | |
| 43221 | 43238 | assert( pFrom->isInit ); |
| 43222 | 43239 | assert( pFrom->nFree>=iToHdr ); |
| @@ -43226,15 +43243,20 @@ | ||
| 43226 | 43243 | iData = get2byte(&aFrom[iFromHdr+5]); |
| 43227 | 43244 | memcpy(&aTo[iData], &aFrom[iData], pBt->usableSize-iData); |
| 43228 | 43245 | memcpy(&aTo[iToHdr], &aFrom[iFromHdr], pFrom->cellOffset + 2*pFrom->nCell); |
| 43229 | 43246 | |
| 43230 | 43247 | /* Reinitialize page pTo so that the contents of the MemPage structure |
| 43231 | - ** match the new data. The initialization of pTo "cannot" fail, as the | |
| 43232 | - ** data copied from pFrom is known to be valid. */ | |
| 43248 | + ** match the new data. The initialization of pTo can actually fail under | |
| 43249 | + ** fairly obscure circumstances, even though it is a copy of initialized | |
| 43250 | + ** page pFrom. | |
| 43251 | + */ | |
| 43233 | 43252 | pTo->isInit = 0; |
| 43234 | - TESTONLY(rc = ) btreeInitPage(pTo); | |
| 43235 | - assert( rc==SQLITE_OK ); | |
| 43253 | + rc = btreeInitPage(pTo); | |
| 43254 | + if( rc!=SQLITE_OK ){ | |
| 43255 | + *pRC = rc; | |
| 43256 | + return; | |
| 43257 | + } | |
| 43236 | 43258 | |
| 43237 | 43259 | /* If this is an auto-vacuum database, update the pointer-map entries |
| 43238 | 43260 | ** for any b-tree or overflow pages that pTo now contains the pointers to. |
| 43239 | 43261 | */ |
| 43240 | 43262 | if( ISAUTOVACUUM ){ |
| @@ -98918,21 +98940,21 @@ | ||
| 98918 | 98940 | int nCol = 0; |
| 98919 | 98941 | char *zCsr; |
| 98920 | 98942 | int nDb; |
| 98921 | 98943 | int nName; |
| 98922 | 98944 | |
| 98945 | + const char *zTokenizer = 0; /* Name of tokenizer to use */ | |
| 98946 | + sqlite3_tokenizer *pTokenizer = 0; /* Tokenizer for this table */ | |
| 98947 | + | |
| 98923 | 98948 | #ifdef SQLITE_TEST |
| 98924 | - char *zTestParam = 0; | |
| 98949 | + const char *zTestParam = 0; | |
| 98925 | 98950 | if( strncmp(argv[argc-1], "test:", 5)==0 ){ |
| 98926 | 98951 | zTestParam = argv[argc-1]; |
| 98927 | 98952 | argc--; |
| 98928 | 98953 | } |
| 98929 | 98954 | #endif |
| 98930 | 98955 | |
| 98931 | - const char *zTokenizer = 0; /* Name of tokenizer to use */ | |
| 98932 | - sqlite3_tokenizer *pTokenizer = 0; /* Tokenizer for this table */ | |
| 98933 | - | |
| 98934 | 98956 | nDb = (int)strlen(argv[1]) + 1; |
| 98935 | 98957 | nName = (int)strlen(argv[2]) + 1; |
| 98936 | 98958 | for(i=3; i<argc; i++){ |
| 98937 | 98959 | char const *z = argv[i]; |
| 98938 | 98960 | rc = sqlite3Fts3InitTokenizer(pHash, z, &pTokenizer, &zTokenizer, pzErr); |
| @@ -99324,10 +99346,12 @@ | ||
| 99324 | 99346 | } |
| 99325 | 99347 | |
| 99326 | 99348 | static void fts3ColumnlistCopy(char **pp, char **ppPoslist){ |
| 99327 | 99349 | char *pEnd = *ppPoslist; |
| 99328 | 99350 | char c = 0; |
| 99351 | + | |
| 99352 | + /* A column-list is terminated by either a 0x01 or 0x00. */ | |
| 99329 | 99353 | while( 0xFE & (*pEnd | c) ) c = *pEnd++ & 0x80; |
| 99330 | 99354 | if( pp ){ |
| 99331 | 99355 | int n = (int)(pEnd - *ppPoslist); |
| 99332 | 99356 | char *p = *pp; |
| 99333 | 99357 | memcpy(p, *ppPoslist, n); |
| @@ -99334,10 +99358,58 @@ | ||
| 99334 | 99358 | p += n; |
| 99335 | 99359 | *pp = p; |
| 99336 | 99360 | } |
| 99337 | 99361 | *ppPoslist = pEnd; |
| 99338 | 99362 | } |
| 99363 | + | |
| 99364 | +/* | |
| 99365 | +** Value used to signify the end of an offset-list. This is safe because | |
| 99366 | +** it is not possible to have a document with 2^31 terms. | |
| 99367 | +*/ | |
| 99368 | +#define OFFSET_LIST_END 0x7fffffff | |
| 99369 | + | |
| 99370 | +/* | |
| 99371 | +** This function is used to help parse offset-lists. When this function is | |
| 99372 | +** called, *pp may point to the start of the next varint in the offset-list | |
| 99373 | +** being parsed, or it may point to 1 byte past the end of the offset-list | |
| 99374 | +** (in which case **pp will be 0x00 or 0x01). | |
| 99375 | +** | |
| 99376 | +** If *pp points past the end of the current offset list, set *pi to | |
| 99377 | +** OFFSET_LIST_END and return. Otherwise, read the next varint from *pp, | |
| 99378 | +** increment the current value of *pi by the value read, and set *pp to | |
| 99379 | +** point to the next value before returning. | |
| 99380 | +*/ | |
| 99381 | +static void fts3ReadNextPos( | |
| 99382 | + char **pp, /* IN/OUT: Pointer into offset-list buffer */ | |
| 99383 | + sqlite3_int64 *pi /* IN/OUT: Value read from offset-list */ | |
| 99384 | +){ | |
| 99385 | + if( **pp&0xFE ){ | |
| 99386 | + fts3GetDeltaVarint(pp, pi); | |
| 99387 | + *pi -= 2; | |
| 99388 | + }else{ | |
| 99389 | + *pi = OFFSET_LIST_END; | |
| 99390 | + } | |
| 99391 | +} | |
| 99392 | + | |
| 99393 | +/* | |
| 99394 | +** If parameter iCol is not 0, write an 0x01 byte followed by the value of | |
| 99395 | +** iCol encoded as a varint to *pp. | |
| 99396 | +** | |
| 99397 | +** Set *pp to point to the byte just after the last byte written before | |
| 99398 | +** returning (do not modify it if iCol==0). Return the total number of bytes | |
| 99399 | +** written (0 if iCol==0). | |
| 99400 | +*/ | |
| 99401 | +static int fts3PutColNumber(char **pp, int iCol){ | |
| 99402 | + int n = 0; /* Number of bytes written */ | |
| 99403 | + if( iCol ){ | |
| 99404 | + char *p = *pp; /* Output pointer */ | |
| 99405 | + n = 1 + sqlite3Fts3PutVarint(&p[1], iCol); | |
| 99406 | + *p = 0x01; | |
| 99407 | + *pp = &p[n]; | |
| 99408 | + } | |
| 99409 | + return n; | |
| 99410 | +} | |
| 99339 | 99411 | |
| 99340 | 99412 | /* |
| 99341 | 99413 | ** |
| 99342 | 99414 | */ |
| 99343 | 99415 | static void fts3PoslistMerge( |
| @@ -99347,44 +99419,57 @@ | ||
| 99347 | 99419 | ){ |
| 99348 | 99420 | char *p = *pp; |
| 99349 | 99421 | char *p1 = *pp1; |
| 99350 | 99422 | char *p2 = *pp2; |
| 99351 | 99423 | |
| 99352 | - while( *p1 && *p2 ){ | |
| 99353 | - int iCol1 = 0; | |
| 99354 | - int iCol2 = 0; | |
| 99424 | + while( *p1 || *p2 ){ | |
| 99425 | + int iCol1; | |
| 99426 | + int iCol2; | |
| 99427 | + | |
| 99355 | 99428 | if( *p1==0x01 ) sqlite3Fts3GetVarint32(&p1[1], &iCol1); |
| 99429 | + else if( *p1==0x00 ) iCol1 = OFFSET_LIST_END; | |
| 99430 | + else iCol1 = 0; | |
| 99431 | + | |
| 99356 | 99432 | if( *p2==0x01 ) sqlite3Fts3GetVarint32(&p2[1], &iCol2); |
| 99433 | + else if( *p2==0x00 ) iCol2 = OFFSET_LIST_END; | |
| 99434 | + else iCol2 = 0; | |
| 99357 | 99435 | |
| 99358 | 99436 | if( iCol1==iCol2 ){ |
| 99359 | 99437 | sqlite3_int64 i1 = 0; |
| 99360 | 99438 | sqlite3_int64 i2 = 0; |
| 99361 | 99439 | sqlite3_int64 iPrev = 0; |
| 99362 | - if( iCol1!=0 ){ | |
| 99363 | - int n; | |
| 99364 | - *p++ = 0x01; | |
| 99365 | - n = sqlite3Fts3PutVarint(p, iCol1); | |
| 99366 | - p += n; | |
| 99367 | - p1 += 1 + n; | |
| 99368 | - p2 += 1 + n; | |
| 99369 | - } | |
| 99370 | - while( (*p1&0xFE) || (*p2&0xFE) ){ | |
| 99440 | + int n = fts3PutColNumber(&p, iCol1); | |
| 99441 | + p1 += n; | |
| 99442 | + p2 += n; | |
| 99443 | + | |
| 99444 | + /* At this point, both p1 and p2 point to the start of offset-lists. | |
| 99445 | + ** An offset-list is a list of non-negative delta-encoded varints, each | |
| 99446 | + ** incremented by 2 before being stored. Each list is terminated by a 0 | |
| 99447 | + ** or 1 value (0x00 or 0x01). The following block merges the two lists | |
| 99448 | + ** and writes the results to buffer p. p is left pointing to the byte | |
| 99449 | + ** after the list written. No terminator (0x00 or 0x01) is written to | |
| 99450 | + ** the output. | |
| 99451 | + */ | |
| 99452 | + fts3GetDeltaVarint(&p1, &i1); | |
| 99453 | + fts3GetDeltaVarint(&p2, &i2); | |
| 99454 | + do { | |
| 99455 | + fts3PutDeltaVarint(&p, &iPrev, (i1<i2) ? i1 : i2); | |
| 99456 | + iPrev -= 2; | |
| 99371 | 99457 | if( i1==i2 ){ |
| 99372 | - fts3GetDeltaVarint(&p1, &i1); i1 -= 2; | |
| 99373 | - fts3GetDeltaVarint(&p2, &i2); i2 -= 2; | |
| 99458 | + fts3ReadNextPos(&p1, &i1); | |
| 99459 | + fts3ReadNextPos(&p2, &i2); | |
| 99374 | 99460 | }else if( i1<i2 ){ |
| 99375 | - fts3GetDeltaVarint(&p1, &i1); i1 -= 2; | |
| 99461 | + fts3ReadNextPos(&p1, &i1); | |
| 99376 | 99462 | }else{ |
| 99377 | - fts3GetDeltaVarint(&p2, &i2); i2 -= 2; | |
| 99463 | + fts3ReadNextPos(&p2, &i2); | |
| 99378 | 99464 | } |
| 99379 | - fts3PutDeltaVarint(&p, &iPrev, (i1<i2 ? i1 : i2) + 2); iPrev -= 2; | |
| 99380 | - if( 0==(*p1&0xFE) ) i1 = 0x7FFFFFFF; | |
| 99381 | - if( 0==(*p2&0xFE) ) i2 = 0x7FFFFFFF; | |
| 99382 | - } | |
| 99465 | + }while( i1!=OFFSET_LIST_END || i2!=OFFSET_LIST_END ); | |
| 99383 | 99466 | }else if( iCol1<iCol2 ){ |
| 99467 | + p1 += fts3PutColNumber(&p, iCol1); | |
| 99384 | 99468 | fts3ColumnlistCopy(&p, &p1); |
| 99385 | 99469 | }else{ |
| 99470 | + p2 += fts3PutColNumber(&p, iCol2); | |
| 99386 | 99471 | fts3ColumnlistCopy(&p, &p2); |
| 99387 | 99472 | } |
| 99388 | 99473 | } |
| 99389 | 99474 | |
| 99390 | 99475 | *p++ = '\0'; |
| @@ -99447,17 +99532,18 @@ | ||
| 99447 | 99532 | } |
| 99448 | 99533 | iSave = isSaveLeft ? iPos1 : iPos2; |
| 99449 | 99534 | fts3PutDeltaVarint(&p, &iPrev, iSave+2); iPrev -= 2; |
| 99450 | 99535 | pSave = 0; |
| 99451 | 99536 | } |
| 99452 | - if( iPos2<=iPos1 ){ | |
| 99537 | + if( (!isSaveLeft && iPos2<=(iPos1+nToken)) || iPos2<=iPos1 ){ | |
| 99453 | 99538 | if( (*p2&0xFE)==0 ) break; |
| 99454 | 99539 | fts3GetDeltaVarint(&p2, &iPos2); iPos2 -= 2; |
| 99455 | 99540 | }else{ |
| 99456 | 99541 | if( (*p1&0xFE)==0 ) break; |
| 99457 | 99542 | fts3GetDeltaVarint(&p1, &iPos1); iPos1 -= 2; |
| 99458 | 99543 | } |
| 99544 | + | |
| 99459 | 99545 | } |
| 99460 | 99546 | if( pSave && pp ){ |
| 99461 | 99547 | p = pSave; |
| 99462 | 99548 | } |
| 99463 | 99549 | |
| @@ -99500,17 +99586,20 @@ | ||
| 99500 | 99586 | *p++ = 0x00; |
| 99501 | 99587 | *pp = p; |
| 99502 | 99588 | return 1; |
| 99503 | 99589 | } |
| 99504 | 99590 | |
| 99591 | +/* | |
| 99592 | +** Merge two position-lists as required by the NEAR operator. | |
| 99593 | +*/ | |
| 99505 | 99594 | static int fts3PoslistNearMerge( |
| 99506 | 99595 | char **pp, /* Output buffer */ |
| 99507 | 99596 | char *aTmp, /* Temporary buffer space */ |
| 99508 | 99597 | int nRight, /* Maximum difference in token positions */ |
| 99509 | 99598 | int nLeft, /* Maximum difference in token positions */ |
| 99510 | - char **pp1, /* Left input list */ | |
| 99511 | - char **pp2 /* Right input list */ | |
| 99599 | + char **pp1, /* IN/OUT: Left input list */ | |
| 99600 | + char **pp2 /* IN/OUT: Right input list */ | |
| 99512 | 99601 | ){ |
| 99513 | 99602 | char *p1 = *pp1; |
| 99514 | 99603 | char *p2 = *pp2; |
| 99515 | 99604 | |
| 99516 | 99605 | if( !pp ){ |
| @@ -99593,10 +99682,14 @@ | ||
| 99593 | 99682 | ); |
| 99594 | 99683 | |
| 99595 | 99684 | if( !aBuffer ){ |
| 99596 | 99685 | return SQLITE_NOMEM; |
| 99597 | 99686 | } |
| 99687 | + if( n1==0 && n2==0 ){ | |
| 99688 | + *pnBuffer = 0; | |
| 99689 | + return SQLITE_OK; | |
| 99690 | + } | |
| 99598 | 99691 | |
| 99599 | 99692 | /* Read the first docid from each doclist */ |
| 99600 | 99693 | fts3GetDeltaVarint2(&p1, pEnd1, &i1); |
| 99601 | 99694 | fts3GetDeltaVarint2(&p2, pEnd2, &i2); |
| 99602 | 99695 | |
| @@ -99672,12 +99765,11 @@ | ||
| 99672 | 99765 | } |
| 99673 | 99766 | } |
| 99674 | 99767 | break; |
| 99675 | 99768 | } |
| 99676 | 99769 | |
| 99677 | - case MERGE_POS_NEAR: | |
| 99678 | - case MERGE_NEAR: { | |
| 99770 | + default: assert( mergetype==MERGE_POS_NEAR || mergetype==MERGE_NEAR ); { | |
| 99679 | 99771 | char *aTmp = 0; |
| 99680 | 99772 | char **ppPos = 0; |
| 99681 | 99773 | if( mergetype==MERGE_POS_NEAR ){ |
| 99682 | 99774 | ppPos = &p; |
| 99683 | 99775 | aTmp = sqlite3_malloc(2*(n1+n2)); |
| @@ -99708,13 +99800,10 @@ | ||
| 99708 | 99800 | } |
| 99709 | 99801 | } |
| 99710 | 99802 | sqlite3_free(aTmp); |
| 99711 | 99803 | break; |
| 99712 | 99804 | } |
| 99713 | - | |
| 99714 | - default: | |
| 99715 | - assert(!"Invalid mergetype value passed to fts3DoclistMerge()"); | |
| 99716 | 99805 | } |
| 99717 | 99806 | |
| 99718 | 99807 | *pnBuffer = (int)(p-aBuffer); |
| 99719 | 99808 | return SQLITE_OK; |
| 99720 | 99809 | } |
| @@ -100287,11 +100376,11 @@ | ||
| 100287 | 100376 | sqlite3_value *pVal, /* argv[0] passed to function */ |
| 100288 | 100377 | Fts3Cursor **ppCsr /* OUT: Store cursor handle here */ |
| 100289 | 100378 | ){ |
| 100290 | 100379 | Fts3Cursor *pRet; |
| 100291 | 100380 | if( sqlite3_value_type(pVal)!=SQLITE_BLOB |
| 100292 | - && sqlite3_value_bytes(pVal)!=sizeof(Fts3Cursor *) | |
| 100381 | + || sqlite3_value_bytes(pVal)!=sizeof(Fts3Cursor *) | |
| 100293 | 100382 | ){ |
| 100294 | 100383 | char *zErr = sqlite3_mprintf("illegal first argument to %s", zFunc); |
| 100295 | 100384 | sqlite3_result_error(pContext, zErr, -1); |
| 100296 | 100385 | sqlite3_free(zErr); |
| 100297 | 100386 | return SQLITE_ERROR; |
| @@ -100303,26 +100392,35 @@ | ||
| 100303 | 100392 | |
| 100304 | 100393 | /* |
| 100305 | 100394 | ** Implementation of the snippet() function for FTS3 |
| 100306 | 100395 | */ |
| 100307 | 100396 | static void fts3SnippetFunc( |
| 100308 | - sqlite3_context *pContext, | |
| 100309 | - int argc, | |
| 100310 | - sqlite3_value **argv | |
| 100397 | + sqlite3_context *pContext, /* SQLite function call context */ | |
| 100398 | + int nVal, /* Size of apVal[] array */ | |
| 100399 | + sqlite3_value **apVal /* Array of arguments */ | |
| 100311 | 100400 | ){ |
| 100312 | 100401 | Fts3Cursor *pCsr; /* Cursor handle passed through apVal[0] */ |
| 100313 | 100402 | const char *zStart = "<b>"; |
| 100314 | 100403 | const char *zEnd = "</b>"; |
| 100315 | 100404 | const char *zEllipsis = "<b>...</b>"; |
| 100316 | 100405 | |
| 100317 | - if( argc<1 || argc>4 ) return; | |
| 100318 | - if( fts3FunctionArg(pContext, "snippet", argv[0], &pCsr) ) return; | |
| 100406 | + /* There must be at least one argument passed to this function (otherwise | |
| 100407 | + ** the non-overloaded version would have been called instead of this one). | |
| 100408 | + */ | |
| 100409 | + assert( nVal>=1 ); | |
| 100319 | 100410 | |
| 100320 | - switch( argc ){ | |
| 100321 | - case 4: zEllipsis = (const char*)sqlite3_value_text(argv[3]); | |
| 100322 | - case 3: zEnd = (const char*)sqlite3_value_text(argv[2]); | |
| 100323 | - case 2: zStart = (const char*)sqlite3_value_text(argv[1]); | |
| 100411 | + if( nVal>4 ){ | |
| 100412 | + sqlite3_result_error(pContext, | |
| 100413 | + "wrong number of arguments to function snippet()", -1); | |
| 100414 | + return; | |
| 100415 | + } | |
| 100416 | + if( fts3FunctionArg(pContext, "snippet", apVal[0], &pCsr) ) return; | |
| 100417 | + | |
| 100418 | + switch( nVal ){ | |
| 100419 | + case 4: zEllipsis = (const char*)sqlite3_value_text(apVal[3]); | |
| 100420 | + case 3: zEnd = (const char*)sqlite3_value_text(apVal[2]); | |
| 100421 | + case 2: zStart = (const char*)sqlite3_value_text(apVal[1]); | |
| 100324 | 100422 | } |
| 100325 | 100423 | |
| 100326 | 100424 | sqlite3Fts3Snippet(pContext, pCsr, zStart, zEnd, zEllipsis); |
| 100327 | 100425 | } |
| 100328 | 100426 | |
| @@ -102669,11 +102767,10 @@ | ||
| 102669 | 102767 | sqlite3_tokenizer_module *m; |
| 102670 | 102768 | |
| 102671 | 102769 | if( !z ){ |
| 102672 | 102770 | zCopy = sqlite3_mprintf("simple"); |
| 102673 | 102771 | }else{ |
| 102674 | - while( (*z&0x80) && isspace(*z) ) z++; | |
| 102675 | 102772 | if( sqlite3_strnicmp(z, "tokenize", 8) || fts3IsIdChar(z[8])){ |
| 102676 | 102773 | return SQLITE_OK; |
| 102677 | 102774 | } |
| 102678 | 102775 | zCopy = sqlite3_mprintf("%s", &z[8]); |
| 102679 | 102776 | *pzTokenizer = zArg; |
| 102680 | 102777 |
| --- src/sqlite3.c | |
| +++ src/sqlite3.c | |
| @@ -643,11 +643,11 @@ | |
| 643 | ** |
| 644 | ** Requirements: [H10011] [H10014] |
| 645 | */ |
| 646 | #define SQLITE_VERSION "3.6.21" |
| 647 | #define SQLITE_VERSION_NUMBER 3006021 |
| 648 | #define SQLITE_SOURCE_ID "2009-12-04 14:25:19 082b8da005128f47f63e95b6b702bf4517221b2a" |
| 649 | |
| 650 | /* |
| 651 | ** CAPI3REF: Run-Time Library Version Numbers {H10020} <S60100> |
| 652 | ** KEYWORDS: sqlite3_version |
| 653 | ** |
| @@ -6755,13 +6755,23 @@ | |
| 6755 | ** Round down to the nearest multiple of 8 |
| 6756 | */ |
| 6757 | #define ROUNDDOWN8(x) ((x)&~7) |
| 6758 | |
| 6759 | /* |
| 6760 | ** Assert that the pointer X is aligned to an 8-byte boundary. |
| 6761 | */ |
| 6762 | #define EIGHT_BYTE_ALIGNMENT(X) ((((char*)(X) - (char*)0)&7)==0) |
| 6763 | |
| 6764 | |
| 6765 | /* |
| 6766 | ** An instance of the following structure is used to store the busy-handler |
| 6767 | ** callback for a given sqlite handle. |
| @@ -38775,18 +38785,20 @@ | |
| 38775 | u8 * const data = pPage->aData; /* Local cache of pPage->aData */ |
| 38776 | int nFrag; /* Number of fragmented bytes on pPage */ |
| 38777 | int top; /* First byte of cell content area */ |
| 38778 | int gap; /* First byte of gap between cell pointers and cell content */ |
| 38779 | int rc; /* Integer return code */ |
| 38780 | |
| 38781 | assert( sqlite3PagerIswriteable(pPage->pDbPage) ); |
| 38782 | assert( pPage->pBt ); |
| 38783 | assert( sqlite3_mutex_held(pPage->pBt->mutex) ); |
| 38784 | assert( nByte>=0 ); /* Minimum cell size is 4 */ |
| 38785 | assert( pPage->nFree>=nByte ); |
| 38786 | assert( pPage->nOverflow==0 ); |
| 38787 | assert( nByte<pPage->pBt->usableSize-8 ); |
| 38788 | |
| 38789 | nFrag = data[hdr+7]; |
| 38790 | assert( pPage->cellOffset == hdr + 12 - 4*pPage->leaf ); |
| 38791 | gap = pPage->cellOffset + 2*pPage->nCell; |
| 38792 | top = get2byte(&data[hdr+5]); |
| @@ -38805,20 +38817,26 @@ | |
| 38805 | ** the request. The allocation is made from the first free slot in |
| 38806 | ** the list that is large enough to accomadate it. |
| 38807 | */ |
| 38808 | int pc, addr; |
| 38809 | for(addr=hdr+1; (pc = get2byte(&data[addr]))>0; addr=pc){ |
| 38810 | int size = get2byte(&data[pc+2]); /* Size of free slot */ |
| 38811 | if( size>=nByte ){ |
| 38812 | int x = size - nByte; |
| 38813 | testcase( x==4 ); |
| 38814 | testcase( x==3 ); |
| 38815 | if( x<4 ){ |
| 38816 | /* Remove the slot from the free-list. Update the number of |
| 38817 | ** fragmented bytes within the page. */ |
| 38818 | memcpy(&data[addr], &data[pc], 2); |
| 38819 | data[hdr+7] = (u8)(nFrag + x); |
| 38820 | }else{ |
| 38821 | /* The slot remains on the free-list. Reduce its size to account |
| 38822 | ** for the portion used by the new allocation. */ |
| 38823 | put2byte(&data[pc+2], x); |
| 38824 | } |
| @@ -39238,11 +39256,10 @@ | |
| 39238 | ** Release a MemPage. This should be called once for each prior |
| 39239 | ** call to btreeGetPage. |
| 39240 | */ |
| 39241 | static void releasePage(MemPage *pPage){ |
| 39242 | if( pPage ){ |
| 39243 | assert( pPage->nOverflow==0 || sqlite3PagerPageRefcount(pPage->pDbPage)>1 ); |
| 39244 | assert( pPage->aData ); |
| 39245 | assert( pPage->pBt ); |
| 39246 | assert( sqlite3PagerGetExtra(pPage->pDbPage) == (void*)pPage ); |
| 39247 | assert( sqlite3PagerGetData(pPage->pDbPage)==pPage->aData ); |
| 39248 | assert( sqlite3_mutex_held(pPage->pBt->mutex) ); |
| @@ -43212,11 +43229,11 @@ | |
| 43212 | BtShared * const pBt = pFrom->pBt; |
| 43213 | u8 * const aFrom = pFrom->aData; |
| 43214 | u8 * const aTo = pTo->aData; |
| 43215 | int const iFromHdr = pFrom->hdrOffset; |
| 43216 | int const iToHdr = ((pTo->pgno==1) ? 100 : 0); |
| 43217 | TESTONLY(int rc;) |
| 43218 | int iData; |
| 43219 | |
| 43220 | |
| 43221 | assert( pFrom->isInit ); |
| 43222 | assert( pFrom->nFree>=iToHdr ); |
| @@ -43226,15 +43243,20 @@ | |
| 43226 | iData = get2byte(&aFrom[iFromHdr+5]); |
| 43227 | memcpy(&aTo[iData], &aFrom[iData], pBt->usableSize-iData); |
| 43228 | memcpy(&aTo[iToHdr], &aFrom[iFromHdr], pFrom->cellOffset + 2*pFrom->nCell); |
| 43229 | |
| 43230 | /* Reinitialize page pTo so that the contents of the MemPage structure |
| 43231 | ** match the new data. The initialization of pTo "cannot" fail, as the |
| 43232 | ** data copied from pFrom is known to be valid. */ |
| 43233 | pTo->isInit = 0; |
| 43234 | TESTONLY(rc = ) btreeInitPage(pTo); |
| 43235 | assert( rc==SQLITE_OK ); |
| 43236 | |
| 43237 | /* If this is an auto-vacuum database, update the pointer-map entries |
| 43238 | ** for any b-tree or overflow pages that pTo now contains the pointers to. |
| 43239 | */ |
| 43240 | if( ISAUTOVACUUM ){ |
| @@ -98918,21 +98940,21 @@ | |
| 98918 | int nCol = 0; |
| 98919 | char *zCsr; |
| 98920 | int nDb; |
| 98921 | int nName; |
| 98922 | |
| 98923 | #ifdef SQLITE_TEST |
| 98924 | char *zTestParam = 0; |
| 98925 | if( strncmp(argv[argc-1], "test:", 5)==0 ){ |
| 98926 | zTestParam = argv[argc-1]; |
| 98927 | argc--; |
| 98928 | } |
| 98929 | #endif |
| 98930 | |
| 98931 | const char *zTokenizer = 0; /* Name of tokenizer to use */ |
| 98932 | sqlite3_tokenizer *pTokenizer = 0; /* Tokenizer for this table */ |
| 98933 | |
| 98934 | nDb = (int)strlen(argv[1]) + 1; |
| 98935 | nName = (int)strlen(argv[2]) + 1; |
| 98936 | for(i=3; i<argc; i++){ |
| 98937 | char const *z = argv[i]; |
| 98938 | rc = sqlite3Fts3InitTokenizer(pHash, z, &pTokenizer, &zTokenizer, pzErr); |
| @@ -99324,10 +99346,12 @@ | |
| 99324 | } |
| 99325 | |
| 99326 | static void fts3ColumnlistCopy(char **pp, char **ppPoslist){ |
| 99327 | char *pEnd = *ppPoslist; |
| 99328 | char c = 0; |
| 99329 | while( 0xFE & (*pEnd | c) ) c = *pEnd++ & 0x80; |
| 99330 | if( pp ){ |
| 99331 | int n = (int)(pEnd - *ppPoslist); |
| 99332 | char *p = *pp; |
| 99333 | memcpy(p, *ppPoslist, n); |
| @@ -99334,10 +99358,58 @@ | |
| 99334 | p += n; |
| 99335 | *pp = p; |
| 99336 | } |
| 99337 | *ppPoslist = pEnd; |
| 99338 | } |
| 99339 | |
| 99340 | /* |
| 99341 | ** |
| 99342 | */ |
| 99343 | static void fts3PoslistMerge( |
| @@ -99347,44 +99419,57 @@ | |
| 99347 | ){ |
| 99348 | char *p = *pp; |
| 99349 | char *p1 = *pp1; |
| 99350 | char *p2 = *pp2; |
| 99351 | |
| 99352 | while( *p1 && *p2 ){ |
| 99353 | int iCol1 = 0; |
| 99354 | int iCol2 = 0; |
| 99355 | if( *p1==0x01 ) sqlite3Fts3GetVarint32(&p1[1], &iCol1); |
| 99356 | if( *p2==0x01 ) sqlite3Fts3GetVarint32(&p2[1], &iCol2); |
| 99357 | |
| 99358 | if( iCol1==iCol2 ){ |
| 99359 | sqlite3_int64 i1 = 0; |
| 99360 | sqlite3_int64 i2 = 0; |
| 99361 | sqlite3_int64 iPrev = 0; |
| 99362 | if( iCol1!=0 ){ |
| 99363 | int n; |
| 99364 | *p++ = 0x01; |
| 99365 | n = sqlite3Fts3PutVarint(p, iCol1); |
| 99366 | p += n; |
| 99367 | p1 += 1 + n; |
| 99368 | p2 += 1 + n; |
| 99369 | } |
| 99370 | while( (*p1&0xFE) || (*p2&0xFE) ){ |
| 99371 | if( i1==i2 ){ |
| 99372 | fts3GetDeltaVarint(&p1, &i1); i1 -= 2; |
| 99373 | fts3GetDeltaVarint(&p2, &i2); i2 -= 2; |
| 99374 | }else if( i1<i2 ){ |
| 99375 | fts3GetDeltaVarint(&p1, &i1); i1 -= 2; |
| 99376 | }else{ |
| 99377 | fts3GetDeltaVarint(&p2, &i2); i2 -= 2; |
| 99378 | } |
| 99379 | fts3PutDeltaVarint(&p, &iPrev, (i1<i2 ? i1 : i2) + 2); iPrev -= 2; |
| 99380 | if( 0==(*p1&0xFE) ) i1 = 0x7FFFFFFF; |
| 99381 | if( 0==(*p2&0xFE) ) i2 = 0x7FFFFFFF; |
| 99382 | } |
| 99383 | }else if( iCol1<iCol2 ){ |
| 99384 | fts3ColumnlistCopy(&p, &p1); |
| 99385 | }else{ |
| 99386 | fts3ColumnlistCopy(&p, &p2); |
| 99387 | } |
| 99388 | } |
| 99389 | |
| 99390 | *p++ = '\0'; |
| @@ -99447,17 +99532,18 @@ | |
| 99447 | } |
| 99448 | iSave = isSaveLeft ? iPos1 : iPos2; |
| 99449 | fts3PutDeltaVarint(&p, &iPrev, iSave+2); iPrev -= 2; |
| 99450 | pSave = 0; |
| 99451 | } |
| 99452 | if( iPos2<=iPos1 ){ |
| 99453 | if( (*p2&0xFE)==0 ) break; |
| 99454 | fts3GetDeltaVarint(&p2, &iPos2); iPos2 -= 2; |
| 99455 | }else{ |
| 99456 | if( (*p1&0xFE)==0 ) break; |
| 99457 | fts3GetDeltaVarint(&p1, &iPos1); iPos1 -= 2; |
| 99458 | } |
| 99459 | } |
| 99460 | if( pSave && pp ){ |
| 99461 | p = pSave; |
| 99462 | } |
| 99463 | |
| @@ -99500,17 +99586,20 @@ | |
| 99500 | *p++ = 0x00; |
| 99501 | *pp = p; |
| 99502 | return 1; |
| 99503 | } |
| 99504 | |
| 99505 | static int fts3PoslistNearMerge( |
| 99506 | char **pp, /* Output buffer */ |
| 99507 | char *aTmp, /* Temporary buffer space */ |
| 99508 | int nRight, /* Maximum difference in token positions */ |
| 99509 | int nLeft, /* Maximum difference in token positions */ |
| 99510 | char **pp1, /* Left input list */ |
| 99511 | char **pp2 /* Right input list */ |
| 99512 | ){ |
| 99513 | char *p1 = *pp1; |
| 99514 | char *p2 = *pp2; |
| 99515 | |
| 99516 | if( !pp ){ |
| @@ -99593,10 +99682,14 @@ | |
| 99593 | ); |
| 99594 | |
| 99595 | if( !aBuffer ){ |
| 99596 | return SQLITE_NOMEM; |
| 99597 | } |
| 99598 | |
| 99599 | /* Read the first docid from each doclist */ |
| 99600 | fts3GetDeltaVarint2(&p1, pEnd1, &i1); |
| 99601 | fts3GetDeltaVarint2(&p2, pEnd2, &i2); |
| 99602 | |
| @@ -99672,12 +99765,11 @@ | |
| 99672 | } |
| 99673 | } |
| 99674 | break; |
| 99675 | } |
| 99676 | |
| 99677 | case MERGE_POS_NEAR: |
| 99678 | case MERGE_NEAR: { |
| 99679 | char *aTmp = 0; |
| 99680 | char **ppPos = 0; |
| 99681 | if( mergetype==MERGE_POS_NEAR ){ |
| 99682 | ppPos = &p; |
| 99683 | aTmp = sqlite3_malloc(2*(n1+n2)); |
| @@ -99708,13 +99800,10 @@ | |
| 99708 | } |
| 99709 | } |
| 99710 | sqlite3_free(aTmp); |
| 99711 | break; |
| 99712 | } |
| 99713 | |
| 99714 | default: |
| 99715 | assert(!"Invalid mergetype value passed to fts3DoclistMerge()"); |
| 99716 | } |
| 99717 | |
| 99718 | *pnBuffer = (int)(p-aBuffer); |
| 99719 | return SQLITE_OK; |
| 99720 | } |
| @@ -100287,11 +100376,11 @@ | |
| 100287 | sqlite3_value *pVal, /* argv[0] passed to function */ |
| 100288 | Fts3Cursor **ppCsr /* OUT: Store cursor handle here */ |
| 100289 | ){ |
| 100290 | Fts3Cursor *pRet; |
| 100291 | if( sqlite3_value_type(pVal)!=SQLITE_BLOB |
| 100292 | && sqlite3_value_bytes(pVal)!=sizeof(Fts3Cursor *) |
| 100293 | ){ |
| 100294 | char *zErr = sqlite3_mprintf("illegal first argument to %s", zFunc); |
| 100295 | sqlite3_result_error(pContext, zErr, -1); |
| 100296 | sqlite3_free(zErr); |
| 100297 | return SQLITE_ERROR; |
| @@ -100303,26 +100392,35 @@ | |
| 100303 | |
| 100304 | /* |
| 100305 | ** Implementation of the snippet() function for FTS3 |
| 100306 | */ |
| 100307 | static void fts3SnippetFunc( |
| 100308 | sqlite3_context *pContext, |
| 100309 | int argc, |
| 100310 | sqlite3_value **argv |
| 100311 | ){ |
| 100312 | Fts3Cursor *pCsr; /* Cursor handle passed through apVal[0] */ |
| 100313 | const char *zStart = "<b>"; |
| 100314 | const char *zEnd = "</b>"; |
| 100315 | const char *zEllipsis = "<b>...</b>"; |
| 100316 | |
| 100317 | if( argc<1 || argc>4 ) return; |
| 100318 | if( fts3FunctionArg(pContext, "snippet", argv[0], &pCsr) ) return; |
| 100319 | |
| 100320 | switch( argc ){ |
| 100321 | case 4: zEllipsis = (const char*)sqlite3_value_text(argv[3]); |
| 100322 | case 3: zEnd = (const char*)sqlite3_value_text(argv[2]); |
| 100323 | case 2: zStart = (const char*)sqlite3_value_text(argv[1]); |
| 100324 | } |
| 100325 | |
| 100326 | sqlite3Fts3Snippet(pContext, pCsr, zStart, zEnd, zEllipsis); |
| 100327 | } |
| 100328 | |
| @@ -102669,11 +102767,10 @@ | |
| 102669 | sqlite3_tokenizer_module *m; |
| 102670 | |
| 102671 | if( !z ){ |
| 102672 | zCopy = sqlite3_mprintf("simple"); |
| 102673 | }else{ |
| 102674 | while( (*z&0x80) && isspace(*z) ) z++; |
| 102675 | if( sqlite3_strnicmp(z, "tokenize", 8) || fts3IsIdChar(z[8])){ |
| 102676 | return SQLITE_OK; |
| 102677 | } |
| 102678 | zCopy = sqlite3_mprintf("%s", &z[8]); |
| 102679 | *pzTokenizer = zArg; |
| 102680 |
| --- src/sqlite3.c | |
| +++ src/sqlite3.c | |
| @@ -643,11 +643,11 @@ | |
| 643 | ** |
| 644 | ** Requirements: [H10011] [H10014] |
| 645 | */ |
| 646 | #define SQLITE_VERSION "3.6.21" |
| 647 | #define SQLITE_VERSION_NUMBER 3006021 |
| 648 | #define SQLITE_SOURCE_ID "2009-12-07 16:39:13 1ed88e9d01e9eda5cbc622e7614277f29bcc551c" |
| 649 | |
| 650 | /* |
| 651 | ** CAPI3REF: Run-Time Library Version Numbers {H10020} <S60100> |
| 652 | ** KEYWORDS: sqlite3_version |
| 653 | ** |
| @@ -6755,13 +6755,23 @@ | |
| 6755 | ** Round down to the nearest multiple of 8 |
| 6756 | */ |
| 6757 | #define ROUNDDOWN8(x) ((x)&~7) |
| 6758 | |
| 6759 | /* |
| 6760 | ** Assert that the pointer X is aligned to an 8-byte boundary. This |
| 6761 | ** macro is used only within assert() to verify that the code gets |
| 6762 | ** all alignment restrictions correct. |
| 6763 | ** |
| 6764 | ** Except, if SQLITE_4_BYTE_ALIGNED_MALLOC is defined, then the |
| 6765 | ** underlying malloc() implemention might return us 4-byte aligned |
| 6766 | ** pointers. In that case, only verify 4-byte alignment. |
| 6767 | */ |
| 6768 | #ifdef SQLITE_4_BYTE_ALIGNED_MALLOC |
| 6769 | # define EIGHT_BYTE_ALIGNMENT(X) ((((char*)(X) - (char*)0)&3)==0) |
| 6770 | #else |
| 6771 | # define EIGHT_BYTE_ALIGNMENT(X) ((((char*)(X) - (char*)0)&7)==0) |
| 6772 | #endif |
| 6773 | |
| 6774 | |
| 6775 | /* |
| 6776 | ** An instance of the following structure is used to store the busy-handler |
| 6777 | ** callback for a given sqlite handle. |
| @@ -38775,18 +38785,20 @@ | |
| 38785 | u8 * const data = pPage->aData; /* Local cache of pPage->aData */ |
| 38786 | int nFrag; /* Number of fragmented bytes on pPage */ |
| 38787 | int top; /* First byte of cell content area */ |
| 38788 | int gap; /* First byte of gap between cell pointers and cell content */ |
| 38789 | int rc; /* Integer return code */ |
| 38790 | int usableSize; /* Usable size of the page */ |
| 38791 | |
| 38792 | assert( sqlite3PagerIswriteable(pPage->pDbPage) ); |
| 38793 | assert( pPage->pBt ); |
| 38794 | assert( sqlite3_mutex_held(pPage->pBt->mutex) ); |
| 38795 | assert( nByte>=0 ); /* Minimum cell size is 4 */ |
| 38796 | assert( pPage->nFree>=nByte ); |
| 38797 | assert( pPage->nOverflow==0 ); |
| 38798 | usableSize = pPage->pBt->usableSize; |
| 38799 | assert( nByte < usableSize-8 ); |
| 38800 | |
| 38801 | nFrag = data[hdr+7]; |
| 38802 | assert( pPage->cellOffset == hdr + 12 - 4*pPage->leaf ); |
| 38803 | gap = pPage->cellOffset + 2*pPage->nCell; |
| 38804 | top = get2byte(&data[hdr+5]); |
| @@ -38805,20 +38817,26 @@ | |
| 38817 | ** the request. The allocation is made from the first free slot in |
| 38818 | ** the list that is large enough to accomadate it. |
| 38819 | */ |
| 38820 | int pc, addr; |
| 38821 | for(addr=hdr+1; (pc = get2byte(&data[addr]))>0; addr=pc){ |
| 38822 | int size; /* Size of the free slot */ |
| 38823 | if( pc>usableSize-4 || pc<addr+4 ){ |
| 38824 | return SQLITE_CORRUPT_BKPT; |
| 38825 | } |
| 38826 | size = get2byte(&data[pc+2]); |
| 38827 | if( size>=nByte ){ |
| 38828 | int x = size - nByte; |
| 38829 | testcase( x==4 ); |
| 38830 | testcase( x==3 ); |
| 38831 | if( x<4 ){ |
| 38832 | /* Remove the slot from the free-list. Update the number of |
| 38833 | ** fragmented bytes within the page. */ |
| 38834 | memcpy(&data[addr], &data[pc], 2); |
| 38835 | data[hdr+7] = (u8)(nFrag + x); |
| 38836 | }else if( size+pc > usableSize ){ |
| 38837 | return SQLITE_CORRUPT_BKPT; |
| 38838 | }else{ |
| 38839 | /* The slot remains on the free-list. Reduce its size to account |
| 38840 | ** for the portion used by the new allocation. */ |
| 38841 | put2byte(&data[pc+2], x); |
| 38842 | } |
| @@ -39238,11 +39256,10 @@ | |
| 39256 | ** Release a MemPage. This should be called once for each prior |
| 39257 | ** call to btreeGetPage. |
| 39258 | */ |
| 39259 | static void releasePage(MemPage *pPage){ |
| 39260 | if( pPage ){ |
| 39261 | assert( pPage->aData ); |
| 39262 | assert( pPage->pBt ); |
| 39263 | assert( sqlite3PagerGetExtra(pPage->pDbPage) == (void*)pPage ); |
| 39264 | assert( sqlite3PagerGetData(pPage->pDbPage)==pPage->aData ); |
| 39265 | assert( sqlite3_mutex_held(pPage->pBt->mutex) ); |
| @@ -43212,11 +43229,11 @@ | |
| 43229 | BtShared * const pBt = pFrom->pBt; |
| 43230 | u8 * const aFrom = pFrom->aData; |
| 43231 | u8 * const aTo = pTo->aData; |
| 43232 | int const iFromHdr = pFrom->hdrOffset; |
| 43233 | int const iToHdr = ((pTo->pgno==1) ? 100 : 0); |
| 43234 | int rc; |
| 43235 | int iData; |
| 43236 | |
| 43237 | |
| 43238 | assert( pFrom->isInit ); |
| 43239 | assert( pFrom->nFree>=iToHdr ); |
| @@ -43226,15 +43243,20 @@ | |
| 43243 | iData = get2byte(&aFrom[iFromHdr+5]); |
| 43244 | memcpy(&aTo[iData], &aFrom[iData], pBt->usableSize-iData); |
| 43245 | memcpy(&aTo[iToHdr], &aFrom[iFromHdr], pFrom->cellOffset + 2*pFrom->nCell); |
| 43246 | |
| 43247 | /* Reinitialize page pTo so that the contents of the MemPage structure |
| 43248 | ** match the new data. The initialization of pTo can actually fail under |
| 43249 | ** fairly obscure circumstances, even though it is a copy of initialized |
| 43250 | ** page pFrom. |
| 43251 | */ |
| 43252 | pTo->isInit = 0; |
| 43253 | rc = btreeInitPage(pTo); |
| 43254 | if( rc!=SQLITE_OK ){ |
| 43255 | *pRC = rc; |
| 43256 | return; |
| 43257 | } |
| 43258 | |
| 43259 | /* If this is an auto-vacuum database, update the pointer-map entries |
| 43260 | ** for any b-tree or overflow pages that pTo now contains the pointers to. |
| 43261 | */ |
| 43262 | if( ISAUTOVACUUM ){ |
| @@ -98918,21 +98940,21 @@ | |
| 98940 | int nCol = 0; |
| 98941 | char *zCsr; |
| 98942 | int nDb; |
| 98943 | int nName; |
| 98944 | |
| 98945 | const char *zTokenizer = 0; /* Name of tokenizer to use */ |
| 98946 | sqlite3_tokenizer *pTokenizer = 0; /* Tokenizer for this table */ |
| 98947 | |
| 98948 | #ifdef SQLITE_TEST |
| 98949 | const char *zTestParam = 0; |
| 98950 | if( strncmp(argv[argc-1], "test:", 5)==0 ){ |
| 98951 | zTestParam = argv[argc-1]; |
| 98952 | argc--; |
| 98953 | } |
| 98954 | #endif |
| 98955 | |
| 98956 | nDb = (int)strlen(argv[1]) + 1; |
| 98957 | nName = (int)strlen(argv[2]) + 1; |
| 98958 | for(i=3; i<argc; i++){ |
| 98959 | char const *z = argv[i]; |
| 98960 | rc = sqlite3Fts3InitTokenizer(pHash, z, &pTokenizer, &zTokenizer, pzErr); |
| @@ -99324,10 +99346,12 @@ | |
| 99346 | } |
| 99347 | |
| 99348 | static void fts3ColumnlistCopy(char **pp, char **ppPoslist){ |
| 99349 | char *pEnd = *ppPoslist; |
| 99350 | char c = 0; |
| 99351 | |
| 99352 | /* A column-list is terminated by either a 0x01 or 0x00. */ |
| 99353 | while( 0xFE & (*pEnd | c) ) c = *pEnd++ & 0x80; |
| 99354 | if( pp ){ |
| 99355 | int n = (int)(pEnd - *ppPoslist); |
| 99356 | char *p = *pp; |
| 99357 | memcpy(p, *ppPoslist, n); |
| @@ -99334,10 +99358,58 @@ | |
| 99358 | p += n; |
| 99359 | *pp = p; |
| 99360 | } |
| 99361 | *ppPoslist = pEnd; |
| 99362 | } |
| 99363 | |
| 99364 | /* |
| 99365 | ** Value used to signify the end of an offset-list. This is safe because |
| 99366 | ** it is not possible to have a document with 2^31 terms. |
| 99367 | */ |
| 99368 | #define OFFSET_LIST_END 0x7fffffff |
| 99369 | |
| 99370 | /* |
| 99371 | ** This function is used to help parse offset-lists. When this function is |
| 99372 | ** called, *pp may point to the start of the next varint in the offset-list |
| 99373 | ** being parsed, or it may point to 1 byte past the end of the offset-list |
| 99374 | ** (in which case **pp will be 0x00 or 0x01). |
| 99375 | ** |
| 99376 | ** If *pp points past the end of the current offset list, set *pi to |
| 99377 | ** OFFSET_LIST_END and return. Otherwise, read the next varint from *pp, |
| 99378 | ** increment the current value of *pi by the value read, and set *pp to |
| 99379 | ** point to the next value before returning. |
| 99380 | */ |
| 99381 | static void fts3ReadNextPos( |
| 99382 | char **pp, /* IN/OUT: Pointer into offset-list buffer */ |
| 99383 | sqlite3_int64 *pi /* IN/OUT: Value read from offset-list */ |
| 99384 | ){ |
| 99385 | if( **pp&0xFE ){ |
| 99386 | fts3GetDeltaVarint(pp, pi); |
| 99387 | *pi -= 2; |
| 99388 | }else{ |
| 99389 | *pi = OFFSET_LIST_END; |
| 99390 | } |
| 99391 | } |
| 99392 | |
| 99393 | /* |
| 99394 | ** If parameter iCol is not 0, write an 0x01 byte followed by the value of |
| 99395 | ** iCol encoded as a varint to *pp. |
| 99396 | ** |
| 99397 | ** Set *pp to point to the byte just after the last byte written before |
| 99398 | ** returning (do not modify it if iCol==0). Return the total number of bytes |
| 99399 | ** written (0 if iCol==0). |
| 99400 | */ |
| 99401 | static int fts3PutColNumber(char **pp, int iCol){ |
| 99402 | int n = 0; /* Number of bytes written */ |
| 99403 | if( iCol ){ |
| 99404 | char *p = *pp; /* Output pointer */ |
| 99405 | n = 1 + sqlite3Fts3PutVarint(&p[1], iCol); |
| 99406 | *p = 0x01; |
| 99407 | *pp = &p[n]; |
| 99408 | } |
| 99409 | return n; |
| 99410 | } |
| 99411 | |
| 99412 | /* |
| 99413 | ** |
| 99414 | */ |
| 99415 | static void fts3PoslistMerge( |
| @@ -99347,44 +99419,57 @@ | |
| 99419 | ){ |
| 99420 | char *p = *pp; |
| 99421 | char *p1 = *pp1; |
| 99422 | char *p2 = *pp2; |
| 99423 | |
| 99424 | while( *p1 || *p2 ){ |
| 99425 | int iCol1; |
| 99426 | int iCol2; |
| 99427 | |
| 99428 | if( *p1==0x01 ) sqlite3Fts3GetVarint32(&p1[1], &iCol1); |
| 99429 | else if( *p1==0x00 ) iCol1 = OFFSET_LIST_END; |
| 99430 | else iCol1 = 0; |
| 99431 | |
| 99432 | if( *p2==0x01 ) sqlite3Fts3GetVarint32(&p2[1], &iCol2); |
| 99433 | else if( *p2==0x00 ) iCol2 = OFFSET_LIST_END; |
| 99434 | else iCol2 = 0; |
| 99435 | |
| 99436 | if( iCol1==iCol2 ){ |
| 99437 | sqlite3_int64 i1 = 0; |
| 99438 | sqlite3_int64 i2 = 0; |
| 99439 | sqlite3_int64 iPrev = 0; |
| 99440 | int n = fts3PutColNumber(&p, iCol1); |
| 99441 | p1 += n; |
| 99442 | p2 += n; |
| 99443 | |
| 99444 | /* At this point, both p1 and p2 point to the start of offset-lists. |
| 99445 | ** An offset-list is a list of non-negative delta-encoded varints, each |
| 99446 | ** incremented by 2 before being stored. Each list is terminated by a 0 |
| 99447 | ** or 1 value (0x00 or 0x01). The following block merges the two lists |
| 99448 | ** and writes the results to buffer p. p is left pointing to the byte |
| 99449 | ** after the list written. No terminator (0x00 or 0x01) is written to |
| 99450 | ** the output. |
| 99451 | */ |
| 99452 | fts3GetDeltaVarint(&p1, &i1); |
| 99453 | fts3GetDeltaVarint(&p2, &i2); |
| 99454 | do { |
| 99455 | fts3PutDeltaVarint(&p, &iPrev, (i1<i2) ? i1 : i2); |
| 99456 | iPrev -= 2; |
| 99457 | if( i1==i2 ){ |
| 99458 | fts3ReadNextPos(&p1, &i1); |
| 99459 | fts3ReadNextPos(&p2, &i2); |
| 99460 | }else if( i1<i2 ){ |
| 99461 | fts3ReadNextPos(&p1, &i1); |
| 99462 | }else{ |
| 99463 | fts3ReadNextPos(&p2, &i2); |
| 99464 | } |
| 99465 | }while( i1!=OFFSET_LIST_END || i2!=OFFSET_LIST_END ); |
| 99466 | }else if( iCol1<iCol2 ){ |
| 99467 | p1 += fts3PutColNumber(&p, iCol1); |
| 99468 | fts3ColumnlistCopy(&p, &p1); |
| 99469 | }else{ |
| 99470 | p2 += fts3PutColNumber(&p, iCol2); |
| 99471 | fts3ColumnlistCopy(&p, &p2); |
| 99472 | } |
| 99473 | } |
| 99474 | |
| 99475 | *p++ = '\0'; |
| @@ -99447,17 +99532,18 @@ | |
| 99532 | } |
| 99533 | iSave = isSaveLeft ? iPos1 : iPos2; |
| 99534 | fts3PutDeltaVarint(&p, &iPrev, iSave+2); iPrev -= 2; |
| 99535 | pSave = 0; |
| 99536 | } |
| 99537 | if( (!isSaveLeft && iPos2<=(iPos1+nToken)) || iPos2<=iPos1 ){ |
| 99538 | if( (*p2&0xFE)==0 ) break; |
| 99539 | fts3GetDeltaVarint(&p2, &iPos2); iPos2 -= 2; |
| 99540 | }else{ |
| 99541 | if( (*p1&0xFE)==0 ) break; |
| 99542 | fts3GetDeltaVarint(&p1, &iPos1); iPos1 -= 2; |
| 99543 | } |
| 99544 | |
| 99545 | } |
| 99546 | if( pSave && pp ){ |
| 99547 | p = pSave; |
| 99548 | } |
| 99549 | |
| @@ -99500,17 +99586,20 @@ | |
| 99586 | *p++ = 0x00; |
| 99587 | *pp = p; |
| 99588 | return 1; |
| 99589 | } |
| 99590 | |
| 99591 | /* |
| 99592 | ** Merge two position-lists as required by the NEAR operator. |
| 99593 | */ |
| 99594 | static int fts3PoslistNearMerge( |
| 99595 | char **pp, /* Output buffer */ |
| 99596 | char *aTmp, /* Temporary buffer space */ |
| 99597 | int nRight, /* Maximum difference in token positions */ |
| 99598 | int nLeft, /* Maximum difference in token positions */ |
| 99599 | char **pp1, /* IN/OUT: Left input list */ |
| 99600 | char **pp2 /* IN/OUT: Right input list */ |
| 99601 | ){ |
| 99602 | char *p1 = *pp1; |
| 99603 | char *p2 = *pp2; |
| 99604 | |
| 99605 | if( !pp ){ |
| @@ -99593,10 +99682,14 @@ | |
| 99682 | ); |
| 99683 | |
| 99684 | if( !aBuffer ){ |
| 99685 | return SQLITE_NOMEM; |
| 99686 | } |
| 99687 | if( n1==0 && n2==0 ){ |
| 99688 | *pnBuffer = 0; |
| 99689 | return SQLITE_OK; |
| 99690 | } |
| 99691 | |
| 99692 | /* Read the first docid from each doclist */ |
| 99693 | fts3GetDeltaVarint2(&p1, pEnd1, &i1); |
| 99694 | fts3GetDeltaVarint2(&p2, pEnd2, &i2); |
| 99695 | |
| @@ -99672,12 +99765,11 @@ | |
| 99765 | } |
| 99766 | } |
| 99767 | break; |
| 99768 | } |
| 99769 | |
| 99770 | default: assert( mergetype==MERGE_POS_NEAR || mergetype==MERGE_NEAR ); { |
| 99771 | char *aTmp = 0; |
| 99772 | char **ppPos = 0; |
| 99773 | if( mergetype==MERGE_POS_NEAR ){ |
| 99774 | ppPos = &p; |
| 99775 | aTmp = sqlite3_malloc(2*(n1+n2)); |
| @@ -99708,13 +99800,10 @@ | |
| 99800 | } |
| 99801 | } |
| 99802 | sqlite3_free(aTmp); |
| 99803 | break; |
| 99804 | } |
| 99805 | } |
| 99806 | |
| 99807 | *pnBuffer = (int)(p-aBuffer); |
| 99808 | return SQLITE_OK; |
| 99809 | } |
| @@ -100287,11 +100376,11 @@ | |
| 100376 | sqlite3_value *pVal, /* argv[0] passed to function */ |
| 100377 | Fts3Cursor **ppCsr /* OUT: Store cursor handle here */ |
| 100378 | ){ |
| 100379 | Fts3Cursor *pRet; |
| 100380 | if( sqlite3_value_type(pVal)!=SQLITE_BLOB |
| 100381 | || sqlite3_value_bytes(pVal)!=sizeof(Fts3Cursor *) |
| 100382 | ){ |
| 100383 | char *zErr = sqlite3_mprintf("illegal first argument to %s", zFunc); |
| 100384 | sqlite3_result_error(pContext, zErr, -1); |
| 100385 | sqlite3_free(zErr); |
| 100386 | return SQLITE_ERROR; |
| @@ -100303,26 +100392,35 @@ | |
| 100392 | |
| 100393 | /* |
| 100394 | ** Implementation of the snippet() function for FTS3 |
| 100395 | */ |
| 100396 | static void fts3SnippetFunc( |
| 100397 | sqlite3_context *pContext, /* SQLite function call context */ |
| 100398 | int nVal, /* Size of apVal[] array */ |
| 100399 | sqlite3_value **apVal /* Array of arguments */ |
| 100400 | ){ |
| 100401 | Fts3Cursor *pCsr; /* Cursor handle passed through apVal[0] */ |
| 100402 | const char *zStart = "<b>"; |
| 100403 | const char *zEnd = "</b>"; |
| 100404 | const char *zEllipsis = "<b>...</b>"; |
| 100405 | |
| 100406 | /* There must be at least one argument passed to this function (otherwise |
| 100407 | ** the non-overloaded version would have been called instead of this one). |
| 100408 | */ |
| 100409 | assert( nVal>=1 ); |
| 100410 | |
| 100411 | if( nVal>4 ){ |
| 100412 | sqlite3_result_error(pContext, |
| 100413 | "wrong number of arguments to function snippet()", -1); |
| 100414 | return; |
| 100415 | } |
| 100416 | if( fts3FunctionArg(pContext, "snippet", apVal[0], &pCsr) ) return; |
| 100417 | |
| 100418 | switch( nVal ){ |
| 100419 | case 4: zEllipsis = (const char*)sqlite3_value_text(apVal[3]); |
| 100420 | case 3: zEnd = (const char*)sqlite3_value_text(apVal[2]); |
| 100421 | case 2: zStart = (const char*)sqlite3_value_text(apVal[1]); |
| 100422 | } |
| 100423 | |
| 100424 | sqlite3Fts3Snippet(pContext, pCsr, zStart, zEnd, zEllipsis); |
| 100425 | } |
| 100426 | |
| @@ -102669,11 +102767,10 @@ | |
| 102767 | sqlite3_tokenizer_module *m; |
| 102768 | |
| 102769 | if( !z ){ |
| 102770 | zCopy = sqlite3_mprintf("simple"); |
| 102771 | }else{ |
| 102772 | if( sqlite3_strnicmp(z, "tokenize", 8) || fts3IsIdChar(z[8])){ |
| 102773 | return SQLITE_OK; |
| 102774 | } |
| 102775 | zCopy = sqlite3_mprintf("%s", &z[8]); |
| 102776 | *pzTokenizer = zArg; |
| 102777 |
+1
-1
| --- src/sqlite3.h | ||
| +++ src/sqlite3.h | ||
| @@ -119,11 +119,11 @@ | ||
| 119 | 119 | ** |
| 120 | 120 | ** Requirements: [H10011] [H10014] |
| 121 | 121 | */ |
| 122 | 122 | #define SQLITE_VERSION "3.6.21" |
| 123 | 123 | #define SQLITE_VERSION_NUMBER 3006021 |
| 124 | -#define SQLITE_SOURCE_ID "2009-12-04 14:25:19 082b8da005128f47f63e95b6b702bf4517221b2a" | |
| 124 | +#define SQLITE_SOURCE_ID "2009-12-07 16:39:13 1ed88e9d01e9eda5cbc622e7614277f29bcc551c" | |
| 125 | 125 | |
| 126 | 126 | /* |
| 127 | 127 | ** CAPI3REF: Run-Time Library Version Numbers {H10020} <S60100> |
| 128 | 128 | ** KEYWORDS: sqlite3_version |
| 129 | 129 | ** |
| 130 | 130 |
| --- src/sqlite3.h | |
| +++ src/sqlite3.h | |
| @@ -119,11 +119,11 @@ | |
| 119 | ** |
| 120 | ** Requirements: [H10011] [H10014] |
| 121 | */ |
| 122 | #define SQLITE_VERSION "3.6.21" |
| 123 | #define SQLITE_VERSION_NUMBER 3006021 |
| 124 | #define SQLITE_SOURCE_ID "2009-12-04 14:25:19 082b8da005128f47f63e95b6b702bf4517221b2a" |
| 125 | |
| 126 | /* |
| 127 | ** CAPI3REF: Run-Time Library Version Numbers {H10020} <S60100> |
| 128 | ** KEYWORDS: sqlite3_version |
| 129 | ** |
| 130 |
| --- src/sqlite3.h | |
| +++ src/sqlite3.h | |
| @@ -119,11 +119,11 @@ | |
| 119 | ** |
| 120 | ** Requirements: [H10011] [H10014] |
| 121 | */ |
| 122 | #define SQLITE_VERSION "3.6.21" |
| 123 | #define SQLITE_VERSION_NUMBER 3006021 |
| 124 | #define SQLITE_SOURCE_ID "2009-12-07 16:39:13 1ed88e9d01e9eda5cbc622e7614277f29bcc551c" |
| 125 | |
| 126 | /* |
| 127 | ** CAPI3REF: Run-Time Library Version Numbers {H10020} <S60100> |
| 128 | ** KEYWORDS: sqlite3_version |
| 129 | ** |
| 130 |