| | @@ -1,8 +1,8 @@ |
| 1 | 1 | /****************************************************************************** |
| 2 | 2 | ** This file is an amalgamation of many separate C source files from SQLite |
| 3 | | -** version 3.49.0. By combining all the individual C code files into this |
| 3 | +** version 3.50.0. By combining all the individual C code files into this |
| 4 | 4 | ** single large file, the entire code can be compiled as a single translation |
| 5 | 5 | ** unit. This allows many compilers to do optimizations that would not be |
| 6 | 6 | ** possible if the files were compiled separately. Performance improvements |
| 7 | 7 | ** of 5% or more are commonly seen when SQLite is compiled as a single |
| 8 | 8 | ** translation unit. |
| | @@ -16,11 +16,11 @@ |
| 16 | 16 | ** if you want a wrapper to interface SQLite with your choice of programming |
| 17 | 17 | ** language. The code for the "sqlite3" command-line shell is also in a |
| 18 | 18 | ** separate file. This file contains only code for the core SQLite library. |
| 19 | 19 | ** |
| 20 | 20 | ** The content in this amalgamation comes from Fossil check-in |
| 21 | | -** 4a7dd425dc2a0e5082a9049c9b4a9d4f199a with changes in files: |
| 21 | +** e5ec5bb9f4dc3e02db7ab0e49686f47617af with changes in files: |
| 22 | 22 | ** |
| 23 | 23 | ** |
| 24 | 24 | */ |
| 25 | 25 | #ifndef SQLITE_AMALGAMATION |
| 26 | 26 | #define SQLITE_CORE 1 |
| | @@ -463,13 +463,13 @@ |
| 463 | 463 | ** |
| 464 | 464 | ** See also: [sqlite3_libversion()], |
| 465 | 465 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 466 | 466 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 467 | 467 | */ |
| 468 | | -#define SQLITE_VERSION "3.49.0" |
| 469 | | -#define SQLITE_VERSION_NUMBER 3049000 |
| 470 | | -#define SQLITE_SOURCE_ID "2025-02-06 11:55:18 4a7dd425dc2a0e5082a9049c9b4a9d4f199a71583d014c24b4cfe276c5a77cde" |
| 468 | +#define SQLITE_VERSION "3.50.0" |
| 469 | +#define SQLITE_VERSION_NUMBER 3050000 |
| 470 | +#define SQLITE_SOURCE_ID "2025-02-11 17:10:46 e5ec5bb9f4dc3e02db7ab0e49686f47617af75d3f7d4ab23288a1aea4a693e59" |
| 471 | 471 | |
| 472 | 472 | /* |
| 473 | 473 | ** CAPI3REF: Run-Time Library Version Numbers |
| 474 | 474 | ** KEYWORDS: sqlite3_version sqlite3_sourceid |
| 475 | 475 | ** |
| | @@ -1480,10 +1480,15 @@ |
| 1480 | 1480 | ** obtain a file lock using the xLock or xShmLock methods of the VFS. |
| 1481 | 1481 | ** The parameter is a pointer to a 32-bit signed integer that contains |
| 1482 | 1482 | ** the value that M is to be set to. Before returning, the 32-bit signed |
| 1483 | 1483 | ** integer is overwritten with the previous value of M. |
| 1484 | 1484 | ** |
| 1485 | +** <li>[[SQLITE_FCNTL_BLOCK_ON_CONNECT]] |
| 1486 | +** The [SQLITE_FCNTL_BLOCK_ON_CONNECT] opcode is used to configure the |
| 1487 | +** VFS to block when taking SHARED locks. This is used to implement the |
| 1488 | +** functionality associated with SQLITE_SETLK_BLOCK_ON_CONNECT. |
| 1489 | +** |
| 1485 | 1490 | ** <li>[[SQLITE_FCNTL_DATA_VERSION]] |
| 1486 | 1491 | ** The [SQLITE_FCNTL_DATA_VERSION] opcode is used to detect changes to |
| 1487 | 1492 | ** a database file. The argument is a pointer to a 32-bit unsigned integer. |
| 1488 | 1493 | ** The "data version" for the pager is written into the pointer. The |
| 1489 | 1494 | ** "data version" changes whenever any change occurs to the corresponding |
| | @@ -1576,10 +1581,11 @@ |
| 1576 | 1581 | #define SQLITE_FCNTL_CKPT_START 39 |
| 1577 | 1582 | #define SQLITE_FCNTL_EXTERNAL_READER 40 |
| 1578 | 1583 | #define SQLITE_FCNTL_CKSM_FILE 41 |
| 1579 | 1584 | #define SQLITE_FCNTL_RESET_CACHE 42 |
| 1580 | 1585 | #define SQLITE_FCNTL_NULL_IO 43 |
| 1586 | +#define SQLITE_FCNTL_BLOCK_ON_CONNECT 44 |
| 1581 | 1587 | |
| 1582 | 1588 | /* deprecated names */ |
| 1583 | 1589 | #define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE |
| 1584 | 1590 | #define SQLITE_SET_LOCKPROXYFILE SQLITE_FCNTL_SET_LOCKPROXYFILE |
| 1585 | 1591 | #define SQLITE_LAST_ERRNO SQLITE_FCNTL_LAST_ERRNO |
| | @@ -3310,10 +3316,48 @@ |
| 3310 | 3316 | ** |
| 3311 | 3317 | ** See also: [PRAGMA busy_timeout] |
| 3312 | 3318 | */ |
| 3313 | 3319 | SQLITE_API int sqlite3_busy_timeout(sqlite3*, int ms); |
| 3314 | 3320 | |
| 3321 | +/* |
| 3322 | +** CAPI3REF: Set the Setlk Timeout |
| 3323 | +** METHOD: sqlite3 |
| 3324 | +** |
| 3325 | +** This routine is only useful in SQLITE_ENABLE_SETLK_TIMEOUT builds. If |
| 3326 | +** the VFS supports blocking locks, it sets the timeout in ms used by |
| 3327 | +** eligible locks taken on wal mode databases by the specified database |
| 3328 | +** handle. In non-SQLITE_ENABLE_SETLK_TIMEOUT builds, or if the VFS does |
| 3329 | +** not support blocking locks, this function is a no-op. |
| 3330 | +** |
| 3331 | +** Passing 0 to this function disables blocking locks altogether. Passing |
| 3332 | +** -1 to this function requests that the VFS blocks for a long time - |
| 3333 | +** indefinitely if possible. The results of passing any other negative value |
| 3334 | +** are undefined. |
| 3335 | +** |
| 3336 | +** Internally, each SQLite database handle store two timeout values - the |
| 3337 | +** busy-timeout (used for rollback mode databases, or if the VFS does not |
| 3338 | +** support blocking locks) and the setlk-timeout (used for blocking locks |
| 3339 | +** on wal-mode databases). The sqlite3_busy_timeout() method sets both |
| 3340 | +** values, this function sets only the setlk-timeout value. Therefore, |
| 3341 | +** to configure separate busy-timeout and setlk-timeout values for a single |
| 3342 | +** database handle, call sqlite3_busy_timeout() followed by this function. |
| 3343 | +** |
| 3344 | +** Whenever the number of connections to a wal mode database falls from |
| 3345 | +** 1 to 0, the last connection takes an exclusive lock on the database, |
| 3346 | +** then checkpoints and deletes the wal file. While it is doing this, any |
| 3347 | +** new connection that tries to read from the database fails with an |
| 3348 | +** SQLITE_BUSY error. Or, if the SQLITE_SETLK_BLOCK_ON_CONNECT flag is |
| 3349 | +** passed to this API, the new connection blocks until the exclusive lock |
| 3350 | +** has been released. |
| 3351 | +*/ |
| 3352 | +SQLITE_API int sqlite3_setlk_timeout(sqlite3*, int ms, int flags); |
| 3353 | + |
| 3354 | +/* |
| 3355 | +** CAPI3REF: Flags for sqlite3_setlk_timeout() |
| 3356 | +*/ |
| 3357 | +#define SQLITE_SETLK_BLOCK_ON_CONNECT 0x01 |
| 3358 | + |
| 3315 | 3359 | /* |
| 3316 | 3360 | ** CAPI3REF: Convenience Routines For Running Queries |
| 3317 | 3361 | ** METHOD: sqlite3 |
| 3318 | 3362 | ** |
| 3319 | 3363 | ** This is a legacy interface that is preserved for backwards compatibility. |
| | @@ -14747,10 +14791,11 @@ |
| 14747 | 14791 | */ |
| 14748 | 14792 | struct HashElem { |
| 14749 | 14793 | HashElem *next, *prev; /* Next and previous elements in the table */ |
| 14750 | 14794 | void *data; /* Data associated with this element */ |
| 14751 | 14795 | const char *pKey; /* Key associated with this element */ |
| 14796 | + unsigned int h; /* hash for pKey */ |
| 14752 | 14797 | }; |
| 14753 | 14798 | |
| 14754 | 14799 | /* |
| 14755 | 14800 | ** Access routines. To delete, insert a NULL pointer. |
| 14756 | 14801 | */ |
| | @@ -15184,10 +15229,15 @@ |
| 15184 | 15229 | typedef UINT32_TYPE u32; /* 4-byte unsigned integer */ |
| 15185 | 15230 | typedef UINT16_TYPE u16; /* 2-byte unsigned integer */ |
| 15186 | 15231 | typedef INT16_TYPE i16; /* 2-byte signed integer */ |
| 15187 | 15232 | typedef UINT8_TYPE u8; /* 1-byte unsigned integer */ |
| 15188 | 15233 | typedef INT8_TYPE i8; /* 1-byte signed integer */ |
| 15234 | + |
| 15235 | +/* A bitfield type for use inside of structures. Always follow with :N where |
| 15236 | +** N is the number of bits. |
| 15237 | +*/ |
| 15238 | +typedef unsigned bft; /* Bit Field Type */ |
| 15189 | 15239 | |
| 15190 | 15240 | /* |
| 15191 | 15241 | ** SQLITE_MAX_U32 is a u64 constant that is the maximum u64 value |
| 15192 | 15242 | ** that can be stored in a u32 without loss of data. The value |
| 15193 | 15243 | ** is 0x00000000ffffffff. But because of quirks of some compilers, we |
| | @@ -18053,10 +18103,14 @@ |
| 18053 | 18103 | BusyHandler busyHandler; /* Busy callback */ |
| 18054 | 18104 | Db aDbStatic[2]; /* Static space for the 2 default backends */ |
| 18055 | 18105 | Savepoint *pSavepoint; /* List of active savepoints */ |
| 18056 | 18106 | int nAnalysisLimit; /* Number of index rows to ANALYZE */ |
| 18057 | 18107 | int busyTimeout; /* Busy handler timeout, in msec */ |
| 18108 | +#ifdef SQLITE_ENABLE_SETLK_TIMEOUT |
| 18109 | + int setlkTimeout; /* Blocking lock timeout, in msec. -1 -> inf. */ |
| 18110 | + int setlkFlags; /* Flags passed to setlk_timeout() */ |
| 18111 | +#endif |
| 18058 | 18112 | int nSavepoint; /* Number of non-transaction savepoints */ |
| 18059 | 18113 | int nStatement; /* Number of nested statement-transactions */ |
| 18060 | 18114 | i64 nDeferredCons; /* Net deferred constraints this transaction. */ |
| 18061 | 18115 | i64 nDeferredImmCons; /* Net deferred immediate constraints */ |
| 18062 | 18116 | int *pnBytesFreed; /* If not NULL, increment this in DbFree() */ |
| | @@ -18731,10 +18785,11 @@ |
| 18731 | 18785 | VTable *p; /* List of VTable objects. */ |
| 18732 | 18786 | } vtab; |
| 18733 | 18787 | } u; |
| 18734 | 18788 | Trigger *pTrigger; /* List of triggers on this object */ |
| 18735 | 18789 | Schema *pSchema; /* Schema that contains this table */ |
| 18790 | + u8 aHx[16]; /* Column aHt[K%sizeof(aHt)] might have hash K */ |
| 18736 | 18791 | }; |
| 18737 | 18792 | |
| 18738 | 18793 | /* |
| 18739 | 18794 | ** Allowed values for Table.tabFlags. |
| 18740 | 18795 | ** |
| | @@ -20128,29 +20183,36 @@ |
| 20128 | 20183 | struct Parse { |
| 20129 | 20184 | sqlite3 *db; /* The main database structure */ |
| 20130 | 20185 | char *zErrMsg; /* An error message */ |
| 20131 | 20186 | Vdbe *pVdbe; /* An engine for executing database bytecode */ |
| 20132 | 20187 | int rc; /* Return code from execution */ |
| 20133 | | - u8 colNamesSet; /* TRUE after OP_ColumnName has been issued to pVdbe */ |
| 20134 | | - u8 checkSchema; /* Causes schema cookie check after an error */ |
| 20188 | + LogEst nQueryLoop; /* Est number of iterations of a query (10*log2(N)) */ |
| 20135 | 20189 | u8 nested; /* Number of nested calls to the parser/code generator */ |
| 20136 | 20190 | u8 nTempReg; /* Number of temporary registers in aTempReg[] */ |
| 20137 | 20191 | u8 isMultiWrite; /* True if statement may modify/insert multiple rows */ |
| 20138 | 20192 | u8 mayAbort; /* True if statement may throw an ABORT exception */ |
| 20139 | 20193 | u8 hasCompound; /* Need to invoke convertCompoundSelectToSubquery() */ |
| 20140 | | - u8 okConstFactor; /* OK to factor out constants */ |
| 20141 | 20194 | u8 disableLookaside; /* Number of times lookaside has been disabled */ |
| 20142 | 20195 | u8 prepFlags; /* SQLITE_PREPARE_* flags */ |
| 20143 | 20196 | u8 withinRJSubrtn; /* Nesting level for RIGHT JOIN body subroutines */ |
| 20144 | | - u8 bHasWith; /* True if statement contains WITH */ |
| 20145 | 20197 | u8 mSubrtnSig; /* mini Bloom filter on available SubrtnSig.selId */ |
| 20198 | + u8 eTriggerOp; /* TK_UPDATE, TK_INSERT or TK_DELETE */ |
| 20199 | + u8 bReturning; /* Coding a RETURNING trigger */ |
| 20200 | + u8 eOrconf; /* Default ON CONFLICT policy for trigger steps */ |
| 20201 | + u8 disableTriggers; /* True to disable triggers */ |
| 20146 | 20202 | #if defined(SQLITE_DEBUG) || defined(SQLITE_COVERAGE_TEST) |
| 20147 | 20203 | u8 earlyCleanup; /* OOM inside sqlite3ParserAddCleanup() */ |
| 20148 | 20204 | #endif |
| 20149 | 20205 | #ifdef SQLITE_DEBUG |
| 20150 | 20206 | u8 ifNotExists; /* Might be true if IF NOT EXISTS. Assert()s only */ |
| 20207 | + u8 isCreate; /* CREATE TABLE, INDEX, or VIEW (but not TRIGGER) |
| 20208 | + ** and ALTER TABLE ADD COLUMN. */ |
| 20151 | 20209 | #endif |
| 20210 | + bft colNamesSet :1; /* TRUE after OP_ColumnName has been issued to pVdbe */ |
| 20211 | + bft bHasWith :1; /* True if statement contains WITH */ |
| 20212 | + bft okConstFactor :1; /* OK to factor out constants */ |
| 20213 | + bft checkSchema :1; /* Causes schema cookie check after an error */ |
| 20152 | 20214 | int nRangeReg; /* Size of the temporary register block */ |
| 20153 | 20215 | int iRangeReg; /* First register in temporary register block */ |
| 20154 | 20216 | int nErr; /* Number of errors seen */ |
| 20155 | 20217 | int nTab; /* Number of previously allocated VDBE cursors */ |
| 20156 | 20218 | int nMem; /* Number of memory cells used so far */ |
| | @@ -20161,16 +20223,13 @@ |
| 20161 | 20223 | int nLabelAlloc; /* Number of slots in aLabel */ |
| 20162 | 20224 | int *aLabel; /* Space to hold the labels */ |
| 20163 | 20225 | ExprList *pConstExpr;/* Constant expressions */ |
| 20164 | 20226 | IndexedExpr *pIdxEpr;/* List of expressions used by active indexes */ |
| 20165 | 20227 | IndexedExpr *pIdxPartExpr; /* Exprs constrained by index WHERE clauses */ |
| 20166 | | - Token constraintName;/* Name of the constraint currently being parsed */ |
| 20167 | 20228 | yDbMask writeMask; /* Start a write transaction on these databases */ |
| 20168 | 20229 | yDbMask cookieMask; /* Bitmask of schema verified databases */ |
| 20169 | | - int regRowid; /* Register holding rowid of CREATE TABLE entry */ |
| 20170 | | - int regRoot; /* Register holding root page number for new objects */ |
| 20171 | | - int nMaxArg; /* Max args passed to user function by sub-program */ |
| 20230 | + int nMaxArg; /* Max args to xUpdate and xFilter vtab methods */ |
| 20172 | 20231 | int nSelect; /* Number of SELECT stmts. Counter for Select.selId */ |
| 20173 | 20232 | #ifndef SQLITE_OMIT_PROGRESS_CALLBACK |
| 20174 | 20233 | u32 nProgressSteps; /* xProgress steps taken during sqlite3_prepare() */ |
| 20175 | 20234 | #endif |
| 20176 | 20235 | #ifndef SQLITE_OMIT_SHARED_CACHE |
| | @@ -20180,21 +20239,10 @@ |
| 20180 | 20239 | AutoincInfo *pAinc; /* Information about AUTOINCREMENT counters */ |
| 20181 | 20240 | Parse *pToplevel; /* Parse structure for main program (or NULL) */ |
| 20182 | 20241 | Table *pTriggerTab; /* Table triggers are being coded for */ |
| 20183 | 20242 | TriggerPrg *pTriggerPrg; /* Linked list of coded triggers */ |
| 20184 | 20243 | ParseCleanup *pCleanup; /* List of cleanup operations to run after parse */ |
| 20185 | | - union { |
| 20186 | | - int addrCrTab; /* Address of OP_CreateBtree on CREATE TABLE */ |
| 20187 | | - Returning *pReturning; /* The RETURNING clause */ |
| 20188 | | - } u1; |
| 20189 | | - u32 oldmask; /* Mask of old.* columns referenced */ |
| 20190 | | - u32 newmask; /* Mask of new.* columns referenced */ |
| 20191 | | - LogEst nQueryLoop; /* Est number of iterations of a query (10*log2(N)) */ |
| 20192 | | - u8 eTriggerOp; /* TK_UPDATE, TK_INSERT or TK_DELETE */ |
| 20193 | | - u8 bReturning; /* Coding a RETURNING trigger */ |
| 20194 | | - u8 eOrconf; /* Default ON CONFLICT policy for trigger steps */ |
| 20195 | | - u8 disableTriggers; /* True to disable triggers */ |
| 20196 | 20244 | |
| 20197 | 20245 | /************************************************************************** |
| 20198 | 20246 | ** Fields above must be initialized to zero. The fields that follow, |
| 20199 | 20247 | ** down to the beginning of the recursive section, do not need to be |
| 20200 | 20248 | ** initialized as they will be set before being used. The boundary is |
| | @@ -20202,10 +20250,23 @@ |
| 20202 | 20250 | **************************************************************************/ |
| 20203 | 20251 | |
| 20204 | 20252 | int aTempReg[8]; /* Holding area for temporary registers */ |
| 20205 | 20253 | Parse *pOuterParse; /* Outer Parse object when nested */ |
| 20206 | 20254 | Token sNameToken; /* Token with unqualified schema object name */ |
| 20255 | + u32 oldmask; /* Mask of old.* columns referenced */ |
| 20256 | + u32 newmask; /* Mask of new.* columns referenced */ |
| 20257 | + union { |
| 20258 | + struct { /* These fields available when isCreate is true */ |
| 20259 | + int addrCrTab; /* Address of OP_CreateBtree on CREATE TABLE */ |
| 20260 | + int regRowid; /* Register holding rowid of CREATE TABLE entry */ |
| 20261 | + int regRoot; /* Register holding root page for new objects */ |
| 20262 | + Token constraintName; /* Name of the constraint currently being parsed */ |
| 20263 | + } cr; |
| 20264 | + struct { /* These fields available to all other statements */ |
| 20265 | + Returning *pReturning; /* The RETURNING clause */ |
| 20266 | + } d; |
| 20267 | + } u1; |
| 20207 | 20268 | |
| 20208 | 20269 | /************************************************************************ |
| 20209 | 20270 | ** Above is constant between recursions. Below is reset before and after |
| 20210 | 20271 | ** each recursion. The boundary between these two regions is determined |
| 20211 | 20272 | ** using offsetof(Parse,sLastToken) so the sLastToken field must be the |
| | @@ -23831,14 +23892,10 @@ |
| 23831 | 23892 | u8 skipFlag; /* Skip accumulator loading if true */ |
| 23832 | 23893 | u16 argc; /* Number of arguments */ |
| 23833 | 23894 | sqlite3_value *argv[1]; /* Argument set */ |
| 23834 | 23895 | }; |
| 23835 | 23896 | |
| 23836 | | -/* A bitfield type for use inside of structures. Always follow with :N where |
| 23837 | | -** N is the number of bits. |
| 23838 | | -*/ |
| 23839 | | -typedef unsigned bft; /* Bit Field Type */ |
| 23840 | 23897 | |
| 23841 | 23898 | /* The ScanStatus object holds a single value for the |
| 23842 | 23899 | ** sqlite3_stmt_scanstatus() interface. |
| 23843 | 23900 | ** |
| 23844 | 23901 | ** aAddrRange[]: |
| | @@ -23895,11 +23952,11 @@ |
| 23895 | 23952 | i64 iCurrentTime; /* Value of julianday('now') for this statement */ |
| 23896 | 23953 | i64 nFkConstraint; /* Number of imm. FK constraints this VM */ |
| 23897 | 23954 | i64 nStmtDefCons; /* Number of def. constraints when stmt started */ |
| 23898 | 23955 | i64 nStmtDefImmCons; /* Number of def. imm constraints when stmt started */ |
| 23899 | 23956 | Mem *aMem; /* The memory locations */ |
| 23900 | | - Mem **apArg; /* Arguments to currently executing user function */ |
| 23957 | + Mem **apArg; /* Arguments xUpdate and xFilter vtab methods */ |
| 23901 | 23958 | VdbeCursor **apCsr; /* One element of this array for each open cursor */ |
| 23902 | 23959 | Mem *aVar; /* Values for the OP_Variable opcode. */ |
| 23903 | 23960 | |
| 23904 | 23961 | /* When allocating a new Vdbe object, all of the fields below should be |
| 23905 | 23962 | ** initialized to zero or NULL */ |
| | @@ -23915,10 +23972,11 @@ |
| 23915 | 23972 | i64 startTime; /* Time when query started - used for profiling */ |
| 23916 | 23973 | #endif |
| 23917 | 23974 | #ifdef SQLITE_DEBUG |
| 23918 | 23975 | int rcApp; /* errcode set by sqlite3_result_error_code() */ |
| 23919 | 23976 | u32 nWrite; /* Number of write operations that have occurred */ |
| 23977 | + int napArg; /* Size of the apArg[] array */ |
| 23920 | 23978 | #endif |
| 23921 | 23979 | u16 nResColumn; /* Number of columns in one row of the result set */ |
| 23922 | 23980 | u16 nResAlloc; /* Column slots allocated to aColName[] */ |
| 23923 | 23981 | u8 errorAction; /* Recovery action to do in case of an error */ |
| 23924 | 23982 | u8 minWriteFileFormat; /* Minimum file format for writable database files */ |
| | @@ -36398,11 +36456,15 @@ |
| 36398 | 36456 | } |
| 36399 | 36457 | } |
| 36400 | 36458 | } |
| 36401 | 36459 | p->z = &p->zBuf[i+1]; |
| 36402 | 36460 | assert( i+p->n < sizeof(p->zBuf) ); |
| 36403 | | - while( ALWAYS(p->n>0) && p->z[p->n-1]=='0' ){ p->n--; } |
| 36461 | + assert( p->n>0 ); |
| 36462 | + while( p->z[p->n-1]=='0' ){ |
| 36463 | + p->n--; |
| 36464 | + assert( p->n>0 ); |
| 36465 | + } |
| 36404 | 36466 | } |
| 36405 | 36467 | |
| 36406 | 36468 | /* |
| 36407 | 36469 | ** Try to convert z into an unsigned 32-bit integer. Return true on |
| 36408 | 36470 | ** success and false if there is an error. |
| | @@ -37184,16 +37246,23 @@ |
| 37184 | 37246 | /* |
| 37185 | 37247 | ** The hashing function. |
| 37186 | 37248 | */ |
| 37187 | 37249 | static unsigned int strHash(const char *z){ |
| 37188 | 37250 | unsigned int h = 0; |
| 37189 | | - unsigned char c; |
| 37190 | | - while( (c = (unsigned char)*z++)!=0 ){ /*OPTIMIZATION-IF-TRUE*/ |
| 37251 | + while( z[0] ){ /*OPTIMIZATION-IF-TRUE*/ |
| 37191 | 37252 | /* Knuth multiplicative hashing. (Sorting & Searching, p. 510). |
| 37192 | 37253 | ** 0x9e3779b1 is 2654435761 which is the closest prime number to |
| 37193 | | - ** (2**32)*golden_ratio, where golden_ratio = (sqrt(5) - 1)/2. */ |
| 37194 | | - h += sqlite3UpperToLower[c]; |
| 37254 | + ** (2**32)*golden_ratio, where golden_ratio = (sqrt(5) - 1)/2. |
| 37255 | + ** |
| 37256 | + ** Only bits 0xdf for ASCII and bits 0xbf for EBCDIC each octet are |
| 37257 | + ** hashed since the omitted bits determine the upper/lower case difference. |
| 37258 | + */ |
| 37259 | +#ifdef SQLITE_EBCDIC |
| 37260 | + h += 0xbf & (unsigned char)*(z++); |
| 37261 | +#else |
| 37262 | + h += 0xdf & (unsigned char)*(z++); |
| 37263 | +#endif |
| 37195 | 37264 | h *= 0x9e3779b1; |
| 37196 | 37265 | } |
| 37197 | 37266 | return h; |
| 37198 | 37267 | } |
| 37199 | 37268 | |
| | @@ -37262,13 +37331,12 @@ |
| 37262 | 37331 | sqlite3_free(pH->ht); |
| 37263 | 37332 | pH->ht = new_ht; |
| 37264 | 37333 | pH->htsize = new_size = sqlite3MallocSize(new_ht)/sizeof(struct _ht); |
| 37265 | 37334 | memset(new_ht, 0, new_size*sizeof(struct _ht)); |
| 37266 | 37335 | for(elem=pH->first, pH->first=0; elem; elem = next_elem){ |
| 37267 | | - unsigned int h = strHash(elem->pKey) % new_size; |
| 37268 | 37336 | next_elem = elem->next; |
| 37269 | | - insertElement(pH, &new_ht[h], elem); |
| 37337 | + insertElement(pH, &new_ht[elem->h % new_size], elem); |
| 37270 | 37338 | } |
| 37271 | 37339 | return 1; |
| 37272 | 37340 | } |
| 37273 | 37341 | |
| 37274 | 37342 | /* This function (for internal use only) locates an element in an |
| | @@ -37282,27 +37350,26 @@ |
| 37282 | 37350 | unsigned int *pHash /* Write the hash value here */ |
| 37283 | 37351 | ){ |
| 37284 | 37352 | HashElem *elem; /* Used to loop thru the element list */ |
| 37285 | 37353 | unsigned int count; /* Number of elements left to test */ |
| 37286 | 37354 | unsigned int h; /* The computed hash */ |
| 37287 | | - static HashElem nullElement = { 0, 0, 0, 0 }; |
| 37355 | + static HashElem nullElement = { 0, 0, 0, 0, 0 }; |
| 37288 | 37356 | |
| 37357 | + h = strHash(pKey); |
| 37289 | 37358 | if( pH->ht ){ /*OPTIMIZATION-IF-TRUE*/ |
| 37290 | 37359 | struct _ht *pEntry; |
| 37291 | | - h = strHash(pKey) % pH->htsize; |
| 37292 | | - pEntry = &pH->ht[h]; |
| 37360 | + pEntry = &pH->ht[h % pH->htsize]; |
| 37293 | 37361 | elem = pEntry->chain; |
| 37294 | 37362 | count = pEntry->count; |
| 37295 | 37363 | }else{ |
| 37296 | | - h = 0; |
| 37297 | 37364 | elem = pH->first; |
| 37298 | 37365 | count = pH->count; |
| 37299 | 37366 | } |
| 37300 | 37367 | if( pHash ) *pHash = h; |
| 37301 | 37368 | while( count ){ |
| 37302 | 37369 | assert( elem!=0 ); |
| 37303 | | - if( sqlite3StrICmp(elem->pKey,pKey)==0 ){ |
| 37370 | + if( h==elem->h && sqlite3StrICmp(elem->pKey,pKey)==0 ){ |
| 37304 | 37371 | return elem; |
| 37305 | 37372 | } |
| 37306 | 37373 | elem = elem->next; |
| 37307 | 37374 | count--; |
| 37308 | 37375 | } |
| | @@ -37310,14 +37377,13 @@ |
| 37310 | 37377 | } |
| 37311 | 37378 | |
| 37312 | 37379 | /* Remove a single entry from the hash table given a pointer to that |
| 37313 | 37380 | ** element and a hash on the element's key. |
| 37314 | 37381 | */ |
| 37315 | | -static void removeElementGivenHash( |
| 37382 | +static void removeElement( |
| 37316 | 37383 | Hash *pH, /* The pH containing "elem" */ |
| 37317 | | - HashElem* elem, /* The element to be removed from the pH */ |
| 37318 | | - unsigned int h /* Hash value for the element */ |
| 37384 | + HashElem *elem /* The element to be removed from the pH */ |
| 37319 | 37385 | ){ |
| 37320 | 37386 | struct _ht *pEntry; |
| 37321 | 37387 | if( elem->prev ){ |
| 37322 | 37388 | elem->prev->next = elem->next; |
| 37323 | 37389 | }else{ |
| | @@ -37325,11 +37391,11 @@ |
| 37325 | 37391 | } |
| 37326 | 37392 | if( elem->next ){ |
| 37327 | 37393 | elem->next->prev = elem->prev; |
| 37328 | 37394 | } |
| 37329 | 37395 | if( pH->ht ){ |
| 37330 | | - pEntry = &pH->ht[h]; |
| 37396 | + pEntry = &pH->ht[elem->h % pH->htsize]; |
| 37331 | 37397 | if( pEntry->chain==elem ){ |
| 37332 | 37398 | pEntry->chain = elem->next; |
| 37333 | 37399 | } |
| 37334 | 37400 | assert( pEntry->count>0 ); |
| 37335 | 37401 | pEntry->count--; |
| | @@ -37376,11 +37442,11 @@ |
| 37376 | 37442 | assert( pKey!=0 ); |
| 37377 | 37443 | elem = findElementWithHash(pH,pKey,&h); |
| 37378 | 37444 | if( elem->data ){ |
| 37379 | 37445 | void *old_data = elem->data; |
| 37380 | 37446 | if( data==0 ){ |
| 37381 | | - removeElementGivenHash(pH,elem,h); |
| 37447 | + removeElement(pH,elem); |
| 37382 | 37448 | }else{ |
| 37383 | 37449 | elem->data = data; |
| 37384 | 37450 | elem->pKey = pKey; |
| 37385 | 37451 | } |
| 37386 | 37452 | return old_data; |
| | @@ -37387,19 +37453,17 @@ |
| 37387 | 37453 | } |
| 37388 | 37454 | if( data==0 ) return 0; |
| 37389 | 37455 | new_elem = (HashElem*)sqlite3Malloc( sizeof(HashElem) ); |
| 37390 | 37456 | if( new_elem==0 ) return data; |
| 37391 | 37457 | new_elem->pKey = pKey; |
| 37458 | + new_elem->h = h; |
| 37392 | 37459 | new_elem->data = data; |
| 37393 | 37460 | pH->count++; |
| 37394 | | - if( pH->count>=10 && pH->count > 2*pH->htsize ){ |
| 37395 | | - if( rehash(pH, pH->count*2) ){ |
| 37396 | | - assert( pH->htsize>0 ); |
| 37397 | | - h = strHash(pKey) % pH->htsize; |
| 37398 | | - } |
| 37461 | + if( pH->count>=5 && pH->count > 2*pH->htsize ){ |
| 37462 | + rehash(pH, pH->count*3); |
| 37399 | 37463 | } |
| 37400 | | - insertElement(pH, pH->ht ? &pH->ht[h] : 0, new_elem); |
| 37464 | + insertElement(pH, pH->ht ? &pH->ht[new_elem->h % pH->htsize] : 0, new_elem); |
| 37401 | 37465 | return 0; |
| 37402 | 37466 | } |
| 37403 | 37467 | |
| 37404 | 37468 | /************** End of hash.c ************************************************/ |
| 37405 | 37469 | /************** Begin file opcodes.c *****************************************/ |
| | @@ -38878,10 +38942,11 @@ |
| 38878 | 38942 | #if SQLITE_ENABLE_LOCKING_STYLE || defined(__APPLE__) |
| 38879 | 38943 | unsigned fsFlags; /* cached details from statfs() */ |
| 38880 | 38944 | #endif |
| 38881 | 38945 | #ifdef SQLITE_ENABLE_SETLK_TIMEOUT |
| 38882 | 38946 | unsigned iBusyTimeout; /* Wait this many millisec on locks */ |
| 38947 | + int bBlockOnConnect; /* True to block for SHARED locks */ |
| 38883 | 38948 | #endif |
| 38884 | 38949 | #if OS_VXWORKS |
| 38885 | 38950 | struct vxworksFileId *pId; /* Unique file ID */ |
| 38886 | 38951 | #endif |
| 38887 | 38952 | #ifdef SQLITE_DEBUG |
| | @@ -40271,10 +40336,17 @@ |
| 40271 | 40336 | pInode->nLock++; |
| 40272 | 40337 | }else{ |
| 40273 | 40338 | rc = 0; |
| 40274 | 40339 | } |
| 40275 | 40340 | }else{ |
| 40341 | +#ifdef SQLITE_ENABLE_SETLK_TIMEOUT |
| 40342 | + if( pFile->bBlockOnConnect && pLock->l_type==F_RDLCK |
| 40343 | + && pLock->l_start==SHARED_FIRST && pLock->l_len==SHARED_SIZE |
| 40344 | + ){ |
| 40345 | + rc = osFcntl(pFile->h, F_SETLKW, pLock); |
| 40346 | + }else |
| 40347 | +#endif |
| 40276 | 40348 | rc = osSetPosixAdvisoryLock(pFile->h, pLock, pFile); |
| 40277 | 40349 | } |
| 40278 | 40350 | return rc; |
| 40279 | 40351 | } |
| 40280 | 40352 | |
| | @@ -42632,21 +42704,27 @@ |
| 42632 | 42704 | return SQLITE_OK; |
| 42633 | 42705 | } |
| 42634 | 42706 | #ifdef SQLITE_ENABLE_SETLK_TIMEOUT |
| 42635 | 42707 | case SQLITE_FCNTL_LOCK_TIMEOUT: { |
| 42636 | 42708 | int iOld = pFile->iBusyTimeout; |
| 42709 | + int iNew = *(int*)pArg; |
| 42637 | 42710 | #if SQLITE_ENABLE_SETLK_TIMEOUT==1 |
| 42638 | | - pFile->iBusyTimeout = *(int*)pArg; |
| 42711 | + pFile->iBusyTimeout = iNew<0 ? 0x7FFFFFFF : (unsigned)iNew; |
| 42639 | 42712 | #elif SQLITE_ENABLE_SETLK_TIMEOUT==2 |
| 42640 | 42713 | pFile->iBusyTimeout = !!(*(int*)pArg); |
| 42641 | 42714 | #else |
| 42642 | 42715 | # error "SQLITE_ENABLE_SETLK_TIMEOUT must be set to 1 or 2" |
| 42643 | 42716 | #endif |
| 42644 | 42717 | *(int*)pArg = iOld; |
| 42645 | 42718 | return SQLITE_OK; |
| 42646 | 42719 | } |
| 42647 | | -#endif |
| 42720 | + case SQLITE_FCNTL_BLOCK_ON_CONNECT: { |
| 42721 | + int iNew = *(int*)pArg; |
| 42722 | + pFile->bBlockOnConnect = iNew; |
| 42723 | + return SQLITE_OK; |
| 42724 | + } |
| 42725 | +#endif /* SQLITE_ENABLE_SETLK_TIMEOUT */ |
| 42648 | 42726 | #if SQLITE_MAX_MMAP_SIZE>0 |
| 42649 | 42727 | case SQLITE_FCNTL_MMAP_SIZE: { |
| 42650 | 42728 | i64 newLimit = *(i64*)pArg; |
| 42651 | 42729 | int rc = SQLITE_OK; |
| 42652 | 42730 | if( newLimit>sqlite3GlobalConfig.mxMmap ){ |
| | @@ -47155,11 +47233,21 @@ |
| 47155 | 47233 | HANDLE hMap; /* Handle for accessing memory mapping */ |
| 47156 | 47234 | void *pMapRegion; /* Area memory mapped */ |
| 47157 | 47235 | sqlite3_int64 mmapSize; /* Size of mapped region */ |
| 47158 | 47236 | sqlite3_int64 mmapSizeMax; /* Configured FCNTL_MMAP_SIZE value */ |
| 47159 | 47237 | #endif |
| 47238 | +#ifdef SQLITE_ENABLE_SETLK_TIMEOUT |
| 47239 | + DWORD iBusyTimeout; /* Wait this many millisec on locks */ |
| 47240 | + int bBlockOnConnect; |
| 47241 | +#endif |
| 47160 | 47242 | }; |
| 47243 | + |
| 47244 | +#ifdef SQLITE_ENABLE_SETLK_TIMEOUT |
| 47245 | +# define winFileBusyTimeout(pDbFd) pDbFd->iBusyTimeout |
| 47246 | +#else |
| 47247 | +# define winFileBusyTimeout(pDbFd) 0 |
| 47248 | +#endif |
| 47161 | 47249 | |
| 47162 | 47250 | /* |
| 47163 | 47251 | ** The winVfsAppData structure is used for the pAppData member for all of the |
| 47164 | 47252 | ** Win32 VFS variants. |
| 47165 | 47253 | */ |
| | @@ -47590,10 +47678,16 @@ |
| 47590 | 47678 | #endif |
| 47591 | 47679 | |
| 47592 | 47680 | #define osGetFullPathNameW ((DWORD(WINAPI*)(LPCWSTR,DWORD,LPWSTR, \ |
| 47593 | 47681 | LPWSTR*))aSyscall[25].pCurrent) |
| 47594 | 47682 | |
| 47683 | +/* |
| 47684 | +** For GetLastError(), MSDN says: |
| 47685 | +** |
| 47686 | +** Minimum supported client: Windows XP [desktop apps | UWP apps] |
| 47687 | +** Minimum supported server: Windows Server 2003 [desktop apps | UWP apps] |
| 47688 | +*/ |
| 47595 | 47689 | { "GetLastError", (SYSCALL)GetLastError, 0 }, |
| 47596 | 47690 | |
| 47597 | 47691 | #define osGetLastError ((DWORD(WINAPI*)(VOID))aSyscall[26].pCurrent) |
| 47598 | 47692 | |
| 47599 | 47693 | #if !defined(SQLITE_OMIT_LOAD_EXTENSION) |
| | @@ -47872,15 +47966,17 @@ |
| 47872 | 47966 | #endif |
| 47873 | 47967 | |
| 47874 | 47968 | #define osCreateEventExW ((HANDLE(WINAPI*)(LPSECURITY_ATTRIBUTES,LPCWSTR, \ |
| 47875 | 47969 | DWORD,DWORD))aSyscall[62].pCurrent) |
| 47876 | 47970 | |
| 47877 | | -#if !SQLITE_OS_WINRT |
| 47971 | +/* |
| 47972 | +** For WaitForSingleObject(), MSDN says: |
| 47973 | +** |
| 47974 | +** Minimum supported client: Windows XP [desktop apps | UWP apps] |
| 47975 | +** Minimum supported server: Windows Server 2003 [desktop apps | UWP apps] |
| 47976 | +*/ |
| 47878 | 47977 | { "WaitForSingleObject", (SYSCALL)WaitForSingleObject, 0 }, |
| 47879 | | -#else |
| 47880 | | - { "WaitForSingleObject", (SYSCALL)0, 0 }, |
| 47881 | | -#endif |
| 47882 | 47978 | |
| 47883 | 47979 | #define osWaitForSingleObject ((DWORD(WINAPI*)(HANDLE, \ |
| 47884 | 47980 | DWORD))aSyscall[63].pCurrent) |
| 47885 | 47981 | |
| 47886 | 47982 | #if !SQLITE_OS_WINCE |
| | @@ -48023,10 +48119,44 @@ |
| 48023 | 48119 | #endif |
| 48024 | 48120 | |
| 48025 | 48121 | #define osFlushViewOfFile \ |
| 48026 | 48122 | ((BOOL(WINAPI*)(LPCVOID,SIZE_T))aSyscall[79].pCurrent) |
| 48027 | 48123 | |
| 48124 | +/* |
| 48125 | +** If SQLITE_ENABLE_SETLK_TIMEOUT is defined, we require CreateEvent() |
| 48126 | +** to implement blocking locks with timeouts. MSDN says: |
| 48127 | +** |
| 48128 | +** Minimum supported client: Windows XP [desktop apps | UWP apps] |
| 48129 | +** Minimum supported server: Windows Server 2003 [desktop apps | UWP apps] |
| 48130 | +*/ |
| 48131 | +#ifdef SQLITE_ENABLE_SETLK_TIMEOUT |
| 48132 | + { "CreateEvent", (SYSCALL)CreateEvent, 0 }, |
| 48133 | +#else |
| 48134 | + { "CreateEvent", (SYSCALL)0, 0 }, |
| 48135 | +#endif |
| 48136 | + |
| 48137 | +#define osCreateEvent ( \ |
| 48138 | + (HANDLE(WINAPI*) (LPSECURITY_ATTRIBUTES,BOOL,BOOL,LPCSTR)) \ |
| 48139 | + aSyscall[80].pCurrent \ |
| 48140 | +) |
| 48141 | + |
| 48142 | +/* |
| 48143 | +** If SQLITE_ENABLE_SETLK_TIMEOUT is defined, we require CancelIo() |
| 48144 | +** for the case where a timeout expires and a lock request must be |
| 48145 | +** cancelled. |
| 48146 | +** |
| 48147 | +** Minimum supported client: Windows XP [desktop apps | UWP apps] |
| 48148 | +** Minimum supported server: Windows Server 2003 [desktop apps | UWP apps] |
| 48149 | +*/ |
| 48150 | +#ifdef SQLITE_ENABLE_SETLK_TIMEOUT |
| 48151 | + { "CancelIo", (SYSCALL)CancelIo, 0 }, |
| 48152 | +#else |
| 48153 | + { "CancelIo", (SYSCALL)0, 0 }, |
| 48154 | +#endif |
| 48155 | + |
| 48156 | +#define osCancelIo ((BOOL(WINAPI*)(HANDLE))aSyscall[81].pCurrent) |
| 48157 | + |
| 48028 | 48158 | }; /* End of the overrideable system calls */ |
| 48029 | 48159 | |
| 48030 | 48160 | /* |
| 48031 | 48161 | ** This is the xSetSystemCall() method of sqlite3_vfs for all of the |
| 48032 | 48162 | ** "win32" VFSes. Return SQLITE_OK upon successfully updating the |
| | @@ -48321,11 +48451,13 @@ |
| 48321 | 48451 | (sInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) ? 2 : 1, 0); |
| 48322 | 48452 | #endif |
| 48323 | 48453 | } |
| 48324 | 48454 | return osInterlockedCompareExchange(&sqlite3_os_type, 2, 2)==2; |
| 48325 | 48455 | #elif SQLITE_TEST |
| 48326 | | - return osInterlockedCompareExchange(&sqlite3_os_type, 2, 2)==2; |
| 48456 | + return osInterlockedCompareExchange(&sqlite3_os_type, 2, 2)==2 |
| 48457 | + || osInterlockedCompareExchange(&sqlite3_os_type, 0, 0)==0 |
| 48458 | + ; |
| 48327 | 48459 | #else |
| 48328 | 48460 | /* |
| 48329 | 48461 | ** NOTE: All sub-platforms where the GetVersionEx[AW] functions are |
| 48330 | 48462 | ** deprecated are always assumed to be based on the NT kernel. |
| 48331 | 48463 | */ |
| | @@ -49407,10 +49539,89 @@ |
| 49407 | 49539 | return osLockFile(*phFile, offsetLow, offsetHigh, numBytesLow, |
| 49408 | 49540 | numBytesHigh); |
| 49409 | 49541 | } |
| 49410 | 49542 | #endif |
| 49411 | 49543 | } |
| 49544 | + |
| 49545 | +/* |
| 49546 | +** Lock a region of nByte bytes starting at offset offset of file hFile. |
| 49547 | +** Take an EXCLUSIVE lock if parameter bExclusive is true, or a SHARED lock |
| 49548 | +** otherwise. If nMs is greater than zero and the lock cannot be obtained |
| 49549 | +** immediately, block for that many ms before giving up. |
| 49550 | +** |
| 49551 | +** This function returns SQLITE_OK if the lock is obtained successfully. If |
| 49552 | +** some other process holds the lock, SQLITE_BUSY is returned if nMs==0, or |
| 49553 | +** SQLITE_BUSY_TIMEOUT otherwise. Or, if an error occurs, SQLITE_IOERR. |
| 49554 | +*/ |
| 49555 | +static int winHandleLockTimeout( |
| 49556 | + HANDLE hFile, |
| 49557 | + DWORD offset, |
| 49558 | + DWORD nByte, |
| 49559 | + int bExcl, |
| 49560 | + DWORD nMs |
| 49561 | +){ |
| 49562 | + DWORD flags = LOCKFILE_FAIL_IMMEDIATELY | (bExcl?LOCKFILE_EXCLUSIVE_LOCK:0); |
| 49563 | + int rc = SQLITE_OK; |
| 49564 | + BOOL ret; |
| 49565 | + |
| 49566 | + if( !osIsNT() ){ |
| 49567 | + ret = winLockFile(&hFile, flags, offset, 0, nByte, 0); |
| 49568 | + }else{ |
| 49569 | + OVERLAPPED ovlp; |
| 49570 | + memset(&ovlp, 0, sizeof(OVERLAPPED)); |
| 49571 | + ovlp.Offset = offset; |
| 49572 | + |
| 49573 | +#ifdef SQLITE_ENABLE_SETLK_TIMEOUT |
| 49574 | + if( nMs!=0 ){ |
| 49575 | + flags &= ~LOCKFILE_FAIL_IMMEDIATELY; |
| 49576 | + } |
| 49577 | + ovlp.hEvent = osCreateEvent(NULL, TRUE, FALSE, NULL); |
| 49578 | + if( ovlp.hEvent==NULL ){ |
| 49579 | + return SQLITE_IOERR_LOCK; |
| 49580 | + } |
| 49581 | +#endif |
| 49582 | + |
| 49583 | + ret = osLockFileEx(hFile, flags, 0, nByte, 0, &ovlp); |
| 49584 | + |
| 49585 | +#ifdef SQLITE_ENABLE_SETLK_TIMEOUT |
| 49586 | + /* If SQLITE_ENABLE_SETLK_TIMEOUT is defined, then the file-handle was |
| 49587 | + ** opened with FILE_FLAG_OVERHEAD specified. In this case, the call to |
| 49588 | + ** LockFileEx() may fail because the request is still pending. This can |
| 49589 | + ** happen even if LOCKFILE_FAIL_IMMEDIATELY was specified. |
| 49590 | + ** |
| 49591 | + ** If nMs is 0, then LOCKFILE_FAIL_IMMEDIATELY was set in the flags |
| 49592 | + ** passed to LockFileEx(). In this case, if the operation is pending, |
| 49593 | + ** block indefinitely until it is finished. |
| 49594 | + ** |
| 49595 | + ** Otherwise, wait for up to nMs ms for the operation to finish. nMs |
| 49596 | + ** may be set to INFINITE. |
| 49597 | + */ |
| 49598 | + if( !ret && GetLastError()==ERROR_IO_PENDING ){ |
| 49599 | + DWORD nDelay = (nMs==0 ? INFINITE : nMs); |
| 49600 | + DWORD res = osWaitForSingleObject(ovlp.hEvent, nDelay); |
| 49601 | + if( res==WAIT_OBJECT_0 ){ |
| 49602 | + ret = TRUE; |
| 49603 | + }else if( res==WAIT_TIMEOUT ){ |
| 49604 | + rc = SQLITE_BUSY_TIMEOUT; |
| 49605 | + }else{ |
| 49606 | + /* Some other error has occurred */ |
| 49607 | + rc = SQLITE_IOERR_LOCK; |
| 49608 | + } |
| 49609 | + |
| 49610 | + /* If it is still pending, cancel the LockFileEx() call. */ |
| 49611 | + osCancelIo(hFile); |
| 49612 | + } |
| 49613 | + |
| 49614 | + osCloseHandle(ovlp.hEvent); |
| 49615 | +#endif |
| 49616 | + } |
| 49617 | + |
| 49618 | + if( rc==SQLITE_OK && !ret ){ |
| 49619 | + rc = SQLITE_BUSY; |
| 49620 | + } |
| 49621 | + return rc; |
| 49622 | +} |
| 49412 | 49623 | |
| 49413 | 49624 | /* |
| 49414 | 49625 | ** Unlock a file region. |
| 49415 | 49626 | */ |
| 49416 | 49627 | static BOOL winUnlockFile( |
| | @@ -49438,10 +49649,18 @@ |
| 49438 | 49649 | return osUnlockFile(*phFile, offsetLow, offsetHigh, numBytesLow, |
| 49439 | 49650 | numBytesHigh); |
| 49440 | 49651 | } |
| 49441 | 49652 | #endif |
| 49442 | 49653 | } |
| 49654 | + |
| 49655 | +/* |
| 49656 | +** Remove an nByte lock starting at offset iOff from HANDLE h. |
| 49657 | +*/ |
| 49658 | +static int winHandleUnlock(HANDLE h, int iOff, int nByte){ |
| 49659 | + BOOL ret = winUnlockFile(&h, iOff, 0, nByte, 0); |
| 49660 | + return (ret ? SQLITE_OK : SQLITE_IOERR_UNLOCK); |
| 49661 | +} |
| 49443 | 49662 | |
| 49444 | 49663 | /***************************************************************************** |
| 49445 | 49664 | ** The next group of routines implement the I/O methods specified |
| 49446 | 49665 | ** by the sqlite3_io_methods object. |
| 49447 | 49666 | ******************************************************************************/ |
| | @@ -49452,69 +49671,73 @@ |
| 49452 | 49671 | #ifndef INVALID_SET_FILE_POINTER |
| 49453 | 49672 | # define INVALID_SET_FILE_POINTER ((DWORD)-1) |
| 49454 | 49673 | #endif |
| 49455 | 49674 | |
| 49456 | 49675 | /* |
| 49457 | | -** Move the current position of the file handle passed as the first |
| 49458 | | -** argument to offset iOffset within the file. If successful, return 0. |
| 49459 | | -** Otherwise, set pFile->lastErrno and return non-zero. |
| 49676 | +** Seek the file handle h to offset nByte of the file. |
| 49677 | +** |
| 49678 | +** If successful, return SQLITE_OK. Or, if an error occurs, return an SQLite |
| 49679 | +** error code. |
| 49460 | 49680 | */ |
| 49461 | | -static int winSeekFile(winFile *pFile, sqlite3_int64 iOffset){ |
| 49681 | +static int winHandleSeek(HANDLE h, sqlite3_int64 iOffset){ |
| 49682 | + int rc = SQLITE_OK; /* Return value */ |
| 49683 | + |
| 49462 | 49684 | #if !SQLITE_OS_WINRT |
| 49463 | 49685 | LONG upperBits; /* Most sig. 32 bits of new offset */ |
| 49464 | 49686 | LONG lowerBits; /* Least sig. 32 bits of new offset */ |
| 49465 | 49687 | DWORD dwRet; /* Value returned by SetFilePointer() */ |
| 49466 | | - DWORD lastErrno; /* Value returned by GetLastError() */ |
| 49467 | | - |
| 49468 | | - OSTRACE(("SEEK file=%p, offset=%lld\n", pFile->h, iOffset)); |
| 49469 | 49688 | |
| 49470 | 49689 | upperBits = (LONG)((iOffset>>32) & 0x7fffffff); |
| 49471 | 49690 | lowerBits = (LONG)(iOffset & 0xffffffff); |
| 49691 | + |
| 49692 | + dwRet = osSetFilePointer(h, lowerBits, &upperBits, FILE_BEGIN); |
| 49472 | 49693 | |
| 49473 | 49694 | /* API oddity: If successful, SetFilePointer() returns a dword |
| 49474 | 49695 | ** containing the lower 32-bits of the new file-offset. Or, if it fails, |
| 49475 | 49696 | ** it returns INVALID_SET_FILE_POINTER. However according to MSDN, |
| 49476 | 49697 | ** INVALID_SET_FILE_POINTER may also be a valid new offset. So to determine |
| 49477 | 49698 | ** whether an error has actually occurred, it is also necessary to call |
| 49478 | | - ** GetLastError(). |
| 49479 | | - */ |
| 49480 | | - dwRet = osSetFilePointer(pFile->h, lowerBits, &upperBits, FILE_BEGIN); |
| 49481 | | - |
| 49482 | | - if( (dwRet==INVALID_SET_FILE_POINTER |
| 49483 | | - && ((lastErrno = osGetLastError())!=NO_ERROR)) ){ |
| 49484 | | - pFile->lastErrno = lastErrno; |
| 49485 | | - winLogError(SQLITE_IOERR_SEEK, pFile->lastErrno, |
| 49486 | | - "winSeekFile", pFile->zPath); |
| 49487 | | - OSTRACE(("SEEK file=%p, rc=SQLITE_IOERR_SEEK\n", pFile->h)); |
| 49488 | | - return 1; |
| 49489 | | - } |
| 49490 | | - |
| 49491 | | - OSTRACE(("SEEK file=%p, rc=SQLITE_OK\n", pFile->h)); |
| 49492 | | - return 0; |
| 49493 | | -#else |
| 49494 | | - /* |
| 49495 | | - ** Same as above, except that this implementation works for WinRT. |
| 49496 | | - */ |
| 49497 | | - |
| 49699 | + ** GetLastError(). */ |
| 49700 | + if( dwRet==INVALID_SET_FILE_POINTER ){ |
| 49701 | + DWORD lastErrno = osGetLastError(); |
| 49702 | + if( lastErrno!=NO_ERROR ){ |
| 49703 | + rc = SQLITE_IOERR_SEEK; |
| 49704 | + } |
| 49705 | + } |
| 49706 | +#else |
| 49707 | + /* This implementation works for WinRT. */ |
| 49498 | 49708 | LARGE_INTEGER x; /* The new offset */ |
| 49499 | 49709 | BOOL bRet; /* Value returned by SetFilePointerEx() */ |
| 49500 | 49710 | |
| 49501 | 49711 | x.QuadPart = iOffset; |
| 49502 | | - bRet = osSetFilePointerEx(pFile->h, x, 0, FILE_BEGIN); |
| 49712 | + bRet = osSetFilePointerEx(h, x, 0, FILE_BEGIN); |
| 49503 | 49713 | |
| 49504 | 49714 | if(!bRet){ |
| 49715 | + rc = SQLITE_IOERR_SEEK; |
| 49716 | + } |
| 49717 | +#endif |
| 49718 | + |
| 49719 | + OSTRACE(("SEEK file=%p, offset=%lld rc=%s\n", h, iOffset, sqlite3ErrName(rc))); |
| 49720 | + return rc; |
| 49721 | +} |
| 49722 | + |
| 49723 | +/* |
| 49724 | +** Move the current position of the file handle passed as the first |
| 49725 | +** argument to offset iOffset within the file. If successful, return 0. |
| 49726 | +** Otherwise, set pFile->lastErrno and return non-zero. |
| 49727 | +*/ |
| 49728 | +static int winSeekFile(winFile *pFile, sqlite3_int64 iOffset){ |
| 49729 | + int rc; |
| 49730 | + |
| 49731 | + rc = winHandleSeek(pFile->h, iOffset); |
| 49732 | + if( rc!=SQLITE_OK ){ |
| 49505 | 49733 | pFile->lastErrno = osGetLastError(); |
| 49506 | | - winLogError(SQLITE_IOERR_SEEK, pFile->lastErrno, |
| 49507 | | - "winSeekFile", pFile->zPath); |
| 49508 | | - OSTRACE(("SEEK file=%p, rc=SQLITE_IOERR_SEEK\n", pFile->h)); |
| 49509 | | - return 1; |
| 49510 | | - } |
| 49511 | | - |
| 49512 | | - OSTRACE(("SEEK file=%p, rc=SQLITE_OK\n", pFile->h)); |
| 49513 | | - return 0; |
| 49514 | | -#endif |
| 49515 | | -} |
| 49734 | + winLogError(rc, pFile->lastErrno, "winSeekFile", pFile->zPath); |
| 49735 | + } |
| 49736 | + return rc; |
| 49737 | +} |
| 49738 | + |
| 49516 | 49739 | |
| 49517 | 49740 | #if SQLITE_MAX_MMAP_SIZE>0 |
| 49518 | 49741 | /* Forward references to VFS helper methods used for memory mapped files */ |
| 49519 | 49742 | static int winMapfile(winFile*, sqlite3_int64); |
| 49520 | 49743 | static int winUnmapfile(winFile*); |
| | @@ -49770,10 +49993,64 @@ |
| 49770 | 49993 | } |
| 49771 | 49994 | OSTRACE(("WRITE pid=%lu, pFile=%p, file=%p, rc=SQLITE_OK\n", |
| 49772 | 49995 | osGetCurrentProcessId(), pFile, pFile->h)); |
| 49773 | 49996 | return SQLITE_OK; |
| 49774 | 49997 | } |
| 49998 | + |
| 49999 | +/* |
| 50000 | +** Truncate the file opened by handle h to nByte bytes in size. |
| 50001 | +*/ |
| 50002 | +static int winHandleTruncate(HANDLE h, sqlite3_int64 nByte){ |
| 50003 | + int rc = SQLITE_OK; /* Return code */ |
| 50004 | + rc = winHandleSeek(h, nByte); |
| 50005 | + if( rc==SQLITE_OK ){ |
| 50006 | + if( 0==osSetEndOfFile(h) ){ |
| 50007 | + rc = SQLITE_IOERR_TRUNCATE; |
| 50008 | + } |
| 50009 | + } |
| 50010 | + return rc; |
| 50011 | +} |
| 50012 | + |
| 50013 | +/* |
| 50014 | +** Determine the size in bytes of the file opened by the handle passed as |
| 50015 | +** the first argument. |
| 50016 | +*/ |
| 50017 | +static int winHandleSize(HANDLE h, sqlite3_int64 *pnByte){ |
| 50018 | + int rc = SQLITE_OK; |
| 50019 | + |
| 50020 | +#if SQLITE_OS_WINRT |
| 50021 | + FILE_STANDARD_INFO info; |
| 50022 | + BOOL b; |
| 50023 | + b = osGetFileInformationByHandleEx(h, FileStandardInfo, &info, sizeof(info)); |
| 50024 | + if( b ){ |
| 50025 | + *pnByte = info.EndOfFile.QuadPart; |
| 50026 | + }else{ |
| 50027 | + rc = SQLITE_IOERR_FSTAT; |
| 50028 | + } |
| 50029 | +#else |
| 50030 | + DWORD upperBits = 0; |
| 50031 | + DWORD lowerBits = 0; |
| 50032 | + |
| 50033 | + assert( pnByte ); |
| 50034 | + lowerBits = osGetFileSize(h, &upperBits); |
| 50035 | + *pnByte = (((sqlite3_int64)upperBits)<<32) + lowerBits; |
| 50036 | + if( lowerBits==INVALID_FILE_SIZE && osGetLastError()!=NO_ERROR ){ |
| 50037 | + rc = SQLITE_IOERR_FSTAT; |
| 50038 | + } |
| 50039 | +#endif |
| 50040 | + |
| 50041 | + return rc; |
| 50042 | +} |
| 50043 | + |
| 50044 | +/* |
| 50045 | +** Close the handle passed as the only argument. |
| 50046 | +*/ |
| 50047 | +static void winHandleClose(HANDLE h){ |
| 50048 | + if( h!=INVALID_HANDLE_VALUE ){ |
| 50049 | + osCloseHandle(h); |
| 50050 | + } |
| 50051 | +} |
| 49775 | 50052 | |
| 49776 | 50053 | /* |
| 49777 | 50054 | ** Truncate an open file to a specified size |
| 49778 | 50055 | */ |
| 49779 | 50056 | static int winTruncate(sqlite3_file *id, sqlite3_int64 nByte){ |
| | @@ -50026,31 +50303,32 @@ |
| 50026 | 50303 | /* |
| 50027 | 50304 | ** Acquire a reader lock. |
| 50028 | 50305 | ** Different API routines are called depending on whether or not this |
| 50029 | 50306 | ** is Win9x or WinNT. |
| 50030 | 50307 | */ |
| 50031 | | -static int winGetReadLock(winFile *pFile){ |
| 50308 | +static int winGetReadLock(winFile *pFile, int bBlock){ |
| 50032 | 50309 | int res; |
| 50310 | + DWORD mask = ~(bBlock ? LOCKFILE_FAIL_IMMEDIATELY : 0); |
| 50033 | 50311 | OSTRACE(("READ-LOCK file=%p, lock=%d\n", pFile->h, pFile->locktype)); |
| 50034 | 50312 | if( osIsNT() ){ |
| 50035 | 50313 | #if SQLITE_OS_WINCE |
| 50036 | 50314 | /* |
| 50037 | 50315 | ** NOTE: Windows CE is handled differently here due its lack of the Win32 |
| 50038 | 50316 | ** API LockFileEx. |
| 50039 | 50317 | */ |
| 50040 | 50318 | res = winceLockFile(&pFile->h, SHARED_FIRST, 0, 1, 0); |
| 50041 | 50319 | #else |
| 50042 | | - res = winLockFile(&pFile->h, SQLITE_LOCKFILEEX_FLAGS, SHARED_FIRST, 0, |
| 50320 | + res = winLockFile(&pFile->h, SQLITE_LOCKFILEEX_FLAGS&mask, SHARED_FIRST, 0, |
| 50043 | 50321 | SHARED_SIZE, 0); |
| 50044 | 50322 | #endif |
| 50045 | 50323 | } |
| 50046 | 50324 | #ifdef SQLITE_WIN32_HAS_ANSI |
| 50047 | 50325 | else{ |
| 50048 | 50326 | int lk; |
| 50049 | 50327 | sqlite3_randomness(sizeof(lk), &lk); |
| 50050 | 50328 | pFile->sharedLockByte = (short)((lk & 0x7fffffff)%(SHARED_SIZE - 1)); |
| 50051 | | - res = winLockFile(&pFile->h, SQLITE_LOCKFILE_FLAGS, |
| 50329 | + res = winLockFile(&pFile->h, SQLITE_LOCKFILE_FLAGS&mask, |
| 50052 | 50330 | SHARED_FIRST+pFile->sharedLockByte, 0, 1, 0); |
| 50053 | 50331 | } |
| 50054 | 50332 | #endif |
| 50055 | 50333 | if( res == 0 ){ |
| 50056 | 50334 | pFile->lastErrno = osGetLastError(); |
| | @@ -50180,11 +50458,11 @@ |
| 50180 | 50458 | |
| 50181 | 50459 | /* Acquire a shared lock |
| 50182 | 50460 | */ |
| 50183 | 50461 | if( locktype==SHARED_LOCK && res ){ |
| 50184 | 50462 | assert( pFile->locktype==NO_LOCK ); |
| 50185 | | - res = winGetReadLock(pFile); |
| 50463 | + res = winGetReadLock(pFile, pFile->bBlockOnConnect); |
| 50186 | 50464 | if( res ){ |
| 50187 | 50465 | newLocktype = SHARED_LOCK; |
| 50188 | 50466 | }else{ |
| 50189 | 50467 | lastErrno = osGetLastError(); |
| 50190 | 50468 | } |
| | @@ -50218,11 +50496,11 @@ |
| 50218 | 50496 | SHARED_SIZE, 0); |
| 50219 | 50497 | if( res ){ |
| 50220 | 50498 | newLocktype = EXCLUSIVE_LOCK; |
| 50221 | 50499 | }else{ |
| 50222 | 50500 | lastErrno = osGetLastError(); |
| 50223 | | - winGetReadLock(pFile); |
| 50501 | + winGetReadLock(pFile, 0); |
| 50224 | 50502 | } |
| 50225 | 50503 | } |
| 50226 | 50504 | |
| 50227 | 50505 | /* If we are holding a PENDING lock that ought to be released, then |
| 50228 | 50506 | ** release it now. |
| | @@ -50508,10 +50786,32 @@ |
| 50508 | 50786 | } |
| 50509 | 50787 | OSTRACE(("FCNTL file=%p, rc=%s\n", pFile->h, sqlite3ErrName(rc))); |
| 50510 | 50788 | return rc; |
| 50511 | 50789 | } |
| 50512 | 50790 | #endif |
| 50791 | + |
| 50792 | +#ifdef SQLITE_ENABLE_SETLK_TIMEOUT |
| 50793 | + case SQLITE_FCNTL_LOCK_TIMEOUT: { |
| 50794 | + int iOld = pFile->iBusyTimeout; |
| 50795 | + int iNew = *(int*)pArg; |
| 50796 | +#if SQLITE_ENABLE_SETLK_TIMEOUT==1 |
| 50797 | + pFile->iBusyTimeout = (iNew < 0) ? INFINITE : (DWORD)iNew; |
| 50798 | +#elif SQLITE_ENABLE_SETLK_TIMEOUT==2 |
| 50799 | + pFile->iBusyTimeout = (DWORD)(!!iNew); |
| 50800 | +#else |
| 50801 | +# error "SQLITE_ENABLE_SETLK_TIMEOUT must be set to 1 or 2" |
| 50802 | +#endif |
| 50803 | + *(int*)pArg = iOld; |
| 50804 | + return SQLITE_OK; |
| 50805 | + } |
| 50806 | + case SQLITE_FCNTL_BLOCK_ON_CONNECT: { |
| 50807 | + int iNew = *(int*)pArg; |
| 50808 | + pFile->bBlockOnConnect = iNew; |
| 50809 | + return SQLITE_OK; |
| 50810 | + } |
| 50811 | +#endif /* SQLITE_ENABLE_SETLK_TIMEOUT */ |
| 50812 | + |
| 50513 | 50813 | } |
| 50514 | 50814 | OSTRACE(("FCNTL file=%p, rc=SQLITE_NOTFOUND\n", pFile->h)); |
| 50515 | 50815 | return SQLITE_NOTFOUND; |
| 50516 | 50816 | } |
| 50517 | 50817 | |
| | @@ -50588,36 +50888,39 @@ |
| 50588 | 50888 | ** nRef |
| 50589 | 50889 | ** pNext |
| 50590 | 50890 | ** |
| 50591 | 50891 | ** The following fields are read-only after the object is created: |
| 50592 | 50892 | ** |
| 50593 | | -** fid |
| 50594 | 50893 | ** zFilename |
| 50595 | 50894 | ** |
| 50596 | 50895 | ** Either winShmNode.mutex must be held or winShmNode.nRef==0 and |
| 50597 | 50896 | ** winShmMutexHeld() is true when reading or writing any other field |
| 50598 | 50897 | ** in this structure. |
| 50599 | 50898 | ** |
| 50899 | +** File-handle hSharedShm is used to (a) take the DMS lock, (b) truncate |
| 50900 | +** the *-shm file if the DMS-locking protocol demands it, and (c) map |
| 50901 | +** regions of the *-shm file into memory using MapViewOfFile() or |
| 50902 | +** similar. Other locks are taken by individual clients using the |
| 50903 | +** winShm.hShm handles. |
| 50600 | 50904 | */ |
| 50601 | 50905 | struct winShmNode { |
| 50602 | 50906 | sqlite3_mutex *mutex; /* Mutex to access this object */ |
| 50603 | 50907 | char *zFilename; /* Name of the file */ |
| 50604 | | - winFile hFile; /* File handle from winOpen */ |
| 50908 | + HANDLE hSharedShm; /* File handle open on zFilename */ |
| 50605 | 50909 | |
| 50910 | + int isUnlocked; /* DMS lock has not yet been obtained */ |
| 50911 | + int isReadonly; /* True if read-only */ |
| 50606 | 50912 | int szRegion; /* Size of shared-memory regions */ |
| 50607 | 50913 | int nRegion; /* Size of array apRegion */ |
| 50608 | | - u8 isReadonly; /* True if read-only */ |
| 50609 | | - u8 isUnlocked; /* True if no DMS lock held */ |
| 50610 | 50914 | |
| 50611 | 50915 | struct ShmRegion { |
| 50612 | 50916 | HANDLE hMap; /* File handle from CreateFileMapping */ |
| 50613 | 50917 | void *pMap; |
| 50614 | 50918 | } *aRegion; |
| 50615 | 50919 | DWORD lastErrno; /* The Windows errno from the last I/O error */ |
| 50616 | 50920 | |
| 50617 | 50921 | int nRef; /* Number of winShm objects pointing to this */ |
| 50618 | | - winShm *pFirst; /* All winShm objects pointing to this */ |
| 50619 | 50922 | winShmNode *pNext; /* Next in list of all winShmNode objects */ |
| 50620 | 50923 | #if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE) |
| 50621 | 50924 | u8 nextShmId; /* Next available winShm.id value */ |
| 50622 | 50925 | #endif |
| 50623 | 50926 | }; |
| | @@ -50629,27 +50932,19 @@ |
| 50629 | 50932 | */ |
| 50630 | 50933 | static winShmNode *winShmNodeList = 0; |
| 50631 | 50934 | |
| 50632 | 50935 | /* |
| 50633 | 50936 | ** Structure used internally by this VFS to record the state of an |
| 50634 | | -** open shared memory connection. |
| 50635 | | -** |
| 50636 | | -** The following fields are initialized when this object is created and |
| 50637 | | -** are read-only thereafter: |
| 50638 | | -** |
| 50639 | | -** winShm.pShmNode |
| 50640 | | -** winShm.id |
| 50641 | | -** |
| 50642 | | -** All other fields are read/write. The winShm.pShmNode->mutex must be held |
| 50643 | | -** while accessing any read/write fields. |
| 50937 | +** open shared memory connection. There is one such structure for each |
| 50938 | +** winFile open on a wal mode database. |
| 50644 | 50939 | */ |
| 50645 | 50940 | struct winShm { |
| 50646 | 50941 | winShmNode *pShmNode; /* The underlying winShmNode object */ |
| 50647 | | - winShm *pNext; /* Next winShm with the same winShmNode */ |
| 50648 | | - u8 hasMutex; /* True if holding the winShmNode mutex */ |
| 50649 | 50942 | u16 sharedMask; /* Mask of shared locks held */ |
| 50650 | 50943 | u16 exclMask; /* Mask of exclusive locks held */ |
| 50944 | + HANDLE hShm; /* File-handle on *-shm file. For locking. */ |
| 50945 | + int bReadonly; /* True if hShm is opened read-only */ |
| 50651 | 50946 | #if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE) |
| 50652 | 50947 | u8 id; /* Id of this connection with its winShmNode */ |
| 50653 | 50948 | #endif |
| 50654 | 50949 | }; |
| 50655 | 50950 | |
| | @@ -50657,54 +50952,10 @@ |
| 50657 | 50952 | ** Constants used for locking |
| 50658 | 50953 | */ |
| 50659 | 50954 | #define WIN_SHM_BASE ((22+SQLITE_SHM_NLOCK)*4) /* first lock byte */ |
| 50660 | 50955 | #define WIN_SHM_DMS (WIN_SHM_BASE+SQLITE_SHM_NLOCK) /* deadman switch */ |
| 50661 | 50956 | |
| 50662 | | -/* |
| 50663 | | -** Apply advisory locks for all n bytes beginning at ofst. |
| 50664 | | -*/ |
| 50665 | | -#define WINSHM_UNLCK 1 |
| 50666 | | -#define WINSHM_RDLCK 2 |
| 50667 | | -#define WINSHM_WRLCK 3 |
| 50668 | | -static int winShmSystemLock( |
| 50669 | | - winShmNode *pFile, /* Apply locks to this open shared-memory segment */ |
| 50670 | | - int lockType, /* WINSHM_UNLCK, WINSHM_RDLCK, or WINSHM_WRLCK */ |
| 50671 | | - int ofst, /* Offset to first byte to be locked/unlocked */ |
| 50672 | | - int nByte /* Number of bytes to lock or unlock */ |
| 50673 | | -){ |
| 50674 | | - int rc = 0; /* Result code form Lock/UnlockFileEx() */ |
| 50675 | | - |
| 50676 | | - /* Access to the winShmNode object is serialized by the caller */ |
| 50677 | | - assert( pFile->nRef==0 || sqlite3_mutex_held(pFile->mutex) ); |
| 50678 | | - |
| 50679 | | - OSTRACE(("SHM-LOCK file=%p, lock=%d, offset=%d, size=%d\n", |
| 50680 | | - pFile->hFile.h, lockType, ofst, nByte)); |
| 50681 | | - |
| 50682 | | - /* Release/Acquire the system-level lock */ |
| 50683 | | - if( lockType==WINSHM_UNLCK ){ |
| 50684 | | - rc = winUnlockFile(&pFile->hFile.h, ofst, 0, nByte, 0); |
| 50685 | | - }else{ |
| 50686 | | - /* Initialize the locking parameters */ |
| 50687 | | - DWORD dwFlags = LOCKFILE_FAIL_IMMEDIATELY; |
| 50688 | | - if( lockType == WINSHM_WRLCK ) dwFlags |= LOCKFILE_EXCLUSIVE_LOCK; |
| 50689 | | - rc = winLockFile(&pFile->hFile.h, dwFlags, ofst, 0, nByte, 0); |
| 50690 | | - } |
| 50691 | | - |
| 50692 | | - if( rc!= 0 ){ |
| 50693 | | - rc = SQLITE_OK; |
| 50694 | | - }else{ |
| 50695 | | - pFile->lastErrno = osGetLastError(); |
| 50696 | | - rc = SQLITE_BUSY; |
| 50697 | | - } |
| 50698 | | - |
| 50699 | | - OSTRACE(("SHM-LOCK file=%p, func=%s, errno=%lu, rc=%s\n", |
| 50700 | | - pFile->hFile.h, (lockType == WINSHM_UNLCK) ? "winUnlockFile" : |
| 50701 | | - "winLockFile", pFile->lastErrno, sqlite3ErrName(rc))); |
| 50702 | | - |
| 50703 | | - return rc; |
| 50704 | | -} |
| 50705 | | - |
| 50706 | 50957 | /* Forward references to VFS methods */ |
| 50707 | 50958 | static int winOpen(sqlite3_vfs*,const char*,sqlite3_file*,int,int*); |
| 50708 | 50959 | static int winDelete(sqlite3_vfs *,const char*,int); |
| 50709 | 50960 | |
| 50710 | 50961 | /* |
| | @@ -50732,15 +50983,11 @@ |
| 50732 | 50983 | bRc = osCloseHandle(p->aRegion[i].hMap); |
| 50733 | 50984 | OSTRACE(("SHM-PURGE-CLOSE pid=%lu, region=%d, rc=%s\n", |
| 50734 | 50985 | osGetCurrentProcessId(), i, bRc ? "ok" : "failed")); |
| 50735 | 50986 | UNUSED_VARIABLE_VALUE(bRc); |
| 50736 | 50987 | } |
| 50737 | | - if( p->hFile.h!=NULL && p->hFile.h!=INVALID_HANDLE_VALUE ){ |
| 50738 | | - SimulateIOErrorBenign(1); |
| 50739 | | - winClose((sqlite3_file *)&p->hFile); |
| 50740 | | - SimulateIOErrorBenign(0); |
| 50741 | | - } |
| 50988 | + winHandleClose(p->hSharedShm); |
| 50742 | 50989 | if( deleteFlag ){ |
| 50743 | 50990 | SimulateIOErrorBenign(1); |
| 50744 | 50991 | sqlite3BeginBenignMalloc(); |
| 50745 | 50992 | winDelete(pVfs, p->zFilename, 0); |
| 50746 | 50993 | sqlite3EndBenignMalloc(); |
| | @@ -50754,46 +51001,166 @@ |
| 50754 | 51001 | } |
| 50755 | 51002 | } |
| 50756 | 51003 | } |
| 50757 | 51004 | |
| 50758 | 51005 | /* |
| 50759 | | -** The DMS lock has not yet been taken on shm file pShmNode. Attempt to |
| 50760 | | -** take it now. Return SQLITE_OK if successful, or an SQLite error |
| 50761 | | -** code otherwise. |
| 50762 | | -** |
| 50763 | | -** If the DMS cannot be locked because this is a readonly_shm=1 |
| 50764 | | -** connection and no other process already holds a lock, return |
| 50765 | | -** SQLITE_READONLY_CANTINIT and set pShmNode->isUnlocked=1. |
| 51006 | +** The DMS lock has not yet been taken on the shm file associated with |
| 51007 | +** pShmNode. Take the lock. Truncate the *-shm file if required. |
| 51008 | +** Return SQLITE_OK if successful, or an SQLite error code otherwise. |
| 50766 | 51009 | */ |
| 50767 | | -static int winLockSharedMemory(winShmNode *pShmNode){ |
| 50768 | | - int rc = winShmSystemLock(pShmNode, WINSHM_WRLCK, WIN_SHM_DMS, 1); |
| 51010 | +static int winLockSharedMemory(winShmNode *pShmNode, DWORD nMs){ |
| 51011 | + HANDLE h = pShmNode->hSharedShm; |
| 51012 | + int rc = SQLITE_OK; |
| 50769 | 51013 | |
| 51014 | + assert( sqlite3_mutex_held(pShmNode->mutex) ); |
| 51015 | + rc = winHandleLockTimeout(h, WIN_SHM_DMS, 1, 1, 0); |
| 50770 | 51016 | if( rc==SQLITE_OK ){ |
| 51017 | + /* We have an EXCLUSIVE lock on the DMS byte. This means that this |
| 51018 | + ** is the first process to open the file. Truncate it to zero bytes |
| 51019 | + ** in this case. */ |
| 50771 | 51020 | if( pShmNode->isReadonly ){ |
| 50772 | | - pShmNode->isUnlocked = 1; |
| 50773 | | - winShmSystemLock(pShmNode, WINSHM_UNLCK, WIN_SHM_DMS, 1); |
| 50774 | | - return SQLITE_READONLY_CANTINIT; |
| 50775 | | - }else if( winTruncate((sqlite3_file*)&pShmNode->hFile, 0) ){ |
| 50776 | | - winShmSystemLock(pShmNode, WINSHM_UNLCK, WIN_SHM_DMS, 1); |
| 50777 | | - return winLogError(SQLITE_IOERR_SHMOPEN, osGetLastError(), |
| 50778 | | - "winLockSharedMemory", pShmNode->zFilename); |
| 50779 | | - } |
| 50780 | | - } |
| 50781 | | - |
| 50782 | | - if( rc==SQLITE_OK ){ |
| 50783 | | - winShmSystemLock(pShmNode, WINSHM_UNLCK, WIN_SHM_DMS, 1); |
| 50784 | | - } |
| 50785 | | - |
| 50786 | | - return winShmSystemLock(pShmNode, WINSHM_RDLCK, WIN_SHM_DMS, 1); |
| 50787 | | -} |
| 50788 | | - |
| 50789 | | -/* |
| 50790 | | -** Open the shared-memory area associated with database file pDbFd. |
| 50791 | | -** |
| 50792 | | -** When opening a new shared-memory file, if no other instances of that |
| 50793 | | -** file are currently open, in this process or in other processes, then |
| 50794 | | -** the file must be truncated to zero length or have its header cleared. |
| 51021 | + rc = SQLITE_READONLY_CANTINIT; |
| 51022 | + }else{ |
| 51023 | + rc = winHandleTruncate(h, 0); |
| 51024 | + } |
| 51025 | + |
| 51026 | + /* Release the EXCLUSIVE lock acquired above. */ |
| 51027 | + winUnlockFile(&h, WIN_SHM_DMS, 0, 1, 0); |
| 51028 | + }else if( (rc & 0xFF)==SQLITE_BUSY ){ |
| 51029 | + rc = SQLITE_OK; |
| 51030 | + } |
| 51031 | + |
| 51032 | + if( rc==SQLITE_OK ){ |
| 51033 | + /* Take a SHARED lock on the DMS byte. */ |
| 51034 | + rc = winHandleLockTimeout(h, WIN_SHM_DMS, 1, 0, nMs); |
| 51035 | + if( rc==SQLITE_OK ){ |
| 51036 | + pShmNode->isUnlocked = 0; |
| 51037 | + } |
| 51038 | + } |
| 51039 | + |
| 51040 | + return rc; |
| 51041 | +} |
| 51042 | + |
| 51043 | + |
| 51044 | +/* |
| 51045 | +** Convert a UTF-8 filename into whatever form the underlying |
| 51046 | +** operating system wants filenames in. Space to hold the result |
| 51047 | +** is obtained from malloc and must be freed by the calling |
| 51048 | +** function. |
| 51049 | +*/ |
| 51050 | +static void *winConvertFromUtf8Filename(const char *zFilename){ |
| 51051 | + void *zConverted = 0; |
| 51052 | + if( osIsNT() ){ |
| 51053 | + zConverted = winUtf8ToUnicode(zFilename); |
| 51054 | + } |
| 51055 | +#ifdef SQLITE_WIN32_HAS_ANSI |
| 51056 | + else{ |
| 51057 | + zConverted = winUtf8ToMbcs(zFilename, osAreFileApisANSI()); |
| 51058 | + } |
| 51059 | +#endif |
| 51060 | + /* caller will handle out of memory */ |
| 51061 | + return zConverted; |
| 51062 | +} |
| 51063 | + |
| 51064 | +/* |
| 51065 | +** This function is used to open a handle on a *-shm file. |
| 51066 | +** |
| 51067 | +** If SQLITE_ENABLE_SETLK_TIMEOUT is defined at build time, then the file |
| 51068 | +** is opened with FILE_FLAG_OVERLAPPED specified. If not, it is not. |
| 51069 | +*/ |
| 51070 | +static int winHandleOpen( |
| 51071 | + const char *zUtf8, /* File to open */ |
| 51072 | + int *pbReadonly, /* IN/OUT: True for readonly handle */ |
| 51073 | + HANDLE *ph /* OUT: New HANDLE for file */ |
| 51074 | +){ |
| 51075 | + int rc = SQLITE_OK; |
| 51076 | + void *zConverted = 0; |
| 51077 | + int bReadonly = *pbReadonly; |
| 51078 | + HANDLE h = INVALID_HANDLE_VALUE; |
| 51079 | + |
| 51080 | +#ifdef SQLITE_ENABLE_SETLK_TIMEOUT |
| 51081 | + const DWORD flag_overlapped = FILE_FLAG_OVERLAPPED; |
| 51082 | +#else |
| 51083 | + const DWORD flag_overlapped = 0; |
| 51084 | +#endif |
| 51085 | + |
| 51086 | + /* Convert the filename to the system encoding. */ |
| 51087 | + zConverted = winConvertFromUtf8Filename(zUtf8); |
| 51088 | + if( zConverted==0 ){ |
| 51089 | + OSTRACE(("OPEN name=%s, rc=SQLITE_IOERR_NOMEM", zUtf8)); |
| 51090 | + rc = SQLITE_IOERR_NOMEM_BKPT; |
| 51091 | + goto winopenfile_out; |
| 51092 | + } |
| 51093 | + |
| 51094 | + /* Ensure the file we are trying to open is not actually a directory. */ |
| 51095 | + if( winIsDir(zConverted) ){ |
| 51096 | + OSTRACE(("OPEN name=%s, rc=SQLITE_CANTOPEN_ISDIR", zUtf8)); |
| 51097 | + rc = SQLITE_CANTOPEN_ISDIR; |
| 51098 | + goto winopenfile_out; |
| 51099 | + } |
| 51100 | + |
| 51101 | + /* TODO: platforms. |
| 51102 | + ** TODO: retry-on-ioerr. |
| 51103 | + */ |
| 51104 | + if( osIsNT() ){ |
| 51105 | +#if SQLITE_OS_WINRT |
| 51106 | + CREATEFILE2_EXTENDED_PARAMETERS extendedParameters; |
| 51107 | + memset(&extendedParameters, 0, sizeof(extendedParameters)); |
| 51108 | + extendedParameters.dwSize = sizeof(extendedParameters); |
| 51109 | + extendedParameters.dwFileAttributes = FILE_ATTRIBUTE_NORMAL; |
| 51110 | + extendedParameters.dwFileFlags = flag_overlapped; |
| 51111 | + extendedParameters.dwSecurityQosFlags = SECURITY_ANONYMOUS; |
| 51112 | + h = osCreateFile2((LPCWSTR)zConverted, |
| 51113 | + (GENERIC_READ | (bReadonly ? 0 : GENERIC_WRITE)),/* dwDesiredAccess */ |
| 51114 | + FILE_SHARE_READ | FILE_SHARE_WRITE, /* dwShareMode */ |
| 51115 | + OPEN_ALWAYS, /* dwCreationDisposition */ |
| 51116 | + &extendedParameters |
| 51117 | + ); |
| 51118 | +#else |
| 51119 | + h = osCreateFileW((LPCWSTR)zConverted, /* lpFileName */ |
| 51120 | + (GENERIC_READ | (bReadonly ? 0 : GENERIC_WRITE)), /* dwDesiredAccess */ |
| 51121 | + FILE_SHARE_READ | FILE_SHARE_WRITE, /* dwShareMode */ |
| 51122 | + NULL, /* lpSecurityAttributes */ |
| 51123 | + OPEN_ALWAYS, /* dwCreationDisposition */ |
| 51124 | + FILE_ATTRIBUTE_NORMAL|flag_overlapped, |
| 51125 | + NULL |
| 51126 | + ); |
| 51127 | +#endif |
| 51128 | + }else{ |
| 51129 | + /* Due to pre-processor directives earlier in this file, |
| 51130 | + ** SQLITE_WIN32_HAS_ANSI is always defined if osIsNT() is false. */ |
| 51131 | +#ifdef SQLITE_WIN32_HAS_ANSI |
| 51132 | + h = osCreateFileA((LPCSTR)zConverted, |
| 51133 | + (GENERIC_READ | (bReadonly ? 0 : GENERIC_WRITE)), /* dwDesiredAccess */ |
| 51134 | + FILE_SHARE_READ | FILE_SHARE_WRITE, /* dwShareMode */ |
| 51135 | + NULL, /* lpSecurityAttributes */ |
| 51136 | + OPEN_ALWAYS, /* dwCreationDisposition */ |
| 51137 | + FILE_ATTRIBUTE_NORMAL|flag_overlapped, |
| 51138 | + NULL |
| 51139 | + ); |
| 51140 | +#endif |
| 51141 | + } |
| 51142 | + |
| 51143 | + if( h==INVALID_HANDLE_VALUE ){ |
| 51144 | + if( bReadonly==0 ){ |
| 51145 | + bReadonly = 1; |
| 51146 | + rc = winHandleOpen(zUtf8, &bReadonly, &h); |
| 51147 | + }else{ |
| 51148 | + rc = SQLITE_CANTOPEN_BKPT; |
| 51149 | + } |
| 51150 | + } |
| 51151 | + |
| 51152 | + winopenfile_out: |
| 51153 | + sqlite3_free(zConverted); |
| 51154 | + *pbReadonly = bReadonly; |
| 51155 | + *ph = h; |
| 51156 | + return rc; |
| 51157 | +} |
| 51158 | + |
| 51159 | + |
| 51160 | +/* |
| 51161 | +** Open the shared-memory area associated with database file pDbFd. |
| 50795 | 51162 | */ |
| 50796 | 51163 | static int winOpenSharedMemory(winFile *pDbFd){ |
| 50797 | 51164 | struct winShm *p; /* The connection to be opened */ |
| 50798 | 51165 | winShmNode *pShmNode = 0; /* The underlying mmapped file */ |
| 50799 | 51166 | int rc = SQLITE_OK; /* Result code */ |
| | @@ -50801,102 +51168,87 @@ |
| 50801 | 51168 | int nName; /* Size of zName in bytes */ |
| 50802 | 51169 | |
| 50803 | 51170 | assert( pDbFd->pShm==0 ); /* Not previously opened */ |
| 50804 | 51171 | |
| 50805 | 51172 | /* Allocate space for the new sqlite3_shm object. Also speculatively |
| 50806 | | - ** allocate space for a new winShmNode and filename. |
| 50807 | | - */ |
| 51173 | + ** allocate space for a new winShmNode and filename. */ |
| 50808 | 51174 | p = sqlite3MallocZero( sizeof(*p) ); |
| 50809 | 51175 | if( p==0 ) return SQLITE_IOERR_NOMEM_BKPT; |
| 50810 | 51176 | nName = sqlite3Strlen30(pDbFd->zPath); |
| 50811 | 51177 | pNew = sqlite3MallocZero( sizeof(*pShmNode) + nName + 17 ); |
| 50812 | 51178 | if( pNew==0 ){ |
| 50813 | 51179 | sqlite3_free(p); |
| 50814 | 51180 | return SQLITE_IOERR_NOMEM_BKPT; |
| 50815 | 51181 | } |
| 50816 | 51182 | pNew->zFilename = (char*)&pNew[1]; |
| 51183 | + pNew->hSharedShm = INVALID_HANDLE_VALUE; |
| 51184 | + pNew->isUnlocked = 1; |
| 50817 | 51185 | sqlite3_snprintf(nName+15, pNew->zFilename, "%s-shm", pDbFd->zPath); |
| 50818 | 51186 | sqlite3FileSuffix3(pDbFd->zPath, pNew->zFilename); |
| 51187 | + |
| 51188 | + /* Open a file-handle on the *-shm file for this connection. This file-handle |
| 51189 | + ** is only used for locking. The mapping of the *-shm file is created using |
| 51190 | + ** the shared file handle in winShmNode.hSharedShm. */ |
| 51191 | + p->bReadonly = sqlite3_uri_boolean(pDbFd->zPath, "readonly_shm", 0); |
| 51192 | + rc = winHandleOpen(pNew->zFilename, &p->bReadonly, &p->hShm); |
| 50819 | 51193 | |
| 50820 | 51194 | /* Look to see if there is an existing winShmNode that can be used. |
| 50821 | | - ** If no matching winShmNode currently exists, create a new one. |
| 50822 | | - */ |
| 51195 | + ** If no matching winShmNode currently exists, then create a new one. */ |
| 50823 | 51196 | winShmEnterMutex(); |
| 50824 | 51197 | for(pShmNode = winShmNodeList; pShmNode; pShmNode=pShmNode->pNext){ |
| 50825 | 51198 | /* TBD need to come up with better match here. Perhaps |
| 50826 | | - ** use FILE_ID_BOTH_DIR_INFO Structure. |
| 50827 | | - */ |
| 51199 | + ** use FILE_ID_BOTH_DIR_INFO Structure. */ |
| 50828 | 51200 | if( sqlite3StrICmp(pShmNode->zFilename, pNew->zFilename)==0 ) break; |
| 50829 | 51201 | } |
| 50830 | | - if( pShmNode ){ |
| 50831 | | - sqlite3_free(pNew); |
| 50832 | | - }else{ |
| 50833 | | - int inFlags = SQLITE_OPEN_WAL; |
| 50834 | | - int outFlags = 0; |
| 50835 | | - |
| 51202 | + if( pShmNode==0 ){ |
| 50836 | 51203 | pShmNode = pNew; |
| 50837 | | - pNew = 0; |
| 50838 | | - ((winFile*)(&pShmNode->hFile))->h = INVALID_HANDLE_VALUE; |
| 50839 | | - pShmNode->pNext = winShmNodeList; |
| 50840 | | - winShmNodeList = pShmNode; |
| 50841 | 51204 | |
| 51205 | + /* Allocate a mutex for this winShmNode object, if one is required. */ |
| 50842 | 51206 | if( sqlite3GlobalConfig.bCoreMutex ){ |
| 50843 | 51207 | pShmNode->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST); |
| 50844 | | - if( pShmNode->mutex==0 ){ |
| 50845 | | - rc = SQLITE_IOERR_NOMEM_BKPT; |
| 50846 | | - goto shm_open_err; |
| 50847 | | - } |
| 50848 | | - } |
| 50849 | | - |
| 50850 | | - if( 0==sqlite3_uri_boolean(pDbFd->zPath, "readonly_shm", 0) ){ |
| 50851 | | - inFlags |= SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE; |
| 50852 | | - }else{ |
| 50853 | | - inFlags |= SQLITE_OPEN_READONLY; |
| 50854 | | - } |
| 50855 | | - rc = winOpen(pDbFd->pVfs, pShmNode->zFilename, |
| 50856 | | - (sqlite3_file*)&pShmNode->hFile, |
| 50857 | | - inFlags, &outFlags); |
| 50858 | | - if( rc!=SQLITE_OK ){ |
| 50859 | | - rc = winLogError(rc, osGetLastError(), "winOpenShm", |
| 50860 | | - pShmNode->zFilename); |
| 50861 | | - goto shm_open_err; |
| 50862 | | - } |
| 50863 | | - if( outFlags==SQLITE_OPEN_READONLY ) pShmNode->isReadonly = 1; |
| 50864 | | - |
| 50865 | | - rc = winLockSharedMemory(pShmNode); |
| 50866 | | - if( rc!=SQLITE_OK && rc!=SQLITE_READONLY_CANTINIT ) goto shm_open_err; |
| 50867 | | - } |
| 50868 | | - |
| 50869 | | - /* Make the new connection a child of the winShmNode */ |
| 50870 | | - p->pShmNode = pShmNode; |
| 51208 | + if( pShmNode->mutex==0 ) rc = SQLITE_IOERR_NOMEM_BKPT; |
| 51209 | + } |
| 51210 | + |
| 51211 | + /* Open a file-handle to use for mappings, and for the DMS lock. */ |
| 51212 | + if( rc==SQLITE_OK ){ |
| 51213 | + HANDLE h = INVALID_HANDLE_VALUE; |
| 51214 | + pShmNode->isReadonly = p->bReadonly; |
| 51215 | + rc = winHandleOpen(pNew->zFilename, &pShmNode->isReadonly, &h); |
| 51216 | + pShmNode->hSharedShm = h; |
| 51217 | + } |
| 51218 | + |
| 51219 | + /* If successful, link the new winShmNode into the global list. If an |
| 51220 | + ** error occurred, free the object. */ |
| 51221 | + if( rc==SQLITE_OK ){ |
| 51222 | + pShmNode->pNext = winShmNodeList; |
| 51223 | + winShmNodeList = pShmNode; |
| 51224 | + pNew = 0; |
| 51225 | + }else{ |
| 51226 | + sqlite3_mutex_free(pShmNode->mutex); |
| 51227 | + if( pShmNode->hSharedShm!=INVALID_HANDLE_VALUE ){ |
| 51228 | + osCloseHandle(pShmNode->hSharedShm); |
| 51229 | + } |
| 51230 | + } |
| 51231 | + } |
| 51232 | + |
| 51233 | + /* If no error has occurred, link the winShm object to the winShmNode and |
| 51234 | + ** the winShm to pDbFd. */ |
| 51235 | + if( rc==SQLITE_OK ){ |
| 51236 | + p->pShmNode = pShmNode; |
| 51237 | + pShmNode->nRef++; |
| 50871 | 51238 | #if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE) |
| 50872 | | - p->id = pShmNode->nextShmId++; |
| 50873 | | -#endif |
| 50874 | | - pShmNode->nRef++; |
| 50875 | | - pDbFd->pShm = p; |
| 50876 | | - winShmLeaveMutex(); |
| 50877 | | - |
| 50878 | | - /* The reference count on pShmNode has already been incremented under |
| 50879 | | - ** the cover of the winShmEnterMutex() mutex and the pointer from the |
| 50880 | | - ** new (struct winShm) object to the pShmNode has been set. All that is |
| 50881 | | - ** left to do is to link the new object into the linked list starting |
| 50882 | | - ** at pShmNode->pFirst. This must be done while holding the pShmNode->mutex |
| 50883 | | - ** mutex. |
| 50884 | | - */ |
| 50885 | | - sqlite3_mutex_enter(pShmNode->mutex); |
| 50886 | | - p->pNext = pShmNode->pFirst; |
| 50887 | | - pShmNode->pFirst = p; |
| 50888 | | - sqlite3_mutex_leave(pShmNode->mutex); |
| 50889 | | - return rc; |
| 50890 | | - |
| 50891 | | - /* Jump here on any error */ |
| 50892 | | -shm_open_err: |
| 50893 | | - winShmSystemLock(pShmNode, WINSHM_UNLCK, WIN_SHM_DMS, 1); |
| 50894 | | - winShmPurge(pDbFd->pVfs, 0); /* This call frees pShmNode if required */ |
| 50895 | | - sqlite3_free(p); |
| 50896 | | - sqlite3_free(pNew); |
| 50897 | | - winShmLeaveMutex(); |
| 51239 | + p->id = pShmNode->nextShmId++; |
| 51240 | +#endif |
| 51241 | + pDbFd->pShm = p; |
| 51242 | + }else if( p ){ |
| 51243 | + winHandleClose(p->hShm); |
| 51244 | + sqlite3_free(p); |
| 51245 | + } |
| 51246 | + |
| 51247 | + assert( rc!=SQLITE_OK || pShmNode->isUnlocked==0 || pShmNode->nRegion==0 ); |
| 51248 | + winShmLeaveMutex(); |
| 51249 | + sqlite3_free(pNew); |
| 50898 | 51250 | return rc; |
| 50899 | 51251 | } |
| 50900 | 51252 | |
| 50901 | 51253 | /* |
| 50902 | 51254 | ** Close a connection to shared-memory. Delete the underlying |
| | @@ -50907,38 +51259,33 @@ |
| 50907 | 51259 | int deleteFlag /* Delete after closing if true */ |
| 50908 | 51260 | ){ |
| 50909 | 51261 | winFile *pDbFd; /* Database holding shared-memory */ |
| 50910 | 51262 | winShm *p; /* The connection to be closed */ |
| 50911 | 51263 | winShmNode *pShmNode; /* The underlying shared-memory file */ |
| 50912 | | - winShm **pp; /* For looping over sibling connections */ |
| 50913 | 51264 | |
| 50914 | 51265 | pDbFd = (winFile*)fd; |
| 50915 | 51266 | p = pDbFd->pShm; |
| 50916 | 51267 | if( p==0 ) return SQLITE_OK; |
| 51268 | + if( p->hShm!=INVALID_HANDLE_VALUE ){ |
| 51269 | + osCloseHandle(p->hShm); |
| 51270 | + } |
| 51271 | + |
| 50917 | 51272 | pShmNode = p->pShmNode; |
| 50918 | | - |
| 50919 | | - /* Remove connection p from the set of connections associated |
| 50920 | | - ** with pShmNode */ |
| 50921 | | - sqlite3_mutex_enter(pShmNode->mutex); |
| 50922 | | - for(pp=&pShmNode->pFirst; (*pp)!=p; pp = &(*pp)->pNext){} |
| 50923 | | - *pp = p->pNext; |
| 50924 | | - |
| 50925 | | - /* Free the connection p */ |
| 50926 | | - sqlite3_free(p); |
| 50927 | | - pDbFd->pShm = 0; |
| 50928 | | - sqlite3_mutex_leave(pShmNode->mutex); |
| 51273 | + winShmEnterMutex(); |
| 50929 | 51274 | |
| 50930 | 51275 | /* If pShmNode->nRef has reached 0, then close the underlying |
| 50931 | | - ** shared-memory file, too */ |
| 50932 | | - winShmEnterMutex(); |
| 51276 | + ** shared-memory file, too. */ |
| 50933 | 51277 | assert( pShmNode->nRef>0 ); |
| 50934 | 51278 | pShmNode->nRef--; |
| 50935 | 51279 | if( pShmNode->nRef==0 ){ |
| 50936 | 51280 | winShmPurge(pDbFd->pVfs, deleteFlag); |
| 50937 | 51281 | } |
| 50938 | 51282 | winShmLeaveMutex(); |
| 50939 | 51283 | |
| 51284 | + /* Free the connection p */ |
| 51285 | + sqlite3_free(p); |
| 51286 | + pDbFd->pShm = 0; |
| 50940 | 51287 | return SQLITE_OK; |
| 50941 | 51288 | } |
| 50942 | 51289 | |
| 50943 | 51290 | /* |
| 50944 | 51291 | ** Change the lock state for a shared-memory segment. |
| | @@ -50949,14 +51296,13 @@ |
| 50949 | 51296 | int n, /* Number of locks to acquire or release */ |
| 50950 | 51297 | int flags /* What to do with the lock */ |
| 50951 | 51298 | ){ |
| 50952 | 51299 | winFile *pDbFd = (winFile*)fd; /* Connection holding shared memory */ |
| 50953 | 51300 | winShm *p = pDbFd->pShm; /* The shared memory being locked */ |
| 50954 | | - winShm *pX; /* For looping over all siblings */ |
| 50955 | 51301 | winShmNode *pShmNode; |
| 50956 | 51302 | int rc = SQLITE_OK; /* Result code */ |
| 50957 | | - u16 mask; /* Mask of locks to take or release */ |
| 51303 | + u16 mask = (u16)((1U<<(ofst+n)) - (1U<<ofst)); /* Mask of locks to [un]take */ |
| 50958 | 51304 | |
| 50959 | 51305 | if( p==0 ) return SQLITE_IOERR_SHMLOCK; |
| 50960 | 51306 | pShmNode = p->pShmNode; |
| 50961 | 51307 | if( NEVER(pShmNode==0) ) return SQLITE_IOERR_SHMLOCK; |
| 50962 | 51308 | |
| | @@ -50966,89 +51312,86 @@ |
| 50966 | 51312 | || flags==(SQLITE_SHM_LOCK | SQLITE_SHM_EXCLUSIVE) |
| 50967 | 51313 | || flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED) |
| 50968 | 51314 | || flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE) ); |
| 50969 | 51315 | assert( n==1 || (flags & SQLITE_SHM_EXCLUSIVE)!=0 ); |
| 50970 | 51316 | |
| 50971 | | - mask = (u16)((1U<<(ofst+n)) - (1U<<ofst)); |
| 50972 | | - assert( n>1 || mask==(1<<ofst) ); |
| 50973 | | - sqlite3_mutex_enter(pShmNode->mutex); |
| 50974 | | - if( flags & SQLITE_SHM_UNLOCK ){ |
| 50975 | | - u16 allMask = 0; /* Mask of locks held by siblings */ |
| 50976 | | - |
| 50977 | | - /* See if any siblings hold this same lock */ |
| 50978 | | - for(pX=pShmNode->pFirst; pX; pX=pX->pNext){ |
| 50979 | | - if( pX==p ) continue; |
| 50980 | | - assert( (pX->exclMask & (p->exclMask|p->sharedMask))==0 ); |
| 50981 | | - allMask |= pX->sharedMask; |
| 50982 | | - } |
| 50983 | | - |
| 50984 | | - /* Unlock the system-level locks */ |
| 50985 | | - if( (mask & allMask)==0 ){ |
| 50986 | | - rc = winShmSystemLock(pShmNode, WINSHM_UNLCK, ofst+WIN_SHM_BASE, n); |
| 50987 | | - }else{ |
| 50988 | | - rc = SQLITE_OK; |
| 50989 | | - } |
| 50990 | | - |
| 50991 | | - /* Undo the local locks */ |
| 50992 | | - if( rc==SQLITE_OK ){ |
| 50993 | | - p->exclMask &= ~mask; |
| 50994 | | - p->sharedMask &= ~mask; |
| 50995 | | - } |
| 50996 | | - }else if( flags & SQLITE_SHM_SHARED ){ |
| 50997 | | - u16 allShared = 0; /* Union of locks held by connections other than "p" */ |
| 50998 | | - |
| 50999 | | - /* Find out which shared locks are already held by sibling connections. |
| 51000 | | - ** If any sibling already holds an exclusive lock, go ahead and return |
| 51001 | | - ** SQLITE_BUSY. |
| 51002 | | - */ |
| 51003 | | - for(pX=pShmNode->pFirst; pX; pX=pX->pNext){ |
| 51004 | | - if( (pX->exclMask & mask)!=0 ){ |
| 51005 | | - rc = SQLITE_BUSY; |
| 51006 | | - break; |
| 51007 | | - } |
| 51008 | | - allShared |= pX->sharedMask; |
| 51009 | | - } |
| 51010 | | - |
| 51011 | | - /* Get shared locks at the system level, if necessary */ |
| 51012 | | - if( rc==SQLITE_OK ){ |
| 51013 | | - if( (allShared & mask)==0 ){ |
| 51014 | | - rc = winShmSystemLock(pShmNode, WINSHM_RDLCK, ofst+WIN_SHM_BASE, n); |
| 51015 | | - }else{ |
| 51016 | | - rc = SQLITE_OK; |
| 51017 | | - } |
| 51018 | | - } |
| 51019 | | - |
| 51020 | | - /* Get the local shared locks */ |
| 51021 | | - if( rc==SQLITE_OK ){ |
| 51022 | | - p->sharedMask |= mask; |
| 51023 | | - } |
| 51024 | | - }else{ |
| 51025 | | - /* Make sure no sibling connections hold locks that will block this |
| 51026 | | - ** lock. If any do, return SQLITE_BUSY right away. |
| 51027 | | - */ |
| 51028 | | - for(pX=pShmNode->pFirst; pX; pX=pX->pNext){ |
| 51029 | | - if( (pX->exclMask & mask)!=0 || (pX->sharedMask & mask)!=0 ){ |
| 51030 | | - rc = SQLITE_BUSY; |
| 51031 | | - break; |
| 51032 | | - } |
| 51033 | | - } |
| 51034 | | - |
| 51035 | | - /* Get the exclusive locks at the system level. Then if successful |
| 51036 | | - ** also mark the local connection as being locked. |
| 51037 | | - */ |
| 51038 | | - if( rc==SQLITE_OK ){ |
| 51039 | | - rc = winShmSystemLock(pShmNode, WINSHM_WRLCK, ofst+WIN_SHM_BASE, n); |
| 51040 | | - if( rc==SQLITE_OK ){ |
| 51041 | | - assert( (p->sharedMask & mask)==0 ); |
| 51042 | | - p->exclMask |= mask; |
| 51043 | | - } |
| 51044 | | - } |
| 51045 | | - } |
| 51046 | | - sqlite3_mutex_leave(pShmNode->mutex); |
| 51047 | | - OSTRACE(("SHM-LOCK pid=%lu, id=%d, sharedMask=%03x, exclMask=%03x, rc=%s\n", |
| 51048 | | - osGetCurrentProcessId(), p->id, p->sharedMask, p->exclMask, |
| 51049 | | - sqlite3ErrName(rc))); |
| 51317 | + /* Check that, if this to be a blocking lock, no locks that occur later |
| 51318 | + ** in the following list than the lock being obtained are already held: |
| 51319 | + ** |
| 51320 | + ** 1. Checkpointer lock (ofst==1). |
| 51321 | + ** 2. Write lock (ofst==0). |
| 51322 | + ** 3. Read locks (ofst>=3 && ofst<SQLITE_SHM_NLOCK). |
| 51323 | + ** |
| 51324 | + ** In other words, if this is a blocking lock, none of the locks that |
| 51325 | + ** occur later in the above list than the lock being obtained may be |
| 51326 | + ** held. |
| 51327 | + ** |
| 51328 | + ** It is not permitted to block on the RECOVER lock. |
| 51329 | + */ |
| 51330 | +#ifdef SQLITE_ENABLE_SETLK_TIMEOUT |
| 51331 | + { |
| 51332 | + u16 lockMask = (p->exclMask|p->sharedMask); |
| 51333 | + assert( (flags & SQLITE_SHM_UNLOCK) || pDbFd->iBusyTimeout==0 || ( |
| 51334 | + (ofst!=2) /* not RECOVER */ |
| 51335 | + && (ofst!=1 || lockMask==0 || lockMask==2) |
| 51336 | + && (ofst!=0 || lockMask<3) |
| 51337 | + && (ofst<3 || lockMask<(1<<ofst)) |
| 51338 | + )); |
| 51339 | + } |
| 51340 | +#endif |
| 51341 | + |
| 51342 | + /* Check if there is any work to do. There are three cases: |
| 51343 | + ** |
| 51344 | + ** a) An unlock operation where there are locks to unlock, |
| 51345 | + ** b) An shared lock where the requested lock is not already held |
| 51346 | + ** c) An exclusive lock where the requested lock is not already held |
| 51347 | + ** |
| 51348 | + ** The SQLite core never requests an exclusive lock that it already holds. |
| 51349 | + ** This is assert()ed immediately below. */ |
| 51350 | + assert( flags!=(SQLITE_SHM_EXCLUSIVE|SQLITE_SHM_LOCK) |
| 51351 | + || 0==(p->exclMask & mask) |
| 51352 | + ); |
| 51353 | + if( ((flags & SQLITE_SHM_UNLOCK) && ((p->exclMask|p->sharedMask) & mask)) |
| 51354 | + || (flags==(SQLITE_SHM_SHARED|SQLITE_SHM_LOCK) && 0==(p->sharedMask & mask)) |
| 51355 | + || (flags==(SQLITE_SHM_EXCLUSIVE|SQLITE_SHM_LOCK)) |
| 51356 | + ){ |
| 51357 | + |
| 51358 | + if( flags & SQLITE_SHM_UNLOCK ){ |
| 51359 | + /* Case (a) - unlock. */ |
| 51360 | + |
| 51361 | + assert( (p->exclMask & p->sharedMask)==0 ); |
| 51362 | + assert( !(flags & SQLITE_SHM_EXCLUSIVE) || (p->exclMask & mask)==mask ); |
| 51363 | + assert( !(flags & SQLITE_SHM_SHARED) || (p->sharedMask & mask)==mask ); |
| 51364 | + |
| 51365 | + rc = winHandleUnlock(p->hShm, ofst+WIN_SHM_BASE, n); |
| 51366 | + |
| 51367 | + /* If successful, also clear the bits in sharedMask/exclMask */ |
| 51368 | + if( rc==SQLITE_OK ){ |
| 51369 | + p->exclMask = (p->exclMask & ~mask); |
| 51370 | + p->sharedMask = (p->sharedMask & ~mask); |
| 51371 | + } |
| 51372 | + }else{ |
| 51373 | + int bExcl = ((flags & SQLITE_SHM_EXCLUSIVE) ? 1 : 0); |
| 51374 | + DWORD nMs = winFileBusyTimeout(pDbFd); |
| 51375 | + rc = winHandleLockTimeout(p->hShm, ofst+WIN_SHM_BASE, n, bExcl, nMs); |
| 51376 | + if( rc==SQLITE_OK ){ |
| 51377 | + if( bExcl ){ |
| 51378 | + p->exclMask = (p->exclMask | mask); |
| 51379 | + }else{ |
| 51380 | + p->sharedMask = (p->sharedMask | mask); |
| 51381 | + } |
| 51382 | + } |
| 51383 | + } |
| 51384 | + } |
| 51385 | + |
| 51386 | + OSTRACE(( |
| 51387 | + "SHM-LOCK(%d,%d,%d) pid=%lu, id=%d, sharedMask=%03x, exclMask=%03x," |
| 51388 | + " rc=%s\n", |
| 51389 | + ofst, n, flags, |
| 51390 | + osGetCurrentProcessId(), p->id, p->sharedMask, p->exclMask, |
| 51391 | + sqlite3ErrName(rc)) |
| 51392 | + ); |
| 51050 | 51393 | return rc; |
| 51051 | 51394 | } |
| 51052 | 51395 | |
| 51053 | 51396 | /* |
| 51054 | 51397 | ** Implement a memory barrier or memory fence on shared memory. |
| | @@ -51106,17 +51449,19 @@ |
| 51106 | 51449 | } |
| 51107 | 51450 | pShmNode = pShm->pShmNode; |
| 51108 | 51451 | |
| 51109 | 51452 | sqlite3_mutex_enter(pShmNode->mutex); |
| 51110 | 51453 | if( pShmNode->isUnlocked ){ |
| 51111 | | - rc = winLockSharedMemory(pShmNode); |
| 51454 | + /* Take the DMS lock. */ |
| 51455 | + assert( pShmNode->nRegion==0 ); |
| 51456 | + rc = winLockSharedMemory(pShmNode, winFileBusyTimeout(pDbFd)); |
| 51112 | 51457 | if( rc!=SQLITE_OK ) goto shmpage_out; |
| 51113 | | - pShmNode->isUnlocked = 0; |
| 51114 | 51458 | } |
| 51459 | + |
| 51115 | 51460 | assert( szRegion==pShmNode->szRegion || pShmNode->nRegion==0 ); |
| 51116 | | - |
| 51117 | 51461 | if( pShmNode->nRegion<=iRegion ){ |
| 51462 | + HANDLE hShared = pShmNode->hSharedShm; |
| 51118 | 51463 | struct ShmRegion *apNew; /* New aRegion[] array */ |
| 51119 | 51464 | int nByte = (iRegion+1)*szRegion; /* Minimum required file size */ |
| 51120 | 51465 | sqlite3_int64 sz; /* Current size of wal-index file */ |
| 51121 | 51466 | |
| 51122 | 51467 | pShmNode->szRegion = szRegion; |
| | @@ -51123,35 +51468,32 @@ |
| 51123 | 51468 | |
| 51124 | 51469 | /* The requested region is not mapped into this processes address space. |
| 51125 | 51470 | ** Check to see if it has been allocated (i.e. if the wal-index file is |
| 51126 | 51471 | ** large enough to contain the requested region). |
| 51127 | 51472 | */ |
| 51128 | | - rc = winFileSize((sqlite3_file *)&pShmNode->hFile, &sz); |
| 51473 | + rc = winHandleSize(hShared, &sz); |
| 51129 | 51474 | if( rc!=SQLITE_OK ){ |
| 51130 | | - rc = winLogError(SQLITE_IOERR_SHMSIZE, osGetLastError(), |
| 51131 | | - "winShmMap1", pDbFd->zPath); |
| 51475 | + rc = winLogError(rc, osGetLastError(), "winShmMap1", pDbFd->zPath); |
| 51132 | 51476 | goto shmpage_out; |
| 51133 | 51477 | } |
| 51134 | 51478 | |
| 51135 | 51479 | if( sz<nByte ){ |
| 51136 | 51480 | /* The requested memory region does not exist. If isWrite is set to |
| 51137 | 51481 | ** zero, exit early. *pp will be set to NULL and SQLITE_OK returned. |
| 51138 | 51482 | ** |
| 51139 | 51483 | ** Alternatively, if isWrite is non-zero, use ftruncate() to allocate |
| 51140 | | - ** the requested memory region. |
| 51141 | | - */ |
| 51484 | + ** the requested memory region. */ |
| 51142 | 51485 | if( !isWrite ) goto shmpage_out; |
| 51143 | | - rc = winTruncate((sqlite3_file *)&pShmNode->hFile, nByte); |
| 51486 | + rc = winHandleTruncate(hShared, nByte); |
| 51144 | 51487 | if( rc!=SQLITE_OK ){ |
| 51145 | | - rc = winLogError(SQLITE_IOERR_SHMSIZE, osGetLastError(), |
| 51146 | | - "winShmMap2", pDbFd->zPath); |
| 51488 | + rc = winLogError(rc, osGetLastError(), "winShmMap2", pDbFd->zPath); |
| 51147 | 51489 | goto shmpage_out; |
| 51148 | 51490 | } |
| 51149 | 51491 | } |
| 51150 | 51492 | |
| 51151 | 51493 | /* Map the requested memory region into this processes address space. */ |
| 51152 | | - apNew = (struct ShmRegion *)sqlite3_realloc64( |
| 51494 | + apNew = (struct ShmRegion*)sqlite3_realloc64( |
| 51153 | 51495 | pShmNode->aRegion, (iRegion+1)*sizeof(apNew[0]) |
| 51154 | 51496 | ); |
| 51155 | 51497 | if( !apNew ){ |
| 51156 | 51498 | rc = SQLITE_IOERR_NOMEM_BKPT; |
| 51157 | 51499 | goto shmpage_out; |
| | @@ -51166,22 +51508,17 @@ |
| 51166 | 51508 | while( pShmNode->nRegion<=iRegion ){ |
| 51167 | 51509 | HANDLE hMap = NULL; /* file-mapping handle */ |
| 51168 | 51510 | void *pMap = 0; /* Mapped memory region */ |
| 51169 | 51511 | |
| 51170 | 51512 | #if SQLITE_OS_WINRT |
| 51171 | | - hMap = osCreateFileMappingFromApp(pShmNode->hFile.h, |
| 51172 | | - NULL, protect, nByte, NULL |
| 51173 | | - ); |
| 51513 | + hMap = osCreateFileMappingFromApp(hShared, NULL, protect, nByte, NULL); |
| 51174 | 51514 | #elif defined(SQLITE_WIN32_HAS_WIDE) |
| 51175 | | - hMap = osCreateFileMappingW(pShmNode->hFile.h, |
| 51176 | | - NULL, protect, 0, nByte, NULL |
| 51177 | | - ); |
| 51515 | + hMap = osCreateFileMappingW(hShared, NULL, protect, 0, nByte, NULL); |
| 51178 | 51516 | #elif defined(SQLITE_WIN32_HAS_ANSI) && SQLITE_WIN32_CREATEFILEMAPPINGA |
| 51179 | | - hMap = osCreateFileMappingA(pShmNode->hFile.h, |
| 51180 | | - NULL, protect, 0, nByte, NULL |
| 51181 | | - ); |
| 51517 | + hMap = osCreateFileMappingA(hShared, NULL, protect, 0, nByte, NULL); |
| 51182 | 51518 | #endif |
| 51519 | + |
| 51183 | 51520 | OSTRACE(("SHM-MAP-CREATE pid=%lu, region=%d, size=%d, rc=%s\n", |
| 51184 | 51521 | osGetCurrentProcessId(), pShmNode->nRegion, nByte, |
| 51185 | 51522 | hMap ? "ok" : "failed")); |
| 51186 | 51523 | if( hMap ){ |
| 51187 | 51524 | int iOffset = pShmNode->nRegion*szRegion; |
| | @@ -51220,11 +51557,13 @@ |
| 51220 | 51557 | char *p = (char *)pShmNode->aRegion[iRegion].pMap; |
| 51221 | 51558 | *pp = (void *)&p[iOffsetShift]; |
| 51222 | 51559 | }else{ |
| 51223 | 51560 | *pp = 0; |
| 51224 | 51561 | } |
| 51225 | | - if( pShmNode->isReadonly && rc==SQLITE_OK ) rc = SQLITE_READONLY; |
| 51562 | + if( pShmNode->isReadonly && rc==SQLITE_OK ){ |
| 51563 | + rc = SQLITE_READONLY; |
| 51564 | + } |
| 51226 | 51565 | sqlite3_mutex_leave(pShmNode->mutex); |
| 51227 | 51566 | return rc; |
| 51228 | 51567 | } |
| 51229 | 51568 | |
| 51230 | 51569 | #else |
| | @@ -51561,30 +51900,10 @@ |
| 51561 | 51900 | /* caller will handle out of memory */ |
| 51562 | 51901 | return zConverted; |
| 51563 | 51902 | } |
| 51564 | 51903 | #endif |
| 51565 | 51904 | |
| 51566 | | -/* |
| 51567 | | -** Convert a UTF-8 filename into whatever form the underlying |
| 51568 | | -** operating system wants filenames in. Space to hold the result |
| 51569 | | -** is obtained from malloc and must be freed by the calling |
| 51570 | | -** function. |
| 51571 | | -*/ |
| 51572 | | -static void *winConvertFromUtf8Filename(const char *zFilename){ |
| 51573 | | - void *zConverted = 0; |
| 51574 | | - if( osIsNT() ){ |
| 51575 | | - zConverted = winUtf8ToUnicode(zFilename); |
| 51576 | | - } |
| 51577 | | -#ifdef SQLITE_WIN32_HAS_ANSI |
| 51578 | | - else{ |
| 51579 | | - zConverted = winUtf8ToMbcs(zFilename, osAreFileApisANSI()); |
| 51580 | | - } |
| 51581 | | -#endif |
| 51582 | | - /* caller will handle out of memory */ |
| 51583 | | - return zConverted; |
| 51584 | | -} |
| 51585 | | - |
| 51586 | 51905 | /* |
| 51587 | 51906 | ** This function returns non-zero if the specified UTF-8 string buffer |
| 51588 | 51907 | ** ends with a directory separator character or one was successfully |
| 51589 | 51908 | ** added to it. |
| 51590 | 51909 | */ |
| | @@ -53035,11 +53354,11 @@ |
| 53035 | 53354 | }; |
| 53036 | 53355 | #endif |
| 53037 | 53356 | |
| 53038 | 53357 | /* Double-check that the aSyscall[] array has been constructed |
| 53039 | 53358 | ** correctly. See ticket [bb3a86e890c8e96ab] */ |
| 53040 | | - assert( ArraySize(aSyscall)==80 ); |
| 53359 | + assert( ArraySize(aSyscall)==82 ); |
| 53041 | 53360 | |
| 53042 | 53361 | /* get memory map allocation granularity */ |
| 53043 | 53362 | memset(&winSysInfo, 0, sizeof(SYSTEM_INFO)); |
| 53044 | 53363 | #if SQLITE_OS_WINRT |
| 53045 | 53364 | osGetNativeSystemInfo(&winSysInfo); |
| | @@ -65633,10 +65952,15 @@ |
| 65633 | 65952 | ) |
| 65634 | 65953 | |
| 65635 | 65954 | /* |
| 65636 | 65955 | ** An open write-ahead log file is represented by an instance of the |
| 65637 | 65956 | ** following object. |
| 65957 | +** |
| 65958 | +** writeLock: |
| 65959 | +** This is usually set to 1 whenever the WRITER lock is held. However, |
| 65960 | +** if it is set to 2, then the WRITER lock is held but must be released |
| 65961 | +** by walHandleException() if a SEH exception is thrown. |
| 65638 | 65962 | */ |
| 65639 | 65963 | struct Wal { |
| 65640 | 65964 | sqlite3_vfs *pVfs; /* The VFS used to create pDbFd */ |
| 65641 | 65965 | sqlite3_file *pDbFd; /* File handle for the database file */ |
| 65642 | 65966 | sqlite3_file *pWalFd; /* File handle for WAL file */ |
| | @@ -67158,11 +67482,11 @@ |
| 67158 | 67482 | ** or 0 otherwise. |
| 67159 | 67483 | */ |
| 67160 | 67484 | static int walEnableBlocking(Wal *pWal){ |
| 67161 | 67485 | int res = 0; |
| 67162 | 67486 | if( pWal->db ){ |
| 67163 | | - int tmout = pWal->db->busyTimeout; |
| 67487 | + int tmout = pWal->db->setlkTimeout; |
| 67164 | 67488 | if( tmout ){ |
| 67165 | 67489 | res = walEnableBlockingMs(pWal, tmout); |
| 67166 | 67490 | } |
| 67167 | 67491 | } |
| 67168 | 67492 | return res; |
| | @@ -67544,11 +67868,13 @@ |
| 67544 | 67868 | static int walHandleException(Wal *pWal){ |
| 67545 | 67869 | if( pWal->exclusiveMode==0 ){ |
| 67546 | 67870 | static const int S = 1; |
| 67547 | 67871 | static const int E = (1<<SQLITE_SHM_NLOCK); |
| 67548 | 67872 | int ii; |
| 67549 | | - u32 mUnlock = pWal->lockMask & ~( |
| 67873 | + u32 mUnlock; |
| 67874 | + if( pWal->writeLock==2 ) pWal->writeLock = 0; |
| 67875 | + mUnlock = pWal->lockMask & ~( |
| 67550 | 67876 | (pWal->readLock<0 ? 0 : (S << WAL_READ_LOCK(pWal->readLock))) |
| 67551 | 67877 | | (pWal->writeLock ? (E << WAL_WRITE_LOCK) : 0) |
| 67552 | 67878 | | (pWal->ckptLock ? (E << WAL_CKPT_LOCK) : 0) |
| 67553 | 67879 | ); |
| 67554 | 67880 | for(ii=0; ii<SQLITE_SHM_NLOCK; ii++){ |
| | @@ -67816,11 +68142,16 @@ |
| 67816 | 68142 | }else{ |
| 67817 | 68143 | int bWriteLock = pWal->writeLock; |
| 67818 | 68144 | if( bWriteLock |
| 67819 | 68145 | || SQLITE_OK==(rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1)) |
| 67820 | 68146 | ){ |
| 67821 | | - pWal->writeLock = 1; |
| 68147 | + /* If the write-lock was just obtained, set writeLock to 2 instead of |
| 68148 | + ** the usual 1. This causes walIndexPage() to behave as if the |
| 68149 | + ** write-lock were held (so that it allocates new pages as required), |
| 68150 | + ** and walHandleException() to unlock the write-lock if a SEH exception |
| 68151 | + ** is thrown. */ |
| 68152 | + if( !bWriteLock ) pWal->writeLock = 2; |
| 67822 | 68153 | if( SQLITE_OK==(rc = walIndexPage(pWal, 0, &page0)) ){ |
| 67823 | 68154 | badHdr = walIndexTryHdr(pWal, pChanged); |
| 67824 | 68155 | if( badHdr ){ |
| 67825 | 68156 | /* If the wal-index header is still malformed even while holding |
| 67826 | 68157 | ** a WRITE lock, it can only mean that the header is corrupted and |
| | @@ -68601,12 +68932,15 @@ |
| 68601 | 68932 | /* |
| 68602 | 68933 | ** Finish with a read transaction. All this does is release the |
| 68603 | 68934 | ** read-lock. |
| 68604 | 68935 | */ |
| 68605 | 68936 | SQLITE_PRIVATE void sqlite3WalEndReadTransaction(Wal *pWal){ |
| 68606 | | - sqlite3WalEndWriteTransaction(pWal); |
| 68937 | +#ifndef SQLITE_ENABLE_SETLK_TIMEOUT |
| 68938 | + assert( pWal->writeLock==0 || pWal->readLock<0 ); |
| 68939 | +#endif |
| 68607 | 68940 | if( pWal->readLock>=0 ){ |
| 68941 | + sqlite3WalEndWriteTransaction(pWal); |
| 68608 | 68942 | walUnlockShared(pWal, WAL_READ_LOCK(pWal->readLock)); |
| 68609 | 68943 | pWal->readLock = -1; |
| 68610 | 68944 | } |
| 68611 | 68945 | } |
| 68612 | 68946 | |
| | @@ -68795,11 +69129,11 @@ |
| 68795 | 69129 | #ifdef SQLITE_ENABLE_SETLK_TIMEOUT |
| 68796 | 69130 | /* If the write-lock is already held, then it was obtained before the |
| 68797 | 69131 | ** read-transaction was even opened, making this call a no-op. |
| 68798 | 69132 | ** Return early. */ |
| 68799 | 69133 | if( pWal->writeLock ){ |
| 68800 | | - assert( !memcmp(&pWal->hdr,(void *)walIndexHdr(pWal),sizeof(WalIndexHdr)) ); |
| 69134 | + assert( !memcmp(&pWal->hdr,(void*)pWal->apWiData[0],sizeof(WalIndexHdr)) ); |
| 68801 | 69135 | return SQLITE_OK; |
| 68802 | 69136 | } |
| 68803 | 69137 | #endif |
| 68804 | 69138 | |
| 68805 | 69139 | /* Cannot start a write transaction without first holding a read |
| | @@ -83370,11 +83704,11 @@ |
| 83370 | 83704 | if( (pMem->flags & (MEM_Str|MEM_Term|MEM_Ephem|MEM_Static))!=MEM_Str ){ |
| 83371 | 83705 | /* pMem must be a string, and it cannot be an ephemeral or static string */ |
| 83372 | 83706 | return; |
| 83373 | 83707 | } |
| 83374 | 83708 | if( pMem->enc!=SQLITE_UTF8 ) return; |
| 83375 | | - if( NEVER(pMem->z==0) ) return; |
| 83709 | + assert( pMem->z!=0 ); |
| 83376 | 83710 | if( pMem->flags & MEM_Dyn ){ |
| 83377 | 83711 | if( pMem->xDel==sqlite3_free |
| 83378 | 83712 | && sqlite3_msize(pMem->z) >= (u64)(pMem->n+1) |
| 83379 | 83713 | ){ |
| 83380 | 83714 | pMem->z[pMem->n] = 0; |
| | @@ -85958,12 +86292,12 @@ |
| 85958 | 86292 | ** through all the opcodes and fixes up some details. |
| 85959 | 86293 | ** |
| 85960 | 86294 | ** (1) For each jump instruction with a negative P2 value (a label) |
| 85961 | 86295 | ** resolve the P2 value to an actual address. |
| 85962 | 86296 | ** |
| 85963 | | -** (2) Compute the maximum number of arguments used by any SQL function |
| 85964 | | -** and store that value in *pMaxFuncArgs. |
| 86297 | +** (2) Compute the maximum number of arguments used by the xUpdate/xFilter |
| 86298 | +** methods of any virtual table and store that value in *pMaxVtabArgs. |
| 85965 | 86299 | ** |
| 85966 | 86300 | ** (3) Update the Vdbe.readOnly and Vdbe.bIsReader flags to accurately |
| 85967 | 86301 | ** indicate what the prepared statement actually does. |
| 85968 | 86302 | ** |
| 85969 | 86303 | ** (4) (discontinued) |
| | @@ -85972,12 +86306,12 @@ |
| 85972 | 86306 | ** |
| 85973 | 86307 | ** This routine will only function correctly if the mkopcodeh.tcl generator |
| 85974 | 86308 | ** script numbers the opcodes correctly. Changes to this routine must be |
| 85975 | 86309 | ** coordinated with changes to mkopcodeh.tcl. |
| 85976 | 86310 | */ |
| 85977 | | -static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){ |
| 85978 | | - int nMaxArgs = *pMaxFuncArgs; |
| 86311 | +static void resolveP2Values(Vdbe *p, int *pMaxVtabArgs){ |
| 86312 | + int nMaxVtabArgs = *pMaxVtabArgs; |
| 85979 | 86313 | Op *pOp; |
| 85980 | 86314 | Parse *pParse = p->pParse; |
| 85981 | 86315 | int *aLabel = pParse->aLabel; |
| 85982 | 86316 | |
| 85983 | 86317 | assert( pParse->db->mallocFailed==0 ); /* tag-20230419-1 */ |
| | @@ -86018,19 +86352,23 @@ |
| 86018 | 86352 | assert( pOp->p2>=0 ); |
| 86019 | 86353 | goto resolve_p2_values_loop_exit; |
| 86020 | 86354 | } |
| 86021 | 86355 | #ifndef SQLITE_OMIT_VIRTUALTABLE |
| 86022 | 86356 | case OP_VUpdate: { |
| 86023 | | - if( pOp->p2>nMaxArgs ) nMaxArgs = pOp->p2; |
| 86357 | + if( pOp->p2>nMaxVtabArgs ) nMaxVtabArgs = pOp->p2; |
| 86024 | 86358 | break; |
| 86025 | 86359 | } |
| 86026 | 86360 | case OP_VFilter: { |
| 86027 | 86361 | int n; |
| 86362 | + /* The instruction immediately prior to VFilter will be an |
| 86363 | + ** OP_Integer that sets the "argc" value for the VFilter. See |
| 86364 | + ** the code where OP_VFilter is generated at tag-20250207a. */ |
| 86028 | 86365 | assert( (pOp - p->aOp) >= 3 ); |
| 86029 | 86366 | assert( pOp[-1].opcode==OP_Integer ); |
| 86367 | + assert( pOp[-1].p2==pOp->p3+1 ); |
| 86030 | 86368 | n = pOp[-1].p1; |
| 86031 | | - if( n>nMaxArgs ) nMaxArgs = n; |
| 86369 | + if( n>nMaxVtabArgs ) nMaxVtabArgs = n; |
| 86032 | 86370 | /* Fall through into the default case */ |
| 86033 | 86371 | /* no break */ deliberate_fall_through |
| 86034 | 86372 | } |
| 86035 | 86373 | #endif |
| 86036 | 86374 | default: { |
| | @@ -86067,11 +86405,11 @@ |
| 86067 | 86405 | if( aLabel ){ |
| 86068 | 86406 | sqlite3DbNNFreeNN(p->db, pParse->aLabel); |
| 86069 | 86407 | pParse->aLabel = 0; |
| 86070 | 86408 | } |
| 86071 | 86409 | pParse->nLabel = 0; |
| 86072 | | - *pMaxFuncArgs = nMaxArgs; |
| 86410 | + *pMaxVtabArgs = nMaxVtabArgs; |
| 86073 | 86411 | assert( p->bIsReader!=0 || DbMaskAllZero(p->btreeMask) ); |
| 86074 | 86412 | } |
| 86075 | 86413 | |
| 86076 | 86414 | #ifdef SQLITE_DEBUG |
| 86077 | 86415 | /* |
| | @@ -87745,11 +88083,11 @@ |
| 87745 | 88083 | ){ |
| 87746 | 88084 | sqlite3 *db; /* The database connection */ |
| 87747 | 88085 | int nVar; /* Number of parameters */ |
| 87748 | 88086 | int nMem; /* Number of VM memory registers */ |
| 87749 | 88087 | int nCursor; /* Number of cursors required */ |
| 87750 | | - int nArg; /* Number of arguments in subprograms */ |
| 88088 | + int nArg; /* Max number args to xFilter or xUpdate */ |
| 87751 | 88089 | int n; /* Loop counter */ |
| 87752 | 88090 | struct ReusableSpace x; /* Reusable bulk memory */ |
| 87753 | 88091 | |
| 87754 | 88092 | assert( p!=0 ); |
| 87755 | 88093 | assert( p->nOp>0 ); |
| | @@ -87817,10 +88155,13 @@ |
| 87817 | 88155 | p->aVar = allocSpace(&x, p->aVar, nVar*sizeof(Mem)); |
| 87818 | 88156 | p->apArg = allocSpace(&x, p->apArg, nArg*sizeof(Mem*)); |
| 87819 | 88157 | p->apCsr = allocSpace(&x, p->apCsr, nCursor*sizeof(VdbeCursor*)); |
| 87820 | 88158 | } |
| 87821 | 88159 | } |
| 88160 | +#ifdef SQLITE_DEBUG |
| 88161 | + p->napArg = nArg; |
| 88162 | +#endif |
| 87822 | 88163 | |
| 87823 | 88164 | if( db->mallocFailed ){ |
| 87824 | 88165 | p->nVar = 0; |
| 87825 | 88166 | p->nCursor = 0; |
| 87826 | 88167 | p->nMem = 0; |
| | @@ -101897,10 +102238,11 @@ |
| 101897 | 102238 | nArg = (int)pArgc->u.i; |
| 101898 | 102239 | iQuery = (int)pQuery->u.i; |
| 101899 | 102240 | |
| 101900 | 102241 | /* Invoke the xFilter method */ |
| 101901 | 102242 | apArg = p->apArg; |
| 102243 | + assert( nArg<=p->napArg ); |
| 101902 | 102244 | for(i = 0; i<nArg; i++){ |
| 101903 | 102245 | apArg[i] = &pArgc[i+1]; |
| 101904 | 102246 | } |
| 101905 | 102247 | rc = pModule->xFilter(pVCur, iQuery, pOp->p4.z, nArg, apArg); |
| 101906 | 102248 | sqlite3VtabImportErrmsg(p, pVtab); |
| | @@ -102107,10 +102449,11 @@ |
| 102107 | 102449 | assert( pOp->p4type==P4_VTAB ); |
| 102108 | 102450 | if( ALWAYS(pModule->xUpdate) ){ |
| 102109 | 102451 | u8 vtabOnConflict = db->vtabOnConflict; |
| 102110 | 102452 | apArg = p->apArg; |
| 102111 | 102453 | pX = &aMem[pOp->p3]; |
| 102454 | + assert( nArg<=p->napArg ); |
| 102112 | 102455 | for(i=0; i<nArg; i++){ |
| 102113 | 102456 | assert( memIsValid(pX) ); |
| 102114 | 102457 | memAboutToChange(p, pX); |
| 102115 | 102458 | apArg[i] = pX; |
| 102116 | 102459 | pX++; |
| | @@ -102952,16 +103295,12 @@ |
| 102952 | 103295 | } |
| 102953 | 103296 | pBlob->pTab = pTab; |
| 102954 | 103297 | pBlob->zDb = db->aDb[sqlite3SchemaToIndex(db, pTab->pSchema)].zDbSName; |
| 102955 | 103298 | |
| 102956 | 103299 | /* Now search pTab for the exact column. */ |
| 102957 | | - for(iCol=0; iCol<pTab->nCol; iCol++) { |
| 102958 | | - if( sqlite3StrICmp(pTab->aCol[iCol].zCnName, zColumn)==0 ){ |
| 102959 | | - break; |
| 102960 | | - } |
| 102961 | | - } |
| 102962 | | - if( iCol==pTab->nCol ){ |
| 103300 | + iCol = sqlite3ColumnIndex(pTab, zColumn); |
| 103301 | + if( iCol<0 ){ |
| 102963 | 103302 | sqlite3DbFree(db, zErr); |
| 102964 | 103303 | zErr = sqlite3MPrintf(db, "no such column: \"%s\"", zColumn); |
| 102965 | 103304 | rc = SQLITE_ERROR; |
| 102966 | 103305 | sqlite3BtreeLeaveAll(db); |
| 102967 | 103306 | goto blob_open_out; |
| | @@ -107503,11 +107842,10 @@ |
| 107503 | 107842 | SrcItem *pMatch = 0; /* The matching pSrcList item */ |
| 107504 | 107843 | NameContext *pTopNC = pNC; /* First namecontext in the list */ |
| 107505 | 107844 | Schema *pSchema = 0; /* Schema of the expression */ |
| 107506 | 107845 | int eNewExprOp = TK_COLUMN; /* New value for pExpr->op on success */ |
| 107507 | 107846 | Table *pTab = 0; /* Table holding the row */ |
| 107508 | | - Column *pCol; /* A column of pTab */ |
| 107509 | 107847 | ExprList *pFJMatch = 0; /* Matches for FULL JOIN .. USING */ |
| 107510 | 107848 | const char *zCol = pRight->u.zToken; |
| 107511 | 107849 | |
| 107512 | 107850 | assert( pNC ); /* the name context cannot be NULL. */ |
| 107513 | 107851 | assert( zCol ); /* The Z in X.Y.Z cannot be NULL */ |
| | @@ -107554,11 +107892,10 @@ |
| 107554 | 107892 | ExprList *pEList; |
| 107555 | 107893 | SrcList *pSrcList = pNC->pSrcList; |
| 107556 | 107894 | |
| 107557 | 107895 | if( pSrcList ){ |
| 107558 | 107896 | for(i=0, pItem=pSrcList->a; i<pSrcList->nSrc; i++, pItem++){ |
| 107559 | | - u8 hCol; |
| 107560 | 107897 | pTab = pItem->pSTab; |
| 107561 | 107898 | assert( pTab!=0 && pTab->zName!=0 ); |
| 107562 | 107899 | assert( pTab->nCol>0 || pParse->nErr ); |
| 107563 | 107900 | assert( (int)pItem->fg.isNestedFrom == IsNestedFrom(pItem)); |
| 107564 | 107901 | if( pItem->fg.isNestedFrom ){ |
| | @@ -107642,47 +107979,42 @@ |
| 107642 | 107979 | assert( ExprUseYTab(pExpr) ); |
| 107643 | 107980 | if( IN_RENAME_OBJECT && pItem->zAlias ){ |
| 107644 | 107981 | sqlite3RenameTokenRemap(pParse, 0, (void*)&pExpr->y.pTab); |
| 107645 | 107982 | } |
| 107646 | 107983 | } |
| 107647 | | - hCol = sqlite3StrIHash(zCol); |
| 107648 | | - for(j=0, pCol=pTab->aCol; j<pTab->nCol; j++, pCol++){ |
| 107649 | | - if( pCol->hName==hCol |
| 107650 | | - && sqlite3StrICmp(pCol->zCnName, zCol)==0 |
| 107651 | | - ){ |
| 107652 | | - if( cnt>0 ){ |
| 107653 | | - if( pItem->fg.isUsing==0 |
| 107654 | | - || sqlite3IdListIndex(pItem->u3.pUsing, zCol)<0 |
| 107655 | | - ){ |
| 107656 | | - /* Two or more tables have the same column name which is |
| 107657 | | - ** not joined by USING. This is an error. Signal as much |
| 107658 | | - ** by clearing pFJMatch and letting cnt go above 1. */ |
| 107659 | | - sqlite3ExprListDelete(db, pFJMatch); |
| 107660 | | - pFJMatch = 0; |
| 107661 | | - }else |
| 107662 | | - if( (pItem->fg.jointype & JT_RIGHT)==0 ){ |
| 107663 | | - /* An INNER or LEFT JOIN. Use the left-most table */ |
| 107664 | | - continue; |
| 107665 | | - }else |
| 107666 | | - if( (pItem->fg.jointype & JT_LEFT)==0 ){ |
| 107667 | | - /* A RIGHT JOIN. Use the right-most table */ |
| 107668 | | - cnt = 0; |
| 107669 | | - sqlite3ExprListDelete(db, pFJMatch); |
| 107670 | | - pFJMatch = 0; |
| 107671 | | - }else{ |
| 107672 | | - /* For a FULL JOIN, we must construct a coalesce() func */ |
| 107673 | | - extendFJMatch(pParse, &pFJMatch, pMatch, pExpr->iColumn); |
| 107674 | | - } |
| 107675 | | - } |
| 107676 | | - cnt++; |
| 107677 | | - pMatch = pItem; |
| 107678 | | - /* Substitute the rowid (column -1) for the INTEGER PRIMARY KEY */ |
| 107679 | | - pExpr->iColumn = j==pTab->iPKey ? -1 : (i16)j; |
| 107680 | | - if( pItem->fg.isNestedFrom ){ |
| 107681 | | - sqlite3SrcItemColumnUsed(pItem, j); |
| 107682 | | - } |
| 107683 | | - break; |
| 107984 | + j = sqlite3ColumnIndex(pTab, zCol); |
| 107985 | + if( j>=0 ){ |
| 107986 | + if( cnt>0 ){ |
| 107987 | + if( pItem->fg.isUsing==0 |
| 107988 | + || sqlite3IdListIndex(pItem->u3.pUsing, zCol)<0 |
| 107989 | + ){ |
| 107990 | + /* Two or more tables have the same column name which is |
| 107991 | + ** not joined by USING. This is an error. Signal as much |
| 107992 | + ** by clearing pFJMatch and letting cnt go above 1. */ |
| 107993 | + sqlite3ExprListDelete(db, pFJMatch); |
| 107994 | + pFJMatch = 0; |
| 107995 | + }else |
| 107996 | + if( (pItem->fg.jointype & JT_RIGHT)==0 ){ |
| 107997 | + /* An INNER or LEFT JOIN. Use the left-most table */ |
| 107998 | + continue; |
| 107999 | + }else |
| 108000 | + if( (pItem->fg.jointype & JT_LEFT)==0 ){ |
| 108001 | + /* A RIGHT JOIN. Use the right-most table */ |
| 108002 | + cnt = 0; |
| 108003 | + sqlite3ExprListDelete(db, pFJMatch); |
| 108004 | + pFJMatch = 0; |
| 108005 | + }else{ |
| 108006 | + /* For a FULL JOIN, we must construct a coalesce() func */ |
| 108007 | + extendFJMatch(pParse, &pFJMatch, pMatch, pExpr->iColumn); |
| 108008 | + } |
| 108009 | + } |
| 108010 | + cnt++; |
| 108011 | + pMatch = pItem; |
| 108012 | + /* Substitute the rowid (column -1) for the INTEGER PRIMARY KEY */ |
| 108013 | + pExpr->iColumn = j==pTab->iPKey ? -1 : (i16)j; |
| 108014 | + if( pItem->fg.isNestedFrom ){ |
| 108015 | + sqlite3SrcItemColumnUsed(pItem, j); |
| 107684 | 108016 | } |
| 107685 | 108017 | } |
| 107686 | 108018 | if( 0==cnt && VisibleRowid(pTab) ){ |
| 107687 | 108019 | /* pTab is a potential ROWID match. Keep track of it and match |
| 107688 | 108020 | ** the ROWID later if that seems appropriate. (Search for "cntTab" |
| | @@ -107768,26 +108100,21 @@ |
| 107768 | 108100 | } |
| 107769 | 108101 | #endif /* SQLITE_OMIT_UPSERT */ |
| 107770 | 108102 | |
| 107771 | 108103 | if( pTab ){ |
| 107772 | 108104 | int iCol; |
| 107773 | | - u8 hCol = sqlite3StrIHash(zCol); |
| 107774 | 108105 | pSchema = pTab->pSchema; |
| 107775 | 108106 | cntTab++; |
| 107776 | | - for(iCol=0, pCol=pTab->aCol; iCol<pTab->nCol; iCol++, pCol++){ |
| 107777 | | - if( pCol->hName==hCol |
| 107778 | | - && sqlite3StrICmp(pCol->zCnName, zCol)==0 |
| 107779 | | - ){ |
| 107780 | | - if( iCol==pTab->iPKey ){ |
| 107781 | | - iCol = -1; |
| 107782 | | - } |
| 107783 | | - break; |
| 107784 | | - } |
| 107785 | | - } |
| 107786 | | - if( iCol>=pTab->nCol && sqlite3IsRowid(zCol) && VisibleRowid(pTab) ){ |
| 107787 | | - /* IMP: R-51414-32910 */ |
| 107788 | | - iCol = -1; |
| 108107 | + iCol = sqlite3ColumnIndex(pTab, zCol); |
| 108108 | + if( iCol>=0 ){ |
| 108109 | + if( pTab->iPKey==iCol ) iCol = -1; |
| 108110 | + }else{ |
| 108111 | + if( sqlite3IsRowid(zCol) && VisibleRowid(pTab) ){ |
| 108112 | + iCol = -1; |
| 108113 | + }else{ |
| 108114 | + iCol = pTab->nCol; |
| 108115 | + } |
| 107789 | 108116 | } |
| 107790 | 108117 | if( iCol<pTab->nCol ){ |
| 107791 | 108118 | cnt++; |
| 107792 | 108119 | pMatch = 0; |
| 107793 | 108120 | #ifndef SQLITE_OMIT_UPSERT |
| | @@ -111379,11 +111706,10 @@ |
| 111379 | 111706 | pNewExpr->pLeft = pPriorSelectColNew; |
| 111380 | 111707 | } |
| 111381 | 111708 | } |
| 111382 | 111709 | pItem->zEName = sqlite3DbStrDup(db, pOldItem->zEName); |
| 111383 | 111710 | pItem->fg = pOldItem->fg; |
| 111384 | | - pItem->fg.done = 0; |
| 111385 | 111711 | pItem->u = pOldItem->u; |
| 111386 | 111712 | } |
| 111387 | 111713 | return pNew; |
| 111388 | 111714 | } |
| 111389 | 111715 | |
| | @@ -112496,17 +112822,11 @@ |
| 112496 | 112822 | SQLITE_PRIVATE const char *sqlite3RowidAlias(Table *pTab){ |
| 112497 | 112823 | const char *azOpt[] = {"_ROWID_", "ROWID", "OID"}; |
| 112498 | 112824 | int ii; |
| 112499 | 112825 | assert( VisibleRowid(pTab) ); |
| 112500 | 112826 | for(ii=0; ii<ArraySize(azOpt); ii++){ |
| 112501 | | - int iCol; |
| 112502 | | - for(iCol=0; iCol<pTab->nCol; iCol++){ |
| 112503 | | - if( sqlite3_stricmp(azOpt[ii], pTab->aCol[iCol].zCnName)==0 ) break; |
| 112504 | | - } |
| 112505 | | - if( iCol==pTab->nCol ){ |
| 112506 | | - return azOpt[ii]; |
| 112507 | | - } |
| 112827 | + if( sqlite3ColumnIndex(pTab, azOpt[ii])<0 ) return azOpt[ii]; |
| 112508 | 112828 | } |
| 112509 | 112829 | return 0; |
| 112510 | 112830 | } |
| 112511 | 112831 | |
| 112512 | 112832 | /* |
| | @@ -117551,14 +117871,12 @@ |
| 117551 | 117871 | |
| 117552 | 117872 | /* Make sure the old name really is a column name in the table to be |
| 117553 | 117873 | ** altered. Set iCol to be the index of the column being renamed */ |
| 117554 | 117874 | zOld = sqlite3NameFromToken(db, pOld); |
| 117555 | 117875 | if( !zOld ) goto exit_rename_column; |
| 117556 | | - for(iCol=0; iCol<pTab->nCol; iCol++){ |
| 117557 | | - if( 0==sqlite3StrICmp(pTab->aCol[iCol].zCnName, zOld) ) break; |
| 117558 | | - } |
| 117559 | | - if( iCol==pTab->nCol ){ |
| 117876 | + iCol = sqlite3ColumnIndex(pTab, zOld); |
| 117877 | + if( iCol<0 ){ |
| 117560 | 117878 | sqlite3ErrorMsg(pParse, "no such column: \"%T\"", pOld); |
| 117561 | 117879 | goto exit_rename_column; |
| 117562 | 117880 | } |
| 117563 | 117881 | |
| 117564 | 117882 | /* Ensure the schema contains no double-quoted strings */ |
| | @@ -119453,11 +119771,12 @@ |
| 119453 | 119771 | ** of the new table in register pParse->regRoot. This is important |
| 119454 | 119772 | ** because the OpenWrite opcode below will be needing it. */ |
| 119455 | 119773 | sqlite3NestedParse(pParse, |
| 119456 | 119774 | "CREATE TABLE %Q.%s(%s)", pDb->zDbSName, zTab, aTable[i].zCols |
| 119457 | 119775 | ); |
| 119458 | | - aRoot[i] = (u32)pParse->regRoot; |
| 119776 | + assert( pParse->isCreate || pParse->nErr ); |
| 119777 | + aRoot[i] = (u32)pParse->u1.cr.regRoot; |
| 119459 | 119778 | aCreateTbl[i] = OPFLAG_P2ISREG; |
| 119460 | 119779 | } |
| 119461 | 119780 | }else{ |
| 119462 | 119781 | /* The table already exists. If zWhere is not NULL, delete all entries |
| 119463 | 119782 | ** associated with the table zWhere. If zWhere is NULL, delete the |
| | @@ -121489,10 +121808,17 @@ |
| 121489 | 121808 | */ |
| 121490 | 121809 | if( rc==SQLITE_OK ){ |
| 121491 | 121810 | sqlite3BtreeEnterAll(db); |
| 121492 | 121811 | db->init.iDb = 0; |
| 121493 | 121812 | db->mDbFlags &= ~(DBFLAG_SchemaKnownOk); |
| 121813 | +#ifdef SQLITE_ENABLE_SETLK_TIMEOUT |
| 121814 | + if( db->setlkFlags & SQLITE_SETLK_BLOCK_ON_CONNECT ){ |
| 121815 | + int val = 1; |
| 121816 | + sqlite3_file *fd = sqlite3PagerFile(sqlite3BtreePager(pNew->pBt)); |
| 121817 | + sqlite3OsFileControlHint(fd, SQLITE_FCNTL_BLOCK_ON_CONNECT, &val); |
| 121818 | + } |
| 121819 | +#endif |
| 121494 | 121820 | if( !REOPEN_AS_MEMDB(db) ){ |
| 121495 | 121821 | rc = sqlite3Init(db, &zErrDyn); |
| 121496 | 121822 | } |
| 121497 | 121823 | sqlite3BtreeLeaveAll(db); |
| 121498 | 121824 | assert( zErrDyn==0 || rc!=SQLITE_OK ); |
| | @@ -122311,14 +122637,16 @@ |
| 122311 | 122637 | } |
| 122312 | 122638 | assert( !pParse->isMultiWrite |
| 122313 | 122639 | || sqlite3VdbeAssertMayAbort(v, pParse->mayAbort)); |
| 122314 | 122640 | if( v ){ |
| 122315 | 122641 | if( pParse->bReturning ){ |
| 122316 | | - Returning *pReturning = pParse->u1.pReturning; |
| 122642 | + Returning *pReturning; |
| 122317 | 122643 | int addrRewind; |
| 122318 | 122644 | int reg; |
| 122319 | 122645 | |
| 122646 | + assert( !pParse->isCreate ); |
| 122647 | + pReturning = pParse->u1.d.pReturning; |
| 122320 | 122648 | if( pReturning->nRetCol ){ |
| 122321 | 122649 | sqlite3VdbeAddOp0(v, OP_FkCheck); |
| 122322 | 122650 | addrRewind = |
| 122323 | 122651 | sqlite3VdbeAddOp1(v, OP_Rewind, pReturning->iRetCur); |
| 122324 | 122652 | VdbeCoverage(v); |
| | @@ -122390,11 +122718,13 @@ |
| 122390 | 122718 | sqlite3ExprCode(pParse, pEL->a[i].pExpr, pEL->a[i].u.iConstExprReg); |
| 122391 | 122719 | } |
| 122392 | 122720 | } |
| 122393 | 122721 | |
| 122394 | 122722 | if( pParse->bReturning ){ |
| 122395 | | - Returning *pRet = pParse->u1.pReturning; |
| 122723 | + Returning *pRet; |
| 122724 | + assert( !pParse->isCreate ); |
| 122725 | + pRet = pParse->u1.d.pReturning; |
| 122396 | 122726 | if( pRet->nRetCol ){ |
| 122397 | 122727 | sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pRet->iRetCur, pRet->nRetCol); |
| 122398 | 122728 | } |
| 122399 | 122729 | } |
| 122400 | 122730 | |
| | @@ -123462,12 +123792,13 @@ |
| 123462 | 123792 | #endif |
| 123463 | 123793 | |
| 123464 | 123794 | /* If the file format and encoding in the database have not been set, |
| 123465 | 123795 | ** set them now. |
| 123466 | 123796 | */ |
| 123467 | | - reg1 = pParse->regRowid = ++pParse->nMem; |
| 123468 | | - reg2 = pParse->regRoot = ++pParse->nMem; |
| 123797 | + assert( pParse->isCreate ); |
| 123798 | + reg1 = pParse->u1.cr.regRowid = ++pParse->nMem; |
| 123799 | + reg2 = pParse->u1.cr.regRoot = ++pParse->nMem; |
| 123469 | 123800 | reg3 = ++pParse->nMem; |
| 123470 | 123801 | sqlite3VdbeAddOp3(v, OP_ReadCookie, iDb, reg3, BTREE_FILE_FORMAT); |
| 123471 | 123802 | sqlite3VdbeUsesBtree(v, iDb); |
| 123472 | 123803 | addr1 = sqlite3VdbeAddOp1(v, OP_If, reg3); VdbeCoverage(v); |
| 123473 | 123804 | fileFormat = (db->flags & SQLITE_LegacyFileFmt)!=0 ? |
| | @@ -123478,12 +123809,12 @@ |
| 123478 | 123809 | |
| 123479 | 123810 | /* This just creates a place-holder record in the sqlite_schema table. |
| 123480 | 123811 | ** The record created does not contain anything yet. It will be replaced |
| 123481 | 123812 | ** by the real entry in code generated at sqlite3EndTable(). |
| 123482 | 123813 | ** |
| 123483 | | - ** The rowid for the new entry is left in register pParse->regRowid. |
| 123484 | | - ** The root page number of the new table is left in reg pParse->regRoot. |
| 123814 | + ** The rowid for the new entry is left in register pParse->u1.cr.regRowid. |
| 123815 | + ** The root page of the new table is left in reg pParse->u1.cr.regRoot. |
| 123485 | 123816 | ** The rowid and root page number values are needed by the code that |
| 123486 | 123817 | ** sqlite3EndTable will generate. |
| 123487 | 123818 | */ |
| 123488 | 123819 | #if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE) |
| 123489 | 123820 | if( isView || isVirtual ){ |
| | @@ -123490,11 +123821,11 @@ |
| 123490 | 123821 | sqlite3VdbeAddOp2(v, OP_Integer, 0, reg2); |
| 123491 | 123822 | }else |
| 123492 | 123823 | #endif |
| 123493 | 123824 | { |
| 123494 | 123825 | assert( !pParse->bReturning ); |
| 123495 | | - pParse->u1.addrCrTab = |
| 123826 | + pParse->u1.cr.addrCrTab = |
| 123496 | 123827 | sqlite3VdbeAddOp3(v, OP_CreateBtree, iDb, reg2, BTREE_INTKEY); |
| 123497 | 123828 | } |
| 123498 | 123829 | sqlite3OpenSchemaTable(pParse, iDb); |
| 123499 | 123830 | sqlite3VdbeAddOp2(v, OP_NewRowid, 0, reg1); |
| 123500 | 123831 | sqlite3VdbeAddOp4(v, OP_Blob, 6, reg3, 0, nullRow, P4_STATIC); |
| | @@ -123568,11 +123899,12 @@ |
| 123568 | 123899 | pRet = sqlite3DbMallocZero(db, sizeof(*pRet)); |
| 123569 | 123900 | if( pRet==0 ){ |
| 123570 | 123901 | sqlite3ExprListDelete(db, pList); |
| 123571 | 123902 | return; |
| 123572 | 123903 | } |
| 123573 | | - pParse->u1.pReturning = pRet; |
| 123904 | + assert( !pParse->isCreate ); |
| 123905 | + pParse->u1.d.pReturning = pRet; |
| 123574 | 123906 | pRet->pParse = pParse; |
| 123575 | 123907 | pRet->pReturnEL = pList; |
| 123576 | 123908 | sqlite3ParserAddCleanup(pParse, sqlite3DeleteReturning, pRet); |
| 123577 | 123909 | testcase( pParse->earlyCleanup ); |
| 123578 | 123910 | if( db->mallocFailed ) return; |
| | @@ -123610,11 +123942,10 @@ |
| 123610 | 123942 | int i; |
| 123611 | 123943 | char *z; |
| 123612 | 123944 | char *zType; |
| 123613 | 123945 | Column *pCol; |
| 123614 | 123946 | sqlite3 *db = pParse->db; |
| 123615 | | - u8 hName; |
| 123616 | 123947 | Column *aNew; |
| 123617 | 123948 | u8 eType = COLTYPE_CUSTOM; |
| 123618 | 123949 | u8 szEst = 1; |
| 123619 | 123950 | char affinity = SQLITE_AFF_BLOB; |
| 123620 | 123951 | |
| | @@ -123664,17 +123995,14 @@ |
| 123664 | 123995 | if( z==0 ) return; |
| 123665 | 123996 | if( IN_RENAME_OBJECT ) sqlite3RenameTokenMap(pParse, (void*)z, &sName); |
| 123666 | 123997 | memcpy(z, sName.z, sName.n); |
| 123667 | 123998 | z[sName.n] = 0; |
| 123668 | 123999 | sqlite3Dequote(z); |
| 123669 | | - hName = sqlite3StrIHash(z); |
| 123670 | | - for(i=0; i<p->nCol; i++){ |
| 123671 | | - if( p->aCol[i].hName==hName && sqlite3StrICmp(z, p->aCol[i].zCnName)==0 ){ |
| 123672 | | - sqlite3ErrorMsg(pParse, "duplicate column name: %s", z); |
| 123673 | | - sqlite3DbFree(db, z); |
| 123674 | | - return; |
| 123675 | | - } |
| 124000 | + if( p->nCol && sqlite3ColumnIndex(p, z)>=0 ){ |
| 124001 | + sqlite3ErrorMsg(pParse, "duplicate column name: %s", z); |
| 124002 | + sqlite3DbFree(db, z); |
| 124003 | + return; |
| 123676 | 124004 | } |
| 123677 | 124005 | aNew = sqlite3DbRealloc(db,p->aCol,((i64)p->nCol+1)*sizeof(p->aCol[0])); |
| 123678 | 124006 | if( aNew==0 ){ |
| 123679 | 124007 | sqlite3DbFree(db, z); |
| 123680 | 124008 | return; |
| | @@ -123681,11 +124009,11 @@ |
| 123681 | 124009 | } |
| 123682 | 124010 | p->aCol = aNew; |
| 123683 | 124011 | pCol = &p->aCol[p->nCol]; |
| 123684 | 124012 | memset(pCol, 0, sizeof(p->aCol[0])); |
| 123685 | 124013 | pCol->zCnName = z; |
| 123686 | | - pCol->hName = hName; |
| 124014 | + pCol->hName = sqlite3StrIHash(z); |
| 123687 | 124015 | sqlite3ColumnPropertiesFromName(p, pCol); |
| 123688 | 124016 | |
| 123689 | 124017 | if( sType.n==0 ){ |
| 123690 | 124018 | /* If there is no type specified, columns have the default affinity |
| 123691 | 124019 | ** 'BLOB' with a default size of 4 bytes. */ |
| | @@ -123705,13 +124033,18 @@ |
| 123705 | 124033 | zType[sType.n] = 0; |
| 123706 | 124034 | sqlite3Dequote(zType); |
| 123707 | 124035 | pCol->affinity = sqlite3AffinityType(zType, pCol); |
| 123708 | 124036 | pCol->colFlags |= COLFLAG_HASTYPE; |
| 123709 | 124037 | } |
| 124038 | + if( p->nCol<=0xff ){ |
| 124039 | + u8 h = pCol->hName % sizeof(p->aHx); |
| 124040 | + p->aHx[h] = p->nCol; |
| 124041 | + } |
| 123710 | 124042 | p->nCol++; |
| 123711 | 124043 | p->nNVCol++; |
| 123712 | | - pParse->constraintName.n = 0; |
| 124044 | + assert( pParse->isCreate ); |
| 124045 | + pParse->u1.cr.constraintName.n = 0; |
| 123713 | 124046 | } |
| 123714 | 124047 | |
| 123715 | 124048 | /* |
| 123716 | 124049 | ** This routine is called by the parser while in the middle of |
| 123717 | 124050 | ** parsing a CREATE TABLE statement. A "NOT NULL" constraint has |
| | @@ -123971,19 +124304,15 @@ |
| 123971 | 124304 | for(i=0; i<nTerm; i++){ |
| 123972 | 124305 | Expr *pCExpr = sqlite3ExprSkipCollate(pList->a[i].pExpr); |
| 123973 | 124306 | assert( pCExpr!=0 ); |
| 123974 | 124307 | sqlite3StringToId(pCExpr); |
| 123975 | 124308 | if( pCExpr->op==TK_ID ){ |
| 123976 | | - const char *zCName; |
| 123977 | 124309 | assert( !ExprHasProperty(pCExpr, EP_IntValue) ); |
| 123978 | | - zCName = pCExpr->u.zToken; |
| 123979 | | - for(iCol=0; iCol<pTab->nCol; iCol++){ |
| 123980 | | - if( sqlite3StrICmp(zCName, pTab->aCol[iCol].zCnName)==0 ){ |
| 123981 | | - pCol = &pTab->aCol[iCol]; |
| 123982 | | - makeColumnPartOfPrimaryKey(pParse, pCol); |
| 123983 | | - break; |
| 123984 | | - } |
| 124310 | + iCol = sqlite3ColumnIndex(pTab, pCExpr->u.zToken); |
| 124311 | + if( iCol>=0 ){ |
| 124312 | + pCol = &pTab->aCol[iCol]; |
| 124313 | + makeColumnPartOfPrimaryKey(pParse, pCol); |
| 123985 | 124314 | } |
| 123986 | 124315 | } |
| 123987 | 124316 | } |
| 123988 | 124317 | } |
| 123989 | 124318 | if( nTerm==1 |
| | @@ -124031,12 +124360,14 @@ |
| 124031 | 124360 | sqlite3 *db = pParse->db; |
| 124032 | 124361 | if( pTab && !IN_DECLARE_VTAB |
| 124033 | 124362 | && !sqlite3BtreeIsReadonly(db->aDb[db->init.iDb].pBt) |
| 124034 | 124363 | ){ |
| 124035 | 124364 | pTab->pCheck = sqlite3ExprListAppend(pParse, pTab->pCheck, pCheckExpr); |
| 124036 | | - if( pParse->constraintName.n ){ |
| 124037 | | - sqlite3ExprListSetName(pParse, pTab->pCheck, &pParse->constraintName, 1); |
| 124365 | + assert( pParse->isCreate ); |
| 124366 | + if( pParse->u1.cr.constraintName.n ){ |
| 124367 | + sqlite3ExprListSetName(pParse, pTab->pCheck, |
| 124368 | + &pParse->u1.cr.constraintName, 1); |
| 124038 | 124369 | }else{ |
| 124039 | 124370 | Token t; |
| 124040 | 124371 | for(zStart++; sqlite3Isspace(zStart[0]); zStart++){} |
| 124041 | 124372 | while( sqlite3Isspace(zEnd[-1]) ){ zEnd--; } |
| 124042 | 124373 | t.z = zStart; |
| | @@ -124482,13 +124813,13 @@ |
| 124482 | 124813 | |
| 124483 | 124814 | /* Convert the P3 operand of the OP_CreateBtree opcode from BTREE_INTKEY |
| 124484 | 124815 | ** into BTREE_BLOBKEY. |
| 124485 | 124816 | */ |
| 124486 | 124817 | assert( !pParse->bReturning ); |
| 124487 | | - if( pParse->u1.addrCrTab ){ |
| 124818 | + if( pParse->u1.cr.addrCrTab ){ |
| 124488 | 124819 | assert( v ); |
| 124489 | | - sqlite3VdbeChangeP3(v, pParse->u1.addrCrTab, BTREE_BLOBKEY); |
| 124820 | + sqlite3VdbeChangeP3(v, pParse->u1.cr.addrCrTab, BTREE_BLOBKEY); |
| 124490 | 124821 | } |
| 124491 | 124822 | |
| 124492 | 124823 | /* Locate the PRIMARY KEY index. Or, if this table was originally |
| 124493 | 124824 | ** an INTEGER PRIMARY KEY table, create a new PRIMARY KEY index. |
| 124494 | 124825 | */ |
| | @@ -124924,11 +125255,11 @@ |
| 124924 | 125255 | #endif |
| 124925 | 125256 | } |
| 124926 | 125257 | |
| 124927 | 125258 | /* If this is a CREATE TABLE xx AS SELECT ..., execute the SELECT |
| 124928 | 125259 | ** statement to populate the new table. The root-page number for the |
| 124929 | | - ** new table is in register pParse->regRoot. |
| 125260 | + ** new table is in register pParse->u1.cr.regRoot. |
| 124930 | 125261 | ** |
| 124931 | 125262 | ** Once the SELECT has been coded by sqlite3Select(), it is in a |
| 124932 | 125263 | ** suitable state to query for the column names and types to be used |
| 124933 | 125264 | ** by the new table. |
| 124934 | 125265 | ** |
| | @@ -124955,11 +125286,12 @@ |
| 124955 | 125286 | iCsr = pParse->nTab++; |
| 124956 | 125287 | regYield = ++pParse->nMem; |
| 124957 | 125288 | regRec = ++pParse->nMem; |
| 124958 | 125289 | regRowid = ++pParse->nMem; |
| 124959 | 125290 | sqlite3MayAbort(pParse); |
| 124960 | | - sqlite3VdbeAddOp3(v, OP_OpenWrite, iCsr, pParse->regRoot, iDb); |
| 125291 | + assert( pParse->isCreate ); |
| 125292 | + sqlite3VdbeAddOp3(v, OP_OpenWrite, iCsr, pParse->u1.cr.regRoot, iDb); |
| 124961 | 125293 | sqlite3VdbeChangeP5(v, OPFLAG_P2ISREG); |
| 124962 | 125294 | addrTop = sqlite3VdbeCurrentAddr(v) + 1; |
| 124963 | 125295 | sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, addrTop); |
| 124964 | 125296 | if( pParse->nErr ) return; |
| 124965 | 125297 | pSelTab = sqlite3ResultSetOfSelect(pParse, pSelect, SQLITE_AFF_BLOB); |
| | @@ -125000,21 +125332,22 @@ |
| 125000 | 125332 | |
| 125001 | 125333 | /* A slot for the record has already been allocated in the |
| 125002 | 125334 | ** schema table. We just need to update that slot with all |
| 125003 | 125335 | ** the information we've collected. |
| 125004 | 125336 | */ |
| 125337 | + assert( pParse->isCreate ); |
| 125005 | 125338 | sqlite3NestedParse(pParse, |
| 125006 | 125339 | "UPDATE %Q." LEGACY_SCHEMA_TABLE |
| 125007 | 125340 | " SET type='%s', name=%Q, tbl_name=%Q, rootpage=#%d, sql=%Q" |
| 125008 | 125341 | " WHERE rowid=#%d", |
| 125009 | 125342 | db->aDb[iDb].zDbSName, |
| 125010 | 125343 | zType, |
| 125011 | 125344 | p->zName, |
| 125012 | 125345 | p->zName, |
| 125013 | | - pParse->regRoot, |
| 125346 | + pParse->u1.cr.regRoot, |
| 125014 | 125347 | zStmt, |
| 125015 | | - pParse->regRowid |
| 125348 | + pParse->u1.cr.regRowid |
| 125016 | 125349 | ); |
| 125017 | 125350 | sqlite3DbFree(db, zStmt); |
| 125018 | 125351 | sqlite3ChangeCookie(pParse, iDb); |
| 125019 | 125352 | |
| 125020 | 125353 | #ifndef SQLITE_OMIT_AUTOINCREMENT |
| | @@ -129850,15 +130183,10 @@ |
| 129850 | 130183 | int len; |
| 129851 | 130184 | int p0type; |
| 129852 | 130185 | i64 p1, p2; |
| 129853 | 130186 | |
| 129854 | 130187 | assert( argc==3 || argc==2 ); |
| 129855 | | - if( sqlite3_value_type(argv[1])==SQLITE_NULL |
| 129856 | | - || (argc==3 && sqlite3_value_type(argv[2])==SQLITE_NULL) |
| 129857 | | - ){ |
| 129858 | | - return; |
| 129859 | | - } |
| 129860 | 130188 | p0type = sqlite3_value_type(argv[0]); |
| 129861 | 130189 | p1 = sqlite3_value_int64(argv[1]); |
| 129862 | 130190 | if( p0type==SQLITE_BLOB ){ |
| 129863 | 130191 | len = sqlite3_value_bytes(argv[0]); |
| 129864 | 130192 | z = sqlite3_value_blob(argv[0]); |
| | @@ -129872,23 +130200,27 @@ |
| 129872 | 130200 | for(z2=z; *z2; len++){ |
| 129873 | 130201 | SQLITE_SKIP_UTF8(z2); |
| 129874 | 130202 | } |
| 129875 | 130203 | } |
| 129876 | 130204 | } |
| 129877 | | -#ifdef SQLITE_SUBSTR_COMPATIBILITY |
| 129878 | | - /* If SUBSTR_COMPATIBILITY is defined then substr(X,0,N) work the same as |
| 129879 | | - ** as substr(X,1,N) - it returns the first N characters of X. This |
| 129880 | | - ** is essentially a back-out of the bug-fix in check-in [5fc125d362df4b8] |
| 129881 | | - ** from 2009-02-02 for compatibility of applications that exploited the |
| 129882 | | - ** old buggy behavior. */ |
| 129883 | | - if( p1==0 ) p1 = 1; /* <rdar://problem/6778339> */ |
| 129884 | | -#endif |
| 129885 | 130205 | if( argc==3 ){ |
| 129886 | 130206 | p2 = sqlite3_value_int64(argv[2]); |
| 130207 | + if( p2==0 && sqlite3_value_type(argv[2])==SQLITE_NULL ) return; |
| 129887 | 130208 | }else{ |
| 129888 | 130209 | p2 = sqlite3_context_db_handle(context)->aLimit[SQLITE_LIMIT_LENGTH]; |
| 129889 | 130210 | } |
| 130211 | + if( p1==0 ){ |
| 130212 | +#ifdef SQLITE_SUBSTR_COMPATIBILITY |
| 130213 | + /* If SUBSTR_COMPATIBILITY is defined then substr(X,0,N) work the same as |
| 130214 | + ** as substr(X,1,N) - it returns the first N characters of X. This |
| 130215 | + ** is essentially a back-out of the bug-fix in check-in [5fc125d362df4b8] |
| 130216 | + ** from 2009-02-02 for compatibility of applications that exploited the |
| 130217 | + ** old buggy behavior. */ |
| 130218 | + p1 = 1; /* <rdar://problem/6778339> */ |
| 130219 | +#endif |
| 130220 | + if( sqlite3_value_type(argv[1])==SQLITE_NULL ) return; |
| 130221 | + } |
| 129890 | 130222 | if( p1<0 ){ |
| 129891 | 130223 | p1 += len; |
| 129892 | 130224 | if( p1<0 ){ |
| 129893 | 130225 | if( p2<0 ){ |
| 129894 | 130226 | p2 = 0; |
| | @@ -134900,32 +135232,26 @@ |
| 134900 | 135232 | bIdListInOrder = (pTab->tabFlags & (TF_OOOHidden|TF_HasStored))==0; |
| 134901 | 135233 | if( pColumn ){ |
| 134902 | 135234 | aTabColMap = sqlite3DbMallocZero(db, pTab->nCol*sizeof(int)); |
| 134903 | 135235 | if( aTabColMap==0 ) goto insert_cleanup; |
| 134904 | 135236 | for(i=0; i<pColumn->nId; i++){ |
| 134905 | | - const char *zCName = pColumn->a[i].zName; |
| 134906 | | - u8 hName = sqlite3StrIHash(zCName); |
| 134907 | | - for(j=0; j<pTab->nCol; j++){ |
| 134908 | | - if( pTab->aCol[j].hName!=hName ) continue; |
| 134909 | | - if( sqlite3StrICmp(zCName, pTab->aCol[j].zCnName)==0 ){ |
| 134910 | | - if( aTabColMap[j]==0 ) aTabColMap[j] = i+1; |
| 134911 | | - if( i!=j ) bIdListInOrder = 0; |
| 134912 | | - if( j==pTab->iPKey ){ |
| 134913 | | - ipkColumn = i; assert( !withoutRowid ); |
| 134914 | | - } |
| 135237 | + j = sqlite3ColumnIndex(pTab, pColumn->a[i].zName); |
| 135238 | + if( j>=0 ){ |
| 135239 | + if( aTabColMap[j]==0 ) aTabColMap[j] = i+1; |
| 135240 | + if( i!=j ) bIdListInOrder = 0; |
| 135241 | + if( j==pTab->iPKey ){ |
| 135242 | + ipkColumn = i; assert( !withoutRowid ); |
| 135243 | + } |
| 134915 | 135244 | #ifndef SQLITE_OMIT_GENERATED_COLUMNS |
| 134916 | | - if( pTab->aCol[j].colFlags & (COLFLAG_STORED|COLFLAG_VIRTUAL) ){ |
| 134917 | | - sqlite3ErrorMsg(pParse, |
| 134918 | | - "cannot INSERT into generated column \"%s\"", |
| 134919 | | - pTab->aCol[j].zCnName); |
| 134920 | | - goto insert_cleanup; |
| 134921 | | - } |
| 135245 | + if( pTab->aCol[j].colFlags & (COLFLAG_STORED|COLFLAG_VIRTUAL) ){ |
| 135246 | + sqlite3ErrorMsg(pParse, |
| 135247 | + "cannot INSERT into generated column \"%s\"", |
| 135248 | + pTab->aCol[j].zCnName); |
| 135249 | + goto insert_cleanup; |
| 135250 | + } |
| 134922 | 135251 | #endif |
| 134923 | | - break; |
| 134924 | | - } |
| 134925 | | - } |
| 134926 | | - if( j>=pTab->nCol ){ |
| 135252 | + }else{ |
| 134927 | 135253 | if( sqlite3IsRowid(pColumn->a[i].zName) && !withoutRowid ){ |
| 134928 | 135254 | ipkColumn = i; |
| 134929 | 135255 | bIdListInOrder = 0; |
| 134930 | 135256 | }else{ |
| 134931 | 135257 | sqlite3ErrorMsg(pParse, "table %S has no column named %s", |
| | @@ -135219,11 +135545,11 @@ |
| 135219 | 135545 | sqlite3VdbeAddOp1(v, OP_SoftNull, iRegStore); |
| 135220 | 135546 | } |
| 135221 | 135547 | continue; |
| 135222 | 135548 | }else if( pColumn==0 ){ |
| 135223 | 135549 | /* Hidden columns that are not explicitly named in the INSERT |
| 135224 | | - ** get there default value */ |
| 135550 | + ** get their default value */ |
| 135225 | 135551 | sqlite3ExprCodeFactorable(pParse, |
| 135226 | 135552 | sqlite3ColumnExpr(pTab, &pTab->aCol[i]), |
| 135227 | 135553 | iRegStore); |
| 135228 | 135554 | continue; |
| 135229 | 135555 | } |
| | @@ -144166,14 +144492,37 @@ |
| 144166 | 144492 | ** Return the index of a column in a table. Return -1 if the column |
| 144167 | 144493 | ** is not contained in the table. |
| 144168 | 144494 | */ |
| 144169 | 144495 | SQLITE_PRIVATE int sqlite3ColumnIndex(Table *pTab, const char *zCol){ |
| 144170 | 144496 | int i; |
| 144171 | | - u8 h = sqlite3StrIHash(zCol); |
| 144172 | | - Column *pCol; |
| 144173 | | - for(pCol=pTab->aCol, i=0; i<pTab->nCol; pCol++, i++){ |
| 144174 | | - if( pCol->hName==h && sqlite3StrICmp(pCol->zCnName, zCol)==0 ) return i; |
| 144497 | + u8 h; |
| 144498 | + const Column *aCol; |
| 144499 | + int nCol; |
| 144500 | + |
| 144501 | + h = sqlite3StrIHash(zCol); |
| 144502 | + aCol = pTab->aCol; |
| 144503 | + nCol = pTab->nCol; |
| 144504 | + |
| 144505 | + /* See if the aHx gives us a lucky match */ |
| 144506 | + i = pTab->aHx[h % sizeof(pTab->aHx)]; |
| 144507 | + assert( i<nCol ); |
| 144508 | + if( aCol[i].hName==h |
| 144509 | + && sqlite3StrICmp(aCol[i].zCnName, zCol)==0 |
| 144510 | + ){ |
| 144511 | + return i; |
| 144512 | + } |
| 144513 | + |
| 144514 | + /* No lucky match from the hash table. Do a full search. */ |
| 144515 | + i = 0; |
| 144516 | + while( 1 /*exit-by-break*/ ){ |
| 144517 | + if( aCol[i].hName==h |
| 144518 | + && sqlite3StrICmp(aCol[i].zCnName, zCol)==0 |
| 144519 | + ){ |
| 144520 | + return i; |
| 144521 | + } |
| 144522 | + i++; |
| 144523 | + if( i>=nCol ) break; |
| 144175 | 144524 | } |
| 144176 | 144525 | return -1; |
| 144177 | 144526 | } |
| 144178 | 144527 | |
| 144179 | 144528 | /* |
| | @@ -152891,11 +153240,12 @@ |
| 152891 | 153240 | }else if( pTrig->op==TK_RETURNING ){ |
| 152892 | 153241 | #ifndef SQLITE_OMIT_VIRTUALTABLE |
| 152893 | 153242 | assert( pParse->db->pVtabCtx==0 ); |
| 152894 | 153243 | #endif |
| 152895 | 153244 | assert( pParse->bReturning ); |
| 152896 | | - assert( &(pParse->u1.pReturning->retTrig) == pTrig ); |
| 153245 | + assert( !pParse->isCreate ); |
| 153246 | + assert( &(pParse->u1.d.pReturning->retTrig) == pTrig ); |
| 152897 | 153247 | pTrig->table = pTab->zName; |
| 152898 | 153248 | pTrig->pTabSchema = pTab->pSchema; |
| 152899 | 153249 | pTrig->pNext = pList; |
| 152900 | 153250 | pList = pTrig; |
| 152901 | 153251 | } |
| | @@ -153868,11 +154218,12 @@ |
| 153868 | 154218 | /* This RETURNING trigger must be for a different statement as |
| 153869 | 154219 | ** this statement lacks a RETURNING clause. */ |
| 153870 | 154220 | return; |
| 153871 | 154221 | } |
| 153872 | 154222 | assert( db->pParse==pParse ); |
| 153873 | | - pReturning = pParse->u1.pReturning; |
| 154223 | + assert( !pParse->isCreate ); |
| 154224 | + pReturning = pParse->u1.d.pReturning; |
| 153874 | 154225 | if( pTrigger != &(pReturning->retTrig) ){ |
| 153875 | 154226 | /* This RETURNING trigger is for a different statement */ |
| 153876 | 154227 | return; |
| 153877 | 154228 | } |
| 153878 | 154229 | memset(&sSelect, 0, sizeof(sSelect)); |
| | @@ -154098,10 +154449,12 @@ |
| 154098 | 154449 | sSubParse.pToplevel = pTop; |
| 154099 | 154450 | sSubParse.zAuthContext = pTrigger->zName; |
| 154100 | 154451 | sSubParse.eTriggerOp = pTrigger->op; |
| 154101 | 154452 | sSubParse.nQueryLoop = pParse->nQueryLoop; |
| 154102 | 154453 | sSubParse.prepFlags = pParse->prepFlags; |
| 154454 | + sSubParse.oldmask = 0; |
| 154455 | + sSubParse.newmask = 0; |
| 154103 | 154456 | |
| 154104 | 154457 | v = sqlite3GetVdbe(&sSubParse); |
| 154105 | 154458 | if( v ){ |
| 154106 | 154459 | VdbeComment((v, "Start: %s.%s (%s %s%s%s ON %s)", |
| 154107 | 154460 | pTrigger->zName, onErrorText(orconf), |
| | @@ -154852,42 +155205,36 @@ |
| 154852 | 155205 | ** column to be updated, make sure we have authorization to change |
| 154853 | 155206 | ** that column. |
| 154854 | 155207 | */ |
| 154855 | 155208 | chngRowid = chngPk = 0; |
| 154856 | 155209 | for(i=0; i<pChanges->nExpr; i++){ |
| 154857 | | - u8 hCol = sqlite3StrIHash(pChanges->a[i].zEName); |
| 154858 | 155210 | /* If this is an UPDATE with a FROM clause, do not resolve expressions |
| 154859 | 155211 | ** here. The call to sqlite3Select() below will do that. */ |
| 154860 | 155212 | if( nChangeFrom==0 && sqlite3ResolveExprNames(&sNC, pChanges->a[i].pExpr) ){ |
| 154861 | 155213 | goto update_cleanup; |
| 154862 | 155214 | } |
| 154863 | | - for(j=0; j<pTab->nCol; j++){ |
| 154864 | | - if( pTab->aCol[j].hName==hCol |
| 154865 | | - && sqlite3StrICmp(pTab->aCol[j].zCnName, pChanges->a[i].zEName)==0 |
| 154866 | | - ){ |
| 154867 | | - if( j==pTab->iPKey ){ |
| 154868 | | - chngRowid = 1; |
| 154869 | | - pRowidExpr = pChanges->a[i].pExpr; |
| 154870 | | - iRowidExpr = i; |
| 154871 | | - }else if( pPk && (pTab->aCol[j].colFlags & COLFLAG_PRIMKEY)!=0 ){ |
| 154872 | | - chngPk = 1; |
| 154873 | | - } |
| 155215 | + j = sqlite3ColumnIndex(pTab, pChanges->a[i].zEName); |
| 155216 | + if( j>=0 ){ |
| 155217 | + if( j==pTab->iPKey ){ |
| 155218 | + chngRowid = 1; |
| 155219 | + pRowidExpr = pChanges->a[i].pExpr; |
| 155220 | + iRowidExpr = i; |
| 155221 | + }else if( pPk && (pTab->aCol[j].colFlags & COLFLAG_PRIMKEY)!=0 ){ |
| 155222 | + chngPk = 1; |
| 155223 | + } |
| 154874 | 155224 | #ifndef SQLITE_OMIT_GENERATED_COLUMNS |
| 154875 | | - else if( pTab->aCol[j].colFlags & COLFLAG_GENERATED ){ |
| 154876 | | - testcase( pTab->aCol[j].colFlags & COLFLAG_VIRTUAL ); |
| 154877 | | - testcase( pTab->aCol[j].colFlags & COLFLAG_STORED ); |
| 154878 | | - sqlite3ErrorMsg(pParse, |
| 154879 | | - "cannot UPDATE generated column \"%s\"", |
| 154880 | | - pTab->aCol[j].zCnName); |
| 154881 | | - goto update_cleanup; |
| 154882 | | - } |
| 155225 | + else if( pTab->aCol[j].colFlags & COLFLAG_GENERATED ){ |
| 155226 | + testcase( pTab->aCol[j].colFlags & COLFLAG_VIRTUAL ); |
| 155227 | + testcase( pTab->aCol[j].colFlags & COLFLAG_STORED ); |
| 155228 | + sqlite3ErrorMsg(pParse, |
| 155229 | + "cannot UPDATE generated column \"%s\"", |
| 155230 | + pTab->aCol[j].zCnName); |
| 155231 | + goto update_cleanup; |
| 155232 | + } |
| 154883 | 155233 | #endif |
| 154884 | | - aXRef[j] = i; |
| 154885 | | - break; |
| 154886 | | - } |
| 154887 | | - } |
| 154888 | | - if( j>=pTab->nCol ){ |
| 155234 | + aXRef[j] = i; |
| 155235 | + }else{ |
| 154889 | 155236 | if( pPk==0 && sqlite3IsRowid(pChanges->a[i].zEName) ){ |
| 154890 | 155237 | j = -1; |
| 154891 | 155238 | chngRowid = 1; |
| 154892 | 155239 | pRowidExpr = pChanges->a[i].pExpr; |
| 154893 | 155240 | iRowidExpr = i; |
| | @@ -156990,24 +157337,25 @@ |
| 156990 | 157337 | |
| 156991 | 157338 | /* A slot for the record has already been allocated in the |
| 156992 | 157339 | ** schema table. We just need to update that slot with all |
| 156993 | 157340 | ** the information we've collected. |
| 156994 | 157341 | ** |
| 156995 | | - ** The VM register number pParse->regRowid holds the rowid of an |
| 157342 | + ** The VM register number pParse->u1.cr.regRowid holds the rowid of an |
| 156996 | 157343 | ** entry in the sqlite_schema table that was created for this vtab |
| 156997 | 157344 | ** by sqlite3StartTable(). |
| 156998 | 157345 | */ |
| 156999 | 157346 | iDb = sqlite3SchemaToIndex(db, pTab->pSchema); |
| 157347 | + assert( pParse->isCreate ); |
| 157000 | 157348 | sqlite3NestedParse(pParse, |
| 157001 | 157349 | "UPDATE %Q." LEGACY_SCHEMA_TABLE " " |
| 157002 | 157350 | "SET type='table', name=%Q, tbl_name=%Q, rootpage=0, sql=%Q " |
| 157003 | 157351 | "WHERE rowid=#%d", |
| 157004 | 157352 | db->aDb[iDb].zDbSName, |
| 157005 | 157353 | pTab->zName, |
| 157006 | 157354 | pTab->zName, |
| 157007 | 157355 | zStmt, |
| 157008 | | - pParse->regRowid |
| 157356 | + pParse->u1.cr.regRowid |
| 157009 | 157357 | ); |
| 157010 | 157358 | v = sqlite3GetVdbe(pParse); |
| 157011 | 157359 | sqlite3ChangeCookie(pParse, iDb); |
| 157012 | 157360 | |
| 157013 | 157361 | sqlite3VdbeAddOp0(v, OP_Expire); |
| | @@ -160161,10 +160509,13 @@ |
| 160161 | 160509 | } |
| 160162 | 160510 | } |
| 160163 | 160511 | } |
| 160164 | 160512 | sqlite3VdbeAddOp2(v, OP_Integer, pLoop->u.vtab.idxNum, iReg); |
| 160165 | 160513 | sqlite3VdbeAddOp2(v, OP_Integer, nConstraint, iReg+1); |
| 160514 | + /* The instruction immediately prior to OP_VFilter must be an OP_Integer |
| 160515 | + ** that sets the "argc" value for xVFilter. This is necessary for |
| 160516 | + ** resolveP2() to work correctly. See tag-20250207a. */ |
| 160166 | 160517 | sqlite3VdbeAddOp4(v, OP_VFilter, iCur, addrNotFound, iReg, |
| 160167 | 160518 | pLoop->u.vtab.idxStr, |
| 160168 | 160519 | pLoop->u.vtab.needFree ? P4_DYNAMIC : P4_STATIC); |
| 160169 | 160520 | VdbeCoverage(v); |
| 160170 | 160521 | pLoop->u.vtab.needFree = 0; |
| | @@ -174215,10 +174566,15 @@ |
| 174215 | 174566 | ** to the original parse.y sources. |
| 174216 | 174567 | */ |
| 174217 | 174568 | |
| 174218 | 174569 | /* #include "sqliteInt.h" */ |
| 174219 | 174570 | |
| 174571 | +/* |
| 174572 | +** Verify that the pParse->isCreate field is set |
| 174573 | +*/ |
| 174574 | +#define ASSERT_IS_CREATE assert(pParse->isCreate) |
| 174575 | + |
| 174220 | 174576 | /* |
| 174221 | 174577 | ** Disable all error recovery processing in the parser push-down |
| 174222 | 174578 | ** automaton. |
| 174223 | 174579 | */ |
| 174224 | 174580 | #define YYNOERRORRECOVERY 1 |
| | @@ -174278,10 +174634,14 @@ |
| 174278 | 174634 | ** shared across database connections. |
| 174279 | 174635 | */ |
| 174280 | 174636 | static void disableLookaside(Parse *pParse){ |
| 174281 | 174637 | sqlite3 *db = pParse->db; |
| 174282 | 174638 | pParse->disableLookaside++; |
| 174639 | +#ifdef SQLITE_DEBUG |
| 174640 | + pParse->isCreate = 1; |
| 174641 | +#endif |
| 174642 | + memset(&pParse->u1.cr, 0, sizeof(pParse->u1.cr)); |
| 174283 | 174643 | DisableLookaside; |
| 174284 | 174644 | } |
| 174285 | 174645 | |
| 174286 | 174646 | #if !defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) \ |
| 174287 | 174647 | && defined(SQLITE_UDL_CAPABLE_PARSER) |
| | @@ -177914,11 +178274,13 @@ |
| 177914 | 178274 | { |
| 177915 | 178275 | sqlite3StartTable(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,yymsp[-4].minor.yy502,0,0,yymsp[-2].minor.yy502); |
| 177916 | 178276 | } |
| 177917 | 178277 | break; |
| 177918 | 178278 | case 14: /* createkw ::= CREATE */ |
| 177919 | | -{disableLookaside(pParse);} |
| 178279 | +{ |
| 178280 | + disableLookaside(pParse); |
| 178281 | +} |
| 177920 | 178282 | break; |
| 177921 | 178283 | case 15: /* ifnotexists ::= */ |
| 177922 | 178284 | case 18: /* temp ::= */ yytestcase(yyruleno==18); |
| 177923 | 178285 | case 47: /* autoinc ::= */ yytestcase(yyruleno==47); |
| 177924 | 178286 | case 62: /* init_deferred_pred_opt ::= */ yytestcase(yyruleno==62); |
| | @@ -178006,11 +178368,11 @@ |
| 178006 | 178368 | yymsp[1].minor.yy0 = yyLookaheadToken; |
| 178007 | 178369 | } |
| 178008 | 178370 | break; |
| 178009 | 178371 | case 32: /* ccons ::= CONSTRAINT nm */ |
| 178010 | 178372 | case 67: /* tcons ::= CONSTRAINT nm */ yytestcase(yyruleno==67); |
| 178011 | | -{pParse->constraintName = yymsp[0].minor.yy0;} |
| 178373 | +{ASSERT_IS_CREATE; pParse->u1.cr.constraintName = yymsp[0].minor.yy0;} |
| 178012 | 178374 | break; |
| 178013 | 178375 | case 33: /* ccons ::= DEFAULT scantok term */ |
| 178014 | 178376 | {sqlite3AddDefaultValue(pParse,yymsp[0].minor.yy590,yymsp[-1].minor.yy0.z,&yymsp[-1].minor.yy0.z[yymsp[-1].minor.yy0.n]);} |
| 178015 | 178377 | break; |
| 178016 | 178378 | case 34: /* ccons ::= DEFAULT LP expr RP */ |
| | @@ -178116,11 +178478,11 @@ |
| 178116 | 178478 | break; |
| 178117 | 178479 | case 64: /* init_deferred_pred_opt ::= INITIALLY IMMEDIATE */ |
| 178118 | 178480 | {yymsp[-1].minor.yy502 = 0;} |
| 178119 | 178481 | break; |
| 178120 | 178482 | case 66: /* tconscomma ::= COMMA */ |
| 178121 | | -{pParse->constraintName.n = 0;} |
| 178483 | +{ASSERT_IS_CREATE; pParse->u1.cr.constraintName.n = 0;} |
| 178122 | 178484 | break; |
| 178123 | 178485 | case 68: /* tcons ::= PRIMARY KEY LP sortlist autoinc RP onconf */ |
| 178124 | 178486 | {sqlite3AddPrimaryKey(pParse,yymsp[-3].minor.yy402,yymsp[0].minor.yy502,yymsp[-2].minor.yy502,0);} |
| 178125 | 178487 | break; |
| 178126 | 178488 | case 69: /* tcons ::= UNIQUE LP sortlist RP onconf */ |
| | @@ -179009,10 +179371,14 @@ |
| 179009 | 179371 | break; |
| 179010 | 179372 | case 261: /* trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */ |
| 179011 | 179373 | { |
| 179012 | 179374 | sqlite3BeginTrigger(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0, yymsp[-5].minor.yy502, yymsp[-4].minor.yy28.a, yymsp[-4].minor.yy28.b, yymsp[-2].minor.yy563, yymsp[0].minor.yy590, yymsp[-10].minor.yy502, yymsp[-8].minor.yy502); |
| 179013 | 179375 | yymsp[-10].minor.yy0 = (yymsp[-6].minor.yy0.n==0?yymsp[-7].minor.yy0:yymsp[-6].minor.yy0); /*A-overwrites-T*/ |
| 179376 | +#ifdef SQLITE_DEBUG |
| 179377 | + assert( pParse->isCreate ); /* Set by createkw reduce action */ |
| 179378 | + pParse->isCreate = 0; /* But, should not be set for CREATE TRIGGER */ |
| 179379 | +#endif |
| 179014 | 179380 | } |
| 179015 | 179381 | break; |
| 179016 | 179382 | case 262: /* trigger_time ::= BEFORE|AFTER */ |
| 179017 | 179383 | { yymsp[0].minor.yy502 = yymsp[0].major; /*A-overwrites-X*/ } |
| 179018 | 179384 | break; |
| | @@ -183305,10 +183671,13 @@ |
| 183305 | 183671 | sqlite3_mutex_enter(db->mutex); |
| 183306 | 183672 | db->busyHandler.xBusyHandler = xBusy; |
| 183307 | 183673 | db->busyHandler.pBusyArg = pArg; |
| 183308 | 183674 | db->busyHandler.nBusy = 0; |
| 183309 | 183675 | db->busyTimeout = 0; |
| 183676 | +#ifdef SQLITE_ENABLE_SETLK_TIMEOUT |
| 183677 | + db->setlkTimeout = 0; |
| 183678 | +#endif |
| 183310 | 183679 | sqlite3_mutex_leave(db->mutex); |
| 183311 | 183680 | return SQLITE_OK; |
| 183312 | 183681 | } |
| 183313 | 183682 | |
| 183314 | 183683 | #ifndef SQLITE_OMIT_PROGRESS_CALLBACK |
| | @@ -183354,15 +183723,46 @@ |
| 183354 | 183723 | #endif |
| 183355 | 183724 | if( ms>0 ){ |
| 183356 | 183725 | sqlite3_busy_handler(db, (int(*)(void*,int))sqliteDefaultBusyCallback, |
| 183357 | 183726 | (void*)db); |
| 183358 | 183727 | db->busyTimeout = ms; |
| 183728 | +#ifdef SQLITE_ENABLE_SETLK_TIMEOUT |
| 183729 | + db->setlkTimeout = ms; |
| 183730 | +#endif |
| 183359 | 183731 | }else{ |
| 183360 | 183732 | sqlite3_busy_handler(db, 0, 0); |
| 183361 | 183733 | } |
| 183362 | 183734 | return SQLITE_OK; |
| 183363 | 183735 | } |
| 183736 | + |
| 183737 | +/* |
| 183738 | +** Set the setlk timeout value. |
| 183739 | +*/ |
| 183740 | +SQLITE_API int sqlite3_setlk_timeout(sqlite3 *db, int ms, int flags){ |
| 183741 | +#ifdef SQLITE_ENABLE_SETLK_TIMEOUT |
| 183742 | + int iDb; |
| 183743 | + int bBOC = ((flags & SQLITE_SETLK_BLOCK_ON_CONNECT) ? 1 : 0); |
| 183744 | +#endif |
| 183745 | +#ifdef SQLITE_ENABLE_API_ARMOR |
| 183746 | + if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; |
| 183747 | +#endif |
| 183748 | + if( ms<-1 ) return SQLITE_RANGE; |
| 183749 | +#ifdef SQLITE_ENABLE_SETLK_TIMEOUT |
| 183750 | + db->setlkTimeout = ms; |
| 183751 | + db->setlkFlags = flags; |
| 183752 | + sqlite3BtreeEnterAll(db); |
| 183753 | + for(iDb=0; iDb<db->nDb; iDb++){ |
| 183754 | + Btree *pBt = db->aDb[iDb].pBt; |
| 183755 | + if( pBt ){ |
| 183756 | + sqlite3_file *fd = sqlite3PagerFile(sqlite3BtreePager(pBt)); |
| 183757 | + sqlite3OsFileControlHint(fd, SQLITE_FCNTL_BLOCK_ON_CONNECT, (void*)&bBOC); |
| 183758 | + } |
| 183759 | + } |
| 183760 | + sqlite3BtreeLeaveAll(db); |
| 183761 | +#endif |
| 183762 | + return SQLITE_OK; |
| 183763 | +} |
| 183364 | 183764 | |
| 183365 | 183765 | /* |
| 183366 | 183766 | ** Cause any pending operation to stop at its earliest opportunity. |
| 183367 | 183767 | */ |
| 183368 | 183768 | SQLITE_API void sqlite3_interrupt(sqlite3 *db){ |
| | @@ -185479,17 +185879,14 @@ |
| 185479 | 185879 | |
| 185480 | 185880 | /* Find the column for which info is requested */ |
| 185481 | 185881 | if( zColumnName==0 ){ |
| 185482 | 185882 | /* Query for existence of table only */ |
| 185483 | 185883 | }else{ |
| 185484 | | - for(iCol=0; iCol<pTab->nCol; iCol++){ |
| 185884 | + iCol = sqlite3ColumnIndex(pTab, zColumnName); |
| 185885 | + if( iCol>=0 ){ |
| 185485 | 185886 | pCol = &pTab->aCol[iCol]; |
| 185486 | | - if( 0==sqlite3StrICmp(pCol->zCnName, zColumnName) ){ |
| 185487 | | - break; |
| 185488 | | - } |
| 185489 | | - } |
| 185490 | | - if( iCol==pTab->nCol ){ |
| 185887 | + }else{ |
| 185491 | 185888 | if( HasRowid(pTab) && sqlite3IsRowid(zColumnName) ){ |
| 185492 | 185889 | iCol = pTab->iPKey; |
| 185493 | 185890 | pCol = iCol>=0 ? &pTab->aCol[iCol] : 0; |
| 185494 | 185891 | }else{ |
| 185495 | 185892 | pTab = 0; |
| | @@ -208697,14 +209094,11 @@ |
| 208697 | 209094 | */ |
| 208698 | 209095 | static u32 jsonbPayloadSize(const JsonParse *pParse, u32 i, u32 *pSz){ |
| 208699 | 209096 | u8 x; |
| 208700 | 209097 | u32 sz; |
| 208701 | 209098 | u32 n; |
| 208702 | | - if( NEVER(i>pParse->nBlob) ){ |
| 208703 | | - *pSz = 0; |
| 208704 | | - return 0; |
| 208705 | | - } |
| 209099 | + assert( i<=pParse->nBlob ); |
| 208706 | 209100 | x = pParse->aBlob[i]>>4; |
| 208707 | 209101 | if( x<=11 ){ |
| 208708 | 209102 | sz = x; |
| 208709 | 209103 | n = 1; |
| 208710 | 209104 | }else if( x==12 ){ |
| | @@ -208744,12 +209138,12 @@ |
| 208744 | 209138 | n = 9; |
| 208745 | 209139 | } |
| 208746 | 209140 | if( (i64)i+sz+n > pParse->nBlob |
| 208747 | 209141 | && (i64)i+sz+n > pParse->nBlob-pParse->delta |
| 208748 | 209142 | ){ |
| 208749 | | - sz = 0; |
| 208750 | | - n = 0; |
| 209143 | + *pSz = 0; |
| 209144 | + return 0; |
| 208751 | 209145 | } |
| 208752 | 209146 | *pSz = sz; |
| 208753 | 209147 | return n; |
| 208754 | 209148 | } |
| 208755 | 209149 | |
| | @@ -208842,13 +209236,16 @@ |
| 208842 | 209236 | } |
| 208843 | 209237 | break; |
| 208844 | 209238 | } |
| 208845 | 209239 | case JSONB_TEXT: |
| 208846 | 209240 | case JSONB_TEXTJ: { |
| 208847 | | - jsonAppendChar(pOut, '"'); |
| 208848 | | - jsonAppendRaw(pOut, (const char*)&pParse->aBlob[i+n], sz); |
| 208849 | | - jsonAppendChar(pOut, '"'); |
| 209241 | + if( pOut->nUsed+sz+2<=pOut->nAlloc || jsonStringGrow(pOut, sz+2)==0 ){ |
| 209242 | + pOut->zBuf[pOut->nUsed] = '"'; |
| 209243 | + memcpy(pOut->zBuf+pOut->nUsed+1,(const char*)&pParse->aBlob[i+n],sz); |
| 209244 | + pOut->zBuf[pOut->nUsed+sz+1] = '"'; |
| 209245 | + pOut->nUsed += sz+2; |
| 209246 | + } |
| 208850 | 209247 | break; |
| 208851 | 209248 | } |
| 208852 | 209249 | case JSONB_TEXT5: { |
| 208853 | 209250 | const char *zIn; |
| 208854 | 209251 | u32 k; |
| | @@ -255870,11 +256267,11 @@ |
| 255870 | 256267 | int nArg, /* Number of args */ |
| 255871 | 256268 | sqlite3_value **apUnused /* Function arguments */ |
| 255872 | 256269 | ){ |
| 255873 | 256270 | assert( nArg==0 ); |
| 255874 | 256271 | UNUSED_PARAM2(nArg, apUnused); |
| 255875 | | - sqlite3_result_text(pCtx, "fts5: 2025-02-06 11:55:18 4a7dd425dc2a0e5082a9049c9b4a9d4f199a71583d014c24b4cfe276c5a77cde", -1, SQLITE_TRANSIENT); |
| 256272 | + sqlite3_result_text(pCtx, "fts5: 2025-02-11 17:10:46 e5ec5bb9f4dc3e02db7ab0e49686f47617af75d3f7d4ab23288a1aea4a693e59", -1, SQLITE_TRANSIENT); |
| 255876 | 256273 | } |
| 255877 | 256274 | |
| 255878 | 256275 | /* |
| 255879 | 256276 | ** Implementation of fts5_locale(LOCALE, TEXT) function. |
| 255880 | 256277 | ** |
| 255881 | 256278 | |