| | @@ -398,11 +398,11 @@ |
| 398 | 398 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 399 | 399 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 400 | 400 | */ |
| 401 | 401 | #define SQLITE_VERSION "3.19.0" |
| 402 | 402 | #define SQLITE_VERSION_NUMBER 3019000 |
| 403 | | -#define SQLITE_SOURCE_ID "2017-05-11 19:09:19 339df63f4064f3b9c8d4e8b82e72d00b49d9406bc350b14809a4caf7ddc4b736" |
| 403 | +#define SQLITE_SOURCE_ID "2017-05-22 13:58:13 28a94eb282822cad1d1420f2dad6bf65e4b8b9062eda4a0b9ee8270b2c608e40" |
| 404 | 404 | |
| 405 | 405 | /* |
| 406 | 406 | ** CAPI3REF: Run-Time Library Version Numbers |
| 407 | 407 | ** KEYWORDS: sqlite3_version sqlite3_sourceid |
| 408 | 408 | ** |
| | @@ -9671,11 +9671,11 @@ |
| 9671 | 9671 | ** |
| 9672 | 9672 | ** As well as the regular sqlite3changegroup_add() and |
| 9673 | 9673 | ** sqlite3changegroup_output() functions, also available are the streaming |
| 9674 | 9674 | ** versions sqlite3changegroup_add_strm() and sqlite3changegroup_output_strm(). |
| 9675 | 9675 | */ |
| 9676 | | -int sqlite3changegroup_new(sqlite3_changegroup **pp); |
| 9676 | +SQLITE_API int sqlite3changegroup_new(sqlite3_changegroup **pp); |
| 9677 | 9677 | |
| 9678 | 9678 | /* |
| 9679 | 9679 | ** CAPI3REF: Add A Changeset To A Changegroup |
| 9680 | 9680 | ** |
| 9681 | 9681 | ** Add all changes within the changeset (or patchset) in buffer pData (size |
| | @@ -9748,11 +9748,11 @@ |
| 9748 | 9748 | ** function returns SQLITE_NOMEM. In all cases, if an error occurs the |
| 9749 | 9749 | ** final contents of the changegroup is undefined. |
| 9750 | 9750 | ** |
| 9751 | 9751 | ** If no error occurs, SQLITE_OK is returned. |
| 9752 | 9752 | */ |
| 9753 | | -int sqlite3changegroup_add(sqlite3_changegroup*, int nData, void *pData); |
| 9753 | +SQLITE_API int sqlite3changegroup_add(sqlite3_changegroup*, int nData, void *pData); |
| 9754 | 9754 | |
| 9755 | 9755 | /* |
| 9756 | 9756 | ** CAPI3REF: Obtain A Composite Changeset From A Changegroup |
| 9757 | 9757 | ** |
| 9758 | 9758 | ** Obtain a buffer containing a changeset (or patchset) representing the |
| | @@ -9774,20 +9774,20 @@ |
| 9774 | 9774 | ** is returned and the output variables are set to the size of and a |
| 9775 | 9775 | ** pointer to the output buffer, respectively. In this case it is the |
| 9776 | 9776 | ** responsibility of the caller to eventually free the buffer using a |
| 9777 | 9777 | ** call to sqlite3_free(). |
| 9778 | 9778 | */ |
| 9779 | | -int sqlite3changegroup_output( |
| 9779 | +SQLITE_API int sqlite3changegroup_output( |
| 9780 | 9780 | sqlite3_changegroup*, |
| 9781 | 9781 | int *pnData, /* OUT: Size of output buffer in bytes */ |
| 9782 | 9782 | void **ppData /* OUT: Pointer to output buffer */ |
| 9783 | 9783 | ); |
| 9784 | 9784 | |
| 9785 | 9785 | /* |
| 9786 | 9786 | ** CAPI3REF: Delete A Changegroup Object |
| 9787 | 9787 | */ |
| 9788 | | -void sqlite3changegroup_delete(sqlite3_changegroup*); |
| 9788 | +SQLITE_API void sqlite3changegroup_delete(sqlite3_changegroup*); |
| 9789 | 9789 | |
| 9790 | 9790 | /* |
| 9791 | 9791 | ** CAPI3REF: Apply A Changeset To A Database |
| 9792 | 9792 | ** |
| 9793 | 9793 | ** Apply a changeset to a database. This function attempts to update the |
| | @@ -10172,15 +10172,15 @@ |
| 10172 | 10172 | SQLITE_API int sqlite3session_patchset_strm( |
| 10173 | 10173 | sqlite3_session *pSession, |
| 10174 | 10174 | int (*xOutput)(void *pOut, const void *pData, int nData), |
| 10175 | 10175 | void *pOut |
| 10176 | 10176 | ); |
| 10177 | | -int sqlite3changegroup_add_strm(sqlite3_changegroup*, |
| 10177 | +SQLITE_API int sqlite3changegroup_add_strm(sqlite3_changegroup*, |
| 10178 | 10178 | int (*xInput)(void *pIn, void *pData, int *pnData), |
| 10179 | 10179 | void *pIn |
| 10180 | 10180 | ); |
| 10181 | | -int sqlite3changegroup_output_strm(sqlite3_changegroup*, |
| 10181 | +SQLITE_API int sqlite3changegroup_output_strm(sqlite3_changegroup*, |
| 10182 | 10182 | int (*xOutput)(void *pOut, const void *pData, int nData), |
| 10183 | 10183 | void *pOut |
| 10184 | 10184 | ); |
| 10185 | 10185 | |
| 10186 | 10186 | |
| | @@ -82388,14 +82388,16 @@ |
| 82388 | 82388 | } |
| 82389 | 82389 | #endif |
| 82390 | 82390 | pIdxKey = &r; |
| 82391 | 82391 | pFree = 0; |
| 82392 | 82392 | }else{ |
| 82393 | + assert( pIn3->flags & MEM_Blob ); |
| 82394 | + rc = ExpandBlob(pIn3); |
| 82395 | + assert( rc==SQLITE_OK || rc==SQLITE_NOMEM ); |
| 82396 | + if( rc ) goto no_mem; |
| 82393 | 82397 | pFree = pIdxKey = sqlite3VdbeAllocUnpackedRecord(pC->pKeyInfo); |
| 82394 | 82398 | if( pIdxKey==0 ) goto no_mem; |
| 82395 | | - assert( pIn3->flags & MEM_Blob ); |
| 82396 | | - (void)ExpandBlob(pIn3); |
| 82397 | 82399 | sqlite3VdbeRecordUnpack(pC->pKeyInfo, pIn3->n, pIn3->z, pIdxKey); |
| 82398 | 82400 | } |
| 82399 | 82401 | pIdxKey->default_rc = 0; |
| 82400 | 82402 | takeJump = 0; |
| 82401 | 82403 | if( pOp->opcode==OP_NoConflict ){ |
| | @@ -91239,11 +91241,10 @@ |
| 91239 | 91241 | }else{ |
| 91240 | 91242 | return 1; |
| 91241 | 91243 | } |
| 91242 | 91244 | } |
| 91243 | 91245 | |
| 91244 | | -#ifndef SQLITE_OMIT_SUBQUERY |
| 91245 | 91246 | /* |
| 91246 | 91247 | ** Return a pointer to a subexpression of pVector that is the i-th |
| 91247 | 91248 | ** column of the vector (numbered starting with 0). The caller must |
| 91248 | 91249 | ** ensure that i is within range. |
| 91249 | 91250 | ** |
| | @@ -91267,13 +91268,11 @@ |
| 91267 | 91268 | return pVector->x.pList->a[i].pExpr; |
| 91268 | 91269 | } |
| 91269 | 91270 | } |
| 91270 | 91271 | return pVector; |
| 91271 | 91272 | } |
| 91272 | | -#endif /* !defined(SQLITE_OMIT_SUBQUERY) */ |
| 91273 | 91273 | |
| 91274 | | -#ifndef SQLITE_OMIT_SUBQUERY |
| 91275 | 91274 | /* |
| 91276 | 91275 | ** Compute and return a new Expr object which when passed to |
| 91277 | 91276 | ** sqlite3ExprCode() will generate all necessary code to compute |
| 91278 | 91277 | ** the iField-th column of the vector expression pVector. |
| 91279 | 91278 | ** |
| | @@ -91327,11 +91326,10 @@ |
| 91327 | 91326 | if( pVector->op==TK_VECTOR ) pVector = pVector->x.pList->a[iField].pExpr; |
| 91328 | 91327 | pRet = sqlite3ExprDup(pParse->db, pVector, 0); |
| 91329 | 91328 | } |
| 91330 | 91329 | return pRet; |
| 91331 | 91330 | } |
| 91332 | | -#endif /* !define(SQLITE_OMIT_SUBQUERY) */ |
| 91333 | 91331 | |
| 91334 | 91332 | /* |
| 91335 | 91333 | ** If expression pExpr is of type TK_SELECT, generate code to evaluate |
| 91336 | 91334 | ** it. Return the register in which the result is stored (or, if the |
| 91337 | 91335 | ** sub-select returns more than one column, the first in an array |
| | @@ -94298,11 +94296,15 @@ |
| 94298 | 94296 | if( nResult==1 ){ |
| 94299 | 94297 | iResult = sqlite3ExprCodeTemp(pParse, p, piFreeable); |
| 94300 | 94298 | }else{ |
| 94301 | 94299 | *piFreeable = 0; |
| 94302 | 94300 | if( p->op==TK_SELECT ){ |
| 94301 | +#if SQLITE_OMIT_SUBQUERY |
| 94302 | + iResult = 0; |
| 94303 | +#else |
| 94303 | 94304 | iResult = sqlite3CodeSubselect(pParse, p, 0, 0); |
| 94305 | +#endif |
| 94304 | 94306 | }else{ |
| 94305 | 94307 | int i; |
| 94306 | 94308 | iResult = pParse->nMem+1; |
| 94307 | 94309 | pParse->nMem += nResult; |
| 94308 | 94310 | for(i=0; i<nResult; i++){ |
| | @@ -185267,13 +185269,15 @@ |
| 185267 | 185269 | Fts5Buffer *pBuf, |
| 185268 | 185270 | u32 nData, |
| 185269 | 185271 | const u8 *pData |
| 185270 | 185272 | ){ |
| 185271 | 185273 | assert_nc( *pRc || nData>=0 ); |
| 185272 | | - if( fts5BufferGrow(pRc, pBuf, nData) ) return; |
| 185273 | | - memcpy(&pBuf->p[pBuf->n], pData, nData); |
| 185274 | | - pBuf->n += nData; |
| 185274 | + if( nData ){ |
| 185275 | + if( fts5BufferGrow(pRc, pBuf, nData) ) return; |
| 185276 | + memcpy(&pBuf->p[pBuf->n], pData, nData); |
| 185277 | + pBuf->n += nData; |
| 185278 | + } |
| 185275 | 185279 | } |
| 185276 | 185280 | |
| 185277 | 185281 | /* |
| 185278 | 185282 | ** Append the nul-terminated string zStr to the buffer pBuf. This function |
| 185279 | 185283 | ** ensures that the byte following the buffer data is set to 0x00, even |
| | @@ -185446,12 +185450,12 @@ |
| 185446 | 185450 | |
| 185447 | 185451 | static void *sqlite3Fts5MallocZero(int *pRc, int nByte){ |
| 185448 | 185452 | void *pRet = 0; |
| 185449 | 185453 | if( *pRc==SQLITE_OK ){ |
| 185450 | 185454 | pRet = sqlite3_malloc(nByte); |
| 185451 | | - if( pRet==0 && nByte>0 ){ |
| 185452 | | - *pRc = SQLITE_NOMEM; |
| 185455 | + if( pRet==0 ){ |
| 185456 | + if( nByte>0 ) *pRc = SQLITE_NOMEM; |
| 185453 | 185457 | }else{ |
| 185454 | 185458 | memset(pRet, 0, nByte); |
| 185455 | 185459 | } |
| 185456 | 185460 | } |
| 185457 | 185461 | return pRet; |
| | @@ -189408,13 +189412,14 @@ |
| 189408 | 189412 | Fts5HashEntry **aSlot; /* Array of hash slots */ |
| 189409 | 189413 | }; |
| 189410 | 189414 | |
| 189411 | 189415 | /* |
| 189412 | 189416 | ** Each entry in the hash table is represented by an object of the |
| 189413 | | -** following type. Each object, its key (zKey[]) and its current data |
| 189414 | | -** are stored in a single memory allocation. The position list data |
| 189415 | | -** immediately follows the key data in memory. |
| 189417 | +** following type. Each object, its key (a nul-terminated string) and |
| 189418 | +** its current data are stored in a single memory allocation. The |
| 189419 | +** key immediately follows the object in memory. The position list |
| 189420 | +** data immediately follows the key data in memory. |
| 189416 | 189421 | ** |
| 189417 | 189422 | ** The data that follows the key is in a similar, but not identical format |
| 189418 | 189423 | ** to the doclist data stored in the database. It is: |
| 189419 | 189424 | ** |
| 189420 | 189425 | ** * Rowid, as a varint |
| | @@ -189434,24 +189439,24 @@ |
| 189434 | 189439 | Fts5HashEntry *pScanNext; /* Next entry in sorted order */ |
| 189435 | 189440 | |
| 189436 | 189441 | int nAlloc; /* Total size of allocation */ |
| 189437 | 189442 | int iSzPoslist; /* Offset of space for 4-byte poslist size */ |
| 189438 | 189443 | int nData; /* Total bytes of data (incl. structure) */ |
| 189439 | | - int nKey; /* Length of zKey[] in bytes */ |
| 189444 | + int nKey; /* Length of key in bytes */ |
| 189440 | 189445 | u8 bDel; /* Set delete-flag @ iSzPoslist */ |
| 189441 | 189446 | u8 bContent; /* Set content-flag (detail=none mode) */ |
| 189442 | 189447 | i16 iCol; /* Column of last value written */ |
| 189443 | 189448 | int iPos; /* Position of last value written */ |
| 189444 | 189449 | i64 iRowid; /* Rowid of last value written */ |
| 189445 | | - char zKey[8]; /* Nul-terminated entry key */ |
| 189446 | 189450 | }; |
| 189447 | 189451 | |
| 189448 | 189452 | /* |
| 189449 | | -** Size of Fts5HashEntry without the zKey[] array. |
| 189453 | +** Eqivalent to: |
| 189454 | +** |
| 189455 | +** char *fts5EntryKey(Fts5HashEntry *pEntry){ return zKey; } |
| 189450 | 189456 | */ |
| 189451 | | -#define FTS5_HASHENTRYSIZE (sizeof(Fts5HashEntry)-8) |
| 189452 | | - |
| 189457 | +#define fts5EntryKey(p) ( ((char *)(&(p)[1])) ) |
| 189453 | 189458 | |
| 189454 | 189459 | |
| 189455 | 189460 | /* |
| 189456 | 189461 | ** Allocate a new hash table. |
| 189457 | 189462 | */ |
| | @@ -189545,11 +189550,11 @@ |
| 189545 | 189550 | for(i=0; i<pHash->nSlot; i++){ |
| 189546 | 189551 | while( apOld[i] ){ |
| 189547 | 189552 | int iHash; |
| 189548 | 189553 | Fts5HashEntry *p = apOld[i]; |
| 189549 | 189554 | apOld[i] = p->pHashNext; |
| 189550 | | - iHash = fts5HashKey(nNew, (u8*)p->zKey, (int)strlen(p->zKey)); |
| 189555 | + iHash = fts5HashKey(nNew, (u8*)fts5EntryKey(p), strlen(fts5EntryKey(p))); |
| 189551 | 189556 | p->pHashNext = apNew[iHash]; |
| 189552 | 189557 | apNew[iHash] = p; |
| 189553 | 189558 | } |
| 189554 | 189559 | } |
| 189555 | 189560 | |
| | @@ -189616,22 +189621,24 @@ |
| 189616 | 189621 | bNew = (pHash->eDetail==FTS5_DETAIL_FULL); |
| 189617 | 189622 | |
| 189618 | 189623 | /* Attempt to locate an existing hash entry */ |
| 189619 | 189624 | iHash = fts5HashKey2(pHash->nSlot, (u8)bByte, (const u8*)pToken, nToken); |
| 189620 | 189625 | for(p=pHash->aSlot[iHash]; p; p=p->pHashNext){ |
| 189621 | | - if( p->zKey[0]==bByte |
| 189626 | + char *zKey = fts5EntryKey(p); |
| 189627 | + if( zKey[0]==bByte |
| 189622 | 189628 | && p->nKey==nToken |
| 189623 | | - && memcmp(&p->zKey[1], pToken, nToken)==0 |
| 189629 | + && memcmp(&zKey[1], pToken, nToken)==0 |
| 189624 | 189630 | ){ |
| 189625 | 189631 | break; |
| 189626 | 189632 | } |
| 189627 | 189633 | } |
| 189628 | 189634 | |
| 189629 | 189635 | /* If an existing hash entry cannot be found, create a new one. */ |
| 189630 | 189636 | if( p==0 ){ |
| 189631 | 189637 | /* Figure out how much space to allocate */ |
| 189632 | | - int nByte = FTS5_HASHENTRYSIZE + (nToken+1) + 1 + 64; |
| 189638 | + char *zKey; |
| 189639 | + int nByte = sizeof(Fts5HashEntry) + (nToken+1) + 1 + 64; |
| 189633 | 189640 | if( nByte<128 ) nByte = 128; |
| 189634 | 189641 | |
| 189635 | 189642 | /* Grow the Fts5Hash.aSlot[] array if necessary. */ |
| 189636 | 189643 | if( (pHash->nEntry*2)>=pHash->nSlot ){ |
| 189637 | 189644 | int rc = fts5HashResize(pHash); |
| | @@ -189640,18 +189647,19 @@ |
| 189640 | 189647 | } |
| 189641 | 189648 | |
| 189642 | 189649 | /* Allocate new Fts5HashEntry and add it to the hash table. */ |
| 189643 | 189650 | p = (Fts5HashEntry*)sqlite3_malloc(nByte); |
| 189644 | 189651 | if( !p ) return SQLITE_NOMEM; |
| 189645 | | - memset(p, 0, FTS5_HASHENTRYSIZE); |
| 189652 | + memset(p, 0, sizeof(Fts5HashEntry)); |
| 189646 | 189653 | p->nAlloc = nByte; |
| 189647 | | - p->zKey[0] = bByte; |
| 189648 | | - memcpy(&p->zKey[1], pToken, nToken); |
| 189649 | | - assert( iHash==fts5HashKey(pHash->nSlot, (u8*)p->zKey, nToken+1) ); |
| 189654 | + zKey = fts5EntryKey(p); |
| 189655 | + zKey[0] = bByte; |
| 189656 | + memcpy(&zKey[1], pToken, nToken); |
| 189657 | + assert( iHash==fts5HashKey(pHash->nSlot, (u8*)zKey, nToken+1) ); |
| 189650 | 189658 | p->nKey = nToken; |
| 189651 | | - p->zKey[nToken+1] = '\0'; |
| 189652 | | - p->nData = nToken+1 + 1 + FTS5_HASHENTRYSIZE; |
| 189659 | + zKey[nToken+1] = '\0'; |
| 189660 | + p->nData = nToken+1 + 1 + sizeof(Fts5HashEntry); |
| 189653 | 189661 | p->pHashNext = pHash->aSlot[iHash]; |
| 189654 | 189662 | pHash->aSlot[iHash] = p; |
| 189655 | 189663 | pHash->nEntry++; |
| 189656 | 189664 | |
| 189657 | 189665 | /* Add the first rowid field to the hash-entry */ |
| | @@ -189765,13 +189773,15 @@ |
| 189765 | 189773 | }else if( p2==0 ){ |
| 189766 | 189774 | *ppOut = p1; |
| 189767 | 189775 | p1 = 0; |
| 189768 | 189776 | }else{ |
| 189769 | 189777 | int i = 0; |
| 189770 | | - while( p1->zKey[i]==p2->zKey[i] ) i++; |
| 189778 | + char *zKey1 = fts5EntryKey(p1); |
| 189779 | + char *zKey2 = fts5EntryKey(p2); |
| 189780 | + while( zKey1[i]==zKey2[i] ) i++; |
| 189771 | 189781 | |
| 189772 | | - if( ((u8)p1->zKey[i])>((u8)p2->zKey[i]) ){ |
| 189782 | + if( ((u8)zKey1[i])>((u8)zKey2[i]) ){ |
| 189773 | 189783 | /* p2 is smaller */ |
| 189774 | 189784 | *ppOut = p2; |
| 189775 | 189785 | ppOut = &p2->pScanNext; |
| 189776 | 189786 | p2 = p2->pScanNext; |
| 189777 | 189787 | }else{ |
| | @@ -189810,11 +189820,11 @@ |
| 189810 | 189820 | memset(ap, 0, sizeof(Fts5HashEntry*) * nMergeSlot); |
| 189811 | 189821 | |
| 189812 | 189822 | for(iSlot=0; iSlot<pHash->nSlot; iSlot++){ |
| 189813 | 189823 | Fts5HashEntry *pIter; |
| 189814 | 189824 | for(pIter=pHash->aSlot[iSlot]; pIter; pIter=pIter->pHashNext){ |
| 189815 | | - if( pTerm==0 || 0==memcmp(pIter->zKey, pTerm, nTerm) ){ |
| 189825 | + if( pTerm==0 || 0==memcmp(fts5EntryKey(pIter), pTerm, nTerm) ){ |
| 189816 | 189826 | Fts5HashEntry *pEntry = pIter; |
| 189817 | 189827 | pEntry->pScanNext = 0; |
| 189818 | 189828 | for(i=0; ap[i]; i++){ |
| 189819 | 189829 | pEntry = fts5HashEntryMerge(pEntry, ap[i]); |
| 189820 | 189830 | ap[i] = 0; |
| | @@ -189843,20 +189853,22 @@ |
| 189843 | 189853 | const char *pTerm, int nTerm, /* Query term */ |
| 189844 | 189854 | const u8 **ppDoclist, /* OUT: Pointer to doclist for pTerm */ |
| 189845 | 189855 | int *pnDoclist /* OUT: Size of doclist in bytes */ |
| 189846 | 189856 | ){ |
| 189847 | 189857 | unsigned int iHash = fts5HashKey(pHash->nSlot, (const u8*)pTerm, nTerm); |
| 189858 | + char *zKey; |
| 189848 | 189859 | Fts5HashEntry *p; |
| 189849 | 189860 | |
| 189850 | 189861 | for(p=pHash->aSlot[iHash]; p; p=p->pHashNext){ |
| 189851 | | - if( memcmp(p->zKey, pTerm, nTerm)==0 && p->zKey[nTerm]==0 ) break; |
| 189862 | + zKey = fts5EntryKey(p); |
| 189863 | + if( memcmp(zKey, pTerm, nTerm)==0 && zKey[nTerm]==0 ) break; |
| 189852 | 189864 | } |
| 189853 | 189865 | |
| 189854 | 189866 | if( p ){ |
| 189855 | 189867 | fts5HashAddPoslistSize(pHash, p); |
| 189856 | | - *ppDoclist = (const u8*)&p->zKey[nTerm+1]; |
| 189857 | | - *pnDoclist = p->nData - (FTS5_HASHENTRYSIZE + nTerm + 1); |
| 189868 | + *ppDoclist = (const u8*)&zKey[nTerm+1]; |
| 189869 | + *pnDoclist = p->nData - (sizeof(Fts5HashEntry) + nTerm + 1); |
| 189858 | 189870 | }else{ |
| 189859 | 189871 | *ppDoclist = 0; |
| 189860 | 189872 | *pnDoclist = 0; |
| 189861 | 189873 | } |
| 189862 | 189874 | |
| | @@ -189885,15 +189897,16 @@ |
| 189885 | 189897 | const u8 **ppDoclist, /* OUT: pointer to doclist */ |
| 189886 | 189898 | int *pnDoclist /* OUT: size of doclist in bytes */ |
| 189887 | 189899 | ){ |
| 189888 | 189900 | Fts5HashEntry *p; |
| 189889 | 189901 | if( (p = pHash->pScan) ){ |
| 189890 | | - int nTerm = (int)strlen(p->zKey); |
| 189902 | + char *zKey = fts5EntryKey(p); |
| 189903 | + int nTerm = (int)strlen(zKey); |
| 189891 | 189904 | fts5HashAddPoslistSize(pHash, p); |
| 189892 | | - *pzTerm = p->zKey; |
| 189893 | | - *ppDoclist = (const u8*)&p->zKey[nTerm+1]; |
| 189894 | | - *pnDoclist = p->nData - (FTS5_HASHENTRYSIZE + nTerm + 1); |
| 189905 | + *pzTerm = zKey; |
| 189906 | + *ppDoclist = (const u8*)&zKey[nTerm+1]; |
| 189907 | + *pnDoclist = p->nData - (sizeof(Fts5HashEntry) + nTerm + 1); |
| 189895 | 189908 | }else{ |
| 189896 | 189909 | *pzTerm = 0; |
| 189897 | 189910 | *ppDoclist = 0; |
| 189898 | 189911 | *pnDoclist = 0; |
| 189899 | 189912 | } |
| | @@ -194993,11 +195006,11 @@ |
| 194993 | 195006 | |
| 194994 | 195007 | pData = fts5IdxMalloc(p, sizeof(Fts5Data) + doclist.n); |
| 194995 | 195008 | if( pData ){ |
| 194996 | 195009 | pData->p = (u8*)&pData[1]; |
| 194997 | 195010 | pData->nn = pData->szLeaf = doclist.n; |
| 194998 | | - memcpy(pData->p, doclist.p, doclist.n); |
| 195011 | + if( doclist.n ) memcpy(pData->p, doclist.p, doclist.n); |
| 194999 | 195012 | fts5MultiIterNew2(p, pData, bDesc, ppIter); |
| 195000 | 195013 | } |
| 195001 | 195014 | fts5BufferFree(&doclist); |
| 195002 | 195015 | } |
| 195003 | 195016 | |
| | @@ -195232,11 +195245,11 @@ |
| 195232 | 195245 | /* If the QUERY_SCAN flag is set, all other flags must be clear. */ |
| 195233 | 195246 | assert( (flags & FTS5INDEX_QUERY_SCAN)==0 || flags==FTS5INDEX_QUERY_SCAN ); |
| 195234 | 195247 | |
| 195235 | 195248 | if( sqlite3Fts5BufferSize(&p->rc, &buf, nToken+1)==0 ){ |
| 195236 | 195249 | int iIdx = 0; /* Index to search */ |
| 195237 | | - memcpy(&buf.p[1], pToken, nToken); |
| 195250 | + if( nToken ) memcpy(&buf.p[1], pToken, nToken); |
| 195238 | 195251 | |
| 195239 | 195252 | /* Figure out which index to search and set iIdx accordingly. If this |
| 195240 | 195253 | ** is a prefix query for which there is no prefix index, set iIdx to |
| 195241 | 195254 | ** greater than pConfig->nPrefix to indicate that the query will be |
| 195242 | 195255 | ** satisfied by scanning multiple terms in the main index. |
| | @@ -195281,11 +195294,11 @@ |
| 195281 | 195294 | if( pSeg->pLeaf ) pRet->xSetOutputs(pRet, pSeg); |
| 195282 | 195295 | } |
| 195283 | 195296 | } |
| 195284 | 195297 | |
| 195285 | 195298 | if( p->rc ){ |
| 195286 | | - sqlite3Fts5IterClose(&pRet->base); |
| 195299 | + sqlite3Fts5IterClose((Fts5IndexIter*)pRet); |
| 195287 | 195300 | pRet = 0; |
| 195288 | 195301 | fts5CloseReader(p); |
| 195289 | 195302 | } |
| 195290 | 195303 | |
| 195291 | 195304 | *ppIter = &pRet->base; |
| | @@ -199021,11 +199034,11 @@ |
| 199021 | 199034 | int nArg, /* Number of args */ |
| 199022 | 199035 | sqlite3_value **apUnused /* Function arguments */ |
| 199023 | 199036 | ){ |
| 199024 | 199037 | assert( nArg==0 ); |
| 199025 | 199038 | UNUSED_PARAM2(nArg, apUnused); |
| 199026 | | - sqlite3_result_text(pCtx, "fts5: 2017-05-11 19:09:19 339df63f4064f3b9c8d4e8b82e72d00b49d9406bc350b14809a4caf7ddc4b736", -1, SQLITE_TRANSIENT); |
| 199039 | + sqlite3_result_text(pCtx, "fts5: 2017-05-22 13:58:13 28a94eb282822cad1d1420f2dad6bf65e4b8b9062eda4a0b9ee8270b2c608e40", -1, SQLITE_TRANSIENT); |
| 199027 | 199040 | } |
| 199028 | 199041 | |
| 199029 | 199042 | static int fts5Init(sqlite3 *db){ |
| 199030 | 199043 | static const sqlite3_module fts5Mod = { |
| 199031 | 199044 | /* iVersion */ 2, |
| 199032 | 199045 | |