Fossil SCM
Update the built-in SQLite to version 3.9.0 final.
Commit
82d84295a8b4d6c00be028b80829409f0d554da4
Parent
16ce7ef0c5e8aa9…
2 files changed
+244
-220
+12
-4
+244
-220
| --- src/sqlite3.c | ||
| +++ src/sqlite3.c | ||
| @@ -325,11 +325,11 @@ | ||
| 325 | 325 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 326 | 326 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 327 | 327 | */ |
| 328 | 328 | #define SQLITE_VERSION "3.9.0" |
| 329 | 329 | #define SQLITE_VERSION_NUMBER 3009000 |
| 330 | -#define SQLITE_SOURCE_ID "2015-10-10 15:57:20 35e6248abb4435a8b26d270092b856beff867406" | |
| 330 | +#define SQLITE_SOURCE_ID "2015-10-14 12:29:53 a721fc0d89495518fe5612e2e3bbc60befd2e90d" | |
| 331 | 331 | |
| 332 | 332 | /* |
| 333 | 333 | ** CAPI3REF: Run-Time Library Version Numbers |
| 334 | 334 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 335 | 335 | ** |
| @@ -5868,13 +5868,13 @@ | ||
| 5868 | 5868 | ** used with an SQLite version earlier than 3.8.2, the results of attempting |
| 5869 | 5869 | ** to read or write the estimatedRows field are undefined (but are likely |
| 5870 | 5870 | ** to included crashing the application). The estimatedRows field should |
| 5871 | 5871 | ** therefore only be used if [sqlite3_libversion_number()] returns a |
| 5872 | 5872 | ** value greater than or equal to 3008002. Similarly, the idxFlags field |
| 5873 | -** was added for version 3.8.12. It may therefore only be used if | |
| 5873 | +** was added for version 3.9.0. It may therefore only be used if | |
| 5874 | 5874 | ** sqlite3_libversion_number() returns a value greater than or equal to |
| 5875 | -** 3008012. | |
| 5875 | +** 3009000. | |
| 5876 | 5876 | */ |
| 5877 | 5877 | struct sqlite3_index_info { |
| 5878 | 5878 | /* Inputs */ |
| 5879 | 5879 | int nConstraint; /* Number of entries in aConstraint */ |
| 5880 | 5880 | struct sqlite3_index_constraint { |
| @@ -5898,11 +5898,11 @@ | ||
| 5898 | 5898 | int needToFreeIdxStr; /* Free idxStr using sqlite3_free() if true */ |
| 5899 | 5899 | int orderByConsumed; /* True if output is already ordered */ |
| 5900 | 5900 | double estimatedCost; /* Estimated cost of using this index */ |
| 5901 | 5901 | /* Fields below are only available in SQLite 3.8.2 and later */ |
| 5902 | 5902 | sqlite3_int64 estimatedRows; /* Estimated number of rows returned */ |
| 5903 | - /* Fields below are only available in SQLite 3.8.12 and later */ | |
| 5903 | + /* Fields below are only available in SQLite 3.9.0 and later */ | |
| 5904 | 5904 | int idxFlags; /* Mask of SQLITE_INDEX_SCAN_* flags */ |
| 5905 | 5905 | }; |
| 5906 | 5906 | |
| 5907 | 5907 | /* |
| 5908 | 5908 | ** CAPI3REF: Virtual Table Scan Flags |
| @@ -8158,10 +8158,14 @@ | ||
| 8158 | 8158 | #ifndef _FTS5_H |
| 8159 | 8159 | #define _FTS5_H |
| 8160 | 8160 | |
| 8161 | 8161 | /* #include "sqlite3.h" */ |
| 8162 | 8162 | |
| 8163 | +#if 0 | |
| 8164 | +extern "C" { | |
| 8165 | +#endif | |
| 8166 | + | |
| 8163 | 8167 | /************************************************************************* |
| 8164 | 8168 | ** CUSTOM AUXILIARY FUNCTIONS |
| 8165 | 8169 | ** |
| 8166 | 8170 | ** Virtual table implementations may overload SQL functions by implementing |
| 8167 | 8171 | ** the sqlite3_module.xFindFunction() method. |
| @@ -8643,10 +8647,14 @@ | ||
| 8643 | 8647 | |
| 8644 | 8648 | /* |
| 8645 | 8649 | ** END OF REGISTRATION API |
| 8646 | 8650 | *************************************************************************/ |
| 8647 | 8651 | |
| 8652 | +#if 0 | |
| 8653 | +} /* end of the 'extern "C"' block */ | |
| 8654 | +#endif | |
| 8655 | + | |
| 8648 | 8656 | #endif /* _FTS5_H */ |
| 8649 | 8657 | |
| 8650 | 8658 | |
| 8651 | 8659 | |
| 8652 | 8660 | /************** End of sqlite3.h *********************************************/ |
| @@ -60993,11 +61001,17 @@ | ||
| 60993 | 61001 | if( (aData[1]==0 && aData[2]==0) || (pSlot = pageFindSlot(pPg,sz,&rc))==0 ){ |
| 60994 | 61002 | pData -= sz; |
| 60995 | 61003 | if( pData<pBegin ) return 1; |
| 60996 | 61004 | pSlot = pData; |
| 60997 | 61005 | } |
| 60998 | - memcpy(pSlot, pCArray->apCell[i], sz); | |
| 61006 | + /* pSlot and pCArray->apCell[i] will never overlap on a well-formed | |
| 61007 | + ** database. But they might for a corrupt database. Hence use memmove() | |
| 61008 | + ** since memcpy() sends SIGABORT with overlapping buffers on OpenBSD */ | |
| 61009 | + assert( (pSlot+sz)<=pCArray->apCell[i] | |
| 61010 | + || pSlot>=(pCArray->apCell[i]+sz) | |
| 61011 | + || CORRUPT_DB ); | |
| 61012 | + memmove(pSlot, pCArray->apCell[i], sz); | |
| 60999 | 61013 | put2byte(pCellptr, (pSlot - aData)); |
| 61000 | 61014 | pCellptr += 2; |
| 61001 | 61015 | } |
| 61002 | 61016 | *ppData = pData; |
| 61003 | 61017 | return 0; |
| @@ -104303,11 +104317,11 @@ | ||
| 104303 | 104317 | /* Version 3.8.11 and later */ |
| 104304 | 104318 | sqlite3_value *(*value_dup)(const sqlite3_value*); |
| 104305 | 104319 | void (*value_free)(sqlite3_value*); |
| 104306 | 104320 | int (*result_zeroblob64)(sqlite3_context*,sqlite3_uint64); |
| 104307 | 104321 | int (*bind_zeroblob64)(sqlite3_stmt*, int, sqlite3_uint64); |
| 104308 | - /* Version 3.8.12 and later */ | |
| 104322 | + /* Version 3.9.0 and later */ | |
| 104309 | 104323 | unsigned int (*value_subtype)(sqlite3_value*); |
| 104310 | 104324 | void (*result_subtype)(sqlite3_context*,unsigned int); |
| 104311 | 104325 | }; |
| 104312 | 104326 | |
| 104313 | 104327 | /* |
| @@ -104542,11 +104556,11 @@ | ||
| 104542 | 104556 | /* Version 3.8.11 and later */ |
| 104543 | 104557 | #define sqlite3_value_dup sqlite3_api->value_dup |
| 104544 | 104558 | #define sqlite3_value_free sqlite3_api->value_free |
| 104545 | 104559 | #define sqlite3_result_zeroblob64 sqlite3_api->result_zeroblob64 |
| 104546 | 104560 | #define sqlite3_bind_zeroblob64 sqlite3_api->bind_zeroblob64 |
| 104547 | -/* Version 3.8.12 and later */ | |
| 104561 | +/* Version 3.9.0 and later */ | |
| 104548 | 104562 | #define sqlite3_value_subtype sqlite3_api->value_subtype |
| 104549 | 104563 | #define sqlite3_result_subtype sqlite3_api->result_subtype |
| 104550 | 104564 | #endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */ |
| 104551 | 104565 | |
| 104552 | 104566 | #if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) |
| @@ -104957,11 +104971,11 @@ | ||
| 104957 | 104971 | /* Version 3.8.11 and later */ |
| 104958 | 104972 | (sqlite3_value*(*)(const sqlite3_value*))sqlite3_value_dup, |
| 104959 | 104973 | sqlite3_value_free, |
| 104960 | 104974 | sqlite3_result_zeroblob64, |
| 104961 | 104975 | sqlite3_bind_zeroblob64, |
| 104962 | - /* Version 3.8.12 and later */ | |
| 104976 | + /* Version 3.9.0 and later */ | |
| 104963 | 104977 | sqlite3_value_subtype, |
| 104964 | 104978 | sqlite3_result_subtype |
| 104965 | 104979 | }; |
| 104966 | 104980 | |
| 104967 | 104981 | /* |
| @@ -111703,11 +111717,11 @@ | ||
| 111703 | 111717 | #endif |
| 111704 | 111718 | |
| 111705 | 111719 | #if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) |
| 111706 | 111720 | /* Forward Declarations */ |
| 111707 | 111721 | static void substExprList(sqlite3*, ExprList*, int, ExprList*); |
| 111708 | -static void substSelect(sqlite3*, Select *, int, ExprList *); | |
| 111722 | +static void substSelect(sqlite3*, Select *, int, ExprList*, int); | |
| 111709 | 111723 | |
| 111710 | 111724 | /* |
| 111711 | 111725 | ** Scan through the expression pExpr. Replace every reference to |
| 111712 | 111726 | ** a column in table number iTable with a copy of the iColumn-th |
| 111713 | 111727 | ** entry in pEList. (But leave references to the ROWID column |
| @@ -111740,11 +111754,11 @@ | ||
| 111740 | 111754 | } |
| 111741 | 111755 | }else{ |
| 111742 | 111756 | pExpr->pLeft = substExpr(db, pExpr->pLeft, iTable, pEList); |
| 111743 | 111757 | pExpr->pRight = substExpr(db, pExpr->pRight, iTable, pEList); |
| 111744 | 111758 | if( ExprHasProperty(pExpr, EP_xIsSelect) ){ |
| 111745 | - substSelect(db, pExpr->x.pSelect, iTable, pEList); | |
| 111759 | + substSelect(db, pExpr->x.pSelect, iTable, pEList, 1); | |
| 111746 | 111760 | }else{ |
| 111747 | 111761 | substExprList(db, pExpr->x.pList, iTable, pEList); |
| 111748 | 111762 | } |
| 111749 | 111763 | } |
| 111750 | 111764 | return pExpr; |
| @@ -111763,29 +111777,32 @@ | ||
| 111763 | 111777 | } |
| 111764 | 111778 | static void substSelect( |
| 111765 | 111779 | sqlite3 *db, /* Report malloc errors here */ |
| 111766 | 111780 | Select *p, /* SELECT statement in which to make substitutions */ |
| 111767 | 111781 | int iTable, /* Table to be replaced */ |
| 111768 | - ExprList *pEList /* Substitute values */ | |
| 111782 | + ExprList *pEList, /* Substitute values */ | |
| 111783 | + int doPrior /* Do substitutes on p->pPrior too */ | |
| 111769 | 111784 | ){ |
| 111770 | 111785 | SrcList *pSrc; |
| 111771 | 111786 | struct SrcList_item *pItem; |
| 111772 | 111787 | int i; |
| 111773 | 111788 | if( !p ) return; |
| 111774 | - substExprList(db, p->pEList, iTable, pEList); | |
| 111775 | - substExprList(db, p->pGroupBy, iTable, pEList); | |
| 111776 | - substExprList(db, p->pOrderBy, iTable, pEList); | |
| 111777 | - p->pHaving = substExpr(db, p->pHaving, iTable, pEList); | |
| 111778 | - p->pWhere = substExpr(db, p->pWhere, iTable, pEList); | |
| 111779 | - substSelect(db, p->pPrior, iTable, pEList); | |
| 111780 | - pSrc = p->pSrc; | |
| 111781 | - assert( pSrc ); /* Even for (SELECT 1) we have: pSrc!=0 but pSrc->nSrc==0 */ | |
| 111782 | - if( ALWAYS(pSrc) ){ | |
| 111789 | + do{ | |
| 111790 | + substExprList(db, p->pEList, iTable, pEList); | |
| 111791 | + substExprList(db, p->pGroupBy, iTable, pEList); | |
| 111792 | + substExprList(db, p->pOrderBy, iTable, pEList); | |
| 111793 | + p->pHaving = substExpr(db, p->pHaving, iTable, pEList); | |
| 111794 | + p->pWhere = substExpr(db, p->pWhere, iTable, pEList); | |
| 111795 | + pSrc = p->pSrc; | |
| 111796 | + assert( pSrc!=0 ); | |
| 111783 | 111797 | for(i=pSrc->nSrc, pItem=pSrc->a; i>0; i--, pItem++){ |
| 111784 | - substSelect(db, pItem->pSelect, iTable, pEList); | |
| 111798 | + substSelect(db, pItem->pSelect, iTable, pEList, 1); | |
| 111799 | + if( pItem->fg.isTabFunc ){ | |
| 111800 | + substExprList(db, pItem->u1.pFuncArg, iTable, pEList); | |
| 111801 | + } | |
| 111785 | 111802 | } |
| 111786 | - } | |
| 111803 | + }while( doPrior && (p = p->pPrior)!=0 ); | |
| 111787 | 111804 | } |
| 111788 | 111805 | #endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */ |
| 111789 | 111806 | |
| 111790 | 111807 | #if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) |
| 111791 | 111808 | /* |
| @@ -111933,11 +111950,11 @@ | ||
| 111933 | 111950 | int iFrom, /* Index in p->pSrc->a[] of the inner subquery */ |
| 111934 | 111951 | int isAgg, /* True if outer SELECT uses aggregate functions */ |
| 111935 | 111952 | int subqueryIsAgg /* True if the subquery uses aggregate functions */ |
| 111936 | 111953 | ){ |
| 111937 | 111954 | const char *zSavedAuthContext = pParse->zAuthContext; |
| 111938 | - Select *pParent; | |
| 111955 | + Select *pParent; /* Current UNION ALL term of the other query */ | |
| 111939 | 111956 | Select *pSub; /* The inner query or "subquery" */ |
| 111940 | 111957 | Select *pSub1; /* Pointer to the rightmost select in sub-query */ |
| 111941 | 111958 | SrcList *pSrc; /* The FROM clause of the outer query */ |
| 111942 | 111959 | SrcList *pSubSrc; /* The FROM clause of the subquery */ |
| 111943 | 111960 | ExprList *pList; /* The result set of the outer query */ |
| @@ -112228,13 +112245,13 @@ | ||
| 112228 | 112245 | ** |
| 112229 | 112246 | ** SELECT * FROM tabA, (SELECT * FROM sub1, sub2), tabB; |
| 112230 | 112247 | ** |
| 112231 | 112248 | ** The outer query has 3 slots in its FROM clause. One slot of the |
| 112232 | 112249 | ** outer query (the middle slot) is used by the subquery. The next |
| 112233 | - ** block of code will expand the out query to 4 slots. The middle | |
| 112234 | - ** slot is expanded to two slots in order to make space for the | |
| 112235 | - ** two elements in the FROM clause of the subquery. | |
| 112250 | + ** block of code will expand the outer query FROM clause to 4 slots. | |
| 112251 | + ** The middle slot is expanded to two slots in order to make space | |
| 112252 | + ** for the two elements in the FROM clause of the subquery. | |
| 112236 | 112253 | */ |
| 112237 | 112254 | if( nSubSrc>1 ){ |
| 112238 | 112255 | pParent->pSrc = pSrc = sqlite3SrcListEnlarge(db, pSrc, nSubSrc-1,iFrom+1); |
| 112239 | 112256 | if( db->mallocFailed ){ |
| 112240 | 112257 | break; |
| @@ -112269,15 +112286,10 @@ | ||
| 112269 | 112286 | char *zName = sqlite3DbStrDup(db, pList->a[i].zSpan); |
| 112270 | 112287 | sqlite3Dequote(zName); |
| 112271 | 112288 | pList->a[i].zName = zName; |
| 112272 | 112289 | } |
| 112273 | 112290 | } |
| 112274 | - substExprList(db, pParent->pEList, iParent, pSub->pEList); | |
| 112275 | - if( isAgg ){ | |
| 112276 | - substExprList(db, pParent->pGroupBy, iParent, pSub->pEList); | |
| 112277 | - pParent->pHaving = substExpr(db, pParent->pHaving, iParent, pSub->pEList); | |
| 112278 | - } | |
| 112279 | 112291 | if( pSub->pOrderBy ){ |
| 112280 | 112292 | /* At this point, any non-zero iOrderByCol values indicate that the |
| 112281 | 112293 | ** ORDER BY column expression is identical to the iOrderByCol'th |
| 112282 | 112294 | ** expression returned by SELECT statement pSub. Since these values |
| 112283 | 112295 | ** do not necessarily correspond to columns in SELECT statement pParent, |
| @@ -112293,31 +112305,24 @@ | ||
| 112293 | 112305 | } |
| 112294 | 112306 | assert( pParent->pOrderBy==0 ); |
| 112295 | 112307 | assert( pSub->pPrior==0 ); |
| 112296 | 112308 | pParent->pOrderBy = pOrderBy; |
| 112297 | 112309 | pSub->pOrderBy = 0; |
| 112298 | - }else if( pParent->pOrderBy ){ | |
| 112299 | - substExprList(db, pParent->pOrderBy, iParent, pSub->pEList); | |
| 112300 | - } | |
| 112301 | - if( pSub->pWhere ){ | |
| 112302 | - pWhere = sqlite3ExprDup(db, pSub->pWhere, 0); | |
| 112303 | - }else{ | |
| 112304 | - pWhere = 0; | |
| 112305 | - } | |
| 112310 | + } | |
| 112311 | + pWhere = sqlite3ExprDup(db, pSub->pWhere, 0); | |
| 112306 | 112312 | if( subqueryIsAgg ){ |
| 112307 | 112313 | assert( pParent->pHaving==0 ); |
| 112308 | 112314 | pParent->pHaving = pParent->pWhere; |
| 112309 | 112315 | pParent->pWhere = pWhere; |
| 112310 | - pParent->pHaving = substExpr(db, pParent->pHaving, iParent, pSub->pEList); | |
| 112311 | 112316 | pParent->pHaving = sqlite3ExprAnd(db, pParent->pHaving, |
| 112312 | 112317 | sqlite3ExprDup(db, pSub->pHaving, 0)); |
| 112313 | 112318 | assert( pParent->pGroupBy==0 ); |
| 112314 | 112319 | pParent->pGroupBy = sqlite3ExprListDup(db, pSub->pGroupBy, 0); |
| 112315 | 112320 | }else{ |
| 112316 | - pParent->pWhere = substExpr(db, pParent->pWhere, iParent, pSub->pEList); | |
| 112317 | 112321 | pParent->pWhere = sqlite3ExprAnd(db, pParent->pWhere, pWhere); |
| 112318 | 112322 | } |
| 112323 | + substSelect(db, pParent, iParent, pSub->pEList, 0); | |
| 112319 | 112324 | |
| 112320 | 112325 | /* The flattened query is distinct if either the inner or the |
| 112321 | 112326 | ** outer query is distinct. |
| 112322 | 112327 | */ |
| 112323 | 112328 | pParent->selFlags |= pSub->selFlags & SF_Distinct; |
| @@ -112878,19 +112883,23 @@ | ||
| 112878 | 112883 | return WRC_Abort; |
| 112879 | 112884 | } |
| 112880 | 112885 | pTab->nRef++; |
| 112881 | 112886 | #if !defined(SQLITE_OMIT_VIEW) || !defined (SQLITE_OMIT_VIRTUALTABLE) |
| 112882 | 112887 | if( pTab->pSelect || IsVirtual(pTab) ){ |
| 112888 | + i16 nCol; | |
| 112883 | 112889 | if( sqlite3ViewGetColumnNames(pParse, pTab) ) return WRC_Abort; |
| 112884 | 112890 | assert( pFrom->pSelect==0 ); |
| 112885 | 112891 | if( pFrom->fg.isTabFunc && !IsVirtual(pTab) ){ |
| 112886 | 112892 | sqlite3ErrorMsg(pParse, "'%s' is not a function", pTab->zName); |
| 112887 | 112893 | return WRC_Abort; |
| 112888 | 112894 | } |
| 112889 | 112895 | pFrom->pSelect = sqlite3SelectDup(db, pTab->pSelect, 0); |
| 112890 | 112896 | sqlite3SelectSetName(pFrom->pSelect, pTab->zName); |
| 112897 | + nCol = pTab->nCol; | |
| 112898 | + pTab->nCol = -1; | |
| 112891 | 112899 | sqlite3WalkSelect(pWalker, pFrom->pSelect); |
| 112900 | + pTab->nCol = nCol; | |
| 112892 | 112901 | } |
| 112893 | 112902 | #endif |
| 112894 | 112903 | } |
| 112895 | 112904 | |
| 112896 | 112905 | /* Locate the index named by the INDEXED BY clause, if any. */ |
| @@ -158656,10 +158665,14 @@ | ||
| 158656 | 158665 | #ifndef _SQLITE3RBU_H |
| 158657 | 158666 | #define _SQLITE3RBU_H |
| 158658 | 158667 | |
| 158659 | 158668 | /* #include "sqlite3.h" ** Required for error code definitions ** */ |
| 158660 | 158669 | |
| 158670 | +#if 0 | |
| 158671 | +extern "C" { | |
| 158672 | +#endif | |
| 158673 | + | |
| 158661 | 158674 | typedef struct sqlite3rbu sqlite3rbu; |
| 158662 | 158675 | |
| 158663 | 158676 | /* |
| 158664 | 158677 | ** Open an RBU handle. |
| 158665 | 158678 | ** |
| @@ -158834,10 +158847,14 @@ | ||
| 158834 | 158847 | ** before all database handles that use it have been closed, the results |
| 158835 | 158848 | ** are undefined. |
| 158836 | 158849 | */ |
| 158837 | 158850 | SQLITE_API void SQLITE_STDCALL sqlite3rbu_destroy_vfs(const char *zName); |
| 158838 | 158851 | |
| 158852 | +#if 0 | |
| 158853 | +} /* end of the 'extern "C"' block */ | |
| 158854 | +#endif | |
| 158855 | + | |
| 158839 | 158856 | #endif /* _SQLITE3RBU_H */ |
| 158840 | 158857 | |
| 158841 | 158858 | /************** End of sqlite3rbu.h ******************************************/ |
| 158842 | 158859 | /************** Continuing where we left off in sqlite3rbu.c *****************/ |
| 158843 | 158860 | |
| @@ -164400,11 +164417,11 @@ | ||
| 164400 | 164417 | |
| 164401 | 164418 | /* |
| 164402 | 164419 | ** Compare the OBJECT label at pNode against zKey,nKey. Return true on |
| 164403 | 164420 | ** a match. |
| 164404 | 164421 | */ |
| 164405 | -static int jsonLabelCompare(JsonNode *pNode, const char *zKey, int nKey){ | |
| 164422 | +static int jsonLabelCompare(JsonNode *pNode, const char *zKey, u32 nKey){ | |
| 164406 | 164423 | if( pNode->jnFlags & JNODE_RAW ){ |
| 164407 | 164424 | if( pNode->n!=nKey ) return 0; |
| 164408 | 164425 | return strncmp(pNode->u.zJContent, zKey, nKey)==0; |
| 164409 | 164426 | }else{ |
| 164410 | 164427 | if( pNode->n!=nKey+2 ) return 0; |
| @@ -165589,10 +165606,14 @@ | ||
| 165589 | 165606 | #ifndef _FTS5_H |
| 165590 | 165607 | #define _FTS5_H |
| 165591 | 165608 | |
| 165592 | 165609 | /* #include "sqlite3.h" */ |
| 165593 | 165610 | |
| 165611 | +#if 0 | |
| 165612 | +extern "C" { | |
| 165613 | +#endif | |
| 165614 | + | |
| 165594 | 165615 | /************************************************************************* |
| 165595 | 165616 | ** CUSTOM AUXILIARY FUNCTIONS |
| 165596 | 165617 | ** |
| 165597 | 165618 | ** Virtual table implementations may overload SQL functions by implementing |
| 165598 | 165619 | ** the sqlite3_module.xFindFunction() method. |
| @@ -166074,10 +166095,14 @@ | ||
| 166074 | 166095 | |
| 166075 | 166096 | /* |
| 166076 | 166097 | ** END OF REGISTRATION API |
| 166077 | 166098 | *************************************************************************/ |
| 166078 | 166099 | |
| 166100 | +#if 0 | |
| 166101 | +} /* end of the 'extern "C"' block */ | |
| 166102 | +#endif | |
| 166103 | + | |
| 166079 | 166104 | #endif /* _FTS5_H */ |
| 166080 | 166105 | |
| 166081 | 166106 | |
| 166082 | 166107 | /* |
| 166083 | 166108 | ** 2014 May 31 |
| @@ -166332,11 +166357,10 @@ | ||
| 166332 | 166357 | #define FTS5_POS2OFFSET(iPos) (int)(iPos & 0xFFFFFFFF) |
| 166333 | 166358 | |
| 166334 | 166359 | typedef struct Fts5PoslistReader Fts5PoslistReader; |
| 166335 | 166360 | struct Fts5PoslistReader { |
| 166336 | 166361 | /* Variables used only by sqlite3Fts5PoslistIterXXX() functions. */ |
| 166337 | - int iCol; /* If (iCol>=0), this column only */ | |
| 166338 | 166362 | const u8 *a; /* Position list to iterate through */ |
| 166339 | 166363 | int n; /* Size of buffer at a[] in bytes */ |
| 166340 | 166364 | int i; /* Current offset in a[] */ |
| 166341 | 166365 | |
| 166342 | 166366 | u8 bFlag; /* For client use (any custom purpose) */ |
| @@ -166344,11 +166368,10 @@ | ||
| 166344 | 166368 | /* Output variables */ |
| 166345 | 166369 | u8 bEof; /* Set to true at EOF */ |
| 166346 | 166370 | i64 iPos; /* (iCol<<32) + iPos */ |
| 166347 | 166371 | }; |
| 166348 | 166372 | static int sqlite3Fts5PoslistReaderInit( |
| 166349 | - int iCol, /* If (iCol>=0), this column only */ | |
| 166350 | 166373 | const u8 *a, int n, /* Poslist buffer to iterate through */ |
| 166351 | 166374 | Fts5PoslistReader *pIter /* Iterator object to initialize */ |
| 166352 | 166375 | ); |
| 166353 | 166376 | static int sqlite3Fts5PoslistReaderNext(Fts5PoslistReader*); |
| 166354 | 166377 | |
| @@ -166425,11 +166448,11 @@ | ||
| 166425 | 166448 | */ |
| 166426 | 166449 | static int sqlite3Fts5IterEof(Fts5IndexIter*); |
| 166427 | 166450 | static int sqlite3Fts5IterNext(Fts5IndexIter*); |
| 166428 | 166451 | static int sqlite3Fts5IterNextFrom(Fts5IndexIter*, i64 iMatch); |
| 166429 | 166452 | static i64 sqlite3Fts5IterRowid(Fts5IndexIter*); |
| 166430 | -static int sqlite3Fts5IterPoslist(Fts5IndexIter*, const u8 **pp, int *pn, i64 *pi); | |
| 166453 | +static int sqlite3Fts5IterPoslist(Fts5IndexIter*,Fts5Colset*, const u8**, int*, i64*); | |
| 166431 | 166454 | static int sqlite3Fts5IterPoslistBuffer(Fts5IndexIter *pIter, Fts5Buffer *pBuf); |
| 166432 | 166455 | |
| 166433 | 166456 | /* |
| 166434 | 166457 | ** Close an iterator opened by sqlite3Fts5IndexQuery(). |
| 166435 | 166458 | */ |
| @@ -168735,30 +168758,24 @@ | ||
| 168735 | 168758 | /* |
| 168736 | 168759 | ** Advance the iterator object passed as the only argument. Return true |
| 168737 | 168760 | ** if the iterator reaches EOF, or false otherwise. |
| 168738 | 168761 | */ |
| 168739 | 168762 | static int sqlite3Fts5PoslistReaderNext(Fts5PoslistReader *pIter){ |
| 168740 | - if( sqlite3Fts5PoslistNext64(pIter->a, pIter->n, &pIter->i, &pIter->iPos) | |
| 168741 | - || (pIter->iCol>=0 && (pIter->iPos >> 32) > pIter->iCol) | |
| 168742 | - ){ | |
| 168763 | + if( sqlite3Fts5PoslistNext64(pIter->a, pIter->n, &pIter->i, &pIter->iPos) ){ | |
| 168743 | 168764 | pIter->bEof = 1; |
| 168744 | 168765 | } |
| 168745 | 168766 | return pIter->bEof; |
| 168746 | 168767 | } |
| 168747 | 168768 | |
| 168748 | 168769 | static int sqlite3Fts5PoslistReaderInit( |
| 168749 | - int iCol, /* If (iCol>=0), this column only */ | |
| 168750 | 168770 | const u8 *a, int n, /* Poslist buffer to iterate through */ |
| 168751 | 168771 | Fts5PoslistReader *pIter /* Iterator object to initialize */ |
| 168752 | 168772 | ){ |
| 168753 | 168773 | memset(pIter, 0, sizeof(*pIter)); |
| 168754 | 168774 | pIter->a = a; |
| 168755 | 168775 | pIter->n = n; |
| 168756 | - pIter->iCol = iCol; | |
| 168757 | - do { | |
| 168758 | - sqlite3Fts5PoslistReaderNext(pIter); | |
| 168759 | - }while( pIter->bEof==0 && (pIter->iPos >> 32)<iCol ); | |
| 168776 | + sqlite3Fts5PoslistReaderNext(pIter); | |
| 168760 | 168777 | return pIter->bEof; |
| 168761 | 168778 | } |
| 168762 | 168779 | |
| 168763 | 168780 | static int sqlite3Fts5PoslistWriterAppend( |
| 168764 | 168781 | Fts5Buffer *pBuf, |
| @@ -169982,18 +169999,10 @@ | ||
| 169982 | 169999 | sqlite3_free(p->apExprPhrase); |
| 169983 | 170000 | sqlite3_free(p); |
| 169984 | 170001 | } |
| 169985 | 170002 | } |
| 169986 | 170003 | |
| 169987 | -static int fts5ExprColsetTest(Fts5Colset *pColset, int iCol){ | |
| 169988 | - int i; | |
| 169989 | - for(i=0; i<pColset->nCol; i++){ | |
| 169990 | - if( pColset->aiCol[i]==iCol ) return 1; | |
| 169991 | - } | |
| 169992 | - return 0; | |
| 169993 | -} | |
| 169994 | - | |
| 169995 | 170004 | /* |
| 169996 | 170005 | ** Argument pTerm must be a synonym iterator. Return the current rowid |
| 169997 | 170006 | ** that it points to. |
| 169998 | 170007 | */ |
| 169999 | 170008 | static i64 fts5ExprSynonymRowid(Fts5ExprTerm *pTerm, int bDesc, int *pbEof){ |
| @@ -170020,10 +170029,11 @@ | ||
| 170020 | 170029 | /* |
| 170021 | 170030 | ** Argument pTerm must be a synonym iterator. |
| 170022 | 170031 | */ |
| 170023 | 170032 | static int fts5ExprSynonymPoslist( |
| 170024 | 170033 | Fts5ExprTerm *pTerm, |
| 170034 | + Fts5Colset *pColset, | |
| 170025 | 170035 | i64 iRowid, |
| 170026 | 170036 | int *pbDel, /* OUT: Caller should sqlite3_free(*pa) */ |
| 170027 | 170037 | u8 **pa, int *pn |
| 170028 | 170038 | ){ |
| 170029 | 170039 | Fts5PoslistReader aStatic[4]; |
| @@ -170038,11 +170048,11 @@ | ||
| 170038 | 170048 | Fts5IndexIter *pIter = p->pIter; |
| 170039 | 170049 | if( sqlite3Fts5IterEof(pIter)==0 && sqlite3Fts5IterRowid(pIter)==iRowid ){ |
| 170040 | 170050 | const u8 *a; |
| 170041 | 170051 | int n; |
| 170042 | 170052 | i64 dummy; |
| 170043 | - rc = sqlite3Fts5IterPoslist(pIter, &a, &n, &dummy); | |
| 170053 | + rc = sqlite3Fts5IterPoslist(pIter, pColset, &a, &n, &dummy); | |
| 170044 | 170054 | if( rc!=SQLITE_OK ) goto synonym_poslist_out; |
| 170045 | 170055 | if( nIter==nAlloc ){ |
| 170046 | 170056 | int nByte = sizeof(Fts5PoslistReader) * nAlloc * 2; |
| 170047 | 170057 | Fts5PoslistReader *aNew = (Fts5PoslistReader*)sqlite3_malloc(nByte); |
| 170048 | 170058 | if( aNew==0 ){ |
| @@ -170052,11 +170062,11 @@ | ||
| 170052 | 170062 | memcpy(aNew, aIter, sizeof(Fts5PoslistReader) * nIter); |
| 170053 | 170063 | nAlloc = nAlloc*2; |
| 170054 | 170064 | if( aIter!=aStatic ) sqlite3_free(aIter); |
| 170055 | 170065 | aIter = aNew; |
| 170056 | 170066 | } |
| 170057 | - sqlite3Fts5PoslistReaderInit(-1, a, n, &aIter[nIter]); | |
| 170067 | + sqlite3Fts5PoslistReaderInit(a, n, &aIter[nIter]); | |
| 170058 | 170068 | assert( aIter[nIter].bEof==0 ); |
| 170059 | 170069 | nIter++; |
| 170060 | 170070 | } |
| 170061 | 170071 | } |
| 170062 | 170072 | |
| @@ -170120,17 +170130,11 @@ | ||
| 170120 | 170130 | Fts5PoslistWriter writer = {0}; |
| 170121 | 170131 | Fts5PoslistReader aStatic[4]; |
| 170122 | 170132 | Fts5PoslistReader *aIter = aStatic; |
| 170123 | 170133 | int i; |
| 170124 | 170134 | int rc = SQLITE_OK; |
| 170125 | - int iCol = -1; | |
| 170126 | 170135 | |
| 170127 | - if( pColset && pColset->nCol==1 ){ | |
| 170128 | - iCol = pColset->aiCol[0]; | |
| 170129 | - pColset = 0; | |
| 170130 | - } | |
| 170131 | - | |
| 170132 | 170136 | fts5BufferZero(&pPhrase->poslist); |
| 170133 | 170137 | |
| 170134 | 170138 | /* If the aStatic[] array is not large enough, allocate a large array |
| 170135 | 170139 | ** using sqlite3_malloc(). This approach could be improved upon. */ |
| 170136 | 170140 | if( pPhrase->nTerm>(sizeof(aStatic) / sizeof(aStatic[0])) ){ |
| @@ -170146,16 +170150,18 @@ | ||
| 170146 | 170150 | i64 dummy; |
| 170147 | 170151 | int n = 0; |
| 170148 | 170152 | int bFlag = 0; |
| 170149 | 170153 | const u8 *a = 0; |
| 170150 | 170154 | if( pTerm->pSynonym ){ |
| 170151 | - rc = fts5ExprSynonymPoslist(pTerm, pNode->iRowid, &bFlag, (u8**)&a, &n); | |
| 170155 | + rc = fts5ExprSynonymPoslist( | |
| 170156 | + pTerm, pColset, pNode->iRowid, &bFlag, (u8**)&a, &n | |
| 170157 | + ); | |
| 170152 | 170158 | }else{ |
| 170153 | - rc = sqlite3Fts5IterPoslist(pTerm->pIter, &a, &n, &dummy); | |
| 170159 | + rc = sqlite3Fts5IterPoslist(pTerm->pIter, pColset, &a, &n, &dummy); | |
| 170154 | 170160 | } |
| 170155 | 170161 | if( rc!=SQLITE_OK ) goto ismatch_out; |
| 170156 | - sqlite3Fts5PoslistReaderInit(iCol, a, n, &aIter[i]); | |
| 170162 | + sqlite3Fts5PoslistReaderInit(a, n, &aIter[i]); | |
| 170157 | 170163 | aIter[i].bFlag = bFlag; |
| 170158 | 170164 | if( aIter[i].bEof ) goto ismatch_out; |
| 170159 | 170165 | } |
| 170160 | 170166 | |
| 170161 | 170167 | while( 1 ){ |
| @@ -170174,15 +170180,13 @@ | ||
| 170174 | 170180 | if( pPos->iPos>iAdj ) iPos = pPos->iPos-i; |
| 170175 | 170181 | } |
| 170176 | 170182 | } |
| 170177 | 170183 | }while( bMatch==0 ); |
| 170178 | 170184 | |
| 170179 | - if( pColset==0 || fts5ExprColsetTest(pColset, FTS5_POS2COLUMN(iPos)) ){ | |
| 170180 | - /* Append position iPos to the output */ | |
| 170181 | - rc = sqlite3Fts5PoslistWriterAppend(&pPhrase->poslist, &writer, iPos); | |
| 170182 | - if( rc!=SQLITE_OK ) goto ismatch_out; | |
| 170183 | - } | |
| 170185 | + /* Append position iPos to the output */ | |
| 170186 | + rc = sqlite3Fts5PoslistWriterAppend(&pPhrase->poslist, &writer, iPos); | |
| 170187 | + if( rc!=SQLITE_OK ) goto ismatch_out; | |
| 170184 | 170188 | |
| 170185 | 170189 | for(i=0; i<pPhrase->nTerm; i++){ |
| 170186 | 170190 | if( sqlite3Fts5PoslistReaderNext(&aIter[i]) ) goto ismatch_out; |
| 170187 | 170191 | } |
| 170188 | 170192 | } |
| @@ -170473,65 +170477,10 @@ | ||
| 170473 | 170477 | *piLast = fts5ExprSynonymRowid(pTerm, bDesc, &bEof); |
| 170474 | 170478 | } |
| 170475 | 170479 | return bEof; |
| 170476 | 170480 | } |
| 170477 | 170481 | |
| 170478 | -/* | |
| 170479 | -** IN/OUT parameter (*pa) points to a position list n bytes in size. If | |
| 170480 | -** the position list contains entries for column iCol, then (*pa) is set | |
| 170481 | -** to point to the sub-position-list for that column and the number of | |
| 170482 | -** bytes in it returned. Or, if the argument position list does not | |
| 170483 | -** contain any entries for column iCol, return 0. | |
| 170484 | -*/ | |
| 170485 | -static int fts5ExprExtractCol( | |
| 170486 | - const u8 **pa, /* IN/OUT: Pointer to poslist */ | |
| 170487 | - int n, /* IN: Size of poslist in bytes */ | |
| 170488 | - int iCol /* Column to extract from poslist */ | |
| 170489 | -){ | |
| 170490 | - int iCurrent = 0; | |
| 170491 | - const u8 *p = *pa; | |
| 170492 | - const u8 *pEnd = &p[n]; /* One byte past end of position list */ | |
| 170493 | - u8 prev = 0; | |
| 170494 | - | |
| 170495 | - while( iCol!=iCurrent ){ | |
| 170496 | - /* Advance pointer p until it points to pEnd or an 0x01 byte that is | |
| 170497 | - ** not part of a varint */ | |
| 170498 | - while( (prev & 0x80) || *p!=0x01 ){ | |
| 170499 | - prev = *p++; | |
| 170500 | - if( p==pEnd ) return 0; | |
| 170501 | - } | |
| 170502 | - *pa = p++; | |
| 170503 | - p += fts5GetVarint32(p, iCurrent); | |
| 170504 | - } | |
| 170505 | - | |
| 170506 | - /* Advance pointer p until it points to pEnd or an 0x01 byte that is | |
| 170507 | - ** not part of a varint */ | |
| 170508 | - assert( (prev & 0x80)==0 ); | |
| 170509 | - while( p<pEnd && ((prev & 0x80) || *p!=0x01) ){ | |
| 170510 | - prev = *p++; | |
| 170511 | - } | |
| 170512 | - return p - (*pa); | |
| 170513 | -} | |
| 170514 | - | |
| 170515 | -static int fts5ExprExtractColset ( | |
| 170516 | - Fts5Colset *pColset, /* Colset to filter on */ | |
| 170517 | - const u8 *pPos, int nPos, /* Position list */ | |
| 170518 | - Fts5Buffer *pBuf /* Output buffer */ | |
| 170519 | -){ | |
| 170520 | - int rc = SQLITE_OK; | |
| 170521 | - int i; | |
| 170522 | - | |
| 170523 | - fts5BufferZero(pBuf); | |
| 170524 | - for(i=0; i<pColset->nCol; i++){ | |
| 170525 | - const u8 *pSub = pPos; | |
| 170526 | - int nSub = fts5ExprExtractCol(&pSub, nPos, pColset->aiCol[i]); | |
| 170527 | - if( nSub ){ | |
| 170528 | - fts5BufferAppendBlob(&rc, pBuf, nSub, pSub); | |
| 170529 | - } | |
| 170530 | - } | |
| 170531 | - return rc; | |
| 170532 | -} | |
| 170533 | 170482 | |
| 170534 | 170483 | static int fts5ExprNearTest( |
| 170535 | 170484 | int *pRc, |
| 170536 | 170485 | Fts5Expr *pExpr, /* Expression that pNear is a part of */ |
| 170537 | 170486 | Fts5ExprNode *pNode /* The "NEAR" node (FTS5_STRING) */ |
| @@ -170575,38 +170524,19 @@ | ||
| 170575 | 170524 | ** expressions. */ |
| 170576 | 170525 | Fts5ExprNearset *pNear = pNode->pNear; |
| 170577 | 170526 | Fts5ExprPhrase *pPhrase = pNear->apPhrase[0]; |
| 170578 | 170527 | Fts5IndexIter *pIter = pPhrase->aTerm[0].pIter; |
| 170579 | 170528 | Fts5Colset *pColset = pNear->pColset; |
| 170580 | - const u8 *pPos; | |
| 170581 | - int nPos; | |
| 170582 | 170529 | int rc; |
| 170583 | 170530 | |
| 170584 | 170531 | assert( pNode->eType==FTS5_TERM ); |
| 170585 | 170532 | assert( pNear->nPhrase==1 && pPhrase->nTerm==1 ); |
| 170586 | 170533 | assert( pPhrase->aTerm[0].pSynonym==0 ); |
| 170587 | 170534 | |
| 170588 | - rc = sqlite3Fts5IterPoslist(pIter, &pPos, &nPos, &pNode->iRowid); | |
| 170589 | - | |
| 170590 | - /* If the term may match any column, then this must be a match. | |
| 170591 | - ** Return immediately in this case. Otherwise, try to find the | |
| 170592 | - ** part of the poslist that corresponds to the required column. | |
| 170593 | - ** If it can be found, return. If it cannot, the next iteration | |
| 170594 | - ** of the loop will test the next rowid in the database for this | |
| 170595 | - ** term. */ | |
| 170596 | - if( pColset==0 ){ | |
| 170597 | - assert( pPhrase->poslist.nSpace==0 ); | |
| 170598 | - pPhrase->poslist.p = (u8*)pPos; | |
| 170599 | - pPhrase->poslist.n = nPos; | |
| 170600 | - }else if( pColset->nCol==1 ){ | |
| 170601 | - assert( pPhrase->poslist.nSpace==0 ); | |
| 170602 | - pPhrase->poslist.n = fts5ExprExtractCol(&pPos, nPos, pColset->aiCol[0]); | |
| 170603 | - pPhrase->poslist.p = (u8*)pPos; | |
| 170604 | - }else if( rc==SQLITE_OK ){ | |
| 170605 | - rc = fts5ExprExtractColset(pColset, pPos, nPos, &pPhrase->poslist); | |
| 170606 | - } | |
| 170607 | - | |
| 170535 | + rc = sqlite3Fts5IterPoslist(pIter, pColset, | |
| 170536 | + (const u8**)&pPhrase->poslist.p, &pPhrase->poslist.n, &pNode->iRowid | |
| 170537 | + ); | |
| 170608 | 170538 | pNode->bNomatch = (pPhrase->poslist.n==0); |
| 170609 | 170539 | return rc; |
| 170610 | 170540 | } |
| 170611 | 170541 | |
| 170612 | 170542 | /* |
| @@ -172033,11 +171963,10 @@ | ||
| 172033 | 171963 | nRet = 0; |
| 172034 | 171964 | } |
| 172035 | 171965 | return nRet; |
| 172036 | 171966 | } |
| 172037 | 171967 | |
| 172038 | - | |
| 172039 | 171968 | /* |
| 172040 | 171969 | ** 2014 August 11 |
| 172041 | 171970 | ** |
| 172042 | 171971 | ** The author disclaims copyright to this source code. In place of |
| 172043 | 171972 | ** a legal notice, here is a blessing: |
| @@ -173018,12 +172947,13 @@ | ||
| 173018 | 172947 | Fts5Structure *pStruct; /* Database structure for this iterator */ |
| 173019 | 172948 | Fts5Buffer poslist; /* Buffer containing current poslist */ |
| 173020 | 172949 | |
| 173021 | 172950 | int nSeg; /* Size of aSeg[] array */ |
| 173022 | 172951 | int bRev; /* True to iterate in reverse order */ |
| 173023 | - int bSkipEmpty; /* True to skip deleted entries */ | |
| 173024 | - int bEof; /* True at EOF */ | |
| 172952 | + u8 bSkipEmpty; /* True to skip deleted entries */ | |
| 172953 | + u8 bEof; /* True at EOF */ | |
| 172954 | + u8 bFiltered; /* True if column-filter already applied */ | |
| 173025 | 172955 | |
| 173026 | 172956 | i64 iSwitchRowid; /* Firstest rowid of other than aFirst[1] */ |
| 173027 | 172957 | Fts5CResult *aFirst; /* Current merge state (see above) */ |
| 173028 | 172958 | Fts5SegIter aSeg[1]; /* Array of segment iterators */ |
| 173029 | 172959 | }; |
| @@ -173964,11 +173894,12 @@ | ||
| 173964 | 173894 | ** read. Before returning, set *pnSz to the number of bytes in the position |
| 173965 | 173895 | ** list, and *pbDel to true if the delete flag is set, or false otherwise. |
| 173966 | 173896 | */ |
| 173967 | 173897 | static int fts5GetPoslistSize(const u8 *p, int *pnSz, int *pbDel){ |
| 173968 | 173898 | int nSz; |
| 173969 | - int n = fts5GetVarint32(p, nSz); | |
| 173899 | + int n = 0; | |
| 173900 | + fts5FastGetVarint32(p, n, nSz); | |
| 173970 | 173901 | assert_nc( nSz>=0 ); |
| 173971 | 173902 | *pnSz = nSz/2; |
| 173972 | 173903 | *pbDel = nSz & 0x0001; |
| 173973 | 173904 | return n; |
| 173974 | 173905 | } |
| @@ -173985,17 +173916,16 @@ | ||
| 173985 | 173916 | ** position list content (if any). |
| 173986 | 173917 | */ |
| 173987 | 173918 | static void fts5SegIterLoadNPos(Fts5Index *p, Fts5SegIter *pIter){ |
| 173988 | 173919 | if( p->rc==SQLITE_OK ){ |
| 173989 | 173920 | int iOff = pIter->iLeafOffset; /* Offset to read at */ |
| 173921 | + int nSz; | |
| 173990 | 173922 | ASSERT_SZLEAF_OK(pIter->pLeaf); |
| 173991 | - if( iOff>=pIter->pLeaf->szLeaf ){ | |
| 173992 | - p->rc = FTS5_CORRUPT; | |
| 173993 | - }else{ | |
| 173994 | - const u8 *a = &pIter->pLeaf->p[iOff]; | |
| 173995 | - pIter->iLeafOffset += fts5GetPoslistSize(a, &pIter->nPos, &pIter->bDel); | |
| 173996 | - } | |
| 173923 | + fts5FastGetVarint32(pIter->pLeaf->p, iOff, nSz); | |
| 173924 | + pIter->bDel = (nSz & 0x0001); | |
| 173925 | + pIter->nPos = nSz>>1; | |
| 173926 | + pIter->iLeafOffset = iOff; | |
| 173997 | 173927 | } |
| 173998 | 173928 | } |
| 173999 | 173929 | |
| 174000 | 173930 | static void fts5SegIterLoadRowid(Fts5Index *p, Fts5SegIter *pIter){ |
| 174001 | 173931 | u8 *a = pIter->pLeaf->p; /* Buffer to read data from */ |
| @@ -175232,10 +175162,11 @@ | ||
| 175232 | 175162 | Fts5IndexIter *pNew; |
| 175233 | 175163 | pNew = fts5MultiIterAlloc(p, 2); |
| 175234 | 175164 | if( pNew ){ |
| 175235 | 175165 | Fts5SegIter *pIter = &pNew->aSeg[1]; |
| 175236 | 175166 | |
| 175167 | + pNew->bFiltered = 1; | |
| 175237 | 175168 | pIter->flags = FTS5_SEGITER_ONETERM; |
| 175238 | 175169 | if( pData->szLeaf>0 ){ |
| 175239 | 175170 | pIter->pLeaf = pData; |
| 175240 | 175171 | pIter->iLeafOffset = fts5GetVarint(pData->p, (u64*)&pIter->iRowid); |
| 175241 | 175172 | pIter->iEndofDoclist = pData->nn; |
| @@ -176447,11 +176378,11 @@ | ||
| 176447 | 176378 | void *pContext, |
| 176448 | 176379 | const u8 *pChunk, int nChunk |
| 176449 | 176380 | ){ |
| 176450 | 176381 | assert_nc( nChunk>=0 ); |
| 176451 | 176382 | if( nChunk>0 ){ |
| 176452 | - fts5BufferAppendBlob(&p->rc, (Fts5Buffer*)pContext, nChunk, pChunk); | |
| 176383 | + fts5BufferSafeAppendBlob((Fts5Buffer*)pContext, pChunk, nChunk); | |
| 176453 | 176384 | } |
| 176454 | 176385 | } |
| 176455 | 176386 | |
| 176456 | 176387 | typedef struct PoslistCallbackCtx PoslistCallbackCtx; |
| 176457 | 176388 | struct PoslistCallbackCtx { |
| @@ -176487,11 +176418,11 @@ | ||
| 176487 | 176418 | if( pCtx->eState==2 ){ |
| 176488 | 176419 | int iCol; |
| 176489 | 176420 | fts5FastGetVarint32(pChunk, i, iCol); |
| 176490 | 176421 | if( fts5IndexColsetTest(pCtx->pColset, iCol) ){ |
| 176491 | 176422 | pCtx->eState = 1; |
| 176492 | - fts5BufferAppendVarint(&p->rc, pCtx->pBuf, 1); | |
| 176423 | + fts5BufferSafeAppendVarint(pCtx->pBuf, 1); | |
| 176493 | 176424 | }else{ |
| 176494 | 176425 | pCtx->eState = 0; |
| 176495 | 176426 | } |
| 176496 | 176427 | } |
| 176497 | 176428 | |
| @@ -176499,11 +176430,11 @@ | ||
| 176499 | 176430 | while( i<nChunk && pChunk[i]!=0x01 ){ |
| 176500 | 176431 | while( pChunk[i] & 0x80 ) i++; |
| 176501 | 176432 | i++; |
| 176502 | 176433 | } |
| 176503 | 176434 | if( pCtx->eState ){ |
| 176504 | - fts5BufferAppendBlob(&p->rc, pCtx->pBuf, i-iStart, &pChunk[iStart]); | |
| 176435 | + fts5BufferSafeAppendBlob(pCtx->pBuf, &pChunk[iStart], i-iStart); | |
| 176505 | 176436 | } |
| 176506 | 176437 | if( i<nChunk ){ |
| 176507 | 176438 | int iCol; |
| 176508 | 176439 | iStart = i; |
| 176509 | 176440 | i++; |
| @@ -176511,11 +176442,11 @@ | ||
| 176511 | 176442 | pCtx->eState = 2; |
| 176512 | 176443 | }else{ |
| 176513 | 176444 | fts5FastGetVarint32(pChunk, i, iCol); |
| 176514 | 176445 | pCtx->eState = fts5IndexColsetTest(pCtx->pColset, iCol); |
| 176515 | 176446 | if( pCtx->eState ){ |
| 176516 | - fts5BufferAppendBlob(&p->rc, pCtx->pBuf, i-iStart, &pChunk[iStart]); | |
| 176447 | + fts5BufferSafeAppendBlob(pCtx->pBuf, &pChunk[iStart], i-iStart); | |
| 176517 | 176448 | iStart = i; |
| 176518 | 176449 | } |
| 176519 | 176450 | } |
| 176520 | 176451 | } |
| 176521 | 176452 | }while( i<nChunk ); |
| @@ -176532,60 +176463,127 @@ | ||
| 176532 | 176463 | Fts5Index *p, |
| 176533 | 176464 | Fts5SegIter *pSeg, |
| 176534 | 176465 | Fts5Colset *pColset, |
| 176535 | 176466 | Fts5Buffer *pBuf |
| 176536 | 176467 | ){ |
| 176537 | - if( pColset==0 ){ | |
| 176538 | - fts5ChunkIterate(p, pSeg, (void*)pBuf, fts5PoslistCallback); | |
| 176539 | - }else{ | |
| 176540 | - PoslistCallbackCtx sCtx; | |
| 176541 | - sCtx.pBuf = pBuf; | |
| 176542 | - sCtx.pColset = pColset; | |
| 176543 | - sCtx.eState = pColset ? fts5IndexColsetTest(pColset, 0) : 1; | |
| 176544 | - assert( sCtx.eState==0 || sCtx.eState==1 ); | |
| 176545 | - fts5ChunkIterate(p, pSeg, (void*)&sCtx, fts5PoslistFilterCallback); | |
| 176468 | + if( 0==fts5BufferGrow(&p->rc, pBuf, pSeg->nPos) ){ | |
| 176469 | + if( pColset==0 ){ | |
| 176470 | + fts5ChunkIterate(p, pSeg, (void*)pBuf, fts5PoslistCallback); | |
| 176471 | + }else{ | |
| 176472 | + PoslistCallbackCtx sCtx; | |
| 176473 | + sCtx.pBuf = pBuf; | |
| 176474 | + sCtx.pColset = pColset; | |
| 176475 | + sCtx.eState = pColset ? fts5IndexColsetTest(pColset, 0) : 1; | |
| 176476 | + assert( sCtx.eState==0 || sCtx.eState==1 ); | |
| 176477 | + fts5ChunkIterate(p, pSeg, (void*)&sCtx, fts5PoslistFilterCallback); | |
| 176478 | + } | |
| 176546 | 176479 | } |
| 176547 | 176480 | } |
| 176481 | + | |
| 176482 | +/* | |
| 176483 | +** IN/OUT parameter (*pa) points to a position list n bytes in size. If | |
| 176484 | +** the position list contains entries for column iCol, then (*pa) is set | |
| 176485 | +** to point to the sub-position-list for that column and the number of | |
| 176486 | +** bytes in it returned. Or, if the argument position list does not | |
| 176487 | +** contain any entries for column iCol, return 0. | |
| 176488 | +*/ | |
| 176489 | +static int fts5IndexExtractCol( | |
| 176490 | + const u8 **pa, /* IN/OUT: Pointer to poslist */ | |
| 176491 | + int n, /* IN: Size of poslist in bytes */ | |
| 176492 | + int iCol /* Column to extract from poslist */ | |
| 176493 | +){ | |
| 176494 | + int iCurrent = 0; /* Anything before the first 0x01 is col 0 */ | |
| 176495 | + const u8 *p = *pa; | |
| 176496 | + const u8 *pEnd = &p[n]; /* One byte past end of position list */ | |
| 176497 | + u8 prev = 0; | |
| 176498 | + | |
| 176499 | + while( iCol!=iCurrent ){ | |
| 176500 | + /* Advance pointer p until it points to pEnd or an 0x01 byte that is | |
| 176501 | + ** not part of a varint */ | |
| 176502 | + while( (prev & 0x80) || *p!=0x01 ){ | |
| 176503 | + prev = *p++; | |
| 176504 | + if( p==pEnd ) return 0; | |
| 176505 | + } | |
| 176506 | + *pa = p++; | |
| 176507 | + p += fts5GetVarint32(p, iCurrent); | |
| 176508 | + } | |
| 176509 | + | |
| 176510 | + /* Advance pointer p until it points to pEnd or an 0x01 byte that is | |
| 176511 | + ** not part of a varint */ | |
| 176512 | + assert( (prev & 0x80)==0 ); | |
| 176513 | + while( p<pEnd && ((prev & 0x80) || *p!=0x01) ){ | |
| 176514 | + prev = *p++; | |
| 176515 | + } | |
| 176516 | + return p - (*pa); | |
| 176517 | +} | |
| 176518 | + | |
| 176548 | 176519 | |
| 176549 | 176520 | /* |
| 176550 | 176521 | ** Iterator pMulti currently points to a valid entry (not EOF). This |
| 176551 | -** function appends a copy of the position-list of the entry pMulti | |
| 176552 | -** currently points to to buffer pBuf. | |
| 176522 | +** function appends the following to buffer pBuf: | |
| 176553 | 176523 | ** |
| 176554 | -** If an error occurs, an error code is left in p->rc. It is assumed | |
| 176555 | -** no error has already occurred when this function is called. | |
| 176524 | +** * The varint iDelta, and | |
| 176525 | +** * the position list that currently points to, including the size field. | |
| 176526 | +** | |
| 176527 | +** If argument pColset is NULL, then the position list is filtered according | |
| 176528 | +** to pColset before being appended to the buffer. If this means there are | |
| 176529 | +** no entries in the position list, nothing is appended to the buffer (not | |
| 176530 | +** even iDelta). | |
| 176531 | +** | |
| 176532 | +** If an error occurs, an error code is left in p->rc. | |
| 176556 | 176533 | */ |
| 176557 | -static int fts5MultiIterPoslist( | |
| 176534 | +static int fts5AppendPoslist( | |
| 176558 | 176535 | Fts5Index *p, |
| 176536 | + i64 iDelta, | |
| 176559 | 176537 | Fts5IndexIter *pMulti, |
| 176560 | 176538 | Fts5Colset *pColset, |
| 176561 | 176539 | Fts5Buffer *pBuf |
| 176562 | 176540 | ){ |
| 176563 | 176541 | if( p->rc==SQLITE_OK ){ |
| 176564 | - int iSz; | |
| 176565 | - int iData; | |
| 176566 | - | |
| 176567 | 176542 | Fts5SegIter *pSeg = &pMulti->aSeg[ pMulti->aFirst[1].iFirst ]; |
| 176568 | 176543 | assert( fts5MultiIterEof(p, pMulti)==0 ); |
| 176569 | - | |
| 176570 | - /* WRITEPOSLISTSIZE */ | |
| 176571 | - iSz = pBuf->n; | |
| 176572 | - fts5BufferSafeAppendVarint(pBuf, pSeg->nPos*2); | |
| 176573 | - iData = pBuf->n; | |
| 176574 | - | |
| 176575 | - fts5SegiterPoslist(p, pSeg, pColset, pBuf); | |
| 176576 | - | |
| 176577 | - if( pColset ){ | |
| 176578 | - int nActual = pBuf->n - iData; | |
| 176579 | - if( nActual!=pSeg->nPos ){ | |
| 176580 | - /* WRITEPOSLISTSIZE */ | |
| 176581 | - if( nActual==0 ){ | |
| 176582 | - return 1; | |
| 176544 | + assert( pSeg->nPos>0 ); | |
| 176545 | + if( 0==fts5BufferGrow(&p->rc, pBuf, pSeg->nPos+9+9) ){ | |
| 176546 | + int iSv1; | |
| 176547 | + int iSv2; | |
| 176548 | + int iData; | |
| 176549 | + | |
| 176550 | + /* Append iDelta */ | |
| 176551 | + iSv1 = pBuf->n; | |
| 176552 | + fts5BufferSafeAppendVarint(pBuf, iDelta); | |
| 176553 | + | |
| 176554 | + /* WRITEPOSLISTSIZE */ | |
| 176555 | + iSv2 = pBuf->n; | |
| 176556 | + fts5BufferSafeAppendVarint(pBuf, pSeg->nPos*2); | |
| 176557 | + iData = pBuf->n; | |
| 176558 | + | |
| 176559 | + if( pSeg->iLeafOffset+pSeg->nPos<=pSeg->pLeaf->szLeaf | |
| 176560 | + && (pColset==0 || pColset->nCol==1) | |
| 176561 | + ){ | |
| 176562 | + const u8 *pPos = &pSeg->pLeaf->p[pSeg->iLeafOffset]; | |
| 176563 | + int nPos; | |
| 176564 | + if( pColset ){ | |
| 176565 | + nPos = fts5IndexExtractCol(&pPos, pSeg->nPos, pColset->aiCol[0]); | |
| 176583 | 176566 | }else{ |
| 176584 | - int nReq = sqlite3Fts5GetVarintLen((u32)(nActual*2)); | |
| 176585 | - while( iSz<(iData-nReq) ){ pBuf->p[iSz++] = 0x80; } | |
| 176586 | - sqlite3Fts5PutVarint(&pBuf->p[iSz], nActual*2); | |
| 176567 | + nPos = pSeg->nPos; | |
| 176568 | + } | |
| 176569 | + fts5BufferSafeAppendBlob(pBuf, pPos, nPos); | |
| 176570 | + }else{ | |
| 176571 | + fts5SegiterPoslist(p, pSeg, pColset, pBuf); | |
| 176572 | + } | |
| 176573 | + | |
| 176574 | + if( pColset ){ | |
| 176575 | + int nActual = pBuf->n - iData; | |
| 176576 | + if( nActual!=pSeg->nPos ){ | |
| 176577 | + if( nActual==0 ){ | |
| 176578 | + pBuf->n = iSv1; | |
| 176579 | + return 1; | |
| 176580 | + }else{ | |
| 176581 | + int nReq = sqlite3Fts5GetVarintLen((u32)(nActual*2)); | |
| 176582 | + while( iSv2<(iData-nReq) ){ pBuf->p[iSv2++] = 0x80; } | |
| 176583 | + sqlite3Fts5PutVarint(&pBuf->p[iSv2], nActual*2); | |
| 176584 | + } | |
| 176587 | 176585 | } |
| 176588 | 176586 | } |
| 176589 | 176587 | } |
| 176590 | 176588 | } |
| 176591 | 176589 | |
| @@ -176789,19 +176787,12 @@ | ||
| 176789 | 176787 | } |
| 176790 | 176788 | } |
| 176791 | 176789 | iLastRowid = 0; |
| 176792 | 176790 | } |
| 176793 | 176791 | |
| 176794 | - if( 0==sqlite3Fts5BufferGrow(&p->rc, &doclist, 9) ){ | |
| 176795 | - int iSave = doclist.n; | |
| 176796 | - assert( doclist.n!=0 || iLastRowid==0 ); | |
| 176797 | - fts5BufferSafeAppendVarint(&doclist, iRowid - iLastRowid); | |
| 176798 | - if( fts5MultiIterPoslist(p, p1, pColset, &doclist) ){ | |
| 176799 | - doclist.n = iSave; | |
| 176800 | - }else{ | |
| 176801 | - iLastRowid = iRowid; | |
| 176802 | - } | |
| 176792 | + if( !fts5AppendPoslist(p, iRowid-iLastRowid, p1, pColset, &doclist) ){ | |
| 176793 | + iLastRowid = iRowid; | |
| 176803 | 176794 | } |
| 176804 | 176795 | } |
| 176805 | 176796 | |
| 176806 | 176797 | for(i=0; i<nBuf; i++){ |
| 176807 | 176798 | if( p->rc==SQLITE_OK ){ |
| @@ -177154,10 +177145,30 @@ | ||
| 177154 | 177145 | const char *z = (const char*)fts5MultiIterTerm(pIter, &n); |
| 177155 | 177146 | *pn = n-1; |
| 177156 | 177147 | return &z[1]; |
| 177157 | 177148 | } |
| 177158 | 177149 | |
| 177150 | + | |
| 177151 | +static int fts5IndexExtractColset ( | |
| 177152 | + Fts5Colset *pColset, /* Colset to filter on */ | |
| 177153 | + const u8 *pPos, int nPos, /* Position list */ | |
| 177154 | + Fts5Buffer *pBuf /* Output buffer */ | |
| 177155 | +){ | |
| 177156 | + int rc = SQLITE_OK; | |
| 177157 | + int i; | |
| 177158 | + | |
| 177159 | + fts5BufferZero(pBuf); | |
| 177160 | + for(i=0; i<pColset->nCol; i++){ | |
| 177161 | + const u8 *pSub = pPos; | |
| 177162 | + int nSub = fts5IndexExtractCol(&pSub, nPos, pColset->aiCol[i]); | |
| 177163 | + if( nSub ){ | |
| 177164 | + fts5BufferAppendBlob(&rc, pBuf, nSub, pSub); | |
| 177165 | + } | |
| 177166 | + } | |
| 177167 | + return rc; | |
| 177168 | +} | |
| 177169 | + | |
| 177159 | 177170 | |
| 177160 | 177171 | /* |
| 177161 | 177172 | ** Return a pointer to a buffer containing a copy of the position list for |
| 177162 | 177173 | ** the current entry. Output variable *pn is set to the size of the buffer |
| 177163 | 177174 | ** in bytes before returning. |
| @@ -177165,24 +177176,37 @@ | ||
| 177165 | 177176 | ** The returned position list does not include the "number of bytes" varint |
| 177166 | 177177 | ** field that starts the position list on disk. |
| 177167 | 177178 | */ |
| 177168 | 177179 | static int sqlite3Fts5IterPoslist( |
| 177169 | 177180 | Fts5IndexIter *pIter, |
| 177181 | + Fts5Colset *pColset, /* Column filter (or NULL) */ | |
| 177170 | 177182 | const u8 **pp, /* OUT: Pointer to position-list data */ |
| 177171 | 177183 | int *pn, /* OUT: Size of position-list in bytes */ |
| 177172 | 177184 | i64 *piRowid /* OUT: Current rowid */ |
| 177173 | 177185 | ){ |
| 177174 | 177186 | Fts5SegIter *pSeg = &pIter->aSeg[ pIter->aFirst[1].iFirst ]; |
| 177175 | 177187 | assert( pIter->pIndex->rc==SQLITE_OK ); |
| 177176 | 177188 | *piRowid = pSeg->iRowid; |
| 177177 | - *pn = pSeg->nPos; | |
| 177178 | - if( pSeg->iLeafOffset+pSeg->nPos <= pSeg->pLeaf->szLeaf ){ | |
| 177179 | - *pp = &pSeg->pLeaf->p[pSeg->iLeafOffset]; | |
| 177189 | + if( pSeg->iLeafOffset+pSeg->nPos<=pSeg->pLeaf->szLeaf ){ | |
| 177190 | + u8 *pPos = &pSeg->pLeaf->p[pSeg->iLeafOffset]; | |
| 177191 | + if( pColset==0 || pIter->bFiltered ){ | |
| 177192 | + *pn = pSeg->nPos; | |
| 177193 | + *pp = pPos; | |
| 177194 | + }else if( pColset->nCol==1 ){ | |
| 177195 | + *pp = pPos; | |
| 177196 | + *pn = fts5IndexExtractCol(pp, pSeg->nPos, pColset->aiCol[0]); | |
| 177197 | + }else{ | |
| 177198 | + fts5BufferZero(&pIter->poslist); | |
| 177199 | + fts5IndexExtractColset(pColset, pPos, pSeg->nPos, &pIter->poslist); | |
| 177200 | + *pp = pIter->poslist.p; | |
| 177201 | + *pn = pIter->poslist.n; | |
| 177202 | + } | |
| 177180 | 177203 | }else{ |
| 177181 | 177204 | fts5BufferZero(&pIter->poslist); |
| 177182 | - fts5SegiterPoslist(pIter->pIndex, pSeg, 0, &pIter->poslist); | |
| 177205 | + fts5SegiterPoslist(pIter->pIndex, pSeg, pColset, &pIter->poslist); | |
| 177183 | 177206 | *pp = pIter->poslist.p; |
| 177207 | + *pn = pIter->poslist.n; | |
| 177184 | 177208 | } |
| 177185 | 177209 | return fts5IndexReturn(pIter->pIndex); |
| 177186 | 177210 | } |
| 177187 | 177211 | |
| 177188 | 177212 | /* |
| @@ -177375,14 +177399,14 @@ | ||
| 177375 | 177399 | while( rc==SQLITE_OK && 0==sqlite3Fts5IterEof(pIdxIter) ){ |
| 177376 | 177400 | i64 dummy; |
| 177377 | 177401 | const u8 *pPos; |
| 177378 | 177402 | int nPos; |
| 177379 | 177403 | i64 rowid = sqlite3Fts5IterRowid(pIdxIter); |
| 177380 | - rc = sqlite3Fts5IterPoslist(pIdxIter, &pPos, &nPos, &dummy); | |
| 177404 | + rc = sqlite3Fts5IterPoslist(pIdxIter, 0, &pPos, &nPos, &dummy); | |
| 177381 | 177405 | if( rc==SQLITE_OK ){ |
| 177382 | 177406 | Fts5PoslistReader sReader; |
| 177383 | - for(sqlite3Fts5PoslistReaderInit(-1, pPos, nPos, &sReader); | |
| 177407 | + for(sqlite3Fts5PoslistReaderInit(pPos, nPos, &sReader); | |
| 177384 | 177408 | sReader.bEof==0; |
| 177385 | 177409 | sqlite3Fts5PoslistReaderNext(&sReader) |
| 177386 | 177410 | ){ |
| 177387 | 177411 | int iCol = FTS5_POS2COLUMN(sReader.iPos); |
| 177388 | 177412 | int iOff = FTS5_POS2OFFSET(sReader.iPos); |
| @@ -179790,11 +179814,11 @@ | ||
| 179790 | 179814 | |
| 179791 | 179815 | /* Initialize all iterators */ |
| 179792 | 179816 | for(i=0; i<nIter; i++){ |
| 179793 | 179817 | const u8 *a; |
| 179794 | 179818 | int n = fts5CsrPoslist(pCsr, i, &a); |
| 179795 | - sqlite3Fts5PoslistReaderInit(-1, a, n, &aIter[i]); | |
| 179819 | + sqlite3Fts5PoslistReaderInit(a, n, &aIter[i]); | |
| 179796 | 179820 | } |
| 179797 | 179821 | |
| 179798 | 179822 | while( 1 ){ |
| 179799 | 179823 | int *aInst; |
| 179800 | 179824 | int iBest = -1; |
| @@ -180541,11 +180565,11 @@ | ||
| 180541 | 180565 | sqlite3_context *pCtx, /* Function call context */ |
| 180542 | 180566 | int nArg, /* Number of args */ |
| 180543 | 180567 | sqlite3_value **apVal /* Function arguments */ |
| 180544 | 180568 | ){ |
| 180545 | 180569 | assert( nArg==0 ); |
| 180546 | - sqlite3_result_text(pCtx, "fts5: 2015-10-10 15:57:20 35e6248abb4435a8b26d270092b856beff867406", -1, SQLITE_TRANSIENT); | |
| 180570 | + sqlite3_result_text(pCtx, "fts5: 2015-10-14 12:29:53 a721fc0d89495518fe5612e2e3bbc60befd2e90d", -1, SQLITE_TRANSIENT); | |
| 180547 | 180571 | } |
| 180548 | 180572 | |
| 180549 | 180573 | static int fts5Init(sqlite3 *db){ |
| 180550 | 180574 | static const sqlite3_module fts5Mod = { |
| 180551 | 180575 | /* iVersion */ 2, |
| @@ -184045,11 +184069,11 @@ | ||
| 184045 | 184069 | i64 dummy; |
| 184046 | 184070 | const u8 *pPos; int nPos; /* Position list */ |
| 184047 | 184071 | i64 iPos = 0; /* 64-bit position read from poslist */ |
| 184048 | 184072 | int iOff = 0; /* Current offset within position list */ |
| 184049 | 184073 | |
| 184050 | - rc = sqlite3Fts5IterPoslist(pCsr->pIter, &pPos, &nPos, &dummy); | |
| 184074 | + rc = sqlite3Fts5IterPoslist(pCsr->pIter, 0, &pPos, &nPos, &dummy); | |
| 184051 | 184075 | if( rc==SQLITE_OK ){ |
| 184052 | 184076 | if( pTab->eType==FTS5_VOCAB_ROW ){ |
| 184053 | 184077 | while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff, &iPos) ){ |
| 184054 | 184078 | pCsr->aVal[1]++; |
| 184055 | 184079 | } |
| 184056 | 184080 |
| --- src/sqlite3.c | |
| +++ src/sqlite3.c | |
| @@ -325,11 +325,11 @@ | |
| 325 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 326 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 327 | */ |
| 328 | #define SQLITE_VERSION "3.9.0" |
| 329 | #define SQLITE_VERSION_NUMBER 3009000 |
| 330 | #define SQLITE_SOURCE_ID "2015-10-10 15:57:20 35e6248abb4435a8b26d270092b856beff867406" |
| 331 | |
| 332 | /* |
| 333 | ** CAPI3REF: Run-Time Library Version Numbers |
| 334 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 335 | ** |
| @@ -5868,13 +5868,13 @@ | |
| 5868 | ** used with an SQLite version earlier than 3.8.2, the results of attempting |
| 5869 | ** to read or write the estimatedRows field are undefined (but are likely |
| 5870 | ** to included crashing the application). The estimatedRows field should |
| 5871 | ** therefore only be used if [sqlite3_libversion_number()] returns a |
| 5872 | ** value greater than or equal to 3008002. Similarly, the idxFlags field |
| 5873 | ** was added for version 3.8.12. It may therefore only be used if |
| 5874 | ** sqlite3_libversion_number() returns a value greater than or equal to |
| 5875 | ** 3008012. |
| 5876 | */ |
| 5877 | struct sqlite3_index_info { |
| 5878 | /* Inputs */ |
| 5879 | int nConstraint; /* Number of entries in aConstraint */ |
| 5880 | struct sqlite3_index_constraint { |
| @@ -5898,11 +5898,11 @@ | |
| 5898 | int needToFreeIdxStr; /* Free idxStr using sqlite3_free() if true */ |
| 5899 | int orderByConsumed; /* True if output is already ordered */ |
| 5900 | double estimatedCost; /* Estimated cost of using this index */ |
| 5901 | /* Fields below are only available in SQLite 3.8.2 and later */ |
| 5902 | sqlite3_int64 estimatedRows; /* Estimated number of rows returned */ |
| 5903 | /* Fields below are only available in SQLite 3.8.12 and later */ |
| 5904 | int idxFlags; /* Mask of SQLITE_INDEX_SCAN_* flags */ |
| 5905 | }; |
| 5906 | |
| 5907 | /* |
| 5908 | ** CAPI3REF: Virtual Table Scan Flags |
| @@ -8158,10 +8158,14 @@ | |
| 8158 | #ifndef _FTS5_H |
| 8159 | #define _FTS5_H |
| 8160 | |
| 8161 | /* #include "sqlite3.h" */ |
| 8162 | |
| 8163 | /************************************************************************* |
| 8164 | ** CUSTOM AUXILIARY FUNCTIONS |
| 8165 | ** |
| 8166 | ** Virtual table implementations may overload SQL functions by implementing |
| 8167 | ** the sqlite3_module.xFindFunction() method. |
| @@ -8643,10 +8647,14 @@ | |
| 8643 | |
| 8644 | /* |
| 8645 | ** END OF REGISTRATION API |
| 8646 | *************************************************************************/ |
| 8647 | |
| 8648 | #endif /* _FTS5_H */ |
| 8649 | |
| 8650 | |
| 8651 | |
| 8652 | /************** End of sqlite3.h *********************************************/ |
| @@ -60993,11 +61001,17 @@ | |
| 60993 | if( (aData[1]==0 && aData[2]==0) || (pSlot = pageFindSlot(pPg,sz,&rc))==0 ){ |
| 60994 | pData -= sz; |
| 60995 | if( pData<pBegin ) return 1; |
| 60996 | pSlot = pData; |
| 60997 | } |
| 60998 | memcpy(pSlot, pCArray->apCell[i], sz); |
| 60999 | put2byte(pCellptr, (pSlot - aData)); |
| 61000 | pCellptr += 2; |
| 61001 | } |
| 61002 | *ppData = pData; |
| 61003 | return 0; |
| @@ -104303,11 +104317,11 @@ | |
| 104303 | /* Version 3.8.11 and later */ |
| 104304 | sqlite3_value *(*value_dup)(const sqlite3_value*); |
| 104305 | void (*value_free)(sqlite3_value*); |
| 104306 | int (*result_zeroblob64)(sqlite3_context*,sqlite3_uint64); |
| 104307 | int (*bind_zeroblob64)(sqlite3_stmt*, int, sqlite3_uint64); |
| 104308 | /* Version 3.8.12 and later */ |
| 104309 | unsigned int (*value_subtype)(sqlite3_value*); |
| 104310 | void (*result_subtype)(sqlite3_context*,unsigned int); |
| 104311 | }; |
| 104312 | |
| 104313 | /* |
| @@ -104542,11 +104556,11 @@ | |
| 104542 | /* Version 3.8.11 and later */ |
| 104543 | #define sqlite3_value_dup sqlite3_api->value_dup |
| 104544 | #define sqlite3_value_free sqlite3_api->value_free |
| 104545 | #define sqlite3_result_zeroblob64 sqlite3_api->result_zeroblob64 |
| 104546 | #define sqlite3_bind_zeroblob64 sqlite3_api->bind_zeroblob64 |
| 104547 | /* Version 3.8.12 and later */ |
| 104548 | #define sqlite3_value_subtype sqlite3_api->value_subtype |
| 104549 | #define sqlite3_result_subtype sqlite3_api->result_subtype |
| 104550 | #endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */ |
| 104551 | |
| 104552 | #if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) |
| @@ -104957,11 +104971,11 @@ | |
| 104957 | /* Version 3.8.11 and later */ |
| 104958 | (sqlite3_value*(*)(const sqlite3_value*))sqlite3_value_dup, |
| 104959 | sqlite3_value_free, |
| 104960 | sqlite3_result_zeroblob64, |
| 104961 | sqlite3_bind_zeroblob64, |
| 104962 | /* Version 3.8.12 and later */ |
| 104963 | sqlite3_value_subtype, |
| 104964 | sqlite3_result_subtype |
| 104965 | }; |
| 104966 | |
| 104967 | /* |
| @@ -111703,11 +111717,11 @@ | |
| 111703 | #endif |
| 111704 | |
| 111705 | #if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) |
| 111706 | /* Forward Declarations */ |
| 111707 | static void substExprList(sqlite3*, ExprList*, int, ExprList*); |
| 111708 | static void substSelect(sqlite3*, Select *, int, ExprList *); |
| 111709 | |
| 111710 | /* |
| 111711 | ** Scan through the expression pExpr. Replace every reference to |
| 111712 | ** a column in table number iTable with a copy of the iColumn-th |
| 111713 | ** entry in pEList. (But leave references to the ROWID column |
| @@ -111740,11 +111754,11 @@ | |
| 111740 | } |
| 111741 | }else{ |
| 111742 | pExpr->pLeft = substExpr(db, pExpr->pLeft, iTable, pEList); |
| 111743 | pExpr->pRight = substExpr(db, pExpr->pRight, iTable, pEList); |
| 111744 | if( ExprHasProperty(pExpr, EP_xIsSelect) ){ |
| 111745 | substSelect(db, pExpr->x.pSelect, iTable, pEList); |
| 111746 | }else{ |
| 111747 | substExprList(db, pExpr->x.pList, iTable, pEList); |
| 111748 | } |
| 111749 | } |
| 111750 | return pExpr; |
| @@ -111763,29 +111777,32 @@ | |
| 111763 | } |
| 111764 | static void substSelect( |
| 111765 | sqlite3 *db, /* Report malloc errors here */ |
| 111766 | Select *p, /* SELECT statement in which to make substitutions */ |
| 111767 | int iTable, /* Table to be replaced */ |
| 111768 | ExprList *pEList /* Substitute values */ |
| 111769 | ){ |
| 111770 | SrcList *pSrc; |
| 111771 | struct SrcList_item *pItem; |
| 111772 | int i; |
| 111773 | if( !p ) return; |
| 111774 | substExprList(db, p->pEList, iTable, pEList); |
| 111775 | substExprList(db, p->pGroupBy, iTable, pEList); |
| 111776 | substExprList(db, p->pOrderBy, iTable, pEList); |
| 111777 | p->pHaving = substExpr(db, p->pHaving, iTable, pEList); |
| 111778 | p->pWhere = substExpr(db, p->pWhere, iTable, pEList); |
| 111779 | substSelect(db, p->pPrior, iTable, pEList); |
| 111780 | pSrc = p->pSrc; |
| 111781 | assert( pSrc ); /* Even for (SELECT 1) we have: pSrc!=0 but pSrc->nSrc==0 */ |
| 111782 | if( ALWAYS(pSrc) ){ |
| 111783 | for(i=pSrc->nSrc, pItem=pSrc->a; i>0; i--, pItem++){ |
| 111784 | substSelect(db, pItem->pSelect, iTable, pEList); |
| 111785 | } |
| 111786 | } |
| 111787 | } |
| 111788 | #endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */ |
| 111789 | |
| 111790 | #if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) |
| 111791 | /* |
| @@ -111933,11 +111950,11 @@ | |
| 111933 | int iFrom, /* Index in p->pSrc->a[] of the inner subquery */ |
| 111934 | int isAgg, /* True if outer SELECT uses aggregate functions */ |
| 111935 | int subqueryIsAgg /* True if the subquery uses aggregate functions */ |
| 111936 | ){ |
| 111937 | const char *zSavedAuthContext = pParse->zAuthContext; |
| 111938 | Select *pParent; |
| 111939 | Select *pSub; /* The inner query or "subquery" */ |
| 111940 | Select *pSub1; /* Pointer to the rightmost select in sub-query */ |
| 111941 | SrcList *pSrc; /* The FROM clause of the outer query */ |
| 111942 | SrcList *pSubSrc; /* The FROM clause of the subquery */ |
| 111943 | ExprList *pList; /* The result set of the outer query */ |
| @@ -112228,13 +112245,13 @@ | |
| 112228 | ** |
| 112229 | ** SELECT * FROM tabA, (SELECT * FROM sub1, sub2), tabB; |
| 112230 | ** |
| 112231 | ** The outer query has 3 slots in its FROM clause. One slot of the |
| 112232 | ** outer query (the middle slot) is used by the subquery. The next |
| 112233 | ** block of code will expand the out query to 4 slots. The middle |
| 112234 | ** slot is expanded to two slots in order to make space for the |
| 112235 | ** two elements in the FROM clause of the subquery. |
| 112236 | */ |
| 112237 | if( nSubSrc>1 ){ |
| 112238 | pParent->pSrc = pSrc = sqlite3SrcListEnlarge(db, pSrc, nSubSrc-1,iFrom+1); |
| 112239 | if( db->mallocFailed ){ |
| 112240 | break; |
| @@ -112269,15 +112286,10 @@ | |
| 112269 | char *zName = sqlite3DbStrDup(db, pList->a[i].zSpan); |
| 112270 | sqlite3Dequote(zName); |
| 112271 | pList->a[i].zName = zName; |
| 112272 | } |
| 112273 | } |
| 112274 | substExprList(db, pParent->pEList, iParent, pSub->pEList); |
| 112275 | if( isAgg ){ |
| 112276 | substExprList(db, pParent->pGroupBy, iParent, pSub->pEList); |
| 112277 | pParent->pHaving = substExpr(db, pParent->pHaving, iParent, pSub->pEList); |
| 112278 | } |
| 112279 | if( pSub->pOrderBy ){ |
| 112280 | /* At this point, any non-zero iOrderByCol values indicate that the |
| 112281 | ** ORDER BY column expression is identical to the iOrderByCol'th |
| 112282 | ** expression returned by SELECT statement pSub. Since these values |
| 112283 | ** do not necessarily correspond to columns in SELECT statement pParent, |
| @@ -112293,31 +112305,24 @@ | |
| 112293 | } |
| 112294 | assert( pParent->pOrderBy==0 ); |
| 112295 | assert( pSub->pPrior==0 ); |
| 112296 | pParent->pOrderBy = pOrderBy; |
| 112297 | pSub->pOrderBy = 0; |
| 112298 | }else if( pParent->pOrderBy ){ |
| 112299 | substExprList(db, pParent->pOrderBy, iParent, pSub->pEList); |
| 112300 | } |
| 112301 | if( pSub->pWhere ){ |
| 112302 | pWhere = sqlite3ExprDup(db, pSub->pWhere, 0); |
| 112303 | }else{ |
| 112304 | pWhere = 0; |
| 112305 | } |
| 112306 | if( subqueryIsAgg ){ |
| 112307 | assert( pParent->pHaving==0 ); |
| 112308 | pParent->pHaving = pParent->pWhere; |
| 112309 | pParent->pWhere = pWhere; |
| 112310 | pParent->pHaving = substExpr(db, pParent->pHaving, iParent, pSub->pEList); |
| 112311 | pParent->pHaving = sqlite3ExprAnd(db, pParent->pHaving, |
| 112312 | sqlite3ExprDup(db, pSub->pHaving, 0)); |
| 112313 | assert( pParent->pGroupBy==0 ); |
| 112314 | pParent->pGroupBy = sqlite3ExprListDup(db, pSub->pGroupBy, 0); |
| 112315 | }else{ |
| 112316 | pParent->pWhere = substExpr(db, pParent->pWhere, iParent, pSub->pEList); |
| 112317 | pParent->pWhere = sqlite3ExprAnd(db, pParent->pWhere, pWhere); |
| 112318 | } |
| 112319 | |
| 112320 | /* The flattened query is distinct if either the inner or the |
| 112321 | ** outer query is distinct. |
| 112322 | */ |
| 112323 | pParent->selFlags |= pSub->selFlags & SF_Distinct; |
| @@ -112878,19 +112883,23 @@ | |
| 112878 | return WRC_Abort; |
| 112879 | } |
| 112880 | pTab->nRef++; |
| 112881 | #if !defined(SQLITE_OMIT_VIEW) || !defined (SQLITE_OMIT_VIRTUALTABLE) |
| 112882 | if( pTab->pSelect || IsVirtual(pTab) ){ |
| 112883 | if( sqlite3ViewGetColumnNames(pParse, pTab) ) return WRC_Abort; |
| 112884 | assert( pFrom->pSelect==0 ); |
| 112885 | if( pFrom->fg.isTabFunc && !IsVirtual(pTab) ){ |
| 112886 | sqlite3ErrorMsg(pParse, "'%s' is not a function", pTab->zName); |
| 112887 | return WRC_Abort; |
| 112888 | } |
| 112889 | pFrom->pSelect = sqlite3SelectDup(db, pTab->pSelect, 0); |
| 112890 | sqlite3SelectSetName(pFrom->pSelect, pTab->zName); |
| 112891 | sqlite3WalkSelect(pWalker, pFrom->pSelect); |
| 112892 | } |
| 112893 | #endif |
| 112894 | } |
| 112895 | |
| 112896 | /* Locate the index named by the INDEXED BY clause, if any. */ |
| @@ -158656,10 +158665,14 @@ | |
| 158656 | #ifndef _SQLITE3RBU_H |
| 158657 | #define _SQLITE3RBU_H |
| 158658 | |
| 158659 | /* #include "sqlite3.h" ** Required for error code definitions ** */ |
| 158660 | |
| 158661 | typedef struct sqlite3rbu sqlite3rbu; |
| 158662 | |
| 158663 | /* |
| 158664 | ** Open an RBU handle. |
| 158665 | ** |
| @@ -158834,10 +158847,14 @@ | |
| 158834 | ** before all database handles that use it have been closed, the results |
| 158835 | ** are undefined. |
| 158836 | */ |
| 158837 | SQLITE_API void SQLITE_STDCALL sqlite3rbu_destroy_vfs(const char *zName); |
| 158838 | |
| 158839 | #endif /* _SQLITE3RBU_H */ |
| 158840 | |
| 158841 | /************** End of sqlite3rbu.h ******************************************/ |
| 158842 | /************** Continuing where we left off in sqlite3rbu.c *****************/ |
| 158843 | |
| @@ -164400,11 +164417,11 @@ | |
| 164400 | |
| 164401 | /* |
| 164402 | ** Compare the OBJECT label at pNode against zKey,nKey. Return true on |
| 164403 | ** a match. |
| 164404 | */ |
| 164405 | static int jsonLabelCompare(JsonNode *pNode, const char *zKey, int nKey){ |
| 164406 | if( pNode->jnFlags & JNODE_RAW ){ |
| 164407 | if( pNode->n!=nKey ) return 0; |
| 164408 | return strncmp(pNode->u.zJContent, zKey, nKey)==0; |
| 164409 | }else{ |
| 164410 | if( pNode->n!=nKey+2 ) return 0; |
| @@ -165589,10 +165606,14 @@ | |
| 165589 | #ifndef _FTS5_H |
| 165590 | #define _FTS5_H |
| 165591 | |
| 165592 | /* #include "sqlite3.h" */ |
| 165593 | |
| 165594 | /************************************************************************* |
| 165595 | ** CUSTOM AUXILIARY FUNCTIONS |
| 165596 | ** |
| 165597 | ** Virtual table implementations may overload SQL functions by implementing |
| 165598 | ** the sqlite3_module.xFindFunction() method. |
| @@ -166074,10 +166095,14 @@ | |
| 166074 | |
| 166075 | /* |
| 166076 | ** END OF REGISTRATION API |
| 166077 | *************************************************************************/ |
| 166078 | |
| 166079 | #endif /* _FTS5_H */ |
| 166080 | |
| 166081 | |
| 166082 | /* |
| 166083 | ** 2014 May 31 |
| @@ -166332,11 +166357,10 @@ | |
| 166332 | #define FTS5_POS2OFFSET(iPos) (int)(iPos & 0xFFFFFFFF) |
| 166333 | |
| 166334 | typedef struct Fts5PoslistReader Fts5PoslistReader; |
| 166335 | struct Fts5PoslistReader { |
| 166336 | /* Variables used only by sqlite3Fts5PoslistIterXXX() functions. */ |
| 166337 | int iCol; /* If (iCol>=0), this column only */ |
| 166338 | const u8 *a; /* Position list to iterate through */ |
| 166339 | int n; /* Size of buffer at a[] in bytes */ |
| 166340 | int i; /* Current offset in a[] */ |
| 166341 | |
| 166342 | u8 bFlag; /* For client use (any custom purpose) */ |
| @@ -166344,11 +166368,10 @@ | |
| 166344 | /* Output variables */ |
| 166345 | u8 bEof; /* Set to true at EOF */ |
| 166346 | i64 iPos; /* (iCol<<32) + iPos */ |
| 166347 | }; |
| 166348 | static int sqlite3Fts5PoslistReaderInit( |
| 166349 | int iCol, /* If (iCol>=0), this column only */ |
| 166350 | const u8 *a, int n, /* Poslist buffer to iterate through */ |
| 166351 | Fts5PoslistReader *pIter /* Iterator object to initialize */ |
| 166352 | ); |
| 166353 | static int sqlite3Fts5PoslistReaderNext(Fts5PoslistReader*); |
| 166354 | |
| @@ -166425,11 +166448,11 @@ | |
| 166425 | */ |
| 166426 | static int sqlite3Fts5IterEof(Fts5IndexIter*); |
| 166427 | static int sqlite3Fts5IterNext(Fts5IndexIter*); |
| 166428 | static int sqlite3Fts5IterNextFrom(Fts5IndexIter*, i64 iMatch); |
| 166429 | static i64 sqlite3Fts5IterRowid(Fts5IndexIter*); |
| 166430 | static int sqlite3Fts5IterPoslist(Fts5IndexIter*, const u8 **pp, int *pn, i64 *pi); |
| 166431 | static int sqlite3Fts5IterPoslistBuffer(Fts5IndexIter *pIter, Fts5Buffer *pBuf); |
| 166432 | |
| 166433 | /* |
| 166434 | ** Close an iterator opened by sqlite3Fts5IndexQuery(). |
| 166435 | */ |
| @@ -168735,30 +168758,24 @@ | |
| 168735 | /* |
| 168736 | ** Advance the iterator object passed as the only argument. Return true |
| 168737 | ** if the iterator reaches EOF, or false otherwise. |
| 168738 | */ |
| 168739 | static int sqlite3Fts5PoslistReaderNext(Fts5PoslistReader *pIter){ |
| 168740 | if( sqlite3Fts5PoslistNext64(pIter->a, pIter->n, &pIter->i, &pIter->iPos) |
| 168741 | || (pIter->iCol>=0 && (pIter->iPos >> 32) > pIter->iCol) |
| 168742 | ){ |
| 168743 | pIter->bEof = 1; |
| 168744 | } |
| 168745 | return pIter->bEof; |
| 168746 | } |
| 168747 | |
| 168748 | static int sqlite3Fts5PoslistReaderInit( |
| 168749 | int iCol, /* If (iCol>=0), this column only */ |
| 168750 | const u8 *a, int n, /* Poslist buffer to iterate through */ |
| 168751 | Fts5PoslistReader *pIter /* Iterator object to initialize */ |
| 168752 | ){ |
| 168753 | memset(pIter, 0, sizeof(*pIter)); |
| 168754 | pIter->a = a; |
| 168755 | pIter->n = n; |
| 168756 | pIter->iCol = iCol; |
| 168757 | do { |
| 168758 | sqlite3Fts5PoslistReaderNext(pIter); |
| 168759 | }while( pIter->bEof==0 && (pIter->iPos >> 32)<iCol ); |
| 168760 | return pIter->bEof; |
| 168761 | } |
| 168762 | |
| 168763 | static int sqlite3Fts5PoslistWriterAppend( |
| 168764 | Fts5Buffer *pBuf, |
| @@ -169982,18 +169999,10 @@ | |
| 169982 | sqlite3_free(p->apExprPhrase); |
| 169983 | sqlite3_free(p); |
| 169984 | } |
| 169985 | } |
| 169986 | |
| 169987 | static int fts5ExprColsetTest(Fts5Colset *pColset, int iCol){ |
| 169988 | int i; |
| 169989 | for(i=0; i<pColset->nCol; i++){ |
| 169990 | if( pColset->aiCol[i]==iCol ) return 1; |
| 169991 | } |
| 169992 | return 0; |
| 169993 | } |
| 169994 | |
| 169995 | /* |
| 169996 | ** Argument pTerm must be a synonym iterator. Return the current rowid |
| 169997 | ** that it points to. |
| 169998 | */ |
| 169999 | static i64 fts5ExprSynonymRowid(Fts5ExprTerm *pTerm, int bDesc, int *pbEof){ |
| @@ -170020,10 +170029,11 @@ | |
| 170020 | /* |
| 170021 | ** Argument pTerm must be a synonym iterator. |
| 170022 | */ |
| 170023 | static int fts5ExprSynonymPoslist( |
| 170024 | Fts5ExprTerm *pTerm, |
| 170025 | i64 iRowid, |
| 170026 | int *pbDel, /* OUT: Caller should sqlite3_free(*pa) */ |
| 170027 | u8 **pa, int *pn |
| 170028 | ){ |
| 170029 | Fts5PoslistReader aStatic[4]; |
| @@ -170038,11 +170048,11 @@ | |
| 170038 | Fts5IndexIter *pIter = p->pIter; |
| 170039 | if( sqlite3Fts5IterEof(pIter)==0 && sqlite3Fts5IterRowid(pIter)==iRowid ){ |
| 170040 | const u8 *a; |
| 170041 | int n; |
| 170042 | i64 dummy; |
| 170043 | rc = sqlite3Fts5IterPoslist(pIter, &a, &n, &dummy); |
| 170044 | if( rc!=SQLITE_OK ) goto synonym_poslist_out; |
| 170045 | if( nIter==nAlloc ){ |
| 170046 | int nByte = sizeof(Fts5PoslistReader) * nAlloc * 2; |
| 170047 | Fts5PoslistReader *aNew = (Fts5PoslistReader*)sqlite3_malloc(nByte); |
| 170048 | if( aNew==0 ){ |
| @@ -170052,11 +170062,11 @@ | |
| 170052 | memcpy(aNew, aIter, sizeof(Fts5PoslistReader) * nIter); |
| 170053 | nAlloc = nAlloc*2; |
| 170054 | if( aIter!=aStatic ) sqlite3_free(aIter); |
| 170055 | aIter = aNew; |
| 170056 | } |
| 170057 | sqlite3Fts5PoslistReaderInit(-1, a, n, &aIter[nIter]); |
| 170058 | assert( aIter[nIter].bEof==0 ); |
| 170059 | nIter++; |
| 170060 | } |
| 170061 | } |
| 170062 | |
| @@ -170120,17 +170130,11 @@ | |
| 170120 | Fts5PoslistWriter writer = {0}; |
| 170121 | Fts5PoslistReader aStatic[4]; |
| 170122 | Fts5PoslistReader *aIter = aStatic; |
| 170123 | int i; |
| 170124 | int rc = SQLITE_OK; |
| 170125 | int iCol = -1; |
| 170126 | |
| 170127 | if( pColset && pColset->nCol==1 ){ |
| 170128 | iCol = pColset->aiCol[0]; |
| 170129 | pColset = 0; |
| 170130 | } |
| 170131 | |
| 170132 | fts5BufferZero(&pPhrase->poslist); |
| 170133 | |
| 170134 | /* If the aStatic[] array is not large enough, allocate a large array |
| 170135 | ** using sqlite3_malloc(). This approach could be improved upon. */ |
| 170136 | if( pPhrase->nTerm>(sizeof(aStatic) / sizeof(aStatic[0])) ){ |
| @@ -170146,16 +170150,18 @@ | |
| 170146 | i64 dummy; |
| 170147 | int n = 0; |
| 170148 | int bFlag = 0; |
| 170149 | const u8 *a = 0; |
| 170150 | if( pTerm->pSynonym ){ |
| 170151 | rc = fts5ExprSynonymPoslist(pTerm, pNode->iRowid, &bFlag, (u8**)&a, &n); |
| 170152 | }else{ |
| 170153 | rc = sqlite3Fts5IterPoslist(pTerm->pIter, &a, &n, &dummy); |
| 170154 | } |
| 170155 | if( rc!=SQLITE_OK ) goto ismatch_out; |
| 170156 | sqlite3Fts5PoslistReaderInit(iCol, a, n, &aIter[i]); |
| 170157 | aIter[i].bFlag = bFlag; |
| 170158 | if( aIter[i].bEof ) goto ismatch_out; |
| 170159 | } |
| 170160 | |
| 170161 | while( 1 ){ |
| @@ -170174,15 +170180,13 @@ | |
| 170174 | if( pPos->iPos>iAdj ) iPos = pPos->iPos-i; |
| 170175 | } |
| 170176 | } |
| 170177 | }while( bMatch==0 ); |
| 170178 | |
| 170179 | if( pColset==0 || fts5ExprColsetTest(pColset, FTS5_POS2COLUMN(iPos)) ){ |
| 170180 | /* Append position iPos to the output */ |
| 170181 | rc = sqlite3Fts5PoslistWriterAppend(&pPhrase->poslist, &writer, iPos); |
| 170182 | if( rc!=SQLITE_OK ) goto ismatch_out; |
| 170183 | } |
| 170184 | |
| 170185 | for(i=0; i<pPhrase->nTerm; i++){ |
| 170186 | if( sqlite3Fts5PoslistReaderNext(&aIter[i]) ) goto ismatch_out; |
| 170187 | } |
| 170188 | } |
| @@ -170473,65 +170477,10 @@ | |
| 170473 | *piLast = fts5ExprSynonymRowid(pTerm, bDesc, &bEof); |
| 170474 | } |
| 170475 | return bEof; |
| 170476 | } |
| 170477 | |
| 170478 | /* |
| 170479 | ** IN/OUT parameter (*pa) points to a position list n bytes in size. If |
| 170480 | ** the position list contains entries for column iCol, then (*pa) is set |
| 170481 | ** to point to the sub-position-list for that column and the number of |
| 170482 | ** bytes in it returned. Or, if the argument position list does not |
| 170483 | ** contain any entries for column iCol, return 0. |
| 170484 | */ |
| 170485 | static int fts5ExprExtractCol( |
| 170486 | const u8 **pa, /* IN/OUT: Pointer to poslist */ |
| 170487 | int n, /* IN: Size of poslist in bytes */ |
| 170488 | int iCol /* Column to extract from poslist */ |
| 170489 | ){ |
| 170490 | int iCurrent = 0; |
| 170491 | const u8 *p = *pa; |
| 170492 | const u8 *pEnd = &p[n]; /* One byte past end of position list */ |
| 170493 | u8 prev = 0; |
| 170494 | |
| 170495 | while( iCol!=iCurrent ){ |
| 170496 | /* Advance pointer p until it points to pEnd or an 0x01 byte that is |
| 170497 | ** not part of a varint */ |
| 170498 | while( (prev & 0x80) || *p!=0x01 ){ |
| 170499 | prev = *p++; |
| 170500 | if( p==pEnd ) return 0; |
| 170501 | } |
| 170502 | *pa = p++; |
| 170503 | p += fts5GetVarint32(p, iCurrent); |
| 170504 | } |
| 170505 | |
| 170506 | /* Advance pointer p until it points to pEnd or an 0x01 byte that is |
| 170507 | ** not part of a varint */ |
| 170508 | assert( (prev & 0x80)==0 ); |
| 170509 | while( p<pEnd && ((prev & 0x80) || *p!=0x01) ){ |
| 170510 | prev = *p++; |
| 170511 | } |
| 170512 | return p - (*pa); |
| 170513 | } |
| 170514 | |
| 170515 | static int fts5ExprExtractColset ( |
| 170516 | Fts5Colset *pColset, /* Colset to filter on */ |
| 170517 | const u8 *pPos, int nPos, /* Position list */ |
| 170518 | Fts5Buffer *pBuf /* Output buffer */ |
| 170519 | ){ |
| 170520 | int rc = SQLITE_OK; |
| 170521 | int i; |
| 170522 | |
| 170523 | fts5BufferZero(pBuf); |
| 170524 | for(i=0; i<pColset->nCol; i++){ |
| 170525 | const u8 *pSub = pPos; |
| 170526 | int nSub = fts5ExprExtractCol(&pSub, nPos, pColset->aiCol[i]); |
| 170527 | if( nSub ){ |
| 170528 | fts5BufferAppendBlob(&rc, pBuf, nSub, pSub); |
| 170529 | } |
| 170530 | } |
| 170531 | return rc; |
| 170532 | } |
| 170533 | |
| 170534 | static int fts5ExprNearTest( |
| 170535 | int *pRc, |
| 170536 | Fts5Expr *pExpr, /* Expression that pNear is a part of */ |
| 170537 | Fts5ExprNode *pNode /* The "NEAR" node (FTS5_STRING) */ |
| @@ -170575,38 +170524,19 @@ | |
| 170575 | ** expressions. */ |
| 170576 | Fts5ExprNearset *pNear = pNode->pNear; |
| 170577 | Fts5ExprPhrase *pPhrase = pNear->apPhrase[0]; |
| 170578 | Fts5IndexIter *pIter = pPhrase->aTerm[0].pIter; |
| 170579 | Fts5Colset *pColset = pNear->pColset; |
| 170580 | const u8 *pPos; |
| 170581 | int nPos; |
| 170582 | int rc; |
| 170583 | |
| 170584 | assert( pNode->eType==FTS5_TERM ); |
| 170585 | assert( pNear->nPhrase==1 && pPhrase->nTerm==1 ); |
| 170586 | assert( pPhrase->aTerm[0].pSynonym==0 ); |
| 170587 | |
| 170588 | rc = sqlite3Fts5IterPoslist(pIter, &pPos, &nPos, &pNode->iRowid); |
| 170589 | |
| 170590 | /* If the term may match any column, then this must be a match. |
| 170591 | ** Return immediately in this case. Otherwise, try to find the |
| 170592 | ** part of the poslist that corresponds to the required column. |
| 170593 | ** If it can be found, return. If it cannot, the next iteration |
| 170594 | ** of the loop will test the next rowid in the database for this |
| 170595 | ** term. */ |
| 170596 | if( pColset==0 ){ |
| 170597 | assert( pPhrase->poslist.nSpace==0 ); |
| 170598 | pPhrase->poslist.p = (u8*)pPos; |
| 170599 | pPhrase->poslist.n = nPos; |
| 170600 | }else if( pColset->nCol==1 ){ |
| 170601 | assert( pPhrase->poslist.nSpace==0 ); |
| 170602 | pPhrase->poslist.n = fts5ExprExtractCol(&pPos, nPos, pColset->aiCol[0]); |
| 170603 | pPhrase->poslist.p = (u8*)pPos; |
| 170604 | }else if( rc==SQLITE_OK ){ |
| 170605 | rc = fts5ExprExtractColset(pColset, pPos, nPos, &pPhrase->poslist); |
| 170606 | } |
| 170607 | |
| 170608 | pNode->bNomatch = (pPhrase->poslist.n==0); |
| 170609 | return rc; |
| 170610 | } |
| 170611 | |
| 170612 | /* |
| @@ -172033,11 +171963,10 @@ | |
| 172033 | nRet = 0; |
| 172034 | } |
| 172035 | return nRet; |
| 172036 | } |
| 172037 | |
| 172038 | |
| 172039 | /* |
| 172040 | ** 2014 August 11 |
| 172041 | ** |
| 172042 | ** The author disclaims copyright to this source code. In place of |
| 172043 | ** a legal notice, here is a blessing: |
| @@ -173018,12 +172947,13 @@ | |
| 173018 | Fts5Structure *pStruct; /* Database structure for this iterator */ |
| 173019 | Fts5Buffer poslist; /* Buffer containing current poslist */ |
| 173020 | |
| 173021 | int nSeg; /* Size of aSeg[] array */ |
| 173022 | int bRev; /* True to iterate in reverse order */ |
| 173023 | int bSkipEmpty; /* True to skip deleted entries */ |
| 173024 | int bEof; /* True at EOF */ |
| 173025 | |
| 173026 | i64 iSwitchRowid; /* Firstest rowid of other than aFirst[1] */ |
| 173027 | Fts5CResult *aFirst; /* Current merge state (see above) */ |
| 173028 | Fts5SegIter aSeg[1]; /* Array of segment iterators */ |
| 173029 | }; |
| @@ -173964,11 +173894,12 @@ | |
| 173964 | ** read. Before returning, set *pnSz to the number of bytes in the position |
| 173965 | ** list, and *pbDel to true if the delete flag is set, or false otherwise. |
| 173966 | */ |
| 173967 | static int fts5GetPoslistSize(const u8 *p, int *pnSz, int *pbDel){ |
| 173968 | int nSz; |
| 173969 | int n = fts5GetVarint32(p, nSz); |
| 173970 | assert_nc( nSz>=0 ); |
| 173971 | *pnSz = nSz/2; |
| 173972 | *pbDel = nSz & 0x0001; |
| 173973 | return n; |
| 173974 | } |
| @@ -173985,17 +173916,16 @@ | |
| 173985 | ** position list content (if any). |
| 173986 | */ |
| 173987 | static void fts5SegIterLoadNPos(Fts5Index *p, Fts5SegIter *pIter){ |
| 173988 | if( p->rc==SQLITE_OK ){ |
| 173989 | int iOff = pIter->iLeafOffset; /* Offset to read at */ |
| 173990 | ASSERT_SZLEAF_OK(pIter->pLeaf); |
| 173991 | if( iOff>=pIter->pLeaf->szLeaf ){ |
| 173992 | p->rc = FTS5_CORRUPT; |
| 173993 | }else{ |
| 173994 | const u8 *a = &pIter->pLeaf->p[iOff]; |
| 173995 | pIter->iLeafOffset += fts5GetPoslistSize(a, &pIter->nPos, &pIter->bDel); |
| 173996 | } |
| 173997 | } |
| 173998 | } |
| 173999 | |
| 174000 | static void fts5SegIterLoadRowid(Fts5Index *p, Fts5SegIter *pIter){ |
| 174001 | u8 *a = pIter->pLeaf->p; /* Buffer to read data from */ |
| @@ -175232,10 +175162,11 @@ | |
| 175232 | Fts5IndexIter *pNew; |
| 175233 | pNew = fts5MultiIterAlloc(p, 2); |
| 175234 | if( pNew ){ |
| 175235 | Fts5SegIter *pIter = &pNew->aSeg[1]; |
| 175236 | |
| 175237 | pIter->flags = FTS5_SEGITER_ONETERM; |
| 175238 | if( pData->szLeaf>0 ){ |
| 175239 | pIter->pLeaf = pData; |
| 175240 | pIter->iLeafOffset = fts5GetVarint(pData->p, (u64*)&pIter->iRowid); |
| 175241 | pIter->iEndofDoclist = pData->nn; |
| @@ -176447,11 +176378,11 @@ | |
| 176447 | void *pContext, |
| 176448 | const u8 *pChunk, int nChunk |
| 176449 | ){ |
| 176450 | assert_nc( nChunk>=0 ); |
| 176451 | if( nChunk>0 ){ |
| 176452 | fts5BufferAppendBlob(&p->rc, (Fts5Buffer*)pContext, nChunk, pChunk); |
| 176453 | } |
| 176454 | } |
| 176455 | |
| 176456 | typedef struct PoslistCallbackCtx PoslistCallbackCtx; |
| 176457 | struct PoslistCallbackCtx { |
| @@ -176487,11 +176418,11 @@ | |
| 176487 | if( pCtx->eState==2 ){ |
| 176488 | int iCol; |
| 176489 | fts5FastGetVarint32(pChunk, i, iCol); |
| 176490 | if( fts5IndexColsetTest(pCtx->pColset, iCol) ){ |
| 176491 | pCtx->eState = 1; |
| 176492 | fts5BufferAppendVarint(&p->rc, pCtx->pBuf, 1); |
| 176493 | }else{ |
| 176494 | pCtx->eState = 0; |
| 176495 | } |
| 176496 | } |
| 176497 | |
| @@ -176499,11 +176430,11 @@ | |
| 176499 | while( i<nChunk && pChunk[i]!=0x01 ){ |
| 176500 | while( pChunk[i] & 0x80 ) i++; |
| 176501 | i++; |
| 176502 | } |
| 176503 | if( pCtx->eState ){ |
| 176504 | fts5BufferAppendBlob(&p->rc, pCtx->pBuf, i-iStart, &pChunk[iStart]); |
| 176505 | } |
| 176506 | if( i<nChunk ){ |
| 176507 | int iCol; |
| 176508 | iStart = i; |
| 176509 | i++; |
| @@ -176511,11 +176442,11 @@ | |
| 176511 | pCtx->eState = 2; |
| 176512 | }else{ |
| 176513 | fts5FastGetVarint32(pChunk, i, iCol); |
| 176514 | pCtx->eState = fts5IndexColsetTest(pCtx->pColset, iCol); |
| 176515 | if( pCtx->eState ){ |
| 176516 | fts5BufferAppendBlob(&p->rc, pCtx->pBuf, i-iStart, &pChunk[iStart]); |
| 176517 | iStart = i; |
| 176518 | } |
| 176519 | } |
| 176520 | } |
| 176521 | }while( i<nChunk ); |
| @@ -176532,60 +176463,127 @@ | |
| 176532 | Fts5Index *p, |
| 176533 | Fts5SegIter *pSeg, |
| 176534 | Fts5Colset *pColset, |
| 176535 | Fts5Buffer *pBuf |
| 176536 | ){ |
| 176537 | if( pColset==0 ){ |
| 176538 | fts5ChunkIterate(p, pSeg, (void*)pBuf, fts5PoslistCallback); |
| 176539 | }else{ |
| 176540 | PoslistCallbackCtx sCtx; |
| 176541 | sCtx.pBuf = pBuf; |
| 176542 | sCtx.pColset = pColset; |
| 176543 | sCtx.eState = pColset ? fts5IndexColsetTest(pColset, 0) : 1; |
| 176544 | assert( sCtx.eState==0 || sCtx.eState==1 ); |
| 176545 | fts5ChunkIterate(p, pSeg, (void*)&sCtx, fts5PoslistFilterCallback); |
| 176546 | } |
| 176547 | } |
| 176548 | |
| 176549 | /* |
| 176550 | ** Iterator pMulti currently points to a valid entry (not EOF). This |
| 176551 | ** function appends a copy of the position-list of the entry pMulti |
| 176552 | ** currently points to to buffer pBuf. |
| 176553 | ** |
| 176554 | ** If an error occurs, an error code is left in p->rc. It is assumed |
| 176555 | ** no error has already occurred when this function is called. |
| 176556 | */ |
| 176557 | static int fts5MultiIterPoslist( |
| 176558 | Fts5Index *p, |
| 176559 | Fts5IndexIter *pMulti, |
| 176560 | Fts5Colset *pColset, |
| 176561 | Fts5Buffer *pBuf |
| 176562 | ){ |
| 176563 | if( p->rc==SQLITE_OK ){ |
| 176564 | int iSz; |
| 176565 | int iData; |
| 176566 | |
| 176567 | Fts5SegIter *pSeg = &pMulti->aSeg[ pMulti->aFirst[1].iFirst ]; |
| 176568 | assert( fts5MultiIterEof(p, pMulti)==0 ); |
| 176569 | |
| 176570 | /* WRITEPOSLISTSIZE */ |
| 176571 | iSz = pBuf->n; |
| 176572 | fts5BufferSafeAppendVarint(pBuf, pSeg->nPos*2); |
| 176573 | iData = pBuf->n; |
| 176574 | |
| 176575 | fts5SegiterPoslist(p, pSeg, pColset, pBuf); |
| 176576 | |
| 176577 | if( pColset ){ |
| 176578 | int nActual = pBuf->n - iData; |
| 176579 | if( nActual!=pSeg->nPos ){ |
| 176580 | /* WRITEPOSLISTSIZE */ |
| 176581 | if( nActual==0 ){ |
| 176582 | return 1; |
| 176583 | }else{ |
| 176584 | int nReq = sqlite3Fts5GetVarintLen((u32)(nActual*2)); |
| 176585 | while( iSz<(iData-nReq) ){ pBuf->p[iSz++] = 0x80; } |
| 176586 | sqlite3Fts5PutVarint(&pBuf->p[iSz], nActual*2); |
| 176587 | } |
| 176588 | } |
| 176589 | } |
| 176590 | } |
| 176591 | |
| @@ -176789,19 +176787,12 @@ | |
| 176789 | } |
| 176790 | } |
| 176791 | iLastRowid = 0; |
| 176792 | } |
| 176793 | |
| 176794 | if( 0==sqlite3Fts5BufferGrow(&p->rc, &doclist, 9) ){ |
| 176795 | int iSave = doclist.n; |
| 176796 | assert( doclist.n!=0 || iLastRowid==0 ); |
| 176797 | fts5BufferSafeAppendVarint(&doclist, iRowid - iLastRowid); |
| 176798 | if( fts5MultiIterPoslist(p, p1, pColset, &doclist) ){ |
| 176799 | doclist.n = iSave; |
| 176800 | }else{ |
| 176801 | iLastRowid = iRowid; |
| 176802 | } |
| 176803 | } |
| 176804 | } |
| 176805 | |
| 176806 | for(i=0; i<nBuf; i++){ |
| 176807 | if( p->rc==SQLITE_OK ){ |
| @@ -177154,10 +177145,30 @@ | |
| 177154 | const char *z = (const char*)fts5MultiIterTerm(pIter, &n); |
| 177155 | *pn = n-1; |
| 177156 | return &z[1]; |
| 177157 | } |
| 177158 | |
| 177159 | |
| 177160 | /* |
| 177161 | ** Return a pointer to a buffer containing a copy of the position list for |
| 177162 | ** the current entry. Output variable *pn is set to the size of the buffer |
| 177163 | ** in bytes before returning. |
| @@ -177165,24 +177176,37 @@ | |
| 177165 | ** The returned position list does not include the "number of bytes" varint |
| 177166 | ** field that starts the position list on disk. |
| 177167 | */ |
| 177168 | static int sqlite3Fts5IterPoslist( |
| 177169 | Fts5IndexIter *pIter, |
| 177170 | const u8 **pp, /* OUT: Pointer to position-list data */ |
| 177171 | int *pn, /* OUT: Size of position-list in bytes */ |
| 177172 | i64 *piRowid /* OUT: Current rowid */ |
| 177173 | ){ |
| 177174 | Fts5SegIter *pSeg = &pIter->aSeg[ pIter->aFirst[1].iFirst ]; |
| 177175 | assert( pIter->pIndex->rc==SQLITE_OK ); |
| 177176 | *piRowid = pSeg->iRowid; |
| 177177 | *pn = pSeg->nPos; |
| 177178 | if( pSeg->iLeafOffset+pSeg->nPos <= pSeg->pLeaf->szLeaf ){ |
| 177179 | *pp = &pSeg->pLeaf->p[pSeg->iLeafOffset]; |
| 177180 | }else{ |
| 177181 | fts5BufferZero(&pIter->poslist); |
| 177182 | fts5SegiterPoslist(pIter->pIndex, pSeg, 0, &pIter->poslist); |
| 177183 | *pp = pIter->poslist.p; |
| 177184 | } |
| 177185 | return fts5IndexReturn(pIter->pIndex); |
| 177186 | } |
| 177187 | |
| 177188 | /* |
| @@ -177375,14 +177399,14 @@ | |
| 177375 | while( rc==SQLITE_OK && 0==sqlite3Fts5IterEof(pIdxIter) ){ |
| 177376 | i64 dummy; |
| 177377 | const u8 *pPos; |
| 177378 | int nPos; |
| 177379 | i64 rowid = sqlite3Fts5IterRowid(pIdxIter); |
| 177380 | rc = sqlite3Fts5IterPoslist(pIdxIter, &pPos, &nPos, &dummy); |
| 177381 | if( rc==SQLITE_OK ){ |
| 177382 | Fts5PoslistReader sReader; |
| 177383 | for(sqlite3Fts5PoslistReaderInit(-1, pPos, nPos, &sReader); |
| 177384 | sReader.bEof==0; |
| 177385 | sqlite3Fts5PoslistReaderNext(&sReader) |
| 177386 | ){ |
| 177387 | int iCol = FTS5_POS2COLUMN(sReader.iPos); |
| 177388 | int iOff = FTS5_POS2OFFSET(sReader.iPos); |
| @@ -179790,11 +179814,11 @@ | |
| 179790 | |
| 179791 | /* Initialize all iterators */ |
| 179792 | for(i=0; i<nIter; i++){ |
| 179793 | const u8 *a; |
| 179794 | int n = fts5CsrPoslist(pCsr, i, &a); |
| 179795 | sqlite3Fts5PoslistReaderInit(-1, a, n, &aIter[i]); |
| 179796 | } |
| 179797 | |
| 179798 | while( 1 ){ |
| 179799 | int *aInst; |
| 179800 | int iBest = -1; |
| @@ -180541,11 +180565,11 @@ | |
| 180541 | sqlite3_context *pCtx, /* Function call context */ |
| 180542 | int nArg, /* Number of args */ |
| 180543 | sqlite3_value **apVal /* Function arguments */ |
| 180544 | ){ |
| 180545 | assert( nArg==0 ); |
| 180546 | sqlite3_result_text(pCtx, "fts5: 2015-10-10 15:57:20 35e6248abb4435a8b26d270092b856beff867406", -1, SQLITE_TRANSIENT); |
| 180547 | } |
| 180548 | |
| 180549 | static int fts5Init(sqlite3 *db){ |
| 180550 | static const sqlite3_module fts5Mod = { |
| 180551 | /* iVersion */ 2, |
| @@ -184045,11 +184069,11 @@ | |
| 184045 | i64 dummy; |
| 184046 | const u8 *pPos; int nPos; /* Position list */ |
| 184047 | i64 iPos = 0; /* 64-bit position read from poslist */ |
| 184048 | int iOff = 0; /* Current offset within position list */ |
| 184049 | |
| 184050 | rc = sqlite3Fts5IterPoslist(pCsr->pIter, &pPos, &nPos, &dummy); |
| 184051 | if( rc==SQLITE_OK ){ |
| 184052 | if( pTab->eType==FTS5_VOCAB_ROW ){ |
| 184053 | while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff, &iPos) ){ |
| 184054 | pCsr->aVal[1]++; |
| 184055 | } |
| 184056 |
| --- src/sqlite3.c | |
| +++ src/sqlite3.c | |
| @@ -325,11 +325,11 @@ | |
| 325 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 326 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 327 | */ |
| 328 | #define SQLITE_VERSION "3.9.0" |
| 329 | #define SQLITE_VERSION_NUMBER 3009000 |
| 330 | #define SQLITE_SOURCE_ID "2015-10-14 12:29:53 a721fc0d89495518fe5612e2e3bbc60befd2e90d" |
| 331 | |
| 332 | /* |
| 333 | ** CAPI3REF: Run-Time Library Version Numbers |
| 334 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 335 | ** |
| @@ -5868,13 +5868,13 @@ | |
| 5868 | ** used with an SQLite version earlier than 3.8.2, the results of attempting |
| 5869 | ** to read or write the estimatedRows field are undefined (but are likely |
| 5870 | ** to included crashing the application). The estimatedRows field should |
| 5871 | ** therefore only be used if [sqlite3_libversion_number()] returns a |
| 5872 | ** value greater than or equal to 3008002. Similarly, the idxFlags field |
| 5873 | ** was added for version 3.9.0. It may therefore only be used if |
| 5874 | ** sqlite3_libversion_number() returns a value greater than or equal to |
| 5875 | ** 3009000. |
| 5876 | */ |
| 5877 | struct sqlite3_index_info { |
| 5878 | /* Inputs */ |
| 5879 | int nConstraint; /* Number of entries in aConstraint */ |
| 5880 | struct sqlite3_index_constraint { |
| @@ -5898,11 +5898,11 @@ | |
| 5898 | int needToFreeIdxStr; /* Free idxStr using sqlite3_free() if true */ |
| 5899 | int orderByConsumed; /* True if output is already ordered */ |
| 5900 | double estimatedCost; /* Estimated cost of using this index */ |
| 5901 | /* Fields below are only available in SQLite 3.8.2 and later */ |
| 5902 | sqlite3_int64 estimatedRows; /* Estimated number of rows returned */ |
| 5903 | /* Fields below are only available in SQLite 3.9.0 and later */ |
| 5904 | int idxFlags; /* Mask of SQLITE_INDEX_SCAN_* flags */ |
| 5905 | }; |
| 5906 | |
| 5907 | /* |
| 5908 | ** CAPI3REF: Virtual Table Scan Flags |
| @@ -8158,10 +8158,14 @@ | |
| 8158 | #ifndef _FTS5_H |
| 8159 | #define _FTS5_H |
| 8160 | |
| 8161 | /* #include "sqlite3.h" */ |
| 8162 | |
| 8163 | #if 0 |
| 8164 | extern "C" { |
| 8165 | #endif |
| 8166 | |
| 8167 | /************************************************************************* |
| 8168 | ** CUSTOM AUXILIARY FUNCTIONS |
| 8169 | ** |
| 8170 | ** Virtual table implementations may overload SQL functions by implementing |
| 8171 | ** the sqlite3_module.xFindFunction() method. |
| @@ -8643,10 +8647,14 @@ | |
| 8647 | |
| 8648 | /* |
| 8649 | ** END OF REGISTRATION API |
| 8650 | *************************************************************************/ |
| 8651 | |
| 8652 | #if 0 |
| 8653 | } /* end of the 'extern "C"' block */ |
| 8654 | #endif |
| 8655 | |
| 8656 | #endif /* _FTS5_H */ |
| 8657 | |
| 8658 | |
| 8659 | |
| 8660 | /************** End of sqlite3.h *********************************************/ |
| @@ -60993,11 +61001,17 @@ | |
| 61001 | if( (aData[1]==0 && aData[2]==0) || (pSlot = pageFindSlot(pPg,sz,&rc))==0 ){ |
| 61002 | pData -= sz; |
| 61003 | if( pData<pBegin ) return 1; |
| 61004 | pSlot = pData; |
| 61005 | } |
| 61006 | /* pSlot and pCArray->apCell[i] will never overlap on a well-formed |
| 61007 | ** database. But they might for a corrupt database. Hence use memmove() |
| 61008 | ** since memcpy() sends SIGABORT with overlapping buffers on OpenBSD */ |
| 61009 | assert( (pSlot+sz)<=pCArray->apCell[i] |
| 61010 | || pSlot>=(pCArray->apCell[i]+sz) |
| 61011 | || CORRUPT_DB ); |
| 61012 | memmove(pSlot, pCArray->apCell[i], sz); |
| 61013 | put2byte(pCellptr, (pSlot - aData)); |
| 61014 | pCellptr += 2; |
| 61015 | } |
| 61016 | *ppData = pData; |
| 61017 | return 0; |
| @@ -104303,11 +104317,11 @@ | |
| 104317 | /* Version 3.8.11 and later */ |
| 104318 | sqlite3_value *(*value_dup)(const sqlite3_value*); |
| 104319 | void (*value_free)(sqlite3_value*); |
| 104320 | int (*result_zeroblob64)(sqlite3_context*,sqlite3_uint64); |
| 104321 | int (*bind_zeroblob64)(sqlite3_stmt*, int, sqlite3_uint64); |
| 104322 | /* Version 3.9.0 and later */ |
| 104323 | unsigned int (*value_subtype)(sqlite3_value*); |
| 104324 | void (*result_subtype)(sqlite3_context*,unsigned int); |
| 104325 | }; |
| 104326 | |
| 104327 | /* |
| @@ -104542,11 +104556,11 @@ | |
| 104556 | /* Version 3.8.11 and later */ |
| 104557 | #define sqlite3_value_dup sqlite3_api->value_dup |
| 104558 | #define sqlite3_value_free sqlite3_api->value_free |
| 104559 | #define sqlite3_result_zeroblob64 sqlite3_api->result_zeroblob64 |
| 104560 | #define sqlite3_bind_zeroblob64 sqlite3_api->bind_zeroblob64 |
| 104561 | /* Version 3.9.0 and later */ |
| 104562 | #define sqlite3_value_subtype sqlite3_api->value_subtype |
| 104563 | #define sqlite3_result_subtype sqlite3_api->result_subtype |
| 104564 | #endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */ |
| 104565 | |
| 104566 | #if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) |
| @@ -104957,11 +104971,11 @@ | |
| 104971 | /* Version 3.8.11 and later */ |
| 104972 | (sqlite3_value*(*)(const sqlite3_value*))sqlite3_value_dup, |
| 104973 | sqlite3_value_free, |
| 104974 | sqlite3_result_zeroblob64, |
| 104975 | sqlite3_bind_zeroblob64, |
| 104976 | /* Version 3.9.0 and later */ |
| 104977 | sqlite3_value_subtype, |
| 104978 | sqlite3_result_subtype |
| 104979 | }; |
| 104980 | |
| 104981 | /* |
| @@ -111703,11 +111717,11 @@ | |
| 111717 | #endif |
| 111718 | |
| 111719 | #if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) |
| 111720 | /* Forward Declarations */ |
| 111721 | static void substExprList(sqlite3*, ExprList*, int, ExprList*); |
| 111722 | static void substSelect(sqlite3*, Select *, int, ExprList*, int); |
| 111723 | |
| 111724 | /* |
| 111725 | ** Scan through the expression pExpr. Replace every reference to |
| 111726 | ** a column in table number iTable with a copy of the iColumn-th |
| 111727 | ** entry in pEList. (But leave references to the ROWID column |
| @@ -111740,11 +111754,11 @@ | |
| 111754 | } |
| 111755 | }else{ |
| 111756 | pExpr->pLeft = substExpr(db, pExpr->pLeft, iTable, pEList); |
| 111757 | pExpr->pRight = substExpr(db, pExpr->pRight, iTable, pEList); |
| 111758 | if( ExprHasProperty(pExpr, EP_xIsSelect) ){ |
| 111759 | substSelect(db, pExpr->x.pSelect, iTable, pEList, 1); |
| 111760 | }else{ |
| 111761 | substExprList(db, pExpr->x.pList, iTable, pEList); |
| 111762 | } |
| 111763 | } |
| 111764 | return pExpr; |
| @@ -111763,29 +111777,32 @@ | |
| 111777 | } |
| 111778 | static void substSelect( |
| 111779 | sqlite3 *db, /* Report malloc errors here */ |
| 111780 | Select *p, /* SELECT statement in which to make substitutions */ |
| 111781 | int iTable, /* Table to be replaced */ |
| 111782 | ExprList *pEList, /* Substitute values */ |
| 111783 | int doPrior /* Do substitutes on p->pPrior too */ |
| 111784 | ){ |
| 111785 | SrcList *pSrc; |
| 111786 | struct SrcList_item *pItem; |
| 111787 | int i; |
| 111788 | if( !p ) return; |
| 111789 | do{ |
| 111790 | substExprList(db, p->pEList, iTable, pEList); |
| 111791 | substExprList(db, p->pGroupBy, iTable, pEList); |
| 111792 | substExprList(db, p->pOrderBy, iTable, pEList); |
| 111793 | p->pHaving = substExpr(db, p->pHaving, iTable, pEList); |
| 111794 | p->pWhere = substExpr(db, p->pWhere, iTable, pEList); |
| 111795 | pSrc = p->pSrc; |
| 111796 | assert( pSrc!=0 ); |
| 111797 | for(i=pSrc->nSrc, pItem=pSrc->a; i>0; i--, pItem++){ |
| 111798 | substSelect(db, pItem->pSelect, iTable, pEList, 1); |
| 111799 | if( pItem->fg.isTabFunc ){ |
| 111800 | substExprList(db, pItem->u1.pFuncArg, iTable, pEList); |
| 111801 | } |
| 111802 | } |
| 111803 | }while( doPrior && (p = p->pPrior)!=0 ); |
| 111804 | } |
| 111805 | #endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */ |
| 111806 | |
| 111807 | #if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) |
| 111808 | /* |
| @@ -111933,11 +111950,11 @@ | |
| 111950 | int iFrom, /* Index in p->pSrc->a[] of the inner subquery */ |
| 111951 | int isAgg, /* True if outer SELECT uses aggregate functions */ |
| 111952 | int subqueryIsAgg /* True if the subquery uses aggregate functions */ |
| 111953 | ){ |
| 111954 | const char *zSavedAuthContext = pParse->zAuthContext; |
| 111955 | Select *pParent; /* Current UNION ALL term of the other query */ |
| 111956 | Select *pSub; /* The inner query or "subquery" */ |
| 111957 | Select *pSub1; /* Pointer to the rightmost select in sub-query */ |
| 111958 | SrcList *pSrc; /* The FROM clause of the outer query */ |
| 111959 | SrcList *pSubSrc; /* The FROM clause of the subquery */ |
| 111960 | ExprList *pList; /* The result set of the outer query */ |
| @@ -112228,13 +112245,13 @@ | |
| 112245 | ** |
| 112246 | ** SELECT * FROM tabA, (SELECT * FROM sub1, sub2), tabB; |
| 112247 | ** |
| 112248 | ** The outer query has 3 slots in its FROM clause. One slot of the |
| 112249 | ** outer query (the middle slot) is used by the subquery. The next |
| 112250 | ** block of code will expand the outer query FROM clause to 4 slots. |
| 112251 | ** The middle slot is expanded to two slots in order to make space |
| 112252 | ** for the two elements in the FROM clause of the subquery. |
| 112253 | */ |
| 112254 | if( nSubSrc>1 ){ |
| 112255 | pParent->pSrc = pSrc = sqlite3SrcListEnlarge(db, pSrc, nSubSrc-1,iFrom+1); |
| 112256 | if( db->mallocFailed ){ |
| 112257 | break; |
| @@ -112269,15 +112286,10 @@ | |
| 112286 | char *zName = sqlite3DbStrDup(db, pList->a[i].zSpan); |
| 112287 | sqlite3Dequote(zName); |
| 112288 | pList->a[i].zName = zName; |
| 112289 | } |
| 112290 | } |
| 112291 | if( pSub->pOrderBy ){ |
| 112292 | /* At this point, any non-zero iOrderByCol values indicate that the |
| 112293 | ** ORDER BY column expression is identical to the iOrderByCol'th |
| 112294 | ** expression returned by SELECT statement pSub. Since these values |
| 112295 | ** do not necessarily correspond to columns in SELECT statement pParent, |
| @@ -112293,31 +112305,24 @@ | |
| 112305 | } |
| 112306 | assert( pParent->pOrderBy==0 ); |
| 112307 | assert( pSub->pPrior==0 ); |
| 112308 | pParent->pOrderBy = pOrderBy; |
| 112309 | pSub->pOrderBy = 0; |
| 112310 | } |
| 112311 | pWhere = sqlite3ExprDup(db, pSub->pWhere, 0); |
| 112312 | if( subqueryIsAgg ){ |
| 112313 | assert( pParent->pHaving==0 ); |
| 112314 | pParent->pHaving = pParent->pWhere; |
| 112315 | pParent->pWhere = pWhere; |
| 112316 | pParent->pHaving = sqlite3ExprAnd(db, pParent->pHaving, |
| 112317 | sqlite3ExprDup(db, pSub->pHaving, 0)); |
| 112318 | assert( pParent->pGroupBy==0 ); |
| 112319 | pParent->pGroupBy = sqlite3ExprListDup(db, pSub->pGroupBy, 0); |
| 112320 | }else{ |
| 112321 | pParent->pWhere = sqlite3ExprAnd(db, pParent->pWhere, pWhere); |
| 112322 | } |
| 112323 | substSelect(db, pParent, iParent, pSub->pEList, 0); |
| 112324 | |
| 112325 | /* The flattened query is distinct if either the inner or the |
| 112326 | ** outer query is distinct. |
| 112327 | */ |
| 112328 | pParent->selFlags |= pSub->selFlags & SF_Distinct; |
| @@ -112878,19 +112883,23 @@ | |
| 112883 | return WRC_Abort; |
| 112884 | } |
| 112885 | pTab->nRef++; |
| 112886 | #if !defined(SQLITE_OMIT_VIEW) || !defined (SQLITE_OMIT_VIRTUALTABLE) |
| 112887 | if( pTab->pSelect || IsVirtual(pTab) ){ |
| 112888 | i16 nCol; |
| 112889 | if( sqlite3ViewGetColumnNames(pParse, pTab) ) return WRC_Abort; |
| 112890 | assert( pFrom->pSelect==0 ); |
| 112891 | if( pFrom->fg.isTabFunc && !IsVirtual(pTab) ){ |
| 112892 | sqlite3ErrorMsg(pParse, "'%s' is not a function", pTab->zName); |
| 112893 | return WRC_Abort; |
| 112894 | } |
| 112895 | pFrom->pSelect = sqlite3SelectDup(db, pTab->pSelect, 0); |
| 112896 | sqlite3SelectSetName(pFrom->pSelect, pTab->zName); |
| 112897 | nCol = pTab->nCol; |
| 112898 | pTab->nCol = -1; |
| 112899 | sqlite3WalkSelect(pWalker, pFrom->pSelect); |
| 112900 | pTab->nCol = nCol; |
| 112901 | } |
| 112902 | #endif |
| 112903 | } |
| 112904 | |
| 112905 | /* Locate the index named by the INDEXED BY clause, if any. */ |
| @@ -158656,10 +158665,14 @@ | |
| 158665 | #ifndef _SQLITE3RBU_H |
| 158666 | #define _SQLITE3RBU_H |
| 158667 | |
| 158668 | /* #include "sqlite3.h" ** Required for error code definitions ** */ |
| 158669 | |
| 158670 | #if 0 |
| 158671 | extern "C" { |
| 158672 | #endif |
| 158673 | |
| 158674 | typedef struct sqlite3rbu sqlite3rbu; |
| 158675 | |
| 158676 | /* |
| 158677 | ** Open an RBU handle. |
| 158678 | ** |
| @@ -158834,10 +158847,14 @@ | |
| 158847 | ** before all database handles that use it have been closed, the results |
| 158848 | ** are undefined. |
| 158849 | */ |
| 158850 | SQLITE_API void SQLITE_STDCALL sqlite3rbu_destroy_vfs(const char *zName); |
| 158851 | |
| 158852 | #if 0 |
| 158853 | } /* end of the 'extern "C"' block */ |
| 158854 | #endif |
| 158855 | |
| 158856 | #endif /* _SQLITE3RBU_H */ |
| 158857 | |
| 158858 | /************** End of sqlite3rbu.h ******************************************/ |
| 158859 | /************** Continuing where we left off in sqlite3rbu.c *****************/ |
| 158860 | |
| @@ -164400,11 +164417,11 @@ | |
| 164417 | |
| 164418 | /* |
| 164419 | ** Compare the OBJECT label at pNode against zKey,nKey. Return true on |
| 164420 | ** a match. |
| 164421 | */ |
| 164422 | static int jsonLabelCompare(JsonNode *pNode, const char *zKey, u32 nKey){ |
| 164423 | if( pNode->jnFlags & JNODE_RAW ){ |
| 164424 | if( pNode->n!=nKey ) return 0; |
| 164425 | return strncmp(pNode->u.zJContent, zKey, nKey)==0; |
| 164426 | }else{ |
| 164427 | if( pNode->n!=nKey+2 ) return 0; |
| @@ -165589,10 +165606,14 @@ | |
| 165606 | #ifndef _FTS5_H |
| 165607 | #define _FTS5_H |
| 165608 | |
| 165609 | /* #include "sqlite3.h" */ |
| 165610 | |
| 165611 | #if 0 |
| 165612 | extern "C" { |
| 165613 | #endif |
| 165614 | |
| 165615 | /************************************************************************* |
| 165616 | ** CUSTOM AUXILIARY FUNCTIONS |
| 165617 | ** |
| 165618 | ** Virtual table implementations may overload SQL functions by implementing |
| 165619 | ** the sqlite3_module.xFindFunction() method. |
| @@ -166074,10 +166095,14 @@ | |
| 166095 | |
| 166096 | /* |
| 166097 | ** END OF REGISTRATION API |
| 166098 | *************************************************************************/ |
| 166099 | |
| 166100 | #if 0 |
| 166101 | } /* end of the 'extern "C"' block */ |
| 166102 | #endif |
| 166103 | |
| 166104 | #endif /* _FTS5_H */ |
| 166105 | |
| 166106 | |
| 166107 | /* |
| 166108 | ** 2014 May 31 |
| @@ -166332,11 +166357,10 @@ | |
| 166357 | #define FTS5_POS2OFFSET(iPos) (int)(iPos & 0xFFFFFFFF) |
| 166358 | |
| 166359 | typedef struct Fts5PoslistReader Fts5PoslistReader; |
| 166360 | struct Fts5PoslistReader { |
| 166361 | /* Variables used only by sqlite3Fts5PoslistIterXXX() functions. */ |
| 166362 | const u8 *a; /* Position list to iterate through */ |
| 166363 | int n; /* Size of buffer at a[] in bytes */ |
| 166364 | int i; /* Current offset in a[] */ |
| 166365 | |
| 166366 | u8 bFlag; /* For client use (any custom purpose) */ |
| @@ -166344,11 +166368,10 @@ | |
| 166368 | /* Output variables */ |
| 166369 | u8 bEof; /* Set to true at EOF */ |
| 166370 | i64 iPos; /* (iCol<<32) + iPos */ |
| 166371 | }; |
| 166372 | static int sqlite3Fts5PoslistReaderInit( |
| 166373 | const u8 *a, int n, /* Poslist buffer to iterate through */ |
| 166374 | Fts5PoslistReader *pIter /* Iterator object to initialize */ |
| 166375 | ); |
| 166376 | static int sqlite3Fts5PoslistReaderNext(Fts5PoslistReader*); |
| 166377 | |
| @@ -166425,11 +166448,11 @@ | |
| 166448 | */ |
| 166449 | static int sqlite3Fts5IterEof(Fts5IndexIter*); |
| 166450 | static int sqlite3Fts5IterNext(Fts5IndexIter*); |
| 166451 | static int sqlite3Fts5IterNextFrom(Fts5IndexIter*, i64 iMatch); |
| 166452 | static i64 sqlite3Fts5IterRowid(Fts5IndexIter*); |
| 166453 | static int sqlite3Fts5IterPoslist(Fts5IndexIter*,Fts5Colset*, const u8**, int*, i64*); |
| 166454 | static int sqlite3Fts5IterPoslistBuffer(Fts5IndexIter *pIter, Fts5Buffer *pBuf); |
| 166455 | |
| 166456 | /* |
| 166457 | ** Close an iterator opened by sqlite3Fts5IndexQuery(). |
| 166458 | */ |
| @@ -168735,30 +168758,24 @@ | |
| 168758 | /* |
| 168759 | ** Advance the iterator object passed as the only argument. Return true |
| 168760 | ** if the iterator reaches EOF, or false otherwise. |
| 168761 | */ |
| 168762 | static int sqlite3Fts5PoslistReaderNext(Fts5PoslistReader *pIter){ |
| 168763 | if( sqlite3Fts5PoslistNext64(pIter->a, pIter->n, &pIter->i, &pIter->iPos) ){ |
| 168764 | pIter->bEof = 1; |
| 168765 | } |
| 168766 | return pIter->bEof; |
| 168767 | } |
| 168768 | |
| 168769 | static int sqlite3Fts5PoslistReaderInit( |
| 168770 | const u8 *a, int n, /* Poslist buffer to iterate through */ |
| 168771 | Fts5PoslistReader *pIter /* Iterator object to initialize */ |
| 168772 | ){ |
| 168773 | memset(pIter, 0, sizeof(*pIter)); |
| 168774 | pIter->a = a; |
| 168775 | pIter->n = n; |
| 168776 | sqlite3Fts5PoslistReaderNext(pIter); |
| 168777 | return pIter->bEof; |
| 168778 | } |
| 168779 | |
| 168780 | static int sqlite3Fts5PoslistWriterAppend( |
| 168781 | Fts5Buffer *pBuf, |
| @@ -169982,18 +169999,10 @@ | |
| 169999 | sqlite3_free(p->apExprPhrase); |
| 170000 | sqlite3_free(p); |
| 170001 | } |
| 170002 | } |
| 170003 | |
| 170004 | /* |
| 170005 | ** Argument pTerm must be a synonym iterator. Return the current rowid |
| 170006 | ** that it points to. |
| 170007 | */ |
| 170008 | static i64 fts5ExprSynonymRowid(Fts5ExprTerm *pTerm, int bDesc, int *pbEof){ |
| @@ -170020,10 +170029,11 @@ | |
| 170029 | /* |
| 170030 | ** Argument pTerm must be a synonym iterator. |
| 170031 | */ |
| 170032 | static int fts5ExprSynonymPoslist( |
| 170033 | Fts5ExprTerm *pTerm, |
| 170034 | Fts5Colset *pColset, |
| 170035 | i64 iRowid, |
| 170036 | int *pbDel, /* OUT: Caller should sqlite3_free(*pa) */ |
| 170037 | u8 **pa, int *pn |
| 170038 | ){ |
| 170039 | Fts5PoslistReader aStatic[4]; |
| @@ -170038,11 +170048,11 @@ | |
| 170048 | Fts5IndexIter *pIter = p->pIter; |
| 170049 | if( sqlite3Fts5IterEof(pIter)==0 && sqlite3Fts5IterRowid(pIter)==iRowid ){ |
| 170050 | const u8 *a; |
| 170051 | int n; |
| 170052 | i64 dummy; |
| 170053 | rc = sqlite3Fts5IterPoslist(pIter, pColset, &a, &n, &dummy); |
| 170054 | if( rc!=SQLITE_OK ) goto synonym_poslist_out; |
| 170055 | if( nIter==nAlloc ){ |
| 170056 | int nByte = sizeof(Fts5PoslistReader) * nAlloc * 2; |
| 170057 | Fts5PoslistReader *aNew = (Fts5PoslistReader*)sqlite3_malloc(nByte); |
| 170058 | if( aNew==0 ){ |
| @@ -170052,11 +170062,11 @@ | |
| 170062 | memcpy(aNew, aIter, sizeof(Fts5PoslistReader) * nIter); |
| 170063 | nAlloc = nAlloc*2; |
| 170064 | if( aIter!=aStatic ) sqlite3_free(aIter); |
| 170065 | aIter = aNew; |
| 170066 | } |
| 170067 | sqlite3Fts5PoslistReaderInit(a, n, &aIter[nIter]); |
| 170068 | assert( aIter[nIter].bEof==0 ); |
| 170069 | nIter++; |
| 170070 | } |
| 170071 | } |
| 170072 | |
| @@ -170120,17 +170130,11 @@ | |
| 170130 | Fts5PoslistWriter writer = {0}; |
| 170131 | Fts5PoslistReader aStatic[4]; |
| 170132 | Fts5PoslistReader *aIter = aStatic; |
| 170133 | int i; |
| 170134 | int rc = SQLITE_OK; |
| 170135 | |
| 170136 | fts5BufferZero(&pPhrase->poslist); |
| 170137 | |
| 170138 | /* If the aStatic[] array is not large enough, allocate a large array |
| 170139 | ** using sqlite3_malloc(). This approach could be improved upon. */ |
| 170140 | if( pPhrase->nTerm>(sizeof(aStatic) / sizeof(aStatic[0])) ){ |
| @@ -170146,16 +170150,18 @@ | |
| 170150 | i64 dummy; |
| 170151 | int n = 0; |
| 170152 | int bFlag = 0; |
| 170153 | const u8 *a = 0; |
| 170154 | if( pTerm->pSynonym ){ |
| 170155 | rc = fts5ExprSynonymPoslist( |
| 170156 | pTerm, pColset, pNode->iRowid, &bFlag, (u8**)&a, &n |
| 170157 | ); |
| 170158 | }else{ |
| 170159 | rc = sqlite3Fts5IterPoslist(pTerm->pIter, pColset, &a, &n, &dummy); |
| 170160 | } |
| 170161 | if( rc!=SQLITE_OK ) goto ismatch_out; |
| 170162 | sqlite3Fts5PoslistReaderInit(a, n, &aIter[i]); |
| 170163 | aIter[i].bFlag = bFlag; |
| 170164 | if( aIter[i].bEof ) goto ismatch_out; |
| 170165 | } |
| 170166 | |
| 170167 | while( 1 ){ |
| @@ -170174,15 +170180,13 @@ | |
| 170180 | if( pPos->iPos>iAdj ) iPos = pPos->iPos-i; |
| 170181 | } |
| 170182 | } |
| 170183 | }while( bMatch==0 ); |
| 170184 | |
| 170185 | /* Append position iPos to the output */ |
| 170186 | rc = sqlite3Fts5PoslistWriterAppend(&pPhrase->poslist, &writer, iPos); |
| 170187 | if( rc!=SQLITE_OK ) goto ismatch_out; |
| 170188 | |
| 170189 | for(i=0; i<pPhrase->nTerm; i++){ |
| 170190 | if( sqlite3Fts5PoslistReaderNext(&aIter[i]) ) goto ismatch_out; |
| 170191 | } |
| 170192 | } |
| @@ -170473,65 +170477,10 @@ | |
| 170477 | *piLast = fts5ExprSynonymRowid(pTerm, bDesc, &bEof); |
| 170478 | } |
| 170479 | return bEof; |
| 170480 | } |
| 170481 | |
| 170482 | |
| 170483 | static int fts5ExprNearTest( |
| 170484 | int *pRc, |
| 170485 | Fts5Expr *pExpr, /* Expression that pNear is a part of */ |
| 170486 | Fts5ExprNode *pNode /* The "NEAR" node (FTS5_STRING) */ |
| @@ -170575,38 +170524,19 @@ | |
| 170524 | ** expressions. */ |
| 170525 | Fts5ExprNearset *pNear = pNode->pNear; |
| 170526 | Fts5ExprPhrase *pPhrase = pNear->apPhrase[0]; |
| 170527 | Fts5IndexIter *pIter = pPhrase->aTerm[0].pIter; |
| 170528 | Fts5Colset *pColset = pNear->pColset; |
| 170529 | int rc; |
| 170530 | |
| 170531 | assert( pNode->eType==FTS5_TERM ); |
| 170532 | assert( pNear->nPhrase==1 && pPhrase->nTerm==1 ); |
| 170533 | assert( pPhrase->aTerm[0].pSynonym==0 ); |
| 170534 | |
| 170535 | rc = sqlite3Fts5IterPoslist(pIter, pColset, |
| 170536 | (const u8**)&pPhrase->poslist.p, &pPhrase->poslist.n, &pNode->iRowid |
| 170537 | ); |
| 170538 | pNode->bNomatch = (pPhrase->poslist.n==0); |
| 170539 | return rc; |
| 170540 | } |
| 170541 | |
| 170542 | /* |
| @@ -172033,11 +171963,10 @@ | |
| 171963 | nRet = 0; |
| 171964 | } |
| 171965 | return nRet; |
| 171966 | } |
| 171967 | |
| 171968 | /* |
| 171969 | ** 2014 August 11 |
| 171970 | ** |
| 171971 | ** The author disclaims copyright to this source code. In place of |
| 171972 | ** a legal notice, here is a blessing: |
| @@ -173018,12 +172947,13 @@ | |
| 172947 | Fts5Structure *pStruct; /* Database structure for this iterator */ |
| 172948 | Fts5Buffer poslist; /* Buffer containing current poslist */ |
| 172949 | |
| 172950 | int nSeg; /* Size of aSeg[] array */ |
| 172951 | int bRev; /* True to iterate in reverse order */ |
| 172952 | u8 bSkipEmpty; /* True to skip deleted entries */ |
| 172953 | u8 bEof; /* True at EOF */ |
| 172954 | u8 bFiltered; /* True if column-filter already applied */ |
| 172955 | |
| 172956 | i64 iSwitchRowid; /* Firstest rowid of other than aFirst[1] */ |
| 172957 | Fts5CResult *aFirst; /* Current merge state (see above) */ |
| 172958 | Fts5SegIter aSeg[1]; /* Array of segment iterators */ |
| 172959 | }; |
| @@ -173964,11 +173894,12 @@ | |
| 173894 | ** read. Before returning, set *pnSz to the number of bytes in the position |
| 173895 | ** list, and *pbDel to true if the delete flag is set, or false otherwise. |
| 173896 | */ |
| 173897 | static int fts5GetPoslistSize(const u8 *p, int *pnSz, int *pbDel){ |
| 173898 | int nSz; |
| 173899 | int n = 0; |
| 173900 | fts5FastGetVarint32(p, n, nSz); |
| 173901 | assert_nc( nSz>=0 ); |
| 173902 | *pnSz = nSz/2; |
| 173903 | *pbDel = nSz & 0x0001; |
| 173904 | return n; |
| 173905 | } |
| @@ -173985,17 +173916,16 @@ | |
| 173916 | ** position list content (if any). |
| 173917 | */ |
| 173918 | static void fts5SegIterLoadNPos(Fts5Index *p, Fts5SegIter *pIter){ |
| 173919 | if( p->rc==SQLITE_OK ){ |
| 173920 | int iOff = pIter->iLeafOffset; /* Offset to read at */ |
| 173921 | int nSz; |
| 173922 | ASSERT_SZLEAF_OK(pIter->pLeaf); |
| 173923 | fts5FastGetVarint32(pIter->pLeaf->p, iOff, nSz); |
| 173924 | pIter->bDel = (nSz & 0x0001); |
| 173925 | pIter->nPos = nSz>>1; |
| 173926 | pIter->iLeafOffset = iOff; |
| 173927 | } |
| 173928 | } |
| 173929 | |
| 173930 | static void fts5SegIterLoadRowid(Fts5Index *p, Fts5SegIter *pIter){ |
| 173931 | u8 *a = pIter->pLeaf->p; /* Buffer to read data from */ |
| @@ -175232,10 +175162,11 @@ | |
| 175162 | Fts5IndexIter *pNew; |
| 175163 | pNew = fts5MultiIterAlloc(p, 2); |
| 175164 | if( pNew ){ |
| 175165 | Fts5SegIter *pIter = &pNew->aSeg[1]; |
| 175166 | |
| 175167 | pNew->bFiltered = 1; |
| 175168 | pIter->flags = FTS5_SEGITER_ONETERM; |
| 175169 | if( pData->szLeaf>0 ){ |
| 175170 | pIter->pLeaf = pData; |
| 175171 | pIter->iLeafOffset = fts5GetVarint(pData->p, (u64*)&pIter->iRowid); |
| 175172 | pIter->iEndofDoclist = pData->nn; |
| @@ -176447,11 +176378,11 @@ | |
| 176378 | void *pContext, |
| 176379 | const u8 *pChunk, int nChunk |
| 176380 | ){ |
| 176381 | assert_nc( nChunk>=0 ); |
| 176382 | if( nChunk>0 ){ |
| 176383 | fts5BufferSafeAppendBlob((Fts5Buffer*)pContext, pChunk, nChunk); |
| 176384 | } |
| 176385 | } |
| 176386 | |
| 176387 | typedef struct PoslistCallbackCtx PoslistCallbackCtx; |
| 176388 | struct PoslistCallbackCtx { |
| @@ -176487,11 +176418,11 @@ | |
| 176418 | if( pCtx->eState==2 ){ |
| 176419 | int iCol; |
| 176420 | fts5FastGetVarint32(pChunk, i, iCol); |
| 176421 | if( fts5IndexColsetTest(pCtx->pColset, iCol) ){ |
| 176422 | pCtx->eState = 1; |
| 176423 | fts5BufferSafeAppendVarint(pCtx->pBuf, 1); |
| 176424 | }else{ |
| 176425 | pCtx->eState = 0; |
| 176426 | } |
| 176427 | } |
| 176428 | |
| @@ -176499,11 +176430,11 @@ | |
| 176430 | while( i<nChunk && pChunk[i]!=0x01 ){ |
| 176431 | while( pChunk[i] & 0x80 ) i++; |
| 176432 | i++; |
| 176433 | } |
| 176434 | if( pCtx->eState ){ |
| 176435 | fts5BufferSafeAppendBlob(pCtx->pBuf, &pChunk[iStart], i-iStart); |
| 176436 | } |
| 176437 | if( i<nChunk ){ |
| 176438 | int iCol; |
| 176439 | iStart = i; |
| 176440 | i++; |
| @@ -176511,11 +176442,11 @@ | |
| 176442 | pCtx->eState = 2; |
| 176443 | }else{ |
| 176444 | fts5FastGetVarint32(pChunk, i, iCol); |
| 176445 | pCtx->eState = fts5IndexColsetTest(pCtx->pColset, iCol); |
| 176446 | if( pCtx->eState ){ |
| 176447 | fts5BufferSafeAppendBlob(pCtx->pBuf, &pChunk[iStart], i-iStart); |
| 176448 | iStart = i; |
| 176449 | } |
| 176450 | } |
| 176451 | } |
| 176452 | }while( i<nChunk ); |
| @@ -176532,60 +176463,127 @@ | |
| 176463 | Fts5Index *p, |
| 176464 | Fts5SegIter *pSeg, |
| 176465 | Fts5Colset *pColset, |
| 176466 | Fts5Buffer *pBuf |
| 176467 | ){ |
| 176468 | if( 0==fts5BufferGrow(&p->rc, pBuf, pSeg->nPos) ){ |
| 176469 | if( pColset==0 ){ |
| 176470 | fts5ChunkIterate(p, pSeg, (void*)pBuf, fts5PoslistCallback); |
| 176471 | }else{ |
| 176472 | PoslistCallbackCtx sCtx; |
| 176473 | sCtx.pBuf = pBuf; |
| 176474 | sCtx.pColset = pColset; |
| 176475 | sCtx.eState = pColset ? fts5IndexColsetTest(pColset, 0) : 1; |
| 176476 | assert( sCtx.eState==0 || sCtx.eState==1 ); |
| 176477 | fts5ChunkIterate(p, pSeg, (void*)&sCtx, fts5PoslistFilterCallback); |
| 176478 | } |
| 176479 | } |
| 176480 | } |
| 176481 | |
| 176482 | /* |
| 176483 | ** IN/OUT parameter (*pa) points to a position list n bytes in size. If |
| 176484 | ** the position list contains entries for column iCol, then (*pa) is set |
| 176485 | ** to point to the sub-position-list for that column and the number of |
| 176486 | ** bytes in it returned. Or, if the argument position list does not |
| 176487 | ** contain any entries for column iCol, return 0. |
| 176488 | */ |
| 176489 | static int fts5IndexExtractCol( |
| 176490 | const u8 **pa, /* IN/OUT: Pointer to poslist */ |
| 176491 | int n, /* IN: Size of poslist in bytes */ |
| 176492 | int iCol /* Column to extract from poslist */ |
| 176493 | ){ |
| 176494 | int iCurrent = 0; /* Anything before the first 0x01 is col 0 */ |
| 176495 | const u8 *p = *pa; |
| 176496 | const u8 *pEnd = &p[n]; /* One byte past end of position list */ |
| 176497 | u8 prev = 0; |
| 176498 | |
| 176499 | while( iCol!=iCurrent ){ |
| 176500 | /* Advance pointer p until it points to pEnd or an 0x01 byte that is |
| 176501 | ** not part of a varint */ |
| 176502 | while( (prev & 0x80) || *p!=0x01 ){ |
| 176503 | prev = *p++; |
| 176504 | if( p==pEnd ) return 0; |
| 176505 | } |
| 176506 | *pa = p++; |
| 176507 | p += fts5GetVarint32(p, iCurrent); |
| 176508 | } |
| 176509 | |
| 176510 | /* Advance pointer p until it points to pEnd or an 0x01 byte that is |
| 176511 | ** not part of a varint */ |
| 176512 | assert( (prev & 0x80)==0 ); |
| 176513 | while( p<pEnd && ((prev & 0x80) || *p!=0x01) ){ |
| 176514 | prev = *p++; |
| 176515 | } |
| 176516 | return p - (*pa); |
| 176517 | } |
| 176518 | |
| 176519 | |
| 176520 | /* |
| 176521 | ** Iterator pMulti currently points to a valid entry (not EOF). This |
| 176522 | ** function appends the following to buffer pBuf: |
| 176523 | ** |
| 176524 | ** * The varint iDelta, and |
| 176525 | ** * the position list that currently points to, including the size field. |
| 176526 | ** |
| 176527 | ** If argument pColset is NULL, then the position list is filtered according |
| 176528 | ** to pColset before being appended to the buffer. If this means there are |
| 176529 | ** no entries in the position list, nothing is appended to the buffer (not |
| 176530 | ** even iDelta). |
| 176531 | ** |
| 176532 | ** If an error occurs, an error code is left in p->rc. |
| 176533 | */ |
| 176534 | static int fts5AppendPoslist( |
| 176535 | Fts5Index *p, |
| 176536 | i64 iDelta, |
| 176537 | Fts5IndexIter *pMulti, |
| 176538 | Fts5Colset *pColset, |
| 176539 | Fts5Buffer *pBuf |
| 176540 | ){ |
| 176541 | if( p->rc==SQLITE_OK ){ |
| 176542 | Fts5SegIter *pSeg = &pMulti->aSeg[ pMulti->aFirst[1].iFirst ]; |
| 176543 | assert( fts5MultiIterEof(p, pMulti)==0 ); |
| 176544 | assert( pSeg->nPos>0 ); |
| 176545 | if( 0==fts5BufferGrow(&p->rc, pBuf, pSeg->nPos+9+9) ){ |
| 176546 | int iSv1; |
| 176547 | int iSv2; |
| 176548 | int iData; |
| 176549 | |
| 176550 | /* Append iDelta */ |
| 176551 | iSv1 = pBuf->n; |
| 176552 | fts5BufferSafeAppendVarint(pBuf, iDelta); |
| 176553 | |
| 176554 | /* WRITEPOSLISTSIZE */ |
| 176555 | iSv2 = pBuf->n; |
| 176556 | fts5BufferSafeAppendVarint(pBuf, pSeg->nPos*2); |
| 176557 | iData = pBuf->n; |
| 176558 | |
| 176559 | if( pSeg->iLeafOffset+pSeg->nPos<=pSeg->pLeaf->szLeaf |
| 176560 | && (pColset==0 || pColset->nCol==1) |
| 176561 | ){ |
| 176562 | const u8 *pPos = &pSeg->pLeaf->p[pSeg->iLeafOffset]; |
| 176563 | int nPos; |
| 176564 | if( pColset ){ |
| 176565 | nPos = fts5IndexExtractCol(&pPos, pSeg->nPos, pColset->aiCol[0]); |
| 176566 | }else{ |
| 176567 | nPos = pSeg->nPos; |
| 176568 | } |
| 176569 | fts5BufferSafeAppendBlob(pBuf, pPos, nPos); |
| 176570 | }else{ |
| 176571 | fts5SegiterPoslist(p, pSeg, pColset, pBuf); |
| 176572 | } |
| 176573 | |
| 176574 | if( pColset ){ |
| 176575 | int nActual = pBuf->n - iData; |
| 176576 | if( nActual!=pSeg->nPos ){ |
| 176577 | if( nActual==0 ){ |
| 176578 | pBuf->n = iSv1; |
| 176579 | return 1; |
| 176580 | }else{ |
| 176581 | int nReq = sqlite3Fts5GetVarintLen((u32)(nActual*2)); |
| 176582 | while( iSv2<(iData-nReq) ){ pBuf->p[iSv2++] = 0x80; } |
| 176583 | sqlite3Fts5PutVarint(&pBuf->p[iSv2], nActual*2); |
| 176584 | } |
| 176585 | } |
| 176586 | } |
| 176587 | } |
| 176588 | } |
| 176589 | |
| @@ -176789,19 +176787,12 @@ | |
| 176787 | } |
| 176788 | } |
| 176789 | iLastRowid = 0; |
| 176790 | } |
| 176791 | |
| 176792 | if( !fts5AppendPoslist(p, iRowid-iLastRowid, p1, pColset, &doclist) ){ |
| 176793 | iLastRowid = iRowid; |
| 176794 | } |
| 176795 | } |
| 176796 | |
| 176797 | for(i=0; i<nBuf; i++){ |
| 176798 | if( p->rc==SQLITE_OK ){ |
| @@ -177154,10 +177145,30 @@ | |
| 177145 | const char *z = (const char*)fts5MultiIterTerm(pIter, &n); |
| 177146 | *pn = n-1; |
| 177147 | return &z[1]; |
| 177148 | } |
| 177149 | |
| 177150 | |
| 177151 | static int fts5IndexExtractColset ( |
| 177152 | Fts5Colset *pColset, /* Colset to filter on */ |
| 177153 | const u8 *pPos, int nPos, /* Position list */ |
| 177154 | Fts5Buffer *pBuf /* Output buffer */ |
| 177155 | ){ |
| 177156 | int rc = SQLITE_OK; |
| 177157 | int i; |
| 177158 | |
| 177159 | fts5BufferZero(pBuf); |
| 177160 | for(i=0; i<pColset->nCol; i++){ |
| 177161 | const u8 *pSub = pPos; |
| 177162 | int nSub = fts5IndexExtractCol(&pSub, nPos, pColset->aiCol[i]); |
| 177163 | if( nSub ){ |
| 177164 | fts5BufferAppendBlob(&rc, pBuf, nSub, pSub); |
| 177165 | } |
| 177166 | } |
| 177167 | return rc; |
| 177168 | } |
| 177169 | |
| 177170 | |
| 177171 | /* |
| 177172 | ** Return a pointer to a buffer containing a copy of the position list for |
| 177173 | ** the current entry. Output variable *pn is set to the size of the buffer |
| 177174 | ** in bytes before returning. |
| @@ -177165,24 +177176,37 @@ | |
| 177176 | ** The returned position list does not include the "number of bytes" varint |
| 177177 | ** field that starts the position list on disk. |
| 177178 | */ |
| 177179 | static int sqlite3Fts5IterPoslist( |
| 177180 | Fts5IndexIter *pIter, |
| 177181 | Fts5Colset *pColset, /* Column filter (or NULL) */ |
| 177182 | const u8 **pp, /* OUT: Pointer to position-list data */ |
| 177183 | int *pn, /* OUT: Size of position-list in bytes */ |
| 177184 | i64 *piRowid /* OUT: Current rowid */ |
| 177185 | ){ |
| 177186 | Fts5SegIter *pSeg = &pIter->aSeg[ pIter->aFirst[1].iFirst ]; |
| 177187 | assert( pIter->pIndex->rc==SQLITE_OK ); |
| 177188 | *piRowid = pSeg->iRowid; |
| 177189 | if( pSeg->iLeafOffset+pSeg->nPos<=pSeg->pLeaf->szLeaf ){ |
| 177190 | u8 *pPos = &pSeg->pLeaf->p[pSeg->iLeafOffset]; |
| 177191 | if( pColset==0 || pIter->bFiltered ){ |
| 177192 | *pn = pSeg->nPos; |
| 177193 | *pp = pPos; |
| 177194 | }else if( pColset->nCol==1 ){ |
| 177195 | *pp = pPos; |
| 177196 | *pn = fts5IndexExtractCol(pp, pSeg->nPos, pColset->aiCol[0]); |
| 177197 | }else{ |
| 177198 | fts5BufferZero(&pIter->poslist); |
| 177199 | fts5IndexExtractColset(pColset, pPos, pSeg->nPos, &pIter->poslist); |
| 177200 | *pp = pIter->poslist.p; |
| 177201 | *pn = pIter->poslist.n; |
| 177202 | } |
| 177203 | }else{ |
| 177204 | fts5BufferZero(&pIter->poslist); |
| 177205 | fts5SegiterPoslist(pIter->pIndex, pSeg, pColset, &pIter->poslist); |
| 177206 | *pp = pIter->poslist.p; |
| 177207 | *pn = pIter->poslist.n; |
| 177208 | } |
| 177209 | return fts5IndexReturn(pIter->pIndex); |
| 177210 | } |
| 177211 | |
| 177212 | /* |
| @@ -177375,14 +177399,14 @@ | |
| 177399 | while( rc==SQLITE_OK && 0==sqlite3Fts5IterEof(pIdxIter) ){ |
| 177400 | i64 dummy; |
| 177401 | const u8 *pPos; |
| 177402 | int nPos; |
| 177403 | i64 rowid = sqlite3Fts5IterRowid(pIdxIter); |
| 177404 | rc = sqlite3Fts5IterPoslist(pIdxIter, 0, &pPos, &nPos, &dummy); |
| 177405 | if( rc==SQLITE_OK ){ |
| 177406 | Fts5PoslistReader sReader; |
| 177407 | for(sqlite3Fts5PoslistReaderInit(pPos, nPos, &sReader); |
| 177408 | sReader.bEof==0; |
| 177409 | sqlite3Fts5PoslistReaderNext(&sReader) |
| 177410 | ){ |
| 177411 | int iCol = FTS5_POS2COLUMN(sReader.iPos); |
| 177412 | int iOff = FTS5_POS2OFFSET(sReader.iPos); |
| @@ -179790,11 +179814,11 @@ | |
| 179814 | |
| 179815 | /* Initialize all iterators */ |
| 179816 | for(i=0; i<nIter; i++){ |
| 179817 | const u8 *a; |
| 179818 | int n = fts5CsrPoslist(pCsr, i, &a); |
| 179819 | sqlite3Fts5PoslistReaderInit(a, n, &aIter[i]); |
| 179820 | } |
| 179821 | |
| 179822 | while( 1 ){ |
| 179823 | int *aInst; |
| 179824 | int iBest = -1; |
| @@ -180541,11 +180565,11 @@ | |
| 180565 | sqlite3_context *pCtx, /* Function call context */ |
| 180566 | int nArg, /* Number of args */ |
| 180567 | sqlite3_value **apVal /* Function arguments */ |
| 180568 | ){ |
| 180569 | assert( nArg==0 ); |
| 180570 | sqlite3_result_text(pCtx, "fts5: 2015-10-14 12:29:53 a721fc0d89495518fe5612e2e3bbc60befd2e90d", -1, SQLITE_TRANSIENT); |
| 180571 | } |
| 180572 | |
| 180573 | static int fts5Init(sqlite3 *db){ |
| 180574 | static const sqlite3_module fts5Mod = { |
| 180575 | /* iVersion */ 2, |
| @@ -184045,11 +184069,11 @@ | |
| 184069 | i64 dummy; |
| 184070 | const u8 *pPos; int nPos; /* Position list */ |
| 184071 | i64 iPos = 0; /* 64-bit position read from poslist */ |
| 184072 | int iOff = 0; /* Current offset within position list */ |
| 184073 | |
| 184074 | rc = sqlite3Fts5IterPoslist(pCsr->pIter, 0, &pPos, &nPos, &dummy); |
| 184075 | if( rc==SQLITE_OK ){ |
| 184076 | if( pTab->eType==FTS5_VOCAB_ROW ){ |
| 184077 | while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff, &iPos) ){ |
| 184078 | pCsr->aVal[1]++; |
| 184079 | } |
| 184080 |
+12
-4
| --- src/sqlite3.h | ||
| +++ src/sqlite3.h | ||
| @@ -111,11 +111,11 @@ | ||
| 111 | 111 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 112 | 112 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 113 | 113 | */ |
| 114 | 114 | #define SQLITE_VERSION "3.9.0" |
| 115 | 115 | #define SQLITE_VERSION_NUMBER 3009000 |
| 116 | -#define SQLITE_SOURCE_ID "2015-10-10 15:57:20 35e6248abb4435a8b26d270092b856beff867406" | |
| 116 | +#define SQLITE_SOURCE_ID "2015-10-14 12:29:53 a721fc0d89495518fe5612e2e3bbc60befd2e90d" | |
| 117 | 117 | |
| 118 | 118 | /* |
| 119 | 119 | ** CAPI3REF: Run-Time Library Version Numbers |
| 120 | 120 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 121 | 121 | ** |
| @@ -5654,13 +5654,13 @@ | ||
| 5654 | 5654 | ** used with an SQLite version earlier than 3.8.2, the results of attempting |
| 5655 | 5655 | ** to read or write the estimatedRows field are undefined (but are likely |
| 5656 | 5656 | ** to included crashing the application). The estimatedRows field should |
| 5657 | 5657 | ** therefore only be used if [sqlite3_libversion_number()] returns a |
| 5658 | 5658 | ** value greater than or equal to 3008002. Similarly, the idxFlags field |
| 5659 | -** was added for version 3.8.12. It may therefore only be used if | |
| 5659 | +** was added for version 3.9.0. It may therefore only be used if | |
| 5660 | 5660 | ** sqlite3_libversion_number() returns a value greater than or equal to |
| 5661 | -** 3008012. | |
| 5661 | +** 3009000. | |
| 5662 | 5662 | */ |
| 5663 | 5663 | struct sqlite3_index_info { |
| 5664 | 5664 | /* Inputs */ |
| 5665 | 5665 | int nConstraint; /* Number of entries in aConstraint */ |
| 5666 | 5666 | struct sqlite3_index_constraint { |
| @@ -5684,11 +5684,11 @@ | ||
| 5684 | 5684 | int needToFreeIdxStr; /* Free idxStr using sqlite3_free() if true */ |
| 5685 | 5685 | int orderByConsumed; /* True if output is already ordered */ |
| 5686 | 5686 | double estimatedCost; /* Estimated cost of using this index */ |
| 5687 | 5687 | /* Fields below are only available in SQLite 3.8.2 and later */ |
| 5688 | 5688 | sqlite3_int64 estimatedRows; /* Estimated number of rows returned */ |
| 5689 | - /* Fields below are only available in SQLite 3.8.12 and later */ | |
| 5689 | + /* Fields below are only available in SQLite 3.9.0 and later */ | |
| 5690 | 5690 | int idxFlags; /* Mask of SQLITE_INDEX_SCAN_* flags */ |
| 5691 | 5691 | }; |
| 5692 | 5692 | |
| 5693 | 5693 | /* |
| 5694 | 5694 | ** CAPI3REF: Virtual Table Scan Flags |
| @@ -7943,10 +7943,14 @@ | ||
| 7943 | 7943 | |
| 7944 | 7944 | #ifndef _FTS5_H |
| 7945 | 7945 | #define _FTS5_H |
| 7946 | 7946 | |
| 7947 | 7947 | #include "sqlite3.h" |
| 7948 | + | |
| 7949 | +#ifdef __cplusplus | |
| 7950 | +extern "C" { | |
| 7951 | +#endif | |
| 7948 | 7952 | |
| 7949 | 7953 | /************************************************************************* |
| 7950 | 7954 | ** CUSTOM AUXILIARY FUNCTIONS |
| 7951 | 7955 | ** |
| 7952 | 7956 | ** Virtual table implementations may overload SQL functions by implementing |
| @@ -8428,9 +8432,13 @@ | ||
| 8428 | 8432 | }; |
| 8429 | 8433 | |
| 8430 | 8434 | /* |
| 8431 | 8435 | ** END OF REGISTRATION API |
| 8432 | 8436 | *************************************************************************/ |
| 8437 | + | |
| 8438 | +#ifdef __cplusplus | |
| 8439 | +} /* end of the 'extern "C"' block */ | |
| 8440 | +#endif | |
| 8433 | 8441 | |
| 8434 | 8442 | #endif /* _FTS5_H */ |
| 8435 | 8443 | |
| 8436 | 8444 | |
| 8437 | 8445 |
| --- src/sqlite3.h | |
| +++ src/sqlite3.h | |
| @@ -111,11 +111,11 @@ | |
| 111 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 112 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 113 | */ |
| 114 | #define SQLITE_VERSION "3.9.0" |
| 115 | #define SQLITE_VERSION_NUMBER 3009000 |
| 116 | #define SQLITE_SOURCE_ID "2015-10-10 15:57:20 35e6248abb4435a8b26d270092b856beff867406" |
| 117 | |
| 118 | /* |
| 119 | ** CAPI3REF: Run-Time Library Version Numbers |
| 120 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 121 | ** |
| @@ -5654,13 +5654,13 @@ | |
| 5654 | ** used with an SQLite version earlier than 3.8.2, the results of attempting |
| 5655 | ** to read or write the estimatedRows field are undefined (but are likely |
| 5656 | ** to included crashing the application). The estimatedRows field should |
| 5657 | ** therefore only be used if [sqlite3_libversion_number()] returns a |
| 5658 | ** value greater than or equal to 3008002. Similarly, the idxFlags field |
| 5659 | ** was added for version 3.8.12. It may therefore only be used if |
| 5660 | ** sqlite3_libversion_number() returns a value greater than or equal to |
| 5661 | ** 3008012. |
| 5662 | */ |
| 5663 | struct sqlite3_index_info { |
| 5664 | /* Inputs */ |
| 5665 | int nConstraint; /* Number of entries in aConstraint */ |
| 5666 | struct sqlite3_index_constraint { |
| @@ -5684,11 +5684,11 @@ | |
| 5684 | int needToFreeIdxStr; /* Free idxStr using sqlite3_free() if true */ |
| 5685 | int orderByConsumed; /* True if output is already ordered */ |
| 5686 | double estimatedCost; /* Estimated cost of using this index */ |
| 5687 | /* Fields below are only available in SQLite 3.8.2 and later */ |
| 5688 | sqlite3_int64 estimatedRows; /* Estimated number of rows returned */ |
| 5689 | /* Fields below are only available in SQLite 3.8.12 and later */ |
| 5690 | int idxFlags; /* Mask of SQLITE_INDEX_SCAN_* flags */ |
| 5691 | }; |
| 5692 | |
| 5693 | /* |
| 5694 | ** CAPI3REF: Virtual Table Scan Flags |
| @@ -7943,10 +7943,14 @@ | |
| 7943 | |
| 7944 | #ifndef _FTS5_H |
| 7945 | #define _FTS5_H |
| 7946 | |
| 7947 | #include "sqlite3.h" |
| 7948 | |
| 7949 | /************************************************************************* |
| 7950 | ** CUSTOM AUXILIARY FUNCTIONS |
| 7951 | ** |
| 7952 | ** Virtual table implementations may overload SQL functions by implementing |
| @@ -8428,9 +8432,13 @@ | |
| 8428 | }; |
| 8429 | |
| 8430 | /* |
| 8431 | ** END OF REGISTRATION API |
| 8432 | *************************************************************************/ |
| 8433 | |
| 8434 | #endif /* _FTS5_H */ |
| 8435 | |
| 8436 | |
| 8437 |
| --- src/sqlite3.h | |
| +++ src/sqlite3.h | |
| @@ -111,11 +111,11 @@ | |
| 111 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 112 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 113 | */ |
| 114 | #define SQLITE_VERSION "3.9.0" |
| 115 | #define SQLITE_VERSION_NUMBER 3009000 |
| 116 | #define SQLITE_SOURCE_ID "2015-10-14 12:29:53 a721fc0d89495518fe5612e2e3bbc60befd2e90d" |
| 117 | |
| 118 | /* |
| 119 | ** CAPI3REF: Run-Time Library Version Numbers |
| 120 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 121 | ** |
| @@ -5654,13 +5654,13 @@ | |
| 5654 | ** used with an SQLite version earlier than 3.8.2, the results of attempting |
| 5655 | ** to read or write the estimatedRows field are undefined (but are likely |
| 5656 | ** to included crashing the application). The estimatedRows field should |
| 5657 | ** therefore only be used if [sqlite3_libversion_number()] returns a |
| 5658 | ** value greater than or equal to 3008002. Similarly, the idxFlags field |
| 5659 | ** was added for version 3.9.0. It may therefore only be used if |
| 5660 | ** sqlite3_libversion_number() returns a value greater than or equal to |
| 5661 | ** 3009000. |
| 5662 | */ |
| 5663 | struct sqlite3_index_info { |
| 5664 | /* Inputs */ |
| 5665 | int nConstraint; /* Number of entries in aConstraint */ |
| 5666 | struct sqlite3_index_constraint { |
| @@ -5684,11 +5684,11 @@ | |
| 5684 | int needToFreeIdxStr; /* Free idxStr using sqlite3_free() if true */ |
| 5685 | int orderByConsumed; /* True if output is already ordered */ |
| 5686 | double estimatedCost; /* Estimated cost of using this index */ |
| 5687 | /* Fields below are only available in SQLite 3.8.2 and later */ |
| 5688 | sqlite3_int64 estimatedRows; /* Estimated number of rows returned */ |
| 5689 | /* Fields below are only available in SQLite 3.9.0 and later */ |
| 5690 | int idxFlags; /* Mask of SQLITE_INDEX_SCAN_* flags */ |
| 5691 | }; |
| 5692 | |
| 5693 | /* |
| 5694 | ** CAPI3REF: Virtual Table Scan Flags |
| @@ -7943,10 +7943,14 @@ | |
| 7943 | |
| 7944 | #ifndef _FTS5_H |
| 7945 | #define _FTS5_H |
| 7946 | |
| 7947 | #include "sqlite3.h" |
| 7948 | |
| 7949 | #ifdef __cplusplus |
| 7950 | extern "C" { |
| 7951 | #endif |
| 7952 | |
| 7953 | /************************************************************************* |
| 7954 | ** CUSTOM AUXILIARY FUNCTIONS |
| 7955 | ** |
| 7956 | ** Virtual table implementations may overload SQL functions by implementing |
| @@ -8428,9 +8432,13 @@ | |
| 8432 | }; |
| 8433 | |
| 8434 | /* |
| 8435 | ** END OF REGISTRATION API |
| 8436 | *************************************************************************/ |
| 8437 | |
| 8438 | #ifdef __cplusplus |
| 8439 | } /* end of the 'extern "C"' block */ |
| 8440 | #endif |
| 8441 | |
| 8442 | #endif /* _FTS5_H */ |
| 8443 | |
| 8444 | |
| 8445 |