| | @@ -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 | | -** cf7163f82ca380958a79350473b2c5a2cebd 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,11 +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-07-30 16:17:14 cf7163f82ca380958a79350473b2c5a2cebda7496d6d575fa2835c362010fea1" |
| 472 | +#define SQLITE_SOURCE_ID "2025-09-24 19:10:58 821cc0e421bc14a68ebaee507e38a900e0c84ff6ba7ee95bf796cad387755232" |
| 473 | +#define SQLITE_SCM_BRANCH "trunk" |
| 474 | +#define SQLITE_SCM_TAGS "" |
| 475 | +#define SQLITE_SCM_DATETIME "2025-09-24T19:10:58.215Z" |
| 471 | 476 | |
| 472 | 477 | /* |
| 473 | 478 | ** CAPI3REF: Run-Time Library Version Numbers |
| 474 | 479 | ** KEYWORDS: sqlite3_version sqlite3_sourceid |
| 475 | 480 | ** |
| | @@ -2657,21 +2662,24 @@ |
| 2657 | 2662 | ** views in the main database schema or in the schemas of ATTACH-ed |
| 2658 | 2663 | ** databases.)^ </dd> |
| 2659 | 2664 | ** |
| 2660 | 2665 | ** [[SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER]] |
| 2661 | 2666 | ** <dt>SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER</dt> |
| 2662 | | -** <dd> ^This option is used to enable or disable the |
| 2663 | | -** [fts3_tokenizer()] function which is part of the |
| 2664 | | -** [FTS3] full-text search engine extension. |
| 2665 | | -** There must be two additional arguments. |
| 2666 | | -** The first argument is an integer which is 0 to disable fts3_tokenizer() or |
| 2667 | | -** positive to enable fts3_tokenizer() or negative to leave the setting |
| 2668 | | -** unchanged. |
| 2669 | | -** The second parameter is a pointer to an integer into which |
| 2670 | | -** is written 0 or 1 to indicate whether fts3_tokenizer is disabled or enabled |
| 2671 | | -** following this call. The second parameter may be a NULL pointer, in |
| 2672 | | -** which case the new setting is not reported back. </dd> |
| 2667 | +** <dd> ^This option is used to enable or disable using the |
| 2668 | +** [fts3_tokenizer()] function - part of the [FTS3] full-text search engine |
| 2669 | +** extension - without using bound parameters as the parameters. Doing so |
| 2670 | +** is disabled by default. There must be two additional arguments. The first |
| 2671 | +** argument is an integer. If it is passed 0, then using fts3_tokenizer() |
| 2672 | +** without bound parameters is disabled. If it is passed a positive value, |
| 2673 | +** then calling fts3_tokenizer without bound parameters is enabled. If it |
| 2674 | +** is passed a negative value, this setting is not modified - this can be |
| 2675 | +** used to query for the current setting. The second parameter is a pointer |
| 2676 | +** to an integer into which is written 0 or 1 to indicate the current value |
| 2677 | +** of this setting (after it is modified, if applicable). The second |
| 2678 | +** parameter may be a NULL pointer, in which case the value of the setting |
| 2679 | +** is not reported back. Refer to [FTS3] documentation for further details. |
| 2680 | +** </dd> |
| 2673 | 2681 | ** |
| 2674 | 2682 | ** [[SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION]] |
| 2675 | 2683 | ** <dt>SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION</dt> |
| 2676 | 2684 | ** <dd> ^This option is used to enable or disable the [sqlite3_load_extension()] |
| 2677 | 2685 | ** interface independently of the [load_extension()] SQL function. |
| | @@ -4517,10 +4525,38 @@ |
| 4517 | 4525 | SQLITE_API const char *sqlite3_errmsg(sqlite3*); |
| 4518 | 4526 | SQLITE_API const void *sqlite3_errmsg16(sqlite3*); |
| 4519 | 4527 | SQLITE_API const char *sqlite3_errstr(int); |
| 4520 | 4528 | SQLITE_API int sqlite3_error_offset(sqlite3 *db); |
| 4521 | 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 | + |
| 4522 | 4558 | /* |
| 4523 | 4559 | ** CAPI3REF: Prepared Statement Object |
| 4524 | 4560 | ** KEYWORDS: {prepared statement} {prepared statements} |
| 4525 | 4561 | ** |
| 4526 | 4562 | ** An instance of this object represents a single SQL statement that |
| | @@ -6527,10 +6563,11 @@ |
| 6527 | 6563 | ** to be attached to [database connection] D using name N. Subsequent |
| 6528 | 6564 | ** calls to sqlite3_get_clientdata(D,N) will return a copy of pointer P |
| 6529 | 6565 | ** or a NULL pointer if there were no prior calls to |
| 6530 | 6566 | ** sqlite3_set_clientdata() with the same values of D and N. |
| 6531 | 6567 | ** Names are compared using strcmp() and are thus case sensitive. |
| 6568 | +** It returns 0 on success and SQLITE_NOMEM on allocation failure. |
| 6532 | 6569 | ** |
| 6533 | 6570 | ** If P and X are both non-NULL, then the destructor X is invoked with |
| 6534 | 6571 | ** argument P on the first of the following occurrences: |
| 6535 | 6572 | ** <ul> |
| 6536 | 6573 | ** <li> An out-of-memory error occurs during the call to |
| | @@ -10098,25 +10135,38 @@ |
| 10098 | 10135 | ** ^The third parameter is the name of the database that was written to - |
| 10099 | 10136 | ** either "main" or the name of an [ATTACH]-ed database. ^The fourth parameter |
| 10100 | 10137 | ** is the number of pages currently in the write-ahead log file, |
| 10101 | 10138 | ** including those that were just committed. |
| 10102 | 10139 | ** |
| 10103 | | -** The callback function should normally return [SQLITE_OK]. ^If an error |
| 10140 | +** ^The callback function should normally return [SQLITE_OK]. ^If an error |
| 10104 | 10141 | ** code is returned, that error will propagate back up through the |
| 10105 | 10142 | ** SQLite code base to cause the statement that provoked the callback |
| 10106 | 10143 | ** to report an error, though the commit will have still occurred. If the |
| 10107 | 10144 | ** callback returns [SQLITE_ROW] or [SQLITE_DONE], or if it returns a value |
| 10108 | 10145 | ** that does not correspond to any valid SQLite error code, the results |
| 10109 | 10146 | ** are undefined. |
| 10110 | 10147 | ** |
| 10111 | | -** A single database handle may have at most a single write-ahead log callback |
| 10112 | | -** registered at one time. ^Calling [sqlite3_wal_hook()] replaces any |
| 10113 | | -** previously registered write-ahead log callback. ^The return value is |
| 10114 | | -** a copy of the third parameter from the previous call, if any, or 0. |
| 10115 | | -** ^Note that the [sqlite3_wal_autocheckpoint()] interface and the |
| 10116 | | -** [wal_autocheckpoint pragma] both invoke [sqlite3_wal_hook()] and will |
| 10117 | | -** overwrite any prior [sqlite3_wal_hook()] settings. |
| 10148 | +** ^A single database handle may have at most a single write-ahead log |
| 10149 | +** callback registered at one time. ^Calling [sqlite3_wal_hook()] |
| 10150 | +** replaces the default behavior or previously registered write-ahead |
| 10151 | +** log callback. |
| 10152 | +** |
| 10153 | +** ^The return value is a copy of the third parameter from the |
| 10154 | +** previous call, if any, or 0. |
| 10155 | +** |
| 10156 | +** ^The [sqlite3_wal_autocheckpoint()] interface and the |
| 10157 | +** [wal_autocheckpoint pragma] both invoke [sqlite3_wal_hook()] and |
| 10158 | +** will overwrite any prior [sqlite3_wal_hook()] settings. |
| 10159 | +** |
| 10160 | +** ^If a write-ahead log callback is set using this function then |
| 10161 | +** [sqlite3_wal_checkpoint_v2()] or [PRAGMA wal_checkpoint] |
| 10162 | +** should be invoked periodically to keep the write-ahead log file |
| 10163 | +** from growing without bound. |
| 10164 | +** |
| 10165 | +** ^Passing a NULL pointer for the callback disables automatic |
| 10166 | +** checkpointing entirely. To re-enable the default behavior, call |
| 10167 | +** sqlite3_wal_autocheckpoint(db,1000) or use [PRAGMA wal_checkpoint]. |
| 10118 | 10168 | */ |
| 10119 | 10169 | SQLITE_API void *sqlite3_wal_hook( |
| 10120 | 10170 | sqlite3*, |
| 10121 | 10171 | int(*)(void *,sqlite3*,const char*,int), |
| 10122 | 10172 | void* |
| | @@ -10129,11 +10179,11 @@ |
| 10129 | 10179 | ** ^The [sqlite3_wal_autocheckpoint(D,N)] is a wrapper around |
| 10130 | 10180 | ** [sqlite3_wal_hook()] that causes any database on [database connection] D |
| 10131 | 10181 | ** to automatically [checkpoint] |
| 10132 | 10182 | ** after committing a transaction if there are N or |
| 10133 | 10183 | ** more frames in the [write-ahead log] file. ^Passing zero or |
| 10134 | | -** a negative value as the nFrame parameter disables automatic |
| 10184 | +** a negative value as the N parameter disables automatic |
| 10135 | 10185 | ** checkpoints entirely. |
| 10136 | 10186 | ** |
| 10137 | 10187 | ** ^The callback registered by this function replaces any existing callback |
| 10138 | 10188 | ** registered using [sqlite3_wal_hook()]. ^Likewise, registering a callback |
| 10139 | 10189 | ** using [sqlite3_wal_hook()] disables the automatic checkpoint mechanism |
| | @@ -10145,13 +10195,14 @@ |
| 10145 | 10195 | ** ^Checkpoints initiated by this mechanism are |
| 10146 | 10196 | ** [sqlite3_wal_checkpoint_v2|PASSIVE]. |
| 10147 | 10197 | ** |
| 10148 | 10198 | ** ^Every new [database connection] defaults to having the auto-checkpoint |
| 10149 | 10199 | ** enabled with a threshold of 1000 or [SQLITE_DEFAULT_WAL_AUTOCHECKPOINT] |
| 10150 | | -** pages. The use of this interface |
| 10151 | | -** is only necessary if the default setting is found to be suboptimal |
| 10152 | | -** for a particular application. |
| 10200 | +** pages. |
| 10201 | +** |
| 10202 | +** ^The use of this interface is only necessary if the default setting |
| 10203 | +** is found to be suboptimal for a particular application. |
| 10153 | 10204 | */ |
| 10154 | 10205 | SQLITE_API int sqlite3_wal_autocheckpoint(sqlite3 *db, int N); |
| 10155 | 10206 | |
| 10156 | 10207 | /* |
| 10157 | 10208 | ** CAPI3REF: Checkpoint a database |
| | @@ -10212,10 +10263,15 @@ |
| 10212 | 10263 | ** |
| 10213 | 10264 | ** <dt>SQLITE_CHECKPOINT_TRUNCATE<dd> |
| 10214 | 10265 | ** ^This mode works the same way as SQLITE_CHECKPOINT_RESTART with the |
| 10215 | 10266 | ** addition that it also truncates the log file to zero bytes just prior |
| 10216 | 10267 | ** to a successful return. |
| 10268 | +** |
| 10269 | +** <dt>SQLITE_CHECKPOINT_NOOP<dd> |
| 10270 | +** ^This mode always checkpoints zero frames. The only reason to invoke |
| 10271 | +** a NOOP checkpoint is to access the values returned by |
| 10272 | +** sqlite3_wal_checkpoint_v2() via output parameters *pnLog and *pnCkpt. |
| 10217 | 10273 | ** </dl> |
| 10218 | 10274 | ** |
| 10219 | 10275 | ** ^If pnLog is not NULL, then *pnLog is set to the total number of frames in |
| 10220 | 10276 | ** the log file or to -1 if the checkpoint could not run because |
| 10221 | 10277 | ** of an error or because the database is not in [WAL mode]. ^If pnCkpt is not |
| | @@ -10282,10 +10338,11 @@ |
| 10282 | 10338 | ** These constants define all valid values for the "checkpoint mode" passed |
| 10283 | 10339 | ** as the third parameter to the [sqlite3_wal_checkpoint_v2()] interface. |
| 10284 | 10340 | ** See the [sqlite3_wal_checkpoint_v2()] documentation for details on the |
| 10285 | 10341 | ** meaning of each of these checkpoint modes. |
| 10286 | 10342 | */ |
| 10343 | +#define SQLITE_CHECKPOINT_NOOP -1 /* Do no work at all */ |
| 10287 | 10344 | #define SQLITE_CHECKPOINT_PASSIVE 0 /* Do as much as possible w/o blocking */ |
| 10288 | 10345 | #define SQLITE_CHECKPOINT_FULL 1 /* Wait for writers, then checkpoint */ |
| 10289 | 10346 | #define SQLITE_CHECKPOINT_RESTART 2 /* Like FULL but wait for readers */ |
| 10290 | 10347 | #define SQLITE_CHECKPOINT_TRUNCATE 3 /* Like RESTART but also truncate WAL */ |
| 10291 | 10348 | |
| | @@ -11109,11 +11166,11 @@ |
| 11109 | 11166 | ** to avoid a memory leak. |
| 11110 | 11167 | ** |
| 11111 | 11168 | ** The [sqlite3_snapshot_get()] interface is only available when the |
| 11112 | 11169 | ** [SQLITE_ENABLE_SNAPSHOT] compile-time option is used. |
| 11113 | 11170 | */ |
| 11114 | | -SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_get( |
| 11171 | +SQLITE_API int sqlite3_snapshot_get( |
| 11115 | 11172 | sqlite3 *db, |
| 11116 | 11173 | const char *zSchema, |
| 11117 | 11174 | sqlite3_snapshot **ppSnapshot |
| 11118 | 11175 | ); |
| 11119 | 11176 | |
| | @@ -11158,11 +11215,11 @@ |
| 11158 | 11215 | ** database connection in order to make it ready to use snapshots.) |
| 11159 | 11216 | ** |
| 11160 | 11217 | ** The [sqlite3_snapshot_open()] interface is only available when the |
| 11161 | 11218 | ** [SQLITE_ENABLE_SNAPSHOT] compile-time option is used. |
| 11162 | 11219 | */ |
| 11163 | | -SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_open( |
| 11220 | +SQLITE_API int sqlite3_snapshot_open( |
| 11164 | 11221 | sqlite3 *db, |
| 11165 | 11222 | const char *zSchema, |
| 11166 | 11223 | sqlite3_snapshot *pSnapshot |
| 11167 | 11224 | ); |
| 11168 | 11225 | |
| | @@ -11175,11 +11232,11 @@ |
| 11175 | 11232 | ** using this routine to avoid a memory leak. |
| 11176 | 11233 | ** |
| 11177 | 11234 | ** The [sqlite3_snapshot_free()] interface is only available when the |
| 11178 | 11235 | ** [SQLITE_ENABLE_SNAPSHOT] compile-time option is used. |
| 11179 | 11236 | */ |
| 11180 | | -SQLITE_API SQLITE_EXPERIMENTAL void sqlite3_snapshot_free(sqlite3_snapshot*); |
| 11237 | +SQLITE_API void sqlite3_snapshot_free(sqlite3_snapshot*); |
| 11181 | 11238 | |
| 11182 | 11239 | /* |
| 11183 | 11240 | ** CAPI3REF: Compare the ages of two snapshot handles. |
| 11184 | 11241 | ** METHOD: sqlite3_snapshot |
| 11185 | 11242 | ** |
| | @@ -11202,11 +11259,11 @@ |
| 11202 | 11259 | ** snapshot, and a positive value if P1 is a newer snapshot than P2. |
| 11203 | 11260 | ** |
| 11204 | 11261 | ** This interface is only available if SQLite is compiled with the |
| 11205 | 11262 | ** [SQLITE_ENABLE_SNAPSHOT] option. |
| 11206 | 11263 | */ |
| 11207 | | -SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_cmp( |
| 11264 | +SQLITE_API int sqlite3_snapshot_cmp( |
| 11208 | 11265 | sqlite3_snapshot *p1, |
| 11209 | 11266 | sqlite3_snapshot *p2 |
| 11210 | 11267 | ); |
| 11211 | 11268 | |
| 11212 | 11269 | /* |
| | @@ -11230,11 +11287,11 @@ |
| 11230 | 11287 | ** SQLITE_OK is returned if successful, or an SQLite error code otherwise. |
| 11231 | 11288 | ** |
| 11232 | 11289 | ** This interface is only available if SQLite is compiled with the |
| 11233 | 11290 | ** [SQLITE_ENABLE_SNAPSHOT] option. |
| 11234 | 11291 | */ |
| 11235 | | -SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_recover(sqlite3 *db, const char *zDb); |
| 11292 | +SQLITE_API int sqlite3_snapshot_recover(sqlite3 *db, const char *zDb); |
| 11236 | 11293 | |
| 11237 | 11294 | /* |
| 11238 | 11295 | ** CAPI3REF: Serialize a database |
| 11239 | 11296 | ** |
| 11240 | 11297 | ** The sqlite3_serialize(D,S,P,F) interface returns a pointer to |
| | @@ -11304,16 +11361,17 @@ |
| 11304 | 11361 | /* |
| 11305 | 11362 | ** CAPI3REF: Deserialize a database |
| 11306 | 11363 | ** |
| 11307 | 11364 | ** The sqlite3_deserialize(D,S,P,N,M,F) interface causes the |
| 11308 | 11365 | ** [database connection] D to disconnect from database S and then |
| 11309 | | -** reopen S as an in-memory database based on the serialization contained |
| 11310 | | -** in P. The serialized database P is N bytes in size. M is the size of |
| 11311 | | -** the buffer P, which might be larger than N. If M is larger than N, and |
| 11312 | | -** the SQLITE_DESERIALIZE_READONLY bit is not set in F, then SQLite is |
| 11313 | | -** permitted to add content to the in-memory database as long as the total |
| 11314 | | -** size does not exceed M bytes. |
| 11366 | +** reopen S as an in-memory database based on the serialization |
| 11367 | +** contained in P. If S is a NULL pointer, the main database is |
| 11368 | +** used. The serialized database P is N bytes in size. M is the size |
| 11369 | +** of the buffer P, which might be larger than N. If M is larger than |
| 11370 | +** N, and the SQLITE_DESERIALIZE_READONLY bit is not set in F, then |
| 11371 | +** SQLite is permitted to add content to the in-memory database as |
| 11372 | +** long as the total size does not exceed M bytes. |
| 11315 | 11373 | ** |
| 11316 | 11374 | ** If the SQLITE_DESERIALIZE_FREEONCLOSE bit is set in F, then SQLite will |
| 11317 | 11375 | ** invoke sqlite3_free() on the serialization buffer when the database |
| 11318 | 11376 | ** connection closes. If the SQLITE_DESERIALIZE_RESIZEABLE bit is set, then |
| 11319 | 11377 | ** SQLite will try to increase the buffer size using sqlite3_realloc64() |
| | @@ -12634,10 +12692,19 @@ |
| 12634 | 12692 | ** CAPI3REF: Apply A Changeset To A Database |
| 12635 | 12693 | ** |
| 12636 | 12694 | ** Apply a changeset or patchset to a database. These functions attempt to |
| 12637 | 12695 | ** update the "main" database attached to handle db with the changes found in |
| 12638 | 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. |
| 12639 | 12706 | ** |
| 12640 | 12707 | ** The fourth argument (xFilter) passed to these functions is the "filter |
| 12641 | 12708 | ** callback". This may be passed NULL, in which case all changes in the |
| 12642 | 12709 | ** changeset are applied to the database. For sqlite3changeset_apply() and |
| 12643 | 12710 | ** sqlite3_changeset_apply_v2(), if it is not NULL, then it is invoked once |
| | @@ -12772,16 +12839,10 @@ |
| 12772 | 12839 | ** It is safe to execute SQL statements, including those that write to the |
| 12773 | 12840 | ** table that the callback related to, from within the xConflict callback. |
| 12774 | 12841 | ** This can be used to further customize the application's conflict |
| 12775 | 12842 | ** resolution strategy. |
| 12776 | 12843 | ** |
| 12777 | | -** All changes made by these functions are enclosed in a savepoint transaction. |
| 12778 | | -** If any other error (aside from a constraint failure when attempting to |
| 12779 | | -** write to the target database) occurs, then the savepoint transaction is |
| 12780 | | -** rolled back, restoring the target database to its original state, and an |
| 12781 | | -** SQLite error code returned. |
| 12782 | | -** |
| 12783 | 12844 | ** If the output parameters (ppRebase) and (pnRebase) are non-NULL and |
| 12784 | 12845 | ** the input is a changeset (not a patchset), then sqlite3changeset_apply_v2() |
| 12785 | 12846 | ** may set (*ppRebase) to point to a "rebase" that may be used with the |
| 12786 | 12847 | ** sqlite3_rebaser APIs buffer before returning. In this case (*pnRebase) |
| 12787 | 12848 | ** is set to the size of the buffer in bytes. It is the responsibility of the |
| | @@ -14356,11 +14417,11 @@ |
| 14356 | 14417 | |
| 14357 | 14418 | /* |
| 14358 | 14419 | ** Maximum number of pages in one database file. |
| 14359 | 14420 | ** |
| 14360 | 14421 | ** This is really just the default value for the max_page_count pragma. |
| 14361 | | -** This value can be lowered (or raised) at run-time using that the |
| 14422 | +** This value can be lowered (or raised) at run-time using the |
| 14362 | 14423 | ** max_page_count macro. |
| 14363 | 14424 | */ |
| 14364 | 14425 | #ifndef SQLITE_MAX_PAGE_COUNT |
| 14365 | 14426 | # define SQLITE_MAX_PAGE_COUNT 0xfffffffe /* 4294967294 */ |
| 14366 | 14427 | #endif |
| | @@ -18127,11 +18188,11 @@ |
| 18127 | 18188 | struct sqlite3InitInfo { /* Information used during initialization */ |
| 18128 | 18189 | Pgno newTnum; /* Rootpage of table being initialized */ |
| 18129 | 18190 | u8 iDb; /* Which db file is being initialized */ |
| 18130 | 18191 | u8 busy; /* TRUE if currently initializing */ |
| 18131 | 18192 | unsigned orphanTrigger : 1; /* Last statement is orphaned TEMP trigger */ |
| 18132 | | - unsigned imposterTable : 1; /* Building an imposter table */ |
| 18193 | + unsigned imposterTable : 2; /* Building an imposter table */ |
| 18133 | 18194 | unsigned reopenMemdb : 1; /* ATTACH is really a reopen using MemDB */ |
| 18134 | 18195 | const char **azInit; /* "type", "name", and "tbl_name" columns */ |
| 18135 | 18196 | } init; |
| 18136 | 18197 | int nVdbeActive; /* Number of VDBEs currently running */ |
| 18137 | 18198 | int nVdbeRead; /* Number of active VDBEs that read or write */ |
| | @@ -18920,10 +18981,11 @@ |
| 18920 | 18981 | #define TF_Shadow 0x00001000 /* True for a shadow table */ |
| 18921 | 18982 | #define TF_HasStat4 0x00002000 /* STAT4 info available for this table */ |
| 18922 | 18983 | #define TF_Ephemeral 0x00004000 /* An ephemeral table */ |
| 18923 | 18984 | #define TF_Eponymous 0x00008000 /* An eponymous virtual table */ |
| 18924 | 18985 | #define TF_Strict 0x00010000 /* STRICT mode */ |
| 18986 | +#define TF_Imposter 0x00020000 /* An imposter table */ |
| 18925 | 18987 | |
| 18926 | 18988 | /* |
| 18927 | 18989 | ** Allowed values for Table.eTabType |
| 18928 | 18990 | */ |
| 18929 | 18991 | #define TABTYP_NORM 0 /* Ordinary table */ |
| | @@ -20086,10 +20148,11 @@ |
| 20086 | 20148 | #define SF_MultiPart 0x2000000 /* Has multiple incompatible PARTITIONs */ |
| 20087 | 20149 | #define SF_CopyCte 0x4000000 /* SELECT statement is a copy of a CTE */ |
| 20088 | 20150 | #define SF_OrderByReqd 0x8000000 /* The ORDER BY clause may not be omitted */ |
| 20089 | 20151 | #define SF_UpdateFrom 0x10000000 /* Query originates with UPDATE FROM */ |
| 20090 | 20152 | #define SF_Correlated 0x20000000 /* True if references the outer context */ |
| 20153 | +#define SF_OnToWhere 0x40000000 /* One or more ON clauses moved to WHERE */ |
| 20091 | 20154 | |
| 20092 | 20155 | /* True if SrcItem X is a subquery that has SF_NestedFrom */ |
| 20093 | 20156 | #define IsNestedFrom(X) \ |
| 20094 | 20157 | ((X)->fg.isSubquery && \ |
| 20095 | 20158 | ((X)->u4.pSubq->pSelect->selFlags&SF_NestedFrom)!=0) |
| | @@ -20839,10 +20902,11 @@ |
| 20839 | 20902 | struct Table *pTab; /* Table of generated column */ |
| 20840 | 20903 | struct CoveringIndexCheck *pCovIdxCk; /* Check for covering index */ |
| 20841 | 20904 | SrcItem *pSrcItem; /* A single FROM clause item */ |
| 20842 | 20905 | DbFixer *pFix; /* See sqlite3FixSelect() */ |
| 20843 | 20906 | Mem *aMem; /* See sqlite3BtreeCursorHint() */ |
| 20907 | + struct CheckOnCtx *pCheckOnCtx; /* See selectCheckOnClauses() */ |
| 20844 | 20908 | } u; |
| 20845 | 20909 | }; |
| 20846 | 20910 | |
| 20847 | 20911 | /* |
| 20848 | 20912 | ** The following structure contains information used by the sqliteFix... |
| | @@ -24209,11 +24273,14 @@ |
| 24209 | 24273 | Mem oldipk; /* Memory cell holding "old" IPK value */ |
| 24210 | 24274 | Mem *aNew; /* Array of new.* values */ |
| 24211 | 24275 | Table *pTab; /* Schema object being updated */ |
| 24212 | 24276 | Index *pPk; /* PK index if pTab is WITHOUT ROWID */ |
| 24213 | 24277 | sqlite3_value **apDflt; /* Array of default values, if required */ |
| 24214 | | - u8 keyinfoSpace[SZ_KEYINFO_0]; /* Space to hold pKeyinfo[0] content */ |
| 24278 | + union { |
| 24279 | + KeyInfo sKey; |
| 24280 | + u8 keyinfoSpace[SZ_KEYINFO_0]; /* Space to hold pKeyinfo[0] content */ |
| 24281 | + } uKey; |
| 24215 | 24282 | }; |
| 24216 | 24283 | |
| 24217 | 24284 | /* |
| 24218 | 24285 | ** An instance of this object is used to pass an vector of values into |
| 24219 | 24286 | ** OP_VFilter, the xFilter method of a virtual table. The vector is the |
| | @@ -24976,10 +25043,14 @@ |
| 24976 | 25043 | if( getDigits(zDate, "20b:20e", &nHr, &nMn)!=2 ){ |
| 24977 | 25044 | return 1; |
| 24978 | 25045 | } |
| 24979 | 25046 | zDate += 5; |
| 24980 | 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 | + } |
| 24981 | 25052 | zulu_time: |
| 24982 | 25053 | while( sqlite3Isspace(*zDate) ){ zDate++; } |
| 24983 | 25054 | return *zDate!=0; |
| 24984 | 25055 | } |
| 24985 | 25056 | |
| | @@ -33486,13 +33557,17 @@ |
| 33486 | 33557 | sqlite3StrAccumFinish(&x); |
| 33487 | 33558 | sqlite3TreeViewItem(pView, zLine, i<pSrc->nSrc-1); |
| 33488 | 33559 | n = 0; |
| 33489 | 33560 | if( pItem->fg.isSubquery ) n++; |
| 33490 | 33561 | if( pItem->fg.isTabFunc ) n++; |
| 33491 | | - if( pItem->fg.isUsing ) n++; |
| 33562 | + if( pItem->fg.isUsing || pItem->u3.pOn!=0 ) n++; |
| 33492 | 33563 | if( pItem->fg.isUsing ){ |
| 33493 | 33564 | sqlite3TreeViewIdList(pView, pItem->u3.pUsing, (--n)>0, "USING"); |
| 33565 | + }else if( pItem->u3.pOn!=0 ){ |
| 33566 | + sqlite3TreeViewItem(pView, "ON", (--n)>0); |
| 33567 | + sqlite3TreeViewExpr(pView, pItem->u3.pOn, 0); |
| 33568 | + sqlite3TreeViewPop(&pView); |
| 33494 | 33569 | } |
| 33495 | 33570 | if( pItem->fg.isSubquery ){ |
| 33496 | 33571 | assert( n==1 ); |
| 33497 | 33572 | if( pItem->pSTab ){ |
| 33498 | 33573 | Table *pTab = pItem->pSTab; |
| | @@ -38131,11 +38206,11 @@ |
| 38131 | 38206 | static int kvstorageDelete(const char*, const char *zKey); |
| 38132 | 38207 | static int kvstorageRead(const char*, const char *zKey, char *zBuf, int nBuf); |
| 38133 | 38208 | #define KVSTORAGE_KEY_SZ 32 |
| 38134 | 38209 | |
| 38135 | 38210 | /* Expand the key name with an appropriate prefix and put the result |
| 38136 | | -** zKeyOut[]. The zKeyOut[] buffer is assumed to hold at least |
| 38211 | +** in zKeyOut[]. The zKeyOut[] buffer is assumed to hold at least |
| 38137 | 38212 | ** KVSTORAGE_KEY_SZ bytes. |
| 38138 | 38213 | */ |
| 38139 | 38214 | static void kvstorageMakeKey( |
| 38140 | 38215 | const char *zClass, |
| 38141 | 38216 | const char *zKeyIn, |
| | @@ -38190,14 +38265,16 @@ |
| 38190 | 38265 | ** enough to hold it all. The value put into zBuf must always be zero |
| 38191 | 38266 | ** terminated, even if it gets truncated because nBuf is not large enough. |
| 38192 | 38267 | ** |
| 38193 | 38268 | ** Return the total number of bytes in the data, without truncation, and |
| 38194 | 38269 | ** not counting the final zero terminator. Return -1 if the key does |
| 38195 | | -** not exist. |
| 38270 | +** not exist or its key cannot be read. |
| 38196 | 38271 | ** |
| 38197 | | -** If nBuf<=0 then this routine simply returns the size of the data without |
| 38198 | | -** 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. |
| 38199 | 38276 | */ |
| 38200 | 38277 | static int kvstorageRead( |
| 38201 | 38278 | const char *zClass, |
| 38202 | 38279 | const char *zKey, |
| 38203 | 38280 | char *zBuf, |
| | @@ -38242,15 +38319,13 @@ |
| 38242 | 38319 | /* |
| 38243 | 38320 | ** An internal level of indirection which enables us to replace the |
| 38244 | 38321 | ** kvvfs i/o methods with JavaScript implementations in WASM builds. |
| 38245 | 38322 | ** Maintenance reminder: if this struct changes in any way, the JSON |
| 38246 | 38323 | ** rendering of its structure must be updated in |
| 38247 | | -** sqlite3_wasm_enum_json(). There are no binary compatibility |
| 38248 | | -** concerns, so it does not need an iVersion member. This file is |
| 38249 | | -** necessarily always compiled together with sqlite3_wasm_enum_json(), |
| 38250 | | -** and JS code dynamically creates the mapping of members based on |
| 38251 | | -** 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. |
| 38252 | 38327 | */ |
| 38253 | 38328 | typedef struct sqlite3_kvvfs_methods sqlite3_kvvfs_methods; |
| 38254 | 38329 | struct sqlite3_kvvfs_methods { |
| 38255 | 38330 | int (*xRead)(const char *zClass, const char *zKey, char *zBuf, int nBuf); |
| 38256 | 38331 | int (*xWrite)(const char *zClass, const char *zKey, const char *zData); |
| | @@ -38263,12 +38338,12 @@ |
| 38263 | 38338 | ** for JavaScript-side implementations in WASM builds. In such builds |
| 38264 | 38339 | ** it cannot be const, but in native builds it should be so that |
| 38265 | 38340 | ** the compiler can hopefully optimize this level of indirection out. |
| 38266 | 38341 | ** That said, kvvfs is intended primarily for use in WASM builds. |
| 38267 | 38342 | ** |
| 38268 | | -** Note that this is not explicitly flagged as static because the |
| 38269 | | -** 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. |
| 38270 | 38345 | */ |
| 38271 | 38346 | #ifndef SQLITE_WASM |
| 38272 | 38347 | const |
| 38273 | 38348 | #endif |
| 38274 | 38349 | SQLITE_PRIVATE sqlite3_kvvfs_methods sqlite3KvvfsMethods = { |
| | @@ -39437,14 +39512,15 @@ |
| 39437 | 39512 | #define osPwrite64 ((ssize_t(*)(int,const void*,size_t,off64_t))\ |
| 39438 | 39513 | aSyscall[13].pCurrent) |
| 39439 | 39514 | |
| 39440 | 39515 | #if defined(HAVE_FCHMOD) |
| 39441 | 39516 | { "fchmod", (sqlite3_syscall_ptr)fchmod, 0 }, |
| 39517 | +#define osFchmod ((int(*)(int,mode_t))aSyscall[14].pCurrent) |
| 39442 | 39518 | #else |
| 39443 | 39519 | { "fchmod", (sqlite3_syscall_ptr)0, 0 }, |
| 39520 | +#define osFchmod(FID,MODE) 0 |
| 39444 | 39521 | #endif |
| 39445 | | -#define osFchmod ((int(*)(int,mode_t))aSyscall[14].pCurrent) |
| 39446 | 39522 | |
| 39447 | 39523 | #if defined(HAVE_POSIX_FALLOCATE) && HAVE_POSIX_FALLOCATE |
| 39448 | 39524 | { "fallocate", (sqlite3_syscall_ptr)posix_fallocate, 0 }, |
| 39449 | 39525 | #else |
| 39450 | 39526 | { "fallocate", (sqlite3_syscall_ptr)0, 0 }, |
| | @@ -39698,13 +39774,12 @@ |
| 39698 | 39774 | return fd; |
| 39699 | 39775 | } |
| 39700 | 39776 | |
| 39701 | 39777 | /* |
| 39702 | 39778 | ** Helper functions to obtain and relinquish the global mutex. The |
| 39703 | | -** global mutex is used to protect the unixInodeInfo and |
| 39704 | | -** vxworksFileId objects used by this file, all of which may be |
| 39705 | | -** 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. |
| 39706 | 39781 | ** |
| 39707 | 39782 | ** Function unixMutexHeld() is used to assert() that the global mutex |
| 39708 | 39783 | ** is held when required. This function is only used as part of assert() |
| 39709 | 39784 | ** statements. e.g. |
| 39710 | 39785 | ** |
| | @@ -39902,10 +39977,11 @@ |
| 39902 | 39977 | /* |
| 39903 | 39978 | ** All unique filenames are held on a linked list headed by this |
| 39904 | 39979 | ** variable: |
| 39905 | 39980 | */ |
| 39906 | 39981 | static struct vxworksFileId *vxworksFileList = 0; |
| 39982 | +static sqlite3_mutex *vxworksMutex = 0; |
| 39907 | 39983 | |
| 39908 | 39984 | /* |
| 39909 | 39985 | ** Simplify a filename into its canonical form |
| 39910 | 39986 | ** by making the following changes: |
| 39911 | 39987 | ** |
| | @@ -39967,47 +40043,47 @@ |
| 39967 | 40043 | |
| 39968 | 40044 | /* Search for an existing entry that matching the canonical name. |
| 39969 | 40045 | ** If found, increment the reference count and return a pointer to |
| 39970 | 40046 | ** the existing file ID. |
| 39971 | 40047 | */ |
| 39972 | | - unixEnterMutex(); |
| 40048 | + sqlite3_mutex_enter(vxworksMutex); |
| 39973 | 40049 | for(pCandidate=vxworksFileList; pCandidate; pCandidate=pCandidate->pNext){ |
| 39974 | 40050 | if( pCandidate->nName==n |
| 39975 | 40051 | && memcmp(pCandidate->zCanonicalName, pNew->zCanonicalName, n)==0 |
| 39976 | 40052 | ){ |
| 39977 | 40053 | sqlite3_free(pNew); |
| 39978 | 40054 | pCandidate->nRef++; |
| 39979 | | - unixLeaveMutex(); |
| 40055 | + sqlite3_mutex_leave(vxworksMutex); |
| 39980 | 40056 | return pCandidate; |
| 39981 | 40057 | } |
| 39982 | 40058 | } |
| 39983 | 40059 | |
| 39984 | 40060 | /* No match was found. We will make a new file ID */ |
| 39985 | 40061 | pNew->nRef = 1; |
| 39986 | 40062 | pNew->nName = n; |
| 39987 | 40063 | pNew->pNext = vxworksFileList; |
| 39988 | 40064 | vxworksFileList = pNew; |
| 39989 | | - unixLeaveMutex(); |
| 40065 | + sqlite3_mutex_leave(vxworksMutex); |
| 39990 | 40066 | return pNew; |
| 39991 | 40067 | } |
| 39992 | 40068 | |
| 39993 | 40069 | /* |
| 39994 | 40070 | ** Decrement the reference count on a vxworksFileId object. Free |
| 39995 | 40071 | ** the object when the reference count reaches zero. |
| 39996 | 40072 | */ |
| 39997 | 40073 | static void vxworksReleaseFileId(struct vxworksFileId *pId){ |
| 39998 | | - unixEnterMutex(); |
| 40074 | + sqlite3_mutex_enter(vxworksMutex); |
| 39999 | 40075 | assert( pId->nRef>0 ); |
| 40000 | 40076 | pId->nRef--; |
| 40001 | 40077 | if( pId->nRef==0 ){ |
| 40002 | 40078 | struct vxworksFileId **pp; |
| 40003 | 40079 | for(pp=&vxworksFileList; *pp && *pp!=pId; pp = &((*pp)->pNext)){} |
| 40004 | 40080 | assert( *pp==pId ); |
| 40005 | 40081 | *pp = pId->pNext; |
| 40006 | 40082 | sqlite3_free(pId); |
| 40007 | 40083 | } |
| 40008 | | - unixLeaveMutex(); |
| 40084 | + sqlite3_mutex_leave(vxworksMutex); |
| 40009 | 40085 | } |
| 40010 | 40086 | #endif /* OS_VXWORKS */ |
| 40011 | 40087 | /*************** End of Unique File ID Utility Used By VxWorks **************** |
| 40012 | 40088 | ******************************************************************************/ |
| 40013 | 40089 | |
| | @@ -40391,10 +40467,14 @@ |
| 40391 | 40467 | do{ rc = osWrite(fd, "S", 1); }while( rc<0 && errno==EINTR ); |
| 40392 | 40468 | if( rc!=1 ){ |
| 40393 | 40469 | storeLastErrno(pFile, errno); |
| 40394 | 40470 | return SQLITE_IOERR; |
| 40395 | 40471 | } |
| 40472 | + if( fsync(fd) ){ |
| 40473 | + storeLastErrno(pFile, errno); |
| 40474 | + return SQLITE_IOERR_FSYNC; |
| 40475 | + } |
| 40396 | 40476 | rc = osFstat(fd, &statbuf); |
| 40397 | 40477 | if( rc!=0 ){ |
| 40398 | 40478 | storeLastErrno(pFile, errno); |
| 40399 | 40479 | return SQLITE_IOERR; |
| 40400 | 40480 | } |
| | @@ -40560,22 +40640,46 @@ |
| 40560 | 40640 | static int osSetPosixAdvisoryLock( |
| 40561 | 40641 | int h, /* The file descriptor on which to take the lock */ |
| 40562 | 40642 | struct flock *pLock, /* The description of the lock */ |
| 40563 | 40643 | unixFile *pFile /* Structure holding timeout value */ |
| 40564 | 40644 | ){ |
| 40565 | | - int tm = pFile->iBusyTimeout; |
| 40566 | | - int rc = osFcntl(h,F_SETLK,pLock); |
| 40567 | | - while( rc<0 && tm>0 ){ |
| 40568 | | - /* On systems that support some kind of blocking file lock with a timeout, |
| 40569 | | - ** make appropriate changes here to invoke that blocking file lock. On |
| 40570 | | - ** generic posix, however, there is no such API. So we simply try the |
| 40571 | | - ** lock once every millisecond until either the timeout expires, or until |
| 40572 | | - ** the lock is obtained. */ |
| 40573 | | - unixSleep(0,1000); |
| 40645 | + int rc = 0; |
| 40646 | + |
| 40647 | + if( pFile->iBusyTimeout==0 ){ |
| 40648 | + /* unixFile->iBusyTimeout is set to 0. In this case, attempt a |
| 40649 | + ** non-blocking lock. */ |
| 40650 | + rc = osFcntl(h,F_SETLK,pLock); |
| 40651 | + }else{ |
| 40652 | + /* unixFile->iBusyTimeout is set to greater than zero. In this case, |
| 40653 | + ** attempt a blocking-lock with a unixFile->iBusyTimeout ms timeout. |
| 40654 | + ** |
| 40655 | + ** On systems that support some kind of blocking file lock operation, |
| 40656 | + ** this block should be replaced by code to attempt a blocking lock |
| 40657 | + ** with a timeout of unixFile->iBusyTimeout ms. The code below is |
| 40658 | + ** placeholder code. If SQLITE_TEST is defined, the placeholder code |
| 40659 | + ** retries the lock once every 1ms until it succeeds or the timeout |
| 40660 | + ** is reached. Or, if SQLITE_TEST is not defined, the placeholder |
| 40661 | + ** code attempts a non-blocking lock and sets unixFile->iBusyTimeout |
| 40662 | + ** to 0. This causes the caller to return SQLITE_BUSY, instead of |
| 40663 | + ** SQLITE_BUSY_TIMEOUT to SQLite - as required by a VFS that does not |
| 40664 | + ** support blocking locks. |
| 40665 | + */ |
| 40666 | +#ifdef SQLITE_TEST |
| 40667 | + int tm = pFile->iBusyTimeout; |
| 40668 | + while( tm>0 ){ |
| 40669 | + rc = osFcntl(h,F_SETLK,pLock); |
| 40670 | + if( rc==0 ) break; |
| 40671 | + unixSleep(0,1000); |
| 40672 | + tm--; |
| 40673 | + } |
| 40674 | +#else |
| 40574 | 40675 | rc = osFcntl(h,F_SETLK,pLock); |
| 40575 | | - tm--; |
| 40676 | + pFile->iBusyTimeout = 0; |
| 40677 | +#endif |
| 40678 | + /* End of code to replace with real blocking-locks code. */ |
| 40576 | 40679 | } |
| 40680 | + |
| 40577 | 40681 | return rc; |
| 40578 | 40682 | } |
| 40579 | 40683 | #endif /* SQLITE_ENABLE_SETLK_TIMEOUT */ |
| 40580 | 40684 | |
| 40581 | 40685 | |
| | @@ -44892,14 +44996,21 @@ |
| 44892 | 44996 | #endif |
| 44893 | 44997 | |
| 44894 | 44998 | storeLastErrno(pNew, 0); |
| 44895 | 44999 | #if OS_VXWORKS |
| 44896 | 45000 | if( rc!=SQLITE_OK ){ |
| 44897 | | - if( h>=0 ) robust_close(pNew, h, __LINE__); |
| 44898 | | - h = -1; |
| 44899 | | - osUnlink(zFilename); |
| 44900 | | - 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 | + } |
| 44901 | 45012 | } |
| 44902 | 45013 | #endif |
| 44903 | 45014 | if( rc!=SQLITE_OK ){ |
| 44904 | 45015 | if( h>=0 ) robust_close(pNew, h, __LINE__); |
| 44905 | 45016 | }else{ |
| | @@ -44939,10 +45050,13 @@ |
| 44939 | 45050 | struct stat buf; |
| 44940 | 45051 | const char *zDir = sqlite3_temp_directory; |
| 44941 | 45052 | |
| 44942 | 45053 | while(1){ |
| 44943 | 45054 | if( zDir!=0 |
| 45055 | +#if OS_VXWORKS |
| 45056 | + && zDir[0]=='/' |
| 45057 | +#endif |
| 44944 | 45058 | && osStat(zDir, &buf)==0 |
| 44945 | 45059 | && S_ISDIR(buf.st_mode) |
| 44946 | 45060 | && osAccess(zDir, 03)==0 |
| 44947 | 45061 | ){ |
| 44948 | 45062 | return zDir; |
| | @@ -45252,10 +45366,16 @@ |
| 45252 | 45366 | assert( eType==SQLITE_OPEN_MAIN_DB || eType==SQLITE_OPEN_TEMP_DB |
| 45253 | 45367 | || eType==SQLITE_OPEN_MAIN_JOURNAL || eType==SQLITE_OPEN_TEMP_JOURNAL |
| 45254 | 45368 | || eType==SQLITE_OPEN_SUBJOURNAL || eType==SQLITE_OPEN_SUPER_JOURNAL |
| 45255 | 45369 | || eType==SQLITE_OPEN_TRANSIENT_DB || eType==SQLITE_OPEN_WAL |
| 45256 | 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 |
| 45257 | 45377 | |
| 45258 | 45378 | /* Detect a pid change and reset the PRNG. There is a race condition |
| 45259 | 45379 | ** here such that two or more threads all trying to open databases at |
| 45260 | 45380 | ** the same instant might all reset the PRNG. But multiple resets |
| 45261 | 45381 | ** are harmless. |
| | @@ -45453,12 +45573,15 @@ |
| 45453 | 45573 | goto open_finished; |
| 45454 | 45574 | } |
| 45455 | 45575 | } |
| 45456 | 45576 | #endif |
| 45457 | 45577 | |
| 45458 | | - assert( zPath==0 || zPath[0]=='/' |
| 45459 | | - || 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 |
| 45460 | 45583 | ); |
| 45461 | 45584 | rc = fillInUnixFile(pVfs, fd, pFile, zPath, ctrlFlags); |
| 45462 | 45585 | |
| 45463 | 45586 | open_finished: |
| 45464 | 45587 | if( rc!=SQLITE_OK ){ |
| | @@ -47183,10 +47306,13 @@ |
| 47183 | 47306 | } |
| 47184 | 47307 | #ifdef SQLITE_OS_KV_OPTIONAL |
| 47185 | 47308 | sqlite3KvvfsInit(); |
| 47186 | 47309 | #endif |
| 47187 | 47310 | unixBigLock = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1); |
| 47311 | +#if OS_VXWORKS |
| 47312 | + vxworksMutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS2); |
| 47313 | +#endif |
| 47188 | 47314 | |
| 47189 | 47315 | #ifndef SQLITE_OMIT_WAL |
| 47190 | 47316 | /* Validate lock assumptions */ |
| 47191 | 47317 | assert( SQLITE_SHM_NLOCK==8 ); /* Number of available locks */ |
| 47192 | 47318 | assert( UNIX_SHM_BASE==120 ); /* Start of locking area */ |
| | @@ -47217,10 +47343,13 @@ |
| 47217 | 47343 | ** to release dynamically allocated objects. But not on unix. |
| 47218 | 47344 | ** This routine is a no-op for unix. |
| 47219 | 47345 | */ |
| 47220 | 47346 | SQLITE_API int sqlite3_os_end(void){ |
| 47221 | 47347 | unixBigLock = 0; |
| 47348 | +#if OS_VXWORKS |
| 47349 | + vxworksMutex = 0; |
| 47350 | +#endif |
| 47222 | 47351 | return SQLITE_OK; |
| 47223 | 47352 | } |
| 47224 | 47353 | |
| 47225 | 47354 | #endif /* SQLITE_OS_UNIX */ |
| 47226 | 47355 | |
| | @@ -51349,33 +51478,39 @@ |
| 51349 | 51478 | ** log-summary, each thread has its own winFile object, but they all |
| 51350 | 51479 | ** point to a single instance of this object. In other words, each |
| 51351 | 51480 | ** log-summary is opened only once per process. |
| 51352 | 51481 | ** |
| 51353 | 51482 | ** winShmMutexHeld() must be true when creating or destroying |
| 51354 | | -** this object or while reading or writing the following fields: |
| 51483 | +** this object, or while editing the global linked list that starts |
| 51484 | +** at winShmNodeList. |
| 51355 | 51485 | ** |
| 51356 | | -** nRef |
| 51357 | | -** pNext |
| 51486 | +** When reading or writing the linked list starting at winShmNode.pWinShmList, |
| 51487 | +** pShmNode->mutex must be held. |
| 51358 | 51488 | ** |
| 51359 | | -** The following fields are read-only after the object is created: |
| 51489 | +** The following fields are constant after the object is created: |
| 51360 | 51490 | ** |
| 51361 | 51491 | ** zFilename |
| 51492 | +** hSharedShm |
| 51493 | +** mutex |
| 51494 | +** bUseSharedLockHandle |
| 51362 | 51495 | ** |
| 51363 | | -** Either winShmNode.mutex must be held or winShmNode.nRef==0 and |
| 51496 | +** Either winShmNode.mutex must be held or winShmNode.pWinShmList==0 and |
| 51364 | 51497 | ** winShmMutexHeld() is true when reading or writing any other field |
| 51365 | 51498 | ** in this structure. |
| 51366 | 51499 | ** |
| 51367 | | -** File-handle hSharedShm is used to (a) take the DMS lock, (b) truncate |
| 51368 | | -** the *-shm file if the DMS-locking protocol demands it, and (c) map |
| 51369 | | -** regions of the *-shm file into memory using MapViewOfFile() or |
| 51370 | | -** similar. Other locks are taken by individual clients using the |
| 51371 | | -** winShm.hShm handles. |
| 51500 | +** File-handle hSharedShm is always used to (a) take the DMS lock, (b) |
| 51501 | +** truncate the *-shm file if the DMS-locking protocol demands it, and |
| 51502 | +** (c) map regions of the *-shm file into memory using MapViewOfFile() |
| 51503 | +** or similar. If bUseSharedLockHandle is true, then other locks are also |
| 51504 | +** taken on hSharedShm. Or, if bUseSharedLockHandle is false, then other |
| 51505 | +** locks are taken using each connection's winShm.hShm handles. |
| 51372 | 51506 | */ |
| 51373 | 51507 | struct winShmNode { |
| 51374 | 51508 | sqlite3_mutex *mutex; /* Mutex to access this object */ |
| 51375 | 51509 | char *zFilename; /* Name of the file */ |
| 51376 | 51510 | HANDLE hSharedShm; /* File handle open on zFilename */ |
| 51511 | + int bUseSharedLockHandle; /* True to use hSharedShm for everything */ |
| 51377 | 51512 | |
| 51378 | 51513 | int isUnlocked; /* DMS lock has not yet been obtained */ |
| 51379 | 51514 | int isReadonly; /* True if read-only */ |
| 51380 | 51515 | int szRegion; /* Size of shared-memory regions */ |
| 51381 | 51516 | int nRegion; /* Size of array apRegion */ |
| | @@ -51384,11 +51519,12 @@ |
| 51384 | 51519 | HANDLE hMap; /* File handle from CreateFileMapping */ |
| 51385 | 51520 | void *pMap; |
| 51386 | 51521 | } *aRegion; |
| 51387 | 51522 | DWORD lastErrno; /* The Windows errno from the last I/O error */ |
| 51388 | 51523 | |
| 51389 | | - int nRef; /* Number of winShm objects pointing to this */ |
| 51524 | + winShm *pWinShmList; /* List of winShm objects with ptrs to this */ |
| 51525 | + |
| 51390 | 51526 | winShmNode *pNext; /* Next in list of all winShmNode objects */ |
| 51391 | 51527 | #if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE) |
| 51392 | 51528 | u8 nextShmId; /* Next available winShm.id value */ |
| 51393 | 51529 | #endif |
| 51394 | 51530 | }; |
| | @@ -51412,10 +51548,11 @@ |
| 51412 | 51548 | HANDLE hShm; /* File-handle on *-shm file. For locking. */ |
| 51413 | 51549 | int bReadonly; /* True if hShm is opened read-only */ |
| 51414 | 51550 | #if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE) |
| 51415 | 51551 | u8 id; /* Id of this connection with its winShmNode */ |
| 51416 | 51552 | #endif |
| 51553 | + winShm *pWinShmNext; /* Next winShm object on same winShmNode */ |
| 51417 | 51554 | }; |
| 51418 | 51555 | |
| 51419 | 51556 | /* |
| 51420 | 51557 | ** Constants used for locking |
| 51421 | 51558 | */ |
| | @@ -51425,11 +51562,11 @@ |
| 51425 | 51562 | /* Forward references to VFS methods */ |
| 51426 | 51563 | static int winOpen(sqlite3_vfs*,const char*,sqlite3_file*,int,int*); |
| 51427 | 51564 | static int winDelete(sqlite3_vfs *,const char*,int); |
| 51428 | 51565 | |
| 51429 | 51566 | /* |
| 51430 | | -** Purge the winShmNodeList list of all entries with winShmNode.nRef==0. |
| 51567 | +** Purge the winShmNodeList list of all entries with winShmNode.pWinShmList==0. |
| 51431 | 51568 | ** |
| 51432 | 51569 | ** This is not a VFS shared-memory method; it is a utility function called |
| 51433 | 51570 | ** by VFS shared-memory methods. |
| 51434 | 51571 | */ |
| 51435 | 51572 | static void winShmPurge(sqlite3_vfs *pVfs, int deleteFlag){ |
| | @@ -51438,11 +51575,11 @@ |
| 51438 | 51575 | assert( winShmMutexHeld() ); |
| 51439 | 51576 | OSTRACE(("SHM-PURGE pid=%lu, deleteFlag=%d\n", |
| 51440 | 51577 | osGetCurrentProcessId(), deleteFlag)); |
| 51441 | 51578 | pp = &winShmNodeList; |
| 51442 | 51579 | while( (p = *pp)!=0 ){ |
| 51443 | | - if( p->nRef==0 ){ |
| 51580 | + if( p->pWinShmList==0 ){ |
| 51444 | 51581 | int i; |
| 51445 | 51582 | if( p->mutex ){ sqlite3_mutex_free(p->mutex); } |
| 51446 | 51583 | for(i=0; i<p->nRegion; i++){ |
| 51447 | 51584 | BOOL bRc = osUnmapViewOfFile(p->aRegion[i].pMap); |
| 51448 | 51585 | OSTRACE(("SHM-PURGE-UNMAP pid=%lu, region=%d, rc=%s\n", |
| | @@ -51602,10 +51739,64 @@ |
| 51602 | 51739 | *pbReadonly = bReadonly; |
| 51603 | 51740 | *ph = h; |
| 51604 | 51741 | return rc; |
| 51605 | 51742 | } |
| 51606 | 51743 | |
| 51744 | +/* |
| 51745 | +** Close pDbFd's connection to shared-memory. Delete the underlying |
| 51746 | +** *-shm file if deleteFlag is true. |
| 51747 | +*/ |
| 51748 | +static int winCloseSharedMemory(winFile *pDbFd, int deleteFlag){ |
| 51749 | + winShm *p; /* The connection to be closed */ |
| 51750 | + winShm **pp; /* Iterator for pShmNode->pWinShmList */ |
| 51751 | + winShmNode *pShmNode; /* The underlying shared-memory file */ |
| 51752 | + |
| 51753 | + p = pDbFd->pShm; |
| 51754 | + if( p==0 ) return SQLITE_OK; |
| 51755 | + if( p->hShm!=INVALID_HANDLE_VALUE ){ |
| 51756 | + osCloseHandle(p->hShm); |
| 51757 | + } |
| 51758 | + |
| 51759 | + winShmEnterMutex(); |
| 51760 | + pShmNode = p->pShmNode; |
| 51761 | + |
| 51762 | + /* Remove this connection from the winShmNode.pWinShmList list */ |
| 51763 | + sqlite3_mutex_enter(pShmNode->mutex); |
| 51764 | + for(pp=&pShmNode->pWinShmList; *pp!=p; pp=&(*pp)->pWinShmNext){} |
| 51765 | + *pp = p->pWinShmNext; |
| 51766 | + sqlite3_mutex_leave(pShmNode->mutex); |
| 51767 | + |
| 51768 | + winShmPurge(pDbFd->pVfs, deleteFlag); |
| 51769 | + winShmLeaveMutex(); |
| 51770 | + |
| 51771 | + /* Free the connection p */ |
| 51772 | + sqlite3_free(p); |
| 51773 | + pDbFd->pShm = 0; |
| 51774 | + return SQLITE_OK; |
| 51775 | +} |
| 51776 | + |
| 51777 | +/* |
| 51778 | +** testfixture builds may set this global variable to true via a |
| 51779 | +** Tcl interface. This forces the VFS to use the locking normally |
| 51780 | +** only used for UNC paths for all files. |
| 51781 | +*/ |
| 51782 | +#ifdef SQLITE_TEST |
| 51783 | +SQLITE_API int sqlite3_win_test_unc_locking = 0; |
| 51784 | +#else |
| 51785 | +# define sqlite3_win_test_unc_locking 0 |
| 51786 | +#endif |
| 51787 | + |
| 51788 | +/* |
| 51789 | +** Return true if the string passed as the only argument is likely |
| 51790 | +** to be a UNC path. In other words, if it starts with "\\". |
| 51791 | +*/ |
| 51792 | +static int winIsUNCPath(const char *zFile){ |
| 51793 | + if( zFile[0]=='\\' && zFile[1]=='\\' ){ |
| 51794 | + return 1; |
| 51795 | + } |
| 51796 | + return sqlite3_win_test_unc_locking; |
| 51797 | +} |
| 51607 | 51798 | |
| 51608 | 51799 | /* |
| 51609 | 51800 | ** Open the shared-memory area associated with database file pDbFd. |
| 51610 | 51801 | */ |
| 51611 | 51802 | static int winOpenSharedMemory(winFile *pDbFd){ |
| | @@ -51628,19 +51819,14 @@ |
| 51628 | 51819 | return SQLITE_IOERR_NOMEM_BKPT; |
| 51629 | 51820 | } |
| 51630 | 51821 | pNew->zFilename = (char*)&pNew[1]; |
| 51631 | 51822 | pNew->hSharedShm = INVALID_HANDLE_VALUE; |
| 51632 | 51823 | pNew->isUnlocked = 1; |
| 51824 | + pNew->bUseSharedLockHandle = winIsUNCPath(pDbFd->zPath); |
| 51633 | 51825 | sqlite3_snprintf(nName+15, pNew->zFilename, "%s-shm", pDbFd->zPath); |
| 51634 | 51826 | sqlite3FileSuffix3(pDbFd->zPath, pNew->zFilename); |
| 51635 | 51827 | |
| 51636 | | - /* Open a file-handle on the *-shm file for this connection. This file-handle |
| 51637 | | - ** is only used for locking. The mapping of the *-shm file is created using |
| 51638 | | - ** the shared file handle in winShmNode.hSharedShm. */ |
| 51639 | | - p->bReadonly = sqlite3_uri_boolean(pDbFd->zPath, "readonly_shm", 0); |
| 51640 | | - rc = winHandleOpen(pNew->zFilename, &p->bReadonly, &p->hShm); |
| 51641 | | - |
| 51642 | 51828 | /* Look to see if there is an existing winShmNode that can be used. |
| 51643 | 51829 | ** If no matching winShmNode currently exists, then create a new one. */ |
| 51644 | 51830 | winShmEnterMutex(); |
| 51645 | 51831 | for(pShmNode = winShmNodeList; pShmNode; pShmNode=pShmNode->pNext){ |
| 51646 | 51832 | /* TBD need to come up with better match here. Perhaps |
| | @@ -51657,11 +51843,11 @@ |
| 51657 | 51843 | } |
| 51658 | 51844 | |
| 51659 | 51845 | /* Open a file-handle to use for mappings, and for the DMS lock. */ |
| 51660 | 51846 | if( rc==SQLITE_OK ){ |
| 51661 | 51847 | HANDLE h = INVALID_HANDLE_VALUE; |
| 51662 | | - pShmNode->isReadonly = p->bReadonly; |
| 51848 | + pShmNode->isReadonly = sqlite3_uri_boolean(pDbFd->zPath,"readonly_shm",0); |
| 51663 | 51849 | rc = winHandleOpen(pNew->zFilename, &pShmNode->isReadonly, &h); |
| 51664 | 51850 | pShmNode->hSharedShm = h; |
| 51665 | 51851 | } |
| 51666 | 51852 | |
| 51667 | 51853 | /* If successful, link the new winShmNode into the global list. If an |
| | @@ -51679,24 +51865,39 @@ |
| 51679 | 51865 | } |
| 51680 | 51866 | |
| 51681 | 51867 | /* If no error has occurred, link the winShm object to the winShmNode and |
| 51682 | 51868 | ** the winShm to pDbFd. */ |
| 51683 | 51869 | if( rc==SQLITE_OK ){ |
| 51870 | + sqlite3_mutex_enter(pShmNode->mutex); |
| 51684 | 51871 | p->pShmNode = pShmNode; |
| 51685 | | - pShmNode->nRef++; |
| 51872 | + p->pWinShmNext = pShmNode->pWinShmList; |
| 51873 | + pShmNode->pWinShmList = p; |
| 51686 | 51874 | #if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE) |
| 51687 | 51875 | p->id = pShmNode->nextShmId++; |
| 51688 | 51876 | #endif |
| 51689 | 51877 | pDbFd->pShm = p; |
| 51878 | + sqlite3_mutex_leave(pShmNode->mutex); |
| 51690 | 51879 | }else if( p ){ |
| 51691 | | - winHandleClose(p->hShm); |
| 51692 | 51880 | sqlite3_free(p); |
| 51693 | 51881 | } |
| 51694 | 51882 | |
| 51695 | 51883 | assert( rc!=SQLITE_OK || pShmNode->isUnlocked==0 || pShmNode->nRegion==0 ); |
| 51696 | 51884 | winShmLeaveMutex(); |
| 51697 | 51885 | sqlite3_free(pNew); |
| 51886 | + |
| 51887 | + /* Open a file-handle on the *-shm file for this connection. This file-handle |
| 51888 | + ** is only used for locking. The mapping of the *-shm file is created using |
| 51889 | + ** the shared file handle in winShmNode.hSharedShm. */ |
| 51890 | + if( rc==SQLITE_OK && pShmNode->bUseSharedLockHandle==0 ){ |
| 51891 | + p->bReadonly = sqlite3_uri_boolean(pDbFd->zPath, "readonly_shm", 0); |
| 51892 | + rc = winHandleOpen(pShmNode->zFilename, &p->bReadonly, &p->hShm); |
| 51893 | + if( rc!=SQLITE_OK ){ |
| 51894 | + assert( p->hShm==INVALID_HANDLE_VALUE ); |
| 51895 | + winCloseSharedMemory(pDbFd, 0); |
| 51896 | + } |
| 51897 | + } |
| 51898 | + |
| 51698 | 51899 | return rc; |
| 51699 | 51900 | } |
| 51700 | 51901 | |
| 51701 | 51902 | /* |
| 51702 | 51903 | ** Close a connection to shared-memory. Delete the underlying |
| | @@ -51704,37 +51905,11 @@ |
| 51704 | 51905 | */ |
| 51705 | 51906 | static int winShmUnmap( |
| 51706 | 51907 | sqlite3_file *fd, /* Database holding shared memory */ |
| 51707 | 51908 | int deleteFlag /* Delete after closing if true */ |
| 51708 | 51909 | ){ |
| 51709 | | - winFile *pDbFd; /* Database holding shared-memory */ |
| 51710 | | - winShm *p; /* The connection to be closed */ |
| 51711 | | - winShmNode *pShmNode; /* The underlying shared-memory file */ |
| 51712 | | - |
| 51713 | | - pDbFd = (winFile*)fd; |
| 51714 | | - p = pDbFd->pShm; |
| 51715 | | - if( p==0 ) return SQLITE_OK; |
| 51716 | | - if( p->hShm!=INVALID_HANDLE_VALUE ){ |
| 51717 | | - osCloseHandle(p->hShm); |
| 51718 | | - } |
| 51719 | | - |
| 51720 | | - pShmNode = p->pShmNode; |
| 51721 | | - winShmEnterMutex(); |
| 51722 | | - |
| 51723 | | - /* If pShmNode->nRef has reached 0, then close the underlying |
| 51724 | | - ** shared-memory file, too. */ |
| 51725 | | - assert( pShmNode->nRef>0 ); |
| 51726 | | - pShmNode->nRef--; |
| 51727 | | - if( pShmNode->nRef==0 ){ |
| 51728 | | - winShmPurge(pDbFd->pVfs, deleteFlag); |
| 51729 | | - } |
| 51730 | | - winShmLeaveMutex(); |
| 51731 | | - |
| 51732 | | - /* Free the connection p */ |
| 51733 | | - sqlite3_free(p); |
| 51734 | | - pDbFd->pShm = 0; |
| 51735 | | - return SQLITE_OK; |
| 51910 | + return winCloseSharedMemory((winFile*)fd, deleteFlag); |
| 51736 | 51911 | } |
| 51737 | 51912 | |
| 51738 | 51913 | /* |
| 51739 | 51914 | ** Change the lock state for a shared-memory segment. |
| 51740 | 51915 | */ |
| | @@ -51799,29 +51974,75 @@ |
| 51799 | 51974 | ); |
| 51800 | 51975 | if( ((flags & SQLITE_SHM_UNLOCK) && ((p->exclMask|p->sharedMask) & mask)) |
| 51801 | 51976 | || (flags==(SQLITE_SHM_SHARED|SQLITE_SHM_LOCK) && 0==(p->sharedMask & mask)) |
| 51802 | 51977 | || (flags==(SQLITE_SHM_EXCLUSIVE|SQLITE_SHM_LOCK)) |
| 51803 | 51978 | ){ |
| 51979 | + HANDLE h = p->hShm; |
| 51804 | 51980 | |
| 51805 | 51981 | if( flags & SQLITE_SHM_UNLOCK ){ |
| 51806 | 51982 | /* Case (a) - unlock. */ |
| 51807 | 51983 | |
| 51808 | 51984 | assert( (p->exclMask & p->sharedMask)==0 ); |
| 51809 | 51985 | assert( !(flags & SQLITE_SHM_EXCLUSIVE) || (p->exclMask & mask)==mask ); |
| 51810 | 51986 | assert( !(flags & SQLITE_SHM_SHARED) || (p->sharedMask & mask)==mask ); |
| 51811 | 51987 | |
| 51812 | | - rc = winHandleUnlock(p->hShm, ofst+WIN_SHM_BASE, n); |
| 51988 | + assert( !(flags & SQLITE_SHM_SHARED) || n==1 ); |
| 51989 | + if( pShmNode->bUseSharedLockHandle ){ |
| 51990 | + h = pShmNode->hSharedShm; |
| 51991 | + if( flags & SQLITE_SHM_SHARED ){ |
| 51992 | + winShm *pShm; |
| 51993 | + sqlite3_mutex_enter(pShmNode->mutex); |
| 51994 | + for(pShm=pShmNode->pWinShmList; pShm; pShm=pShm->pWinShmNext){ |
| 51995 | + if( pShm!=p && (pShm->sharedMask & mask) ){ |
| 51996 | + /* Another connection within this process is also holding this |
| 51997 | + ** SHARED lock. So do not actually release the OS lock. */ |
| 51998 | + h = INVALID_HANDLE_VALUE; |
| 51999 | + break; |
| 52000 | + } |
| 52001 | + } |
| 52002 | + sqlite3_mutex_leave(pShmNode->mutex); |
| 52003 | + } |
| 52004 | + } |
| 52005 | + |
| 52006 | + if( h!=INVALID_HANDLE_VALUE ){ |
| 52007 | + rc = winHandleUnlock(h, ofst+WIN_SHM_BASE, n); |
| 52008 | + } |
| 51813 | 52009 | |
| 51814 | 52010 | /* If successful, also clear the bits in sharedMask/exclMask */ |
| 51815 | 52011 | if( rc==SQLITE_OK ){ |
| 51816 | 52012 | p->exclMask = (p->exclMask & ~mask); |
| 51817 | 52013 | p->sharedMask = (p->sharedMask & ~mask); |
| 51818 | 52014 | } |
| 51819 | 52015 | }else{ |
| 51820 | 52016 | int bExcl = ((flags & SQLITE_SHM_EXCLUSIVE) ? 1 : 0); |
| 51821 | 52017 | DWORD nMs = winFileBusyTimeout(pDbFd); |
| 51822 | | - rc = winHandleLockTimeout(p->hShm, ofst+WIN_SHM_BASE, n, bExcl, nMs); |
| 52018 | + |
| 52019 | + if( pShmNode->bUseSharedLockHandle ){ |
| 52020 | + winShm *pShm; |
| 52021 | + h = pShmNode->hSharedShm; |
| 52022 | + sqlite3_mutex_enter(pShmNode->mutex); |
| 52023 | + for(pShm=pShmNode->pWinShmList; pShm; pShm=pShm->pWinShmNext){ |
| 52024 | + if( bExcl ){ |
| 52025 | + if( (pShm->sharedMask|pShm->exclMask) & mask ){ |
| 52026 | + rc = SQLITE_BUSY; |
| 52027 | + h = INVALID_HANDLE_VALUE; |
| 52028 | + } |
| 52029 | + }else{ |
| 52030 | + if( pShm->sharedMask & mask ){ |
| 52031 | + h = INVALID_HANDLE_VALUE; |
| 52032 | + }else if( pShm->exclMask & mask ){ |
| 52033 | + rc = SQLITE_BUSY; |
| 52034 | + h = INVALID_HANDLE_VALUE; |
| 52035 | + } |
| 52036 | + } |
| 52037 | + } |
| 52038 | + sqlite3_mutex_leave(pShmNode->mutex); |
| 52039 | + } |
| 52040 | + |
| 52041 | + if( h!=INVALID_HANDLE_VALUE ){ |
| 52042 | + rc = winHandleLockTimeout(h, ofst+WIN_SHM_BASE, n, bExcl, nMs); |
| 52043 | + } |
| 51823 | 52044 | if( rc==SQLITE_OK ){ |
| 51824 | 52045 | if( bExcl ){ |
| 51825 | 52046 | p->exclMask = (p->exclMask | mask); |
| 51826 | 52047 | }else{ |
| 51827 | 52048 | p->sharedMask = (p->sharedMask | mask); |
| | @@ -61848,18 +62069,31 @@ |
| 61848 | 62069 | SQLITE_PRIVATE void sqlite3PagerSetFlags( |
| 61849 | 62070 | Pager *pPager, /* The pager to set safety level for */ |
| 61850 | 62071 | unsigned pgFlags /* Various flags */ |
| 61851 | 62072 | ){ |
| 61852 | 62073 | unsigned level = pgFlags & PAGER_SYNCHRONOUS_MASK; |
| 61853 | | - if( pPager->tempFile ){ |
| 62074 | + if( pPager->tempFile || level==PAGER_SYNCHRONOUS_OFF ){ |
| 61854 | 62075 | pPager->noSync = 1; |
| 61855 | 62076 | pPager->fullSync = 0; |
| 61856 | 62077 | pPager->extraSync = 0; |
| 61857 | 62078 | }else{ |
| 61858 | | - pPager->noSync = level==PAGER_SYNCHRONOUS_OFF ?1:0; |
| 62079 | + pPager->noSync = 0; |
| 61859 | 62080 | pPager->fullSync = level>=PAGER_SYNCHRONOUS_FULL ?1:0; |
| 61860 | | - 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 | + } |
| 61861 | 62095 | } |
| 61862 | 62096 | if( pPager->noSync ){ |
| 61863 | 62097 | pPager->syncFlags = 0; |
| 61864 | 62098 | }else if( pgFlags & PAGER_FULLFSYNC ){ |
| 61865 | 62099 | pPager->syncFlags = SQLITE_SYNC_FULL; |
| | @@ -65748,11 +65982,11 @@ |
| 65748 | 65982 | */ |
| 65749 | 65983 | sqlite3_exec(db, "PRAGMA table_list",0,0,0); |
| 65750 | 65984 | } |
| 65751 | 65985 | if( pPager->pWal ){ |
| 65752 | 65986 | rc = sqlite3WalCheckpoint(pPager->pWal, db, eMode, |
| 65753 | | - (eMode==SQLITE_CHECKPOINT_PASSIVE ? 0 : pPager->xBusyHandler), |
| 65987 | + (eMode<=SQLITE_CHECKPOINT_PASSIVE ? 0 : pPager->xBusyHandler), |
| 65754 | 65988 | pPager->pBusyHandlerArg, |
| 65755 | 65989 | pPager->walSyncFlags, pPager->pageSize, (u8 *)pPager->pTmpSpace, |
| 65756 | 65990 | pnLog, pnCkpt |
| 65757 | 65991 | ); |
| 65758 | 65992 | } |
| | @@ -70353,11 +70587,12 @@ |
| 70353 | 70587 | assert( pWal->ckptLock==0 ); |
| 70354 | 70588 | assert( pWal->writeLock==0 ); |
| 70355 | 70589 | |
| 70356 | 70590 | /* EVIDENCE-OF: R-62920-47450 The busy-handler callback is never invoked |
| 70357 | 70591 | ** in the SQLITE_CHECKPOINT_PASSIVE mode. */ |
| 70358 | | - assert( eMode!=SQLITE_CHECKPOINT_PASSIVE || xBusy==0 ); |
| 70592 | + assert( SQLITE_CHECKPOINT_NOOP<SQLITE_CHECKPOINT_PASSIVE ); |
| 70593 | + assert( eMode>SQLITE_CHECKPOINT_PASSIVE || xBusy==0 ); |
| 70359 | 70594 | |
| 70360 | 70595 | if( pWal->readOnly ) return SQLITE_READONLY; |
| 70361 | 70596 | WALTRACE(("WAL%p: checkpoint begins\n", pWal)); |
| 70362 | 70597 | |
| 70363 | 70598 | /* Enable blocking locks, if possible. */ |
| | @@ -70370,35 +70605,39 @@ |
| 70370 | 70605 | ** checkpoint operation at the same time, the lock cannot be obtained and |
| 70371 | 70606 | ** SQLITE_BUSY is returned. |
| 70372 | 70607 | ** EVIDENCE-OF: R-53820-33897 Even if there is a busy-handler configured, |
| 70373 | 70608 | ** it will not be invoked in this case. |
| 70374 | 70609 | */ |
| 70375 | | - rc = walLockExclusive(pWal, WAL_CKPT_LOCK, 1); |
| 70376 | | - testcase( rc==SQLITE_BUSY ); |
| 70377 | | - testcase( rc!=SQLITE_OK && xBusy2!=0 ); |
| 70378 | | - if( rc==SQLITE_OK ){ |
| 70379 | | - pWal->ckptLock = 1; |
| 70380 | | - |
| 70381 | | - /* IMPLEMENTATION-OF: R-59782-36818 The SQLITE_CHECKPOINT_FULL, RESTART and |
| 70382 | | - ** TRUNCATE modes also obtain the exclusive "writer" lock on the database |
| 70383 | | - ** file. |
| 70384 | | - ** |
| 70385 | | - ** EVIDENCE-OF: R-60642-04082 If the writer lock cannot be obtained |
| 70386 | | - ** immediately, and a busy-handler is configured, it is invoked and the |
| 70387 | | - ** writer lock retried until either the busy-handler returns 0 or the |
| 70388 | | - ** lock is successfully obtained. |
| 70389 | | - */ |
| 70390 | | - if( eMode!=SQLITE_CHECKPOINT_PASSIVE ){ |
| 70391 | | - rc = walBusyLock(pWal, xBusy2, pBusyArg, WAL_WRITE_LOCK, 1); |
| 70392 | | - if( rc==SQLITE_OK ){ |
| 70393 | | - pWal->writeLock = 1; |
| 70394 | | - }else if( rc==SQLITE_BUSY ){ |
| 70395 | | - eMode2 = SQLITE_CHECKPOINT_PASSIVE; |
| 70396 | | - xBusy2 = 0; |
| 70397 | | - rc = SQLITE_OK; |
| 70398 | | - } |
| 70399 | | - } |
| 70610 | + if( eMode!=SQLITE_CHECKPOINT_NOOP ){ |
| 70611 | + rc = walLockExclusive(pWal, WAL_CKPT_LOCK, 1); |
| 70612 | + testcase( rc==SQLITE_BUSY ); |
| 70613 | + testcase( rc!=SQLITE_OK && xBusy2!=0 ); |
| 70614 | + if( rc==SQLITE_OK ){ |
| 70615 | + pWal->ckptLock = 1; |
| 70616 | + |
| 70617 | + /* IMPLEMENTATION-OF: R-59782-36818 The SQLITE_CHECKPOINT_FULL, RESTART |
| 70618 | + ** and TRUNCATE modes also obtain the exclusive "writer" lock on the |
| 70619 | + ** database file. |
| 70620 | + ** |
| 70621 | + ** EVIDENCE-OF: R-60642-04082 If the writer lock cannot be obtained |
| 70622 | + ** immediately, and a busy-handler is configured, it is invoked and the |
| 70623 | + ** writer lock retried until either the busy-handler returns 0 or the |
| 70624 | + ** lock is successfully obtained. |
| 70625 | + */ |
| 70626 | + if( eMode!=SQLITE_CHECKPOINT_PASSIVE ){ |
| 70627 | + rc = walBusyLock(pWal, xBusy2, pBusyArg, WAL_WRITE_LOCK, 1); |
| 70628 | + if( rc==SQLITE_OK ){ |
| 70629 | + pWal->writeLock = 1; |
| 70630 | + }else if( rc==SQLITE_BUSY ){ |
| 70631 | + eMode2 = SQLITE_CHECKPOINT_PASSIVE; |
| 70632 | + xBusy2 = 0; |
| 70633 | + rc = SQLITE_OK; |
| 70634 | + } |
| 70635 | + } |
| 70636 | + } |
| 70637 | + }else{ |
| 70638 | + rc = SQLITE_OK; |
| 70400 | 70639 | } |
| 70401 | 70640 | |
| 70402 | 70641 | |
| 70403 | 70642 | /* Read the wal-index header. */ |
| 70404 | 70643 | SEH_TRY { |
| | @@ -70408,21 +70647,21 @@ |
| 70408 | 70647 | ** or invoke the busy handler. The only lock such a checkpoint may |
| 70409 | 70648 | ** attempt to obtain is a lock on a read-slot, and it should give up |
| 70410 | 70649 | ** immediately and do a partial checkpoint if it cannot obtain it. */ |
| 70411 | 70650 | walDisableBlocking(pWal); |
| 70412 | 70651 | rc = walIndexReadHdr(pWal, &isChanged); |
| 70413 | | - if( eMode2!=SQLITE_CHECKPOINT_PASSIVE ) (void)walEnableBlocking(pWal); |
| 70652 | + if( eMode2>SQLITE_CHECKPOINT_PASSIVE ) (void)walEnableBlocking(pWal); |
| 70414 | 70653 | if( isChanged && pWal->pDbFd->pMethods->iVersion>=3 ){ |
| 70415 | 70654 | sqlite3OsUnfetch(pWal->pDbFd, 0, 0); |
| 70416 | 70655 | } |
| 70417 | 70656 | } |
| 70418 | 70657 | |
| 70419 | 70658 | /* Copy data from the log to the database file. */ |
| 70420 | 70659 | if( rc==SQLITE_OK ){ |
| 70421 | 70660 | if( pWal->hdr.mxFrame && walPagesize(pWal)!=nBuf ){ |
| 70422 | 70661 | rc = SQLITE_CORRUPT_BKPT; |
| 70423 | | - }else{ |
| 70662 | + }else if( eMode2!=SQLITE_CHECKPOINT_NOOP ){ |
| 70424 | 70663 | rc = walCheckpoint(pWal, db, eMode2, xBusy2, pBusyArg, sync_flags,zBuf); |
| 70425 | 70664 | } |
| 70426 | 70665 | |
| 70427 | 70666 | /* If no error occurred, set the output variables. */ |
| 70428 | 70667 | if( rc==SQLITE_OK || rc==SQLITE_BUSY ){ |
| | @@ -91645,11 +91884,11 @@ |
| 91645 | 91884 | |
| 91646 | 91885 | preupdate.v = v; |
| 91647 | 91886 | preupdate.pCsr = pCsr; |
| 91648 | 91887 | preupdate.op = op; |
| 91649 | 91888 | preupdate.iNewReg = iReg; |
| 91650 | | - preupdate.pKeyinfo = (KeyInfo*)&preupdate.keyinfoSpace; |
| 91889 | + preupdate.pKeyinfo = &preupdate.uKey.sKey; |
| 91651 | 91890 | preupdate.pKeyinfo->db = db; |
| 91652 | 91891 | preupdate.pKeyinfo->enc = ENC(db); |
| 91653 | 91892 | preupdate.pKeyinfo->nKeyField = pTab->nCol; |
| 91654 | 91893 | preupdate.pKeyinfo->aSortFlags = 0; /* Indicate .aColl, .nAllField uninit */ |
| 91655 | 91894 | preupdate.iKey1 = iKey1; |
| | @@ -102528,10 +102767,11 @@ |
| 102528 | 102767 | aRes[1] = aRes[2] = -1; |
| 102529 | 102768 | assert( pOp->p2==SQLITE_CHECKPOINT_PASSIVE |
| 102530 | 102769 | || pOp->p2==SQLITE_CHECKPOINT_FULL |
| 102531 | 102770 | || pOp->p2==SQLITE_CHECKPOINT_RESTART |
| 102532 | 102771 | || pOp->p2==SQLITE_CHECKPOINT_TRUNCATE |
| 102772 | + || pOp->p2==SQLITE_CHECKPOINT_NOOP |
| 102533 | 102773 | ); |
| 102534 | 102774 | rc = sqlite3Checkpoint(db, pOp->p1, pOp->p2, &aRes[1], &aRes[2]); |
| 102535 | 102775 | if( rc ){ |
| 102536 | 102776 | if( rc!=SQLITE_BUSY ) goto abort_due_to_error; |
| 102537 | 102777 | rc = SQLITE_OK; |
| | @@ -110651,18 +110891,21 @@ |
| 110651 | 110891 | ExprList *pList /* Expression list to resolve. May be NULL. */ |
| 110652 | 110892 | ){ |
| 110653 | 110893 | SrcList *pSrc; /* Fake SrcList for pParse->pNewTable */ |
| 110654 | 110894 | NameContext sNC; /* Name context for pParse->pNewTable */ |
| 110655 | 110895 | int rc; |
| 110656 | | - u8 srcSpace[SZ_SRCLIST_1]; /* Memory space for the fake SrcList */ |
| 110896 | + union { |
| 110897 | + SrcList sSrc; |
| 110898 | + u8 srcSpace[SZ_SRCLIST_1]; /* Memory space for the fake SrcList */ |
| 110899 | + } uSrc; |
| 110657 | 110900 | |
| 110658 | 110901 | assert( type==0 || pTab!=0 ); |
| 110659 | 110902 | assert( type==NC_IsCheck || type==NC_PartIdx || type==NC_IdxExpr |
| 110660 | 110903 | || type==NC_GenCol || pTab==0 ); |
| 110661 | 110904 | memset(&sNC, 0, sizeof(sNC)); |
| 110662 | | - pSrc = (SrcList*)srcSpace; |
| 110663 | | - memset(pSrc, 0, SZ_SRCLIST_1); |
| 110905 | + memset(&uSrc, 0, sizeof(uSrc)); |
| 110906 | + pSrc = &uSrc.sSrc; |
| 110664 | 110907 | if( pTab ){ |
| 110665 | 110908 | pSrc->nSrc = 1; |
| 110666 | 110909 | pSrc->a[0].zName = pTab->zName; |
| 110667 | 110910 | pSrc->a[0].pSTab = pTab; |
| 110668 | 110911 | pSrc->a[0].iCursor = -1; |
| | @@ -111921,10 +112164,15 @@ |
| 111921 | 112164 | if( IsWindowFunc(pExpr) ){ |
| 111922 | 112165 | sqlite3ExprOrderByAggregateError(pParse, pExpr); |
| 111923 | 112166 | sqlite3ExprListDelete(db, pOrderBy); |
| 111924 | 112167 | return; |
| 111925 | 112168 | } |
| 112169 | + if( pOrderBy->nExpr>db->aLimit[SQLITE_LIMIT_COLUMN] ){ |
| 112170 | + sqlite3ErrorMsg(pParse, "too many terms in ORDER BY clause"); |
| 112171 | + sqlite3ExprListDelete(db, pOrderBy); |
| 112172 | + return; |
| 112173 | + } |
| 111926 | 112174 | |
| 111927 | 112175 | pOB = sqlite3ExprAlloc(db, TK_ORDER, 0, 0); |
| 111928 | 112176 | if( pOB==0 ){ |
| 111929 | 112177 | sqlite3ExprListDelete(db, pOrderBy); |
| 111930 | 112178 | return; |
| | @@ -113117,13 +113365,12 @@ |
| 113117 | 113365 | } |
| 113118 | 113366 | r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, pFree1); |
| 113119 | 113367 | if( addrIsNull==0 ){ |
| 113120 | 113368 | /* |
| 113121 | 113369 | ** If the right operand contains a subquery and the left operand does not |
| 113122 | | - ** and the left operand might be NULL, then check the left operand do |
| 113123 | | - ** an IsNull check on the left operand before computing the right |
| 113124 | | - ** 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. |
| 113125 | 113372 | */ |
| 113126 | 113373 | if( ExprHasProperty(pExpr->pRight, EP_Subquery) |
| 113127 | 113374 | && sqlite3ExprCanBeNull(pExpr->pLeft) |
| 113128 | 113375 | ){ |
| 113129 | 113376 | addrIsNull = sqlite3VdbeAddOp1(v, OP_IsNull, r1); |
| | @@ -114683,11 +114930,10 @@ |
| 114683 | 114930 | int destIfNull /* Jump here if the results are unknown due to NULLs */ |
| 114684 | 114931 | ){ |
| 114685 | 114932 | int rRhsHasNull = 0; /* Register that is true if RHS contains NULL values */ |
| 114686 | 114933 | int eType; /* Type of the RHS */ |
| 114687 | 114934 | int rLhs; /* Register(s) holding the LHS values */ |
| 114688 | | - int rLhsOrig; /* LHS values prior to reordering by aiMap[] */ |
| 114689 | 114935 | Vdbe *v; /* Statement under construction */ |
| 114690 | 114936 | int *aiMap = 0; /* Map from vector field to index column */ |
| 114691 | 114937 | char *zAff = 0; /* Affinity string for comparisons */ |
| 114692 | 114938 | int nVector; /* Size of vectors for this IN operator */ |
| 114693 | 114939 | int iDummy; /* Dummy parameter to exprCodeVector() */ |
| | @@ -114746,23 +114992,12 @@ |
| 114746 | 114992 | ** Avoid factoring the LHS of the IN(...) expression out of the loop, |
| 114747 | 114993 | ** even if it is constant, as OP_Affinity may be used on the register |
| 114748 | 114994 | ** by code generated below. */ |
| 114749 | 114995 | assert( pParse->okConstFactor==okConstFactor ); |
| 114750 | 114996 | pParse->okConstFactor = 0; |
| 114751 | | - rLhsOrig = exprCodeVector(pParse, pLeft, &iDummy); |
| 114997 | + rLhs = exprCodeVector(pParse, pLeft, &iDummy); |
| 114752 | 114998 | pParse->okConstFactor = okConstFactor; |
| 114753 | | - for(i=0; i<nVector && aiMap[i]==i; i++){} /* Are LHS fields reordered? */ |
| 114754 | | - if( i==nVector ){ |
| 114755 | | - /* LHS fields are not reordered */ |
| 114756 | | - rLhs = rLhsOrig; |
| 114757 | | - }else{ |
| 114758 | | - /* Need to reorder the LHS fields according to aiMap */ |
| 114759 | | - rLhs = sqlite3GetTempRange(pParse, nVector); |
| 114760 | | - for(i=0; i<nVector; i++){ |
| 114761 | | - sqlite3VdbeAddOp3(v, OP_Copy, rLhsOrig+i, rLhs+aiMap[i], 0); |
| 114762 | | - } |
| 114763 | | - } |
| 114764 | 114999 | |
| 114765 | 115000 | /* If sqlite3FindInIndex() did not find or create an index that is |
| 114766 | 115001 | ** suitable for evaluating the IN operator, then evaluate using a |
| 114767 | 115002 | ** sequence of comparisons. |
| 114768 | 115003 | ** |
| | @@ -114773,10 +115008,11 @@ |
| 114773 | 115008 | CollSeq *pColl; |
| 114774 | 115009 | int labelOk = sqlite3VdbeMakeLabel(pParse); |
| 114775 | 115010 | int r2, regToFree; |
| 114776 | 115011 | int regCkNull = 0; |
| 114777 | 115012 | int ii; |
| 115013 | + assert( nVector==1 ); |
| 114778 | 115014 | assert( ExprUseXList(pExpr) ); |
| 114779 | 115015 | pList = pExpr->x.pList; |
| 114780 | 115016 | pColl = sqlite3ExprCollSeq(pParse, pExpr->pLeft); |
| 114781 | 115017 | if( destIfNull!=destIfFalse ){ |
| 114782 | 115018 | regCkNull = sqlite3GetTempReg(pParse); |
| | @@ -114813,10 +115049,30 @@ |
| 114813 | 115049 | } |
| 114814 | 115050 | sqlite3VdbeResolveLabel(v, labelOk); |
| 114815 | 115051 | sqlite3ReleaseTempReg(pParse, regCkNull); |
| 114816 | 115052 | goto sqlite3ExprCodeIN_finished; |
| 114817 | 115053 | } |
| 115054 | + |
| 115055 | + if( eType!=IN_INDEX_ROWID ){ |
| 115056 | + /* If this IN operator will use an index, then the order of columns in the |
| 115057 | + ** vector might be different from the order in the index. In that case, |
| 115058 | + ** we need to reorder the LHS values to be in index order. Run Affinity |
| 115059 | + ** before reordering the columns, so that the affinity is correct. |
| 115060 | + */ |
| 115061 | + sqlite3VdbeAddOp4(v, OP_Affinity, rLhs, nVector, 0, zAff, nVector); |
| 115062 | + for(i=0; i<nVector && aiMap[i]==i; i++){} /* Are LHS fields reordered? */ |
| 115063 | + if( i!=nVector ){ |
| 115064 | + /* Need to reorder the LHS fields according to aiMap */ |
| 115065 | + int rLhsOrig = rLhs; |
| 115066 | + rLhs = sqlite3GetTempRange(pParse, nVector); |
| 115067 | + for(i=0; i<nVector; i++){ |
| 115068 | + sqlite3VdbeAddOp3(v, OP_Copy, rLhsOrig+i, rLhs+aiMap[i], 0); |
| 115069 | + } |
| 115070 | + sqlite3ReleaseTempReg(pParse, rLhsOrig); |
| 115071 | + } |
| 115072 | + } |
| 115073 | + |
| 114818 | 115074 | |
| 114819 | 115075 | /* Step 2: Check to see if the LHS contains any NULL columns. If the |
| 114820 | 115076 | ** LHS does contain NULLs then the result must be either FALSE or NULL. |
| 114821 | 115077 | ** We will then skip the binary search of the RHS. |
| 114822 | 115078 | */ |
| | @@ -114840,15 +115096,15 @@ |
| 114840 | 115096 | */ |
| 114841 | 115097 | if( eType==IN_INDEX_ROWID ){ |
| 114842 | 115098 | /* In this case, the RHS is the ROWID of table b-tree and so we also |
| 114843 | 115099 | ** know that the RHS is non-NULL. Hence, we combine steps 3 and 4 |
| 114844 | 115100 | ** into a single opcode. */ |
| 115101 | + assert( nVector==1 ); |
| 114845 | 115102 | sqlite3VdbeAddOp3(v, OP_SeekRowid, iTab, destIfFalse, rLhs); |
| 114846 | 115103 | VdbeCoverage(v); |
| 114847 | 115104 | addrTruthOp = sqlite3VdbeAddOp0(v, OP_Goto); /* Return True */ |
| 114848 | 115105 | }else{ |
| 114849 | | - sqlite3VdbeAddOp4(v, OP_Affinity, rLhs, nVector, 0, zAff, nVector); |
| 114850 | 115106 | if( destIfFalse==destIfNull ){ |
| 114851 | 115107 | /* Combine Step 3 and Step 5 into a single opcode */ |
| 114852 | 115108 | if( ExprHasProperty(pExpr, EP_Subrtn) ){ |
| 114853 | 115109 | const VdbeOp *pOp = sqlite3VdbeGetOp(v, pExpr->y.sub.iAddr); |
| 114854 | 115110 | assert( pOp->opcode==OP_Once || pParse->nErr ); |
| | @@ -114922,11 +115178,10 @@ |
| 114922 | 115178 | |
| 114923 | 115179 | /* Jumps here in order to return true. */ |
| 114924 | 115180 | sqlite3VdbeJumpHere(v, addrTruthOp); |
| 114925 | 115181 | |
| 114926 | 115182 | sqlite3ExprCodeIN_finished: |
| 114927 | | - if( rLhs!=rLhsOrig ) sqlite3ReleaseTempReg(pParse, rLhs); |
| 114928 | 115183 | VdbeComment((v, "end IN expr")); |
| 114929 | 115184 | sqlite3ExprCodeIN_oom_error: |
| 114930 | 115185 | sqlite3DbFree(pParse->db, aiMap); |
| 114931 | 115186 | sqlite3DbFree(pParse->db, zAff); |
| 114932 | 115187 | } |
| | @@ -115480,10 +115735,82 @@ |
| 115480 | 115735 | } |
| 115481 | 115736 | } |
| 115482 | 115737 | return 0; |
| 115483 | 115738 | } |
| 115484 | 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 | + |
| 115485 | 115812 | |
| 115486 | 115813 | /* |
| 115487 | 115814 | ** Generate code into the current Vdbe to evaluate the given |
| 115488 | 115815 | ** expression. Attempt to store the results in register "target". |
| 115489 | 115816 | ** Return the register where results are stored. |
| | @@ -115768,16 +116095,18 @@ |
| 115768 | 116095 | sqlite3VdbeAddOp2(v, OP_Null, 0, inReg); |
| 115769 | 116096 | } |
| 115770 | 116097 | } |
| 115771 | 116098 | testcase( regFree1==0 ); |
| 115772 | 116099 | testcase( regFree2==0 ); |
| 115773 | | - |
| 115774 | 116100 | } |
| 115775 | 116101 | break; |
| 115776 | 116102 | } |
| 115777 | 116103 | case TK_AND: |
| 115778 | | - case TK_OR: |
| 116104 | + case TK_OR: { |
| 116105 | + inReg = exprCodeTargetAndOr(pParse, pExpr, target, ®Free1); |
| 116106 | + break; |
| 116107 | + } |
| 115779 | 116108 | case TK_PLUS: |
| 115780 | 116109 | case TK_STAR: |
| 115781 | 116110 | case TK_MINUS: |
| 115782 | 116111 | case TK_REM: |
| 115783 | 116112 | case TK_BITAND: |
| | @@ -115785,12 +116114,10 @@ |
| 115785 | 116114 | case TK_SLASH: |
| 115786 | 116115 | case TK_LSHIFT: |
| 115787 | 116116 | case TK_RSHIFT: |
| 115788 | 116117 | case TK_CONCAT: { |
| 115789 | 116118 | int addrIsNull; |
| 115790 | | - assert( TK_AND==OP_And ); testcase( op==TK_AND ); |
| 115791 | | - assert( TK_OR==OP_Or ); testcase( op==TK_OR ); |
| 115792 | 116119 | assert( TK_PLUS==OP_Add ); testcase( op==TK_PLUS ); |
| 115793 | 116120 | assert( TK_MINUS==OP_Subtract ); testcase( op==TK_MINUS ); |
| 115794 | 116121 | assert( TK_REM==OP_Remainder ); testcase( op==TK_REM ); |
| 115795 | 116122 | assert( TK_BITAND==OP_BitAnd ); testcase( op==TK_BITAND ); |
| 115796 | 116123 | assert( TK_BITOR==OP_BitOr ); testcase( op==TK_BITOR ); |
| | @@ -124573,11 +124900,11 @@ |
| 124573 | 124900 | */ |
| 124574 | 124901 | SQLITE_PRIVATE int sqlite3TableColumnToIndex(Index *pIdx, int iCol){ |
| 124575 | 124902 | int i; |
| 124576 | 124903 | i16 iCol16; |
| 124577 | 124904 | assert( iCol>=(-1) && iCol<=SQLITE_MAX_COLUMN ); |
| 124578 | | - assert( pIdx->nColumn<=SQLITE_MAX_COLUMN+1 ); |
| 124905 | + assert( pIdx->nColumn<=SQLITE_MAX_COLUMN*2 ); |
| 124579 | 124906 | iCol16 = iCol; |
| 124580 | 124907 | for(i=0; i<pIdx->nColumn; i++){ |
| 124581 | 124908 | if( iCol16==pIdx->aiColumn[i] ){ |
| 124582 | 124909 | return i; |
| 124583 | 124910 | } |
| | @@ -124870,10 +125197,13 @@ |
| 124870 | 125197 | sqlite3VdbeAddOp2(v, OP_NewRowid, 0, reg1); |
| 124871 | 125198 | sqlite3VdbeAddOp4(v, OP_Blob, 6, reg3, 0, nullRow, P4_STATIC); |
| 124872 | 125199 | sqlite3VdbeAddOp3(v, OP_Insert, 0, reg3, reg1); |
| 124873 | 125200 | sqlite3VdbeChangeP5(v, OPFLAG_APPEND); |
| 124874 | 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; |
| 124875 | 125205 | } |
| 124876 | 125206 | |
| 124877 | 125207 | /* Normal (non-error) return. */ |
| 124878 | 125208 | return; |
| 124879 | 125209 | |
| | @@ -129165,18 +129495,23 @@ |
| 129165 | 129495 | pKey->aSortFlags[i] = pIdx->aSortOrder[i]; |
| 129166 | 129496 | assert( 0==(pKey->aSortFlags[i] & KEYINFO_ORDER_BIGNULL) ); |
| 129167 | 129497 | } |
| 129168 | 129498 | if( pParse->nErr ){ |
| 129169 | 129499 | assert( pParse->rc==SQLITE_ERROR_MISSING_COLLSEQ ); |
| 129170 | | - if( pIdx->bNoQuery==0 ){ |
| 129500 | + if( pIdx->bNoQuery==0 |
| 129501 | + && sqlite3HashFind(&pIdx->pSchema->idxHash, pIdx->zName) |
| 129502 | + ){ |
| 129171 | 129503 | /* Deactivate the index because it contains an unknown collating |
| 129172 | 129504 | ** sequence. The only way to reactive the index is to reload the |
| 129173 | 129505 | ** schema. Adding the missing collating sequence later does not |
| 129174 | 129506 | ** reactive the index. The application had the chance to register |
| 129175 | 129507 | ** the missing index using the collation-needed callback. For |
| 129176 | 129508 | ** simplicity, SQLite will not give the application a second chance. |
| 129177 | | - */ |
| 129509 | + ** |
| 129510 | + ** Except, do not do this if the index is not in the schema hash |
| 129511 | + ** table. In this case the index is currently being constructed |
| 129512 | + ** by a CREATE INDEX statement, and retrying will not help. */ |
| 129178 | 129513 | pIdx->bNoQuery = 1; |
| 129179 | 129514 | pParse->rc = SQLITE_ERROR_RETRY; |
| 129180 | 129515 | } |
| 129181 | 129516 | sqlite3KeyInfoUnref(pKey); |
| 129182 | 129517 | pKey = 0; |
| | @@ -139247,10 +139582,12 @@ |
| 139247 | 139582 | /* Version 3.44.0 and later */ |
| 139248 | 139583 | void *(*get_clientdata)(sqlite3*,const char*); |
| 139249 | 139584 | int (*set_clientdata)(sqlite3*, const char*, void*, void(*)(void*)); |
| 139250 | 139585 | /* Version 3.50.0 and later */ |
| 139251 | 139586 | int (*setlk_timeout)(sqlite3*,int,int); |
| 139587 | + /* Version 3.51.0 and later */ |
| 139588 | + int (*set_errmsg)(sqlite3*,int,const char*); |
| 139252 | 139589 | }; |
| 139253 | 139590 | |
| 139254 | 139591 | /* |
| 139255 | 139592 | ** This is the function signature used for all extension entry points. It |
| 139256 | 139593 | ** is also defined in the file "loadext.c". |
| | @@ -139582,10 +139919,12 @@ |
| 139582 | 139919 | /* Version 3.44.0 and later */ |
| 139583 | 139920 | #define sqlite3_get_clientdata sqlite3_api->get_clientdata |
| 139584 | 139921 | #define sqlite3_set_clientdata sqlite3_api->set_clientdata |
| 139585 | 139922 | /* Version 3.50.0 and later */ |
| 139586 | 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 |
| 139587 | 139926 | #endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */ |
| 139588 | 139927 | |
| 139589 | 139928 | #if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) |
| 139590 | 139929 | /* This case when the file really is being compiled as a loadable |
| 139591 | 139930 | ** extension */ |
| | @@ -140105,11 +140444,13 @@ |
| 140105 | 140444 | sqlite3_stmt_explain, |
| 140106 | 140445 | /* Version 3.44.0 and later */ |
| 140107 | 140446 | sqlite3_get_clientdata, |
| 140108 | 140447 | sqlite3_set_clientdata, |
| 140109 | 140448 | /* Version 3.50.0 and later */ |
| 140110 | | - sqlite3_setlk_timeout |
| 140449 | + sqlite3_setlk_timeout, |
| 140450 | + /* Version 3.51.0 and later */ |
| 140451 | + sqlite3_set_errmsg |
| 140111 | 140452 | }; |
| 140112 | 140453 | |
| 140113 | 140454 | /* True if x is the directory separator character |
| 140114 | 140455 | */ |
| 140115 | 140456 | #if SQLITE_OS_WIN |
| | @@ -141566,10 +141907,26 @@ |
| 141566 | 141907 | addr = sqlite3VdbeAddOp3(v, OP_IfPos, 1, sqlite3VdbeCurrentAddr(v)+2, 1); |
| 141567 | 141908 | VdbeCoverage(v); |
| 141568 | 141909 | sqlite3VdbeAddOp0(v, OP_Halt); |
| 141569 | 141910 | return addr; |
| 141570 | 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 | +} |
| 141571 | 141928 | |
| 141572 | 141929 | /* |
| 141573 | 141930 | ** Process a pragma statement. |
| 141574 | 141931 | ** |
| 141575 | 141932 | ** Pragmas are of this form: |
| | @@ -142912,11 +143269,11 @@ |
| 142912 | 143269 | pTbls = &db->aDb[i].pSchema->tblHash; |
| 142913 | 143270 | for(cnt=0, x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){ |
| 142914 | 143271 | Table *pTab = sqliteHashData(x); /* Current table */ |
| 142915 | 143272 | Index *pIdx; /* An index on pTab */ |
| 142916 | 143273 | int nIdx; /* Number of indexes on pTab */ |
| 142917 | | - if( pObjTab && pObjTab!=pTab ) continue; |
| 143274 | + if( tableSkipIntegrityCheck(pTab,pObjTab) ) continue; |
| 142918 | 143275 | if( HasRowid(pTab) ) cnt++; |
| 142919 | 143276 | for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdx++){ cnt++; } |
| 142920 | 143277 | } |
| 142921 | 143278 | if( cnt==0 ) continue; |
| 142922 | 143279 | if( pObjTab ) cnt++; |
| | @@ -142925,11 +143282,11 @@ |
| 142925 | 143282 | cnt = 0; |
| 142926 | 143283 | if( pObjTab ) aRoot[++cnt] = 0; |
| 142927 | 143284 | for(x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){ |
| 142928 | 143285 | Table *pTab = sqliteHashData(x); |
| 142929 | 143286 | Index *pIdx; |
| 142930 | | - if( pObjTab && pObjTab!=pTab ) continue; |
| 143287 | + if( tableSkipIntegrityCheck(pTab,pObjTab) ) continue; |
| 142931 | 143288 | if( HasRowid(pTab) ) aRoot[++cnt] = pTab->tnum; |
| 142932 | 143289 | for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ |
| 142933 | 143290 | aRoot[++cnt] = pIdx->tnum; |
| 142934 | 143291 | } |
| 142935 | 143292 | } |
| | @@ -142956,11 +143313,11 @@ |
| 142956 | 143313 | sqlite3VdbeLoadString(v, 2, "wrong # of entries in index "); |
| 142957 | 143314 | for(x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){ |
| 142958 | 143315 | int iTab = 0; |
| 142959 | 143316 | Table *pTab = sqliteHashData(x); |
| 142960 | 143317 | Index *pIdx; |
| 142961 | | - if( pObjTab && pObjTab!=pTab ) continue; |
| 143318 | + if( tableSkipIntegrityCheck(pTab,pObjTab) ) continue; |
| 142962 | 143319 | if( HasRowid(pTab) ){ |
| 142963 | 143320 | iTab = cnt++; |
| 142964 | 143321 | }else{ |
| 142965 | 143322 | iTab = cnt; |
| 142966 | 143323 | for(pIdx=pTab->pIndex; ALWAYS(pIdx); pIdx=pIdx->pNext){ |
| | @@ -142992,11 +143349,11 @@ |
| 142992 | 143349 | int r1 = -1; |
| 142993 | 143350 | int bStrict; /* True for a STRICT table */ |
| 142994 | 143351 | int r2; /* Previous key for WITHOUT ROWID tables */ |
| 142995 | 143352 | int mxCol; /* Maximum non-virtual column number */ |
| 142996 | 143353 | |
| 142997 | | - if( pObjTab && pObjTab!=pTab ) continue; |
| 143354 | + if( tableSkipIntegrityCheck(pTab,pObjTab) ) continue; |
| 142998 | 143355 | if( !IsOrdinaryTable(pTab) ) continue; |
| 142999 | 143356 | if( isQuick || HasRowid(pTab) ){ |
| 143000 | 143357 | pPk = 0; |
| 143001 | 143358 | r2 = 0; |
| 143002 | 143359 | }else{ |
| | @@ -143316,11 +143673,11 @@ |
| 143316 | 143673 | */ |
| 143317 | 143674 | for(x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){ |
| 143318 | 143675 | Table *pTab = sqliteHashData(x); |
| 143319 | 143676 | sqlite3_vtab *pVTab; |
| 143320 | 143677 | int a1; |
| 143321 | | - if( pObjTab && pObjTab!=pTab ) continue; |
| 143678 | + if( tableSkipIntegrityCheck(pTab,pObjTab) ) continue; |
| 143322 | 143679 | if( IsOrdinaryTable(pTab) ) continue; |
| 143323 | 143680 | if( !IsVirtual(pTab) ) continue; |
| 143324 | 143681 | if( pTab->nCol<=0 ){ |
| 143325 | 143682 | const char *zMod = pTab->u.vtab.azArg[0]; |
| 143326 | 143683 | if( sqlite3HashFind(&db->aModule, zMod)==0 ) continue; |
| | @@ -143548,10 +143905,12 @@ |
| 143548 | 143905 | eMode = SQLITE_CHECKPOINT_FULL; |
| 143549 | 143906 | }else if( sqlite3StrICmp(zRight, "restart")==0 ){ |
| 143550 | 143907 | eMode = SQLITE_CHECKPOINT_RESTART; |
| 143551 | 143908 | }else if( sqlite3StrICmp(zRight, "truncate")==0 ){ |
| 143552 | 143909 | eMode = SQLITE_CHECKPOINT_TRUNCATE; |
| 143910 | + }else if( sqlite3StrICmp(zRight, "noop")==0 ){ |
| 143911 | + eMode = SQLITE_CHECKPOINT_NOOP; |
| 143553 | 143912 | } |
| 143554 | 143913 | } |
| 143555 | 143914 | pParse->nMem = 3; |
| 143556 | 143915 | sqlite3VdbeAddOp3(v, OP_Checkpoint, iBt, eMode, 1); |
| 143557 | 143916 | sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 3); |
| | @@ -145114,13 +145473,15 @@ |
| 145114 | 145473 | ** or encounters a permanent error. A schema problem after one schema |
| 145115 | 145474 | ** reset is considered a permanent error. */ |
| 145116 | 145475 | rc = sqlite3Prepare(db, zSql, nBytes, prepFlags, pOld, ppStmt, pzTail); |
| 145117 | 145476 | assert( rc==SQLITE_OK || *ppStmt==0 ); |
| 145118 | 145477 | if( rc==SQLITE_OK || db->mallocFailed ) break; |
| 145119 | | - }while( (rc==SQLITE_ERROR_RETRY && (cnt++)<SQLITE_MAX_PREPARE_RETRY) |
| 145120 | | - || (rc==SQLITE_SCHEMA && (sqlite3ResetOneSchema(db,-1), cnt++)==0) ); |
| 145478 | + cnt++; |
| 145479 | + }while( (rc==SQLITE_ERROR_RETRY && ALWAYS(cnt<=SQLITE_MAX_PREPARE_RETRY)) |
| 145480 | + || (rc==SQLITE_SCHEMA && (sqlite3ResetOneSchema(db,-1), cnt)==1) ); |
| 145121 | 145481 | sqlite3BtreeLeaveAll(db); |
| 145482 | + assert( rc!=SQLITE_ERROR_RETRY ); |
| 145122 | 145483 | rc = sqlite3ApiExit(db, rc); |
| 145123 | 145484 | assert( (rc&db->errMask)==rc ); |
| 145124 | 145485 | db->busyHandler.nBusy = 0; |
| 145125 | 145486 | sqlite3_mutex_leave(db->mutex); |
| 145126 | 145487 | assert( rc==SQLITE_OK || (*ppStmt)==0 ); |
| | @@ -145790,12 +146151,11 @@ |
| 145790 | 146151 | while( p ){ |
| 145791 | 146152 | ExprSetProperty(p, joinFlag); |
| 145792 | 146153 | assert( !ExprHasProperty(p, EP_TokenOnly|EP_Reduced) ); |
| 145793 | 146154 | ExprSetVVAProperty(p, EP_NoReduce); |
| 145794 | 146155 | p->w.iJoin = iTable; |
| 145795 | | - if( p->op==TK_FUNCTION ){ |
| 145796 | | - assert( ExprUseXList(p) ); |
| 146156 | + if( ExprUseXList(p) ){ |
| 145797 | 146157 | if( p->x.pList ){ |
| 145798 | 146158 | int i; |
| 145799 | 146159 | for(i=0; i<p->x.pList->nExpr; i++){ |
| 145800 | 146160 | sqlite3SetJoinExpr(p->x.pList->a[i].pExpr, iTable, joinFlag); |
| 145801 | 146161 | } |
| | @@ -146007,10 +146367,11 @@ |
| 146007 | 146367 | else if( pRight->u3.pOn ){ |
| 146008 | 146368 | sqlite3SetJoinExpr(pRight->u3.pOn, pRight->iCursor, joinType); |
| 146009 | 146369 | p->pWhere = sqlite3ExprAnd(pParse, p->pWhere, pRight->u3.pOn); |
| 146010 | 146370 | pRight->u3.pOn = 0; |
| 146011 | 146371 | pRight->fg.isOn = 1; |
| 146372 | + p->selFlags |= SF_OnToWhere; |
| 146012 | 146373 | } |
| 146013 | 146374 | } |
| 146014 | 146375 | return 0; |
| 146015 | 146376 | } |
| 146016 | 146377 | |
| | @@ -146893,11 +147254,14 @@ |
| 146893 | 147254 | ** Allocate a KeyInfo object sufficient for an index of N key columns and |
| 146894 | 147255 | ** X extra columns. |
| 146895 | 147256 | */ |
| 146896 | 147257 | SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoAlloc(sqlite3 *db, int N, int X){ |
| 146897 | 147258 | int nExtra = (N+X)*(sizeof(CollSeq*)+1); |
| 146898 | | - KeyInfo *p = sqlite3DbMallocRawNN(db, SZ_KEYINFO(0) + nExtra); |
| 147259 | + KeyInfo *p; |
| 147260 | + assert( X>=0 ); |
| 147261 | + if( NEVER(N+X>0xffff) ) return (KeyInfo*)sqlite3OomFault(db); |
| 147262 | + p = sqlite3DbMallocRawNN(db, SZ_KEYINFO(0) + nExtra); |
| 146899 | 147263 | if( p ){ |
| 146900 | 147264 | p->aSortFlags = (u8*)&p->aColl[N+X]; |
| 146901 | 147265 | p->nKeyField = (u16)N; |
| 146902 | 147266 | p->nAllField = (u16)(N+X); |
| 146903 | 147267 | p->enc = ENC(db); |
| | @@ -149212,11 +149576,11 @@ |
| 149212 | 149576 | ** expressions in pEList. |
| 149213 | 149577 | ** |
| 149214 | 149578 | ** ## About "isOuterJoin": |
| 149215 | 149579 | ** |
| 149216 | 149580 | ** The isOuterJoin column indicates that the replacement will occur into a |
| 149217 | | -** position in the parent that NULL-able due to an OUTER JOIN. Either the |
| 149581 | +** position in the parent that is NULL-able due to an OUTER JOIN. Either the |
| 149218 | 149582 | ** target slot in the parent is the right operand of a LEFT JOIN, or one of |
| 149219 | 149583 | ** the left operands of a RIGHT JOIN. In either case, we need to potentially |
| 149220 | 149584 | ** bypass the substituted expression with OP_IfNullRow. |
| 149221 | 149585 | ** |
| 149222 | 149586 | ** Suppose the original expression is an integer constant. Even though the table |
| | @@ -150050,21 +150414,16 @@ |
| 150050 | 150414 | ** elements we are now copying in. |
| 150051 | 150415 | */ |
| 150052 | 150416 | pSub = pSub1; |
| 150053 | 150417 | for(pParent=p; pParent; pParent=pParent->pPrior, pSub=pSub->pPrior){ |
| 150054 | 150418 | int nSubSrc; |
| 150055 | | - u8 jointype = 0; |
| 150056 | | - u8 ltorj = pSrc->a[iFrom].fg.jointype & JT_LTORJ; |
| 150419 | + u8 jointype = pSubitem->fg.jointype; |
| 150057 | 150420 | assert( pSub!=0 ); |
| 150058 | 150421 | pSubSrc = pSub->pSrc; /* FROM clause of subquery */ |
| 150059 | 150422 | nSubSrc = pSubSrc->nSrc; /* Number of terms in subquery FROM clause */ |
| 150060 | 150423 | pSrc = pParent->pSrc; /* FROM clause of the outer query */ |
| 150061 | 150424 | |
| 150062 | | - if( pParent==p ){ |
| 150063 | | - jointype = pSubitem->fg.jointype; /* First time through the loop */ |
| 150064 | | - } |
| 150065 | | - |
| 150066 | 150425 | /* The subquery uses a single slot of the FROM clause of the outer |
| 150067 | 150426 | ** query. If the subquery has more than one element in its FROM clause, |
| 150068 | 150427 | ** then expand the outer query to make space for it to hold all elements |
| 150069 | 150428 | ** of the subquery. |
| 150070 | 150429 | ** |
| | @@ -150080,10 +150439,11 @@ |
| 150080 | 150439 | */ |
| 150081 | 150440 | if( nSubSrc>1 ){ |
| 150082 | 150441 | pSrc = sqlite3SrcListEnlarge(pParse, pSrc, nSubSrc-1,iFrom+1); |
| 150083 | 150442 | if( pSrc==0 ) break; |
| 150084 | 150443 | pParent->pSrc = pSrc; |
| 150444 | + pSubitem = &pSrc->a[iFrom]; |
| 150085 | 150445 | } |
| 150086 | 150446 | |
| 150087 | 150447 | /* Transfer the FROM clause terms from the subquery into the |
| 150088 | 150448 | ** outer query. |
| 150089 | 150449 | */ |
| | @@ -150094,15 +150454,14 @@ |
| 150094 | 150454 | assert( pItem->fg.isSubquery |
| 150095 | 150455 | || pItem->fg.fixedSchema |
| 150096 | 150456 | || pItem->u4.zDatabase==0 ); |
| 150097 | 150457 | if( pItem->fg.isUsing ) sqlite3IdListDelete(db, pItem->u3.pUsing); |
| 150098 | 150458 | *pItem = pSubSrc->a[i]; |
| 150099 | | - pItem->fg.jointype |= ltorj; |
| 150459 | + pItem->fg.jointype |= (jointype & JT_LTORJ); |
| 150100 | 150460 | memset(&pSubSrc->a[i], 0, sizeof(pSubSrc->a[i])); |
| 150101 | 150461 | } |
| 150102 | | - pSrc->a[iFrom].fg.jointype &= JT_LTORJ; |
| 150103 | | - pSrc->a[iFrom].fg.jointype |= jointype | ltorj; |
| 150462 | + pSubitem->fg.jointype |= jointype; |
| 150104 | 150463 | |
| 150105 | 150464 | /* Now begin substituting subquery result set expressions for |
| 150106 | 150465 | ** references to the iParent in the outer query. |
| 150107 | 150466 | ** |
| 150108 | 150467 | ** Example: |
| | @@ -152838,10 +153197,119 @@ |
| 152838 | 153197 | existsToJoin(pParse, p, pSubWhere); |
| 152839 | 153198 | } |
| 152840 | 153199 | } |
| 152841 | 153200 | } |
| 152842 | 153201 | } |
| 153202 | + |
| 153203 | +/* |
| 153204 | +** Type used for Walker callbacks by selectCheckOnClauses(). |
| 153205 | +*/ |
| 153206 | +typedef struct CheckOnCtx CheckOnCtx; |
| 153207 | +struct CheckOnCtx { |
| 153208 | + SrcList *pSrc; /* SrcList for this context */ |
| 153209 | + int iJoin; /* Cursor numbers must be =< than this */ |
| 153210 | + CheckOnCtx *pParent; /* Parent context */ |
| 153211 | +}; |
| 153212 | + |
| 153213 | +/* |
| 153214 | +** True if the SrcList passed as the only argument contains at least |
| 153215 | +** one RIGHT or FULL JOIN. False otherwise. |
| 153216 | +*/ |
| 153217 | +#define hasRightJoin(pSrc) (((pSrc)->a[0].fg.jointype & JT_LTORJ)!=0) |
| 153218 | + |
| 153219 | +/* |
| 153220 | +** The xExpr callback for the search of invalid ON clause terms. |
| 153221 | +*/ |
| 153222 | +static int selectCheckOnClausesExpr(Walker *pWalker, Expr *pExpr){ |
| 153223 | + CheckOnCtx *pCtx = pWalker->u.pCheckOnCtx; |
| 153224 | + |
| 153225 | + /* Check if pExpr is root or near-root of an ON clause constraint that needs |
| 153226 | + ** to be checked to ensure that it does not refer to tables in its FROM |
| 153227 | + ** clause to the right of itself. i.e. it is either: |
| 153228 | + ** |
| 153229 | + ** + an ON clause on an OUTER join, or |
| 153230 | + ** + an ON clause on an INNER join within a FROM that features at |
| 153231 | + ** least one RIGHT or FULL join. |
| 153232 | + */ |
| 153233 | + if( (ExprHasProperty(pExpr, EP_OuterON)) |
| 153234 | + || (ExprHasProperty(pExpr, EP_InnerON) && hasRightJoin(pCtx->pSrc)) |
| 153235 | + ){ |
| 153236 | + /* If CheckOnCtx.iJoin is already set, then fall through and process |
| 153237 | + ** this expression node as normal. Or, if CheckOnCtx.iJoin is still 0, |
| 153238 | + ** set it to the cursor number of the RHS of the join to which this |
| 153239 | + ** ON expression was attached and then iterate through the entire |
| 153240 | + ** expression. */ |
| 153241 | + assert( pCtx->iJoin==0 || pCtx->iJoin==pExpr->w.iJoin ); |
| 153242 | + if( pCtx->iJoin==0 ){ |
| 153243 | + pCtx->iJoin = pExpr->w.iJoin; |
| 153244 | + sqlite3WalkExprNN(pWalker, pExpr); |
| 153245 | + pCtx->iJoin = 0; |
| 153246 | + return WRC_Prune; |
| 153247 | + } |
| 153248 | + } |
| 153249 | + |
| 153250 | + if( pExpr->op==TK_COLUMN ){ |
| 153251 | + /* A column expression. Find the SrcList (if any) to which it refers. |
| 153252 | + ** Then, if CheckOnCtx.iJoin indicates that this expression is part of an |
| 153253 | + ** ON clause from that SrcList (i.e. if iJoin is non-zero), check that it |
| 153254 | + ** does not refer to a table to the right of CheckOnCtx.iJoin. */ |
| 153255 | + do { |
| 153256 | + SrcList *pSrc = pCtx->pSrc; |
| 153257 | + int iTab = pExpr->iTable; |
| 153258 | + if( iTab>=pSrc->a[0].iCursor && iTab<=pSrc->a[pSrc->nSrc-1].iCursor ){ |
| 153259 | + if( pCtx->iJoin && iTab>pCtx->iJoin ){ |
| 153260 | + sqlite3ErrorMsg(pWalker->pParse, |
| 153261 | + "ON clause references tables to its right"); |
| 153262 | + return WRC_Abort; |
| 153263 | + } |
| 153264 | + break; |
| 153265 | + } |
| 153266 | + pCtx = pCtx->pParent; |
| 153267 | + }while( pCtx ); |
| 153268 | + } |
| 153269 | + return WRC_Continue; |
| 153270 | +} |
| 153271 | + |
| 153272 | +/* |
| 153273 | +** The xSelect callback for the search of invalid ON clause terms. |
| 153274 | +*/ |
| 153275 | +static int selectCheckOnClausesSelect(Walker *pWalker, Select *pSelect){ |
| 153276 | + CheckOnCtx *pCtx = pWalker->u.pCheckOnCtx; |
| 153277 | + if( pSelect->pSrc==pCtx->pSrc || pSelect->pSrc->nSrc==0 ){ |
| 153278 | + return WRC_Continue; |
| 153279 | + }else{ |
| 153280 | + CheckOnCtx sCtx; |
| 153281 | + memset(&sCtx, 0, sizeof(sCtx)); |
| 153282 | + sCtx.pSrc = pSelect->pSrc; |
| 153283 | + sCtx.pParent = pCtx; |
| 153284 | + pWalker->u.pCheckOnCtx = &sCtx; |
| 153285 | + sqlite3WalkSelect(pWalker, pSelect); |
| 153286 | + pWalker->u.pCheckOnCtx = pCtx; |
| 153287 | + pSelect->selFlags &= ~SF_OnToWhere; |
| 153288 | + return WRC_Prune; |
| 153289 | + } |
| 153290 | +} |
| 153291 | + |
| 153292 | +/* |
| 153293 | +** Check all ON clauses in pSelect to verify that they do not reference |
| 153294 | +** columns to the right. |
| 153295 | +*/ |
| 153296 | +static void selectCheckOnClauses(Parse *pParse, Select *pSelect){ |
| 153297 | + Walker w; |
| 153298 | + CheckOnCtx sCtx; |
| 153299 | + assert( pSelect->selFlags & SF_OnToWhere ); |
| 153300 | + assert( pSelect->pSrc!=0 && pSelect->pSrc->nSrc>=2 ); |
| 153301 | + memset(&w, 0, sizeof(w)); |
| 153302 | + w.pParse = pParse; |
| 153303 | + w.xExprCallback = selectCheckOnClausesExpr; |
| 153304 | + w.xSelectCallback = selectCheckOnClausesSelect; |
| 153305 | + w.u.pCheckOnCtx = &sCtx; |
| 153306 | + memset(&sCtx, 0, sizeof(sCtx)); |
| 153307 | + sCtx.pSrc = pSelect->pSrc; |
| 153308 | + sqlite3WalkExprNN(&w, pSelect->pWhere); |
| 153309 | + pSelect->selFlags &= ~SF_OnToWhere; |
| 153310 | +} |
| 152843 | 153311 | |
| 152844 | 153312 | /* |
| 152845 | 153313 | ** Generate byte-code for the SELECT statement given in the p argument. |
| 152846 | 153314 | ** |
| 152847 | 153315 | ** The results are returned according to the SelectDest structure. |
| | @@ -152965,10 +153433,22 @@ |
| 152965 | 153433 | if( sqlite3TreeTrace & 0x10 ){ |
| 152966 | 153434 | TREETRACE(0x10,pParse,p, ("after name resolution:\n")); |
| 152967 | 153435 | sqlite3TreeViewSelect(0, p, 0); |
| 152968 | 153436 | } |
| 152969 | 153437 | #endif |
| 153438 | + |
| 153439 | + /* If the SELECT statement contains ON clauses that were moved into |
| 153440 | + ** the WHERE clause, go through and verify that none of the terms |
| 153441 | + ** in the ON clauses reference tables to the right of the ON clause. |
| 153442 | + ** Do this now, after name resolution, but before query flattening |
| 153443 | + */ |
| 153444 | + if( p->selFlags & SF_OnToWhere ){ |
| 153445 | + selectCheckOnClauses(pParse, p); |
| 153446 | + if( pParse->nErr ){ |
| 153447 | + goto select_end; |
| 153448 | + } |
| 153449 | + } |
| 152970 | 153450 | |
| 152971 | 153451 | /* If the SF_UFSrcCheck flag is set, then this function is being called |
| 152972 | 153452 | ** as part of populating the temp table for an UPDATE...FROM statement. |
| 152973 | 153453 | ** In this case, it is an error if the target object (pSrc->a[0]) name |
| 152974 | 153454 | ** or alias is duplicated within FROM clause (pSrc->a[1..n]). |
| | @@ -155531,11 +156011,14 @@ |
| 155531 | 156011 | sqlite3 *db = pParse->db; |
| 155532 | 156012 | ExprList *pNew; |
| 155533 | 156013 | Returning *pReturning; |
| 155534 | 156014 | Select sSelect; |
| 155535 | 156015 | SrcList *pFrom; |
| 155536 | | - u8 fromSpace[SZ_SRCLIST_1]; |
| 156016 | + union { |
| 156017 | + SrcList sSrc; |
| 156018 | + u8 fromSpace[SZ_SRCLIST_1]; |
| 156019 | + } uSrc; |
| 155537 | 156020 | |
| 155538 | 156021 | assert( v!=0 ); |
| 155539 | 156022 | if( !pParse->bReturning ){ |
| 155540 | 156023 | /* This RETURNING trigger must be for a different statement as |
| 155541 | 156024 | ** this statement lacks a RETURNING clause. */ |
| | @@ -155547,12 +156030,12 @@ |
| 155547 | 156030 | if( pTrigger != &(pReturning->retTrig) ){ |
| 155548 | 156031 | /* This RETURNING trigger is for a different statement */ |
| 155549 | 156032 | return; |
| 155550 | 156033 | } |
| 155551 | 156034 | memset(&sSelect, 0, sizeof(sSelect)); |
| 155552 | | - pFrom = (SrcList*)fromSpace; |
| 155553 | | - memset(pFrom, 0, SZ_SRCLIST_1); |
| 156035 | + memset(&uSrc, 0, sizeof(uSrc)); |
| 156036 | + pFrom = &uSrc.sSrc; |
| 155554 | 156037 | sSelect.pEList = sqlite3ExprListDup(db, pReturning->pReturnEL, 0); |
| 155555 | 156038 | sSelect.pSrc = pFrom; |
| 155556 | 156039 | pFrom->nSrc = 1; |
| 155557 | 156040 | pFrom->a[0].pSTab = pTab; |
| 155558 | 156041 | pFrom->a[0].zName = pTab->zName; /* tag-20240424-1 */ |
| | @@ -163079,11 +163562,14 @@ |
| 163079 | 163562 | WhereClause *pWC = &pWInfo->sWC; |
| 163080 | 163563 | WhereInfo *pSubWInfo; |
| 163081 | 163564 | WhereLoop *pLoop = pLevel->pWLoop; |
| 163082 | 163565 | SrcItem *pTabItem = &pWInfo->pTabList->a[pLevel->iFrom]; |
| 163083 | 163566 | SrcList *pFrom; |
| 163084 | | - u8 fromSpace[SZ_SRCLIST_1]; |
| 163567 | + union { |
| 163568 | + SrcList sSrc; |
| 163569 | + u8 fromSpace[SZ_SRCLIST_1]; |
| 163570 | + } uSrc; |
| 163085 | 163571 | Bitmask mAll = 0; |
| 163086 | 163572 | int k; |
| 163087 | 163573 | |
| 163088 | 163574 | ExplainQueryPlan((pParse, 1, "RIGHT-JOIN %s", pTabItem->pSTab->zName)); |
| 163089 | 163575 | sqlite3VdbeNoJumpsOutsideSubrtn(v, pRJ->addrSubrtn, pRJ->endSubrtn, |
| | @@ -163123,11 +163609,11 @@ |
| 163123 | 163609 | if( ExprHasProperty(pTerm->pExpr, EP_OuterON|EP_InnerON) ) continue; |
| 163124 | 163610 | pSubWhere = sqlite3ExprAnd(pParse, pSubWhere, |
| 163125 | 163611 | sqlite3ExprDup(pParse->db, pTerm->pExpr, 0)); |
| 163126 | 163612 | } |
| 163127 | 163613 | } |
| 163128 | | - pFrom = (SrcList*)fromSpace; |
| 163614 | + pFrom = &uSrc.sSrc; |
| 163129 | 163615 | pFrom->nSrc = 1; |
| 163130 | 163616 | pFrom->nAlloc = 1; |
| 163131 | 163617 | memcpy(&pFrom->a[0], pTabItem, sizeof(SrcItem)); |
| 163132 | 163618 | pFrom->a[0].fg.jointype = 0; |
| 163133 | 163619 | assert( pParse->withinRJSubrtn < 100 ); |
| | @@ -164340,25 +164826,11 @@ |
| 164340 | 164826 | Bitmask x = sqlite3WhereGetMask(pMaskSet, pExpr->w.iJoin); |
| 164341 | 164827 | if( ExprHasProperty(pExpr, EP_OuterON) ){ |
| 164342 | 164828 | prereqAll |= x; |
| 164343 | 164829 | extraRight = x-1; /* ON clause terms may not be used with an index |
| 164344 | 164830 | ** on left table of a LEFT JOIN. Ticket #3015 */ |
| 164345 | | - if( (prereqAll>>1)>=x ){ |
| 164346 | | - sqlite3ErrorMsg(pParse, "ON clause references tables to its right"); |
| 164347 | | - return; |
| 164348 | | - } |
| 164349 | 164831 | }else if( (prereqAll>>1)>=x ){ |
| 164350 | | - /* The ON clause of an INNER JOIN references a table to its right. |
| 164351 | | - ** Most other SQL database engines raise an error. But SQLite versions |
| 164352 | | - ** 3.0 through 3.38 just put the ON clause constraint into the WHERE |
| 164353 | | - ** clause and carried on. Beginning with 3.39, raise an error only |
| 164354 | | - ** if there is a RIGHT or FULL JOIN in the query. This makes SQLite |
| 164355 | | - ** more like other systems, and also preserves legacy. */ |
| 164356 | | - if( ALWAYS(pSrc->nSrc>0) && (pSrc->a[0].fg.jointype & JT_LTORJ)!=0 ){ |
| 164357 | | - sqlite3ErrorMsg(pParse, "ON clause references tables to its right"); |
| 164358 | | - return; |
| 164359 | | - } |
| 164360 | 164832 | ExprClearProperty(pExpr, EP_InnerON); |
| 164361 | 164833 | } |
| 164362 | 164834 | } |
| 164363 | 164835 | pTerm->prereqAll = prereqAll; |
| 164364 | 164836 | pTerm->leftCursor = -1; |
| | @@ -170216,10 +170688,14 @@ |
| 170216 | 170688 | if( pLoop->wsFlags & WHERE_VIRTUALTABLE ){ |
| 170217 | 170689 | if( pLoop->u.vtab.isOrdered |
| 170218 | 170690 | && ((wctrlFlags&(WHERE_DISTINCTBY|WHERE_SORTBYGROUP))!=WHERE_DISTINCTBY) |
| 170219 | 170691 | ){ |
| 170220 | 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; |
| 170221 | 170697 | } |
| 170222 | 170698 | break; |
| 170223 | 170699 | } |
| 170224 | 170700 | iCur = pWInfo->pTabList->a[pLoop->iTab].iCursor; |
| 170225 | 170701 | |
| | @@ -171119,22 +171595,18 @@ |
| 171119 | 171595 | pFrom = aTo; |
| 171120 | 171596 | aTo = aFrom; |
| 171121 | 171597 | aFrom = pFrom; |
| 171122 | 171598 | nFrom = nTo; |
| 171123 | 171599 | } |
| 171600 | + assert( nFrom==0 || nFrom==1 ); |
| 171124 | 171601 | |
| 171125 | 171602 | if( nFrom==0 ){ |
| 171126 | 171603 | sqlite3ErrorMsg(pParse, "no query solution"); |
| 171127 | 171604 | sqlite3StackFreeNN(pParse->db, pSpace); |
| 171128 | 171605 | return SQLITE_ERROR; |
| 171129 | 171606 | } |
| 171130 | | - |
| 171131 | | - /* Find the lowest cost path. pFrom will be left pointing to that path */ |
| 171132 | 171607 | pFrom = aFrom; |
| 171133 | | - for(ii=1; ii<nFrom; ii++){ |
| 171134 | | - if( pFrom->rCost>aFrom[ii].rCost ) pFrom = &aFrom[ii]; |
| 171135 | | - } |
| 171136 | 171608 | assert( pWInfo->nLevel==nLoop ); |
| 171137 | 171609 | /* Load the lowest cost path into pWInfo */ |
| 171138 | 171610 | for(iLoop=0; iLoop<nLoop; iLoop++){ |
| 171139 | 171611 | WhereLevel *pLevel = pWInfo->a + iLoop; |
| 171140 | 171612 | pLevel->pWLoop = pWLoop = pFrom->aLoop[iLoop]; |
| | @@ -171263,11 +171735,14 @@ |
| 171263 | 171735 | int once = 0; |
| 171264 | 171736 | #endif |
| 171265 | 171737 | for(i=0; i<pWInfo->nLevel; i++){ |
| 171266 | 171738 | WhereLoop *p = pWInfo->a[i].pWLoop; |
| 171267 | 171739 | if( p==0 ) break; |
| 171268 | | - 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 | + } |
| 171269 | 171744 | if( (p->wsFlags & (WHERE_COLUMN_EQ|WHERE_COLUMN_NULL|WHERE_COLUMN_IN))!=0 ){ |
| 171270 | 171745 | u8 iTab = p->iTab; |
| 171271 | 171746 | WhereLoop *pLoop; |
| 171272 | 171747 | for(pLoop=pWInfo->pLoops; pLoop; pLoop=pLoop->pNextLoop){ |
| 171273 | 171748 | if( pLoop->iTab!=iTab ) continue; |
| | @@ -175376,11 +175851,11 @@ |
| 175376 | 175851 | ** RETURN_ROW |
| 175377 | 175852 | ** |
| 175378 | 175853 | ** |
| 175379 | 175854 | ** ROWS BETWEEN <expr1> FOLLOWING AND <expr2> FOLLOWING |
| 175380 | 175855 | ** |
| 175381 | | -** ... loop started by sqlite3WhereBegin() ... |
| 175856 | +** ... loop started by sqlite3WhereBegin() ... |
| 175382 | 175857 | ** if( new partition ){ |
| 175383 | 175858 | ** Gosub flush |
| 175384 | 175859 | ** } |
| 175385 | 175860 | ** Insert new row into eph table. |
| 175386 | 175861 | ** if( first row of partition ){ |
| | @@ -175894,10 +176369,16 @@ |
| 175894 | 176369 | addrStart = sqlite3VdbeCurrentAddr(v); |
| 175895 | 176370 | addrBreak1 = windowCodeOp(&s, WINDOW_RETURN_ROW, regStart, 1); |
| 175896 | 176371 | addrBreak2 = windowCodeOp(&s, WINDOW_AGGINVERSE, 0, 1); |
| 175897 | 176372 | }else{ |
| 175898 | 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 | + |
| 175899 | 176380 | addrStart = sqlite3VdbeCurrentAddr(v); |
| 175900 | 176381 | addrBreak1 = windowCodeOp(&s, WINDOW_RETURN_ROW, regEnd, 1); |
| 175901 | 176382 | addrBreak2 = windowCodeOp(&s, WINDOW_AGGINVERSE, regStart, 1); |
| 175902 | 176383 | } |
| 175903 | 176384 | sqlite3VdbeAddOp2(v, OP_Goto, 0, addrStart); |
| | @@ -184839,10 +185320,13 @@ |
| 184839 | 185320 | for(i=0; i<2 && zName==0; i++, rc &= 0xff){ |
| 184840 | 185321 | switch( rc ){ |
| 184841 | 185322 | case SQLITE_OK: zName = "SQLITE_OK"; break; |
| 184842 | 185323 | case SQLITE_ERROR: zName = "SQLITE_ERROR"; break; |
| 184843 | 185324 | case SQLITE_ERROR_SNAPSHOT: zName = "SQLITE_ERROR_SNAPSHOT"; break; |
| 185325 | + case SQLITE_ERROR_RETRY: zName = "SQLITE_ERROR_RETRY"; break; |
| 185326 | + case SQLITE_ERROR_MISSING_COLLSEQ: |
| 185327 | + zName = "SQLITE_ERROR_MISSING_COLLSEQ"; break; |
| 184844 | 185328 | case SQLITE_INTERNAL: zName = "SQLITE_INTERNAL"; break; |
| 184845 | 185329 | case SQLITE_PERM: zName = "SQLITE_PERM"; break; |
| 184846 | 185330 | case SQLITE_ABORT: zName = "SQLITE_ABORT"; break; |
| 184847 | 185331 | case SQLITE_ABORT_ROLLBACK: zName = "SQLITE_ABORT_ROLLBACK"; break; |
| 184848 | 185332 | case SQLITE_BUSY: zName = "SQLITE_BUSY"; break; |
| | @@ -186019,10 +186503,33 @@ |
| 186019 | 186503 | } |
| 186020 | 186504 | } |
| 186021 | 186505 | sqlite3_mutex_leave(db->mutex); |
| 186022 | 186506 | return z; |
| 186023 | 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 | +} |
| 186024 | 186531 | |
| 186025 | 186532 | /* |
| 186026 | 186533 | ** Return the byte offset of the most recent error |
| 186027 | 186534 | */ |
| 186028 | 186535 | SQLITE_API int sqlite3_error_offset(sqlite3 *db){ |
| | @@ -187844,17 +188351,19 @@ |
| 187844 | 188351 | case SQLITE_TESTCTRL_ISINIT: { |
| 187845 | 188352 | if( sqlite3GlobalConfig.isInit==0 ) rc = SQLITE_ERROR; |
| 187846 | 188353 | break; |
| 187847 | 188354 | } |
| 187848 | 188355 | |
| 187849 | | - /* sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, db, dbName, onOff, tnum); |
| 188356 | + /* sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, db, dbName, mode, tnum); |
| 187850 | 188357 | ** |
| 187851 | 188358 | ** This test control is used to create imposter tables. "db" is a pointer |
| 187852 | 188359 | ** to the database connection. dbName is the database name (ex: "main" or |
| 187853 | | - ** "temp") which will receive the imposter. "onOff" turns imposter mode on |
| 187854 | | - ** or off. "tnum" is the root page of the b-tree to which the imposter |
| 187855 | | - ** 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. |
| 187856 | 188365 | ** |
| 187857 | 188366 | ** Enable imposter mode only when the schema has already been parsed. Then |
| 187858 | 188367 | ** run a single CREATE TABLE statement to construct the imposter table in |
| 187859 | 188368 | ** the parsed schema. Then turn imposter mode back off again. |
| 187860 | 188369 | ** |
| | @@ -189087,21 +189596,24 @@ |
| 189087 | 189596 | ** |
| 189088 | 189597 | */ |
| 189089 | 189598 | #ifndef _FTSINT_H |
| 189090 | 189599 | #define _FTSINT_H |
| 189091 | 189600 | |
| 189601 | +/* |
| 189602 | +** Activate assert() only if SQLITE_TEST is enabled. |
| 189603 | +*/ |
| 189604 | +#if !defined(NDEBUG) && !defined(SQLITE_DEBUG) |
| 189605 | +# define NDEBUG 1 |
| 189606 | +#endif |
| 189607 | + |
| 189092 | 189608 | /* #include <assert.h> */ |
| 189093 | 189609 | /* #include <stdlib.h> */ |
| 189094 | 189610 | /* #include <stddef.h> */ |
| 189095 | 189611 | /* #include <stdio.h> */ |
| 189096 | 189612 | /* #include <string.h> */ |
| 189097 | 189613 | /* #include <stdarg.h> */ |
| 189098 | 189614 | |
| 189099 | | -#if !defined(NDEBUG) && !defined(SQLITE_DEBUG) |
| 189100 | | -# define NDEBUG 1 |
| 189101 | | -#endif |
| 189102 | | - |
| 189103 | 189615 | /* FTS3/FTS4 require virtual tables */ |
| 189104 | 189616 | #ifdef SQLITE_OMIT_VIRTUALTABLE |
| 189105 | 189617 | # undef SQLITE_ENABLE_FTS3 |
| 189106 | 189618 | # undef SQLITE_ENABLE_FTS4 |
| 189107 | 189619 | #endif |
| | @@ -189540,17 +190052,10 @@ |
| 189540 | 190052 | /* |
| 189541 | 190053 | ** Macro used to suppress compiler warnings for unused parameters. |
| 189542 | 190054 | */ |
| 189543 | 190055 | #define UNUSED_PARAMETER(x) (void)(x) |
| 189544 | 190056 | |
| 189545 | | -/* |
| 189546 | | -** Activate assert() only if SQLITE_TEST is enabled. |
| 189547 | | -*/ |
| 189548 | | -#if !defined(NDEBUG) && !defined(SQLITE_DEBUG) |
| 189549 | | -# define NDEBUG 1 |
| 189550 | | -#endif |
| 189551 | | - |
| 189552 | 190057 | /* |
| 189553 | 190058 | ** The TESTONLY macro is used to enclose variable declarations or |
| 189554 | 190059 | ** other bits of code that are needed to support the arguments |
| 189555 | 190060 | ** within testcase() and assert() macros. |
| 189556 | 190061 | */ |
| | @@ -203821,12 +204326,12 @@ |
| 203821 | 204326 | /* |
| 203822 | 204327 | ** An object of this type contains the state required to create or append |
| 203823 | 204328 | ** to an appendable b-tree segment. |
| 203824 | 204329 | */ |
| 203825 | 204330 | struct IncrmergeWriter { |
| 203826 | | - int nLeafEst; /* Space allocated for leaf blocks */ |
| 203827 | | - int nWork; /* Number of leaf pages flushed */ |
| 204331 | + i64 nLeafEst; /* Space allocated for leaf blocks */ |
| 204332 | + i64 nWork; /* Number of leaf pages flushed */ |
| 203828 | 204333 | sqlite3_int64 iAbsLevel; /* Absolute level of input segments */ |
| 203829 | 204334 | int iIdx; /* Index of *output* segment in iAbsLevel+1 */ |
| 203830 | 204335 | sqlite3_int64 iStart; /* Block number of first allocated block */ |
| 203831 | 204336 | sqlite3_int64 iEnd; /* Block number of last allocated block */ |
| 203832 | 204337 | sqlite3_int64 nLeafData; /* Bytes of leaf page data so far */ |
| | @@ -204568,21 +205073,21 @@ |
| 204568 | 205073 | Fts3MultiSegReader *pCsr, /* Cursor that data will be read from */ |
| 204569 | 205074 | IncrmergeWriter *pWriter /* Populate this object */ |
| 204570 | 205075 | ){ |
| 204571 | 205076 | int rc; /* Return Code */ |
| 204572 | 205077 | int i; /* Iterator variable */ |
| 204573 | | - int nLeafEst = 0; /* Blocks allocated for leaf nodes */ |
| 205078 | + i64 nLeafEst = 0; /* Blocks allocated for leaf nodes */ |
| 204574 | 205079 | sqlite3_stmt *pLeafEst = 0; /* SQL used to determine nLeafEst */ |
| 204575 | 205080 | sqlite3_stmt *pFirstBlock = 0; /* SQL used to determine first block */ |
| 204576 | 205081 | |
| 204577 | 205082 | /* Calculate nLeafEst. */ |
| 204578 | 205083 | rc = fts3SqlStmt(p, SQL_MAX_LEAF_NODE_ESTIMATE, &pLeafEst, 0); |
| 204579 | 205084 | if( rc==SQLITE_OK ){ |
| 204580 | 205085 | sqlite3_bind_int64(pLeafEst, 1, iAbsLevel); |
| 204581 | 205086 | sqlite3_bind_int64(pLeafEst, 2, pCsr->nSegment); |
| 204582 | 205087 | if( SQLITE_ROW==sqlite3_step(pLeafEst) ){ |
| 204583 | | - nLeafEst = sqlite3_column_int(pLeafEst, 0); |
| 205088 | + nLeafEst = sqlite3_column_int64(pLeafEst, 0); |
| 204584 | 205089 | } |
| 204585 | 205090 | rc = sqlite3_reset(pLeafEst); |
| 204586 | 205091 | } |
| 204587 | 205092 | if( rc!=SQLITE_OK ) return rc; |
| 204588 | 205093 | |
| | @@ -228353,12 +228858,12 @@ |
| 228353 | 228858 | typedef struct DbpageTable DbpageTable; |
| 228354 | 228859 | typedef struct DbpageCursor DbpageCursor; |
| 228355 | 228860 | |
| 228356 | 228861 | struct DbpageCursor { |
| 228357 | 228862 | sqlite3_vtab_cursor base; /* Base class. Must be first */ |
| 228358 | | - int pgno; /* Current page number */ |
| 228359 | | - int mxPgno; /* Last page to visit on this scan */ |
| 228863 | + Pgno pgno; /* Current page number */ |
| 228864 | + Pgno mxPgno; /* Last page to visit on this scan */ |
| 228360 | 228865 | Pager *pPager; /* Pager being read/written */ |
| 228361 | 228866 | DbPage *pPage1; /* Page 1 of the database */ |
| 228362 | 228867 | int iDb; /* Index of database to analyze */ |
| 228363 | 228868 | int szPage; /* Size of each page in bytes */ |
| 228364 | 228869 | }; |
| | @@ -228491,11 +228996,11 @@ |
| 228491 | 228996 | if( pCsr==0 ){ |
| 228492 | 228997 | return SQLITE_NOMEM_BKPT; |
| 228493 | 228998 | }else{ |
| 228494 | 228999 | memset(pCsr, 0, sizeof(DbpageCursor)); |
| 228495 | 229000 | pCsr->base.pVtab = pVTab; |
| 228496 | | - pCsr->pgno = -1; |
| 229001 | + pCsr->pgno = 0; |
| 228497 | 229002 | } |
| 228498 | 229003 | |
| 228499 | 229004 | *ppCursor = (sqlite3_vtab_cursor *)pCsr; |
| 228500 | 229005 | return SQLITE_OK; |
| 228501 | 229006 | } |
| | @@ -228591,16 +229096,16 @@ |
| 228591 | 229096 | ){ |
| 228592 | 229097 | DbpageCursor *pCsr = (DbpageCursor *)pCursor; |
| 228593 | 229098 | int rc = SQLITE_OK; |
| 228594 | 229099 | switch( i ){ |
| 228595 | 229100 | case 0: { /* pgno */ |
| 228596 | | - sqlite3_result_int(ctx, pCsr->pgno); |
| 229101 | + sqlite3_result_int64(ctx, (sqlite3_int64)pCsr->pgno); |
| 228597 | 229102 | break; |
| 228598 | 229103 | } |
| 228599 | 229104 | case 1: { /* data */ |
| 228600 | 229105 | DbPage *pDbPage = 0; |
| 228601 | | - if( pCsr->pgno==((PENDING_BYTE/pCsr->szPage)+1) ){ |
| 229106 | + if( pCsr->pgno==(Pgno)((PENDING_BYTE/pCsr->szPage)+1) ){ |
| 228602 | 229107 | /* The pending byte page. Assume it is zeroed out. Attempting to |
| 228603 | 229108 | ** request this page from the page is an SQLITE_CORRUPT error. */ |
| 228604 | 229109 | sqlite3_result_zeroblob(ctx, pCsr->szPage); |
| 228605 | 229110 | }else{ |
| 228606 | 229111 | rc = sqlite3PagerGet(pCsr->pPager, pCsr->pgno, (DbPage**)&pDbPage, 0); |
| | @@ -228670,14 +229175,14 @@ |
| 228670 | 229175 | if( argc==1 ){ |
| 228671 | 229176 | zErr = "cannot delete"; |
| 228672 | 229177 | goto update_fail; |
| 228673 | 229178 | } |
| 228674 | 229179 | if( sqlite3_value_type(argv[0])==SQLITE_NULL ){ |
| 228675 | | - pgno = (Pgno)sqlite3_value_int(argv[2]); |
| 229180 | + pgno = (Pgno)sqlite3_value_int64(argv[2]); |
| 228676 | 229181 | isInsert = 1; |
| 228677 | 229182 | }else{ |
| 228678 | | - pgno = sqlite3_value_int(argv[0]); |
| 229183 | + pgno = (Pgno)sqlite3_value_int64(argv[0]); |
| 228679 | 229184 | if( (Pgno)sqlite3_value_int(argv[1])!=pgno ){ |
| 228680 | 229185 | zErr = "cannot insert"; |
| 228681 | 229186 | goto update_fail; |
| 228682 | 229187 | } |
| 228683 | 229188 | isInsert = 0; |
| | @@ -231625,10 +232130,23 @@ |
| 231625 | 232130 | assert( (a - p->aRecord)==p->nRecord ); |
| 231626 | 232131 | } |
| 231627 | 232132 | |
| 231628 | 232133 | return rc; |
| 231629 | 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 | +} |
| 231630 | 232148 | |
| 231631 | 232149 | /* |
| 231632 | 232150 | ** Formulate and prepare a SELECT statement to retrieve a row from table |
| 231633 | 232151 | ** zTab in database zDb based on its primary key. i.e. |
| 231634 | 232152 | ** |
| | @@ -231647,16 +232165,16 @@ |
| 231647 | 232165 | const char *zTab, /* Table name */ |
| 231648 | 232166 | int bRowid, |
| 231649 | 232167 | int nCol, /* Number of columns in table */ |
| 231650 | 232168 | const char **azCol, /* Names of table columns */ |
| 231651 | 232169 | u8 *abPK, /* PRIMARY KEY array */ |
| 231652 | | - sqlite3_stmt **ppStmt /* OUT: Prepared SELECT statement */ |
| 232170 | + sqlite3_stmt **ppStmt, /* OUT: Prepared SELECT statement */ |
| 232171 | + char **pzErrmsg /* OUT: Error message */ |
| 231653 | 232172 | ){ |
| 231654 | 232173 | int rc = SQLITE_OK; |
| 231655 | 232174 | char *zSql = 0; |
| 231656 | 232175 | const char *zSep = ""; |
| 231657 | | - int nSql = -1; |
| 231658 | 232176 | int i; |
| 231659 | 232177 | |
| 231660 | 232178 | SessionBuffer cols = {0, 0, 0}; |
| 231661 | 232179 | SessionBuffer nooptest = {0, 0, 0}; |
| 231662 | 232180 | SessionBuffer pkfield = {0, 0, 0}; |
| | @@ -231732,11 +232250,11 @@ |
| 231732 | 232250 | nSql = buf.nBuf; |
| 231733 | 232251 | } |
| 231734 | 232252 | #endif |
| 231735 | 232253 | |
| 231736 | 232254 | if( rc==SQLITE_OK ){ |
| 231737 | | - rc = sqlite3_prepare_v2(db, zSql, nSql, ppStmt, 0); |
| 232255 | + rc = sessionPrepare(db, ppStmt, pzErrmsg, zSql); |
| 231738 | 232256 | } |
| 231739 | 232257 | sqlite3_free(zSql); |
| 231740 | 232258 | sqlite3_free(nooptest.aBuf); |
| 231741 | 232259 | sqlite3_free(pkfield.aBuf); |
| 231742 | 232260 | sqlite3_free(pkvar.aBuf); |
| | @@ -231896,11 +232414,11 @@ |
| 231896 | 232414 | sessionAppendTableHdr(&buf, bPatchset, pTab, &rc); |
| 231897 | 232415 | |
| 231898 | 232416 | /* Build and compile a statement to execute: */ |
| 231899 | 232417 | if( rc==SQLITE_OK ){ |
| 231900 | 232418 | rc = sessionSelectStmt(db, 0, pSession->zDb, |
| 231901 | | - zName, pTab->bRowid, pTab->nCol, pTab->azCol, pTab->abPK, &pSel |
| 232419 | + zName, pTab->bRowid, pTab->nCol, pTab->azCol, pTab->abPK, &pSel, 0 |
| 231902 | 232420 | ); |
| 231903 | 232421 | } |
| 231904 | 232422 | |
| 231905 | 232423 | nNoop = buf.nBuf; |
| 231906 | 232424 | for(i=0; i<pTab->nChange && rc==SQLITE_OK; i++){ |
| | @@ -233105,10 +233623,11 @@ |
| 233105 | 233623 | SessionBuffer rebase; /* Rebase information (if any) here */ |
| 233106 | 233624 | u8 bRebaseStarted; /* If table header is already in rebase */ |
| 233107 | 233625 | u8 bRebase; /* True to collect rebase information */ |
| 233108 | 233626 | u8 bIgnoreNoop; /* True to ignore no-op conflicts */ |
| 233109 | 233627 | int bRowid; |
| 233628 | + char *zErr; /* Error message, if any */ |
| 233110 | 233629 | }; |
| 233111 | 233630 | |
| 233112 | 233631 | /* Number of prepared UPDATE statements to cache. */ |
| 233113 | 233632 | #define SESSION_UPDATE_CACHE_SZ 12 |
| 233114 | 233633 | |
| | @@ -233330,11 +233849,11 @@ |
| 233330 | 233849 | } |
| 233331 | 233850 | sessionAppendStr(&buf, ")", &rc); |
| 233332 | 233851 | } |
| 233333 | 233852 | |
| 233334 | 233853 | if( rc==SQLITE_OK ){ |
| 233335 | | - rc = sqlite3_prepare_v2(db, (char *)buf.aBuf, buf.nBuf, &p->pDelete, 0); |
| 233854 | + rc = sessionPrepare(db, &p->pDelete, &p->zErr, (char*)buf.aBuf); |
| 233336 | 233855 | } |
| 233337 | 233856 | sqlite3_free(buf.aBuf); |
| 233338 | 233857 | |
| 233339 | 233858 | return rc; |
| 233340 | 233859 | } |
| | @@ -233357,11 +233876,11 @@ |
| 233357 | 233876 | const char *zTab, /* Table name */ |
| 233358 | 233877 | SessionApplyCtx *p /* Session changeset-apply context */ |
| 233359 | 233878 | ){ |
| 233360 | 233879 | /* TODO */ |
| 233361 | 233880 | return sessionSelectStmt(db, p->bIgnoreNoop, |
| 233362 | | - "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 |
| 233363 | 233882 | ); |
| 233364 | 233883 | } |
| 233365 | 233884 | |
| 233366 | 233885 | /* |
| 233367 | 233886 | ** Formulate and prepare an INSERT statement to add a record to table zTab. |
| | @@ -233394,37 +233913,33 @@ |
| 233394 | 233913 | sessionAppendStr(&buf, ", ?", &rc); |
| 233395 | 233914 | } |
| 233396 | 233915 | sessionAppendStr(&buf, ")", &rc); |
| 233397 | 233916 | |
| 233398 | 233917 | if( rc==SQLITE_OK ){ |
| 233399 | | - rc = sqlite3_prepare_v2(db, (char *)buf.aBuf, buf.nBuf, &p->pInsert, 0); |
| 233918 | + rc = sessionPrepare(db, &p->pInsert, &p->zErr, (char*)buf.aBuf); |
| 233400 | 233919 | } |
| 233401 | 233920 | sqlite3_free(buf.aBuf); |
| 233402 | 233921 | return rc; |
| 233403 | 233922 | } |
| 233404 | 233923 | |
| 233405 | | -static int sessionPrepare(sqlite3 *db, sqlite3_stmt **pp, const char *zSql){ |
| 233406 | | - return sqlite3_prepare_v2(db, zSql, -1, pp, 0); |
| 233407 | | -} |
| 233408 | | - |
| 233409 | 233924 | /* |
| 233410 | 233925 | ** Prepare statements for applying changes to the sqlite_stat1 table. |
| 233411 | 233926 | ** These are similar to those created by sessionSelectRow(), |
| 233412 | 233927 | ** sessionInsertRow(), sessionUpdateRow() and sessionDeleteRow() for |
| 233413 | 233928 | ** other tables. |
| 233414 | 233929 | */ |
| 233415 | 233930 | static int sessionStat1Sql(sqlite3 *db, SessionApplyCtx *p){ |
| 233416 | 233931 | int rc = sessionSelectRow(db, "sqlite_stat1", p); |
| 233417 | 233932 | if( rc==SQLITE_OK ){ |
| 233418 | | - rc = sessionPrepare(db, &p->pInsert, |
| 233933 | + rc = sessionPrepare(db, &p->pInsert, 0, |
| 233419 | 233934 | "INSERT INTO main.sqlite_stat1 VALUES(?1, " |
| 233420 | 233935 | "CASE WHEN length(?2)=0 AND typeof(?2)='blob' THEN NULL ELSE ?2 END, " |
| 233421 | 233936 | "?3)" |
| 233422 | 233937 | ); |
| 233423 | 233938 | } |
| 233424 | 233939 | if( rc==SQLITE_OK ){ |
| 233425 | | - rc = sessionPrepare(db, &p->pDelete, |
| 233940 | + rc = sessionPrepare(db, &p->pDelete, 0, |
| 233426 | 233941 | "DELETE FROM main.sqlite_stat1 WHERE tbl=?1 AND idx IS " |
| 233427 | 233942 | "CASE WHEN length(?2)=0 AND typeof(?2)='blob' THEN NULL ELSE ?2 END " |
| 233428 | 233943 | "AND (?4 OR stat IS ?3)" |
| 233429 | 233944 | ); |
| 233430 | 233945 | } |
| | @@ -233644,11 +234159,11 @@ |
| 233644 | 234159 | sqlite3_changeset_iter *pIter, /* Changeset iterator */ |
| 233645 | 234160 | int(*xConflict)(void *, int, sqlite3_changeset_iter*), |
| 233646 | 234161 | void *pCtx, /* First argument for conflict handler */ |
| 233647 | 234162 | int *pbReplace /* OUT: Set to true if PK row is found */ |
| 233648 | 234163 | ){ |
| 233649 | | - int res = 0; /* Value returned by conflict handler */ |
| 234164 | + int res = SQLITE_CHANGESET_OMIT;/* Value returned by conflict handler */ |
| 233650 | 234165 | int rc; |
| 233651 | 234166 | int nCol; |
| 233652 | 234167 | int op; |
| 233653 | 234168 | const char *zDummy; |
| 233654 | 234169 | |
| | @@ -233665,15 +234180,13 @@ |
| 233665 | 234180 | rc = SQLITE_OK; |
| 233666 | 234181 | } |
| 233667 | 234182 | |
| 233668 | 234183 | if( rc==SQLITE_ROW ){ |
| 233669 | 234184 | /* There exists another row with the new.* primary key. */ |
| 233670 | | - if( p->bIgnoreNoop |
| 233671 | | - && sqlite3_column_int(p->pSelect, sqlite3_column_count(p->pSelect)-1) |
| 234185 | + if( 0==p->bIgnoreNoop |
| 234186 | + || 0==sqlite3_column_int(p->pSelect, sqlite3_column_count(p->pSelect)-1) |
| 233672 | 234187 | ){ |
| 233673 | | - res = SQLITE_CHANGESET_OMIT; |
| 233674 | | - }else{ |
| 233675 | 234188 | pIter->pConflict = p->pSelect; |
| 233676 | 234189 | res = xConflict(pCtx, eType, pIter); |
| 233677 | 234190 | pIter->pConflict = 0; |
| 233678 | 234191 | } |
| 233679 | 234192 | rc = sqlite3_reset(p->pSelect); |
| | @@ -233683,11 +234196,13 @@ |
| 233683 | 234196 | ** to the SessionApplyCtx.constraints buffer. */ |
| 233684 | 234197 | u8 *aBlob = &pIter->in.aData[pIter->in.iCurrent]; |
| 233685 | 234198 | int nBlob = pIter->in.iNext - pIter->in.iCurrent; |
| 233686 | 234199 | sessionAppendBlob(&p->constraints, aBlob, nBlob, &rc); |
| 233687 | 234200 | return SQLITE_OK; |
| 233688 | | - }else{ |
| 234201 | + }else if( p->bIgnoreNoop==0 || op!=SQLITE_DELETE |
| 234202 | + || eType==SQLITE_CHANGESET_CONFLICT |
| 234203 | + ){ |
| 233689 | 234204 | /* No other row with the new.* primary key. */ |
| 233690 | 234205 | res = xConflict(pCtx, eType+1, pIter); |
| 233691 | 234206 | if( res==SQLITE_CHANGESET_REPLACE ) rc = SQLITE_MISUSE; |
| 233692 | 234207 | } |
| 233693 | 234208 | } |
| | @@ -233781,11 +234296,11 @@ |
| 233781 | 234296 | } |
| 233782 | 234297 | if( rc!=SQLITE_OK ) return rc; |
| 233783 | 234298 | |
| 233784 | 234299 | sqlite3_step(p->pDelete); |
| 233785 | 234300 | rc = sqlite3_reset(p->pDelete); |
| 233786 | | - if( rc==SQLITE_OK && sqlite3_changes(p->db)==0 && p->bIgnoreNoop==0 ){ |
| 234301 | + if( rc==SQLITE_OK && sqlite3_changes(p->db)==0 ){ |
| 233787 | 234302 | rc = sessionConflictHandler( |
| 233788 | 234303 | SQLITE_CHANGESET_DATA, p, pIter, xConflict, pCtx, pbRetry |
| 233789 | 234304 | ); |
| 233790 | 234305 | }else if( (rc&0xff)==SQLITE_CONSTRAINT ){ |
| 233791 | 234306 | rc = sessionConflictHandler( |
| | @@ -234203,10 +234718,15 @@ |
| 234203 | 234718 | if( (flags & SQLITE_CHANGESETAPPLY_FKNOACTION) && savedFlag==0 ){ |
| 234204 | 234719 | assert( db->flags & SQLITE_FkNoAction ); |
| 234205 | 234720 | db->flags &= ~((u64)SQLITE_FkNoAction); |
| 234206 | 234721 | db->aDb[0].pSchema->schema_cookie -= 32; |
| 234207 | 234722 | } |
| 234723 | + |
| 234724 | + assert( rc!=SQLITE_OK || sApply.zErr==0 ); |
| 234725 | + sqlite3_set_errmsg(db, rc, sApply.zErr); |
| 234726 | + sqlite3_free(sApply.zErr); |
| 234727 | + |
| 234208 | 234728 | sqlite3_mutex_leave(sqlite3_db_mutex(db)); |
| 234209 | 234729 | return rc; |
| 234210 | 234730 | } |
| 234211 | 234731 | |
| 234212 | 234732 | /* |
| | @@ -236412,25 +236932,18 @@ |
| 236412 | 236932 | ** Constants for the largest and smallest possible 64-bit signed integers. |
| 236413 | 236933 | */ |
| 236414 | 236934 | # define LARGEST_INT64 (0xffffffff|(((i64)0x7fffffff)<<32)) |
| 236415 | 236935 | # define SMALLEST_INT64 (((i64)-1) - LARGEST_INT64) |
| 236416 | 236936 | |
| 236417 | | -/* The uptr type is an unsigned integer large enough to hold a pointer |
| 236937 | +/* |
| 236938 | +** This macro is used in a single assert() within fts5 to check that an |
| 236939 | +** allocation is aligned to an 8-byte boundary. But it is a complicated |
| 236940 | +** macro to get right for multiple platforms without generating warnings. |
| 236941 | +** So instead of reproducing the entire definition from sqliteInt.h, we |
| 236942 | +** just do without this assert() for the rare non-amalgamation builds. |
| 236418 | 236943 | */ |
| 236419 | | -#if defined(HAVE_STDINT_H) |
| 236420 | | - typedef uintptr_t uptr; |
| 236421 | | -#elif SQLITE_PTRSIZE==4 |
| 236422 | | - typedef u32 uptr; |
| 236423 | | -#else |
| 236424 | | - typedef u64 uptr; |
| 236425 | | -#endif |
| 236426 | | - |
| 236427 | | -#ifdef SQLITE_4_BYTE_ALIGNED_MALLOC |
| 236428 | | -# define EIGHT_BYTE_ALIGNMENT(X) ((((uptr)(X) - (uptr)0)&3)==0) |
| 236429 | | -#else |
| 236430 | | -# define EIGHT_BYTE_ALIGNMENT(X) ((((uptr)(X) - (uptr)0)&7)==0) |
| 236431 | | -#endif |
| 236944 | +#define EIGHT_BYTE_ALIGNMENT(x) 1 |
| 236432 | 236945 | |
| 236433 | 236946 | /* |
| 236434 | 236947 | ** Macros needed to provide flexible arrays in a portable way |
| 236435 | 236948 | */ |
| 236436 | 236949 | #ifndef offsetof |
| | @@ -237174,11 +237687,11 @@ |
| 237174 | 237687 | ** ){ |
| 237175 | 237688 | ** // The document with rowid iRowid matches the expression! |
| 237176 | 237689 | ** i64 iRowid = sqlite3Fts5ExprRowid(pExpr); |
| 237177 | 237690 | ** } |
| 237178 | 237691 | */ |
| 237179 | | -static int sqlite3Fts5ExprFirst(Fts5Expr*, Fts5Index *pIdx, i64 iMin, int bDesc); |
| 237692 | +static int sqlite3Fts5ExprFirst(Fts5Expr*, Fts5Index *pIdx, i64 iMin, i64, int bDesc); |
| 237180 | 237693 | static int sqlite3Fts5ExprNext(Fts5Expr*, i64 iMax); |
| 237181 | 237694 | static int sqlite3Fts5ExprEof(Fts5Expr*); |
| 237182 | 237695 | static i64 sqlite3Fts5ExprRowid(Fts5Expr*); |
| 237183 | 237696 | |
| 237184 | 237697 | static void sqlite3Fts5ExprFree(Fts5Expr*); |
| | @@ -242743,11 +243256,17 @@ |
| 242743 | 243256 | ** equal to iFirst. |
| 242744 | 243257 | ** |
| 242745 | 243258 | ** Return SQLITE_OK if successful, or an SQLite error code otherwise. It |
| 242746 | 243259 | ** is not considered an error if the query does not match any documents. |
| 242747 | 243260 | */ |
| 242748 | | -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 | +){ |
| 242749 | 243268 | Fts5ExprNode *pRoot = p->pRoot; |
| 242750 | 243269 | int rc; /* Return code */ |
| 242751 | 243270 | |
| 242752 | 243271 | p->pIndex = pIdx; |
| 242753 | 243272 | p->bDesc = bDesc; |
| | @@ -242764,10 +243283,13 @@ |
| 242764 | 243283 | |
| 242765 | 243284 | /* If the iterator is not at a real match, skip forward until it is. */ |
| 242766 | 243285 | while( pRoot->bNomatch && rc==SQLITE_OK ){ |
| 242767 | 243286 | assert( pRoot->bEof==0 ); |
| 242768 | 243287 | rc = fts5ExprNodeNext(p, pRoot, 0, 0); |
| 243288 | + } |
| 243289 | + if( fts5RowidCmp(p, pRoot->iRowid, iLast)>0 ){ |
| 243290 | + pRoot->bEof = 1; |
| 242769 | 243291 | } |
| 242770 | 243292 | return rc; |
| 242771 | 243293 | } |
| 242772 | 243294 | |
| 242773 | 243295 | /* |
| | @@ -251885,14 +252407,17 @@ |
| 251885 | 252407 | ** function populates it with the initial structure objects for each index, |
| 251886 | 252408 | ** and the initial version of the "averages" record (a zero-byte blob). |
| 251887 | 252409 | */ |
| 251888 | 252410 | static int sqlite3Fts5IndexReinit(Fts5Index *p){ |
| 251889 | 252411 | Fts5Structure *pTmp; |
| 251890 | | - u8 tmpSpace[SZ_FTS5STRUCTURE(1)]; |
| 252412 | + union { |
| 252413 | + Fts5Structure sFts; |
| 252414 | + u8 tmpSpace[SZ_FTS5STRUCTURE(1)]; |
| 252415 | + } uFts; |
| 251891 | 252416 | fts5StructureInvalidate(p); |
| 251892 | 252417 | fts5IndexDiscardData(p); |
| 251893 | | - pTmp = (Fts5Structure*)tmpSpace; |
| 252418 | + pTmp = &uFts.sFts; |
| 251894 | 252419 | memset(pTmp, 0, SZ_FTS5STRUCTURE(1)); |
| 251895 | 252420 | if( p->pConfig->bContentlessDelete ){ |
| 251896 | 252421 | pTmp->nOriginCntr = 1; |
| 251897 | 252422 | } |
| 251898 | 252423 | fts5DataWrite(p, FTS5_AVERAGES_ROWID, (const u8*)"", 0); |
| | @@ -255109,10 +255634,21 @@ |
| 255109 | 255634 | { |
| 255110 | 255635 | pIdxInfo->idxFlags |= SQLITE_INDEX_SCAN_UNIQUE; |
| 255111 | 255636 | } |
| 255112 | 255637 | #endif |
| 255113 | 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 | +} |
| 255114 | 255650 | |
| 255115 | 255651 | static int fts5UsePatternMatch( |
| 255116 | 255652 | Fts5Config *pConfig, |
| 255117 | 255653 | struct sqlite3_index_constraint *p |
| 255118 | 255654 | ){ |
| | @@ -255245,11 +255781,11 @@ |
| 255245 | 255781 | bSeenRank = 1; |
| 255246 | 255782 | }else{ |
| 255247 | 255783 | nSeenMatch++; |
| 255248 | 255784 | idxStr[iIdxStr++] = 'M'; |
| 255249 | 255785 | sqlite3_snprintf(6, &idxStr[iIdxStr], "%d", iCol); |
| 255250 | | - idxStr += strlen(&idxStr[iIdxStr]); |
| 255786 | + iIdxStr += (int)strlen(&idxStr[iIdxStr]); |
| 255251 | 255787 | assert( idxStr[iIdxStr]=='\0' ); |
| 255252 | 255788 | } |
| 255253 | 255789 | pInfo->aConstraintUsage[i].argvIndex = ++iCons; |
| 255254 | 255790 | pInfo->aConstraintUsage[i].omit = 1; |
| 255255 | 255791 | } |
| | @@ -255264,10 +255800,11 @@ |
| 255264 | 255800 | nSeenMatch++; |
| 255265 | 255801 | }else if( bSeenEq==0 && p->op==SQLITE_INDEX_CONSTRAINT_EQ && iCol<0 ){ |
| 255266 | 255802 | idxStr[iIdxStr++] = '='; |
| 255267 | 255803 | bSeenEq = 1; |
| 255268 | 255804 | pInfo->aConstraintUsage[i].argvIndex = ++iCons; |
| 255805 | + pInfo->aConstraintUsage[i].omit = 1; |
| 255269 | 255806 | } |
| 255270 | 255807 | } |
| 255271 | 255808 | } |
| 255272 | 255809 | |
| 255273 | 255810 | if( bSeenEq==0 ){ |
| | @@ -255311,21 +255848,25 @@ |
| 255311 | 255848 | } |
| 255312 | 255849 | } |
| 255313 | 255850 | |
| 255314 | 255851 | /* Calculate the estimated cost based on the flags set in idxFlags. */ |
| 255315 | 255852 | if( bSeenEq ){ |
| 255316 | | - pInfo->estimatedCost = nSeenMatch ? 1000.0 : 10.0; |
| 255317 | | - if( nSeenMatch==0 ) fts5SetUniqueFlag(pInfo); |
| 255318 | | - }else if( bSeenLt && bSeenGt ){ |
| 255319 | | - pInfo->estimatedCost = nSeenMatch ? 5000.0 : 250000.0; |
| 255320 | | - }else if( bSeenLt || bSeenGt ){ |
| 255321 | | - pInfo->estimatedCost = nSeenMatch ? 7500.0 : 750000.0; |
| 255853 | + pInfo->estimatedCost = nSeenMatch ? 1000.0 : 25.0; |
| 255854 | + fts5SetUniqueFlag(pInfo); |
| 255855 | + fts5SetEstimatedRows(pInfo, 1); |
| 255322 | 255856 | }else{ |
| 255323 | | - pInfo->estimatedCost = nSeenMatch ? 10000.0 : 1000000.0; |
| 255324 | | - } |
| 255325 | | - for(i=1; i<nSeenMatch; i++){ |
| 255326 | | - 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)); |
| 255327 | 255868 | } |
| 255328 | 255869 | |
| 255329 | 255870 | pInfo->idxNum = idxFlags; |
| 255330 | 255871 | return SQLITE_OK; |
| 255331 | 255872 | } |
| | @@ -255520,11 +256061,13 @@ |
| 255520 | 256061 | if( CsrFlagTest(pCsr, FTS5CSR_REQUIRE_RESEEK) ){ |
| 255521 | 256062 | Fts5FullTable *pTab = (Fts5FullTable*)(pCsr->base.pVtab); |
| 255522 | 256063 | int bDesc = pCsr->bDesc; |
| 255523 | 256064 | i64 iRowid = sqlite3Fts5ExprRowid(pCsr->pExpr); |
| 255524 | 256065 | |
| 255525 | | - rc = sqlite3Fts5ExprFirst(pCsr->pExpr, pTab->p.pIndex, iRowid, bDesc); |
| 256066 | + rc = sqlite3Fts5ExprFirst( |
| 256067 | + pCsr->pExpr, pTab->p.pIndex, iRowid, pCsr->iLastRowid, bDesc |
| 256068 | + ); |
| 255526 | 256069 | if( rc==SQLITE_OK && iRowid!=sqlite3Fts5ExprRowid(pCsr->pExpr) ){ |
| 255527 | 256070 | *pbSkip = 1; |
| 255528 | 256071 | } |
| 255529 | 256072 | |
| 255530 | 256073 | CsrFlagClear(pCsr, FTS5CSR_REQUIRE_RESEEK); |
| | @@ -255692,11 +256235,13 @@ |
| 255692 | 256235 | } |
| 255693 | 256236 | |
| 255694 | 256237 | static int fts5CursorFirst(Fts5FullTable *pTab, Fts5Cursor *pCsr, int bDesc){ |
| 255695 | 256238 | int rc; |
| 255696 | 256239 | Fts5Expr *pExpr = pCsr->pExpr; |
| 255697 | | - rc = sqlite3Fts5ExprFirst(pExpr, pTab->p.pIndex, pCsr->iFirstRowid, bDesc); |
| 256240 | + rc = sqlite3Fts5ExprFirst( |
| 256241 | + pExpr, pTab->p.pIndex, pCsr->iFirstRowid, pCsr->iLastRowid, bDesc |
| 256242 | + ); |
| 255698 | 256243 | if( sqlite3Fts5ExprEof(pExpr) ){ |
| 255699 | 256244 | CsrFlagSet(pCsr, FTS5CSR_EOF); |
| 255700 | 256245 | } |
| 255701 | 256246 | fts5CsrNewrow(pCsr); |
| 255702 | 256247 | return rc; |
| | @@ -258177,11 +258722,11 @@ |
| 258177 | 258722 | int nArg, /* Number of args */ |
| 258178 | 258723 | sqlite3_value **apUnused /* Function arguments */ |
| 258179 | 258724 | ){ |
| 258180 | 258725 | assert( nArg==0 ); |
| 258181 | 258726 | UNUSED_PARAM2(nArg, apUnused); |
| 258182 | | - sqlite3_result_text(pCtx, "fts5: 2025-07-30 16:17:14 cf7163f82ca380958a79350473b2c5a2cebda7496d6d575fa2835c362010fea1", -1, SQLITE_TRANSIENT); |
| 258727 | + sqlite3_result_text(pCtx, "fts5: 2025-09-24 19:10:58 821cc0e421bc14a68ebaee507e38a900e0c84ff6ba7ee95bf796cad387755232", -1, SQLITE_TRANSIENT); |
| 258183 | 258728 | } |
| 258184 | 258729 | |
| 258185 | 258730 | /* |
| 258186 | 258731 | ** Implementation of fts5_locale(LOCALE, TEXT) function. |
| 258187 | 258732 | ** |
| 258188 | 258733 | |