| | @@ -1,8 +1,8 @@ |
| 1 | 1 | /****************************************************************************** |
| 2 | 2 | ** This file is an amalgamation of many separate C source files from SQLite |
| 3 | | -** version 3.54.0. By combining all the individual C code files into this |
| 3 | +** version 3.55.0. By combining all the individual C code files into this |
| 4 | 4 | ** single large file, the entire code can be compiled as a single translation |
| 5 | 5 | ** unit. This allows many compilers to do optimizations that would not be |
| 6 | 6 | ** possible if the files were compiled separately. Performance improvements |
| 7 | 7 | ** of 5% or more are commonly seen when SQLite is compiled as a single |
| 8 | 8 | ** translation unit. |
| | @@ -16,11 +16,11 @@ |
| 16 | 16 | ** if you want a wrapper to interface SQLite with your choice of programming |
| 17 | 17 | ** language. The code for the "sqlite3" command-line shell is also in a |
| 18 | 18 | ** separate file. This file contains only code for the core SQLite library. |
| 19 | 19 | ** |
| 20 | 20 | ** The content in this amalgamation comes from Fossil check-in |
| 21 | | -** a3332bd623d997921c3186433cd1eab0c941 with changes in files: |
| 21 | +** 668541c592b89d32716420615450d55d9faf with changes in files: |
| 22 | 22 | ** |
| 23 | 23 | ** |
| 24 | 24 | */ |
| 25 | 25 | #ifndef SQLITE_AMALGAMATION |
| 26 | 26 | #define SQLITE_CORE 1 |
| | @@ -465,16 +465,16 @@ |
| 465 | 465 | ** |
| 466 | 466 | ** See also: [sqlite3_libversion()], |
| 467 | 467 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 468 | 468 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 469 | 469 | */ |
| 470 | | -#define SQLITE_VERSION "3.54.0" |
| 471 | | -#define SQLITE_VERSION_NUMBER 3054000 |
| 472 | | -#define SQLITE_SOURCE_ID "2026-10-09 11:47:51 a3332bd623d997921c3186433cd1eab0c9413aa0f68d93b1731cf80128ec3a36" |
| 470 | +#define SQLITE_VERSION "3.55.0" |
| 471 | +#define SQLITE_VERSION_NUMBER 3055000 |
| 472 | +#define SQLITE_SOURCE_ID "2026-10-16 14:31:53 668541c592b89d32716420615450d55d9faf89da8a8e389c673973d8383cca98" |
| 473 | 473 | #define SQLITE_SCM_BRANCH "trunk" |
| 474 | 474 | #define SQLITE_SCM_TAGS "" |
| 475 | | -#define SQLITE_SCM_DATETIME "2026-10-09T11:47:51.732Z" |
| 475 | +#define SQLITE_SCM_DATETIME "2026-10-16T14:31:53.543Z" |
| 476 | 476 | |
| 477 | 477 | /* |
| 478 | 478 | ** CAPI3REF: Run-Time Library Version Numbers |
| 479 | 479 | ** KEYWORDS: sqlite3_version sqlite3_sourceid |
| 480 | 480 | ** |
| | @@ -4399,11 +4399,11 @@ |
| 4399 | 4399 | ** parameter on F or if the value of P does not match any of the |
| 4400 | 4400 | ** above, then sqlite3_uri_boolean(F,P,B) returns (B!=0). |
| 4401 | 4401 | ** |
| 4402 | 4402 | ** The sqlite3_uri_int64(F,P,D) routine converts the value of P into a |
| 4403 | 4403 | ** 64-bit signed integer and returns that integer, or D if P does not |
| 4404 | | -** exist or ff the value of P is something other than an integer. |
| 4404 | +** exist or if the value of P is something other than an integer. |
| 4405 | 4405 | ** |
| 4406 | 4406 | ** The sqlite3_uri_key(F,N) returns a pointer to the name (not |
| 4407 | 4407 | ** the value) of the N-th query parameter for filename F, or a NULL |
| 4408 | 4408 | ** pointer if N is less than zero or greater than the number of query |
| 4409 | 4409 | ** parameters minus 1. The N value is zero-based so N should be 0 to obtain |
| | @@ -18876,11 +18876,10 @@ |
| 18876 | 18876 | unsigned int openFlags; /* Flags passed to sqlite3_vfs.xOpen() */ |
| 18877 | 18877 | int errCode; /* Most recent error code (SQLITE_*) */ |
| 18878 | 18878 | int errByteOffset; /* Byte offset of error in SQL statement */ |
| 18879 | 18879 | int errMask; /* & result codes with this before returning */ |
| 18880 | 18880 | int iSysErrno; /* Errno value from last system error */ |
| 18881 | | - u32 dbOptFlags; /* Flags to enable/disable optimizations */ |
| 18882 | 18881 | u8 enc; /* Text encoding */ |
| 18883 | 18882 | u8 autoCommit; /* The auto-commit flag. */ |
| 18884 | 18883 | u8 temp_store; /* 1: file 2: memory 0: default */ |
| 18885 | 18884 | u8 mallocFailed; /* True if we have seen a malloc failure */ |
| 18886 | 18885 | u8 bBenignMalloc; /* Do not require OOMs if true */ |
| | @@ -18895,10 +18894,11 @@ |
| 18895 | 18894 | u8 eOpenState; /* Current condition of the connection */ |
| 18896 | 18895 | u8 nFpDigit; /* Significant digits to keep on double->text */ |
| 18897 | 18896 | int nextPagesize; /* Pagesize after VACUUM if >0 */ |
| 18898 | 18897 | i64 nChange; /* Value returned by sqlite3_changes() */ |
| 18899 | 18898 | i64 nTotalChange; /* Value returned by sqlite3_total_changes() */ |
| 18899 | + u32 dbOptFlags; /* Flags to enable/disable optimizations */ |
| 18900 | 18900 | int aLimit[SQLITE_N_LIMIT]; /* Limits */ |
| 18901 | 18901 | int nMaxSorterMmap; /* Maximum size of regions mapped by sorter */ |
| 18902 | 18902 | struct sqlite3InitInfo { /* Information used during initialization */ |
| 18903 | 18903 | Pgno newTnum; /* Rootpage of table being initialized */ |
| 18904 | 18904 | u8 iDb; /* Which db file is being initialized */ |
| | @@ -19094,55 +19094,53 @@ |
| 19094 | 19094 | #define DBFLAG_EncodingFixed 0x0040 /* No longer possible to change enc. */ |
| 19095 | 19095 | |
| 19096 | 19096 | /* |
| 19097 | 19097 | ** Bits of the sqlite3.dbOptFlags field that are used by the |
| 19098 | 19098 | ** sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS,...) interface to |
| 19099 | | -** selectively disable various optimizations. |
| 19099 | +** selectively disable various optimizations. The numbers in each macro |
| 19100 | +** are the one-based bit position (for improved readability). |
| 19101 | +** |
| 19102 | +** Keep these values in sync with the ext/misc/optname.c extension. |
| 19100 | 19103 | */ |
| 19101 | | -#define SQLITE_QueryFlattener 0x00000001 /* Query flattening */ |
| 19102 | | -#define SQLITE_WindowFunc 0x00000002 /* Use xInverse for window functions */ |
| 19103 | | -#define SQLITE_GroupByOrder 0x00000004 /* GROUPBY cover of ORDERBY */ |
| 19104 | | - /* 0x00000008 -- Available for reuse */ |
| 19105 | | -#define SQLITE_DistinctOpt 0x00000010 /* DISTINCT using indexes */ |
| 19106 | | -#define SQLITE_CoverIdxScan 0x00000020 /* Covering index scans */ |
| 19107 | | -#define SQLITE_OrderByIdxJoin 0x00000040 /* ORDER BY of joins via index */ |
| 19108 | | -#define SQLITE_Transitive 0x00000080 /* Transitive constraints */ |
| 19109 | | -#define SQLITE_OmitNoopJoin 0x00000100 /* Omit unused tables in joins */ |
| 19110 | | -#define SQLITE_CountOfView 0x00000200 /* The count-of-view optimization */ |
| 19111 | | -#define SQLITE_CursorHints 0x00000400 /* Add OP_CursorHint opcodes */ |
| 19112 | | -#define SQLITE_Stat4 0x00000800 /* Use STAT4 data */ |
| 19113 | | - /* TH3 expects this value ^^^^^^^^^^ */ |
| 19114 | | -#define SQLITE_PushDown 0x00001000 /* WHERE-clause push-down opt */ |
| 19115 | | -#define SQLITE_SimplifyJoin 0x00002000 /* Convert LEFT JOIN to JOIN */ |
| 19116 | | -#define SQLITE_SkipScan 0x00004000 /* Skip-scans */ |
| 19117 | | -#define SQLITE_PropagateConst 0x00008000 /* The constant propagation opt */ |
| 19118 | | -#define SQLITE_MinMaxOpt 0x00010000 /* The min/max optimization */ |
| 19119 | | -#define SQLITE_SeekScan 0x00020000 /* The OP_SeekScan optimization */ |
| 19120 | | -#define SQLITE_OmitOrderBy 0x00040000 /* Omit pointless ORDER BY */ |
| 19121 | | - /* TH3 expects this value ^^^^^^^^^^ */ |
| 19122 | | -#define SQLITE_BloomFilter 0x00080000 /* Use a Bloom filters */ |
| 19123 | | - /* TH3 expects this value ^^^^^^^^^^ */ |
| 19124 | | - /* 0x00100000 -- Available for reuse */ |
| 19125 | | -#define SQLITE_BalancedMerge 0x00200000 /* Balance multi-way merges */ |
| 19126 | | -#define SQLITE_ReleaseReg 0x00400000 /* Use OP_ReleaseReg for testing */ |
| 19127 | | -#define SQLITE_FlttnUnionAll 0x00800000 /* Disable the UNION ALL flattener */ |
| 19128 | | - /* TH3 expects this value ^^^^^^^^^^ */ |
| 19129 | | -#define SQLITE_IndexedExpr 0x01000000 /* Pull exprs from index when able */ |
| 19130 | | -#define SQLITE_Coroutines 0x02000000 /* Co-routines for subqueries */ |
| 19131 | | -#define SQLITE_NullUnusedCols 0x04000000 /* NULL unused columns in subqueries */ |
| 19132 | | -#define SQLITE_OnePass 0x08000000 /* Single-pass DELETE and UPDATE */ |
| 19133 | | -#define SQLITE_OrderBySubq 0x10000000 /* ORDER BY in subquery helps outer */ |
| 19134 | | -#define SQLITE_StarQuery 0x20000000 /* Heurists for star queries */ |
| 19135 | | -#define SQLITE_ExistsToJoin 0x40000000 /* The EXISTS-to-JOIN optimization */ |
| 19136 | | -#define SQLITE_UnionLimit 0x80000000 /* Optimizations for UNION + LIMIT */ |
| 19137 | | -#define SQLITE_AllOpts 0xffffffff /* All optimizations */ |
| 19104 | +#define SQLITE_QueryFlattener 1 /* Query flattening */ |
| 19105 | +#define SQLITE_WindowFunc 2 /* Use xInverse for window functions */ |
| 19106 | +#define SQLITE_GroupByOrder 3 /* GROUPBY cover of ORDERBY */ |
| 19107 | +#define SQLITE_JoinMiss 4 /* Unwind join loops on a lookup miss*/ |
| 19108 | +#define SQLITE_DistinctOpt 5 /* DISTINCT using indexes */ |
| 19109 | +#define SQLITE_CoverIdxScan 6 /* Covering index scans */ |
| 19110 | +#define SQLITE_OrderByIdxJoin 7 /* ORDER BY of joins via index */ |
| 19111 | +#define SQLITE_Transitive 8 /* Transitive constraints */ |
| 19112 | +#define SQLITE_OmitNoopJoin 9 /* Omit unused tables in joins */ |
| 19113 | +#define SQLITE_CountOfView 10 /* The count-of-view optimization */ |
| 19114 | +#define SQLITE_CursorHints 11 /* Add OP_CursorHint opcodes */ |
| 19115 | +#define SQLITE_Stat4 12 /* Use STAT4 data */ |
| 19116 | +#define SQLITE_PushDown 13 /* WHERE-clause push-down opt */ |
| 19117 | +#define SQLITE_SimplifyJoin 14 /* Convert LEFT JOIN to JOIN */ |
| 19118 | +#define SQLITE_SkipScan 15 /* Skip-scans */ |
| 19119 | +#define SQLITE_PropagateConst 16 /* The constant propagation opt */ |
| 19120 | +#define SQLITE_MinMaxOpt 17 /* The min/max optimization */ |
| 19121 | +#define SQLITE_SeekScan 18 /* The OP_SeekScan optimization */ |
| 19122 | +#define SQLITE_OmitOrderBy 19 /* Omit pointless ORDER BY */ |
| 19123 | +#define SQLITE_BloomFilter 20 /* Use a Bloom filters */ |
| 19124 | + /* 21 -- Available for reuse */ |
| 19125 | +#define SQLITE_BalancedMerge 22 /* Balance multi-way merges */ |
| 19126 | +#define SQLITE_ReleaseReg 23 /* Use OP_ReleaseReg for testing */ |
| 19127 | +#define SQLITE_FlttnUnionAll 24 /* Disable the UNION ALL flattener */ |
| 19128 | +#define SQLITE_IndexedExpr 25 /* Pull exprs from index when able */ |
| 19129 | +#define SQLITE_Coroutines 26 /* Co-routines for subqueries */ |
| 19130 | +#define SQLITE_NullUnusedCols 27 /* NULL unused columns in subqueries */ |
| 19131 | +#define SQLITE_OnePass 28 /* Single-pass DELETE and UPDATE */ |
| 19132 | +#define SQLITE_OrderBySubq 29 /* ORDER BY in subquery helps outer */ |
| 19133 | +#define SQLITE_StarQuery 30 /* Heurists for star queries */ |
| 19134 | +#define SQLITE_ExistsToJoin 31 /* The EXISTS-to-JOIN optimization */ |
| 19135 | +#define SQLITE_UnionLimit 32 /* Optimizations for UNION + LIMIT */ |
| 19138 | 19136 | |
| 19139 | 19137 | /* |
| 19140 | 19138 | ** Macros for testing whether or not optimizations are enabled or disabled. |
| 19141 | 19139 | */ |
| 19142 | | -#define OptimizationDisabled(db, mask) (((db)->dbOptFlags&(mask))!=0) |
| 19143 | | -#define OptimizationEnabled(db, mask) (((db)->dbOptFlags&(mask))==0) |
| 19140 | +#define OptimizationDisabled(D,M) (((D)->dbOptFlags&(1ul<<((M)-1)))!=0) |
| 19141 | +#define OptimizationEnabled(D,M) (((D)->dbOptFlags&(1ul<<((M)-1)))==0) |
| 19144 | 19142 | |
| 19145 | 19143 | /* |
| 19146 | 19144 | ** Return true if it OK to factor constant expressions into the initialization |
| 19147 | 19145 | ** code. The argument is a Parse object for the code generator. |
| 19148 | 19146 | */ |
| | @@ -21119,10 +21117,11 @@ |
| 21119 | 21117 | int nRangeReg; /* Size of the temporary register block */ |
| 21120 | 21118 | int iRangeReg; /* First register in temporary register block */ |
| 21121 | 21119 | int nErr; /* Number of errors seen */ |
| 21122 | 21120 | int nTab; /* Number of previously allocated VDBE cursors */ |
| 21123 | 21121 | int nMem; /* Number of memory cells used so far */ |
| 21122 | + int szOpAlloc; /* Bytes of memory space allocated for Vdbe.aOp[] */ |
| 21124 | 21123 | int iSelfTab; /* Table associated with an index on expr, or negative |
| 21125 | 21124 | ** of the base register during check-constraint eval */ |
| 21126 | 21125 | int nNestSel; /* Number of nested SELECT statements and/or VIEWs */ |
| 21127 | 21126 | int nLabel; /* The *negative* of the number of labels used */ |
| 21128 | 21127 | int nLabelAlloc; /* Number of slots in aLabel */ |
| | @@ -22448,15 +22447,14 @@ |
| 22448 | 22447 | SQLITE_PRIVATE int sqlite3ExprIdToTrueFalse(Expr*); |
| 22449 | 22448 | SQLITE_PRIVATE int sqlite3ExprTruthValue(const Expr*); |
| 22450 | 22449 | SQLITE_PRIVATE int sqlite3ExprIsConstant(Parse*,Expr*); |
| 22451 | 22450 | SQLITE_PRIVATE int sqlite3ExprIsConstantOrFunction(Expr*, u8); |
| 22452 | 22451 | SQLITE_PRIVATE int sqlite3ExprIsConstantOrGroupBy(Parse*, Expr*, ExprList*); |
| 22452 | +SQLITE_PRIVATE int sqlite3ExprIsTableConstant(Expr*,int,int); |
| 22453 | 22453 | SQLITE_PRIVATE int sqlite3ExprIsSingleTableConstraint(Expr*,const SrcList*,int,int); |
| 22454 | 22454 | SQLITE_PRIVATE int sqlite3ExprListIsConstant(Parse *pParse, ExprList *pList, int bNoIs); |
| 22455 | | -#ifdef SQLITE_ENABLE_CURSOR_HINTS |
| 22456 | 22455 | SQLITE_PRIVATE int sqlite3ExprContainsSubquery(Expr*); |
| 22457 | | -#endif |
| 22458 | 22456 | SQLITE_PRIVATE int sqlite3ExprIsInteger(const Expr*, int*, Parse*, int); |
| 22459 | 22457 | SQLITE_PRIVATE int sqlite3ExprCanBeNull(const Expr*); |
| 22460 | 22458 | SQLITE_PRIVATE int sqlite3ExprNeedsNoAffinityChange(const Expr*, char); |
| 22461 | 22459 | SQLITE_PRIVATE int sqlite3ExprIsLikeOperator(const Expr*); |
| 22462 | 22460 | SQLITE_PRIVATE int sqlite3IsRowid(const char*); |
| | @@ -26055,36 +26053,39 @@ |
| 26055 | 26053 | p->isUtc = 1; |
| 26056 | 26054 | p->isLocal = 0; |
| 26057 | 26055 | } |
| 26058 | 26056 | } |
| 26059 | 26057 | } |
| 26058 | + |
| 26059 | +/* |
| 26060 | +** Return the number of dates in a specific month. |
| 26061 | +*/ |
| 26062 | +static int daysOfMonth(int Y, int M){ |
| 26063 | + if( (1<<M) & 0x15aa ){ |
| 26064 | + return 31; |
| 26065 | + }else if( M!=2 ){ |
| 26066 | + return 30; |
| 26067 | + }else if( Y%4==0 && (Y%100!=0 || Y%400==0) ){ |
| 26068 | + return 29; |
| 26069 | + }else{ |
| 26070 | + return 28; |
| 26071 | + } |
| 26072 | +} |
| 26060 | 26073 | |
| 26061 | 26074 | /* |
| 26062 | 26075 | ** Given the YYYY-MM-DD information current in p, determine if there |
| 26063 | 26076 | ** is day-of-month overflow and set nFloor to the number of days that |
| 26064 | 26077 | ** would need to be subtracted from the date in order to bring the |
| 26065 | 26078 | ** date back to the end of the month. |
| 26066 | 26079 | */ |
| 26067 | 26080 | static void computeFloor(DateTime *p){ |
| 26081 | + int mxD; /* Maximum day number for the current month */ |
| 26068 | 26082 | assert( p->validYMD || p->isError ); |
| 26069 | | - assert( p->D>=0 && p->D<=31 ); |
| 26083 | + assert( p->D>=0 && p->D<=32 ); |
| 26070 | 26084 | assert( p->M>=0 && p->M<=12 ); |
| 26071 | | - if( p->validHMS && p->h==24 ){ |
| 26072 | | - p->h = 0; |
| 26073 | | - p->D++; |
| 26074 | | - } |
| 26075 | | - if( p->D<=28 ){ |
| 26076 | | - p->nFloor = 0; |
| 26077 | | - }else if( (1<<p->M) & 0x15aa ){ |
| 26078 | | - p->nFloor = 0; |
| 26079 | | - }else if( p->M!=2 ){ |
| 26080 | | - p->nFloor = (p->D==31); |
| 26081 | | - }else if( p->Y%4!=0 || (p->Y%100==0 && p->Y%400!=0) ){ |
| 26082 | | - p->nFloor = p->D - 28; |
| 26083 | | - }else{ |
| 26084 | | - p->nFloor = p->D - 29; |
| 26085 | | - } |
| 26085 | + mxD = daysOfMonth(p->Y, p->M); |
| 26086 | + p->nFloor = p->D>mxD ? p->D - mxD : 0; |
| 26086 | 26087 | } |
| 26087 | 26088 | |
| 26088 | 26089 | /* |
| 26089 | 26090 | ** Parse dates of the form |
| 26090 | 26091 | ** |
| | @@ -26110,11 +26111,23 @@ |
| 26110 | 26111 | return 1; |
| 26111 | 26112 | } |
| 26112 | 26113 | zDate += 10; |
| 26113 | 26114 | while( sqlite3Isspace(*zDate) || 'T'==*(u8*)zDate ){ zDate++; } |
| 26114 | 26115 | if( parseHhMmSs(zDate, p)==0 ){ |
| 26115 | | - /* We got the time */ |
| 26116 | + if( p->h==24 ){ |
| 26117 | + int mxD = daysOfMonth(Y,M); |
| 26118 | + p->h = 0; |
| 26119 | + D++; |
| 26120 | + if( D>mxD ){ |
| 26121 | + D -= mxD; |
| 26122 | + M++; |
| 26123 | + if( M>12 ){ |
| 26124 | + M = 1; |
| 26125 | + Y++; |
| 26126 | + } |
| 26127 | + } |
| 26128 | + } |
| 26116 | 26129 | }else if( *zDate==0 ){ |
| 26117 | 26130 | p->validHMS = 0; |
| 26118 | 26131 | }else{ |
| 26119 | 26132 | return 1; |
| 26120 | 26133 | } |
| | @@ -46240,32 +46253,39 @@ |
| 46240 | 46253 | #ifdef SQLITE_MMAP_READWRITE |
| 46241 | 46254 | if( (pFd->ctrlFlags & UNIXFILE_RDONLY)==0 ) flags |= PROT_WRITE; |
| 46242 | 46255 | #endif |
| 46243 | 46256 | |
| 46244 | 46257 | if( pOrig ){ |
| 46258 | + i64 nReuse = pFd->mmapSize & ~((int)osGetpagesize()-1); |
| 46259 | + |
| 46260 | + /* Unmap any part of the current mapping that will not be reused */ |
| 46261 | + if( nReuse<pFd->mmapSizeActual ){ |
| 46262 | + osMunmap(&pOrig[nReuse], pFd->mmapSizeActual - nReuse); |
| 46263 | + } |
| 46264 | + |
| 46265 | + /* If nReuse is now zero, then the entire mapping was unmapped by the |
| 46266 | + ** call above. In this case do not attempt to extend pOrig. */ |
| 46267 | + if( nReuse>0 ){ |
| 46245 | 46268 | #if HAVE_MREMAP |
| 46246 | | - i64 nReuse = pFd->mmapSize; |
| 46247 | | - pNew = osMremap(pOrig, nReuse, nNew, MREMAP_MAYMOVE); |
| 46248 | | - zErr = "mremap"; |
| 46269 | + pNew = osMremap(pOrig, nReuse, nNew, MREMAP_MAYMOVE); |
| 46270 | + zErr = "mremap"; |
| 46249 | 46271 | #else |
| 46250 | | - const int szSyspage = osGetpagesize(); |
| 46251 | | - i64 nReuse = (pFd->mmapSize & ~(szSyspage-1)); |
| 46252 | | - u8 *pReq = &pOrig[nReuse]; |
| 46253 | | - pNew = osMmap(pReq, nNew-nReuse, flags, MAP_SHARED, h, nReuse); |
| 46254 | | - if( pNew!=MAP_FAILED ){ |
| 46255 | | - if( pNew!=pReq ){ |
| 46256 | | - osMunmap(pNew, nNew - nReuse); |
| 46257 | | - pNew = 0; |
| 46258 | | - }else{ |
| 46259 | | - pNew = pOrig; |
| 46260 | | - } |
| 46261 | | - } |
| 46272 | + pNew = osMmap(&pOrig[nReuse], nNew-nReuse, flags, MAP_SHARED, h, nReuse); |
| 46273 | + if( pNew!=MAP_FAILED ){ |
| 46274 | + if( pNew!=&pOrig[nReuse] ){ |
| 46275 | + osMunmap(pNew, nNew - nReuse); |
| 46276 | + pNew = 0; |
| 46277 | + }else{ |
| 46278 | + pNew = pOrig; |
| 46279 | + } |
| 46280 | + } |
| 46262 | 46281 | #endif |
| 46263 | 46282 | |
| 46264 | | - /* The attempt to extend the existing mapping failed. Free it. */ |
| 46265 | | - if( pNew==MAP_FAILED || pNew==0 ){ |
| 46266 | | - osMunmap(pOrig, nReuse); |
| 46283 | + /* The attempt to extend the existing mapping failed. Free it. */ |
| 46284 | + if( pNew==MAP_FAILED || pNew==0 ){ |
| 46285 | + osMunmap(pOrig, nReuse); |
| 46286 | + } |
| 46267 | 46287 | } |
| 46268 | 46288 | } |
| 46269 | 46289 | |
| 46270 | 46290 | /* If pNew is still NULL, try to create an entirely new mapping. */ |
| 46271 | 46291 | if( pNew==0 ){ |
| | @@ -72669,16 +72689,22 @@ |
| 72669 | 72689 | SQLITE_PRIVATE void sqlite3BtreeEnter(Btree *p){ |
| 72670 | 72690 | p->pBt->db = p->db; |
| 72671 | 72691 | } |
| 72672 | 72692 | SQLITE_PRIVATE void sqlite3BtreeEnterAll(sqlite3 *db){ |
| 72673 | 72693 | int i; |
| 72694 | + u8 skipOk = 1; |
| 72695 | + /* As in the threadsafe build: set db->noSharedCache when no attached |
| 72696 | + ** Btree is sharable, so that schema and table-lock checks are skipped */ |
| 72697 | + if( db->noSharedCache ) return; |
| 72674 | 72698 | for(i=0; i<db->nDb; i++){ |
| 72675 | 72699 | Btree *p = db->aDb[i].pBt; |
| 72676 | 72700 | if( p ){ |
| 72677 | 72701 | p->pBt->db = p->db; |
| 72702 | + if( p->sharable ) skipOk = 0; |
| 72678 | 72703 | } |
| 72679 | 72704 | } |
| 72705 | + db->noSharedCache = skipOk; |
| 72680 | 72706 | } |
| 72681 | 72707 | #endif /* if SQLITE_THREADSAFE */ |
| 72682 | 72708 | |
| 72683 | 72709 | #ifndef SQLITE_OMIT_INCRBLOB |
| 72684 | 72710 | /* |
| | @@ -80129,11 +80155,11 @@ |
| 80129 | 80155 | ** the source page. Make sure this does not cause problems by not |
| 80130 | 80156 | ** reading the first 4 bytes */ |
| 80131 | 80157 | memcpy(&data[idx+4], pCell+4, sz-4); |
| 80132 | 80158 | put4byte(&data[idx], iChild); |
| 80133 | 80159 | pIns = pPage->aCellIdx + i*2; |
| 80134 | | - memmove(pIns+2, pIns, 2*(pPage->nCell - i)); |
| 80160 | + if( i<pPage->nCell ) memmove(pIns+2, pIns, 2*(pPage->nCell - i)); |
| 80135 | 80161 | put2byte(pIns, idx); |
| 80136 | 80162 | pPage->nCell++; |
| 80137 | 80163 | /* increment the cell count */ |
| 80138 | 80164 | if( (++data[pPage->hdrOffset+4])==0 ) data[pPage->hdrOffset+3]++; |
| 80139 | 80165 | assert( get2byte(&data[pPage->hdrOffset+3])==pPage->nCell || CORRUPT_DB ); |
| | @@ -80213,11 +80239,11 @@ |
| 80213 | 80239 | assert( idx >= pPage->cellOffset+2*pPage->nCell+2 || CORRUPT_DB ); |
| 80214 | 80240 | assert( idx+sz <= (int)pPage->pBt->usableSize ); |
| 80215 | 80241 | pPage->nFree -= (u16)(2 + sz); |
| 80216 | 80242 | memcpy(&data[idx], pCell, sz); |
| 80217 | 80243 | pIns = pPage->aCellIdx + i*2; |
| 80218 | | - memmove(pIns+2, pIns, 2*(pPage->nCell - i)); |
| 80244 | + if( i<pPage->nCell ) memmove(pIns+2, pIns, 2*(pPage->nCell - i)); |
| 80219 | 80245 | put2byte(pIns, idx); |
| 80220 | 80246 | pPage->nCell++; |
| 80221 | 80247 | /* increment the cell count */ |
| 80222 | 80248 | if( (++data[pPage->hdrOffset+4])==0 ) data[pPage->hdrOffset+3]++; |
| 80223 | 80249 | assert( get2byte(&data[pPage->hdrOffset+3])==pPage->nCell || CORRUPT_DB ); |
| | @@ -81166,10 +81192,11 @@ |
| 81166 | 81192 | int limit = pOld->nCell; |
| 81167 | 81193 | u8 *aData = pOld->aData; |
| 81168 | 81194 | u16 maskPage = pOld->maskPage; |
| 81169 | 81195 | u8 *piCell = aData + pOld->cellOffset; |
| 81170 | 81196 | u8 *piEnd; |
| 81197 | + u8 **ppCell; |
| 81171 | 81198 | VVA_ONLY( int nCellAtStart = b.nCell; ) |
| 81172 | 81199 | |
| 81173 | 81200 | /* Verify that all sibling pages are of the same "type" (table-leaf, |
| 81174 | 81201 | ** table-interior, index-leaf, or index-interior). |
| 81175 | 81202 | */ |
| | @@ -81201,27 +81228,29 @@ |
| 81201 | 81228 | rc = SQLITE_CORRUPT_PAGE(pOld); |
| 81202 | 81229 | goto balance_cleanup; |
| 81203 | 81230 | } |
| 81204 | 81231 | limit = pOld->aiOvfl[0]; |
| 81205 | 81232 | for(j=0; j<limit; j++){ |
| 81206 | | - b.apCell[b.nCell] = aData + (maskPage & get2byteAligned(piCell)); |
| 81233 | + b.apCell[b.nCell+j] = aData + (maskPage & get2byteAligned(piCell)); |
| 81207 | 81234 | piCell += 2; |
| 81208 | | - b.nCell++; |
| 81209 | 81235 | } |
| 81236 | + b.nCell += limit; |
| 81210 | 81237 | for(k=0; k<pOld->nOverflow; k++){ |
| 81211 | 81238 | assert( k==0 || pOld->aiOvfl[k-1]+1==pOld->aiOvfl[k] );/* NOTE 1 */ |
| 81212 | 81239 | b.apCell[b.nCell] = pOld->apOvfl[k]; |
| 81213 | 81240 | b.nCell++; |
| 81214 | 81241 | } |
| 81215 | 81242 | } |
| 81216 | 81243 | piEnd = aData + pOld->cellOffset + 2*pOld->nCell; |
| 81244 | + /* Collect cell pointers before updating the cell count. */ |
| 81245 | + ppCell = &b.apCell[b.nCell]; |
| 81217 | 81246 | while( piCell<piEnd ){ |
| 81218 | | - assert( b.nCell<nMaxCells ); |
| 81219 | | - b.apCell[b.nCell] = aData + (maskPage & get2byteAligned(piCell)); |
| 81247 | + assert( ppCell<&b.apCell[nMaxCells] ); |
| 81248 | + *ppCell++ = aData + (maskPage & get2byteAligned(piCell)); |
| 81220 | 81249 | piCell += 2; |
| 81221 | | - b.nCell++; |
| 81222 | 81250 | } |
| 81251 | + b.nCell = (int)(ppCell - b.apCell); |
| 81223 | 81252 | assert( (b.nCell-nCellAtStart)==(pOld->nCell+pOld->nOverflow) ); |
| 81224 | 81253 | |
| 81225 | 81254 | cntOld[i] = b.nCell; |
| 81226 | 81255 | if( i<nOld-1 && !leafData){ |
| 81227 | 81256 | u16 sz = (u16)szNew[i]; |
| | @@ -87092,10 +87121,11 @@ |
| 87092 | 87121 | zVal = &pExpr->u.zToken[2]; |
| 87093 | 87122 | nVal = sqlite3Strlen30(zVal)-1; |
| 87094 | 87123 | assert( zVal[nVal]=='\'' ); |
| 87095 | 87124 | sqlite3VdbeMemSetStr(pVal, sqlite3HexToBlob(db, zVal, nVal), nVal/2, |
| 87096 | 87125 | 0, SQLITE_DYNAMIC); |
| 87126 | + pVal->enc = enc; |
| 87097 | 87127 | } |
| 87098 | 87128 | #endif |
| 87099 | 87129 | #ifdef SQLITE_ENABLE_STAT4 |
| 87100 | 87130 | else if( op==TK_FUNCTION && pCtx!=0 ){ |
| 87101 | 87131 | rc = valueFromFunction(db, pExpr, enc, affinity, &pVal, pCtx); |
| | @@ -87486,10 +87516,11 @@ |
| 87486 | 87516 | p->pParse = pParse; |
| 87487 | 87517 | pParse->pVdbe = p; |
| 87488 | 87518 | assert( pParse->aLabel==0 ); |
| 87489 | 87519 | assert( pParse->nLabel==0 ); |
| 87490 | 87520 | assert( p->nOpAlloc==0 ); |
| 87521 | + assert( pParse->szOpAlloc==0 ); |
| 87491 | 87522 | sqlite3VdbeAddOp2(p, OP_Init, 0, 1); |
| 87492 | 87523 | return p; |
| 87493 | 87524 | } |
| 87494 | 87525 | |
| 87495 | 87526 | /* |
| | @@ -87516,10 +87547,11 @@ |
| 87516 | 87547 | SQLITE_PRIVATE void sqlite3VdbeSetSql(Vdbe *p, const char *z, int n, u8 prepFlags){ |
| 87517 | 87548 | if( p==0 ) return; |
| 87518 | 87549 | p->prepFlags = prepFlags; |
| 87519 | 87550 | if( (prepFlags & SQLITE_PREPARE_SAVESQL)==0 ){ |
| 87520 | 87551 | p->expmask = 0; |
| 87552 | + p->smimask = 0; |
| 87521 | 87553 | } |
| 87522 | 87554 | assert( p->zSql==0 ); |
| 87523 | 87555 | p->zSql = sqlite3DbStrNDup(p->db, z, n); |
| 87524 | 87556 | } |
| 87525 | 87557 | |
| | @@ -87636,11 +87668,12 @@ |
| 87636 | 87668 | |
| 87637 | 87669 | assert( nOp<=(int)(1024/sizeof(Op)) ); |
| 87638 | 87670 | assert( nNew>=(v->nOpAlloc+nOp) ); |
| 87639 | 87671 | pNew = sqlite3DbRealloc(p->db, v->aOp, nNew*sizeof(Op)); |
| 87640 | 87672 | if( pNew ){ |
| 87641 | | - v->nOpAlloc = sqlite3DbMallocSize(p->db, pNew)/sizeof(Op); |
| 87673 | + p->szOpAlloc = sqlite3DbMallocSize(p->db, pNew); |
| 87674 | + v->nOpAlloc = p->szOpAlloc/sizeof(Op); |
| 87642 | 87675 | v->aOp = pNew; |
| 87643 | 87676 | } |
| 87644 | 87677 | return (pNew ? SQLITE_OK : SQLITE_NOMEM_BKPT); |
| 87645 | 87678 | } |
| 87646 | 87679 | |
| | @@ -90143,11 +90176,11 @@ |
| 90143 | 90176 | ** of the prepared statement. |
| 90144 | 90177 | */ |
| 90145 | 90178 | n = ROUND8P(sizeof(Op)*p->nOp); /* Bytes of opcode memory used */ |
| 90146 | 90179 | x.pSpace = &((u8*)p->aOp)[n]; /* Unused opcode memory */ |
| 90147 | 90180 | assert( EIGHT_BYTE_ALIGNMENT(x.pSpace) ); |
| 90148 | | - x.nFree = ROUNDDOWN8((p->nOpAlloc-p->nOp)*sizeof(Op)); /* Bytes unused mem */ |
| 90181 | + x.nFree = ROUNDDOWN8(pParse->szOpAlloc - n); /* Bytes unused memory */ |
| 90149 | 90182 | assert( x.nFree>=0 ); |
| 90150 | 90183 | assert( EIGHT_BYTE_ALIGNMENT(&x.pSpace[x.nFree]) ); |
| 90151 | 90184 | |
| 90152 | 90185 | resolveP2Values(p, &nArg); |
| 90153 | 90186 | p->usesStmtJournal = (u8)(pParse->isMultiWrite && pParse->mayAbort); |
| | @@ -92794,14 +92827,16 @@ |
| 92794 | 92827 | assert( iVar>0 ); |
| 92795 | 92828 | assert( (v->db->flags & SQLITE_EnableQPSG)==0 |
| 92796 | 92829 | || (v->db->mDbFlags & DBFLAG_InternalFunc)!=0 ); |
| 92797 | 92830 | |
| 92798 | 92831 | m = (iVar>=32) ? 0x80000000 : ((u32)1 << (iVar-1)); |
| 92799 | | - v->expmask |= m; |
| 92800 | 92832 | if( bSmallint ){ |
| 92801 | | - v->smimask |= m; |
| 92833 | + if( (v->expmask & m)==0 ) v->smimask |= m; |
| 92834 | + }else{ |
| 92835 | + v->smimask &= ~m; |
| 92802 | 92836 | } |
| 92837 | + v->expmask |= m; |
| 92803 | 92838 | |
| 92804 | 92839 | /* smimask is always a subset of expmask */ |
| 92805 | 92840 | assert( (v->smimask & v->expmask) == v->smimask ); |
| 92806 | 92841 | } |
| 92807 | 92842 | |
| | @@ -94950,14 +94985,12 @@ |
| 94950 | 94985 | if( i>=(unsigned int)p->nVar ){ |
| 94951 | 94986 | sqlite3Error(p->db, SQLITE_RANGE); |
| 94952 | 94987 | sqlite3_mutex_leave(p->db->mutex); |
| 94953 | 94988 | return SQLITE_RANGE; |
| 94954 | 94989 | } |
| 94990 | + |
| 94955 | 94991 | pVar = &p->aVar[i]; |
| 94956 | | - sqlite3VdbeMemRelease(pVar); |
| 94957 | | - pVar->flags = MEM_Null; |
| 94958 | | - p->db->errCode = SQLITE_OK; |
| 94959 | 94992 | |
| 94960 | 94993 | /* If the bit corresponding to this variable in Vdbe.expmask is set, then |
| 94961 | 94994 | ** binding a new value to this variable invalidates the current query plan. |
| 94962 | 94995 | ** |
| 94963 | 94996 | ** IMPLEMENTATION-OF: R-57496-20354 If the specific value bound to a host |
| | @@ -94967,15 +95000,24 @@ |
| 94967 | 95000 | ** following any change to the bindings of that parameter. |
| 94968 | 95001 | */ |
| 94969 | 95002 | assert( (p->prepFlags & SQLITE_PREPARE_SAVESQL)!=0 || p->expmask==0 ); |
| 94970 | 95003 | assert( (p->expmask & p->smimask)==p->smimask ); |
| 94971 | 95004 | if( p->expmask!=0 && (p->expmask & (i>=31 ? 0x80000000 : (u32)1<<i))!=0 ){ |
| 94972 | | - /* We might avoid a reprepare here if p->smimask is set and the old |
| 94973 | | - ** value is an integer other than (0,1). But that is such a corner |
| 94974 | | - ** case that it does not seem worth the extra code to implement. */ |
| 94975 | | - p->expired = 1; |
| 95005 | + /* If the p->smimask bit is also set, then only expire the statement if |
| 95006 | + ** the value being clobbered was integer value 0 or 1. */ |
| 95007 | + if( (p->smimask==0) |
| 95008 | + || (p->smimask & (i>=31 ? 0x80000000 : (u32)1<<i))==0 |
| 95009 | + || ((pVar->flags & MEM_Int)!=0 && pVar->u.i>=0 && pVar->u.i<=1) |
| 95010 | + ){ |
| 95011 | + p->expired = 1; |
| 95012 | + } |
| 94976 | 95013 | } |
| 95014 | + |
| 95015 | + sqlite3VdbeMemRelease(pVar); |
| 95016 | + pVar->flags = MEM_Null; |
| 95017 | + p->db->errCode = SQLITE_OK; |
| 95018 | + |
| 94977 | 95019 | return SQLITE_OK; |
| 94978 | 95020 | } |
| 94979 | 95021 | |
| 94980 | 95022 | /* |
| 94981 | 95023 | ** Bind a text or BLOB value. |
| | @@ -95099,12 +95141,12 @@ |
| 95099 | 95141 | int sm1 = (pVar->flags & MEM_Int)!=0 && pVar->u.i>=0 && pVar->u.i<=1; |
| 95100 | 95142 | int sm2 = iValue>=0 && iValue<=1; |
| 95101 | 95143 | if( sm1!=sm2 ){ |
| 95102 | 95144 | p->expired = 1; |
| 95103 | 95145 | } |
| 95104 | | - }else if( (pVar->flags & MEM_Int)==0 || pVar->u.i!=iValue ){ |
| 95105 | | - /* Always expire if the value really is changing */ |
| 95146 | + }else if( (pVar->flags & MEM_Int)==0 || iValue!=pVar->u.i ){ |
| 95147 | + /* Always expire if the smimask bit is clear */ |
| 95106 | 95148 | p->expired = 1; |
| 95107 | 95149 | } |
| 95108 | 95150 | } |
| 95109 | 95151 | } |
| 95110 | 95152 | sqlite3VdbeMemSetInt64(pVar, iValue); |
| | @@ -98405,11 +98447,22 @@ |
| 98405 | 98447 | ** raise an SQLITE_MISMATCH exception. |
| 98406 | 98448 | */ |
| 98407 | 98449 | case OP_MustBeInt: { /* jump0, in1 */ |
| 98408 | 98450 | pIn1 = &aMem[pOp->p1]; |
| 98409 | 98451 | if( (pIn1->flags & MEM_Int)==0 ){ |
| 98410 | | - applyAffinity(pIn1, SQLITE_AFF_NUMERIC, encoding); |
| 98452 | + if( (pIn1->flags & MEM_Real)!=0 ){ |
| 98453 | + sqlite3_int64 ix; |
| 98454 | + if( pIn1->u.r>=-9223372036854775808.0 |
| 98455 | + && pIn1->u.r<+9223372036854775808.0 |
| 98456 | + && (double)(ix = sqlite3RealToI64(pIn1->u.r))==pIn1->u.r |
| 98457 | + ){ |
| 98458 | + pIn1->u.i = ix; |
| 98459 | + MemSetTypeFlag(pIn1, MEM_Int); |
| 98460 | + } |
| 98461 | + }else{ |
| 98462 | + applyAffinity(pIn1, SQLITE_AFF_NUMERIC, encoding); |
| 98463 | + } |
| 98411 | 98464 | if( (pIn1->flags & MEM_Int)==0 ){ |
| 98412 | 98465 | VdbeBranchTaken(1, 2); |
| 98413 | 98466 | if( pOp->p2==0 ){ |
| 98414 | 98467 | rc = SQLITE_MISMATCH; |
| 98415 | 98468 | goto abort_due_to_error; |
| | @@ -100995,10 +101048,13 @@ |
| 100995 | 101048 | assert( !sqlite3BtreeClosesWithCursor(pCx->ub.pBtx, pCx->uc.pCursor) ); |
| 100996 | 101049 | sqlite3BtreeClose(pCx->ub.pBtx); |
| 100997 | 101050 | p->apCsr[pOp->p1] = 0; /* Not required; helps with static analysis */ |
| 100998 | 101051 | }else{ |
| 100999 | 101052 | assert( sqlite3BtreeClosesWithCursor(pCx->ub.pBtx, pCx->uc.pCursor) ); |
| 101053 | + if( pOp->opcode==OP_OpenAutoindex ){ |
| 101054 | + sqlite3BtreeCursorHintFlags(pCx->uc.pCursor, BTREE_SEEK_EQ); |
| 101055 | + } |
| 101000 | 101056 | } |
| 101001 | 101057 | } |
| 101002 | 101058 | } |
| 101003 | 101059 | if( rc ) goto abort_due_to_error; |
| 101004 | 101060 | pCx->nullRow = 1; |
| | @@ -101129,15 +101185,26 @@ |
| 101129 | 101185 | ** greater than or equal to the key and P2 is not zero, then jump to P2. |
| 101130 | 101186 | ** |
| 101131 | 101187 | ** If the cursor P1 was opened using the OPFLAG_SEEKEQ flag, then this |
| 101132 | 101188 | ** opcode will either land on a record that exactly matches the key, or |
| 101133 | 101189 | ** else it will cause a jump to P2. When the cursor is OPFLAG_SEEKEQ, |
| 101134 | | -** this opcode must be followed by an IdxLE opcode with the same arguments. |
| 101190 | +** this opcode must be followed by an IdxLE opcode with the same arguments, |
| 101191 | +** except that the P2 argument (the jump destination) can be different. |
| 101135 | 101192 | ** The IdxGT opcode will be skipped if this opcode succeeds, but the |
| 101136 | 101193 | ** IdxGT opcode will be used on subsequent loop iterations. The |
| 101137 | 101194 | ** OPFLAG_SEEKEQ flags is a hint to the btree layer to say that this |
| 101138 | 101195 | ** is an equality search. |
| 101196 | +** |
| 101197 | +** The P2 of the IdxLE might be less than the P2 of this opcode. The P2 |
| 101198 | +** of the IdxLE will be the location to jump to if there are one or more |
| 101199 | +** matching rows and is the location to continue with the next row of the |
| 101200 | +** first containing loop. The P2 of this opcode will be the location to |
| 101201 | +** jump to if zero rows of cursor P1 match the key, and that will be the |
| 101202 | +** continuation address of the first outer loop that contributes to the |
| 101203 | +** key. The P2 of this opcode might be greater than the P2 of the |
| 101204 | +** subsequent IdxLE if the first outer loop that influences the key is |
| 101205 | +** outer to the immediately next outer loop. |
| 101139 | 101206 | ** |
| 101140 | 101207 | ** This opcode leaves the cursor configured to move in forward order, |
| 101141 | 101208 | ** from the beginning toward the end. In other words, the cursor is |
| 101142 | 101209 | ** configured to use Next, not Prev. |
| 101143 | 101210 | ** |
| | @@ -101196,15 +101263,26 @@ |
| 101196 | 101263 | ** configured to use Prev, not Next. |
| 101197 | 101264 | ** |
| 101198 | 101265 | ** If the cursor P1 was opened using the OPFLAG_SEEKEQ flag, then this |
| 101199 | 101266 | ** opcode will either land on a record that exactly matches the key, or |
| 101200 | 101267 | ** else it will cause a jump to P2. When the cursor is OPFLAG_SEEKEQ, |
| 101201 | | -** this opcode must be followed by an IdxLE opcode with the same arguments. |
| 101268 | +** this opcode must be followed by an IdxGE opcode with the same arguments |
| 101269 | +** except the P2 of IdxGE might be less than the P2 of this opcode. |
| 101202 | 101270 | ** The IdxGE opcode will be skipped if this opcode succeeds, but the |
| 101203 | 101271 | ** IdxGE opcode will be used on subsequent loop iterations. The |
| 101204 | 101272 | ** OPFLAG_SEEKEQ flags is a hint to the btree layer to say that this |
| 101205 | 101273 | ** is an equality search. |
| 101274 | +** |
| 101275 | +** The P2 of the IdxGE might be less than the P2 of this opcode. The P2 |
| 101276 | +** of the IdxGE will be the location to jump to if there are one or more |
| 101277 | +** matching rows and is the location to continue with the next row of the |
| 101278 | +** first containing loop. The P2 of this opcode will be the location to |
| 101279 | +** jump to if no rows of cursor P1 match the key, and that will be the |
| 101280 | +** continuation address of the first outer loop that contributes to the |
| 101281 | +** key. The P2 of this opcode might be greater than the P2 of the |
| 101282 | +** subsequent IdxLE if the first outer loop that influences the key is |
| 101283 | +** outer to the immediately next outer loop. |
| 101206 | 101284 | ** |
| 101207 | 101285 | ** See also: Found, NotFound, SeekGt, SeekGe, SeekLt |
| 101208 | 101286 | */ |
| 101209 | 101287 | case OP_SeekLT: /* jump0, in3, group, ncycle */ |
| 101210 | 101288 | case OP_SeekLE: /* jump0, in3, group, ncycle */ |
| | @@ -101310,11 +101388,13 @@ |
| 101310 | 101388 | assert( pOp->opcode==OP_SeekGE || pOp->opcode==OP_SeekLE ); |
| 101311 | 101389 | assert( pOp[1].opcode==OP_IdxLT || pOp[1].opcode==OP_IdxGT ); |
| 101312 | 101390 | assert( pOp->opcode==OP_SeekGE || pOp[1].opcode==OP_IdxLT ); |
| 101313 | 101391 | assert( pOp->opcode==OP_SeekLE || pOp[1].opcode==OP_IdxGT ); |
| 101314 | 101392 | assert( pOp[1].p1==pOp[0].p1 ); |
| 101315 | | - assert( pOp[1].p2==pOp[0].p2 ); |
| 101393 | + assert( pOp[1].p2<=pOp[0].p2 ); |
| 101394 | + testcase( pOp->opcode==OP_SeekGE && pOp[1].p2<pOp[0].p2 ); |
| 101395 | + testcase( pOp->opcode==OP_SeekLE && pOp[1].p2<pOp[0].p2 ); |
| 101316 | 101396 | assert( pOp[1].p3==pOp[0].p3 ); |
| 101317 | 101397 | assert( pOp[1].p4.i==pOp[0].p4.i ); |
| 101318 | 101398 | } |
| 101319 | 101399 | |
| 101320 | 101400 | nField = pOp->p4.i; |
| | @@ -113193,15 +113273,14 @@ |
| 113193 | 113273 | char aff; |
| 113194 | 113274 | assert( pExpr->op==TK_EQ || pExpr->op==TK_IN || pExpr->op==TK_LT || |
| 113195 | 113275 | pExpr->op==TK_GT || pExpr->op==TK_GE || pExpr->op==TK_LE || |
| 113196 | 113276 | pExpr->op==TK_NE || pExpr->op==TK_IS || pExpr->op==TK_ISNOT ); |
| 113197 | 113277 | assert( pExpr->pLeft ); |
| 113278 | + assert( !ExprUseXSelect(pExpr) ); |
| 113198 | 113279 | aff = sqlite3ExprAffinity(pExpr->pLeft); |
| 113199 | 113280 | if( pExpr->pRight ){ |
| 113200 | 113281 | aff = sqlite3CompareAffinity(pExpr->pRight, aff); |
| 113201 | | - }else if( ExprUseXSelect(pExpr) ){ |
| 113202 | | - aff = sqlite3CompareAffinity(pExpr->x.pSelect->pEList->a[0].pExpr, aff); |
| 113203 | 113282 | }else if( aff==0 ){ |
| 113204 | 113283 | aff = SQLITE_AFF_BLOB; |
| 113205 | 113284 | } |
| 113206 | 113285 | return aff; |
| 113207 | 113286 | } |
| | @@ -115560,11 +115639,11 @@ |
| 115560 | 115639 | ** table other than iCur. |
| 115561 | 115640 | ** |
| 115562 | 115641 | ** Consider uncorrelated subqueries to be constants if the bAllowSubq |
| 115563 | 115642 | ** parameter is true. |
| 115564 | 115643 | */ |
| 115565 | | -static int sqlite3ExprIsTableConstant(Expr *p, int iCur, int bAllowSubq){ |
| 115644 | +SQLITE_PRIVATE int sqlite3ExprIsTableConstant(Expr *p, int iCur, int bAllowSubq){ |
| 115566 | 115645 | Walker w; |
| 115567 | 115646 | w.eCode = 3; |
| 115568 | 115647 | w.pParse = 0; |
| 115569 | 115648 | w.xExprCallback = exprNodeIsConstant; |
| 115570 | 115649 | if( bAllowSubq ){ |
| | @@ -115740,11 +115819,10 @@ |
| 115740 | 115819 | SQLITE_PRIVATE int sqlite3ExprIsConstantOrFunction(Expr *p, u8 isInit){ |
| 115741 | 115820 | assert( isInit==0 || isInit==1 ); |
| 115742 | 115821 | return exprIsConst(0, p, 4+isInit); |
| 115743 | 115822 | } |
| 115744 | 115823 | |
| 115745 | | -#ifdef SQLITE_ENABLE_CURSOR_HINTS |
| 115746 | 115824 | /* |
| 115747 | 115825 | ** Walk an expression tree. Return 1 if the expression contains a |
| 115748 | 115826 | ** subquery of some kind. Return 0 if there are no subqueries. |
| 115749 | 115827 | */ |
| 115750 | 115828 | SQLITE_PRIVATE int sqlite3ExprContainsSubquery(Expr *p){ |
| | @@ -115756,11 +115834,10 @@ |
| 115756 | 115834 | w.xSelectCallback2 = sqlite3SelectWalkAssert2; |
| 115757 | 115835 | #endif |
| 115758 | 115836 | sqlite3WalkExpr(&w, p); |
| 115759 | 115837 | return w.eCode==0; |
| 115760 | 115838 | } |
| 115761 | | -#endif |
| 115762 | 115839 | |
| 115763 | 115840 | /* |
| 115764 | 115841 | ** If the expression p codes a constant integer between 0 and 0x7fffffff, |
| 115765 | 115842 | ** then return 1 and put the value of the integer in *pValue. If the |
| 115766 | 115843 | ** expression is not an integer or if it is an integer that is out side |
| | @@ -115775,14 +115852,11 @@ |
| 115775 | 115852 | ** |
| 115776 | 115853 | ** If pParse is not NULL and expression p is a variable, then the variable |
| 115777 | 115854 | ** is marked so as to cause the statement to be reprepared each time a new |
| 115778 | 115855 | ** value is bound to it. Except, if parameter bRSI is true, then the statement |
| 115779 | 115856 | ** will only be reprepared if the rebind changes the value to or from a |
| 115780 | | -** "small integer" (either 0 or 1). Note that if p is a variable then |
| 115781 | | -** reprepare is always enabled for that variable, regardless of its current |
| 115782 | | -** binding. The RSI is only enabled if the current binding is a small |
| 115783 | | -** integer. "RSI" stands for "Reprepare Small Integers". |
| 115857 | +** "small integer" (either 0 or 1). |
| 115784 | 115858 | */ |
| 115785 | 115859 | SQLITE_PRIVATE int sqlite3ExprIsInteger(const Expr *p, int *pValue, Parse *pParse, int bRSI){ |
| 115786 | 115860 | int iSign = 1; /* Either +1 or -1. */ |
| 115787 | 115861 | while( 1/*exit-by-break*/ ){ |
| 115788 | 115862 | if( NEVER(p==0) ) return 0; |
| | @@ -115801,11 +115875,10 @@ |
| 115801 | 115875 | pParse = 0; |
| 115802 | 115876 | continue; |
| 115803 | 115877 | } |
| 115804 | 115878 | if( p->op==TK_VARIABLE && pParse!=0 ){ |
| 115805 | 115879 | sqlite3_value *pVal; /* The variable */ |
| 115806 | | - int isSmall = 0; /* Only reprepare if change to/from small integer */ |
| 115807 | 115880 | int rc = 0; /* 1 if successful, 0 if failed */ |
| 115808 | 115881 | assert( iSign==1 ); |
| 115809 | 115882 | if( NEVER(pParse->pVdbe==0) ) break; |
| 115810 | 115883 | if( (pParse->db->flags & SQLITE_EnableQPSG)!=0 ) break; |
| 115811 | 115884 | pVal = sqlite3VdbeGetBoundValue(pParse->pReprepare, p->iColumn, |
| | @@ -115815,18 +115888,15 @@ |
| 115815 | 115888 | if( sqlite3_value_type(pVal)==SQLITE_INTEGER |
| 115816 | 115889 | && (vv = sqlite3_value_int64(pVal))>=0 |
| 115817 | 115890 | && vv<=0x7fffffff |
| 115818 | 115891 | ){ |
| 115819 | 115892 | *pValue = (int)vv; |
| 115820 | | - if( bRSI ){ |
| 115821 | | - isSmall = vv<=1; |
| 115822 | | - } |
| 115823 | 115893 | rc = 1; |
| 115824 | 115894 | } |
| 115825 | 115895 | sqlite3ValueFree(pVal); |
| 115826 | 115896 | } |
| 115827 | | - sqlite3VdbeReprepareOnBind(pParse->pVdbe, p->iColumn, isSmall); |
| 115897 | + sqlite3VdbeReprepareOnBind(pParse->pVdbe, p->iColumn, bRSI); |
| 115828 | 115898 | return rc; |
| 115829 | 115899 | } |
| 115830 | 115900 | break; |
| 115831 | 115901 | } |
| 115832 | 115902 | return 0; |
| | @@ -116862,10 +116932,16 @@ |
| 116862 | 116932 | ExprSetVVAProperty(pExpr, EP_NoReduce); |
| 116863 | 116933 | if( addrOnce ){ |
| 116864 | 116934 | sqlite3VdbeJumpHere(v, addrOnce); |
| 116865 | 116935 | } |
| 116866 | 116936 | sqlite3VdbeScanStatusRange(v, addrExplain, addrExplain, -1); |
| 116937 | + |
| 116938 | + if( dest.eDest==SRT_Mem |
| 116939 | + && sqlite3ExprCanReturnSubtype(pParse, pSel->pEList->a[0].pExpr) |
| 116940 | + ){ |
| 116941 | + sqlite3VdbeAddOp1(v, OP_ClrSubtype, rReg); |
| 116942 | + } |
| 116867 | 116943 | |
| 116868 | 116944 | /* Subroutine return */ |
| 116869 | 116945 | assert( ExprUseYSub(pExpr) ); |
| 116870 | 116946 | assert( sqlite3VdbeGetOp(v,pExpr->y.sub.iAddr-1)->opcode==OP_BeginSubrtn |
| 116871 | 116947 | || pParse->nErr ); |
| | @@ -117082,11 +117158,10 @@ |
| 117082 | 117158 | rLhs = sqlite3GetTempRange(pParse, nVector); |
| 117083 | 117159 | for(i=0; i<nVector; i++){ |
| 117084 | 117160 | testcase( aiMap[i]!=i ); |
| 117085 | 117161 | sqlite3VdbeAddOp3(v, OP_Copy, rLhsOrig+i, rLhs+aiMap[i], 0); |
| 117086 | 117162 | } |
| 117087 | | - sqlite3ReleaseTempReg(pParse, rLhsOrig); |
| 117088 | 117163 | } |
| 117089 | 117164 | } |
| 117090 | 117165 | |
| 117091 | 117166 | |
| 117092 | 117167 | /* Step 2: Check to see if the LHS contains any NULL columns. If the |
| | @@ -117618,11 +117693,11 @@ |
| 117618 | 117693 | ** pExpr is able to return a subtype, set pWalker->eCode and abort |
| 117619 | 117694 | ** the search. If pExpr can never return a subtype, prune search. |
| 117620 | 117695 | ** |
| 117621 | 117696 | ** The only expressions that can return a subtype are: |
| 117622 | 117697 | ** |
| 117623 | | -** 1. A function |
| 117698 | +** 1. A function, including an aggregate function |
| 117624 | 117699 | ** 2. The no-op "+" operator |
| 117625 | 117700 | ** 3. A CASE...END expression |
| 117626 | 117701 | ** 4. A CAST() expression |
| 117627 | 117702 | ** 5. A "expr COLLATE colseq" expression. |
| 117628 | 117703 | ** |
| | @@ -117643,18 +117718,23 @@ |
| 117643 | 117718 | if( pExpr->op==TK_CASE || pExpr->op==TK_UPLUS |
| 117644 | 117719 | || pExpr->op==TK_COLLATE || pExpr->op==TK_CAST |
| 117645 | 117720 | ){ |
| 117646 | 117721 | return WRC_Continue; |
| 117647 | 117722 | } |
| 117648 | | - if( pExpr->op!=TK_FUNCTION ){ |
| 117723 | + if( pExpr->op!=TK_FUNCTION && pExpr->op!=TK_AGG_FUNCTION ){ |
| 117649 | 117724 | return WRC_Prune; |
| 117650 | 117725 | } |
| 117651 | 117726 | assert( ExprUseXList(pExpr) ); |
| 117652 | 117727 | db = pWalker->pParse->db; |
| 117653 | 117728 | n = pExpr->x.pList ? pExpr->x.pList->nExpr : 0; |
| 117654 | 117729 | pDef = sqlite3FindFunction(db, pExpr->u.zToken, n, ENC(db), 0); |
| 117655 | | - if( NEVER(pDef==0) || (pDef->funcFlags & SQLITE_RESULT_SUBTYPE)!=0 ){ |
| 117730 | +#ifdef SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION |
| 117731 | + if( pDef==0 ) return WRC_Continue; |
| 117732 | +#else |
| 117733 | + assert( pDef!=0 ); |
| 117734 | +#endif |
| 117735 | + if( (pDef->funcFlags & SQLITE_RESULT_SUBTYPE)!=0 ){ |
| 117656 | 117736 | pWalker->eCode = 1; |
| 117657 | 117737 | return WRC_Abort; |
| 117658 | 117738 | } |
| 117659 | 117739 | return WRC_Continue; |
| 117660 | 117740 | } |
| | @@ -117720,14 +117800,20 @@ |
| 117720 | 117800 | continue; |
| 117721 | 117801 | } |
| 117722 | 117802 | |
| 117723 | 117803 | v = pParse->pVdbe; |
| 117724 | 117804 | assert( v!=0 ); |
| 117725 | | - if( p->bMaybeNullRow ){ |
| 117726 | | - /* If the index is on a NULL row due to an outer join, then we |
| 117727 | | - ** cannot extract the value from the index. The value must be |
| 117728 | | - ** computed using the original expression. */ |
| 117805 | + if( p->bMaybeNullRow || sqlite3ExprIsConstant(pParse, pExpr) ){ |
| 117806 | + /* The value of pExpr should be computed from the original expression, |
| 117807 | + ** not from the index, if either: |
| 117808 | + ** |
| 117809 | + ** 1. The index might be on a NULL row due to an outer join. |
| 117810 | + ** |
| 117811 | + ** 2. The expression is a constant. This prevents an attempt to |
| 117812 | + ** use an index value outside of the loop that positions the |
| 117813 | + ** index. (Bug 2026-10-11T19:26:40Z). |
| 117814 | + */ |
| 117729 | 117815 | int addr = sqlite3VdbeCurrentAddr(v); |
| 117730 | 117816 | sqlite3VdbeAddOp3(v, OP_IfNullRow, p->iIdxCur, addr+3, target); |
| 117731 | 117817 | VdbeCoverage(v); |
| 117732 | 117818 | sqlite3VdbeAddOp3(v, OP_Column, p->iIdxCur, p->iIdxCol, target); |
| 117733 | 117819 | VdbeComment((v, "%s expr-column %d", p->zIdxName, p->iIdxCol)); |
| | @@ -120450,11 +120536,11 @@ |
| 120450 | 120536 | assert( pOBList->nExpr>0 ); |
| 120451 | 120537 | assert( pItem->bOBUnique==0 ); |
| 120452 | 120538 | if( pOBList->nExpr==1 |
| 120453 | 120539 | && nArg==1 |
| 120454 | 120540 | && sqlite3ExprCompare(0,pOBList->a[0].pExpr, |
| 120455 | | - pExpr->x.pList->a[0].pExpr,0)==0 |
| 120541 | + pExpr->x.pList->a[0].pExpr,-1)==0 |
| 120456 | 120542 | ){ |
| 120457 | 120543 | pItem->bOBPayload = 0; |
| 120458 | 120544 | pItem->bOBUnique = ExprHasProperty(pExpr, EP_Distinct); |
| 120459 | 120545 | }else{ |
| 120460 | 120546 | pItem->bOBPayload = 1; |
| | @@ -120538,10 +120624,17 @@ |
| 120538 | 120624 | ** Deallocate a register, making available for reuse for some other |
| 120539 | 120625 | ** purpose. |
| 120540 | 120626 | */ |
| 120541 | 120627 | SQLITE_PRIVATE void sqlite3ReleaseTempReg(Parse *pParse, int iReg){ |
| 120542 | 120628 | if( iReg ){ |
| 120629 | +#ifdef SQLITE_DEBUG |
| 120630 | + /* Verify that iReg is not already on the unused register list */ |
| 120631 | + int kk; |
| 120632 | + for(kk=0; kk<pParse->nTempReg; kk++){ |
| 120633 | + assert( pParse->aTempReg[kk]!=iReg ); |
| 120634 | + } |
| 120635 | +#endif |
| 120543 | 120636 | sqlite3VdbeReleaseRegisters(pParse, iReg, 1, 0, 0); |
| 120544 | 120637 | if( pParse->nTempReg<ArraySize(pParse->aTempReg) ){ |
| 120545 | 120638 | pParse->aTempReg[pParse->nTempReg++] = iReg; |
| 120546 | 120639 | } |
| 120547 | 120640 | } |
| | @@ -127356,10 +127449,11 @@ |
| 127356 | 127449 | |
| 127357 | 127450 | if( db->nSchemaLock==0 ){ |
| 127358 | 127451 | for(i=0; i<db->nDb; i++){ |
| 127359 | 127452 | if( DbHasProperty(db, i, DB_ResetWanted) ){ |
| 127360 | 127453 | sqlite3SchemaClear(db->aDb[i].pSchema); |
| 127454 | + db->mDbFlags &= ~DBFLAG_SchemaKnownOk; |
| 127361 | 127455 | } |
| 127362 | 127456 | } |
| 127363 | 127457 | } |
| 127364 | 127458 | } |
| 127365 | 127459 | |
| | @@ -134158,19 +134252,22 @@ |
| 134158 | 134252 | } |
| 134159 | 134253 | nCol = (prefixOnly && pIdx->uniqNotNull) ? pIdx->nKeyCol : pIdx->nColumn; |
| 134160 | 134254 | regBase = sqlite3GetTempRange(pParse, nCol); |
| 134161 | 134255 | if( pPrior && (regBase!=regPrior || pPrior->pPartIdxWhere) ) pPrior = 0; |
| 134162 | 134256 | for(j=0; j<nCol; j++){ |
| 134257 | + int iTabCol; |
| 134163 | 134258 | if( pPrior |
| 134164 | 134259 | && pPrior->aiColumn[j]==pIdx->aiColumn[j] |
| 134165 | 134260 | && pPrior->aiColumn[j]!=XN_EXPR |
| 134166 | 134261 | ){ |
| 134167 | 134262 | /* This column was already computed by the previous index */ |
| 134168 | 134263 | continue; |
| 134169 | 134264 | } |
| 134170 | 134265 | sqlite3ExprCodeLoadIndexColumn(pParse, pIdx, iDataCur, j, regBase+j); |
| 134171 | | - if( pIdx->aiColumn[j]>=0 ){ |
| 134266 | + if( (iTabCol = pIdx->aiColumn[j])>=0 |
| 134267 | + && (pIdx->pTable->aCol[iTabCol].colFlags & COLFLAG_VIRTUAL)==0 |
| 134268 | + ){ |
| 134172 | 134269 | /* If the column affinity is REAL but the number is an integer, then it |
| 134173 | 134270 | ** might be stored in the table as an integer (using a compact |
| 134174 | 134271 | ** representation) then converted to REAL by an OP_RealAffinity opcode. |
| 134175 | 134272 | ** But we are getting ready to store this value back into an index, where |
| 134176 | 134273 | ** it should be converted by to INTEGER again. So omit the |
| | @@ -134530,10 +134627,18 @@ |
| 134530 | 134627 | str.printfFlags = SQLITE_PRINTF_SQLFUNC; |
| 134531 | 134628 | sqlite3_str_appendf(&str, zFormat, &x); |
| 134532 | 134629 | sqlite3_result_str(context, &str, SQLITE_XFER); |
| 134533 | 134630 | } |
| 134534 | 134631 | } |
| 134632 | + |
| 134633 | +/* Return true if any of the eight bytes in word is NUL or non-ASCII. */ |
| 134634 | +static SQLITE_INLINE int containsNulOrNonAscii(u64 word){ |
| 134635 | + const u64 byteOnes = UINT64_C(0x0101010101010101); |
| 134636 | + const u64 byteHighBits = UINT64_C(0x8080808080808080); |
| 134637 | + /* NUL causes a borrow into a high bit; non-ASCII already has one set. */ |
| 134638 | + return ((word | (word - byteOnes)) & byteHighBits)!=0; |
| 134639 | +} |
| 134535 | 134640 | |
| 134536 | 134641 | /* |
| 134537 | 134642 | ** Implementation of the substr() function. |
| 134538 | 134643 | ** |
| 134539 | 134644 | ** substr(x,p1,p2) returns p2 characters of x[] beginning with p1. |
| | @@ -134614,10 +134719,24 @@ |
| 134614 | 134719 | } |
| 134615 | 134720 | p1 -= p2; |
| 134616 | 134721 | } |
| 134617 | 134722 | assert( p1>=0 && p2>=0 ); |
| 134618 | 134723 | if( p0type!=SQLITE_BLOB ){ |
| 134724 | + if( p1>=8 ){ |
| 134725 | + /* Skip 8 characters at a time while all 8 bytes are in 0x01..0x7f */ |
| 134726 | + const unsigned char *zEnd = z + sqlite3_value_bytes(argv[0]); |
| 134727 | + while( p1>=8 && zEnd-z>=8 ){ |
| 134728 | + u64 word; |
| 134729 | + memcpy(&word, z, sizeof(word)); |
| 134730 | + /* Handle NUL and UTF-8 with the scalar loop below. */ |
| 134731 | + if( containsNulOrNonAscii(word) ){ |
| 134732 | + break; |
| 134733 | + } |
| 134734 | + z += 8; |
| 134735 | + p1 -= 8; |
| 134736 | + } |
| 134737 | + } |
| 134619 | 134738 | for( ; p1>0; p1--){ |
| 134620 | 134739 | /* vvvvvv---- See tag-20260418-01 */ |
| 134621 | 134740 | if( (u8)(z[0]-1)<(0x80-1) ){ |
| 134622 | 134741 | z++; |
| 134623 | 134742 | }else if( z[0]==0 ){ |
| | @@ -134991,22 +135110,33 @@ |
| 134991 | 135110 | ** c or cx. |
| 134992 | 135111 | */ |
| 134993 | 135112 | if( c<0x80 ){ |
| 134994 | 135113 | char zStop[3]; |
| 134995 | 135114 | int bMatch; |
| 135115 | + /* If the next pattern character is an ordinary ASCII character, |
| 135116 | + ** then a candidate position can only match if the next input |
| 135117 | + ** character is nx or ny. Check that inline, to avoid most of the |
| 135118 | + ** recursive calls. nx==0 disables this check. */ |
| 135119 | + u8 nx = zPattern[0], ny = nx; |
| 135120 | + if( nx>=0x80 || nx==matchAll || nx==matchOne || nx==matchOther ){ |
| 135121 | + nx = 0; |
| 135122 | + } |
| 134996 | 135123 | if( noCase ){ |
| 134997 | 135124 | zStop[0] = sqlite3Toupper(c); |
| 134998 | 135125 | zStop[1] = sqlite3Tolower(c); |
| 134999 | 135126 | zStop[2] = 0; |
| 135127 | + nx = sqlite3Toupper(nx); |
| 135128 | + ny = sqlite3Tolower(ny); |
| 135000 | 135129 | }else{ |
| 135001 | 135130 | zStop[0] = c; |
| 135002 | 135131 | zStop[1] = 0; |
| 135003 | 135132 | } |
| 135004 | 135133 | while(1){ |
| 135005 | 135134 | zString += strcspn((const char*)zString, zStop); |
| 135006 | 135135 | if( zString[0]==0 ) break; |
| 135007 | 135136 | zString++; |
| 135137 | + if( nx && zString[0]!=nx && zString[0]!=ny ) continue; |
| 135008 | 135138 | bMatch = patternCompare(zPattern,zString,pInfo,matchOther); |
| 135009 | 135139 | if( bMatch!=SQLITE_NOMATCH ) return bMatch; |
| 135010 | 135140 | } |
| 135011 | 135141 | }else{ |
| 135012 | 135142 | int bMatch; |
| | @@ -135280,18 +135410,24 @@ |
| 135280 | 135410 | static void compileoptiongetFunc( |
| 135281 | 135411 | sqlite3_context *context, |
| 135282 | 135412 | int argc, |
| 135283 | 135413 | sqlite3_value **argv |
| 135284 | 135414 | ){ |
| 135285 | | - int n; |
| 135415 | + i64 n; |
| 135416 | + const char *zRes; |
| 135286 | 135417 | assert( argc==1 ); |
| 135287 | 135418 | UNUSED_PARAMETER(argc); |
| 135288 | 135419 | /* IMP: R-04922-24076 The sqlite_compileoption_get() SQL function |
| 135289 | 135420 | ** is a wrapper around the sqlite3_compileoption_get() C/C++ function. |
| 135290 | 135421 | */ |
| 135291 | | - n = sqlite3_value_int(argv[0]); |
| 135292 | | - sqlite3_result_text(context, sqlite3_compileoption_get(n), -1, SQLITE_STATIC); |
| 135422 | + n = sqlite3_value_int64(argv[0]); |
| 135423 | + /* Use a negative lower bound to assist testing of the |
| 135424 | + ** sqlite3_compileoption_get() C-language interface and its handling |
| 135425 | + ** of negative inputs. |
| 135426 | + ** vvvvv */ |
| 135427 | + zRes = (n>=(-10) && n<10000) ? sqlite3_compileoption_get((int)n) : 0; |
| 135428 | + sqlite3_result_text(context, zRes, -1, SQLITE_STATIC); |
| 135293 | 135429 | } |
| 135294 | 135430 | #endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */ |
| 135295 | 135431 | |
| 135296 | 135432 | /* Array for converting from half-bytes (nybbles) into ASCII hex |
| 135297 | 135433 | ** digits. */ |
| | @@ -153606,11 +153742,13 @@ |
| 153606 | 153742 | static int renumberCursorsCb(Walker *pWalker, Expr *pExpr){ |
| 153607 | 153743 | int op = pExpr->op; |
| 153608 | 153744 | if( op==TK_COLUMN || op==TK_IF_NULL_ROW ){ |
| 153609 | 153745 | renumberCursorDoMapping(pWalker, &pExpr->iTable); |
| 153610 | 153746 | } |
| 153611 | | - if( ExprHasProperty(pExpr, EP_OuterON) ){ |
| 153747 | + if( ExprHasProperty(pExpr, (EP_OuterON|EP_InnerON)) ){ |
| 153748 | + testcase( ExprHasProperty(pExpr, EP_OuterON) ); |
| 153749 | + testcase( ExprHasProperty(pExpr, EP_InnerON) ); |
| 153612 | 153750 | renumberCursorDoMapping(pWalker, &pExpr->w.iJoin); |
| 153613 | 153751 | } |
| 153614 | 153752 | return WRC_Continue; |
| 153615 | 153753 | } |
| 153616 | 153754 | |
| | @@ -154486,11 +154624,11 @@ |
| 154486 | 154624 | /* |
| 154487 | 154625 | ** The WHERE-clause constant propagation optimization. |
| 154488 | 154626 | ** |
| 154489 | 154627 | ** If the WHERE clause contains terms of the form COLUMN=CONSTANT or |
| 154490 | 154628 | ** CONSTANT=COLUMN that are top-level AND-connected terms that are not |
| 154491 | | -** part of a ON clause from a LEFT JOIN, then throughout the query |
| 154629 | +** part of a ON clause from an OUTER JOIN, then throughout the query |
| 154492 | 154630 | ** replace all other occurrences of COLUMN with CONSTANT. |
| 154493 | 154631 | ** |
| 154494 | 154632 | ** For example, the query: |
| 154495 | 154633 | ** |
| 154496 | 154634 | ** SELECT * FROM t1, t2, t3 WHERE t1.a=39 AND t2.b=t1.a AND t3.c=t2.b |
| | @@ -164036,10 +164174,11 @@ |
| 164036 | 164174 | int addrBrk; /* Jump here to break out of the loop */ |
| 164037 | 164175 | int addrHalt; /* Abort the query due to empty table or similar */ |
| 164038 | 164176 | int addrNxt; /* Jump here to start the next IN combination */ |
| 164039 | 164177 | int addrSkip; /* Jump here for next iteration of skip-scan */ |
| 164040 | 164178 | int addrCont; /* Jump here to continue with the next loop cycle */ |
| 164179 | + int addrDeleteCont; /* Delete auto-index entry then same as addrCont */ |
| 164041 | 164180 | int addrFirst; /* First instruction of interior of the loop */ |
| 164042 | 164181 | int addrBody; /* Beginning of the body of this loop */ |
| 164043 | 164182 | int regBignull; /* big-null flag reg. True if a NULL-scan is needed */ |
| 164044 | 164183 | int addrBignull; /* Jump here for next part of big-null scan */ |
| 164045 | 164184 | #ifndef SQLITE_LIKE_DOESNT_MATCH_BLOBS |
| | @@ -166119,10 +166258,131 @@ |
| 166119 | 166258 | } |
| 166120 | 166259 | } |
| 166121 | 166260 | } |
| 166122 | 166261 | return 1; |
| 166123 | 166262 | } |
| 166263 | + |
| 166264 | +/* |
| 166265 | +** Find the best address for an inner loop to jump to if its join |
| 166266 | +** constraint matches no rows. |
| 166267 | +** |
| 166268 | +** This is an optimization. The default behavior is to continue with |
| 166269 | +** the inner-most of the outer loops. But if the join constraint is not |
| 166270 | +** influenced by the inner-most outer loop, we might as well skip that |
| 166271 | +** loop too, and continue with the second inner-most outer loop. And |
| 166272 | +** so forth through subsequent outer loops. |
| 166273 | +** |
| 166274 | +** Return 0 to use the default behavior (continue with the inner-most |
| 166275 | +** outer loop. Or return an optimized address to jump to instead if |
| 166276 | +** we can do better. |
| 166277 | +** |
| 166278 | +** Conditions for returning non-zero: |
| 166279 | +** |
| 166280 | +** 1. The SQLITE_JoinMiss optimization must be enabled. |
| 166281 | +** |
| 166282 | +** 2. The iLevel loop must have at least two outer loops, otherwise |
| 166283 | +** this optimization is pointless. |
| 166284 | +** |
| 166285 | +** 3. We are not attempting to do one-pass |
| 166286 | +** |
| 166287 | +** 4. The join constraints may not contain subqueries |
| 166288 | +** |
| 166289 | +** If the inner-most outer loop that influences iLevel is also the |
| 166290 | +** only loop that influences iLevel, and if that loop uses an |
| 166291 | +** automatic index, then also arrange to delete the currently used |
| 166292 | +** entry from that automatic index, since we know that it can never |
| 166293 | +** be successful. |
| 166294 | +** |
| 166295 | +** This optimization inspired by the paper: "TreeTracker Join: Simple, |
| 166296 | +** Optimal, Fast" by Hu, Wang, and Miranker, 2025. |
| 166297 | +*/ |
| 166298 | +static int findNoMatchContinuation( |
| 166299 | + WhereInfo *pWInfo, /* WHERE clause */ |
| 166300 | + int iLevel /* Which loop we are talking about */ |
| 166301 | +){ |
| 166302 | + WhereLoop *pLoop; /* Description of this loop */ |
| 166303 | + WhereLevel *pParent; /* Controlling parent loop */ |
| 166304 | + SrcList *pTabList; /* Complete FROM clause */ |
| 166305 | + Bitmask mKey; /* Mask of dependent tables */ |
| 166306 | + int iParent; /* Inner-most loop affecting the key to iLevel */ |
| 166307 | + int i; /* Loop counter */ |
| 166308 | + |
| 166309 | + if( iLevel<2 ){ |
| 166310 | + /* If there are less than two outer loops, this optimization is no help */ |
| 166311 | + return 0; |
| 166312 | + } |
| 166313 | + |
| 166314 | + /* The OP_SeekGE and OP_SeekLE opcodes only work right for this |
| 166315 | + ** optimization on a pure equality constraint, so skip the optimization |
| 166316 | + ** for anything else. |
| 166317 | + */ |
| 166318 | + pLoop = pWInfo->a[iLevel].pWLoop; |
| 166319 | + if( (pLoop->wsFlags & WHERE_CONSTRAINT)!=WHERE_COLUMN_EQ ) return 0; |
| 166320 | + if( pLoop->wsFlags & WHERE_SKIPSCAN ) return 0; |
| 166321 | + if( pLoop->wsFlags & WHERE_BIGNULL_SORT ) return 0; |
| 166322 | + assert( (pLoop->wsFlags & (WHERE_VIRTUALTABLE|WHERE_MULTI_OR))==0 ); |
| 166323 | + assert( pLoop->u.btree.nEq>0 ); |
| 166324 | + |
| 166325 | + /* Find a mask of all outer tables that influence the key. At the same |
| 166326 | + ** time, check to see if any keys values are computed from subqueries and |
| 166327 | + ** fail out (return 0) if there are any. */ |
| 166328 | + mKey = 0; |
| 166329 | + for(i=0; i<pLoop->nLTerm; i++){ |
| 166330 | + if( sqlite3ExprContainsSubquery(pLoop->aLTerm[i]->pExpr) ){ |
| 166331 | + return 0; |
| 166332 | + } |
| 166333 | + mKey |= pLoop->aLTerm[i]->prereqRight; |
| 166334 | + } |
| 166335 | + |
| 166336 | + /* Look back through outer loops. Find the inner-most outer loop |
| 166337 | + ** that influences the key. Make iParent be the index of that inner-most |
| 166338 | + ** outer loop. |
| 166339 | + */ |
| 166340 | + pTabList = pWInfo->pTabList; |
| 166341 | + iParent = iLevel-1; |
| 166342 | + while( iParent>0 && (pWInfo->a[iParent].pWLoop->maskSelf & mKey)==0 ){ |
| 166343 | + iParent--; |
| 166344 | + } |
| 166345 | + assert( iParent>=0 && iParent<=iLevel ); |
| 166346 | + |
| 166347 | + /* Everything needs to be an INNER join. Fail if there are any |
| 166348 | + ** OUTER joins in between iParent and iLevel. */ |
| 166349 | + for(i=iParent; i<=iLevel; i++){ |
| 166350 | + if( pTabList->a[pWInfo->a[i].iFrom].fg.jointype & JT_OUTER ) return 0; |
| 166351 | + } |
| 166352 | + |
| 166353 | + /* If we reach this point, that means the conditions of the optimization |
| 166354 | + ** have been met. Even so, disallow the optimization if it is disabled. |
| 166355 | + */ |
| 166356 | + if( OptimizationDisabled(pWInfo->pParse->db, SQLITE_JoinMiss) ){ |
| 166357 | + return 0; |
| 166358 | + } |
| 166359 | + |
| 166360 | + /* If the inner-most outer loop that influences the key for iLevel |
| 166361 | + ** is controlled by an automatic index and if the automatic index is |
| 166362 | + ** the only outer loop that influences the key, then arrange to delete |
| 166363 | + ** the automatic index entry if there is no match on the key. |
| 166364 | + */ |
| 166365 | + pParent = &pWInfo->a[iParent]; |
| 166366 | + if( (pParent->pWLoop->wsFlags & WHERE_AUTO_INDEX)!=0 |
| 166367 | + && (mKey & (mKey-1))==0 |
| 166368 | + ){ |
| 166369 | + for(i=0; i<pLoop->nLTerm; i++){ |
| 166370 | + Expr *pX = pLoop->aLTerm[i]->pExpr; |
| 166371 | + if( !sqlite3ExprIsTableConstant(pX->pRight,pParent->iTabCur,0) ) break; |
| 166372 | + } |
| 166373 | + if( i==pLoop->nLTerm ){ |
| 166374 | + if( pParent->addrDeleteCont==0 ){ |
| 166375 | + pParent->addrDeleteCont = sqlite3VdbeMakeLabel(pWInfo->pParse); |
| 166376 | + } |
| 166377 | + return pParent->addrDeleteCont; |
| 166378 | + } |
| 166379 | + } |
| 166380 | + |
| 166381 | + testcase( iParent<iLevel-1 ); |
| 166382 | + return pParent->addrCont; |
| 166383 | +} |
| 166124 | 166384 | |
| 166125 | 166385 | /* |
| 166126 | 166386 | ** Generate code for the start of the iLevel-th loop in the WHERE clause |
| 166127 | 166387 | ** implementation described by pWInfo. |
| 166128 | 166388 | */ |
| | @@ -166138,15 +166398,16 @@ |
| 166138 | 166398 | int iCur; /* The VDBE cursor for the table */ |
| 166139 | 166399 | int addrNxt; /* Where to jump to continue with the next IN case */ |
| 166140 | 166400 | int bRev; /* True if we need to scan in reverse order */ |
| 166141 | 166401 | WhereLoop *pLoop; /* The WhereLoop object being coded */ |
| 166142 | 166402 | WhereClause *pWC; /* Decomposition of the entire WHERE clause */ |
| 166143 | | - WhereTerm *pTerm; /* A WHERE clause term */ |
| 166144 | | - sqlite3 *db; /* Database connection */ |
| 166145 | | - SrcItem *pTabItem; /* FROM clause term being coded */ |
| 166146 | | - int addrBrk; /* Jump here to break out of the loop */ |
| 166147 | | - int addrCont; /* Jump here to continue with next cycle */ |
| 166403 | + WhereTerm *pTerm; /* A WHERE clause term */ |
| 166404 | + sqlite3 *db; /* Database connection */ |
| 166405 | + SrcItem *pTabItem; /* FROM clause term being coded */ |
| 166406 | + int addrBrk; /* Jump here to break out of the loop */ |
| 166407 | + int addrCont; /* Jump here to continue with next cycle */ |
| 166408 | + int addrMiss; /* addrCont enhanced for no-matching rows */ |
| 166148 | 166409 | int iRowidReg = 0; /* Rowid is stored in this register, if not zero */ |
| 166149 | 166410 | int iReleaseReg = 0; /* Temp register to free before returning */ |
| 166150 | 166411 | Index *pIdx = 0; /* Index used by loop (if any) */ |
| 166151 | 166412 | int iLoop; /* Iteration of constraint generator loop */ |
| 166152 | 166413 | |
| | @@ -166187,10 +166448,11 @@ |
| 166187 | 166448 | ** there are no IN operators in the constraints, the "addrNxt" label |
| 166188 | 166449 | ** is the same as "addrBrk". |
| 166189 | 166450 | */ |
| 166190 | 166451 | addrBrk = pLevel->addrNxt = pLevel->addrBrk; |
| 166191 | 166452 | addrCont = pLevel->addrCont = sqlite3VdbeMakeLabel(pParse); |
| 166453 | + addrMiss = findNoMatchContinuation(pWInfo, iLevel); |
| 166192 | 166454 | |
| 166193 | 166455 | /* If this is the right table of a LEFT OUTER JOIN, allocate and |
| 166194 | 166456 | ** initialize a memory cell that records if this table matches any |
| 166195 | 166457 | ** row of the left table of the join. |
| 166196 | 166458 | */ |
| | @@ -166362,19 +166624,20 @@ |
| 166362 | 166624 | testcase( pTerm->wtFlags & TERM_VIRTUAL ); |
| 166363 | 166625 | iReleaseReg = ++pParse->nMem; |
| 166364 | 166626 | iRowidReg = codeEqualityTerm(pParse, pTerm, pLevel, 0, bRev, iReleaseReg); |
| 166365 | 166627 | if( iRowidReg!=iReleaseReg ) sqlite3ReleaseTempReg(pParse, iReleaseReg); |
| 166366 | 166628 | addrNxt = pLevel->addrNxt; |
| 166629 | + if( addrMiss==0 ) addrMiss = addrNxt; |
| 166367 | 166630 | if( pLevel->regFilter ){ |
| 166368 | | - sqlite3VdbeAddOp2(v, OP_MustBeInt, iRowidReg, addrNxt); |
| 166631 | + sqlite3VdbeAddOp2(v, OP_MustBeInt, iRowidReg, addrMiss); |
| 166369 | 166632 | VdbeCoverage(v); |
| 166370 | | - sqlite3VdbeAddOp4Int(v, OP_Filter, pLevel->regFilter, addrNxt, |
| 166633 | + sqlite3VdbeAddOp4Int(v, OP_Filter, pLevel->regFilter, addrMiss, |
| 166371 | 166634 | iRowidReg, 1); |
| 166372 | 166635 | VdbeCoverage(v); |
| 166373 | 166636 | filterPullDown(pParse, pWInfo, iLevel, addrNxt, notReady); |
| 166374 | 166637 | } |
| 166375 | | - sqlite3VdbeAddOp3(v, OP_SeekRowid, iCur, addrNxt, iRowidReg); |
| 166638 | + sqlite3VdbeAddOp3(v, OP_SeekRowid, iCur, addrMiss, iRowidReg); |
| 166376 | 166639 | VdbeCoverage(v); |
| 166377 | 166640 | pLevel->op = OP_Noop; |
| 166378 | 166641 | }else if( (pLoop->wsFlags & WHERE_IPK)!=0 |
| 166379 | 166642 | && (pLoop->wsFlags & WHERE_COLUMN_RANGE)!=0 |
| 166380 | 166643 | ){ |
| | @@ -166573,13 +166836,10 @@ |
| 166573 | 166836 | #ifndef SQLITE_LIKE_DOESNT_MATCH_BLOBS |
| 166574 | 166837 | if( (pRangeEnd->wtFlags & TERM_LIKEOPT)!=0 ){ |
| 166575 | 166838 | assert( pRangeStart!=0 ); /* LIKE opt constraints */ |
| 166576 | 166839 | assert( pRangeStart->wtFlags & TERM_LIKEOPT ); /* occur in pairs */ |
| 166577 | 166840 | pLevel->iLikeRepCntr = (u32)++pParse->nMem; |
| 166578 | | - sqlite3VdbeAddOp2(v, OP_Integer, 1, (int)pLevel->iLikeRepCntr); |
| 166579 | | - VdbeComment((v, "LIKE loop counter")); |
| 166580 | | - pLevel->addrLikeRep = sqlite3VdbeCurrentAddr(v); |
| 166581 | 166841 | /* iLikeRepCntr actually stores 2x the counter register number. The |
| 166582 | 166842 | ** bottom bit indicates whether the search order is ASC or DESC. */ |
| 166583 | 166843 | testcase( bRev ); |
| 166584 | 166844 | testcase( pIdx->aSortOrder[nEq]==SQLITE_SO_DESC ); |
| 166585 | 166845 | assert( (bRev & ~1)==0 ); |
| | @@ -166639,14 +166899,29 @@ |
| 166639 | 166899 | ** starting at regBase. |
| 166640 | 166900 | */ |
| 166641 | 166901 | codeCursorHint(pTabItem, pWInfo, pLevel, pRangeEnd); |
| 166642 | 166902 | regBase = codeAllEqualityTerms(pParse,pLevel,bRev,nExtraReg,&zStartAff); |
| 166643 | 166903 | assert( zStartAff==0 || sqlite3Strlen30(zStartAff)>=nEq ); |
| 166904 | +#ifndef SQLITE_LIKE_DOESNT_MATCH_BLOBS |
| 166905 | + if( pLevel->iLikeRepCntr ){ |
| 166906 | + /* The LIKE optimization loop must be the innermost of any IN(...) |
| 166907 | + ** or skip-scan loops. Otherwise rows may not be visited in index |
| 166908 | + ** order. This means it needs an addrNxt label for the same reason |
| 166909 | + ** IN(...) scans do. */ |
| 166910 | + if( pLevel->addrNxt==pLevel->addrBrk ){ |
| 166911 | + pLevel->addrNxt = sqlite3VdbeMakeLabel(pParse); |
| 166912 | + } |
| 166913 | + sqlite3VdbeAddOp2(v, OP_Integer, 1, (int)(pLevel->iLikeRepCntr>>1)); |
| 166914 | + VdbeComment((v, "LIKE loop counter")); |
| 166915 | + pLevel->addrLikeRep = sqlite3VdbeCurrentAddr(v); |
| 166916 | + } |
| 166917 | +#endif |
| 166644 | 166918 | if( zStartAff && nTop ){ |
| 166645 | 166919 | zEndAff = sqlite3DbStrDup(db, &zStartAff[nEq]); |
| 166646 | 166920 | } |
| 166647 | 166921 | addrNxt = (regBignull ? pLevel->addrBignull : pLevel->addrNxt); |
| 166922 | + if( addrMiss==0 ) addrMiss = addrNxt; |
| 166648 | 166923 | |
| 166649 | 166924 | testcase( pRangeStart && (pRangeStart->eOperator & WO_LE)!=0 ); |
| 166650 | 166925 | testcase( pRangeStart && (pRangeStart->eOperator & WO_GE)!=0 ); |
| 166651 | 166926 | testcase( pRangeEnd && (pRangeEnd->eOperator & WO_LE)!=0 ); |
| 166652 | 166927 | testcase( pRangeEnd && (pRangeEnd->eOperator & WO_GE)!=0 ); |
| | @@ -166697,11 +166972,11 @@ |
| 166697 | 166972 | sqlite3VdbeAddOp2(v, OP_Integer, 1, regBignull); |
| 166698 | 166973 | VdbeComment((v, "NULL-scan pass ctr")); |
| 166699 | 166974 | } |
| 166700 | 166975 | if( pLevel->regFilter ){ |
| 166701 | 166976 | assert( sqlite3WhereLoopBloomable(pLoop) ); |
| 166702 | | - sqlite3VdbeAddOp4Int(v, OP_Filter, pLevel->regFilter, addrNxt, |
| 166977 | + sqlite3VdbeAddOp4Int(v, OP_Filter, pLevel->regFilter, addrMiss, |
| 166703 | 166978 | regBase, nEq); |
| 166704 | 166979 | VdbeCoverage(v); |
| 166705 | 166980 | filterPullDown(pParse, pWInfo, iLevel, addrNxt, notReady); |
| 166706 | 166981 | } |
| 166707 | 166982 | |
| | @@ -166724,11 +166999,11 @@ |
| 166724 | 166999 | sqlite3VdbeChangeP2(v, addrSeekScan, sqlite3VdbeCurrentAddr(v)+1); |
| 166725 | 167000 | addrSeekScan = 0; |
| 166726 | 167001 | } |
| 166727 | 167002 | VdbeCoverage(v); |
| 166728 | 167003 | } |
| 166729 | | - sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint); |
| 167004 | + sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrMiss, regBase, nConstraint); |
| 166730 | 167005 | VdbeCoverage(v); |
| 166731 | 167006 | VdbeCoverageIf(v, op==OP_Rewind); testcase( op==OP_Rewind ); |
| 166732 | 167007 | VdbeCoverageIf(v, op==OP_Last); testcase( op==OP_Last ); |
| 166733 | 167008 | VdbeCoverageIf(v, op==OP_SeekGT); testcase( op==OP_SeekGT ); |
| 166734 | 167009 | VdbeCoverageIf(v, op==OP_SeekGE); testcase( op==OP_SeekGE ); |
| | @@ -169965,16 +170240,20 @@ |
| 169965 | 170240 | Expr *pX = pTerm->pExpr; |
| 169966 | 170241 | Expr inexpr; |
| 169967 | 170242 | |
| 169968 | 170243 | assert( pTerm->eOperator & WO_IN ); |
| 169969 | 170244 | |
| 169970 | | - if( sqlite3ExprIsVector(pX->pLeft) ){ |
| 169971 | | - int iField = pTerm->u.x.iField - 1; |
| 170245 | + if( ExprUseXSelect(pX) ){ |
| 170246 | + int iField = 0; |
| 169972 | 170247 | inexpr.flags = 0; |
| 169973 | 170248 | inexpr.op = TK_EQ; |
| 169974 | | - inexpr.pLeft = pX->pLeft->x.pList->a[iField].pExpr; |
| 169975 | | - assert( ExprUseXSelect(pX) ); |
| 170249 | + if( sqlite3ExprIsVector(pX->pLeft) ){ |
| 170250 | + iField = pTerm->u.x.iField - 1; |
| 170251 | + inexpr.pLeft = pX->pLeft->x.pList->a[iField].pExpr; |
| 170252 | + }else{ |
| 170253 | + inexpr.pLeft = pX->pLeft; |
| 170254 | + } |
| 169976 | 170255 | inexpr.pRight = pX->x.pSelect->pEList->a[iField].pExpr; |
| 169977 | 170256 | pX = &inexpr; |
| 169978 | 170257 | } |
| 169979 | 170258 | |
| 169980 | 170259 | if( sqlite3IndexAffinityOk(pX, idxaff) ){ |
| | @@ -173573,39 +173852,55 @@ |
| 173573 | 173852 | } |
| 173574 | 173853 | |
| 173575 | 173854 | if( (pPart->op==TK_EQ || pPart->op==TK_IS) ){ |
| 173576 | 173855 | Expr *pLeft = pPart->pLeft; |
| 173577 | 173856 | Expr *pRight = pPart->pRight; |
| 173578 | | - u8 aff; |
| 173857 | + Table *pLeftTab; /* Table of the left operand */ |
| 173858 | + Column *pLeftCol; /* Column of the left operand */ |
| 173859 | + u8 affRight, affLeft; |
| 173579 | 173860 | |
| 173580 | 173861 | if( pLeft->op!=TK_COLUMN ) return; |
| 173581 | 173862 | if( !sqlite3ExprIsConstant(0, pRight) ) return; |
| 173582 | 173863 | if( !sqlite3IsBinary(sqlite3ExprCompareCollSeq(pParse, pPart)) ) return; |
| 173583 | 173864 | if( pLeft->iColumn<0 ) return; |
| 173584 | | - aff = pIdx->pTable->aCol[pLeft->iColumn].affinity; |
| 173585 | | - if( aff>=SQLITE_AFF_TEXT ){ |
| 173586 | | - if( pItem ){ |
| 173587 | | - sqlite3 *db = pParse->db; |
| 173588 | | - IndexedExpr *p = (IndexedExpr*)sqlite3DbMallocRaw(db, sizeof(*p)); |
| 173589 | | - if( p ){ |
| 173590 | | - int bNullRow = (pItem->fg.jointype&(JT_LEFT|JT_LTORJ))!=0; |
| 173591 | | - p->pExpr = sqlite3ExprDup(db, pRight, 0); |
| 173592 | | - p->iDataCur = pItem->iCursor; |
| 173593 | | - p->iIdxCur = iIdxCur; |
| 173594 | | - p->iIdxCol = pLeft->iColumn; |
| 173595 | | - p->bMaybeNullRow = bNullRow; |
| 173596 | | - p->pIENext = pParse->pIdxPartExpr; |
| 173597 | | - p->aff = aff; |
| 173598 | | - pParse->pIdxPartExpr = p; |
| 173599 | | - if( p->pIENext==0 ){ |
| 173600 | | - void *pArg = (void*)&pParse->pIdxPartExpr; |
| 173601 | | - sqlite3ParserAddCleanup(pParse, whereIndexedExprCleanup, pArg); |
| 173602 | | - } |
| 173603 | | - } |
| 173604 | | - }else if( pLeft->iColumn<(BMS-1) ){ |
| 173605 | | - *pMask &= ~((Bitmask)1 << pLeft->iColumn); |
| 173606 | | - } |
| 173865 | + pLeftTab = pIdx->pTable; |
| 173866 | + pLeftCol = &pLeftTab->aCol[pLeft->iColumn]; |
| 173867 | + affLeft = pLeftCol->affinity; |
| 173868 | + assert( SQLITE_AFF_BLOB<SQLITE_AFF_TEXT ); |
| 173869 | + if( affLeft<SQLITE_AFF_TEXT ) return; |
| 173870 | + affRight = sqlite3ExprAffinity(pRight); |
| 173871 | + if( affRight!=0 && affRight!=affLeft ) return; |
| 173872 | + if( pItem ){ |
| 173873 | + sqlite3 *db = pParse->db; |
| 173874 | + IndexedExpr *p = (IndexedExpr*)sqlite3DbMallocRaw(db, sizeof(*p)); |
| 173875 | + if( p ){ |
| 173876 | + int bNullRow = (pItem->fg.jointype&(JT_LEFT|JT_LTORJ))!=0; |
| 173877 | + pRight = sqlite3ExprDup(db, pRight, 0); |
| 173878 | + if( (pLeftTab->tabFlags & TF_Strict)!=0 ){ |
| 173879 | + Token t; |
| 173880 | + t.z = sqlite3ColumnType(pLeftCol, 0); |
| 173881 | + assert( t.z!=0 ); /* Because affLeft>=SQLITE_AFF_TEXT */ |
| 173882 | + t.n = (int)strlen(t.z); |
| 173883 | + p->pExpr = sqlite3ExprAlloc(db, TK_CAST, &t, 1); |
| 173884 | + sqlite3ExprAttachSubtrees(db, p->pExpr, pRight, 0); |
| 173885 | + }else{ |
| 173886 | + p->pExpr = pRight; |
| 173887 | + } |
| 173888 | + p->iDataCur = pItem->iCursor; |
| 173889 | + p->iIdxCur = iIdxCur; |
| 173890 | + p->iIdxCol = pLeft->iColumn; |
| 173891 | + p->bMaybeNullRow = bNullRow; |
| 173892 | + p->pIENext = pParse->pIdxPartExpr; |
| 173893 | + p->aff = affLeft; |
| 173894 | + pParse->pIdxPartExpr = p; |
| 173895 | + if( p->pIENext==0 ){ |
| 173896 | + void *pArg = (void*)&pParse->pIdxPartExpr; |
| 173897 | + sqlite3ParserAddCleanup(pParse, whereIndexedExprCleanup, pArg); |
| 173898 | + } |
| 173899 | + } |
| 173900 | + }else if( pLeft->iColumn<(BMS-1) ){ |
| 173901 | + *pMask &= ~((Bitmask)1 << pLeft->iColumn); |
| 173607 | 173902 | } |
| 173608 | 173903 | } |
| 173609 | 173904 | } |
| 173610 | 173905 | |
| 173611 | 173906 | |
| | @@ -173834,11 +174129,13 @@ |
| 173834 | 174129 | if( pProbe->isCovering ){ |
| 173835 | 174130 | m = 0; |
| 173836 | 174131 | pNew->wsFlags = WHERE_IDX_ONLY | WHERE_INDEXED; |
| 173837 | 174132 | }else{ |
| 173838 | 174133 | m = pSrc->colUsed & pProbe->colNotIdxed; |
| 173839 | | - if( pProbe->pPartIdxWhere ){ |
| 174134 | + if( pProbe->pPartIdxWhere |
| 174135 | + && (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE)==0 |
| 174136 | + ){ |
| 173840 | 174137 | wherePartIdxExpr( |
| 173841 | 174138 | pWInfo->pParse, pProbe, pProbe->pPartIdxWhere, &m, 0, 0 |
| 173842 | 174139 | ); |
| 173843 | 174140 | } |
| 173844 | 174141 | pNew->wsFlags = WHERE_INDEXED; |
| | @@ -174718,17 +175015,17 @@ |
| 174718 | 175015 | ** long as the subquery is materialized. If the subquery is |
| 174719 | 175016 | ** implemented as a co-routine, the sort orders must be in the same |
| 174720 | 175017 | ** direction because there is no way to run a co-routine backwards. |
| 174721 | 175018 | */ |
| 174722 | 175019 | static SQLITE_NOINLINE int wherePathMatchSubqueryOB( |
| 174723 | | - WhereInfo *pWInfo, /* The WHERE clause */ |
| 174724 | 175020 | WhereLoop *pLoop, /* The nested loop term that is a subquery */ |
| 174725 | 175021 | int iLoop, /* Which level of the nested loop. 0==outermost */ |
| 174726 | 175022 | int iCur, /* Cursor used by the this loop */ |
| 174727 | 175023 | ExprList *pOrderBy, /* The ORDER BY clause on the whole query */ |
| 174728 | 175024 | Bitmask *pRevMask, /* When loops need to go in reverse order */ |
| 174729 | | - Bitmask *pOBSat /* Which terms of pOrderBy are satisfied so far */ |
| 175025 | + Bitmask *pOBSat, /* Which terms of pOrderBy are satisfied so far */ |
| 175026 | + u16 wctrlFlags /* WHERE_GROUPBY or _DISTINCTBY or _ORDERBY_LIMIT */ |
| 174730 | 175027 | ){ |
| 174731 | 175028 | int iOB; /* Index into pOrderBy->a[] */ |
| 174732 | 175029 | int jSub; /* Index into pSubOB->a[] */ |
| 174733 | 175030 | u8 rev = 0; /* True if iOB and jSub sort in opposite directions */ |
| 174734 | 175031 | u8 revIdx = 0; /* Sort direction for jSub */ |
| | @@ -174742,11 +175039,11 @@ |
| 174742 | 175039 | if( pSubOB->a[jSub].u.x.iOrderByCol==0 ) break; |
| 174743 | 175040 | pOBExpr = pOrderBy->a[iOB].pExpr; |
| 174744 | 175041 | if( pOBExpr->op!=TK_COLUMN && pOBExpr->op!=TK_AGG_COLUMN ) break; |
| 174745 | 175042 | if( pOBExpr->iTable!=iCur ) break; |
| 174746 | 175043 | if( pOBExpr->iColumn!=pSubOB->a[jSub].u.x.iOrderByCol-1 ) break; |
| 174747 | | - if( (pWInfo->wctrlFlags & WHERE_GROUPBY)==0 ){ |
| 175044 | + if( (wctrlFlags & WHERE_GROUPBY)==0 ){ |
| 174748 | 175045 | u8 sfOB = pOrderBy->a[iOB].fg.sortFlags; /* sortFlags for iOB */ |
| 174749 | 175046 | u8 sfSub = pSubOB->a[jSub].fg.sortFlags; /* sortFlags for jSub */ |
| 174750 | 175047 | if( (sfSub & KEYINFO_ORDER_BIGNULL) != (sfOB & KEYINFO_ORDER_BIGNULL) ){ |
| 174751 | 175048 | break; |
| 174752 | 175049 | } |
| | @@ -174924,20 +175221,20 @@ |
| 174924 | 175221 | |
| 174925 | 175222 | if( (pLoop->wsFlags & WHERE_ONEROW)==0 ){ |
| 174926 | 175223 | if( pLoop->wsFlags & WHERE_IPK ){ |
| 174927 | 175224 | if( pLoop->u.btree.pOrderBy |
| 174928 | 175225 | && OptimizationEnabled(db, SQLITE_OrderBySubq) |
| 174929 | | - && wherePathMatchSubqueryOB(pWInfo,pLoop,iLoop,iCur, |
| 174930 | | - pOrderBy,pRevMask, &obSat) |
| 175226 | + && wherePathMatchSubqueryOB(pLoop,iLoop,iCur, |
| 175227 | + pOrderBy,pRevMask, &obSat, wctrlFlags) |
| 174931 | 175228 | ){ |
| 174932 | 175229 | nColumn = 0; |
| 174933 | 175230 | isOrderDistinct = 0; |
| 174934 | 175231 | }else{ |
| 174935 | 175232 | nColumn = 1; |
| 174936 | 175233 | } |
| 174937 | 175234 | pIndex = 0; |
| 174938 | | - nKeyCol = 0; |
| 175235 | + nKeyCol = 1; |
| 174939 | 175236 | }else if( (pIndex = pLoop->u.btree.pIndex)==0 || pIndex->bUnordered ){ |
| 174940 | 175237 | return 0; |
| 174941 | 175238 | }else{ |
| 174942 | 175239 | nKeyCol = pIndex->nKeyCol; |
| 174943 | 175240 | nColumn = pIndex->nColumn; |
| | @@ -175074,11 +175371,18 @@ |
| 175074 | 175371 | if( rev ) *pRevMask |= MASKBIT(iLoop); |
| 175075 | 175372 | revSet = 1; |
| 175076 | 175373 | } |
| 175077 | 175374 | } |
| 175078 | 175375 | if( isMatch && (pOrderBy->a[i].fg.sortFlags & KEYINFO_ORDER_BIGNULL) ){ |
| 175079 | | - if( j==pLoop->u.btree.nEq ){ |
| 175376 | + if( j==pLoop->u.btree.nEq |
| 175377 | + && (j<nKeyCol||HasRowid(pIndex->pTable)||!IsPrimaryKeyIndex(pIndex)) |
| 175378 | + ){ |
| 175379 | + /* If this is the PK of a WITHOUT ROWID table, do not use any |
| 175380 | + ** field past nKeyCol for a NULLS LAST sort. If ALTER TABLE has |
| 175381 | + ** been used to add columns to the table, this field may not |
| 175382 | + ** be present in all records, which causes problems for the seeks |
| 175383 | + ** used by NULLS LAST sorts. */ |
| 175080 | 175384 | pLoop->wsFlags |= WHERE_BIGNULL_SORT; |
| 175081 | 175385 | }else{ |
| 175082 | 175386 | isMatch = 0; |
| 175083 | 175387 | } |
| 175084 | 175388 | } |
| | @@ -175088,11 +175392,12 @@ |
| 175088 | 175392 | distinctColumns = 1; |
| 175089 | 175393 | } |
| 175090 | 175394 | obSat |= MASKBIT(i); |
| 175091 | 175395 | }else{ |
| 175092 | 175396 | /* No match found */ |
| 175093 | | - if( j==0 || j<nKeyCol ){ |
| 175397 | + assert( nKeyCol>0 ); |
| 175398 | + if( j<nKeyCol ){ |
| 175094 | 175399 | testcase( isOrderDistinct!=0 ); |
| 175095 | 175400 | isOrderDistinct = 0; |
| 175096 | 175401 | } |
| 175097 | 175402 | break; |
| 175098 | 175403 | } |
| | @@ -177249,10 +177554,21 @@ |
| 177249 | 177554 | if( pTabList->a[pLevel->iFrom].fg.fromExists ){ |
| 177250 | 177555 | /* This is an EXISTS-to-JOIN optimization loop. If this loop sees a |
| 177251 | 177556 | ** successful row, it should break out of itself. */ |
| 177252 | 177557 | sqlite3VdbeAddOp2(v, OP_Goto, 0, pLevel->addrBrk); |
| 177253 | 177558 | VdbeComment((v, "EXISTS break %d", i)); |
| 177559 | + }else if( pLevel->addrDeleteCont ){ |
| 177560 | + /* An inner loop matched no rows on this auto-index driven loop and |
| 177561 | + ** there are outer loops. So delete the auto-index entry to avoid |
| 177562 | + ** future unnecessary work. */ |
| 177563 | + int iBypass = sqlite3VdbeAddOp0(v, OP_Goto); |
| 177564 | + assert( pLoop->wsFlags & WHERE_AUTO_INDEX ); |
| 177565 | + sqlite3VdbeResolveLabel(v, pLevel->addrDeleteCont); |
| 177566 | + sqlite3VdbeAddOp1(v, OP_Delete, pLevel->iIdxCur); |
| 177567 | + sqlite3VdbeChangeP5(v, OPFLAG_SAVEPOSITION); |
| 177568 | + VdbeComment((v, "delete useless auto-index entry")); |
| 177569 | + sqlite3VdbeJumpHere(v, iBypass); |
| 177254 | 177570 | } |
| 177255 | 177571 | sqlite3VdbeResolveLabel(v, pLevel->addrCont); |
| 177256 | 177572 | if( pLevel->op!=OP_Noop ){ |
| 177257 | 177573 | sqlite3VdbeAddOp3(v, pLevel->op, pLevel->p1, pLevel->p2, pLevel->p3); |
| 177258 | 177574 | sqlite3VdbeChangeP5(v, pLevel->p5); |
| | @@ -177270,14 +177586,35 @@ |
| 177270 | 177586 | sqlite3VdbeResolveLabel(v, pLevel->addrBignull); |
| 177271 | 177587 | sqlite3VdbeAddOp2(v, OP_DecrJumpZero, pLevel->regBignull, pLevel->p2-1); |
| 177272 | 177588 | VdbeCoverage(v); |
| 177273 | 177589 | } |
| 177274 | 177590 | } |
| 177591 | + if( pLevel->addrNxt!=pLevel->addrBrk ){ |
| 177592 | + /* This occurs in three cases - (a) for a LIKE/GLOB scan that must visit |
| 177593 | + ** ranges of text and blob values separately, and (b) when there is |
| 177594 | + ** an IN(...) constraint driving the index, and (c) when a prior error |
| 177595 | + ** such as an OOM has left us in an unusual state. This is asserted() |
| 177596 | + ** in the next block, inside the #ifndef. */ |
| 177597 | + sqlite3VdbeResolveLabel(v, pLevel->addrNxt); |
| 177598 | + } |
| 177599 | +#ifndef SQLITE_LIKE_DOESNT_MATCH_BLOBS |
| 177600 | + assert( (pLevel->addrNxt==pLevel->addrBrk) |
| 177601 | + || (pLevel->addrLikeRep) /* (a) */ |
| 177602 | + || ((pLoop->wsFlags & WHERE_IN_ABLE) && pLevel->u.in.nIn>0) /* (b) */ |
| 177603 | + || pWInfo->pParse->nErr>0 /* (c) */ |
| 177604 | + ); |
| 177605 | + if( pLevel->addrLikeRep ){ |
| 177606 | + /* The LIKE optimization loop is nested inside any IN(...) and |
| 177607 | + ** skip-scan loops, so it is closed here, before either of those. */ |
| 177608 | + sqlite3VdbeAddOp2(v, OP_DecrJumpZero, (int)(pLevel->iLikeRepCntr>>1), |
| 177609 | + pLevel->addrLikeRep); |
| 177610 | + VdbeCoverage(v); |
| 177611 | + } |
| 177612 | +#endif |
| 177275 | 177613 | if( (pLoop->wsFlags & WHERE_IN_ABLE)!=0 && pLevel->u.in.nIn>0 ){ |
| 177276 | 177614 | struct InLoop *pIn; |
| 177277 | 177615 | int j; |
| 177278 | | - sqlite3VdbeResolveLabel(v, pLevel->addrNxt); |
| 177279 | 177616 | for(j=pLevel->u.in.nIn, pIn=&pLevel->u.in.aInLoop[j-1]; j>0; j--, pIn--){ |
| 177280 | 177617 | assert( sqlite3VdbeGetOp(v, pIn->addrInTop+1)->opcode==OP_IsNull |
| 177281 | 177618 | || pParse->db->mallocFailed ); |
| 177282 | 177619 | sqlite3VdbeJumpHere(v, pIn->addrInTop+1); |
| 177283 | 177620 | if( pIn->eEndLoopOp!=OP_Noop ){ |
| | @@ -177325,17 +177662,10 @@ |
| 177325 | 177662 | sqlite3VdbeGoto(v, pLevel->addrSkip); |
| 177326 | 177663 | VdbeComment((v, "next skip-scan on %s", pLoop->u.btree.pIndex->zName)); |
| 177327 | 177664 | sqlite3VdbeJumpHere(v, pLevel->addrSkip); |
| 177328 | 177665 | sqlite3VdbeJumpHere(v, pLevel->addrSkip-2); |
| 177329 | 177666 | } |
| 177330 | | -#ifndef SQLITE_LIKE_DOESNT_MATCH_BLOBS |
| 177331 | | - if( pLevel->addrLikeRep ){ |
| 177332 | | - sqlite3VdbeAddOp2(v, OP_DecrJumpZero, (int)(pLevel->iLikeRepCntr>>1), |
| 177333 | | - pLevel->addrLikeRep); |
| 177334 | | - VdbeCoverage(v); |
| 177335 | | - } |
| 177336 | | -#endif |
| 177337 | 177667 | if( pLevel->iLeftJoin ){ |
| 177338 | 177668 | int ws = pLoop->wsFlags; |
| 177339 | 177669 | addr = sqlite3VdbeAddOp1(v, OP_IfPos, pLevel->iLeftJoin); VdbeCoverage(v); |
| 177340 | 177670 | assert( (ws & WHERE_IDX_ONLY)==0 || (ws & WHERE_INDEXED)!=0 ); |
| 177341 | 177671 | if( (ws & WHERE_IDX_ONLY)==0 ){ |
| | @@ -212949,17 +213279,15 @@ |
| 212949 | 213279 | /* #include <string.h> */ |
| 212950 | 213280 | |
| 212951 | 213281 | /* #include "fts3_tokenizer.h" */ |
| 212952 | 213282 | |
| 212953 | 213283 | /* |
| 212954 | | -** The following two macros - READ_UTF8 and WRITE_UTF8 - have been copied |
| 212955 | | -** from the sqlite3 source file utf.c. If this file is compiled as part |
| 212956 | | -** of the amalgamation, they are not required. |
| 213284 | +** The following two macros - FTS3_READ_UTF8 and FTS3_WRITE_UTF8 - have |
| 213285 | +** been copied from the sqlite3 source file utf.c. |
| 212957 | 213286 | */ |
| 212958 | | -#ifndef SQLITE_AMALGAMATION |
| 212959 | 213287 | |
| 212960 | | -static const unsigned char sqlite3Utf8Trans1[] = { |
| 213288 | +static const unsigned char fts3Utf8Trans1[] = { |
| 212961 | 213289 | 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, |
| 212962 | 213290 | 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, |
| 212963 | 213291 | 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, |
| 212964 | 213292 | 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, |
| 212965 | 213293 | 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, |
| | @@ -212966,43 +213294,41 @@ |
| 212966 | 213294 | 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, |
| 212967 | 213295 | 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, |
| 212968 | 213296 | 0x00, 0x01, 0x02, 0x03, 0x00, 0x01, 0x00, 0x00, |
| 212969 | 213297 | }; |
| 212970 | 213298 | |
| 212971 | | -#define READ_UTF8(zIn, zTerm, c) \ |
| 213299 | +#define FTS3_READ_UTF8(zIn, zTerm, c) \ |
| 212972 | 213300 | c = *(zIn++); \ |
| 212973 | 213301 | if( c>=0xc0 ){ \ |
| 212974 | | - c = sqlite3Utf8Trans1[c-0xc0]; \ |
| 213302 | + c = fts3Utf8Trans1[c-0xc0]; \ |
| 212975 | 213303 | while( zIn!=zTerm && (*zIn & 0xc0)==0x80 ){ \ |
| 212976 | 213304 | c = (c<<6) + (0x3f & *(zIn++)); \ |
| 212977 | 213305 | } \ |
| 212978 | 213306 | if( c<0x80 \ |
| 212979 | 213307 | || (c&0xFFFFF800)==0xD800 \ |
| 212980 | 213308 | || (c&0xFFFFFFFE)==0xFFFE ){ c = 0xFFFD; } \ |
| 212981 | 213309 | } |
| 212982 | 213310 | |
| 212983 | | -#define WRITE_UTF8(zOut, c) { \ |
| 212984 | | - if( c<0x00080 ){ \ |
| 212985 | | - *zOut++ = (u8)(c&0xFF); \ |
| 212986 | | - } \ |
| 212987 | | - else if( c<0x00800 ){ \ |
| 212988 | | - *zOut++ = 0xC0 + (u8)((c>>6)&0x1F); \ |
| 212989 | | - *zOut++ = 0x80 + (u8)(c & 0x3F); \ |
| 212990 | | - } \ |
| 212991 | | - else if( c<0x10000 ){ \ |
| 212992 | | - *zOut++ = 0xE0 + (u8)((c>>12)&0x0F); \ |
| 212993 | | - *zOut++ = 0x80 + (u8)((c>>6) & 0x3F); \ |
| 212994 | | - *zOut++ = 0x80 + (u8)(c & 0x3F); \ |
| 212995 | | - }else{ \ |
| 212996 | | - *zOut++ = 0xF0 + (u8)((c>>18) & 0x07); \ |
| 212997 | | - *zOut++ = 0x80 + (u8)((c>>12) & 0x3F); \ |
| 212998 | | - *zOut++ = 0x80 + (u8)((c>>6) & 0x3F); \ |
| 212999 | | - *zOut++ = 0x80 + (u8)(c & 0x3F); \ |
| 213000 | | - } \ |
| 213001 | | -} |
| 213002 | | - |
| 213003 | | -#endif /* ifndef SQLITE_AMALGAMATION */ |
| 213311 | +#define FTS3_WRITE_UTF8(zOut, c) { \ |
| 213312 | + if( c<0x00080 ){ \ |
| 213313 | + *zOut++ = (u8)(c&0xFF); \ |
| 213314 | + } \ |
| 213315 | + else if( c<0x00800 ){ \ |
| 213316 | + *zOut++ = 0xC0 + (u8)((c>>6)&0x1F); \ |
| 213317 | + *zOut++ = 0x80 + (u8)(c & 0x3F); \ |
| 213318 | + } \ |
| 213319 | + else if( c<0x10000 ){ \ |
| 213320 | + *zOut++ = 0xE0 + (u8)((c>>12)&0x0F); \ |
| 213321 | + *zOut++ = 0x80 + (u8)((c>>6) & 0x3F); \ |
| 213322 | + *zOut++ = 0x80 + (u8)(c & 0x3F); \ |
| 213323 | + }else{ \ |
| 213324 | + *zOut++ = 0xF0 + (u8)((c>>18) & 0x07); \ |
| 213325 | + *zOut++ = 0x80 + (u8)((c>>12) & 0x3F); \ |
| 213326 | + *zOut++ = 0x80 + (u8)((c>>6) & 0x3F); \ |
| 213327 | + *zOut++ = 0x80 + (u8)(c & 0x3F); \ |
| 213328 | + } \ |
| 213329 | +} |
| 213004 | 213330 | |
| 213005 | 213331 | typedef struct unicode_tokenizer unicode_tokenizer; |
| 213006 | 213332 | typedef struct unicode_cursor unicode_cursor; |
| 213007 | 213333 | |
| 213008 | 213334 | struct unicode_tokenizer { |
| | @@ -213065,11 +213391,11 @@ |
| 213065 | 213391 | int nEntry = 0; |
| 213066 | 213392 | |
| 213067 | 213393 | assert( bAlnum==0 || bAlnum==1 ); |
| 213068 | 213394 | |
| 213069 | 213395 | while( z<zTerm ){ |
| 213070 | | - READ_UTF8(z, zTerm, iCode); |
| 213396 | + FTS3_READ_UTF8(z, zTerm, iCode); |
| 213071 | 213397 | assert( (sqlite3FtsUnicodeIsalnum((int)iCode) & 0xFFFFFFFE)==0 ); |
| 213072 | 213398 | if( sqlite3FtsUnicodeIsalnum((int)iCode)!=bAlnum |
| 213073 | 213399 | && sqlite3FtsUnicodeIsdiacritic((int)iCode)==0 |
| 213074 | 213400 | ){ |
| 213075 | 213401 | nEntry++; |
| | @@ -213084,11 +213410,11 @@ |
| 213084 | 213410 | if( aNew==0 ) return SQLITE_NOMEM; |
| 213085 | 213411 | nNew = p->nException; |
| 213086 | 213412 | |
| 213087 | 213413 | z = (const unsigned char *)zIn; |
| 213088 | 213414 | while( z<zTerm ){ |
| 213089 | | - READ_UTF8(z, zTerm, iCode); |
| 213415 | + FTS3_READ_UTF8(z, zTerm, iCode); |
| 213090 | 213416 | if( sqlite3FtsUnicodeIsalnum((int)iCode)!=bAlnum |
| 213091 | 213417 | && sqlite3FtsUnicodeIsdiacritic((int)iCode)==0 |
| 213092 | 213418 | ){ |
| 213093 | 213419 | int i, j; |
| 213094 | 213420 | for(i=0; i<nNew && aNew[i]<(int)iCode; i++); |
| | @@ -213256,11 +213582,11 @@ |
| 213256 | 213582 | |
| 213257 | 213583 | /* Scan past any delimiter characters before the start of the next token. |
| 213258 | 213584 | ** Return SQLITE_DONE early if this takes us all the way to the end of |
| 213259 | 213585 | ** the input. */ |
| 213260 | 213586 | while( z<zTerm ){ |
| 213261 | | - READ_UTF8(z, zTerm, iCode); |
| 213587 | + FTS3_READ_UTF8(z, zTerm, iCode); |
| 213262 | 213588 | if( unicodeIsAlnum(p, (int)iCode) ) break; |
| 213263 | 213589 | zStart = z; |
| 213264 | 213590 | } |
| 213265 | 213591 | if( zStart>=zTerm ) return SQLITE_DONE; |
| 213266 | 213592 | |
| | @@ -213279,16 +213605,16 @@ |
| 213279 | 213605 | |
| 213280 | 213606 | /* Write the folded case of the last character read to the output */ |
| 213281 | 213607 | zEnd = z; |
| 213282 | 213608 | iOut = sqlite3FtsUnicodeFold((int)iCode, p->eRemoveDiacritic); |
| 213283 | 213609 | if( iOut ){ |
| 213284 | | - WRITE_UTF8(zOut, iOut); |
| 213610 | + FTS3_WRITE_UTF8(zOut, iOut); |
| 213285 | 213611 | } |
| 213286 | 213612 | |
| 213287 | 213613 | /* If the cursor is not at EOF, read the next character */ |
| 213288 | 213614 | if( z>=zTerm ) break; |
| 213289 | | - READ_UTF8(z, zTerm, iCode); |
| 213615 | + FTS3_READ_UTF8(z, zTerm, iCode); |
| 213290 | 213616 | }while( unicodeIsAlnum(p, (int)iCode) |
| 213291 | 213617 | || sqlite3FtsUnicodeIsdiacritic((int)iCode) |
| 213292 | 213618 | ); |
| 213293 | 213619 | |
| 213294 | 213620 | /* Set the output variables and return. */ |
| | @@ -214107,10 +214433,11 @@ |
| 214107 | 214433 | /* |
| 214108 | 214434 | ** Allowed values for the flgs argument to jsonParseFuncArg(); |
| 214109 | 214435 | */ |
| 214110 | 214436 | #define JSON_EDITABLE 0x01 /* Generate a writable JsonParse object */ |
| 214111 | 214437 | #define JSON_KEEPERROR 0x02 /* Return non-NULL even if there is an error */ |
| 214438 | +#define JSON_NOCACHE 0x04 /* Do not use the JSON cache */ |
| 214112 | 214439 | |
| 214113 | 214440 | /************************************************************************** |
| 214114 | 214441 | ** Forward references |
| 214115 | 214442 | **************************************************************************/ |
| 214116 | 214443 | static void jsonReturnStringAsBlob(JsonString*); |
| | @@ -217550,11 +217877,13 @@ |
| 217550 | 217877 | assert( ctx!=0 ); |
| 217551 | 217878 | eType = sqlite3_value_type(pArg); |
| 217552 | 217879 | if( eType==SQLITE_NULL ){ |
| 217553 | 217880 | return 0; |
| 217554 | 217881 | } |
| 217555 | | - pFromCache = jsonCacheSearch(ctx, pArg); |
| 217882 | + if( (flgs & JSON_NOCACHE)==0 ){ |
| 217883 | + pFromCache = jsonCacheSearch(ctx, pArg); |
| 217884 | + } |
| 217556 | 217885 | if( pFromCache ){ |
| 217557 | 217886 | pFromCache->nJPRef++; |
| 217558 | 217887 | if( (flgs & JSON_EDITABLE)==0 ){ |
| 217559 | 217888 | return pFromCache; |
| 217560 | 217889 | } |
| | @@ -218625,11 +218954,11 @@ |
| 218625 | 218954 | default: { |
| 218626 | 218955 | JsonParse px; |
| 218627 | 218956 | if( (flags & 0x3)==0 ) break; |
| 218628 | 218957 | memset(&px, 0, sizeof(px)); |
| 218629 | 218958 | |
| 218630 | | - p = jsonParseFuncArg(ctx, argv[0], JSON_KEEPERROR); |
| 218959 | + p = jsonParseFuncArg(ctx, argv[0], JSON_KEEPERROR|JSON_NOCACHE); |
| 218631 | 218960 | if( p ){ |
| 218632 | 218961 | if( p->oom ){ |
| 218633 | 218962 | sqlite3_result_error_nomem(ctx); |
| 218634 | 218963 | }else if( p->nErr ){ |
| 218635 | 218964 | /* no-op */ |
| | @@ -219218,21 +219547,20 @@ |
| 219218 | 219547 | */ |
| 219219 | 219548 | static int jsonEachPathLength(JsonEachCursor *p){ |
| 219220 | 219549 | u32 n = p->path.nUsed; |
| 219221 | 219550 | char *z = p->path.zBuf; |
| 219222 | 219551 | if( p->iRowid==0 && p->bRecursive && n>=2 ){ |
| 219223 | | - while( n>1 ){ |
| 219552 | + while( ALWAYS(n>1) ){ |
| 219224 | 219553 | n--; |
| 219225 | 219554 | if( z[n]=='[' || z[n]=='.' ){ |
| 219226 | | - u32 x, sz = 0; |
| 219555 | + u32 x; |
| 219227 | 219556 | char cSaved = z[n]; |
| 219228 | 219557 | z[n] = 0; |
| 219229 | 219558 | assert( p->sParse.eEdit==0 ); |
| 219230 | 219559 | x = jsonLookupStep(&p->sParse, 0, z+1, 0); |
| 219231 | 219560 | z[n] = cSaved; |
| 219232 | | - if( JSON_LOOKUP_ISERROR(x) ) continue; |
| 219233 | | - if( x + jsonbPayloadSize(&p->sParse, x, &sz) == p->i ) break; |
| 219561 | + if( !JSON_LOOKUP_ISERROR(x) ) break; |
| 219234 | 219562 | } |
| 219235 | 219563 | } |
| 219236 | 219564 | } |
| 219237 | 219565 | return n; |
| 219238 | 219566 | } |
| | @@ -246043,11 +246371,26 @@ |
| 246043 | 246371 | } |
| 246044 | 246372 | |
| 246045 | 246373 | return rc; |
| 246046 | 246374 | } |
| 246047 | 246375 | |
| 246048 | | - |
| 246376 | +/* |
| 246377 | +** Load error code rc into the context handle pCtx. Except, if |
| 246378 | +** rc==SQLITE_ERROR and there is an error message in the associated db |
| 246379 | +** handle, return that error message as well. |
| 246380 | +*/ |
| 246381 | +static void fts5AuxResultError(sqlite3_context *pCtx, int rc){ |
| 246382 | + if( rc==SQLITE_ERROR ){ |
| 246383 | + sqlite3 *db = sqlite3_context_db_handle(pCtx); |
| 246384 | + if( sqlite3_errcode(db)==SQLITE_ERROR ){ |
| 246385 | + const char *zErr = sqlite3_errmsg(db); |
| 246386 | + sqlite3_result_error(pCtx, zErr, -1); |
| 246387 | + return; |
| 246388 | + } |
| 246389 | + } |
| 246390 | + sqlite3_result_error_code(pCtx, rc); |
| 246391 | +} |
| 246049 | 246392 | |
| 246050 | 246393 | /************************************************************************* |
| 246051 | 246394 | ** Start of highlight() implementation. |
| 246052 | 246395 | */ |
| 246053 | 246396 | typedef struct HighlightContext HighlightContext; |
| | @@ -246232,11 +246575,11 @@ |
| 246232 | 246575 | sqlite3_result_text(pCtx, (const char*)ctx.zOut, -1, SQLITE_TRANSIENT); |
| 246233 | 246576 | } |
| 246234 | 246577 | sqlite3_free(ctx.zOut); |
| 246235 | 246578 | } |
| 246236 | 246579 | if( rc!=SQLITE_OK ){ |
| 246237 | | - sqlite3_result_error_code(pCtx, rc); |
| 246580 | + fts5AuxResultError(pCtx, rc); |
| 246238 | 246581 | } |
| 246239 | 246582 | } |
| 246240 | 246583 | /* |
| 246241 | 246584 | ** End of highlight() implementation. |
| 246242 | 246585 | **************************************************************************/ |
| | @@ -246526,11 +246869,11 @@ |
| 246526 | 246869 | } |
| 246527 | 246870 | } |
| 246528 | 246871 | if( rc==SQLITE_OK ){ |
| 246529 | 246872 | sqlite3_result_text(pCtx, (const char*)ctx.zOut, -1, SQLITE_TRANSIENT); |
| 246530 | 246873 | }else{ |
| 246531 | | - sqlite3_result_error_code(pCtx, rc); |
| 246874 | + fts5AuxResultError(pCtx, rc); |
| 246532 | 246875 | } |
| 246533 | 246876 | sqlite3_free(ctx.zOut); |
| 246534 | 246877 | sqlite3_free(aSeen); |
| 246535 | 246878 | sqlite3_free(sFinder.aFirst); |
| 246536 | 246879 | } |
| | @@ -246692,11 +247035,11 @@ |
| 246692 | 247035 | ( aFreq[i] + k1 * (1 - b + b * D / pData->avgdl) ) |
| 246693 | 247036 | ); |
| 246694 | 247037 | } |
| 246695 | 247038 | sqlite3_result_double(pCtx, -1.0 * score); |
| 246696 | 247039 | }else{ |
| 246697 | | - sqlite3_result_error_code(pCtx, rc); |
| 247040 | + fts5AuxResultError(pCtx, rc); |
| 246698 | 247041 | } |
| 246699 | 247042 | } |
| 246700 | 247043 | |
| 246701 | 247044 | /* |
| 246702 | 247045 | ** Implementation of fts5_get_locale() function. |
| | @@ -246730,17 +247073,17 @@ |
| 246730 | 247073 | return; |
| 246731 | 247074 | } |
| 246732 | 247075 | |
| 246733 | 247076 | iCol = fts5ValueClampedInt(apVal[0]); |
| 246734 | 247077 | if( iCol<0 || iCol>=pApi->xColumnCount(pFts) ){ |
| 246735 | | - sqlite3_result_error_code(pCtx, SQLITE_RANGE); |
| 247078 | + fts5AuxResultError(pCtx, SQLITE_RANGE); |
| 246736 | 247079 | return; |
| 246737 | 247080 | } |
| 246738 | 247081 | |
| 246739 | 247082 | rc = pApi->xColumnLocale(pFts, iCol, &zLocale, &nLocale); |
| 246740 | 247083 | if( rc!=SQLITE_OK ){ |
| 246741 | | - sqlite3_result_error_code(pCtx, rc); |
| 247084 | + fts5AuxResultError(pCtx, rc); |
| 246742 | 247085 | return; |
| 246743 | 247086 | } |
| 246744 | 247087 | |
| 246745 | 247088 | sqlite3_result_text(pCtx, zLocale, nLocale, SQLITE_TRANSIENT); |
| 246746 | 247089 | } |
| | @@ -265407,11 +265750,11 @@ |
| 265407 | 265750 | int nArg, /* Number of args */ |
| 265408 | 265751 | sqlite3_value **apUnused /* Function arguments */ |
| 265409 | 265752 | ){ |
| 265410 | 265753 | assert( nArg==0 ); |
| 265411 | 265754 | UNUSED_PARAM2(nArg, apUnused); |
| 265412 | | - sqlite3_result_text(pCtx, "fts5: 2026-10-09 11:47:51 a3332bd623d997921c3186433cd1eab0c9413aa0f68d93b1731cf80128ec3a36", -1, SQLITE_TRANSIENT); |
| 265755 | + sqlite3_result_text(pCtx, "fts5: 2026-10-16 14:31:53 668541c592b89d32716420615450d55d9faf89da8a8e389c673973d8383cca98", -1, SQLITE_TRANSIENT); |
| 265413 | 265756 | } |
| 265414 | 265757 | |
| 265415 | 265758 | /* |
| 265416 | 265759 | ** Implementation of fts5_locale(LOCALE, TEXT) function. |
| 265417 | 265760 | ** |
| | @@ -265886,17 +266229,17 @@ |
| 265886 | 266229 | if( eStmt>FTS5_STMT_LOOKUP2 ) f |= SQLITE_PREPARE_NO_VTAB; |
| 265887 | 266230 | p->pConfig->bLock++; |
| 265888 | 266231 | rc = sqlite3_prepare_v3(pC->db, zSql, -1, f, &p->aStmt[eStmt], 0); |
| 265889 | 266232 | p->pConfig->bLock--; |
| 265890 | 266233 | sqlite3_free(zSql); |
| 265891 | | - if( rc!=SQLITE_OK && pzErrMsg ){ |
| 265892 | | - *pzErrMsg = sqlite3_mprintf("%s", sqlite3_errmsg(pC->db)); |
| 265893 | | - } |
| 265894 | 266234 | if( rc==SQLITE_ERROR && eStmt>FTS5_STMT_LOOKUP2 && eStmt<FTS5_STMT_SCAN ){ |
| 265895 | 266235 | /* One of the internal tables - not the %_content table - is missing. |
| 265896 | 266236 | ** This counts as a corrupted table. */ |
| 265897 | | - rc = SQLITE_CORRUPT; |
| 266237 | + rc = SQLITE_CORRUPT_VTAB; |
| 266238 | + }else if( rc!=SQLITE_OK && p->pConfig->pzErrmsg ){ |
| 266239 | + assert( *p->pConfig->pzErrmsg==0 ); |
| 266240 | + *p->pConfig->pzErrmsg = sqlite3_mprintf("%s", sqlite3_errmsg(pC->db)); |
| 265898 | 266241 | } |
| 265899 | 266242 | } |
| 265900 | 266243 | } |
| 265901 | 266244 | |
| 265902 | 266245 | *ppStmt = p->aStmt[eStmt]; |
| | @@ -267411,17 +267754,14 @@ |
| 267411 | 267754 | ** Start of unicode61 tokenizer implementation. |
| 267412 | 267755 | */ |
| 267413 | 267756 | |
| 267414 | 267757 | |
| 267415 | 267758 | /* |
| 267416 | | -** The following two macros - READ_UTF8 and WRITE_UTF8 - have been copied |
| 267417 | | -** from the sqlite3 source file utf.c. If this file is compiled as part |
| 267418 | | -** of the amalgamation, they are not required. |
| 267759 | +** The following two macros - FTS5_READ_UTF8 and FTS5_WRITE_UTF8 - have |
| 267760 | +** been copied from the sqlite3 source file utf.c. |
| 267419 | 267761 | */ |
| 267420 | | -#ifndef SQLITE_AMALGAMATION |
| 267421 | | - |
| 267422 | | -static const unsigned char sqlite3Utf8Trans1[] = { |
| 267762 | +static const unsigned char fts5Utf8Trans1[] = { |
| 267423 | 267763 | 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, |
| 267424 | 267764 | 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, |
| 267425 | 267765 | 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, |
| 267426 | 267766 | 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, |
| 267427 | 267767 | 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, |
| | @@ -267428,49 +267768,47 @@ |
| 267428 | 267768 | 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, |
| 267429 | 267769 | 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, |
| 267430 | 267770 | 0x00, 0x01, 0x02, 0x03, 0x00, 0x01, 0x00, 0x00, |
| 267431 | 267771 | }; |
| 267432 | 267772 | |
| 267433 | | -#define READ_UTF8(zIn, zTerm, c) \ |
| 267773 | +#define FTS5_READ_UTF8(zIn, zTerm, c) \ |
| 267434 | 267774 | c = *(zIn++); \ |
| 267435 | 267775 | if( c>=0xc0 ){ \ |
| 267436 | | - c = sqlite3Utf8Trans1[c-0xc0]; \ |
| 267776 | + c = fts5Utf8Trans1[c-0xc0]; \ |
| 267437 | 267777 | while( zIn<zTerm && (*zIn & 0xc0)==0x80 ){ \ |
| 267438 | 267778 | c = (c<<6) + (0x3f & *(zIn++)); \ |
| 267439 | 267779 | } \ |
| 267440 | 267780 | if( c<0x80 \ |
| 267441 | | - || (c&0xFFFFF800)==0xD800 \ |
| 267442 | | - || (c&0xFFFFFFFE)==0xFFFE ){ c = 0xFFFD; } \ |
| 267443 | | - } |
| 267444 | | - |
| 267445 | | - |
| 267446 | | -#define WRITE_UTF8(zOut, c) { \ |
| 267447 | | - if( c<0x00080 ){ \ |
| 267448 | | - *zOut++ = (unsigned char)(c&0xFF); \ |
| 267449 | | - } \ |
| 267450 | | - else if( c<0x00800 ){ \ |
| 267451 | | - *zOut++ = 0xC0 + (unsigned char)((c>>6)&0x1F); \ |
| 267452 | | - *zOut++ = 0x80 + (unsigned char)(c & 0x3F); \ |
| 267453 | | - } \ |
| 267454 | | - else if( c<0x10000 ){ \ |
| 267455 | | - *zOut++ = 0xE0 + (unsigned char)((c>>12)&0x0F); \ |
| 267456 | | - *zOut++ = 0x80 + (unsigned char)((c>>6) & 0x3F); \ |
| 267457 | | - *zOut++ = 0x80 + (unsigned char)(c & 0x3F); \ |
| 267458 | | - }else{ \ |
| 267459 | | - *zOut++ = 0xF0 + (unsigned char)((c>>18) & 0x07); \ |
| 267460 | | - *zOut++ = 0x80 + (unsigned char)((c>>12) & 0x3F); \ |
| 267461 | | - *zOut++ = 0x80 + (unsigned char)((c>>6) & 0x3F); \ |
| 267462 | | - *zOut++ = 0x80 + (unsigned char)(c & 0x3F); \ |
| 267463 | | - } \ |
| 267464 | | -} |
| 267465 | | - |
| 267466 | | -#endif /* ifndef SQLITE_AMALGAMATION */ |
| 267467 | | - |
| 267468 | | -#define FTS5_SKIP_UTF8(zIn) { \ |
| 267469 | | - if( ((unsigned char)(*(zIn++)))>=0xc0 ){ \ |
| 267470 | | - while( (((unsigned char)*zIn) & 0xc0)==0x80 ){ zIn++; } \ |
| 267471 | | - } \ |
| 267781 | + || (c&0xFFFFF800)==0xD800 \ |
| 267782 | + || (c&0xFFFFFFFE)==0xFFFE ){ c = 0xFFFD; } \ |
| 267783 | + } |
| 267784 | + |
| 267785 | + |
| 267786 | +#define FTS5_WRITE_UTF8(zOut, c) { \ |
| 267787 | + if( c<0x00080 ){ \ |
| 267788 | + *zOut++ = (unsigned char)(c&0xFF); \ |
| 267789 | + } \ |
| 267790 | + else if( c<0x00800 ){ \ |
| 267791 | + *zOut++ = 0xC0 + (unsigned char)((c>>6)&0x1F); \ |
| 267792 | + *zOut++ = 0x80 + (unsigned char)(c & 0x3F); \ |
| 267793 | + } \ |
| 267794 | + else if( c<0x10000 ){ \ |
| 267795 | + *zOut++ = 0xE0 + (unsigned char)((c>>12)&0x0F); \ |
| 267796 | + *zOut++ = 0x80 + (unsigned char)((c>>6) & 0x3F); \ |
| 267797 | + *zOut++ = 0x80 + (unsigned char)(c & 0x3F); \ |
| 267798 | + }else{ \ |
| 267799 | + *zOut++ = 0xF0 + (unsigned char)((c>>18) & 0x07); \ |
| 267800 | + *zOut++ = 0x80 + (unsigned char)((c>>12) & 0x3F); \ |
| 267801 | + *zOut++ = 0x80 + (unsigned char)((c>>6) & 0x3F); \ |
| 267802 | + *zOut++ = 0x80 + (unsigned char)(c & 0x3F); \ |
| 267803 | + } \ |
| 267804 | +} |
| 267805 | + |
| 267806 | +#define FTS5_SKIP_UTF8(zIn) { \ |
| 267807 | + if( ((unsigned char)(*(zIn++)))>=0xc0 ){ \ |
| 267808 | + while( (((unsigned char)*zIn) & 0xc0)==0x80 ){zIn++;} \ |
| 267809 | + } \ |
| 267472 | 267810 | } |
| 267473 | 267811 | |
| 267474 | 267812 | typedef struct Unicode61Tokenizer Unicode61Tokenizer; |
| 267475 | 267813 | struct Unicode61Tokenizer { |
| 267476 | 267814 | unsigned char aTokenChar[128]; /* ASCII range token characters */ |
| | @@ -267505,11 +267843,11 @@ |
| 267505 | 267843 | const unsigned char *zCsr = (const unsigned char*)z; |
| 267506 | 267844 | const unsigned char *zTerm = (const unsigned char*)&z[n]; |
| 267507 | 267845 | while( zCsr<zTerm ){ |
| 267508 | 267846 | u32 iCode; |
| 267509 | 267847 | int bToken; |
| 267510 | | - READ_UTF8(zCsr, zTerm, iCode); |
| 267848 | + FTS5_READ_UTF8(zCsr, zTerm, iCode); |
| 267511 | 267849 | if( iCode<128 ){ |
| 267512 | 267850 | p->aTokenChar[iCode] = (unsigned char)bTokenChars; |
| 267513 | 267851 | }else{ |
| 267514 | 267852 | bToken = p->aCategory[sqlite3Fts5UnicodeCategory(iCode)]; |
| 267515 | 267853 | assert( (bToken==0 || bToken==1) ); |
| | @@ -267709,11 +268047,11 @@ |
| 267709 | 268047 | if( zCsr>=zTerm ) goto tokenize_done; |
| 267710 | 268048 | if( *zCsr & 0x80 ) { |
| 267711 | 268049 | /* A character outside of the ascii range. Skip past it if it is |
| 267712 | 268050 | ** a separator character. Or break out of the loop if it is not. */ |
| 267713 | 268051 | is = zCsr - (unsigned char*)pText; |
| 267714 | | - READ_UTF8(zCsr, zTerm, iCode); |
| 268052 | + FTS5_READ_UTF8(zCsr, zTerm, iCode); |
| 267715 | 268053 | if( fts5UnicodeIsAlnum(p, iCode) ){ |
| 267716 | 268054 | goto non_ascii_tokenchar; |
| 267717 | 268055 | } |
| 267718 | 268056 | }else{ |
| 267719 | 268057 | if( a[*zCsr] ){ |
| | @@ -267745,15 +268083,15 @@ |
| 267745 | 268083 | } |
| 267746 | 268084 | |
| 267747 | 268085 | if( *zCsr & 0x80 ){ |
| 267748 | 268086 | /* An non-ascii-range character. Fold it into the output buffer if |
| 267749 | 268087 | ** it is a token character, or break out of the loop if it is not. */ |
| 267750 | | - READ_UTF8(zCsr, zTerm, iCode); |
| 268088 | + FTS5_READ_UTF8(zCsr, zTerm, iCode); |
| 267751 | 268089 | if( fts5UnicodeIsAlnum(p,iCode)||sqlite3Fts5UnicodeIsdiacritic(iCode) ){ |
| 267752 | 268090 | non_ascii_tokenchar: |
| 267753 | 268091 | iCode = sqlite3Fts5UnicodeFold(iCode, p->eRemoveDiacritic); |
| 267754 | | - if( iCode ) WRITE_UTF8(zOut, iCode); |
| 268092 | + if( iCode ) FTS5_WRITE_UTF8(zOut, iCode); |
| 267755 | 268093 | }else{ |
| 267756 | 268094 | break; |
| 267757 | 268095 | } |
| 267758 | 268096 | }else if( a[*zCsr]==0 ){ |
| 267759 | 268097 | /* An ascii-range separator character. End of token. */ |
| | @@ -268604,14 +268942,14 @@ |
| 268604 | 268942 | /* Populate aBuf[] with the characters for the first trigram. */ |
| 268605 | 268943 | for(ii=0; ii<3; ii++){ |
| 268606 | 268944 | do { |
| 268607 | 268945 | aStart[ii] = zIn - (const unsigned char*)pText; |
| 268608 | 268946 | if( zIn>=zEof ) return SQLITE_OK; |
| 268609 | | - READ_UTF8(zIn, zEof, iCode); |
| 268947 | + FTS5_READ_UTF8(zIn, zEof, iCode); |
| 268610 | 268948 | if( p->bFold ) iCode = sqlite3Fts5UnicodeFold(iCode, p->iFoldParam); |
| 268611 | 268949 | }while( iCode==0 ); |
| 268612 | | - WRITE_UTF8(zOut, iCode); |
| 268950 | + FTS5_WRITE_UTF8(zOut, iCode); |
| 268613 | 268951 | } |
| 268614 | 268952 | |
| 268615 | 268953 | /* At the start of each iteration of this loop: |
| 268616 | 268954 | ** |
| 268617 | 268955 | ** aBuf: Contains 3 characters. The 3 characters of the next trigram. |
| | @@ -268629,11 +268967,11 @@ |
| 268629 | 268967 | iNext = zIn - (const unsigned char*)pText; |
| 268630 | 268968 | if( zIn>=zEof ){ |
| 268631 | 268969 | iCode = 0; |
| 268632 | 268970 | break; |
| 268633 | 268971 | } |
| 268634 | | - READ_UTF8(zIn, zEof, iCode); |
| 268972 | + FTS5_READ_UTF8(zIn, zEof, iCode); |
| 268635 | 268973 | if( p->bFold ) iCode = sqlite3Fts5UnicodeFold(iCode, p->iFoldParam); |
| 268636 | 268974 | }while( iCode==0 ); |
| 268637 | 268975 | |
| 268638 | 268976 | /* Pass the current trigram back to fts5 */ |
| 268639 | 268977 | rc = xToken(pCtx, 0, aBuf, zOut-aBuf, aStart[0], iNext); |
| | @@ -268643,11 +268981,11 @@ |
| 268643 | 268981 | ** with codepoint iCode. */ |
| 268644 | 268982 | z1 = aBuf; |
| 268645 | 268983 | FTS5_SKIP_UTF8(z1); |
| 268646 | 268984 | memmove(aBuf, z1, zOut - z1); |
| 268647 | 268985 | zOut -= (z1 - aBuf); |
| 268648 | | - WRITE_UTF8(zOut, iCode); |
| 268986 | + FTS5_WRITE_UTF8(zOut, iCode); |
| 268649 | 268987 | |
| 268650 | 268988 | /* Update the aStart[] array */ |
| 268651 | 268989 | aStart[0] = aStart[1]; |
| 268652 | 268990 | aStart[1] = aStart[2]; |
| 268653 | 268991 | aStart[2] = iNext; |
| 268654 | 268992 | |