| | @@ -452,11 +452,11 @@ |
| 452 | 452 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 453 | 453 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 454 | 454 | */ |
| 455 | 455 | #define SQLITE_VERSION "3.41.0" |
| 456 | 456 | #define SQLITE_VERSION_NUMBER 3041000 |
| 457 | | -#define SQLITE_SOURCE_ID "2023-01-16 18:13:00 83f21285fe86430a66ce6841606e3ad7c27da52ac75a034c6a00c7a9fdb9791d" |
| 457 | +#define SQLITE_SOURCE_ID "2023-01-27 07:53:49 eabb551b8b3d33fc3a327ecf7225436a3a3f616901e22c868fd76a5e3adc7b3f" |
| 458 | 458 | |
| 459 | 459 | /* |
| 460 | 460 | ** CAPI3REF: Run-Time Library Version Numbers |
| 461 | 461 | ** KEYWORDS: sqlite3_version sqlite3_sourceid |
| 462 | 462 | ** |
| | @@ -10110,18 +10110,17 @@ |
| 10110 | 10110 | ** [xFilter|xFilter() method] of a [virtual table] implementation. |
| 10111 | 10111 | ** The result of invoking these interfaces from any other context |
| 10112 | 10112 | ** is undefined and probably harmful. |
| 10113 | 10113 | ** |
| 10114 | 10114 | ** The X parameter in a call to sqlite3_vtab_in_first(X,P) or |
| 10115 | | -** sqlite3_vtab_in_next(X,P) must be one of the parameters to the |
| 10115 | +** sqlite3_vtab_in_next(X,P) should be one of the parameters to the |
| 10116 | 10116 | ** xFilter method which invokes these routines, and specifically |
| 10117 | 10117 | ** a parameter that was previously selected for all-at-once IN constraint |
| 10118 | 10118 | ** processing use the [sqlite3_vtab_in()] interface in the |
| 10119 | 10119 | ** [xBestIndex|xBestIndex method]. ^(If the X parameter is not |
| 10120 | 10120 | ** an xFilter argument that was selected for all-at-once IN constraint |
| 10121 | | -** processing, then these routines return [SQLITE_MISUSE])^ or perhaps |
| 10122 | | -** exhibit some other undefined or harmful behavior. |
| 10121 | +** processing, then these routines return [SQLITE_ERROR].)^ |
| 10123 | 10122 | ** |
| 10124 | 10123 | ** ^(Use these routines to access all values on the right-hand side |
| 10125 | 10124 | ** of the IN constraint using code like the following: |
| 10126 | 10125 | ** |
| 10127 | 10126 | ** <blockquote><pre> |
| | @@ -23039,10 +23038,12 @@ |
| 23039 | 23038 | SQLITE_PRIVATE int sqlite3VdbeSorterRowkey(const VdbeCursor *, Mem *); |
| 23040 | 23039 | SQLITE_PRIVATE int sqlite3VdbeSorterNext(sqlite3 *, const VdbeCursor *); |
| 23041 | 23040 | SQLITE_PRIVATE int sqlite3VdbeSorterRewind(const VdbeCursor *, int *); |
| 23042 | 23041 | SQLITE_PRIVATE int sqlite3VdbeSorterWrite(const VdbeCursor *, Mem *); |
| 23043 | 23042 | SQLITE_PRIVATE int sqlite3VdbeSorterCompare(const VdbeCursor *, Mem *, int, int *); |
| 23043 | + |
| 23044 | +SQLITE_PRIVATE void sqlite3VdbeValueListFree(void*); |
| 23044 | 23045 | |
| 23045 | 23046 | #ifdef SQLITE_DEBUG |
| 23046 | 23047 | SQLITE_PRIVATE void sqlite3VdbeIncrWriteCounter(Vdbe*, VdbeCursor*); |
| 23047 | 23048 | SQLITE_PRIVATE void sqlite3VdbeAssertAbortable(Vdbe*); |
| 23048 | 23049 | #else |
| | @@ -58359,11 +58360,11 @@ |
| 58359 | 58360 | if( rc==SQLITE_OK && zSuper[0] && res ){ |
| 58360 | 58361 | /* If there was a super-journal and this routine will return success, |
| 58361 | 58362 | ** see if it is possible to delete the super-journal. |
| 58362 | 58363 | */ |
| 58363 | 58364 | assert( zSuper==&pPager->pTmpSpace[4] ); |
| 58364 | | - memset(&zSuper[-4], 0, 4); |
| 58365 | + memset(pPager->pTmpSpace, 0, 4); |
| 58365 | 58366 | rc = pager_delsuper(pPager, zSuper); |
| 58366 | 58367 | testcase( rc!=SQLITE_OK ); |
| 58367 | 58368 | } |
| 58368 | 58369 | if( isHot && nPlayback ){ |
| 58369 | 58370 | sqlite3_log(SQLITE_NOTICE_RECOVER_ROLLBACK, "recovered %d pages from %s", |
| | @@ -88576,10 +88577,21 @@ |
| 88576 | 88577 | */ |
| 88577 | 88578 | SQLITE_API int sqlite3_vtab_nochange(sqlite3_context *p){ |
| 88578 | 88579 | assert( p ); |
| 88579 | 88580 | return sqlite3_value_nochange(p->pOut); |
| 88580 | 88581 | } |
| 88582 | + |
| 88583 | +/* |
| 88584 | +** The destructor function for a ValueList object. This needs to be |
| 88585 | +** a separate function, unknowable to the application, to ensure that |
| 88586 | +** calls to sqlite3_vtab_in_first()/sqlite3_vtab_in_next() that are not |
| 88587 | +** preceeded by activation of IN processing via sqlite3_vtab_int() do not |
| 88588 | +** try to access a fake ValueList object inserted by a hostile extension. |
| 88589 | +*/ |
| 88590 | +SQLITE_PRIVATE void sqlite3VdbeValueListFree(void *pToDelete){ |
| 88591 | + sqlite3_free(pToDelete); |
| 88592 | +} |
| 88581 | 88593 | |
| 88582 | 88594 | /* |
| 88583 | 88595 | ** Implementation of sqlite3_vtab_in_first() (if bNext==0) and |
| 88584 | 88596 | ** sqlite3_vtab_in_next() (if bNext!=0). |
| 88585 | 88597 | */ |
| | @@ -88591,12 +88603,19 @@ |
| 88591 | 88603 | int rc; |
| 88592 | 88604 | ValueList *pRhs; |
| 88593 | 88605 | |
| 88594 | 88606 | *ppOut = 0; |
| 88595 | 88607 | if( pVal==0 ) return SQLITE_MISUSE; |
| 88596 | | - pRhs = (ValueList*)sqlite3_value_pointer(pVal, "ValueList"); |
| 88597 | | - if( pRhs==0 ) return SQLITE_MISUSE; |
| 88608 | + if( (pVal->flags & MEM_Dyn)==0 || pVal->xDel!=sqlite3VdbeValueListFree ){ |
| 88609 | + return SQLITE_ERROR; |
| 88610 | + }else{ |
| 88611 | + assert( (pVal->flags&(MEM_TypeMask|MEM_Term|MEM_Subtype)) == |
| 88612 | + (MEM_Null|MEM_Term|MEM_Subtype) ); |
| 88613 | + assert( pVal->eSubtype=='p' ); |
| 88614 | + assert( pVal->u.zPType!=0 && strcmp(pVal->u.zPType,"ValueList")==0 ); |
| 88615 | + pRhs = (ValueList*)pVal->z; |
| 88616 | + } |
| 88598 | 88617 | if( bNext ){ |
| 88599 | 88618 | rc = sqlite3BtreeNext(pRhs->pCsr, 0); |
| 88600 | 88619 | }else{ |
| 88601 | 88620 | int dummy = 0; |
| 88602 | 88621 | rc = sqlite3BtreeFirst(pRhs->pCsr, &dummy); |
| | @@ -92358,11 +92377,11 @@ |
| 92358 | 92377 | affinity = pOp->p5 & SQLITE_AFF_MASK; |
| 92359 | 92378 | if( affinity>=SQLITE_AFF_NUMERIC ){ |
| 92360 | 92379 | if( (flags1 | flags3)&MEM_Str ){ |
| 92361 | 92380 | if( (flags1 & (MEM_Int|MEM_IntReal|MEM_Real|MEM_Str))==MEM_Str ){ |
| 92362 | 92381 | applyNumericAffinity(pIn1,0); |
| 92363 | | - testcase( flags3==pIn3->flags ); |
| 92382 | + assert( flags3==pIn3->flags || CORRUPT_DB ); |
| 92364 | 92383 | flags3 = pIn3->flags; |
| 92365 | 92384 | } |
| 92366 | 92385 | if( (flags3 & (MEM_Int|MEM_IntReal|MEM_Real|MEM_Str))==MEM_Str ){ |
| 92367 | 92386 | applyNumericAffinity(pIn3,0); |
| 92368 | 92387 | } |
| | @@ -98195,11 +98214,11 @@ |
| 98195 | 98214 | if( pRhs==0 ) goto no_mem; |
| 98196 | 98215 | pRhs->pCsr = pC->uc.pCursor; |
| 98197 | 98216 | pRhs->pOut = &aMem[pOp->p3]; |
| 98198 | 98217 | pOut = out2Prerelease(p, pOp); |
| 98199 | 98218 | pOut->flags = MEM_Null; |
| 98200 | | - sqlite3VdbeMemSetPointer(pOut, pRhs, "ValueList", sqlite3_free); |
| 98219 | + sqlite3VdbeMemSetPointer(pOut, pRhs, "ValueList", sqlite3VdbeValueListFree); |
| 98201 | 98220 | break; |
| 98202 | 98221 | } |
| 98203 | 98222 | #endif /* SQLITE_OMIT_VIRTUALTABLE */ |
| 98204 | 98223 | |
| 98205 | 98224 | |
| | @@ -116559,11 +116578,11 @@ |
| 116559 | 116578 | const char *zFile; |
| 116560 | 116579 | char *zPath = 0; |
| 116561 | 116580 | char *zErr = 0; |
| 116562 | 116581 | unsigned int flags; |
| 116563 | 116582 | Db *aNew; /* New array of Db pointers */ |
| 116564 | | - Db *pNew; /* Db object for the newly attached database */ |
| 116583 | + Db *pNew = 0; /* Db object for the newly attached database */ |
| 116565 | 116584 | char *zErrDyn = 0; |
| 116566 | 116585 | sqlite3_vfs *pVfs; |
| 116567 | 116586 | |
| 116568 | 116587 | UNUSED_PARAMETER(NotUsed); |
| 116569 | 116588 | zFile = (const char *)sqlite3_value_text(argv[0]); |
| | @@ -116579,17 +116598,30 @@ |
| 116579 | 116598 | |
| 116580 | 116599 | if( REOPEN_AS_MEMDB(db) ){ |
| 116581 | 116600 | /* This is not a real ATTACH. Instead, this routine is being called |
| 116582 | 116601 | ** from sqlite3_deserialize() to close database db->init.iDb and |
| 116583 | 116602 | ** reopen it as a MemDB */ |
| 116603 | + Btree *pNewBt = 0; |
| 116584 | 116604 | pVfs = sqlite3_vfs_find("memdb"); |
| 116585 | 116605 | if( pVfs==0 ) return; |
| 116586 | | - pNew = &db->aDb[db->init.iDb]; |
| 116587 | | - if( pNew->pBt ) sqlite3BtreeClose(pNew->pBt); |
| 116588 | | - pNew->pBt = 0; |
| 116589 | | - pNew->pSchema = 0; |
| 116590 | | - rc = sqlite3BtreeOpen(pVfs, "x\0", db, &pNew->pBt, 0, SQLITE_OPEN_MAIN_DB); |
| 116606 | + rc = sqlite3BtreeOpen(pVfs, "x\0", db, &pNewBt, 0, SQLITE_OPEN_MAIN_DB); |
| 116607 | + if( rc==SQLITE_OK ){ |
| 116608 | + Schema *pNewSchema = sqlite3SchemaGet(db, pNewBt); |
| 116609 | + if( pNewSchema ){ |
| 116610 | + /* Both the Btree and the new Schema were allocated successfully. |
| 116611 | + ** Close the old db and update the aDb[] slot with the new memdb |
| 116612 | + ** values. */ |
| 116613 | + pNew = &db->aDb[db->init.iDb]; |
| 116614 | + if( ALWAYS(pNew->pBt) ) sqlite3BtreeClose(pNew->pBt); |
| 116615 | + pNew->pBt = pNewBt; |
| 116616 | + pNew->pSchema = pNewSchema; |
| 116617 | + }else{ |
| 116618 | + sqlite3BtreeClose(pNewBt); |
| 116619 | + rc = SQLITE_NOMEM; |
| 116620 | + } |
| 116621 | + } |
| 116622 | + if( rc ) goto attach_error; |
| 116591 | 116623 | }else{ |
| 116592 | 116624 | /* This is a real ATTACH |
| 116593 | 116625 | ** |
| 116594 | 116626 | ** Check for the following errors: |
| 116595 | 116627 | ** |
| | @@ -116698,11 +116730,11 @@ |
| 116698 | 116730 | rc = SQLITE_AUTH_USER; |
| 116699 | 116731 | } |
| 116700 | 116732 | } |
| 116701 | 116733 | #endif |
| 116702 | 116734 | if( rc ){ |
| 116703 | | - if( !REOPEN_AS_MEMDB(db) ){ |
| 116735 | + if( ALWAYS(!REOPEN_AS_MEMDB(db)) ){ |
| 116704 | 116736 | int iDb = db->nDb - 1; |
| 116705 | 116737 | assert( iDb>=2 ); |
| 116706 | 116738 | if( db->aDb[iDb].pBt ){ |
| 116707 | 116739 | sqlite3BtreeClose(db->aDb[iDb].pBt); |
| 116708 | 116740 | db->aDb[iDb].pBt = 0; |
| | @@ -116814,10 +116846,12 @@ |
| 116814 | 116846 | int rc; |
| 116815 | 116847 | NameContext sName; |
| 116816 | 116848 | Vdbe *v; |
| 116817 | 116849 | sqlite3* db = pParse->db; |
| 116818 | 116850 | int regArgs; |
| 116851 | + |
| 116852 | + if( SQLITE_OK!=sqlite3ReadSchema(pParse) ) goto attach_end; |
| 116819 | 116853 | |
| 116820 | 116854 | if( pParse->nErr ) goto attach_end; |
| 116821 | 116855 | memset(&sName, 0, sizeof(NameContext)); |
| 116822 | 116856 | sName.pParse = pParse; |
| 116823 | 116857 | |
| | @@ -125826,10 +125860,100 @@ |
| 125826 | 125860 | } |
| 125827 | 125861 | *z = 0; |
| 125828 | 125862 | sqlite3_result_text(context, zHex, n*2, sqlite3_free); |
| 125829 | 125863 | } |
| 125830 | 125864 | } |
| 125865 | + |
| 125866 | +/* |
| 125867 | +** Buffer zStr contains nStr bytes of utf-8 encoded text. Return 1 if zStr |
| 125868 | +** contains character ch, or 0 if it does not. |
| 125869 | +*/ |
| 125870 | +static int strContainsChar(const u8 *zStr, int nStr, u32 ch){ |
| 125871 | + const u8 *zEnd = &zStr[nStr]; |
| 125872 | + const u8 *z = zStr; |
| 125873 | + while( z<zEnd ){ |
| 125874 | + u32 tst = Utf8Read(z); |
| 125875 | + if( tst==ch ) return 1; |
| 125876 | + } |
| 125877 | + return 0; |
| 125878 | +} |
| 125879 | + |
| 125880 | +/* |
| 125881 | +** The unhex() function. This function may be invoked with either one or |
| 125882 | +** two arguments. In both cases the first argument is interpreted as text |
| 125883 | +** a text value containing a set of pairs of hexadecimal digits which are |
| 125884 | +** decoded and returned as a blob. |
| 125885 | +** |
| 125886 | +** If there is only a single argument, then it must consist only of an |
| 125887 | +** even number of hexadeximal digits. Otherwise, return NULL. |
| 125888 | +** |
| 125889 | +** Or, if there is a second argument, then any character that appears in |
| 125890 | +** the second argument is also allowed to appear between pairs of hexadecimal |
| 125891 | +** digits in the first argument. If any other character appears in the |
| 125892 | +** first argument, or if one of the allowed characters appears between |
| 125893 | +** two hexadecimal digits that make up a single byte, NULL is returned. |
| 125894 | +** |
| 125895 | +** The following expressions are all true: |
| 125896 | +** |
| 125897 | +** unhex('ABCD') IS x'ABCD' |
| 125898 | +** unhex('AB CD') IS NULL |
| 125899 | +** unhex('AB CD', ' ') IS x'ABCD' |
| 125900 | +** unhex('A BCD', ' ') IS NULL |
| 125901 | +*/ |
| 125902 | +static void unhexFunc( |
| 125903 | + sqlite3_context *pCtx, |
| 125904 | + int argc, |
| 125905 | + sqlite3_value **argv |
| 125906 | +){ |
| 125907 | + const u8 *zPass = (const u8*)""; |
| 125908 | + int nPass = 0; |
| 125909 | + const u8 *zHex = sqlite3_value_text(argv[0]); |
| 125910 | + int nHex = sqlite3_value_bytes(argv[0]); |
| 125911 | +#ifdef SQLITE_DEBUG |
| 125912 | + const u8 *zEnd = &zHex[nHex]; |
| 125913 | +#endif |
| 125914 | + u8 *pBlob = 0; |
| 125915 | + u8 *p = 0; |
| 125916 | + |
| 125917 | + assert( argc==1 || argc==2 ); |
| 125918 | + if( argc==2 ){ |
| 125919 | + zPass = sqlite3_value_text(argv[1]); |
| 125920 | + nPass = sqlite3_value_bytes(argv[1]); |
| 125921 | + } |
| 125922 | + if( !zHex || !zPass ) return; |
| 125923 | + |
| 125924 | + p = pBlob = contextMalloc(pCtx, (nHex/2)+1); |
| 125925 | + if( pBlob ){ |
| 125926 | + u8 c; /* Most significant digit of next byte */ |
| 125927 | + u8 d; /* Least significant digit of next byte */ |
| 125928 | + |
| 125929 | + while( (c = *zHex)!=0x00 ){ |
| 125930 | + while( !sqlite3Isxdigit(c) ){ |
| 125931 | + u32 ch = Utf8Read(zHex); |
| 125932 | + assert( zHex<=zEnd ); |
| 125933 | + if( !strContainsChar(zPass, nPass, ch) ) goto unhex_null; |
| 125934 | + c = *zHex; |
| 125935 | + if( c==0x00 ) goto unhex_done; |
| 125936 | + } |
| 125937 | + zHex++; |
| 125938 | + assert( *zEnd==0x00 ); |
| 125939 | + assert( zHex<=zEnd ); |
| 125940 | + d = *(zHex++); |
| 125941 | + if( !sqlite3Isxdigit(d) ) goto unhex_null; |
| 125942 | + *(p++) = (sqlite3HexToInt(c)<<4) | sqlite3HexToInt(d); |
| 125943 | + } |
| 125944 | + } |
| 125945 | + |
| 125946 | + unhex_done: |
| 125947 | + sqlite3_result_blob(pCtx, pBlob, (p - pBlob), sqlite3_free); |
| 125948 | + return; |
| 125949 | + |
| 125950 | + unhex_null: |
| 125951 | + sqlite3_free(pBlob); |
| 125952 | + return; |
| 125953 | +} |
| 125954 | + |
| 125831 | 125955 | |
| 125832 | 125956 | /* |
| 125833 | 125957 | ** The zeroblob(N) function returns a zero-filled blob of size N bytes. |
| 125834 | 125958 | */ |
| 125835 | 125959 | static void zeroblobFunc( |
| | @@ -126891,10 +127015,12 @@ |
| 126891 | 127015 | FUNCTION(round, 2, 0, 0, roundFunc ), |
| 126892 | 127016 | #endif |
| 126893 | 127017 | FUNCTION(upper, 1, 0, 0, upperFunc ), |
| 126894 | 127018 | FUNCTION(lower, 1, 0, 0, lowerFunc ), |
| 126895 | 127019 | FUNCTION(hex, 1, 0, 0, hexFunc ), |
| 127020 | + FUNCTION(unhex, 1, 0, 0, unhexFunc ), |
| 127021 | + FUNCTION(unhex, 2, 0, 0, unhexFunc ), |
| 126896 | 127022 | INLINE_FUNC(ifnull, 2, INLINEFUNC_coalesce, 0 ), |
| 126897 | 127023 | VFUNCTION(random, 0, 0, 0, randomFunc ), |
| 126898 | 127024 | VFUNCTION(randomblob, 1, 0, 0, randomBlob ), |
| 126899 | 127025 | FUNCTION(nullif, 2, 0, 1, nullifFunc ), |
| 126900 | 127026 | DFUNCTION(sqlite_version, 0, 0, 0, versionFunc ), |
| | @@ -137240,11 +137366,16 @@ |
| 137240 | 137366 | encoding = (u8)meta[BTREE_TEXT_ENCODING-1] & 3; |
| 137241 | 137367 | if( encoding==0 ) encoding = SQLITE_UTF8; |
| 137242 | 137368 | #else |
| 137243 | 137369 | encoding = SQLITE_UTF8; |
| 137244 | 137370 | #endif |
| 137245 | | - sqlite3SetTextEncoding(db, encoding); |
| 137371 | + if( db->nVdbeActive>0 && encoding!=ENC(db) ){ |
| 137372 | + rc = SQLITE_LOCKED; |
| 137373 | + goto initone_error_out; |
| 137374 | + }else{ |
| 137375 | + sqlite3SetTextEncoding(db, encoding); |
| 137376 | + } |
| 137246 | 137377 | }else{ |
| 137247 | 137378 | /* If opening an attached database, the encoding much match ENC(db) */ |
| 137248 | 137379 | if( (meta[BTREE_TEXT_ENCODING-1] & 3)!=ENC(db) ){ |
| 137249 | 137380 | sqlite3SetString(pzErrMsg, db, "attached databases must use the same" |
| 137250 | 137381 | " text encoding as main database"); |
| | @@ -150191,14 +150322,14 @@ |
| 150191 | 150322 | || db->eOpenState==SQLITE_STATE_ZOMBIE ); |
| 150192 | 150323 | |
| 150193 | 150324 | pVTab->nRef--; |
| 150194 | 150325 | if( pVTab->nRef==0 ){ |
| 150195 | 150326 | sqlite3_vtab *p = pVTab->pVtab; |
| 150196 | | - sqlite3VtabModuleUnref(pVTab->db, pVTab->pMod); |
| 150197 | 150327 | if( p ){ |
| 150198 | 150328 | p->pModule->xDisconnect(p); |
| 150199 | 150329 | } |
| 150330 | + sqlite3VtabModuleUnref(pVTab->db, pVTab->pMod); |
| 150200 | 150331 | sqlite3DbFree(db, pVTab); |
| 150201 | 150332 | } |
| 150202 | 150333 | } |
| 150203 | 150334 | |
| 150204 | 150335 | /* |
| | @@ -160714,11 +160845,11 @@ |
| 160714 | 160845 | |
| 160715 | 160846 | #if (defined(SQLITE_ENABLE_DBPAGE_VTAB) || defined(SQLITE_TEST)) \ |
| 160716 | 160847 | && !defined(SQLITE_OMIT_VIRTUALTABLE) |
| 160717 | 160848 | /* |
| 160718 | 160849 | ** Cause the prepared statement that is associated with a call to |
| 160719 | | -** xBestIndex to potentiall use all schemas. If the statement being |
| 160850 | +** xBestIndex to potentially use all schemas. If the statement being |
| 160720 | 160851 | ** prepared is read-only, then just start read transactions on all |
| 160721 | 160852 | ** schemas. But if this is a write operation, start writes on all |
| 160722 | 160853 | ** schemas. |
| 160723 | 160854 | ** |
| 160724 | 160855 | ** This is used by the (built-in) sqlite_dbpage virtual table. |
| | @@ -160729,11 +160860,11 @@ |
| 160729 | 160860 | int nDb = pParse->db->nDb; |
| 160730 | 160861 | int i; |
| 160731 | 160862 | for(i=0; i<nDb; i++){ |
| 160732 | 160863 | sqlite3CodeVerifySchema(pParse, i); |
| 160733 | 160864 | } |
| 160734 | | - if( pParse->writeMask ){ |
| 160865 | + if( DbMaskNonZero(pParse->writeMask) ){ |
| 160735 | 160866 | for(i=0; i<nDb; i++){ |
| 160736 | 160867 | sqlite3BeginWriteOperation(pParse, 0, i); |
| 160737 | 160868 | } |
| 160738 | 160869 | } |
| 160739 | 160870 | } |
| | @@ -180122,10 +180253,12 @@ |
| 180122 | 180253 | SQLITE_PRIVATE int sqlite3FtsUnicodeFold(int, int); |
| 180123 | 180254 | SQLITE_PRIVATE int sqlite3FtsUnicodeIsalnum(int); |
| 180124 | 180255 | SQLITE_PRIVATE int sqlite3FtsUnicodeIsdiacritic(int); |
| 180125 | 180256 | #endif |
| 180126 | 180257 | |
| 180258 | +SQLITE_PRIVATE int sqlite3Fts3ExprIterate(Fts3Expr*, int (*x)(Fts3Expr*,int,void*), void*); |
| 180259 | + |
| 180127 | 180260 | #endif /* !SQLITE_CORE || SQLITE_ENABLE_FTS3 */ |
| 180128 | 180261 | #endif /* _FTSINT_H */ |
| 180129 | 180262 | |
| 180130 | 180263 | /************** End of fts3Int.h *********************************************/ |
| 180131 | 180264 | /************** Continuing where we left off in fts3.c ***********************/ |
| | @@ -185125,13 +185258,12 @@ |
| 185125 | 185258 | static void fts3EvalNextRow( |
| 185126 | 185259 | Fts3Cursor *pCsr, /* FTS Cursor handle */ |
| 185127 | 185260 | Fts3Expr *pExpr, /* Expr. to advance to next matching row */ |
| 185128 | 185261 | int *pRc /* IN/OUT: Error code */ |
| 185129 | 185262 | ){ |
| 185130 | | - if( *pRc==SQLITE_OK ){ |
| 185263 | + if( *pRc==SQLITE_OK && pExpr->bEof==0 ){ |
| 185131 | 185264 | int bDescDoclist = pCsr->bDesc; /* Used by DOCID_CMP() macro */ |
| 185132 | | - assert( pExpr->bEof==0 ); |
| 185133 | 185265 | pExpr->bStart = 1; |
| 185134 | 185266 | |
| 185135 | 185267 | switch( pExpr->eType ){ |
| 185136 | 185268 | case FTSQUERY_NEAR: |
| 185137 | 185269 | case FTSQUERY_AND: { |
| | @@ -185602,10 +185734,26 @@ |
| 185602 | 185734 | |
| 185603 | 185735 | fts3EvalUpdateCounts(pExpr->pLeft, nCol); |
| 185604 | 185736 | fts3EvalUpdateCounts(pExpr->pRight, nCol); |
| 185605 | 185737 | } |
| 185606 | 185738 | } |
| 185739 | + |
| 185740 | +/* |
| 185741 | +** This is an sqlite3Fts3ExprIterate() callback. If the Fts3Expr.aMI[] array |
| 185742 | +** has not yet been allocated, allocate and zero it. Otherwise, just zero |
| 185743 | +** it. |
| 185744 | +*/ |
| 185745 | +static int fts3AllocateMSI(Fts3Expr *pExpr, int iPhrase, void *pCtx){ |
| 185746 | + Fts3Table *pTab = (Fts3Table*)pCtx; |
| 185747 | + UNUSED_PARAMETER(iPhrase); |
| 185748 | + if( pExpr->aMI==0 ){ |
| 185749 | + pExpr->aMI = (u32 *)sqlite3_malloc64(pTab->nColumn * 3 * sizeof(u32)); |
| 185750 | + if( pExpr->aMI==0 ) return SQLITE_NOMEM; |
| 185751 | + } |
| 185752 | + memset(pExpr->aMI, 0, pTab->nColumn * 3 * sizeof(u32)); |
| 185753 | + return SQLITE_OK; |
| 185754 | +} |
| 185607 | 185755 | |
| 185608 | 185756 | /* |
| 185609 | 185757 | ** Expression pExpr must be of type FTSQUERY_PHRASE. |
| 185610 | 185758 | ** |
| 185611 | 185759 | ** If it is not already allocated and populated, this function allocates and |
| | @@ -185624,34 +185772,29 @@ |
| 185624 | 185772 | |
| 185625 | 185773 | assert( pExpr->eType==FTSQUERY_PHRASE ); |
| 185626 | 185774 | if( pExpr->aMI==0 ){ |
| 185627 | 185775 | Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab; |
| 185628 | 185776 | Fts3Expr *pRoot; /* Root of NEAR expression */ |
| 185629 | | - Fts3Expr *p; /* Iterator used for several purposes */ |
| 185630 | 185777 | |
| 185631 | 185778 | sqlite3_int64 iPrevId = pCsr->iPrevId; |
| 185632 | 185779 | sqlite3_int64 iDocid; |
| 185633 | 185780 | u8 bEof; |
| 185634 | 185781 | |
| 185635 | 185782 | /* Find the root of the NEAR expression */ |
| 185636 | 185783 | pRoot = pExpr; |
| 185637 | | - while( pRoot->pParent && pRoot->pParent->eType==FTSQUERY_NEAR ){ |
| 185784 | + while( pRoot->pParent |
| 185785 | + && (pRoot->pParent->eType==FTSQUERY_NEAR || pRoot->bDeferred) |
| 185786 | + ){ |
| 185638 | 185787 | pRoot = pRoot->pParent; |
| 185639 | 185788 | } |
| 185640 | 185789 | iDocid = pRoot->iDocid; |
| 185641 | 185790 | bEof = pRoot->bEof; |
| 185642 | 185791 | assert( pRoot->bStart ); |
| 185643 | 185792 | |
| 185644 | 185793 | /* Allocate space for the aMSI[] array of each FTSQUERY_PHRASE node */ |
| 185645 | | - for(p=pRoot; p; p=p->pLeft){ |
| 185646 | | - Fts3Expr *pE = (p->eType==FTSQUERY_PHRASE?p:p->pRight); |
| 185647 | | - assert( pE->aMI==0 ); |
| 185648 | | - pE->aMI = (u32 *)sqlite3_malloc64(pTab->nColumn * 3 * sizeof(u32)); |
| 185649 | | - if( !pE->aMI ) return SQLITE_NOMEM; |
| 185650 | | - memset(pE->aMI, 0, pTab->nColumn * 3 * sizeof(u32)); |
| 185651 | | - } |
| 185652 | | - |
| 185794 | + rc = sqlite3Fts3ExprIterate(pRoot, fts3AllocateMSI, (void*)pTab); |
| 185795 | + if( rc!=SQLITE_OK ) return rc; |
| 185653 | 185796 | fts3EvalRestart(pCsr, pRoot, &rc); |
| 185654 | 185797 | |
| 185655 | 185798 | while( pCsr->isEof==0 && rc==SQLITE_OK ){ |
| 185656 | 185799 | |
| 185657 | 185800 | do { |
| | @@ -185803,10 +185946,11 @@ |
| 185803 | 185946 | int bDescDoclist = pTab->bDescIdx; /* For DOCID_CMP macro */ |
| 185804 | 185947 | int bOr = 0; |
| 185805 | 185948 | u8 bTreeEof = 0; |
| 185806 | 185949 | Fts3Expr *p; /* Used to iterate from pExpr to root */ |
| 185807 | 185950 | Fts3Expr *pNear; /* Most senior NEAR ancestor (or pExpr) */ |
| 185951 | + Fts3Expr *pRun; /* Closest non-deferred ancestor of pNear */ |
| 185808 | 185952 | int bMatch; |
| 185809 | 185953 | |
| 185810 | 185954 | /* Check if this phrase descends from an OR expression node. If not, |
| 185811 | 185955 | ** return NULL. Otherwise, the entry that corresponds to docid |
| 185812 | 185956 | ** pCsr->iPrevId may lie earlier in the doclist buffer. Or, if the |
| | @@ -185817,29 +185961,34 @@ |
| 185817 | 185961 | if( p->eType==FTSQUERY_OR ) bOr = 1; |
| 185818 | 185962 | if( p->eType==FTSQUERY_NEAR ) pNear = p; |
| 185819 | 185963 | if( p->bEof ) bTreeEof = 1; |
| 185820 | 185964 | } |
| 185821 | 185965 | if( bOr==0 ) return SQLITE_OK; |
| 185966 | + pRun = pNear; |
| 185967 | + while( pRun->bDeferred ){ |
| 185968 | + assert( pRun->pParent ); |
| 185969 | + pRun = pRun->pParent; |
| 185970 | + } |
| 185822 | 185971 | |
| 185823 | 185972 | /* This is the descendent of an OR node. In this case we cannot use |
| 185824 | 185973 | ** an incremental phrase. Load the entire doclist for the phrase |
| 185825 | 185974 | ** into memory in this case. */ |
| 185826 | 185975 | if( pPhrase->bIncr ){ |
| 185827 | | - int bEofSave = pNear->bEof; |
| 185828 | | - fts3EvalRestart(pCsr, pNear, &rc); |
| 185829 | | - while( rc==SQLITE_OK && !pNear->bEof ){ |
| 185830 | | - fts3EvalNextRow(pCsr, pNear, &rc); |
| 185831 | | - if( bEofSave==0 && pNear->iDocid==iDocid ) break; |
| 185976 | + int bEofSave = pRun->bEof; |
| 185977 | + fts3EvalRestart(pCsr, pRun, &rc); |
| 185978 | + while( rc==SQLITE_OK && !pRun->bEof ){ |
| 185979 | + fts3EvalNextRow(pCsr, pRun, &rc); |
| 185980 | + if( bEofSave==0 && pRun->iDocid==iDocid ) break; |
| 185832 | 185981 | } |
| 185833 | 185982 | assert( rc!=SQLITE_OK || pPhrase->bIncr==0 ); |
| 185834 | | - if( rc==SQLITE_OK && pNear->bEof!=bEofSave ){ |
| 185983 | + if( rc==SQLITE_OK && pRun->bEof!=bEofSave ){ |
| 185835 | 185984 | rc = FTS_CORRUPT_VTAB; |
| 185836 | 185985 | } |
| 185837 | 185986 | } |
| 185838 | 185987 | if( bTreeEof ){ |
| 185839 | | - while( rc==SQLITE_OK && !pNear->bEof ){ |
| 185840 | | - fts3EvalNextRow(pCsr, pNear, &rc); |
| 185988 | + while( rc==SQLITE_OK && !pRun->bEof ){ |
| 185989 | + fts3EvalNextRow(pCsr, pRun, &rc); |
| 185841 | 185990 | } |
| 185842 | 185991 | } |
| 185843 | 185992 | if( rc!=SQLITE_OK ) return rc; |
| 185844 | 185993 | |
| 185845 | 185994 | bMatch = 1; |
| | @@ -195942,11 +196091,11 @@ |
| 195942 | 196091 | */ |
| 195943 | 196092 | #define FTS3_MATCHINFO_DEFAULT "pcx" |
| 195944 | 196093 | |
| 195945 | 196094 | |
| 195946 | 196095 | /* |
| 195947 | | -** Used as an fts3ExprIterate() context when loading phrase doclists to |
| 196096 | +** Used as an sqlite3Fts3ExprIterate() context when loading phrase doclists to |
| 195948 | 196097 | ** Fts3Expr.aDoclist[]/nDoclist. |
| 195949 | 196098 | */ |
| 195950 | 196099 | typedef struct LoadDoclistCtx LoadDoclistCtx; |
| 195951 | 196100 | struct LoadDoclistCtx { |
| 195952 | 196101 | Fts3Cursor *pCsr; /* FTS3 Cursor */ |
| | @@ -195986,11 +196135,11 @@ |
| 195986 | 196135 | u64 covered; /* Mask of query phrases covered */ |
| 195987 | 196136 | u64 hlmask; /* Mask of snippet terms to highlight */ |
| 195988 | 196137 | }; |
| 195989 | 196138 | |
| 195990 | 196139 | /* |
| 195991 | | -** This type is used as an fts3ExprIterate() context object while |
| 196140 | +** This type is used as an sqlite3Fts3ExprIterate() context object while |
| 195992 | 196141 | ** accumulating the data returned by the matchinfo() function. |
| 195993 | 196142 | */ |
| 195994 | 196143 | typedef struct MatchInfo MatchInfo; |
| 195995 | 196144 | struct MatchInfo { |
| 195996 | 196145 | Fts3Cursor *pCursor; /* FTS3 Cursor */ |
| | @@ -196145,11 +196294,11 @@ |
| 196145 | 196294 | *pp += fts3GetVarint32(*pp, &iVal); |
| 196146 | 196295 | *piPos += (iVal-2); |
| 196147 | 196296 | } |
| 196148 | 196297 | |
| 196149 | 196298 | /* |
| 196150 | | -** Helper function for fts3ExprIterate() (see below). |
| 196299 | +** Helper function for sqlite3Fts3ExprIterate() (see below). |
| 196151 | 196300 | */ |
| 196152 | 196301 | static int fts3ExprIterate2( |
| 196153 | 196302 | Fts3Expr *pExpr, /* Expression to iterate phrases of */ |
| 196154 | 196303 | int *piPhrase, /* Pointer to phrase counter */ |
| 196155 | 196304 | int (*x)(Fts3Expr*,int,void*), /* Callback function to invoke for phrases */ |
| | @@ -196179,23 +196328,22 @@ |
| 196179 | 196328 | ** If the callback function returns anything other than SQLITE_OK, |
| 196180 | 196329 | ** the iteration is abandoned and the error code returned immediately. |
| 196181 | 196330 | ** Otherwise, SQLITE_OK is returned after a callback has been made for |
| 196182 | 196331 | ** all eligible phrase nodes. |
| 196183 | 196332 | */ |
| 196184 | | -static int fts3ExprIterate( |
| 196333 | +SQLITE_PRIVATE int sqlite3Fts3ExprIterate( |
| 196185 | 196334 | Fts3Expr *pExpr, /* Expression to iterate phrases of */ |
| 196186 | 196335 | int (*x)(Fts3Expr*,int,void*), /* Callback function to invoke for phrases */ |
| 196187 | 196336 | void *pCtx /* Second argument to pass to callback */ |
| 196188 | 196337 | ){ |
| 196189 | 196338 | int iPhrase = 0; /* Variable used as the phrase counter */ |
| 196190 | 196339 | return fts3ExprIterate2(pExpr, &iPhrase, x, pCtx); |
| 196191 | 196340 | } |
| 196192 | 196341 | |
| 196193 | | - |
| 196194 | 196342 | /* |
| 196195 | | -** This is an fts3ExprIterate() callback used while loading the doclists |
| 196196 | | -** for each phrase into Fts3Expr.aDoclist[]/nDoclist. See also |
| 196343 | +** This is an sqlite3Fts3ExprIterate() callback used while loading the |
| 196344 | +** doclists for each phrase into Fts3Expr.aDoclist[]/nDoclist. See also |
| 196197 | 196345 | ** fts3ExprLoadDoclists(). |
| 196198 | 196346 | */ |
| 196199 | 196347 | static int fts3ExprLoadDoclistsCb(Fts3Expr *pExpr, int iPhrase, void *ctx){ |
| 196200 | 196348 | int rc = SQLITE_OK; |
| 196201 | 196349 | Fts3Phrase *pPhrase = pExpr->pPhrase; |
| | @@ -196223,13 +196371,13 @@ |
| 196223 | 196371 | Fts3Cursor *pCsr, /* Fts3 cursor for current query */ |
| 196224 | 196372 | int *pnPhrase, /* OUT: Number of phrases in query */ |
| 196225 | 196373 | int *pnToken /* OUT: Number of tokens in query */ |
| 196226 | 196374 | ){ |
| 196227 | 196375 | int rc; /* Return Code */ |
| 196228 | | - LoadDoclistCtx sCtx = {0,0,0}; /* Context for fts3ExprIterate() */ |
| 196376 | + LoadDoclistCtx sCtx = {0,0,0}; /* Context for sqlite3Fts3ExprIterate() */ |
| 196229 | 196377 | sCtx.pCsr = pCsr; |
| 196230 | | - rc = fts3ExprIterate(pCsr->pExpr, fts3ExprLoadDoclistsCb, (void *)&sCtx); |
| 196378 | + rc = sqlite3Fts3ExprIterate(pCsr->pExpr,fts3ExprLoadDoclistsCb,(void*)&sCtx); |
| 196231 | 196379 | if( pnPhrase ) *pnPhrase = sCtx.nPhrase; |
| 196232 | 196380 | if( pnToken ) *pnToken = sCtx.nToken; |
| 196233 | 196381 | return rc; |
| 196234 | 196382 | } |
| 196235 | 196383 | |
| | @@ -196238,11 +196386,11 @@ |
| 196238 | 196386 | pExpr->iPhrase = iPhrase; |
| 196239 | 196387 | return SQLITE_OK; |
| 196240 | 196388 | } |
| 196241 | 196389 | static int fts3ExprPhraseCount(Fts3Expr *pExpr){ |
| 196242 | 196390 | int nPhrase = 0; |
| 196243 | | - (void)fts3ExprIterate(pExpr, fts3ExprPhraseCountCb, (void *)&nPhrase); |
| 196391 | + (void)sqlite3Fts3ExprIterate(pExpr, fts3ExprPhraseCountCb, (void *)&nPhrase); |
| 196244 | 196392 | return nPhrase; |
| 196245 | 196393 | } |
| 196246 | 196394 | |
| 196247 | 196395 | /* |
| 196248 | 196396 | ** Advance the position list iterator specified by the first two |
| | @@ -196366,12 +196514,13 @@ |
| 196366 | 196514 | *pmCover = mCover; |
| 196367 | 196515 | *pmHighlight = mHighlight; |
| 196368 | 196516 | } |
| 196369 | 196517 | |
| 196370 | 196518 | /* |
| 196371 | | -** This function is an fts3ExprIterate() callback used by fts3BestSnippet(). |
| 196372 | | -** Each invocation populates an element of the SnippetIter.aPhrase[] array. |
| 196519 | +** This function is an sqlite3Fts3ExprIterate() callback used by |
| 196520 | +** fts3BestSnippet(). Each invocation populates an element of the |
| 196521 | +** SnippetIter.aPhrase[] array. |
| 196373 | 196522 | */ |
| 196374 | 196523 | static int fts3SnippetFindPositions(Fts3Expr *pExpr, int iPhrase, void *ctx){ |
| 196375 | 196524 | SnippetIter *p = (SnippetIter *)ctx; |
| 196376 | 196525 | SnippetPhrase *pPhrase = &p->aPhrase[iPhrase]; |
| 196377 | 196526 | char *pCsr; |
| | @@ -196457,11 +196606,13 @@ |
| 196457 | 196606 | sIter.pCsr = pCsr; |
| 196458 | 196607 | sIter.iCol = iCol; |
| 196459 | 196608 | sIter.nSnippet = nSnippet; |
| 196460 | 196609 | sIter.nPhrase = nList; |
| 196461 | 196610 | sIter.iCurrent = -1; |
| 196462 | | - rc = fts3ExprIterate(pCsr->pExpr, fts3SnippetFindPositions, (void*)&sIter); |
| 196611 | + rc = sqlite3Fts3ExprIterate( |
| 196612 | + pCsr->pExpr, fts3SnippetFindPositions, (void*)&sIter |
| 196613 | + ); |
| 196463 | 196614 | if( rc==SQLITE_OK ){ |
| 196464 | 196615 | |
| 196465 | 196616 | /* Set the *pmSeen output variable. */ |
| 196466 | 196617 | for(i=0; i<nList; i++){ |
| 196467 | 196618 | if( sIter.aPhrase[i].pHead ){ |
| | @@ -196818,14 +196969,14 @@ |
| 196818 | 196969 | } |
| 196819 | 196970 | return rc; |
| 196820 | 196971 | } |
| 196821 | 196972 | |
| 196822 | 196973 | /* |
| 196823 | | -** fts3ExprIterate() callback used to collect the "global" matchinfo stats |
| 196824 | | -** for a single query. |
| 196974 | +** sqlite3Fts3ExprIterate() callback used to collect the "global" matchinfo |
| 196975 | +** stats for a single query. |
| 196825 | 196976 | ** |
| 196826 | | -** fts3ExprIterate() callback to load the 'global' elements of a |
| 196977 | +** sqlite3Fts3ExprIterate() callback to load the 'global' elements of a |
| 196827 | 196978 | ** FTS3_MATCHINFO_HITS matchinfo array. The global stats are those elements |
| 196828 | 196979 | ** of the matchinfo array that are constant for all rows returned by the |
| 196829 | 196980 | ** current query. |
| 196830 | 196981 | ** |
| 196831 | 196982 | ** Argument pCtx is actually a pointer to a struct of type MatchInfo. This |
| | @@ -196856,11 +197007,11 @@ |
| 196856 | 197007 | p->pCursor, pExpr, &p->aMatchinfo[3*iPhrase*p->nCol] |
| 196857 | 197008 | ); |
| 196858 | 197009 | } |
| 196859 | 197010 | |
| 196860 | 197011 | /* |
| 196861 | | -** fts3ExprIterate() callback used to collect the "local" part of the |
| 197012 | +** sqlite3Fts3ExprIterate() callback used to collect the "local" part of the |
| 196862 | 197013 | ** FTS3_MATCHINFO_HITS array. The local stats are those elements of the |
| 196863 | 197014 | ** array that are different for each row returned by the query. |
| 196864 | 197015 | */ |
| 196865 | 197016 | static int fts3ExprLocalHitsCb( |
| 196866 | 197017 | Fts3Expr *pExpr, /* Phrase expression node */ |
| | @@ -197052,11 +197203,11 @@ |
| 197052 | 197203 | /* Allocate and populate the array of LcsIterator objects. The array |
| 197053 | 197204 | ** contains one element for each matchable phrase in the query. |
| 197054 | 197205 | **/ |
| 197055 | 197206 | aIter = sqlite3Fts3MallocZero(sizeof(LcsIterator) * pCsr->nPhrase); |
| 197056 | 197207 | if( !aIter ) return SQLITE_NOMEM; |
| 197057 | | - (void)fts3ExprIterate(pCsr->pExpr, fts3MatchinfoLcsCb, (void*)aIter); |
| 197208 | + (void)sqlite3Fts3ExprIterate(pCsr->pExpr, fts3MatchinfoLcsCb, (void*)aIter); |
| 197058 | 197209 | |
| 197059 | 197210 | for(i=0; i<pInfo->nPhrase; i++){ |
| 197060 | 197211 | LcsIterator *pIter = &aIter[i]; |
| 197061 | 197212 | nToken -= pIter->pExpr->pPhrase->nToken; |
| 197062 | 197213 | pIter->iPosOffset = nToken; |
| | @@ -197229,15 +197380,15 @@ |
| 197229 | 197380 | if( bGlobal ){ |
| 197230 | 197381 | if( pCsr->pDeferred ){ |
| 197231 | 197382 | rc = fts3MatchinfoSelectDoctotal(pTab, &pSelect, &pInfo->nDoc,0,0); |
| 197232 | 197383 | if( rc!=SQLITE_OK ) break; |
| 197233 | 197384 | } |
| 197234 | | - rc = fts3ExprIterate(pExpr, fts3ExprGlobalHitsCb,(void*)pInfo); |
| 197385 | + rc = sqlite3Fts3ExprIterate(pExpr, fts3ExprGlobalHitsCb,(void*)pInfo); |
| 197235 | 197386 | sqlite3Fts3EvalTestDeferred(pCsr, &rc); |
| 197236 | 197387 | if( rc!=SQLITE_OK ) break; |
| 197237 | 197388 | } |
| 197238 | | - (void)fts3ExprIterate(pExpr, fts3ExprLocalHitsCb,(void*)pInfo); |
| 197389 | + (void)sqlite3Fts3ExprIterate(pExpr, fts3ExprLocalHitsCb,(void*)pInfo); |
| 197239 | 197390 | break; |
| 197240 | 197391 | } |
| 197241 | 197392 | } |
| 197242 | 197393 | |
| 197243 | 197394 | pInfo->aMatchinfo += fts3MatchinfoSize(pInfo, zArg[i]); |
| | @@ -197456,11 +197607,11 @@ |
| 197456 | 197607 | sqlite3_int64 iDocid; |
| 197457 | 197608 | TermOffset *aTerm; |
| 197458 | 197609 | }; |
| 197459 | 197610 | |
| 197460 | 197611 | /* |
| 197461 | | -** This function is an fts3ExprIterate() callback used by sqlite3Fts3Offsets(). |
| 197612 | +** This function is an sqlite3Fts3ExprIterate() callback used by sqlite3Fts3Offsets(). |
| 197462 | 197613 | */ |
| 197463 | 197614 | static int fts3ExprTermOffsetInit(Fts3Expr *pExpr, int iPhrase, void *ctx){ |
| 197464 | 197615 | TermOffsetCtx *p = (TermOffsetCtx *)ctx; |
| 197465 | 197616 | int nTerm; /* Number of tokens in phrase */ |
| 197466 | 197617 | int iTerm; /* For looping through nTerm phrase terms */ |
| | @@ -197538,11 +197689,13 @@ |
| 197538 | 197689 | /* Initialize the contents of sCtx.aTerm[] for column iCol. This |
| 197539 | 197690 | ** operation may fail if the database contains corrupt records. |
| 197540 | 197691 | */ |
| 197541 | 197692 | sCtx.iCol = iCol; |
| 197542 | 197693 | sCtx.iTerm = 0; |
| 197543 | | - rc = fts3ExprIterate(pCsr->pExpr, fts3ExprTermOffsetInit, (void*)&sCtx); |
| 197694 | + rc = sqlite3Fts3ExprIterate( |
| 197695 | + pCsr->pExpr, fts3ExprTermOffsetInit, (void*)&sCtx |
| 197696 | + ); |
| 197544 | 197697 | if( rc!=SQLITE_OK ) goto offsets_out; |
| 197545 | 197698 | |
| 197546 | 197699 | /* Retreive the text stored in column iCol. If an SQL NULL is stored |
| 197547 | 197700 | ** in column iCol, jump immediately to the next iteration of the loop. |
| 197548 | 197701 | ** If an OOM occurs while retrieving the data (this can happen if SQLite |
| | @@ -200914,10 +201067,17 @@ |
| 200914 | 201067 | }else if( pConstraint->op==SQLITE_INDEX_CONSTRAINT_EQ ){ |
| 200915 | 201068 | aIdx[iCol] = i; |
| 200916 | 201069 | idxMask |= iMask; |
| 200917 | 201070 | } |
| 200918 | 201071 | } |
| 201072 | + if( pIdxInfo->nOrderBy>0 |
| 201073 | + && pIdxInfo->aOrderBy[0].iColumn<0 |
| 201074 | + && pIdxInfo->aOrderBy[0].desc==0 |
| 201075 | + ){ |
| 201076 | + pIdxInfo->orderByConsumed = 1; |
| 201077 | + } |
| 201078 | + |
| 200919 | 201079 | if( (unusableMask & ~idxMask)!=0 ){ |
| 200920 | 201080 | /* If there are any unusable constraints on JSON or ROOT, then reject |
| 200921 | 201081 | ** this entire plan */ |
| 200922 | 201082 | return SQLITE_CONSTRAINT; |
| 200923 | 201083 | } |
| | @@ -201109,14 +201269,14 @@ |
| 201109 | 201269 | JFUNCTION(json_parse, 1, 0, jsonParseFunc), |
| 201110 | 201270 | JFUNCTION(json_test1, 1, 0, jsonTest1Func), |
| 201111 | 201271 | #endif |
| 201112 | 201272 | WAGGREGATE(json_group_array, 1, 0, 0, |
| 201113 | 201273 | jsonArrayStep, jsonArrayFinal, jsonArrayValue, jsonGroupInverse, |
| 201114 | | - SQLITE_SUBTYPE|SQLITE_UTF8|SQLITE_DETERMINISTIC|SQLITE_INNOCUOUS), |
| 201274 | + SQLITE_SUBTYPE|SQLITE_UTF8|SQLITE_DETERMINISTIC), |
| 201115 | 201275 | WAGGREGATE(json_group_object, 2, 0, 0, |
| 201116 | 201276 | jsonObjectStep, jsonObjectFinal, jsonObjectValue, jsonGroupInverse, |
| 201117 | | - SQLITE_SUBTYPE|SQLITE_UTF8|SQLITE_DETERMINISTIC|SQLITE_INNOCUOUS) |
| 201277 | + SQLITE_SUBTYPE|SQLITE_UTF8|SQLITE_DETERMINISTIC) |
| 201118 | 201278 | }; |
| 201119 | 201279 | sqlite3InsertBuiltinFuncs(aJsonFunc, ArraySize(aJsonFunc)); |
| 201120 | 201280 | #endif |
| 201121 | 201281 | } |
| 201122 | 201282 | |
| | @@ -208579,11 +208739,11 @@ |
| 208579 | 208739 | ** CREATE TABLE data_t1(a INTEGER, b TEXT, c, rbu_control); |
| 208580 | 208740 | ** |
| 208581 | 208741 | ** The order of the columns in the data_% table does not matter. |
| 208582 | 208742 | ** |
| 208583 | 208743 | ** Instead of a regular table, the RBU database may also contain virtual |
| 208584 | | -** tables or view named using the data_<target> naming scheme. |
| 208744 | +** tables or views named using the data_<target> naming scheme. |
| 208585 | 208745 | ** |
| 208586 | 208746 | ** Instead of the plain data_<target> naming scheme, RBU database tables |
| 208587 | 208747 | ** may also be named data<integer>_<target>, where <integer> is any sequence |
| 208588 | 208748 | ** of zero or more numeric characters (0-9). This can be significant because |
| 208589 | 208749 | ** tables within the RBU database are always processed in order sorted by |
| | @@ -208592,11 +208752,11 @@ |
| 208592 | 208752 | ** are processed. This can be useful, for example, to ensure that "external |
| 208593 | 208753 | ** content" FTS4 tables are updated before their underlying content tables. |
| 208594 | 208754 | ** |
| 208595 | 208755 | ** If the target database table is a virtual table or a table that has no |
| 208596 | 208756 | ** PRIMARY KEY declaration, the data_% table must also contain a column |
| 208597 | | -** named "rbu_rowid". This column is mapped to the tables implicit primary |
| 208757 | +** named "rbu_rowid". This column is mapped to the table's implicit primary |
| 208598 | 208758 | ** key column - "rowid". Virtual tables for which the "rowid" column does |
| 208599 | 208759 | ** not function like a primary key value cannot be updated using RBU. For |
| 208600 | 208760 | ** example, if the target db contains either of the following: |
| 208601 | 208761 | ** |
| 208602 | 208762 | ** CREATE VIRTUAL TABLE x1 USING fts3(a, b); |
| | @@ -239876,11 +240036,11 @@ |
| 239876 | 240036 | int nArg, /* Number of args */ |
| 239877 | 240037 | sqlite3_value **apUnused /* Function arguments */ |
| 239878 | 240038 | ){ |
| 239879 | 240039 | assert( nArg==0 ); |
| 239880 | 240040 | UNUSED_PARAM2(nArg, apUnused); |
| 239881 | | - sqlite3_result_text(pCtx, "fts5: 2023-01-16 18:13:00 83f21285fe86430a66ce6841606e3ad7c27da52ac75a034c6a00c7a9fdb9791d", -1, SQLITE_TRANSIENT); |
| 240041 | + sqlite3_result_text(pCtx, "fts5: 2023-01-19 18:16:09 fa10e561f5dcdb23af862c2e486e877d379f12eae077ae5fd3da6028f1c20b49", -1, SQLITE_TRANSIENT); |
| 239882 | 240042 | } |
| 239883 | 240043 | |
| 239884 | 240044 | /* |
| 239885 | 240045 | ** Return true if zName is the extension on one of the shadow tables used |
| 239886 | 240046 | ** by this module. |
| | @@ -239949,11 +240109,13 @@ |
| 239949 | 240109 | db, "fts5", 1, SQLITE_UTF8, p, fts5Fts5Func, 0, 0 |
| 239950 | 240110 | ); |
| 239951 | 240111 | } |
| 239952 | 240112 | if( rc==SQLITE_OK ){ |
| 239953 | 240113 | rc = sqlite3_create_function( |
| 239954 | | - db, "fts5_source_id", 0, SQLITE_UTF8, p, fts5SourceIdFunc, 0, 0 |
| 240114 | + db, "fts5_source_id", 0, |
| 240115 | + SQLITE_UTF8|SQLITE_DETERMINISTIC|SQLITE_INNOCUOUS, |
| 240116 | + p, fts5SourceIdFunc, 0, 0 |
| 239955 | 240117 | ); |
| 239956 | 240118 | } |
| 239957 | 240119 | } |
| 239958 | 240120 | |
| 239959 | 240121 | /* If SQLITE_FTS5_ENABLE_TEST_MI is defined, assume that the file |
| 239960 | 240122 | |