| | @@ -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 | | -** 57caa3136d1bfca06e4f2285734a4977b8d3 with changes in files: |
| 21 | +** e6784af6d50f715338ae3218fc8ba1b89488 with changes in files: |
| 22 | 22 | ** |
| 23 | 23 | ** |
| 24 | 24 | */ |
| 25 | 25 | #ifndef SQLITE_AMALGAMATION |
| 26 | 26 | #define SQLITE_CORE 1 |
| | @@ -465,11 +465,11 @@ |
| 465 | 465 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 466 | 466 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 467 | 467 | */ |
| 468 | 468 | #define SQLITE_VERSION "3.50.0" |
| 469 | 469 | #define SQLITE_VERSION_NUMBER 3050000 |
| 470 | | -#define SQLITE_SOURCE_ID "2025-02-18 01:16:26 57caa3136d1bfca06e4f2285734a4977b8d3fa1f75bf87453b975867e9de38fc" |
| 470 | +#define SQLITE_SOURCE_ID "2025-02-25 18:10:47 e6784af6d50f715338ae3218fc8ba1b894883c27d797f0b7fd2625cac17d9cd7" |
| 471 | 471 | |
| 472 | 472 | /* |
| 473 | 473 | ** CAPI3REF: Run-Time Library Version Numbers |
| 474 | 474 | ** KEYWORDS: sqlite3_version sqlite3_sourceid |
| 475 | 475 | ** |
| | @@ -1479,10 +1479,16 @@ |
| 1479 | 1479 | ** to block for up to M milliseconds before failing when attempting to |
| 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 | +** |
| 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 a SHARED lock to connect to a wal mode database. |
| 1488 | +** This is used to implement the functionality associated with |
| 1489 | +** SQLITE_SETLK_BLOCK_ON_CONNECT. |
| 1484 | 1490 | ** |
| 1485 | 1491 | ** <li>[[SQLITE_FCNTL_DATA_VERSION]] |
| 1486 | 1492 | ** The [SQLITE_FCNTL_DATA_VERSION] opcode is used to detect changes to |
| 1487 | 1493 | ** a database file. The argument is a pointer to a 32-bit unsigned integer. |
| 1488 | 1494 | ** The "data version" for the pager is written into the pointer. The |
| | @@ -1576,10 +1582,11 @@ |
| 1576 | 1582 | #define SQLITE_FCNTL_CKPT_START 39 |
| 1577 | 1583 | #define SQLITE_FCNTL_EXTERNAL_READER 40 |
| 1578 | 1584 | #define SQLITE_FCNTL_CKSM_FILE 41 |
| 1579 | 1585 | #define SQLITE_FCNTL_RESET_CACHE 42 |
| 1580 | 1586 | #define SQLITE_FCNTL_NULL_IO 43 |
| 1587 | +#define SQLITE_FCNTL_BLOCK_ON_CONNECT 44 |
| 1581 | 1588 | |
| 1582 | 1589 | /* deprecated names */ |
| 1583 | 1590 | #define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE |
| 1584 | 1591 | #define SQLITE_SET_LOCKPROXYFILE SQLITE_FCNTL_SET_LOCKPROXYFILE |
| 1585 | 1592 | #define SQLITE_LAST_ERRNO SQLITE_FCNTL_LAST_ERRNO |
| | @@ -3332,10 +3339,48 @@ |
| 3332 | 3339 | ** |
| 3333 | 3340 | ** See also: [PRAGMA busy_timeout] |
| 3334 | 3341 | */ |
| 3335 | 3342 | SQLITE_API int sqlite3_busy_timeout(sqlite3*, int ms); |
| 3336 | 3343 | |
| 3344 | +/* |
| 3345 | +** CAPI3REF: Set the Setlk Timeout |
| 3346 | +** METHOD: sqlite3 |
| 3347 | +** |
| 3348 | +** This routine is only useful in SQLITE_ENABLE_SETLK_TIMEOUT builds. If |
| 3349 | +** the VFS supports blocking locks, it sets the timeout in ms used by |
| 3350 | +** eligible locks taken on wal mode databases by the specified database |
| 3351 | +** handle. In non-SQLITE_ENABLE_SETLK_TIMEOUT builds, or if the VFS does |
| 3352 | +** not support blocking locks, this function is a no-op. |
| 3353 | +** |
| 3354 | +** Passing 0 to this function disables blocking locks altogether. Passing |
| 3355 | +** -1 to this function requests that the VFS blocks for a long time - |
| 3356 | +** indefinitely if possible. The results of passing any other negative value |
| 3357 | +** are undefined. |
| 3358 | +** |
| 3359 | +** Internally, each SQLite database handle store two timeout values - the |
| 3360 | +** busy-timeout (used for rollback mode databases, or if the VFS does not |
| 3361 | +** support blocking locks) and the setlk-timeout (used for blocking locks |
| 3362 | +** on wal-mode databases). The sqlite3_busy_timeout() method sets both |
| 3363 | +** values, this function sets only the setlk-timeout value. Therefore, |
| 3364 | +** to configure separate busy-timeout and setlk-timeout values for a single |
| 3365 | +** database handle, call sqlite3_busy_timeout() followed by this function. |
| 3366 | +** |
| 3367 | +** Whenever the number of connections to a wal mode database falls from |
| 3368 | +** 1 to 0, the last connection takes an exclusive lock on the database, |
| 3369 | +** then checkpoints and deletes the wal file. While it is doing this, any |
| 3370 | +** new connection that tries to read from the database fails with an |
| 3371 | +** SQLITE_BUSY error. Or, if the SQLITE_SETLK_BLOCK_ON_CONNECT flag is |
| 3372 | +** passed to this API, the new connection blocks until the exclusive lock |
| 3373 | +** has been released. |
| 3374 | +*/ |
| 3375 | +SQLITE_API int sqlite3_setlk_timeout(sqlite3*, int ms, int flags); |
| 3376 | + |
| 3377 | +/* |
| 3378 | +** CAPI3REF: Flags for sqlite3_setlk_timeout() |
| 3379 | +*/ |
| 3380 | +#define SQLITE_SETLK_BLOCK_ON_CONNECT 0x01 |
| 3381 | + |
| 3337 | 3382 | /* |
| 3338 | 3383 | ** CAPI3REF: Convenience Routines For Running Queries |
| 3339 | 3384 | ** METHOD: sqlite3 |
| 3340 | 3385 | ** |
| 3341 | 3386 | ** This is a legacy interface that is preserved for backwards compatibility. |
| | @@ -14097,18 +14142,26 @@ |
| 14097 | 14142 | ** * Terms in the SET clause of an UPDATE statement |
| 14098 | 14143 | ** * Terms in the result set of a SELECT statement |
| 14099 | 14144 | ** * Terms in the GROUP BY or ORDER BY clauses of a SELECT statement. |
| 14100 | 14145 | ** * Terms in the VALUES clause of an INSERT statement |
| 14101 | 14146 | ** |
| 14102 | | -** The hard upper limit here is 32676. Most database people will |
| 14147 | +** The hard upper limit here is 32767. Most database people will |
| 14103 | 14148 | ** tell you that in a well-normalized database, you usually should |
| 14104 | 14149 | ** not have more than a dozen or so columns in any table. And if |
| 14105 | 14150 | ** that is the case, there is no point in having more than a few |
| 14106 | 14151 | ** dozen values in any of the other situations described above. |
| 14152 | +** |
| 14153 | +** An index can only have SQLITE_MAX_COLUMN columns from the user |
| 14154 | +** point of view, but the underlying b-tree that implements the index |
| 14155 | +** might have up to twice as many columns in a WITHOUT ROWID table, |
| 14156 | +** since must also store the primary key at the end. Hence the |
| 14157 | +** column count for Index is u16 instead of i16. |
| 14107 | 14158 | */ |
| 14108 | | -#ifndef SQLITE_MAX_COLUMN |
| 14159 | +#if !defined(SQLITE_MAX_COLUMN) |
| 14109 | 14160 | # define SQLITE_MAX_COLUMN 2000 |
| 14161 | +#elif SQLITE_MAX_COLUMN>32767 |
| 14162 | +# error SQLITE_MAX_COLUMN may not exceed 32767 |
| 14110 | 14163 | #endif |
| 14111 | 14164 | |
| 14112 | 14165 | /* |
| 14113 | 14166 | ** The maximum length of a single SQL statement in bytes. |
| 14114 | 14167 | ** |
| | @@ -18076,10 +18129,14 @@ |
| 18076 | 18129 | BusyHandler busyHandler; /* Busy callback */ |
| 18077 | 18130 | Db aDbStatic[2]; /* Static space for the 2 default backends */ |
| 18078 | 18131 | Savepoint *pSavepoint; /* List of active savepoints */ |
| 18079 | 18132 | int nAnalysisLimit; /* Number of index rows to ANALYZE */ |
| 18080 | 18133 | int busyTimeout; /* Busy handler timeout, in msec */ |
| 18134 | +#ifdef SQLITE_ENABLE_SETLK_TIMEOUT |
| 18135 | + int setlkTimeout; /* Blocking lock timeout, in msec. -1 -> inf. */ |
| 18136 | + int setlkFlags; /* Flags passed to setlk_timeout() */ |
| 18137 | +#endif |
| 18081 | 18138 | int nSavepoint; /* Number of non-transaction savepoints */ |
| 18082 | 18139 | int nStatement; /* Number of nested statement-transactions */ |
| 18083 | 18140 | i64 nDeferredCons; /* Net deferred constraints this transaction. */ |
| 18084 | 18141 | i64 nDeferredImmCons; /* Net deferred immediate constraints */ |
| 18085 | 18142 | int *pnBytesFreed; /* If not NULL, increment this in DbFree() */ |
| | @@ -19074,11 +19131,11 @@ |
| 19074 | 19131 | Expr *pPartIdxWhere; /* WHERE clause for partial indices */ |
| 19075 | 19132 | ExprList *aColExpr; /* Column expressions */ |
| 19076 | 19133 | Pgno tnum; /* DB Page containing root of this index */ |
| 19077 | 19134 | LogEst szIdxRow; /* Estimated average row size in bytes */ |
| 19078 | 19135 | u16 nKeyCol; /* Number of columns forming the key */ |
| 19079 | | - u16 nColumn; /* Number of columns stored in the index */ |
| 19136 | + u16 nColumn; /* Nr columns in btree. Can be 2*Table.nCol */ |
| 19080 | 19137 | u8 onError; /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */ |
| 19081 | 19138 | unsigned idxType:2; /* 0:Normal 1:UNIQUE, 2:PRIMARY KEY, 3:IPK */ |
| 19082 | 19139 | unsigned bUnordered:1; /* Use this index for == or IN queries only */ |
| 19083 | 19140 | unsigned uniqNotNull:1; /* True if UNIQUE and NOT NULL for all columns */ |
| 19084 | 19141 | unsigned isResized:1; /* True if resizeIndexObject() has been called */ |
| | @@ -19412,14 +19469,14 @@ |
| 19412 | 19469 | #define EP_Propagate (EP_Collate|EP_Subquery|EP_HasFunc) |
| 19413 | 19470 | |
| 19414 | 19471 | /* Macros can be used to test, set, or clear bits in the |
| 19415 | 19472 | ** Expr.flags field. |
| 19416 | 19473 | */ |
| 19417 | | -#define ExprHasProperty(E,P) (((E)->flags&(P))!=0) |
| 19418 | | -#define ExprHasAllProperty(E,P) (((E)->flags&(P))==(P)) |
| 19419 | | -#define ExprSetProperty(E,P) (E)->flags|=(P) |
| 19420 | | -#define ExprClearProperty(E,P) (E)->flags&=~(P) |
| 19474 | +#define ExprHasProperty(E,P) (((E)->flags&(u32)(P))!=0) |
| 19475 | +#define ExprHasAllProperty(E,P) (((E)->flags&(u32)(P))==(u32)(P)) |
| 19476 | +#define ExprSetProperty(E,P) (E)->flags|=(u32)(P) |
| 19477 | +#define ExprClearProperty(E,P) (E)->flags&=~(u32)(P) |
| 19421 | 19478 | #define ExprAlwaysTrue(E) (((E)->flags&(EP_OuterON|EP_IsTrue))==EP_IsTrue) |
| 19422 | 19479 | #define ExprAlwaysFalse(E) (((E)->flags&(EP_OuterON|EP_IsFalse))==EP_IsFalse) |
| 19423 | 19480 | #define ExprIsFullSize(E) (((E)->flags&(EP_Reduced|EP_TokenOnly))==0) |
| 19424 | 19481 | |
| 19425 | 19482 | /* Macros used to ensure that the correct members of unions are accessed |
| | @@ -21223,11 +21280,11 @@ |
| 21223 | 21280 | SQLITE_PRIVATE int sqlite3ColumnsFromExprList(Parse*,ExprList*,i16*,Column**); |
| 21224 | 21281 | SQLITE_PRIVATE void sqlite3SubqueryColumnTypes(Parse*,Table*,Select*,char); |
| 21225 | 21282 | SQLITE_PRIVATE Table *sqlite3ResultSetOfSelect(Parse*,Select*,char); |
| 21226 | 21283 | SQLITE_PRIVATE void sqlite3OpenSchemaTable(Parse *, int); |
| 21227 | 21284 | SQLITE_PRIVATE Index *sqlite3PrimaryKeyIndex(Table*); |
| 21228 | | -SQLITE_PRIVATE i16 sqlite3TableColumnToIndex(Index*, i16); |
| 21285 | +SQLITE_PRIVATE int sqlite3TableColumnToIndex(Index*, int); |
| 21229 | 21286 | #ifdef SQLITE_OMIT_GENERATED_COLUMNS |
| 21230 | 21287 | # define sqlite3TableColumnToStorage(T,X) (X) /* No-op pass-through */ |
| 21231 | 21288 | # define sqlite3StorageColumnToTable(T,X) (X) /* No-op pass-through */ |
| 21232 | 21289 | #else |
| 21233 | 21290 | SQLITE_PRIVATE i16 sqlite3TableColumnToStorage(Table*, i16); |
| | @@ -21321,11 +21378,11 @@ |
| 21321 | 21378 | SQLITE_PRIVATE void sqlite3SrcListShiftJoinType(Parse*,SrcList*); |
| 21322 | 21379 | SQLITE_PRIVATE void sqlite3SrcListAssignCursors(Parse*, SrcList*); |
| 21323 | 21380 | SQLITE_PRIVATE void sqlite3IdListDelete(sqlite3*, IdList*); |
| 21324 | 21381 | SQLITE_PRIVATE void sqlite3ClearOnOrUsing(sqlite3*, OnOrUsing*); |
| 21325 | 21382 | SQLITE_PRIVATE void sqlite3SrcListDelete(sqlite3*, SrcList*); |
| 21326 | | -SQLITE_PRIVATE Index *sqlite3AllocateIndexObject(sqlite3*,i16,int,char**); |
| 21383 | +SQLITE_PRIVATE Index *sqlite3AllocateIndexObject(sqlite3*,int,int,char**); |
| 21327 | 21384 | SQLITE_PRIVATE void sqlite3CreateIndex(Parse*,Token*,Token*,SrcList*,ExprList*,int,Token*, |
| 21328 | 21385 | Expr*, int, int, u8); |
| 21329 | 21386 | SQLITE_PRIVATE void sqlite3DropIndex(Parse*, SrcList*, int); |
| 21330 | 21387 | SQLITE_PRIVATE int sqlite3Select(Parse*, Select*, SelectDest*); |
| 21331 | 21388 | SQLITE_PRIVATE Select *sqlite3SelectNew(Parse*,ExprList*,SrcList*,Expr*,ExprList*, |
| | @@ -21457,11 +21514,12 @@ |
| 21457 | 21514 | SQLITE_PRIVATE IdList *sqlite3IdListDup(sqlite3*,const IdList*); |
| 21458 | 21515 | SQLITE_PRIVATE Select *sqlite3SelectDup(sqlite3*,const Select*,int); |
| 21459 | 21516 | SQLITE_PRIVATE FuncDef *sqlite3FunctionSearch(int,const char*); |
| 21460 | 21517 | SQLITE_PRIVATE void sqlite3InsertBuiltinFuncs(FuncDef*,int); |
| 21461 | 21518 | SQLITE_PRIVATE FuncDef *sqlite3FindFunction(sqlite3*,const char*,int,u8,u8); |
| 21462 | | -SQLITE_PRIVATE void sqlite3QuoteValue(StrAccum*,sqlite3_value*); |
| 21519 | +SQLITE_PRIVATE void sqlite3QuoteValue(StrAccum*,sqlite3_value*,int); |
| 21520 | +SQLITE_PRIVATE int sqlite3AppendOneUtf8Character(char*, u32); |
| 21463 | 21521 | SQLITE_PRIVATE void sqlite3RegisterBuiltinFunctions(void); |
| 21464 | 21522 | SQLITE_PRIVATE void sqlite3RegisterDateTimeFunctions(void); |
| 21465 | 21523 | SQLITE_PRIVATE void sqlite3RegisterJsonFunctions(void); |
| 21466 | 21524 | SQLITE_PRIVATE void sqlite3RegisterPerConnectionBuiltinFunctions(sqlite3*); |
| 21467 | 21525 | #if !defined(SQLITE_OMIT_VIRTUALTABLE) && !defined(SQLITE_OMIT_JSON) |
| | @@ -22557,10 +22615,13 @@ |
| 22557 | 22615 | #ifdef SQLITE_ENABLE_RTREE |
| 22558 | 22616 | "ENABLE_RTREE", |
| 22559 | 22617 | #endif |
| 22560 | 22618 | #ifdef SQLITE_ENABLE_SESSION |
| 22561 | 22619 | "ENABLE_SESSION", |
| 22620 | +#endif |
| 22621 | +#ifdef SQLITE_ENABLE_SETLK_TIMEOUT |
| 22622 | + "ENABLE_SETLK_TIMEOUT", |
| 22562 | 22623 | #endif |
| 22563 | 22624 | #ifdef SQLITE_ENABLE_SNAPSHOT |
| 22564 | 22625 | "ENABLE_SNAPSHOT", |
| 22565 | 22626 | #endif |
| 22566 | 22627 | #ifdef SQLITE_ENABLE_SORTER_REFERENCES |
| | @@ -24372,12 +24433,13 @@ |
| 24372 | 24433 | u32 nFree = countLookasideSlots(db->lookaside.pFree); |
| 24373 | 24434 | #ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE |
| 24374 | 24435 | nInit += countLookasideSlots(db->lookaside.pSmallInit); |
| 24375 | 24436 | nFree += countLookasideSlots(db->lookaside.pSmallFree); |
| 24376 | 24437 | #endif /* SQLITE_OMIT_TWOSIZE_LOOKASIDE */ |
| 24377 | | - if( pHighwater ) *pHighwater = db->lookaside.nSlot - nInit; |
| 24378 | | - return db->lookaside.nSlot - (nInit+nFree); |
| 24438 | + assert( db->lookaside.nSlot >= nInit+nFree ); |
| 24439 | + if( pHighwater ) *pHighwater = (int)(db->lookaside.nSlot - nInit); |
| 24440 | + return (int)(db->lookaside.nSlot - (nInit+nFree)); |
| 24379 | 24441 | } |
| 24380 | 24442 | |
| 24381 | 24443 | /* |
| 24382 | 24444 | ** Query status information for a single database connection |
| 24383 | 24445 | */ |
| | @@ -24426,11 +24488,11 @@ |
| 24426 | 24488 | testcase( op==SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE ); |
| 24427 | 24489 | testcase( op==SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL ); |
| 24428 | 24490 | assert( (op-SQLITE_DBSTATUS_LOOKASIDE_HIT)>=0 ); |
| 24429 | 24491 | assert( (op-SQLITE_DBSTATUS_LOOKASIDE_HIT)<3 ); |
| 24430 | 24492 | *pCurrent = 0; |
| 24431 | | - *pHighwater = db->lookaside.anStat[op - SQLITE_DBSTATUS_LOOKASIDE_HIT]; |
| 24493 | + *pHighwater = (int)db->lookaside.anStat[op-SQLITE_DBSTATUS_LOOKASIDE_HIT]; |
| 24432 | 24494 | if( resetFlag ){ |
| 24433 | 24495 | db->lookaside.anStat[op - SQLITE_DBSTATUS_LOOKASIDE_HIT] = 0; |
| 24434 | 24496 | } |
| 24435 | 24497 | break; |
| 24436 | 24498 | } |
| | @@ -31541,21 +31603,21 @@ |
| 31541 | 31603 | #define etSTRING 5 /* Strings. %s */ |
| 31542 | 31604 | #define etDYNSTRING 6 /* Dynamically allocated strings. %z */ |
| 31543 | 31605 | #define etPERCENT 7 /* Percent symbol. %% */ |
| 31544 | 31606 | #define etCHARX 8 /* Characters. %c */ |
| 31545 | 31607 | /* The rest are extensions, not normally found in printf() */ |
| 31546 | | -#define etSQLESCAPE 9 /* Strings with '\'' doubled. %q */ |
| 31547 | | -#define etSQLESCAPE2 10 /* Strings with '\'' doubled and enclosed in '', |
| 31548 | | - NULL pointers replaced by SQL NULL. %Q */ |
| 31549 | | -#define etTOKEN 11 /* a pointer to a Token structure */ |
| 31550 | | -#define etSRCITEM 12 /* a pointer to a SrcItem */ |
| 31551 | | -#define etPOINTER 13 /* The %p conversion */ |
| 31552 | | -#define etSQLESCAPE3 14 /* %w -> Strings with '\"' doubled */ |
| 31553 | | -#define etORDINAL 15 /* %r -> 1st, 2nd, 3rd, 4th, etc. English only */ |
| 31554 | | -#define etDECIMAL 16 /* %d or %u, but not %x, %o */ |
| 31555 | | - |
| 31556 | | -#define etINVALID 17 /* Any unrecognized conversion type */ |
| 31608 | +#define etESCAPE_q 9 /* Strings with '\'' doubled. %q */ |
| 31609 | +#define etESCAPE_Q 10 /* Strings with '\'' doubled and enclosed in '', |
| 31610 | + NULL pointers replaced by SQL NULL. %Q */ |
| 31611 | +#define etTOKEN 11 /* a pointer to a Token structure */ |
| 31612 | +#define etSRCITEM 12 /* a pointer to a SrcItem */ |
| 31613 | +#define etPOINTER 13 /* The %p conversion */ |
| 31614 | +#define etESCAPE_w 14 /* %w -> Strings with '\"' doubled */ |
| 31615 | +#define etORDINAL 15 /* %r -> 1st, 2nd, 3rd, 4th, etc. English only */ |
| 31616 | +#define etDECIMAL 16 /* %d or %u, but not %x, %o */ |
| 31617 | + |
| 31618 | +#define etINVALID 17 /* Any unrecognized conversion type */ |
| 31557 | 31619 | |
| 31558 | 31620 | |
| 31559 | 31621 | /* |
| 31560 | 31622 | ** An "etByte" is an 8-bit unsigned value. |
| 31561 | 31623 | */ |
| | @@ -31590,13 +31652,13 @@ |
| 31590 | 31652 | static const et_info fmtinfo[] = { |
| 31591 | 31653 | { 'd', 10, 1, etDECIMAL, 0, 0 }, |
| 31592 | 31654 | { 's', 0, 4, etSTRING, 0, 0 }, |
| 31593 | 31655 | { 'g', 0, 1, etGENERIC, 30, 0 }, |
| 31594 | 31656 | { 'z', 0, 4, etDYNSTRING, 0, 0 }, |
| 31595 | | - { 'q', 0, 4, etSQLESCAPE, 0, 0 }, |
| 31596 | | - { 'Q', 0, 4, etSQLESCAPE2, 0, 0 }, |
| 31597 | | - { 'w', 0, 4, etSQLESCAPE3, 0, 0 }, |
| 31657 | + { 'q', 0, 4, etESCAPE_q, 0, 0 }, |
| 31658 | + { 'Q', 0, 4, etESCAPE_Q, 0, 0 }, |
| 31659 | + { 'w', 0, 4, etESCAPE_w, 0, 0 }, |
| 31598 | 31660 | { 'c', 0, 0, etCHARX, 0, 0 }, |
| 31599 | 31661 | { 'o', 8, 0, etRADIX, 0, 2 }, |
| 31600 | 31662 | { 'u', 10, 0, etDECIMAL, 0, 0 }, |
| 31601 | 31663 | { 'x', 16, 0, etRADIX, 16, 1 }, |
| 31602 | 31664 | { 'X', 16, 0, etRADIX, 0, 4 }, |
| | @@ -32189,29 +32251,11 @@ |
| 32189 | 32251 | }else{ |
| 32190 | 32252 | buf[0] = 0; |
| 32191 | 32253 | } |
| 32192 | 32254 | }else{ |
| 32193 | 32255 | unsigned int ch = va_arg(ap,unsigned int); |
| 32194 | | - if( ch<0x00080 ){ |
| 32195 | | - buf[0] = ch & 0xff; |
| 32196 | | - length = 1; |
| 32197 | | - }else if( ch<0x00800 ){ |
| 32198 | | - buf[0] = 0xc0 + (u8)((ch>>6)&0x1f); |
| 32199 | | - buf[1] = 0x80 + (u8)(ch & 0x3f); |
| 32200 | | - length = 2; |
| 32201 | | - }else if( ch<0x10000 ){ |
| 32202 | | - buf[0] = 0xe0 + (u8)((ch>>12)&0x0f); |
| 32203 | | - buf[1] = 0x80 + (u8)((ch>>6) & 0x3f); |
| 32204 | | - buf[2] = 0x80 + (u8)(ch & 0x3f); |
| 32205 | | - length = 3; |
| 32206 | | - }else{ |
| 32207 | | - buf[0] = 0xf0 + (u8)((ch>>18) & 0x07); |
| 32208 | | - buf[1] = 0x80 + (u8)((ch>>12) & 0x3f); |
| 32209 | | - buf[2] = 0x80 + (u8)((ch>>6) & 0x3f); |
| 32210 | | - buf[3] = 0x80 + (u8)(ch & 0x3f); |
| 32211 | | - length = 4; |
| 32212 | | - } |
| 32256 | + length = sqlite3AppendOneUtf8Character(buf, ch); |
| 32213 | 32257 | } |
| 32214 | 32258 | if( precision>1 ){ |
| 32215 | 32259 | i64 nPrior = 1; |
| 32216 | 32260 | width -= precision-1; |
| 32217 | 32261 | if( width>1 && !flag_leftjustify ){ |
| | @@ -32287,26 +32331,35 @@ |
| 32287 | 32331 | /* Adjust width to account for extra bytes in UTF-8 characters */ |
| 32288 | 32332 | int ii = length - 1; |
| 32289 | 32333 | while( ii>=0 ) if( (bufpt[ii--] & 0xc0)==0x80 ) width++; |
| 32290 | 32334 | } |
| 32291 | 32335 | break; |
| 32292 | | - case etSQLESCAPE: /* %q: Escape ' characters */ |
| 32293 | | - case etSQLESCAPE2: /* %Q: Escape ' and enclose in '...' */ |
| 32294 | | - case etSQLESCAPE3: { /* %w: Escape " characters */ |
| 32336 | + case etESCAPE_q: /* %q: Escape ' characters */ |
| 32337 | + case etESCAPE_Q: /* %Q: Escape ' and enclose in '...' */ |
| 32338 | + case etESCAPE_w: { /* %w: Escape " characters */ |
| 32295 | 32339 | i64 i, j, k, n; |
| 32296 | | - int needQuote, isnull; |
| 32340 | + int needQuote = 0; |
| 32297 | 32341 | char ch; |
| 32298 | | - char q = ((xtype==etSQLESCAPE3)?'"':'\''); /* Quote character */ |
| 32299 | 32342 | char *escarg; |
| 32343 | + char q; |
| 32300 | 32344 | |
| 32301 | 32345 | if( bArgList ){ |
| 32302 | 32346 | escarg = getTextArg(pArgList); |
| 32303 | 32347 | }else{ |
| 32304 | 32348 | escarg = va_arg(ap,char*); |
| 32305 | 32349 | } |
| 32306 | | - isnull = escarg==0; |
| 32307 | | - if( isnull ) escarg = (xtype==etSQLESCAPE2 ? "NULL" : "(NULL)"); |
| 32350 | + if( escarg==0 ){ |
| 32351 | + escarg = (xtype==etESCAPE_Q ? "NULL" : "(NULL)"); |
| 32352 | + }else if( xtype==etESCAPE_Q ){ |
| 32353 | + needQuote = 1; |
| 32354 | + } |
| 32355 | + if( xtype==etESCAPE_w ){ |
| 32356 | + q = '"'; |
| 32357 | + flag_alternateform = 0; |
| 32358 | + }else{ |
| 32359 | + q = '\''; |
| 32360 | + } |
| 32308 | 32361 | /* For %q, %Q, and %w, the precision is the number of bytes (or |
| 32309 | 32362 | ** characters if the ! flags is present) to use from the input. |
| 32310 | 32363 | ** Because of the extra quoting characters inserted, the number |
| 32311 | 32364 | ** of output characters may be larger than the precision. |
| 32312 | 32365 | */ |
| | @@ -32315,26 +32368,77 @@ |
| 32315 | 32368 | if( ch==q ) n++; |
| 32316 | 32369 | if( flag_altform2 && (ch&0xc0)==0xc0 ){ |
| 32317 | 32370 | while( (escarg[i+1]&0xc0)==0x80 ){ i++; } |
| 32318 | 32371 | } |
| 32319 | 32372 | } |
| 32320 | | - needQuote = !isnull && xtype==etSQLESCAPE2; |
| 32373 | + if( flag_alternateform ){ |
| 32374 | + /* For %#q, do unistr()-style backslash escapes for |
| 32375 | + ** all control characters, and for backslash itself. |
| 32376 | + ** For %#Q, do the same but only if there is at least |
| 32377 | + ** one control character. */ |
| 32378 | + u32 nBack = 0; |
| 32379 | + u32 nCtrl = 0; |
| 32380 | + for(k=0; k<i; k++){ |
| 32381 | + if( escarg[k]=='\\' ){ |
| 32382 | + nBack++; |
| 32383 | + }else if( escarg[k]<=0x1f ){ |
| 32384 | + nCtrl++; |
| 32385 | + } |
| 32386 | + } |
| 32387 | + if( nCtrl || xtype==etESCAPE_q ){ |
| 32388 | + n += nBack + 5*nCtrl; |
| 32389 | + if( xtype==etESCAPE_Q ){ |
| 32390 | + n += 10; |
| 32391 | + needQuote = 2; |
| 32392 | + } |
| 32393 | + }else{ |
| 32394 | + flag_alternateform = 0; |
| 32395 | + } |
| 32396 | + } |
| 32321 | 32397 | n += i + 3; |
| 32322 | 32398 | if( n>etBUFSIZE ){ |
| 32323 | 32399 | bufpt = zExtra = printfTempBuf(pAccum, n); |
| 32324 | 32400 | if( bufpt==0 ) return; |
| 32325 | 32401 | }else{ |
| 32326 | 32402 | bufpt = buf; |
| 32327 | 32403 | } |
| 32328 | 32404 | j = 0; |
| 32329 | | - if( needQuote ) bufpt[j++] = q; |
| 32405 | + if( needQuote ){ |
| 32406 | + if( needQuote==2 ){ |
| 32407 | + memcpy(&bufpt[j], "unistr('", 8); |
| 32408 | + j += 8; |
| 32409 | + }else{ |
| 32410 | + bufpt[j++] = '\''; |
| 32411 | + } |
| 32412 | + } |
| 32330 | 32413 | k = i; |
| 32331 | | - for(i=0; i<k; i++){ |
| 32332 | | - bufpt[j++] = ch = escarg[i]; |
| 32333 | | - if( ch==q ) bufpt[j++] = ch; |
| 32414 | + if( flag_alternateform ){ |
| 32415 | + for(i=0; i<k; i++){ |
| 32416 | + bufpt[j++] = ch = escarg[i]; |
| 32417 | + if( ch==q ){ |
| 32418 | + bufpt[j++] = ch; |
| 32419 | + }else if( ch=='\\' ){ |
| 32420 | + bufpt[j++] = '\\'; |
| 32421 | + }else if( ch<=0x1f ){ |
| 32422 | + bufpt[j-1] = '\\'; |
| 32423 | + bufpt[j++] = 'u'; |
| 32424 | + bufpt[j++] = '0'; |
| 32425 | + bufpt[j++] = '0'; |
| 32426 | + bufpt[j++] = ch>=0x10 ? '1' : '0'; |
| 32427 | + bufpt[j++] = "0123456789abcdef"[ch&0xf]; |
| 32428 | + } |
| 32429 | + } |
| 32430 | + }else{ |
| 32431 | + for(i=0; i<k; i++){ |
| 32432 | + bufpt[j++] = ch = escarg[i]; |
| 32433 | + if( ch==q ) bufpt[j++] = ch; |
| 32434 | + } |
| 32334 | 32435 | } |
| 32335 | | - if( needQuote ) bufpt[j++] = q; |
| 32436 | + if( needQuote ){ |
| 32437 | + bufpt[j++] = '\''; |
| 32438 | + if( needQuote==2 ) bufpt[j++] = ')'; |
| 32439 | + } |
| 32336 | 32440 | bufpt[j] = 0; |
| 32337 | 32441 | length = j; |
| 32338 | 32442 | goto adjust_width_for_utf8; |
| 32339 | 32443 | } |
| 32340 | 32444 | case etTOKEN: { |
| | @@ -34828,10 +34932,39 @@ |
| 34828 | 34932 | *zOut++ = (u8)(((c>>10)&0x003F) + (((c-0x10000)>>10)&0x00C0)); \ |
| 34829 | 34933 | *zOut++ = (u8)(0x00DC + ((c>>8)&0x03)); \ |
| 34830 | 34934 | *zOut++ = (u8)(c&0x00FF); \ |
| 34831 | 34935 | } \ |
| 34832 | 34936 | } |
| 34937 | + |
| 34938 | +/* |
| 34939 | +** Write a single UTF8 character whose value is v into the |
| 34940 | +** buffer starting at zOut. zOut must be sized to hold at |
| 34941 | +** least for bytes. Return the number of bytes needed |
| 34942 | +** to encode the new character. |
| 34943 | +*/ |
| 34944 | +SQLITE_PRIVATE int sqlite3AppendOneUtf8Character(char *zOut, u32 v){ |
| 34945 | + if( v<0x00080 ){ |
| 34946 | + zOut[0] = (u8)(v & 0xff); |
| 34947 | + return 1; |
| 34948 | + } |
| 34949 | + if( v<0x00800 ){ |
| 34950 | + zOut[0] = 0xc0 + (u8)((v>>6) & 0x1f); |
| 34951 | + zOut[1] = 0x80 + (u8)(v & 0x3f); |
| 34952 | + return 2; |
| 34953 | + } |
| 34954 | + if( v<0x10000 ){ |
| 34955 | + zOut[0] = 0xe0 + (u8)((v>>12) & 0x0f); |
| 34956 | + zOut[1] = 0x80 + (u8)((v>>6) & 0x3f); |
| 34957 | + zOut[2] = 0x80 + (u8)(v & 0x3f); |
| 34958 | + return 3; |
| 34959 | + } |
| 34960 | + zOut[0] = 0xf0 + (u8)((v>>18) & 0x07); |
| 34961 | + zOut[1] = 0x80 + (u8)((v>>12) & 0x3f); |
| 34962 | + zOut[2] = 0x80 + (u8)((v>>6) & 0x3f); |
| 34963 | + zOut[3] = 0x80 + (u8)(v & 0x3f); |
| 34964 | + return 4; |
| 34965 | +} |
| 34833 | 34966 | |
| 34834 | 34967 | /* |
| 34835 | 34968 | ** Translate a single UTF-8 character. Return the unicode value. |
| 34836 | 34969 | ** |
| 34837 | 34970 | ** During translation, assume that the byte that zTerm points |
| | @@ -38911,10 +39044,11 @@ |
| 38911 | 39044 | #if SQLITE_ENABLE_LOCKING_STYLE || defined(__APPLE__) |
| 38912 | 39045 | unsigned fsFlags; /* cached details from statfs() */ |
| 38913 | 39046 | #endif |
| 38914 | 39047 | #ifdef SQLITE_ENABLE_SETLK_TIMEOUT |
| 38915 | 39048 | unsigned iBusyTimeout; /* Wait this many millisec on locks */ |
| 39049 | + int bBlockOnConnect; /* True to block for SHARED locks */ |
| 38916 | 39050 | #endif |
| 38917 | 39051 | #if OS_VXWORKS |
| 38918 | 39052 | struct vxworksFileId *pId; /* Unique file ID */ |
| 38919 | 39053 | #endif |
| 38920 | 39054 | #ifdef SQLITE_DEBUG |
| | @@ -40304,10 +40438,17 @@ |
| 40304 | 40438 | pInode->nLock++; |
| 40305 | 40439 | }else{ |
| 40306 | 40440 | rc = 0; |
| 40307 | 40441 | } |
| 40308 | 40442 | }else{ |
| 40443 | +#ifdef SQLITE_ENABLE_SETLK_TIMEOUT |
| 40444 | + if( pFile->bBlockOnConnect && pLock->l_type==F_RDLCK |
| 40445 | + && pLock->l_start==SHARED_FIRST && pLock->l_len==SHARED_SIZE |
| 40446 | + ){ |
| 40447 | + rc = osFcntl(pFile->h, F_SETLKW, pLock); |
| 40448 | + }else |
| 40449 | +#endif |
| 40309 | 40450 | rc = osSetPosixAdvisoryLock(pFile->h, pLock, pFile); |
| 40310 | 40451 | } |
| 40311 | 40452 | return rc; |
| 40312 | 40453 | } |
| 40313 | 40454 | |
| | @@ -42665,21 +42806,27 @@ |
| 42665 | 42806 | return SQLITE_OK; |
| 42666 | 42807 | } |
| 42667 | 42808 | #ifdef SQLITE_ENABLE_SETLK_TIMEOUT |
| 42668 | 42809 | case SQLITE_FCNTL_LOCK_TIMEOUT: { |
| 42669 | 42810 | int iOld = pFile->iBusyTimeout; |
| 42811 | + int iNew = *(int*)pArg; |
| 42670 | 42812 | #if SQLITE_ENABLE_SETLK_TIMEOUT==1 |
| 42671 | | - pFile->iBusyTimeout = *(int*)pArg; |
| 42813 | + pFile->iBusyTimeout = iNew<0 ? 0x7FFFFFFF : (unsigned)iNew; |
| 42672 | 42814 | #elif SQLITE_ENABLE_SETLK_TIMEOUT==2 |
| 42673 | 42815 | pFile->iBusyTimeout = !!(*(int*)pArg); |
| 42674 | 42816 | #else |
| 42675 | 42817 | # error "SQLITE_ENABLE_SETLK_TIMEOUT must be set to 1 or 2" |
| 42676 | 42818 | #endif |
| 42677 | 42819 | *(int*)pArg = iOld; |
| 42678 | 42820 | return SQLITE_OK; |
| 42679 | 42821 | } |
| 42680 | | -#endif |
| 42822 | + case SQLITE_FCNTL_BLOCK_ON_CONNECT: { |
| 42823 | + int iNew = *(int*)pArg; |
| 42824 | + pFile->bBlockOnConnect = iNew; |
| 42825 | + return SQLITE_OK; |
| 42826 | + } |
| 42827 | +#endif /* SQLITE_ENABLE_SETLK_TIMEOUT */ |
| 42681 | 42828 | #if SQLITE_MAX_MMAP_SIZE>0 |
| 42682 | 42829 | case SQLITE_FCNTL_MMAP_SIZE: { |
| 42683 | 42830 | i64 newLimit = *(i64*)pArg; |
| 42684 | 42831 | int rc = SQLITE_OK; |
| 42685 | 42832 | if( newLimit>sqlite3GlobalConfig.mxMmap ){ |
| | @@ -43658,11 +43805,11 @@ |
| 43658 | 43805 | ** occur later in the above list than the lock being obtained may be |
| 43659 | 43806 | ** held. |
| 43660 | 43807 | ** |
| 43661 | 43808 | ** It is not permitted to block on the RECOVER lock. |
| 43662 | 43809 | */ |
| 43663 | | -#ifdef SQLITE_ENABLE_SETLK_TIMEOUT |
| 43810 | +#if defined(SQLITE_ENABLE_SETLK_TIMEOUT) && defined(SQLITE_DEBUG) |
| 43664 | 43811 | { |
| 43665 | 43812 | u16 lockMask = (p->exclMask|p->sharedMask); |
| 43666 | 43813 | assert( (flags & SQLITE_SHM_UNLOCK) || pDbFd->iBusyTimeout==0 || ( |
| 43667 | 43814 | (ofst!=2) /* not RECOVER */ |
| 43668 | 43815 | && (ofst!=1 || lockMask==0 || lockMask==2) |
| | @@ -47188,11 +47335,21 @@ |
| 47188 | 47335 | HANDLE hMap; /* Handle for accessing memory mapping */ |
| 47189 | 47336 | void *pMapRegion; /* Area memory mapped */ |
| 47190 | 47337 | sqlite3_int64 mmapSize; /* Size of mapped region */ |
| 47191 | 47338 | sqlite3_int64 mmapSizeMax; /* Configured FCNTL_MMAP_SIZE value */ |
| 47192 | 47339 | #endif |
| 47340 | +#ifdef SQLITE_ENABLE_SETLK_TIMEOUT |
| 47341 | + DWORD iBusyTimeout; /* Wait this many millisec on locks */ |
| 47342 | + int bBlockOnConnect; |
| 47343 | +#endif |
| 47193 | 47344 | }; |
| 47345 | + |
| 47346 | +#ifdef SQLITE_ENABLE_SETLK_TIMEOUT |
| 47347 | +# define winFileBusyTimeout(pDbFd) pDbFd->iBusyTimeout |
| 47348 | +#else |
| 47349 | +# define winFileBusyTimeout(pDbFd) 0 |
| 47350 | +#endif |
| 47194 | 47351 | |
| 47195 | 47352 | /* |
| 47196 | 47353 | ** The winVfsAppData structure is used for the pAppData member for all of the |
| 47197 | 47354 | ** Win32 VFS variants. |
| 47198 | 47355 | */ |
| | @@ -47623,10 +47780,16 @@ |
| 47623 | 47780 | #endif |
| 47624 | 47781 | |
| 47625 | 47782 | #define osGetFullPathNameW ((DWORD(WINAPI*)(LPCWSTR,DWORD,LPWSTR, \ |
| 47626 | 47783 | LPWSTR*))aSyscall[25].pCurrent) |
| 47627 | 47784 | |
| 47785 | +/* |
| 47786 | +** For GetLastError(), MSDN says: |
| 47787 | +** |
| 47788 | +** Minimum supported client: Windows XP [desktop apps | UWP apps] |
| 47789 | +** Minimum supported server: Windows Server 2003 [desktop apps | UWP apps] |
| 47790 | +*/ |
| 47628 | 47791 | { "GetLastError", (SYSCALL)GetLastError, 0 }, |
| 47629 | 47792 | |
| 47630 | 47793 | #define osGetLastError ((DWORD(WINAPI*)(VOID))aSyscall[26].pCurrent) |
| 47631 | 47794 | |
| 47632 | 47795 | #if !defined(SQLITE_OMIT_LOAD_EXTENSION) |
| | @@ -47905,15 +48068,17 @@ |
| 47905 | 48068 | #endif |
| 47906 | 48069 | |
| 47907 | 48070 | #define osCreateEventExW ((HANDLE(WINAPI*)(LPSECURITY_ATTRIBUTES,LPCWSTR, \ |
| 47908 | 48071 | DWORD,DWORD))aSyscall[62].pCurrent) |
| 47909 | 48072 | |
| 47910 | | -#if !SQLITE_OS_WINRT |
| 48073 | +/* |
| 48074 | +** For WaitForSingleObject(), MSDN says: |
| 48075 | +** |
| 48076 | +** Minimum supported client: Windows XP [desktop apps | UWP apps] |
| 48077 | +** Minimum supported server: Windows Server 2003 [desktop apps | UWP apps] |
| 48078 | +*/ |
| 47911 | 48079 | { "WaitForSingleObject", (SYSCALL)WaitForSingleObject, 0 }, |
| 47912 | | -#else |
| 47913 | | - { "WaitForSingleObject", (SYSCALL)0, 0 }, |
| 47914 | | -#endif |
| 47915 | 48080 | |
| 47916 | 48081 | #define osWaitForSingleObject ((DWORD(WINAPI*)(HANDLE, \ |
| 47917 | 48082 | DWORD))aSyscall[63].pCurrent) |
| 47918 | 48083 | |
| 47919 | 48084 | #if !SQLITE_OS_WINCE |
| | @@ -48056,10 +48221,44 @@ |
| 48056 | 48221 | #endif |
| 48057 | 48222 | |
| 48058 | 48223 | #define osFlushViewOfFile \ |
| 48059 | 48224 | ((BOOL(WINAPI*)(LPCVOID,SIZE_T))aSyscall[79].pCurrent) |
| 48060 | 48225 | |
| 48226 | +/* |
| 48227 | +** If SQLITE_ENABLE_SETLK_TIMEOUT is defined, we require CreateEvent() |
| 48228 | +** to implement blocking locks with timeouts. MSDN says: |
| 48229 | +** |
| 48230 | +** Minimum supported client: Windows XP [desktop apps | UWP apps] |
| 48231 | +** Minimum supported server: Windows Server 2003 [desktop apps | UWP apps] |
| 48232 | +*/ |
| 48233 | +#ifdef SQLITE_ENABLE_SETLK_TIMEOUT |
| 48234 | + { "CreateEvent", (SYSCALL)CreateEvent, 0 }, |
| 48235 | +#else |
| 48236 | + { "CreateEvent", (SYSCALL)0, 0 }, |
| 48237 | +#endif |
| 48238 | + |
| 48239 | +#define osCreateEvent ( \ |
| 48240 | + (HANDLE(WINAPI*) (LPSECURITY_ATTRIBUTES,BOOL,BOOL,LPCSTR)) \ |
| 48241 | + aSyscall[80].pCurrent \ |
| 48242 | +) |
| 48243 | + |
| 48244 | +/* |
| 48245 | +** If SQLITE_ENABLE_SETLK_TIMEOUT is defined, we require CancelIo() |
| 48246 | +** for the case where a timeout expires and a lock request must be |
| 48247 | +** cancelled. |
| 48248 | +** |
| 48249 | +** Minimum supported client: Windows XP [desktop apps | UWP apps] |
| 48250 | +** Minimum supported server: Windows Server 2003 [desktop apps | UWP apps] |
| 48251 | +*/ |
| 48252 | +#ifdef SQLITE_ENABLE_SETLK_TIMEOUT |
| 48253 | + { "CancelIo", (SYSCALL)CancelIo, 0 }, |
| 48254 | +#else |
| 48255 | + { "CancelIo", (SYSCALL)0, 0 }, |
| 48256 | +#endif |
| 48257 | + |
| 48258 | +#define osCancelIo ((BOOL(WINAPI*)(HANDLE))aSyscall[81].pCurrent) |
| 48259 | + |
| 48061 | 48260 | }; /* End of the overrideable system calls */ |
| 48062 | 48261 | |
| 48063 | 48262 | /* |
| 48064 | 48263 | ** This is the xSetSystemCall() method of sqlite3_vfs for all of the |
| 48065 | 48264 | ** "win32" VFSes. Return SQLITE_OK upon successfully updating the |
| | @@ -48354,11 +48553,13 @@ |
| 48354 | 48553 | (sInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) ? 2 : 1, 0); |
| 48355 | 48554 | #endif |
| 48356 | 48555 | } |
| 48357 | 48556 | return osInterlockedCompareExchange(&sqlite3_os_type, 2, 2)==2; |
| 48358 | 48557 | #elif SQLITE_TEST |
| 48359 | | - return osInterlockedCompareExchange(&sqlite3_os_type, 2, 2)==2; |
| 48558 | + return osInterlockedCompareExchange(&sqlite3_os_type, 2, 2)==2 |
| 48559 | + || osInterlockedCompareExchange(&sqlite3_os_type, 0, 0)==0 |
| 48560 | + ; |
| 48360 | 48561 | #else |
| 48361 | 48562 | /* |
| 48362 | 48563 | ** NOTE: All sub-platforms where the GetVersionEx[AW] functions are |
| 48363 | 48564 | ** deprecated are always assumed to be based on the NT kernel. |
| 48364 | 48565 | */ |
| | @@ -49440,10 +49641,89 @@ |
| 49440 | 49641 | return osLockFile(*phFile, offsetLow, offsetHigh, numBytesLow, |
| 49441 | 49642 | numBytesHigh); |
| 49442 | 49643 | } |
| 49443 | 49644 | #endif |
| 49444 | 49645 | } |
| 49646 | + |
| 49647 | +/* |
| 49648 | +** Lock a region of nByte bytes starting at offset offset of file hFile. |
| 49649 | +** Take an EXCLUSIVE lock if parameter bExclusive is true, or a SHARED lock |
| 49650 | +** otherwise. If nMs is greater than zero and the lock cannot be obtained |
| 49651 | +** immediately, block for that many ms before giving up. |
| 49652 | +** |
| 49653 | +** This function returns SQLITE_OK if the lock is obtained successfully. If |
| 49654 | +** some other process holds the lock, SQLITE_BUSY is returned if nMs==0, or |
| 49655 | +** SQLITE_BUSY_TIMEOUT otherwise. Or, if an error occurs, SQLITE_IOERR. |
| 49656 | +*/ |
| 49657 | +static int winHandleLockTimeout( |
| 49658 | + HANDLE hFile, |
| 49659 | + DWORD offset, |
| 49660 | + DWORD nByte, |
| 49661 | + int bExcl, |
| 49662 | + DWORD nMs |
| 49663 | +){ |
| 49664 | + DWORD flags = LOCKFILE_FAIL_IMMEDIATELY | (bExcl?LOCKFILE_EXCLUSIVE_LOCK:0); |
| 49665 | + int rc = SQLITE_OK; |
| 49666 | + BOOL ret; |
| 49667 | + |
| 49668 | + if( !osIsNT() ){ |
| 49669 | + ret = winLockFile(&hFile, flags, offset, 0, nByte, 0); |
| 49670 | + }else{ |
| 49671 | + OVERLAPPED ovlp; |
| 49672 | + memset(&ovlp, 0, sizeof(OVERLAPPED)); |
| 49673 | + ovlp.Offset = offset; |
| 49674 | + |
| 49675 | +#ifdef SQLITE_ENABLE_SETLK_TIMEOUT |
| 49676 | + if( nMs!=0 ){ |
| 49677 | + flags &= ~LOCKFILE_FAIL_IMMEDIATELY; |
| 49678 | + } |
| 49679 | + ovlp.hEvent = osCreateEvent(NULL, TRUE, FALSE, NULL); |
| 49680 | + if( ovlp.hEvent==NULL ){ |
| 49681 | + return SQLITE_IOERR_LOCK; |
| 49682 | + } |
| 49683 | +#endif |
| 49684 | + |
| 49685 | + ret = osLockFileEx(hFile, flags, 0, nByte, 0, &ovlp); |
| 49686 | + |
| 49687 | +#ifdef SQLITE_ENABLE_SETLK_TIMEOUT |
| 49688 | + /* If SQLITE_ENABLE_SETLK_TIMEOUT is defined, then the file-handle was |
| 49689 | + ** opened with FILE_FLAG_OVERHEAD specified. In this case, the call to |
| 49690 | + ** LockFileEx() may fail because the request is still pending. This can |
| 49691 | + ** happen even if LOCKFILE_FAIL_IMMEDIATELY was specified. |
| 49692 | + ** |
| 49693 | + ** If nMs is 0, then LOCKFILE_FAIL_IMMEDIATELY was set in the flags |
| 49694 | + ** passed to LockFileEx(). In this case, if the operation is pending, |
| 49695 | + ** block indefinitely until it is finished. |
| 49696 | + ** |
| 49697 | + ** Otherwise, wait for up to nMs ms for the operation to finish. nMs |
| 49698 | + ** may be set to INFINITE. |
| 49699 | + */ |
| 49700 | + if( !ret && GetLastError()==ERROR_IO_PENDING ){ |
| 49701 | + DWORD nDelay = (nMs==0 ? INFINITE : nMs); |
| 49702 | + DWORD res = osWaitForSingleObject(ovlp.hEvent, nDelay); |
| 49703 | + if( res==WAIT_OBJECT_0 ){ |
| 49704 | + ret = TRUE; |
| 49705 | + }else if( res==WAIT_TIMEOUT ){ |
| 49706 | + rc = SQLITE_BUSY_TIMEOUT; |
| 49707 | + }else{ |
| 49708 | + /* Some other error has occurred */ |
| 49709 | + rc = SQLITE_IOERR_LOCK; |
| 49710 | + } |
| 49711 | + |
| 49712 | + /* If it is still pending, cancel the LockFileEx() call. */ |
| 49713 | + osCancelIo(hFile); |
| 49714 | + } |
| 49715 | + |
| 49716 | + osCloseHandle(ovlp.hEvent); |
| 49717 | +#endif |
| 49718 | + } |
| 49719 | + |
| 49720 | + if( rc==SQLITE_OK && !ret ){ |
| 49721 | + rc = SQLITE_BUSY; |
| 49722 | + } |
| 49723 | + return rc; |
| 49724 | +} |
| 49445 | 49725 | |
| 49446 | 49726 | /* |
| 49447 | 49727 | ** Unlock a file region. |
| 49448 | 49728 | */ |
| 49449 | 49729 | static BOOL winUnlockFile( |
| | @@ -49471,10 +49751,18 @@ |
| 49471 | 49751 | return osUnlockFile(*phFile, offsetLow, offsetHigh, numBytesLow, |
| 49472 | 49752 | numBytesHigh); |
| 49473 | 49753 | } |
| 49474 | 49754 | #endif |
| 49475 | 49755 | } |
| 49756 | + |
| 49757 | +/* |
| 49758 | +** Remove an nByte lock starting at offset iOff from HANDLE h. |
| 49759 | +*/ |
| 49760 | +static int winHandleUnlock(HANDLE h, int iOff, int nByte){ |
| 49761 | + BOOL ret = winUnlockFile(&h, iOff, 0, nByte, 0); |
| 49762 | + return (ret ? SQLITE_OK : SQLITE_IOERR_UNLOCK); |
| 49763 | +} |
| 49476 | 49764 | |
| 49477 | 49765 | /***************************************************************************** |
| 49478 | 49766 | ** The next group of routines implement the I/O methods specified |
| 49479 | 49767 | ** by the sqlite3_io_methods object. |
| 49480 | 49768 | ******************************************************************************/ |
| | @@ -49485,69 +49773,73 @@ |
| 49485 | 49773 | #ifndef INVALID_SET_FILE_POINTER |
| 49486 | 49774 | # define INVALID_SET_FILE_POINTER ((DWORD)-1) |
| 49487 | 49775 | #endif |
| 49488 | 49776 | |
| 49489 | 49777 | /* |
| 49490 | | -** Move the current position of the file handle passed as the first |
| 49491 | | -** argument to offset iOffset within the file. If successful, return 0. |
| 49492 | | -** Otherwise, set pFile->lastErrno and return non-zero. |
| 49778 | +** Seek the file handle h to offset nByte of the file. |
| 49779 | +** |
| 49780 | +** If successful, return SQLITE_OK. Or, if an error occurs, return an SQLite |
| 49781 | +** error code. |
| 49493 | 49782 | */ |
| 49494 | | -static int winSeekFile(winFile *pFile, sqlite3_int64 iOffset){ |
| 49783 | +static int winHandleSeek(HANDLE h, sqlite3_int64 iOffset){ |
| 49784 | + int rc = SQLITE_OK; /* Return value */ |
| 49785 | + |
| 49495 | 49786 | #if !SQLITE_OS_WINRT |
| 49496 | 49787 | LONG upperBits; /* Most sig. 32 bits of new offset */ |
| 49497 | 49788 | LONG lowerBits; /* Least sig. 32 bits of new offset */ |
| 49498 | 49789 | DWORD dwRet; /* Value returned by SetFilePointer() */ |
| 49499 | | - DWORD lastErrno; /* Value returned by GetLastError() */ |
| 49500 | | - |
| 49501 | | - OSTRACE(("SEEK file=%p, offset=%lld\n", pFile->h, iOffset)); |
| 49502 | 49790 | |
| 49503 | 49791 | upperBits = (LONG)((iOffset>>32) & 0x7fffffff); |
| 49504 | 49792 | lowerBits = (LONG)(iOffset & 0xffffffff); |
| 49793 | + |
| 49794 | + dwRet = osSetFilePointer(h, lowerBits, &upperBits, FILE_BEGIN); |
| 49505 | 49795 | |
| 49506 | 49796 | /* API oddity: If successful, SetFilePointer() returns a dword |
| 49507 | 49797 | ** containing the lower 32-bits of the new file-offset. Or, if it fails, |
| 49508 | 49798 | ** it returns INVALID_SET_FILE_POINTER. However according to MSDN, |
| 49509 | 49799 | ** INVALID_SET_FILE_POINTER may also be a valid new offset. So to determine |
| 49510 | 49800 | ** whether an error has actually occurred, it is also necessary to call |
| 49511 | | - ** GetLastError(). |
| 49512 | | - */ |
| 49513 | | - dwRet = osSetFilePointer(pFile->h, lowerBits, &upperBits, FILE_BEGIN); |
| 49514 | | - |
| 49515 | | - if( (dwRet==INVALID_SET_FILE_POINTER |
| 49516 | | - && ((lastErrno = osGetLastError())!=NO_ERROR)) ){ |
| 49517 | | - pFile->lastErrno = lastErrno; |
| 49518 | | - winLogError(SQLITE_IOERR_SEEK, pFile->lastErrno, |
| 49519 | | - "winSeekFile", pFile->zPath); |
| 49520 | | - OSTRACE(("SEEK file=%p, rc=SQLITE_IOERR_SEEK\n", pFile->h)); |
| 49521 | | - return 1; |
| 49522 | | - } |
| 49523 | | - |
| 49524 | | - OSTRACE(("SEEK file=%p, rc=SQLITE_OK\n", pFile->h)); |
| 49525 | | - return 0; |
| 49526 | | -#else |
| 49527 | | - /* |
| 49528 | | - ** Same as above, except that this implementation works for WinRT. |
| 49529 | | - */ |
| 49530 | | - |
| 49801 | + ** GetLastError(). */ |
| 49802 | + if( dwRet==INVALID_SET_FILE_POINTER ){ |
| 49803 | + DWORD lastErrno = osGetLastError(); |
| 49804 | + if( lastErrno!=NO_ERROR ){ |
| 49805 | + rc = SQLITE_IOERR_SEEK; |
| 49806 | + } |
| 49807 | + } |
| 49808 | +#else |
| 49809 | + /* This implementation works for WinRT. */ |
| 49531 | 49810 | LARGE_INTEGER x; /* The new offset */ |
| 49532 | 49811 | BOOL bRet; /* Value returned by SetFilePointerEx() */ |
| 49533 | 49812 | |
| 49534 | 49813 | x.QuadPart = iOffset; |
| 49535 | | - bRet = osSetFilePointerEx(pFile->h, x, 0, FILE_BEGIN); |
| 49814 | + bRet = osSetFilePointerEx(h, x, 0, FILE_BEGIN); |
| 49536 | 49815 | |
| 49537 | 49816 | if(!bRet){ |
| 49817 | + rc = SQLITE_IOERR_SEEK; |
| 49818 | + } |
| 49819 | +#endif |
| 49820 | + |
| 49821 | + OSTRACE(("SEEK file=%p, offset=%lld rc=%s\n", h, iOffset, sqlite3ErrName(rc))); |
| 49822 | + return rc; |
| 49823 | +} |
| 49824 | + |
| 49825 | +/* |
| 49826 | +** Move the current position of the file handle passed as the first |
| 49827 | +** argument to offset iOffset within the file. If successful, return 0. |
| 49828 | +** Otherwise, set pFile->lastErrno and return non-zero. |
| 49829 | +*/ |
| 49830 | +static int winSeekFile(winFile *pFile, sqlite3_int64 iOffset){ |
| 49831 | + int rc; |
| 49832 | + |
| 49833 | + rc = winHandleSeek(pFile->h, iOffset); |
| 49834 | + if( rc!=SQLITE_OK ){ |
| 49538 | 49835 | pFile->lastErrno = osGetLastError(); |
| 49539 | | - winLogError(SQLITE_IOERR_SEEK, pFile->lastErrno, |
| 49540 | | - "winSeekFile", pFile->zPath); |
| 49541 | | - OSTRACE(("SEEK file=%p, rc=SQLITE_IOERR_SEEK\n", pFile->h)); |
| 49542 | | - return 1; |
| 49543 | | - } |
| 49544 | | - |
| 49545 | | - OSTRACE(("SEEK file=%p, rc=SQLITE_OK\n", pFile->h)); |
| 49546 | | - return 0; |
| 49547 | | -#endif |
| 49548 | | -} |
| 49836 | + winLogError(rc, pFile->lastErrno, "winSeekFile", pFile->zPath); |
| 49837 | + } |
| 49838 | + return rc; |
| 49839 | +} |
| 49840 | + |
| 49549 | 49841 | |
| 49550 | 49842 | #if SQLITE_MAX_MMAP_SIZE>0 |
| 49551 | 49843 | /* Forward references to VFS helper methods used for memory mapped files */ |
| 49552 | 49844 | static int winMapfile(winFile*, sqlite3_int64); |
| 49553 | 49845 | static int winUnmapfile(winFile*); |
| | @@ -49803,10 +50095,64 @@ |
| 49803 | 50095 | } |
| 49804 | 50096 | OSTRACE(("WRITE pid=%lu, pFile=%p, file=%p, rc=SQLITE_OK\n", |
| 49805 | 50097 | osGetCurrentProcessId(), pFile, pFile->h)); |
| 49806 | 50098 | return SQLITE_OK; |
| 49807 | 50099 | } |
| 50100 | + |
| 50101 | +/* |
| 50102 | +** Truncate the file opened by handle h to nByte bytes in size. |
| 50103 | +*/ |
| 50104 | +static int winHandleTruncate(HANDLE h, sqlite3_int64 nByte){ |
| 50105 | + int rc = SQLITE_OK; /* Return code */ |
| 50106 | + rc = winHandleSeek(h, nByte); |
| 50107 | + if( rc==SQLITE_OK ){ |
| 50108 | + if( 0==osSetEndOfFile(h) ){ |
| 50109 | + rc = SQLITE_IOERR_TRUNCATE; |
| 50110 | + } |
| 50111 | + } |
| 50112 | + return rc; |
| 50113 | +} |
| 50114 | + |
| 50115 | +/* |
| 50116 | +** Determine the size in bytes of the file opened by the handle passed as |
| 50117 | +** the first argument. |
| 50118 | +*/ |
| 50119 | +static int winHandleSize(HANDLE h, sqlite3_int64 *pnByte){ |
| 50120 | + int rc = SQLITE_OK; |
| 50121 | + |
| 50122 | +#if SQLITE_OS_WINRT |
| 50123 | + FILE_STANDARD_INFO info; |
| 50124 | + BOOL b; |
| 50125 | + b = osGetFileInformationByHandleEx(h, FileStandardInfo, &info, sizeof(info)); |
| 50126 | + if( b ){ |
| 50127 | + *pnByte = info.EndOfFile.QuadPart; |
| 50128 | + }else{ |
| 50129 | + rc = SQLITE_IOERR_FSTAT; |
| 50130 | + } |
| 50131 | +#else |
| 50132 | + DWORD upperBits = 0; |
| 50133 | + DWORD lowerBits = 0; |
| 50134 | + |
| 50135 | + assert( pnByte ); |
| 50136 | + lowerBits = osGetFileSize(h, &upperBits); |
| 50137 | + *pnByte = (((sqlite3_int64)upperBits)<<32) + lowerBits; |
| 50138 | + if( lowerBits==INVALID_FILE_SIZE && osGetLastError()!=NO_ERROR ){ |
| 50139 | + rc = SQLITE_IOERR_FSTAT; |
| 50140 | + } |
| 50141 | +#endif |
| 50142 | + |
| 50143 | + return rc; |
| 50144 | +} |
| 50145 | + |
| 50146 | +/* |
| 50147 | +** Close the handle passed as the only argument. |
| 50148 | +*/ |
| 50149 | +static void winHandleClose(HANDLE h){ |
| 50150 | + if( h!=INVALID_HANDLE_VALUE ){ |
| 50151 | + osCloseHandle(h); |
| 50152 | + } |
| 50153 | +} |
| 49808 | 50154 | |
| 49809 | 50155 | /* |
| 49810 | 50156 | ** Truncate an open file to a specified size |
| 49811 | 50157 | */ |
| 49812 | 50158 | static int winTruncate(sqlite3_file *id, sqlite3_int64 nByte){ |
| | @@ -50059,31 +50405,32 @@ |
| 50059 | 50405 | /* |
| 50060 | 50406 | ** Acquire a reader lock. |
| 50061 | 50407 | ** Different API routines are called depending on whether or not this |
| 50062 | 50408 | ** is Win9x or WinNT. |
| 50063 | 50409 | */ |
| 50064 | | -static int winGetReadLock(winFile *pFile){ |
| 50410 | +static int winGetReadLock(winFile *pFile, int bBlock){ |
| 50065 | 50411 | int res; |
| 50412 | + DWORD mask = ~(bBlock ? LOCKFILE_FAIL_IMMEDIATELY : 0); |
| 50066 | 50413 | OSTRACE(("READ-LOCK file=%p, lock=%d\n", pFile->h, pFile->locktype)); |
| 50067 | 50414 | if( osIsNT() ){ |
| 50068 | 50415 | #if SQLITE_OS_WINCE |
| 50069 | 50416 | /* |
| 50070 | 50417 | ** NOTE: Windows CE is handled differently here due its lack of the Win32 |
| 50071 | 50418 | ** API LockFileEx. |
| 50072 | 50419 | */ |
| 50073 | 50420 | res = winceLockFile(&pFile->h, SHARED_FIRST, 0, 1, 0); |
| 50074 | 50421 | #else |
| 50075 | | - res = winLockFile(&pFile->h, SQLITE_LOCKFILEEX_FLAGS, SHARED_FIRST, 0, |
| 50422 | + res = winLockFile(&pFile->h, SQLITE_LOCKFILEEX_FLAGS&mask, SHARED_FIRST, 0, |
| 50076 | 50423 | SHARED_SIZE, 0); |
| 50077 | 50424 | #endif |
| 50078 | 50425 | } |
| 50079 | 50426 | #ifdef SQLITE_WIN32_HAS_ANSI |
| 50080 | 50427 | else{ |
| 50081 | 50428 | int lk; |
| 50082 | 50429 | sqlite3_randomness(sizeof(lk), &lk); |
| 50083 | 50430 | pFile->sharedLockByte = (short)((lk & 0x7fffffff)%(SHARED_SIZE - 1)); |
| 50084 | | - res = winLockFile(&pFile->h, SQLITE_LOCKFILE_FLAGS, |
| 50431 | + res = winLockFile(&pFile->h, SQLITE_LOCKFILE_FLAGS&mask, |
| 50085 | 50432 | SHARED_FIRST+pFile->sharedLockByte, 0, 1, 0); |
| 50086 | 50433 | } |
| 50087 | 50434 | #endif |
| 50088 | 50435 | if( res == 0 ){ |
| 50089 | 50436 | pFile->lastErrno = osGetLastError(); |
| | @@ -50174,50 +50521,66 @@ |
| 50174 | 50521 | */ |
| 50175 | 50522 | assert( pFile->locktype!=NO_LOCK || locktype==SHARED_LOCK ); |
| 50176 | 50523 | assert( locktype!=PENDING_LOCK ); |
| 50177 | 50524 | assert( locktype!=RESERVED_LOCK || pFile->locktype==SHARED_LOCK ); |
| 50178 | 50525 | |
| 50179 | | - /* Lock the PENDING_LOCK byte if we need to acquire a PENDING lock or |
| 50526 | + /* Lock the PENDING_LOCK byte if we need to acquire an EXCLUSIVE lock or |
| 50180 | 50527 | ** a SHARED lock. If we are acquiring a SHARED lock, the acquisition of |
| 50181 | 50528 | ** the PENDING_LOCK byte is temporary. |
| 50182 | 50529 | */ |
| 50183 | 50530 | newLocktype = pFile->locktype; |
| 50184 | | - if( pFile->locktype==NO_LOCK |
| 50185 | | - || (locktype==EXCLUSIVE_LOCK && pFile->locktype<=RESERVED_LOCK) |
| 50531 | + if( locktype==SHARED_LOCK |
| 50532 | + || (locktype==EXCLUSIVE_LOCK && pFile->locktype==RESERVED_LOCK) |
| 50186 | 50533 | ){ |
| 50187 | 50534 | int cnt = 3; |
| 50188 | | - while( cnt-->0 && (res = winLockFile(&pFile->h, SQLITE_LOCKFILE_FLAGS, |
| 50189 | | - PENDING_BYTE, 0, 1, 0))==0 ){ |
| 50535 | + |
| 50536 | + /* Flags for the LockFileEx() call. This should be an exclusive lock if |
| 50537 | + ** this call is to obtain EXCLUSIVE, or a shared lock if this call is to |
| 50538 | + ** obtain SHARED. */ |
| 50539 | + int flags = LOCKFILE_FAIL_IMMEDIATELY; |
| 50540 | + if( locktype==EXCLUSIVE_LOCK ){ |
| 50541 | + flags |= LOCKFILE_EXCLUSIVE_LOCK; |
| 50542 | + } |
| 50543 | + while( cnt>0 ){ |
| 50190 | 50544 | /* Try 3 times to get the pending lock. This is needed to work |
| 50191 | 50545 | ** around problems caused by indexing and/or anti-virus software on |
| 50192 | 50546 | ** Windows systems. |
| 50547 | + ** |
| 50193 | 50548 | ** If you are using this code as a model for alternative VFSes, do not |
| 50194 | | - ** copy this retry logic. It is a hack intended for Windows only. |
| 50195 | | - */ |
| 50549 | + ** copy this retry logic. It is a hack intended for Windows only. */ |
| 50550 | + res = winLockFile(&pFile->h, flags, PENDING_BYTE, 0, 1, 0); |
| 50551 | + if( res ) break; |
| 50552 | + |
| 50196 | 50553 | lastErrno = osGetLastError(); |
| 50197 | 50554 | OSTRACE(("LOCK-PENDING-FAIL file=%p, count=%d, result=%d\n", |
| 50198 | | - pFile->h, cnt, res)); |
| 50555 | + pFile->h, cnt, res |
| 50556 | + )); |
| 50557 | + |
| 50199 | 50558 | if( lastErrno==ERROR_INVALID_HANDLE ){ |
| 50200 | 50559 | pFile->lastErrno = lastErrno; |
| 50201 | 50560 | rc = SQLITE_IOERR_LOCK; |
| 50202 | 50561 | OSTRACE(("LOCK-FAIL file=%p, count=%d, rc=%s\n", |
| 50203 | | - pFile->h, cnt, sqlite3ErrName(rc))); |
| 50562 | + pFile->h, cnt, sqlite3ErrName(rc) |
| 50563 | + )); |
| 50204 | 50564 | return rc; |
| 50205 | 50565 | } |
| 50206 | | - if( cnt ) sqlite3_win32_sleep(1); |
| 50566 | + |
| 50567 | + cnt--; |
| 50568 | + if( cnt>0 ) sqlite3_win32_sleep(1); |
| 50207 | 50569 | } |
| 50208 | 50570 | gotPendingLock = res; |
| 50209 | | - if( !res ){ |
| 50210 | | - lastErrno = osGetLastError(); |
| 50211 | | - } |
| 50212 | 50571 | } |
| 50213 | 50572 | |
| 50214 | 50573 | /* Acquire a shared lock |
| 50215 | 50574 | */ |
| 50216 | 50575 | if( locktype==SHARED_LOCK && res ){ |
| 50217 | 50576 | assert( pFile->locktype==NO_LOCK ); |
| 50218 | | - res = winGetReadLock(pFile); |
| 50577 | +#ifdef SQLITE_ENABLE_SETLK_TIMEOUT |
| 50578 | + res = winGetReadLock(pFile, pFile->bBlockOnConnect); |
| 50579 | +#else |
| 50580 | + res = winGetReadLock(pFile, 0); |
| 50581 | +#endif |
| 50219 | 50582 | if( res ){ |
| 50220 | 50583 | newLocktype = SHARED_LOCK; |
| 50221 | 50584 | }else{ |
| 50222 | 50585 | lastErrno = osGetLastError(); |
| 50223 | 50586 | } |
| | @@ -50251,11 +50614,11 @@ |
| 50251 | 50614 | SHARED_SIZE, 0); |
| 50252 | 50615 | if( res ){ |
| 50253 | 50616 | newLocktype = EXCLUSIVE_LOCK; |
| 50254 | 50617 | }else{ |
| 50255 | 50618 | lastErrno = osGetLastError(); |
| 50256 | | - winGetReadLock(pFile); |
| 50619 | + winGetReadLock(pFile, 0); |
| 50257 | 50620 | } |
| 50258 | 50621 | } |
| 50259 | 50622 | |
| 50260 | 50623 | /* If we are holding a PENDING lock that ought to be released, then |
| 50261 | 50624 | ** release it now. |
| | @@ -50331,11 +50694,11 @@ |
| 50331 | 50694 | OSTRACE(("UNLOCK file=%p, oldLock=%d(%d), newLock=%d\n", |
| 50332 | 50695 | pFile->h, pFile->locktype, pFile->sharedLockByte, locktype)); |
| 50333 | 50696 | type = pFile->locktype; |
| 50334 | 50697 | if( type>=EXCLUSIVE_LOCK ){ |
| 50335 | 50698 | winUnlockFile(&pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0); |
| 50336 | | - if( locktype==SHARED_LOCK && !winGetReadLock(pFile) ){ |
| 50699 | + if( locktype==SHARED_LOCK && !winGetReadLock(pFile, 0) ){ |
| 50337 | 50700 | /* This should never happen. We should always be able to |
| 50338 | 50701 | ** reacquire the read lock */ |
| 50339 | 50702 | rc = winLogError(SQLITE_IOERR_UNLOCK, osGetLastError(), |
| 50340 | 50703 | "winUnlock", pFile->zPath); |
| 50341 | 50704 | } |
| | @@ -50541,10 +50904,32 @@ |
| 50541 | 50904 | } |
| 50542 | 50905 | OSTRACE(("FCNTL file=%p, rc=%s\n", pFile->h, sqlite3ErrName(rc))); |
| 50543 | 50906 | return rc; |
| 50544 | 50907 | } |
| 50545 | 50908 | #endif |
| 50909 | + |
| 50910 | +#ifdef SQLITE_ENABLE_SETLK_TIMEOUT |
| 50911 | + case SQLITE_FCNTL_LOCK_TIMEOUT: { |
| 50912 | + int iOld = pFile->iBusyTimeout; |
| 50913 | + int iNew = *(int*)pArg; |
| 50914 | +#if SQLITE_ENABLE_SETLK_TIMEOUT==1 |
| 50915 | + pFile->iBusyTimeout = (iNew < 0) ? INFINITE : (DWORD)iNew; |
| 50916 | +#elif SQLITE_ENABLE_SETLK_TIMEOUT==2 |
| 50917 | + pFile->iBusyTimeout = (DWORD)(!!iNew); |
| 50918 | +#else |
| 50919 | +# error "SQLITE_ENABLE_SETLK_TIMEOUT must be set to 1 or 2" |
| 50920 | +#endif |
| 50921 | + *(int*)pArg = iOld; |
| 50922 | + return SQLITE_OK; |
| 50923 | + } |
| 50924 | + case SQLITE_FCNTL_BLOCK_ON_CONNECT: { |
| 50925 | + int iNew = *(int*)pArg; |
| 50926 | + pFile->bBlockOnConnect = iNew; |
| 50927 | + return SQLITE_OK; |
| 50928 | + } |
| 50929 | +#endif /* SQLITE_ENABLE_SETLK_TIMEOUT */ |
| 50930 | + |
| 50546 | 50931 | } |
| 50547 | 50932 | OSTRACE(("FCNTL file=%p, rc=SQLITE_NOTFOUND\n", pFile->h)); |
| 50548 | 50933 | return SQLITE_NOTFOUND; |
| 50549 | 50934 | } |
| 50550 | 50935 | |
| | @@ -50621,36 +51006,39 @@ |
| 50621 | 51006 | ** nRef |
| 50622 | 51007 | ** pNext |
| 50623 | 51008 | ** |
| 50624 | 51009 | ** The following fields are read-only after the object is created: |
| 50625 | 51010 | ** |
| 50626 | | -** fid |
| 50627 | 51011 | ** zFilename |
| 50628 | 51012 | ** |
| 50629 | 51013 | ** Either winShmNode.mutex must be held or winShmNode.nRef==0 and |
| 50630 | 51014 | ** winShmMutexHeld() is true when reading or writing any other field |
| 50631 | 51015 | ** in this structure. |
| 50632 | 51016 | ** |
| 51017 | +** File-handle hSharedShm is used to (a) take the DMS lock, (b) truncate |
| 51018 | +** the *-shm file if the DMS-locking protocol demands it, and (c) map |
| 51019 | +** regions of the *-shm file into memory using MapViewOfFile() or |
| 51020 | +** similar. Other locks are taken by individual clients using the |
| 51021 | +** winShm.hShm handles. |
| 50633 | 51022 | */ |
| 50634 | 51023 | struct winShmNode { |
| 50635 | 51024 | sqlite3_mutex *mutex; /* Mutex to access this object */ |
| 50636 | 51025 | char *zFilename; /* Name of the file */ |
| 50637 | | - winFile hFile; /* File handle from winOpen */ |
| 51026 | + HANDLE hSharedShm; /* File handle open on zFilename */ |
| 50638 | 51027 | |
| 51028 | + int isUnlocked; /* DMS lock has not yet been obtained */ |
| 51029 | + int isReadonly; /* True if read-only */ |
| 50639 | 51030 | int szRegion; /* Size of shared-memory regions */ |
| 50640 | 51031 | int nRegion; /* Size of array apRegion */ |
| 50641 | | - u8 isReadonly; /* True if read-only */ |
| 50642 | | - u8 isUnlocked; /* True if no DMS lock held */ |
| 50643 | 51032 | |
| 50644 | 51033 | struct ShmRegion { |
| 50645 | 51034 | HANDLE hMap; /* File handle from CreateFileMapping */ |
| 50646 | 51035 | void *pMap; |
| 50647 | 51036 | } *aRegion; |
| 50648 | 51037 | DWORD lastErrno; /* The Windows errno from the last I/O error */ |
| 50649 | 51038 | |
| 50650 | 51039 | int nRef; /* Number of winShm objects pointing to this */ |
| 50651 | | - winShm *pFirst; /* All winShm objects pointing to this */ |
| 50652 | 51040 | winShmNode *pNext; /* Next in list of all winShmNode objects */ |
| 50653 | 51041 | #if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE) |
| 50654 | 51042 | u8 nextShmId; /* Next available winShm.id value */ |
| 50655 | 51043 | #endif |
| 50656 | 51044 | }; |
| | @@ -50662,27 +51050,19 @@ |
| 50662 | 51050 | */ |
| 50663 | 51051 | static winShmNode *winShmNodeList = 0; |
| 50664 | 51052 | |
| 50665 | 51053 | /* |
| 50666 | 51054 | ** Structure used internally by this VFS to record the state of an |
| 50667 | | -** open shared memory connection. |
| 50668 | | -** |
| 50669 | | -** The following fields are initialized when this object is created and |
| 50670 | | -** are read-only thereafter: |
| 50671 | | -** |
| 50672 | | -** winShm.pShmNode |
| 50673 | | -** winShm.id |
| 50674 | | -** |
| 50675 | | -** All other fields are read/write. The winShm.pShmNode->mutex must be held |
| 50676 | | -** while accessing any read/write fields. |
| 51055 | +** open shared memory connection. There is one such structure for each |
| 51056 | +** winFile open on a wal mode database. |
| 50677 | 51057 | */ |
| 50678 | 51058 | struct winShm { |
| 50679 | 51059 | winShmNode *pShmNode; /* The underlying winShmNode object */ |
| 50680 | | - winShm *pNext; /* Next winShm with the same winShmNode */ |
| 50681 | | - u8 hasMutex; /* True if holding the winShmNode mutex */ |
| 50682 | 51060 | u16 sharedMask; /* Mask of shared locks held */ |
| 50683 | 51061 | u16 exclMask; /* Mask of exclusive locks held */ |
| 51062 | + HANDLE hShm; /* File-handle on *-shm file. For locking. */ |
| 51063 | + int bReadonly; /* True if hShm is opened read-only */ |
| 50684 | 51064 | #if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE) |
| 50685 | 51065 | u8 id; /* Id of this connection with its winShmNode */ |
| 50686 | 51066 | #endif |
| 50687 | 51067 | }; |
| 50688 | 51068 | |
| | @@ -50690,54 +51070,10 @@ |
| 50690 | 51070 | ** Constants used for locking |
| 50691 | 51071 | */ |
| 50692 | 51072 | #define WIN_SHM_BASE ((22+SQLITE_SHM_NLOCK)*4) /* first lock byte */ |
| 50693 | 51073 | #define WIN_SHM_DMS (WIN_SHM_BASE+SQLITE_SHM_NLOCK) /* deadman switch */ |
| 50694 | 51074 | |
| 50695 | | -/* |
| 50696 | | -** Apply advisory locks for all n bytes beginning at ofst. |
| 50697 | | -*/ |
| 50698 | | -#define WINSHM_UNLCK 1 |
| 50699 | | -#define WINSHM_RDLCK 2 |
| 50700 | | -#define WINSHM_WRLCK 3 |
| 50701 | | -static int winShmSystemLock( |
| 50702 | | - winShmNode *pFile, /* Apply locks to this open shared-memory segment */ |
| 50703 | | - int lockType, /* WINSHM_UNLCK, WINSHM_RDLCK, or WINSHM_WRLCK */ |
| 50704 | | - int ofst, /* Offset to first byte to be locked/unlocked */ |
| 50705 | | - int nByte /* Number of bytes to lock or unlock */ |
| 50706 | | -){ |
| 50707 | | - int rc = 0; /* Result code form Lock/UnlockFileEx() */ |
| 50708 | | - |
| 50709 | | - /* Access to the winShmNode object is serialized by the caller */ |
| 50710 | | - assert( pFile->nRef==0 || sqlite3_mutex_held(pFile->mutex) ); |
| 50711 | | - |
| 50712 | | - OSTRACE(("SHM-LOCK file=%p, lock=%d, offset=%d, size=%d\n", |
| 50713 | | - pFile->hFile.h, lockType, ofst, nByte)); |
| 50714 | | - |
| 50715 | | - /* Release/Acquire the system-level lock */ |
| 50716 | | - if( lockType==WINSHM_UNLCK ){ |
| 50717 | | - rc = winUnlockFile(&pFile->hFile.h, ofst, 0, nByte, 0); |
| 50718 | | - }else{ |
| 50719 | | - /* Initialize the locking parameters */ |
| 50720 | | - DWORD dwFlags = LOCKFILE_FAIL_IMMEDIATELY; |
| 50721 | | - if( lockType == WINSHM_WRLCK ) dwFlags |= LOCKFILE_EXCLUSIVE_LOCK; |
| 50722 | | - rc = winLockFile(&pFile->hFile.h, dwFlags, ofst, 0, nByte, 0); |
| 50723 | | - } |
| 50724 | | - |
| 50725 | | - if( rc!= 0 ){ |
| 50726 | | - rc = SQLITE_OK; |
| 50727 | | - }else{ |
| 50728 | | - pFile->lastErrno = osGetLastError(); |
| 50729 | | - rc = SQLITE_BUSY; |
| 50730 | | - } |
| 50731 | | - |
| 50732 | | - OSTRACE(("SHM-LOCK file=%p, func=%s, errno=%lu, rc=%s\n", |
| 50733 | | - pFile->hFile.h, (lockType == WINSHM_UNLCK) ? "winUnlockFile" : |
| 50734 | | - "winLockFile", pFile->lastErrno, sqlite3ErrName(rc))); |
| 50735 | | - |
| 50736 | | - return rc; |
| 50737 | | -} |
| 50738 | | - |
| 50739 | 51075 | /* Forward references to VFS methods */ |
| 50740 | 51076 | static int winOpen(sqlite3_vfs*,const char*,sqlite3_file*,int,int*); |
| 50741 | 51077 | static int winDelete(sqlite3_vfs *,const char*,int); |
| 50742 | 51078 | |
| 50743 | 51079 | /* |
| | @@ -50765,15 +51101,11 @@ |
| 50765 | 51101 | bRc = osCloseHandle(p->aRegion[i].hMap); |
| 50766 | 51102 | OSTRACE(("SHM-PURGE-CLOSE pid=%lu, region=%d, rc=%s\n", |
| 50767 | 51103 | osGetCurrentProcessId(), i, bRc ? "ok" : "failed")); |
| 50768 | 51104 | UNUSED_VARIABLE_VALUE(bRc); |
| 50769 | 51105 | } |
| 50770 | | - if( p->hFile.h!=NULL && p->hFile.h!=INVALID_HANDLE_VALUE ){ |
| 50771 | | - SimulateIOErrorBenign(1); |
| 50772 | | - winClose((sqlite3_file *)&p->hFile); |
| 50773 | | - SimulateIOErrorBenign(0); |
| 50774 | | - } |
| 51106 | + winHandleClose(p->hSharedShm); |
| 50775 | 51107 | if( deleteFlag ){ |
| 50776 | 51108 | SimulateIOErrorBenign(1); |
| 50777 | 51109 | sqlite3BeginBenignMalloc(); |
| 50778 | 51110 | winDelete(pVfs, p->zFilename, 0); |
| 50779 | 51111 | sqlite3EndBenignMalloc(); |
| | @@ -50787,46 +51119,166 @@ |
| 50787 | 51119 | } |
| 50788 | 51120 | } |
| 50789 | 51121 | } |
| 50790 | 51122 | |
| 50791 | 51123 | /* |
| 50792 | | -** The DMS lock has not yet been taken on shm file pShmNode. Attempt to |
| 50793 | | -** take it now. Return SQLITE_OK if successful, or an SQLite error |
| 50794 | | -** code otherwise. |
| 50795 | | -** |
| 50796 | | -** If the DMS cannot be locked because this is a readonly_shm=1 |
| 50797 | | -** connection and no other process already holds a lock, return |
| 50798 | | -** SQLITE_READONLY_CANTINIT and set pShmNode->isUnlocked=1. |
| 51124 | +** The DMS lock has not yet been taken on the shm file associated with |
| 51125 | +** pShmNode. Take the lock. Truncate the *-shm file if required. |
| 51126 | +** Return SQLITE_OK if successful, or an SQLite error code otherwise. |
| 50799 | 51127 | */ |
| 50800 | | -static int winLockSharedMemory(winShmNode *pShmNode){ |
| 50801 | | - int rc = winShmSystemLock(pShmNode, WINSHM_WRLCK, WIN_SHM_DMS, 1); |
| 51128 | +static int winLockSharedMemory(winShmNode *pShmNode, DWORD nMs){ |
| 51129 | + HANDLE h = pShmNode->hSharedShm; |
| 51130 | + int rc = SQLITE_OK; |
| 50802 | 51131 | |
| 51132 | + assert( sqlite3_mutex_held(pShmNode->mutex) ); |
| 51133 | + rc = winHandleLockTimeout(h, WIN_SHM_DMS, 1, 1, 0); |
| 50803 | 51134 | if( rc==SQLITE_OK ){ |
| 51135 | + /* We have an EXCLUSIVE lock on the DMS byte. This means that this |
| 51136 | + ** is the first process to open the file. Truncate it to zero bytes |
| 51137 | + ** in this case. */ |
| 50804 | 51138 | if( pShmNode->isReadonly ){ |
| 50805 | | - pShmNode->isUnlocked = 1; |
| 50806 | | - winShmSystemLock(pShmNode, WINSHM_UNLCK, WIN_SHM_DMS, 1); |
| 50807 | | - return SQLITE_READONLY_CANTINIT; |
| 50808 | | - }else if( winTruncate((sqlite3_file*)&pShmNode->hFile, 0) ){ |
| 50809 | | - winShmSystemLock(pShmNode, WINSHM_UNLCK, WIN_SHM_DMS, 1); |
| 50810 | | - return winLogError(SQLITE_IOERR_SHMOPEN, osGetLastError(), |
| 50811 | | - "winLockSharedMemory", pShmNode->zFilename); |
| 50812 | | - } |
| 50813 | | - } |
| 50814 | | - |
| 50815 | | - if( rc==SQLITE_OK ){ |
| 50816 | | - winShmSystemLock(pShmNode, WINSHM_UNLCK, WIN_SHM_DMS, 1); |
| 50817 | | - } |
| 50818 | | - |
| 50819 | | - return winShmSystemLock(pShmNode, WINSHM_RDLCK, WIN_SHM_DMS, 1); |
| 50820 | | -} |
| 50821 | | - |
| 50822 | | -/* |
| 50823 | | -** Open the shared-memory area associated with database file pDbFd. |
| 50824 | | -** |
| 50825 | | -** When opening a new shared-memory file, if no other instances of that |
| 50826 | | -** file are currently open, in this process or in other processes, then |
| 50827 | | -** the file must be truncated to zero length or have its header cleared. |
| 51139 | + rc = SQLITE_READONLY_CANTINIT; |
| 51140 | + }else{ |
| 51141 | + rc = winHandleTruncate(h, 0); |
| 51142 | + } |
| 51143 | + |
| 51144 | + /* Release the EXCLUSIVE lock acquired above. */ |
| 51145 | + winUnlockFile(&h, WIN_SHM_DMS, 0, 1, 0); |
| 51146 | + }else if( (rc & 0xFF)==SQLITE_BUSY ){ |
| 51147 | + rc = SQLITE_OK; |
| 51148 | + } |
| 51149 | + |
| 51150 | + if( rc==SQLITE_OK ){ |
| 51151 | + /* Take a SHARED lock on the DMS byte. */ |
| 51152 | + rc = winHandleLockTimeout(h, WIN_SHM_DMS, 1, 0, nMs); |
| 51153 | + if( rc==SQLITE_OK ){ |
| 51154 | + pShmNode->isUnlocked = 0; |
| 51155 | + } |
| 51156 | + } |
| 51157 | + |
| 51158 | + return rc; |
| 51159 | +} |
| 51160 | + |
| 51161 | + |
| 51162 | +/* |
| 51163 | +** Convert a UTF-8 filename into whatever form the underlying |
| 51164 | +** operating system wants filenames in. Space to hold the result |
| 51165 | +** is obtained from malloc and must be freed by the calling |
| 51166 | +** function. |
| 51167 | +*/ |
| 51168 | +static void *winConvertFromUtf8Filename(const char *zFilename){ |
| 51169 | + void *zConverted = 0; |
| 51170 | + if( osIsNT() ){ |
| 51171 | + zConverted = winUtf8ToUnicode(zFilename); |
| 51172 | + } |
| 51173 | +#ifdef SQLITE_WIN32_HAS_ANSI |
| 51174 | + else{ |
| 51175 | + zConverted = winUtf8ToMbcs(zFilename, osAreFileApisANSI()); |
| 51176 | + } |
| 51177 | +#endif |
| 51178 | + /* caller will handle out of memory */ |
| 51179 | + return zConverted; |
| 51180 | +} |
| 51181 | + |
| 51182 | +/* |
| 51183 | +** This function is used to open a handle on a *-shm file. |
| 51184 | +** |
| 51185 | +** If SQLITE_ENABLE_SETLK_TIMEOUT is defined at build time, then the file |
| 51186 | +** is opened with FILE_FLAG_OVERLAPPED specified. If not, it is not. |
| 51187 | +*/ |
| 51188 | +static int winHandleOpen( |
| 51189 | + const char *zUtf8, /* File to open */ |
| 51190 | + int *pbReadonly, /* IN/OUT: True for readonly handle */ |
| 51191 | + HANDLE *ph /* OUT: New HANDLE for file */ |
| 51192 | +){ |
| 51193 | + int rc = SQLITE_OK; |
| 51194 | + void *zConverted = 0; |
| 51195 | + int bReadonly = *pbReadonly; |
| 51196 | + HANDLE h = INVALID_HANDLE_VALUE; |
| 51197 | + |
| 51198 | +#ifdef SQLITE_ENABLE_SETLK_TIMEOUT |
| 51199 | + const DWORD flag_overlapped = FILE_FLAG_OVERLAPPED; |
| 51200 | +#else |
| 51201 | + const DWORD flag_overlapped = 0; |
| 51202 | +#endif |
| 51203 | + |
| 51204 | + /* Convert the filename to the system encoding. */ |
| 51205 | + zConverted = winConvertFromUtf8Filename(zUtf8); |
| 51206 | + if( zConverted==0 ){ |
| 51207 | + OSTRACE(("OPEN name=%s, rc=SQLITE_IOERR_NOMEM", zUtf8)); |
| 51208 | + rc = SQLITE_IOERR_NOMEM_BKPT; |
| 51209 | + goto winopenfile_out; |
| 51210 | + } |
| 51211 | + |
| 51212 | + /* Ensure the file we are trying to open is not actually a directory. */ |
| 51213 | + if( winIsDir(zConverted) ){ |
| 51214 | + OSTRACE(("OPEN name=%s, rc=SQLITE_CANTOPEN_ISDIR", zUtf8)); |
| 51215 | + rc = SQLITE_CANTOPEN_ISDIR; |
| 51216 | + goto winopenfile_out; |
| 51217 | + } |
| 51218 | + |
| 51219 | + /* TODO: platforms. |
| 51220 | + ** TODO: retry-on-ioerr. |
| 51221 | + */ |
| 51222 | + if( osIsNT() ){ |
| 51223 | +#if SQLITE_OS_WINRT |
| 51224 | + CREATEFILE2_EXTENDED_PARAMETERS extendedParameters; |
| 51225 | + memset(&extendedParameters, 0, sizeof(extendedParameters)); |
| 51226 | + extendedParameters.dwSize = sizeof(extendedParameters); |
| 51227 | + extendedParameters.dwFileAttributes = FILE_ATTRIBUTE_NORMAL; |
| 51228 | + extendedParameters.dwFileFlags = flag_overlapped; |
| 51229 | + extendedParameters.dwSecurityQosFlags = SECURITY_ANONYMOUS; |
| 51230 | + h = osCreateFile2((LPCWSTR)zConverted, |
| 51231 | + (GENERIC_READ | (bReadonly ? 0 : GENERIC_WRITE)),/* dwDesiredAccess */ |
| 51232 | + FILE_SHARE_READ | FILE_SHARE_WRITE, /* dwShareMode */ |
| 51233 | + OPEN_ALWAYS, /* dwCreationDisposition */ |
| 51234 | + &extendedParameters |
| 51235 | + ); |
| 51236 | +#else |
| 51237 | + h = osCreateFileW((LPCWSTR)zConverted, /* lpFileName */ |
| 51238 | + (GENERIC_READ | (bReadonly ? 0 : GENERIC_WRITE)), /* dwDesiredAccess */ |
| 51239 | + FILE_SHARE_READ | FILE_SHARE_WRITE, /* dwShareMode */ |
| 51240 | + NULL, /* lpSecurityAttributes */ |
| 51241 | + OPEN_ALWAYS, /* dwCreationDisposition */ |
| 51242 | + FILE_ATTRIBUTE_NORMAL|flag_overlapped, |
| 51243 | + NULL |
| 51244 | + ); |
| 51245 | +#endif |
| 51246 | + }else{ |
| 51247 | + /* Due to pre-processor directives earlier in this file, |
| 51248 | + ** SQLITE_WIN32_HAS_ANSI is always defined if osIsNT() is false. */ |
| 51249 | +#ifdef SQLITE_WIN32_HAS_ANSI |
| 51250 | + h = osCreateFileA((LPCSTR)zConverted, |
| 51251 | + (GENERIC_READ | (bReadonly ? 0 : GENERIC_WRITE)), /* dwDesiredAccess */ |
| 51252 | + FILE_SHARE_READ | FILE_SHARE_WRITE, /* dwShareMode */ |
| 51253 | + NULL, /* lpSecurityAttributes */ |
| 51254 | + OPEN_ALWAYS, /* dwCreationDisposition */ |
| 51255 | + FILE_ATTRIBUTE_NORMAL|flag_overlapped, |
| 51256 | + NULL |
| 51257 | + ); |
| 51258 | +#endif |
| 51259 | + } |
| 51260 | + |
| 51261 | + if( h==INVALID_HANDLE_VALUE ){ |
| 51262 | + if( bReadonly==0 ){ |
| 51263 | + bReadonly = 1; |
| 51264 | + rc = winHandleOpen(zUtf8, &bReadonly, &h); |
| 51265 | + }else{ |
| 51266 | + rc = SQLITE_CANTOPEN_BKPT; |
| 51267 | + } |
| 51268 | + } |
| 51269 | + |
| 51270 | + winopenfile_out: |
| 51271 | + sqlite3_free(zConverted); |
| 51272 | + *pbReadonly = bReadonly; |
| 51273 | + *ph = h; |
| 51274 | + return rc; |
| 51275 | +} |
| 51276 | + |
| 51277 | + |
| 51278 | +/* |
| 51279 | +** Open the shared-memory area associated with database file pDbFd. |
| 50828 | 51280 | */ |
| 50829 | 51281 | static int winOpenSharedMemory(winFile *pDbFd){ |
| 50830 | 51282 | struct winShm *p; /* The connection to be opened */ |
| 50831 | 51283 | winShmNode *pShmNode = 0; /* The underlying mmapped file */ |
| 50832 | 51284 | int rc = SQLITE_OK; /* Result code */ |
| | @@ -50834,102 +51286,87 @@ |
| 50834 | 51286 | int nName; /* Size of zName in bytes */ |
| 50835 | 51287 | |
| 50836 | 51288 | assert( pDbFd->pShm==0 ); /* Not previously opened */ |
| 50837 | 51289 | |
| 50838 | 51290 | /* Allocate space for the new sqlite3_shm object. Also speculatively |
| 50839 | | - ** allocate space for a new winShmNode and filename. |
| 50840 | | - */ |
| 51291 | + ** allocate space for a new winShmNode and filename. */ |
| 50841 | 51292 | p = sqlite3MallocZero( sizeof(*p) ); |
| 50842 | 51293 | if( p==0 ) return SQLITE_IOERR_NOMEM_BKPT; |
| 50843 | 51294 | nName = sqlite3Strlen30(pDbFd->zPath); |
| 50844 | 51295 | pNew = sqlite3MallocZero( sizeof(*pShmNode) + (i64)nName + 17 ); |
| 50845 | 51296 | if( pNew==0 ){ |
| 50846 | 51297 | sqlite3_free(p); |
| 50847 | 51298 | return SQLITE_IOERR_NOMEM_BKPT; |
| 50848 | 51299 | } |
| 50849 | 51300 | pNew->zFilename = (char*)&pNew[1]; |
| 51301 | + pNew->hSharedShm = INVALID_HANDLE_VALUE; |
| 51302 | + pNew->isUnlocked = 1; |
| 50850 | 51303 | sqlite3_snprintf(nName+15, pNew->zFilename, "%s-shm", pDbFd->zPath); |
| 50851 | 51304 | sqlite3FileSuffix3(pDbFd->zPath, pNew->zFilename); |
| 51305 | + |
| 51306 | + /* Open a file-handle on the *-shm file for this connection. This file-handle |
| 51307 | + ** is only used for locking. The mapping of the *-shm file is created using |
| 51308 | + ** the shared file handle in winShmNode.hSharedShm. */ |
| 51309 | + p->bReadonly = sqlite3_uri_boolean(pDbFd->zPath, "readonly_shm", 0); |
| 51310 | + rc = winHandleOpen(pNew->zFilename, &p->bReadonly, &p->hShm); |
| 50852 | 51311 | |
| 50853 | 51312 | /* Look to see if there is an existing winShmNode that can be used. |
| 50854 | | - ** If no matching winShmNode currently exists, create a new one. |
| 50855 | | - */ |
| 51313 | + ** If no matching winShmNode currently exists, then create a new one. */ |
| 50856 | 51314 | winShmEnterMutex(); |
| 50857 | 51315 | for(pShmNode = winShmNodeList; pShmNode; pShmNode=pShmNode->pNext){ |
| 50858 | 51316 | /* TBD need to come up with better match here. Perhaps |
| 50859 | | - ** use FILE_ID_BOTH_DIR_INFO Structure. |
| 50860 | | - */ |
| 51317 | + ** use FILE_ID_BOTH_DIR_INFO Structure. */ |
| 50861 | 51318 | if( sqlite3StrICmp(pShmNode->zFilename, pNew->zFilename)==0 ) break; |
| 50862 | 51319 | } |
| 50863 | | - if( pShmNode ){ |
| 50864 | | - sqlite3_free(pNew); |
| 50865 | | - }else{ |
| 50866 | | - int inFlags = SQLITE_OPEN_WAL; |
| 50867 | | - int outFlags = 0; |
| 50868 | | - |
| 51320 | + if( pShmNode==0 ){ |
| 50869 | 51321 | pShmNode = pNew; |
| 50870 | | - pNew = 0; |
| 50871 | | - ((winFile*)(&pShmNode->hFile))->h = INVALID_HANDLE_VALUE; |
| 50872 | | - pShmNode->pNext = winShmNodeList; |
| 50873 | | - winShmNodeList = pShmNode; |
| 50874 | 51322 | |
| 51323 | + /* Allocate a mutex for this winShmNode object, if one is required. */ |
| 50875 | 51324 | if( sqlite3GlobalConfig.bCoreMutex ){ |
| 50876 | 51325 | pShmNode->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST); |
| 50877 | | - if( pShmNode->mutex==0 ){ |
| 50878 | | - rc = SQLITE_IOERR_NOMEM_BKPT; |
| 50879 | | - goto shm_open_err; |
| 50880 | | - } |
| 50881 | | - } |
| 50882 | | - |
| 50883 | | - if( 0==sqlite3_uri_boolean(pDbFd->zPath, "readonly_shm", 0) ){ |
| 50884 | | - inFlags |= SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE; |
| 50885 | | - }else{ |
| 50886 | | - inFlags |= SQLITE_OPEN_READONLY; |
| 50887 | | - } |
| 50888 | | - rc = winOpen(pDbFd->pVfs, pShmNode->zFilename, |
| 50889 | | - (sqlite3_file*)&pShmNode->hFile, |
| 50890 | | - inFlags, &outFlags); |
| 50891 | | - if( rc!=SQLITE_OK ){ |
| 50892 | | - rc = winLogError(rc, osGetLastError(), "winOpenShm", |
| 50893 | | - pShmNode->zFilename); |
| 50894 | | - goto shm_open_err; |
| 50895 | | - } |
| 50896 | | - if( outFlags==SQLITE_OPEN_READONLY ) pShmNode->isReadonly = 1; |
| 50897 | | - |
| 50898 | | - rc = winLockSharedMemory(pShmNode); |
| 50899 | | - if( rc!=SQLITE_OK && rc!=SQLITE_READONLY_CANTINIT ) goto shm_open_err; |
| 50900 | | - } |
| 50901 | | - |
| 50902 | | - /* Make the new connection a child of the winShmNode */ |
| 50903 | | - p->pShmNode = pShmNode; |
| 51326 | + if( pShmNode->mutex==0 ) rc = SQLITE_IOERR_NOMEM_BKPT; |
| 51327 | + } |
| 51328 | + |
| 51329 | + /* Open a file-handle to use for mappings, and for the DMS lock. */ |
| 51330 | + if( rc==SQLITE_OK ){ |
| 51331 | + HANDLE h = INVALID_HANDLE_VALUE; |
| 51332 | + pShmNode->isReadonly = p->bReadonly; |
| 51333 | + rc = winHandleOpen(pNew->zFilename, &pShmNode->isReadonly, &h); |
| 51334 | + pShmNode->hSharedShm = h; |
| 51335 | + } |
| 51336 | + |
| 51337 | + /* If successful, link the new winShmNode into the global list. If an |
| 51338 | + ** error occurred, free the object. */ |
| 51339 | + if( rc==SQLITE_OK ){ |
| 51340 | + pShmNode->pNext = winShmNodeList; |
| 51341 | + winShmNodeList = pShmNode; |
| 51342 | + pNew = 0; |
| 51343 | + }else{ |
| 51344 | + sqlite3_mutex_free(pShmNode->mutex); |
| 51345 | + if( pShmNode->hSharedShm!=INVALID_HANDLE_VALUE ){ |
| 51346 | + osCloseHandle(pShmNode->hSharedShm); |
| 51347 | + } |
| 51348 | + } |
| 51349 | + } |
| 51350 | + |
| 51351 | + /* If no error has occurred, link the winShm object to the winShmNode and |
| 51352 | + ** the winShm to pDbFd. */ |
| 51353 | + if( rc==SQLITE_OK ){ |
| 51354 | + p->pShmNode = pShmNode; |
| 51355 | + pShmNode->nRef++; |
| 50904 | 51356 | #if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE) |
| 50905 | | - p->id = pShmNode->nextShmId++; |
| 50906 | | -#endif |
| 50907 | | - pShmNode->nRef++; |
| 50908 | | - pDbFd->pShm = p; |
| 50909 | | - winShmLeaveMutex(); |
| 50910 | | - |
| 50911 | | - /* The reference count on pShmNode has already been incremented under |
| 50912 | | - ** the cover of the winShmEnterMutex() mutex and the pointer from the |
| 50913 | | - ** new (struct winShm) object to the pShmNode has been set. All that is |
| 50914 | | - ** left to do is to link the new object into the linked list starting |
| 50915 | | - ** at pShmNode->pFirst. This must be done while holding the pShmNode->mutex |
| 50916 | | - ** mutex. |
| 50917 | | - */ |
| 50918 | | - sqlite3_mutex_enter(pShmNode->mutex); |
| 50919 | | - p->pNext = pShmNode->pFirst; |
| 50920 | | - pShmNode->pFirst = p; |
| 50921 | | - sqlite3_mutex_leave(pShmNode->mutex); |
| 50922 | | - return rc; |
| 50923 | | - |
| 50924 | | - /* Jump here on any error */ |
| 50925 | | -shm_open_err: |
| 50926 | | - winShmSystemLock(pShmNode, WINSHM_UNLCK, WIN_SHM_DMS, 1); |
| 50927 | | - winShmPurge(pDbFd->pVfs, 0); /* This call frees pShmNode if required */ |
| 50928 | | - sqlite3_free(p); |
| 50929 | | - sqlite3_free(pNew); |
| 50930 | | - winShmLeaveMutex(); |
| 51357 | + p->id = pShmNode->nextShmId++; |
| 51358 | +#endif |
| 51359 | + pDbFd->pShm = p; |
| 51360 | + }else if( p ){ |
| 51361 | + winHandleClose(p->hShm); |
| 51362 | + sqlite3_free(p); |
| 51363 | + } |
| 51364 | + |
| 51365 | + assert( rc!=SQLITE_OK || pShmNode->isUnlocked==0 || pShmNode->nRegion==0 ); |
| 51366 | + winShmLeaveMutex(); |
| 51367 | + sqlite3_free(pNew); |
| 50931 | 51368 | return rc; |
| 50932 | 51369 | } |
| 50933 | 51370 | |
| 50934 | 51371 | /* |
| 50935 | 51372 | ** Close a connection to shared-memory. Delete the underlying |
| | @@ -50940,38 +51377,33 @@ |
| 50940 | 51377 | int deleteFlag /* Delete after closing if true */ |
| 50941 | 51378 | ){ |
| 50942 | 51379 | winFile *pDbFd; /* Database holding shared-memory */ |
| 50943 | 51380 | winShm *p; /* The connection to be closed */ |
| 50944 | 51381 | winShmNode *pShmNode; /* The underlying shared-memory file */ |
| 50945 | | - winShm **pp; /* For looping over sibling connections */ |
| 50946 | 51382 | |
| 50947 | 51383 | pDbFd = (winFile*)fd; |
| 50948 | 51384 | p = pDbFd->pShm; |
| 50949 | 51385 | if( p==0 ) return SQLITE_OK; |
| 51386 | + if( p->hShm!=INVALID_HANDLE_VALUE ){ |
| 51387 | + osCloseHandle(p->hShm); |
| 51388 | + } |
| 51389 | + |
| 50950 | 51390 | pShmNode = p->pShmNode; |
| 50951 | | - |
| 50952 | | - /* Remove connection p from the set of connections associated |
| 50953 | | - ** with pShmNode */ |
| 50954 | | - sqlite3_mutex_enter(pShmNode->mutex); |
| 50955 | | - for(pp=&pShmNode->pFirst; (*pp)!=p; pp = &(*pp)->pNext){} |
| 50956 | | - *pp = p->pNext; |
| 50957 | | - |
| 50958 | | - /* Free the connection p */ |
| 50959 | | - sqlite3_free(p); |
| 50960 | | - pDbFd->pShm = 0; |
| 50961 | | - sqlite3_mutex_leave(pShmNode->mutex); |
| 51391 | + winShmEnterMutex(); |
| 50962 | 51392 | |
| 50963 | 51393 | /* If pShmNode->nRef has reached 0, then close the underlying |
| 50964 | | - ** shared-memory file, too */ |
| 50965 | | - winShmEnterMutex(); |
| 51394 | + ** shared-memory file, too. */ |
| 50966 | 51395 | assert( pShmNode->nRef>0 ); |
| 50967 | 51396 | pShmNode->nRef--; |
| 50968 | 51397 | if( pShmNode->nRef==0 ){ |
| 50969 | 51398 | winShmPurge(pDbFd->pVfs, deleteFlag); |
| 50970 | 51399 | } |
| 50971 | 51400 | winShmLeaveMutex(); |
| 50972 | 51401 | |
| 51402 | + /* Free the connection p */ |
| 51403 | + sqlite3_free(p); |
| 51404 | + pDbFd->pShm = 0; |
| 50973 | 51405 | return SQLITE_OK; |
| 50974 | 51406 | } |
| 50975 | 51407 | |
| 50976 | 51408 | /* |
| 50977 | 51409 | ** Change the lock state for a shared-memory segment. |
| | @@ -50982,14 +51414,13 @@ |
| 50982 | 51414 | int n, /* Number of locks to acquire or release */ |
| 50983 | 51415 | int flags /* What to do with the lock */ |
| 50984 | 51416 | ){ |
| 50985 | 51417 | winFile *pDbFd = (winFile*)fd; /* Connection holding shared memory */ |
| 50986 | 51418 | winShm *p = pDbFd->pShm; /* The shared memory being locked */ |
| 50987 | | - winShm *pX; /* For looping over all siblings */ |
| 50988 | 51419 | winShmNode *pShmNode; |
| 50989 | 51420 | int rc = SQLITE_OK; /* Result code */ |
| 50990 | | - u16 mask; /* Mask of locks to take or release */ |
| 51421 | + u16 mask = (u16)((1U<<(ofst+n)) - (1U<<ofst)); /* Mask of locks to [un]take */ |
| 50991 | 51422 | |
| 50992 | 51423 | if( p==0 ) return SQLITE_IOERR_SHMLOCK; |
| 50993 | 51424 | pShmNode = p->pShmNode; |
| 50994 | 51425 | if( NEVER(pShmNode==0) ) return SQLITE_IOERR_SHMLOCK; |
| 50995 | 51426 | |
| | @@ -50999,89 +51430,86 @@ |
| 50999 | 51430 | || flags==(SQLITE_SHM_LOCK | SQLITE_SHM_EXCLUSIVE) |
| 51000 | 51431 | || flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED) |
| 51001 | 51432 | || flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE) ); |
| 51002 | 51433 | assert( n==1 || (flags & SQLITE_SHM_EXCLUSIVE)!=0 ); |
| 51003 | 51434 | |
| 51004 | | - mask = (u16)((1U<<(ofst+n)) - (1U<<ofst)); |
| 51005 | | - assert( n>1 || mask==(1<<ofst) ); |
| 51006 | | - sqlite3_mutex_enter(pShmNode->mutex); |
| 51007 | | - if( flags & SQLITE_SHM_UNLOCK ){ |
| 51008 | | - u16 allMask = 0; /* Mask of locks held by siblings */ |
| 51009 | | - |
| 51010 | | - /* See if any siblings hold this same lock */ |
| 51011 | | - for(pX=pShmNode->pFirst; pX; pX=pX->pNext){ |
| 51012 | | - if( pX==p ) continue; |
| 51013 | | - assert( (pX->exclMask & (p->exclMask|p->sharedMask))==0 ); |
| 51014 | | - allMask |= pX->sharedMask; |
| 51015 | | - } |
| 51016 | | - |
| 51017 | | - /* Unlock the system-level locks */ |
| 51018 | | - if( (mask & allMask)==0 ){ |
| 51019 | | - rc = winShmSystemLock(pShmNode, WINSHM_UNLCK, ofst+WIN_SHM_BASE, n); |
| 51020 | | - }else{ |
| 51021 | | - rc = SQLITE_OK; |
| 51022 | | - } |
| 51023 | | - |
| 51024 | | - /* Undo the local locks */ |
| 51025 | | - if( rc==SQLITE_OK ){ |
| 51026 | | - p->exclMask &= ~mask; |
| 51027 | | - p->sharedMask &= ~mask; |
| 51028 | | - } |
| 51029 | | - }else if( flags & SQLITE_SHM_SHARED ){ |
| 51030 | | - u16 allShared = 0; /* Union of locks held by connections other than "p" */ |
| 51031 | | - |
| 51032 | | - /* Find out which shared locks are already held by sibling connections. |
| 51033 | | - ** If any sibling already holds an exclusive lock, go ahead and return |
| 51034 | | - ** SQLITE_BUSY. |
| 51035 | | - */ |
| 51036 | | - for(pX=pShmNode->pFirst; pX; pX=pX->pNext){ |
| 51037 | | - if( (pX->exclMask & mask)!=0 ){ |
| 51038 | | - rc = SQLITE_BUSY; |
| 51039 | | - break; |
| 51040 | | - } |
| 51041 | | - allShared |= pX->sharedMask; |
| 51042 | | - } |
| 51043 | | - |
| 51044 | | - /* Get shared locks at the system level, if necessary */ |
| 51045 | | - if( rc==SQLITE_OK ){ |
| 51046 | | - if( (allShared & mask)==0 ){ |
| 51047 | | - rc = winShmSystemLock(pShmNode, WINSHM_RDLCK, ofst+WIN_SHM_BASE, n); |
| 51048 | | - }else{ |
| 51049 | | - rc = SQLITE_OK; |
| 51050 | | - } |
| 51051 | | - } |
| 51052 | | - |
| 51053 | | - /* Get the local shared locks */ |
| 51054 | | - if( rc==SQLITE_OK ){ |
| 51055 | | - p->sharedMask |= mask; |
| 51056 | | - } |
| 51057 | | - }else{ |
| 51058 | | - /* Make sure no sibling connections hold locks that will block this |
| 51059 | | - ** lock. If any do, return SQLITE_BUSY right away. |
| 51060 | | - */ |
| 51061 | | - for(pX=pShmNode->pFirst; pX; pX=pX->pNext){ |
| 51062 | | - if( (pX->exclMask & mask)!=0 || (pX->sharedMask & mask)!=0 ){ |
| 51063 | | - rc = SQLITE_BUSY; |
| 51064 | | - break; |
| 51065 | | - } |
| 51066 | | - } |
| 51067 | | - |
| 51068 | | - /* Get the exclusive locks at the system level. Then if successful |
| 51069 | | - ** also mark the local connection as being locked. |
| 51070 | | - */ |
| 51071 | | - if( rc==SQLITE_OK ){ |
| 51072 | | - rc = winShmSystemLock(pShmNode, WINSHM_WRLCK, ofst+WIN_SHM_BASE, n); |
| 51073 | | - if( rc==SQLITE_OK ){ |
| 51074 | | - assert( (p->sharedMask & mask)==0 ); |
| 51075 | | - p->exclMask |= mask; |
| 51076 | | - } |
| 51077 | | - } |
| 51078 | | - } |
| 51079 | | - sqlite3_mutex_leave(pShmNode->mutex); |
| 51080 | | - OSTRACE(("SHM-LOCK pid=%lu, id=%d, sharedMask=%03x, exclMask=%03x, rc=%s\n", |
| 51081 | | - osGetCurrentProcessId(), p->id, p->sharedMask, p->exclMask, |
| 51082 | | - sqlite3ErrName(rc))); |
| 51435 | + /* Check that, if this to be a blocking lock, no locks that occur later |
| 51436 | + ** in the following list than the lock being obtained are already held: |
| 51437 | + ** |
| 51438 | + ** 1. Checkpointer lock (ofst==1). |
| 51439 | + ** 2. Write lock (ofst==0). |
| 51440 | + ** 3. Read locks (ofst>=3 && ofst<SQLITE_SHM_NLOCK). |
| 51441 | + ** |
| 51442 | + ** In other words, if this is a blocking lock, none of the locks that |
| 51443 | + ** occur later in the above list than the lock being obtained may be |
| 51444 | + ** held. |
| 51445 | + ** |
| 51446 | + ** It is not permitted to block on the RECOVER lock. |
| 51447 | + */ |
| 51448 | +#if defined(SQLITE_ENABLE_SETLK_TIMEOUT) && defined(SQLITE_DEBUG) |
| 51449 | + { |
| 51450 | + u16 lockMask = (p->exclMask|p->sharedMask); |
| 51451 | + assert( (flags & SQLITE_SHM_UNLOCK) || pDbFd->iBusyTimeout==0 || ( |
| 51452 | + (ofst!=2) /* not RECOVER */ |
| 51453 | + && (ofst!=1 || lockMask==0 || lockMask==2) |
| 51454 | + && (ofst!=0 || lockMask<3) |
| 51455 | + && (ofst<3 || lockMask<(1<<ofst)) |
| 51456 | + )); |
| 51457 | + } |
| 51458 | +#endif |
| 51459 | + |
| 51460 | + /* Check if there is any work to do. There are three cases: |
| 51461 | + ** |
| 51462 | + ** a) An unlock operation where there are locks to unlock, |
| 51463 | + ** b) An shared lock where the requested lock is not already held |
| 51464 | + ** c) An exclusive lock where the requested lock is not already held |
| 51465 | + ** |
| 51466 | + ** The SQLite core never requests an exclusive lock that it already holds. |
| 51467 | + ** This is assert()ed immediately below. */ |
| 51468 | + assert( flags!=(SQLITE_SHM_EXCLUSIVE|SQLITE_SHM_LOCK) |
| 51469 | + || 0==(p->exclMask & mask) |
| 51470 | + ); |
| 51471 | + if( ((flags & SQLITE_SHM_UNLOCK) && ((p->exclMask|p->sharedMask) & mask)) |
| 51472 | + || (flags==(SQLITE_SHM_SHARED|SQLITE_SHM_LOCK) && 0==(p->sharedMask & mask)) |
| 51473 | + || (flags==(SQLITE_SHM_EXCLUSIVE|SQLITE_SHM_LOCK)) |
| 51474 | + ){ |
| 51475 | + |
| 51476 | + if( flags & SQLITE_SHM_UNLOCK ){ |
| 51477 | + /* Case (a) - unlock. */ |
| 51478 | + |
| 51479 | + assert( (p->exclMask & p->sharedMask)==0 ); |
| 51480 | + assert( !(flags & SQLITE_SHM_EXCLUSIVE) || (p->exclMask & mask)==mask ); |
| 51481 | + assert( !(flags & SQLITE_SHM_SHARED) || (p->sharedMask & mask)==mask ); |
| 51482 | + |
| 51483 | + rc = winHandleUnlock(p->hShm, ofst+WIN_SHM_BASE, n); |
| 51484 | + |
| 51485 | + /* If successful, also clear the bits in sharedMask/exclMask */ |
| 51486 | + if( rc==SQLITE_OK ){ |
| 51487 | + p->exclMask = (p->exclMask & ~mask); |
| 51488 | + p->sharedMask = (p->sharedMask & ~mask); |
| 51489 | + } |
| 51490 | + }else{ |
| 51491 | + int bExcl = ((flags & SQLITE_SHM_EXCLUSIVE) ? 1 : 0); |
| 51492 | + DWORD nMs = winFileBusyTimeout(pDbFd); |
| 51493 | + rc = winHandleLockTimeout(p->hShm, ofst+WIN_SHM_BASE, n, bExcl, nMs); |
| 51494 | + if( rc==SQLITE_OK ){ |
| 51495 | + if( bExcl ){ |
| 51496 | + p->exclMask = (p->exclMask | mask); |
| 51497 | + }else{ |
| 51498 | + p->sharedMask = (p->sharedMask | mask); |
| 51499 | + } |
| 51500 | + } |
| 51501 | + } |
| 51502 | + } |
| 51503 | + |
| 51504 | + OSTRACE(( |
| 51505 | + "SHM-LOCK(%d,%d,%d) pid=%lu, id=%d, sharedMask=%03x, exclMask=%03x," |
| 51506 | + " rc=%s\n", |
| 51507 | + ofst, n, flags, |
| 51508 | + osGetCurrentProcessId(), p->id, p->sharedMask, p->exclMask, |
| 51509 | + sqlite3ErrName(rc)) |
| 51510 | + ); |
| 51083 | 51511 | return rc; |
| 51084 | 51512 | } |
| 51085 | 51513 | |
| 51086 | 51514 | /* |
| 51087 | 51515 | ** Implement a memory barrier or memory fence on shared memory. |
| | @@ -51139,17 +51567,19 @@ |
| 51139 | 51567 | } |
| 51140 | 51568 | pShmNode = pShm->pShmNode; |
| 51141 | 51569 | |
| 51142 | 51570 | sqlite3_mutex_enter(pShmNode->mutex); |
| 51143 | 51571 | if( pShmNode->isUnlocked ){ |
| 51144 | | - rc = winLockSharedMemory(pShmNode); |
| 51572 | + /* Take the DMS lock. */ |
| 51573 | + assert( pShmNode->nRegion==0 ); |
| 51574 | + rc = winLockSharedMemory(pShmNode, winFileBusyTimeout(pDbFd)); |
| 51145 | 51575 | if( rc!=SQLITE_OK ) goto shmpage_out; |
| 51146 | | - pShmNode->isUnlocked = 0; |
| 51147 | 51576 | } |
| 51577 | + |
| 51148 | 51578 | assert( szRegion==pShmNode->szRegion || pShmNode->nRegion==0 ); |
| 51149 | | - |
| 51150 | 51579 | if( pShmNode->nRegion<=iRegion ){ |
| 51580 | + HANDLE hShared = pShmNode->hSharedShm; |
| 51151 | 51581 | struct ShmRegion *apNew; /* New aRegion[] array */ |
| 51152 | 51582 | int nByte = (iRegion+1)*szRegion; /* Minimum required file size */ |
| 51153 | 51583 | sqlite3_int64 sz; /* Current size of wal-index file */ |
| 51154 | 51584 | |
| 51155 | 51585 | pShmNode->szRegion = szRegion; |
| | @@ -51156,35 +51586,32 @@ |
| 51156 | 51586 | |
| 51157 | 51587 | /* The requested region is not mapped into this processes address space. |
| 51158 | 51588 | ** Check to see if it has been allocated (i.e. if the wal-index file is |
| 51159 | 51589 | ** large enough to contain the requested region). |
| 51160 | 51590 | */ |
| 51161 | | - rc = winFileSize((sqlite3_file *)&pShmNode->hFile, &sz); |
| 51591 | + rc = winHandleSize(hShared, &sz); |
| 51162 | 51592 | if( rc!=SQLITE_OK ){ |
| 51163 | | - rc = winLogError(SQLITE_IOERR_SHMSIZE, osGetLastError(), |
| 51164 | | - "winShmMap1", pDbFd->zPath); |
| 51593 | + rc = winLogError(rc, osGetLastError(), "winShmMap1", pDbFd->zPath); |
| 51165 | 51594 | goto shmpage_out; |
| 51166 | 51595 | } |
| 51167 | 51596 | |
| 51168 | 51597 | if( sz<nByte ){ |
| 51169 | 51598 | /* The requested memory region does not exist. If isWrite is set to |
| 51170 | 51599 | ** zero, exit early. *pp will be set to NULL and SQLITE_OK returned. |
| 51171 | 51600 | ** |
| 51172 | 51601 | ** Alternatively, if isWrite is non-zero, use ftruncate() to allocate |
| 51173 | | - ** the requested memory region. |
| 51174 | | - */ |
| 51602 | + ** the requested memory region. */ |
| 51175 | 51603 | if( !isWrite ) goto shmpage_out; |
| 51176 | | - rc = winTruncate((sqlite3_file *)&pShmNode->hFile, nByte); |
| 51604 | + rc = winHandleTruncate(hShared, nByte); |
| 51177 | 51605 | if( rc!=SQLITE_OK ){ |
| 51178 | | - rc = winLogError(SQLITE_IOERR_SHMSIZE, osGetLastError(), |
| 51179 | | - "winShmMap2", pDbFd->zPath); |
| 51606 | + rc = winLogError(rc, osGetLastError(), "winShmMap2", pDbFd->zPath); |
| 51180 | 51607 | goto shmpage_out; |
| 51181 | 51608 | } |
| 51182 | 51609 | } |
| 51183 | 51610 | |
| 51184 | 51611 | /* Map the requested memory region into this processes address space. */ |
| 51185 | | - apNew = (struct ShmRegion *)sqlite3_realloc64( |
| 51612 | + apNew = (struct ShmRegion*)sqlite3_realloc64( |
| 51186 | 51613 | pShmNode->aRegion, (iRegion+1)*sizeof(apNew[0]) |
| 51187 | 51614 | ); |
| 51188 | 51615 | if( !apNew ){ |
| 51189 | 51616 | rc = SQLITE_IOERR_NOMEM_BKPT; |
| 51190 | 51617 | goto shmpage_out; |
| | @@ -51199,22 +51626,17 @@ |
| 51199 | 51626 | while( pShmNode->nRegion<=iRegion ){ |
| 51200 | 51627 | HANDLE hMap = NULL; /* file-mapping handle */ |
| 51201 | 51628 | void *pMap = 0; /* Mapped memory region */ |
| 51202 | 51629 | |
| 51203 | 51630 | #if SQLITE_OS_WINRT |
| 51204 | | - hMap = osCreateFileMappingFromApp(pShmNode->hFile.h, |
| 51205 | | - NULL, protect, nByte, NULL |
| 51206 | | - ); |
| 51631 | + hMap = osCreateFileMappingFromApp(hShared, NULL, protect, nByte, NULL); |
| 51207 | 51632 | #elif defined(SQLITE_WIN32_HAS_WIDE) |
| 51208 | | - hMap = osCreateFileMappingW(pShmNode->hFile.h, |
| 51209 | | - NULL, protect, 0, nByte, NULL |
| 51210 | | - ); |
| 51633 | + hMap = osCreateFileMappingW(hShared, NULL, protect, 0, nByte, NULL); |
| 51211 | 51634 | #elif defined(SQLITE_WIN32_HAS_ANSI) && SQLITE_WIN32_CREATEFILEMAPPINGA |
| 51212 | | - hMap = osCreateFileMappingA(pShmNode->hFile.h, |
| 51213 | | - NULL, protect, 0, nByte, NULL |
| 51214 | | - ); |
| 51635 | + hMap = osCreateFileMappingA(hShared, NULL, protect, 0, nByte, NULL); |
| 51215 | 51636 | #endif |
| 51637 | + |
| 51216 | 51638 | OSTRACE(("SHM-MAP-CREATE pid=%lu, region=%d, size=%d, rc=%s\n", |
| 51217 | 51639 | osGetCurrentProcessId(), pShmNode->nRegion, nByte, |
| 51218 | 51640 | hMap ? "ok" : "failed")); |
| 51219 | 51641 | if( hMap ){ |
| 51220 | 51642 | int iOffset = pShmNode->nRegion*szRegion; |
| | @@ -51253,11 +51675,13 @@ |
| 51253 | 51675 | char *p = (char *)pShmNode->aRegion[iRegion].pMap; |
| 51254 | 51676 | *pp = (void *)&p[iOffsetShift]; |
| 51255 | 51677 | }else{ |
| 51256 | 51678 | *pp = 0; |
| 51257 | 51679 | } |
| 51258 | | - if( pShmNode->isReadonly && rc==SQLITE_OK ) rc = SQLITE_READONLY; |
| 51680 | + if( pShmNode->isReadonly && rc==SQLITE_OK ){ |
| 51681 | + rc = SQLITE_READONLY; |
| 51682 | + } |
| 51259 | 51683 | sqlite3_mutex_leave(pShmNode->mutex); |
| 51260 | 51684 | return rc; |
| 51261 | 51685 | } |
| 51262 | 51686 | |
| 51263 | 51687 | #else |
| | @@ -51594,30 +52018,10 @@ |
| 51594 | 52018 | /* caller will handle out of memory */ |
| 51595 | 52019 | return zConverted; |
| 51596 | 52020 | } |
| 51597 | 52021 | #endif |
| 51598 | 52022 | |
| 51599 | | -/* |
| 51600 | | -** Convert a UTF-8 filename into whatever form the underlying |
| 51601 | | -** operating system wants filenames in. Space to hold the result |
| 51602 | | -** is obtained from malloc and must be freed by the calling |
| 51603 | | -** function. |
| 51604 | | -*/ |
| 51605 | | -static void *winConvertFromUtf8Filename(const char *zFilename){ |
| 51606 | | - void *zConverted = 0; |
| 51607 | | - if( osIsNT() ){ |
| 51608 | | - zConverted = winUtf8ToUnicode(zFilename); |
| 51609 | | - } |
| 51610 | | -#ifdef SQLITE_WIN32_HAS_ANSI |
| 51611 | | - else{ |
| 51612 | | - zConverted = winUtf8ToMbcs(zFilename, osAreFileApisANSI()); |
| 51613 | | - } |
| 51614 | | -#endif |
| 51615 | | - /* caller will handle out of memory */ |
| 51616 | | - return zConverted; |
| 51617 | | -} |
| 51618 | | - |
| 51619 | 52023 | /* |
| 51620 | 52024 | ** This function returns non-zero if the specified UTF-8 string buffer |
| 51621 | 52025 | ** ends with a directory separator character or one was successfully |
| 51622 | 52026 | ** added to it. |
| 51623 | 52027 | */ |
| | @@ -53067,11 +53471,11 @@ |
| 53067 | 53471 | }; |
| 53068 | 53472 | #endif |
| 53069 | 53473 | |
| 53070 | 53474 | /* Double-check that the aSyscall[] array has been constructed |
| 53071 | 53475 | ** correctly. See ticket [bb3a86e890c8e96ab] */ |
| 53072 | | - assert( ArraySize(aSyscall)==80 ); |
| 53476 | + assert( ArraySize(aSyscall)==82 ); |
| 53073 | 53477 | |
| 53074 | 53478 | /* get memory map allocation granularity */ |
| 53075 | 53479 | memset(&winSysInfo, 0, sizeof(SYSTEM_INFO)); |
| 53076 | 53480 | #if SQLITE_OS_WINRT |
| 53077 | 53481 | osGetNativeSystemInfo(&winSysInfo); |
| | @@ -54125,11 +54529,11 @@ |
| 54125 | 54529 | ** Empirical testing showed that the *37 multiplier |
| 54126 | 54530 | ** (an arbitrary prime)in the hash function provided |
| 54127 | 54531 | ** no fewer collisions than the no-op *1. */ |
| 54128 | 54532 | #define BITVEC_HASH(X) (((X)*1)%BITVEC_NINT) |
| 54129 | 54533 | |
| 54130 | | -#define BITVEC_NPTR (BITVEC_USIZE/sizeof(Bitvec *)) |
| 54534 | +#define BITVEC_NPTR ((u32)(BITVEC_USIZE/sizeof(Bitvec *))) |
| 54131 | 54535 | |
| 54132 | 54536 | |
| 54133 | 54537 | /* |
| 54134 | 54538 | ** A bitmap is an instance of the following structure. |
| 54135 | 54539 | ** |
| | @@ -54308,11 +54712,11 @@ |
| 54308 | 54712 | if (!p) { |
| 54309 | 54713 | return; |
| 54310 | 54714 | } |
| 54311 | 54715 | } |
| 54312 | 54716 | if( p->iSize<=BITVEC_NBIT ){ |
| 54313 | | - p->u.aBitmap[i/BITVEC_SZELEM] &= ~(1 << (i&(BITVEC_SZELEM-1))); |
| 54717 | + p->u.aBitmap[i/BITVEC_SZELEM] &= ~(BITVEC_TELEM)(1<<(i&(BITVEC_SZELEM-1))); |
| 54314 | 54718 | }else{ |
| 54315 | 54719 | unsigned int j; |
| 54316 | 54720 | u32 *aiValues = pBuf; |
| 54317 | 54721 | memcpy(aiValues, p->u.aHash, sizeof(p->u.aHash)); |
| 54318 | 54722 | memset(p->u.aHash, 0, sizeof(p->u.aHash)); |
| | @@ -54359,11 +54763,11 @@ |
| 54359 | 54763 | ** up to N bits. Let I be an integer between 0 and N. 0<=I<N. |
| 54360 | 54764 | ** Then the following macros can be used to set, clear, or test |
| 54361 | 54765 | ** individual bits within V. |
| 54362 | 54766 | */ |
| 54363 | 54767 | #define SETBIT(V,I) V[I>>3] |= (1<<(I&7)) |
| 54364 | | -#define CLEARBIT(V,I) V[I>>3] &= ~(1<<(I&7)) |
| 54768 | +#define CLEARBIT(V,I) V[I>>3] &= ~(BITVEC_TELEM)(1<<(I&7)) |
| 54365 | 54769 | #define TESTBIT(V,I) (V[I>>3]&(1<<(I&7)))!=0 |
| 54366 | 54770 | |
| 54367 | 54771 | /* |
| 54368 | 54772 | ** This routine runs an extensive test of the Bitvec code. |
| 54369 | 54773 | ** |
| | @@ -59211,10 +59615,19 @@ |
| 59211 | 59615 | pPager->pInJournal = 0; |
| 59212 | 59616 | releaseAllSavepoints(pPager); |
| 59213 | 59617 | |
| 59214 | 59618 | if( pagerUseWal(pPager) ){ |
| 59215 | 59619 | assert( !isOpen(pPager->jfd) ); |
| 59620 | + if( pPager->eState==PAGER_ERROR ){ |
| 59621 | + /* If an IO error occurs in wal.c while attempting to wrap the wal file, |
| 59622 | + ** then the Wal object may be holding a write-lock but no read-lock. |
| 59623 | + ** This call ensures that the write-lock is dropped as well. We cannot |
| 59624 | + ** have sqlite3WalEndReadTransaction() drop the write-lock, as it once |
| 59625 | + ** did, because this would break "BEGIN EXCLUSIVE" handling for |
| 59626 | + ** SQLITE_ENABLE_SETLK_TIMEOUT builds. */ |
| 59627 | + sqlite3WalEndWriteTransaction(pPager->pWal); |
| 59628 | + } |
| 59216 | 59629 | sqlite3WalEndReadTransaction(pPager->pWal); |
| 59217 | 59630 | pPager->eState = PAGER_OPEN; |
| 59218 | 59631 | }else if( !pPager->exclusiveMode ){ |
| 59219 | 59632 | int rc; /* Error code returned by pagerUnlockDb() */ |
| 59220 | 59633 | int iDc = isOpen(pPager->fd)?sqlite3OsDeviceCharacteristics(pPager->fd):0; |
| | @@ -65669,10 +66082,15 @@ |
| 65669 | 66082 | ) |
| 65670 | 66083 | |
| 65671 | 66084 | /* |
| 65672 | 66085 | ** An open write-ahead log file is represented by an instance of the |
| 65673 | 66086 | ** following object. |
| 66087 | +** |
| 66088 | +** writeLock: |
| 66089 | +** This is usually set to 1 whenever the WRITER lock is held. However, |
| 66090 | +** if it is set to 2, then the WRITER lock is held but must be released |
| 66091 | +** by walHandleException() if a SEH exception is thrown. |
| 65674 | 66092 | */ |
| 65675 | 66093 | struct Wal { |
| 65676 | 66094 | sqlite3_vfs *pVfs; /* The VFS used to create pDbFd */ |
| 65677 | 66095 | sqlite3_file *pDbFd; /* File handle for the database file */ |
| 65678 | 66096 | sqlite3_file *pWalFd; /* File handle for WAL file */ |
| | @@ -67194,11 +67612,11 @@ |
| 67194 | 67612 | ** or 0 otherwise. |
| 67195 | 67613 | */ |
| 67196 | 67614 | static int walEnableBlocking(Wal *pWal){ |
| 67197 | 67615 | int res = 0; |
| 67198 | 67616 | if( pWal->db ){ |
| 67199 | | - int tmout = pWal->db->busyTimeout; |
| 67617 | + int tmout = pWal->db->setlkTimeout; |
| 67200 | 67618 | if( tmout ){ |
| 67201 | 67619 | res = walEnableBlockingMs(pWal, tmout); |
| 67202 | 67620 | } |
| 67203 | 67621 | } |
| 67204 | 67622 | return res; |
| | @@ -67580,11 +67998,13 @@ |
| 67580 | 67998 | static int walHandleException(Wal *pWal){ |
| 67581 | 67999 | if( pWal->exclusiveMode==0 ){ |
| 67582 | 68000 | static const int S = 1; |
| 67583 | 68001 | static const int E = (1<<SQLITE_SHM_NLOCK); |
| 67584 | 68002 | int ii; |
| 67585 | | - u32 mUnlock = pWal->lockMask & ~( |
| 68003 | + u32 mUnlock; |
| 68004 | + if( pWal->writeLock==2 ) pWal->writeLock = 0; |
| 68005 | + mUnlock = pWal->lockMask & ~( |
| 67586 | 68006 | (pWal->readLock<0 ? 0 : (S << WAL_READ_LOCK(pWal->readLock))) |
| 67587 | 68007 | | (pWal->writeLock ? (E << WAL_WRITE_LOCK) : 0) |
| 67588 | 68008 | | (pWal->ckptLock ? (E << WAL_CKPT_LOCK) : 0) |
| 67589 | 68009 | ); |
| 67590 | 68010 | for(ii=0; ii<SQLITE_SHM_NLOCK; ii++){ |
| | @@ -67852,11 +68272,16 @@ |
| 67852 | 68272 | }else{ |
| 67853 | 68273 | int bWriteLock = pWal->writeLock; |
| 67854 | 68274 | if( bWriteLock |
| 67855 | 68275 | || SQLITE_OK==(rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1)) |
| 67856 | 68276 | ){ |
| 67857 | | - pWal->writeLock = 1; |
| 68277 | + /* If the write-lock was just obtained, set writeLock to 2 instead of |
| 68278 | + ** the usual 1. This causes walIndexPage() to behave as if the |
| 68279 | + ** write-lock were held (so that it allocates new pages as required), |
| 68280 | + ** and walHandleException() to unlock the write-lock if a SEH exception |
| 68281 | + ** is thrown. */ |
| 68282 | + if( !bWriteLock ) pWal->writeLock = 2; |
| 67858 | 68283 | if( SQLITE_OK==(rc = walIndexPage(pWal, 0, &page0)) ){ |
| 67859 | 68284 | badHdr = walIndexTryHdr(pWal, pChanged); |
| 67860 | 68285 | if( badHdr ){ |
| 67861 | 68286 | /* If the wal-index header is still malformed even while holding |
| 67862 | 68287 | ** a WRITE lock, it can only mean that the header is corrupted and |
| | @@ -68637,12 +69062,15 @@ |
| 68637 | 69062 | /* |
| 68638 | 69063 | ** Finish with a read transaction. All this does is release the |
| 68639 | 69064 | ** read-lock. |
| 68640 | 69065 | */ |
| 68641 | 69066 | SQLITE_PRIVATE void sqlite3WalEndReadTransaction(Wal *pWal){ |
| 68642 | | - sqlite3WalEndWriteTransaction(pWal); |
| 69067 | +#ifndef SQLITE_ENABLE_SETLK_TIMEOUT |
| 69068 | + assert( pWal->writeLock==0 || pWal->readLock<0 ); |
| 69069 | +#endif |
| 68643 | 69070 | if( pWal->readLock>=0 ){ |
| 69071 | + sqlite3WalEndWriteTransaction(pWal); |
| 68644 | 69072 | walUnlockShared(pWal, WAL_READ_LOCK(pWal->readLock)); |
| 68645 | 69073 | pWal->readLock = -1; |
| 68646 | 69074 | } |
| 68647 | 69075 | } |
| 68648 | 69076 | |
| | @@ -68831,11 +69259,11 @@ |
| 68831 | 69259 | #ifdef SQLITE_ENABLE_SETLK_TIMEOUT |
| 68832 | 69260 | /* If the write-lock is already held, then it was obtained before the |
| 68833 | 69261 | ** read-transaction was even opened, making this call a no-op. |
| 68834 | 69262 | ** Return early. */ |
| 68835 | 69263 | if( pWal->writeLock ){ |
| 68836 | | - assert( !memcmp(&pWal->hdr,(void *)walIndexHdr(pWal),sizeof(WalIndexHdr)) ); |
| 69264 | + assert( !memcmp(&pWal->hdr,(void*)pWal->apWiData[0],sizeof(WalIndexHdr)) ); |
| 68837 | 69265 | return SQLITE_OK; |
| 68838 | 69266 | } |
| 68839 | 69267 | #endif |
| 68840 | 69268 | |
| 68841 | 69269 | /* Cannot start a write transaction without first holding a read |
| | @@ -70280,10 +70708,16 @@ |
| 70280 | 70708 | ** If a tree that appears to be taller than this is encountered, it is |
| 70281 | 70709 | ** assumed that the database is corrupt. |
| 70282 | 70710 | */ |
| 70283 | 70711 | #define BTCURSOR_MAX_DEPTH 20 |
| 70284 | 70712 | |
| 70713 | +/* |
| 70714 | +** Maximum amount of storage local to a database page, regardless of |
| 70715 | +** page size. |
| 70716 | +*/ |
| 70717 | +#define BT_MAX_LOCAL 65501 /* 65536 - 35 */ |
| 70718 | + |
| 70285 | 70719 | /* |
| 70286 | 70720 | ** A cursor is a pointer to a particular entry within a particular |
| 70287 | 70721 | ** b-tree within a database file. |
| 70288 | 70722 | ** |
| 70289 | 70723 | ** The entry is identified by its MemPage and the index in |
| | @@ -70688,11 +71122,11 @@ |
| 70688 | 71122 | ** two or more btrees in common both try to lock all their btrees |
| 70689 | 71123 | ** at the same instant. |
| 70690 | 71124 | */ |
| 70691 | 71125 | static void SQLITE_NOINLINE btreeEnterAll(sqlite3 *db){ |
| 70692 | 71126 | int i; |
| 70693 | | - int skipOk = 1; |
| 71127 | + u8 skipOk = 1; |
| 70694 | 71128 | Btree *p; |
| 70695 | 71129 | assert( sqlite3_mutex_held(db->mutex) ); |
| 70696 | 71130 | for(i=0; i<db->nDb; i++){ |
| 70697 | 71131 | p = db->aDb[i].pBt; |
| 70698 | 71132 | if( p && p->sharable ){ |
| | @@ -71834,11 +72268,11 @@ |
| 71834 | 72268 | /* |
| 71835 | 72269 | ** Provide flag hints to the cursor. |
| 71836 | 72270 | */ |
| 71837 | 72271 | SQLITE_PRIVATE void sqlite3BtreeCursorHintFlags(BtCursor *pCur, unsigned x){ |
| 71838 | 72272 | assert( x==BTREE_SEEK_EQ || x==BTREE_BULKLOAD || x==0 ); |
| 71839 | | - pCur->hints = x; |
| 72273 | + pCur->hints = (u8)x; |
| 71840 | 72274 | } |
| 71841 | 72275 | |
| 71842 | 72276 | |
| 71843 | 72277 | #ifndef SQLITE_OMIT_AUTOVACUUM |
| 71844 | 72278 | /* |
| | @@ -72028,18 +72462,19 @@ |
| 72028 | 72462 | ** page pPage, return the number of bytes of payload stored locally. |
| 72029 | 72463 | */ |
| 72030 | 72464 | static int btreePayloadToLocal(MemPage *pPage, i64 nPayload){ |
| 72031 | 72465 | int maxLocal; /* Maximum amount of payload held locally */ |
| 72032 | 72466 | maxLocal = pPage->maxLocal; |
| 72467 | + assert( nPayload>=0 ); |
| 72033 | 72468 | if( nPayload<=maxLocal ){ |
| 72034 | | - return nPayload; |
| 72469 | + return (int)nPayload; |
| 72035 | 72470 | }else{ |
| 72036 | 72471 | int minLocal; /* Minimum amount of payload held locally */ |
| 72037 | 72472 | int surplus; /* Overflow payload available for local storage */ |
| 72038 | 72473 | minLocal = pPage->minLocal; |
| 72039 | | - surplus = minLocal + (nPayload - minLocal)%(pPage->pBt->usableSize-4); |
| 72040 | | - return ( surplus <= maxLocal ) ? surplus : minLocal; |
| 72474 | + surplus = (int)(minLocal +(nPayload - minLocal)%(pPage->pBt->usableSize-4)); |
| 72475 | + return (surplus <= maxLocal) ? surplus : minLocal; |
| 72041 | 72476 | } |
| 72042 | 72477 | } |
| 72043 | 72478 | |
| 72044 | 72479 | /* |
| 72045 | 72480 | ** The following routines are implementations of the MemPage.xParseCell() |
| | @@ -72145,15 +72580,17 @@ |
| 72145 | 72580 | pInfo->nKey = *(i64*)&iKey; |
| 72146 | 72581 | pInfo->nPayload = nPayload; |
| 72147 | 72582 | pInfo->pPayload = pIter; |
| 72148 | 72583 | testcase( nPayload==pPage->maxLocal ); |
| 72149 | 72584 | testcase( nPayload==(u32)pPage->maxLocal+1 ); |
| 72585 | + assert( nPayload>=0 ); |
| 72586 | + assert( pPage->maxLocal <= BT_MAX_LOCAL ); |
| 72150 | 72587 | if( nPayload<=pPage->maxLocal ){ |
| 72151 | 72588 | /* This is the (easy) common case where the entire payload fits |
| 72152 | 72589 | ** on the local page. No overflow is required. |
| 72153 | 72590 | */ |
| 72154 | | - pInfo->nSize = nPayload + (u16)(pIter - pCell); |
| 72591 | + pInfo->nSize = (u16)nPayload + (u16)(pIter - pCell); |
| 72155 | 72592 | if( pInfo->nSize<4 ) pInfo->nSize = 4; |
| 72156 | 72593 | pInfo->nLocal = (u16)nPayload; |
| 72157 | 72594 | }else{ |
| 72158 | 72595 | btreeParseCellAdjustSizeForOverflow(pPage, pCell, pInfo); |
| 72159 | 72596 | } |
| | @@ -72182,15 +72619,17 @@ |
| 72182 | 72619 | pInfo->nKey = nPayload; |
| 72183 | 72620 | pInfo->nPayload = nPayload; |
| 72184 | 72621 | pInfo->pPayload = pIter; |
| 72185 | 72622 | testcase( nPayload==pPage->maxLocal ); |
| 72186 | 72623 | testcase( nPayload==(u32)pPage->maxLocal+1 ); |
| 72624 | + assert( nPayload>=0 ); |
| 72625 | + assert( pPage->maxLocal <= BT_MAX_LOCAL ); |
| 72187 | 72626 | if( nPayload<=pPage->maxLocal ){ |
| 72188 | 72627 | /* This is the (easy) common case where the entire payload fits |
| 72189 | 72628 | ** on the local page. No overflow is required. |
| 72190 | 72629 | */ |
| 72191 | | - pInfo->nSize = nPayload + (u16)(pIter - pCell); |
| 72630 | + pInfo->nSize = (u16)nPayload + (u16)(pIter - pCell); |
| 72192 | 72631 | if( pInfo->nSize<4 ) pInfo->nSize = 4; |
| 72193 | 72632 | pInfo->nLocal = (u16)nPayload; |
| 72194 | 72633 | }else{ |
| 72195 | 72634 | btreeParseCellAdjustSizeForOverflow(pPage, pCell, pInfo); |
| 72196 | 72635 | } |
| | @@ -72725,18 +73164,18 @@ |
| 72725 | 73164 | ** that routine will not detect overlap between cells or freeblocks. Nor |
| 72726 | 73165 | ** does it detect cells or freeblocks that encroach into the reserved bytes |
| 72727 | 73166 | ** at the end of the page. So do additional corruption checks inside this |
| 72728 | 73167 | ** routine and return SQLITE_CORRUPT if any problems are found. |
| 72729 | 73168 | */ |
| 72730 | | -static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){ |
| 72731 | | - u16 iPtr; /* Address of ptr to next freeblock */ |
| 72732 | | - u16 iFreeBlk; /* Address of the next freeblock */ |
| 73169 | +static int freeSpace(MemPage *pPage, int iStart, int iSize){ |
| 73170 | + int iPtr; /* Address of ptr to next freeblock */ |
| 73171 | + int iFreeBlk; /* Address of the next freeblock */ |
| 72733 | 73172 | u8 hdr; /* Page header size. 0 or 100 */ |
| 72734 | | - u8 nFrag = 0; /* Reduction in fragmentation */ |
| 72735 | | - u16 iOrigSize = iSize; /* Original value of iSize */ |
| 72736 | | - u16 x; /* Offset to cell content area */ |
| 72737 | | - u32 iEnd = iStart + iSize; /* First byte past the iStart buffer */ |
| 73173 | + int nFrag = 0; /* Reduction in fragmentation */ |
| 73174 | + int iOrigSize = iSize; /* Original value of iSize */ |
| 73175 | + int x; /* Offset to cell content area */ |
| 73176 | + int iEnd = iStart + iSize; /* First byte past the iStart buffer */ |
| 72738 | 73177 | unsigned char *data = pPage->aData; /* Page content */ |
| 72739 | 73178 | u8 *pTmp; /* Temporary ptr into data[] */ |
| 72740 | 73179 | |
| 72741 | 73180 | assert( pPage->pBt!=0 ); |
| 72742 | 73181 | assert( sqlite3PagerIswriteable(pPage->pDbPage) ); |
| | @@ -72759,11 +73198,11 @@ |
| 72759 | 73198 | if( iFreeBlk==0 ) break; /* TH3: corrupt082.100 */ |
| 72760 | 73199 | return SQLITE_CORRUPT_PAGE(pPage); |
| 72761 | 73200 | } |
| 72762 | 73201 | iPtr = iFreeBlk; |
| 72763 | 73202 | } |
| 72764 | | - if( iFreeBlk>pPage->pBt->usableSize-4 ){ /* TH3: corrupt081.100 */ |
| 73203 | + if( iFreeBlk>(int)pPage->pBt->usableSize-4 ){ /* TH3: corrupt081.100 */ |
| 72765 | 73204 | return SQLITE_CORRUPT_PAGE(pPage); |
| 72766 | 73205 | } |
| 72767 | 73206 | assert( iFreeBlk>iPtr || iFreeBlk==0 || CORRUPT_DB ); |
| 72768 | 73207 | |
| 72769 | 73208 | /* At this point: |
| | @@ -72774,11 +73213,11 @@ |
| 72774 | 73213 | */ |
| 72775 | 73214 | if( iFreeBlk && iEnd+3>=iFreeBlk ){ |
| 72776 | 73215 | nFrag = iFreeBlk - iEnd; |
| 72777 | 73216 | if( iEnd>iFreeBlk ) return SQLITE_CORRUPT_PAGE(pPage); |
| 72778 | 73217 | iEnd = iFreeBlk + get2byte(&data[iFreeBlk+2]); |
| 72779 | | - if( iEnd > pPage->pBt->usableSize ){ |
| 73218 | + if( iEnd > (int)pPage->pBt->usableSize ){ |
| 72780 | 73219 | return SQLITE_CORRUPT_PAGE(pPage); |
| 72781 | 73220 | } |
| 72782 | 73221 | iSize = iEnd - iStart; |
| 72783 | 73222 | iFreeBlk = get2byte(&data[iFreeBlk]); |
| 72784 | 73223 | } |
| | @@ -72795,11 +73234,11 @@ |
| 72795 | 73234 | iSize = iEnd - iPtr; |
| 72796 | 73235 | iStart = iPtr; |
| 72797 | 73236 | } |
| 72798 | 73237 | } |
| 72799 | 73238 | if( nFrag>data[hdr+7] ) return SQLITE_CORRUPT_PAGE(pPage); |
| 72800 | | - data[hdr+7] -= nFrag; |
| 73239 | + data[hdr+7] -= (u8)nFrag; |
| 72801 | 73240 | } |
| 72802 | 73241 | pTmp = &data[hdr+5]; |
| 72803 | 73242 | x = get2byte(pTmp); |
| 72804 | 73243 | if( pPage->pBt->btsFlags & BTS_FAST_SECURE ){ |
| 72805 | 73244 | /* Overwrite deleted information with zeros when the secure_delete |
| | @@ -72816,11 +73255,12 @@ |
| 72816 | 73255 | put2byte(&data[hdr+5], iEnd); |
| 72817 | 73256 | }else{ |
| 72818 | 73257 | /* Insert the new freeblock into the freelist */ |
| 72819 | 73258 | put2byte(&data[iPtr], iStart); |
| 72820 | 73259 | put2byte(&data[iStart], iFreeBlk); |
| 72821 | | - put2byte(&data[iStart+2], iSize); |
| 73260 | + assert( iSize>=0 && iSize<=0xffff ); |
| 73261 | + put2byte(&data[iStart+2], (u16)iSize); |
| 72822 | 73262 | } |
| 72823 | 73263 | pPage->nFree += iOrigSize; |
| 72824 | 73264 | return SQLITE_OK; |
| 72825 | 73265 | } |
| 72826 | 73266 | |
| | @@ -73042,11 +73482,11 @@ |
| 73042 | 73482 | return SQLITE_CORRUPT_PAGE(pPage); |
| 73043 | 73483 | } |
| 73044 | 73484 | assert( pBt->pageSize>=512 && pBt->pageSize<=65536 ); |
| 73045 | 73485 | pPage->maskPage = (u16)(pBt->pageSize - 1); |
| 73046 | 73486 | pPage->nOverflow = 0; |
| 73047 | | - pPage->cellOffset = pPage->hdrOffset + 8 + pPage->childPtrSize; |
| 73487 | + pPage->cellOffset = (u16)(pPage->hdrOffset + 8 + pPage->childPtrSize); |
| 73048 | 73488 | pPage->aCellIdx = data + pPage->childPtrSize + 8; |
| 73049 | 73489 | pPage->aDataEnd = pPage->aData + pBt->pageSize; |
| 73050 | 73490 | pPage->aDataOfst = pPage->aData + pPage->childPtrSize; |
| 73051 | 73491 | /* EVIDENCE-OF: R-37002-32774 The two-byte integer at offset 3 gives the |
| 73052 | 73492 | ** number of cells on the page. */ |
| | @@ -73076,12 +73516,12 @@ |
| 73076 | 73516 | ** no entries. |
| 73077 | 73517 | */ |
| 73078 | 73518 | static void zeroPage(MemPage *pPage, int flags){ |
| 73079 | 73519 | unsigned char *data = pPage->aData; |
| 73080 | 73520 | BtShared *pBt = pPage->pBt; |
| 73081 | | - u8 hdr = pPage->hdrOffset; |
| 73082 | | - u16 first; |
| 73521 | + int hdr = pPage->hdrOffset; |
| 73522 | + int first; |
| 73083 | 73523 | |
| 73084 | 73524 | assert( sqlite3PagerPagenumber(pPage->pDbPage)==pPage->pgno || CORRUPT_DB ); |
| 73085 | 73525 | assert( sqlite3PagerGetExtra(pPage->pDbPage) == (void*)pPage ); |
| 73086 | 73526 | assert( sqlite3PagerGetData(pPage->pDbPage) == data ); |
| 73087 | 73527 | assert( sqlite3PagerIswriteable(pPage->pDbPage) ); |
| | @@ -73094,11 +73534,11 @@ |
| 73094 | 73534 | memset(&data[hdr+1], 0, 4); |
| 73095 | 73535 | data[hdr+7] = 0; |
| 73096 | 73536 | put2byte(&data[hdr+5], pBt->usableSize); |
| 73097 | 73537 | pPage->nFree = (u16)(pBt->usableSize - first); |
| 73098 | 73538 | decodeFlags(pPage, flags); |
| 73099 | | - pPage->cellOffset = first; |
| 73539 | + pPage->cellOffset = (u16)first; |
| 73100 | 73540 | pPage->aDataEnd = &data[pBt->pageSize]; |
| 73101 | 73541 | pPage->aCellIdx = &data[first]; |
| 73102 | 73542 | pPage->aDataOfst = &data[pPage->childPtrSize]; |
| 73103 | 73543 | pPage->nOverflow = 0; |
| 73104 | 73544 | assert( pBt->pageSize>=512 && pBt->pageSize<=65536 ); |
| | @@ -73880,11 +74320,11 @@ |
| 73880 | 74320 | int rc = SQLITE_OK; |
| 73881 | 74321 | int x; |
| 73882 | 74322 | BtShared *pBt = p->pBt; |
| 73883 | 74323 | assert( nReserve>=0 && nReserve<=255 ); |
| 73884 | 74324 | sqlite3BtreeEnter(p); |
| 73885 | | - pBt->nReserveWanted = nReserve; |
| 74325 | + pBt->nReserveWanted = (u8)nReserve; |
| 73886 | 74326 | x = pBt->pageSize - pBt->usableSize; |
| 73887 | 74327 | if( nReserve<x ) nReserve = x; |
| 73888 | 74328 | if( pBt->btsFlags & BTS_PAGESIZE_FIXED ){ |
| 73889 | 74329 | sqlite3BtreeLeave(p); |
| 73890 | 74330 | return SQLITE_READONLY; |
| | @@ -73986,11 +74426,11 @@ |
| 73986 | 74426 | sqlite3BtreeEnter(p); |
| 73987 | 74427 | assert( BTS_OVERWRITE==BTS_SECURE_DELETE*2 ); |
| 73988 | 74428 | assert( BTS_FAST_SECURE==(BTS_OVERWRITE|BTS_SECURE_DELETE) ); |
| 73989 | 74429 | if( newFlag>=0 ){ |
| 73990 | 74430 | p->pBt->btsFlags &= ~BTS_FAST_SECURE; |
| 73991 | | - p->pBt->btsFlags |= BTS_SECURE_DELETE*newFlag; |
| 74431 | + p->pBt->btsFlags |= (u16)(BTS_SECURE_DELETE*newFlag); |
| 73992 | 74432 | } |
| 73993 | 74433 | b = (p->pBt->btsFlags & BTS_FAST_SECURE)/BTS_SECURE_DELETE; |
| 73994 | 74434 | sqlite3BtreeLeave(p); |
| 73995 | 74435 | return b; |
| 73996 | 74436 | } |
| | @@ -78434,11 +78874,12 @@ |
| 78434 | 78874 | pSrcEnd = pCArray->apEnd[k]; |
| 78435 | 78875 | } |
| 78436 | 78876 | } |
| 78437 | 78877 | |
| 78438 | 78878 | /* The pPg->nFree field is now set incorrectly. The caller will fix it. */ |
| 78439 | | - pPg->nCell = nCell; |
| 78879 | + assert( nCell < 10922 ); |
| 78880 | + pPg->nCell = (u16)nCell; |
| 78440 | 78881 | pPg->nOverflow = 0; |
| 78441 | 78882 | |
| 78442 | 78883 | put2byte(&aData[hdr+1], 0); |
| 78443 | 78884 | put2byte(&aData[hdr+3], pPg->nCell); |
| 78444 | 78885 | put2byte(&aData[hdr+5], pData - aData); |
| | @@ -78681,13 +79122,17 @@ |
| 78681 | 79122 | assert( nCell>=0 ); |
| 78682 | 79123 | pCellptr = &pPg->aCellIdx[nCell*2]; |
| 78683 | 79124 | if( pageInsertArray( |
| 78684 | 79125 | pPg, pBegin, &pData, pCellptr, |
| 78685 | 79126 | iNew+nCell, nNew-nCell, pCArray |
| 78686 | | - ) ) goto editpage_fail; |
| 79127 | + ) |
| 79128 | + ){ |
| 79129 | + goto editpage_fail; |
| 79130 | + } |
| 78687 | 79131 | |
| 78688 | | - pPg->nCell = nNew; |
| 79132 | + assert( nNew < 10922 ); |
| 79133 | + pPg->nCell = (u16)nNew; |
| 78689 | 79134 | pPg->nOverflow = 0; |
| 78690 | 79135 | |
| 78691 | 79136 | put2byte(&aData[hdr+3], pPg->nCell); |
| 78692 | 79137 | put2byte(&aData[hdr+5], pData - aData); |
| 78693 | 79138 | |
| | @@ -78992,11 +79437,11 @@ |
| 78992 | 79437 | int leafData; /* True if pPage is a leaf of a LEAFDATA tree */ |
| 78993 | 79438 | int usableSpace; /* Bytes in pPage beyond the header */ |
| 78994 | 79439 | int pageFlags; /* Value of pPage->aData[0] */ |
| 78995 | 79440 | int iSpace1 = 0; /* First unused byte of aSpace1[] */ |
| 78996 | 79441 | int iOvflSpace = 0; /* First unused byte of aOvflSpace[] */ |
| 78997 | | - int szScratch; /* Size of scratch memory requested */ |
| 79442 | + u64 szScratch; /* Size of scratch memory requested */ |
| 78998 | 79443 | MemPage *apOld[NB]; /* pPage and up to two siblings */ |
| 78999 | 79444 | MemPage *apNew[NB+2]; /* pPage and up to NB siblings after balancing */ |
| 79000 | 79445 | u8 *pRight; /* Location in parent of right-sibling pointer */ |
| 79001 | 79446 | u8 *apDiv[NB-1]; /* Divider cells in pParent */ |
| 79002 | 79447 | int cntNew[NB+2]; /* Index in b.paCell[] of cell after i-th page */ |
| | @@ -80277,11 +80722,11 @@ |
| 80277 | 80722 | if( loc==0 ){ |
| 80278 | 80723 | getCellInfo(pCur); |
| 80279 | 80724 | if( pCur->info.nKey==pX->nKey ){ |
| 80280 | 80725 | BtreePayload x2; |
| 80281 | 80726 | x2.pData = pX->pKey; |
| 80282 | | - x2.nData = pX->nKey; |
| 80727 | + x2.nData = (int)pX->nKey; assert( pX->nKey<=0x7fffffff ); |
| 80283 | 80728 | x2.nZero = 0; |
| 80284 | 80729 | return btreeOverwriteCell(pCur, &x2); |
| 80285 | 80730 | } |
| 80286 | 80731 | } |
| 80287 | 80732 | } |
| | @@ -80458,11 +80903,11 @@ |
| 80458 | 80903 | u32 nIn; /* Size of input buffer aIn[] */ |
| 80459 | 80904 | u32 nRem; /* Bytes of data still to copy */ |
| 80460 | 80905 | |
| 80461 | 80906 | getCellInfo(pSrc); |
| 80462 | 80907 | if( pSrc->info.nPayload<0x80 ){ |
| 80463 | | - *(aOut++) = pSrc->info.nPayload; |
| 80908 | + *(aOut++) = (u8)pSrc->info.nPayload; |
| 80464 | 80909 | }else{ |
| 80465 | 80910 | aOut += sqlite3PutVarint(aOut, pSrc->info.nPayload); |
| 80466 | 80911 | } |
| 80467 | 80912 | if( pDest->pKeyInfo==0 ) aOut += putVarint(aOut, iKey); |
| 80468 | 80913 | nIn = pSrc->info.nLocal; |
| | @@ -80471,11 +80916,11 @@ |
| 80471 | 80916 | return SQLITE_CORRUPT_PAGE(pSrc->pPage); |
| 80472 | 80917 | } |
| 80473 | 80918 | nRem = pSrc->info.nPayload; |
| 80474 | 80919 | if( nIn==nRem && nIn<pDest->pPage->maxLocal ){ |
| 80475 | 80920 | memcpy(aOut, aIn, nIn); |
| 80476 | | - pBt->nPreformatSize = nIn + (aOut - pBt->pTmpSpace); |
| 80921 | + pBt->nPreformatSize = nIn + (int)(aOut - pBt->pTmpSpace); |
| 80477 | 80922 | return SQLITE_OK; |
| 80478 | 80923 | }else{ |
| 80479 | 80924 | int rc = SQLITE_OK; |
| 80480 | 80925 | Pager *pSrcPager = pSrc->pBt->pPager; |
| 80481 | 80926 | u8 *pPgnoOut = 0; |
| | @@ -80483,11 +80928,11 @@ |
| 80483 | 80928 | DbPage *pPageIn = 0; |
| 80484 | 80929 | MemPage *pPageOut = 0; |
| 80485 | 80930 | u32 nOut; /* Size of output buffer aOut[] */ |
| 80486 | 80931 | |
| 80487 | 80932 | nOut = btreePayloadToLocal(pDest->pPage, pSrc->info.nPayload); |
| 80488 | | - pBt->nPreformatSize = nOut + (aOut - pBt->pTmpSpace); |
| 80933 | + pBt->nPreformatSize = (int)nOut + (int)(aOut - pBt->pTmpSpace); |
| 80489 | 80934 | if( nOut<pSrc->info.nPayload ){ |
| 80490 | 80935 | pPgnoOut = &aOut[nOut]; |
| 80491 | 80936 | pBt->nPreformatSize += 4; |
| 80492 | 80937 | } |
| 80493 | 80938 | |
| | @@ -111531,11 +111976,11 @@ |
| 111531 | 111976 | pNew->pNext = pNext; |
| 111532 | 111977 | pNew->pPrior = 0; |
| 111533 | 111978 | pNew->pLimit = sqlite3ExprDup(db, p->pLimit, flags); |
| 111534 | 111979 | pNew->iLimit = 0; |
| 111535 | 111980 | pNew->iOffset = 0; |
| 111536 | | - pNew->selFlags = p->selFlags & ~SF_UsesEphemeral; |
| 111981 | + pNew->selFlags = p->selFlags & ~(u32)SF_UsesEphemeral; |
| 111537 | 111982 | pNew->addrOpenEphm[0] = -1; |
| 111538 | 111983 | pNew->addrOpenEphm[1] = -1; |
| 111539 | 111984 | pNew->nSelectRow = p->nSelectRow; |
| 111540 | 111985 | pNew->pWith = sqlite3WithDup(db, p->pWith); |
| 111541 | 111986 | #ifndef SQLITE_OMIT_WINDOWFUNC |
| | @@ -117481,17 +117926,17 @@ |
| 117481 | 117926 | pNew->nTabRef = 1; |
| 117482 | 117927 | pNew->nCol = pTab->nCol; |
| 117483 | 117928 | assert( pNew->nCol>0 ); |
| 117484 | 117929 | nAlloc = (((pNew->nCol-1)/8)*8)+8; |
| 117485 | 117930 | assert( nAlloc>=pNew->nCol && nAlloc%8==0 && nAlloc-pNew->nCol<8 ); |
| 117486 | | - pNew->aCol = (Column*)sqlite3DbMallocZero(db, sizeof(Column)*nAlloc); |
| 117931 | + pNew->aCol = (Column*)sqlite3DbMallocZero(db, sizeof(Column)*(u32)nAlloc); |
| 117487 | 117932 | pNew->zName = sqlite3MPrintf(db, "sqlite_altertab_%s", pTab->zName); |
| 117488 | 117933 | if( !pNew->aCol || !pNew->zName ){ |
| 117489 | 117934 | assert( db->mallocFailed ); |
| 117490 | 117935 | goto exit_begin_add_column; |
| 117491 | 117936 | } |
| 117492 | | - memcpy(pNew->aCol, pTab->aCol, sizeof(Column)*pNew->nCol); |
| 117937 | + memcpy(pNew->aCol, pTab->aCol, sizeof(Column)*(size_t)pNew->nCol); |
| 117493 | 117938 | for(i=0; i<pNew->nCol; i++){ |
| 117494 | 117939 | Column *pCol = &pNew->aCol[i]; |
| 117495 | 117940 | pCol->zCnName = sqlite3DbStrDup(db, pCol->zCnName); |
| 117496 | 117941 | pCol->hName = sqlite3StrIHash(pCol->zCnName); |
| 117497 | 117942 | } |
| | @@ -118094,11 +118539,17 @@ |
| 118094 | 118539 | return SQLITE_NOMEM; |
| 118095 | 118540 | } |
| 118096 | 118541 | if( sqlite3StrNICmp(zSql,"CREATE ",7)!=0 ){ |
| 118097 | 118542 | return SQLITE_CORRUPT_BKPT; |
| 118098 | 118543 | } |
| 118099 | | - db->init.iDb = bTemp ? 1 : sqlite3FindDbName(db, zDb); |
| 118544 | + if( bTemp ){ |
| 118545 | + db->init.iDb = 1; |
| 118546 | + }else{ |
| 118547 | + int iDb = sqlite3FindDbName(db, zDb); |
| 118548 | + assert( iDb>=0 && iDb<=0xff ); |
| 118549 | + db->init.iDb = (u8)iDb; |
| 118550 | + } |
| 118100 | 118551 | p->eParseMode = PARSE_MODE_RENAME; |
| 118101 | 118552 | p->db = db; |
| 118102 | 118553 | p->nQueryLoop = 1; |
| 118103 | 118554 | rc = sqlite3RunParser(p, zSql); |
| 118104 | 118555 | if( db->mallocFailed ) rc = SQLITE_NOMEM; |
| | @@ -118161,14 +118612,15 @@ |
| 118161 | 118612 | return SQLITE_NOMEM; |
| 118162 | 118613 | }else{ |
| 118163 | 118614 | nQuot = sqlite3Strlen30(zQuot)-1; |
| 118164 | 118615 | } |
| 118165 | 118616 | |
| 118166 | | - assert( nQuot>=nNew ); |
| 118167 | | - zOut = sqlite3DbMallocZero(db, nSql + pRename->nList*nQuot + 1); |
| 118617 | + assert( nQuot>=nNew && nSql>=0 && nNew>=0 ); |
| 118618 | + zOut = sqlite3DbMallocZero(db, (u64)(nSql + pRename->nList*nQuot + 1)); |
| 118168 | 118619 | }else{ |
| 118169 | | - zOut = (char*)sqlite3DbMallocZero(db, (nSql*2+1) * 3); |
| 118620 | + assert( nSql>0 ); |
| 118621 | + zOut = (char*)sqlite3DbMallocZero(db, (u64)(nSql*2+1) * 3); |
| 118170 | 118622 | if( zOut ){ |
| 118171 | 118623 | zBuf1 = &zOut[nSql*2+1]; |
| 118172 | 118624 | zBuf2 = &zOut[nSql*4+2]; |
| 118173 | 118625 | } |
| 118174 | 118626 | } |
| | @@ -118176,20 +118628,21 @@ |
| 118176 | 118628 | /* At this point pRename->pList contains a list of RenameToken objects |
| 118177 | 118629 | ** corresponding to all tokens in the input SQL that must be replaced |
| 118178 | 118630 | ** with the new column name, or with single-quoted versions of themselves. |
| 118179 | 118631 | ** All that remains is to construct and return the edited SQL string. */ |
| 118180 | 118632 | if( zOut ){ |
| 118181 | | - int nOut = nSql; |
| 118182 | | - memcpy(zOut, zSql, nSql); |
| 118633 | + i64 nOut = nSql; |
| 118634 | + assert( nSql>0 ); |
| 118635 | + memcpy(zOut, zSql, (size_t)nSql); |
| 118183 | 118636 | while( pRename->pList ){ |
| 118184 | 118637 | int iOff; /* Offset of token to replace in zOut */ |
| 118185 | | - u32 nReplace; |
| 118638 | + i64 nReplace; |
| 118186 | 118639 | const char *zReplace; |
| 118187 | 118640 | RenameToken *pBest = renameColumnTokenNext(pRename); |
| 118188 | 118641 | |
| 118189 | 118642 | if( zNew ){ |
| 118190 | | - if( bQuote==0 && sqlite3IsIdChar(*pBest->t.z) ){ |
| 118643 | + if( bQuote==0 && sqlite3IsIdChar(*(u8*)pBest->t.z) ){ |
| 118191 | 118644 | nReplace = nNew; |
| 118192 | 118645 | zReplace = zNew; |
| 118193 | 118646 | }else{ |
| 118194 | 118647 | nReplace = nQuot; |
| 118195 | 118648 | zReplace = zQuot; |
| | @@ -118203,18 +118656,19 @@ |
| 118203 | 118656 | ** token. This is so that (SELECT "string"'alias') maps to |
| 118204 | 118657 | ** (SELECT 'string' 'alias'), and not (SELECT 'string''alias'). */ |
| 118205 | 118658 | memcpy(zBuf1, pBest->t.z, pBest->t.n); |
| 118206 | 118659 | zBuf1[pBest->t.n] = 0; |
| 118207 | 118660 | sqlite3Dequote(zBuf1); |
| 118208 | | - sqlite3_snprintf(nSql*2, zBuf2, "%Q%s", zBuf1, |
| 118661 | + assert( nSql < 0x15555554 /* otherwise malloc would have failed */ ); |
| 118662 | + sqlite3_snprintf((int)(nSql*2), zBuf2, "%Q%s", zBuf1, |
| 118209 | 118663 | pBest->t.z[pBest->t.n]=='\'' ? " " : "" |
| 118210 | 118664 | ); |
| 118211 | 118665 | zReplace = zBuf2; |
| 118212 | 118666 | nReplace = sqlite3Strlen30(zReplace); |
| 118213 | 118667 | } |
| 118214 | 118668 | |
| 118215 | | - iOff = pBest->t.z - zSql; |
| 118669 | + iOff = (int)(pBest->t.z - zSql); |
| 118216 | 118670 | if( pBest->t.n!=nReplace ){ |
| 118217 | 118671 | memmove(&zOut[iOff + nReplace], &zOut[iOff + pBest->t.n], |
| 118218 | 118672 | nOut - (iOff + pBest->t.n) |
| 118219 | 118673 | ); |
| 118220 | 118674 | nOut += nReplace - pBest->t.n; |
| | @@ -118236,15 +118690,16 @@ |
| 118236 | 118690 | |
| 118237 | 118691 | /* |
| 118238 | 118692 | ** Set all pEList->a[].fg.eEName fields in the expression-list to val. |
| 118239 | 118693 | */ |
| 118240 | 118694 | static void renameSetENames(ExprList *pEList, int val){ |
| 118695 | + assert( val==ENAME_NAME || val==ENAME_TAB || val==ENAME_SPAN ); |
| 118241 | 118696 | if( pEList ){ |
| 118242 | 118697 | int i; |
| 118243 | 118698 | for(i=0; i<pEList->nExpr; i++){ |
| 118244 | 118699 | assert( val==ENAME_NAME || pEList->a[i].fg.eEName==ENAME_NAME ); |
| 118245 | | - pEList->a[i].fg.eEName = val; |
| 118700 | + pEList->a[i].fg.eEName = val&0x3; |
| 118246 | 118701 | } |
| 118247 | 118702 | } |
| 118248 | 118703 | } |
| 118249 | 118704 | |
| 118250 | 118705 | /* |
| | @@ -118497,11 +118952,11 @@ |
| 118497 | 118952 | sCtx.pTab = pTab; |
| 118498 | 118953 | if( rc!=SQLITE_OK ) goto renameColumnFunc_done; |
| 118499 | 118954 | if( sParse.pNewTable ){ |
| 118500 | 118955 | if( IsView(sParse.pNewTable) ){ |
| 118501 | 118956 | Select *pSelect = sParse.pNewTable->u.view.pSelect; |
| 118502 | | - pSelect->selFlags &= ~SF_View; |
| 118957 | + pSelect->selFlags &= ~(u32)SF_View; |
| 118503 | 118958 | sParse.rc = SQLITE_OK; |
| 118504 | 118959 | sqlite3SelectPrep(&sParse, pSelect, 0); |
| 118505 | 118960 | rc = (db->mallocFailed ? SQLITE_NOMEM : sParse.rc); |
| 118506 | 118961 | if( rc==SQLITE_OK ){ |
| 118507 | 118962 | sqlite3WalkSelect(&sWalker, pSelect); |
| | @@ -118715,11 +119170,11 @@ |
| 118715 | 119170 | NameContext sNC; |
| 118716 | 119171 | memset(&sNC, 0, sizeof(sNC)); |
| 118717 | 119172 | sNC.pParse = &sParse; |
| 118718 | 119173 | |
| 118719 | 119174 | assert( pSelect->selFlags & SF_View ); |
| 118720 | | - pSelect->selFlags &= ~SF_View; |
| 119175 | + pSelect->selFlags &= ~(u32)SF_View; |
| 118721 | 119176 | sqlite3SelectPrep(&sParse, pTab->u.view.pSelect, &sNC); |
| 118722 | 119177 | if( sParse.nErr ){ |
| 118723 | 119178 | rc = sParse.rc; |
| 118724 | 119179 | }else{ |
| 118725 | 119180 | sqlite3WalkSelect(&sWalker, pTab->u.view.pSelect); |
| | @@ -118888,11 +119343,11 @@ |
| 118888 | 119343 | sWalker.u.pRename = &sCtx; |
| 118889 | 119344 | |
| 118890 | 119345 | if( sParse.pNewTable ){ |
| 118891 | 119346 | if( IsView(sParse.pNewTable) ){ |
| 118892 | 119347 | Select *pSelect = sParse.pNewTable->u.view.pSelect; |
| 118893 | | - pSelect->selFlags &= ~SF_View; |
| 119348 | + pSelect->selFlags &= ~(u32)SF_View; |
| 118894 | 119349 | sParse.rc = SQLITE_OK; |
| 118895 | 119350 | sqlite3SelectPrep(&sParse, pSelect, 0); |
| 118896 | 119351 | rc = (db->mallocFailed ? SQLITE_NOMEM : sParse.rc); |
| 118897 | 119352 | if( rc==SQLITE_OK ){ |
| 118898 | 119353 | sqlite3WalkSelect(&sWalker, pSelect); |
| | @@ -118987,11 +119442,11 @@ |
| 118987 | 119442 | UNUSED_PARAMETER(NotUsed); |
| 118988 | 119443 | |
| 118989 | 119444 | if( zDb && zInput ){ |
| 118990 | 119445 | int rc; |
| 118991 | 119446 | Parse sParse; |
| 118992 | | - int flags = db->flags; |
| 119447 | + u64 flags = db->flags; |
| 118993 | 119448 | if( bNoDQS ) db->flags &= ~(SQLITE_DqsDML|SQLITE_DqsDDL); |
| 118994 | 119449 | rc = renameParseSql(&sParse, zDb, db, zInput, bTemp); |
| 118995 | 119450 | db->flags |= (flags & (SQLITE_DqsDML|SQLITE_DqsDDL)); |
| 118996 | 119451 | if( rc==SQLITE_OK ){ |
| 118997 | 119452 | if( isLegacy==0 && sParse.pNewTable && IsView(sParse.pNewTable) ){ |
| | @@ -119710,11 +120165,11 @@ |
| 119710 | 120165 | } |
| 119711 | 120166 | |
| 119712 | 120167 | p->db = db; |
| 119713 | 120168 | p->nEst = sqlite3_value_int64(argv[2]); |
| 119714 | 120169 | p->nRow = 0; |
| 119715 | | - p->nLimit = sqlite3_value_int64(argv[3]); |
| 120170 | + p->nLimit = sqlite3_value_int(argv[3]); |
| 119716 | 120171 | p->nCol = nCol; |
| 119717 | 120172 | p->nKeyCol = nKeyCol; |
| 119718 | 120173 | p->nSkipAhead = 0; |
| 119719 | 120174 | p->current.anDLt = (tRowcnt*)&p[1]; |
| 119720 | 120175 | |
| | @@ -121519,10 +121974,17 @@ |
| 121519 | 121974 | */ |
| 121520 | 121975 | if( rc==SQLITE_OK ){ |
| 121521 | 121976 | sqlite3BtreeEnterAll(db); |
| 121522 | 121977 | db->init.iDb = 0; |
| 121523 | 121978 | db->mDbFlags &= ~(DBFLAG_SchemaKnownOk); |
| 121979 | +#ifdef SQLITE_ENABLE_SETLK_TIMEOUT |
| 121980 | + if( db->setlkFlags & SQLITE_SETLK_BLOCK_ON_CONNECT ){ |
| 121981 | + int val = 1; |
| 121982 | + sqlite3_file *fd = sqlite3PagerFile(sqlite3BtreePager(pNew->pBt)); |
| 121983 | + sqlite3OsFileControlHint(fd, SQLITE_FCNTL_BLOCK_ON_CONNECT, &val); |
| 121984 | + } |
| 121985 | +#endif |
| 121524 | 121986 | if( !REOPEN_AS_MEMDB(db) ){ |
| 121525 | 121987 | rc = sqlite3Init(db, &zErrDyn); |
| 121526 | 121988 | } |
| 121527 | 121989 | sqlite3BtreeLeaveAll(db); |
| 121528 | 121990 | assert( zErrDyn==0 || rc!=SQLITE_OK ); |
| | @@ -123240,14 +123702,20 @@ |
| 123240 | 123702 | ** Convert an table column number into a index column number. That is, |
| 123241 | 123703 | ** for the column iCol in the table (as defined by the CREATE TABLE statement) |
| 123242 | 123704 | ** find the (first) offset of that column in index pIdx. Or return -1 |
| 123243 | 123705 | ** if column iCol is not used in index pIdx. |
| 123244 | 123706 | */ |
| 123245 | | -SQLITE_PRIVATE i16 sqlite3TableColumnToIndex(Index *pIdx, i16 iCol){ |
| 123707 | +SQLITE_PRIVATE int sqlite3TableColumnToIndex(Index *pIdx, int iCol){ |
| 123246 | 123708 | int i; |
| 123709 | + i16 iCol16; |
| 123710 | + assert( iCol>=(-1) && iCol<=SQLITE_MAX_COLUMN ); |
| 123711 | + assert( pIdx->nColumn<=SQLITE_MAX_COLUMN ); |
| 123712 | + iCol16 = iCol; |
| 123247 | 123713 | for(i=0; i<pIdx->nColumn; i++){ |
| 123248 | | - if( iCol==pIdx->aiColumn[i] ) return i; |
| 123714 | + if( iCol16==pIdx->aiColumn[i] ){ |
| 123715 | + return i; |
| 123716 | + } |
| 123249 | 123717 | } |
| 123250 | 123718 | return -1; |
| 123251 | 123719 | } |
| 123252 | 123720 | |
| 123253 | 123721 | #ifndef SQLITE_OMIT_GENERATED_COLUMNS |
| | @@ -124340,16 +124808,21 @@ |
| 124340 | 124808 | |
| 124341 | 124809 | /* |
| 124342 | 124810 | ** Resize an Index object to hold N columns total. Return SQLITE_OK |
| 124343 | 124811 | ** on success and SQLITE_NOMEM on an OOM error. |
| 124344 | 124812 | */ |
| 124345 | | -static int resizeIndexObject(sqlite3 *db, Index *pIdx, int N){ |
| 124813 | +static int resizeIndexObject(Parse *pParse, Index *pIdx, int N){ |
| 124346 | 124814 | char *zExtra; |
| 124347 | | - int nByte; |
| 124815 | + u64 nByte; |
| 124816 | + sqlite3 *db; |
| 124348 | 124817 | if( pIdx->nColumn>=N ) return SQLITE_OK; |
| 124818 | + db = pParse->db; |
| 124819 | + assert( N>0 ); |
| 124820 | + assert( N <= SQLITE_MAX_COLUMN*2 /* tag-20250221-1 */ ); |
| 124821 | + testcase( N==2*pParse->db->aLimit[SQLITE_LIMIT_COLUMN] ); |
| 124349 | 124822 | assert( pIdx->isResized==0 ); |
| 124350 | | - nByte = (sizeof(char*) + sizeof(LogEst) + sizeof(i16) + 1)*N; |
| 124823 | + nByte = (sizeof(char*) + sizeof(LogEst) + sizeof(i16) + 1)*(u64)N; |
| 124351 | 124824 | zExtra = sqlite3DbMallocZero(db, nByte); |
| 124352 | 124825 | if( zExtra==0 ) return SQLITE_NOMEM_BKPT; |
| 124353 | 124826 | memcpy(zExtra, pIdx->azColl, sizeof(char*)*pIdx->nColumn); |
| 124354 | 124827 | pIdx->azColl = (const char**)zExtra; |
| 124355 | 124828 | zExtra += sizeof(char*)*N; |
| | @@ -124359,11 +124832,11 @@ |
| 124359 | 124832 | memcpy(zExtra, pIdx->aiColumn, sizeof(i16)*pIdx->nColumn); |
| 124360 | 124833 | pIdx->aiColumn = (i16*)zExtra; |
| 124361 | 124834 | zExtra += sizeof(i16)*N; |
| 124362 | 124835 | memcpy(zExtra, pIdx->aSortOrder, pIdx->nColumn); |
| 124363 | 124836 | pIdx->aSortOrder = (u8*)zExtra; |
| 124364 | | - pIdx->nColumn = N; |
| 124837 | + pIdx->nColumn = (u16)N; /* See tag-20250221-1 above for proof of safety */ |
| 124365 | 124838 | pIdx->isResized = 1; |
| 124366 | 124839 | return SQLITE_OK; |
| 124367 | 124840 | } |
| 124368 | 124841 | |
| 124369 | 124842 | /* |
| | @@ -124613,11 +125086,11 @@ |
| 124613 | 125086 | if( n==0 ){ |
| 124614 | 125087 | /* This index is a superset of the primary key */ |
| 124615 | 125088 | pIdx->nColumn = pIdx->nKeyCol; |
| 124616 | 125089 | continue; |
| 124617 | 125090 | } |
| 124618 | | - if( resizeIndexObject(db, pIdx, pIdx->nKeyCol+n) ) return; |
| 125091 | + if( resizeIndexObject(pParse, pIdx, pIdx->nKeyCol+n) ) return; |
| 124619 | 125092 | for(i=0, j=pIdx->nKeyCol; i<nPk; i++){ |
| 124620 | 125093 | if( !isDupColumn(pIdx, pIdx->nKeyCol, pPk, i) ){ |
| 124621 | 125094 | testcase( hasColumn(pIdx->aiColumn, pIdx->nKeyCol, pPk->aiColumn[i]) ); |
| 124622 | 125095 | pIdx->aiColumn[j] = pPk->aiColumn[i]; |
| 124623 | 125096 | pIdx->azColl[j] = pPk->azColl[i]; |
| | @@ -124637,11 +125110,11 @@ |
| 124637 | 125110 | nExtra = 0; |
| 124638 | 125111 | for(i=0; i<pTab->nCol; i++){ |
| 124639 | 125112 | if( !hasColumn(pPk->aiColumn, nPk, i) |
| 124640 | 125113 | && (pTab->aCol[i].colFlags & COLFLAG_VIRTUAL)==0 ) nExtra++; |
| 124641 | 125114 | } |
| 124642 | | - if( resizeIndexObject(db, pPk, nPk+nExtra) ) return; |
| 125115 | + if( resizeIndexObject(pParse, pPk, nPk+nExtra) ) return; |
| 124643 | 125116 | for(i=0, j=nPk; i<pTab->nCol; i++){ |
| 124644 | 125117 | if( !hasColumn(pPk->aiColumn, j, i) |
| 124645 | 125118 | && (pTab->aCol[i].colFlags & COLFLAG_VIRTUAL)==0 |
| 124646 | 125119 | ){ |
| 124647 | 125120 | assert( j<pPk->nColumn ); |
| | @@ -126021,17 +126494,18 @@ |
| 126021 | 126494 | ** of 8-byte aligned space after the Index object and return a |
| 126022 | 126495 | ** pointer to this extra space in *ppExtra. |
| 126023 | 126496 | */ |
| 126024 | 126497 | SQLITE_PRIVATE Index *sqlite3AllocateIndexObject( |
| 126025 | 126498 | sqlite3 *db, /* Database connection */ |
| 126026 | | - i16 nCol, /* Total number of columns in the index */ |
| 126499 | + int nCol, /* Total number of columns in the index */ |
| 126027 | 126500 | int nExtra, /* Number of bytes of extra space to alloc */ |
| 126028 | 126501 | char **ppExtra /* Pointer to the "extra" space */ |
| 126029 | 126502 | ){ |
| 126030 | 126503 | Index *p; /* Allocated index object */ |
| 126031 | 126504 | i64 nByte; /* Bytes of space for Index object + arrays */ |
| 126032 | 126505 | |
| 126506 | + assert( nCol <= 2*db->aLimit[SQLITE_LIMIT_COLUMN] ); |
| 126033 | 126507 | nByte = ROUND8(sizeof(Index)) + /* Index structure */ |
| 126034 | 126508 | ROUND8(sizeof(char*)*nCol) + /* Index.azColl */ |
| 126035 | 126509 | ROUND8(sizeof(LogEst)*(nCol+1) + /* Index.aiRowLogEst */ |
| 126036 | 126510 | sizeof(i16)*nCol + /* Index.aiColumn */ |
| 126037 | 126511 | sizeof(u8)*nCol); /* Index.aSortOrder */ |
| | @@ -126040,12 +126514,13 @@ |
| 126040 | 126514 | char *pExtra = ((char*)p)+ROUND8(sizeof(Index)); |
| 126041 | 126515 | p->azColl = (const char**)pExtra; pExtra += ROUND8(sizeof(char*)*nCol); |
| 126042 | 126516 | p->aiRowLogEst = (LogEst*)pExtra; pExtra += sizeof(LogEst)*(nCol+1); |
| 126043 | 126517 | p->aiColumn = (i16*)pExtra; pExtra += sizeof(i16)*nCol; |
| 126044 | 126518 | p->aSortOrder = (u8*)pExtra; |
| 126045 | | - p->nColumn = nCol; |
| 126046 | | - p->nKeyCol = nCol - 1; |
| 126519 | + assert( nCol>0 ); |
| 126520 | + p->nColumn = (u16)nCol; |
| 126521 | + p->nKeyCol = (u16)(nCol - 1); |
| 126047 | 126522 | *ppExtra = ((char*)p) + nByte; |
| 126048 | 126523 | } |
| 126049 | 126524 | return p; |
| 126050 | 126525 | } |
| 126051 | 126526 | |
| | @@ -130629,11 +131104,11 @@ |
| 130629 | 131104 | |
| 130630 | 131105 | /* |
| 130631 | 131106 | ** Append to pStr text that is the SQL literal representation of the |
| 130632 | 131107 | ** value contained in pValue. |
| 130633 | 131108 | */ |
| 130634 | | -SQLITE_PRIVATE void sqlite3QuoteValue(StrAccum *pStr, sqlite3_value *pValue){ |
| 131109 | +SQLITE_PRIVATE void sqlite3QuoteValue(StrAccum *pStr, sqlite3_value *pValue, int bEscape){ |
| 130635 | 131110 | /* As currently implemented, the string must be initially empty. |
| 130636 | 131111 | ** we might relax this requirement in the future, but that will |
| 130637 | 131112 | ** require enhancements to the implementation. */ |
| 130638 | 131113 | assert( pStr!=0 && pStr->nChar==0 ); |
| 130639 | 131114 | |
| | @@ -130677,20 +131152,119 @@ |
| 130677 | 131152 | } |
| 130678 | 131153 | break; |
| 130679 | 131154 | } |
| 130680 | 131155 | case SQLITE_TEXT: { |
| 130681 | 131156 | const unsigned char *zArg = sqlite3_value_text(pValue); |
| 130682 | | - sqlite3_str_appendf(pStr, "%Q", zArg); |
| 131157 | + sqlite3_str_appendf(pStr, bEscape ? "%#Q" : "%Q", zArg); |
| 130683 | 131158 | break; |
| 130684 | 131159 | } |
| 130685 | 131160 | default: { |
| 130686 | 131161 | assert( sqlite3_value_type(pValue)==SQLITE_NULL ); |
| 130687 | 131162 | sqlite3_str_append(pStr, "NULL", 4); |
| 130688 | 131163 | break; |
| 130689 | 131164 | } |
| 130690 | 131165 | } |
| 130691 | 131166 | } |
| 131167 | + |
| 131168 | +/* |
| 131169 | +** Return true if z[] begins with N hexadecimal digits, and write |
| 131170 | +** a decoding of those digits into *pVal. Or return false if any |
| 131171 | +** one of the first N characters in z[] is not a hexadecimal digit. |
| 131172 | +*/ |
| 131173 | +static int isNHex(const char *z, int N, u32 *pVal){ |
| 131174 | + int i; |
| 131175 | + int v = 0; |
| 131176 | + for(i=0; i<N; i++){ |
| 131177 | + if( !sqlite3Isxdigit(z[i]) ) return 0; |
| 131178 | + v = (v<<4) + sqlite3HexToInt(z[i]); |
| 131179 | + } |
| 131180 | + *pVal = v; |
| 131181 | + return 1; |
| 131182 | +} |
| 131183 | + |
| 131184 | +/* |
| 131185 | +** Implementation of the UNISTR() function. |
| 131186 | +** |
| 131187 | +** This is intended to be a work-alike of the UNISTR() function in |
| 131188 | +** PostgreSQL. Quoting from the PG documentation (PostgreSQL 17 - |
| 131189 | +** scraped on 2025-02-22): |
| 131190 | +** |
| 131191 | +** Evaluate escaped Unicode characters in the argument. Unicode |
| 131192 | +** characters can be specified as \XXXX (4 hexadecimal digits), |
| 131193 | +** \+XXXXXX (6 hexadecimal digits), \uXXXX (4 hexadecimal digits), |
| 131194 | +** or \UXXXXXXXX (8 hexadecimal digits). To specify a backslash, |
| 131195 | +** write two backslashes. All other characters are taken literally. |
| 131196 | +*/ |
| 131197 | +static void unistrFunc( |
| 131198 | + sqlite3_context *context, |
| 131199 | + int argc, |
| 131200 | + sqlite3_value **argv |
| 131201 | +){ |
| 131202 | + char *zOut; |
| 131203 | + const char *zIn; |
| 131204 | + int nIn; |
| 131205 | + int i, j, n; |
| 131206 | + u32 v; |
| 131207 | + |
| 131208 | + assert( argc==1 ); |
| 131209 | + UNUSED_PARAMETER( argc ); |
| 131210 | + zIn = (const char*)sqlite3_value_text(argv[0]); |
| 131211 | + if( zIn==0 ) return; |
| 131212 | + nIn = sqlite3_value_bytes(argv[0]); |
| 131213 | + zOut = sqlite3_malloc64(nIn+1); |
| 131214 | + if( zOut==0 ){ |
| 131215 | + sqlite3_result_error_nomem(context); |
| 131216 | + return; |
| 131217 | + } |
| 131218 | + i = j = 0; |
| 131219 | + while( i<nIn ){ |
| 131220 | + char *z = strchr(&zIn[i],'\\'); |
| 131221 | + if( z==0 ){ |
| 131222 | + n = nIn - i; |
| 131223 | + memmove(&zOut[j], &zIn[i], n); |
| 131224 | + j += n; |
| 131225 | + break; |
| 131226 | + } |
| 131227 | + n = z - &zIn[i]; |
| 131228 | + if( n>0 ){ |
| 131229 | + memmove(&zOut[j], &zIn[i], n); |
| 131230 | + j += n; |
| 131231 | + i += n; |
| 131232 | + } |
| 131233 | + if( zIn[i+1]=='\\' ){ |
| 131234 | + i += 2; |
| 131235 | + zOut[j++] = '\\'; |
| 131236 | + }else if( sqlite3Isxdigit(zIn[i+1]) ){ |
| 131237 | + if( !isNHex(&zIn[i+1], 4, &v) ) goto unistr_error; |
| 131238 | + i += 5; |
| 131239 | + j += sqlite3AppendOneUtf8Character(&zOut[j], v); |
| 131240 | + }else if( zIn[i+1]=='+' ){ |
| 131241 | + if( !isNHex(&zIn[i+2], 6, &v) ) goto unistr_error; |
| 131242 | + i += 8; |
| 131243 | + j += sqlite3AppendOneUtf8Character(&zOut[j], v); |
| 131244 | + }else if( zIn[i+1]=='u' ){ |
| 131245 | + if( !isNHex(&zIn[i+2], 4, &v) ) goto unistr_error; |
| 131246 | + i += 6; |
| 131247 | + j += sqlite3AppendOneUtf8Character(&zOut[j], v); |
| 131248 | + }else if( zIn[i+1]=='U' ){ |
| 131249 | + if( !isNHex(&zIn[i+2], 8, &v) ) goto unistr_error; |
| 131250 | + i += 10; |
| 131251 | + j += sqlite3AppendOneUtf8Character(&zOut[j], v); |
| 131252 | + }else{ |
| 131253 | + goto unistr_error; |
| 131254 | + } |
| 131255 | + } |
| 131256 | + zOut[j] = 0; |
| 131257 | + sqlite3_result_text64(context, zOut, j, sqlite3_free, SQLITE_UTF8); |
| 131258 | + return; |
| 131259 | + |
| 131260 | +unistr_error: |
| 131261 | + sqlite3_free(zOut); |
| 131262 | + sqlite3_result_error(context, "invalid Unicode escape", -1); |
| 131263 | + return; |
| 131264 | +} |
| 131265 | + |
| 130692 | 131266 | |
| 130693 | 131267 | /* |
| 130694 | 131268 | ** Implementation of the QUOTE() function. |
| 130695 | 131269 | ** |
| 130696 | 131270 | ** The quote(X) function returns the text of an SQL literal which is the |
| | @@ -130697,18 +131271,22 @@ |
| 130697 | 131271 | ** value of its argument suitable for inclusion into an SQL statement. |
| 130698 | 131272 | ** Strings are surrounded by single-quotes with escapes on interior quotes |
| 130699 | 131273 | ** as needed. BLOBs are encoded as hexadecimal literals. Strings with |
| 130700 | 131274 | ** embedded NUL characters cannot be represented as string literals in SQL |
| 130701 | 131275 | ** and hence the returned string literal is truncated prior to the first NUL. |
| 131276 | +** |
| 131277 | +** If sqlite3_user_data() is non-zero, then the UNISTR_QUOTE() function is |
| 131278 | +** implemented instead. The difference is that UNISTR_QUOTE() uses the |
| 131279 | +** UNISTR() function to escape control characters. |
| 130702 | 131280 | */ |
| 130703 | 131281 | static void quoteFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ |
| 130704 | 131282 | sqlite3_str str; |
| 130705 | 131283 | sqlite3 *db = sqlite3_context_db_handle(context); |
| 130706 | 131284 | assert( argc==1 ); |
| 130707 | 131285 | UNUSED_PARAMETER(argc); |
| 130708 | 131286 | sqlite3StrAccumInit(&str, db, 0, 0, db->aLimit[SQLITE_LIMIT_LENGTH]); |
| 130709 | | - sqlite3QuoteValue(&str,argv[0]); |
| 131287 | + sqlite3QuoteValue(&str,argv[0],SQLITE_PTR_TO_INT(sqlite3_user_data(context))); |
| 130710 | 131288 | sqlite3_result_text(context, sqlite3StrAccumFinish(&str), str.nChar, |
| 130711 | 131289 | SQLITE_DYNAMIC); |
| 130712 | 131290 | if( str.accError!=SQLITE_OK ){ |
| 130713 | 131291 | sqlite3_result_null(context); |
| 130714 | 131292 | sqlite3_result_error_code(context, str.accError); |
| | @@ -132275,11 +132853,13 @@ |
| 132275 | 132853 | VFUNCTION(randomblob, 1, 0, 0, randomBlob ), |
| 132276 | 132854 | FUNCTION(nullif, 2, 0, 1, nullifFunc ), |
| 132277 | 132855 | DFUNCTION(sqlite_version, 0, 0, 0, versionFunc ), |
| 132278 | 132856 | DFUNCTION(sqlite_source_id, 0, 0, 0, sourceidFunc ), |
| 132279 | 132857 | FUNCTION(sqlite_log, 2, 0, 0, errlogFunc ), |
| 132858 | + FUNCTION(unistr, 1, 0, 0, unistrFunc ), |
| 132280 | 132859 | FUNCTION(quote, 1, 0, 0, quoteFunc ), |
| 132860 | + FUNCTION(unistr_quote, 1, 1, 0, quoteFunc ), |
| 132281 | 132861 | VFUNCTION(last_insert_rowid, 0, 0, 0, last_insert_rowid), |
| 132282 | 132862 | VFUNCTION(changes, 0, 0, 0, changes ), |
| 132283 | 132863 | VFUNCTION(total_changes, 0, 0, 0, total_changes ), |
| 132284 | 132864 | FUNCTION(replace, 3, 0, 0, replaceFunc ), |
| 132285 | 132865 | FUNCTION(zeroblob, 1, 0, 0, zeroblobFunc ), |
| | @@ -134562,11 +135142,11 @@ |
| 134562 | 135142 | }else if( pLeft->pPrior ){ |
| 134563 | 135143 | /* In this case set the SF_MultiValue flag only if it was set on pLeft */ |
| 134564 | 135144 | f = (f & pLeft->selFlags); |
| 134565 | 135145 | } |
| 134566 | 135146 | pSelect = sqlite3SelectNew(pParse, pRow, 0, 0, 0, 0, 0, f, 0); |
| 134567 | | - pLeft->selFlags &= ~SF_MultiValue; |
| 135147 | + pLeft->selFlags &= ~(u32)SF_MultiValue; |
| 134568 | 135148 | if( pSelect ){ |
| 134569 | 135149 | pSelect->op = TK_ALL; |
| 134570 | 135150 | pSelect->pPrior = pLeft; |
| 134571 | 135151 | pLeft = pSelect; |
| 134572 | 135152 | } |
| | @@ -149534,11 +150114,11 @@ |
| 149534 | 150114 | p->pNext = 0; |
| 149535 | 150115 | p->pWith = 0; |
| 149536 | 150116 | #ifndef SQLITE_OMIT_WINDOWFUNC |
| 149537 | 150117 | p->pWinDefn = 0; |
| 149538 | 150118 | #endif |
| 149539 | | - p->selFlags &= ~SF_Compound; |
| 150119 | + p->selFlags &= ~(u32)SF_Compound; |
| 149540 | 150120 | assert( (p->selFlags & SF_Converted)==0 ); |
| 149541 | 150121 | p->selFlags |= SF_Converted; |
| 149542 | 150122 | assert( pNew->pPrior!=0 ); |
| 149543 | 150123 | pNew->pPrior->pNext = pNew; |
| 149544 | 150124 | pNew->pLimit = 0; |
| | @@ -151140,11 +151720,11 @@ |
| 151140 | 151720 | Expr *pTerm; |
| 151141 | 151721 | pPrior = pSub->pPrior; |
| 151142 | 151722 | pSub->pPrior = 0; |
| 151143 | 151723 | pSub->pNext = 0; |
| 151144 | 151724 | pSub->selFlags |= SF_Aggregate; |
| 151145 | | - pSub->selFlags &= ~SF_Compound; |
| 151725 | + pSub->selFlags &= ~(u32)SF_Compound; |
| 151146 | 151726 | pSub->nSelectRow = 0; |
| 151147 | 151727 | sqlite3ParserAddCleanup(pParse, sqlite3ExprListDeleteGeneric, pSub->pEList); |
| 151148 | 151728 | pTerm = pPrior ? sqlite3ExprDup(db, pCount, 0) : pCount; |
| 151149 | 151729 | pSub->pEList = sqlite3ExprListAppend(pParse, 0, pTerm); |
| 151150 | 151730 | pTerm = sqlite3PExpr(pParse, TK_SELECT, 0, 0); |
| | @@ -151155,11 +151735,11 @@ |
| 151155 | 151735 | pExpr = sqlite3PExpr(pParse, TK_PLUS, pTerm, pExpr); |
| 151156 | 151736 | } |
| 151157 | 151737 | pSub = pPrior; |
| 151158 | 151738 | } |
| 151159 | 151739 | p->pEList->a[0].pExpr = pExpr; |
| 151160 | | - p->selFlags &= ~SF_Aggregate; |
| 151740 | + p->selFlags &= ~(u32)SF_Aggregate; |
| 151161 | 151741 | |
| 151162 | 151742 | #if TREETRACE_ENABLED |
| 151163 | 151743 | if( sqlite3TreeTrace & 0x200 ){ |
| 151164 | 151744 | TREETRACE(0x200,pParse,p,("After count-of-view optimization:\n")); |
| 151165 | 151745 | sqlite3TreeViewSelect(0, p, 0); |
| | @@ -151362,11 +151942,11 @@ |
| 151362 | 151942 | sqlite3ParserAddCleanup(pParse, sqlite3ExprListDeleteGeneric, |
| 151363 | 151943 | p->pOrderBy); |
| 151364 | 151944 | testcase( pParse->earlyCleanup ); |
| 151365 | 151945 | p->pOrderBy = 0; |
| 151366 | 151946 | } |
| 151367 | | - p->selFlags &= ~SF_Distinct; |
| 151947 | + p->selFlags &= ~(u32)SF_Distinct; |
| 151368 | 151948 | p->selFlags |= SF_NoopOrderBy; |
| 151369 | 151949 | } |
| 151370 | 151950 | sqlite3SelectPrep(pParse, p, 0); |
| 151371 | 151951 | if( pParse->nErr ){ |
| 151372 | 151952 | goto select_end; |
| | @@ -151401,11 +151981,11 @@ |
| 151401 | 151981 | |
| 151402 | 151982 | /* Clear the SF_UFSrcCheck flag. The check has already been performed, |
| 151403 | 151983 | ** and leaving this flag set can cause errors if a compound sub-query |
| 151404 | 151984 | ** in p->pSrc is flattened into this query and this function called |
| 151405 | 151985 | ** again as part of compound SELECT processing. */ |
| 151406 | | - p->selFlags &= ~SF_UFSrcCheck; |
| 151986 | + p->selFlags &= ~(u32)SF_UFSrcCheck; |
| 151407 | 151987 | } |
| 151408 | 151988 | |
| 151409 | 151989 | if( pDest->eDest==SRT_Output ){ |
| 151410 | 151990 | sqlite3GenerateColumnNames(pParse, p); |
| 151411 | 151991 | } |
| | @@ -151890,11 +152470,11 @@ |
| 151890 | 152470 | && OptimizationEnabled(db, SQLITE_GroupByOrder) |
| 151891 | 152471 | #ifndef SQLITE_OMIT_WINDOWFUNC |
| 151892 | 152472 | && p->pWin==0 |
| 151893 | 152473 | #endif |
| 151894 | 152474 | ){ |
| 151895 | | - p->selFlags &= ~SF_Distinct; |
| 152475 | + p->selFlags &= ~(u32)SF_Distinct; |
| 151896 | 152476 | pGroupBy = p->pGroupBy = sqlite3ExprListDup(db, pEList, 0); |
| 151897 | 152477 | if( pGroupBy ){ |
| 151898 | 152478 | for(i=0; i<pGroupBy->nExpr; i++){ |
| 151899 | 152479 | pGroupBy->a[i].u.x.iOrderByCol = i+1; |
| 151900 | 152480 | } |
| | @@ -164580,10 +165160,12 @@ |
| 164580 | 165160 | if( pSrc->colUsed & MASKBIT(BMS-1) ){ |
| 164581 | 165161 | nKeyCol += pTable->nCol - BMS + 1; |
| 164582 | 165162 | } |
| 164583 | 165163 | |
| 164584 | 165164 | /* Construct the Index object to describe this index */ |
| 165165 | + assert( nKeyCol <= pTable->nCol + MAX(0, pTable->nCol - BMS + 1) ); |
| 165166 | + /* ^-- This guarantees that the number of index columns will fit in the u16 */ |
| 164585 | 165167 | pIdx = sqlite3AllocateIndexObject(pParse->db, nKeyCol+HasRowid(pTable), |
| 164586 | 165168 | 0, &zNotUsed); |
| 164587 | 165169 | if( pIdx==0 ) goto end_auto_index_create; |
| 164588 | 165170 | pLoop->u.btree.pIndex = pIdx; |
| 164589 | 165171 | pIdx->zName = "auto-index"; |
| | @@ -172141,11 +172723,11 @@ |
| 172141 | 172723 | |
| 172142 | 172724 | p->pSrc = 0; |
| 172143 | 172725 | p->pWhere = 0; |
| 172144 | 172726 | p->pGroupBy = 0; |
| 172145 | 172727 | p->pHaving = 0; |
| 172146 | | - p->selFlags &= ~SF_Aggregate; |
| 172728 | + p->selFlags &= ~(u32)SF_Aggregate; |
| 172147 | 172729 | p->selFlags |= SF_WinRewrite; |
| 172148 | 172730 | |
| 172149 | 172731 | /* Create the ORDER BY clause for the sub-select. This is the concatenation |
| 172150 | 172732 | ** of the window PARTITION and ORDER BY clauses. Then, if this makes it |
| 172151 | 172733 | ** redundant, remove the ORDER BY from the parent SELECT. */ |
| | @@ -178280,12 +178862,12 @@ |
| 178280 | 178862 | pRhs = sqlite3SelectNew(pParse,0,pFrom,0,0,0,0,0,0); |
| 178281 | 178863 | } |
| 178282 | 178864 | if( pRhs ){ |
| 178283 | 178865 | pRhs->op = (u8)yymsp[-1].minor.yy502; |
| 178284 | 178866 | pRhs->pPrior = pLhs; |
| 178285 | | - if( ALWAYS(pLhs) ) pLhs->selFlags &= ~SF_MultiValue; |
| 178286 | | - pRhs->selFlags &= ~SF_MultiValue; |
| 178867 | + if( ALWAYS(pLhs) ) pLhs->selFlags &= ~(u32)SF_MultiValue; |
| 178868 | + pRhs->selFlags &= ~(u32)SF_MultiValue; |
| 178287 | 178869 | if( yymsp[-1].minor.yy502!=TK_ALL ) pParse->hasCompound = 1; |
| 178288 | 178870 | }else{ |
| 178289 | 178871 | sqlite3SelectDelete(pParse->db, pLhs); |
| 178290 | 178872 | } |
| 178291 | 178873 | yymsp[-2].minor.yy637 = pRhs; |
| | @@ -183396,10 +183978,13 @@ |
| 183396 | 183978 | sqlite3_mutex_enter(db->mutex); |
| 183397 | 183979 | db->busyHandler.xBusyHandler = xBusy; |
| 183398 | 183980 | db->busyHandler.pBusyArg = pArg; |
| 183399 | 183981 | db->busyHandler.nBusy = 0; |
| 183400 | 183982 | db->busyTimeout = 0; |
| 183983 | +#ifdef SQLITE_ENABLE_SETLK_TIMEOUT |
| 183984 | + db->setlkTimeout = 0; |
| 183985 | +#endif |
| 183401 | 183986 | sqlite3_mutex_leave(db->mutex); |
| 183402 | 183987 | return SQLITE_OK; |
| 183403 | 183988 | } |
| 183404 | 183989 | |
| 183405 | 183990 | #ifndef SQLITE_OMIT_PROGRESS_CALLBACK |
| | @@ -183445,15 +184030,46 @@ |
| 183445 | 184030 | #endif |
| 183446 | 184031 | if( ms>0 ){ |
| 183447 | 184032 | sqlite3_busy_handler(db, (int(*)(void*,int))sqliteDefaultBusyCallback, |
| 183448 | 184033 | (void*)db); |
| 183449 | 184034 | db->busyTimeout = ms; |
| 184035 | +#ifdef SQLITE_ENABLE_SETLK_TIMEOUT |
| 184036 | + db->setlkTimeout = ms; |
| 184037 | +#endif |
| 183450 | 184038 | }else{ |
| 183451 | 184039 | sqlite3_busy_handler(db, 0, 0); |
| 183452 | 184040 | } |
| 183453 | 184041 | return SQLITE_OK; |
| 183454 | 184042 | } |
| 184043 | + |
| 184044 | +/* |
| 184045 | +** Set the setlk timeout value. |
| 184046 | +*/ |
| 184047 | +SQLITE_API int sqlite3_setlk_timeout(sqlite3 *db, int ms, int flags){ |
| 184048 | +#ifdef SQLITE_ENABLE_SETLK_TIMEOUT |
| 184049 | + int iDb; |
| 184050 | + int bBOC = ((flags & SQLITE_SETLK_BLOCK_ON_CONNECT) ? 1 : 0); |
| 184051 | +#endif |
| 184052 | +#ifdef SQLITE_ENABLE_API_ARMOR |
| 184053 | + if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; |
| 184054 | +#endif |
| 184055 | + if( ms<-1 ) return SQLITE_RANGE; |
| 184056 | +#ifdef SQLITE_ENABLE_SETLK_TIMEOUT |
| 184057 | + db->setlkTimeout = ms; |
| 184058 | + db->setlkFlags = flags; |
| 184059 | + sqlite3BtreeEnterAll(db); |
| 184060 | + for(iDb=0; iDb<db->nDb; iDb++){ |
| 184061 | + Btree *pBt = db->aDb[iDb].pBt; |
| 184062 | + if( pBt ){ |
| 184063 | + sqlite3_file *fd = sqlite3PagerFile(sqlite3BtreePager(pBt)); |
| 184064 | + sqlite3OsFileControlHint(fd, SQLITE_FCNTL_BLOCK_ON_CONNECT, (void*)&bBOC); |
| 184065 | + } |
| 184066 | + } |
| 184067 | + sqlite3BtreeLeaveAll(db); |
| 184068 | +#endif |
| 184069 | + return SQLITE_OK; |
| 184070 | +} |
| 183455 | 184071 | |
| 183456 | 184072 | /* |
| 183457 | 184073 | ** Cause any pending operation to stop at its earliest opportunity. |
| 183458 | 184074 | */ |
| 183459 | 184075 | SQLITE_API void sqlite3_interrupt(sqlite3 *db){ |
| | @@ -255960,11 +256576,11 @@ |
| 255960 | 256576 | int nArg, /* Number of args */ |
| 255961 | 256577 | sqlite3_value **apUnused /* Function arguments */ |
| 255962 | 256578 | ){ |
| 255963 | 256579 | assert( nArg==0 ); |
| 255964 | 256580 | UNUSED_PARAM2(nArg, apUnused); |
| 255965 | | - sqlite3_result_text(pCtx, "fts5: 2025-02-18 01:16:26 57caa3136d1bfca06e4f2285734a4977b8d3fa1f75bf87453b975867e9de38fc", -1, SQLITE_TRANSIENT); |
| 256581 | + sqlite3_result_text(pCtx, "fts5: 2025-02-25 16:39:51 6f0b6d95db17e69ac7e46a39f52770291ac4cfe43eea09add224946a6e11f04e", -1, SQLITE_TRANSIENT); |
| 255966 | 256582 | } |
| 255967 | 256583 | |
| 255968 | 256584 | /* |
| 255969 | 256585 | ** Implementation of fts5_locale(LOCALE, TEXT) function. |
| 255970 | 256586 | ** |
| | @@ -256185,12 +256801,12 @@ |
| 256185 | 256801 | /* If SQLITE_FTS5_ENABLE_TEST_MI is defined, assume that the file |
| 256186 | 256802 | ** fts5_test_mi.c is compiled and linked into the executable. And call |
| 256187 | 256803 | ** its entry point to enable the matchinfo() demo. */ |
| 256188 | 256804 | #ifdef SQLITE_FTS5_ENABLE_TEST_MI |
| 256189 | 256805 | if( rc==SQLITE_OK ){ |
| 256190 | | - extern int sqlite3Fts5TestRegisterMatchinfo(sqlite3*); |
| 256191 | | - rc = sqlite3Fts5TestRegisterMatchinfo(db); |
| 256806 | + extern int sqlite3Fts5TestRegisterMatchinfoAPI(fts5_api*); |
| 256807 | + rc = sqlite3Fts5TestRegisterMatchinfoAPI(&pGlobal->api); |
| 256192 | 256808 | } |
| 256193 | 256809 | #endif |
| 256194 | 256810 | |
| 256195 | 256811 | return rc; |
| 256196 | 256812 | } |
| 256197 | 256813 | |