Fossil SCM
Update the built-in SQLite to the latest 3.43.0 beta for testing.
Commit
16ee39539a51a914a9f2f75e428032c6ba338508d46effcfff18ea81bf826a6a
Parent
f0e1d0c95834694…
2 files changed
+536
-168
+5
-4
+536
-168
| --- extsrc/sqlite3.c | ||
| +++ extsrc/sqlite3.c | ||
| @@ -1,8 +1,8 @@ | ||
| 1 | 1 | /****************************************************************************** |
| 2 | 2 | ** This file is an amalgamation of many separate C source files from SQLite |
| 3 | -** version $VERSION. By combining all the individual C code files into this | |
| 3 | +** version 3.43.0. By combining all the individual C code files into this | |
| 4 | 4 | ** single large file, the entire code can be compiled as a single translation |
| 5 | 5 | ** unit. This allows many compilers to do optimizations that would not be |
| 6 | 6 | ** possible if the files were compiled separately. Performance improvements |
| 7 | 7 | ** of 5% or more are commonly seen when SQLite is compiled as a single |
| 8 | 8 | ** translation unit. |
| @@ -16,11 +16,11 @@ | ||
| 16 | 16 | ** if you want a wrapper to interface SQLite with your choice of programming |
| 17 | 17 | ** language. The code for the "sqlite3" command-line shell is also in a |
| 18 | 18 | ** separate file. This file contains only code for the core SQLite library. |
| 19 | 19 | ** |
| 20 | 20 | ** The content in this amalgamation comes from Fossil check-in |
| 21 | -** a7a66db13b28da0b41f03be825a59360847. | |
| 21 | +** bc0693c4633f545f09dbee702e25354504b. | |
| 22 | 22 | */ |
| 23 | 23 | #define SQLITE_CORE 1 |
| 24 | 24 | #define SQLITE_AMALGAMATION 1 |
| 25 | 25 | #ifndef SQLITE_PRIVATE |
| 26 | 26 | # define SQLITE_PRIVATE static |
| @@ -459,11 +459,11 @@ | ||
| 459 | 459 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 460 | 460 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 461 | 461 | */ |
| 462 | 462 | #define SQLITE_VERSION "3.43.0" |
| 463 | 463 | #define SQLITE_VERSION_NUMBER 3043000 |
| 464 | -#define SQLITE_SOURCE_ID "2023-08-04 13:19:11 ba7a66db13b28da0b41f03be825a593608474a5ebda89e12d58d89db709b8f65" | |
| 464 | +#define SQLITE_SOURCE_ID "2023-08-11 22:40:06 3bc0693c4633f545f09dbee702e25354504b20836373a068447e6c61cb2ebd79" | |
| 465 | 465 | |
| 466 | 466 | /* |
| 467 | 467 | ** CAPI3REF: Run-Time Library Version Numbers |
| 468 | 468 | ** KEYWORDS: sqlite3_version sqlite3_sourceid |
| 469 | 469 | ** |
| @@ -839,10 +839,11 @@ | ||
| 839 | 839 | #define SQLITE_IOERR_BEGIN_ATOMIC (SQLITE_IOERR | (29<<8)) |
| 840 | 840 | #define SQLITE_IOERR_COMMIT_ATOMIC (SQLITE_IOERR | (30<<8)) |
| 841 | 841 | #define SQLITE_IOERR_ROLLBACK_ATOMIC (SQLITE_IOERR | (31<<8)) |
| 842 | 842 | #define SQLITE_IOERR_DATA (SQLITE_IOERR | (32<<8)) |
| 843 | 843 | #define SQLITE_IOERR_CORRUPTFS (SQLITE_IOERR | (33<<8)) |
| 844 | +#define SQLITE_IOERR_IN_PAGE (SQLITE_IOERR | (34<<8)) | |
| 844 | 845 | #define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8)) |
| 845 | 846 | #define SQLITE_LOCKED_VTAB (SQLITE_LOCKED | (2<<8)) |
| 846 | 847 | #define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8)) |
| 847 | 848 | #define SQLITE_BUSY_SNAPSHOT (SQLITE_BUSY | (2<<8)) |
| 848 | 849 | #define SQLITE_BUSY_TIMEOUT (SQLITE_BUSY | (3<<8)) |
| @@ -13394,28 +13395,28 @@ | ||
| 13394 | 13395 | |
| 13395 | 13396 | /* Create a new tokenizer */ |
| 13396 | 13397 | int (*xCreateTokenizer)( |
| 13397 | 13398 | fts5_api *pApi, |
| 13398 | 13399 | const char *zName, |
| 13399 | - void *pContext, | |
| 13400 | + void *pUserData, | |
| 13400 | 13401 | fts5_tokenizer *pTokenizer, |
| 13401 | 13402 | void (*xDestroy)(void*) |
| 13402 | 13403 | ); |
| 13403 | 13404 | |
| 13404 | 13405 | /* Find an existing tokenizer */ |
| 13405 | 13406 | int (*xFindTokenizer)( |
| 13406 | 13407 | fts5_api *pApi, |
| 13407 | 13408 | const char *zName, |
| 13408 | - void **ppContext, | |
| 13409 | + void **ppUserData, | |
| 13409 | 13410 | fts5_tokenizer *pTokenizer |
| 13410 | 13411 | ); |
| 13411 | 13412 | |
| 13412 | 13413 | /* Create a new auxiliary function */ |
| 13413 | 13414 | int (*xCreateFunction)( |
| 13414 | 13415 | fts5_api *pApi, |
| 13415 | 13416 | const char *zName, |
| 13416 | - void *pContext, | |
| 13417 | + void *pUserData, | |
| 13417 | 13418 | fts5_extension_function xFunction, |
| 13418 | 13419 | void (*xDestroy)(void*) |
| 13419 | 13420 | ); |
| 13420 | 13421 | }; |
| 13421 | 13422 | |
| @@ -14630,11 +14631,11 @@ | ||
| 14630 | 14631 | #define SQLITE_WITHIN(P,S,E) (((uptr)(P)>=(uptr)(S))&&((uptr)(P)<(uptr)(E))) |
| 14631 | 14632 | |
| 14632 | 14633 | /* |
| 14633 | 14634 | ** P is one byte past the end of a large buffer. Return true if a span of bytes |
| 14634 | 14635 | ** between S..E crosses the end of that buffer. In other words, return true |
| 14635 | -** if the sub-buffer S..E-1 overflows the buffer show last byte is P-1. | |
| 14636 | +** if the sub-buffer S..E-1 overflows the buffer whose last byte is P-1. | |
| 14636 | 14637 | ** |
| 14637 | 14638 | ** S is the start of the span. E is one byte past the end of end of span. |
| 14638 | 14639 | ** |
| 14639 | 14640 | ** P |
| 14640 | 14641 | ** |-----------------| FALSE |
| @@ -14993,11 +14994,10 @@ | ||
| 14993 | 14994 | typedef struct Column Column; |
| 14994 | 14995 | typedef struct Cte Cte; |
| 14995 | 14996 | typedef struct CteUse CteUse; |
| 14996 | 14997 | typedef struct Db Db; |
| 14997 | 14998 | typedef struct DbFixer DbFixer; |
| 14998 | -typedef struct DblDbl DblDbl; | |
| 14999 | 14999 | typedef struct Schema Schema; |
| 15000 | 15000 | typedef struct Expr Expr; |
| 15001 | 15001 | typedef struct ExprList ExprList; |
| 15002 | 15002 | typedef struct FKey FKey; |
| 15003 | 15003 | typedef struct FpDecode FpDecode; |
| @@ -15654,10 +15654,14 @@ | ||
| 15654 | 15654 | void enable_simulated_io_errors(void); |
| 15655 | 15655 | #else |
| 15656 | 15656 | # define disable_simulated_io_errors() |
| 15657 | 15657 | # define enable_simulated_io_errors() |
| 15658 | 15658 | #endif |
| 15659 | + | |
| 15660 | +#ifdef SQLITE_USE_SEH | |
| 15661 | +SQLITE_PRIVATE int sqlite3PagerWalSystemErrno(Pager*); | |
| 15662 | +#endif | |
| 15659 | 15663 | |
| 15660 | 15664 | #endif /* SQLITE_PAGER_H */ |
| 15661 | 15665 | |
| 15662 | 15666 | /************** End of pager.h ***********************************************/ |
| 15663 | 15667 | /************** Continuing where we left off in sqliteInt.h ******************/ |
| @@ -19430,10 +19434,13 @@ | ||
| 19430 | 19434 | yDbMask cookieMask; /* Bitmask of schema verified databases */ |
| 19431 | 19435 | int regRowid; /* Register holding rowid of CREATE TABLE entry */ |
| 19432 | 19436 | int regRoot; /* Register holding root page number for new objects */ |
| 19433 | 19437 | int nMaxArg; /* Max args passed to user function by sub-program */ |
| 19434 | 19438 | int nSelect; /* Number of SELECT stmts. Counter for Select.selId */ |
| 19439 | +#ifndef SQLITE_OMIT_PROGRESS_CALLBACK | |
| 19440 | + u32 nProgressSteps; /* xProgress steps taken during sqlite3_prepare() */ | |
| 19441 | +#endif | |
| 19435 | 19442 | #ifndef SQLITE_OMIT_SHARED_CACHE |
| 19436 | 19443 | int nTableLock; /* Number of locks in aTableLock */ |
| 19437 | 19444 | TableLock *aTableLock; /* Required table locks for shared-cache mode */ |
| 19438 | 19445 | #endif |
| 19439 | 19446 | AutoincInfo *pAinc; /* Information about AUTOINCREMENT counters */ |
| @@ -19443,16 +19450,13 @@ | ||
| 19443 | 19450 | ParseCleanup *pCleanup; /* List of cleanup operations to run after parse */ |
| 19444 | 19451 | union { |
| 19445 | 19452 | int addrCrTab; /* Address of OP_CreateBtree on CREATE TABLE */ |
| 19446 | 19453 | Returning *pReturning; /* The RETURNING clause */ |
| 19447 | 19454 | } u1; |
| 19448 | - LogEst nQueryLoop; /* Est number of iterations of a query (10*log2(N)) */ | |
| 19449 | 19455 | u32 oldmask; /* Mask of old.* columns referenced */ |
| 19450 | 19456 | u32 newmask; /* Mask of new.* columns referenced */ |
| 19451 | -#ifndef SQLITE_OMIT_PROGRESS_CALLBACK | |
| 19452 | - u32 nProgressSteps; /* xProgress steps taken during sqlite3_prepare() */ | |
| 19453 | -#endif | |
| 19457 | + LogEst nQueryLoop; /* Est number of iterations of a query (10*log2(N)) */ | |
| 19454 | 19458 | u8 eTriggerOp; /* TK_UPDATE, TK_INSERT or TK_DELETE */ |
| 19455 | 19459 | u8 bReturning; /* Coding a RETURNING trigger */ |
| 19456 | 19460 | u8 eOrconf; /* Default ON CONFLICT policy for trigger steps */ |
| 19457 | 19461 | u8 disableTriggers; /* True to disable triggers */ |
| 19458 | 19462 | |
| @@ -21503,13 +21507,10 @@ | ||
| 21503 | 21507 | "32BIT_ROWID", |
| 21504 | 21508 | #endif |
| 21505 | 21509 | #ifdef SQLITE_4_BYTE_ALIGNED_MALLOC |
| 21506 | 21510 | "4_BYTE_ALIGNED_MALLOC", |
| 21507 | 21511 | #endif |
| 21508 | -#ifdef SQLITE_64BIT_STATS | |
| 21509 | - "64BIT_STATS", | |
| 21510 | -#endif | |
| 21511 | 21512 | #ifdef SQLITE_ALLOW_COVERING_INDEX_SCAN |
| 21512 | 21513 | # if SQLITE_ALLOW_COVERING_INDEX_SCAN != 1 |
| 21513 | 21514 | "ALLOW_COVERING_INDEX_SCAN=" CTIMEOPT_VAL(SQLITE_ALLOW_COVERING_INDEX_SCAN), |
| 21514 | 21515 | # endif |
| 21515 | 21516 | #endif |
| @@ -21841,10 +21842,13 @@ | ||
| 21841 | 21842 | #ifdef SQLITE_INT64_TYPE |
| 21842 | 21843 | "INT64_TYPE", |
| 21843 | 21844 | #endif |
| 21844 | 21845 | #ifdef SQLITE_INTEGRITY_CHECK_ERROR_MAX |
| 21845 | 21846 | "INTEGRITY_CHECK_ERROR_MAX=" CTIMEOPT_VAL(SQLITE_INTEGRITY_CHECK_ERROR_MAX), |
| 21847 | +#endif | |
| 21848 | +#ifdef SQLITE_LEGACY_JSON_VALID | |
| 21849 | + "LEGACY_JSON_VALID", | |
| 21846 | 21850 | #endif |
| 21847 | 21851 | #ifdef SQLITE_LIKE_DOESNT_MATCH_BLOBS |
| 21848 | 21852 | "LIKE_DOESNT_MATCH_BLOBS", |
| 21849 | 21853 | #endif |
| 21850 | 21854 | #ifdef SQLITE_LOCK_TRACE |
| @@ -34295,10 +34299,27 @@ | ||
| 34295 | 34299 | ** Load the sqlite3.iSysErrno field if that is an appropriate thing |
| 34296 | 34300 | ** to do based on the SQLite error code in rc. |
| 34297 | 34301 | */ |
| 34298 | 34302 | SQLITE_PRIVATE void sqlite3SystemError(sqlite3 *db, int rc){ |
| 34299 | 34303 | if( rc==SQLITE_IOERR_NOMEM ) return; |
| 34304 | +#ifdef SQLITE_USE_SEH | |
| 34305 | + if( rc==SQLITE_IOERR_IN_PAGE ){ | |
| 34306 | + int ii; | |
| 34307 | + int iErr; | |
| 34308 | + sqlite3BtreeEnterAll(db); | |
| 34309 | + for(ii=0; ii<db->nDb; ii++){ | |
| 34310 | + if( db->aDb[ii].pBt ){ | |
| 34311 | + iErr = sqlite3PagerWalSystemErrno(sqlite3BtreePager(db->aDb[ii].pBt)); | |
| 34312 | + if( iErr ){ | |
| 34313 | + db->iSysErrno = iErr; | |
| 34314 | + } | |
| 34315 | + } | |
| 34316 | + } | |
| 34317 | + sqlite3BtreeLeaveAll(db); | |
| 34318 | + return; | |
| 34319 | + } | |
| 34320 | +#endif | |
| 34300 | 34321 | rc &= 0xff; |
| 34301 | 34322 | if( rc==SQLITE_CANTOPEN || rc==SQLITE_IOERR ){ |
| 34302 | 34323 | db->iSysErrno = sqlite3OsGetLastError(db->pVfs); |
| 34303 | 34324 | } |
| 34304 | 34325 | } |
| @@ -56206,10 +56227,14 @@ | ||
| 56206 | 56227 | |
| 56207 | 56228 | #ifdef SQLITE_ENABLE_SETLK_TIMEOUT |
| 56208 | 56229 | SQLITE_PRIVATE int sqlite3WalWriteLock(Wal *pWal, int bLock); |
| 56209 | 56230 | SQLITE_PRIVATE void sqlite3WalDb(Wal *pWal, sqlite3 *db); |
| 56210 | 56231 | #endif |
| 56232 | + | |
| 56233 | +#ifdef SQLITE_USE_SEH | |
| 56234 | +SQLITE_PRIVATE int sqlite3WalSystemErrno(Wal*); | |
| 56235 | +#endif | |
| 56211 | 56236 | |
| 56212 | 56237 | #endif /* ifndef SQLITE_OMIT_WAL */ |
| 56213 | 56238 | #endif /* SQLITE_WAL_H */ |
| 56214 | 56239 | |
| 56215 | 56240 | /************** End of wal.h *************************************************/ |
| @@ -63919,10 +63944,16 @@ | ||
| 63919 | 63944 | SQLITE_PRIVATE int sqlite3PagerWalFramesize(Pager *pPager){ |
| 63920 | 63945 | assert( pPager->eState>=PAGER_READER ); |
| 63921 | 63946 | return sqlite3WalFramesize(pPager->pWal); |
| 63922 | 63947 | } |
| 63923 | 63948 | #endif |
| 63949 | + | |
| 63950 | +#ifdef SQLITE_USE_SEH | |
| 63951 | +SQLITE_PRIVATE int sqlite3PagerWalSystemErrno(Pager *pPager){ | |
| 63952 | + return sqlite3WalSystemErrno(pPager->pWal); | |
| 63953 | +} | |
| 63954 | +#endif | |
| 63924 | 63955 | |
| 63925 | 63956 | #endif /* SQLITE_OMIT_DISKIO */ |
| 63926 | 63957 | |
| 63927 | 63958 | /************** End of pager.c ***********************************************/ |
| 63928 | 63959 | /************** Begin file wal.c *********************************************/ |
| @@ -64454,11 +64485,17 @@ | ||
| 64454 | 64485 | WalIndexHdr hdr; /* Wal-index header for current transaction */ |
| 64455 | 64486 | u32 minFrame; /* Ignore wal frames before this one */ |
| 64456 | 64487 | u32 iReCksum; /* On commit, recalculate checksums from here */ |
| 64457 | 64488 | const char *zWalName; /* Name of WAL file */ |
| 64458 | 64489 | u32 nCkpt; /* Checkpoint sequence counter in the wal-header */ |
| 64490 | +#ifdef SQLITE_USE_SEH | |
| 64491 | + u32 lockMask; /* Mask of locks held */ | |
| 64492 | + void *pFree; /* Pointer to sqlite3_free() if exception thrown */ | |
| 64493 | + int iSysErrno; /* System error code following exception */ | |
| 64494 | +#endif | |
| 64459 | 64495 | #ifdef SQLITE_DEBUG |
| 64496 | + int nSehTry; /* Number of nested SEH_TRY{} blocks */ | |
| 64460 | 64497 | u8 lockError; /* True if a locking error has occurred */ |
| 64461 | 64498 | #endif |
| 64462 | 64499 | #ifdef SQLITE_ENABLE_SNAPSHOT |
| 64463 | 64500 | WalIndexHdr *pSnapshot; /* Start transaction here if not NULL */ |
| 64464 | 64501 | #endif |
| @@ -64535,10 +64572,104 @@ | ||
| 64535 | 64572 | |
| 64536 | 64573 | /* The wal-index is divided into pages of WALINDEX_PGSZ bytes each. */ |
| 64537 | 64574 | #define WALINDEX_PGSZ ( \ |
| 64538 | 64575 | sizeof(ht_slot)*HASHTABLE_NSLOT + HASHTABLE_NPAGE*sizeof(u32) \ |
| 64539 | 64576 | ) |
| 64577 | + | |
| 64578 | +/* | |
| 64579 | +** Structured Exception Handling (SEH) is a Windows-specific technique | |
| 64580 | +** for catching exceptions raised while accessing memory-mapped files. | |
| 64581 | +** | |
| 64582 | +** The -DSQLITE_USE_SEH compile-time option means to use SEH to catch and | |
| 64583 | +** deal with system-level errors that arise during WAL -shm file processing. | |
| 64584 | +** Without this compile-time option, any system-level faults that appear | |
| 64585 | +** while accessing the memory-mapped -shm file will cause a process-wide | |
| 64586 | +** signal to be deliver, which will more than likely cause the entire | |
| 64587 | +** process to exit. | |
| 64588 | +*/ | |
| 64589 | +#ifdef SQLITE_USE_SEH | |
| 64590 | +#include <Windows.h> | |
| 64591 | + | |
| 64592 | +/* Beginning of a block of code in which an exception might occur */ | |
| 64593 | +# define SEH_TRY __try { \ | |
| 64594 | + assert( walAssertLockmask(pWal) && pWal->nSehTry==0 ); \ | |
| 64595 | + VVA_ONLY(pWal->nSehTry++); | |
| 64596 | + | |
| 64597 | +/* The end of a block of code in which an exception might occur */ | |
| 64598 | +# define SEH_EXCEPT(X) \ | |
| 64599 | + VVA_ONLY(pWal->nSehTry--); \ | |
| 64600 | + assert( pWal->nSehTry==0 ); \ | |
| 64601 | + } __except( sehExceptionFilter(pWal, GetExceptionCode(), GetExceptionInformation() ) ){ X } | |
| 64602 | + | |
| 64603 | +/* Simulate a memory-mapping fault in the -shm file for testing purposes */ | |
| 64604 | +# define SEH_INJECT_FAULT sehInjectFault(pWal) | |
| 64605 | + | |
| 64606 | +/* | |
| 64607 | +** The second argument is the return value of GetExceptionCode() for the | |
| 64608 | +** current exception. Return EXCEPTION_EXECUTE_HANDLER if the exception code | |
| 64609 | +** indicates that the exception may have been caused by accessing the *-shm | |
| 64610 | +** file mapping. Or EXCEPTION_CONTINUE_SEARCH otherwise. | |
| 64611 | +*/ | |
| 64612 | +static int sehExceptionFilter(Wal *pWal, int eCode, EXCEPTION_POINTERS *p){ | |
| 64613 | + VVA_ONLY(pWal->nSehTry--); | |
| 64614 | + if( eCode==EXCEPTION_IN_PAGE_ERROR ){ | |
| 64615 | + if( p && p->ExceptionRecord && p->ExceptionRecord->NumberParameters>=3 ){ | |
| 64616 | + /* From MSDN: For this type of exception, the first element of the | |
| 64617 | + ** ExceptionInformation[] array is a read-write flag - 0 if the exception | |
| 64618 | + ** was thrown while reading, 1 if while writing. The second element is | |
| 64619 | + ** the virtual address being accessed. The "third array element specifies | |
| 64620 | + ** the underlying NTSTATUS code that resulted in the exception". */ | |
| 64621 | + pWal->iSysErrno = (int)p->ExceptionRecord->ExceptionInformation[2]; | |
| 64622 | + } | |
| 64623 | + return EXCEPTION_EXECUTE_HANDLER; | |
| 64624 | + } | |
| 64625 | + return EXCEPTION_CONTINUE_SEARCH; | |
| 64626 | +} | |
| 64627 | + | |
| 64628 | +/* | |
| 64629 | +** If one is configured, invoke the xTestCallback callback with 650 as | |
| 64630 | +** the argument. If it returns true, throw the same exception that is | |
| 64631 | +** thrown by the system if the *-shm file mapping is accessed after it | |
| 64632 | +** has been invalidated. | |
| 64633 | +*/ | |
| 64634 | +static void sehInjectFault(Wal *pWal){ | |
| 64635 | + int res; | |
| 64636 | + assert( pWal->nSehTry>0 ); | |
| 64637 | + | |
| 64638 | + res = sqlite3FaultSim(650); | |
| 64639 | + if( res!=0 ){ | |
| 64640 | + ULONG_PTR aArg[3]; | |
| 64641 | + aArg[0] = 0; | |
| 64642 | + aArg[1] = 0; | |
| 64643 | + aArg[2] = (ULONG_PTR)res; | |
| 64644 | + RaiseException(EXCEPTION_IN_PAGE_ERROR, 0, 3, (const ULONG_PTR*)aArg); | |
| 64645 | + } | |
| 64646 | +} | |
| 64647 | + | |
| 64648 | +/* | |
| 64649 | +** There are two ways to use this macro. To set a pointer to be freed | |
| 64650 | +** if an exception is thrown: | |
| 64651 | +** | |
| 64652 | +** SEH_FREE_ON_ERROR(0, pPtr); | |
| 64653 | +** | |
| 64654 | +** and to cancel the same: | |
| 64655 | +** | |
| 64656 | +** SEH_FREE_ON_ERROR(pPtr, 0); | |
| 64657 | +** | |
| 64658 | +** In the first case, there must not already be a pointer registered to | |
| 64659 | +** be freed. In the second case, pPtr must be the registered pointer. | |
| 64660 | +*/ | |
| 64661 | +#define SEH_FREE_ON_ERROR(X,Y) \ | |
| 64662 | + assert( (X==0 || Y==0) && pWal->pFree==X ); pWal->pFree = Y | |
| 64663 | + | |
| 64664 | +#else | |
| 64665 | +# define SEH_TRY VVA_ONLY(pWal->nSehTry++); | |
| 64666 | +# define SEH_EXCEPT(X) VVA_ONLY(pWal->nSehTry--); assert( pWal->nSehTry==0 ); | |
| 64667 | +# define SEH_INJECT_FAULT assert( pWal->nSehTry>0 ); | |
| 64668 | +# define SEH_FREE_ON_ERROR(X,Y) | |
| 64669 | +#endif /* ifdef SQLITE_USE_SEH */ | |
| 64670 | + | |
| 64540 | 64671 | |
| 64541 | 64672 | /* |
| 64542 | 64673 | ** Obtain a pointer to the iPage'th page of the wal-index. The wal-index |
| 64543 | 64674 | ** is broken into pages of WALINDEX_PGSZ bytes. Wal-index pages are |
| 64544 | 64675 | ** numbered from zero. |
| @@ -64608,10 +64739,11 @@ | ||
| 64608 | 64739 | static int walIndexPage( |
| 64609 | 64740 | Wal *pWal, /* The WAL context */ |
| 64610 | 64741 | int iPage, /* The page we seek */ |
| 64611 | 64742 | volatile u32 **ppPage /* Write the page pointer here */ |
| 64612 | 64743 | ){ |
| 64744 | + SEH_INJECT_FAULT; | |
| 64613 | 64745 | if( pWal->nWiData<=iPage || (*ppPage = pWal->apWiData[iPage])==0 ){ |
| 64614 | 64746 | return walIndexPageRealloc(pWal, iPage, ppPage); |
| 64615 | 64747 | } |
| 64616 | 64748 | return SQLITE_OK; |
| 64617 | 64749 | } |
| @@ -64619,18 +64751,20 @@ | ||
| 64619 | 64751 | /* |
| 64620 | 64752 | ** Return a pointer to the WalCkptInfo structure in the wal-index. |
| 64621 | 64753 | */ |
| 64622 | 64754 | static volatile WalCkptInfo *walCkptInfo(Wal *pWal){ |
| 64623 | 64755 | assert( pWal->nWiData>0 && pWal->apWiData[0] ); |
| 64756 | + SEH_INJECT_FAULT; | |
| 64624 | 64757 | return (volatile WalCkptInfo*)&(pWal->apWiData[0][sizeof(WalIndexHdr)/2]); |
| 64625 | 64758 | } |
| 64626 | 64759 | |
| 64627 | 64760 | /* |
| 64628 | 64761 | ** Return a pointer to the WalIndexHdr structure in the wal-index. |
| 64629 | 64762 | */ |
| 64630 | 64763 | static volatile WalIndexHdr *walIndexHdr(Wal *pWal){ |
| 64631 | 64764 | assert( pWal->nWiData>0 && pWal->apWiData[0] ); |
| 64765 | + SEH_INJECT_FAULT; | |
| 64632 | 64766 | return (volatile WalIndexHdr*)pWal->apWiData[0]; |
| 64633 | 64767 | } |
| 64634 | 64768 | |
| 64635 | 64769 | /* |
| 64636 | 64770 | ** The argument to this macro must be of type u32. On a little-endian |
| @@ -64884,16 +65018,22 @@ | ||
| 64884 | 65018 | rc = sqlite3OsShmLock(pWal->pDbFd, lockIdx, 1, |
| 64885 | 65019 | SQLITE_SHM_LOCK | SQLITE_SHM_SHARED); |
| 64886 | 65020 | WALTRACE(("WAL%p: acquire SHARED-%s %s\n", pWal, |
| 64887 | 65021 | walLockName(lockIdx), rc ? "failed" : "ok")); |
| 64888 | 65022 | VVA_ONLY( pWal->lockError = (u8)(rc!=SQLITE_OK && (rc&0xFF)!=SQLITE_BUSY); ) |
| 65023 | +#ifdef SQLITE_USE_SEH | |
| 65024 | + if( rc==SQLITE_OK ) pWal->lockMask |= (1 << lockIdx); | |
| 65025 | +#endif | |
| 64889 | 65026 | return rc; |
| 64890 | 65027 | } |
| 64891 | 65028 | static void walUnlockShared(Wal *pWal, int lockIdx){ |
| 64892 | 65029 | if( pWal->exclusiveMode ) return; |
| 64893 | 65030 | (void)sqlite3OsShmLock(pWal->pDbFd, lockIdx, 1, |
| 64894 | 65031 | SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED); |
| 65032 | +#ifdef SQLITE_USE_SEH | |
| 65033 | + pWal->lockMask &= ~(1 << lockIdx); | |
| 65034 | +#endif | |
| 64895 | 65035 | WALTRACE(("WAL%p: release SHARED-%s\n", pWal, walLockName(lockIdx))); |
| 64896 | 65036 | } |
| 64897 | 65037 | static int walLockExclusive(Wal *pWal, int lockIdx, int n){ |
| 64898 | 65038 | int rc; |
| 64899 | 65039 | if( pWal->exclusiveMode ) return SQLITE_OK; |
| @@ -64900,16 +65040,24 @@ | ||
| 64900 | 65040 | rc = sqlite3OsShmLock(pWal->pDbFd, lockIdx, n, |
| 64901 | 65041 | SQLITE_SHM_LOCK | SQLITE_SHM_EXCLUSIVE); |
| 64902 | 65042 | WALTRACE(("WAL%p: acquire EXCLUSIVE-%s cnt=%d %s\n", pWal, |
| 64903 | 65043 | walLockName(lockIdx), n, rc ? "failed" : "ok")); |
| 64904 | 65044 | VVA_ONLY( pWal->lockError = (u8)(rc!=SQLITE_OK && (rc&0xFF)!=SQLITE_BUSY); ) |
| 65045 | +#ifdef SQLITE_USE_SEH | |
| 65046 | + if( rc==SQLITE_OK ){ | |
| 65047 | + pWal->lockMask |= (((1<<n)-1) << (SQLITE_SHM_NLOCK+lockIdx)); | |
| 65048 | + } | |
| 65049 | +#endif | |
| 64905 | 65050 | return rc; |
| 64906 | 65051 | } |
| 64907 | 65052 | static void walUnlockExclusive(Wal *pWal, int lockIdx, int n){ |
| 64908 | 65053 | if( pWal->exclusiveMode ) return; |
| 64909 | 65054 | (void)sqlite3OsShmLock(pWal->pDbFd, lockIdx, n, |
| 64910 | 65055 | SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE); |
| 65056 | +#ifdef SQLITE_USE_SEH | |
| 65057 | + pWal->lockMask &= ~(((1<<n)-1) << (SQLITE_SHM_NLOCK+lockIdx)); | |
| 65058 | +#endif | |
| 64911 | 65059 | WALTRACE(("WAL%p: release EXCLUSIVE-%s cnt=%d\n", pWal, |
| 64912 | 65060 | walLockName(lockIdx), n)); |
| 64913 | 65061 | } |
| 64914 | 65062 | |
| 64915 | 65063 | /* |
| @@ -64997,10 +65145,11 @@ | ||
| 64997 | 65145 | /* |
| 64998 | 65146 | ** Return the page number associated with frame iFrame in this WAL. |
| 64999 | 65147 | */ |
| 65000 | 65148 | static u32 walFramePgno(Wal *pWal, u32 iFrame){ |
| 65001 | 65149 | int iHash = walFramePage(iFrame); |
| 65150 | + SEH_INJECT_FAULT; | |
| 65002 | 65151 | if( iHash==0 ){ |
| 65003 | 65152 | return pWal->apWiData[0][WALINDEX_HDR_SIZE/sizeof(u32) + iFrame - 1]; |
| 65004 | 65153 | } |
| 65005 | 65154 | return pWal->apWiData[iHash][(iFrame-1-HASHTABLE_NPAGE_ONE)%HASHTABLE_NPAGE]; |
| 65006 | 65155 | } |
| @@ -65256,10 +65405,11 @@ | ||
| 65256 | 65405 | } |
| 65257 | 65406 | |
| 65258 | 65407 | /* Malloc a buffer to read frames into. */ |
| 65259 | 65408 | szFrame = szPage + WAL_FRAME_HDRSIZE; |
| 65260 | 65409 | aFrame = (u8 *)sqlite3_malloc64(szFrame + WALINDEX_PGSZ); |
| 65410 | + SEH_FREE_ON_ERROR(0, aFrame); | |
| 65261 | 65411 | if( !aFrame ){ |
| 65262 | 65412 | rc = SQLITE_NOMEM_BKPT; |
| 65263 | 65413 | goto recovery_error; |
| 65264 | 65414 | } |
| 65265 | 65415 | aData = &aFrame[WAL_FRAME_HDRSIZE]; |
| @@ -65331,13 +65481,15 @@ | ||
| 65331 | 65481 | aShare[i] = aPrivate[i]; |
| 65332 | 65482 | } |
| 65333 | 65483 | } |
| 65334 | 65484 | } |
| 65335 | 65485 | #endif |
| 65486 | + SEH_INJECT_FAULT; | |
| 65336 | 65487 | if( iFrame<=iLast ) break; |
| 65337 | 65488 | } |
| 65338 | 65489 | |
| 65490 | + SEH_FREE_ON_ERROR(aFrame, 0); | |
| 65339 | 65491 | sqlite3_free(aFrame); |
| 65340 | 65492 | } |
| 65341 | 65493 | |
| 65342 | 65494 | finished: |
| 65343 | 65495 | if( rc==SQLITE_OK ){ |
| @@ -65361,10 +65513,11 @@ | ||
| 65361 | 65513 | if( i==1 && pWal->hdr.mxFrame ){ |
| 65362 | 65514 | pInfo->aReadMark[i] = pWal->hdr.mxFrame; |
| 65363 | 65515 | }else{ |
| 65364 | 65516 | pInfo->aReadMark[i] = READMARK_NOT_USED; |
| 65365 | 65517 | } |
| 65518 | + SEH_INJECT_FAULT; | |
| 65366 | 65519 | walUnlockExclusive(pWal, WAL_READ_LOCK(i), 1); |
| 65367 | 65520 | }else if( rc!=SQLITE_BUSY ){ |
| 65368 | 65521 | goto recovery_error; |
| 65369 | 65522 | } |
| 65370 | 65523 | } |
| @@ -65753,10 +65906,11 @@ | ||
| 65753 | 65906 | return SQLITE_NOMEM_BKPT; |
| 65754 | 65907 | } |
| 65755 | 65908 | memset(p, 0, nByte); |
| 65756 | 65909 | p->nSegment = nSegment; |
| 65757 | 65910 | aTmp = (ht_slot*)&(((u8*)p)[nByte]); |
| 65911 | + SEH_FREE_ON_ERROR(0, p); | |
| 65758 | 65912 | for(i=walFramePage(nBackfill+1); rc==SQLITE_OK && i<nSegment; i++){ |
| 65759 | 65913 | WalHashLoc sLoc; |
| 65760 | 65914 | |
| 65761 | 65915 | rc = walHashGet(pWal, i, &sLoc); |
| 65762 | 65916 | if( rc==SQLITE_OK ){ |
| @@ -65781,10 +65935,11 @@ | ||
| 65781 | 65935 | p->aSegment[i].aIndex = aIndex; |
| 65782 | 65936 | p->aSegment[i].aPgno = (u32 *)sLoc.aPgno; |
| 65783 | 65937 | } |
| 65784 | 65938 | } |
| 65785 | 65939 | if( rc!=SQLITE_OK ){ |
| 65940 | + SEH_FREE_ON_ERROR(p, 0); | |
| 65786 | 65941 | walIteratorFree(p); |
| 65787 | 65942 | p = 0; |
| 65788 | 65943 | } |
| 65789 | 65944 | *pp = p; |
| 65790 | 65945 | return rc; |
| @@ -66006,17 +66161,17 @@ | ||
| 66006 | 66161 | ** cannot be backfilled from the WAL. |
| 66007 | 66162 | */ |
| 66008 | 66163 | mxSafeFrame = pWal->hdr.mxFrame; |
| 66009 | 66164 | mxPage = pWal->hdr.nPage; |
| 66010 | 66165 | for(i=1; i<WAL_NREADER; i++){ |
| 66011 | - u32 y = AtomicLoad(pInfo->aReadMark+i); | |
| 66166 | + u32 y = AtomicLoad(pInfo->aReadMark+i); SEH_INJECT_FAULT; | |
| 66012 | 66167 | if( mxSafeFrame>y ){ |
| 66013 | 66168 | assert( y<=pWal->hdr.mxFrame ); |
| 66014 | 66169 | rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_READ_LOCK(i), 1); |
| 66015 | 66170 | if( rc==SQLITE_OK ){ |
| 66016 | 66171 | u32 iMark = (i==1 ? mxSafeFrame : READMARK_NOT_USED); |
| 66017 | - AtomicStore(pInfo->aReadMark+i, iMark); | |
| 66172 | + AtomicStore(pInfo->aReadMark+i, iMark); SEH_INJECT_FAULT; | |
| 66018 | 66173 | walUnlockExclusive(pWal, WAL_READ_LOCK(i), 1); |
| 66019 | 66174 | }else if( rc==SQLITE_BUSY ){ |
| 66020 | 66175 | mxSafeFrame = y; |
| 66021 | 66176 | xBusy = 0; |
| 66022 | 66177 | }else{ |
| @@ -66033,12 +66188,11 @@ | ||
| 66033 | 66188 | |
| 66034 | 66189 | if( pIter |
| 66035 | 66190 | && (rc = walBusyLock(pWal,xBusy,pBusyArg,WAL_READ_LOCK(0),1))==SQLITE_OK |
| 66036 | 66191 | ){ |
| 66037 | 66192 | u32 nBackfill = pInfo->nBackfill; |
| 66038 | - | |
| 66039 | - pInfo->nBackfillAttempted = mxSafeFrame; | |
| 66193 | + pInfo->nBackfillAttempted = mxSafeFrame; SEH_INJECT_FAULT; | |
| 66040 | 66194 | |
| 66041 | 66195 | /* Sync the WAL to disk */ |
| 66042 | 66196 | rc = sqlite3OsSync(pWal->pWalFd, CKPT_SYNC_FLAGS(sync_flags)); |
| 66043 | 66197 | |
| 66044 | 66198 | /* If the database may grow as a result of this checkpoint, hint |
| @@ -66065,10 +66219,11 @@ | ||
| 66065 | 66219 | |
| 66066 | 66220 | /* Iterate through the contents of the WAL, copying data to the db file */ |
| 66067 | 66221 | while( rc==SQLITE_OK && 0==walIteratorNext(pIter, &iDbpage, &iFrame) ){ |
| 66068 | 66222 | i64 iOffset; |
| 66069 | 66223 | assert( walFramePgno(pWal, iFrame)==iDbpage ); |
| 66224 | + SEH_INJECT_FAULT; | |
| 66070 | 66225 | if( AtomicLoad(&db->u1.isInterrupted) ){ |
| 66071 | 66226 | rc = db->mallocFailed ? SQLITE_NOMEM_BKPT : SQLITE_INTERRUPT; |
| 66072 | 66227 | break; |
| 66073 | 66228 | } |
| 66074 | 66229 | if( iFrame<=nBackfill || iFrame>mxSafeFrame || iDbpage>mxPage ){ |
| @@ -66094,11 +66249,11 @@ | ||
| 66094 | 66249 | if( rc==SQLITE_OK ){ |
| 66095 | 66250 | rc = sqlite3OsSync(pWal->pDbFd, CKPT_SYNC_FLAGS(sync_flags)); |
| 66096 | 66251 | } |
| 66097 | 66252 | } |
| 66098 | 66253 | if( rc==SQLITE_OK ){ |
| 66099 | - AtomicStore(&pInfo->nBackfill, mxSafeFrame); | |
| 66254 | + AtomicStore(&pInfo->nBackfill, mxSafeFrame); SEH_INJECT_FAULT; | |
| 66100 | 66255 | } |
| 66101 | 66256 | } |
| 66102 | 66257 | |
| 66103 | 66258 | /* Release the reader lock held while backfilling */ |
| 66104 | 66259 | walUnlockExclusive(pWal, WAL_READ_LOCK(0), 1); |
| @@ -66116,10 +66271,11 @@ | ||
| 66116 | 66271 | ** until all readers have finished using the wal file. This ensures that |
| 66117 | 66272 | ** the next process to write to the database restarts the wal file. |
| 66118 | 66273 | */ |
| 66119 | 66274 | if( rc==SQLITE_OK && eMode!=SQLITE_CHECKPOINT_PASSIVE ){ |
| 66120 | 66275 | assert( pWal->writeLock ); |
| 66276 | + SEH_INJECT_FAULT; | |
| 66121 | 66277 | if( pInfo->nBackfill<pWal->hdr.mxFrame ){ |
| 66122 | 66278 | rc = SQLITE_BUSY; |
| 66123 | 66279 | }else if( eMode>=SQLITE_CHECKPOINT_RESTART ){ |
| 66124 | 66280 | u32 salt1; |
| 66125 | 66281 | sqlite3_randomness(4, &salt1); |
| @@ -66147,10 +66303,11 @@ | ||
| 66147 | 66303 | } |
| 66148 | 66304 | } |
| 66149 | 66305 | } |
| 66150 | 66306 | |
| 66151 | 66307 | walcheckpoint_out: |
| 66308 | + SEH_FREE_ON_ERROR(pIter, 0); | |
| 66152 | 66309 | walIteratorFree(pIter); |
| 66153 | 66310 | return rc; |
| 66154 | 66311 | } |
| 66155 | 66312 | |
| 66156 | 66313 | /* |
| @@ -66169,10 +66326,91 @@ | ||
| 66169 | 66326 | if( rx ){ |
| 66170 | 66327 | sqlite3_log(rx, "cannot limit WAL size: %s", pWal->zWalName); |
| 66171 | 66328 | } |
| 66172 | 66329 | } |
| 66173 | 66330 | |
| 66331 | +#ifdef SQLITE_USE_SEH | |
| 66332 | +/* | |
| 66333 | +** This is the "standard" exception handler used in a few places to handle | |
| 66334 | +** an exception thrown by reading from the *-shm mapping after it has become | |
| 66335 | +** invalid in SQLITE_USE_SEH builds. It is used as follows: | |
| 66336 | +** | |
| 66337 | +** SEH_TRY { ... } | |
| 66338 | +** SEH_EXCEPT( rc = walHandleException(pWal); ) | |
| 66339 | +** | |
| 66340 | +** This function does three things: | |
| 66341 | +** | |
| 66342 | +** 1) Determines the locks that should be held, based on the contents of | |
| 66343 | +** the Wal.readLock, Wal.writeLock and Wal.ckptLock variables. All other | |
| 66344 | +** held locks are assumed to be transient locks that would have been | |
| 66345 | +** released had the exception not been thrown and are dropped. | |
| 66346 | +** | |
| 66347 | +** 2) Frees the pointer at Wal.pFree, if any, using sqlite3_free(). | |
| 66348 | +** | |
| 66349 | +** 3) Returns SQLITE_IOERR. | |
| 66350 | +*/ | |
| 66351 | +static int walHandleException(Wal *pWal){ | |
| 66352 | + if( pWal->exclusiveMode==0 ){ | |
| 66353 | + static const int S = 1; | |
| 66354 | + static const int E = (1<<SQLITE_SHM_NLOCK); | |
| 66355 | + int ii; | |
| 66356 | + u32 mUnlock = pWal->lockMask & ~( | |
| 66357 | + (pWal->readLock<0 ? 0 : (S << WAL_READ_LOCK(pWal->readLock))) | |
| 66358 | + | (pWal->writeLock ? (E << WAL_WRITE_LOCK) : 0) | |
| 66359 | + | (pWal->ckptLock ? (E << WAL_CKPT_LOCK) : 0) | |
| 66360 | + ); | |
| 66361 | + for(ii=0; ii<SQLITE_SHM_NLOCK; ii++){ | |
| 66362 | + if( (S<<ii) & mUnlock ) walUnlockShared(pWal, ii); | |
| 66363 | + if( (E<<ii) & mUnlock ) walUnlockExclusive(pWal, ii, 1); | |
| 66364 | + } | |
| 66365 | + } | |
| 66366 | + sqlite3_free(pWal->pFree); | |
| 66367 | + pWal->pFree = 0; | |
| 66368 | + return SQLITE_IOERR_IN_PAGE; | |
| 66369 | +} | |
| 66370 | + | |
| 66371 | +/* | |
| 66372 | +** Assert that the Wal.lockMask mask, which indicates the locks held | |
| 66373 | +** by the connenction, is consistent with the Wal.readLock, Wal.writeLock | |
| 66374 | +** and Wal.ckptLock variables. To be used as: | |
| 66375 | +** | |
| 66376 | +** assert( walAssertLockmask(pWal) ); | |
| 66377 | +*/ | |
| 66378 | +static int walAssertLockmask(Wal *pWal){ | |
| 66379 | + if( pWal->exclusiveMode==0 ){ | |
| 66380 | + static const int S = 1; | |
| 66381 | + static const int E = (1<<SQLITE_SHM_NLOCK); | |
| 66382 | + u32 mExpect = ( | |
| 66383 | + (pWal->readLock<0 ? 0 : (S << WAL_READ_LOCK(pWal->readLock))) | |
| 66384 | + | (pWal->writeLock ? (E << WAL_WRITE_LOCK) : 0) | |
| 66385 | + | (pWal->ckptLock ? (E << WAL_CKPT_LOCK) : 0) | |
| 66386 | +#ifdef SQLITE_ENABLE_SNAPSHOT | |
| 66387 | + | (pWal->pSnapshot ? (pWal->lockMask & (1 << WAL_CKPT_LOCK)) : 0) | |
| 66388 | +#endif | |
| 66389 | + ); | |
| 66390 | + assert( mExpect==pWal->lockMask ); | |
| 66391 | + } | |
| 66392 | + return 1; | |
| 66393 | +} | |
| 66394 | + | |
| 66395 | +/* | |
| 66396 | +** Return and zero the "system error" field set when an | |
| 66397 | +** EXCEPTION_IN_PAGE_ERROR exception is caught. | |
| 66398 | +*/ | |
| 66399 | +SQLITE_PRIVATE int sqlite3WalSystemErrno(Wal *pWal){ | |
| 66400 | + int iRet = 0; | |
| 66401 | + if( pWal ){ | |
| 66402 | + iRet = pWal->iSysErrno; | |
| 66403 | + pWal->iSysErrno = 0; | |
| 66404 | + } | |
| 66405 | + return iRet; | |
| 66406 | +} | |
| 66407 | + | |
| 66408 | +#else | |
| 66409 | +# define walAssertLockmask(x) 1 | |
| 66410 | +#endif /* ifdef SQLITE_USE_SEH */ | |
| 66411 | + | |
| 66174 | 66412 | /* |
| 66175 | 66413 | ** Close a connection to a log file. |
| 66176 | 66414 | */ |
| 66177 | 66415 | SQLITE_PRIVATE int sqlite3WalClose( |
| 66178 | 66416 | Wal *pWal, /* Wal to close */ |
| @@ -66182,10 +66420,12 @@ | ||
| 66182 | 66420 | u8 *zBuf /* Buffer of at least nBuf bytes */ |
| 66183 | 66421 | ){ |
| 66184 | 66422 | int rc = SQLITE_OK; |
| 66185 | 66423 | if( pWal ){ |
| 66186 | 66424 | int isDelete = 0; /* True to unlink wal and wal-index files */ |
| 66425 | + | |
| 66426 | + assert( walAssertLockmask(pWal) ); | |
| 66187 | 66427 | |
| 66188 | 66428 | /* If an EXCLUSIVE lock can be obtained on the database file (using the |
| 66189 | 66429 | ** ordinary, rollback-mode locking methods, this guarantees that the |
| 66190 | 66430 | ** connection associated with this log file is the only connection to |
| 66191 | 66431 | ** the database. In this case checkpoint the database and unlink both |
| @@ -66725,10 +66965,11 @@ | ||
| 66725 | 66965 | } |
| 66726 | 66966 | |
| 66727 | 66967 | assert( pWal->nWiData>0 ); |
| 66728 | 66968 | assert( pWal->apWiData[0]!=0 ); |
| 66729 | 66969 | pInfo = walCkptInfo(pWal); |
| 66970 | + SEH_INJECT_FAULT; | |
| 66730 | 66971 | if( !useWal && AtomicLoad(&pInfo->nBackfill)==pWal->hdr.mxFrame |
| 66731 | 66972 | #ifdef SQLITE_ENABLE_SNAPSHOT |
| 66732 | 66973 | && (pWal->pSnapshot==0 || pWal->hdr.mxFrame==0) |
| 66733 | 66974 | #endif |
| 66734 | 66975 | ){ |
| @@ -66774,11 +67015,11 @@ | ||
| 66774 | 67015 | if( pWal->pSnapshot && pWal->pSnapshot->mxFrame<mxFrame ){ |
| 66775 | 67016 | mxFrame = pWal->pSnapshot->mxFrame; |
| 66776 | 67017 | } |
| 66777 | 67018 | #endif |
| 66778 | 67019 | for(i=1; i<WAL_NREADER; i++){ |
| 66779 | - u32 thisMark = AtomicLoad(pInfo->aReadMark+i); | |
| 67020 | + u32 thisMark = AtomicLoad(pInfo->aReadMark+i); SEH_INJECT_FAULT; | |
| 66780 | 67021 | if( mxReadMark<=thisMark && thisMark<=mxFrame ){ |
| 66781 | 67022 | assert( thisMark!=READMARK_NOT_USED ); |
| 66782 | 67023 | mxReadMark = thisMark; |
| 66783 | 67024 | mxI = i; |
| 66784 | 67025 | } |
| @@ -66840,11 +67081,11 @@ | ||
| 66840 | 67081 | ** frame pWal->hdr.mxFrame - then the client would incorrectly assume |
| 66841 | 67082 | ** that it can read version A from the database file. However, since |
| 66842 | 67083 | ** we can guarantee that the checkpointer that set nBackfill could not |
| 66843 | 67084 | ** see any pages past pWal->hdr.mxFrame, this problem does not come up. |
| 66844 | 67085 | */ |
| 66845 | - pWal->minFrame = AtomicLoad(&pInfo->nBackfill)+1; | |
| 67086 | + pWal->minFrame = AtomicLoad(&pInfo->nBackfill)+1; SEH_INJECT_FAULT; | |
| 66846 | 67087 | walShmBarrier(pWal); |
| 66847 | 67088 | if( AtomicLoad(pInfo->aReadMark+mxI)!=mxReadMark |
| 66848 | 67089 | || memcmp((void *)walIndexHdr(pWal), &pWal->hdr, sizeof(WalIndexHdr)) |
| 66849 | 67090 | ){ |
| 66850 | 67091 | walUnlockShared(pWal, WAL_READ_LOCK(mxI)); |
| @@ -66855,10 +67096,57 @@ | ||
| 66855 | 67096 | } |
| 66856 | 67097 | return rc; |
| 66857 | 67098 | } |
| 66858 | 67099 | |
| 66859 | 67100 | #ifdef SQLITE_ENABLE_SNAPSHOT |
| 67101 | +/* | |
| 67102 | +** This function does the work of sqlite3WalSnapshotRecover(). | |
| 67103 | +*/ | |
| 67104 | +static int walSnapshotRecover( | |
| 67105 | + Wal *pWal, /* WAL handle */ | |
| 67106 | + void *pBuf1, /* Temp buffer pWal->szPage bytes in size */ | |
| 67107 | + void *pBuf2 /* Temp buffer pWal->szPage bytes in size */ | |
| 67108 | +){ | |
| 67109 | + int szPage = (int)pWal->szPage; | |
| 67110 | + int rc; | |
| 67111 | + i64 szDb; /* Size of db file in bytes */ | |
| 67112 | + | |
| 67113 | + rc = sqlite3OsFileSize(pWal->pDbFd, &szDb); | |
| 67114 | + if( rc==SQLITE_OK ){ | |
| 67115 | + volatile WalCkptInfo *pInfo = walCkptInfo(pWal); | |
| 67116 | + u32 i = pInfo->nBackfillAttempted; | |
| 67117 | + for(i=pInfo->nBackfillAttempted; i>AtomicLoad(&pInfo->nBackfill); i--){ | |
| 67118 | + WalHashLoc sLoc; /* Hash table location */ | |
| 67119 | + u32 pgno; /* Page number in db file */ | |
| 67120 | + i64 iDbOff; /* Offset of db file entry */ | |
| 67121 | + i64 iWalOff; /* Offset of wal file entry */ | |
| 67122 | + | |
| 67123 | + rc = walHashGet(pWal, walFramePage(i), &sLoc); | |
| 67124 | + if( rc!=SQLITE_OK ) break; | |
| 67125 | + pgno = sLoc.aPgno[i-sLoc.iZero]; | |
| 67126 | + iDbOff = (i64)(pgno-1) * szPage; | |
| 67127 | + | |
| 67128 | + if( iDbOff+szPage<=szDb ){ | |
| 67129 | + iWalOff = walFrameOffset(i, szPage) + WAL_FRAME_HDRSIZE; | |
| 67130 | + rc = sqlite3OsRead(pWal->pWalFd, pBuf1, szPage, iWalOff); | |
| 67131 | + | |
| 67132 | + if( rc==SQLITE_OK ){ | |
| 67133 | + rc = sqlite3OsRead(pWal->pDbFd, pBuf2, szPage, iDbOff); | |
| 67134 | + } | |
| 67135 | + | |
| 67136 | + if( rc!=SQLITE_OK || 0==memcmp(pBuf1, pBuf2, szPage) ){ | |
| 67137 | + break; | |
| 67138 | + } | |
| 67139 | + } | |
| 67140 | + | |
| 67141 | + pInfo->nBackfillAttempted = i-1; | |
| 67142 | + } | |
| 67143 | + } | |
| 67144 | + | |
| 67145 | + return rc; | |
| 67146 | +} | |
| 67147 | + | |
| 66860 | 67148 | /* |
| 66861 | 67149 | ** Attempt to reduce the value of the WalCkptInfo.nBackfillAttempted |
| 66862 | 67150 | ** variable so that older snapshots can be accessed. To do this, loop |
| 66863 | 67151 | ** through all wal frames from nBackfillAttempted to (nBackfill+1), |
| 66864 | 67152 | ** comparing their content to the corresponding page with the database |
| @@ -66880,84 +67168,47 @@ | ||
| 66880 | 67168 | int rc; |
| 66881 | 67169 | |
| 66882 | 67170 | assert( pWal->readLock>=0 ); |
| 66883 | 67171 | rc = walLockExclusive(pWal, WAL_CKPT_LOCK, 1); |
| 66884 | 67172 | if( rc==SQLITE_OK ){ |
| 66885 | - volatile WalCkptInfo *pInfo = walCkptInfo(pWal); | |
| 66886 | - int szPage = (int)pWal->szPage; | |
| 66887 | - i64 szDb; /* Size of db file in bytes */ | |
| 66888 | - | |
| 66889 | - rc = sqlite3OsFileSize(pWal->pDbFd, &szDb); | |
| 66890 | - if( rc==SQLITE_OK ){ | |
| 66891 | - void *pBuf1 = sqlite3_malloc(szPage); | |
| 66892 | - void *pBuf2 = sqlite3_malloc(szPage); | |
| 66893 | - if( pBuf1==0 || pBuf2==0 ){ | |
| 66894 | - rc = SQLITE_NOMEM; | |
| 66895 | - }else{ | |
| 66896 | - u32 i = pInfo->nBackfillAttempted; | |
| 66897 | - for(i=pInfo->nBackfillAttempted; i>AtomicLoad(&pInfo->nBackfill); i--){ | |
| 66898 | - WalHashLoc sLoc; /* Hash table location */ | |
| 66899 | - u32 pgno; /* Page number in db file */ | |
| 66900 | - i64 iDbOff; /* Offset of db file entry */ | |
| 66901 | - i64 iWalOff; /* Offset of wal file entry */ | |
| 66902 | - | |
| 66903 | - rc = walHashGet(pWal, walFramePage(i), &sLoc); | |
| 66904 | - if( rc!=SQLITE_OK ) break; | |
| 66905 | - assert( i - sLoc.iZero - 1 >=0 ); | |
| 66906 | - pgno = sLoc.aPgno[i-sLoc.iZero-1]; | |
| 66907 | - iDbOff = (i64)(pgno-1) * szPage; | |
| 66908 | - | |
| 66909 | - if( iDbOff+szPage<=szDb ){ | |
| 66910 | - iWalOff = walFrameOffset(i, szPage) + WAL_FRAME_HDRSIZE; | |
| 66911 | - rc = sqlite3OsRead(pWal->pWalFd, pBuf1, szPage, iWalOff); | |
| 66912 | - | |
| 66913 | - if( rc==SQLITE_OK ){ | |
| 66914 | - rc = sqlite3OsRead(pWal->pDbFd, pBuf2, szPage, iDbOff); | |
| 66915 | - } | |
| 66916 | - | |
| 66917 | - if( rc!=SQLITE_OK || 0==memcmp(pBuf1, pBuf2, szPage) ){ | |
| 66918 | - break; | |
| 66919 | - } | |
| 66920 | - } | |
| 66921 | - | |
| 66922 | - pInfo->nBackfillAttempted = i-1; | |
| 66923 | - } | |
| 66924 | - } | |
| 66925 | - | |
| 66926 | - sqlite3_free(pBuf1); | |
| 66927 | - sqlite3_free(pBuf2); | |
| 66928 | - } | |
| 67173 | + void *pBuf1 = sqlite3_malloc(pWal->szPage); | |
| 67174 | + void *pBuf2 = sqlite3_malloc(pWal->szPage); | |
| 67175 | + if( pBuf1==0 || pBuf2==0 ){ | |
| 67176 | + rc = SQLITE_NOMEM; | |
| 67177 | + }else{ | |
| 67178 | + pWal->ckptLock = 1; | |
| 67179 | + SEH_TRY { | |
| 67180 | + rc = walSnapshotRecover(pWal, pBuf1, pBuf2); | |
| 67181 | + } | |
| 67182 | + SEH_EXCEPT( rc = SQLITE_IOERR_IN_PAGE; ) | |
| 67183 | + pWal->ckptLock = 0; | |
| 67184 | + } | |
| 67185 | + | |
| 67186 | + sqlite3_free(pBuf1); | |
| 67187 | + sqlite3_free(pBuf2); | |
| 66929 | 67188 | walUnlockExclusive(pWal, WAL_CKPT_LOCK, 1); |
| 66930 | 67189 | } |
| 66931 | 67190 | |
| 66932 | 67191 | return rc; |
| 66933 | 67192 | } |
| 66934 | 67193 | #endif /* SQLITE_ENABLE_SNAPSHOT */ |
| 66935 | 67194 | |
| 66936 | 67195 | /* |
| 66937 | -** Begin a read transaction on the database. | |
| 66938 | -** | |
| 66939 | -** This routine used to be called sqlite3OpenSnapshot() and with good reason: | |
| 66940 | -** it takes a snapshot of the state of the WAL and wal-index for the current | |
| 66941 | -** instant in time. The current thread will continue to use this snapshot. | |
| 66942 | -** Other threads might append new content to the WAL and wal-index but | |
| 66943 | -** that extra content is ignored by the current thread. | |
| 66944 | -** | |
| 66945 | -** If the database contents have changes since the previous read | |
| 66946 | -** transaction, then *pChanged is set to 1 before returning. The | |
| 66947 | -** Pager layer will use this to know that its cache is stale and | |
| 66948 | -** needs to be flushed. | |
| 67196 | +** This function does the work of sqlite3WalBeginReadTransaction() (see | |
| 67197 | +** below). That function simply calls this one inside an SEH_TRY{...} block. | |
| 66949 | 67198 | */ |
| 66950 | -SQLITE_PRIVATE int sqlite3WalBeginReadTransaction(Wal *pWal, int *pChanged){ | |
| 67199 | +static int walBeginReadTransaction(Wal *pWal, int *pChanged){ | |
| 66951 | 67200 | int rc; /* Return code */ |
| 66952 | 67201 | int cnt = 0; /* Number of TryBeginRead attempts */ |
| 66953 | 67202 | #ifdef SQLITE_ENABLE_SNAPSHOT |
| 67203 | + int ckptLock = 0; | |
| 66954 | 67204 | int bChanged = 0; |
| 66955 | 67205 | WalIndexHdr *pSnapshot = pWal->pSnapshot; |
| 66956 | 67206 | #endif |
| 66957 | 67207 | |
| 66958 | 67208 | assert( pWal->ckptLock==0 ); |
| 67209 | + assert( pWal->nSehTry>0 ); | |
| 66959 | 67210 | |
| 66960 | 67211 | #ifdef SQLITE_ENABLE_SNAPSHOT |
| 66961 | 67212 | if( pSnapshot ){ |
| 66962 | 67213 | if( memcmp(pSnapshot, &pWal->hdr, sizeof(WalIndexHdr))!=0 ){ |
| 66963 | 67214 | bChanged = 1; |
| @@ -66976,11 +67227,11 @@ | ||
| 66976 | 67227 | walDisableBlocking(pWal); |
| 66977 | 67228 | |
| 66978 | 67229 | if( rc!=SQLITE_OK ){ |
| 66979 | 67230 | return rc; |
| 66980 | 67231 | } |
| 66981 | - pWal->ckptLock = 1; | |
| 67232 | + ckptLock = 1; | |
| 66982 | 67233 | } |
| 66983 | 67234 | #endif |
| 66984 | 67235 | |
| 66985 | 67236 | do{ |
| 66986 | 67237 | rc = walTryBeginRead(pWal, pChanged, 0, ++cnt); |
| @@ -67040,18 +67291,40 @@ | ||
| 67040 | 67291 | } |
| 67041 | 67292 | } |
| 67042 | 67293 | } |
| 67043 | 67294 | |
| 67044 | 67295 | /* Release the shared CKPT lock obtained above. */ |
| 67045 | - if( pWal->ckptLock ){ | |
| 67296 | + if( ckptLock ){ | |
| 67046 | 67297 | assert( pSnapshot ); |
| 67047 | 67298 | walUnlockShared(pWal, WAL_CKPT_LOCK); |
| 67048 | - pWal->ckptLock = 0; | |
| 67049 | 67299 | } |
| 67050 | 67300 | #endif |
| 67051 | 67301 | return rc; |
| 67052 | 67302 | } |
| 67303 | + | |
| 67304 | +/* | |
| 67305 | +** Begin a read transaction on the database. | |
| 67306 | +** | |
| 67307 | +** This routine used to be called sqlite3OpenSnapshot() and with good reason: | |
| 67308 | +** it takes a snapshot of the state of the WAL and wal-index for the current | |
| 67309 | +** instant in time. The current thread will continue to use this snapshot. | |
| 67310 | +** Other threads might append new content to the WAL and wal-index but | |
| 67311 | +** that extra content is ignored by the current thread. | |
| 67312 | +** | |
| 67313 | +** If the database contents have changes since the previous read | |
| 67314 | +** transaction, then *pChanged is set to 1 before returning. The | |
| 67315 | +** Pager layer will use this to know that its cache is stale and | |
| 67316 | +** needs to be flushed. | |
| 67317 | +*/ | |
| 67318 | +SQLITE_PRIVATE int sqlite3WalBeginReadTransaction(Wal *pWal, int *pChanged){ | |
| 67319 | + int rc; | |
| 67320 | + SEH_TRY { | |
| 67321 | + rc = walBeginReadTransaction(pWal, pChanged); | |
| 67322 | + } | |
| 67323 | + SEH_EXCEPT( rc = walHandleException(pWal); ) | |
| 67324 | + return rc; | |
| 67325 | +} | |
| 67053 | 67326 | |
| 67054 | 67327 | /* |
| 67055 | 67328 | ** Finish with a read transaction. All this does is release the |
| 67056 | 67329 | ** read-lock. |
| 67057 | 67330 | */ |
| @@ -67069,11 +67342,11 @@ | ||
| 67069 | 67342 | ** to zero. |
| 67070 | 67343 | ** |
| 67071 | 67344 | ** Return SQLITE_OK if successful, or an error code if an error occurs. If an |
| 67072 | 67345 | ** error does occur, the final value of *piRead is undefined. |
| 67073 | 67346 | */ |
| 67074 | -SQLITE_PRIVATE int sqlite3WalFindFrame( | |
| 67347 | +static int walFindFrame( | |
| 67075 | 67348 | Wal *pWal, /* WAL handle */ |
| 67076 | 67349 | Pgno pgno, /* Database page number to read data for */ |
| 67077 | 67350 | u32 *piRead /* OUT: Frame number (or zero) */ |
| 67078 | 67351 | ){ |
| 67079 | 67352 | u32 iRead = 0; /* If !=0, WAL frame to return data from */ |
| @@ -67132,10 +67405,11 @@ | ||
| 67132 | 67405 | if( rc!=SQLITE_OK ){ |
| 67133 | 67406 | return rc; |
| 67134 | 67407 | } |
| 67135 | 67408 | nCollide = HASHTABLE_NSLOT; |
| 67136 | 67409 | iKey = walHash(pgno); |
| 67410 | + SEH_INJECT_FAULT; | |
| 67137 | 67411 | while( (iH = AtomicLoad(&sLoc.aHash[iKey]))!=0 ){ |
| 67138 | 67412 | u32 iFrame = iH + sLoc.iZero; |
| 67139 | 67413 | if( iFrame<=iLast && iFrame>=pWal->minFrame && sLoc.aPgno[iH-1]==pgno ){ |
| 67140 | 67414 | assert( iFrame>iRead || CORRUPT_DB ); |
| 67141 | 67415 | iRead = iFrame; |
| @@ -67167,10 +67441,34 @@ | ||
| 67167 | 67441 | #endif |
| 67168 | 67442 | |
| 67169 | 67443 | *piRead = iRead; |
| 67170 | 67444 | return SQLITE_OK; |
| 67171 | 67445 | } |
| 67446 | + | |
| 67447 | +/* | |
| 67448 | +** Search the wal file for page pgno. If found, set *piRead to the frame that | |
| 67449 | +** contains the page. Otherwise, if pgno is not in the wal file, set *piRead | |
| 67450 | +** to zero. | |
| 67451 | +** | |
| 67452 | +** Return SQLITE_OK if successful, or an error code if an error occurs. If an | |
| 67453 | +** error does occur, the final value of *piRead is undefined. | |
| 67454 | +** | |
| 67455 | +** The difference between this function and walFindFrame() is that this | |
| 67456 | +** function wraps walFindFrame() in an SEH_TRY{...} block. | |
| 67457 | +*/ | |
| 67458 | +SQLITE_PRIVATE int sqlite3WalFindFrame( | |
| 67459 | + Wal *pWal, /* WAL handle */ | |
| 67460 | + Pgno pgno, /* Database page number to read data for */ | |
| 67461 | + u32 *piRead /* OUT: Frame number (or zero) */ | |
| 67462 | +){ | |
| 67463 | + int rc; | |
| 67464 | + SEH_TRY { | |
| 67465 | + rc = walFindFrame(pWal, pgno, piRead); | |
| 67466 | + } | |
| 67467 | + SEH_EXCEPT( rc = SQLITE_IOERR_IN_PAGE; ) | |
| 67468 | + return rc; | |
| 67469 | +} | |
| 67172 | 67470 | |
| 67173 | 67471 | /* |
| 67174 | 67472 | ** Read the contents of frame iRead from the wal file into buffer pOut |
| 67175 | 67473 | ** (which is nOut bytes in size). Return SQLITE_OK if successful, or an |
| 67176 | 67474 | ** error code otherwise. |
| @@ -67249,16 +67547,21 @@ | ||
| 67249 | 67547 | |
| 67250 | 67548 | /* If another connection has written to the database file since the |
| 67251 | 67549 | ** time the read transaction on this connection was started, then |
| 67252 | 67550 | ** the write is disallowed. |
| 67253 | 67551 | */ |
| 67254 | - if( memcmp(&pWal->hdr, (void *)walIndexHdr(pWal), sizeof(WalIndexHdr))!=0 ){ | |
| 67552 | + SEH_TRY { | |
| 67553 | + if( memcmp(&pWal->hdr, (void *)walIndexHdr(pWal), sizeof(WalIndexHdr))!=0 ){ | |
| 67554 | + rc = SQLITE_BUSY_SNAPSHOT; | |
| 67555 | + } | |
| 67556 | + } | |
| 67557 | + SEH_EXCEPT( rc = SQLITE_IOERR_IN_PAGE; ) | |
| 67558 | + | |
| 67559 | + if( rc!=SQLITE_OK ){ | |
| 67255 | 67560 | walUnlockExclusive(pWal, WAL_WRITE_LOCK, 1); |
| 67256 | 67561 | pWal->writeLock = 0; |
| 67257 | - rc = SQLITE_BUSY_SNAPSHOT; | |
| 67258 | 67562 | } |
| 67259 | - | |
| 67260 | 67563 | return rc; |
| 67261 | 67564 | } |
| 67262 | 67565 | |
| 67263 | 67566 | /* |
| 67264 | 67567 | ** End a write transaction. The commit has already been done. This |
| @@ -67290,34 +67593,37 @@ | ||
| 67290 | 67593 | int rc = SQLITE_OK; |
| 67291 | 67594 | if( ALWAYS(pWal->writeLock) ){ |
| 67292 | 67595 | Pgno iMax = pWal->hdr.mxFrame; |
| 67293 | 67596 | Pgno iFrame; |
| 67294 | 67597 | |
| 67295 | - /* Restore the clients cache of the wal-index header to the state it | |
| 67296 | - ** was in before the client began writing to the database. | |
| 67297 | - */ | |
| 67298 | - memcpy(&pWal->hdr, (void *)walIndexHdr(pWal), sizeof(WalIndexHdr)); | |
| 67299 | - | |
| 67300 | - for(iFrame=pWal->hdr.mxFrame+1; | |
| 67301 | - ALWAYS(rc==SQLITE_OK) && iFrame<=iMax; | |
| 67302 | - iFrame++ | |
| 67303 | - ){ | |
| 67304 | - /* This call cannot fail. Unless the page for which the page number | |
| 67305 | - ** is passed as the second argument is (a) in the cache and | |
| 67306 | - ** (b) has an outstanding reference, then xUndo is either a no-op | |
| 67307 | - ** (if (a) is false) or simply expels the page from the cache (if (b) | |
| 67308 | - ** is false). | |
| 67309 | - ** | |
| 67310 | - ** If the upper layer is doing a rollback, it is guaranteed that there | |
| 67311 | - ** are no outstanding references to any page other than page 1. And | |
| 67312 | - ** page 1 is never written to the log until the transaction is | |
| 67313 | - ** committed. As a result, the call to xUndo may not fail. | |
| 67314 | - */ | |
| 67315 | - assert( walFramePgno(pWal, iFrame)!=1 ); | |
| 67316 | - rc = xUndo(pUndoCtx, walFramePgno(pWal, iFrame)); | |
| 67317 | - } | |
| 67318 | - if( iMax!=pWal->hdr.mxFrame ) walCleanupHash(pWal); | |
| 67598 | + SEH_TRY { | |
| 67599 | + /* Restore the clients cache of the wal-index header to the state it | |
| 67600 | + ** was in before the client began writing to the database. | |
| 67601 | + */ | |
| 67602 | + memcpy(&pWal->hdr, (void *)walIndexHdr(pWal), sizeof(WalIndexHdr)); | |
| 67603 | + | |
| 67604 | + for(iFrame=pWal->hdr.mxFrame+1; | |
| 67605 | + ALWAYS(rc==SQLITE_OK) && iFrame<=iMax; | |
| 67606 | + iFrame++ | |
| 67607 | + ){ | |
| 67608 | + /* This call cannot fail. Unless the page for which the page number | |
| 67609 | + ** is passed as the second argument is (a) in the cache and | |
| 67610 | + ** (b) has an outstanding reference, then xUndo is either a no-op | |
| 67611 | + ** (if (a) is false) or simply expels the page from the cache (if (b) | |
| 67612 | + ** is false). | |
| 67613 | + ** | |
| 67614 | + ** If the upper layer is doing a rollback, it is guaranteed that there | |
| 67615 | + ** are no outstanding references to any page other than page 1. And | |
| 67616 | + ** page 1 is never written to the log until the transaction is | |
| 67617 | + ** committed. As a result, the call to xUndo may not fail. | |
| 67618 | + */ | |
| 67619 | + assert( walFramePgno(pWal, iFrame)!=1 ); | |
| 67620 | + rc = xUndo(pUndoCtx, walFramePgno(pWal, iFrame)); | |
| 67621 | + } | |
| 67622 | + if( iMax!=pWal->hdr.mxFrame ) walCleanupHash(pWal); | |
| 67623 | + } | |
| 67624 | + SEH_EXCEPT( rc = SQLITE_IOERR_IN_PAGE; ) | |
| 67319 | 67625 | } |
| 67320 | 67626 | return rc; |
| 67321 | 67627 | } |
| 67322 | 67628 | |
| 67323 | 67629 | /* |
| @@ -67357,11 +67663,14 @@ | ||
| 67357 | 67663 | |
| 67358 | 67664 | if( aWalData[0]<pWal->hdr.mxFrame ){ |
| 67359 | 67665 | pWal->hdr.mxFrame = aWalData[0]; |
| 67360 | 67666 | pWal->hdr.aFrameCksum[0] = aWalData[1]; |
| 67361 | 67667 | pWal->hdr.aFrameCksum[1] = aWalData[2]; |
| 67362 | - walCleanupHash(pWal); | |
| 67668 | + SEH_TRY { | |
| 67669 | + walCleanupHash(pWal); | |
| 67670 | + } | |
| 67671 | + SEH_EXCEPT( rc = SQLITE_IOERR_IN_PAGE; ) | |
| 67363 | 67672 | } |
| 67364 | 67673 | |
| 67365 | 67674 | return rc; |
| 67366 | 67675 | } |
| 67367 | 67676 | |
| @@ -67538,11 +67847,11 @@ | ||
| 67538 | 67847 | |
| 67539 | 67848 | /* |
| 67540 | 67849 | ** Write a set of frames to the log. The caller must hold the write-lock |
| 67541 | 67850 | ** on the log file (obtained using sqlite3WalBeginWriteTransaction()). |
| 67542 | 67851 | */ |
| 67543 | -SQLITE_PRIVATE int sqlite3WalFrames( | |
| 67852 | +static int walFrames( | |
| 67544 | 67853 | Wal *pWal, /* Wal handle to write to */ |
| 67545 | 67854 | int szPage, /* Database page-size in bytes */ |
| 67546 | 67855 | PgHdr *pList, /* List of dirty pages to write */ |
| 67547 | 67856 | Pgno nTruncate, /* Database size after this commit */ |
| 67548 | 67857 | int isCommit, /* True if this is a commit */ |
| @@ -67649,11 +67958,11 @@ | ||
| 67649 | 67958 | ** the current transaction. If so, overwrite the existing frame and |
| 67650 | 67959 | ** set Wal.writeLock to WAL_WRITELOCK_RECKSUM - indicating that |
| 67651 | 67960 | ** checksums must be recomputed when the transaction is committed. */ |
| 67652 | 67961 | if( iFirst && (p->pDirty || isCommit==0) ){ |
| 67653 | 67962 | u32 iWrite = 0; |
| 67654 | - VVA_ONLY(rc =) sqlite3WalFindFrame(pWal, p->pgno, &iWrite); | |
| 67963 | + VVA_ONLY(rc =) walFindFrame(pWal, p->pgno, &iWrite); | |
| 67655 | 67964 | assert( rc==SQLITE_OK || iWrite==0 ); |
| 67656 | 67965 | if( iWrite>=iFirst ){ |
| 67657 | 67966 | i64 iOff = walFrameOffset(iWrite, szPage) + WAL_FRAME_HDRSIZE; |
| 67658 | 67967 | void *pData; |
| 67659 | 67968 | if( pWal->iReCksum==0 || iWrite<pWal->iReCksum ){ |
| @@ -67767,10 +68076,33 @@ | ||
| 67767 | 68076 | } |
| 67768 | 68077 | |
| 67769 | 68078 | WALTRACE(("WAL%p: frame write %s\n", pWal, rc ? "failed" : "ok")); |
| 67770 | 68079 | return rc; |
| 67771 | 68080 | } |
| 68081 | + | |
| 68082 | +/* | |
| 68083 | +** Write a set of frames to the log. The caller must hold the write-lock | |
| 68084 | +** on the log file (obtained using sqlite3WalBeginWriteTransaction()). | |
| 68085 | +** | |
| 68086 | +** The difference between this function and walFrames() is that this | |
| 68087 | +** function wraps walFrames() in an SEH_TRY{...} block. | |
| 68088 | +*/ | |
| 68089 | +SQLITE_PRIVATE int sqlite3WalFrames( | |
| 68090 | + Wal *pWal, /* Wal handle to write to */ | |
| 68091 | + int szPage, /* Database page-size in bytes */ | |
| 68092 | + PgHdr *pList, /* List of dirty pages to write */ | |
| 68093 | + Pgno nTruncate, /* Database size after this commit */ | |
| 68094 | + int isCommit, /* True if this is a commit */ | |
| 68095 | + int sync_flags /* Flags to pass to OsSync() (or 0) */ | |
| 68096 | +){ | |
| 68097 | + int rc; | |
| 68098 | + SEH_TRY { | |
| 68099 | + rc = walFrames(pWal, szPage, pList, nTruncate, isCommit, sync_flags); | |
| 68100 | + } | |
| 68101 | + SEH_EXCEPT( rc = walHandleException(pWal); ) | |
| 68102 | + return rc; | |
| 68103 | +} | |
| 67772 | 68104 | |
| 67773 | 68105 | /* |
| 67774 | 68106 | ** This routine is called to implement sqlite3_wal_checkpoint() and |
| 67775 | 68107 | ** related interfaces. |
| 67776 | 68108 | ** |
| @@ -67847,34 +68179,37 @@ | ||
| 67847 | 68179 | } |
| 67848 | 68180 | } |
| 67849 | 68181 | |
| 67850 | 68182 | |
| 67851 | 68183 | /* Read the wal-index header. */ |
| 67852 | - if( rc==SQLITE_OK ){ | |
| 67853 | - walDisableBlocking(pWal); | |
| 67854 | - rc = walIndexReadHdr(pWal, &isChanged); | |
| 67855 | - (void)walEnableBlocking(pWal); | |
| 67856 | - if( isChanged && pWal->pDbFd->pMethods->iVersion>=3 ){ | |
| 67857 | - sqlite3OsUnfetch(pWal->pDbFd, 0, 0); | |
| 67858 | - } | |
| 67859 | - } | |
| 67860 | - | |
| 67861 | - /* Copy data from the log to the database file. */ | |
| 67862 | - if( rc==SQLITE_OK ){ | |
| 67863 | - | |
| 67864 | - if( pWal->hdr.mxFrame && walPagesize(pWal)!=nBuf ){ | |
| 67865 | - rc = SQLITE_CORRUPT_BKPT; | |
| 67866 | - }else{ | |
| 67867 | - rc = walCheckpoint(pWal, db, eMode2, xBusy2, pBusyArg, sync_flags, zBuf); | |
| 67868 | - } | |
| 67869 | - | |
| 67870 | - /* If no error occurred, set the output variables. */ | |
| 67871 | - if( rc==SQLITE_OK || rc==SQLITE_BUSY ){ | |
| 67872 | - if( pnLog ) *pnLog = (int)pWal->hdr.mxFrame; | |
| 67873 | - if( pnCkpt ) *pnCkpt = (int)(walCkptInfo(pWal)->nBackfill); | |
| 67874 | - } | |
| 67875 | - } | |
| 68184 | + SEH_TRY { | |
| 68185 | + if( rc==SQLITE_OK ){ | |
| 68186 | + walDisableBlocking(pWal); | |
| 68187 | + rc = walIndexReadHdr(pWal, &isChanged); | |
| 68188 | + (void)walEnableBlocking(pWal); | |
| 68189 | + if( isChanged && pWal->pDbFd->pMethods->iVersion>=3 ){ | |
| 68190 | + sqlite3OsUnfetch(pWal->pDbFd, 0, 0); | |
| 68191 | + } | |
| 68192 | + } | |
| 68193 | + | |
| 68194 | + /* Copy data from the log to the database file. */ | |
| 68195 | + if( rc==SQLITE_OK ){ | |
| 68196 | + if( pWal->hdr.mxFrame && walPagesize(pWal)!=nBuf ){ | |
| 68197 | + rc = SQLITE_CORRUPT_BKPT; | |
| 68198 | + }else{ | |
| 68199 | + rc = walCheckpoint(pWal, db, eMode2, xBusy2, pBusyArg, sync_flags,zBuf); | |
| 68200 | + } | |
| 68201 | + | |
| 68202 | + /* If no error occurred, set the output variables. */ | |
| 68203 | + if( rc==SQLITE_OK || rc==SQLITE_BUSY ){ | |
| 68204 | + if( pnLog ) *pnLog = (int)pWal->hdr.mxFrame; | |
| 68205 | + SEH_INJECT_FAULT; | |
| 68206 | + if( pnCkpt ) *pnCkpt = (int)(walCkptInfo(pWal)->nBackfill); | |
| 68207 | + } | |
| 68208 | + } | |
| 68209 | + } | |
| 68210 | + SEH_EXCEPT( rc = walHandleException(pWal); ) | |
| 67876 | 68211 | |
| 67877 | 68212 | if( isChanged ){ |
| 67878 | 68213 | /* If a new wal-index header was loaded before the checkpoint was |
| 67879 | 68214 | ** performed, then the pager-cache associated with pWal is now |
| 67880 | 68215 | ** out of date. So zero the cached wal-index header to ensure that |
| @@ -67947,11 +68282,13 @@ | ||
| 67947 | 68282 | ** prior error while attempting to acquire are read-lock. This cannot |
| 67948 | 68283 | ** happen if the connection is actually in exclusive mode (as no xShmLock |
| 67949 | 68284 | ** locks are taken in this case). Nor should the pager attempt to |
| 67950 | 68285 | ** upgrade to exclusive-mode following such an error. |
| 67951 | 68286 | */ |
| 68287 | +#ifndef SQLITE_USE_SEH | |
| 67952 | 68288 | assert( pWal->readLock>=0 || pWal->lockError ); |
| 68289 | +#endif | |
| 67953 | 68290 | assert( pWal->readLock>=0 || (op<=0 && pWal->exclusiveMode==0) ); |
| 67954 | 68291 | |
| 67955 | 68292 | if( op==0 ){ |
| 67956 | 68293 | if( pWal->exclusiveMode!=WAL_NORMAL_MODE ){ |
| 67957 | 68294 | pWal->exclusiveMode = WAL_NORMAL_MODE; |
| @@ -68048,20 +68385,23 @@ | ||
| 68048 | 68385 | ** occurs (any value other than SQLITE_OK is returned), the CHECKPOINTER |
| 68049 | 68386 | ** lock is released before returning. |
| 68050 | 68387 | */ |
| 68051 | 68388 | SQLITE_PRIVATE int sqlite3WalSnapshotCheck(Wal *pWal, sqlite3_snapshot *pSnapshot){ |
| 68052 | 68389 | int rc; |
| 68053 | - rc = walLockShared(pWal, WAL_CKPT_LOCK); | |
| 68054 | - if( rc==SQLITE_OK ){ | |
| 68055 | - WalIndexHdr *pNew = (WalIndexHdr*)pSnapshot; | |
| 68056 | - if( memcmp(pNew->aSalt, pWal->hdr.aSalt, sizeof(pWal->hdr.aSalt)) | |
| 68057 | - || pNew->mxFrame<walCkptInfo(pWal)->nBackfillAttempted | |
| 68058 | - ){ | |
| 68059 | - rc = SQLITE_ERROR_SNAPSHOT; | |
| 68060 | - walUnlockShared(pWal, WAL_CKPT_LOCK); | |
| 68390 | + SEH_TRY { | |
| 68391 | + rc = walLockShared(pWal, WAL_CKPT_LOCK); | |
| 68392 | + if( rc==SQLITE_OK ){ | |
| 68393 | + WalIndexHdr *pNew = (WalIndexHdr*)pSnapshot; | |
| 68394 | + if( memcmp(pNew->aSalt, pWal->hdr.aSalt, sizeof(pWal->hdr.aSalt)) | |
| 68395 | + || pNew->mxFrame<walCkptInfo(pWal)->nBackfillAttempted | |
| 68396 | + ){ | |
| 68397 | + rc = SQLITE_ERROR_SNAPSHOT; | |
| 68398 | + walUnlockShared(pWal, WAL_CKPT_LOCK); | |
| 68399 | + } | |
| 68061 | 68400 | } |
| 68062 | 68401 | } |
| 68402 | + SEH_EXCEPT( rc = walHandleException(pWal); ) | |
| 68063 | 68403 | return rc; |
| 68064 | 68404 | } |
| 68065 | 68405 | |
| 68066 | 68406 | /* |
| 68067 | 68407 | ** Release a lock obtained by an earlier successful call to |
| @@ -86698,10 +87038,11 @@ | ||
| 86698 | 87038 | } |
| 86699 | 87039 | if( rc==SQLITE_BUSY && p->readOnly ){ |
| 86700 | 87040 | sqlite3VdbeLeave(p); |
| 86701 | 87041 | return SQLITE_BUSY; |
| 86702 | 87042 | }else if( rc!=SQLITE_OK ){ |
| 87043 | + sqlite3SystemError(db, rc); | |
| 86703 | 87044 | p->rc = rc; |
| 86704 | 87045 | sqlite3RollbackAll(db, SQLITE_OK); |
| 86705 | 87046 | p->nChange = 0; |
| 86706 | 87047 | }else{ |
| 86707 | 87048 | db->nDeferredCons = 0; |
| @@ -93737,14 +94078,14 @@ | ||
| 93737 | 94078 | ** This opcode must follow an OP_Lt or OP_Gt comparison operator. There |
| 93738 | 94079 | ** can be zero or more OP_ReleaseReg opcodes intervening, but no other |
| 93739 | 94080 | ** opcodes are allowed to occur between this instruction and the previous |
| 93740 | 94081 | ** OP_Lt or OP_Gt. |
| 93741 | 94082 | ** |
| 93742 | -** If result of an OP_Eq comparison on the same two operands as the | |
| 93743 | -** prior OP_Lt or OP_Gt would have been true, then jump to P2. | |
| 93744 | -** If the result of an OP_Eq comparison on the two previous | |
| 93745 | -** operands would have been false or NULL, then fall through. | |
| 94083 | +** If the result of an OP_Eq comparison on the same two operands as | |
| 94084 | +** the prior OP_Lt or OP_Gt would have been true, then jump to P2. If | |
| 94085 | +** the result of an OP_Eq comparison on the two previous operands | |
| 94086 | +** would have been false or NULL, then fall through. | |
| 93746 | 94087 | */ |
| 93747 | 94088 | case OP_ElseEq: { /* same as TK_ESCAPE, jump */ |
| 93748 | 94089 | |
| 93749 | 94090 | #ifdef SQLITE_DEBUG |
| 93750 | 94091 | /* Verify the preconditions of this opcode - that it follows an OP_Lt or |
| @@ -94170,11 +94511,11 @@ | ||
| 94170 | 94511 | } |
| 94171 | 94512 | |
| 94172 | 94513 | /* Opcode: ZeroOrNull P1 P2 P3 * * |
| 94173 | 94514 | ** Synopsis: r[P2] = 0 OR NULL |
| 94174 | 94515 | ** |
| 94175 | -** If all both registers P1 and P3 are NOT NULL, then store a zero in | |
| 94516 | +** If both registers P1 and P3 are NOT NULL, then store a zero in | |
| 94176 | 94517 | ** register P2. If either registers P1 or P3 are NULL then put |
| 94177 | 94518 | ** a NULL in register P2. |
| 94178 | 94519 | */ |
| 94179 | 94520 | case OP_ZeroOrNull: { /* in1, in2, out2, in3 */ |
| 94180 | 94521 | if( (aMem[pOp->p1].flags & MEM_Null)!=0 |
| @@ -96571,17 +96912,17 @@ | ||
| 96571 | 96912 | ** record. Cursor P1 is an index btree. P2 is a jump destination. |
| 96572 | 96913 | ** In other words, the operands to this opcode are the same as the |
| 96573 | 96914 | ** operands to OP_NotFound and OP_IdxGT. |
| 96574 | 96915 | ** |
| 96575 | 96916 | ** This opcode is an optimization attempt only. If this opcode always |
| 96576 | -** falls through, the correct answer is still obtained, but extra works | |
| 96917 | +** falls through, the correct answer is still obtained, but extra work | |
| 96577 | 96918 | ** is performed. |
| 96578 | 96919 | ** |
| 96579 | 96920 | ** A value of N in the seekHit flag of cursor P1 means that there exists |
| 96580 | 96921 | ** a key P3:N that will match some record in the index. We want to know |
| 96581 | 96922 | ** if it is possible for a record P3:P4 to match some record in the |
| 96582 | -** index. If it is not possible, we can skips some work. So if seekHit | |
| 96923 | +** index. If it is not possible, we can skip some work. So if seekHit | |
| 96583 | 96924 | ** is less than P4, attempt to find out if a match is possible by running |
| 96584 | 96925 | ** OP_NotFound. |
| 96585 | 96926 | ** |
| 96586 | 96927 | ** This opcode is used in IN clause processing for a multi-column key. |
| 96587 | 96928 | ** If an IN clause is attached to an element of the key other than the |
| @@ -97143,14 +97484,14 @@ | ||
| 97143 | 97484 | ** it is ok to delete a record from within a Next loop. If |
| 97144 | 97485 | ** OPFLAG_SAVEPOSITION bit of P5 is clear, then the cursor will be |
| 97145 | 97486 | ** left in an undefined state. |
| 97146 | 97487 | ** |
| 97147 | 97488 | ** If the OPFLAG_AUXDELETE bit is set on P5, that indicates that this |
| 97148 | -** delete one of several associated with deleting a table row and all its | |
| 97149 | -** associated index entries. Exactly one of those deletes is the "primary" | |
| 97150 | -** delete. The others are all on OPFLAG_FORDELETE cursors or else are | |
| 97151 | -** marked with the AUXDELETE flag. | |
| 97489 | +** delete is one of several associated with deleting a table row and | |
| 97490 | +** all its associated index entries. Exactly one of those deletes is | |
| 97491 | +** the "primary" delete. The others are all on OPFLAG_FORDELETE | |
| 97492 | +** cursors or else are marked with the AUXDELETE flag. | |
| 97152 | 97493 | ** |
| 97153 | 97494 | ** If the OPFLAG_NCHANGE flag of P2 (NB: P2 not P5) is set, then the row |
| 97154 | 97495 | ** change count is incremented (otherwise not). |
| 97155 | 97496 | ** |
| 97156 | 97497 | ** P1 must not be pseudo-table. It has to be a real table with |
| @@ -97318,11 +97659,11 @@ | ||
| 97318 | 97659 | ** Synopsis: r[P2]=data |
| 97319 | 97660 | ** |
| 97320 | 97661 | ** Write into register P2 the current sorter data for sorter cursor P1. |
| 97321 | 97662 | ** Then clear the column header cache on cursor P3. |
| 97322 | 97663 | ** |
| 97323 | -** This opcode is normally use to move a record out of the sorter and into | |
| 97664 | +** This opcode is normally used to move a record out of the sorter and into | |
| 97324 | 97665 | ** a register that is the source for a pseudo-table cursor created using |
| 97325 | 97666 | ** OpenPseudo. That pseudo-table cursor is the one that is identified by |
| 97326 | 97667 | ** parameter P3. Clearing the P3 column cache as part of this opcode saves |
| 97327 | 97668 | ** us from having to issue a separate NullRow instruction to clear that cache. |
| 97328 | 97669 | */ |
| @@ -98127,11 +98468,11 @@ | ||
| 98127 | 98468 | ** |
| 98128 | 98469 | ** Delete an entire database table or index whose root page in the database |
| 98129 | 98470 | ** file is given by P1. |
| 98130 | 98471 | ** |
| 98131 | 98472 | ** The table being destroyed is in the main database file if P3==0. If |
| 98132 | -** P3==1 then the table to be clear is in the auxiliary database file | |
| 98473 | +** P3==1 then the table to be destroyed is in the auxiliary database file | |
| 98133 | 98474 | ** that is used to store tables create using CREATE TEMPORARY TABLE. |
| 98134 | 98475 | ** |
| 98135 | 98476 | ** If AUTOVACUUM is enabled then it is possible that another root page |
| 98136 | 98477 | ** might be moved into the newly deleted root page in order to keep all |
| 98137 | 98478 | ** root pages contiguous at the beginning of the database. The former |
| @@ -98187,12 +98528,12 @@ | ||
| 98187 | 98528 | ** |
| 98188 | 98529 | ** Delete all contents of the database table or index whose root page |
| 98189 | 98530 | ** in the database file is given by P1. But, unlike Destroy, do not |
| 98190 | 98531 | ** remove the table or index from the database file. |
| 98191 | 98532 | ** |
| 98192 | -** The table being clear is in the main database file if P2==0. If | |
| 98193 | -** P2==1 then the table to be clear is in the auxiliary database file | |
| 98533 | +** The table being cleared is in the main database file if P2==0. If | |
| 98534 | +** P2==1 then the table to be cleared is in the auxiliary database file | |
| 98194 | 98535 | ** that is used to store tables create using CREATE TEMPORARY TABLE. |
| 98195 | 98536 | ** |
| 98196 | 98537 | ** If the P3 value is non-zero, then the row change count is incremented |
| 98197 | 98538 | ** by the number of rows in the table being cleared. If P3 is greater |
| 98198 | 98539 | ** than zero, then the value stored in register P3 is also incremented |
| @@ -110966,14 +111307,17 @@ | ||
| 110966 | 111307 | int iTable, /* The cursor pointing to the table */ |
| 110967 | 111308 | int iReg, /* Store results here */ |
| 110968 | 111309 | u8 p5 /* P5 value for OP_Column + FLAGS */ |
| 110969 | 111310 | ){ |
| 110970 | 111311 | assert( pParse->pVdbe!=0 ); |
| 111312 | + assert( (p5 & (OPFLAG_NOCHNG|OPFLAG_TYPEOFARG|OPFLAG_LENGTHARG))==p5 ); | |
| 111313 | + assert( IsVirtual(pTab) || (p5 & OPFLAG_NOCHNG)==0 ); | |
| 110971 | 111314 | sqlite3ExprCodeGetColumnOfTable(pParse->pVdbe, pTab, iTable, iColumn, iReg); |
| 110972 | 111315 | if( p5 ){ |
| 110973 | 111316 | VdbeOp *pOp = sqlite3VdbeGetLastOp(pParse->pVdbe); |
| 110974 | 111317 | if( pOp->opcode==OP_Column ) pOp->p5 = p5; |
| 111318 | + if( pOp->opcode==OP_VColumn ) pOp->p5 = (p5 & OPFLAG_NOCHNG); | |
| 110975 | 111319 | } |
| 110976 | 111320 | return iReg; |
| 110977 | 111321 | } |
| 110978 | 111322 | |
| 110979 | 111323 | /* |
| @@ -141288,10 +141632,20 @@ | ||
| 141288 | 141632 | testcase( eDest==SRT_Table ); |
| 141289 | 141633 | testcase( eDest==SRT_EphemTab ); |
| 141290 | 141634 | testcase( eDest==SRT_Fifo ); |
| 141291 | 141635 | testcase( eDest==SRT_DistFifo ); |
| 141292 | 141636 | sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nResultCol, r1+nPrefixReg); |
| 141637 | +#if !defined(SQLITE_ENABLE_NULL_TRIM) && defined(SQLITE_DEBUG) | |
| 141638 | + /* A destination of SRT_Table and a non-zero iSDParm2 parameter means | |
| 141639 | + ** that this is an "UPDATE ... FROM" on a virtual table or view. In this | |
| 141640 | + ** case set the p5 parameter of the OP_MakeRecord to OPFLAG_NOCHNG_MAGIC. | |
| 141641 | + ** This does not affect operation in any way - it just allows MakeRecord | |
| 141642 | + ** to process OPFLAG_NOCHANGE values without an assert() failing. */ | |
| 141643 | + if( eDest==SRT_Table && pDest->iSDParm2 ){ | |
| 141644 | + sqlite3VdbeChangeP5(v, OPFLAG_NOCHNG_MAGIC); | |
| 141645 | + } | |
| 141646 | +#endif | |
| 141293 | 141647 | #ifndef SQLITE_OMIT_CTE |
| 141294 | 141648 | if( eDest==SRT_DistFifo ){ |
| 141295 | 141649 | /* If the destination is DistFifo, then cursor (iParm+1) is open |
| 141296 | 141650 | ** on an ephemeral index. If the current row is already present |
| 141297 | 141651 | ** in the index, do not write it to the output. If not, add the |
| @@ -151336,11 +151690,13 @@ | ||
| 151336 | 151690 | if( aXRef[i]>=0 ){ |
| 151337 | 151691 | pList = sqlite3ExprListAppend(pParse, pList, |
| 151338 | 151692 | sqlite3ExprDup(db, pChanges->a[aXRef[i]].pExpr, 0) |
| 151339 | 151693 | ); |
| 151340 | 151694 | }else{ |
| 151341 | - pList = sqlite3ExprListAppend(pParse, pList, exprRowColumn(pParse, i)); | |
| 151695 | + Expr *pRow = exprRowColumn(pParse, i); | |
| 151696 | + if( pRow ) pRow->op2 = OPFLAG_NOCHNG; | |
| 151697 | + pList = sqlite3ExprListAppend(pParse, pList, pRow); | |
| 151342 | 151698 | } |
| 151343 | 151699 | } |
| 151344 | 151700 | |
| 151345 | 151701 | updateFromSelect(pParse, ephemTab, pPk, pList, pSrc, pWhere, 0, 0); |
| 151346 | 151702 | sqlite3ExprListDelete(db, pList); |
| @@ -175166,11 +175522,11 @@ | ||
| 175166 | 175522 | } |
| 175167 | 175523 | case CC_DIGIT: { |
| 175168 | 175524 | testcase( z[0]=='0' ); testcase( z[0]=='1' ); testcase( z[0]=='2' ); |
| 175169 | 175525 | testcase( z[0]=='3' ); testcase( z[0]=='4' ); testcase( z[0]=='5' ); |
| 175170 | 175526 | testcase( z[0]=='6' ); testcase( z[0]=='7' ); testcase( z[0]=='8' ); |
| 175171 | - testcase( z[0]=='9' ); | |
| 175527 | + testcase( z[0]=='9' ); testcase( z[0]=='.' ); | |
| 175172 | 175528 | *tokenType = TK_INTEGER; |
| 175173 | 175529 | #ifndef SQLITE_OMIT_HEX_INTEGER |
| 175174 | 175530 | if( z[0]=='0' && (z[1]=='x' || z[1]=='X') && sqlite3Isxdigit(z[2]) ){ |
| 175175 | 175531 | for(i=3; sqlite3Isxdigit(z[i]); i++){} |
| 175176 | 175532 | return i; |
| @@ -203827,11 +204183,17 @@ | ||
| 203827 | 204183 | int argc, |
| 203828 | 204184 | sqlite3_value **argv |
| 203829 | 204185 | ){ |
| 203830 | 204186 | JsonParse *p; /* The parse */ |
| 203831 | 204187 | UNUSED_PARAMETER(argc); |
| 203832 | - if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return; | |
| 204188 | + if( sqlite3_value_type(argv[0])==SQLITE_NULL ){ | |
| 204189 | +#ifdef SQLITE_LEGACY_JSON_VALID | |
| 204190 | + /* Incorrect legacy behavior was to return FALSE for a NULL input */ | |
| 204191 | + sqlite3_result_int(ctx, 0); | |
| 204192 | +#endif | |
| 204193 | + return; | |
| 204194 | + } | |
| 203833 | 204195 | p = jsonParseCached(ctx, argv[0], 0, 0); |
| 203834 | 204196 | if( p==0 || p->oom ){ |
| 203835 | 204197 | sqlite3_result_error_nomem(ctx); |
| 203836 | 204198 | sqlite3_free(p); |
| 203837 | 204199 | }else{ |
| @@ -225917,28 +226279,28 @@ | ||
| 225917 | 226279 | |
| 225918 | 226280 | /* Create a new tokenizer */ |
| 225919 | 226281 | int (*xCreateTokenizer)( |
| 225920 | 226282 | fts5_api *pApi, |
| 225921 | 226283 | const char *zName, |
| 225922 | - void *pContext, | |
| 226284 | + void *pUserData, | |
| 225923 | 226285 | fts5_tokenizer *pTokenizer, |
| 225924 | 226286 | void (*xDestroy)(void*) |
| 225925 | 226287 | ); |
| 225926 | 226288 | |
| 225927 | 226289 | /* Find an existing tokenizer */ |
| 225928 | 226290 | int (*xFindTokenizer)( |
| 225929 | 226291 | fts5_api *pApi, |
| 225930 | 226292 | const char *zName, |
| 225931 | - void **ppContext, | |
| 226293 | + void **ppUserData, | |
| 225932 | 226294 | fts5_tokenizer *pTokenizer |
| 225933 | 226295 | ); |
| 225934 | 226296 | |
| 225935 | 226297 | /* Create a new auxiliary function */ |
| 225936 | 226298 | int (*xCreateFunction)( |
| 225937 | 226299 | fts5_api *pApi, |
| 225938 | 226300 | const char *zName, |
| 225939 | - void *pContext, | |
| 226301 | + void *pUserData, | |
| 225940 | 226302 | fts5_extension_function xFunction, |
| 225941 | 226303 | void (*xDestroy)(void*) |
| 225942 | 226304 | ); |
| 225943 | 226305 | }; |
| 225944 | 226306 | |
| @@ -244178,11 +244540,11 @@ | ||
| 244178 | 244540 | /* Filter out attempts to run UPDATE or DELETE on contentless tables. |
| 244179 | 244541 | ** This is not suported. Except - DELETE is supported if the CREATE |
| 244180 | 244542 | ** VIRTUAL TABLE statement contained "contentless_delete=1". */ |
| 244181 | 244543 | if( eType0==SQLITE_INTEGER |
| 244182 | 244544 | && pConfig->eContent==FTS5_CONTENT_NONE |
| 244183 | - && (nArg>1 || pConfig->bContentlessDelete==0) | |
| 244545 | + && pConfig->bContentlessDelete==0 | |
| 244184 | 244546 | ){ |
| 244185 | 244547 | pTab->p.base.zErrMsg = sqlite3_mprintf( |
| 244186 | 244548 | "cannot %s contentless fts5 table: %s", |
| 244187 | 244549 | (nArg>1 ? "UPDATE" : "DELETE from"), pConfig->zName |
| 244188 | 244550 | ); |
| @@ -245033,10 +245395,16 @@ | ||
| 245033 | 245395 | rc = fts5SeekCursor(pCsr, 1); |
| 245034 | 245396 | if( rc==SQLITE_OK ){ |
| 245035 | 245397 | sqlite3_result_value(pCtx, sqlite3_column_value(pCsr->pStmt, iCol+1)); |
| 245036 | 245398 | } |
| 245037 | 245399 | pConfig->pzErrmsg = 0; |
| 245400 | + }else if( pConfig->bContentlessDelete && sqlite3_vtab_nochange(pCtx) ){ | |
| 245401 | + char *zErr = sqlite3_mprintf("cannot UPDATE a subset of " | |
| 245402 | + "columns on fts5 contentless-delete table: %s", pConfig->zName | |
| 245403 | + ); | |
| 245404 | + sqlite3_result_error(pCtx, zErr, -1); | |
| 245405 | + sqlite3_free(zErr); | |
| 245038 | 245406 | } |
| 245039 | 245407 | return rc; |
| 245040 | 245408 | } |
| 245041 | 245409 | |
| 245042 | 245410 | |
| @@ -245315,11 +245683,11 @@ | ||
| 245315 | 245683 | int nArg, /* Number of args */ |
| 245316 | 245684 | sqlite3_value **apUnused /* Function arguments */ |
| 245317 | 245685 | ){ |
| 245318 | 245686 | assert( nArg==0 ); |
| 245319 | 245687 | UNUSED_PARAM2(nArg, apUnused); |
| 245320 | - sqlite3_result_text(pCtx, "fts5: 2023-08-04 13:19:11 ba7a66db13b28da0b41f03be825a593608474a5ebda89e12d58d89db709b8f65", -1, SQLITE_TRANSIENT); | |
| 245688 | + sqlite3_result_text(pCtx, "fts5: 2023-08-11 22:40:06 3bc0693c4633f545f09dbee702e25354504b20836373a068447e6c61cb2ebd79", -1, SQLITE_TRANSIENT); | |
| 245321 | 245689 | } |
| 245322 | 245690 | |
| 245323 | 245691 | /* |
| 245324 | 245692 | ** Return true if zName is the extension on one of the shadow tables used |
| 245325 | 245693 | ** by this module. |
| 245326 | 245694 |
| --- extsrc/sqlite3.c | |
| +++ extsrc/sqlite3.c | |
| @@ -1,8 +1,8 @@ | |
| 1 | /****************************************************************************** |
| 2 | ** This file is an amalgamation of many separate C source files from SQLite |
| 3 | ** version $VERSION. By combining all the individual C code files into this |
| 4 | ** single large file, the entire code can be compiled as a single translation |
| 5 | ** unit. This allows many compilers to do optimizations that would not be |
| 6 | ** possible if the files were compiled separately. Performance improvements |
| 7 | ** of 5% or more are commonly seen when SQLite is compiled as a single |
| 8 | ** translation unit. |
| @@ -16,11 +16,11 @@ | |
| 16 | ** if you want a wrapper to interface SQLite with your choice of programming |
| 17 | ** language. The code for the "sqlite3" command-line shell is also in a |
| 18 | ** separate file. This file contains only code for the core SQLite library. |
| 19 | ** |
| 20 | ** The content in this amalgamation comes from Fossil check-in |
| 21 | ** a7a66db13b28da0b41f03be825a59360847. |
| 22 | */ |
| 23 | #define SQLITE_CORE 1 |
| 24 | #define SQLITE_AMALGAMATION 1 |
| 25 | #ifndef SQLITE_PRIVATE |
| 26 | # define SQLITE_PRIVATE static |
| @@ -459,11 +459,11 @@ | |
| 459 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 460 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 461 | */ |
| 462 | #define SQLITE_VERSION "3.43.0" |
| 463 | #define SQLITE_VERSION_NUMBER 3043000 |
| 464 | #define SQLITE_SOURCE_ID "2023-08-04 13:19:11 ba7a66db13b28da0b41f03be825a593608474a5ebda89e12d58d89db709b8f65" |
| 465 | |
| 466 | /* |
| 467 | ** CAPI3REF: Run-Time Library Version Numbers |
| 468 | ** KEYWORDS: sqlite3_version sqlite3_sourceid |
| 469 | ** |
| @@ -839,10 +839,11 @@ | |
| 839 | #define SQLITE_IOERR_BEGIN_ATOMIC (SQLITE_IOERR | (29<<8)) |
| 840 | #define SQLITE_IOERR_COMMIT_ATOMIC (SQLITE_IOERR | (30<<8)) |
| 841 | #define SQLITE_IOERR_ROLLBACK_ATOMIC (SQLITE_IOERR | (31<<8)) |
| 842 | #define SQLITE_IOERR_DATA (SQLITE_IOERR | (32<<8)) |
| 843 | #define SQLITE_IOERR_CORRUPTFS (SQLITE_IOERR | (33<<8)) |
| 844 | #define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8)) |
| 845 | #define SQLITE_LOCKED_VTAB (SQLITE_LOCKED | (2<<8)) |
| 846 | #define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8)) |
| 847 | #define SQLITE_BUSY_SNAPSHOT (SQLITE_BUSY | (2<<8)) |
| 848 | #define SQLITE_BUSY_TIMEOUT (SQLITE_BUSY | (3<<8)) |
| @@ -13394,28 +13395,28 @@ | |
| 13394 | |
| 13395 | /* Create a new tokenizer */ |
| 13396 | int (*xCreateTokenizer)( |
| 13397 | fts5_api *pApi, |
| 13398 | const char *zName, |
| 13399 | void *pContext, |
| 13400 | fts5_tokenizer *pTokenizer, |
| 13401 | void (*xDestroy)(void*) |
| 13402 | ); |
| 13403 | |
| 13404 | /* Find an existing tokenizer */ |
| 13405 | int (*xFindTokenizer)( |
| 13406 | fts5_api *pApi, |
| 13407 | const char *zName, |
| 13408 | void **ppContext, |
| 13409 | fts5_tokenizer *pTokenizer |
| 13410 | ); |
| 13411 | |
| 13412 | /* Create a new auxiliary function */ |
| 13413 | int (*xCreateFunction)( |
| 13414 | fts5_api *pApi, |
| 13415 | const char *zName, |
| 13416 | void *pContext, |
| 13417 | fts5_extension_function xFunction, |
| 13418 | void (*xDestroy)(void*) |
| 13419 | ); |
| 13420 | }; |
| 13421 | |
| @@ -14630,11 +14631,11 @@ | |
| 14630 | #define SQLITE_WITHIN(P,S,E) (((uptr)(P)>=(uptr)(S))&&((uptr)(P)<(uptr)(E))) |
| 14631 | |
| 14632 | /* |
| 14633 | ** P is one byte past the end of a large buffer. Return true if a span of bytes |
| 14634 | ** between S..E crosses the end of that buffer. In other words, return true |
| 14635 | ** if the sub-buffer S..E-1 overflows the buffer show last byte is P-1. |
| 14636 | ** |
| 14637 | ** S is the start of the span. E is one byte past the end of end of span. |
| 14638 | ** |
| 14639 | ** P |
| 14640 | ** |-----------------| FALSE |
| @@ -14993,11 +14994,10 @@ | |
| 14993 | typedef struct Column Column; |
| 14994 | typedef struct Cte Cte; |
| 14995 | typedef struct CteUse CteUse; |
| 14996 | typedef struct Db Db; |
| 14997 | typedef struct DbFixer DbFixer; |
| 14998 | typedef struct DblDbl DblDbl; |
| 14999 | typedef struct Schema Schema; |
| 15000 | typedef struct Expr Expr; |
| 15001 | typedef struct ExprList ExprList; |
| 15002 | typedef struct FKey FKey; |
| 15003 | typedef struct FpDecode FpDecode; |
| @@ -15654,10 +15654,14 @@ | |
| 15654 | void enable_simulated_io_errors(void); |
| 15655 | #else |
| 15656 | # define disable_simulated_io_errors() |
| 15657 | # define enable_simulated_io_errors() |
| 15658 | #endif |
| 15659 | |
| 15660 | #endif /* SQLITE_PAGER_H */ |
| 15661 | |
| 15662 | /************** End of pager.h ***********************************************/ |
| 15663 | /************** Continuing where we left off in sqliteInt.h ******************/ |
| @@ -19430,10 +19434,13 @@ | |
| 19430 | yDbMask cookieMask; /* Bitmask of schema verified databases */ |
| 19431 | int regRowid; /* Register holding rowid of CREATE TABLE entry */ |
| 19432 | int regRoot; /* Register holding root page number for new objects */ |
| 19433 | int nMaxArg; /* Max args passed to user function by sub-program */ |
| 19434 | int nSelect; /* Number of SELECT stmts. Counter for Select.selId */ |
| 19435 | #ifndef SQLITE_OMIT_SHARED_CACHE |
| 19436 | int nTableLock; /* Number of locks in aTableLock */ |
| 19437 | TableLock *aTableLock; /* Required table locks for shared-cache mode */ |
| 19438 | #endif |
| 19439 | AutoincInfo *pAinc; /* Information about AUTOINCREMENT counters */ |
| @@ -19443,16 +19450,13 @@ | |
| 19443 | ParseCleanup *pCleanup; /* List of cleanup operations to run after parse */ |
| 19444 | union { |
| 19445 | int addrCrTab; /* Address of OP_CreateBtree on CREATE TABLE */ |
| 19446 | Returning *pReturning; /* The RETURNING clause */ |
| 19447 | } u1; |
| 19448 | LogEst nQueryLoop; /* Est number of iterations of a query (10*log2(N)) */ |
| 19449 | u32 oldmask; /* Mask of old.* columns referenced */ |
| 19450 | u32 newmask; /* Mask of new.* columns referenced */ |
| 19451 | #ifndef SQLITE_OMIT_PROGRESS_CALLBACK |
| 19452 | u32 nProgressSteps; /* xProgress steps taken during sqlite3_prepare() */ |
| 19453 | #endif |
| 19454 | u8 eTriggerOp; /* TK_UPDATE, TK_INSERT or TK_DELETE */ |
| 19455 | u8 bReturning; /* Coding a RETURNING trigger */ |
| 19456 | u8 eOrconf; /* Default ON CONFLICT policy for trigger steps */ |
| 19457 | u8 disableTriggers; /* True to disable triggers */ |
| 19458 | |
| @@ -21503,13 +21507,10 @@ | |
| 21503 | "32BIT_ROWID", |
| 21504 | #endif |
| 21505 | #ifdef SQLITE_4_BYTE_ALIGNED_MALLOC |
| 21506 | "4_BYTE_ALIGNED_MALLOC", |
| 21507 | #endif |
| 21508 | #ifdef SQLITE_64BIT_STATS |
| 21509 | "64BIT_STATS", |
| 21510 | #endif |
| 21511 | #ifdef SQLITE_ALLOW_COVERING_INDEX_SCAN |
| 21512 | # if SQLITE_ALLOW_COVERING_INDEX_SCAN != 1 |
| 21513 | "ALLOW_COVERING_INDEX_SCAN=" CTIMEOPT_VAL(SQLITE_ALLOW_COVERING_INDEX_SCAN), |
| 21514 | # endif |
| 21515 | #endif |
| @@ -21841,10 +21842,13 @@ | |
| 21841 | #ifdef SQLITE_INT64_TYPE |
| 21842 | "INT64_TYPE", |
| 21843 | #endif |
| 21844 | #ifdef SQLITE_INTEGRITY_CHECK_ERROR_MAX |
| 21845 | "INTEGRITY_CHECK_ERROR_MAX=" CTIMEOPT_VAL(SQLITE_INTEGRITY_CHECK_ERROR_MAX), |
| 21846 | #endif |
| 21847 | #ifdef SQLITE_LIKE_DOESNT_MATCH_BLOBS |
| 21848 | "LIKE_DOESNT_MATCH_BLOBS", |
| 21849 | #endif |
| 21850 | #ifdef SQLITE_LOCK_TRACE |
| @@ -34295,10 +34299,27 @@ | |
| 34295 | ** Load the sqlite3.iSysErrno field if that is an appropriate thing |
| 34296 | ** to do based on the SQLite error code in rc. |
| 34297 | */ |
| 34298 | SQLITE_PRIVATE void sqlite3SystemError(sqlite3 *db, int rc){ |
| 34299 | if( rc==SQLITE_IOERR_NOMEM ) return; |
| 34300 | rc &= 0xff; |
| 34301 | if( rc==SQLITE_CANTOPEN || rc==SQLITE_IOERR ){ |
| 34302 | db->iSysErrno = sqlite3OsGetLastError(db->pVfs); |
| 34303 | } |
| 34304 | } |
| @@ -56206,10 +56227,14 @@ | |
| 56206 | |
| 56207 | #ifdef SQLITE_ENABLE_SETLK_TIMEOUT |
| 56208 | SQLITE_PRIVATE int sqlite3WalWriteLock(Wal *pWal, int bLock); |
| 56209 | SQLITE_PRIVATE void sqlite3WalDb(Wal *pWal, sqlite3 *db); |
| 56210 | #endif |
| 56211 | |
| 56212 | #endif /* ifndef SQLITE_OMIT_WAL */ |
| 56213 | #endif /* SQLITE_WAL_H */ |
| 56214 | |
| 56215 | /************** End of wal.h *************************************************/ |
| @@ -63919,10 +63944,16 @@ | |
| 63919 | SQLITE_PRIVATE int sqlite3PagerWalFramesize(Pager *pPager){ |
| 63920 | assert( pPager->eState>=PAGER_READER ); |
| 63921 | return sqlite3WalFramesize(pPager->pWal); |
| 63922 | } |
| 63923 | #endif |
| 63924 | |
| 63925 | #endif /* SQLITE_OMIT_DISKIO */ |
| 63926 | |
| 63927 | /************** End of pager.c ***********************************************/ |
| 63928 | /************** Begin file wal.c *********************************************/ |
| @@ -64454,11 +64485,17 @@ | |
| 64454 | WalIndexHdr hdr; /* Wal-index header for current transaction */ |
| 64455 | u32 minFrame; /* Ignore wal frames before this one */ |
| 64456 | u32 iReCksum; /* On commit, recalculate checksums from here */ |
| 64457 | const char *zWalName; /* Name of WAL file */ |
| 64458 | u32 nCkpt; /* Checkpoint sequence counter in the wal-header */ |
| 64459 | #ifdef SQLITE_DEBUG |
| 64460 | u8 lockError; /* True if a locking error has occurred */ |
| 64461 | #endif |
| 64462 | #ifdef SQLITE_ENABLE_SNAPSHOT |
| 64463 | WalIndexHdr *pSnapshot; /* Start transaction here if not NULL */ |
| 64464 | #endif |
| @@ -64535,10 +64572,104 @@ | |
| 64535 | |
| 64536 | /* The wal-index is divided into pages of WALINDEX_PGSZ bytes each. */ |
| 64537 | #define WALINDEX_PGSZ ( \ |
| 64538 | sizeof(ht_slot)*HASHTABLE_NSLOT + HASHTABLE_NPAGE*sizeof(u32) \ |
| 64539 | ) |
| 64540 | |
| 64541 | /* |
| 64542 | ** Obtain a pointer to the iPage'th page of the wal-index. The wal-index |
| 64543 | ** is broken into pages of WALINDEX_PGSZ bytes. Wal-index pages are |
| 64544 | ** numbered from zero. |
| @@ -64608,10 +64739,11 @@ | |
| 64608 | static int walIndexPage( |
| 64609 | Wal *pWal, /* The WAL context */ |
| 64610 | int iPage, /* The page we seek */ |
| 64611 | volatile u32 **ppPage /* Write the page pointer here */ |
| 64612 | ){ |
| 64613 | if( pWal->nWiData<=iPage || (*ppPage = pWal->apWiData[iPage])==0 ){ |
| 64614 | return walIndexPageRealloc(pWal, iPage, ppPage); |
| 64615 | } |
| 64616 | return SQLITE_OK; |
| 64617 | } |
| @@ -64619,18 +64751,20 @@ | |
| 64619 | /* |
| 64620 | ** Return a pointer to the WalCkptInfo structure in the wal-index. |
| 64621 | */ |
| 64622 | static volatile WalCkptInfo *walCkptInfo(Wal *pWal){ |
| 64623 | assert( pWal->nWiData>0 && pWal->apWiData[0] ); |
| 64624 | return (volatile WalCkptInfo*)&(pWal->apWiData[0][sizeof(WalIndexHdr)/2]); |
| 64625 | } |
| 64626 | |
| 64627 | /* |
| 64628 | ** Return a pointer to the WalIndexHdr structure in the wal-index. |
| 64629 | */ |
| 64630 | static volatile WalIndexHdr *walIndexHdr(Wal *pWal){ |
| 64631 | assert( pWal->nWiData>0 && pWal->apWiData[0] ); |
| 64632 | return (volatile WalIndexHdr*)pWal->apWiData[0]; |
| 64633 | } |
| 64634 | |
| 64635 | /* |
| 64636 | ** The argument to this macro must be of type u32. On a little-endian |
| @@ -64884,16 +65018,22 @@ | |
| 64884 | rc = sqlite3OsShmLock(pWal->pDbFd, lockIdx, 1, |
| 64885 | SQLITE_SHM_LOCK | SQLITE_SHM_SHARED); |
| 64886 | WALTRACE(("WAL%p: acquire SHARED-%s %s\n", pWal, |
| 64887 | walLockName(lockIdx), rc ? "failed" : "ok")); |
| 64888 | VVA_ONLY( pWal->lockError = (u8)(rc!=SQLITE_OK && (rc&0xFF)!=SQLITE_BUSY); ) |
| 64889 | return rc; |
| 64890 | } |
| 64891 | static void walUnlockShared(Wal *pWal, int lockIdx){ |
| 64892 | if( pWal->exclusiveMode ) return; |
| 64893 | (void)sqlite3OsShmLock(pWal->pDbFd, lockIdx, 1, |
| 64894 | SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED); |
| 64895 | WALTRACE(("WAL%p: release SHARED-%s\n", pWal, walLockName(lockIdx))); |
| 64896 | } |
| 64897 | static int walLockExclusive(Wal *pWal, int lockIdx, int n){ |
| 64898 | int rc; |
| 64899 | if( pWal->exclusiveMode ) return SQLITE_OK; |
| @@ -64900,16 +65040,24 @@ | |
| 64900 | rc = sqlite3OsShmLock(pWal->pDbFd, lockIdx, n, |
| 64901 | SQLITE_SHM_LOCK | SQLITE_SHM_EXCLUSIVE); |
| 64902 | WALTRACE(("WAL%p: acquire EXCLUSIVE-%s cnt=%d %s\n", pWal, |
| 64903 | walLockName(lockIdx), n, rc ? "failed" : "ok")); |
| 64904 | VVA_ONLY( pWal->lockError = (u8)(rc!=SQLITE_OK && (rc&0xFF)!=SQLITE_BUSY); ) |
| 64905 | return rc; |
| 64906 | } |
| 64907 | static void walUnlockExclusive(Wal *pWal, int lockIdx, int n){ |
| 64908 | if( pWal->exclusiveMode ) return; |
| 64909 | (void)sqlite3OsShmLock(pWal->pDbFd, lockIdx, n, |
| 64910 | SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE); |
| 64911 | WALTRACE(("WAL%p: release EXCLUSIVE-%s cnt=%d\n", pWal, |
| 64912 | walLockName(lockIdx), n)); |
| 64913 | } |
| 64914 | |
| 64915 | /* |
| @@ -64997,10 +65145,11 @@ | |
| 64997 | /* |
| 64998 | ** Return the page number associated with frame iFrame in this WAL. |
| 64999 | */ |
| 65000 | static u32 walFramePgno(Wal *pWal, u32 iFrame){ |
| 65001 | int iHash = walFramePage(iFrame); |
| 65002 | if( iHash==0 ){ |
| 65003 | return pWal->apWiData[0][WALINDEX_HDR_SIZE/sizeof(u32) + iFrame - 1]; |
| 65004 | } |
| 65005 | return pWal->apWiData[iHash][(iFrame-1-HASHTABLE_NPAGE_ONE)%HASHTABLE_NPAGE]; |
| 65006 | } |
| @@ -65256,10 +65405,11 @@ | |
| 65256 | } |
| 65257 | |
| 65258 | /* Malloc a buffer to read frames into. */ |
| 65259 | szFrame = szPage + WAL_FRAME_HDRSIZE; |
| 65260 | aFrame = (u8 *)sqlite3_malloc64(szFrame + WALINDEX_PGSZ); |
| 65261 | if( !aFrame ){ |
| 65262 | rc = SQLITE_NOMEM_BKPT; |
| 65263 | goto recovery_error; |
| 65264 | } |
| 65265 | aData = &aFrame[WAL_FRAME_HDRSIZE]; |
| @@ -65331,13 +65481,15 @@ | |
| 65331 | aShare[i] = aPrivate[i]; |
| 65332 | } |
| 65333 | } |
| 65334 | } |
| 65335 | #endif |
| 65336 | if( iFrame<=iLast ) break; |
| 65337 | } |
| 65338 | |
| 65339 | sqlite3_free(aFrame); |
| 65340 | } |
| 65341 | |
| 65342 | finished: |
| 65343 | if( rc==SQLITE_OK ){ |
| @@ -65361,10 +65513,11 @@ | |
| 65361 | if( i==1 && pWal->hdr.mxFrame ){ |
| 65362 | pInfo->aReadMark[i] = pWal->hdr.mxFrame; |
| 65363 | }else{ |
| 65364 | pInfo->aReadMark[i] = READMARK_NOT_USED; |
| 65365 | } |
| 65366 | walUnlockExclusive(pWal, WAL_READ_LOCK(i), 1); |
| 65367 | }else if( rc!=SQLITE_BUSY ){ |
| 65368 | goto recovery_error; |
| 65369 | } |
| 65370 | } |
| @@ -65753,10 +65906,11 @@ | |
| 65753 | return SQLITE_NOMEM_BKPT; |
| 65754 | } |
| 65755 | memset(p, 0, nByte); |
| 65756 | p->nSegment = nSegment; |
| 65757 | aTmp = (ht_slot*)&(((u8*)p)[nByte]); |
| 65758 | for(i=walFramePage(nBackfill+1); rc==SQLITE_OK && i<nSegment; i++){ |
| 65759 | WalHashLoc sLoc; |
| 65760 | |
| 65761 | rc = walHashGet(pWal, i, &sLoc); |
| 65762 | if( rc==SQLITE_OK ){ |
| @@ -65781,10 +65935,11 @@ | |
| 65781 | p->aSegment[i].aIndex = aIndex; |
| 65782 | p->aSegment[i].aPgno = (u32 *)sLoc.aPgno; |
| 65783 | } |
| 65784 | } |
| 65785 | if( rc!=SQLITE_OK ){ |
| 65786 | walIteratorFree(p); |
| 65787 | p = 0; |
| 65788 | } |
| 65789 | *pp = p; |
| 65790 | return rc; |
| @@ -66006,17 +66161,17 @@ | |
| 66006 | ** cannot be backfilled from the WAL. |
| 66007 | */ |
| 66008 | mxSafeFrame = pWal->hdr.mxFrame; |
| 66009 | mxPage = pWal->hdr.nPage; |
| 66010 | for(i=1; i<WAL_NREADER; i++){ |
| 66011 | u32 y = AtomicLoad(pInfo->aReadMark+i); |
| 66012 | if( mxSafeFrame>y ){ |
| 66013 | assert( y<=pWal->hdr.mxFrame ); |
| 66014 | rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_READ_LOCK(i), 1); |
| 66015 | if( rc==SQLITE_OK ){ |
| 66016 | u32 iMark = (i==1 ? mxSafeFrame : READMARK_NOT_USED); |
| 66017 | AtomicStore(pInfo->aReadMark+i, iMark); |
| 66018 | walUnlockExclusive(pWal, WAL_READ_LOCK(i), 1); |
| 66019 | }else if( rc==SQLITE_BUSY ){ |
| 66020 | mxSafeFrame = y; |
| 66021 | xBusy = 0; |
| 66022 | }else{ |
| @@ -66033,12 +66188,11 @@ | |
| 66033 | |
| 66034 | if( pIter |
| 66035 | && (rc = walBusyLock(pWal,xBusy,pBusyArg,WAL_READ_LOCK(0),1))==SQLITE_OK |
| 66036 | ){ |
| 66037 | u32 nBackfill = pInfo->nBackfill; |
| 66038 | |
| 66039 | pInfo->nBackfillAttempted = mxSafeFrame; |
| 66040 | |
| 66041 | /* Sync the WAL to disk */ |
| 66042 | rc = sqlite3OsSync(pWal->pWalFd, CKPT_SYNC_FLAGS(sync_flags)); |
| 66043 | |
| 66044 | /* If the database may grow as a result of this checkpoint, hint |
| @@ -66065,10 +66219,11 @@ | |
| 66065 | |
| 66066 | /* Iterate through the contents of the WAL, copying data to the db file */ |
| 66067 | while( rc==SQLITE_OK && 0==walIteratorNext(pIter, &iDbpage, &iFrame) ){ |
| 66068 | i64 iOffset; |
| 66069 | assert( walFramePgno(pWal, iFrame)==iDbpage ); |
| 66070 | if( AtomicLoad(&db->u1.isInterrupted) ){ |
| 66071 | rc = db->mallocFailed ? SQLITE_NOMEM_BKPT : SQLITE_INTERRUPT; |
| 66072 | break; |
| 66073 | } |
| 66074 | if( iFrame<=nBackfill || iFrame>mxSafeFrame || iDbpage>mxPage ){ |
| @@ -66094,11 +66249,11 @@ | |
| 66094 | if( rc==SQLITE_OK ){ |
| 66095 | rc = sqlite3OsSync(pWal->pDbFd, CKPT_SYNC_FLAGS(sync_flags)); |
| 66096 | } |
| 66097 | } |
| 66098 | if( rc==SQLITE_OK ){ |
| 66099 | AtomicStore(&pInfo->nBackfill, mxSafeFrame); |
| 66100 | } |
| 66101 | } |
| 66102 | |
| 66103 | /* Release the reader lock held while backfilling */ |
| 66104 | walUnlockExclusive(pWal, WAL_READ_LOCK(0), 1); |
| @@ -66116,10 +66271,11 @@ | |
| 66116 | ** until all readers have finished using the wal file. This ensures that |
| 66117 | ** the next process to write to the database restarts the wal file. |
| 66118 | */ |
| 66119 | if( rc==SQLITE_OK && eMode!=SQLITE_CHECKPOINT_PASSIVE ){ |
| 66120 | assert( pWal->writeLock ); |
| 66121 | if( pInfo->nBackfill<pWal->hdr.mxFrame ){ |
| 66122 | rc = SQLITE_BUSY; |
| 66123 | }else if( eMode>=SQLITE_CHECKPOINT_RESTART ){ |
| 66124 | u32 salt1; |
| 66125 | sqlite3_randomness(4, &salt1); |
| @@ -66147,10 +66303,11 @@ | |
| 66147 | } |
| 66148 | } |
| 66149 | } |
| 66150 | |
| 66151 | walcheckpoint_out: |
| 66152 | walIteratorFree(pIter); |
| 66153 | return rc; |
| 66154 | } |
| 66155 | |
| 66156 | /* |
| @@ -66169,10 +66326,91 @@ | |
| 66169 | if( rx ){ |
| 66170 | sqlite3_log(rx, "cannot limit WAL size: %s", pWal->zWalName); |
| 66171 | } |
| 66172 | } |
| 66173 | |
| 66174 | /* |
| 66175 | ** Close a connection to a log file. |
| 66176 | */ |
| 66177 | SQLITE_PRIVATE int sqlite3WalClose( |
| 66178 | Wal *pWal, /* Wal to close */ |
| @@ -66182,10 +66420,12 @@ | |
| 66182 | u8 *zBuf /* Buffer of at least nBuf bytes */ |
| 66183 | ){ |
| 66184 | int rc = SQLITE_OK; |
| 66185 | if( pWal ){ |
| 66186 | int isDelete = 0; /* True to unlink wal and wal-index files */ |
| 66187 | |
| 66188 | /* If an EXCLUSIVE lock can be obtained on the database file (using the |
| 66189 | ** ordinary, rollback-mode locking methods, this guarantees that the |
| 66190 | ** connection associated with this log file is the only connection to |
| 66191 | ** the database. In this case checkpoint the database and unlink both |
| @@ -66725,10 +66965,11 @@ | |
| 66725 | } |
| 66726 | |
| 66727 | assert( pWal->nWiData>0 ); |
| 66728 | assert( pWal->apWiData[0]!=0 ); |
| 66729 | pInfo = walCkptInfo(pWal); |
| 66730 | if( !useWal && AtomicLoad(&pInfo->nBackfill)==pWal->hdr.mxFrame |
| 66731 | #ifdef SQLITE_ENABLE_SNAPSHOT |
| 66732 | && (pWal->pSnapshot==0 || pWal->hdr.mxFrame==0) |
| 66733 | #endif |
| 66734 | ){ |
| @@ -66774,11 +67015,11 @@ | |
| 66774 | if( pWal->pSnapshot && pWal->pSnapshot->mxFrame<mxFrame ){ |
| 66775 | mxFrame = pWal->pSnapshot->mxFrame; |
| 66776 | } |
| 66777 | #endif |
| 66778 | for(i=1; i<WAL_NREADER; i++){ |
| 66779 | u32 thisMark = AtomicLoad(pInfo->aReadMark+i); |
| 66780 | if( mxReadMark<=thisMark && thisMark<=mxFrame ){ |
| 66781 | assert( thisMark!=READMARK_NOT_USED ); |
| 66782 | mxReadMark = thisMark; |
| 66783 | mxI = i; |
| 66784 | } |
| @@ -66840,11 +67081,11 @@ | |
| 66840 | ** frame pWal->hdr.mxFrame - then the client would incorrectly assume |
| 66841 | ** that it can read version A from the database file. However, since |
| 66842 | ** we can guarantee that the checkpointer that set nBackfill could not |
| 66843 | ** see any pages past pWal->hdr.mxFrame, this problem does not come up. |
| 66844 | */ |
| 66845 | pWal->minFrame = AtomicLoad(&pInfo->nBackfill)+1; |
| 66846 | walShmBarrier(pWal); |
| 66847 | if( AtomicLoad(pInfo->aReadMark+mxI)!=mxReadMark |
| 66848 | || memcmp((void *)walIndexHdr(pWal), &pWal->hdr, sizeof(WalIndexHdr)) |
| 66849 | ){ |
| 66850 | walUnlockShared(pWal, WAL_READ_LOCK(mxI)); |
| @@ -66855,10 +67096,57 @@ | |
| 66855 | } |
| 66856 | return rc; |
| 66857 | } |
| 66858 | |
| 66859 | #ifdef SQLITE_ENABLE_SNAPSHOT |
| 66860 | /* |
| 66861 | ** Attempt to reduce the value of the WalCkptInfo.nBackfillAttempted |
| 66862 | ** variable so that older snapshots can be accessed. To do this, loop |
| 66863 | ** through all wal frames from nBackfillAttempted to (nBackfill+1), |
| 66864 | ** comparing their content to the corresponding page with the database |
| @@ -66880,84 +67168,47 @@ | |
| 66880 | int rc; |
| 66881 | |
| 66882 | assert( pWal->readLock>=0 ); |
| 66883 | rc = walLockExclusive(pWal, WAL_CKPT_LOCK, 1); |
| 66884 | if( rc==SQLITE_OK ){ |
| 66885 | volatile WalCkptInfo *pInfo = walCkptInfo(pWal); |
| 66886 | int szPage = (int)pWal->szPage; |
| 66887 | i64 szDb; /* Size of db file in bytes */ |
| 66888 | |
| 66889 | rc = sqlite3OsFileSize(pWal->pDbFd, &szDb); |
| 66890 | if( rc==SQLITE_OK ){ |
| 66891 | void *pBuf1 = sqlite3_malloc(szPage); |
| 66892 | void *pBuf2 = sqlite3_malloc(szPage); |
| 66893 | if( pBuf1==0 || pBuf2==0 ){ |
| 66894 | rc = SQLITE_NOMEM; |
| 66895 | }else{ |
| 66896 | u32 i = pInfo->nBackfillAttempted; |
| 66897 | for(i=pInfo->nBackfillAttempted; i>AtomicLoad(&pInfo->nBackfill); i--){ |
| 66898 | WalHashLoc sLoc; /* Hash table location */ |
| 66899 | u32 pgno; /* Page number in db file */ |
| 66900 | i64 iDbOff; /* Offset of db file entry */ |
| 66901 | i64 iWalOff; /* Offset of wal file entry */ |
| 66902 | |
| 66903 | rc = walHashGet(pWal, walFramePage(i), &sLoc); |
| 66904 | if( rc!=SQLITE_OK ) break; |
| 66905 | assert( i - sLoc.iZero - 1 >=0 ); |
| 66906 | pgno = sLoc.aPgno[i-sLoc.iZero-1]; |
| 66907 | iDbOff = (i64)(pgno-1) * szPage; |
| 66908 | |
| 66909 | if( iDbOff+szPage<=szDb ){ |
| 66910 | iWalOff = walFrameOffset(i, szPage) + WAL_FRAME_HDRSIZE; |
| 66911 | rc = sqlite3OsRead(pWal->pWalFd, pBuf1, szPage, iWalOff); |
| 66912 | |
| 66913 | if( rc==SQLITE_OK ){ |
| 66914 | rc = sqlite3OsRead(pWal->pDbFd, pBuf2, szPage, iDbOff); |
| 66915 | } |
| 66916 | |
| 66917 | if( rc!=SQLITE_OK || 0==memcmp(pBuf1, pBuf2, szPage) ){ |
| 66918 | break; |
| 66919 | } |
| 66920 | } |
| 66921 | |
| 66922 | pInfo->nBackfillAttempted = i-1; |
| 66923 | } |
| 66924 | } |
| 66925 | |
| 66926 | sqlite3_free(pBuf1); |
| 66927 | sqlite3_free(pBuf2); |
| 66928 | } |
| 66929 | walUnlockExclusive(pWal, WAL_CKPT_LOCK, 1); |
| 66930 | } |
| 66931 | |
| 66932 | return rc; |
| 66933 | } |
| 66934 | #endif /* SQLITE_ENABLE_SNAPSHOT */ |
| 66935 | |
| 66936 | /* |
| 66937 | ** Begin a read transaction on the database. |
| 66938 | ** |
| 66939 | ** This routine used to be called sqlite3OpenSnapshot() and with good reason: |
| 66940 | ** it takes a snapshot of the state of the WAL and wal-index for the current |
| 66941 | ** instant in time. The current thread will continue to use this snapshot. |
| 66942 | ** Other threads might append new content to the WAL and wal-index but |
| 66943 | ** that extra content is ignored by the current thread. |
| 66944 | ** |
| 66945 | ** If the database contents have changes since the previous read |
| 66946 | ** transaction, then *pChanged is set to 1 before returning. The |
| 66947 | ** Pager layer will use this to know that its cache is stale and |
| 66948 | ** needs to be flushed. |
| 66949 | */ |
| 66950 | SQLITE_PRIVATE int sqlite3WalBeginReadTransaction(Wal *pWal, int *pChanged){ |
| 66951 | int rc; /* Return code */ |
| 66952 | int cnt = 0; /* Number of TryBeginRead attempts */ |
| 66953 | #ifdef SQLITE_ENABLE_SNAPSHOT |
| 66954 | int bChanged = 0; |
| 66955 | WalIndexHdr *pSnapshot = pWal->pSnapshot; |
| 66956 | #endif |
| 66957 | |
| 66958 | assert( pWal->ckptLock==0 ); |
| 66959 | |
| 66960 | #ifdef SQLITE_ENABLE_SNAPSHOT |
| 66961 | if( pSnapshot ){ |
| 66962 | if( memcmp(pSnapshot, &pWal->hdr, sizeof(WalIndexHdr))!=0 ){ |
| 66963 | bChanged = 1; |
| @@ -66976,11 +67227,11 @@ | |
| 66976 | walDisableBlocking(pWal); |
| 66977 | |
| 66978 | if( rc!=SQLITE_OK ){ |
| 66979 | return rc; |
| 66980 | } |
| 66981 | pWal->ckptLock = 1; |
| 66982 | } |
| 66983 | #endif |
| 66984 | |
| 66985 | do{ |
| 66986 | rc = walTryBeginRead(pWal, pChanged, 0, ++cnt); |
| @@ -67040,18 +67291,40 @@ | |
| 67040 | } |
| 67041 | } |
| 67042 | } |
| 67043 | |
| 67044 | /* Release the shared CKPT lock obtained above. */ |
| 67045 | if( pWal->ckptLock ){ |
| 67046 | assert( pSnapshot ); |
| 67047 | walUnlockShared(pWal, WAL_CKPT_LOCK); |
| 67048 | pWal->ckptLock = 0; |
| 67049 | } |
| 67050 | #endif |
| 67051 | return rc; |
| 67052 | } |
| 67053 | |
| 67054 | /* |
| 67055 | ** Finish with a read transaction. All this does is release the |
| 67056 | ** read-lock. |
| 67057 | */ |
| @@ -67069,11 +67342,11 @@ | |
| 67069 | ** to zero. |
| 67070 | ** |
| 67071 | ** Return SQLITE_OK if successful, or an error code if an error occurs. If an |
| 67072 | ** error does occur, the final value of *piRead is undefined. |
| 67073 | */ |
| 67074 | SQLITE_PRIVATE int sqlite3WalFindFrame( |
| 67075 | Wal *pWal, /* WAL handle */ |
| 67076 | Pgno pgno, /* Database page number to read data for */ |
| 67077 | u32 *piRead /* OUT: Frame number (or zero) */ |
| 67078 | ){ |
| 67079 | u32 iRead = 0; /* If !=0, WAL frame to return data from */ |
| @@ -67132,10 +67405,11 @@ | |
| 67132 | if( rc!=SQLITE_OK ){ |
| 67133 | return rc; |
| 67134 | } |
| 67135 | nCollide = HASHTABLE_NSLOT; |
| 67136 | iKey = walHash(pgno); |
| 67137 | while( (iH = AtomicLoad(&sLoc.aHash[iKey]))!=0 ){ |
| 67138 | u32 iFrame = iH + sLoc.iZero; |
| 67139 | if( iFrame<=iLast && iFrame>=pWal->minFrame && sLoc.aPgno[iH-1]==pgno ){ |
| 67140 | assert( iFrame>iRead || CORRUPT_DB ); |
| 67141 | iRead = iFrame; |
| @@ -67167,10 +67441,34 @@ | |
| 67167 | #endif |
| 67168 | |
| 67169 | *piRead = iRead; |
| 67170 | return SQLITE_OK; |
| 67171 | } |
| 67172 | |
| 67173 | /* |
| 67174 | ** Read the contents of frame iRead from the wal file into buffer pOut |
| 67175 | ** (which is nOut bytes in size). Return SQLITE_OK if successful, or an |
| 67176 | ** error code otherwise. |
| @@ -67249,16 +67547,21 @@ | |
| 67249 | |
| 67250 | /* If another connection has written to the database file since the |
| 67251 | ** time the read transaction on this connection was started, then |
| 67252 | ** the write is disallowed. |
| 67253 | */ |
| 67254 | if( memcmp(&pWal->hdr, (void *)walIndexHdr(pWal), sizeof(WalIndexHdr))!=0 ){ |
| 67255 | walUnlockExclusive(pWal, WAL_WRITE_LOCK, 1); |
| 67256 | pWal->writeLock = 0; |
| 67257 | rc = SQLITE_BUSY_SNAPSHOT; |
| 67258 | } |
| 67259 | |
| 67260 | return rc; |
| 67261 | } |
| 67262 | |
| 67263 | /* |
| 67264 | ** End a write transaction. The commit has already been done. This |
| @@ -67290,34 +67593,37 @@ | |
| 67290 | int rc = SQLITE_OK; |
| 67291 | if( ALWAYS(pWal->writeLock) ){ |
| 67292 | Pgno iMax = pWal->hdr.mxFrame; |
| 67293 | Pgno iFrame; |
| 67294 | |
| 67295 | /* Restore the clients cache of the wal-index header to the state it |
| 67296 | ** was in before the client began writing to the database. |
| 67297 | */ |
| 67298 | memcpy(&pWal->hdr, (void *)walIndexHdr(pWal), sizeof(WalIndexHdr)); |
| 67299 | |
| 67300 | for(iFrame=pWal->hdr.mxFrame+1; |
| 67301 | ALWAYS(rc==SQLITE_OK) && iFrame<=iMax; |
| 67302 | iFrame++ |
| 67303 | ){ |
| 67304 | /* This call cannot fail. Unless the page for which the page number |
| 67305 | ** is passed as the second argument is (a) in the cache and |
| 67306 | ** (b) has an outstanding reference, then xUndo is either a no-op |
| 67307 | ** (if (a) is false) or simply expels the page from the cache (if (b) |
| 67308 | ** is false). |
| 67309 | ** |
| 67310 | ** If the upper layer is doing a rollback, it is guaranteed that there |
| 67311 | ** are no outstanding references to any page other than page 1. And |
| 67312 | ** page 1 is never written to the log until the transaction is |
| 67313 | ** committed. As a result, the call to xUndo may not fail. |
| 67314 | */ |
| 67315 | assert( walFramePgno(pWal, iFrame)!=1 ); |
| 67316 | rc = xUndo(pUndoCtx, walFramePgno(pWal, iFrame)); |
| 67317 | } |
| 67318 | if( iMax!=pWal->hdr.mxFrame ) walCleanupHash(pWal); |
| 67319 | } |
| 67320 | return rc; |
| 67321 | } |
| 67322 | |
| 67323 | /* |
| @@ -67357,11 +67663,14 @@ | |
| 67357 | |
| 67358 | if( aWalData[0]<pWal->hdr.mxFrame ){ |
| 67359 | pWal->hdr.mxFrame = aWalData[0]; |
| 67360 | pWal->hdr.aFrameCksum[0] = aWalData[1]; |
| 67361 | pWal->hdr.aFrameCksum[1] = aWalData[2]; |
| 67362 | walCleanupHash(pWal); |
| 67363 | } |
| 67364 | |
| 67365 | return rc; |
| 67366 | } |
| 67367 | |
| @@ -67538,11 +67847,11 @@ | |
| 67538 | |
| 67539 | /* |
| 67540 | ** Write a set of frames to the log. The caller must hold the write-lock |
| 67541 | ** on the log file (obtained using sqlite3WalBeginWriteTransaction()). |
| 67542 | */ |
| 67543 | SQLITE_PRIVATE int sqlite3WalFrames( |
| 67544 | Wal *pWal, /* Wal handle to write to */ |
| 67545 | int szPage, /* Database page-size in bytes */ |
| 67546 | PgHdr *pList, /* List of dirty pages to write */ |
| 67547 | Pgno nTruncate, /* Database size after this commit */ |
| 67548 | int isCommit, /* True if this is a commit */ |
| @@ -67649,11 +67958,11 @@ | |
| 67649 | ** the current transaction. If so, overwrite the existing frame and |
| 67650 | ** set Wal.writeLock to WAL_WRITELOCK_RECKSUM - indicating that |
| 67651 | ** checksums must be recomputed when the transaction is committed. */ |
| 67652 | if( iFirst && (p->pDirty || isCommit==0) ){ |
| 67653 | u32 iWrite = 0; |
| 67654 | VVA_ONLY(rc =) sqlite3WalFindFrame(pWal, p->pgno, &iWrite); |
| 67655 | assert( rc==SQLITE_OK || iWrite==0 ); |
| 67656 | if( iWrite>=iFirst ){ |
| 67657 | i64 iOff = walFrameOffset(iWrite, szPage) + WAL_FRAME_HDRSIZE; |
| 67658 | void *pData; |
| 67659 | if( pWal->iReCksum==0 || iWrite<pWal->iReCksum ){ |
| @@ -67767,10 +68076,33 @@ | |
| 67767 | } |
| 67768 | |
| 67769 | WALTRACE(("WAL%p: frame write %s\n", pWal, rc ? "failed" : "ok")); |
| 67770 | return rc; |
| 67771 | } |
| 67772 | |
| 67773 | /* |
| 67774 | ** This routine is called to implement sqlite3_wal_checkpoint() and |
| 67775 | ** related interfaces. |
| 67776 | ** |
| @@ -67847,34 +68179,37 @@ | |
| 67847 | } |
| 67848 | } |
| 67849 | |
| 67850 | |
| 67851 | /* Read the wal-index header. */ |
| 67852 | if( rc==SQLITE_OK ){ |
| 67853 | walDisableBlocking(pWal); |
| 67854 | rc = walIndexReadHdr(pWal, &isChanged); |
| 67855 | (void)walEnableBlocking(pWal); |
| 67856 | if( isChanged && pWal->pDbFd->pMethods->iVersion>=3 ){ |
| 67857 | sqlite3OsUnfetch(pWal->pDbFd, 0, 0); |
| 67858 | } |
| 67859 | } |
| 67860 | |
| 67861 | /* Copy data from the log to the database file. */ |
| 67862 | if( rc==SQLITE_OK ){ |
| 67863 | |
| 67864 | if( pWal->hdr.mxFrame && walPagesize(pWal)!=nBuf ){ |
| 67865 | rc = SQLITE_CORRUPT_BKPT; |
| 67866 | }else{ |
| 67867 | rc = walCheckpoint(pWal, db, eMode2, xBusy2, pBusyArg, sync_flags, zBuf); |
| 67868 | } |
| 67869 | |
| 67870 | /* If no error occurred, set the output variables. */ |
| 67871 | if( rc==SQLITE_OK || rc==SQLITE_BUSY ){ |
| 67872 | if( pnLog ) *pnLog = (int)pWal->hdr.mxFrame; |
| 67873 | if( pnCkpt ) *pnCkpt = (int)(walCkptInfo(pWal)->nBackfill); |
| 67874 | } |
| 67875 | } |
| 67876 | |
| 67877 | if( isChanged ){ |
| 67878 | /* If a new wal-index header was loaded before the checkpoint was |
| 67879 | ** performed, then the pager-cache associated with pWal is now |
| 67880 | ** out of date. So zero the cached wal-index header to ensure that |
| @@ -67947,11 +68282,13 @@ | |
| 67947 | ** prior error while attempting to acquire are read-lock. This cannot |
| 67948 | ** happen if the connection is actually in exclusive mode (as no xShmLock |
| 67949 | ** locks are taken in this case). Nor should the pager attempt to |
| 67950 | ** upgrade to exclusive-mode following such an error. |
| 67951 | */ |
| 67952 | assert( pWal->readLock>=0 || pWal->lockError ); |
| 67953 | assert( pWal->readLock>=0 || (op<=0 && pWal->exclusiveMode==0) ); |
| 67954 | |
| 67955 | if( op==0 ){ |
| 67956 | if( pWal->exclusiveMode!=WAL_NORMAL_MODE ){ |
| 67957 | pWal->exclusiveMode = WAL_NORMAL_MODE; |
| @@ -68048,20 +68385,23 @@ | |
| 68048 | ** occurs (any value other than SQLITE_OK is returned), the CHECKPOINTER |
| 68049 | ** lock is released before returning. |
| 68050 | */ |
| 68051 | SQLITE_PRIVATE int sqlite3WalSnapshotCheck(Wal *pWal, sqlite3_snapshot *pSnapshot){ |
| 68052 | int rc; |
| 68053 | rc = walLockShared(pWal, WAL_CKPT_LOCK); |
| 68054 | if( rc==SQLITE_OK ){ |
| 68055 | WalIndexHdr *pNew = (WalIndexHdr*)pSnapshot; |
| 68056 | if( memcmp(pNew->aSalt, pWal->hdr.aSalt, sizeof(pWal->hdr.aSalt)) |
| 68057 | || pNew->mxFrame<walCkptInfo(pWal)->nBackfillAttempted |
| 68058 | ){ |
| 68059 | rc = SQLITE_ERROR_SNAPSHOT; |
| 68060 | walUnlockShared(pWal, WAL_CKPT_LOCK); |
| 68061 | } |
| 68062 | } |
| 68063 | return rc; |
| 68064 | } |
| 68065 | |
| 68066 | /* |
| 68067 | ** Release a lock obtained by an earlier successful call to |
| @@ -86698,10 +87038,11 @@ | |
| 86698 | } |
| 86699 | if( rc==SQLITE_BUSY && p->readOnly ){ |
| 86700 | sqlite3VdbeLeave(p); |
| 86701 | return SQLITE_BUSY; |
| 86702 | }else if( rc!=SQLITE_OK ){ |
| 86703 | p->rc = rc; |
| 86704 | sqlite3RollbackAll(db, SQLITE_OK); |
| 86705 | p->nChange = 0; |
| 86706 | }else{ |
| 86707 | db->nDeferredCons = 0; |
| @@ -93737,14 +94078,14 @@ | |
| 93737 | ** This opcode must follow an OP_Lt or OP_Gt comparison operator. There |
| 93738 | ** can be zero or more OP_ReleaseReg opcodes intervening, but no other |
| 93739 | ** opcodes are allowed to occur between this instruction and the previous |
| 93740 | ** OP_Lt or OP_Gt. |
| 93741 | ** |
| 93742 | ** If result of an OP_Eq comparison on the same two operands as the |
| 93743 | ** prior OP_Lt or OP_Gt would have been true, then jump to P2. |
| 93744 | ** If the result of an OP_Eq comparison on the two previous |
| 93745 | ** operands would have been false or NULL, then fall through. |
| 93746 | */ |
| 93747 | case OP_ElseEq: { /* same as TK_ESCAPE, jump */ |
| 93748 | |
| 93749 | #ifdef SQLITE_DEBUG |
| 93750 | /* Verify the preconditions of this opcode - that it follows an OP_Lt or |
| @@ -94170,11 +94511,11 @@ | |
| 94170 | } |
| 94171 | |
| 94172 | /* Opcode: ZeroOrNull P1 P2 P3 * * |
| 94173 | ** Synopsis: r[P2] = 0 OR NULL |
| 94174 | ** |
| 94175 | ** If all both registers P1 and P3 are NOT NULL, then store a zero in |
| 94176 | ** register P2. If either registers P1 or P3 are NULL then put |
| 94177 | ** a NULL in register P2. |
| 94178 | */ |
| 94179 | case OP_ZeroOrNull: { /* in1, in2, out2, in3 */ |
| 94180 | if( (aMem[pOp->p1].flags & MEM_Null)!=0 |
| @@ -96571,17 +96912,17 @@ | |
| 96571 | ** record. Cursor P1 is an index btree. P2 is a jump destination. |
| 96572 | ** In other words, the operands to this opcode are the same as the |
| 96573 | ** operands to OP_NotFound and OP_IdxGT. |
| 96574 | ** |
| 96575 | ** This opcode is an optimization attempt only. If this opcode always |
| 96576 | ** falls through, the correct answer is still obtained, but extra works |
| 96577 | ** is performed. |
| 96578 | ** |
| 96579 | ** A value of N in the seekHit flag of cursor P1 means that there exists |
| 96580 | ** a key P3:N that will match some record in the index. We want to know |
| 96581 | ** if it is possible for a record P3:P4 to match some record in the |
| 96582 | ** index. If it is not possible, we can skips some work. So if seekHit |
| 96583 | ** is less than P4, attempt to find out if a match is possible by running |
| 96584 | ** OP_NotFound. |
| 96585 | ** |
| 96586 | ** This opcode is used in IN clause processing for a multi-column key. |
| 96587 | ** If an IN clause is attached to an element of the key other than the |
| @@ -97143,14 +97484,14 @@ | |
| 97143 | ** it is ok to delete a record from within a Next loop. If |
| 97144 | ** OPFLAG_SAVEPOSITION bit of P5 is clear, then the cursor will be |
| 97145 | ** left in an undefined state. |
| 97146 | ** |
| 97147 | ** If the OPFLAG_AUXDELETE bit is set on P5, that indicates that this |
| 97148 | ** delete one of several associated with deleting a table row and all its |
| 97149 | ** associated index entries. Exactly one of those deletes is the "primary" |
| 97150 | ** delete. The others are all on OPFLAG_FORDELETE cursors or else are |
| 97151 | ** marked with the AUXDELETE flag. |
| 97152 | ** |
| 97153 | ** If the OPFLAG_NCHANGE flag of P2 (NB: P2 not P5) is set, then the row |
| 97154 | ** change count is incremented (otherwise not). |
| 97155 | ** |
| 97156 | ** P1 must not be pseudo-table. It has to be a real table with |
| @@ -97318,11 +97659,11 @@ | |
| 97318 | ** Synopsis: r[P2]=data |
| 97319 | ** |
| 97320 | ** Write into register P2 the current sorter data for sorter cursor P1. |
| 97321 | ** Then clear the column header cache on cursor P3. |
| 97322 | ** |
| 97323 | ** This opcode is normally use to move a record out of the sorter and into |
| 97324 | ** a register that is the source for a pseudo-table cursor created using |
| 97325 | ** OpenPseudo. That pseudo-table cursor is the one that is identified by |
| 97326 | ** parameter P3. Clearing the P3 column cache as part of this opcode saves |
| 97327 | ** us from having to issue a separate NullRow instruction to clear that cache. |
| 97328 | */ |
| @@ -98127,11 +98468,11 @@ | |
| 98127 | ** |
| 98128 | ** Delete an entire database table or index whose root page in the database |
| 98129 | ** file is given by P1. |
| 98130 | ** |
| 98131 | ** The table being destroyed is in the main database file if P3==0. If |
| 98132 | ** P3==1 then the table to be clear is in the auxiliary database file |
| 98133 | ** that is used to store tables create using CREATE TEMPORARY TABLE. |
| 98134 | ** |
| 98135 | ** If AUTOVACUUM is enabled then it is possible that another root page |
| 98136 | ** might be moved into the newly deleted root page in order to keep all |
| 98137 | ** root pages contiguous at the beginning of the database. The former |
| @@ -98187,12 +98528,12 @@ | |
| 98187 | ** |
| 98188 | ** Delete all contents of the database table or index whose root page |
| 98189 | ** in the database file is given by P1. But, unlike Destroy, do not |
| 98190 | ** remove the table or index from the database file. |
| 98191 | ** |
| 98192 | ** The table being clear is in the main database file if P2==0. If |
| 98193 | ** P2==1 then the table to be clear is in the auxiliary database file |
| 98194 | ** that is used to store tables create using CREATE TEMPORARY TABLE. |
| 98195 | ** |
| 98196 | ** If the P3 value is non-zero, then the row change count is incremented |
| 98197 | ** by the number of rows in the table being cleared. If P3 is greater |
| 98198 | ** than zero, then the value stored in register P3 is also incremented |
| @@ -110966,14 +111307,17 @@ | |
| 110966 | int iTable, /* The cursor pointing to the table */ |
| 110967 | int iReg, /* Store results here */ |
| 110968 | u8 p5 /* P5 value for OP_Column + FLAGS */ |
| 110969 | ){ |
| 110970 | assert( pParse->pVdbe!=0 ); |
| 110971 | sqlite3ExprCodeGetColumnOfTable(pParse->pVdbe, pTab, iTable, iColumn, iReg); |
| 110972 | if( p5 ){ |
| 110973 | VdbeOp *pOp = sqlite3VdbeGetLastOp(pParse->pVdbe); |
| 110974 | if( pOp->opcode==OP_Column ) pOp->p5 = p5; |
| 110975 | } |
| 110976 | return iReg; |
| 110977 | } |
| 110978 | |
| 110979 | /* |
| @@ -141288,10 +141632,20 @@ | |
| 141288 | testcase( eDest==SRT_Table ); |
| 141289 | testcase( eDest==SRT_EphemTab ); |
| 141290 | testcase( eDest==SRT_Fifo ); |
| 141291 | testcase( eDest==SRT_DistFifo ); |
| 141292 | sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nResultCol, r1+nPrefixReg); |
| 141293 | #ifndef SQLITE_OMIT_CTE |
| 141294 | if( eDest==SRT_DistFifo ){ |
| 141295 | /* If the destination is DistFifo, then cursor (iParm+1) is open |
| 141296 | ** on an ephemeral index. If the current row is already present |
| 141297 | ** in the index, do not write it to the output. If not, add the |
| @@ -151336,11 +151690,13 @@ | |
| 151336 | if( aXRef[i]>=0 ){ |
| 151337 | pList = sqlite3ExprListAppend(pParse, pList, |
| 151338 | sqlite3ExprDup(db, pChanges->a[aXRef[i]].pExpr, 0) |
| 151339 | ); |
| 151340 | }else{ |
| 151341 | pList = sqlite3ExprListAppend(pParse, pList, exprRowColumn(pParse, i)); |
| 151342 | } |
| 151343 | } |
| 151344 | |
| 151345 | updateFromSelect(pParse, ephemTab, pPk, pList, pSrc, pWhere, 0, 0); |
| 151346 | sqlite3ExprListDelete(db, pList); |
| @@ -175166,11 +175522,11 @@ | |
| 175166 | } |
| 175167 | case CC_DIGIT: { |
| 175168 | testcase( z[0]=='0' ); testcase( z[0]=='1' ); testcase( z[0]=='2' ); |
| 175169 | testcase( z[0]=='3' ); testcase( z[0]=='4' ); testcase( z[0]=='5' ); |
| 175170 | testcase( z[0]=='6' ); testcase( z[0]=='7' ); testcase( z[0]=='8' ); |
| 175171 | testcase( z[0]=='9' ); |
| 175172 | *tokenType = TK_INTEGER; |
| 175173 | #ifndef SQLITE_OMIT_HEX_INTEGER |
| 175174 | if( z[0]=='0' && (z[1]=='x' || z[1]=='X') && sqlite3Isxdigit(z[2]) ){ |
| 175175 | for(i=3; sqlite3Isxdigit(z[i]); i++){} |
| 175176 | return i; |
| @@ -203827,11 +204183,17 @@ | |
| 203827 | int argc, |
| 203828 | sqlite3_value **argv |
| 203829 | ){ |
| 203830 | JsonParse *p; /* The parse */ |
| 203831 | UNUSED_PARAMETER(argc); |
| 203832 | if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return; |
| 203833 | p = jsonParseCached(ctx, argv[0], 0, 0); |
| 203834 | if( p==0 || p->oom ){ |
| 203835 | sqlite3_result_error_nomem(ctx); |
| 203836 | sqlite3_free(p); |
| 203837 | }else{ |
| @@ -225917,28 +226279,28 @@ | |
| 225917 | |
| 225918 | /* Create a new tokenizer */ |
| 225919 | int (*xCreateTokenizer)( |
| 225920 | fts5_api *pApi, |
| 225921 | const char *zName, |
| 225922 | void *pContext, |
| 225923 | fts5_tokenizer *pTokenizer, |
| 225924 | void (*xDestroy)(void*) |
| 225925 | ); |
| 225926 | |
| 225927 | /* Find an existing tokenizer */ |
| 225928 | int (*xFindTokenizer)( |
| 225929 | fts5_api *pApi, |
| 225930 | const char *zName, |
| 225931 | void **ppContext, |
| 225932 | fts5_tokenizer *pTokenizer |
| 225933 | ); |
| 225934 | |
| 225935 | /* Create a new auxiliary function */ |
| 225936 | int (*xCreateFunction)( |
| 225937 | fts5_api *pApi, |
| 225938 | const char *zName, |
| 225939 | void *pContext, |
| 225940 | fts5_extension_function xFunction, |
| 225941 | void (*xDestroy)(void*) |
| 225942 | ); |
| 225943 | }; |
| 225944 | |
| @@ -244178,11 +244540,11 @@ | |
| 244178 | /* Filter out attempts to run UPDATE or DELETE on contentless tables. |
| 244179 | ** This is not suported. Except - DELETE is supported if the CREATE |
| 244180 | ** VIRTUAL TABLE statement contained "contentless_delete=1". */ |
| 244181 | if( eType0==SQLITE_INTEGER |
| 244182 | && pConfig->eContent==FTS5_CONTENT_NONE |
| 244183 | && (nArg>1 || pConfig->bContentlessDelete==0) |
| 244184 | ){ |
| 244185 | pTab->p.base.zErrMsg = sqlite3_mprintf( |
| 244186 | "cannot %s contentless fts5 table: %s", |
| 244187 | (nArg>1 ? "UPDATE" : "DELETE from"), pConfig->zName |
| 244188 | ); |
| @@ -245033,10 +245395,16 @@ | |
| 245033 | rc = fts5SeekCursor(pCsr, 1); |
| 245034 | if( rc==SQLITE_OK ){ |
| 245035 | sqlite3_result_value(pCtx, sqlite3_column_value(pCsr->pStmt, iCol+1)); |
| 245036 | } |
| 245037 | pConfig->pzErrmsg = 0; |
| 245038 | } |
| 245039 | return rc; |
| 245040 | } |
| 245041 | |
| 245042 | |
| @@ -245315,11 +245683,11 @@ | |
| 245315 | int nArg, /* Number of args */ |
| 245316 | sqlite3_value **apUnused /* Function arguments */ |
| 245317 | ){ |
| 245318 | assert( nArg==0 ); |
| 245319 | UNUSED_PARAM2(nArg, apUnused); |
| 245320 | sqlite3_result_text(pCtx, "fts5: 2023-08-04 13:19:11 ba7a66db13b28da0b41f03be825a593608474a5ebda89e12d58d89db709b8f65", -1, SQLITE_TRANSIENT); |
| 245321 | } |
| 245322 | |
| 245323 | /* |
| 245324 | ** Return true if zName is the extension on one of the shadow tables used |
| 245325 | ** by this module. |
| 245326 |
| --- extsrc/sqlite3.c | |
| +++ extsrc/sqlite3.c | |
| @@ -1,8 +1,8 @@ | |
| 1 | /****************************************************************************** |
| 2 | ** This file is an amalgamation of many separate C source files from SQLite |
| 3 | ** version 3.43.0. By combining all the individual C code files into this |
| 4 | ** single large file, the entire code can be compiled as a single translation |
| 5 | ** unit. This allows many compilers to do optimizations that would not be |
| 6 | ** possible if the files were compiled separately. Performance improvements |
| 7 | ** of 5% or more are commonly seen when SQLite is compiled as a single |
| 8 | ** translation unit. |
| @@ -16,11 +16,11 @@ | |
| 16 | ** if you want a wrapper to interface SQLite with your choice of programming |
| 17 | ** language. The code for the "sqlite3" command-line shell is also in a |
| 18 | ** separate file. This file contains only code for the core SQLite library. |
| 19 | ** |
| 20 | ** The content in this amalgamation comes from Fossil check-in |
| 21 | ** bc0693c4633f545f09dbee702e25354504b. |
| 22 | */ |
| 23 | #define SQLITE_CORE 1 |
| 24 | #define SQLITE_AMALGAMATION 1 |
| 25 | #ifndef SQLITE_PRIVATE |
| 26 | # define SQLITE_PRIVATE static |
| @@ -459,11 +459,11 @@ | |
| 459 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 460 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 461 | */ |
| 462 | #define SQLITE_VERSION "3.43.0" |
| 463 | #define SQLITE_VERSION_NUMBER 3043000 |
| 464 | #define SQLITE_SOURCE_ID "2023-08-11 22:40:06 3bc0693c4633f545f09dbee702e25354504b20836373a068447e6c61cb2ebd79" |
| 465 | |
| 466 | /* |
| 467 | ** CAPI3REF: Run-Time Library Version Numbers |
| 468 | ** KEYWORDS: sqlite3_version sqlite3_sourceid |
| 469 | ** |
| @@ -839,10 +839,11 @@ | |
| 839 | #define SQLITE_IOERR_BEGIN_ATOMIC (SQLITE_IOERR | (29<<8)) |
| 840 | #define SQLITE_IOERR_COMMIT_ATOMIC (SQLITE_IOERR | (30<<8)) |
| 841 | #define SQLITE_IOERR_ROLLBACK_ATOMIC (SQLITE_IOERR | (31<<8)) |
| 842 | #define SQLITE_IOERR_DATA (SQLITE_IOERR | (32<<8)) |
| 843 | #define SQLITE_IOERR_CORRUPTFS (SQLITE_IOERR | (33<<8)) |
| 844 | #define SQLITE_IOERR_IN_PAGE (SQLITE_IOERR | (34<<8)) |
| 845 | #define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8)) |
| 846 | #define SQLITE_LOCKED_VTAB (SQLITE_LOCKED | (2<<8)) |
| 847 | #define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8)) |
| 848 | #define SQLITE_BUSY_SNAPSHOT (SQLITE_BUSY | (2<<8)) |
| 849 | #define SQLITE_BUSY_TIMEOUT (SQLITE_BUSY | (3<<8)) |
| @@ -13394,28 +13395,28 @@ | |
| 13395 | |
| 13396 | /* Create a new tokenizer */ |
| 13397 | int (*xCreateTokenizer)( |
| 13398 | fts5_api *pApi, |
| 13399 | const char *zName, |
| 13400 | void *pUserData, |
| 13401 | fts5_tokenizer *pTokenizer, |
| 13402 | void (*xDestroy)(void*) |
| 13403 | ); |
| 13404 | |
| 13405 | /* Find an existing tokenizer */ |
| 13406 | int (*xFindTokenizer)( |
| 13407 | fts5_api *pApi, |
| 13408 | const char *zName, |
| 13409 | void **ppUserData, |
| 13410 | fts5_tokenizer *pTokenizer |
| 13411 | ); |
| 13412 | |
| 13413 | /* Create a new auxiliary function */ |
| 13414 | int (*xCreateFunction)( |
| 13415 | fts5_api *pApi, |
| 13416 | const char *zName, |
| 13417 | void *pUserData, |
| 13418 | fts5_extension_function xFunction, |
| 13419 | void (*xDestroy)(void*) |
| 13420 | ); |
| 13421 | }; |
| 13422 | |
| @@ -14630,11 +14631,11 @@ | |
| 14631 | #define SQLITE_WITHIN(P,S,E) (((uptr)(P)>=(uptr)(S))&&((uptr)(P)<(uptr)(E))) |
| 14632 | |
| 14633 | /* |
| 14634 | ** P is one byte past the end of a large buffer. Return true if a span of bytes |
| 14635 | ** between S..E crosses the end of that buffer. In other words, return true |
| 14636 | ** if the sub-buffer S..E-1 overflows the buffer whose last byte is P-1. |
| 14637 | ** |
| 14638 | ** S is the start of the span. E is one byte past the end of end of span. |
| 14639 | ** |
| 14640 | ** P |
| 14641 | ** |-----------------| FALSE |
| @@ -14993,11 +14994,10 @@ | |
| 14994 | typedef struct Column Column; |
| 14995 | typedef struct Cte Cte; |
| 14996 | typedef struct CteUse CteUse; |
| 14997 | typedef struct Db Db; |
| 14998 | typedef struct DbFixer DbFixer; |
| 14999 | typedef struct Schema Schema; |
| 15000 | typedef struct Expr Expr; |
| 15001 | typedef struct ExprList ExprList; |
| 15002 | typedef struct FKey FKey; |
| 15003 | typedef struct FpDecode FpDecode; |
| @@ -15654,10 +15654,14 @@ | |
| 15654 | void enable_simulated_io_errors(void); |
| 15655 | #else |
| 15656 | # define disable_simulated_io_errors() |
| 15657 | # define enable_simulated_io_errors() |
| 15658 | #endif |
| 15659 | |
| 15660 | #ifdef SQLITE_USE_SEH |
| 15661 | SQLITE_PRIVATE int sqlite3PagerWalSystemErrno(Pager*); |
| 15662 | #endif |
| 15663 | |
| 15664 | #endif /* SQLITE_PAGER_H */ |
| 15665 | |
| 15666 | /************** End of pager.h ***********************************************/ |
| 15667 | /************** Continuing where we left off in sqliteInt.h ******************/ |
| @@ -19430,10 +19434,13 @@ | |
| 19434 | yDbMask cookieMask; /* Bitmask of schema verified databases */ |
| 19435 | int regRowid; /* Register holding rowid of CREATE TABLE entry */ |
| 19436 | int regRoot; /* Register holding root page number for new objects */ |
| 19437 | int nMaxArg; /* Max args passed to user function by sub-program */ |
| 19438 | int nSelect; /* Number of SELECT stmts. Counter for Select.selId */ |
| 19439 | #ifndef SQLITE_OMIT_PROGRESS_CALLBACK |
| 19440 | u32 nProgressSteps; /* xProgress steps taken during sqlite3_prepare() */ |
| 19441 | #endif |
| 19442 | #ifndef SQLITE_OMIT_SHARED_CACHE |
| 19443 | int nTableLock; /* Number of locks in aTableLock */ |
| 19444 | TableLock *aTableLock; /* Required table locks for shared-cache mode */ |
| 19445 | #endif |
| 19446 | AutoincInfo *pAinc; /* Information about AUTOINCREMENT counters */ |
| @@ -19443,16 +19450,13 @@ | |
| 19450 | ParseCleanup *pCleanup; /* List of cleanup operations to run after parse */ |
| 19451 | union { |
| 19452 | int addrCrTab; /* Address of OP_CreateBtree on CREATE TABLE */ |
| 19453 | Returning *pReturning; /* The RETURNING clause */ |
| 19454 | } u1; |
| 19455 | u32 oldmask; /* Mask of old.* columns referenced */ |
| 19456 | u32 newmask; /* Mask of new.* columns referenced */ |
| 19457 | LogEst nQueryLoop; /* Est number of iterations of a query (10*log2(N)) */ |
| 19458 | u8 eTriggerOp; /* TK_UPDATE, TK_INSERT or TK_DELETE */ |
| 19459 | u8 bReturning; /* Coding a RETURNING trigger */ |
| 19460 | u8 eOrconf; /* Default ON CONFLICT policy for trigger steps */ |
| 19461 | u8 disableTriggers; /* True to disable triggers */ |
| 19462 | |
| @@ -21503,13 +21507,10 @@ | |
| 21507 | "32BIT_ROWID", |
| 21508 | #endif |
| 21509 | #ifdef SQLITE_4_BYTE_ALIGNED_MALLOC |
| 21510 | "4_BYTE_ALIGNED_MALLOC", |
| 21511 | #endif |
| 21512 | #ifdef SQLITE_ALLOW_COVERING_INDEX_SCAN |
| 21513 | # if SQLITE_ALLOW_COVERING_INDEX_SCAN != 1 |
| 21514 | "ALLOW_COVERING_INDEX_SCAN=" CTIMEOPT_VAL(SQLITE_ALLOW_COVERING_INDEX_SCAN), |
| 21515 | # endif |
| 21516 | #endif |
| @@ -21841,10 +21842,13 @@ | |
| 21842 | #ifdef SQLITE_INT64_TYPE |
| 21843 | "INT64_TYPE", |
| 21844 | #endif |
| 21845 | #ifdef SQLITE_INTEGRITY_CHECK_ERROR_MAX |
| 21846 | "INTEGRITY_CHECK_ERROR_MAX=" CTIMEOPT_VAL(SQLITE_INTEGRITY_CHECK_ERROR_MAX), |
| 21847 | #endif |
| 21848 | #ifdef SQLITE_LEGACY_JSON_VALID |
| 21849 | "LEGACY_JSON_VALID", |
| 21850 | #endif |
| 21851 | #ifdef SQLITE_LIKE_DOESNT_MATCH_BLOBS |
| 21852 | "LIKE_DOESNT_MATCH_BLOBS", |
| 21853 | #endif |
| 21854 | #ifdef SQLITE_LOCK_TRACE |
| @@ -34295,10 +34299,27 @@ | |
| 34299 | ** Load the sqlite3.iSysErrno field if that is an appropriate thing |
| 34300 | ** to do based on the SQLite error code in rc. |
| 34301 | */ |
| 34302 | SQLITE_PRIVATE void sqlite3SystemError(sqlite3 *db, int rc){ |
| 34303 | if( rc==SQLITE_IOERR_NOMEM ) return; |
| 34304 | #ifdef SQLITE_USE_SEH |
| 34305 | if( rc==SQLITE_IOERR_IN_PAGE ){ |
| 34306 | int ii; |
| 34307 | int iErr; |
| 34308 | sqlite3BtreeEnterAll(db); |
| 34309 | for(ii=0; ii<db->nDb; ii++){ |
| 34310 | if( db->aDb[ii].pBt ){ |
| 34311 | iErr = sqlite3PagerWalSystemErrno(sqlite3BtreePager(db->aDb[ii].pBt)); |
| 34312 | if( iErr ){ |
| 34313 | db->iSysErrno = iErr; |
| 34314 | } |
| 34315 | } |
| 34316 | } |
| 34317 | sqlite3BtreeLeaveAll(db); |
| 34318 | return; |
| 34319 | } |
| 34320 | #endif |
| 34321 | rc &= 0xff; |
| 34322 | if( rc==SQLITE_CANTOPEN || rc==SQLITE_IOERR ){ |
| 34323 | db->iSysErrno = sqlite3OsGetLastError(db->pVfs); |
| 34324 | } |
| 34325 | } |
| @@ -56206,10 +56227,14 @@ | |
| 56227 | |
| 56228 | #ifdef SQLITE_ENABLE_SETLK_TIMEOUT |
| 56229 | SQLITE_PRIVATE int sqlite3WalWriteLock(Wal *pWal, int bLock); |
| 56230 | SQLITE_PRIVATE void sqlite3WalDb(Wal *pWal, sqlite3 *db); |
| 56231 | #endif |
| 56232 | |
| 56233 | #ifdef SQLITE_USE_SEH |
| 56234 | SQLITE_PRIVATE int sqlite3WalSystemErrno(Wal*); |
| 56235 | #endif |
| 56236 | |
| 56237 | #endif /* ifndef SQLITE_OMIT_WAL */ |
| 56238 | #endif /* SQLITE_WAL_H */ |
| 56239 | |
| 56240 | /************** End of wal.h *************************************************/ |
| @@ -63919,10 +63944,16 @@ | |
| 63944 | SQLITE_PRIVATE int sqlite3PagerWalFramesize(Pager *pPager){ |
| 63945 | assert( pPager->eState>=PAGER_READER ); |
| 63946 | return sqlite3WalFramesize(pPager->pWal); |
| 63947 | } |
| 63948 | #endif |
| 63949 | |
| 63950 | #ifdef SQLITE_USE_SEH |
| 63951 | SQLITE_PRIVATE int sqlite3PagerWalSystemErrno(Pager *pPager){ |
| 63952 | return sqlite3WalSystemErrno(pPager->pWal); |
| 63953 | } |
| 63954 | #endif |
| 63955 | |
| 63956 | #endif /* SQLITE_OMIT_DISKIO */ |
| 63957 | |
| 63958 | /************** End of pager.c ***********************************************/ |
| 63959 | /************** Begin file wal.c *********************************************/ |
| @@ -64454,11 +64485,17 @@ | |
| 64485 | WalIndexHdr hdr; /* Wal-index header for current transaction */ |
| 64486 | u32 minFrame; /* Ignore wal frames before this one */ |
| 64487 | u32 iReCksum; /* On commit, recalculate checksums from here */ |
| 64488 | const char *zWalName; /* Name of WAL file */ |
| 64489 | u32 nCkpt; /* Checkpoint sequence counter in the wal-header */ |
| 64490 | #ifdef SQLITE_USE_SEH |
| 64491 | u32 lockMask; /* Mask of locks held */ |
| 64492 | void *pFree; /* Pointer to sqlite3_free() if exception thrown */ |
| 64493 | int iSysErrno; /* System error code following exception */ |
| 64494 | #endif |
| 64495 | #ifdef SQLITE_DEBUG |
| 64496 | int nSehTry; /* Number of nested SEH_TRY{} blocks */ |
| 64497 | u8 lockError; /* True if a locking error has occurred */ |
| 64498 | #endif |
| 64499 | #ifdef SQLITE_ENABLE_SNAPSHOT |
| 64500 | WalIndexHdr *pSnapshot; /* Start transaction here if not NULL */ |
| 64501 | #endif |
| @@ -64535,10 +64572,104 @@ | |
| 64572 | |
| 64573 | /* The wal-index is divided into pages of WALINDEX_PGSZ bytes each. */ |
| 64574 | #define WALINDEX_PGSZ ( \ |
| 64575 | sizeof(ht_slot)*HASHTABLE_NSLOT + HASHTABLE_NPAGE*sizeof(u32) \ |
| 64576 | ) |
| 64577 | |
| 64578 | /* |
| 64579 | ** Structured Exception Handling (SEH) is a Windows-specific technique |
| 64580 | ** for catching exceptions raised while accessing memory-mapped files. |
| 64581 | ** |
| 64582 | ** The -DSQLITE_USE_SEH compile-time option means to use SEH to catch and |
| 64583 | ** deal with system-level errors that arise during WAL -shm file processing. |
| 64584 | ** Without this compile-time option, any system-level faults that appear |
| 64585 | ** while accessing the memory-mapped -shm file will cause a process-wide |
| 64586 | ** signal to be deliver, which will more than likely cause the entire |
| 64587 | ** process to exit. |
| 64588 | */ |
| 64589 | #ifdef SQLITE_USE_SEH |
| 64590 | #include <Windows.h> |
| 64591 | |
| 64592 | /* Beginning of a block of code in which an exception might occur */ |
| 64593 | # define SEH_TRY __try { \ |
| 64594 | assert( walAssertLockmask(pWal) && pWal->nSehTry==0 ); \ |
| 64595 | VVA_ONLY(pWal->nSehTry++); |
| 64596 | |
| 64597 | /* The end of a block of code in which an exception might occur */ |
| 64598 | # define SEH_EXCEPT(X) \ |
| 64599 | VVA_ONLY(pWal->nSehTry--); \ |
| 64600 | assert( pWal->nSehTry==0 ); \ |
| 64601 | } __except( sehExceptionFilter(pWal, GetExceptionCode(), GetExceptionInformation() ) ){ X } |
| 64602 | |
| 64603 | /* Simulate a memory-mapping fault in the -shm file for testing purposes */ |
| 64604 | # define SEH_INJECT_FAULT sehInjectFault(pWal) |
| 64605 | |
| 64606 | /* |
| 64607 | ** The second argument is the return value of GetExceptionCode() for the |
| 64608 | ** current exception. Return EXCEPTION_EXECUTE_HANDLER if the exception code |
| 64609 | ** indicates that the exception may have been caused by accessing the *-shm |
| 64610 | ** file mapping. Or EXCEPTION_CONTINUE_SEARCH otherwise. |
| 64611 | */ |
| 64612 | static int sehExceptionFilter(Wal *pWal, int eCode, EXCEPTION_POINTERS *p){ |
| 64613 | VVA_ONLY(pWal->nSehTry--); |
| 64614 | if( eCode==EXCEPTION_IN_PAGE_ERROR ){ |
| 64615 | if( p && p->ExceptionRecord && p->ExceptionRecord->NumberParameters>=3 ){ |
| 64616 | /* From MSDN: For this type of exception, the first element of the |
| 64617 | ** ExceptionInformation[] array is a read-write flag - 0 if the exception |
| 64618 | ** was thrown while reading, 1 if while writing. The second element is |
| 64619 | ** the virtual address being accessed. The "third array element specifies |
| 64620 | ** the underlying NTSTATUS code that resulted in the exception". */ |
| 64621 | pWal->iSysErrno = (int)p->ExceptionRecord->ExceptionInformation[2]; |
| 64622 | } |
| 64623 | return EXCEPTION_EXECUTE_HANDLER; |
| 64624 | } |
| 64625 | return EXCEPTION_CONTINUE_SEARCH; |
| 64626 | } |
| 64627 | |
| 64628 | /* |
| 64629 | ** If one is configured, invoke the xTestCallback callback with 650 as |
| 64630 | ** the argument. If it returns true, throw the same exception that is |
| 64631 | ** thrown by the system if the *-shm file mapping is accessed after it |
| 64632 | ** has been invalidated. |
| 64633 | */ |
| 64634 | static void sehInjectFault(Wal *pWal){ |
| 64635 | int res; |
| 64636 | assert( pWal->nSehTry>0 ); |
| 64637 | |
| 64638 | res = sqlite3FaultSim(650); |
| 64639 | if( res!=0 ){ |
| 64640 | ULONG_PTR aArg[3]; |
| 64641 | aArg[0] = 0; |
| 64642 | aArg[1] = 0; |
| 64643 | aArg[2] = (ULONG_PTR)res; |
| 64644 | RaiseException(EXCEPTION_IN_PAGE_ERROR, 0, 3, (const ULONG_PTR*)aArg); |
| 64645 | } |
| 64646 | } |
| 64647 | |
| 64648 | /* |
| 64649 | ** There are two ways to use this macro. To set a pointer to be freed |
| 64650 | ** if an exception is thrown: |
| 64651 | ** |
| 64652 | ** SEH_FREE_ON_ERROR(0, pPtr); |
| 64653 | ** |
| 64654 | ** and to cancel the same: |
| 64655 | ** |
| 64656 | ** SEH_FREE_ON_ERROR(pPtr, 0); |
| 64657 | ** |
| 64658 | ** In the first case, there must not already be a pointer registered to |
| 64659 | ** be freed. In the second case, pPtr must be the registered pointer. |
| 64660 | */ |
| 64661 | #define SEH_FREE_ON_ERROR(X,Y) \ |
| 64662 | assert( (X==0 || Y==0) && pWal->pFree==X ); pWal->pFree = Y |
| 64663 | |
| 64664 | #else |
| 64665 | # define SEH_TRY VVA_ONLY(pWal->nSehTry++); |
| 64666 | # define SEH_EXCEPT(X) VVA_ONLY(pWal->nSehTry--); assert( pWal->nSehTry==0 ); |
| 64667 | # define SEH_INJECT_FAULT assert( pWal->nSehTry>0 ); |
| 64668 | # define SEH_FREE_ON_ERROR(X,Y) |
| 64669 | #endif /* ifdef SQLITE_USE_SEH */ |
| 64670 | |
| 64671 | |
| 64672 | /* |
| 64673 | ** Obtain a pointer to the iPage'th page of the wal-index. The wal-index |
| 64674 | ** is broken into pages of WALINDEX_PGSZ bytes. Wal-index pages are |
| 64675 | ** numbered from zero. |
| @@ -64608,10 +64739,11 @@ | |
| 64739 | static int walIndexPage( |
| 64740 | Wal *pWal, /* The WAL context */ |
| 64741 | int iPage, /* The page we seek */ |
| 64742 | volatile u32 **ppPage /* Write the page pointer here */ |
| 64743 | ){ |
| 64744 | SEH_INJECT_FAULT; |
| 64745 | if( pWal->nWiData<=iPage || (*ppPage = pWal->apWiData[iPage])==0 ){ |
| 64746 | return walIndexPageRealloc(pWal, iPage, ppPage); |
| 64747 | } |
| 64748 | return SQLITE_OK; |
| 64749 | } |
| @@ -64619,18 +64751,20 @@ | |
| 64751 | /* |
| 64752 | ** Return a pointer to the WalCkptInfo structure in the wal-index. |
| 64753 | */ |
| 64754 | static volatile WalCkptInfo *walCkptInfo(Wal *pWal){ |
| 64755 | assert( pWal->nWiData>0 && pWal->apWiData[0] ); |
| 64756 | SEH_INJECT_FAULT; |
| 64757 | return (volatile WalCkptInfo*)&(pWal->apWiData[0][sizeof(WalIndexHdr)/2]); |
| 64758 | } |
| 64759 | |
| 64760 | /* |
| 64761 | ** Return a pointer to the WalIndexHdr structure in the wal-index. |
| 64762 | */ |
| 64763 | static volatile WalIndexHdr *walIndexHdr(Wal *pWal){ |
| 64764 | assert( pWal->nWiData>0 && pWal->apWiData[0] ); |
| 64765 | SEH_INJECT_FAULT; |
| 64766 | return (volatile WalIndexHdr*)pWal->apWiData[0]; |
| 64767 | } |
| 64768 | |
| 64769 | /* |
| 64770 | ** The argument to this macro must be of type u32. On a little-endian |
| @@ -64884,16 +65018,22 @@ | |
| 65018 | rc = sqlite3OsShmLock(pWal->pDbFd, lockIdx, 1, |
| 65019 | SQLITE_SHM_LOCK | SQLITE_SHM_SHARED); |
| 65020 | WALTRACE(("WAL%p: acquire SHARED-%s %s\n", pWal, |
| 65021 | walLockName(lockIdx), rc ? "failed" : "ok")); |
| 65022 | VVA_ONLY( pWal->lockError = (u8)(rc!=SQLITE_OK && (rc&0xFF)!=SQLITE_BUSY); ) |
| 65023 | #ifdef SQLITE_USE_SEH |
| 65024 | if( rc==SQLITE_OK ) pWal->lockMask |= (1 << lockIdx); |
| 65025 | #endif |
| 65026 | return rc; |
| 65027 | } |
| 65028 | static void walUnlockShared(Wal *pWal, int lockIdx){ |
| 65029 | if( pWal->exclusiveMode ) return; |
| 65030 | (void)sqlite3OsShmLock(pWal->pDbFd, lockIdx, 1, |
| 65031 | SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED); |
| 65032 | #ifdef SQLITE_USE_SEH |
| 65033 | pWal->lockMask &= ~(1 << lockIdx); |
| 65034 | #endif |
| 65035 | WALTRACE(("WAL%p: release SHARED-%s\n", pWal, walLockName(lockIdx))); |
| 65036 | } |
| 65037 | static int walLockExclusive(Wal *pWal, int lockIdx, int n){ |
| 65038 | int rc; |
| 65039 | if( pWal->exclusiveMode ) return SQLITE_OK; |
| @@ -64900,16 +65040,24 @@ | |
| 65040 | rc = sqlite3OsShmLock(pWal->pDbFd, lockIdx, n, |
| 65041 | SQLITE_SHM_LOCK | SQLITE_SHM_EXCLUSIVE); |
| 65042 | WALTRACE(("WAL%p: acquire EXCLUSIVE-%s cnt=%d %s\n", pWal, |
| 65043 | walLockName(lockIdx), n, rc ? "failed" : "ok")); |
| 65044 | VVA_ONLY( pWal->lockError = (u8)(rc!=SQLITE_OK && (rc&0xFF)!=SQLITE_BUSY); ) |
| 65045 | #ifdef SQLITE_USE_SEH |
| 65046 | if( rc==SQLITE_OK ){ |
| 65047 | pWal->lockMask |= (((1<<n)-1) << (SQLITE_SHM_NLOCK+lockIdx)); |
| 65048 | } |
| 65049 | #endif |
| 65050 | return rc; |
| 65051 | } |
| 65052 | static void walUnlockExclusive(Wal *pWal, int lockIdx, int n){ |
| 65053 | if( pWal->exclusiveMode ) return; |
| 65054 | (void)sqlite3OsShmLock(pWal->pDbFd, lockIdx, n, |
| 65055 | SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE); |
| 65056 | #ifdef SQLITE_USE_SEH |
| 65057 | pWal->lockMask &= ~(((1<<n)-1) << (SQLITE_SHM_NLOCK+lockIdx)); |
| 65058 | #endif |
| 65059 | WALTRACE(("WAL%p: release EXCLUSIVE-%s cnt=%d\n", pWal, |
| 65060 | walLockName(lockIdx), n)); |
| 65061 | } |
| 65062 | |
| 65063 | /* |
| @@ -64997,10 +65145,11 @@ | |
| 65145 | /* |
| 65146 | ** Return the page number associated with frame iFrame in this WAL. |
| 65147 | */ |
| 65148 | static u32 walFramePgno(Wal *pWal, u32 iFrame){ |
| 65149 | int iHash = walFramePage(iFrame); |
| 65150 | SEH_INJECT_FAULT; |
| 65151 | if( iHash==0 ){ |
| 65152 | return pWal->apWiData[0][WALINDEX_HDR_SIZE/sizeof(u32) + iFrame - 1]; |
| 65153 | } |
| 65154 | return pWal->apWiData[iHash][(iFrame-1-HASHTABLE_NPAGE_ONE)%HASHTABLE_NPAGE]; |
| 65155 | } |
| @@ -65256,10 +65405,11 @@ | |
| 65405 | } |
| 65406 | |
| 65407 | /* Malloc a buffer to read frames into. */ |
| 65408 | szFrame = szPage + WAL_FRAME_HDRSIZE; |
| 65409 | aFrame = (u8 *)sqlite3_malloc64(szFrame + WALINDEX_PGSZ); |
| 65410 | SEH_FREE_ON_ERROR(0, aFrame); |
| 65411 | if( !aFrame ){ |
| 65412 | rc = SQLITE_NOMEM_BKPT; |
| 65413 | goto recovery_error; |
| 65414 | } |
| 65415 | aData = &aFrame[WAL_FRAME_HDRSIZE]; |
| @@ -65331,13 +65481,15 @@ | |
| 65481 | aShare[i] = aPrivate[i]; |
| 65482 | } |
| 65483 | } |
| 65484 | } |
| 65485 | #endif |
| 65486 | SEH_INJECT_FAULT; |
| 65487 | if( iFrame<=iLast ) break; |
| 65488 | } |
| 65489 | |
| 65490 | SEH_FREE_ON_ERROR(aFrame, 0); |
| 65491 | sqlite3_free(aFrame); |
| 65492 | } |
| 65493 | |
| 65494 | finished: |
| 65495 | if( rc==SQLITE_OK ){ |
| @@ -65361,10 +65513,11 @@ | |
| 65513 | if( i==1 && pWal->hdr.mxFrame ){ |
| 65514 | pInfo->aReadMark[i] = pWal->hdr.mxFrame; |
| 65515 | }else{ |
| 65516 | pInfo->aReadMark[i] = READMARK_NOT_USED; |
| 65517 | } |
| 65518 | SEH_INJECT_FAULT; |
| 65519 | walUnlockExclusive(pWal, WAL_READ_LOCK(i), 1); |
| 65520 | }else if( rc!=SQLITE_BUSY ){ |
| 65521 | goto recovery_error; |
| 65522 | } |
| 65523 | } |
| @@ -65753,10 +65906,11 @@ | |
| 65906 | return SQLITE_NOMEM_BKPT; |
| 65907 | } |
| 65908 | memset(p, 0, nByte); |
| 65909 | p->nSegment = nSegment; |
| 65910 | aTmp = (ht_slot*)&(((u8*)p)[nByte]); |
| 65911 | SEH_FREE_ON_ERROR(0, p); |
| 65912 | for(i=walFramePage(nBackfill+1); rc==SQLITE_OK && i<nSegment; i++){ |
| 65913 | WalHashLoc sLoc; |
| 65914 | |
| 65915 | rc = walHashGet(pWal, i, &sLoc); |
| 65916 | if( rc==SQLITE_OK ){ |
| @@ -65781,10 +65935,11 @@ | |
| 65935 | p->aSegment[i].aIndex = aIndex; |
| 65936 | p->aSegment[i].aPgno = (u32 *)sLoc.aPgno; |
| 65937 | } |
| 65938 | } |
| 65939 | if( rc!=SQLITE_OK ){ |
| 65940 | SEH_FREE_ON_ERROR(p, 0); |
| 65941 | walIteratorFree(p); |
| 65942 | p = 0; |
| 65943 | } |
| 65944 | *pp = p; |
| 65945 | return rc; |
| @@ -66006,17 +66161,17 @@ | |
| 66161 | ** cannot be backfilled from the WAL. |
| 66162 | */ |
| 66163 | mxSafeFrame = pWal->hdr.mxFrame; |
| 66164 | mxPage = pWal->hdr.nPage; |
| 66165 | for(i=1; i<WAL_NREADER; i++){ |
| 66166 | u32 y = AtomicLoad(pInfo->aReadMark+i); SEH_INJECT_FAULT; |
| 66167 | if( mxSafeFrame>y ){ |
| 66168 | assert( y<=pWal->hdr.mxFrame ); |
| 66169 | rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_READ_LOCK(i), 1); |
| 66170 | if( rc==SQLITE_OK ){ |
| 66171 | u32 iMark = (i==1 ? mxSafeFrame : READMARK_NOT_USED); |
| 66172 | AtomicStore(pInfo->aReadMark+i, iMark); SEH_INJECT_FAULT; |
| 66173 | walUnlockExclusive(pWal, WAL_READ_LOCK(i), 1); |
| 66174 | }else if( rc==SQLITE_BUSY ){ |
| 66175 | mxSafeFrame = y; |
| 66176 | xBusy = 0; |
| 66177 | }else{ |
| @@ -66033,12 +66188,11 @@ | |
| 66188 | |
| 66189 | if( pIter |
| 66190 | && (rc = walBusyLock(pWal,xBusy,pBusyArg,WAL_READ_LOCK(0),1))==SQLITE_OK |
| 66191 | ){ |
| 66192 | u32 nBackfill = pInfo->nBackfill; |
| 66193 | pInfo->nBackfillAttempted = mxSafeFrame; SEH_INJECT_FAULT; |
| 66194 | |
| 66195 | /* Sync the WAL to disk */ |
| 66196 | rc = sqlite3OsSync(pWal->pWalFd, CKPT_SYNC_FLAGS(sync_flags)); |
| 66197 | |
| 66198 | /* If the database may grow as a result of this checkpoint, hint |
| @@ -66065,10 +66219,11 @@ | |
| 66219 | |
| 66220 | /* Iterate through the contents of the WAL, copying data to the db file */ |
| 66221 | while( rc==SQLITE_OK && 0==walIteratorNext(pIter, &iDbpage, &iFrame) ){ |
| 66222 | i64 iOffset; |
| 66223 | assert( walFramePgno(pWal, iFrame)==iDbpage ); |
| 66224 | SEH_INJECT_FAULT; |
| 66225 | if( AtomicLoad(&db->u1.isInterrupted) ){ |
| 66226 | rc = db->mallocFailed ? SQLITE_NOMEM_BKPT : SQLITE_INTERRUPT; |
| 66227 | break; |
| 66228 | } |
| 66229 | if( iFrame<=nBackfill || iFrame>mxSafeFrame || iDbpage>mxPage ){ |
| @@ -66094,11 +66249,11 @@ | |
| 66249 | if( rc==SQLITE_OK ){ |
| 66250 | rc = sqlite3OsSync(pWal->pDbFd, CKPT_SYNC_FLAGS(sync_flags)); |
| 66251 | } |
| 66252 | } |
| 66253 | if( rc==SQLITE_OK ){ |
| 66254 | AtomicStore(&pInfo->nBackfill, mxSafeFrame); SEH_INJECT_FAULT; |
| 66255 | } |
| 66256 | } |
| 66257 | |
| 66258 | /* Release the reader lock held while backfilling */ |
| 66259 | walUnlockExclusive(pWal, WAL_READ_LOCK(0), 1); |
| @@ -66116,10 +66271,11 @@ | |
| 66271 | ** until all readers have finished using the wal file. This ensures that |
| 66272 | ** the next process to write to the database restarts the wal file. |
| 66273 | */ |
| 66274 | if( rc==SQLITE_OK && eMode!=SQLITE_CHECKPOINT_PASSIVE ){ |
| 66275 | assert( pWal->writeLock ); |
| 66276 | SEH_INJECT_FAULT; |
| 66277 | if( pInfo->nBackfill<pWal->hdr.mxFrame ){ |
| 66278 | rc = SQLITE_BUSY; |
| 66279 | }else if( eMode>=SQLITE_CHECKPOINT_RESTART ){ |
| 66280 | u32 salt1; |
| 66281 | sqlite3_randomness(4, &salt1); |
| @@ -66147,10 +66303,11 @@ | |
| 66303 | } |
| 66304 | } |
| 66305 | } |
| 66306 | |
| 66307 | walcheckpoint_out: |
| 66308 | SEH_FREE_ON_ERROR(pIter, 0); |
| 66309 | walIteratorFree(pIter); |
| 66310 | return rc; |
| 66311 | } |
| 66312 | |
| 66313 | /* |
| @@ -66169,10 +66326,91 @@ | |
| 66326 | if( rx ){ |
| 66327 | sqlite3_log(rx, "cannot limit WAL size: %s", pWal->zWalName); |
| 66328 | } |
| 66329 | } |
| 66330 | |
| 66331 | #ifdef SQLITE_USE_SEH |
| 66332 | /* |
| 66333 | ** This is the "standard" exception handler used in a few places to handle |
| 66334 | ** an exception thrown by reading from the *-shm mapping after it has become |
| 66335 | ** invalid in SQLITE_USE_SEH builds. It is used as follows: |
| 66336 | ** |
| 66337 | ** SEH_TRY { ... } |
| 66338 | ** SEH_EXCEPT( rc = walHandleException(pWal); ) |
| 66339 | ** |
| 66340 | ** This function does three things: |
| 66341 | ** |
| 66342 | ** 1) Determines the locks that should be held, based on the contents of |
| 66343 | ** the Wal.readLock, Wal.writeLock and Wal.ckptLock variables. All other |
| 66344 | ** held locks are assumed to be transient locks that would have been |
| 66345 | ** released had the exception not been thrown and are dropped. |
| 66346 | ** |
| 66347 | ** 2) Frees the pointer at Wal.pFree, if any, using sqlite3_free(). |
| 66348 | ** |
| 66349 | ** 3) Returns SQLITE_IOERR. |
| 66350 | */ |
| 66351 | static int walHandleException(Wal *pWal){ |
| 66352 | if( pWal->exclusiveMode==0 ){ |
| 66353 | static const int S = 1; |
| 66354 | static const int E = (1<<SQLITE_SHM_NLOCK); |
| 66355 | int ii; |
| 66356 | u32 mUnlock = pWal->lockMask & ~( |
| 66357 | (pWal->readLock<0 ? 0 : (S << WAL_READ_LOCK(pWal->readLock))) |
| 66358 | | (pWal->writeLock ? (E << WAL_WRITE_LOCK) : 0) |
| 66359 | | (pWal->ckptLock ? (E << WAL_CKPT_LOCK) : 0) |
| 66360 | ); |
| 66361 | for(ii=0; ii<SQLITE_SHM_NLOCK; ii++){ |
| 66362 | if( (S<<ii) & mUnlock ) walUnlockShared(pWal, ii); |
| 66363 | if( (E<<ii) & mUnlock ) walUnlockExclusive(pWal, ii, 1); |
| 66364 | } |
| 66365 | } |
| 66366 | sqlite3_free(pWal->pFree); |
| 66367 | pWal->pFree = 0; |
| 66368 | return SQLITE_IOERR_IN_PAGE; |
| 66369 | } |
| 66370 | |
| 66371 | /* |
| 66372 | ** Assert that the Wal.lockMask mask, which indicates the locks held |
| 66373 | ** by the connenction, is consistent with the Wal.readLock, Wal.writeLock |
| 66374 | ** and Wal.ckptLock variables. To be used as: |
| 66375 | ** |
| 66376 | ** assert( walAssertLockmask(pWal) ); |
| 66377 | */ |
| 66378 | static int walAssertLockmask(Wal *pWal){ |
| 66379 | if( pWal->exclusiveMode==0 ){ |
| 66380 | static const int S = 1; |
| 66381 | static const int E = (1<<SQLITE_SHM_NLOCK); |
| 66382 | u32 mExpect = ( |
| 66383 | (pWal->readLock<0 ? 0 : (S << WAL_READ_LOCK(pWal->readLock))) |
| 66384 | | (pWal->writeLock ? (E << WAL_WRITE_LOCK) : 0) |
| 66385 | | (pWal->ckptLock ? (E << WAL_CKPT_LOCK) : 0) |
| 66386 | #ifdef SQLITE_ENABLE_SNAPSHOT |
| 66387 | | (pWal->pSnapshot ? (pWal->lockMask & (1 << WAL_CKPT_LOCK)) : 0) |
| 66388 | #endif |
| 66389 | ); |
| 66390 | assert( mExpect==pWal->lockMask ); |
| 66391 | } |
| 66392 | return 1; |
| 66393 | } |
| 66394 | |
| 66395 | /* |
| 66396 | ** Return and zero the "system error" field set when an |
| 66397 | ** EXCEPTION_IN_PAGE_ERROR exception is caught. |
| 66398 | */ |
| 66399 | SQLITE_PRIVATE int sqlite3WalSystemErrno(Wal *pWal){ |
| 66400 | int iRet = 0; |
| 66401 | if( pWal ){ |
| 66402 | iRet = pWal->iSysErrno; |
| 66403 | pWal->iSysErrno = 0; |
| 66404 | } |
| 66405 | return iRet; |
| 66406 | } |
| 66407 | |
| 66408 | #else |
| 66409 | # define walAssertLockmask(x) 1 |
| 66410 | #endif /* ifdef SQLITE_USE_SEH */ |
| 66411 | |
| 66412 | /* |
| 66413 | ** Close a connection to a log file. |
| 66414 | */ |
| 66415 | SQLITE_PRIVATE int sqlite3WalClose( |
| 66416 | Wal *pWal, /* Wal to close */ |
| @@ -66182,10 +66420,12 @@ | |
| 66420 | u8 *zBuf /* Buffer of at least nBuf bytes */ |
| 66421 | ){ |
| 66422 | int rc = SQLITE_OK; |
| 66423 | if( pWal ){ |
| 66424 | int isDelete = 0; /* True to unlink wal and wal-index files */ |
| 66425 | |
| 66426 | assert( walAssertLockmask(pWal) ); |
| 66427 | |
| 66428 | /* If an EXCLUSIVE lock can be obtained on the database file (using the |
| 66429 | ** ordinary, rollback-mode locking methods, this guarantees that the |
| 66430 | ** connection associated with this log file is the only connection to |
| 66431 | ** the database. In this case checkpoint the database and unlink both |
| @@ -66725,10 +66965,11 @@ | |
| 66965 | } |
| 66966 | |
| 66967 | assert( pWal->nWiData>0 ); |
| 66968 | assert( pWal->apWiData[0]!=0 ); |
| 66969 | pInfo = walCkptInfo(pWal); |
| 66970 | SEH_INJECT_FAULT; |
| 66971 | if( !useWal && AtomicLoad(&pInfo->nBackfill)==pWal->hdr.mxFrame |
| 66972 | #ifdef SQLITE_ENABLE_SNAPSHOT |
| 66973 | && (pWal->pSnapshot==0 || pWal->hdr.mxFrame==0) |
| 66974 | #endif |
| 66975 | ){ |
| @@ -66774,11 +67015,11 @@ | |
| 67015 | if( pWal->pSnapshot && pWal->pSnapshot->mxFrame<mxFrame ){ |
| 67016 | mxFrame = pWal->pSnapshot->mxFrame; |
| 67017 | } |
| 67018 | #endif |
| 67019 | for(i=1; i<WAL_NREADER; i++){ |
| 67020 | u32 thisMark = AtomicLoad(pInfo->aReadMark+i); SEH_INJECT_FAULT; |
| 67021 | if( mxReadMark<=thisMark && thisMark<=mxFrame ){ |
| 67022 | assert( thisMark!=READMARK_NOT_USED ); |
| 67023 | mxReadMark = thisMark; |
| 67024 | mxI = i; |
| 67025 | } |
| @@ -66840,11 +67081,11 @@ | |
| 67081 | ** frame pWal->hdr.mxFrame - then the client would incorrectly assume |
| 67082 | ** that it can read version A from the database file. However, since |
| 67083 | ** we can guarantee that the checkpointer that set nBackfill could not |
| 67084 | ** see any pages past pWal->hdr.mxFrame, this problem does not come up. |
| 67085 | */ |
| 67086 | pWal->minFrame = AtomicLoad(&pInfo->nBackfill)+1; SEH_INJECT_FAULT; |
| 67087 | walShmBarrier(pWal); |
| 67088 | if( AtomicLoad(pInfo->aReadMark+mxI)!=mxReadMark |
| 67089 | || memcmp((void *)walIndexHdr(pWal), &pWal->hdr, sizeof(WalIndexHdr)) |
| 67090 | ){ |
| 67091 | walUnlockShared(pWal, WAL_READ_LOCK(mxI)); |
| @@ -66855,10 +67096,57 @@ | |
| 67096 | } |
| 67097 | return rc; |
| 67098 | } |
| 67099 | |
| 67100 | #ifdef SQLITE_ENABLE_SNAPSHOT |
| 67101 | /* |
| 67102 | ** This function does the work of sqlite3WalSnapshotRecover(). |
| 67103 | */ |
| 67104 | static int walSnapshotRecover( |
| 67105 | Wal *pWal, /* WAL handle */ |
| 67106 | void *pBuf1, /* Temp buffer pWal->szPage bytes in size */ |
| 67107 | void *pBuf2 /* Temp buffer pWal->szPage bytes in size */ |
| 67108 | ){ |
| 67109 | int szPage = (int)pWal->szPage; |
| 67110 | int rc; |
| 67111 | i64 szDb; /* Size of db file in bytes */ |
| 67112 | |
| 67113 | rc = sqlite3OsFileSize(pWal->pDbFd, &szDb); |
| 67114 | if( rc==SQLITE_OK ){ |
| 67115 | volatile WalCkptInfo *pInfo = walCkptInfo(pWal); |
| 67116 | u32 i = pInfo->nBackfillAttempted; |
| 67117 | for(i=pInfo->nBackfillAttempted; i>AtomicLoad(&pInfo->nBackfill); i--){ |
| 67118 | WalHashLoc sLoc; /* Hash table location */ |
| 67119 | u32 pgno; /* Page number in db file */ |
| 67120 | i64 iDbOff; /* Offset of db file entry */ |
| 67121 | i64 iWalOff; /* Offset of wal file entry */ |
| 67122 | |
| 67123 | rc = walHashGet(pWal, walFramePage(i), &sLoc); |
| 67124 | if( rc!=SQLITE_OK ) break; |
| 67125 | pgno = sLoc.aPgno[i-sLoc.iZero]; |
| 67126 | iDbOff = (i64)(pgno-1) * szPage; |
| 67127 | |
| 67128 | if( iDbOff+szPage<=szDb ){ |
| 67129 | iWalOff = walFrameOffset(i, szPage) + WAL_FRAME_HDRSIZE; |
| 67130 | rc = sqlite3OsRead(pWal->pWalFd, pBuf1, szPage, iWalOff); |
| 67131 | |
| 67132 | if( rc==SQLITE_OK ){ |
| 67133 | rc = sqlite3OsRead(pWal->pDbFd, pBuf2, szPage, iDbOff); |
| 67134 | } |
| 67135 | |
| 67136 | if( rc!=SQLITE_OK || 0==memcmp(pBuf1, pBuf2, szPage) ){ |
| 67137 | break; |
| 67138 | } |
| 67139 | } |
| 67140 | |
| 67141 | pInfo->nBackfillAttempted = i-1; |
| 67142 | } |
| 67143 | } |
| 67144 | |
| 67145 | return rc; |
| 67146 | } |
| 67147 | |
| 67148 | /* |
| 67149 | ** Attempt to reduce the value of the WalCkptInfo.nBackfillAttempted |
| 67150 | ** variable so that older snapshots can be accessed. To do this, loop |
| 67151 | ** through all wal frames from nBackfillAttempted to (nBackfill+1), |
| 67152 | ** comparing their content to the corresponding page with the database |
| @@ -66880,84 +67168,47 @@ | |
| 67168 | int rc; |
| 67169 | |
| 67170 | assert( pWal->readLock>=0 ); |
| 67171 | rc = walLockExclusive(pWal, WAL_CKPT_LOCK, 1); |
| 67172 | if( rc==SQLITE_OK ){ |
| 67173 | void *pBuf1 = sqlite3_malloc(pWal->szPage); |
| 67174 | void *pBuf2 = sqlite3_malloc(pWal->szPage); |
| 67175 | if( pBuf1==0 || pBuf2==0 ){ |
| 67176 | rc = SQLITE_NOMEM; |
| 67177 | }else{ |
| 67178 | pWal->ckptLock = 1; |
| 67179 | SEH_TRY { |
| 67180 | rc = walSnapshotRecover(pWal, pBuf1, pBuf2); |
| 67181 | } |
| 67182 | SEH_EXCEPT( rc = SQLITE_IOERR_IN_PAGE; ) |
| 67183 | pWal->ckptLock = 0; |
| 67184 | } |
| 67185 | |
| 67186 | sqlite3_free(pBuf1); |
| 67187 | sqlite3_free(pBuf2); |
| 67188 | walUnlockExclusive(pWal, WAL_CKPT_LOCK, 1); |
| 67189 | } |
| 67190 | |
| 67191 | return rc; |
| 67192 | } |
| 67193 | #endif /* SQLITE_ENABLE_SNAPSHOT */ |
| 67194 | |
| 67195 | /* |
| 67196 | ** This function does the work of sqlite3WalBeginReadTransaction() (see |
| 67197 | ** below). That function simply calls this one inside an SEH_TRY{...} block. |
| 67198 | */ |
| 67199 | static int walBeginReadTransaction(Wal *pWal, int *pChanged){ |
| 67200 | int rc; /* Return code */ |
| 67201 | int cnt = 0; /* Number of TryBeginRead attempts */ |
| 67202 | #ifdef SQLITE_ENABLE_SNAPSHOT |
| 67203 | int ckptLock = 0; |
| 67204 | int bChanged = 0; |
| 67205 | WalIndexHdr *pSnapshot = pWal->pSnapshot; |
| 67206 | #endif |
| 67207 | |
| 67208 | assert( pWal->ckptLock==0 ); |
| 67209 | assert( pWal->nSehTry>0 ); |
| 67210 | |
| 67211 | #ifdef SQLITE_ENABLE_SNAPSHOT |
| 67212 | if( pSnapshot ){ |
| 67213 | if( memcmp(pSnapshot, &pWal->hdr, sizeof(WalIndexHdr))!=0 ){ |
| 67214 | bChanged = 1; |
| @@ -66976,11 +67227,11 @@ | |
| 67227 | walDisableBlocking(pWal); |
| 67228 | |
| 67229 | if( rc!=SQLITE_OK ){ |
| 67230 | return rc; |
| 67231 | } |
| 67232 | ckptLock = 1; |
| 67233 | } |
| 67234 | #endif |
| 67235 | |
| 67236 | do{ |
| 67237 | rc = walTryBeginRead(pWal, pChanged, 0, ++cnt); |
| @@ -67040,18 +67291,40 @@ | |
| 67291 | } |
| 67292 | } |
| 67293 | } |
| 67294 | |
| 67295 | /* Release the shared CKPT lock obtained above. */ |
| 67296 | if( ckptLock ){ |
| 67297 | assert( pSnapshot ); |
| 67298 | walUnlockShared(pWal, WAL_CKPT_LOCK); |
| 67299 | } |
| 67300 | #endif |
| 67301 | return rc; |
| 67302 | } |
| 67303 | |
| 67304 | /* |
| 67305 | ** Begin a read transaction on the database. |
| 67306 | ** |
| 67307 | ** This routine used to be called sqlite3OpenSnapshot() and with good reason: |
| 67308 | ** it takes a snapshot of the state of the WAL and wal-index for the current |
| 67309 | ** instant in time. The current thread will continue to use this snapshot. |
| 67310 | ** Other threads might append new content to the WAL and wal-index but |
| 67311 | ** that extra content is ignored by the current thread. |
| 67312 | ** |
| 67313 | ** If the database contents have changes since the previous read |
| 67314 | ** transaction, then *pChanged is set to 1 before returning. The |
| 67315 | ** Pager layer will use this to know that its cache is stale and |
| 67316 | ** needs to be flushed. |
| 67317 | */ |
| 67318 | SQLITE_PRIVATE int sqlite3WalBeginReadTransaction(Wal *pWal, int *pChanged){ |
| 67319 | int rc; |
| 67320 | SEH_TRY { |
| 67321 | rc = walBeginReadTransaction(pWal, pChanged); |
| 67322 | } |
| 67323 | SEH_EXCEPT( rc = walHandleException(pWal); ) |
| 67324 | return rc; |
| 67325 | } |
| 67326 | |
| 67327 | /* |
| 67328 | ** Finish with a read transaction. All this does is release the |
| 67329 | ** read-lock. |
| 67330 | */ |
| @@ -67069,11 +67342,11 @@ | |
| 67342 | ** to zero. |
| 67343 | ** |
| 67344 | ** Return SQLITE_OK if successful, or an error code if an error occurs. If an |
| 67345 | ** error does occur, the final value of *piRead is undefined. |
| 67346 | */ |
| 67347 | static int walFindFrame( |
| 67348 | Wal *pWal, /* WAL handle */ |
| 67349 | Pgno pgno, /* Database page number to read data for */ |
| 67350 | u32 *piRead /* OUT: Frame number (or zero) */ |
| 67351 | ){ |
| 67352 | u32 iRead = 0; /* If !=0, WAL frame to return data from */ |
| @@ -67132,10 +67405,11 @@ | |
| 67405 | if( rc!=SQLITE_OK ){ |
| 67406 | return rc; |
| 67407 | } |
| 67408 | nCollide = HASHTABLE_NSLOT; |
| 67409 | iKey = walHash(pgno); |
| 67410 | SEH_INJECT_FAULT; |
| 67411 | while( (iH = AtomicLoad(&sLoc.aHash[iKey]))!=0 ){ |
| 67412 | u32 iFrame = iH + sLoc.iZero; |
| 67413 | if( iFrame<=iLast && iFrame>=pWal->minFrame && sLoc.aPgno[iH-1]==pgno ){ |
| 67414 | assert( iFrame>iRead || CORRUPT_DB ); |
| 67415 | iRead = iFrame; |
| @@ -67167,10 +67441,34 @@ | |
| 67441 | #endif |
| 67442 | |
| 67443 | *piRead = iRead; |
| 67444 | return SQLITE_OK; |
| 67445 | } |
| 67446 | |
| 67447 | /* |
| 67448 | ** Search the wal file for page pgno. If found, set *piRead to the frame that |
| 67449 | ** contains the page. Otherwise, if pgno is not in the wal file, set *piRead |
| 67450 | ** to zero. |
| 67451 | ** |
| 67452 | ** Return SQLITE_OK if successful, or an error code if an error occurs. If an |
| 67453 | ** error does occur, the final value of *piRead is undefined. |
| 67454 | ** |
| 67455 | ** The difference between this function and walFindFrame() is that this |
| 67456 | ** function wraps walFindFrame() in an SEH_TRY{...} block. |
| 67457 | */ |
| 67458 | SQLITE_PRIVATE int sqlite3WalFindFrame( |
| 67459 | Wal *pWal, /* WAL handle */ |
| 67460 | Pgno pgno, /* Database page number to read data for */ |
| 67461 | u32 *piRead /* OUT: Frame number (or zero) */ |
| 67462 | ){ |
| 67463 | int rc; |
| 67464 | SEH_TRY { |
| 67465 | rc = walFindFrame(pWal, pgno, piRead); |
| 67466 | } |
| 67467 | SEH_EXCEPT( rc = SQLITE_IOERR_IN_PAGE; ) |
| 67468 | return rc; |
| 67469 | } |
| 67470 | |
| 67471 | /* |
| 67472 | ** Read the contents of frame iRead from the wal file into buffer pOut |
| 67473 | ** (which is nOut bytes in size). Return SQLITE_OK if successful, or an |
| 67474 | ** error code otherwise. |
| @@ -67249,16 +67547,21 @@ | |
| 67547 | |
| 67548 | /* If another connection has written to the database file since the |
| 67549 | ** time the read transaction on this connection was started, then |
| 67550 | ** the write is disallowed. |
| 67551 | */ |
| 67552 | SEH_TRY { |
| 67553 | if( memcmp(&pWal->hdr, (void *)walIndexHdr(pWal), sizeof(WalIndexHdr))!=0 ){ |
| 67554 | rc = SQLITE_BUSY_SNAPSHOT; |
| 67555 | } |
| 67556 | } |
| 67557 | SEH_EXCEPT( rc = SQLITE_IOERR_IN_PAGE; ) |
| 67558 | |
| 67559 | if( rc!=SQLITE_OK ){ |
| 67560 | walUnlockExclusive(pWal, WAL_WRITE_LOCK, 1); |
| 67561 | pWal->writeLock = 0; |
| 67562 | } |
| 67563 | return rc; |
| 67564 | } |
| 67565 | |
| 67566 | /* |
| 67567 | ** End a write transaction. The commit has already been done. This |
| @@ -67290,34 +67593,37 @@ | |
| 67593 | int rc = SQLITE_OK; |
| 67594 | if( ALWAYS(pWal->writeLock) ){ |
| 67595 | Pgno iMax = pWal->hdr.mxFrame; |
| 67596 | Pgno iFrame; |
| 67597 | |
| 67598 | SEH_TRY { |
| 67599 | /* Restore the clients cache of the wal-index header to the state it |
| 67600 | ** was in before the client began writing to the database. |
| 67601 | */ |
| 67602 | memcpy(&pWal->hdr, (void *)walIndexHdr(pWal), sizeof(WalIndexHdr)); |
| 67603 | |
| 67604 | for(iFrame=pWal->hdr.mxFrame+1; |
| 67605 | ALWAYS(rc==SQLITE_OK) && iFrame<=iMax; |
| 67606 | iFrame++ |
| 67607 | ){ |
| 67608 | /* This call cannot fail. Unless the page for which the page number |
| 67609 | ** is passed as the second argument is (a) in the cache and |
| 67610 | ** (b) has an outstanding reference, then xUndo is either a no-op |
| 67611 | ** (if (a) is false) or simply expels the page from the cache (if (b) |
| 67612 | ** is false). |
| 67613 | ** |
| 67614 | ** If the upper layer is doing a rollback, it is guaranteed that there |
| 67615 | ** are no outstanding references to any page other than page 1. And |
| 67616 | ** page 1 is never written to the log until the transaction is |
| 67617 | ** committed. As a result, the call to xUndo may not fail. |
| 67618 | */ |
| 67619 | assert( walFramePgno(pWal, iFrame)!=1 ); |
| 67620 | rc = xUndo(pUndoCtx, walFramePgno(pWal, iFrame)); |
| 67621 | } |
| 67622 | if( iMax!=pWal->hdr.mxFrame ) walCleanupHash(pWal); |
| 67623 | } |
| 67624 | SEH_EXCEPT( rc = SQLITE_IOERR_IN_PAGE; ) |
| 67625 | } |
| 67626 | return rc; |
| 67627 | } |
| 67628 | |
| 67629 | /* |
| @@ -67357,11 +67663,14 @@ | |
| 67663 | |
| 67664 | if( aWalData[0]<pWal->hdr.mxFrame ){ |
| 67665 | pWal->hdr.mxFrame = aWalData[0]; |
| 67666 | pWal->hdr.aFrameCksum[0] = aWalData[1]; |
| 67667 | pWal->hdr.aFrameCksum[1] = aWalData[2]; |
| 67668 | SEH_TRY { |
| 67669 | walCleanupHash(pWal); |
| 67670 | } |
| 67671 | SEH_EXCEPT( rc = SQLITE_IOERR_IN_PAGE; ) |
| 67672 | } |
| 67673 | |
| 67674 | return rc; |
| 67675 | } |
| 67676 | |
| @@ -67538,11 +67847,11 @@ | |
| 67847 | |
| 67848 | /* |
| 67849 | ** Write a set of frames to the log. The caller must hold the write-lock |
| 67850 | ** on the log file (obtained using sqlite3WalBeginWriteTransaction()). |
| 67851 | */ |
| 67852 | static int walFrames( |
| 67853 | Wal *pWal, /* Wal handle to write to */ |
| 67854 | int szPage, /* Database page-size in bytes */ |
| 67855 | PgHdr *pList, /* List of dirty pages to write */ |
| 67856 | Pgno nTruncate, /* Database size after this commit */ |
| 67857 | int isCommit, /* True if this is a commit */ |
| @@ -67649,11 +67958,11 @@ | |
| 67958 | ** the current transaction. If so, overwrite the existing frame and |
| 67959 | ** set Wal.writeLock to WAL_WRITELOCK_RECKSUM - indicating that |
| 67960 | ** checksums must be recomputed when the transaction is committed. */ |
| 67961 | if( iFirst && (p->pDirty || isCommit==0) ){ |
| 67962 | u32 iWrite = 0; |
| 67963 | VVA_ONLY(rc =) walFindFrame(pWal, p->pgno, &iWrite); |
| 67964 | assert( rc==SQLITE_OK || iWrite==0 ); |
| 67965 | if( iWrite>=iFirst ){ |
| 67966 | i64 iOff = walFrameOffset(iWrite, szPage) + WAL_FRAME_HDRSIZE; |
| 67967 | void *pData; |
| 67968 | if( pWal->iReCksum==0 || iWrite<pWal->iReCksum ){ |
| @@ -67767,10 +68076,33 @@ | |
| 68076 | } |
| 68077 | |
| 68078 | WALTRACE(("WAL%p: frame write %s\n", pWal, rc ? "failed" : "ok")); |
| 68079 | return rc; |
| 68080 | } |
| 68081 | |
| 68082 | /* |
| 68083 | ** Write a set of frames to the log. The caller must hold the write-lock |
| 68084 | ** on the log file (obtained using sqlite3WalBeginWriteTransaction()). |
| 68085 | ** |
| 68086 | ** The difference between this function and walFrames() is that this |
| 68087 | ** function wraps walFrames() in an SEH_TRY{...} block. |
| 68088 | */ |
| 68089 | SQLITE_PRIVATE int sqlite3WalFrames( |
| 68090 | Wal *pWal, /* Wal handle to write to */ |
| 68091 | int szPage, /* Database page-size in bytes */ |
| 68092 | PgHdr *pList, /* List of dirty pages to write */ |
| 68093 | Pgno nTruncate, /* Database size after this commit */ |
| 68094 | int isCommit, /* True if this is a commit */ |
| 68095 | int sync_flags /* Flags to pass to OsSync() (or 0) */ |
| 68096 | ){ |
| 68097 | int rc; |
| 68098 | SEH_TRY { |
| 68099 | rc = walFrames(pWal, szPage, pList, nTruncate, isCommit, sync_flags); |
| 68100 | } |
| 68101 | SEH_EXCEPT( rc = walHandleException(pWal); ) |
| 68102 | return rc; |
| 68103 | } |
| 68104 | |
| 68105 | /* |
| 68106 | ** This routine is called to implement sqlite3_wal_checkpoint() and |
| 68107 | ** related interfaces. |
| 68108 | ** |
| @@ -67847,34 +68179,37 @@ | |
| 68179 | } |
| 68180 | } |
| 68181 | |
| 68182 | |
| 68183 | /* Read the wal-index header. */ |
| 68184 | SEH_TRY { |
| 68185 | if( rc==SQLITE_OK ){ |
| 68186 | walDisableBlocking(pWal); |
| 68187 | rc = walIndexReadHdr(pWal, &isChanged); |
| 68188 | (void)walEnableBlocking(pWal); |
| 68189 | if( isChanged && pWal->pDbFd->pMethods->iVersion>=3 ){ |
| 68190 | sqlite3OsUnfetch(pWal->pDbFd, 0, 0); |
| 68191 | } |
| 68192 | } |
| 68193 | |
| 68194 | /* Copy data from the log to the database file. */ |
| 68195 | if( rc==SQLITE_OK ){ |
| 68196 | if( pWal->hdr.mxFrame && walPagesize(pWal)!=nBuf ){ |
| 68197 | rc = SQLITE_CORRUPT_BKPT; |
| 68198 | }else{ |
| 68199 | rc = walCheckpoint(pWal, db, eMode2, xBusy2, pBusyArg, sync_flags,zBuf); |
| 68200 | } |
| 68201 | |
| 68202 | /* If no error occurred, set the output variables. */ |
| 68203 | if( rc==SQLITE_OK || rc==SQLITE_BUSY ){ |
| 68204 | if( pnLog ) *pnLog = (int)pWal->hdr.mxFrame; |
| 68205 | SEH_INJECT_FAULT; |
| 68206 | if( pnCkpt ) *pnCkpt = (int)(walCkptInfo(pWal)->nBackfill); |
| 68207 | } |
| 68208 | } |
| 68209 | } |
| 68210 | SEH_EXCEPT( rc = walHandleException(pWal); ) |
| 68211 | |
| 68212 | if( isChanged ){ |
| 68213 | /* If a new wal-index header was loaded before the checkpoint was |
| 68214 | ** performed, then the pager-cache associated with pWal is now |
| 68215 | ** out of date. So zero the cached wal-index header to ensure that |
| @@ -67947,11 +68282,13 @@ | |
| 68282 | ** prior error while attempting to acquire are read-lock. This cannot |
| 68283 | ** happen if the connection is actually in exclusive mode (as no xShmLock |
| 68284 | ** locks are taken in this case). Nor should the pager attempt to |
| 68285 | ** upgrade to exclusive-mode following such an error. |
| 68286 | */ |
| 68287 | #ifndef SQLITE_USE_SEH |
| 68288 | assert( pWal->readLock>=0 || pWal->lockError ); |
| 68289 | #endif |
| 68290 | assert( pWal->readLock>=0 || (op<=0 && pWal->exclusiveMode==0) ); |
| 68291 | |
| 68292 | if( op==0 ){ |
| 68293 | if( pWal->exclusiveMode!=WAL_NORMAL_MODE ){ |
| 68294 | pWal->exclusiveMode = WAL_NORMAL_MODE; |
| @@ -68048,20 +68385,23 @@ | |
| 68385 | ** occurs (any value other than SQLITE_OK is returned), the CHECKPOINTER |
| 68386 | ** lock is released before returning. |
| 68387 | */ |
| 68388 | SQLITE_PRIVATE int sqlite3WalSnapshotCheck(Wal *pWal, sqlite3_snapshot *pSnapshot){ |
| 68389 | int rc; |
| 68390 | SEH_TRY { |
| 68391 | rc = walLockShared(pWal, WAL_CKPT_LOCK); |
| 68392 | if( rc==SQLITE_OK ){ |
| 68393 | WalIndexHdr *pNew = (WalIndexHdr*)pSnapshot; |
| 68394 | if( memcmp(pNew->aSalt, pWal->hdr.aSalt, sizeof(pWal->hdr.aSalt)) |
| 68395 | || pNew->mxFrame<walCkptInfo(pWal)->nBackfillAttempted |
| 68396 | ){ |
| 68397 | rc = SQLITE_ERROR_SNAPSHOT; |
| 68398 | walUnlockShared(pWal, WAL_CKPT_LOCK); |
| 68399 | } |
| 68400 | } |
| 68401 | } |
| 68402 | SEH_EXCEPT( rc = walHandleException(pWal); ) |
| 68403 | return rc; |
| 68404 | } |
| 68405 | |
| 68406 | /* |
| 68407 | ** Release a lock obtained by an earlier successful call to |
| @@ -86698,10 +87038,11 @@ | |
| 87038 | } |
| 87039 | if( rc==SQLITE_BUSY && p->readOnly ){ |
| 87040 | sqlite3VdbeLeave(p); |
| 87041 | return SQLITE_BUSY; |
| 87042 | }else if( rc!=SQLITE_OK ){ |
| 87043 | sqlite3SystemError(db, rc); |
| 87044 | p->rc = rc; |
| 87045 | sqlite3RollbackAll(db, SQLITE_OK); |
| 87046 | p->nChange = 0; |
| 87047 | }else{ |
| 87048 | db->nDeferredCons = 0; |
| @@ -93737,14 +94078,14 @@ | |
| 94078 | ** This opcode must follow an OP_Lt or OP_Gt comparison operator. There |
| 94079 | ** can be zero or more OP_ReleaseReg opcodes intervening, but no other |
| 94080 | ** opcodes are allowed to occur between this instruction and the previous |
| 94081 | ** OP_Lt or OP_Gt. |
| 94082 | ** |
| 94083 | ** If the result of an OP_Eq comparison on the same two operands as |
| 94084 | ** the prior OP_Lt or OP_Gt would have been true, then jump to P2. If |
| 94085 | ** the result of an OP_Eq comparison on the two previous operands |
| 94086 | ** would have been false or NULL, then fall through. |
| 94087 | */ |
| 94088 | case OP_ElseEq: { /* same as TK_ESCAPE, jump */ |
| 94089 | |
| 94090 | #ifdef SQLITE_DEBUG |
| 94091 | /* Verify the preconditions of this opcode - that it follows an OP_Lt or |
| @@ -94170,11 +94511,11 @@ | |
| 94511 | } |
| 94512 | |
| 94513 | /* Opcode: ZeroOrNull P1 P2 P3 * * |
| 94514 | ** Synopsis: r[P2] = 0 OR NULL |
| 94515 | ** |
| 94516 | ** If both registers P1 and P3 are NOT NULL, then store a zero in |
| 94517 | ** register P2. If either registers P1 or P3 are NULL then put |
| 94518 | ** a NULL in register P2. |
| 94519 | */ |
| 94520 | case OP_ZeroOrNull: { /* in1, in2, out2, in3 */ |
| 94521 | if( (aMem[pOp->p1].flags & MEM_Null)!=0 |
| @@ -96571,17 +96912,17 @@ | |
| 96912 | ** record. Cursor P1 is an index btree. P2 is a jump destination. |
| 96913 | ** In other words, the operands to this opcode are the same as the |
| 96914 | ** operands to OP_NotFound and OP_IdxGT. |
| 96915 | ** |
| 96916 | ** This opcode is an optimization attempt only. If this opcode always |
| 96917 | ** falls through, the correct answer is still obtained, but extra work |
| 96918 | ** is performed. |
| 96919 | ** |
| 96920 | ** A value of N in the seekHit flag of cursor P1 means that there exists |
| 96921 | ** a key P3:N that will match some record in the index. We want to know |
| 96922 | ** if it is possible for a record P3:P4 to match some record in the |
| 96923 | ** index. If it is not possible, we can skip some work. So if seekHit |
| 96924 | ** is less than P4, attempt to find out if a match is possible by running |
| 96925 | ** OP_NotFound. |
| 96926 | ** |
| 96927 | ** This opcode is used in IN clause processing for a multi-column key. |
| 96928 | ** If an IN clause is attached to an element of the key other than the |
| @@ -97143,14 +97484,14 @@ | |
| 97484 | ** it is ok to delete a record from within a Next loop. If |
| 97485 | ** OPFLAG_SAVEPOSITION bit of P5 is clear, then the cursor will be |
| 97486 | ** left in an undefined state. |
| 97487 | ** |
| 97488 | ** If the OPFLAG_AUXDELETE bit is set on P5, that indicates that this |
| 97489 | ** delete is one of several associated with deleting a table row and |
| 97490 | ** all its associated index entries. Exactly one of those deletes is |
| 97491 | ** the "primary" delete. The others are all on OPFLAG_FORDELETE |
| 97492 | ** cursors or else are marked with the AUXDELETE flag. |
| 97493 | ** |
| 97494 | ** If the OPFLAG_NCHANGE flag of P2 (NB: P2 not P5) is set, then the row |
| 97495 | ** change count is incremented (otherwise not). |
| 97496 | ** |
| 97497 | ** P1 must not be pseudo-table. It has to be a real table with |
| @@ -97318,11 +97659,11 @@ | |
| 97659 | ** Synopsis: r[P2]=data |
| 97660 | ** |
| 97661 | ** Write into register P2 the current sorter data for sorter cursor P1. |
| 97662 | ** Then clear the column header cache on cursor P3. |
| 97663 | ** |
| 97664 | ** This opcode is normally used to move a record out of the sorter and into |
| 97665 | ** a register that is the source for a pseudo-table cursor created using |
| 97666 | ** OpenPseudo. That pseudo-table cursor is the one that is identified by |
| 97667 | ** parameter P3. Clearing the P3 column cache as part of this opcode saves |
| 97668 | ** us from having to issue a separate NullRow instruction to clear that cache. |
| 97669 | */ |
| @@ -98127,11 +98468,11 @@ | |
| 98468 | ** |
| 98469 | ** Delete an entire database table or index whose root page in the database |
| 98470 | ** file is given by P1. |
| 98471 | ** |
| 98472 | ** The table being destroyed is in the main database file if P3==0. If |
| 98473 | ** P3==1 then the table to be destroyed is in the auxiliary database file |
| 98474 | ** that is used to store tables create using CREATE TEMPORARY TABLE. |
| 98475 | ** |
| 98476 | ** If AUTOVACUUM is enabled then it is possible that another root page |
| 98477 | ** might be moved into the newly deleted root page in order to keep all |
| 98478 | ** root pages contiguous at the beginning of the database. The former |
| @@ -98187,12 +98528,12 @@ | |
| 98528 | ** |
| 98529 | ** Delete all contents of the database table or index whose root page |
| 98530 | ** in the database file is given by P1. But, unlike Destroy, do not |
| 98531 | ** remove the table or index from the database file. |
| 98532 | ** |
| 98533 | ** The table being cleared is in the main database file if P2==0. If |
| 98534 | ** P2==1 then the table to be cleared is in the auxiliary database file |
| 98535 | ** that is used to store tables create using CREATE TEMPORARY TABLE. |
| 98536 | ** |
| 98537 | ** If the P3 value is non-zero, then the row change count is incremented |
| 98538 | ** by the number of rows in the table being cleared. If P3 is greater |
| 98539 | ** than zero, then the value stored in register P3 is also incremented |
| @@ -110966,14 +111307,17 @@ | |
| 111307 | int iTable, /* The cursor pointing to the table */ |
| 111308 | int iReg, /* Store results here */ |
| 111309 | u8 p5 /* P5 value for OP_Column + FLAGS */ |
| 111310 | ){ |
| 111311 | assert( pParse->pVdbe!=0 ); |
| 111312 | assert( (p5 & (OPFLAG_NOCHNG|OPFLAG_TYPEOFARG|OPFLAG_LENGTHARG))==p5 ); |
| 111313 | assert( IsVirtual(pTab) || (p5 & OPFLAG_NOCHNG)==0 ); |
| 111314 | sqlite3ExprCodeGetColumnOfTable(pParse->pVdbe, pTab, iTable, iColumn, iReg); |
| 111315 | if( p5 ){ |
| 111316 | VdbeOp *pOp = sqlite3VdbeGetLastOp(pParse->pVdbe); |
| 111317 | if( pOp->opcode==OP_Column ) pOp->p5 = p5; |
| 111318 | if( pOp->opcode==OP_VColumn ) pOp->p5 = (p5 & OPFLAG_NOCHNG); |
| 111319 | } |
| 111320 | return iReg; |
| 111321 | } |
| 111322 | |
| 111323 | /* |
| @@ -141288,10 +141632,20 @@ | |
| 141632 | testcase( eDest==SRT_Table ); |
| 141633 | testcase( eDest==SRT_EphemTab ); |
| 141634 | testcase( eDest==SRT_Fifo ); |
| 141635 | testcase( eDest==SRT_DistFifo ); |
| 141636 | sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nResultCol, r1+nPrefixReg); |
| 141637 | #if !defined(SQLITE_ENABLE_NULL_TRIM) && defined(SQLITE_DEBUG) |
| 141638 | /* A destination of SRT_Table and a non-zero iSDParm2 parameter means |
| 141639 | ** that this is an "UPDATE ... FROM" on a virtual table or view. In this |
| 141640 | ** case set the p5 parameter of the OP_MakeRecord to OPFLAG_NOCHNG_MAGIC. |
| 141641 | ** This does not affect operation in any way - it just allows MakeRecord |
| 141642 | ** to process OPFLAG_NOCHANGE values without an assert() failing. */ |
| 141643 | if( eDest==SRT_Table && pDest->iSDParm2 ){ |
| 141644 | sqlite3VdbeChangeP5(v, OPFLAG_NOCHNG_MAGIC); |
| 141645 | } |
| 141646 | #endif |
| 141647 | #ifndef SQLITE_OMIT_CTE |
| 141648 | if( eDest==SRT_DistFifo ){ |
| 141649 | /* If the destination is DistFifo, then cursor (iParm+1) is open |
| 141650 | ** on an ephemeral index. If the current row is already present |
| 141651 | ** in the index, do not write it to the output. If not, add the |
| @@ -151336,11 +151690,13 @@ | |
| 151690 | if( aXRef[i]>=0 ){ |
| 151691 | pList = sqlite3ExprListAppend(pParse, pList, |
| 151692 | sqlite3ExprDup(db, pChanges->a[aXRef[i]].pExpr, 0) |
| 151693 | ); |
| 151694 | }else{ |
| 151695 | Expr *pRow = exprRowColumn(pParse, i); |
| 151696 | if( pRow ) pRow->op2 = OPFLAG_NOCHNG; |
| 151697 | pList = sqlite3ExprListAppend(pParse, pList, pRow); |
| 151698 | } |
| 151699 | } |
| 151700 | |
| 151701 | updateFromSelect(pParse, ephemTab, pPk, pList, pSrc, pWhere, 0, 0); |
| 151702 | sqlite3ExprListDelete(db, pList); |
| @@ -175166,11 +175522,11 @@ | |
| 175522 | } |
| 175523 | case CC_DIGIT: { |
| 175524 | testcase( z[0]=='0' ); testcase( z[0]=='1' ); testcase( z[0]=='2' ); |
| 175525 | testcase( z[0]=='3' ); testcase( z[0]=='4' ); testcase( z[0]=='5' ); |
| 175526 | testcase( z[0]=='6' ); testcase( z[0]=='7' ); testcase( z[0]=='8' ); |
| 175527 | testcase( z[0]=='9' ); testcase( z[0]=='.' ); |
| 175528 | *tokenType = TK_INTEGER; |
| 175529 | #ifndef SQLITE_OMIT_HEX_INTEGER |
| 175530 | if( z[0]=='0' && (z[1]=='x' || z[1]=='X') && sqlite3Isxdigit(z[2]) ){ |
| 175531 | for(i=3; sqlite3Isxdigit(z[i]); i++){} |
| 175532 | return i; |
| @@ -203827,11 +204183,17 @@ | |
| 204183 | int argc, |
| 204184 | sqlite3_value **argv |
| 204185 | ){ |
| 204186 | JsonParse *p; /* The parse */ |
| 204187 | UNUSED_PARAMETER(argc); |
| 204188 | if( sqlite3_value_type(argv[0])==SQLITE_NULL ){ |
| 204189 | #ifdef SQLITE_LEGACY_JSON_VALID |
| 204190 | /* Incorrect legacy behavior was to return FALSE for a NULL input */ |
| 204191 | sqlite3_result_int(ctx, 0); |
| 204192 | #endif |
| 204193 | return; |
| 204194 | } |
| 204195 | p = jsonParseCached(ctx, argv[0], 0, 0); |
| 204196 | if( p==0 || p->oom ){ |
| 204197 | sqlite3_result_error_nomem(ctx); |
| 204198 | sqlite3_free(p); |
| 204199 | }else{ |
| @@ -225917,28 +226279,28 @@ | |
| 226279 | |
| 226280 | /* Create a new tokenizer */ |
| 226281 | int (*xCreateTokenizer)( |
| 226282 | fts5_api *pApi, |
| 226283 | const char *zName, |
| 226284 | void *pUserData, |
| 226285 | fts5_tokenizer *pTokenizer, |
| 226286 | void (*xDestroy)(void*) |
| 226287 | ); |
| 226288 | |
| 226289 | /* Find an existing tokenizer */ |
| 226290 | int (*xFindTokenizer)( |
| 226291 | fts5_api *pApi, |
| 226292 | const char *zName, |
| 226293 | void **ppUserData, |
| 226294 | fts5_tokenizer *pTokenizer |
| 226295 | ); |
| 226296 | |
| 226297 | /* Create a new auxiliary function */ |
| 226298 | int (*xCreateFunction)( |
| 226299 | fts5_api *pApi, |
| 226300 | const char *zName, |
| 226301 | void *pUserData, |
| 226302 | fts5_extension_function xFunction, |
| 226303 | void (*xDestroy)(void*) |
| 226304 | ); |
| 226305 | }; |
| 226306 | |
| @@ -244178,11 +244540,11 @@ | |
| 244540 | /* Filter out attempts to run UPDATE or DELETE on contentless tables. |
| 244541 | ** This is not suported. Except - DELETE is supported if the CREATE |
| 244542 | ** VIRTUAL TABLE statement contained "contentless_delete=1". */ |
| 244543 | if( eType0==SQLITE_INTEGER |
| 244544 | && pConfig->eContent==FTS5_CONTENT_NONE |
| 244545 | && pConfig->bContentlessDelete==0 |
| 244546 | ){ |
| 244547 | pTab->p.base.zErrMsg = sqlite3_mprintf( |
| 244548 | "cannot %s contentless fts5 table: %s", |
| 244549 | (nArg>1 ? "UPDATE" : "DELETE from"), pConfig->zName |
| 244550 | ); |
| @@ -245033,10 +245395,16 @@ | |
| 245395 | rc = fts5SeekCursor(pCsr, 1); |
| 245396 | if( rc==SQLITE_OK ){ |
| 245397 | sqlite3_result_value(pCtx, sqlite3_column_value(pCsr->pStmt, iCol+1)); |
| 245398 | } |
| 245399 | pConfig->pzErrmsg = 0; |
| 245400 | }else if( pConfig->bContentlessDelete && sqlite3_vtab_nochange(pCtx) ){ |
| 245401 | char *zErr = sqlite3_mprintf("cannot UPDATE a subset of " |
| 245402 | "columns on fts5 contentless-delete table: %s", pConfig->zName |
| 245403 | ); |
| 245404 | sqlite3_result_error(pCtx, zErr, -1); |
| 245405 | sqlite3_free(zErr); |
| 245406 | } |
| 245407 | return rc; |
| 245408 | } |
| 245409 | |
| 245410 | |
| @@ -245315,11 +245683,11 @@ | |
| 245683 | int nArg, /* Number of args */ |
| 245684 | sqlite3_value **apUnused /* Function arguments */ |
| 245685 | ){ |
| 245686 | assert( nArg==0 ); |
| 245687 | UNUSED_PARAM2(nArg, apUnused); |
| 245688 | sqlite3_result_text(pCtx, "fts5: 2023-08-11 22:40:06 3bc0693c4633f545f09dbee702e25354504b20836373a068447e6c61cb2ebd79", -1, SQLITE_TRANSIENT); |
| 245689 | } |
| 245690 | |
| 245691 | /* |
| 245692 | ** Return true if zName is the extension on one of the shadow tables used |
| 245693 | ** by this module. |
| 245694 |
+5
-4
| --- extsrc/sqlite3.h | ||
| +++ extsrc/sqlite3.h | ||
| @@ -146,11 +146,11 @@ | ||
| 146 | 146 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 147 | 147 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 148 | 148 | */ |
| 149 | 149 | #define SQLITE_VERSION "3.43.0" |
| 150 | 150 | #define SQLITE_VERSION_NUMBER 3043000 |
| 151 | -#define SQLITE_SOURCE_ID "2023-08-04 13:19:11 ba7a66db13b28da0b41f03be825a593608474a5ebda89e12d58d89db709b8f65" | |
| 151 | +#define SQLITE_SOURCE_ID "2023-08-11 22:40:06 3bc0693c4633f545f09dbee702e25354504b20836373a068447e6c61cb2ebd79" | |
| 152 | 152 | |
| 153 | 153 | /* |
| 154 | 154 | ** CAPI3REF: Run-Time Library Version Numbers |
| 155 | 155 | ** KEYWORDS: sqlite3_version sqlite3_sourceid |
| 156 | 156 | ** |
| @@ -526,10 +526,11 @@ | ||
| 526 | 526 | #define SQLITE_IOERR_BEGIN_ATOMIC (SQLITE_IOERR | (29<<8)) |
| 527 | 527 | #define SQLITE_IOERR_COMMIT_ATOMIC (SQLITE_IOERR | (30<<8)) |
| 528 | 528 | #define SQLITE_IOERR_ROLLBACK_ATOMIC (SQLITE_IOERR | (31<<8)) |
| 529 | 529 | #define SQLITE_IOERR_DATA (SQLITE_IOERR | (32<<8)) |
| 530 | 530 | #define SQLITE_IOERR_CORRUPTFS (SQLITE_IOERR | (33<<8)) |
| 531 | +#define SQLITE_IOERR_IN_PAGE (SQLITE_IOERR | (34<<8)) | |
| 531 | 532 | #define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8)) |
| 532 | 533 | #define SQLITE_LOCKED_VTAB (SQLITE_LOCKED | (2<<8)) |
| 533 | 534 | #define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8)) |
| 534 | 535 | #define SQLITE_BUSY_SNAPSHOT (SQLITE_BUSY | (2<<8)) |
| 535 | 536 | #define SQLITE_BUSY_TIMEOUT (SQLITE_BUSY | (3<<8)) |
| @@ -13081,28 +13082,28 @@ | ||
| 13081 | 13082 | |
| 13082 | 13083 | /* Create a new tokenizer */ |
| 13083 | 13084 | int (*xCreateTokenizer)( |
| 13084 | 13085 | fts5_api *pApi, |
| 13085 | 13086 | const char *zName, |
| 13086 | - void *pContext, | |
| 13087 | + void *pUserData, | |
| 13087 | 13088 | fts5_tokenizer *pTokenizer, |
| 13088 | 13089 | void (*xDestroy)(void*) |
| 13089 | 13090 | ); |
| 13090 | 13091 | |
| 13091 | 13092 | /* Find an existing tokenizer */ |
| 13092 | 13093 | int (*xFindTokenizer)( |
| 13093 | 13094 | fts5_api *pApi, |
| 13094 | 13095 | const char *zName, |
| 13095 | - void **ppContext, | |
| 13096 | + void **ppUserData, | |
| 13096 | 13097 | fts5_tokenizer *pTokenizer |
| 13097 | 13098 | ); |
| 13098 | 13099 | |
| 13099 | 13100 | /* Create a new auxiliary function */ |
| 13100 | 13101 | int (*xCreateFunction)( |
| 13101 | 13102 | fts5_api *pApi, |
| 13102 | 13103 | const char *zName, |
| 13103 | - void *pContext, | |
| 13104 | + void *pUserData, | |
| 13104 | 13105 | fts5_extension_function xFunction, |
| 13105 | 13106 | void (*xDestroy)(void*) |
| 13106 | 13107 | ); |
| 13107 | 13108 | }; |
| 13108 | 13109 | |
| 13109 | 13110 |
| --- extsrc/sqlite3.h | |
| +++ extsrc/sqlite3.h | |
| @@ -146,11 +146,11 @@ | |
| 146 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 147 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 148 | */ |
| 149 | #define SQLITE_VERSION "3.43.0" |
| 150 | #define SQLITE_VERSION_NUMBER 3043000 |
| 151 | #define SQLITE_SOURCE_ID "2023-08-04 13:19:11 ba7a66db13b28da0b41f03be825a593608474a5ebda89e12d58d89db709b8f65" |
| 152 | |
| 153 | /* |
| 154 | ** CAPI3REF: Run-Time Library Version Numbers |
| 155 | ** KEYWORDS: sqlite3_version sqlite3_sourceid |
| 156 | ** |
| @@ -526,10 +526,11 @@ | |
| 526 | #define SQLITE_IOERR_BEGIN_ATOMIC (SQLITE_IOERR | (29<<8)) |
| 527 | #define SQLITE_IOERR_COMMIT_ATOMIC (SQLITE_IOERR | (30<<8)) |
| 528 | #define SQLITE_IOERR_ROLLBACK_ATOMIC (SQLITE_IOERR | (31<<8)) |
| 529 | #define SQLITE_IOERR_DATA (SQLITE_IOERR | (32<<8)) |
| 530 | #define SQLITE_IOERR_CORRUPTFS (SQLITE_IOERR | (33<<8)) |
| 531 | #define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8)) |
| 532 | #define SQLITE_LOCKED_VTAB (SQLITE_LOCKED | (2<<8)) |
| 533 | #define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8)) |
| 534 | #define SQLITE_BUSY_SNAPSHOT (SQLITE_BUSY | (2<<8)) |
| 535 | #define SQLITE_BUSY_TIMEOUT (SQLITE_BUSY | (3<<8)) |
| @@ -13081,28 +13082,28 @@ | |
| 13081 | |
| 13082 | /* Create a new tokenizer */ |
| 13083 | int (*xCreateTokenizer)( |
| 13084 | fts5_api *pApi, |
| 13085 | const char *zName, |
| 13086 | void *pContext, |
| 13087 | fts5_tokenizer *pTokenizer, |
| 13088 | void (*xDestroy)(void*) |
| 13089 | ); |
| 13090 | |
| 13091 | /* Find an existing tokenizer */ |
| 13092 | int (*xFindTokenizer)( |
| 13093 | fts5_api *pApi, |
| 13094 | const char *zName, |
| 13095 | void **ppContext, |
| 13096 | fts5_tokenizer *pTokenizer |
| 13097 | ); |
| 13098 | |
| 13099 | /* Create a new auxiliary function */ |
| 13100 | int (*xCreateFunction)( |
| 13101 | fts5_api *pApi, |
| 13102 | const char *zName, |
| 13103 | void *pContext, |
| 13104 | fts5_extension_function xFunction, |
| 13105 | void (*xDestroy)(void*) |
| 13106 | ); |
| 13107 | }; |
| 13108 | |
| 13109 |
| --- extsrc/sqlite3.h | |
| +++ extsrc/sqlite3.h | |
| @@ -146,11 +146,11 @@ | |
| 146 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 147 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 148 | */ |
| 149 | #define SQLITE_VERSION "3.43.0" |
| 150 | #define SQLITE_VERSION_NUMBER 3043000 |
| 151 | #define SQLITE_SOURCE_ID "2023-08-11 22:40:06 3bc0693c4633f545f09dbee702e25354504b20836373a068447e6c61cb2ebd79" |
| 152 | |
| 153 | /* |
| 154 | ** CAPI3REF: Run-Time Library Version Numbers |
| 155 | ** KEYWORDS: sqlite3_version sqlite3_sourceid |
| 156 | ** |
| @@ -526,10 +526,11 @@ | |
| 526 | #define SQLITE_IOERR_BEGIN_ATOMIC (SQLITE_IOERR | (29<<8)) |
| 527 | #define SQLITE_IOERR_COMMIT_ATOMIC (SQLITE_IOERR | (30<<8)) |
| 528 | #define SQLITE_IOERR_ROLLBACK_ATOMIC (SQLITE_IOERR | (31<<8)) |
| 529 | #define SQLITE_IOERR_DATA (SQLITE_IOERR | (32<<8)) |
| 530 | #define SQLITE_IOERR_CORRUPTFS (SQLITE_IOERR | (33<<8)) |
| 531 | #define SQLITE_IOERR_IN_PAGE (SQLITE_IOERR | (34<<8)) |
| 532 | #define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8)) |
| 533 | #define SQLITE_LOCKED_VTAB (SQLITE_LOCKED | (2<<8)) |
| 534 | #define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8)) |
| 535 | #define SQLITE_BUSY_SNAPSHOT (SQLITE_BUSY | (2<<8)) |
| 536 | #define SQLITE_BUSY_TIMEOUT (SQLITE_BUSY | (3<<8)) |
| @@ -13081,28 +13082,28 @@ | |
| 13082 | |
| 13083 | /* Create a new tokenizer */ |
| 13084 | int (*xCreateTokenizer)( |
| 13085 | fts5_api *pApi, |
| 13086 | const char *zName, |
| 13087 | void *pUserData, |
| 13088 | fts5_tokenizer *pTokenizer, |
| 13089 | void (*xDestroy)(void*) |
| 13090 | ); |
| 13091 | |
| 13092 | /* Find an existing tokenizer */ |
| 13093 | int (*xFindTokenizer)( |
| 13094 | fts5_api *pApi, |
| 13095 | const char *zName, |
| 13096 | void **ppUserData, |
| 13097 | fts5_tokenizer *pTokenizer |
| 13098 | ); |
| 13099 | |
| 13100 | /* Create a new auxiliary function */ |
| 13101 | int (*xCreateFunction)( |
| 13102 | fts5_api *pApi, |
| 13103 | const char *zName, |
| 13104 | void *pUserData, |
| 13105 | fts5_extension_function xFunction, |
| 13106 | void (*xDestroy)(void*) |
| 13107 | ); |
| 13108 | }; |
| 13109 | |
| 13110 |