Overview
SHA1 Hash: | 9f654b99840423c091ac06e15f64da27e413954e |
---|---|
Date: | 2009-12-07 20:23:03 |
User: | drh |
Comment: | Update SQLite to version 3.6.21 final. |
Timelines: | ancestors | descendants | both | trunk |
Other Links: | files | ZIP archive | manifest |
Tags And Properties
- branch=trunk inherited from [a28c83647d]
- sym-trunk inherited from [a28c83647d]
Changes
[hide diffs]Modified src/sqlite3.c from [d909879b17] to [bc27f16f36].
@@ -643,11 +643,11 @@ ** ** Requirements: [H10011] [H10014] */ #define SQLITE_VERSION "3.6.21" #define SQLITE_VERSION_NUMBER 3006021 -#define SQLITE_SOURCE_ID "2009-12-04 14:25:19 082b8da005128f47f63e95b6b702bf4517221b2a" +#define SQLITE_SOURCE_ID "2009-12-07 16:39:13 1ed88e9d01e9eda5cbc622e7614277f29bcc551c" /* ** CAPI3REF: Run-Time Library Version Numbers {H10020} <S60100> ** KEYWORDS: sqlite3_version ** @@ -6755,13 +6755,23 @@ ** Round down to the nearest multiple of 8 */ #define ROUNDDOWN8(x) ((x)&~7) /* -** Assert that the pointer X is aligned to an 8-byte boundary. -*/ -#define EIGHT_BYTE_ALIGNMENT(X) ((((char*)(X) - (char*)0)&7)==0) +** Assert that the pointer X is aligned to an 8-byte boundary. This +** macro is used only within assert() to verify that the code gets +** all alignment restrictions correct. +** +** Except, if SQLITE_4_BYTE_ALIGNED_MALLOC is defined, then the +** underlying malloc() implemention might return us 4-byte aligned +** pointers. In that case, only verify 4-byte alignment. +*/ +#ifdef SQLITE_4_BYTE_ALIGNED_MALLOC +# define EIGHT_BYTE_ALIGNMENT(X) ((((char*)(X) - (char*)0)&3)==0) +#else +# define EIGHT_BYTE_ALIGNMENT(X) ((((char*)(X) - (char*)0)&7)==0) +#endif /* ** An instance of the following structure is used to store the busy-handler ** callback for a given sqlite handle. @@ -38775,18 +38785,20 @@ u8 * const data = pPage->aData; /* Local cache of pPage->aData */ int nFrag; /* Number of fragmented bytes on pPage */ int top; /* First byte of cell content area */ int gap; /* First byte of gap between cell pointers and cell content */ int rc; /* Integer return code */ + int usableSize; /* Usable size of the page */ assert( sqlite3PagerIswriteable(pPage->pDbPage) ); assert( pPage->pBt ); assert( sqlite3_mutex_held(pPage->pBt->mutex) ); assert( nByte>=0 ); /* Minimum cell size is 4 */ assert( pPage->nFree>=nByte ); assert( pPage->nOverflow==0 ); - assert( nByte<pPage->pBt->usableSize-8 ); + usableSize = pPage->pBt->usableSize; + assert( nByte < usableSize-8 ); nFrag = data[hdr+7]; assert( pPage->cellOffset == hdr + 12 - 4*pPage->leaf ); gap = pPage->cellOffset + 2*pPage->nCell; top = get2byte(&data[hdr+5]); @@ -38805,20 +38817,26 @@ ** the request. The allocation is made from the first free slot in ** the list that is large enough to accomadate it. */ int pc, addr; for(addr=hdr+1; (pc = get2byte(&data[addr]))>0; addr=pc){ - int size = get2byte(&data[pc+2]); /* Size of free slot */ + int size; /* Size of the free slot */ + if( pc>usableSize-4 || pc<addr+4 ){ + return SQLITE_CORRUPT_BKPT; + } + size = get2byte(&data[pc+2]); if( size>=nByte ){ int x = size - nByte; testcase( x==4 ); testcase( x==3 ); if( x<4 ){ /* Remove the slot from the free-list. Update the number of ** fragmented bytes within the page. */ memcpy(&data[addr], &data[pc], 2); data[hdr+7] = (u8)(nFrag + x); + }else if( size+pc > usableSize ){ + return SQLITE_CORRUPT_BKPT; }else{ /* The slot remains on the free-list. Reduce its size to account ** for the portion used by the new allocation. */ put2byte(&data[pc+2], x); } @@ -39238,11 +39256,10 @@ ** Release a MemPage. This should be called once for each prior ** call to btreeGetPage. */ static void releasePage(MemPage *pPage){ if( pPage ){ - assert( pPage->nOverflow==0 || sqlite3PagerPageRefcount(pPage->pDbPage)>1 ); assert( pPage->aData ); assert( pPage->pBt ); assert( sqlite3PagerGetExtra(pPage->pDbPage) == (void*)pPage ); assert( sqlite3PagerGetData(pPage->pDbPage)==pPage->aData ); assert( sqlite3_mutex_held(pPage->pBt->mutex) ); @@ -43212,11 +43229,11 @@ BtShared * const pBt = pFrom->pBt; u8 * const aFrom = pFrom->aData; u8 * const aTo = pTo->aData; int const iFromHdr = pFrom->hdrOffset; int const iToHdr = ((pTo->pgno==1) ? 100 : 0); - TESTONLY(int rc;) + int rc; int iData; assert( pFrom->isInit ); assert( pFrom->nFree>=iToHdr ); @@ -43226,15 +43243,20 @@ iData = get2byte(&aFrom[iFromHdr+5]); memcpy(&aTo[iData], &aFrom[iData], pBt->usableSize-iData); memcpy(&aTo[iToHdr], &aFrom[iFromHdr], pFrom->cellOffset + 2*pFrom->nCell); /* Reinitialize page pTo so that the contents of the MemPage structure - ** match the new data. The initialization of pTo "cannot" fail, as the - ** data copied from pFrom is known to be valid. */ + ** match the new data. The initialization of pTo can actually fail under + ** fairly obscure circumstances, even though it is a copy of initialized + ** page pFrom. + */ pTo->isInit = 0; - TESTONLY(rc = ) btreeInitPage(pTo); - assert( rc==SQLITE_OK ); + rc = btreeInitPage(pTo); + if( rc!=SQLITE_OK ){ + *pRC = rc; + return; + } /* If this is an auto-vacuum database, update the pointer-map entries ** for any b-tree or overflow pages that pTo now contains the pointers to. */ if( ISAUTOVACUUM ){ @@ -98918,20 +98940,20 @@ int nCol = 0; char *zCsr; int nDb; int nName; + const char *zTokenizer = 0; /* Name of tokenizer to use */ + sqlite3_tokenizer *pTokenizer = 0; /* Tokenizer for this table */ + #ifdef SQLITE_TEST - char *zTestParam = 0; + const char *zTestParam = 0; if( strncmp(argv[argc-1], "test:", 5)==0 ){ zTestParam = argv[argc-1]; argc--; } #endif - - const char *zTokenizer = 0; /* Name of tokenizer to use */ - sqlite3_tokenizer *pTokenizer = 0; /* Tokenizer for this table */ nDb = (int)strlen(argv[1]) + 1; nName = (int)strlen(argv[2]) + 1; for(i=3; i<argc; i++){ char const *z = argv[i]; @@ -99324,19 +99346,69 @@ } static void fts3ColumnlistCopy(char **pp, char **ppPoslist){ char *pEnd = *ppPoslist; char c = 0; + + /* A column-list is terminated by either a 0x01 or 0x00. */ while( 0xFE & (*pEnd | c) ) c = *pEnd++ & 0x80; if( pp ){ int n = (int)(pEnd - *ppPoslist); char *p = *pp; memcpy(p, *ppPoslist, n); p += n; *pp = p; } *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; } /* ** */ @@ -99347,44 +99419,57 @@ ){ char *p = *pp; char *p1 = *pp1; char *p2 = *pp2; - while( *p1 && *p2 ){ - int iCol1 = 0; - int iCol2 = 0; + while( *p1 || *p2 ){ + int iCol1; + int iCol2; + if( *p1==0x01 ) sqlite3Fts3GetVarint32(&p1[1], &iCol1); + else if( *p1==0x00 ) iCol1 = OFFSET_LIST_END; + else iCol1 = 0; + if( *p2==0x01 ) sqlite3Fts3GetVarint32(&p2[1], &iCol2); + else if( *p2==0x00 ) iCol2 = OFFSET_LIST_END; + else iCol2 = 0; if( iCol1==iCol2 ){ 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<i2) ? i1 : i2); + iPrev -= 2; if( i1==i2 ){ - fts3GetDeltaVarint(&p1, &i1); i1 -= 2; - fts3GetDeltaVarint(&p2, &i2); i2 -= 2; + fts3ReadNextPos(&p1, &i1); + fts3ReadNextPos(&p2, &i2); }else if( i1<i2 ){ - fts3GetDeltaVarint(&p1, &i1); i1 -= 2; - }else{ - fts3GetDeltaVarint(&p2, &i2); i2 -= 2; - } - fts3PutDeltaVarint(&p, &iPrev, (i1<i2 ? i1 : i2) + 2); iPrev -= 2; - if( 0==(*p1&0xFE) ) i1 = 0x7FFFFFFF; - if( 0==(*p2&0xFE) ) i2 = 0x7FFFFFFF; - } + fts3ReadNextPos(&p1, &i1); + }else{ + fts3ReadNextPos(&p2, &i2); + } + }while( i1!=OFFSET_LIST_END || i2!=OFFSET_LIST_END ); }else if( iCol1<iCol2 ){ + p1 += fts3PutColNumber(&p, iCol1); fts3ColumnlistCopy(&p, &p1); }else{ + p2 += fts3PutColNumber(&p, iCol2); fts3ColumnlistCopy(&p, &p2); } } *p++ = '\0'; @@ -99447,17 +99532,18 @@ } iSave = isSaveLeft ? iPos1 : iPos2; fts3PutDeltaVarint(&p, &iPrev, iSave+2); iPrev -= 2; pSave = 0; } - if( iPos2<=iPos1 ){ + if( (!isSaveLeft && iPos2<=(iPos1+nToken)) || iPos2<=iPos1 ){ if( (*p2&0xFE)==0 ) break; fts3GetDeltaVarint(&p2, &iPos2); iPos2 -= 2; }else{ if( (*p1&0xFE)==0 ) break; fts3GetDeltaVarint(&p1, &iPos1); iPos1 -= 2; } + } if( pSave && pp ){ p = pSave; } @@ -99500,17 +99586,20 @@ *p++ = 0x00; *pp = p; return 1; } +/* +** Merge two position-lists as required by the NEAR operator. +*/ static int fts3PoslistNearMerge( char **pp, /* Output buffer */ char *aTmp, /* Temporary buffer space */ int nRight, /* Maximum difference in token positions */ int nLeft, /* Maximum difference in token positions */ - char **pp1, /* Left input list */ - char **pp2 /* Right input list */ + char **pp1, /* IN/OUT: Left input list */ + char **pp2 /* IN/OUT: Right input list */ ){ char *p1 = *pp1; char *p2 = *pp2; if( !pp ){ @@ -99593,10 +99682,14 @@ ); if( !aBuffer ){ return SQLITE_NOMEM; } + if( n1==0 && n2==0 ){ + *pnBuffer = 0; + return SQLITE_OK; + } /* Read the first docid from each doclist */ fts3GetDeltaVarint2(&p1, pEnd1, &i1); fts3GetDeltaVarint2(&p2, pEnd2, &i2); @@ -99672,12 +99765,11 @@ } } break; } - case MERGE_POS_NEAR: - case MERGE_NEAR: { + default: assert( mergetype==MERGE_POS_NEAR || mergetype==MERGE_NEAR ); { char *aTmp = 0; char **ppPos = 0; if( mergetype==MERGE_POS_NEAR ){ ppPos = &p; aTmp = sqlite3_malloc(2*(n1+n2)); @@ -99708,13 +99800,10 @@ } } sqlite3_free(aTmp); break; } - - default: - assert(!"Invalid mergetype value passed to fts3DoclistMerge()"); } *pnBuffer = (int)(p-aBuffer); return SQLITE_OK; } @@ -100287,11 +100376,11 @@ sqlite3_value *pVal, /* argv[0] passed to function */ Fts3Cursor **ppCsr /* OUT: Store cursor handle here */ ){ Fts3Cursor *pRet; if( sqlite3_value_type(pVal)!=SQLITE_BLOB - && sqlite3_value_bytes(pVal)!=sizeof(Fts3Cursor *) + || sqlite3_value_bytes(pVal)!=sizeof(Fts3Cursor *) ){ char *zErr = sqlite3_mprintf("illegal first argument to %s", zFunc); sqlite3_result_error(pContext, zErr, -1); sqlite3_free(zErr); return SQLITE_ERROR; @@ -100303,26 +100392,35 @@ /* ** Implementation of the snippet() function for FTS3 */ static void fts3SnippetFunc( - sqlite3_context *pContext, - int argc, - sqlite3_value **argv + sqlite3_context *pContext, /* SQLite function call context */ + int nVal, /* Size of apVal[] array */ + sqlite3_value **apVal /* Array of arguments */ ){ Fts3Cursor *pCsr; /* Cursor handle passed through apVal[0] */ const char *zStart = "<b>"; const char *zEnd = "</b>"; const char *zEllipsis = "<b>...</b>"; - if( argc<1 || argc>4 ) return; - if( fts3FunctionArg(pContext, "snippet", argv[0], &pCsr) ) return; - - switch( argc ){ - case 4: zEllipsis = (const char*)sqlite3_value_text(argv[3]); - case 3: zEnd = (const char*)sqlite3_value_text(argv[2]); - case 2: zStart = (const char*)sqlite3_value_text(argv[1]); + /* There must be at least one argument passed to this function (otherwise + ** the non-overloaded version would have been called instead of this one). + */ + assert( nVal>=1 ); + + if( nVal>4 ){ + sqlite3_result_error(pContext, + "wrong number of arguments to function snippet()", -1); + return; + } + if( fts3FunctionArg(pContext, "snippet", apVal[0], &pCsr) ) return; + + switch( nVal ){ + case 4: zEllipsis = (const char*)sqlite3_value_text(apVal[3]); + case 3: zEnd = (const char*)sqlite3_value_text(apVal[2]); + case 2: zStart = (const char*)sqlite3_value_text(apVal[1]); } sqlite3Fts3Snippet(pContext, pCsr, zStart, zEnd, zEllipsis); } @@ -102669,11 +102767,10 @@ sqlite3_tokenizer_module *m; if( !z ){ zCopy = sqlite3_mprintf("simple"); }else{ - while( (*z&0x80) && isspace(*z) ) z++; if( sqlite3_strnicmp(z, "tokenize", 8) || fts3IsIdChar(z[8])){ return SQLITE_OK; } zCopy = sqlite3_mprintf("%s", &z[8]); *pzTokenizer = zArg;
Modified src/sqlite3.h from [01d7fc5733] to [99a4282d9b].
@@ -119,11 +119,11 @@ ** ** Requirements: [H10011] [H10014] */ #define SQLITE_VERSION "3.6.21" #define SQLITE_VERSION_NUMBER 3006021 -#define SQLITE_SOURCE_ID "2009-12-04 14:25:19 082b8da005128f47f63e95b6b702bf4517221b2a" +#define SQLITE_SOURCE_ID "2009-12-07 16:39:13 1ed88e9d01e9eda5cbc622e7614277f29bcc551c" /* ** CAPI3REF: Run-Time Library Version Numbers {H10020} <S60100> ** KEYWORDS: sqlite3_version **