| | @@ -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 | | -** 61d9e204c5801a94811fdb0afe2c04f9814e with changes in files: |
| 21 | +** 821cc0e421bc14a68ebaee507e38a900e0c8 with changes in files: |
| 22 | 22 | ** |
| 23 | 23 | ** |
| 24 | 24 | */ |
| 25 | 25 | #ifndef SQLITE_AMALGAMATION |
| 26 | 26 | #define SQLITE_CORE 1 |
| | @@ -168,11 +168,13 @@ |
| 168 | 168 | #define SQLITE_OMIT_LOAD_EXTENSION 1 |
| 169 | 169 | #define SQLITE_ENABLE_LOCKING_STYLE 0 |
| 170 | 170 | #define HAVE_UTIME 1 |
| 171 | 171 | #else |
| 172 | 172 | /* This is not VxWorks. */ |
| 173 | | -#define OS_VXWORKS 0 |
| 173 | +#ifndef OS_VXWORKS |
| 174 | +# define OS_VXWORKS 0 |
| 175 | +#endif |
| 174 | 176 | #define HAVE_FCHOWN 1 |
| 175 | 177 | #define HAVE_READLINK 1 |
| 176 | 178 | #define HAVE_LSTAT 1 |
| 177 | 179 | #endif /* defined(_WRS_KERNEL) */ |
| 178 | 180 | |
| | @@ -465,14 +467,14 @@ |
| 465 | 467 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 466 | 468 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 467 | 469 | */ |
| 468 | 470 | #define SQLITE_VERSION "3.51.0" |
| 469 | 471 | #define SQLITE_VERSION_NUMBER 3051000 |
| 470 | | -#define SQLITE_SOURCE_ID "2025-09-10 14:28:07 61d9e204c5801a94811fdb0afe2c04f9814e08f2e141afa6dbda0fa45f026f70" |
| 472 | +#define SQLITE_SOURCE_ID "2025-09-24 19:10:58 821cc0e421bc14a68ebaee507e38a900e0c84ff6ba7ee95bf796cad387755232" |
| 471 | 473 | #define SQLITE_SCM_BRANCH "trunk" |
| 472 | 474 | #define SQLITE_SCM_TAGS "" |
| 473 | | -#define SQLITE_SCM_DATETIME "2025-09-10T14:28:07.926Z" |
| 475 | +#define SQLITE_SCM_DATETIME "2025-09-24T19:10:58.215Z" |
| 474 | 476 | |
| 475 | 477 | /* |
| 476 | 478 | ** CAPI3REF: Run-Time Library Version Numbers |
| 477 | 479 | ** KEYWORDS: sqlite3_version sqlite3_sourceid |
| 478 | 480 | ** |
| | @@ -4523,10 +4525,38 @@ |
| 4523 | 4525 | SQLITE_API const char *sqlite3_errmsg(sqlite3*); |
| 4524 | 4526 | SQLITE_API const void *sqlite3_errmsg16(sqlite3*); |
| 4525 | 4527 | SQLITE_API const char *sqlite3_errstr(int); |
| 4526 | 4528 | SQLITE_API int sqlite3_error_offset(sqlite3 *db); |
| 4527 | 4529 | |
| 4530 | +/* |
| 4531 | +** CAPI3REF: Set Error Codes And Message |
| 4532 | +** METHOD: sqlite3 |
| 4533 | +** |
| 4534 | +** Set the error code of the database handle passed as the first argument |
| 4535 | +** to errcode, and the error message to a copy of nul-terminated string |
| 4536 | +** zErrMsg. If zErrMsg is passed NULL, then the error message is set to |
| 4537 | +** the default message associated with the supplied error code. Subsequent |
| 4538 | +** calls to [sqlite3_errcode()] and [sqlite3_errmsg()] and similar will |
| 4539 | +** return the values set by this routine in place of what was previously |
| 4540 | +** set by SQLite itself. |
| 4541 | +** |
| 4542 | +** This function returns SQLITE_OK if the error code and error message are |
| 4543 | +** successfully set, SQLITE_NOMEM if an OOM occurs, and SQLITE_MISUSE if |
| 4544 | +** the database handle is NULL or invalid. |
| 4545 | +** |
| 4546 | +** The error code and message set by this routine remains in effect until |
| 4547 | +** they are changed, either by another call to this routine or until they are |
| 4548 | +** changed to by SQLite itself to reflect the result of some subsquent |
| 4549 | +** API call. |
| 4550 | +** |
| 4551 | +** This function is intended for use by SQLite extensions or wrappers. The |
| 4552 | +** idea is that an extension or wrapper can use this routine to set error |
| 4553 | +** messages and error codes and thus behave more like a core SQLite |
| 4554 | +** feature from the point of view of an application. |
| 4555 | +*/ |
| 4556 | +SQLITE_API int sqlite3_set_errmsg(sqlite3 *db, int errcode, const char *zErrMsg); |
| 4557 | + |
| 4528 | 4558 | /* |
| 4529 | 4559 | ** CAPI3REF: Prepared Statement Object |
| 4530 | 4560 | ** KEYWORDS: {prepared statement} {prepared statements} |
| 4531 | 4561 | ** |
| 4532 | 4562 | ** An instance of this object represents a single SQL statement that |
| | @@ -12662,10 +12692,19 @@ |
| 12662 | 12692 | ** CAPI3REF: Apply A Changeset To A Database |
| 12663 | 12693 | ** |
| 12664 | 12694 | ** Apply a changeset or patchset to a database. These functions attempt to |
| 12665 | 12695 | ** update the "main" database attached to handle db with the changes found in |
| 12666 | 12696 | ** the changeset passed via the second and third arguments. |
| 12697 | +** |
| 12698 | +** All changes made by these functions are enclosed in a savepoint transaction. |
| 12699 | +** If any other error (aside from a constraint failure when attempting to |
| 12700 | +** write to the target database) occurs, then the savepoint transaction is |
| 12701 | +** rolled back, restoring the target database to its original state, and an |
| 12702 | +** SQLite error code returned. Additionally, starting with version 3.51.0, |
| 12703 | +** an error code and error message that may be accessed using the |
| 12704 | +** [sqlite3_errcode()] and [sqlite3_errmsg()] APIs are left in the database |
| 12705 | +** handle. |
| 12667 | 12706 | ** |
| 12668 | 12707 | ** The fourth argument (xFilter) passed to these functions is the "filter |
| 12669 | 12708 | ** callback". This may be passed NULL, in which case all changes in the |
| 12670 | 12709 | ** changeset are applied to the database. For sqlite3changeset_apply() and |
| 12671 | 12710 | ** sqlite3_changeset_apply_v2(), if it is not NULL, then it is invoked once |
| | @@ -12800,16 +12839,10 @@ |
| 12800 | 12839 | ** It is safe to execute SQL statements, including those that write to the |
| 12801 | 12840 | ** table that the callback related to, from within the xConflict callback. |
| 12802 | 12841 | ** This can be used to further customize the application's conflict |
| 12803 | 12842 | ** resolution strategy. |
| 12804 | 12843 | ** |
| 12805 | | -** All changes made by these functions are enclosed in a savepoint transaction. |
| 12806 | | -** If any other error (aside from a constraint failure when attempting to |
| 12807 | | -** write to the target database) occurs, then the savepoint transaction is |
| 12808 | | -** rolled back, restoring the target database to its original state, and an |
| 12809 | | -** SQLite error code returned. |
| 12810 | | -** |
| 12811 | 12844 | ** If the output parameters (ppRebase) and (pnRebase) are non-NULL and |
| 12812 | 12845 | ** the input is a changeset (not a patchset), then sqlite3changeset_apply_v2() |
| 12813 | 12846 | ** may set (*ppRebase) to point to a "rebase" that may be used with the |
| 12814 | 12847 | ** sqlite3_rebaser APIs buffer before returning. In this case (*pnRebase) |
| 12815 | 12848 | ** is set to the size of the buffer in bytes. It is the responsibility of the |
| | @@ -18155,11 +18188,11 @@ |
| 18155 | 18188 | struct sqlite3InitInfo { /* Information used during initialization */ |
| 18156 | 18189 | Pgno newTnum; /* Rootpage of table being initialized */ |
| 18157 | 18190 | u8 iDb; /* Which db file is being initialized */ |
| 18158 | 18191 | u8 busy; /* TRUE if currently initializing */ |
| 18159 | 18192 | unsigned orphanTrigger : 1; /* Last statement is orphaned TEMP trigger */ |
| 18160 | | - unsigned imposterTable : 1; /* Building an imposter table */ |
| 18193 | + unsigned imposterTable : 2; /* Building an imposter table */ |
| 18161 | 18194 | unsigned reopenMemdb : 1; /* ATTACH is really a reopen using MemDB */ |
| 18162 | 18195 | const char **azInit; /* "type", "name", and "tbl_name" columns */ |
| 18163 | 18196 | } init; |
| 18164 | 18197 | int nVdbeActive; /* Number of VDBEs currently running */ |
| 18165 | 18198 | int nVdbeRead; /* Number of active VDBEs that read or write */ |
| | @@ -18948,10 +18981,11 @@ |
| 18948 | 18981 | #define TF_Shadow 0x00001000 /* True for a shadow table */ |
| 18949 | 18982 | #define TF_HasStat4 0x00002000 /* STAT4 info available for this table */ |
| 18950 | 18983 | #define TF_Ephemeral 0x00004000 /* An ephemeral table */ |
| 18951 | 18984 | #define TF_Eponymous 0x00008000 /* An eponymous virtual table */ |
| 18952 | 18985 | #define TF_Strict 0x00010000 /* STRICT mode */ |
| 18986 | +#define TF_Imposter 0x00020000 /* An imposter table */ |
| 18953 | 18987 | |
| 18954 | 18988 | /* |
| 18955 | 18989 | ** Allowed values for Table.eTabType |
| 18956 | 18990 | */ |
| 18957 | 18991 | #define TABTYP_NORM 0 /* Ordinary table */ |
| | @@ -25009,10 +25043,14 @@ |
| 25009 | 25043 | if( getDigits(zDate, "20b:20e", &nHr, &nMn)!=2 ){ |
| 25010 | 25044 | return 1; |
| 25011 | 25045 | } |
| 25012 | 25046 | zDate += 5; |
| 25013 | 25047 | p->tz = sgn*(nMn + nHr*60); |
| 25048 | + if( p->tz==0 ){ /* Forum post 2025-09-17T10:12:14z */ |
| 25049 | + p->isLocal = 0; |
| 25050 | + p->isUtc = 1; |
| 25051 | + } |
| 25014 | 25052 | zulu_time: |
| 25015 | 25053 | while( sqlite3Isspace(*zDate) ){ zDate++; } |
| 25016 | 25054 | return *zDate!=0; |
| 25017 | 25055 | } |
| 25018 | 25056 | |
| | @@ -38168,11 +38206,11 @@ |
| 38168 | 38206 | static int kvstorageDelete(const char*, const char *zKey); |
| 38169 | 38207 | static int kvstorageRead(const char*, const char *zKey, char *zBuf, int nBuf); |
| 38170 | 38208 | #define KVSTORAGE_KEY_SZ 32 |
| 38171 | 38209 | |
| 38172 | 38210 | /* Expand the key name with an appropriate prefix and put the result |
| 38173 | | -** zKeyOut[]. The zKeyOut[] buffer is assumed to hold at least |
| 38211 | +** in zKeyOut[]. The zKeyOut[] buffer is assumed to hold at least |
| 38174 | 38212 | ** KVSTORAGE_KEY_SZ bytes. |
| 38175 | 38213 | */ |
| 38176 | 38214 | static void kvstorageMakeKey( |
| 38177 | 38215 | const char *zClass, |
| 38178 | 38216 | const char *zKeyIn, |
| | @@ -38227,14 +38265,16 @@ |
| 38227 | 38265 | ** enough to hold it all. The value put into zBuf must always be zero |
| 38228 | 38266 | ** terminated, even if it gets truncated because nBuf is not large enough. |
| 38229 | 38267 | ** |
| 38230 | 38268 | ** Return the total number of bytes in the data, without truncation, and |
| 38231 | 38269 | ** not counting the final zero terminator. Return -1 if the key does |
| 38232 | | -** not exist. |
| 38270 | +** not exist or its key cannot be read. |
| 38233 | 38271 | ** |
| 38234 | | -** If nBuf<=0 then this routine simply returns the size of the data without |
| 38235 | | -** actually reading it. |
| 38272 | +** If nBuf<=0 then this routine simply returns the size of the data |
| 38273 | +** without actually reading it. Similarly, if nBuf==1 then it |
| 38274 | +** zero-terminates zBuf at zBuf[0] and returns the size of the data |
| 38275 | +** without reading it. |
| 38236 | 38276 | */ |
| 38237 | 38277 | static int kvstorageRead( |
| 38238 | 38278 | const char *zClass, |
| 38239 | 38279 | const char *zKey, |
| 38240 | 38280 | char *zBuf, |
| | @@ -38279,15 +38319,13 @@ |
| 38279 | 38319 | /* |
| 38280 | 38320 | ** An internal level of indirection which enables us to replace the |
| 38281 | 38321 | ** kvvfs i/o methods with JavaScript implementations in WASM builds. |
| 38282 | 38322 | ** Maintenance reminder: if this struct changes in any way, the JSON |
| 38283 | 38323 | ** rendering of its structure must be updated in |
| 38284 | | -** sqlite3_wasm_enum_json(). There are no binary compatibility |
| 38285 | | -** concerns, so it does not need an iVersion member. This file is |
| 38286 | | -** necessarily always compiled together with sqlite3_wasm_enum_json(), |
| 38287 | | -** and JS code dynamically creates the mapping of members based on |
| 38288 | | -** that JSON description. |
| 38324 | +** sqlite3-wasm.c:sqlite3__wasm_enum_json(). There are no binary |
| 38325 | +** compatibility concerns, so it does not need an iVersion |
| 38326 | +** member. |
| 38289 | 38327 | */ |
| 38290 | 38328 | typedef struct sqlite3_kvvfs_methods sqlite3_kvvfs_methods; |
| 38291 | 38329 | struct sqlite3_kvvfs_methods { |
| 38292 | 38330 | int (*xRead)(const char *zClass, const char *zKey, char *zBuf, int nBuf); |
| 38293 | 38331 | int (*xWrite)(const char *zClass, const char *zKey, const char *zData); |
| | @@ -38300,12 +38338,12 @@ |
| 38300 | 38338 | ** for JavaScript-side implementations in WASM builds. In such builds |
| 38301 | 38339 | ** it cannot be const, but in native builds it should be so that |
| 38302 | 38340 | ** the compiler can hopefully optimize this level of indirection out. |
| 38303 | 38341 | ** That said, kvvfs is intended primarily for use in WASM builds. |
| 38304 | 38342 | ** |
| 38305 | | -** Note that this is not explicitly flagged as static because the |
| 38306 | | -** amalgamation build will tag it with SQLITE_PRIVATE. |
| 38343 | +** This is not explicitly flagged as static because the amalgamation |
| 38344 | +** build will tag it with SQLITE_PRIVATE. |
| 38307 | 38345 | */ |
| 38308 | 38346 | #ifndef SQLITE_WASM |
| 38309 | 38347 | const |
| 38310 | 38348 | #endif |
| 38311 | 38349 | SQLITE_PRIVATE sqlite3_kvvfs_methods sqlite3KvvfsMethods = { |
| | @@ -39736,13 +39774,12 @@ |
| 39736 | 39774 | return fd; |
| 39737 | 39775 | } |
| 39738 | 39776 | |
| 39739 | 39777 | /* |
| 39740 | 39778 | ** Helper functions to obtain and relinquish the global mutex. The |
| 39741 | | -** global mutex is used to protect the unixInodeInfo and |
| 39742 | | -** vxworksFileId objects used by this file, all of which may be |
| 39743 | | -** shared by multiple threads. |
| 39779 | +** global mutex is used to protect the unixInodeInfo objects used by |
| 39780 | +** this file, all of which may be shared by multiple threads. |
| 39744 | 39781 | ** |
| 39745 | 39782 | ** Function unixMutexHeld() is used to assert() that the global mutex |
| 39746 | 39783 | ** is held when required. This function is only used as part of assert() |
| 39747 | 39784 | ** statements. e.g. |
| 39748 | 39785 | ** |
| | @@ -39940,10 +39977,11 @@ |
| 39940 | 39977 | /* |
| 39941 | 39978 | ** All unique filenames are held on a linked list headed by this |
| 39942 | 39979 | ** variable: |
| 39943 | 39980 | */ |
| 39944 | 39981 | static struct vxworksFileId *vxworksFileList = 0; |
| 39982 | +static sqlite3_mutex *vxworksMutex = 0; |
| 39945 | 39983 | |
| 39946 | 39984 | /* |
| 39947 | 39985 | ** Simplify a filename into its canonical form |
| 39948 | 39986 | ** by making the following changes: |
| 39949 | 39987 | ** |
| | @@ -40005,47 +40043,47 @@ |
| 40005 | 40043 | |
| 40006 | 40044 | /* Search for an existing entry that matching the canonical name. |
| 40007 | 40045 | ** If found, increment the reference count and return a pointer to |
| 40008 | 40046 | ** the existing file ID. |
| 40009 | 40047 | */ |
| 40010 | | - unixEnterMutex(); |
| 40048 | + sqlite3_mutex_enter(vxworksMutex); |
| 40011 | 40049 | for(pCandidate=vxworksFileList; pCandidate; pCandidate=pCandidate->pNext){ |
| 40012 | 40050 | if( pCandidate->nName==n |
| 40013 | 40051 | && memcmp(pCandidate->zCanonicalName, pNew->zCanonicalName, n)==0 |
| 40014 | 40052 | ){ |
| 40015 | 40053 | sqlite3_free(pNew); |
| 40016 | 40054 | pCandidate->nRef++; |
| 40017 | | - unixLeaveMutex(); |
| 40055 | + sqlite3_mutex_leave(vxworksMutex); |
| 40018 | 40056 | return pCandidate; |
| 40019 | 40057 | } |
| 40020 | 40058 | } |
| 40021 | 40059 | |
| 40022 | 40060 | /* No match was found. We will make a new file ID */ |
| 40023 | 40061 | pNew->nRef = 1; |
| 40024 | 40062 | pNew->nName = n; |
| 40025 | 40063 | pNew->pNext = vxworksFileList; |
| 40026 | 40064 | vxworksFileList = pNew; |
| 40027 | | - unixLeaveMutex(); |
| 40065 | + sqlite3_mutex_leave(vxworksMutex); |
| 40028 | 40066 | return pNew; |
| 40029 | 40067 | } |
| 40030 | 40068 | |
| 40031 | 40069 | /* |
| 40032 | 40070 | ** Decrement the reference count on a vxworksFileId object. Free |
| 40033 | 40071 | ** the object when the reference count reaches zero. |
| 40034 | 40072 | */ |
| 40035 | 40073 | static void vxworksReleaseFileId(struct vxworksFileId *pId){ |
| 40036 | | - unixEnterMutex(); |
| 40074 | + sqlite3_mutex_enter(vxworksMutex); |
| 40037 | 40075 | assert( pId->nRef>0 ); |
| 40038 | 40076 | pId->nRef--; |
| 40039 | 40077 | if( pId->nRef==0 ){ |
| 40040 | 40078 | struct vxworksFileId **pp; |
| 40041 | 40079 | for(pp=&vxworksFileList; *pp && *pp!=pId; pp = &((*pp)->pNext)){} |
| 40042 | 40080 | assert( *pp==pId ); |
| 40043 | 40081 | *pp = pId->pNext; |
| 40044 | 40082 | sqlite3_free(pId); |
| 40045 | 40083 | } |
| 40046 | | - unixLeaveMutex(); |
| 40084 | + sqlite3_mutex_leave(vxworksMutex); |
| 40047 | 40085 | } |
| 40048 | 40086 | #endif /* OS_VXWORKS */ |
| 40049 | 40087 | /*************** End of Unique File ID Utility Used By VxWorks **************** |
| 40050 | 40088 | ******************************************************************************/ |
| 40051 | 40089 | |
| | @@ -44958,14 +44996,21 @@ |
| 44958 | 44996 | #endif |
| 44959 | 44997 | |
| 44960 | 44998 | storeLastErrno(pNew, 0); |
| 44961 | 44999 | #if OS_VXWORKS |
| 44962 | 45000 | if( rc!=SQLITE_OK ){ |
| 44963 | | - if( h>=0 ) robust_close(pNew, h, __LINE__); |
| 44964 | | - h = -1; |
| 44965 | | - osUnlink(zFilename); |
| 44966 | | - pNew->ctrlFlags |= UNIXFILE_DELETE; |
| 45001 | + if( h>=0 ){ |
| 45002 | + robust_close(pNew, h, __LINE__); |
| 45003 | + h = -1; |
| 45004 | + } |
| 45005 | + if( pNew->ctrlFlags & UNIXFILE_DELETE ){ |
| 45006 | + osUnlink(zFilename); |
| 45007 | + } |
| 45008 | + if( pNew->pId ){ |
| 45009 | + vxworksReleaseFileId(pNew->pId); |
| 45010 | + pNew->pId = 0; |
| 45011 | + } |
| 44967 | 45012 | } |
| 44968 | 45013 | #endif |
| 44969 | 45014 | if( rc!=SQLITE_OK ){ |
| 44970 | 45015 | if( h>=0 ) robust_close(pNew, h, __LINE__); |
| 44971 | 45016 | }else{ |
| | @@ -45005,10 +45050,13 @@ |
| 45005 | 45050 | struct stat buf; |
| 45006 | 45051 | const char *zDir = sqlite3_temp_directory; |
| 45007 | 45052 | |
| 45008 | 45053 | while(1){ |
| 45009 | 45054 | if( zDir!=0 |
| 45055 | +#if OS_VXWORKS |
| 45056 | + && zDir[0]=='/' |
| 45057 | +#endif |
| 45010 | 45058 | && osStat(zDir, &buf)==0 |
| 45011 | 45059 | && S_ISDIR(buf.st_mode) |
| 45012 | 45060 | && osAccess(zDir, 03)==0 |
| 45013 | 45061 | ){ |
| 45014 | 45062 | return zDir; |
| | @@ -45318,10 +45366,16 @@ |
| 45318 | 45366 | assert( eType==SQLITE_OPEN_MAIN_DB || eType==SQLITE_OPEN_TEMP_DB |
| 45319 | 45367 | || eType==SQLITE_OPEN_MAIN_JOURNAL || eType==SQLITE_OPEN_TEMP_JOURNAL |
| 45320 | 45368 | || eType==SQLITE_OPEN_SUBJOURNAL || eType==SQLITE_OPEN_SUPER_JOURNAL |
| 45321 | 45369 | || eType==SQLITE_OPEN_TRANSIENT_DB || eType==SQLITE_OPEN_WAL |
| 45322 | 45370 | ); |
| 45371 | + |
| 45372 | +#if OS_VXWORKS |
| 45373 | + /* The file-ID mechanism used in Vxworks requires that all pathnames |
| 45374 | + ** provided to unixOpen must be absolute pathnames. */ |
| 45375 | + if( zPath!=0 && zPath[0]!='/' ){ return SQLITE_CANTOPEN; } |
| 45376 | +#endif |
| 45323 | 45377 | |
| 45324 | 45378 | /* Detect a pid change and reset the PRNG. There is a race condition |
| 45325 | 45379 | ** here such that two or more threads all trying to open databases at |
| 45326 | 45380 | ** the same instant might all reset the PRNG. But multiple resets |
| 45327 | 45381 | ** are harmless. |
| | @@ -45519,12 +45573,15 @@ |
| 45519 | 45573 | goto open_finished; |
| 45520 | 45574 | } |
| 45521 | 45575 | } |
| 45522 | 45576 | #endif |
| 45523 | 45577 | |
| 45524 | | - assert( zPath==0 || zPath[0]=='/' |
| 45525 | | - || eType==SQLITE_OPEN_SUPER_JOURNAL || eType==SQLITE_OPEN_MAIN_JOURNAL |
| 45578 | + assert( zPath==0 |
| 45579 | + || zPath[0]=='/' |
| 45580 | + || eType==SQLITE_OPEN_SUPER_JOURNAL |
| 45581 | + || eType==SQLITE_OPEN_MAIN_JOURNAL |
| 45582 | + || eType==SQLITE_OPEN_TEMP_JOURNAL |
| 45526 | 45583 | ); |
| 45527 | 45584 | rc = fillInUnixFile(pVfs, fd, pFile, zPath, ctrlFlags); |
| 45528 | 45585 | |
| 45529 | 45586 | open_finished: |
| 45530 | 45587 | if( rc!=SQLITE_OK ){ |
| | @@ -47249,10 +47306,13 @@ |
| 47249 | 47306 | } |
| 47250 | 47307 | #ifdef SQLITE_OS_KV_OPTIONAL |
| 47251 | 47308 | sqlite3KvvfsInit(); |
| 47252 | 47309 | #endif |
| 47253 | 47310 | unixBigLock = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1); |
| 47311 | +#if OS_VXWORKS |
| 47312 | + vxworksMutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS2); |
| 47313 | +#endif |
| 47254 | 47314 | |
| 47255 | 47315 | #ifndef SQLITE_OMIT_WAL |
| 47256 | 47316 | /* Validate lock assumptions */ |
| 47257 | 47317 | assert( SQLITE_SHM_NLOCK==8 ); /* Number of available locks */ |
| 47258 | 47318 | assert( UNIX_SHM_BASE==120 ); /* Start of locking area */ |
| | @@ -47283,10 +47343,13 @@ |
| 47283 | 47343 | ** to release dynamically allocated objects. But not on unix. |
| 47284 | 47344 | ** This routine is a no-op for unix. |
| 47285 | 47345 | */ |
| 47286 | 47346 | SQLITE_API int sqlite3_os_end(void){ |
| 47287 | 47347 | unixBigLock = 0; |
| 47348 | +#if OS_VXWORKS |
| 47349 | + vxworksMutex = 0; |
| 47350 | +#endif |
| 47288 | 47351 | return SQLITE_OK; |
| 47289 | 47352 | } |
| 47290 | 47353 | |
| 47291 | 47354 | #endif /* SQLITE_OS_UNIX */ |
| 47292 | 47355 | |
| | @@ -62006,18 +62069,31 @@ |
| 62006 | 62069 | SQLITE_PRIVATE void sqlite3PagerSetFlags( |
| 62007 | 62070 | Pager *pPager, /* The pager to set safety level for */ |
| 62008 | 62071 | unsigned pgFlags /* Various flags */ |
| 62009 | 62072 | ){ |
| 62010 | 62073 | unsigned level = pgFlags & PAGER_SYNCHRONOUS_MASK; |
| 62011 | | - if( pPager->tempFile ){ |
| 62074 | + if( pPager->tempFile || level==PAGER_SYNCHRONOUS_OFF ){ |
| 62012 | 62075 | pPager->noSync = 1; |
| 62013 | 62076 | pPager->fullSync = 0; |
| 62014 | 62077 | pPager->extraSync = 0; |
| 62015 | 62078 | }else{ |
| 62016 | | - pPager->noSync = level==PAGER_SYNCHRONOUS_OFF ?1:0; |
| 62079 | + pPager->noSync = 0; |
| 62017 | 62080 | pPager->fullSync = level>=PAGER_SYNCHRONOUS_FULL ?1:0; |
| 62018 | | - pPager->extraSync = level==PAGER_SYNCHRONOUS_EXTRA ?1:0; |
| 62081 | + |
| 62082 | + /* Set Pager.extraSync if "PRAGMA synchronous=EXTRA" is requested, or |
| 62083 | + ** if the file-system supports F2FS style atomic writes. If this flag |
| 62084 | + ** is set, SQLite syncs the directory to disk immediately after deleting |
| 62085 | + ** a journal file in "PRAGMA journal_mode=DELETE" mode. */ |
| 62086 | + if( level==PAGER_SYNCHRONOUS_EXTRA |
| 62087 | +#ifdef SQLITE_ENABLE_BATCH_ATOMIC_WRITE |
| 62088 | + || (sqlite3OsDeviceCharacteristics(pPager->fd) & SQLITE_IOCAP_BATCH_ATOMIC) |
| 62089 | +#endif |
| 62090 | + ){ |
| 62091 | + pPager->extraSync = 1; |
| 62092 | + }else{ |
| 62093 | + pPager->extraSync = 0; |
| 62094 | + } |
| 62019 | 62095 | } |
| 62020 | 62096 | if( pPager->noSync ){ |
| 62021 | 62097 | pPager->syncFlags = 0; |
| 62022 | 62098 | }else if( pgFlags & PAGER_FULLFSYNC ){ |
| 62023 | 62099 | pPager->syncFlags = SQLITE_SYNC_FULL; |
| | @@ -113289,13 +113365,12 @@ |
| 113289 | 113365 | } |
| 113290 | 113366 | r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, pFree1); |
| 113291 | 113367 | if( addrIsNull==0 ){ |
| 113292 | 113368 | /* |
| 113293 | 113369 | ** If the right operand contains a subquery and the left operand does not |
| 113294 | | - ** and the left operand might be NULL, then check the left operand do |
| 113295 | | - ** an IsNull check on the left operand before computing the right |
| 113296 | | - ** operand. |
| 113370 | + ** and the left operand might be NULL, then do an IsNull check |
| 113371 | + ** check on the left operand before computing the right operand. |
| 113297 | 113372 | */ |
| 113298 | 113373 | if( ExprHasProperty(pExpr->pRight, EP_Subquery) |
| 113299 | 113374 | && sqlite3ExprCanBeNull(pExpr->pLeft) |
| 113300 | 113375 | ){ |
| 113301 | 113376 | addrIsNull = sqlite3VdbeAddOp1(v, OP_IsNull, r1); |
| | @@ -115660,10 +115735,82 @@ |
| 115660 | 115735 | } |
| 115661 | 115736 | } |
| 115662 | 115737 | return 0; |
| 115663 | 115738 | } |
| 115664 | 115739 | |
| 115740 | +/* |
| 115741 | +** Generate code that evaluates an AND or OR operator leaving a |
| 115742 | +** boolean result in a register. pExpr is the AND/OR expression. |
| 115743 | +** Store the result in the "target" register. Use short-circuit |
| 115744 | +** evaluation to avoid computing both operands, if possible. |
| 115745 | +** |
| 115746 | +** The code generated might require the use of a temporary register. |
| 115747 | +** If it does, then write the number of that temporary register |
| 115748 | +** into *pTmpReg. If not, leave *pTmpReg unchanged. |
| 115749 | +*/ |
| 115750 | +static SQLITE_NOINLINE int exprCodeTargetAndOr( |
| 115751 | + Parse *pParse, /* Parsing context */ |
| 115752 | + Expr *pExpr, /* AND or OR expression to be coded */ |
| 115753 | + int target, /* Put result in this register, guaranteed */ |
| 115754 | + int *pTmpReg /* Write a temporary register here */ |
| 115755 | +){ |
| 115756 | + int op; /* The opcode. TK_AND or TK_OR */ |
| 115757 | + int skipOp; /* Opcode for the branch that skips one operand */ |
| 115758 | + int addrSkip; /* Branch instruction that skips one of the operands */ |
| 115759 | + int regSS = 0; /* Register holding computed operand when other omitted */ |
| 115760 | + int r1, r2; /* Registers for left and right operands, respectively */ |
| 115761 | + Expr *pAlt; /* Alternative, simplified expression */ |
| 115762 | + Vdbe *v; /* statement being coded */ |
| 115763 | + |
| 115764 | + assert( pExpr!=0 ); |
| 115765 | + op = pExpr->op; |
| 115766 | + assert( op==TK_AND || op==TK_OR ); |
| 115767 | + assert( TK_AND==OP_And ); testcase( op==TK_AND ); |
| 115768 | + assert( TK_OR==OP_Or ); testcase( op==TK_OR ); |
| 115769 | + pAlt = sqlite3ExprSimplifiedAndOr(pExpr); |
| 115770 | + if( pAlt!=pExpr ){ |
| 115771 | + return sqlite3ExprCodeTarget(pParse, pAlt, target); |
| 115772 | + } |
| 115773 | + assert( pParse->pVdbe!=0 ); |
| 115774 | + v = pParse->pVdbe; |
| 115775 | + skipOp = op==TK_AND ? OP_IfNot : OP_If; |
| 115776 | + if( exprEvalRhsFirst(pExpr) ){ |
| 115777 | + /* Compute the right operand first. Skip the computation of the left |
| 115778 | + ** operand if the right operand fully determines the result */ |
| 115779 | + r2 = regSS = sqlite3ExprCodeTarget(pParse, pExpr->pRight, target); |
| 115780 | + addrSkip = sqlite3VdbeAddOp1(v, skipOp, r2); |
| 115781 | + VdbeComment((v, "skip left operand")); |
| 115782 | + VdbeCoverage(v); |
| 115783 | + r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, pTmpReg); |
| 115784 | + }else{ |
| 115785 | + /* Compute the left operand first */ |
| 115786 | + r1 = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target); |
| 115787 | + if( ExprHasProperty(pExpr->pRight, EP_Subquery) ){ |
| 115788 | + /* Skip over the computation of the right operand if the right |
| 115789 | + ** operand is a subquery and the left operand completely determines |
| 115790 | + ** the result */ |
| 115791 | + regSS = r1; |
| 115792 | + addrSkip = sqlite3VdbeAddOp1(v, skipOp, r1); |
| 115793 | + VdbeComment((v, "skip right operand")); |
| 115794 | + VdbeCoverage(v); |
| 115795 | + }else{ |
| 115796 | + addrSkip = regSS = 0; |
| 115797 | + } |
| 115798 | + r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, pTmpReg); |
| 115799 | + } |
| 115800 | + sqlite3VdbeAddOp3(v, op, r2, r1, target); |
| 115801 | + testcase( (*pTmpReg)==0 ); |
| 115802 | + if( addrSkip ){ |
| 115803 | + sqlite3VdbeAddOp2(v, OP_Goto, 0, sqlite3VdbeCurrentAddr(v)+2); |
| 115804 | + sqlite3VdbeJumpHere(v, addrSkip); |
| 115805 | + sqlite3VdbeAddOp3(v, OP_Or, regSS, regSS, target); |
| 115806 | + VdbeComment((v, "short-circut value")); |
| 115807 | + } |
| 115808 | + return target; |
| 115809 | +} |
| 115810 | + |
| 115811 | + |
| 115665 | 115812 | |
| 115666 | 115813 | /* |
| 115667 | 115814 | ** Generate code into the current Vdbe to evaluate the given |
| 115668 | 115815 | ** expression. Attempt to store the results in register "target". |
| 115669 | 115816 | ** Return the register where results are stored. |
| | @@ -115948,16 +116095,18 @@ |
| 115948 | 116095 | sqlite3VdbeAddOp2(v, OP_Null, 0, inReg); |
| 115949 | 116096 | } |
| 115950 | 116097 | } |
| 115951 | 116098 | testcase( regFree1==0 ); |
| 115952 | 116099 | testcase( regFree2==0 ); |
| 115953 | | - |
| 115954 | 116100 | } |
| 115955 | 116101 | break; |
| 115956 | 116102 | } |
| 115957 | 116103 | case TK_AND: |
| 115958 | | - case TK_OR: |
| 116104 | + case TK_OR: { |
| 116105 | + inReg = exprCodeTargetAndOr(pParse, pExpr, target, ®Free1); |
| 116106 | + break; |
| 116107 | + } |
| 115959 | 116108 | case TK_PLUS: |
| 115960 | 116109 | case TK_STAR: |
| 115961 | 116110 | case TK_MINUS: |
| 115962 | 116111 | case TK_REM: |
| 115963 | 116112 | case TK_BITAND: |
| | @@ -115965,12 +116114,10 @@ |
| 115965 | 116114 | case TK_SLASH: |
| 115966 | 116115 | case TK_LSHIFT: |
| 115967 | 116116 | case TK_RSHIFT: |
| 115968 | 116117 | case TK_CONCAT: { |
| 115969 | 116118 | int addrIsNull; |
| 115970 | | - assert( TK_AND==OP_And ); testcase( op==TK_AND ); |
| 115971 | | - assert( TK_OR==OP_Or ); testcase( op==TK_OR ); |
| 115972 | 116119 | assert( TK_PLUS==OP_Add ); testcase( op==TK_PLUS ); |
| 115973 | 116120 | assert( TK_MINUS==OP_Subtract ); testcase( op==TK_MINUS ); |
| 115974 | 116121 | assert( TK_REM==OP_Remainder ); testcase( op==TK_REM ); |
| 115975 | 116122 | assert( TK_BITAND==OP_BitAnd ); testcase( op==TK_BITAND ); |
| 115976 | 116123 | assert( TK_BITOR==OP_BitOr ); testcase( op==TK_BITOR ); |
| | @@ -125050,10 +125197,13 @@ |
| 125050 | 125197 | sqlite3VdbeAddOp2(v, OP_NewRowid, 0, reg1); |
| 125051 | 125198 | sqlite3VdbeAddOp4(v, OP_Blob, 6, reg3, 0, nullRow, P4_STATIC); |
| 125052 | 125199 | sqlite3VdbeAddOp3(v, OP_Insert, 0, reg3, reg1); |
| 125053 | 125200 | sqlite3VdbeChangeP5(v, OPFLAG_APPEND); |
| 125054 | 125201 | sqlite3VdbeAddOp0(v, OP_Close); |
| 125202 | + }else if( db->init.imposterTable ){ |
| 125203 | + pTable->tabFlags |= TF_Imposter; |
| 125204 | + if( db->init.imposterTable>=2 ) pTable->tabFlags |= TF_Readonly; |
| 125055 | 125205 | } |
| 125056 | 125206 | |
| 125057 | 125207 | /* Normal (non-error) return. */ |
| 125058 | 125208 | return; |
| 125059 | 125209 | |
| | @@ -139432,10 +139582,12 @@ |
| 139432 | 139582 | /* Version 3.44.0 and later */ |
| 139433 | 139583 | void *(*get_clientdata)(sqlite3*,const char*); |
| 139434 | 139584 | int (*set_clientdata)(sqlite3*, const char*, void*, void(*)(void*)); |
| 139435 | 139585 | /* Version 3.50.0 and later */ |
| 139436 | 139586 | int (*setlk_timeout)(sqlite3*,int,int); |
| 139587 | + /* Version 3.51.0 and later */ |
| 139588 | + int (*set_errmsg)(sqlite3*,int,const char*); |
| 139437 | 139589 | }; |
| 139438 | 139590 | |
| 139439 | 139591 | /* |
| 139440 | 139592 | ** This is the function signature used for all extension entry points. It |
| 139441 | 139593 | ** is also defined in the file "loadext.c". |
| | @@ -139767,10 +139919,12 @@ |
| 139767 | 139919 | /* Version 3.44.0 and later */ |
| 139768 | 139920 | #define sqlite3_get_clientdata sqlite3_api->get_clientdata |
| 139769 | 139921 | #define sqlite3_set_clientdata sqlite3_api->set_clientdata |
| 139770 | 139922 | /* Version 3.50.0 and later */ |
| 139771 | 139923 | #define sqlite3_setlk_timeout sqlite3_api->setlk_timeout |
| 139924 | +/* Version 3.51.0 and later */ |
| 139925 | +#define sqlite3_set_errmsg sqlite3_api->set_errmsg |
| 139772 | 139926 | #endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */ |
| 139773 | 139927 | |
| 139774 | 139928 | #if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) |
| 139775 | 139929 | /* This case when the file really is being compiled as a loadable |
| 139776 | 139930 | ** extension */ |
| | @@ -140290,11 +140444,13 @@ |
| 140290 | 140444 | sqlite3_stmt_explain, |
| 140291 | 140445 | /* Version 3.44.0 and later */ |
| 140292 | 140446 | sqlite3_get_clientdata, |
| 140293 | 140447 | sqlite3_set_clientdata, |
| 140294 | 140448 | /* Version 3.50.0 and later */ |
| 140295 | | - sqlite3_setlk_timeout |
| 140449 | + sqlite3_setlk_timeout, |
| 140450 | + /* Version 3.51.0 and later */ |
| 140451 | + sqlite3_set_errmsg |
| 140296 | 140452 | }; |
| 140297 | 140453 | |
| 140298 | 140454 | /* True if x is the directory separator character |
| 140299 | 140455 | */ |
| 140300 | 140456 | #if SQLITE_OS_WIN |
| | @@ -141751,10 +141907,26 @@ |
| 141751 | 141907 | addr = sqlite3VdbeAddOp3(v, OP_IfPos, 1, sqlite3VdbeCurrentAddr(v)+2, 1); |
| 141752 | 141908 | VdbeCoverage(v); |
| 141753 | 141909 | sqlite3VdbeAddOp0(v, OP_Halt); |
| 141754 | 141910 | return addr; |
| 141755 | 141911 | } |
| 141912 | + |
| 141913 | +/* |
| 141914 | +** Should table pTab be skipped when doing an integrity_check? |
| 141915 | +** Return true or false. |
| 141916 | +** |
| 141917 | +** If pObjTab is not null, the return true if pTab matches pObjTab. |
| 141918 | +** |
| 141919 | +** If pObjTab is null, then return true only if pTab is an imposter table. |
| 141920 | +*/ |
| 141921 | +static int tableSkipIntegrityCheck(const Table *pTab, const Table *pObjTab){ |
| 141922 | + if( pObjTab ){ |
| 141923 | + return pTab!=pObjTab; |
| 141924 | + }else{ |
| 141925 | + return (pTab->tabFlags & TF_Imposter)!=0; |
| 141926 | + } |
| 141927 | +} |
| 141756 | 141928 | |
| 141757 | 141929 | /* |
| 141758 | 141930 | ** Process a pragma statement. |
| 141759 | 141931 | ** |
| 141760 | 141932 | ** Pragmas are of this form: |
| | @@ -143097,11 +143269,11 @@ |
| 143097 | 143269 | pTbls = &db->aDb[i].pSchema->tblHash; |
| 143098 | 143270 | for(cnt=0, x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){ |
| 143099 | 143271 | Table *pTab = sqliteHashData(x); /* Current table */ |
| 143100 | 143272 | Index *pIdx; /* An index on pTab */ |
| 143101 | 143273 | int nIdx; /* Number of indexes on pTab */ |
| 143102 | | - if( pObjTab && pObjTab!=pTab ) continue; |
| 143274 | + if( tableSkipIntegrityCheck(pTab,pObjTab) ) continue; |
| 143103 | 143275 | if( HasRowid(pTab) ) cnt++; |
| 143104 | 143276 | for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdx++){ cnt++; } |
| 143105 | 143277 | } |
| 143106 | 143278 | if( cnt==0 ) continue; |
| 143107 | 143279 | if( pObjTab ) cnt++; |
| | @@ -143110,11 +143282,11 @@ |
| 143110 | 143282 | cnt = 0; |
| 143111 | 143283 | if( pObjTab ) aRoot[++cnt] = 0; |
| 143112 | 143284 | for(x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){ |
| 143113 | 143285 | Table *pTab = sqliteHashData(x); |
| 143114 | 143286 | Index *pIdx; |
| 143115 | | - if( pObjTab && pObjTab!=pTab ) continue; |
| 143287 | + if( tableSkipIntegrityCheck(pTab,pObjTab) ) continue; |
| 143116 | 143288 | if( HasRowid(pTab) ) aRoot[++cnt] = pTab->tnum; |
| 143117 | 143289 | for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ |
| 143118 | 143290 | aRoot[++cnt] = pIdx->tnum; |
| 143119 | 143291 | } |
| 143120 | 143292 | } |
| | @@ -143141,11 +143313,11 @@ |
| 143141 | 143313 | sqlite3VdbeLoadString(v, 2, "wrong # of entries in index "); |
| 143142 | 143314 | for(x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){ |
| 143143 | 143315 | int iTab = 0; |
| 143144 | 143316 | Table *pTab = sqliteHashData(x); |
| 143145 | 143317 | Index *pIdx; |
| 143146 | | - if( pObjTab && pObjTab!=pTab ) continue; |
| 143318 | + if( tableSkipIntegrityCheck(pTab,pObjTab) ) continue; |
| 143147 | 143319 | if( HasRowid(pTab) ){ |
| 143148 | 143320 | iTab = cnt++; |
| 143149 | 143321 | }else{ |
| 143150 | 143322 | iTab = cnt; |
| 143151 | 143323 | for(pIdx=pTab->pIndex; ALWAYS(pIdx); pIdx=pIdx->pNext){ |
| | @@ -143177,11 +143349,11 @@ |
| 143177 | 143349 | int r1 = -1; |
| 143178 | 143350 | int bStrict; /* True for a STRICT table */ |
| 143179 | 143351 | int r2; /* Previous key for WITHOUT ROWID tables */ |
| 143180 | 143352 | int mxCol; /* Maximum non-virtual column number */ |
| 143181 | 143353 | |
| 143182 | | - if( pObjTab && pObjTab!=pTab ) continue; |
| 143354 | + if( tableSkipIntegrityCheck(pTab,pObjTab) ) continue; |
| 143183 | 143355 | if( !IsOrdinaryTable(pTab) ) continue; |
| 143184 | 143356 | if( isQuick || HasRowid(pTab) ){ |
| 143185 | 143357 | pPk = 0; |
| 143186 | 143358 | r2 = 0; |
| 143187 | 143359 | }else{ |
| | @@ -143501,11 +143673,11 @@ |
| 143501 | 143673 | */ |
| 143502 | 143674 | for(x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){ |
| 143503 | 143675 | Table *pTab = sqliteHashData(x); |
| 143504 | 143676 | sqlite3_vtab *pVTab; |
| 143505 | 143677 | int a1; |
| 143506 | | - if( pObjTab && pObjTab!=pTab ) continue; |
| 143678 | + if( tableSkipIntegrityCheck(pTab,pObjTab) ) continue; |
| 143507 | 143679 | if( IsOrdinaryTable(pTab) ) continue; |
| 143508 | 143680 | if( !IsVirtual(pTab) ) continue; |
| 143509 | 143681 | if( pTab->nCol<=0 ){ |
| 143510 | 143682 | const char *zMod = pTab->u.vtab.azArg[0]; |
| 143511 | 143683 | if( sqlite3HashFind(&db->aModule, zMod)==0 ) continue; |
| | @@ -170516,10 +170688,14 @@ |
| 170516 | 170688 | if( pLoop->wsFlags & WHERE_VIRTUALTABLE ){ |
| 170517 | 170689 | if( pLoop->u.vtab.isOrdered |
| 170518 | 170690 | && ((wctrlFlags&(WHERE_DISTINCTBY|WHERE_SORTBYGROUP))!=WHERE_DISTINCTBY) |
| 170519 | 170691 | ){ |
| 170520 | 170692 | obSat = obDone; |
| 170693 | + }else{ |
| 170694 | + /* No further ORDER BY terms may be matched. So this call should |
| 170695 | + ** return >=0, not -1. Clear isOrderDistinct to ensure it does so. */ |
| 170696 | + isOrderDistinct = 0; |
| 170521 | 170697 | } |
| 170522 | 170698 | break; |
| 170523 | 170699 | } |
| 170524 | 170700 | iCur = pWInfo->pTabList->a[pLoop->iTab].iCursor; |
| 170525 | 170701 | |
| | @@ -171419,22 +171595,18 @@ |
| 171419 | 171595 | pFrom = aTo; |
| 171420 | 171596 | aTo = aFrom; |
| 171421 | 171597 | aFrom = pFrom; |
| 171422 | 171598 | nFrom = nTo; |
| 171423 | 171599 | } |
| 171600 | + assert( nFrom==0 || nFrom==1 ); |
| 171424 | 171601 | |
| 171425 | 171602 | if( nFrom==0 ){ |
| 171426 | 171603 | sqlite3ErrorMsg(pParse, "no query solution"); |
| 171427 | 171604 | sqlite3StackFreeNN(pParse->db, pSpace); |
| 171428 | 171605 | return SQLITE_ERROR; |
| 171429 | 171606 | } |
| 171430 | | - |
| 171431 | | - /* Find the lowest cost path. pFrom will be left pointing to that path */ |
| 171432 | 171607 | pFrom = aFrom; |
| 171433 | | - for(ii=1; ii<nFrom; ii++){ |
| 171434 | | - if( pFrom->rCost>aFrom[ii].rCost ) pFrom = &aFrom[ii]; |
| 171435 | | - } |
| 171436 | 171608 | assert( pWInfo->nLevel==nLoop ); |
| 171437 | 171609 | /* Load the lowest cost path into pWInfo */ |
| 171438 | 171610 | for(iLoop=0; iLoop<nLoop; iLoop++){ |
| 171439 | 171611 | WhereLevel *pLevel = pWInfo->a + iLoop; |
| 171440 | 171612 | pLevel->pWLoop = pWLoop = pFrom->aLoop[iLoop]; |
| | @@ -171563,11 +171735,14 @@ |
| 171563 | 171735 | int once = 0; |
| 171564 | 171736 | #endif |
| 171565 | 171737 | for(i=0; i<pWInfo->nLevel; i++){ |
| 171566 | 171738 | WhereLoop *p = pWInfo->a[i].pWLoop; |
| 171567 | 171739 | if( p==0 ) break; |
| 171568 | | - if( (p->wsFlags & WHERE_VIRTUALTABLE)!=0 ) continue; |
| 171740 | + if( (p->wsFlags & WHERE_VIRTUALTABLE)!=0 ){ |
| 171741 | + /* Treat a vtab scan as similar to a full-table scan */ |
| 171742 | + break; |
| 171743 | + } |
| 171569 | 171744 | if( (p->wsFlags & (WHERE_COLUMN_EQ|WHERE_COLUMN_NULL|WHERE_COLUMN_IN))!=0 ){ |
| 171570 | 171745 | u8 iTab = p->iTab; |
| 171571 | 171746 | WhereLoop *pLoop; |
| 171572 | 171747 | for(pLoop=pWInfo->pLoops; pLoop; pLoop=pLoop->pNextLoop){ |
| 171573 | 171748 | if( pLoop->iTab!=iTab ) continue; |
| | @@ -175676,11 +175851,11 @@ |
| 175676 | 175851 | ** RETURN_ROW |
| 175677 | 175852 | ** |
| 175678 | 175853 | ** |
| 175679 | 175854 | ** ROWS BETWEEN <expr1> FOLLOWING AND <expr2> FOLLOWING |
| 175680 | 175855 | ** |
| 175681 | | -** ... loop started by sqlite3WhereBegin() ... |
| 175856 | +** ... loop started by sqlite3WhereBegin() ... |
| 175682 | 175857 | ** if( new partition ){ |
| 175683 | 175858 | ** Gosub flush |
| 175684 | 175859 | ** } |
| 175685 | 175860 | ** Insert new row into eph table. |
| 175686 | 175861 | ** if( first row of partition ){ |
| | @@ -176194,10 +176369,16 @@ |
| 176194 | 176369 | addrStart = sqlite3VdbeCurrentAddr(v); |
| 176195 | 176370 | addrBreak1 = windowCodeOp(&s, WINDOW_RETURN_ROW, regStart, 1); |
| 176196 | 176371 | addrBreak2 = windowCodeOp(&s, WINDOW_AGGINVERSE, 0, 1); |
| 176197 | 176372 | }else{ |
| 176198 | 176373 | assert( pMWin->eEnd==TK_FOLLOWING ); |
| 176374 | + /* assert( regStart>=0 ); |
| 176375 | + ** regEnd = regEnd - regStart; |
| 176376 | + ** regStart = 0; */ |
| 176377 | + sqlite3VdbeAddOp3(v, OP_Subtract, regStart, regEnd, regEnd); |
| 176378 | + sqlite3VdbeAddOp2(v, OP_Integer, 0, regStart); |
| 176379 | + |
| 176199 | 176380 | addrStart = sqlite3VdbeCurrentAddr(v); |
| 176200 | 176381 | addrBreak1 = windowCodeOp(&s, WINDOW_RETURN_ROW, regEnd, 1); |
| 176201 | 176382 | addrBreak2 = windowCodeOp(&s, WINDOW_AGGINVERSE, regStart, 1); |
| 176202 | 176383 | } |
| 176203 | 176384 | sqlite3VdbeAddOp2(v, OP_Goto, 0, addrStart); |
| | @@ -186322,10 +186503,33 @@ |
| 186322 | 186503 | } |
| 186323 | 186504 | } |
| 186324 | 186505 | sqlite3_mutex_leave(db->mutex); |
| 186325 | 186506 | return z; |
| 186326 | 186507 | } |
| 186508 | + |
| 186509 | +/* |
| 186510 | +** Set the error code and error message associated with the database handle. |
| 186511 | +** |
| 186512 | +** This routine is intended to be called by outside extensions (ex: the |
| 186513 | +** Session extension). Internal logic should invoke sqlite3Error() or |
| 186514 | +** sqlite3ErrorWithMsg() directly. |
| 186515 | +*/ |
| 186516 | +SQLITE_API int sqlite3_set_errmsg(sqlite3 *db, int errcode, const char *zMsg){ |
| 186517 | + int rc = SQLITE_OK; |
| 186518 | + if( !sqlite3SafetyCheckSickOrOk(db) ){ |
| 186519 | + return SQLITE_MISUSE_BKPT; |
| 186520 | + } |
| 186521 | + sqlite3_mutex_enter(db->mutex); |
| 186522 | + if( zMsg ){ |
| 186523 | + sqlite3ErrorWithMsg(db, errcode, "%s", zMsg); |
| 186524 | + }else{ |
| 186525 | + sqlite3Error(db, errcode); |
| 186526 | + } |
| 186527 | + rc = sqlite3ApiExit(db, rc); |
| 186528 | + sqlite3_mutex_leave(db->mutex); |
| 186529 | + return rc; |
| 186530 | +} |
| 186327 | 186531 | |
| 186328 | 186532 | /* |
| 186329 | 186533 | ** Return the byte offset of the most recent error |
| 186330 | 186534 | */ |
| 186331 | 186535 | SQLITE_API int sqlite3_error_offset(sqlite3 *db){ |
| | @@ -188147,17 +188351,19 @@ |
| 188147 | 188351 | case SQLITE_TESTCTRL_ISINIT: { |
| 188148 | 188352 | if( sqlite3GlobalConfig.isInit==0 ) rc = SQLITE_ERROR; |
| 188149 | 188353 | break; |
| 188150 | 188354 | } |
| 188151 | 188355 | |
| 188152 | | - /* sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, db, dbName, onOff, tnum); |
| 188356 | + /* sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, db, dbName, mode, tnum); |
| 188153 | 188357 | ** |
| 188154 | 188358 | ** This test control is used to create imposter tables. "db" is a pointer |
| 188155 | 188359 | ** to the database connection. dbName is the database name (ex: "main" or |
| 188156 | | - ** "temp") which will receive the imposter. "onOff" turns imposter mode on |
| 188157 | | - ** or off. "tnum" is the root page of the b-tree to which the imposter |
| 188158 | | - ** table should connect. |
| 188360 | + ** "temp") which will receive the imposter. "mode" turns imposter mode on |
| 188361 | + ** or off. mode==0 means imposter mode is off. mode==1 means imposter mode |
| 188362 | + ** is on. mode==2 means imposter mode is on but results in an imposter |
| 188363 | + ** table that is read-only unless writable_schema is on. "tnum" is the |
| 188364 | + ** root page of the b-tree to which the imposter table should connect. |
| 188159 | 188365 | ** |
| 188160 | 188366 | ** Enable imposter mode only when the schema has already been parsed. Then |
| 188161 | 188367 | ** run a single CREATE TABLE statement to construct the imposter table in |
| 188162 | 188368 | ** the parsed schema. Then turn imposter mode back off again. |
| 188163 | 188369 | ** |
| | @@ -228653,11 +228859,11 @@ |
| 228653 | 228859 | typedef struct DbpageCursor DbpageCursor; |
| 228654 | 228860 | |
| 228655 | 228861 | struct DbpageCursor { |
| 228656 | 228862 | sqlite3_vtab_cursor base; /* Base class. Must be first */ |
| 228657 | 228863 | Pgno pgno; /* Current page number */ |
| 228658 | | - int mxPgno; /* Last page to visit on this scan */ |
| 228864 | + Pgno mxPgno; /* Last page to visit on this scan */ |
| 228659 | 228865 | Pager *pPager; /* Pager being read/written */ |
| 228660 | 228866 | DbPage *pPage1; /* Page 1 of the database */ |
| 228661 | 228867 | int iDb; /* Index of database to analyze */ |
| 228662 | 228868 | int szPage; /* Size of each page in bytes */ |
| 228663 | 228869 | }; |
| | @@ -231924,10 +232130,23 @@ |
| 231924 | 232130 | assert( (a - p->aRecord)==p->nRecord ); |
| 231925 | 232131 | } |
| 231926 | 232132 | |
| 231927 | 232133 | return rc; |
| 231928 | 232134 | } |
| 232135 | + |
| 232136 | +static int sessionPrepare( |
| 232137 | + sqlite3 *db, |
| 232138 | + sqlite3_stmt **pp, |
| 232139 | + char **pzErrmsg, |
| 232140 | + const char *zSql |
| 232141 | +){ |
| 232142 | + int rc = sqlite3_prepare_v2(db, zSql, -1, pp, 0); |
| 232143 | + if( pzErrmsg && rc!=SQLITE_OK ){ |
| 232144 | + *pzErrmsg = sqlite3_mprintf("%s", sqlite3_errmsg(db)); |
| 232145 | + } |
| 232146 | + return rc; |
| 232147 | +} |
| 231929 | 232148 | |
| 231930 | 232149 | /* |
| 231931 | 232150 | ** Formulate and prepare a SELECT statement to retrieve a row from table |
| 231932 | 232151 | ** zTab in database zDb based on its primary key. i.e. |
| 231933 | 232152 | ** |
| | @@ -231946,16 +232165,16 @@ |
| 231946 | 232165 | const char *zTab, /* Table name */ |
| 231947 | 232166 | int bRowid, |
| 231948 | 232167 | int nCol, /* Number of columns in table */ |
| 231949 | 232168 | const char **azCol, /* Names of table columns */ |
| 231950 | 232169 | u8 *abPK, /* PRIMARY KEY array */ |
| 231951 | | - sqlite3_stmt **ppStmt /* OUT: Prepared SELECT statement */ |
| 232170 | + sqlite3_stmt **ppStmt, /* OUT: Prepared SELECT statement */ |
| 232171 | + char **pzErrmsg /* OUT: Error message */ |
| 231952 | 232172 | ){ |
| 231953 | 232173 | int rc = SQLITE_OK; |
| 231954 | 232174 | char *zSql = 0; |
| 231955 | 232175 | const char *zSep = ""; |
| 231956 | | - int nSql = -1; |
| 231957 | 232176 | int i; |
| 231958 | 232177 | |
| 231959 | 232178 | SessionBuffer cols = {0, 0, 0}; |
| 231960 | 232179 | SessionBuffer nooptest = {0, 0, 0}; |
| 231961 | 232180 | SessionBuffer pkfield = {0, 0, 0}; |
| | @@ -232031,11 +232250,11 @@ |
| 232031 | 232250 | nSql = buf.nBuf; |
| 232032 | 232251 | } |
| 232033 | 232252 | #endif |
| 232034 | 232253 | |
| 232035 | 232254 | if( rc==SQLITE_OK ){ |
| 232036 | | - rc = sqlite3_prepare_v2(db, zSql, nSql, ppStmt, 0); |
| 232255 | + rc = sessionPrepare(db, ppStmt, pzErrmsg, zSql); |
| 232037 | 232256 | } |
| 232038 | 232257 | sqlite3_free(zSql); |
| 232039 | 232258 | sqlite3_free(nooptest.aBuf); |
| 232040 | 232259 | sqlite3_free(pkfield.aBuf); |
| 232041 | 232260 | sqlite3_free(pkvar.aBuf); |
| | @@ -232195,11 +232414,11 @@ |
| 232195 | 232414 | sessionAppendTableHdr(&buf, bPatchset, pTab, &rc); |
| 232196 | 232415 | |
| 232197 | 232416 | /* Build and compile a statement to execute: */ |
| 232198 | 232417 | if( rc==SQLITE_OK ){ |
| 232199 | 232418 | rc = sessionSelectStmt(db, 0, pSession->zDb, |
| 232200 | | - zName, pTab->bRowid, pTab->nCol, pTab->azCol, pTab->abPK, &pSel |
| 232419 | + zName, pTab->bRowid, pTab->nCol, pTab->azCol, pTab->abPK, &pSel, 0 |
| 232201 | 232420 | ); |
| 232202 | 232421 | } |
| 232203 | 232422 | |
| 232204 | 232423 | nNoop = buf.nBuf; |
| 232205 | 232424 | for(i=0; i<pTab->nChange && rc==SQLITE_OK; i++){ |
| | @@ -233404,10 +233623,11 @@ |
| 233404 | 233623 | SessionBuffer rebase; /* Rebase information (if any) here */ |
| 233405 | 233624 | u8 bRebaseStarted; /* If table header is already in rebase */ |
| 233406 | 233625 | u8 bRebase; /* True to collect rebase information */ |
| 233407 | 233626 | u8 bIgnoreNoop; /* True to ignore no-op conflicts */ |
| 233408 | 233627 | int bRowid; |
| 233628 | + char *zErr; /* Error message, if any */ |
| 233409 | 233629 | }; |
| 233410 | 233630 | |
| 233411 | 233631 | /* Number of prepared UPDATE statements to cache. */ |
| 233412 | 233632 | #define SESSION_UPDATE_CACHE_SZ 12 |
| 233413 | 233633 | |
| | @@ -233629,11 +233849,11 @@ |
| 233629 | 233849 | } |
| 233630 | 233850 | sessionAppendStr(&buf, ")", &rc); |
| 233631 | 233851 | } |
| 233632 | 233852 | |
| 233633 | 233853 | if( rc==SQLITE_OK ){ |
| 233634 | | - rc = sqlite3_prepare_v2(db, (char *)buf.aBuf, buf.nBuf, &p->pDelete, 0); |
| 233854 | + rc = sessionPrepare(db, &p->pDelete, &p->zErr, (char*)buf.aBuf); |
| 233635 | 233855 | } |
| 233636 | 233856 | sqlite3_free(buf.aBuf); |
| 233637 | 233857 | |
| 233638 | 233858 | return rc; |
| 233639 | 233859 | } |
| | @@ -233656,11 +233876,11 @@ |
| 233656 | 233876 | const char *zTab, /* Table name */ |
| 233657 | 233877 | SessionApplyCtx *p /* Session changeset-apply context */ |
| 233658 | 233878 | ){ |
| 233659 | 233879 | /* TODO */ |
| 233660 | 233880 | return sessionSelectStmt(db, p->bIgnoreNoop, |
| 233661 | | - "main", zTab, p->bRowid, p->nCol, p->azCol, p->abPK, &p->pSelect |
| 233881 | + "main", zTab, p->bRowid, p->nCol, p->azCol, p->abPK, &p->pSelect, &p->zErr |
| 233662 | 233882 | ); |
| 233663 | 233883 | } |
| 233664 | 233884 | |
| 233665 | 233885 | /* |
| 233666 | 233886 | ** Formulate and prepare an INSERT statement to add a record to table zTab. |
| | @@ -233693,37 +233913,33 @@ |
| 233693 | 233913 | sessionAppendStr(&buf, ", ?", &rc); |
| 233694 | 233914 | } |
| 233695 | 233915 | sessionAppendStr(&buf, ")", &rc); |
| 233696 | 233916 | |
| 233697 | 233917 | if( rc==SQLITE_OK ){ |
| 233698 | | - rc = sqlite3_prepare_v2(db, (char *)buf.aBuf, buf.nBuf, &p->pInsert, 0); |
| 233918 | + rc = sessionPrepare(db, &p->pInsert, &p->zErr, (char*)buf.aBuf); |
| 233699 | 233919 | } |
| 233700 | 233920 | sqlite3_free(buf.aBuf); |
| 233701 | 233921 | return rc; |
| 233702 | 233922 | } |
| 233703 | 233923 | |
| 233704 | | -static int sessionPrepare(sqlite3 *db, sqlite3_stmt **pp, const char *zSql){ |
| 233705 | | - return sqlite3_prepare_v2(db, zSql, -1, pp, 0); |
| 233706 | | -} |
| 233707 | | - |
| 233708 | 233924 | /* |
| 233709 | 233925 | ** Prepare statements for applying changes to the sqlite_stat1 table. |
| 233710 | 233926 | ** These are similar to those created by sessionSelectRow(), |
| 233711 | 233927 | ** sessionInsertRow(), sessionUpdateRow() and sessionDeleteRow() for |
| 233712 | 233928 | ** other tables. |
| 233713 | 233929 | */ |
| 233714 | 233930 | static int sessionStat1Sql(sqlite3 *db, SessionApplyCtx *p){ |
| 233715 | 233931 | int rc = sessionSelectRow(db, "sqlite_stat1", p); |
| 233716 | 233932 | if( rc==SQLITE_OK ){ |
| 233717 | | - rc = sessionPrepare(db, &p->pInsert, |
| 233933 | + rc = sessionPrepare(db, &p->pInsert, 0, |
| 233718 | 233934 | "INSERT INTO main.sqlite_stat1 VALUES(?1, " |
| 233719 | 233935 | "CASE WHEN length(?2)=0 AND typeof(?2)='blob' THEN NULL ELSE ?2 END, " |
| 233720 | 233936 | "?3)" |
| 233721 | 233937 | ); |
| 233722 | 233938 | } |
| 233723 | 233939 | if( rc==SQLITE_OK ){ |
| 233724 | | - rc = sessionPrepare(db, &p->pDelete, |
| 233940 | + rc = sessionPrepare(db, &p->pDelete, 0, |
| 233725 | 233941 | "DELETE FROM main.sqlite_stat1 WHERE tbl=?1 AND idx IS " |
| 233726 | 233942 | "CASE WHEN length(?2)=0 AND typeof(?2)='blob' THEN NULL ELSE ?2 END " |
| 233727 | 233943 | "AND (?4 OR stat IS ?3)" |
| 233728 | 233944 | ); |
| 233729 | 233945 | } |
| | @@ -234502,10 +234718,15 @@ |
| 234502 | 234718 | if( (flags & SQLITE_CHANGESETAPPLY_FKNOACTION) && savedFlag==0 ){ |
| 234503 | 234719 | assert( db->flags & SQLITE_FkNoAction ); |
| 234504 | 234720 | db->flags &= ~((u64)SQLITE_FkNoAction); |
| 234505 | 234721 | db->aDb[0].pSchema->schema_cookie -= 32; |
| 234506 | 234722 | } |
| 234723 | + |
| 234724 | + assert( rc!=SQLITE_OK || sApply.zErr==0 ); |
| 234725 | + sqlite3_set_errmsg(db, rc, sApply.zErr); |
| 234726 | + sqlite3_free(sApply.zErr); |
| 234727 | + |
| 234507 | 234728 | sqlite3_mutex_leave(sqlite3_db_mutex(db)); |
| 234508 | 234729 | return rc; |
| 234509 | 234730 | } |
| 234510 | 234731 | |
| 234511 | 234732 | /* |
| | @@ -237466,11 +237687,11 @@ |
| 237466 | 237687 | ** ){ |
| 237467 | 237688 | ** // The document with rowid iRowid matches the expression! |
| 237468 | 237689 | ** i64 iRowid = sqlite3Fts5ExprRowid(pExpr); |
| 237469 | 237690 | ** } |
| 237470 | 237691 | */ |
| 237471 | | -static int sqlite3Fts5ExprFirst(Fts5Expr*, Fts5Index *pIdx, i64 iMin, int bDesc); |
| 237692 | +static int sqlite3Fts5ExprFirst(Fts5Expr*, Fts5Index *pIdx, i64 iMin, i64, int bDesc); |
| 237472 | 237693 | static int sqlite3Fts5ExprNext(Fts5Expr*, i64 iMax); |
| 237473 | 237694 | static int sqlite3Fts5ExprEof(Fts5Expr*); |
| 237474 | 237695 | static i64 sqlite3Fts5ExprRowid(Fts5Expr*); |
| 237475 | 237696 | |
| 237476 | 237697 | static void sqlite3Fts5ExprFree(Fts5Expr*); |
| | @@ -243035,11 +243256,17 @@ |
| 243035 | 243256 | ** equal to iFirst. |
| 243036 | 243257 | ** |
| 243037 | 243258 | ** Return SQLITE_OK if successful, or an SQLite error code otherwise. It |
| 243038 | 243259 | ** is not considered an error if the query does not match any documents. |
| 243039 | 243260 | */ |
| 243040 | | -static int sqlite3Fts5ExprFirst(Fts5Expr *p, Fts5Index *pIdx, i64 iFirst, int bDesc){ |
| 243261 | +static int sqlite3Fts5ExprFirst( |
| 243262 | + Fts5Expr *p, |
| 243263 | + Fts5Index *pIdx, |
| 243264 | + i64 iFirst, |
| 243265 | + i64 iLast, |
| 243266 | + int bDesc |
| 243267 | +){ |
| 243041 | 243268 | Fts5ExprNode *pRoot = p->pRoot; |
| 243042 | 243269 | int rc; /* Return code */ |
| 243043 | 243270 | |
| 243044 | 243271 | p->pIndex = pIdx; |
| 243045 | 243272 | p->bDesc = bDesc; |
| | @@ -243056,10 +243283,13 @@ |
| 243056 | 243283 | |
| 243057 | 243284 | /* If the iterator is not at a real match, skip forward until it is. */ |
| 243058 | 243285 | while( pRoot->bNomatch && rc==SQLITE_OK ){ |
| 243059 | 243286 | assert( pRoot->bEof==0 ); |
| 243060 | 243287 | rc = fts5ExprNodeNext(p, pRoot, 0, 0); |
| 243288 | + } |
| 243289 | + if( fts5RowidCmp(p, pRoot->iRowid, iLast)>0 ){ |
| 243290 | + pRoot->bEof = 1; |
| 243061 | 243291 | } |
| 243062 | 243292 | return rc; |
| 243063 | 243293 | } |
| 243064 | 243294 | |
| 243065 | 243295 | /* |
| | @@ -255404,10 +255634,21 @@ |
| 255404 | 255634 | { |
| 255405 | 255635 | pIdxInfo->idxFlags |= SQLITE_INDEX_SCAN_UNIQUE; |
| 255406 | 255636 | } |
| 255407 | 255637 | #endif |
| 255408 | 255638 | } |
| 255639 | + |
| 255640 | +static void fts5SetEstimatedRows(sqlite3_index_info *pIdxInfo, i64 nRow){ |
| 255641 | +#if SQLITE_VERSION_NUMBER>=3008002 |
| 255642 | +#ifndef SQLITE_CORE |
| 255643 | + if( sqlite3_libversion_number()>=3008002 ) |
| 255644 | +#endif |
| 255645 | + { |
| 255646 | + pIdxInfo->estimatedRows = nRow; |
| 255647 | + } |
| 255648 | +#endif |
| 255649 | +} |
| 255409 | 255650 | |
| 255410 | 255651 | static int fts5UsePatternMatch( |
| 255411 | 255652 | Fts5Config *pConfig, |
| 255412 | 255653 | struct sqlite3_index_constraint *p |
| 255413 | 255654 | ){ |
| | @@ -255540,11 +255781,11 @@ |
| 255540 | 255781 | bSeenRank = 1; |
| 255541 | 255782 | }else{ |
| 255542 | 255783 | nSeenMatch++; |
| 255543 | 255784 | idxStr[iIdxStr++] = 'M'; |
| 255544 | 255785 | sqlite3_snprintf(6, &idxStr[iIdxStr], "%d", iCol); |
| 255545 | | - idxStr += strlen(&idxStr[iIdxStr]); |
| 255786 | + iIdxStr += (int)strlen(&idxStr[iIdxStr]); |
| 255546 | 255787 | assert( idxStr[iIdxStr]=='\0' ); |
| 255547 | 255788 | } |
| 255548 | 255789 | pInfo->aConstraintUsage[i].argvIndex = ++iCons; |
| 255549 | 255790 | pInfo->aConstraintUsage[i].omit = 1; |
| 255550 | 255791 | } |
| | @@ -255559,10 +255800,11 @@ |
| 255559 | 255800 | nSeenMatch++; |
| 255560 | 255801 | }else if( bSeenEq==0 && p->op==SQLITE_INDEX_CONSTRAINT_EQ && iCol<0 ){ |
| 255561 | 255802 | idxStr[iIdxStr++] = '='; |
| 255562 | 255803 | bSeenEq = 1; |
| 255563 | 255804 | pInfo->aConstraintUsage[i].argvIndex = ++iCons; |
| 255805 | + pInfo->aConstraintUsage[i].omit = 1; |
| 255564 | 255806 | } |
| 255565 | 255807 | } |
| 255566 | 255808 | } |
| 255567 | 255809 | |
| 255568 | 255810 | if( bSeenEq==0 ){ |
| | @@ -255606,21 +255848,25 @@ |
| 255606 | 255848 | } |
| 255607 | 255849 | } |
| 255608 | 255850 | |
| 255609 | 255851 | /* Calculate the estimated cost based on the flags set in idxFlags. */ |
| 255610 | 255852 | if( bSeenEq ){ |
| 255611 | | - pInfo->estimatedCost = nSeenMatch ? 1000.0 : 10.0; |
| 255612 | | - if( nSeenMatch==0 ) fts5SetUniqueFlag(pInfo); |
| 255613 | | - }else if( bSeenLt && bSeenGt ){ |
| 255614 | | - pInfo->estimatedCost = nSeenMatch ? 5000.0 : 250000.0; |
| 255615 | | - }else if( bSeenLt || bSeenGt ){ |
| 255616 | | - pInfo->estimatedCost = nSeenMatch ? 7500.0 : 750000.0; |
| 255853 | + pInfo->estimatedCost = nSeenMatch ? 1000.0 : 25.0; |
| 255854 | + fts5SetUniqueFlag(pInfo); |
| 255855 | + fts5SetEstimatedRows(pInfo, 1); |
| 255617 | 255856 | }else{ |
| 255618 | | - pInfo->estimatedCost = nSeenMatch ? 10000.0 : 1000000.0; |
| 255619 | | - } |
| 255620 | | - for(i=1; i<nSeenMatch; i++){ |
| 255621 | | - pInfo->estimatedCost *= 0.4; |
| 255857 | + if( bSeenLt && bSeenGt ){ |
| 255858 | + pInfo->estimatedCost = nSeenMatch ? 5000.0 : 750000.0; |
| 255859 | + }else if( bSeenLt || bSeenGt ){ |
| 255860 | + pInfo->estimatedCost = nSeenMatch ? 7500.0 : 2250000.0; |
| 255861 | + }else{ |
| 255862 | + pInfo->estimatedCost = nSeenMatch ? 10000.0 : 3000000.0; |
| 255863 | + } |
| 255864 | + for(i=1; i<nSeenMatch; i++){ |
| 255865 | + pInfo->estimatedCost *= 0.4; |
| 255866 | + } |
| 255867 | + fts5SetEstimatedRows(pInfo, (i64)(pInfo->estimatedCost / 4.0)); |
| 255622 | 255868 | } |
| 255623 | 255869 | |
| 255624 | 255870 | pInfo->idxNum = idxFlags; |
| 255625 | 255871 | return SQLITE_OK; |
| 255626 | 255872 | } |
| | @@ -255815,11 +256061,13 @@ |
| 255815 | 256061 | if( CsrFlagTest(pCsr, FTS5CSR_REQUIRE_RESEEK) ){ |
| 255816 | 256062 | Fts5FullTable *pTab = (Fts5FullTable*)(pCsr->base.pVtab); |
| 255817 | 256063 | int bDesc = pCsr->bDesc; |
| 255818 | 256064 | i64 iRowid = sqlite3Fts5ExprRowid(pCsr->pExpr); |
| 255819 | 256065 | |
| 255820 | | - rc = sqlite3Fts5ExprFirst(pCsr->pExpr, pTab->p.pIndex, iRowid, bDesc); |
| 256066 | + rc = sqlite3Fts5ExprFirst( |
| 256067 | + pCsr->pExpr, pTab->p.pIndex, iRowid, pCsr->iLastRowid, bDesc |
| 256068 | + ); |
| 255821 | 256069 | if( rc==SQLITE_OK && iRowid!=sqlite3Fts5ExprRowid(pCsr->pExpr) ){ |
| 255822 | 256070 | *pbSkip = 1; |
| 255823 | 256071 | } |
| 255824 | 256072 | |
| 255825 | 256073 | CsrFlagClear(pCsr, FTS5CSR_REQUIRE_RESEEK); |
| | @@ -255987,11 +256235,13 @@ |
| 255987 | 256235 | } |
| 255988 | 256236 | |
| 255989 | 256237 | static int fts5CursorFirst(Fts5FullTable *pTab, Fts5Cursor *pCsr, int bDesc){ |
| 255990 | 256238 | int rc; |
| 255991 | 256239 | Fts5Expr *pExpr = pCsr->pExpr; |
| 255992 | | - rc = sqlite3Fts5ExprFirst(pExpr, pTab->p.pIndex, pCsr->iFirstRowid, bDesc); |
| 256240 | + rc = sqlite3Fts5ExprFirst( |
| 256241 | + pExpr, pTab->p.pIndex, pCsr->iFirstRowid, pCsr->iLastRowid, bDesc |
| 256242 | + ); |
| 255993 | 256243 | if( sqlite3Fts5ExprEof(pExpr) ){ |
| 255994 | 256244 | CsrFlagSet(pCsr, FTS5CSR_EOF); |
| 255995 | 256245 | } |
| 255996 | 256246 | fts5CsrNewrow(pCsr); |
| 255997 | 256247 | return rc; |
| | @@ -258472,11 +258722,11 @@ |
| 258472 | 258722 | int nArg, /* Number of args */ |
| 258473 | 258723 | sqlite3_value **apUnused /* Function arguments */ |
| 258474 | 258724 | ){ |
| 258475 | 258725 | assert( nArg==0 ); |
| 258476 | 258726 | UNUSED_PARAM2(nArg, apUnused); |
| 258477 | | - sqlite3_result_text(pCtx, "fts5: 2025-09-10 14:28:07 61d9e204c5801a94811fdb0afe2c04f9814e08f2e141afa6dbda0fa45f026f70", -1, SQLITE_TRANSIENT); |
| 258727 | + sqlite3_result_text(pCtx, "fts5: 2025-09-24 19:10:58 821cc0e421bc14a68ebaee507e38a900e0c84ff6ba7ee95bf796cad387755232", -1, SQLITE_TRANSIENT); |
| 258478 | 258728 | } |
| 258479 | 258729 | |
| 258480 | 258730 | /* |
| 258481 | 258731 | ** Implementation of fts5_locale(LOCALE, TEXT) function. |
| 258482 | 258732 | ** |
| 258483 | 258733 | |