[libgda] Switched to SQlite 3.8.0.2 and SlqCipher 3.0.0
- From: Vivien Malerba <vivien src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libgda] Switched to SQlite 3.8.0.2 and SlqCipher 3.0.0
- Date: Mon, 11 Nov 2013 20:49:25 +0000 (UTC)
commit 70e44aa0e21c74bf1a3968454db1bd77c546d590
Author: Vivien Malerba <malerba gnome-db org>
Date: Mon Nov 11 13:53:13 2013 +0100
Switched to SQlite 3.8.0.2 and SlqCipher 3.0.0
libgda/sqlite/sqlite-src/PragmasPatch | 6 +-
libgda/sqlite/sqlite-src/sqlite3.c | 8621 +++--
libgda/sqlite/sqlite-src/sqlite3.h | 124 +-
providers/sqlcipher/sqlcipher.patch |62995 +--------------------------------
4 files changed, 5860 insertions(+), 65886 deletions(-)
---
diff --git a/libgda/sqlite/sqlite-src/PragmasPatch b/libgda/sqlite/sqlite-src/PragmasPatch
index a8f87f9..decd9ea 100644
--- a/libgda/sqlite/sqlite-src/PragmasPatch
+++ b/libgda/sqlite/sqlite-src/PragmasPatch
@@ -1,6 +1,6 @@
---- sqlite3.c.orig 2013-05-20 12:56:34.000000000 +0200
-+++ sqlite3.c 2013-06-30 15:08:52.994949387 +0200
-@@ -94348,6 +94348,60 @@
+--- sqlite3.c.orig 2013-09-04 00:26:22.000000000 +0200
++++ sqlite3.c 2013-11-09 12:39:57.315522927 +0100
+@@ -94739,6 +94739,60 @@
#ifndef SQLITE_OMIT_SCHEMA_PRAGMAS
/*
diff --git a/libgda/sqlite/sqlite-src/sqlite3.c b/libgda/sqlite/sqlite-src/sqlite3.c
index 3e7d7a5..af83417 100644
--- a/libgda/sqlite/sqlite-src/sqlite3.c
+++ b/libgda/sqlite/sqlite-src/sqlite3.c
@@ -1,6 +1,6 @@
/******************************************************************************
** This file is an amalgamation of many separate C source files from SQLite
-** version 3.7.17. By combining all the individual C code files into this
+** version 3.8.0.2. By combining all the individual C code files into this
** single large file, the entire code can be compiled as a single translation
** unit. This allows many compilers to do optimizations that would not be
** possible if the files were compiled separately. Performance improvements
@@ -354,7 +354,7 @@
** The SQLITE_THREADSAFE macro must be defined as 0, 1, or 2.
** 0 means mutexes are permanently disable and the library is never
** threadsafe. 1 means the library is serialized which is the highest
-** level of threadsafety. 2 means the libary is multithreaded - multiple
+** level of threadsafety. 2 means the library is multithreaded - multiple
** threads can use SQLite as long as no two threads try to use the same
** database connection at the same time.
**
@@ -401,9 +401,6 @@
** will cause HeapValidate to be called. If heap validation should fail, an
** assertion will be triggered.
**
-** (Historical note: There used to be several other options, but we've
-** pared it down to just these three.)
-**
** If none of the above are defined, then set SQLITE_SYSTEM_MALLOC as
** the default.
*/
@@ -433,27 +430,12 @@
/*
** We need to define _XOPEN_SOURCE as follows in order to enable
-** recursive mutexes on most Unix systems. But Mac OS X is different.
-** The _XOPEN_SOURCE define causes problems for Mac OS X we are told,
-** so it is omitted there. See ticket #2673.
-**
-** Later we learn that _XOPEN_SOURCE is poorly or incorrectly
-** implemented on some systems. So we avoid defining it at all
-** if it is already defined or if it is unneeded because we are
-** not doing a threadsafe build. Ticket #2681.
-**
-** See also ticket #2741.
-*/
-#if !defined(_XOPEN_SOURCE) && !defined(__DARWIN__) \
- && !defined(__APPLE__) && SQLITE_THREADSAFE
-# define _XOPEN_SOURCE 500 /* Needed to enable pthread recursive mutexes */
-#endif
-
-/*
-** The TCL headers are only needed when compiling the TCL bindings.
+** recursive mutexes on most Unix systems and fchmod() on OpenBSD.
+** But _XOPEN_SOURCE define causes problems for Mac OS X, so omit
+** it.
*/
-#if defined(SQLITE_TCL) || defined(TCLSH)
-# include <tcl.h>
+#if !defined(_XOPEN_SOURCE) && !defined(__DARWIN__) && !defined(__APPLE__)
+# define _XOPEN_SOURCE 600
#endif
/*
@@ -461,8 +443,8 @@
** defined(NDEBUG)==!defined(SQLITE_DEBUG). If this is not currently true,
** make it true by defining or undefining NDEBUG.
**
-** Setting NDEBUG makes the code smaller and run faster by disabling the
-** number assert() statements in the code. So we want the default action
+** Setting NDEBUG makes the code smaller and faster by disabling the
+** assert() statements in the code. So we want the default action
** to be for NDEBUG to be set and NDEBUG to be undefined only if SQLITE_DEBUG
** is set. Thus NDEBUG becomes an opt-in rather than an opt-out
** feature.
@@ -532,7 +514,7 @@ SQLITE_PRIVATE void sqlite3Coverage(int);
** In other words, ALWAYS and NEVER are added for defensive code.
**
** When doing coverage testing ALWAYS and NEVER are hard-coded to
-** be true and false so that the unreachable code then specify will
+** be true and false so that the unreachable code they specify will
** not be counted as untested code.
*/
#if defined(SQLITE_COVERAGE_TEST)
@@ -556,16 +538,12 @@ SQLITE_PRIVATE void sqlite3Coverage(int);
/*
** The macro unlikely() is a hint that surrounds a boolean
** expression that is usually false. Macro likely() surrounds
-** a boolean expression that is usually true. GCC is able to
-** use these hints to generate better code, sometimes.
+** a boolean expression that is usually true. These hints could,
+** in theory, be used by the compiler to generate better code, but
+** currently they are just comments for human readers.
*/
-#if defined(__GNUC__) && 0
-# define likely(X) __builtin_expect((X),1)
-# define unlikely(X) __builtin_expect((X),0)
-#else
-# define likely(X) !!(X)
-# define unlikely(X) !!(X)
-#endif
+#define likely(X) (X)
+#define unlikely(X) (X)
/************** Include sqlite3.h in the middle of sqliteInt.h ***************/
/************** Begin file sqlite3.h *****************************************/
@@ -678,9 +656,9 @@ extern "C" {
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
-#define SQLITE_VERSION "3.7.17"
-#define SQLITE_VERSION_NUMBER 3007017
-#define SQLITE_SOURCE_ID "2013-05-20 00:56:22 118a3b35693b134d56ebd780123b7fd6f1497668"
+#define SQLITE_VERSION "3.8.0.2"
+#define SQLITE_VERSION_NUMBER 3008000
+#define SQLITE_SOURCE_ID "2013-09-03 17:11:13 7dd4968f235d6e1ca9547cda9cf3bd570e1609ef"
/*
** CAPI3REF: Run-Time Library Version Numbers
@@ -1049,8 +1027,10 @@ SQLITE_API int sqlite3_exec(
#define SQLITE_IOERR_SEEK (SQLITE_IOERR | (22<<8))
#define SQLITE_IOERR_DELETE_NOENT (SQLITE_IOERR | (23<<8))
#define SQLITE_IOERR_MMAP (SQLITE_IOERR | (24<<8))
+#define SQLITE_IOERR_GETTEMPPATH (SQLITE_IOERR | (25<<8))
#define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8))
#define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8))
+#define SQLITE_BUSY_SNAPSHOT (SQLITE_BUSY | (2<<8))
#define SQLITE_CANTOPEN_NOTEMPDIR (SQLITE_CANTOPEN | (1<<8))
#define SQLITE_CANTOPEN_ISDIR (SQLITE_CANTOPEN | (2<<8))
#define SQLITE_CANTOPEN_FULLPATH (SQLITE_CANTOPEN | (3<<8))
@@ -1070,6 +1050,7 @@ SQLITE_API int sqlite3_exec(
#define SQLITE_CONSTRAINT_VTAB (SQLITE_CONSTRAINT | (9<<8))
#define SQLITE_NOTICE_RECOVER_WAL (SQLITE_NOTICE | (1<<8))
#define SQLITE_NOTICE_RECOVER_ROLLBACK (SQLITE_NOTICE | (2<<8))
+#define SQLITE_WARNING_AUTOINDEX (SQLITE_WARNING | (1<<8))
/*
** CAPI3REF: Flags For File Open Operations
@@ -3128,9 +3109,10 @@ SQLITE_API SQLITE_EXPERIMENTAL void *sqlite3_profile(sqlite3*,
** interface is to keep a GUI updated during a large query.
**
** ^The parameter P is passed through as the only parameter to the
-** callback function X. ^The parameter N is the number of
+** callback function X. ^The parameter N is the approximate number of
** [virtual machine instructions] that are evaluated between successive
-** invocations of the callback X.
+** invocations of the callback X. ^If N is less than one then the progress
+** handler is disabled.
**
** ^Only a single progress handler may be defined at one time per
** [database connection]; setting a new progress handler cancels the
@@ -4750,41 +4732,49 @@ SQLITE_API sqlite3 *sqlite3_context_db_handle(sqlite3_context*);
/*
** CAPI3REF: Function Auxiliary Data
**
-** The following two functions may be used by scalar SQL functions to
+** These functions may be used by (non-aggregate) SQL functions to
** associate metadata with argument values. If the same value is passed to
** multiple invocations of the same SQL function during query execution, under
-** some circumstances the associated metadata may be preserved. This may
-** be used, for example, to add a regular-expression matching scalar
-** function. The compiled version of the regular expression is stored as
-** metadata associated with the SQL value passed as the regular expression
-** pattern. The compiled regular expression can be reused on multiple
-** invocations of the same function so that the original pattern string
-** does not need to be recompiled on each invocation.
+** some circumstances the associated metadata may be preserved. An example
+** of where this might be useful is in a regular-expression matching
+** function. The compiled version of the regular expression can be stored as
+** metadata associated with the pattern string.
+** Then as long as the pattern string remains the same,
+** the compiled regular expression can be reused on multiple
+** invocations of the same function.
**
** ^The sqlite3_get_auxdata() interface returns a pointer to the metadata
** associated by the sqlite3_set_auxdata() function with the Nth argument
-** value to the application-defined function. ^If no metadata has been ever
-** been set for the Nth argument of the function, or if the corresponding
-** function parameter has changed since the meta-data was set,
-** then sqlite3_get_auxdata() returns a NULL pointer.
-**
-** ^The sqlite3_set_auxdata() interface saves the metadata
-** pointed to by its 3rd parameter as the metadata for the N-th
-** argument of the application-defined function. Subsequent
-** calls to sqlite3_get_auxdata() might return this data, if it has
-** not been destroyed.
-** ^If it is not NULL, SQLite will invoke the destructor
-** function given by the 4th parameter to sqlite3_set_auxdata() on
-** the metadata when the corresponding function parameter changes
-** or when the SQL statement completes, whichever comes first.
-**
-** SQLite is free to call the destructor and drop metadata on any
-** parameter of any function at any time. ^The only guarantee is that
-** the destructor will be called before the metadata is dropped.
+** value to the application-defined function. ^If there is no metadata
+** associated with the function argument, this sqlite3_get_auxdata() interface
+** returns a NULL pointer.
+**
+** ^The sqlite3_set_auxdata(C,N,P,X) interface saves P as metadata for the N-th
+** argument of the application-defined function. ^Subsequent
+** calls to sqlite3_get_auxdata(C,N) return P from the most recent
+** sqlite3_set_auxdata(C,N,P,X) call if the metadata is still valid or
+** NULL if the metadata has been discarded.
+** ^After each call to sqlite3_set_auxdata(C,N,P,X) where X is not NULL,
+** SQLite will invoke the destructor function X with parameter P exactly
+** once, when the metadata is discarded.
+** SQLite is free to discard the metadata at any time, including: <ul>
+** <li> when the corresponding function parameter changes, or
+** <li> when [sqlite3_reset()] or [sqlite3_finalize()] is called for the
+** SQL statement, or
+** <li> when sqlite3_set_auxdata() is invoked again on the same parameter, or
+** <li> during the original sqlite3_set_auxdata() call when a memory
+** allocation error occurs. </ul>)^
+**
+** Note the last bullet in particular. The destructor X in
+** sqlite3_set_auxdata(C,N,P,X) might be called immediately, before the
+** sqlite3_set_auxdata() interface even returns. Hence sqlite3_set_auxdata()
+** should be called near the end of the function implementation and the
+** function implementation should not make any use of P after
+** sqlite3_set_auxdata() has been called.
**
** ^(In practice, metadata is preserved between function calls for
-** expressions that are constant at compile time. This includes literal
-** values and [parameters].)^
+** function parameters that are compile-time constants, including literal
+** values and [parameters] and expressions composed from the same.)^
**
** These routines must be called from the same thread in which
** the SQL function is running.
@@ -5089,6 +5079,11 @@ SQLITE_API int sqlite3_key(
sqlite3 *db, /* Database to be rekeyed */
const void *pKey, int nKey /* The key */
);
+SQLITE_API int sqlite3_key_v2(
+ sqlite3 *db, /* Database to be rekeyed */
+ const char *zDbName, /* Name of the database */
+ const void *pKey, int nKey /* The key */
+);
/*
** Change the key on an open database. If the current database is not
@@ -5102,6 +5097,11 @@ SQLITE_API int sqlite3_rekey(
sqlite3 *db, /* Database to be rekeyed */
const void *pKey, int nKey /* The new key */
);
+SQLITE_API int sqlite3_rekey_v2(
+ sqlite3 *db, /* Database to be rekeyed */
+ const char *zDbName, /* Name of the database */
+ const void *pKey, int nKey /* The new key */
+);
/*
** Specify the activation key for a SEE database. Unless
@@ -5687,11 +5687,24 @@ SQLITE_API int sqlite3_enable_load_extension(sqlite3 *db, int onoff);
** on the list of automatic extensions is a harmless no-op. ^No entry point
** will be called more than once for each database connection that is opened.
**
-** See also: [sqlite3_reset_auto_extension()].
+** See also: [sqlite3_reset_auto_extension()]
+** and [sqlite3_cancel_auto_extension()]
*/
SQLITE_API int sqlite3_auto_extension(void (*xEntryPoint)(void));
/*
+** CAPI3REF: Cancel Automatic Extension Loading
+**
+** ^The [sqlite3_cancel_auto_extension(X)] interface unregisters the
+** initialization routine X that was registered using a prior call to
+** [sqlite3_auto_extension(X)]. ^The [sqlite3_cancel_auto_extension(X)]
+** routine returns 1 if initialization routine X was successfully
+** unregistered and it returns 0 if X was not on the list of initialization
+** routines.
+*/
+SQLITE_API int sqlite3_cancel_auto_extension(void (*xEntryPoint)(void));
+
+/*
** CAPI3REF: Reset Automatic Extension Loading
**
** ^This interface disables all automatic extensions previously
@@ -6803,6 +6816,12 @@ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int r
** on subsequent SQLITE_DBSTATUS_CACHE_WRITE requests is undefined.)^ ^The
** highwater mark associated with SQLITE_DBSTATUS_CACHE_WRITE is always 0.
** </dd>
+**
+** [[SQLITE_DBSTATUS_DEFERRED_FKS]] ^(<dt>SQLITE_DBSTATUS_DEFERRED_FKS</dt>
+** <dd>This parameter returns zero for the current value if and only if
+** all foreign key constraints (deferred or immediate) have been
+** resolved.)^ ^The highwater mark is always 0.
+** </dd>
** </dl>
*/
#define SQLITE_DBSTATUS_LOOKASIDE_USED 0
@@ -6815,7 +6834,8 @@ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int r
#define SQLITE_DBSTATUS_CACHE_HIT 7
#define SQLITE_DBSTATUS_CACHE_MISS 8
#define SQLITE_DBSTATUS_CACHE_WRITE 9
-#define SQLITE_DBSTATUS_MAX 9 /* Largest defined DBSTATUS */
+#define SQLITE_DBSTATUS_DEFERRED_FKS 10
+#define SQLITE_DBSTATUS_MAX 10 /* Largest defined DBSTATUS */
/*
@@ -6869,11 +6889,21 @@ SQLITE_API int sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg);
** A non-zero value in this counter may indicate an opportunity to
** improvement performance by adding permanent indices that do not
** need to be reinitialized each time the statement is run.</dd>
+**
+** [[SQLITE_STMTSTATUS_VM_STEP]] <dt>SQLITE_STMTSTATUS_VM_STEP</dt>
+** <dd>^This is the number of virtual machine operations executed
+** by the prepared statement if that number is less than or equal
+** to 2147483647. The number of virtual machine operations can be
+** used as a proxy for the total work done by the prepared statement.
+** If the number of virtual machine operations exceeds 2147483647
+** then the value returned by this statement status code is undefined.
+** </dd>
** </dl>
*/
#define SQLITE_STMTSTATUS_FULLSCAN_STEP 1
#define SQLITE_STMTSTATUS_SORT 2
#define SQLITE_STMTSTATUS_AUTOINDEX 3
+#define SQLITE_STMTSTATUS_VM_STEP 4
/*
** CAPI3REF: Custom Page Cache Object
@@ -7752,7 +7782,7 @@ SQLITE_API int sqlite3_vtab_on_conflict(sqlite3 *);
#if 0
} /* End of the 'extern "C"' block */
#endif
-#endif
+#endif /* _SQLITE3_H_ */
/*
** 2010 August 30
@@ -8154,6 +8184,12 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash*);
#endif
/*
+** Macros to compute minimum and maximum of two numbers.
+*/
+#define MIN(A,B) ((A)<(B)?(A):(B))
+#define MAX(A,B) ((A)>(B)?(A):(B))
+
+/*
** Check to see if this machine uses EBCDIC. (Yes, believe it or
** not, there are still machines out there that use EBCDIC.)
*/
@@ -8478,9 +8514,7 @@ typedef struct UnpackedRecord UnpackedRecord;
typedef struct VTable VTable;
typedef struct VtabCtx VtabCtx;
typedef struct Walker Walker;
-typedef struct WherePlan WherePlan;
typedef struct WhereInfo WhereInfo;
-typedef struct WhereLevel WhereLevel;
/*
** Defer sourcing vdbe.h and btree.h until after the "u8" and
@@ -8555,7 +8589,7 @@ SQLITE_PRIVATE int sqlite3BtreeOpen(
SQLITE_PRIVATE int sqlite3BtreeClose(Btree*);
SQLITE_PRIVATE int sqlite3BtreeSetCacheSize(Btree*,int);
SQLITE_PRIVATE int sqlite3BtreeSetMmapLimit(Btree*,sqlite3_int64);
-SQLITE_PRIVATE int sqlite3BtreeSetSafetyLevel(Btree*,int,int,int);
+SQLITE_PRIVATE int sqlite3BtreeSetPagerFlags(Btree*,unsigned);
SQLITE_PRIVATE int sqlite3BtreeSyncDisabled(Btree*);
SQLITE_PRIVATE int sqlite3BtreeSetPageSize(Btree *p, int nPagesize, int nReserve, int eFix);
SQLITE_PRIVATE int sqlite3BtreeGetPageSize(Btree*);
@@ -8779,7 +8813,6 @@ typedef struct Vdbe Vdbe;
** The names of the following types declared in vdbeInt.h are required
** for the VdbeOp definition.
*/
-typedef struct VdbeFunc VdbeFunc;
typedef struct Mem Mem;
typedef struct SubProgram SubProgram;
@@ -8803,7 +8836,6 @@ struct VdbeOp {
i64 *pI64; /* Used when p4type is P4_INT64 */
double *pReal; /* Used when p4type is P4_REAL */
FuncDef *pFunc; /* Used when p4type is P4_FUNCDEF */
- VdbeFunc *pVdbeFunc; /* Used when p4type is P4_VDBEFUNC */
CollSeq *pColl; /* Used when p4type is P4_COLLSEQ */
Mem *pMem; /* Used when p4type is P4_MEM */
VTable *pVtab; /* Used when p4type is P4_VTAB */
@@ -8857,7 +8889,6 @@ typedef struct VdbeOpList VdbeOpList;
#define P4_COLLSEQ (-4) /* P4 is a pointer to a CollSeq structure */
#define P4_FUNCDEF (-5) /* P4 is a pointer to a FuncDef structure */
#define P4_KEYINFO (-6) /* P4 is a pointer to a KeyInfo structure */
-#define P4_VDBEFUNC (-7) /* P4 is a pointer to a VdbeFunc structure */
#define P4_MEM (-8) /* P4 is a pointer to a Mem* structure */
#define P4_TRANSIENT 0 /* P4 is a pointer to a transient string */
#define P4_VTAB (-10) /* P4 is a pointer to an sqlite3_vtab structure */
@@ -8914,151 +8945,151 @@ typedef struct VdbeOpList VdbeOpList;
/************** Begin file opcodes.h *****************************************/
/* Automatically generated. Do not edit */
/* See the mkopcodeh.awk script for details */
-#define OP_Goto 1
-#define OP_Gosub 2
-#define OP_Return 3
-#define OP_Yield 4
-#define OP_HaltIfNull 5
-#define OP_Halt 6
-#define OP_Integer 7
-#define OP_Int64 8
-#define OP_Real 130 /* same as TK_FLOAT */
-#define OP_String8 94 /* same as TK_STRING */
-#define OP_String 9
-#define OP_Null 10
-#define OP_Blob 11
-#define OP_Variable 12
-#define OP_Move 13
-#define OP_Copy 14
-#define OP_SCopy 15
-#define OP_ResultRow 16
-#define OP_Concat 91 /* same as TK_CONCAT */
+#define OP_Function 1
+#define OP_Savepoint 2
+#define OP_AutoCommit 3
+#define OP_Transaction 4
+#define OP_SorterNext 5
+#define OP_Prev 6
+#define OP_Next 7
+#define OP_AggStep 8
+#define OP_Checkpoint 9
+#define OP_JournalMode 10
+#define OP_Vacuum 11
+#define OP_VFilter 12
+#define OP_VUpdate 13
+#define OP_Goto 14
+#define OP_Gosub 15
+#define OP_Return 16
+#define OP_Yield 17
+#define OP_HaltIfNull 18
+#define OP_Not 19 /* same as TK_NOT */
+#define OP_Halt 20
+#define OP_Integer 21
+#define OP_Int64 22
+#define OP_String 23
+#define OP_Null 24
+#define OP_Blob 25
+#define OP_Variable 26
+#define OP_Move 27
+#define OP_Copy 28
+#define OP_SCopy 29
+#define OP_ResultRow 30
+#define OP_CollSeq 31
+#define OP_AddImm 32
+#define OP_MustBeInt 33
+#define OP_RealAffinity 34
+#define OP_Permutation 35
+#define OP_Compare 36
+#define OP_Jump 37
+#define OP_Once 38
+#define OP_If 39
+#define OP_IfNot 40
+#define OP_Column 41
+#define OP_Affinity 42
+#define OP_MakeRecord 43
+#define OP_Count 44
+#define OP_ReadCookie 45
+#define OP_SetCookie 46
+#define OP_VerifyCookie 47
+#define OP_OpenRead 48
+#define OP_OpenWrite 49
+#define OP_OpenAutoindex 50
+#define OP_OpenEphemeral 51
+#define OP_SorterOpen 52
+#define OP_OpenPseudo 53
+#define OP_Close 54
+#define OP_SeekLt 55
+#define OP_SeekLe 56
+#define OP_SeekGe 57
+#define OP_SeekGt 58
+#define OP_Seek 59
+#define OP_NotFound 60
+#define OP_Found 61
+#define OP_IsUnique 62
+#define OP_NotExists 63
+#define OP_Sequence 64
+#define OP_NewRowid 65
+#define OP_Insert 66
+#define OP_InsertInt 67
+#define OP_Or 68 /* same as TK_OR */
+#define OP_And 69 /* same as TK_AND */
+#define OP_Delete 70
+#define OP_ResetCount 71
+#define OP_SorterCompare 72
+#define OP_IsNull 73 /* same as TK_ISNULL */
+#define OP_NotNull 74 /* same as TK_NOTNULL */
+#define OP_Ne 75 /* same as TK_NE */
+#define OP_Eq 76 /* same as TK_EQ */
+#define OP_Gt 77 /* same as TK_GT */
+#define OP_Le 78 /* same as TK_LE */
+#define OP_Lt 79 /* same as TK_LT */
+#define OP_Ge 80 /* same as TK_GE */
+#define OP_SorterData 81
+#define OP_BitAnd 82 /* same as TK_BITAND */
+#define OP_BitOr 83 /* same as TK_BITOR */
+#define OP_ShiftLeft 84 /* same as TK_LSHIFT */
+#define OP_ShiftRight 85 /* same as TK_RSHIFT */
#define OP_Add 86 /* same as TK_PLUS */
#define OP_Subtract 87 /* same as TK_MINUS */
#define OP_Multiply 88 /* same as TK_STAR */
#define OP_Divide 89 /* same as TK_SLASH */
#define OP_Remainder 90 /* same as TK_REM */
-#define OP_CollSeq 17
-#define OP_Function 18
-#define OP_BitAnd 82 /* same as TK_BITAND */
-#define OP_BitOr 83 /* same as TK_BITOR */
-#define OP_ShiftLeft 84 /* same as TK_LSHIFT */
-#define OP_ShiftRight 85 /* same as TK_RSHIFT */
-#define OP_AddImm 20
-#define OP_MustBeInt 21
-#define OP_RealAffinity 22
+#define OP_Concat 91 /* same as TK_CONCAT */
+#define OP_RowKey 92
+#define OP_BitNot 93 /* same as TK_BITNOT */
+#define OP_String8 94 /* same as TK_STRING */
+#define OP_RowData 95
+#define OP_Rowid 96
+#define OP_NullRow 97
+#define OP_Last 98
+#define OP_SorterSort 99
+#define OP_Sort 100
+#define OP_Rewind 101
+#define OP_SorterInsert 102
+#define OP_IdxInsert 103
+#define OP_IdxDelete 104
+#define OP_IdxRowid 105
+#define OP_IdxLT 106
+#define OP_IdxGE 107
+#define OP_Destroy 108
+#define OP_Clear 109
+#define OP_CreateIndex 110
+#define OP_CreateTable 111
+#define OP_ParseSchema 112
+#define OP_LoadAnalysis 113
+#define OP_DropTable 114
+#define OP_DropIndex 115
+#define OP_DropTrigger 116
+#define OP_IntegrityCk 117
+#define OP_RowSetAdd 118
+#define OP_RowSetRead 119
+#define OP_RowSetTest 120
+#define OP_Program 121
+#define OP_Param 122
+#define OP_FkCounter 123
+#define OP_FkIfZero 124
+#define OP_MemMax 125
+#define OP_IfPos 126
+#define OP_IfNeg 127
+#define OP_IfZero 128
+#define OP_AggFinal 129
+#define OP_Real 130 /* same as TK_FLOAT */
+#define OP_IncrVacuum 131
+#define OP_Expire 132
+#define OP_TableLock 133
+#define OP_VBegin 134
+#define OP_VCreate 135
+#define OP_VDestroy 136
+#define OP_VOpen 137
+#define OP_VColumn 138
+#define OP_VNext 139
+#define OP_VRename 140
#define OP_ToText 141 /* same as TK_TO_TEXT */
#define OP_ToBlob 142 /* same as TK_TO_BLOB */
#define OP_ToNumeric 143 /* same as TK_TO_NUMERIC*/
#define OP_ToInt 144 /* same as TK_TO_INT */
#define OP_ToReal 145 /* same as TK_TO_REAL */
-#define OP_Eq 76 /* same as TK_EQ */
-#define OP_Ne 75 /* same as TK_NE */
-#define OP_Lt 79 /* same as TK_LT */
-#define OP_Le 78 /* same as TK_LE */
-#define OP_Gt 77 /* same as TK_GT */
-#define OP_Ge 80 /* same as TK_GE */
-#define OP_Permutation 23
-#define OP_Compare 24
-#define OP_Jump 25
-#define OP_And 69 /* same as TK_AND */
-#define OP_Or 68 /* same as TK_OR */
-#define OP_Not 19 /* same as TK_NOT */
-#define OP_BitNot 93 /* same as TK_BITNOT */
-#define OP_Once 26
-#define OP_If 27
-#define OP_IfNot 28
-#define OP_IsNull 73 /* same as TK_ISNULL */
-#define OP_NotNull 74 /* same as TK_NOTNULL */
-#define OP_Column 29
-#define OP_Affinity 30
-#define OP_MakeRecord 31
-#define OP_Count 32
-#define OP_Savepoint 33
-#define OP_AutoCommit 34
-#define OP_Transaction 35
-#define OP_ReadCookie 36
-#define OP_SetCookie 37
-#define OP_VerifyCookie 38
-#define OP_OpenRead 39
-#define OP_OpenWrite 40
-#define OP_OpenAutoindex 41
-#define OP_OpenEphemeral 42
-#define OP_SorterOpen 43
-#define OP_OpenPseudo 44
-#define OP_Close 45
-#define OP_SeekLt 46
-#define OP_SeekLe 47
-#define OP_SeekGe 48
-#define OP_SeekGt 49
-#define OP_Seek 50
-#define OP_NotFound 51
-#define OP_Found 52
-#define OP_IsUnique 53
-#define OP_NotExists 54
-#define OP_Sequence 55
-#define OP_NewRowid 56
-#define OP_Insert 57
-#define OP_InsertInt 58
-#define OP_Delete 59
-#define OP_ResetCount 60
-#define OP_SorterCompare 61
-#define OP_SorterData 62
-#define OP_RowKey 63
-#define OP_RowData 64
-#define OP_Rowid 65
-#define OP_NullRow 66
-#define OP_Last 67
-#define OP_SorterSort 70
-#define OP_Sort 71
-#define OP_Rewind 72
-#define OP_SorterNext 81
-#define OP_Prev 92
-#define OP_Next 95
-#define OP_SorterInsert 96
-#define OP_IdxInsert 97
-#define OP_IdxDelete 98
-#define OP_IdxRowid 99
-#define OP_IdxLT 100
-#define OP_IdxGE 101
-#define OP_Destroy 102
-#define OP_Clear 103
-#define OP_CreateIndex 104
-#define OP_CreateTable 105
-#define OP_ParseSchema 106
-#define OP_LoadAnalysis 107
-#define OP_DropTable 108
-#define OP_DropIndex 109
-#define OP_DropTrigger 110
-#define OP_IntegrityCk 111
-#define OP_RowSetAdd 112
-#define OP_RowSetRead 113
-#define OP_RowSetTest 114
-#define OP_Program 115
-#define OP_Param 116
-#define OP_FkCounter 117
-#define OP_FkIfZero 118
-#define OP_MemMax 119
-#define OP_IfPos 120
-#define OP_IfNeg 121
-#define OP_IfZero 122
-#define OP_AggStep 123
-#define OP_AggFinal 124
-#define OP_Checkpoint 125
-#define OP_JournalMode 126
-#define OP_Vacuum 127
-#define OP_IncrVacuum 128
-#define OP_Expire 129
-#define OP_TableLock 131
-#define OP_VBegin 132
-#define OP_VCreate 133
-#define OP_VDestroy 134
-#define OP_VOpen 135
-#define OP_VFilter 136
-#define OP_VColumn 137
-#define OP_VNext 138
-#define OP_VRename 139
-#define OP_VUpdate 140
#define OP_Pagecount 146
#define OP_MaxPgcnt 147
#define OP_Trace 148
@@ -9078,24 +9109,24 @@ typedef struct VdbeOpList VdbeOpList;
#define OPFLG_OUT2 0x0020 /* out2: P2 is an output */
#define OPFLG_OUT3 0x0040 /* out3: P3 is an output */
#define OPFLG_INITIALIZER {\
-/* 0 */ 0x00, 0x01, 0x01, 0x04, 0x04, 0x10, 0x00, 0x02,\
-/* 8 */ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x24,\
-/* 16 */ 0x00, 0x00, 0x00, 0x24, 0x04, 0x05, 0x04, 0x00,\
-/* 24 */ 0x00, 0x01, 0x01, 0x05, 0x05, 0x00, 0x00, 0x00,\
-/* 32 */ 0x02, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00,\
-/* 40 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11,\
-/* 48 */ 0x11, 0x11, 0x08, 0x11, 0x11, 0x11, 0x11, 0x02,\
-/* 56 */ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
-/* 64 */ 0x00, 0x02, 0x00, 0x01, 0x4c, 0x4c, 0x01, 0x01,\
-/* 72 */ 0x01, 0x05, 0x05, 0x15, 0x15, 0x15, 0x15, 0x15,\
-/* 80 */ 0x15, 0x01, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c,\
-/* 88 */ 0x4c, 0x4c, 0x4c, 0x4c, 0x01, 0x24, 0x02, 0x01,\
-/* 96 */ 0x08, 0x08, 0x00, 0x02, 0x01, 0x01, 0x02, 0x00,\
-/* 104 */ 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
-/* 112 */ 0x0c, 0x45, 0x15, 0x01, 0x02, 0x00, 0x01, 0x08,\
-/* 120 */ 0x05, 0x05, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00,\
-/* 128 */ 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,\
-/* 136 */ 0x01, 0x00, 0x01, 0x00, 0x00, 0x04, 0x04, 0x04,\
+/* 0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01,\
+/* 8 */ 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0x01,\
+/* 16 */ 0x04, 0x04, 0x10, 0x24, 0x00, 0x02, 0x02, 0x02,\
+/* 24 */ 0x02, 0x02, 0x02, 0x00, 0x00, 0x24, 0x00, 0x00,\
+/* 32 */ 0x04, 0x05, 0x04, 0x00, 0x00, 0x01, 0x01, 0x05,\
+/* 40 */ 0x05, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00,\
+/* 48 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11,\
+/* 56 */ 0x11, 0x11, 0x11, 0x08, 0x11, 0x11, 0x11, 0x11,\
+/* 64 */ 0x02, 0x02, 0x00, 0x00, 0x4c, 0x4c, 0x00, 0x00,\
+/* 72 */ 0x00, 0x05, 0x05, 0x15, 0x15, 0x15, 0x15, 0x15,\
+/* 80 */ 0x15, 0x00, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c,\
+/* 88 */ 0x4c, 0x4c, 0x4c, 0x4c, 0x00, 0x24, 0x02, 0x00,\
+/* 96 */ 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x08, 0x08,\
+/* 104 */ 0x00, 0x02, 0x01, 0x01, 0x02, 0x00, 0x02, 0x02,\
+/* 112 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x45,\
+/* 120 */ 0x15, 0x01, 0x02, 0x00, 0x01, 0x08, 0x05, 0x05,\
+/* 128 */ 0x05, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00,\
+/* 136 */ 0x00, 0x00, 0x00, 0x01, 0x00, 0x04, 0x04, 0x04,\
/* 144 */ 0x04, 0x04, 0x02, 0x02, 0x00, 0x00, 0x00,}
/************** End of opcodes.h *********************************************/
@@ -9145,7 +9176,7 @@ SQLITE_PRIVATE sqlite3 *sqlite3VdbeDb(Vdbe*);
SQLITE_PRIVATE void sqlite3VdbeSetSql(Vdbe*, const char *z, int n, int);
SQLITE_PRIVATE void sqlite3VdbeSwap(Vdbe*,Vdbe*);
SQLITE_PRIVATE VdbeOp *sqlite3VdbeTakeOpArray(Vdbe*, int*, int*);
-SQLITE_PRIVATE sqlite3_value *sqlite3VdbeGetValue(Vdbe*, int, u8);
+SQLITE_PRIVATE sqlite3_value *sqlite3VdbeGetBoundValue(Vdbe*, int, u8);
SQLITE_PRIVATE void sqlite3VdbeSetVarmask(Vdbe*, int);
#ifndef SQLITE_OMIT_TRACE
SQLITE_PRIVATE char *sqlite3VdbeExpandSql(Vdbe*, const char*);
@@ -9259,8 +9290,20 @@ typedef struct PgHdr DbPage;
/*
** Flags that make up the mask passed to sqlite3PagerAcquire().
*/
-#define PAGER_ACQUIRE_NOCONTENT 0x01 /* Do not load data from disk */
-#define PAGER_ACQUIRE_READONLY 0x02 /* Read-only page is acceptable */
+#define PAGER_GET_NOCONTENT 0x01 /* Do not load data from disk */
+#define PAGER_GET_READONLY 0x02 /* Read-only page is acceptable */
+
+/*
+** Flags for sqlite3PagerSetFlags()
+*/
+#define PAGER_SYNCHRONOUS_OFF 0x01 /* PRAGMA synchronous=OFF */
+#define PAGER_SYNCHRONOUS_NORMAL 0x02 /* PRAGMA synchronous=NORMAL */
+#define PAGER_SYNCHRONOUS_FULL 0x03 /* PRAGMA synchronous=FULL */
+#define PAGER_SYNCHRONOUS_MASK 0x03 /* Mask for three values above */
+#define PAGER_FULLFSYNC 0x04 /* PRAGMA fullfsync=ON */
+#define PAGER_CKPT_FULLFSYNC 0x08 /* PRAGMA checkpoint_fullfsync=ON */
+#define PAGER_CACHESPILL 0x10 /* PRAGMA cache_spill=ON */
+#define PAGER_FLAGS_MASK 0x1c /* All above except SYNCHRONOUS */
/*
** The remainder of this file contains the declarations of the functions
@@ -9288,7 +9331,7 @@ SQLITE_PRIVATE int sqlite3PagerMaxPageCount(Pager*, int);
SQLITE_PRIVATE void sqlite3PagerSetCachesize(Pager*, int);
SQLITE_PRIVATE void sqlite3PagerSetMmapLimit(Pager *, sqlite3_int64);
SQLITE_PRIVATE void sqlite3PagerShrink(Pager*);
-SQLITE_PRIVATE void sqlite3PagerSetSafetyLevel(Pager*,int,int,int);
+SQLITE_PRIVATE void sqlite3PagerSetFlags(Pager*,unsigned);
SQLITE_PRIVATE int sqlite3PagerLockingMode(Pager *, int);
SQLITE_PRIVATE int sqlite3PagerSetJournalMode(Pager *, int);
SQLITE_PRIVATE int sqlite3PagerGetJournalMode(Pager*);
@@ -9917,7 +9960,6 @@ SQLITE_PRIVATE int sqlite3OsCloseFree(sqlite3_file *);
struct Db {
char *zName; /* Name of this database */
Btree *pBt; /* The B*Tree structure for this database file */
- u8 inTrans; /* 0: not writable. 1: Transaction. 2: Checkpoint */
u8 safety_level; /* How aggressive at syncing data to disk */
Schema *pSchema; /* Pointer to database schema (possibly shared) */
};
@@ -10063,9 +10105,10 @@ struct sqlite3 {
u8 busy; /* TRUE if currently initializing */
u8 orphanTrigger; /* Last statement is orphaned TEMP trigger */
} init;
- int activeVdbeCnt; /* Number of VDBEs currently executing */
- int writeVdbeCnt; /* Number of active VDBEs that are writing */
- int vdbeExecCnt; /* Number of nested calls to VdbeExec() */
+ int nVdbeActive; /* Number of VDBEs currently running */
+ int nVdbeRead; /* Number of active VDBEs that read or write */
+ int nVdbeWrite; /* Number of active VDBEs that read and write */
+ int nVdbeExec; /* Number of nested calls to VdbeExec() */
int nExtension; /* Number of loaded extensions */
void **aExtension; /* Array of shared library handles */
void (*xTrace)(void*,const char*); /* Trace function */
@@ -10101,7 +10144,7 @@ struct sqlite3 {
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
int (*xProgress)(void *); /* The progress callback */
void *pProgressArg; /* Argument to the progress callback */
- int nProgressOps; /* Number of opcodes for progress callback */
+ unsigned nProgressOps; /* Number of opcodes for progress callback */
#endif
#ifndef SQLITE_OMIT_VIRTUALTABLE
int nVTrans; /* Allocated size of aVTrans */
@@ -10119,6 +10162,7 @@ struct sqlite3 {
int nSavepoint; /* Number of non-transaction savepoints */
int nStatement; /* Number of nested statement-transactions */
i64 nDeferredCons; /* Net deferred constraints this transaction. */
+ i64 nDeferredImmCons; /* Net deferred immediate constraints */
int *pnBytesFreed; /* If not NULL, increment this in DbFree() */
#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
@@ -10150,30 +10194,34 @@ struct sqlite3 {
*/
#define SQLITE_VdbeTrace 0x00000001 /* True to trace VDBE execution */
#define SQLITE_InternChanges 0x00000002 /* Uncommitted Hash table changes */
-#define SQLITE_FullColNames 0x00000004 /* Show full column names on SELECT */
-#define SQLITE_ShortColNames 0x00000008 /* Show short columns names */
-#define SQLITE_CountRows 0x00000010 /* Count rows changed by INSERT, */
+#define SQLITE_FullFSync 0x00000004 /* Use full fsync on the backend */
+#define SQLITE_CkptFullFSync 0x00000008 /* Use full fsync for checkpoint */
+#define SQLITE_CacheSpill 0x00000010 /* OK to spill pager cache */
+#define SQLITE_FullColNames 0x00000020 /* Show full column names on SELECT */
+#define SQLITE_ShortColNames 0x00000040 /* Show short columns names */
+#define SQLITE_CountRows 0x00000080 /* Count rows changed by INSERT, */
/* DELETE, or UPDATE and return */
/* the count using a callback. */
-#define SQLITE_NullCallback 0x00000020 /* Invoke the callback once if the */
+#define SQLITE_NullCallback 0x00000100 /* Invoke the callback once if the */
/* result set is empty */
-#define SQLITE_SqlTrace 0x00000040 /* Debug print SQL as it executes */
-#define SQLITE_VdbeListing 0x00000080 /* Debug listings of VDBE programs */
-#define SQLITE_WriteSchema 0x00000100 /* OK to update SQLITE_MASTER */
-#define SQLITE_VdbeAddopTrace 0x00000200 /* Trace sqlite3VdbeAddOp() calls */
-#define SQLITE_IgnoreChecks 0x00000400 /* Do not enforce check constraints */
-#define SQLITE_ReadUncommitted 0x0000800 /* For shared-cache mode */
-#define SQLITE_LegacyFileFmt 0x00001000 /* Create new databases in format 1 */
-#define SQLITE_FullFSync 0x00002000 /* Use full fsync on the backend */
-#define SQLITE_CkptFullFSync 0x00004000 /* Use full fsync for checkpoint */
-#define SQLITE_RecoveryMode 0x00008000 /* Ignore schema errors */
-#define SQLITE_ReverseOrder 0x00010000 /* Reverse unordered SELECTs */
-#define SQLITE_RecTriggers 0x00020000 /* Enable recursive triggers */
-#define SQLITE_ForeignKeys 0x00040000 /* Enforce foreign key constraints */
-#define SQLITE_AutoIndex 0x00080000 /* Enable automatic indexes */
-#define SQLITE_PreferBuiltin 0x00100000 /* Preference to built-in funcs */
-#define SQLITE_LoadExtension 0x00200000 /* Enable load_extension */
-#define SQLITE_EnableTrigger 0x00400000 /* True to enable triggers */
+#define SQLITE_SqlTrace 0x00000200 /* Debug print SQL as it executes */
+#define SQLITE_VdbeListing 0x00000400 /* Debug listings of VDBE programs */
+#define SQLITE_WriteSchema 0x00000800 /* OK to update SQLITE_MASTER */
+#define SQLITE_VdbeAddopTrace 0x00001000 /* Trace sqlite3VdbeAddOp() calls */
+#define SQLITE_IgnoreChecks 0x00002000 /* Do not enforce check constraints */
+#define SQLITE_ReadUncommitted 0x0004000 /* For shared-cache mode */
+#define SQLITE_LegacyFileFmt 0x00008000 /* Create new databases in format 1 */
+#define SQLITE_RecoveryMode 0x00010000 /* Ignore schema errors */
+#define SQLITE_ReverseOrder 0x00020000 /* Reverse unordered SELECTs */
+#define SQLITE_RecTriggers 0x00040000 /* Enable recursive triggers */
+#define SQLITE_ForeignKeys 0x00080000 /* Enforce foreign key constraints */
+#define SQLITE_AutoIndex 0x00100000 /* Enable automatic indexes */
+#define SQLITE_PreferBuiltin 0x00200000 /* Preference to built-in funcs */
+#define SQLITE_LoadExtension 0x00400000 /* Enable load_extension */
+#define SQLITE_EnableTrigger 0x00800000 /* True to enable triggers */
+#define SQLITE_DeferFKs 0x01000000 /* Defer all FK constraints */
+#define SQLITE_QueryOnly 0x02000000 /* Disable database changes */
+
/*
** Bits of the sqlite3.dbOptFlags field that are used by the
@@ -10190,6 +10238,8 @@ struct sqlite3 {
#define SQLITE_OrderByIdxJoin 0x0080 /* ORDER BY of joins via index */
#define SQLITE_SubqCoroutine 0x0100 /* Evaluate subqueries as coroutines */
#define SQLITE_Transitive 0x0200 /* Transitive constraints */
+#define SQLITE_OmitNoopJoin 0x0400 /* Omit unused tables in joins */
+#define SQLITE_Stat3 0x0800 /* Use the SQLITE_STAT3 table */
#define SQLITE_AllOpts 0xffff /* All optimizations */
/*
@@ -10318,6 +10368,7 @@ struct FuncDestructor {
struct Savepoint {
char *zName; /* Savepoint name (nul-terminated) */
i64 nDeferredCons; /* Number of deferred fk violations */
+ i64 nDeferredImmCons; /* Number of deferred imm fk. */
Savepoint *pNext; /* Parent savepoint (if any) */
};
@@ -10636,12 +10687,16 @@ struct FKey {
** An instance of the following structure is passed as the first
** argument to sqlite3VdbeKeyCompare and is used to control the
** comparison of the two index keys.
+**
+** Note that aSortOrder[] and aColl[] have nField+1 slots. There
+** are nField slots for the columns of an index then one extra slot
+** for the rowid at the end.
*/
struct KeyInfo {
sqlite3 *db; /* The database connection */
u8 enc; /* Text encoding - one of the SQLITE_UTF* values */
- u16 nField; /* Number of entries in aColl[] */
- u8 *aSortOrder; /* Sort order for each column. May be NULL */
+ u16 nField; /* Maximum index for aColl[] and aSortOrder[] */
+ u8 *aSortOrder; /* Sort order for each column. */
CollSeq *aColl[1]; /* Collating sequence for each term of the key */
};
@@ -10710,11 +10765,13 @@ struct Index {
Schema *pSchema; /* Schema containing this index */
u8 *aSortOrder; /* for each column: True==DESC, False==ASC */
char **azColl; /* Array of collation sequence names for index */
+ Expr *pPartIdxWhere; /* WHERE clause for partial indices */
int tnum; /* DB Page containing root of this index */
u16 nColumn; /* Number of columns in table used by this index */
u8 onError; /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */
unsigned autoIndex:2; /* 1==UNIQUE, 2==PRIMARY KEY, 0==CREATE INDEX */
unsigned bUnordered:1; /* Use this index for == or IN queries only */
+ unsigned uniqNotNull:1; /* True if UNIQUE and NOT NULL for all columns */
#ifdef SQLITE_ENABLE_STAT3
int nSample; /* Number of elements in aSample[] */
tRowcnt avgEq; /* Average nEq value for key values not in aSample */
@@ -11061,6 +11118,11 @@ typedef u64 Bitmask;
#define BMS ((int)(sizeof(Bitmask)*8))
/*
+** A bit in a Bitmask
+*/
+#define MASKBIT(n) (((Bitmask)1)<<(n))
+
+/*
** The following structure describes the FROM clause of a SELECT statement.
** Each table or subquery in the FROM clause is a separate element of
** the SrcList.a[] array.
@@ -11080,8 +11142,8 @@ typedef u64 Bitmask;
** contains more than 63 columns and the 64-th or later column is used.
*/
struct SrcList {
- i16 nSrc; /* Number of tables or subqueries in the FROM clause */
- i16 nAlloc; /* Number of entries allocated in a[] below */
+ u8 nSrc; /* Number of tables or subqueries in the FROM clause */
+ u8 nAlloc; /* Number of entries allocated in a[] below */
struct SrcList_item {
Schema *pSchema; /* Schema to which this item is fixed */
char *zDatabase; /* Name of database holding this table */
@@ -11120,79 +11182,6 @@ struct SrcList {
/*
-** A WherePlan object holds information that describes a lookup
-** strategy.
-**
-** This object is intended to be opaque outside of the where.c module.
-** It is included here only so that that compiler will know how big it
-** is. None of the fields in this object should be used outside of
-** the where.c module.
-**
-** Within the union, pIdx is only used when wsFlags&WHERE_INDEXED is true.
-** pTerm is only used when wsFlags&WHERE_MULTI_OR is true. And pVtabIdx
-** is only used when wsFlags&WHERE_VIRTUALTABLE is true. It is never the
-** case that more than one of these conditions is true.
-*/
-struct WherePlan {
- u32 wsFlags; /* WHERE_* flags that describe the strategy */
- u16 nEq; /* Number of == constraints */
- u16 nOBSat; /* Number of ORDER BY terms satisfied */
- double nRow; /* Estimated number of rows (for EQP) */
- union {
- Index *pIdx; /* Index when WHERE_INDEXED is true */
- struct WhereTerm *pTerm; /* WHERE clause term for OR-search */
- sqlite3_index_info *pVtabIdx; /* Virtual table index to use */
- } u;
-};
-
-/*
-** For each nested loop in a WHERE clause implementation, the WhereInfo
-** structure contains a single instance of this structure. This structure
-** is intended to be private to the where.c module and should not be
-** access or modified by other modules.
-**
-** The pIdxInfo field is used to help pick the best index on a
-** virtual table. The pIdxInfo pointer contains indexing
-** information for the i-th table in the FROM clause before reordering.
-** All the pIdxInfo pointers are freed by whereInfoFree() in where.c.
-** All other information in the i-th WhereLevel object for the i-th table
-** after FROM clause ordering.
-*/
-struct WhereLevel {
- WherePlan plan; /* query plan for this element of the FROM clause */
- int iLeftJoin; /* Memory cell used to implement LEFT OUTER JOIN */
- int iTabCur; /* The VDBE cursor used to access the table */
- int iIdxCur; /* The VDBE cursor used to access pIdx */
- int addrBrk; /* Jump here to break out of the loop */
- int addrNxt; /* Jump here to start the next IN combination */
- int addrCont; /* Jump here to continue with the next loop cycle */
- int addrFirst; /* First instruction of interior of the loop */
- u8 iFrom; /* Which entry in the FROM clause */
- u8 op, p5; /* Opcode and P5 of the opcode that ends the loop */
- int p1, p2; /* Operands of the opcode used to ends the loop */
- union { /* Information that depends on plan.wsFlags */
- struct {
- int nIn; /* Number of entries in aInLoop[] */
- struct InLoop {
- int iCur; /* The VDBE cursor used by this IN operator */
- int addrInTop; /* Top of the IN loop */
- u8 eEndLoopOp; /* IN Loop terminator. OP_Next or OP_Prev */
- } *aInLoop; /* Information about each nested IN operator */
- } in; /* Used when plan.wsFlags&WHERE_IN_ABLE */
- Index *pCovidx; /* Possible covering index for WHERE_MULTI_OR */
- } u;
- double rOptCost; /* "Optimal" cost for this level */
-
- /* The following field is really not part of the current level. But
- ** we need a place to cache virtual table index information for each
- ** virtual table in the FROM clause and the WhereLevel structure is
- ** a convenient place since there is one WhereLevel for each FROM clause
- ** element.
- */
- sqlite3_index_info *pIdxInfo; /* Index info for n-th source table */
-};
-
-/*
** Flags appropriate for the wctrlFlags parameter of sqlite3WhereBegin()
** and the WhereInfo.wctrlFlags member.
*/
@@ -11205,33 +11194,12 @@ struct WhereLevel {
#define WHERE_FORCE_TABLE 0x0020 /* Do not use an index-only search */
#define WHERE_ONETABLE_ONLY 0x0040 /* Only code the 1st table in pTabList */
#define WHERE_AND_ONLY 0x0080 /* Don't use indices for OR terms */
+#define WHERE_GROUPBY 0x0100 /* pOrderBy is really a GROUP BY */
+#define WHERE_DISTINCTBY 0x0200 /* pOrderby is really a DISTINCT clause */
+#define WHERE_WANT_DISTINCT 0x0400 /* All output needs to be distinct */
-/*
-** The WHERE clause processing routine has two halves. The
-** first part does the start of the WHERE loop and the second
-** half does the tail of the WHERE loop. An instance of
-** this structure is returned by the first half and passed
-** into the second half to give some continuity.
+/* Allowed return values from sqlite3WhereIsDistinct()
*/
-struct WhereInfo {
- Parse *pParse; /* Parsing and code generating context */
- SrcList *pTabList; /* List of tables in the join */
- u16 nOBSat; /* Number of ORDER BY terms satisfied by indices */
- u16 wctrlFlags; /* Flags originally passed to sqlite3WhereBegin() */
- u8 okOnePass; /* Ok to use one-pass algorithm for UPDATE/DELETE */
- u8 untestedTerms; /* Not all WHERE terms resolved by outer loop */
- u8 eDistinct; /* One of the WHERE_DISTINCT_* values below */
- int iTop; /* The very beginning of the WHERE loop */
- int iContinue; /* Jump here to continue with next record */
- int iBreak; /* Jump here to break out of the loop */
- int nLevel; /* Number of nested loop */
- struct WhereClause *pWC; /* Decomposition of the WHERE clause */
- double savedNQueryLoop; /* pParse->nQueryLoop outside the WHERE loop */
- double nRowOut; /* Estimated number of output rows */
- WhereLevel a[1]; /* Information about each nest loop in WHERE */
-};
-
-/* Allowed values for WhereInfo.eDistinct and DistinctCtx.eTnctType */
#define WHERE_DISTINCT_NOOP 0 /* DISTINCT keyword not used */
#define WHERE_DISTINCT_UNIQUE 1 /* No duplicates */
#define WHERE_DISTINCT_ORDERED 2 /* All duplicates are adjacent */
@@ -11261,7 +11229,7 @@ struct WhereInfo {
struct NameContext {
Parse *pParse; /* The parser */
SrcList *pSrcList; /* One or more tables used to resolve names */
- ExprList *pEList; /* Optional list of named expressions */
+ ExprList *pEList; /* Optional list of result-set columns */
AggInfo *pAggInfo; /* Information about aggregates at this level */
NameContext *pNext; /* Next outer name context. NULL for outermost */
int nRef; /* Number of names resolved by this context */
@@ -11276,8 +11244,7 @@ struct NameContext {
#define NC_HasAgg 0x02 /* One or more aggregate functions seen */
#define NC_IsCheck 0x04 /* True if resolving names in a CHECK constraint */
#define NC_InAggFunc 0x08 /* True if analyzing arguments to an agg func */
-#define NC_AsMaybe 0x10 /* Resolve to AS terms of the result set only
- ** if no other resolution is available */
+#define NC_PartIdx 0x10 /* True if resolving a partial index WHERE */
/*
** An instance of the following structure contains all information
@@ -11305,7 +11272,7 @@ struct Select {
u16 selFlags; /* Various SF_* values */
int iLimit, iOffset; /* Memory registers holding LIMIT & OFFSET counters */
int addrOpenEphm[3]; /* OP_OpenEphem opcodes related to this select */
- double nSelectRow; /* Estimated number of result rows */
+ u64 nSelectRow; /* Estimated number of result rows */
SrcList *pSrc; /* The FROM clause */
Expr *pWhere; /* The WHERE clause */
ExprList *pGroupBy; /* The GROUP BY clause */
@@ -11332,6 +11299,7 @@ struct Select {
#define SF_Values 0x0080 /* Synthesized from VALUES clause */
#define SF_Materialize 0x0100 /* Force materialization of views */
#define SF_NestedFrom 0x0200 /* Part of a parenthesized FROM clause */
+#define SF_MaybeConvert 0x0400 /* Need convertCompoundSelectToSubquery() */
/*
@@ -11453,6 +11421,7 @@ struct Parse {
u8 iColCache; /* Next entry in aColCache[] to replace */
u8 isMultiWrite; /* True if statement may modify/insert multiple rows */
u8 mayAbort; /* True if statement may throw an ABORT exception */
+ u8 hasCompound; /* Need to invoke convertCompoundSelectToSubquery() */
int aTempReg[8]; /* Holding area for temporary registers */
int nRangeReg; /* Size of the temporary register block */
int iRangeReg; /* First register in temporary register block */
@@ -11462,6 +11431,7 @@ struct Parse {
int nSet; /* Number of sets used so far */
int nOnce; /* Number of OP_Once instructions so far */
int ckBase; /* Base register of data during check constraints */
+ int iPartIdxTab; /* Table corresponding to a partial index */
int iCacheLevel; /* ColCache valid when aColCache[].iLevel<=iCacheLevel */
int iCacheCnt; /* Counter used to generate aColCache[].lru values */
struct yColCache {
@@ -11489,7 +11459,7 @@ struct Parse {
/* Information used while coding trigger programs. */
Parse *pToplevel; /* Parse structure for main program (or NULL) */
Table *pTriggerTab; /* Table triggers are being coded for */
- double nQueryLoop; /* Estimated number of iterations of a query */
+ u32 nQueryLoop; /* Est number of iterations of a query (10*log2(N)) */
u32 oldmask; /* Mask of old.* columns referenced */
u32 newmask; /* Mask of new.* columns referenced */
u8 eTriggerOp; /* TK_UPDATE, TK_INSERT or TK_DELETE */
@@ -11677,10 +11647,11 @@ struct StrAccum {
int nChar; /* Length of the string so far */
int nAlloc; /* Amount of space allocated in zText */
int mxAlloc; /* Maximum allowed string length */
- u8 mallocFailed; /* Becomes true if any memory allocation fails */
u8 useMalloc; /* 0: none, 1: sqlite3DbMalloc, 2: sqlite3_malloc */
- u8 tooBig; /* Becomes true if string size exceeds limits */
+ u8 accError; /* STRACCUM_NOMEM or STRACCUM_TOOBIG */
};
+#define STRACCUM_NOMEM 1
+#define STRACCUM_TOOBIG 2
/*
** A pointer to this structure is used to communicate information
@@ -12043,7 +12014,7 @@ SQLITE_PRIVATE void sqlite3SrcListAssignCursors(Parse*, SrcList*);
SQLITE_PRIVATE void sqlite3IdListDelete(sqlite3*, IdList*);
SQLITE_PRIVATE void sqlite3SrcListDelete(sqlite3*, SrcList*);
SQLITE_PRIVATE Index *sqlite3CreateIndex(Parse*,Token*,Token*,SrcList*,ExprList*,int,Token*,
- Token*, int, int);
+ Expr*, int, int);
SQLITE_PRIVATE void sqlite3DropIndex(Parse*, SrcList*, int);
SQLITE_PRIVATE int sqlite3Select(Parse*, Select*, SelectDest*);
SQLITE_PRIVATE Select *sqlite3SelectNew(Parse*,ExprList*,SrcList*,Expr*,ExprList*,
@@ -12059,6 +12030,12 @@ SQLITE_PRIVATE void sqlite3DeleteFrom(Parse*, SrcList*, Expr*);
SQLITE_PRIVATE void sqlite3Update(Parse*, SrcList*, ExprList*, Expr*, int);
SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(Parse*,SrcList*,Expr*,ExprList*,ExprList*,u16,int);
SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo*);
+SQLITE_PRIVATE u64 sqlite3WhereOutputRowCount(WhereInfo*);
+SQLITE_PRIVATE int sqlite3WhereIsDistinct(WhereInfo*);
+SQLITE_PRIVATE int sqlite3WhereIsOrdered(WhereInfo*);
+SQLITE_PRIVATE int sqlite3WhereContinueLabel(WhereInfo*);
+SQLITE_PRIVATE int sqlite3WhereBreakLabel(WhereInfo*);
+SQLITE_PRIVATE int sqlite3WhereOkOnePass(WhereInfo*);
SQLITE_PRIVATE int sqlite3ExprCodeGetColumn(Parse*, Table*, int, int, int, u8);
SQLITE_PRIVATE void sqlite3ExprCodeGetColumnOfTable(Vdbe*, Table*, int, int, int);
SQLITE_PRIVATE void sqlite3ExprCodeMove(Parse*, int, int, int);
@@ -12085,8 +12062,9 @@ SQLITE_PRIVATE void sqlite3UnlinkAndDeleteIndex(sqlite3*,int,const char*);
SQLITE_PRIVATE void sqlite3Vacuum(Parse*);
SQLITE_PRIVATE int sqlite3RunVacuum(char**, sqlite3*);
SQLITE_PRIVATE char *sqlite3NameFromToken(sqlite3*, Token*);
-SQLITE_PRIVATE int sqlite3ExprCompare(Expr*, Expr*);
-SQLITE_PRIVATE int sqlite3ExprListCompare(ExprList*, ExprList*);
+SQLITE_PRIVATE int sqlite3ExprCompare(Expr*, Expr*, int);
+SQLITE_PRIVATE int sqlite3ExprListCompare(ExprList*, ExprList*, int);
+SQLITE_PRIVATE int sqlite3ExprImpliesExpr(Expr*, Expr*, int);
SQLITE_PRIVATE void sqlite3ExprAnalyzeAggregates(NameContext*, Expr*);
SQLITE_PRIVATE void sqlite3ExprAnalyzeAggList(NameContext*,ExprList*);
SQLITE_PRIVATE int sqlite3FunctionUsesThisSrc(Expr*, SrcList*);
@@ -12113,7 +12091,7 @@ SQLITE_PRIVATE int sqlite3ExprNeedsNoAffinityChange(const Expr*, char);
SQLITE_PRIVATE int sqlite3IsRowid(const char*);
SQLITE_PRIVATE void sqlite3GenerateRowDelete(Parse*, Table*, int, int, int, Trigger *, int);
SQLITE_PRIVATE void sqlite3GenerateRowIndexDelete(Parse*, Table*, int, int*);
-SQLITE_PRIVATE int sqlite3GenerateIndexKey(Parse*, Index*, int, int, int);
+SQLITE_PRIVATE int sqlite3GenerateIndexKey(Parse*, Index*, int, int, int, int*);
SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(Parse*,Table*,int,int,
int*,int,int,int,int,int*);
SQLITE_PRIVATE void sqlite3CompleteInsertion(Parse*, Table*, int, int, int*, int, int, int);
@@ -12316,6 +12294,7 @@ SQLITE_PRIVATE void sqlite3SelectPrep(Parse*, Select*, NameContext*);
SQLITE_PRIVATE int sqlite3MatchSpanName(const char*, const char*, const char*, const char*);
SQLITE_PRIVATE int sqlite3ResolveExprNames(NameContext*, Expr*);
SQLITE_PRIVATE void sqlite3ResolveSelectNames(Parse*, Select*, NameContext*);
+SQLITE_PRIVATE void sqlite3ResolveSelfReference(Parse*,Table*,int,Expr*,ExprList*);
SQLITE_PRIVATE int sqlite3ResolveOrderGroupBy(Parse*, Select*, ExprList*, const char*);
SQLITE_PRIVATE void sqlite3ColumnDefault(Vdbe *, Table *, int, int);
SQLITE_PRIVATE void sqlite3AlterFinishAddColumn(Parse *, Token *);
@@ -12335,6 +12314,7 @@ SQLITE_PRIVATE void sqlite3MinimumFileFormat(Parse*, int, int);
SQLITE_PRIVATE void sqlite3SchemaClear(void *);
SQLITE_PRIVATE Schema *sqlite3SchemaGet(sqlite3 *, Btree *);
SQLITE_PRIVATE int sqlite3SchemaToIndex(sqlite3 *db, Schema *);
+SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoAlloc(sqlite3*,int);
SQLITE_PRIVATE KeyInfo *sqlite3IndexKeyinfo(Parse *, Index *);
SQLITE_PRIVATE int sqlite3CreateFunc(sqlite3 *, const char *, int, int, void *,
void (*)(sqlite3_context*,int,sqlite3_value **),
@@ -12396,13 +12376,14 @@ SQLITE_PRIVATE int sqlite3Utf8To8(unsigned char*);
#else
SQLITE_PRIVATE void sqlite3VtabClear(sqlite3 *db, Table*);
SQLITE_PRIVATE void sqlite3VtabDisconnect(sqlite3 *db, Table *p);
-SQLITE_PRIVATE int sqlite3VtabSync(sqlite3 *db, char **);
+SQLITE_PRIVATE int sqlite3VtabSync(sqlite3 *db, Vdbe*);
SQLITE_PRIVATE int sqlite3VtabRollback(sqlite3 *db);
SQLITE_PRIVATE int sqlite3VtabCommit(sqlite3 *db);
SQLITE_PRIVATE void sqlite3VtabLock(VTable *);
SQLITE_PRIVATE void sqlite3VtabUnlock(VTable *);
SQLITE_PRIVATE void sqlite3VtabUnlockList(sqlite3*);
SQLITE_PRIVATE int sqlite3VtabSavepoint(sqlite3 *, int, int);
+SQLITE_PRIVATE void sqlite3VtabImportErrmsg(Vdbe*, sqlite3_vtab*);
SQLITE_PRIVATE VTable *sqlite3GetVTable(sqlite3*, Table*);
# define sqlite3VtabInSync(db) ((db)->nVTrans>0 && (db)->aVTrans==0)
#endif
@@ -13287,6 +13268,9 @@ typedef struct VdbeSorter VdbeSorter;
/* Opaque type used by the explainer */
typedef struct Explain Explain;
+/* Elements of the linked list at Vdbe.pAuxData */
+typedef struct AuxData AuxData;
+
/*
** A cursor is a pointer into a single BTree within a database file.
** The cursor can seek to a BTree entry with a particular key, or
@@ -13473,23 +13457,19 @@ struct Mem {
#define memIsValid(M) ((M)->flags & MEM_Invalid)==0
#endif
-
-/* A VdbeFunc is just a FuncDef (defined in sqliteInt.h) that contains
-** additional information about auxiliary information bound to arguments
-** of the function. This is used to implement the sqlite3_get_auxdata()
-** and sqlite3_set_auxdata() APIs. The "auxdata" is some auxiliary data
-** that can be associated with a constant argument to a function. This
-** allows functions such as "regexp" to compile their constant regular
-** expression argument once and reused the compiled code for multiple
-** invocations.
+/*
+** Each auxilliary data pointer stored by a user defined function
+** implementation calling sqlite3_set_auxdata() is stored in an instance
+** of this structure. All such structures associated with a single VM
+** are stored in a linked list headed at Vdbe.pAuxData. All are destroyed
+** when the VM is halted (if not before).
*/
-struct VdbeFunc {
- FuncDef *pFunc; /* The definition of the function */
- int nAux; /* Number of entries allocated for apAux[] */
- struct AuxData {
- void *pAux; /* Aux data for the i-th argument */
- void (*xDelete)(void *); /* Destructor for the aux data */
- } apAux[1]; /* One slot for each function argument */
+struct AuxData {
+ int iOp; /* Instruction number of OP_Function opcode */
+ int iArg; /* Index of function argument. */
+ void *pAux; /* Aux data pointer */
+ void (*xDelete)(void *); /* Destructor for the aux data */
+ AuxData *pNext; /* Next element in list */
};
/*
@@ -13507,12 +13487,14 @@ struct VdbeFunc {
*/
struct sqlite3_context {
FuncDef *pFunc; /* Pointer to function information. MUST BE FIRST */
- VdbeFunc *pVdbeFunc; /* Auxilary data, if created. */
Mem s; /* The return value is stored here */
Mem *pMem; /* Memory cell used to store aggregate context */
CollSeq *pColl; /* Collating sequence */
+ Vdbe *pVdbe; /* The VM that owns this context */
+ int iOp; /* Instruction number of OP_Function */
int isError; /* Error code returned by the function. */
- int skipFlag; /* Skip skip accumulator loading if true */
+ u8 skipFlag; /* Skip skip accumulator loading if true */
+ u8 fErrorOrAux; /* isError!=0 or pVdbe->pAuxData modified */
};
/*
@@ -13580,19 +13562,21 @@ struct Vdbe {
bft expired:1; /* True if the VM needs to be recompiled */
bft runOnlyOnce:1; /* Automatically expire on reset */
bft usesStmtJournal:1; /* True if uses a statement journal */
- bft readOnly:1; /* True for read-only statements */
+ bft readOnly:1; /* True for statements that do not write */
+ bft bIsReader:1; /* True for statements that read */
bft isPrepareV2:1; /* True if prepared with prepare_v2() */
bft doingRerun:1; /* True if rerunning after an auto-reprepare */
int nChange; /* Number of db changes made since last reset */
yDbMask btreeMask; /* Bitmask of db->aDb[] entries referenced */
yDbMask lockMask; /* Subset of btreeMask that requires a lock */
int iStatement; /* Statement number (or 0 if has not opened stmt) */
- int aCounter[3]; /* Counters used by sqlite3_stmt_status() */
+ u32 aCounter[5]; /* Counters used by sqlite3_stmt_status() */
#ifndef SQLITE_OMIT_TRACE
i64 startTime; /* Time when query started - used for profiling */
#endif
i64 nFkConstraint; /* Number of imm. FK constraints this VM */
i64 nStmtDefCons; /* Number of def. constraints when stmt started */
+ i64 nStmtDefImmCons; /* Number of def. imm constraints when stmt started */
char *zSql; /* Text of the SQL statement that generated this */
void *pFree; /* Free this when deleting the vdbe */
#ifdef SQLITE_DEBUG
@@ -13609,6 +13593,7 @@ struct Vdbe {
SubProgram *pProgram; /* Linked list of all sub-programs used by VM */
int nOnceFlag; /* Size of array aOnceFlag[] */
u8 *aOnceFlag; /* Flags for OP_Once */
+ AuxData *pAuxData; /* Linked list of auxdata allocations */
};
/*
@@ -13632,7 +13617,7 @@ SQLITE_PRIVATE u32 sqlite3VdbeSerialTypeLen(u32);
SQLITE_PRIVATE u32 sqlite3VdbeSerialType(Mem*, int);
SQLITE_PRIVATE u32 sqlite3VdbeSerialPut(unsigned char*, int, Mem*, int);
SQLITE_PRIVATE u32 sqlite3VdbeSerialGet(const unsigned char*, u32, Mem*);
-SQLITE_PRIVATE void sqlite3VdbeDeleteAuxData(VdbeFunc*, int);
+SQLITE_PRIVATE void sqlite3VdbeDeleteAuxData(Vdbe*, int, int);
int sqlite2BtreeKeyCompare(BtCursor *, const void *, int, int, int *);
SQLITE_PRIVATE int sqlite3VdbeIdxKeyCompare(VdbeCursor*,UnpackedRecord*,int*);
@@ -13953,6 +13938,16 @@ SQLITE_API int sqlite3_db_status(
break;
}
+ /* Set *pCurrent to non-zero if there are unresolved deferred foreign
+ ** key constraints. Set *pCurrent to zero if all foreign key constraints
+ ** have been satisfied. The *pHighwater is always set to zero.
+ */
+ case SQLITE_DBSTATUS_DEFERRED_FKS: {
+ *pHighwater = 0;
+ *pCurrent = db->nDeferredImmCons>0 || db->nDeferredCons>0;
+ break;
+ }
+
default: {
rc = SQLITE_ERROR;
}
@@ -17252,13 +17247,13 @@ static SQLITE_WSD struct Mem5Global {
} mem5;
/*
-** Access the static variable through a macro for SQLITE_OMIT_WSD
+** Access the static variable through a macro for SQLITE_OMIT_WSD.
*/
#define mem5 GLOBAL(struct Mem5Global, mem5)
/*
** Assuming mem5.zPool is divided up into an array of Mem5Link
-** structures, return a pointer to the idx-th such lik.
+** structures, return a pointer to the idx-th such link.
*/
#define MEM5LINK(idx) ((Mem5Link *)(&mem5.zPool[(idx)*mem5.szAtom]))
@@ -17354,7 +17349,7 @@ static int memsys5UnlinkFirst(int iLogsize){
** Return a block of memory of at least nBytes in size.
** Return NULL if unable. Return NULL if nBytes==0.
**
-** The caller guarantees that nByte positive.
+** The caller guarantees that nByte is positive.
**
** The caller has obtained a mutex prior to invoking this
** routine so there is never any chance that two or more
@@ -17476,7 +17471,7 @@ static void memsys5FreeUnsafe(void *pOld){
}
/*
-** Allocate nBytes of memory
+** Allocate nBytes of memory.
*/
static void *memsys5Malloc(int nBytes){
sqlite3_int64 *p = 0;
@@ -19908,7 +19903,7 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
nOut = precision + 10;
zOut = zExtra = sqlite3Malloc( nOut );
if( zOut==0 ){
- pAccum->mallocFailed = 1;
+ pAccum->accError = STRACCUM_NOMEM;
return;
}
}
@@ -19962,13 +19957,7 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
else prefix = 0;
}
if( xtype==etGENERIC && precision>0 ) precision--;
-#if 0
- /* Rounding works like BSD when the constant 0.4999 is used. Wierd! */
- for(idx=precision, rounder=0.4999; idx>0; idx--, rounder*=0.1);
-#else
- /* It makes more sense to use 0.5 */
for(idx=precision, rounder=0.5; idx>0; idx--, rounder*=0.1){}
-#endif
if( xtype==etFLOAT ) realvalue += rounder;
/* Normalize realvalue to within 10.0 > realvalue >= 1.0 */
exp = 0;
@@ -20023,10 +20012,10 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
}else{
e2 = exp;
}
- if( e2+precision+width > etBUFSIZE - 15 ){
- bufpt = zExtra = sqlite3Malloc( e2+precision+width+15 );
+ if( MAX(e2,0)+precision+width > etBUFSIZE - 15 ){
+ bufpt = zExtra = sqlite3Malloc( MAX(e2,0)+precision+width+15 );
if( bufpt==0 ){
- pAccum->mallocFailed = 1;
+ pAccum->accError = STRACCUM_NOMEM;
return;
}
}
@@ -20161,7 +20150,7 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
if( n>etBUFSIZE ){
bufpt = zExtra = sqlite3Malloc( n );
if( bufpt==0 ){
- pAccum->mallocFailed = 1;
+ pAccum->accError = STRACCUM_NOMEM;
return;
}
}else{
@@ -20239,22 +20228,20 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
*/
SQLITE_PRIVATE void sqlite3StrAccumAppend(StrAccum *p, const char *z, int N){
assert( z!=0 || N==0 );
- if( p->tooBig | p->mallocFailed ){
- testcase(p->tooBig);
- testcase(p->mallocFailed);
+ if( p->accError ){
+ testcase(p->accError==STRACCUM_TOOBIG);
+ testcase(p->accError==STRACCUM_NOMEM);
return;
}
assert( p->zText!=0 || p->nChar==0 );
- if( N<0 ){
+ if( N<=0 ){
+ if( N==0 || z[0]==0 ) return;
N = sqlite3Strlen30(z);
}
- if( N==0 || NEVER(z==0) ){
- return;
- }
if( p->nChar+N >= p->nAlloc ){
char *zNew;
if( !p->useMalloc ){
- p->tooBig = 1;
+ p->accError = STRACCUM_TOOBIG;
N = p->nAlloc - p->nChar - 1;
if( N<=0 ){
return;
@@ -20265,7 +20252,7 @@ SQLITE_PRIVATE void sqlite3StrAccumAppend(StrAccum *p, const char *z, int N){
szNew += N + 1;
if( szNew > p->mxAlloc ){
sqlite3StrAccumReset(p);
- p->tooBig = 1;
+ p->accError = STRACCUM_TOOBIG;
return;
}else{
p->nAlloc = (int)szNew;
@@ -20279,7 +20266,7 @@ SQLITE_PRIVATE void sqlite3StrAccumAppend(StrAccum *p, const char *z, int N){
if( zOld==0 && p->nChar>0 ) memcpy(zNew, p->zText, p->nChar);
p->zText = zNew;
}else{
- p->mallocFailed = 1;
+ p->accError = STRACCUM_NOMEM;
sqlite3StrAccumReset(p);
return;
}
@@ -20307,7 +20294,7 @@ SQLITE_PRIVATE char *sqlite3StrAccumFinish(StrAccum *p){
if( p->zText ){
memcpy(p->zText, p->zBase, p->nChar+1);
}else{
- p->mallocFailed = 1;
+ p->accError = STRACCUM_NOMEM;
}
}
}
@@ -20338,8 +20325,7 @@ SQLITE_PRIVATE void sqlite3StrAccumInit(StrAccum *p, char *zBase, int n, int mx)
p->nAlloc = n;
p->mxAlloc = mx;
p->useMalloc = 1;
- p->tooBig = 0;
- p->mallocFailed = 0;
+ p->accError = 0;
}
/*
@@ -20356,7 +20342,7 @@ SQLITE_PRIVATE char *sqlite3VMPrintf(sqlite3 *db, const char *zFormat, va_list a
acc.db = db;
sqlite3VXPrintf(&acc, 1, zFormat, ap);
z = sqlite3StrAccumFinish(&acc);
- if( acc.mallocFailed ){
+ if( acc.accError==STRACCUM_NOMEM ){
db->mallocFailed = 1;
}
return z;
@@ -20553,24 +20539,11 @@ static SQLITE_WSD struct sqlite3PrngType {
} sqlite3Prng;
/*
-** Get a single 8-bit random value from the RC4 PRNG. The Mutex
-** must be held while executing this routine.
-**
-** Why not just use a library random generator like lrand48() for this?
-** Because the OP_NewRowid opcode in the VDBE depends on having a very
-** good source of random numbers. The lrand48() library function may
-** well be good enough. But maybe not. Or maybe lrand48() has some
-** subtle problems on some systems that could cause problems. It is hard
-** to know. To minimize the risk of problems due to bad lrand48()
-** implementations, SQLite uses this random number generator based
-** on RC4, which we know works very well.
-**
-** (Later): Actually, OP_NewRowid does not depend on a good source of
-** randomness any more. But we will leave this code in all the same.
+** Return N random bytes.
*/
-static u8 randomByte(void){
+SQLITE_API void sqlite3_randomness(int N, void *pBuf){
unsigned char t;
-
+ unsigned char *zBuf = pBuf;
/* The "wsdPrng" macro will resolve to the pseudo-random number generator
** state vector. If writable static data is unsupported on the target,
@@ -20585,6 +20558,10 @@ static u8 randomByte(void){
# define wsdPrng sqlite3Prng
#endif
+#if SQLITE_THREADSAFE
+ sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_PRNG);
+ sqlite3_mutex_enter(mutex);
+#endif
/* Initialize the state of the random number generator once,
** the first time this routine is called. The seed value does
@@ -20613,28 +20590,14 @@ static u8 randomByte(void){
wsdPrng.isInit = 1;
}
- /* Generate and return single random byte
- */
- wsdPrng.i++;
- t = wsdPrng.s[wsdPrng.i];
- wsdPrng.j += t;
- wsdPrng.s[wsdPrng.i] = wsdPrng.s[wsdPrng.j];
- wsdPrng.s[wsdPrng.j] = t;
- t += wsdPrng.s[wsdPrng.i];
- return wsdPrng.s[t];
-}
-
-/*
-** Return N random bytes.
-*/
-SQLITE_API void sqlite3_randomness(int N, void *pBuf){
- unsigned char *zBuf = pBuf;
-#if SQLITE_THREADSAFE
- sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_PRNG);
-#endif
- sqlite3_mutex_enter(mutex);
while( N-- ){
- *(zBuf++) = randomByte();
+ wsdPrng.i++;
+ t = wsdPrng.s[wsdPrng.i];
+ wsdPrng.j += t;
+ wsdPrng.s[wsdPrng.i] = wsdPrng.s[wsdPrng.j];
+ wsdPrng.s[wsdPrng.j] = t;
+ t += wsdPrng.s[wsdPrng.i];
+ *(zBuf++) = wsdPrng.s[t];
}
sqlite3_mutex_leave(mutex);
}
@@ -22727,78 +22690,78 @@ SQLITE_PRIVATE void *sqlite3HashInsert(Hash *pH, const char *pKey, int nKey, voi
#if !defined(SQLITE_OMIT_EXPLAIN) || !defined(NDEBUG) || defined(VDBE_PROFILE) || defined(SQLITE_DEBUG)
SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
static const char *const azName[] = { "?",
- /* 1 */ "Goto",
- /* 2 */ "Gosub",
- /* 3 */ "Return",
- /* 4 */ "Yield",
- /* 5 */ "HaltIfNull",
- /* 6 */ "Halt",
- /* 7 */ "Integer",
- /* 8 */ "Int64",
- /* 9 */ "String",
- /* 10 */ "Null",
- /* 11 */ "Blob",
- /* 12 */ "Variable",
- /* 13 */ "Move",
- /* 14 */ "Copy",
- /* 15 */ "SCopy",
- /* 16 */ "ResultRow",
- /* 17 */ "CollSeq",
- /* 18 */ "Function",
+ /* 1 */ "Function",
+ /* 2 */ "Savepoint",
+ /* 3 */ "AutoCommit",
+ /* 4 */ "Transaction",
+ /* 5 */ "SorterNext",
+ /* 6 */ "Prev",
+ /* 7 */ "Next",
+ /* 8 */ "AggStep",
+ /* 9 */ "Checkpoint",
+ /* 10 */ "JournalMode",
+ /* 11 */ "Vacuum",
+ /* 12 */ "VFilter",
+ /* 13 */ "VUpdate",
+ /* 14 */ "Goto",
+ /* 15 */ "Gosub",
+ /* 16 */ "Return",
+ /* 17 */ "Yield",
+ /* 18 */ "HaltIfNull",
/* 19 */ "Not",
- /* 20 */ "AddImm",
- /* 21 */ "MustBeInt",
- /* 22 */ "RealAffinity",
- /* 23 */ "Permutation",
- /* 24 */ "Compare",
- /* 25 */ "Jump",
- /* 26 */ "Once",
- /* 27 */ "If",
- /* 28 */ "IfNot",
- /* 29 */ "Column",
- /* 30 */ "Affinity",
- /* 31 */ "MakeRecord",
- /* 32 */ "Count",
- /* 33 */ "Savepoint",
- /* 34 */ "AutoCommit",
- /* 35 */ "Transaction",
- /* 36 */ "ReadCookie",
- /* 37 */ "SetCookie",
- /* 38 */ "VerifyCookie",
- /* 39 */ "OpenRead",
- /* 40 */ "OpenWrite",
- /* 41 */ "OpenAutoindex",
- /* 42 */ "OpenEphemeral",
- /* 43 */ "SorterOpen",
- /* 44 */ "OpenPseudo",
- /* 45 */ "Close",
- /* 46 */ "SeekLt",
- /* 47 */ "SeekLe",
- /* 48 */ "SeekGe",
- /* 49 */ "SeekGt",
- /* 50 */ "Seek",
- /* 51 */ "NotFound",
- /* 52 */ "Found",
- /* 53 */ "IsUnique",
- /* 54 */ "NotExists",
- /* 55 */ "Sequence",
- /* 56 */ "NewRowid",
- /* 57 */ "Insert",
- /* 58 */ "InsertInt",
- /* 59 */ "Delete",
- /* 60 */ "ResetCount",
- /* 61 */ "SorterCompare",
- /* 62 */ "SorterData",
- /* 63 */ "RowKey",
- /* 64 */ "RowData",
- /* 65 */ "Rowid",
- /* 66 */ "NullRow",
- /* 67 */ "Last",
+ /* 20 */ "Halt",
+ /* 21 */ "Integer",
+ /* 22 */ "Int64",
+ /* 23 */ "String",
+ /* 24 */ "Null",
+ /* 25 */ "Blob",
+ /* 26 */ "Variable",
+ /* 27 */ "Move",
+ /* 28 */ "Copy",
+ /* 29 */ "SCopy",
+ /* 30 */ "ResultRow",
+ /* 31 */ "CollSeq",
+ /* 32 */ "AddImm",
+ /* 33 */ "MustBeInt",
+ /* 34 */ "RealAffinity",
+ /* 35 */ "Permutation",
+ /* 36 */ "Compare",
+ /* 37 */ "Jump",
+ /* 38 */ "Once",
+ /* 39 */ "If",
+ /* 40 */ "IfNot",
+ /* 41 */ "Column",
+ /* 42 */ "Affinity",
+ /* 43 */ "MakeRecord",
+ /* 44 */ "Count",
+ /* 45 */ "ReadCookie",
+ /* 46 */ "SetCookie",
+ /* 47 */ "VerifyCookie",
+ /* 48 */ "OpenRead",
+ /* 49 */ "OpenWrite",
+ /* 50 */ "OpenAutoindex",
+ /* 51 */ "OpenEphemeral",
+ /* 52 */ "SorterOpen",
+ /* 53 */ "OpenPseudo",
+ /* 54 */ "Close",
+ /* 55 */ "SeekLt",
+ /* 56 */ "SeekLe",
+ /* 57 */ "SeekGe",
+ /* 58 */ "SeekGt",
+ /* 59 */ "Seek",
+ /* 60 */ "NotFound",
+ /* 61 */ "Found",
+ /* 62 */ "IsUnique",
+ /* 63 */ "NotExists",
+ /* 64 */ "Sequence",
+ /* 65 */ "NewRowid",
+ /* 66 */ "Insert",
+ /* 67 */ "InsertInt",
/* 68 */ "Or",
/* 69 */ "And",
- /* 70 */ "SorterSort",
- /* 71 */ "Sort",
- /* 72 */ "Rewind",
+ /* 70 */ "Delete",
+ /* 71 */ "ResetCount",
+ /* 72 */ "SorterCompare",
/* 73 */ "IsNull",
/* 74 */ "NotNull",
/* 75 */ "Ne",
@@ -22807,7 +22770,7 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
/* 78 */ "Le",
/* 79 */ "Lt",
/* 80 */ "Ge",
- /* 81 */ "SorterNext",
+ /* 81 */ "SorterData",
/* 82 */ "BitAnd",
/* 83 */ "BitOr",
/* 84 */ "ShiftLeft",
@@ -22818,55 +22781,55 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
/* 89 */ "Divide",
/* 90 */ "Remainder",
/* 91 */ "Concat",
- /* 92 */ "Prev",
+ /* 92 */ "RowKey",
/* 93 */ "BitNot",
/* 94 */ "String8",
- /* 95 */ "Next",
- /* 96 */ "SorterInsert",
- /* 97 */ "IdxInsert",
- /* 98 */ "IdxDelete",
- /* 99 */ "IdxRowid",
- /* 100 */ "IdxLT",
- /* 101 */ "IdxGE",
- /* 102 */ "Destroy",
- /* 103 */ "Clear",
- /* 104 */ "CreateIndex",
- /* 105 */ "CreateTable",
- /* 106 */ "ParseSchema",
- /* 107 */ "LoadAnalysis",
- /* 108 */ "DropTable",
- /* 109 */ "DropIndex",
- /* 110 */ "DropTrigger",
- /* 111 */ "IntegrityCk",
- /* 112 */ "RowSetAdd",
- /* 113 */ "RowSetRead",
- /* 114 */ "RowSetTest",
- /* 115 */ "Program",
- /* 116 */ "Param",
- /* 117 */ "FkCounter",
- /* 118 */ "FkIfZero",
- /* 119 */ "MemMax",
- /* 120 */ "IfPos",
- /* 121 */ "IfNeg",
- /* 122 */ "IfZero",
- /* 123 */ "AggStep",
- /* 124 */ "AggFinal",
- /* 125 */ "Checkpoint",
- /* 126 */ "JournalMode",
- /* 127 */ "Vacuum",
- /* 128 */ "IncrVacuum",
- /* 129 */ "Expire",
+ /* 95 */ "RowData",
+ /* 96 */ "Rowid",
+ /* 97 */ "NullRow",
+ /* 98 */ "Last",
+ /* 99 */ "SorterSort",
+ /* 100 */ "Sort",
+ /* 101 */ "Rewind",
+ /* 102 */ "SorterInsert",
+ /* 103 */ "IdxInsert",
+ /* 104 */ "IdxDelete",
+ /* 105 */ "IdxRowid",
+ /* 106 */ "IdxLT",
+ /* 107 */ "IdxGE",
+ /* 108 */ "Destroy",
+ /* 109 */ "Clear",
+ /* 110 */ "CreateIndex",
+ /* 111 */ "CreateTable",
+ /* 112 */ "ParseSchema",
+ /* 113 */ "LoadAnalysis",
+ /* 114 */ "DropTable",
+ /* 115 */ "DropIndex",
+ /* 116 */ "DropTrigger",
+ /* 117 */ "IntegrityCk",
+ /* 118 */ "RowSetAdd",
+ /* 119 */ "RowSetRead",
+ /* 120 */ "RowSetTest",
+ /* 121 */ "Program",
+ /* 122 */ "Param",
+ /* 123 */ "FkCounter",
+ /* 124 */ "FkIfZero",
+ /* 125 */ "MemMax",
+ /* 126 */ "IfPos",
+ /* 127 */ "IfNeg",
+ /* 128 */ "IfZero",
+ /* 129 */ "AggFinal",
/* 130 */ "Real",
- /* 131 */ "TableLock",
- /* 132 */ "VBegin",
- /* 133 */ "VCreate",
- /* 134 */ "VDestroy",
- /* 135 */ "VOpen",
- /* 136 */ "VFilter",
- /* 137 */ "VColumn",
- /* 138 */ "VNext",
- /* 139 */ "VRename",
- /* 140 */ "VUpdate",
+ /* 131 */ "IncrVacuum",
+ /* 132 */ "Expire",
+ /* 133 */ "TableLock",
+ /* 134 */ "VBegin",
+ /* 135 */ "VCreate",
+ /* 136 */ "VDestroy",
+ /* 137 */ "VOpen",
+ /* 138 */ "VColumn",
+ /* 139 */ "VNext",
+ /* 140 */ "VRename",
/* 141 */ "ToText",
/* 142 */ "ToBlob",
/* 143 */ "ToNumeric",
@@ -22931,13 +22894,6 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
*/
#if SQLITE_OS_UNIX /* This file is used on unix only */
-/* Use posix_fallocate() if it is available
-*/
-#if !defined(HAVE_POSIX_FALLOCATE) \
- && (_XOPEN_SOURCE >= 600 || _POSIX_C_SOURCE >= 200112L)
-# define HAVE_POSIX_FALLOCATE 1
-#endif
-
/*
** There are various methods for file locking used for concurrency
** control:
@@ -26868,15 +26824,19 @@ static int unixFileControl(sqlite3_file *id, int op, void *pArg){
}
case SQLITE_FCNTL_MMAP_SIZE: {
i64 newLimit = *(i64*)pArg;
+ int rc = SQLITE_OK;
if( newLimit>sqlite3GlobalConfig.mxMmap ){
newLimit = sqlite3GlobalConfig.mxMmap;
}
*(i64*)pArg = pFile->mmapSizeMax;
- if( newLimit>=0 ){
+ if( newLimit>=0 && newLimit!=pFile->mmapSizeMax && pFile->nFetchOut==0 ){
pFile->mmapSizeMax = newLimit;
- if( newLimit<pFile->mmapSize ) pFile->mmapSize = newLimit;
+ if( pFile->mmapSize>0 ){
+ unixUnmapfile(pFile);
+ rc = unixMapfile(pFile, -1);
+ }
}
- return SQLITE_OK;
+ return rc;
}
#ifdef SQLITE_DEBUG
/* The pager calls this method to signal that it has done
@@ -30526,6 +30486,7 @@ SQLITE_API int sqlite3_os_end(void){
#ifdef __CYGWIN__
# include <sys/cygwin.h>
+/* # include <errno.h> */
#endif
/*
@@ -30802,13 +30763,6 @@ WINBASEAPI BOOL WINAPI UnmapViewOfFile(LPCVOID);
#endif /* SQLITE_WIN32_FILEMAPPING_API && !defined(SQLITE_OMIT_WAL) */
/*
-** Macro to find the minimum of two numeric values.
-*/
-#ifndef MIN
-# define MIN(x,y) ((x)<(y)?(x):(y))
-#endif
-
-/*
** Some Microsoft compilers lack this definition.
*/
#ifndef INVALID_FILE_ATTRIBUTES
@@ -30954,6 +30908,7 @@ struct winFile {
# define SQLITE_WIN32_HEAP_FLAGS (0)
#endif
+
/*
** The winMemData structure stores information required by the Win32-specific
** sqlite3_mem_methods implementation.
@@ -33533,6 +33488,9 @@ static void winModeBit(winFile *pFile, unsigned char mask, int *pArg){
/* Forward declaration */
static int getTempname(int nBuf, char *zBuf);
+#if SQLITE_MAX_MMAP_SIZE>0
+static int winMapfile(winFile*, sqlite3_int64);
+#endif
/*
** Control and query of the open file handle.
@@ -33616,13 +33574,20 @@ static int winFileControl(sqlite3_file *id, int op, void *pArg){
#if SQLITE_MAX_MMAP_SIZE>0
case SQLITE_FCNTL_MMAP_SIZE: {
i64 newLimit = *(i64*)pArg;
+ int rc = SQLITE_OK;
if( newLimit>sqlite3GlobalConfig.mxMmap ){
newLimit = sqlite3GlobalConfig.mxMmap;
}
*(i64*)pArg = pFile->mmapSizeMax;
- if( newLimit>=0 ) pFile->mmapSizeMax = newLimit;
- OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
- return SQLITE_OK;
+ if( newLimit>=0 && newLimit!=pFile->mmapSizeMax && pFile->nFetchOut==0 ){
+ pFile->mmapSizeMax = newLimit;
+ if( pFile->mmapSize>0 ){
+ (void)winUnmapfile(pFile);
+ rc = winMapfile(pFile, -1);
+ }
+ }
+ OSTRACE(("FCNTL file=%p, rc=%d\n", pFile->h, rc));
+ return rc;
}
#endif
}
@@ -34408,10 +34373,10 @@ static int winMapfile(winFile *pFd, sqlite3_int64 nByte){
return SQLITE_OK;
}
assert( (nMap % winSysInfo.dwPageSize)==0 );
+ assert( sizeof(SIZE_T)==sizeof(sqlite3_int64) || nMap<=0xffffffff );
#if SQLITE_OS_WINRT
- pNew = osMapViewOfFileFromApp(pFd->hMap, flags, 0, nMap);
+ pNew = osMapViewOfFileFromApp(pFd->hMap, flags, 0, (SIZE_T)nMap);
#else
- assert( sizeof(SIZE_T)==sizeof(sqlite3_int64) || nMap<=0xffffffff );
pNew = osMapViewOfFile(pFd->hMap, flags, 0, 0, (SIZE_T)nMap);
#endif
if( pNew==NULL ){
@@ -34581,6 +34546,15 @@ static void *convertUtf8Filename(const char *zFilename){
}
/*
+** Maximum pathname length (in bytes) for windows. The MAX_PATH macro is
+** in characters, so we allocate 3 bytes per character assuming worst-case
+** 3-bytes-per-character UTF8.
+*/
+#ifndef SQLITE_WIN32_MAX_PATH
+# define SQLITE_WIN32_MAX_PATH (MAX_PATH*3)
+#endif
+
+/*
** Create a temporary file name in zBuf. zBuf must be big enough to
** hold at pVfs->mxPathname characters.
*/
@@ -34591,7 +34565,7 @@ static int getTempname(int nBuf, char *zBuf){
"0123456789";
size_t i, j;
int nTempPath;
- char zTempPath[MAX_PATH+2];
+ char zTempPath[SQLITE_WIN32_MAX_PATH+2];
/* It's odd to simulate an io-error here, but really this is just
** using the io-error infrastructure to test that SQLite handles this
@@ -34599,19 +34573,21 @@ static int getTempname(int nBuf, char *zBuf){
*/
SimulateIOError( return SQLITE_IOERR );
- memset(zTempPath, 0, MAX_PATH+2);
-
if( sqlite3_temp_directory ){
- sqlite3_snprintf(MAX_PATH-30, zTempPath, "%s", sqlite3_temp_directory);
+ sqlite3_snprintf(SQLITE_WIN32_MAX_PATH-30, zTempPath, "%s",
+ sqlite3_temp_directory);
}
#if !SQLITE_OS_WINRT
else if( isNT() ){
char *zMulti;
WCHAR zWidePath[MAX_PATH];
- osGetTempPathW(MAX_PATH-30, zWidePath);
+ if( osGetTempPathW(MAX_PATH-30, zWidePath)==0 ){
+ OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_GETTEMPPATH\n"));
+ return SQLITE_IOERR_GETTEMPPATH;
+ }
zMulti = unicodeToUtf8(zWidePath);
if( zMulti ){
- sqlite3_snprintf(MAX_PATH-30, zTempPath, "%s", zMulti);
+ sqlite3_snprintf(SQLITE_WIN32_MAX_PATH-30, zTempPath, "%s", zMulti);
sqlite3_free(zMulti);
}else{
OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n"));
@@ -34621,19 +34597,38 @@ static int getTempname(int nBuf, char *zBuf){
#ifdef SQLITE_WIN32_HAS_ANSI
else{
char *zUtf8;
- char zMbcsPath[MAX_PATH];
- osGetTempPathA(MAX_PATH-30, zMbcsPath);
+ char zMbcsPath[SQLITE_WIN32_MAX_PATH];
+ if( osGetTempPathA(SQLITE_WIN32_MAX_PATH-30, zMbcsPath)==0 ){
+ OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_GETTEMPPATH\n"));
+ return SQLITE_IOERR_GETTEMPPATH;
+ }
zUtf8 = sqlite3_win32_mbcs_to_utf8(zMbcsPath);
if( zUtf8 ){
- sqlite3_snprintf(MAX_PATH-30, zTempPath, "%s", zUtf8);
+ sqlite3_snprintf(SQLITE_WIN32_MAX_PATH-30, zTempPath, "%s", zUtf8);
sqlite3_free(zUtf8);
}else{
OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n"));
return SQLITE_IOERR_NOMEM;
}
}
-#endif
-#endif
+#else
+ else{
+ /*
+ ** Compiled without ANSI support and the current operating system
+ ** is not Windows NT; therefore, just zero the temporary buffer.
+ */
+ memset(zTempPath, 0, SQLITE_WIN32_MAX_PATH+2);
+ }
+#endif /* SQLITE_WIN32_HAS_ANSI */
+#else
+ else{
+ /*
+ ** Compiled for WinRT and the sqlite3_temp_directory is not set;
+ ** therefore, just zero the temporary buffer.
+ */
+ memset(zTempPath, 0, SQLITE_WIN32_MAX_PATH+2);
+ }
+#endif /* !SQLITE_OS_WINRT */
/* Check that the output buffer is large enough for the temporary file
** name. If it is not, return SQLITE_ERROR.
@@ -34719,7 +34714,7 @@ static int winOpen(
/* If argument zPath is a NULL pointer, this function is required to open
** a temporary file. Use this buffer to store the file name in.
*/
- char zTmpname[MAX_PATH+2]; /* Buffer used to create temp filename */
+ char zTmpname[SQLITE_WIN32_MAX_PATH+2]; /* Buffer used to create temp filename */
int rc = SQLITE_OK; /* Function Return Code */
#if !defined(NDEBUG) || SQLITE_OS_WINCE
@@ -34785,8 +34780,7 @@ static int winOpen(
*/
if( !zUtf8Name ){
assert(isDelete && !isOpenJournal);
- memset(zTmpname, 0, MAX_PATH+2);
- rc = getTempname(MAX_PATH+2, zTmpname);
+ rc = getTempname(SQLITE_WIN32_MAX_PATH+2, zTmpname);
if( rc!=SQLITE_OK ){
OSTRACE(("OPEN name=%s, rc=%s", zUtf8Name, sqlite3ErrName(rc)));
return rc;
@@ -35217,7 +35211,7 @@ static int winFullPathname(
#if defined(__CYGWIN__)
SimulateIOError( return SQLITE_ERROR );
UNUSED_PARAMETER(nFull);
- assert( pVfs->mxPathname>=MAX_PATH );
+ assert( pVfs->mxPathname>=SQLITE_WIN32_MAX_PATH );
assert( nFull>=pVfs->mxPathname );
if ( sqlite3_data_directory && !winIsVerbatimPathname(zRelative) ){
/*
@@ -35226,14 +35220,21 @@ static int winFullPathname(
** for converting the relative path name to an absolute
** one by prepending the data directory and a slash.
*/
- char zOut[MAX_PATH+1];
- memset(zOut, 0, MAX_PATH+1);
- cygwin_conv_path(CCP_POSIX_TO_WIN_A|CCP_RELATIVE, zRelative, zOut,
- MAX_PATH+1);
+ char zOut[SQLITE_WIN32_MAX_PATH+1];
+ if( cygwin_conv_path(CCP_POSIX_TO_WIN_A|CCP_RELATIVE, zRelative, zOut,
+ SQLITE_WIN32_MAX_PATH+1)<0 ){
+ winLogError(SQLITE_CANTOPEN_FULLPATH, (DWORD)errno, "cygwin_conv_path",
+ zRelative);
+ return SQLITE_CANTOPEN_FULLPATH;
+ }
sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s\\%s",
sqlite3_data_directory, zOut);
}else{
- cygwin_conv_path(CCP_POSIX_TO_WIN_A, zRelative, zFull, nFull);
+ if( cygwin_conv_path(CCP_POSIX_TO_WIN_A, zRelative, zFull, nFull)<0 ){
+ winLogError(SQLITE_CANTOPEN_FULLPATH, (DWORD)errno, "cygwin_conv_path",
+ zRelative);
+ return SQLITE_CANTOPEN_FULLPATH;
+ }
}
return SQLITE_OK;
#endif
@@ -35575,7 +35576,7 @@ SQLITE_API int sqlite3_os_init(void){
static sqlite3_vfs winVfs = {
3, /* iVersion */
sizeof(winFile), /* szOsFile */
- MAX_PATH, /* mxPathname */
+ SQLITE_WIN32_MAX_PATH, /* mxPathname */
0, /* pNext */
"win32", /* zName */
0, /* pAppData */
@@ -37222,7 +37223,7 @@ static sqlite3_pcache *pcache1Create(int szPage, int szExtra, int bPurgeable){
int sz; /* Bytes of memory required to allocate the new cache */
/*
- ** The seperateCache variable is true if each PCache has its own private
+ ** The separateCache variable is true if each PCache has its own private
** PGroup. In other words, separateCache is true for mode (1) where no
** mutexing is required.
**
@@ -37425,6 +37426,7 @@ static sqlite3_pcache_page *pcache1Fetch(
if( pCache->nPage>=pCache->nHash && pcache1ResizeHash(pCache) ){
goto fetch_out;
}
+ assert( pCache->nHash>0 && pCache->apHash );
/* Step 4. Try to recycle a page. */
if( pCache->bPurgeable && pGroup->pLruTail && (
@@ -38786,6 +38788,13 @@ struct PagerSavepoint {
};
/*
+** Bits of the Pager.doNotSpill flag. See further description below.
+*/
+#define SPILLFLAG_OFF 0x01 /* Never spill cache. Set via pragma */
+#define SPILLFLAG_ROLLBACK 0x02 /* Current rolling back, so do not spill */
+#define SPILLFLAG_NOSYNC 0x04 /* Spill is ok, but do not sync */
+
+/*
** A open page cache is an instance of struct Pager. A description of
** some of the more important member variables follows:
**
@@ -38851,19 +38860,21 @@ struct PagerSavepoint {
** journal file from being successfully finalized, the setMaster flag
** is cleared anyway (and the pager will move to ERROR state).
**
-** doNotSpill, doNotSyncSpill
+** doNotSpill
**
-** These two boolean variables control the behavior of cache-spills
-** (calls made by the pcache module to the pagerStress() routine to
-** write cached data to the file-system in order to free up memory).
+** This variables control the behavior of cache-spills (calls made by
+** the pcache module to the pagerStress() routine to write cached data
+** to the file-system in order to free up memory).
**
-** When doNotSpill is non-zero, writing to the database from pagerStress()
-** is disabled altogether. This is done in a very obscure case that
+** When bits SPILLFLAG_OFF or SPILLFLAG_ROLLBACK of doNotSpill are set,
+** writing to the database from pagerStress() is disabled altogether.
+** The SPILLFLAG_ROLLBACK case is done in a very obscure case that
** comes up during savepoint rollback that requires the pcache module
** to allocate a new page to prevent the journal file from being written
-** while it is being traversed by code in pager_playback().
+** while it is being traversed by code in pager_playback(). The SPILLFLAG_OFF
+** case is a user preference.
**
-** If doNotSyncSpill is non-zero, writing to the database from pagerStress()
+** If the SPILLFLAG_NOSYNC bit is set, writing to the database from pagerStress()
** is permitted, but syncing the journal file is not. This flag is set
** by sqlite3PagerWrite() when the file-system sector-size is larger than
** the database page-size in order to prevent a journal sync from happening
@@ -38967,7 +38978,6 @@ struct Pager {
u8 changeCountDone; /* Set after incrementing the change-counter */
u8 setMaster; /* True if a m-j name has been written to jrnl */
u8 doNotSpill; /* Do not spill the cache when non-zero */
- u8 doNotSyncSpill; /* Do not do a spill that requires jrnl sync */
u8 subjInMemory; /* True to use in-memory sub-journals */
Pgno dbSize; /* Number of pages in the database */
Pgno dbOrigSize; /* dbSize before the current transaction */
@@ -39346,13 +39356,17 @@ static char *print_pager_state(Pager *p){
** PagerSavepoint.pInSavepoint.
*/
static int subjRequiresPage(PgHdr *pPg){
- Pgno pgno = pPg->pgno;
Pager *pPager = pPg->pPager;
+ PagerSavepoint *p;
+ Pgno pgno;
int i;
- for(i=0; i<pPager->nSavepoint; i++){
- PagerSavepoint *p = &pPager->aSavepoint[i];
- if( p->nOrig>=pgno && 0==sqlite3BitvecTest(p->pInSavepoint, pgno) ){
- return 1;
+ if( pPager->nSavepoint ){
+ pgno = pPg->pgno;
+ for(i=0; i<pPager->nSavepoint; i++){
+ p = &pPager->aSavepoint[i];
+ if( p->nOrig>=pgno && 0==sqlite3BitvecTest(p->pInSavepoint, pgno) ){
+ return 1;
+ }
}
}
return 0;
@@ -40144,6 +40158,7 @@ static void pager_unlock(Pager *pPager){
pPager->changeCountDone = pPager->tempFile;
pPager->eState = PAGER_OPEN;
pPager->errCode = SQLITE_OK;
+ if( USEFETCH(pPager) ) sqlite3OsUnfetch(pPager->fd, 0, 0);
}
pPager->journalOff = 0;
@@ -40626,11 +40641,11 @@ static int pager_playback_one_page(
** requiring a journal-sync before it is written.
*/
assert( isSavepnt );
- assert( pPager->doNotSpill==0 );
- pPager->doNotSpill++;
+ assert( (pPager->doNotSpill & SPILLFLAG_ROLLBACK)==0 );
+ pPager->doNotSpill |= SPILLFLAG_ROLLBACK;
rc = sqlite3PagerAcquire(pPager, pgno, &pPg, 1);
- assert( pPager->doNotSpill==1 );
- pPager->doNotSpill--;
+ assert( (pPager->doNotSpill & SPILLFLAG_ROLLBACK)!=0 );
+ pPager->doNotSpill &= ~SPILLFLAG_ROLLBACK;
if( rc!=SQLITE_OK ) return rc;
pPg->flags &= ~PGHDR_NEED_READ;
sqlite3PcacheMakeDirty(pPg);
@@ -41197,12 +41212,6 @@ static int readDbPage(PgHdr *pPg, u32 iFrame){
assert( pPager->eState>=PAGER_READER && !MEMDB );
assert( isOpen(pPager->fd) );
- if( NEVER(!isOpen(pPager->fd)) ){
- assert( pPager->tempFile );
- memset(pPg->pData, 0, pPager->pageSize);
- return SQLITE_OK;
- }
-
#ifndef SQLITE_OMIT_WAL
if( iFrame ){
/* Try to pull the page from the write-ahead log. */
@@ -41710,10 +41719,10 @@ SQLITE_PRIVATE void sqlite3PagerSetCachesize(Pager *pPager, int mxPage){
static void pagerFixMaplimit(Pager *pPager){
#if SQLITE_MAX_MMAP_SIZE>0
sqlite3_file *fd = pPager->fd;
- if( isOpen(fd) ){
+ if( isOpen(fd) && fd->pMethods->iVersion>=3 ){
sqlite3_int64 sz;
- pPager->bUseFetch = (fd->pMethods->iVersion>=3) && pPager->szMmap>0;
sz = pPager->szMmap;
+ pPager->bUseFetch = (sz>0);
sqlite3OsFileControlHint(pPager->fd, SQLITE_FCNTL_MMAP_SIZE, &sz);
}
#endif
@@ -41735,9 +41744,12 @@ SQLITE_PRIVATE void sqlite3PagerShrink(Pager *pPager){
}
/*
-** Adjust the robustness of the database to damage due to OS crashes
-** or power failures by changing the number of syncs()s when writing
-** the rollback journal. There are three levels:
+** Adjust settings of the pager to those specified in the pgFlags parameter.
+**
+** The "level" in pgFlags & PAGER_SYNCHRONOUS_MASK sets the robustness
+** of the database to damage due to OS crashes or power failures by
+** changing the number of syncs()s when writing the journals.
+** There are three levels:
**
** OFF sqlite3OsSync() is never called. This is the default
** for temporary and transient files.
@@ -41778,22 +41790,21 @@ SQLITE_PRIVATE void sqlite3PagerShrink(Pager *pPager){
** and FULL=3.
*/
#ifndef SQLITE_OMIT_PAGER_PRAGMAS
-SQLITE_PRIVATE void sqlite3PagerSetSafetyLevel(
+SQLITE_PRIVATE void sqlite3PagerSetFlags(
Pager *pPager, /* The pager to set safety level for */
- int level, /* PRAGMA synchronous. 1=OFF, 2=NORMAL, 3=FULL */
- int bFullFsync, /* PRAGMA fullfsync */
- int bCkptFullFsync /* PRAGMA checkpoint_fullfsync */
+ unsigned pgFlags /* Various flags */
){
+ unsigned level = pgFlags & PAGER_SYNCHRONOUS_MASK;
assert( level>=1 && level<=3 );
pPager->noSync = (level==1 || pPager->tempFile) ?1:0;
pPager->fullSync = (level==3 && !pPager->tempFile) ?1:0;
if( pPager->noSync ){
pPager->syncFlags = 0;
pPager->ckptSyncFlags = 0;
- }else if( bFullFsync ){
+ }else if( pgFlags & PAGER_FULLFSYNC ){
pPager->syncFlags = SQLITE_SYNC_FULL;
pPager->ckptSyncFlags = SQLITE_SYNC_FULL;
- }else if( bCkptFullFsync ){
+ }else if( pgFlags & PAGER_CKPT_FULLFSYNC ){
pPager->syncFlags = SQLITE_SYNC_NORMAL;
pPager->ckptSyncFlags = SQLITE_SYNC_FULL;
}else{
@@ -41804,6 +41815,11 @@ SQLITE_PRIVATE void sqlite3PagerSetSafetyLevel(
if( pPager->fullSync ){
pPager->walSyncFlags |= WAL_SYNC_TRANSACTIONS;
}
+ if( pgFlags & PAGER_CACHESPILL ){
+ pPager->doNotSpill &= ~SPILLFLAG_OFF;
+ }else{
+ pPager->doNotSpill |= SPILLFLAG_OFF;
+ }
}
#endif
@@ -42546,7 +42562,8 @@ static int pager_write_pagelist(Pager *pPager, PgHdr *pList){
*/
assert( rc!=SQLITE_OK || isOpen(pPager->fd) );
if( rc==SQLITE_OK
- && (pList->pDirty ? pPager->dbSize : pList->pgno+1)>pPager->dbHintSize
+ && pPager->dbHintSize<pPager->dbSize
+ && (pList->pDirty || pList->pgno>pPager->dbHintSize)
){
sqlite3_int64 szFile = pPager->pageSize * (sqlite3_int64)pPager->dbSize;
sqlite3OsFileControlHint(pPager->fd, SQLITE_FCNTL_SIZE_HINT, &szFile);
@@ -42703,13 +42720,14 @@ static int pagerStress(void *p, PgHdr *pPg){
assert( pPg->pPager==pPager );
assert( pPg->flags&PGHDR_DIRTY );
- /* The doNotSyncSpill flag is set during times when doing a sync of
+ /* The doNotSpill NOSYNC bit is set during times when doing a sync of
** journal (and adding a new header) is not allowed. This occurs
** during calls to sqlite3PagerWrite() while trying to journal multiple
** pages belonging to the same sector.
**
- ** The doNotSpill flag inhibits all cache spilling regardless of whether
- ** or not a sync is required. This is set during a rollback.
+ ** The doNotSpill ROLLBACK and OFF bits inhibits all cache spilling
+ ** regardless of whether or not a sync is required. This is set during
+ ** a rollback or by user request, respectively.
**
** Spilling is also prohibited when in an error state since that could
** lead to database corruption. In the current implementaton it
@@ -42719,8 +42737,13 @@ static int pagerStress(void *p, PgHdr *pPg){
** test for the error state as a safeguard against future changes.
*/
if( NEVER(pPager->errCode) ) return SQLITE_OK;
- if( pPager->doNotSpill ) return SQLITE_OK;
- if( pPager->doNotSyncSpill && (pPg->flags & PGHDR_NEED_SYNC)!=0 ){
+ testcase( pPager->doNotSpill & SPILLFLAG_ROLLBACK );
+ testcase( pPager->doNotSpill & SPILLFLAG_OFF );
+ testcase( pPager->doNotSpill & SPILLFLAG_NOSYNC );
+ if( pPager->doNotSpill
+ && ((pPager->doNotSpill & (SPILLFLAG_ROLLBACK|SPILLFLAG_OFF))!=0
+ || (pPg->flags & PGHDR_NEED_SYNC)!=0)
+ ){
return SQLITE_OK;
}
@@ -43511,7 +43534,7 @@ static void pagerUnlockIfUnused(Pager *pPager){
** page is initialized to all zeros.
**
** If noContent is true, it means that we do not care about the contents
-** of the page. This occurs in two seperate scenarios:
+** of the page. This occurs in two scenarios:
**
** a) When reading a free-list leaf page from the database, and
**
@@ -43542,19 +43565,19 @@ SQLITE_PRIVATE int sqlite3PagerAcquire(
Pager *pPager, /* The pager open on the database file */
Pgno pgno, /* Page number to fetch */
DbPage **ppPage, /* Write a pointer to the page here */
- int flags /* PAGER_ACQUIRE_XXX flags */
+ int flags /* PAGER_GET_XXX flags */
){
int rc = SQLITE_OK;
PgHdr *pPg = 0;
u32 iFrame = 0; /* Frame to read from WAL file */
- const int noContent = (flags & PAGER_ACQUIRE_NOCONTENT);
+ const int noContent = (flags & PAGER_GET_NOCONTENT);
/* It is acceptable to use a read-only (mmap) page for any page except
** page 1 if there is no write-transaction open or the ACQUIRE_READONLY
** flag was specified by the caller. And so long as the db is not a
** temporary or in-memory database. */
const int bMmapOk = (pgno!=1 && USEFETCH(pPager)
- && (pPager->eState==PAGER_READER || (flags & PAGER_ACQUIRE_READONLY))
+ && (pPager->eState==PAGER_READER || (flags & PAGER_GET_READONLY))
#ifdef SQLITE_HAS_CODEC
&& pPager->xCodec==0
#endif
@@ -44074,13 +44097,13 @@ SQLITE_PRIVATE int sqlite3PagerWrite(DbPage *pDbPage){
int ii; /* Loop counter */
int needSync = 0; /* True if any page has PGHDR_NEED_SYNC */
- /* Set the doNotSyncSpill flag to 1. This is because we cannot allow
+ /* Set the doNotSpill NOSYNC bit to 1. This is because we cannot allow
** a journal header to be written between the pages journaled by
** this function.
*/
assert( !MEMDB );
- assert( pPager->doNotSyncSpill==0 );
- pPager->doNotSyncSpill++;
+ assert( (pPager->doNotSpill & SPILLFLAG_NOSYNC)==0 );
+ pPager->doNotSpill |= SPILLFLAG_NOSYNC;
/* This trick assumes that both the page-size and sector-size are
** an integer power of 2. It sets variable pg1 to the identifier
@@ -44139,8 +44162,8 @@ SQLITE_PRIVATE int sqlite3PagerWrite(DbPage *pDbPage){
}
}
- assert( pPager->doNotSyncSpill==1 );
- pPager->doNotSyncSpill--;
+ assert( (pPager->doNotSpill & SPILLFLAG_NOSYNC)!=0 );
+ pPager->doNotSpill &= ~SPILLFLAG_NOSYNC;
}else{
rc = pager_write(pDbPage);
}
@@ -44921,7 +44944,27 @@ SQLITE_PRIVATE void sqlite3PagerSetCodec(
SQLITE_PRIVATE void *sqlite3PagerGetCodec(Pager *pPager){
return pPager->pCodec;
}
-#endif
+
+/*
+** This function is called by the wal module when writing page content
+** into the log file.
+**
+** This function returns a pointer to a buffer containing the encrypted
+** page content. If a malloc fails, this function may return NULL.
+*/
+SQLITE_PRIVATE void *sqlite3PagerCodec(PgHdr *pPg){
+ void *aData = 0;
+ CODEC2(pPg->pPager, pPg->pData, pPg->pgno, 6, return 0, aData);
+ return aData;
+}
+
+/*
+** Return the current pager state
+*/
+SQLITE_PRIVATE int sqlite3PagerState(Pager *pPager){
+ return pPager->eState;
+}
+#endif /* SQLITE_HAS_CODEC */
#ifndef SQLITE_OMIT_AUTOVACUUM
/*
@@ -45476,21 +45519,6 @@ SQLITE_PRIVATE int sqlite3PagerWalFramesize(Pager *pPager){
}
#endif
-#ifdef SQLITE_HAS_CODEC
-/*
-** This function is called by the wal module when writing page content
-** into the log file.
-**
-** This function returns a pointer to a buffer containing the encrypted
-** page content. If a malloc fails, this function may return NULL.
-*/
-SQLITE_PRIVATE void *sqlite3PagerCodec(PgHdr *pPg){
- void *aData = 0;
- CODEC2(pPg->pPager, pPg->pData, pPg->pgno, 6, return 0, aData);
- return aData;
-}
-#endif /* SQLITE_HAS_CODEC */
-
#endif /* SQLITE_OMIT_DISKIO */
/************** End of pager.c ***********************************************/
@@ -47959,7 +47987,7 @@ SQLITE_PRIVATE int sqlite3WalBeginWriteTransaction(Wal *pWal){
if( memcmp(&pWal->hdr, (void *)walIndexHdr(pWal), sizeof(WalIndexHdr))!=0 ){
walUnlockExclusive(pWal, WAL_WRITE_LOCK, 1);
pWal->writeLock = 0;
- rc = SQLITE_BUSY;
+ rc = SQLITE_BUSY_SNAPSHOT;
}
return rc;
@@ -49131,14 +49159,19 @@ struct BtCursor {
/*
** Potential values for BtCursor.eState.
**
-** CURSOR_VALID:
-** Cursor points to a valid entry. getPayload() etc. may be called.
-**
** CURSOR_INVALID:
** Cursor does not point to a valid entry. This can happen (for example)
** because the table is empty or because BtreeCursorFirst() has not been
** called.
**
+** CURSOR_VALID:
+** Cursor points to a valid entry. getPayload() etc. may be called.
+**
+** CURSOR_SKIPNEXT:
+** Cursor is valid except that the Cursor.skipNext field is non-zero
+** indicating that the next sqlite3BtreeNext() or sqlite3BtreePrevious()
+** operation should be a no-op.
+**
** CURSOR_REQUIRESEEK:
** The table that this cursor was opened on still exists, but has been
** modified since the cursor was last used. The cursor position is saved
@@ -49155,8 +49188,9 @@ struct BtCursor {
*/
#define CURSOR_INVALID 0
#define CURSOR_VALID 1
-#define CURSOR_REQUIRESEEK 2
-#define CURSOR_FAULT 3
+#define CURSOR_SKIPNEXT 2
+#define CURSOR_REQUIRESEEK 3
+#define CURSOR_FAULT 4
/*
** The database page the PENDING_BYTE occupies. This page is never used.
@@ -50270,6 +50304,9 @@ static int btreeRestoreCursorPosition(BtCursor *pCur){
sqlite3_free(pCur->pKey);
pCur->pKey = 0;
assert( pCur->eState==CURSOR_VALID || pCur->eState==CURSOR_INVALID );
+ if( pCur->skipNext && pCur->eState==CURSOR_VALID ){
+ pCur->eState = CURSOR_SKIPNEXT;
+ }
}
return rc;
}
@@ -50295,7 +50332,7 @@ SQLITE_PRIVATE int sqlite3BtreeCursorHasMoved(BtCursor *pCur, int *pHasMoved){
*pHasMoved = 1;
return rc;
}
- if( pCur->eState!=CURSOR_VALID || pCur->skipNext!=0 ){
+ if( pCur->eState!=CURSOR_VALID || NEVER(pCur->skipNext!=0) ){
*pHasMoved = 1;
}else{
*pHasMoved = 0;
@@ -50483,7 +50520,8 @@ static void btreeParseCellPtr(
assert( n==4-4*pPage->leaf );
if( pPage->intKey ){
if( pPage->hasData ){
- n += getVarint32(&pCell[n], nPayload);
+ assert( n==0 );
+ n = getVarint32(pCell, nPayload);
}else{
nPayload = 0;
}
@@ -50761,7 +50799,7 @@ static int allocateSpace(MemPage *pPage, int nByte, int *pIdx){
}else if( gap+2<=top ){
/* Search the freelist looking for a free slot big enough to satisfy
** the request. The allocation is made from the first free slot in
- ** the list that is large enough to accomadate it.
+ ** the list that is large enough to accommodate it.
*/
int pc, addr;
for(addr=hdr+1; (pc = get2byte(&data[addr]))>0; addr=pc){
@@ -51127,15 +51165,12 @@ static int btreeGetPage(
BtShared *pBt, /* The btree */
Pgno pgno, /* Number of the page to fetch */
MemPage **ppPage, /* Return the page in this parameter */
- int noContent, /* Do not load page content if true */
- int bReadonly /* True if a read-only (mmap) page is ok */
+ int flags /* PAGER_GET_NOCONTENT or PAGER_GET_READONLY */
){
int rc;
DbPage *pDbPage;
- int flags = (noContent ? PAGER_ACQUIRE_NOCONTENT : 0)
- | (bReadonly ? PAGER_ACQUIRE_READONLY : 0);
- assert( noContent==0 || bReadonly==0 );
+ assert( flags==0 || flags==PAGER_GET_NOCONTENT || flags==PAGER_GET_READONLY );
assert( sqlite3_mutex_held(pBt->mutex) );
rc = sqlite3PagerAcquire(pBt->pPager, pgno, (DbPage**)&pDbPage, flags);
if( rc ) return rc;
@@ -51183,15 +51218,16 @@ static int getAndInitPage(
BtShared *pBt, /* The database file */
Pgno pgno, /* Number of the page to get */
MemPage **ppPage, /* Write the page pointer here */
- int bReadonly /* True if a read-only (mmap) page is ok */
+ int bReadonly /* PAGER_GET_READONLY or 0 */
){
int rc;
assert( sqlite3_mutex_held(pBt->mutex) );
+ assert( bReadonly==PAGER_GET_READONLY || bReadonly==0 );
if( pgno>btreePagecount(pBt) ){
rc = SQLITE_CORRUPT_BKPT;
}else{
- rc = btreeGetPage(pBt, pgno, ppPage, 0, bReadonly);
+ rc = btreeGetPage(pBt, pgno, ppPage, bReadonly);
if( rc==SQLITE_OK ){
rc = btreeInitPage(*ppPage);
if( rc!=SQLITE_OK ){
@@ -51711,17 +51747,14 @@ SQLITE_PRIVATE int sqlite3BtreeSetMmapLimit(Btree *p, sqlite3_int64 szMmap){
** probability of damage to near zero but with a write performance reduction.
*/
#ifndef SQLITE_OMIT_PAGER_PRAGMAS
-SQLITE_PRIVATE int sqlite3BtreeSetSafetyLevel(
+SQLITE_PRIVATE int sqlite3BtreeSetPagerFlags(
Btree *p, /* The btree to set the safety level on */
- int level, /* PRAGMA synchronous. 1=OFF, 2=NORMAL, 3=FULL */
- int fullSync, /* PRAGMA fullfsync. */
- int ckptFullSync /* PRAGMA checkpoint_fullfync */
+ unsigned pgFlags /* Various PAGER_* flags */
){
BtShared *pBt = p->pBt;
assert( sqlite3_mutex_held(p->db->mutex) );
- assert( level>=1 && level<=3 );
sqlite3BtreeEnter(p);
- sqlite3PagerSetSafetyLevel(pBt->pPager, level, fullSync, ckptFullSync);
+ sqlite3PagerSetFlags(pBt->pPager, pgFlags);
sqlite3BtreeLeave(p);
return SQLITE_OK;
}
@@ -51927,7 +51960,7 @@ static int lockBtree(BtShared *pBt){
assert( pBt->pPage1==0 );
rc = sqlite3PagerSharedLock(pBt->pPager);
if( rc!=SQLITE_OK ) return rc;
- rc = btreeGetPage(pBt, 1, &pPage1, 0, 0);
+ rc = btreeGetPage(pBt, 1, &pPage1, 0);
if( rc!=SQLITE_OK ) return rc;
/* Do some checking to help insure the file we opened really is
@@ -52509,7 +52542,7 @@ static int relocatePage(
** iPtrPage.
*/
if( eType!=PTRMAP_ROOTPAGE ){
- rc = btreeGetPage(pBt, iPtrPage, &pPtrPage, 0, 0);
+ rc = btreeGetPage(pBt, iPtrPage, &pPtrPage, 0);
if( rc!=SQLITE_OK ){
return rc;
}
@@ -52593,7 +52626,7 @@ static int incrVacuumStep(BtShared *pBt, Pgno nFin, Pgno iLastPg, int bCommit){
u8 eMode = BTALLOC_ANY; /* Mode parameter for allocateBtreePage() */
Pgno iNear = 0; /* nearby parameter for allocateBtreePage() */
- rc = btreeGetPage(pBt, iLastPg, &pLastPg, 0, 0);
+ rc = btreeGetPage(pBt, iLastPg, &pLastPg, 0);
if( rc!=SQLITE_OK ){
return rc;
}
@@ -52704,7 +52737,7 @@ SQLITE_PRIVATE int sqlite3BtreeIncrVacuum(Btree *p){
/*
** This routine is called prior to sqlite3PagerCommit when a transaction
-** is commited for an auto-vacuum database.
+** is committed for an auto-vacuum database.
**
** If SQLITE_OK is returned, then *pnTrunc is set to the number of pages
** the database file should be truncated to during the commit process.
@@ -52819,12 +52852,13 @@ SQLITE_PRIVATE int sqlite3BtreeCommitPhaseOne(Btree *p, const char *zMaster){
*/
static void btreeEndTransaction(Btree *p){
BtShared *pBt = p->pBt;
+ sqlite3 *db = p->db;
assert( sqlite3BtreeHoldsMutex(p) );
#ifndef SQLITE_OMIT_AUTOVACUUM
pBt->bDoTruncate = 0;
#endif
- if( p->inTrans>TRANS_NONE && p->db->activeVdbeCnt>1 ){
+ if( p->inTrans>TRANS_NONE && db->nVdbeRead>1 ){
/* If there are other active statements that belong to this database
** handle, downgrade to a read-only transaction. The other statements
** may still be reading from the database. */
@@ -52991,7 +53025,7 @@ SQLITE_PRIVATE int sqlite3BtreeRollback(Btree *p, int tripCode){
/* The rollback may have destroyed the pPage1->aData value. So
** call btreeGetPage() on page 1 again to make
** sure pPage1->aData is set correctly. */
- if( btreeGetPage(pBt, 1, &pPage1, 0, 0)==SQLITE_OK ){
+ if( btreeGetPage(pBt, 1, &pPage1, 0)==SQLITE_OK ){
int nPage = get4byte(28+(u8*)pPage1->aData);
testcase( nPage==0 );
if( nPage==0 ) sqlite3PagerPagecount(pBt->pPager, &nPage);
@@ -53426,7 +53460,7 @@ static int getOverflowPage(
assert( next==0 || rc==SQLITE_DONE );
if( rc==SQLITE_OK ){
- rc = btreeGetPage(pBt, ovfl, &pPage, 0, (ppPage==0));
+ rc = btreeGetPage(pBt, ovfl, &pPage, (ppPage==0) ? PAGER_GET_READONLY : 0);
assert( rc==SQLITE_OK || pPage==0 );
if( rc==SQLITE_OK ){
next = get4byte(pPage->aData);
@@ -53648,7 +53682,7 @@ static int accessPayload(
{
DbPage *pDbPage;
rc = sqlite3PagerAcquire(pBt->pPager, nextPage, &pDbPage,
- (eOp==0 ? PAGER_ACQUIRE_READONLY : 0)
+ (eOp==0 ? PAGER_GET_READONLY : 0)
);
if( rc==SQLITE_OK ){
aPayload = sqlite3PagerGetData(pDbPage);
@@ -53832,7 +53866,8 @@ static int moveToChild(BtCursor *pCur, u32 newPgno){
if( pCur->iPage>=(BTCURSOR_MAX_DEPTH-1) ){
return SQLITE_CORRUPT_BKPT;
}
- rc = getAndInitPage(pBt, newPgno, &pNewPage, (pCur->wrFlag==0));
+ rc = getAndInitPage(pBt, newPgno, &pNewPage,
+ pCur->wrFlag==0 ? PAGER_GET_READONLY : 0);
if( rc ) return rc;
pCur->apPage[i+1] = pNewPage;
pCur->aiIdx[i+1] = 0;
@@ -53949,7 +53984,8 @@ static int moveToRoot(BtCursor *pCur){
pCur->eState = CURSOR_INVALID;
return SQLITE_OK;
}else{
- rc = getAndInitPage(pBt, pCur->pgnoRoot, &pCur->apPage[0], pCur->wrFlag==0);
+ rc = getAndInitPage(pBt, pCur->pgnoRoot, &pCur->apPage[0],
+ pCur->wrFlag==0 ? PAGER_GET_READONLY : 0);
if( rc!=SQLITE_OK ){
pCur->eState = CURSOR_INVALID;
return rc;
@@ -54344,21 +54380,29 @@ SQLITE_PRIVATE int sqlite3BtreeNext(BtCursor *pCur, int *pRes){
MemPage *pPage;
assert( cursorHoldsMutex(pCur) );
- rc = restoreCursorPosition(pCur);
- if( rc!=SQLITE_OK ){
- return rc;
- }
assert( pRes!=0 );
- if( CURSOR_INVALID==pCur->eState ){
- *pRes = 1;
- return SQLITE_OK;
- }
- if( pCur->skipNext>0 ){
- pCur->skipNext = 0;
- *pRes = 0;
- return SQLITE_OK;
+ assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID );
+ if( pCur->eState!=CURSOR_VALID ){
+ rc = restoreCursorPosition(pCur);
+ if( rc!=SQLITE_OK ){
+ *pRes = 0;
+ return rc;
+ }
+ if( CURSOR_INVALID==pCur->eState ){
+ *pRes = 1;
+ return SQLITE_OK;
+ }
+ if( pCur->skipNext ){
+ assert( pCur->eState==CURSOR_VALID || pCur->eState==CURSOR_SKIPNEXT );
+ pCur->eState = CURSOR_VALID;
+ if( pCur->skipNext>0 ){
+ pCur->skipNext = 0;
+ *pRes = 0;
+ return SQLITE_OK;
+ }
+ pCur->skipNext = 0;
+ }
}
- pCur->skipNext = 0;
pPage = pCur->apPage[pCur->iPage];
idx = ++pCur->aiIdx[pCur->iPage];
@@ -54376,7 +54420,10 @@ SQLITE_PRIVATE int sqlite3BtreeNext(BtCursor *pCur, int *pRes){
if( idx>=pPage->nCell ){
if( !pPage->leaf ){
rc = moveToChild(pCur, get4byte(&pPage->aData[pPage->hdrOffset+8]));
- if( rc ) return rc;
+ if( rc ){
+ *pRes = 0;
+ return rc;
+ }
rc = moveToLeftmost(pCur);
*pRes = 0;
return rc;
@@ -54418,21 +54465,32 @@ SQLITE_PRIVATE int sqlite3BtreePrevious(BtCursor *pCur, int *pRes){
MemPage *pPage;
assert( cursorHoldsMutex(pCur) );
- rc = restoreCursorPosition(pCur);
- if( rc!=SQLITE_OK ){
- return rc;
- }
+ assert( pRes!=0 );
+ assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID );
pCur->atLast = 0;
- if( CURSOR_INVALID==pCur->eState ){
- *pRes = 1;
- return SQLITE_OK;
- }
- if( pCur->skipNext<0 ){
- pCur->skipNext = 0;
- *pRes = 0;
- return SQLITE_OK;
+ if( pCur->eState!=CURSOR_VALID ){
+ if( ALWAYS(pCur->eState>=CURSOR_REQUIRESEEK) ){
+ rc = btreeRestoreCursorPosition(pCur);
+ if( rc!=SQLITE_OK ){
+ *pRes = 0;
+ return rc;
+ }
+ }
+ if( CURSOR_INVALID==pCur->eState ){
+ *pRes = 1;
+ return SQLITE_OK;
+ }
+ if( pCur->skipNext ){
+ assert( pCur->eState==CURSOR_VALID || pCur->eState==CURSOR_SKIPNEXT );
+ pCur->eState = CURSOR_VALID;
+ if( pCur->skipNext<0 ){
+ pCur->skipNext = 0;
+ *pRes = 0;
+ return SQLITE_OK;
+ }
+ pCur->skipNext = 0;
+ }
}
- pCur->skipNext = 0;
pPage = pCur->apPage[pCur->iPage];
assert( pPage->isInit );
@@ -54440,6 +54498,7 @@ SQLITE_PRIVATE int sqlite3BtreePrevious(BtCursor *pCur, int *pRes){
int idx = pCur->aiIdx[pCur->iPage];
rc = moveToChild(pCur, get4byte(findCell(pPage, idx)));
if( rc ){
+ *pRes = 0;
return rc;
}
rc = moveToRightmost(pCur);
@@ -54563,7 +54622,7 @@ static int allocateBtreePage(
if( iTrunk>mxPage ){
rc = SQLITE_CORRUPT_BKPT;
}else{
- rc = btreeGetPage(pBt, iTrunk, &pTrunk, 0, 0);
+ rc = btreeGetPage(pBt, iTrunk, &pTrunk, 0);
}
if( rc ){
pTrunk = 0;
@@ -54627,7 +54686,7 @@ static int allocateBtreePage(
goto end_allocate_page;
}
testcase( iNewTrunk==mxPage );
- rc = btreeGetPage(pBt, iNewTrunk, &pNewTrunk, 0, 0);
+ rc = btreeGetPage(pBt, iNewTrunk, &pNewTrunk, 0);
if( rc!=SQLITE_OK ){
goto end_allocate_page;
}
@@ -54706,8 +54765,8 @@ static int allocateBtreePage(
memcpy(&aData[8+closest*4], &aData[4+k*4], 4);
}
put4byte(&aData[4], k-1);
- noContent = !btreeGetHasContent(pBt, *pPgno);
- rc = btreeGetPage(pBt, *pPgno, ppPage, noContent, 0);
+ noContent = !btreeGetHasContent(pBt, *pPgno) ? PAGER_GET_NOCONTENT : 0;
+ rc = btreeGetPage(pBt, *pPgno, ppPage, noContent);
if( rc==SQLITE_OK ){
rc = sqlite3PagerWrite((*ppPage)->pDbPage);
if( rc!=SQLITE_OK ){
@@ -54739,7 +54798,7 @@ static int allocateBtreePage(
** here are confined to those pages that lie between the end of the
** database image and the end of the database file.
*/
- int bNoContent = (0==IfNotOmitAV(pBt->bDoTruncate));
+ int bNoContent = (0==IfNotOmitAV(pBt->bDoTruncate)) ? PAGER_GET_NOCONTENT : 0;
rc = sqlite3PagerWrite(pBt->pPage1->pDbPage);
if( rc ) return rc;
@@ -54755,7 +54814,7 @@ static int allocateBtreePage(
MemPage *pPg = 0;
TRACE(("ALLOCATE: %d from end of file (pointer-map page)\n", pBt->nPage));
assert( pBt->nPage!=PENDING_BYTE_PAGE(pBt) );
- rc = btreeGetPage(pBt, pBt->nPage, &pPg, bNoContent, 0);
+ rc = btreeGetPage(pBt, pBt->nPage, &pPg, bNoContent);
if( rc==SQLITE_OK ){
rc = sqlite3PagerWrite(pPg->pDbPage);
releasePage(pPg);
@@ -54769,7 +54828,7 @@ static int allocateBtreePage(
*pPgno = pBt->nPage;
assert( *pPgno!=PENDING_BYTE_PAGE(pBt) );
- rc = btreeGetPage(pBt, *pPgno, ppPage, bNoContent, 0);
+ rc = btreeGetPage(pBt, *pPgno, ppPage, bNoContent);
if( rc ) return rc;
rc = sqlite3PagerWrite((*ppPage)->pDbPage);
if( rc!=SQLITE_OK ){
@@ -54837,7 +54896,7 @@ static int freePage2(BtShared *pBt, MemPage *pMemPage, Pgno iPage){
/* If the secure_delete option is enabled, then
** always fully overwrite deleted information with zeros.
*/
- if( (!pPage && ((rc = btreeGetPage(pBt, iPage, &pPage, 0, 0))!=0) )
+ if( (!pPage && ((rc = btreeGetPage(pBt, iPage, &pPage, 0))!=0) )
|| ((rc = sqlite3PagerWrite(pPage->pDbPage))!=0)
){
goto freepage_out;
@@ -54864,7 +54923,7 @@ static int freePage2(BtShared *pBt, MemPage *pMemPage, Pgno iPage){
u32 nLeaf; /* Initial number of leaf cells on trunk page */
iTrunk = get4byte(&pPage1->aData[32]);
- rc = btreeGetPage(pBt, iTrunk, &pTrunk, 0, 0);
+ rc = btreeGetPage(pBt, iTrunk, &pTrunk, 0);
if( rc!=SQLITE_OK ){
goto freepage_out;
}
@@ -54910,7 +54969,7 @@ static int freePage2(BtShared *pBt, MemPage *pMemPage, Pgno iPage){
** first trunk in the free-list is full. Either way, the page being freed
** will become the new first trunk page in the free-list.
*/
- if( pPage==0 && SQLITE_OK!=(rc = btreeGetPage(pBt, iPage, &pPage, 0, 0)) ){
+ if( pPage==0 && SQLITE_OK!=(rc = btreeGetPage(pBt, iPage, &pPage, 0)) ){
goto freepage_out;
}
rc = sqlite3PagerWrite(pPage->pDbPage);
@@ -56809,7 +56868,7 @@ static int btreeCreateTable(Btree *p, int *piTable, int createTabFlags){
}
/* Move the page currently at pgnoRoot to pgnoMove. */
- rc = btreeGetPage(pBt, pgnoRoot, &pRoot, 0, 0);
+ rc = btreeGetPage(pBt, pgnoRoot, &pRoot, 0);
if( rc!=SQLITE_OK ){
return rc;
}
@@ -56830,7 +56889,7 @@ static int btreeCreateTable(Btree *p, int *piTable, int createTabFlags){
if( rc!=SQLITE_OK ){
return rc;
}
- rc = btreeGetPage(pBt, pgnoRoot, &pRoot, 0, 0);
+ rc = btreeGetPage(pBt, pgnoRoot, &pRoot, 0);
if( rc!=SQLITE_OK ){
return rc;
}
@@ -57008,7 +57067,7 @@ static int btreeDropTable(Btree *p, Pgno iTable, int *piMoved){
return SQLITE_LOCKED_SHAREDCACHE;
}
- rc = btreeGetPage(pBt, (Pgno)iTable, &pPage, 0, 0);
+ rc = btreeGetPage(pBt, (Pgno)iTable, &pPage, 0);
if( rc ) return rc;
rc = sqlite3BtreeClearTable(p, iTable, 0);
if( rc ){
@@ -57043,7 +57102,7 @@ static int btreeDropTable(Btree *p, Pgno iTable, int *piMoved){
*/
MemPage *pMove;
releasePage(pPage);
- rc = btreeGetPage(pBt, maxRootPgno, &pMove, 0, 0);
+ rc = btreeGetPage(pBt, maxRootPgno, &pMove, 0);
if( rc!=SQLITE_OK ){
return rc;
}
@@ -57053,7 +57112,7 @@ static int btreeDropTable(Btree *p, Pgno iTable, int *piMoved){
return rc;
}
pMove = 0;
- rc = btreeGetPage(pBt, maxRootPgno, &pMove, 0, 0);
+ rc = btreeGetPage(pBt, maxRootPgno, &pMove, 0);
freePage(pMove, &rc);
releasePage(pMove);
if( rc!=SQLITE_OK ){
@@ -57268,7 +57327,7 @@ static void checkAppendMsg(
}
sqlite3VXPrintf(&pCheck->errMsg, 1, zFormat, ap);
va_end(ap);
- if( pCheck->errMsg.mallocFailed ){
+ if( pCheck->errMsg.accError==STRACCUM_NOMEM ){
pCheck->mallocFailed = 1;
}
}
@@ -57465,7 +57524,7 @@ static int checkTreePage(
usableSize = pBt->usableSize;
if( iPage==0 ) return 0;
if( checkRef(pCheck, iPage, zParentContext) ) return 0;
- if( (rc = btreeGetPage(pBt, (Pgno)iPage, &pPage, 0, 0))!=0 ){
+ if( (rc = btreeGetPage(pBt, (Pgno)iPage, &pPage, 0))!=0 ){
checkAppendMsg(pCheck, zContext,
"unable to get the page. error code=%d", rc);
return 0;
@@ -58047,12 +58106,6 @@ SQLITE_PRIVATE void sqlite3BtreeCursorHints(BtCursor *pCsr, unsigned int mask){
** API functions and the related features.
*/
-/* Macro to find the minimum of two numeric values.
-*/
-#ifndef MIN
-# define MIN(x,y) ((x)<(y)?(x):(y))
-#endif
-
/*
** Structure allocated for each backup operation.
*/
@@ -58430,7 +58483,7 @@ SQLITE_API int sqlite3_backup_step(sqlite3_backup *p, int nPage){
if( iSrcPg!=PENDING_BYTE_PAGE(p->pSrc->pBt) ){
DbPage *pSrcPg; /* Source page object */
rc = sqlite3PagerAcquire(pSrcPager, iSrcPg, &pSrcPg,
- PAGER_ACQUIRE_READONLY);
+ PAGER_GET_READONLY);
if( rc==SQLITE_OK ){
rc = backupOnePage(p, iSrcPg, sqlite3PagerGetData(pSrcPg), 0);
sqlite3PagerUnref(pSrcPg);
@@ -59585,34 +59638,29 @@ SQLITE_PRIVATE int sqlite3MemCompare(const Mem *pMem1, const Mem *pMem2, const C
** if both values are integers.
*/
if( combined_flags&(MEM_Int|MEM_Real) ){
- if( !(f1&(MEM_Int|MEM_Real)) ){
- return 1;
- }
- if( !(f2&(MEM_Int|MEM_Real)) ){
- return -1;
- }
- if( (f1 & f2 & MEM_Int)==0 ){
- double r1, r2;
- if( (f1&MEM_Real)==0 ){
- r1 = (double)pMem1->u.i;
- }else{
- r1 = pMem1->r;
- }
- if( (f2&MEM_Real)==0 ){
- r2 = (double)pMem2->u.i;
- }else{
- r2 = pMem2->r;
- }
- if( r1<r2 ) return -1;
- if( r1>r2 ) return 1;
- return 0;
- }else{
- assert( f1&MEM_Int );
- assert( f2&MEM_Int );
+ double r1, r2;
+ if( (f1 & f2 & MEM_Int)!=0 ){
if( pMem1->u.i < pMem2->u.i ) return -1;
if( pMem1->u.i > pMem2->u.i ) return 1;
return 0;
}
+ if( (f1&MEM_Real)!=0 ){
+ r1 = pMem1->r;
+ }else if( (f1&MEM_Int)!=0 ){
+ r1 = (double)pMem1->u.i;
+ }else{
+ return 1;
+ }
+ if( (f2&MEM_Real)!=0 ){
+ r2 = pMem2->r;
+ }else if( (f2&MEM_Int)!=0 ){
+ r2 = (double)pMem2->u.i;
+ }else{
+ return -1;
+ }
+ if( r1<r2 ) return -1;
+ if( r1>r2 ) return 1;
+ return 0;
}
/* If one value is a string and the other is a blob, the string is less.
@@ -60198,8 +60246,8 @@ SQLITE_PRIVATE int sqlite3VdbeMakeLabel(Vdbe *p){
SQLITE_PRIVATE void sqlite3VdbeResolveLabel(Vdbe *p, int x){
int j = -1-x;
assert( p->magic==VDBE_MAGIC_INIT );
- assert( j>=0 && j<p->nLabel );
- if( p->aLabel ){
+ assert( j<p->nLabel );
+ if( j>=0 && p->aLabel ){
p->aLabel[j] = p->nOp;
}
}
@@ -60351,32 +60399,64 @@ static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){
Op *pOp;
int *aLabel = p->aLabel;
p->readOnly = 1;
+ p->bIsReader = 0;
for(pOp=p->aOp, i=p->nOp-1; i>=0; i--, pOp++){
u8 opcode = pOp->opcode;
- pOp->opflags = sqlite3OpcodeProperty[opcode];
- if( opcode==OP_Function || opcode==OP_AggStep ){
- if( pOp->p5>nMaxArgs ) nMaxArgs = pOp->p5;
- }else if( (opcode==OP_Transaction && pOp->p2!=0) || opcode==OP_Vacuum ){
- p->readOnly = 0;
+ /* NOTE: Be sure to update mkopcodeh.awk when adding or removing
+ ** cases from this switch! */
+ switch( opcode ){
+ case OP_Function:
+ case OP_AggStep: {
+ if( pOp->p5>nMaxArgs ) nMaxArgs = pOp->p5;
+ break;
+ }
+ case OP_Transaction: {
+ if( pOp->p2!=0 ) p->readOnly = 0;
+ /* fall thru */
+ }
+ case OP_AutoCommit:
+ case OP_Savepoint: {
+ p->bIsReader = 1;
+ break;
+ }
+#ifndef SQLITE_OMIT_WAL
+ case OP_Checkpoint:
+#endif
+ case OP_Vacuum:
+ case OP_JournalMode: {
+ p->readOnly = 0;
+ p->bIsReader = 1;
+ break;
+ }
#ifndef SQLITE_OMIT_VIRTUALTABLE
- }else if( opcode==OP_VUpdate ){
- if( pOp->p2>nMaxArgs ) nMaxArgs = pOp->p2;
- }else if( opcode==OP_VFilter ){
- int n;
- assert( p->nOp - i >= 3 );
- assert( pOp[-1].opcode==OP_Integer );
- n = pOp[-1].p1;
- if( n>nMaxArgs ) nMaxArgs = n;
+ case OP_VUpdate: {
+ if( pOp->p2>nMaxArgs ) nMaxArgs = pOp->p2;
+ break;
+ }
+ case OP_VFilter: {
+ int n;
+ assert( p->nOp - i >= 3 );
+ assert( pOp[-1].opcode==OP_Integer );
+ n = pOp[-1].p1;
+ if( n>nMaxArgs ) nMaxArgs = n;
+ break;
+ }
#endif
- }else if( opcode==OP_Next || opcode==OP_SorterNext ){
- pOp->p4.xAdvance = sqlite3BtreeNext;
- pOp->p4type = P4_ADVANCE;
- }else if( opcode==OP_Prev ){
- pOp->p4.xAdvance = sqlite3BtreePrevious;
- pOp->p4type = P4_ADVANCE;
+ case OP_Next:
+ case OP_SorterNext: {
+ pOp->p4.xAdvance = sqlite3BtreeNext;
+ pOp->p4type = P4_ADVANCE;
+ break;
+ }
+ case OP_Prev: {
+ pOp->p4.xAdvance = sqlite3BtreePrevious;
+ pOp->p4type = P4_ADVANCE;
+ break;
+ }
}
+ pOp->opflags = sqlite3OpcodeProperty[opcode];
if( (pOp->opflags & OPFLG_JUMP)!=0 && pOp->p2<0 ){
assert( -1-pOp->p2<p->nLabel );
pOp->p2 = aLabel[-1-pOp->p2];
@@ -60384,8 +60464,8 @@ static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){
}
sqlite3DbFree(p->db, p->aLabel);
p->aLabel = 0;
-
*pMaxFuncArgs = nMaxArgs;
+ assert( p->bIsReader!=0 || p->btreeMask==0 );
}
/*
@@ -60511,8 +60591,7 @@ SQLITE_PRIVATE void sqlite3VdbeChangeP5(Vdbe *p, u8 val){
** the address of the next instruction to be coded.
*/
SQLITE_PRIVATE void sqlite3VdbeJumpHere(Vdbe *p, int addr){
- assert( addr>=0 || p->db->mallocFailed );
- if( addr>=0 ) sqlite3VdbeChangeP2(p, addr, p->nOp);
+ if( ALWAYS(addr>=0) ) sqlite3VdbeChangeP2(p, addr, p->nOp);
}
@@ -60548,13 +60627,6 @@ static void freeP4(sqlite3 *db, int p4type, void *p4){
if( db->pnBytesFreed==0 ) sqlite3_free(p4);
break;
}
- case P4_VDBEFUNC: {
- VdbeFunc *pVdbeFunc = (VdbeFunc *)p4;
- freeEphemeralFunction(db, pVdbeFunc->pFunc);
- if( db->pnBytesFreed==0 ) sqlite3VdbeDeleteAuxData(pVdbeFunc, 0);
- sqlite3DbFree(db, pVdbeFunc);
- break;
- }
case P4_FUNCDEF: {
freeEphemeralFunction(db, (FuncDef*)p4);
break;
@@ -60673,20 +60745,13 @@ SQLITE_PRIVATE void sqlite3VdbeChangeP4(Vdbe *p, int addr, const char *zP4, int
pOp->p4.p = 0;
pOp->p4type = P4_NOTUSED;
}else if( n==P4_KEYINFO ){
- KeyInfo *pKeyInfo;
- int nField, nByte;
-
- nField = ((KeyInfo*)zP4)->nField;
- nByte = sizeof(*pKeyInfo) + (nField-1)*sizeof(pKeyInfo->aColl[0]) + nField;
- pKeyInfo = sqlite3DbMallocRaw(0, nByte);
- pOp->p4.pKeyInfo = pKeyInfo;
- if( pKeyInfo ){
- u8 *aSortOrder;
- memcpy((char*)pKeyInfo, zP4, nByte - nField);
- aSortOrder = pKeyInfo->aSortOrder;
- assert( aSortOrder!=0 );
- pKeyInfo->aSortOrder = (unsigned char*)&pKeyInfo->aColl[nField];
- memcpy(pKeyInfo->aSortOrder, aSortOrder, nField);
+ KeyInfo *pOrig, *pNew;
+
+ pOrig = (KeyInfo*)zP4;
+ pOp->p4.pKeyInfo = pNew = sqlite3KeyInfoAlloc(db, pOrig->nField);
+ if( pNew ){
+ memcpy(pNew->aColl, pOrig->aColl, pOrig->nField*sizeof(pNew->aColl[0]));
+ memcpy(pNew->aSortOrder, pOrig->aSortOrder, pOrig->nField);
pOp->p4type = P4_KEYINFO;
}else{
p->db->mallocFailed = 1;
@@ -61584,6 +61649,10 @@ static void closeAllCursors(Vdbe *p){
p->pDelFrame = pDel->pParent;
sqlite3VdbeFrameDelete(pDel);
}
+
+ /* Delete any auxdata allocations made by the VM */
+ sqlite3VdbeDeleteAuxData(p, -1, 0);
+ assert( p->pAuxData==0 );
}
/*
@@ -61692,7 +61761,7 @@ static int vdbeCommit(sqlite3 *db, Vdbe *p){
** required, as an xSync() callback may add an attached database
** to the transaction.
*/
- rc = sqlite3VtabSync(db, &p->zErrMsg);
+ rc = sqlite3VtabSync(db, p);
/* This loop determines (a) if the commit hook should be invoked and
** (b) how many database files have open write transactions, not
@@ -61911,7 +61980,7 @@ static int vdbeCommit(sqlite3 *db, Vdbe *p){
}
/*
-** This routine checks that the sqlite3.activeVdbeCnt count variable
+** This routine checks that the sqlite3.nVdbeActive count variable
** matches the number of vdbe's in the list sqlite3.pVdbe that are
** currently active. An assertion fails if the two counts do not match.
** This is an internal self-check only - it is not an essential processing
@@ -61924,16 +61993,19 @@ static void checkActiveVdbeCnt(sqlite3 *db){
Vdbe *p;
int cnt = 0;
int nWrite = 0;
+ int nRead = 0;
p = db->pVdbe;
while( p ){
if( p->magic==VDBE_MAGIC_RUN && p->pc>=0 ){
cnt++;
if( p->readOnly==0 ) nWrite++;
+ if( p->bIsReader ) nRead++;
}
p = p->pNext;
}
- assert( cnt==db->activeVdbeCnt );
- assert( nWrite==db->writeVdbeCnt );
+ assert( cnt==db->nVdbeActive );
+ assert( nWrite==db->nVdbeWrite );
+ assert( nRead==db->nVdbeRead );
}
#else
#define checkActiveVdbeCnt(x)
@@ -61944,7 +62016,7 @@ static void checkActiveVdbeCnt(sqlite3 *db){
** close it now. Argument eOp must be either SAVEPOINT_ROLLBACK or
** SAVEPOINT_RELEASE. If it is SAVEPOINT_ROLLBACK, then the statement
** transaction is rolled back. If eOp is SAVEPOINT_RELEASE, then the
-** statement transaction is commtted.
+** statement transaction is committed.
**
** If an IO error occurs, an SQLITE_IOERR_XXX error code is returned.
** Otherwise SQLITE_OK.
@@ -61998,6 +62070,7 @@ SQLITE_PRIVATE int sqlite3VdbeCloseStatement(Vdbe *p, int eOp){
** the statement transaction was opened. */
if( eOp==SAVEPOINT_ROLLBACK ){
db->nDeferredCons = p->nStmtDefCons;
+ db->nDeferredImmCons = p->nStmtDefImmCons;
}
}
return rc;
@@ -62016,7 +62089,9 @@ SQLITE_PRIVATE int sqlite3VdbeCloseStatement(Vdbe *p, int eOp){
#ifndef SQLITE_OMIT_FOREIGN_KEY
SQLITE_PRIVATE int sqlite3VdbeCheckFk(Vdbe *p, int deferred){
sqlite3 *db = p->db;
- if( (deferred && db->nDeferredCons>0) || (!deferred && p->nFkConstraint>0) ){
+ if( (deferred && (db->nDeferredCons+db->nDeferredImmCons)>0)
+ || (!deferred && p->nFkConstraint>0)
+ ){
p->rc = SQLITE_CONSTRAINT_FOREIGNKEY;
p->errorAction = OE_Abort;
sqlite3SetString(&p->zErrMsg, db, "foreign key constraint failed");
@@ -62069,8 +62144,9 @@ SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe *p){
}
checkActiveVdbeCnt(db);
- /* No commit or rollback needed if the program never started */
- if( p->pc>=0 ){
+ /* No commit or rollback needed if the program never started or if the
+ ** SQL statement does not read or write a database file. */
+ if( p->pc>=0 && p->bIsReader ){
int mrc; /* Primary error code from p->rc */
int eStatementOp = 0;
int isSpecialError; /* Set to true if a 'special' error */
@@ -62123,7 +62199,7 @@ SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe *p){
*/
if( !sqlite3VtabInSync(db)
&& db->autoCommit
- && db->writeVdbeCnt==(p->readOnly==0)
+ && db->nVdbeWrite==(p->readOnly==0)
){
if( p->rc==SQLITE_OK || (p->errorAction==OE_Fail && !isSpecialError) ){
rc = sqlite3VdbeCheckFk(p, 1);
@@ -62148,6 +62224,8 @@ SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe *p){
sqlite3RollbackAll(db, SQLITE_OK);
}else{
db->nDeferredCons = 0;
+ db->nDeferredImmCons = 0;
+ db->flags &= ~SQLITE_DeferFKs;
sqlite3CommitInternalChanges(db);
}
}else{
@@ -62204,11 +62282,12 @@ SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe *p){
/* We have successfully halted and closed the VM. Record this fact. */
if( p->pc>=0 ){
- db->activeVdbeCnt--;
- if( !p->readOnly ){
- db->writeVdbeCnt--;
- }
- assert( db->activeVdbeCnt>=db->writeVdbeCnt );
+ db->nVdbeActive--;
+ if( !p->readOnly ) db->nVdbeWrite--;
+ if( p->bIsReader ) db->nVdbeRead--;
+ assert( db->nVdbeActive>=db->nVdbeRead );
+ assert( db->nVdbeRead>=db->nVdbeWrite );
+ assert( db->nVdbeWrite>=0 );
}
p->magic = VDBE_MAGIC_HALT;
checkActiveVdbeCnt(db);
@@ -62224,7 +62303,7 @@ SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe *p){
sqlite3ConnectionUnlocked(db);
}
- assert( db->activeVdbeCnt>0 || db->autoCommit==0 || db->nStatement==0 );
+ assert( db->nVdbeActive>0 || db->autoCommit==0 || db->nStatement==0 );
return (p->rc==SQLITE_BUSY ? SQLITE_BUSY : SQLITE_OK);
}
@@ -62372,20 +62451,35 @@ SQLITE_PRIVATE int sqlite3VdbeFinalize(Vdbe *p){
}
/*
-** Call the destructor for each auxdata entry in pVdbeFunc for which
-** the corresponding bit in mask is clear. Auxdata entries beyond 31
-** are always destroyed. To destroy all auxdata entries, call this
-** routine with mask==0.
+** If parameter iOp is less than zero, then invoke the destructor for
+** all auxiliary data pointers currently cached by the VM passed as
+** the first argument.
+**
+** Or, if iOp is greater than or equal to zero, then the destructor is
+** only invoked for those auxiliary data pointers created by the user
+** function invoked by the OP_Function opcode at instruction iOp of
+** VM pVdbe, and only then if:
+**
+** * the associated function parameter is the 32nd or later (counting
+** from left to right), or
+**
+** * the corresponding bit in argument mask is clear (where the first
+** function parameter corrsponds to bit 0 etc.).
*/
-SQLITE_PRIVATE void sqlite3VdbeDeleteAuxData(VdbeFunc *pVdbeFunc, int mask){
- int i;
- for(i=0; i<pVdbeFunc->nAux; i++){
- struct AuxData *pAux = &pVdbeFunc->apAux[i];
- if( (i>31 || !(mask&(((u32)1)<<i))) && pAux->pAux ){
+SQLITE_PRIVATE void sqlite3VdbeDeleteAuxData(Vdbe *pVdbe, int iOp, int mask){
+ AuxData **pp = &pVdbe->pAuxData;
+ while( *pp ){
+ AuxData *pAux = *pp;
+ if( (iOp<0)
+ || (pAux->iOp==iOp && (pAux->iArg>31 || !(mask & ((u32)1<<pAux->iArg))))
+ ){
if( pAux->xDelete ){
pAux->xDelete(pAux->pAux);
}
- pAux->pAux = 0;
+ *pp = pAux->pNext;
+ sqlite3DbFree(pVdbe->db, pAux);
+ }else{
+ pp= &pAux->pNext;
}
}
}
@@ -62904,11 +62998,10 @@ SQLITE_PRIVATE int sqlite3VdbeRecordCompare(
int nKey1, const void *pKey1, /* Left key */
UnpackedRecord *pPKey2 /* Right key */
){
- int d1; /* Offset into aKey[] of next data element */
+ u32 d1; /* Offset into aKey[] of next data element */
u32 idx1; /* Offset into aKey[] of next header element */
u32 szHdr1; /* Number of bytes in header */
int i = 0;
- int nField;
int rc = 0;
const unsigned char *aKey1 = (const unsigned char *)pKey1;
KeyInfo *pKeyInfo;
@@ -62931,14 +63024,25 @@ SQLITE_PRIVATE int sqlite3VdbeRecordCompare(
idx1 = getVarint32(aKey1, szHdr1);
d1 = szHdr1;
- nField = pKeyInfo->nField;
+ assert( pKeyInfo->nField+1>=pPKey2->nField );
assert( pKeyInfo->aSortOrder!=0 );
while( idx1<szHdr1 && i<pPKey2->nField ){
u32 serial_type1;
/* Read the serial types for the next element in each key. */
idx1 += getVarint32( aKey1+idx1, serial_type1 );
- if( d1>=nKey1 && sqlite3VdbeSerialTypeLen(serial_type1)>0 ) break;
+
+ /* Verify that there is enough key space remaining to avoid
+ ** a buffer overread. The "d1+serial_type1+2" subexpression will
+ ** always be greater than or equal to the amount of required key space.
+ ** Use that approximation to avoid the more expensive call to
+ ** sqlite3VdbeSerialTypeLen() in the common case.
+ */
+ if( d1+serial_type1+2>(u32)nKey1
+ && d1+sqlite3VdbeSerialTypeLen(serial_type1)>(u32)nKey1
+ ){
+ break;
+ }
/* Extract the values to be compared.
*/
@@ -62946,13 +63050,12 @@ SQLITE_PRIVATE int sqlite3VdbeRecordCompare(
/* Do the comparison
*/
- rc = sqlite3MemCompare(&mem1, &pPKey2->aMem[i],
- i<nField ? pKeyInfo->aColl[i] : 0);
+ rc = sqlite3MemCompare(&mem1, &pPKey2->aMem[i], pKeyInfo->aColl[i]);
if( rc!=0 ){
assert( mem1.zMalloc==0 ); /* See comment below */
/* Invert the result if we are using DESC sort order. */
- if( i<nField && pKeyInfo->aSortOrder[i] ){
+ if( pKeyInfo->aSortOrder[i] ){
rc = -rc;
}
@@ -63167,7 +63270,7 @@ SQLITE_PRIVATE sqlite3 *sqlite3VdbeDb(Vdbe *v){
**
** The returned value must be freed by the caller using sqlite3ValueFree().
*/
-SQLITE_PRIVATE sqlite3_value *sqlite3VdbeGetValue(Vdbe *v, int iVar, u8 aff){
+SQLITE_PRIVATE sqlite3_value *sqlite3VdbeGetBoundValue(Vdbe *v, int iVar, u8 aff){
assert( iVar>0 );
if( v ){
Mem *pMem = &v->aVar[iVar-1];
@@ -63198,6 +63301,21 @@ SQLITE_PRIVATE void sqlite3VdbeSetVarmask(Vdbe *v, int iVar){
}
}
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+/*
+** Transfer error message text from an sqlite3_vtab.zErrMsg (text stored
+** in memory obtained from sqlite3_malloc) into a Vdbe.zErrMsg (text stored
+** in memory obtained from sqlite3DbMalloc).
+*/
+SQLITE_PRIVATE void sqlite3VtabImportErrmsg(Vdbe *p, sqlite3_vtab *pVtab){
+ sqlite3 *db = p->db;
+ sqlite3DbFree(db, p->zErrMsg);
+ p->zErrMsg = sqlite3DbStrDup(db, pVtab->zErrMsg);
+ sqlite3_free(pVtab->zErrMsg);
+ pVtab->zErrMsg = 0;
+}
+#endif /* SQLITE_OMIT_VIRTUALTABLE */
+
/************** End of vdbeaux.c *********************************************/
/************** Begin file vdbeapi.c *****************************************/
/*
@@ -63411,12 +63529,14 @@ SQLITE_API void sqlite3_result_double(sqlite3_context *pCtx, double rVal){
SQLITE_API void sqlite3_result_error(sqlite3_context *pCtx, const char *z, int n){
assert( sqlite3_mutex_held(pCtx->s.db->mutex) );
pCtx->isError = SQLITE_ERROR;
+ pCtx->fErrorOrAux = 1;
sqlite3VdbeMemSetStr(&pCtx->s, z, n, SQLITE_UTF8, SQLITE_TRANSIENT);
}
#ifndef SQLITE_OMIT_UTF16
SQLITE_API void sqlite3_result_error16(sqlite3_context *pCtx, const void *z, int n){
assert( sqlite3_mutex_held(pCtx->s.db->mutex) );
pCtx->isError = SQLITE_ERROR;
+ pCtx->fErrorOrAux = 1;
sqlite3VdbeMemSetStr(&pCtx->s, z, n, SQLITE_UTF16NATIVE, SQLITE_TRANSIENT);
}
#endif
@@ -63480,6 +63600,7 @@ SQLITE_API void sqlite3_result_zeroblob(sqlite3_context *pCtx, int n){
}
SQLITE_API void sqlite3_result_error_code(sqlite3_context *pCtx, int errCode){
pCtx->isError = errCode;
+ pCtx->fErrorOrAux = 1;
if( pCtx->s.flags & MEM_Null ){
sqlite3VdbeMemSetStr(&pCtx->s, sqlite3ErrStr(errCode), -1,
SQLITE_UTF8, SQLITE_STATIC);
@@ -63490,6 +63611,7 @@ SQLITE_API void sqlite3_result_error_code(sqlite3_context *pCtx, int errCode){
SQLITE_API void sqlite3_result_error_toobig(sqlite3_context *pCtx){
assert( sqlite3_mutex_held(pCtx->s.db->mutex) );
pCtx->isError = SQLITE_TOOBIG;
+ pCtx->fErrorOrAux = 1;
sqlite3VdbeMemSetStr(&pCtx->s, "string or blob too big", -1,
SQLITE_UTF8, SQLITE_STATIC);
}
@@ -63499,6 +63621,7 @@ SQLITE_API void sqlite3_result_error_nomem(sqlite3_context *pCtx){
assert( sqlite3_mutex_held(pCtx->s.db->mutex) );
sqlite3VdbeMemSetNull(&pCtx->s);
pCtx->isError = SQLITE_NOMEM;
+ pCtx->fErrorOrAux = 1;
pCtx->s.db->mallocFailed = 1;
}
@@ -63582,11 +63705,13 @@ static int sqlite3Step(Vdbe *p){
** reset the interrupt flag. This prevents a call to sqlite3_interrupt
** from interrupting a statement that has not yet started.
*/
- if( db->activeVdbeCnt==0 ){
+ if( db->nVdbeActive==0 ){
db->u1.isInterrupted = 0;
}
- assert( db->writeVdbeCnt>0 || db->autoCommit==0 || db->nDeferredCons==0 );
+ assert( db->nVdbeWrite>0 || db->autoCommit==0
+ || (db->nDeferredCons==0 && db->nDeferredImmCons==0)
+ );
#ifndef SQLITE_OMIT_TRACE
if( db->xProfile && !db->init.busy ){
@@ -63594,8 +63719,9 @@ static int sqlite3Step(Vdbe *p){
}
#endif
- db->activeVdbeCnt++;
- if( p->readOnly==0 ) db->writeVdbeCnt++;
+ db->nVdbeActive++;
+ if( p->readOnly==0 ) db->nVdbeWrite++;
+ if( p->bIsReader ) db->nVdbeRead++;
p->pc = 0;
}
#ifndef SQLITE_OMIT_EXPLAIN
@@ -63604,9 +63730,9 @@ static int sqlite3Step(Vdbe *p){
}else
#endif /* SQLITE_OMIT_EXPLAIN */
{
- db->vdbeExecCnt++;
+ db->nVdbeExec++;
rc = sqlite3VdbeExec(p);
- db->vdbeExecCnt--;
+ db->nVdbeExec--;
}
#ifndef SQLITE_OMIT_TRACE
@@ -63781,14 +63907,14 @@ SQLITE_API void *sqlite3_aggregate_context(sqlite3_context *p, int nByte){
** the user-function defined by pCtx.
*/
SQLITE_API void *sqlite3_get_auxdata(sqlite3_context *pCtx, int iArg){
- VdbeFunc *pVdbeFunc;
+ AuxData *pAuxData;
assert( sqlite3_mutex_held(pCtx->s.db->mutex) );
- pVdbeFunc = pCtx->pVdbeFunc;
- if( !pVdbeFunc || iArg>=pVdbeFunc->nAux || iArg<0 ){
- return 0;
+ for(pAuxData=pCtx->pVdbe->pAuxData; pAuxData; pAuxData=pAuxData->pNext){
+ if( pAuxData->iOp==pCtx->iOp && pAuxData->iArg==iArg ) break;
}
- return pVdbeFunc->apAux[iArg].pAux;
+
+ return (pAuxData ? pAuxData->pAux : 0);
}
/*
@@ -63802,29 +63928,30 @@ SQLITE_API void sqlite3_set_auxdata(
void *pAux,
void (*xDelete)(void*)
){
- struct AuxData *pAuxData;
- VdbeFunc *pVdbeFunc;
- if( iArg<0 ) goto failed;
+ AuxData *pAuxData;
+ Vdbe *pVdbe = pCtx->pVdbe;
assert( sqlite3_mutex_held(pCtx->s.db->mutex) );
- pVdbeFunc = pCtx->pVdbeFunc;
- if( !pVdbeFunc || pVdbeFunc->nAux<=iArg ){
- int nAux = (pVdbeFunc ? pVdbeFunc->nAux : 0);
- int nMalloc = sizeof(VdbeFunc) + sizeof(struct AuxData)*iArg;
- pVdbeFunc = sqlite3DbRealloc(pCtx->s.db, pVdbeFunc, nMalloc);
- if( !pVdbeFunc ){
- goto failed;
- }
- pCtx->pVdbeFunc = pVdbeFunc;
- memset(&pVdbeFunc->apAux[nAux], 0, sizeof(struct AuxData)*(iArg+1-nAux));
- pVdbeFunc->nAux = iArg+1;
- pVdbeFunc->pFunc = pCtx->pFunc;
- }
+ if( iArg<0 ) goto failed;
- pAuxData = &pVdbeFunc->apAux[iArg];
- if( pAuxData->pAux && pAuxData->xDelete ){
+ for(pAuxData=pVdbe->pAuxData; pAuxData; pAuxData=pAuxData->pNext){
+ if( pAuxData->iOp==pCtx->iOp && pAuxData->iArg==iArg ) break;
+ }
+ if( pAuxData==0 ){
+ pAuxData = sqlite3DbMallocZero(pVdbe->db, sizeof(AuxData));
+ if( !pAuxData ) goto failed;
+ pAuxData->iOp = pCtx->iOp;
+ pAuxData->iArg = iArg;
+ pAuxData->pNext = pVdbe->pAuxData;
+ pVdbe->pAuxData = pAuxData;
+ if( pCtx->fErrorOrAux==0 ){
+ pCtx->isError = 0;
+ pCtx->fErrorOrAux = 1;
+ }
+ }else if( pAuxData->xDelete ){
pAuxData->xDelete(pAuxData->pAux);
}
+
pAuxData->pAux = pAux;
pAuxData->xDelete = xDelete;
return;
@@ -64013,13 +64140,6 @@ SQLITE_API int sqlite3_column_type(sqlite3_stmt *pStmt, int i){
return iType;
}
-/* The following function is experimental and subject to change or
-** removal */
-/*int sqlite3_column_numeric_type(sqlite3_stmt *pStmt, int i){
-** return sqlite3_value_numeric_type( columnMem(pStmt,i) );
-**}
-*/
-
/*
** Convert the N-th element of pStmt->pColName[] into a string using
** xFunc() then return that string. If N is out of range, return 0.
@@ -64496,9 +64616,9 @@ SQLITE_API sqlite3_stmt *sqlite3_next_stmt(sqlite3 *pDb, sqlite3_stmt *pStmt){
*/
SQLITE_API int sqlite3_stmt_status(sqlite3_stmt *pStmt, int op, int resetFlag){
Vdbe *pVdbe = (Vdbe*)pStmt;
- int v = pVdbe->aCounter[op-1];
- if( resetFlag ) pVdbe->aCounter[op-1] = 0;
- return v;
+ u32 v = pVdbe->aCounter[op];
+ if( resetFlag ) pVdbe->aCounter[op] = 0;
+ return (int)v;
}
/************** End of vdbeapi.c *********************************************/
@@ -64550,9 +64670,9 @@ static int findNextHostParameter(const char *zSql, int *pnToken){
/*
** This function returns a pointer to a nul-terminated string in memory
-** obtained from sqlite3DbMalloc(). If sqlite3.vdbeExecCnt is 1, then the
+** obtained from sqlite3DbMalloc(). If sqlite3.nVdbeExec is 1, then the
** string contains a copy of zRawSql but with host parameters expanded to
-** their current bindings. Or, if sqlite3.vdbeExecCnt is greater than 1,
+** their current bindings. Or, if sqlite3.nVdbeExec is greater than 1,
** then the returned string holds a copy of zRawSql with "-- " prepended
** to each line of text.
**
@@ -64590,7 +64710,7 @@ SQLITE_PRIVATE char *sqlite3VdbeExpandSql(
sqlite3StrAccumInit(&out, zBase, sizeof(zBase),
db->aLimit[SQLITE_LIMIT_LENGTH]);
out.db = db;
- if( db->vdbeExecCnt>1 ){
+ if( db->nVdbeExec>1 ){
while( *zRawSql ){
const char *zStart = zRawSql;
while( *(zRawSql++)!='\n' && *zRawSql );
@@ -65385,19 +65505,6 @@ static int checkSavepointCount(sqlite3 *db){
}
#endif
-/*
-** Transfer error message text from an sqlite3_vtab.zErrMsg (text stored
-** in memory obtained from sqlite3_malloc) into a Vdbe.zErrMsg (text stored
-** in memory obtained from sqlite3DbMalloc).
-*/
-static void importVtabErrMsg(Vdbe *p, sqlite3_vtab *pVtab){
- sqlite3 *db = p->db;
- sqlite3DbFree(db, p->zErrMsg);
- p->zErrMsg = sqlite3DbStrDup(db, pVtab->zErrMsg);
- sqlite3_free(pVtab->zErrMsg);
- pVtab->zErrMsg = 0;
-}
-
/*
** Execute as much of a VDBE program as we can then return.
@@ -65440,16 +65547,16 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
sqlite3 *db = p->db; /* The database */
u8 resetSchemaOnFault = 0; /* Reset schema after an error if positive */
u8 encoding = ENC(db); /* The database encoding */
+ int iCompare = 0; /* Result of last OP_Compare operation */
+ unsigned nVmStep = 0; /* Number of virtual machine steps */
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
- int checkProgress; /* True if progress callbacks are enabled */
- int nProgressOps = 0; /* Opcodes executed since progress callback. */
+ unsigned nProgressLimit = 0;/* Invoke xProgress() when nVmStep reaches this */
#endif
Mem *aMem = p->aMem; /* Copy of p->aMem */
Mem *pIn1 = 0; /* 1st input operand */
Mem *pIn2 = 0; /* 2nd input operand */
Mem *pIn3 = 0; /* 3rd input operand */
Mem *pOut = 0; /* Output operand */
- int iCompare = 0; /* Result of last OP_Compare operation */
int *aPermute = 0; /* Permutation of columns for OP_Compare */
i64 lastRowid = db->lastRowid; /* Saved value of the last insert ROWID */
#ifdef VDBE_PROFILE
@@ -65895,6 +66002,7 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
goto no_mem;
}
assert( p->rc==SQLITE_OK || p->rc==SQLITE_BUSY );
+ assert( p->bIsReader || p->readOnly!=0 );
p->rc = SQLITE_OK;
assert( p->explain==0 );
p->pResultSet = 0;
@@ -65902,7 +66010,15 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
CHECK_FOR_INTERRUPT;
sqlite3VdbeIOTraceSql(p);
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
- checkProgress = db->xProgress!=0;
+ if( db->xProgress ){
+ assert( 0 < db->nProgressOps );
+ nProgressLimit = (unsigned)p->aCounter[SQLITE_STMTSTATUS_VM_STEP];
+ if( nProgressLimit==0 ){
+ nProgressLimit = db->nProgressOps;
+ }else{
+ nProgressLimit %= (unsigned)db->nProgressOps;
+ }
+ }
#endif
#ifdef SQLITE_DEBUG
sqlite3BeginBenignMalloc();
@@ -65923,6 +66039,7 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
origPc = pc;
start = sqlite3Hwtime();
#endif
+ nVmStep++;
pOp = &aOp[pc];
/* Only allow tracing if SQLITE_DEBUG is defined.
@@ -65950,27 +66067,6 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
}
#endif
-#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
- /* Call the progress callback if it is configured and the required number
- ** of VDBE ops have been executed (either since this invocation of
- ** sqlite3VdbeExec() or since last time the progress callback was called).
- ** If the progress callback returns non-zero, exit the virtual machine with
- ** a return code SQLITE_ABORT.
- */
- if( checkProgress ){
- if( db->nProgressOps==nProgressOps ){
- int prc;
- prc = db->xProgress(db->pProgressArg);
- if( prc!=0 ){
- rc = SQLITE_INTERRUPT;
- goto vdbe_error_halt;
- }
- nProgressOps = 0;
- }
- nProgressOps++;
- }
-#endif
-
/* On any opcode with the "out2-prerelease" tag, free any
** external allocations out of mem[p2] and set mem[p2] to be
** an undefined integer. Opcodes will either fill in the integer
@@ -66063,8 +66159,40 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
** the program.
*/
case OP_Goto: { /* jump */
- CHECK_FOR_INTERRUPT;
pc = pOp->p2 - 1;
+
+ /* Opcodes that are used as the bottom of a loop (OP_Next, OP_Prev,
+ ** OP_VNext, OP_RowSetNext, or OP_SorterNext) all jump here upon
+ ** completion. Check to see if sqlite3_interrupt() has been called
+ ** or if the progress callback needs to be invoked.
+ **
+ ** This code uses unstructured "goto" statements and does not look clean.
+ ** But that is not due to sloppy coding habits. The code is written this
+ ** way for performance, to avoid having to run the interrupt and progress
+ ** checks on every opcode. This helps sqlite3_step() to run about 1.5%
+ ** faster according to "valgrind --tool=cachegrind" */
+check_for_interrupt:
+ CHECK_FOR_INTERRUPT;
+#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
+ /* Call the progress callback if it is configured and the required number
+ ** of VDBE ops have been executed (either since this invocation of
+ ** sqlite3VdbeExec() or since last time the progress callback was called).
+ ** If the progress callback returns non-zero, exit the virtual machine with
+ ** a return code SQLITE_ABORT.
+ */
+ if( db->xProgress!=0 && nVmStep>=nProgressLimit ){
+ int prc;
+ prc = db->xProgress(db->pProgressArg);
+ if( prc!=0 ){
+ rc = SQLITE_INTERRUPT;
+ goto vdbe_error_halt;
+ }
+ if( db->xProgress!=0 ){
+ nProgressLimit = nVmStep + db->nProgressOps - (nVmStep%db->nProgressOps);
+ }
+ }
+#endif
+
break;
}
@@ -66185,7 +66313,7 @@ case OP_Halt: {
p->rc = rc = SQLITE_BUSY;
}else{
assert( rc==SQLITE_OK || (p->rc&0xff)==SQLITE_CONSTRAINT );
- assert( rc==SQLITE_OK || db->nDeferredCons>0 );
+ assert( rc==SQLITE_OK || db->nDeferredCons>0 || db->nDeferredImmCons>0 );
rc = p->rc ? SQLITE_ERROR : SQLITE_DONE;
}
goto vdbe_return;
@@ -66747,19 +66875,14 @@ case OP_Function: {
REGISTER_TRACE(pOp->p2+u.ai.i, u.ai.pArg);
}
- assert( pOp->p4type==P4_FUNCDEF || pOp->p4type==P4_VDBEFUNC );
- if( pOp->p4type==P4_FUNCDEF ){
- u.ai.ctx.pFunc = pOp->p4.pFunc;
- u.ai.ctx.pVdbeFunc = 0;
- }else{
- u.ai.ctx.pVdbeFunc = (VdbeFunc*)pOp->p4.pVdbeFunc;
- u.ai.ctx.pFunc = u.ai.ctx.pVdbeFunc->pFunc;
- }
-
+ assert( pOp->p4type==P4_FUNCDEF );
+ u.ai.ctx.pFunc = pOp->p4.pFunc;
u.ai.ctx.s.flags = MEM_Null;
u.ai.ctx.s.db = db;
u.ai.ctx.s.xDel = 0;
u.ai.ctx.s.zMalloc = 0;
+ u.ai.ctx.iOp = pc;
+ u.ai.ctx.pVdbe = p;
/* The output cell may already have a buffer allocated. Move
** the pointer to u.ai.ctx.s so in case the user-function can use
@@ -66768,7 +66891,7 @@ case OP_Function: {
sqlite3VdbeMemMove(&u.ai.ctx.s, pOut);
MemSetTypeFlag(&u.ai.ctx.s, MEM_Null);
- u.ai.ctx.isError = 0;
+ u.ai.ctx.fErrorOrAux = 0;
if( u.ai.ctx.pFunc->flags & SQLITE_FUNC_NEEDCOLL ){
assert( pOp>aOp );
assert( pOp[-1].p4type==P4_COLLSEQ );
@@ -66779,15 +66902,6 @@ case OP_Function: {
(*u.ai.ctx.pFunc->xFunc)(&u.ai.ctx, u.ai.n, u.ai.apVal); /* IMP: R-24505-23230 */
lastRowid = db->lastRowid;
- /* If any auxiliary data functions have been called by this user function,
- ** immediately call the destructor for any non-static values.
- */
- if( u.ai.ctx.pVdbeFunc ){
- sqlite3VdbeDeleteAuxData(u.ai.ctx.pVdbeFunc, pOp->p1);
- pOp->p4.pVdbeFunc = u.ai.ctx.pVdbeFunc;
- pOp->p4type = P4_VDBEFUNC;
- }
-
if( db->mallocFailed ){
/* Even though a malloc() has failed, the implementation of the
** user function may have called an sqlite3_result_XXX() function
@@ -66799,9 +66913,12 @@ case OP_Function: {
}
/* If the function returned an error, throw an exception */
- if( u.ai.ctx.isError ){
- sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(&u.ai.ctx.s));
- rc = u.ai.ctx.isError;
+ if( u.ai.ctx.fErrorOrAux ){
+ if( u.ai.ctx.isError ){
+ sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(&u.ai.ctx.s));
+ rc = u.ai.ctx.isError;
+ }
+ sqlite3VdbeDeleteAuxData(p, pc, pOp->p1);
}
/* Copy the result of the function into register P3 */
@@ -67177,12 +67294,12 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
** then the result is always NULL.
** The jump is taken if the SQLITE_JUMPIFNULL bit is set.
*/
- if( pOp->p5 & SQLITE_STOREP2 ){
+ if( pOp->p5 & SQLITE_JUMPIFNULL ){
+ pc = pOp->p2-1;
+ }else if( pOp->p5 & SQLITE_STOREP2 ){
pOut = &aMem[pOp->p2];
MemSetTypeFlag(pOut, MEM_Null);
REGISTER_TRACE(pOp->p2, pOut);
- }else if( pOp->p5 & SQLITE_JUMPIFNULL ){
- pc = pOp->p2-1;
}
break;
}
@@ -68038,9 +68155,10 @@ case OP_Savepoint: {
assert( u.as.p1==SAVEPOINT_BEGIN||u.as.p1==SAVEPOINT_RELEASE||u.as.p1==SAVEPOINT_ROLLBACK );
assert( db->pSavepoint || db->isTransactionSavepoint==0 );
assert( checkSavepointCount(db) );
+ assert( p->bIsReader );
if( u.as.p1==SAVEPOINT_BEGIN ){
- if( db->writeVdbeCnt>0 ){
+ if( db->nVdbeWrite>0 ){
/* A new savepoint cannot be created if there are active write
** statements (i.e. open read/write incremental blob handles).
*/
@@ -68080,6 +68198,7 @@ case OP_Savepoint: {
u.as.pNew->pNext = db->pSavepoint;
db->pSavepoint = u.as.pNew;
u.as.pNew->nDeferredCons = db->nDeferredCons;
+ u.as.pNew->nDeferredImmCons = db->nDeferredImmCons;
}
}
}else{
@@ -68097,7 +68216,7 @@ case OP_Savepoint: {
if( !u.as.pSavepoint ){
sqlite3SetString(&p->zErrMsg, db, "no such savepoint: %s", u.as.zName);
rc = SQLITE_ERROR;
- }else if( db->writeVdbeCnt>0 && u.as.p1==SAVEPOINT_RELEASE ){
+ }else if( db->nVdbeWrite>0 && u.as.p1==SAVEPOINT_RELEASE ){
/* It is not possible to release (commit) a savepoint if there are
** active write statements.
*/
@@ -68167,6 +68286,7 @@ case OP_Savepoint: {
}
}else{
db->nDeferredCons = u.as.pSavepoint->nDeferredCons;
+ db->nDeferredImmCons = u.as.pSavepoint->nDeferredImmCons;
}
if( !isTransaction ){
@@ -68200,10 +68320,11 @@ case OP_AutoCommit: {
u.at.turnOnAC = u.at.desiredAutoCommit && !db->autoCommit;
assert( u.at.desiredAutoCommit==1 || u.at.desiredAutoCommit==0 );
assert( u.at.desiredAutoCommit==1 || u.at.iRollback==0 );
- assert( db->activeVdbeCnt>0 ); /* At least this one VM is active */
+ assert( db->nVdbeActive>0 ); /* At least this one VM is active */
+ assert( p->bIsReader );
#if 0
- if( u.at.turnOnAC && u.at.iRollback && db->activeVdbeCnt>1 ){
+ if( u.at.turnOnAC && u.at.iRollback && db->nVdbeActive>1 ){
/* If this instruction implements a ROLLBACK and other VMs are
** still running, and a transaction is active, return an error indicating
** that the other VMs must complete first.
@@ -68213,7 +68334,7 @@ case OP_AutoCommit: {
rc = SQLITE_BUSY;
}else
#endif
- if( u.at.turnOnAC && !u.at.iRollback && db->writeVdbeCnt>0 ){
+ if( u.at.turnOnAC && !u.at.iRollback && db->nVdbeWrite>0 ){
/* If this instruction implements a COMMIT and other VMs are writing
** return an error indicating that the other VMs must complete first.
*/
@@ -68271,8 +68392,8 @@ case OP_AutoCommit: {
** other process can start another write transaction while this transaction is
** underway. Starting a write transaction also creates a rollback journal. A
** write transaction must be started before any changes can be made to the
-** database. If P2 is 2 or greater then an EXCLUSIVE lock is also obtained
-** on the file.
+** database. If P2 is greater than or equal to 2 then an EXCLUSIVE lock is
+** also obtained on the file.
**
** If a write-transaction is started and the Vdbe.usesStmtJournal flag is
** true (this flag is set if the Vdbe may modify more than one row and may
@@ -68291,8 +68412,14 @@ case OP_Transaction: {
Btree *pBt;
#endif /* local variables moved into u.au */
+ assert( p->bIsReader );
+ assert( p->readOnly==0 || pOp->p2==0 );
assert( pOp->p1>=0 && pOp->p1<db->nDb );
assert( (p->btreeMask & (((yDbMask)1)<<pOp->p1))!=0 );
+ if( pOp->p2 && (db->flags & SQLITE_QueryOnly)!=0 ){
+ rc = SQLITE_READONLY;
+ goto abort_due_to_error;
+ }
u.au.pBt = db->aDb[pOp->p1].pBt;
if( u.au.pBt ){
@@ -68307,7 +68434,7 @@ case OP_Transaction: {
}
if( pOp->p2 && p->usesStmtJournal
- && (db->autoCommit==0 || db->activeVdbeCnt>1)
+ && (db->autoCommit==0 || db->nVdbeRead>1)
){
assert( sqlite3BtreeIsInTrans(u.au.pBt) );
if( p->iStatement==0 ){
@@ -68325,6 +68452,7 @@ case OP_Transaction: {
** counter. If the statement transaction needs to be rolled back,
** the value of this counter needs to be restored too. */
p->nStmtDefCons = db->nDeferredCons;
+ p->nStmtDefImmCons = db->nDeferredImmCons;
}
}
break;
@@ -68349,6 +68477,7 @@ case OP_ReadCookie: { /* out2-prerelease */
int iCookie;
#endif /* local variables moved into u.av */
+ assert( p->bIsReader );
u.av.iDb = pOp->p1;
u.av.iCookie = pOp->p3;
assert( pOp->p3<SQLITE_N_BTREE_META );
@@ -68378,6 +68507,7 @@ case OP_SetCookie: { /* in3 */
assert( pOp->p2<SQLITE_N_BTREE_META );
assert( pOp->p1>=0 && pOp->p1<db->nDb );
assert( (p->btreeMask & (((yDbMask)1)<<pOp->p1))!=0 );
+ assert( p->readOnly==0 );
u.aw.pDb = &db->aDb[pOp->p1];
assert( u.aw.pDb->pBt!=0 );
assert( sqlite3SchemaMutexHeld(db, pOp->p1, 0) );
@@ -68430,6 +68560,7 @@ case OP_VerifyCookie: {
assert( pOp->p1>=0 && pOp->p1<db->nDb );
assert( (p->btreeMask & (((yDbMask)1)<<pOp->p1))!=0 );
assert( sqlite3SchemaMutexHeld(db, pOp->p1, 0) );
+ assert( p->bIsReader );
u.ax.pBt = db->aDb[pOp->p1].pBt;
if( u.ax.pBt ){
sqlite3BtreeGetMeta(u.ax.pBt, BTREE_SCHEMA_VERSION, (u32 *)&u.ax.iMeta);
@@ -68527,6 +68658,8 @@ case OP_OpenWrite: {
assert( (pOp->p5&(OPFLAG_P2ISREG|OPFLAG_BULKCSR))==pOp->p5 );
assert( pOp->opcode==OP_OpenWrite || pOp->p5==0 );
+ assert( p->bIsReader );
+ assert( pOp->opcode==OP_OpenRead || p->readOnly==0 );
if( p->expired ){
rc = SQLITE_ABORT;
@@ -69721,7 +69854,7 @@ case OP_Rowid: { /* out2-prerelease */
u.bn.pModule = u.bn.pVtab->pModule;
assert( u.bn.pModule->xRowid );
rc = u.bn.pModule->xRowid(u.bn.pC->pVtabCursor, &u.bn.v);
- importVtabErrMsg(p, u.bn.pVtab);
+ sqlite3VtabImportErrmsg(p, u.bn.pVtab);
#endif /* SQLITE_OMIT_VIRTUALTABLE */
}else{
assert( u.bn.pC->pCursor!=0 );
@@ -69813,7 +69946,7 @@ case OP_Sort: { /* jump */
sqlite3_sort_count++;
sqlite3_search_count--;
#endif
- p->aCounter[SQLITE_STMTSTATUS_SORT-1]++;
+ p->aCounter[SQLITE_STMTSTATUS_SORT]++;
/* Fall through into OP_Rewind */
}
/* Opcode: Rewind P1 P2 * * *
@@ -69895,9 +70028,8 @@ case OP_Next: { /* jump */
int res;
#endif /* local variables moved into u.br */
- CHECK_FOR_INTERRUPT;
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
- assert( pOp->p5<=ArraySize(p->aCounter) );
+ assert( pOp->p5<ArraySize(p->aCounter) );
u.br.pC = p->apCsr[pOp->p1];
if( u.br.pC==0 ){
break; /* See ticket #2273 */
@@ -69907,7 +70039,7 @@ case OP_Next: { /* jump */
assert( pOp->opcode==OP_SorterNext );
rc = sqlite3VdbeSorterNext(db, u.br.pC, &u.br.res);
}else{
- u.br.res = 1;
+ /* u.br.res = 1; // Always initialized by the xAdvance() call */
assert( u.br.pC->deferredMoveto==0 );
assert( u.br.pC->pCursor );
assert( pOp->opcode!=OP_Next || pOp->p4.xAdvance==sqlite3BtreeNext );
@@ -69918,13 +70050,13 @@ case OP_Next: { /* jump */
u.br.pC->cacheStatus = CACHE_STALE;
if( u.br.res==0 ){
pc = pOp->p2 - 1;
- if( pOp->p5 ) p->aCounter[pOp->p5-1]++;
+ p->aCounter[pOp->p5]++;
#ifdef SQLITE_TEST
sqlite3_search_count++;
#endif
}
u.br.pC->rowidIsValid = 0;
- break;
+ goto check_for_interrupt;
}
/* Opcode: IdxInsert P1 P2 P3 * P5
@@ -70145,15 +70277,18 @@ case OP_Destroy: { /* out2-prerelease */
int iDb;
#endif /* local variables moved into u.bw */
+ assert( p->readOnly==0 );
#ifndef SQLITE_OMIT_VIRTUALTABLE
u.bw.iCnt = 0;
for(u.bw.pVdbe=db->pVdbe; u.bw.pVdbe; u.bw.pVdbe = u.bw.pVdbe->pNext){
- if( u.bw.pVdbe->magic==VDBE_MAGIC_RUN && u.bw.pVdbe->inVtabMethod<2 && u.bw.pVdbe->pc>=0 ){
+ if( u.bw.pVdbe->magic==VDBE_MAGIC_RUN && u.bw.pVdbe->bIsReader
+ && u.bw.pVdbe->inVtabMethod<2 && u.bw.pVdbe->pc>=0
+ ){
u.bw.iCnt++;
}
}
#else
- u.bw.iCnt = db->activeVdbeCnt;
+ u.bw.iCnt = db->nVdbeRead;
#endif
pOut->flags = MEM_Null;
if( u.bw.iCnt>1 ){
@@ -70202,6 +70337,7 @@ case OP_Clear: {
#endif /* local variables moved into u.bx */
u.bx.nChange = 0;
+ assert( p->readOnly==0 );
assert( (p->btreeMask & (((yDbMask)1)<<pOp->p2))!=0 );
rc = sqlite3BtreeClearTable(
db->aDb[pOp->p2].pBt, pOp->p1, (pOp->p3 ? &u.bx.nChange : 0)
@@ -70250,6 +70386,7 @@ case OP_CreateTable: { /* out2-prerelease */
u.by.pgno = 0;
assert( pOp->p1>=0 && pOp->p1<db->nDb );
assert( (p->btreeMask & (((yDbMask)1)<<pOp->p1))!=0 );
+ assert( p->readOnly==0 );
u.by.pDb = &db->aDb[pOp->p1];
assert( u.by.pDb->pBt!=0 );
if( pOp->opcode==OP_CreateTable ){
@@ -70402,6 +70539,7 @@ case OP_IntegrityCk: {
Mem *pnErr; /* Register keeping track of errors remaining */
#endif /* local variables moved into u.ca */
+ assert( p->bIsReader );
u.ca.nRoot = pOp->p2;
assert( u.ca.nRoot>0 );
u.ca.aRoot = sqlite3DbMallocRaw(db, sizeof(int)*(u.ca.nRoot+1) );
@@ -70464,7 +70602,7 @@ case OP_RowSetRead: { /* jump, in1, out3 */
#if 0 /* local variables moved into u.cb */
i64 val;
#endif /* local variables moved into u.cb */
- CHECK_FOR_INTERRUPT;
+
pIn1 = &aMem[pOp->p1];
if( (pIn1->flags & MEM_RowSet)==0
|| sqlite3RowSetNext(pIn1->u.pRowSet, &u.cb.val)==0
@@ -70476,7 +70614,7 @@ case OP_RowSetRead: { /* jump, in1, out3 */
/* A value was pulled from the index */
sqlite3VdbeMemSetInt64(&aMem[pOp->p3], u.cb.val);
}
- break;
+ goto check_for_interrupt;
}
/* Opcode: RowSetTest P1 P2 P3 P4
@@ -70696,7 +70834,9 @@ case OP_Param: { /* out2-prerelease */
** statement counter is incremented (immediate foreign key constraints).
*/
case OP_FkCounter: {
- if( pOp->p1 ){
+ if( db->flags & SQLITE_DeferFKs ){
+ db->nDeferredImmCons += pOp->p2;
+ }else if( pOp->p1 ){
db->nDeferredCons += pOp->p2;
}else{
p->nFkConstraint += pOp->p2;
@@ -70717,9 +70857,9 @@ case OP_FkCounter: {
*/
case OP_FkIfZero: { /* jump */
if( pOp->p1 ){
- if( db->nDeferredCons==0 ) pc = pOp->p2-1;
+ if( db->nDeferredCons==0 && db->nDeferredImmCons==0 ) pc = pOp->p2-1;
}else{
- if( p->nFkConstraint==0 ) pc = pOp->p2-1;
+ if( p->nFkConstraint==0 && db->nDeferredImmCons==0 ) pc = pOp->p2-1;
}
break;
}
@@ -70923,6 +71063,7 @@ case OP_Checkpoint: {
Mem *pMem; /* Write results here */
#endif /* local variables moved into u.ci */
+ assert( p->readOnly==0 );
u.ci.aRes[0] = 0;
u.ci.aRes[1] = u.ci.aRes[2] = -1;
assert( pOp->p2==SQLITE_CHECKPOINT_PASSIVE
@@ -70974,6 +71115,7 @@ case OP_JournalMode: { /* out2-prerelease */
|| u.cj.eNew==PAGER_JOURNALMODE_QUERY
);
assert( pOp->p1>=0 && pOp->p1<db->nDb );
+ assert( p->readOnly==0 );
u.cj.pBt = db->aDb[pOp->p1].pBt;
u.cj.pPager = sqlite3BtreePager(u.cj.pBt);
@@ -70997,7 +71139,7 @@ case OP_JournalMode: { /* out2-prerelease */
if( (u.cj.eNew!=u.cj.eOld)
&& (u.cj.eOld==PAGER_JOURNALMODE_WAL || u.cj.eNew==PAGER_JOURNALMODE_WAL)
){
- if( !db->autoCommit || db->activeVdbeCnt>1 ){
+ if( !db->autoCommit || db->nVdbeRead>1 ){
rc = SQLITE_ERROR;
sqlite3SetString(&p->zErrMsg, db,
"cannot change %s wal mode from within a transaction",
@@ -71056,6 +71198,7 @@ case OP_JournalMode: { /* out2-prerelease */
** a transaction.
*/
case OP_Vacuum: {
+ assert( p->readOnly==0 );
rc = sqlite3RunVacuum(&p->zErrMsg, db);
break;
}
@@ -71075,6 +71218,7 @@ case OP_IncrVacuum: { /* jump */
assert( pOp->p1>=0 && pOp->p1<db->nDb );
assert( (p->btreeMask & (((yDbMask)1)<<pOp->p1))!=0 );
+ assert( p->readOnly==0 );
u.ck.pBt = db->aDb[pOp->p1].pBt;
rc = sqlite3BtreeIncrVacuum(u.ck.pBt);
if( rc==SQLITE_DONE ){
@@ -71151,7 +71295,7 @@ case OP_VBegin: {
#endif /* local variables moved into u.cl */
u.cl.pVTab = pOp->p4.pVtab;
rc = sqlite3VtabBegin(db, u.cl.pVTab);
- if( u.cl.pVTab ) importVtabErrMsg(p, u.cl.pVTab->pVtab);
+ if( u.cl.pVTab ) sqlite3VtabImportErrmsg(p, u.cl.pVTab->pVtab);
break;
}
#endif /* SQLITE_OMIT_VIRTUALTABLE */
@@ -71197,13 +71341,14 @@ case OP_VOpen: {
sqlite3_module *pModule;
#endif /* local variables moved into u.cm */
+ assert( p->bIsReader );
u.cm.pCur = 0;
u.cm.pVtabCursor = 0;
u.cm.pVtab = pOp->p4.pVtab->pVtab;
u.cm.pModule = (sqlite3_module *)u.cm.pVtab->pModule;
assert(u.cm.pVtab && u.cm.pModule);
rc = u.cm.pModule->xOpen(u.cm.pVtab, &u.cm.pVtabCursor);
- importVtabErrMsg(p, u.cm.pVtab);
+ sqlite3VtabImportErrmsg(p, u.cm.pVtab);
if( SQLITE_OK==rc ){
/* Initialize sqlite3_vtab_cursor base class */
u.cm.pVtabCursor->pVtab = u.cm.pVtab;
@@ -71283,7 +71428,7 @@ case OP_VFilter: { /* jump */
p->inVtabMethod = 1;
rc = u.cn.pModule->xFilter(u.cn.pVtabCursor, u.cn.iQuery, pOp->p4.z, u.cn.nArg, u.cn.apArg);
p->inVtabMethod = 0;
- importVtabErrMsg(p, u.cn.pVtab);
+ sqlite3VtabImportErrmsg(p, u.cn.pVtab);
if( rc==SQLITE_OK ){
u.cn.res = u.cn.pModule->xEof(u.cn.pVtabCursor);
}
@@ -71336,7 +71481,7 @@ case OP_VColumn: {
MemSetTypeFlag(&u.co.sContext.s, MEM_Null);
rc = u.co.pModule->xColumn(pCur->pVtabCursor, &u.co.sContext, pOp->p2);
- importVtabErrMsg(p, u.co.pVtab);
+ sqlite3VtabImportErrmsg(p, u.co.pVtab);
if( u.co.sContext.isError ){
rc = u.co.sContext.isError;
}
@@ -71391,7 +71536,7 @@ case OP_VNext: { /* jump */
p->inVtabMethod = 1;
rc = u.cp.pModule->xNext(u.cp.pCur->pVtabCursor);
p->inVtabMethod = 0;
- importVtabErrMsg(p, u.cp.pVtab);
+ sqlite3VtabImportErrmsg(p, u.cp.pVtab);
if( rc==SQLITE_OK ){
u.cp.res = u.cp.pModule->xEof(u.cp.pCur->pVtabCursor);
}
@@ -71400,7 +71545,7 @@ case OP_VNext: { /* jump */
/* If there is data, jump to P2 */
pc = pOp->p2 - 1;
}
- break;
+ goto check_for_interrupt;
}
#endif /* SQLITE_OMIT_VIRTUALTABLE */
@@ -71421,6 +71566,7 @@ case OP_VRename: {
u.cq.pName = &aMem[pOp->p1];
assert( u.cq.pVtab->pModule->xRename );
assert( memIsValid(u.cq.pName) );
+ assert( p->readOnly==0 );
REGISTER_TRACE(pOp->p1, u.cq.pName);
assert( u.cq.pName->flags & MEM_Str );
testcase( u.cq.pName->enc==SQLITE_UTF8 );
@@ -71429,7 +71575,7 @@ case OP_VRename: {
rc = sqlite3VdbeChangeEncoding(u.cq.pName, SQLITE_UTF8);
if( rc==SQLITE_OK ){
rc = u.cq.pVtab->pModule->xRename(u.cq.pVtab, u.cq.pName->z);
- importVtabErrMsg(p, u.cq.pVtab);
+ sqlite3VtabImportErrmsg(p, u.cq.pVtab);
p->expired = 0;
}
break;
@@ -71474,6 +71620,7 @@ case OP_VUpdate: {
assert( pOp->p2==1 || pOp->p5==OE_Fail || pOp->p5==OE_Rollback
|| pOp->p5==OE_Abort || pOp->p5==OE_Ignore || pOp->p5==OE_Replace
);
+ assert( p->readOnly==0 );
u.cr.pVtab = pOp->p4.pVtab->pVtab;
u.cr.pModule = (sqlite3_module *)u.cr.pVtab->pModule;
u.cr.nArg = pOp->p2;
@@ -71492,7 +71639,7 @@ case OP_VUpdate: {
db->vtabOnConflict = pOp->p5;
rc = u.cr.pModule->xUpdate(u.cr.pVtab, u.cr.nArg, u.cr.apArg, &u.cr.rowid);
db->vtabOnConflict = vtabOnConflict;
- importVtabErrMsg(p, u.cr.pVtab);
+ sqlite3VtabImportErrmsg(p, u.cr.pVtab);
if( rc==SQLITE_OK && pOp->p1 ){
assert( u.cr.nArg>1 && u.cr.apArg[0] && (u.cr.apArg[0]->flags&MEM_Null) );
db->lastRowid = lastRowid = u.cr.rowid;
@@ -71659,6 +71806,8 @@ vdbe_error_halt:
** top. */
vdbe_return:
db->lastRowid = lastRowid;
+ testcase( nVmStep>0 );
+ p->aCounter[SQLITE_STMTSTATUS_VM_STEP] += (int)nVmStep;
sqlite3VdbeLeave(p);
return rc;
@@ -72226,7 +72375,7 @@ typedef struct FileWriter FileWriter;
** other key value. If the keys are equal (only possible with two EOF
** values), it doesn't matter which index is stored.
**
-** The (N/4) elements of aTree[] that preceed the final (N/2) described
+** The (N/4) elements of aTree[] that precede the final (N/2) described
** above contains the index of the smallest of each block of 4 iterators.
** And so on. So that aTree[1] contains the index of the iterator that
** currently points to the smallest key value. aTree[0] is unused.
@@ -73501,12 +73650,6 @@ typedef struct FileChunk FileChunk;
*/
#define JOURNAL_CHUNKSIZE ((int)(1024-sizeof(FileChunk*)))
-/* Macro to find the minimum of two numeric values.
-*/
-#ifndef MIN
-# define MIN(x,y) ((x)<(y)?(x):(y))
-#endif
-
/*
** The rollback journal is composed of a linked list of these structures.
*/
@@ -73943,7 +74086,7 @@ static void incrAggFunctionDepth(Expr *pExpr, int N){
** column reference is so that the column reference will be recognized as
** usable by indices within the WHERE clause processing logic.
**
-** Hack: The TK_AS operator is inhibited if zType[0]=='G'. This means
+** The TK_AS operator is inhibited if zType[0]=='G'. This means
** that in a GROUP BY clause, the expression is evaluated twice. Hence:
**
** SELECT random()%5 AS x, count(*) FROM tab GROUP BY x
@@ -73953,8 +74096,9 @@ static void incrAggFunctionDepth(Expr *pExpr, int N){
** SELECT random()%5 AS x, count(*) FROM tab GROUP BY random()%5
**
** The result of random()%5 in the GROUP BY clause is probably different
-** from the result in the result-set. We might fix this someday. Or
-** then again, we might not...
+** from the result in the result-set. On the other hand Standard SQL does
+** not allow the GROUP BY clause to contain references to result-set columns.
+** So this should never come up in well-formed queries.
**
** If the reference is followed by a COLLATE operator, then make sure
** the COLLATE operator is preserved. For example:
@@ -74128,11 +74272,20 @@ static int lookupName(
** resulting in an appropriate error message toward the end of this routine
*/
if( zDb ){
- for(i=0; i<db->nDb; i++){
- assert( db->aDb[i].zName );
- if( sqlite3StrICmp(db->aDb[i].zName,zDb)==0 ){
- pSchema = db->aDb[i].pSchema;
- break;
+ testcase( pNC->ncFlags & NC_PartIdx );
+ testcase( pNC->ncFlags & NC_IsCheck );
+ if( (pNC->ncFlags & (NC_PartIdx|NC_IsCheck))!=0 ){
+ /* Silently ignore database qualifiers inside CHECK constraints and partial
+ ** indices. Do not raise errors because that might break legacy and
+ ** because it does not hurt anything to just ignore the database name. */
+ zDb = 0;
+ }else{
+ for(i=0; i<db->nDb; i++){
+ assert( db->aDb[i].zName );
+ if( sqlite3StrICmp(db->aDb[i].zName,zDb)==0 ){
+ pSchema = db->aDb[i].pSchema;
+ break;
+ }
}
}
}
@@ -74275,10 +74428,16 @@ static int lookupName(
** forms the result set entry ("a+b" in the example) and return immediately.
** Note that the expression in the result set should have already been
** resolved by the time the WHERE clause is resolved.
+ **
+ ** The ability to use an output result-set column in the WHERE, GROUP BY,
+ ** or HAVING clauses, or as part of a larger expression in the ORDRE BY
+ ** clause is not standard SQL. This is a (goofy) SQLite extension, that
+ ** is supported for backwards compatibility only. TO DO: Issue a warning
+ ** on sqlite3_log() whenever the capability is used.
*/
if( (pEList = pNC->pEList)!=0
&& zTab==0
- && ((pNC->ncFlags & NC_AsMaybe)==0 || cnt==0)
+ && cnt==0
){
for(j=0; j<pEList->nExpr; j++){
char *zAs = pEList->a[j].zName;
@@ -74411,6 +74570,39 @@ SQLITE_PRIVATE Expr *sqlite3CreateColumnExpr(sqlite3 *db, SrcList *pSrc, int iSr
}
/*
+** Report an error that an expression is not valid for a partial index WHERE
+** clause.
+*/
+static void notValidPartIdxWhere(
+ Parse *pParse, /* Leave error message here */
+ NameContext *pNC, /* The name context */
+ const char *zMsg /* Type of error */
+){
+ if( (pNC->ncFlags & NC_PartIdx)!=0 ){
+ sqlite3ErrorMsg(pParse, "%s prohibited in partial index WHERE clauses",
+ zMsg);
+ }
+}
+
+#ifndef SQLITE_OMIT_CHECK
+/*
+** Report an error that an expression is not valid for a CHECK constraint.
+*/
+static void notValidCheckConstraint(
+ Parse *pParse, /* Leave error message here */
+ NameContext *pNC, /* The name context */
+ const char *zMsg /* Type of error */
+){
+ if( (pNC->ncFlags & NC_IsCheck)!=0 ){
+ sqlite3ErrorMsg(pParse,"%s prohibited in CHECK constraints", zMsg);
+ }
+}
+#else
+# define notValidCheckConstraint(P,N,M)
+#endif
+
+
+/*
** This routine is callback for sqlite3WalkExpr().
**
** Resolve symbolic names into TK_COLUMN operators for the current
@@ -74509,6 +74701,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
testcase( pExpr->op==TK_CONST_FUNC );
assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
+ notValidPartIdxWhere(pParse, pNC, "functions");
zId = pExpr->u.zToken;
nId = sqlite3Strlen30(zId);
pDef = sqlite3FindFunction(pParse->db, zId, nId, n, enc, 0);
@@ -74574,11 +74767,8 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
testcase( pExpr->op==TK_IN );
if( ExprHasProperty(pExpr, EP_xIsSelect) ){
int nRef = pNC->nRef;
-#ifndef SQLITE_OMIT_CHECK
- if( (pNC->ncFlags & NC_IsCheck)!=0 ){
- sqlite3ErrorMsg(pParse,"subqueries prohibited in CHECK constraints");
- }
-#endif
+ notValidCheckConstraint(pParse, pNC, "subqueries");
+ notValidPartIdxWhere(pParse, pNC, "subqueries");
sqlite3WalkSelect(pWalker, pExpr->x.pSelect);
assert( pNC->nRef>=nRef );
if( nRef!=pNC->nRef ){
@@ -74587,14 +74777,11 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
}
break;
}
-#ifndef SQLITE_OMIT_CHECK
case TK_VARIABLE: {
- if( (pNC->ncFlags & NC_IsCheck)!=0 ){
- sqlite3ErrorMsg(pParse,"parameters prohibited in CHECK constraints");
- }
+ notValidCheckConstraint(pParse, pNC, "parameters");
+ notValidPartIdxWhere(pParse, pNC, "parameters");
break;
}
-#endif
}
return (pParse->nErr || pParse->db->mallocFailed) ? WRC_Abort : WRC_Continue;
}
@@ -74685,7 +74872,7 @@ static int resolveOrderByTermToExprList(
** result-set entry.
*/
for(i=0; i<pEList->nExpr; i++){
- if( sqlite3ExprCompare(pEList->a[i].pExpr, pE)<2 ){
+ if( sqlite3ExprCompare(pEList->a[i].pExpr, pE, -1)<2 ){
return i+1;
}
}
@@ -74812,7 +74999,7 @@ static int resolveCompoundOrderBy(
/*
** Check every term in the ORDER BY or GROUP BY clause pOrderBy of
** the SELECT statement pSelect. If any term is reference to a
-** result set expression (as determined by the ExprList.a.iCol field)
+** result set expression (as determined by the ExprList.a.iOrderByCol field)
** then convert that term into a copy of the corresponding result set
** column.
**
@@ -74860,7 +75047,7 @@ SQLITE_PRIVATE int sqlite3ResolveOrderGroupBy(
** If the order-by term is an integer I between 1 and N (where N is the
** number of columns in the result set of the SELECT) then the expression
** in the resolution is a copy of the I-th result-set expression. If
-** the order-by term is an identify that corresponds to the AS-name of
+** the order-by term is an identifier that corresponds to the AS-name of
** a result-set expression, then the term resolves to a copy of the
** result-set expression. Otherwise, the expression is resolved in
** the usual way - using sqlite3ResolveExprNames().
@@ -74886,16 +75073,19 @@ static int resolveOrderGroupBy(
pParse = pNC->pParse;
for(i=0, pItem=pOrderBy->a; i<pOrderBy->nExpr; i++, pItem++){
Expr *pE = pItem->pExpr;
- iCol = resolveAsName(pParse, pSelect->pEList, pE);
- if( iCol>0 ){
- /* If an AS-name match is found, mark this ORDER BY column as being
- ** a copy of the iCol-th result-set column. The subsequent call to
- ** sqlite3ResolveOrderGroupBy() will convert the expression to a
- ** copy of the iCol-th result-set expression. */
- pItem->iOrderByCol = (u16)iCol;
- continue;
+ Expr *pE2 = sqlite3ExprSkipCollate(pE);
+ if( zType[0]!='G' ){
+ iCol = resolveAsName(pParse, pSelect->pEList, pE2);
+ if( iCol>0 ){
+ /* If an AS-name match is found, mark this ORDER BY column as being
+ ** a copy of the iCol-th result-set column. The subsequent call to
+ ** sqlite3ResolveOrderGroupBy() will convert the expression to a
+ ** copy of the iCol-th result-set expression. */
+ pItem->iOrderByCol = (u16)iCol;
+ continue;
+ }
}
- if( sqlite3ExprIsInteger(sqlite3ExprSkipCollate(pE), &iCol) ){
+ if( sqlite3ExprIsInteger(pE2, &iCol) ){
/* The ORDER BY term is an integer constant. Again, set the column
** number so that sqlite3ResolveOrderGroupBy() will convert the
** order-by term to a copy of the result-set expression */
@@ -74913,7 +75103,7 @@ static int resolveOrderGroupBy(
return 1;
}
for(j=0; j<pSelect->pEList->nExpr; j++){
- if( sqlite3ExprCompare(pE, pSelect->pEList->a[j].pExpr)==0 ){
+ if( sqlite3ExprCompare(pE, pSelect->pEList->a[j].pExpr, -1)==0 ){
pItem->iOrderByCol = j+1;
}
}
@@ -75038,7 +75228,7 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
return WRC_Abort;
}
- /* Add the expression list to the name-context before parsing the
+ /* Add the output column list to the name-context before parsing the
** other expressions in the SELECT statement. This is so that
** expressions in the WHERE clause (etc.) can refer to expressions by
** aliases in the result set.
@@ -75047,10 +75237,8 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
** re-evaluated for each reference to it.
*/
sNC.pEList = p->pEList;
- sNC.ncFlags |= NC_AsMaybe;
if( sqlite3ResolveExprNames(&sNC, p->pHaving) ) return WRC_Abort;
if( sqlite3ResolveExprNames(&sNC, p->pWhere) ) return WRC_Abort;
- sNC.ncFlags &= ~NC_AsMaybe;
/* The ORDER BY and GROUP BY clauses may not refer to terms in
** outer queries
@@ -75220,6 +75408,48 @@ SQLITE_PRIVATE void sqlite3ResolveSelectNames(
sqlite3WalkSelect(&w, p);
}
+/*
+** Resolve names in expressions that can only reference a single table:
+**
+** * CHECK constraints
+** * WHERE clauses on partial indices
+**
+** The Expr.iTable value for Expr.op==TK_COLUMN nodes of the expression
+** is set to -1 and the Expr.iColumn value is set to the column number.
+**
+** Any errors cause an error message to be set in pParse.
+*/
+SQLITE_PRIVATE void sqlite3ResolveSelfReference(
+ Parse *pParse, /* Parsing context */
+ Table *pTab, /* The table being referenced */
+ int type, /* NC_IsCheck or NC_PartIdx */
+ Expr *pExpr, /* Expression to resolve. May be NULL. */
+ ExprList *pList /* Expression list to resolve. May be NUL. */
+){
+ SrcList sSrc; /* Fake SrcList for pParse->pNewTable */
+ NameContext sNC; /* Name context for pParse->pNewTable */
+ int i; /* Loop counter */
+
+ assert( type==NC_IsCheck || type==NC_PartIdx );
+ memset(&sNC, 0, sizeof(sNC));
+ memset(&sSrc, 0, sizeof(sSrc));
+ sSrc.nSrc = 1;
+ sSrc.a[0].zName = pTab->zName;
+ sSrc.a[0].pTab = pTab;
+ sSrc.a[0].iCursor = -1;
+ sNC.pParse = pParse;
+ sNC.pSrcList = &sSrc;
+ sNC.ncFlags = type;
+ if( sqlite3ResolveExprNames(&sNC, pExpr) ) return;
+ if( pList ){
+ for(i=0; i<pList->nExpr; i++){
+ if( sqlite3ResolveExprNames(&sNC, pList->a[i].pExpr) ){
+ return;
+ }
+ }
+ }
+}
+
/************** End of resolve.c *********************************************/
/************** Begin file expr.c ********************************************/
/*
@@ -75337,8 +75567,7 @@ SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){
p = p->pLeft;
continue;
}
- assert( op!=TK_REGISTER || p->op2!=TK_COLLATE );
- if( op==TK_COLLATE ){
+ if( op==TK_COLLATE || (op==TK_REGISTER && p->op2==TK_COLLATE) ){
pColl = sqlite3GetCollSeq(pParse, ENC(db), 0, p->u.zToken);
break;
}
@@ -76143,6 +76372,7 @@ SQLITE_PRIVATE ExprList *sqlite3ExprListDup(sqlite3 *db, ExprList *p, int flags)
pItem->zSpan = sqlite3DbStrDup(db, pOldItem->zSpan);
pItem->sortOrder = pOldItem->sortOrder;
pItem->done = 0;
+ pItem->bSpanIsTab = pOldItem->bSpanIsTab;
pItem->iOrderByCol = pOldItem->iOrderByCol;
pItem->iAlias = pOldItem->iAlias;
}
@@ -76501,6 +76731,7 @@ SQLITE_PRIVATE int sqlite3ExprIsInteger(Expr *p, int *pValue){
case TK_UMINUS: {
int v;
if( sqlite3ExprIsInteger(p->pLeft, &v) ){
+ assert( v!=-2147483648 );
*pValue = -v;
rc = 1;
}
@@ -76819,15 +77050,15 @@ SQLITE_PRIVATE int sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound){
/* Could not found an existing table or index to use as the RHS b-tree.
** We will have to generate an ephemeral table to do the job.
*/
- double savedNQueryLoop = pParse->nQueryLoop;
+ u32 savedNQueryLoop = pParse->nQueryLoop;
int rMayHaveNull = 0;
eType = IN_INDEX_EPH;
if( prNotFound ){
*prNotFound = rMayHaveNull = ++pParse->nMem;
sqlite3VdbeAddOp2(v, OP_Null, 0, *prNotFound);
}else{
- testcase( pParse->nQueryLoop>(double)1 );
- pParse->nQueryLoop = (double)1;
+ testcase( pParse->nQueryLoop>0 );
+ pParse->nQueryLoop = 0;
if( pX->pLeft->iColumn<0 && !ExprHasAnyProperty(pX, EP_xIsSelect) ){
eType = IN_INDEX_ROWID;
}
@@ -76869,7 +77100,7 @@ SQLITE_PRIVATE int sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound){
**
** If rMayHaveNull is zero, that means that the subquery is being used
** for membership testing only. There is no need to initialize any
-** registers to indicate the presense or absence of NULLs on the RHS.
+** registers to indicate the presence or absence of NULLs on the RHS.
**
** For a SELECT or EXISTS operator, return the register that holds the
** result. For IN operators or if an error occurs, the return value is 0.
@@ -76914,10 +77145,9 @@ SQLITE_PRIVATE int sqlite3CodeSubselect(
switch( pExpr->op ){
case TK_IN: {
char affinity; /* Affinity of the LHS of the IN */
- KeyInfo keyInfo; /* Keyinfo for the generated table */
- static u8 sortOrder = 0; /* Fake aSortOrder for keyInfo */
int addr; /* Address of OP_OpenEphemeral instruction */
Expr *pLeft = pExpr->pLeft; /* the LHS of the IN operator */
+ KeyInfo *pKeyInfo = 0; /* Key information */
if( rMayHaveNull ){
sqlite3VdbeAddOp2(v, OP_Null, 0, rMayHaveNull);
@@ -76941,9 +77171,7 @@ SQLITE_PRIVATE int sqlite3CodeSubselect(
pExpr->iTable = pParse->nTab++;
addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pExpr->iTable, !isRowid);
if( rMayHaveNull==0 ) sqlite3VdbeChangeP5(v, BTREE_UNORDERED);
- memset(&keyInfo, 0, sizeof(keyInfo));
- keyInfo.nField = 1;
- keyInfo.aSortOrder = &sortOrder;
+ pKeyInfo = isRowid ? 0 : sqlite3KeyInfoAlloc(pParse->db, 1);
if( ExprHasProperty(pExpr, EP_xIsSelect) ){
/* Case 1: expr IN (SELECT ...)
@@ -76959,14 +77187,17 @@ SQLITE_PRIVATE int sqlite3CodeSubselect(
dest.affSdst = (u8)affinity;
assert( (pExpr->iTable&0x0000FFFF)==pExpr->iTable );
pExpr->x.pSelect->iLimit = 0;
+ testcase( pKeyInfo==0 ); /* Caused by OOM in sqlite3KeyInfoAlloc() */
if( sqlite3Select(pParse, pExpr->x.pSelect, &dest) ){
+ sqlite3DbFree(pParse->db, pKeyInfo);
return 0;
}
pEList = pExpr->x.pSelect->pEList;
- if( ALWAYS(pEList!=0 && pEList->nExpr>0) ){
- keyInfo.aColl[0] = sqlite3BinaryCompareCollSeq(pParse, pExpr->pLeft,
- pEList->a[0].pExpr);
- }
+ assert( pKeyInfo!=0 ); /* OOM will cause exit after sqlite3Select() */
+ assert( pEList!=0 );
+ assert( pEList->nExpr>0 );
+ pKeyInfo->aColl[0] = sqlite3BinaryCompareCollSeq(pParse, pExpr->pLeft,
+ pEList->a[0].pExpr);
}else if( ALWAYS(pExpr->x.pList!=0) ){
/* Case 2: expr IN (exprlist)
**
@@ -76983,8 +77214,9 @@ SQLITE_PRIVATE int sqlite3CodeSubselect(
if( !affinity ){
affinity = SQLITE_AFF_NONE;
}
- keyInfo.aColl[0] = sqlite3ExprCollSeq(pParse, pExpr->pLeft);
- keyInfo.aSortOrder = &sortOrder;
+ if( pKeyInfo ){
+ pKeyInfo->aColl[0] = sqlite3ExprCollSeq(pParse, pExpr->pLeft);
+ }
/* Loop through each expression in <exprlist>. */
r1 = sqlite3GetTempReg(pParse);
@@ -77023,8 +77255,8 @@ SQLITE_PRIVATE int sqlite3CodeSubselect(
sqlite3ReleaseTempReg(pParse, r1);
sqlite3ReleaseTempReg(pParse, r2);
}
- if( !isRowid ){
- sqlite3VdbeChangeP4(v, addr, (void *)&keyInfo, P4_KEYINFO);
+ if( pKeyInfo ){
+ sqlite3VdbeChangeP4(v, addr, (void *)pKeyInfo, P4_KEYINFO_HANDOFF);
}
break;
}
@@ -77584,15 +77816,20 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
/* Otherwise, fall thru into the TK_COLUMN case */
}
case TK_COLUMN: {
- if( pExpr->iTable<0 ){
- /* This only happens when coding check constraints */
- assert( pParse->ckBase>0 );
- inReg = pExpr->iColumn + pParse->ckBase;
- }else{
- inReg = sqlite3ExprCodeGetColumn(pParse, pExpr->pTab,
- pExpr->iColumn, pExpr->iTable, target,
- pExpr->op2);
+ int iTab = pExpr->iTable;
+ if( iTab<0 ){
+ if( pParse->ckBase>0 ){
+ /* Generating CHECK constraints or inserting into partial index */
+ inReg = pExpr->iColumn + pParse->ckBase;
+ break;
+ }else{
+ /* Deleting from a partial index */
+ iTab = pParse->iPartIdxTab;
+ }
}
+ inReg = sqlite3ExprCodeGetColumn(pParse, pExpr->pTab,
+ pExpr->iColumn, iTab, target,
+ pExpr->op2);
break;
}
case TK_INTEGER: {
@@ -78720,6 +78957,7 @@ static void exprCodeBetween(
compRight.pLeft = &exprX;
compRight.pRight = pExpr->x.pList->a[1].pExpr;
exprX.iTable = sqlite3ExprCodeTemp(pParse, &exprX, ®Free1);
+ exprX.op2 = exprX.op;
exprX.op = TK_REGISTER;
if( jumpIfTrue ){
sqlite3ExprIfTrue(pParse, &exprAnd, dest, jumpIfNull);
@@ -79015,6 +79253,12 @@ SQLITE_PRIVATE void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int
** by a COLLATE operator at the top level. Return 2 if there are differences
** other than the top-level COLLATE operator.
**
+** If any subelement of pB has Expr.iTable==(-1) then it is allowed
+** to compare equal to an equivalent element in pA with Expr.iTable==iTab.
+**
+** The pA side might be using TK_REGISTER. If that is the case and pB is
+** not using TK_REGISTER but is otherwise equivalent, then still return 0.
+**
** Sometimes this routine will return 2 even if the two expressions
** really are equivalent. If we cannot prove that the expressions are
** identical, we return 2 just to be safe. So if this routine
@@ -79025,7 +79269,7 @@ SQLITE_PRIVATE void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int
** just might result in some slightly slower code. But returning
** an incorrect 0 or 1 could lead to a malfunction.
*/
-SQLITE_PRIVATE int sqlite3ExprCompare(Expr *pA, Expr *pB){
+SQLITE_PRIVATE int sqlite3ExprCompare(Expr *pA, Expr *pB, int iTab){
if( pA==0||pB==0 ){
return pB==pA ? 0 : 2;
}
@@ -79035,19 +79279,22 @@ SQLITE_PRIVATE int sqlite3ExprCompare(Expr *pA, Expr *pB){
return 2;
}
if( (pA->flags & EP_Distinct)!=(pB->flags & EP_Distinct) ) return 2;
- if( pA->op!=pB->op ){
- if( pA->op==TK_COLLATE && sqlite3ExprCompare(pA->pLeft, pB)<2 ){
+ if( pA->op!=pB->op && (pA->op!=TK_REGISTER || pA->op2!=pB->op) ){
+ if( pA->op==TK_COLLATE && sqlite3ExprCompare(pA->pLeft, pB, iTab)<2 ){
return 1;
}
- if( pB->op==TK_COLLATE && sqlite3ExprCompare(pA, pB->pLeft)<2 ){
+ if( pB->op==TK_COLLATE && sqlite3ExprCompare(pA, pB->pLeft, iTab)<2 ){
return 1;
}
return 2;
}
- if( sqlite3ExprCompare(pA->pLeft, pB->pLeft) ) return 2;
- if( sqlite3ExprCompare(pA->pRight, pB->pRight) ) return 2;
- if( sqlite3ExprListCompare(pA->x.pList, pB->x.pList) ) return 2;
- if( pA->iTable!=pB->iTable || pA->iColumn!=pB->iColumn ) return 2;
+ if( sqlite3ExprCompare(pA->pLeft, pB->pLeft, iTab) ) return 2;
+ if( sqlite3ExprCompare(pA->pRight, pB->pRight, iTab) ) return 2;
+ if( sqlite3ExprListCompare(pA->x.pList, pB->x.pList, iTab) ) return 2;
+ if( pA->iColumn!=pB->iColumn ) return 2;
+ if( pA->iTable!=pB->iTable
+ && pA->op!=TK_REGISTER
+ && (pA->iTable!=iTab || NEVER(pB->iTable>=0)) ) return 2;
if( ExprHasProperty(pA, EP_IntValue) ){
if( !ExprHasProperty(pB, EP_IntValue) || pA->u.iValue!=pB->u.iValue ){
return 2;
@@ -79065,6 +79312,9 @@ SQLITE_PRIVATE int sqlite3ExprCompare(Expr *pA, Expr *pB){
** Compare two ExprList objects. Return 0 if they are identical and
** non-zero if they differ in any way.
**
+** If any subelement of pB has Expr.iTable==(-1) then it is allowed
+** to compare equal to an equivalent element in pA with Expr.iTable==iTab.
+**
** This routine might return non-zero for equivalent ExprLists. The
** only consequence will be disabled optimizations. But this routine
** must never return 0 if the two ExprList objects are different, or
@@ -79073,7 +79323,7 @@ SQLITE_PRIVATE int sqlite3ExprCompare(Expr *pA, Expr *pB){
** Two NULL pointers are considered to be the same. But a NULL pointer
** always differs from a non-NULL pointer.
*/
-SQLITE_PRIVATE int sqlite3ExprListCompare(ExprList *pA, ExprList *pB){
+SQLITE_PRIVATE int sqlite3ExprListCompare(ExprList *pA, ExprList *pB, int iTab){
int i;
if( pA==0 && pB==0 ) return 0;
if( pA==0 || pB==0 ) return 1;
@@ -79082,7 +79332,46 @@ SQLITE_PRIVATE int sqlite3ExprListCompare(ExprList *pA, ExprList *pB){
Expr *pExprA = pA->a[i].pExpr;
Expr *pExprB = pB->a[i].pExpr;
if( pA->a[i].sortOrder!=pB->a[i].sortOrder ) return 1;
- if( sqlite3ExprCompare(pExprA, pExprB) ) return 1;
+ if( sqlite3ExprCompare(pExprA, pExprB, iTab) ) return 1;
+ }
+ return 0;
+}
+
+/*
+** Return true if we can prove the pE2 will always be true if pE1 is
+** true. Return false if we cannot complete the proof or if pE2 might
+** be false. Examples:
+**
+** pE1: x==5 pE2: x==5 Result: true
+** pE1: x>0 pE2: x==5 Result: false
+** pE1: x=21 pE2: x=21 OR y=43 Result: true
+** pE1: x!=123 pE2: x IS NOT NULL Result: true
+** pE1: x!=?1 pE2: x IS NOT NULL Result: true
+** pE1: x IS NULL pE2: x IS NOT NULL Result: false
+** pE1: x IS ?2 pE2: x IS NOT NULL Reuslt: false
+**
+** When comparing TK_COLUMN nodes between pE1 and pE2, if pE2 has
+** Expr.iTable<0 then assume a table number given by iTab.
+**
+** When in doubt, return false. Returning true might give a performance
+** improvement. Returning false might cause a performance reduction, but
+** it will always give the correct answer and is hence always safe.
+*/
+SQLITE_PRIVATE int sqlite3ExprImpliesExpr(Expr *pE1, Expr *pE2, int iTab){
+ if( sqlite3ExprCompare(pE1, pE2, iTab)==0 ){
+ return 1;
+ }
+ if( pE2->op==TK_OR
+ && (sqlite3ExprImpliesExpr(pE1, pE2->pLeft, iTab)
+ || sqlite3ExprImpliesExpr(pE1, pE2->pRight, iTab) )
+ ){
+ return 1;
+ }
+ if( pE2->op==TK_NOTNULL
+ && sqlite3ExprCompare(pE1->pLeft, pE2->pLeft, iTab)==0
+ && (pE1->op!=TK_ISNULL && pE1->op!=TK_IS)
+ ){
+ return 1;
}
return 0;
}
@@ -79267,7 +79556,7 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){
*/
struct AggInfo_func *pItem = pAggInfo->aFunc;
for(i=0; i<pAggInfo->nFunc; i++, pItem++){
- if( sqlite3ExprCompare(pItem->pExpr, pExpr)==0 ){
+ if( sqlite3ExprCompare(pItem->pExpr, pExpr, -1)==0 ){
break;
}
}
@@ -80269,7 +80558,7 @@ exit_begin_add_column:
** The sqlite_stat2 table is not created or used unless the SQLite version
** is between 3.6.18 and 3.7.8, inclusive, and unless SQLite is compiled
** with SQLITE_ENABLE_STAT2. The sqlite_stat2 table is deprecated.
-** The sqlite_stat2 table is superceded by sqlite_stat3, which is only
+** The sqlite_stat2 table is superseded by sqlite_stat3, which is only
** created and used by SQLite versions 3.7.9 and later and with
** SQLITE_ENABLE_STAT3 defined. The fucntionality of sqlite_stat3
** is a superset of sqlite_stat2.
@@ -80684,6 +80973,7 @@ static void analyzeOneTable(
int endOfLoop; /* The end of the loop */
int jZeroRows = -1; /* Jump from here if number of rows is zero */
int iDb; /* Index of database containing pTab */
+ u8 needTableCnt = 1; /* True to count the table */
int regTabname = iMem++; /* Register containing table name */
int regIdxname = iMem++; /* Register containing index name */
int regStat1 = iMem++; /* The stat column of sqlite_stat1 */
@@ -80743,6 +81033,7 @@ static void analyzeOneTable(
int *aChngAddr; /* Array of jump instruction addresses */
if( pOnlyIdx && pOnlyIdx!=pIdx ) continue;
+ if( pIdx->pPartIdxWhere==0 ) needTableCnt = 0;
VdbeNoopComment((v, "Begin analysis of %s", pIdx->zName));
nCol = pIdx->nColumn;
aChngAddr = sqlite3DbMallocRaw(db, sizeof(int)*nCol);
@@ -80902,9 +81193,7 @@ static void analyzeOneTable(
** is never possible.
*/
sqlite3VdbeAddOp2(v, OP_SCopy, iMem, regStat1);
- if( jZeroRows<0 ){
- jZeroRows = sqlite3VdbeAddOp1(v, OP_IfNot, iMem);
- }
+ jZeroRows = sqlite3VdbeAddOp1(v, OP_IfNot, iMem);
for(i=0; i<nCol; i++){
sqlite3VdbeAddOp4(v, OP_String8, 0, regTemp, 0, " ", 0);
sqlite3VdbeAddOp3(v, OP_Concat, regTemp, regStat1, regStat1);
@@ -80914,32 +81203,31 @@ static void analyzeOneTable(
sqlite3VdbeAddOp1(v, OP_ToInt, regTemp);
sqlite3VdbeAddOp3(v, OP_Concat, regTemp, regStat1, regStat1);
}
+ if( pIdx->pPartIdxWhere!=0 ) sqlite3VdbeJumpHere(v, jZeroRows);
sqlite3VdbeAddOp4(v, OP_MakeRecord, regTabname, 3, regRec, "aaa", 0);
sqlite3VdbeAddOp2(v, OP_NewRowid, iStatCur, regNewRowid);
sqlite3VdbeAddOp3(v, OP_Insert, iStatCur, regRec, regNewRowid);
sqlite3VdbeChangeP5(v, OPFLAG_APPEND);
+ if( pIdx->pPartIdxWhere==0 ) sqlite3VdbeJumpHere(v, jZeroRows);
}
- /* If the table has no indices, create a single sqlite_stat1 entry
- ** containing NULL as the index name and the row count as the content.
+ /* Create a single sqlite_stat1 entry containing NULL as the index
+ ** name and the row count as the content.
*/
- if( pTab->pIndex==0 ){
+ if( pOnlyIdx==0 && needTableCnt ){
sqlite3VdbeAddOp3(v, OP_OpenRead, iIdxCur, pTab->tnum, iDb);
VdbeComment((v, "%s", pTab->zName));
sqlite3VdbeAddOp2(v, OP_Count, iIdxCur, regStat1);
sqlite3VdbeAddOp1(v, OP_Close, iIdxCur);
jZeroRows = sqlite3VdbeAddOp1(v, OP_IfNot, regStat1);
- }else{
+ sqlite3VdbeAddOp2(v, OP_Null, 0, regIdxname);
+ sqlite3VdbeAddOp4(v, OP_MakeRecord, regTabname, 3, regRec, "aaa", 0);
+ sqlite3VdbeAddOp2(v, OP_NewRowid, iStatCur, regNewRowid);
+ sqlite3VdbeAddOp3(v, OP_Insert, iStatCur, regRec, regNewRowid);
+ sqlite3VdbeChangeP5(v, OPFLAG_APPEND);
sqlite3VdbeJumpHere(v, jZeroRows);
- jZeroRows = sqlite3VdbeAddOp0(v, OP_Goto);
}
- sqlite3VdbeAddOp2(v, OP_Null, 0, regIdxname);
- sqlite3VdbeAddOp4(v, OP_MakeRecord, regTabname, 3, regRec, "aaa", 0);
- sqlite3VdbeAddOp2(v, OP_NewRowid, iStatCur, regNewRowid);
- sqlite3VdbeAddOp3(v, OP_Insert, iStatCur, regRec, regNewRowid);
- sqlite3VdbeChangeP5(v, OPFLAG_APPEND);
if( pParse->nMem<regRec ) pParse->nMem = regRec;
- sqlite3VdbeJumpHere(v, jZeroRows);
}
@@ -81122,8 +81410,10 @@ static int analysisLoader(void *pData, int argc, char **argv, char **NotUsed){
v = v*10 + c - '0';
z++;
}
- if( i==0 ) pTable->nRowEst = v;
- if( pIndex==0 ) break;
+ if( i==0 && (pIndex==0 || pIndex->pPartIdxWhere==0) ){
+ if( v>0 ) pTable->nRowEst = v;
+ if( pIndex==0 ) break;
+ }
pIndex->aiRowEst[i] = v;
if( *z==' ' ) z++;
if( strcmp(z, "unordered")==0 ){
@@ -81527,6 +81817,9 @@ static void attachFunc(
sqlite3PagerLockingMode(pPager, db->dfltLockMode);
sqlite3BtreeSecureDelete(aNew->pBt,
sqlite3BtreeSecureDelete(db->aDb[0].pBt,-1) );
+#ifndef SQLITE_OMIT_PAGER_PRAGMAS
+ sqlite3BtreeSetPagerFlags(aNew->pBt, 3 | (db->flags & PAGER_FLAGS_MASK));
+#endif
}
aNew->safety_level = 3;
aNew->zName = sqlite3DbStrDup(db, zName);
@@ -82563,6 +82856,7 @@ static void freeIndex(sqlite3 *db, Index *p){
#ifndef SQLITE_OMIT_ANALYZE
sqlite3DeleteIndexSamples(db, p);
#endif
+ sqlite3ExprDelete(db, p->pPartIdxWhere);
sqlite3DbFree(db, p->zColAff);
sqlite3DbFree(db, p);
}
@@ -83406,7 +83700,8 @@ SQLITE_PRIVATE void sqlite3AddPrimaryKey(
#endif
}else{
Index *p;
- p = sqlite3CreateIndex(pParse, 0, 0, 0, pList, onError, 0, 0, sortOrder, 0);
+ p = sqlite3CreateIndex(pParse, 0, 0, 0, pList, onError, 0,
+ 0, sortOrder, 0);
if( p ){
p->autoIndex = 2;
}
@@ -83457,6 +83752,7 @@ SQLITE_PRIVATE void sqlite3AddCollateType(Parse *pParse, Token *pToken){
if( sqlite3LocateCollSeq(pParse, zColl) ){
Index *pIdx;
+ sqlite3DbFree(db, p->aCol[i].zColl);
p->aCol[i].zColl = zColl;
/* If the column is declared as "<name> PRIMARY KEY COLLATE <type>",
@@ -83700,26 +83996,7 @@ SQLITE_PRIVATE void sqlite3EndTable(
/* Resolve names in all CHECK constraint expressions.
*/
if( p->pCheck ){
- SrcList sSrc; /* Fake SrcList for pParse->pNewTable */
- NameContext sNC; /* Name context for pParse->pNewTable */
- ExprList *pList; /* List of all CHECK constraints */
- int i; /* Loop counter */
-
- memset(&sNC, 0, sizeof(sNC));
- memset(&sSrc, 0, sizeof(sSrc));
- sSrc.nSrc = 1;
- sSrc.a[0].zName = p->zName;
- sSrc.a[0].pTab = p;
- sSrc.a[0].iCursor = -1;
- sNC.pParse = pParse;
- sNC.pSrcList = &sSrc;
- sNC.ncFlags = NC_IsCheck;
- pList = p->pCheck;
- for(i=0; i<pList->nExpr; i++){
- if( sqlite3ResolveExprNames(&sNC, pList->a[i].pExpr) ){
- return;
- }
- }
+ sqlite3ResolveSelfReference(pParse, p, NC_IsCheck, 0, p->pCheck);
}
#endif /* !defined(SQLITE_OMIT_CHECK) */
@@ -84571,6 +84848,7 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
int addr1; /* Address of top of loop */
int addr2; /* Address to jump to for next iteration */
int tnum; /* Root page of index */
+ int iPartIdxLabel; /* Jump to this label to skip a row */
Vdbe *v; /* Generate code into this virtual machine */
KeyInfo *pKey; /* KeyInfo for index */
int regRecord; /* Register holding assemblied index record */
@@ -84610,8 +84888,9 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iTab, 0);
regRecord = sqlite3GetTempReg(pParse);
- sqlite3GenerateIndexKey(pParse, pIndex, iTab, regRecord, 1);
+ sqlite3GenerateIndexKey(pParse, pIndex, iTab, regRecord, 1, &iPartIdxLabel);
sqlite3VdbeAddOp2(v, OP_SorterInsert, iSorter, regRecord);
+ sqlite3VdbeResolveLabel(v, iPartIdxLabel);
sqlite3VdbeAddOp2(v, OP_Next, iTab, addr1+1);
sqlite3VdbeJumpHere(v, addr1);
addr1 = sqlite3VdbeAddOp2(v, OP_SorterSort, iSorter, 0);
@@ -84662,7 +84941,7 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex(
ExprList *pList, /* A list of columns to be indexed */
int onError, /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */
Token *pStart, /* The CREATE token that begins this statement */
- Token *pEnd, /* The ")" that closes the CREATE INDEX statement */
+ Expr *pPIWhere, /* WHERE clause for partial indices */
int sortOrder, /* Sort order of primary key when pList==NULL */
int ifNotExist /* Omit error if index already exists */
){
@@ -84684,7 +84963,6 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex(
int nExtra = 0;
char *zExtra;
- assert( pStart==0 || pEnd!=0 ); /* pEnd must be non-NULL if pStart is */
assert( pParse->nErr==0 ); /* Never called with prior errors */
if( db->mallocFailed || IN_DECLARE_VTAB ){
goto exit_create_index;
@@ -84730,7 +85008,12 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex(
pTab = sqlite3LocateTableItem(pParse, 0, &pTblName->a[0]);
assert( db->mallocFailed==0 || pTab==0 );
if( pTab==0 ) goto exit_create_index;
- assert( db->aDb[iDb].pSchema==pTab->pSchema );
+ if( iDb==1 && db->aDb[iDb].pSchema!=pTab->pSchema ){
+ sqlite3ErrorMsg(pParse,
+ "cannot create a TEMP index on non-TEMP table \"%s\"",
+ pTab->zName);
+ goto exit_create_index;
+ }
}else{
assert( pName==0 );
assert( pStart==0 );
@@ -84876,8 +85159,14 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex(
pIndex->pTable = pTab;
pIndex->nColumn = pList->nExpr;
pIndex->onError = (u8)onError;
+ pIndex->uniqNotNull = onError==OE_Abort;
pIndex->autoIndex = (u8)(pName==0);
pIndex->pSchema = db->aDb[iDb].pSchema;
+ if( pPIWhere ){
+ sqlite3ResolveSelfReference(pParse, pTab, NC_PartIdx, pPIWhere, 0);
+ pIndex->pPartIdxWhere = pPIWhere;
+ pPIWhere = 0;
+ }
assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
/* Check to see if we should honor DESC requests on index columns
@@ -84934,6 +85223,7 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex(
pIndex->azColl[i] = zColl;
requestedSortOrder = pListItem->sortOrder & sortOrderMask;
pIndex->aSortOrder[i] = (u8)requestedSortOrder;
+ if( pTab->aCol[j].notNull==0 ) pIndex->uniqNotNull = 0;
}
sqlite3DefaultRowEst(pIndex);
@@ -85032,7 +85322,7 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex(
** has just been created, it contains no data and the index initialization
** step can be skipped.
*/
- else{ /* if( db->init.busy==0 ) */
+ else if( pParse->nErr==0 ){
Vdbe *v;
char *zStmt;
int iMem = ++pParse->nMem;
@@ -85050,12 +85340,11 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex(
** the zStmt variable
*/
if( pStart ){
- assert( pEnd!=0 );
+ int n = (int)(pParse->sLastToken.z - pName->z) + pParse->sLastToken.n;
+ if( pName->z[n-1]==';' ) n--;
/* A named index with an explicit CREATE INDEX statement */
zStmt = sqlite3MPrintf(db, "CREATE%s INDEX %.*s",
- onError==OE_None ? "" : " UNIQUE",
- (int)(pEnd->z - pName->z) + 1,
- pName->z);
+ onError==OE_None ? "" : " UNIQUE", n, pName->z);
}else{
/* An automatic index created by a PRIMARY KEY or UNIQUE constraint */
/* zStmt = sqlite3MPrintf(""); */
@@ -85111,10 +85400,8 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex(
/* Clean up before exiting */
exit_create_index:
- if( pIndex ){
- sqlite3DbFree(db, pIndex->zColAff);
- sqlite3DbFree(db, pIndex);
- }
+ if( pIndex ) freeIndex(db, pIndex);
+ sqlite3ExprDelete(db, pPIWhere);
sqlite3ExprListDelete(db, pList);
sqlite3SrcListDelete(db, pTblName);
sqlite3DbFree(db, zName);
@@ -85365,7 +85652,7 @@ SQLITE_PRIVATE SrcList *sqlite3SrcListEnlarge(
}
pSrc = pNew;
nGot = (sqlite3DbMallocSize(db, pNew) - sizeof(*pSrc))/sizeof(pSrc->a[0])+1;
- pSrc->nAlloc = (u16)nGot;
+ pSrc->nAlloc = (u8)nGot;
}
/* Move existing slots that come after the newly inserted slots
@@ -85373,7 +85660,7 @@ SQLITE_PRIVATE SrcList *sqlite3SrcListEnlarge(
for(i=pSrc->nSrc-1; i>=iStart; i--){
pSrc->a[i+nExtra] = pSrc->a[i];
}
- pSrc->nSrc += (i16)nExtra;
+ pSrc->nSrc += (i8)nExtra;
/* Zero the newly allocated slots */
memset(&pSrc->a[iStart], 0, sizeof(pSrc->a[0])*nExtra);
@@ -85992,25 +86279,20 @@ SQLITE_PRIVATE void sqlite3Reindex(Parse *pParse, Token *pName1, Token *pName2){
SQLITE_PRIVATE KeyInfo *sqlite3IndexKeyinfo(Parse *pParse, Index *pIdx){
int i;
int nCol = pIdx->nColumn;
- int nBytes = sizeof(KeyInfo) + (nCol-1)*sizeof(CollSeq*) + nCol;
- sqlite3 *db = pParse->db;
- KeyInfo *pKey = (KeyInfo *)sqlite3DbMallocZero(db, nBytes);
+ KeyInfo *pKey;
+ pKey = sqlite3KeyInfoAlloc(pParse->db, nCol);
if( pKey ){
- pKey->db = pParse->db;
- pKey->aSortOrder = (u8 *)&(pKey->aColl[nCol]);
- assert( &pKey->aSortOrder[nCol]==&(((u8 *)pKey)[nBytes]) );
for(i=0; i<nCol; i++){
char *zColl = pIdx->azColl[i];
assert( zColl );
pKey->aColl[i] = sqlite3LocateCollSeq(pParse, zColl);
pKey->aSortOrder[i] = pIdx->aSortOrder[i];
}
- pKey->nField = (u16)nCol;
}
if( pParse->nErr ){
- sqlite3DbFree(db, pKey);
+ sqlite3DbFree(pParse->db, pKey);
pKey = 0;
}
return pKey;
@@ -87090,11 +87372,14 @@ SQLITE_PRIVATE void sqlite3GenerateRowIndexDelete(
int i;
Index *pIdx;
int r1;
+ int iPartIdxLabel;
+ Vdbe *v = pParse->pVdbe;
for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
if( aRegIdx!=0 && aRegIdx[i-1]==0 ) continue;
- r1 = sqlite3GenerateIndexKey(pParse, pIdx, iCur, 0, 0);
- sqlite3VdbeAddOp3(pParse->pVdbe, OP_IdxDelete, iCur+i, r1,pIdx->nColumn+1);
+ r1 = sqlite3GenerateIndexKey(pParse, pIdx, iCur, 0, 0, &iPartIdxLabel);
+ sqlite3VdbeAddOp3(v, OP_IdxDelete, iCur+i, r1, pIdx->nColumn+1);
+ sqlite3VdbeResolveLabel(v, iPartIdxLabel);
}
}
@@ -87108,13 +87393,21 @@ SQLITE_PRIVATE void sqlite3GenerateRowIndexDelete(
** registers that holds the elements of the index key. The
** block of registers has already been deallocated by the time
** this routine returns.
+**
+** If *piPartIdxLabel is not NULL, fill it in with a label and jump
+** to that label if pIdx is a partial index that should be skipped.
+** A partial index should be skipped if its WHERE clause evaluates
+** to false or null. If pIdx is not a partial index, *piPartIdxLabel
+** will be set to zero which is an empty label that is ignored by
+** sqlite3VdbeResolveLabel().
*/
SQLITE_PRIVATE int sqlite3GenerateIndexKey(
- Parse *pParse, /* Parsing context */
- Index *pIdx, /* The index for which to generate a key */
- int iCur, /* Cursor number for the pIdx->pTable table */
- int regOut, /* Write the new index key to this register */
- int doMakeRec /* Run the OP_MakeRecord instruction if true */
+ Parse *pParse, /* Parsing context */
+ Index *pIdx, /* The index for which to generate a key */
+ int iCur, /* Cursor number for the pIdx->pTable table */
+ int regOut, /* Write the new index key to this register */
+ int doMakeRec, /* Run the OP_MakeRecord instruction if true */
+ int *piPartIdxLabel /* OUT: Jump to this label to skip partial index */
){
Vdbe *v = pParse->pVdbe;
int j;
@@ -87122,6 +87415,16 @@ SQLITE_PRIVATE int sqlite3GenerateIndexKey(
int regBase;
int nCol;
+ if( piPartIdxLabel ){
+ if( pIdx->pPartIdxWhere ){
+ *piPartIdxLabel = sqlite3VdbeMakeLabel(v);
+ pParse->iPartIdxTab = iCur;
+ sqlite3ExprIfFalse(pParse, pIdx->pPartIdxWhere, *piPartIdxLabel,
+ SQLITE_JUMPIFNULL);
+ }else{
+ *piPartIdxLabel = 0;
+ }
+ }
nCol = pIdx->nColumn;
regBase = sqlite3GetTempRange(pParse, nCol+1);
sqlite3VdbeAddOp2(v, OP_Rowid, iCur, regBase+nCol);
@@ -87380,7 +87683,7 @@ static void instrFunc(
**
** If p1 is negative, then we begin abs(p1) from the end of x[].
**
-** If p2 is negative, return the p2 characters preceeding p1.
+** If p2 is negative, return the p2 characters preceding p1.
*/
static void substrFunc(
sqlite3_context *context,
@@ -88039,10 +88342,6 @@ static const char hexdigits[] = {
};
/*
-** EXPERIMENTAL - This is not an official function. The interface may
-** change. This function may disappear. Do not write code that depends
-** on this function.
-**
** Implementation of the QUOTE() function. This function takes a single
** argument. If the argument is numeric, the return value is the same as
** the argument. If the argument is NULL, the return value is the string
@@ -88231,7 +88530,7 @@ static void zeroblobFunc(
/*
** The replace() function. Three arguments are all strings: call
** them A, B, and C. The result is also a string which is derived
-** from A by replacing every occurance of B with C. The match
+** from A by replacing every occurrence of B with C. The match
** must be exact. Collating sequences are not used.
*/
static void replaceFunc(
@@ -88678,9 +88977,9 @@ static void groupConcatFinalize(sqlite3_context *context){
StrAccum *pAccum;
pAccum = sqlite3_aggregate_context(context, 0);
if( pAccum ){
- if( pAccum->tooBig ){
+ if( pAccum->accError==STRACCUM_TOOBIG ){
sqlite3_result_error_toobig(context);
- }else if( pAccum->mallocFailed ){
+ }else if( pAccum->accError==STRACCUM_NOMEM ){
sqlite3_result_error_nomem(context);
}else{
sqlite3_result_text(context, sqlite3StrAccumFinish(pAccum), -1,
@@ -89298,7 +89597,10 @@ static void fkLookupParent(
}
}
- if( !pFKey->isDeferred && !pParse->pToplevel && !pParse->isMultiWrite ){
+ if( !pFKey->isDeferred && !(pParse->db->flags & SQLITE_DeferFKs)
+ && !pParse->pToplevel
+ && !pParse->isMultiWrite
+ ){
/* Special case: If this is an INSERT statement that will insert exactly
** one row into the table, raise a constraint immediately instead of
** incrementing a counter. This is necessary as the VM code is being
@@ -89689,7 +89991,9 @@ SQLITE_PRIVATE void sqlite3FkCheck(
SrcList *pSrc;
int *aiCol = 0;
- if( !pFKey->isDeferred && !pParse->pToplevel && !pParse->isMultiWrite ){
+ if( !pFKey->isDeferred && !(db->flags & SQLITE_DeferFKs)
+ && !pParse->pToplevel && !pParse->isMultiWrite
+ ){
assert( regOld==0 && regNew!=0 );
/* Inserting a single row into a parent table cannot cause an immediate
** foreign key violation. So do nothing in this case. */
@@ -91484,9 +91788,19 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
for(iCur=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, iCur++){
int regIdx;
int regR;
+ int addrSkipRow = 0;
if( aRegIdx[iCur]==0 ) continue; /* Skip unused indices */
+ if( pIdx->pPartIdxWhere ){
+ sqlite3VdbeAddOp2(v, OP_Null, 0, aRegIdx[iCur]);
+ addrSkipRow = sqlite3VdbeMakeLabel(v);
+ pParse->ckBase = regData;
+ sqlite3ExprIfFalse(pParse, pIdx->pPartIdxWhere, addrSkipRow,
+ SQLITE_JUMPIFNULL);
+ pParse->ckBase = 0;
+ }
+
/* Create a key for accessing the index entry */
regIdx = sqlite3GetTempRange(pParse, pIdx->nColumn+1);
for(i=0; i<pIdx->nColumn; i++){
@@ -91506,6 +91820,7 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
onError = pIdx->onError;
if( onError==OE_None ){
sqlite3ReleaseTempRange(pParse, regIdx, pIdx->nColumn+1);
+ sqlite3VdbeResolveLabel(v, addrSkipRow);
continue; /* pIdx is not a UNIQUE index */
}
if( overrideError!=OE_Default ){
@@ -91575,6 +91890,7 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
}
}
sqlite3VdbeJumpHere(v, j3);
+ sqlite3VdbeResolveLabel(v, addrSkipRow);
sqlite3ReleaseTempReg(pParse, regR);
}
@@ -91604,7 +91920,6 @@ SQLITE_PRIVATE void sqlite3CompleteInsertion(
){
int i;
Vdbe *v;
- int nIdx;
Index *pIdx;
u8 pik_flags;
int regData;
@@ -91613,9 +91928,11 @@ SQLITE_PRIVATE void sqlite3CompleteInsertion(
v = sqlite3GetVdbe(pParse);
assert( v!=0 );
assert( pTab->pSelect==0 ); /* This table is not a VIEW */
- for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdx++){}
- for(i=nIdx-1; i>=0; i--){
+ for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
if( aRegIdx[i]==0 ) continue;
+ if( pIdx->pPartIdxWhere ){
+ sqlite3VdbeAddOp2(v, OP_IsNull, aRegIdx[i], sqlite3VdbeCurrentAddr(v)+2);
+ }
sqlite3VdbeAddOp2(v, OP_IdxInsert, baseCur+i+1, aRegIdx[i]);
if( useSeekResult ){
sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
@@ -91717,6 +92034,7 @@ static int xferCompatibleCollation(const char *z1, const char *z2){
** * The same DESC and ASC markings occurs on all columns
** * The same onError processing (OE_Abort, OE_Ignore, etc)
** * The same collating sequence on each column
+** * The index has the exact same WHERE clause
*/
static int xferCompatibleIndex(Index *pDest, Index *pSrc){
int i;
@@ -91739,6 +92057,9 @@ static int xferCompatibleIndex(Index *pDest, Index *pSrc){
return 0; /* Different collating sequences */
}
}
+ if( sqlite3ExprCompare(pSrc->pPartIdxWhere, pDest->pPartIdxWhere, -1) ){
+ return 0; /* Different WHERE clauses */
+ }
/* If no test above fails then the indices must be compatible */
return 1;
@@ -91894,7 +92215,7 @@ static int xferOptimization(
}
}
#ifndef SQLITE_OMIT_CHECK
- if( pDest->pCheck && sqlite3ExprListCompare(pSrc->pCheck, pDest->pCheck) ){
+ if( pDest->pCheck && sqlite3ExprListCompare(pSrc->pCheck,pDest->pCheck,-1) ){
return 0; /* Tables have different CHECK constraints. Ticket #2252 */
}
#endif
@@ -92651,11 +92972,14 @@ struct sqlite3_api_routines {
** extension */
# define SQLITE_EXTENSION_INIT1 const sqlite3_api_routines *sqlite3_api=0;
# define SQLITE_EXTENSION_INIT2(v) sqlite3_api=v;
+# define SQLITE_EXTENSION_INIT3 \
+ extern const sqlite3_api_routines *sqlite3_api;
#else
/* This case when the file is being statically linked into the
** application */
# define SQLITE_EXTENSION_INIT1 /*no-op*/
# define SQLITE_EXTENSION_INIT2(v) (void)v; /* unused parameter */
+# define SQLITE_EXTENSION_INIT3 /*no-op*/
#endif
#endif /* _SQLITE3EXT_H_ */
@@ -93313,6 +93637,35 @@ SQLITE_API int sqlite3_auto_extension(void (*xInit)(void)){
}
/*
+** Cancel a prior call to sqlite3_auto_extension. Remove xInit from the
+** set of routines that is invoked for each new database connection, if it
+** is currently on the list. If xInit is not on the list, then this
+** routine is a no-op.
+**
+** Return 1 if xInit was found on the list and removed. Return 0 if xInit
+** was not on the list.
+*/
+SQLITE_API int sqlite3_cancel_auto_extension(void (*xInit)(void)){
+#if SQLITE_THREADSAFE
+ sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
+#endif
+ int i;
+ int n = 0;
+ wsdAutoextInit;
+ sqlite3_mutex_enter(mutex);
+ for(i=wsdAutoext.nExt-1; i>=0; i--){
+ if( wsdAutoext.aExt[i]==xInit ){
+ wsdAutoext.nExt--;
+ wsdAutoext.aExt[i] = wsdAutoext.aExt[wsdAutoext.nExt];
+ n++;
+ break;
+ }
+ }
+ sqlite3_mutex_leave(mutex);
+ return n;
+}
+
+/*
** Reset the automatic extension loading mechanism.
*/
SQLITE_API void sqlite3_reset_auto_extension(void){
@@ -93533,6 +93886,36 @@ static void returnSingleInt(Parse *pParse, const char *zLabel, i64 value){
sqlite3VdbeAddOp2(v, OP_ResultRow, mem, 1);
}
+
+/*
+** Set the safety_level and pager flags for pager iDb. Or if iDb<0
+** set these values for all pagers.
+*/
+#ifndef SQLITE_OMIT_PAGER_PRAGMAS
+static void setAllPagerFlags(sqlite3 *db){
+ if( db->autoCommit ){
+ Db *pDb = db->aDb;
+ int n = db->nDb;
+ assert( SQLITE_FullFSync==PAGER_FULLFSYNC );
+ assert( SQLITE_CkptFullFSync==PAGER_CKPT_FULLFSYNC );
+ assert( SQLITE_CacheSpill==PAGER_CACHESPILL );
+ assert( (PAGER_FULLFSYNC | PAGER_CKPT_FULLFSYNC | PAGER_CACHESPILL)
+ == PAGER_FLAGS_MASK );
+ assert( (pDb->safety_level & PAGER_SYNCHRONOUS_MASK)==pDb->safety_level );
+ while( (n--) > 0 ){
+ if( pDb->pBt ){
+ sqlite3BtreeSetPagerFlags(pDb->pBt,
+ pDb->safety_level | (db->flags & PAGER_FLAGS_MASK) );
+ }
+ pDb++;
+ }
+ }
+}
+#else
+# define setAllPagerFlags(X) /* no-op */
+#endif
+
+
#ifndef SQLITE_OMIT_FLAG_PRAGMAS
/*
** Check to see if zRight and zLeft refer to a pragma that queries
@@ -93551,7 +93934,9 @@ static int flagPragma(Parse *pParse, const char *zLeft, const char *zRight){
{ "legacy_file_format", SQLITE_LegacyFileFmt },
{ "fullfsync", SQLITE_FullFSync },
{ "checkpoint_fullfsync", SQLITE_CkptFullFSync },
+ { "cache_spill", SQLITE_CacheSpill },
{ "reverse_unordered_selects", SQLITE_ReverseOrder },
+ { "query_only", SQLITE_QueryOnly },
#ifndef SQLITE_OMIT_AUTOMATIC_INDEX
{ "automatic_index", SQLITE_AutoIndex },
#endif
@@ -93572,12 +93957,13 @@ static int flagPragma(Parse *pParse, const char *zLeft, const char *zRight){
/* TODO: Maybe it shouldn't be possible to change the ReadUncommitted
** flag if there are any active statements. */
{ "read_uncommitted", SQLITE_ReadUncommitted },
- { "recursive_triggers", SQLITE_RecTriggers },
+ { "recursive_triggers", SQLITE_RecTriggers },
/* This flag may only be set if both foreign-key and trigger support
** are present in the build. */
#if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER)
- { "foreign_keys", SQLITE_ForeignKeys },
+ { "foreign_keys", SQLITE_ForeignKeys },
+ { "defer_foreign_keys", SQLITE_DeferFKs },
#endif
};
int i;
@@ -93603,6 +93989,7 @@ static int flagPragma(Parse *pParse, const char *zLeft, const char *zRight){
db->flags |= mask;
}else{
db->flags &= ~mask;
+ if( mask==SQLITE_DeferFKs ) db->nDeferredImmCons = 0;
}
/* Many of the flag-pragmas modify the code generated by the SQL
@@ -94149,11 +94536,15 @@ SQLITE_PRIVATE void sqlite3Pragma(
}
}
sz = -1;
- if( sqlite3_file_control(db,zDb,SQLITE_FCNTL_MMAP_SIZE,&sz)==SQLITE_OK ){
+ rc = sqlite3_file_control(db, zDb, SQLITE_FCNTL_MMAP_SIZE, &sz);
#if SQLITE_MAX_MMAP_SIZE==0
- sz = 0;
+ sz = 0;
#endif
+ if( rc==SQLITE_OK ){
returnSingleInt(pParse, "mmap_size", sz);
+ }else if( rc!=SQLITE_NOTFOUND ){
+ pParse->nErr++;
+ pParse->rc = rc;
}
}else
@@ -94334,6 +94725,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
"Safety level may not be changed inside a transaction");
}else{
pDb->safety_level = getSafetyLevel(zRight,0,1)+1;
+ setAllPagerFlags(db);
}
}
}else
@@ -94341,8 +94733,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
#ifndef SQLITE_OMIT_FLAG_PRAGMAS
if( flagPragma(pParse, zLeft, zRight) ){
- /* The flagPragma() subroutine also generates any necessary code
- ** there is nothing more to do here */
+ setAllPagerFlags(db);
}else
#endif /* SQLITE_OMIT_FLAG_PRAGMAS */
@@ -94738,7 +95129,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
#endif
#ifndef SQLITE_OMIT_INTEGRITY_CHECK
- /* Pragma "quick_check" is an experimental reduced version of
+ /* Pragma "quick_check" is reduced version of
** integrity_check designed to detect most database corruption
** without most of the overhead of a full integrity-check.
*/
@@ -94822,9 +95213,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
}
/* Make sure sufficient number of registers have been allocated */
- if( pParse->nMem < cnt+4 ){
- pParse->nMem = cnt+4;
- }
+ pParse->nMem = MAX( pParse->nMem, cnt+7 );
/* Do the b-tree integrity checks */
sqlite3VdbeAddOp3(v, OP_IntegrityCk, 2, cnt, 1);
@@ -94849,12 +95238,15 @@ SQLITE_PRIVATE void sqlite3Pragma(
addr = sqlite3VdbeAddOp1(v, OP_IfPos, 1); /* Stop if out of errors */
sqlite3VdbeAddOp2(v, OP_Halt, 0, 0);
sqlite3VdbeJumpHere(v, addr);
+ sqlite3ExprCacheClear(pParse);
sqlite3OpenTableAndIndices(pParse, pTab, 1, OP_OpenRead);
- sqlite3VdbeAddOp2(v, OP_Integer, 0, 2); /* reg(2) will count entries */
- loopTop = sqlite3VdbeAddOp2(v, OP_Rewind, 1, 0);
- sqlite3VdbeAddOp2(v, OP_AddImm, 2, 1); /* increment entry count */
for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
- int jmp2;
+ sqlite3VdbeAddOp2(v, OP_Integer, 0, 7+j); /* index entries counter */
+ }
+ pParse->nMem = MAX(pParse->nMem, 7+j);
+ loopTop = sqlite3VdbeAddOp2(v, OP_Rewind, 1, 0) + 1;
+ for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
+ int jmp2, jmp3;
int r1;
static const VdbeOpList idxErr[] = {
{ OP_AddImm, 1, -1, 0},
@@ -94869,7 +95261,8 @@ SQLITE_PRIVATE void sqlite3Pragma(
{ OP_IfPos, 1, 0, 0}, /* 9 */
{ OP_Halt, 0, 0, 0},
};
- r1 = sqlite3GenerateIndexKey(pParse, pIdx, 1, 3, 0);
+ r1 = sqlite3GenerateIndexKey(pParse, pIdx, 1, 3, 0, &jmp3);
+ sqlite3VdbeAddOp2(v, OP_AddImm, 7+j, 1); /* increment entry count */
jmp2 = sqlite3VdbeAddOp4Int(v, OP_Found, j+2, 0, r1, pIdx->nColumn+1);
addr = sqlite3VdbeAddOpList(v, ArraySize(idxErr), idxErr);
sqlite3VdbeChangeP4(v, addr+1, "rowid ", P4_STATIC);
@@ -94877,35 +95270,25 @@ SQLITE_PRIVATE void sqlite3Pragma(
sqlite3VdbeChangeP4(v, addr+4, pIdx->zName, P4_TRANSIENT);
sqlite3VdbeJumpHere(v, addr+9);
sqlite3VdbeJumpHere(v, jmp2);
+ sqlite3VdbeResolveLabel(v, jmp3);
}
- sqlite3VdbeAddOp2(v, OP_Next, 1, loopTop+1);
- sqlite3VdbeJumpHere(v, loopTop);
+ sqlite3VdbeAddOp2(v, OP_Next, 1, loopTop);
+ sqlite3VdbeJumpHere(v, loopTop-1);
+#ifndef SQLITE_OMIT_BTREECOUNT
+ sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0,
+ "wrong # of entries in index ", P4_STATIC);
for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
- static const VdbeOpList cntIdx[] = {
- { OP_Integer, 0, 3, 0},
- { OP_Rewind, 0, 0, 0}, /* 1 */
- { OP_AddImm, 3, 1, 0},
- { OP_Next, 0, 0, 0}, /* 3 */
- { OP_Eq, 2, 0, 3}, /* 4 */
- { OP_AddImm, 1, -1, 0},
- { OP_String8, 0, 2, 0}, /* 6 */
- { OP_String8, 0, 3, 0}, /* 7 */
- { OP_Concat, 3, 2, 2},
- { OP_ResultRow, 2, 1, 0},
- };
- addr = sqlite3VdbeAddOp1(v, OP_IfPos, 1);
+ addr = sqlite3VdbeCurrentAddr(v);
+ sqlite3VdbeAddOp2(v, OP_IfPos, 1, addr+2);
sqlite3VdbeAddOp2(v, OP_Halt, 0, 0);
- sqlite3VdbeJumpHere(v, addr);
- addr = sqlite3VdbeAddOpList(v, ArraySize(cntIdx), cntIdx);
- sqlite3VdbeChangeP1(v, addr+1, j+2);
- sqlite3VdbeChangeP2(v, addr+1, addr+4);
- sqlite3VdbeChangeP1(v, addr+3, j+2);
- sqlite3VdbeChangeP2(v, addr+3, addr+2);
- sqlite3VdbeJumpHere(v, addr+4);
- sqlite3VdbeChangeP4(v, addr+6,
- "wrong # of entries in index ", P4_STATIC);
- sqlite3VdbeChangeP4(v, addr+7, pIdx->zName, P4_TRANSIENT);
+ sqlite3VdbeAddOp2(v, OP_Count, j+2, 3);
+ sqlite3VdbeAddOp3(v, OP_Eq, 7+j, addr+8, 3);
+ sqlite3VdbeAddOp2(v, OP_AddImm, 1, -1);
+ sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, pIdx->zName, P4_TRANSIENT);
+ sqlite3VdbeAddOp3(v, OP_Concat, 3, 2, 7);
+ sqlite3VdbeAddOp2(v, OP_ResultRow, 7, 1);
}
+#endif /* SQLITE_OMIT_BTREECOUNT */
}
}
addr = sqlite3VdbeAddOpList(v, ArraySize(endCode), endCode);
@@ -95196,10 +95579,10 @@ SQLITE_PRIVATE void sqlite3Pragma(
#ifdef SQLITE_HAS_CODEC
if( sqlite3StrICmp(zLeft, "key")==0 && zRight ){
- sqlite3_key(db, zRight, sqlite3Strlen30(zRight));
+ sqlite3_key_v2(db, zDb, zRight, sqlite3Strlen30(zRight));
}else
if( sqlite3StrICmp(zLeft, "rekey")==0 && zRight ){
- sqlite3_rekey(db, zRight, sqlite3Strlen30(zRight));
+ sqlite3_rekey_v2(db, zDb, zRight, sqlite3Strlen30(zRight));
}else
if( zRight && (sqlite3StrICmp(zLeft, "hexkey")==0 ||
sqlite3StrICmp(zLeft, "hexrekey")==0) ){
@@ -95211,9 +95594,9 @@ SQLITE_PRIVATE void sqlite3Pragma(
zKey[i/2] = (h2 & 0x0f) | ((h1 & 0xf)<<4);
}
if( (zLeft[3] & 0xf)==0xb ){
- sqlite3_key(db, zKey, i/2);
+ sqlite3_key_v2(db, zDb, zKey, i/2);
}else{
- sqlite3_rekey(db, zKey, i/2);
+ sqlite3_rekey_v2(db, zDb, zKey, i/2);
}
}else
#endif
@@ -95235,17 +95618,6 @@ SQLITE_PRIVATE void sqlite3Pragma(
{/* Empty ELSE clause */}
- /*
- ** Reset the safety level, in case the fullfsync flag or synchronous
- ** setting changed.
- */
-#ifndef SQLITE_OMIT_PAGER_PRAGMAS
- if( db->autoCommit ){
- sqlite3BtreeSetSafetyLevel(pDb->pBt, pDb->safety_level,
- (db->flags&SQLITE_FullFSync)!=0,
- (db->flags&SQLITE_CkptFullFSync)!=0);
- }
-#endif
pragma_out:
sqlite3DbFree(db, zLeft);
sqlite3DbFree(db, zRight);
@@ -95848,7 +96220,7 @@ static int sqlite3Prepare(
sqlite3VtabUnlockList(db);
pParse->db = db;
- pParse->nQueryLoop = (double)1;
+ pParse->nQueryLoop = 0; /* Logarithmic, so 0 really means 1 */
if( nBytes>=0 && (nBytes==0 || zSql[nBytes-1]!=0) ){
char *zSqlCopy;
int mxLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH];
@@ -95870,7 +96242,7 @@ static int sqlite3Prepare(
}else{
sqlite3RunParser(pParse, zSql, &zErrMsg);
}
- assert( 1==(int)pParse->nQueryLoop );
+ assert( 0==pParse->nQueryLoop );
if( db->mallocFailed ){
pParse->rc = SQLITE_NOMEM;
@@ -96066,6 +96438,12 @@ static int sqlite3Prepare16(
if( !sqlite3SafetyCheckOk(db) ){
return SQLITE_MISUSE_BKPT;
}
+ if( nBytes>=0 ){
+ int sz;
+ const char *z = (const char*)zSql;
+ for(sz=0; sz<nBytes && (z[sz]!=0 || z[sz+1]!=0); sz += 2){}
+ nBytes = sz;
+ }
sqlite3_mutex_enter(db->mutex);
zSql8 = sqlite3Utf16to8(db, zSql, nBytes, SQLITE_UTF16NATIVE);
if( zSql8 ){
@@ -96234,7 +96612,7 @@ SQLITE_PRIVATE void sqlite3SelectDelete(sqlite3 *db, Select *p){
}
/*
-** Given 1 to 3 identifiers preceeding the JOIN keyword, determine the
+** Given 1 to 3 identifiers preceding the JOIN keyword, determine the
** type of join. Return an integer constant that expresses that type
** in terms of the following bit values:
**
@@ -96928,6 +97306,25 @@ static void selectInnerLoop(
}
/*
+** Allocate a KeyInfo object sufficient for an index of N columns.
+**
+** Actually, always allocate one extra column for the rowid at the end
+** of the index. So the KeyInfo returned will have space sufficient for
+** N+1 columns.
+*/
+SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoAlloc(sqlite3 *db, int N){
+ KeyInfo *p = sqlite3DbMallocZero(db,
+ sizeof(KeyInfo) + (N+1)*(sizeof(CollSeq*)+1));
+ if( p ){
+ p->aSortOrder = (u8*)&p->aColl[N+1];
+ p->nField = (u16)N;
+ p->enc = ENC(db);
+ p->db = db;
+ }
+ return p;
+}
+
+/*
** Given an expression list, generate a KeyInfo structure that records
** the collating sequence for each expression in that expression list.
**
@@ -96943,25 +97340,19 @@ static void selectInnerLoop(
** P4_KEYINFO_HANDOFF is the usual way of dealing with this.
*/
static KeyInfo *keyInfoFromExprList(Parse *pParse, ExprList *pList){
- sqlite3 *db = pParse->db;
int nExpr;
KeyInfo *pInfo;
struct ExprList_item *pItem;
+ sqlite3 *db = pParse->db;
int i;
nExpr = pList->nExpr;
- pInfo = sqlite3DbMallocZero(db, sizeof(*pInfo) + nExpr*(sizeof(CollSeq*)+1) );
+ pInfo = sqlite3KeyInfoAlloc(db, nExpr);
if( pInfo ){
- pInfo->aSortOrder = (u8*)&pInfo->aColl[nExpr];
- pInfo->nField = (u16)nExpr;
- pInfo->enc = ENC(db);
- pInfo->db = db;
for(i=0, pItem=pList->a; i<nExpr; i++, pItem++){
CollSeq *pColl;
pColl = sqlite3ExprCollSeq(pParse, pItem->pExpr);
- if( !pColl ){
- pColl = db->pDfltColl;
- }
+ if( !pColl ) pColl = db->pDfltColl;
pInfo->aColl[i] = pColl;
pInfo->aSortOrder[i] = pItem->sortOrder;
}
@@ -97648,7 +98039,7 @@ static void computeLimitRegisters(Parse *pParse, Select *p, int iBreak){
/*
** "LIMIT -1" always shows all rows. There is some
- ** contraversy about what the correct behavior should be.
+ ** controversy about what the correct behavior should be.
** The current implementation interprets "LIMIT 0" to mean
** no rows.
*/
@@ -97663,8 +98054,8 @@ static void computeLimitRegisters(Parse *pParse, Select *p, int iBreak){
VdbeComment((v, "LIMIT counter"));
if( n==0 ){
sqlite3VdbeAddOp2(v, OP_Goto, 0, iBreak);
- }else{
- if( p->nSelectRow > (double)n ) p->nSelectRow = (double)n;
+ }else if( n>=0 && p->nSelectRow>(u64)n ){
+ p->nSelectRow = n;
}
}else{
sqlite3ExprCode(pParse, p->pLimit, iLimit);
@@ -97858,9 +98249,9 @@ static int multiSelect(
p->nSelectRow += pPrior->nSelectRow;
if( pPrior->pLimit
&& sqlite3ExprIsInteger(pPrior->pLimit, &nLimit)
- && p->nSelectRow > (double)nLimit
+ && nLimit>0 && p->nSelectRow > (u64)nLimit
){
- p->nSelectRow = (double)nLimit;
+ p->nSelectRow = nLimit;
}
if( addr ){
sqlite3VdbeJumpHere(v, addr);
@@ -98067,23 +98458,17 @@ static int multiSelect(
assert( p->pRightmost==p );
nCol = p->pEList->nExpr;
- pKeyInfo = sqlite3DbMallocZero(db,
- sizeof(*pKeyInfo)+nCol*(sizeof(CollSeq*) + 1));
+ pKeyInfo = sqlite3KeyInfoAlloc(db, nCol);
if( !pKeyInfo ){
rc = SQLITE_NOMEM;
goto multi_select_end;
}
-
- pKeyInfo->enc = ENC(db);
- pKeyInfo->nField = (u16)nCol;
-
for(i=0, apColl=pKeyInfo->aColl; i<nCol; i++, apColl++){
*apColl = multiSelectCollSeq(pParse, p, i);
if( 0==*apColl ){
*apColl = db->pDfltColl;
}
}
- pKeyInfo->aSortOrder = (u8*)apColl;
for(pLoop=p; pLoop; pLoop=pLoop->pPrior){
for(i=0; i<2; i++){
@@ -98452,12 +98837,8 @@ static int multiSelectOrderBy(
assert( pItem->iOrderByCol>0 && pItem->iOrderByCol<=p->pEList->nExpr );
aPermute[i] = pItem->iOrderByCol - 1;
}
- pKeyMerge =
- sqlite3DbMallocRaw(db, sizeof(*pKeyMerge)+nOrderBy*(sizeof(CollSeq*)+1));
+ pKeyMerge = sqlite3KeyInfoAlloc(db, nOrderBy);
if( pKeyMerge ){
- pKeyMerge->aSortOrder = (u8*)&pKeyMerge->aColl[nOrderBy];
- pKeyMerge->nField = (u16)nOrderBy;
- pKeyMerge->enc = ENC(db);
for(i=0; i<nOrderBy; i++){
CollSeq *pColl;
Expr *pTerm = pOrderBy->a[i].pExpr;
@@ -98494,12 +98875,8 @@ static int multiSelectOrderBy(
regPrev = pParse->nMem+1;
pParse->nMem += nExpr+1;
sqlite3VdbeAddOp2(v, OP_Integer, 0, regPrev);
- pKeyDup = sqlite3DbMallocZero(db,
- sizeof(*pKeyDup) + nExpr*(sizeof(CollSeq*)+1) );
+ pKeyDup = sqlite3KeyInfoAlloc(db, nExpr);
if( pKeyDup ){
- pKeyDup->aSortOrder = (u8*)&pKeyDup->aColl[nExpr];
- pKeyDup->nField = (u16)nExpr;
- pKeyDup->enc = ENC(db);
for(i=0; i<nExpr; i++){
pKeyDup->aColl[i] = multiSelectCollSeq(pParse, p, i);
pKeyDup->aSortOrder[i] = 0;
@@ -99765,10 +100142,12 @@ static int exprWalkNoop(Walker *NotUsed, Expr *NotUsed2){
static void sqlite3SelectExpand(Parse *pParse, Select *pSelect){
Walker w;
memset(&w, 0, sizeof(w));
- w.xSelectCallback = convertCompoundSelectToSubquery;
w.xExprCallback = exprWalkNoop;
w.pParse = pParse;
- sqlite3WalkSelect(&w, pSelect);
+ if( pParse->hasCompound ){
+ w.xSelectCallback = convertCompoundSelectToSubquery;
+ sqlite3WalkSelect(&w, pSelect);
+ }
w.xSelectCallback = selectExpander;
sqlite3WalkSelect(&w, pSelect);
}
@@ -100009,11 +100388,10 @@ static void explainSimpleCount(
Index *pIdx /* Index used to optimize scan, or NULL */
){
if( pParse->explain==2 ){
- char *zEqp = sqlite3MPrintf(pParse->db, "SCAN TABLE %s %s%s(~%d rows)",
+ char *zEqp = sqlite3MPrintf(pParse->db, "SCAN TABLE %s%s%s",
pTab->zName,
- pIdx ? "USING COVERING INDEX " : "",
- pIdx ? pIdx->zName : "",
- pTab->nRowEst
+ pIdx ? " USING COVERING INDEX " : "",
+ pIdx ? pIdx->zName : ""
);
sqlite3VdbeAddOp4(
pParse->pVdbe, OP_Explain, pParse->iSelectId, 0, 0, zEqp, P4_DYNAMIC
@@ -100171,7 +100549,7 @@ SQLITE_PRIVATE int sqlite3Select(
}
/* Increment Parse.nHeight by the height of the largest expression
- ** tree refered to by this, the parent select. The child select
+ ** tree referred to by this, the parent select. The child select
** may contain expression trees of at most
** (SQLITE_MAX_EXPR_DEPTH-Parse.nHeight) height. This is a bit
** more conservative than necessary, but much easier than enforcing
@@ -100303,7 +100681,7 @@ SQLITE_PRIVATE int sqlite3Select(
** Use the SQLITE_GroupByOrder flag with SQLITE_TESTCTRL_OPTIMIZER
** to disable this optimization for testing purposes.
*/
- if( sqlite3ExprListCompare(p->pGroupBy, pOrderBy)==0
+ if( sqlite3ExprListCompare(p->pGroupBy, pOrderBy, -1)==0
&& OptimizationEnabled(db, SQLITE_GroupByOrder) ){
pOrderBy = 0;
}
@@ -100324,7 +100702,7 @@ SQLITE_PRIVATE int sqlite3Select(
** BY and DISTINCT, and an index or separate temp-table for the other.
*/
if( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct
- && sqlite3ExprListCompare(pOrderBy, p->pEList)==0
+ && sqlite3ExprListCompare(pOrderBy, p->pEList, -1)==0
){
p->selFlags &= ~SF_Distinct;
p->pGroupBy = sqlite3ExprListDup(db, p->pEList, 0);
@@ -100364,7 +100742,7 @@ SQLITE_PRIVATE int sqlite3Select(
/* Set the limiter.
*/
iEnd = sqlite3VdbeMakeLabel(v);
- p->nSelectRow = (double)LARGEST_INT64;
+ p->nSelectRow = LARGEST_INT64;
computeLimitRegisters(pParse, p, iEnd);
if( p->iLimit==0 && addrSortIndex>=0 ){
sqlite3VdbeGetOp(v, addrSortIndex)->opcode = OP_SorterOpen;
@@ -100387,14 +100765,19 @@ SQLITE_PRIVATE int sqlite3Select(
if( !isAgg && pGroupBy==0 ){
/* No aggregate functions and no GROUP BY clause */
- ExprList *pDist = (sDistinct.isTnct ? p->pEList : 0);
+ u16 wctrlFlags = (sDistinct.isTnct ? WHERE_WANT_DISTINCT : 0);
/* Begin the database scan. */
- pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pOrderBy, pDist, 0,0);
+ pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pOrderBy, p->pEList,
+ wctrlFlags, 0);
if( pWInfo==0 ) goto select_end;
- if( pWInfo->nRowOut < p->nSelectRow ) p->nSelectRow = pWInfo->nRowOut;
- if( pWInfo->eDistinct ) sDistinct.eTnctType = pWInfo->eDistinct;
- if( pOrderBy && pWInfo->nOBSat==pOrderBy->nExpr ) pOrderBy = 0;
+ if( sqlite3WhereOutputRowCount(pWInfo) < p->nSelectRow ){
+ p->nSelectRow = sqlite3WhereOutputRowCount(pWInfo);
+ }
+ if( sDistinct.isTnct && sqlite3WhereIsDistinct(pWInfo) ){
+ sDistinct.eTnctType = sqlite3WhereIsDistinct(pWInfo);
+ }
+ if( pOrderBy && sqlite3WhereIsOrdered(pWInfo) ) pOrderBy = 0;
/* If sorting index that was created by a prior OP_OpenEphemeral
** instruction ended up not being needed, then change the OP_OpenEphemeral
@@ -100407,7 +100790,8 @@ SQLITE_PRIVATE int sqlite3Select(
/* Use the standard inner loop. */
selectInnerLoop(pParse, p, pEList, 0, 0, pOrderBy, &sDistinct, pDest,
- pWInfo->iContinue, pWInfo->iBreak);
+ sqlite3WhereContinueLabel(pWInfo),
+ sqlite3WhereBreakLabel(pWInfo));
/* End the database scan loop.
*/
@@ -100440,9 +100824,9 @@ SQLITE_PRIVATE int sqlite3Select(
for(k=pGroupBy->nExpr, pItem=pGroupBy->a; k>0; k--, pItem++){
pItem->iAlias = 0;
}
- if( p->nSelectRow>(double)100 ) p->nSelectRow = (double)100;
+ if( p->nSelectRow>100 ) p->nSelectRow = 100;
}else{
- p->nSelectRow = (double)1;
+ p->nSelectRow = 1;
}
@@ -100522,9 +100906,10 @@ SQLITE_PRIVATE int sqlite3Select(
** in the right order to begin with.
*/
sqlite3VdbeAddOp2(v, OP_Gosub, regReset, addrReset);
- pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pGroupBy, 0, 0, 0);
+ pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pGroupBy, 0,
+ WHERE_GROUPBY, 0);
if( pWInfo==0 ) goto select_end;
- if( pWInfo->nOBSat==pGroupBy->nExpr ){
+ if( sqlite3WhereIsOrdered(pWInfo) ){
/* The optimizer is able to deliver rows in group by order so
** we do not have to sort. The OP_OpenEphemeral table will be
** cancelled later because we still need to use the pKeyInfo
@@ -100805,8 +101190,8 @@ SQLITE_PRIVATE int sqlite3Select(
}
updateAccumulator(pParse, &sAggInfo);
assert( pMinMax==0 || pMinMax->nExpr==1 );
- if( pWInfo->nOBSat>0 ){
- sqlite3VdbeAddOp2(v, OP_Goto, 0, pWInfo->iBreak);
+ if( sqlite3WhereIsOrdered(pWInfo) ){
+ sqlite3VdbeAddOp2(v, OP_Goto, 0, sqlite3WhereBreakLabel(pWInfo));
VdbeComment((v, "%s() by index",
(flag==WHERE_ORDERBY_MIN?"min":"max")));
}
@@ -102165,7 +102550,7 @@ SQLITE_PRIVATE void sqlite3CodeRowTriggerDirect(
/*
** This is called to code the required FOR EACH ROW triggers for an operation
** on table pTab. The operation to code triggers for (INSERT, UPDATE or DELETE)
-** is given by the op paramater. The tr_tm parameter determines whether the
+** is given by the op parameter. The tr_tm parameter determines whether the
** BEFORE or AFTER triggers are coded. If the operation is an UPDATE, then
** parameter pChanges is passed the list of columns being modified.
**
@@ -102544,7 +102929,7 @@ SQLITE_PRIVATE void sqlite3Update(
}
for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
int reg;
- if( hasFK || chngRowid ){
+ if( hasFK || chngRowid || pIdx->pPartIdxWhere ){
reg = ++pParse->nMem;
}else{
reg = 0;
@@ -102616,7 +103001,7 @@ SQLITE_PRIVATE void sqlite3Update(
pParse, pTabList, pWhere, 0, 0, WHERE_ONEPASS_DESIRED, 0
);
if( pWInfo==0 ) goto update_cleanup;
- okOnePass = pWInfo->okOnePass;
+ okOnePass = sqlite3WhereOkOnePass(pWInfo);
/* Remember the rowid of every item to be updated.
*/
@@ -103085,7 +103470,7 @@ SQLITE_PRIVATE int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){
sqlite3SetString(pzErrMsg, db, "cannot VACUUM from within a transaction");
return SQLITE_ERROR;
}
- if( db->activeVdbeCnt>1 ){
+ if( db->nVdbeActive>1 ){
sqlite3SetString(pzErrMsg, db,"cannot VACUUM - SQL statements in progress");
return SQLITE_ERROR;
}
@@ -104135,10 +104520,9 @@ static void callFinaliser(sqlite3 *db, int offset){
** array. Return the error code for the first error that occurs, or
** SQLITE_OK if all xSync operations are successful.
**
-** Set *pzErrmsg to point to a buffer that should be released using
-** sqlite3DbFree() containing an error message, if one is available.
+** If an error message is available, leave it in p->zErrMsg.
*/
-SQLITE_PRIVATE int sqlite3VtabSync(sqlite3 *db, char **pzErrmsg){
+SQLITE_PRIVATE int sqlite3VtabSync(sqlite3 *db, Vdbe *p){
int i;
int rc = SQLITE_OK;
VTable **aVTrans = db->aVTrans;
@@ -104149,9 +104533,7 @@ SQLITE_PRIVATE int sqlite3VtabSync(sqlite3 *db, char **pzErrmsg){
sqlite3_vtab *pVtab = aVTrans[i]->pVtab;
if( pVtab && (x = pVtab->pModule->xSync)!=0 ){
rc = x(pVtab);
- sqlite3DbFree(db, *pzErrmsg);
- *pzErrmsg = sqlite3DbStrDup(db, pVtab->zErrMsg);
- sqlite3_free(pVtab->zErrMsg);
+ sqlite3VtabImportErrmsg(p, pVtab);
}
}
db->aVTrans = aVTrans;
@@ -104453,18 +104835,186 @@ SQLITE_API int sqlite3_vtab_config(sqlite3 *db, int op, ...){
#endif
#if defined(SQLITE_DEBUG) \
&& (defined(SQLITE_TEST) || defined(SQLITE_ENABLE_WHERETRACE))
-# define WHERETRACE(X) if(sqlite3WhereTrace) sqlite3DebugPrintf X
+# define WHERETRACE(K,X) if(sqlite3WhereTrace&(K)) sqlite3DebugPrintf X
+# define WHERETRACE_ENABLED 1
#else
-# define WHERETRACE(X)
+# define WHERETRACE(K,X)
#endif
-/* Forward reference
+/* Forward references
*/
typedef struct WhereClause WhereClause;
typedef struct WhereMaskSet WhereMaskSet;
typedef struct WhereOrInfo WhereOrInfo;
typedef struct WhereAndInfo WhereAndInfo;
-typedef struct WhereCost WhereCost;
+typedef struct WhereLevel WhereLevel;
+typedef struct WhereLoop WhereLoop;
+typedef struct WherePath WherePath;
+typedef struct WhereTerm WhereTerm;
+typedef struct WhereLoopBuilder WhereLoopBuilder;
+typedef struct WhereScan WhereScan;
+typedef struct WhereOrCost WhereOrCost;
+typedef struct WhereOrSet WhereOrSet;
+
+/*
+** Cost X is tracked as 10*log2(X) stored in a 16-bit integer. The
+** maximum cost for ordinary tables is 64*(2**63) which becomes 6900.
+** (Virtual tables can return a larger cost, but let's assume they do not.)
+** So all costs can be stored in a 16-bit unsigned integer without risk
+** of overflow.
+**
+** Costs are estimates, so no effort is made to compute 10*log2(X) exactly.
+** Instead, a close estimate is used. Any value of X<=1 is stored as 0.
+** X=2 is 10. X=3 is 16. X=1000 is 99. etc.
+**
+** The tool/wherecosttest.c source file implements a command-line program
+** that will convert WhereCosts to integers, convert integers to WhereCosts
+** and do addition and multiplication on WhereCost values. The wherecosttest
+** command-line program is a useful utility to have around when working with
+** this module.
+*/
+typedef unsigned short int WhereCost;
+
+/*
+** This object contains information needed to implement a single nested
+** loop in WHERE clause.
+**
+** Contrast this object with WhereLoop. This object describes the
+** implementation of the loop. WhereLoop describes the algorithm.
+** This object contains a pointer to the WhereLoop algorithm as one of
+** its elements.
+**
+** The WhereInfo object contains a single instance of this object for
+** each term in the FROM clause (which is to say, for each of the
+** nested loops as implemented). The order of WhereLevel objects determines
+** the loop nested order, with WhereInfo.a[0] being the outer loop and
+** WhereInfo.a[WhereInfo.nLevel-1] being the inner loop.
+*/
+struct WhereLevel {
+ int iLeftJoin; /* Memory cell used to implement LEFT OUTER JOIN */
+ int iTabCur; /* The VDBE cursor used to access the table */
+ int iIdxCur; /* The VDBE cursor used to access pIdx */
+ int addrBrk; /* Jump here to break out of the loop */
+ int addrNxt; /* Jump here to start the next IN combination */
+ int addrCont; /* Jump here to continue with the next loop cycle */
+ int addrFirst; /* First instruction of interior of the loop */
+ int addrBody; /* Beginning of the body of this loop */
+ u8 iFrom; /* Which entry in the FROM clause */
+ u8 op, p5; /* Opcode and P5 of the opcode that ends the loop */
+ int p1, p2; /* Operands of the opcode used to ends the loop */
+ union { /* Information that depends on pWLoop->wsFlags */
+ struct {
+ int nIn; /* Number of entries in aInLoop[] */
+ struct InLoop {
+ int iCur; /* The VDBE cursor used by this IN operator */
+ int addrInTop; /* Top of the IN loop */
+ u8 eEndLoopOp; /* IN Loop terminator. OP_Next or OP_Prev */
+ } *aInLoop; /* Information about each nested IN operator */
+ } in; /* Used when pWLoop->wsFlags&WHERE_IN_ABLE */
+ Index *pCovidx; /* Possible covering index for WHERE_MULTI_OR */
+ } u;
+ struct WhereLoop *pWLoop; /* The selected WhereLoop object */
+};
+
+/*
+** Each instance of this object represents an algorithm for evaluating one
+** term of a join. Every term of the FROM clause will have at least
+** one corresponding WhereLoop object (unless INDEXED BY constraints
+** prevent a query solution - which is an error) and many terms of the
+** FROM clause will have multiple WhereLoop objects, each describing a
+** potential way of implementing that FROM-clause term, together with
+** dependencies and cost estimates for using the chosen algorithm.
+**
+** Query planning consists of building up a collection of these WhereLoop
+** objects, then computing a particular sequence of WhereLoop objects, with
+** one WhereLoop object per FROM clause term, that satisfy all dependencies
+** and that minimize the overall cost.
+*/
+struct WhereLoop {
+ Bitmask prereq; /* Bitmask of other loops that must run first */
+ Bitmask maskSelf; /* Bitmask identifying table iTab */
+#ifdef SQLITE_DEBUG
+ char cId; /* Symbolic ID of this loop for debugging use */
+#endif
+ u8 iTab; /* Position in FROM clause of table for this loop */
+ u8 iSortIdx; /* Sorting index number. 0==None */
+ WhereCost rSetup; /* One-time setup cost (ex: create transient index) */
+ WhereCost rRun; /* Cost of running each loop */
+ WhereCost nOut; /* Estimated number of output rows */
+ union {
+ struct { /* Information for internal btree tables */
+ int nEq; /* Number of equality constraints */
+ Index *pIndex; /* Index used, or NULL */
+ } btree;
+ struct { /* Information for virtual tables */
+ int idxNum; /* Index number */
+ u8 needFree; /* True if sqlite3_free(idxStr) is needed */
+ u8 isOrdered; /* True if satisfies ORDER BY */
+ u16 omitMask; /* Terms that may be omitted */
+ char *idxStr; /* Index identifier string */
+ } vtab;
+ } u;
+ u32 wsFlags; /* WHERE_* flags describing the plan */
+ u16 nLTerm; /* Number of entries in aLTerm[] */
+ /**** whereLoopXfer() copies fields above ***********************/
+# define WHERE_LOOP_XFER_SZ offsetof(WhereLoop,nLSlot)
+ u16 nLSlot; /* Number of slots allocated for aLTerm[] */
+ WhereTerm **aLTerm; /* WhereTerms used */
+ WhereLoop *pNextLoop; /* Next WhereLoop object in the WhereClause */
+ WhereTerm *aLTermSpace[4]; /* Initial aLTerm[] space */
+};
+
+/* This object holds the prerequisites and the cost of running a
+** subquery on one operand of an OR operator in the WHERE clause.
+** See WhereOrSet for additional information
+*/
+struct WhereOrCost {
+ Bitmask prereq; /* Prerequisites */
+ WhereCost rRun; /* Cost of running this subquery */
+ WhereCost nOut; /* Number of outputs for this subquery */
+};
+
+/* The WhereOrSet object holds a set of possible WhereOrCosts that
+** correspond to the subquery(s) of OR-clause processing. Only the
+** best N_OR_COST elements are retained.
+*/
+#define N_OR_COST 3
+struct WhereOrSet {
+ u16 n; /* Number of valid a[] entries */
+ WhereOrCost a[N_OR_COST]; /* Set of best costs */
+};
+
+
+/* Forward declaration of methods */
+static int whereLoopResize(sqlite3*, WhereLoop*, int);
+
+/*
+** Each instance of this object holds a sequence of WhereLoop objects
+** that implement some or all of a query plan.
+**
+** Think of each WhereLoop object as a node in a graph with arcs
+** showing dependences and costs for travelling between nodes. (That is
+** not a completely accurate description because WhereLoop costs are a
+** vector, not a scalar, and because dependences are many-to-one, not
+** one-to-one as are graph nodes. But it is a useful visualization aid.)
+** Then a WherePath object is a path through the graph that visits some
+** or all of the WhereLoop objects once.
+**
+** The "solver" works by creating the N best WherePath objects of length
+** 1. Then using those as a basis to compute the N best WherePath objects
+** of length 2. And so forth until the length of WherePaths equals the
+** number of nodes in the FROM clause. The best (lowest cost) WherePath
+** at the end is the choosen query plan.
+*/
+struct WherePath {
+ Bitmask maskLoop; /* Bitmask of all WhereLoop objects in this path */
+ Bitmask revLoop; /* aLoop[]s that should be reversed for ORDER BY */
+ WhereCost nRow; /* Estimated number of rows generated by this path */
+ WhereCost rCost; /* Total cost of this path */
+ u8 isOrdered; /* True if this path satisfies ORDER BY */
+ u8 isOrderedValid; /* True if the isOrdered field is valid */
+ WhereLoop **aLoop; /* Array of WhereLoop objects implementing this path */
+};
/*
** The query generator uses an array of instances of this structure to
@@ -104492,9 +105042,9 @@ typedef struct WhereCost WhereCost;
**
** (t1.X <op> <expr>) OR (t1.Y <op> <expr>) OR ....
**
-** In this second case, wtFlag as the TERM_ORINFO set and eOperator==WO_OR
+** In this second case, wtFlag has the TERM_ORINFO bit set and eOperator==WO_OR
** and the WhereTerm.u.pOrInfo field points to auxiliary information that
-** is collected about the
+** is collected about the OR clause.
**
** If a term in the WHERE clause does not match either of the two previous
** categories, then eOperator==0. The WhereTerm.pExpr field is still set
@@ -104517,7 +105067,6 @@ typedef struct WhereCost WhereCost;
** in prereqRight and prereqAll. The default is 64 bits, hence SQLite
** is only able to process joins with 64 or fewer tables.
*/
-typedef struct WhereTerm WhereTerm;
struct WhereTerm {
Expr *pExpr; /* Pointer to the subexpression that is this term */
int iParent; /* Disable pWC->a[iParent] when this term disabled */
@@ -104552,6 +105101,22 @@ struct WhereTerm {
#endif
/*
+** An instance of the WhereScan object is used as an iterator for locating
+** terms in the WHERE clause that are useful to the query planner.
+*/
+struct WhereScan {
+ WhereClause *pOrigWC; /* Original, innermost WhereClause */
+ WhereClause *pWC; /* WhereClause currently being scanned */
+ char *zCollName; /* Required collating sequence, if not NULL */
+ char idxaff; /* Must match this affinity, if zCollName!=NULL */
+ unsigned char nEquiv; /* Number of entries in aEquiv[] */
+ unsigned char iEquiv; /* Next unused slot in aEquiv[] */
+ u32 opMask; /* Acceptable operators */
+ int k; /* Resume scanning at this->pWC->a[this->k] */
+ int aEquiv[22]; /* Cursor,Column pairs for equivalence classes */
+};
+
+/*
** An instance of the following structure holds all information about a
** WHERE clause. Mostly this is a container for one or more WhereTerms.
**
@@ -104564,11 +105129,9 @@ struct WhereTerm {
** subclauses points to the WhereClause object for the whole clause.
*/
struct WhereClause {
- Parse *pParse; /* The parser context */
- WhereMaskSet *pMaskSet; /* Mapping of table cursor numbers to bitmasks */
+ WhereInfo *pWInfo; /* WHERE clause processing context */
WhereClause *pOuter; /* Outer conjunction */
u8 op; /* Split operator. TK_AND or TK_OR */
- u16 wctrlFlags; /* Might include WHERE_AND_ONLY */
int nTerm; /* Number of terms */
int nSlot; /* Number of entries in a[] */
WhereTerm *a; /* Each a[] describes a term of the WHERE cluase */
@@ -104628,19 +105191,55 @@ struct WhereMaskSet {
};
/*
-** A WhereCost object records a lookup strategy and the estimated
-** cost of pursuing that strategy.
+** This object is a convenience wrapper holding all information needed
+** to construct WhereLoop objects for a particular query.
*/
-struct WhereCost {
- WherePlan plan; /* The lookup strategy */
- double rCost; /* Overall cost of pursuing this search strategy */
- Bitmask used; /* Bitmask of cursors used by this plan */
+struct WhereLoopBuilder {
+ WhereInfo *pWInfo; /* Information about this WHERE */
+ WhereClause *pWC; /* WHERE clause terms */
+ ExprList *pOrderBy; /* ORDER BY clause */
+ WhereLoop *pNew; /* Template WhereLoop */
+ WhereOrSet *pOrSet; /* Record best loops here, if not NULL */
+};
+
+/*
+** The WHERE clause processing routine has two halves. The
+** first part does the start of the WHERE loop and the second
+** half does the tail of the WHERE loop. An instance of
+** this structure is returned by the first half and passed
+** into the second half to give some continuity.
+**
+** An instance of this object holds the complete state of the query
+** planner.
+*/
+struct WhereInfo {
+ Parse *pParse; /* Parsing and code generating context */
+ SrcList *pTabList; /* List of tables in the join */
+ ExprList *pOrderBy; /* The ORDER BY clause or NULL */
+ ExprList *pResultSet; /* Result set. DISTINCT operates on these */
+ WhereLoop *pLoops; /* List of all WhereLoop objects */
+ Bitmask revMask; /* Mask of ORDER BY terms that need reversing */
+ WhereCost nRowOut; /* Estimated number of output rows */
+ u16 wctrlFlags; /* Flags originally passed to sqlite3WhereBegin() */
+ u8 bOBSat; /* ORDER BY satisfied by indices */
+ u8 okOnePass; /* Ok to use one-pass algorithm for UPDATE/DELETE */
+ u8 untestedTerms; /* Not all WHERE terms resolved by outer loop */
+ u8 eDistinct; /* One of the WHERE_DISTINCT_* values below */
+ u8 nLevel; /* Number of nested loop */
+ int iTop; /* The very beginning of the WHERE loop */
+ int iContinue; /* Jump here to continue with next record */
+ int iBreak; /* Jump here to break out of the loop */
+ int savedNQueryLoop; /* pParse->nQueryLoop outside the WHERE loop */
+ WhereMaskSet sMaskSet; /* Map cursor numbers to bitmasks */
+ WhereClause sWC; /* Decomposition of the WHERE clause */
+ WhereLevel a[1]; /* Information about each nest loop in WHERE */
};
/*
-** Bitmasks for the operators that indices are able to exploit. An
+** Bitmasks for the operators on WhereTerm objects. These are all
+** operators that are of interest to the query planner. An
** OR-ed combination of these values can be used when searching for
-** terms in the where clause.
+** particular WhereTerms within a WhereClause.
*/
#define WO_IN 0x001
#define WO_EQ 0x002
@@ -104659,74 +105258,136 @@ struct WhereCost {
#define WO_SINGLE 0x0ff /* Mask of all non-compound WO_* values */
/*
-** Value for wsFlags returned by bestIndex() and stored in
-** WhereLevel.wsFlags. These flags determine which search
-** strategies are appropriate.
-**
-** The least significant 12 bits is reserved as a mask for WO_ values above.
-** The WhereLevel.wsFlags field is usually set to WO_IN|WO_EQ|WO_ISNULL.
-** But if the table is the right table of a left join, WhereLevel.wsFlags
-** is set to WO_IN|WO_EQ. The WhereLevel.wsFlags field can then be used as
-** the "op" parameter to findTerm when we are resolving equality constraints.
-** ISNULL constraints will then not be used on the right table of a left
-** join. Tickets #2177 and #2189.
-*/
-#define WHERE_ROWID_EQ 0x00001000 /* rowid=EXPR or rowid IN (...) */
-#define WHERE_ROWID_RANGE 0x00002000 /* rowid<EXPR and/or rowid>EXPR */
-#define WHERE_COLUMN_EQ 0x00010000 /* x=EXPR or x IN (...) or x IS NULL */
-#define WHERE_COLUMN_RANGE 0x00020000 /* x<EXPR and/or x>EXPR */
-#define WHERE_COLUMN_IN 0x00040000 /* x IN (...) */
-#define WHERE_COLUMN_NULL 0x00080000 /* x IS NULL */
-#define WHERE_INDEXED 0x000f0000 /* Anything that uses an index */
-#define WHERE_NOT_FULLSCAN 0x100f3000 /* Does not do a full table scan */
-#define WHERE_IN_ABLE 0x080f1000 /* Able to support an IN operator */
-#define WHERE_TOP_LIMIT 0x00100000 /* x<EXPR or x<=EXPR constraint */
-#define WHERE_BTM_LIMIT 0x00200000 /* x>EXPR or x>=EXPR constraint */
-#define WHERE_BOTH_LIMIT 0x00300000 /* Both x>EXPR and x<EXPR */
-#define WHERE_IDX_ONLY 0x00400000 /* Use index only - omit table */
-#define WHERE_ORDERED 0x00800000 /* Output will appear in correct order */
-#define WHERE_REVERSE 0x01000000 /* Scan in reverse order */
-#define WHERE_UNIQUE 0x02000000 /* Selects no more than one row */
-#define WHERE_ALL_UNIQUE 0x04000000 /* This and all prior have one row */
-#define WHERE_OB_UNIQUE 0x00004000 /* Values in ORDER BY columns are
- ** different for every output row */
-#define WHERE_VIRTUALTABLE 0x08000000 /* Use virtual-table processing */
-#define WHERE_MULTI_OR 0x10000000 /* OR using multiple indices */
-#define WHERE_TEMP_INDEX 0x20000000 /* Uses an ephemeral index */
-#define WHERE_DISTINCT 0x40000000 /* Correct order for DISTINCT */
-#define WHERE_COVER_SCAN 0x80000000 /* Full scan of a covering index */
-
-/*
-** This module contains many separate subroutines that work together to
-** find the best indices to use for accessing a particular table in a query.
-** An instance of the following structure holds context information about the
-** index search so that it can be more easily passed between the various
-** routines.
+** These are definitions of bits in the WhereLoop.wsFlags field.
+** The particular combination of bits in each WhereLoop help to
+** determine the algorithm that WhereLoop represents.
+*/
+#define WHERE_COLUMN_EQ 0x00000001 /* x=EXPR */
+#define WHERE_COLUMN_RANGE 0x00000002 /* x<EXPR and/or x>EXPR */
+#define WHERE_COLUMN_IN 0x00000004 /* x IN (...) */
+#define WHERE_COLUMN_NULL 0x00000008 /* x IS NULL */
+#define WHERE_CONSTRAINT 0x0000000f /* Any of the WHERE_COLUMN_xxx values */
+#define WHERE_TOP_LIMIT 0x00000010 /* x<EXPR or x<=EXPR constraint */
+#define WHERE_BTM_LIMIT 0x00000020 /* x>EXPR or x>=EXPR constraint */
+#define WHERE_BOTH_LIMIT 0x00000030 /* Both x>EXPR and x<EXPR */
+#define WHERE_IDX_ONLY 0x00000040 /* Use index only - omit table */
+#define WHERE_IPK 0x00000100 /* x is the INTEGER PRIMARY KEY */
+#define WHERE_INDEXED 0x00000200 /* WhereLoop.u.btree.pIndex is valid */
+#define WHERE_VIRTUALTABLE 0x00000400 /* WhereLoop.u.vtab is valid */
+#define WHERE_IN_ABLE 0x00000800 /* Able to support an IN operator */
+#define WHERE_ONEROW 0x00001000 /* Selects no more than one row */
+#define WHERE_MULTI_OR 0x00002000 /* OR using multiple indices */
+#define WHERE_AUTO_INDEX 0x00004000 /* Uses an ephemeral index */
+
+
+/* Convert a WhereCost value (10 times log2(X)) into its integer value X.
+** A rough approximation is used. The value returned is not exact.
+*/
+static u64 whereCostToInt(WhereCost x){
+ u64 n;
+ if( x<10 ) return 1;
+ n = x%10;
+ x /= 10;
+ if( n>=5 ) n -= 2;
+ else if( n>=1 ) n -= 1;
+ if( x>=3 ) return (n+8)<<(x-3);
+ return (n+8)>>(3-x);
+}
+
+/*
+** Return the estimated number of output rows from a WHERE clause
*/
-typedef struct WhereBestIdx WhereBestIdx;
-struct WhereBestIdx {
- Parse *pParse; /* Parser context */
- WhereClause *pWC; /* The WHERE clause */
- struct SrcList_item *pSrc; /* The FROM clause term to search */
- Bitmask notReady; /* Mask of cursors not available */
- Bitmask notValid; /* Cursors not available for any purpose */
- ExprList *pOrderBy; /* The ORDER BY clause */
- ExprList *pDistinct; /* The select-list if query is DISTINCT */
- sqlite3_index_info **ppIdxInfo; /* Index information passed to xBestIndex */
- int i, n; /* Which loop is being coded; # of loops */
- WhereLevel *aLevel; /* Info about outer loops */
- WhereCost cost; /* Lowest cost query plan */
-};
+SQLITE_PRIVATE u64 sqlite3WhereOutputRowCount(WhereInfo *pWInfo){
+ return whereCostToInt(pWInfo->nRowOut);
+}
/*
-** Return TRUE if the probe cost is less than the baseline cost
+** Return one of the WHERE_DISTINCT_xxxxx values to indicate how this
+** WHERE clause returns outputs for DISTINCT processing.
*/
-static int compareCost(const WhereCost *pProbe, const WhereCost *pBaseline){
- if( pProbe->rCost<pBaseline->rCost ) return 1;
- if( pProbe->rCost>pBaseline->rCost ) return 0;
- if( pProbe->plan.nOBSat>pBaseline->plan.nOBSat ) return 1;
- if( pProbe->plan.nRow<pBaseline->plan.nRow ) return 1;
- return 0;
+SQLITE_PRIVATE int sqlite3WhereIsDistinct(WhereInfo *pWInfo){
+ return pWInfo->eDistinct;
+}
+
+/*
+** Return TRUE if the WHERE clause returns rows in ORDER BY order.
+** Return FALSE if the output needs to be sorted.
+*/
+SQLITE_PRIVATE int sqlite3WhereIsOrdered(WhereInfo *pWInfo){
+ return pWInfo->bOBSat!=0;
+}
+
+/*
+** Return the VDBE address or label to jump to in order to continue
+** immediately with the next row of a WHERE clause.
+*/
+SQLITE_PRIVATE int sqlite3WhereContinueLabel(WhereInfo *pWInfo){
+ return pWInfo->iContinue;
+}
+
+/*
+** Return the VDBE address or label to jump to in order to break
+** out of a WHERE loop.
+*/
+SQLITE_PRIVATE int sqlite3WhereBreakLabel(WhereInfo *pWInfo){
+ return pWInfo->iBreak;
+}
+
+/*
+** Return TRUE if an UPDATE or DELETE statement can operate directly on
+** the rowids returned by a WHERE clause. Return FALSE if doing an
+** UPDATE or DELETE might change subsequent WHERE clause results.
+*/
+SQLITE_PRIVATE int sqlite3WhereOkOnePass(WhereInfo *pWInfo){
+ return pWInfo->okOnePass;
+}
+
+/*
+** Move the content of pSrc into pDest
+*/
+static void whereOrMove(WhereOrSet *pDest, WhereOrSet *pSrc){
+ pDest->n = pSrc->n;
+ memcpy(pDest->a, pSrc->a, pDest->n*sizeof(pDest->a[0]));
+}
+
+/*
+** Try to insert a new prerequisite/cost entry into the WhereOrSet pSet.
+**
+** The new entry might overwrite an existing entry, or it might be
+** appended, or it might be discarded. Do whatever is the right thing
+** so that pSet keeps the N_OR_COST best entries seen so far.
+*/
+static int whereOrInsert(
+ WhereOrSet *pSet, /* The WhereOrSet to be updated */
+ Bitmask prereq, /* Prerequisites of the new entry */
+ WhereCost rRun, /* Run-cost of the new entry */
+ WhereCost nOut /* Number of outputs for the new entry */
+){
+ u16 i;
+ WhereOrCost *p;
+ for(i=pSet->n, p=pSet->a; i>0; i--, p++){
+ if( rRun<=p->rRun && (prereq & p->prereq)==prereq ){
+ goto whereOrInsert_done;
+ }
+ if( p->rRun<=rRun && (p->prereq & prereq)==p->prereq ){
+ return 0;
+ }
+ }
+ if( pSet->n<N_OR_COST ){
+ p = &pSet->a[pSet->n++];
+ p->nOut = nOut;
+ }else{
+ p = pSet->a;
+ for(i=1; i<pSet->n; i++){
+ if( p->rRun>pSet->a[i].rRun ) p = pSet->a + i;
+ }
+ if( p->rRun<=rRun ) return 0;
+ }
+whereOrInsert_done:
+ p->prereq = prereq;
+ p->rRun = rRun;
+ if( p->nOut>nOut ) p->nOut = nOut;
+ return 1;
}
/*
@@ -104734,17 +105395,13 @@ static int compareCost(const WhereCost *pProbe, const WhereCost *pBaseline){
*/
static void whereClauseInit(
WhereClause *pWC, /* The WhereClause to be initialized */
- Parse *pParse, /* The parsing context */
- WhereMaskSet *pMaskSet, /* Mapping from table cursor numbers to bitmasks */
- u16 wctrlFlags /* Might include WHERE_AND_ONLY */
+ WhereInfo *pWInfo /* The WHERE processing context */
){
- pWC->pParse = pParse;
- pWC->pMaskSet = pMaskSet;
+ pWC->pWInfo = pWInfo;
pWC->pOuter = 0;
pWC->nTerm = 0;
pWC->nSlot = ArraySize(pWC->aStatic);
pWC->a = pWC->aStatic;
- pWC->wctrlFlags = wctrlFlags;
}
/* Forward reference */
@@ -104773,7 +105430,7 @@ static void whereAndInfoDelete(sqlite3 *db, WhereAndInfo *p){
static void whereClauseClear(WhereClause *pWC){
int i;
WhereTerm *a;
- sqlite3 *db = pWC->pParse->db;
+ sqlite3 *db = pWC->pWInfo->pParse->db;
for(i=pWC->nTerm-1, a=pWC->a; i>=0; i--, a++){
if( a->wtFlags & TERM_DYNAMIC ){
sqlite3ExprDelete(db, a->pExpr);
@@ -104811,10 +105468,10 @@ static void whereClauseClear(WhereClause *pWC){
static int whereClauseInsert(WhereClause *pWC, Expr *p, u8 wtFlags){
WhereTerm *pTerm;
int idx;
- testcase( wtFlags & TERM_VIRTUAL ); /* EV: R-00211-15100 */
+ testcase( wtFlags & TERM_VIRTUAL );
if( pWC->nTerm>=pWC->nSlot ){
WhereTerm *pOld = pWC->a;
- sqlite3 *db = pWC->pParse->db;
+ sqlite3 *db = pWC->pWInfo->pParse->db;
pWC->a = sqlite3DbMallocRaw(db, sizeof(pWC->a[0])*pWC->nSlot*2 );
if( pWC->a==0 ){
if( wtFlags & TERM_DYNAMIC ){
@@ -104854,8 +105511,8 @@ static int whereClauseInsert(WhereClause *pWC, Expr *p, u8 wtFlags){
** the WhereClause.a[] array. The slot[] array grows as needed to contain
** all terms of the WHERE clause.
*/
-static void whereSplit(WhereClause *pWC, Expr *pExpr, int op){
- pWC->op = (u8)op;
+static void whereSplit(WhereClause *pWC, Expr *pExpr, u8 op){
+ pWC->op = op;
if( pExpr==0 ) return;
if( pExpr->op!=op ){
whereClauseInsert(pWC, pExpr, 0);
@@ -104866,9 +105523,9 @@ static void whereSplit(WhereClause *pWC, Expr *pExpr, int op){
}
/*
-** Initialize an expression mask set (a WhereMaskSet object)
+** Initialize a WhereMaskSet object
*/
-#define initMaskSet(P) memset(P, 0, sizeof(*P))
+#define initMaskSet(P) (P)->n=0
/*
** Return the bitmask for the given cursor number. Return 0 if
@@ -104879,7 +105536,7 @@ static Bitmask getMask(WhereMaskSet *pMaskSet, int iCursor){
assert( pMaskSet->n<=(int)sizeof(Bitmask)*8 );
for(i=0; i<pMaskSet->n; i++){
if( pMaskSet->ix[i]==iCursor ){
- return ((Bitmask)1)<<i;
+ return MASKBIT(i);
}
}
return 0;
@@ -104899,18 +105556,9 @@ static void createMask(WhereMaskSet *pMaskSet, int iCursor){
}
/*
-** This routine walks (recursively) an expression tree and generates
+** These routines walk (recursively) an expression tree and generate
** a bitmask indicating which tables are used in that expression
** tree.
-**
-** In order for this routine to work, the calling function must have
-** previously invoked sqlite3ResolveExprNames() on the expression. See
-** the header comment on that routine for additional information.
-** The sqlite3ResolveExprNames() routines looks for column names and
-** sets their opcodes to TK_COLUMN and their Expr.iTable fields to
-** the VDBE cursor number of the table. This routine just has to
-** translate the cursor numbers into bitmask values and OR all
-** the bitmasks together.
*/
static Bitmask exprListTableUsage(WhereMaskSet*, ExprList*);
static Bitmask exprSelectTableUsage(WhereMaskSet*, Select*);
@@ -104964,14 +105612,7 @@ static Bitmask exprSelectTableUsage(WhereMaskSet *pMaskSet, Select *pS){
/*
** Return TRUE if the given operator is one of the operators that is
** allowed for an indexable WHERE clause term. The allowed operators are
-** "=", "<", ">", "<=", ">=", and "IN".
-**
-** IMPLEMENTATION-OF: R-59926-26393 To be usable by an index a term must be
-** of one of the following forms: column = expression column > expression
-** column >= expression column < expression column <= expression
-** expression = column expression > column expression >= column
-** expression < column expression <= column column IN
-** (expression-list) column IN (subquery) column IS NULL
+** "=", "<", ">", "<=", ">=", "IN", and "IS NULL"
*/
static int allowedOp(int op){
assert( TK_GT>TK_EQ && TK_GT<TK_GE );
@@ -104991,10 +105632,9 @@ static int allowedOp(int op){
** are converted into "Y op X".
**
** If left/right precedence rules come into play when determining the
-** collating
-** side of the comparison, it remains associated with the same side after
-** the commutation. So "Y collate NOCASE op X" becomes
-** "X op Y". This is because any collation sequence on
+** collating sequence, then COLLATE operators are adjusted to ensure
+** that the collating sequence does not change. For example:
+** "Y collate NOCASE op X" becomes "X op Y" because any collation sequence on
** the left hand side of a comparison overrides any collation sequence
** attached to the right. For the same reason the EP_Collate flag
** is not commuted.
@@ -105052,6 +105692,130 @@ static u16 operatorMask(int op){
}
/*
+** Advance to the next WhereTerm that matches according to the criteria
+** established when the pScan object was initialized by whereScanInit().
+** Return NULL if there are no more matching WhereTerms.
+*/
+static WhereTerm *whereScanNext(WhereScan *pScan){
+ int iCur; /* The cursor on the LHS of the term */
+ int iColumn; /* The column on the LHS of the term. -1 for IPK */
+ Expr *pX; /* An expression being tested */
+ WhereClause *pWC; /* Shorthand for pScan->pWC */
+ WhereTerm *pTerm; /* The term being tested */
+ int k = pScan->k; /* Where to start scanning */
+
+ while( pScan->iEquiv<=pScan->nEquiv ){
+ iCur = pScan->aEquiv[pScan->iEquiv-2];
+ iColumn = pScan->aEquiv[pScan->iEquiv-1];
+ while( (pWC = pScan->pWC)!=0 ){
+ for(pTerm=pWC->a+k; k<pWC->nTerm; k++, pTerm++){
+ if( pTerm->leftCursor==iCur && pTerm->u.leftColumn==iColumn ){
+ if( (pTerm->eOperator & WO_EQUIV)!=0
+ && pScan->nEquiv<ArraySize(pScan->aEquiv)
+ ){
+ int j;
+ pX = sqlite3ExprSkipCollate(pTerm->pExpr->pRight);
+ assert( pX->op==TK_COLUMN );
+ for(j=0; j<pScan->nEquiv; j+=2){
+ if( pScan->aEquiv[j]==pX->iTable
+ && pScan->aEquiv[j+1]==pX->iColumn ){
+ break;
+ }
+ }
+ if( j==pScan->nEquiv ){
+ pScan->aEquiv[j] = pX->iTable;
+ pScan->aEquiv[j+1] = pX->iColumn;
+ pScan->nEquiv += 2;
+ }
+ }
+ if( (pTerm->eOperator & pScan->opMask)!=0 ){
+ /* Verify the affinity and collating sequence match */
+ if( pScan->zCollName && (pTerm->eOperator & WO_ISNULL)==0 ){
+ CollSeq *pColl;
+ Parse *pParse = pWC->pWInfo->pParse;
+ pX = pTerm->pExpr;
+ if( !sqlite3IndexAffinityOk(pX, pScan->idxaff) ){
+ continue;
+ }
+ assert(pX->pLeft);
+ pColl = sqlite3BinaryCompareCollSeq(pParse,
+ pX->pLeft, pX->pRight);
+ if( pColl==0 ) pColl = pParse->db->pDfltColl;
+ if( sqlite3StrICmp(pColl->zName, pScan->zCollName) ){
+ continue;
+ }
+ }
+ if( (pTerm->eOperator & WO_EQ)!=0
+ && (pX = pTerm->pExpr->pRight)->op==TK_COLUMN
+ && pX->iTable==pScan->aEquiv[0]
+ && pX->iColumn==pScan->aEquiv[1]
+ ){
+ continue;
+ }
+ pScan->k = k+1;
+ return pTerm;
+ }
+ }
+ }
+ pScan->pWC = pScan->pWC->pOuter;
+ k = 0;
+ }
+ pScan->pWC = pScan->pOrigWC;
+ k = 0;
+ pScan->iEquiv += 2;
+ }
+ return 0;
+}
+
+/*
+** Initialize a WHERE clause scanner object. Return a pointer to the
+** first match. Return NULL if there are no matches.
+**
+** The scanner will be searching the WHERE clause pWC. It will look
+** for terms of the form "X <op> <expr>" where X is column iColumn of table
+** iCur. The <op> must be one of the operators described by opMask.
+**
+** If the search is for X and the WHERE clause contains terms of the
+** form X=Y then this routine might also return terms of the form
+** "Y <op> <expr>". The number of levels of transitivity is limited,
+** but is enough to handle most commonly occurring SQL statements.
+**
+** If X is not the INTEGER PRIMARY KEY then X must be compatible with
+** index pIdx.
+*/
+static WhereTerm *whereScanInit(
+ WhereScan *pScan, /* The WhereScan object being initialized */
+ WhereClause *pWC, /* The WHERE clause to be scanned */
+ int iCur, /* Cursor to scan for */
+ int iColumn, /* Column to scan for */
+ u32 opMask, /* Operator(s) to scan for */
+ Index *pIdx /* Must be compatible with this index */
+){
+ int j;
+
+ /* memset(pScan, 0, sizeof(*pScan)); */
+ pScan->pOrigWC = pWC;
+ pScan->pWC = pWC;
+ if( pIdx && iColumn>=0 ){
+ pScan->idxaff = pIdx->pTable->aCol[iColumn].affinity;
+ for(j=0; pIdx->aiColumn[j]!=iColumn; j++){
+ if( NEVER(j>=pIdx->nColumn) ) return 0;
+ }
+ pScan->zCollName = pIdx->azColl[j];
+ }else{
+ pScan->idxaff = 0;
+ pScan->zCollName = 0;
+ }
+ pScan->opMask = opMask;
+ pScan->k = 0;
+ pScan->aEquiv[0] = iCur;
+ pScan->aEquiv[1] = iColumn;
+ pScan->nEquiv = 2;
+ pScan->iEquiv = 2;
+ return whereScanNext(pScan);
+}
+
+/*
** Search for a term in the WHERE clause that is of the form "X <op> <expr>"
** where X is a reference to the iColumn of table iCur and <op> is one of
** the WO_xx operator codes specified by the op parameter.
@@ -105082,84 +105846,20 @@ static WhereTerm *findTerm(
u32 op, /* Mask of WO_xx values describing operator */
Index *pIdx /* Must be compatible with this index, if not NULL */
){
- WhereTerm *pTerm; /* Term being examined as possible result */
- WhereTerm *pResult = 0; /* The answer to return */
- WhereClause *pWCOrig = pWC; /* Original pWC value */
- int j, k; /* Loop counters */
- Expr *pX; /* Pointer to an expression */
- Parse *pParse; /* Parsing context */
- int iOrigCol = iColumn; /* Original value of iColumn */
- int nEquiv = 2; /* Number of entires in aEquiv[] */
- int iEquiv = 2; /* Number of entries of aEquiv[] processed so far */
- int aEquiv[22]; /* iCur,iColumn and up to 10 other equivalents */
-
- assert( iCur>=0 );
- aEquiv[0] = iCur;
- aEquiv[1] = iColumn;
- for(;;){
- for(pWC=pWCOrig; pWC; pWC=pWC->pOuter){
- for(pTerm=pWC->a, k=pWC->nTerm; k; k--, pTerm++){
- if( pTerm->leftCursor==iCur
- && pTerm->u.leftColumn==iColumn
- ){
- if( (pTerm->prereqRight & notReady)==0
- && (pTerm->eOperator & op & WO_ALL)!=0
- ){
- if( iOrigCol>=0 && pIdx && (pTerm->eOperator & WO_ISNULL)==0 ){
- CollSeq *pColl;
- char idxaff;
-
- pX = pTerm->pExpr;
- pParse = pWC->pParse;
- idxaff = pIdx->pTable->aCol[iOrigCol].affinity;
- if( !sqlite3IndexAffinityOk(pX, idxaff) ){
- continue;
- }
-
- /* Figure out the collation sequence required from an index for
- ** it to be useful for optimising expression pX. Store this
- ** value in variable pColl.
- */
- assert(pX->pLeft);
- pColl = sqlite3BinaryCompareCollSeq(pParse,pX->pLeft,pX->pRight);
- if( pColl==0 ) pColl = pParse->db->pDfltColl;
-
- for(j=0; pIdx->aiColumn[j]!=iOrigCol; j++){
- if( NEVER(j>=pIdx->nColumn) ) return 0;
- }
- if( sqlite3StrICmp(pColl->zName, pIdx->azColl[j]) ){
- continue;
- }
- }
- if( pTerm->prereqRight==0 && (pTerm->eOperator&WO_EQ)!=0 ){
- pResult = pTerm;
- goto findTerm_success;
- }else if( pResult==0 ){
- pResult = pTerm;
- }
- }
- if( (pTerm->eOperator & WO_EQUIV)!=0
- && nEquiv<ArraySize(aEquiv)
- ){
- pX = sqlite3ExprSkipCollate(pTerm->pExpr->pRight);
- assert( pX->op==TK_COLUMN );
- for(j=0; j<nEquiv; j+=2){
- if( aEquiv[j]==pX->iTable && aEquiv[j+1]==pX->iColumn ) break;
- }
- if( j==nEquiv ){
- aEquiv[j] = pX->iTable;
- aEquiv[j+1] = pX->iColumn;
- nEquiv += 2;
- }
- }
- }
+ WhereTerm *pResult = 0;
+ WhereTerm *p;
+ WhereScan scan;
+
+ p = whereScanInit(&scan, pWC, iCur, iColumn, op, pIdx);
+ while( p ){
+ if( (p->prereqRight & notReady)==0 ){
+ if( p->prereqRight==0 && (p->eOperator&WO_EQ)!=0 ){
+ return p;
}
+ if( pResult==0 ) pResult = p;
}
- if( iEquiv>=nEquiv ) break;
- iCur = aEquiv[iEquiv++];
- iColumn = aEquiv[iEquiv++];
+ p = whereScanNext(&scan);
}
-findTerm_success:
return pResult;
}
@@ -105168,8 +105868,6 @@ static void exprAnalyze(SrcList*, WhereClause*, int);
/*
** Call exprAnalyze on all terms in a WHERE clause.
-**
-**
*/
static void exprAnalyzeAll(
SrcList *pTabList, /* the FROM clause */
@@ -105233,7 +105931,7 @@ static int isLikeOrGlob(
if( op==TK_VARIABLE ){
Vdbe *pReprepare = pParse->pReprepare;
int iCol = pRight->iColumn;
- pVal = sqlite3VdbeGetValue(pReprepare, iCol, SQLITE_AFF_NONE);
+ pVal = sqlite3VdbeGetBoundValue(pReprepare, iCol, SQLITE_AFF_NONE);
if( pVal && sqlite3_value_type(pVal)==SQLITE_TEXT ){
z = (char *)sqlite3_value_text(pVal);
}
@@ -105315,8 +106013,10 @@ static int isMatchOfColumn(
** a join, then transfer the appropriate markings over to derived.
*/
static void transferJoinMarkings(Expr *pDerived, Expr *pBase){
- pDerived->flags |= pBase->flags & EP_FromJoin;
- pDerived->iRightJoinTable = pBase->iRightJoinTable;
+ if( pDerived ){
+ pDerived->flags |= pBase->flags & EP_FromJoin;
+ pDerived->iRightJoinTable = pBase->iRightJoinTable;
+ }
}
#if !defined(SQLITE_OMIT_OR_OPTIMIZATION) && !defined(SQLITE_OMIT_SUBQUERY)
@@ -105375,10 +106075,10 @@ static void transferJoinMarkings(Expr *pDerived, Expr *pBase){
** From another point of view, "indexable" means that the subterm could
** potentially be used with an index if an appropriate index exists.
** This analysis does not consider whether or not the index exists; that
-** is something the bestIndex() routine will determine. This analysis
-** only looks at whether subterms appropriate for indexing exist.
+** is decided elsewhere. This analysis only looks at whether subterms
+** appropriate for indexing exist.
**
-** All examples A through E above all satisfy case 2. But if a term
+** All examples A through E above satisfy case 2. But if a term
** also statisfies case 1 (such as B) we know that the optimizer will
** always prefer case 1, so in that case we pretend that case 2 is not
** satisfied.
@@ -105401,11 +106101,11 @@ static void exprAnalyzeOrTerm(
WhereClause *pWC, /* the complete WHERE clause */
int idxTerm /* Index of the OR-term to be analyzed */
){
- Parse *pParse = pWC->pParse; /* Parser context */
+ WhereInfo *pWInfo = pWC->pWInfo; /* WHERE clause processing context */
+ Parse *pParse = pWInfo->pParse; /* Parser context */
sqlite3 *db = pParse->db; /* Database connection */
WhereTerm *pTerm = &pWC->a[idxTerm]; /* The term to be analyzed */
Expr *pExpr = pTerm->pExpr; /* The expression of the term */
- WhereMaskSet *pMaskSet = pWC->pMaskSet; /* Table use masks */
int i; /* Loop counters */
WhereClause *pOrWc; /* Breakup of pTerm into subterms */
WhereTerm *pOrTerm; /* A Sub-term within the pOrWc */
@@ -105424,7 +106124,7 @@ static void exprAnalyzeOrTerm(
if( pOrInfo==0 ) return;
pTerm->wtFlags |= TERM_ORINFO;
pOrWc = &pOrInfo->wc;
- whereClauseInit(pOrWc, pWC->pParse, pMaskSet, pWC->wctrlFlags);
+ whereClauseInit(pOrWc, pWInfo);
whereSplit(pOrWc, pExpr, TK_OR);
exprAnalyzeAll(pSrc, pOrWc);
if( db->mallocFailed ) return;
@@ -105450,7 +106150,7 @@ static void exprAnalyzeOrTerm(
pOrTerm->wtFlags |= TERM_ANDINFO;
pOrTerm->eOperator = WO_AND;
pAndWC = &pAndInfo->wc;
- whereClauseInit(pAndWC, pWC->pParse, pMaskSet, pWC->wctrlFlags);
+ whereClauseInit(pAndWC, pWC->pWInfo);
whereSplit(pAndWC, pOrTerm->pExpr, TK_AND);
exprAnalyzeAll(pSrc, pAndWC);
pAndWC->pOuter = pWC;
@@ -105459,7 +106159,7 @@ static void exprAnalyzeOrTerm(
for(j=0, pAndTerm=pAndWC->a; j<pAndWC->nTerm; j++, pAndTerm++){
assert( pAndTerm->pExpr );
if( allowedOp(pAndTerm->pExpr->op) ){
- b |= getMask(pMaskSet, pAndTerm->leftCursor);
+ b |= getMask(&pWInfo->sMaskSet, pAndTerm->leftCursor);
}
}
}
@@ -105470,10 +106170,10 @@ static void exprAnalyzeOrTerm(
** corresponding TERM_VIRTUAL term */
}else{
Bitmask b;
- b = getMask(pMaskSet, pOrTerm->leftCursor);
+ b = getMask(&pWInfo->sMaskSet, pOrTerm->leftCursor);
if( pOrTerm->wtFlags & TERM_VIRTUAL ){
WhereTerm *pOther = &pOrWc->a[pOrTerm->iParent];
- b |= getMask(pMaskSet, pOther->leftCursor);
+ b |= getMask(&pWInfo->sMaskSet, pOther->leftCursor);
}
indexable &= b;
if( (pOrTerm->eOperator & WO_EQ)==0 ){
@@ -105535,7 +106235,7 @@ static void exprAnalyzeOrTerm(
assert( j==1 );
continue;
}
- if( (chngToIN & getMask(pMaskSet, pOrTerm->leftCursor))==0 ){
+ if( (chngToIN & getMask(&pWInfo->sMaskSet, pOrTerm->leftCursor))==0 ){
/* This term must be of the form t1.a==t2.b where t2 is in the
** chngToIN set but t1 is not. This term will be either preceeded
** or follwed by an inverted copy (t2.b==t1.a). Skip this term
@@ -105554,7 +106254,7 @@ static void exprAnalyzeOrTerm(
** on the second iteration */
assert( j==1 );
assert( IsPowerOfTwo(chngToIN) );
- assert( chngToIN==getMask(pMaskSet, iCursor) );
+ assert( chngToIN==getMask(&pWInfo->sMaskSet, iCursor) );
break;
}
testcase( j==1 );
@@ -105588,8 +106288,6 @@ static void exprAnalyzeOrTerm(
/* At this point, okToChngToIN is true if original pTerm satisfies
** case 1. In that case, construct a new virtual term that is
** pTerm converted into an IN operator.
- **
- ** EV: R-00211-15100
*/
if( okToChngToIN ){
Expr *pDup; /* A transient duplicate expression */
@@ -105603,7 +106301,7 @@ static void exprAnalyzeOrTerm(
assert( pOrTerm->leftCursor==iCursor );
assert( pOrTerm->u.leftColumn==iColumn );
pDup = sqlite3ExprDup(db, pOrTerm->pExpr->pRight, 0);
- pList = sqlite3ExprListAppend(pWC->pParse, pList, pDup);
+ pList = sqlite3ExprListAppend(pWInfo->pParse, pList, pDup);
pLeft = pOrTerm->pExpr->pLeft;
}
assert( pLeft!=0 );
@@ -105652,6 +106350,7 @@ static void exprAnalyze(
WhereClause *pWC, /* the WHERE clause */
int idxTerm /* Index of the term to be analyzed */
){
+ WhereInfo *pWInfo = pWC->pWInfo; /* WHERE clause processing context */
WhereTerm *pTerm; /* The term to be analyzed */
WhereMaskSet *pMaskSet; /* Set of table index masks */
Expr *pExpr; /* The expression to be analyzed */
@@ -105662,14 +106361,14 @@ static void exprAnalyze(
int isComplete = 0; /* RHS of LIKE/GLOB ends with wildcard */
int noCase = 0; /* LIKE/GLOB distinguishes case */
int op; /* Top-level operator. pExpr->op */
- Parse *pParse = pWC->pParse; /* Parsing context */
+ Parse *pParse = pWInfo->pParse; /* Parsing context */
sqlite3 *db = pParse->db; /* Database connection */
if( db->mallocFailed ){
return;
}
pTerm = &pWC->a[idxTerm];
- pMaskSet = pWC->pMaskSet;
+ pMaskSet = &pWInfo->sMaskSet;
pExpr = pTerm->pExpr;
assert( pExpr->op!=TK_AS && pExpr->op!=TK_COLLATE );
prereqLeft = exprTableUsage(pMaskSet, pExpr->pLeft);
@@ -105774,6 +106473,7 @@ static void exprAnalyze(
pNewExpr = sqlite3PExpr(pParse, ops[i],
sqlite3ExprDup(db, pExpr->pLeft, 0),
sqlite3ExprDup(db, pList->a[i].pExpr, 0), 0);
+ transferJoinMarkings(pNewExpr, pExpr);
idxNew = whereClauseInsert(pWC, pNewExpr, TERM_VIRTUAL|TERM_DYNAMIC);
testcase( idxNew==0 );
exprAnalyze(pSrc, pWC, idxNew);
@@ -105830,9 +106530,7 @@ static void exprAnalyze(
** inequality. To avoid this, make sure to also run the full
** LIKE on all candidate expressions by clearing the isComplete flag
*/
- if( c=='A'-1 ) isComplete = 0; /* EV: R-64339-08207 */
-
-
+ if( c=='A'-1 ) isComplete = 0;
c = sqlite3UpperToLower[c];
}
*pC = c + 1;
@@ -105843,6 +106541,7 @@ static void exprAnalyze(
pNewExpr1 = sqlite3PExpr(pParse, TK_GE,
sqlite3ExprAddCollateToken(pParse,pNewExpr1,&sCollSeqName),
pStr1, 0);
+ transferJoinMarkings(pNewExpr1, pExpr);
idxNew1 = whereClauseInsert(pWC, pNewExpr1, TERM_VIRTUAL|TERM_DYNAMIC);
testcase( idxNew1==0 );
exprAnalyze(pSrc, pWC, idxNew1);
@@ -105850,6 +106549,7 @@ static void exprAnalyze(
pNewExpr2 = sqlite3PExpr(pParse, TK_LT,
sqlite3ExprAddCollateToken(pParse,pNewExpr2,&sCollSeqName),
pStr2, 0);
+ transferJoinMarkings(pNewExpr2, pExpr);
idxNew2 = whereClauseInsert(pWC, pNewExpr2, TERM_VIRTUAL|TERM_DYNAMIC);
testcase( idxNew2==0 );
exprAnalyze(pSrc, pWC, idxNew2);
@@ -105913,6 +106613,7 @@ static void exprAnalyze(
if( pExpr->op==TK_NOTNULL
&& pExpr->pLeft->op==TK_COLUMN
&& pExpr->pLeft->iColumn>=0
+ && OptimizationEnabled(db, SQLITE_Stat3)
){
Expr *pNewExpr;
Expr *pLeft = pExpr->pLeft;
@@ -105947,11 +106648,8 @@ static void exprAnalyze(
}
/*
-** This function searches the expression list passed as the second argument
-** for an expression of type TK_COLUMN that refers to the same column and
-** uses the same collation sequence as the iCol'th column of index pIdx.
-** Argument iBase is the cursor number used for the table that pIdx refers
-** to.
+** This function searches pList for a entry that matches the iCol-th column
+** of index pIdx.
**
** If such an expression is found, its index in pList->a[] is returned. If
** no expression is found, -1 is returned.
@@ -105983,76 +106681,17 @@ static int findIndexCol(
}
/*
-** This routine determines if pIdx can be used to assist in processing a
-** DISTINCT qualifier. In other words, it tests whether or not using this
-** index for the outer loop guarantees that rows with equal values for
-** all expressions in the pDistinct list are delivered grouped together.
-**
-** For example, the query
-**
-** SELECT DISTINCT a, b, c FROM tbl WHERE a = ?
-**
-** can benefit from any index on columns "b" and "c".
-*/
-static int isDistinctIndex(
- Parse *pParse, /* Parsing context */
- WhereClause *pWC, /* The WHERE clause */
- Index *pIdx, /* The index being considered */
- int base, /* Cursor number for the table pIdx is on */
- ExprList *pDistinct, /* The DISTINCT expressions */
- int nEqCol /* Number of index columns with == */
-){
- Bitmask mask = 0; /* Mask of unaccounted for pDistinct exprs */
- int i; /* Iterator variable */
-
- assert( pDistinct!=0 );
- if( pIdx->zName==0 || pDistinct->nExpr>=BMS ) return 0;
- testcase( pDistinct->nExpr==BMS-1 );
-
- /* Loop through all the expressions in the distinct list. If any of them
- ** are not simple column references, return early. Otherwise, test if the
- ** WHERE clause contains a "col=X" clause. If it does, the expression
- ** can be ignored. If it does not, and the column does not belong to the
- ** same table as index pIdx, return early. Finally, if there is no
- ** matching "col=X" expression and the column is on the same table as pIdx,
- ** set the corresponding bit in variable mask.
- */
- for(i=0; i<pDistinct->nExpr; i++){
- WhereTerm *pTerm;
- Expr *p = sqlite3ExprSkipCollate(pDistinct->a[i].pExpr);
- if( p->op!=TK_COLUMN ) return 0;
- pTerm = findTerm(pWC, p->iTable, p->iColumn, ~(Bitmask)0, WO_EQ, 0);
- if( pTerm ){
- Expr *pX = pTerm->pExpr;
- CollSeq *p1 = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft, pX->pRight);
- CollSeq *p2 = sqlite3ExprCollSeq(pParse, p);
- if( p1==p2 ) continue;
- }
- if( p->iTable!=base ) return 0;
- mask |= (((Bitmask)1) << i);
- }
-
- for(i=nEqCol; mask && i<pIdx->nColumn; i++){
- int iExpr = findIndexCol(pParse, pDistinct, base, pIdx, i);
- if( iExpr<0 ) break;
- mask &= ~(((Bitmask)1) << iExpr);
- }
-
- return (mask==0);
-}
-
-
-/*
** Return true if the DISTINCT expression-list passed as the third argument
-** is redundant. A DISTINCT list is redundant if the database contains a
-** UNIQUE index that guarantees that the result of the query will be distinct
-** anyway.
+** is redundant.
+**
+** A DISTINCT list is redundant if the database contains some subset of
+** columns that are unique and non-null.
*/
static int isDistinctRedundant(
- Parse *pParse,
- SrcList *pTabList,
- WhereClause *pWC,
- ExprList *pDistinct
+ Parse *pParse, /* Parsing context */
+ SrcList *pTabList, /* The FROM clause */
+ WhereClause *pWC, /* The WHERE clause */
+ ExprList *pDistinct /* The result set that needs to be DISTINCT */
){
Table *pTab;
Index *pIdx;
@@ -106108,21 +106747,76 @@ static int isDistinctRedundant(
return 0;
}
+/*
+** Find (an approximate) sum of two WhereCosts. This computation is
+** not a simple "+" operator because WhereCost is stored as a logarithmic
+** value.
+**
+*/
+static WhereCost whereCostAdd(WhereCost a, WhereCost b){
+ static const unsigned char x[] = {
+ 10, 10, /* 0,1 */
+ 9, 9, /* 2,3 */
+ 8, 8, /* 4,5 */
+ 7, 7, 7, /* 6,7,8 */
+ 6, 6, 6, /* 9,10,11 */
+ 5, 5, 5, /* 12-14 */
+ 4, 4, 4, 4, /* 15-18 */
+ 3, 3, 3, 3, 3, 3, /* 19-24 */
+ 2, 2, 2, 2, 2, 2, 2, /* 25-31 */
+ };
+ if( a>=b ){
+ if( a>b+49 ) return a;
+ if( a>b+31 ) return a+1;
+ return a+x[a-b];
+ }else{
+ if( b>a+49 ) return b;
+ if( b>a+31 ) return b+1;
+ return b+x[b-a];
+ }
+}
+
/*
-** Prepare a crude estimate of the logarithm of the input value.
-** The results need not be exact. This is only used for estimating
-** the total cost of performing operations with O(logN) or O(NlogN)
-** complexity. Because N is just a guess, it is no great tragedy if
-** logN is a little off.
+** Convert an integer into a WhereCost. In other words, compute a
+** good approximatation for 10*log2(x).
*/
-static double estLog(double N){
- double logN = 1;
- double x = 10;
- while( N>x ){
- logN += 1;
- x *= 10;
+static WhereCost whereCost(tRowcnt x){
+ static WhereCost a[] = { 0, 2, 3, 5, 6, 7, 8, 9 };
+ WhereCost y = 40;
+ if( x<8 ){
+ if( x<2 ) return 0;
+ while( x<8 ){ y -= 10; x <<= 1; }
+ }else{
+ while( x>255 ){ y += 40; x >>= 4; }
+ while( x>15 ){ y += 10; x >>= 1; }
}
- return logN;
+ return a[x&7] + y - 10;
+}
+
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+/*
+** Convert a double (as received from xBestIndex of a virtual table)
+** into a WhereCost. In other words, compute an approximation for
+** 10*log2(x).
+*/
+static WhereCost whereCostFromDouble(double x){
+ u64 a;
+ WhereCost e;
+ assert( sizeof(x)==8 && sizeof(a)==8 );
+ if( x<=1 ) return 0;
+ if( x<=2000000000 ) return whereCost((tRowcnt)x);
+ memcpy(&a, &x, 8);
+ e = (a>>52) - 1022;
+ return e*10;
+}
+#endif /* SQLITE_OMIT_VIRTUALTABLE */
+
+/*
+** Estimate the logarithm of the input value to base 2.
+*/
+static WhereCost estLog(WhereCost N){
+ WhereCost x = whereCost(N);
+ return x>33 ? x - 33 : 0;
}
/*
@@ -106131,7 +106825,7 @@ static double estLog(double N){
** SQLITE_TEST or SQLITE_DEBUG are defined, then these routines
** are no-ops.
*/
-#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_DEBUG)
+#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(WHERETRACE_ENABLED)
static void TRACE_IDX_INPUTS(sqlite3_index_info *p){
int i;
if( !sqlite3WhereTrace ) return;
@@ -106169,107 +106863,6 @@ static void TRACE_IDX_OUTPUTS(sqlite3_index_info *p){
#define TRACE_IDX_OUTPUTS(A)
#endif
-/*
-** Required because bestIndex() is called by bestOrClauseIndex()
-*/
-static void bestIndex(WhereBestIdx*);
-
-/*
-** This routine attempts to find an scanning strategy that can be used
-** to optimize an 'OR' expression that is part of a WHERE clause.
-**
-** The table associated with FROM clause term pSrc may be either a
-** regular B-Tree table or a virtual table.
-*/
-static void bestOrClauseIndex(WhereBestIdx *p){
-#ifndef SQLITE_OMIT_OR_OPTIMIZATION
- WhereClause *pWC = p->pWC; /* The WHERE clause */
- struct SrcList_item *pSrc = p->pSrc; /* The FROM clause term to search */
- const int iCur = pSrc->iCursor; /* The cursor of the table */
- const Bitmask maskSrc = getMask(pWC->pMaskSet, iCur); /* Bitmask for pSrc */
- WhereTerm * const pWCEnd = &pWC->a[pWC->nTerm]; /* End of pWC->a[] */
- WhereTerm *pTerm; /* A single term of the WHERE clause */
-
- /* The OR-clause optimization is disallowed if the INDEXED BY or
- ** NOT INDEXED clauses are used or if the WHERE_AND_ONLY bit is set. */
- if( pSrc->notIndexed || pSrc->pIndex!=0 ){
- return;
- }
- if( pWC->wctrlFlags & WHERE_AND_ONLY ){
- return;
- }
-
- /* Search the WHERE clause terms for a usable WO_OR term. */
- for(pTerm=pWC->a; pTerm<pWCEnd; pTerm++){
- if( (pTerm->eOperator & WO_OR)!=0
- && ((pTerm->prereqAll & ~maskSrc) & p->notReady)==0
- && (pTerm->u.pOrInfo->indexable & maskSrc)!=0
- ){
- WhereClause * const pOrWC = &pTerm->u.pOrInfo->wc;
- WhereTerm * const pOrWCEnd = &pOrWC->a[pOrWC->nTerm];
- WhereTerm *pOrTerm;
- int flags = WHERE_MULTI_OR;
- double rTotal = 0;
- double nRow = 0;
- Bitmask used = 0;
- WhereBestIdx sBOI;
-
- sBOI = *p;
- sBOI.pOrderBy = 0;
- sBOI.pDistinct = 0;
- sBOI.ppIdxInfo = 0;
- for(pOrTerm=pOrWC->a; pOrTerm<pOrWCEnd; pOrTerm++){
- WHERETRACE(("... Multi-index OR testing for term %d of %d....\n",
- (pOrTerm - pOrWC->a), (pTerm - pWC->a)
- ));
- if( (pOrTerm->eOperator& WO_AND)!=0 ){
- sBOI.pWC = &pOrTerm->u.pAndInfo->wc;
- bestIndex(&sBOI);
- }else if( pOrTerm->leftCursor==iCur ){
- WhereClause tempWC;
- tempWC.pParse = pWC->pParse;
- tempWC.pMaskSet = pWC->pMaskSet;
- tempWC.pOuter = pWC;
- tempWC.op = TK_AND;
- tempWC.a = pOrTerm;
- tempWC.wctrlFlags = 0;
- tempWC.nTerm = 1;
- sBOI.pWC = &tempWC;
- bestIndex(&sBOI);
- }else{
- continue;
- }
- rTotal += sBOI.cost.rCost;
- nRow += sBOI.cost.plan.nRow;
- used |= sBOI.cost.used;
- if( rTotal>=p->cost.rCost ) break;
- }
-
- /* If there is an ORDER BY clause, increase the scan cost to account
- ** for the cost of the sort. */
- if( p->pOrderBy!=0 ){
- WHERETRACE(("... sorting increases OR cost %.9g to %.9g\n",
- rTotal, rTotal+nRow*estLog(nRow)));
- rTotal += nRow*estLog(nRow);
- }
-
- /* If the cost of scanning using this OR term for optimization is
- ** less than the current cost stored in pCost, replace the contents
- ** of pCost. */
- WHERETRACE(("... multi-index OR cost=%.9g nrow=%.9g\n", rTotal, nRow));
- if( rTotal<p->cost.rCost ){
- p->cost.rCost = rTotal;
- p->cost.used = used;
- p->cost.plan.nRow = nRow;
- p->cost.plan.nOBSat = p->i ? p->aLevel[p->i-1].plan.nOBSat : 0;
- p->cost.plan.wsFlags = flags;
- p->cost.plan.u.pTerm = pTerm;
- }
- }
- }
-#endif /* SQLITE_OMIT_OR_OPTIMIZATION */
-}
-
#ifndef SQLITE_OMIT_AUTOMATIC_INDEX
/*
** Return TRUE if the WHERE clause term pTerm is of a form where it
@@ -106285,88 +106878,13 @@ static int termCanDriveIndex(
if( pTerm->leftCursor!=pSrc->iCursor ) return 0;
if( (pTerm->eOperator & WO_EQ)==0 ) return 0;
if( (pTerm->prereqRight & notReady)!=0 ) return 0;
+ if( pTerm->u.leftColumn<0 ) return 0;
aff = pSrc->pTab->aCol[pTerm->u.leftColumn].affinity;
if( !sqlite3IndexAffinityOk(pTerm->pExpr, aff) ) return 0;
return 1;
}
#endif
-#ifndef SQLITE_OMIT_AUTOMATIC_INDEX
-/*
-** If the query plan for pSrc specified in pCost is a full table scan
-** and indexing is allows (if there is no NOT INDEXED clause) and it
-** possible to construct a transient index that would perform better
-** than a full table scan even when the cost of constructing the index
-** is taken into account, then alter the query plan to use the
-** transient index.
-*/
-static void bestAutomaticIndex(WhereBestIdx *p){
- Parse *pParse = p->pParse; /* The parsing context */
- WhereClause *pWC = p->pWC; /* The WHERE clause */
- struct SrcList_item *pSrc = p->pSrc; /* The FROM clause term to search */
- double nTableRow; /* Rows in the input table */
- double logN; /* log(nTableRow) */
- double costTempIdx; /* per-query cost of the transient index */
- WhereTerm *pTerm; /* A single term of the WHERE clause */
- WhereTerm *pWCEnd; /* End of pWC->a[] */
- Table *pTable; /* Table tht might be indexed */
-
- if( pParse->nQueryLoop<=(double)1 ){
- /* There is no point in building an automatic index for a single scan */
- return;
- }
- if( (pParse->db->flags & SQLITE_AutoIndex)==0 ){
- /* Automatic indices are disabled at run-time */
- return;
- }
- if( (p->cost.plan.wsFlags & WHERE_NOT_FULLSCAN)!=0
- && (p->cost.plan.wsFlags & WHERE_COVER_SCAN)==0
- ){
- /* We already have some kind of index in use for this query. */
- return;
- }
- if( pSrc->viaCoroutine ){
- /* Cannot index a co-routine */
- return;
- }
- if( pSrc->notIndexed ){
- /* The NOT INDEXED clause appears in the SQL. */
- return;
- }
- if( pSrc->isCorrelated ){
- /* The source is a correlated sub-query. No point in indexing it. */
- return;
- }
-
- assert( pParse->nQueryLoop >= (double)1 );
- pTable = pSrc->pTab;
- nTableRow = pTable->nRowEst;
- logN = estLog(nTableRow);
- costTempIdx = 2*logN*(nTableRow/pParse->nQueryLoop + 1);
- if( costTempIdx>=p->cost.rCost ){
- /* The cost of creating the transient table would be greater than
- ** doing the full table scan */
- return;
- }
-
- /* Search for any equality comparison term */
- pWCEnd = &pWC->a[pWC->nTerm];
- for(pTerm=pWC->a; pTerm<pWCEnd; pTerm++){
- if( termCanDriveIndex(pTerm, pSrc, p->notReady) ){
- WHERETRACE(("auto-index reduces cost from %.1f to %.1f\n",
- p->cost.rCost, costTempIdx));
- p->cost.rCost = costTempIdx;
- p->cost.plan.nRow = logN + 1;
- p->cost.plan.wsFlags = WHERE_TEMP_INDEX;
- p->cost.used = pTerm->prereqRight;
- break;
- }
- }
-}
-#else
-# define bestAutomaticIndex(A) /* no-op */
-#endif /* SQLITE_OMIT_AUTOMATIC_INDEX */
-
#ifndef SQLITE_OMIT_AUTOMATIC_INDEX
/*
@@ -106396,8 +106914,10 @@ static void constructAutomaticIndex(
int i; /* Loop counter */
int mxBitCol; /* Maximum column in pSrc->colUsed */
CollSeq *pColl; /* Collating sequence to on a column */
+ WhereLoop *pLoop; /* The Loop object */
Bitmask idxCols; /* Bitmap of columns used for indexing */
Bitmask extraCols; /* Bitmap of additional columns */
+ u8 sentWarning = 0; /* True if a warnning has been issued */
/* Generate code to skip over the creation and initialization of the
** transient index on 2nd and subsequent iterations of the loop. */
@@ -106410,21 +106930,31 @@ static void constructAutomaticIndex(
nColumn = 0;
pTable = pSrc->pTab;
pWCEnd = &pWC->a[pWC->nTerm];
+ pLoop = pLevel->pWLoop;
idxCols = 0;
for(pTerm=pWC->a; pTerm<pWCEnd; pTerm++){
if( termCanDriveIndex(pTerm, pSrc, notReady) ){
int iCol = pTerm->u.leftColumn;
- Bitmask cMask = iCol>=BMS ? ((Bitmask)1)<<(BMS-1) : ((Bitmask)1)<<iCol;
+ Bitmask cMask = iCol>=BMS ? MASKBIT(BMS-1) : MASKBIT(iCol);
testcase( iCol==BMS );
testcase( iCol==BMS-1 );
+ if( !sentWarning ){
+ sqlite3_log(SQLITE_WARNING_AUTOINDEX,
+ "automatic index on %s(%s)", pTable->zName,
+ pTable->aCol[iCol].zName);
+ sentWarning = 1;
+ }
if( (idxCols & cMask)==0 ){
- nColumn++;
+ if( whereLoopResize(pParse->db, pLoop, nColumn+1) ) return;
+ pLoop->aLTerm[nColumn++] = pTerm;
idxCols |= cMask;
}
}
}
assert( nColumn>0 );
- pLevel->plan.nEq = nColumn;
+ pLoop->u.btree.nEq = pLoop->nLTerm = nColumn;
+ pLoop->wsFlags = WHERE_COLUMN_EQ | WHERE_IDX_ONLY | WHERE_INDEXED
+ | WHERE_AUTO_INDEX;
/* Count the number of additional columns needed to create a
** covering index. A "covering index" is an index that contains all
@@ -106434,17 +106964,17 @@ static void constructAutomaticIndex(
** original table changes and the index and table cannot both be used
** if they go out of sync.
*/
- extraCols = pSrc->colUsed & (~idxCols | (((Bitmask)1)<<(BMS-1)));
+ extraCols = pSrc->colUsed & (~idxCols | MASKBIT(BMS-1));
mxBitCol = (pTable->nCol >= BMS-1) ? BMS-1 : pTable->nCol;
testcase( pTable->nCol==BMS-1 );
testcase( pTable->nCol==BMS-2 );
for(i=0; i<mxBitCol; i++){
- if( extraCols & (((Bitmask)1)<<i) ) nColumn++;
+ if( extraCols & MASKBIT(i) ) nColumn++;
}
- if( pSrc->colUsed & (((Bitmask)1)<<(BMS-1)) ){
+ if( pSrc->colUsed & MASKBIT(BMS-1) ){
nColumn += pTable->nCol - BMS + 1;
}
- pLevel->plan.wsFlags |= WHERE_COLUMN_EQ | WHERE_IDX_ONLY | WO_EQ;
+ pLoop->wsFlags |= WHERE_COLUMN_EQ | WHERE_IDX_ONLY;
/* Construct the Index object to describe this index */
nByte = sizeof(Index);
@@ -106453,7 +106983,7 @@ static void constructAutomaticIndex(
nByte += nColumn; /* Index.aSortOrder */
pIdx = sqlite3DbMallocZero(pParse->db, nByte);
if( pIdx==0 ) return;
- pLevel->plan.u.pIdx = pIdx;
+ pLoop->u.btree.pIndex = pIdx;
pIdx->azColl = (char**)&pIdx[1];
pIdx->aiColumn = (int*)&pIdx->azColl[nColumn];
pIdx->aSortOrder = (u8*)&pIdx->aiColumn[nColumn];
@@ -106465,7 +106995,9 @@ static void constructAutomaticIndex(
for(pTerm=pWC->a; pTerm<pWCEnd; pTerm++){
if( termCanDriveIndex(pTerm, pSrc, notReady) ){
int iCol = pTerm->u.leftColumn;
- Bitmask cMask = iCol>=BMS ? ((Bitmask)1)<<(BMS-1) : ((Bitmask)1)<<iCol;
+ Bitmask cMask = iCol>=BMS ? MASKBIT(BMS-1) : MASKBIT(iCol);
+ testcase( iCol==BMS-1 );
+ testcase( iCol==BMS );
if( (idxCols & cMask)==0 ){
Expr *pX = pTerm->pExpr;
idxCols |= cMask;
@@ -106476,18 +107008,18 @@ static void constructAutomaticIndex(
}
}
}
- assert( (u32)n==pLevel->plan.nEq );
+ assert( (u32)n==pLoop->u.btree.nEq );
/* Add additional columns needed to make the automatic index into
** a covering index */
for(i=0; i<mxBitCol; i++){
- if( extraCols & (((Bitmask)1)<<i) ){
+ if( extraCols & MASKBIT(i) ){
pIdx->aiColumn[n] = i;
pIdx->azColl[n] = "BINARY";
n++;
}
}
- if( pSrc->colUsed & (((Bitmask)1)<<(BMS-1)) ){
+ if( pSrc->colUsed & MASKBIT(BMS-1) ){
for(i=BMS-1; i<pTable->nCol; i++){
pIdx->aiColumn[n] = i;
pIdx->azColl[n] = "BINARY";
@@ -106499,6 +107031,7 @@ static void constructAutomaticIndex(
/* Create the automatic index */
pKeyinfo = sqlite3IndexKeyinfo(pParse, pIdx);
assert( pLevel->iIdxCur>=0 );
+ pLevel->iIdxCur = pParse->nTab++;
sqlite3VdbeAddOp4(v, OP_OpenAutoindex, pLevel->iIdxCur, nColumn+1, 0,
(char*)pKeyinfo, P4_KEYINFO_HANDOFF);
VdbeComment((v, "for %s", pTable->zName));
@@ -106506,7 +107039,7 @@ static void constructAutomaticIndex(
/* Fill the automatic index with content */
addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, pLevel->iTabCur);
regRecord = sqlite3GetTempReg(pParse);
- sqlite3GenerateIndexKey(pParse, pIdx, pLevel->iTabCur, regRecord, 1);
+ sqlite3GenerateIndexKey(pParse, pIdx, pLevel->iTabCur, regRecord, 1, 0);
sqlite3VdbeAddOp2(v, OP_IdxInsert, pLevel->iIdxCur, regRecord);
sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
sqlite3VdbeAddOp2(v, OP_Next, pLevel->iTabCur, addrTop+1);
@@ -106525,11 +107058,12 @@ static void constructAutomaticIndex(
** responsibility of the caller to eventually release the structure
** by passing the pointer returned by this function to sqlite3_free().
*/
-static sqlite3_index_info *allocateIndexInfo(WhereBestIdx *p){
- Parse *pParse = p->pParse;
- WhereClause *pWC = p->pWC;
- struct SrcList_item *pSrc = p->pSrc;
- ExprList *pOrderBy = p->pOrderBy;
+static sqlite3_index_info *allocateIndexInfo(
+ Parse *pParse,
+ WhereClause *pWC,
+ struct SrcList_item *pSrc,
+ ExprList *pOrderBy
+){
int i, j;
int nTerm;
struct sqlite3_index_constraint *pIdxCons;
@@ -106539,8 +107073,6 @@ static sqlite3_index_info *allocateIndexInfo(WhereBestIdx *p){
int nOrderBy;
sqlite3_index_info *pIdxInfo;
- WHERETRACE(("Recomputing index info for %s...\n", pSrc->pTab->zName));
-
/* Count the number of possible WHERE clause constraints referring
** to this virtual table */
for(i=nTerm=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){
@@ -106576,7 +107108,6 @@ static sqlite3_index_info *allocateIndexInfo(WhereBestIdx *p){
+ sizeof(*pIdxOrderBy)*nOrderBy );
if( pIdxInfo==0 ){
sqlite3ErrorMsg(pParse, "out of memory");
- /* (double)0 In case of SQLITE_OMIT_FLOATING_POINT... */
return 0;
}
@@ -106632,8 +107163,8 @@ static sqlite3_index_info *allocateIndexInfo(WhereBestIdx *p){
/*
** The table object reference passed as the second argument to this function
** must represent a virtual table. This function invokes the xBestIndex()
-** method of the virtual table with the sqlite3_index_info pointer passed
-** as the argument.
+** method of the virtual table with the sqlite3_index_info object that
+** comes in as the 3rd argument to this function.
**
** If an error occurs, pParse is populated with an error message and a
** non-zero value is returned. Otherwise, 0 is returned and the output
@@ -106648,7 +107179,6 @@ static int vtabBestIndex(Parse *pParse, Table *pTab, sqlite3_index_info *p){
int i;
int rc;
- WHERETRACE(("xBestIndex for %s\n", pTab->zName));
TRACE_IDX_INPUTS(p);
rc = pVtab->pModule->xBestIndex(pVtab, p);
TRACE_IDX_OUTPUTS(p);
@@ -106674,208 +107204,9 @@ static int vtabBestIndex(Parse *pParse, Table *pTab, sqlite3_index_info *p){
return pParse->nErr;
}
+#endif /* !defined(SQLITE_OMIT_VIRTUALTABLE) */
-/*
-** Compute the best index for a virtual table.
-**
-** The best index is computed by the xBestIndex method of the virtual
-** table module. This routine is really just a wrapper that sets up
-** the sqlite3_index_info structure that is used to communicate with
-** xBestIndex.
-**
-** In a join, this routine might be called multiple times for the
-** same virtual table. The sqlite3_index_info structure is created
-** and initialized on the first invocation and reused on all subsequent
-** invocations. The sqlite3_index_info structure is also used when
-** code is generated to access the virtual table. The whereInfoDelete()
-** routine takes care of freeing the sqlite3_index_info structure after
-** everybody has finished with it.
-*/
-static void bestVirtualIndex(WhereBestIdx *p){
- Parse *pParse = p->pParse; /* The parsing context */
- WhereClause *pWC = p->pWC; /* The WHERE clause */
- struct SrcList_item *pSrc = p->pSrc; /* The FROM clause term to search */
- Table *pTab = pSrc->pTab;
- sqlite3_index_info *pIdxInfo;
- struct sqlite3_index_constraint *pIdxCons;
- struct sqlite3_index_constraint_usage *pUsage;
- WhereTerm *pTerm;
- int i, j;
- int nOrderBy;
- int bAllowIN; /* Allow IN optimizations */
- double rCost;
-
- /* Make sure wsFlags is initialized to some sane value. Otherwise, if the
- ** malloc in allocateIndexInfo() fails and this function returns leaving
- ** wsFlags in an uninitialized state, the caller may behave unpredictably.
- */
- memset(&p->cost, 0, sizeof(p->cost));
- p->cost.plan.wsFlags = WHERE_VIRTUALTABLE;
-
- /* If the sqlite3_index_info structure has not been previously
- ** allocated and initialized, then allocate and initialize it now.
- */
- pIdxInfo = *p->ppIdxInfo;
- if( pIdxInfo==0 ){
- *p->ppIdxInfo = pIdxInfo = allocateIndexInfo(p);
- }
- if( pIdxInfo==0 ){
- return;
- }
-
- /* At this point, the sqlite3_index_info structure that pIdxInfo points
- ** to will have been initialized, either during the current invocation or
- ** during some prior invocation. Now we just have to customize the
- ** details of pIdxInfo for the current invocation and pass it to
- ** xBestIndex.
- */
-
- /* The module name must be defined. Also, by this point there must
- ** be a pointer to an sqlite3_vtab structure. Otherwise
- ** sqlite3ViewGetColumnNames() would have picked up the error.
- */
- assert( pTab->azModuleArg && pTab->azModuleArg[0] );
- assert( sqlite3GetVTable(pParse->db, pTab) );
-
- /* Try once or twice. On the first attempt, allow IN optimizations.
- ** If an IN optimization is accepted by the virtual table xBestIndex
- ** method, but the pInfo->aConstrainUsage.omit flag is not set, then
- ** the query will not work because it might allow duplicate rows in
- ** output. In that case, run the xBestIndex method a second time
- ** without the IN constraints. Usually this loop only runs once.
- ** The loop will exit using a "break" statement.
- */
- for(bAllowIN=1; 1; bAllowIN--){
- assert( bAllowIN==0 || bAllowIN==1 );
-
- /* Set the aConstraint[].usable fields and initialize all
- ** output variables to zero.
- **
- ** aConstraint[].usable is true for constraints where the right-hand
- ** side contains only references to tables to the left of the current
- ** table. In other words, if the constraint is of the form:
- **
- ** column = expr
- **
- ** and we are evaluating a join, then the constraint on column is
- ** only valid if all tables referenced in expr occur to the left
- ** of the table containing column.
- **
- ** The aConstraints[] array contains entries for all constraints
- ** on the current table. That way we only have to compute it once
- ** even though we might try to pick the best index multiple times.
- ** For each attempt at picking an index, the order of tables in the
- ** join might be different so we have to recompute the usable flag
- ** each time.
- */
- pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint;
- pUsage = pIdxInfo->aConstraintUsage;
- for(i=0; i<pIdxInfo->nConstraint; i++, pIdxCons++){
- j = pIdxCons->iTermOffset;
- pTerm = &pWC->a[j];
- if( (pTerm->prereqRight&p->notReady)==0
- && (bAllowIN || (pTerm->eOperator & WO_IN)==0)
- ){
- pIdxCons->usable = 1;
- }else{
- pIdxCons->usable = 0;
- }
- }
- memset(pUsage, 0, sizeof(pUsage[0])*pIdxInfo->nConstraint);
- if( pIdxInfo->needToFreeIdxStr ){
- sqlite3_free(pIdxInfo->idxStr);
- }
- pIdxInfo->idxStr = 0;
- pIdxInfo->idxNum = 0;
- pIdxInfo->needToFreeIdxStr = 0;
- pIdxInfo->orderByConsumed = 0;
- /* ((double)2) In case of SQLITE_OMIT_FLOATING_POINT... */
- pIdxInfo->estimatedCost = SQLITE_BIG_DBL / ((double)2);
- nOrderBy = pIdxInfo->nOrderBy;
- if( !p->pOrderBy ){
- pIdxInfo->nOrderBy = 0;
- }
-
- if( vtabBestIndex(pParse, pTab, pIdxInfo) ){
- return;
- }
-
- pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint;
- for(i=0; i<pIdxInfo->nConstraint; i++, pIdxCons++){
- if( pUsage[i].argvIndex>0 ){
- j = pIdxCons->iTermOffset;
- pTerm = &pWC->a[j];
- p->cost.used |= pTerm->prereqRight;
- if( (pTerm->eOperator & WO_IN)!=0 ){
- if( pUsage[i].omit==0 ){
- /* Do not attempt to use an IN constraint if the virtual table
- ** says that the equivalent EQ constraint cannot be safely omitted.
- ** If we do attempt to use such a constraint, some rows might be
- ** repeated in the output. */
- break;
- }
- /* A virtual table that is constrained by an IN clause may not
- ** consume the ORDER BY clause because (1) the order of IN terms
- ** is not necessarily related to the order of output terms and
- ** (2) Multiple outputs from a single IN value will not merge
- ** together. */
- pIdxInfo->orderByConsumed = 0;
- }
- }
- }
- if( i>=pIdxInfo->nConstraint ) break;
- }
-
- /* The orderByConsumed signal is only valid if all outer loops collectively
- ** generate just a single row of output.
- */
- if( pIdxInfo->orderByConsumed ){
- for(i=0; i<p->i; i++){
- if( (p->aLevel[i].plan.wsFlags & WHERE_UNIQUE)==0 ){
- pIdxInfo->orderByConsumed = 0;
- }
- }
- }
-
- /* If there is an ORDER BY clause, and the selected virtual table index
- ** does not satisfy it, increase the cost of the scan accordingly. This
- ** matches the processing for non-virtual tables in bestBtreeIndex().
- */
- rCost = pIdxInfo->estimatedCost;
- if( p->pOrderBy && pIdxInfo->orderByConsumed==0 ){
- rCost += estLog(rCost)*rCost;
- }
-
- /* The cost is not allowed to be larger than SQLITE_BIG_DBL (the
- ** inital value of lowestCost in this loop. If it is, then the
- ** (cost<lowestCost) test below will never be true.
- **
- ** Use "(double)2" instead of "2.0" in case OMIT_FLOATING_POINT
- ** is defined.
- */
- if( (SQLITE_BIG_DBL/((double)2))<rCost ){
- p->cost.rCost = (SQLITE_BIG_DBL/((double)2));
- }else{
- p->cost.rCost = rCost;
- }
- p->cost.plan.u.pVtabIdx = pIdxInfo;
- if( pIdxInfo->orderByConsumed ){
- p->cost.plan.wsFlags |= WHERE_ORDERED;
- p->cost.plan.nOBSat = nOrderBy;
- }else{
- p->cost.plan.nOBSat = p->i ? p->aLevel[p->i-1].plan.nOBSat : 0;
- }
- p->cost.plan.nEq = 0;
- pIdxInfo->nOrderBy = nOrderBy;
-
- /* Try to find a more efficient access pattern by using multiple indexes
- ** to optimize an OR expression within the WHERE clause.
- */
- bestOrClauseIndex(p);
-}
-#endif /* SQLITE_OMIT_VIRTUALTABLE */
-
#ifdef SQLITE_ENABLE_STAT3
/*
** Estimate the location of a particular key among all keys in an
@@ -106961,9 +107292,10 @@ static int whereKeyStats(
assert( pColl->enc==SQLITE_UTF8 );
}else{
pColl = sqlite3GetCollSeq(pParse, SQLITE_UTF8, 0, *pIdx->azColl);
- if( pColl==0 ){
- return SQLITE_ERROR;
- }
+ /* If the collating sequence was unavailable, we should have failed
+ ** long ago and never reached this point. But we'll check just to
+ ** be doubly sure. */
+ if( NEVER(pColl==0) ) return SQLITE_ERROR;
z = (const u8 *)sqlite3ValueText(pVal, pColl->enc);
if( !z ){
return SQLITE_NOMEM;
@@ -107064,7 +107396,7 @@ static int valueFromExpr(
){
int iVar = pExpr->iColumn;
sqlite3VdbeSetVarmask(pParse->pVdbe, iVar);
- *pp = sqlite3VdbeGetValue(pParse->pReprepare, iVar, aff);
+ *pp = sqlite3VdbeGetBoundValue(pParse->pReprepare, iVar, aff);
return SQLITE_OK;
}
return sqlite3ValueFromExpr(pParse->db, pExpr, SQLITE_UTF8, aff, pp);
@@ -107116,13 +107448,13 @@ static int whereRangeScanEst(
int nEq, /* index into p->aCol[] of the range-compared column */
WhereTerm *pLower, /* Lower bound on the range. ex: "x>123" Might be NULL */
WhereTerm *pUpper, /* Upper bound on the range. ex: "x<455" Might be NULL */
- double *pRangeDiv /* OUT: Reduce search space by this divisor */
+ WhereCost *pRangeDiv /* OUT: Reduce search space by this divisor */
){
int rc = SQLITE_OK;
#ifdef SQLITE_ENABLE_STAT3
- if( nEq==0 && p->nSample ){
+ if( nEq==0 && p->nSample && OptimizationEnabled(pParse->db, SQLITE_Stat3) ){
sqlite3_value *pRangeVal;
tRowcnt iLower = 0;
tRowcnt iUpper = p->aiRowEst[0];
@@ -107154,13 +107486,13 @@ static int whereRangeScanEst(
sqlite3ValueFree(pRangeVal);
}
if( rc==SQLITE_OK ){
- if( iUpper<=iLower ){
- *pRangeDiv = (double)p->aiRowEst[0];
- }else{
- *pRangeDiv = (double)p->aiRowEst[0]/(double)(iUpper - iLower);
+ WhereCost iBase = whereCost(p->aiRowEst[0]);
+ if( iUpper>iLower ){
+ iBase -= whereCost(iUpper - iLower);
}
- WHERETRACE(("range scan regions: %u..%u div=%g\n",
- (u32)iLower, (u32)iUpper, *pRangeDiv));
+ *pRangeDiv = iBase;
+ WHERETRACE(0x100, ("range scan regions: %u..%u div=%d\n",
+ (u32)iLower, (u32)iUpper, *pRangeDiv));
return SQLITE_OK;
}
}
@@ -107170,9 +107502,15 @@ static int whereRangeScanEst(
UNUSED_PARAMETER(nEq);
#endif
assert( pLower || pUpper );
- *pRangeDiv = (double)1;
- if( pLower && (pLower->wtFlags & TERM_VNULL)==0 ) *pRangeDiv *= (double)4;
- if( pUpper ) *pRangeDiv *= (double)4;
+ *pRangeDiv = 0;
+ /* TUNING: Each inequality constraint reduces the search space 4-fold.
+ ** A BETWEEN operator, therefore, reduces the search space 16-fold */
+ if( pLower && (pLower->wtFlags & TERM_VNULL)==0 ){
+ *pRangeDiv += 20; assert( 20==whereCost(4) );
+ }
+ if( pUpper ){
+ *pRangeDiv += 20; assert( 20==whereCost(4) );
+ }
return rc;
}
@@ -107198,7 +107536,7 @@ static int whereEqualScanEst(
Parse *pParse, /* Parsing & code generating context */
Index *p, /* The index whose left-most column is pTerm */
Expr *pExpr, /* Expression for VALUE in the x=VALUE constraint */
- double *pnRow /* Write the revised row estimate here */
+ tRowcnt *pnRow /* Write the revised row estimate here */
){
sqlite3_value *pRhs = 0; /* VALUE on right-hand side of pTerm */
u8 aff; /* Column affinity */
@@ -107217,7 +107555,7 @@ static int whereEqualScanEst(
if( pRhs==0 ) return SQLITE_NOTFOUND;
rc = whereKeyStats(pParse, p, pRhs, 0, a);
if( rc==SQLITE_OK ){
- WHERETRACE(("equality scan regions: %d\n", (int)a[1]));
+ WHERETRACE(0x100,("equality scan regions: %d\n", (int)a[1]));
*pnRow = a[1];
}
whereEqualScanEst_cancel:
@@ -107247,12 +107585,12 @@ static int whereInScanEst(
Parse *pParse, /* Parsing & code generating context */
Index *p, /* The index whose left-most column is pTerm */
ExprList *pList, /* The value list on the RHS of "x IN (v1,v2,v3,...)" */
- double *pnRow /* Write the revised row estimate here */
+ tRowcnt *pnRow /* Write the revised row estimate here */
){
- int rc = SQLITE_OK; /* Subfunction return code */
- double nEst; /* Number of rows for a single term */
- double nRowEst = (double)0; /* New estimate of the number of rows */
- int i; /* Loop counter */
+ int rc = SQLITE_OK; /* Subfunction return code */
+ tRowcnt nEst; /* Number of rows for a single term */
+ tRowcnt nRowEst = 0; /* New estimate of the number of rows */
+ int i; /* Loop counter */
assert( p->aSample!=0 );
for(i=0; rc==SQLITE_OK && i<pList->nExpr; i++){
@@ -107263,886 +107601,13 @@ static int whereInScanEst(
if( rc==SQLITE_OK ){
if( nRowEst > p->aiRowEst[0] ) nRowEst = p->aiRowEst[0];
*pnRow = nRowEst;
- WHERETRACE(("IN row estimate: est=%g\n", nRowEst));
+ WHERETRACE(0x100,("IN row estimate: est=%g\n", nRowEst));
}
return rc;
}
#endif /* defined(SQLITE_ENABLE_STAT3) */
/*
-** Check to see if column iCol of the table with cursor iTab will appear
-** in sorted order according to the current query plan.
-**
-** Return values:
-**
-** 0 iCol is not ordered
-** 1 iCol has only a single value
-** 2 iCol is in ASC order
-** 3 iCol is in DESC order
-*/
-static int isOrderedColumn(
- WhereBestIdx *p,
- int iTab,
- int iCol
-){
- int i, j;
- WhereLevel *pLevel = &p->aLevel[p->i-1];
- Index *pIdx;
- u8 sortOrder;
- for(i=p->i-1; i>=0; i--, pLevel--){
- if( pLevel->iTabCur!=iTab ) continue;
- if( (pLevel->plan.wsFlags & WHERE_ALL_UNIQUE)!=0 ){
- return 1;
- }
- assert( (pLevel->plan.wsFlags & WHERE_ORDERED)!=0 );
- if( (pIdx = pLevel->plan.u.pIdx)!=0 ){
- if( iCol<0 ){
- sortOrder = 0;
- testcase( (pLevel->plan.wsFlags & WHERE_REVERSE)!=0 );
- }else{
- int n = pIdx->nColumn;
- for(j=0; j<n; j++){
- if( iCol==pIdx->aiColumn[j] ) break;
- }
- if( j>=n ) return 0;
- sortOrder = pIdx->aSortOrder[j];
- testcase( (pLevel->plan.wsFlags & WHERE_REVERSE)!=0 );
- }
- }else{
- if( iCol!=(-1) ) return 0;
- sortOrder = 0;
- testcase( (pLevel->plan.wsFlags & WHERE_REVERSE)!=0 );
- }
- if( (pLevel->plan.wsFlags & WHERE_REVERSE)!=0 ){
- assert( sortOrder==0 || sortOrder==1 );
- testcase( sortOrder==1 );
- sortOrder = 1 - sortOrder;
- }
- return sortOrder+2;
- }
- return 0;
-}
-
-/*
-** This routine decides if pIdx can be used to satisfy the ORDER BY
-** clause, either in whole or in part. The return value is the
-** cumulative number of terms in the ORDER BY clause that are satisfied
-** by the index pIdx and other indices in outer loops.
-**
-** The table being queried has a cursor number of "base". pIdx is the
-** index that is postulated for use to access the table.
-**
-** The *pbRev value is set to 0 order 1 depending on whether or not
-** pIdx should be run in the forward order or in reverse order.
-*/
-static int isSortingIndex(
- WhereBestIdx *p, /* Best index search context */
- Index *pIdx, /* The index we are testing */
- int base, /* Cursor number for the table to be sorted */
- int *pbRev, /* Set to 1 for reverse-order scan of pIdx */
- int *pbObUnique /* ORDER BY column values will different in every row */
-){
- int i; /* Number of pIdx terms used */
- int j; /* Number of ORDER BY terms satisfied */
- int sortOrder = 2; /* 0: forward. 1: backward. 2: unknown */
- int nTerm; /* Number of ORDER BY terms */
- struct ExprList_item *pOBItem;/* A term of the ORDER BY clause */
- Table *pTab = pIdx->pTable; /* Table that owns index pIdx */
- ExprList *pOrderBy; /* The ORDER BY clause */
- Parse *pParse = p->pParse; /* Parser context */
- sqlite3 *db = pParse->db; /* Database connection */
- int nPriorSat; /* ORDER BY terms satisfied by outer loops */
- int seenRowid = 0; /* True if an ORDER BY rowid term is seen */
- int uniqueNotNull; /* pIdx is UNIQUE with all terms are NOT NULL */
- int outerObUnique; /* Outer loops generate different values in
- ** every row for the ORDER BY columns */
-
- if( p->i==0 ){
- nPriorSat = 0;
- outerObUnique = 1;
- }else{
- u32 wsFlags = p->aLevel[p->i-1].plan.wsFlags;
- nPriorSat = p->aLevel[p->i-1].plan.nOBSat;
- if( (wsFlags & WHERE_ORDERED)==0 ){
- /* This loop cannot be ordered unless the next outer loop is
- ** also ordered */
- return nPriorSat;
- }
- if( OptimizationDisabled(db, SQLITE_OrderByIdxJoin) ){
- /* Only look at the outer-most loop if the OrderByIdxJoin
- ** optimization is disabled */
- return nPriorSat;
- }
- testcase( wsFlags & WHERE_OB_UNIQUE );
- testcase( wsFlags & WHERE_ALL_UNIQUE );
- outerObUnique = (wsFlags & (WHERE_OB_UNIQUE|WHERE_ALL_UNIQUE))!=0;
- }
- pOrderBy = p->pOrderBy;
- assert( pOrderBy!=0 );
- if( pIdx->bUnordered ){
- /* Hash indices (indicated by the "unordered" tag on sqlite_stat1) cannot
- ** be used for sorting */
- return nPriorSat;
- }
- nTerm = pOrderBy->nExpr;
- uniqueNotNull = pIdx->onError!=OE_None;
- assert( nTerm>0 );
-
- /* Argument pIdx must either point to a 'real' named index structure,
- ** or an index structure allocated on the stack by bestBtreeIndex() to
- ** represent the rowid index that is part of every table. */
- assert( pIdx->zName || (pIdx->nColumn==1 && pIdx->aiColumn[0]==-1) );
-
- /* Match terms of the ORDER BY clause against columns of
- ** the index.
- **
- ** Note that indices have pIdx->nColumn regular columns plus
- ** one additional column containing the rowid. The rowid column
- ** of the index is also allowed to match against the ORDER BY
- ** clause.
- */
- j = nPriorSat;
- for(i=0,pOBItem=&pOrderBy->a[j]; j<nTerm && i<=pIdx->nColumn; i++){
- Expr *pOBExpr; /* The expression of the ORDER BY pOBItem */
- CollSeq *pColl; /* The collating sequence of pOBExpr */
- int termSortOrder; /* Sort order for this term */
- int iColumn; /* The i-th column of the index. -1 for rowid */
- int iSortOrder; /* 1 for DESC, 0 for ASC on the i-th index term */
- int isEq; /* Subject to an == or IS NULL constraint */
- int isMatch; /* ORDER BY term matches the index term */
- const char *zColl; /* Name of collating sequence for i-th index term */
- WhereTerm *pConstraint; /* A constraint in the WHERE clause */
-
- /* If the next term of the ORDER BY clause refers to anything other than
- ** a column in the "base" table, then this index will not be of any
- ** further use in handling the ORDER BY. */
- pOBExpr = sqlite3ExprSkipCollate(pOBItem->pExpr);
- if( pOBExpr->op!=TK_COLUMN || pOBExpr->iTable!=base ){
- break;
- }
-
- /* Find column number and collating sequence for the next entry
- ** in the index */
- if( pIdx->zName && i<pIdx->nColumn ){
- iColumn = pIdx->aiColumn[i];
- if( iColumn==pIdx->pTable->iPKey ){
- iColumn = -1;
- }
- iSortOrder = pIdx->aSortOrder[i];
- zColl = pIdx->azColl[i];
- assert( zColl!=0 );
- }else{
- iColumn = -1;
- iSortOrder = 0;
- zColl = 0;
- }
-
- /* Check to see if the column number and collating sequence of the
- ** index match the column number and collating sequence of the ORDER BY
- ** clause entry. Set isMatch to 1 if they both match. */
- if( pOBExpr->iColumn==iColumn ){
- if( zColl ){
- pColl = sqlite3ExprCollSeq(pParse, pOBItem->pExpr);
- if( !pColl ) pColl = db->pDfltColl;
- isMatch = sqlite3StrICmp(pColl->zName, zColl)==0;
- }else{
- isMatch = 1;
- }
- }else{
- isMatch = 0;
- }
-
- /* termSortOrder is 0 or 1 for whether or not the access loop should
- ** run forward or backwards (respectively) in order to satisfy this
- ** term of the ORDER BY clause. */
- assert( pOBItem->sortOrder==0 || pOBItem->sortOrder==1 );
- assert( iSortOrder==0 || iSortOrder==1 );
- termSortOrder = iSortOrder ^ pOBItem->sortOrder;
-
- /* If X is the column in the index and ORDER BY clause, check to see
- ** if there are any X= or X IS NULL constraints in the WHERE clause. */
- pConstraint = findTerm(p->pWC, base, iColumn, p->notReady,
- WO_EQ|WO_ISNULL|WO_IN, pIdx);
- if( pConstraint==0 ){
- isEq = 0;
- }else if( (pConstraint->eOperator & WO_IN)!=0 ){
- isEq = 0;
- }else if( (pConstraint->eOperator & WO_ISNULL)!=0 ){
- uniqueNotNull = 0;
- isEq = 1; /* "X IS NULL" means X has only a single value */
- }else if( pConstraint->prereqRight==0 ){
- isEq = 1; /* Constraint "X=constant" means X has only a single value */
- }else{
- Expr *pRight = pConstraint->pExpr->pRight;
- if( pRight->op==TK_COLUMN ){
- WHERETRACE((" .. isOrderedColumn(tab=%d,col=%d)",
- pRight->iTable, pRight->iColumn));
- isEq = isOrderedColumn(p, pRight->iTable, pRight->iColumn);
- WHERETRACE((" -> isEq=%d\n", isEq));
-
- /* If the constraint is of the form X=Y where Y is an ordered value
- ** in an outer loop, then make sure the sort order of Y matches the
- ** sort order required for X. */
- if( isMatch && isEq>=2 && isEq!=pOBItem->sortOrder+2 ){
- testcase( isEq==2 );
- testcase( isEq==3 );
- break;
- }
- }else{
- isEq = 0; /* "X=expr" places no ordering constraints on X */
- }
- }
- if( !isMatch ){
- if( isEq==0 ){
- break;
- }else{
- continue;
- }
- }else if( isEq!=1 ){
- if( sortOrder==2 ){
- sortOrder = termSortOrder;
- }else if( termSortOrder!=sortOrder ){
- break;
- }
- }
- j++;
- pOBItem++;
- if( iColumn<0 ){
- seenRowid = 1;
- break;
- }else if( pTab->aCol[iColumn].notNull==0 && isEq!=1 ){
- testcase( isEq==0 );
- testcase( isEq==2 );
- testcase( isEq==3 );
- uniqueNotNull = 0;
- }
- }
- if( seenRowid ){
- uniqueNotNull = 1;
- }else if( uniqueNotNull==0 || i<pIdx->nColumn ){
- uniqueNotNull = 0;
- }
-
- /* If we have not found at least one ORDER BY term that matches the
- ** index, then show no progress. */
- if( pOBItem==&pOrderBy->a[nPriorSat] ) return nPriorSat;
-
- /* Either the outer queries must generate rows where there are no two
- ** rows with the same values in all ORDER BY columns, or else this
- ** loop must generate just a single row of output. Example: Suppose
- ** the outer loops generate A=1 and A=1, and this loop generates B=3
- ** and B=4. Then without the following test, ORDER BY A,B would
- ** generate the wrong order output: 1,3 1,4 1,3 1,4
- */
- if( outerObUnique==0 && uniqueNotNull==0 ) return nPriorSat;
- *pbObUnique = uniqueNotNull;
-
- /* Return the necessary scan order back to the caller */
- *pbRev = sortOrder & 1;
-
- /* If there was an "ORDER BY rowid" term that matched, or it is only
- ** possible for a single row from this table to match, then skip over
- ** any additional ORDER BY terms dealing with this table.
- */
- if( uniqueNotNull ){
- /* Advance j over additional ORDER BY terms associated with base */
- WhereMaskSet *pMS = p->pWC->pMaskSet;
- Bitmask m = ~getMask(pMS, base);
- while( j<nTerm && (exprTableUsage(pMS, pOrderBy->a[j].pExpr)&m)==0 ){
- j++;
- }
- }
- return j;
-}
-
-/*
-** Find the best query plan for accessing a particular table. Write the
-** best query plan and its cost into the p->cost.
-**
-** The lowest cost plan wins. The cost is an estimate of the amount of
-** CPU and disk I/O needed to process the requested result.
-** Factors that influence cost include:
-**
-** * The estimated number of rows that will be retrieved. (The
-** fewer the better.)
-**
-** * Whether or not sorting must occur.
-**
-** * Whether or not there must be separate lookups in the
-** index and in the main table.
-**
-** If there was an INDEXED BY clause (pSrc->pIndex) attached to the table in
-** the SQL statement, then this function only considers plans using the
-** named index. If no such plan is found, then the returned cost is
-** SQLITE_BIG_DBL. If a plan is found that uses the named index,
-** then the cost is calculated in the usual way.
-**
-** If a NOT INDEXED clause was attached to the table
-** in the SELECT statement, then no indexes are considered. However, the
-** selected plan may still take advantage of the built-in rowid primary key
-** index.
-*/
-static void bestBtreeIndex(WhereBestIdx *p){
- Parse *pParse = p->pParse; /* The parsing context */
- WhereClause *pWC = p->pWC; /* The WHERE clause */
- struct SrcList_item *pSrc = p->pSrc; /* The FROM clause term to search */
- int iCur = pSrc->iCursor; /* The cursor of the table to be accessed */
- Index *pProbe; /* An index we are evaluating */
- Index *pIdx; /* Copy of pProbe, or zero for IPK index */
- int eqTermMask; /* Current mask of valid equality operators */
- int idxEqTermMask; /* Index mask of valid equality operators */
- Index sPk; /* A fake index object for the primary key */
- tRowcnt aiRowEstPk[2]; /* The aiRowEst[] value for the sPk index */
- int aiColumnPk = -1; /* The aColumn[] value for the sPk index */
- int wsFlagMask; /* Allowed flags in p->cost.plan.wsFlag */
- int nPriorSat; /* ORDER BY terms satisfied by outer loops */
- int nOrderBy; /* Number of ORDER BY terms */
- char bSortInit; /* Initializer for bSort in inner loop */
- char bDistInit; /* Initializer for bDist in inner loop */
-
-
- /* Initialize the cost to a worst-case value */
- memset(&p->cost, 0, sizeof(p->cost));
- p->cost.rCost = SQLITE_BIG_DBL;
-
- /* If the pSrc table is the right table of a LEFT JOIN then we may not
- ** use an index to satisfy IS NULL constraints on that table. This is
- ** because columns might end up being NULL if the table does not match -
- ** a circumstance which the index cannot help us discover. Ticket #2177.
- */
- if( pSrc->jointype & JT_LEFT ){
- idxEqTermMask = WO_EQ|WO_IN;
- }else{
- idxEqTermMask = WO_EQ|WO_IN|WO_ISNULL;
- }
-
- if( pSrc->pIndex ){
- /* An INDEXED BY clause specifies a particular index to use */
- pIdx = pProbe = pSrc->pIndex;
- wsFlagMask = ~(WHERE_ROWID_EQ|WHERE_ROWID_RANGE);
- eqTermMask = idxEqTermMask;
- }else{
- /* There is no INDEXED BY clause. Create a fake Index object in local
- ** variable sPk to represent the rowid primary key index. Make this
- ** fake index the first in a chain of Index objects with all of the real
- ** indices to follow */
- Index *pFirst; /* First of real indices on the table */
- memset(&sPk, 0, sizeof(Index));
- sPk.nColumn = 1;
- sPk.aiColumn = &aiColumnPk;
- sPk.aiRowEst = aiRowEstPk;
- sPk.onError = OE_Replace;
- sPk.pTable = pSrc->pTab;
- aiRowEstPk[0] = pSrc->pTab->nRowEst;
- aiRowEstPk[1] = 1;
- pFirst = pSrc->pTab->pIndex;
- if( pSrc->notIndexed==0 ){
- /* The real indices of the table are only considered if the
- ** NOT INDEXED qualifier is omitted from the FROM clause */
- sPk.pNext = pFirst;
- }
- pProbe = &sPk;
- wsFlagMask = ~(
- WHERE_COLUMN_IN|WHERE_COLUMN_EQ|WHERE_COLUMN_NULL|WHERE_COLUMN_RANGE
- );
- eqTermMask = WO_EQ|WO_IN;
- pIdx = 0;
- }
-
- nOrderBy = p->pOrderBy ? p->pOrderBy->nExpr : 0;
- if( p->i ){
- nPriorSat = p->aLevel[p->i-1].plan.nOBSat;
- bSortInit = nPriorSat<nOrderBy;
- bDistInit = 0;
- }else{
- nPriorSat = 0;
- bSortInit = nOrderBy>0;
- bDistInit = p->pDistinct!=0;
- }
-
- /* Loop over all indices looking for the best one to use
- */
- for(; pProbe; pIdx=pProbe=pProbe->pNext){
- const tRowcnt * const aiRowEst = pProbe->aiRowEst;
- WhereCost pc; /* Cost of using pProbe */
- double log10N = (double)1; /* base-10 logarithm of nRow (inexact) */
-
- /* The following variables are populated based on the properties of
- ** index being evaluated. They are then used to determine the expected
- ** cost and number of rows returned.
- **
- ** pc.plan.nEq:
- ** Number of equality terms that can be implemented using the index.
- ** In other words, the number of initial fields in the index that
- ** are used in == or IN or NOT NULL constraints of the WHERE clause.
- **
- ** nInMul:
- ** The "in-multiplier". This is an estimate of how many seek operations
- ** SQLite must perform on the index in question. For example, if the
- ** WHERE clause is:
- **
- ** WHERE a IN (1, 2, 3) AND b IN (4, 5, 6)
- **
- ** SQLite must perform 9 lookups on an index on (a, b), so nInMul is
- ** set to 9. Given the same schema and either of the following WHERE
- ** clauses:
- **
- ** WHERE a = 1
- ** WHERE a >= 2
- **
- ** nInMul is set to 1.
- **
- ** If there exists a WHERE term of the form "x IN (SELECT ...)", then
- ** the sub-select is assumed to return 25 rows for the purposes of
- ** determining nInMul.
- **
- ** bInEst:
- ** Set to true if there was at least one "x IN (SELECT ...)" term used
- ** in determining the value of nInMul. Note that the RHS of the
- ** IN operator must be a SELECT, not a value list, for this variable
- ** to be true.
- **
- ** rangeDiv:
- ** An estimate of a divisor by which to reduce the search space due
- ** to inequality constraints. In the absence of sqlite_stat3 ANALYZE
- ** data, a single inequality reduces the search space to 1/4rd its
- ** original size (rangeDiv==4). Two inequalities reduce the search
- ** space to 1/16th of its original size (rangeDiv==16).
- **
- ** bSort:
- ** Boolean. True if there is an ORDER BY clause that will require an
- ** external sort (i.e. scanning the index being evaluated will not
- ** correctly order records).
- **
- ** bDist:
- ** Boolean. True if there is a DISTINCT clause that will require an
- ** external btree.
- **
- ** bLookup:
- ** Boolean. True if a table lookup is required for each index entry
- ** visited. In other words, true if this is not a covering index.
- ** This is always false for the rowid primary key index of a table.
- ** For other indexes, it is true unless all the columns of the table
- ** used by the SELECT statement are present in the index (such an
- ** index is sometimes described as a covering index).
- ** For example, given the index on (a, b), the second of the following
- ** two queries requires table b-tree lookups in order to find the value
- ** of column c, but the first does not because columns a and b are
- ** both available in the index.
- **
- ** SELECT a, b FROM tbl WHERE a = 1;
- ** SELECT a, b, c FROM tbl WHERE a = 1;
- */
- int bInEst = 0; /* True if "x IN (SELECT...)" seen */
- int nInMul = 1; /* Number of distinct equalities to lookup */
- double rangeDiv = (double)1; /* Estimated reduction in search space */
- int nBound = 0; /* Number of range constraints seen */
- char bSort = bSortInit; /* True if external sort required */
- char bDist = bDistInit; /* True if index cannot help with DISTINCT */
- char bLookup = 0; /* True if not a covering index */
- WhereTerm *pTerm; /* A single term of the WHERE clause */
-#ifdef SQLITE_ENABLE_STAT3
- WhereTerm *pFirstTerm = 0; /* First term matching the index */
-#endif
-
- WHERETRACE((
- " %s(%s):\n",
- pSrc->pTab->zName, (pIdx ? pIdx->zName : "ipk")
- ));
- memset(&pc, 0, sizeof(pc));
- pc.plan.nOBSat = nPriorSat;
-
- /* Determine the values of pc.plan.nEq and nInMul */
- for(pc.plan.nEq=0; pc.plan.nEq<pProbe->nColumn; pc.plan.nEq++){
- int j = pProbe->aiColumn[pc.plan.nEq];
- pTerm = findTerm(pWC, iCur, j, p->notReady, eqTermMask, pIdx);
- if( pTerm==0 ) break;
- pc.plan.wsFlags |= (WHERE_COLUMN_EQ|WHERE_ROWID_EQ);
- testcase( pTerm->pWC!=pWC );
- if( pTerm->eOperator & WO_IN ){
- Expr *pExpr = pTerm->pExpr;
- pc.plan.wsFlags |= WHERE_COLUMN_IN;
- if( ExprHasProperty(pExpr, EP_xIsSelect) ){
- /* "x IN (SELECT ...)": Assume the SELECT returns 25 rows */
- nInMul *= 25;
- bInEst = 1;
- }else if( ALWAYS(pExpr->x.pList && pExpr->x.pList->nExpr) ){
- /* "x IN (value, value, ...)" */
- nInMul *= pExpr->x.pList->nExpr;
- }
- }else if( pTerm->eOperator & WO_ISNULL ){
- pc.plan.wsFlags |= WHERE_COLUMN_NULL;
- }
-#ifdef SQLITE_ENABLE_STAT3
- if( pc.plan.nEq==0 && pProbe->aSample ) pFirstTerm = pTerm;
-#endif
- pc.used |= pTerm->prereqRight;
- }
-
- /* If the index being considered is UNIQUE, and there is an equality
- ** constraint for all columns in the index, then this search will find
- ** at most a single row. In this case set the WHERE_UNIQUE flag to
- ** indicate this to the caller.
- **
- ** Otherwise, if the search may find more than one row, test to see if
- ** there is a range constraint on indexed column (pc.plan.nEq+1) that
- ** can be optimized using the index.
- */
- if( pc.plan.nEq==pProbe->nColumn && pProbe->onError!=OE_None ){
- testcase( pc.plan.wsFlags & WHERE_COLUMN_IN );
- testcase( pc.plan.wsFlags & WHERE_COLUMN_NULL );
- if( (pc.plan.wsFlags & (WHERE_COLUMN_IN|WHERE_COLUMN_NULL))==0 ){
- pc.plan.wsFlags |= WHERE_UNIQUE;
- if( p->i==0 || (p->aLevel[p->i-1].plan.wsFlags & WHERE_ALL_UNIQUE)!=0 ){
- pc.plan.wsFlags |= WHERE_ALL_UNIQUE;
- }
- }
- }else if( pProbe->bUnordered==0 ){
- int j;
- j = (pc.plan.nEq==pProbe->nColumn ? -1 : pProbe->aiColumn[pc.plan.nEq]);
- if( findTerm(pWC, iCur, j, p->notReady, WO_LT|WO_LE|WO_GT|WO_GE, pIdx) ){
- WhereTerm *pTop, *pBtm;
- pTop = findTerm(pWC, iCur, j, p->notReady, WO_LT|WO_LE, pIdx);
- pBtm = findTerm(pWC, iCur, j, p->notReady, WO_GT|WO_GE, pIdx);
- whereRangeScanEst(pParse, pProbe, pc.plan.nEq, pBtm, pTop, &rangeDiv);
- if( pTop ){
- nBound = 1;
- pc.plan.wsFlags |= WHERE_TOP_LIMIT;
- pc.used |= pTop->prereqRight;
- testcase( pTop->pWC!=pWC );
- }
- if( pBtm ){
- nBound++;
- pc.plan.wsFlags |= WHERE_BTM_LIMIT;
- pc.used |= pBtm->prereqRight;
- testcase( pBtm->pWC!=pWC );
- }
- pc.plan.wsFlags |= (WHERE_COLUMN_RANGE|WHERE_ROWID_RANGE);
- }
- }
-
- /* If there is an ORDER BY clause and the index being considered will
- ** naturally scan rows in the required order, set the appropriate flags
- ** in pc.plan.wsFlags. Otherwise, if there is an ORDER BY clause but
- ** the index will scan rows in a different order, set the bSort
- ** variable. */
- if( bSort && (pSrc->jointype & JT_LEFT)==0 ){
- int bRev = 2;
- int bObUnique = 0;
- WHERETRACE((" --> before isSortIndex: nPriorSat=%d\n",nPriorSat));
- pc.plan.nOBSat = isSortingIndex(p, pProbe, iCur, &bRev, &bObUnique);
- WHERETRACE((" --> after isSortIndex: bRev=%d bObU=%d nOBSat=%d\n",
- bRev, bObUnique, pc.plan.nOBSat));
- if( nPriorSat<pc.plan.nOBSat || (pc.plan.wsFlags & WHERE_ALL_UNIQUE)!=0 ){
- pc.plan.wsFlags |= WHERE_ORDERED;
- if( bObUnique ) pc.plan.wsFlags |= WHERE_OB_UNIQUE;
- }
- if( nOrderBy==pc.plan.nOBSat ){
- bSort = 0;
- pc.plan.wsFlags |= WHERE_ROWID_RANGE|WHERE_COLUMN_RANGE;
- }
- if( bRev & 1 ) pc.plan.wsFlags |= WHERE_REVERSE;
- }
-
- /* If there is a DISTINCT qualifier and this index will scan rows in
- ** order of the DISTINCT expressions, clear bDist and set the appropriate
- ** flags in pc.plan.wsFlags. */
- if( bDist
- && isDistinctIndex(pParse, pWC, pProbe, iCur, p->pDistinct, pc.plan.nEq)
- && (pc.plan.wsFlags & WHERE_COLUMN_IN)==0
- ){
- bDist = 0;
- pc.plan.wsFlags |= WHERE_ROWID_RANGE|WHERE_COLUMN_RANGE|WHERE_DISTINCT;
- }
-
- /* If currently calculating the cost of using an index (not the IPK
- ** index), determine if all required column data may be obtained without
- ** using the main table (i.e. if the index is a covering
- ** index for this query). If it is, set the WHERE_IDX_ONLY flag in
- ** pc.plan.wsFlags. Otherwise, set the bLookup variable to true. */
- if( pIdx ){
- Bitmask m = pSrc->colUsed;
- int j;
- for(j=0; j<pIdx->nColumn; j++){
- int x = pIdx->aiColumn[j];
- if( x<BMS-1 ){
- m &= ~(((Bitmask)1)<<x);
- }
- }
- if( m==0 ){
- pc.plan.wsFlags |= WHERE_IDX_ONLY;
- }else{
- bLookup = 1;
- }
- }
-
- /*
- ** Estimate the number of rows of output. For an "x IN (SELECT...)"
- ** constraint, do not let the estimate exceed half the rows in the table.
- */
- pc.plan.nRow = (double)(aiRowEst[pc.plan.nEq] * nInMul);
- if( bInEst && pc.plan.nRow*2>aiRowEst[0] ){
- pc.plan.nRow = aiRowEst[0]/2;
- nInMul = (int)(pc.plan.nRow / aiRowEst[pc.plan.nEq]);
- }
-
-#ifdef SQLITE_ENABLE_STAT3
- /* If the constraint is of the form x=VALUE or x IN (E1,E2,...)
- ** and we do not think that values of x are unique and if histogram
- ** data is available for column x, then it might be possible
- ** to get a better estimate on the number of rows based on
- ** VALUE and how common that value is according to the histogram.
- */
- if( pc.plan.nRow>(double)1 && pc.plan.nEq==1
- && pFirstTerm!=0 && aiRowEst[1]>1 ){
- assert( (pFirstTerm->eOperator & (WO_EQ|WO_ISNULL|WO_IN))!=0 );
- if( pFirstTerm->eOperator & (WO_EQ|WO_ISNULL) ){
- testcase( pFirstTerm->eOperator & WO_EQ );
- testcase( pFirstTerm->eOperator & WO_EQUIV );
- testcase( pFirstTerm->eOperator & WO_ISNULL );
- whereEqualScanEst(pParse, pProbe, pFirstTerm->pExpr->pRight,
- &pc.plan.nRow);
- }else if( bInEst==0 ){
- assert( pFirstTerm->eOperator & WO_IN );
- whereInScanEst(pParse, pProbe, pFirstTerm->pExpr->x.pList,
- &pc.plan.nRow);
- }
- }
-#endif /* SQLITE_ENABLE_STAT3 */
-
- /* Adjust the number of output rows and downward to reflect rows
- ** that are excluded by range constraints.
- */
- pc.plan.nRow = pc.plan.nRow/rangeDiv;
- if( pc.plan.nRow<1 ) pc.plan.nRow = 1;
-
- /* Experiments run on real SQLite databases show that the time needed
- ** to do a binary search to locate a row in a table or index is roughly
- ** log10(N) times the time to move from one row to the next row within
- ** a table or index. The actual times can vary, with the size of
- ** records being an important factor. Both moves and searches are
- ** slower with larger records, presumably because fewer records fit
- ** on one page and hence more pages have to be fetched.
- **
- ** The ANALYZE command and the sqlite_stat1 and sqlite_stat3 tables do
- ** not give us data on the relative sizes of table and index records.
- ** So this computation assumes table records are about twice as big
- ** as index records
- */
- if( (pc.plan.wsFlags&~(WHERE_REVERSE|WHERE_ORDERED|WHERE_OB_UNIQUE))
- ==WHERE_IDX_ONLY
- && (pWC->wctrlFlags & WHERE_ONEPASS_DESIRED)==0
- && sqlite3GlobalConfig.bUseCis
- && OptimizationEnabled(pParse->db, SQLITE_CoverIdxScan)
- ){
- /* This index is not useful for indexing, but it is a covering index.
- ** A full-scan of the index might be a little faster than a full-scan
- ** of the table, so give this case a cost slightly less than a table
- ** scan. */
- pc.rCost = aiRowEst[0]*3 + pProbe->nColumn;
- pc.plan.wsFlags |= WHERE_COVER_SCAN|WHERE_COLUMN_RANGE;
- }else if( (pc.plan.wsFlags & WHERE_NOT_FULLSCAN)==0 ){
- /* The cost of a full table scan is a number of move operations equal
- ** to the number of rows in the table.
- **
- ** We add an additional 4x penalty to full table scans. This causes
- ** the cost function to err on the side of choosing an index over
- ** choosing a full scan. This 4x full-scan penalty is an arguable
- ** decision and one which we expect to revisit in the future. But
- ** it seems to be working well enough at the moment.
- */
- pc.rCost = aiRowEst[0]*4;
- pc.plan.wsFlags &= ~WHERE_IDX_ONLY;
- if( pIdx ){
- pc.plan.wsFlags &= ~WHERE_ORDERED;
- pc.plan.nOBSat = nPriorSat;
- }
- }else{
- log10N = estLog(aiRowEst[0]);
- pc.rCost = pc.plan.nRow;
- if( pIdx ){
- if( bLookup ){
- /* For an index lookup followed by a table lookup:
- ** nInMul index searches to find the start of each index range
- ** + nRow steps through the index
- ** + nRow table searches to lookup the table entry using the rowid
- */
- pc.rCost += (nInMul + pc.plan.nRow)*log10N;
- }else{
- /* For a covering index:
- ** nInMul index searches to find the initial entry
- ** + nRow steps through the index
- */
- pc.rCost += nInMul*log10N;
- }
- }else{
- /* For a rowid primary key lookup:
- ** nInMult table searches to find the initial entry for each range
- ** + nRow steps through the table
- */
- pc.rCost += nInMul*log10N;
- }
- }
-
- /* Add in the estimated cost of sorting the result. Actual experimental
- ** measurements of sorting performance in SQLite show that sorting time
- ** adds C*N*log10(N) to the cost, where N is the number of rows to be
- ** sorted and C is a factor between 1.95 and 4.3. We will split the
- ** difference and select C of 3.0.
- */
- if( bSort ){
- double m = estLog(pc.plan.nRow*(nOrderBy - pc.plan.nOBSat)/nOrderBy);
- m *= (double)(pc.plan.nOBSat ? 2 : 3);
- pc.rCost += pc.plan.nRow*m;
- }
- if( bDist ){
- pc.rCost += pc.plan.nRow*estLog(pc.plan.nRow)*3;
- }
-
- /**** Cost of using this index has now been computed ****/
-
- /* If there are additional constraints on this table that cannot
- ** be used with the current index, but which might lower the number
- ** of output rows, adjust the nRow value accordingly. This only
- ** matters if the current index is the least costly, so do not bother
- ** with this step if we already know this index will not be chosen.
- ** Also, never reduce the output row count below 2 using this step.
- **
- ** It is critical that the notValid mask be used here instead of
- ** the notReady mask. When computing an "optimal" index, the notReady
- ** mask will only have one bit set - the bit for the current table.
- ** The notValid mask, on the other hand, always has all bits set for
- ** tables that are not in outer loops. If notReady is used here instead
- ** of notValid, then a optimal index that depends on inner joins loops
- ** might be selected even when there exists an optimal index that has
- ** no such dependency.
- */
- if( pc.plan.nRow>2 && pc.rCost<=p->cost.rCost ){
- int k; /* Loop counter */
- int nSkipEq = pc.plan.nEq; /* Number of == constraints to skip */
- int nSkipRange = nBound; /* Number of < constraints to skip */
- Bitmask thisTab; /* Bitmap for pSrc */
-
- thisTab = getMask(pWC->pMaskSet, iCur);
- for(pTerm=pWC->a, k=pWC->nTerm; pc.plan.nRow>2 && k; k--, pTerm++){
- if( pTerm->wtFlags & TERM_VIRTUAL ) continue;
- if( (pTerm->prereqAll & p->notValid)!=thisTab ) continue;
- if( pTerm->eOperator & (WO_EQ|WO_IN|WO_ISNULL) ){
- if( nSkipEq ){
- /* Ignore the first pc.plan.nEq equality matches since the index
- ** has already accounted for these */
- nSkipEq--;
- }else{
- /* Assume each additional equality match reduces the result
- ** set size by a factor of 10 */
- pc.plan.nRow /= 10;
- }
- }else if( pTerm->eOperator & (WO_LT|WO_LE|WO_GT|WO_GE) ){
- if( nSkipRange ){
- /* Ignore the first nSkipRange range constraints since the index
- ** has already accounted for these */
- nSkipRange--;
- }else{
- /* Assume each additional range constraint reduces the result
- ** set size by a factor of 3. Indexed range constraints reduce
- ** the search space by a larger factor: 4. We make indexed range
- ** more selective intentionally because of the subjective
- ** observation that indexed range constraints really are more
- ** selective in practice, on average. */
- pc.plan.nRow /= 3;
- }
- }else if( (pTerm->eOperator & WO_NOOP)==0 ){
- /* Any other expression lowers the output row count by half */
- pc.plan.nRow /= 2;
- }
- }
- if( pc.plan.nRow<2 ) pc.plan.nRow = 2;
- }
-
-
- WHERETRACE((
- " nEq=%d nInMul=%d rangeDiv=%d bSort=%d bLookup=%d wsFlags=0x%08x\n"
- " notReady=0x%llx log10N=%.1f nRow=%.1f cost=%.1f\n"
- " used=0x%llx nOBSat=%d\n",
- pc.plan.nEq, nInMul, (int)rangeDiv, bSort, bLookup, pc.plan.wsFlags,
- p->notReady, log10N, pc.plan.nRow, pc.rCost, pc.used,
- pc.plan.nOBSat
- ));
-
- /* If this index is the best we have seen so far, then record this
- ** index and its cost in the p->cost structure.
- */
- if( (!pIdx || pc.plan.wsFlags) && compareCost(&pc, &p->cost) ){
- p->cost = pc;
- p->cost.plan.wsFlags &= wsFlagMask;
- p->cost.plan.u.pIdx = pIdx;
- }
-
- /* If there was an INDEXED BY clause, then only that one index is
- ** considered. */
- if( pSrc->pIndex ) break;
-
- /* Reset masks for the next index in the loop */
- wsFlagMask = ~(WHERE_ROWID_EQ|WHERE_ROWID_RANGE);
- eqTermMask = idxEqTermMask;
- }
-
- /* If there is no ORDER BY clause and the SQLITE_ReverseOrder flag
- ** is set, then reverse the order that the index will be scanned
- ** in. This is used for application testing, to help find cases
- ** where application behavior depends on the (undefined) order that
- ** SQLite outputs rows in in the absence of an ORDER BY clause. */
- if( !p->pOrderBy && pParse->db->flags & SQLITE_ReverseOrder ){
- p->cost.plan.wsFlags |= WHERE_REVERSE;
- }
-
- assert( p->pOrderBy || (p->cost.plan.wsFlags&WHERE_ORDERED)==0 );
- assert( p->cost.plan.u.pIdx==0 || (p->cost.plan.wsFlags&WHERE_ROWID_EQ)==0 );
- assert( pSrc->pIndex==0
- || p->cost.plan.u.pIdx==0
- || p->cost.plan.u.pIdx==pSrc->pIndex
- );
-
- WHERETRACE((" best index is %s cost=%.1f\n",
- p->cost.plan.u.pIdx ? p->cost.plan.u.pIdx->zName : "ipk",
- p->cost.rCost));
-
- bestOrClauseIndex(p);
- bestAutomaticIndex(p);
- p->cost.plan.wsFlags |= eqTermMask;
-}
-
-/*
-** Find the query plan for accessing table pSrc->pTab. Write the
-** best query plan and its cost into the WhereCost object supplied
-** as the last parameter. This function may calculate the cost of
-** both real and virtual table scans.
-**
-** This function does not take ORDER BY or DISTINCT into account. Nor
-** does it remember the virtual table query plan. All it does is compute
-** the cost while determining if an OR optimization is applicable. The
-** details will be reconsidered later if the optimization is found to be
-** applicable.
-*/
-static void bestIndex(WhereBestIdx *p){
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- if( IsVirtual(p->pSrc->pTab) ){
- sqlite3_index_info *pIdxInfo = 0;
- p->ppIdxInfo = &pIdxInfo;
- bestVirtualIndex(p);
- assert( pIdxInfo!=0 || p->pParse->db->mallocFailed );
- if( pIdxInfo && pIdxInfo->needToFreeIdxStr ){
- sqlite3_free(pIdxInfo->idxStr);
- }
- sqlite3DbFree(p->pParse->db, pIdxInfo);
- }else
-#endif
- {
- bestBtreeIndex(p);
- }
-}
-
-/*
** Disable a term in the WHERE clause. Except, do not disable the term
** if it controls a LEFT OUTER JOIN and it did not originate in the ON
** or USING clause of that join.
@@ -108157,9 +107622,6 @@ static void bestIndex(WhereBestIdx *p){
** in the ON clause. The term is disabled in (3) because it is not part
** of a LEFT OUTER JOIN. In (1), the term is not disabled.
**
-** IMPLEMENTATION-OF: R-24597-58655 No tests are done for terms that are
-** completely satisfied by indices.
-**
** Disabling a term causes that term to not be tested in the inner loop
** of the join. Disabling is an optimization. When terms are satisfied
** by indices, we disable them to prevent redundant tests in the inner
@@ -108239,6 +107701,7 @@ static int codeEqualityTerm(
WhereTerm *pTerm, /* The term of the WHERE clause to be coded */
WhereLevel *pLevel, /* The level of the FROM clause we are working on */
int iEq, /* Index of the equality term within this level */
+ int bRev, /* True for reverse-order IN operations */
int iTarget /* Attempt to leave results in this register */
){
Expr *pX = pTerm->pExpr;
@@ -108256,14 +107719,13 @@ static int codeEqualityTerm(
int eType;
int iTab;
struct InLoop *pIn;
- u8 bRev = (pLevel->plan.wsFlags & WHERE_REVERSE)!=0;
+ WhereLoop *pLoop = pLevel->pWLoop;
- if( (pLevel->plan.wsFlags & WHERE_INDEXED)!=0
- && pLevel->plan.u.pIdx->aSortOrder[iEq]
+ if( (pLoop->wsFlags & WHERE_VIRTUALTABLE)==0
+ && pLoop->u.btree.pIndex!=0
+ && pLoop->u.btree.pIndex->aSortOrder[iEq]
){
testcase( iEq==0 );
- testcase( iEq==pLevel->plan.u.pIdx->nColumn-1 );
- testcase( iEq>0 && iEq+1<pLevel->plan.u.pIdx->nColumn );
testcase( bRev );
bRev = !bRev;
}
@@ -108276,7 +107738,8 @@ static int codeEqualityTerm(
}
iTab = pX->iTable;
sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iTab, 0);
- assert( pLevel->plan.wsFlags & WHERE_IN_ABLE );
+ assert( (pLoop->wsFlags & WHERE_MULTI_OR)==0 );
+ pLoop->wsFlags |= WHERE_IN_ABLE;
if( pLevel->u.in.nIn==0 ){
pLevel->addrNxt = sqlite3VdbeMakeLabel(v);
}
@@ -108346,29 +107809,31 @@ static int codeEqualityTerm(
static int codeAllEqualityTerms(
Parse *pParse, /* Parsing context */
WhereLevel *pLevel, /* Which nested loop of the FROM we are coding */
- WhereClause *pWC, /* The WHERE clause */
- Bitmask notReady, /* Which parts of FROM have not yet been coded */
+ int bRev, /* Reverse the order of IN operators */
int nExtraReg, /* Number of extra registers to allocate */
char **pzAff /* OUT: Set to point to affinity string */
){
- int nEq = pLevel->plan.nEq; /* The number of == or IN constraints to code */
+ int nEq; /* The number of == or IN constraints to code */
Vdbe *v = pParse->pVdbe; /* The vm under construction */
Index *pIdx; /* The index being used for this loop */
- int iCur = pLevel->iTabCur; /* The cursor of the table */
WhereTerm *pTerm; /* A single constraint term */
+ WhereLoop *pLoop; /* The WhereLoop object */
int j; /* Loop counter */
int regBase; /* Base register */
int nReg; /* Number of registers to allocate */
char *zAff; /* Affinity string to return */
/* This module is only called on query plans that use an index. */
- assert( pLevel->plan.wsFlags & WHERE_INDEXED );
- pIdx = pLevel->plan.u.pIdx;
+ pLoop = pLevel->pWLoop;
+ assert( (pLoop->wsFlags & WHERE_VIRTUALTABLE)==0 );
+ nEq = pLoop->u.btree.nEq;
+ pIdx = pLoop->u.btree.pIndex;
+ assert( pIdx!=0 );
/* Figure out how many memory cells we will need then allocate them.
*/
regBase = pParse->nMem + 1;
- nReg = pLevel->plan.nEq + nExtraReg;
+ nReg = pLoop->u.btree.nEq + nExtraReg;
pParse->nMem += nReg;
zAff = sqlite3DbStrDup(pParse->db, sqlite3IndexAffinityStr(v, pIdx));
@@ -108378,17 +107843,16 @@ static int codeAllEqualityTerms(
/* Evaluate the equality constraints
*/
- assert( pIdx->nColumn>=nEq );
+ assert( zAff==0 || strlen(zAff)>=nEq );
for(j=0; j<nEq; j++){
int r1;
- int k = pIdx->aiColumn[j];
- pTerm = findTerm(pWC, iCur, k, notReady, pLevel->plan.wsFlags, pIdx);
- if( pTerm==0 ) break;
+ pTerm = pLoop->aLTerm[j];
+ assert( pTerm!=0 );
/* The following true for indices with redundant columns.
** Ex: CREATE INDEX i1 ON t1(a,b,a); SELECT * FROM t1 WHERE a=0 AND b=0; */
testcase( (pTerm->wtFlags & TERM_CODED)!=0 );
- testcase( pTerm->wtFlags & TERM_VIRTUAL ); /* EV: R-30575-11662 */
- r1 = codeEqualityTerm(pParse, pTerm, pLevel, j, regBase+j);
+ testcase( pTerm->wtFlags & TERM_VIRTUAL );
+ r1 = codeEqualityTerm(pParse, pTerm, pLevel, j, bRev, regBase+j);
if( r1!=regBase+j ){
if( nReg==1 ){
sqlite3ReleaseTempReg(pParse, regBase);
@@ -108456,31 +107920,31 @@ static void explainAppendTerm(
** It is the responsibility of the caller to free the buffer when it is
** no longer required.
*/
-static char *explainIndexRange(sqlite3 *db, WhereLevel *pLevel, Table *pTab){
- WherePlan *pPlan = &pLevel->plan;
- Index *pIndex = pPlan->u.pIdx;
- int nEq = pPlan->nEq;
+static char *explainIndexRange(sqlite3 *db, WhereLoop *pLoop, Table *pTab){
+ Index *pIndex = pLoop->u.btree.pIndex;
+ int nEq = pLoop->u.btree.nEq;
int i, j;
Column *aCol = pTab->aCol;
int *aiColumn = pIndex->aiColumn;
StrAccum txt;
- if( nEq==0 && (pPlan->wsFlags & (WHERE_BTM_LIMIT|WHERE_TOP_LIMIT))==0 ){
+ if( nEq==0 && (pLoop->wsFlags & (WHERE_BTM_LIMIT|WHERE_TOP_LIMIT))==0 ){
return 0;
}
sqlite3StrAccumInit(&txt, 0, 0, SQLITE_MAX_LENGTH);
txt.db = db;
sqlite3StrAccumAppend(&txt, " (", 2);
for(i=0; i<nEq; i++){
- explainAppendTerm(&txt, i, aCol[aiColumn[i]].zName, "=");
+ char *z = (i==pIndex->nColumn ) ? "rowid" : aCol[aiColumn[i]].zName;
+ explainAppendTerm(&txt, i, z, "=");
}
j = i;
- if( pPlan->wsFlags&WHERE_BTM_LIMIT ){
+ if( pLoop->wsFlags&WHERE_BTM_LIMIT ){
char *z = (j==pIndex->nColumn ) ? "rowid" : aCol[aiColumn[j]].zName;
explainAppendTerm(&txt, i++, z, ">");
}
- if( pPlan->wsFlags&WHERE_TOP_LIMIT ){
+ if( pLoop->wsFlags&WHERE_TOP_LIMIT ){
char *z = (j==pIndex->nColumn ) ? "rowid" : aCol[aiColumn[j]].zName;
explainAppendTerm(&txt, i, z, "<");
}
@@ -108503,20 +107967,22 @@ static void explainOneScan(
u16 wctrlFlags /* Flags passed to sqlite3WhereBegin() */
){
if( pParse->explain==2 ){
- u32 flags = pLevel->plan.wsFlags;
struct SrcList_item *pItem = &pTabList->a[pLevel->iFrom];
Vdbe *v = pParse->pVdbe; /* VM being constructed */
sqlite3 *db = pParse->db; /* Database handle */
char *zMsg; /* Text to add to EQP output */
- sqlite3_int64 nRow; /* Expected number of rows visited by scan */
int iId = pParse->iSelectId; /* Select id (left-most output column) */
int isSearch; /* True for a SEARCH. False for SCAN. */
+ WhereLoop *pLoop; /* The controlling WhereLoop object */
+ u32 flags; /* Flags that describe this loop */
+ pLoop = pLevel->pWLoop;
+ flags = pLoop->wsFlags;
if( (flags&WHERE_MULTI_OR) || (wctrlFlags&WHERE_ONETABLE_ONLY) ) return;
- isSearch = (pLevel->plan.nEq>0)
- || (flags&(WHERE_BTM_LIMIT|WHERE_TOP_LIMIT))!=0
- || (wctrlFlags&(WHERE_ORDERBY_MIN|WHERE_ORDERBY_MAX));
+ isSearch = (flags&(WHERE_BTM_LIMIT|WHERE_TOP_LIMIT))!=0
+ || ((flags&WHERE_VIRTUALTABLE)==0 && (pLoop->u.btree.nEq>0))
+ || (wctrlFlags&(WHERE_ORDERBY_MIN|WHERE_ORDERBY_MAX));
zMsg = sqlite3MPrintf(db, "%s", isSearch?"SEARCH":"SCAN");
if( pItem->pSelect ){
@@ -108528,43 +107994,37 @@ static void explainOneScan(
if( pItem->zAlias ){
zMsg = sqlite3MAppendf(db, zMsg, "%s AS %s", zMsg, pItem->zAlias);
}
- if( (flags & WHERE_INDEXED)!=0 ){
- char *zWhere = explainIndexRange(db, pLevel, pItem->pTab);
- zMsg = sqlite3MAppendf(db, zMsg, "%s USING %s%sINDEX%s%s%s", zMsg,
- ((flags & WHERE_TEMP_INDEX)?"AUTOMATIC ":""),
- ((flags & WHERE_IDX_ONLY)?"COVERING ":""),
- ((flags & WHERE_TEMP_INDEX)?"":" "),
- ((flags & WHERE_TEMP_INDEX)?"": pLevel->plan.u.pIdx->zName),
- zWhere
- );
+ if( (flags & (WHERE_IPK|WHERE_VIRTUALTABLE))==0
+ && ALWAYS(pLoop->u.btree.pIndex!=0)
+ ){
+ char *zWhere = explainIndexRange(db, pLoop, pItem->pTab);
+ zMsg = sqlite3MAppendf(db, zMsg,
+ ((flags & WHERE_AUTO_INDEX) ?
+ "%s USING AUTOMATIC %sINDEX%.0s%s" :
+ "%s USING %sINDEX %s%s"),
+ zMsg, ((flags & WHERE_IDX_ONLY) ? "COVERING " : ""),
+ pLoop->u.btree.pIndex->zName, zWhere);
sqlite3DbFree(db, zWhere);
- }else if( flags & (WHERE_ROWID_EQ|WHERE_ROWID_RANGE) ){
+ }else if( (flags & WHERE_IPK)!=0 && (flags & WHERE_CONSTRAINT)!=0 ){
zMsg = sqlite3MAppendf(db, zMsg, "%s USING INTEGER PRIMARY KEY", zMsg);
- if( flags&WHERE_ROWID_EQ ){
+ if( flags&(WHERE_COLUMN_EQ|WHERE_COLUMN_IN) ){
zMsg = sqlite3MAppendf(db, zMsg, "%s (rowid=?)", zMsg);
}else if( (flags&WHERE_BOTH_LIMIT)==WHERE_BOTH_LIMIT ){
zMsg = sqlite3MAppendf(db, zMsg, "%s (rowid>? AND rowid<?)", zMsg);
}else if( flags&WHERE_BTM_LIMIT ){
zMsg = sqlite3MAppendf(db, zMsg, "%s (rowid>?)", zMsg);
- }else if( flags&WHERE_TOP_LIMIT ){
+ }else if( ALWAYS(flags&WHERE_TOP_LIMIT) ){
zMsg = sqlite3MAppendf(db, zMsg, "%s (rowid<?)", zMsg);
}
}
#ifndef SQLITE_OMIT_VIRTUALTABLE
else if( (flags & WHERE_VIRTUALTABLE)!=0 ){
- sqlite3_index_info *pVtabIdx = pLevel->plan.u.pVtabIdx;
zMsg = sqlite3MAppendf(db, zMsg, "%s VIRTUAL TABLE INDEX %d:%s", zMsg,
- pVtabIdx->idxNum, pVtabIdx->idxStr);
+ pLoop->u.vtab.idxNum, pLoop->u.vtab.idxStr);
}
#endif
- if( wctrlFlags&(WHERE_ORDERBY_MIN|WHERE_ORDERBY_MAX) ){
- testcase( wctrlFlags & WHERE_ORDERBY_MIN );
- nRow = 1;
- }else{
- nRow = (sqlite3_int64)pLevel->plan.nRow;
- }
- zMsg = sqlite3MAppendf(db, zMsg, "%s (~%lld rows)", zMsg, nRow);
+ zMsg = sqlite3MAppendf(db, zMsg, "%s", zMsg);
sqlite3VdbeAddOp4(v, OP_Explain, iId, iLevel, iFrom, zMsg, P4_DYNAMIC);
}
}
@@ -108580,7 +108040,6 @@ static void explainOneScan(
static Bitmask codeOneLoopStart(
WhereInfo *pWInfo, /* Complete information about the WHERE clause */
int iLevel, /* Which level of pWInfo->a[] should be coded */
- u16 wctrlFlags, /* One of the WHERE_* flags defined in sqliteInt.h */
Bitmask notReady /* Which tables are currently available */
){
int j, k; /* Loop counters */
@@ -108589,9 +108048,11 @@ static Bitmask codeOneLoopStart(
int omitTable; /* True if we use the index only */
int bRev; /* True if we need to scan in reverse order */
WhereLevel *pLevel; /* The where level to be coded */
+ WhereLoop *pLoop; /* The WhereLoop object being coded */
WhereClause *pWC; /* Decomposition of the entire WHERE clause */
WhereTerm *pTerm; /* A WHERE clause term */
Parse *pParse; /* Parsing context */
+ sqlite3 *db; /* Database connection */
Vdbe *v; /* The prepared stmt under constructions */
struct SrcList_item *pTabItem; /* FROM clause term being coded */
int addrBrk; /* Jump here to break out of the loop */
@@ -108602,13 +108063,15 @@ static Bitmask codeOneLoopStart(
pParse = pWInfo->pParse;
v = pParse->pVdbe;
- pWC = pWInfo->pWC;
+ pWC = &pWInfo->sWC;
+ db = pParse->db;
pLevel = &pWInfo->a[iLevel];
+ pLoop = pLevel->pWLoop;
pTabItem = &pWInfo->pTabList->a[pLevel->iFrom];
iCur = pTabItem->iCursor;
- bRev = (pLevel->plan.wsFlags & WHERE_REVERSE)!=0;
- omitTable = (pLevel->plan.wsFlags & WHERE_IDX_ONLY)!=0
- && (wctrlFlags & WHERE_FORCE_TABLE)==0;
+ bRev = (pWInfo->revMask>>iLevel)&1;
+ omitTable = (pLoop->wsFlags & WHERE_IDX_ONLY)!=0
+ && (pWInfo->wctrlFlags & WHERE_FORCE_TABLE)==0;
VdbeNoopComment((v, "Begin Join Loop %d", iLevel));
/* Create labels for the "break" and "continue" instructions
@@ -108645,47 +108108,37 @@ static Bitmask codeOneLoopStart(
}else
#ifndef SQLITE_OMIT_VIRTUALTABLE
- if( (pLevel->plan.wsFlags & WHERE_VIRTUALTABLE)!=0 ){
- /* Case 0: The table is a virtual-table. Use the VFilter and VNext
+ if( (pLoop->wsFlags & WHERE_VIRTUALTABLE)!=0 ){
+ /* Case 1: The table is a virtual-table. Use the VFilter and VNext
** to access the data.
*/
int iReg; /* P3 Value for OP_VFilter */
int addrNotFound;
- sqlite3_index_info *pVtabIdx = pLevel->plan.u.pVtabIdx;
- int nConstraint = pVtabIdx->nConstraint;
- struct sqlite3_index_constraint_usage *aUsage =
- pVtabIdx->aConstraintUsage;
- const struct sqlite3_index_constraint *aConstraint =
- pVtabIdx->aConstraint;
+ int nConstraint = pLoop->nLTerm;
sqlite3ExprCachePush(pParse);
iReg = sqlite3GetTempRange(pParse, nConstraint+2);
addrNotFound = pLevel->addrBrk;
- for(j=1; j<=nConstraint; j++){
- for(k=0; k<nConstraint; k++){
- if( aUsage[k].argvIndex==j ){
- int iTarget = iReg+j+1;
- pTerm = &pWC->a[aConstraint[k].iTermOffset];
- if( pTerm->eOperator & WO_IN ){
- codeEqualityTerm(pParse, pTerm, pLevel, k, iTarget);
- addrNotFound = pLevel->addrNxt;
- }else{
- sqlite3ExprCode(pParse, pTerm->pExpr->pRight, iTarget);
- }
- break;
- }
+ for(j=0; j<nConstraint; j++){
+ int iTarget = iReg+j+2;
+ pTerm = pLoop->aLTerm[j];
+ if( pTerm==0 ) continue;
+ if( pTerm->eOperator & WO_IN ){
+ codeEqualityTerm(pParse, pTerm, pLevel, j, bRev, iTarget);
+ addrNotFound = pLevel->addrNxt;
+ }else{
+ sqlite3ExprCode(pParse, pTerm->pExpr->pRight, iTarget);
}
- if( k==nConstraint ) break;
}
- sqlite3VdbeAddOp2(v, OP_Integer, pVtabIdx->idxNum, iReg);
- sqlite3VdbeAddOp2(v, OP_Integer, j-1, iReg+1);
- sqlite3VdbeAddOp4(v, OP_VFilter, iCur, addrNotFound, iReg, pVtabIdx->idxStr,
- pVtabIdx->needToFreeIdxStr ? P4_MPRINTF : P4_STATIC);
- pVtabIdx->needToFreeIdxStr = 0;
- for(j=0; j<nConstraint; j++){
- if( aUsage[j].omit ){
- int iTerm = aConstraint[j].iTermOffset;
- disableTerm(pLevel, &pWC->a[iTerm]);
+ sqlite3VdbeAddOp2(v, OP_Integer, pLoop->u.vtab.idxNum, iReg);
+ sqlite3VdbeAddOp2(v, OP_Integer, nConstraint, iReg+1);
+ sqlite3VdbeAddOp4(v, OP_VFilter, iCur, addrNotFound, iReg,
+ pLoop->u.vtab.idxStr,
+ pLoop->u.vtab.needFree ? P4_MPRINTF : P4_STATIC);
+ pLoop->u.vtab.needFree = 0;
+ for(j=0; j<nConstraint && j<16; j++){
+ if( (pLoop->u.vtab.omitMask>>j)&1 ){
+ disableTerm(pLevel, pLoop->aLTerm[j]);
}
}
pLevel->op = OP_VNext;
@@ -108696,19 +108149,22 @@ static Bitmask codeOneLoopStart(
}else
#endif /* SQLITE_OMIT_VIRTUALTABLE */
- if( pLevel->plan.wsFlags & WHERE_ROWID_EQ ){
- /* Case 1: We can directly reference a single row using an
+ if( (pLoop->wsFlags & WHERE_IPK)!=0
+ && (pLoop->wsFlags & (WHERE_COLUMN_IN|WHERE_COLUMN_EQ))!=0
+ ){
+ /* Case 2: We can directly reference a single row using an
** equality comparison against the ROWID field. Or
** we reference multiple rows using a "rowid IN (...)"
** construct.
*/
+ assert( pLoop->u.btree.nEq==1 );
iReleaseReg = sqlite3GetTempReg(pParse);
- pTerm = findTerm(pWC, iCur, -1, notReady, WO_EQ|WO_IN, 0);
+ pTerm = pLoop->aLTerm[0];
assert( pTerm!=0 );
assert( pTerm->pExpr!=0 );
assert( omitTable==0 );
- testcase( pTerm->wtFlags & TERM_VIRTUAL ); /* EV: R-30575-11662 */
- iRowidReg = codeEqualityTerm(pParse, pTerm, pLevel, 0, iReleaseReg);
+ testcase( pTerm->wtFlags & TERM_VIRTUAL );
+ iRowidReg = codeEqualityTerm(pParse, pTerm, pLevel, 0, bRev, iReleaseReg);
addrNxt = pLevel->addrNxt;
sqlite3VdbeAddOp2(v, OP_MustBeInt, iRowidReg, addrNxt);
sqlite3VdbeAddOp3(v, OP_NotExists, iCur, addrNxt, iRowidReg);
@@ -108716,8 +108172,10 @@ static Bitmask codeOneLoopStart(
sqlite3ExprCacheStore(pParse, iCur, -1, iRowidReg);
VdbeComment((v, "pk"));
pLevel->op = OP_Noop;
- }else if( pLevel->plan.wsFlags & WHERE_ROWID_RANGE ){
- /* Case 2: We have an inequality comparison against the ROWID field.
+ }else if( (pLoop->wsFlags & WHERE_IPK)!=0
+ && (pLoop->wsFlags & WHERE_COLUMN_RANGE)!=0
+ ){
+ /* Case 3: We have an inequality comparison against the ROWID field.
*/
int testOp = OP_Noop;
int start;
@@ -108725,8 +108183,11 @@ static Bitmask codeOneLoopStart(
WhereTerm *pStart, *pEnd;
assert( omitTable==0 );
- pStart = findTerm(pWC, iCur, -1, notReady, WO_GT|WO_GE, 0);
- pEnd = findTerm(pWC, iCur, -1, notReady, WO_LT|WO_LE, 0);
+ j = 0;
+ pStart = pEnd = 0;
+ if( pLoop->wsFlags & WHERE_BTM_LIMIT ) pStart = pLoop->aLTerm[j++];
+ if( pLoop->wsFlags & WHERE_TOP_LIMIT ) pEnd = pLoop->aLTerm[j++];
+ assert( pStart!=0 || pEnd!=0 );
if( bRev ){
pTerm = pStart;
pStart = pEnd;
@@ -108749,10 +108210,11 @@ static Bitmask codeOneLoopStart(
assert( TK_LT==TK_GT+2 ); /* ... of the TK_xx values... */
assert( TK_GE==TK_GT+3 ); /* ... is correcct. */
- testcase( pStart->wtFlags & TERM_VIRTUAL ); /* EV: R-30575-11662 */
+ assert( (pStart->wtFlags & TERM_VNULL)==0 );
+ testcase( pStart->wtFlags & TERM_VIRTUAL );
pX = pStart->pExpr;
assert( pX!=0 );
- assert( pStart->leftCursor==iCur );
+ testcase( pStart->leftCursor!=iCur ); /* transitive constraints */
r1 = sqlite3ExprCodeTemp(pParse, pX->pRight, &rTemp);
sqlite3VdbeAddOp3(v, aMoveOp[pX->op-TK_GT], iCur, addrBrk, r1);
VdbeComment((v, "pk"));
@@ -108766,8 +108228,9 @@ static Bitmask codeOneLoopStart(
Expr *pX;
pX = pEnd->pExpr;
assert( pX!=0 );
- assert( pEnd->leftCursor==iCur );
- testcase( pEnd->wtFlags & TERM_VIRTUAL ); /* EV: R-30575-11662 */
+ assert( (pEnd->wtFlags & TERM_VNULL)==0 );
+ testcase( pEnd->leftCursor!=iCur ); /* Transitive constraints */
+ testcase( pEnd->wtFlags & TERM_VIRTUAL );
memEndValue = ++pParse->nMem;
sqlite3ExprCode(pParse, pX->pRight, memEndValue);
if( pX->op==TK_LT || pX->op==TK_GT ){
@@ -108781,11 +108244,7 @@ static Bitmask codeOneLoopStart(
pLevel->op = bRev ? OP_Prev : OP_Next;
pLevel->p1 = iCur;
pLevel->p2 = start;
- if( pStart==0 && pEnd==0 ){
- pLevel->p5 = SQLITE_STMTSTATUS_FULLSCAN_STEP;
- }else{
- assert( pLevel->p5==0 );
- }
+ assert( pLevel->p5==0 );
if( testOp!=OP_Noop ){
iRowidReg = iReleaseReg = sqlite3GetTempReg(pParse);
sqlite3VdbeAddOp2(v, OP_Rowid, iCur, iRowidReg);
@@ -108793,8 +108252,8 @@ static Bitmask codeOneLoopStart(
sqlite3VdbeAddOp3(v, testOp, memEndValue, addrBrk, iRowidReg);
sqlite3VdbeChangeP5(v, SQLITE_AFF_NUMERIC | SQLITE_JUMPIFNULL);
}
- }else if( pLevel->plan.wsFlags & (WHERE_COLUMN_RANGE|WHERE_COLUMN_EQ) ){
- /* Case 3: A scan using an index.
+ }else if( pLoop->wsFlags & WHERE_INDEXED ){
+ /* Case 4: A scan using an index.
**
** The WHERE clause may contain zero or more equality
** terms ("==" or "IN" operators) that refer to the N
@@ -108840,8 +108299,8 @@ static Bitmask codeOneLoopStart(
OP_IdxGE, /* 1: (end_constraints && !bRev) */
OP_IdxLT /* 2: (end_constraints && bRev) */
};
- int nEq = pLevel->plan.nEq; /* Number of == or IN terms */
- int isMinQuery = 0; /* If this is an optimized SELECT min(x).. */
+ int nEq = pLoop->u.btree.nEq; /* Number of == or IN terms */
+ int isMinQuery = 0; /* If this is an optimized SELECT min(x).. */
int regBase; /* Base register holding constraint values */
int r1; /* Temp register */
WhereTerm *pRangeStart = 0; /* Inequality constraint at range start */
@@ -108857,9 +108316,8 @@ static Bitmask codeOneLoopStart(
char *zStartAff; /* Affinity for start of range constraint */
char *zEndAff; /* Affinity for end of range constraint */
- pIdx = pLevel->plan.u.pIdx;
+ pIdx = pLoop->u.btree.pIndex;
iIdxCur = pLevel->iIdxCur;
- k = (nEq==pIdx->nColumn ? -1 : pIdx->aiColumn[nEq]);
/* If this loop satisfies a sort order (pOrderBy) request that
** was passed to this function to implement a "SELECT min(x) ..."
@@ -108869,8 +108327,8 @@ static Bitmask codeOneLoopStart(
** the first one after the nEq equality constraints in the index,
** this requires some special handling.
*/
- if( (wctrlFlags&WHERE_ORDERBY_MIN)!=0
- && (pLevel->plan.wsFlags&WHERE_ORDERED)
+ if( (pWInfo->wctrlFlags&WHERE_ORDERBY_MIN)!=0
+ && (pWInfo->bOBSat!=0)
&& (pIdx->nColumn>nEq)
){
/* assert( pOrderBy->nExpr==1 ); */
@@ -108882,12 +108340,13 @@ static Bitmask codeOneLoopStart(
/* Find any inequality constraint terms for the start and end
** of the range.
*/
- if( pLevel->plan.wsFlags & WHERE_TOP_LIMIT ){
- pRangeEnd = findTerm(pWC, iCur, k, notReady, (WO_LT|WO_LE), pIdx);
+ j = nEq;
+ if( pLoop->wsFlags & WHERE_BTM_LIMIT ){
+ pRangeStart = pLoop->aLTerm[j++];
nExtraReg = 1;
}
- if( pLevel->plan.wsFlags & WHERE_BTM_LIMIT ){
- pRangeStart = findTerm(pWC, iCur, k, notReady, (WO_GT|WO_GE), pIdx);
+ if( pLoop->wsFlags & WHERE_TOP_LIMIT ){
+ pRangeEnd = pLoop->aLTerm[j++];
nExtraReg = 1;
}
@@ -108895,10 +108354,8 @@ static Bitmask codeOneLoopStart(
** and store the values of those terms in an array of registers
** starting at regBase.
*/
- regBase = codeAllEqualityTerms(
- pParse, pLevel, pWC, notReady, nExtraReg, &zStartAff
- );
- zEndAff = sqlite3DbStrDup(pParse->db, zStartAff);
+ regBase = codeAllEqualityTerms(pParse,pLevel,bRev,nExtraReg,&zStartAff);
+ zEndAff = sqlite3DbStrDup(db, zStartAff);
addrNxt = pLevel->addrNxt;
/* If we are doing a reverse order scan on an ascending index, or
@@ -108911,10 +108368,10 @@ static Bitmask codeOneLoopStart(
SWAP(WhereTerm *, pRangeEnd, pRangeStart);
}
- testcase( pRangeStart && pRangeStart->eOperator & WO_LE );
- testcase( pRangeStart && pRangeStart->eOperator & WO_GE );
- testcase( pRangeEnd && pRangeEnd->eOperator & WO_LE );
- testcase( pRangeEnd && pRangeEnd->eOperator & WO_GE );
+ testcase( pRangeStart && (pRangeStart->eOperator & WO_LE)!=0 );
+ testcase( pRangeStart && (pRangeStart->eOperator & WO_GE)!=0 );
+ testcase( pRangeEnd && (pRangeEnd->eOperator & WO_LE)!=0 );
+ testcase( pRangeEnd && (pRangeEnd->eOperator & WO_GE)!=0 );
startEq = !pRangeStart || pRangeStart->eOperator & (WO_LE|WO_GE);
endEq = !pRangeEnd || pRangeEnd->eOperator & (WO_LE|WO_GE);
start_constraints = pRangeStart || nEq>0;
@@ -108939,7 +108396,7 @@ static Bitmask codeOneLoopStart(
}
}
nConstraint++;
- testcase( pRangeStart->wtFlags & TERM_VIRTUAL ); /* EV: R-30575-11662 */
+ testcase( pRangeStart->wtFlags & TERM_VIRTUAL );
}else if( isMinQuery ){
sqlite3VdbeAddOp2(v, OP_Null, 0, regBase+nEq);
nConstraint++;
@@ -108981,10 +108438,10 @@ static Bitmask codeOneLoopStart(
}
codeApplyAffinity(pParse, regBase, nEq+1, zEndAff);
nConstraint++;
- testcase( pRangeEnd->wtFlags & TERM_VIRTUAL ); /* EV: R-30575-11662 */
+ testcase( pRangeEnd->wtFlags & TERM_VIRTUAL );
}
- sqlite3DbFree(pParse->db, zStartAff);
- sqlite3DbFree(pParse->db, zEndAff);
+ sqlite3DbFree(db, zStartAff);
+ sqlite3DbFree(db, zEndAff);
/* Top of the loop body */
pLevel->p2 = sqlite3VdbeCurrentAddr(v);
@@ -109004,9 +108461,9 @@ static Bitmask codeOneLoopStart(
** If it is, jump to the next iteration of the loop.
*/
r1 = sqlite3GetTempReg(pParse);
- testcase( pLevel->plan.wsFlags & WHERE_BTM_LIMIT );
- testcase( pLevel->plan.wsFlags & WHERE_TOP_LIMIT );
- if( (pLevel->plan.wsFlags & (WHERE_BTM_LIMIT|WHERE_TOP_LIMIT))!=0 ){
+ testcase( pLoop->wsFlags & WHERE_BTM_LIMIT );
+ testcase( pLoop->wsFlags & WHERE_TOP_LIMIT );
+ if( (pLoop->wsFlags & (WHERE_BTM_LIMIT|WHERE_TOP_LIMIT))!=0 ){
sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, nEq, r1);
sqlite3VdbeAddOp2(v, OP_IsNull, r1, addrCont);
}
@@ -109025,7 +108482,7 @@ static Bitmask codeOneLoopStart(
/* Record the instruction used to terminate the loop. Disable
** WHERE clause terms made redundant by the index range scan.
*/
- if( pLevel->plan.wsFlags & WHERE_UNIQUE ){
+ if( pLoop->wsFlags & WHERE_ONEROW ){
pLevel->op = OP_Noop;
}else if( bRev ){
pLevel->op = OP_Prev;
@@ -109033,7 +108490,7 @@ static Bitmask codeOneLoopStart(
pLevel->op = OP_Next;
}
pLevel->p1 = iIdxCur;
- if( pLevel->plan.wsFlags & WHERE_COVER_SCAN ){
+ if( (pLoop->wsFlags & WHERE_CONSTRAINT)==0 ){
pLevel->p5 = SQLITE_STMTSTATUS_FULLSCAN_STEP;
}else{
assert( pLevel->p5==0 );
@@ -109041,8 +108498,8 @@ static Bitmask codeOneLoopStart(
}else
#ifndef SQLITE_OMIT_OR_OPTIMIZATION
- if( pLevel->plan.wsFlags & WHERE_MULTI_OR ){
- /* Case 4: Two or more separately indexed terms connected by OR
+ if( pLoop->wsFlags & WHERE_MULTI_OR ){
+ /* Case 5: Two or more separately indexed terms connected by OR
**
** Example:
**
@@ -109095,7 +108552,7 @@ static Bitmask codeOneLoopStart(
int ii; /* Loop counter */
Expr *pAndExpr = 0; /* An ".. AND (...)" expression */
- pTerm = pLevel->plan.u.pTerm;
+ pTerm = pLoop->aLTerm[0];
assert( pTerm!=0 );
assert( pTerm->eOperator & WO_OR );
assert( (pTerm->wtFlags & TERM_ORINFO)!=0 );
@@ -109111,10 +108568,10 @@ static Bitmask codeOneLoopStart(
int nNotReady; /* The number of notReady tables */
struct SrcList_item *origSrc; /* Original list of tables */
nNotReady = pWInfo->nLevel - iLevel - 1;
- pOrTab = sqlite3StackAllocRaw(pParse->db,
+ pOrTab = sqlite3StackAllocRaw(db,
sizeof(*pOrTab)+ nNotReady*sizeof(pOrTab->a[0]));
if( pOrTab==0 ) return notReady;
- pOrTab->nAlloc = (i16)(nNotReady + 1);
+ pOrTab->nAlloc = (u8)(nNotReady + 1);
pOrTab->nSrc = pOrTab->nAlloc;
memcpy(pOrTab->a, pTabItem, sizeof(*pTabItem));
origSrc = pWInfo->pTabList->a;
@@ -109136,7 +108593,7 @@ static Bitmask codeOneLoopStart(
** fall through to the next instruction, just as an OP_Next does if
** called on an uninitialized cursor.
*/
- if( (wctrlFlags & WHERE_DUPLICATES_OK)==0 ){
+ if( (pWInfo->wctrlFlags & WHERE_DUPLICATES_OK)==0 ){
regRowset = ++pParse->nMem;
regRowid = ++pParse->nMem;
sqlite3VdbeAddOp2(v, OP_Null, 0, regRowset);
@@ -109161,11 +108618,12 @@ static Bitmask codeOneLoopStart(
int iTerm;
for(iTerm=0; iTerm<pWC->nTerm; iTerm++){
Expr *pExpr = pWC->a[iTerm].pExpr;
+ if( &pWC->a[iTerm] == pTerm ) continue;
if( ExprHasProperty(pExpr, EP_FromJoin) ) continue;
- if( pWC->a[iTerm].wtFlags & (TERM_VIRTUAL|TERM_ORINFO) ) continue;
+ if( pWC->a[iTerm].wtFlags & (TERM_ORINFO) ) continue;
if( (pWC->a[iTerm].eOperator & WO_ALL)==0 ) continue;
- pExpr = sqlite3ExprDup(pParse->db, pExpr, 0);
- pAndExpr = sqlite3ExprAnd(pParse->db, pAndExpr, pExpr);
+ pExpr = sqlite3ExprDup(db, pExpr, 0);
+ pAndExpr = sqlite3ExprAnd(db, pAndExpr, pExpr);
}
if( pAndExpr ){
pAndExpr = sqlite3PExpr(pParse, TK_AND, 0, pAndExpr, 0);
@@ -109185,13 +108643,13 @@ static Bitmask codeOneLoopStart(
pSubWInfo = sqlite3WhereBegin(pParse, pOrTab, pOrExpr, 0, 0,
WHERE_OMIT_OPEN_CLOSE | WHERE_AND_ONLY |
WHERE_FORCE_TABLE | WHERE_ONETABLE_ONLY, iCovCur);
- assert( pSubWInfo || pParse->nErr || pParse->db->mallocFailed );
+ assert( pSubWInfo || pParse->nErr || db->mallocFailed );
if( pSubWInfo ){
- WhereLevel *pLvl;
+ WhereLoop *pSubLoop;
explainOneScan(
pParse, pOrTab, &pSubWInfo->a[0], iLevel, pLevel->iFrom, 0
);
- if( (wctrlFlags & WHERE_DUPLICATES_OK)==0 ){
+ if( (pWInfo->wctrlFlags & WHERE_DUPLICATES_OK)==0 ){
int iSet = ((ii==pOrWc->nTerm-1)?-1:ii);
int r;
r = sqlite3ExprCodeGetColumn(pParse, pTabItem->pTab, -1, iCur,
@@ -109220,13 +108678,13 @@ static Bitmask codeOneLoopStart(
** pCov to NULL to indicate that no candidate covering index will
** be available.
*/
- pLvl = &pSubWInfo->a[0];
- if( (pLvl->plan.wsFlags & WHERE_INDEXED)!=0
- && (pLvl->plan.wsFlags & WHERE_TEMP_INDEX)==0
- && (ii==0 || pLvl->plan.u.pIdx==pCov)
+ pSubLoop = pSubWInfo->a[0].pWLoop;
+ assert( (pSubLoop->wsFlags & WHERE_AUTO_INDEX)==0 );
+ if( (pSubLoop->wsFlags & WHERE_INDEXED)!=0
+ && (ii==0 || pSubLoop->u.btree.pIndex==pCov)
){
- assert( pLvl->iIdxCur==iCovCur );
- pCov = pLvl->plan.u.pIdx;
+ assert( pSubWInfo->a[0].iIdxCur==iCovCur );
+ pCov = pSubLoop->u.btree.pIndex;
}else{
pCov = 0;
}
@@ -109240,42 +108698,37 @@ static Bitmask codeOneLoopStart(
if( pCov ) pLevel->iIdxCur = iCovCur;
if( pAndExpr ){
pAndExpr->pLeft = 0;
- sqlite3ExprDelete(pParse->db, pAndExpr);
+ sqlite3ExprDelete(db, pAndExpr);
}
sqlite3VdbeChangeP1(v, iRetInit, sqlite3VdbeCurrentAddr(v));
sqlite3VdbeAddOp2(v, OP_Goto, 0, pLevel->addrBrk);
sqlite3VdbeResolveLabel(v, iLoopBody);
- if( pWInfo->nLevel>1 ) sqlite3StackFree(pParse->db, pOrTab);
+ if( pWInfo->nLevel>1 ) sqlite3StackFree(db, pOrTab);
if( !untestedTerms ) disableTerm(pLevel, pTerm);
}else
#endif /* SQLITE_OMIT_OR_OPTIMIZATION */
{
- /* Case 5: There is no usable index. We must do a complete
+ /* Case 6: There is no usable index. We must do a complete
** scan of the entire table.
*/
static const u8 aStep[] = { OP_Next, OP_Prev };
static const u8 aStart[] = { OP_Rewind, OP_Last };
assert( bRev==0 || bRev==1 );
- assert( omitTable==0 );
pLevel->op = aStep[bRev];
pLevel->p1 = iCur;
pLevel->p2 = 1 + sqlite3VdbeAddOp2(v, aStart[bRev], iCur, addrBrk);
pLevel->p5 = SQLITE_STMTSTATUS_FULLSCAN_STEP;
}
- newNotReady = notReady & ~getMask(pWC->pMaskSet, iCur);
+ newNotReady = notReady & ~getMask(&pWInfo->sMaskSet, iCur);
/* Insert code to test every subexpression that can be completely
** computed using the current set of tables.
- **
- ** IMPLEMENTATION-OF: R-49525-50935 Terms that cannot be satisfied through
- ** the use of indices become tests that are evaluated against each row of
- ** the relevant input tables.
*/
for(pTerm=pWC->a, j=pWC->nTerm; j>0; j--, pTerm++){
Expr *pE;
- testcase( pTerm->wtFlags & TERM_VIRTUAL ); /* IMP: R-30575-11662 */
+ testcase( pTerm->wtFlags & TERM_VIRTUAL );
testcase( pTerm->wtFlags & TERM_CODED );
if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue;
if( (pTerm->prereqAll & newNotReady)!=0 ){
@@ -109302,22 +108755,28 @@ static Bitmask codeOneLoopStart(
** the implied "t1.a=123" constraint.
*/
for(pTerm=pWC->a, j=pWC->nTerm; j>0; j--, pTerm++){
- Expr *pE;
+ Expr *pE, *pEAlt;
WhereTerm *pAlt;
- Expr sEq;
if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue;
if( pTerm->eOperator!=(WO_EQUIV|WO_EQ) ) continue;
if( pTerm->leftCursor!=iCur ) continue;
+ if( pLevel->iLeftJoin ) continue;
pE = pTerm->pExpr;
assert( !ExprHasProperty(pE, EP_FromJoin) );
assert( (pTerm->prereqRight & newNotReady)!=0 );
pAlt = findTerm(pWC, iCur, pTerm->u.leftColumn, notReady, WO_EQ|WO_IN, 0);
if( pAlt==0 ) continue;
if( pAlt->wtFlags & (TERM_CODED) ) continue;
+ testcase( pAlt->eOperator & WO_EQ );
+ testcase( pAlt->eOperator & WO_IN );
VdbeNoopComment((v, "begin transitive constraint"));
- sEq = *pAlt->pExpr;
- sEq.pLeft = pE->pLeft;
- sqlite3ExprIfFalse(pParse, &sEq, addrCont, SQLITE_JUMPIFNULL);
+ pEAlt = sqlite3StackAllocRaw(db, sizeof(*pEAlt));
+ if( pEAlt ){
+ *pEAlt = *pAlt->pExpr;
+ pEAlt->pLeft = pE->pLeft;
+ sqlite3ExprIfFalse(pParse, pEAlt, addrCont, SQLITE_JUMPIFNULL);
+ sqlite3StackFree(db, pEAlt);
+ }
}
/* For a LEFT OUTER JOIN, generate code that will record the fact that
@@ -109329,7 +108788,7 @@ static Bitmask codeOneLoopStart(
VdbeComment((v, "record LEFT JOIN hit"));
sqlite3ExprCacheClear(pParse);
for(pTerm=pWC->a, j=0; j<pWC->nTerm; j++, pTerm++){
- testcase( pTerm->wtFlags & TERM_VIRTUAL ); /* IMP: R-30575-11662 */
+ testcase( pTerm->wtFlags & TERM_VIRTUAL );
testcase( pTerm->wtFlags & TERM_CODED );
if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue;
if( (pTerm->prereqAll & newNotReady)!=0 ){
@@ -109346,47 +108805,1601 @@ static Bitmask codeOneLoopStart(
return newNotReady;
}
-#if defined(SQLITE_TEST)
+#ifdef WHERETRACE_ENABLED
+/*
+** Print a WhereLoop object for debugging purposes
+*/
+static void whereLoopPrint(WhereLoop *p, SrcList *pTabList){
+ int nb = 1+(pTabList->nSrc+7)/8;
+ struct SrcList_item *pItem = pTabList->a + p->iTab;
+ Table *pTab = pItem->pTab;
+ sqlite3DebugPrintf("%c%2d.%0*llx.%0*llx", p->cId,
+ p->iTab, nb, p->maskSelf, nb, p->prereq);
+ sqlite3DebugPrintf(" %12s",
+ pItem->zAlias ? pItem->zAlias : pTab->zName);
+ if( (p->wsFlags & WHERE_VIRTUALTABLE)==0 ){
+ if( p->u.btree.pIndex ){
+ const char *zName = p->u.btree.pIndex->zName;
+ if( zName==0 ) zName = "ipk";
+ if( strncmp(zName, "sqlite_autoindex_", 17)==0 ){
+ int i = sqlite3Strlen30(zName) - 1;
+ while( zName[i]!='_' ) i--;
+ zName += i;
+ }
+ sqlite3DebugPrintf(".%-16s %2d", zName, p->u.btree.nEq);
+ }else{
+ sqlite3DebugPrintf("%20s","");
+ }
+ }else{
+ char *z;
+ if( p->u.vtab.idxStr ){
+ z = sqlite3_mprintf("(%d,\"%s\",%x)",
+ p->u.vtab.idxNum, p->u.vtab.idxStr, p->u.vtab.omitMask);
+ }else{
+ z = sqlite3_mprintf("(%d,%x)", p->u.vtab.idxNum, p->u.vtab.omitMask);
+ }
+ sqlite3DebugPrintf(" %-19s", z);
+ sqlite3_free(z);
+ }
+ sqlite3DebugPrintf(" f %04x N %d", p->wsFlags, p->nLTerm);
+ sqlite3DebugPrintf(" cost %d,%d,%d\n", p->rSetup, p->rRun, p->nOut);
+}
+#endif
+
/*
-** The following variable holds a text description of query plan generated
-** by the most recent call to sqlite3WhereBegin(). Each call to WhereBegin
-** overwrites the previous. This information is used for testing and
-** analysis only.
+** Convert bulk memory into a valid WhereLoop that can be passed
+** to whereLoopClear harmlessly.
*/
-SQLITE_API char sqlite3_query_plan[BMS*2*40]; /* Text of the join */
-static int nQPlan = 0; /* Next free slow in _query_plan[] */
+static void whereLoopInit(WhereLoop *p){
+ p->aLTerm = p->aLTermSpace;
+ p->nLTerm = 0;
+ p->nLSlot = ArraySize(p->aLTermSpace);
+ p->wsFlags = 0;
+}
-#endif /* SQLITE_TEST */
+/*
+** Clear the WhereLoop.u union. Leave WhereLoop.pLTerm intact.
+*/
+static void whereLoopClearUnion(sqlite3 *db, WhereLoop *p){
+ if( p->wsFlags & (WHERE_VIRTUALTABLE|WHERE_AUTO_INDEX) ){
+ if( (p->wsFlags & WHERE_VIRTUALTABLE)!=0 && p->u.vtab.needFree ){
+ sqlite3_free(p->u.vtab.idxStr);
+ p->u.vtab.needFree = 0;
+ p->u.vtab.idxStr = 0;
+ }else if( (p->wsFlags & WHERE_AUTO_INDEX)!=0 && p->u.btree.pIndex!=0 ){
+ sqlite3DbFree(db, p->u.btree.pIndex->zColAff);
+ sqlite3DbFree(db, p->u.btree.pIndex);
+ p->u.btree.pIndex = 0;
+ }
+ }
+}
+
+/*
+** Deallocate internal memory used by a WhereLoop object
+*/
+static void whereLoopClear(sqlite3 *db, WhereLoop *p){
+ if( p->aLTerm!=p->aLTermSpace ) sqlite3DbFree(db, p->aLTerm);
+ whereLoopClearUnion(db, p);
+ whereLoopInit(p);
+}
+/*
+** Increase the memory allocation for pLoop->aLTerm[] to be at least n.
+*/
+static int whereLoopResize(sqlite3 *db, WhereLoop *p, int n){
+ WhereTerm **paNew;
+ if( p->nLSlot>=n ) return SQLITE_OK;
+ n = (n+7)&~7;
+ paNew = sqlite3DbMallocRaw(db, sizeof(p->aLTerm[0])*n);
+ if( paNew==0 ) return SQLITE_NOMEM;
+ memcpy(paNew, p->aLTerm, sizeof(p->aLTerm[0])*p->nLSlot);
+ if( p->aLTerm!=p->aLTermSpace ) sqlite3DbFree(db, p->aLTerm);
+ p->aLTerm = paNew;
+ p->nLSlot = n;
+ return SQLITE_OK;
+}
+
+/*
+** Transfer content from the second pLoop into the first.
+*/
+static int whereLoopXfer(sqlite3 *db, WhereLoop *pTo, WhereLoop *pFrom){
+ if( whereLoopResize(db, pTo, pFrom->nLTerm) ) return SQLITE_NOMEM;
+ whereLoopClearUnion(db, pTo);
+ memcpy(pTo, pFrom, WHERE_LOOP_XFER_SZ);
+ memcpy(pTo->aLTerm, pFrom->aLTerm, pTo->nLTerm*sizeof(pTo->aLTerm[0]));
+ if( pFrom->wsFlags & WHERE_VIRTUALTABLE ){
+ pFrom->u.vtab.needFree = 0;
+ }else if( (pFrom->wsFlags & WHERE_AUTO_INDEX)!=0 ){
+ pFrom->u.btree.pIndex = 0;
+ }
+ return SQLITE_OK;
+}
+
+/*
+** Delete a WhereLoop object
+*/
+static void whereLoopDelete(sqlite3 *db, WhereLoop *p){
+ whereLoopClear(db, p);
+ sqlite3DbFree(db, p);
+}
/*
** Free a WhereInfo structure
*/
static void whereInfoFree(sqlite3 *db, WhereInfo *pWInfo){
if( ALWAYS(pWInfo) ){
- int i;
- for(i=0; i<pWInfo->nLevel; i++){
- sqlite3_index_info *pInfo = pWInfo->a[i].pIdxInfo;
- if( pInfo ){
- /* assert( pInfo->needToFreeIdxStr==0 || db->mallocFailed ); */
- if( pInfo->needToFreeIdxStr ){
- sqlite3_free(pInfo->idxStr);
+ whereClauseClear(&pWInfo->sWC);
+ while( pWInfo->pLoops ){
+ WhereLoop *p = pWInfo->pLoops;
+ pWInfo->pLoops = p->pNextLoop;
+ whereLoopDelete(db, p);
+ }
+ sqlite3DbFree(db, pWInfo);
+ }
+}
+
+/*
+** Insert or replace a WhereLoop entry using the template supplied.
+**
+** An existing WhereLoop entry might be overwritten if the new template
+** is better and has fewer dependencies. Or the template will be ignored
+** and no insert will occur if an existing WhereLoop is faster and has
+** fewer dependencies than the template. Otherwise a new WhereLoop is
+** added based on the template.
+**
+** If pBuilder->pOrSet is not NULL then we only care about only the
+** prerequisites and rRun and nOut costs of the N best loops. That
+** information is gathered in the pBuilder->pOrSet object. This special
+** processing mode is used only for OR clause processing.
+**
+** When accumulating multiple loops (when pBuilder->pOrSet is NULL) we
+** still might overwrite similar loops with the new template if the
+** template is better. Loops may be overwritten if the following
+** conditions are met:
+**
+** (1) They have the same iTab.
+** (2) They have the same iSortIdx.
+** (3) The template has same or fewer dependencies than the current loop
+** (4) The template has the same or lower cost than the current loop
+** (5) The template uses more terms of the same index but has no additional
+** dependencies
+*/
+static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){
+ WhereLoop **ppPrev, *p, *pNext = 0;
+ WhereInfo *pWInfo = pBuilder->pWInfo;
+ sqlite3 *db = pWInfo->pParse->db;
+
+ /* If pBuilder->pOrSet is defined, then only keep track of the costs
+ ** and prereqs.
+ */
+ if( pBuilder->pOrSet!=0 ){
+#if WHERETRACE_ENABLED
+ u16 n = pBuilder->pOrSet->n;
+ int x =
+#endif
+ whereOrInsert(pBuilder->pOrSet, pTemplate->prereq, pTemplate->rRun,
+ pTemplate->nOut);
+#if WHERETRACE_ENABLED
+ if( sqlite3WhereTrace & 0x8 ){
+ sqlite3DebugPrintf(x?" or-%d: ":" or-X: ", n);
+ whereLoopPrint(pTemplate, pWInfo->pTabList);
+ }
+#endif
+ return SQLITE_OK;
+ }
+
+ /* Search for an existing WhereLoop to overwrite, or which takes
+ ** priority over pTemplate.
+ */
+ for(ppPrev=&pWInfo->pLoops, p=*ppPrev; p; ppPrev=&p->pNextLoop, p=*ppPrev){
+ if( p->iTab!=pTemplate->iTab || p->iSortIdx!=pTemplate->iSortIdx ){
+ /* If either the iTab or iSortIdx values for two WhereLoop are different
+ ** then those WhereLoops need to be considered separately. Neither is
+ ** a candidate to replace the other. */
+ continue;
+ }
+ /* In the current implementation, the rSetup value is either zero
+ ** or the cost of building an automatic index (NlogN) and the NlogN
+ ** is the same for compatible WhereLoops. */
+ assert( p->rSetup==0 || pTemplate->rSetup==0
+ || p->rSetup==pTemplate->rSetup );
+
+ /* whereLoopAddBtree() always generates and inserts the automatic index
+ ** case first. Hence compatible candidate WhereLoops never have a larger
+ ** rSetup. Call this SETUP-INVARIANT */
+ assert( p->rSetup>=pTemplate->rSetup );
+
+ if( (p->prereq & pTemplate->prereq)==p->prereq
+ && p->rSetup<=pTemplate->rSetup
+ && p->rRun<=pTemplate->rRun
+ ){
+ /* This branch taken when p is equal or better than pTemplate in
+ ** all of (1) dependences (2) setup-cost, and (3) run-cost. */
+ assert( p->rSetup==pTemplate->rSetup );
+ if( p->nLTerm<pTemplate->nLTerm
+ && (p->wsFlags & WHERE_INDEXED)!=0
+ && (pTemplate->wsFlags & WHERE_INDEXED)!=0
+ && p->u.btree.pIndex==pTemplate->u.btree.pIndex
+ && p->prereq==pTemplate->prereq
+ ){
+ /* Overwrite an existing WhereLoop with an similar one that uses
+ ** more terms of the index */
+ pNext = p->pNextLoop;
+ break;
+ }else{
+ /* pTemplate is not helpful.
+ ** Return without changing or adding anything */
+ goto whereLoopInsert_noop;
+ }
+ }
+ if( (p->prereq & pTemplate->prereq)==pTemplate->prereq
+ && p->rRun>=pTemplate->rRun
+ && ALWAYS(p->rSetup>=pTemplate->rSetup) /* See SETUP-INVARIANT above */
+ ){
+ /* Overwrite an existing WhereLoop with a better one: one that is
+ ** better at one of (1) dependences, (2) setup-cost, or (3) run-cost
+ ** and is no worse in any of those categories. */
+ pNext = p->pNextLoop;
+ break;
+ }
+ }
+
+ /* If we reach this point it means that either p[] should be overwritten
+ ** with pTemplate[] if p[] exists, or if p==NULL then allocate a new
+ ** WhereLoop and insert it.
+ */
+#if WHERETRACE_ENABLED
+ if( sqlite3WhereTrace & 0x8 ){
+ if( p!=0 ){
+ sqlite3DebugPrintf("ins-del: ");
+ whereLoopPrint(p, pWInfo->pTabList);
+ }
+ sqlite3DebugPrintf("ins-new: ");
+ whereLoopPrint(pTemplate, pWInfo->pTabList);
+ }
+#endif
+ if( p==0 ){
+ p = sqlite3DbMallocRaw(db, sizeof(WhereLoop));
+ if( p==0 ) return SQLITE_NOMEM;
+ whereLoopInit(p);
+ }
+ whereLoopXfer(db, p, pTemplate);
+ p->pNextLoop = pNext;
+ *ppPrev = p;
+ if( (p->wsFlags & WHERE_VIRTUALTABLE)==0 ){
+ Index *pIndex = p->u.btree.pIndex;
+ if( pIndex && pIndex->tnum==0 ){
+ p->u.btree.pIndex = 0;
+ }
+ }
+ return SQLITE_OK;
+
+ /* Jump here if the insert is a no-op */
+whereLoopInsert_noop:
+#if WHERETRACE_ENABLED
+ if( sqlite3WhereTrace & 0x8 ){
+ sqlite3DebugPrintf("ins-noop: ");
+ whereLoopPrint(pTemplate, pWInfo->pTabList);
+ }
+#endif
+ return SQLITE_OK;
+}
+
+/*
+** We have so far matched pBuilder->pNew->u.btree.nEq terms of the index pIndex.
+** Try to match one more.
+**
+** If pProbe->tnum==0, that means pIndex is a fake index used for the
+** INTEGER PRIMARY KEY.
+*/
+static int whereLoopAddBtreeIndex(
+ WhereLoopBuilder *pBuilder, /* The WhereLoop factory */
+ struct SrcList_item *pSrc, /* FROM clause term being analyzed */
+ Index *pProbe, /* An index on pSrc */
+ WhereCost nInMul /* log(Number of iterations due to IN) */
+){
+ WhereInfo *pWInfo = pBuilder->pWInfo; /* WHERE analyse context */
+ Parse *pParse = pWInfo->pParse; /* Parsing context */
+ sqlite3 *db = pParse->db; /* Database connection malloc context */
+ WhereLoop *pNew; /* Template WhereLoop under construction */
+ WhereTerm *pTerm; /* A WhereTerm under consideration */
+ int opMask; /* Valid operators for constraints */
+ WhereScan scan; /* Iterator for WHERE terms */
+ Bitmask saved_prereq; /* Original value of pNew->prereq */
+ u16 saved_nLTerm; /* Original value of pNew->nLTerm */
+ int saved_nEq; /* Original value of pNew->u.btree.nEq */
+ u32 saved_wsFlags; /* Original value of pNew->wsFlags */
+ WhereCost saved_nOut; /* Original value of pNew->nOut */
+ int iCol; /* Index of the column in the table */
+ int rc = SQLITE_OK; /* Return code */
+ WhereCost nRowEst; /* Estimated index selectivity */
+ WhereCost rLogSize; /* Logarithm of table size */
+ WhereTerm *pTop = 0, *pBtm = 0; /* Top and bottom range constraints */
+
+ pNew = pBuilder->pNew;
+ if( db->mallocFailed ) return SQLITE_NOMEM;
+
+ assert( (pNew->wsFlags & WHERE_VIRTUALTABLE)==0 );
+ assert( (pNew->wsFlags & WHERE_TOP_LIMIT)==0 );
+ if( pNew->wsFlags & WHERE_BTM_LIMIT ){
+ opMask = WO_LT|WO_LE;
+ }else if( pProbe->tnum<=0 || (pSrc->jointype & JT_LEFT)!=0 ){
+ opMask = WO_EQ|WO_IN|WO_GT|WO_GE|WO_LT|WO_LE;
+ }else{
+ opMask = WO_EQ|WO_IN|WO_ISNULL|WO_GT|WO_GE|WO_LT|WO_LE;
+ }
+ if( pProbe->bUnordered ) opMask &= ~(WO_GT|WO_GE|WO_LT|WO_LE);
+
+ assert( pNew->u.btree.nEq<=pProbe->nColumn );
+ if( pNew->u.btree.nEq < pProbe->nColumn ){
+ iCol = pProbe->aiColumn[pNew->u.btree.nEq];
+ nRowEst = whereCost(pProbe->aiRowEst[pNew->u.btree.nEq+1]);
+ if( nRowEst==0 && pProbe->onError==OE_None ) nRowEst = 1;
+ }else{
+ iCol = -1;
+ nRowEst = 0;
+ }
+ pTerm = whereScanInit(&scan, pBuilder->pWC, pSrc->iCursor, iCol,
+ opMask, pProbe);
+ saved_nEq = pNew->u.btree.nEq;
+ saved_nLTerm = pNew->nLTerm;
+ saved_wsFlags = pNew->wsFlags;
+ saved_prereq = pNew->prereq;
+ saved_nOut = pNew->nOut;
+ pNew->rSetup = 0;
+ rLogSize = estLog(whereCost(pProbe->aiRowEst[0]));
+ for(; rc==SQLITE_OK && pTerm!=0; pTerm = whereScanNext(&scan)){
+ int nIn = 0;
+ if( pTerm->prereqRight & pNew->maskSelf ) continue;
+ if( (pTerm->eOperator==WO_ISNULL || (pTerm->wtFlags&TERM_VNULL)!=0)
+ && (iCol<0 || pSrc->pTab->aCol[iCol].notNull)
+ ){
+ continue; /* ignore IS [NOT] NULL constraints on NOT NULL columns */
+ }
+ pNew->wsFlags = saved_wsFlags;
+ pNew->u.btree.nEq = saved_nEq;
+ pNew->nLTerm = saved_nLTerm;
+ if( whereLoopResize(db, pNew, pNew->nLTerm+1) ) break; /* OOM */
+ pNew->aLTerm[pNew->nLTerm++] = pTerm;
+ pNew->prereq = (saved_prereq | pTerm->prereqRight) & ~pNew->maskSelf;
+ pNew->rRun = rLogSize; /* Baseline cost is log2(N). Adjustments below */
+ if( pTerm->eOperator & WO_IN ){
+ Expr *pExpr = pTerm->pExpr;
+ pNew->wsFlags |= WHERE_COLUMN_IN;
+ if( ExprHasProperty(pExpr, EP_xIsSelect) ){
+ /* "x IN (SELECT ...)": TUNING: the SELECT returns 25 rows */
+ nIn = 46; assert( 46==whereCost(25) );
+ }else if( ALWAYS(pExpr->x.pList && pExpr->x.pList->nExpr) ){
+ /* "x IN (value, value, ...)" */
+ nIn = whereCost(pExpr->x.pList->nExpr);
+ }
+ pNew->rRun += nIn;
+ pNew->u.btree.nEq++;
+ pNew->nOut = nRowEst + nInMul + nIn;
+ }else if( pTerm->eOperator & (WO_EQ) ){
+ assert( (pNew->wsFlags & (WHERE_COLUMN_NULL|WHERE_COLUMN_IN))!=0
+ || nInMul==0 );
+ pNew->wsFlags |= WHERE_COLUMN_EQ;
+ if( iCol<0
+ || (pProbe->onError!=OE_None && nInMul==0
+ && pNew->u.btree.nEq==pProbe->nColumn-1)
+ ){
+ assert( (pNew->wsFlags & WHERE_COLUMN_IN)==0 || iCol<0 );
+ pNew->wsFlags |= WHERE_ONEROW;
+ }
+ pNew->u.btree.nEq++;
+ pNew->nOut = nRowEst + nInMul;
+ }else if( pTerm->eOperator & (WO_ISNULL) ){
+ pNew->wsFlags |= WHERE_COLUMN_NULL;
+ pNew->u.btree.nEq++;
+ /* TUNING: IS NULL selects 2 rows */
+ nIn = 10; assert( 10==whereCost(2) );
+ pNew->nOut = nRowEst + nInMul + nIn;
+ }else if( pTerm->eOperator & (WO_GT|WO_GE) ){
+ testcase( pTerm->eOperator & WO_GT );
+ testcase( pTerm->eOperator & WO_GE );
+ pNew->wsFlags |= WHERE_COLUMN_RANGE|WHERE_BTM_LIMIT;
+ pBtm = pTerm;
+ pTop = 0;
+ }else{
+ assert( pTerm->eOperator & (WO_LT|WO_LE) );
+ testcase( pTerm->eOperator & WO_LT );
+ testcase( pTerm->eOperator & WO_LE );
+ pNew->wsFlags |= WHERE_COLUMN_RANGE|WHERE_TOP_LIMIT;
+ pTop = pTerm;
+ pBtm = (pNew->wsFlags & WHERE_BTM_LIMIT)!=0 ?
+ pNew->aLTerm[pNew->nLTerm-2] : 0;
+ }
+ if( pNew->wsFlags & WHERE_COLUMN_RANGE ){
+ /* Adjust nOut and rRun for STAT3 range values */
+ WhereCost rDiv;
+ whereRangeScanEst(pParse, pProbe, pNew->u.btree.nEq,
+ pBtm, pTop, &rDiv);
+ pNew->nOut = saved_nOut>rDiv+10 ? saved_nOut - rDiv : 10;
+ }
+#ifdef SQLITE_ENABLE_STAT3
+ if( pNew->u.btree.nEq==1 && pProbe->nSample
+ && OptimizationEnabled(db, SQLITE_Stat3) ){
+ tRowcnt nOut = 0;
+ if( (pTerm->eOperator & (WO_EQ|WO_ISNULL))!=0 ){
+ testcase( pTerm->eOperator & WO_EQ );
+ testcase( pTerm->eOperator & WO_ISNULL );
+ rc = whereEqualScanEst(pParse, pProbe, pTerm->pExpr->pRight, &nOut);
+ }else if( (pTerm->eOperator & WO_IN)
+ && !ExprHasProperty(pTerm->pExpr, EP_xIsSelect) ){
+ rc = whereInScanEst(pParse, pProbe, pTerm->pExpr->x.pList, &nOut);
+ }
+ assert( nOut==0 || rc==SQLITE_OK );
+ if( nOut ) pNew->nOut = whereCost(nOut);
+ }
+#endif
+ if( (pNew->wsFlags & (WHERE_IDX_ONLY|WHERE_IPK))==0 ){
+ /* Each row involves a step of the index, then a binary search of
+ ** the main table */
+ pNew->rRun = whereCostAdd(pNew->rRun, rLogSize>27 ? rLogSize-17 : 10);
+ }
+ /* Step cost for each output row */
+ pNew->rRun = whereCostAdd(pNew->rRun, pNew->nOut);
+ /* TBD: Adjust nOut for additional constraints */
+ rc = whereLoopInsert(pBuilder, pNew);
+ if( (pNew->wsFlags & WHERE_TOP_LIMIT)==0
+ && pNew->u.btree.nEq<(pProbe->nColumn + (pProbe->zName!=0))
+ ){
+ whereLoopAddBtreeIndex(pBuilder, pSrc, pProbe, nInMul+nIn);
+ }
+ }
+ pNew->prereq = saved_prereq;
+ pNew->u.btree.nEq = saved_nEq;
+ pNew->wsFlags = saved_wsFlags;
+ pNew->nOut = saved_nOut;
+ pNew->nLTerm = saved_nLTerm;
+ return rc;
+}
+
+/*
+** Return True if it is possible that pIndex might be useful in
+** implementing the ORDER BY clause in pBuilder.
+**
+** Return False if pBuilder does not contain an ORDER BY clause or
+** if there is no way for pIndex to be useful in implementing that
+** ORDER BY clause.
+*/
+static int indexMightHelpWithOrderBy(
+ WhereLoopBuilder *pBuilder,
+ Index *pIndex,
+ int iCursor
+){
+ ExprList *pOB;
+ int ii, jj;
+
+ if( pIndex->bUnordered ) return 0;
+ if( (pOB = pBuilder->pWInfo->pOrderBy)==0 ) return 0;
+ for(ii=0; ii<pOB->nExpr; ii++){
+ Expr *pExpr = sqlite3ExprSkipCollate(pOB->a[ii].pExpr);
+ if( pExpr->op!=TK_COLUMN ) return 0;
+ if( pExpr->iTable==iCursor ){
+ for(jj=0; jj<pIndex->nColumn; jj++){
+ if( pExpr->iColumn==pIndex->aiColumn[jj] ) return 1;
+ }
+ }
+ }
+ return 0;
+}
+
+/*
+** Return a bitmask where 1s indicate that the corresponding column of
+** the table is used by an index. Only the first 63 columns are considered.
+*/
+static Bitmask columnsInIndex(Index *pIdx){
+ Bitmask m = 0;
+ int j;
+ for(j=pIdx->nColumn-1; j>=0; j--){
+ int x = pIdx->aiColumn[j];
+ assert( x>=0 );
+ testcase( x==BMS-1 );
+ testcase( x==BMS-2 );
+ if( x<BMS-1 ) m |= MASKBIT(x);
+ }
+ return m;
+}
+
+/* Check to see if a partial index with pPartIndexWhere can be used
+** in the current query. Return true if it can be and false if not.
+*/
+static int whereUsablePartialIndex(int iTab, WhereClause *pWC, Expr *pWhere){
+ int i;
+ WhereTerm *pTerm;
+ for(i=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){
+ if( sqlite3ExprImpliesExpr(pTerm->pExpr, pWhere, iTab) ) return 1;
+ }
+ return 0;
+}
+
+/*
+** Add all WhereLoop objects for a single table of the join where the table
+** is idenfied by pBuilder->pNew->iTab. That table is guaranteed to be
+** a b-tree table, not a virtual table.
+*/
+static int whereLoopAddBtree(
+ WhereLoopBuilder *pBuilder, /* WHERE clause information */
+ Bitmask mExtra /* Extra prerequesites for using this table */
+){
+ WhereInfo *pWInfo; /* WHERE analysis context */
+ Index *pProbe; /* An index we are evaluating */
+ Index sPk; /* A fake index object for the primary key */
+ tRowcnt aiRowEstPk[2]; /* The aiRowEst[] value for the sPk index */
+ int aiColumnPk = -1; /* The aColumn[] value for the sPk index */
+ SrcList *pTabList; /* The FROM clause */
+ struct SrcList_item *pSrc; /* The FROM clause btree term to add */
+ WhereLoop *pNew; /* Template WhereLoop object */
+ int rc = SQLITE_OK; /* Return code */
+ int iSortIdx = 1; /* Index number */
+ int b; /* A boolean value */
+ WhereCost rSize; /* number of rows in the table */
+ WhereCost rLogSize; /* Logarithm of the number of rows in the table */
+ WhereClause *pWC; /* The parsed WHERE clause */
+
+ pNew = pBuilder->pNew;
+ pWInfo = pBuilder->pWInfo;
+ pTabList = pWInfo->pTabList;
+ pSrc = pTabList->a + pNew->iTab;
+ pWC = pBuilder->pWC;
+ assert( !IsVirtual(pSrc->pTab) );
+
+ if( pSrc->pIndex ){
+ /* An INDEXED BY clause specifies a particular index to use */
+ pProbe = pSrc->pIndex;
+ }else{
+ /* There is no INDEXED BY clause. Create a fake Index object in local
+ ** variable sPk to represent the rowid primary key index. Make this
+ ** fake index the first in a chain of Index objects with all of the real
+ ** indices to follow */
+ Index *pFirst; /* First of real indices on the table */
+ memset(&sPk, 0, sizeof(Index));
+ sPk.nColumn = 1;
+ sPk.aiColumn = &aiColumnPk;
+ sPk.aiRowEst = aiRowEstPk;
+ sPk.onError = OE_Replace;
+ sPk.pTable = pSrc->pTab;
+ aiRowEstPk[0] = pSrc->pTab->nRowEst;
+ aiRowEstPk[1] = 1;
+ pFirst = pSrc->pTab->pIndex;
+ if( pSrc->notIndexed==0 ){
+ /* The real indices of the table are only considered if the
+ ** NOT INDEXED qualifier is omitted from the FROM clause */
+ sPk.pNext = pFirst;
+ }
+ pProbe = &sPk;
+ }
+ rSize = whereCost(pSrc->pTab->nRowEst);
+ rLogSize = estLog(rSize);
+
+#ifndef SQLITE_OMIT_AUTOMATIC_INDEX
+ /* Automatic indexes */
+ if( !pBuilder->pOrSet
+ && (pWInfo->pParse->db->flags & SQLITE_AutoIndex)!=0
+ && pSrc->pIndex==0
+ && !pSrc->viaCoroutine
+ && !pSrc->notIndexed
+ && !pSrc->isCorrelated
+ ){
+ /* Generate auto-index WhereLoops */
+ WhereTerm *pTerm;
+ WhereTerm *pWCEnd = pWC->a + pWC->nTerm;
+ for(pTerm=pWC->a; rc==SQLITE_OK && pTerm<pWCEnd; pTerm++){
+ if( pTerm->prereqRight & pNew->maskSelf ) continue;
+ if( termCanDriveIndex(pTerm, pSrc, 0) ){
+ pNew->u.btree.nEq = 1;
+ pNew->u.btree.pIndex = 0;
+ pNew->nLTerm = 1;
+ pNew->aLTerm[0] = pTerm;
+ /* TUNING: One-time cost for computing the automatic index is
+ ** approximately 7*N*log2(N) where N is the number of rows in
+ ** the table being indexed. */
+ pNew->rSetup = rLogSize + rSize + 28; assert( 28==whereCost(7) );
+ /* TUNING: Each index lookup yields 20 rows in the table. This
+ ** is more than the usual guess of 10 rows, since we have no way
+ ** of knowning how selective the index will ultimately be. It would
+ ** not be unreasonable to make this value much larger. */
+ pNew->nOut = 43; assert( 43==whereCost(20) );
+ pNew->rRun = whereCostAdd(rLogSize,pNew->nOut);
+ pNew->wsFlags = WHERE_AUTO_INDEX;
+ pNew->prereq = mExtra | pTerm->prereqRight;
+ rc = whereLoopInsert(pBuilder, pNew);
+ }
+ }
+ }
+#endif /* SQLITE_OMIT_AUTOMATIC_INDEX */
+
+ /* Loop over all indices
+ */
+ for(; rc==SQLITE_OK && pProbe; pProbe=pProbe->pNext, iSortIdx++){
+ if( pProbe->pPartIdxWhere!=0
+ && !whereUsablePartialIndex(pNew->iTab, pWC, pProbe->pPartIdxWhere) ){
+ continue; /* Partial index inappropriate for this query */
+ }
+ pNew->u.btree.nEq = 0;
+ pNew->nLTerm = 0;
+ pNew->iSortIdx = 0;
+ pNew->rSetup = 0;
+ pNew->prereq = mExtra;
+ pNew->nOut = rSize;
+ pNew->u.btree.pIndex = pProbe;
+ b = indexMightHelpWithOrderBy(pBuilder, pProbe, pSrc->iCursor);
+ /* The ONEPASS_DESIRED flags never occurs together with ORDER BY */
+ assert( (pWInfo->wctrlFlags & WHERE_ONEPASS_DESIRED)==0 || b==0 );
+ if( pProbe->tnum<=0 ){
+ /* Integer primary key index */
+ pNew->wsFlags = WHERE_IPK;
+
+ /* Full table scan */
+ pNew->iSortIdx = b ? iSortIdx : 0;
+ /* TUNING: Cost of full table scan is 3*(N + log2(N)).
+ ** + The extra 3 factor is to encourage the use of indexed lookups
+ ** over full scans. A smaller constant 2 is used for covering
+ ** index scans so that a covering index scan will be favored over
+ ** a table scan. */
+ pNew->rRun = whereCostAdd(rSize,rLogSize) + 16;
+ rc = whereLoopInsert(pBuilder, pNew);
+ if( rc ) break;
+ }else{
+ Bitmask m = pSrc->colUsed & ~columnsInIndex(pProbe);
+ pNew->wsFlags = (m==0) ? (WHERE_IDX_ONLY|WHERE_INDEXED) : WHERE_INDEXED;
+
+ /* Full scan via index */
+ if( b
+ || ( m==0
+ && pProbe->bUnordered==0
+ && (pWInfo->wctrlFlags & WHERE_ONEPASS_DESIRED)==0
+ && sqlite3GlobalConfig.bUseCis
+ && OptimizationEnabled(pWInfo->pParse->db, SQLITE_CoverIdxScan)
+ )
+ ){
+ pNew->iSortIdx = b ? iSortIdx : 0;
+ if( m==0 ){
+ /* TUNING: Cost of a covering index scan is 2*(N + log2(N)).
+ ** + The extra 2 factor is to encourage the use of indexed lookups
+ ** over index scans. A table scan uses a factor of 3 so that
+ ** index scans are favored over table scans.
+ ** + If this covering index might also help satisfy the ORDER BY
+ ** clause, then the cost is fudged down slightly so that this
+ ** index is favored above other indices that have no hope of
+ ** helping with the ORDER BY. */
+ pNew->rRun = 10 + whereCostAdd(rSize,rLogSize) - b;
+ }else{
+ assert( b!=0 );
+ /* TUNING: Cost of scanning a non-covering index is (N+1)*log2(N)
+ ** which we will simplify to just N*log2(N) */
+ pNew->rRun = rSize + rLogSize;
}
- sqlite3DbFree(db, pInfo);
+ rc = whereLoopInsert(pBuilder, pNew);
+ if( rc ) break;
}
- if( pWInfo->a[i].plan.wsFlags & WHERE_TEMP_INDEX ){
- Index *pIdx = pWInfo->a[i].plan.u.pIdx;
- if( pIdx ){
- sqlite3DbFree(db, pIdx->zColAff);
- sqlite3DbFree(db, pIdx);
+ }
+ rc = whereLoopAddBtreeIndex(pBuilder, pSrc, pProbe, 0);
+
+ /* If there was an INDEXED BY clause, then only that one index is
+ ** considered. */
+ if( pSrc->pIndex ) break;
+ }
+ return rc;
+}
+
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+/*
+** Add all WhereLoop objects for a table of the join identified by
+** pBuilder->pNew->iTab. That table is guaranteed to be a virtual table.
+*/
+static int whereLoopAddVirtual(
+ WhereLoopBuilder *pBuilder /* WHERE clause information */
+){
+ WhereInfo *pWInfo; /* WHERE analysis context */
+ Parse *pParse; /* The parsing context */
+ WhereClause *pWC; /* The WHERE clause */
+ struct SrcList_item *pSrc; /* The FROM clause term to search */
+ Table *pTab;
+ sqlite3 *db;
+ sqlite3_index_info *pIdxInfo;
+ struct sqlite3_index_constraint *pIdxCons;
+ struct sqlite3_index_constraint_usage *pUsage;
+ WhereTerm *pTerm;
+ int i, j;
+ int iTerm, mxTerm;
+ int nConstraint;
+ int seenIn = 0; /* True if an IN operator is seen */
+ int seenVar = 0; /* True if a non-constant constraint is seen */
+ int iPhase; /* 0: const w/o IN, 1: const, 2: no IN, 2: IN */
+ WhereLoop *pNew;
+ int rc = SQLITE_OK;
+
+ pWInfo = pBuilder->pWInfo;
+ pParse = pWInfo->pParse;
+ db = pParse->db;
+ pWC = pBuilder->pWC;
+ pNew = pBuilder->pNew;
+ pSrc = &pWInfo->pTabList->a[pNew->iTab];
+ pTab = pSrc->pTab;
+ assert( IsVirtual(pTab) );
+ pIdxInfo = allocateIndexInfo(pParse, pWC, pSrc, pBuilder->pOrderBy);
+ if( pIdxInfo==0 ) return SQLITE_NOMEM;
+ pNew->prereq = 0;
+ pNew->rSetup = 0;
+ pNew->wsFlags = WHERE_VIRTUALTABLE;
+ pNew->nLTerm = 0;
+ pNew->u.vtab.needFree = 0;
+ pUsage = pIdxInfo->aConstraintUsage;
+ nConstraint = pIdxInfo->nConstraint;
+ if( whereLoopResize(db, pNew, nConstraint) ){
+ sqlite3DbFree(db, pIdxInfo);
+ return SQLITE_NOMEM;
+ }
+
+ for(iPhase=0; iPhase<=3; iPhase++){
+ if( !seenIn && (iPhase&1)!=0 ){
+ iPhase++;
+ if( iPhase>3 ) break;
+ }
+ if( !seenVar && iPhase>1 ) break;
+ pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint;
+ for(i=0; i<pIdxInfo->nConstraint; i++, pIdxCons++){
+ j = pIdxCons->iTermOffset;
+ pTerm = &pWC->a[j];
+ switch( iPhase ){
+ case 0: /* Constants without IN operator */
+ pIdxCons->usable = 0;
+ if( (pTerm->eOperator & WO_IN)!=0 ){
+ seenIn = 1;
+ }
+ if( pTerm->prereqRight!=0 ){
+ seenVar = 1;
+ }else if( (pTerm->eOperator & WO_IN)==0 ){
+ pIdxCons->usable = 1;
+ }
+ break;
+ case 1: /* Constants with IN operators */
+ assert( seenIn );
+ pIdxCons->usable = (pTerm->prereqRight==0);
+ break;
+ case 2: /* Variables without IN */
+ assert( seenVar );
+ pIdxCons->usable = (pTerm->eOperator & WO_IN)==0;
+ break;
+ default: /* Variables with IN */
+ assert( seenVar && seenIn );
+ pIdxCons->usable = 1;
+ break;
+ }
+ }
+ memset(pUsage, 0, sizeof(pUsage[0])*pIdxInfo->nConstraint);
+ if( pIdxInfo->needToFreeIdxStr ) sqlite3_free(pIdxInfo->idxStr);
+ pIdxInfo->idxStr = 0;
+ pIdxInfo->idxNum = 0;
+ pIdxInfo->needToFreeIdxStr = 0;
+ pIdxInfo->orderByConsumed = 0;
+ pIdxInfo->estimatedCost = SQLITE_BIG_DBL / (double)2;
+ rc = vtabBestIndex(pParse, pTab, pIdxInfo);
+ if( rc ) goto whereLoopAddVtab_exit;
+ pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint;
+ pNew->prereq = 0;
+ mxTerm = -1;
+ assert( pNew->nLSlot>=nConstraint );
+ for(i=0; i<nConstraint; i++) pNew->aLTerm[i] = 0;
+ pNew->u.vtab.omitMask = 0;
+ for(i=0; i<nConstraint; i++, pIdxCons++){
+ if( (iTerm = pUsage[i].argvIndex - 1)>=0 ){
+ j = pIdxCons->iTermOffset;
+ if( iTerm>=nConstraint
+ || j<0
+ || j>=pWC->nTerm
+ || pNew->aLTerm[iTerm]!=0
+ ){
+ rc = SQLITE_ERROR;
+ sqlite3ErrorMsg(pParse, "%s.xBestIndex() malfunction", pTab->zName);
+ goto whereLoopAddVtab_exit;
+ }
+ testcase( iTerm==nConstraint-1 );
+ testcase( j==0 );
+ testcase( j==pWC->nTerm-1 );
+ pTerm = &pWC->a[j];
+ pNew->prereq |= pTerm->prereqRight;
+ assert( iTerm<pNew->nLSlot );
+ pNew->aLTerm[iTerm] = pTerm;
+ if( iTerm>mxTerm ) mxTerm = iTerm;
+ testcase( iTerm==15 );
+ testcase( iTerm==16 );
+ if( iTerm<16 && pUsage[i].omit ) pNew->u.vtab.omitMask |= 1<<iTerm;
+ if( (pTerm->eOperator & WO_IN)!=0 ){
+ if( pUsage[i].omit==0 ){
+ /* Do not attempt to use an IN constraint if the virtual table
+ ** says that the equivalent EQ constraint cannot be safely omitted.
+ ** If we do attempt to use such a constraint, some rows might be
+ ** repeated in the output. */
+ break;
+ }
+ /* A virtual table that is constrained by an IN clause may not
+ ** consume the ORDER BY clause because (1) the order of IN terms
+ ** is not necessarily related to the order of output terms and
+ ** (2) Multiple outputs from a single IN value will not merge
+ ** together. */
+ pIdxInfo->orderByConsumed = 0;
}
}
}
- whereClauseClear(pWInfo->pWC);
- sqlite3DbFree(db, pWInfo);
+ if( i>=nConstraint ){
+ pNew->nLTerm = mxTerm+1;
+ assert( pNew->nLTerm<=pNew->nLSlot );
+ pNew->u.vtab.idxNum = pIdxInfo->idxNum;
+ pNew->u.vtab.needFree = pIdxInfo->needToFreeIdxStr;
+ pIdxInfo->needToFreeIdxStr = 0;
+ pNew->u.vtab.idxStr = pIdxInfo->idxStr;
+ pNew->u.vtab.isOrdered = (u8)((pIdxInfo->nOrderBy!=0)
+ && pIdxInfo->orderByConsumed);
+ pNew->rSetup = 0;
+ pNew->rRun = whereCostFromDouble(pIdxInfo->estimatedCost);
+ /* TUNING: Every virtual table query returns 25 rows */
+ pNew->nOut = 46; assert( 46==whereCost(25) );
+ whereLoopInsert(pBuilder, pNew);
+ if( pNew->u.vtab.needFree ){
+ sqlite3_free(pNew->u.vtab.idxStr);
+ pNew->u.vtab.needFree = 0;
+ }
+ }
+ }
+
+whereLoopAddVtab_exit:
+ if( pIdxInfo->needToFreeIdxStr ) sqlite3_free(pIdxInfo->idxStr);
+ sqlite3DbFree(db, pIdxInfo);
+ return rc;
+}
+#endif /* SQLITE_OMIT_VIRTUALTABLE */
+
+/*
+** Add WhereLoop entries to handle OR terms. This works for either
+** btrees or virtual tables.
+*/
+static int whereLoopAddOr(WhereLoopBuilder *pBuilder, Bitmask mExtra){
+ WhereInfo *pWInfo = pBuilder->pWInfo;
+ WhereClause *pWC;
+ WhereLoop *pNew;
+ WhereTerm *pTerm, *pWCEnd;
+ int rc = SQLITE_OK;
+ int iCur;
+ WhereClause tempWC;
+ WhereLoopBuilder sSubBuild;
+ WhereOrSet sSum, sCur, sPrev;
+ struct SrcList_item *pItem;
+
+ pWC = pBuilder->pWC;
+ if( pWInfo->wctrlFlags & WHERE_AND_ONLY ) return SQLITE_OK;
+ pWCEnd = pWC->a + pWC->nTerm;
+ pNew = pBuilder->pNew;
+ memset(&sSum, 0, sizeof(sSum));
+
+ for(pTerm=pWC->a; pTerm<pWCEnd && rc==SQLITE_OK; pTerm++){
+ if( (pTerm->eOperator & WO_OR)!=0
+ && (pTerm->u.pOrInfo->indexable & pNew->maskSelf)!=0
+ ){
+ WhereClause * const pOrWC = &pTerm->u.pOrInfo->wc;
+ WhereTerm * const pOrWCEnd = &pOrWC->a[pOrWC->nTerm];
+ WhereTerm *pOrTerm;
+ int once = 1;
+ int i, j;
+
+ pItem = pWInfo->pTabList->a + pNew->iTab;
+ iCur = pItem->iCursor;
+ sSubBuild = *pBuilder;
+ sSubBuild.pOrderBy = 0;
+ sSubBuild.pOrSet = &sCur;
+
+ for(pOrTerm=pOrWC->a; pOrTerm<pOrWCEnd; pOrTerm++){
+ if( (pOrTerm->eOperator & WO_AND)!=0 ){
+ sSubBuild.pWC = &pOrTerm->u.pAndInfo->wc;
+ }else if( pOrTerm->leftCursor==iCur ){
+ tempWC.pWInfo = pWC->pWInfo;
+ tempWC.pOuter = pWC;
+ tempWC.op = TK_AND;
+ tempWC.nTerm = 1;
+ tempWC.a = pOrTerm;
+ sSubBuild.pWC = &tempWC;
+ }else{
+ continue;
+ }
+ sCur.n = 0;
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ if( IsVirtual(pItem->pTab) ){
+ rc = whereLoopAddVirtual(&sSubBuild);
+ for(i=0; i<sCur.n; i++) sCur.a[i].prereq |= mExtra;
+ }else
+#endif
+ {
+ rc = whereLoopAddBtree(&sSubBuild, mExtra);
+ }
+ assert( rc==SQLITE_OK || sCur.n==0 );
+ if( sCur.n==0 ){
+ sSum.n = 0;
+ break;
+ }else if( once ){
+ whereOrMove(&sSum, &sCur);
+ once = 0;
+ }else{
+ whereOrMove(&sPrev, &sSum);
+ sSum.n = 0;
+ for(i=0; i<sPrev.n; i++){
+ for(j=0; j<sCur.n; j++){
+ whereOrInsert(&sSum, sPrev.a[i].prereq | sCur.a[j].prereq,
+ whereCostAdd(sPrev.a[i].rRun, sCur.a[j].rRun),
+ whereCostAdd(sPrev.a[i].nOut, sCur.a[j].nOut));
+ }
+ }
+ }
+ }
+ pNew->nLTerm = 1;
+ pNew->aLTerm[0] = pTerm;
+ pNew->wsFlags = WHERE_MULTI_OR;
+ pNew->rSetup = 0;
+ pNew->iSortIdx = 0;
+ memset(&pNew->u, 0, sizeof(pNew->u));
+ for(i=0; rc==SQLITE_OK && i<sSum.n; i++){
+ /* TUNING: Multiple by 3.5 for the secondary table lookup */
+ pNew->rRun = sSum.a[i].rRun + 18;
+ pNew->nOut = sSum.a[i].nOut;
+ pNew->prereq = sSum.a[i].prereq;
+ rc = whereLoopInsert(pBuilder, pNew);
+ }
+ }
+ }
+ return rc;
+}
+
+/*
+** Add all WhereLoop objects for all tables
+*/
+static int whereLoopAddAll(WhereLoopBuilder *pBuilder){
+ WhereInfo *pWInfo = pBuilder->pWInfo;
+ Bitmask mExtra = 0;
+ Bitmask mPrior = 0;
+ int iTab;
+ SrcList *pTabList = pWInfo->pTabList;
+ struct SrcList_item *pItem;
+ sqlite3 *db = pWInfo->pParse->db;
+ int nTabList = pWInfo->nLevel;
+ int rc = SQLITE_OK;
+ u8 priorJoinType = 0;
+ WhereLoop *pNew;
+
+ /* Loop over the tables in the join, from left to right */
+ pNew = pBuilder->pNew;
+ whereLoopInit(pNew);
+ for(iTab=0, pItem=pTabList->a; iTab<nTabList; iTab++, pItem++){
+ pNew->iTab = iTab;
+ pNew->maskSelf = getMask(&pWInfo->sMaskSet, pItem->iCursor);
+ if( ((pItem->jointype|priorJoinType) & (JT_LEFT|JT_CROSS))!=0 ){
+ mExtra = mPrior;
+ }
+ priorJoinType = pItem->jointype;
+ if( IsVirtual(pItem->pTab) ){
+ rc = whereLoopAddVirtual(pBuilder);
+ }else{
+ rc = whereLoopAddBtree(pBuilder, mExtra);
+ }
+ if( rc==SQLITE_OK ){
+ rc = whereLoopAddOr(pBuilder, mExtra);
+ }
+ mPrior |= pNew->maskSelf;
+ if( rc || db->mallocFailed ) break;
+ }
+ whereLoopClear(db, pNew);
+ return rc;
+}
+
+/*
+** Examine a WherePath (with the addition of the extra WhereLoop of the 5th
+** parameters) to see if it outputs rows in the requested ORDER BY
+** (or GROUP BY) without requiring a separate sort operation. Return:
+**
+** 0: ORDER BY is not satisfied. Sorting required
+** 1: ORDER BY is satisfied. Omit sorting
+** -1: Unknown at this time
+**
+** Note that processing for WHERE_GROUPBY and WHERE_DISTINCTBY is not as
+** strict. With GROUP BY and DISTINCT the only requirement is that
+** equivalent rows appear immediately adjacent to one another. GROUP BY
+** and DISTINT do not require rows to appear in any particular order as long
+** as equivelent rows are grouped together. Thus for GROUP BY and DISTINCT
+** the pOrderBy terms can be matched in any order. With ORDER BY, the
+** pOrderBy terms must be matched in strict left-to-right order.
+*/
+static int wherePathSatisfiesOrderBy(
+ WhereInfo *pWInfo, /* The WHERE clause */
+ ExprList *pOrderBy, /* ORDER BY or GROUP BY or DISTINCT clause to check */
+ WherePath *pPath, /* The WherePath to check */
+ u16 wctrlFlags, /* Might contain WHERE_GROUPBY or WHERE_DISTINCTBY */
+ u16 nLoop, /* Number of entries in pPath->aLoop[] */
+ WhereLoop *pLast, /* Add this WhereLoop to the end of pPath->aLoop[] */
+ Bitmask *pRevMask /* OUT: Mask of WhereLoops to run in reverse order */
+){
+ u8 revSet; /* True if rev is known */
+ u8 rev; /* Composite sort order */
+ u8 revIdx; /* Index sort order */
+ u8 isOrderDistinct; /* All prior WhereLoops are order-distinct */
+ u8 distinctColumns; /* True if the loop has UNIQUE NOT NULL columns */
+ u8 isMatch; /* iColumn matches a term of the ORDER BY clause */
+ u16 nColumn; /* Number of columns in pIndex */
+ u16 nOrderBy; /* Number terms in the ORDER BY clause */
+ int iLoop; /* Index of WhereLoop in pPath being processed */
+ int i, j; /* Loop counters */
+ int iCur; /* Cursor number for current WhereLoop */
+ int iColumn; /* A column number within table iCur */
+ WhereLoop *pLoop = 0; /* Current WhereLoop being processed. */
+ WhereTerm *pTerm; /* A single term of the WHERE clause */
+ Expr *pOBExpr; /* An expression from the ORDER BY clause */
+ CollSeq *pColl; /* COLLATE function from an ORDER BY clause term */
+ Index *pIndex; /* The index associated with pLoop */
+ sqlite3 *db = pWInfo->pParse->db; /* Database connection */
+ Bitmask obSat = 0; /* Mask of ORDER BY terms satisfied so far */
+ Bitmask obDone; /* Mask of all ORDER BY terms */
+ Bitmask orderDistinctMask; /* Mask of all well-ordered loops */
+ Bitmask ready; /* Mask of inner loops */
+
+ /*
+ ** We say the WhereLoop is "one-row" if it generates no more than one
+ ** row of output. A WhereLoop is one-row if all of the following are true:
+ ** (a) All index columns match with WHERE_COLUMN_EQ.
+ ** (b) The index is unique
+ ** Any WhereLoop with an WHERE_COLUMN_EQ constraint on the rowid is one-row.
+ ** Every one-row WhereLoop will have the WHERE_ONEROW bit set in wsFlags.
+ **
+ ** We say the WhereLoop is "order-distinct" if the set of columns from
+ ** that WhereLoop that are in the ORDER BY clause are different for every
+ ** row of the WhereLoop. Every one-row WhereLoop is automatically
+ ** order-distinct. A WhereLoop that has no columns in the ORDER BY clause
+ ** is not order-distinct. To be order-distinct is not quite the same as being
+ ** UNIQUE since a UNIQUE column or index can have multiple rows that
+ ** are NULL and NULL values are equivalent for the purpose of order-distinct.
+ ** To be order-distinct, the columns must be UNIQUE and NOT NULL.
+ **
+ ** The rowid for a table is always UNIQUE and NOT NULL so whenever the
+ ** rowid appears in the ORDER BY clause, the corresponding WhereLoop is
+ ** automatically order-distinct.
+ */
+
+ assert( pOrderBy!=0 );
+
+ /* Sortability of virtual tables is determined by the xBestIndex method
+ ** of the virtual table itself */
+ if( pLast->wsFlags & WHERE_VIRTUALTABLE ){
+ testcase( nLoop>0 ); /* True when outer loops are one-row and match
+ ** no ORDER BY terms */
+ return pLast->u.vtab.isOrdered;
+ }
+ if( nLoop && OptimizationDisabled(db, SQLITE_OrderByIdxJoin) ) return 0;
+
+ nOrderBy = pOrderBy->nExpr;
+ testcase( nOrderBy==BMS-1 );
+ if( nOrderBy>BMS-1 ) return 0; /* Cannot optimize overly large ORDER BYs */
+ isOrderDistinct = 1;
+ obDone = MASKBIT(nOrderBy)-1;
+ orderDistinctMask = 0;
+ ready = 0;
+ for(iLoop=0; isOrderDistinct && obSat<obDone && iLoop<=nLoop; iLoop++){
+ if( iLoop>0 ) ready |= pLoop->maskSelf;
+ pLoop = iLoop<nLoop ? pPath->aLoop[iLoop] : pLast;
+ assert( (pLoop->wsFlags & WHERE_VIRTUALTABLE)==0 );
+ iCur = pWInfo->pTabList->a[pLoop->iTab].iCursor;
+
+ /* Mark off any ORDER BY term X that is a column in the table of
+ ** the current loop for which there is term in the WHERE
+ ** clause of the form X IS NULL or X=? that reference only outer
+ ** loops.
+ */
+ for(i=0; i<nOrderBy; i++){
+ if( MASKBIT(i) & obSat ) continue;
+ pOBExpr = sqlite3ExprSkipCollate(pOrderBy->a[i].pExpr);
+ if( pOBExpr->op!=TK_COLUMN ) continue;
+ if( pOBExpr->iTable!=iCur ) continue;
+ pTerm = findTerm(&pWInfo->sWC, iCur, pOBExpr->iColumn,
+ ~ready, WO_EQ|WO_ISNULL, 0);
+ if( pTerm==0 ) continue;
+ if( (pTerm->eOperator&WO_EQ)!=0 && pOBExpr->iColumn>=0 ){
+ const char *z1, *z2;
+ pColl = sqlite3ExprCollSeq(pWInfo->pParse, pOrderBy->a[i].pExpr);
+ if( !pColl ) pColl = db->pDfltColl;
+ z1 = pColl->zName;
+ pColl = sqlite3ExprCollSeq(pWInfo->pParse, pTerm->pExpr);
+ if( !pColl ) pColl = db->pDfltColl;
+ z2 = pColl->zName;
+ if( sqlite3StrICmp(z1, z2)!=0 ) continue;
+ }
+ obSat |= MASKBIT(i);
+ }
+
+ if( (pLoop->wsFlags & WHERE_ONEROW)==0 ){
+ if( pLoop->wsFlags & WHERE_IPK ){
+ pIndex = 0;
+ nColumn = 0;
+ }else if( (pIndex = pLoop->u.btree.pIndex)==0 || pIndex->bUnordered ){
+ return 0;
+ }else{
+ nColumn = pIndex->nColumn;
+ isOrderDistinct = pIndex->onError!=OE_None;
+ }
+
+ /* Loop through all columns of the index and deal with the ones
+ ** that are not constrained by == or IN.
+ */
+ rev = revSet = 0;
+ distinctColumns = 0;
+ for(j=0; j<=nColumn; j++){
+ u8 bOnce; /* True to run the ORDER BY search loop */
+
+ /* Skip over == and IS NULL terms */
+ if( j<pLoop->u.btree.nEq
+ && ((i = pLoop->aLTerm[j]->eOperator) & (WO_EQ|WO_ISNULL))!=0
+ ){
+ if( i & WO_ISNULL ){
+ testcase( isOrderDistinct );
+ isOrderDistinct = 0;
+ }
+ continue;
+ }
+
+ /* Get the column number in the table (iColumn) and sort order
+ ** (revIdx) for the j-th column of the index.
+ */
+ if( j<nColumn ){
+ /* Normal index columns */
+ iColumn = pIndex->aiColumn[j];
+ revIdx = pIndex->aSortOrder[j];
+ if( iColumn==pIndex->pTable->iPKey ) iColumn = -1;
+ }else{
+ /* The ROWID column at the end */
+ assert( j==nColumn );
+ iColumn = -1;
+ revIdx = 0;
+ }
+
+ /* An unconstrained column that might be NULL means that this
+ ** WhereLoop is not well-ordered
+ */
+ if( isOrderDistinct
+ && iColumn>=0
+ && j>=pLoop->u.btree.nEq
+ && pIndex->pTable->aCol[iColumn].notNull==0
+ ){
+ isOrderDistinct = 0;
+ }
+
+ /* Find the ORDER BY term that corresponds to the j-th column
+ ** of the index and and mark that ORDER BY term off
+ */
+ bOnce = 1;
+ isMatch = 0;
+ for(i=0; bOnce && i<nOrderBy; i++){
+ if( MASKBIT(i) & obSat ) continue;
+ pOBExpr = sqlite3ExprSkipCollate(pOrderBy->a[i].pExpr);
+ testcase( wctrlFlags & WHERE_GROUPBY );
+ testcase( wctrlFlags & WHERE_DISTINCTBY );
+ if( (wctrlFlags & (WHERE_GROUPBY|WHERE_DISTINCTBY))==0 ) bOnce = 0;
+ if( pOBExpr->op!=TK_COLUMN ) continue;
+ if( pOBExpr->iTable!=iCur ) continue;
+ if( pOBExpr->iColumn!=iColumn ) continue;
+ if( iColumn>=0 ){
+ pColl = sqlite3ExprCollSeq(pWInfo->pParse, pOrderBy->a[i].pExpr);
+ if( !pColl ) pColl = db->pDfltColl;
+ if( sqlite3StrICmp(pColl->zName, pIndex->azColl[j])!=0 ) continue;
+ }
+ isMatch = 1;
+ break;
+ }
+ if( isMatch ){
+ if( iColumn<0 ){
+ testcase( distinctColumns==0 );
+ distinctColumns = 1;
+ }
+ obSat |= MASKBIT(i);
+ if( (pWInfo->wctrlFlags & WHERE_GROUPBY)==0 ){
+ /* Make sure the sort order is compatible in an ORDER BY clause.
+ ** Sort order is irrelevant for a GROUP BY clause. */
+ if( revSet ){
+ if( (rev ^ revIdx)!=pOrderBy->a[i].sortOrder ) return 0;
+ }else{
+ rev = revIdx ^ pOrderBy->a[i].sortOrder;
+ if( rev ) *pRevMask |= MASKBIT(iLoop);
+ revSet = 1;
+ }
+ }
+ }else{
+ /* No match found */
+ if( j==0 || j<nColumn ){
+ testcase( isOrderDistinct!=0 );
+ isOrderDistinct = 0;
+ }
+ break;
+ }
+ } /* end Loop over all index columns */
+ if( distinctColumns ){
+ testcase( isOrderDistinct==0 );
+ isOrderDistinct = 1;
+ }
+ } /* end-if not one-row */
+
+ /* Mark off any other ORDER BY terms that reference pLoop */
+ if( isOrderDistinct ){
+ orderDistinctMask |= pLoop->maskSelf;
+ for(i=0; i<nOrderBy; i++){
+ Expr *p;
+ if( MASKBIT(i) & obSat ) continue;
+ p = pOrderBy->a[i].pExpr;
+ if( (exprTableUsage(&pWInfo->sMaskSet, p)&~orderDistinctMask)==0 ){
+ obSat |= MASKBIT(i);
+ }
+ }
+ }
+ } /* End the loop over all WhereLoops from outer-most down to inner-most */
+ if( obSat==obDone ) return 1;
+ if( !isOrderDistinct ) return 0;
+ return -1;
+}
+
+#ifdef WHERETRACE_ENABLED
+/* For debugging use only: */
+static const char *wherePathName(WherePath *pPath, int nLoop, WhereLoop *pLast){
+ static char zName[65];
+ int i;
+ for(i=0; i<nLoop; i++){ zName[i] = pPath->aLoop[i]->cId; }
+ if( pLast ) zName[i++] = pLast->cId;
+ zName[i] = 0;
+ return zName;
+}
+#endif
+
+
+/*
+** Given the list of WhereLoop objects at pWInfo->pLoops, this routine
+** attempts to find the lowest cost path that visits each WhereLoop
+** once. This path is then loaded into the pWInfo->a[].pWLoop fields.
+**
+** Assume that the total number of output rows that will need to be sorted
+** will be nRowEst (in the 10*log2 representation). Or, ignore sorting
+** costs if nRowEst==0.
+**
+** Return SQLITE_OK on success or SQLITE_NOMEM of a memory allocation
+** error occurs.
+*/
+static int wherePathSolver(WhereInfo *pWInfo, WhereCost nRowEst){
+ int mxChoice; /* Maximum number of simultaneous paths tracked */
+ int nLoop; /* Number of terms in the join */
+ Parse *pParse; /* Parsing context */
+ sqlite3 *db; /* The database connection */
+ int iLoop; /* Loop counter over the terms of the join */
+ int ii, jj; /* Loop counters */
+ WhereCost rCost; /* Cost of a path */
+ WhereCost mxCost = 0; /* Maximum cost of a set of paths */
+ WhereCost rSortCost; /* Cost to do a sort */
+ int nTo, nFrom; /* Number of valid entries in aTo[] and aFrom[] */
+ WherePath *aFrom; /* All nFrom paths at the previous level */
+ WherePath *aTo; /* The nTo best paths at the current level */
+ WherePath *pFrom; /* An element of aFrom[] that we are working on */
+ WherePath *pTo; /* An element of aTo[] that we are working on */
+ WhereLoop *pWLoop; /* One of the WhereLoop objects */
+ WhereLoop **pX; /* Used to divy up the pSpace memory */
+ char *pSpace; /* Temporary memory used by this routine */
+
+ pParse = pWInfo->pParse;
+ db = pParse->db;
+ nLoop = pWInfo->nLevel;
+ /* TUNING: For simple queries, only the best path is tracked.
+ ** For 2-way joins, the 5 best paths are followed.
+ ** For joins of 3 or more tables, track the 10 best paths */
+ mxChoice = (nLoop==1) ? 1 : (nLoop==2 ? 5 : 10);
+ assert( nLoop<=pWInfo->pTabList->nSrc );
+ WHERETRACE(0x002, ("---- begin solver\n"));
+
+ /* Allocate and initialize space for aTo and aFrom */
+ ii = (sizeof(WherePath)+sizeof(WhereLoop*)*nLoop)*mxChoice*2;
+ pSpace = sqlite3DbMallocRaw(db, ii);
+ if( pSpace==0 ) return SQLITE_NOMEM;
+ aTo = (WherePath*)pSpace;
+ aFrom = aTo+mxChoice;
+ memset(aFrom, 0, sizeof(aFrom[0]));
+ pX = (WhereLoop**)(aFrom+mxChoice);
+ for(ii=mxChoice*2, pFrom=aTo; ii>0; ii--, pFrom++, pX += nLoop){
+ pFrom->aLoop = pX;
+ }
+
+ /* Seed the search with a single WherePath containing zero WhereLoops.
+ **
+ ** TUNING: Do not let the number of iterations go above 25. If the cost
+ ** of computing an automatic index is not paid back within the first 25
+ ** rows, then do not use the automatic index. */
+ aFrom[0].nRow = MIN(pParse->nQueryLoop, 46); assert( 46==whereCost(25) );
+ nFrom = 1;
+
+ /* Precompute the cost of sorting the final result set, if the caller
+ ** to sqlite3WhereBegin() was concerned about sorting */
+ rSortCost = 0;
+ if( pWInfo->pOrderBy==0 || nRowEst==0 ){
+ aFrom[0].isOrderedValid = 1;
+ }else{
+ /* TUNING: Estimated cost of sorting is N*log2(N) where N is the
+ ** number of output rows. */
+ rSortCost = nRowEst + estLog(nRowEst);
+ WHERETRACE(0x002,("---- sort cost=%-3d\n", rSortCost));
+ }
+
+ /* Compute successively longer WherePaths using the previous generation
+ ** of WherePaths as the basis for the next. Keep track of the mxChoice
+ ** best paths at each generation */
+ for(iLoop=0; iLoop<nLoop; iLoop++){
+ nTo = 0;
+ for(ii=0, pFrom=aFrom; ii<nFrom; ii++, pFrom++){
+ for(pWLoop=pWInfo->pLoops; pWLoop; pWLoop=pWLoop->pNextLoop){
+ Bitmask maskNew;
+ Bitmask revMask = 0;
+ u8 isOrderedValid = pFrom->isOrderedValid;
+ u8 isOrdered = pFrom->isOrdered;
+ if( (pWLoop->prereq & ~pFrom->maskLoop)!=0 ) continue;
+ if( (pWLoop->maskSelf & pFrom->maskLoop)!=0 ) continue;
+ /* At this point, pWLoop is a candidate to be the next loop.
+ ** Compute its cost */
+ rCost = whereCostAdd(pWLoop->rSetup,pWLoop->rRun + pFrom->nRow);
+ rCost = whereCostAdd(rCost, pFrom->rCost);
+ maskNew = pFrom->maskLoop | pWLoop->maskSelf;
+ if( !isOrderedValid ){
+ switch( wherePathSatisfiesOrderBy(pWInfo,
+ pWInfo->pOrderBy, pFrom, pWInfo->wctrlFlags,
+ iLoop, pWLoop, &revMask) ){
+ case 1: /* Yes. pFrom+pWLoop does satisfy the ORDER BY clause */
+ isOrdered = 1;
+ isOrderedValid = 1;
+ break;
+ case 0: /* No. pFrom+pWLoop will require a separate sort */
+ isOrdered = 0;
+ isOrderedValid = 1;
+ rCost = whereCostAdd(rCost, rSortCost);
+ break;
+ default: /* Cannot tell yet. Try again on the next iteration */
+ break;
+ }
+ }else{
+ revMask = pFrom->revLoop;
+ }
+ /* Check to see if pWLoop should be added to the mxChoice best so far */
+ for(jj=0, pTo=aTo; jj<nTo; jj++, pTo++){
+ if( pTo->maskLoop==maskNew && pTo->isOrderedValid==isOrderedValid ){
+ testcase( jj==nTo-1 );
+ break;
+ }
+ }
+ if( jj>=nTo ){
+ if( nTo>=mxChoice && rCost>=mxCost ){
+#ifdef WHERETRACE_ENABLED
+ if( sqlite3WhereTrace&0x4 ){
+ sqlite3DebugPrintf("Skip %s cost=%3d order=%c\n",
+ wherePathName(pFrom, iLoop, pWLoop), rCost,
+ isOrderedValid ? (isOrdered ? 'Y' : 'N') : '?');
+ }
+#endif
+ continue;
+ }
+ /* Add a new Path to the aTo[] set */
+ if( nTo<mxChoice ){
+ /* Increase the size of the aTo set by one */
+ jj = nTo++;
+ }else{
+ /* New path replaces the prior worst to keep count below mxChoice */
+ for(jj=nTo-1; aTo[jj].rCost<mxCost; jj--){ assert(jj>0); }
+ }
+ pTo = &aTo[jj];
+#ifdef WHERETRACE_ENABLED
+ if( sqlite3WhereTrace&0x4 ){
+ sqlite3DebugPrintf("New %s cost=%-3d order=%c\n",
+ wherePathName(pFrom, iLoop, pWLoop), rCost,
+ isOrderedValid ? (isOrdered ? 'Y' : 'N') : '?');
+ }
+#endif
+ }else{
+ if( pTo->rCost<=rCost ){
+#ifdef WHERETRACE_ENABLED
+ if( sqlite3WhereTrace&0x4 ){
+ sqlite3DebugPrintf(
+ "Skip %s cost=%-3d order=%c",
+ wherePathName(pFrom, iLoop, pWLoop), rCost,
+ isOrderedValid ? (isOrdered ? 'Y' : 'N') : '?');
+ sqlite3DebugPrintf(" vs %s cost=%-3d order=%c\n",
+ wherePathName(pTo, iLoop+1, 0), pTo->rCost,
+ pTo->isOrderedValid ? (pTo->isOrdered ? 'Y' : 'N') : '?');
+ }
+#endif
+ testcase( pTo->rCost==rCost );
+ continue;
+ }
+ testcase( pTo->rCost==rCost+1 );
+ /* A new and better score for a previously created equivalent path */
+#ifdef WHERETRACE_ENABLED
+ if( sqlite3WhereTrace&0x4 ){
+ sqlite3DebugPrintf(
+ "Update %s cost=%-3d order=%c",
+ wherePathName(pFrom, iLoop, pWLoop), rCost,
+ isOrderedValid ? (isOrdered ? 'Y' : 'N') : '?');
+ sqlite3DebugPrintf(" was %s cost=%-3d order=%c\n",
+ wherePathName(pTo, iLoop+1, 0), pTo->rCost,
+ pTo->isOrderedValid ? (pTo->isOrdered ? 'Y' : 'N') : '?');
+ }
+#endif
+ }
+ /* pWLoop is a winner. Add it to the set of best so far */
+ pTo->maskLoop = pFrom->maskLoop | pWLoop->maskSelf;
+ pTo->revLoop = revMask;
+ pTo->nRow = pFrom->nRow + pWLoop->nOut;
+ pTo->rCost = rCost;
+ pTo->isOrderedValid = isOrderedValid;
+ pTo->isOrdered = isOrdered;
+ memcpy(pTo->aLoop, pFrom->aLoop, sizeof(WhereLoop*)*iLoop);
+ pTo->aLoop[iLoop] = pWLoop;
+ if( nTo>=mxChoice ){
+ mxCost = aTo[0].rCost;
+ for(jj=1, pTo=&aTo[1]; jj<mxChoice; jj++, pTo++){
+ if( pTo->rCost>mxCost ) mxCost = pTo->rCost;
+ }
+ }
+ }
+ }
+
+#ifdef WHERETRACE_ENABLED
+ if( sqlite3WhereTrace>=2 ){
+ sqlite3DebugPrintf("---- after round %d ----\n", iLoop);
+ for(ii=0, pTo=aTo; ii<nTo; ii++, pTo++){
+ sqlite3DebugPrintf(" %s cost=%-3d nrow=%-3d order=%c",
+ wherePathName(pTo, iLoop+1, 0), pTo->rCost, pTo->nRow,
+ pTo->isOrderedValid ? (pTo->isOrdered ? 'Y' : 'N') : '?');
+ if( pTo->isOrderedValid && pTo->isOrdered ){
+ sqlite3DebugPrintf(" rev=0x%llx\n", pTo->revLoop);
+ }else{
+ sqlite3DebugPrintf("\n");
+ }
+ }
+ }
+#endif
+
+ /* Swap the roles of aFrom and aTo for the next generation */
+ pFrom = aTo;
+ aTo = aFrom;
+ aFrom = pFrom;
+ nFrom = nTo;
}
+
+ if( nFrom==0 ){
+ sqlite3ErrorMsg(pParse, "no query solution");
+ sqlite3DbFree(db, pSpace);
+ return SQLITE_ERROR;
+ }
+
+ /* Find the lowest cost path. pFrom will be left pointing to that path */
+ pFrom = aFrom;
+ assert( nFrom==1 );
+#if 0 /* The following is needed if nFrom is ever more than 1 */
+ for(ii=1; ii<nFrom; ii++){
+ if( pFrom->rCost>aFrom[ii].rCost ) pFrom = &aFrom[ii];
+ }
+#endif
+ assert( pWInfo->nLevel==nLoop );
+ /* Load the lowest cost path into pWInfo */
+ for(iLoop=0; iLoop<nLoop; iLoop++){
+ WhereLevel *pLevel = pWInfo->a + iLoop;
+ pLevel->pWLoop = pWLoop = pFrom->aLoop[iLoop];
+ pLevel->iFrom = pWLoop->iTab;
+ pLevel->iTabCur = pWInfo->pTabList->a[pLevel->iFrom].iCursor;
+ }
+ if( (pWInfo->wctrlFlags & WHERE_WANT_DISTINCT)!=0
+ && (pWInfo->wctrlFlags & WHERE_DISTINCTBY)==0
+ && pWInfo->eDistinct==WHERE_DISTINCT_NOOP
+ && nRowEst
+ ){
+ Bitmask notUsed;
+ int rc = wherePathSatisfiesOrderBy(pWInfo, pWInfo->pResultSet, pFrom,
+ WHERE_DISTINCTBY, nLoop-1, pFrom->aLoop[nLoop-1], ¬Used);
+ if( rc==1 ) pWInfo->eDistinct = WHERE_DISTINCT_ORDERED;
+ }
+ if( pFrom->isOrdered ){
+ if( pWInfo->wctrlFlags & WHERE_DISTINCTBY ){
+ pWInfo->eDistinct = WHERE_DISTINCT_ORDERED;
+ }else{
+ pWInfo->bOBSat = 1;
+ pWInfo->revMask = pFrom->revLoop;
+ }
+ }
+ pWInfo->nRowOut = pFrom->nRow;
+
+ /* Free temporary memory and return success */
+ sqlite3DbFree(db, pSpace);
+ return SQLITE_OK;
}
+/*
+** Most queries use only a single table (they are not joins) and have
+** simple == constraints against indexed fields. This routine attempts
+** to plan those simple cases using much less ceremony than the
+** general-purpose query planner, and thereby yield faster sqlite3_prepare()
+** times for the common case.
+**
+** Return non-zero on success, if this query can be handled by this
+** no-frills query planner. Return zero if this query needs the
+** general-purpose query planner.
+*/
+static int whereShortCut(WhereLoopBuilder *pBuilder){
+ WhereInfo *pWInfo;
+ struct SrcList_item *pItem;
+ WhereClause *pWC;
+ WhereTerm *pTerm;
+ WhereLoop *pLoop;
+ int iCur;
+ int j;
+ Table *pTab;
+ Index *pIdx;
+
+ pWInfo = pBuilder->pWInfo;
+ if( pWInfo->wctrlFlags & WHERE_FORCE_TABLE ) return 0;
+ assert( pWInfo->pTabList->nSrc>=1 );
+ pItem = pWInfo->pTabList->a;
+ pTab = pItem->pTab;
+ if( IsVirtual(pTab) ) return 0;
+ if( pItem->zIndex ) return 0;
+ iCur = pItem->iCursor;
+ pWC = &pWInfo->sWC;
+ pLoop = pBuilder->pNew;
+ pLoop->wsFlags = 0;
+ pTerm = findTerm(pWC, iCur, -1, 0, WO_EQ, 0);
+ if( pTerm ){
+ pLoop->wsFlags = WHERE_COLUMN_EQ|WHERE_IPK|WHERE_ONEROW;
+ pLoop->aLTerm[0] = pTerm;
+ pLoop->nLTerm = 1;
+ pLoop->u.btree.nEq = 1;
+ /* TUNING: Cost of a rowid lookup is 10 */
+ pLoop->rRun = 33; /* 33==whereCost(10) */
+ }else{
+ for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
+ assert( pLoop->aLTermSpace==pLoop->aLTerm );
+ assert( ArraySize(pLoop->aLTermSpace)==4 );
+ if( pIdx->onError==OE_None
+ || pIdx->pPartIdxWhere!=0
+ || pIdx->nColumn>ArraySize(pLoop->aLTermSpace)
+ ) continue;
+ for(j=0; j<pIdx->nColumn; j++){
+ pTerm = findTerm(pWC, iCur, pIdx->aiColumn[j], 0, WO_EQ, pIdx);
+ if( pTerm==0 ) break;
+ pLoop->aLTerm[j] = pTerm;
+ }
+ if( j!=pIdx->nColumn ) continue;
+ pLoop->wsFlags = WHERE_COLUMN_EQ|WHERE_ONEROW|WHERE_INDEXED;
+ if( (pItem->colUsed & ~columnsInIndex(pIdx))==0 ){
+ pLoop->wsFlags |= WHERE_IDX_ONLY;
+ }
+ pLoop->nLTerm = j;
+ pLoop->u.btree.nEq = j;
+ pLoop->u.btree.pIndex = pIdx;
+ /* TUNING: Cost of a unique index lookup is 15 */
+ pLoop->rRun = 39; /* 39==whereCost(15) */
+ break;
+ }
+ }
+ if( pLoop->wsFlags ){
+ pLoop->nOut = (WhereCost)1;
+ pWInfo->a[0].pWLoop = pLoop;
+ pLoop->maskSelf = getMask(&pWInfo->sMaskSet, iCur);
+ pWInfo->a[0].iTabCur = iCur;
+ pWInfo->nRowOut = 1;
+ if( pWInfo->pOrderBy ) pWInfo->bOBSat = 1;
+ if( pWInfo->wctrlFlags & WHERE_WANT_DISTINCT ){
+ pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE;
+ }
+#ifdef SQLITE_DEBUG
+ pLoop->cId = '0';
+#endif
+ return 1;
+ }
+ return 0;
+}
/*
** Generate the beginning of the loop used for WHERE clause processing.
@@ -109463,25 +110476,17 @@ static void whereInfoFree(sqlite3 *db, WhereInfo *pWInfo){
**
** ORDER BY CLAUSE PROCESSING
**
-** pOrderBy is a pointer to the ORDER BY clause of a SELECT statement,
+** pOrderBy is a pointer to the ORDER BY clause (or the GROUP BY clause
+** if the WHERE_GROUPBY flag is set in wctrlFlags) of a SELECT statement
** if there is one. If there is no ORDER BY clause or if this routine
** is called from an UPDATE or DELETE statement, then pOrderBy is NULL.
-**
-** If an index can be used so that the natural output order of the table
-** scan is correct for the ORDER BY clause, then that index is used and
-** the returned WhereInfo.nOBSat field is set to pOrderBy->nExpr. This
-** is an optimization that prevents an unnecessary sort of the result set
-** if an index appropriate for the ORDER BY clause already exists.
-**
-** If the where clause loops cannot be arranged to provide the correct
-** output order, then WhereInfo.nOBSat is 0.
*/
SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
Parse *pParse, /* The parser context */
- SrcList *pTabList, /* A list of all tables to be scanned */
+ SrcList *pTabList, /* FROM clause: A list of all tables to be scanned */
Expr *pWhere, /* The WHERE clause */
ExprList *pOrderBy, /* An ORDER BY clause, or NULL */
- ExprList *pDistinct, /* The select-list for DISTINCT queries - or NULL */
+ ExprList *pResultSet, /* Result set of the query */
u16 wctrlFlags, /* One of the WHERE_* flags defined in sqliteInt.h */
int iIdxCur /* If WHERE_ONETABLE_ONLY is set, index cursor number */
){
@@ -109490,18 +110495,25 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
WhereInfo *pWInfo; /* Will become the return value of this function */
Vdbe *v = pParse->pVdbe; /* The virtual database engine */
Bitmask notReady; /* Cursors that are not yet positioned */
- WhereBestIdx sWBI; /* Best index search context */
+ WhereLoopBuilder sWLB; /* The WhereLoop builder */
WhereMaskSet *pMaskSet; /* The expression mask set */
WhereLevel *pLevel; /* A single level in pWInfo->a[] */
- int iFrom; /* First unused FROM clause element */
- int andFlags; /* AND-ed combination of all pWC->a[].wtFlags */
+ WhereLoop *pLoop; /* Pointer to a single WhereLoop object */
int ii; /* Loop counter */
sqlite3 *db; /* Database connection */
+ int rc; /* Return code */
/* Variable initialization */
- memset(&sWBI, 0, sizeof(sWBI));
- sWBI.pParse = pParse;
+ db = pParse->db;
+ memset(&sWLB, 0, sizeof(sWLB));
+ sWLB.pOrderBy = pOrderBy;
+
+ /* Disable the DISTINCT optimization if SQLITE_DistinctOpt is set via
+ ** sqlite3_test_ctrl(SQLITE_TESTCTRL_OPTIMIZATIONS,...) */
+ if( OptimizationDisabled(db, SQLITE_DistinctOpt) ){
+ wctrlFlags &= ~WHERE_WANT_DISTINCT;
+ }
/* The number of tables in the FROM clause is limited by the number of
** bits in a Bitmask
@@ -109526,13 +110538,8 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
** field (type Bitmask) it must be aligned on an 8-byte boundary on
** some architectures. Hence the ROUND8() below.
*/
- db = pParse->db;
nByteWInfo = ROUND8(sizeof(WhereInfo)+(nTabList-1)*sizeof(WhereLevel));
- pWInfo = sqlite3DbMallocZero(db,
- nByteWInfo +
- sizeof(WhereClause) +
- sizeof(WhereMaskSet)
- );
+ pWInfo = sqlite3DbMallocZero(db, nByteWInfo + sizeof(WhereLoop));
if( db->mallocFailed ){
sqlite3DbFree(db, pWInfo);
pWInfo = 0;
@@ -109541,24 +110548,29 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
pWInfo->nLevel = nTabList;
pWInfo->pParse = pParse;
pWInfo->pTabList = pTabList;
+ pWInfo->pOrderBy = pOrderBy;
+ pWInfo->pResultSet = pResultSet;
pWInfo->iBreak = sqlite3VdbeMakeLabel(v);
- pWInfo->pWC = sWBI.pWC = (WhereClause *)&((u8 *)pWInfo)[nByteWInfo];
pWInfo->wctrlFlags = wctrlFlags;
pWInfo->savedNQueryLoop = pParse->nQueryLoop;
- pMaskSet = (WhereMaskSet*)&sWBI.pWC[1];
- sWBI.aLevel = pWInfo->a;
-
- /* Disable the DISTINCT optimization if SQLITE_DistinctOpt is set via
- ** sqlite3_test_ctrl(SQLITE_TESTCTRL_OPTIMIZATIONS,...) */
- if( OptimizationDisabled(db, SQLITE_DistinctOpt) ) pDistinct = 0;
+ pMaskSet = &pWInfo->sMaskSet;
+ sWLB.pWInfo = pWInfo;
+ sWLB.pWC = &pWInfo->sWC;
+ sWLB.pNew = (WhereLoop*)(((char*)pWInfo)+nByteWInfo);
+ assert( EIGHT_BYTE_ALIGNMENT(sWLB.pNew) );
+ whereLoopInit(sWLB.pNew);
+#ifdef SQLITE_DEBUG
+ sWLB.pNew->cId = '*';
+#endif
/* Split the WHERE clause into separate subexpressions where each
** subexpression is separated by an AND operator.
*/
initMaskSet(pMaskSet);
- whereClauseInit(sWBI.pWC, pParse, pMaskSet, wctrlFlags);
+ whereClauseInit(&pWInfo->sWC, pWInfo);
sqlite3ExprCodeConstants(pParse, pWhere);
- whereSplit(sWBI.pWC, pWhere, TK_AND); /* IMP: R-15842-53296 */
+ whereSplit(&pWInfo->sWC, pWhere, TK_AND);
+ sqlite3CodeVerifySchema(pParse, -1); /* Insert the cookie verifier Goto */
/* Special case: a WHERE clause that is constant. Evaluate the
** expression and either jump over all of the code or fall thru.
@@ -109568,6 +110580,15 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
pWhere = 0;
}
+ /* Special case: No FROM clause
+ */
+ if( nTabList==0 ){
+ if( pOrderBy ) pWInfo->bOBSat = 1;
+ if( wctrlFlags & WHERE_WANT_DISTINCT ){
+ pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE;
+ }
+ }
+
/* Assign a bit from the bitmask to every term in the FROM clause.
**
** When assigning bitmask values to FROM clause cursors, it must be
@@ -109603,288 +110624,131 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
** want to analyze these virtual terms, so start analyzing at the end
** and work forward so that the added virtual terms are never processed.
*/
- exprAnalyzeAll(pTabList, sWBI.pWC);
+ exprAnalyzeAll(pTabList, &pWInfo->sWC);
if( db->mallocFailed ){
goto whereBeginError;
}
- /* Check if the DISTINCT qualifier, if there is one, is redundant.
- ** If it is, then set pDistinct to NULL and WhereInfo.eDistinct to
- ** WHERE_DISTINCT_UNIQUE to tell the caller to ignore the DISTINCT.
+ /* If the ORDER BY (or GROUP BY) clause contains references to general
+ ** expressions, then we won't be able to satisfy it using indices, so
+ ** go ahead and disable it now.
*/
- if( pDistinct && isDistinctRedundant(pParse, pTabList, sWBI.pWC, pDistinct) ){
- pDistinct = 0;
- pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE;
+ if( pOrderBy && (wctrlFlags & WHERE_WANT_DISTINCT)!=0 ){
+ for(ii=0; ii<pOrderBy->nExpr; ii++){
+ Expr *pExpr = sqlite3ExprSkipCollate(pOrderBy->a[ii].pExpr);
+ if( pExpr->op!=TK_COLUMN ){
+ pWInfo->pOrderBy = pOrderBy = 0;
+ break;
+ }else if( pExpr->iColumn<0 ){
+ break;
+ }
+ }
}
- /* Chose the best index to use for each table in the FROM clause.
- **
- ** This loop fills in the following fields:
- **
- ** pWInfo->a[].pIdx The index to use for this level of the loop.
- ** pWInfo->a[].wsFlags WHERE_xxx flags associated with pIdx
- ** pWInfo->a[].nEq The number of == and IN constraints
- ** pWInfo->a[].iFrom Which term of the FROM clause is being coded
- ** pWInfo->a[].iTabCur The VDBE cursor for the database table
- ** pWInfo->a[].iIdxCur The VDBE cursor for the index
- ** pWInfo->a[].pTerm When wsFlags==WO_OR, the OR-clause term
- **
- ** This loop also figures out the nesting order of tables in the FROM
- ** clause.
- */
- sWBI.notValid = ~(Bitmask)0;
- sWBI.pOrderBy = pOrderBy;
- sWBI.n = nTabList;
- sWBI.pDistinct = pDistinct;
- andFlags = ~0;
- WHERETRACE(("*** Optimizer Start ***\n"));
- for(sWBI.i=iFrom=0, pLevel=pWInfo->a; sWBI.i<nTabList; sWBI.i++, pLevel++){
- WhereCost bestPlan; /* Most efficient plan seen so far */
- Index *pIdx; /* Index for FROM table at pTabItem */
- int j; /* For looping over FROM tables */
- int bestJ = -1; /* The value of j */
- Bitmask m; /* Bitmask value for j or bestJ */
- int isOptimal; /* Iterator for optimal/non-optimal search */
- int ckOptimal; /* Do the optimal scan check */
- int nUnconstrained; /* Number tables without INDEXED BY */
- Bitmask notIndexed; /* Mask of tables that cannot use an index */
-
- memset(&bestPlan, 0, sizeof(bestPlan));
- bestPlan.rCost = SQLITE_BIG_DBL;
- WHERETRACE(("*** Begin search for loop %d ***\n", sWBI.i));
-
- /* Loop through the remaining entries in the FROM clause to find the
- ** next nested loop. The loop tests all FROM clause entries
- ** either once or twice.
- **
- ** The first test is always performed if there are two or more entries
- ** remaining and never performed if there is only one FROM clause entry
- ** to choose from. The first test looks for an "optimal" scan. In
- ** this context an optimal scan is one that uses the same strategy
- ** for the given FROM clause entry as would be selected if the entry
- ** were used as the innermost nested loop. In other words, a table
- ** is chosen such that the cost of running that table cannot be reduced
- ** by waiting for other tables to run first. This "optimal" test works
- ** by first assuming that the FROM clause is on the inner loop and finding
- ** its query plan, then checking to see if that query plan uses any
- ** other FROM clause terms that are sWBI.notValid. If no notValid terms
- ** are used then the "optimal" query plan works.
- **
- ** Note that the WhereCost.nRow parameter for an optimal scan might
- ** not be as small as it would be if the table really were the innermost
- ** join. The nRow value can be reduced by WHERE clause constraints
- ** that do not use indices. But this nRow reduction only happens if the
- ** table really is the innermost join.
- **
- ** The second loop iteration is only performed if no optimal scan
- ** strategies were found by the first iteration. This second iteration
- ** is used to search for the lowest cost scan overall.
- **
- ** Without the optimal scan step (the first iteration) a suboptimal
- ** plan might be chosen for queries like this:
- **
- ** CREATE TABLE t1(a, b);
- ** CREATE TABLE t2(c, d);
- ** SELECT * FROM t2, t1 WHERE t2.rowid = t1.a;
- **
- ** The best strategy is to iterate through table t1 first. However it
- ** is not possible to determine this with a simple greedy algorithm.
- ** Since the cost of a linear scan through table t2 is the same
- ** as the cost of a linear scan through table t1, a simple greedy
- ** algorithm may choose to use t2 for the outer loop, which is a much
- ** costlier approach.
- */
- nUnconstrained = 0;
- notIndexed = 0;
-
- /* The optimal scan check only occurs if there are two or more tables
- ** available to be reordered */
- if( iFrom==nTabList-1 ){
- ckOptimal = 0; /* Common case of just one table in the FROM clause */
- }else{
- ckOptimal = -1;
- for(j=iFrom, sWBI.pSrc=&pTabList->a[j]; j<nTabList; j++, sWBI.pSrc++){
- m = getMask(pMaskSet, sWBI.pSrc->iCursor);
- if( (m & sWBI.notValid)==0 ){
- if( j==iFrom ) iFrom++;
- continue;
- }
- if( j>iFrom && (sWBI.pSrc->jointype & (JT_LEFT|JT_CROSS))!=0 ) break;
- if( ++ckOptimal ) break;
- if( (sWBI.pSrc->jointype & JT_LEFT)!=0 ) break;
- }
+ if( wctrlFlags & WHERE_WANT_DISTINCT ){
+ if( isDistinctRedundant(pParse, pTabList, &pWInfo->sWC, pResultSet) ){
+ /* The DISTINCT marking is pointless. Ignore it. */
+ pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE;
+ }else if( pOrderBy==0 ){
+ /* Try to ORDER BY the result set to make distinct processing easier */
+ pWInfo->wctrlFlags |= WHERE_DISTINCTBY;
+ pWInfo->pOrderBy = pResultSet;
}
- assert( ckOptimal==0 || ckOptimal==1 );
+ }
- for(isOptimal=ckOptimal; isOptimal>=0 && bestJ<0; isOptimal--){
- for(j=iFrom, sWBI.pSrc=&pTabList->a[j]; j<nTabList; j++, sWBI.pSrc++){
- if( j>iFrom && (sWBI.pSrc->jointype & (JT_LEFT|JT_CROSS))!=0 ){
- /* This break and one like it in the ckOptimal computation loop
- ** above prevent table reordering across LEFT and CROSS JOINs.
- ** The LEFT JOIN case is necessary for correctness. The prohibition
- ** against reordering across a CROSS JOIN is an SQLite feature that
- ** allows the developer to control table reordering */
- break;
- }
- m = getMask(pMaskSet, sWBI.pSrc->iCursor);
- if( (m & sWBI.notValid)==0 ){
- assert( j>iFrom );
- continue;
- }
- sWBI.notReady = (isOptimal ? m : sWBI.notValid);
- if( sWBI.pSrc->pIndex==0 ) nUnconstrained++;
+ /* Construct the WhereLoop objects */
+ WHERETRACE(0xffff,("*** Optimizer Start ***\n"));
+ if( nTabList!=1 || whereShortCut(&sWLB)==0 ){
+ rc = whereLoopAddAll(&sWLB);
+ if( rc ) goto whereBeginError;
- WHERETRACE((" === trying table %d (%s) with isOptimal=%d ===\n",
- j, sWBI.pSrc->pTab->zName, isOptimal));
- assert( sWBI.pSrc->pTab );
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- if( IsVirtual(sWBI.pSrc->pTab) ){
- sWBI.ppIdxInfo = &pWInfo->a[j].pIdxInfo;
- bestVirtualIndex(&sWBI);
- }else
-#endif
- {
- bestBtreeIndex(&sWBI);
- }
- assert( isOptimal || (sWBI.cost.used&sWBI.notValid)==0 );
-
- /* If an INDEXED BY clause is present, then the plan must use that
- ** index if it uses any index at all */
- assert( sWBI.pSrc->pIndex==0
- || (sWBI.cost.plan.wsFlags & WHERE_NOT_FULLSCAN)==0
- || sWBI.cost.plan.u.pIdx==sWBI.pSrc->pIndex );
-
- if( isOptimal && (sWBI.cost.plan.wsFlags & WHERE_NOT_FULLSCAN)==0 ){
- notIndexed |= m;
- }
- if( isOptimal ){
- pWInfo->a[j].rOptCost = sWBI.cost.rCost;
- }else if( ckOptimal ){
- /* If two or more tables have nearly the same outer loop cost, but
- ** very different inner loop (optimal) cost, we want to choose
- ** for the outer loop that table which benefits the least from
- ** being in the inner loop. The following code scales the
- ** outer loop cost estimate to accomplish that. */
- WHERETRACE((" scaling cost from %.1f to %.1f\n",
- sWBI.cost.rCost,
- sWBI.cost.rCost/pWInfo->a[j].rOptCost));
- sWBI.cost.rCost /= pWInfo->a[j].rOptCost;
- }
-
- /* Conditions under which this table becomes the best so far:
- **
- ** (1) The table must not depend on other tables that have not
- ** yet run. (In other words, it must not depend on tables
- ** in inner loops.)
- **
- ** (2) (This rule was removed on 2012-11-09. The scaling of the
- ** cost using the optimal scan cost made this rule obsolete.)
- **
- ** (3) All tables have an INDEXED BY clause or this table lacks an
- ** INDEXED BY clause or this table uses the specific
- ** index specified by its INDEXED BY clause. This rule ensures
- ** that a best-so-far is always selected even if an impossible
- ** combination of INDEXED BY clauses are given. The error
- ** will be detected and relayed back to the application later.
- ** The NEVER() comes about because rule (2) above prevents
- ** An indexable full-table-scan from reaching rule (3).
- **
- ** (4) The plan cost must be lower than prior plans, where "cost"
- ** is defined by the compareCost() function above.
- */
- if( (sWBI.cost.used&sWBI.notValid)==0 /* (1) */
- && (nUnconstrained==0 || sWBI.pSrc->pIndex==0 /* (3) */
- || NEVER((sWBI.cost.plan.wsFlags & WHERE_NOT_FULLSCAN)!=0))
- && (bestJ<0 || compareCost(&sWBI.cost, &bestPlan)) /* (4) */
- ){
- WHERETRACE((" === table %d (%s) is best so far\n"
- " cost=%.1f, nRow=%.1f, nOBSat=%d, wsFlags=%08x\n",
- j, sWBI.pSrc->pTab->zName,
- sWBI.cost.rCost, sWBI.cost.plan.nRow,
- sWBI.cost.plan.nOBSat, sWBI.cost.plan.wsFlags));
- bestPlan = sWBI.cost;
- bestJ = j;
- }
-
- /* In a join like "w JOIN x LEFT JOIN y JOIN z" make sure that
- ** table y (and not table z) is always the next inner loop inside
- ** of table x. */
- if( (sWBI.pSrc->jointype & JT_LEFT)!=0 ) break;
- }
- }
- assert( bestJ>=0 );
- assert( sWBI.notValid & getMask(pMaskSet, pTabList->a[bestJ].iCursor) );
- assert( bestJ==iFrom || (pTabList->a[iFrom].jointype & JT_LEFT)==0 );
- testcase( bestJ>iFrom && (pTabList->a[iFrom].jointype & JT_CROSS)!=0 );
- testcase( bestJ>iFrom && bestJ<nTabList-1
- && (pTabList->a[bestJ+1].jointype & JT_LEFT)!=0 );
- WHERETRACE(("*** Optimizer selects table %d (%s) for loop %d with:\n"
- " cost=%.1f, nRow=%.1f, nOBSat=%d, wsFlags=0x%08x\n",
- bestJ, pTabList->a[bestJ].pTab->zName,
- pLevel-pWInfo->a, bestPlan.rCost, bestPlan.plan.nRow,
- bestPlan.plan.nOBSat, bestPlan.plan.wsFlags));
- if( (bestPlan.plan.wsFlags & WHERE_DISTINCT)!=0 ){
- assert( pWInfo->eDistinct==0 );
- pWInfo->eDistinct = WHERE_DISTINCT_ORDERED;
- }
- andFlags &= bestPlan.plan.wsFlags;
- pLevel->plan = bestPlan.plan;
- pLevel->iTabCur = pTabList->a[bestJ].iCursor;
- testcase( bestPlan.plan.wsFlags & WHERE_INDEXED );
- testcase( bestPlan.plan.wsFlags & WHERE_TEMP_INDEX );
- if( bestPlan.plan.wsFlags & (WHERE_INDEXED|WHERE_TEMP_INDEX) ){
- if( (wctrlFlags & WHERE_ONETABLE_ONLY)
- && (bestPlan.plan.wsFlags & WHERE_TEMP_INDEX)==0
- ){
- pLevel->iIdxCur = iIdxCur;
- }else{
- pLevel->iIdxCur = pParse->nTab++;
+ /* Display all of the WhereLoop objects if wheretrace is enabled */
+#ifdef WHERETRACE_ENABLED
+ if( sqlite3WhereTrace ){
+ WhereLoop *p;
+ int i;
+ static char zLabel[] = "0123456789abcdefghijklmnopqrstuvwyxz"
+ "ABCDEFGHIJKLMNOPQRSTUVWYXZ";
+ for(p=pWInfo->pLoops, i=0; p; p=p->pNextLoop, i++){
+ p->cId = zLabel[i%sizeof(zLabel)];
+ whereLoopPrint(p, pTabList);
}
- }else{
- pLevel->iIdxCur = -1;
- }
- sWBI.notValid &= ~getMask(pMaskSet, pTabList->a[bestJ].iCursor);
- pLevel->iFrom = (u8)bestJ;
- if( bestPlan.plan.nRow>=(double)1 ){
- pParse->nQueryLoop *= bestPlan.plan.nRow;
}
-
- /* Check that if the table scanned by this loop iteration had an
- ** INDEXED BY clause attached to it, that the named index is being
- ** used for the scan. If not, then query compilation has failed.
- ** Return an error.
- */
- pIdx = pTabList->a[bestJ].pIndex;
- if( pIdx ){
- if( (bestPlan.plan.wsFlags & WHERE_INDEXED)==0 ){
- sqlite3ErrorMsg(pParse, "cannot use index: %s", pIdx->zName);
- goto whereBeginError;
- }else{
- /* If an INDEXED BY clause is used, the bestIndex() function is
- ** guaranteed to find the index specified in the INDEXED BY clause
- ** if it find an index at all. */
- assert( bestPlan.plan.u.pIdx==pIdx );
- }
+#endif
+
+ wherePathSolver(pWInfo, 0);
+ if( db->mallocFailed ) goto whereBeginError;
+ if( pWInfo->pOrderBy ){
+ wherePathSolver(pWInfo, pWInfo->nRowOut+1);
+ if( db->mallocFailed ) goto whereBeginError;
}
}
- WHERETRACE(("*** Optimizer Finished ***\n"));
- if( pParse->nErr || db->mallocFailed ){
+ if( pWInfo->pOrderBy==0 && (db->flags & SQLITE_ReverseOrder)!=0 ){
+ pWInfo->revMask = (Bitmask)(-1);
+ }
+ if( pParse->nErr || NEVER(db->mallocFailed) ){
goto whereBeginError;
}
- if( nTabList ){
- pLevel--;
- pWInfo->nOBSat = pLevel->plan.nOBSat;
- }else{
- pWInfo->nOBSat = 0;
+#ifdef WHERETRACE_ENABLED
+ if( sqlite3WhereTrace ){
+ int ii;
+ sqlite3DebugPrintf("---- Solution nRow=%d", pWInfo->nRowOut);
+ if( pWInfo->bOBSat ){
+ sqlite3DebugPrintf(" ORDERBY=0x%llx", pWInfo->revMask);
+ }
+ switch( pWInfo->eDistinct ){
+ case WHERE_DISTINCT_UNIQUE: {
+ sqlite3DebugPrintf(" DISTINCT=unique");
+ break;
+ }
+ case WHERE_DISTINCT_ORDERED: {
+ sqlite3DebugPrintf(" DISTINCT=ordered");
+ break;
+ }
+ case WHERE_DISTINCT_UNORDERED: {
+ sqlite3DebugPrintf(" DISTINCT=unordered");
+ break;
+ }
+ }
+ sqlite3DebugPrintf("\n");
+ for(ii=0; ii<pWInfo->nLevel; ii++){
+ whereLoopPrint(pWInfo->a[ii].pWLoop, pTabList);
+ }
}
-
- /* If the total query only selects a single row, then the ORDER BY
- ** clause is irrelevant.
- */
- if( (andFlags & WHERE_UNIQUE)!=0 && pOrderBy ){
- assert( nTabList==0 || (pLevel->plan.wsFlags & WHERE_ALL_UNIQUE)!=0 );
- pWInfo->nOBSat = pOrderBy->nExpr;
+#endif
+ /* Attempt to omit tables from the join that do not effect the result */
+ if( pWInfo->nLevel>=2
+ && pResultSet!=0
+ && OptimizationEnabled(db, SQLITE_OmitNoopJoin)
+ ){
+ Bitmask tabUsed = exprListTableUsage(pMaskSet, pResultSet);
+ if( sWLB.pOrderBy ) tabUsed |= exprListTableUsage(pMaskSet, sWLB.pOrderBy);
+ while( pWInfo->nLevel>=2 ){
+ WhereTerm *pTerm, *pEnd;
+ pLoop = pWInfo->a[pWInfo->nLevel-1].pWLoop;
+ if( (pWInfo->pTabList->a[pLoop->iTab].jointype & JT_LEFT)==0 ) break;
+ if( (wctrlFlags & WHERE_WANT_DISTINCT)==0
+ && (pLoop->wsFlags & WHERE_ONEROW)==0
+ ){
+ break;
+ }
+ if( (tabUsed & pLoop->maskSelf)!=0 ) break;
+ pEnd = sWLB.pWC->a + sWLB.pWC->nTerm;
+ for(pTerm=sWLB.pWC->a; pTerm<pEnd; pTerm++){
+ if( (pTerm->prereqAll & pLoop->maskSelf)!=0
+ && !ExprHasProperty(pTerm->pExpr, EP_FromJoin)
+ ){
+ break;
+ }
+ }
+ if( pTerm<pEnd ) break;
+ WHERETRACE(0xffff, ("-> drop loop %c not used\n", pLoop->cId));
+ pWInfo->nLevel--;
+ nTabList--;
+ }
}
+ WHERETRACE(0xffff,("*** Optimizer Finished ***\n"));
+ pWInfo->pParse->nQueryLoop += pWInfo->nRowOut;
/* If the caller is an UPDATE or DELETE statement that is requesting
** to use a one-pass algorithm, determine if this is appropriate.
@@ -109892,17 +110756,16 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
** the statement to update a single row.
*/
assert( (wctrlFlags & WHERE_ONEPASS_DESIRED)==0 || pWInfo->nLevel==1 );
- if( (wctrlFlags & WHERE_ONEPASS_DESIRED)!=0 && (andFlags & WHERE_UNIQUE)!=0 ){
+ if( (wctrlFlags & WHERE_ONEPASS_DESIRED)!=0
+ && (pWInfo->a[0].pWLoop->wsFlags & WHERE_ONEROW)!=0 ){
pWInfo->okOnePass = 1;
- pWInfo->a[0].plan.wsFlags &= ~WHERE_IDX_ONLY;
+ pWInfo->a[0].pWLoop->wsFlags &= ~WHERE_IDX_ONLY;
}
/* Open all tables in the pTabList and any indices selected for
** searching those tables.
*/
- sqlite3CodeVerifySchema(pParse, -1); /* Insert the cookie verifier Goto */
notReady = ~(Bitmask)0;
- pWInfo->nRowOut = (double)1;
for(ii=0, pLevel=pWInfo->a; ii<nTabList; ii++, pLevel++){
Table *pTab; /* Table to open */
int iDb; /* Index of database containing table/index */
@@ -109910,13 +110773,13 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
pTabItem = &pTabList->a[pLevel->iFrom];
pTab = pTabItem->pTab;
- pWInfo->nRowOut *= pLevel->plan.nRow;
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
+ pLoop = pLevel->pWLoop;
if( (pTab->tabFlags & TF_Ephemeral)!=0 || pTab->pSelect ){
/* Do nothing */
}else
#ifndef SQLITE_OMIT_VIRTUALTABLE
- if( (pLevel->plan.wsFlags & WHERE_VIRTUALTABLE)!=0 ){
+ if( (pLoop->wsFlags & WHERE_VIRTUALTABLE)!=0 ){
const char *pVTab = (const char *)sqlite3GetVTable(db, pTab);
int iCur = pTabItem->iCursor;
sqlite3VdbeAddOp4(v, OP_VOpen, iCur, 0, 0, pVTab, P4_VTAB);
@@ -109924,12 +110787,12 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
/* noop */
}else
#endif
- if( (pLevel->plan.wsFlags & WHERE_IDX_ONLY)==0
+ if( (pLoop->wsFlags & WHERE_IDX_ONLY)==0
&& (wctrlFlags & WHERE_OMIT_OPEN_CLOSE)==0 ){
int op = pWInfo->okOnePass ? OP_OpenWrite : OP_OpenRead;
sqlite3OpenTable(pParse, pTabItem->iCursor, iDb, pTab, op);
- testcase( pTab->nCol==BMS-1 );
- testcase( pTab->nCol==BMS );
+ testcase( !pWInfo->okOnePass && pTab->nCol==BMS-1 );
+ testcase( !pWInfo->okOnePass && pTab->nCol==BMS );
if( !pWInfo->okOnePass && pTab->nCol<BMS ){
Bitmask b = pTabItem->colUsed;
int n = 0;
@@ -109941,15 +110804,11 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
}else{
sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName);
}
-#ifndef SQLITE_OMIT_AUTOMATIC_INDEX
- if( (pLevel->plan.wsFlags & WHERE_TEMP_INDEX)!=0 ){
- constructAutomaticIndex(pParse, sWBI.pWC, pTabItem, notReady, pLevel);
- }else
-#endif
- if( (pLevel->plan.wsFlags & WHERE_INDEXED)!=0 ){
- Index *pIx = pLevel->plan.u.pIdx;
+ if( pLoop->wsFlags & WHERE_INDEXED ){
+ Index *pIx = pLoop->u.btree.pIndex;
KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIx);
- int iIndexCur = pLevel->iIdxCur;
+ /* FIXME: As an optimization use pTabItem->iCursor if WHERE_IDX_ONLY */
+ int iIndexCur = pLevel->iIdxCur = iIdxCur ? iIdxCur : pParse->nTab++;
assert( pIx->pSchema==pTab->pSchema );
assert( iIndexCur>=0 );
sqlite3VdbeAddOp4(v, OP_OpenRead, iIndexCur, pIx->tnum, iDb,
@@ -109957,7 +110816,7 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
VdbeComment((v, "%s", pIx->zName));
}
sqlite3CodeVerifySchema(pParse, iDb);
- notReady &= ~getMask(sWBI.pWC->pMaskSet, pTabItem->iCursor);
+ notReady &= ~getMask(&pWInfo->sMaskSet, pTabItem->iCursor);
}
pWInfo->iTop = sqlite3VdbeCurrentAddr(v);
if( db->mallocFailed ) goto whereBeginError;
@@ -109969,67 +110828,20 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
notReady = ~(Bitmask)0;
for(ii=0; ii<nTabList; ii++){
pLevel = &pWInfo->a[ii];
+#ifndef SQLITE_OMIT_AUTOMATIC_INDEX
+ if( (pLevel->pWLoop->wsFlags & WHERE_AUTO_INDEX)!=0 ){
+ constructAutomaticIndex(pParse, &pWInfo->sWC,
+ &pTabList->a[pLevel->iFrom], notReady, pLevel);
+ if( db->mallocFailed ) goto whereBeginError;
+ }
+#endif
explainOneScan(pParse, pTabList, pLevel, ii, pLevel->iFrom, wctrlFlags);
- notReady = codeOneLoopStart(pWInfo, ii, wctrlFlags, notReady);
+ pLevel->addrBody = sqlite3VdbeCurrentAddr(v);
+ notReady = codeOneLoopStart(pWInfo, ii, notReady);
pWInfo->iContinue = pLevel->addrCont;
}
-#ifdef SQLITE_TEST /* For testing and debugging use only */
- /* Record in the query plan information about the current table
- ** and the index used to access it (if any). If the table itself
- ** is not used, its name is just '{}'. If no index is used
- ** the index is listed as "{}". If the primary key is used the
- ** index name is '*'.
- */
- for(ii=0; ii<nTabList; ii++){
- char *z;
- int n;
- int w;
- struct SrcList_item *pTabItem;
-
- pLevel = &pWInfo->a[ii];
- w = pLevel->plan.wsFlags;
- pTabItem = &pTabList->a[pLevel->iFrom];
- z = pTabItem->zAlias;
- if( z==0 ) z = pTabItem->pTab->zName;
- n = sqlite3Strlen30(z);
- if( n+nQPlan < sizeof(sqlite3_query_plan)-10 ){
- if( (w & WHERE_IDX_ONLY)!=0 && (w & WHERE_COVER_SCAN)==0 ){
- memcpy(&sqlite3_query_plan[nQPlan], "{}", 2);
- nQPlan += 2;
- }else{
- memcpy(&sqlite3_query_plan[nQPlan], z, n);
- nQPlan += n;
- }
- sqlite3_query_plan[nQPlan++] = ' ';
- }
- testcase( w & WHERE_ROWID_EQ );
- testcase( w & WHERE_ROWID_RANGE );
- if( w & (WHERE_ROWID_EQ|WHERE_ROWID_RANGE) ){
- memcpy(&sqlite3_query_plan[nQPlan], "* ", 2);
- nQPlan += 2;
- }else if( (w & WHERE_INDEXED)!=0 && (w & WHERE_COVER_SCAN)==0 ){
- n = sqlite3Strlen30(pLevel->plan.u.pIdx->zName);
- if( n+nQPlan < sizeof(sqlite3_query_plan)-2 ){
- memcpy(&sqlite3_query_plan[nQPlan], pLevel->plan.u.pIdx->zName, n);
- nQPlan += n;
- sqlite3_query_plan[nQPlan++] = ' ';
- }
- }else{
- memcpy(&sqlite3_query_plan[nQPlan], "{} ", 3);
- nQPlan += 3;
- }
- }
- while( nQPlan>0 && sqlite3_query_plan[nQPlan-1]==' ' ){
- sqlite3_query_plan[--nQPlan] = 0;
- }
- sqlite3_query_plan[nQPlan] = 0;
- nQPlan = 0;
-#endif /* SQLITE_TEST // Testing and debugging use only */
-
- /* Record the continuation address in the WhereInfo structure. Then
- ** clean up and return.
- */
+ /* Done. */
return pWInfo;
/* Jump here if malloc fails */
@@ -110050,6 +110862,7 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){
Vdbe *v = pParse->pVdbe;
int i;
WhereLevel *pLevel;
+ WhereLoop *pLoop;
SrcList *pTabList = pWInfo->pTabList;
sqlite3 *db = pParse->db;
@@ -110058,12 +110871,13 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){
sqlite3ExprCacheClear(pParse);
for(i=pWInfo->nLevel-1; i>=0; i--){
pLevel = &pWInfo->a[i];
+ pLoop = pLevel->pWLoop;
sqlite3VdbeResolveLabel(v, pLevel->addrCont);
if( pLevel->op!=OP_Noop ){
sqlite3VdbeAddOp2(v, pLevel->op, pLevel->p1, pLevel->p2);
sqlite3VdbeChangeP5(v, pLevel->p5);
}
- if( pLevel->plan.wsFlags & WHERE_IN_ABLE && pLevel->u.in.nIn>0 ){
+ if( pLoop->wsFlags & WHERE_IN_ABLE && pLevel->u.in.nIn>0 ){
struct InLoop *pIn;
int j;
sqlite3VdbeResolveLabel(v, pLevel->addrNxt);
@@ -110078,12 +110892,12 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){
if( pLevel->iLeftJoin ){
int addr;
addr = sqlite3VdbeAddOp1(v, OP_IfPos, pLevel->iLeftJoin);
- assert( (pLevel->plan.wsFlags & WHERE_IDX_ONLY)==0
- || (pLevel->plan.wsFlags & WHERE_INDEXED)!=0 );
- if( (pLevel->plan.wsFlags & WHERE_IDX_ONLY)==0 ){
+ assert( (pLoop->wsFlags & WHERE_IDX_ONLY)==0
+ || (pLoop->wsFlags & WHERE_INDEXED)!=0 );
+ if( (pLoop->wsFlags & WHERE_IDX_ONLY)==0 ){
sqlite3VdbeAddOp1(v, OP_NullRow, pTabList->a[i].iCursor);
}
- if( pLevel->iIdxCur>=0 ){
+ if( pLoop->wsFlags & WHERE_INDEXED ){
sqlite3VdbeAddOp1(v, OP_NullRow, pLevel->iIdxCur);
}
if( pLevel->op==OP_Return ){
@@ -110102,31 +110916,30 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){
/* Close all of the cursors that were opened by sqlite3WhereBegin.
*/
- assert( pWInfo->nLevel==1 || pWInfo->nLevel==pTabList->nSrc );
+ assert( pWInfo->nLevel<=pTabList->nSrc );
for(i=0, pLevel=pWInfo->a; i<pWInfo->nLevel; i++, pLevel++){
Index *pIdx = 0;
struct SrcList_item *pTabItem = &pTabList->a[pLevel->iFrom];
Table *pTab = pTabItem->pTab;
assert( pTab!=0 );
+ pLoop = pLevel->pWLoop;
if( (pTab->tabFlags & TF_Ephemeral)==0
&& pTab->pSelect==0
&& (pWInfo->wctrlFlags & WHERE_OMIT_OPEN_CLOSE)==0
){
- int ws = pLevel->plan.wsFlags;
+ int ws = pLoop->wsFlags;
if( !pWInfo->okOnePass && (ws & WHERE_IDX_ONLY)==0 ){
sqlite3VdbeAddOp1(v, OP_Close, pTabItem->iCursor);
}
- if( (ws & WHERE_INDEXED)!=0 && (ws & WHERE_TEMP_INDEX)==0 ){
+ if( (ws & WHERE_INDEXED)!=0 && (ws & (WHERE_IPK|WHERE_AUTO_INDEX))==0 ){
sqlite3VdbeAddOp1(v, OP_Close, pLevel->iIdxCur);
}
}
- /* If this scan uses an index, make code substitutions to read data
- ** from the index in preference to the table. Sometimes, this means
- ** the table need never be read from. This is a performance boost,
- ** as the vdbe level waits until the table is read before actually
- ** seeking the table cursor to the record corresponding to the current
- ** position in the index.
+ /* If this scan uses an index, make VDBE code substitutions to read data
+ ** from the index instead of from the table where possible. In some cases
+ ** this optimization prevents the table from ever being read, which can
+ ** yield a significant performance boost.
**
** Calls to the code generator in between sqlite3WhereBegin and
** sqlite3WhereEnd will have created code that references the table
@@ -110134,18 +110947,19 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){
** that reference the table and converts them into opcodes that
** reference the index.
*/
- if( pLevel->plan.wsFlags & WHERE_INDEXED ){
- pIdx = pLevel->plan.u.pIdx;
- }else if( pLevel->plan.wsFlags & WHERE_MULTI_OR ){
+ if( pLoop->wsFlags & (WHERE_INDEXED|WHERE_IDX_ONLY) ){
+ pIdx = pLoop->u.btree.pIndex;
+ }else if( pLoop->wsFlags & WHERE_MULTI_OR ){
pIdx = pLevel->u.pCovidx;
}
- if( pIdx && !db->mallocFailed){
+ if( pIdx && !db->mallocFailed ){
int k, j, last;
VdbeOp *pOp;
- pOp = sqlite3VdbeGetOp(v, pWInfo->iTop);
last = sqlite3VdbeCurrentAddr(v);
- for(k=pWInfo->iTop; k<last; k++, pOp++){
+ k = pLevel->addrBody;
+ pOp = sqlite3VdbeGetOp(v, k);
+ for(; k<last; k++, pOp++){
if( pOp->p1!=pLevel->iTabCur ) continue;
if( pOp->opcode==OP_Column ){
for(j=0; j<pIdx->nColumn; j++){
@@ -110155,8 +110969,7 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){
break;
}
}
- assert( (pLevel->plan.wsFlags & WHERE_IDX_ONLY)==0
- || j<pIdx->nColumn );
+ assert( (pLoop->wsFlags & WHERE_IDX_ONLY)==0 || j<pIdx->nColumn );
}else if( pOp->opcode==OP_Rowid ){
pOp->p1 = pLevel->iIdxCur;
pOp->opcode = OP_IdxRowid;
@@ -110394,7 +111207,7 @@ typedef union {
#define sqlite3ParserARG_PDECL ,Parse *pParse
#define sqlite3ParserARG_FETCH Parse *pParse = yypParser->pParse
#define sqlite3ParserARG_STORE yypParser->pParse = pParse
-#define YYNSTATE 627
+#define YYNSTATE 628
#define YYNRULE 327
#define YYFALLBACK 1
#define YY_NO_ACTION (YYNSTATE+YYNRULE+2)
@@ -110467,163 +111280,163 @@ static const YYMINORTYPE yyzerominor = { 0 };
*/
#define YY_ACTTAB_COUNT (1564)
static const YYACTIONTYPE yy_action[] = {
- /* 0 */ 309, 955, 184, 417, 2, 171, 624, 594, 56, 56,
+ /* 0 */ 310, 956, 184, 418, 2, 171, 625, 595, 56, 56,
/* 10 */ 56, 56, 49, 54, 54, 54, 54, 53, 53, 52,
- /* 20 */ 52, 52, 51, 233, 620, 619, 298, 620, 619, 234,
- /* 30 */ 587, 581, 56, 56, 56, 56, 19, 54, 54, 54,
- /* 40 */ 54, 53, 53, 52, 52, 52, 51, 233, 605, 57,
- /* 50 */ 58, 48, 579, 578, 580, 580, 55, 55, 56, 56,
- /* 60 */ 56, 56, 541, 54, 54, 54, 54, 53, 53, 52,
- /* 70 */ 52, 52, 51, 233, 309, 594, 325, 196, 195, 194,
+ /* 20 */ 52, 52, 51, 233, 621, 620, 299, 621, 620, 234,
+ /* 30 */ 588, 582, 56, 56, 56, 56, 19, 54, 54, 54,
+ /* 40 */ 54, 53, 53, 52, 52, 52, 51, 233, 606, 57,
+ /* 50 */ 58, 48, 580, 579, 581, 581, 55, 55, 56, 56,
+ /* 60 */ 56, 56, 542, 54, 54, 54, 54, 53, 53, 52,
+ /* 70 */ 52, 52, 51, 233, 310, 595, 326, 196, 195, 194,
/* 80 */ 33, 54, 54, 54, 54, 53, 53, 52, 52, 52,
- /* 90 */ 51, 233, 617, 616, 165, 617, 616, 380, 377, 376,
- /* 100 */ 407, 532, 576, 576, 587, 581, 303, 422, 375, 59,
+ /* 90 */ 51, 233, 618, 617, 165, 618, 617, 381, 378, 377,
+ /* 100 */ 408, 533, 577, 577, 588, 582, 304, 423, 376, 59,
/* 110 */ 53, 53, 52, 52, 52, 51, 233, 50, 47, 146,
- /* 120 */ 574, 545, 65, 57, 58, 48, 579, 578, 580, 580,
+ /* 120 */ 575, 546, 65, 57, 58, 48, 580, 579, 581, 581,
/* 130 */ 55, 55, 56, 56, 56, 56, 213, 54, 54, 54,
- /* 140 */ 54, 53, 53, 52, 52, 52, 51, 233, 309, 223,
- /* 150 */ 539, 420, 170, 176, 138, 280, 383, 275, 382, 168,
- /* 160 */ 489, 551, 409, 668, 620, 619, 271, 438, 409, 438,
- /* 170 */ 550, 604, 67, 482, 507, 618, 599, 412, 587, 581,
- /* 180 */ 600, 483, 618, 412, 618, 598, 91, 439, 440, 439,
- /* 190 */ 335, 598, 73, 669, 222, 266, 480, 57, 58, 48,
- /* 200 */ 579, 578, 580, 580, 55, 55, 56, 56, 56, 56,
- /* 210 */ 670, 54, 54, 54, 54, 53, 53, 52, 52, 52,
- /* 220 */ 51, 233, 309, 279, 232, 231, 1, 132, 200, 385,
- /* 230 */ 620, 619, 617, 616, 278, 435, 289, 563, 175, 262,
- /* 240 */ 409, 264, 437, 497, 436, 166, 441, 568, 336, 568,
- /* 250 */ 201, 537, 587, 581, 599, 412, 165, 594, 600, 380,
- /* 260 */ 377, 376, 597, 598, 92, 523, 618, 569, 569, 592,
- /* 270 */ 375, 57, 58, 48, 579, 578, 580, 580, 55, 55,
- /* 280 */ 56, 56, 56, 56, 597, 54, 54, 54, 54, 53,
- /* 290 */ 53, 52, 52, 52, 51, 233, 309, 463, 617, 616,
- /* 300 */ 590, 590, 590, 174, 272, 396, 409, 272, 409, 548,
- /* 310 */ 397, 620, 619, 68, 326, 620, 619, 620, 619, 618,
- /* 320 */ 546, 412, 618, 412, 471, 594, 587, 581, 472, 598,
- /* 330 */ 92, 598, 92, 52, 52, 52, 51, 233, 513, 512,
- /* 340 */ 206, 322, 363, 464, 221, 57, 58, 48, 579, 578,
- /* 350 */ 580, 580, 55, 55, 56, 56, 56, 56, 529, 54,
+ /* 140 */ 54, 53, 53, 52, 52, 52, 51, 233, 310, 223,
+ /* 150 */ 540, 421, 170, 176, 138, 281, 384, 276, 383, 168,
+ /* 160 */ 490, 552, 410, 669, 621, 620, 272, 439, 410, 439,
+ /* 170 */ 551, 605, 67, 483, 508, 619, 600, 413, 588, 582,
+ /* 180 */ 601, 484, 619, 413, 619, 599, 91, 440, 441, 440,
+ /* 190 */ 336, 599, 73, 670, 222, 267, 481, 57, 58, 48,
+ /* 200 */ 580, 579, 581, 581, 55, 55, 56, 56, 56, 56,
+ /* 210 */ 671, 54, 54, 54, 54, 53, 53, 52, 52, 52,
+ /* 220 */ 51, 233, 310, 280, 232, 231, 1, 132, 200, 386,
+ /* 230 */ 621, 620, 618, 617, 279, 436, 290, 564, 175, 263,
+ /* 240 */ 410, 265, 438, 498, 437, 166, 442, 569, 337, 569,
+ /* 250 */ 201, 538, 588, 582, 600, 413, 165, 595, 601, 381,
+ /* 260 */ 378, 377, 598, 599, 92, 524, 619, 570, 570, 593,
+ /* 270 */ 376, 57, 58, 48, 580, 579, 581, 581, 55, 55,
+ /* 280 */ 56, 56, 56, 56, 598, 54, 54, 54, 54, 53,
+ /* 290 */ 53, 52, 52, 52, 51, 233, 310, 464, 618, 617,
+ /* 300 */ 591, 591, 591, 174, 273, 397, 410, 273, 410, 549,
+ /* 310 */ 398, 621, 620, 68, 327, 621, 620, 621, 620, 619,
+ /* 320 */ 547, 413, 619, 413, 472, 595, 588, 582, 473, 599,
+ /* 330 */ 92, 599, 92, 52, 52, 52, 51, 233, 514, 513,
+ /* 340 */ 206, 323, 364, 465, 221, 57, 58, 48, 580, 579,
+ /* 350 */ 581, 581, 55, 55, 56, 56, 56, 56, 530, 54,
/* 360 */ 54, 54, 54, 53, 53, 52, 52, 52, 51, 233,
- /* 370 */ 309, 396, 409, 396, 597, 372, 386, 530, 347, 617,
- /* 380 */ 616, 575, 202, 617, 616, 617, 616, 412, 620, 619,
- /* 390 */ 145, 255, 346, 254, 577, 598, 74, 351, 45, 489,
- /* 400 */ 587, 581, 235, 189, 464, 544, 167, 296, 187, 469,
- /* 410 */ 479, 67, 62, 39, 618, 546, 597, 345, 573, 57,
- /* 420 */ 58, 48, 579, 578, 580, 580, 55, 55, 56, 56,
+ /* 370 */ 310, 397, 410, 397, 598, 373, 387, 531, 348, 618,
+ /* 380 */ 617, 576, 202, 618, 617, 618, 617, 413, 621, 620,
+ /* 390 */ 145, 255, 347, 254, 578, 599, 74, 352, 45, 490,
+ /* 400 */ 588, 582, 235, 189, 465, 545, 167, 297, 187, 470,
+ /* 410 */ 480, 67, 62, 39, 619, 547, 598, 346, 574, 57,
+ /* 420 */ 58, 48, 580, 579, 581, 581, 55, 55, 56, 56,
/* 430 */ 56, 56, 6, 54, 54, 54, 54, 53, 53, 52,
- /* 440 */ 52, 52, 51, 233, 309, 562, 558, 407, 528, 576,
- /* 450 */ 576, 344, 255, 346, 254, 182, 617, 616, 503, 504,
- /* 460 */ 314, 409, 557, 235, 166, 271, 409, 352, 564, 181,
- /* 470 */ 407, 546, 576, 576, 587, 581, 412, 537, 556, 561,
- /* 480 */ 517, 412, 618, 249, 598, 16, 7, 36, 467, 598,
- /* 490 */ 92, 516, 618, 57, 58, 48, 579, 578, 580, 580,
- /* 500 */ 55, 55, 56, 56, 56, 56, 541, 54, 54, 54,
- /* 510 */ 54, 53, 53, 52, 52, 52, 51, 233, 309, 327,
- /* 520 */ 572, 571, 525, 558, 560, 394, 871, 246, 409, 248,
- /* 530 */ 171, 392, 594, 219, 407, 409, 576, 576, 502, 557,
- /* 540 */ 364, 145, 510, 412, 407, 229, 576, 576, 587, 581,
- /* 550 */ 412, 598, 92, 381, 269, 556, 166, 400, 598, 69,
- /* 560 */ 501, 419, 945, 199, 945, 198, 546, 57, 58, 48,
- /* 570 */ 579, 578, 580, 580, 55, 55, 56, 56, 56, 56,
- /* 580 */ 568, 54, 54, 54, 54, 53, 53, 52, 52, 52,
- /* 590 */ 51, 233, 309, 317, 419, 944, 508, 944, 308, 597,
- /* 600 */ 594, 565, 490, 212, 173, 247, 423, 615, 614, 613,
- /* 610 */ 323, 197, 143, 405, 572, 571, 489, 66, 50, 47,
- /* 620 */ 146, 594, 587, 581, 232, 231, 559, 427, 67, 555,
- /* 630 */ 15, 618, 186, 543, 303, 421, 35, 206, 432, 423,
- /* 640 */ 552, 57, 58, 48, 579, 578, 580, 580, 55, 55,
+ /* 440 */ 52, 52, 51, 233, 310, 563, 559, 408, 529, 577,
+ /* 450 */ 577, 345, 255, 347, 254, 182, 618, 617, 504, 505,
+ /* 460 */ 315, 410, 558, 235, 166, 272, 410, 353, 565, 181,
+ /* 470 */ 408, 547, 577, 577, 588, 582, 413, 538, 557, 562,
+ /* 480 */ 518, 413, 619, 249, 599, 16, 7, 36, 468, 599,
+ /* 490 */ 92, 517, 619, 57, 58, 48, 580, 579, 581, 581,
+ /* 500 */ 55, 55, 56, 56, 56, 56, 542, 54, 54, 54,
+ /* 510 */ 54, 53, 53, 52, 52, 52, 51, 233, 310, 328,
+ /* 520 */ 573, 572, 526, 559, 561, 395, 872, 246, 410, 248,
+ /* 530 */ 171, 393, 595, 219, 408, 410, 577, 577, 503, 558,
+ /* 540 */ 365, 145, 511, 413, 408, 229, 577, 577, 588, 582,
+ /* 550 */ 413, 599, 92, 382, 270, 557, 166, 401, 599, 69,
+ /* 560 */ 502, 420, 946, 199, 946, 198, 547, 57, 58, 48,
+ /* 570 */ 580, 579, 581, 581, 55, 55, 56, 56, 56, 56,
+ /* 580 */ 569, 54, 54, 54, 54, 53, 53, 52, 52, 52,
+ /* 590 */ 51, 233, 310, 318, 420, 945, 509, 945, 309, 598,
+ /* 600 */ 595, 566, 491, 212, 173, 247, 424, 616, 615, 614,
+ /* 610 */ 324, 197, 143, 406, 573, 572, 490, 66, 50, 47,
+ /* 620 */ 146, 595, 588, 582, 232, 231, 560, 428, 67, 556,
+ /* 630 */ 15, 619, 186, 544, 304, 422, 35, 206, 433, 424,
+ /* 640 */ 553, 57, 58, 48, 580, 579, 581, 581, 55, 55,
/* 650 */ 56, 56, 56, 56, 205, 54, 54, 54, 54, 53,
- /* 660 */ 53, 52, 52, 52, 51, 233, 309, 569, 569, 260,
- /* 670 */ 268, 597, 12, 373, 568, 166, 409, 313, 409, 420,
- /* 680 */ 409, 473, 473, 365, 618, 50, 47, 146, 597, 594,
- /* 690 */ 468, 412, 166, 412, 351, 412, 587, 581, 32, 598,
- /* 700 */ 94, 598, 97, 598, 95, 627, 625, 329, 142, 50,
- /* 710 */ 47, 146, 333, 349, 358, 57, 58, 48, 579, 578,
- /* 720 */ 580, 580, 55, 55, 56, 56, 56, 56, 409, 54,
+ /* 660 */ 53, 52, 52, 52, 51, 233, 310, 570, 570, 261,
+ /* 670 */ 269, 598, 12, 374, 569, 166, 410, 314, 410, 421,
+ /* 680 */ 410, 474, 474, 366, 619, 50, 47, 146, 598, 595,
+ /* 690 */ 256, 413, 166, 413, 352, 413, 588, 582, 32, 599,
+ /* 700 */ 94, 599, 97, 599, 95, 628, 626, 330, 142, 50,
+ /* 710 */ 47, 146, 334, 350, 359, 57, 58, 48, 580, 579,
+ /* 720 */ 581, 581, 55, 55, 56, 56, 56, 56, 410, 54,
/* 730 */ 54, 54, 54, 53, 53, 52, 52, 52, 51, 233,
- /* 740 */ 309, 409, 388, 412, 409, 22, 565, 404, 212, 362,
- /* 750 */ 389, 598, 104, 359, 409, 156, 412, 409, 603, 412,
- /* 760 */ 537, 331, 569, 569, 598, 103, 493, 598, 105, 412,
- /* 770 */ 587, 581, 412, 260, 549, 618, 11, 598, 106, 521,
- /* 780 */ 598, 133, 169, 457, 456, 170, 35, 601, 618, 57,
- /* 790 */ 58, 48, 579, 578, 580, 580, 55, 55, 56, 56,
- /* 800 */ 56, 56, 409, 54, 54, 54, 54, 53, 53, 52,
- /* 810 */ 52, 52, 51, 233, 309, 409, 259, 412, 409, 50,
- /* 820 */ 47, 146, 357, 318, 355, 598, 134, 527, 352, 337,
- /* 830 */ 412, 409, 356, 412, 357, 409, 357, 618, 598, 98,
- /* 840 */ 129, 598, 102, 618, 587, 581, 412, 21, 235, 618,
- /* 850 */ 412, 618, 211, 143, 598, 101, 30, 167, 598, 93,
- /* 860 */ 350, 535, 203, 57, 58, 48, 579, 578, 580, 580,
- /* 870 */ 55, 55, 56, 56, 56, 56, 409, 54, 54, 54,
- /* 880 */ 54, 53, 53, 52, 52, 52, 51, 233, 309, 409,
- /* 890 */ 526, 412, 409, 425, 215, 305, 597, 551, 141, 598,
- /* 900 */ 100, 40, 409, 38, 412, 409, 550, 412, 409, 228,
- /* 910 */ 220, 314, 598, 77, 500, 598, 96, 412, 587, 581,
- /* 920 */ 412, 338, 253, 412, 218, 598, 137, 379, 598, 136,
- /* 930 */ 28, 598, 135, 270, 715, 210, 481, 57, 58, 48,
- /* 940 */ 579, 578, 580, 580, 55, 55, 56, 56, 56, 56,
- /* 950 */ 409, 54, 54, 54, 54, 53, 53, 52, 52, 52,
- /* 960 */ 51, 233, 309, 409, 272, 412, 409, 315, 147, 597,
- /* 970 */ 272, 626, 2, 598, 76, 209, 409, 127, 412, 618,
- /* 980 */ 126, 412, 409, 621, 235, 618, 598, 90, 374, 598,
- /* 990 */ 89, 412, 587, 581, 27, 260, 350, 412, 618, 598,
- /* 1000 */ 75, 321, 541, 541, 125, 598, 88, 320, 278, 597,
- /* 1010 */ 618, 57, 46, 48, 579, 578, 580, 580, 55, 55,
- /* 1020 */ 56, 56, 56, 56, 409, 54, 54, 54, 54, 53,
- /* 1030 */ 53, 52, 52, 52, 51, 233, 309, 409, 450, 412,
- /* 1040 */ 164, 284, 282, 272, 609, 424, 304, 598, 87, 370,
- /* 1050 */ 409, 477, 412, 409, 608, 409, 607, 602, 618, 618,
- /* 1060 */ 598, 99, 586, 585, 122, 412, 587, 581, 412, 618,
- /* 1070 */ 412, 618, 618, 598, 86, 366, 598, 17, 598, 85,
- /* 1080 */ 319, 185, 519, 518, 583, 582, 58, 48, 579, 578,
- /* 1090 */ 580, 580, 55, 55, 56, 56, 56, 56, 409, 54,
+ /* 740 */ 310, 410, 389, 413, 410, 22, 566, 405, 212, 363,
+ /* 750 */ 390, 599, 104, 360, 410, 156, 413, 410, 604, 413,
+ /* 760 */ 538, 332, 570, 570, 599, 103, 494, 599, 105, 413,
+ /* 770 */ 588, 582, 413, 261, 550, 619, 11, 599, 106, 522,
+ /* 780 */ 599, 133, 169, 458, 457, 170, 35, 602, 619, 57,
+ /* 790 */ 58, 48, 580, 579, 581, 581, 55, 55, 56, 56,
+ /* 800 */ 56, 56, 410, 54, 54, 54, 54, 53, 53, 52,
+ /* 810 */ 52, 52, 51, 233, 310, 410, 260, 413, 410, 50,
+ /* 820 */ 47, 146, 358, 319, 356, 599, 134, 528, 353, 338,
+ /* 830 */ 413, 410, 357, 413, 358, 410, 358, 619, 599, 98,
+ /* 840 */ 129, 599, 102, 619, 588, 582, 413, 21, 235, 619,
+ /* 850 */ 413, 619, 211, 143, 599, 101, 30, 167, 599, 93,
+ /* 860 */ 351, 536, 203, 57, 58, 48, 580, 579, 581, 581,
+ /* 870 */ 55, 55, 56, 56, 56, 56, 410, 54, 54, 54,
+ /* 880 */ 54, 53, 53, 52, 52, 52, 51, 233, 310, 410,
+ /* 890 */ 527, 413, 410, 426, 215, 306, 598, 552, 141, 599,
+ /* 900 */ 100, 40, 410, 38, 413, 410, 551, 413, 410, 228,
+ /* 910 */ 220, 315, 599, 77, 501, 599, 96, 413, 588, 582,
+ /* 920 */ 413, 339, 253, 413, 218, 599, 137, 380, 599, 136,
+ /* 930 */ 28, 599, 135, 271, 716, 210, 482, 57, 58, 48,
+ /* 940 */ 580, 579, 581, 581, 55, 55, 56, 56, 56, 56,
+ /* 950 */ 410, 54, 54, 54, 54, 53, 53, 52, 52, 52,
+ /* 960 */ 51, 233, 310, 410, 273, 413, 410, 316, 147, 598,
+ /* 970 */ 273, 627, 2, 599, 76, 209, 410, 127, 413, 619,
+ /* 980 */ 126, 413, 410, 622, 235, 619, 599, 90, 375, 599,
+ /* 990 */ 89, 413, 588, 582, 27, 261, 351, 413, 619, 599,
+ /* 1000 */ 75, 322, 542, 542, 125, 599, 88, 321, 279, 598,
+ /* 1010 */ 619, 57, 46, 48, 580, 579, 581, 581, 55, 55,
+ /* 1020 */ 56, 56, 56, 56, 410, 54, 54, 54, 54, 53,
+ /* 1030 */ 53, 52, 52, 52, 51, 233, 310, 410, 451, 413,
+ /* 1040 */ 164, 285, 283, 273, 610, 425, 305, 599, 87, 371,
+ /* 1050 */ 410, 478, 413, 410, 609, 410, 608, 603, 619, 619,
+ /* 1060 */ 599, 99, 587, 586, 122, 413, 588, 582, 413, 619,
+ /* 1070 */ 413, 619, 619, 599, 86, 367, 599, 17, 599, 85,
+ /* 1080 */ 320, 185, 520, 519, 584, 583, 58, 48, 580, 579,
+ /* 1090 */ 581, 581, 55, 55, 56, 56, 56, 56, 410, 54,
/* 1100 */ 54, 54, 54, 53, 53, 52, 52, 52, 51, 233,
- /* 1110 */ 309, 584, 409, 412, 409, 260, 260, 260, 408, 591,
- /* 1120 */ 474, 598, 84, 170, 409, 466, 518, 412, 121, 412,
- /* 1130 */ 618, 618, 618, 618, 618, 598, 83, 598, 72, 412,
- /* 1140 */ 587, 581, 51, 233, 625, 329, 470, 598, 71, 257,
- /* 1150 */ 159, 120, 14, 462, 157, 158, 117, 260, 448, 447,
- /* 1160 */ 446, 48, 579, 578, 580, 580, 55, 55, 56, 56,
- /* 1170 */ 56, 56, 618, 54, 54, 54, 54, 53, 53, 52,
- /* 1180 */ 52, 52, 51, 233, 44, 403, 260, 3, 409, 459,
- /* 1190 */ 260, 413, 619, 118, 398, 10, 25, 24, 554, 348,
- /* 1200 */ 217, 618, 406, 412, 409, 618, 4, 44, 403, 618,
- /* 1210 */ 3, 598, 82, 618, 413, 619, 455, 542, 115, 412,
- /* 1220 */ 538, 401, 536, 274, 506, 406, 251, 598, 81, 216,
- /* 1230 */ 273, 563, 618, 243, 453, 618, 154, 618, 618, 618,
- /* 1240 */ 449, 416, 623, 110, 401, 618, 409, 236, 64, 123,
- /* 1250 */ 487, 41, 42, 531, 563, 204, 409, 267, 43, 411,
- /* 1260 */ 410, 412, 265, 592, 108, 618, 107, 434, 332, 598,
- /* 1270 */ 80, 412, 618, 263, 41, 42, 443, 618, 409, 598,
- /* 1280 */ 70, 43, 411, 410, 433, 261, 592, 149, 618, 597,
- /* 1290 */ 256, 237, 188, 412, 590, 590, 590, 589, 588, 13,
- /* 1300 */ 618, 598, 18, 328, 235, 618, 44, 403, 360, 3,
- /* 1310 */ 418, 461, 339, 413, 619, 227, 124, 590, 590, 590,
- /* 1320 */ 589, 588, 13, 618, 406, 409, 618, 409, 139, 34,
- /* 1330 */ 403, 387, 3, 148, 622, 312, 413, 619, 311, 330,
- /* 1340 */ 412, 460, 412, 401, 180, 353, 412, 406, 598, 79,
- /* 1350 */ 598, 78, 250, 563, 598, 9, 618, 612, 611, 610,
- /* 1360 */ 618, 8, 452, 442, 242, 415, 401, 618, 239, 235,
- /* 1370 */ 179, 238, 428, 41, 42, 288, 563, 618, 618, 618,
- /* 1380 */ 43, 411, 410, 618, 144, 592, 618, 618, 177, 61,
- /* 1390 */ 618, 596, 391, 620, 619, 287, 41, 42, 414, 618,
- /* 1400 */ 293, 30, 393, 43, 411, 410, 292, 618, 592, 31,
- /* 1410 */ 618, 395, 291, 60, 230, 37, 590, 590, 590, 589,
- /* 1420 */ 588, 13, 214, 553, 183, 290, 172, 301, 300, 299,
- /* 1430 */ 178, 297, 595, 563, 451, 29, 285, 390, 540, 590,
- /* 1440 */ 590, 590, 589, 588, 13, 283, 520, 534, 150, 533,
- /* 1450 */ 241, 281, 384, 192, 191, 324, 515, 514, 276, 240,
- /* 1460 */ 510, 523, 307, 511, 128, 592, 509, 225, 226, 486,
- /* 1470 */ 485, 224, 152, 491, 464, 306, 484, 163, 153, 371,
- /* 1480 */ 478, 151, 162, 258, 369, 161, 367, 208, 475, 476,
- /* 1490 */ 26, 160, 465, 140, 361, 131, 590, 590, 590, 116,
- /* 1500 */ 119, 454, 343, 155, 114, 342, 113, 112, 445, 111,
- /* 1510 */ 130, 109, 431, 316, 426, 430, 23, 429, 20, 606,
- /* 1520 */ 190, 507, 255, 341, 244, 63, 294, 593, 310, 570,
- /* 1530 */ 277, 402, 354, 235, 567, 496, 495, 492, 494, 302,
- /* 1540 */ 458, 378, 286, 245, 566, 5, 252, 547, 193, 444,
- /* 1550 */ 233, 340, 207, 524, 368, 505, 334, 522, 499, 399,
- /* 1560 */ 295, 498, 956, 488,
+ /* 1110 */ 310, 585, 410, 413, 410, 261, 261, 261, 409, 592,
+ /* 1120 */ 475, 599, 84, 170, 410, 467, 519, 413, 121, 413,
+ /* 1130 */ 619, 619, 619, 619, 619, 599, 83, 599, 72, 413,
+ /* 1140 */ 588, 582, 51, 233, 626, 330, 471, 599, 71, 258,
+ /* 1150 */ 159, 120, 14, 463, 157, 158, 117, 261, 449, 448,
+ /* 1160 */ 447, 48, 580, 579, 581, 581, 55, 55, 56, 56,
+ /* 1170 */ 56, 56, 619, 54, 54, 54, 54, 53, 53, 52,
+ /* 1180 */ 52, 52, 51, 233, 44, 404, 261, 3, 410, 460,
+ /* 1190 */ 261, 414, 620, 118, 399, 10, 25, 24, 555, 349,
+ /* 1200 */ 217, 619, 407, 413, 410, 619, 4, 44, 404, 619,
+ /* 1210 */ 3, 599, 82, 619, 414, 620, 456, 543, 115, 413,
+ /* 1220 */ 539, 402, 537, 275, 507, 407, 251, 599, 81, 216,
+ /* 1230 */ 274, 564, 619, 243, 454, 619, 154, 619, 619, 619,
+ /* 1240 */ 450, 417, 624, 110, 402, 619, 410, 236, 64, 123,
+ /* 1250 */ 488, 41, 42, 532, 564, 204, 410, 268, 43, 412,
+ /* 1260 */ 411, 413, 266, 593, 108, 619, 107, 435, 333, 599,
+ /* 1270 */ 80, 413, 619, 264, 41, 42, 444, 619, 410, 599,
+ /* 1280 */ 70, 43, 412, 411, 434, 262, 593, 149, 619, 598,
+ /* 1290 */ 257, 237, 188, 413, 591, 591, 591, 590, 589, 13,
+ /* 1300 */ 619, 599, 18, 329, 235, 619, 44, 404, 361, 3,
+ /* 1310 */ 419, 462, 340, 414, 620, 227, 124, 591, 591, 591,
+ /* 1320 */ 590, 589, 13, 619, 407, 410, 619, 410, 139, 34,
+ /* 1330 */ 404, 388, 3, 148, 623, 313, 414, 620, 312, 331,
+ /* 1340 */ 413, 461, 413, 402, 180, 354, 413, 407, 599, 79,
+ /* 1350 */ 599, 78, 250, 564, 599, 9, 619, 613, 612, 611,
+ /* 1360 */ 619, 8, 453, 443, 242, 416, 402, 619, 239, 235,
+ /* 1370 */ 179, 238, 429, 41, 42, 289, 564, 619, 619, 619,
+ /* 1380 */ 43, 412, 411, 619, 144, 593, 619, 619, 177, 61,
+ /* 1390 */ 619, 597, 392, 621, 620, 288, 41, 42, 415, 619,
+ /* 1400 */ 294, 30, 394, 43, 412, 411, 293, 619, 593, 31,
+ /* 1410 */ 619, 396, 292, 60, 230, 37, 591, 591, 591, 590,
+ /* 1420 */ 589, 13, 214, 554, 183, 291, 172, 302, 301, 300,
+ /* 1430 */ 178, 298, 596, 564, 452, 29, 286, 391, 541, 591,
+ /* 1440 */ 591, 591, 590, 589, 13, 284, 521, 535, 150, 534,
+ /* 1450 */ 241, 282, 385, 192, 191, 325, 516, 515, 277, 240,
+ /* 1460 */ 511, 524, 308, 512, 128, 593, 510, 225, 226, 487,
+ /* 1470 */ 486, 224, 152, 492, 465, 307, 485, 163, 153, 372,
+ /* 1480 */ 479, 151, 162, 259, 370, 161, 368, 208, 476, 477,
+ /* 1490 */ 26, 160, 469, 466, 362, 140, 591, 591, 591, 116,
+ /* 1500 */ 119, 455, 344, 155, 114, 343, 113, 112, 446, 111,
+ /* 1510 */ 131, 109, 432, 317, 130, 431, 23, 20, 430, 427,
+ /* 1520 */ 190, 63, 255, 342, 244, 607, 295, 287, 311, 594,
+ /* 1530 */ 278, 508, 496, 235, 493, 571, 497, 568, 495, 403,
+ /* 1540 */ 459, 379, 355, 245, 193, 303, 567, 296, 341, 5,
+ /* 1550 */ 445, 548, 506, 207, 525, 500, 335, 489, 252, 369,
+ /* 1560 */ 400, 499, 523, 233,
};
static const YYCODETYPE yy_lookahead[] = {
/* 0 */ 19, 142, 143, 144, 145, 24, 1, 26, 77, 78,
@@ -110775,17 +111588,17 @@ static const YYCODETYPE yy_lookahead[] = {
/* 1460 */ 103, 94, 178, 177, 22, 98, 175, 92, 228, 175,
/* 1470 */ 175, 228, 55, 183, 57, 178, 175, 156, 61, 18,
/* 1480 */ 157, 64, 156, 235, 157, 156, 45, 157, 236, 157,
- /* 1490 */ 135, 156, 189, 68, 157, 218, 129, 130, 131, 22,
+ /* 1490 */ 135, 156, 199, 189, 157, 68, 129, 130, 131, 22,
/* 1500 */ 189, 199, 157, 156, 192, 18, 192, 192, 199, 192,
- /* 1510 */ 218, 189, 40, 157, 38, 157, 240, 157, 240, 153,
- /* 1520 */ 196, 181, 105, 106, 107, 243, 198, 166, 111, 230,
- /* 1530 */ 176, 226, 239, 116, 230, 176, 166, 166, 176, 148,
- /* 1540 */ 199, 177, 209, 209, 166, 196, 239, 208, 185, 199,
- /* 1550 */ 92, 209, 233, 173, 234, 182, 139, 173, 182, 191,
- /* 1560 */ 195, 182, 250, 186,
+ /* 1510 */ 218, 189, 40, 157, 218, 157, 240, 240, 157, 38,
+ /* 1520 */ 196, 243, 105, 106, 107, 153, 198, 209, 111, 166,
+ /* 1530 */ 176, 181, 166, 116, 166, 230, 176, 230, 176, 226,
+ /* 1540 */ 199, 177, 239, 209, 185, 148, 166, 195, 209, 196,
+ /* 1550 */ 199, 208, 182, 233, 173, 182, 139, 186, 239, 234,
+ /* 1560 */ 191, 182, 173, 92,
};
#define YY_SHIFT_USE_DFLT (-70)
-#define YY_SHIFT_COUNT (416)
+#define YY_SHIFT_COUNT (417)
#define YY_SHIFT_MIN (-69)
#define YY_SHIFT_MAX (1487)
static const short yy_shift_ofst[] = {
@@ -110802,7 +111615,7 @@ static const short yy_shift_ofst[] = {
/* 100 */ -45, -45, -45, -45, -1, 24, 245, 362, 362, 362,
/* 110 */ 362, 362, 362, 362, 362, 362, 362, 362, 362, 362,
/* 120 */ 362, 362, 362, 388, 356, 362, 362, 362, 362, 362,
- /* 130 */ 732, 868, 231, 1051, 1458, -70, -70, -70, 1367, 57,
+ /* 130 */ 732, 868, 231, 1051, 1471, -70, -70, -70, 1367, 57,
/* 140 */ 434, 434, 289, 291, 285, 1, 204, 572, 539, 362,
/* 150 */ 362, 362, 362, 362, 362, 362, 362, 362, 362, 362,
/* 160 */ 362, 362, 362, 362, 362, 362, 362, 362, 362, 362,
@@ -110812,30 +111625,30 @@ static const short yy_shift_ofst[] = {
/* 200 */ 422, 358, 335, -12, -12, -12, -12, 576, 294, -12,
/* 210 */ -12, 295, 595, 141, 600, 730, 723, 723, 805, 730,
/* 220 */ 805, 439, 911, 231, 865, 231, 865, 807, 865, 723,
- /* 230 */ 766, 633, 633, 231, 284, 63, 608, 1476, 1308, 1308,
- /* 240 */ 1472, 1472, 1308, 1477, 1425, 1275, 1487, 1487, 1487, 1487,
- /* 250 */ 1308, 1461, 1275, 1477, 1425, 1425, 1308, 1461, 1355, 1441,
- /* 260 */ 1308, 1308, 1461, 1308, 1461, 1308, 1461, 1442, 1348, 1348,
- /* 270 */ 1348, 1408, 1375, 1375, 1442, 1348, 1357, 1348, 1408, 1348,
- /* 280 */ 1348, 1316, 1331, 1316, 1331, 1316, 1331, 1308, 1308, 1280,
- /* 290 */ 1288, 1289, 1285, 1279, 1275, 1253, 1336, 1346, 1346, 1338,
- /* 300 */ 1338, 1338, 1338, -70, -70, -70, -70, -70, -70, 1013,
- /* 310 */ 467, 612, 84, 179, -28, 870, 410, 761, 760, 667,
- /* 320 */ 650, 531, 220, 361, 331, 125, 127, 97, 1306, 1300,
- /* 330 */ 1270, 1151, 1272, 1203, 1232, 1261, 1244, 1148, 1174, 1139,
- /* 340 */ 1156, 1124, 1220, 1115, 1210, 1233, 1099, 1193, 1184, 1174,
- /* 350 */ 1173, 1029, 1121, 1120, 1085, 1162, 1119, 1037, 1152, 1147,
- /* 360 */ 1129, 1046, 1011, 1093, 1098, 1075, 1061, 1032, 960, 1057,
- /* 370 */ 1031, 1030, 899, 938, 982, 936, 972, 958, 910, 955,
- /* 380 */ 875, 885, 908, 857, 859, 867, 804, 590, 834, 747,
- /* 390 */ 818, 513, 611, 741, 673, 637, 611, 606, 603, 579,
- /* 400 */ 501, 541, 468, 386, 445, 395, 376, 281, 185, 120,
- /* 410 */ 92, 75, 45, 114, 25, 11, 5,
+ /* 230 */ 766, 633, 633, 231, 284, 63, 608, 1481, 1308, 1308,
+ /* 240 */ 1472, 1472, 1308, 1477, 1427, 1275, 1487, 1487, 1487, 1487,
+ /* 250 */ 1308, 1461, 1275, 1477, 1427, 1427, 1275, 1308, 1461, 1355,
+ /* 260 */ 1441, 1308, 1308, 1461, 1308, 1461, 1308, 1461, 1442, 1348,
+ /* 270 */ 1348, 1348, 1408, 1375, 1375, 1442, 1348, 1357, 1348, 1408,
+ /* 280 */ 1348, 1348, 1316, 1331, 1316, 1331, 1316, 1331, 1308, 1308,
+ /* 290 */ 1280, 1288, 1289, 1285, 1279, 1275, 1253, 1336, 1346, 1346,
+ /* 300 */ 1338, 1338, 1338, 1338, -70, -70, -70, -70, -70, -70,
+ /* 310 */ 1013, 467, 612, 84, 179, -28, 870, 410, 761, 760,
+ /* 320 */ 667, 650, 531, 220, 361, 331, 125, 127, 97, 1306,
+ /* 330 */ 1300, 1270, 1151, 1272, 1203, 1232, 1261, 1244, 1148, 1174,
+ /* 340 */ 1139, 1156, 1124, 1220, 1115, 1210, 1233, 1099, 1193, 1184,
+ /* 350 */ 1174, 1173, 1029, 1121, 1120, 1085, 1162, 1119, 1037, 1152,
+ /* 360 */ 1147, 1129, 1046, 1011, 1093, 1098, 1075, 1061, 1032, 960,
+ /* 370 */ 1057, 1031, 1030, 899, 938, 982, 936, 972, 958, 910,
+ /* 380 */ 955, 875, 885, 908, 857, 859, 867, 804, 590, 834,
+ /* 390 */ 747, 818, 513, 611, 741, 673, 637, 611, 606, 603,
+ /* 400 */ 579, 501, 541, 468, 386, 445, 395, 376, 281, 185,
+ /* 410 */ 120, 92, 75, 45, 114, 25, 11, 5,
};
#define YY_REDUCE_USE_DFLT (-169)
-#define YY_REDUCE_COUNT (308)
+#define YY_REDUCE_COUNT (309)
#define YY_REDUCE_MIN (-168)
-#define YY_REDUCE_MAX (1391)
+#define YY_REDUCE_MAX (1397)
static const short yy_reduce_ofst[] = {
/* 0 */ -141, 90, 1095, 222, 158, 156, 19, 17, 10, -104,
/* 10 */ 378, 316, 311, 12, 180, 249, 598, 464, 397, 1181,
@@ -110856,83 +111669,83 @@ static const short yy_reduce_ofst[] = {
/* 160 */ 1140, 1135, 1123, 1112, 1107, 1100, 1080, 1074, 1073, 1072,
/* 170 */ 1070, 1067, 1048, 1044, 969, 968, 907, 906, 904, 894,
/* 180 */ 833, 837, 836, 340, 827, 815, 775, 68, 722, 646,
- /* 190 */ -168, 1384, 1380, 1377, 1379, 1376, 1373, 1339, 1365, 1368,
- /* 200 */ 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1320, 1319, 1365,
- /* 210 */ 1365, 1339, 1378, 1349, 1391, 1350, 1342, 1334, 1307, 1341,
- /* 220 */ 1293, 1364, 1363, 1371, 1362, 1370, 1359, 1340, 1354, 1333,
- /* 230 */ 1305, 1304, 1299, 1361, 1328, 1324, 1366, 1282, 1360, 1358,
- /* 240 */ 1278, 1276, 1356, 1292, 1322, 1309, 1317, 1315, 1314, 1312,
- /* 250 */ 1345, 1347, 1302, 1277, 1311, 1303, 1337, 1335, 1252, 1248,
- /* 260 */ 1332, 1330, 1329, 1327, 1326, 1323, 1321, 1297, 1301, 1295,
- /* 270 */ 1294, 1290, 1243, 1240, 1284, 1291, 1286, 1283, 1274, 1281,
- /* 280 */ 1271, 1238, 1241, 1236, 1235, 1227, 1226, 1267, 1266, 1189,
- /* 290 */ 1229, 1223, 1211, 1206, 1201, 1197, 1239, 1237, 1219, 1216,
- /* 300 */ 1209, 1208, 1185, 1089, 1086, 1087, 1137, 1136, 1164,
+ /* 190 */ -168, 1389, 1381, 1371, 1379, 1373, 1370, 1343, 1352, 1369,
+ /* 200 */ 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1325, 1320, 1352,
+ /* 210 */ 1352, 1343, 1380, 1353, 1397, 1351, 1339, 1334, 1319, 1341,
+ /* 220 */ 1303, 1364, 1359, 1368, 1362, 1366, 1360, 1350, 1354, 1318,
+ /* 230 */ 1313, 1307, 1305, 1363, 1328, 1324, 1372, 1278, 1361, 1358,
+ /* 240 */ 1277, 1276, 1356, 1296, 1322, 1309, 1317, 1315, 1314, 1312,
+ /* 250 */ 1345, 1347, 1302, 1292, 1311, 1304, 1293, 1337, 1335, 1252,
+ /* 260 */ 1248, 1332, 1330, 1329, 1327, 1326, 1323, 1321, 1297, 1301,
+ /* 270 */ 1295, 1294, 1290, 1243, 1240, 1284, 1291, 1286, 1283, 1274,
+ /* 280 */ 1281, 1271, 1238, 1241, 1236, 1235, 1227, 1226, 1267, 1266,
+ /* 290 */ 1189, 1229, 1223, 1211, 1206, 1201, 1197, 1239, 1237, 1219,
+ /* 300 */ 1216, 1209, 1208, 1185, 1089, 1086, 1087, 1137, 1136, 1164,
};
static const YYACTIONTYPE yy_default[] = {
- /* 0 */ 632, 866, 954, 954, 866, 866, 954, 954, 954, 756,
- /* 10 */ 954, 954, 954, 864, 954, 954, 784, 784, 928, 954,
- /* 20 */ 954, 954, 954, 954, 954, 954, 954, 954, 954, 954,
- /* 30 */ 954, 954, 954, 954, 954, 954, 954, 954, 954, 954,
- /* 40 */ 954, 954, 954, 954, 954, 954, 954, 954, 954, 954,
- /* 50 */ 954, 954, 954, 954, 954, 954, 954, 954, 954, 954,
- /* 60 */ 954, 954, 954, 954, 954, 954, 954, 671, 760, 790,
- /* 70 */ 954, 954, 954, 954, 954, 954, 954, 954, 927, 929,
- /* 80 */ 798, 797, 907, 771, 795, 788, 792, 867, 860, 861,
- /* 90 */ 859, 863, 868, 954, 791, 827, 844, 826, 838, 843,
- /* 100 */ 850, 842, 839, 829, 828, 830, 831, 954, 954, 954,
- /* 110 */ 954, 954, 954, 954, 954, 954, 954, 954, 954, 954,
- /* 120 */ 954, 954, 954, 658, 725, 954, 954, 954, 954, 954,
- /* 130 */ 954, 954, 954, 832, 833, 847, 846, 845, 954, 663,
- /* 140 */ 954, 954, 954, 954, 954, 954, 954, 954, 954, 954,
- /* 150 */ 934, 932, 954, 879, 954, 954, 954, 954, 954, 954,
- /* 160 */ 954, 954, 954, 954, 954, 954, 954, 954, 954, 954,
- /* 170 */ 954, 954, 954, 954, 954, 954, 954, 954, 954, 954,
- /* 180 */ 638, 756, 756, 756, 632, 954, 954, 954, 946, 760,
- /* 190 */ 750, 954, 954, 954, 954, 954, 954, 954, 954, 954,
- /* 200 */ 954, 954, 954, 800, 739, 917, 919, 954, 900, 737,
- /* 210 */ 660, 758, 673, 748, 640, 794, 773, 773, 912, 794,
- /* 220 */ 912, 696, 719, 954, 784, 954, 784, 693, 784, 773,
- /* 230 */ 862, 954, 954, 954, 757, 748, 954, 939, 764, 764,
- /* 240 */ 931, 931, 764, 806, 729, 794, 736, 736, 736, 736,
- /* 250 */ 764, 655, 794, 806, 729, 729, 764, 655, 906, 904,
- /* 260 */ 764, 764, 655, 764, 655, 764, 655, 872, 727, 727,
- /* 270 */ 727, 711, 876, 876, 872, 727, 696, 727, 711, 727,
- /* 280 */ 727, 777, 772, 777, 772, 777, 772, 764, 764, 954,
- /* 290 */ 789, 778, 787, 785, 794, 954, 714, 648, 648, 637,
- /* 300 */ 637, 637, 637, 951, 951, 946, 698, 698, 681, 954,
- /* 310 */ 954, 954, 954, 954, 954, 954, 881, 954, 954, 954,
- /* 320 */ 954, 954, 954, 954, 954, 954, 954, 954, 954, 633,
- /* 330 */ 941, 954, 954, 938, 954, 954, 954, 954, 799, 954,
- /* 340 */ 954, 954, 954, 954, 954, 954, 954, 954, 954, 916,
- /* 350 */ 954, 954, 954, 954, 954, 954, 954, 910, 954, 954,
- /* 360 */ 954, 954, 954, 954, 903, 902, 954, 954, 954, 954,
- /* 370 */ 954, 954, 954, 954, 954, 954, 954, 954, 954, 954,
- /* 380 */ 954, 954, 954, 954, 954, 954, 954, 954, 954, 954,
- /* 390 */ 954, 954, 786, 954, 779, 954, 865, 954, 954, 954,
- /* 400 */ 954, 954, 954, 954, 954, 954, 954, 742, 815, 954,
- /* 410 */ 814, 818, 813, 665, 954, 646, 954, 629, 634, 950,
- /* 420 */ 953, 952, 949, 948, 947, 942, 940, 937, 936, 935,
- /* 430 */ 933, 930, 926, 885, 883, 890, 889, 888, 887, 886,
- /* 440 */ 884, 882, 880, 801, 796, 793, 925, 878, 738, 735,
- /* 450 */ 734, 654, 943, 909, 918, 805, 804, 807, 915, 914,
- /* 460 */ 913, 911, 908, 895, 803, 802, 730, 870, 869, 657,
- /* 470 */ 899, 898, 897, 901, 905, 896, 766, 656, 653, 662,
- /* 480 */ 717, 718, 726, 724, 723, 722, 721, 720, 716, 664,
- /* 490 */ 672, 710, 695, 694, 875, 877, 874, 873, 703, 702,
- /* 500 */ 708, 707, 706, 705, 704, 701, 700, 699, 692, 691,
- /* 510 */ 697, 690, 713, 712, 709, 689, 733, 732, 731, 728,
- /* 520 */ 688, 687, 686, 818, 685, 684, 824, 823, 811, 854,
- /* 530 */ 753, 752, 751, 763, 762, 775, 774, 809, 808, 776,
- /* 540 */ 761, 755, 754, 770, 769, 768, 767, 759, 749, 781,
- /* 550 */ 783, 782, 780, 856, 765, 853, 924, 923, 922, 921,
- /* 560 */ 920, 858, 857, 825, 822, 676, 677, 893, 892, 894,
- /* 570 */ 891, 679, 678, 675, 674, 855, 744, 743, 851, 848,
- /* 580 */ 840, 836, 852, 849, 841, 837, 835, 834, 820, 819,
- /* 590 */ 817, 816, 812, 821, 667, 745, 741, 740, 810, 747,
- /* 600 */ 746, 683, 682, 680, 661, 659, 652, 650, 649, 651,
- /* 610 */ 647, 645, 644, 643, 642, 641, 670, 669, 668, 666,
- /* 620 */ 665, 639, 636, 635, 631, 630, 628,
+ /* 0 */ 633, 867, 955, 955, 867, 867, 955, 955, 955, 757,
+ /* 10 */ 955, 955, 955, 865, 955, 955, 785, 785, 929, 955,
+ /* 20 */ 955, 955, 955, 955, 955, 955, 955, 955, 955, 955,
+ /* 30 */ 955, 955, 955, 955, 955, 955, 955, 955, 955, 955,
+ /* 40 */ 955, 955, 955, 955, 955, 955, 955, 955, 955, 955,
+ /* 50 */ 955, 955, 955, 955, 955, 955, 955, 955, 955, 955,
+ /* 60 */ 955, 955, 955, 955, 955, 955, 955, 672, 761, 791,
+ /* 70 */ 955, 955, 955, 955, 955, 955, 955, 955, 928, 930,
+ /* 80 */ 799, 798, 908, 772, 796, 789, 793, 868, 861, 862,
+ /* 90 */ 860, 864, 869, 955, 792, 828, 845, 827, 839, 844,
+ /* 100 */ 851, 843, 840, 830, 829, 831, 832, 955, 955, 955,
+ /* 110 */ 955, 955, 955, 955, 955, 955, 955, 955, 955, 955,
+ /* 120 */ 955, 955, 955, 659, 726, 955, 955, 955, 955, 955,
+ /* 130 */ 955, 955, 955, 833, 834, 848, 847, 846, 955, 664,
+ /* 140 */ 955, 955, 955, 955, 955, 955, 955, 955, 955, 955,
+ /* 150 */ 935, 933, 955, 880, 955, 955, 955, 955, 955, 955,
+ /* 160 */ 955, 955, 955, 955, 955, 955, 955, 955, 955, 955,
+ /* 170 */ 955, 955, 955, 955, 955, 955, 955, 955, 955, 955,
+ /* 180 */ 639, 757, 757, 757, 633, 955, 955, 955, 947, 761,
+ /* 190 */ 751, 955, 955, 955, 955, 955, 955, 955, 955, 955,
+ /* 200 */ 955, 955, 955, 801, 740, 918, 920, 955, 901, 738,
+ /* 210 */ 661, 759, 674, 749, 641, 795, 774, 774, 913, 795,
+ /* 220 */ 913, 697, 720, 955, 785, 955, 785, 694, 785, 774,
+ /* 230 */ 863, 955, 955, 955, 758, 749, 955, 940, 765, 765,
+ /* 240 */ 932, 932, 765, 807, 730, 795, 737, 737, 737, 737,
+ /* 250 */ 765, 656, 795, 807, 730, 730, 795, 765, 656, 907,
+ /* 260 */ 905, 765, 765, 656, 765, 656, 765, 656, 873, 728,
+ /* 270 */ 728, 728, 712, 877, 877, 873, 728, 697, 728, 712,
+ /* 280 */ 728, 728, 778, 773, 778, 773, 778, 773, 765, 765,
+ /* 290 */ 955, 790, 779, 788, 786, 795, 955, 715, 649, 649,
+ /* 300 */ 638, 638, 638, 638, 952, 952, 947, 699, 699, 682,
+ /* 310 */ 955, 955, 955, 955, 955, 955, 955, 882, 955, 955,
+ /* 320 */ 955, 955, 955, 955, 955, 955, 955, 955, 955, 955,
+ /* 330 */ 634, 942, 955, 955, 939, 955, 955, 955, 955, 800,
+ /* 340 */ 955, 955, 955, 955, 955, 955, 955, 955, 955, 955,
+ /* 350 */ 917, 955, 955, 955, 955, 955, 955, 955, 911, 955,
+ /* 360 */ 955, 955, 955, 955, 955, 904, 903, 955, 955, 955,
+ /* 370 */ 955, 955, 955, 955, 955, 955, 955, 955, 955, 955,
+ /* 380 */ 955, 955, 955, 955, 955, 955, 955, 955, 955, 955,
+ /* 390 */ 955, 955, 955, 787, 955, 780, 955, 866, 955, 955,
+ /* 400 */ 955, 955, 955, 955, 955, 955, 955, 955, 743, 816,
+ /* 410 */ 955, 815, 819, 814, 666, 955, 647, 955, 630, 635,
+ /* 420 */ 951, 954, 953, 950, 949, 948, 943, 941, 938, 937,
+ /* 430 */ 936, 934, 931, 927, 886, 884, 891, 890, 889, 888,
+ /* 440 */ 887, 885, 883, 881, 802, 797, 794, 926, 879, 739,
+ /* 450 */ 736, 735, 655, 944, 910, 919, 806, 805, 808, 916,
+ /* 460 */ 915, 914, 912, 909, 896, 804, 803, 731, 871, 870,
+ /* 470 */ 658, 900, 899, 898, 902, 906, 897, 767, 657, 654,
+ /* 480 */ 663, 718, 719, 727, 725, 724, 723, 722, 721, 717,
+ /* 490 */ 665, 673, 711, 696, 695, 876, 878, 875, 874, 704,
+ /* 500 */ 703, 709, 708, 707, 706, 705, 702, 701, 700, 693,
+ /* 510 */ 692, 698, 691, 714, 713, 710, 690, 734, 733, 732,
+ /* 520 */ 729, 689, 688, 687, 819, 686, 685, 825, 824, 812,
+ /* 530 */ 855, 754, 753, 752, 764, 763, 776, 775, 810, 809,
+ /* 540 */ 777, 762, 756, 755, 771, 770, 769, 768, 760, 750,
+ /* 550 */ 782, 784, 783, 781, 857, 766, 854, 925, 924, 923,
+ /* 560 */ 922, 921, 859, 858, 826, 823, 677, 678, 894, 893,
+ /* 570 */ 895, 892, 680, 679, 676, 675, 856, 745, 744, 852,
+ /* 580 */ 849, 841, 837, 853, 850, 842, 838, 836, 835, 821,
+ /* 590 */ 820, 818, 817, 813, 822, 668, 746, 742, 741, 811,
+ /* 600 */ 748, 747, 684, 683, 681, 662, 660, 653, 651, 650,
+ /* 610 */ 652, 648, 646, 645, 644, 643, 642, 671, 670, 669,
+ /* 620 */ 667, 666, 640, 637, 636, 632, 631, 629,
};
/* The next table maps tokens into fallback tokens. If a construct
@@ -111404,7 +112217,7 @@ static const char *const yyRuleName[] = {
/* 239 */ "exprlist ::=",
/* 240 */ "nexprlist ::= nexprlist COMMA expr",
/* 241 */ "nexprlist ::= expr",
- /* 242 */ "cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP idxlist RP",
+ /* 242 */ "cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP idxlist RP where_opt",
/* 243 */ "uniqueflag ::= UNIQUE",
/* 244 */ "uniqueflag ::=",
/* 245 */ "idxlist_opt ::=",
@@ -112123,7 +112936,7 @@ static const struct {
{ 220, 0 },
{ 215, 3 },
{ 215, 1 },
- { 147, 11 },
+ { 147, 12 },
{ 227, 1 },
{ 227, 0 },
{ 178, 0 },
@@ -112565,6 +113378,7 @@ static void yy_reduce(
if( yymsp[0].minor.yy159 ){
yymsp[0].minor.yy159->op = (u8)yymsp[-1].minor.yy392;
yymsp[0].minor.yy159->pPrior = yymsp[-2].minor.yy159;
+ if( yymsp[-1].minor.yy392!=TK_ALL ) pParse->hasCompound = 1;
}else{
sqlite3SelectDelete(pParse->db, yymsp[-2].minor.yy159);
}
@@ -113127,11 +113941,11 @@ static void yy_reduce(
case 241: /* nexprlist ::= expr */
{yygotominor.yy442 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy342.pExpr);}
break;
- case 242: /* cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP idxlist RP */
+ case 242: /* cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP idxlist RP where_opt */
{
- sqlite3CreateIndex(pParse, &yymsp[-6].minor.yy0, &yymsp[-5].minor.yy0,
- sqlite3SrcListAppend(pParse->db,0,&yymsp[-3].minor.yy0,0), yymsp[-1].minor.yy442,
yymsp[-9].minor.yy392,
- &yymsp[-10].minor.yy0, &yymsp[0].minor.yy0, SQLITE_SO_ASC, yymsp[-7].minor.yy392);
+ sqlite3CreateIndex(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0,
+ sqlite3SrcListAppend(pParse->db,0,&yymsp[-4].minor.yy0,0), yymsp[-2].minor.yy442,
yymsp[-10].minor.yy392,
+ &yymsp[-11].minor.yy0, yymsp[0].minor.yy122, SQLITE_SO_ASC, yymsp[-8].minor.yy392);
}
break;
case 243: /* uniqueflag ::= UNIQUE */
@@ -114057,7 +114871,6 @@ SQLITE_PRIVATE int sqlite3GetToken(const unsigned char *z, int *tokenType){
}
case '-': {
if( z[1]=='-' ){
- /* IMP: R-50417-27976 -- syntax diagram for comments */
for(i=2; (c=z[i])!=0 && c!='\n'; i++){}
*tokenType = TK_SPACE; /* IMP: R-22934-25134 */
return i;
@@ -114090,7 +114903,6 @@ SQLITE_PRIVATE int sqlite3GetToken(const unsigned char *z, int *tokenType){
*tokenType = TK_SLASH;
return 1;
}
- /* IMP: R-50417-27976 -- syntax diagram for comments */
for(i=3, c=z[2]; (c!='*' || z[i]!='/') && (c=z[i])!=0; i++){}
if( c ) i++;
*tokenType = TK_SPACE; /* IMP: R-22934-25134 */
@@ -114330,7 +115142,7 @@ SQLITE_PRIVATE int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzEr
mxSqlLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH];
- if( db->activeVdbeCnt==0 ){
+ if( db->nVdbeActive==0 ){
db->u1.isInterrupted = 0;
}
pParse->rc = SQLITE_OK;
@@ -114952,6 +115764,9 @@ SQLITE_API char *sqlite3_data_directory = 0;
SQLITE_API int sqlite3_initialize(void){
MUTEX_LOGIC( sqlite3_mutex *pMaster; ) /* The main static mutex */
int rc; /* Result code */
+#ifdef SQLITE_EXTRA_INIT
+ int bRunExtraInit = 0; /* Extra initialization needed */
+#endif
#ifdef SQLITE_OMIT_WSD
rc = sqlite3_wsd_init(4096, 24);
@@ -115049,6 +115864,9 @@ SQLITE_API int sqlite3_initialize(void){
sqlite3PCacheBufferSetup( sqlite3GlobalConfig.pPage,
sqlite3GlobalConfig.szPage, sqlite3GlobalConfig.nPage);
sqlite3GlobalConfig.isInit = 1;
+#ifdef SQLITE_EXTRA_INIT
+ bRunExtraInit = 1;
+#endif
}
sqlite3GlobalConfig.inProgress = 0;
}
@@ -115089,7 +115907,7 @@ SQLITE_API int sqlite3_initialize(void){
** compile-time option.
*/
#ifdef SQLITE_EXTRA_INIT
- if( rc==SQLITE_OK && sqlite3GlobalConfig.isInit ){
+ if( bRunExtraInit ){
int SQLITE_EXTRA_INIT(const char*);
rc = SQLITE_EXTRA_INIT(0);
}
@@ -115277,8 +116095,8 @@ SQLITE_API int sqlite3_config(int op, ...){
memset(&sqlite3GlobalConfig.m, 0, sizeof(sqlite3GlobalConfig.m));
}else{
/* The heap pointer is not NULL, then install one of the
- ** mem5.c/mem3.c methods. If neither ENABLE_MEMSYS3 nor
- ** ENABLE_MEMSYS5 is defined, return an error.
+ ** mem5.c/mem3.c methods. The enclosing #if guarantees at
+ ** least one of these methods is currently enabled.
*/
#ifdef SQLITE_ENABLE_MEMSYS3
sqlite3GlobalConfig.m = *sqlite3MemGetMemsys3();
@@ -115297,7 +116115,7 @@ SQLITE_API int sqlite3_config(int op, ...){
break;
}
- /* Record a pointer to the logger funcction and its first argument.
+ /* Record a pointer to the logger function and its first argument.
** The default is NULL. Logging is disabled if the function pointer is
** NULL.
*/
@@ -115536,7 +116354,7 @@ static int binCollFunc(
/*
** Another built-in collating sequence: NOCASE.
**
-** This collating sequence is intended to be used for "case independant
+** This collating sequence is intended to be used for "case independent
** comparison". SQLite's knowledge of upper and lower case equivalents
** extends only to the 26 characters used in the English language.
**
@@ -115859,7 +116677,6 @@ SQLITE_PRIVATE void sqlite3RollbackAll(sqlite3 *db, int tripCode){
inTrans = 1;
}
sqlite3BtreeRollback(p, tripCode);
- db->aDb[i].inTrans = 0;
}
}
sqlite3VtabRollback(db);
@@ -115873,6 +116690,8 @@ SQLITE_PRIVATE void sqlite3RollbackAll(sqlite3 *db, int tripCode){
/* Any deferred constraint violations have now been resolved. */
db->nDeferredCons = 0;
+ db->nDeferredImmCons = 0;
+ db->flags &= ~SQLITE_DeferFKs;
/* If one has been configured, invoke the rollback-hook callback */
if( db->xRollbackCallback && (inTrans || !db->autoCommit) ){
@@ -115899,6 +116718,7 @@ SQLITE_PRIVATE const char *sqlite3ErrName(int rc){
case SQLITE_ABORT_ROLLBACK: zName = "SQLITE_ABORT_ROLLBACK"; break;
case SQLITE_BUSY: zName = "SQLITE_BUSY"; break;
case SQLITE_BUSY_RECOVERY: zName = "SQLITE_BUSY_RECOVERY"; break;
+ case SQLITE_BUSY_SNAPSHOT: zName = "SQLITE_BUSY_SNAPSHOT"; break;
case SQLITE_LOCKED: zName = "SQLITE_LOCKED"; break;
case SQLITE_LOCKED_SHAREDCACHE: zName = "SQLITE_LOCKED_SHAREDCACHE";break;
case SQLITE_NOMEM: zName = "SQLITE_NOMEM"; break;
@@ -115933,6 +116753,7 @@ SQLITE_PRIVATE const char *sqlite3ErrName(int rc){
case SQLITE_IOERR_SEEK: zName = "SQLITE_IOERR_SEEK"; break;
case SQLITE_IOERR_DELETE_NOENT: zName = "SQLITE_IOERR_DELETE_NOENT";break;
case SQLITE_IOERR_MMAP: zName = "SQLITE_IOERR_MMAP"; break;
+ case SQLITE_IOERR_GETTEMPPATH: zName = "SQLITE_IOERR_GETTEMPPATH"; break;
case SQLITE_CORRUPT: zName = "SQLITE_CORRUPT"; break;
case SQLITE_CORRUPT_VTAB: zName = "SQLITE_CORRUPT_VTAB"; break;
case SQLITE_NOTFOUND: zName = "SQLITE_NOTFOUND"; break;
@@ -115972,6 +116793,7 @@ SQLITE_PRIVATE const char *sqlite3ErrName(int rc){
case SQLITE_NOTICE_RECOVER_ROLLBACK:
zName = "SQLITE_NOTICE_RECOVER_ROLLBACK"; break;
case SQLITE_WARNING: zName = "SQLITE_WARNING"; break;
+ case SQLITE_WARNING_AUTOINDEX: zName = "SQLITE_WARNING_AUTOINDEX"; break;
case SQLITE_DONE: zName = "SQLITE_DONE"; break;
}
}
@@ -116132,7 +116954,7 @@ SQLITE_API void sqlite3_progress_handler(
sqlite3_mutex_enter(db->mutex);
if( nOps>0 ){
db->xProgress = xProgress;
- db->nProgressOps = nOps;
+ db->nProgressOps = (unsigned)nOps;
db->pProgressArg = pArg;
}else{
db->xProgress = 0;
@@ -116230,7 +117052,7 @@ SQLITE_PRIVATE int sqlite3CreateFunc(
*/
p = sqlite3FindFunction(db, zFunctionName, nName, nArg, (u8)enc, 0);
if( p && p->iPrefEnc==enc && p->nArg==nArg ){
- if( db->activeVdbeCnt ){
+ if( db->nVdbeActive ){
sqlite3Error(db, SQLITE_BUSY,
"unable to delete/modify user-function due to active statements");
assert( !db->mallocFailed );
@@ -116811,7 +117633,7 @@ static int createCollation(
*/
pColl = sqlite3FindCollSeq(db, (u8)enc2, zName, 0);
if( pColl && pColl->xCmp ){
- if( db->activeVdbeCnt ){
+ if( db->nVdbeActive ){
sqlite3Error(db, SQLITE_BUSY,
"unable to delete/modify collation sequence due to active statements");
return SQLITE_BUSY;
@@ -117009,20 +117831,20 @@ SQLITE_PRIVATE int sqlite3ParseUri(
zFile = sqlite3_malloc(nByte);
if( !zFile ) return SQLITE_NOMEM;
+ iIn = 5;
+#ifndef SQLITE_ALLOW_URI_AUTHORITY
/* Discard the scheme and authority segments of the URI. */
if( zUri[5]=='/' && zUri[6]=='/' ){
iIn = 7;
while( zUri[iIn] && zUri[iIn]!='/' ) iIn++;
-
if( iIn!=7 && (iIn!=16 || memcmp("localhost", &zUri[7], 9)) ){
*pzErrMsg = sqlite3_mprintf("invalid uri authority: %.*s",
iIn-7, &zUri[7]);
rc = SQLITE_ERROR;
goto parse_uri_out;
}
- }else{
- iIn = 5;
}
+#endif
/* Copy the filename and any query parameters into the zFile buffer.
** Decode %HH escape codes along the way.
@@ -117286,7 +118108,10 @@ static int openDatabase(
db->nextAutovac = -1;
db->szMmap = sqlite3GlobalConfig.szMmap;
db->nextPagesize = 0;
- db->flags |= SQLITE_ShortColNames | SQLITE_AutoIndex | SQLITE_EnableTrigger
+ db->flags |= SQLITE_ShortColNames | SQLITE_EnableTrigger | SQLITE_CacheSpill
+#if !defined(SQLITE_DEFAULT_AUTOMATIC_INDEX) || SQLITE_DEFAULT_AUTOMATIC_INDEX
+ | SQLITE_AutoIndex
+#endif
#if SQLITE_DEFAULT_FILE_FORMAT<4
| SQLITE_LegacyFileFmt
#endif
@@ -117626,8 +118451,6 @@ SQLITE_API int sqlite3_global_recover(void){
** mode. Return TRUE if it is and FALSE if not. Autocommit mode is on
** by default. Autocommit is disabled by a BEGIN statement and reenabled
** by the next COMMIT or ROLLBACK.
-**
-******* THIS IS AN EXPERIMENTAL API AND IS SUBJECT TO CHANGE ******
*/
SQLITE_API int sqlite3_get_autocommit(sqlite3 *db){
return db->autoCommit;
@@ -118830,7 +119653,7 @@ SQLITE_PRIVATE void sqlite3ConnectionClosed(sqlite3 *db){
/* If not building as part of the core, include sqlite3ext.h. */
#ifndef SQLITE_CORE
-SQLITE_API extern const sqlite3_api_routines *sqlite3_api;
+SQLITE_EXTENSION_INIT3
#endif
/************** Include fts3_tokenizer.h in the middle of fts3Int.h **********/
@@ -119117,6 +119940,18 @@ SQLITE_PRIVATE Fts3HashElem *sqlite3Fts3HashFindElem(const Fts3Hash *, const voi
/************** Continuing where we left off in fts3Int.h ********************/
/*
+** This constant determines the maximum depth of an FTS expression tree
+** that the library will create and use. FTS uses recursion to perform
+** various operations on the query tree, so the disadvantage of a large
+** limit is that it may allow very large queries to use large amounts
+** of stack space (perhaps causing a stack overflow).
+*/
+#ifndef SQLITE_FTS3_MAX_EXPR_DEPTH
+# define SQLITE_FTS3_MAX_EXPR_DEPTH 12
+#endif
+
+
+/*
** This constant controls how often segments are merged. Once there are
** FTS3_MERGE_COUNT segments of level N, they are merged into a single
** segment of level N+1.
@@ -119271,6 +120106,7 @@ struct Fts3Table {
const char *zName; /* virtual table name */
int nColumn; /* number of named columns in virtual table */
char **azColumn; /* column names. malloced */
+ u8 *abNotindexed; /* True for 'notindexed' columns */
sqlite3_tokenizer *pTokenizer; /* tokenizer for inserts and queries */
char *zContentTbl; /* content=xxx option, or NULL */
char *zLanguageid; /* languageid=xxx option, or NULL */
@@ -119498,7 +120334,6 @@ SQLITE_PRIVATE int sqlite3Fts3SegReaderPending(
Fts3Table*,int,const char*,int,int,Fts3SegReader**);
SQLITE_PRIVATE void sqlite3Fts3SegReaderFree(Fts3SegReader *);
SQLITE_PRIVATE int sqlite3Fts3AllSegdirs(Fts3Table*, int, int, int, sqlite3_stmt **);
-SQLITE_PRIVATE int sqlite3Fts3ReadLock(Fts3Table *);
SQLITE_PRIVATE int sqlite3Fts3ReadBlock(Fts3Table*, sqlite3_int64, char **, int*, int*);
SQLITE_PRIVATE int sqlite3Fts3SelectDoctotal(Fts3Table *, sqlite3_stmt **);
@@ -120431,6 +121266,8 @@ static int fts3InitVtab(
char *zUncompress = 0; /* uncompress=? parameter (or NULL) */
char *zContent = 0; /* content=? parameter (or NULL) */
char *zLanguageid = 0; /* languageid=? parameter (or NULL) */
+ char **azNotindexed = 0; /* The set of notindexed= columns */
+ int nNotindexed = 0; /* Size of azNotindexed[] array */
assert( strlen(argv[0])==4 );
assert( (sqlite3_strnicmp(argv[0], "fts4", 4)==0 && isFts4)
@@ -120440,9 +121277,19 @@ static int fts3InitVtab(
nDb = (int)strlen(argv[1]) + 1;
nName = (int)strlen(argv[2]) + 1;
- aCol = (const char **)sqlite3_malloc(sizeof(const char *) * (argc-2) );
- if( !aCol ) return SQLITE_NOMEM;
- memset((void *)aCol, 0, sizeof(const char *) * (argc-2));
+ nByte = sizeof(const char *) * (argc-2);
+ aCol = (const char **)sqlite3_malloc(nByte);
+ if( aCol ){
+ memset((void*)aCol, 0, nByte);
+ azNotindexed = (char **)sqlite3_malloc(nByte);
+ }
+ if( azNotindexed ){
+ memset(azNotindexed, 0, nByte);
+ }
+ if( !aCol || !azNotindexed ){
+ rc = SQLITE_NOMEM;
+ goto fts3_init_out;
+ }
/* Loop through all of the arguments passed by the user to the FTS3/4
** module (i.e. all the column names and special arguments). This loop
@@ -120481,7 +121328,8 @@ static int fts3InitVtab(
{ "uncompress", 10 }, /* 3 -> UNCOMPRESS */
{ "order", 5 }, /* 4 -> ORDER */
{ "content", 7 }, /* 5 -> CONTENT */
- { "languageid", 10 } /* 6 -> LANGUAGEID */
+ { "languageid", 10 }, /* 6 -> LANGUAGEID */
+ { "notindexed", 10 } /* 7 -> NOTINDEXED */
};
int iOpt;
@@ -120547,6 +121395,11 @@ static int fts3InitVtab(
zLanguageid = zVal;
zVal = 0;
break;
+
+ case 7: /* NOTINDEXED */
+ azNotindexed[nNotindexed++] = zVal;
+ zVal = 0;
+ break;
}
}
sqlite3_free(zVal);
@@ -120618,6 +121471,7 @@ static int fts3InitVtab(
nByte = sizeof(Fts3Table) + /* Fts3Table */
nCol * sizeof(char *) + /* azColumn */
nIndex * sizeof(struct Fts3Index) + /* aIndex */
+ nCol * sizeof(u8) + /* abNotindexed */
nName + /* zName */
nDb + /* zDb */
nString; /* Space for azColumn strings */
@@ -120651,9 +121505,10 @@ static int fts3InitVtab(
for(i=0; i<nIndex; i++){
fts3HashInit(&p->aIndex[i].hPending, FTS3_HASH_STRING, 1);
}
+ p->abNotindexed = (u8 *)&p->aIndex[nIndex];
/* Fill in the zName and zDb fields of the vtab structure. */
- zCsr = (char *)&p->aIndex[nIndex];
+ zCsr = (char *)&p->abNotindexed[nCol];
p->zName = zCsr;
memcpy(zCsr, argv[2], nName);
zCsr += nName;
@@ -120674,7 +121529,26 @@ static int fts3InitVtab(
assert( zCsr <= &((char *)p)[nByte] );
}
- if( (zCompress==0)!=(zUncompress==0) ){
+ /* Fill in the abNotindexed array */
+ for(iCol=0; iCol<nCol; iCol++){
+ int n = (int)strlen(p->azColumn[iCol]);
+ for(i=0; i<nNotindexed; i++){
+ char *zNot = azNotindexed[i];
+ if( zNot && 0==sqlite3_strnicmp(p->azColumn[iCol], zNot, n) ){
+ p->abNotindexed[iCol] = 1;
+ sqlite3_free(zNot);
+ azNotindexed[i] = 0;
+ }
+ }
+ }
+ for(i=0; i<nNotindexed; i++){
+ if( azNotindexed[i] ){
+ *pzErr = sqlite3_mprintf("no such column: %s", azNotindexed[i]);
+ rc = SQLITE_ERROR;
+ }
+ }
+
+ if( rc==SQLITE_OK && (zCompress==0)!=(zUncompress==0) ){
char const *zMiss = (zCompress==0 ? "compress" : "uncompress");
rc = SQLITE_ERROR;
*pzErr = sqlite3_mprintf("missing %s parameter in fts4 constructor", zMiss);
@@ -120715,7 +121589,9 @@ fts3_init_out:
sqlite3_free(zUncompress);
sqlite3_free(zContent);
sqlite3_free(zLanguageid);
+ for(i=0; i<nNotindexed; i++) sqlite3_free(azNotindexed[i]);
sqlite3_free((void *)aCol);
+ sqlite3_free((void *)azNotindexed);
if( rc!=SQLITE_OK ){
if( p ){
fts3DisconnectMethod((sqlite3_vtab *)p);
@@ -120773,7 +121649,7 @@ static int fts3BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
** strategy is possible.
*/
pInfo->idxNum = FTS3_FULLSCAN_SEARCH;
- pInfo->estimatedCost = 500000;
+ pInfo->estimatedCost = 5000000;
for(i=0; i<pInfo->nConstraint; i++){
struct sqlite3_index_constraint *pCons = &pInfo->aConstraint[i];
if( pCons->usable==0 ) continue;
@@ -122334,11 +123210,7 @@ static int fts3FilterMethod(
return rc;
}
- rc = sqlite3Fts3ReadLock(p);
- if( rc!=SQLITE_OK ) return rc;
-
rc = fts3EvalStart(pCsr);
-
sqlite3Fts3SegmentsClose(p);
if( rc!=SQLITE_OK ) return rc;
pCsr->pNextId = pCsr->aDoclist;
@@ -124689,7 +125561,10 @@ SQLITE_PRIVATE int sqlite3Fts3Corrupt(){
/*
** Initialize API pointer table, if required.
*/
-SQLITE_API int sqlite3_extension_init(
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+SQLITE_API int sqlite3_fts3_init(
sqlite3 *db,
char **pzErrMsg,
const sqlite3_api_routines *pApi
@@ -126193,17 +127068,16 @@ SQLITE_PRIVATE int sqlite3Fts3ExprParse(
Fts3Expr **ppExpr, /* OUT: Parsed query structure */
char **pzErr /* OUT: Error message (sqlite3_malloc) */
){
- static const int MAX_EXPR_DEPTH = 12;
int rc = fts3ExprParseUnbalanced(
pTokenizer, iLangid, azCol, bFts4, nCol, iDefaultCol, z, n, ppExpr
);
/* Rebalance the expression. And check that its depth does not exceed
- ** MAX_EXPR_DEPTH. */
+ ** SQLITE_FTS3_MAX_EXPR_DEPTH. */
if( rc==SQLITE_OK && *ppExpr ){
- rc = fts3ExprBalance(ppExpr, MAX_EXPR_DEPTH);
+ rc = fts3ExprBalance(ppExpr, SQLITE_FTS3_MAX_EXPR_DEPTH);
if( rc==SQLITE_OK ){
- rc = fts3ExprCheckDepth(*ppExpr, MAX_EXPR_DEPTH);
+ rc = fts3ExprCheckDepth(*ppExpr, SQLITE_FTS3_MAX_EXPR_DEPTH);
}
}
@@ -126212,7 +127086,8 @@ SQLITE_PRIVATE int sqlite3Fts3ExprParse(
*ppExpr = 0;
if( rc==SQLITE_TOOBIG ){
*pzErr = sqlite3_mprintf(
- "FTS expression tree is too large (maximum depth %d)", MAX_EXPR_DEPTH
+ "FTS expression tree is too large (maximum depth %d)",
+ SQLITE_FTS3_MAX_EXPR_DEPTH
);
rc = SQLITE_ERROR;
}else if( rc==SQLITE_ERROR ){
@@ -127707,7 +128582,7 @@ SQLITE_PRIVATE int sqlite3Fts3InitTokenizer(
#ifdef SQLITE_TEST
-/* #include <tcl.h> */
+#include <tcl.h>
/* #include <string.h> */
/*
@@ -129174,37 +130049,30 @@ static void fts3SqlExec(
/*
-** This function ensures that the caller has obtained a shared-cache
-** table-lock on the %_content table. This is required before reading
-** data from the fts3 table. If this lock is not acquired first, then
-** the caller may end up holding read-locks on the %_segments and %_segdir
-** tables, but no read-lock on the %_content table. If this happens
-** a second connection will be able to write to the fts3 table, but
-** attempting to commit those writes might return SQLITE_LOCKED or
-** SQLITE_LOCKED_SHAREDCACHE (because the commit attempts to obtain
-** write-locks on the %_segments and %_segdir ** tables).
+** This function ensures that the caller has obtained an exclusive
+** shared-cache table-lock on the %_segdir table. This is required before
+** writing data to the fts3 table. If this lock is not acquired first, then
+** the caller may end up attempting to take this lock as part of committing
+** a transaction, causing SQLite to return SQLITE_LOCKED or
+** LOCKED_SHAREDCACHEto a COMMIT command.
**
-** We try to avoid this because if FTS3 returns any error when committing
-** a transaction, the whole transaction will be rolled back. And this is
-** not what users expect when they get SQLITE_LOCKED_SHAREDCACHE. It can
-** still happen if the user reads data directly from the %_segments or
-** %_segdir tables instead of going through FTS3 though.
-**
-** This reasoning does not apply to a content=xxx table.
+** It is best to avoid this because if FTS3 returns any error when
+** committing a transaction, the whole transaction will be rolled back.
+** And this is not what users expect when they get SQLITE_LOCKED_SHAREDCACHE.
+** It can still happen if the user locks the underlying tables directly
+** instead of accessing them via FTS.
*/
-SQLITE_PRIVATE int sqlite3Fts3ReadLock(Fts3Table *p){
- int rc; /* Return code */
- sqlite3_stmt *pStmt; /* Statement used to obtain lock */
-
- if( p->zContentTbl==0 ){
- rc = fts3SqlStmt(p, SQL_SELECT_CONTENT_BY_ROWID, &pStmt, 0);
+static int fts3Writelock(Fts3Table *p){
+ int rc = SQLITE_OK;
+
+ if( p->nPendingData==0 ){
+ sqlite3_stmt *pStmt;
+ rc = fts3SqlStmt(p, SQL_DELETE_SEGDIR_LEVEL, &pStmt, 0);
if( rc==SQLITE_OK ){
sqlite3_bind_null(pStmt, 1);
sqlite3_step(pStmt);
rc = sqlite3_reset(pStmt);
}
- }else{
- rc = SQLITE_OK;
}
return rc;
@@ -129592,12 +130460,15 @@ static int fts3InsertTerms(
){
int i; /* Iterator variable */
for(i=2; i<p->nColumn+2; i++){
- const char *zText = (const char *)sqlite3_value_text(apVal[i]);
- int rc = fts3PendingTermsAdd(p, iLangid, zText, i-2, &aSz[i-2]);
- if( rc!=SQLITE_OK ){
- return rc;
+ int iCol = i-2;
+ if( p->abNotindexed[iCol]==0 ){
+ const char *zText = (const char *)sqlite3_value_text(apVal[i]);
+ int rc = fts3PendingTermsAdd(p, iLangid, zText, iCol, &aSz[iCol]);
+ if( rc!=SQLITE_OK ){
+ return rc;
+ }
+ aSz[p->nColumn] += sqlite3_value_bytes(apVal[i]);
}
- aSz[p->nColumn] += sqlite3_value_bytes(apVal[i]);
}
return SQLITE_OK;
}
@@ -129744,9 +130615,12 @@ static void fts3DeleteTerms(
int iLangid = langidFromSelect(p, pSelect);
rc = fts3PendingTermsDocid(p, iLangid, sqlite3_column_int64(pSelect, 0));
for(i=1; rc==SQLITE_OK && i<=p->nColumn; i++){
- const char *zText = (const char *)sqlite3_column_text(pSelect, i);
- rc = fts3PendingTermsAdd(p, iLangid, zText, -1, &aSz[i-1]);
- aSz[p->nColumn] += sqlite3_column_bytes(pSelect, i);
+ int iCol = i-1;
+ if( p->abNotindexed[iCol]==0 ){
+ const char *zText = (const char *)sqlite3_column_text(pSelect, i);
+ rc = fts3PendingTermsAdd(p, iLangid, zText, -1, &aSz[iCol]);
+ aSz[p->nColumn] += sqlite3_column_bytes(pSelect, i);
+ }
}
if( rc!=SQLITE_OK ){
sqlite3_reset(pSelect);
@@ -130147,7 +131021,7 @@ static int fts3SegReaderNextDocid(
/* The following line of code (and the "p++" below the while() loop) is
** normally all that is required to move pointer p to the desired
** position. The exception is if this node is being loaded from disk
- ** incrementally and pointer "p" now points to the first byte passed
+ ** incrementally and pointer "p" now points to the first byte past
** the populated part of pReader->aNode[].
*/
while( *p | c ) c = *p++ & 0x80;
@@ -131534,8 +132408,8 @@ SQLITE_PRIVATE int sqlite3Fts3SegReaderStep(
fts3SegReaderSort(apSegment, nMerge, nMerge, xCmp);
while( apSegment[0]->pOffsetList ){
int j; /* Number of segments that share a docid */
- char *pList;
- int nList;
+ char *pList = 0;
+ int nList = 0;
int nByte;
sqlite3_int64 iDocid = apSegment[0]->iDocid;
fts3SegReaderNextDocid(p, apSegment[0], &pList, &nList);
@@ -131988,9 +132862,11 @@ static int fts3DoRebuild(Fts3Table *p){
rc = fts3PendingTermsDocid(p, iLangid, sqlite3_column_int64(pStmt, 0));
memset(aSz, 0, sizeof(aSz[0]) * (p->nColumn+1));
for(iCol=0; rc==SQLITE_OK && iCol<p->nColumn; iCol++){
- const char *z = (const char *) sqlite3_column_text(pStmt, iCol+1);
- rc = fts3PendingTermsAdd(p, iLangid, z, iCol, &aSz[iCol]);
- aSz[p->nColumn] += sqlite3_column_bytes(pStmt, iCol+1);
+ if( p->abNotindexed[iCol]==0 ){
+ const char *z = (const char *) sqlite3_column_text(pStmt, iCol+1);
+ rc = fts3PendingTermsAdd(p, iLangid, z, iCol, &aSz[iCol]);
+ aSz[p->nColumn] += sqlite3_column_bytes(pStmt, iCol+1);
+ }
}
if( p->bHasDocsize ){
fts3InsertDocsize(&rc, p, aSz);
@@ -133793,32 +134669,34 @@ SQLITE_PRIVATE int sqlite3Fts3CacheDeferredDoclists(Fts3Cursor *pCsr){
iDocid = sqlite3_column_int64(pCsr->pStmt, 0);
for(i=0; i<p->nColumn && rc==SQLITE_OK; i++){
- const char *zText = (const char *)sqlite3_column_text(pCsr->pStmt, i+1);
- sqlite3_tokenizer_cursor *pTC = 0;
-
- rc = sqlite3Fts3OpenTokenizer(pT, pCsr->iLangid, zText, -1, &pTC);
- while( rc==SQLITE_OK ){
- char const *zToken; /* Buffer containing token */
- int nToken = 0; /* Number of bytes in token */
- int iDum1 = 0, iDum2 = 0; /* Dummy variables */
- int iPos = 0; /* Position of token in zText */
-
- rc = pModule->xNext(pTC, &zToken, &nToken, &iDum1, &iDum2, &iPos);
- for(pDef=pCsr->pDeferred; pDef && rc==SQLITE_OK; pDef=pDef->pNext){
- Fts3PhraseToken *pPT = pDef->pToken;
- if( (pDef->iCol>=p->nColumn || pDef->iCol==i)
- && (pPT->bFirst==0 || iPos==0)
- && (pPT->n==nToken || (pPT->isPrefix && pPT->n<nToken))
- && (0==memcmp(zToken, pPT->z, pPT->n))
- ){
- fts3PendingListAppend(&pDef->pList, iDocid, i, iPos, &rc);
+ if( p->abNotindexed[i]==0 ){
+ const char *zText = (const char *)sqlite3_column_text(pCsr->pStmt, i+1);
+ sqlite3_tokenizer_cursor *pTC = 0;
+
+ rc = sqlite3Fts3OpenTokenizer(pT, pCsr->iLangid, zText, -1, &pTC);
+ while( rc==SQLITE_OK ){
+ char const *zToken; /* Buffer containing token */
+ int nToken = 0; /* Number of bytes in token */
+ int iDum1 = 0, iDum2 = 0; /* Dummy variables */
+ int iPos = 0; /* Position of token in zText */
+
+ rc = pModule->xNext(pTC, &zToken, &nToken, &iDum1, &iDum2, &iPos);
+ for(pDef=pCsr->pDeferred; pDef && rc==SQLITE_OK; pDef=pDef->pNext){
+ Fts3PhraseToken *pPT = pDef->pToken;
+ if( (pDef->iCol>=p->nColumn || pDef->iCol==i)
+ && (pPT->bFirst==0 || iPos==0)
+ && (pPT->n==nToken || (pPT->isPrefix && pPT->n<nToken))
+ && (0==memcmp(zToken, pPT->z, pPT->n))
+ ){
+ fts3PendingListAppend(&pDef->pList, iDocid, i, iPos, &rc);
+ }
}
}
+ if( pTC ) pModule->xClose(pTC);
+ if( rc==SQLITE_DONE ) rc = SQLITE_OK;
}
- if( pTC ) pModule->xClose(pTC);
- if( rc==SQLITE_DONE ) rc = SQLITE_OK;
}
-
+
for(pDef=pCsr->pDeferred; pDef && rc==SQLITE_OK; pDef=pDef->pNext){
if( pDef->pList ){
rc = fts3PendingListAppendVarint(&pDef->pList, 0);
@@ -133982,6 +134860,9 @@ SQLITE_PRIVATE int sqlite3Fts3UpdateMethod(
aSzIns = &aSzDel[p->nColumn+1];
memset(aSzDel, 0, sizeof(aSzDel[0])*(p->nColumn+1)*2);
+ rc = fts3Writelock(p);
+ if( rc!=SQLITE_OK ) goto update_out;
+
/* If this is an INSERT operation, or an UPDATE that modifies the rowid
** value, then this operation requires constraint handling.
**
@@ -134601,6 +135482,7 @@ static int fts3StringAppend(
pStr->z = zNew;
pStr->nAlloc = nAlloc;
}
+ assert( pStr->z!=0 && (pStr->nAlloc >= pStr->n+nAppend+1) );
/* Append the data to the string buffer. */
memcpy(&pStr->z[pStr->n], zAppend, nAppend);
@@ -136115,28 +136997,27 @@ SQLITE_PRIVATE int sqlite3FtsUnicodeIsalnum(int c){
0x02A97004, 0x02A9DC03, 0x02A9EC01, 0x02AAC001, 0x02AAC803,
0x02AADC02, 0x02AAF802, 0x02AB0401, 0x02AB7802, 0x02ABAC07,
0x02ABD402, 0x02AF8C0B, 0x03600001, 0x036DFC02, 0x036FFC02,
- 0x037FFC02, 0x03E3FC01, 0x03EC7801, 0x03ECA401, 0x03EEC810,
- 0x03F4F802, 0x03F7F002, 0x03F8001A, 0x03F88007, 0x03F8C023,
- 0x03F95013, 0x03F9A004, 0x03FBFC01, 0x03FC040F, 0x03FC6807,
- 0x03FCEC06, 0x03FD6C0B, 0x03FF8007, 0x03FFA007, 0x03FFE405,
- 0x04040003, 0x0404DC09, 0x0405E411, 0x0406400C, 0x0407402E,
- 0x040E7C01, 0x040F4001, 0x04215C01, 0x04247C01, 0x0424FC01,
- 0x04280403, 0x04281402, 0x04283004, 0x0428E003, 0x0428FC01,
- 0x04294009, 0x0429FC01, 0x042CE407, 0x04400003, 0x0440E016,
- 0x04420003, 0x0442C012, 0x04440003, 0x04449C0E, 0x04450004,
- 0x04460003, 0x0446CC0E, 0x04471404, 0x045AAC0D, 0x0491C004,
- 0x05BD442E, 0x05BE3C04, 0x074000F6, 0x07440027, 0x0744A4B5,
- 0x07480046, 0x074C0057, 0x075B0401, 0x075B6C01, 0x075BEC01,
- 0x075C5401, 0x075CD401, 0x075D3C01, 0x075DBC01, 0x075E2401,
- 0x075EA401, 0x075F0C01, 0x07BBC002, 0x07C0002C, 0x07C0C064,
- 0x07C2800F, 0x07C2C40E, 0x07C3040F, 0x07C3440F, 0x07C4401F,
- 0x07C4C03C, 0x07C5C02B, 0x07C7981D, 0x07C8402B, 0x07C90009,
- 0x07C94002, 0x07CC0021, 0x07CCC006, 0x07CCDC46, 0x07CE0014,
- 0x07CE8025, 0x07CF1805, 0x07CF8011, 0x07D0003F, 0x07D10001,
- 0x07D108B6, 0x07D3E404, 0x07D4003E, 0x07D50004, 0x07D54018,
- 0x07D7EC46, 0x07D9140B, 0x07DA0046, 0x07DC0074, 0x38000401,
- 0x38008060, 0x380400F0, 0x3C000001, 0x3FFFF401, 0x40000001,
- 0x43FFF401,
+ 0x037FFC01, 0x03EC7801, 0x03ECA401, 0x03EEC810, 0x03F4F802,
+ 0x03F7F002, 0x03F8001A, 0x03F88007, 0x03F8C023, 0x03F95013,
+ 0x03F9A004, 0x03FBFC01, 0x03FC040F, 0x03FC6807, 0x03FCEC06,
+ 0x03FD6C0B, 0x03FF8007, 0x03FFA007, 0x03FFE405, 0x04040003,
+ 0x0404DC09, 0x0405E411, 0x0406400C, 0x0407402E, 0x040E7C01,
+ 0x040F4001, 0x04215C01, 0x04247C01, 0x0424FC01, 0x04280403,
+ 0x04281402, 0x04283004, 0x0428E003, 0x0428FC01, 0x04294009,
+ 0x0429FC01, 0x042CE407, 0x04400003, 0x0440E016, 0x04420003,
+ 0x0442C012, 0x04440003, 0x04449C0E, 0x04450004, 0x04460003,
+ 0x0446CC0E, 0x04471404, 0x045AAC0D, 0x0491C004, 0x05BD442E,
+ 0x05BE3C04, 0x074000F6, 0x07440027, 0x0744A4B5, 0x07480046,
+ 0x074C0057, 0x075B0401, 0x075B6C01, 0x075BEC01, 0x075C5401,
+ 0x075CD401, 0x075D3C01, 0x075DBC01, 0x075E2401, 0x075EA401,
+ 0x075F0C01, 0x07BBC002, 0x07C0002C, 0x07C0C064, 0x07C2800F,
+ 0x07C2C40E, 0x07C3040F, 0x07C3440F, 0x07C4401F, 0x07C4C03C,
+ 0x07C5C02B, 0x07C7981D, 0x07C8402B, 0x07C90009, 0x07C94002,
+ 0x07CC0021, 0x07CCC006, 0x07CCDC46, 0x07CE0014, 0x07CE8025,
+ 0x07CF1805, 0x07CF8011, 0x07D0003F, 0x07D10001, 0x07D108B6,
+ 0x07D3E404, 0x07D4003E, 0x07D50004, 0x07D54018, 0x07D7EC46,
+ 0x07D9140B, 0x07DA0046, 0x07DC0074, 0x38000401, 0x38008060,
+ 0x380400F0,
};
static const unsigned int aAscii[4] = {
0xFFFFFFFF, 0xFC00FFFF, 0xF8000001, 0xF8000001,
@@ -139731,7 +140612,10 @@ SQLITE_API int sqlite3_rtree_geometry_callback(
}
#if !SQLITE_CORE
-SQLITE_API int sqlite3_extension_init(
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+SQLITE_API int sqlite3_rtree_init(
sqlite3 *db,
char **pzErrMsg,
const sqlite3_api_routines *pApi
@@ -139769,7 +140653,7 @@ SQLITE_API int sqlite3_extension_init(
** * Implementations of the SQL scalar upper() and lower() functions
** for case mapping.
**
-** * Integration of ICU and SQLite collation seqences.
+** * Integration of ICU and SQLite collation sequences.
**
** * An implementation of the LIKE operator that uses ICU to
** provide case-independent matching.
@@ -140233,7 +141117,10 @@ SQLITE_PRIVATE int sqlite3IcuInit(sqlite3 *db){
}
#if !SQLITE_CORE
-SQLITE_API int sqlite3_extension_init(
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+SQLITE_API int sqlite3_icu_init(
sqlite3 *db,
char **pzErrMsg,
const sqlite3_api_routines *pApi
diff --git a/libgda/sqlite/sqlite-src/sqlite3.h b/libgda/sqlite/sqlite-src/sqlite3.h
index e398838..70cfd5f 100644
--- a/libgda/sqlite/sqlite-src/sqlite3.h
+++ b/libgda/sqlite/sqlite-src/sqlite3.h
@@ -107,9 +107,9 @@ extern "C" {
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
-#define SQLITE_VERSION "3.7.17"
-#define SQLITE_VERSION_NUMBER 3007017
-#define SQLITE_SOURCE_ID "2013-05-20 00:56:22 118a3b35693b134d56ebd780123b7fd6f1497668"
+#define SQLITE_VERSION "3.8.0.2"
+#define SQLITE_VERSION_NUMBER 3008000
+#define SQLITE_SOURCE_ID "2013-09-03 17:11:13 7dd4968f235d6e1ca9547cda9cf3bd570e1609ef"
/*
** CAPI3REF: Run-Time Library Version Numbers
@@ -478,8 +478,10 @@ SQLITE_API int sqlite3_exec(
#define SQLITE_IOERR_SEEK (SQLITE_IOERR | (22<<8))
#define SQLITE_IOERR_DELETE_NOENT (SQLITE_IOERR | (23<<8))
#define SQLITE_IOERR_MMAP (SQLITE_IOERR | (24<<8))
+#define SQLITE_IOERR_GETTEMPPATH (SQLITE_IOERR | (25<<8))
#define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8))
#define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8))
+#define SQLITE_BUSY_SNAPSHOT (SQLITE_BUSY | (2<<8))
#define SQLITE_CANTOPEN_NOTEMPDIR (SQLITE_CANTOPEN | (1<<8))
#define SQLITE_CANTOPEN_ISDIR (SQLITE_CANTOPEN | (2<<8))
#define SQLITE_CANTOPEN_FULLPATH (SQLITE_CANTOPEN | (3<<8))
@@ -499,6 +501,7 @@ SQLITE_API int sqlite3_exec(
#define SQLITE_CONSTRAINT_VTAB (SQLITE_CONSTRAINT | (9<<8))
#define SQLITE_NOTICE_RECOVER_WAL (SQLITE_NOTICE | (1<<8))
#define SQLITE_NOTICE_RECOVER_ROLLBACK (SQLITE_NOTICE | (2<<8))
+#define SQLITE_WARNING_AUTOINDEX (SQLITE_WARNING | (1<<8))
/*
** CAPI3REF: Flags For File Open Operations
@@ -2557,9 +2560,10 @@ SQLITE_API SQLITE_EXPERIMENTAL void *sqlite3_profile(sqlite3*,
** interface is to keep a GUI updated during a large query.
**
** ^The parameter P is passed through as the only parameter to the
-** callback function X. ^The parameter N is the number of
+** callback function X. ^The parameter N is the approximate number of
** [virtual machine instructions] that are evaluated between successive
-** invocations of the callback X.
+** invocations of the callback X. ^If N is less than one then the progress
+** handler is disabled.
**
** ^Only a single progress handler may be defined at one time per
** [database connection]; setting a new progress handler cancels the
@@ -4179,41 +4183,49 @@ SQLITE_API sqlite3 *sqlite3_context_db_handle(sqlite3_context*);
/*
** CAPI3REF: Function Auxiliary Data
**
-** The following two functions may be used by scalar SQL functions to
+** These functions may be used by (non-aggregate) SQL functions to
** associate metadata with argument values. If the same value is passed to
** multiple invocations of the same SQL function during query execution, under
-** some circumstances the associated metadata may be preserved. This may
-** be used, for example, to add a regular-expression matching scalar
-** function. The compiled version of the regular expression is stored as
-** metadata associated with the SQL value passed as the regular expression
-** pattern. The compiled regular expression can be reused on multiple
-** invocations of the same function so that the original pattern string
-** does not need to be recompiled on each invocation.
+** some circumstances the associated metadata may be preserved. An example
+** of where this might be useful is in a regular-expression matching
+** function. The compiled version of the regular expression can be stored as
+** metadata associated with the pattern string.
+** Then as long as the pattern string remains the same,
+** the compiled regular expression can be reused on multiple
+** invocations of the same function.
**
** ^The sqlite3_get_auxdata() interface returns a pointer to the metadata
** associated by the sqlite3_set_auxdata() function with the Nth argument
-** value to the application-defined function. ^If no metadata has been ever
-** been set for the Nth argument of the function, or if the corresponding
-** function parameter has changed since the meta-data was set,
-** then sqlite3_get_auxdata() returns a NULL pointer.
-**
-** ^The sqlite3_set_auxdata() interface saves the metadata
-** pointed to by its 3rd parameter as the metadata for the N-th
-** argument of the application-defined function. Subsequent
-** calls to sqlite3_get_auxdata() might return this data, if it has
-** not been destroyed.
-** ^If it is not NULL, SQLite will invoke the destructor
-** function given by the 4th parameter to sqlite3_set_auxdata() on
-** the metadata when the corresponding function parameter changes
-** or when the SQL statement completes, whichever comes first.
-**
-** SQLite is free to call the destructor and drop metadata on any
-** parameter of any function at any time. ^The only guarantee is that
-** the destructor will be called before the metadata is dropped.
+** value to the application-defined function. ^If there is no metadata
+** associated with the function argument, this sqlite3_get_auxdata() interface
+** returns a NULL pointer.
+**
+** ^The sqlite3_set_auxdata(C,N,P,X) interface saves P as metadata for the N-th
+** argument of the application-defined function. ^Subsequent
+** calls to sqlite3_get_auxdata(C,N) return P from the most recent
+** sqlite3_set_auxdata(C,N,P,X) call if the metadata is still valid or
+** NULL if the metadata has been discarded.
+** ^After each call to sqlite3_set_auxdata(C,N,P,X) where X is not NULL,
+** SQLite will invoke the destructor function X with parameter P exactly
+** once, when the metadata is discarded.
+** SQLite is free to discard the metadata at any time, including: <ul>
+** <li> when the corresponding function parameter changes, or
+** <li> when [sqlite3_reset()] or [sqlite3_finalize()] is called for the
+** SQL statement, or
+** <li> when sqlite3_set_auxdata() is invoked again on the same parameter, or
+** <li> during the original sqlite3_set_auxdata() call when a memory
+** allocation error occurs. </ul>)^
+**
+** Note the last bullet in particular. The destructor X in
+** sqlite3_set_auxdata(C,N,P,X) might be called immediately, before the
+** sqlite3_set_auxdata() interface even returns. Hence sqlite3_set_auxdata()
+** should be called near the end of the function implementation and the
+** function implementation should not make any use of P after
+** sqlite3_set_auxdata() has been called.
**
** ^(In practice, metadata is preserved between function calls for
-** expressions that are constant at compile time. This includes literal
-** values and [parameters].)^
+** function parameters that are compile-time constants, including literal
+** values and [parameters] and expressions composed from the same.)^
**
** These routines must be called from the same thread in which
** the SQL function is running.
@@ -4518,6 +4530,11 @@ SQLITE_API int sqlite3_key(
sqlite3 *db, /* Database to be rekeyed */
const void *pKey, int nKey /* The key */
);
+SQLITE_API int sqlite3_key_v2(
+ sqlite3 *db, /* Database to be rekeyed */
+ const char *zDbName, /* Name of the database */
+ const void *pKey, int nKey /* The key */
+);
/*
** Change the key on an open database. If the current database is not
@@ -4531,6 +4548,11 @@ SQLITE_API int sqlite3_rekey(
sqlite3 *db, /* Database to be rekeyed */
const void *pKey, int nKey /* The new key */
);
+SQLITE_API int sqlite3_rekey_v2(
+ sqlite3 *db, /* Database to be rekeyed */
+ const char *zDbName, /* Name of the database */
+ const void *pKey, int nKey /* The new key */
+);
/*
** Specify the activation key for a SEE database. Unless
@@ -5116,11 +5138,24 @@ SQLITE_API int sqlite3_enable_load_extension(sqlite3 *db, int onoff);
** on the list of automatic extensions is a harmless no-op. ^No entry point
** will be called more than once for each database connection that is opened.
**
-** See also: [sqlite3_reset_auto_extension()].
+** See also: [sqlite3_reset_auto_extension()]
+** and [sqlite3_cancel_auto_extension()]
*/
SQLITE_API int sqlite3_auto_extension(void (*xEntryPoint)(void));
/*
+** CAPI3REF: Cancel Automatic Extension Loading
+**
+** ^The [sqlite3_cancel_auto_extension(X)] interface unregisters the
+** initialization routine X that was registered using a prior call to
+** [sqlite3_auto_extension(X)]. ^The [sqlite3_cancel_auto_extension(X)]
+** routine returns 1 if initialization routine X was successfully
+** unregistered and it returns 0 if X was not on the list of initialization
+** routines.
+*/
+SQLITE_API int sqlite3_cancel_auto_extension(void (*xEntryPoint)(void));
+
+/*
** CAPI3REF: Reset Automatic Extension Loading
**
** ^This interface disables all automatic extensions previously
@@ -6232,6 +6267,12 @@ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int r
** on subsequent SQLITE_DBSTATUS_CACHE_WRITE requests is undefined.)^ ^The
** highwater mark associated with SQLITE_DBSTATUS_CACHE_WRITE is always 0.
** </dd>
+**
+** [[SQLITE_DBSTATUS_DEFERRED_FKS]] ^(<dt>SQLITE_DBSTATUS_DEFERRED_FKS</dt>
+** <dd>This parameter returns zero for the current value if and only if
+** all foreign key constraints (deferred or immediate) have been
+** resolved.)^ ^The highwater mark is always 0.
+** </dd>
** </dl>
*/
#define SQLITE_DBSTATUS_LOOKASIDE_USED 0
@@ -6244,7 +6285,8 @@ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int r
#define SQLITE_DBSTATUS_CACHE_HIT 7
#define SQLITE_DBSTATUS_CACHE_MISS 8
#define SQLITE_DBSTATUS_CACHE_WRITE 9
-#define SQLITE_DBSTATUS_MAX 9 /* Largest defined DBSTATUS */
+#define SQLITE_DBSTATUS_DEFERRED_FKS 10
+#define SQLITE_DBSTATUS_MAX 10 /* Largest defined DBSTATUS */
/*
@@ -6298,11 +6340,21 @@ SQLITE_API int sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg);
** A non-zero value in this counter may indicate an opportunity to
** improvement performance by adding permanent indices that do not
** need to be reinitialized each time the statement is run.</dd>
+**
+** [[SQLITE_STMTSTATUS_VM_STEP]] <dt>SQLITE_STMTSTATUS_VM_STEP</dt>
+** <dd>^This is the number of virtual machine operations executed
+** by the prepared statement if that number is less than or equal
+** to 2147483647. The number of virtual machine operations can be
+** used as a proxy for the total work done by the prepared statement.
+** If the number of virtual machine operations exceeds 2147483647
+** then the value returned by this statement status code is undefined.
+** </dd>
** </dl>
*/
#define SQLITE_STMTSTATUS_FULLSCAN_STEP 1
#define SQLITE_STMTSTATUS_SORT 2
#define SQLITE_STMTSTATUS_AUTOINDEX 3
+#define SQLITE_STMTSTATUS_VM_STEP 4
/*
** CAPI3REF: Custom Page Cache Object
@@ -7181,7 +7233,7 @@ SQLITE_API int sqlite3_vtab_on_conflict(sqlite3 *);
#ifdef __cplusplus
} /* End of the 'extern "C"' block */
#endif
-#endif
+#endif /* _SQLITE3_H_ */
/*
** 2010 August 30
diff --git a/providers/sqlcipher/sqlcipher.patch b/providers/sqlcipher/sqlcipher.patch
index fad792e..5f0f8d5 100644
--- a/providers/sqlcipher/sqlcipher.patch
+++ b/providers/sqlcipher/sqlcipher.patch
@@ -1,6 +1,6 @@
---- sqlite3.c.sqlite 2013-07-13 11:02:55.228615268 +0200
-+++ sqlite3.c 2013-07-13 11:02:46.604615238 +0200
-@@ -12585,9 +12585,45 @@
+--- sqlite3.c.sqlite 2013-11-09 12:42:08.623520057 +0100
++++ sqlite3.c 2013-11-09 12:41:58.695520274 +0100
+@@ -12566,9 +12566,45 @@
#endif /* _SQLITEINT_H_ */
/************** End of sqliteInt.h *******************************************/
@@ -48,7 +48,7 @@
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
-@@ -12597,3032 +12633,3229 @@
+@@ -12578,246 +12614,3589 @@
** May you share freely, never taking more than you give.
**
*************************************************************************
@@ -585,9 +585,6 @@
+** cursors have to go through this Btree to find their BtShared and
+** they often do so without holding sqlite3.mutex.
*/
--
--#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
--
+struct Btree {
+ sqlite3 *db; /* The database connection holding this btree */
+ BtShared *pBt; /* Sharable content of this btree */
@@ -602,109 +599,18 @@
+ BtLock lock; /* Object used to lock page 1 */
+#endif
+};
-
- /*
--** An array of names of all compile-time options. This array should
--** be sorted A-Z.
++
++/*
+** Btree.inTrans may take one of the following values.
- **
--** This array looks large, but in a typical installation actually uses
--** only a handful of compile-time options, so most times this array is usually
--** rather short and uses little memory space.
++**
+** If the shared-data extension is enabled, there may be multiple users
+** of the Btree structure. At most one of these may open a write transaction,
+** but any number may have active read transactions.
- */
--static const char * const azCompileOpt[] = {
--
--/* These macros are provided to "stringify" the value of the define
--** for those options in which the value is meaningful. */
--#define CTIMEOPT_VAL_(opt) #opt
--#define CTIMEOPT_VAL(opt) CTIMEOPT_VAL_(opt)
++*/
+#define TRANS_NONE 0
+#define TRANS_READ 1
+#define TRANS_WRITE 2
-
--#ifdef SQLITE_32BIT_ROWID
-- "32BIT_ROWID",
--#endif
--#ifdef SQLITE_4_BYTE_ALIGNED_MALLOC
-- "4_BYTE_ALIGNED_MALLOC",
--#endif
--#ifdef SQLITE_CASE_SENSITIVE_LIKE
-- "CASE_SENSITIVE_LIKE",
--#endif
--#ifdef SQLITE_CHECK_PAGES
-- "CHECK_PAGES",
--#endif
--#ifdef SQLITE_COVERAGE_TEST
-- "COVERAGE_TEST",
--#endif
--#ifdef SQLITE_DEBUG
-- "DEBUG",
--#endif
--#ifdef SQLITE_DEFAULT_LOCKING_MODE
-- "DEFAULT_LOCKING_MODE=" CTIMEOPT_VAL(SQLITE_DEFAULT_LOCKING_MODE),
--#endif
--#if defined(SQLITE_DEFAULT_MMAP_SIZE) && !defined(SQLITE_DEFAULT_MMAP_SIZE_xc)
-- "DEFAULT_MMAP_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_MMAP_SIZE),
--#endif
--#ifdef SQLITE_DISABLE_DIRSYNC
-- "DISABLE_DIRSYNC",
--#endif
--#ifdef SQLITE_DISABLE_LFS
-- "DISABLE_LFS",
--#endif
--#ifdef SQLITE_ENABLE_ATOMIC_WRITE
-- "ENABLE_ATOMIC_WRITE",
--#endif
--#ifdef SQLITE_ENABLE_CEROD
-- "ENABLE_CEROD",
--#endif
--#ifdef SQLITE_ENABLE_COLUMN_METADATA
-- "ENABLE_COLUMN_METADATA",
--#endif
--#ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT
-- "ENABLE_EXPENSIVE_ASSERT",
--#endif
--#ifdef SQLITE_ENABLE_FTS1
-- "ENABLE_FTS1",
--#endif
--#ifdef SQLITE_ENABLE_FTS2
-- "ENABLE_FTS2",
--#endif
--#ifdef SQLITE_ENABLE_FTS3
-- "ENABLE_FTS3",
--#endif
--#ifdef SQLITE_ENABLE_FTS3_PARENTHESIS
-- "ENABLE_FTS3_PARENTHESIS",
--#endif
--#ifdef SQLITE_ENABLE_FTS4
-- "ENABLE_FTS4",
--#endif
--#ifdef SQLITE_ENABLE_ICU
-- "ENABLE_ICU",
--#endif
--#ifdef SQLITE_ENABLE_IOTRACE
-- "ENABLE_IOTRACE",
--#endif
--#ifdef SQLITE_ENABLE_LOAD_EXTENSION
-- "ENABLE_LOAD_EXTENSION",
--#endif
--#ifdef SQLITE_ENABLE_LOCKING_STYLE
-- "ENABLE_LOCKING_STYLE=" CTIMEOPT_VAL(SQLITE_ENABLE_LOCKING_STYLE),
--#endif
--#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
-- "ENABLE_MEMORY_MANAGEMENT",
--#endif
--#ifdef SQLITE_ENABLE_MEMSYS3
-- "ENABLE_MEMSYS3",
--#endif
--#ifdef SQLITE_ENABLE_MEMSYS5
-- "ENABLE_MEMSYS5",
--#endif
--#ifdef SQLITE_ENABLE_OVERSIZE_CELL_CHECK
-- "ENABLE_OVERSIZE_CELL_CHECK",
++
+/*
+** An instance of this object represents a single database file.
+**
@@ -750,9 +656,7 @@
+ u8 autoVacuum; /* True if auto-vacuum is enabled */
+ u8 incrVacuum; /* True if incr-vacuum is enabled */
+ u8 bDoTruncate; /* True to truncate db on commit */
- #endif
--#ifdef SQLITE_ENABLE_RTREE
-- "ENABLE_RTREE",
++#endif
+ u8 inTransaction; /* Transaction state */
+ u8 max1bytePayload; /* Maximum first byte of cell for a 1-byte payload */
+ u16 btsFlags; /* Boolean parameters. See BTS_* macros below */
@@ -773,9 +677,7 @@
+ BtShared *pNext; /* Next on a list of sharable BtShared structs */
+ BtLock *pLock; /* List of locks held on this shared-btree struct */
+ Btree *pWriter; /* Btree with currently open write transaction */
- #endif
--#ifdef SQLITE_ENABLE_STAT3
-- "ENABLE_STAT3",
++#endif
+ u8 *pTmpSpace; /* BtShared.pageSize bytes of space for tmp use */
+};
+
@@ -839,9 +741,7 @@
+ struct KeyInfo *pKeyInfo; /* Argument passed to comparison function */
+#ifndef SQLITE_OMIT_INCRBLOB
+ Pgno *aOverflow; /* Cache of overflow page locations */
- #endif
--#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
-- "ENABLE_UNLOCK_NOTIFY",
++#endif
+ Pgno pgnoRoot; /* The root page of this tree */
+ sqlite3_int64 cachedRowid; /* Next rowid cache. 0 means not valid */
+ CellInfo info; /* A parse of the cell we are pointing at */
@@ -854,9 +754,7 @@
+ u8 eState; /* One of the CURSOR_XXX constants (see below) */
+#ifndef SQLITE_OMIT_INCRBLOB
+ u8 isIncrblobHandle; /* True if this cursor is an incr. io handle */
- #endif
--#ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT
-- "ENABLE_UPDATE_DELETE_LIMIT",
++#endif
+ u8 hints; /* As configured by CursorSetHints() */
+ i16 iPage; /* Index of current page in apPage */
+ u16 aiIdx[BTCURSOR_MAX_DEPTH]; /* Current index in apPage[i] */
@@ -866,14 +764,19 @@
+/*
+** Potential values for BtCursor.eState.
+**
-+** CURSOR_VALID:
-+** Cursor points to a valid entry. getPayload() etc. may be called.
-+**
+** CURSOR_INVALID:
+** Cursor does not point to a valid entry. This can happen (for example)
+** because the table is empty or because BtreeCursorFirst() has not been
+** called.
+**
++** CURSOR_VALID:
++** Cursor points to a valid entry. getPayload() etc. may be called.
++**
++** CURSOR_SKIPNEXT:
++** Cursor is valid except that the Cursor.skipNext field is non-zero
++** indicating that the next sqlite3BtreeNext() or sqlite3BtreePrevious()
++** operation should be a no-op.
++**
+** CURSOR_REQUIRESEEK:
+** The table that this cursor was opened on still exists, but has been
+** modified since the cursor was last used. The cursor position is saved
@@ -890,8 +793,9 @@
+*/
+#define CURSOR_INVALID 0
+#define CURSOR_VALID 1
-+#define CURSOR_REQUIRESEEK 2
-+#define CURSOR_FAULT 3
++#define CURSOR_SKIPNEXT 2
++#define CURSOR_REQUIRESEEK 3
++#define CURSOR_FAULT 4
+
+/*
+** The database page the PENDING_BYTE occupies. This page is never used.
@@ -973,7 +877,7 @@
+#define ISAUTOVACUUM (pBt->autoVacuum)
+#else
+#define ISAUTOVACUUM 0
- #endif
++#endif
+
+
+/*
@@ -1043,26 +947,7 @@
+**
+*/
+/* BEGIN SQLCIPHER */
- #ifdef SQLITE_HAS_CODEC
-- "HAS_CODEC",
--#endif
--#ifdef SQLITE_HAVE_ISNAN
-- "HAVE_ISNAN",
--#endif
--#ifdef SQLITE_HOMEGROWN_RECURSIVE_MUTEX
-- "HOMEGROWN_RECURSIVE_MUTEX",
--#endif
--#ifdef SQLITE_IGNORE_AFP_LOCK_ERRORS
-- "IGNORE_AFP_LOCK_ERRORS",
--#endif
--#ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS
-- "IGNORE_FLOCK_LOCK_ERRORS",
--#endif
--#ifdef SQLITE_INT64_TYPE
-- "INT64_TYPE",
--#endif
--#ifdef SQLITE_LOCK_TRACE
-- "LOCK_TRACE",
++#ifdef SQLITE_HAS_CODEC
+#ifndef CRYPTO_H
+#define CRYPTO_H
+
@@ -1070,23 +955,17 @@
+ && !defined (SQLCIPHER_CRYPTO_LIBTOMCRYPT) \
+ && !defined (SQLCIPHER_CRYPTO_OPENSSL)
+#define SQLCIPHER_CRYPTO_OPENSSL
- #endif
--#if defined(SQLITE_MAX_MMAP_SIZE) && !defined(SQLITE_MAX_MMAP_SIZE_xc)
-- "MAX_MMAP_SIZE=" CTIMEOPT_VAL(SQLITE_MAX_MMAP_SIZE),
++#endif
+
+#define FILE_HEADER_SZ 16
+
+#ifndef CIPHER_VERSION
-+#define CIPHER_VERSION "2.2.1"
- #endif
--#ifdef SQLITE_MAX_SCHEMA_RETRY
-- "MAX_SCHEMA_RETRY=" CTIMEOPT_VAL(SQLITE_MAX_SCHEMA_RETRY),
++#define CIPHER_VERSION "3.0.0"
++#endif
+
+#ifndef CIPHER
+#define CIPHER "aes-256-cbc"
- #endif
--#ifdef SQLITE_MEMDEBUG
-- "MEMDEBUG",
++#endif
+
+#define CIPHER_DECRYPT 0
+#define CIPHER_ENCRYPT 1
@@ -1096,10 +975,8 @@
+#define CIPHER_READWRITE_CTX 2
+
+#ifndef PBKDF2_ITER
-+#define PBKDF2_ITER 4000
- #endif
--#ifdef SQLITE_MIXED_ENDIAN_64BIT_FLOAT
-- "MIXED_ENDIAN_64BIT_FLOAT",
++#define PBKDF2_ITER 64000
++#endif
+
+/* possible flags for cipher_ctx->flags */
+#define CIPHER_FLAG_HMAC 0x01
@@ -1108,9 +985,7 @@
+
+#ifndef DEFAULT_CIPHER_FLAGS
+#define DEFAULT_CIPHER_FLAGS CIPHER_FLAG_HMAC | CIPHER_FLAG_LE_PGNO
- #endif
--#ifdef SQLITE_NO_SYNC
-- "NO_SYNC",
++#endif
+
+
+/* by default, sqlcipher will use a reduced number of iterations to generate
@@ -1118,9 +993,7 @@
+ */
+#ifndef FAST_PBKDF2_ITER
+#define FAST_PBKDF2_ITER 2
- #endif
--#ifdef SQLITE_OMIT_ALTERTABLE
-- "OMIT_ALTERTABLE",
++#endif
+
+/* this if a fixed random array that will be xor'd with the database salt to ensure that the
+ salt passed to the HMAC key derivation function is not the same as that used to derive
@@ -1129,30 +1002,22 @@
+ will likely allow this to be defined at runtime via pragma */
+#ifndef HMAC_SALT_MASK
+#define HMAC_SALT_MASK 0x3a
- #endif
--#ifdef SQLITE_OMIT_ANALYZE
-- "OMIT_ANALYZE",
++#endif
+
+#ifndef CIPHER_MAX_IV_SZ
+#define CIPHER_MAX_IV_SZ 16
- #endif
--#ifdef SQLITE_OMIT_ATTACH
-- "OMIT_ATTACH",
++#endif
+
+#ifndef CIPHER_MAX_KEY_SZ
+#define CIPHER_MAX_KEY_SZ 64
- #endif
--#ifdef SQLITE_OMIT_AUTHORIZATION
-- "OMIT_AUTHORIZATION",
++#endif
+
+
+#ifdef CODEC_DEBUG
+#define CODEC_TRACE(X) {printf X;fflush(stdout);}
+#else
+#define CODEC_TRACE(X)
- #endif
--#ifdef SQLITE_OMIT_AUTOINCREMENT
-- "OMIT_AUTOINCREMENT",
++#endif
+
+#ifdef CODEC_DEBUG_PAGEDATA
+#define CODEC_HEXDUMP(DESC,BUFFER,LEN) \
@@ -1168,9 +1033,7 @@
+ }
+#else
+#define CODEC_HEXDUMP(DESC,BUFFER,LEN)
- #endif
--#ifdef SQLITE_OMIT_AUTOINIT
-- "OMIT_AUTOINIT",
++#endif
+
+/* extensions defined in pager.c */
+SQLITE_PRIVATE void sqlite3pager_get_codec(Pager *pPager, void **ctx);
@@ -1195,13 +1058,20 @@
+ (c>='a' && c<='f') ? (c)-'a'+10 : 0;
+}
+
-+static void cipher_hex2bin(const char *hex, int sz, unsigned char *out){
++static void cipher_hex2bin(const unsigned char *hex, int sz, unsigned char *out){
+ int i;
+ for(i = 0; i < sz; i += 2){
+ out[i/2] = (cipher_hex2int(hex[i])<<4) | cipher_hex2int(hex[i+1]);
+ }
+}
+
++static void cipher_bin2hex(const unsigned char* in, int sz, char *out) {
++ int i;
++ for(i=0; i < sz; i++) {
++ sqlite3_snprintf(3, out + (i*2), "%02x ", in[i]);
++ }
++}
++
+/* extensions defined in crypto_impl.c */
+typedef struct codec_ctx codec_ctx;
+
@@ -1220,12 +1090,15 @@
+void sqlcipher_codec_ctx_set_error(codec_ctx *, int);
+
+int sqlcipher_codec_ctx_set_pass(codec_ctx *, const void *, int, int);
-+void sqlcipher_codec_get_pass(codec_ctx *, void **zKey, int *nKey);
++void sqlcipher_codec_get_keyspec(codec_ctx *, void **zKey, int *nKey);
+
+int sqlcipher_codec_ctx_set_pagesize(codec_ctx *, int);
+int sqlcipher_codec_ctx_get_pagesize(codec_ctx *);
+int sqlcipher_codec_ctx_get_reservesize(codec_ctx *);
+
++void sqlcipher_set_default_kdf_iter(int iter);
++int sqlcipher_get_default_kdf_iter();
++
+int sqlcipher_codec_ctx_set_kdf_iter(codec_ctx *, int, int);
+int sqlcipher_codec_ctx_get_kdf_iter(codec_ctx *ctx, int);
+
@@ -1255,214 +1128,14 @@
+int sqlcipher_codec_ctx_get_flag(codec_ctx *ctx, unsigned int flag, int for_ctx);
+
+const char* sqlcipher_codec_get_cipher_provider(codec_ctx *ctx);
- #endif
--#ifdef SQLITE_OMIT_AUTOMATIC_INDEX
-- "OMIT_AUTOMATIC_INDEX",
- #endif
--#ifdef SQLITE_OMIT_AUTORESET
-- "OMIT_AUTORESET",
--#endif
--#ifdef SQLITE_OMIT_AUTOVACUUM
-- "OMIT_AUTOVACUUM",
--#endif
--#ifdef SQLITE_OMIT_BETWEEN_OPTIMIZATION
-- "OMIT_BETWEEN_OPTIMIZATION",
--#endif
--#ifdef SQLITE_OMIT_BLOB_LITERAL
-- "OMIT_BLOB_LITERAL",
--#endif
--#ifdef SQLITE_OMIT_BTREECOUNT
-- "OMIT_BTREECOUNT",
--#endif
--#ifdef SQLITE_OMIT_BUILTIN_TEST
-- "OMIT_BUILTIN_TEST",
--#endif
--#ifdef SQLITE_OMIT_CAST
-- "OMIT_CAST",
--#endif
--#ifdef SQLITE_OMIT_CHECK
-- "OMIT_CHECK",
--#endif
--#ifdef SQLITE_OMIT_COMPLETE
-- "OMIT_COMPLETE",
--#endif
--#ifdef SQLITE_OMIT_COMPOUND_SELECT
-- "OMIT_COMPOUND_SELECT",
--#endif
--#ifdef SQLITE_OMIT_DATETIME_FUNCS
-- "OMIT_DATETIME_FUNCS",
--#endif
--#ifdef SQLITE_OMIT_DECLTYPE
-- "OMIT_DECLTYPE",
--#endif
--#ifdef SQLITE_OMIT_DEPRECATED
-- "OMIT_DEPRECATED",
--#endif
--#ifdef SQLITE_OMIT_DISKIO
-- "OMIT_DISKIO",
--#endif
--#ifdef SQLITE_OMIT_EXPLAIN
-- "OMIT_EXPLAIN",
--#endif
--#ifdef SQLITE_OMIT_FLAG_PRAGMAS
-- "OMIT_FLAG_PRAGMAS",
--#endif
--#ifdef SQLITE_OMIT_FLOATING_POINT
-- "OMIT_FLOATING_POINT",
--#endif
--#ifdef SQLITE_OMIT_FOREIGN_KEY
-- "OMIT_FOREIGN_KEY",
--#endif
--#ifdef SQLITE_OMIT_GET_TABLE
-- "OMIT_GET_TABLE",
--#endif
--#ifdef SQLITE_OMIT_INCRBLOB
-- "OMIT_INCRBLOB",
--#endif
--#ifdef SQLITE_OMIT_INTEGRITY_CHECK
-- "OMIT_INTEGRITY_CHECK",
--#endif
--#ifdef SQLITE_OMIT_LIKE_OPTIMIZATION
-- "OMIT_LIKE_OPTIMIZATION",
--#endif
--#ifdef SQLITE_OMIT_LOAD_EXTENSION
-- "OMIT_LOAD_EXTENSION",
--#endif
--#ifdef SQLITE_OMIT_LOCALTIME
-- "OMIT_LOCALTIME",
--#endif
--#ifdef SQLITE_OMIT_LOOKASIDE
-- "OMIT_LOOKASIDE",
--#endif
--#ifdef SQLITE_OMIT_MEMORYDB
-- "OMIT_MEMORYDB",
--#endif
--#ifdef SQLITE_OMIT_OR_OPTIMIZATION
-- "OMIT_OR_OPTIMIZATION",
--#endif
--#ifdef SQLITE_OMIT_PAGER_PRAGMAS
-- "OMIT_PAGER_PRAGMAS",
--#endif
--#ifdef SQLITE_OMIT_PRAGMA
-- "OMIT_PRAGMA",
--#endif
--#ifdef SQLITE_OMIT_PROGRESS_CALLBACK
-- "OMIT_PROGRESS_CALLBACK",
--#endif
--#ifdef SQLITE_OMIT_QUICKBALANCE
-- "OMIT_QUICKBALANCE",
--#endif
--#ifdef SQLITE_OMIT_REINDEX
-- "OMIT_REINDEX",
--#endif
--#ifdef SQLITE_OMIT_SCHEMA_PRAGMAS
-- "OMIT_SCHEMA_PRAGMAS",
--#endif
--#ifdef SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS
-- "OMIT_SCHEMA_VERSION_PRAGMAS",
--#endif
--#ifdef SQLITE_OMIT_SHARED_CACHE
-- "OMIT_SHARED_CACHE",
--#endif
--#ifdef SQLITE_OMIT_SUBQUERY
-- "OMIT_SUBQUERY",
--#endif
--#ifdef SQLITE_OMIT_TCL_VARIABLE
-- "OMIT_TCL_VARIABLE",
--#endif
--#ifdef SQLITE_OMIT_TEMPDB
-- "OMIT_TEMPDB",
--#endif
--#ifdef SQLITE_OMIT_TRACE
-- "OMIT_TRACE",
--#endif
--#ifdef SQLITE_OMIT_TRIGGER
-- "OMIT_TRIGGER",
--#endif
--#ifdef SQLITE_OMIT_TRUNCATE_OPTIMIZATION
-- "OMIT_TRUNCATE_OPTIMIZATION",
--#endif
--#ifdef SQLITE_OMIT_UTF16
-- "OMIT_UTF16",
--#endif
--#ifdef SQLITE_OMIT_VACUUM
-- "OMIT_VACUUM",
--#endif
--#ifdef SQLITE_OMIT_VIEW
-- "OMIT_VIEW",
--#endif
--#ifdef SQLITE_OMIT_VIRTUALTABLE
-- "OMIT_VIRTUALTABLE",
--#endif
--#ifdef SQLITE_OMIT_WAL
-- "OMIT_WAL",
--#endif
--#ifdef SQLITE_OMIT_WSD
-- "OMIT_WSD",
--#endif
--#ifdef SQLITE_OMIT_XFER_OPT
-- "OMIT_XFER_OPT",
--#endif
--#ifdef SQLITE_PERFORMANCE_TRACE
-- "PERFORMANCE_TRACE",
--#endif
--#ifdef SQLITE_PROXY_DEBUG
-- "PROXY_DEBUG",
--#endif
--#ifdef SQLITE_RTREE_INT_ONLY
-- "RTREE_INT_ONLY",
--#endif
--#ifdef SQLITE_SECURE_DELETE
-- "SECURE_DELETE",
--#endif
--#ifdef SQLITE_SMALL_STACK
-- "SMALL_STACK",
--#endif
--#ifdef SQLITE_SOUNDEX
-- "SOUNDEX",
--#endif
--#ifdef SQLITE_TCL
-- "TCL",
--#endif
--#if defined(SQLITE_TEMP_STORE) && !defined(SQLITE_TEMP_STORE_xc)
-- "TEMP_STORE=" CTIMEOPT_VAL(SQLITE_TEMP_STORE),
--#endif
--#ifdef SQLITE_TEST
-- "TEST",
--#endif
--#if defined(SQLITE_THREADSAFE)
-- "THREADSAFE=" CTIMEOPT_VAL(SQLITE_THREADSAFE),
--#endif
--#ifdef SQLITE_USE_ALLOCA
-- "USE_ALLOCA",
--#endif
--#ifdef SQLITE_ZERO_MALLOC
-- "ZERO_MALLOC"
--#endif
--};
++int sqlcipher_codec_ctx_migrate(codec_ctx *ctx);
++#endif
++#endif
+/* END SQLCIPHER */
-
--/*
--** Given the name of a compile-time option, return true if that option
--** was used and false if not.
--**
--** The name can optionally begin with "SQLITE_" but the "SQLITE_" prefix
--** is not required for a match.
--*/
--SQLITE_API int sqlite3_compileoption_used(const char *zOptName){
-- int i, n;
-- if( sqlite3StrNICmp(zOptName, "SQLITE_", 7)==0 ) zOptName += 7;
-- n = sqlite3Strlen30(zOptName);
++
+/************** End of crypto.h **********************************************/
+/************** Continuing where we left off in crypto.c *********************/
-
-- /* Since ArraySize(azCompileOpt) is normally in single digits, a
-- ** linear search is adequate. No need for a binary search. */
-- for(i=0; i<ArraySize(azCompileOpt); i++){
-- if( sqlite3StrNICmp(zOptName, azCompileOpt[i], n)==0
-- && sqlite3CtypeMap[(unsigned char)azCompileOpt[i][n]]==0
-- ){
-- return 1;
++
+static const char* codec_get_cipher_version() {
+ return CIPHER_VERSION;
+}
@@ -1505,7 +1178,7 @@
+ return SQLITE_ERROR;
+}
+
-+int codec_pragma(sqlite3* db, int iDb, Parse *pParse, const char *zLeft, const char *zRight) {
++int sqlcipher_codec_pragma(sqlite3* db, int iDb, Parse *pParse, const char *zLeft, const char *zRight) {
+ struct Db *pDb = &db->aDb[iDb];
+ codec_ctx *ctx = NULL;
+ int rc;
@@ -1514,8 +1187,15 @@
+ sqlite3pager_get_codec(pDb->pBt->pBt->pPager, (void **) &ctx);
+ }
+
-+ CODEC_TRACE(("codec_pragma: entered db=%p iDb=%d pParse=%p zLeft=%s zRight=%s ctx=%p\n", db, iDb, pParse,
zLeft, zRight, ctx));
-+
++ CODEC_TRACE(("sqlcipher_codec_pragma: entered db=%p iDb=%d pParse=%p zLeft=%s zRight=%s ctx=%p\n", db,
iDb, pParse, zLeft, zRight, ctx));
++
++ if( sqlite3StrICmp(zLeft, "cipher_migrate")==0 && !zRight ){
++ if(ctx){
++ char *migrate_status = sqlite3_mprintf("%d", sqlcipher_codec_ctx_migrate(ctx));
++ codec_vdbe_return_static_string(pParse, "cipher_migrate", migrate_status);
++ sqlite3_free(migrate_status);
++ }
++ } else
+ if( sqlite3StrICmp(zLeft, "cipher_provider")==0 && !zRight ){
+ if(ctx) { codec_vdbe_return_static_string(pParse, "cipher_provider",
+ sqlcipher_codec_get_cipher_provider(ctx));
@@ -1537,6 +1217,15 @@
+ if( sqlite3StrICmp(zLeft, "rekey_cipher")==0 && zRight ){
+ if(ctx) sqlcipher_codec_ctx_set_cipher(ctx, zRight, 1); // change write cipher only
+ }else
++ if( sqlite3StrICmp(zLeft,"cipher_default_kdf_iter")==0 ){
++ if( zRight ) {
++ sqlcipher_set_default_kdf_iter(atoi(zRight)); // change default KDF iterations
++ } else {
++ char *kdf_iter = sqlite3_mprintf("%d", sqlcipher_get_default_kdf_iter());
++ codec_vdbe_return_static_string(pParse, "cipher_default_kdf_iter", kdf_iter);
++ sqlite3_free(kdf_iter);
++ }
++ }else
+ if( sqlite3StrICmp(zLeft, "kdf_iter")==0 ){
+ if(ctx) {
+ if( zRight ) {
@@ -1631,7 +1320,7 @@
+ if(zRight) {
+ if (sqlite3StrNICmp(zRight ,"x'", 2) == 0 && sqlite3Strlen30(zRight) == 5) {
+ unsigned char mask = 0;
-+ const char *hex = zRight+2;
++ const unsigned char *hex = (const unsigned char *)zRight+2;
+ cipher_hex2bin(hex,2,&mask);
+ sqlcipher_set_hmac_salt_mask(mask);
+ }
@@ -1640,21 +1329,14 @@
+ codec_vdbe_return_static_string(pParse, "cipher_hmac_salt_mask", hmac_salt_mask);
+ sqlite3_free(hmac_salt_mask);
+ }
- }
++ }
+ }else {
+ return 0;
- }
-- return 0;
++ }
+ return 1;
- }
-
- /*
--** Return the N-th compile-time option string. If N is out of range,
--** return a NULL pointer.
--*/
--SQLITE_API const char *sqlite3_compileoption_get(int N){
-- if( N>=0 && N<ArraySize(azCompileOpt) ){
-- return azCompileOpt[N];
++}
++
++/*
+ * sqlite3Codec can be called in multiple modes.
+ * encrypt mode - expected to return a pointer to the
+ * encrypted data without altering pData.
@@ -1704,11 +1386,9 @@
+ default:
+ return pData;
+ break;
- }
-- return 0;
- }
-
--#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */
++ }
++}
++
+SQLITE_PRIVATE void sqlite3FreeCodecArg(void *pCodecArg) {
+ codec_ctx *ctx = (codec_ctx *) pCodecArg;
+ if(pCodecArg == NULL) return;
@@ -1761,16 +1441,41 @@
+ /* do nothing, security enhancements are always active */
+}
+
++static int sqlcipher_find_db_index(sqlite3 *db, const char *zDb) {
++ int db_index;
++ if(zDb == NULL){
++ return 0;
++ }
++ for(db_index = 0; db_index < db->nDb; db_index++) {
++ struct Db *pDb = &db->aDb[db_index];
++ if(strcmp(pDb->zName, zDb) == 0) {
++ return db_index;
++ }
++ }
++ return 0;
++}
++
+SQLITE_API int sqlite3_key(sqlite3 *db, const void *pKey, int nKey) {
-+ CODEC_TRACE(("sqlite3_key: entered db=%p pKey=%s nKey=%d\n", db, (char *)pKey, nKey));
++ CODEC_TRACE(("sqlite3_key entered: db=%p pKey=%s nKey=%d\n", db, (char *)pKey, nKey));
++ return sqlite3_key_v2(db, "main", pKey, nKey);
++}
++
++SQLITE_API int sqlite3_key_v2(sqlite3 *db, const char *zDb, const void *pKey, int nKey) {
++ CODEC_TRACE(("sqlite3_key_v2: entered db=%p zDb=%s pKey=%s nKey=%d\n", db, zDb, (char *)pKey, nKey));
+ /* attach key if db and pKey are not null and nKey is > 0 */
+ if(db && pKey && nKey) {
-+ return sqlite3CodecAttach(db, 0, pKey, nKey); // operate only on the main db
++ int db_index = sqlcipher_find_db_index(db, zDb);
++ return sqlite3CodecAttach(db, db_index, pKey, nKey);
+ }
+ return SQLITE_ERROR;
+}
+
-+/* sqlite3_rekey
++SQLITE_API int sqlite3_rekey(sqlite3 *db, const void *pKey, int nKey) {
++ CODEC_TRACE(("sqlite3_rekey entered: db=%p pKey=%s nKey=%d\n", db, (char *)pKey, nKey));
++ return sqlite3_rekey_v2(db, "main", pKey, nKey);
++}
++
++/* sqlite3_rekey_v2
+** Given a database, this will reencrypt the database using a new key.
+** There is only one possible modes of operation - to encrypt a database
+** that is already encrpyted. If the database is not already encrypted
@@ -1780,11 +1485,12 @@
+** 2. If there is NOT already a key present do nothing
+** 3. If there is a key present, re-encrypt the database with the new key
+*/
-+SQLITE_API int sqlite3_rekey(sqlite3 *db, const void *pKey, int nKey) {
-+ CODEC_TRACE(("sqlite3_rekey: entered db=%p pKey=%s, nKey=%d\n", db, (char *)pKey, nKey));
++SQLITE_API int sqlite3_rekey_v2(sqlite3 *db, const char *zDb, const void *pKey, int nKey) {
++ CODEC_TRACE(("sqlite3_rekey_v2: entered db=%p zDb=%s pKey=%s, nKey=%d\n", db, zDb, (char *)pKey, nKey));
+ if(db && pKey && nKey) {
-+ struct Db *pDb = &db->aDb[0];
-+ CODEC_TRACE(("sqlite3_rekey: database pDb=%p\n", pDb));
++ int db_index = sqlcipher_find_db_index(db, zDb);
++ struct Db *pDb = &db->aDb[db_index];
++ CODEC_TRACE(("sqlite3_rekey_v2: database pDb=%p db_index:%d\n", pDb, db_index));
+ if(pDb->pBt) {
+ codec_ctx *ctx;
+ int rc, page_count;
@@ -1796,13 +1502,13 @@
+
+ if(ctx == NULL) {
+ /* there was no codec attached to this database, so this should do nothing! */
-+ CODEC_TRACE(("sqlite3_rekey: no codec attached to db, exiting\n"));
++ CODEC_TRACE(("sqlite3_rekey_v2: no codec attached to db, exiting\n"));
+ return SQLITE_OK;
+ }
+
+ sqlite3_mutex_enter(db->mutex);
+
-+ codec_set_pass_key(db, 0, pKey, nKey, CIPHER_WRITE_CTX);
++ codec_set_pass_key(db, db_index, pKey, nKey, CIPHER_WRITE_CTX);
+
+ /* do stuff here to rewrite the database
+ ** 1. Create a transaction on the database
@@ -1812,7 +1518,7 @@
+ */
+ rc = sqlite3BtreeBeginTrans(pDb->pBt, 1); /* begin write transaction */
+ sqlite3PagerPagecount(pPager, &page_count);
-+ for(pgno = 1; rc == SQLITE_OK && pgno <= page_count; pgno++) { /* pgno's start at 1 see
pager.c:pagerAcquire */
++ for(pgno = 1; rc == SQLITE_OK && pgno <= (unsigned int)page_count; pgno++) { /* pgno's start at 1 see
pager.c:pagerAcquire */
+ if(!sqlite3pager_is_mj_pgno(pPager, pgno)) { /* skip this page (see pager.c:pagerAcquire for
reasoning) */
+ rc = sqlite3PagerGet(pPager, pgno, &page);
+ if(rc == SQLITE_OK) { /* write page see pager_incr_changecounter for example */
@@ -1820,21 +1526,21 @@
+ if(rc == SQLITE_OK) {
+ sqlite3PagerUnref(page);
+ } else {
-+ CODEC_TRACE(("sqlite3_rekey: error %d occurred writing page %d\n", rc, pgno));
++ CODEC_TRACE(("sqlite3_rekey_v2: error %d occurred writing page %d\n", rc, pgno));
+ }
+ } else {
-+ CODEC_TRACE(("sqlite3_rekey: error %d occurred getting page %d\n", rc, pgno));
++ CODEC_TRACE(("sqlite3_rekey_v2: error %d occurred getting page %d\n", rc, pgno));
+ }
+ }
+ }
+
+ /* if commit was successful commit and copy the rekey data to current key, else rollback to release
locks */
+ if(rc == SQLITE_OK) {
-+ CODEC_TRACE(("sqlite3_rekey: committing\n"));
++ CODEC_TRACE(("sqlite3_rekey_v2: committing\n"));
+ rc = sqlite3BtreeCommit(pDb->pBt);
+ sqlcipher_codec_key_copy(ctx, CIPHER_WRITE_CTX);
+ } else {
-+ CODEC_TRACE(("sqlite3_rekey: rollback\n"));
++ CODEC_TRACE(("sqlite3_rekey_v2: rollback\n"));
+ sqlite3BtreeRollback(pDb->pBt, SQLITE_ABORT_ROLLBACK);
+ }
+
@@ -1848,13 +1554,11 @@
+SQLITE_PRIVATE void sqlite3CodecGetKey(sqlite3* db, int nDb, void **zKey, int *nKey) {
+ struct Db *pDb = &db->aDb[nDb];
+ CODEC_TRACE(("sqlite3CodecGetKey: entered db=%p, nDb=%d\n", db, nDb));
-+
+ if( pDb->pBt ) {
+ codec_ctx *ctx;
+ sqlite3pager_get_codec(pDb->pBt->pBt->pPager, (void **) &ctx);
-+
+ if(ctx) { /* if the codec has an attached codec_context user the raw key data */
-+ sqlcipher_codec_get_pass(ctx, zKey, nKey);
++ sqlcipher_codec_get_keyspec(ctx, zKey, nKey);
+ } else {
+ *zKey = NULL;
+ *nKey = 0;
@@ -1863,26 +1567,8 @@
+}
+
+#ifndef OMIT_EXPORT
-
--/************** End of ctime.c ***********************************************/
--/************** Begin file status.c ******************************************/
- /*
--** 2008 June 18
--**
--** The author disclaims copyright to this source code. In place of
--** a legal notice, here is a blessing:
--**
--** May you do good and not evil.
--** May you find forgiveness for yourself and forgive others.
--** May you share freely, never taking more than you give.
--**
--*************************************************************************
--**
--** This module implements the sqlite3_status() interface and related
--** functionality.
--*/
--/************** Include vdbeInt.h in the middle of status.c ******************/
--/************** Begin file vdbeInt.h *****************************************/
++
++/*
+ * Implementation of an "export" function that allows a caller
+ * to duplicate the main database to an attached database. This is intended
+ * as a conveneince for users who need to:
@@ -1896,29 +1582,12 @@
+ * named attached database.
+ */
+
- /*
--** 2003 September 6
--**
--** The author disclaims copyright to this source code. In place of
--** a legal notice, here is a blessing:
--**
--** May you do good and not evil.
--** May you find forgiveness for yourself and forgive others.
--** May you share freely, never taking more than you give.
--**
--*************************************************************************
--** This is the header file for information that is private to the
--** VDBE. This information used to all be at the top of the single
--** source code file "vdbe.c". When that file became too big (over
--** 6000 lines long) it was split up into several smaller files and
--** this header information was factored out.
++/*
+** Finalize a prepared statement. If there was an error, store the
+** text of the error message in *pzErrMsg. Return the result code.
+**
+** Based on vacuumFinalize from vacuum.c
- */
--#ifndef _VDBEINT_H_
--#define _VDBEINT_H_
++*/
+static int sqlcipher_finalize(sqlite3 *db, sqlite3_stmt *pStmt, char **pzErrMsg){
+ int rc;
+ rc = sqlite3VdbeFinalize((Vdbe*)pStmt);
@@ -1927,17 +1596,12 @@
+ }
+ return rc;
+}
-
- /*
--** The maximum number of times that a statement will try to reparse
--** itself before giving up and returning SQLITE_SCHEMA.
++
++/*
+** Execute zSql on database db. Return an error code.
+**
+** Based on execSql from vacuum.c
- */
--#ifndef SQLITE_MAX_SCHEMA_RETRY
--# define SQLITE_MAX_SCHEMA_RETRY 50
--#endif
++*/
+static int sqlcipher_execSql(sqlite3 *db, char **pzErrMsg, const char *zSql){
+ sqlite3_stmt *pStmt;
+ VVA_ONLY( int rc; )
@@ -1952,17 +1616,13 @@
+ assert( rc!=SQLITE_ROW );
+ return sqlcipher_finalize(db, pStmt, pzErrMsg);
+}
-
- /*
--** SQL is translated into a sequence of instructions to be
--** executed by a virtual machine. Each instruction is an instance
--** of the following structure.
++
++/*
+** Execute zSql on database db. The statement returns exactly
+** one column. Execute this as SQL on the same database.
+**
+** Based on execExecSql from vacuum.c
- */
--typedef struct VdbeOp Op;
++*/
+static int sqlcipher_execExecSql(sqlite3 *db, char **pzErrMsg, const char *zSql){
+ sqlite3_stmt *pStmt;
+ int rc;
@@ -1980,14 +1640,12 @@
+
+ return sqlcipher_finalize(db, pStmt, pzErrMsg);
+}
-
- /*
--** Boolean values
++
++/*
+ * copy database and schema from the main database to an attached database
+ *
+ * Based on sqlite3RunVacuum from vacuum.c
- */
--typedef unsigned char Bool;
++*/
+void sqlcipher_exportFunc(sqlite3_context *context, int argc, sqlite3_value **argv) {
+ sqlite3 *db = sqlite3_context_db_handle(context);
+ const char* attachedDb = (const char*) sqlite3_value_text(argv[0]);
@@ -2103,30 +1761,18 @@
+ }
+ }
+}
-
--/* Opaque type used by code in vdbesort.c */
--typedef struct VdbeSorter VdbeSorter;
++
+#endif
-
--/* Opaque type used by the explainer */
--typedef struct Explain Explain;
++
+/* END SQLCIPHER */
+#endif
-
--/*
--** A cursor is a pointer into a single BTree within a database file.
--** The cursor can seek to a BTree entry with a particular key, or
--** loop over all entries of the Btree. You can also insert new BTree
--** entries or retrieve the key or data from the entry that the cursor
--** is currently pointing to.
++
+/************** End of crypto.c **********************************************/
+/************** Begin file crypto_impl.c *************************************/
+/*
+** SQLCipher
+** http://sqlcipher.net
- **
--** Every cursor that the virtual machine has open is represented by an
--** instance of the following structure.
++**
+** Copyright (c) 2008 - 2013, ZETETIC LLC
+** All rights reserved.
+**
@@ -2152,37 +1798,10 @@
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+**
- */
--struct VdbeCursor {
-- BtCursor *pCursor; /* The cursor structure of the backend */
-- Btree *pBt; /* Separate file holding temporary table */
-- KeyInfo *pKeyInfo; /* Info about index keys needed by index cursors */
-- int iDb; /* Index of cursor database in db->aDb[] (or -1) */
-- int pseudoTableReg; /* Register holding pseudotable content. */
-- int nField; /* Number of fields in the header */
-- Bool zeroed; /* True if zeroed out and ready for reuse */
-- Bool rowidIsValid; /* True if lastRowid is valid */
-- Bool atFirst; /* True if pointing to first entry */
-- Bool useRandomRowid; /* Generate new record numbers semi-randomly */
-- Bool nullRow; /* True if pointing to a row with no data */
-- Bool deferredMoveto; /* A call to sqlite3BtreeMoveto() is needed */
-- Bool isTable; /* True if a table requiring integer keys */
-- Bool isIndex; /* True if an index containing keys only - no data */
-- Bool isOrdered; /* True if the underlying table is BTREE_UNORDERED */
-- Bool isSorter; /* True if a new-style sorter */
-- Bool multiPseudo; /* Multi-register pseudo-cursor */
-- sqlite3_vtab_cursor *pVtabCursor; /* The cursor for a virtual table */
-- const sqlite3_module *pModule; /* Module for cursor pVtabCursor */
-- i64 seqCount; /* Sequence counter */
-- i64 movetoTarget; /* Argument to the deferred sqlite3BtreeMoveto() */
-- i64 lastRowid; /* Last rowid from a Next or NextIdx operation */
-- VdbeSorter *pSorter; /* Sorter object for OP_SorterOpen cursors */
++*/
+/* BEGIN SQLCIPHER */
+#ifdef SQLITE_HAS_CODEC
-
-- /* Result of last sqlite3BtreeMoveto() done by an OP_NotExists or
-- ** OP_IsUnique opcode on this cursor. */
-- int seekResult;
++
+/************** Include sqlcipher.h in the middle of crypto_impl.c ***********/
+/************** Begin file sqlcipher.h ***************************************/
+/*
@@ -2221,21 +1840,7 @@
+#ifdef SQLITE_HAS_CODEC
+#ifndef SQLCIPHER_H
+#define SQLCIPHER_H
-
-- /* Cached information about the header for the data record that the
-- ** cursor is currently pointing to. Only valid if cacheStatus matches
-- ** Vdbe.cacheCtr. Vdbe.cacheCtr will never take on the value of
-- ** CACHE_STALE and so setting cacheStatus=CACHE_STALE guarantees that
-- ** the cache is out of date.
-- **
-- ** aRow might point to (ephemeral) data for the current row, or it might
-- ** be NULL.
-- */
-- u32 cacheStatus; /* Cache is valid if this matches Vdbe.cacheCtr */
-- int payloadSize; /* Total number of bytes in the record */
-- u32 *aType; /* Type values for all entries in the record */
-- u32 *aOffset; /* Cached offsets to the start of each columns data */
-- u8 *aRow; /* Data for the current row, if all on one page */
++
+
+typedef struct {
+ int (*activate)(void *ctx);
@@ -2244,7 +1849,7 @@
+ int (*add_random)(void *ctx, void *buffer, int length);
+ int (*random)(void *ctx, void *buffer, int length);
+ int (*hmac)(void *ctx, unsigned char *hmac_key, int key_sz, unsigned char *in, int in_sz, unsigned char
*in2, int in2_sz, unsigned char *out);
-+ int (*kdf)(void *ctx, const char *pass, int pass_sz, unsigned char* salt, int salt_sz, int workfactor,
int key_sz, unsigned char *key);
++ int (*kdf)(void *ctx, const unsigned char *pass, int pass_sz, unsigned char* salt, int salt_sz, int
workfactor, int key_sz, unsigned char *key);
+ int (*cipher)(void *ctx, int mode, unsigned char *key, int key_sz, unsigned char *iv, unsigned char *in,
int in_sz, unsigned char *out);
+ int (*set_cipher)(void *ctx, const char *cipher_name);
+ const char* (*get_cipher)(void *ctx);
@@ -2298,16 +1903,19 @@
+ int pass_sz;
+ int reserve_sz;
+ int hmac_sz;
++ int keyspec_sz;
+ unsigned int flags;
+ unsigned char *key;
+ unsigned char *hmac_key;
-+ char *pass;
++ unsigned char *pass;
++ char *keyspec;
+ sqlcipher_provider *provider;
+ void *provider_ctx;
+} cipher_ctx;
+
+static unsigned int default_flags = DEFAULT_CIPHER_FLAGS;
+static unsigned char hmac_salt_mask = HMAC_SALT_MASK;
++static int default_kdf_iter = PBKDF2_ITER;
+static unsigned int sqlcipher_activate_count = 0;
+static sqlite3_mutex* sqlcipher_provider_mutex = NULL;
+static sqlcipher_provider *default_provider = NULL;
@@ -2321,49 +1929,9 @@
+ Btree *pBt;
+ cipher_ctx *read_ctx;
+ cipher_ctx *write_ctx;
- };
--typedef struct VdbeCursor VdbeCursor;
-
--/*
--** When a sub-program is executed (OP_Program), a structure of this type
--** is allocated to store the current value of the program counter, as
--** well as the current memory cell array and various other frame specific
--** values stored in the Vdbe struct. When the sub-program is finished,
--** these values are copied back to the Vdbe from the VdbeFrame structure,
--** restoring the state of the VM to as it was before the sub-program
--** began executing.
--**
--** The memory for a VdbeFrame object is allocated and managed by a memory
--** cell in the parent (calling) frame. When the memory cell is deleted or
--** overwritten, the VdbeFrame object is not freed immediately. Instead, it
--** is linked into the Vdbe.pDelFrame list. The contents of the Vdbe.pDelFrame
--** list is deleted when the VM is reset in VdbeHalt(). The reason for doing
--** this instead of deleting the VdbeFrame immediately is to avoid recursive
--** calls to sqlite3VdbeMemRelease() when the memory cells belonging to the
--** child frame are released.
--**
--** The currently executing frame is stored in Vdbe.pFrame. Vdbe.pFrame is
--** set to NULL if the currently executing frame is the main program.
--*/
--typedef struct VdbeFrame VdbeFrame;
--struct VdbeFrame {
-- Vdbe *v; /* VM this frame belongs to */
-- VdbeFrame *pParent; /* Parent of this frame, or NULL if parent is main */
-- Op *aOp; /* Program instructions for parent frame */
-- Mem *aMem; /* Array of memory cells for parent frame */
-- u8 *aOnceFlag; /* Array of OP_Once flags for parent frame */
-- VdbeCursor **apCsr; /* Array of Vdbe cursors for parent frame */
-- void *token; /* Copy of SubProgram.token */
-- i64 lastRowid; /* Last insert rowid (sqlite3.lastRowid) */
-- int nCursor; /* Number of entries in apCsr */
-- int pc; /* Program Counter in parent (calling) frame */
-- int nOp; /* Size of aOp array */
-- int nMem; /* Number of entries in aMem */
-- int nOnceFlag; /* Number of entries in aOnceFlag */
-- int nChildMem; /* Number of memory cells for child frame */
-- int nChildCsr; /* Number of cursors for child frame */
-- int nChange; /* Statement changes (Vdbe.nChanges) */
--};
++ unsigned int skip_read_hmac;
++};
++
+int sqlcipher_register_provider(sqlcipher_provider *p) {
+ sqlite3_mutex_enter(sqlcipher_provider_mutex);
+ if(default_provider != NULL && default_provider != p) {
@@ -2376,45 +1944,17 @@
+ sqlite3_mutex_leave(sqlcipher_provider_mutex);
+ return SQLITE_OK;
+}
-
--#define VdbeFrameMem(p) ((Mem *)&((u8 *)p)[ROUND8(sizeof(VdbeFrame))])
++
+/* return a pointer to the currently registered provider. This will
+ allow an application to fetch the current registered provider and
+ make minor changes to it */
+sqlcipher_provider* sqlcipher_get_provider() {
+ return default_provider;
+}
-
--/*
--** A value for VdbeCursor.cacheValid that means the cache is always invalid.
--*/
--#define CACHE_STALE 0
++
+void sqlcipher_activate() {
+ sqlite3_mutex_enter(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER));
-
--/*
--** Internally, the vdbe manipulates nearly all SQL values as Mem
--** structures. Each Mem struct may cache multiple representations (string,
--** integer etc.) of the same value.
--*/
--struct Mem {
-- sqlite3 *db; /* The associated database connection */
-- char *z; /* String or BLOB value */
-- double r; /* Real value */
-- union {
-- i64 i; /* Integer value used when MEM_Int is set in flags */
-- int nZero; /* Used when bit MEM_Zero is set in flags */
-- FuncDef *pDef; /* Used only when flags==MEM_Agg */
-- RowSet *pRowSet; /* Used only when flags==MEM_RowSet */
-- VdbeFrame *pFrame; /* Used when flags==MEM_Frame */
-- } u;
-- int n; /* Number of characters in string value, excluding '\0' */
-- u16 flags; /* Some combination of MEM_Null, MEM_Str, MEM_Dyn, etc. */
-- u8 type; /* One of SQLITE_NULL, SQLITE_TEXT, SQLITE_INTEGER, etc */
-- u8 enc; /* SQLITE_UTF8, SQLITE_UTF16BE, SQLITE_UTF16LE */
--#ifdef SQLITE_DEBUG
-- Mem *pScopyFrom; /* This Mem is a shallow copy of pScopyFrom */
-- void *pFiller; /* So that sizeof(Mem) is a multiple of 8 */
++
+ if(sqlcipher_provider_mutex == NULL) {
+ /* allocate a new mutex to guard access to the provider */
+ sqlcipher_provider_mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
@@ -2436,55 +1976,15 @@
+ sqlcipher_openssl_setup(p);
+#else
+#error "NO DEFAULT SQLCIPHER CRYPTO PROVIDER DEFINED"
- #endif
-- void (*xDel)(void *); /* If not null, call this function to delete Mem.z */
-- char *zMalloc; /* Dynamic buffer allocated by sqlite3_malloc() */
--};
++#endif
+ sqlcipher_register_provider(p);
+ }
-
--/* One or more of the following flags are set to indicate the validOK
--** representations of the value stored in the Mem struct.
--**
--** If the MEM_Null flag is set, then the value is an SQL NULL value.
--** No other flags may be set in this case.
--**
--** If the MEM_Str flag is set then Mem.z points at a string representation.
--** Usually this is encoded in the same unicode encoding as the main
--** database (see below for exceptions). If the MEM_Term flag is also
--** set, then the string is nul terminated. The MEM_Int and MEM_Real
--** flags may coexist with the MEM_Str flag.
--*/
--#define MEM_Null 0x0001 /* Value is NULL */
--#define MEM_Str 0x0002 /* Value is a string */
--#define MEM_Int 0x0004 /* Value is an integer */
--#define MEM_Real 0x0008 /* Value is a real number */
--#define MEM_Blob 0x0010 /* Value is a BLOB */
--#define MEM_RowSet 0x0020 /* Value is a RowSet object */
--#define MEM_Frame 0x0040 /* Value is a VdbeFrame object */
--#define MEM_Invalid 0x0080 /* Value is undefined */
--#define MEM_Cleared 0x0100 /* NULL set by OP_Null, not from data */
--#define MEM_TypeMask 0x01ff /* Mask of type bits */
++
+ sqlcipher_activate_count++; /* increment activation count */
-
++
+ sqlite3_mutex_leave(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER));
+}
-
--/* Whenever Mem contains a valid string or blob representation, one of
--** the following flags must be set to determine the memory management
--** policy for Mem.z. The MEM_Term flag tells us whether or not the
--** string is \000 or \u0000 terminated
--*/
--#define MEM_Term 0x0200 /* String rep is nul terminated */
--#define MEM_Dyn 0x0400 /* Need to call sqliteFree() on Mem.z */
--#define MEM_Static 0x0800 /* Mem.z points to a static string */
--#define MEM_Ephem 0x1000 /* Mem.z points to an ephemeral string */
--#define MEM_Agg 0x2000 /* Mem.z points to an agg function context */
--#define MEM_Zero 0x4000 /* Mem.i contains count of 0s appended to blob */
--#ifdef SQLITE_OMIT_INCRBLOB
-- #undef MEM_Zero
-- #define MEM_Zero 0x0000
--#endif
++
+void sqlcipher_deactivate() {
+ sqlite3_mutex_enter(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER));
+ sqlcipher_activate_count--;
@@ -2500,163 +2000,40 @@
+ /* last connection closed, free provider mutex*/
+ sqlite3_mutex_free(sqlcipher_provider_mutex);
+ sqlcipher_provider_mutex = NULL;
-
--/*
--** Clear any existing type flags from a Mem and replace them with f
--*/
--#define MemSetTypeFlag(p, f) \
-- ((p)->flags = ((p)->flags&~(MEM_TypeMask|MEM_Zero))|f)
++
+ sqlcipher_activate_count = 0; /* reset activation count */
+ }
+ sqlite3_mutex_leave(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER));
+}
-
--/*
--** Return true if a memory cell is not marked as invalid. This macro
--** is for use inside assert() statements only.
++
+/* constant time memset using volitile to avoid having the memset
+ optimized out by the compiler.
+ Note: As suggested by Joachim Schipper (joachim schipper fox-it com)
- */
--#ifdef SQLITE_DEBUG
--#define memIsValid(M) ((M)->flags & MEM_Invalid)==0
--#endif
++*/
+void* sqlcipher_memset(void *v, unsigned char value, int len) {
+ int i = 0;
+ volatile unsigned char *a = v;
-
++
+ if (v == NULL) return v;
-
--/* A VdbeFunc is just a FuncDef (defined in sqliteInt.h) that contains
--** additional information about auxiliary information bound to arguments
--** of the function. This is used to implement the sqlite3_get_auxdata()
--** and sqlite3_set_auxdata() APIs. The "auxdata" is some auxiliary data
--** that can be associated with a constant argument to a function. This
--** allows functions such as "regexp" to compile their constant regular
--** expression argument once and reused the compiled code for multiple
--** invocations.
--*/
--struct VdbeFunc {
-- FuncDef *pFunc; /* The definition of the function */
-- int nAux; /* Number of entries allocated for apAux[] */
-- struct AuxData {
-- void *pAux; /* Aux data for the i-th argument */
-- void (*xDelete)(void *); /* Destructor for the aux data */
-- } apAux[1]; /* One slot for each function argument */
--};
++
+ for(i = 0; i < len; i++) {
+ a[i] = value;
+ }
-
--/*
--** The "context" argument for a installable function. A pointer to an
--** instance of this structure is the first argument to the routines used
--** implement the SQL functions.
--**
--** There is a typedef for this structure in sqlite.h. So all routines,
--** even the public interface to SQLite, can use a pointer to this structure.
--** But this file is the only place where the internal details of this
--** structure are known.
--**
--** This structure is defined inside of vdbeInt.h because it uses substructures
--** (Mem) which are only defined there.
--*/
--struct sqlite3_context {
-- FuncDef *pFunc; /* Pointer to function information. MUST BE FIRST */
-- VdbeFunc *pVdbeFunc; /* Auxilary data, if created. */
-- Mem s; /* The return value is stored here */
-- Mem *pMem; /* Memory cell used to store aggregate context */
-- CollSeq *pColl; /* Collating sequence */
-- int isError; /* Error code returned by the function. */
-- int skipFlag; /* Skip skip accumulator loading if true */
--};
++
+ return v;
+}
-
--/*
--** An Explain object accumulates indented output which is helpful
--** in describing recursive data structures.
--*/
--struct Explain {
-- Vdbe *pVdbe; /* Attach the explanation to this Vdbe */
-- StrAccum str; /* The string being accumulated */
-- int nIndent; /* Number of elements in aIndent */
-- u16 aIndent[100]; /* Levels of indentation */
-- char zBase[100]; /* Initial space */
--};
++
+/* constant time memory check tests every position of a memory segement
+ matches a single value (i.e. the memory is all zeros)
+ returns 0 if match, 1 of no match */
+int sqlcipher_ismemset(const void *v, unsigned char value, int len) {
+ const unsigned char *a = v;
+ int i = 0, result = 0;
-
--/* A bitfield type for use inside of structures. Always follow with :N where
--** N is the number of bits.
--*/
--typedef unsigned bft; /* Bit Field Type */
++
+ for(i = 0; i < len; i++) {
+ result |= a[i] ^ value;
+ }
-
--/*
--** An instance of the virtual machine. This structure contains the complete
--** state of the virtual machine.
--**
--** The "sqlite3_stmt" structure pointer that is returned by sqlite3_prepare()
--** is really a pointer to an instance of this structure.
--**
--** The Vdbe.inVtabMethod variable is set to non-zero for the duration of
--** any virtual table method invocations made by the vdbe program. It is
--** set to 2 for xDestroy method calls and 1 for all other methods. This
--** variable is used for two purposes: to allow xDestroy methods to execute
--** "DROP TABLE" statements and to prevent some nasty side effects of
--** malloc failure when SQLite is invoked recursively by a virtual table
--** method function.
--*/
--struct Vdbe {
-- sqlite3 *db; /* The database connection that owns this statement */
-- Op *aOp; /* Space to hold the virtual machine's program */
-- Mem *aMem; /* The memory locations */
-- Mem **apArg; /* Arguments to currently executing user function */
-- Mem *aColName; /* Column names to return */
-- Mem *pResultSet; /* Pointer to an array of results */
-- int nMem; /* Number of memory locations currently allocated */
-- int nOp; /* Number of instructions in the program */
-- int nOpAlloc; /* Number of slots allocated for aOp[] */
-- int nLabel; /* Number of labels used */
-- int *aLabel; /* Space to hold the labels */
-- u16 nResColumn; /* Number of columns in one row of the result set */
-- int nCursor; /* Number of slots in apCsr[] */
-- u32 magic; /* Magic number for sanity checking */
-- char *zErrMsg; /* Error message written here */
-- Vdbe *pPrev,*pNext; /* Linked list of VDBEs with the same Vdbe.db */
-- VdbeCursor **apCsr; /* One element of this array for each open cursor */
-- Mem *aVar; /* Values for the OP_Variable opcode. */
-- char **azVar; /* Name of variables */
-- ynVar nVar; /* Number of entries in aVar[] */
-- ynVar nzVar; /* Number of entries in azVar[] */
-- u32 cacheCtr; /* VdbeCursor row cache generation counter */
-- int pc; /* The program counter */
-- int rc; /* Value to return */
-- u8 errorAction; /* Recovery action to do in case of an error */
-- u8 minWriteFileFormat; /* Minimum file format for writable database files */
-- bft explain:2; /* True if EXPLAIN present on SQL command */
-- bft inVtabMethod:2; /* See comments above */
-- bft changeCntOn:1; /* True to update the change-counter */
-- bft expired:1; /* True if the VM needs to be recompiled */
-- bft runOnlyOnce:1; /* Automatically expire on reset */
-- bft usesStmtJournal:1; /* True if uses a statement journal */
-- bft readOnly:1; /* True for read-only statements */
-- bft isPrepareV2:1; /* True if prepared with prepare_v2() */
-- bft doingRerun:1; /* True if rerunning after an auto-reprepare */
-- int nChange; /* Number of db changes made since last reset */
-- yDbMask btreeMask; /* Bitmask of db->aDb[] entries referenced */
-- yDbMask lockMask; /* Subset of btreeMask that requires a lock */
-- int iStatement; /* Statement number (or 0 if has not opened stmt) */
-- int aCounter[3]; /* Counters used by sqlite3_stmt_status() */
--#ifndef SQLITE_OMIT_TRACE
-- i64 startTime; /* Time when query started - used for profiling */
++
+ return (result != 0);
+}
+
@@ -2689,18 +2066,11 @@
+#if defined(__unix__) || defined(__APPLE__)
+ munlock(ptr, sz);
+#elif defined(_WIN32)
-+ VirtualUnlock(ptr, sz);
- #endif
-- i64 nFkConstraint; /* Number of imm. FK constraints this VM */
-- i64 nStmtDefCons; /* Number of def. constraints when stmt started */
-- char *zSql; /* Text of the SQL statement that generated this */
-- void *pFree; /* Free this when deleting the vdbe */
--#ifdef SQLITE_DEBUG
-- FILE *trace; /* Write an execution trace here, if not NULL */
- #endif
--#ifdef SQLITE_ENABLE_TREE_EXPLAIN
-- Explain *pExplain; /* The explainer */
-- char *zExplain; /* Explanation of data structures */
++#if !(defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP || WINAPI_FAMILY ==
WINAPI_FAMILY_APP))
++VirtualUnlock(ptr, sz);
++#endif
++#endif
++#endif
+ }
+ sqlite3_free(ptr);
+ }
@@ -2719,43 +2089,16 @@
+#if defined(__unix__) || defined(__APPLE__)
+ mlock(ptr, sz);
+#elif defined(_WIN32)
++#if !(defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP || WINAPI_FAMILY ==
WINAPI_FAMILY_APP))
+ VirtualLock(ptr, sz);
- #endif
-- VdbeFrame *pFrame; /* Parent frame */
-- VdbeFrame *pDelFrame; /* List of frame objects to free on VM reset */
-- int nFrame; /* Number of frames in pFrame list */
-- u32 expmask; /* Binding to these vars invalidates VM */
-- SubProgram *pProgram; /* Linked list of all sub-programs used by VM */
-- int nOnceFlag; /* Size of array aOnceFlag[] */
-- u8 *aOnceFlag; /* Flags for OP_Once */
--};
++#endif
++#endif
+ }
+#endif
+ return ptr;
+}
-
--/*
--** The following are allowed values for Vdbe.magic
--*/
--#define VDBE_MAGIC_INIT 0x26bceaa5 /* Building a VDBE program */
--#define VDBE_MAGIC_RUN 0xbdf20da3 /* VDBE is ready to execute */
--#define VDBE_MAGIC_HALT 0x519c2973 /* VDBE has completed execution */
--#define VDBE_MAGIC_DEAD 0xb606c3c8 /* The VDBE has been deallocated */
-
--/*
--** Function prototypes
--*/
--SQLITE_PRIVATE void sqlite3VdbeFreeCursor(Vdbe *, VdbeCursor*);
--void sqliteVdbePopStack(Vdbe*,int);
--SQLITE_PRIVATE int sqlite3VdbeCursorMoveto(VdbeCursor*);
--#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE)
--SQLITE_PRIVATE void sqlite3VdbePrintOp(FILE*, int, Op*);
--#endif
--SQLITE_PRIVATE u32 sqlite3VdbeSerialTypeLen(u32);
--SQLITE_PRIVATE u32 sqlite3VdbeSerialType(Mem*, int);
--SQLITE_PRIVATE u32 sqlite3VdbeSerialPut(unsigned char*, int, Mem*, int);
--SQLITE_PRIVATE u32 sqlite3VdbeSerialGet(const unsigned char*, u32, Mem*);
--SQLITE_PRIVATE void sqlite3VdbeDeleteAuxData(VdbeFunc*, int);
++
++
+/**
+ * Initialize new cipher_ctx struct. This function will allocate memory
+ * for the cipher context and for the key
@@ -2783,72 +2126,13 @@
+ ctx->hmac_key = (unsigned char *) sqlcipher_malloc(CIPHER_MAX_KEY_SZ);
+ if(ctx->key == NULL) return SQLITE_NOMEM;
+ if(ctx->hmac_key == NULL) return SQLITE_NOMEM;
-
--int sqlite2BtreeKeyCompare(BtCursor *, const void *, int, int, int *);
--SQLITE_PRIVATE int sqlite3VdbeIdxKeyCompare(VdbeCursor*,UnpackedRecord*,int*);
--SQLITE_PRIVATE int sqlite3VdbeIdxRowid(sqlite3*, BtCursor *, i64 *);
--SQLITE_PRIVATE int sqlite3MemCompare(const Mem*, const Mem*, const CollSeq*);
--SQLITE_PRIVATE int sqlite3VdbeExec(Vdbe*);
--SQLITE_PRIVATE int sqlite3VdbeList(Vdbe*);
--SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe*);
--SQLITE_PRIVATE int sqlite3VdbeChangeEncoding(Mem *, int);
--SQLITE_PRIVATE int sqlite3VdbeMemTooBig(Mem*);
--SQLITE_PRIVATE int sqlite3VdbeMemCopy(Mem*, const Mem*);
--SQLITE_PRIVATE void sqlite3VdbeMemShallowCopy(Mem*, const Mem*, int);
--SQLITE_PRIVATE void sqlite3VdbeMemMove(Mem*, Mem*);
--SQLITE_PRIVATE int sqlite3VdbeMemNulTerminate(Mem*);
--SQLITE_PRIVATE int sqlite3VdbeMemSetStr(Mem*, const char*, int, u8, void(*)(void*));
--SQLITE_PRIVATE void sqlite3VdbeMemSetInt64(Mem*, i64);
--#ifdef SQLITE_OMIT_FLOATING_POINT
--# define sqlite3VdbeMemSetDouble sqlite3VdbeMemSetInt64
--#else
--SQLITE_PRIVATE void sqlite3VdbeMemSetDouble(Mem*, double);
--#endif
--SQLITE_PRIVATE void sqlite3VdbeMemSetNull(Mem*);
--SQLITE_PRIVATE void sqlite3VdbeMemSetZeroBlob(Mem*,int);
--SQLITE_PRIVATE void sqlite3VdbeMemSetRowSet(Mem*);
--SQLITE_PRIVATE int sqlite3VdbeMemMakeWriteable(Mem*);
--SQLITE_PRIVATE int sqlite3VdbeMemStringify(Mem*, int);
--SQLITE_PRIVATE i64 sqlite3VdbeIntValue(Mem*);
--SQLITE_PRIVATE int sqlite3VdbeMemIntegerify(Mem*);
--SQLITE_PRIVATE double sqlite3VdbeRealValue(Mem*);
--SQLITE_PRIVATE void sqlite3VdbeIntegerAffinity(Mem*);
--SQLITE_PRIVATE int sqlite3VdbeMemRealify(Mem*);
--SQLITE_PRIVATE int sqlite3VdbeMemNumerify(Mem*);
--SQLITE_PRIVATE int sqlite3VdbeMemFromBtree(BtCursor*,int,int,int,Mem*);
--SQLITE_PRIVATE void sqlite3VdbeMemRelease(Mem *p);
--SQLITE_PRIVATE void sqlite3VdbeMemReleaseExternal(Mem *p);
--#define VdbeMemRelease(X) \
-- if((X)->flags&(MEM_Agg|MEM_Dyn|MEM_RowSet|MEM_Frame)) \
-- sqlite3VdbeMemReleaseExternal(X);
--SQLITE_PRIVATE int sqlite3VdbeMemFinalize(Mem*, FuncDef*);
--SQLITE_PRIVATE const char *sqlite3OpcodeName(int);
--SQLITE_PRIVATE int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve);
--SQLITE_PRIVATE int sqlite3VdbeCloseStatement(Vdbe *, int);
--SQLITE_PRIVATE void sqlite3VdbeFrameDelete(VdbeFrame*);
--SQLITE_PRIVATE int sqlite3VdbeFrameRestore(VdbeFrame *);
--SQLITE_PRIVATE void sqlite3VdbeMemStoreType(Mem *pMem);
--SQLITE_PRIVATE int sqlite3VdbeTransferError(Vdbe *p);
++
+ /* setup default flags */
+ ctx->flags = default_flags;
-
--SQLITE_PRIVATE int sqlite3VdbeSorterInit(sqlite3 *, VdbeCursor *);
--SQLITE_PRIVATE void sqlite3VdbeSorterClose(sqlite3 *, VdbeCursor *);
--SQLITE_PRIVATE int sqlite3VdbeSorterRowkey(const VdbeCursor *, Mem *);
--SQLITE_PRIVATE int sqlite3VdbeSorterNext(sqlite3 *, const VdbeCursor *, int *);
--SQLITE_PRIVATE int sqlite3VdbeSorterRewind(sqlite3 *, const VdbeCursor *, int *);
--SQLITE_PRIVATE int sqlite3VdbeSorterWrite(sqlite3 *, const VdbeCursor *, Mem *);
--SQLITE_PRIVATE int sqlite3VdbeSorterCompare(const VdbeCursor *, Mem *, int *);
++
+ return SQLITE_OK;
+}
-
--#if !defined(SQLITE_OMIT_SHARED_CACHE) && SQLITE_THREADSAFE>0
--SQLITE_PRIVATE void sqlite3VdbeEnter(Vdbe*);
--SQLITE_PRIVATE void sqlite3VdbeLeave(Vdbe*);
--#else
--# define sqlite3VdbeEnter(X)
--# define sqlite3VdbeLeave(X)
--#endif
++
+/**
+ * Free and wipe memory associated with a cipher_ctx
+ */
@@ -2860,6 +2144,7 @@
+ sqlcipher_free(ctx->key, ctx->key_sz);
+ sqlcipher_free(ctx->hmac_key, ctx->key_sz);
+ sqlcipher_free(ctx->pass, ctx->pass_sz);
++ sqlcipher_free(ctx->keyspec, ctx->keyspec_sz);
+ sqlcipher_free(ctx, sizeof(cipher_ctx));
+}
+
@@ -2890,10 +2175,7 @@
+ ) return 0;
+ return 1;
+}
-
--#ifdef SQLITE_DEBUG
--SQLITE_PRIVATE void sqlite3VdbeMemAboutToChange(Vdbe*,Mem*);
--#endif
++
+/**
+ * Copy one cipher_ctx to another. For instance, assuming that read_ctx is a
+ * fully initialized context, you could copy it to write_ctx and all yet data
@@ -2910,103 +2192,90 @@
+
+ CODEC_TRACE(("sqlcipher_cipher_ctx_copy: entered target=%p, source=%p\n", target, source));
+ sqlcipher_free(target->pass, target->pass_sz);
++ sqlcipher_free(target->keyspec, target->keyspec_sz);
+ memcpy(target, source, sizeof(cipher_ctx));
-+
++
+ target->key = key; //restore pointer to previously allocated key data
+ memcpy(target->key, source->key, CIPHER_MAX_KEY_SZ);
-
--#ifndef SQLITE_OMIT_FOREIGN_KEY
--SQLITE_PRIVATE int sqlite3VdbeCheckFk(Vdbe *, int);
--#else
--# define sqlite3VdbeCheckFk(p,i) 0
--#endif
++
+ target->hmac_key = hmac_key; //restore pointer to previously allocated hmac key data
+ memcpy(target->hmac_key, source->hmac_key, CIPHER_MAX_KEY_SZ);
-
--SQLITE_PRIVATE int sqlite3VdbeMemTranslate(Mem*, u8);
--#ifdef SQLITE_DEBUG
--SQLITE_PRIVATE void sqlite3VdbePrintSql(Vdbe*);
--SQLITE_PRIVATE void sqlite3VdbeMemPrettyPrint(Mem *pMem, char *zBuf);
--#endif
--SQLITE_PRIVATE int sqlite3VdbeMemHandleBom(Mem *pMem);
++
+ target->provider = provider; // restore pointer to previouly allocated provider;
+ memcpy(target->provider, source->provider, sizeof(sqlcipher_provider));
-
--#ifndef SQLITE_OMIT_INCRBLOB
--SQLITE_PRIVATE int sqlite3VdbeMemExpandBlob(Mem *);
-- #define ExpandBlob(P) (((P)->flags&MEM_Zero)?sqlite3VdbeMemExpandBlob(P):0)
--#else
-- #define sqlite3VdbeMemExpandBlob(x) SQLITE_OK
-- #define ExpandBlob(P) SQLITE_OK
--#endif
++
+ target->provider_ctx = provider_ctx; // restore pointer to previouly allocated provider context;
+ target->provider->ctx_copy(target->provider_ctx, source->provider_ctx);
-
--#endif /* !defined(_VDBEINT_H_) */
-+ target->pass = sqlcipher_malloc(source->pass_sz);
-+ if(target->pass == NULL) return SQLITE_NOMEM;
-+ memcpy(target->pass, source->pass, source->pass_sz);
-
--/************** End of vdbeInt.h *********************************************/
--/************** Continuing where we left off in status.c *********************/
++
++ if(source->pass && source->pass_sz) {
++ target->pass = sqlcipher_malloc(source->pass_sz);
++ if(target->pass == NULL) return SQLITE_NOMEM;
++ memcpy(target->pass, source->pass, source->pass_sz);
++ }
++ if(source->keyspec && source->keyspec_sz) {
++ target->keyspec = sqlcipher_malloc(source->keyspec_sz);
++ if(target->keyspec == NULL) return SQLITE_NOMEM;
++ memcpy(target->keyspec, source->keyspec, source->keyspec_sz);
++ }
+ return SQLITE_OK;
+}
-
--/*
--** Variables in which to record status information.
--*/
--typedef struct sqlite3StatType sqlite3StatType;
--static SQLITE_WSD struct sqlite3StatType {
-- int nowValue[10]; /* Current value */
-- int mxValue[10]; /* Maximum value */
--} sqlite3Stat = { {0,}, {0,} };
-
++
++/**
++ * Set the keyspec for the cipher_ctx
++ *
++ * returns SQLITE_OK if assignment was successfull
++ * returns SQLITE_NOMEM if an error occured allocating memory
++ */
++static int sqlcipher_cipher_ctx_set_keyspec(cipher_ctx *ctx, const unsigned char *key, int key_sz, const
unsigned char *salt, int salt_sz) {
++
++ /* free, zero existing pointers and size */
++ sqlcipher_free(ctx->keyspec, ctx->keyspec_sz);
++ ctx->keyspec = NULL;
++ ctx->keyspec_sz = 0;
++
++ /* establic a hex-formated key specification, containing the raw encryption key and
++ the salt used to generate it */
++ ctx->keyspec_sz = ((key_sz + salt_sz) * 2) + 3;
++ ctx->keyspec = sqlcipher_malloc(ctx->keyspec_sz);
++ if(ctx->keyspec == NULL) return SQLITE_NOMEM;
++
++ ctx->keyspec[0] = 'x';
++ ctx->keyspec[1] = '\'';
++ cipher_bin2hex(key, key_sz, ctx->keyspec + 2);
++ cipher_bin2hex(salt, salt_sz, ctx->keyspec + (key_sz * 2) + 2);
++ ctx->keyspec[ctx->keyspec_sz - 1] = '\'';
++ return SQLITE_OK;
++}
++
+/**
-+ * Set the raw password / key data for a cipher context
++ * Set the passphrase for the cipher_ctx
+ *
+ * returns SQLITE_OK if assignment was successfull
+ * returns SQLITE_NOMEM if an error occured allocating memory
-+ * returns SQLITE_ERROR if the key couldn't be set because the pass was null or size was zero
+ */
+static int sqlcipher_cipher_ctx_set_pass(cipher_ctx *ctx, const void *zKey, int nKey) {
++
++ /* free, zero existing pointers and size */
+ sqlcipher_free(ctx->pass, ctx->pass_sz);
-+ ctx->pass_sz = nKey;
-+ if(zKey && nKey) {
++ ctx->pass = NULL;
++ ctx->pass_sz = 0;
++
++ if(zKey && nKey) { /* if new password is provided, copy it */
++ ctx->pass_sz = nKey;
+ ctx->pass = sqlcipher_malloc(nKey);
+ if(ctx->pass == NULL) return SQLITE_NOMEM;
+ memcpy(ctx->pass, zKey, nKey);
-+ return SQLITE_OK;
-+ }
-+ return SQLITE_ERROR;
++ }
++ return SQLITE_OK;
+}
+
+int sqlcipher_codec_ctx_set_pass(codec_ctx *ctx, const void *zKey, int nKey, int for_ctx) {
+ cipher_ctx *c_ctx = for_ctx ? ctx->write_ctx : ctx->read_ctx;
+ int rc;
-
--/* The "wsdStat" macro will resolve to the status information
--** state vector. If writable static data is unsupported on the target,
--** we have to locate the state vector at run-time. In the more common
--** case where writable static data is supported, wsdStat can refer directly
--** to the "sqlite3Stat" state vector declared above.
--*/
--#ifdef SQLITE_OMIT_WSD
--# define wsdStatInit sqlite3StatType *x = &GLOBAL(sqlite3StatType,sqlite3Stat)
--# define wsdStat x[0]
--#else
--# define wsdStatInit
--# define wsdStat sqlite3Stat
--#endif
++
+ if((rc = sqlcipher_cipher_ctx_set_pass(c_ctx, zKey, nKey)) != SQLITE_OK) return rc;
+ c_ctx->derive_key = 1;
-
--/*
--** Return the current value of a status parameter.
--*/
--SQLITE_PRIVATE int sqlite3StatusValue(int op){
-- wsdStatInit;
-- assert( op>=0 && op<ArraySize(wsdStat.nowValue) );
-- return wsdStat.nowValue[op];
++
+ if(for_ctx == 2)
+ if((rc = sqlcipher_cipher_ctx_copy( for_ctx ? ctx->read_ctx : ctx->write_ctx, c_ctx)) != SQLITE_OK)
+ return rc;
@@ -3031,34 +2300,22 @@
+ return rc;
+
+ return SQLITE_OK;
- }
-
--/*
--** Add N to the value of a status record. It is assumed that the
--** caller holds appropriate locks.
--*/
--SQLITE_PRIVATE void sqlite3StatusAdd(int op, int N){
-- wsdStatInit;
-- assert( op>=0 && op<ArraySize(wsdStat.nowValue) );
-- wsdStat.nowValue[op] += N;
-- if( wsdStat.nowValue[op]>wsdStat.mxValue[op] ){
-- wsdStat.mxValue[op] = wsdStat.nowValue[op];
-- }
++}
++
+const char* sqlcipher_codec_ctx_get_cipher(codec_ctx *ctx, int for_ctx) {
+ cipher_ctx *c_ctx = for_ctx ? ctx->write_ctx : ctx->read_ctx;
+ return c_ctx->provider->get_cipher(c_ctx->provider_ctx);
- }
-
--/*
--** Set the value of a status to X.
--*/
--SQLITE_PRIVATE void sqlite3StatusSet(int op, int X){
-- wsdStatInit;
-- assert( op>=0 && op<ArraySize(wsdStat.nowValue) );
-- wsdStat.nowValue[op] = X;
-- if( wsdStat.nowValue[op]>wsdStat.mxValue[op] ){
-- wsdStat.mxValue[op] = wsdStat.nowValue[op];
-- }
++}
++
++/* set the global default KDF iteration */
++void sqlcipher_set_default_kdf_iter(int iter) {
++ default_kdf_iter = iter;
++}
++
++int sqlcipher_get_default_kdf_iter() {
++ return default_kdf_iter;
++}
++
+int sqlcipher_codec_ctx_set_kdf_iter(codec_ctx *ctx, int kdf_iter, int for_ctx) {
+ cipher_ctx *c_ctx = for_ctx ? ctx->write_ctx : ctx->read_ctx;
+ int rc;
@@ -3071,25 +2328,8 @@
+ return rc;
+
+ return SQLITE_OK;
- }
-
--/*
--** Query status information.
--**
--** This implementation assumes that reading or writing an aligned
--** 32-bit integer is an atomic operation. If that assumption is not true,
--** then this routine is not threadsafe.
--*/
--SQLITE_API int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag){
-- wsdStatInit;
-- if( op<0 || op>=ArraySize(wsdStat.nowValue) ){
-- return SQLITE_MISUSE_BKPT;
-- }
-- *pCurrent = wsdStat.nowValue[op];
-- *pHighwater = wsdStat.mxValue[op];
-- if( resetFlag ){
-- wsdStat.mxValue[op] = wsdStat.nowValue[op];
-- }
++}
++
+int sqlcipher_codec_ctx_get_kdf_iter(codec_ctx *ctx, int for_ctx) {
+ cipher_ctx *c_ctx = for_ctx ? ctx->write_ctx : ctx->read_ctx;
+ return c_ctx->kdf_iter;
@@ -3106,157 +2346,46 @@
+ if((rc = sqlcipher_cipher_ctx_copy( for_ctx ? ctx->read_ctx : ctx->write_ctx, c_ctx)) != SQLITE_OK)
+ return rc;
+
- return SQLITE_OK;
- }
-
--/*
--** Query status information for a single database connection
--*/
--SQLITE_API int sqlite3_db_status(
-- sqlite3 *db, /* The database connection whose status is desired */
-- int op, /* Status verb */
-- int *pCurrent, /* Write current value here */
-- int *pHighwater, /* Write high-water mark here */
-- int resetFlag /* Reset high-water mark if true */
--){
-- int rc = SQLITE_OK; /* Return code */
-- sqlite3_mutex_enter(db->mutex);
-- switch( op ){
-- case SQLITE_DBSTATUS_LOOKASIDE_USED: {
-- *pCurrent = db->lookaside.nOut;
-- *pHighwater = db->lookaside.mxOut;
-- if( resetFlag ){
-- db->lookaside.mxOut = db->lookaside.nOut;
-- }
-- break;
-- }
++ return SQLITE_OK;
++}
++
+int sqlcipher_codec_ctx_get_fast_kdf_iter(codec_ctx *ctx, int for_ctx) {
+ cipher_ctx *c_ctx = for_ctx ? ctx->write_ctx : ctx->read_ctx;
+ return c_ctx->fast_kdf_iter;
+}
-
-- case SQLITE_DBSTATUS_LOOKASIDE_HIT:
-- case SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE:
-- case SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL: {
-- testcase( op==SQLITE_DBSTATUS_LOOKASIDE_HIT );
-- testcase( op==SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE );
-- testcase( op==SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL );
-- assert( (op-SQLITE_DBSTATUS_LOOKASIDE_HIT)>=0 );
-- assert( (op-SQLITE_DBSTATUS_LOOKASIDE_HIT)<3 );
-- *pCurrent = 0;
-- *pHighwater = db->lookaside.anStat[op - SQLITE_DBSTATUS_LOOKASIDE_HIT];
-- if( resetFlag ){
-- db->lookaside.anStat[op - SQLITE_DBSTATUS_LOOKASIDE_HIT] = 0;
-- }
-- break;
-- }
++
+/* set the global default flag for HMAC */
+void sqlcipher_set_default_use_hmac(int use) {
+ if(use) default_flags |= CIPHER_FLAG_HMAC;
+ else default_flags &= ~CIPHER_FLAG_HMAC;
+}
-
-- /*
-- ** Return an approximation for the amount of memory currently used
-- ** by all pagers associated with the given database connection. The
-- ** highwater mark is meaningless and is returned as zero.
-- */
-- case SQLITE_DBSTATUS_CACHE_USED: {
-- int totalUsed = 0;
-- int i;
-- sqlite3BtreeEnterAll(db);
-- for(i=0; i<db->nDb; i++){
-- Btree *pBt = db->aDb[i].pBt;
-- if( pBt ){
-- Pager *pPager = sqlite3BtreePager(pBt);
-- totalUsed += sqlite3PagerMemUsed(pPager);
-- }
-- }
-- sqlite3BtreeLeaveAll(db);
-- *pCurrent = totalUsed;
-- *pHighwater = 0;
-- break;
-- }
++
+int sqlcipher_get_default_use_hmac() {
+ return (default_flags & CIPHER_FLAG_HMAC) != 0;
+}
-
-- /*
-- ** *pCurrent gets an accurate estimate of the amount of memory used
-- ** to store the schema for all databases (main, temp, and any ATTACHed
-- ** databases. *pHighwater is set to zero.
-- */
-- case SQLITE_DBSTATUS_SCHEMA_USED: {
-- int i; /* Used to iterate through schemas */
-- int nByte = 0; /* Used to accumulate return value */
++
+void sqlcipher_set_hmac_salt_mask(unsigned char mask) {
+ hmac_salt_mask = mask;
+}
-
-- sqlite3BtreeEnterAll(db);
-- db->pnBytesFreed = &nByte;
-- for(i=0; i<db->nDb; i++){
-- Schema *pSchema = db->aDb[i].pSchema;
-- if( ALWAYS(pSchema!=0) ){
-- HashElem *p;
++
+unsigned char sqlcipher_get_hmac_salt_mask() {
+ return hmac_salt_mask;
+}
-
-- nByte += sqlite3GlobalConfig.m.xRoundup(sizeof(HashElem)) * (
-- pSchema->tblHash.count
-- + pSchema->trigHash.count
-- + pSchema->idxHash.count
-- + pSchema->fkeyHash.count
-- );
-- nByte += sqlite3MallocSize(pSchema->tblHash.ht);
-- nByte += sqlite3MallocSize(pSchema->trigHash.ht);
-- nByte += sqlite3MallocSize(pSchema->idxHash.ht);
-- nByte += sqlite3MallocSize(pSchema->fkeyHash.ht);
++
+/* set the codec flag for whether this individual database should be using hmac */
+int sqlcipher_codec_ctx_set_use_hmac(codec_ctx *ctx, int use) {
+ int reserve = CIPHER_MAX_IV_SZ; /* base reserve size will be IV only */
-
-- for(p=sqliteHashFirst(&pSchema->trigHash); p; p=sqliteHashNext(p)){
-- sqlite3DeleteTrigger(db, (Trigger*)sqliteHashData(p));
-- }
-- for(p=sqliteHashFirst(&pSchema->tblHash); p; p=sqliteHashNext(p)){
-- sqlite3DeleteTable(db, (Table *)sqliteHashData(p));
-- }
-- }
-- }
-- db->pnBytesFreed = 0;
-- sqlite3BtreeLeaveAll(db);
++
+ if(use) reserve += ctx->read_ctx->hmac_sz; /* if reserve will include hmac, update that size */
-
-- *pHighwater = 0;
-- *pCurrent = nByte;
-- break;
-- }
++
+ /* calculate the amount of reserve needed in even increments of the cipher block size */
-
-- /*
-- ** *pCurrent gets an accurate estimate of the amount of memory used
-- ** to store all prepared statements.
-- ** *pHighwater is set to zero.
-- */
-- case SQLITE_DBSTATUS_STMT_USED: {
-- struct Vdbe *pVdbe; /* Used to iterate through VMs */
-- int nByte = 0; /* Used to accumulate return value */
++
+ reserve = ((reserve % ctx->read_ctx->block_sz) == 0) ? reserve :
+ ((reserve / ctx->read_ctx->block_sz) + 1) * ctx->read_ctx->block_sz;
-
-- db->pnBytesFreed = &nByte;
-- for(pVdbe=db->pVdbe; pVdbe; pVdbe=pVdbe->pNext){
-- sqlite3VdbeClearObject(db, pVdbe);
-- sqlite3DbFree(db, pVdbe);
-- }
-- db->pnBytesFreed = 0;
++
+ CODEC_TRACE(("sqlcipher_codec_ctx_set_use_hmac: use=%d block_sz=%d md_size=%d reserve=%d\n",
+ use, ctx->read_ctx->block_sz, ctx->read_ctx->hmac_sz, reserve));
-
-- *pHighwater = 0;
-- *pCurrent = nByte;
++
+
+ if(use) {
+ sqlcipher_codec_ctx_set_flag(ctx, CIPHER_FLAG_HMAC);
@@ -3265,234 +2394,55 @@
+ }
+
+ ctx->write_ctx->reserve_sz = ctx->read_ctx->reserve_sz = reserve;
-
-- break;
-- }
++
+ return SQLITE_OK;
+}
-
-- /*
-- ** Set *pCurrent to the total cache hits or misses encountered by all
-- ** pagers the database handle is connected to. *pHighwater is always set
-- ** to zero.
-- */
-- case SQLITE_DBSTATUS_CACHE_HIT:
-- case SQLITE_DBSTATUS_CACHE_MISS:
-- case SQLITE_DBSTATUS_CACHE_WRITE:{
-- int i;
-- int nRet = 0;
-- assert( SQLITE_DBSTATUS_CACHE_MISS==SQLITE_DBSTATUS_CACHE_HIT+1 );
-- assert( SQLITE_DBSTATUS_CACHE_WRITE==SQLITE_DBSTATUS_CACHE_HIT+2 );
++
+int sqlcipher_codec_ctx_get_use_hmac(codec_ctx *ctx, int for_ctx) {
+ cipher_ctx * c_ctx = for_ctx ? ctx->write_ctx : ctx->read_ctx;
+ return (c_ctx->flags & CIPHER_FLAG_HMAC) != 0;
+}
-
-- for(i=0; i<db->nDb; i++){
-- if( db->aDb[i].pBt ){
-- Pager *pPager = sqlite3BtreePager(db->aDb[i].pBt);
-- sqlite3PagerCacheStat(pPager, op, resetFlag, &nRet);
-- }
-- }
-- *pHighwater = 0;
-- *pCurrent = nRet;
-- break;
-- }
++
+int sqlcipher_codec_ctx_set_flag(codec_ctx *ctx, unsigned int flag) {
+ ctx->write_ctx->flags |= flag;
+ ctx->read_ctx->flags |= flag;
+ return SQLITE_OK;
+}
-
-- default: {
-- rc = SQLITE_ERROR;
-- }
-- }
-- sqlite3_mutex_leave(db->mutex);
-- return rc;
++
+int sqlcipher_codec_ctx_unset_flag(codec_ctx *ctx, unsigned int flag) {
+ ctx->write_ctx->flags &= ~flag;
+ ctx->read_ctx->flags &= ~flag;
+ return SQLITE_OK;
- }
-
--/************** End of status.c **********************************************/
--/************** Begin file date.c ********************************************/
--/*
--** 2003 October 31
--**
--** The author disclaims copyright to this source code. In place of
--** a legal notice, here is a blessing:
--**
--** May you do good and not evil.
--** May you find forgiveness for yourself and forgive others.
--** May you share freely, never taking more than you give.
--**
--*************************************************************************
--** This file contains the C functions that implement date and time
--** functions for SQLite.
--**
--** There is only one exported symbol in this file - the function
--** sqlite3RegisterDateTimeFunctions() found at the bottom of the file.
--** All other code has file scope.
--**
--** SQLite processes all times and dates as Julian Day numbers. The
--** dates and times are stored as the number of days since noon
--** in Greenwich on November 24, 4714 B.C. according to the Gregorian
--** calendar system.
--**
--** 1970-01-01 00:00:00 is JD 2440587.5
--** 2000-01-01 00:00:00 is JD 2451544.5
--**
--** This implemention requires years to be expressed as a 4-digit number
--** which means that only dates between 0000-01-01 and 9999-12-31 can
--** be represented, even though julian day numbers allow a much wider
--** range of dates.
--**
--** The Gregorian calendar system is used for all dates and times,
--** even those that predate the Gregorian calendar. Historians usually
--** use the Julian calendar for dates prior to 1582-10-15 and for some
--** dates afterwards, depending on locale. Beware of this difference.
--**
--** The conversion algorithms are implemented based on descriptions
--** in the following text:
--**
--** Jean Meeus
--** Astronomical Algorithms, 2nd Edition, 1998
--** ISBM 0-943396-61-1
--** Willmann-Bell, Inc
--** Richmond, Virginia (USA)
--*/
--/* #include <stdlib.h> */
--/* #include <assert.h> */
--#include <time.h>
++}
++
+int sqlcipher_codec_ctx_get_flag(codec_ctx *ctx, unsigned int flag, int for_ctx) {
+ cipher_ctx * c_ctx = for_ctx ? ctx->write_ctx : ctx->read_ctx;
+ return (c_ctx->flags & flag) != 0;
+}
-
--#ifndef SQLITE_OMIT_DATETIME_FUNCS
++
+void sqlcipher_codec_ctx_set_error(codec_ctx *ctx, int error) {
+ CODEC_TRACE(("sqlcipher_codec_ctx_set_error: ctx=%p, error=%d\n", ctx, error));
+ sqlite3pager_sqlite3PagerSetError(ctx->pBt->pBt->pPager, error);
+ ctx->pBt->pBt->db->errCode = error;
+}
-
++
+int sqlcipher_codec_ctx_get_reservesize(codec_ctx *ctx) {
+ return ctx->read_ctx->reserve_sz;
+}
-
--/*
--** A structure for holding a single date and time.
--*/
--typedef struct DateTime DateTime;
--struct DateTime {
-- sqlite3_int64 iJD; /* The julian day number times 86400000 */
-- int Y, M, D; /* Year, month, and day */
-- int h, m; /* Hour and minutes */
-- int tz; /* Timezone offset in minutes */
-- double s; /* Seconds */
-- char validYMD; /* True (1) if Y,M,D are valid */
-- char validHMS; /* True (1) if h,m,s are valid */
-- char validJD; /* True (1) if iJD is valid */
-- char validTZ; /* True (1) if tz is valid */
--};
++
+void* sqlcipher_codec_ctx_get_data(codec_ctx *ctx) {
+ return ctx->buffer;
+}
-
++
+void* sqlcipher_codec_ctx_get_kdf_salt(codec_ctx *ctx) {
+ return ctx->kdf_salt;
+}
-
--/*
--** Convert zDate into one or more integers. Additional arguments
--** come in groups of 5 as follows:
--**
--** N number of digits in the integer
--** min minimum allowed value of the integer
--** max maximum allowed value of the integer
--** nextC first character after the integer
--** pVal where to write the integers value.
--**
--** Conversions continue until one with nextC==0 is encountered.
--** The function returns the number of successful conversions.
--*/
--static int getDigits(const char *zDate, ...){
-- va_list ap;
-- int val;
-- int N;
-- int min;
-- int max;
-- int nextC;
-- int *pVal;
-- int cnt = 0;
-- va_start(ap, zDate);
-- do{
-- N = va_arg(ap, int);
-- min = va_arg(ap, int);
-- max = va_arg(ap, int);
-- nextC = va_arg(ap, int);
-- pVal = va_arg(ap, int*);
-- val = 0;
-- while( N-- ){
-- if( !sqlite3Isdigit(*zDate) ){
-- goto end_getDigits;
-- }
-- val = val*10 + *zDate - '0';
-- zDate++;
-- }
-- if( val<min || val>max || (nextC!=0 && nextC!=*zDate) ){
-- goto end_getDigits;
-- }
-- *pVal = val;
-- zDate++;
-- cnt++;
-- }while( nextC );
--end_getDigits:
-- va_end(ap);
-- return cnt;
-+void sqlcipher_codec_get_pass(codec_ctx *ctx, void **zKey, int *nKey) {
-+ *zKey = ctx->read_ctx->pass;
-+ *nKey = ctx->read_ctx->pass_sz;
- }
-
--/*
--** Parse a timezone extension on the end of a date-time.
--** The extension is of the form:
--**
--** (+/-)HH:MM
--**
--** Or the "zulu" notation:
--**
--** Z
--**
--** If the parse is successful, write the number of minutes
--** of change in p->tz and return 0. If a parser error occurs,
--** return non-zero.
--**
--** A missing specifier is not considered an error.
--*/
--static int parseTimezone(const char *zDate, DateTime *p){
-- int sgn = 0;
-- int nHr, nMn;
-- int c;
-- while( sqlite3Isspace(*zDate) ){ zDate++; }
-- p->tz = 0;
-- c = *zDate;
-- if( c=='-' ){
-- sgn = -1;
-- }else if( c=='+' ){
-- sgn = +1;
-- }else if( c=='Z' || c=='z' ){
-- zDate++;
-- goto zulu_time;
-- }else{
-- return c!=0;
-- }
-- zDate++;
-- if( getDigits(zDate, 2, 0, 14, ':', &nHr, 2, 0, 59, 0, &nMn)!=2 ){
-- return 1;
++
++void sqlcipher_codec_get_keyspec(codec_ctx *ctx, void **zKey, int *nKey) {
++ *zKey = ctx->read_ctx->keyspec;
++ *nKey = ctx->read_ctx->keyspec_sz;
++}
++
+int sqlcipher_codec_ctx_set_pagesize(codec_ctx *ctx, int size) {
+ /* attempt to free the existing page buffer */
+ sqlcipher_free(ctx->buffer,ctx->page_sz);
@@ -3549,15 +2499,10 @@
+ if(fd == NULL || sqlite3OsRead(fd, ctx->kdf_salt, FILE_HEADER_SZ, 0) != SQLITE_OK) {
+ /* if unable to read the bytes, generate random salt */
+ if(ctx->read_ctx->provider->random(ctx->read_ctx->provider_ctx, ctx->kdf_salt, FILE_HEADER_SZ) !=
SQLITE_OK) return SQLITE_ERROR;
- }
-- zDate += 5;
-- p->tz = sgn*(nMn + nHr*60);
--zulu_time:
-- while( sqlite3Isspace(*zDate) ){ zDate++; }
-- return *zDate!=0;
++ }
+
+ if((rc = sqlcipher_codec_ctx_set_cipher(ctx, CIPHER, 0)) != SQLITE_OK) return rc;
-+ if((rc = sqlcipher_codec_ctx_set_kdf_iter(ctx, PBKDF2_ITER, 0)) != SQLITE_OK) return rc;
++ if((rc = sqlcipher_codec_ctx_set_kdf_iter(ctx, default_kdf_iter, 0)) != SQLITE_OK) return rc;
+ if((rc = sqlcipher_codec_ctx_set_fast_kdf_iter(ctx, FAST_PBKDF2_ITER, 0)) != SQLITE_OK) return rc;
+ if((rc = sqlcipher_codec_ctx_set_pass(ctx, zKey, nKey, 0)) != SQLITE_OK) return rc;
+
@@ -3620,26 +2565,9 @@
+ in_sz, (unsigned char*) &pgno_raw,
+ sizeof(pgno), out);
+ return SQLITE_OK;
- }
-
- /*
--** Parse times of the form HH:MM or HH:MM:SS or HH:MM:SS.FFFF.
--** The HH, MM, and SS must each be exactly 2 digits. The
--** fractional seconds FFFF can be one or more digits.
--**
--** Return 1 if there is a parsing error and 0 on success.
--*/
--static int parseHhMmSs(const char *zDate, DateTime *p){
-- int h, m, s;
-- double ms = 0.0;
-- if( getDigits(zDate, 2, 0, 24, ':', &h, 2, 0, 59, 0, &m)!=2 ){
-- return 1;
-- }
-- zDate += 5;
-- if( *zDate==':' ){
-- zDate++;
-- if( getDigits(zDate, 2, 0, 59, 0, &s)!=1 ){
-- return 1;
++}
++
++/*
+ * ctx - codec context
+ * pgno - page number in database
+ * size - size in bytes of input and output buffers
@@ -3680,20 +2608,12 @@
+ memcpy(iv_out, iv_in, c_ctx->iv_sz); /* copy the iv from the input to output buffer */
+ }
+
-+ if((c_ctx->flags & CIPHER_FLAG_HMAC) && (mode == CIPHER_DECRYPT)) {
++ if((c_ctx->flags & CIPHER_FLAG_HMAC) && (mode == CIPHER_DECRYPT) && !ctx->skip_read_hmac) {
+ if(sqlcipher_page_hmac(c_ctx, pgno, in, size + c_ctx->iv_sz, hmac_out) != SQLITE_OK) {
+ sqlcipher_memset(out, 0, page_sz);
+ CODEC_TRACE(("codec_cipher: hmac operations failed for pgno=%d\n", pgno));
+ return SQLITE_ERROR;
- }
-- zDate += 2;
-- if( *zDate=='.' && sqlite3Isdigit(zDate[1]) ){
-- double rScale = 1.0;
-- zDate++;
-- while( sqlite3Isdigit(*zDate) ){
-- ms = ms*10.0 + *zDate - '0';
-- rScale *= 10.0;
-- zDate++;
++ }
+
+ CODEC_TRACE(("codec_cipher: comparing hmac on in=%p out=%p hmac_sz=%d\n", hmac_in, hmac_out,
c_ctx->hmac_sz));
+ if(sqlcipher_memcmp(hmac_in, hmac_out, c_ctx->hmac_sz) != 0) { /* the hmac check failed */
@@ -3712,45 +2632,30 @@
+ CODEC_TRACE(("codec_cipher: hmac check failed for pgno=%d returning SQLITE_ERROR\n", pgno));
+ sqlcipher_memset(out, 0, page_sz);
+ return SQLITE_ERROR;
- }
-- ms /= rScale;
- }
-- }else{
-- s = 0;
++ }
++ }
+ }
+
+ c_ctx->provider->cipher(c_ctx->provider_ctx, mode, c_ctx->key, c_ctx->key_sz, iv_out, in, size, out);
+
+ if((c_ctx->flags & CIPHER_FLAG_HMAC) && (mode == CIPHER_ENCRYPT)) {
+ sqlcipher_page_hmac(c_ctx, pgno, out_start, size + c_ctx->iv_sz, hmac_out);
- }
-- p->validJD = 0;
-- p->validHMS = 1;
-- p->h = h;
-- p->m = m;
-- p->s = s + ms;
-- if( parseTimezone(zDate, p) ) return 1;
-- p->validTZ = (p->tz!=0)?1:0;
-- return 0;
++ }
+
+ CODEC_HEXDUMP("codec_cipher: output page data", out_start, page_sz);
+
+ return SQLITE_OK;
- }
-
--/*
--** Convert from YYYY-MM-DD HH:MM:SS to julian day. We always assume
--** that the YYYY-MM-DD is according to the Gregorian calendar.
--**
--** Reference: Meeus page 61
--*/
--static void computeJD(DateTime *p){
-- int Y, M, D, A, B, X1, X2;
++}
++
+/**
+ * Derive an encryption key for a cipher contex key based on the raw password.
+ *
+ * If the raw key data is formated as x'hex' and there are exactly enough hex chars to fill
-+ * the key space (i.e 64 hex chars for a 256 bit key) then the key data will be used directly.
++ * the key (i.e 64 hex chars for a 256 bit key) then the key data will be used directly.
++
++ * Else, if the raw key data is formated as x'hex' and there are exactly enough hex chars to fill
++ * the key and the salt (i.e 92 hex chars for a 256 bit key and 16 byte salt) then it will be unpacked
++ * as the key followed by the salt.
+ *
+ * Otherwise, a key data will be derived using PBKDF2
+ *
@@ -3758,7 +2663,8 @@
+ * returns SQLITE_ERROR if the key could't be derived (for instance if pass is NULL or pass_sz is 0)
+ */
+static int sqlcipher_cipher_ctx_key_derive(codec_ctx *ctx, cipher_ctx *c_ctx) {
-+ CODEC_TRACE(("codec_key_derive: entered c_ctx->pass=%s, c_ctx->pass_sz=%d \
++ int rc;
++ CODEC_TRACE(("cipher_ctx_key_derive: entered c_ctx->pass=%s, c_ctx->pass_sz=%d \
+ ctx->kdf_salt=%p ctx->kdf_salt_sz=%d c_ctx->kdf_iter=%d \
+ ctx->hmac_kdf_salt=%p, c_ctx->fast_kdf_iter=%d c_ctx->key_sz=%d\n",
+ c_ctx->pass, c_ctx->pass_sz, ctx->kdf_salt, ctx->kdf_salt_sz, c_ctx->kdf_iter,
@@ -3766,38 +2672,32 @@
+
+
+ if(c_ctx->pass && c_ctx->pass_sz) { // if pass is not null
-+ if (c_ctx->pass_sz == ((c_ctx->key_sz*2)+3) && sqlite3StrNICmp(c_ctx->pass ,"x'", 2) == 0) {
++ if (c_ctx->pass_sz == ((c_ctx->key_sz * 2) + 3) && sqlite3StrNICmp((const char *)c_ctx->pass ,"x'", 2)
== 0) {
+ int n = c_ctx->pass_sz - 3; /* adjust for leading x' and tailing ' */
-+ const char *z = c_ctx->pass + 2; /* adjust lead offset of x' */
-+ CODEC_TRACE(("codec_key_derive: using raw key from hex\n"));
++ const unsigned char *z = c_ctx->pass + 2; /* adjust lead offset of x' */
++ CODEC_TRACE(("cipher_ctx_key_derive: using raw key from hex\n"));
+ cipher_hex2bin(z, n, c_ctx->key);
++ } else if (c_ctx->pass_sz == (((c_ctx->key_sz + ctx->kdf_salt_sz) * 2) + 3) && sqlite3StrNICmp((const
char *)c_ctx->pass ,"x'", 2) == 0) {
++ const unsigned char *z = c_ctx->pass + 2; /* adjust lead offset of x' */
++ CODEC_TRACE(("cipher_ctx_key_derive: using raw key from hex\n"));
++ cipher_hex2bin(z, (c_ctx->key_sz * 2), c_ctx->key);
++ cipher_hex2bin(z + (c_ctx->key_sz * 2), (ctx->kdf_salt_sz * 2), ctx->kdf_salt);
+ } else {
-+ CODEC_TRACE(("codec_key_derive: deriving key using full PBKDF2 with %d iterations\n",
c_ctx->kdf_iter));
-+ c_ctx->provider->kdf(c_ctx->provider_ctx, (const char*) c_ctx->pass, c_ctx->pass_sz,
++ CODEC_TRACE(("cipher_ctx_key_derive: deriving key using full PBKDF2 with %d iterations\n",
c_ctx->kdf_iter));
++ c_ctx->provider->kdf(c_ctx->provider_ctx, c_ctx->pass, c_ctx->pass_sz,
+ ctx->kdf_salt, ctx->kdf_salt_sz, c_ctx->kdf_iter,
+ c_ctx->key_sz, c_ctx->key);
-+
+ }
+
++ /* set the context "keyspec" containing the hex-formatted key and salt to be used when attaching
databases */
++ if((rc = sqlcipher_cipher_ctx_set_keyspec(c_ctx, c_ctx->key, c_ctx->key_sz, ctx->kdf_salt,
ctx->kdf_salt_sz)) != SQLITE_OK) return rc;
++
+ /* if this context is setup to use hmac checks, generate a seperate and different
+ key for HMAC. In this case, we use the output of the previous KDF as the input to
+ this KDF run. This ensures a distinct but predictable HMAC key. */
+ if(c_ctx->flags & CIPHER_FLAG_HMAC) {
+ int i;
-
-- if( p->validJD ) return;
-- if( p->validYMD ){
-- Y = p->Y;
-- M = p->M;
-- D = p->D;
-- }else{
-- Y = 2000; /* If no YMD specified, assume 2000-Jan-01 */
-- M = 1;
-- D = 1;
-- }
-- if( M<=2 ){
-- Y--;
-- M += 12;
++
+ /* start by copying the kdf key into the hmac salt slot
+ then XOR it with the fixed hmac salt defined at compile time
+ this ensures that the salt passed in to derive the hmac key, while
@@ -3808,11 +2708,11 @@
+ ctx->hmac_kdf_salt[i] ^= hmac_salt_mask;
+ }
+
-+ CODEC_TRACE(("codec_key_derive: deriving hmac key from encryption key using PBKDF2 with %d
iterations\n",
++ CODEC_TRACE(("cipher_ctx_key_derive: deriving hmac key from encryption key using PBKDF2 with %d
iterations\n",
+ c_ctx->fast_kdf_iter));
+
+
-+ c_ctx->provider->kdf(c_ctx->provider_ctx, (const char*)c_ctx->key, c_ctx->key_sz,
++ c_ctx->provider->kdf(c_ctx->provider_ctx, c_ctx->key, c_ctx->key_sz,
+ ctx->hmac_kdf_salt, ctx->kdf_salt_sz, c_ctx->fast_kdf_iter,
+ c_ctx->key_sz, c_ctx->hmac_key);
+ }
@@ -3827,29 +2727,21 @@
+ /* derive key on first use if necessary */
+ if(ctx->read_ctx->derive_key) {
+ if(sqlcipher_cipher_ctx_key_derive(ctx, ctx->read_ctx) != SQLITE_OK) return SQLITE_ERROR;
- }
-- A = Y/100;
-- B = 2 - A + (A/4);
-- X1 = 36525*(Y+4716)/100;
-- X2 = 306001*(M+1)/10000;
-- p->iJD = (sqlite3_int64)((X1 + X2 + D + B - 1524.5 ) * 86400000);
-- p->validJD = 1;
-- if( p->validHMS ){
-- p->iJD += p->h*3600000 + p->m*60000 + (sqlite3_int64)(p->s*1000);
-- if( p->validTZ ){
-- p->iJD -= p->tz*60000;
-- p->validYMD = 0;
-- p->validHMS = 0;
-- p->validTZ = 0;
++ }
+
+ if(ctx->write_ctx->derive_key) {
+ if(sqlcipher_cipher_ctx_cmp(ctx->write_ctx, ctx->read_ctx) == 0) {
-+ // the relevant parameters are the same, just copy read key
++ /* the relevant parameters are the same, just copy read key */
+ if(sqlcipher_cipher_ctx_copy(ctx->write_ctx, ctx->read_ctx) != SQLITE_OK) return SQLITE_ERROR;
+ } else {
+ if(sqlcipher_cipher_ctx_key_derive(ctx, ctx->write_ctx) != SQLITE_OK) return SQLITE_ERROR;
- }
- }
++ }
++ }
++
++ /* TODO: wipe and free passphrase after key derivation */
++ sqlcipher_cipher_ctx_set_pass(ctx->read_ctx, NULL, 0);
++ sqlcipher_cipher_ctx_set_pass(ctx->write_ctx, NULL, 0);
++
+ return SQLITE_OK;
+}
+
@@ -3863,22 +2755,227 @@
+
+const char* sqlcipher_codec_get_cipher_provider(codec_ctx *ctx) {
+ return ctx->read_ctx->provider->get_provider_name(ctx->read_ctx);
- }
-
++}
++
++
++static int sqlcipher_check_connection(const char *filename, char *key, int key_sz, char *sql, int
*user_version) {
++ int rc;
++ sqlite3 *db = NULL;
++ sqlite3_stmt *statement = NULL;
++ char *query_user_version = "PRAGMA user_version;";
++
++ rc = sqlite3_open(filename, &db);
++ if(rc != SQLITE_OK){
++ goto cleanup;
++ }
++ rc = sqlite3_key(db, key, key_sz);
++ if(rc != SQLITE_OK){
++ goto cleanup;
++ }
++ rc = sqlite3_exec(db, sql, NULL, NULL, NULL);
++ if(rc != SQLITE_OK){
++ goto cleanup;
++ }
++ rc = sqlite3_prepare(db, query_user_version, -1, &statement, NULL);
++ if(rc != SQLITE_OK){
++ goto cleanup;
++ }
++ rc = sqlite3_step(statement);
++ if(rc == SQLITE_ROW){
++ *user_version = sqlite3_column_int(statement, 0);
++ rc = SQLITE_OK;
++ }
++
++cleanup:
++ if(statement){
++ sqlite3_finalize(statement);
++ }
++ if(db){
++ sqlite3_close(db);
++ }
++ return rc;
++}
++
++int sqlcipher_codec_ctx_migrate(codec_ctx *ctx) {
++ u32 meta;
++ int rc = 0;
++ int command_idx = 0;
++ int password_sz;
++ int saved_flags;
++ int saved_nChange;
++ int saved_nTotalChange;
++ void (*saved_xTrace)(void*,const char*);
++ Db *pDb = 0;
++ sqlite3 *db = ctx->pBt->db;
++ const char *db_filename = sqlite3_db_filename(db, "main");
++ char *migrated_db_filename = sqlite3_mprintf("%s-migrated", db_filename);
++ char *pragma_hmac_off = "PRAGMA cipher_use_hmac = OFF;";
++ char *pragma_4k_kdf_iter = "PRAGMA kdf_iter = 4000;";
++ char *pragma_1x_and_4k;
++ char *set_user_version;
++ char *key;
++ int key_sz;
++ int user_version = 0;
++ int upgrade_1x_format = 0;
++ int upgrade_4k_format = 0;
++ static const unsigned char aCopy[] = {
++ BTREE_SCHEMA_VERSION, 1, /* Add one to the old schema cookie */
++ BTREE_DEFAULT_CACHE_SIZE, 0, /* Preserve the default page cache size */
++ BTREE_TEXT_ENCODING, 0, /* Preserve the text encoding */
++ BTREE_USER_VERSION, 0, /* Preserve the user version */
++ BTREE_APPLICATION_ID, 0, /* Preserve the application id */
++ };
++
++
++ key_sz = ctx->read_ctx->pass_sz + 1;
++ key = sqlcipher_malloc(key_sz);
++ memset(key, 0, key_sz);
++ memcpy(key, ctx->read_ctx->pass, ctx->read_ctx->pass_sz);
++
++ if(db_filename){
++ const char* commands[5];
++ char *attach_command = sqlite3_mprintf("ATTACH DATABASE '%s-migrated' as migrate KEY '%q';",
++ db_filename, key);
++
++ int rc = sqlcipher_check_connection(db_filename, key, key_sz, "", &user_version);
++ if(rc == SQLITE_OK){
++ CODEC_TRACE(("No upgrade required - exiting\n"));
++ goto exit;
++ }
++
++ // Version 2 - check for 4k with hmac format
++ rc = sqlcipher_check_connection(db_filename, key, key_sz, pragma_4k_kdf_iter, &user_version);
++ if(rc == SQLITE_OK) {
++ CODEC_TRACE(("Version 2 format found\n"));
++ upgrade_4k_format = 1;
++ }
++
++ // Version 1 - check both no hmac and 4k together
++ pragma_1x_and_4k = sqlite3_mprintf("%s%s", pragma_hmac_off,
++ pragma_4k_kdf_iter);
++ rc = sqlcipher_check_connection(db_filename, key, key_sz, pragma_1x_and_4k, &user_version);
++ sqlite3_free(pragma_1x_and_4k);
++ if(rc == SQLITE_OK) {
++ CODEC_TRACE(("Version 1 format found\n"));
++ upgrade_1x_format = 1;
++ upgrade_4k_format = 1;
++ }
++
++ if(upgrade_1x_format == 0 && upgrade_4k_format == 0) {
++ CODEC_TRACE(("Upgrade format not determined\n"));
++ goto handle_error;
++ }
++
++ set_user_version = sqlite3_mprintf("PRAGMA migrate.user_version = %d;", user_version);
++ commands[0] = upgrade_4k_format == 1 ? pragma_4k_kdf_iter : "";
++ commands[1] = upgrade_1x_format == 1 ? pragma_hmac_off : "";
++ commands[2] = attach_command;
++ commands[3] = "SELECT sqlcipher_export('migrate');";
++ commands[4] = set_user_version;
++
++ for(command_idx = 0; command_idx < ArraySize(commands); command_idx++){
++ const char *command = commands[command_idx];
++ if(strcmp(command, "") == 0){
++ continue;
++ }
++ rc = sqlite3_exec(db, command, NULL, NULL, NULL);
++ if(rc != SQLITE_OK){
++ break;
++ }
++ }
++ sqlite3_free(attach_command);
++ sqlite3_free(set_user_version);
++ sqlcipher_free(key, key_sz);
++
++ if(rc == SQLITE_OK){
++ Btree *pDest;
++ Btree *pSrc;
++ int i = 0;
++
++ if( !db->autoCommit ){
++ CODEC_TRACE(("cannot migrate from within a transaction"));
++ goto handle_error;
++ }
++ if( db->nVdbeActive>1 ){
++ CODEC_TRACE(("cannot migrate - SQL statements in progress"));
++ goto handle_error;
++ }
++
++ /* Save the current value of the database flags so that it can be
++ ** restored before returning. Then set the writable-schema flag, and
++ ** disable CHECK and foreign key constraints. */
++ saved_flags = db->flags;
++ saved_nChange = db->nChange;
++ saved_nTotalChange = db->nTotalChange;
++ saved_xTrace = db->xTrace;
++ db->flags |= SQLITE_WriteSchema | SQLITE_IgnoreChecks | SQLITE_PreferBuiltin;
++ db->flags &= ~(SQLITE_ForeignKeys | SQLITE_ReverseOrder);
++ db->xTrace = 0;
++
++ pDest = db->aDb[0].pBt;
++ pDb = &(db->aDb[db->nDb-1]);
++ pSrc = pDb->pBt;
++
++ rc = sqlite3_exec(db, "BEGIN;", NULL, NULL, NULL);
++ rc = sqlite3BtreeBeginTrans(pSrc, 2);
++ rc = sqlite3BtreeBeginTrans(pDest, 2);
++
++ assert( 1==sqlite3BtreeIsInTrans(pDest) );
++ assert( 1==sqlite3BtreeIsInTrans(pSrc) );
++
++ sqlite3CodecGetKey(db, db->nDb - 1, (void**)&key, &password_sz);
++ sqlite3CodecAttach(db, 0, key, password_sz);
++ sqlite3pager_get_codec(pDest->pBt->pPager, (void**)&ctx);
++
++ ctx->skip_read_hmac = 1;
++ for(i=0; i<ArraySize(aCopy); i+=2){
++ sqlite3BtreeGetMeta(pSrc, aCopy[i], &meta);
++ rc = sqlite3BtreeUpdateMeta(pDest, aCopy[i], meta+aCopy[i+1]);
++ if( NEVER(rc!=SQLITE_OK) ) goto handle_error;
++ }
++ rc = sqlite3BtreeCopyFile(pDest, pSrc);
++ ctx->skip_read_hmac = 0;
++ if( rc!=SQLITE_OK ) goto handle_error;
++ rc = sqlite3BtreeCommit(pDest);
++
++ db->flags = saved_flags;
++ db->nChange = saved_nChange;
++ db->nTotalChange = saved_nTotalChange;
++ db->xTrace = saved_xTrace;
++ db->autoCommit = 1;
++ if( pDb ){
++ sqlite3BtreeClose(pDb->pBt);
++ pDb->pBt = 0;
++ pDb->pSchema = 0;
++ }
++ sqlite3ResetAllSchemasOfConnection(db);
++ remove(migrated_db_filename);
++ sqlite3_free(migrated_db_filename);
++ } else {
++ CODEC_TRACE(("*** migration failure** \n\n"));
++ }
++
++ }
++ goto exit;
++
++ handle_error:
++ CODEC_TRACE(("An error occurred attempting to migrate the database\n"));
++ rc = SQLITE_ERROR;
++
++ exit:
++ return rc;
++}
++
++
+#endif
+/* END SQLCIPHER */
+
+/************** End of crypto_impl.c *****************************************/
+/************** Begin file crypto_libtomcrypt.c ******************************/
- /*
--** Parse dates of the form
++/*
+** SQLCipher
+** http://sqlcipher.net
- **
--** YYYY-MM-DD HH:MM:SS.FFF
--** YYYY-MM-DD HH:MM:SS
--** YYYY-MM-DD HH:MM
--** YYYY-MM-DD
++**
+** Copyright (c) 2008 - 2013, ZETETIC LLC
+** All rights reserved.
+**
@@ -3903,23 +3000,13 @@
+** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- **
--** Write the result into the DateTime structure and return 0
--** on success and 1 if the input string is not a well-formed
--** date.
- */
--static int parseYyyyMmDd(const char *zDate, DateTime *p){
-- int Y, M, D, neg;
++**
++*/
+/* BEGIN SQLCIPHER */
+#ifdef SQLITE_HAS_CODEC
+#ifdef SQLCIPHER_CRYPTO_LIBTOMCRYPT
+#include <tomcrypt.h>
-
-- if( zDate[0]=='-' ){
-- zDate++;
-- neg = 1;
-- }else{
-- neg = 0;
++
+typedef struct {
+ prng_state prng;
+} ltc_ctx;
@@ -3934,64 +3021,37 @@
+
+static int sqlcipher_ltc_activate(void *ctx) {
+ ltc_ctx *ltc = (ltc_ctx*)ctx;
-+ int random_buffer_sz = 32;
-+ unsigned char random_buffer[random_buffer_sz];
++ int random_buffer_sz = sizeof(char) * 32;
++ unsigned char *random_buffer = sqlcipher_malloc(random_buffer_sz);
++ sqlcipher_memset(random_buffer, 0, random_buffer_sz);
+
+ if(ltc_init == 0) {
+ if(register_prng(&fortuna_desc) != CRYPT_OK) return SQLITE_ERROR;
+ if(register_cipher(&rijndael_desc) != CRYPT_OK) return SQLITE_ERROR;
+ if(register_hash(&sha1_desc) != CRYPT_OK) return SQLITE_ERROR;
+ ltc_init = 1;
- }
-- if( getDigits(zDate,4,0,9999,'-',&Y,2,1,12,'-',&M,2,1,31,0,&D)!=3 ){
-- return 1;
++ }
+ if(fortuna_start(&(ltc->prng)) != CRYPT_OK) {
+ return SQLITE_ERROR;
- }
-- zDate += 10;
-- while( sqlite3Isspace(*zDate) || 'T'==*(u8*)zDate ){ zDate++; }
-- if( parseHhMmSs(zDate, p)==0 ){
-- /* We got the time */
-- }else if( *zDate==0 ){
-- p->validHMS = 0;
-- }else{
-- return 1;
-+ sqlite3_randomness(random_buffer_sz, &random_buffer);
++ }
++ sqlite3_randomness(random_buffer_sz, random_buffer);
+ if(sqlcipher_ltc_add_random(ctx, random_buffer, random_buffer_sz) != SQLITE_OK) {
+ return SQLITE_ERROR;
- }
-- p->validJD = 0;
-- p->validYMD = 1;
-- p->Y = neg ? -Y : Y;
-- p->M = M;
-- p->D = D;
-- if( p->validTZ ){
-- computeJD(p);
++ }
+ if(sqlcipher_ltc_add_random(ctx, <c, sizeof(ltc_ctx*)) != SQLITE_OK) {
+ return SQLITE_ERROR;
- }
-- return 0;
++ }
+ if(fortuna_ready(&(ltc->prng)) != CRYPT_OK) {
+ return SQLITE_ERROR;
+ }
++ sqlcipher_free(random_buffer, random_buffer_sz);
+ return SQLITE_OK;
- }
-
--/*
--** Set the time to the current time reported by the VFS.
--**
--** Return the number of errors.
--*/
--static int setDateTimeToCurrent(sqlite3_context *context, DateTime *p){
-- sqlite3 *db = sqlite3_context_db_handle(context);
-- if( sqlite3OsCurrentTimeInt64(db->pVfs, &p->iJD)==SQLITE_OK ){
-- p->validJD = 1;
-- return 0;
-- }else{
-- return 1;
++}
++
+static int sqlcipher_ltc_deactivate(void *ctx) {
+ ltc_ctx *ltc = (ltc_ctx*)ctx;
+ fortuna_done(&(ltc->prng));
++ return SQLITE_OK;
+}
+
+static const char* sqlcipher_ltc_get_provider_name(void *ctx) {
@@ -4004,43 +3064,11 @@
+
+ if((rc = fortuna_ready(&(ltc->prng))) != CRYPT_OK) {
+ return SQLITE_ERROR;
- }
++ }
+ fortuna_read(buffer, length, &(ltc->prng));
+ return SQLITE_OK;
- }
-
--/*
--** Attempt to parse the given string into a Julian Day Number. Return
--** the number of errors.
--**
--** The following are acceptable forms for the input string:
--**
--** YYYY-MM-DD HH:MM:SS.FFF +/-HH:MM
--** DDDD.DD
--** now
--**
--** In the first form, the +/-HH:MM is always optional. The fractional
--** seconds extension (the ".FFF") is optional. The seconds portion
--** (":SS.FFF") is option. The year and date can be omitted as long
--** as there is a time string. The time string can be omitted as long
--** as there is a year and date.
--*/
--static int parseDateOrTime(
-- sqlite3_context *context,
-- const char *zDate,
-- DateTime *p
--){
-- double r;
-- if( parseYyyyMmDd(zDate,p)==0 ){
-- return 0;
-- }else if( parseHhMmSs(zDate, p)==0 ){
-- return 0;
-- }else if( sqlite3StrICmp(zDate,"now")==0){
-- return setDateTimeToCurrent(context, p);
-- }else if( sqlite3AtoF(zDate, &r, sqlite3Strlen30(zDate), SQLITE_UTF8) ){
-- p->iJD = (sqlite3_int64)(r*86400000.0 + 0.5);
-- p->validJD = 1;
-- return 0;
++}
++
+static int sqlcipher_ltc_hmac(void *ctx, unsigned char *hmac_key, int key_sz, unsigned char *in, int in_sz,
unsigned char *in2, int in2_sz, unsigned char *out) {
+ int rc, hash_idx;
+ hmac_state hmac;
@@ -4054,73 +3082,34 @@
+ return SQLITE_OK;
+}
+
-+static int sqlcipher_ltc_kdf(void *ctx, const char *pass, int pass_sz, unsigned char* salt, int salt_sz,
int workfactor, int key_sz, unsigned char *key) {
++static int sqlcipher_ltc_kdf(void *ctx, const unsigned char *pass, int pass_sz, unsigned char* salt, int
salt_sz, int workfactor, int key_sz, unsigned char *key) {
+ int rc, hash_idx;
-+ unsigned long outlen = key_sz;
-+ unsigned long random_buffer_sz = 256;
-+ char random_buffer[random_buffer_sz];
+ ltc_ctx *ltc = (ltc_ctx*)ctx;
++ unsigned long outlen = key_sz;
++ unsigned long random_buffer_sz = sizeof(char) * 256;
++ unsigned char *random_buffer = sqlcipher_malloc(random_buffer_sz);
++ sqlcipher_memset(random_buffer, 0, random_buffer_sz);
+
+ hash_idx = find_hash("sha1");
+ if((rc = pkcs_5_alg2(pass, pass_sz, salt, salt_sz,
+ workfactor, hash_idx, key, &outlen)) != CRYPT_OK) {
+ return SQLITE_ERROR;
- }
-- return 1;
++ }
+ if((rc = pkcs_5_alg2(key, key_sz, salt, salt_sz,
+ 1, hash_idx, random_buffer, &random_buffer_sz)) != CRYPT_OK) {
+ return SQLITE_ERROR;
+ }
+ sqlcipher_ltc_add_random(ctx, random_buffer, random_buffer_sz);
++ sqlcipher_free(random_buffer, random_buffer_sz);
+ return SQLITE_OK;
- }
-
--/*
--** Compute the Year, Month, and Day from the julian day number.
--*/
--static void computeYMD(DateTime *p){
-- int Z, A, B, C, D, E, X1;
-- if( p->validYMD ) return;
-- if( !p->validJD ){
-- p->Y = 2000;
-- p->M = 1;
-- p->D = 1;
-- }else{
-- Z = (int)((p->iJD + 43200000)/86400000);
-- A = (int)((Z - 1867216.25)/36524.25);
-- A = Z + 1 + A - (A/4);
-- B = A + 1524;
-- C = (int)((B - 122.1)/365.25);
-- D = (36525*C)/100;
-- E = (int)((B-D)/30.6001);
-- X1 = (int)(30.6001*E);
-- p->D = B - D - X1;
-- p->M = E<14 ? E-1 : E-13;
-- p->Y = p->M>2 ? C - 4716 : C - 4715;
-- }
-- p->validYMD = 1;
++}
++
+static const char* sqlcipher_ltc_get_cipher(void *ctx) {
+ return "rijndael";
- }
-
--/*
--** Compute the Hour, Minute, and Seconds from the julian day number.
--*/
--static void computeHMS(DateTime *p){
-- int s;
-- if( p->validHMS ) return;
-- computeJD(p);
-- s = (int)((p->iJD + 43200000) % 86400000);
-- p->s = s/1000.0;
-- s = (int)p->s;
-- p->s -= s;
-- p->h = s/3600;
-- s -= p->h*3600;
-- p->m = s/60;
-- p->s += s - p->m*60;
-- p->validHMS = 1;
++}
++
+static int sqlcipher_ltc_cipher(void *ctx, int mode, unsigned char *key, int key_sz, unsigned char *iv,
unsigned char *in, int in_sz, unsigned char *out) {
-+ int rc, cipher_idx, hash_idx;
++ int rc, cipher_idx;
+ symmetric_CBC cbc;
+
+ if((cipher_idx = find_cipher(sqlcipher_ltc_get_cipher(ctx))) == -1) return SQLITE_ERROR;
@@ -4129,188 +3118,48 @@
+ if(rc != CRYPT_OK) return SQLITE_ERROR;
+ cbc_done(&cbc);
+ return SQLITE_OK;
- }
-
--/*
--** Compute both YMD and HMS
--*/
--static void computeYMD_HMS(DateTime *p){
-- computeYMD(p);
-- computeHMS(p);
++}
++
+static int sqlcipher_ltc_set_cipher(void *ctx, const char *cipher_name) {
+ return SQLITE_OK;
- }
-
--/*
--** Clear the YMD and HMS and the TZ
--*/
--static void clearYMD_HMS_TZ(DateTime *p){
-- p->validYMD = 0;
-- p->validHMS = 0;
-- p->validTZ = 0;
++}
++
+static int sqlcipher_ltc_get_key_sz(void *ctx) {
+ int cipher_idx = find_cipher(sqlcipher_ltc_get_cipher(ctx));
+ return cipher_descriptor[cipher_idx].max_key_length;
- }
-
--/*
--** On recent Windows platforms, the localtime_s() function is available
--** as part of the "Secure CRT". It is essentially equivalent to
--** localtime_r() available under most POSIX platforms, except that the
--** order of the parameters is reversed.
--**
--** See http://msdn.microsoft.com/en-us/library/a442x3ye(VS.80).aspx.
--**
--** If the user has not indicated to use localtime_r() or localtime_s()
--** already, check for an MSVC build environment that provides
--** localtime_s().
--*/
--#if !defined(HAVE_LOCALTIME_R) && !defined(HAVE_LOCALTIME_S) && \
-- defined(_MSC_VER) && defined(_CRT_INSECURE_DEPRECATE)
--#define HAVE_LOCALTIME_S 1
--#endif
++}
++
+static int sqlcipher_ltc_get_iv_sz(void *ctx) {
+ int cipher_idx = find_cipher(sqlcipher_ltc_get_cipher(ctx));
+ return cipher_descriptor[cipher_idx].block_length;
+}
-
--#ifndef SQLITE_OMIT_LOCALTIME
--/*
--** The following routine implements the rough equivalent of localtime_r()
--** using whatever operating-system specific localtime facility that
--** is available. This routine returns 0 on success and
--** non-zero on any kind of error.
--**
--** If the sqlite3GlobalConfig.bLocaltimeFault variable is true then this
--** routine will always fail.
--*/
--static int osLocaltime(time_t *t, struct tm *pTm){
-- int rc;
--#if (!defined(HAVE_LOCALTIME_R) || !HAVE_LOCALTIME_R) \
-- && (!defined(HAVE_LOCALTIME_S) || !HAVE_LOCALTIME_S)
-- struct tm *pX;
--#if SQLITE_THREADSAFE>0
-- sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
--#endif
-- sqlite3_mutex_enter(mutex);
-- pX = localtime(t);
--#ifndef SQLITE_OMIT_BUILTIN_TEST
-- if( sqlite3GlobalConfig.bLocaltimeFault ) pX = 0;
--#endif
-- if( pX ) *pTm = *pX;
-- sqlite3_mutex_leave(mutex);
-- rc = pX==0;
--#else
--#ifndef SQLITE_OMIT_BUILTIN_TEST
-- if( sqlite3GlobalConfig.bLocaltimeFault ) return 1;
--#endif
--#if defined(HAVE_LOCALTIME_R) && HAVE_LOCALTIME_R
-- rc = localtime_r(t, pTm)==0;
--#else
-- rc = localtime_s(pTm, t);
--#endif /* HAVE_LOCALTIME_R */
--#endif /* HAVE_LOCALTIME_R || HAVE_LOCALTIME_S */
-- return rc;
++
+static int sqlcipher_ltc_get_block_sz(void *ctx) {
+ int cipher_idx = find_cipher(sqlcipher_ltc_get_cipher(ctx));
+ return cipher_descriptor[cipher_idx].block_length;
- }
--#endif /* SQLITE_OMIT_LOCALTIME */
-
++}
++
+static int sqlcipher_ltc_get_hmac_sz(void *ctx) {
+ int hash_idx = find_hash("sha1");
+ return hash_descriptor[hash_idx].hashsize;
+}
-
--#ifndef SQLITE_OMIT_LOCALTIME
--/*
--** Compute the difference (in milliseconds) between localtime and UTC
--** (a.k.a. GMT) for the time value p where p is in UTC. If no error occurs,
--** return this value and set *pRc to SQLITE_OK.
--**
--** Or, if an error does occur, set *pRc to SQLITE_ERROR. The returned value
--** is undefined in this case.
--*/
--static sqlite3_int64 localtimeOffset(
-- DateTime *p, /* Date at which to calculate offset */
-- sqlite3_context *pCtx, /* Write error here if one occurs */
-- int *pRc /* OUT: Error code. SQLITE_OK or ERROR */
--){
-- DateTime x, y;
-- time_t t;
-- struct tm sLocal;
++
+static int sqlcipher_ltc_ctx_copy(void *target_ctx, void *source_ctx) {
+ memcpy(target_ctx, source_ctx, sizeof(ltc_ctx));
+ return SQLITE_OK;
+}
-
-- /* Initialize the contents of sLocal to avoid a compiler warning. */
-- memset(&sLocal, 0, sizeof(sLocal));
++
+static int sqlcipher_ltc_ctx_cmp(void *c1, void *c2) {
+ return 1;
+}
-
-- x = *p;
-- computeYMD_HMS(&x);
-- if( x.Y<1971 || x.Y>=2038 ){
-- x.Y = 2000;
-- x.M = 1;
-- x.D = 1;
-- x.h = 0;
-- x.m = 0;
-- x.s = 0.0;
-- } else {
-- int s = (int)(x.s + 0.5);
-- x.s = s;
-- }
-- x.tz = 0;
-- x.validJD = 0;
-- computeJD(&x);
-- t = (time_t)(x.iJD/1000 - 21086676*(i64)10000);
-- if( osLocaltime(&t, &sLocal) ){
-- sqlite3_result_error(pCtx, "local time unavailable", -1);
-- *pRc = SQLITE_ERROR;
-- return 0;
-- }
-- y.Y = sLocal.tm_year + 1900;
-- y.M = sLocal.tm_mon + 1;
-- y.D = sLocal.tm_mday;
-- y.h = sLocal.tm_hour;
-- y.m = sLocal.tm_min;
-- y.s = sLocal.tm_sec;
-- y.validYMD = 1;
-- y.validHMS = 1;
-- y.validJD = 0;
-- y.validTZ = 0;
-- computeJD(&y);
-- *pRc = SQLITE_OK;
-- return y.iJD - x.iJD;
++
+static int sqlcipher_ltc_ctx_init(void **ctx) {
+ *ctx = sqlcipher_malloc(sizeof(ltc_ctx));
+ if(*ctx == NULL) return SQLITE_NOMEM;
+ sqlcipher_ltc_activate(*ctx);
+ return SQLITE_OK;
- }
--#endif /* SQLITE_OMIT_LOCALTIME */
-
--/*
--** Process a modifier to a date-time stamp. The modifiers are
--** as follows:
--**
--** NNN days
--** NNN hours
--** NNN minutes
--** NNN.NNNN seconds
--** NNN months
--** NNN years
--** start of month
--** start of year
--** start of week
--** start of day
--** weekday N
--** unixepoch
--** localtime
--** utc
++}
++
+static int sqlcipher_ltc_ctx_free(void **ctx) {
+ sqlcipher_ltc_deactivate(&ctx);
+ sqlcipher_free(*ctx, sizeof(ltc_ctx));
@@ -4336,6 +3185,7 @@
+ p->ctx_init = sqlcipher_ltc_ctx_init;
+ p->ctx_free = sqlcipher_ltc_ctx_free;
+ p->add_random = sqlcipher_ltc_add_random;
++ return SQLITE_OK;
+}
+
+#endif
@@ -4372,20 +3222,8 @@
+** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- **
--** Return 0 on success and 1 if there is any kind of error. If the error
--** is in a system call (i.e. localtime()), then an error message is written
--** to context pCtx. If the error is an unrecognized modifier, no error is
--** written to pCtx.
- */
--static int parseModifier(sqlite3_context *pCtx, const char *zMod, DateTime *p){
-- int rc = 1;
-- int n;
-- double r;
-- char *z, zBuf[30];
-- z = zBuf;
-- for(n=0; n<ArraySize(zBuf)-1 && zMod[n]; n++){
-- z[n] = (char)sqlite3UpperToLower[(u8)zMod[n]];
++**
++*/
+/* BEGIN SQLCIPHER */
+#ifdef SQLITE_HAS_CODEC
+#ifdef SQLCIPHER_CRYPTO_OPENSSL
@@ -4441,47 +3279,8 @@
+ if(openssl_rand_mutex == NULL) {
+ /* allocate a mutex to guard against concurrent calls to RAND_bytes() */
+ openssl_rand_mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
- }
-- z[n] = 0;
-- switch( z[0] ){
--#ifndef SQLITE_OMIT_LOCALTIME
-- case 'l': {
-- /* localtime
-- **
-- ** Assuming the current time value is UTC (a.k.a. GMT), shift it to
-- ** show local time.
-- */
-- if( strcmp(z, "localtime")==0 ){
-- computeJD(p);
-- p->iJD += localtimeOffset(p, pCtx, &rc);
-- clearYMD_HMS_TZ(p);
-- }
-- break;
-- }
- #endif
-- case 'u': {
-- /*
-- ** unixepoch
-- **
-- ** Treat the current value of p->iJD as the number of
-- ** seconds since 1970. Convert to a real julian day number.
-- */
-- if( strcmp(z, "unixepoch")==0 && p->validJD ){
-- p->iJD = (p->iJD + 43200)/86400 + 21086676*(i64)10000000;
-- clearYMD_HMS_TZ(p);
-- rc = 0;
-- }
--#ifndef SQLITE_OMIT_LOCALTIME
-- else if( strcmp(z, "utc")==0 ){
-- sqlite3_int64 c1;
-- computeJD(p);
-- c1 = localtimeOffset(p, pCtx, &rc);
-- if( rc==SQLITE_OK ){
-- p->iJD -= c1;
-- clearYMD_HMS_TZ(p);
-- p->iJD += c1 - localtimeOffset(p, pCtx, &rc);
-- }
-- }
++ }
++#endif
+
+ openssl_init_count++;
+ sqlite3_mutex_leave(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER));
@@ -4507,196 +3306,16 @@
+#ifndef SQLCIPHER_OPENSSL_NO_MUTEX_RAND
+ sqlite3_mutex_free(openssl_rand_mutex);
+ openssl_rand_mutex = NULL;
- #endif
-- break;
-- }
-- case 'w': {
-- /*
-- ** weekday N
-- **
-- ** Move the date to the same time on the next occurrence of
-- ** weekday N where 0==Sunday, 1==Monday, and so forth. If the
-- ** date is already on the appropriate weekday, this is a no-op.
-- */
-- if( strncmp(z, "weekday ", 8)==0
-- && sqlite3AtoF(&z[8], &r, sqlite3Strlen30(&z[8]), SQLITE_UTF8)
-- && (n=(int)r)==r && n>=0 && r<7 ){
-- sqlite3_int64 Z;
-- computeYMD_HMS(p);
-- p->validTZ = 0;
-- p->validJD = 0;
-- computeJD(p);
-- Z = ((p->iJD + 129600000)/86400000) % 7;
-- if( Z>n ) Z -= 7;
-- p->iJD += (n - Z)*86400000;
-- clearYMD_HMS_TZ(p);
-- rc = 0;
-- }
-- break;
-- }
-- case 's': {
-- /*
-- ** start of TTTTT
-- **
-- ** Move the date backwards to the beginning of the current day,
-- ** or month or year.
-- */
-- if( strncmp(z, "start of ", 9)!=0 ) break;
-- z += 9;
-- computeYMD(p);
-- p->validHMS = 1;
-- p->h = p->m = 0;
-- p->s = 0.0;
-- p->validTZ = 0;
-- p->validJD = 0;
-- if( strcmp(z,"month")==0 ){
-- p->D = 1;
-- rc = 0;
-- }else if( strcmp(z,"year")==0 ){
-- computeYMD(p);
-- p->M = 1;
-- p->D = 1;
-- rc = 0;
-- }else if( strcmp(z,"day")==0 ){
-- rc = 0;
-- }
-- break;
-- }
-- case '+':
-- case '-':
-- case '0':
-- case '1':
-- case '2':
-- case '3':
-- case '4':
-- case '5':
-- case '6':
-- case '7':
-- case '8':
-- case '9': {
-- double rRounder;
-- for(n=1; z[n] && z[n]!=':' && !sqlite3Isspace(z[n]); n++){}
-- if( !sqlite3AtoF(z, &r, n, SQLITE_UTF8) ){
-- rc = 1;
-- break;
-- }
-- if( z[n]==':' ){
-- /* A modifier of the form (+|-)HH:MM:SS.FFF adds (or subtracts) the
-- ** specified number of hours, minutes, seconds, and fractional seconds
-- ** to the time. The ".FFF" may be omitted. The ":SS.FFF" may be
-- ** omitted.
-- */
-- const char *z2 = z;
-- DateTime tx;
-- sqlite3_int64 day;
-- if( !sqlite3Isdigit(*z2) ) z2++;
-- memset(&tx, 0, sizeof(tx));
-- if( parseHhMmSs(z2, &tx) ) break;
-- computeJD(&tx);
-- tx.iJD -= 43200000;
-- day = tx.iJD/86400000;
-- tx.iJD -= day*86400000;
-- if( z[0]=='-' ) tx.iJD = -tx.iJD;
-- computeJD(p);
-- clearYMD_HMS_TZ(p);
-- p->iJD += tx.iJD;
-- rc = 0;
-- break;
-- }
-- z += n;
-- while( sqlite3Isspace(*z) ) z++;
-- n = sqlite3Strlen30(z);
-- if( n>10 || n<3 ) break;
-- if( z[n-1]=='s' ){ z[n-1] = 0; n--; }
-- computeJD(p);
-- rc = 0;
-- rRounder = r<0 ? -0.5 : +0.5;
-- if( n==3 && strcmp(z,"day")==0 ){
-- p->iJD += (sqlite3_int64)(r*86400000.0 + rRounder);
-- }else if( n==4 && strcmp(z,"hour")==0 ){
-- p->iJD += (sqlite3_int64)(r*(86400000.0/24.0) + rRounder);
-- }else if( n==6 && strcmp(z,"minute")==0 ){
-- p->iJD += (sqlite3_int64)(r*(86400000.0/(24.0*60.0)) + rRounder);
-- }else if( n==6 && strcmp(z,"second")==0 ){
-- p->iJD += (sqlite3_int64)(r*(86400000.0/(24.0*60.0*60.0)) + rRounder);
-- }else if( n==5 && strcmp(z,"month")==0 ){
-- int x, y;
-- computeYMD_HMS(p);
-- p->M += (int)r;
-- x = p->M>0 ? (p->M-1)/12 : (p->M-12)/12;
-- p->Y += x;
-- p->M -= x*12;
-- p->validJD = 0;
-- computeJD(p);
-- y = (int)r;
-- if( y!=r ){
-- p->iJD += (sqlite3_int64)((r - y)*30.0*86400000.0 + rRounder);
-- }
-- }else if( n==4 && strcmp(z,"year")==0 ){
-- int y = (int)r;
-- computeYMD_HMS(p);
-- p->Y += y;
-- p->validJD = 0;
-- computeJD(p);
-- if( y!=r ){
-- p->iJD += (sqlite3_int64)((r - y)*365.0*86400000.0 + rRounder);
-- }
-- }else{
-- rc = 1;
-- }
-- clearYMD_HMS_TZ(p);
-- break;
-- }
-- default: {
-- break;
-- }
- }
-- return rc;
++#endif
++ }
+ sqlite3_mutex_leave(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER));
+ return SQLITE_OK;
- }
-
--/*
--** Process time function arguments. argv[0] is a date-time stamp.
--** argv[1] and following are modifiers. Parse them all and write
--** the resulting time into the DateTime structure p. Return 0
--** on success and 1 if there are any errors.
--**
--** If there are zero parameters (if even argv[0] is undefined)
--** then assume a default value of "now" for argv[0].
--*/
--static int isDate(
-- sqlite3_context *context,
-- int argc,
-- sqlite3_value **argv,
-- DateTime *p
--){
-- int i;
-- const unsigned char *z;
-- int eType;
-- memset(p, 0, sizeof(*p));
-- if( argc==0 ){
-- return setDateTimeToCurrent(context, p);
-- }
-- if( (eType = sqlite3_value_type(argv[0]))==SQLITE_FLOAT
-- || eType==SQLITE_INTEGER ){
-- p->iJD = (sqlite3_int64)(sqlite3_value_double(argv[0])*86400000.0 + 0.5);
-- p->validJD = 1;
-- }else{
-- z = sqlite3_value_text(argv[0]);
-- if( !z || parseDateOrTime(context, (char*)z, p) ){
-- return 1;
-- }
-- }
-- for(i=1; i<argc; i++){
-- z = sqlite3_value_text(argv[i]);
-- if( z==0 || parseModifier(context, (char*)z, p) ) return 1;
-- }
-- return 0;
++}
++
+static const char* sqlcipher_openssl_get_provider_name(void *ctx) {
+ return "openssl";
- }
-
++}
++
+/* generate a defined number of random bytes */
+static int sqlcipher_openssl_random (void *ctx, void *buffer, int length) {
+ int rc = 0;
@@ -4727,31 +3346,12 @@
+ HMAC_CTX_cleanup(&hctx);
+ return SQLITE_OK;
+}
-
--/*
--** The following routines implement the various date and time functions
--** of SQLite.
--*/
-+static int sqlcipher_openssl_kdf(void *ctx, const char *pass, int pass_sz, unsigned char* salt, int
salt_sz, int workfactor, int key_sz, unsigned char *key) {
-+ PKCS5_PBKDF2_HMAC_SHA1(pass, pass_sz, salt, salt_sz, workfactor, key_sz, key);
++
++static int sqlcipher_openssl_kdf(void *ctx, const unsigned char *pass, int pass_sz, unsigned char* salt,
int salt_sz, int workfactor, int key_sz, unsigned char *key) {
++ PKCS5_PBKDF2_HMAC_SHA1((const char *)pass, pass_sz, salt, salt_sz, workfactor, key_sz, key);
+ return SQLITE_OK;
+}
-
--/*
--** julianday( TIMESTRING, MOD, MOD, ...)
--**
--** Return the julian day number of the date specified in the arguments
--*/
--static void juliandayFunc(
-- sqlite3_context *context,
-- int argc,
-- sqlite3_value **argv
--){
-- DateTime x;
-- if( isDate(context, argc, argv, &x)==0 ){
-- computeJD(&x);
-- sqlite3_result_double(context, x.iJD/86400000.0);
-- }
++
+static int sqlcipher_openssl_cipher(void *ctx, int mode, unsigned char *key, int key_sz, unsigned char *iv,
unsigned char *in, int in_sz, unsigned char *out) {
+ EVP_CIPHER_CTX ectx;
+ int tmp_csz, csz;
@@ -4767,364 +3367,56 @@
+ EVP_CIPHER_CTX_cleanup(&ectx);
+ assert(in_sz == csz);
+ return SQLITE_OK;
- }
-
--/*
--** datetime( TIMESTRING, MOD, MOD, ...)
--**
--** Return YYYY-MM-DD HH:MM:SS
--*/
--static void datetimeFunc(
-- sqlite3_context *context,
-- int argc,
-- sqlite3_value **argv
--){
-- DateTime x;
-- if( isDate(context, argc, argv, &x)==0 ){
-- char zBuf[100];
-- computeYMD_HMS(&x);
-- sqlite3_snprintf(sizeof(zBuf), zBuf, "%04d-%02d-%02d %02d:%02d:%02d",
-- x.Y, x.M, x.D, x.h, x.m, (int)(x.s));
-- sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
-- }
++}
++
+static int sqlcipher_openssl_set_cipher(void *ctx, const char *cipher_name) {
+ openssl_ctx *o_ctx = (openssl_ctx *)ctx;
+ o_ctx->evp_cipher = (EVP_CIPHER *) EVP_get_cipherbyname(cipher_name);
+ return SQLITE_OK;
- }
-
--/*
--** time( TIMESTRING, MOD, MOD, ...)
--**
--** Return HH:MM:SS
--*/
--static void timeFunc(
-- sqlite3_context *context,
-- int argc,
-- sqlite3_value **argv
--){
-- DateTime x;
-- if( isDate(context, argc, argv, &x)==0 ){
-- char zBuf[100];
-- computeHMS(&x);
-- sqlite3_snprintf(sizeof(zBuf), zBuf, "%02d:%02d:%02d", x.h, x.m, (int)x.s);
-- sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
-- }
++}
++
+static const char* sqlcipher_openssl_get_cipher(void *ctx) {
+ return EVP_CIPHER_name(((openssl_ctx *)ctx)->evp_cipher);
- }
-
--/*
--** date( TIMESTRING, MOD, MOD, ...)
--**
--** Return YYYY-MM-DD
--*/
--static void dateFunc(
-- sqlite3_context *context,
-- int argc,
-- sqlite3_value **argv
--){
-- DateTime x;
-- if( isDate(context, argc, argv, &x)==0 ){
-- char zBuf[100];
-- computeYMD(&x);
-- sqlite3_snprintf(sizeof(zBuf), zBuf, "%04d-%02d-%02d", x.Y, x.M, x.D);
-- sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
-- }
++}
++
+static int sqlcipher_openssl_get_key_sz(void *ctx) {
+ return EVP_CIPHER_key_length(((openssl_ctx *)ctx)->evp_cipher);
- }
-
--/*
--** strftime( FORMAT, TIMESTRING, MOD, MOD, ...)
--**
--** Return a string described by FORMAT. Conversions as follows:
--**
--** %d day of month
--** %f ** fractional seconds SS.SSS
--** %H hour 00-24
--** %j day of year 000-366
--** %J ** Julian day number
--** %m month 01-12
--** %M minute 00-59
--** %s seconds since 1970-01-01
--** %S seconds 00-59
--** %w day of week 0-6 sunday==0
--** %W week of year 00-53
--** %Y year 0000-9999
--** %% %
--*/
--static void strftimeFunc(
-- sqlite3_context *context,
-- int argc,
-- sqlite3_value **argv
--){
-- DateTime x;
-- u64 n;
-- size_t i,j;
-- char *z;
-- sqlite3 *db;
-- const char *zFmt = (const char*)sqlite3_value_text(argv[0]);
-- char zBuf[100];
-- if( zFmt==0 || isDate(context, argc-1, argv+1, &x) ) return;
-- db = sqlite3_context_db_handle(context);
-- for(i=0, n=1; zFmt[i]; i++, n++){
-- if( zFmt[i]=='%' ){
-- switch( zFmt[i+1] ){
-- case 'd':
-- case 'H':
-- case 'm':
-- case 'M':
-- case 'S':
-- case 'W':
-- n++;
-- /* fall thru */
-- case 'w':
-- case '%':
-- break;
-- case 'f':
-- n += 8;
-- break;
-- case 'j':
-- n += 3;
-- break;
-- case 'Y':
-- n += 8;
-- break;
-- case 's':
-- case 'J':
-- n += 50;
-- break;
-- default:
-- return; /* ERROR. return a NULL */
-- }
-- i++;
-- }
-- }
-- testcase( n==sizeof(zBuf)-1 );
-- testcase( n==sizeof(zBuf) );
-- testcase( n==(u64)db->aLimit[SQLITE_LIMIT_LENGTH]+1 );
-- testcase( n==(u64)db->aLimit[SQLITE_LIMIT_LENGTH] );
-- if( n<sizeof(zBuf) ){
-- z = zBuf;
-- }else if( n>(u64)db->aLimit[SQLITE_LIMIT_LENGTH] ){
-- sqlite3_result_error_toobig(context);
-- return;
-- }else{
-- z = sqlite3DbMallocRaw(db, (int)n);
-- if( z==0 ){
-- sqlite3_result_error_nomem(context);
-- return;
-- }
-- }
-- computeJD(&x);
-- computeYMD_HMS(&x);
-- for(i=j=0; zFmt[i]; i++){
-- if( zFmt[i]!='%' ){
-- z[j++] = zFmt[i];
-- }else{
-- i++;
-- switch( zFmt[i] ){
-- case 'd': sqlite3_snprintf(3, &z[j],"%02d",x.D); j+=2; break;
-- case 'f': {
-- double s = x.s;
-- if( s>59.999 ) s = 59.999;
-- sqlite3_snprintf(7, &z[j],"%06.3f", s);
-- j += sqlite3Strlen30(&z[j]);
-- break;
-- }
-- case 'H': sqlite3_snprintf(3, &z[j],"%02d",x.h); j+=2; break;
-- case 'W': /* Fall thru */
-- case 'j': {
-- int nDay; /* Number of days since 1st day of year */
-- DateTime y = x;
-- y.validJD = 0;
-- y.M = 1;
-- y.D = 1;
-- computeJD(&y);
-- nDay = (int)((x.iJD-y.iJD+43200000)/86400000);
-- if( zFmt[i]=='W' ){
-- int wd; /* 0=Monday, 1=Tuesday, ... 6=Sunday */
-- wd = (int)(((x.iJD+43200000)/86400000)%7);
-- sqlite3_snprintf(3, &z[j],"%02d",(nDay+7-wd)/7);
-- j += 2;
-- }else{
-- sqlite3_snprintf(4, &z[j],"%03d",nDay+1);
-- j += 3;
-- }
-- break;
-- }
-- case 'J': {
-- sqlite3_snprintf(20, &z[j],"%.16g",x.iJD/86400000.0);
-- j+=sqlite3Strlen30(&z[j]);
-- break;
-- }
-- case 'm': sqlite3_snprintf(3, &z[j],"%02d",x.M); j+=2; break;
-- case 'M': sqlite3_snprintf(3, &z[j],"%02d",x.m); j+=2; break;
-- case 's': {
-- sqlite3_snprintf(30,&z[j],"%lld",
-- (i64)(x.iJD/1000 - 21086676*(i64)10000));
-- j += sqlite3Strlen30(&z[j]);
-- break;
-- }
-- case 'S': sqlite3_snprintf(3,&z[j],"%02d",(int)x.s); j+=2; break;
-- case 'w': {
-- z[j++] = (char)(((x.iJD+129600000)/86400000) % 7) + '0';
-- break;
-- }
-- case 'Y': {
-- sqlite3_snprintf(5,&z[j],"%04d",x.Y); j+=sqlite3Strlen30(&z[j]);
-- break;
-- }
-- default: z[j++] = '%'; break;
-- }
-- }
-- }
-- z[j] = 0;
-- sqlite3_result_text(context, z, -1,
-- z==zBuf ? SQLITE_TRANSIENT : SQLITE_DYNAMIC);
++}
++
+static int sqlcipher_openssl_get_iv_sz(void *ctx) {
+ return EVP_CIPHER_iv_length(((openssl_ctx *)ctx)->evp_cipher);
- }
-
--/*
--** current_time()
--**
--** This function returns the same value as time('now').
--*/
--static void ctimeFunc(
-- sqlite3_context *context,
-- int NotUsed,
-- sqlite3_value **NotUsed2
--){
-- UNUSED_PARAMETER2(NotUsed, NotUsed2);
-- timeFunc(context, 0, 0);
++}
++
+static int sqlcipher_openssl_get_block_sz(void *ctx) {
+ return EVP_CIPHER_block_size(((openssl_ctx *)ctx)->evp_cipher);
- }
-
--/*
--** current_date()
--**
--** This function returns the same value as date('now').
--*/
--static void cdateFunc(
-- sqlite3_context *context,
-- int NotUsed,
-- sqlite3_value **NotUsed2
--){
-- UNUSED_PARAMETER2(NotUsed, NotUsed2);
-- dateFunc(context, 0, 0);
++}
++
+static int sqlcipher_openssl_get_hmac_sz(void *ctx) {
+ return EVP_MD_size(EVP_sha1());
- }
-
--/*
--** current_timestamp()
--**
--** This function returns the same value as datetime('now').
--*/
--static void ctimestampFunc(
-- sqlite3_context *context,
-- int NotUsed,
-- sqlite3_value **NotUsed2
--){
-- UNUSED_PARAMETER2(NotUsed, NotUsed2);
-- datetimeFunc(context, 0, 0);
++}
++
+static int sqlcipher_openssl_ctx_copy(void *target_ctx, void *source_ctx) {
+ memcpy(target_ctx, source_ctx, sizeof(openssl_ctx));
+ return SQLITE_OK;
- }
--#endif /* !defined(SQLITE_OMIT_DATETIME_FUNCS) */
--
--#ifdef SQLITE_OMIT_DATETIME_FUNCS
--/*
--** If the library is compiled to omit the full-scale date and time
--** handling (to get a smaller binary), the following minimal version
--** of the functions current_time(), current_date() and current_timestamp()
--** are included instead. This is to support column declarations that
--** include "DEFAULT CURRENT_TIME" etc.
--**
--** This function uses the C-library functions time(), gmtime()
--** and strftime(). The format string to pass to strftime() is supplied
--** as the user-data for the function.
--*/
--static void currentTimeFunc(
-- sqlite3_context *context,
-- int argc,
-- sqlite3_value **argv
--){
-- time_t t;
-- char *zFormat = (char *)sqlite3_user_data(context);
-- sqlite3 *db;
-- sqlite3_int64 iT;
-- struct tm *pTm;
-- struct tm sNow;
-- char zBuf[20];
-
-- UNUSED_PARAMETER(argc);
-- UNUSED_PARAMETER(argv);
++}
++
+static int sqlcipher_openssl_ctx_cmp(void *c1, void *c2) {
+ return ((openssl_ctx *)c1)->evp_cipher == ((openssl_ctx *)c2)->evp_cipher;
+}
-
-- db = sqlite3_context_db_handle(context);
-- if( sqlite3OsCurrentTimeInt64(db->pVfs, &iT) ) return;
-- t = iT/1000 - 10000*(sqlite3_int64)21086676;
--#ifdef HAVE_GMTIME_R
-- pTm = gmtime_r(&t, &sNow);
--#else
-- sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
-- pTm = gmtime(&t);
-- if( pTm ) memcpy(&sNow, pTm, sizeof(sNow));
-- sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
--#endif
-- if( pTm ){
-- strftime(zBuf, 20, zFormat, &sNow);
-- sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
-- }
++
+static int sqlcipher_openssl_ctx_init(void **ctx) {
+ *ctx = sqlcipher_malloc(sizeof(openssl_ctx));
+ if(*ctx == NULL) return SQLITE_NOMEM;
+ sqlcipher_openssl_activate(*ctx);
+ return SQLITE_OK;
- }
--#endif
-
--/*
--** This function registered all of the above C functions as SQL
--** functions. This should be the only routine in this file with
--** external linkage.
--*/
--SQLITE_PRIVATE void sqlite3RegisterDateTimeFunctions(void){
-- static SQLITE_WSD FuncDef aDateTimeFuncs[] = {
--#ifndef SQLITE_OMIT_DATETIME_FUNCS
-- FUNCTION(julianday, -1, 0, 0, juliandayFunc ),
-- FUNCTION(date, -1, 0, 0, dateFunc ),
-- FUNCTION(time, -1, 0, 0, timeFunc ),
-- FUNCTION(datetime, -1, 0, 0, datetimeFunc ),
-- FUNCTION(strftime, -1, 0, 0, strftimeFunc ),
-- FUNCTION(current_time, 0, 0, 0, ctimeFunc ),
-- FUNCTION(current_timestamp, 0, 0, 0, ctimestampFunc),
-- FUNCTION(current_date, 0, 0, 0, cdateFunc ),
--#else
-- STR_FUNCTION(current_time, 0, "%H:%M:%S", 0, currentTimeFunc),
-- STR_FUNCTION(current_date, 0, "%Y-%m-%d", 0, currentTimeFunc),
-- STR_FUNCTION(current_timestamp, 0, "%Y-%m-%d %H:%M:%S", 0, currentTimeFunc),
--#endif
-- };
-- int i;
-- FuncDefHash *pHash = &GLOBAL(FuncDefHash, sqlite3GlobalFunctions);
-- FuncDef *aFunc = (FuncDef*)&GLOBAL(FuncDef, aDateTimeFuncs);
++}
++
+static int sqlcipher_openssl_ctx_free(void **ctx) {
+ sqlcipher_openssl_deactivate(*ctx);
+ sqlcipher_free(*ctx, sizeof(openssl_ctx));
+ return SQLITE_OK;
+}
-
-- for(i=0; i<ArraySize(aDateTimeFuncs); i++){
-- sqlite3FuncDefInsert(pHash, &aFunc[i]);
-- }
++
+int sqlcipher_openssl_setup(sqlcipher_provider *p) {
+ p->activate = sqlcipher_openssl_activate;
+ p->deactivate = sqlcipher_openssl_deactivate;
@@ -5145,57 +3437,18 @@
+ p->ctx_free = sqlcipher_openssl_ctx_free;
+ p->add_random = sqlcipher_openssl_add_random;
+ return SQLITE_OK;
- }
-
--/************** End of date.c ************************************************/
--/************** Begin file os.c **********************************************/
--/*
--** 2005 November 29
--**
--** The author disclaims copyright to this source code. In place of
--** a legal notice, here is a blessing:
--**
--** May you do good and not evil.
--** May you find forgiveness for yourself and forgive others.
--** May you share freely, never taking more than you give.
--**
--******************************************************************************
--**
--** This file contains OS interface code that is common to all
--** architectures.
--*/
--#define _SQLITE_OS_C_ 1
--#undef _SQLITE_OS_C_
++}
++
+#endif
+#endif
+/* END SQLCIPHER */
-
++
+/************** End of crypto_openssl.c **************************************/
+/************** Begin file crypto_cc.c ***************************************/
- /*
--** The default SQLite sqlite3_vfs implementations do not allocate
--** memory (actually, os_unix.c allocates a small amount of memory
--** from within OsOpen()), but some third-party implementations may.
--** So we test the effects of a malloc() failing and the sqlite3OsXXX()
--** function returning SQLITE_IOERR_NOMEM using the DO_OS_MALLOC_TEST macro.
--**
--** The following functions are instrumented for malloc() failure
--** testing:
++/*
+** SQLCipher
+** http://sqlcipher.net
- **
--** sqlite3OsRead()
--** sqlite3OsWrite()
--** sqlite3OsSync()
--** sqlite3OsFileSize()
--** sqlite3OsLock()
--** sqlite3OsCheckReservedLock()
--** sqlite3OsFileControl()
--** sqlite3OsShmMap()
--** sqlite3OsOpen()
--** sqlite3OsDelete()
--** sqlite3OsAccess()
--** sqlite3OsFullPathname()
++**
+** Copyright (c) 2008 - 2013, ZETETIC LLC
+** All rights reserved.
+**
@@ -5220,70 +3473,22 @@
+** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- **
- */
--#if defined(SQLITE_TEST)
--SQLITE_API int sqlite3_memdebug_vfs_oom_test = 1;
-- #define DO_OS_MALLOC_TEST(x) \
-- if (sqlite3_memdebug_vfs_oom_test && (!x || !sqlite3IsMemJournal(x))) { \
-- void *pTstAlloc = sqlite3Malloc(10); \
-- if (!pTstAlloc) return SQLITE_IOERR_NOMEM; \
-- sqlite3_free(pTstAlloc); \
-- }
--#else
-- #define DO_OS_MALLOC_TEST(x)
--#endif
++**
++*/
+/* BEGIN SQLCIPHER */
+#ifdef SQLITE_HAS_CODEC
+#ifdef SQLCIPHER_CRYPTO_CC
+#include <CommonCrypto/CommonCrypto.h>
+#include <Security/SecRandom.h>
-
--/*
--** The following routines are convenience wrappers around methods
--** of the sqlite3_file object. This is mostly just syntactic sugar. All
--** of this would be completely automatic if SQLite were coded using
--** C++ instead of plain old C.
--*/
--SQLITE_PRIVATE int sqlite3OsClose(sqlite3_file *pId){
-- int rc = SQLITE_OK;
-- if( pId->pMethods ){
-- rc = pId->pMethods->xClose(pId);
-- pId->pMethods = 0;
-- }
-- return rc;
--}
--SQLITE_PRIVATE int sqlite3OsRead(sqlite3_file *id, void *pBuf, int amt, i64 offset){
-- DO_OS_MALLOC_TEST(id);
-- return id->pMethods->xRead(id, pBuf, amt, offset);
--}
--SQLITE_PRIVATE int sqlite3OsWrite(sqlite3_file *id, const void *pBuf, int amt, i64 offset){
-- DO_OS_MALLOC_TEST(id);
-- return id->pMethods->xWrite(id, pBuf, amt, offset);
--}
--SQLITE_PRIVATE int sqlite3OsTruncate(sqlite3_file *id, i64 size){
-- return id->pMethods->xTruncate(id, size);
--}
--SQLITE_PRIVATE int sqlite3OsSync(sqlite3_file *id, int flags){
-- DO_OS_MALLOC_TEST(id);
-- return id->pMethods->xSync(id, flags);
--}
--SQLITE_PRIVATE int sqlite3OsFileSize(sqlite3_file *id, i64 *pSize){
-- DO_OS_MALLOC_TEST(id);
-- return id->pMethods->xFileSize(id, pSize);
++
+/* generate a defined number of random bytes */
+static int sqlcipher_cc_random (void *ctx, void *buffer, int length) {
+ return (SecRandomCopyBytes(kSecRandomDefault, length, (uint8_t *)buffer) == 0) ? SQLITE_OK : SQLITE_ERROR;
- }
--SQLITE_PRIVATE int sqlite3OsLock(sqlite3_file *id, int lockType){
-- DO_OS_MALLOC_TEST(id);
-- return id->pMethods->xLock(id, lockType);
++}
+
+static const char* sqlcipher_cc_get_provider_name(void *ctx) {
+ return "commoncrypto";
- }
--SQLITE_PRIVATE int sqlite3OsUnlock(sqlite3_file *id, int lockType){
-- return id->pMethods->xUnlock(id, lockType);
++}
+
+static int sqlcipher_cc_hmac(void *ctx, unsigned char *hmac_key, int key_sz, unsigned char *in, int in_sz,
unsigned char *in2, int in2_sz, unsigned char *out) {
+ CCHmacContext hmac_context;
@@ -5292,27 +3497,13 @@
+ CCHmacUpdate(&hmac_context, in2, in2_sz);
+ CCHmacFinal(&hmac_context, out);
+ return SQLITE_OK;
- }
--SQLITE_PRIVATE int sqlite3OsCheckReservedLock(sqlite3_file *id, int *pResOut){
-- DO_OS_MALLOC_TEST(id);
-- return id->pMethods->xCheckReservedLock(id, pResOut);
++}
+
-+static int sqlcipher_cc_kdf(void *ctx, const char *pass, int pass_sz, unsigned char* salt, int salt_sz, int
workfactor, int key_sz, unsigned char *key) {
-+ CCKeyDerivationPBKDF(kCCPBKDF2, pass, pass_sz, salt, salt_sz, kCCPRFHmacAlgSHA1, workfactor, key, key_sz);
++static int sqlcipher_cc_kdf(void *ctx, const unsigned char *pass, int pass_sz, unsigned char* salt, int
salt_sz, int workfactor, int key_sz, unsigned char *key) {
++ CCKeyDerivationPBKDF(kCCPBKDF2, (const char *)pass, pass_sz, salt, salt_sz, kCCPRFHmacAlgSHA1,
workfactor, key, key_sz);
+ return SQLITE_OK;
- }
-
--/*
--** Use sqlite3OsFileControl() when we are doing something that might fail
--** and we need to know about the failures. Use sqlite3OsFileControlHint()
--** when simply tossing information over the wall to the VFS and we do not
--** really care if the VFS receives and understands the information since it
--** is only a hint and can be safely ignored. The sqlite3OsFileControlHint()
--** routine has no return value since the return value would be meaningless.
--*/
--SQLITE_PRIVATE int sqlite3OsFileControl(sqlite3_file *id, int op, void *pArg){
-- DO_OS_MALLOC_TEST(id);
-- return id->pMethods->xFileControl(id, op, pArg);
++}
++
+static int sqlcipher_cc_cipher(void *ctx, int mode, unsigned char *key, int key_sz, unsigned char *iv,
unsigned char *in, int in_sz, unsigned char *out) {
+ CCCryptorRef cryptor;
+ size_t tmp_csz, csz;
@@ -5328,81 +3519,47 @@
+ assert(size == csz);
+
+ return SQLITE_OK;
- }
--SQLITE_PRIVATE void sqlite3OsFileControlHint(sqlite3_file *id, int op, void *pArg){
-- (void)id->pMethods->xFileControl(id, op, pArg);
++}
+
+static int sqlcipher_cc_set_cipher(void *ctx, const char *cipher_name) {
+ return SQLITE_OK;
- }
-
--SQLITE_PRIVATE int sqlite3OsSectorSize(sqlite3_file *id){
-- int (*xSectorSize)(sqlite3_file*) = id->pMethods->xSectorSize;
-- return (xSectorSize ? xSectorSize(id) : SQLITE_DEFAULT_SECTOR_SIZE);
++}
++
+static const char* sqlcipher_cc_get_cipher(void *ctx) {
+ return "aes-256-cbc";
- }
--SQLITE_PRIVATE int sqlite3OsDeviceCharacteristics(sqlite3_file *id){
-- return id->pMethods->xDeviceCharacteristics(id);
++}
+
+static int sqlcipher_cc_get_key_sz(void *ctx) {
+ return kCCKeySizeAES256;
- }
--SQLITE_PRIVATE int sqlite3OsShmLock(sqlite3_file *id, int offset, int n, int flags){
-- return id->pMethods->xShmLock(id, offset, n, flags);
++}
+
+static int sqlcipher_cc_get_iv_sz(void *ctx) {
+ return kCCBlockSizeAES128;
- }
--SQLITE_PRIVATE void sqlite3OsShmBarrier(sqlite3_file *id){
-- id->pMethods->xShmBarrier(id);
++}
+
+static int sqlcipher_cc_get_block_sz(void *ctx) {
+ return kCCBlockSizeAES128;
- }
--SQLITE_PRIVATE int sqlite3OsShmUnmap(sqlite3_file *id, int deleteFlag){
-- return id->pMethods->xShmUnmap(id, deleteFlag);
++}
+
+static int sqlcipher_cc_get_hmac_sz(void *ctx) {
+ return CC_SHA1_DIGEST_LENGTH;
- }
--SQLITE_PRIVATE int sqlite3OsShmMap(
-- sqlite3_file *id, /* Database file handle */
-- int iPage,
-- int pgsz,
-- int bExtend, /* True to extend file if necessary */
-- void volatile **pp /* OUT: Pointer to mapping */
--){
-- DO_OS_MALLOC_TEST(id);
-- return id->pMethods->xShmMap(id, iPage, pgsz, bExtend, pp);
++}
+
+static int sqlcipher_cc_ctx_copy(void *target_ctx, void *source_ctx) {
+ return SQLITE_OK;
- }
-
--#if SQLITE_MAX_MMAP_SIZE>0
--/* The real implementation of xFetch and xUnfetch */
--SQLITE_PRIVATE int sqlite3OsFetch(sqlite3_file *id, i64 iOff, int iAmt, void **pp){
-- DO_OS_MALLOC_TEST(id);
-- return id->pMethods->xFetch(id, iOff, iAmt, pp);
++}
++
+static int sqlcipher_cc_ctx_cmp(void *c1, void *c2) {
+ return SQLITE_OK;
- }
--SQLITE_PRIVATE int sqlite3OsUnfetch(sqlite3_file *id, i64 iOff, void *p){
-- return id->pMethods->xUnfetch(id, iOff, p);
++}
+
+static int sqlcipher_cc_ctx_init(void **ctx) {
+ return SQLITE_OK;
- }
--#else
--/* No-op stubs to use when memory-mapped I/O is disabled */
--SQLITE_PRIVATE int sqlite3OsFetch(sqlite3_file *id, i64 iOff, int iAmt, void **pp){
-- *pp = 0;
++}
+
+static int sqlcipher_cc_ctx_free(void **ctx) {
- return SQLITE_OK;
- }
--SQLITE_PRIVATE int sqlite3OsUnfetch(sqlite3_file *id, i64 iOff, void *p){
++ return SQLITE_OK;
++}
+
+int sqlcipher_cc_setup(sqlcipher_provider *p) {
+ p->random = sqlcipher_cc_random;
@@ -5420,18 +3577,16 @@
+ p->ctx_cmp = sqlcipher_cc_ctx_cmp;
+ p->ctx_init = sqlcipher_cc_ctx_init;
+ p->ctx_free = sqlcipher_cc_ctx_free;
- return SQLITE_OK;
- }
++ return SQLITE_OK;
++}
+
+#endif
- #endif
++#endif
+/* END SQLCIPHER */
-
++
+/************** End of crypto_cc.c *******************************************/
+/************** Begin file global.c ******************************************/
- /*
--** The next group of routines are convenience wrappers around the
--** VFS methods.
++/*
+** 2008 June 13
+**
+** The author disclaims copyright to this source code. In place of
@@ -5444,194 +3599,15 @@
+*************************************************************************
+**
+** This file contains definitions of global variables and contants.
- */
--SQLITE_PRIVATE int sqlite3OsOpen(
-- sqlite3_vfs *pVfs,
-- const char *zPath,
-- sqlite3_file *pFile,
-- int flags,
-- int *pFlagsOut
--){
-- int rc;
-- DO_OS_MALLOC_TEST(0);
-- /* 0x87f7f is a mask of SQLITE_OPEN_ flags that are valid to be passed
-- ** down into the VFS layer. Some SQLITE_OPEN_ flags (for example,
-- ** SQLITE_OPEN_FULLMUTEX or SQLITE_OPEN_SHAREDCACHE) are blocked before
-- ** reaching the VFS. */
-- rc = pVfs->xOpen(pVfs, zPath, pFile, flags & 0x87f7f, pFlagsOut);
-- assert( rc==SQLITE_OK || pFile->pMethods==0 );
-- return rc;
--}
--SQLITE_PRIVATE int sqlite3OsDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
-- DO_OS_MALLOC_TEST(0);
-- assert( dirSync==0 || dirSync==1 );
-- return pVfs->xDelete(pVfs, zPath, dirSync);
--}
--SQLITE_PRIVATE int sqlite3OsAccess(
-- sqlite3_vfs *pVfs,
-- const char *zPath,
-- int flags,
-- int *pResOut
--){
-- DO_OS_MALLOC_TEST(0);
-- return pVfs->xAccess(pVfs, zPath, flags, pResOut);
--}
--SQLITE_PRIVATE int sqlite3OsFullPathname(
-- sqlite3_vfs *pVfs,
-- const char *zPath,
-- int nPathOut,
-- char *zPathOut
--){
-- DO_OS_MALLOC_TEST(0);
-- zPathOut[0] = 0;
-- return pVfs->xFullPathname(pVfs, zPath, nPathOut, zPathOut);
--}
--#ifndef SQLITE_OMIT_LOAD_EXTENSION
--SQLITE_PRIVATE void *sqlite3OsDlOpen(sqlite3_vfs *pVfs, const char *zPath){
-- return pVfs->xDlOpen(pVfs, zPath);
--}
--SQLITE_PRIVATE void sqlite3OsDlError(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
-- pVfs->xDlError(pVfs, nByte, zBufOut);
--}
--SQLITE_PRIVATE void (*sqlite3OsDlSym(sqlite3_vfs *pVfs, void *pHdle, const char *zSym))(void){
-- return pVfs->xDlSym(pVfs, pHdle, zSym);
--}
--SQLITE_PRIVATE void sqlite3OsDlClose(sqlite3_vfs *pVfs, void *pHandle){
-- pVfs->xDlClose(pVfs, pHandle);
--}
--#endif /* SQLITE_OMIT_LOAD_EXTENSION */
--SQLITE_PRIVATE int sqlite3OsRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
-- return pVfs->xRandomness(pVfs, nByte, zBufOut);
--}
--SQLITE_PRIVATE int sqlite3OsSleep(sqlite3_vfs *pVfs, int nMicro){
-- return pVfs->xSleep(pVfs, nMicro);
--}
--SQLITE_PRIVATE int sqlite3OsCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *pTimeOut){
-- int rc;
-- /* IMPLEMENTATION-OF: R-49045-42493 SQLite will use the xCurrentTimeInt64()
-- ** method to get the current date and time if that method is available
-- ** (if iVersion is 2 or greater and the function pointer is not NULL) and
-- ** will fall back to xCurrentTime() if xCurrentTimeInt64() is
-- ** unavailable.
-- */
-- if( pVfs->iVersion>=2 && pVfs->xCurrentTimeInt64 ){
-- rc = pVfs->xCurrentTimeInt64(pVfs, pTimeOut);
-- }else{
-- double r;
-- rc = pVfs->xCurrentTime(pVfs, &r);
-- *pTimeOut = (sqlite3_int64)(r*86400000.0);
-- }
-- return rc;
--}
--
--SQLITE_PRIVATE int sqlite3OsOpenMalloc(
-- sqlite3_vfs *pVfs,
-- const char *zFile,
-- sqlite3_file **ppFile,
-- int flags,
-- int *pOutFlags
--){
-- int rc = SQLITE_NOMEM;
-- sqlite3_file *pFile;
-- pFile = (sqlite3_file *)sqlite3MallocZero(pVfs->szOsFile);
-- if( pFile ){
-- rc = sqlite3OsOpen(pVfs, zFile, pFile, flags, pOutFlags);
-- if( rc!=SQLITE_OK ){
-- sqlite3_free(pFile);
-- }else{
-- *ppFile = pFile;
-- }
-- }
-- return rc;
--}
--SQLITE_PRIVATE int sqlite3OsCloseFree(sqlite3_file *pFile){
-- int rc = SQLITE_OK;
-- assert( pFile );
-- rc = sqlite3OsClose(pFile);
-- sqlite3_free(pFile);
-- return rc;
--}
--
--/*
--** This function is a wrapper around the OS specific implementation of
--** sqlite3_os_init(). The purpose of the wrapper is to provide the
--** ability to simulate a malloc failure, so that the handling of an
--** error in sqlite3_os_init() by the upper layers can be tested.
--*/
--SQLITE_PRIVATE int sqlite3OsInit(void){
-- void *p = sqlite3_malloc(10);
-- if( p==0 ) return SQLITE_NOMEM;
-- sqlite3_free(p);
-- return sqlite3_os_init();
--}
--
--/*
--** The list of all registered VFS implementations.
--*/
--static sqlite3_vfs * SQLITE_WSD vfsList = 0;
--#define vfsList GLOBAL(sqlite3_vfs *, vfsList)
--
--/*
--** Locate a VFS by name. If no name is given, simply return the
--** first VFS on the list.
--*/
--SQLITE_API sqlite3_vfs *sqlite3_vfs_find(const char *zVfs){
-- sqlite3_vfs *pVfs = 0;
--#if SQLITE_THREADSAFE
-- sqlite3_mutex *mutex;
--#endif
--#ifndef SQLITE_OMIT_AUTOINIT
-- int rc = sqlite3_initialize();
-- if( rc ) return 0;
--#endif
--#if SQLITE_THREADSAFE
-- mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
--#endif
-- sqlite3_mutex_enter(mutex);
-- for(pVfs = vfsList; pVfs; pVfs=pVfs->pNext){
-- if( zVfs==0 ) break;
-- if( strcmp(zVfs, pVfs->zName)==0 ) break;
-- }
-- sqlite3_mutex_leave(mutex);
-- return pVfs;
--}
--
--/*
--** Unlink a VFS from the linked list
--*/
--static void vfsUnlink(sqlite3_vfs *pVfs){
-- assert( sqlite3_mutex_held(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER)) );
-- if( pVfs==0 ){
-- /* No-op */
-- }else if( vfsList==pVfs ){
-- vfsList = pVfs->pNext;
-- }else if( vfsList ){
-- sqlite3_vfs *p = vfsList;
-- while( p->pNext && p->pNext!=pVfs ){
-- p = p->pNext;
-- }
-- if( p->pNext==pVfs ){
-- p->pNext = pVfs->pNext;
-- }
-- }
--}
-
--/*
--** Register a VFS with the system. It is harmless to register the same
--** VFS multiple times. The new VFS becomes the default if makeDflt is
--** true.
++*/
++
+/* An array to map all upper-case characters into their corresponding
+** lower-case character.
+**
+** SQLite only considers US-ASCII (or EBCDIC) characters. We do not
+** handle case conversions for the UTF character set since the tables
+** involved are nearly as big or bigger than SQLite itself.
- */
--SQLITE_API int sqlite3_vfs_register(sqlite3_vfs *pVfs, int makeDflt){
-- MUTEX_LOGIC(sqlite3_mutex *mutex;)
--#ifndef SQLITE_OMIT_AUTOINIT
-- int rc = sqlite3_initialize();
-- if( rc ) return rc;
++*/
+SQLITE_PRIVATE const unsigned char sqlite3UpperToLower[] = {
+#ifdef SQLITE_ASCII
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
@@ -5649,28 +3625,7 @@
+ 216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,
+ 234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,
+ 252,253,254,255
- #endif
-- MUTEX_LOGIC( mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); )
-- sqlite3_mutex_enter(mutex);
-- vfsUnlink(pVfs);
-- if( makeDflt || vfsList==0 ){
-- pVfs->pNext = vfsList;
-- vfsList = pVfs;
-- }else{
-- pVfs->pNext = vfsList->pNext;
-- vfsList->pNext = pVfs;
-- }
-- assert(vfsList);
-- sqlite3_mutex_leave(mutex);
-- return SQLITE_OK;
--}
--
--/*
--** Unregister a VFS so that it is no longer accessible.
--*/
--SQLITE_API int sqlite3_vfs_unregister(sqlite3_vfs *pVfs){
--#if SQLITE_THREADSAFE
-- sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
++#endif
+#ifdef SQLITE_EBCDIC
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, /* 0x */
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, /* 1x */
@@ -5688,23 +3643,13 @@
+ 208,145,146,147,148,149,150,151,152,153,218,219,220,221,222,223, /* Dx */
+ 224,225,162,163,164,165,166,167,168,169,232,203,204,205,206,207, /* Ex */
+ 239,240,241,242,243,244,245,246,247,248,249,219,220,221,222,255, /* Fx */
- #endif
-- sqlite3_mutex_enter(mutex);
-- vfsUnlink(pVfs);
-- sqlite3_mutex_leave(mutex);
-- return SQLITE_OK;
--}
++#endif
+};
-
--/************** End of os.c **************************************************/
--/************** Begin file fault.c *******************************************/
- /*
--** 2008 Jan 22
++
++/*
+** The following 256 byte lookup table is used to support SQLites built-in
+** equivalents to the following standard library functions:
- **
--** The author disclaims copyright to this source code. In place of
--** a legal notice, here is a blessing:
++**
+** isspace() 0x01
+** isalpha() 0x02
+** isdigit() 0x04
@@ -5712,32 +3657,17 @@
+** isxdigit() 0x08
+** toupper() 0x20
+** SQLite identifier character 0x40
- **
--** May you do good and not evil.
--** May you find forgiveness for yourself and forgive others.
--** May you share freely, never taking more than you give.
++**
+** Bit 0x20 is set if the mapped character requires translation to upper
+** case. i.e. if the character is a lower-case ASCII character.
+** If x is a lower-case ASCII character, then its upper-case equivalent
+** is (x - 0x20). Therefore toupper() can be implemented as:
- **
--*************************************************************************
++**
+** (x & ~(map[x]&0x20))
- **
--** This file contains code to support the concept of "benign"
--** malloc failures (when the xMalloc() or xRealloc() method of the
--** sqlite3_mem_methods structure fails to allocate a block of memory
--** and returns 0).
++**
+** Standard function tolower() is implemented using the sqlite3UpperToLower[]
+** array. tolower() is used more often than toupper() by SQLite.
- **
--** Most malloc failures are non-benign. After they occur, SQLite
--** abandons the current operation and returns an error code (usually
--** SQLITE_NOMEM) to the user. However, sometimes a fault is not necessarily
--** fatal. For example, if a malloc fails while resizing a hash table, this
--** is completely recoverable simply by not carrying out the resize. The
--** hash table will continue to function normally. So a malloc failure
--** during a hash table resize is a benign fault.
++**
+** Bit 0x40 is set if the character non-alphanumeric and can be used in an
+** SQLite identifier. Identifiers are alphanumerics, "_", "$", and any
+** non-ASCII UTF character. Hence the test for whether or not a character is
@@ -5745,7 +3675,7 @@
+**
+** SQLite's versions are identical to the standard versions assuming a
+** locale of "C". They are implemented as macros in sqliteInt.h.
- */
++*/
+#ifdef SQLITE_ASCII
+SQLITE_PRIVATE const unsigned char sqlite3CtypeMap[256] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 00..07 ........ */
@@ -5756,7 +3686,7 @@
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 28..2f ()*+,-./ */
+ 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, /* 30..37 01234567 */
+ 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 38..3f 89:;<=>? */
-
++
+ 0x00, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x02, /* 40..47 @ABCDEFG */
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, /* 48..4f HIJKLMNO */
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, /* 50..57 PQRSTUVW */
@@ -5765,17 +3695,7 @@
+ 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, /* 68..6f hijklmno */
+ 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, /* 70..77 pqrstuvw */
+ 0x22, 0x22, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, /* 78..7f xyz{|}~. */
-
--#ifndef SQLITE_OMIT_BUILTIN_TEST
--
--/*
--** Global variables.
--*/
--typedef struct BenignMallocHooks BenignMallocHooks;
--static SQLITE_WSD struct BenignMallocHooks {
-- void (*xBenignBegin)(void);
-- void (*xBenignEnd)(void);
--} sqlite3Hooks = { 0, 0 };
++
+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* 80..87 ........ */
+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* 88..8f ........ */
+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* 90..97 ........ */
@@ -5784,20 +3704,7 @@
+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* a8..af ........ */
+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* b0..b7 ........ */
+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* b8..bf ........ */
-
--/* The "wsdHooks" macro will resolve to the appropriate BenignMallocHooks
--** structure. If writable static data is unsupported on the target,
--** we have to locate the state vector at run-time. In the more common
--** case where writable static data is supported, wsdHooks can refer directly
--** to the "sqlite3Hooks" state vector declared above.
--*/
--#ifdef SQLITE_OMIT_WSD
--# define wsdHooksInit \
-- BenignMallocHooks *x = &GLOBAL(BenignMallocHooks,sqlite3Hooks)
--# define wsdHooks x[0]
--#else
--# define wsdHooksInit
--# define wsdHooks sqlite3Hooks
++
+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* c0..c7 ........ */
+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* c8..cf ........ */
+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* d0..d7 ........ */
@@ -5807,47 +3714,20 @@
+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* f0..f7 ........ */
+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40 /* f8..ff ........ */
+};
- #endif
-
++#endif
++
+#ifndef SQLITE_USE_URI
+# define SQLITE_USE_URI 0
+#endif
-
--/*
--** Register hooks to call when sqlite3BeginBenignMalloc() and
--** sqlite3EndBenignMalloc() are called, respectively.
--*/
--SQLITE_PRIVATE void sqlite3BenignMallocHooks(
-- void (*xBenignBegin)(void),
-- void (*xBenignEnd)(void)
--){
-- wsdHooksInit;
-- wsdHooks.xBenignBegin = xBenignBegin;
-- wsdHooks.xBenignEnd = xBenignEnd;
--}
++
+#ifndef SQLITE_ALLOW_COVERING_INDEX_SCAN
+# define SQLITE_ALLOW_COVERING_INDEX_SCAN 1
+#endif
-
- /*
--** This (sqlite3EndBenignMalloc()) is called by SQLite code to indicate that
--** subsequent malloc failures are benign. A call to sqlite3EndBenignMalloc()
--** indicates that subsequent malloc failures are non-benign.
++
++/*
+** The following singleton contains the global configuration for
+** the SQLite library.
- */
--SQLITE_PRIVATE void sqlite3BeginBenignMalloc(void){
-- wsdHooksInit;
-- if( wsdHooks.xBenignBegin ){
-- wsdHooks.xBenignBegin();
-- }
--}
--SQLITE_PRIVATE void sqlite3EndBenignMalloc(void){
-- wsdHooksInit;
-- if( wsdHooks.xBenignEnd ){
-- wsdHooks.xBenignEnd();
-- }
--}
++*/
+SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlite3Config = {
+ SQLITE_DEFAULT_MEMSTATUS, /* bMemstat */
+ 1, /* bCoreMutex */
@@ -5889,67 +3769,31 @@
+ 0 /* pSqllogArg */
+#endif
+};
-
--#endif /* #ifndef SQLITE_OMIT_BUILTIN_TEST */
-
--/************** End of fault.c ***********************************************/
--/************** Begin file mem0.c ********************************************/
- /*
--** 2008 October 28
--**
--** The author disclaims copyright to this source code. In place of
--** a legal notice, here is a blessing:
--**
--** May you do good and not evil.
--** May you find forgiveness for yourself and forgive others.
--** May you share freely, never taking more than you give.
--**
--*************************************************************************
--**
--** This file contains a no-op memory allocation drivers for use when
--** SQLITE_ZERO_MALLOC is defined. The allocation drivers implemented
--** here always fail. SQLite will not operate with these drivers. These
--** are merely placeholders. Real drivers must be substituted using
--** sqlite3_config() before SQLite will operate.
++
++
++/*
+** Hash table for global functions - functions common to all
+** database connections. After initialization, this table is
+** read-only.
- */
++*/
+SQLITE_PRIVATE SQLITE_WSD FuncDefHash sqlite3GlobalFunctions;
-
- /*
--** This version of the memory allocator is the default. It is
--** used when no other memory allocator is specified using compile-time
--** macros.
++
++/*
+** Constant tokens for values 0 and 1.
- */
--#ifdef SQLITE_ZERO_MALLOC
++*/
+SQLITE_PRIVATE const Token sqlite3IntTokens[] = {
+ { "0", 1 },
+ { "1", 1 }
+};
-
--/*
--** No-op versions of all memory allocation routines
--*/
--static void *sqlite3MemMalloc(int nByte){ return 0; }
--static void sqlite3MemFree(void *pPrior){ return; }
--static void *sqlite3MemRealloc(void *pPrior, int nByte){ return 0; }
--static int sqlite3MemSize(void *pPrior){ return 0; }
--static int sqlite3MemRoundup(int n){ return n; }
--static int sqlite3MemInit(void *NotUsed){ return SQLITE_OK; }
--static void sqlite3MemShutdown(void *NotUsed){ return; }
-
- /*
--** This routine is the only routine in this file with external linkage.
++
++
++/*
+** The value of the "pending" byte must be 0x40000000 (1 byte past the
+** 1-gibabyte boundary) in a compatible database. SQLite never uses
+** the database page that contains the pending byte. It never attempts
+** to read or write that page. The pending byte page is set assign
+** for use by the VFS layers as space for managing file locks.
- **
--** Populate the low-level memory allocation function pointers in
--** sqlite3GlobalConfig.m with pointers to the routines in this file.
++**
+** During testing, it is often desirable to move the pending byte to
+** a different position in the file. This allows code that has to
+** deal with the pending byte to run on files that are much smaller
@@ -5960,25 +3804,11 @@
+** 0x40000000 results in an incompatible database file format!
+** Changing the pending byte during operating results in undefined
+** and dileterious behavior.
- */
--SQLITE_PRIVATE void sqlite3MemSetDefault(void){
-- static const sqlite3_mem_methods defaultMethods = {
-- sqlite3MemMalloc,
-- sqlite3MemFree,
-- sqlite3MemRealloc,
-- sqlite3MemSize,
-- sqlite3MemRoundup,
-- sqlite3MemInit,
-- sqlite3MemShutdown,
-- 0
-- };
-- sqlite3_config(SQLITE_CONFIG_MALLOC, &defaultMethods);
--}
++*/
+#ifndef SQLITE_OMIT_WSD
+SQLITE_PRIVATE int sqlite3PendingByte = 0x40000000;
+#endif
-
--#endif /* SQLITE_ZERO_MALLOC */
++
+/*
+** Properties of opcodes. The OPFLG_INITIALIZER macro is
+** created by mkopcodeh.awk during compilation. Data is obtained
@@ -5986,8374 +3816,11 @@
+** the vdbe.c file.
+*/
+SQLITE_PRIVATE const unsigned char sqlite3OpcodeProperty[] = OPFLG_INITIALIZER;
-
--/************** End of mem0.c ************************************************/
--/************** Begin file mem1.c ********************************************/
++
+/************** End of global.c **********************************************/
+/************** Begin file ctime.c *******************************************/
- /*
--** 2007 August 14
-+** 2010 February 23
- **
- ** The author disclaims copyright to this source code. In place of
- ** a legal notice, here is a blessing:
-@@ -15633,807 +15866,1140 @@
- **
- *************************************************************************
- **
--** This file contains low-level memory allocation drivers for when
--** SQLite will use the standard C-library malloc/realloc/free interface
--** to obtain the memory it needs.
--**
--** This file contains implementations of the low-level memory allocation
--** routines specified in the sqlite3_mem_methods object. The content of
--** this file is only used if SQLITE_SYSTEM_MALLOC is defined. The
--** SQLITE_SYSTEM_MALLOC macro is defined automatically if neither the
--** SQLITE_MEMDEBUG nor the SQLITE_WIN32_MALLOC macros are defined. The
--** default configuration is to use memory allocation routines in this
--** file.
--**
--** C-preprocessor macro summary:
--**
--** HAVE_MALLOC_USABLE_SIZE The configure script sets this symbol if
--** the malloc_usable_size() interface exists
--** on the target platform. Or, this symbol
--** can be set manually, if desired.
--** If an equivalent interface exists by
--** a different name, using a separate -D
--** option to rename it.
--**
--** SQLITE_WITHOUT_ZONEMALLOC Some older macs lack support for the zone
--** memory allocator. Set this symbol to enable
--** building on older macs.
--**
--** SQLITE_WITHOUT_MSIZE Set this symbol to disable the use of
--** _msize() on windows systems. This might
--** be necessary when compiling for Delphi,
--** for example.
--*/
--
--/*
--** This version of the memory allocator is the default. It is
--** used when no other memory allocator is specified using compile-time
--** macros.
-+** This file implements routines used to report what compile-time options
-+** SQLite was built with.
- */
--#ifdef SQLITE_SYSTEM_MALLOC
-
--/*
--** The MSVCRT has malloc_usable_size() but it is called _msize().
--** The use of _msize() is automatic, but can be disabled by compiling
--** with -DSQLITE_WITHOUT_MSIZE
--*/
--#if defined(_MSC_VER) && !defined(SQLITE_WITHOUT_MSIZE)
--# define SQLITE_MALLOCSIZE _msize
--#endif
-+#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
-
--#if defined(__APPLE__) && !defined(SQLITE_WITHOUT_ZONEMALLOC)
-
- /*
--** Use the zone allocator available on apple products unless the
--** SQLITE_WITHOUT_ZONEMALLOC symbol is defined.
-+** An array of names of all compile-time options. This array should
-+** be sorted A-Z.
-+**
-+** This array looks large, but in a typical installation actually uses
-+** only a handful of compile-time options, so most times this array is usually
-+** rather short and uses little memory space.
- */
--#include <sys/sysctl.h>
--#include <malloc/malloc.h>
--#include <libkern/OSAtomic.h>
--static malloc_zone_t* _sqliteZone_;
--#define SQLITE_MALLOC(x) malloc_zone_malloc(_sqliteZone_, (x))
--#define SQLITE_FREE(x) malloc_zone_free(_sqliteZone_, (x));
--#define SQLITE_REALLOC(x,y) malloc_zone_realloc(_sqliteZone_, (x), (y))
--#define SQLITE_MALLOCSIZE(x) \
-- (_sqliteZone_ ? _sqliteZone_->size(_sqliteZone_,x) : malloc_size(x))
-+static const char * const azCompileOpt[] = {
-
--#else /* if not __APPLE__ */
-+/* These macros are provided to "stringify" the value of the define
-+** for those options in which the value is meaningful. */
-+#define CTIMEOPT_VAL_(opt) #opt
-+#define CTIMEOPT_VAL(opt) CTIMEOPT_VAL_(opt)
-
--/*
--** Use standard C library malloc and free on non-Apple systems.
--** Also used by Apple systems if SQLITE_WITHOUT_ZONEMALLOC is defined.
--*/
--#define SQLITE_MALLOC(x) malloc(x)
--#define SQLITE_FREE(x) free(x)
--#define SQLITE_REALLOC(x,y) realloc((x),(y))
--
--#if (defined(_MSC_VER) && !defined(SQLITE_WITHOUT_MSIZE)) \
-- || (defined(HAVE_MALLOC_H) && defined(HAVE_MALLOC_USABLE_SIZE))
--# include <malloc.h> /* Needed for malloc_usable_size on linux */
-+#ifdef SQLITE_32BIT_ROWID
-+ "32BIT_ROWID",
- #endif
--#ifdef HAVE_MALLOC_USABLE_SIZE
--# ifndef SQLITE_MALLOCSIZE
--# define SQLITE_MALLOCSIZE(x) malloc_usable_size(x)
--# endif
--#else
--# undef SQLITE_MALLOCSIZE
-+#ifdef SQLITE_4_BYTE_ALIGNED_MALLOC
-+ "4_BYTE_ALIGNED_MALLOC",
- #endif
--
--#endif /* __APPLE__ or not __APPLE__ */
-+#ifdef SQLITE_CASE_SENSITIVE_LIKE
-+ "CASE_SENSITIVE_LIKE",
-+#endif
-+#ifdef SQLITE_CHECK_PAGES
-+ "CHECK_PAGES",
-+#endif
-+#ifdef SQLITE_COVERAGE_TEST
-+ "COVERAGE_TEST",
-+#endif
-+#ifdef SQLITE_DEBUG
-+ "DEBUG",
-+#endif
-+#ifdef SQLITE_DEFAULT_LOCKING_MODE
-+ "DEFAULT_LOCKING_MODE=" CTIMEOPT_VAL(SQLITE_DEFAULT_LOCKING_MODE),
-+#endif
-+#if defined(SQLITE_DEFAULT_MMAP_SIZE) && !defined(SQLITE_DEFAULT_MMAP_SIZE_xc)
-+ "DEFAULT_MMAP_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_MMAP_SIZE),
-+#endif
-+#ifdef SQLITE_DISABLE_DIRSYNC
-+ "DISABLE_DIRSYNC",
-+#endif
-+#ifdef SQLITE_DISABLE_LFS
-+ "DISABLE_LFS",
-+#endif
-+#ifdef SQLITE_ENABLE_ATOMIC_WRITE
-+ "ENABLE_ATOMIC_WRITE",
-+#endif
-+#ifdef SQLITE_ENABLE_CEROD
-+ "ENABLE_CEROD",
-+#endif
-+#ifdef SQLITE_ENABLE_COLUMN_METADATA
-+ "ENABLE_COLUMN_METADATA",
-+#endif
-+#ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT
-+ "ENABLE_EXPENSIVE_ASSERT",
-+#endif
-+#ifdef SQLITE_ENABLE_FTS1
-+ "ENABLE_FTS1",
-+#endif
-+#ifdef SQLITE_ENABLE_FTS2
-+ "ENABLE_FTS2",
-+#endif
-+#ifdef SQLITE_ENABLE_FTS3
-+ "ENABLE_FTS3",
-+#endif
-+#ifdef SQLITE_ENABLE_FTS3_PARENTHESIS
-+ "ENABLE_FTS3_PARENTHESIS",
-+#endif
-+#ifdef SQLITE_ENABLE_FTS4
-+ "ENABLE_FTS4",
-+#endif
-+#ifdef SQLITE_ENABLE_ICU
-+ "ENABLE_ICU",
-+#endif
-+#ifdef SQLITE_ENABLE_IOTRACE
-+ "ENABLE_IOTRACE",
-+#endif
-+#ifdef SQLITE_ENABLE_LOAD_EXTENSION
-+ "ENABLE_LOAD_EXTENSION",
-+#endif
-+#ifdef SQLITE_ENABLE_LOCKING_STYLE
-+ "ENABLE_LOCKING_STYLE=" CTIMEOPT_VAL(SQLITE_ENABLE_LOCKING_STYLE),
-+#endif
-+#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
-+ "ENABLE_MEMORY_MANAGEMENT",
-+#endif
-+#ifdef SQLITE_ENABLE_MEMSYS3
-+ "ENABLE_MEMSYS3",
-+#endif
-+#ifdef SQLITE_ENABLE_MEMSYS5
-+ "ENABLE_MEMSYS5",
-+#endif
-+#ifdef SQLITE_ENABLE_OVERSIZE_CELL_CHECK
-+ "ENABLE_OVERSIZE_CELL_CHECK",
-+#endif
-+#ifdef SQLITE_ENABLE_RTREE
-+ "ENABLE_RTREE",
-+#endif
-+#ifdef SQLITE_ENABLE_STAT3
-+ "ENABLE_STAT3",
-+#endif
-+#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
-+ "ENABLE_UNLOCK_NOTIFY",
-+#endif
-+#ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT
-+ "ENABLE_UPDATE_DELETE_LIMIT",
-+#endif
-+#ifdef SQLITE_HAS_CODEC
-+ "HAS_CODEC",
-+#endif
-+#ifdef SQLITE_HAVE_ISNAN
-+ "HAVE_ISNAN",
-+#endif
-+#ifdef SQLITE_HOMEGROWN_RECURSIVE_MUTEX
-+ "HOMEGROWN_RECURSIVE_MUTEX",
-+#endif
-+#ifdef SQLITE_IGNORE_AFP_LOCK_ERRORS
-+ "IGNORE_AFP_LOCK_ERRORS",
-+#endif
-+#ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS
-+ "IGNORE_FLOCK_LOCK_ERRORS",
-+#endif
-+#ifdef SQLITE_INT64_TYPE
-+ "INT64_TYPE",
-+#endif
-+#ifdef SQLITE_LOCK_TRACE
-+ "LOCK_TRACE",
-+#endif
-+#if defined(SQLITE_MAX_MMAP_SIZE) && !defined(SQLITE_MAX_MMAP_SIZE_xc)
-+ "MAX_MMAP_SIZE=" CTIMEOPT_VAL(SQLITE_MAX_MMAP_SIZE),
-+#endif
-+#ifdef SQLITE_MAX_SCHEMA_RETRY
-+ "MAX_SCHEMA_RETRY=" CTIMEOPT_VAL(SQLITE_MAX_SCHEMA_RETRY),
-+#endif
-+#ifdef SQLITE_MEMDEBUG
-+ "MEMDEBUG",
-+#endif
-+#ifdef SQLITE_MIXED_ENDIAN_64BIT_FLOAT
-+ "MIXED_ENDIAN_64BIT_FLOAT",
-+#endif
-+#ifdef SQLITE_NO_SYNC
-+ "NO_SYNC",
-+#endif
-+#ifdef SQLITE_OMIT_ALTERTABLE
-+ "OMIT_ALTERTABLE",
-+#endif
-+#ifdef SQLITE_OMIT_ANALYZE
-+ "OMIT_ANALYZE",
-+#endif
-+#ifdef SQLITE_OMIT_ATTACH
-+ "OMIT_ATTACH",
-+#endif
-+#ifdef SQLITE_OMIT_AUTHORIZATION
-+ "OMIT_AUTHORIZATION",
-+#endif
-+#ifdef SQLITE_OMIT_AUTOINCREMENT
-+ "OMIT_AUTOINCREMENT",
-+#endif
-+#ifdef SQLITE_OMIT_AUTOINIT
-+ "OMIT_AUTOINIT",
-+#endif
-+#ifdef SQLITE_OMIT_AUTOMATIC_INDEX
-+ "OMIT_AUTOMATIC_INDEX",
-+#endif
-+#ifdef SQLITE_OMIT_AUTORESET
-+ "OMIT_AUTORESET",
-+#endif
-+#ifdef SQLITE_OMIT_AUTOVACUUM
-+ "OMIT_AUTOVACUUM",
-+#endif
-+#ifdef SQLITE_OMIT_BETWEEN_OPTIMIZATION
-+ "OMIT_BETWEEN_OPTIMIZATION",
-+#endif
-+#ifdef SQLITE_OMIT_BLOB_LITERAL
-+ "OMIT_BLOB_LITERAL",
-+#endif
-+#ifdef SQLITE_OMIT_BTREECOUNT
-+ "OMIT_BTREECOUNT",
-+#endif
-+#ifdef SQLITE_OMIT_BUILTIN_TEST
-+ "OMIT_BUILTIN_TEST",
-+#endif
-+#ifdef SQLITE_OMIT_CAST
-+ "OMIT_CAST",
-+#endif
-+#ifdef SQLITE_OMIT_CHECK
-+ "OMIT_CHECK",
-+#endif
-+#ifdef SQLITE_OMIT_COMPLETE
-+ "OMIT_COMPLETE",
-+#endif
-+#ifdef SQLITE_OMIT_COMPOUND_SELECT
-+ "OMIT_COMPOUND_SELECT",
-+#endif
-+#ifdef SQLITE_OMIT_DATETIME_FUNCS
-+ "OMIT_DATETIME_FUNCS",
-+#endif
-+#ifdef SQLITE_OMIT_DECLTYPE
-+ "OMIT_DECLTYPE",
-+#endif
-+#ifdef SQLITE_OMIT_DEPRECATED
-+ "OMIT_DEPRECATED",
-+#endif
-+#ifdef SQLITE_OMIT_DISKIO
-+ "OMIT_DISKIO",
-+#endif
-+#ifdef SQLITE_OMIT_EXPLAIN
-+ "OMIT_EXPLAIN",
-+#endif
-+#ifdef SQLITE_OMIT_FLAG_PRAGMAS
-+ "OMIT_FLAG_PRAGMAS",
-+#endif
-+#ifdef SQLITE_OMIT_FLOATING_POINT
-+ "OMIT_FLOATING_POINT",
-+#endif
-+#ifdef SQLITE_OMIT_FOREIGN_KEY
-+ "OMIT_FOREIGN_KEY",
-+#endif
-+#ifdef SQLITE_OMIT_GET_TABLE
-+ "OMIT_GET_TABLE",
-+#endif
-+#ifdef SQLITE_OMIT_INCRBLOB
-+ "OMIT_INCRBLOB",
-+#endif
-+#ifdef SQLITE_OMIT_INTEGRITY_CHECK
-+ "OMIT_INTEGRITY_CHECK",
-+#endif
-+#ifdef SQLITE_OMIT_LIKE_OPTIMIZATION
-+ "OMIT_LIKE_OPTIMIZATION",
-+#endif
-+#ifdef SQLITE_OMIT_LOAD_EXTENSION
-+ "OMIT_LOAD_EXTENSION",
-+#endif
-+#ifdef SQLITE_OMIT_LOCALTIME
-+ "OMIT_LOCALTIME",
-+#endif
-+#ifdef SQLITE_OMIT_LOOKASIDE
-+ "OMIT_LOOKASIDE",
-+#endif
-+#ifdef SQLITE_OMIT_MEMORYDB
-+ "OMIT_MEMORYDB",
-+#endif
-+#ifdef SQLITE_OMIT_OR_OPTIMIZATION
-+ "OMIT_OR_OPTIMIZATION",
-+#endif
-+#ifdef SQLITE_OMIT_PAGER_PRAGMAS
-+ "OMIT_PAGER_PRAGMAS",
-+#endif
-+#ifdef SQLITE_OMIT_PRAGMA
-+ "OMIT_PRAGMA",
-+#endif
-+#ifdef SQLITE_OMIT_PROGRESS_CALLBACK
-+ "OMIT_PROGRESS_CALLBACK",
-+#endif
-+#ifdef SQLITE_OMIT_QUICKBALANCE
-+ "OMIT_QUICKBALANCE",
-+#endif
-+#ifdef SQLITE_OMIT_REINDEX
-+ "OMIT_REINDEX",
-+#endif
-+#ifdef SQLITE_OMIT_SCHEMA_PRAGMAS
-+ "OMIT_SCHEMA_PRAGMAS",
-+#endif
-+#ifdef SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS
-+ "OMIT_SCHEMA_VERSION_PRAGMAS",
-+#endif
-+#ifdef SQLITE_OMIT_SHARED_CACHE
-+ "OMIT_SHARED_CACHE",
-+#endif
-+#ifdef SQLITE_OMIT_SUBQUERY
-+ "OMIT_SUBQUERY",
-+#endif
-+#ifdef SQLITE_OMIT_TCL_VARIABLE
-+ "OMIT_TCL_VARIABLE",
-+#endif
-+#ifdef SQLITE_OMIT_TEMPDB
-+ "OMIT_TEMPDB",
-+#endif
-+#ifdef SQLITE_OMIT_TRACE
-+ "OMIT_TRACE",
-+#endif
-+#ifdef SQLITE_OMIT_TRIGGER
-+ "OMIT_TRIGGER",
-+#endif
-+#ifdef SQLITE_OMIT_TRUNCATE_OPTIMIZATION
-+ "OMIT_TRUNCATE_OPTIMIZATION",
-+#endif
-+#ifdef SQLITE_OMIT_UTF16
-+ "OMIT_UTF16",
-+#endif
-+#ifdef SQLITE_OMIT_VACUUM
-+ "OMIT_VACUUM",
-+#endif
-+#ifdef SQLITE_OMIT_VIEW
-+ "OMIT_VIEW",
-+#endif
-+#ifdef SQLITE_OMIT_VIRTUALTABLE
-+ "OMIT_VIRTUALTABLE",
-+#endif
-+#ifdef SQLITE_OMIT_WAL
-+ "OMIT_WAL",
-+#endif
-+#ifdef SQLITE_OMIT_WSD
-+ "OMIT_WSD",
-+#endif
-+#ifdef SQLITE_OMIT_XFER_OPT
-+ "OMIT_XFER_OPT",
-+#endif
-+#ifdef SQLITE_PERFORMANCE_TRACE
-+ "PERFORMANCE_TRACE",
-+#endif
-+#ifdef SQLITE_PROXY_DEBUG
-+ "PROXY_DEBUG",
-+#endif
-+#ifdef SQLITE_RTREE_INT_ONLY
-+ "RTREE_INT_ONLY",
-+#endif
-+#ifdef SQLITE_SECURE_DELETE
-+ "SECURE_DELETE",
-+#endif
-+#ifdef SQLITE_SMALL_STACK
-+ "SMALL_STACK",
-+#endif
-+#ifdef SQLITE_SOUNDEX
-+ "SOUNDEX",
-+#endif
-+#ifdef SQLITE_TCL
-+ "TCL",
-+#endif
-+#if defined(SQLITE_TEMP_STORE) && !defined(SQLITE_TEMP_STORE_xc)
-+ "TEMP_STORE=" CTIMEOPT_VAL(SQLITE_TEMP_STORE),
-+#endif
-+#ifdef SQLITE_TEST
-+ "TEST",
-+#endif
-+#if defined(SQLITE_THREADSAFE)
-+ "THREADSAFE=" CTIMEOPT_VAL(SQLITE_THREADSAFE),
-+#endif
-+#ifdef SQLITE_USE_ALLOCA
-+ "USE_ALLOCA",
-+#endif
-+#ifdef SQLITE_ZERO_MALLOC
-+ "ZERO_MALLOC"
-+#endif
-+};
-
- /*
--** Like malloc(), but remember the size of the allocation
--** so that we can find it later using sqlite3MemSize().
-+** Given the name of a compile-time option, return true if that option
-+** was used and false if not.
- **
--** For this low-level routine, we are guaranteed that nByte>0 because
--** cases of nByte<=0 will be intercepted and dealt with by higher level
--** routines.
-+** The name can optionally begin with "SQLITE_" but the "SQLITE_" prefix
-+** is not required for a match.
- */
--static void *sqlite3MemMalloc(int nByte){
--#ifdef SQLITE_MALLOCSIZE
-- void *p = SQLITE_MALLOC( nByte );
-- if( p==0 ){
-- testcase( sqlite3GlobalConfig.xLog!=0 );
-- sqlite3_log(SQLITE_NOMEM, "failed to allocate %u bytes of memory", nByte);
-- }
-- return p;
--#else
-- sqlite3_int64 *p;
-- assert( nByte>0 );
-- nByte = ROUND8(nByte);
-- p = SQLITE_MALLOC( nByte+8 );
-- if( p ){
-- p[0] = nByte;
-- p++;
-- }else{
-- testcase( sqlite3GlobalConfig.xLog!=0 );
-- sqlite3_log(SQLITE_NOMEM, "failed to allocate %u bytes of memory", nByte);
-+SQLITE_API int sqlite3_compileoption_used(const char *zOptName){
-+ int i, n;
-+ if( sqlite3StrNICmp(zOptName, "SQLITE_", 7)==0 ) zOptName += 7;
-+ n = sqlite3Strlen30(zOptName);
-+
-+ /* Since ArraySize(azCompileOpt) is normally in single digits, a
-+ ** linear search is adequate. No need for a binary search. */
-+ for(i=0; i<ArraySize(azCompileOpt); i++){
-+ if( sqlite3StrNICmp(zOptName, azCompileOpt[i], n)==0
-+ && sqlite3CtypeMap[(unsigned char)azCompileOpt[i][n]]==0
-+ ){
-+ return 1;
-+ }
- }
-- return (void *)p;
--#endif
-+ return 0;
- }
-
- /*
--** Like free() but works for allocations obtained from sqlite3MemMalloc()
--** or sqlite3MemRealloc().
--**
--** For this low-level routine, we already know that pPrior!=0 since
--** cases where pPrior==0 will have been intecepted and dealt with
--** by higher-level routines.
-+** Return the N-th compile-time option string. If N is out of range,
-+** return a NULL pointer.
- */
--static void sqlite3MemFree(void *pPrior){
--#ifdef SQLITE_MALLOCSIZE
-- SQLITE_FREE(pPrior);
--#else
-- sqlite3_int64 *p = (sqlite3_int64*)pPrior;
-- assert( pPrior!=0 );
-- p--;
-- SQLITE_FREE(p);
--#endif
-+SQLITE_API const char *sqlite3_compileoption_get(int N){
-+ if( N>=0 && N<ArraySize(azCompileOpt) ){
-+ return azCompileOpt[N];
-+ }
-+ return 0;
- }
-
-+#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */
-+
-+/************** End of ctime.c ***********************************************/
-+/************** Begin file status.c ******************************************/
- /*
--** Report the allocated size of a prior return from xMalloc()
--** or xRealloc().
-+** 2008 June 18
-+**
-+** The author disclaims copyright to this source code. In place of
-+** a legal notice, here is a blessing:
-+**
-+** May you do good and not evil.
-+** May you find forgiveness for yourself and forgive others.
-+** May you share freely, never taking more than you give.
-+**
-+*************************************************************************
-+**
-+** This module implements the sqlite3_status() interface and related
-+** functionality.
- */
--static int sqlite3MemSize(void *pPrior){
--#ifdef SQLITE_MALLOCSIZE
-- return pPrior ? (int)SQLITE_MALLOCSIZE(pPrior) : 0;
--#else
-- sqlite3_int64 *p;
-- if( pPrior==0 ) return 0;
-- p = (sqlite3_int64*)pPrior;
-- p--;
-- return (int)p[0];
--#endif
--}
--
-+/************** Include vdbeInt.h in the middle of status.c ******************/
-+/************** Begin file vdbeInt.h *****************************************/
- /*
--** Like realloc(). Resize an allocation previously obtained from
--** sqlite3MemMalloc().
-+** 2003 September 6
- **
--** For this low-level interface, we know that pPrior!=0. Cases where
--** pPrior==0 while have been intercepted by higher-level routine and
--** redirected to xMalloc. Similarly, we know that nByte>0 becauses
--** cases where nByte<=0 will have been intercepted by higher-level
--** routines and redirected to xFree.
-+** The author disclaims copyright to this source code. In place of
-+** a legal notice, here is a blessing:
-+**
-+** May you do good and not evil.
-+** May you find forgiveness for yourself and forgive others.
-+** May you share freely, never taking more than you give.
-+**
-+*************************************************************************
-+** This is the header file for information that is private to the
-+** VDBE. This information used to all be at the top of the single
-+** source code file "vdbe.c". When that file became too big (over
-+** 6000 lines long) it was split up into several smaller files and
-+** this header information was factored out.
- */
--static void *sqlite3MemRealloc(void *pPrior, int nByte){
--#ifdef SQLITE_MALLOCSIZE
-- void *p = SQLITE_REALLOC(pPrior, nByte);
-- if( p==0 ){
-- testcase( sqlite3GlobalConfig.xLog!=0 );
-- sqlite3_log(SQLITE_NOMEM,
-- "failed memory resize %u to %u bytes",
-- SQLITE_MALLOCSIZE(pPrior), nByte);
-- }
-- return p;
--#else
-- sqlite3_int64 *p = (sqlite3_int64*)pPrior;
-- assert( pPrior!=0 && nByte>0 );
-- assert( nByte==ROUND8(nByte) ); /* EV: R-46199-30249 */
-- p--;
-- p = SQLITE_REALLOC(p, nByte+8 );
-- if( p ){
-- p[0] = nByte;
-- p++;
-- }else{
-- testcase( sqlite3GlobalConfig.xLog!=0 );
-- sqlite3_log(SQLITE_NOMEM,
-- "failed memory resize %u to %u bytes",
-- sqlite3MemSize(pPrior), nByte);
-- }
-- return (void*)p;
-+#ifndef _VDBEINT_H_
-+#define _VDBEINT_H_
-+
+/*
-+** The maximum number of times that a statement will try to reparse
-+** itself before giving up and returning SQLITE_SCHEMA.
-+*/
-+#ifndef SQLITE_MAX_SCHEMA_RETRY
-+# define SQLITE_MAX_SCHEMA_RETRY 50
- #endif
--}
-
- /*
--** Round up a request size to the next valid allocation size.
-+** SQL is translated into a sequence of instructions to be
-+** executed by a virtual machine. Each instruction is an instance
-+** of the following structure.
- */
--static int sqlite3MemRoundup(int n){
-- return ROUND8(n);
--}
-+typedef struct VdbeOp Op;
-
- /*
--** Initialize this module.
-+** Boolean values
- */
--static int sqlite3MemInit(void *NotUsed){
--#if defined(__APPLE__) && !defined(SQLITE_WITHOUT_ZONEMALLOC)
-- int cpuCount;
-- size_t len;
-- if( _sqliteZone_ ){
-- return SQLITE_OK;
-- }
-- len = sizeof(cpuCount);
-- /* One usually wants to use hw.acctivecpu for MT decisions, but not here */
-- sysctlbyname("hw.ncpu", &cpuCount, &len, NULL, 0);
-- if( cpuCount>1 ){
-- /* defer MT decisions to system malloc */
-- _sqliteZone_ = malloc_default_zone();
-- }else{
-- /* only 1 core, use our own zone to contention over global locks,
-- ** e.g. we have our own dedicated locks */
-- bool success;
-- malloc_zone_t* newzone = malloc_create_zone(4096, 0);
-- malloc_set_zone_name(newzone, "Sqlite_Heap");
-- do{
-- success = OSAtomicCompareAndSwapPtrBarrier(NULL, newzone,
-- (void * volatile *)&_sqliteZone_);
-- }while(!_sqliteZone_);
-- if( !success ){
-- /* somebody registered a zone first */
-- malloc_destroy_zone(newzone);
-- }
-- }
--#endif
-- UNUSED_PARAMETER(NotUsed);
-- return SQLITE_OK;
--}
-+typedef unsigned char Bool;
-
--/*
--** Deinitialize this module.
--*/
--static void sqlite3MemShutdown(void *NotUsed){
-- UNUSED_PARAMETER(NotUsed);
-- return;
--}
-+/* Opaque type used by code in vdbesort.c */
-+typedef struct VdbeSorter VdbeSorter;
-+
-+/* Opaque type used by the explainer */
-+typedef struct Explain Explain;
-
- /*
--** This routine is the only routine in this file with external linkage.
--**
--** Populate the low-level memory allocation function pointers in
--** sqlite3GlobalConfig.m with pointers to the routines in this file.
-+** A cursor is a pointer into a single BTree within a database file.
-+** The cursor can seek to a BTree entry with a particular key, or
-+** loop over all entries of the Btree. You can also insert new BTree
-+** entries or retrieve the key or data from the entry that the cursor
-+** is currently pointing to.
-+**
-+** Every cursor that the virtual machine has open is represented by an
-+** instance of the following structure.
- */
--SQLITE_PRIVATE void sqlite3MemSetDefault(void){
-- static const sqlite3_mem_methods defaultMethods = {
-- sqlite3MemMalloc,
-- sqlite3MemFree,
-- sqlite3MemRealloc,
-- sqlite3MemSize,
-- sqlite3MemRoundup,
-- sqlite3MemInit,
-- sqlite3MemShutdown,
-- 0
-- };
-- sqlite3_config(SQLITE_CONFIG_MALLOC, &defaultMethods);
--}
-+struct VdbeCursor {
-+ BtCursor *pCursor; /* The cursor structure of the backend */
-+ Btree *pBt; /* Separate file holding temporary table */
-+ KeyInfo *pKeyInfo; /* Info about index keys needed by index cursors */
-+ int iDb; /* Index of cursor database in db->aDb[] (or -1) */
-+ int pseudoTableReg; /* Register holding pseudotable content. */
-+ int nField; /* Number of fields in the header */
-+ Bool zeroed; /* True if zeroed out and ready for reuse */
-+ Bool rowidIsValid; /* True if lastRowid is valid */
-+ Bool atFirst; /* True if pointing to first entry */
-+ Bool useRandomRowid; /* Generate new record numbers semi-randomly */
-+ Bool nullRow; /* True if pointing to a row with no data */
-+ Bool deferredMoveto; /* A call to sqlite3BtreeMoveto() is needed */
-+ Bool isTable; /* True if a table requiring integer keys */
-+ Bool isIndex; /* True if an index containing keys only - no data */
-+ Bool isOrdered; /* True if the underlying table is BTREE_UNORDERED */
-+ Bool isSorter; /* True if a new-style sorter */
-+ Bool multiPseudo; /* Multi-register pseudo-cursor */
-+ sqlite3_vtab_cursor *pVtabCursor; /* The cursor for a virtual table */
-+ const sqlite3_module *pModule; /* Module for cursor pVtabCursor */
-+ i64 seqCount; /* Sequence counter */
-+ i64 movetoTarget; /* Argument to the deferred sqlite3BtreeMoveto() */
-+ i64 lastRowid; /* Last rowid from a Next or NextIdx operation */
-+ VdbeSorter *pSorter; /* Sorter object for OP_SorterOpen cursors */
-
--#endif /* SQLITE_SYSTEM_MALLOC */
-+ /* Result of last sqlite3BtreeMoveto() done by an OP_NotExists or
-+ ** OP_IsUnique opcode on this cursor. */
-+ int seekResult;
-+
-+ /* Cached information about the header for the data record that the
-+ ** cursor is currently pointing to. Only valid if cacheStatus matches
-+ ** Vdbe.cacheCtr. Vdbe.cacheCtr will never take on the value of
-+ ** CACHE_STALE and so setting cacheStatus=CACHE_STALE guarantees that
-+ ** the cache is out of date.
-+ **
-+ ** aRow might point to (ephemeral) data for the current row, or it might
-+ ** be NULL.
-+ */
-+ u32 cacheStatus; /* Cache is valid if this matches Vdbe.cacheCtr */
-+ int payloadSize; /* Total number of bytes in the record */
-+ u32 *aType; /* Type values for all entries in the record */
-+ u32 *aOffset; /* Cached offsets to the start of each columns data */
-+ u8 *aRow; /* Data for the current row, if all on one page */
-+};
-+typedef struct VdbeCursor VdbeCursor;
-
--/************** End of mem1.c ************************************************/
--/************** Begin file mem2.c ********************************************/
- /*
--** 2007 August 15
--**
--** The author disclaims copyright to this source code. In place of
--** a legal notice, here is a blessing:
--**
--** May you do good and not evil.
--** May you find forgiveness for yourself and forgive others.
--** May you share freely, never taking more than you give.
--**
--*************************************************************************
-+** When a sub-program is executed (OP_Program), a structure of this type
-+** is allocated to store the current value of the program counter, as
-+** well as the current memory cell array and various other frame specific
-+** values stored in the Vdbe struct. When the sub-program is finished,
-+** these values are copied back to the Vdbe from the VdbeFrame structure,
-+** restoring the state of the VM to as it was before the sub-program
-+** began executing.
- **
--** This file contains low-level memory allocation drivers for when
--** SQLite will use the standard C-library malloc/realloc/free interface
--** to obtain the memory it needs while adding lots of additional debugging
--** information to each allocation in order to help detect and fix memory
--** leaks and memory usage errors.
-+** The memory for a VdbeFrame object is allocated and managed by a memory
-+** cell in the parent (calling) frame. When the memory cell is deleted or
-+** overwritten, the VdbeFrame object is not freed immediately. Instead, it
-+** is linked into the Vdbe.pDelFrame list. The contents of the Vdbe.pDelFrame
-+** list is deleted when the VM is reset in VdbeHalt(). The reason for doing
-+** this instead of deleting the VdbeFrame immediately is to avoid recursive
-+** calls to sqlite3VdbeMemRelease() when the memory cells belonging to the
-+** child frame are released.
- **
--** This file contains implementations of the low-level memory allocation
--** routines specified in the sqlite3_mem_methods object.
-+** The currently executing frame is stored in Vdbe.pFrame. Vdbe.pFrame is
-+** set to NULL if the currently executing frame is the main program.
- */
-+typedef struct VdbeFrame VdbeFrame;
-+struct VdbeFrame {
-+ Vdbe *v; /* VM this frame belongs to */
-+ VdbeFrame *pParent; /* Parent of this frame, or NULL if parent is main */
-+ Op *aOp; /* Program instructions for parent frame */
-+ Mem *aMem; /* Array of memory cells for parent frame */
-+ u8 *aOnceFlag; /* Array of OP_Once flags for parent frame */
-+ VdbeCursor **apCsr; /* Array of Vdbe cursors for parent frame */
-+ void *token; /* Copy of SubProgram.token */
-+ i64 lastRowid; /* Last insert rowid (sqlite3.lastRowid) */
-+ int nCursor; /* Number of entries in apCsr */
-+ int pc; /* Program Counter in parent (calling) frame */
-+ int nOp; /* Size of aOp array */
-+ int nMem; /* Number of entries in aMem */
-+ int nOnceFlag; /* Number of entries in aOnceFlag */
-+ int nChildMem; /* Number of memory cells for child frame */
-+ int nChildCsr; /* Number of cursors for child frame */
-+ int nChange; /* Statement changes (Vdbe.nChanges) */
-+};
-+
-+#define VdbeFrameMem(p) ((Mem *)&((u8 *)p)[ROUND8(sizeof(VdbeFrame))])
-
- /*
--** This version of the memory allocator is used only if the
--** SQLITE_MEMDEBUG macro is defined
-+** A value for VdbeCursor.cacheValid that means the cache is always invalid.
- */
--#ifdef SQLITE_MEMDEBUG
-+#define CACHE_STALE 0
-
- /*
--** The backtrace functionality is only available with GLIBC
-+** Internally, the vdbe manipulates nearly all SQL values as Mem
-+** structures. Each Mem struct may cache multiple representations (string,
-+** integer etc.) of the same value.
- */
--#ifdef __GLIBC__
-- extern int backtrace(void**,int);
-- extern void backtrace_symbols_fd(void*const*,int,int);
--#else
--# define backtrace(A,B) 1
--# define backtrace_symbols_fd(A,B,C)
-+struct Mem {
-+ sqlite3 *db; /* The associated database connection */
-+ char *z; /* String or BLOB value */
-+ double r; /* Real value */
-+ union {
-+ i64 i; /* Integer value used when MEM_Int is set in flags */
-+ int nZero; /* Used when bit MEM_Zero is set in flags */
-+ FuncDef *pDef; /* Used only when flags==MEM_Agg */
-+ RowSet *pRowSet; /* Used only when flags==MEM_RowSet */
-+ VdbeFrame *pFrame; /* Used when flags==MEM_Frame */
-+ } u;
-+ int n; /* Number of characters in string value, excluding '\0' */
-+ u16 flags; /* Some combination of MEM_Null, MEM_Str, MEM_Dyn, etc. */
-+ u8 type; /* One of SQLITE_NULL, SQLITE_TEXT, SQLITE_INTEGER, etc */
-+ u8 enc; /* SQLITE_UTF8, SQLITE_UTF16BE, SQLITE_UTF16LE */
-+#ifdef SQLITE_DEBUG
-+ Mem *pScopyFrom; /* This Mem is a shallow copy of pScopyFrom */
-+ void *pFiller; /* So that sizeof(Mem) is a multiple of 8 */
- #endif
--/* #include <stdio.h> */
-+ void (*xDel)(void *); /* If not null, call this function to delete Mem.z */
-+ char *zMalloc; /* Dynamic buffer allocated by sqlite3_malloc() */
-+};
-
--/*
--** Each memory allocation looks like this:
-+/* One or more of the following flags are set to indicate the validOK
-+** representations of the value stored in the Mem struct.
- **
--** ------------------------------------------------------------------------
--** | Title | backtrace pointers | MemBlockHdr | allocation | EndGuard |
--** ------------------------------------------------------------------------
-+** If the MEM_Null flag is set, then the value is an SQL NULL value.
-+** No other flags may be set in this case.
- **
--** The application code sees only a pointer to the allocation. We have
--** to back up from the allocation pointer to find the MemBlockHdr. The
--** MemBlockHdr tells us the size of the allocation and the number of
--** backtrace pointers. There is also a guard word at the end of the
--** MemBlockHdr.
-+** If the MEM_Str flag is set then Mem.z points at a string representation.
-+** Usually this is encoded in the same unicode encoding as the main
-+** database (see below for exceptions). If the MEM_Term flag is also
-+** set, then the string is nul terminated. The MEM_Int and MEM_Real
-+** flags may coexist with the MEM_Str flag.
- */
--struct MemBlockHdr {
-- i64 iSize; /* Size of this allocation */
-- struct MemBlockHdr *pNext, *pPrev; /* Linked list of all unfreed memory */
-- char nBacktrace; /* Number of backtraces on this alloc */
-- char nBacktraceSlots; /* Available backtrace slots */
-- u8 nTitle; /* Bytes of title; includes '\0' */
-- u8 eType; /* Allocation type code */
-- int iForeGuard; /* Guard word for sanity */
--};
-+#define MEM_Null 0x0001 /* Value is NULL */
-+#define MEM_Str 0x0002 /* Value is a string */
-+#define MEM_Int 0x0004 /* Value is an integer */
-+#define MEM_Real 0x0008 /* Value is a real number */
-+#define MEM_Blob 0x0010 /* Value is a BLOB */
-+#define MEM_RowSet 0x0020 /* Value is a RowSet object */
-+#define MEM_Frame 0x0040 /* Value is a VdbeFrame object */
-+#define MEM_Invalid 0x0080 /* Value is undefined */
-+#define MEM_Cleared 0x0100 /* NULL set by OP_Null, not from data */
-+#define MEM_TypeMask 0x01ff /* Mask of type bits */
-
--/*
--** Guard words
-+
-+/* Whenever Mem contains a valid string or blob representation, one of
-+** the following flags must be set to determine the memory management
-+** policy for Mem.z. The MEM_Term flag tells us whether or not the
-+** string is \000 or \u0000 terminated
- */
--#define FOREGUARD 0x80F5E153
--#define REARGUARD 0xE4676B53
-+#define MEM_Term 0x0200 /* String rep is nul terminated */
-+#define MEM_Dyn 0x0400 /* Need to call sqliteFree() on Mem.z */
-+#define MEM_Static 0x0800 /* Mem.z points to a static string */
-+#define MEM_Ephem 0x1000 /* Mem.z points to an ephemeral string */
-+#define MEM_Agg 0x2000 /* Mem.z points to an agg function context */
-+#define MEM_Zero 0x4000 /* Mem.i contains count of 0s appended to blob */
-+#ifdef SQLITE_OMIT_INCRBLOB
-+ #undef MEM_Zero
-+ #define MEM_Zero 0x0000
-+#endif
-
- /*
--** Number of malloc size increments to track.
-+** Clear any existing type flags from a Mem and replace them with f
- */
--#define NCSIZE 1000
-+#define MemSetTypeFlag(p, f) \
-+ ((p)->flags = ((p)->flags&~(MEM_TypeMask|MEM_Zero))|f)
-
- /*
--** All of the static variables used by this module are collected
--** into a single structure named "mem". This is to keep the
--** static variables organized and to reduce namespace pollution
--** when this module is combined with other in the amalgamation.
-+** Return true if a memory cell is not marked as invalid. This macro
-+** is for use inside assert() statements only.
- */
--static struct {
--
-- /*
-- ** Mutex to control access to the memory allocation subsystem.
-- */
-- sqlite3_mutex *mutex;
--
-- /*
-- ** Head and tail of a linked list of all outstanding allocations
-- */
-- struct MemBlockHdr *pFirst;
-- struct MemBlockHdr *pLast;
--
-- /*
-- ** The number of levels of backtrace to save in new allocations.
-- */
-- int nBacktrace;
-- void (*xBacktrace)(int, int, void **);
--
-- /*
-- ** Title text to insert in front of each block
-- */
-- int nTitle; /* Bytes of zTitle to save. Includes '\0' and padding */
-- char zTitle[100]; /* The title text */
--
-- /*
-- ** sqlite3MallocDisallow() increments the following counter.
-- ** sqlite3MallocAllow() decrements it.
-- */
-- int disallow; /* Do not allow memory allocation */
--
-- /*
-- ** Gather statistics on the sizes of memory allocations.
-- ** nAlloc[i] is the number of allocation attempts of i*8
-- ** bytes. i==NCSIZE is the number of allocation attempts for
-- ** sizes more than NCSIZE*8 bytes.
-- */
-- int nAlloc[NCSIZE]; /* Total number of allocations */
-- int nCurrent[NCSIZE]; /* Current number of allocations */
-- int mxCurrent[NCSIZE]; /* Highwater mark for nCurrent */
--
--} mem;
-+#ifdef SQLITE_DEBUG
-+#define memIsValid(M) ((M)->flags & MEM_Invalid)==0
-+#endif
-
-
--/*
--** Adjust memory usage statistics
-+/* A VdbeFunc is just a FuncDef (defined in sqliteInt.h) that contains
-+** additional information about auxiliary information bound to arguments
-+** of the function. This is used to implement the sqlite3_get_auxdata()
-+** and sqlite3_set_auxdata() APIs. The "auxdata" is some auxiliary data
-+** that can be associated with a constant argument to a function. This
-+** allows functions such as "regexp" to compile their constant regular
-+** expression argument once and reused the compiled code for multiple
-+** invocations.
- */
--static void adjustStats(int iSize, int increment){
-- int i = ROUND8(iSize)/8;
-- if( i>NCSIZE-1 ){
-- i = NCSIZE - 1;
-- }
-- if( increment>0 ){
-- mem.nAlloc[i]++;
-- mem.nCurrent[i]++;
-- if( mem.nCurrent[i]>mem.mxCurrent[i] ){
-- mem.mxCurrent[i] = mem.nCurrent[i];
-- }
-- }else{
-- mem.nCurrent[i]--;
-- assert( mem.nCurrent[i]>=0 );
-- }
--}
-+struct VdbeFunc {
-+ FuncDef *pFunc; /* The definition of the function */
-+ int nAux; /* Number of entries allocated for apAux[] */
-+ struct AuxData {
-+ void *pAux; /* Aux data for the i-th argument */
-+ void (*xDelete)(void *); /* Destructor for the aux data */
-+ } apAux[1]; /* One slot for each function argument */
-+};
-
- /*
--** Given an allocation, find the MemBlockHdr for that allocation.
-+** The "context" argument for a installable function. A pointer to an
-+** instance of this structure is the first argument to the routines used
-+** implement the SQL functions.
- **
--** This routine checks the guards at either end of the allocation and
--** if they are incorrect it asserts.
-+** There is a typedef for this structure in sqlite.h. So all routines,
-+** even the public interface to SQLite, can use a pointer to this structure.
-+** But this file is the only place where the internal details of this
-+** structure are known.
-+**
-+** This structure is defined inside of vdbeInt.h because it uses substructures
-+** (Mem) which are only defined there.
- */
--static struct MemBlockHdr *sqlite3MemsysGetHeader(void *pAllocation){
-- struct MemBlockHdr *p;
-- int *pInt;
-- u8 *pU8;
-- int nReserve;
--
-- p = (struct MemBlockHdr*)pAllocation;
-- p--;
-- assert( p->iForeGuard==(int)FOREGUARD );
-- nReserve = ROUND8(p->iSize);
-- pInt = (int*)pAllocation;
-- pU8 = (u8*)pAllocation;
-- assert( pInt[nReserve/sizeof(int)]==(int)REARGUARD );
-- /* This checks any of the "extra" bytes allocated due
-- ** to rounding up to an 8 byte boundary to ensure
-- ** they haven't been overwritten.
-- */
-- while( nReserve-- > p->iSize ) assert( pU8[nReserve]==0x65 );
-- return p;
--}
-+struct sqlite3_context {
-+ FuncDef *pFunc; /* Pointer to function information. MUST BE FIRST */
-+ VdbeFunc *pVdbeFunc; /* Auxilary data, if created. */
-+ Mem s; /* The return value is stored here */
-+ Mem *pMem; /* Memory cell used to store aggregate context */
-+ CollSeq *pColl; /* Collating sequence */
-+ int isError; /* Error code returned by the function. */
-+ int skipFlag; /* Skip skip accumulator loading if true */
-+};
-
- /*
--** Return the number of bytes currently allocated at address p.
-+** An Explain object accumulates indented output which is helpful
-+** in describing recursive data structures.
- */
--static int sqlite3MemSize(void *p){
-- struct MemBlockHdr *pHdr;
-- if( !p ){
-- return 0;
-- }
-- pHdr = sqlite3MemsysGetHeader(p);
-- return pHdr->iSize;
--}
-+struct Explain {
-+ Vdbe *pVdbe; /* Attach the explanation to this Vdbe */
-+ StrAccum str; /* The string being accumulated */
-+ int nIndent; /* Number of elements in aIndent */
-+ u16 aIndent[100]; /* Levels of indentation */
-+ char zBase[100]; /* Initial space */
-+};
-
--/*
--** Initialize the memory allocation subsystem.
-+/* A bitfield type for use inside of structures. Always follow with :N where
-+** N is the number of bits.
- */
--static int sqlite3MemInit(void *NotUsed){
-- UNUSED_PARAMETER(NotUsed);
-- assert( (sizeof(struct MemBlockHdr)&7) == 0 );
-- if( !sqlite3GlobalConfig.bMemstat ){
-- /* If memory status is enabled, then the malloc.c wrapper will already
-- ** hold the STATIC_MEM mutex when the routines here are invoked. */
-- mem.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM);
-- }
-- return SQLITE_OK;
--}
-+typedef unsigned bft; /* Bit Field Type */
-
- /*
--** Deinitialize the memory allocation subsystem.
-+** An instance of the virtual machine. This structure contains the complete
-+** state of the virtual machine.
-+**
-+** The "sqlite3_stmt" structure pointer that is returned by sqlite3_prepare()
-+** is really a pointer to an instance of this structure.
-+**
-+** The Vdbe.inVtabMethod variable is set to non-zero for the duration of
-+** any virtual table method invocations made by the vdbe program. It is
-+** set to 2 for xDestroy method calls and 1 for all other methods. This
-+** variable is used for two purposes: to allow xDestroy methods to execute
-+** "DROP TABLE" statements and to prevent some nasty side effects of
-+** malloc failure when SQLite is invoked recursively by a virtual table
-+** method function.
- */
--static void sqlite3MemShutdown(void *NotUsed){
-- UNUSED_PARAMETER(NotUsed);
-- mem.mutex = 0;
--}
-+struct Vdbe {
-+ sqlite3 *db; /* The database connection that owns this statement */
-+ Op *aOp; /* Space to hold the virtual machine's program */
-+ Mem *aMem; /* The memory locations */
-+ Mem **apArg; /* Arguments to currently executing user function */
-+ Mem *aColName; /* Column names to return */
-+ Mem *pResultSet; /* Pointer to an array of results */
-+ int nMem; /* Number of memory locations currently allocated */
-+ int nOp; /* Number of instructions in the program */
-+ int nOpAlloc; /* Number of slots allocated for aOp[] */
-+ int nLabel; /* Number of labels used */
-+ int *aLabel; /* Space to hold the labels */
-+ u16 nResColumn; /* Number of columns in one row of the result set */
-+ int nCursor; /* Number of slots in apCsr[] */
-+ u32 magic; /* Magic number for sanity checking */
-+ char *zErrMsg; /* Error message written here */
-+ Vdbe *pPrev,*pNext; /* Linked list of VDBEs with the same Vdbe.db */
-+ VdbeCursor **apCsr; /* One element of this array for each open cursor */
-+ Mem *aVar; /* Values for the OP_Variable opcode. */
-+ char **azVar; /* Name of variables */
-+ ynVar nVar; /* Number of entries in aVar[] */
-+ ynVar nzVar; /* Number of entries in azVar[] */
-+ u32 cacheCtr; /* VdbeCursor row cache generation counter */
-+ int pc; /* The program counter */
-+ int rc; /* Value to return */
-+ u8 errorAction; /* Recovery action to do in case of an error */
-+ u8 minWriteFileFormat; /* Minimum file format for writable database files */
-+ bft explain:2; /* True if EXPLAIN present on SQL command */
-+ bft inVtabMethod:2; /* See comments above */
-+ bft changeCntOn:1; /* True to update the change-counter */
-+ bft expired:1; /* True if the VM needs to be recompiled */
-+ bft runOnlyOnce:1; /* Automatically expire on reset */
-+ bft usesStmtJournal:1; /* True if uses a statement journal */
-+ bft readOnly:1; /* True for read-only statements */
-+ bft isPrepareV2:1; /* True if prepared with prepare_v2() */
-+ bft doingRerun:1; /* True if rerunning after an auto-reprepare */
-+ int nChange; /* Number of db changes made since last reset */
-+ yDbMask btreeMask; /* Bitmask of db->aDb[] entries referenced */
-+ yDbMask lockMask; /* Subset of btreeMask that requires a lock */
-+ int iStatement; /* Statement number (or 0 if has not opened stmt) */
-+ int aCounter[3]; /* Counters used by sqlite3_stmt_status() */
-+#ifndef SQLITE_OMIT_TRACE
-+ i64 startTime; /* Time when query started - used for profiling */
-+#endif
-+ i64 nFkConstraint; /* Number of imm. FK constraints this VM */
-+ i64 nStmtDefCons; /* Number of def. constraints when stmt started */
-+ char *zSql; /* Text of the SQL statement that generated this */
-+ void *pFree; /* Free this when deleting the vdbe */
-+#ifdef SQLITE_DEBUG
-+ FILE *trace; /* Write an execution trace here, if not NULL */
-+#endif
-+#ifdef SQLITE_ENABLE_TREE_EXPLAIN
-+ Explain *pExplain; /* The explainer */
-+ char *zExplain; /* Explanation of data structures */
-+#endif
-+ VdbeFrame *pFrame; /* Parent frame */
-+ VdbeFrame *pDelFrame; /* List of frame objects to free on VM reset */
-+ int nFrame; /* Number of frames in pFrame list */
-+ u32 expmask; /* Binding to these vars invalidates VM */
-+ SubProgram *pProgram; /* Linked list of all sub-programs used by VM */
-+ int nOnceFlag; /* Size of array aOnceFlag[] */
-+ u8 *aOnceFlag; /* Flags for OP_Once */
-+};
-
- /*
--** Round up a request size to the next valid allocation size.
-+** The following are allowed values for Vdbe.magic
- */
--static int sqlite3MemRoundup(int n){
-- return ROUND8(n);
--}
-+#define VDBE_MAGIC_INIT 0x26bceaa5 /* Building a VDBE program */
-+#define VDBE_MAGIC_RUN 0xbdf20da3 /* VDBE is ready to execute */
-+#define VDBE_MAGIC_HALT 0x519c2973 /* VDBE has completed execution */
-+#define VDBE_MAGIC_DEAD 0xb606c3c8 /* The VDBE has been deallocated */
-
- /*
--** Fill a buffer with pseudo-random bytes. This is used to preset
--** the content of a new memory allocation to unpredictable values and
--** to clear the content of a freed allocation to unpredictable values.
-+** Function prototypes
- */
--static void randomFill(char *pBuf, int nByte){
-- unsigned int x, y, r;
-- x = SQLITE_PTR_TO_INT(pBuf);
-- y = nByte | 1;
-- while( nByte >= 4 ){
-- x = (x>>1) ^ (-(x&1) & 0xd0000001);
-- y = y*1103515245 + 12345;
-- r = x ^ y;
-- *(int*)pBuf = r;
-- pBuf += 4;
-- nByte -= 4;
-- }
-- while( nByte-- > 0 ){
-- x = (x>>1) ^ (-(x&1) & 0xd0000001);
-- y = y*1103515245 + 12345;
-- r = x ^ y;
-- *(pBuf++) = r & 0xff;
-- }
--}
-+SQLITE_PRIVATE void sqlite3VdbeFreeCursor(Vdbe *, VdbeCursor*);
-+void sqliteVdbePopStack(Vdbe*,int);
-+SQLITE_PRIVATE int sqlite3VdbeCursorMoveto(VdbeCursor*);
-+#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE)
-+SQLITE_PRIVATE void sqlite3VdbePrintOp(FILE*, int, Op*);
-+#endif
-+SQLITE_PRIVATE u32 sqlite3VdbeSerialTypeLen(u32);
-+SQLITE_PRIVATE u32 sqlite3VdbeSerialType(Mem*, int);
-+SQLITE_PRIVATE u32 sqlite3VdbeSerialPut(unsigned char*, int, Mem*, int);
-+SQLITE_PRIVATE u32 sqlite3VdbeSerialGet(const unsigned char*, u32, Mem*);
-+SQLITE_PRIVATE void sqlite3VdbeDeleteAuxData(VdbeFunc*, int);
-
--/*
--** Allocate nByte bytes of memory.
--*/
--static void *sqlite3MemMalloc(int nByte){
-- struct MemBlockHdr *pHdr;
-- void **pBt;
-- char *z;
-- int *pInt;
-- void *p = 0;
-- int totalSize;
-- int nReserve;
-- sqlite3_mutex_enter(mem.mutex);
-- assert( mem.disallow==0 );
-- nReserve = ROUND8(nByte);
-- totalSize = nReserve + sizeof(*pHdr) + sizeof(int) +
-- mem.nBacktrace*sizeof(void*) + mem.nTitle;
-- p = malloc(totalSize);
-- if( p ){
-- z = p;
-- pBt = (void**)&z[mem.nTitle];
-- pHdr = (struct MemBlockHdr*)&pBt[mem.nBacktrace];
-- pHdr->pNext = 0;
-- pHdr->pPrev = mem.pLast;
-- if( mem.pLast ){
-- mem.pLast->pNext = pHdr;
-- }else{
-- mem.pFirst = pHdr;
-- }
-- mem.pLast = pHdr;
-- pHdr->iForeGuard = FOREGUARD;
-- pHdr->eType = MEMTYPE_HEAP;
-- pHdr->nBacktraceSlots = mem.nBacktrace;
-- pHdr->nTitle = mem.nTitle;
-- if( mem.nBacktrace ){
-- void *aAddr[40];
-- pHdr->nBacktrace = backtrace(aAddr, mem.nBacktrace+1)-1;
-- memcpy(pBt, &aAddr[1], pHdr->nBacktrace*sizeof(void*));
-- assert(pBt[0]);
-- if( mem.xBacktrace ){
-- mem.xBacktrace(nByte, pHdr->nBacktrace-1, &aAddr[1]);
-- }
-- }else{
-- pHdr->nBacktrace = 0;
-- }
-- if( mem.nTitle ){
-- memcpy(z, mem.zTitle, mem.nTitle);
-- }
-- pHdr->iSize = nByte;
-- adjustStats(nByte, +1);
-- pInt = (int*)&pHdr[1];
-- pInt[nReserve/sizeof(int)] = REARGUARD;
-- randomFill((char*)pInt, nByte);
-- memset(((char*)pInt)+nByte, 0x65, nReserve-nByte);
-- p = (void*)pInt;
-- }
-- sqlite3_mutex_leave(mem.mutex);
-- return p;
--}
-+int sqlite2BtreeKeyCompare(BtCursor *, const void *, int, int, int *);
-+SQLITE_PRIVATE int sqlite3VdbeIdxKeyCompare(VdbeCursor*,UnpackedRecord*,int*);
-+SQLITE_PRIVATE int sqlite3VdbeIdxRowid(sqlite3*, BtCursor *, i64 *);
-+SQLITE_PRIVATE int sqlite3MemCompare(const Mem*, const Mem*, const CollSeq*);
-+SQLITE_PRIVATE int sqlite3VdbeExec(Vdbe*);
-+SQLITE_PRIVATE int sqlite3VdbeList(Vdbe*);
-+SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe*);
-+SQLITE_PRIVATE int sqlite3VdbeChangeEncoding(Mem *, int);
-+SQLITE_PRIVATE int sqlite3VdbeMemTooBig(Mem*);
-+SQLITE_PRIVATE int sqlite3VdbeMemCopy(Mem*, const Mem*);
-+SQLITE_PRIVATE void sqlite3VdbeMemShallowCopy(Mem*, const Mem*, int);
-+SQLITE_PRIVATE void sqlite3VdbeMemMove(Mem*, Mem*);
-+SQLITE_PRIVATE int sqlite3VdbeMemNulTerminate(Mem*);
-+SQLITE_PRIVATE int sqlite3VdbeMemSetStr(Mem*, const char*, int, u8, void(*)(void*));
-+SQLITE_PRIVATE void sqlite3VdbeMemSetInt64(Mem*, i64);
-+#ifdef SQLITE_OMIT_FLOATING_POINT
-+# define sqlite3VdbeMemSetDouble sqlite3VdbeMemSetInt64
-+#else
-+SQLITE_PRIVATE void sqlite3VdbeMemSetDouble(Mem*, double);
-+#endif
-+SQLITE_PRIVATE void sqlite3VdbeMemSetNull(Mem*);
-+SQLITE_PRIVATE void sqlite3VdbeMemSetZeroBlob(Mem*,int);
-+SQLITE_PRIVATE void sqlite3VdbeMemSetRowSet(Mem*);
-+SQLITE_PRIVATE int sqlite3VdbeMemMakeWriteable(Mem*);
-+SQLITE_PRIVATE int sqlite3VdbeMemStringify(Mem*, int);
-+SQLITE_PRIVATE i64 sqlite3VdbeIntValue(Mem*);
-+SQLITE_PRIVATE int sqlite3VdbeMemIntegerify(Mem*);
-+SQLITE_PRIVATE double sqlite3VdbeRealValue(Mem*);
-+SQLITE_PRIVATE void sqlite3VdbeIntegerAffinity(Mem*);
-+SQLITE_PRIVATE int sqlite3VdbeMemRealify(Mem*);
-+SQLITE_PRIVATE int sqlite3VdbeMemNumerify(Mem*);
-+SQLITE_PRIVATE int sqlite3VdbeMemFromBtree(BtCursor*,int,int,int,Mem*);
-+SQLITE_PRIVATE void sqlite3VdbeMemRelease(Mem *p);
-+SQLITE_PRIVATE void sqlite3VdbeMemReleaseExternal(Mem *p);
-+#define VdbeMemRelease(X) \
-+ if((X)->flags&(MEM_Agg|MEM_Dyn|MEM_RowSet|MEM_Frame)) \
-+ sqlite3VdbeMemReleaseExternal(X);
-+SQLITE_PRIVATE int sqlite3VdbeMemFinalize(Mem*, FuncDef*);
-+SQLITE_PRIVATE const char *sqlite3OpcodeName(int);
-+SQLITE_PRIVATE int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve);
-+SQLITE_PRIVATE int sqlite3VdbeCloseStatement(Vdbe *, int);
-+SQLITE_PRIVATE void sqlite3VdbeFrameDelete(VdbeFrame*);
-+SQLITE_PRIVATE int sqlite3VdbeFrameRestore(VdbeFrame *);
-+SQLITE_PRIVATE void sqlite3VdbeMemStoreType(Mem *pMem);
-+SQLITE_PRIVATE int sqlite3VdbeTransferError(Vdbe *p);
-+
-+SQLITE_PRIVATE int sqlite3VdbeSorterInit(sqlite3 *, VdbeCursor *);
-+SQLITE_PRIVATE void sqlite3VdbeSorterClose(sqlite3 *, VdbeCursor *);
-+SQLITE_PRIVATE int sqlite3VdbeSorterRowkey(const VdbeCursor *, Mem *);
-+SQLITE_PRIVATE int sqlite3VdbeSorterNext(sqlite3 *, const VdbeCursor *, int *);
-+SQLITE_PRIVATE int sqlite3VdbeSorterRewind(sqlite3 *, const VdbeCursor *, int *);
-+SQLITE_PRIVATE int sqlite3VdbeSorterWrite(sqlite3 *, const VdbeCursor *, Mem *);
-+SQLITE_PRIVATE int sqlite3VdbeSorterCompare(const VdbeCursor *, Mem *, int *);
-+
-+#if !defined(SQLITE_OMIT_SHARED_CACHE) && SQLITE_THREADSAFE>0
-+SQLITE_PRIVATE void sqlite3VdbeEnter(Vdbe*);
-+SQLITE_PRIVATE void sqlite3VdbeLeave(Vdbe*);
-+#else
-+# define sqlite3VdbeEnter(X)
-+# define sqlite3VdbeLeave(X)
-+#endif
-+
-+#ifdef SQLITE_DEBUG
-+SQLITE_PRIVATE void sqlite3VdbeMemAboutToChange(Vdbe*,Mem*);
-+#endif
-+
-+#ifndef SQLITE_OMIT_FOREIGN_KEY
-+SQLITE_PRIVATE int sqlite3VdbeCheckFk(Vdbe *, int);
-+#else
-+# define sqlite3VdbeCheckFk(p,i) 0
-+#endif
-+
-+SQLITE_PRIVATE int sqlite3VdbeMemTranslate(Mem*, u8);
-+#ifdef SQLITE_DEBUG
-+SQLITE_PRIVATE void sqlite3VdbePrintSql(Vdbe*);
-+SQLITE_PRIVATE void sqlite3VdbeMemPrettyPrint(Mem *pMem, char *zBuf);
-+#endif
-+SQLITE_PRIVATE int sqlite3VdbeMemHandleBom(Mem *pMem);
-+
-+#ifndef SQLITE_OMIT_INCRBLOB
-+SQLITE_PRIVATE int sqlite3VdbeMemExpandBlob(Mem *);
-+ #define ExpandBlob(P) (((P)->flags&MEM_Zero)?sqlite3VdbeMemExpandBlob(P):0)
-+#else
-+ #define sqlite3VdbeMemExpandBlob(x) SQLITE_OK
-+ #define ExpandBlob(P) SQLITE_OK
-+#endif
-+
-+#endif /* !defined(_VDBEINT_H_) */
-+
-+/************** End of vdbeInt.h *********************************************/
-+/************** Continuing where we left off in status.c *********************/
-
- /*
--** Free memory.
-+** Variables in which to record status information.
- */
--static void sqlite3MemFree(void *pPrior){
-- struct MemBlockHdr *pHdr;
-- void **pBt;
-- char *z;
-- assert( sqlite3GlobalConfig.bMemstat || sqlite3GlobalConfig.bCoreMutex==0
-- || mem.mutex!=0 );
-- pHdr = sqlite3MemsysGetHeader(pPrior);
-- pBt = (void**)pHdr;
-- pBt -= pHdr->nBacktraceSlots;
-- sqlite3_mutex_enter(mem.mutex);
-- if( pHdr->pPrev ){
-- assert( pHdr->pPrev->pNext==pHdr );
-- pHdr->pPrev->pNext = pHdr->pNext;
-- }else{
-- assert( mem.pFirst==pHdr );
-- mem.pFirst = pHdr->pNext;
-- }
-- if( pHdr->pNext ){
-- assert( pHdr->pNext->pPrev==pHdr );
-- pHdr->pNext->pPrev = pHdr->pPrev;
-- }else{
-- assert( mem.pLast==pHdr );
-- mem.pLast = pHdr->pPrev;
-- }
-- z = (char*)pBt;
-- z -= pHdr->nTitle;
-- adjustStats(pHdr->iSize, -1);
-- randomFill(z, sizeof(void*)*pHdr->nBacktraceSlots + sizeof(*pHdr) +
-- pHdr->iSize + sizeof(int) + pHdr->nTitle);
-- free(z);
-- sqlite3_mutex_leave(mem.mutex);
--}
-+typedef struct sqlite3StatType sqlite3StatType;
-+static SQLITE_WSD struct sqlite3StatType {
-+ int nowValue[10]; /* Current value */
-+ int mxValue[10]; /* Maximum value */
-+} sqlite3Stat = { {0,}, {0,} };
-
--/*
--** Change the size of an existing memory allocation.
--**
--** For this debugging implementation, we *always* make a copy of the
--** allocation into a new place in memory. In this way, if the
--** higher level code is using pointer to the old allocation, it is
--** much more likely to break and we are much more liking to find
--** the error.
-+
-+/* The "wsdStat" macro will resolve to the status information
-+** state vector. If writable static data is unsupported on the target,
-+** we have to locate the state vector at run-time. In the more common
-+** case where writable static data is supported, wsdStat can refer directly
-+** to the "sqlite3Stat" state vector declared above.
- */
--static void *sqlite3MemRealloc(void *pPrior, int nByte){
-- struct MemBlockHdr *pOldHdr;
-- void *pNew;
-- assert( mem.disallow==0 );
-- assert( (nByte & 7)==0 ); /* EV: R-46199-30249 */
-- pOldHdr = sqlite3MemsysGetHeader(pPrior);
-- pNew = sqlite3MemMalloc(nByte);
-- if( pNew ){
-- memcpy(pNew, pPrior, nByte<pOldHdr->iSize ? nByte : pOldHdr->iSize);
-- if( nByte>pOldHdr->iSize ){
-- randomFill(&((char*)pNew)[pOldHdr->iSize], nByte - pOldHdr->iSize);
-- }
-- sqlite3MemFree(pPrior);
-- }
-- return pNew;
--}
-+#ifdef SQLITE_OMIT_WSD
-+# define wsdStatInit sqlite3StatType *x = &GLOBAL(sqlite3StatType,sqlite3Stat)
-+# define wsdStat x[0]
-+#else
-+# define wsdStatInit
-+# define wsdStat sqlite3Stat
-+#endif
-
- /*
--** Populate the low-level memory allocation function pointers in
--** sqlite3GlobalConfig.m with pointers to the routines in this file.
-+** Return the current value of a status parameter.
- */
--SQLITE_PRIVATE void sqlite3MemSetDefault(void){
-- static const sqlite3_mem_methods defaultMethods = {
-- sqlite3MemMalloc,
-- sqlite3MemFree,
-- sqlite3MemRealloc,
-- sqlite3MemSize,
-- sqlite3MemRoundup,
-- sqlite3MemInit,
-- sqlite3MemShutdown,
-- 0
-- };
-- sqlite3_config(SQLITE_CONFIG_MALLOC, &defaultMethods);
-+SQLITE_PRIVATE int sqlite3StatusValue(int op){
-+ wsdStatInit;
-+ assert( op>=0 && op<ArraySize(wsdStat.nowValue) );
-+ return wsdStat.nowValue[op];
- }
-
- /*
--** Set the "type" of an allocation.
-+** Add N to the value of a status record. It is assumed that the
-+** caller holds appropriate locks.
- */
--SQLITE_PRIVATE void sqlite3MemdebugSetType(void *p, u8 eType){
-- if( p && sqlite3GlobalConfig.m.xMalloc==sqlite3MemMalloc ){
-- struct MemBlockHdr *pHdr;
-- pHdr = sqlite3MemsysGetHeader(p);
-- assert( pHdr->iForeGuard==FOREGUARD );
-- pHdr->eType = eType;
-+SQLITE_PRIVATE void sqlite3StatusAdd(int op, int N){
-+ wsdStatInit;
-+ assert( op>=0 && op<ArraySize(wsdStat.nowValue) );
-+ wsdStat.nowValue[op] += N;
-+ if( wsdStat.nowValue[op]>wsdStat.mxValue[op] ){
-+ wsdStat.mxValue[op] = wsdStat.nowValue[op];
- }
- }
-
- /*
--** Return TRUE if the mask of type in eType matches the type of the
--** allocation p. Also return true if p==NULL.
--**
--** This routine is designed for use within an assert() statement, to
--** verify the type of an allocation. For example:
--**
--** assert( sqlite3MemdebugHasType(p, MEMTYPE_DB) );
-+** Set the value of a status to X.
- */
--SQLITE_PRIVATE int sqlite3MemdebugHasType(void *p, u8 eType){
-- int rc = 1;
-- if( p && sqlite3GlobalConfig.m.xMalloc==sqlite3MemMalloc ){
-- struct MemBlockHdr *pHdr;
-- pHdr = sqlite3MemsysGetHeader(p);
-- assert( pHdr->iForeGuard==FOREGUARD ); /* Allocation is valid */
-- if( (pHdr->eType&eType)==0 ){
-- rc = 0;
-- }
-+SQLITE_PRIVATE void sqlite3StatusSet(int op, int X){
-+ wsdStatInit;
-+ assert( op>=0 && op<ArraySize(wsdStat.nowValue) );
-+ wsdStat.nowValue[op] = X;
-+ if( wsdStat.nowValue[op]>wsdStat.mxValue[op] ){
-+ wsdStat.mxValue[op] = wsdStat.nowValue[op];
- }
-- return rc;
- }
-
- /*
--** Return TRUE if the mask of type in eType matches no bits of the type of the
--** allocation p. Also return true if p==NULL.
--**
--** This routine is designed for use within an assert() statement, to
--** verify the type of an allocation. For example:
-+** Query status information.
- **
--** assert( sqlite3MemdebugNoType(p, MEMTYPE_DB) );
-+** This implementation assumes that reading or writing an aligned
-+** 32-bit integer is an atomic operation. If that assumption is not true,
-+** then this routine is not threadsafe.
- */
--SQLITE_PRIVATE int sqlite3MemdebugNoType(void *p, u8 eType){
-- int rc = 1;
-- if( p && sqlite3GlobalConfig.m.xMalloc==sqlite3MemMalloc ){
-- struct MemBlockHdr *pHdr;
-- pHdr = sqlite3MemsysGetHeader(p);
-- assert( pHdr->iForeGuard==FOREGUARD ); /* Allocation is valid */
-- if( (pHdr->eType&eType)!=0 ){
-- rc = 0;
-- }
-+SQLITE_API int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag){
-+ wsdStatInit;
-+ if( op<0 || op>=ArraySize(wsdStat.nowValue) ){
-+ return SQLITE_MISUSE_BKPT;
- }
-- return rc;
--}
--
--/*
--** Set the number of backtrace levels kept for each allocation.
--** A value of zero turns off backtracing. The number is always rounded
--** up to a multiple of 2.
--*/
--SQLITE_PRIVATE void sqlite3MemdebugBacktrace(int depth){
-- if( depth<0 ){ depth = 0; }
-- if( depth>20 ){ depth = 20; }
-- depth = (depth+1)&0xfe;
-- mem.nBacktrace = depth;
--}
--
--SQLITE_PRIVATE void sqlite3MemdebugBacktraceCallback(void (*xBacktrace)(int, int, void **)){
-- mem.xBacktrace = xBacktrace;
--}
--
--/*
--** Set the title string for subsequent allocations.
--*/
--SQLITE_PRIVATE void sqlite3MemdebugSettitle(const char *zTitle){
-- unsigned int n = sqlite3Strlen30(zTitle) + 1;
-- sqlite3_mutex_enter(mem.mutex);
-- if( n>=sizeof(mem.zTitle) ) n = sizeof(mem.zTitle)-1;
-- memcpy(mem.zTitle, zTitle, n);
-- mem.zTitle[n] = 0;
-- mem.nTitle = ROUND8(n);
-- sqlite3_mutex_leave(mem.mutex);
--}
--
--SQLITE_PRIVATE void sqlite3MemdebugSync(){
-- struct MemBlockHdr *pHdr;
-- for(pHdr=mem.pFirst; pHdr; pHdr=pHdr->pNext){
-- void **pBt = (void**)pHdr;
-- pBt -= pHdr->nBacktraceSlots;
-- mem.xBacktrace(pHdr->iSize, pHdr->nBacktrace-1, &pBt[1]);
-+ *pCurrent = wsdStat.nowValue[op];
-+ *pHighwater = wsdStat.mxValue[op];
-+ if( resetFlag ){
-+ wsdStat.mxValue[op] = wsdStat.nowValue[op];
- }
-+ return SQLITE_OK;
- }
-
- /*
--** Open the file indicated and write a log of all unfreed memory
--** allocations into that log.
-+** Query status information for a single database connection
- */
--SQLITE_PRIVATE void sqlite3MemdebugDump(const char *zFilename){
-- FILE *out;
-- struct MemBlockHdr *pHdr;
-- void **pBt;
-- int i;
-- out = fopen(zFilename, "w");
-- if( out==0 ){
-- fprintf(stderr, "** Unable to output memory debug output log: %s **\n",
-- zFilename);
-- return;
-- }
-- for(pHdr=mem.pFirst; pHdr; pHdr=pHdr->pNext){
-- char *z = (char*)pHdr;
-- z -= pHdr->nBacktraceSlots*sizeof(void*) + pHdr->nTitle;
-- fprintf(out, "**** %lld bytes at %p from %s ****\n",
-- pHdr->iSize, &pHdr[1], pHdr->nTitle ? z : "???");
-- if( pHdr->nBacktrace ){
-- fflush(out);
-- pBt = (void**)pHdr;
-- pBt -= pHdr->nBacktraceSlots;
-- backtrace_symbols_fd(pBt, pHdr->nBacktrace, fileno(out));
-- fprintf(out, "\n");
-+SQLITE_API int sqlite3_db_status(
-+ sqlite3 *db, /* The database connection whose status is desired */
-+ int op, /* Status verb */
-+ int *pCurrent, /* Write current value here */
-+ int *pHighwater, /* Write high-water mark here */
-+ int resetFlag /* Reset high-water mark if true */
-+){
-+ int rc = SQLITE_OK; /* Return code */
-+ sqlite3_mutex_enter(db->mutex);
-+ switch( op ){
-+ case SQLITE_DBSTATUS_LOOKASIDE_USED: {
-+ *pCurrent = db->lookaside.nOut;
-+ *pHighwater = db->lookaside.mxOut;
-+ if( resetFlag ){
-+ db->lookaside.mxOut = db->lookaside.nOut;
-+ }
-+ break;
- }
-- }
-- fprintf(out, "COUNTS:\n");
-- for(i=0; i<NCSIZE-1; i++){
-- if( mem.nAlloc[i] ){
-- fprintf(out, " %5d: %10d %10d %10d\n",
-- i*8, mem.nAlloc[i], mem.nCurrent[i], mem.mxCurrent[i]);
-+
-+ case SQLITE_DBSTATUS_LOOKASIDE_HIT:
-+ case SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE:
-+ case SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL: {
-+ testcase( op==SQLITE_DBSTATUS_LOOKASIDE_HIT );
-+ testcase( op==SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE );
-+ testcase( op==SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL );
-+ assert( (op-SQLITE_DBSTATUS_LOOKASIDE_HIT)>=0 );
-+ assert( (op-SQLITE_DBSTATUS_LOOKASIDE_HIT)<3 );
-+ *pCurrent = 0;
-+ *pHighwater = db->lookaside.anStat[op - SQLITE_DBSTATUS_LOOKASIDE_HIT];
-+ if( resetFlag ){
-+ db->lookaside.anStat[op - SQLITE_DBSTATUS_LOOKASIDE_HIT] = 0;
-+ }
-+ break;
- }
-- }
-- if( mem.nAlloc[NCSIZE-1] ){
-- fprintf(out, " %5d: %10d %10d %10d\n",
-- NCSIZE*8-8, mem.nAlloc[NCSIZE-1],
-- mem.nCurrent[NCSIZE-1], mem.mxCurrent[NCSIZE-1]);
-- }
-- fclose(out);
--}
-
--/*
--** Return the number of times sqlite3MemMalloc() has been called.
--*/
--SQLITE_PRIVATE int sqlite3MemdebugMallocCount(){
-- int i;
-- int nTotal = 0;
-- for(i=0; i<NCSIZE; i++){
-- nTotal += mem.nAlloc[i];
-- }
-- return nTotal;
--}
-+ /*
-+ ** Return an approximation for the amount of memory currently used
-+ ** by all pagers associated with the given database connection. The
-+ ** highwater mark is meaningless and is returned as zero.
-+ */
-+ case SQLITE_DBSTATUS_CACHE_USED: {
-+ int totalUsed = 0;
-+ int i;
-+ sqlite3BtreeEnterAll(db);
-+ for(i=0; i<db->nDb; i++){
-+ Btree *pBt = db->aDb[i].pBt;
-+ if( pBt ){
-+ Pager *pPager = sqlite3BtreePager(pBt);
-+ totalUsed += sqlite3PagerMemUsed(pPager);
-+ }
-+ }
-+ sqlite3BtreeLeaveAll(db);
-+ *pCurrent = totalUsed;
-+ *pHighwater = 0;
-+ break;
-+ }
-
-+ /*
-+ ** *pCurrent gets an accurate estimate of the amount of memory used
-+ ** to store the schema for all databases (main, temp, and any ATTACHed
-+ ** databases. *pHighwater is set to zero.
-+ */
-+ case SQLITE_DBSTATUS_SCHEMA_USED: {
-+ int i; /* Used to iterate through schemas */
-+ int nByte = 0; /* Used to accumulate return value */
-
--#endif /* SQLITE_MEMDEBUG */
-+ sqlite3BtreeEnterAll(db);
-+ db->pnBytesFreed = &nByte;
-+ for(i=0; i<db->nDb; i++){
-+ Schema *pSchema = db->aDb[i].pSchema;
-+ if( ALWAYS(pSchema!=0) ){
-+ HashElem *p;
-
--/************** End of mem2.c ************************************************/
--/************** Begin file mem3.c ********************************************/
--/*
--** 2007 October 14
-+ nByte += sqlite3GlobalConfig.m.xRoundup(sizeof(HashElem)) * (
-+ pSchema->tblHash.count
-+ + pSchema->trigHash.count
-+ + pSchema->idxHash.count
-+ + pSchema->fkeyHash.count
-+ );
-+ nByte += sqlite3MallocSize(pSchema->tblHash.ht);
-+ nByte += sqlite3MallocSize(pSchema->trigHash.ht);
-+ nByte += sqlite3MallocSize(pSchema->idxHash.ht);
-+ nByte += sqlite3MallocSize(pSchema->fkeyHash.ht);
-+
-+ for(p=sqliteHashFirst(&pSchema->trigHash); p; p=sqliteHashNext(p)){
-+ sqlite3DeleteTrigger(db, (Trigger*)sqliteHashData(p));
-+ }
-+ for(p=sqliteHashFirst(&pSchema->tblHash); p; p=sqliteHashNext(p)){
-+ sqlite3DeleteTable(db, (Table *)sqliteHashData(p));
-+ }
-+ }
-+ }
-+ db->pnBytesFreed = 0;
-+ sqlite3BtreeLeaveAll(db);
-+
-+ *pHighwater = 0;
-+ *pCurrent = nByte;
-+ break;
-+ }
-+
-+ /*
-+ ** *pCurrent gets an accurate estimate of the amount of memory used
-+ ** to store all prepared statements.
-+ ** *pHighwater is set to zero.
-+ */
-+ case SQLITE_DBSTATUS_STMT_USED: {
-+ struct Vdbe *pVdbe; /* Used to iterate through VMs */
-+ int nByte = 0; /* Used to accumulate return value */
-+
-+ db->pnBytesFreed = &nByte;
-+ for(pVdbe=db->pVdbe; pVdbe; pVdbe=pVdbe->pNext){
-+ sqlite3VdbeClearObject(db, pVdbe);
-+ sqlite3DbFree(db, pVdbe);
-+ }
-+ db->pnBytesFreed = 0;
-+
-+ *pHighwater = 0;
-+ *pCurrent = nByte;
-+
-+ break;
-+ }
-+
-+ /*
-+ ** Set *pCurrent to the total cache hits or misses encountered by all
-+ ** pagers the database handle is connected to. *pHighwater is always set
-+ ** to zero.
-+ */
-+ case SQLITE_DBSTATUS_CACHE_HIT:
-+ case SQLITE_DBSTATUS_CACHE_MISS:
-+ case SQLITE_DBSTATUS_CACHE_WRITE:{
-+ int i;
-+ int nRet = 0;
-+ assert( SQLITE_DBSTATUS_CACHE_MISS==SQLITE_DBSTATUS_CACHE_HIT+1 );
-+ assert( SQLITE_DBSTATUS_CACHE_WRITE==SQLITE_DBSTATUS_CACHE_HIT+2 );
-+
-+ for(i=0; i<db->nDb; i++){
-+ if( db->aDb[i].pBt ){
-+ Pager *pPager = sqlite3BtreePager(db->aDb[i].pBt);
-+ sqlite3PagerCacheStat(pPager, op, resetFlag, &nRet);
-+ }
-+ }
-+ *pHighwater = 0;
-+ *pCurrent = nRet;
-+ break;
-+ }
-+
-+ default: {
-+ rc = SQLITE_ERROR;
-+ }
-+ }
-+ sqlite3_mutex_leave(db->mutex);
-+ return rc;
-+}
-+
-+/************** End of status.c **********************************************/
-+/************** Begin file date.c ********************************************/
-+/*
-+** 2003 October 31
- **
- ** The author disclaims copyright to this source code. In place of
- ** a legal notice, here is a blessing:
-@@ -16443,1269 +17009,1505 @@
- ** May you share freely, never taking more than you give.
- **
- *************************************************************************
--** This file contains the C functions that implement a memory
--** allocation subsystem for use by SQLite.
-+** This file contains the C functions that implement date and time
-+** functions for SQLite.
- **
--** This version of the memory allocation subsystem omits all
--** use of malloc(). The SQLite user supplies a block of memory
--** before calling sqlite3_initialize() from which allocations
--** are made and returned by the xMalloc() and xRealloc()
--** implementations. Once sqlite3_initialize() has been called,
--** the amount of memory available to SQLite is fixed and cannot
--** be changed.
-+** There is only one exported symbol in this file - the function
-+** sqlite3RegisterDateTimeFunctions() found at the bottom of the file.
-+** All other code has file scope.
- **
--** This version of the memory allocation subsystem is included
--** in the build only if SQLITE_ENABLE_MEMSYS3 is defined.
-+** SQLite processes all times and dates as Julian Day numbers. The
-+** dates and times are stored as the number of days since noon
-+** in Greenwich on November 24, 4714 B.C. according to the Gregorian
-+** calendar system.
-+**
-+** 1970-01-01 00:00:00 is JD 2440587.5
-+** 2000-01-01 00:00:00 is JD 2451544.5
-+**
-+** This implemention requires years to be expressed as a 4-digit number
-+** which means that only dates between 0000-01-01 and 9999-12-31 can
-+** be represented, even though julian day numbers allow a much wider
-+** range of dates.
-+**
-+** The Gregorian calendar system is used for all dates and times,
-+** even those that predate the Gregorian calendar. Historians usually
-+** use the Julian calendar for dates prior to 1582-10-15 and for some
-+** dates afterwards, depending on locale. Beware of this difference.
-+**
-+** The conversion algorithms are implemented based on descriptions
-+** in the following text:
-+**
-+** Jean Meeus
-+** Astronomical Algorithms, 2nd Edition, 1998
-+** ISBM 0-943396-61-1
-+** Willmann-Bell, Inc
-+** Richmond, Virginia (USA)
- */
-+/* #include <stdlib.h> */
-+/* #include <assert.h> */
-+#include <time.h>
-+
-+#ifndef SQLITE_OMIT_DATETIME_FUNCS
-
--/*
--** This version of the memory allocator is only built into the library
--** SQLITE_ENABLE_MEMSYS3 is defined. Defining this symbol does not
--** mean that the library will use a memory-pool by default, just that
--** it is available. The mempool allocator is activated by calling
--** sqlite3_config().
--*/
--#ifdef SQLITE_ENABLE_MEMSYS3
-
- /*
--** Maximum size (in Mem3Blocks) of a "small" chunk.
-+** A structure for holding a single date and time.
- */
--#define MX_SMALL 10
-+typedef struct DateTime DateTime;
-+struct DateTime {
-+ sqlite3_int64 iJD; /* The julian day number times 86400000 */
-+ int Y, M, D; /* Year, month, and day */
-+ int h, m; /* Hour and minutes */
-+ int tz; /* Timezone offset in minutes */
-+ double s; /* Seconds */
-+ char validYMD; /* True (1) if Y,M,D are valid */
-+ char validHMS; /* True (1) if h,m,s are valid */
-+ char validJD; /* True (1) if iJD is valid */
-+ char validTZ; /* True (1) if tz is valid */
-+};
-
-
- /*
--** Number of freelist hash slots
-+** Convert zDate into one or more integers. Additional arguments
-+** come in groups of 5 as follows:
-+**
-+** N number of digits in the integer
-+** min minimum allowed value of the integer
-+** max maximum allowed value of the integer
-+** nextC first character after the integer
-+** pVal where to write the integers value.
-+**
-+** Conversions continue until one with nextC==0 is encountered.
-+** The function returns the number of successful conversions.
- */
--#define N_HASH 61
-+static int getDigits(const char *zDate, ...){
-+ va_list ap;
-+ int val;
-+ int N;
-+ int min;
-+ int max;
-+ int nextC;
-+ int *pVal;
-+ int cnt = 0;
-+ va_start(ap, zDate);
-+ do{
-+ N = va_arg(ap, int);
-+ min = va_arg(ap, int);
-+ max = va_arg(ap, int);
-+ nextC = va_arg(ap, int);
-+ pVal = va_arg(ap, int*);
-+ val = 0;
-+ while( N-- ){
-+ if( !sqlite3Isdigit(*zDate) ){
-+ goto end_getDigits;
-+ }
-+ val = val*10 + *zDate - '0';
-+ zDate++;
-+ }
-+ if( val<min || val>max || (nextC!=0 && nextC!=*zDate) ){
-+ goto end_getDigits;
-+ }
-+ *pVal = val;
-+ zDate++;
-+ cnt++;
-+ }while( nextC );
-+end_getDigits:
-+ va_end(ap);
-+ return cnt;
-+}
-
- /*
--** A memory allocation (also called a "chunk") consists of two or
--** more blocks where each block is 8 bytes. The first 8 bytes are
--** a header that is not returned to the user.
-+** Parse a timezone extension on the end of a date-time.
-+** The extension is of the form:
- **
--** A chunk is two or more blocks that is either checked out or
--** free. The first block has format u.hdr. u.hdr.size4x is 4 times the
--** size of the allocation in blocks if the allocation is free.
--** The u.hdr.size4x&1 bit is true if the chunk is checked out and
--** false if the chunk is on the freelist. The u.hdr.size4x&2 bit
--** is true if the previous chunk is checked out and false if the
--** previous chunk is free. The u.hdr.prevSize field is the size of
--** the previous chunk in blocks if the previous chunk is on the
--** freelist. If the previous chunk is checked out, then
--** u.hdr.prevSize can be part of the data for that chunk and should
--** not be read or written.
-+** (+/-)HH:MM
- **
--** We often identify a chunk by its index in mem3.aPool[]. When
--** this is done, the chunk index refers to the second block of
--** the chunk. In this way, the first chunk has an index of 1.
--** A chunk index of 0 means "no such chunk" and is the equivalent
--** of a NULL pointer.
-+** Or the "zulu" notation:
- **
--** The second block of free chunks is of the form u.list. The
--** two fields form a double-linked list of chunks of related sizes.
--** Pointers to the head of the list are stored in mem3.aiSmall[]
--** for smaller chunks and mem3.aiHash[] for larger chunks.
-+** Z
- **
--** The second block of a chunk is user data if the chunk is checked
--** out. If a chunk is checked out, the user data may extend into
--** the u.hdr.prevSize value of the following chunk.
--*/
--typedef struct Mem3Block Mem3Block;
--struct Mem3Block {
-- union {
-- struct {
-- u32 prevSize; /* Size of previous chunk in Mem3Block elements */
-- u32 size4x; /* 4x the size of current chunk in Mem3Block elements */
-- } hdr;
-- struct {
-- u32 next; /* Index in mem3.aPool[] of next free chunk */
-- u32 prev; /* Index in mem3.aPool[] of previous free chunk */
-- } list;
-- } u;
--};
--
--/*
--** All of the static variables used by this module are collected
--** into a single structure named "mem3". This is to keep the
--** static variables organized and to reduce namespace pollution
--** when this module is combined with other in the amalgamation.
--*/
--static SQLITE_WSD struct Mem3Global {
-- /*
-- ** Memory available for allocation. nPool is the size of the array
-- ** (in Mem3Blocks) pointed to by aPool less 2.
-- */
-- u32 nPool;
-- Mem3Block *aPool;
--
-- /*
-- ** True if we are evaluating an out-of-memory callback.
-- */
-- int alarmBusy;
--
-- /*
-- ** Mutex to control access to the memory allocation subsystem.
-- */
-- sqlite3_mutex *mutex;
--
-- /*
-- ** The minimum amount of free space that we have seen.
-- */
-- u32 mnMaster;
--
-- /*
-- ** iMaster is the index of the master chunk. Most new allocations
-- ** occur off of this chunk. szMaster is the size (in Mem3Blocks)
-- ** of the current master. iMaster is 0 if there is not master chunk.
-- ** The master chunk is not in either the aiHash[] or aiSmall[].
-- */
-- u32 iMaster;
-- u32 szMaster;
--
-- /*
-- ** Array of lists of free blocks according to the block size
-- ** for smaller chunks, or a hash on the block size for larger
-- ** chunks.
-- */
-- u32 aiSmall[MX_SMALL-1]; /* For sizes 2 through MX_SMALL, inclusive */
-- u32 aiHash[N_HASH]; /* For sizes MX_SMALL+1 and larger */
--} mem3 = { 97535575 };
--
--#define mem3 GLOBAL(struct Mem3Global, mem3)
--
--/*
--** Unlink the chunk at mem3.aPool[i] from list it is currently
--** on. *pRoot is the list that i is a member of.
-+** If the parse is successful, write the number of minutes
-+** of change in p->tz and return 0. If a parser error occurs,
-+** return non-zero.
-+**
-+** A missing specifier is not considered an error.
- */
--static void memsys3UnlinkFromList(u32 i, u32 *pRoot){
-- u32 next = mem3.aPool[i].u.list.next;
-- u32 prev = mem3.aPool[i].u.list.prev;
-- assert( sqlite3_mutex_held(mem3.mutex) );
-- if( prev==0 ){
-- *pRoot = next;
-+static int parseTimezone(const char *zDate, DateTime *p){
-+ int sgn = 0;
-+ int nHr, nMn;
-+ int c;
-+ while( sqlite3Isspace(*zDate) ){ zDate++; }
-+ p->tz = 0;
-+ c = *zDate;
-+ if( c=='-' ){
-+ sgn = -1;
-+ }else if( c=='+' ){
-+ sgn = +1;
-+ }else if( c=='Z' || c=='z' ){
-+ zDate++;
-+ goto zulu_time;
- }else{
-- mem3.aPool[prev].u.list.next = next;
-+ return c!=0;
- }
-- if( next ){
-- mem3.aPool[next].u.list.prev = prev;
-+ zDate++;
-+ if( getDigits(zDate, 2, 0, 14, ':', &nHr, 2, 0, 59, 0, &nMn)!=2 ){
-+ return 1;
- }
-- mem3.aPool[i].u.list.next = 0;
-- mem3.aPool[i].u.list.prev = 0;
-+ zDate += 5;
-+ p->tz = sgn*(nMn + nHr*60);
-+zulu_time:
-+ while( sqlite3Isspace(*zDate) ){ zDate++; }
-+ return *zDate!=0;
- }
-
- /*
--** Unlink the chunk at index i from
--** whatever list is currently a member of.
-+** Parse times of the form HH:MM or HH:MM:SS or HH:MM:SS.FFFF.
-+** The HH, MM, and SS must each be exactly 2 digits. The
-+** fractional seconds FFFF can be one or more digits.
-+**
-+** Return 1 if there is a parsing error and 0 on success.
- */
--static void memsys3Unlink(u32 i){
-- u32 size, hash;
-- assert( sqlite3_mutex_held(mem3.mutex) );
-- assert( (mem3.aPool[i-1].u.hdr.size4x & 1)==0 );
-- assert( i>=1 );
-- size = mem3.aPool[i-1].u.hdr.size4x/4;
-- assert( size==mem3.aPool[i+size-1].u.hdr.prevSize );
-- assert( size>=2 );
-- if( size <= MX_SMALL ){
-- memsys3UnlinkFromList(i, &mem3.aiSmall[size-2]);
-+static int parseHhMmSs(const char *zDate, DateTime *p){
-+ int h, m, s;
-+ double ms = 0.0;
-+ if( getDigits(zDate, 2, 0, 24, ':', &h, 2, 0, 59, 0, &m)!=2 ){
-+ return 1;
-+ }
-+ zDate += 5;
-+ if( *zDate==':' ){
-+ zDate++;
-+ if( getDigits(zDate, 2, 0, 59, 0, &s)!=1 ){
-+ return 1;
-+ }
-+ zDate += 2;
-+ if( *zDate=='.' && sqlite3Isdigit(zDate[1]) ){
-+ double rScale = 1.0;
-+ zDate++;
-+ while( sqlite3Isdigit(*zDate) ){
-+ ms = ms*10.0 + *zDate - '0';
-+ rScale *= 10.0;
-+ zDate++;
-+ }
-+ ms /= rScale;
-+ }
- }else{
-- hash = size % N_HASH;
-- memsys3UnlinkFromList(i, &mem3.aiHash[hash]);
-+ s = 0;
- }
-+ p->validJD = 0;
-+ p->validHMS = 1;
-+ p->h = h;
-+ p->m = m;
-+ p->s = s + ms;
-+ if( parseTimezone(zDate, p) ) return 1;
-+ p->validTZ = (p->tz!=0)?1:0;
-+ return 0;
- }
-
- /*
--** Link the chunk at mem3.aPool[i] so that is on the list rooted
--** at *pRoot.
-+** Convert from YYYY-MM-DD HH:MM:SS to julian day. We always assume
-+** that the YYYY-MM-DD is according to the Gregorian calendar.
-+**
-+** Reference: Meeus page 61
- */
--static void memsys3LinkIntoList(u32 i, u32 *pRoot){
-- assert( sqlite3_mutex_held(mem3.mutex) );
-- mem3.aPool[i].u.list.next = *pRoot;
-- mem3.aPool[i].u.list.prev = 0;
-- if( *pRoot ){
-- mem3.aPool[*pRoot].u.list.prev = i;
-+static void computeJD(DateTime *p){
-+ int Y, M, D, A, B, X1, X2;
-+
-+ if( p->validJD ) return;
-+ if( p->validYMD ){
-+ Y = p->Y;
-+ M = p->M;
-+ D = p->D;
-+ }else{
-+ Y = 2000; /* If no YMD specified, assume 2000-Jan-01 */
-+ M = 1;
-+ D = 1;
-+ }
-+ if( M<=2 ){
-+ Y--;
-+ M += 12;
-+ }
-+ A = Y/100;
-+ B = 2 - A + (A/4);
-+ X1 = 36525*(Y+4716)/100;
-+ X2 = 306001*(M+1)/10000;
-+ p->iJD = (sqlite3_int64)((X1 + X2 + D + B - 1524.5 ) * 86400000);
-+ p->validJD = 1;
-+ if( p->validHMS ){
-+ p->iJD += p->h*3600000 + p->m*60000 + (sqlite3_int64)(p->s*1000);
-+ if( p->validTZ ){
-+ p->iJD -= p->tz*60000;
-+ p->validYMD = 0;
-+ p->validHMS = 0;
-+ p->validTZ = 0;
-+ }
- }
-- *pRoot = i;
- }
-
- /*
--** Link the chunk at index i into either the appropriate
--** small chunk list, or into the large chunk hash table.
-+** Parse dates of the form
-+**
-+** YYYY-MM-DD HH:MM:SS.FFF
-+** YYYY-MM-DD HH:MM:SS
-+** YYYY-MM-DD HH:MM
-+** YYYY-MM-DD
-+**
-+** Write the result into the DateTime structure and return 0
-+** on success and 1 if the input string is not a well-formed
-+** date.
- */
--static void memsys3Link(u32 i){
-- u32 size, hash;
-- assert( sqlite3_mutex_held(mem3.mutex) );
-- assert( i>=1 );
-- assert( (mem3.aPool[i-1].u.hdr.size4x & 1)==0 );
-- size = mem3.aPool[i-1].u.hdr.size4x/4;
-- assert( size==mem3.aPool[i+size-1].u.hdr.prevSize );
-- assert( size>=2 );
-- if( size <= MX_SMALL ){
-- memsys3LinkIntoList(i, &mem3.aiSmall[size-2]);
-+static int parseYyyyMmDd(const char *zDate, DateTime *p){
-+ int Y, M, D, neg;
-+
-+ if( zDate[0]=='-' ){
-+ zDate++;
-+ neg = 1;
- }else{
-- hash = size % N_HASH;
-- memsys3LinkIntoList(i, &mem3.aiHash[hash]);
-+ neg = 0;
-+ }
-+ if( getDigits(zDate,4,0,9999,'-',&Y,2,1,12,'-',&M,2,1,31,0,&D)!=3 ){
-+ return 1;
-+ }
-+ zDate += 10;
-+ while( sqlite3Isspace(*zDate) || 'T'==*(u8*)zDate ){ zDate++; }
-+ if( parseHhMmSs(zDate, p)==0 ){
-+ /* We got the time */
-+ }else if( *zDate==0 ){
-+ p->validHMS = 0;
-+ }else{
-+ return 1;
-+ }
-+ p->validJD = 0;
-+ p->validYMD = 1;
-+ p->Y = neg ? -Y : Y;
-+ p->M = M;
-+ p->D = D;
-+ if( p->validTZ ){
-+ computeJD(p);
- }
-+ return 0;
- }
-
- /*
--** If the STATIC_MEM mutex is not already held, obtain it now. The mutex
--** will already be held (obtained by code in malloc.c) if
--** sqlite3GlobalConfig.bMemStat is true.
-+** Set the time to the current time reported by the VFS.
-+**
-+** Return the number of errors.
- */
--static void memsys3Enter(void){
-- if( sqlite3GlobalConfig.bMemstat==0 && mem3.mutex==0 ){
-- mem3.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM);
-+static int setDateTimeToCurrent(sqlite3_context *context, DateTime *p){
-+ sqlite3 *db = sqlite3_context_db_handle(context);
-+ if( sqlite3OsCurrentTimeInt64(db->pVfs, &p->iJD)==SQLITE_OK ){
-+ p->validJD = 1;
-+ return 0;
-+ }else{
-+ return 1;
- }
-- sqlite3_mutex_enter(mem3.mutex);
--}
--static void memsys3Leave(void){
-- sqlite3_mutex_leave(mem3.mutex);
- }
-
- /*
--** Called when we are unable to satisfy an allocation of nBytes.
--*/
--static void memsys3OutOfMemory(int nByte){
-- if( !mem3.alarmBusy ){
-- mem3.alarmBusy = 1;
-- assert( sqlite3_mutex_held(mem3.mutex) );
-- sqlite3_mutex_leave(mem3.mutex);
-- sqlite3_release_memory(nByte);
-- sqlite3_mutex_enter(mem3.mutex);
-- mem3.alarmBusy = 0;
-- }
--}
--
--
--/*
--** Chunk i is a free chunk that has been unlinked. Adjust its
--** size parameters for check-out and return a pointer to the
--** user portion of the chunk.
--*/
--static void *memsys3Checkout(u32 i, u32 nBlock){
-- u32 x;
-- assert( sqlite3_mutex_held(mem3.mutex) );
-- assert( i>=1 );
-- assert( mem3.aPool[i-1].u.hdr.size4x/4==nBlock );
-- assert( mem3.aPool[i+nBlock-1].u.hdr.prevSize==nBlock );
-- x = mem3.aPool[i-1].u.hdr.size4x;
-- mem3.aPool[i-1].u.hdr.size4x = nBlock*4 | 1 | (x&2);
-- mem3.aPool[i+nBlock-1].u.hdr.prevSize = nBlock;
-- mem3.aPool[i+nBlock-1].u.hdr.size4x |= 2;
-- return &mem3.aPool[i];
--}
--
--/*
--** Carve a piece off of the end of the mem3.iMaster free chunk.
--** Return a pointer to the new allocation. Or, if the master chunk
--** is not large enough, return 0.
--*/
--static void *memsys3FromMaster(u32 nBlock){
-- assert( sqlite3_mutex_held(mem3.mutex) );
-- assert( mem3.szMaster>=nBlock );
-- if( nBlock>=mem3.szMaster-1 ){
-- /* Use the entire master */
-- void *p = memsys3Checkout(mem3.iMaster, mem3.szMaster);
-- mem3.iMaster = 0;
-- mem3.szMaster = 0;
-- mem3.mnMaster = 0;
-- return p;
-- }else{
-- /* Split the master block. Return the tail. */
-- u32 newi, x;
-- newi = mem3.iMaster + mem3.szMaster - nBlock;
-- assert( newi > mem3.iMaster+1 );
-- mem3.aPool[mem3.iMaster+mem3.szMaster-1].u.hdr.prevSize = nBlock;
-- mem3.aPool[mem3.iMaster+mem3.szMaster-1].u.hdr.size4x |= 2;
-- mem3.aPool[newi-1].u.hdr.size4x = nBlock*4 + 1;
-- mem3.szMaster -= nBlock;
-- mem3.aPool[newi-1].u.hdr.prevSize = mem3.szMaster;
-- x = mem3.aPool[mem3.iMaster-1].u.hdr.size4x & 2;
-- mem3.aPool[mem3.iMaster-1].u.hdr.size4x = mem3.szMaster*4 | x;
-- if( mem3.szMaster < mem3.mnMaster ){
-- mem3.mnMaster = mem3.szMaster;
-- }
-- return (void*)&mem3.aPool[newi];
-- }
--}
--
--/*
--** *pRoot is the head of a list of free chunks of the same size
--** or same size hash. In other words, *pRoot is an entry in either
--** mem3.aiSmall[] or mem3.aiHash[].
-+** Attempt to parse the given string into a Julian Day Number. Return
-+** the number of errors.
- **
--** This routine examines all entries on the given list and tries
--** to coalesce each entries with adjacent free chunks.
-+** The following are acceptable forms for the input string:
- **
--** If it sees a chunk that is larger than mem3.iMaster, it replaces
--** the current mem3.iMaster with the new larger chunk. In order for
--** this mem3.iMaster replacement to work, the master chunk must be
--** linked into the hash tables. That is not the normal state of
--** affairs, of course. The calling routine must link the master
--** chunk before invoking this routine, then must unlink the (possibly
--** changed) master chunk once this routine has finished.
-+** YYYY-MM-DD HH:MM:SS.FFF +/-HH:MM
-+** DDDD.DD
-+** now
-+**
-+** In the first form, the +/-HH:MM is always optional. The fractional
-+** seconds extension (the ".FFF") is optional. The seconds portion
-+** (":SS.FFF") is option. The year and date can be omitted as long
-+** as there is a time string. The time string can be omitted as long
-+** as there is a year and date.
- */
--static void memsys3Merge(u32 *pRoot){
-- u32 iNext, prev, size, i, x;
--
-- assert( sqlite3_mutex_held(mem3.mutex) );
-- for(i=*pRoot; i>0; i=iNext){
-- iNext = mem3.aPool[i].u.list.next;
-- size = mem3.aPool[i-1].u.hdr.size4x;
-- assert( (size&1)==0 );
-- if( (size&2)==0 ){
-- memsys3UnlinkFromList(i, pRoot);
-- assert( i > mem3.aPool[i-1].u.hdr.prevSize );
-- prev = i - mem3.aPool[i-1].u.hdr.prevSize;
-- if( prev==iNext ){
-- iNext = mem3.aPool[prev].u.list.next;
-- }
-- memsys3Unlink(prev);
-- size = i + size/4 - prev;
-- x = mem3.aPool[prev-1].u.hdr.size4x & 2;
-- mem3.aPool[prev-1].u.hdr.size4x = size*4 | x;
-- mem3.aPool[prev+size-1].u.hdr.prevSize = size;
-- memsys3Link(prev);
-- i = prev;
-- }else{
-- size /= 4;
-- }
-- if( size>mem3.szMaster ){
-- mem3.iMaster = i;
-- mem3.szMaster = size;
-- }
-+static int parseDateOrTime(
-+ sqlite3_context *context,
-+ const char *zDate,
-+ DateTime *p
-+){
-+ double r;
-+ if( parseYyyyMmDd(zDate,p)==0 ){
-+ return 0;
-+ }else if( parseHhMmSs(zDate, p)==0 ){
-+ return 0;
-+ }else if( sqlite3StrICmp(zDate,"now")==0){
-+ return setDateTimeToCurrent(context, p);
-+ }else if( sqlite3AtoF(zDate, &r, sqlite3Strlen30(zDate), SQLITE_UTF8) ){
-+ p->iJD = (sqlite3_int64)(r*86400000.0 + 0.5);
-+ p->validJD = 1;
-+ return 0;
- }
-+ return 1;
- }
-
- /*
--** Return a block of memory of at least nBytes in size.
--** Return NULL if unable.
--**
--** This function assumes that the necessary mutexes, if any, are
--** already held by the caller. Hence "Unsafe".
-+** Compute the Year, Month, and Day from the julian day number.
- */
--static void *memsys3MallocUnsafe(int nByte){
-- u32 i;
-- u32 nBlock;
-- u32 toFree;
--
-- assert( sqlite3_mutex_held(mem3.mutex) );
-- assert( sizeof(Mem3Block)==8 );
-- if( nByte<=12 ){
-- nBlock = 2;
-- }else{
-- nBlock = (nByte + 11)/8;
-- }
-- assert( nBlock>=2 );
--
-- /* STEP 1:
-- ** Look for an entry of the correct size in either the small
-- ** chunk table or in the large chunk hash table. This is
-- ** successful most of the time (about 9 times out of 10).
-- */
-- if( nBlock <= MX_SMALL ){
-- i = mem3.aiSmall[nBlock-2];
-- if( i>0 ){
-- memsys3UnlinkFromList(i, &mem3.aiSmall[nBlock-2]);
-- return memsys3Checkout(i, nBlock);
-- }
-+static void computeYMD(DateTime *p){
-+ int Z, A, B, C, D, E, X1;
-+ if( p->validYMD ) return;
-+ if( !p->validJD ){
-+ p->Y = 2000;
-+ p->M = 1;
-+ p->D = 1;
- }else{
-- int hash = nBlock % N_HASH;
-- for(i=mem3.aiHash[hash]; i>0; i=mem3.aPool[i].u.list.next){
-- if( mem3.aPool[i-1].u.hdr.size4x/4==nBlock ){
-- memsys3UnlinkFromList(i, &mem3.aiHash[hash]);
-- return memsys3Checkout(i, nBlock);
-- }
-- }
-- }
--
-- /* STEP 2:
-- ** Try to satisfy the allocation by carving a piece off of the end
-- ** of the master chunk. This step usually works if step 1 fails.
-- */
-- if( mem3.szMaster>=nBlock ){
-- return memsys3FromMaster(nBlock);
-- }
--
--
-- /* STEP 3:
-- ** Loop through the entire memory pool. Coalesce adjacent free
-- ** chunks. Recompute the master chunk as the largest free chunk.
-- ** Then try again to satisfy the allocation by carving a piece off
-- ** of the end of the master chunk. This step happens very
-- ** rarely (we hope!)
-- */
-- for(toFree=nBlock*16; toFree<(mem3.nPool*16); toFree *= 2){
-- memsys3OutOfMemory(toFree);
-- if( mem3.iMaster ){
-- memsys3Link(mem3.iMaster);
-- mem3.iMaster = 0;
-- mem3.szMaster = 0;
-- }
-- for(i=0; i<N_HASH; i++){
-- memsys3Merge(&mem3.aiHash[i]);
-- }
-- for(i=0; i<MX_SMALL-1; i++){
-- memsys3Merge(&mem3.aiSmall[i]);
-- }
-- if( mem3.szMaster ){
-- memsys3Unlink(mem3.iMaster);
-- if( mem3.szMaster>=nBlock ){
-- return memsys3FromMaster(nBlock);
-- }
-- }
-+ Z = (int)((p->iJD + 43200000)/86400000);
-+ A = (int)((Z - 1867216.25)/36524.25);
-+ A = Z + 1 + A - (A/4);
-+ B = A + 1524;
-+ C = (int)((B - 122.1)/365.25);
-+ D = (36525*C)/100;
-+ E = (int)((B-D)/30.6001);
-+ X1 = (int)(30.6001*E);
-+ p->D = B - D - X1;
-+ p->M = E<14 ? E-1 : E-13;
-+ p->Y = p->M>2 ? C - 4716 : C - 4715;
- }
--
-- /* If none of the above worked, then we fail. */
-- return 0;
-+ p->validYMD = 1;
- }
-
- /*
--** Free an outstanding memory allocation.
--**
--** This function assumes that the necessary mutexes, if any, are
--** already held by the caller. Hence "Unsafe".
-+** Compute the Hour, Minute, and Seconds from the julian day number.
- */
--static void memsys3FreeUnsafe(void *pOld){
-- Mem3Block *p = (Mem3Block*)pOld;
-- int i;
-- u32 size, x;
-- assert( sqlite3_mutex_held(mem3.mutex) );
-- assert( p>mem3.aPool && p<&mem3.aPool[mem3.nPool] );
-- i = p - mem3.aPool;
-- assert( (mem3.aPool[i-1].u.hdr.size4x&1)==1 );
-- size = mem3.aPool[i-1].u.hdr.size4x/4;
-- assert( i+size<=mem3.nPool+1 );
-- mem3.aPool[i-1].u.hdr.size4x &= ~1;
-- mem3.aPool[i+size-1].u.hdr.prevSize = size;
-- mem3.aPool[i+size-1].u.hdr.size4x &= ~2;
-- memsys3Link(i);
--
-- /* Try to expand the master using the newly freed chunk */
-- if( mem3.iMaster ){
-- while( (mem3.aPool[mem3.iMaster-1].u.hdr.size4x&2)==0 ){
-- size = mem3.aPool[mem3.iMaster-1].u.hdr.prevSize;
-- mem3.iMaster -= size;
-- mem3.szMaster += size;
-- memsys3Unlink(mem3.iMaster);
-- x = mem3.aPool[mem3.iMaster-1].u.hdr.size4x & 2;
-- mem3.aPool[mem3.iMaster-1].u.hdr.size4x = mem3.szMaster*4 | x;
-- mem3.aPool[mem3.iMaster+mem3.szMaster-1].u.hdr.prevSize = mem3.szMaster;
-- }
-- x = mem3.aPool[mem3.iMaster-1].u.hdr.size4x & 2;
-- while( (mem3.aPool[mem3.iMaster+mem3.szMaster-1].u.hdr.size4x&1)==0 ){
-- memsys3Unlink(mem3.iMaster+mem3.szMaster);
-- mem3.szMaster += mem3.aPool[mem3.iMaster+mem3.szMaster-1].u.hdr.size4x/4;
-- mem3.aPool[mem3.iMaster-1].u.hdr.size4x = mem3.szMaster*4 | x;
-- mem3.aPool[mem3.iMaster+mem3.szMaster-1].u.hdr.prevSize = mem3.szMaster;
-- }
-- }
-+static void computeHMS(DateTime *p){
-+ int s;
-+ if( p->validHMS ) return;
-+ computeJD(p);
-+ s = (int)((p->iJD + 43200000) % 86400000);
-+ p->s = s/1000.0;
-+ s = (int)p->s;
-+ p->s -= s;
-+ p->h = s/3600;
-+ s -= p->h*3600;
-+ p->m = s/60;
-+ p->s += s - p->m*60;
-+ p->validHMS = 1;
- }
-
- /*
--** Return the size of an outstanding allocation, in bytes. The
--** size returned omits the 8-byte header overhead. This only
--** works for chunks that are currently checked out.
-+** Compute both YMD and HMS
- */
--static int memsys3Size(void *p){
-- Mem3Block *pBlock;
-- if( p==0 ) return 0;
-- pBlock = (Mem3Block*)p;
-- assert( (pBlock[-1].u.hdr.size4x&1)!=0 );
-- return (pBlock[-1].u.hdr.size4x&~3)*2 - 4;
-+static void computeYMD_HMS(DateTime *p){
-+ computeYMD(p);
-+ computeHMS(p);
- }
-
- /*
--** Round up a request size to the next valid allocation size.
-+** Clear the YMD and HMS and the TZ
- */
--static int memsys3Roundup(int n){
-- if( n<=12 ){
-- return 12;
-- }else{
-- return ((n+11)&~7) - 4;
-- }
-+static void clearYMD_HMS_TZ(DateTime *p){
-+ p->validYMD = 0;
-+ p->validHMS = 0;
-+ p->validTZ = 0;
- }
-
- /*
--** Allocate nBytes of memory.
-+** On recent Windows platforms, the localtime_s() function is available
-+** as part of the "Secure CRT". It is essentially equivalent to
-+** localtime_r() available under most POSIX platforms, except that the
-+** order of the parameters is reversed.
-+**
-+** See http://msdn.microsoft.com/en-us/library/a442x3ye(VS.80).aspx.
-+**
-+** If the user has not indicated to use localtime_r() or localtime_s()
-+** already, check for an MSVC build environment that provides
-+** localtime_s().
- */
--static void *memsys3Malloc(int nBytes){
-- sqlite3_int64 *p;
-- assert( nBytes>0 ); /* malloc.c filters out 0 byte requests */
-- memsys3Enter();
-- p = memsys3MallocUnsafe(nBytes);
-- memsys3Leave();
-- return (void*)p;
--}
-+#if !defined(HAVE_LOCALTIME_R) && !defined(HAVE_LOCALTIME_S) && \
-+ defined(_MSC_VER) && defined(_CRT_INSECURE_DEPRECATE)
-+#define HAVE_LOCALTIME_S 1
-+#endif
-
-+#ifndef SQLITE_OMIT_LOCALTIME
- /*
--** Free memory.
-+** The following routine implements the rough equivalent of localtime_r()
-+** using whatever operating-system specific localtime facility that
-+** is available. This routine returns 0 on success and
-+** non-zero on any kind of error.
-+**
-+** If the sqlite3GlobalConfig.bLocaltimeFault variable is true then this
-+** routine will always fail.
- */
--static void memsys3Free(void *pPrior){
-- assert( pPrior );
-- memsys3Enter();
-- memsys3FreeUnsafe(pPrior);
-- memsys3Leave();
-+static int osLocaltime(time_t *t, struct tm *pTm){
-+ int rc;
-+#if (!defined(HAVE_LOCALTIME_R) || !HAVE_LOCALTIME_R) \
-+ && (!defined(HAVE_LOCALTIME_S) || !HAVE_LOCALTIME_S)
-+ struct tm *pX;
-+#if SQLITE_THREADSAFE>0
-+ sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
-+#endif
-+ sqlite3_mutex_enter(mutex);
-+ pX = localtime(t);
-+#ifndef SQLITE_OMIT_BUILTIN_TEST
-+ if( sqlite3GlobalConfig.bLocaltimeFault ) pX = 0;
-+#endif
-+ if( pX ) *pTm = *pX;
-+ sqlite3_mutex_leave(mutex);
-+ rc = pX==0;
-+#else
-+#ifndef SQLITE_OMIT_BUILTIN_TEST
-+ if( sqlite3GlobalConfig.bLocaltimeFault ) return 1;
-+#endif
-+#if defined(HAVE_LOCALTIME_R) && HAVE_LOCALTIME_R
-+ rc = localtime_r(t, pTm)==0;
-+#else
-+ rc = localtime_s(pTm, t);
-+#endif /* HAVE_LOCALTIME_R */
-+#endif /* HAVE_LOCALTIME_R || HAVE_LOCALTIME_S */
-+ return rc;
- }
-+#endif /* SQLITE_OMIT_LOCALTIME */
-+
-
-+#ifndef SQLITE_OMIT_LOCALTIME
- /*
--** Change the size of an existing memory allocation
-+** Compute the difference (in milliseconds) between localtime and UTC
-+** (a.k.a. GMT) for the time value p where p is in UTC. If no error occurs,
-+** return this value and set *pRc to SQLITE_OK.
-+**
-+** Or, if an error does occur, set *pRc to SQLITE_ERROR. The returned value
-+** is undefined in this case.
- */
--static void *memsys3Realloc(void *pPrior, int nBytes){
-- int nOld;
-- void *p;
-- if( pPrior==0 ){
-- return sqlite3_malloc(nBytes);
-+static sqlite3_int64 localtimeOffset(
-+ DateTime *p, /* Date at which to calculate offset */
-+ sqlite3_context *pCtx, /* Write error here if one occurs */
-+ int *pRc /* OUT: Error code. SQLITE_OK or ERROR */
-+){
-+ DateTime x, y;
-+ time_t t;
-+ struct tm sLocal;
-+
-+ /* Initialize the contents of sLocal to avoid a compiler warning. */
-+ memset(&sLocal, 0, sizeof(sLocal));
-+
-+ x = *p;
-+ computeYMD_HMS(&x);
-+ if( x.Y<1971 || x.Y>=2038 ){
-+ x.Y = 2000;
-+ x.M = 1;
-+ x.D = 1;
-+ x.h = 0;
-+ x.m = 0;
-+ x.s = 0.0;
-+ } else {
-+ int s = (int)(x.s + 0.5);
-+ x.s = s;
- }
-- if( nBytes<=0 ){
-- sqlite3_free(pPrior);
-+ x.tz = 0;
-+ x.validJD = 0;
-+ computeJD(&x);
-+ t = (time_t)(x.iJD/1000 - 21086676*(i64)10000);
-+ if( osLocaltime(&t, &sLocal) ){
-+ sqlite3_result_error(pCtx, "local time unavailable", -1);
-+ *pRc = SQLITE_ERROR;
- return 0;
- }
-- nOld = memsys3Size(pPrior);
-- if( nBytes<=nOld && nBytes>=nOld-128 ){
-- return pPrior;
-- }
-- memsys3Enter();
-- p = memsys3MallocUnsafe(nBytes);
-- if( p ){
-- if( nOld<nBytes ){
-- memcpy(p, pPrior, nOld);
-- }else{
-- memcpy(p, pPrior, nBytes);
-- }
-- memsys3FreeUnsafe(pPrior);
-- }
-- memsys3Leave();
-- return p;
-+ y.Y = sLocal.tm_year + 1900;
-+ y.M = sLocal.tm_mon + 1;
-+ y.D = sLocal.tm_mday;
-+ y.h = sLocal.tm_hour;
-+ y.m = sLocal.tm_min;
-+ y.s = sLocal.tm_sec;
-+ y.validYMD = 1;
-+ y.validHMS = 1;
-+ y.validJD = 0;
-+ y.validTZ = 0;
-+ computeJD(&y);
-+ *pRc = SQLITE_OK;
-+ return y.iJD - x.iJD;
- }
-+#endif /* SQLITE_OMIT_LOCALTIME */
-
- /*
--** Initialize this module.
-+** Process a modifier to a date-time stamp. The modifiers are
-+** as follows:
-+**
-+** NNN days
-+** NNN hours
-+** NNN minutes
-+** NNN.NNNN seconds
-+** NNN months
-+** NNN years
-+** start of month
-+** start of year
-+** start of week
-+** start of day
-+** weekday N
-+** unixepoch
-+** localtime
-+** utc
-+**
-+** Return 0 on success and 1 if there is any kind of error. If the error
-+** is in a system call (i.e. localtime()), then an error message is written
-+** to context pCtx. If the error is an unrecognized modifier, no error is
-+** written to pCtx.
- */
--static int memsys3Init(void *NotUsed){
-- UNUSED_PARAMETER(NotUsed);
-- if( !sqlite3GlobalConfig.pHeap ){
-- return SQLITE_ERROR;
-+static int parseModifier(sqlite3_context *pCtx, const char *zMod, DateTime *p){
-+ int rc = 1;
-+ int n;
-+ double r;
-+ char *z, zBuf[30];
-+ z = zBuf;
-+ for(n=0; n<ArraySize(zBuf)-1 && zMod[n]; n++){
-+ z[n] = (char)sqlite3UpperToLower[(u8)zMod[n]];
- }
--
-- /* Store a pointer to the memory block in global structure mem3. */
-- assert( sizeof(Mem3Block)==8 );
-- mem3.aPool = (Mem3Block *)sqlite3GlobalConfig.pHeap;
-- mem3.nPool = (sqlite3GlobalConfig.nHeap / sizeof(Mem3Block)) - 2;
--
-- /* Initialize the master block. */
-- mem3.szMaster = mem3.nPool;
-- mem3.mnMaster = mem3.szMaster;
-- mem3.iMaster = 1;
-- mem3.aPool[0].u.hdr.size4x = (mem3.szMaster<<2) + 2;
-- mem3.aPool[mem3.nPool].u.hdr.prevSize = mem3.nPool;
-- mem3.aPool[mem3.nPool].u.hdr.size4x = 1;
--
-- return SQLITE_OK;
--}
--
--/*
--** Deinitialize this module.
--*/
--static void memsys3Shutdown(void *NotUsed){
-- UNUSED_PARAMETER(NotUsed);
-- mem3.mutex = 0;
-- return;
--}
--
--
--
--/*
--** Open the file indicated and write a log of all unfreed memory
--** allocations into that log.
--*/
--SQLITE_PRIVATE void sqlite3Memsys3Dump(const char *zFilename){
--#ifdef SQLITE_DEBUG
-- FILE *out;
-- u32 i, j;
-- u32 size;
-- if( zFilename==0 || zFilename[0]==0 ){
-- out = stdout;
-- }else{
-- out = fopen(zFilename, "w");
-- if( out==0 ){
-- fprintf(stderr, "** Unable to output memory debug output log: %s **\n",
-- zFilename);
-- return;
-- }
-- }
-- memsys3Enter();
-- fprintf(out, "CHUNKS:\n");
-- for(i=1; i<=mem3.nPool; i+=size/4){
-- size = mem3.aPool[i-1].u.hdr.size4x;
-- if( size/4<=1 ){
-- fprintf(out, "%p size error\n", &mem3.aPool[i]);
-- assert( 0 );
-+ z[n] = 0;
-+ switch( z[0] ){
-+#ifndef SQLITE_OMIT_LOCALTIME
-+ case 'l': {
-+ /* localtime
-+ **
-+ ** Assuming the current time value is UTC (a.k.a. GMT), shift it to
-+ ** show local time.
-+ */
-+ if( strcmp(z, "localtime")==0 ){
-+ computeJD(p);
-+ p->iJD += localtimeOffset(p, pCtx, &rc);
-+ clearYMD_HMS_TZ(p);
-+ }
- break;
- }
-- if( (size&1)==0 && mem3.aPool[i+size/4-1].u.hdr.prevSize!=size/4 ){
-- fprintf(out, "%p tail size does not match\n", &mem3.aPool[i]);
-- assert( 0 );
-+#endif
-+ case 'u': {
-+ /*
-+ ** unixepoch
-+ **
-+ ** Treat the current value of p->iJD as the number of
-+ ** seconds since 1970. Convert to a real julian day number.
-+ */
-+ if( strcmp(z, "unixepoch")==0 && p->validJD ){
-+ p->iJD = (p->iJD + 43200)/86400 + 21086676*(i64)10000000;
-+ clearYMD_HMS_TZ(p);
-+ rc = 0;
-+ }
-+#ifndef SQLITE_OMIT_LOCALTIME
-+ else if( strcmp(z, "utc")==0 ){
-+ sqlite3_int64 c1;
-+ computeJD(p);
-+ c1 = localtimeOffset(p, pCtx, &rc);
-+ if( rc==SQLITE_OK ){
-+ p->iJD -= c1;
-+ clearYMD_HMS_TZ(p);
-+ p->iJD += c1 - localtimeOffset(p, pCtx, &rc);
-+ }
-+ }
-+#endif
- break;
- }
-- if( ((mem3.aPool[i+size/4-1].u.hdr.size4x&2)>>1)!=(size&1) ){
-- fprintf(out, "%p tail checkout bit is incorrect\n", &mem3.aPool[i]);
-- assert( 0 );
-+ case 'w': {
-+ /*
-+ ** weekday N
-+ **
-+ ** Move the date to the same time on the next occurrence of
-+ ** weekday N where 0==Sunday, 1==Monday, and so forth. If the
-+ ** date is already on the appropriate weekday, this is a no-op.
-+ */
-+ if( strncmp(z, "weekday ", 8)==0
-+ && sqlite3AtoF(&z[8], &r, sqlite3Strlen30(&z[8]), SQLITE_UTF8)
-+ && (n=(int)r)==r && n>=0 && r<7 ){
-+ sqlite3_int64 Z;
-+ computeYMD_HMS(p);
-+ p->validTZ = 0;
-+ p->validJD = 0;
-+ computeJD(p);
-+ Z = ((p->iJD + 129600000)/86400000) % 7;
-+ if( Z>n ) Z -= 7;
-+ p->iJD += (n - Z)*86400000;
-+ clearYMD_HMS_TZ(p);
-+ rc = 0;
-+ }
- break;
- }
-- if( size&1 ){
-- fprintf(out, "%p %6d bytes checked out\n", &mem3.aPool[i], (size/4)*8-8);
-- }else{
-- fprintf(out, "%p %6d bytes free%s\n", &mem3.aPool[i], (size/4)*8-8,
-- i==mem3.iMaster ? " **master**" : "");
-+ case 's': {
-+ /*
-+ ** start of TTTTT
-+ **
-+ ** Move the date backwards to the beginning of the current day,
-+ ** or month or year.
-+ */
-+ if( strncmp(z, "start of ", 9)!=0 ) break;
-+ z += 9;
-+ computeYMD(p);
-+ p->validHMS = 1;
-+ p->h = p->m = 0;
-+ p->s = 0.0;
-+ p->validTZ = 0;
-+ p->validJD = 0;
-+ if( strcmp(z,"month")==0 ){
-+ p->D = 1;
-+ rc = 0;
-+ }else if( strcmp(z,"year")==0 ){
-+ computeYMD(p);
-+ p->M = 1;
-+ p->D = 1;
-+ rc = 0;
-+ }else if( strcmp(z,"day")==0 ){
-+ rc = 0;
-+ }
-+ break;
- }
-- }
-- for(i=0; i<MX_SMALL-1; i++){
-- if( mem3.aiSmall[i]==0 ) continue;
-- fprintf(out, "small(%2d):", i);
-- for(j = mem3.aiSmall[i]; j>0; j=mem3.aPool[j].u.list.next){
-- fprintf(out, " %p(%d)", &mem3.aPool[j],
-- (mem3.aPool[j-1].u.hdr.size4x/4)*8-8);
-+ case '+':
-+ case '-':
-+ case '0':
-+ case '1':
-+ case '2':
-+ case '3':
-+ case '4':
-+ case '5':
-+ case '6':
-+ case '7':
-+ case '8':
-+ case '9': {
-+ double rRounder;
-+ for(n=1; z[n] && z[n]!=':' && !sqlite3Isspace(z[n]); n++){}
-+ if( !sqlite3AtoF(z, &r, n, SQLITE_UTF8) ){
-+ rc = 1;
-+ break;
-+ }
-+ if( z[n]==':' ){
-+ /* A modifier of the form (+|-)HH:MM:SS.FFF adds (or subtracts) the
-+ ** specified number of hours, minutes, seconds, and fractional seconds
-+ ** to the time. The ".FFF" may be omitted. The ":SS.FFF" may be
-+ ** omitted.
-+ */
-+ const char *z2 = z;
-+ DateTime tx;
-+ sqlite3_int64 day;
-+ if( !sqlite3Isdigit(*z2) ) z2++;
-+ memset(&tx, 0, sizeof(tx));
-+ if( parseHhMmSs(z2, &tx) ) break;
-+ computeJD(&tx);
-+ tx.iJD -= 43200000;
-+ day = tx.iJD/86400000;
-+ tx.iJD -= day*86400000;
-+ if( z[0]=='-' ) tx.iJD = -tx.iJD;
-+ computeJD(p);
-+ clearYMD_HMS_TZ(p);
-+ p->iJD += tx.iJD;
-+ rc = 0;
-+ break;
-+ }
-+ z += n;
-+ while( sqlite3Isspace(*z) ) z++;
-+ n = sqlite3Strlen30(z);
-+ if( n>10 || n<3 ) break;
-+ if( z[n-1]=='s' ){ z[n-1] = 0; n--; }
-+ computeJD(p);
-+ rc = 0;
-+ rRounder = r<0 ? -0.5 : +0.5;
-+ if( n==3 && strcmp(z,"day")==0 ){
-+ p->iJD += (sqlite3_int64)(r*86400000.0 + rRounder);
-+ }else if( n==4 && strcmp(z,"hour")==0 ){
-+ p->iJD += (sqlite3_int64)(r*(86400000.0/24.0) + rRounder);
-+ }else if( n==6 && strcmp(z,"minute")==0 ){
-+ p->iJD += (sqlite3_int64)(r*(86400000.0/(24.0*60.0)) + rRounder);
-+ }else if( n==6 && strcmp(z,"second")==0 ){
-+ p->iJD += (sqlite3_int64)(r*(86400000.0/(24.0*60.0*60.0)) + rRounder);
-+ }else if( n==5 && strcmp(z,"month")==0 ){
-+ int x, y;
-+ computeYMD_HMS(p);
-+ p->M += (int)r;
-+ x = p->M>0 ? (p->M-1)/12 : (p->M-12)/12;
-+ p->Y += x;
-+ p->M -= x*12;
-+ p->validJD = 0;
-+ computeJD(p);
-+ y = (int)r;
-+ if( y!=r ){
-+ p->iJD += (sqlite3_int64)((r - y)*30.0*86400000.0 + rRounder);
-+ }
-+ }else if( n==4 && strcmp(z,"year")==0 ){
-+ int y = (int)r;
-+ computeYMD_HMS(p);
-+ p->Y += y;
-+ p->validJD = 0;
-+ computeJD(p);
-+ if( y!=r ){
-+ p->iJD += (sqlite3_int64)((r - y)*365.0*86400000.0 + rRounder);
-+ }
-+ }else{
-+ rc = 1;
-+ }
-+ clearYMD_HMS_TZ(p);
-+ break;
- }
-- fprintf(out, "\n");
-- }
-- for(i=0; i<N_HASH; i++){
-- if( mem3.aiHash[i]==0 ) continue;
-- fprintf(out, "hash(%2d):", i);
-- for(j = mem3.aiHash[i]; j>0; j=mem3.aPool[j].u.list.next){
-- fprintf(out, " %p(%d)", &mem3.aPool[j],
-- (mem3.aPool[j-1].u.hdr.size4x/4)*8-8);
-+ default: {
-+ break;
- }
-- fprintf(out, "\n");
-- }
-- fprintf(out, "master=%d\n", mem3.iMaster);
-- fprintf(out, "nowUsed=%d\n", mem3.nPool*8 - mem3.szMaster*8);
-- fprintf(out, "mxUsed=%d\n", mem3.nPool*8 - mem3.mnMaster*8);
-- sqlite3_mutex_leave(mem3.mutex);
-- if( out==stdout ){
-- fflush(stdout);
-- }else{
-- fclose(out);
- }
--#else
-- UNUSED_PARAMETER(zFilename);
--#endif
-+ return rc;
- }
-
- /*
--** This routine is the only routine in this file with external
--** linkage.
--**
--** Populate the low-level memory allocation function pointers in
--** sqlite3GlobalConfig.m with pointers to the routines in this file. The
--** arguments specify the block of memory to manage.
-+** Process time function arguments. argv[0] is a date-time stamp.
-+** argv[1] and following are modifiers. Parse them all and write
-+** the resulting time into the DateTime structure p. Return 0
-+** on success and 1 if there are any errors.
- **
--** This routine is only called by sqlite3_config(), and therefore
--** is not required to be threadsafe (it is not).
-+** If there are zero parameters (if even argv[0] is undefined)
-+** then assume a default value of "now" for argv[0].
- */
--SQLITE_PRIVATE const sqlite3_mem_methods *sqlite3MemGetMemsys3(void){
-- static const sqlite3_mem_methods mempoolMethods = {
-- memsys3Malloc,
-- memsys3Free,
-- memsys3Realloc,
-- memsys3Size,
-- memsys3Roundup,
-- memsys3Init,
-- memsys3Shutdown,
-- 0
-- };
-- return &mempoolMethods;
-+static int isDate(
-+ sqlite3_context *context,
-+ int argc,
-+ sqlite3_value **argv,
-+ DateTime *p
-+){
-+ int i;
-+ const unsigned char *z;
-+ int eType;
-+ memset(p, 0, sizeof(*p));
-+ if( argc==0 ){
-+ return setDateTimeToCurrent(context, p);
-+ }
-+ if( (eType = sqlite3_value_type(argv[0]))==SQLITE_FLOAT
-+ || eType==SQLITE_INTEGER ){
-+ p->iJD = (sqlite3_int64)(sqlite3_value_double(argv[0])*86400000.0 + 0.5);
-+ p->validJD = 1;
-+ }else{
-+ z = sqlite3_value_text(argv[0]);
-+ if( !z || parseDateOrTime(context, (char*)z, p) ){
-+ return 1;
-+ }
-+ }
-+ for(i=1; i<argc; i++){
-+ z = sqlite3_value_text(argv[i]);
-+ if( z==0 || parseModifier(context, (char*)z, p) ) return 1;
-+ }
-+ return 0;
- }
-
--#endif /* SQLITE_ENABLE_MEMSYS3 */
--
--/************** End of mem3.c ************************************************/
--/************** Begin file mem5.c ********************************************/
--/*
--** 2007 October 14
--**
--** The author disclaims copyright to this source code. In place of
--** a legal notice, here is a blessing:
--**
--** May you do good and not evil.
--** May you find forgiveness for yourself and forgive others.
--** May you share freely, never taking more than you give.
--**
--*************************************************************************
--** This file contains the C functions that implement a memory
--** allocation subsystem for use by SQLite.
--**
--** This version of the memory allocation subsystem omits all
--** use of malloc(). The application gives SQLite a block of memory
--** before calling sqlite3_initialize() from which allocations
--** are made and returned by the xMalloc() and xRealloc()
--** implementations. Once sqlite3_initialize() has been called,
--** the amount of memory available to SQLite is fixed and cannot
--** be changed.
--**
--** This version of the memory allocation subsystem is included
--** in the build only if SQLITE_ENABLE_MEMSYS5 is defined.
--**
--** This memory allocator uses the following algorithm:
--**
--** 1. All memory allocations sizes are rounded up to a power of 2.
--**
--** 2. If two adjacent free blocks are the halves of a larger block,
--** then the two blocks are coalesed into the single larger block.
--**
--** 3. New memory is allocated from the first available free block.
--**
--** This algorithm is described in: J. M. Robson. "Bounds for Some Functions
--** Concerning Dynamic Storage Allocation". Journal of the Association for
--** Computing Machinery, Volume 21, Number 8, July 1974, pages 491-499.
--**
--** Let n be the size of the largest allocation divided by the minimum
--** allocation size (after rounding all sizes up to a power of 2.) Let M
--** be the maximum amount of memory ever outstanding at one time. Let
--** N be the total amount of memory available for allocation. Robson
--** proved that this memory allocator will never breakdown due to
--** fragmentation as long as the following constraint holds:
--**
--** N >= M*(1 + log2(n)/2) - n + 1
--**
--** The sqlite3_status() logic tracks the maximum values of n and M so
--** that an application can, at any time, verify this constraint.
--*/
-
- /*
--** This version of the memory allocator is used only when
--** SQLITE_ENABLE_MEMSYS5 is defined.
-+** The following routines implement the various date and time functions
-+** of SQLite.
- */
--#ifdef SQLITE_ENABLE_MEMSYS5
-
- /*
--** A minimum allocation is an instance of the following structure.
--** Larger allocations are an array of these structures where the
--** size of the array is a power of 2.
-+** julianday( TIMESTRING, MOD, MOD, ...)
- **
--** The size of this object must be a power of two. That fact is
--** verified in memsys5Init().
--*/
--typedef struct Mem5Link Mem5Link;
--struct Mem5Link {
-- int next; /* Index of next free chunk */
-- int prev; /* Index of previous free chunk */
--};
--
--/*
--** Maximum size of any allocation is ((1<<LOGMAX)*mem5.szAtom). Since
--** mem5.szAtom is always at least 8 and 32-bit integers are used,
--** it is not actually possible to reach this limit.
--*/
--#define LOGMAX 30
--
--/*
--** Masks used for mem5.aCtrl[] elements.
--*/
--#define CTRL_LOGSIZE 0x1f /* Log2 Size of this block */
--#define CTRL_FREE 0x20 /* True if not checked out */
--
--/*
--** All of the static variables used by this module are collected
--** into a single structure named "mem5". This is to keep the
--** static variables organized and to reduce namespace pollution
--** when this module is combined with other in the amalgamation.
--*/
--static SQLITE_WSD struct Mem5Global {
-- /*
-- ** Memory available for allocation
-- */
-- int szAtom; /* Smallest possible allocation in bytes */
-- int nBlock; /* Number of szAtom sized blocks in zPool */
-- u8 *zPool; /* Memory available to be allocated */
--
-- /*
-- ** Mutex to control access to the memory allocation subsystem.
-- */
-- sqlite3_mutex *mutex;
--
-- /*
-- ** Performance statistics
-- */
-- u64 nAlloc; /* Total number of calls to malloc */
-- u64 totalAlloc; /* Total of all malloc calls - includes internal frag */
-- u64 totalExcess; /* Total internal fragmentation */
-- u32 currentOut; /* Current checkout, including internal fragmentation */
-- u32 currentCount; /* Current number of distinct checkouts */
-- u32 maxOut; /* Maximum instantaneous currentOut */
-- u32 maxCount; /* Maximum instantaneous currentCount */
-- u32 maxRequest; /* Largest allocation (exclusive of internal frag) */
--
-- /*
-- ** Lists of free blocks. aiFreelist[0] is a list of free blocks of
-- ** size mem5.szAtom. aiFreelist[1] holds blocks of size szAtom*2.
-- ** and so forth.
-- */
-- int aiFreelist[LOGMAX+1];
--
-- /*
-- ** Space for tracking which blocks are checked out and the size
-- ** of each block. One byte per block.
-- */
-- u8 *aCtrl;
--
--} mem5;
--
--/*
--** Access the static variable through a macro for SQLITE_OMIT_WSD
--*/
--#define mem5 GLOBAL(struct Mem5Global, mem5)
--
--/*
--** Assuming mem5.zPool is divided up into an array of Mem5Link
--** structures, return a pointer to the idx-th such lik.
-+** Return the julian day number of the date specified in the arguments
- */
--#define MEM5LINK(idx) ((Mem5Link *)(&mem5.zPool[(idx)*mem5.szAtom]))
-+static void juliandayFunc(
-+ sqlite3_context *context,
-+ int argc,
-+ sqlite3_value **argv
-+){
-+ DateTime x;
-+ if( isDate(context, argc, argv, &x)==0 ){
-+ computeJD(&x);
-+ sqlite3_result_double(context, x.iJD/86400000.0);
-+ }
-+}
-
- /*
--** Unlink the chunk at mem5.aPool[i] from list it is currently
--** on. It should be found on mem5.aiFreelist[iLogsize].
-+** datetime( TIMESTRING, MOD, MOD, ...)
-+**
-+** Return YYYY-MM-DD HH:MM:SS
- */
--static void memsys5Unlink(int i, int iLogsize){
-- int next, prev;
-- assert( i>=0 && i<mem5.nBlock );
-- assert( iLogsize>=0 && iLogsize<=LOGMAX );
-- assert( (mem5.aCtrl[i] & CTRL_LOGSIZE)==iLogsize );
--
-- next = MEM5LINK(i)->next;
-- prev = MEM5LINK(i)->prev;
-- if( prev<0 ){
-- mem5.aiFreelist[iLogsize] = next;
-- }else{
-- MEM5LINK(prev)->next = next;
-- }
-- if( next>=0 ){
-- MEM5LINK(next)->prev = prev;
-+static void datetimeFunc(
-+ sqlite3_context *context,
-+ int argc,
-+ sqlite3_value **argv
-+){
-+ DateTime x;
-+ if( isDate(context, argc, argv, &x)==0 ){
-+ char zBuf[100];
-+ computeYMD_HMS(&x);
-+ sqlite3_snprintf(sizeof(zBuf), zBuf, "%04d-%02d-%02d %02d:%02d:%02d",
-+ x.Y, x.M, x.D, x.h, x.m, (int)(x.s));
-+ sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
- }
- }
-
- /*
--** Link the chunk at mem5.aPool[i] so that is on the iLogsize
--** free list.
-+** time( TIMESTRING, MOD, MOD, ...)
-+**
-+** Return HH:MM:SS
- */
--static void memsys5Link(int i, int iLogsize){
-- int x;
-- assert( sqlite3_mutex_held(mem5.mutex) );
-- assert( i>=0 && i<mem5.nBlock );
-- assert( iLogsize>=0 && iLogsize<=LOGMAX );
-- assert( (mem5.aCtrl[i] & CTRL_LOGSIZE)==iLogsize );
--
-- x = MEM5LINK(i)->next = mem5.aiFreelist[iLogsize];
-- MEM5LINK(i)->prev = -1;
-- if( x>=0 ){
-- assert( x<mem5.nBlock );
-- MEM5LINK(x)->prev = i;
-+static void timeFunc(
-+ sqlite3_context *context,
-+ int argc,
-+ sqlite3_value **argv
-+){
-+ DateTime x;
-+ if( isDate(context, argc, argv, &x)==0 ){
-+ char zBuf[100];
-+ computeHMS(&x);
-+ sqlite3_snprintf(sizeof(zBuf), zBuf, "%02d:%02d:%02d", x.h, x.m, (int)x.s);
-+ sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
- }
-- mem5.aiFreelist[iLogsize] = i;
- }
-
- /*
--** If the STATIC_MEM mutex is not already held, obtain it now. The mutex
--** will already be held (obtained by code in malloc.c) if
--** sqlite3GlobalConfig.bMemStat is true.
-+** date( TIMESTRING, MOD, MOD, ...)
-+**
-+** Return YYYY-MM-DD
- */
--static void memsys5Enter(void){
-- sqlite3_mutex_enter(mem5.mutex);
--}
--static void memsys5Leave(void){
-- sqlite3_mutex_leave(mem5.mutex);
--}
--
--/*
--** Return the size of an outstanding allocation, in bytes. The
--** size returned omits the 8-byte header overhead. This only
--** works for chunks that are currently checked out.
--*/
--static int memsys5Size(void *p){
-- int iSize = 0;
-- if( p ){
-- int i = ((u8 *)p-mem5.zPool)/mem5.szAtom;
-- assert( i>=0 && i<mem5.nBlock );
-- iSize = mem5.szAtom * (1 << (mem5.aCtrl[i]&CTRL_LOGSIZE));
-- }
-- return iSize;
--}
--
--/*
--** Find the first entry on the freelist iLogsize. Unlink that
--** entry and return its index.
--*/
--static int memsys5UnlinkFirst(int iLogsize){
-- int i;
-- int iFirst;
--
-- assert( iLogsize>=0 && iLogsize<=LOGMAX );
-- i = iFirst = mem5.aiFreelist[iLogsize];
-- assert( iFirst>=0 );
-- while( i>0 ){
-- if( i<iFirst ) iFirst = i;
-- i = MEM5LINK(i)->next;
-+static void dateFunc(
-+ sqlite3_context *context,
-+ int argc,
-+ sqlite3_value **argv
-+){
-+ DateTime x;
-+ if( isDate(context, argc, argv, &x)==0 ){
-+ char zBuf[100];
-+ computeYMD(&x);
-+ sqlite3_snprintf(sizeof(zBuf), zBuf, "%04d-%02d-%02d", x.Y, x.M, x.D);
-+ sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
- }
-- memsys5Unlink(iFirst, iLogsize);
-- return iFirst;
- }
-
- /*
--** Return a block of memory of at least nBytes in size.
--** Return NULL if unable. Return NULL if nBytes==0.
-+** strftime( FORMAT, TIMESTRING, MOD, MOD, ...)
- **
--** The caller guarantees that nByte positive.
-+** Return a string described by FORMAT. Conversions as follows:
- **
--** The caller has obtained a mutex prior to invoking this
--** routine so there is never any chance that two or more
--** threads can be in this routine at the same time.
-+** %d day of month
-+** %f ** fractional seconds SS.SSS
-+** %H hour 00-24
-+** %j day of year 000-366
-+** %J ** Julian day number
-+** %m month 01-12
-+** %M minute 00-59
-+** %s seconds since 1970-01-01
-+** %S seconds 00-59
-+** %w day of week 0-6 sunday==0
-+** %W week of year 00-53
-+** %Y year 0000-9999
-+** %% %
- */
--static void *memsys5MallocUnsafe(int nByte){
-- int i; /* Index of a mem5.aPool[] slot */
-- int iBin; /* Index into mem5.aiFreelist[] */
-- int iFullSz; /* Size of allocation rounded up to power of 2 */
-- int iLogsize; /* Log2 of iFullSz/POW2_MIN */
--
-- /* nByte must be a positive */
-- assert( nByte>0 );
--
-- /* Keep track of the maximum allocation request. Even unfulfilled
-- ** requests are counted */
-- if( (u32)nByte>mem5.maxRequest ){
-- mem5.maxRequest = nByte;
-- }
--
-- /* Abort if the requested allocation size is larger than the largest
-- ** power of two that we can represent using 32-bit signed integers.
-- */
-- if( nByte > 0x40000000 ){
-- return 0;
-+static void strftimeFunc(
-+ sqlite3_context *context,
-+ int argc,
-+ sqlite3_value **argv
-+){
-+ DateTime x;
-+ u64 n;
-+ size_t i,j;
-+ char *z;
-+ sqlite3 *db;
-+ const char *zFmt = (const char*)sqlite3_value_text(argv[0]);
-+ char zBuf[100];
-+ if( zFmt==0 || isDate(context, argc-1, argv+1, &x) ) return;
-+ db = sqlite3_context_db_handle(context);
-+ for(i=0, n=1; zFmt[i]; i++, n++){
-+ if( zFmt[i]=='%' ){
-+ switch( zFmt[i+1] ){
-+ case 'd':
-+ case 'H':
-+ case 'm':
-+ case 'M':
-+ case 'S':
-+ case 'W':
-+ n++;
-+ /* fall thru */
-+ case 'w':
-+ case '%':
-+ break;
-+ case 'f':
-+ n += 8;
-+ break;
-+ case 'j':
-+ n += 3;
-+ break;
-+ case 'Y':
-+ n += 8;
-+ break;
-+ case 's':
-+ case 'J':
-+ n += 50;
-+ break;
-+ default:
-+ return; /* ERROR. return a NULL */
-+ }
-+ i++;
-+ }
- }
--
-- /* Round nByte up to the next valid power of two */
-- for(iFullSz=mem5.szAtom, iLogsize=0; iFullSz<nByte; iFullSz *= 2, iLogsize++){}
--
-- /* Make sure mem5.aiFreelist[iLogsize] contains at least one free
-- ** block. If not, then split a block of the next larger power of
-- ** two in order to create a new free block of size iLogsize.
-- */
-- for(iBin=iLogsize; mem5.aiFreelist[iBin]<0 && iBin<=LOGMAX; iBin++){}
-- if( iBin>LOGMAX ){
-- testcase( sqlite3GlobalConfig.xLog!=0 );
-- sqlite3_log(SQLITE_NOMEM, "failed to allocate %u bytes", nByte);
-- return 0;
-+ testcase( n==sizeof(zBuf)-1 );
-+ testcase( n==sizeof(zBuf) );
-+ testcase( n==(u64)db->aLimit[SQLITE_LIMIT_LENGTH]+1 );
-+ testcase( n==(u64)db->aLimit[SQLITE_LIMIT_LENGTH] );
-+ if( n<sizeof(zBuf) ){
-+ z = zBuf;
-+ }else if( n>(u64)db->aLimit[SQLITE_LIMIT_LENGTH] ){
-+ sqlite3_result_error_toobig(context);
-+ return;
-+ }else{
-+ z = sqlite3DbMallocRaw(db, (int)n);
-+ if( z==0 ){
-+ sqlite3_result_error_nomem(context);
-+ return;
-+ }
- }
-- i = memsys5UnlinkFirst(iBin);
-- while( iBin>iLogsize ){
-- int newSize;
--
-- iBin--;
-- newSize = 1 << iBin;
-- mem5.aCtrl[i+newSize] = CTRL_FREE | iBin;
-- memsys5Link(i+newSize, iBin);
-+ computeJD(&x);
-+ computeYMD_HMS(&x);
-+ for(i=j=0; zFmt[i]; i++){
-+ if( zFmt[i]!='%' ){
-+ z[j++] = zFmt[i];
-+ }else{
-+ i++;
-+ switch( zFmt[i] ){
-+ case 'd': sqlite3_snprintf(3, &z[j],"%02d",x.D); j+=2; break;
-+ case 'f': {
-+ double s = x.s;
-+ if( s>59.999 ) s = 59.999;
-+ sqlite3_snprintf(7, &z[j],"%06.3f", s);
-+ j += sqlite3Strlen30(&z[j]);
-+ break;
-+ }
-+ case 'H': sqlite3_snprintf(3, &z[j],"%02d",x.h); j+=2; break;
-+ case 'W': /* Fall thru */
-+ case 'j': {
-+ int nDay; /* Number of days since 1st day of year */
-+ DateTime y = x;
-+ y.validJD = 0;
-+ y.M = 1;
-+ y.D = 1;
-+ computeJD(&y);
-+ nDay = (int)((x.iJD-y.iJD+43200000)/86400000);
-+ if( zFmt[i]=='W' ){
-+ int wd; /* 0=Monday, 1=Tuesday, ... 6=Sunday */
-+ wd = (int)(((x.iJD+43200000)/86400000)%7);
-+ sqlite3_snprintf(3, &z[j],"%02d",(nDay+7-wd)/7);
-+ j += 2;
-+ }else{
-+ sqlite3_snprintf(4, &z[j],"%03d",nDay+1);
-+ j += 3;
-+ }
-+ break;
-+ }
-+ case 'J': {
-+ sqlite3_snprintf(20, &z[j],"%.16g",x.iJD/86400000.0);
-+ j+=sqlite3Strlen30(&z[j]);
-+ break;
-+ }
-+ case 'm': sqlite3_snprintf(3, &z[j],"%02d",x.M); j+=2; break;
-+ case 'M': sqlite3_snprintf(3, &z[j],"%02d",x.m); j+=2; break;
-+ case 's': {
-+ sqlite3_snprintf(30,&z[j],"%lld",
-+ (i64)(x.iJD/1000 - 21086676*(i64)10000));
-+ j += sqlite3Strlen30(&z[j]);
-+ break;
-+ }
-+ case 'S': sqlite3_snprintf(3,&z[j],"%02d",(int)x.s); j+=2; break;
-+ case 'w': {
-+ z[j++] = (char)(((x.iJD+129600000)/86400000) % 7) + '0';
-+ break;
-+ }
-+ case 'Y': {
-+ sqlite3_snprintf(5,&z[j],"%04d",x.Y); j+=sqlite3Strlen30(&z[j]);
-+ break;
-+ }
-+ default: z[j++] = '%'; break;
-+ }
-+ }
- }
-- mem5.aCtrl[i] = iLogsize;
--
-- /* Update allocator performance statistics. */
-- mem5.nAlloc++;
-- mem5.totalAlloc += iFullSz;
-- mem5.totalExcess += iFullSz - nByte;
-- mem5.currentCount++;
-- mem5.currentOut += iFullSz;
-- if( mem5.maxCount<mem5.currentCount ) mem5.maxCount = mem5.currentCount;
-- if( mem5.maxOut<mem5.currentOut ) mem5.maxOut = mem5.currentOut;
--
-- /* Return a pointer to the allocated memory. */
-- return (void*)&mem5.zPool[i*mem5.szAtom];
-+ z[j] = 0;
-+ sqlite3_result_text(context, z, -1,
-+ z==zBuf ? SQLITE_TRANSIENT : SQLITE_DYNAMIC);
- }
-
- /*
--** Free an outstanding memory allocation.
-+** current_time()
-+**
-+** This function returns the same value as time('now').
- */
--static void memsys5FreeUnsafe(void *pOld){
-- u32 size, iLogsize;
-- int iBlock;
--
-- /* Set iBlock to the index of the block pointed to by pOld in
-- ** the array of mem5.szAtom byte blocks pointed to by mem5.zPool.
-- */
-- iBlock = ((u8 *)pOld-mem5.zPool)/mem5.szAtom;
--
-- /* Check that the pointer pOld points to a valid, non-free block. */
-- assert( iBlock>=0 && iBlock<mem5.nBlock );
-- assert( ((u8 *)pOld-mem5.zPool)%mem5.szAtom==0 );
-- assert( (mem5.aCtrl[iBlock] & CTRL_FREE)==0 );
--
-- iLogsize = mem5.aCtrl[iBlock] & CTRL_LOGSIZE;
-- size = 1<<iLogsize;
-- assert( iBlock+size-1<(u32)mem5.nBlock );
--
-- mem5.aCtrl[iBlock] |= CTRL_FREE;
-- mem5.aCtrl[iBlock+size-1] |= CTRL_FREE;
-- assert( mem5.currentCount>0 );
-- assert( mem5.currentOut>=(size*mem5.szAtom) );
-- mem5.currentCount--;
-- mem5.currentOut -= size*mem5.szAtom;
-- assert( mem5.currentOut>0 || mem5.currentCount==0 );
-- assert( mem5.currentCount>0 || mem5.currentOut==0 );
--
-- mem5.aCtrl[iBlock] = CTRL_FREE | iLogsize;
-- while( ALWAYS(iLogsize<LOGMAX) ){
-- int iBuddy;
-- if( (iBlock>>iLogsize) & 1 ){
-- iBuddy = iBlock - size;
-- }else{
-- iBuddy = iBlock + size;
-- }
-- assert( iBuddy>=0 );
-- if( (iBuddy+(1<<iLogsize))>mem5.nBlock ) break;
-- if( mem5.aCtrl[iBuddy]!=(CTRL_FREE | iLogsize) ) break;
-- memsys5Unlink(iBuddy, iLogsize);
-- iLogsize++;
-- if( iBuddy<iBlock ){
-- mem5.aCtrl[iBuddy] = CTRL_FREE | iLogsize;
-- mem5.aCtrl[iBlock] = 0;
-- iBlock = iBuddy;
-- }else{
-- mem5.aCtrl[iBlock] = CTRL_FREE | iLogsize;
-- mem5.aCtrl[iBuddy] = 0;
-- }
-- size *= 2;
-- }
-- memsys5Link(iBlock, iLogsize);
-+static void ctimeFunc(
-+ sqlite3_context *context,
-+ int NotUsed,
-+ sqlite3_value **NotUsed2
-+){
-+ UNUSED_PARAMETER2(NotUsed, NotUsed2);
-+ timeFunc(context, 0, 0);
- }
-
- /*
--** Allocate nBytes of memory
-+** current_date()
-+**
-+** This function returns the same value as date('now').
- */
--static void *memsys5Malloc(int nBytes){
-- sqlite3_int64 *p = 0;
-- if( nBytes>0 ){
-- memsys5Enter();
-- p = memsys5MallocUnsafe(nBytes);
-- memsys5Leave();
-- }
-- return (void*)p;
-+static void cdateFunc(
-+ sqlite3_context *context,
-+ int NotUsed,
-+ sqlite3_value **NotUsed2
-+){
-+ UNUSED_PARAMETER2(NotUsed, NotUsed2);
-+ dateFunc(context, 0, 0);
- }
-
- /*
--** Free memory.
-+** current_timestamp()
- **
--** The outer layer memory allocator prevents this routine from
--** being called with pPrior==0.
-+** This function returns the same value as datetime('now').
- */
--static void memsys5Free(void *pPrior){
-- assert( pPrior!=0 );
-- memsys5Enter();
-- memsys5FreeUnsafe(pPrior);
-- memsys5Leave();
-+static void ctimestampFunc(
-+ sqlite3_context *context,
-+ int NotUsed,
-+ sqlite3_value **NotUsed2
-+){
-+ UNUSED_PARAMETER2(NotUsed, NotUsed2);
-+ datetimeFunc(context, 0, 0);
- }
-+#endif /* !defined(SQLITE_OMIT_DATETIME_FUNCS) */
-
-+#ifdef SQLITE_OMIT_DATETIME_FUNCS
- /*
--** Change the size of an existing memory allocation.
--**
--** The outer layer memory allocator prevents this routine from
--** being called with pPrior==0.
-+** If the library is compiled to omit the full-scale date and time
-+** handling (to get a smaller binary), the following minimal version
-+** of the functions current_time(), current_date() and current_timestamp()
-+** are included instead. This is to support column declarations that
-+** include "DEFAULT CURRENT_TIME" etc.
- **
--** nBytes is always a value obtained from a prior call to
--** memsys5Round(). Hence nBytes is always a non-negative power
--** of two. If nBytes==0 that means that an oversize allocation
--** (an allocation larger than 0x40000000) was requested and this
--** routine should return 0 without freeing pPrior.
-+** This function uses the C-library functions time(), gmtime()
-+** and strftime(). The format string to pass to strftime() is supplied
-+** as the user-data for the function.
- */
--static void *memsys5Realloc(void *pPrior, int nBytes){
-- int nOld;
-- void *p;
-- assert( pPrior!=0 );
-- assert( (nBytes&(nBytes-1))==0 ); /* EV: R-46199-30249 */
-- assert( nBytes>=0 );
-- if( nBytes==0 ){
-- return 0;
-- }
-- nOld = memsys5Size(pPrior);
-- if( nBytes<=nOld ){
-- return pPrior;
-- }
-- memsys5Enter();
-- p = memsys5MallocUnsafe(nBytes);
-- if( p ){
-- memcpy(p, pPrior, nOld);
-- memsys5FreeUnsafe(pPrior);
-+static void currentTimeFunc(
-+ sqlite3_context *context,
-+ int argc,
-+ sqlite3_value **argv
-+){
-+ time_t t;
-+ char *zFormat = (char *)sqlite3_user_data(context);
-+ sqlite3 *db;
-+ sqlite3_int64 iT;
-+ struct tm *pTm;
-+ struct tm sNow;
-+ char zBuf[20];
-+
-+ UNUSED_PARAMETER(argc);
-+ UNUSED_PARAMETER(argv);
-+
-+ db = sqlite3_context_db_handle(context);
-+ if( sqlite3OsCurrentTimeInt64(db->pVfs, &iT) ) return;
-+ t = iT/1000 - 10000*(sqlite3_int64)21086676;
-+#ifdef HAVE_GMTIME_R
-+ pTm = gmtime_r(&t, &sNow);
-+#else
-+ sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
-+ pTm = gmtime(&t);
-+ if( pTm ) memcpy(&sNow, pTm, sizeof(sNow));
-+ sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
-+#endif
-+ if( pTm ){
-+ strftime(zBuf, 20, zFormat, &sNow);
-+ sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
- }
-- memsys5Leave();
-- return p;
- }
-+#endif
-
- /*
--** Round up a request size to the next valid allocation size. If
--** the allocation is too large to be handled by this allocation system,
--** return 0.
--**
--** All allocations must be a power of two and must be expressed by a
--** 32-bit signed integer. Hence the largest allocation is 0x40000000
--** or 1073741824 bytes.
-+** This function registered all of the above C functions as SQL
-+** functions. This should be the only routine in this file with
-+** external linkage.
- */
--static int memsys5Roundup(int n){
-- int iFullSz;
-- if( n > 0x40000000 ) return 0;
-- for(iFullSz=mem5.szAtom; iFullSz<n; iFullSz *= 2);
-- return iFullSz;
-+SQLITE_PRIVATE void sqlite3RegisterDateTimeFunctions(void){
-+ static SQLITE_WSD FuncDef aDateTimeFuncs[] = {
-+#ifndef SQLITE_OMIT_DATETIME_FUNCS
-+ FUNCTION(julianday, -1, 0, 0, juliandayFunc ),
-+ FUNCTION(date, -1, 0, 0, dateFunc ),
-+ FUNCTION(time, -1, 0, 0, timeFunc ),
-+ FUNCTION(datetime, -1, 0, 0, datetimeFunc ),
-+ FUNCTION(strftime, -1, 0, 0, strftimeFunc ),
-+ FUNCTION(current_time, 0, 0, 0, ctimeFunc ),
-+ FUNCTION(current_timestamp, 0, 0, 0, ctimestampFunc),
-+ FUNCTION(current_date, 0, 0, 0, cdateFunc ),
-+#else
-+ STR_FUNCTION(current_time, 0, "%H:%M:%S", 0, currentTimeFunc),
-+ STR_FUNCTION(current_date, 0, "%Y-%m-%d", 0, currentTimeFunc),
-+ STR_FUNCTION(current_timestamp, 0, "%Y-%m-%d %H:%M:%S", 0, currentTimeFunc),
-+#endif
-+ };
-+ int i;
-+ FuncDefHash *pHash = &GLOBAL(FuncDefHash, sqlite3GlobalFunctions);
-+ FuncDef *aFunc = (FuncDef*)&GLOBAL(FuncDef, aDateTimeFuncs);
-+
-+ for(i=0; i<ArraySize(aDateTimeFuncs); i++){
-+ sqlite3FuncDefInsert(pHash, &aFunc[i]);
-+ }
- }
-
-+/************** End of date.c ************************************************/
-+/************** Begin file os.c **********************************************/
- /*
--** Return the ceiling of the logarithm base 2 of iValue.
-+** 2005 November 29
- **
--** Examples: memsys5Log(1) -> 0
--** memsys5Log(2) -> 1
--** memsys5Log(4) -> 2
--** memsys5Log(5) -> 3
--** memsys5Log(8) -> 3
--** memsys5Log(9) -> 4
-+** The author disclaims copyright to this source code. In place of
-+** a legal notice, here is a blessing:
-+**
-+** May you do good and not evil.
-+** May you find forgiveness for yourself and forgive others.
-+** May you share freely, never taking more than you give.
-+**
-+******************************************************************************
-+**
-+** This file contains OS interface code that is common to all
-+** architectures.
- */
--static int memsys5Log(int iValue){
-- int iLog;
-- for(iLog=0; (iLog<(int)((sizeof(int)*8)-1)) && (1<<iLog)<iValue; iLog++);
-- return iLog;
--}
-+#define _SQLITE_OS_C_ 1
-+#undef _SQLITE_OS_C_
-
- /*
--** Initialize the memory allocator.
-+** The default SQLite sqlite3_vfs implementations do not allocate
-+** memory (actually, os_unix.c allocates a small amount of memory
-+** from within OsOpen()), but some third-party implementations may.
-+** So we test the effects of a malloc() failing and the sqlite3OsXXX()
-+** function returning SQLITE_IOERR_NOMEM using the DO_OS_MALLOC_TEST macro.
-+**
-+** The following functions are instrumented for malloc() failure
-+** testing:
-+**
-+** sqlite3OsRead()
-+** sqlite3OsWrite()
-+** sqlite3OsSync()
-+** sqlite3OsFileSize()
-+** sqlite3OsLock()
-+** sqlite3OsCheckReservedLock()
-+** sqlite3OsFileControl()
-+** sqlite3OsShmMap()
-+** sqlite3OsOpen()
-+** sqlite3OsDelete()
-+** sqlite3OsAccess()
-+** sqlite3OsFullPathname()
- **
--** This routine is not threadsafe. The caller must be holding a mutex
--** to prevent multiple threads from entering at the same time.
- */
--static int memsys5Init(void *NotUsed){
-- int ii; /* Loop counter */
-- int nByte; /* Number of bytes of memory available to this allocator */
-- u8 *zByte; /* Memory usable by this allocator */
-- int nMinLog; /* Log base 2 of minimum allocation size in bytes */
-- int iOffset; /* An offset into mem5.aCtrl[] */
--
-- UNUSED_PARAMETER(NotUsed);
--
-- /* For the purposes of this routine, disable the mutex */
-- mem5.mutex = 0;
-+#if defined(SQLITE_TEST)
-+SQLITE_API int sqlite3_memdebug_vfs_oom_test = 1;
-+ #define DO_OS_MALLOC_TEST(x) \
-+ if (sqlite3_memdebug_vfs_oom_test && (!x || !sqlite3IsMemJournal(x))) { \
-+ void *pTstAlloc = sqlite3Malloc(10); \
-+ if (!pTstAlloc) return SQLITE_IOERR_NOMEM; \
-+ sqlite3_free(pTstAlloc); \
-+ }
-+#else
-+ #define DO_OS_MALLOC_TEST(x)
-+#endif
-
-- /* The size of a Mem5Link object must be a power of two. Verify that
-- ** this is case.
-- */
-- assert( (sizeof(Mem5Link)&(sizeof(Mem5Link)-1))==0 );
-+/*
-+** The following routines are convenience wrappers around methods
-+** of the sqlite3_file object. This is mostly just syntactic sugar. All
-+** of this would be completely automatic if SQLite were coded using
-+** C++ instead of plain old C.
-+*/
-+SQLITE_PRIVATE int sqlite3OsClose(sqlite3_file *pId){
-+ int rc = SQLITE_OK;
-+ if( pId->pMethods ){
-+ rc = pId->pMethods->xClose(pId);
-+ pId->pMethods = 0;
-+ }
-+ return rc;
-+}
-+SQLITE_PRIVATE int sqlite3OsRead(sqlite3_file *id, void *pBuf, int amt, i64 offset){
-+ DO_OS_MALLOC_TEST(id);
-+ return id->pMethods->xRead(id, pBuf, amt, offset);
-+}
-+SQLITE_PRIVATE int sqlite3OsWrite(sqlite3_file *id, const void *pBuf, int amt, i64 offset){
-+ DO_OS_MALLOC_TEST(id);
-+ return id->pMethods->xWrite(id, pBuf, amt, offset);
-+}
-+SQLITE_PRIVATE int sqlite3OsTruncate(sqlite3_file *id, i64 size){
-+ return id->pMethods->xTruncate(id, size);
-+}
-+SQLITE_PRIVATE int sqlite3OsSync(sqlite3_file *id, int flags){
-+ DO_OS_MALLOC_TEST(id);
-+ return id->pMethods->xSync(id, flags);
-+}
-+SQLITE_PRIVATE int sqlite3OsFileSize(sqlite3_file *id, i64 *pSize){
-+ DO_OS_MALLOC_TEST(id);
-+ return id->pMethods->xFileSize(id, pSize);
-+}
-+SQLITE_PRIVATE int sqlite3OsLock(sqlite3_file *id, int lockType){
-+ DO_OS_MALLOC_TEST(id);
-+ return id->pMethods->xLock(id, lockType);
-+}
-+SQLITE_PRIVATE int sqlite3OsUnlock(sqlite3_file *id, int lockType){
-+ return id->pMethods->xUnlock(id, lockType);
-+}
-+SQLITE_PRIVATE int sqlite3OsCheckReservedLock(sqlite3_file *id, int *pResOut){
-+ DO_OS_MALLOC_TEST(id);
-+ return id->pMethods->xCheckReservedLock(id, pResOut);
-+}
-
-- nByte = sqlite3GlobalConfig.nHeap;
-- zByte = (u8*)sqlite3GlobalConfig.pHeap;
-- assert( zByte!=0 ); /* sqlite3_config() does not allow otherwise */
-+/*
-+** Use sqlite3OsFileControl() when we are doing something that might fail
-+** and we need to know about the failures. Use sqlite3OsFileControlHint()
-+** when simply tossing information over the wall to the VFS and we do not
-+** really care if the VFS receives and understands the information since it
-+** is only a hint and can be safely ignored. The sqlite3OsFileControlHint()
-+** routine has no return value since the return value would be meaningless.
-+*/
-+SQLITE_PRIVATE int sqlite3OsFileControl(sqlite3_file *id, int op, void *pArg){
-+ DO_OS_MALLOC_TEST(id);
-+ return id->pMethods->xFileControl(id, op, pArg);
-+}
-+SQLITE_PRIVATE void sqlite3OsFileControlHint(sqlite3_file *id, int op, void *pArg){
-+ (void)id->pMethods->xFileControl(id, op, pArg);
-+}
-
-- /* boundaries on sqlite3GlobalConfig.mnReq are enforced in sqlite3_config() */
-- nMinLog = memsys5Log(sqlite3GlobalConfig.mnReq);
-- mem5.szAtom = (1<<nMinLog);
-- while( (int)sizeof(Mem5Link)>mem5.szAtom ){
-- mem5.szAtom = mem5.szAtom << 1;
-- }
-+SQLITE_PRIVATE int sqlite3OsSectorSize(sqlite3_file *id){
-+ int (*xSectorSize)(sqlite3_file*) = id->pMethods->xSectorSize;
-+ return (xSectorSize ? xSectorSize(id) : SQLITE_DEFAULT_SECTOR_SIZE);
-+}
-+SQLITE_PRIVATE int sqlite3OsDeviceCharacteristics(sqlite3_file *id){
-+ return id->pMethods->xDeviceCharacteristics(id);
-+}
-+SQLITE_PRIVATE int sqlite3OsShmLock(sqlite3_file *id, int offset, int n, int flags){
-+ return id->pMethods->xShmLock(id, offset, n, flags);
-+}
-+SQLITE_PRIVATE void sqlite3OsShmBarrier(sqlite3_file *id){
-+ id->pMethods->xShmBarrier(id);
-+}
-+SQLITE_PRIVATE int sqlite3OsShmUnmap(sqlite3_file *id, int deleteFlag){
-+ return id->pMethods->xShmUnmap(id, deleteFlag);
-+}
-+SQLITE_PRIVATE int sqlite3OsShmMap(
-+ sqlite3_file *id, /* Database file handle */
-+ int iPage,
-+ int pgsz,
-+ int bExtend, /* True to extend file if necessary */
-+ void volatile **pp /* OUT: Pointer to mapping */
-+){
-+ DO_OS_MALLOC_TEST(id);
-+ return id->pMethods->xShmMap(id, iPage, pgsz, bExtend, pp);
-+}
-
-- mem5.nBlock = (nByte / (mem5.szAtom+sizeof(u8)));
-- mem5.zPool = zByte;
-- mem5.aCtrl = (u8 *)&mem5.zPool[mem5.nBlock*mem5.szAtom];
-+#if SQLITE_MAX_MMAP_SIZE>0
-+/* The real implementation of xFetch and xUnfetch */
-+SQLITE_PRIVATE int sqlite3OsFetch(sqlite3_file *id, i64 iOff, int iAmt, void **pp){
-+ DO_OS_MALLOC_TEST(id);
-+ return id->pMethods->xFetch(id, iOff, iAmt, pp);
-+}
-+SQLITE_PRIVATE int sqlite3OsUnfetch(sqlite3_file *id, i64 iOff, void *p){
-+ return id->pMethods->xUnfetch(id, iOff, p);
-+}
-+#else
-+/* No-op stubs to use when memory-mapped I/O is disabled */
-+SQLITE_PRIVATE int sqlite3OsFetch(sqlite3_file *id, i64 iOff, int iAmt, void **pp){
-+ *pp = 0;
-+ return SQLITE_OK;
-+}
-+SQLITE_PRIVATE int sqlite3OsUnfetch(sqlite3_file *id, i64 iOff, void *p){
-+ return SQLITE_OK;
-+}
-+#endif
-
-- for(ii=0; ii<=LOGMAX; ii++){
-- mem5.aiFreelist[ii] = -1;
-+/*
-+** The next group of routines are convenience wrappers around the
-+** VFS methods.
-+*/
-+SQLITE_PRIVATE int sqlite3OsOpen(
-+ sqlite3_vfs *pVfs,
-+ const char *zPath,
-+ sqlite3_file *pFile,
-+ int flags,
-+ int *pFlagsOut
-+){
-+ int rc;
-+ DO_OS_MALLOC_TEST(0);
-+ /* 0x87f7f is a mask of SQLITE_OPEN_ flags that are valid to be passed
-+ ** down into the VFS layer. Some SQLITE_OPEN_ flags (for example,
-+ ** SQLITE_OPEN_FULLMUTEX or SQLITE_OPEN_SHAREDCACHE) are blocked before
-+ ** reaching the VFS. */
-+ rc = pVfs->xOpen(pVfs, zPath, pFile, flags & 0x87f7f, pFlagsOut);
-+ assert( rc==SQLITE_OK || pFile->pMethods==0 );
-+ return rc;
-+}
-+SQLITE_PRIVATE int sqlite3OsDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
-+ DO_OS_MALLOC_TEST(0);
-+ assert( dirSync==0 || dirSync==1 );
-+ return pVfs->xDelete(pVfs, zPath, dirSync);
-+}
-+SQLITE_PRIVATE int sqlite3OsAccess(
-+ sqlite3_vfs *pVfs,
-+ const char *zPath,
-+ int flags,
-+ int *pResOut
-+){
-+ DO_OS_MALLOC_TEST(0);
-+ return pVfs->xAccess(pVfs, zPath, flags, pResOut);
-+}
-+SQLITE_PRIVATE int sqlite3OsFullPathname(
-+ sqlite3_vfs *pVfs,
-+ const char *zPath,
-+ int nPathOut,
-+ char *zPathOut
-+){
-+ DO_OS_MALLOC_TEST(0);
-+ zPathOut[0] = 0;
-+ return pVfs->xFullPathname(pVfs, zPath, nPathOut, zPathOut);
-+}
-+#ifndef SQLITE_OMIT_LOAD_EXTENSION
-+SQLITE_PRIVATE void *sqlite3OsDlOpen(sqlite3_vfs *pVfs, const char *zPath){
-+ return pVfs->xDlOpen(pVfs, zPath);
-+}
-+SQLITE_PRIVATE void sqlite3OsDlError(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
-+ pVfs->xDlError(pVfs, nByte, zBufOut);
-+}
-+SQLITE_PRIVATE void (*sqlite3OsDlSym(sqlite3_vfs *pVfs, void *pHdle, const char *zSym))(void){
-+ return pVfs->xDlSym(pVfs, pHdle, zSym);
-+}
-+SQLITE_PRIVATE void sqlite3OsDlClose(sqlite3_vfs *pVfs, void *pHandle){
-+ pVfs->xDlClose(pVfs, pHandle);
-+}
-+#endif /* SQLITE_OMIT_LOAD_EXTENSION */
-+SQLITE_PRIVATE int sqlite3OsRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
-+ return pVfs->xRandomness(pVfs, nByte, zBufOut);
-+}
-+SQLITE_PRIVATE int sqlite3OsSleep(sqlite3_vfs *pVfs, int nMicro){
-+ return pVfs->xSleep(pVfs, nMicro);
-+}
-+SQLITE_PRIVATE int sqlite3OsCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *pTimeOut){
-+ int rc;
-+ /* IMPLEMENTATION-OF: R-49045-42493 SQLite will use the xCurrentTimeInt64()
-+ ** method to get the current date and time if that method is available
-+ ** (if iVersion is 2 or greater and the function pointer is not NULL) and
-+ ** will fall back to xCurrentTime() if xCurrentTimeInt64() is
-+ ** unavailable.
-+ */
-+ if( pVfs->iVersion>=2 && pVfs->xCurrentTimeInt64 ){
-+ rc = pVfs->xCurrentTimeInt64(pVfs, pTimeOut);
-+ }else{
-+ double r;
-+ rc = pVfs->xCurrentTime(pVfs, &r);
-+ *pTimeOut = (sqlite3_int64)(r*86400000.0);
- }
-+ return rc;
-+}
-
-- iOffset = 0;
-- for(ii=LOGMAX; ii>=0; ii--){
-- int nAlloc = (1<<ii);
-- if( (iOffset+nAlloc)<=mem5.nBlock ){
-- mem5.aCtrl[iOffset] = ii | CTRL_FREE;
-- memsys5Link(iOffset, ii);
-- iOffset += nAlloc;
-+SQLITE_PRIVATE int sqlite3OsOpenMalloc(
-+ sqlite3_vfs *pVfs,
-+ const char *zFile,
-+ sqlite3_file **ppFile,
-+ int flags,
-+ int *pOutFlags
-+){
-+ int rc = SQLITE_NOMEM;
-+ sqlite3_file *pFile;
-+ pFile = (sqlite3_file *)sqlite3MallocZero(pVfs->szOsFile);
-+ if( pFile ){
-+ rc = sqlite3OsOpen(pVfs, zFile, pFile, flags, pOutFlags);
-+ if( rc!=SQLITE_OK ){
-+ sqlite3_free(pFile);
-+ }else{
-+ *ppFile = pFile;
- }
-- assert((iOffset+nAlloc)>mem5.nBlock);
-- }
--
-- /* If a mutex is required for normal operation, allocate one */
-- if( sqlite3GlobalConfig.bMemstat==0 ){
-- mem5.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM);
- }
--
-- return SQLITE_OK;
-+ return rc;
-+}
-+SQLITE_PRIVATE int sqlite3OsCloseFree(sqlite3_file *pFile){
-+ int rc = SQLITE_OK;
-+ assert( pFile );
-+ rc = sqlite3OsClose(pFile);
-+ sqlite3_free(pFile);
-+ return rc;
- }
-
- /*
--** Deinitialize this module.
-+** This function is a wrapper around the OS specific implementation of
-+** sqlite3_os_init(). The purpose of the wrapper is to provide the
-+** ability to simulate a malloc failure, so that the handling of an
-+** error in sqlite3_os_init() by the upper layers can be tested.
- */
--static void memsys5Shutdown(void *NotUsed){
-- UNUSED_PARAMETER(NotUsed);
-- mem5.mutex = 0;
-- return;
-+SQLITE_PRIVATE int sqlite3OsInit(void){
-+ void *p = sqlite3_malloc(10);
-+ if( p==0 ) return SQLITE_NOMEM;
-+ sqlite3_free(p);
-+ return sqlite3_os_init();
- }
-
--#ifdef SQLITE_TEST
- /*
--** Open the file indicated and write a log of all unfreed memory
--** allocations into that log.
-+** The list of all registered VFS implementations.
- */
--SQLITE_PRIVATE void sqlite3Memsys5Dump(const char *zFilename){
-- FILE *out;
-- int i, j, n;
-- int nMinLog;
-+static sqlite3_vfs * SQLITE_WSD vfsList = 0;
-+#define vfsList GLOBAL(sqlite3_vfs *, vfsList)
-
-- if( zFilename==0 || zFilename[0]==0 ){
-- out = stdout;
-- }else{
-- out = fopen(zFilename, "w");
-- if( out==0 ){
-- fprintf(stderr, "** Unable to output memory debug output log: %s **\n",
-- zFilename);
-- return;
-- }
-+/*
-+** Locate a VFS by name. If no name is given, simply return the
-+** first VFS on the list.
-+*/
-+SQLITE_API sqlite3_vfs *sqlite3_vfs_find(const char *zVfs){
-+ sqlite3_vfs *pVfs = 0;
-+#if SQLITE_THREADSAFE
-+ sqlite3_mutex *mutex;
-+#endif
-+#ifndef SQLITE_OMIT_AUTOINIT
-+ int rc = sqlite3_initialize();
-+ if( rc ) return 0;
-+#endif
-+#if SQLITE_THREADSAFE
-+ mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
-+#endif
-+ sqlite3_mutex_enter(mutex);
-+ for(pVfs = vfsList; pVfs; pVfs=pVfs->pNext){
-+ if( zVfs==0 ) break;
-+ if( strcmp(zVfs, pVfs->zName)==0 ) break;
- }
-- memsys5Enter();
-- nMinLog = memsys5Log(mem5.szAtom);
-- for(i=0; i<=LOGMAX && i+nMinLog<32; i++){
-- for(n=0, j=mem5.aiFreelist[i]; j>=0; j = MEM5LINK(j)->next, n++){}
-- fprintf(out, "freelist items of size %d: %d\n", mem5.szAtom << i, n);
-+ sqlite3_mutex_leave(mutex);
-+ return pVfs;
-+}
-+
-+/*
-+** Unlink a VFS from the linked list
-+*/
-+static void vfsUnlink(sqlite3_vfs *pVfs){
-+ assert( sqlite3_mutex_held(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER)) );
-+ if( pVfs==0 ){
-+ /* No-op */
-+ }else if( vfsList==pVfs ){
-+ vfsList = pVfs->pNext;
-+ }else if( vfsList ){
-+ sqlite3_vfs *p = vfsList;
-+ while( p->pNext && p->pNext!=pVfs ){
-+ p = p->pNext;
-+ }
-+ if( p->pNext==pVfs ){
-+ p->pNext = pVfs->pNext;
-+ }
- }
-- fprintf(out, "mem5.nAlloc = %llu\n", mem5.nAlloc);
-- fprintf(out, "mem5.totalAlloc = %llu\n", mem5.totalAlloc);
-- fprintf(out, "mem5.totalExcess = %llu\n", mem5.totalExcess);
-- fprintf(out, "mem5.currentOut = %u\n", mem5.currentOut);
-- fprintf(out, "mem5.currentCount = %u\n", mem5.currentCount);
-- fprintf(out, "mem5.maxOut = %u\n", mem5.maxOut);
-- fprintf(out, "mem5.maxCount = %u\n", mem5.maxCount);
-- fprintf(out, "mem5.maxRequest = %u\n", mem5.maxRequest);
-- memsys5Leave();
-- if( out==stdout ){
-- fflush(stdout);
-+}
-+
-+/*
-+** Register a VFS with the system. It is harmless to register the same
-+** VFS multiple times. The new VFS becomes the default if makeDflt is
-+** true.
-+*/
-+SQLITE_API int sqlite3_vfs_register(sqlite3_vfs *pVfs, int makeDflt){
-+ MUTEX_LOGIC(sqlite3_mutex *mutex;)
-+#ifndef SQLITE_OMIT_AUTOINIT
-+ int rc = sqlite3_initialize();
-+ if( rc ) return rc;
-+#endif
-+ MUTEX_LOGIC( mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); )
-+ sqlite3_mutex_enter(mutex);
-+ vfsUnlink(pVfs);
-+ if( makeDflt || vfsList==0 ){
-+ pVfs->pNext = vfsList;
-+ vfsList = pVfs;
- }else{
-- fclose(out);
-+ pVfs->pNext = vfsList->pNext;
-+ vfsList->pNext = pVfs;
- }
-+ assert(vfsList);
-+ sqlite3_mutex_leave(mutex);
-+ return SQLITE_OK;
- }
--#endif
-
- /*
--** This routine is the only routine in this file with external
--** linkage. It returns a pointer to a static sqlite3_mem_methods
--** struct populated with the memsys5 methods.
-+** Unregister a VFS so that it is no longer accessible.
- */
--SQLITE_PRIVATE const sqlite3_mem_methods *sqlite3MemGetMemsys5(void){
-- static const sqlite3_mem_methods memsys5Methods = {
-- memsys5Malloc,
-- memsys5Free,
-- memsys5Realloc,
-- memsys5Size,
-- memsys5Roundup,
-- memsys5Init,
-- memsys5Shutdown,
-- 0
-- };
-- return &memsys5Methods;
-+SQLITE_API int sqlite3_vfs_unregister(sqlite3_vfs *pVfs){
-+#if SQLITE_THREADSAFE
-+ sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
-+#endif
-+ sqlite3_mutex_enter(mutex);
-+ vfsUnlink(pVfs);
-+ sqlite3_mutex_leave(mutex);
-+ return SQLITE_OK;
- }
-
--#endif /* SQLITE_ENABLE_MEMSYS5 */
--
--/************** End of mem5.c ************************************************/
--/************** Begin file mutex.c *******************************************/
-+/************** End of os.c **************************************************/
-+/************** Begin file fault.c *******************************************/
- /*
--** 2007 August 14
-+** 2008 Jan 22
- **
- ** The author disclaims copyright to this source code. In place of
- ** a legal notice, here is a blessing:
-@@ -17715,152 +18517,147 @@
- ** May you share freely, never taking more than you give.
- **
- *************************************************************************
--** This file contains the C functions that implement mutexes.
- **
--** This file contains code that is common across all mutex implementations.
-+** This file contains code to support the concept of "benign"
-+** malloc failures (when the xMalloc() or xRealloc() method of the
-+** sqlite3_mem_methods structure fails to allocate a block of memory
-+** and returns 0).
-+**
-+** Most malloc failures are non-benign. After they occur, SQLite
-+** abandons the current operation and returns an error code (usually
-+** SQLITE_NOMEM) to the user. However, sometimes a fault is not necessarily
-+** fatal. For example, if a malloc fails while resizing a hash table, this
-+** is completely recoverable simply by not carrying out the resize. The
-+** hash table will continue to function normally. So a malloc failure
-+** during a hash table resize is a benign fault.
- */
-
--#if defined(SQLITE_DEBUG) && !defined(SQLITE_MUTEX_OMIT)
--/*
--** For debugging purposes, record when the mutex subsystem is initialized
--** and uninitialized so that we can assert() if there is an attempt to
--** allocate a mutex while the system is uninitialized.
--*/
--static SQLITE_WSD int mutexIsInit = 0;
--#endif /* SQLITE_DEBUG */
-
-+#ifndef SQLITE_OMIT_BUILTIN_TEST
-
--#ifndef SQLITE_MUTEX_OMIT
- /*
--** Initialize the mutex system.
-+** Global variables.
- */
--SQLITE_PRIVATE int sqlite3MutexInit(void){
-- int rc = SQLITE_OK;
-- if( !sqlite3GlobalConfig.mutex.xMutexAlloc ){
-- /* If the xMutexAlloc method has not been set, then the user did not
-- ** install a mutex implementation via sqlite3_config() prior to
-- ** sqlite3_initialize() being called. This block copies pointers to
-- ** the default implementation into the sqlite3GlobalConfig structure.
-- */
-- sqlite3_mutex_methods const *pFrom;
-- sqlite3_mutex_methods *pTo = &sqlite3GlobalConfig.mutex;
--
-- if( sqlite3GlobalConfig.bCoreMutex ){
-- pFrom = sqlite3DefaultMutex();
-- }else{
-- pFrom = sqlite3NoopMutex();
-- }
-- memcpy(pTo, pFrom, offsetof(sqlite3_mutex_methods, xMutexAlloc));
-- memcpy(&pTo->xMutexFree, &pFrom->xMutexFree,
-- sizeof(*pTo) - offsetof(sqlite3_mutex_methods, xMutexFree));
-- pTo->xMutexAlloc = pFrom->xMutexAlloc;
-- }
-- rc = sqlite3GlobalConfig.mutex.xMutexInit();
-+typedef struct BenignMallocHooks BenignMallocHooks;
-+static SQLITE_WSD struct BenignMallocHooks {
-+ void (*xBenignBegin)(void);
-+ void (*xBenignEnd)(void);
-+} sqlite3Hooks = { 0, 0 };
-
--#ifdef SQLITE_DEBUG
-- GLOBAL(int, mutexIsInit) = 1;
-+/* The "wsdHooks" macro will resolve to the appropriate BenignMallocHooks
-+** structure. If writable static data is unsupported on the target,
-+** we have to locate the state vector at run-time. In the more common
-+** case where writable static data is supported, wsdHooks can refer directly
-+** to the "sqlite3Hooks" state vector declared above.
-+*/
-+#ifdef SQLITE_OMIT_WSD
-+# define wsdHooksInit \
-+ BenignMallocHooks *x = &GLOBAL(BenignMallocHooks,sqlite3Hooks)
-+# define wsdHooks x[0]
-+#else
-+# define wsdHooksInit
-+# define wsdHooks sqlite3Hooks
- #endif
-
-- return rc;
--}
-
- /*
--** Shutdown the mutex system. This call frees resources allocated by
--** sqlite3MutexInit().
-+** Register hooks to call when sqlite3BeginBenignMalloc() and
-+** sqlite3EndBenignMalloc() are called, respectively.
- */
--SQLITE_PRIVATE int sqlite3MutexEnd(void){
-- int rc = SQLITE_OK;
-- if( sqlite3GlobalConfig.mutex.xMutexEnd ){
-- rc = sqlite3GlobalConfig.mutex.xMutexEnd();
-- }
--
--#ifdef SQLITE_DEBUG
-- GLOBAL(int, mutexIsInit) = 0;
--#endif
--
-- return rc;
-+SQLITE_PRIVATE void sqlite3BenignMallocHooks(
-+ void (*xBenignBegin)(void),
-+ void (*xBenignEnd)(void)
-+){
-+ wsdHooksInit;
-+ wsdHooks.xBenignBegin = xBenignBegin;
-+ wsdHooks.xBenignEnd = xBenignEnd;
- }
-
- /*
--** Retrieve a pointer to a static mutex or allocate a new dynamic one.
-+** This (sqlite3EndBenignMalloc()) is called by SQLite code to indicate that
-+** subsequent malloc failures are benign. A call to sqlite3EndBenignMalloc()
-+** indicates that subsequent malloc failures are non-benign.
- */
--SQLITE_API sqlite3_mutex *sqlite3_mutex_alloc(int id){
--#ifndef SQLITE_OMIT_AUTOINIT
-- if( sqlite3_initialize() ) return 0;
--#endif
-- return sqlite3GlobalConfig.mutex.xMutexAlloc(id);
--}
--
--SQLITE_PRIVATE sqlite3_mutex *sqlite3MutexAlloc(int id){
-- if( !sqlite3GlobalConfig.bCoreMutex ){
-- return 0;
-+SQLITE_PRIVATE void sqlite3BeginBenignMalloc(void){
-+ wsdHooksInit;
-+ if( wsdHooks.xBenignBegin ){
-+ wsdHooks.xBenignBegin();
- }
-- assert( GLOBAL(int, mutexIsInit) );
-- return sqlite3GlobalConfig.mutex.xMutexAlloc(id);
- }
--
--/*
--** Free a dynamic mutex.
--*/
--SQLITE_API void sqlite3_mutex_free(sqlite3_mutex *p){
-- if( p ){
-- sqlite3GlobalConfig.mutex.xMutexFree(p);
-+SQLITE_PRIVATE void sqlite3EndBenignMalloc(void){
-+ wsdHooksInit;
-+ if( wsdHooks.xBenignEnd ){
-+ wsdHooks.xBenignEnd();
- }
- }
-
-+#endif /* #ifndef SQLITE_OMIT_BUILTIN_TEST */
-+
-+/************** End of fault.c ***********************************************/
-+/************** Begin file mem0.c ********************************************/
- /*
--** Obtain the mutex p. If some other thread already has the mutex, block
--** until it can be obtained.
-+** 2008 October 28
-+**
-+** The author disclaims copyright to this source code. In place of
-+** a legal notice, here is a blessing:
-+**
-+** May you do good and not evil.
-+** May you find forgiveness for yourself and forgive others.
-+** May you share freely, never taking more than you give.
-+**
-+*************************************************************************
-+**
-+** This file contains a no-op memory allocation drivers for use when
-+** SQLITE_ZERO_MALLOC is defined. The allocation drivers implemented
-+** here always fail. SQLite will not operate with these drivers. These
-+** are merely placeholders. Real drivers must be substituted using
-+** sqlite3_config() before SQLite will operate.
- */
--SQLITE_API void sqlite3_mutex_enter(sqlite3_mutex *p){
-- if( p ){
-- sqlite3GlobalConfig.mutex.xMutexEnter(p);
-- }
--}
-
- /*
--** Obtain the mutex p. If successful, return SQLITE_OK. Otherwise, if another
--** thread holds the mutex and it cannot be obtained, return SQLITE_BUSY.
-+** This version of the memory allocator is the default. It is
-+** used when no other memory allocator is specified using compile-time
-+** macros.
- */
--SQLITE_API int sqlite3_mutex_try(sqlite3_mutex *p){
-- int rc = SQLITE_OK;
-- if( p ){
-- return sqlite3GlobalConfig.mutex.xMutexTry(p);
-- }
-- return rc;
--}
-+#ifdef SQLITE_ZERO_MALLOC
-
- /*
--** The sqlite3_mutex_leave() routine exits a mutex that was previously
--** entered by the same thread. The behavior is undefined if the mutex
--** is not currently entered. If a NULL pointer is passed as an argument
--** this function is a no-op.
-+** No-op versions of all memory allocation routines
- */
--SQLITE_API void sqlite3_mutex_leave(sqlite3_mutex *p){
-- if( p ){
-- sqlite3GlobalConfig.mutex.xMutexLeave(p);
-- }
--}
-+static void *sqlite3MemMalloc(int nByte){ return 0; }
-+static void sqlite3MemFree(void *pPrior){ return; }
-+static void *sqlite3MemRealloc(void *pPrior, int nByte){ return 0; }
-+static int sqlite3MemSize(void *pPrior){ return 0; }
-+static int sqlite3MemRoundup(int n){ return n; }
-+static int sqlite3MemInit(void *NotUsed){ return SQLITE_OK; }
-+static void sqlite3MemShutdown(void *NotUsed){ return; }
-
--#ifndef NDEBUG
- /*
--** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are
--** intended for use inside assert() statements.
-+** This routine is the only routine in this file with external linkage.
-+**
-+** Populate the low-level memory allocation function pointers in
-+** sqlite3GlobalConfig.m with pointers to the routines in this file.
- */
--SQLITE_API int sqlite3_mutex_held(sqlite3_mutex *p){
-- return p==0 || sqlite3GlobalConfig.mutex.xMutexHeld(p);
--}
--SQLITE_API int sqlite3_mutex_notheld(sqlite3_mutex *p){
-- return p==0 || sqlite3GlobalConfig.mutex.xMutexNotheld(p);
-+SQLITE_PRIVATE void sqlite3MemSetDefault(void){
-+ static const sqlite3_mem_methods defaultMethods = {
-+ sqlite3MemMalloc,
-+ sqlite3MemFree,
-+ sqlite3MemRealloc,
-+ sqlite3MemSize,
-+ sqlite3MemRoundup,
-+ sqlite3MemInit,
-+ sqlite3MemShutdown,
-+ 0
-+ };
-+ sqlite3_config(SQLITE_CONFIG_MALLOC, &defaultMethods);
- }
--#endif
-
--#endif /* !defined(SQLITE_MUTEX_OMIT) */
-+#endif /* SQLITE_ZERO_MALLOC */
-
--/************** End of mutex.c ***********************************************/
--/************** Begin file mutex_noop.c **************************************/
-+/************** End of mem0.c ************************************************/
-+/************** Begin file mem1.c ********************************************/
- /*
--** 2008 October 07
-+** 2007 August 14
- **
- ** The author disclaims copyright to this source code. In place of
- ** a legal notice, here is a blessing:
-@@ -17870,205 +18667,278 @@
- ** May you share freely, never taking more than you give.
- **
- *************************************************************************
--** This file contains the C functions that implement mutexes.
- **
--** This implementation in this file does not provide any mutual
--** exclusion and is thus suitable for use only in applications
--** that use SQLite in a single thread. The routines defined
--** here are place-holders. Applications can substitute working
--** mutex routines at start-time using the
-+** This file contains low-level memory allocation drivers for when
-+** SQLite will use the standard C-library malloc/realloc/free interface
-+** to obtain the memory it needs.
- **
--** sqlite3_config(SQLITE_CONFIG_MUTEX,...)
-+** This file contains implementations of the low-level memory allocation
-+** routines specified in the sqlite3_mem_methods object. The content of
-+** this file is only used if SQLITE_SYSTEM_MALLOC is defined. The
-+** SQLITE_SYSTEM_MALLOC macro is defined automatically if neither the
-+** SQLITE_MEMDEBUG nor the SQLITE_WIN32_MALLOC macros are defined. The
-+** default configuration is to use memory allocation routines in this
-+** file.
- **
--** interface.
-+** C-preprocessor macro summary:
- **
--** If compiled with SQLITE_DEBUG, then additional logic is inserted
--** that does error checking on mutexes to make sure they are being
--** called correctly.
-+** HAVE_MALLOC_USABLE_SIZE The configure script sets this symbol if
-+** the malloc_usable_size() interface exists
-+** on the target platform. Or, this symbol
-+** can be set manually, if desired.
-+** If an equivalent interface exists by
-+** a different name, using a separate -D
-+** option to rename it.
-+**
-+** SQLITE_WITHOUT_ZONEMALLOC Some older macs lack support for the zone
-+** memory allocator. Set this symbol to enable
-+** building on older macs.
-+**
-+** SQLITE_WITHOUT_MSIZE Set this symbol to disable the use of
-+** _msize() on windows systems. This might
-+** be necessary when compiling for Delphi,
-+** for example.
- */
-
--#ifndef SQLITE_MUTEX_OMIT
-+/*
-+** This version of the memory allocator is the default. It is
-+** used when no other memory allocator is specified using compile-time
-+** macros.
-+*/
-+#ifdef SQLITE_SYSTEM_MALLOC
-
--#ifndef SQLITE_DEBUG
- /*
--** Stub routines for all mutex methods.
--**
--** This routines provide no mutual exclusion or error checking.
-+** The MSVCRT has malloc_usable_size() but it is called _msize().
-+** The use of _msize() is automatic, but can be disabled by compiling
-+** with -DSQLITE_WITHOUT_MSIZE
- */
--static int noopMutexInit(void){ return SQLITE_OK; }
--static int noopMutexEnd(void){ return SQLITE_OK; }
--static sqlite3_mutex *noopMutexAlloc(int id){
-- UNUSED_PARAMETER(id);
-- return (sqlite3_mutex*)8;
--}
--static void noopMutexFree(sqlite3_mutex *p){ UNUSED_PARAMETER(p); return; }
--static void noopMutexEnter(sqlite3_mutex *p){ UNUSED_PARAMETER(p); return; }
--static int noopMutexTry(sqlite3_mutex *p){
-- UNUSED_PARAMETER(p);
-- return SQLITE_OK;
--}
--static void noopMutexLeave(sqlite3_mutex *p){ UNUSED_PARAMETER(p); return; }
-+#if defined(_MSC_VER) && !defined(SQLITE_WITHOUT_MSIZE)
-+# define SQLITE_MALLOCSIZE _msize
-+#endif
-
--SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3NoopMutex(void){
-- static const sqlite3_mutex_methods sMutex = {
-- noopMutexInit,
-- noopMutexEnd,
-- noopMutexAlloc,
-- noopMutexFree,
-- noopMutexEnter,
-- noopMutexTry,
-- noopMutexLeave,
-+#if defined(__APPLE__) && !defined(SQLITE_WITHOUT_ZONEMALLOC)
-
-- 0,
-- 0,
-- };
-+/*
-+** Use the zone allocator available on apple products unless the
-+** SQLITE_WITHOUT_ZONEMALLOC symbol is defined.
-+*/
-+#include <sys/sysctl.h>
-+#include <malloc/malloc.h>
-+#include <libkern/OSAtomic.h>
-+static malloc_zone_t* _sqliteZone_;
-+#define SQLITE_MALLOC(x) malloc_zone_malloc(_sqliteZone_, (x))
-+#define SQLITE_FREE(x) malloc_zone_free(_sqliteZone_, (x));
-+#define SQLITE_REALLOC(x,y) malloc_zone_realloc(_sqliteZone_, (x), (y))
-+#define SQLITE_MALLOCSIZE(x) \
-+ (_sqliteZone_ ? _sqliteZone_->size(_sqliteZone_,x) : malloc_size(x))
-
-- return &sMutex;
--}
--#endif /* !SQLITE_DEBUG */
-+#else /* if not __APPLE__ */
-
--#ifdef SQLITE_DEBUG
- /*
--** In this implementation, error checking is provided for testing
--** and debugging purposes. The mutexes still do not provide any
--** mutual exclusion.
-+** Use standard C library malloc and free on non-Apple systems.
-+** Also used by Apple systems if SQLITE_WITHOUT_ZONEMALLOC is defined.
- */
-+#define SQLITE_MALLOC(x) malloc(x)
-+#define SQLITE_FREE(x) free(x)
-+#define SQLITE_REALLOC(x,y) realloc((x),(y))
-+
-+#if (defined(_MSC_VER) && !defined(SQLITE_WITHOUT_MSIZE)) \
-+ || (defined(HAVE_MALLOC_H) && defined(HAVE_MALLOC_USABLE_SIZE))
-+# include <malloc.h> /* Needed for malloc_usable_size on linux */
-+#endif
-+#ifdef HAVE_MALLOC_USABLE_SIZE
-+# ifndef SQLITE_MALLOCSIZE
-+# define SQLITE_MALLOCSIZE(x) malloc_usable_size(x)
-+# endif
-+#else
-+# undef SQLITE_MALLOCSIZE
-+#endif
-+
-+#endif /* __APPLE__ or not __APPLE__ */
-
- /*
--** The mutex object
-+** Like malloc(), but remember the size of the allocation
-+** so that we can find it later using sqlite3MemSize().
-+**
-+** For this low-level routine, we are guaranteed that nByte>0 because
-+** cases of nByte<=0 will be intercepted and dealt with by higher level
-+** routines.
- */
--typedef struct sqlite3_debug_mutex {
-- int id; /* The mutex type */
-- int cnt; /* Number of entries without a matching leave */
--} sqlite3_debug_mutex;
-+static void *sqlite3MemMalloc(int nByte){
-+#ifdef SQLITE_MALLOCSIZE
-+ void *p = SQLITE_MALLOC( nByte );
-+ if( p==0 ){
-+ testcase( sqlite3GlobalConfig.xLog!=0 );
-+ sqlite3_log(SQLITE_NOMEM, "failed to allocate %u bytes of memory", nByte);
-+ }
-+ return p;
-+#else
-+ sqlite3_int64 *p;
-+ assert( nByte>0 );
-+ nByte = ROUND8(nByte);
-+ p = SQLITE_MALLOC( nByte+8 );
-+ if( p ){
-+ p[0] = nByte;
-+ p++;
-+ }else{
-+ testcase( sqlite3GlobalConfig.xLog!=0 );
-+ sqlite3_log(SQLITE_NOMEM, "failed to allocate %u bytes of memory", nByte);
-+ }
-+ return (void *)p;
-+#endif
-+}
-
- /*
--** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are
--** intended for use inside assert() statements.
-+** Like free() but works for allocations obtained from sqlite3MemMalloc()
-+** or sqlite3MemRealloc().
-+**
-+** For this low-level routine, we already know that pPrior!=0 since
-+** cases where pPrior==0 will have been intecepted and dealt with
-+** by higher-level routines.
- */
--static int debugMutexHeld(sqlite3_mutex *pX){
-- sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX;
-- return p==0 || p->cnt>0;
--}
--static int debugMutexNotheld(sqlite3_mutex *pX){
-- sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX;
-- return p==0 || p->cnt==0;
-+static void sqlite3MemFree(void *pPrior){
-+#ifdef SQLITE_MALLOCSIZE
-+ SQLITE_FREE(pPrior);
-+#else
-+ sqlite3_int64 *p = (sqlite3_int64*)pPrior;
-+ assert( pPrior!=0 );
-+ p--;
-+ SQLITE_FREE(p);
-+#endif
- }
-
- /*
--** Initialize and deinitialize the mutex subsystem.
-+** Report the allocated size of a prior return from xMalloc()
-+** or xRealloc().
- */
--static int debugMutexInit(void){ return SQLITE_OK; }
--static int debugMutexEnd(void){ return SQLITE_OK; }
-+static int sqlite3MemSize(void *pPrior){
-+#ifdef SQLITE_MALLOCSIZE
-+ return pPrior ? (int)SQLITE_MALLOCSIZE(pPrior) : 0;
-+#else
-+ sqlite3_int64 *p;
-+ if( pPrior==0 ) return 0;
-+ p = (sqlite3_int64*)pPrior;
-+ p--;
-+ return (int)p[0];
-+#endif
-+}
-
- /*
--** The sqlite3_mutex_alloc() routine allocates a new
--** mutex and returns a pointer to it. If it returns NULL
--** that means that a mutex could not be allocated.
-+** Like realloc(). Resize an allocation previously obtained from
-+** sqlite3MemMalloc().
-+**
-+** For this low-level interface, we know that pPrior!=0. Cases where
-+** pPrior==0 while have been intercepted by higher-level routine and
-+** redirected to xMalloc. Similarly, we know that nByte>0 becauses
-+** cases where nByte<=0 will have been intercepted by higher-level
-+** routines and redirected to xFree.
- */
--static sqlite3_mutex *debugMutexAlloc(int id){
-- static sqlite3_debug_mutex aStatic[6];
-- sqlite3_debug_mutex *pNew = 0;
-- switch( id ){
-- case SQLITE_MUTEX_FAST:
-- case SQLITE_MUTEX_RECURSIVE: {
-- pNew = sqlite3Malloc(sizeof(*pNew));
-- if( pNew ){
-- pNew->id = id;
-- pNew->cnt = 0;
-- }
-- break;
-- }
-- default: {
-- assert( id-2 >= 0 );
-- assert( id-2 < (int)(sizeof(aStatic)/sizeof(aStatic[0])) );
-- pNew = &aStatic[id-2];
-- pNew->id = id;
-- break;
-- }
-+static void *sqlite3MemRealloc(void *pPrior, int nByte){
-+#ifdef SQLITE_MALLOCSIZE
-+ void *p = SQLITE_REALLOC(pPrior, nByte);
-+ if( p==0 ){
-+ testcase( sqlite3GlobalConfig.xLog!=0 );
-+ sqlite3_log(SQLITE_NOMEM,
-+ "failed memory resize %u to %u bytes",
-+ SQLITE_MALLOCSIZE(pPrior), nByte);
- }
-- return (sqlite3_mutex*)pNew;
-+ return p;
-+#else
-+ sqlite3_int64 *p = (sqlite3_int64*)pPrior;
-+ assert( pPrior!=0 && nByte>0 );
-+ assert( nByte==ROUND8(nByte) ); /* EV: R-46199-30249 */
-+ p--;
-+ p = SQLITE_REALLOC(p, nByte+8 );
-+ if( p ){
-+ p[0] = nByte;
-+ p++;
-+ }else{
-+ testcase( sqlite3GlobalConfig.xLog!=0 );
-+ sqlite3_log(SQLITE_NOMEM,
-+ "failed memory resize %u to %u bytes",
-+ sqlite3MemSize(pPrior), nByte);
-+ }
-+ return (void*)p;
-+#endif
- }
-
- /*
--** This routine deallocates a previously allocated mutex.
-+** Round up a request size to the next valid allocation size.
- */
--static void debugMutexFree(sqlite3_mutex *pX){
-- sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX;
-- assert( p->cnt==0 );
-- assert( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE );
-- sqlite3_free(p);
-+static int sqlite3MemRoundup(int n){
-+ return ROUND8(n);
- }
-
- /*
--** The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt
--** to enter a mutex. If another thread is already within the mutex,
--** sqlite3_mutex_enter() will block and sqlite3_mutex_try() will return
--** SQLITE_BUSY. The sqlite3_mutex_try() interface returns SQLITE_OK
--** upon successful entry. Mutexes created using SQLITE_MUTEX_RECURSIVE can
--** be entered multiple times by the same thread. In such cases the,
--** mutex must be exited an equal number of times before another thread
--** can enter. If the same thread tries to enter any other kind of mutex
--** more than once, the behavior is undefined.
-+** Initialize this module.
- */
--static void debugMutexEnter(sqlite3_mutex *pX){
-- sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX;
-- assert( p->id==SQLITE_MUTEX_RECURSIVE || debugMutexNotheld(pX) );
-- p->cnt++;
--}
--static int debugMutexTry(sqlite3_mutex *pX){
-- sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX;
-- assert( p->id==SQLITE_MUTEX_RECURSIVE || debugMutexNotheld(pX) );
-- p->cnt++;
-+static int sqlite3MemInit(void *NotUsed){
-+#if defined(__APPLE__) && !defined(SQLITE_WITHOUT_ZONEMALLOC)
-+ int cpuCount;
-+ size_t len;
-+ if( _sqliteZone_ ){
-+ return SQLITE_OK;
-+ }
-+ len = sizeof(cpuCount);
-+ /* One usually wants to use hw.acctivecpu for MT decisions, but not here */
-+ sysctlbyname("hw.ncpu", &cpuCount, &len, NULL, 0);
-+ if( cpuCount>1 ){
-+ /* defer MT decisions to system malloc */
-+ _sqliteZone_ = malloc_default_zone();
-+ }else{
-+ /* only 1 core, use our own zone to contention over global locks,
-+ ** e.g. we have our own dedicated locks */
-+ bool success;
-+ malloc_zone_t* newzone = malloc_create_zone(4096, 0);
-+ malloc_set_zone_name(newzone, "Sqlite_Heap");
-+ do{
-+ success = OSAtomicCompareAndSwapPtrBarrier(NULL, newzone,
-+ (void * volatile *)&_sqliteZone_);
-+ }while(!_sqliteZone_);
-+ if( !success ){
-+ /* somebody registered a zone first */
-+ malloc_destroy_zone(newzone);
-+ }
-+ }
-+#endif
-+ UNUSED_PARAMETER(NotUsed);
- return SQLITE_OK;
- }
-
- /*
--** The sqlite3_mutex_leave() routine exits a mutex that was
--** previously entered by the same thread. The behavior
--** is undefined if the mutex is not currently entered or
--** is not currently allocated. SQLite will never do either.
-+** Deinitialize this module.
- */
--static void debugMutexLeave(sqlite3_mutex *pX){
-- sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX;
-- assert( debugMutexHeld(pX) );
-- p->cnt--;
-- assert( p->id==SQLITE_MUTEX_RECURSIVE || debugMutexNotheld(pX) );
--}
--
--SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3NoopMutex(void){
-- static const sqlite3_mutex_methods sMutex = {
-- debugMutexInit,
-- debugMutexEnd,
-- debugMutexAlloc,
-- debugMutexFree,
-- debugMutexEnter,
-- debugMutexTry,
-- debugMutexLeave,
--
-- debugMutexHeld,
-- debugMutexNotheld
-- };
--
-- return &sMutex;
-+static void sqlite3MemShutdown(void *NotUsed){
-+ UNUSED_PARAMETER(NotUsed);
-+ return;
- }
--#endif /* SQLITE_DEBUG */
-
- /*
--** If compiled with SQLITE_MUTEX_NOOP, then the no-op mutex implementation
--** is used regardless of the run-time threadsafety setting.
-+** This routine is the only routine in this file with external linkage.
-+**
-+** Populate the low-level memory allocation function pointers in
-+** sqlite3GlobalConfig.m with pointers to the routines in this file.
- */
--#ifdef SQLITE_MUTEX_NOOP
--SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3DefaultMutex(void){
-- return sqlite3NoopMutex();
-+SQLITE_PRIVATE void sqlite3MemSetDefault(void){
-+ static const sqlite3_mem_methods defaultMethods = {
-+ sqlite3MemMalloc,
-+ sqlite3MemFree,
-+ sqlite3MemRealloc,
-+ sqlite3MemSize,
-+ sqlite3MemRoundup,
-+ sqlite3MemInit,
-+ sqlite3MemShutdown,
-+ 0
-+ };
-+ sqlite3_config(SQLITE_CONFIG_MALLOC, &defaultMethods);
- }
--#endif /* defined(SQLITE_MUTEX_NOOP) */
--#endif /* !defined(SQLITE_MUTEX_OMIT) */
-
--/************** End of mutex_noop.c ******************************************/
--/************** Begin file mutex_unix.c **************************************/
-+#endif /* SQLITE_SYSTEM_MALLOC */
-+
-+/************** End of mem1.c ************************************************/
-+/************** Begin file mem2.c ********************************************/
- /*
--** 2007 August 28
-+** 2007 August 15
- **
- ** The author disclaims copyright to this source code. In place of
- ** a legal notice, here is a blessing:
-@@ -18078,694 +18948,527 @@
- ** May you share freely, never taking more than you give.
- **
- *************************************************************************
--** This file contains the C functions that implement mutexes for pthreads
-+**
-+** This file contains low-level memory allocation drivers for when
-+** SQLite will use the standard C-library malloc/realloc/free interface
-+** to obtain the memory it needs while adding lots of additional debugging
-+** information to each allocation in order to help detect and fix memory
-+** leaks and memory usage errors.
-+**
-+** This file contains implementations of the low-level memory allocation
-+** routines specified in the sqlite3_mem_methods object.
- */
-
- /*
--** The code in this file is only used if we are compiling threadsafe
--** under unix with pthreads.
--**
--** Note that this implementation requires a version of pthreads that
--** supports recursive mutexes.
-+** This version of the memory allocator is used only if the
-+** SQLITE_MEMDEBUG macro is defined
- */
--#ifdef SQLITE_MUTEX_PTHREADS
--
--#include <pthread.h>
-+#ifdef SQLITE_MEMDEBUG
-
- /*
--** The sqlite3_mutex.id, sqlite3_mutex.nRef, and sqlite3_mutex.owner fields
--** are necessary under two condidtions: (1) Debug builds and (2) using
--** home-grown mutexes. Encapsulate these conditions into a single #define.
-+** The backtrace functionality is only available with GLIBC
- */
--#if defined(SQLITE_DEBUG) || defined(SQLITE_HOMEGROWN_RECURSIVE_MUTEX)
--# define SQLITE_MUTEX_NREF 1
--#else
--# define SQLITE_MUTEX_NREF 0
--#endif
--
--/*
--** Each recursive mutex is an instance of the following structure.
--*/
--struct sqlite3_mutex {
-- pthread_mutex_t mutex; /* Mutex controlling the lock */
--#if SQLITE_MUTEX_NREF
-- int id; /* Mutex type */
-- volatile int nRef; /* Number of entrances */
-- volatile pthread_t owner; /* Thread that is within this mutex */
-- int trace; /* True to trace changes */
--#endif
--};
--#if SQLITE_MUTEX_NREF
--#define SQLITE3_MUTEX_INITIALIZER { PTHREAD_MUTEX_INITIALIZER, 0, 0, (pthread_t)0, 0 }
-+#ifdef __GLIBC__
-+ extern int backtrace(void**,int);
-+ extern void backtrace_symbols_fd(void*const*,int,int);
- #else
--#define SQLITE3_MUTEX_INITIALIZER { PTHREAD_MUTEX_INITIALIZER }
-+# define backtrace(A,B) 1
-+# define backtrace_symbols_fd(A,B,C)
- #endif
-+/* #include <stdio.h> */
-
- /*
--** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are
--** intended for use only inside assert() statements. On some platforms,
--** there might be race conditions that can cause these routines to
--** deliver incorrect results. In particular, if pthread_equal() is
--** not an atomic operation, then these routines might delivery
--** incorrect results. On most platforms, pthread_equal() is a
--** comparison of two integers and is therefore atomic. But we are
--** told that HPUX is not such a platform. If so, then these routines
--** will not always work correctly on HPUX.
-+** Each memory allocation looks like this:
- **
--** On those platforms where pthread_equal() is not atomic, SQLite
--** should be compiled without -DSQLITE_DEBUG and with -DNDEBUG to
--** make sure no assert() statements are evaluated and hence these
--** routines are never called.
--*/
--#if !defined(NDEBUG) || defined(SQLITE_DEBUG)
--static int pthreadMutexHeld(sqlite3_mutex *p){
-- return (p->nRef!=0 && pthread_equal(p->owner, pthread_self()));
--}
--static int pthreadMutexNotheld(sqlite3_mutex *p){
-- return p->nRef==0 || pthread_equal(p->owner, pthread_self())==0;
--}
--#endif
--
--/*
--** Initialize and deinitialize the mutex subsystem.
-+** ------------------------------------------------------------------------
-+** | Title | backtrace pointers | MemBlockHdr | allocation | EndGuard |
-+** ------------------------------------------------------------------------
-+**
-+** The application code sees only a pointer to the allocation. We have
-+** to back up from the allocation pointer to find the MemBlockHdr. The
-+** MemBlockHdr tells us the size of the allocation and the number of
-+** backtrace pointers. There is also a guard word at the end of the
-+** MemBlockHdr.
- */
--static int pthreadMutexInit(void){ return SQLITE_OK; }
--static int pthreadMutexEnd(void){ return SQLITE_OK; }
-+struct MemBlockHdr {
-+ i64 iSize; /* Size of this allocation */
-+ struct MemBlockHdr *pNext, *pPrev; /* Linked list of all unfreed memory */
-+ char nBacktrace; /* Number of backtraces on this alloc */
-+ char nBacktraceSlots; /* Available backtrace slots */
-+ u8 nTitle; /* Bytes of title; includes '\0' */
-+ u8 eType; /* Allocation type code */
-+ int iForeGuard; /* Guard word for sanity */
-+};
-
- /*
--** The sqlite3_mutex_alloc() routine allocates a new
--** mutex and returns a pointer to it. If it returns NULL
--** that means that a mutex could not be allocated. SQLite
--** will unwind its stack and return an error. The argument
--** to sqlite3_mutex_alloc() is one of these integer constants:
--**
--** <ul>
--** <li> SQLITE_MUTEX_FAST
--** <li> SQLITE_MUTEX_RECURSIVE
--** <li> SQLITE_MUTEX_STATIC_MASTER
--** <li> SQLITE_MUTEX_STATIC_MEM
--** <li> SQLITE_MUTEX_STATIC_MEM2
--** <li> SQLITE_MUTEX_STATIC_PRNG
--** <li> SQLITE_MUTEX_STATIC_LRU
--** <li> SQLITE_MUTEX_STATIC_PMEM
--** </ul>
--**
--** The first two constants cause sqlite3_mutex_alloc() to create
--** a new mutex. The new mutex is recursive when SQLITE_MUTEX_RECURSIVE
--** is used but not necessarily so when SQLITE_MUTEX_FAST is used.
--** The mutex implementation does not need to make a distinction
--** between SQLITE_MUTEX_RECURSIVE and SQLITE_MUTEX_FAST if it does
--** not want to. But SQLite will only request a recursive mutex in
--** cases where it really needs one. If a faster non-recursive mutex
--** implementation is available on the host platform, the mutex subsystem
--** might return such a mutex in response to SQLITE_MUTEX_FAST.
--**
--** The other allowed parameters to sqlite3_mutex_alloc() each return
--** a pointer to a static preexisting mutex. Six static mutexes are
--** used by the current version of SQLite. Future versions of SQLite
--** may add additional static mutexes. Static mutexes are for internal
--** use by SQLite only. Applications that use SQLite mutexes should
--** use only the dynamic mutexes returned by SQLITE_MUTEX_FAST or
--** SQLITE_MUTEX_RECURSIVE.
--**
--** Note that if one of the dynamic mutex parameters (SQLITE_MUTEX_FAST
--** or SQLITE_MUTEX_RECURSIVE) is used then sqlite3_mutex_alloc()
--** returns a different mutex on every call. But for the static
--** mutex types, the same mutex is returned on every call that has
--** the same type number.
-+** Guard words
- */
--static sqlite3_mutex *pthreadMutexAlloc(int iType){
-- static sqlite3_mutex staticMutexes[] = {
-- SQLITE3_MUTEX_INITIALIZER,
-- SQLITE3_MUTEX_INITIALIZER,
-- SQLITE3_MUTEX_INITIALIZER,
-- SQLITE3_MUTEX_INITIALIZER,
-- SQLITE3_MUTEX_INITIALIZER,
-- SQLITE3_MUTEX_INITIALIZER
-- };
-- sqlite3_mutex *p;
-- switch( iType ){
-- case SQLITE_MUTEX_RECURSIVE: {
-- p = sqlite3MallocZero( sizeof(*p) );
-- if( p ){
--#ifdef SQLITE_HOMEGROWN_RECURSIVE_MUTEX
-- /* If recursive mutexes are not available, we will have to
-- ** build our own. See below. */
-- pthread_mutex_init(&p->mutex, 0);
--#else
-- /* Use a recursive mutex if it is available */
-- pthread_mutexattr_t recursiveAttr;
-- pthread_mutexattr_init(&recursiveAttr);
-- pthread_mutexattr_settype(&recursiveAttr, PTHREAD_MUTEX_RECURSIVE);
-- pthread_mutex_init(&p->mutex, &recursiveAttr);
-- pthread_mutexattr_destroy(&recursiveAttr);
--#endif
--#if SQLITE_MUTEX_NREF
-- p->id = iType;
--#endif
-- }
-- break;
-- }
-- case SQLITE_MUTEX_FAST: {
-- p = sqlite3MallocZero( sizeof(*p) );
-- if( p ){
--#if SQLITE_MUTEX_NREF
-- p->id = iType;
--#endif
-- pthread_mutex_init(&p->mutex, 0);
-- }
-- break;
-- }
-- default: {
-- assert( iType-2 >= 0 );
-- assert( iType-2 < ArraySize(staticMutexes) );
-- p = &staticMutexes[iType-2];
--#if SQLITE_MUTEX_NREF
-- p->id = iType;
--#endif
-- break;
-- }
-- }
-- return p;
--}
--
-+#define FOREGUARD 0x80F5E153
-+#define REARGUARD 0xE4676B53
-
- /*
--** This routine deallocates a previously
--** allocated mutex. SQLite is careful to deallocate every
--** mutex that it allocates.
-+** Number of malloc size increments to track.
- */
--static void pthreadMutexFree(sqlite3_mutex *p){
-- assert( p->nRef==0 );
-- assert( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE );
-- pthread_mutex_destroy(&p->mutex);
-- sqlite3_free(p);
--}
-+#define NCSIZE 1000
-
- /*
--** The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt
--** to enter a mutex. If another thread is already within the mutex,
--** sqlite3_mutex_enter() will block and sqlite3_mutex_try() will return
--** SQLITE_BUSY. The sqlite3_mutex_try() interface returns SQLITE_OK
--** upon successful entry. Mutexes created using SQLITE_MUTEX_RECURSIVE can
--** be entered multiple times by the same thread. In such cases the,
--** mutex must be exited an equal number of times before another thread
--** can enter. If the same thread tries to enter any other kind of mutex
--** more than once, the behavior is undefined.
-+** All of the static variables used by this module are collected
-+** into a single structure named "mem". This is to keep the
-+** static variables organized and to reduce namespace pollution
-+** when this module is combined with other in the amalgamation.
- */
--static void pthreadMutexEnter(sqlite3_mutex *p){
-- assert( p->id==SQLITE_MUTEX_RECURSIVE || pthreadMutexNotheld(p) );
-+static struct {
-+
-+ /*
-+ ** Mutex to control access to the memory allocation subsystem.
-+ */
-+ sqlite3_mutex *mutex;
-
--#ifdef SQLITE_HOMEGROWN_RECURSIVE_MUTEX
-- /* If recursive mutexes are not available, then we have to grow
-- ** our own. This implementation assumes that pthread_equal()
-- ** is atomic - that it cannot be deceived into thinking self
-- ** and p->owner are equal if p->owner changes between two values
-- ** that are not equal to self while the comparison is taking place.
-- ** This implementation also assumes a coherent cache - that
-- ** separate processes cannot read different values from the same
-- ** address at the same time. If either of these two conditions
-- ** are not met, then the mutexes will fail and problems will result.
-+ /*
-+ ** Head and tail of a linked list of all outstanding allocations
- */
-- {
-- pthread_t self = pthread_self();
-- if( p->nRef>0 && pthread_equal(p->owner, self) ){
-- p->nRef++;
-- }else{
-- pthread_mutex_lock(&p->mutex);
-- assert( p->nRef==0 );
-- p->owner = self;
-- p->nRef = 1;
-- }
-- }
--#else
-- /* Use the built-in recursive mutexes if they are available.
-+ struct MemBlockHdr *pFirst;
-+ struct MemBlockHdr *pLast;
-+
-+ /*
-+ ** The number of levels of backtrace to save in new allocations.
- */
-- pthread_mutex_lock(&p->mutex);
--#if SQLITE_MUTEX_NREF
-- assert( p->nRef>0 || p->owner==0 );
-- p->owner = pthread_self();
-- p->nRef++;
--#endif
--#endif
-+ int nBacktrace;
-+ void (*xBacktrace)(int, int, void **);
-
--#ifdef SQLITE_DEBUG
-- if( p->trace ){
-- printf("enter mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef);
-- }
--#endif
--}
--static int pthreadMutexTry(sqlite3_mutex *p){
-- int rc;
-- assert( p->id==SQLITE_MUTEX_RECURSIVE || pthreadMutexNotheld(p) );
-+ /*
-+ ** Title text to insert in front of each block
-+ */
-+ int nTitle; /* Bytes of zTitle to save. Includes '\0' and padding */
-+ char zTitle[100]; /* The title text */
-
--#ifdef SQLITE_HOMEGROWN_RECURSIVE_MUTEX
-- /* If recursive mutexes are not available, then we have to grow
-- ** our own. This implementation assumes that pthread_equal()
-- ** is atomic - that it cannot be deceived into thinking self
-- ** and p->owner are equal if p->owner changes between two values
-- ** that are not equal to self while the comparison is taking place.
-- ** This implementation also assumes a coherent cache - that
-- ** separate processes cannot read different values from the same
-- ** address at the same time. If either of these two conditions
-- ** are not met, then the mutexes will fail and problems will result.
-+ /*
-+ ** sqlite3MallocDisallow() increments the following counter.
-+ ** sqlite3MallocAllow() decrements it.
- */
-- {
-- pthread_t self = pthread_self();
-- if( p->nRef>0 && pthread_equal(p->owner, self) ){
-- p->nRef++;
-- rc = SQLITE_OK;
-- }else if( pthread_mutex_trylock(&p->mutex)==0 ){
-- assert( p->nRef==0 );
-- p->owner = self;
-- p->nRef = 1;
-- rc = SQLITE_OK;
-- }else{
-- rc = SQLITE_BUSY;
-- }
-- }
--#else
-- /* Use the built-in recursive mutexes if they are available.
-+ int disallow; /* Do not allow memory allocation */
-+
-+ /*
-+ ** Gather statistics on the sizes of memory allocations.
-+ ** nAlloc[i] is the number of allocation attempts of i*8
-+ ** bytes. i==NCSIZE is the number of allocation attempts for
-+ ** sizes more than NCSIZE*8 bytes.
- */
-- if( pthread_mutex_trylock(&p->mutex)==0 ){
--#if SQLITE_MUTEX_NREF
-- p->owner = pthread_self();
-- p->nRef++;
--#endif
-- rc = SQLITE_OK;
-- }else{
-- rc = SQLITE_BUSY;
-- }
--#endif
-+ int nAlloc[NCSIZE]; /* Total number of allocations */
-+ int nCurrent[NCSIZE]; /* Current number of allocations */
-+ int mxCurrent[NCSIZE]; /* Highwater mark for nCurrent */
-+
-+} mem;
-
--#ifdef SQLITE_DEBUG
-- if( rc==SQLITE_OK && p->trace ){
-- printf("enter mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef);
-- }
--#endif
-- return rc;
--}
-
- /*
--** The sqlite3_mutex_leave() routine exits a mutex that was
--** previously entered by the same thread. The behavior
--** is undefined if the mutex is not currently entered or
--** is not currently allocated. SQLite will never do either.
-+** Adjust memory usage statistics
- */
--static void pthreadMutexLeave(sqlite3_mutex *p){
-- assert( pthreadMutexHeld(p) );
--#if SQLITE_MUTEX_NREF
-- p->nRef--;
-- if( p->nRef==0 ) p->owner = 0;
--#endif
-- assert( p->nRef==0 || p->id==SQLITE_MUTEX_RECURSIVE );
--
--#ifdef SQLITE_HOMEGROWN_RECURSIVE_MUTEX
-- if( p->nRef==0 ){
-- pthread_mutex_unlock(&p->mutex);
-+static void adjustStats(int iSize, int increment){
-+ int i = ROUND8(iSize)/8;
-+ if( i>NCSIZE-1 ){
-+ i = NCSIZE - 1;
- }
--#else
-- pthread_mutex_unlock(&p->mutex);
--#endif
--
--#ifdef SQLITE_DEBUG
-- if( p->trace ){
-- printf("leave mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef);
-+ if( increment>0 ){
-+ mem.nAlloc[i]++;
-+ mem.nCurrent[i]++;
-+ if( mem.nCurrent[i]>mem.mxCurrent[i] ){
-+ mem.mxCurrent[i] = mem.nCurrent[i];
-+ }
-+ }else{
-+ mem.nCurrent[i]--;
-+ assert( mem.nCurrent[i]>=0 );
- }
--#endif
--}
--
--SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3DefaultMutex(void){
-- static const sqlite3_mutex_methods sMutex = {
-- pthreadMutexInit,
-- pthreadMutexEnd,
-- pthreadMutexAlloc,
-- pthreadMutexFree,
-- pthreadMutexEnter,
-- pthreadMutexTry,
-- pthreadMutexLeave,
--#ifdef SQLITE_DEBUG
-- pthreadMutexHeld,
-- pthreadMutexNotheld
--#else
-- 0,
-- 0
--#endif
-- };
--
-- return &sMutex;
- }
-
--#endif /* SQLITE_MUTEX_PTHREADS */
--
--/************** End of mutex_unix.c ******************************************/
--/************** Begin file mutex_w32.c ***************************************/
- /*
--** 2007 August 14
--**
--** The author disclaims copyright to this source code. In place of
--** a legal notice, here is a blessing:
--**
--** May you do good and not evil.
--** May you find forgiveness for yourself and forgive others.
--** May you share freely, never taking more than you give.
-+** Given an allocation, find the MemBlockHdr for that allocation.
- **
--*************************************************************************
--** This file contains the C functions that implement mutexes for win32
-+** This routine checks the guards at either end of the allocation and
-+** if they are incorrect it asserts.
- */
-+static struct MemBlockHdr *sqlite3MemsysGetHeader(void *pAllocation){
-+ struct MemBlockHdr *p;
-+ int *pInt;
-+ u8 *pU8;
-+ int nReserve;
-
--/*
--** The code in this file is only used if we are compiling multithreaded
--** on a win32 system.
--*/
--#ifdef SQLITE_MUTEX_W32
-+ p = (struct MemBlockHdr*)pAllocation;
-+ p--;
-+ assert( p->iForeGuard==(int)FOREGUARD );
-+ nReserve = ROUND8(p->iSize);
-+ pInt = (int*)pAllocation;
-+ pU8 = (u8*)pAllocation;
-+ assert( pInt[nReserve/sizeof(int)]==(int)REARGUARD );
-+ /* This checks any of the "extra" bytes allocated due
-+ ** to rounding up to an 8 byte boundary to ensure
-+ ** they haven't been overwritten.
-+ */
-+ while( nReserve-- > p->iSize ) assert( pU8[nReserve]==0x65 );
-+ return p;
-+}
-
- /*
--** Each recursive mutex is an instance of the following structure.
-+** Return the number of bytes currently allocated at address p.
- */
--struct sqlite3_mutex {
-- CRITICAL_SECTION mutex; /* Mutex controlling the lock */
-- int id; /* Mutex type */
--#ifdef SQLITE_DEBUG
-- volatile int nRef; /* Number of enterances */
-- volatile DWORD owner; /* Thread holding this mutex */
-- int trace; /* True to trace changes */
--#endif
--};
--#define SQLITE_W32_MUTEX_INITIALIZER { 0 }
--#ifdef SQLITE_DEBUG
--#define SQLITE3_MUTEX_INITIALIZER { SQLITE_W32_MUTEX_INITIALIZER, 0, 0L, (DWORD)0, 0 }
--#else
--#define SQLITE3_MUTEX_INITIALIZER { SQLITE_W32_MUTEX_INITIALIZER, 0 }
--#endif
-+static int sqlite3MemSize(void *p){
-+ struct MemBlockHdr *pHdr;
-+ if( !p ){
-+ return 0;
-+ }
-+ pHdr = sqlite3MemsysGetHeader(p);
-+ return pHdr->iSize;
-+}
-
- /*
--** Return true (non-zero) if we are running under WinNT, Win2K, WinXP,
--** or WinCE. Return false (zero) for Win95, Win98, or WinME.
--**
--** Here is an interesting observation: Win95, Win98, and WinME lack
--** the LockFileEx() API. But we can still statically link against that
--** API as long as we don't call it win running Win95/98/ME. A call to
--** this routine is used to determine if the host is Win95/98/ME or
--** WinNT/2K/XP so that we will know whether or not we can safely call
--** the LockFileEx() API.
--**
--** mutexIsNT() is only used for the TryEnterCriticalSection() API call,
--** which is only available if your application was compiled with
--** _WIN32_WINNT defined to a value >= 0x0400. Currently, the only
--** call to TryEnterCriticalSection() is #ifdef'ed out, so #ifdef
--** this out as well.
-+** Initialize the memory allocation subsystem.
- */
--#if 0
--#if SQLITE_OS_WINCE || SQLITE_OS_WINRT
--# define mutexIsNT() (1)
--#else
-- static int mutexIsNT(void){
-- static int osType = 0;
-- if( osType==0 ){
-- OSVERSIONINFO sInfo;
-- sInfo.dwOSVersionInfoSize = sizeof(sInfo);
-- GetVersionEx(&sInfo);
-- osType = sInfo.dwPlatformId==VER_PLATFORM_WIN32_NT ? 2 : 1;
-- }
-- return osType==2;
-+static int sqlite3MemInit(void *NotUsed){
-+ UNUSED_PARAMETER(NotUsed);
-+ assert( (sizeof(struct MemBlockHdr)&7) == 0 );
-+ if( !sqlite3GlobalConfig.bMemstat ){
-+ /* If memory status is enabled, then the malloc.c wrapper will already
-+ ** hold the STATIC_MEM mutex when the routines here are invoked. */
-+ mem.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM);
- }
--#endif /* SQLITE_OS_WINCE */
--#endif
-+ return SQLITE_OK;
-+}
-
--#ifdef SQLITE_DEBUG
- /*
--** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are
--** intended for use only inside assert() statements.
-+** Deinitialize the memory allocation subsystem.
- */
--static int winMutexHeld(sqlite3_mutex *p){
-- return p->nRef!=0 && p->owner==GetCurrentThreadId();
--}
--static int winMutexNotheld2(sqlite3_mutex *p, DWORD tid){
-- return p->nRef==0 || p->owner!=tid;
--}
--static int winMutexNotheld(sqlite3_mutex *p){
-- DWORD tid = GetCurrentThreadId();
-- return winMutexNotheld2(p, tid);
-+static void sqlite3MemShutdown(void *NotUsed){
-+ UNUSED_PARAMETER(NotUsed);
-+ mem.mutex = 0;
- }
--#endif
--
-
- /*
--** Initialize and deinitialize the mutex subsystem.
--*/
--static sqlite3_mutex winMutex_staticMutexes[6] = {
-- SQLITE3_MUTEX_INITIALIZER,
-- SQLITE3_MUTEX_INITIALIZER,
-- SQLITE3_MUTEX_INITIALIZER,
-- SQLITE3_MUTEX_INITIALIZER,
-- SQLITE3_MUTEX_INITIALIZER,
-- SQLITE3_MUTEX_INITIALIZER
--};
--static int winMutex_isInit = 0;
--/* As winMutexInit() and winMutexEnd() are called as part
--** of the sqlite3_initialize and sqlite3_shutdown()
--** processing, the "interlocked" magic is probably not
--** strictly necessary.
-+** Round up a request size to the next valid allocation size.
- */
--static long winMutex_lock = 0;
-+static int sqlite3MemRoundup(int n){
-+ return ROUND8(n);
-+}
-
--SQLITE_API void sqlite3_win32_sleep(DWORD milliseconds); /* os_win.c */
-+/*
-+** Fill a buffer with pseudo-random bytes. This is used to preset
-+** the content of a new memory allocation to unpredictable values and
-+** to clear the content of a freed allocation to unpredictable values.
-+*/
-+static void randomFill(char *pBuf, int nByte){
-+ unsigned int x, y, r;
-+ x = SQLITE_PTR_TO_INT(pBuf);
-+ y = nByte | 1;
-+ while( nByte >= 4 ){
-+ x = (x>>1) ^ (-(x&1) & 0xd0000001);
-+ y = y*1103515245 + 12345;
-+ r = x ^ y;
-+ *(int*)pBuf = r;
-+ pBuf += 4;
-+ nByte -= 4;
-+ }
-+ while( nByte-- > 0 ){
-+ x = (x>>1) ^ (-(x&1) & 0xd0000001);
-+ y = y*1103515245 + 12345;
-+ r = x ^ y;
-+ *(pBuf++) = r & 0xff;
-+ }
-+}
-
--static int winMutexInit(void){
-- /* The first to increment to 1 does actual initialization */
-- if( InterlockedCompareExchange(&winMutex_lock, 1, 0)==0 ){
-- int i;
-- for(i=0; i<ArraySize(winMutex_staticMutexes); i++){
--#if SQLITE_OS_WINRT
-- InitializeCriticalSectionEx(&winMutex_staticMutexes[i].mutex, 0, 0);
--#else
-- InitializeCriticalSection(&winMutex_staticMutexes[i].mutex);
--#endif
-+/*
-+** Allocate nByte bytes of memory.
-+*/
-+static void *sqlite3MemMalloc(int nByte){
-+ struct MemBlockHdr *pHdr;
-+ void **pBt;
-+ char *z;
-+ int *pInt;
-+ void *p = 0;
-+ int totalSize;
-+ int nReserve;
-+ sqlite3_mutex_enter(mem.mutex);
-+ assert( mem.disallow==0 );
-+ nReserve = ROUND8(nByte);
-+ totalSize = nReserve + sizeof(*pHdr) + sizeof(int) +
-+ mem.nBacktrace*sizeof(void*) + mem.nTitle;
-+ p = malloc(totalSize);
-+ if( p ){
-+ z = p;
-+ pBt = (void**)&z[mem.nTitle];
-+ pHdr = (struct MemBlockHdr*)&pBt[mem.nBacktrace];
-+ pHdr->pNext = 0;
-+ pHdr->pPrev = mem.pLast;
-+ if( mem.pLast ){
-+ mem.pLast->pNext = pHdr;
-+ }else{
-+ mem.pFirst = pHdr;
- }
-- winMutex_isInit = 1;
-- }else{
-- /* Someone else is in the process of initing the static mutexes */
-- while( !winMutex_isInit ){
-- sqlite3_win32_sleep(1);
-+ mem.pLast = pHdr;
-+ pHdr->iForeGuard = FOREGUARD;
-+ pHdr->eType = MEMTYPE_HEAP;
-+ pHdr->nBacktraceSlots = mem.nBacktrace;
-+ pHdr->nTitle = mem.nTitle;
-+ if( mem.nBacktrace ){
-+ void *aAddr[40];
-+ pHdr->nBacktrace = backtrace(aAddr, mem.nBacktrace+1)-1;
-+ memcpy(pBt, &aAddr[1], pHdr->nBacktrace*sizeof(void*));
-+ assert(pBt[0]);
-+ if( mem.xBacktrace ){
-+ mem.xBacktrace(nByte, pHdr->nBacktrace-1, &aAddr[1]);
-+ }
-+ }else{
-+ pHdr->nBacktrace = 0;
-+ }
-+ if( mem.nTitle ){
-+ memcpy(z, mem.zTitle, mem.nTitle);
- }
-+ pHdr->iSize = nByte;
-+ adjustStats(nByte, +1);
-+ pInt = (int*)&pHdr[1];
-+ pInt[nReserve/sizeof(int)] = REARGUARD;
-+ randomFill((char*)pInt, nByte);
-+ memset(((char*)pInt)+nByte, 0x65, nReserve-nByte);
-+ p = (void*)pInt;
- }
-- return SQLITE_OK;
-+ sqlite3_mutex_leave(mem.mutex);
-+ return p;
- }
-
--static int winMutexEnd(void){
-- /* The first to decrement to 0 does actual shutdown
-- ** (which should be the last to shutdown.) */
-- if( InterlockedCompareExchange(&winMutex_lock, 0, 1)==1 ){
-- if( winMutex_isInit==1 ){
-- int i;
-- for(i=0; i<ArraySize(winMutex_staticMutexes); i++){
-- DeleteCriticalSection(&winMutex_staticMutexes[i].mutex);
-- }
-- winMutex_isInit = 0;
-+/*
-+** Free memory.
-+*/
-+static void sqlite3MemFree(void *pPrior){
-+ struct MemBlockHdr *pHdr;
-+ void **pBt;
-+ char *z;
-+ assert( sqlite3GlobalConfig.bMemstat || sqlite3GlobalConfig.bCoreMutex==0
-+ || mem.mutex!=0 );
-+ pHdr = sqlite3MemsysGetHeader(pPrior);
-+ pBt = (void**)pHdr;
-+ pBt -= pHdr->nBacktraceSlots;
-+ sqlite3_mutex_enter(mem.mutex);
-+ if( pHdr->pPrev ){
-+ assert( pHdr->pPrev->pNext==pHdr );
-+ pHdr->pPrev->pNext = pHdr->pNext;
-+ }else{
-+ assert( mem.pFirst==pHdr );
-+ mem.pFirst = pHdr->pNext;
-+ }
-+ if( pHdr->pNext ){
-+ assert( pHdr->pNext->pPrev==pHdr );
-+ pHdr->pNext->pPrev = pHdr->pPrev;
-+ }else{
-+ assert( mem.pLast==pHdr );
-+ mem.pLast = pHdr->pPrev;
-+ }
-+ z = (char*)pBt;
-+ z -= pHdr->nTitle;
-+ adjustStats(pHdr->iSize, -1);
-+ randomFill(z, sizeof(void*)*pHdr->nBacktraceSlots + sizeof(*pHdr) +
-+ pHdr->iSize + sizeof(int) + pHdr->nTitle);
-+ free(z);
-+ sqlite3_mutex_leave(mem.mutex);
-+}
-+
-+/*
-+** Change the size of an existing memory allocation.
-+**
-+** For this debugging implementation, we *always* make a copy of the
-+** allocation into a new place in memory. In this way, if the
-+** higher level code is using pointer to the old allocation, it is
-+** much more likely to break and we are much more liking to find
-+** the error.
-+*/
-+static void *sqlite3MemRealloc(void *pPrior, int nByte){
-+ struct MemBlockHdr *pOldHdr;
-+ void *pNew;
-+ assert( mem.disallow==0 );
-+ assert( (nByte & 7)==0 ); /* EV: R-46199-30249 */
-+ pOldHdr = sqlite3MemsysGetHeader(pPrior);
-+ pNew = sqlite3MemMalloc(nByte);
-+ if( pNew ){
-+ memcpy(pNew, pPrior, nByte<pOldHdr->iSize ? nByte : pOldHdr->iSize);
-+ if( nByte>pOldHdr->iSize ){
-+ randomFill(&((char*)pNew)[pOldHdr->iSize], nByte - pOldHdr->iSize);
- }
-+ sqlite3MemFree(pPrior);
- }
-- return SQLITE_OK;
-+ return pNew;
- }
-
- /*
--** The sqlite3_mutex_alloc() routine allocates a new
--** mutex and returns a pointer to it. If it returns NULL
--** that means that a mutex could not be allocated. SQLite
--** will unwind its stack and return an error. The argument
--** to sqlite3_mutex_alloc() is one of these integer constants:
-+** Populate the low-level memory allocation function pointers in
-+** sqlite3GlobalConfig.m with pointers to the routines in this file.
-+*/
-+SQLITE_PRIVATE void sqlite3MemSetDefault(void){
-+ static const sqlite3_mem_methods defaultMethods = {
-+ sqlite3MemMalloc,
-+ sqlite3MemFree,
-+ sqlite3MemRealloc,
-+ sqlite3MemSize,
-+ sqlite3MemRoundup,
-+ sqlite3MemInit,
-+ sqlite3MemShutdown,
-+ 0
-+ };
-+ sqlite3_config(SQLITE_CONFIG_MALLOC, &defaultMethods);
-+}
-+
-+/*
-+** Set the "type" of an allocation.
-+*/
-+SQLITE_PRIVATE void sqlite3MemdebugSetType(void *p, u8 eType){
-+ if( p && sqlite3GlobalConfig.m.xMalloc==sqlite3MemMalloc ){
-+ struct MemBlockHdr *pHdr;
-+ pHdr = sqlite3MemsysGetHeader(p);
-+ assert( pHdr->iForeGuard==FOREGUARD );
-+ pHdr->eType = eType;
-+ }
-+}
-+
-+/*
-+** Return TRUE if the mask of type in eType matches the type of the
-+** allocation p. Also return true if p==NULL.
- **
--** <ul>
--** <li> SQLITE_MUTEX_FAST
--** <li> SQLITE_MUTEX_RECURSIVE
--** <li> SQLITE_MUTEX_STATIC_MASTER
--** <li> SQLITE_MUTEX_STATIC_MEM
--** <li> SQLITE_MUTEX_STATIC_MEM2
--** <li> SQLITE_MUTEX_STATIC_PRNG
--** <li> SQLITE_MUTEX_STATIC_LRU
--** <li> SQLITE_MUTEX_STATIC_PMEM
--** </ul>
-+** This routine is designed for use within an assert() statement, to
-+** verify the type of an allocation. For example:
- **
--** The first two constants cause sqlite3_mutex_alloc() to create
--** a new mutex. The new mutex is recursive when SQLITE_MUTEX_RECURSIVE
--** is used but not necessarily so when SQLITE_MUTEX_FAST is used.
--** The mutex implementation does not need to make a distinction
--** between SQLITE_MUTEX_RECURSIVE and SQLITE_MUTEX_FAST if it does
--** not want to. But SQLite will only request a recursive mutex in
--** cases where it really needs one. If a faster non-recursive mutex
--** implementation is available on the host platform, the mutex subsystem
--** might return such a mutex in response to SQLITE_MUTEX_FAST.
-+** assert( sqlite3MemdebugHasType(p, MEMTYPE_DB) );
-+*/
-+SQLITE_PRIVATE int sqlite3MemdebugHasType(void *p, u8 eType){
-+ int rc = 1;
-+ if( p && sqlite3GlobalConfig.m.xMalloc==sqlite3MemMalloc ){
-+ struct MemBlockHdr *pHdr;
-+ pHdr = sqlite3MemsysGetHeader(p);
-+ assert( pHdr->iForeGuard==FOREGUARD ); /* Allocation is valid */
-+ if( (pHdr->eType&eType)==0 ){
-+ rc = 0;
-+ }
-+ }
-+ return rc;
-+}
-+
-+/*
-+** Return TRUE if the mask of type in eType matches no bits of the type of the
-+** allocation p. Also return true if p==NULL.
- **
--** The other allowed parameters to sqlite3_mutex_alloc() each return
--** a pointer to a static preexisting mutex. Six static mutexes are
--** used by the current version of SQLite. Future versions of SQLite
--** may add additional static mutexes. Static mutexes are for internal
--** use by SQLite only. Applications that use SQLite mutexes should
--** use only the dynamic mutexes returned by SQLITE_MUTEX_FAST or
--** SQLITE_MUTEX_RECURSIVE.
-+** This routine is designed for use within an assert() statement, to
-+** verify the type of an allocation. For example:
- **
--** Note that if one of the dynamic mutex parameters (SQLITE_MUTEX_FAST
--** or SQLITE_MUTEX_RECURSIVE) is used then sqlite3_mutex_alloc()
--** returns a different mutex on every call. But for the static
--** mutex types, the same mutex is returned on every call that has
--** the same type number.
-+** assert( sqlite3MemdebugNoType(p, MEMTYPE_DB) );
- */
--static sqlite3_mutex *winMutexAlloc(int iType){
-- sqlite3_mutex *p;
--
-- switch( iType ){
-- case SQLITE_MUTEX_FAST:
-- case SQLITE_MUTEX_RECURSIVE: {
-- p = sqlite3MallocZero( sizeof(*p) );
-- if( p ){
--#ifdef SQLITE_DEBUG
-- p->id = iType;
--#endif
--#if SQLITE_OS_WINRT
-- InitializeCriticalSectionEx(&p->mutex, 0, 0);
--#else
-- InitializeCriticalSection(&p->mutex);
--#endif
-- }
-- break;
-- }
-- default: {
-- assert( winMutex_isInit==1 );
-- assert( iType-2 >= 0 );
-- assert( iType-2 < ArraySize(winMutex_staticMutexes) );
-- p = &winMutex_staticMutexes[iType-2];
--#ifdef SQLITE_DEBUG
-- p->id = iType;
--#endif
-- break;
-+SQLITE_PRIVATE int sqlite3MemdebugNoType(void *p, u8 eType){
-+ int rc = 1;
-+ if( p && sqlite3GlobalConfig.m.xMalloc==sqlite3MemMalloc ){
-+ struct MemBlockHdr *pHdr;
-+ pHdr = sqlite3MemsysGetHeader(p);
-+ assert( pHdr->iForeGuard==FOREGUARD ); /* Allocation is valid */
-+ if( (pHdr->eType&eType)!=0 ){
-+ rc = 0;
- }
- }
-- return p;
-+ return rc;
- }
-
--
- /*
--** This routine deallocates a previously
--** allocated mutex. SQLite is careful to deallocate every
--** mutex that it allocates.
-+** Set the number of backtrace levels kept for each allocation.
-+** A value of zero turns off backtracing. The number is always rounded
-+** up to a multiple of 2.
- */
--static void winMutexFree(sqlite3_mutex *p){
-- assert( p );
-- assert( p->nRef==0 && p->owner==0 );
-- assert( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE );
-- DeleteCriticalSection(&p->mutex);
-- sqlite3_free(p);
-+SQLITE_PRIVATE void sqlite3MemdebugBacktrace(int depth){
-+ if( depth<0 ){ depth = 0; }
-+ if( depth>20 ){ depth = 20; }
-+ depth = (depth+1)&0xfe;
-+ mem.nBacktrace = depth;
-+}
-+
-+SQLITE_PRIVATE void sqlite3MemdebugBacktraceCallback(void (*xBacktrace)(int, int, void **)){
-+ mem.xBacktrace = xBacktrace;
- }
-
- /*
--** The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt
--** to enter a mutex. If another thread is already within the mutex,
--** sqlite3_mutex_enter() will block and sqlite3_mutex_try() will return
--** SQLITE_BUSY. The sqlite3_mutex_try() interface returns SQLITE_OK
--** upon successful entry. Mutexes created using SQLITE_MUTEX_RECURSIVE can
--** be entered multiple times by the same thread. In such cases the,
--** mutex must be exited an equal number of times before another thread
--** can enter. If the same thread tries to enter any other kind of mutex
--** more than once, the behavior is undefined.
-+** Set the title string for subsequent allocations.
- */
--static void winMutexEnter(sqlite3_mutex *p){
--#ifdef SQLITE_DEBUG
-- DWORD tid = GetCurrentThreadId();
-- assert( p->id==SQLITE_MUTEX_RECURSIVE || winMutexNotheld2(p, tid) );
--#endif
-- EnterCriticalSection(&p->mutex);
--#ifdef SQLITE_DEBUG
-- assert( p->nRef>0 || p->owner==0 );
-- p->owner = tid;
-- p->nRef++;
-- if( p->trace ){
-- printf("enter mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef);
-+SQLITE_PRIVATE void sqlite3MemdebugSettitle(const char *zTitle){
-+ unsigned int n = sqlite3Strlen30(zTitle) + 1;
-+ sqlite3_mutex_enter(mem.mutex);
-+ if( n>=sizeof(mem.zTitle) ) n = sizeof(mem.zTitle)-1;
-+ memcpy(mem.zTitle, zTitle, n);
-+ mem.zTitle[n] = 0;
-+ mem.nTitle = ROUND8(n);
-+ sqlite3_mutex_leave(mem.mutex);
-+}
-+
-+SQLITE_PRIVATE void sqlite3MemdebugSync(){
-+ struct MemBlockHdr *pHdr;
-+ for(pHdr=mem.pFirst; pHdr; pHdr=pHdr->pNext){
-+ void **pBt = (void**)pHdr;
-+ pBt -= pHdr->nBacktraceSlots;
-+ mem.xBacktrace(pHdr->iSize, pHdr->nBacktrace-1, &pBt[1]);
- }
--#endif
- }
--static int winMutexTry(sqlite3_mutex *p){
--#ifndef NDEBUG
-- DWORD tid = GetCurrentThreadId();
--#endif
-- int rc = SQLITE_BUSY;
-- assert( p->id==SQLITE_MUTEX_RECURSIVE || winMutexNotheld2(p, tid) );
-- /*
-- ** The sqlite3_mutex_try() routine is very rarely used, and when it
-- ** is used it is merely an optimization. So it is OK for it to always
-- ** fail.
-- **
-- ** The TryEnterCriticalSection() interface is only available on WinNT.
-- ** And some windows compilers complain if you try to use it without
-- ** first doing some #defines that prevent SQLite from building on Win98.
-- ** For that reason, we will omit this optimization for now. See
-- ** ticket #2685.
-- */
--#if 0
-- if( mutexIsNT() && TryEnterCriticalSection(&p->mutex) ){
-- p->owner = tid;
-- p->nRef++;
-- rc = SQLITE_OK;
-+
-+/*
-+** Open the file indicated and write a log of all unfreed memory
-+** allocations into that log.
-+*/
-+SQLITE_PRIVATE void sqlite3MemdebugDump(const char *zFilename){
-+ FILE *out;
-+ struct MemBlockHdr *pHdr;
-+ void **pBt;
-+ int i;
-+ out = fopen(zFilename, "w");
-+ if( out==0 ){
-+ fprintf(stderr, "** Unable to output memory debug output log: %s **\n",
-+ zFilename);
-+ return;
- }
--#else
-- UNUSED_PARAMETER(p);
--#endif
--#ifdef SQLITE_DEBUG
-- if( rc==SQLITE_OK && p->trace ){
-- printf("try mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef);
-+ for(pHdr=mem.pFirst; pHdr; pHdr=pHdr->pNext){
-+ char *z = (char*)pHdr;
-+ z -= pHdr->nBacktraceSlots*sizeof(void*) + pHdr->nTitle;
-+ fprintf(out, "**** %lld bytes at %p from %s ****\n",
-+ pHdr->iSize, &pHdr[1], pHdr->nTitle ? z : "???");
-+ if( pHdr->nBacktrace ){
-+ fflush(out);
-+ pBt = (void**)pHdr;
-+ pBt -= pHdr->nBacktraceSlots;
-+ backtrace_symbols_fd(pBt, pHdr->nBacktrace, fileno(out));
-+ fprintf(out, "\n");
-+ }
- }
--#endif
-- return rc;
-+ fprintf(out, "COUNTS:\n");
-+ for(i=0; i<NCSIZE-1; i++){
-+ if( mem.nAlloc[i] ){
-+ fprintf(out, " %5d: %10d %10d %10d\n",
-+ i*8, mem.nAlloc[i], mem.nCurrent[i], mem.mxCurrent[i]);
-+ }
-+ }
-+ if( mem.nAlloc[NCSIZE-1] ){
-+ fprintf(out, " %5d: %10d %10d %10d\n",
-+ NCSIZE*8-8, mem.nAlloc[NCSIZE-1],
-+ mem.nCurrent[NCSIZE-1], mem.mxCurrent[NCSIZE-1]);
-+ }
-+ fclose(out);
- }
-
- /*
--** The sqlite3_mutex_leave() routine exits a mutex that was
--** previously entered by the same thread. The behavior
--** is undefined if the mutex is not currently entered or
--** is not currently allocated. SQLite will never do either.
-+** Return the number of times sqlite3MemMalloc() has been called.
- */
--static void winMutexLeave(sqlite3_mutex *p){
--#ifndef NDEBUG
-- DWORD tid = GetCurrentThreadId();
-- assert( p->nRef>0 );
-- assert( p->owner==tid );
-- p->nRef--;
-- if( p->nRef==0 ) p->owner = 0;
-- assert( p->nRef==0 || p->id==SQLITE_MUTEX_RECURSIVE );
--#endif
-- LeaveCriticalSection(&p->mutex);
--#ifdef SQLITE_DEBUG
-- if( p->trace ){
-- printf("leave mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef);
-+SQLITE_PRIVATE int sqlite3MemdebugMallocCount(){
-+ int i;
-+ int nTotal = 0;
-+ for(i=0; i<NCSIZE; i++){
-+ nTotal += mem.nAlloc[i];
- }
--#endif
-+ return nTotal;
- }
-
--SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3DefaultMutex(void){
-- static const sqlite3_mutex_methods sMutex = {
-- winMutexInit,
-- winMutexEnd,
-- winMutexAlloc,
-- winMutexFree,
-- winMutexEnter,
-- winMutexTry,
-- winMutexLeave,
--#ifdef SQLITE_DEBUG
-- winMutexHeld,
-- winMutexNotheld
--#else
-- 0,
-- 0
--#endif
-- };
-
-- return &sMutex;
--}
--#endif /* SQLITE_MUTEX_W32 */
-+#endif /* SQLITE_MEMDEBUG */
-
--/************** End of mutex_w32.c *******************************************/
--/************** Begin file malloc.c ******************************************/
-+/************** End of mem2.c ************************************************/
-+/************** Begin file mem3.c ********************************************/
- /*
--** 2001 September 15
-+** 2007 October 14
- **
- ** The author disclaims copyright to this source code. In place of
- ** a legal notice, here is a blessing:
-@@ -18775,1904 +19478,1632 @@
- ** May you share freely, never taking more than you give.
- **
- *************************************************************************
-+** This file contains the C functions that implement a memory
-+** allocation subsystem for use by SQLite.
- **
--** Memory allocation functions used throughout sqlite.
-+** This version of the memory allocation subsystem omits all
-+** use of malloc(). The SQLite user supplies a block of memory
-+** before calling sqlite3_initialize() from which allocations
-+** are made and returned by the xMalloc() and xRealloc()
-+** implementations. Once sqlite3_initialize() has been called,
-+** the amount of memory available to SQLite is fixed and cannot
-+** be changed.
-+**
-+** This version of the memory allocation subsystem is included
-+** in the build only if SQLITE_ENABLE_MEMSYS3 is defined.
- */
--/* #include <stdarg.h> */
-
- /*
--** Attempt to release up to n bytes of non-essential memory currently
--** held by SQLite. An example of non-essential memory is memory used to
--** cache database pages that are not currently in use.
-+** This version of the memory allocator is only built into the library
-+** SQLITE_ENABLE_MEMSYS3 is defined. Defining this symbol does not
-+** mean that the library will use a memory-pool by default, just that
-+** it is available. The mempool allocator is activated by calling
-+** sqlite3_config().
- */
--SQLITE_API int sqlite3_release_memory(int n){
--#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
-- return sqlite3PcacheReleaseMemory(n);
--#else
-- /* IMPLEMENTATION-OF: R-34391-24921 The sqlite3_release_memory() routine
-- ** is a no-op returning zero if SQLite is not compiled with
-- ** SQLITE_ENABLE_MEMORY_MANAGEMENT. */
-- UNUSED_PARAMETER(n);
-- return 0;
--#endif
--}
-+#ifdef SQLITE_ENABLE_MEMSYS3
-
- /*
--** An instance of the following object records the location of
--** each unused scratch buffer.
-+** Maximum size (in Mem3Blocks) of a "small" chunk.
- */
--typedef struct ScratchFreeslot {
-- struct ScratchFreeslot *pNext; /* Next unused scratch buffer */
--} ScratchFreeslot;
-+#define MX_SMALL 10
-+
-
- /*
--** State information local to the memory allocation subsystem.
-+** Number of freelist hash slots
- */
--static SQLITE_WSD struct Mem0Global {
-- sqlite3_mutex *mutex; /* Mutex to serialize access */
-+#define N_HASH 61
-+
-+/*
-+** A memory allocation (also called a "chunk") consists of two or
-+** more blocks where each block is 8 bytes. The first 8 bytes are
-+** a header that is not returned to the user.
-+**
-+** A chunk is two or more blocks that is either checked out or
-+** free. The first block has format u.hdr. u.hdr.size4x is 4 times the
-+** size of the allocation in blocks if the allocation is free.
-+** The u.hdr.size4x&1 bit is true if the chunk is checked out and
-+** false if the chunk is on the freelist. The u.hdr.size4x&2 bit
-+** is true if the previous chunk is checked out and false if the
-+** previous chunk is free. The u.hdr.prevSize field is the size of
-+** the previous chunk in blocks if the previous chunk is on the
-+** freelist. If the previous chunk is checked out, then
-+** u.hdr.prevSize can be part of the data for that chunk and should
-+** not be read or written.
-+**
-+** We often identify a chunk by its index in mem3.aPool[]. When
-+** this is done, the chunk index refers to the second block of
-+** the chunk. In this way, the first chunk has an index of 1.
-+** A chunk index of 0 means "no such chunk" and is the equivalent
-+** of a NULL pointer.
-+**
-+** The second block of free chunks is of the form u.list. The
-+** two fields form a double-linked list of chunks of related sizes.
-+** Pointers to the head of the list are stored in mem3.aiSmall[]
-+** for smaller chunks and mem3.aiHash[] for larger chunks.
-+**
-+** The second block of a chunk is user data if the chunk is checked
-+** out. If a chunk is checked out, the user data may extend into
-+** the u.hdr.prevSize value of the following chunk.
-+*/
-+typedef struct Mem3Block Mem3Block;
-+struct Mem3Block {
-+ union {
-+ struct {
-+ u32 prevSize; /* Size of previous chunk in Mem3Block elements */
-+ u32 size4x; /* 4x the size of current chunk in Mem3Block elements */
-+ } hdr;
-+ struct {
-+ u32 next; /* Index in mem3.aPool[] of next free chunk */
-+ u32 prev; /* Index in mem3.aPool[] of previous free chunk */
-+ } list;
-+ } u;
-+};
-
-+/*
-+** All of the static variables used by this module are collected
-+** into a single structure named "mem3". This is to keep the
-+** static variables organized and to reduce namespace pollution
-+** when this module is combined with other in the amalgamation.
-+*/
-+static SQLITE_WSD struct Mem3Global {
- /*
-- ** The alarm callback and its arguments. The mem0.mutex lock will
-- ** be held while the callback is running. Recursive calls into
-- ** the memory subsystem are allowed, but no new callbacks will be
-- ** issued.
-+ ** Memory available for allocation. nPool is the size of the array
-+ ** (in Mem3Blocks) pointed to by aPool less 2.
- */
-- sqlite3_int64 alarmThreshold;
-- void (*alarmCallback)(void*, sqlite3_int64,int);
-- void *alarmArg;
-+ u32 nPool;
-+ Mem3Block *aPool;
-
- /*
-- ** Pointers to the end of sqlite3GlobalConfig.pScratch memory
-- ** (so that a range test can be used to determine if an allocation
-- ** being freed came from pScratch) and a pointer to the list of
-- ** unused scratch allocations.
-+ ** True if we are evaluating an out-of-memory callback.
- */
-- void *pScratchEnd;
-- ScratchFreeslot *pScratchFree;
-- u32 nScratchFree;
-+ int alarmBusy;
-+
-+ /*
-+ ** Mutex to control access to the memory allocation subsystem.
-+ */
-+ sqlite3_mutex *mutex;
-+
-+ /*
-+ ** The minimum amount of free space that we have seen.
-+ */
-+ u32 mnMaster;
-
- /*
-- ** True if heap is nearly "full" where "full" is defined by the
-- ** sqlite3_soft_heap_limit() setting.
-+ ** iMaster is the index of the master chunk. Most new allocations
-+ ** occur off of this chunk. szMaster is the size (in Mem3Blocks)
-+ ** of the current master. iMaster is 0 if there is not master chunk.
-+ ** The master chunk is not in either the aiHash[] or aiSmall[].
- */
-- int nearlyFull;
--} mem0 = { 0, 0, 0, 0, 0, 0, 0, 0 };
-+ u32 iMaster;
-+ u32 szMaster;
-
--#define mem0 GLOBAL(struct Mem0Global, mem0)
-+ /*
-+ ** Array of lists of free blocks according to the block size
-+ ** for smaller chunks, or a hash on the block size for larger
-+ ** chunks.
-+ */
-+ u32 aiSmall[MX_SMALL-1]; /* For sizes 2 through MX_SMALL, inclusive */
-+ u32 aiHash[N_HASH]; /* For sizes MX_SMALL+1 and larger */
-+} mem3 = { 97535575 };
-
--/*
--** This routine runs when the memory allocator sees that the
--** total memory allocation is about to exceed the soft heap
--** limit.
--*/
--static void softHeapLimitEnforcer(
-- void *NotUsed,
-- sqlite3_int64 NotUsed2,
-- int allocSize
--){
-- UNUSED_PARAMETER2(NotUsed, NotUsed2);
-- sqlite3_release_memory(allocSize);
--}
-+#define mem3 GLOBAL(struct Mem3Global, mem3)
-
- /*
--** Change the alarm callback
-+** Unlink the chunk at mem3.aPool[i] from list it is currently
-+** on. *pRoot is the list that i is a member of.
- */
--static int sqlite3MemoryAlarm(
-- void(*xCallback)(void *pArg, sqlite3_int64 used,int N),
-- void *pArg,
-- sqlite3_int64 iThreshold
--){
-- int nUsed;
-- sqlite3_mutex_enter(mem0.mutex);
-- mem0.alarmCallback = xCallback;
-- mem0.alarmArg = pArg;
-- mem0.alarmThreshold = iThreshold;
-- nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED);
-- mem0.nearlyFull = (iThreshold>0 && iThreshold<=nUsed);
-- sqlite3_mutex_leave(mem0.mutex);
-- return SQLITE_OK;
-+static void memsys3UnlinkFromList(u32 i, u32 *pRoot){
-+ u32 next = mem3.aPool[i].u.list.next;
-+ u32 prev = mem3.aPool[i].u.list.prev;
-+ assert( sqlite3_mutex_held(mem3.mutex) );
-+ if( prev==0 ){
-+ *pRoot = next;
-+ }else{
-+ mem3.aPool[prev].u.list.next = next;
-+ }
-+ if( next ){
-+ mem3.aPool[next].u.list.prev = prev;
-+ }
-+ mem3.aPool[i].u.list.next = 0;
-+ mem3.aPool[i].u.list.prev = 0;
- }
-
--#ifndef SQLITE_OMIT_DEPRECATED
- /*
--** Deprecated external interface. Internal/core SQLite code
--** should call sqlite3MemoryAlarm.
-+** Unlink the chunk at index i from
-+** whatever list is currently a member of.
- */
--SQLITE_API int sqlite3_memory_alarm(
-- void(*xCallback)(void *pArg, sqlite3_int64 used,int N),
-- void *pArg,
-- sqlite3_int64 iThreshold
--){
-- return sqlite3MemoryAlarm(xCallback, pArg, iThreshold);
-+static void memsys3Unlink(u32 i){
-+ u32 size, hash;
-+ assert( sqlite3_mutex_held(mem3.mutex) );
-+ assert( (mem3.aPool[i-1].u.hdr.size4x & 1)==0 );
-+ assert( i>=1 );
-+ size = mem3.aPool[i-1].u.hdr.size4x/4;
-+ assert( size==mem3.aPool[i+size-1].u.hdr.prevSize );
-+ assert( size>=2 );
-+ if( size <= MX_SMALL ){
-+ memsys3UnlinkFromList(i, &mem3.aiSmall[size-2]);
-+ }else{
-+ hash = size % N_HASH;
-+ memsys3UnlinkFromList(i, &mem3.aiHash[hash]);
-+ }
- }
--#endif
-
- /*
--** Set the soft heap-size limit for the library. Passing a zero or
--** negative value indicates no limit.
-+** Link the chunk at mem3.aPool[i] so that is on the list rooted
-+** at *pRoot.
- */
--SQLITE_API sqlite3_int64 sqlite3_soft_heap_limit64(sqlite3_int64 n){
-- sqlite3_int64 priorLimit;
-- sqlite3_int64 excess;
--#ifndef SQLITE_OMIT_AUTOINIT
-- int rc = sqlite3_initialize();
-- if( rc ) return -1;
--#endif
-- sqlite3_mutex_enter(mem0.mutex);
-- priorLimit = mem0.alarmThreshold;
-- sqlite3_mutex_leave(mem0.mutex);
-- if( n<0 ) return priorLimit;
-- if( n>0 ){
-- sqlite3MemoryAlarm(softHeapLimitEnforcer, 0, n);
-- }else{
-- sqlite3MemoryAlarm(0, 0, 0);
-+static void memsys3LinkIntoList(u32 i, u32 *pRoot){
-+ assert( sqlite3_mutex_held(mem3.mutex) );
-+ mem3.aPool[i].u.list.next = *pRoot;
-+ mem3.aPool[i].u.list.prev = 0;
-+ if( *pRoot ){
-+ mem3.aPool[*pRoot].u.list.prev = i;
- }
-- excess = sqlite3_memory_used() - n;
-- if( excess>0 ) sqlite3_release_memory((int)(excess & 0x7fffffff));
-- return priorLimit;
--}
--SQLITE_API void sqlite3_soft_heap_limit(int n){
-- if( n<0 ) n = 0;
-- sqlite3_soft_heap_limit64(n);
-+ *pRoot = i;
- }
-
- /*
--** Initialize the memory allocation subsystem.
-+** Link the chunk at index i into either the appropriate
-+** small chunk list, or into the large chunk hash table.
- */
--SQLITE_PRIVATE int sqlite3MallocInit(void){
-- if( sqlite3GlobalConfig.m.xMalloc==0 ){
-- sqlite3MemSetDefault();
-- }
-- memset(&mem0, 0, sizeof(mem0));
-- if( sqlite3GlobalConfig.bCoreMutex ){
-- mem0.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM);
-- }
-- if( sqlite3GlobalConfig.pScratch && sqlite3GlobalConfig.szScratch>=100
-- && sqlite3GlobalConfig.nScratch>0 ){
-- int i, n, sz;
-- ScratchFreeslot *pSlot;
-- sz = ROUNDDOWN8(sqlite3GlobalConfig.szScratch);
-- sqlite3GlobalConfig.szScratch = sz;
-- pSlot = (ScratchFreeslot*)sqlite3GlobalConfig.pScratch;
-- n = sqlite3GlobalConfig.nScratch;
-- mem0.pScratchFree = pSlot;
-- mem0.nScratchFree = n;
-- for(i=0; i<n-1; i++){
-- pSlot->pNext = (ScratchFreeslot*)(sz+(char*)pSlot);
-- pSlot = pSlot->pNext;
-- }
-- pSlot->pNext = 0;
-- mem0.pScratchEnd = (void*)&pSlot[1];
-+static void memsys3Link(u32 i){
-+ u32 size, hash;
-+ assert( sqlite3_mutex_held(mem3.mutex) );
-+ assert( i>=1 );
-+ assert( (mem3.aPool[i-1].u.hdr.size4x & 1)==0 );
-+ size = mem3.aPool[i-1].u.hdr.size4x/4;
-+ assert( size==mem3.aPool[i+size-1].u.hdr.prevSize );
-+ assert( size>=2 );
-+ if( size <= MX_SMALL ){
-+ memsys3LinkIntoList(i, &mem3.aiSmall[size-2]);
- }else{
-- mem0.pScratchEnd = 0;
-- sqlite3GlobalConfig.pScratch = 0;
-- sqlite3GlobalConfig.szScratch = 0;
-- sqlite3GlobalConfig.nScratch = 0;
-- }
-- if( sqlite3GlobalConfig.pPage==0 || sqlite3GlobalConfig.szPage<512
-- || sqlite3GlobalConfig.nPage<1 ){
-- sqlite3GlobalConfig.pPage = 0;
-- sqlite3GlobalConfig.szPage = 0;
-- sqlite3GlobalConfig.nPage = 0;
-+ hash = size % N_HASH;
-+ memsys3LinkIntoList(i, &mem3.aiHash[hash]);
- }
-- return sqlite3GlobalConfig.m.xInit(sqlite3GlobalConfig.m.pAppData);
- }
-
- /*
--** Return true if the heap is currently under memory pressure - in other
--** words if the amount of heap used is close to the limit set by
--** sqlite3_soft_heap_limit().
-+** If the STATIC_MEM mutex is not already held, obtain it now. The mutex
-+** will already be held (obtained by code in malloc.c) if
-+** sqlite3GlobalConfig.bMemStat is true.
- */
--SQLITE_PRIVATE int sqlite3HeapNearlyFull(void){
-- return mem0.nearlyFull;
-+static void memsys3Enter(void){
-+ if( sqlite3GlobalConfig.bMemstat==0 && mem3.mutex==0 ){
-+ mem3.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM);
-+ }
-+ sqlite3_mutex_enter(mem3.mutex);
-+}
-+static void memsys3Leave(void){
-+ sqlite3_mutex_leave(mem3.mutex);
- }
-
- /*
--** Deinitialize the memory allocation subsystem.
-+** Called when we are unable to satisfy an allocation of nBytes.
- */
--SQLITE_PRIVATE void sqlite3MallocEnd(void){
-- if( sqlite3GlobalConfig.m.xShutdown ){
-- sqlite3GlobalConfig.m.xShutdown(sqlite3GlobalConfig.m.pAppData);
-+static void memsys3OutOfMemory(int nByte){
-+ if( !mem3.alarmBusy ){
-+ mem3.alarmBusy = 1;
-+ assert( sqlite3_mutex_held(mem3.mutex) );
-+ sqlite3_mutex_leave(mem3.mutex);
-+ sqlite3_release_memory(nByte);
-+ sqlite3_mutex_enter(mem3.mutex);
-+ mem3.alarmBusy = 0;
- }
-- memset(&mem0, 0, sizeof(mem0));
- }
-
--/*
--** Return the amount of memory currently checked out.
--*/
--SQLITE_API sqlite3_int64 sqlite3_memory_used(void){
-- int n, mx;
-- sqlite3_int64 res;
-- sqlite3_status(SQLITE_STATUS_MEMORY_USED, &n, &mx, 0);
-- res = (sqlite3_int64)n; /* Work around bug in Borland C. Ticket #3216 */
-- return res;
--}
-
- /*
--** Return the maximum amount of memory that has ever been
--** checked out since either the beginning of this process
--** or since the most recent reset.
-+** Chunk i is a free chunk that has been unlinked. Adjust its
-+** size parameters for check-out and return a pointer to the
-+** user portion of the chunk.
- */
--SQLITE_API sqlite3_int64 sqlite3_memory_highwater(int resetFlag){
-- int n, mx;
-- sqlite3_int64 res;
-- sqlite3_status(SQLITE_STATUS_MEMORY_USED, &n, &mx, resetFlag);
-- res = (sqlite3_int64)mx; /* Work around bug in Borland C. Ticket #3216 */
-- return res;
-+static void *memsys3Checkout(u32 i, u32 nBlock){
-+ u32 x;
-+ assert( sqlite3_mutex_held(mem3.mutex) );
-+ assert( i>=1 );
-+ assert( mem3.aPool[i-1].u.hdr.size4x/4==nBlock );
-+ assert( mem3.aPool[i+nBlock-1].u.hdr.prevSize==nBlock );
-+ x = mem3.aPool[i-1].u.hdr.size4x;
-+ mem3.aPool[i-1].u.hdr.size4x = nBlock*4 | 1 | (x&2);
-+ mem3.aPool[i+nBlock-1].u.hdr.prevSize = nBlock;
-+ mem3.aPool[i+nBlock-1].u.hdr.size4x |= 2;
-+ return &mem3.aPool[i];
- }
-
- /*
--** Trigger the alarm
-+** Carve a piece off of the end of the mem3.iMaster free chunk.
-+** Return a pointer to the new allocation. Or, if the master chunk
-+** is not large enough, return 0.
- */
--static void sqlite3MallocAlarm(int nByte){
-- void (*xCallback)(void*,sqlite3_int64,int);
-- sqlite3_int64 nowUsed;
-- void *pArg;
-- if( mem0.alarmCallback==0 ) return;
-- xCallback = mem0.alarmCallback;
-- nowUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED);
-- pArg = mem0.alarmArg;
-- mem0.alarmCallback = 0;
-- sqlite3_mutex_leave(mem0.mutex);
-- xCallback(pArg, nowUsed, nByte);
-- sqlite3_mutex_enter(mem0.mutex);
-- mem0.alarmCallback = xCallback;
-- mem0.alarmArg = pArg;
-+static void *memsys3FromMaster(u32 nBlock){
-+ assert( sqlite3_mutex_held(mem3.mutex) );
-+ assert( mem3.szMaster>=nBlock );
-+ if( nBlock>=mem3.szMaster-1 ){
-+ /* Use the entire master */
-+ void *p = memsys3Checkout(mem3.iMaster, mem3.szMaster);
-+ mem3.iMaster = 0;
-+ mem3.szMaster = 0;
-+ mem3.mnMaster = 0;
-+ return p;
-+ }else{
-+ /* Split the master block. Return the tail. */
-+ u32 newi, x;
-+ newi = mem3.iMaster + mem3.szMaster - nBlock;
-+ assert( newi > mem3.iMaster+1 );
-+ mem3.aPool[mem3.iMaster+mem3.szMaster-1].u.hdr.prevSize = nBlock;
-+ mem3.aPool[mem3.iMaster+mem3.szMaster-1].u.hdr.size4x |= 2;
-+ mem3.aPool[newi-1].u.hdr.size4x = nBlock*4 + 1;
-+ mem3.szMaster -= nBlock;
-+ mem3.aPool[newi-1].u.hdr.prevSize = mem3.szMaster;
-+ x = mem3.aPool[mem3.iMaster-1].u.hdr.size4x & 2;
-+ mem3.aPool[mem3.iMaster-1].u.hdr.size4x = mem3.szMaster*4 | x;
-+ if( mem3.szMaster < mem3.mnMaster ){
-+ mem3.mnMaster = mem3.szMaster;
-+ }
-+ return (void*)&mem3.aPool[newi];
-+ }
- }
-
- /*
--** Do a memory allocation with statistics and alarms. Assume the
--** lock is already held.
-+** *pRoot is the head of a list of free chunks of the same size
-+** or same size hash. In other words, *pRoot is an entry in either
-+** mem3.aiSmall[] or mem3.aiHash[].
-+**
-+** This routine examines all entries on the given list and tries
-+** to coalesce each entries with adjacent free chunks.
-+**
-+** If it sees a chunk that is larger than mem3.iMaster, it replaces
-+** the current mem3.iMaster with the new larger chunk. In order for
-+** this mem3.iMaster replacement to work, the master chunk must be
-+** linked into the hash tables. That is not the normal state of
-+** affairs, of course. The calling routine must link the master
-+** chunk before invoking this routine, then must unlink the (possibly
-+** changed) master chunk once this routine has finished.
- */
--static int mallocWithAlarm(int n, void **pp){
-- int nFull;
-- void *p;
-- assert( sqlite3_mutex_held(mem0.mutex) );
-- nFull = sqlite3GlobalConfig.m.xRoundup(n);
-- sqlite3StatusSet(SQLITE_STATUS_MALLOC_SIZE, n);
-- if( mem0.alarmCallback!=0 ){
-- int nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED);
-- if( nUsed >= mem0.alarmThreshold - nFull ){
-- mem0.nearlyFull = 1;
-- sqlite3MallocAlarm(nFull);
-+static void memsys3Merge(u32 *pRoot){
-+ u32 iNext, prev, size, i, x;
-+
-+ assert( sqlite3_mutex_held(mem3.mutex) );
-+ for(i=*pRoot; i>0; i=iNext){
-+ iNext = mem3.aPool[i].u.list.next;
-+ size = mem3.aPool[i-1].u.hdr.size4x;
-+ assert( (size&1)==0 );
-+ if( (size&2)==0 ){
-+ memsys3UnlinkFromList(i, pRoot);
-+ assert( i > mem3.aPool[i-1].u.hdr.prevSize );
-+ prev = i - mem3.aPool[i-1].u.hdr.prevSize;
-+ if( prev==iNext ){
-+ iNext = mem3.aPool[prev].u.list.next;
-+ }
-+ memsys3Unlink(prev);
-+ size = i + size/4 - prev;
-+ x = mem3.aPool[prev-1].u.hdr.size4x & 2;
-+ mem3.aPool[prev-1].u.hdr.size4x = size*4 | x;
-+ mem3.aPool[prev+size-1].u.hdr.prevSize = size;
-+ memsys3Link(prev);
-+ i = prev;
- }else{
-- mem0.nearlyFull = 0;
-+ size /= 4;
-+ }
-+ if( size>mem3.szMaster ){
-+ mem3.iMaster = i;
-+ mem3.szMaster = size;
- }
- }
-- p = sqlite3GlobalConfig.m.xMalloc(nFull);
--#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
-- if( p==0 && mem0.alarmCallback ){
-- sqlite3MallocAlarm(nFull);
-- p = sqlite3GlobalConfig.m.xMalloc(nFull);
-- }
--#endif
-- if( p ){
-- nFull = sqlite3MallocSize(p);
-- sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, nFull);
-- sqlite3StatusAdd(SQLITE_STATUS_MALLOC_COUNT, 1);
-- }
-- *pp = p;
-- return nFull;
- }
-
- /*
--** Allocate memory. This routine is like sqlite3_malloc() except that it
--** assumes the memory subsystem has already been initialized.
-+** Return a block of memory of at least nBytes in size.
-+** Return NULL if unable.
-+**
-+** This function assumes that the necessary mutexes, if any, are
-+** already held by the caller. Hence "Unsafe".
- */
--SQLITE_PRIVATE void *sqlite3Malloc(int n){
-- void *p;
-- if( n<=0 /* IMP: R-65312-04917 */
-- || n>=0x7fffff00
-- ){
-- /* A memory allocation of a number of bytes which is near the maximum
-- ** signed integer value might cause an integer overflow inside of the
-- ** xMalloc(). Hence we limit the maximum size to 0x7fffff00, giving
-- ** 255 bytes of overhead. SQLite itself will never use anything near
-- ** this amount. The only way to reach the limit is with sqlite3_malloc() */
-- p = 0;
-- }else if( sqlite3GlobalConfig.bMemstat ){
-- sqlite3_mutex_enter(mem0.mutex);
-- mallocWithAlarm(n, &p);
-- sqlite3_mutex_leave(mem0.mutex);
-+static void *memsys3MallocUnsafe(int nByte){
-+ u32 i;
-+ u32 nBlock;
-+ u32 toFree;
-+
-+ assert( sqlite3_mutex_held(mem3.mutex) );
-+ assert( sizeof(Mem3Block)==8 );
-+ if( nByte<=12 ){
-+ nBlock = 2;
- }else{
-- p = sqlite3GlobalConfig.m.xMalloc(n);
-+ nBlock = (nByte + 11)/8;
- }
-- assert( EIGHT_BYTE_ALIGNMENT(p) ); /* IMP: R-04675-44850 */
-- return p;
--}
-+ assert( nBlock>=2 );
-
--/*
--** This version of the memory allocation is for use by the application.
--** First make sure the memory subsystem is initialized, then do the
--** allocation.
--*/
--SQLITE_API void *sqlite3_malloc(int n){
--#ifndef SQLITE_OMIT_AUTOINIT
-- if( sqlite3_initialize() ) return 0;
--#endif
-- return sqlite3Malloc(n);
--}
--
--/*
--** Each thread may only have a single outstanding allocation from
--** xScratchMalloc(). We verify this constraint in the single-threaded
--** case by setting scratchAllocOut to 1 when an allocation
--** is outstanding clearing it when the allocation is freed.
--*/
--#if SQLITE_THREADSAFE==0 && !defined(NDEBUG)
--static int scratchAllocOut = 0;
--#endif
-+ /* STEP 1:
-+ ** Look for an entry of the correct size in either the small
-+ ** chunk table or in the large chunk hash table. This is
-+ ** successful most of the time (about 9 times out of 10).
-+ */
-+ if( nBlock <= MX_SMALL ){
-+ i = mem3.aiSmall[nBlock-2];
-+ if( i>0 ){
-+ memsys3UnlinkFromList(i, &mem3.aiSmall[nBlock-2]);
-+ return memsys3Checkout(i, nBlock);
-+ }
-+ }else{
-+ int hash = nBlock % N_HASH;
-+ for(i=mem3.aiHash[hash]; i>0; i=mem3.aPool[i].u.list.next){
-+ if( mem3.aPool[i-1].u.hdr.size4x/4==nBlock ){
-+ memsys3UnlinkFromList(i, &mem3.aiHash[hash]);
-+ return memsys3Checkout(i, nBlock);
-+ }
-+ }
-+ }
-
-+ /* STEP 2:
-+ ** Try to satisfy the allocation by carving a piece off of the end
-+ ** of the master chunk. This step usually works if step 1 fails.
-+ */
-+ if( mem3.szMaster>=nBlock ){
-+ return memsys3FromMaster(nBlock);
-+ }
-
--/*
--** Allocate memory that is to be used and released right away.
--** This routine is similar to alloca() in that it is not intended
--** for situations where the memory might be held long-term. This
--** routine is intended to get memory to old large transient data
--** structures that would not normally fit on the stack of an
--** embedded processor.
--*/
--SQLITE_PRIVATE void *sqlite3ScratchMalloc(int n){
-- void *p;
-- assert( n>0 );
-
-- sqlite3_mutex_enter(mem0.mutex);
-- if( mem0.nScratchFree && sqlite3GlobalConfig.szScratch>=n ){
-- p = mem0.pScratchFree;
-- mem0.pScratchFree = mem0.pScratchFree->pNext;
-- mem0.nScratchFree--;
-- sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_USED, 1);
-- sqlite3StatusSet(SQLITE_STATUS_SCRATCH_SIZE, n);
-- sqlite3_mutex_leave(mem0.mutex);
-- }else{
-- if( sqlite3GlobalConfig.bMemstat ){
-- sqlite3StatusSet(SQLITE_STATUS_SCRATCH_SIZE, n);
-- n = mallocWithAlarm(n, &p);
-- if( p ) sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_OVERFLOW, n);
-- sqlite3_mutex_leave(mem0.mutex);
-- }else{
-- sqlite3_mutex_leave(mem0.mutex);
-- p = sqlite3GlobalConfig.m.xMalloc(n);
-+ /* STEP 3:
-+ ** Loop through the entire memory pool. Coalesce adjacent free
-+ ** chunks. Recompute the master chunk as the largest free chunk.
-+ ** Then try again to satisfy the allocation by carving a piece off
-+ ** of the end of the master chunk. This step happens very
-+ ** rarely (we hope!)
-+ */
-+ for(toFree=nBlock*16; toFree<(mem3.nPool*16); toFree *= 2){
-+ memsys3OutOfMemory(toFree);
-+ if( mem3.iMaster ){
-+ memsys3Link(mem3.iMaster);
-+ mem3.iMaster = 0;
-+ mem3.szMaster = 0;
-+ }
-+ for(i=0; i<N_HASH; i++){
-+ memsys3Merge(&mem3.aiHash[i]);
-+ }
-+ for(i=0; i<MX_SMALL-1; i++){
-+ memsys3Merge(&mem3.aiSmall[i]);
-+ }
-+ if( mem3.szMaster ){
-+ memsys3Unlink(mem3.iMaster);
-+ if( mem3.szMaster>=nBlock ){
-+ return memsys3FromMaster(nBlock);
-+ }
- }
-- sqlite3MemdebugSetType(p, MEMTYPE_SCRATCH);
- }
-- assert( sqlite3_mutex_notheld(mem0.mutex) );
--
--
--#if SQLITE_THREADSAFE==0 && !defined(NDEBUG)
-- /* Verify that no more than two scratch allocations per thread
-- ** are outstanding at one time. (This is only checked in the
-- ** single-threaded case since checking in the multi-threaded case
-- ** would be much more complicated.) */
-- assert( scratchAllocOut<=1 );
-- if( p ) scratchAllocOut++;
--#endif
-
-- return p;
-+ /* If none of the above worked, then we fail. */
-+ return 0;
- }
--SQLITE_PRIVATE void sqlite3ScratchFree(void *p){
-- if( p ){
-
--#if SQLITE_THREADSAFE==0 && !defined(NDEBUG)
-- /* Verify that no more than two scratch allocation per thread
-- ** is outstanding at one time. (This is only checked in the
-- ** single-threaded case since checking in the multi-threaded case
-- ** would be much more complicated.) */
-- assert( scratchAllocOut>=1 && scratchAllocOut<=2 );
-- scratchAllocOut--;
--#endif
-+/*
-+** Free an outstanding memory allocation.
-+**
-+** This function assumes that the necessary mutexes, if any, are
-+** already held by the caller. Hence "Unsafe".
-+*/
-+static void memsys3FreeUnsafe(void *pOld){
-+ Mem3Block *p = (Mem3Block*)pOld;
-+ int i;
-+ u32 size, x;
-+ assert( sqlite3_mutex_held(mem3.mutex) );
-+ assert( p>mem3.aPool && p<&mem3.aPool[mem3.nPool] );
-+ i = p - mem3.aPool;
-+ assert( (mem3.aPool[i-1].u.hdr.size4x&1)==1 );
-+ size = mem3.aPool[i-1].u.hdr.size4x/4;
-+ assert( i+size<=mem3.nPool+1 );
-+ mem3.aPool[i-1].u.hdr.size4x &= ~1;
-+ mem3.aPool[i+size-1].u.hdr.prevSize = size;
-+ mem3.aPool[i+size-1].u.hdr.size4x &= ~2;
-+ memsys3Link(i);
-
-- if( p>=sqlite3GlobalConfig.pScratch && p<mem0.pScratchEnd ){
-- /* Release memory from the SQLITE_CONFIG_SCRATCH allocation */
-- ScratchFreeslot *pSlot;
-- pSlot = (ScratchFreeslot*)p;
-- sqlite3_mutex_enter(mem0.mutex);
-- pSlot->pNext = mem0.pScratchFree;
-- mem0.pScratchFree = pSlot;
-- mem0.nScratchFree++;
-- assert( mem0.nScratchFree <= (u32)sqlite3GlobalConfig.nScratch );
-- sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_USED, -1);
-- sqlite3_mutex_leave(mem0.mutex);
-- }else{
-- /* Release memory back to the heap */
-- assert( sqlite3MemdebugHasType(p, MEMTYPE_SCRATCH) );
-- assert( sqlite3MemdebugNoType(p, ~MEMTYPE_SCRATCH) );
-- sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
-- if( sqlite3GlobalConfig.bMemstat ){
-- int iSize = sqlite3MallocSize(p);
-- sqlite3_mutex_enter(mem0.mutex);
-- sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_OVERFLOW, -iSize);
-- sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, -iSize);
-- sqlite3StatusAdd(SQLITE_STATUS_MALLOC_COUNT, -1);
-- sqlite3GlobalConfig.m.xFree(p);
-- sqlite3_mutex_leave(mem0.mutex);
-- }else{
-- sqlite3GlobalConfig.m.xFree(p);
-- }
-+ /* Try to expand the master using the newly freed chunk */
-+ if( mem3.iMaster ){
-+ while( (mem3.aPool[mem3.iMaster-1].u.hdr.size4x&2)==0 ){
-+ size = mem3.aPool[mem3.iMaster-1].u.hdr.prevSize;
-+ mem3.iMaster -= size;
-+ mem3.szMaster += size;
-+ memsys3Unlink(mem3.iMaster);
-+ x = mem3.aPool[mem3.iMaster-1].u.hdr.size4x & 2;
-+ mem3.aPool[mem3.iMaster-1].u.hdr.size4x = mem3.szMaster*4 | x;
-+ mem3.aPool[mem3.iMaster+mem3.szMaster-1].u.hdr.prevSize = mem3.szMaster;
-+ }
-+ x = mem3.aPool[mem3.iMaster-1].u.hdr.size4x & 2;
-+ while( (mem3.aPool[mem3.iMaster+mem3.szMaster-1].u.hdr.size4x&1)==0 ){
-+ memsys3Unlink(mem3.iMaster+mem3.szMaster);
-+ mem3.szMaster += mem3.aPool[mem3.iMaster+mem3.szMaster-1].u.hdr.size4x/4;
-+ mem3.aPool[mem3.iMaster-1].u.hdr.size4x = mem3.szMaster*4 | x;
-+ mem3.aPool[mem3.iMaster+mem3.szMaster-1].u.hdr.prevSize = mem3.szMaster;
- }
- }
- }
-
- /*
--** TRUE if p is a lookaside memory allocation from db
-+** Return the size of an outstanding allocation, in bytes. The
-+** size returned omits the 8-byte header overhead. This only
-+** works for chunks that are currently checked out.
- */
--#ifndef SQLITE_OMIT_LOOKASIDE
--static int isLookaside(sqlite3 *db, void *p){
-- return p && p>=db->lookaside.pStart && p<db->lookaside.pEnd;
-+static int memsys3Size(void *p){
-+ Mem3Block *pBlock;
-+ if( p==0 ) return 0;
-+ pBlock = (Mem3Block*)p;
-+ assert( (pBlock[-1].u.hdr.size4x&1)!=0 );
-+ return (pBlock[-1].u.hdr.size4x&~3)*2 - 4;
- }
--#else
--#define isLookaside(A,B) 0
--#endif
-
- /*
--** Return the size of a memory allocation previously obtained from
--** sqlite3Malloc() or sqlite3_malloc().
-+** Round up a request size to the next valid allocation size.
- */
--SQLITE_PRIVATE int sqlite3MallocSize(void *p){
-- assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) );
-- assert( sqlite3MemdebugNoType(p, MEMTYPE_DB) );
-- return sqlite3GlobalConfig.m.xSize(p);
--}
--SQLITE_PRIVATE int sqlite3DbMallocSize(sqlite3 *db, void *p){
-- assert( db==0 || sqlite3_mutex_held(db->mutex) );
-- if( db && isLookaside(db, p) ){
-- return db->lookaside.sz;
-+static int memsys3Roundup(int n){
-+ if( n<=12 ){
-+ return 12;
- }else{
-- assert( sqlite3MemdebugHasType(p, MEMTYPE_DB) );
-- assert( sqlite3MemdebugHasType(p, MEMTYPE_LOOKASIDE|MEMTYPE_HEAP) );
-- assert( db!=0 || sqlite3MemdebugNoType(p, MEMTYPE_LOOKASIDE) );
-- return sqlite3GlobalConfig.m.xSize(p);
-+ return ((n+11)&~7) - 4;
- }
- }
-
- /*
--** Free memory previously obtained from sqlite3Malloc().
-+** Allocate nBytes of memory.
- */
--SQLITE_API void sqlite3_free(void *p){
-- if( p==0 ) return; /* IMP: R-49053-54554 */
-- assert( sqlite3MemdebugNoType(p, MEMTYPE_DB) );
-- assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) );
-- if( sqlite3GlobalConfig.bMemstat ){
-- sqlite3_mutex_enter(mem0.mutex);
-- sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, -sqlite3MallocSize(p));
-- sqlite3StatusAdd(SQLITE_STATUS_MALLOC_COUNT, -1);
-- sqlite3GlobalConfig.m.xFree(p);
-- sqlite3_mutex_leave(mem0.mutex);
-- }else{
-- sqlite3GlobalConfig.m.xFree(p);
-- }
-+static void *memsys3Malloc(int nBytes){
-+ sqlite3_int64 *p;
-+ assert( nBytes>0 ); /* malloc.c filters out 0 byte requests */
-+ memsys3Enter();
-+ p = memsys3MallocUnsafe(nBytes);
-+ memsys3Leave();
-+ return (void*)p;
- }
-
- /*
--** Free memory that might be associated with a particular database
--** connection.
-+** Free memory.
- */
--SQLITE_PRIVATE void sqlite3DbFree(sqlite3 *db, void *p){
-- assert( db==0 || sqlite3_mutex_held(db->mutex) );
-- if( db ){
-- if( db->pnBytesFreed ){
-- *db->pnBytesFreed += sqlite3DbMallocSize(db, p);
-- return;
-- }
-- if( isLookaside(db, p) ){
-- LookasideSlot *pBuf = (LookasideSlot*)p;
--#if SQLITE_DEBUG
-- /* Trash all content in the buffer being freed */
-- memset(p, 0xaa, db->lookaside.sz);
--#endif
-- pBuf->pNext = db->lookaside.pFree;
-- db->lookaside.pFree = pBuf;
-- db->lookaside.nOut--;
-- return;
-- }
-- }
-- assert( sqlite3MemdebugHasType(p, MEMTYPE_DB) );
-- assert( sqlite3MemdebugHasType(p, MEMTYPE_LOOKASIDE|MEMTYPE_HEAP) );
-- assert( db!=0 || sqlite3MemdebugNoType(p, MEMTYPE_LOOKASIDE) );
-- sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
-- sqlite3_free(p);
-+static void memsys3Free(void *pPrior){
-+ assert( pPrior );
-+ memsys3Enter();
-+ memsys3FreeUnsafe(pPrior);
-+ memsys3Leave();
- }
-
- /*
- ** Change the size of an existing memory allocation
- */
--SQLITE_PRIVATE void *sqlite3Realloc(void *pOld, int nBytes){
-- int nOld, nNew, nDiff;
-- void *pNew;
-- if( pOld==0 ){
-- return sqlite3Malloc(nBytes); /* IMP: R-28354-25769 */
-+static void *memsys3Realloc(void *pPrior, int nBytes){
-+ int nOld;
-+ void *p;
-+ if( pPrior==0 ){
-+ return sqlite3_malloc(nBytes);
- }
- if( nBytes<=0 ){
-- sqlite3_free(pOld); /* IMP: R-31593-10574 */
-+ sqlite3_free(pPrior);
- return 0;
- }
-- if( nBytes>=0x7fffff00 ){
-- /* The 0x7ffff00 limit term is explained in comments on sqlite3Malloc() */
-- return 0;
-+ nOld = memsys3Size(pPrior);
-+ if( nBytes<=nOld && nBytes>=nOld-128 ){
-+ return pPrior;
- }
-- nOld = sqlite3MallocSize(pOld);
-- /* IMPLEMENTATION-OF: R-46199-30249 SQLite guarantees that the second
-- ** argument to xRealloc is always a value returned by a prior call to
-- ** xRoundup. */
-- nNew = sqlite3GlobalConfig.m.xRoundup(nBytes);
-- if( nOld==nNew ){
-- pNew = pOld;
-- }else if( sqlite3GlobalConfig.bMemstat ){
-- sqlite3_mutex_enter(mem0.mutex);
-- sqlite3StatusSet(SQLITE_STATUS_MALLOC_SIZE, nBytes);
-- nDiff = nNew - nOld;
-- if( sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED) >=
-- mem0.alarmThreshold-nDiff ){
-- sqlite3MallocAlarm(nDiff);
-- }
-- assert( sqlite3MemdebugHasType(pOld, MEMTYPE_HEAP) );
-- assert( sqlite3MemdebugNoType(pOld, ~MEMTYPE_HEAP) );
-- pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew);
-- if( pNew==0 && mem0.alarmCallback ){
-- sqlite3MallocAlarm(nBytes);
-- pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew);
-- }
-- if( pNew ){
-- nNew = sqlite3MallocSize(pNew);
-- sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, nNew-nOld);
-+ memsys3Enter();
-+ p = memsys3MallocUnsafe(nBytes);
-+ if( p ){
-+ if( nOld<nBytes ){
-+ memcpy(p, pPrior, nOld);
-+ }else{
-+ memcpy(p, pPrior, nBytes);
- }
-- sqlite3_mutex_leave(mem0.mutex);
-- }else{
-- pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew);
-+ memsys3FreeUnsafe(pPrior);
- }
-- assert( EIGHT_BYTE_ALIGNMENT(pNew) ); /* IMP: R-04675-44850 */
-- return pNew;
-+ memsys3Leave();
-+ return p;
- }
-
- /*
--** The public interface to sqlite3Realloc. Make sure that the memory
--** subsystem is initialized prior to invoking sqliteRealloc.
-+** Initialize this module.
- */
--SQLITE_API void *sqlite3_realloc(void *pOld, int n){
--#ifndef SQLITE_OMIT_AUTOINIT
-- if( sqlite3_initialize() ) return 0;
--#endif
-- return sqlite3Realloc(pOld, n);
--}
-+static int memsys3Init(void *NotUsed){
-+ UNUSED_PARAMETER(NotUsed);
-+ if( !sqlite3GlobalConfig.pHeap ){
-+ return SQLITE_ERROR;
-+ }
-
-+ /* Store a pointer to the memory block in global structure mem3. */
-+ assert( sizeof(Mem3Block)==8 );
-+ mem3.aPool = (Mem3Block *)sqlite3GlobalConfig.pHeap;
-+ mem3.nPool = (sqlite3GlobalConfig.nHeap / sizeof(Mem3Block)) - 2;
-
--/*
--** Allocate and zero memory.
--*/
--SQLITE_PRIVATE void *sqlite3MallocZero(int n){
-- void *p = sqlite3Malloc(n);
-- if( p ){
-- memset(p, 0, n);
-- }
-- return p;
-+ /* Initialize the master block. */
-+ mem3.szMaster = mem3.nPool;
-+ mem3.mnMaster = mem3.szMaster;
-+ mem3.iMaster = 1;
-+ mem3.aPool[0].u.hdr.size4x = (mem3.szMaster<<2) + 2;
-+ mem3.aPool[mem3.nPool].u.hdr.prevSize = mem3.nPool;
-+ mem3.aPool[mem3.nPool].u.hdr.size4x = 1;
-+
-+ return SQLITE_OK;
- }
-
- /*
--** Allocate and zero memory. If the allocation fails, make
--** the mallocFailed flag in the connection pointer.
-+** Deinitialize this module.
- */
--SQLITE_PRIVATE void *sqlite3DbMallocZero(sqlite3 *db, int n){
-- void *p = sqlite3DbMallocRaw(db, n);
-- if( p ){
-- memset(p, 0, n);
-- }
-- return p;
-+static void memsys3Shutdown(void *NotUsed){
-+ UNUSED_PARAMETER(NotUsed);
-+ mem3.mutex = 0;
-+ return;
- }
-
-+
-+
- /*
--** Allocate and zero memory. If the allocation fails, make
--** the mallocFailed flag in the connection pointer.
--**
--** If db!=0 and db->mallocFailed is true (indicating a prior malloc
--** failure on the same database connection) then always return 0.
--** Hence for a particular database connection, once malloc starts
--** failing, it fails consistently until mallocFailed is reset.
--** This is an important assumption. There are many places in the
--** code that do things like this:
--**
--** int *a = (int*)sqlite3DbMallocRaw(db, 100);
--** int *b = (int*)sqlite3DbMallocRaw(db, 200);
--** if( b ) a[10] = 9;
--**
--** In other words, if a subsequent malloc (ex: "b") worked, it is assumed
--** that all prior mallocs (ex: "a") worked too.
-+** Open the file indicated and write a log of all unfreed memory
-+** allocations into that log.
- */
--SQLITE_PRIVATE void *sqlite3DbMallocRaw(sqlite3 *db, int n){
-- void *p;
-- assert( db==0 || sqlite3_mutex_held(db->mutex) );
-- assert( db==0 || db->pnBytesFreed==0 );
--#ifndef SQLITE_OMIT_LOOKASIDE
-- if( db ){
-- LookasideSlot *pBuf;
-- if( db->mallocFailed ){
-- return 0;
-- }
-- if( db->lookaside.bEnabled ){
-- if( n>db->lookaside.sz ){
-- db->lookaside.anStat[1]++;
-- }else if( (pBuf = db->lookaside.pFree)==0 ){
-- db->lookaside.anStat[2]++;
-- }else{
-- db->lookaside.pFree = pBuf->pNext;
-- db->lookaside.nOut++;
-- db->lookaside.anStat[0]++;
-- if( db->lookaside.nOut>db->lookaside.mxOut ){
-- db->lookaside.mxOut = db->lookaside.nOut;
-- }
-- return (void*)pBuf;
-- }
-+SQLITE_PRIVATE void sqlite3Memsys3Dump(const char *zFilename){
-+#ifdef SQLITE_DEBUG
-+ FILE *out;
-+ u32 i, j;
-+ u32 size;
-+ if( zFilename==0 || zFilename[0]==0 ){
-+ out = stdout;
-+ }else{
-+ out = fopen(zFilename, "w");
-+ if( out==0 ){
-+ fprintf(stderr, "** Unable to output memory debug output log: %s **\n",
-+ zFilename);
-+ return;
- }
- }
--#else
-- if( db && db->mallocFailed ){
-- return 0;
-- }
--#endif
-- p = sqlite3Malloc(n);
-- if( !p && db ){
-- db->mallocFailed = 1;
-- }
-- sqlite3MemdebugSetType(p, MEMTYPE_DB |
-- ((db && db->lookaside.bEnabled) ? MEMTYPE_LOOKASIDE : MEMTYPE_HEAP));
-- return p;
--}
--
--/*
--** Resize the block of memory pointed to by p to n bytes. If the
--** resize fails, set the mallocFailed flag in the connection object.
--*/
--SQLITE_PRIVATE void *sqlite3DbRealloc(sqlite3 *db, void *p, int n){
-- void *pNew = 0;
-- assert( db!=0 );
-- assert( sqlite3_mutex_held(db->mutex) );
-- if( db->mallocFailed==0 ){
-- if( p==0 ){
-- return sqlite3DbMallocRaw(db, n);
-+ memsys3Enter();
-+ fprintf(out, "CHUNKS:\n");
-+ for(i=1; i<=mem3.nPool; i+=size/4){
-+ size = mem3.aPool[i-1].u.hdr.size4x;
-+ if( size/4<=1 ){
-+ fprintf(out, "%p size error\n", &mem3.aPool[i]);
-+ assert( 0 );
-+ break;
- }
-- if( isLookaside(db, p) ){
-- if( n<=db->lookaside.sz ){
-- return p;
-- }
-- pNew = sqlite3DbMallocRaw(db, n);
-- if( pNew ){
-- memcpy(pNew, p, db->lookaside.sz);
-- sqlite3DbFree(db, p);
-- }
-+ if( (size&1)==0 && mem3.aPool[i+size/4-1].u.hdr.prevSize!=size/4 ){
-+ fprintf(out, "%p tail size does not match\n", &mem3.aPool[i]);
-+ assert( 0 );
-+ break;
-+ }
-+ if( ((mem3.aPool[i+size/4-1].u.hdr.size4x&2)>>1)!=(size&1) ){
-+ fprintf(out, "%p tail checkout bit is incorrect\n", &mem3.aPool[i]);
-+ assert( 0 );
-+ break;
-+ }
-+ if( size&1 ){
-+ fprintf(out, "%p %6d bytes checked out\n", &mem3.aPool[i], (size/4)*8-8);
- }else{
-- assert( sqlite3MemdebugHasType(p, MEMTYPE_DB) );
-- assert( sqlite3MemdebugHasType(p, MEMTYPE_LOOKASIDE|MEMTYPE_HEAP) );
-- sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
-- pNew = sqlite3_realloc(p, n);
-- if( !pNew ){
-- sqlite3MemdebugSetType(p, MEMTYPE_DB|MEMTYPE_HEAP);
-- db->mallocFailed = 1;
-- }
-- sqlite3MemdebugSetType(pNew, MEMTYPE_DB |
-- (db->lookaside.bEnabled ? MEMTYPE_LOOKASIDE : MEMTYPE_HEAP));
-+ fprintf(out, "%p %6d bytes free%s\n", &mem3.aPool[i], (size/4)*8-8,
-+ i==mem3.iMaster ? " **master**" : "");
- }
- }
-- return pNew;
-+ for(i=0; i<MX_SMALL-1; i++){
-+ if( mem3.aiSmall[i]==0 ) continue;
-+ fprintf(out, "small(%2d):", i);
-+ for(j = mem3.aiSmall[i]; j>0; j=mem3.aPool[j].u.list.next){
-+ fprintf(out, " %p(%d)", &mem3.aPool[j],
-+ (mem3.aPool[j-1].u.hdr.size4x/4)*8-8);
-+ }
-+ fprintf(out, "\n");
-+ }
-+ for(i=0; i<N_HASH; i++){
-+ if( mem3.aiHash[i]==0 ) continue;
-+ fprintf(out, "hash(%2d):", i);
-+ for(j = mem3.aiHash[i]; j>0; j=mem3.aPool[j].u.list.next){
-+ fprintf(out, " %p(%d)", &mem3.aPool[j],
-+ (mem3.aPool[j-1].u.hdr.size4x/4)*8-8);
-+ }
-+ fprintf(out, "\n");
-+ }
-+ fprintf(out, "master=%d\n", mem3.iMaster);
-+ fprintf(out, "nowUsed=%d\n", mem3.nPool*8 - mem3.szMaster*8);
-+ fprintf(out, "mxUsed=%d\n", mem3.nPool*8 - mem3.mnMaster*8);
-+ sqlite3_mutex_leave(mem3.mutex);
-+ if( out==stdout ){
-+ fflush(stdout);
-+ }else{
-+ fclose(out);
-+ }
-+#else
-+ UNUSED_PARAMETER(zFilename);
-+#endif
- }
-
- /*
--** Attempt to reallocate p. If the reallocation fails, then free p
--** and set the mallocFailed flag in the database connection.
-+** This routine is the only routine in this file with external
-+** linkage.
-+**
-+** Populate the low-level memory allocation function pointers in
-+** sqlite3GlobalConfig.m with pointers to the routines in this file. The
-+** arguments specify the block of memory to manage.
-+**
-+** This routine is only called by sqlite3_config(), and therefore
-+** is not required to be threadsafe (it is not).
- */
--SQLITE_PRIVATE void *sqlite3DbReallocOrFree(sqlite3 *db, void *p, int n){
-- void *pNew;
-- pNew = sqlite3DbRealloc(db, p, n);
-- if( !pNew ){
-- sqlite3DbFree(db, p);
-- }
-- return pNew;
-+SQLITE_PRIVATE const sqlite3_mem_methods *sqlite3MemGetMemsys3(void){
-+ static const sqlite3_mem_methods mempoolMethods = {
-+ memsys3Malloc,
-+ memsys3Free,
-+ memsys3Realloc,
-+ memsys3Size,
-+ memsys3Roundup,
-+ memsys3Init,
-+ memsys3Shutdown,
-+ 0
-+ };
-+ return &mempoolMethods;
- }
-
-+#endif /* SQLITE_ENABLE_MEMSYS3 */
-+
-+/************** End of mem3.c ************************************************/
-+/************** Begin file mem5.c ********************************************/
- /*
--** Make a copy of a string in memory obtained from sqliteMalloc(). These
--** functions call sqlite3MallocRaw() directly instead of sqliteMalloc(). This
--** is because when memory debugging is turned on, these two functions are
--** called via macros that record the current file and line number in the
--** ThreadData structure.
-+** 2007 October 14
-+**
-+** The author disclaims copyright to this source code. In place of
-+** a legal notice, here is a blessing:
-+**
-+** May you do good and not evil.
-+** May you find forgiveness for yourself and forgive others.
-+** May you share freely, never taking more than you give.
-+**
-+*************************************************************************
-+** This file contains the C functions that implement a memory
-+** allocation subsystem for use by SQLite.
-+**
-+** This version of the memory allocation subsystem omits all
-+** use of malloc(). The application gives SQLite a block of memory
-+** before calling sqlite3_initialize() from which allocations
-+** are made and returned by the xMalloc() and xRealloc()
-+** implementations. Once sqlite3_initialize() has been called,
-+** the amount of memory available to SQLite is fixed and cannot
-+** be changed.
-+**
-+** This version of the memory allocation subsystem is included
-+** in the build only if SQLITE_ENABLE_MEMSYS5 is defined.
-+**
-+** This memory allocator uses the following algorithm:
-+**
-+** 1. All memory allocations sizes are rounded up to a power of 2.
-+**
-+** 2. If two adjacent free blocks are the halves of a larger block,
-+** then the two blocks are coalesed into the single larger block.
-+**
-+** 3. New memory is allocated from the first available free block.
-+**
-+** This algorithm is described in: J. M. Robson. "Bounds for Some Functions
-+** Concerning Dynamic Storage Allocation". Journal of the Association for
-+** Computing Machinery, Volume 21, Number 8, July 1974, pages 491-499.
-+**
-+** Let n be the size of the largest allocation divided by the minimum
-+** allocation size (after rounding all sizes up to a power of 2.) Let M
-+** be the maximum amount of memory ever outstanding at one time. Let
-+** N be the total amount of memory available for allocation. Robson
-+** proved that this memory allocator will never breakdown due to
-+** fragmentation as long as the following constraint holds:
-+**
-+** N >= M*(1 + log2(n)/2) - n + 1
-+**
-+** The sqlite3_status() logic tracks the maximum values of n and M so
-+** that an application can, at any time, verify this constraint.
- */
--SQLITE_PRIVATE char *sqlite3DbStrDup(sqlite3 *db, const char *z){
-- char *zNew;
-- size_t n;
-- if( z==0 ){
-- return 0;
-- }
-- n = sqlite3Strlen30(z) + 1;
-- assert( (n&0x7fffffff)==n );
-- zNew = sqlite3DbMallocRaw(db, (int)n);
-- if( zNew ){
-- memcpy(zNew, z, n);
-- }
-- return zNew;
--}
--SQLITE_PRIVATE char *sqlite3DbStrNDup(sqlite3 *db, const char *z, int n){
-- char *zNew;
-- if( z==0 ){
-- return 0;
-- }
-- assert( (n&0x7fffffff)==n );
-- zNew = sqlite3DbMallocRaw(db, n+1);
-- if( zNew ){
-- memcpy(zNew, z, n);
-- zNew[n] = 0;
-- }
-- return zNew;
--}
-
- /*
--** Create a string from the zFromat argument and the va_list that follows.
--** Store the string in memory obtained from sqliteMalloc() and make *pz
--** point to that string.
-+** This version of the memory allocator is used only when
-+** SQLITE_ENABLE_MEMSYS5 is defined.
- */
--SQLITE_PRIVATE void sqlite3SetString(char **pz, sqlite3 *db, const char *zFormat, ...){
-- va_list ap;
-- char *z;
--
-- va_start(ap, zFormat);
-- z = sqlite3VMPrintf(db, zFormat, ap);
-- va_end(ap);
-- sqlite3DbFree(db, *pz);
-- *pz = z;
--}
--
-+#ifdef SQLITE_ENABLE_MEMSYS5
-
- /*
--** This function must be called before exiting any API function (i.e.
--** returning control to the user) that has called sqlite3_malloc or
--** sqlite3_realloc.
--**
--** The returned value is normally a copy of the second argument to this
--** function. However, if a malloc() failure has occurred since the previous
--** invocation SQLITE_NOMEM is returned instead.
-+** A minimum allocation is an instance of the following structure.
-+** Larger allocations are an array of these structures where the
-+** size of the array is a power of 2.
- **
--** If the first argument, db, is not NULL and a malloc() error has occurred,
--** then the connection error-code (the value returned by sqlite3_errcode())
--** is set to SQLITE_NOMEM.
-+** The size of this object must be a power of two. That fact is
-+** verified in memsys5Init().
- */
--SQLITE_PRIVATE int sqlite3ApiExit(sqlite3* db, int rc){
-- /* If the db handle is not NULL, then we must hold the connection handle
-- ** mutex here. Otherwise the read (and possible write) of db->mallocFailed
-- ** is unsafe, as is the call to sqlite3Error().
-- */
-- assert( !db || sqlite3_mutex_held(db->mutex) );
-- if( db && (db->mallocFailed || rc==SQLITE_IOERR_NOMEM) ){
-- sqlite3Error(db, SQLITE_NOMEM, 0);
-- db->mallocFailed = 0;
-- rc = SQLITE_NOMEM;
-- }
-- return rc & (db ? db->errMask : 0xff);
--}
-+typedef struct Mem5Link Mem5Link;
-+struct Mem5Link {
-+ int next; /* Index of next free chunk */
-+ int prev; /* Index of previous free chunk */
-+};
-
--/************** End of malloc.c **********************************************/
--/************** Begin file printf.c ******************************************/
- /*
--** The "printf" code that follows dates from the 1980's. It is in
--** the public domain. The original comments are included here for
--** completeness. They are very out-of-date but might be useful as
--** an historical reference. Most of the "enhancements" have been backed
--** out so that the functionality is now the same as standard printf().
--**
--**************************************************************************
--**
--** This file contains code for a set of "printf"-like routines. These
--** routines format strings much like the printf() from the standard C
--** library, though the implementation here has enhancements to support
--** SQLlite.
-+** Maximum size of any allocation is ((1<<LOGMAX)*mem5.szAtom). Since
-+** mem5.szAtom is always at least 8 and 32-bit integers are used,
-+** it is not actually possible to reach this limit.
- */
-+#define LOGMAX 30
-
- /*
--** Conversion types fall into various categories as defined by the
--** following enumeration.
-+** Masks used for mem5.aCtrl[] elements.
- */
--#define etRADIX 1 /* Integer types. %d, %x, %o, and so forth */
--#define etFLOAT 2 /* Floating point. %f */
--#define etEXP 3 /* Exponentional notation. %e and %E */
--#define etGENERIC 4 /* Floating or exponential, depending on exponent. %g */
--#define etSIZE 5 /* Return number of characters processed so far. %n */
--#define etSTRING 6 /* Strings. %s */
--#define etDYNSTRING 7 /* Dynamically allocated strings. %z */
--#define etPERCENT 8 /* Percent symbol. %% */
--#define etCHARX 9 /* Characters. %c */
--/* The rest are extensions, not normally found in printf() */
--#define etSQLESCAPE 10 /* Strings with '\'' doubled. %q */
--#define etSQLESCAPE2 11 /* Strings with '\'' doubled and enclosed in '',
-- NULL pointers replaced by SQL NULL. %Q */
--#define etTOKEN 12 /* a pointer to a Token structure */
--#define etSRCLIST 13 /* a pointer to a SrcList */
--#define etPOINTER 14 /* The %p conversion */
--#define etSQLESCAPE3 15 /* %w -> Strings with '\"' doubled */
--#define etORDINAL 16 /* %r -> 1st, 2nd, 3rd, 4th, etc. English only */
-+#define CTRL_LOGSIZE 0x1f /* Log2 Size of this block */
-+#define CTRL_FREE 0x20 /* True if not checked out */
-
--#define etINVALID 0 /* Any unrecognized conversion type */
-+/*
-+** All of the static variables used by this module are collected
-+** into a single structure named "mem5". This is to keep the
-+** static variables organized and to reduce namespace pollution
-+** when this module is combined with other in the amalgamation.
-+*/
-+static SQLITE_WSD struct Mem5Global {
-+ /*
-+ ** Memory available for allocation
-+ */
-+ int szAtom; /* Smallest possible allocation in bytes */
-+ int nBlock; /* Number of szAtom sized blocks in zPool */
-+ u8 *zPool; /* Memory available to be allocated */
-+
-+ /*
-+ ** Mutex to control access to the memory allocation subsystem.
-+ */
-+ sqlite3_mutex *mutex;
-+
-+ /*
-+ ** Performance statistics
-+ */
-+ u64 nAlloc; /* Total number of calls to malloc */
-+ u64 totalAlloc; /* Total of all malloc calls - includes internal frag */
-+ u64 totalExcess; /* Total internal fragmentation */
-+ u32 currentOut; /* Current checkout, including internal fragmentation */
-+ u32 currentCount; /* Current number of distinct checkouts */
-+ u32 maxOut; /* Maximum instantaneous currentOut */
-+ u32 maxCount; /* Maximum instantaneous currentCount */
-+ u32 maxRequest; /* Largest allocation (exclusive of internal frag) */
-+
-+ /*
-+ ** Lists of free blocks. aiFreelist[0] is a list of free blocks of
-+ ** size mem5.szAtom. aiFreelist[1] holds blocks of size szAtom*2.
-+ ** and so forth.
-+ */
-+ int aiFreelist[LOGMAX+1];
-+
-+ /*
-+ ** Space for tracking which blocks are checked out and the size
-+ ** of each block. One byte per block.
-+ */
-+ u8 *aCtrl;
-
-+} mem5;
-
- /*
--** An "etByte" is an 8-bit unsigned value.
-+** Access the static variable through a macro for SQLITE_OMIT_WSD
- */
--typedef unsigned char etByte;
-+#define mem5 GLOBAL(struct Mem5Global, mem5)
-
- /*
--** Each builtin conversion character (ex: the 'd' in "%d") is described
--** by an instance of the following structure
-+** Assuming mem5.zPool is divided up into an array of Mem5Link
-+** structures, return a pointer to the idx-th such lik.
- */
--typedef struct et_info { /* Information about each format field */
-- char fmttype; /* The format field code letter */
-- etByte base; /* The base for radix conversion */
-- etByte flags; /* One or more of FLAG_ constants below */
-- etByte type; /* Conversion paradigm */
-- etByte charset; /* Offset into aDigits[] of the digits string */
-- etByte prefix; /* Offset into aPrefix[] of the prefix string */
--} et_info;
-+#define MEM5LINK(idx) ((Mem5Link *)(&mem5.zPool[(idx)*mem5.szAtom]))
-
- /*
--** Allowed values for et_info.flags
-+** Unlink the chunk at mem5.aPool[i] from list it is currently
-+** on. It should be found on mem5.aiFreelist[iLogsize].
- */
--#define FLAG_SIGNED 1 /* True if the value to convert is signed */
--#define FLAG_INTERN 2 /* True if for internal use only */
--#define FLAG_STRING 4 /* Allow infinity precision */
-+static void memsys5Unlink(int i, int iLogsize){
-+ int next, prev;
-+ assert( i>=0 && i<mem5.nBlock );
-+ assert( iLogsize>=0 && iLogsize<=LOGMAX );
-+ assert( (mem5.aCtrl[i] & CTRL_LOGSIZE)==iLogsize );
-
-+ next = MEM5LINK(i)->next;
-+ prev = MEM5LINK(i)->prev;
-+ if( prev<0 ){
-+ mem5.aiFreelist[iLogsize] = next;
-+ }else{
-+ MEM5LINK(prev)->next = next;
-+ }
-+ if( next>=0 ){
-+ MEM5LINK(next)->prev = prev;
-+ }
-+}
-
- /*
--** The following table is searched linearly, so it is good to put the
--** most frequently used conversion types first.
-+** Link the chunk at mem5.aPool[i] so that is on the iLogsize
-+** free list.
- */
--static const char aDigits[] = "0123456789ABCDEF0123456789abcdef";
--static const char aPrefix[] = "-x0\000X0";
--static const et_info fmtinfo[] = {
-- { 'd', 10, 1, etRADIX, 0, 0 },
-- { 's', 0, 4, etSTRING, 0, 0 },
-- { 'g', 0, 1, etGENERIC, 30, 0 },
-- { 'z', 0, 4, etDYNSTRING, 0, 0 },
-- { 'q', 0, 4, etSQLESCAPE, 0, 0 },
-- { 'Q', 0, 4, etSQLESCAPE2, 0, 0 },
-- { 'w', 0, 4, etSQLESCAPE3, 0, 0 },
-- { 'c', 0, 0, etCHARX, 0, 0 },
-- { 'o', 8, 0, etRADIX, 0, 2 },
-- { 'u', 10, 0, etRADIX, 0, 0 },
-- { 'x', 16, 0, etRADIX, 16, 1 },
-- { 'X', 16, 0, etRADIX, 0, 4 },
--#ifndef SQLITE_OMIT_FLOATING_POINT
-- { 'f', 0, 1, etFLOAT, 0, 0 },
-- { 'e', 0, 1, etEXP, 30, 0 },
-- { 'E', 0, 1, etEXP, 14, 0 },
-- { 'G', 0, 1, etGENERIC, 14, 0 },
--#endif
-- { 'i', 10, 1, etRADIX, 0, 0 },
-- { 'n', 0, 0, etSIZE, 0, 0 },
-- { '%', 0, 0, etPERCENT, 0, 0 },
-- { 'p', 16, 0, etPOINTER, 0, 1 },
-+static void memsys5Link(int i, int iLogsize){
-+ int x;
-+ assert( sqlite3_mutex_held(mem5.mutex) );
-+ assert( i>=0 && i<mem5.nBlock );
-+ assert( iLogsize>=0 && iLogsize<=LOGMAX );
-+ assert( (mem5.aCtrl[i] & CTRL_LOGSIZE)==iLogsize );
-
--/* All the rest have the FLAG_INTERN bit set and are thus for internal
--** use only */
-- { 'T', 0, 2, etTOKEN, 0, 0 },
-- { 'S', 0, 2, etSRCLIST, 0, 0 },
-- { 'r', 10, 3, etORDINAL, 0, 0 },
--};
-+ x = MEM5LINK(i)->next = mem5.aiFreelist[iLogsize];
-+ MEM5LINK(i)->prev = -1;
-+ if( x>=0 ){
-+ assert( x<mem5.nBlock );
-+ MEM5LINK(x)->prev = i;
-+ }
-+ mem5.aiFreelist[iLogsize] = i;
-+}
-
- /*
--** If SQLITE_OMIT_FLOATING_POINT is defined, then none of the floating point
--** conversions will work.
-+** If the STATIC_MEM mutex is not already held, obtain it now. The mutex
-+** will already be held (obtained by code in malloc.c) if
-+** sqlite3GlobalConfig.bMemStat is true.
- */
--#ifndef SQLITE_OMIT_FLOATING_POINT
-+static void memsys5Enter(void){
-+ sqlite3_mutex_enter(mem5.mutex);
-+}
-+static void memsys5Leave(void){
-+ sqlite3_mutex_leave(mem5.mutex);
-+}
-+
- /*
--** "*val" is a double such that 0.1 <= *val < 10.0
--** Return the ascii code for the leading digit of *val, then
--** multiply "*val" by 10.0 to renormalize.
--**
--** Example:
--** input: *val = 3.14159
--** output: *val = 1.4159 function return = '3'
--**
--** The counter *cnt is incremented each time. After counter exceeds
--** 16 (the number of significant digits in a 64-bit float) '0' is
--** always returned.
-+** Return the size of an outstanding allocation, in bytes. The
-+** size returned omits the 8-byte header overhead. This only
-+** works for chunks that are currently checked out.
- */
--static char et_getdigit(LONGDOUBLE_TYPE *val, int *cnt){
-- int digit;
-- LONGDOUBLE_TYPE d;
-- if( (*cnt)<=0 ) return '0';
-- (*cnt)--;
-- digit = (int)*val;
-- d = digit;
-- digit += '0';
-- *val = (*val - d)*10.0;
-- return (char)digit;
-+static int memsys5Size(void *p){
-+ int iSize = 0;
-+ if( p ){
-+ int i = ((u8 *)p-mem5.zPool)/mem5.szAtom;
-+ assert( i>=0 && i<mem5.nBlock );
-+ iSize = mem5.szAtom * (1 << (mem5.aCtrl[i]&CTRL_LOGSIZE));
-+ }
-+ return iSize;
- }
--#endif /* SQLITE_OMIT_FLOATING_POINT */
-
- /*
--** Append N space characters to the given string buffer.
-+** Find the first entry on the freelist iLogsize. Unlink that
-+** entry and return its index.
- */
--SQLITE_PRIVATE void sqlite3AppendSpace(StrAccum *pAccum, int N){
-- static const char zSpaces[] = " ";
-- while( N>=(int)sizeof(zSpaces)-1 ){
-- sqlite3StrAccumAppend(pAccum, zSpaces, sizeof(zSpaces)-1);
-- N -= sizeof(zSpaces)-1;
-- }
-- if( N>0 ){
-- sqlite3StrAccumAppend(pAccum, zSpaces, N);
-+static int memsys5UnlinkFirst(int iLogsize){
-+ int i;
-+ int iFirst;
-+
-+ assert( iLogsize>=0 && iLogsize<=LOGMAX );
-+ i = iFirst = mem5.aiFreelist[iLogsize];
-+ assert( iFirst>=0 );
-+ while( i>0 ){
-+ if( i<iFirst ) iFirst = i;
-+ i = MEM5LINK(i)->next;
- }
-+ memsys5Unlink(iFirst, iLogsize);
-+ return iFirst;
- }
-
- /*
--** On machines with a small stack size, you can redefine the
--** SQLITE_PRINT_BUF_SIZE to be something smaller, if desired.
-+** Return a block of memory of at least nBytes in size.
-+** Return NULL if unable. Return NULL if nBytes==0.
-+**
-+** The caller guarantees that nByte positive.
-+**
-+** The caller has obtained a mutex prior to invoking this
-+** routine so there is never any chance that two or more
-+** threads can be in this routine at the same time.
- */
--#ifndef SQLITE_PRINT_BUF_SIZE
--# define SQLITE_PRINT_BUF_SIZE 70
--#endif
--#define etBUFSIZE SQLITE_PRINT_BUF_SIZE /* Size of the output buffer */
-+static void *memsys5MallocUnsafe(int nByte){
-+ int i; /* Index of a mem5.aPool[] slot */
-+ int iBin; /* Index into mem5.aiFreelist[] */
-+ int iFullSz; /* Size of allocation rounded up to power of 2 */
-+ int iLogsize; /* Log2 of iFullSz/POW2_MIN */
-+
-+ /* nByte must be a positive */
-+ assert( nByte>0 );
-+
-+ /* Keep track of the maximum allocation request. Even unfulfilled
-+ ** requests are counted */
-+ if( (u32)nByte>mem5.maxRequest ){
-+ mem5.maxRequest = nByte;
-+ }
-+
-+ /* Abort if the requested allocation size is larger than the largest
-+ ** power of two that we can represent using 32-bit signed integers.
-+ */
-+ if( nByte > 0x40000000 ){
-+ return 0;
-+ }
-+
-+ /* Round nByte up to the next valid power of two */
-+ for(iFullSz=mem5.szAtom, iLogsize=0; iFullSz<nByte; iFullSz *= 2, iLogsize++){}
-+
-+ /* Make sure mem5.aiFreelist[iLogsize] contains at least one free
-+ ** block. If not, then split a block of the next larger power of
-+ ** two in order to create a new free block of size iLogsize.
-+ */
-+ for(iBin=iLogsize; mem5.aiFreelist[iBin]<0 && iBin<=LOGMAX; iBin++){}
-+ if( iBin>LOGMAX ){
-+ testcase( sqlite3GlobalConfig.xLog!=0 );
-+ sqlite3_log(SQLITE_NOMEM, "failed to allocate %u bytes", nByte);
-+ return 0;
-+ }
-+ i = memsys5UnlinkFirst(iBin);
-+ while( iBin>iLogsize ){
-+ int newSize;
-+
-+ iBin--;
-+ newSize = 1 << iBin;
-+ mem5.aCtrl[i+newSize] = CTRL_FREE | iBin;
-+ memsys5Link(i+newSize, iBin);
-+ }
-+ mem5.aCtrl[i] = iLogsize;
-+
-+ /* Update allocator performance statistics. */
-+ mem5.nAlloc++;
-+ mem5.totalAlloc += iFullSz;
-+ mem5.totalExcess += iFullSz - nByte;
-+ mem5.currentCount++;
-+ mem5.currentOut += iFullSz;
-+ if( mem5.maxCount<mem5.currentCount ) mem5.maxCount = mem5.currentCount;
-+ if( mem5.maxOut<mem5.currentOut ) mem5.maxOut = mem5.currentOut;
-+
-+ /* Return a pointer to the allocated memory. */
-+ return (void*)&mem5.zPool[i*mem5.szAtom];
-+}
-
- /*
--** Render a string given by "fmt" into the StrAccum object.
-+** Free an outstanding memory allocation.
- */
--SQLITE_PRIVATE void sqlite3VXPrintf(
-- StrAccum *pAccum, /* Accumulate results here */
-- int useExtended, /* Allow extended %-conversions */
-- const char *fmt, /* Format string */
-- va_list ap /* arguments */
--){
-- int c; /* Next character in the format string */
-- char *bufpt; /* Pointer to the conversion buffer */
-- int precision; /* Precision of the current field */
-- int length; /* Length of the field */
-- int idx; /* A general purpose loop counter */
-- int width; /* Width of the current field */
-- etByte flag_leftjustify; /* True if "-" flag is present */
-- etByte flag_plussign; /* True if "+" flag is present */
-- etByte flag_blanksign; /* True if " " flag is present */
-- etByte flag_alternateform; /* True if "#" flag is present */
-- etByte flag_altform2; /* True if "!" flag is present */
-- etByte flag_zeropad; /* True if field width constant starts with zero */
-- etByte flag_long; /* True if "l" flag is present */
-- etByte flag_longlong; /* True if the "ll" flag is present */
-- etByte done; /* Loop termination flag */
-- etByte xtype = 0; /* Conversion paradigm */
-- char prefix; /* Prefix character. "+" or "-" or " " or '\0'. */
-- sqlite_uint64 longvalue; /* Value for integer types */
-- LONGDOUBLE_TYPE realvalue; /* Value for real types */
-- const et_info *infop; /* Pointer to the appropriate info structure */
-- char *zOut; /* Rendering buffer */
-- int nOut; /* Size of the rendering buffer */
-- char *zExtra; /* Malloced memory used by some conversion */
--#ifndef SQLITE_OMIT_FLOATING_POINT
-- int exp, e2; /* exponent of real numbers */
-- int nsd; /* Number of significant digits returned */
-- double rounder; /* Used for rounding floating point values */
-- etByte flag_dp; /* True if decimal point should be shown */
-- etByte flag_rtz; /* True if trailing zeros should be removed */
--#endif
-- char buf[etBUFSIZE]; /* Conversion buffer */
-+static void memsys5FreeUnsafe(void *pOld){
-+ u32 size, iLogsize;
-+ int iBlock;
-
-- bufpt = 0;
-- for(; (c=(*fmt))!=0; ++fmt){
-- if( c!='%' ){
-- int amt;
-- bufpt = (char *)fmt;
-- amt = 1;
-- while( (c=(*++fmt))!='%' && c!=0 ) amt++;
-- sqlite3StrAccumAppend(pAccum, bufpt, amt);
-- if( c==0 ) break;
-- }
-- if( (c=(*++fmt))==0 ){
-- sqlite3StrAccumAppend(pAccum, "%", 1);
-- break;
-- }
-- /* Find out what flags are present */
-- flag_leftjustify = flag_plussign = flag_blanksign =
-- flag_alternateform = flag_altform2 = flag_zeropad = 0;
-- done = 0;
-- do{
-- switch( c ){
-- case '-': flag_leftjustify = 1; break;
-- case '+': flag_plussign = 1; break;
-- case ' ': flag_blanksign = 1; break;
-- case '#': flag_alternateform = 1; break;
-- case '!': flag_altform2 = 1; break;
-- case '0': flag_zeropad = 1; break;
-- default: done = 1; break;
-- }
-- }while( !done && (c=(*++fmt))!=0 );
-- /* Get the field width */
-- width = 0;
-- if( c=='*' ){
-- width = va_arg(ap,int);
-- if( width<0 ){
-- flag_leftjustify = 1;
-- width = -width;
-- }
-- c = *++fmt;
-+ /* Set iBlock to the index of the block pointed to by pOld in
-+ ** the array of mem5.szAtom byte blocks pointed to by mem5.zPool.
-+ */
-+ iBlock = ((u8 *)pOld-mem5.zPool)/mem5.szAtom;
-+
-+ /* Check that the pointer pOld points to a valid, non-free block. */
-+ assert( iBlock>=0 && iBlock<mem5.nBlock );
-+ assert( ((u8 *)pOld-mem5.zPool)%mem5.szAtom==0 );
-+ assert( (mem5.aCtrl[iBlock] & CTRL_FREE)==0 );
-+
-+ iLogsize = mem5.aCtrl[iBlock] & CTRL_LOGSIZE;
-+ size = 1<<iLogsize;
-+ assert( iBlock+size-1<(u32)mem5.nBlock );
-+
-+ mem5.aCtrl[iBlock] |= CTRL_FREE;
-+ mem5.aCtrl[iBlock+size-1] |= CTRL_FREE;
-+ assert( mem5.currentCount>0 );
-+ assert( mem5.currentOut>=(size*mem5.szAtom) );
-+ mem5.currentCount--;
-+ mem5.currentOut -= size*mem5.szAtom;
-+ assert( mem5.currentOut>0 || mem5.currentCount==0 );
-+ assert( mem5.currentCount>0 || mem5.currentOut==0 );
-+
-+ mem5.aCtrl[iBlock] = CTRL_FREE | iLogsize;
-+ while( ALWAYS(iLogsize<LOGMAX) ){
-+ int iBuddy;
-+ if( (iBlock>>iLogsize) & 1 ){
-+ iBuddy = iBlock - size;
- }else{
-- while( c>='0' && c<='9' ){
-- width = width*10 + c - '0';
-- c = *++fmt;
-- }
-+ iBuddy = iBlock + size;
- }
-- /* Get the precision */
-- if( c=='.' ){
-- precision = 0;
-- c = *++fmt;
-- if( c=='*' ){
-- precision = va_arg(ap,int);
-- if( precision<0 ) precision = -precision;
-- c = *++fmt;
-- }else{
-- while( c>='0' && c<='9' ){
-- precision = precision*10 + c - '0';
-- c = *++fmt;
-- }
-- }
-+ assert( iBuddy>=0 );
-+ if( (iBuddy+(1<<iLogsize))>mem5.nBlock ) break;
-+ if( mem5.aCtrl[iBuddy]!=(CTRL_FREE | iLogsize) ) break;
-+ memsys5Unlink(iBuddy, iLogsize);
-+ iLogsize++;
-+ if( iBuddy<iBlock ){
-+ mem5.aCtrl[iBuddy] = CTRL_FREE | iLogsize;
-+ mem5.aCtrl[iBlock] = 0;
-+ iBlock = iBuddy;
- }else{
-- precision = -1;
-+ mem5.aCtrl[iBlock] = CTRL_FREE | iLogsize;
-+ mem5.aCtrl[iBuddy] = 0;
- }
-- /* Get the conversion type modifier */
-- if( c=='l' ){
-- flag_long = 1;
-- c = *++fmt;
-- if( c=='l' ){
-- flag_longlong = 1;
-- c = *++fmt;
-- }else{
-- flag_longlong = 0;
-- }
-- }else{
-- flag_long = flag_longlong = 0;
-+ size *= 2;
-+ }
-+ memsys5Link(iBlock, iLogsize);
-+}
-+
-+/*
-+** Allocate nBytes of memory
-+*/
-+static void *memsys5Malloc(int nBytes){
-+ sqlite3_int64 *p = 0;
-+ if( nBytes>0 ){
-+ memsys5Enter();
-+ p = memsys5MallocUnsafe(nBytes);
-+ memsys5Leave();
-+ }
-+ return (void*)p;
-+}
-+
-+/*
-+** Free memory.
-+**
-+** The outer layer memory allocator prevents this routine from
-+** being called with pPrior==0.
-+*/
-+static void memsys5Free(void *pPrior){
-+ assert( pPrior!=0 );
-+ memsys5Enter();
-+ memsys5FreeUnsafe(pPrior);
-+ memsys5Leave();
-+}
-+
-+/*
-+** Change the size of an existing memory allocation.
-+**
-+** The outer layer memory allocator prevents this routine from
-+** being called with pPrior==0.
-+**
-+** nBytes is always a value obtained from a prior call to
-+** memsys5Round(). Hence nBytes is always a non-negative power
-+** of two. If nBytes==0 that means that an oversize allocation
-+** (an allocation larger than 0x40000000) was requested and this
-+** routine should return 0 without freeing pPrior.
-+*/
-+static void *memsys5Realloc(void *pPrior, int nBytes){
-+ int nOld;
-+ void *p;
-+ assert( pPrior!=0 );
-+ assert( (nBytes&(nBytes-1))==0 ); /* EV: R-46199-30249 */
-+ assert( nBytes>=0 );
-+ if( nBytes==0 ){
-+ return 0;
-+ }
-+ nOld = memsys5Size(pPrior);
-+ if( nBytes<=nOld ){
-+ return pPrior;
-+ }
-+ memsys5Enter();
-+ p = memsys5MallocUnsafe(nBytes);
-+ if( p ){
-+ memcpy(p, pPrior, nOld);
-+ memsys5FreeUnsafe(pPrior);
-+ }
-+ memsys5Leave();
-+ return p;
-+}
-+
-+/*
-+** Round up a request size to the next valid allocation size. If
-+** the allocation is too large to be handled by this allocation system,
-+** return 0.
-+**
-+** All allocations must be a power of two and must be expressed by a
-+** 32-bit signed integer. Hence the largest allocation is 0x40000000
-+** or 1073741824 bytes.
-+*/
-+static int memsys5Roundup(int n){
-+ int iFullSz;
-+ if( n > 0x40000000 ) return 0;
-+ for(iFullSz=mem5.szAtom; iFullSz<n; iFullSz *= 2);
-+ return iFullSz;
-+}
-+
-+/*
-+** Return the ceiling of the logarithm base 2 of iValue.
-+**
-+** Examples: memsys5Log(1) -> 0
-+** memsys5Log(2) -> 1
-+** memsys5Log(4) -> 2
-+** memsys5Log(5) -> 3
-+** memsys5Log(8) -> 3
-+** memsys5Log(9) -> 4
-+*/
-+static int memsys5Log(int iValue){
-+ int iLog;
-+ for(iLog=0; (iLog<(int)((sizeof(int)*8)-1)) && (1<<iLog)<iValue; iLog++);
-+ return iLog;
-+}
-+
-+/*
-+** Initialize the memory allocator.
-+**
-+** This routine is not threadsafe. The caller must be holding a mutex
-+** to prevent multiple threads from entering at the same time.
-+*/
-+static int memsys5Init(void *NotUsed){
-+ int ii; /* Loop counter */
-+ int nByte; /* Number of bytes of memory available to this allocator */
-+ u8 *zByte; /* Memory usable by this allocator */
-+ int nMinLog; /* Log base 2 of minimum allocation size in bytes */
-+ int iOffset; /* An offset into mem5.aCtrl[] */
-+
-+ UNUSED_PARAMETER(NotUsed);
-+
-+ /* For the purposes of this routine, disable the mutex */
-+ mem5.mutex = 0;
-+
-+ /* The size of a Mem5Link object must be a power of two. Verify that
-+ ** this is case.
-+ */
-+ assert( (sizeof(Mem5Link)&(sizeof(Mem5Link)-1))==0 );
-+
-+ nByte = sqlite3GlobalConfig.nHeap;
-+ zByte = (u8*)sqlite3GlobalConfig.pHeap;
-+ assert( zByte!=0 ); /* sqlite3_config() does not allow otherwise */
-+
-+ /* boundaries on sqlite3GlobalConfig.mnReq are enforced in sqlite3_config() */
-+ nMinLog = memsys5Log(sqlite3GlobalConfig.mnReq);
-+ mem5.szAtom = (1<<nMinLog);
-+ while( (int)sizeof(Mem5Link)>mem5.szAtom ){
-+ mem5.szAtom = mem5.szAtom << 1;
-+ }
-+
-+ mem5.nBlock = (nByte / (mem5.szAtom+sizeof(u8)));
-+ mem5.zPool = zByte;
-+ mem5.aCtrl = (u8 *)&mem5.zPool[mem5.nBlock*mem5.szAtom];
-+
-+ for(ii=0; ii<=LOGMAX; ii++){
-+ mem5.aiFreelist[ii] = -1;
-+ }
-+
-+ iOffset = 0;
-+ for(ii=LOGMAX; ii>=0; ii--){
-+ int nAlloc = (1<<ii);
-+ if( (iOffset+nAlloc)<=mem5.nBlock ){
-+ mem5.aCtrl[iOffset] = ii | CTRL_FREE;
-+ memsys5Link(iOffset, ii);
-+ iOffset += nAlloc;
- }
-- /* Fetch the info entry for the field */
-- infop = &fmtinfo[0];
-- xtype = etINVALID;
-- for(idx=0; idx<ArraySize(fmtinfo); idx++){
-- if( c==fmtinfo[idx].fmttype ){
-- infop = &fmtinfo[idx];
-- if( useExtended || (infop->flags & FLAG_INTERN)==0 ){
-- xtype = infop->type;
-- }else{
-- return;
-- }
-- break;
-- }
-+ assert((iOffset+nAlloc)>mem5.nBlock);
-+ }
-+
-+ /* If a mutex is required for normal operation, allocate one */
-+ if( sqlite3GlobalConfig.bMemstat==0 ){
-+ mem5.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM);
-+ }
-+
-+ return SQLITE_OK;
-+}
-+
-+/*
-+** Deinitialize this module.
-+*/
-+static void memsys5Shutdown(void *NotUsed){
-+ UNUSED_PARAMETER(NotUsed);
-+ mem5.mutex = 0;
-+ return;
-+}
-+
-+#ifdef SQLITE_TEST
-+/*
-+** Open the file indicated and write a log of all unfreed memory
-+** allocations into that log.
-+*/
-+SQLITE_PRIVATE void sqlite3Memsys5Dump(const char *zFilename){
-+ FILE *out;
-+ int i, j, n;
-+ int nMinLog;
-+
-+ if( zFilename==0 || zFilename[0]==0 ){
-+ out = stdout;
-+ }else{
-+ out = fopen(zFilename, "w");
-+ if( out==0 ){
-+ fprintf(stderr, "** Unable to output memory debug output log: %s **\n",
-+ zFilename);
-+ return;
- }
-- zExtra = 0;
-+ }
-+ memsys5Enter();
-+ nMinLog = memsys5Log(mem5.szAtom);
-+ for(i=0; i<=LOGMAX && i+nMinLog<32; i++){
-+ for(n=0, j=mem5.aiFreelist[i]; j>=0; j = MEM5LINK(j)->next, n++){}
-+ fprintf(out, "freelist items of size %d: %d\n", mem5.szAtom << i, n);
-+ }
-+ fprintf(out, "mem5.nAlloc = %llu\n", mem5.nAlloc);
-+ fprintf(out, "mem5.totalAlloc = %llu\n", mem5.totalAlloc);
-+ fprintf(out, "mem5.totalExcess = %llu\n", mem5.totalExcess);
-+ fprintf(out, "mem5.currentOut = %u\n", mem5.currentOut);
-+ fprintf(out, "mem5.currentCount = %u\n", mem5.currentCount);
-+ fprintf(out, "mem5.maxOut = %u\n", mem5.maxOut);
-+ fprintf(out, "mem5.maxCount = %u\n", mem5.maxCount);
-+ fprintf(out, "mem5.maxRequest = %u\n", mem5.maxRequest);
-+ memsys5Leave();
-+ if( out==stdout ){
-+ fflush(stdout);
-+ }else{
-+ fclose(out);
-+ }
-+}
-+#endif
-
-- /*
-- ** At this point, variables are initialized as follows:
-- **
-- ** flag_alternateform TRUE if a '#' is present.
-- ** flag_altform2 TRUE if a '!' is present.
-- ** flag_plussign TRUE if a '+' is present.
-- ** flag_leftjustify TRUE if a '-' is present or if the
-- ** field width was negative.
-- ** flag_zeropad TRUE if the width began with 0.
-- ** flag_long TRUE if the letter 'l' (ell) prefixed
-- ** the conversion character.
-- ** flag_longlong TRUE if the letter 'll' (ell ell) prefixed
-- ** the conversion character.
-- ** flag_blanksign TRUE if a ' ' is present.
-- ** width The specified field width. This is
-- ** always non-negative. Zero is the default.
-- ** precision The specified precision. The default
-- ** is -1.
-- ** xtype The class of the conversion.
-- ** infop Pointer to the appropriate info struct.
-+/*
-+** This routine is the only routine in this file with external
-+** linkage. It returns a pointer to a static sqlite3_mem_methods
-+** struct populated with the memsys5 methods.
-+*/
-+SQLITE_PRIVATE const sqlite3_mem_methods *sqlite3MemGetMemsys5(void){
-+ static const sqlite3_mem_methods memsys5Methods = {
-+ memsys5Malloc,
-+ memsys5Free,
-+ memsys5Realloc,
-+ memsys5Size,
-+ memsys5Roundup,
-+ memsys5Init,
-+ memsys5Shutdown,
-+ 0
-+ };
-+ return &memsys5Methods;
-+}
-+
-+#endif /* SQLITE_ENABLE_MEMSYS5 */
-+
-+/************** End of mem5.c ************************************************/
-+/************** Begin file mutex.c *******************************************/
-+/*
-+** 2007 August 14
++** 2010 February 23
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
@@ -14363,49857 +3830,72 @@
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
-+** This file contains the C functions that implement mutexes.
-+**
-+** This file contains code that is common across all mutex implementations.
-+*/
-+
-+#if defined(SQLITE_DEBUG) && !defined(SQLITE_MUTEX_OMIT)
-+/*
-+** For debugging purposes, record when the mutex subsystem is initialized
-+** and uninitialized so that we can assert() if there is an attempt to
-+** allocate a mutex while the system is uninitialized.
-+*/
-+static SQLITE_WSD int mutexIsInit = 0;
-+#endif /* SQLITE_DEBUG */
-+
-+
-+#ifndef SQLITE_MUTEX_OMIT
-+/*
-+** Initialize the mutex system.
-+*/
-+SQLITE_PRIVATE int sqlite3MutexInit(void){
-+ int rc = SQLITE_OK;
-+ if( !sqlite3GlobalConfig.mutex.xMutexAlloc ){
-+ /* If the xMutexAlloc method has not been set, then the user did not
-+ ** install a mutex implementation via sqlite3_config() prior to
-+ ** sqlite3_initialize() being called. This block copies pointers to
-+ ** the default implementation into the sqlite3GlobalConfig structure.
- */
-- switch( xtype ){
-- case etPOINTER:
-- flag_longlong = sizeof(char*)==sizeof(i64);
-- flag_long = sizeof(char*)==sizeof(long int);
-- /* Fall through into the next case */
-- case etORDINAL:
-- case etRADIX:
-- if( infop->flags & FLAG_SIGNED ){
-- i64 v;
-- if( flag_longlong ){
-- v = va_arg(ap,i64);
-- }else if( flag_long ){
-- v = va_arg(ap,long int);
-- }else{
-- v = va_arg(ap,int);
-- }
-- if( v<0 ){
-- if( v==SMALLEST_INT64 ){
-- longvalue = ((u64)1)<<63;
-- }else{
-- longvalue = -v;
-- }
-- prefix = '-';
-- }else{
-- longvalue = v;
-- if( flag_plussign ) prefix = '+';
-- else if( flag_blanksign ) prefix = ' ';
-- else prefix = 0;
-- }
-- }else{
-- if( flag_longlong ){
-- longvalue = va_arg(ap,u64);
-- }else if( flag_long ){
-- longvalue = va_arg(ap,unsigned long int);
-- }else{
-- longvalue = va_arg(ap,unsigned int);
-- }
-- prefix = 0;
-- }
-- if( longvalue==0 ) flag_alternateform = 0;
-- if( flag_zeropad && precision<width-(prefix!=0) ){
-- precision = width-(prefix!=0);
-- }
-- if( precision<etBUFSIZE-10 ){
-- nOut = etBUFSIZE;
-- zOut = buf;
-- }else{
-- nOut = precision + 10;
-- zOut = zExtra = sqlite3Malloc( nOut );
-- if( zOut==0 ){
-- pAccum->mallocFailed = 1;
-- return;
-- }
-- }
-- bufpt = &zOut[nOut-1];
-- if( xtype==etORDINAL ){
-- static const char zOrd[] = "thstndrd";
-- int x = (int)(longvalue % 10);
-- if( x>=4 || (longvalue/10)%10==1 ){
-- x = 0;
-- }
-- *(--bufpt) = zOrd[x*2+1];
-- *(--bufpt) = zOrd[x*2];
-- }
-- {
-- register const char *cset; /* Use registers for speed */
-- register int base;
-- cset = &aDigits[infop->charset];
-- base = infop->base;
-- do{ /* Convert to ascii */
-- *(--bufpt) = cset[longvalue%base];
-- longvalue = longvalue/base;
-- }while( longvalue>0 );
-- }
-- length = (int)(&zOut[nOut-1]-bufpt);
-- for(idx=precision-length; idx>0; idx--){
-- *(--bufpt) = '0'; /* Zero pad */
-- }
-- if( prefix ) *(--bufpt) = prefix; /* Add sign */
-- if( flag_alternateform && infop->prefix ){ /* Add "0" or "0x" */
-- const char *pre;
-- char x;
-- pre = &aPrefix[infop->prefix];
-- for(; (x=(*pre))!=0; pre++) *(--bufpt) = x;
-- }
-- length = (int)(&zOut[nOut-1]-bufpt);
-- break;
-- case etFLOAT:
-- case etEXP:
-- case etGENERIC:
-- realvalue = va_arg(ap,double);
--#ifdef SQLITE_OMIT_FLOATING_POINT
-- length = 0;
--#else
-- if( precision<0 ) precision = 6; /* Set default precision */
-- if( realvalue<0.0 ){
-- realvalue = -realvalue;
-- prefix = '-';
-- }else{
-- if( flag_plussign ) prefix = '+';
-- else if( flag_blanksign ) prefix = ' ';
-- else prefix = 0;
-- }
-- if( xtype==etGENERIC && precision>0 ) precision--;
--#if 0
-- /* Rounding works like BSD when the constant 0.4999 is used. Wierd! */
-- for(idx=precision, rounder=0.4999; idx>0; idx--, rounder*=0.1);
--#else
-- /* It makes more sense to use 0.5 */
-- for(idx=precision, rounder=0.5; idx>0; idx--, rounder*=0.1){}
--#endif
-- if( xtype==etFLOAT ) realvalue += rounder;
-- /* Normalize realvalue to within 10.0 > realvalue >= 1.0 */
-- exp = 0;
-- if( sqlite3IsNaN((double)realvalue) ){
-- bufpt = "NaN";
-- length = 3;
-- break;
-- }
-- if( realvalue>0.0 ){
-- LONGDOUBLE_TYPE scale = 1.0;
-- while( realvalue>=1e100*scale && exp<=350 ){ scale *= 1e100;exp+=100;}
-- while( realvalue>=1e64*scale && exp<=350 ){ scale *= 1e64; exp+=64; }
-- while( realvalue>=1e8*scale && exp<=350 ){ scale *= 1e8; exp+=8; }
-- while( realvalue>=10.0*scale && exp<=350 ){ scale *= 10.0; exp++; }
-- realvalue /= scale;
-- while( realvalue<1e-8 ){ realvalue *= 1e8; exp-=8; }
-- while( realvalue<1.0 ){ realvalue *= 10.0; exp--; }
-- if( exp>350 ){
-- if( prefix=='-' ){
-- bufpt = "-Inf";
-- }else if( prefix=='+' ){
-- bufpt = "+Inf";
-- }else{
-- bufpt = "Inf";
-- }
-- length = sqlite3Strlen30(bufpt);
-- break;
-- }
-- }
-- bufpt = buf;
-- /*
-- ** If the field type is etGENERIC, then convert to either etEXP
-- ** or etFLOAT, as appropriate.
-- */
-- if( xtype!=etFLOAT ){
-- realvalue += rounder;
-- if( realvalue>=10.0 ){ realvalue *= 0.1; exp++; }
-- }
-- if( xtype==etGENERIC ){
-- flag_rtz = !flag_alternateform;
-- if( exp<-4 || exp>precision ){
-- xtype = etEXP;
-- }else{
-- precision = precision - exp;
-- xtype = etFLOAT;
-- }
-- }else{
-- flag_rtz = flag_altform2;
-- }
-- if( xtype==etEXP ){
-- e2 = 0;
-- }else{
-- e2 = exp;
-- }
-- if( e2+precision+width > etBUFSIZE - 15 ){
-- bufpt = zExtra = sqlite3Malloc( e2+precision+width+15 );
-- if( bufpt==0 ){
-- pAccum->mallocFailed = 1;
-- return;
-- }
-- }
-- zOut = bufpt;
-- nsd = 16 + flag_altform2*10;
-- flag_dp = (precision>0 ?1:0) | flag_alternateform | flag_altform2;
-- /* The sign in front of the number */
-- if( prefix ){
-- *(bufpt++) = prefix;
-- }
-- /* Digits prior to the decimal point */
-- if( e2<0 ){
-- *(bufpt++) = '0';
-- }else{
-- for(; e2>=0; e2--){
-- *(bufpt++) = et_getdigit(&realvalue,&nsd);
-- }
-- }
-- /* The decimal point */
-- if( flag_dp ){
-- *(bufpt++) = '.';
-- }
-- /* "0" digits after the decimal point but before the first
-- ** significant digit of the number */
-- for(e2++; e2<0; precision--, e2++){
-- assert( precision>0 );
-- *(bufpt++) = '0';
-- }
-- /* Significant digits after the decimal point */
-- while( (precision--)>0 ){
-- *(bufpt++) = et_getdigit(&realvalue,&nsd);
-- }
-- /* Remove trailing zeros and the "." if no digits follow the "." */
-- if( flag_rtz && flag_dp ){
-- while( bufpt[-1]=='0' ) *(--bufpt) = 0;
-- assert( bufpt>zOut );
-- if( bufpt[-1]=='.' ){
-- if( flag_altform2 ){
-- *(bufpt++) = '0';
-- }else{
-- *(--bufpt) = 0;
-- }
-- }
-- }
-- /* Add the "eNNN" suffix */
-- if( xtype==etEXP ){
-- *(bufpt++) = aDigits[infop->charset];
-- if( exp<0 ){
-- *(bufpt++) = '-'; exp = -exp;
-- }else{
-- *(bufpt++) = '+';
-- }
-- if( exp>=100 ){
-- *(bufpt++) = (char)((exp/100)+'0'); /* 100's digit */
-- exp %= 100;
-- }
-- *(bufpt++) = (char)(exp/10+'0'); /* 10's digit */
-- *(bufpt++) = (char)(exp%10+'0'); /* 1's digit */
-- }
-- *bufpt = 0;
--
-- /* The converted number is in buf[] and zero terminated. Output it.
-- ** Note that the number is in the usual order, not reversed as with
-- ** integer conversions. */
-- length = (int)(bufpt-zOut);
-- bufpt = zOut;
--
-- /* Special case: Add leading zeros if the flag_zeropad flag is
-- ** set and we are not left justified */
-- if( flag_zeropad && !flag_leftjustify && length < width){
-- int i;
-- int nPad = width - length;
-- for(i=width; i>=nPad; i--){
-- bufpt[i] = bufpt[i-nPad];
-- }
-- i = prefix!=0;
-- while( nPad-- ) bufpt[i++] = '0';
-- length = width;
-- }
--#endif /* !defined(SQLITE_OMIT_FLOATING_POINT) */
-- break;
-- case etSIZE:
-- *(va_arg(ap,int*)) = pAccum->nChar;
-- length = width = 0;
-- break;
-- case etPERCENT:
-- buf[0] = '%';
-- bufpt = buf;
-- length = 1;
-- break;
-- case etCHARX:
-- c = va_arg(ap,int);
-- buf[0] = (char)c;
-- if( precision>=0 ){
-- for(idx=1; idx<precision; idx++) buf[idx] = (char)c;
-- length = precision;
-- }else{
-- length =1;
-- }
-- bufpt = buf;
-- break;
-- case etSTRING:
-- case etDYNSTRING:
-- bufpt = va_arg(ap,char*);
-- if( bufpt==0 ){
-- bufpt = "";
-- }else if( xtype==etDYNSTRING ){
-- zExtra = bufpt;
-- }
-- if( precision>=0 ){
-- for(length=0; length<precision && bufpt[length]; length++){}
-- }else{
-- length = sqlite3Strlen30(bufpt);
-- }
-- break;
-- case etSQLESCAPE:
-- case etSQLESCAPE2:
-- case etSQLESCAPE3: {
-- int i, j, k, n, isnull;
-- int needQuote;
-- char ch;
-- char q = ((xtype==etSQLESCAPE3)?'"':'\''); /* Quote character */
-- char *escarg = va_arg(ap,char*);
-- isnull = escarg==0;
-- if( isnull ) escarg = (xtype==etSQLESCAPE2 ? "NULL" : "(NULL)");
-- k = precision;
-- for(i=n=0; k!=0 && (ch=escarg[i])!=0; i++, k--){
-- if( ch==q ) n++;
-- }
-- needQuote = !isnull && xtype==etSQLESCAPE2;
-- n += i + 1 + needQuote*2;
-- if( n>etBUFSIZE ){
-- bufpt = zExtra = sqlite3Malloc( n );
-- if( bufpt==0 ){
-- pAccum->mallocFailed = 1;
-- return;
-- }
-- }else{
-- bufpt = buf;
-- }
-- j = 0;
-- if( needQuote ) bufpt[j++] = q;
-- k = i;
-- for(i=0; i<k; i++){
-- bufpt[j++] = ch = escarg[i];
-- if( ch==q ) bufpt[j++] = ch;
-- }
-- if( needQuote ) bufpt[j++] = q;
-- bufpt[j] = 0;
-- length = j;
-- /* The precision in %q and %Q means how many input characters to
-- ** consume, not the length of the output...
-- ** if( precision>=0 && precision<length ) length = precision; */
-- break;
-- }
-- case etTOKEN: {
-- Token *pToken = va_arg(ap, Token*);
-- if( pToken ){
-- sqlite3StrAccumAppend(pAccum, (const char*)pToken->z, pToken->n);
-- }
-- length = width = 0;
-- break;
-- }
-- case etSRCLIST: {
-- SrcList *pSrc = va_arg(ap, SrcList*);
-- int k = va_arg(ap, int);
-- struct SrcList_item *pItem = &pSrc->a[k];
-- assert( k>=0 && k<pSrc->nSrc );
-- if( pItem->zDatabase ){
-- sqlite3StrAccumAppend(pAccum, pItem->zDatabase, -1);
-- sqlite3StrAccumAppend(pAccum, ".", 1);
-- }
-- sqlite3StrAccumAppend(pAccum, pItem->zName, -1);
-- length = width = 0;
-- break;
-- }
-- default: {
-- assert( xtype==etINVALID );
-- return;
-- }
-- }/* End switch over the format type */
-- /*
-- ** The text of the conversion is pointed to by "bufpt" and is
-- ** "length" characters long. The field width is "width". Do
-- ** the output.
-- */
-- if( !flag_leftjustify ){
-- register int nspace;
-- nspace = width-length;
-- if( nspace>0 ){
-- sqlite3AppendSpace(pAccum, nspace);
-- }
-- }
-- if( length>0 ){
-- sqlite3StrAccumAppend(pAccum, bufpt, length);
-- }
-- if( flag_leftjustify ){
-- register int nspace;
-- nspace = width-length;
-- if( nspace>0 ){
-- sqlite3AppendSpace(pAccum, nspace);
-- }
-- }
-- sqlite3_free(zExtra);
-- }/* End for loop over the format string */
--} /* End of function */
-+ sqlite3_mutex_methods const *pFrom;
-+ sqlite3_mutex_methods *pTo = &sqlite3GlobalConfig.mutex;
-
--/*
--** Append N bytes of text from z to the StrAccum object.
--*/
--SQLITE_PRIVATE void sqlite3StrAccumAppend(StrAccum *p, const char *z, int N){
-- assert( z!=0 || N==0 );
-- if( p->tooBig | p->mallocFailed ){
-- testcase(p->tooBig);
-- testcase(p->mallocFailed);
-- return;
-- }
-- assert( p->zText!=0 || p->nChar==0 );
-- if( N<0 ){
-- N = sqlite3Strlen30(z);
-- }
-- if( N==0 || NEVER(z==0) ){
-- return;
-- }
-- if( p->nChar+N >= p->nAlloc ){
-- char *zNew;
-- if( !p->useMalloc ){
-- p->tooBig = 1;
-- N = p->nAlloc - p->nChar - 1;
-- if( N<=0 ){
-- return;
-- }
-+ if( sqlite3GlobalConfig.bCoreMutex ){
-+ pFrom = sqlite3DefaultMutex();
- }else{
-- char *zOld = (p->zText==p->zBase ? 0 : p->zText);
-- i64 szNew = p->nChar;
-- szNew += N + 1;
-- if( szNew > p->mxAlloc ){
-- sqlite3StrAccumReset(p);
-- p->tooBig = 1;
-- return;
-- }else{
-- p->nAlloc = (int)szNew;
-- }
-- if( p->useMalloc==1 ){
-- zNew = sqlite3DbRealloc(p->db, zOld, p->nAlloc);
-- }else{
-- zNew = sqlite3_realloc(zOld, p->nAlloc);
-- }
-- if( zNew ){
-- if( zOld==0 && p->nChar>0 ) memcpy(zNew, p->zText, p->nChar);
-- p->zText = zNew;
-- }else{
-- p->mallocFailed = 1;
-- sqlite3StrAccumReset(p);
-- return;
-- }
-+ pFrom = sqlite3NoopMutex();
- }
-+ memcpy(pTo, pFrom, offsetof(sqlite3_mutex_methods, xMutexAlloc));
-+ memcpy(&pTo->xMutexFree, &pFrom->xMutexFree,
-+ sizeof(*pTo) - offsetof(sqlite3_mutex_methods, xMutexFree));
-+ pTo->xMutexAlloc = pFrom->xMutexAlloc;
- }
-- assert( p->zText );
-- memcpy(&p->zText[p->nChar], z, N);
-- p->nChar += N;
-+ rc = sqlite3GlobalConfig.mutex.xMutexInit();
-+
-+#ifdef SQLITE_DEBUG
-+ GLOBAL(int, mutexIsInit) = 1;
-+#endif
-+
-+ return rc;
- }
-
- /*
--** Finish off a string by making sure it is zero-terminated.
--** Return a pointer to the resulting string. Return a NULL
--** pointer if any kind of error was encountered.
-+** Shutdown the mutex system. This call frees resources allocated by
-+** sqlite3MutexInit().
- */
--SQLITE_PRIVATE char *sqlite3StrAccumFinish(StrAccum *p){
-- if( p->zText ){
-- p->zText[p->nChar] = 0;
-- if( p->useMalloc && p->zText==p->zBase ){
-- if( p->useMalloc==1 ){
-- p->zText = sqlite3DbMallocRaw(p->db, p->nChar+1 );
-- }else{
-- p->zText = sqlite3_malloc(p->nChar+1);
-- }
-- if( p->zText ){
-- memcpy(p->zText, p->zBase, p->nChar+1);
-- }else{
-- p->mallocFailed = 1;
-- }
-- }
-+SQLITE_PRIVATE int sqlite3MutexEnd(void){
-+ int rc = SQLITE_OK;
-+ if( sqlite3GlobalConfig.mutex.xMutexEnd ){
-+ rc = sqlite3GlobalConfig.mutex.xMutexEnd();
- }
-- return p->zText;
-+
-+#ifdef SQLITE_DEBUG
-+ GLOBAL(int, mutexIsInit) = 0;
-+#endif
-+
-+ return rc;
- }
-
- /*
--** Reset an StrAccum string. Reclaim all malloced memory.
-+** Retrieve a pointer to a static mutex or allocate a new dynamic one.
- */
--SQLITE_PRIVATE void sqlite3StrAccumReset(StrAccum *p){
-- if( p->zText!=p->zBase ){
-- if( p->useMalloc==1 ){
-- sqlite3DbFree(p->db, p->zText);
-- }else{
-- sqlite3_free(p->zText);
-- }
-- }
-- p->zText = 0;
-+SQLITE_API sqlite3_mutex *sqlite3_mutex_alloc(int id){
-+#ifndef SQLITE_OMIT_AUTOINIT
-+ if( sqlite3_initialize() ) return 0;
-+#endif
-+ return sqlite3GlobalConfig.mutex.xMutexAlloc(id);
- }
-
--/*
--** Initialize a string accumulator
--*/
--SQLITE_PRIVATE void sqlite3StrAccumInit(StrAccum *p, char *zBase, int n, int mx){
-- p->zText = p->zBase = zBase;
-- p->db = 0;
-- p->nChar = 0;
-- p->nAlloc = n;
-- p->mxAlloc = mx;
-- p->useMalloc = 1;
-- p->tooBig = 0;
-- p->mallocFailed = 0;
-+SQLITE_PRIVATE sqlite3_mutex *sqlite3MutexAlloc(int id){
-+ if( !sqlite3GlobalConfig.bCoreMutex ){
-+ return 0;
-+ }
-+ assert( GLOBAL(int, mutexIsInit) );
-+ return sqlite3GlobalConfig.mutex.xMutexAlloc(id);
- }
-
- /*
--** Print into memory obtained from sqliteMalloc(). Use the internal
--** %-conversion extensions.
-+** Free a dynamic mutex.
- */
--SQLITE_PRIVATE char *sqlite3VMPrintf(sqlite3 *db, const char *zFormat, va_list ap){
-- char *z;
-- char zBase[SQLITE_PRINT_BUF_SIZE];
-- StrAccum acc;
-- assert( db!=0 );
-- sqlite3StrAccumInit(&acc, zBase, sizeof(zBase),
-- db->aLimit[SQLITE_LIMIT_LENGTH]);
-- acc.db = db;
-- sqlite3VXPrintf(&acc, 1, zFormat, ap);
-- z = sqlite3StrAccumFinish(&acc);
-- if( acc.mallocFailed ){
-- db->mallocFailed = 1;
-+SQLITE_API void sqlite3_mutex_free(sqlite3_mutex *p){
-+ if( p ){
-+ sqlite3GlobalConfig.mutex.xMutexFree(p);
- }
-- return z;
- }
-
- /*
--** Print into memory obtained from sqliteMalloc(). Use the internal
--** %-conversion extensions.
-+** Obtain the mutex p. If some other thread already has the mutex, block
-+** until it can be obtained.
- */
--SQLITE_PRIVATE char *sqlite3MPrintf(sqlite3 *db, const char *zFormat, ...){
-- va_list ap;
-- char *z;
-- va_start(ap, zFormat);
-- z = sqlite3VMPrintf(db, zFormat, ap);
-- va_end(ap);
-- return z;
-+SQLITE_API void sqlite3_mutex_enter(sqlite3_mutex *p){
-+ if( p ){
-+ sqlite3GlobalConfig.mutex.xMutexEnter(p);
-+ }
- }
-
- /*
--** Like sqlite3MPrintf(), but call sqlite3DbFree() on zStr after formatting
--** the string and before returnning. This routine is intended to be used
--** to modify an existing string. For example:
--**
--** x = sqlite3MPrintf(db, x, "prefix %s suffix", x);
--**
-+** Obtain the mutex p. If successful, return SQLITE_OK. Otherwise, if another
-+** thread holds the mutex and it cannot be obtained, return SQLITE_BUSY.
- */
--SQLITE_PRIVATE char *sqlite3MAppendf(sqlite3 *db, char *zStr, const char *zFormat, ...){
-- va_list ap;
-- char *z;
-- va_start(ap, zFormat);
-- z = sqlite3VMPrintf(db, zFormat, ap);
-- va_end(ap);
-- sqlite3DbFree(db, zStr);
-- return z;
-+SQLITE_API int sqlite3_mutex_try(sqlite3_mutex *p){
-+ int rc = SQLITE_OK;
-+ if( p ){
-+ return sqlite3GlobalConfig.mutex.xMutexTry(p);
-+ }
-+ return rc;
- }
-
- /*
--** Print into memory obtained from sqlite3_malloc(). Omit the internal
--** %-conversion extensions.
-+** The sqlite3_mutex_leave() routine exits a mutex that was previously
-+** entered by the same thread. The behavior is undefined if the mutex
-+** is not currently entered. If a NULL pointer is passed as an argument
-+** this function is a no-op.
- */
--SQLITE_API char *sqlite3_vmprintf(const char *zFormat, va_list ap){
-- char *z;
-- char zBase[SQLITE_PRINT_BUF_SIZE];
-- StrAccum acc;
--#ifndef SQLITE_OMIT_AUTOINIT
-- if( sqlite3_initialize() ) return 0;
--#endif
-- sqlite3StrAccumInit(&acc, zBase, sizeof(zBase), SQLITE_MAX_LENGTH);
-- acc.useMalloc = 2;
-- sqlite3VXPrintf(&acc, 0, zFormat, ap);
-- z = sqlite3StrAccumFinish(&acc);
-- return z;
-+SQLITE_API void sqlite3_mutex_leave(sqlite3_mutex *p){
-+ if( p ){
-+ sqlite3GlobalConfig.mutex.xMutexLeave(p);
-+ }
- }
-
-+#ifndef NDEBUG
- /*
--** Print into memory obtained from sqlite3_malloc()(). Omit the internal
--** %-conversion extensions.
-+** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are
-+** intended for use inside assert() statements.
- */
--SQLITE_API char *sqlite3_mprintf(const char *zFormat, ...){
-- va_list ap;
-- char *z;
--#ifndef SQLITE_OMIT_AUTOINIT
-- if( sqlite3_initialize() ) return 0;
--#endif
-- va_start(ap, zFormat);
-- z = sqlite3_vmprintf(zFormat, ap);
-- va_end(ap);
-- return z;
-+SQLITE_API int sqlite3_mutex_held(sqlite3_mutex *p){
-+ return p==0 || sqlite3GlobalConfig.mutex.xMutexHeld(p);
- }
-+SQLITE_API int sqlite3_mutex_notheld(sqlite3_mutex *p){
-+ return p==0 || sqlite3GlobalConfig.mutex.xMutexNotheld(p);
-+}
-+#endif
-
-+#endif /* !defined(SQLITE_MUTEX_OMIT) */
-+
-+/************** End of mutex.c ***********************************************/
-+/************** Begin file mutex_noop.c **************************************/
- /*
--** sqlite3_snprintf() works like snprintf() except that it ignores the
--** current locale settings. This is important for SQLite because we
--** are not able to use a "," as the decimal point in place of "." as
--** specified by some locales.
-+** 2008 October 07
- **
--** Oops: The first two arguments of sqlite3_snprintf() are backwards
--** from the snprintf() standard. Unfortunately, it is too late to change
--** this without breaking compatibility, so we just have to live with the
--** mistake.
-+** The author disclaims copyright to this source code. In place of
-+** a legal notice, here is a blessing:
- **
--** sqlite3_vsnprintf() is the varargs version.
-+** May you do good and not evil.
-+** May you find forgiveness for yourself and forgive others.
-+** May you share freely, never taking more than you give.
-+**
-+*************************************************************************
-+** This file contains the C functions that implement mutexes.
-+**
-+** This implementation in this file does not provide any mutual
-+** exclusion and is thus suitable for use only in applications
-+** that use SQLite in a single thread. The routines defined
-+** here are place-holders. Applications can substitute working
-+** mutex routines at start-time using the
-+**
-+** sqlite3_config(SQLITE_CONFIG_MUTEX,...)
-+**
-+** interface.
-+**
-+** If compiled with SQLITE_DEBUG, then additional logic is inserted
-+** that does error checking on mutexes to make sure they are being
-+** called correctly.
- */
--SQLITE_API char *sqlite3_vsnprintf(int n, char *zBuf, const char *zFormat, va_list ap){
-- StrAccum acc;
-- if( n<=0 ) return zBuf;
-- sqlite3StrAccumInit(&acc, zBuf, n, 0);
-- acc.useMalloc = 0;
-- sqlite3VXPrintf(&acc, 0, zFormat, ap);
-- return sqlite3StrAccumFinish(&acc);
--}
--SQLITE_API char *sqlite3_snprintf(int n, char *zBuf, const char *zFormat, ...){
-- char *z;
-- va_list ap;
-- va_start(ap,zFormat);
-- z = sqlite3_vsnprintf(n, zBuf, zFormat, ap);
-- va_end(ap);
-- return z;
--}
-
-+#ifndef SQLITE_MUTEX_OMIT
-+
-+#ifndef SQLITE_DEBUG
- /*
--** This is the routine that actually formats the sqlite3_log() message.
--** We house it in a separate routine from sqlite3_log() to avoid using
--** stack space on small-stack systems when logging is disabled.
-+** Stub routines for all mutex methods.
- **
--** sqlite3_log() must render into a static buffer. It cannot dynamically
--** allocate memory because it might be called while the memory allocator
--** mutex is held.
-+** This routines provide no mutual exclusion or error checking.
- */
--static void renderLogMsg(int iErrCode, const char *zFormat, va_list ap){
-- StrAccum acc; /* String accumulator */
-- char zMsg[SQLITE_PRINT_BUF_SIZE*3]; /* Complete log message */
-+static int noopMutexInit(void){ return SQLITE_OK; }
-+static int noopMutexEnd(void){ return SQLITE_OK; }
-+static sqlite3_mutex *noopMutexAlloc(int id){
-+ UNUSED_PARAMETER(id);
-+ return (sqlite3_mutex*)8;
-+}
-+static void noopMutexFree(sqlite3_mutex *p){ UNUSED_PARAMETER(p); return; }
-+static void noopMutexEnter(sqlite3_mutex *p){ UNUSED_PARAMETER(p); return; }
-+static int noopMutexTry(sqlite3_mutex *p){
-+ UNUSED_PARAMETER(p);
-+ return SQLITE_OK;
-+}
-+static void noopMutexLeave(sqlite3_mutex *p){ UNUSED_PARAMETER(p); return; }
-
-- sqlite3StrAccumInit(&acc, zMsg, sizeof(zMsg), 0);
-- acc.useMalloc = 0;
-- sqlite3VXPrintf(&acc, 0, zFormat, ap);
-- sqlite3GlobalConfig.xLog(sqlite3GlobalConfig.pLogArg, iErrCode,
-- sqlite3StrAccumFinish(&acc));
-+SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3NoopMutex(void){
-+ static const sqlite3_mutex_methods sMutex = {
-+ noopMutexInit,
-+ noopMutexEnd,
-+ noopMutexAlloc,
-+ noopMutexFree,
-+ noopMutexEnter,
-+ noopMutexTry,
-+ noopMutexLeave,
-+
-+ 0,
-+ 0,
-+ };
-+
-+ return &sMutex;
- }
-+#endif /* !SQLITE_DEBUG */
-
-+#ifdef SQLITE_DEBUG
- /*
--** Format and write a message to the log if logging is enabled.
-+** In this implementation, error checking is provided for testing
-+** and debugging purposes. The mutexes still do not provide any
-+** mutual exclusion.
- */
--SQLITE_API void sqlite3_log(int iErrCode, const char *zFormat, ...){
-- va_list ap; /* Vararg list */
-- if( sqlite3GlobalConfig.xLog ){
-- va_start(ap, zFormat);
-- renderLogMsg(iErrCode, zFormat, ap);
-- va_end(ap);
-- }
--}
-
--#if defined(SQLITE_DEBUG)
- /*
--** A version of printf() that understands %lld. Used for debugging.
--** The printf() built into some versions of windows does not understand %lld
--** and segfaults if you give it a long long int.
-+** The mutex object
- */
--SQLITE_PRIVATE void sqlite3DebugPrintf(const char *zFormat, ...){
-- va_list ap;
-- StrAccum acc;
-- char zBuf[500];
-- sqlite3StrAccumInit(&acc, zBuf, sizeof(zBuf), 0);
-- acc.useMalloc = 0;
-- va_start(ap,zFormat);
-- sqlite3VXPrintf(&acc, 0, zFormat, ap);
-- va_end(ap);
-- sqlite3StrAccumFinish(&acc);
-- fprintf(stdout,"%s", zBuf);
-- fflush(stdout);
--}
--#endif
-+typedef struct sqlite3_debug_mutex {
-+ int id; /* The mutex type */
-+ int cnt; /* Number of entries without a matching leave */
-+} sqlite3_debug_mutex;
-
--#ifndef SQLITE_OMIT_TRACE
- /*
--** variable-argument wrapper around sqlite3VXPrintf().
-+** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are
-+** intended for use inside assert() statements.
- */
--SQLITE_PRIVATE void sqlite3XPrintf(StrAccum *p, const char *zFormat, ...){
-- va_list ap;
-- va_start(ap,zFormat);
-- sqlite3VXPrintf(p, 1, zFormat, ap);
-- va_end(ap);
-+static int debugMutexHeld(sqlite3_mutex *pX){
-+ sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX;
-+ return p==0 || p->cnt>0;
-+}
-+static int debugMutexNotheld(sqlite3_mutex *pX){
-+ sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX;
-+ return p==0 || p->cnt==0;
- }
--#endif
-
--/************** End of printf.c **********************************************/
--/************** Begin file random.c ******************************************/
- /*
--** 2001 September 15
--**
--** The author disclaims copyright to this source code. In place of
--** a legal notice, here is a blessing:
--**
--** May you do good and not evil.
--** May you find forgiveness for yourself and forgive others.
--** May you share freely, never taking more than you give.
--**
--*************************************************************************
--** This file contains code to implement a pseudo-random number
--** generator (PRNG) for SQLite.
--**
--** Random numbers are used by some of the database backends in order
--** to generate random integer keys for tables or random filenames.
--*/
--
--
--/* All threads share a single random number generator.
--** This structure is the current state of the generator.
-+** Initialize and deinitialize the mutex subsystem.
- */
--static SQLITE_WSD struct sqlite3PrngType {
-- unsigned char isInit; /* True if initialized */
-- unsigned char i, j; /* State variables */
-- unsigned char s[256]; /* State variables */
--} sqlite3Prng;
-+static int debugMutexInit(void){ return SQLITE_OK; }
-+static int debugMutexEnd(void){ return SQLITE_OK; }
-
- /*
--** Get a single 8-bit random value from the RC4 PRNG. The Mutex
--** must be held while executing this routine.
--**
--** Why not just use a library random generator like lrand48() for this?
--** Because the OP_NewRowid opcode in the VDBE depends on having a very
--** good source of random numbers. The lrand48() library function may
--** well be good enough. But maybe not. Or maybe lrand48() has some
--** subtle problems on some systems that could cause problems. It is hard
--** to know. To minimize the risk of problems due to bad lrand48()
--** implementations, SQLite uses this random number generator based
--** on RC4, which we know works very well.
--**
--** (Later): Actually, OP_NewRowid does not depend on a good source of
--** randomness any more. But we will leave this code in all the same.
-+** The sqlite3_mutex_alloc() routine allocates a new
-+** mutex and returns a pointer to it. If it returns NULL
-+** that means that a mutex could not be allocated.
- */
--static u8 randomByte(void){
-- unsigned char t;
--
--
-- /* The "wsdPrng" macro will resolve to the pseudo-random number generator
-- ** state vector. If writable static data is unsupported on the target,
-- ** we have to locate the state vector at run-time. In the more common
-- ** case where writable static data is supported, wsdPrng can refer directly
-- ** to the "sqlite3Prng" state vector declared above.
-- */
--#ifdef SQLITE_OMIT_WSD
-- struct sqlite3PrngType *p = &GLOBAL(struct sqlite3PrngType, sqlite3Prng);
--# define wsdPrng p[0]
--#else
--# define wsdPrng sqlite3Prng
--#endif
--
--
-- /* Initialize the state of the random number generator once,
-- ** the first time this routine is called. The seed value does
-- ** not need to contain a lot of randomness since we are not
-- ** trying to do secure encryption or anything like that...
-- **
-- ** Nothing in this file or anywhere else in SQLite does any kind of
-- ** encryption. The RC4 algorithm is being used as a PRNG (pseudo-random
-- ** number generator) not as an encryption device.
-- */
-- if( !wsdPrng.isInit ){
-- int i;
-- char k[256];
-- wsdPrng.j = 0;
-- wsdPrng.i = 0;
-- sqlite3OsRandomness(sqlite3_vfs_find(0), 256, k);
-- for(i=0; i<256; i++){
-- wsdPrng.s[i] = (u8)i;
-+static sqlite3_mutex *debugMutexAlloc(int id){
-+ static sqlite3_debug_mutex aStatic[6];
-+ sqlite3_debug_mutex *pNew = 0;
-+ switch( id ){
-+ case SQLITE_MUTEX_FAST:
-+ case SQLITE_MUTEX_RECURSIVE: {
-+ pNew = sqlite3Malloc(sizeof(*pNew));
-+ if( pNew ){
-+ pNew->id = id;
-+ pNew->cnt = 0;
-+ }
-+ break;
- }
-- for(i=0; i<256; i++){
-- wsdPrng.j += wsdPrng.s[i] + k[i];
-- t = wsdPrng.s[wsdPrng.j];
-- wsdPrng.s[wsdPrng.j] = wsdPrng.s[i];
-- wsdPrng.s[i] = t;
-+ default: {
-+ assert( id-2 >= 0 );
-+ assert( id-2 < (int)(sizeof(aStatic)/sizeof(aStatic[0])) );
-+ pNew = &aStatic[id-2];
-+ pNew->id = id;
-+ break;
- }
-- wsdPrng.isInit = 1;
- }
-+ return (sqlite3_mutex*)pNew;
-+}
-
-- /* Generate and return single random byte
-- */
-- wsdPrng.i++;
-- t = wsdPrng.s[wsdPrng.i];
-- wsdPrng.j += t;
-- wsdPrng.s[wsdPrng.i] = wsdPrng.s[wsdPrng.j];
-- wsdPrng.s[wsdPrng.j] = t;
-- t += wsdPrng.s[wsdPrng.i];
-- return wsdPrng.s[t];
-+/*
-+** This routine deallocates a previously allocated mutex.
-+*/
-+static void debugMutexFree(sqlite3_mutex *pX){
-+ sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX;
-+ assert( p->cnt==0 );
-+ assert( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE );
-+ sqlite3_free(p);
- }
-
- /*
--** Return N random bytes.
-+** The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt
-+** to enter a mutex. If another thread is already within the mutex,
-+** sqlite3_mutex_enter() will block and sqlite3_mutex_try() will return
-+** SQLITE_BUSY. The sqlite3_mutex_try() interface returns SQLITE_OK
-+** upon successful entry. Mutexes created using SQLITE_MUTEX_RECURSIVE can
-+** be entered multiple times by the same thread. In such cases the,
-+** mutex must be exited an equal number of times before another thread
-+** can enter. If the same thread tries to enter any other kind of mutex
-+** more than once, the behavior is undefined.
- */
--SQLITE_API void sqlite3_randomness(int N, void *pBuf){
-- unsigned char *zBuf = pBuf;
--#if SQLITE_THREADSAFE
-- sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_PRNG);
--#endif
-- sqlite3_mutex_enter(mutex);
-- while( N-- ){
-- *(zBuf++) = randomByte();
-- }
-- sqlite3_mutex_leave(mutex);
-+static void debugMutexEnter(sqlite3_mutex *pX){
-+ sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX;
-+ assert( p->id==SQLITE_MUTEX_RECURSIVE || debugMutexNotheld(pX) );
-+ p->cnt++;
-+}
-+static int debugMutexTry(sqlite3_mutex *pX){
-+ sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX;
-+ assert( p->id==SQLITE_MUTEX_RECURSIVE || debugMutexNotheld(pX) );
-+ p->cnt++;
-+ return SQLITE_OK;
- }
-
--#ifndef SQLITE_OMIT_BUILTIN_TEST
- /*
--** For testing purposes, we sometimes want to preserve the state of
--** PRNG and restore the PRNG to its saved state at a later time, or
--** to reset the PRNG to its initial state. These routines accomplish
--** those tasks.
--**
--** The sqlite3_test_control() interface calls these routines to
--** control the PRNG.
-+** The sqlite3_mutex_leave() routine exits a mutex that was
-+** previously entered by the same thread. The behavior
-+** is undefined if the mutex is not currently entered or
-+** is not currently allocated. SQLite will never do either.
- */
--static SQLITE_WSD struct sqlite3PrngType sqlite3SavedPrng;
--SQLITE_PRIVATE void sqlite3PrngSaveState(void){
-- memcpy(
-- &GLOBAL(struct sqlite3PrngType, sqlite3SavedPrng),
-- &GLOBAL(struct sqlite3PrngType, sqlite3Prng),
-- sizeof(sqlite3Prng)
-- );
-+static void debugMutexLeave(sqlite3_mutex *pX){
-+ sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX;
-+ assert( debugMutexHeld(pX) );
-+ p->cnt--;
-+ assert( p->id==SQLITE_MUTEX_RECURSIVE || debugMutexNotheld(pX) );
- }
--SQLITE_PRIVATE void sqlite3PrngRestoreState(void){
-- memcpy(
-- &GLOBAL(struct sqlite3PrngType, sqlite3Prng),
-- &GLOBAL(struct sqlite3PrngType, sqlite3SavedPrng),
-- sizeof(sqlite3Prng)
-- );
-+
-+SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3NoopMutex(void){
-+ static const sqlite3_mutex_methods sMutex = {
-+ debugMutexInit,
-+ debugMutexEnd,
-+ debugMutexAlloc,
-+ debugMutexFree,
-+ debugMutexEnter,
-+ debugMutexTry,
-+ debugMutexLeave,
-+
-+ debugMutexHeld,
-+ debugMutexNotheld
-+ };
-+
-+ return &sMutex;
- }
--SQLITE_PRIVATE void sqlite3PrngResetState(void){
-- GLOBAL(struct sqlite3PrngType, sqlite3Prng).isInit = 0;
-+#endif /* SQLITE_DEBUG */
-+
-+/*
-+** If compiled with SQLITE_MUTEX_NOOP, then the no-op mutex implementation
-+** is used regardless of the run-time threadsafety setting.
-+*/
-+#ifdef SQLITE_MUTEX_NOOP
-+SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3DefaultMutex(void){
-+ return sqlite3NoopMutex();
- }
--#endif /* SQLITE_OMIT_BUILTIN_TEST */
-+#endif /* defined(SQLITE_MUTEX_NOOP) */
-+#endif /* !defined(SQLITE_MUTEX_OMIT) */
-
--/************** End of random.c **********************************************/
--/************** Begin file utf.c *********************************************/
-+/************** End of mutex_noop.c ******************************************/
-+/************** Begin file mutex_unix.c **************************************/
- /*
--** 2004 April 13
-+** 2007 August 28
- **
- ** The author disclaims copyright to this source code. In place of
- ** a legal notice, here is a blessing:
-@@ -20682,2498 +21113,2601 @@
- ** May you share freely, never taking more than you give.
- **
- *************************************************************************
--** This file contains routines used to translate between UTF-8,
--** UTF-16, UTF-16BE, and UTF-16LE.
--**
--** Notes on UTF-8:
--**
--** Byte-0 Byte-1 Byte-2 Byte-3 Value
--** 0xxxxxxx 00000000 00000000 0xxxxxxx
--** 110yyyyy 10xxxxxx 00000000 00000yyy yyxxxxxx
--** 1110zzzz 10yyyyyy 10xxxxxx 00000000 zzzzyyyy yyxxxxxx
--** 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx 000uuuuu zzzzyyyy yyxxxxxx
--**
--**
--** Notes on UTF-16: (with wwww+1==uuuuu)
--**
--** Word-0 Word-1 Value
--** 110110ww wwzzzzyy 110111yy yyxxxxxx 000uuuuu zzzzyyyy yyxxxxxx
--** zzzzyyyy yyxxxxxx 00000000 zzzzyyyy yyxxxxxx
--**
--**
--** BOM or Byte Order Mark:
--** 0xff 0xfe little-endian utf-16 follows
--** 0xfe 0xff big-endian utf-16 follows
-+** This file contains the C functions that implement mutexes for pthreads
-+*/
-+
-+/*
-+** The code in this file is only used if we are compiling threadsafe
-+** under unix with pthreads.
- **
-+** Note that this implementation requires a version of pthreads that
-+** supports recursive mutexes.
- */
--/* #include <assert.h> */
-+#ifdef SQLITE_MUTEX_PTHREADS
-+
-+#include <pthread.h>
-
--#ifndef SQLITE_AMALGAMATION
- /*
--** The following constant value is used by the SQLITE_BIGENDIAN and
--** SQLITE_LITTLEENDIAN macros.
-+** The sqlite3_mutex.id, sqlite3_mutex.nRef, and sqlite3_mutex.owner fields
-+** are necessary under two condidtions: (1) Debug builds and (2) using
-+** home-grown mutexes. Encapsulate these conditions into a single #define.
- */
--SQLITE_PRIVATE const int sqlite3one = 1;
--#endif /* SQLITE_AMALGAMATION */
-+#if defined(SQLITE_DEBUG) || defined(SQLITE_HOMEGROWN_RECURSIVE_MUTEX)
-+# define SQLITE_MUTEX_NREF 1
-+#else
-+# define SQLITE_MUTEX_NREF 0
-+#endif
-
- /*
--** This lookup table is used to help decode the first byte of
--** a multi-byte UTF8 character.
-+** Each recursive mutex is an instance of the following structure.
- */
--static const unsigned char sqlite3Utf8Trans1[] = {
-- 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
-- 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
-- 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
-- 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
-- 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-- 0x00, 0x01, 0x02, 0x03, 0x00, 0x01, 0x00, 0x00,
-+struct sqlite3_mutex {
-+ pthread_mutex_t mutex; /* Mutex controlling the lock */
-+#if SQLITE_MUTEX_NREF
-+ int id; /* Mutex type */
-+ volatile int nRef; /* Number of entrances */
-+ volatile pthread_t owner; /* Thread that is within this mutex */
-+ int trace; /* True to trace changes */
-+#endif
- };
-+#if SQLITE_MUTEX_NREF
-+#define SQLITE3_MUTEX_INITIALIZER { PTHREAD_MUTEX_INITIALIZER, 0, 0, (pthread_t)0, 0 }
-+#else
-+#define SQLITE3_MUTEX_INITIALIZER { PTHREAD_MUTEX_INITIALIZER }
-+#endif
-
--
--#define WRITE_UTF8(zOut, c) { \
-- if( c<0x00080 ){ \
-- *zOut++ = (u8)(c&0xFF); \
-- } \
-- else if( c<0x00800 ){ \
-- *zOut++ = 0xC0 + (u8)((c>>6)&0x1F); \
-- *zOut++ = 0x80 + (u8)(c & 0x3F); \
-- } \
-- else if( c<0x10000 ){ \
-- *zOut++ = 0xE0 + (u8)((c>>12)&0x0F); \
-- *zOut++ = 0x80 + (u8)((c>>6) & 0x3F); \
-- *zOut++ = 0x80 + (u8)(c & 0x3F); \
-- }else{ \
-- *zOut++ = 0xF0 + (u8)((c>>18) & 0x07); \
-- *zOut++ = 0x80 + (u8)((c>>12) & 0x3F); \
-- *zOut++ = 0x80 + (u8)((c>>6) & 0x3F); \
-- *zOut++ = 0x80 + (u8)(c & 0x3F); \
-- } \
--}
--
--#define WRITE_UTF16LE(zOut, c) { \
-- if( c<=0xFFFF ){ \
-- *zOut++ = (u8)(c&0x00FF); \
-- *zOut++ = (u8)((c>>8)&0x00FF); \
-- }else{ \
-- *zOut++ = (u8)(((c>>10)&0x003F) + (((c-0x10000)>>10)&0x00C0)); \
-- *zOut++ = (u8)(0x00D8 + (((c-0x10000)>>18)&0x03)); \
-- *zOut++ = (u8)(c&0x00FF); \
-- *zOut++ = (u8)(0x00DC + ((c>>8)&0x03)); \
-- } \
-+/*
-+** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are
-+** intended for use only inside assert() statements. On some platforms,
-+** there might be race conditions that can cause these routines to
-+** deliver incorrect results. In particular, if pthread_equal() is
-+** not an atomic operation, then these routines might delivery
-+** incorrect results. On most platforms, pthread_equal() is a
-+** comparison of two integers and is therefore atomic. But we are
-+** told that HPUX is not such a platform. If so, then these routines
-+** will not always work correctly on HPUX.
-+**
-+** On those platforms where pthread_equal() is not atomic, SQLite
-+** should be compiled without -DSQLITE_DEBUG and with -DNDEBUG to
-+** make sure no assert() statements are evaluated and hence these
-+** routines are never called.
-+*/
-+#if !defined(NDEBUG) || defined(SQLITE_DEBUG)
-+static int pthreadMutexHeld(sqlite3_mutex *p){
-+ return (p->nRef!=0 && pthread_equal(p->owner, pthread_self()));
- }
--
--#define WRITE_UTF16BE(zOut, c) { \
-- if( c<=0xFFFF ){ \
-- *zOut++ = (u8)((c>>8)&0x00FF); \
-- *zOut++ = (u8)(c&0x00FF); \
-- }else{ \
-- *zOut++ = (u8)(0x00D8 + (((c-0x10000)>>18)&0x03)); \
-- *zOut++ = (u8)(((c>>10)&0x003F) + (((c-0x10000)>>10)&0x00C0)); \
-- *zOut++ = (u8)(0x00DC + ((c>>8)&0x03)); \
-- *zOut++ = (u8)(c&0x00FF); \
-- } \
-+static int pthreadMutexNotheld(sqlite3_mutex *p){
-+ return p->nRef==0 || pthread_equal(p->owner, pthread_self())==0;
- }
-+#endif
-
--#define READ_UTF16LE(zIn, TERM, c){ \
-- c = (*zIn++); \
-- c += ((*zIn++)<<8); \
-- if( c>=0xD800 && c<0xE000 && TERM ){ \
-- int c2 = (*zIn++); \
-- c2 += ((*zIn++)<<8); \
-- c = (c2&0x03FF) + ((c&0x003F)<<10) + (((c&0x03C0)+0x0040)<<10); \
-- } \
--}
--
--#define READ_UTF16BE(zIn, TERM, c){ \
-- c = ((*zIn++)<<8); \
-- c += (*zIn++); \
-- if( c>=0xD800 && c<0xE000 && TERM ){ \
-- int c2 = ((*zIn++)<<8); \
-- c2 += (*zIn++); \
-- c = (c2&0x03FF) + ((c&0x003F)<<10) + (((c&0x03C0)+0x0040)<<10); \
-- } \
--}
-+/*
-+** Initialize and deinitialize the mutex subsystem.
-+*/
-+static int pthreadMutexInit(void){ return SQLITE_OK; }
-+static int pthreadMutexEnd(void){ return SQLITE_OK; }
-
- /*
--** Translate a single UTF-8 character. Return the unicode value.
--**
--** During translation, assume that the byte that zTerm points
--** is a 0x00.
--**
--** Write a pointer to the next unread byte back into *pzNext.
--**
--** Notes On Invalid UTF-8:
-+** The sqlite3_mutex_alloc() routine allocates a new
-+** mutex and returns a pointer to it. If it returns NULL
-+** that means that a mutex could not be allocated. SQLite
-+** will unwind its stack and return an error. The argument
-+** to sqlite3_mutex_alloc() is one of these integer constants:
- **
--** * This routine never allows a 7-bit character (0x00 through 0x7f) to
--** be encoded as a multi-byte character. Any multi-byte character that
--** attempts to encode a value between 0x00 and 0x7f is rendered as 0xfffd.
-+** <ul>
-+** <li> SQLITE_MUTEX_FAST
-+** <li> SQLITE_MUTEX_RECURSIVE
-+** <li> SQLITE_MUTEX_STATIC_MASTER
-+** <li> SQLITE_MUTEX_STATIC_MEM
-+** <li> SQLITE_MUTEX_STATIC_MEM2
-+** <li> SQLITE_MUTEX_STATIC_PRNG
-+** <li> SQLITE_MUTEX_STATIC_LRU
-+** <li> SQLITE_MUTEX_STATIC_PMEM
-+** </ul>
- **
--** * This routine never allows a UTF16 surrogate value to be encoded.
--** If a multi-byte character attempts to encode a value between
--** 0xd800 and 0xe000 then it is rendered as 0xfffd.
-+** The first two constants cause sqlite3_mutex_alloc() to create
-+** a new mutex. The new mutex is recursive when SQLITE_MUTEX_RECURSIVE
-+** is used but not necessarily so when SQLITE_MUTEX_FAST is used.
-+** The mutex implementation does not need to make a distinction
-+** between SQLITE_MUTEX_RECURSIVE and SQLITE_MUTEX_FAST if it does
-+** not want to. But SQLite will only request a recursive mutex in
-+** cases where it really needs one. If a faster non-recursive mutex
-+** implementation is available on the host platform, the mutex subsystem
-+** might return such a mutex in response to SQLITE_MUTEX_FAST.
- **
--** * Bytes in the range of 0x80 through 0xbf which occur as the first
--** byte of a character are interpreted as single-byte characters
--** and rendered as themselves even though they are technically
--** invalid characters.
-+** The other allowed parameters to sqlite3_mutex_alloc() each return
-+** a pointer to a static preexisting mutex. Six static mutexes are
-+** used by the current version of SQLite. Future versions of SQLite
-+** may add additional static mutexes. Static mutexes are for internal
-+** use by SQLite only. Applications that use SQLite mutexes should
-+** use only the dynamic mutexes returned by SQLITE_MUTEX_FAST or
-+** SQLITE_MUTEX_RECURSIVE.
- **
--** * This routine accepts an infinite number of different UTF8 encodings
--** for unicode values 0x80 and greater. It do not change over-length
--** encodings to 0xfffd as some systems recommend.
-+** Note that if one of the dynamic mutex parameters (SQLITE_MUTEX_FAST
-+** or SQLITE_MUTEX_RECURSIVE) is used then sqlite3_mutex_alloc()
-+** returns a different mutex on every call. But for the static
-+** mutex types, the same mutex is returned on every call that has
-+** the same type number.
- */
--#define READ_UTF8(zIn, zTerm, c) \
-- c = *(zIn++); \
-- if( c>=0xc0 ){ \
-- c = sqlite3Utf8Trans1[c-0xc0]; \
-- while( zIn!=zTerm && (*zIn & 0xc0)==0x80 ){ \
-- c = (c<<6) + (0x3f & *(zIn++)); \
-- } \
-- if( c<0x80 \
-- || (c&0xFFFFF800)==0xD800 \
-- || (c&0xFFFFFFFE)==0xFFFE ){ c = 0xFFFD; } \
-- }
--SQLITE_PRIVATE u32 sqlite3Utf8Read(
-- const unsigned char **pz /* Pointer to string from which to read char */
--){
-- unsigned int c;
--
-- /* Same as READ_UTF8() above but without the zTerm parameter.
-- ** For this routine, we assume the UTF8 string is always zero-terminated.
-- */
-- c = *((*pz)++);
-- if( c>=0xc0 ){
-- c = sqlite3Utf8Trans1[c-0xc0];
-- while( (*(*pz) & 0xc0)==0x80 ){
-- c = (c<<6) + (0x3f & *((*pz)++));
-+static sqlite3_mutex *pthreadMutexAlloc(int iType){
-+ static sqlite3_mutex staticMutexes[] = {
-+ SQLITE3_MUTEX_INITIALIZER,
-+ SQLITE3_MUTEX_INITIALIZER,
-+ SQLITE3_MUTEX_INITIALIZER,
-+ SQLITE3_MUTEX_INITIALIZER,
-+ SQLITE3_MUTEX_INITIALIZER,
-+ SQLITE3_MUTEX_INITIALIZER
-+ };
-+ sqlite3_mutex *p;
-+ switch( iType ){
-+ case SQLITE_MUTEX_RECURSIVE: {
-+ p = sqlite3MallocZero( sizeof(*p) );
-+ if( p ){
-+#ifdef SQLITE_HOMEGROWN_RECURSIVE_MUTEX
-+ /* If recursive mutexes are not available, we will have to
-+ ** build our own. See below. */
-+ pthread_mutex_init(&p->mutex, 0);
-+#else
-+ /* Use a recursive mutex if it is available */
-+ pthread_mutexattr_t recursiveAttr;
-+ pthread_mutexattr_init(&recursiveAttr);
-+ pthread_mutexattr_settype(&recursiveAttr, PTHREAD_MUTEX_RECURSIVE);
-+ pthread_mutex_init(&p->mutex, &recursiveAttr);
-+ pthread_mutexattr_destroy(&recursiveAttr);
-+#endif
-+#if SQLITE_MUTEX_NREF
-+ p->id = iType;
-+#endif
-+ }
-+ break;
-+ }
-+ case SQLITE_MUTEX_FAST: {
-+ p = sqlite3MallocZero( sizeof(*p) );
-+ if( p ){
-+#if SQLITE_MUTEX_NREF
-+ p->id = iType;
-+#endif
-+ pthread_mutex_init(&p->mutex, 0);
-+ }
-+ break;
-+ }
-+ default: {
-+ assert( iType-2 >= 0 );
-+ assert( iType-2 < ArraySize(staticMutexes) );
-+ p = &staticMutexes[iType-2];
-+#if SQLITE_MUTEX_NREF
-+ p->id = iType;
-+#endif
-+ break;
- }
-- if( c<0x80
-- || (c&0xFFFFF800)==0xD800
-- || (c&0xFFFFFFFE)==0xFFFE ){ c = 0xFFFD; }
- }
-- return c;
-+ return p;
- }
-
-
--
--
- /*
--** If the TRANSLATE_TRACE macro is defined, the value of each Mem is
--** printed on stderr on the way into and out of sqlite3VdbeMemTranslate().
--*/
--/* #define TRANSLATE_TRACE 1 */
-+** This routine deallocates a previously
-+** allocated mutex. SQLite is careful to deallocate every
-+** mutex that it allocates.
-+*/
-+static void pthreadMutexFree(sqlite3_mutex *p){
-+ assert( p->nRef==0 );
-+ assert( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE );
-+ pthread_mutex_destroy(&p->mutex);
-+ sqlite3_free(p);
-+}
-
--#ifndef SQLITE_OMIT_UTF16
- /*
--** This routine transforms the internal text encoding used by pMem to
--** desiredEnc. It is an error if the string is already of the desired
--** encoding, or if *pMem does not contain a string value.
-+** The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt
-+** to enter a mutex. If another thread is already within the mutex,
-+** sqlite3_mutex_enter() will block and sqlite3_mutex_try() will return
-+** SQLITE_BUSY. The sqlite3_mutex_try() interface returns SQLITE_OK
-+** upon successful entry. Mutexes created using SQLITE_MUTEX_RECURSIVE can
-+** be entered multiple times by the same thread. In such cases the,
-+** mutex must be exited an equal number of times before another thread
-+** can enter. If the same thread tries to enter any other kind of mutex
-+** more than once, the behavior is undefined.
- */
--SQLITE_PRIVATE int sqlite3VdbeMemTranslate(Mem *pMem, u8 desiredEnc){
-- int len; /* Maximum length of output string in bytes */
-- unsigned char *zOut; /* Output buffer */
-- unsigned char *zIn; /* Input iterator */
-- unsigned char *zTerm; /* End of input */
-- unsigned char *z; /* Output iterator */
-- unsigned int c;
--
-- assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
-- assert( pMem->flags&MEM_Str );
-- assert( pMem->enc!=desiredEnc );
-- assert( pMem->enc!=0 );
-- assert( pMem->n>=0 );
--
--#if defined(TRANSLATE_TRACE) && defined(SQLITE_DEBUG)
-- {
-- char zBuf[100];
-- sqlite3VdbeMemPrettyPrint(pMem, zBuf);
-- fprintf(stderr, "INPUT: %s\n", zBuf);
-- }
--#endif
-+static void pthreadMutexEnter(sqlite3_mutex *p){
-+ assert( p->id==SQLITE_MUTEX_RECURSIVE || pthreadMutexNotheld(p) );
-
-- /* If the translation is between UTF-16 little and big endian, then
-- ** all that is required is to swap the byte order. This case is handled
-- ** differently from the others.
-+#ifdef SQLITE_HOMEGROWN_RECURSIVE_MUTEX
-+ /* If recursive mutexes are not available, then we have to grow
-+ ** our own. This implementation assumes that pthread_equal()
-+ ** is atomic - that it cannot be deceived into thinking self
-+ ** and p->owner are equal if p->owner changes between two values
-+ ** that are not equal to self while the comparison is taking place.
-+ ** This implementation also assumes a coherent cache - that
-+ ** separate processes cannot read different values from the same
-+ ** address at the same time. If either of these two conditions
-+ ** are not met, then the mutexes will fail and problems will result.
- */
-- if( pMem->enc!=SQLITE_UTF8 && desiredEnc!=SQLITE_UTF8 ){
-- u8 temp;
-- int rc;
-- rc = sqlite3VdbeMemMakeWriteable(pMem);
-- if( rc!=SQLITE_OK ){
-- assert( rc==SQLITE_NOMEM );
-- return SQLITE_NOMEM;
-- }
-- zIn = (u8*)pMem->z;
-- zTerm = &zIn[pMem->n&~1];
-- while( zIn<zTerm ){
-- temp = *zIn;
-- *zIn = *(zIn+1);
-- zIn++;
-- *zIn++ = temp;
-+ {
-+ pthread_t self = pthread_self();
-+ if( p->nRef>0 && pthread_equal(p->owner, self) ){
-+ p->nRef++;
-+ }else{
-+ pthread_mutex_lock(&p->mutex);
-+ assert( p->nRef==0 );
-+ p->owner = self;
-+ p->nRef = 1;
- }
-- pMem->enc = desiredEnc;
-- goto translate_out;
- }
-+#else
-+ /* Use the built-in recursive mutexes if they are available.
-+ */
-+ pthread_mutex_lock(&p->mutex);
-+#if SQLITE_MUTEX_NREF
-+ assert( p->nRef>0 || p->owner==0 );
-+ p->owner = pthread_self();
-+ p->nRef++;
-+#endif
-+#endif
-
-- /* Set len to the maximum number of bytes required in the output buffer. */
-- if( desiredEnc==SQLITE_UTF8 ){
-- /* When converting from UTF-16, the maximum growth results from
-- ** translating a 2-byte character to a 4-byte UTF-8 character.
-- ** A single byte is required for the output string
-- ** nul-terminator.
-- */
-- pMem->n &= ~1;
-- len = pMem->n * 2 + 1;
-- }else{
-- /* When converting from UTF-8 to UTF-16 the maximum growth is caused
-- ** when a 1-byte UTF-8 character is translated into a 2-byte UTF-16
-- ** character. Two bytes are required in the output buffer for the
-- ** nul-terminator.
-- */
-- len = pMem->n * 2 + 2;
-+#ifdef SQLITE_DEBUG
-+ if( p->trace ){
-+ printf("enter mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef);
- }
-+#endif
-+}
-+static int pthreadMutexTry(sqlite3_mutex *p){
-+ int rc;
-+ assert( p->id==SQLITE_MUTEX_RECURSIVE || pthreadMutexNotheld(p) );
-
-- /* Set zIn to point at the start of the input buffer and zTerm to point 1
-- ** byte past the end.
-- **
-- ** Variable zOut is set to point at the output buffer, space obtained
-- ** from sqlite3_malloc().
-+#ifdef SQLITE_HOMEGROWN_RECURSIVE_MUTEX
-+ /* If recursive mutexes are not available, then we have to grow
-+ ** our own. This implementation assumes that pthread_equal()
-+ ** is atomic - that it cannot be deceived into thinking self
-+ ** and p->owner are equal if p->owner changes between two values
-+ ** that are not equal to self while the comparison is taking place.
-+ ** This implementation also assumes a coherent cache - that
-+ ** separate processes cannot read different values from the same
-+ ** address at the same time. If either of these two conditions
-+ ** are not met, then the mutexes will fail and problems will result.
- */
-- zIn = (u8*)pMem->z;
-- zTerm = &zIn[pMem->n];
-- zOut = sqlite3DbMallocRaw(pMem->db, len);
-- if( !zOut ){
-- return SQLITE_NOMEM;
-- }
-- z = zOut;
--
-- if( pMem->enc==SQLITE_UTF8 ){
-- if( desiredEnc==SQLITE_UTF16LE ){
-- /* UTF-8 -> UTF-16 Little-endian */
-- while( zIn<zTerm ){
-- READ_UTF8(zIn, zTerm, c);
-- WRITE_UTF16LE(z, c);
-- }
-+ {
-+ pthread_t self = pthread_self();
-+ if( p->nRef>0 && pthread_equal(p->owner, self) ){
-+ p->nRef++;
-+ rc = SQLITE_OK;
-+ }else if( pthread_mutex_trylock(&p->mutex)==0 ){
-+ assert( p->nRef==0 );
-+ p->owner = self;
-+ p->nRef = 1;
-+ rc = SQLITE_OK;
- }else{
-- assert( desiredEnc==SQLITE_UTF16BE );
-- /* UTF-8 -> UTF-16 Big-endian */
-- while( zIn<zTerm ){
-- READ_UTF8(zIn, zTerm, c);
-- WRITE_UTF16BE(z, c);
-- }
-+ rc = SQLITE_BUSY;
- }
-- pMem->n = (int)(z - zOut);
-- *z++ = 0;
-+ }
-+#else
-+ /* Use the built-in recursive mutexes if they are available.
-+ */
-+ if( pthread_mutex_trylock(&p->mutex)==0 ){
-+#if SQLITE_MUTEX_NREF
-+ p->owner = pthread_self();
-+ p->nRef++;
-+#endif
-+ rc = SQLITE_OK;
- }else{
-- assert( desiredEnc==SQLITE_UTF8 );
-- if( pMem->enc==SQLITE_UTF16LE ){
-- /* UTF-16 Little-endian -> UTF-8 */
-- while( zIn<zTerm ){
-- READ_UTF16LE(zIn, zIn<zTerm, c);
-- WRITE_UTF8(z, c);
-- }
-- }else{
-- /* UTF-16 Big-endian -> UTF-8 */
-- while( zIn<zTerm ){
-- READ_UTF16BE(zIn, zIn<zTerm, c);
-- WRITE_UTF8(z, c);
-- }
-- }
-- pMem->n = (int)(z - zOut);
-+ rc = SQLITE_BUSY;
- }
-- *z = 0;
-- assert( (pMem->n+(desiredEnc==SQLITE_UTF8?1:2))<=len );
--
-- sqlite3VdbeMemRelease(pMem);
-- pMem->flags &= ~(MEM_Static|MEM_Dyn|MEM_Ephem);
-- pMem->enc = desiredEnc;
-- pMem->flags |= (MEM_Term|MEM_Dyn);
-- pMem->z = (char*)zOut;
-- pMem->zMalloc = pMem->z;
-+#endif
-
--translate_out:
--#if defined(TRANSLATE_TRACE) && defined(SQLITE_DEBUG)
-- {
-- char zBuf[100];
-- sqlite3VdbeMemPrettyPrint(pMem, zBuf);
-- fprintf(stderr, "OUTPUT: %s\n", zBuf);
-+#ifdef SQLITE_DEBUG
-+ if( rc==SQLITE_OK && p->trace ){
-+ printf("enter mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef);
- }
- #endif
-- return SQLITE_OK;
-+ return rc;
- }
-
- /*
--** This routine checks for a byte-order mark at the beginning of the
--** UTF-16 string stored in *pMem. If one is present, it is removed and
--** the encoding of the Mem adjusted. This routine does not do any
--** byte-swapping, it just sets Mem.enc appropriately.
--**
--** The allocation (static, dynamic etc.) and encoding of the Mem may be
--** changed by this function.
-+** The sqlite3_mutex_leave() routine exits a mutex that was
-+** previously entered by the same thread. The behavior
-+** is undefined if the mutex is not currently entered or
-+** is not currently allocated. SQLite will never do either.
- */
--SQLITE_PRIVATE int sqlite3VdbeMemHandleBom(Mem *pMem){
-- int rc = SQLITE_OK;
-- u8 bom = 0;
-+static void pthreadMutexLeave(sqlite3_mutex *p){
-+ assert( pthreadMutexHeld(p) );
-+#if SQLITE_MUTEX_NREF
-+ p->nRef--;
-+ if( p->nRef==0 ) p->owner = 0;
-+#endif
-+ assert( p->nRef==0 || p->id==SQLITE_MUTEX_RECURSIVE );
-
-- assert( pMem->n>=0 );
-- if( pMem->n>1 ){
-- u8 b1 = *(u8 *)pMem->z;
-- u8 b2 = *(((u8 *)pMem->z) + 1);
-- if( b1==0xFE && b2==0xFF ){
-- bom = SQLITE_UTF16BE;
-- }
-- if( b1==0xFF && b2==0xFE ){
-- bom = SQLITE_UTF16LE;
-- }
-+#ifdef SQLITE_HOMEGROWN_RECURSIVE_MUTEX
-+ if( p->nRef==0 ){
-+ pthread_mutex_unlock(&p->mutex);
- }
--
-- if( bom ){
-- rc = sqlite3VdbeMemMakeWriteable(pMem);
-- if( rc==SQLITE_OK ){
-- pMem->n -= 2;
-- memmove(pMem->z, &pMem->z[2], pMem->n);
-- pMem->z[pMem->n] = '\0';
-- pMem->z[pMem->n+1] = '\0';
-- pMem->flags |= MEM_Term;
-- pMem->enc = bom;
-- }
-+#else
-+ pthread_mutex_unlock(&p->mutex);
-+#endif
-+
-+#ifdef SQLITE_DEBUG
-+ if( p->trace ){
-+ printf("leave mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef);
- }
-- return rc;
-+#endif
- }
--#endif /* SQLITE_OMIT_UTF16 */
-
--/*
--** pZ is a UTF-8 encoded unicode string. If nByte is less than zero,
--** return the number of unicode characters in pZ up to (but not including)
--** the first 0x00 byte. If nByte is not less than zero, return the
--** number of unicode characters in the first nByte of pZ (or up to
--** the first 0x00, whichever comes first).
--*/
--SQLITE_PRIVATE int sqlite3Utf8CharLen(const char *zIn, int nByte){
-- int r = 0;
-- const u8 *z = (const u8*)zIn;
-- const u8 *zTerm;
-- if( nByte>=0 ){
-- zTerm = &z[nByte];
-- }else{
-- zTerm = (const u8*)(-1);
-- }
-- assert( z<=zTerm );
-- while( *z!=0 && z<zTerm ){
-- SQLITE_SKIP_UTF8(z);
-- r++;
-- }
-- return r;
-+SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3DefaultMutex(void){
-+ static const sqlite3_mutex_methods sMutex = {
-+ pthreadMutexInit,
-+ pthreadMutexEnd,
-+ pthreadMutexAlloc,
-+ pthreadMutexFree,
-+ pthreadMutexEnter,
-+ pthreadMutexTry,
-+ pthreadMutexLeave,
-+#ifdef SQLITE_DEBUG
-+ pthreadMutexHeld,
-+ pthreadMutexNotheld
-+#else
-+ 0,
-+ 0
-+#endif
-+ };
-+
-+ return &sMutex;
- }
-
--/* This test function is not currently used by the automated test-suite.
--** Hence it is only available in debug builds.
--*/
--#if defined(SQLITE_TEST) && defined(SQLITE_DEBUG)
-+#endif /* SQLITE_MUTEX_PTHREADS */
-+
-+/************** End of mutex_unix.c ******************************************/
-+/************** Begin file mutex_w32.c ***************************************/
- /*
--** Translate UTF-8 to UTF-8.
-+** 2007 August 14
- **
--** This has the effect of making sure that the string is well-formed
--** UTF-8. Miscoded characters are removed.
-+** The author disclaims copyright to this source code. In place of
-+** a legal notice, here is a blessing:
- **
--** The translation is done in-place and aborted if the output
--** overruns the input.
-+** May you do good and not evil.
-+** May you find forgiveness for yourself and forgive others.
-+** May you share freely, never taking more than you give.
-+**
-+*************************************************************************
-+** This file contains the C functions that implement mutexes for win32
- */
--SQLITE_PRIVATE int sqlite3Utf8To8(unsigned char *zIn){
-- unsigned char *zOut = zIn;
-- unsigned char *zStart = zIn;
-- u32 c;
--
-- while( zIn[0] && zOut<=zIn ){
-- c = sqlite3Utf8Read((const u8**)&zIn);
-- if( c!=0xfffd ){
-- WRITE_UTF8(zOut, c);
-- }
-- }
-- *zOut = 0;
-- return (int)(zOut - zStart);
--}
--#endif
-
--#ifndef SQLITE_OMIT_UTF16
- /*
--** Convert a UTF-16 string in the native encoding into a UTF-8 string.
--** Memory to hold the UTF-8 string is obtained from sqlite3_malloc and must
--** be freed by the calling function.
-+** The code in this file is only used if we are compiling multithreaded
-+** on a win32 system.
-+*/
-+#ifdef SQLITE_MUTEX_W32
-+
-+/*
-+** Each recursive mutex is an instance of the following structure.
-+*/
-+struct sqlite3_mutex {
-+ CRITICAL_SECTION mutex; /* Mutex controlling the lock */
-+ int id; /* Mutex type */
-+#ifdef SQLITE_DEBUG
-+ volatile int nRef; /* Number of enterances */
-+ volatile DWORD owner; /* Thread holding this mutex */
-+ int trace; /* True to trace changes */
-+#endif
-+};
-+#define SQLITE_W32_MUTEX_INITIALIZER { 0 }
-+#ifdef SQLITE_DEBUG
-+#define SQLITE3_MUTEX_INITIALIZER { SQLITE_W32_MUTEX_INITIALIZER, 0, 0L, (DWORD)0, 0 }
-+#else
-+#define SQLITE3_MUTEX_INITIALIZER { SQLITE_W32_MUTEX_INITIALIZER, 0 }
-+#endif
-+
-+/*
-+** Return true (non-zero) if we are running under WinNT, Win2K, WinXP,
-+** or WinCE. Return false (zero) for Win95, Win98, or WinME.
- **
--** NULL is returned if there is an allocation error.
-+** Here is an interesting observation: Win95, Win98, and WinME lack
-+** the LockFileEx() API. But we can still statically link against that
-+** API as long as we don't call it win running Win95/98/ME. A call to
-+** this routine is used to determine if the host is Win95/98/ME or
-+** WinNT/2K/XP so that we will know whether or not we can safely call
-+** the LockFileEx() API.
-+**
-+** mutexIsNT() is only used for the TryEnterCriticalSection() API call,
-+** which is only available if your application was compiled with
-+** _WIN32_WINNT defined to a value >= 0x0400. Currently, the only
-+** call to TryEnterCriticalSection() is #ifdef'ed out, so #ifdef
-+** this out as well.
- */
--SQLITE_PRIVATE char *sqlite3Utf16to8(sqlite3 *db, const void *z, int nByte, u8 enc){
-- Mem m;
-- memset(&m, 0, sizeof(m));
-- m.db = db;
-- sqlite3VdbeMemSetStr(&m, z, nByte, enc, SQLITE_STATIC);
-- sqlite3VdbeChangeEncoding(&m, SQLITE_UTF8);
-- if( db->mallocFailed ){
-- sqlite3VdbeMemRelease(&m);
-- m.z = 0;
-+#if 0
-+#if SQLITE_OS_WINCE || SQLITE_OS_WINRT
-+# define mutexIsNT() (1)
-+#else
-+ static int mutexIsNT(void){
-+ static int osType = 0;
-+ if( osType==0 ){
-+ OSVERSIONINFO sInfo;
-+ sInfo.dwOSVersionInfoSize = sizeof(sInfo);
-+ GetVersionEx(&sInfo);
-+ osType = sInfo.dwPlatformId==VER_PLATFORM_WIN32_NT ? 2 : 1;
-+ }
-+ return osType==2;
- }
-- assert( (m.flags & MEM_Term)!=0 || db->mallocFailed );
-- assert( (m.flags & MEM_Str)!=0 || db->mallocFailed );
-- assert( (m.flags & MEM_Dyn)!=0 || db->mallocFailed );
-- assert( m.z || db->mallocFailed );
-- return m.z;
--}
-+#endif /* SQLITE_OS_WINCE */
-+#endif
-
-+#ifdef SQLITE_DEBUG
- /*
--** Convert a UTF-8 string to the UTF-16 encoding specified by parameter
--** enc. A pointer to the new string is returned, and the value of *pnOut
--** is set to the length of the returned string in bytes. The call should
--** arrange to call sqlite3DbFree() on the returned pointer when it is
--** no longer required.
--**
--** If a malloc failure occurs, NULL is returned and the db.mallocFailed
--** flag set.
-+** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are
-+** intended for use only inside assert() statements.
- */
--#ifdef SQLITE_ENABLE_STAT3
--SQLITE_PRIVATE char *sqlite3Utf8to16(sqlite3 *db, u8 enc, char *z, int n, int *pnOut){
-- Mem m;
-- memset(&m, 0, sizeof(m));
-- m.db = db;
-- sqlite3VdbeMemSetStr(&m, z, n, SQLITE_UTF8, SQLITE_STATIC);
-- if( sqlite3VdbeMemTranslate(&m, enc) ){
-- assert( db->mallocFailed );
-- return 0;
-- }
-- assert( m.z==m.zMalloc );
-- *pnOut = m.n;
-- return m.z;
-+static int winMutexHeld(sqlite3_mutex *p){
-+ return p->nRef!=0 && p->owner==GetCurrentThreadId();
-+}
-+static int winMutexNotheld2(sqlite3_mutex *p, DWORD tid){
-+ return p->nRef==0 || p->owner!=tid;
-+}
-+static int winMutexNotheld(sqlite3_mutex *p){
-+ DWORD tid = GetCurrentThreadId();
-+ return winMutexNotheld2(p, tid);
- }
- #endif
-
-+
- /*
--** zIn is a UTF-16 encoded unicode string at least nChar characters long.
--** Return the number of bytes in the first nChar unicode characters
--** in pZ. nChar must be non-negative.
-+** Initialize and deinitialize the mutex subsystem.
- */
--SQLITE_PRIVATE int sqlite3Utf16ByteLen(const void *zIn, int nChar){
-- int c;
-- unsigned char const *z = zIn;
-- int n = 0;
--
-- if( SQLITE_UTF16NATIVE==SQLITE_UTF16BE ){
-- while( n<nChar ){
-- READ_UTF16BE(z, 1, c);
-- n++;
-+static sqlite3_mutex winMutex_staticMutexes[6] = {
-+ SQLITE3_MUTEX_INITIALIZER,
-+ SQLITE3_MUTEX_INITIALIZER,
-+ SQLITE3_MUTEX_INITIALIZER,
-+ SQLITE3_MUTEX_INITIALIZER,
-+ SQLITE3_MUTEX_INITIALIZER,
-+ SQLITE3_MUTEX_INITIALIZER
-+};
-+static int winMutex_isInit = 0;
-+/* As winMutexInit() and winMutexEnd() are called as part
-+** of the sqlite3_initialize and sqlite3_shutdown()
-+** processing, the "interlocked" magic is probably not
-+** strictly necessary.
-+*/
-+static long winMutex_lock = 0;
-+
-+SQLITE_API void sqlite3_win32_sleep(DWORD milliseconds); /* os_win.c */
-+
-+static int winMutexInit(void){
-+ /* The first to increment to 1 does actual initialization */
-+ if( InterlockedCompareExchange(&winMutex_lock, 1, 0)==0 ){
-+ int i;
-+ for(i=0; i<ArraySize(winMutex_staticMutexes); i++){
-+#if SQLITE_OS_WINRT
-+ InitializeCriticalSectionEx(&winMutex_staticMutexes[i].mutex, 0, 0);
-+#else
-+ InitializeCriticalSection(&winMutex_staticMutexes[i].mutex);
-+#endif
- }
-+ winMutex_isInit = 1;
- }else{
-- while( n<nChar ){
-- READ_UTF16LE(z, 1, c);
-- n++;
-+ /* Someone else is in the process of initing the static mutexes */
-+ while( !winMutex_isInit ){
-+ sqlite3_win32_sleep(1);
- }
- }
-- return (int)(z-(unsigned char const *)zIn);
-+ return SQLITE_OK;
- }
-
--#if defined(SQLITE_TEST)
--/*
--** This routine is called from the TCL test function "translate_selftest".
--** It checks that the primitives for serializing and deserializing
--** characters in each encoding are inverses of each other.
--*/
--SQLITE_PRIVATE void sqlite3UtfSelfTest(void){
-- unsigned int i, t;
-- unsigned char zBuf[20];
-- unsigned char *z;
-- int n;
-- unsigned int c;
--
-- for(i=0; i<0x00110000; i++){
-- z = zBuf;
-- WRITE_UTF8(z, i);
-- n = (int)(z-zBuf);
-- assert( n>0 && n<=4 );
-- z[0] = 0;
-- z = zBuf;
-- c = sqlite3Utf8Read((const u8**)&z);
-- t = i;
-- if( i>=0xD800 && i<=0xDFFF ) t = 0xFFFD;
-- if( (i&0xFFFFFFFE)==0xFFFE ) t = 0xFFFD;
-- assert( c==t );
-- assert( (z-zBuf)==n );
-- }
-- for(i=0; i<0x00110000; i++){
-- if( i>=0xD800 && i<0xE000 ) continue;
-- z = zBuf;
-- WRITE_UTF16LE(z, i);
-- n = (int)(z-zBuf);
-- assert( n>0 && n<=4 );
-- z[0] = 0;
-- z = zBuf;
-- READ_UTF16LE(z, 1, c);
-- assert( c==i );
-- assert( (z-zBuf)==n );
-- }
-- for(i=0; i<0x00110000; i++){
-- if( i>=0xD800 && i<0xE000 ) continue;
-- z = zBuf;
-- WRITE_UTF16BE(z, i);
-- n = (int)(z-zBuf);
-- assert( n>0 && n<=4 );
-- z[0] = 0;
-- z = zBuf;
-- READ_UTF16BE(z, 1, c);
-- assert( c==i );
-- assert( (z-zBuf)==n );
-+static int winMutexEnd(void){
-+ /* The first to decrement to 0 does actual shutdown
-+ ** (which should be the last to shutdown.) */
-+ if( InterlockedCompareExchange(&winMutex_lock, 0, 1)==1 ){
-+ if( winMutex_isInit==1 ){
-+ int i;
-+ for(i=0; i<ArraySize(winMutex_staticMutexes); i++){
-+ DeleteCriticalSection(&winMutex_staticMutexes[i].mutex);
-+ }
-+ winMutex_isInit = 0;
-+ }
- }
-+ return SQLITE_OK;
- }
--#endif /* SQLITE_TEST */
--#endif /* SQLITE_OMIT_UTF16 */
-
--/************** End of utf.c *************************************************/
--/************** Begin file util.c ********************************************/
- /*
--** 2001 September 15
--**
--** The author disclaims copyright to this source code. In place of
--** a legal notice, here is a blessing:
-+** The sqlite3_mutex_alloc() routine allocates a new
-+** mutex and returns a pointer to it. If it returns NULL
-+** that means that a mutex could not be allocated. SQLite
-+** will unwind its stack and return an error. The argument
-+** to sqlite3_mutex_alloc() is one of these integer constants:
- **
--** May you do good and not evil.
--** May you find forgiveness for yourself and forgive others.
--** May you share freely, never taking more than you give.
-+** <ul>
-+** <li> SQLITE_MUTEX_FAST
-+** <li> SQLITE_MUTEX_RECURSIVE
-+** <li> SQLITE_MUTEX_STATIC_MASTER
-+** <li> SQLITE_MUTEX_STATIC_MEM
-+** <li> SQLITE_MUTEX_STATIC_MEM2
-+** <li> SQLITE_MUTEX_STATIC_PRNG
-+** <li> SQLITE_MUTEX_STATIC_LRU
-+** <li> SQLITE_MUTEX_STATIC_PMEM
-+** </ul>
- **
--*************************************************************************
--** Utility functions used throughout sqlite.
-+** The first two constants cause sqlite3_mutex_alloc() to create
-+** a new mutex. The new mutex is recursive when SQLITE_MUTEX_RECURSIVE
-+** is used but not necessarily so when SQLITE_MUTEX_FAST is used.
-+** The mutex implementation does not need to make a distinction
-+** between SQLITE_MUTEX_RECURSIVE and SQLITE_MUTEX_FAST if it does
-+** not want to. But SQLite will only request a recursive mutex in
-+** cases where it really needs one. If a faster non-recursive mutex
-+** implementation is available on the host platform, the mutex subsystem
-+** might return such a mutex in response to SQLITE_MUTEX_FAST.
- **
--** This file contains functions for allocating memory, comparing
--** strings, and stuff like that.
-+** The other allowed parameters to sqlite3_mutex_alloc() each return
-+** a pointer to a static preexisting mutex. Six static mutexes are
-+** used by the current version of SQLite. Future versions of SQLite
-+** may add additional static mutexes. Static mutexes are for internal
-+** use by SQLite only. Applications that use SQLite mutexes should
-+** use only the dynamic mutexes returned by SQLITE_MUTEX_FAST or
-+** SQLITE_MUTEX_RECURSIVE.
- **
-+** Note that if one of the dynamic mutex parameters (SQLITE_MUTEX_FAST
-+** or SQLITE_MUTEX_RECURSIVE) is used then sqlite3_mutex_alloc()
-+** returns a different mutex on every call. But for the static
-+** mutex types, the same mutex is returned on every call that has
-+** the same type number.
- */
--/* #include <stdarg.h> */
--#ifdef SQLITE_HAVE_ISNAN
--# include <math.h>
-+static sqlite3_mutex *winMutexAlloc(int iType){
-+ sqlite3_mutex *p;
-+
-+ switch( iType ){
-+ case SQLITE_MUTEX_FAST:
-+ case SQLITE_MUTEX_RECURSIVE: {
-+ p = sqlite3MallocZero( sizeof(*p) );
-+ if( p ){
-+#ifdef SQLITE_DEBUG
-+ p->id = iType;
-+#endif
-+#if SQLITE_OS_WINRT
-+ InitializeCriticalSectionEx(&p->mutex, 0, 0);
-+#else
-+ InitializeCriticalSection(&p->mutex);
-+#endif
-+ }
-+ break;
-+ }
-+ default: {
-+ assert( winMutex_isInit==1 );
-+ assert( iType-2 >= 0 );
-+ assert( iType-2 < ArraySize(winMutex_staticMutexes) );
-+ p = &winMutex_staticMutexes[iType-2];
-+#ifdef SQLITE_DEBUG
-+ p->id = iType;
- #endif
-+ break;
-+ }
-+ }
-+ return p;
-+}
-+
-
- /*
--** Routine needed to support the testcase() macro.
-+** This routine deallocates a previously
-+** allocated mutex. SQLite is careful to deallocate every
-+** mutex that it allocates.
- */
--#ifdef SQLITE_COVERAGE_TEST
--SQLITE_PRIVATE void sqlite3Coverage(int x){
-- static unsigned dummy = 0;
-- dummy += (unsigned)x;
-+static void winMutexFree(sqlite3_mutex *p){
-+ assert( p );
-+ assert( p->nRef==0 && p->owner==0 );
-+ assert( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE );
-+ DeleteCriticalSection(&p->mutex);
-+ sqlite3_free(p);
- }
--#endif
-
--#ifndef SQLITE_OMIT_FLOATING_POINT
- /*
--** Return true if the floating point value is Not a Number (NaN).
--**
--** Use the math library isnan() function if compiled with SQLITE_HAVE_ISNAN.
--** Otherwise, we have our own implementation that works on most systems.
-+** The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt
-+** to enter a mutex. If another thread is already within the mutex,
-+** sqlite3_mutex_enter() will block and sqlite3_mutex_try() will return
-+** SQLITE_BUSY. The sqlite3_mutex_try() interface returns SQLITE_OK
-+** upon successful entry. Mutexes created using SQLITE_MUTEX_RECURSIVE can
-+** be entered multiple times by the same thread. In such cases the,
-+** mutex must be exited an equal number of times before another thread
-+** can enter. If the same thread tries to enter any other kind of mutex
-+** more than once, the behavior is undefined.
- */
--SQLITE_PRIVATE int sqlite3IsNaN(double x){
-- int rc; /* The value return */
--#if !defined(SQLITE_HAVE_ISNAN)
-+static void winMutexEnter(sqlite3_mutex *p){
-+#ifdef SQLITE_DEBUG
-+ DWORD tid = GetCurrentThreadId();
-+ assert( p->id==SQLITE_MUTEX_RECURSIVE || winMutexNotheld2(p, tid) );
-+#endif
-+ EnterCriticalSection(&p->mutex);
-+#ifdef SQLITE_DEBUG
-+ assert( p->nRef>0 || p->owner==0 );
-+ p->owner = tid;
-+ p->nRef++;
-+ if( p->trace ){
-+ printf("enter mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef);
-+ }
-+#endif
-+}
-+static int winMutexTry(sqlite3_mutex *p){
-+#ifndef NDEBUG
-+ DWORD tid = GetCurrentThreadId();
-+#endif
-+ int rc = SQLITE_BUSY;
-+ assert( p->id==SQLITE_MUTEX_RECURSIVE || winMutexNotheld2(p, tid) );
- /*
-- ** Systems that support the isnan() library function should probably
-- ** make use of it by compiling with -DSQLITE_HAVE_ISNAN. But we have
-- ** found that many systems do not have a working isnan() function so
-- ** this implementation is provided as an alternative.
-- **
-- ** This NaN test sometimes fails if compiled on GCC with -ffast-math.
-- ** On the other hand, the use of -ffast-math comes with the following
-- ** warning:
-- **
-- ** This option [-ffast-math] should never be turned on by any
-- ** -O option since it can result in incorrect output for programs
-- ** which depend on an exact implementation of IEEE or ISO
-- ** rules/specifications for math functions.
-- **
-- ** Under MSVC, this NaN test may fail if compiled with a floating-
-- ** point precision mode other than /fp:precise. From the MSDN
-- ** documentation:
-+ ** The sqlite3_mutex_try() routine is very rarely used, and when it
-+ ** is used it is merely an optimization. So it is OK for it to always
-+ ** fail.
- **
-- ** The compiler [with /fp:precise] will properly handle comparisons
-- ** involving NaN. For example, x != x evaluates to true if x is NaN
-- ** ...
-+ ** The TryEnterCriticalSection() interface is only available on WinNT.
-+ ** And some windows compilers complain if you try to use it without
-+ ** first doing some #defines that prevent SQLite from building on Win98.
-+ ** For that reason, we will omit this optimization for now. See
-+ ** ticket #2685.
- */
--#ifdef __FAST_MATH__
--# error SQLite will not work correctly with the -ffast-math option of GCC.
-+#if 0
-+ if( mutexIsNT() && TryEnterCriticalSection(&p->mutex) ){
-+ p->owner = tid;
-+ p->nRef++;
-+ rc = SQLITE_OK;
-+ }
-+#else
-+ UNUSED_PARAMETER(p);
-+#endif
-+#ifdef SQLITE_DEBUG
-+ if( rc==SQLITE_OK && p->trace ){
-+ printf("try mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef);
-+ }
- #endif
-- volatile double y = x;
-- volatile double z = y;
-- rc = (y!=z);
--#else /* if defined(SQLITE_HAVE_ISNAN) */
-- rc = isnan(x);
--#endif /* SQLITE_HAVE_ISNAN */
-- testcase( rc );
- return rc;
- }
--#endif /* SQLITE_OMIT_FLOATING_POINT */
-
- /*
--** Compute a string length that is limited to what can be stored in
--** lower 30 bits of a 32-bit signed integer.
--**
--** The value returned will never be negative. Nor will it ever be greater
--** than the actual length of the string. For very long strings (greater
--** than 1GiB) the value returned might be less than the true string length.
-+** The sqlite3_mutex_leave() routine exits a mutex that was
-+** previously entered by the same thread. The behavior
-+** is undefined if the mutex is not currently entered or
-+** is not currently allocated. SQLite will never do either.
- */
--SQLITE_PRIVATE int sqlite3Strlen30(const char *z){
-- const char *z2 = z;
-- if( z==0 ) return 0;
-- while( *z2 ){ z2++; }
-- return 0x3fffffff & (int)(z2 - z);
-+static void winMutexLeave(sqlite3_mutex *p){
-+#ifndef NDEBUG
-+ DWORD tid = GetCurrentThreadId();
-+ assert( p->nRef>0 );
-+ assert( p->owner==tid );
-+ p->nRef--;
-+ if( p->nRef==0 ) p->owner = 0;
-+ assert( p->nRef==0 || p->id==SQLITE_MUTEX_RECURSIVE );
-+#endif
-+ LeaveCriticalSection(&p->mutex);
-+#ifdef SQLITE_DEBUG
-+ if( p->trace ){
-+ printf("leave mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef);
-+ }
-+#endif
-+}
-+
-+SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3DefaultMutex(void){
-+ static const sqlite3_mutex_methods sMutex = {
-+ winMutexInit,
-+ winMutexEnd,
-+ winMutexAlloc,
-+ winMutexFree,
-+ winMutexEnter,
-+ winMutexTry,
-+ winMutexLeave,
-+#ifdef SQLITE_DEBUG
-+ winMutexHeld,
-+ winMutexNotheld
-+#else
-+ 0,
-+ 0
-+#endif
-+ };
-+
-+ return &sMutex;
- }
-+#endif /* SQLITE_MUTEX_W32 */
-
-+/************** End of mutex_w32.c *******************************************/
-+/************** Begin file malloc.c ******************************************/
- /*
--** Set the most recent error code and error string for the sqlite
--** handle "db". The error code is set to "err_code".
-+** 2001 September 15
- **
--** If it is not NULL, string zFormat specifies the format of the
--** error string in the style of the printf functions: The following
--** format characters are allowed:
-+** The author disclaims copyright to this source code. In place of
-+** a legal notice, here is a blessing:
- **
--** %s Insert a string
--** %z A string that should be freed after use
--** %d Insert an integer
--** %T Insert a token
--** %S Insert the first element of a SrcList
-+** May you do good and not evil.
-+** May you find forgiveness for yourself and forgive others.
-+** May you share freely, never taking more than you give.
- **
--** zFormat and any string tokens that follow it are assumed to be
--** encoded in UTF-8.
-+*************************************************************************
- **
--** To clear the most recent error for sqlite handle "db", sqlite3Error
--** should be called with err_code set to SQLITE_OK and zFormat set
--** to NULL.
-+** Memory allocation functions used throughout sqlite.
- */
--SQLITE_PRIVATE void sqlite3Error(sqlite3 *db, int err_code, const char *zFormat, ...){
-- if( db && (db->pErr || (db->pErr = sqlite3ValueNew(db))!=0) ){
-- db->errCode = err_code;
-- if( zFormat ){
-- char *z;
-- va_list ap;
-- va_start(ap, zFormat);
-- z = sqlite3VMPrintf(db, zFormat, ap);
-- va_end(ap);
-- sqlite3ValueSetStr(db->pErr, -1, z, SQLITE_UTF8, SQLITE_DYNAMIC);
-- }else{
-- sqlite3ValueSetStr(db->pErr, 0, 0, SQLITE_UTF8, SQLITE_STATIC);
-- }
-- }
--}
-+/* #include <stdarg.h> */
-
- /*
--** Add an error message to pParse->zErrMsg and increment pParse->nErr.
--** The following formatting characters are allowed:
--**
--** %s Insert a string
--** %z A string that should be freed after use
--** %d Insert an integer
--** %T Insert a token
--** %S Insert the first element of a SrcList
--**
--** This function should be used to report any error that occurs whilst
--** compiling an SQL statement (i.e. within sqlite3_prepare()). The
--** last thing the sqlite3_prepare() function does is copy the error
--** stored by this function into the database handle using sqlite3Error().
--** Function sqlite3Error() should be used during statement execution
--** (sqlite3_step() etc.).
-+** Attempt to release up to n bytes of non-essential memory currently
-+** held by SQLite. An example of non-essential memory is memory used to
-+** cache database pages that are not currently in use.
- */
--SQLITE_PRIVATE void sqlite3ErrorMsg(Parse *pParse, const char *zFormat, ...){
-- char *zMsg;
-- va_list ap;
-- sqlite3 *db = pParse->db;
-- va_start(ap, zFormat);
-- zMsg = sqlite3VMPrintf(db, zFormat, ap);
-- va_end(ap);
-- if( db->suppressErr ){
-- sqlite3DbFree(db, zMsg);
-- }else{
-- pParse->nErr++;
-- sqlite3DbFree(db, pParse->zErrMsg);
-- pParse->zErrMsg = zMsg;
-- pParse->rc = SQLITE_ERROR;
-- }
-+SQLITE_API int sqlite3_release_memory(int n){
-+#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
-+ return sqlite3PcacheReleaseMemory(n);
-+#else
-+ /* IMPLEMENTATION-OF: R-34391-24921 The sqlite3_release_memory() routine
-+ ** is a no-op returning zero if SQLite is not compiled with
-+ ** SQLITE_ENABLE_MEMORY_MANAGEMENT. */
-+ UNUSED_PARAMETER(n);
-+ return 0;
-+#endif
- }
-
- /*
--** Convert an SQL-style quoted string into a normal string by removing
--** the quote characters. The conversion is done in-place. If the
--** input does not begin with a quote character, then this routine
--** is a no-op.
--**
--** The input string must be zero-terminated. A new zero-terminator
--** is added to the dequoted string.
--**
--** The return value is -1 if no dequoting occurs or the length of the
--** dequoted string, exclusive of the zero terminator, if dequoting does
--** occur.
--**
--** 2002-Feb-14: This routine is extended to remove MS-Access style
--** brackets from around identifers. For example: "[a-b-c]" becomes
--** "a-b-c".
-+** An instance of the following object records the location of
-+** each unused scratch buffer.
- */
--SQLITE_PRIVATE int sqlite3Dequote(char *z){
-- char quote;
-- int i, j;
-- if( z==0 ) return -1;
-- quote = z[0];
-- switch( quote ){
-- case '\'': break;
-- case '"': break;
-- case '`': break; /* For MySQL compatibility */
-- case '[': quote = ']'; break; /* For MS SqlServer compatibility */
-- default: return -1;
-- }
-- for(i=1, j=0; ALWAYS(z[i]); i++){
-- if( z[i]==quote ){
-- if( z[i+1]==quote ){
-- z[j++] = quote;
-- i++;
-- }else{
-- break;
-- }
-- }else{
-- z[j++] = z[i];
-- }
-- }
-- z[j] = 0;
-- return j;
--}
-+typedef struct ScratchFreeslot {
-+ struct ScratchFreeslot *pNext; /* Next unused scratch buffer */
-+} ScratchFreeslot;
-
--/* Convenient short-hand */
--#define UpperToLower sqlite3UpperToLower
-+/*
-+** State information local to the memory allocation subsystem.
-+*/
-+static SQLITE_WSD struct Mem0Global {
-+ sqlite3_mutex *mutex; /* Mutex to serialize access */
-+
-+ /*
-+ ** The alarm callback and its arguments. The mem0.mutex lock will
-+ ** be held while the callback is running. Recursive calls into
-+ ** the memory subsystem are allowed, but no new callbacks will be
-+ ** issued.
-+ */
-+ sqlite3_int64 alarmThreshold;
-+ void (*alarmCallback)(void*, sqlite3_int64,int);
-+ void *alarmArg;
-+
-+ /*
-+ ** Pointers to the end of sqlite3GlobalConfig.pScratch memory
-+ ** (so that a range test can be used to determine if an allocation
-+ ** being freed came from pScratch) and a pointer to the list of
-+ ** unused scratch allocations.
-+ */
-+ void *pScratchEnd;
-+ ScratchFreeslot *pScratchFree;
-+ u32 nScratchFree;
-+
-+ /*
-+ ** True if heap is nearly "full" where "full" is defined by the
-+ ** sqlite3_soft_heap_limit() setting.
-+ */
-+ int nearlyFull;
-+} mem0 = { 0, 0, 0, 0, 0, 0, 0, 0 };
-+
-+#define mem0 GLOBAL(struct Mem0Global, mem0)
-
- /*
--** Some systems have stricmp(). Others have strcasecmp(). Because
--** there is no consistency, we will define our own.
--**
--** IMPLEMENTATION-OF: R-30243-02494 The sqlite3_stricmp() and
--** sqlite3_strnicmp() APIs allow applications and extensions to compare
--** the contents of two buffers containing UTF-8 strings in a
--** case-independent fashion, using the same definition of "case
--** independence" that SQLite uses internally when comparing identifiers.
-+** This routine runs when the memory allocator sees that the
-+** total memory allocation is about to exceed the soft heap
-+** limit.
- */
--SQLITE_API int sqlite3_stricmp(const char *zLeft, const char *zRight){
-- register unsigned char *a, *b;
-- a = (unsigned char *)zLeft;
-- b = (unsigned char *)zRight;
-- while( *a!=0 && UpperToLower[*a]==UpperToLower[*b]){ a++; b++; }
-- return UpperToLower[*a] - UpperToLower[*b];
--}
--SQLITE_API int sqlite3_strnicmp(const char *zLeft, const char *zRight, int N){
-- register unsigned char *a, *b;
-- a = (unsigned char *)zLeft;
-- b = (unsigned char *)zRight;
-- while( N-- > 0 && *a!=0 && UpperToLower[*a]==UpperToLower[*b]){ a++; b++; }
-- return N<0 ? 0 : UpperToLower[*a] - UpperToLower[*b];
-+static void softHeapLimitEnforcer(
-+ void *NotUsed,
-+ sqlite3_int64 NotUsed2,
-+ int allocSize
-+){
-+ UNUSED_PARAMETER2(NotUsed, NotUsed2);
-+ sqlite3_release_memory(allocSize);
- }
-
- /*
--** The string z[] is an text representation of a real number.
--** Convert this string to a double and write it into *pResult.
--**
--** The string z[] is length bytes in length (bytes, not characters) and
--** uses the encoding enc. The string is not necessarily zero-terminated.
--**
--** Return TRUE if the result is a valid real number (or integer) and FALSE
--** if the string is empty or contains extraneous text. Valid numbers
--** are in one of these formats:
--**
--** [+-]digits[E[+-]digits]
--** [+-]digits.[digits][E[+-]digits]
--** [+-].digits[E[+-]digits]
--**
--** Leading and trailing whitespace is ignored for the purpose of determining
--** validity.
--**
--** If some prefix of the input string is a valid number, this routine
--** returns FALSE but it still converts the prefix and writes the result
--** into *pResult.
-+** Change the alarm callback
- */
--SQLITE_PRIVATE int sqlite3AtoF(const char *z, double *pResult, int length, u8 enc){
--#ifndef SQLITE_OMIT_FLOATING_POINT
-- int incr;
-- const char *zEnd = z + length;
-- /* sign * significand * (10 ^ (esign * exponent)) */
-- int sign = 1; /* sign of significand */
-- i64 s = 0; /* significand */
-- int d = 0; /* adjust exponent for shifting decimal point */
-- int esign = 1; /* sign of exponent */
-- int e = 0; /* exponent */
-- int eValid = 1; /* True exponent is either not used or is well-formed */
-- double result;
-- int nDigits = 0;
-- int nonNum = 0;
-+static int sqlite3MemoryAlarm(
-+ void(*xCallback)(void *pArg, sqlite3_int64 used,int N),
-+ void *pArg,
-+ sqlite3_int64 iThreshold
-+){
-+ int nUsed;
-+ sqlite3_mutex_enter(mem0.mutex);
-+ mem0.alarmCallback = xCallback;
-+ mem0.alarmArg = pArg;
-+ mem0.alarmThreshold = iThreshold;
-+ nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED);
-+ mem0.nearlyFull = (iThreshold>0 && iThreshold<=nUsed);
-+ sqlite3_mutex_leave(mem0.mutex);
-+ return SQLITE_OK;
-+}
-
-- assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE );
-- *pResult = 0.0; /* Default return value, in case of an error */
-+#ifndef SQLITE_OMIT_DEPRECATED
-+/*
-+** Deprecated external interface. Internal/core SQLite code
-+** should call sqlite3MemoryAlarm.
-+*/
-+SQLITE_API int sqlite3_memory_alarm(
-+ void(*xCallback)(void *pArg, sqlite3_int64 used,int N),
-+ void *pArg,
-+ sqlite3_int64 iThreshold
-+){
-+ return sqlite3MemoryAlarm(xCallback, pArg, iThreshold);
-+}
-+#endif
-
-- if( enc==SQLITE_UTF8 ){
-- incr = 1;
-+/*
-+** Set the soft heap-size limit for the library. Passing a zero or
-+** negative value indicates no limit.
-+*/
-+SQLITE_API sqlite3_int64 sqlite3_soft_heap_limit64(sqlite3_int64 n){
-+ sqlite3_int64 priorLimit;
-+ sqlite3_int64 excess;
-+#ifndef SQLITE_OMIT_AUTOINIT
-+ int rc = sqlite3_initialize();
-+ if( rc ) return -1;
-+#endif
-+ sqlite3_mutex_enter(mem0.mutex);
-+ priorLimit = mem0.alarmThreshold;
-+ sqlite3_mutex_leave(mem0.mutex);
-+ if( n<0 ) return priorLimit;
-+ if( n>0 ){
-+ sqlite3MemoryAlarm(softHeapLimitEnforcer, 0, n);
- }else{
-- int i;
-- incr = 2;
-- assert( SQLITE_UTF16LE==2 && SQLITE_UTF16BE==3 );
-- for(i=3-enc; i<length && z[i]==0; i+=2){}
-- nonNum = i<length;
-- zEnd = z+i+enc-3;
-- z += (enc&1);
-- }
--
-- /* skip leading spaces */
-- while( z<zEnd && sqlite3Isspace(*z) ) z+=incr;
-- if( z>=zEnd ) return 0;
--
-- /* get sign of significand */
-- if( *z=='-' ){
-- sign = -1;
-- z+=incr;
-- }else if( *z=='+' ){
-- z+=incr;
-+ sqlite3MemoryAlarm(0, 0, 0);
- }
-+ excess = sqlite3_memory_used() - n;
-+ if( excess>0 ) sqlite3_release_memory((int)(excess & 0x7fffffff));
-+ return priorLimit;
-+}
-+SQLITE_API void sqlite3_soft_heap_limit(int n){
-+ if( n<0 ) n = 0;
-+ sqlite3_soft_heap_limit64(n);
-+}
-
-- /* skip leading zeroes */
-- while( z<zEnd && z[0]=='0' ) z+=incr, nDigits++;
--
-- /* copy max significant digits to significand */
-- while( z<zEnd && sqlite3Isdigit(*z) && s<((LARGEST_INT64-9)/10) ){
-- s = s*10 + (*z - '0');
-- z+=incr, nDigits++;
-+/*
-+** Initialize the memory allocation subsystem.
-+*/
-+SQLITE_PRIVATE int sqlite3MallocInit(void){
-+ if( sqlite3GlobalConfig.m.xMalloc==0 ){
-+ sqlite3MemSetDefault();
- }
--
-- /* skip non-significant significand digits
-- ** (increase exponent by d to shift decimal left) */
-- while( z<zEnd && sqlite3Isdigit(*z) ) z+=incr, nDigits++, d++;
-- if( z>=zEnd ) goto do_atof_calc;
--
-- /* if decimal point is present */
-- if( *z=='.' ){
-- z+=incr;
-- /* copy digits from after decimal to significand
-- ** (decrease exponent by d to shift decimal right) */
-- while( z<zEnd && sqlite3Isdigit(*z) && s<((LARGEST_INT64-9)/10) ){
-- s = s*10 + (*z - '0');
-- z+=incr, nDigits++, d--;
-- }
-- /* skip non-significant digits */
-- while( z<zEnd && sqlite3Isdigit(*z) ) z+=incr, nDigits++;
-+ memset(&mem0, 0, sizeof(mem0));
-+ if( sqlite3GlobalConfig.bCoreMutex ){
-+ mem0.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM);
- }
-- if( z>=zEnd ) goto do_atof_calc;
--
-- /* if exponent is present */
-- if( *z=='e' || *z=='E' ){
-- z+=incr;
-- eValid = 0;
-- if( z>=zEnd ) goto do_atof_calc;
-- /* get sign of exponent */
-- if( *z=='-' ){
-- esign = -1;
-- z+=incr;
-- }else if( *z=='+' ){
-- z+=incr;
-- }
-- /* copy digits to exponent */
-- while( z<zEnd && sqlite3Isdigit(*z) ){
-- e = e<10000 ? (e*10 + (*z - '0')) : 10000;
-- z+=incr;
-- eValid = 1;
-+ if( sqlite3GlobalConfig.pScratch && sqlite3GlobalConfig.szScratch>=100
-+ && sqlite3GlobalConfig.nScratch>0 ){
-+ int i, n, sz;
-+ ScratchFreeslot *pSlot;
-+ sz = ROUNDDOWN8(sqlite3GlobalConfig.szScratch);
-+ sqlite3GlobalConfig.szScratch = sz;
-+ pSlot = (ScratchFreeslot*)sqlite3GlobalConfig.pScratch;
-+ n = sqlite3GlobalConfig.nScratch;
-+ mem0.pScratchFree = pSlot;
-+ mem0.nScratchFree = n;
-+ for(i=0; i<n-1; i++){
-+ pSlot->pNext = (ScratchFreeslot*)(sz+(char*)pSlot);
-+ pSlot = pSlot->pNext;
- }
-+ pSlot->pNext = 0;
-+ mem0.pScratchEnd = (void*)&pSlot[1];
-+ }else{
-+ mem0.pScratchEnd = 0;
-+ sqlite3GlobalConfig.pScratch = 0;
-+ sqlite3GlobalConfig.szScratch = 0;
-+ sqlite3GlobalConfig.nScratch = 0;
- }
--
-- /* skip trailing spaces */
-- if( nDigits && eValid ){
-- while( z<zEnd && sqlite3Isspace(*z) ) z+=incr;
-- }
--
--do_atof_calc:
-- /* adjust exponent by d, and update sign */
-- e = (e*esign) + d;
-- if( e<0 ) {
-- esign = -1;
-- e *= -1;
-- } else {
-- esign = 1;
-+ if( sqlite3GlobalConfig.pPage==0 || sqlite3GlobalConfig.szPage<512
-+ || sqlite3GlobalConfig.nPage<1 ){
-+ sqlite3GlobalConfig.pPage = 0;
-+ sqlite3GlobalConfig.szPage = 0;
-+ sqlite3GlobalConfig.nPage = 0;
- }
-+ return sqlite3GlobalConfig.m.xInit(sqlite3GlobalConfig.m.pAppData);
-+}
-
-- /* if 0 significand */
-- if( !s ) {
-- /* In the IEEE 754 standard, zero is signed.
-- ** Add the sign if we've seen at least one digit */
-- result = (sign<0 && nDigits) ? -(double)0 : (double)0;
-- } else {
-- /* attempt to reduce exponent */
-- if( esign>0 ){
-- while( s<(LARGEST_INT64/10) && e>0 ) e--,s*=10;
-- }else{
-- while( !(s%10) && e>0 ) e--,s/=10;
-- }
--
-- /* adjust the sign of significand */
-- s = sign<0 ? -s : s;
-+/*
-+** Return true if the heap is currently under memory pressure - in other
-+** words if the amount of heap used is close to the limit set by
-+** sqlite3_soft_heap_limit().
-+*/
-+SQLITE_PRIVATE int sqlite3HeapNearlyFull(void){
-+ return mem0.nearlyFull;
-+}
-
-- /* if exponent, scale significand as appropriate
-- ** and store in result. */
-- if( e ){
-- LONGDOUBLE_TYPE scale = 1.0;
-- /* attempt to handle extremely small/large numbers better */
-- if( e>307 && e<342 ){
-- while( e%308 ) { scale *= 1.0e+1; e -= 1; }
-- if( esign<0 ){
-- result = s / scale;
-- result /= 1.0e+308;
-- }else{
-- result = s * scale;
-- result *= 1.0e+308;
-- }
-- }else if( e>=342 ){
-- if( esign<0 ){
-- result = 0.0*s;
-- }else{
-- result = 1e308*1e308*s; /* Infinity */
-- }
-- }else{
-- /* 1.0e+22 is the largest power of 10 than can be
-- ** represented exactly. */
-- while( e%22 ) { scale *= 1.0e+1; e -= 1; }
-- while( e>0 ) { scale *= 1.0e+22; e -= 22; }
-- if( esign<0 ){
-- result = s / scale;
-- }else{
-- result = s * scale;
-- }
-- }
-- } else {
-- result = (double)s;
-- }
-+/*
-+** Deinitialize the memory allocation subsystem.
-+*/
-+SQLITE_PRIVATE void sqlite3MallocEnd(void){
-+ if( sqlite3GlobalConfig.m.xShutdown ){
-+ sqlite3GlobalConfig.m.xShutdown(sqlite3GlobalConfig.m.pAppData);
- }
-+ memset(&mem0, 0, sizeof(mem0));
-+}
-
-- /* store the result */
-- *pResult = result;
--
-- /* return true if number and no extra non-whitespace chracters after */
-- return z>=zEnd && nDigits>0 && eValid && nonNum==0;
--#else
-- return !sqlite3Atoi64(z, pResult, length, enc);
--#endif /* SQLITE_OMIT_FLOATING_POINT */
-+/*
-+** Return the amount of memory currently checked out.
-+*/
-+SQLITE_API sqlite3_int64 sqlite3_memory_used(void){
-+ int n, mx;
-+ sqlite3_int64 res;
-+ sqlite3_status(SQLITE_STATUS_MEMORY_USED, &n, &mx, 0);
-+ res = (sqlite3_int64)n; /* Work around bug in Borland C. Ticket #3216 */
-+ return res;
- }
-
- /*
--** Compare the 19-character string zNum against the text representation
--** value 2^63: 9223372036854775808. Return negative, zero, or positive
--** if zNum is less than, equal to, or greater than the string.
--** Note that zNum must contain exactly 19 characters.
--**
--** Unlike memcmp() this routine is guaranteed to return the difference
--** in the values of the last digit if the only difference is in the
--** last digit. So, for example,
--**
--** compare2pow63("9223372036854775800", 1)
--**
--** will return -8.
-+** Return the maximum amount of memory that has ever been
-+** checked out since either the beginning of this process
-+** or since the most recent reset.
- */
--static int compare2pow63(const char *zNum, int incr){
-- int c = 0;
-- int i;
-- /* 012345678901234567 */
-- const char *pow63 = "922337203685477580";
-- for(i=0; c==0 && i<18; i++){
-- c = (zNum[i*incr]-pow63[i])*10;
-- }
-- if( c==0 ){
-- c = zNum[18*incr] - '8';
-- testcase( c==(-1) );
-- testcase( c==0 );
-- testcase( c==(+1) );
-- }
-- return c;
-+SQLITE_API sqlite3_int64 sqlite3_memory_highwater(int resetFlag){
-+ int n, mx;
-+ sqlite3_int64 res;
-+ sqlite3_status(SQLITE_STATUS_MEMORY_USED, &n, &mx, resetFlag);
-+ res = (sqlite3_int64)mx; /* Work around bug in Borland C. Ticket #3216 */
-+ return res;
- }
-
-+/*
-+** Trigger the alarm
-+*/
-+static void sqlite3MallocAlarm(int nByte){
-+ void (*xCallback)(void*,sqlite3_int64,int);
-+ sqlite3_int64 nowUsed;
-+ void *pArg;
-+ if( mem0.alarmCallback==0 ) return;
-+ xCallback = mem0.alarmCallback;
-+ nowUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED);
-+ pArg = mem0.alarmArg;
-+ mem0.alarmCallback = 0;
-+ sqlite3_mutex_leave(mem0.mutex);
-+ xCallback(pArg, nowUsed, nByte);
-+ sqlite3_mutex_enter(mem0.mutex);
-+ mem0.alarmCallback = xCallback;
-+ mem0.alarmArg = pArg;
-+}
-
- /*
--** Convert zNum to a 64-bit signed integer.
--**
--** If the zNum value is representable as a 64-bit twos-complement
--** integer, then write that value into *pNum and return 0.
--**
--** If zNum is exactly 9223372036854665808, return 2. This special
--** case is broken out because while 9223372036854665808 cannot be a
--** signed 64-bit integer, its negative -9223372036854665808 can be.
--**
--** If zNum is too big for a 64-bit integer and is not
--** 9223372036854665808 or if zNum contains any non-numeric text,
--** then return 1.
--**
--** length is the number of bytes in the string (bytes, not characters).
--** The string is not necessarily zero-terminated. The encoding is
--** given by enc.
-+** Do a memory allocation with statistics and alarms. Assume the
-+** lock is already held.
- */
--SQLITE_PRIVATE int sqlite3Atoi64(const char *zNum, i64 *pNum, int length, u8 enc){
-- int incr;
-- u64 u = 0;
-- int neg = 0; /* assume positive */
-- int i;
-- int c = 0;
-- int nonNum = 0;
-- const char *zStart;
-- const char *zEnd = zNum + length;
-- assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE );
-- if( enc==SQLITE_UTF8 ){
-- incr = 1;
-- }else{
-- incr = 2;
-- assert( SQLITE_UTF16LE==2 && SQLITE_UTF16BE==3 );
-- for(i=3-enc; i<length && zNum[i]==0; i+=2){}
-- nonNum = i<length;
-- zEnd = zNum+i+enc-3;
-- zNum += (enc&1);
-- }
-- while( zNum<zEnd && sqlite3Isspace(*zNum) ) zNum+=incr;
-- if( zNum<zEnd ){
-- if( *zNum=='-' ){
-- neg = 1;
-- zNum+=incr;
-- }else if( *zNum=='+' ){
-- zNum+=incr;
-+static int mallocWithAlarm(int n, void **pp){
-+ int nFull;
-+ void *p;
-+ assert( sqlite3_mutex_held(mem0.mutex) );
-+ nFull = sqlite3GlobalConfig.m.xRoundup(n);
-+ sqlite3StatusSet(SQLITE_STATUS_MALLOC_SIZE, n);
-+ if( mem0.alarmCallback!=0 ){
-+ int nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED);
-+ if( nUsed >= mem0.alarmThreshold - nFull ){
-+ mem0.nearlyFull = 1;
-+ sqlite3MallocAlarm(nFull);
-+ }else{
-+ mem0.nearlyFull = 0;
- }
- }
-- zStart = zNum;
-- while( zNum<zEnd && zNum[0]=='0' ){ zNum+=incr; } /* Skip leading zeros. */
-- for(i=0; &zNum[i]<zEnd && (c=zNum[i])>='0' && c<='9'; i+=incr){
-- u = u*10 + c - '0';
-+ p = sqlite3GlobalConfig.m.xMalloc(nFull);
-+#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
-+ if( p==0 && mem0.alarmCallback ){
-+ sqlite3MallocAlarm(nFull);
-+ p = sqlite3GlobalConfig.m.xMalloc(nFull);
- }
-- if( u>LARGEST_INT64 ){
-- *pNum = SMALLEST_INT64;
-- }else if( neg ){
-- *pNum = -(i64)u;
-- }else{
-- *pNum = (i64)u;
-+#endif
-+ if( p ){
-+ nFull = sqlite3MallocSize(p);
-+ sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, nFull);
-+ sqlite3StatusAdd(SQLITE_STATUS_MALLOC_COUNT, 1);
- }
-- testcase( i==18 );
-- testcase( i==19 );
-- testcase( i==20 );
-- if( (c!=0 && &zNum[i]<zEnd) || (i==0 && zStart==zNum) || i>19*incr || nonNum ){
-- /* zNum is empty or contains non-numeric text or is longer
-- ** than 19 digits (thus guaranteeing that it is too large) */
-- return 1;
-- }else if( i<19*incr ){
-- /* Less than 19 digits, so we know that it fits in 64 bits */
-- assert( u<=LARGEST_INT64 );
-- return 0;
-+ *pp = p;
-+ return nFull;
-+}
-+
-+/*
-+** Allocate memory. This routine is like sqlite3_malloc() except that it
-+** assumes the memory subsystem has already been initialized.
-+*/
-+SQLITE_PRIVATE void *sqlite3Malloc(int n){
-+ void *p;
-+ if( n<=0 /* IMP: R-65312-04917 */
-+ || n>=0x7fffff00
-+ ){
-+ /* A memory allocation of a number of bytes which is near the maximum
-+ ** signed integer value might cause an integer overflow inside of the
-+ ** xMalloc(). Hence we limit the maximum size to 0x7fffff00, giving
-+ ** 255 bytes of overhead. SQLite itself will never use anything near
-+ ** this amount. The only way to reach the limit is with sqlite3_malloc() */
-+ p = 0;
-+ }else if( sqlite3GlobalConfig.bMemstat ){
-+ sqlite3_mutex_enter(mem0.mutex);
-+ mallocWithAlarm(n, &p);
-+ sqlite3_mutex_leave(mem0.mutex);
- }else{
-- /* zNum is a 19-digit numbers. Compare it against 9223372036854775808. */
-- c = compare2pow63(zNum, incr);
-- if( c<0 ){
-- /* zNum is less than 9223372036854775808 so it fits */
-- assert( u<=LARGEST_INT64 );
-- return 0;
-- }else if( c>0 ){
-- /* zNum is greater than 9223372036854775808 so it overflows */
-- return 1;
-- }else{
-- /* zNum is exactly 9223372036854775808. Fits if negative. The
-- ** special case 2 overflow if positive */
-- assert( u-1==LARGEST_INT64 );
-- assert( (*pNum)==SMALLEST_INT64 );
-- return neg ? 0 : 2;
-- }
-+ p = sqlite3GlobalConfig.m.xMalloc(n);
- }
-+ assert( EIGHT_BYTE_ALIGNMENT(p) ); /* IMP: R-04675-44850 */
-+ return p;
- }
-
- /*
--** If zNum represents an integer that will fit in 32-bits, then set
--** *pValue to that integer and return true. Otherwise return false.
--**
--** Any non-numeric characters that following zNum are ignored.
--** This is different from sqlite3Atoi64() which requires the
--** input number to be zero-terminated.
-+** This version of the memory allocation is for use by the application.
-+** First make sure the memory subsystem is initialized, then do the
-+** allocation.
- */
--SQLITE_PRIVATE int sqlite3GetInt32(const char *zNum, int *pValue){
-- sqlite_int64 v = 0;
-- int i, c;
-- int neg = 0;
-- if( zNum[0]=='-' ){
-- neg = 1;
-- zNum++;
-- }else if( zNum[0]=='+' ){
-- zNum++;
-- }
-- while( zNum[0]=='0' ) zNum++;
-- for(i=0; i<11 && (c = zNum[i] - '0')>=0 && c<=9; i++){
-- v = v*10 + c;
-- }
-+SQLITE_API void *sqlite3_malloc(int n){
-+#ifndef SQLITE_OMIT_AUTOINIT
-+ if( sqlite3_initialize() ) return 0;
-+#endif
-+ return sqlite3Malloc(n);
-+}
-
-- /* The longest decimal representation of a 32 bit integer is 10 digits:
-- **
-- ** 1234567890
-- ** 2^31 -> 2147483648
-- */
-- testcase( i==10 );
-- if( i>10 ){
-- return 0;
-- }
-- testcase( v-neg==2147483647 );
-- if( v-neg>2147483647 ){
-- return 0;
-+/*
-+** Each thread may only have a single outstanding allocation from
-+** xScratchMalloc(). We verify this constraint in the single-threaded
-+** case by setting scratchAllocOut to 1 when an allocation
-+** is outstanding clearing it when the allocation is freed.
-+*/
-+#if SQLITE_THREADSAFE==0 && !defined(NDEBUG)
-+static int scratchAllocOut = 0;
-+#endif
-+
-+
-+/*
-+** Allocate memory that is to be used and released right away.
-+** This routine is similar to alloca() in that it is not intended
-+** for situations where the memory might be held long-term. This
-+** routine is intended to get memory to old large transient data
-+** structures that would not normally fit on the stack of an
-+** embedded processor.
-+*/
-+SQLITE_PRIVATE void *sqlite3ScratchMalloc(int n){
-+ void *p;
-+ assert( n>0 );
-+
-+ sqlite3_mutex_enter(mem0.mutex);
-+ if( mem0.nScratchFree && sqlite3GlobalConfig.szScratch>=n ){
-+ p = mem0.pScratchFree;
-+ mem0.pScratchFree = mem0.pScratchFree->pNext;
-+ mem0.nScratchFree--;
-+ sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_USED, 1);
-+ sqlite3StatusSet(SQLITE_STATUS_SCRATCH_SIZE, n);
-+ sqlite3_mutex_leave(mem0.mutex);
-+ }else{
-+ if( sqlite3GlobalConfig.bMemstat ){
-+ sqlite3StatusSet(SQLITE_STATUS_SCRATCH_SIZE, n);
-+ n = mallocWithAlarm(n, &p);
-+ if( p ) sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_OVERFLOW, n);
-+ sqlite3_mutex_leave(mem0.mutex);
-+ }else{
-+ sqlite3_mutex_leave(mem0.mutex);
-+ p = sqlite3GlobalConfig.m.xMalloc(n);
-+ }
-+ sqlite3MemdebugSetType(p, MEMTYPE_SCRATCH);
- }
-- if( neg ){
-- v = -v;
-+ assert( sqlite3_mutex_notheld(mem0.mutex) );
-+
-+
-+#if SQLITE_THREADSAFE==0 && !defined(NDEBUG)
-+ /* Verify that no more than two scratch allocations per thread
-+ ** are outstanding at one time. (This is only checked in the
-+ ** single-threaded case since checking in the multi-threaded case
-+ ** would be much more complicated.) */
-+ assert( scratchAllocOut<=1 );
-+ if( p ) scratchAllocOut++;
-+#endif
-+
-+ return p;
-+}
-+SQLITE_PRIVATE void sqlite3ScratchFree(void *p){
-+ if( p ){
-+
-+#if SQLITE_THREADSAFE==0 && !defined(NDEBUG)
-+ /* Verify that no more than two scratch allocation per thread
-+ ** is outstanding at one time. (This is only checked in the
-+ ** single-threaded case since checking in the multi-threaded case
-+ ** would be much more complicated.) */
-+ assert( scratchAllocOut>=1 && scratchAllocOut<=2 );
-+ scratchAllocOut--;
-+#endif
-+
-+ if( p>=sqlite3GlobalConfig.pScratch && p<mem0.pScratchEnd ){
-+ /* Release memory from the SQLITE_CONFIG_SCRATCH allocation */
-+ ScratchFreeslot *pSlot;
-+ pSlot = (ScratchFreeslot*)p;
-+ sqlite3_mutex_enter(mem0.mutex);
-+ pSlot->pNext = mem0.pScratchFree;
-+ mem0.pScratchFree = pSlot;
-+ mem0.nScratchFree++;
-+ assert( mem0.nScratchFree <= (u32)sqlite3GlobalConfig.nScratch );
-+ sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_USED, -1);
-+ sqlite3_mutex_leave(mem0.mutex);
-+ }else{
-+ /* Release memory back to the heap */
-+ assert( sqlite3MemdebugHasType(p, MEMTYPE_SCRATCH) );
-+ assert( sqlite3MemdebugNoType(p, ~MEMTYPE_SCRATCH) );
-+ sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
-+ if( sqlite3GlobalConfig.bMemstat ){
-+ int iSize = sqlite3MallocSize(p);
-+ sqlite3_mutex_enter(mem0.mutex);
-+ sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_OVERFLOW, -iSize);
-+ sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, -iSize);
-+ sqlite3StatusAdd(SQLITE_STATUS_MALLOC_COUNT, -1);
-+ sqlite3GlobalConfig.m.xFree(p);
-+ sqlite3_mutex_leave(mem0.mutex);
-+ }else{
-+ sqlite3GlobalConfig.m.xFree(p);
-+ }
-+ }
- }
-- *pValue = (int)v;
-- return 1;
- }
-
- /*
--** Return a 32-bit integer value extracted from a string. If the
--** string is not an integer, just return 0.
-+** TRUE if p is a lookaside memory allocation from db
- */
--SQLITE_PRIVATE int sqlite3Atoi(const char *z){
-- int x = 0;
-- if( z ) sqlite3GetInt32(z, &x);
-- return x;
-+#ifndef SQLITE_OMIT_LOOKASIDE
-+static int isLookaside(sqlite3 *db, void *p){
-+ return p && p>=db->lookaside.pStart && p<db->lookaside.pEnd;
- }
-+#else
-+#define isLookaside(A,B) 0
-+#endif
-
- /*
--** The variable-length integer encoding is as follows:
--**
--** KEY:
--** A = 0xxxxxxx 7 bits of data and one flag bit
--** B = 1xxxxxxx 7 bits of data and one flag bit
--** C = xxxxxxxx 8 bits of data
--**
--** 7 bits - A
--** 14 bits - BA
--** 21 bits - BBA
--** 28 bits - BBBA
--** 35 bits - BBBBA
--** 42 bits - BBBBBA
--** 49 bits - BBBBBBA
--** 56 bits - BBBBBBBA
--** 64 bits - BBBBBBBBC
-+** Return the size of a memory allocation previously obtained from
-+** sqlite3Malloc() or sqlite3_malloc().
- */
-+SQLITE_PRIVATE int sqlite3MallocSize(void *p){
-+ assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) );
-+ assert( sqlite3MemdebugNoType(p, MEMTYPE_DB) );
-+ return sqlite3GlobalConfig.m.xSize(p);
-+}
-+SQLITE_PRIVATE int sqlite3DbMallocSize(sqlite3 *db, void *p){
-+ assert( db==0 || sqlite3_mutex_held(db->mutex) );
-+ if( db && isLookaside(db, p) ){
-+ return db->lookaside.sz;
-+ }else{
-+ assert( sqlite3MemdebugHasType(p, MEMTYPE_DB) );
-+ assert( sqlite3MemdebugHasType(p, MEMTYPE_LOOKASIDE|MEMTYPE_HEAP) );
-+ assert( db!=0 || sqlite3MemdebugNoType(p, MEMTYPE_LOOKASIDE) );
-+ return sqlite3GlobalConfig.m.xSize(p);
-+ }
-+}
-
- /*
--** Write a 64-bit variable-length integer to memory starting at p[0].
--** The length of data write will be between 1 and 9 bytes. The number
--** of bytes written is returned.
--**
--** A variable-length integer consists of the lower 7 bits of each byte
--** for all bytes that have the 8th bit set and one byte with the 8th
--** bit clear. Except, if we get to the 9th byte, it stores the full
--** 8 bits and is the last byte.
-+** Free memory previously obtained from sqlite3Malloc().
- */
--SQLITE_PRIVATE int sqlite3PutVarint(unsigned char *p, u64 v){
-- int i, j, n;
-- u8 buf[10];
-- if( v & (((u64)0xff000000)<<32) ){
-- p[8] = (u8)v;
-- v >>= 8;
-- for(i=7; i>=0; i--){
-- p[i] = (u8)((v & 0x7f) | 0x80);
-- v >>= 7;
-- }
-- return 9;
-- }
-- n = 0;
-- do{
-- buf[n++] = (u8)((v & 0x7f) | 0x80);
-- v >>= 7;
-- }while( v!=0 );
-- buf[0] &= 0x7f;
-- assert( n<=9 );
-- for(i=0, j=n-1; j>=0; j--, i++){
-- p[i] = buf[j];
-+SQLITE_API void sqlite3_free(void *p){
-+ if( p==0 ) return; /* IMP: R-49053-54554 */
-+ assert( sqlite3MemdebugNoType(p, MEMTYPE_DB) );
-+ assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) );
-+ if( sqlite3GlobalConfig.bMemstat ){
-+ sqlite3_mutex_enter(mem0.mutex);
-+ sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, -sqlite3MallocSize(p));
-+ sqlite3StatusAdd(SQLITE_STATUS_MALLOC_COUNT, -1);
-+ sqlite3GlobalConfig.m.xFree(p);
-+ sqlite3_mutex_leave(mem0.mutex);
-+ }else{
-+ sqlite3GlobalConfig.m.xFree(p);
- }
-- return n;
- }
-
- /*
--** This routine is a faster version of sqlite3PutVarint() that only
--** works for 32-bit positive integers and which is optimized for
--** the common case of small integers. A MACRO version, putVarint32,
--** is provided which inlines the single-byte case. All code should use
--** the MACRO version as this function assumes the single-byte case has
--** already been handled.
-+** Free memory that might be associated with a particular database
-+** connection.
- */
--SQLITE_PRIVATE int sqlite3PutVarint32(unsigned char *p, u32 v){
--#ifndef putVarint32
-- if( (v & ~0x7f)==0 ){
-- p[0] = v;
-- return 1;
-- }
-+SQLITE_PRIVATE void sqlite3DbFree(sqlite3 *db, void *p){
-+ assert( db==0 || sqlite3_mutex_held(db->mutex) );
-+ if( db ){
-+ if( db->pnBytesFreed ){
-+ *db->pnBytesFreed += sqlite3DbMallocSize(db, p);
-+ return;
-+ }
-+ if( isLookaside(db, p) ){
-+ LookasideSlot *pBuf = (LookasideSlot*)p;
-+#if SQLITE_DEBUG
-+ /* Trash all content in the buffer being freed */
-+ memset(p, 0xaa, db->lookaside.sz);
- #endif
-- if( (v & ~0x3fff)==0 ){
-- p[0] = (u8)((v>>7) | 0x80);
-- p[1] = (u8)(v & 0x7f);
-- return 2;
-+ pBuf->pNext = db->lookaside.pFree;
-+ db->lookaside.pFree = pBuf;
-+ db->lookaside.nOut--;
-+ return;
-+ }
- }
-- return sqlite3PutVarint(p, v);
-+ assert( sqlite3MemdebugHasType(p, MEMTYPE_DB) );
-+ assert( sqlite3MemdebugHasType(p, MEMTYPE_LOOKASIDE|MEMTYPE_HEAP) );
-+ assert( db!=0 || sqlite3MemdebugNoType(p, MEMTYPE_LOOKASIDE) );
-+ sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
-+ sqlite3_free(p);
- }
-
- /*
--** Bitmasks used by sqlite3GetVarint(). These precomputed constants
--** are defined here rather than simply putting the constant expressions
--** inline in order to work around bugs in the RVT compiler.
--**
--** SLOT_2_0 A mask for (0x7f<<14) | 0x7f
--**
--** SLOT_4_2_0 A mask for (0x7f<<28) | SLOT_2_0
-+** Change the size of an existing memory allocation
- */
--#define SLOT_2_0 0x001fc07f
--#define SLOT_4_2_0 0xf01fc07f
--
-+SQLITE_PRIVATE void *sqlite3Realloc(void *pOld, int nBytes){
-+ int nOld, nNew, nDiff;
-+ void *pNew;
-+ if( pOld==0 ){
-+ return sqlite3Malloc(nBytes); /* IMP: R-28354-25769 */
-+ }
-+ if( nBytes<=0 ){
-+ sqlite3_free(pOld); /* IMP: R-31593-10574 */
-+ return 0;
-+ }
-+ if( nBytes>=0x7fffff00 ){
-+ /* The 0x7ffff00 limit term is explained in comments on sqlite3Malloc() */
-+ return 0;
-+ }
-+ nOld = sqlite3MallocSize(pOld);
-+ /* IMPLEMENTATION-OF: R-46199-30249 SQLite guarantees that the second
-+ ** argument to xRealloc is always a value returned by a prior call to
-+ ** xRoundup. */
-+ nNew = sqlite3GlobalConfig.m.xRoundup(nBytes);
-+ if( nOld==nNew ){
-+ pNew = pOld;
-+ }else if( sqlite3GlobalConfig.bMemstat ){
-+ sqlite3_mutex_enter(mem0.mutex);
-+ sqlite3StatusSet(SQLITE_STATUS_MALLOC_SIZE, nBytes);
-+ nDiff = nNew - nOld;
-+ if( sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED) >=
-+ mem0.alarmThreshold-nDiff ){
-+ sqlite3MallocAlarm(nDiff);
-+ }
-+ assert( sqlite3MemdebugHasType(pOld, MEMTYPE_HEAP) );
-+ assert( sqlite3MemdebugNoType(pOld, ~MEMTYPE_HEAP) );
-+ pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew);
-+ if( pNew==0 && mem0.alarmCallback ){
-+ sqlite3MallocAlarm(nBytes);
-+ pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew);
-+ }
-+ if( pNew ){
-+ nNew = sqlite3MallocSize(pNew);
-+ sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, nNew-nOld);
-+ }
-+ sqlite3_mutex_leave(mem0.mutex);
-+ }else{
-+ pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew);
-+ }
-+ assert( EIGHT_BYTE_ALIGNMENT(pNew) ); /* IMP: R-04675-44850 */
-+ return pNew;
-+}
-
- /*
--** Read a 64-bit variable-length integer from memory starting at p[0].
--** Return the number of bytes read. The value is stored in *v.
-+** The public interface to sqlite3Realloc. Make sure that the memory
-+** subsystem is initialized prior to invoking sqliteRealloc.
- */
--SQLITE_PRIVATE u8 sqlite3GetVarint(const unsigned char *p, u64 *v){
-- u32 a,b,s;
-+SQLITE_API void *sqlite3_realloc(void *pOld, int n){
-+#ifndef SQLITE_OMIT_AUTOINIT
-+ if( sqlite3_initialize() ) return 0;
-+#endif
-+ return sqlite3Realloc(pOld, n);
-+}
-
-- a = *p;
-- /* a: p0 (unmasked) */
-- if (!(a&0x80))
-- {
-- *v = a;
-- return 1;
-- }
-
-- p++;
-- b = *p;
-- /* b: p1 (unmasked) */
-- if (!(b&0x80))
-- {
-- a &= 0x7f;
-- a = a<<7;
-- a |= b;
-- *v = a;
-- return 2;
-+/*
-+** Allocate and zero memory.
-+*/
-+SQLITE_PRIVATE void *sqlite3MallocZero(int n){
-+ void *p = sqlite3Malloc(n);
-+ if( p ){
-+ memset(p, 0, n);
- }
-+ return p;
-+}
-
-- /* Verify that constants are precomputed correctly */
-- assert( SLOT_2_0 == ((0x7f<<14) | (0x7f)) );
-- assert( SLOT_4_2_0 == ((0xfU<<28) | (0x7f<<14) | (0x7f)) );
--
-- p++;
-- a = a<<14;
-- a |= *p;
-- /* a: p0<<14 | p2 (unmasked) */
-- if (!(a&0x80))
-- {
-- a &= SLOT_2_0;
-- b &= 0x7f;
-- b = b<<7;
-- a |= b;
-- *v = a;
-- return 3;
-+/*
-+** Allocate and zero memory. If the allocation fails, make
-+** the mallocFailed flag in the connection pointer.
-+*/
-+SQLITE_PRIVATE void *sqlite3DbMallocZero(sqlite3 *db, int n){
-+ void *p = sqlite3DbMallocRaw(db, n);
-+ if( p ){
-+ memset(p, 0, n);
- }
-+ return p;
-+}
-
-- /* CSE1 from below */
-- a &= SLOT_2_0;
-- p++;
-- b = b<<14;
-- b |= *p;
-- /* b: p1<<14 | p3 (unmasked) */
-- if (!(b&0x80))
-- {
-- b &= SLOT_2_0;
-- /* moved CSE1 up */
-- /* a &= (0x7f<<14)|(0x7f); */
-- a = a<<7;
-- a |= b;
-- *v = a;
-- return 4;
-+/*
-+** Allocate and zero memory. If the allocation fails, make
-+** the mallocFailed flag in the connection pointer.
-+**
-+** If db!=0 and db->mallocFailed is true (indicating a prior malloc
-+** failure on the same database connection) then always return 0.
-+** Hence for a particular database connection, once malloc starts
-+** failing, it fails consistently until mallocFailed is reset.
-+** This is an important assumption. There are many places in the
-+** code that do things like this:
-+**
-+** int *a = (int*)sqlite3DbMallocRaw(db, 100);
-+** int *b = (int*)sqlite3DbMallocRaw(db, 200);
-+** if( b ) a[10] = 9;
-+**
-+** In other words, if a subsequent malloc (ex: "b") worked, it is assumed
-+** that all prior mallocs (ex: "a") worked too.
-+*/
-+SQLITE_PRIVATE void *sqlite3DbMallocRaw(sqlite3 *db, int n){
-+ void *p;
-+ assert( db==0 || sqlite3_mutex_held(db->mutex) );
-+ assert( db==0 || db->pnBytesFreed==0 );
-+#ifndef SQLITE_OMIT_LOOKASIDE
-+ if( db ){
-+ LookasideSlot *pBuf;
-+ if( db->mallocFailed ){
-+ return 0;
-+ }
-+ if( db->lookaside.bEnabled ){
-+ if( n>db->lookaside.sz ){
-+ db->lookaside.anStat[1]++;
-+ }else if( (pBuf = db->lookaside.pFree)==0 ){
-+ db->lookaside.anStat[2]++;
-+ }else{
-+ db->lookaside.pFree = pBuf->pNext;
-+ db->lookaside.nOut++;
-+ db->lookaside.anStat[0]++;
-+ if( db->lookaside.nOut>db->lookaside.mxOut ){
-+ db->lookaside.mxOut = db->lookaside.nOut;
-+ }
-+ return (void*)pBuf;
-+ }
-+ }
- }
--
-- /* a: p0<<14 | p2 (masked) */
-- /* b: p1<<14 | p3 (unmasked) */
-- /* 1:save off p0<<21 | p1<<14 | p2<<7 | p3 (masked) */
-- /* moved CSE1 up */
-- /* a &= (0x7f<<14)|(0x7f); */
-- b &= SLOT_2_0;
-- s = a;
-- /* s: p0<<14 | p2 (masked) */
--
-- p++;
-- a = a<<14;
-- a |= *p;
-- /* a: p0<<28 | p2<<14 | p4 (unmasked) */
-- if (!(a&0x80))
-- {
-- /* we can skip these cause they were (effectively) done above in calc'ing s */
-- /* a &= (0x7f<<28)|(0x7f<<14)|(0x7f); */
-- /* b &= (0x7f<<14)|(0x7f); */
-- b = b<<7;
-- a |= b;
-- s = s>>18;
-- *v = ((u64)s)<<32 | a;
-- return 5;
-+#else
-+ if( db && db->mallocFailed ){
-+ return 0;
- }
--
-- /* 2:save off p0<<21 | p1<<14 | p2<<7 | p3 (masked) */
-- s = s<<7;
-- s |= b;
-- /* s: p0<<21 | p1<<14 | p2<<7 | p3 (masked) */
--
-- p++;
-- b = b<<14;
-- b |= *p;
-- /* b: p1<<28 | p3<<14 | p5 (unmasked) */
-- if (!(b&0x80))
-- {
-- /* we can skip this cause it was (effectively) done above in calc'ing s */
-- /* b &= (0x7f<<28)|(0x7f<<14)|(0x7f); */
-- a &= SLOT_2_0;
-- a = a<<7;
-- a |= b;
-- s = s>>18;
-- *v = ((u64)s)<<32 | a;
-- return 6;
-+#endif
-+ p = sqlite3Malloc(n);
-+ if( !p && db ){
-+ db->mallocFailed = 1;
- }
-+ sqlite3MemdebugSetType(p, MEMTYPE_DB |
-+ ((db && db->lookaside.bEnabled) ? MEMTYPE_LOOKASIDE : MEMTYPE_HEAP));
-+ return p;
-+}
-
-- p++;
-- a = a<<14;
-- a |= *p;
-- /* a: p2<<28 | p4<<14 | p6 (unmasked) */
-- if (!(a&0x80))
-- {
-- a &= SLOT_4_2_0;
-- b &= SLOT_2_0;
-- b = b<<7;
-- a |= b;
-- s = s>>11;
-- *v = ((u64)s)<<32 | a;
-- return 7;
-+/*
-+** Resize the block of memory pointed to by p to n bytes. If the
-+** resize fails, set the mallocFailed flag in the connection object.
-+*/
-+SQLITE_PRIVATE void *sqlite3DbRealloc(sqlite3 *db, void *p, int n){
-+ void *pNew = 0;
-+ assert( db!=0 );
-+ assert( sqlite3_mutex_held(db->mutex) );
-+ if( db->mallocFailed==0 ){
-+ if( p==0 ){
-+ return sqlite3DbMallocRaw(db, n);
-+ }
-+ if( isLookaside(db, p) ){
-+ if( n<=db->lookaside.sz ){
-+ return p;
-+ }
-+ pNew = sqlite3DbMallocRaw(db, n);
-+ if( pNew ){
-+ memcpy(pNew, p, db->lookaside.sz);
-+ sqlite3DbFree(db, p);
-+ }
-+ }else{
-+ assert( sqlite3MemdebugHasType(p, MEMTYPE_DB) );
-+ assert( sqlite3MemdebugHasType(p, MEMTYPE_LOOKASIDE|MEMTYPE_HEAP) );
-+ sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
-+ pNew = sqlite3_realloc(p, n);
-+ if( !pNew ){
-+ sqlite3MemdebugSetType(p, MEMTYPE_DB|MEMTYPE_HEAP);
-+ db->mallocFailed = 1;
-+ }
-+ sqlite3MemdebugSetType(pNew, MEMTYPE_DB |
-+ (db->lookaside.bEnabled ? MEMTYPE_LOOKASIDE : MEMTYPE_HEAP));
-+ }
- }
-+ return pNew;
-+}
-
-- /* CSE2 from below */
-- a &= SLOT_2_0;
-- p++;
-- b = b<<14;
-- b |= *p;
-- /* b: p3<<28 | p5<<14 | p7 (unmasked) */
-- if (!(b&0x80))
-- {
-- b &= SLOT_4_2_0;
-- /* moved CSE2 up */
-- /* a &= (0x7f<<14)|(0x7f); */
-- a = a<<7;
-- a |= b;
-- s = s>>4;
-- *v = ((u64)s)<<32 | a;
-- return 8;
-+/*
-+** Attempt to reallocate p. If the reallocation fails, then free p
-+** and set the mallocFailed flag in the database connection.
-+*/
-+SQLITE_PRIVATE void *sqlite3DbReallocOrFree(sqlite3 *db, void *p, int n){
-+ void *pNew;
-+ pNew = sqlite3DbRealloc(db, p, n);
-+ if( !pNew ){
-+ sqlite3DbFree(db, p);
- }
--
-- p++;
-- a = a<<15;
-- a |= *p;
-- /* a: p4<<29 | p6<<15 | p8 (unmasked) */
--
-- /* moved CSE2 up */
-- /* a &= (0x7f<<29)|(0x7f<<15)|(0xff); */
-- b &= SLOT_2_0;
-- b = b<<8;
-- a |= b;
--
-- s = s<<4;
-- b = p[-4];
-- b &= 0x7f;
-- b = b>>3;
-- s |= b;
--
-- *v = ((u64)s)<<32 | a;
--
-- return 9;
-+ return pNew;
- }
-
- /*
--** Read a 32-bit variable-length integer from memory starting at p[0].
--** Return the number of bytes read. The value is stored in *v.
--**
--** If the varint stored in p[0] is larger than can fit in a 32-bit unsigned
--** integer, then set *v to 0xffffffff.
--**
--** A MACRO version, getVarint32, is provided which inlines the
--** single-byte case. All code should use the MACRO version as
--** this function assumes the single-byte case has already been handled.
-+** Make a copy of a string in memory obtained from sqliteMalloc(). These
-+** functions call sqlite3MallocRaw() directly instead of sqliteMalloc(). This
-+** is because when memory debugging is turned on, these two functions are
-+** called via macros that record the current file and line number in the
-+** ThreadData structure.
- */
--SQLITE_PRIVATE u8 sqlite3GetVarint32(const unsigned char *p, u32 *v){
-- u32 a,b;
--
-- /* The 1-byte case. Overwhelmingly the most common. Handled inline
-- ** by the getVarin32() macro */
-- a = *p;
-- /* a: p0 (unmasked) */
--#ifndef getVarint32
-- if (!(a&0x80))
-- {
-- /* Values between 0 and 127 */
-- *v = a;
-- return 1;
-+SQLITE_PRIVATE char *sqlite3DbStrDup(sqlite3 *db, const char *z){
-+ char *zNew;
-+ size_t n;
-+ if( z==0 ){
-+ return 0;
- }
--#endif
--
-- /* The 2-byte case */
-- p++;
-- b = *p;
-- /* b: p1 (unmasked) */
-- if (!(b&0x80))
-- {
-- /* Values between 128 and 16383 */
-- a &= 0x7f;
-- a = a<<7;
-- *v = a | b;
-- return 2;
-+ n = sqlite3Strlen30(z) + 1;
-+ assert( (n&0x7fffffff)==n );
-+ zNew = sqlite3DbMallocRaw(db, (int)n);
-+ if( zNew ){
-+ memcpy(zNew, z, n);
- }
--
-- /* The 3-byte case */
-- p++;
-- a = a<<14;
-- a |= *p;
-- /* a: p0<<14 | p2 (unmasked) */
-- if (!(a&0x80))
-- {
-- /* Values between 16384 and 2097151 */
-- a &= (0x7f<<14)|(0x7f);
-- b &= 0x7f;
-- b = b<<7;
-- *v = a | b;
-- return 3;
-+ return zNew;
-+}
-+SQLITE_PRIVATE char *sqlite3DbStrNDup(sqlite3 *db, const char *z, int n){
-+ char *zNew;
-+ if( z==0 ){
-+ return 0;
- }
--
-- /* A 32-bit varint is used to store size information in btrees.
-- ** Objects are rarely larger than 2MiB limit of a 3-byte varint.
-- ** A 3-byte varint is sufficient, for example, to record the size
-- ** of a 1048569-byte BLOB or string.
-- **
-- ** We only unroll the first 1-, 2-, and 3- byte cases. The very
-- ** rare larger cases can be handled by the slower 64-bit varint
-- ** routine.
-- */
--#if 1
-- {
-- u64 v64;
-- u8 n;
--
-- p -= 2;
-- n = sqlite3GetVarint(p, &v64);
-- assert( n>3 && n<=9 );
-- if( (v64 & SQLITE_MAX_U32)!=v64 ){
-- *v = 0xffffffff;
-- }else{
-- *v = (u32)v64;
-- }
-- return n;
-+ assert( (n&0x7fffffff)==n );
-+ zNew = sqlite3DbMallocRaw(db, n+1);
-+ if( zNew ){
-+ memcpy(zNew, z, n);
-+ zNew[n] = 0;
- }
-+ return zNew;
-+}
-
--#else
-- /* For following code (kept for historical record only) shows an
-- ** unrolling for the 3- and 4-byte varint cases. This code is
-- ** slightly faster, but it is also larger and much harder to test.
-- */
-- p++;
-- b = b<<14;
-- b |= *p;
-- /* b: p1<<14 | p3 (unmasked) */
-- if (!(b&0x80))
-- {
-- /* Values between 2097152 and 268435455 */
-- b &= (0x7f<<14)|(0x7f);
-- a &= (0x7f<<14)|(0x7f);
-- a = a<<7;
-- *v = a | b;
-- return 4;
-- }
-+/*
-+** Create a string from the zFromat argument and the va_list that follows.
-+** Store the string in memory obtained from sqliteMalloc() and make *pz
-+** point to that string.
-+*/
-+SQLITE_PRIVATE void sqlite3SetString(char **pz, sqlite3 *db, const char *zFormat, ...){
-+ va_list ap;
-+ char *z;
-
-- p++;
-- a = a<<14;
-- a |= *p;
-- /* a: p0<<28 | p2<<14 | p4 (unmasked) */
-- if (!(a&0x80))
-- {
-- /* Values between 268435456 and 34359738367 */
-- a &= SLOT_4_2_0;
-- b &= SLOT_4_2_0;
-- b = b<<7;
-- *v = a | b;
-- return 5;
-- }
-+ va_start(ap, zFormat);
-+ z = sqlite3VMPrintf(db, zFormat, ap);
-+ va_end(ap);
-+ sqlite3DbFree(db, *pz);
-+ *pz = z;
-+}
-
-- /* We can only reach this point when reading a corrupt database
-- ** file. In that case we are not in any hurry. Use the (relatively
-- ** slow) general-purpose sqlite3GetVarint() routine to extract the
-- ** value. */
-- {
-- u64 v64;
-- u8 n;
-
-- p -= 4;
-- n = sqlite3GetVarint(p, &v64);
-- assert( n>5 && n<=9 );
-- *v = (u32)v64;
-- return n;
-+/*
-+** This function must be called before exiting any API function (i.e.
-+** returning control to the user) that has called sqlite3_malloc or
-+** sqlite3_realloc.
+**
-+** The returned value is normally a copy of the second argument to this
-+** function. However, if a malloc() failure has occurred since the previous
-+** invocation SQLITE_NOMEM is returned instead.
-+**
-+** If the first argument, db, is not NULL and a malloc() error has occurred,
-+** then the connection error-code (the value returned by sqlite3_errcode())
-+** is set to SQLITE_NOMEM.
++** This file implements routines used to report what compile-time options
++** SQLite was built with.
+*/
-+SQLITE_PRIVATE int sqlite3ApiExit(sqlite3* db, int rc){
-+ /* If the db handle is not NULL, then we must hold the connection handle
-+ ** mutex here. Otherwise the read (and possible write) of db->mallocFailed
-+ ** is unsafe, as is the call to sqlite3Error().
-+ */
-+ assert( !db || sqlite3_mutex_held(db->mutex) );
-+ if( db && (db->mallocFailed || rc==SQLITE_IOERR_NOMEM) ){
-+ sqlite3Error(db, SQLITE_NOMEM, 0);
-+ db->mallocFailed = 0;
-+ rc = SQLITE_NOMEM;
- }
--#endif
-+ return rc & (db ? db->errMask : 0xff);
- }
-
-+/************** End of malloc.c **********************************************/
-+/************** Begin file printf.c ******************************************/
- /*
--** Return the number of bytes that will be needed to store the given
--** 64-bit integer.
-+** The "printf" code that follows dates from the 1980's. It is in
-+** the public domain. The original comments are included here for
-+** completeness. They are very out-of-date but might be useful as
-+** an historical reference. Most of the "enhancements" have been backed
-+** out so that the functionality is now the same as standard printf().
-+**
-+**************************************************************************
-+**
-+** This file contains code for a set of "printf"-like routines. These
-+** routines format strings much like the printf() from the standard C
-+** library, though the implementation here has enhancements to support
-+** SQLlite.
- */
--SQLITE_PRIVATE int sqlite3VarintLen(u64 v){
-- int i = 0;
-- do{
-- i++;
-- v >>= 7;
-- }while( v!=0 && ALWAYS(i<9) );
-- return i;
--}
--
-
- /*
--** Read or write a four-byte big-endian integer value.
-+** Conversion types fall into various categories as defined by the
-+** following enumeration.
- */
--SQLITE_PRIVATE u32 sqlite3Get4byte(const u8 *p){
-- return (p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3];
--}
--SQLITE_PRIVATE void sqlite3Put4byte(unsigned char *p, u32 v){
-- p[0] = (u8)(v>>24);
-- p[1] = (u8)(v>>16);
-- p[2] = (u8)(v>>8);
-- p[3] = (u8)v;
--}
-+#define etRADIX 1 /* Integer types. %d, %x, %o, and so forth */
-+#define etFLOAT 2 /* Floating point. %f */
-+#define etEXP 3 /* Exponentional notation. %e and %E */
-+#define etGENERIC 4 /* Floating or exponential, depending on exponent. %g */
-+#define etSIZE 5 /* Return number of characters processed so far. %n */
-+#define etSTRING 6 /* Strings. %s */
-+#define etDYNSTRING 7 /* Dynamically allocated strings. %z */
-+#define etPERCENT 8 /* Percent symbol. %% */
-+#define etCHARX 9 /* Characters. %c */
-+/* The rest are extensions, not normally found in printf() */
-+#define etSQLESCAPE 10 /* Strings with '\'' doubled. %q */
-+#define etSQLESCAPE2 11 /* Strings with '\'' doubled and enclosed in '',
-+ NULL pointers replaced by SQL NULL. %Q */
-+#define etTOKEN 12 /* a pointer to a Token structure */
-+#define etSRCLIST 13 /* a pointer to a SrcList */
-+#define etPOINTER 14 /* The %p conversion */
-+#define etSQLESCAPE3 15 /* %w -> Strings with '\"' doubled */
-+#define etORDINAL 16 /* %r -> 1st, 2nd, 3rd, 4th, etc. English only */
-
-+#define etINVALID 0 /* Any unrecognized conversion type */
-
-
- /*
--** Translate a single byte of Hex into an integer.
--** This routine only works if h really is a valid hexadecimal
--** character: 0..9a..fA..F
-+** An "etByte" is an 8-bit unsigned value.
- */
--SQLITE_PRIVATE u8 sqlite3HexToInt(int h){
-- assert( (h>='0' && h<='9') || (h>='a' && h<='f') || (h>='A' && h<='F') );
--#ifdef SQLITE_ASCII
-- h += 9*(1&(h>>6));
--#endif
--#ifdef SQLITE_EBCDIC
-- h += 9*(1&~(h>>4));
--#endif
-- return (u8)(h & 0xf);
--}
-+typedef unsigned char etByte;
-
--#if !defined(SQLITE_OMIT_BLOB_LITERAL) || defined(SQLITE_HAS_CODEC)
- /*
--** Convert a BLOB literal of the form "x'hhhhhh'" into its binary
--** value. Return a pointer to its binary value. Space to hold the
--** binary value has been obtained from malloc and must be freed by
--** the calling routine.
-+** Each builtin conversion character (ex: the 'd' in "%d") is described
-+** by an instance of the following structure
- */
--SQLITE_PRIVATE void *sqlite3HexToBlob(sqlite3 *db, const char *z, int n){
-- char *zBlob;
-- int i;
--
-- zBlob = (char *)sqlite3DbMallocRaw(db, n/2 + 1);
-- n--;
-- if( zBlob ){
-- for(i=0; i<n; i+=2){
-- zBlob[i/2] = (sqlite3HexToInt(z[i])<<4) | sqlite3HexToInt(z[i+1]);
-- }
-- zBlob[i/2] = 0;
-- }
-- return zBlob;
--}
--#endif /* !SQLITE_OMIT_BLOB_LITERAL || SQLITE_HAS_CODEC */
-+typedef struct et_info { /* Information about each format field */
-+ char fmttype; /* The format field code letter */
-+ etByte base; /* The base for radix conversion */
-+ etByte flags; /* One or more of FLAG_ constants below */
-+ etByte type; /* Conversion paradigm */
-+ etByte charset; /* Offset into aDigits[] of the digits string */
-+ etByte prefix; /* Offset into aPrefix[] of the prefix string */
-+} et_info;
-
- /*
--** Log an error that is an API call on a connection pointer that should
--** not have been used. The "type" of connection pointer is given as the
--** argument. The zType is a word like "NULL" or "closed" or "invalid".
-+** Allowed values for et_info.flags
- */
--static void logBadConnection(const char *zType){
-- sqlite3_log(SQLITE_MISUSE,
-- "API call with %s database connection pointer",
-- zType
-- );
--}
-+#define FLAG_SIGNED 1 /* True if the value to convert is signed */
-+#define FLAG_INTERN 2 /* True if for internal use only */
-+#define FLAG_STRING 4 /* Allow infinity precision */
+
++#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
- /*
--** Check to make sure we have a valid db pointer. This test is not
--** foolproof but it does provide some measure of protection against
--** misuse of the interface such as passing in db pointers that are
--** NULL or which have been previously closed. If this routine returns
--** 1 it means that the db pointer is valid and 0 if it should not be
--** dereferenced for any reason. The calling function should invoke
--** SQLITE_MISUSE immediately.
--**
--** sqlite3SafetyCheckOk() requires that the db pointer be valid for
--** use. sqlite3SafetyCheckSickOrOk() allows a db pointer that failed to
--** open properly and is not fit for general use but which can be
--** used as an argument to sqlite3_errmsg() or sqlite3_close().
-+** The following table is searched linearly, so it is good to put the
-+** most frequently used conversion types first.
- */
--SQLITE_PRIVATE int sqlite3SafetyCheckOk(sqlite3 *db){
-- u32 magic;
-- if( db==0 ){
-- logBadConnection("NULL");
-- return 0;
-- }
-- magic = db->magic;
-- if( magic!=SQLITE_MAGIC_OPEN ){
-- if( sqlite3SafetyCheckSickOrOk(db) ){
-- testcase( sqlite3GlobalConfig.xLog!=0 );
-- logBadConnection("unopened");
-- }
-- return 0;
-- }else{
-- return 1;
-- }
--}
--SQLITE_PRIVATE int sqlite3SafetyCheckSickOrOk(sqlite3 *db){
-- u32 magic;
-- magic = db->magic;
-- if( magic!=SQLITE_MAGIC_SICK &&
-- magic!=SQLITE_MAGIC_OPEN &&
-- magic!=SQLITE_MAGIC_BUSY ){
-- testcase( sqlite3GlobalConfig.xLog!=0 );
-- logBadConnection("invalid");
-- return 0;
-- }else{
-- return 1;
-- }
--}
--
--/*
--** Attempt to add, substract, or multiply the 64-bit signed value iB against
--** the other 64-bit signed integer at *pA and store the result in *pA.
--** Return 0 on success. Or if the operation would have resulted in an
--** overflow, leave *pA unchanged and return 1.
--*/
--SQLITE_PRIVATE int sqlite3AddInt64(i64 *pA, i64 iB){
-- i64 iA = *pA;
-- testcase( iA==0 ); testcase( iA==1 );
-- testcase( iB==-1 ); testcase( iB==0 );
-- if( iB>=0 ){
-- testcase( iA>0 && LARGEST_INT64 - iA == iB );
-- testcase( iA>0 && LARGEST_INT64 - iA == iB - 1 );
-- if( iA>0 && LARGEST_INT64 - iA < iB ) return 1;
-- *pA += iB;
-- }else{
-- testcase( iA<0 && -(iA + LARGEST_INT64) == iB + 1 );
-- testcase( iA<0 && -(iA + LARGEST_INT64) == iB + 2 );
-- if( iA<0 && -(iA + LARGEST_INT64) > iB + 1 ) return 1;
-- *pA += iB;
-- }
-- return 0;
--}
--SQLITE_PRIVATE int sqlite3SubInt64(i64 *pA, i64 iB){
-- testcase( iB==SMALLEST_INT64+1 );
-- if( iB==SMALLEST_INT64 ){
-- testcase( (*pA)==(-1) ); testcase( (*pA)==0 );
-- if( (*pA)>=0 ) return 1;
-- *pA -= iB;
-- return 0;
-- }else{
-- return sqlite3AddInt64(pA, -iB);
-- }
--}
--#define TWOPOWER32 (((i64)1)<<32)
--#define TWOPOWER31 (((i64)1)<<31)
--SQLITE_PRIVATE int sqlite3MulInt64(i64 *pA, i64 iB){
-- i64 iA = *pA;
-- i64 iA1, iA0, iB1, iB0, r;
-+static const char aDigits[] = "0123456789ABCDEF0123456789abcdef";
-+static const char aPrefix[] = "-x0\000X0";
-+static const et_info fmtinfo[] = {
-+ { 'd', 10, 1, etRADIX, 0, 0 },
-+ { 's', 0, 4, etSTRING, 0, 0 },
-+ { 'g', 0, 1, etGENERIC, 30, 0 },
-+ { 'z', 0, 4, etDYNSTRING, 0, 0 },
-+ { 'q', 0, 4, etSQLESCAPE, 0, 0 },
-+ { 'Q', 0, 4, etSQLESCAPE2, 0, 0 },
-+ { 'w', 0, 4, etSQLESCAPE3, 0, 0 },
-+ { 'c', 0, 0, etCHARX, 0, 0 },
-+ { 'o', 8, 0, etRADIX, 0, 2 },
-+ { 'u', 10, 0, etRADIX, 0, 0 },
-+ { 'x', 16, 0, etRADIX, 16, 1 },
-+ { 'X', 16, 0, etRADIX, 0, 4 },
-+#ifndef SQLITE_OMIT_FLOATING_POINT
-+ { 'f', 0, 1, etFLOAT, 0, 0 },
-+ { 'e', 0, 1, etEXP, 30, 0 },
-+ { 'E', 0, 1, etEXP, 14, 0 },
-+ { 'G', 0, 1, etGENERIC, 14, 0 },
-+#endif
-+ { 'i', 10, 1, etRADIX, 0, 0 },
-+ { 'n', 0, 0, etSIZE, 0, 0 },
-+ { '%', 0, 0, etPERCENT, 0, 0 },
-+ { 'p', 16, 0, etPOINTER, 0, 1 },
-
-- iA1 = iA/TWOPOWER32;
-- iA0 = iA % TWOPOWER32;
-- iB1 = iB/TWOPOWER32;
-- iB0 = iB % TWOPOWER32;
-- if( iA1*iB1 != 0 ) return 1;
-- assert( iA1*iB0==0 || iA0*iB1==0 );
-- r = iA1*iB0 + iA0*iB1;
-- testcase( r==(-TWOPOWER31)-1 );
-- testcase( r==(-TWOPOWER31) );
-- testcase( r==TWOPOWER31 );
-- testcase( r==TWOPOWER31-1 );
-- if( r<(-TWOPOWER31) || r>=TWOPOWER31 ) return 1;
-- r *= TWOPOWER32;
-- if( sqlite3AddInt64(&r, iA0*iB0) ) return 1;
-- *pA = r;
-- return 0;
--}
-+/* All the rest have the FLAG_INTERN bit set and are thus for internal
-+** use only */
-+ { 'T', 0, 2, etTOKEN, 0, 0 },
-+ { 'S', 0, 2, etSRCLIST, 0, 0 },
-+ { 'r', 10, 3, etORDINAL, 0, 0 },
-+};
-
- /*
--** Compute the absolute value of a 32-bit signed integer, of possible. Or
--** if the integer has a value of -2147483648, return +2147483647
-+** If SQLITE_OMIT_FLOATING_POINT is defined, then none of the floating point
-+** conversions will work.
- */
--SQLITE_PRIVATE int sqlite3AbsInt32(int x){
-- if( x>=0 ) return x;
-- if( x==(int)0x80000000 ) return 0x7fffffff;
-- return -x;
--}
--
--#ifdef SQLITE_ENABLE_8_3_NAMES
-+#ifndef SQLITE_OMIT_FLOATING_POINT
- /*
--** If SQLITE_ENABLE_8_3_NAMES is set at compile-time and if the database
--** filename in zBaseFilename is a URI with the "8_3_names=1" parameter and
--** if filename in z[] has a suffix (a.k.a. "extension") that is longer than
--** three characters, then shorten the suffix on z[] to be the last three
--** characters of the original suffix.
--**
--** If SQLITE_ENABLE_8_3_NAMES is set to 2 at compile-time, then always
--** do the suffix shortening regardless of URI parameter.
-+** "*val" is a double such that 0.1 <= *val < 10.0
-+** Return the ascii code for the leading digit of *val, then
-+** multiply "*val" by 10.0 to renormalize.
- **
--** Examples:
-+** Example:
-+** input: *val = 3.14159
-+** output: *val = 1.4159 function return = '3'
- **
--** test.db-journal => test.nal
--** test.db-wal => test.wal
--** test.db-shm => test.shm
--** test.db-mj7f3319fa => test.9fa
-+** The counter *cnt is incremented each time. After counter exceeds
-+** 16 (the number of significant digits in a 64-bit float) '0' is
-+** always returned.
- */
--SQLITE_PRIVATE void sqlite3FileSuffix3(const char *zBaseFilename, char *z){
--#if SQLITE_ENABLE_8_3_NAMES<2
-- if( sqlite3_uri_boolean(zBaseFilename, "8_3_names", 0) )
--#endif
-- {
-- int i, sz;
-- sz = sqlite3Strlen30(z);
-- for(i=sz-1; i>0 && z[i]!='/' && z[i]!='.'; i--){}
-- if( z[i]=='.' && ALWAYS(sz>i+4) ) memmove(&z[i+1], &z[sz-3], 4);
-- }
-+static char et_getdigit(LONGDOUBLE_TYPE *val, int *cnt){
-+ int digit;
-+ LONGDOUBLE_TYPE d;
-+ if( (*cnt)<=0 ) return '0';
-+ (*cnt)--;
-+ digit = (int)*val;
-+ d = digit;
-+ digit += '0';
-+ *val = (*val - d)*10.0;
-+ return (char)digit;
- }
--#endif
-+#endif /* SQLITE_OMIT_FLOATING_POINT */
-
--/************** End of util.c ************************************************/
--/************** Begin file hash.c ********************************************/
- /*
--** 2001 September 22
--**
--** The author disclaims copyright to this source code. In place of
--** a legal notice, here is a blessing:
--**
--** May you do good and not evil.
--** May you find forgiveness for yourself and forgive others.
--** May you share freely, never taking more than you give.
--**
--*************************************************************************
--** This is the implementation of generic hash-tables
--** used in SQLite.
--*/
--/* #include <assert.h> */
--
--/* Turn bulk memory into a hash table object by initializing the
--** fields of the Hash structure.
--**
--** "pNew" is a pointer to the hash table that is to be initialized.
--*/
--SQLITE_PRIVATE void sqlite3HashInit(Hash *pNew){
-- assert( pNew!=0 );
-- pNew->first = 0;
-- pNew->count = 0;
-- pNew->htsize = 0;
-- pNew->ht = 0;
--}
--
--/* Remove all entries from a hash table. Reclaim all memory.
--** Call this routine to delete a hash table or to reset a hash table
--** to the empty state.
-+** Append N space characters to the given string buffer.
- */
--SQLITE_PRIVATE void sqlite3HashClear(Hash *pH){
-- HashElem *elem; /* For looping over all elements of the table */
--
-- assert( pH!=0 );
-- elem = pH->first;
-- pH->first = 0;
-- sqlite3_free(pH->ht);
-- pH->ht = 0;
-- pH->htsize = 0;
-- while( elem ){
-- HashElem *next_elem = elem->next;
-- sqlite3_free(elem);
-- elem = next_elem;
-+SQLITE_PRIVATE void sqlite3AppendSpace(StrAccum *pAccum, int N){
-+ static const char zSpaces[] = " ";
-+ while( N>=(int)sizeof(zSpaces)-1 ){
-+ sqlite3StrAccumAppend(pAccum, zSpaces, sizeof(zSpaces)-1);
-+ N -= sizeof(zSpaces)-1;
-+ }
-+ if( N>0 ){
-+ sqlite3StrAccumAppend(pAccum, zSpaces, N);
- }
-- pH->count = 0;
- }
-
- /*
--** The hashing function.
-+** On machines with a small stack size, you can redefine the
-+** SQLITE_PRINT_BUF_SIZE to be something smaller, if desired.
- */
--static unsigned int strHash(const char *z, int nKey){
-- int h = 0;
-- assert( nKey>=0 );
-- while( nKey > 0 ){
-- h = (h<<3) ^ h ^ sqlite3UpperToLower[(unsigned char)*z++];
-- nKey--;
-- }
-- return h;
--}
--
-+#ifndef SQLITE_PRINT_BUF_SIZE
-+# define SQLITE_PRINT_BUF_SIZE 70
-+#endif
-+#define etBUFSIZE SQLITE_PRINT_BUF_SIZE /* Size of the output buffer */
-
--/* Link pNew element into the hash table pH. If pEntry!=0 then also
--** insert pNew into the pEntry hash bucket.
-+/*
-+** Render a string given by "fmt" into the StrAccum object.
- */
--static void insertElement(
-- Hash *pH, /* The complete hash table */
-- struct _ht *pEntry, /* The entry into which pNew is inserted */
-- HashElem *pNew /* The element to be inserted */
-+SQLITE_PRIVATE void sqlite3VXPrintf(
-+ StrAccum *pAccum, /* Accumulate results here */
-+ int useExtended, /* Allow extended %-conversions */
-+ const char *fmt, /* Format string */
-+ va_list ap /* arguments */
- ){
-- HashElem *pHead; /* First element already in pEntry */
-- if( pEntry ){
-- pHead = pEntry->count ? pEntry->chain : 0;
-- pEntry->count++;
-- pEntry->chain = pNew;
-- }else{
-- pHead = 0;
-- }
-- if( pHead ){
-- pNew->next = pHead;
-- pNew->prev = pHead->prev;
-- if( pHead->prev ){ pHead->prev->next = pNew; }
-- else { pH->first = pNew; }
-- pHead->prev = pNew;
-- }else{
-- pNew->next = pH->first;
-- if( pH->first ){ pH->first->prev = pNew; }
-- pNew->prev = 0;
-- pH->first = pNew;
-- }
--}
--
--
--/* Resize the hash table so that it cantains "new_size" buckets.
--**
--** The hash table might fail to resize if sqlite3_malloc() fails or
--** if the new size is the same as the prior size.
--** Return TRUE if the resize occurs and false if not.
--*/
--static int rehash(Hash *pH, unsigned int new_size){
-- struct _ht *new_ht; /* The new hash table */
-- HashElem *elem, *next_elem; /* For looping over existing elements */
--
--#if SQLITE_MALLOC_SOFT_LIMIT>0
-- if( new_size*sizeof(struct _ht)>SQLITE_MALLOC_SOFT_LIMIT ){
-- new_size = SQLITE_MALLOC_SOFT_LIMIT/sizeof(struct _ht);
-- }
-- if( new_size==pH->htsize ) return 0;
-+ int c; /* Next character in the format string */
-+ char *bufpt; /* Pointer to the conversion buffer */
-+ int precision; /* Precision of the current field */
-+ int length; /* Length of the field */
-+ int idx; /* A general purpose loop counter */
-+ int width; /* Width of the current field */
-+ etByte flag_leftjustify; /* True if "-" flag is present */
-+ etByte flag_plussign; /* True if "+" flag is present */
-+ etByte flag_blanksign; /* True if " " flag is present */
-+ etByte flag_alternateform; /* True if "#" flag is present */
-+ etByte flag_altform2; /* True if "!" flag is present */
-+ etByte flag_zeropad; /* True if field width constant starts with zero */
-+ etByte flag_long; /* True if "l" flag is present */
-+ etByte flag_longlong; /* True if the "ll" flag is present */
-+ etByte done; /* Loop termination flag */
-+ etByte xtype = 0; /* Conversion paradigm */
-+ char prefix; /* Prefix character. "+" or "-" or " " or '\0'. */
-+ sqlite_uint64 longvalue; /* Value for integer types */
-+ LONGDOUBLE_TYPE realvalue; /* Value for real types */
-+ const et_info *infop; /* Pointer to the appropriate info structure */
-+ char *zOut; /* Rendering buffer */
-+ int nOut; /* Size of the rendering buffer */
-+ char *zExtra; /* Malloced memory used by some conversion */
-+#ifndef SQLITE_OMIT_FLOATING_POINT
-+ int exp, e2; /* exponent of real numbers */
-+ int nsd; /* Number of significant digits returned */
-+ double rounder; /* Used for rounding floating point values */
-+ etByte flag_dp; /* True if decimal point should be shown */
-+ etByte flag_rtz; /* True if trailing zeros should be removed */
- #endif
-+ char buf[etBUFSIZE]; /* Conversion buffer */
-
-- /* The inability to allocates space for a larger hash table is
-- ** a performance hit but it is not a fatal error. So mark the
-- ** allocation as a benign. Use sqlite3Malloc()/memset(0) instead of
-- ** sqlite3MallocZero() to make the allocation, as sqlite3MallocZero()
-- ** only zeroes the requested number of bytes whereas this module will
-- ** use the actual amount of space allocated for the hash table (which
-- ** may be larger than the requested amount).
-- */
-- sqlite3BeginBenignMalloc();
-- new_ht = (struct _ht *)sqlite3Malloc( new_size*sizeof(struct _ht) );
-- sqlite3EndBenignMalloc();
-+ bufpt = 0;
-+ for(; (c=(*fmt))!=0; ++fmt){
-+ if( c!='%' ){
-+ int amt;
-+ bufpt = (char *)fmt;
-+ amt = 1;
-+ while( (c=(*++fmt))!='%' && c!=0 ) amt++;
-+ sqlite3StrAccumAppend(pAccum, bufpt, amt);
-+ if( c==0 ) break;
-+ }
-+ if( (c=(*++fmt))==0 ){
-+ sqlite3StrAccumAppend(pAccum, "%", 1);
-+ break;
-+ }
-+ /* Find out what flags are present */
-+ flag_leftjustify = flag_plussign = flag_blanksign =
-+ flag_alternateform = flag_altform2 = flag_zeropad = 0;
-+ done = 0;
-+ do{
-+ switch( c ){
-+ case '-': flag_leftjustify = 1; break;
-+ case '+': flag_plussign = 1; break;
-+ case ' ': flag_blanksign = 1; break;
-+ case '#': flag_alternateform = 1; break;
-+ case '!': flag_altform2 = 1; break;
-+ case '0': flag_zeropad = 1; break;
-+ default: done = 1; break;
-+ }
-+ }while( !done && (c=(*++fmt))!=0 );
-+ /* Get the field width */
-+ width = 0;
-+ if( c=='*' ){
-+ width = va_arg(ap,int);
-+ if( width<0 ){
-+ flag_leftjustify = 1;
-+ width = -width;
-+ }
-+ c = *++fmt;
-+ }else{
-+ while( c>='0' && c<='9' ){
-+ width = width*10 + c - '0';
-+ c = *++fmt;
-+ }
-+ }
-+ /* Get the precision */
-+ if( c=='.' ){
-+ precision = 0;
-+ c = *++fmt;
-+ if( c=='*' ){
-+ precision = va_arg(ap,int);
-+ if( precision<0 ) precision = -precision;
-+ c = *++fmt;
-+ }else{
-+ while( c>='0' && c<='9' ){
-+ precision = precision*10 + c - '0';
-+ c = *++fmt;
-+ }
-+ }
-+ }else{
-+ precision = -1;
-+ }
-+ /* Get the conversion type modifier */
-+ if( c=='l' ){
-+ flag_long = 1;
-+ c = *++fmt;
-+ if( c=='l' ){
-+ flag_longlong = 1;
-+ c = *++fmt;
-+ }else{
-+ flag_longlong = 0;
-+ }
-+ }else{
-+ flag_long = flag_longlong = 0;
-+ }
-+ /* Fetch the info entry for the field */
-+ infop = &fmtinfo[0];
-+ xtype = etINVALID;
-+ for(idx=0; idx<ArraySize(fmtinfo); idx++){
-+ if( c==fmtinfo[idx].fmttype ){
-+ infop = &fmtinfo[idx];
-+ if( useExtended || (infop->flags & FLAG_INTERN)==0 ){
-+ xtype = infop->type;
-+ }else{
-+ return;
-+ }
-+ break;
-+ }
-+ }
-+ zExtra = 0;
-
-- if( new_ht==0 ) return 0;
-- sqlite3_free(pH->ht);
-- pH->ht = new_ht;
-- pH->htsize = new_size = sqlite3MallocSize(new_ht)/sizeof(struct _ht);
-- memset(new_ht, 0, new_size*sizeof(struct _ht));
-- for(elem=pH->first, pH->first=0; elem; elem = next_elem){
-- unsigned int h = strHash(elem->pKey, elem->nKey) % new_size;
-- next_elem = elem->next;
-- insertElement(pH, &new_ht[h], elem);
-- }
-- return 1;
--}
-+ /*
-+ ** At this point, variables are initialized as follows:
-+ **
-+ ** flag_alternateform TRUE if a '#' is present.
-+ ** flag_altform2 TRUE if a '!' is present.
-+ ** flag_plussign TRUE if a '+' is present.
-+ ** flag_leftjustify TRUE if a '-' is present or if the
-+ ** field width was negative.
-+ ** flag_zeropad TRUE if the width began with 0.
-+ ** flag_long TRUE if the letter 'l' (ell) prefixed
-+ ** the conversion character.
-+ ** flag_longlong TRUE if the letter 'll' (ell ell) prefixed
-+ ** the conversion character.
-+ ** flag_blanksign TRUE if a ' ' is present.
-+ ** width The specified field width. This is
-+ ** always non-negative. Zero is the default.
-+ ** precision The specified precision. The default
-+ ** is -1.
-+ ** xtype The class of the conversion.
-+ ** infop Pointer to the appropriate info struct.
-+ */
-+ switch( xtype ){
-+ case etPOINTER:
-+ flag_longlong = sizeof(char*)==sizeof(i64);
-+ flag_long = sizeof(char*)==sizeof(long int);
-+ /* Fall through into the next case */
-+ case etORDINAL:
-+ case etRADIX:
-+ if( infop->flags & FLAG_SIGNED ){
-+ i64 v;
-+ if( flag_longlong ){
-+ v = va_arg(ap,i64);
-+ }else if( flag_long ){
-+ v = va_arg(ap,long int);
-+ }else{
-+ v = va_arg(ap,int);
-+ }
-+ if( v<0 ){
-+ if( v==SMALLEST_INT64 ){
-+ longvalue = ((u64)1)<<63;
-+ }else{
-+ longvalue = -v;
-+ }
-+ prefix = '-';
-+ }else{
-+ longvalue = v;
-+ if( flag_plussign ) prefix = '+';
-+ else if( flag_blanksign ) prefix = ' ';
-+ else prefix = 0;
-+ }
-+ }else{
-+ if( flag_longlong ){
-+ longvalue = va_arg(ap,u64);
-+ }else if( flag_long ){
-+ longvalue = va_arg(ap,unsigned long int);
-+ }else{
-+ longvalue = va_arg(ap,unsigned int);
-+ }
-+ prefix = 0;
-+ }
-+ if( longvalue==0 ) flag_alternateform = 0;
-+ if( flag_zeropad && precision<width-(prefix!=0) ){
-+ precision = width-(prefix!=0);
-+ }
-+ if( precision<etBUFSIZE-10 ){
-+ nOut = etBUFSIZE;
-+ zOut = buf;
-+ }else{
-+ nOut = precision + 10;
-+ zOut = zExtra = sqlite3Malloc( nOut );
-+ if( zOut==0 ){
-+ pAccum->mallocFailed = 1;
-+ return;
-+ }
-+ }
-+ bufpt = &zOut[nOut-1];
-+ if( xtype==etORDINAL ){
-+ static const char zOrd[] = "thstndrd";
-+ int x = (int)(longvalue % 10);
-+ if( x>=4 || (longvalue/10)%10==1 ){
-+ x = 0;
-+ }
-+ *(--bufpt) = zOrd[x*2+1];
-+ *(--bufpt) = zOrd[x*2];
-+ }
-+ {
-+ register const char *cset; /* Use registers for speed */
-+ register int base;
-+ cset = &aDigits[infop->charset];
-+ base = infop->base;
-+ do{ /* Convert to ascii */
-+ *(--bufpt) = cset[longvalue%base];
-+ longvalue = longvalue/base;
-+ }while( longvalue>0 );
-+ }
-+ length = (int)(&zOut[nOut-1]-bufpt);
-+ for(idx=precision-length; idx>0; idx--){
-+ *(--bufpt) = '0'; /* Zero pad */
-+ }
-+ if( prefix ) *(--bufpt) = prefix; /* Add sign */
-+ if( flag_alternateform && infop->prefix ){ /* Add "0" or "0x" */
-+ const char *pre;
-+ char x;
-+ pre = &aPrefix[infop->prefix];
-+ for(; (x=(*pre))!=0; pre++) *(--bufpt) = x;
-+ }
-+ length = (int)(&zOut[nOut-1]-bufpt);
-+ break;
-+ case etFLOAT:
-+ case etEXP:
-+ case etGENERIC:
-+ realvalue = va_arg(ap,double);
-+#ifdef SQLITE_OMIT_FLOATING_POINT
-+ length = 0;
-+#else
-+ if( precision<0 ) precision = 6; /* Set default precision */
-+ if( realvalue<0.0 ){
-+ realvalue = -realvalue;
-+ prefix = '-';
-+ }else{
-+ if( flag_plussign ) prefix = '+';
-+ else if( flag_blanksign ) prefix = ' ';
-+ else prefix = 0;
-+ }
-+ if( xtype==etGENERIC && precision>0 ) precision--;
-+#if 0
-+ /* Rounding works like BSD when the constant 0.4999 is used. Wierd! */
-+ for(idx=precision, rounder=0.4999; idx>0; idx--, rounder*=0.1);
-+#else
-+ /* It makes more sense to use 0.5 */
-+ for(idx=precision, rounder=0.5; idx>0; idx--, rounder*=0.1){}
-+#endif
-+ if( xtype==etFLOAT ) realvalue += rounder;
-+ /* Normalize realvalue to within 10.0 > realvalue >= 1.0 */
-+ exp = 0;
-+ if( sqlite3IsNaN((double)realvalue) ){
-+ bufpt = "NaN";
-+ length = 3;
-+ break;
-+ }
-+ if( realvalue>0.0 ){
-+ LONGDOUBLE_TYPE scale = 1.0;
-+ while( realvalue>=1e100*scale && exp<=350 ){ scale *= 1e100;exp+=100;}
-+ while( realvalue>=1e64*scale && exp<=350 ){ scale *= 1e64; exp+=64; }
-+ while( realvalue>=1e8*scale && exp<=350 ){ scale *= 1e8; exp+=8; }
-+ while( realvalue>=10.0*scale && exp<=350 ){ scale *= 10.0; exp++; }
-+ realvalue /= scale;
-+ while( realvalue<1e-8 ){ realvalue *= 1e8; exp-=8; }
-+ while( realvalue<1.0 ){ realvalue *= 10.0; exp--; }
-+ if( exp>350 ){
-+ if( prefix=='-' ){
-+ bufpt = "-Inf";
-+ }else if( prefix=='+' ){
-+ bufpt = "+Inf";
-+ }else{
-+ bufpt = "Inf";
-+ }
-+ length = sqlite3Strlen30(bufpt);
-+ break;
-+ }
-+ }
-+ bufpt = buf;
-+ /*
-+ ** If the field type is etGENERIC, then convert to either etEXP
-+ ** or etFLOAT, as appropriate.
-+ */
-+ if( xtype!=etFLOAT ){
-+ realvalue += rounder;
-+ if( realvalue>=10.0 ){ realvalue *= 0.1; exp++; }
-+ }
-+ if( xtype==etGENERIC ){
-+ flag_rtz = !flag_alternateform;
-+ if( exp<-4 || exp>precision ){
-+ xtype = etEXP;
-+ }else{
-+ precision = precision - exp;
-+ xtype = etFLOAT;
-+ }
-+ }else{
-+ flag_rtz = flag_altform2;
-+ }
-+ if( xtype==etEXP ){
-+ e2 = 0;
-+ }else{
-+ e2 = exp;
-+ }
-+ if( e2+precision+width > etBUFSIZE - 15 ){
-+ bufpt = zExtra = sqlite3Malloc( e2+precision+width+15 );
-+ if( bufpt==0 ){
-+ pAccum->mallocFailed = 1;
-+ return;
-+ }
-+ }
-+ zOut = bufpt;
-+ nsd = 16 + flag_altform2*10;
-+ flag_dp = (precision>0 ?1:0) | flag_alternateform | flag_altform2;
-+ /* The sign in front of the number */
-+ if( prefix ){
-+ *(bufpt++) = prefix;
-+ }
-+ /* Digits prior to the decimal point */
-+ if( e2<0 ){
-+ *(bufpt++) = '0';
-+ }else{
-+ for(; e2>=0; e2--){
-+ *(bufpt++) = et_getdigit(&realvalue,&nsd);
-+ }
-+ }
-+ /* The decimal point */
-+ if( flag_dp ){
-+ *(bufpt++) = '.';
-+ }
-+ /* "0" digits after the decimal point but before the first
-+ ** significant digit of the number */
-+ for(e2++; e2<0; precision--, e2++){
-+ assert( precision>0 );
-+ *(bufpt++) = '0';
-+ }
-+ /* Significant digits after the decimal point */
-+ while( (precision--)>0 ){
-+ *(bufpt++) = et_getdigit(&realvalue,&nsd);
-+ }
-+ /* Remove trailing zeros and the "." if no digits follow the "." */
-+ if( flag_rtz && flag_dp ){
-+ while( bufpt[-1]=='0' ) *(--bufpt) = 0;
-+ assert( bufpt>zOut );
-+ if( bufpt[-1]=='.' ){
-+ if( flag_altform2 ){
-+ *(bufpt++) = '0';
-+ }else{
-+ *(--bufpt) = 0;
-+ }
-+ }
-+ }
-+ /* Add the "eNNN" suffix */
-+ if( xtype==etEXP ){
-+ *(bufpt++) = aDigits[infop->charset];
-+ if( exp<0 ){
-+ *(bufpt++) = '-'; exp = -exp;
-+ }else{
-+ *(bufpt++) = '+';
-+ }
-+ if( exp>=100 ){
-+ *(bufpt++) = (char)((exp/100)+'0'); /* 100's digit */
-+ exp %= 100;
-+ }
-+ *(bufpt++) = (char)(exp/10+'0'); /* 10's digit */
-+ *(bufpt++) = (char)(exp%10+'0'); /* 1's digit */
-+ }
-+ *bufpt = 0;
-
--/* This function (for internal use only) locates an element in an
--** hash table that matches the given key. The hash for this key has
--** already been computed and is passed as the 4th parameter.
--*/
--static HashElem *findElementGivenHash(
-- const Hash *pH, /* The pH to be searched */
-- const char *pKey, /* The key we are searching for */
-- int nKey, /* Bytes in key (not counting zero terminator) */
-- unsigned int h /* The hash for this key. */
--){
-- HashElem *elem; /* Used to loop thru the element list */
-- int count; /* Number of elements left to test */
-+ /* The converted number is in buf[] and zero terminated. Output it.
-+ ** Note that the number is in the usual order, not reversed as with
-+ ** integer conversions. */
-+ length = (int)(bufpt-zOut);
-+ bufpt = zOut;
-
-- if( pH->ht ){
-- struct _ht *pEntry = &pH->ht[h];
-- elem = pEntry->chain;
-- count = pEntry->count;
-- }else{
-- elem = pH->first;
-- count = pH->count;
-- }
-- while( count-- && ALWAYS(elem) ){
-- if( elem->nKey==nKey && sqlite3StrNICmp(elem->pKey,pKey,nKey)==0 ){
-- return elem;
-+ /* Special case: Add leading zeros if the flag_zeropad flag is
-+ ** set and we are not left justified */
-+ if( flag_zeropad && !flag_leftjustify && length < width){
-+ int i;
-+ int nPad = width - length;
-+ for(i=width; i>=nPad; i--){
-+ bufpt[i] = bufpt[i-nPad];
-+ }
-+ i = prefix!=0;
-+ while( nPad-- ) bufpt[i++] = '0';
-+ length = width;
-+ }
-+#endif /* !defined(SQLITE_OMIT_FLOATING_POINT) */
-+ break;
-+ case etSIZE:
-+ *(va_arg(ap,int*)) = pAccum->nChar;
-+ length = width = 0;
-+ break;
-+ case etPERCENT:
-+ buf[0] = '%';
-+ bufpt = buf;
-+ length = 1;
-+ break;
-+ case etCHARX:
-+ c = va_arg(ap,int);
-+ buf[0] = (char)c;
-+ if( precision>=0 ){
-+ for(idx=1; idx<precision; idx++) buf[idx] = (char)c;
-+ length = precision;
-+ }else{
-+ length =1;
-+ }
-+ bufpt = buf;
-+ break;
-+ case etSTRING:
-+ case etDYNSTRING:
-+ bufpt = va_arg(ap,char*);
-+ if( bufpt==0 ){
-+ bufpt = "";
-+ }else if( xtype==etDYNSTRING ){
-+ zExtra = bufpt;
-+ }
-+ if( precision>=0 ){
-+ for(length=0; length<precision && bufpt[length]; length++){}
-+ }else{
-+ length = sqlite3Strlen30(bufpt);
-+ }
-+ break;
-+ case etSQLESCAPE:
-+ case etSQLESCAPE2:
-+ case etSQLESCAPE3: {
-+ int i, j, k, n, isnull;
-+ int needQuote;
-+ char ch;
-+ char q = ((xtype==etSQLESCAPE3)?'"':'\''); /* Quote character */
-+ char *escarg = va_arg(ap,char*);
-+ isnull = escarg==0;
-+ if( isnull ) escarg = (xtype==etSQLESCAPE2 ? "NULL" : "(NULL)");
-+ k = precision;
-+ for(i=n=0; k!=0 && (ch=escarg[i])!=0; i++, k--){
-+ if( ch==q ) n++;
-+ }
-+ needQuote = !isnull && xtype==etSQLESCAPE2;
-+ n += i + 1 + needQuote*2;
-+ if( n>etBUFSIZE ){
-+ bufpt = zExtra = sqlite3Malloc( n );
-+ if( bufpt==0 ){
-+ pAccum->mallocFailed = 1;
-+ return;
-+ }
-+ }else{
-+ bufpt = buf;
-+ }
-+ j = 0;
-+ if( needQuote ) bufpt[j++] = q;
-+ k = i;
-+ for(i=0; i<k; i++){
-+ bufpt[j++] = ch = escarg[i];
-+ if( ch==q ) bufpt[j++] = ch;
-+ }
-+ if( needQuote ) bufpt[j++] = q;
-+ bufpt[j] = 0;
-+ length = j;
-+ /* The precision in %q and %Q means how many input characters to
-+ ** consume, not the length of the output...
-+ ** if( precision>=0 && precision<length ) length = precision; */
-+ break;
-+ }
-+ case etTOKEN: {
-+ Token *pToken = va_arg(ap, Token*);
-+ if( pToken ){
-+ sqlite3StrAccumAppend(pAccum, (const char*)pToken->z, pToken->n);
-+ }
-+ length = width = 0;
-+ break;
-+ }
-+ case etSRCLIST: {
-+ SrcList *pSrc = va_arg(ap, SrcList*);
-+ int k = va_arg(ap, int);
-+ struct SrcList_item *pItem = &pSrc->a[k];
-+ assert( k>=0 && k<pSrc->nSrc );
-+ if( pItem->zDatabase ){
-+ sqlite3StrAccumAppend(pAccum, pItem->zDatabase, -1);
-+ sqlite3StrAccumAppend(pAccum, ".", 1);
-+ }
-+ sqlite3StrAccumAppend(pAccum, pItem->zName, -1);
-+ length = width = 0;
-+ break;
-+ }
-+ default: {
-+ assert( xtype==etINVALID );
-+ return;
-+ }
-+ }/* End switch over the format type */
-+ /*
-+ ** The text of the conversion is pointed to by "bufpt" and is
-+ ** "length" characters long. The field width is "width". Do
-+ ** the output.
-+ */
-+ if( !flag_leftjustify ){
-+ register int nspace;
-+ nspace = width-length;
-+ if( nspace>0 ){
-+ sqlite3AppendSpace(pAccum, nspace);
-+ }
- }
-- elem = elem->next;
-- }
-- return 0;
--}
-+ if( length>0 ){
-+ sqlite3StrAccumAppend(pAccum, bufpt, length);
-+ }
-+ if( flag_leftjustify ){
-+ register int nspace;
-+ nspace = width-length;
-+ if( nspace>0 ){
-+ sqlite3AppendSpace(pAccum, nspace);
-+ }
-+ }
-+ sqlite3_free(zExtra);
-+ }/* End for loop over the format string */
-+} /* End of function */
-
--/* Remove a single entry from the hash table given a pointer to that
--** element and a hash on the element's key.
-+/*
-+** Append N bytes of text from z to the StrAccum object.
- */
--static void removeElementGivenHash(
-- Hash *pH, /* The pH containing "elem" */
-- HashElem* elem, /* The element to be removed from the pH */
-- unsigned int h /* Hash value for the element */
--){
-- struct _ht *pEntry;
-- if( elem->prev ){
-- elem->prev->next = elem->next;
-- }else{
-- pH->first = elem->next;
-+SQLITE_PRIVATE void sqlite3StrAccumAppend(StrAccum *p, const char *z, int N){
-+ assert( z!=0 || N==0 );
-+ if( p->tooBig | p->mallocFailed ){
-+ testcase(p->tooBig);
-+ testcase(p->mallocFailed);
-+ return;
- }
-- if( elem->next ){
-- elem->next->prev = elem->prev;
-+ assert( p->zText!=0 || p->nChar==0 );
-+ if( N<0 ){
-+ N = sqlite3Strlen30(z);
- }
-- if( pH->ht ){
-- pEntry = &pH->ht[h];
-- if( pEntry->chain==elem ){
-- pEntry->chain = elem->next;
-- }
-- pEntry->count--;
-- assert( pEntry->count>=0 );
-+ if( N==0 || NEVER(z==0) ){
-+ return;
- }
-- sqlite3_free( elem );
-- pH->count--;
-- if( pH->count==0 ){
-- assert( pH->first==0 );
-- assert( pH->count==0 );
-- sqlite3HashClear(pH);
-+ if( p->nChar+N >= p->nAlloc ){
-+ char *zNew;
-+ if( !p->useMalloc ){
-+ p->tooBig = 1;
-+ N = p->nAlloc - p->nChar - 1;
-+ if( N<=0 ){
-+ return;
-+ }
-+ }else{
-+ char *zOld = (p->zText==p->zBase ? 0 : p->zText);
-+ i64 szNew = p->nChar;
-+ szNew += N + 1;
-+ if( szNew > p->mxAlloc ){
-+ sqlite3StrAccumReset(p);
-+ p->tooBig = 1;
-+ return;
-+ }else{
-+ p->nAlloc = (int)szNew;
-+ }
-+ if( p->useMalloc==1 ){
-+ zNew = sqlite3DbRealloc(p->db, zOld, p->nAlloc);
-+ }else{
-+ zNew = sqlite3_realloc(zOld, p->nAlloc);
-+ }
-+ if( zNew ){
-+ if( zOld==0 && p->nChar>0 ) memcpy(zNew, p->zText, p->nChar);
-+ p->zText = zNew;
-+ }else{
-+ p->mallocFailed = 1;
-+ sqlite3StrAccumReset(p);
-+ return;
-+ }
-+ }
- }
-+ assert( p->zText );
-+ memcpy(&p->zText[p->nChar], z, N);
-+ p->nChar += N;
- }
-
--/* Attempt to locate an element of the hash table pH with a key
--** that matches pKey,nKey. Return the data for this element if it is
--** found, or NULL if there is no match.
-+/*
-+** Finish off a string by making sure it is zero-terminated.
-+** Return a pointer to the resulting string. Return a NULL
-+** pointer if any kind of error was encountered.
- */
--SQLITE_PRIVATE void *sqlite3HashFind(const Hash *pH, const char *pKey, int nKey){
-- HashElem *elem; /* The element that matches key */
-- unsigned int h; /* A hash on key */
--
-- assert( pH!=0 );
-- assert( pKey!=0 );
-- assert( nKey>=0 );
-- if( pH->ht ){
-- h = strHash(pKey, nKey) % pH->htsize;
-- }else{
-- h = 0;
-+SQLITE_PRIVATE char *sqlite3StrAccumFinish(StrAccum *p){
-+ if( p->zText ){
-+ p->zText[p->nChar] = 0;
-+ if( p->useMalloc && p->zText==p->zBase ){
-+ if( p->useMalloc==1 ){
-+ p->zText = sqlite3DbMallocRaw(p->db, p->nChar+1 );
-+ }else{
-+ p->zText = sqlite3_malloc(p->nChar+1);
-+ }
-+ if( p->zText ){
-+ memcpy(p->zText, p->zBase, p->nChar+1);
-+ }else{
-+ p->mallocFailed = 1;
-+ }
-+ }
- }
-- elem = findElementGivenHash(pH, pKey, nKey, h);
-- return elem ? elem->data : 0;
-+ return p->zText;
- }
-
--/* Insert an element into the hash table pH. The key is pKey,nKey
--** and the data is "data".
--**
--** If no element exists with a matching key, then a new
--** element is created and NULL is returned.
--**
--** If another element already exists with the same key, then the
--** new data replaces the old data and the old data is returned.
--** The key is not copied in this instance. If a malloc fails, then
--** the new data is returned and the hash table is unchanged.
--**
--** If the "data" parameter to this function is NULL, then the
--** element corresponding to "key" is removed from the hash table.
-+/*
-+** Reset an StrAccum string. Reclaim all malloced memory.
- */
--SQLITE_PRIVATE void *sqlite3HashInsert(Hash *pH, const char *pKey, int nKey, void *data){
-- unsigned int h; /* the hash of the key modulo hash table size */
-- HashElem *elem; /* Used to loop thru the element list */
-- HashElem *new_elem; /* New element added to the pH */
+-#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
-
-- assert( pH!=0 );
-- assert( pKey!=0 );
-- assert( nKey>=0 );
-- if( pH->htsize ){
-- h = strHash(pKey, nKey) % pH->htsize;
-- }else{
-- h = 0;
-- }
-- elem = findElementGivenHash(pH,pKey,nKey,h);
-- if( elem ){
-- void *old_data = elem->data;
-- if( data==0 ){
-- removeElementGivenHash(pH,elem,h);
-+SQLITE_PRIVATE void sqlite3StrAccumReset(StrAccum *p){
-+ if( p->zText!=p->zBase ){
-+ if( p->useMalloc==1 ){
-+ sqlite3DbFree(p->db, p->zText);
- }else{
-- elem->data = data;
-- elem->pKey = pKey;
-- assert(nKey==elem->nKey);
-- }
-- return old_data;
-- }
-- if( data==0 ) return 0;
-- new_elem = (HashElem*)sqlite3Malloc( sizeof(HashElem) );
-- if( new_elem==0 ) return data;
-- new_elem->pKey = pKey;
-- new_elem->nKey = nKey;
-- new_elem->data = data;
-- pH->count++;
-- if( pH->count>=10 && pH->count > 2*pH->htsize ){
-- if( rehash(pH, pH->count*2) ){
-- assert( pH->htsize>0 );
-- h = strHash(pKey, nKey) % pH->htsize;
-+ sqlite3_free(p->zText);
- }
- }
-- if( pH->ht ){
-- insertElement(pH, &pH->ht[h], new_elem);
-- }else{
-- insertElement(pH, 0, new_elem);
-- }
-- return 0;
-+ p->zText = 0;
- }
-
--/************** End of hash.c ************************************************/
--/************** Begin file opcodes.c *****************************************/
--/* Automatically generated. Do not edit */
--/* See the mkopcodec.awk script for details. */
--#if !defined(SQLITE_OMIT_EXPLAIN) || !defined(NDEBUG) || defined(VDBE_PROFILE) || defined(SQLITE_DEBUG)
--SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
-- static const char *const azName[] = { "?",
-- /* 1 */ "Goto",
-- /* 2 */ "Gosub",
-- /* 3 */ "Return",
-- /* 4 */ "Yield",
-- /* 5 */ "HaltIfNull",
-- /* 6 */ "Halt",
-- /* 7 */ "Integer",
-- /* 8 */ "Int64",
-- /* 9 */ "String",
-- /* 10 */ "Null",
-- /* 11 */ "Blob",
-- /* 12 */ "Variable",
-- /* 13 */ "Move",
-- /* 14 */ "Copy",
-- /* 15 */ "SCopy",
-- /* 16 */ "ResultRow",
-- /* 17 */ "CollSeq",
-- /* 18 */ "Function",
-- /* 19 */ "Not",
-- /* 20 */ "AddImm",
-- /* 21 */ "MustBeInt",
-- /* 22 */ "RealAffinity",
-- /* 23 */ "Permutation",
-- /* 24 */ "Compare",
-- /* 25 */ "Jump",
-- /* 26 */ "Once",
-- /* 27 */ "If",
-- /* 28 */ "IfNot",
-- /* 29 */ "Column",
-- /* 30 */ "Affinity",
-- /* 31 */ "MakeRecord",
-- /* 32 */ "Count",
-- /* 33 */ "Savepoint",
-- /* 34 */ "AutoCommit",
-- /* 35 */ "Transaction",
-- /* 36 */ "ReadCookie",
-- /* 37 */ "SetCookie",
-- /* 38 */ "VerifyCookie",
-- /* 39 */ "OpenRead",
-- /* 40 */ "OpenWrite",
-- /* 41 */ "OpenAutoindex",
-- /* 42 */ "OpenEphemeral",
-- /* 43 */ "SorterOpen",
-- /* 44 */ "OpenPseudo",
-- /* 45 */ "Close",
-- /* 46 */ "SeekLt",
-- /* 47 */ "SeekLe",
-- /* 48 */ "SeekGe",
-- /* 49 */ "SeekGt",
-- /* 50 */ "Seek",
-- /* 51 */ "NotFound",
-- /* 52 */ "Found",
-- /* 53 */ "IsUnique",
-- /* 54 */ "NotExists",
-- /* 55 */ "Sequence",
-- /* 56 */ "NewRowid",
-- /* 57 */ "Insert",
-- /* 58 */ "InsertInt",
-- /* 59 */ "Delete",
-- /* 60 */ "ResetCount",
-- /* 61 */ "SorterCompare",
-- /* 62 */ "SorterData",
-- /* 63 */ "RowKey",
-- /* 64 */ "RowData",
-- /* 65 */ "Rowid",
-- /* 66 */ "NullRow",
-- /* 67 */ "Last",
-- /* 68 */ "Or",
-- /* 69 */ "And",
-- /* 70 */ "SorterSort",
-- /* 71 */ "Sort",
-- /* 72 */ "Rewind",
-- /* 73 */ "IsNull",
-- /* 74 */ "NotNull",
-- /* 75 */ "Ne",
-- /* 76 */ "Eq",
-- /* 77 */ "Gt",
-- /* 78 */ "Le",
-- /* 79 */ "Lt",
-- /* 80 */ "Ge",
-- /* 81 */ "SorterNext",
-- /* 82 */ "BitAnd",
-- /* 83 */ "BitOr",
-- /* 84 */ "ShiftLeft",
-- /* 85 */ "ShiftRight",
-- /* 86 */ "Add",
-- /* 87 */ "Subtract",
-- /* 88 */ "Multiply",
-- /* 89 */ "Divide",
-- /* 90 */ "Remainder",
-- /* 91 */ "Concat",
-- /* 92 */ "Prev",
-- /* 93 */ "BitNot",
-- /* 94 */ "String8",
-- /* 95 */ "Next",
-- /* 96 */ "SorterInsert",
-- /* 97 */ "IdxInsert",
-- /* 98 */ "IdxDelete",
-- /* 99 */ "IdxRowid",
-- /* 100 */ "IdxLT",
-- /* 101 */ "IdxGE",
-- /* 102 */ "Destroy",
-- /* 103 */ "Clear",
-- /* 104 */ "CreateIndex",
-- /* 105 */ "CreateTable",
-- /* 106 */ "ParseSchema",
-- /* 107 */ "LoadAnalysis",
-- /* 108 */ "DropTable",
-- /* 109 */ "DropIndex",
-- /* 110 */ "DropTrigger",
-- /* 111 */ "IntegrityCk",
-- /* 112 */ "RowSetAdd",
-- /* 113 */ "RowSetRead",
-- /* 114 */ "RowSetTest",
-- /* 115 */ "Program",
-- /* 116 */ "Param",
-- /* 117 */ "FkCounter",
-- /* 118 */ "FkIfZero",
-- /* 119 */ "MemMax",
-- /* 120 */ "IfPos",
-- /* 121 */ "IfNeg",
-- /* 122 */ "IfZero",
-- /* 123 */ "AggStep",
-- /* 124 */ "AggFinal",
-- /* 125 */ "Checkpoint",
-- /* 126 */ "JournalMode",
-- /* 127 */ "Vacuum",
-- /* 128 */ "IncrVacuum",
-- /* 129 */ "Expire",
-- /* 130 */ "Real",
-- /* 131 */ "TableLock",
-- /* 132 */ "VBegin",
-- /* 133 */ "VCreate",
-- /* 134 */ "VDestroy",
-- /* 135 */ "VOpen",
-- /* 136 */ "VFilter",
-- /* 137 */ "VColumn",
-- /* 138 */ "VNext",
-- /* 139 */ "VRename",
-- /* 140 */ "VUpdate",
-- /* 141 */ "ToText",
-- /* 142 */ "ToBlob",
-- /* 143 */ "ToNumeric",
-- /* 144 */ "ToInt",
-- /* 145 */ "ToReal",
-- /* 146 */ "Pagecount",
-- /* 147 */ "MaxPgcnt",
-- /* 148 */ "Trace",
-- /* 149 */ "Noop",
-- /* 150 */ "Explain",
-- };
-- return azName[i];
-+/*
-+** Initialize a string accumulator
-+*/
-+SQLITE_PRIVATE void sqlite3StrAccumInit(StrAccum *p, char *zBase, int n, int mx){
-+ p->zText = p->zBase = zBase;
-+ p->db = 0;
-+ p->nChar = 0;
-+ p->nAlloc = n;
-+ p->mxAlloc = mx;
-+ p->useMalloc = 1;
-+ p->tooBig = 0;
-+ p->mallocFailed = 0;
- }
--#endif
-
--/************** End of opcodes.c *********************************************/
--/************** Begin file os_unix.c *****************************************/
- /*
--** 2004 May 22
--**
--** The author disclaims copyright to this source code. In place of
--** a legal notice, here is a blessing:
--**
--** May you do good and not evil.
--** May you find forgiveness for yourself and forgive others.
--** May you share freely, never taking more than you give.
--**
--******************************************************************************
--**
--** This file contains the VFS implementation for unix-like operating systems
--** include Linux, MacOSX, *BSD, QNX, VxWorks, AIX, HPUX, and others.
--**
--** There are actually several different VFS implementations in this file.
--** The differences are in the way that file locking is done. The default
--** implementation uses Posix Advisory Locks. Alternative implementations
--** use flock(), dot-files, various proprietary locking schemas, or simply
--** skip locking all together.
--**
--** This source file is organized into divisions where the logic for various
--** subfunctions is contained within the appropriate division. PLEASE
--** KEEP THE STRUCTURE OF THIS FILE INTACT. New code should be placed
--** in the correct division and should be clearly labeled.
--**
--** The layout of divisions is as follows:
--**
--** * General-purpose declarations and utility functions.
--** * Unique file ID logic used by VxWorks.
--** * Various locking primitive implementations (all except proxy locking):
--** + for Posix Advisory Locks
--** + for no-op locks
--** + for dot-file locks
--** + for flock() locking
--** + for named semaphore locks (VxWorks only)
--** + for AFP filesystem locks (MacOSX only)
--** * sqlite3_file methods not associated with locking.
--** * Definitions of sqlite3_io_methods objects for all locking
--** methods plus "finder" functions for each locking method.
--** * sqlite3_vfs method implementations.
--** * Locking primitives for the proxy uber-locking-method. (MacOSX only)
--** * Definitions of sqlite3_vfs objects for all locking methods
--** plus implementations of sqlite3_os_init() and sqlite3_os_end().
-+** Print into memory obtained from sqliteMalloc(). Use the internal
-+** %-conversion extensions.
- */
--#if SQLITE_OS_UNIX /* This file is used on unix only */
-+SQLITE_PRIVATE char *sqlite3VMPrintf(sqlite3 *db, const char *zFormat, va_list ap){
-+ char *z;
-+ char zBase[SQLITE_PRINT_BUF_SIZE];
-+ StrAccum acc;
-+ assert( db!=0 );
-+ sqlite3StrAccumInit(&acc, zBase, sizeof(zBase),
-+ db->aLimit[SQLITE_LIMIT_LENGTH]);
-+ acc.db = db;
-+ sqlite3VXPrintf(&acc, 1, zFormat, ap);
-+ z = sqlite3StrAccumFinish(&acc);
-+ if( acc.mallocFailed ){
-+ db->mallocFailed = 1;
-+ }
-+ return z;
-+}
-
--/* Use posix_fallocate() if it is available
-+/*
-+** Print into memory obtained from sqliteMalloc(). Use the internal
-+** %-conversion extensions.
- */
--#if !defined(HAVE_POSIX_FALLOCATE) \
-- && (_XOPEN_SOURCE >= 600 || _POSIX_C_SOURCE >= 200112L)
--# define HAVE_POSIX_FALLOCATE 1
--#endif
-+SQLITE_PRIVATE char *sqlite3MPrintf(sqlite3 *db, const char *zFormat, ...){
-+ va_list ap;
-+ char *z;
-+ va_start(ap, zFormat);
-+ z = sqlite3VMPrintf(db, zFormat, ap);
-+ va_end(ap);
-+ return z;
-+}
-
- /*
--** There are various methods for file locking used for concurrency
--** control:
-+** Like sqlite3MPrintf(), but call sqlite3DbFree() on zStr after formatting
-+** the string and before returnning. This routine is intended to be used
-+** to modify an existing string. For example:
- **
--** 1. POSIX locking (the default),
--** 2. No locking,
--** 3. Dot-file locking,
--** 4. flock() locking,
--** 5. AFP locking (OSX only),
--** 6. Named POSIX semaphores (VXWorks only),
--** 7. proxy locking. (OSX only)
-+** x = sqlite3MPrintf(db, x, "prefix %s suffix", x);
- **
--** Styles 4, 5, and 7 are only available of SQLITE_ENABLE_LOCKING_STYLE
--** is defined to 1. The SQLITE_ENABLE_LOCKING_STYLE also enables automatic
--** selection of the appropriate locking style based on the filesystem
--** where the database is located.
- */
--#if !defined(SQLITE_ENABLE_LOCKING_STYLE)
--# if defined(__APPLE__)
--# define SQLITE_ENABLE_LOCKING_STYLE 1
--# else
--# define SQLITE_ENABLE_LOCKING_STYLE 0
--# endif
-+SQLITE_PRIVATE char *sqlite3MAppendf(sqlite3 *db, char *zStr, const char *zFormat, ...){
-+ va_list ap;
-+ char *z;
-+ va_start(ap, zFormat);
-+ z = sqlite3VMPrintf(db, zFormat, ap);
-+ va_end(ap);
-+ sqlite3DbFree(db, zStr);
-+ return z;
-+}
-+
-+/*
-+** Print into memory obtained from sqlite3_malloc(). Omit the internal
-+** %-conversion extensions.
-+*/
-+SQLITE_API char *sqlite3_vmprintf(const char *zFormat, va_list ap){
-+ char *z;
-+ char zBase[SQLITE_PRINT_BUF_SIZE];
-+ StrAccum acc;
-+#ifndef SQLITE_OMIT_AUTOINIT
-+ if( sqlite3_initialize() ) return 0;
- #endif
-+ sqlite3StrAccumInit(&acc, zBase, sizeof(zBase), SQLITE_MAX_LENGTH);
-+ acc.useMalloc = 2;
-+ sqlite3VXPrintf(&acc, 0, zFormat, ap);
-+ z = sqlite3StrAccumFinish(&acc);
-+ return z;
-+}
-
- /*
--** Define the OS_VXWORKS pre-processor macro to 1 if building on
--** vxworks, or 0 otherwise.
-+** Print into memory obtained from sqlite3_malloc()(). Omit the internal
-+** %-conversion extensions.
- */
--#ifndef OS_VXWORKS
--# if defined(__RTP__) || defined(_WRS_KERNEL)
--# define OS_VXWORKS 1
--# else
--# define OS_VXWORKS 0
--# endif
-+SQLITE_API char *sqlite3_mprintf(const char *zFormat, ...){
-+ va_list ap;
-+ char *z;
-+#ifndef SQLITE_OMIT_AUTOINIT
-+ if( sqlite3_initialize() ) return 0;
- #endif
-+ va_start(ap, zFormat);
-+ z = sqlite3_vmprintf(zFormat, ap);
-+ va_end(ap);
-+ return z;
-+}
/*
--** These #defines should enable >2GB file support on Posix if the
--** underlying operating system supports it. If the OS lacks
--** large file support, these should be no-ops.
-+** sqlite3_snprintf() works like snprintf() except that it ignores the
-+** current locale settings. This is important for SQLite because we
-+** are not able to use a "," as the decimal point in place of "." as
-+** specified by some locales.
- **
--** Large file support can be disabled using the -DSQLITE_DISABLE_LFS switch
--** on the compiler command line. This is necessary if you are compiling
--** on a recent machine (ex: RedHat 7.2) but you want your code to work
--** on an older machine (ex: RedHat 6.0). If you compile on RedHat 7.2
--** without this option, LFS is enable. But LFS does not exist in the kernel
--** in RedHat 6.0, so the code won't work. Hence, for maximum binary
--** portability you should omit LFS.
-+** Oops: The first two arguments of sqlite3_snprintf() are backwards
-+** from the snprintf() standard. Unfortunately, it is too late to change
-+** this without breaking compatibility, so we just have to live with the
-+** mistake.
- **
--** The previous paragraph was written in 2005. (This paragraph is written
--** on 2008-11-28.) These days, all Linux kernels support large files, so
--** you should probably leave LFS enabled. But some embedded platforms might
--** lack LFS in which case the SQLITE_DISABLE_LFS macro might still be useful.
-+** sqlite3_vsnprintf() is the varargs version.
- */
--#ifndef SQLITE_DISABLE_LFS
--# define _LARGE_FILE 1
--# ifndef _FILE_OFFSET_BITS
--# define _FILE_OFFSET_BITS 64
--# endif
--# define _LARGEFILE_SOURCE 1
--#endif
-+SQLITE_API char *sqlite3_vsnprintf(int n, char *zBuf, const char *zFormat, va_list ap){
-+ StrAccum acc;
-+ if( n<=0 ) return zBuf;
-+ sqlite3StrAccumInit(&acc, zBuf, n, 0);
-+ acc.useMalloc = 0;
-+ sqlite3VXPrintf(&acc, 0, zFormat, ap);
-+ return sqlite3StrAccumFinish(&acc);
-+}
-+SQLITE_API char *sqlite3_snprintf(int n, char *zBuf, const char *zFormat, ...){
-+ char *z;
-+ va_list ap;
-+ va_start(ap,zFormat);
-+ z = sqlite3_vsnprintf(n, zBuf, zFormat, ap);
-+ va_end(ap);
-+ return z;
-+}
-
- /*
--** standard include files.
-+** This is the routine that actually formats the sqlite3_log() message.
-+** We house it in a separate routine from sqlite3_log() to avoid using
-+** stack space on small-stack systems when logging is disabled.
-+**
-+** sqlite3_log() must render into a static buffer. It cannot dynamically
-+** allocate memory because it might be called while the memory allocator
-+** mutex is held.
- */
--#include <sys/types.h>
--#include <sys/stat.h>
--#include <fcntl.h>
--#include <unistd.h>
--/* #include <time.h> */
--#include <sys/time.h>
--#include <errno.h>
--#if !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0
+ ** An array of names of all compile-time options. This array should
+@@ -22968,7 +26347,7 @@
+ #include <sys/time.h>
+ #include <errno.h>
+ #if !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0
-#include <sys/mman.h>
--#endif
--
--
--#if SQLITE_ENABLE_LOCKING_STYLE
--# include <sys/ioctl.h>
--# if OS_VXWORKS
--# include <semaphore.h>
--# include <limits.h>
--# else
--# include <sys/file.h>
--# include <sys/param.h>
--# endif
--#endif /* SQLITE_ENABLE_LOCKING_STYLE */
--
--#if defined(__APPLE__) || (SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORKS)
--# include <sys/mount.h>
--#endif
-+static void renderLogMsg(int iErrCode, const char *zFormat, va_list ap){
-+ StrAccum acc; /* String accumulator */
-+ char zMsg[SQLITE_PRINT_BUF_SIZE*3]; /* Complete log message */
-
--#ifdef HAVE_UTIME
--# include <utime.h>
--#endif
-+ sqlite3StrAccumInit(&acc, zMsg, sizeof(zMsg), 0);
-+ acc.useMalloc = 0;
-+ sqlite3VXPrintf(&acc, 0, zFormat, ap);
-+ sqlite3GlobalConfig.xLog(sqlite3GlobalConfig.pLogArg, iErrCode,
-+ sqlite3StrAccumFinish(&acc));
-+}
-
- /*
--** Allowed values of unixFile.fsFlags
-+** Format and write a message to the log if logging is enabled.
- */
--#define SQLITE_FSFLAGS_IS_MSDOS 0x1
-+SQLITE_API void sqlite3_log(int iErrCode, const char *zFormat, ...){
-+ va_list ap; /* Vararg list */
-+ if( sqlite3GlobalConfig.xLog ){
-+ va_start(ap, zFormat);
-+ renderLogMsg(iErrCode, zFormat, ap);
-+ va_end(ap);
-+ }
-+}
-
-+#if defined(SQLITE_DEBUG)
- /*
--** If we are to be thread-safe, include the pthreads header and define
--** the SQLITE_UNIX_THREADS macro.
-+** A version of printf() that understands %lld. Used for debugging.
-+** The printf() built into some versions of windows does not understand %lld
-+** and segfaults if you give it a long long int.
- */
--#if SQLITE_THREADSAFE
--/* # include <pthread.h> */
--# define SQLITE_UNIX_THREADS 1
-+SQLITE_PRIVATE void sqlite3DebugPrintf(const char *zFormat, ...){
-+ va_list ap;
-+ StrAccum acc;
-+ char zBuf[500];
-+ sqlite3StrAccumInit(&acc, zBuf, sizeof(zBuf), 0);
-+ acc.useMalloc = 0;
-+ va_start(ap,zFormat);
-+ sqlite3VXPrintf(&acc, 0, zFormat, ap);
-+ va_end(ap);
-+ sqlite3StrAccumFinish(&acc);
-+ fprintf(stdout,"%s", zBuf);
-+ fflush(stdout);
-+}
- #endif
-
-+#ifndef SQLITE_OMIT_TRACE
- /*
--** Default permissions when creating a new file
-+** variable-argument wrapper around sqlite3VXPrintf().
- */
--#ifndef SQLITE_DEFAULT_FILE_PERMISSIONS
--# define SQLITE_DEFAULT_FILE_PERMISSIONS 0644
-+SQLITE_PRIVATE void sqlite3XPrintf(StrAccum *p, const char *zFormat, ...){
-+ va_list ap;
-+ va_start(ap,zFormat);
-+ sqlite3VXPrintf(p, 1, zFormat, ap);
-+ va_end(ap);
-+}
- #endif
-
-+/************** End of printf.c **********************************************/
-+/************** Begin file random.c ******************************************/
- /*
--** Default permissions when creating auto proxy dir
-+** 2001 September 15
-+**
-+** The author disclaims copyright to this source code. In place of
-+** a legal notice, here is a blessing:
-+**
-+** May you do good and not evil.
-+** May you find forgiveness for yourself and forgive others.
-+** May you share freely, never taking more than you give.
-+**
-+*************************************************************************
-+** This file contains code to implement a pseudo-random number
-+** generator (PRNG) for SQLite.
-+**
-+** Random numbers are used by some of the database backends in order
-+** to generate random integer keys for tables or random filenames.
- */
--#ifndef SQLITE_DEFAULT_PROXYDIR_PERMISSIONS
--# define SQLITE_DEFAULT_PROXYDIR_PERMISSIONS 0755
--#endif
-
--/*
--** Maximum supported path-length.
--*/
--#define MAX_PATHNAME 512
-
--/*
--** Only set the lastErrno if the error code is a real error and not
--** a normal expected return code of SQLITE_BUSY or SQLITE_OK
-+/* All threads share a single random number generator.
-+** This structure is the current state of the generator.
- */
--#define IS_LOCK_ERROR(x) ((x != SQLITE_OK) && (x != SQLITE_BUSY))
--
--/* Forward references */
--typedef struct unixShm unixShm; /* Connection shared memory */
--typedef struct unixShmNode unixShmNode; /* Shared memory instance */
--typedef struct unixInodeInfo unixInodeInfo; /* An i-node */
--typedef struct UnixUnusedFd UnixUnusedFd; /* An unused file descriptor */
-+static SQLITE_WSD struct sqlite3PrngType {
-+ unsigned char isInit; /* True if initialized */
-+ unsigned char i, j; /* State variables */
-+ unsigned char s[256]; /* State variables */
-+} sqlite3Prng;
-
- /*
--** Sometimes, after a file handle is closed by SQLite, the file descriptor
--** cannot be closed immediately. In these cases, instances of the following
--** structure are used to store the file descriptor while waiting for an
--** opportunity to either close or reuse it.
-+** Get a single 8-bit random value from the RC4 PRNG. The Mutex
-+** must be held while executing this routine.
-+**
-+** Why not just use a library random generator like lrand48() for this?
-+** Because the OP_NewRowid opcode in the VDBE depends on having a very
-+** good source of random numbers. The lrand48() library function may
-+** well be good enough. But maybe not. Or maybe lrand48() has some
-+** subtle problems on some systems that could cause problems. It is hard
-+** to know. To minimize the risk of problems due to bad lrand48()
-+** implementations, SQLite uses this random number generator based
-+** on RC4, which we know works very well.
-+**
-+** (Later): Actually, OP_NewRowid does not depend on a good source of
-+** randomness any more. But we will leave this code in all the same.
- */
--struct UnixUnusedFd {
-- int fd; /* File descriptor to close */
-- int flags; /* Flags this file descriptor was opened with */
-- UnixUnusedFd *pNext; /* Next unused file descriptor on same file */
--};
-+static u8 randomByte(void){
-+ unsigned char t;
-
--/*
--** The unixFile structure is subclass of sqlite3_file specific to the unix
--** VFS implementations.
--*/
--typedef struct unixFile unixFile;
--struct unixFile {
-- sqlite3_io_methods const *pMethod; /* Always the first entry */
-- sqlite3_vfs *pVfs; /* The VFS that created this unixFile */
-- unixInodeInfo *pInode; /* Info about locks on this inode */
-- int h; /* The file descriptor */
-- unsigned char eFileLock; /* The type of lock held on this fd */
-- unsigned short int ctrlFlags; /* Behavioral bits. UNIXFILE_* flags */
-- int lastErrno; /* The unix errno from last I/O error */
-- void *lockingContext; /* Locking style specific state */
-- UnixUnusedFd *pUnused; /* Pre-allocated UnixUnusedFd */
-- const char *zPath; /* Name of the file */
-- unixShm *pShm; /* Shared memory segment information */
-- int szChunk; /* Configured by FCNTL_CHUNK_SIZE */
-- int nFetchOut; /* Number of outstanding xFetch refs */
-- sqlite3_int64 mmapSize; /* Usable size of mapping at pMapRegion */
-- sqlite3_int64 mmapSizeActual; /* Actual size of mapping at pMapRegion */
-- sqlite3_int64 mmapSizeMax; /* Configured FCNTL_MMAP_SIZE value */
-- void *pMapRegion; /* Memory mapped region */
--#ifdef __QNXNTO__
-- int sectorSize; /* Device sector size */
-- int deviceCharacteristics; /* Precomputed device characteristics */
--#endif
--#if SQLITE_ENABLE_LOCKING_STYLE
-- int openFlags; /* The flags specified at open() */
--#endif
--#if SQLITE_ENABLE_LOCKING_STYLE || defined(__APPLE__)
-- unsigned fsFlags; /* cached details from statfs() */
--#endif
--#if OS_VXWORKS
-- struct vxworksFileId *pId; /* Unique file ID */
--#endif
--#ifdef SQLITE_DEBUG
-- /* The next group of variables are used to track whether or not the
-- ** transaction counter in bytes 24-27 of database files are updated
-- ** whenever any part of the database changes. An assertion fault will
-- ** occur if a file is updated without also updating the transaction
-- ** counter. This test is made to avoid new problems similar to the
-- ** one described by ticket #3584.
-- */
-- unsigned char transCntrChng; /* True if the transaction counter changed */
-- unsigned char dbUpdate; /* True if any part of database file changed */
-- unsigned char inNormalWrite; /* True if in a normal write operation */
-
-+ /* The "wsdPrng" macro will resolve to the pseudo-random number generator
-+ ** state vector. If writable static data is unsupported on the target,
-+ ** we have to locate the state vector at run-time. In the more common
-+ ** case where writable static data is supported, wsdPrng can refer directly
-+ ** to the "sqlite3Prng" state vector declared above.
-+ */
-+#ifdef SQLITE_OMIT_WSD
-+ struct sqlite3PrngType *p = &GLOBAL(struct sqlite3PrngType, sqlite3Prng);
-+# define wsdPrng p[0]
-+#else
-+# define wsdPrng sqlite3Prng
- #endif
-
--#ifdef SQLITE_TEST
-- /* In test mode, increase the size of this structure a bit so that
-- ** it is larger than the struct CrashFile defined in test6.c.
-+
-+ /* Initialize the state of the random number generator once,
-+ ** the first time this routine is called. The seed value does
-+ ** not need to contain a lot of randomness since we are not
-+ ** trying to do secure encryption or anything like that...
-+ **
-+ ** Nothing in this file or anywhere else in SQLite does any kind of
-+ ** encryption. The RC4 algorithm is being used as a PRNG (pseudo-random
-+ ** number generator) not as an encryption device.
- */
-- char aPadding[32];
--#endif
--};
-+ if( !wsdPrng.isInit ){
-+ int i;
-+ char k[256];
-+ wsdPrng.j = 0;
-+ wsdPrng.i = 0;
-+ sqlite3OsRandomness(sqlite3_vfs_find(0), 256, k);
-+ for(i=0; i<256; i++){
-+ wsdPrng.s[i] = (u8)i;
-+ }
-+ for(i=0; i<256; i++){
-+ wsdPrng.j += wsdPrng.s[i] + k[i];
-+ t = wsdPrng.s[wsdPrng.j];
-+ wsdPrng.s[wsdPrng.j] = wsdPrng.s[i];
-+ wsdPrng.s[i] = t;
-+ }
-+ wsdPrng.isInit = 1;
-+ }
-+
-+ /* Generate and return single random byte
-+ */
-+ wsdPrng.i++;
-+ t = wsdPrng.s[wsdPrng.i];
-+ wsdPrng.j += t;
-+ wsdPrng.s[wsdPrng.i] = wsdPrng.s[wsdPrng.j];
-+ wsdPrng.s[wsdPrng.j] = t;
-+ t += wsdPrng.s[wsdPrng.i];
-+ return wsdPrng.s[t];
-+}
-
- /*
--** Allowed values for the unixFile.ctrlFlags bitmask:
-+** Return N random bytes.
- */
--#define UNIXFILE_EXCL 0x01 /* Connections from one process only */
--#define UNIXFILE_RDONLY 0x02 /* Connection is read only */
--#define UNIXFILE_PERSIST_WAL 0x04 /* Persistent WAL mode */
--#ifndef SQLITE_DISABLE_DIRSYNC
--# define UNIXFILE_DIRSYNC 0x08 /* Directory sync needed */
--#else
--# define UNIXFILE_DIRSYNC 0x00
-+SQLITE_API void sqlite3_randomness(int N, void *pBuf){
-+ unsigned char *zBuf = pBuf;
-+#if SQLITE_THREADSAFE
-+ sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_PRNG);
- #endif
--#define UNIXFILE_PSOW 0x10 /* SQLITE_IOCAP_POWERSAFE_OVERWRITE */
--#define UNIXFILE_DELETE 0x20 /* Delete on close */
--#define UNIXFILE_URI 0x40 /* Filename might have query parameters */
--#define UNIXFILE_NOLOCK 0x80 /* Do no file locking */
--#define UNIXFILE_WARNED 0x0100 /* verifyDbFile() warnings have been issued */
-+ sqlite3_mutex_enter(mutex);
-+ while( N-- ){
-+ *(zBuf++) = randomByte();
-+ }
-+ sqlite3_mutex_leave(mutex);
-+}
-
-+#ifndef SQLITE_OMIT_BUILTIN_TEST
- /*
--** Include code that is common to all os_*.c files
-+** For testing purposes, we sometimes want to preserve the state of
-+** PRNG and restore the PRNG to its saved state at a later time, or
-+** to reset the PRNG to its initial state. These routines accomplish
-+** those tasks.
-+**
-+** The sqlite3_test_control() interface calls these routines to
-+** control the PRNG.
- */
--/************** Include os_common.h in the middle of os_unix.c ***************/
--/************** Begin file os_common.h ***************************************/
-+static SQLITE_WSD struct sqlite3PrngType sqlite3SavedPrng;
-+SQLITE_PRIVATE void sqlite3PrngSaveState(void){
-+ memcpy(
-+ &GLOBAL(struct sqlite3PrngType, sqlite3SavedPrng),
-+ &GLOBAL(struct sqlite3PrngType, sqlite3Prng),
-+ sizeof(sqlite3Prng)
-+ );
-+}
-+SQLITE_PRIVATE void sqlite3PrngRestoreState(void){
-+ memcpy(
-+ &GLOBAL(struct sqlite3PrngType, sqlite3Prng),
-+ &GLOBAL(struct sqlite3PrngType, sqlite3SavedPrng),
-+ sizeof(sqlite3Prng)
-+ );
-+}
-+SQLITE_PRIVATE void sqlite3PrngResetState(void){
-+ GLOBAL(struct sqlite3PrngType, sqlite3Prng).isInit = 0;
-+}
-+#endif /* SQLITE_OMIT_BUILTIN_TEST */
-+
-+/************** End of random.c **********************************************/
-+/************** Begin file utf.c *********************************************/
- /*
--** 2004 May 22
-+** 2004 April 13
- **
- ** The author disclaims copyright to this source code. In place of
- ** a legal notice, here is a blessing:
-@@ -23182,13485 +23716,14956 @@
- ** May you find forgiveness for yourself and forgive others.
- ** May you share freely, never taking more than you give.
- **
--******************************************************************************
-+*************************************************************************
-+** This file contains routines used to translate between UTF-8,
-+** UTF-16, UTF-16BE, and UTF-16LE.
- **
--** This file contains macros and a little bit of code that is common to
--** all of the platform-specific files (os_*.c) and is #included into those
--** files.
-+** Notes on UTF-8:
-+**
-+** Byte-0 Byte-1 Byte-2 Byte-3 Value
-+** 0xxxxxxx 00000000 00000000 0xxxxxxx
-+** 110yyyyy 10xxxxxx 00000000 00000yyy yyxxxxxx
-+** 1110zzzz 10yyyyyy 10xxxxxx 00000000 zzzzyyyy yyxxxxxx
-+** 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx 000uuuuu zzzzyyyy yyxxxxxx
-+**
-+**
-+** Notes on UTF-16: (with wwww+1==uuuuu)
-+**
-+** Word-0 Word-1 Value
-+** 110110ww wwzzzzyy 110111yy yyxxxxxx 000uuuuu zzzzyyyy yyxxxxxx
-+** zzzzyyyy yyxxxxxx 00000000 zzzzyyyy yyxxxxxx
-+**
-+**
-+** BOM or Byte Order Mark:
-+** 0xff 0xfe little-endian utf-16 follows
-+** 0xfe 0xff big-endian utf-16 follows
- **
--** This file should be #included by the os_*.c files only. It is not a
--** general purpose header file.
- */
--#ifndef _OS_COMMON_H_
--#define _OS_COMMON_H_
-+/* #include <assert.h> */
-
-+#ifndef SQLITE_AMALGAMATION
- /*
--** At least two bugs have slipped in because we changed the MEMORY_DEBUG
--** macro to SQLITE_DEBUG and some older makefiles have not yet made the
--** switch. The following code should catch this problem at compile-time.
-+** The following constant value is used by the SQLITE_BIGENDIAN and
-+** SQLITE_LITTLEENDIAN macros.
- */
--#ifdef MEMORY_DEBUG
--# error "The MEMORY_DEBUG macro is obsolete. Use SQLITE_DEBUG instead."
--#endif
--
--#if defined(SQLITE_TEST) && defined(SQLITE_DEBUG)
--# ifndef SQLITE_DEBUG_OS_TRACE
--# define SQLITE_DEBUG_OS_TRACE 0
--# endif
-- int sqlite3OSTrace = SQLITE_DEBUG_OS_TRACE;
--# define OSTRACE(X) if( sqlite3OSTrace ) sqlite3DebugPrintf X
--#else
--# define OSTRACE(X)
--#endif
-+SQLITE_PRIVATE const int sqlite3one = 1;
-+#endif /* SQLITE_AMALGAMATION */
-
- /*
--** Macros for performance tracing. Normally turned off. Only works
--** on i486 hardware.
-+** This lookup table is used to help decode the first byte of
-+** a multi-byte UTF8 character.
- */
--#ifdef SQLITE_PERFORMANCE_TRACE
-+static const unsigned char sqlite3Utf8Trans1[] = {
-+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
-+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
-+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
-+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
-+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-+ 0x00, 0x01, 0x02, 0x03, 0x00, 0x01, 0x00, 0x00,
-+};
-+
-+
-+#define WRITE_UTF8(zOut, c) { \
-+ if( c<0x00080 ){ \
-+ *zOut++ = (u8)(c&0xFF); \
-+ } \
-+ else if( c<0x00800 ){ \
-+ *zOut++ = 0xC0 + (u8)((c>>6)&0x1F); \
-+ *zOut++ = 0x80 + (u8)(c & 0x3F); \
-+ } \
-+ else if( c<0x10000 ){ \
-+ *zOut++ = 0xE0 + (u8)((c>>12)&0x0F); \
-+ *zOut++ = 0x80 + (u8)((c>>6) & 0x3F); \
-+ *zOut++ = 0x80 + (u8)(c & 0x3F); \
-+ }else{ \
-+ *zOut++ = 0xF0 + (u8)((c>>18) & 0x07); \
-+ *zOut++ = 0x80 + (u8)((c>>12) & 0x3F); \
-+ *zOut++ = 0x80 + (u8)((c>>6) & 0x3F); \
-+ *zOut++ = 0x80 + (u8)(c & 0x3F); \
-+ } \
-+}
-+
-+#define WRITE_UTF16LE(zOut, c) { \
-+ if( c<=0xFFFF ){ \
-+ *zOut++ = (u8)(c&0x00FF); \
-+ *zOut++ = (u8)((c>>8)&0x00FF); \
-+ }else{ \
-+ *zOut++ = (u8)(((c>>10)&0x003F) + (((c-0x10000)>>10)&0x00C0)); \
-+ *zOut++ = (u8)(0x00D8 + (((c-0x10000)>>18)&0x03)); \
-+ *zOut++ = (u8)(c&0x00FF); \
-+ *zOut++ = (u8)(0x00DC + ((c>>8)&0x03)); \
-+ } \
-+}
-+
-+#define WRITE_UTF16BE(zOut, c) { \
-+ if( c<=0xFFFF ){ \
-+ *zOut++ = (u8)((c>>8)&0x00FF); \
-+ *zOut++ = (u8)(c&0x00FF); \
-+ }else{ \
-+ *zOut++ = (u8)(0x00D8 + (((c-0x10000)>>18)&0x03)); \
-+ *zOut++ = (u8)(((c>>10)&0x003F) + (((c-0x10000)>>10)&0x00C0)); \
-+ *zOut++ = (u8)(0x00DC + ((c>>8)&0x03)); \
-+ *zOut++ = (u8)(c&0x00FF); \
-+ } \
-+}
-+
-+#define READ_UTF16LE(zIn, TERM, c){ \
-+ c = (*zIn++); \
-+ c += ((*zIn++)<<8); \
-+ if( c>=0xD800 && c<0xE000 && TERM ){ \
-+ int c2 = (*zIn++); \
-+ c2 += ((*zIn++)<<8); \
-+ c = (c2&0x03FF) + ((c&0x003F)<<10) + (((c&0x03C0)+0x0040)<<10); \
-+ } \
-+}
-+
-+#define READ_UTF16BE(zIn, TERM, c){ \
-+ c = ((*zIn++)<<8); \
-+ c += (*zIn++); \
-+ if( c>=0xD800 && c<0xE000 && TERM ){ \
-+ int c2 = ((*zIn++)<<8); \
-+ c2 += (*zIn++); \
-+ c = (c2&0x03FF) + ((c&0x003F)<<10) + (((c&0x03C0)+0x0040)<<10); \
-+ } \
-+}
-
--/*
--** hwtime.h contains inline assembler code for implementing
--** high-performance timing routines.
--*/
--/************** Include hwtime.h in the middle of os_common.h ****************/
--/************** Begin file hwtime.h ******************************************/
- /*
--** 2008 May 27
-+** Translate a single UTF-8 character. Return the unicode value.
- **
--** The author disclaims copyright to this source code. In place of
--** a legal notice, here is a blessing:
-+** During translation, assume that the byte that zTerm points
-+** is a 0x00.
- **
--** May you do good and not evil.
--** May you find forgiveness for yourself and forgive others.
--** May you share freely, never taking more than you give.
-+** Write a pointer to the next unread byte back into *pzNext.
- **
--******************************************************************************
-+** Notes On Invalid UTF-8:
- **
--** This file contains inline asm code for retrieving "high-performance"
--** counters for x86 class CPUs.
-+** * This routine never allows a 7-bit character (0x00 through 0x7f) to
-+** be encoded as a multi-byte character. Any multi-byte character that
-+** attempts to encode a value between 0x00 and 0x7f is rendered as 0xfffd.
-+**
-+** * This routine never allows a UTF16 surrogate value to be encoded.
-+** If a multi-byte character attempts to encode a value between
-+** 0xd800 and 0xe000 then it is rendered as 0xfffd.
-+**
-+** * Bytes in the range of 0x80 through 0xbf which occur as the first
-+** byte of a character are interpreted as single-byte characters
-+** and rendered as themselves even though they are technically
-+** invalid characters.
-+**
-+** * This routine accepts an infinite number of different UTF8 encodings
-+** for unicode values 0x80 and greater. It do not change over-length
-+** encodings to 0xfffd as some systems recommend.
- */
--#ifndef _HWTIME_H_
--#define _HWTIME_H_
-+#define READ_UTF8(zIn, zTerm, c) \
-+ c = *(zIn++); \
-+ if( c>=0xc0 ){ \
-+ c = sqlite3Utf8Trans1[c-0xc0]; \
-+ while( zIn!=zTerm && (*zIn & 0xc0)==0x80 ){ \
-+ c = (c<<6) + (0x3f & *(zIn++)); \
-+ } \
-+ if( c<0x80 \
-+ || (c&0xFFFFF800)==0xD800 \
-+ || (c&0xFFFFFFFE)==0xFFFE ){ c = 0xFFFD; } \
-+ }
-+SQLITE_PRIVATE u32 sqlite3Utf8Read(
-+ const unsigned char **pz /* Pointer to string from which to read char */
-+){
-+ unsigned int c;
-+
-+ /* Same as READ_UTF8() above but without the zTerm parameter.
-+ ** For this routine, we assume the UTF8 string is always zero-terminated.
-+ */
-+ c = *((*pz)++);
-+ if( c>=0xc0 ){
-+ c = sqlite3Utf8Trans1[c-0xc0];
-+ while( (*(*pz) & 0xc0)==0x80 ){
-+ c = (c<<6) + (0x3f & *((*pz)++));
-+ }
-+ if( c<0x80
-+ || (c&0xFFFFF800)==0xD800
-+ || (c&0xFFFFFFFE)==0xFFFE ){ c = 0xFFFD; }
-+ }
-+ return c;
-+}
-+
-+
-+
-
- /*
--** The following routine only works on pentium-class (or newer) processors.
--** It uses the RDTSC opcode to read the cycle count value out of the
--** processor and returns that value. This can be used for high-res
--** profiling.
-+** If the TRANSLATE_TRACE macro is defined, the value of each Mem is
-+** printed on stderr on the way into and out of sqlite3VdbeMemTranslate().
-+*/
-+/* #define TRANSLATE_TRACE 1 */
-+
-+#ifndef SQLITE_OMIT_UTF16
-+/*
-+** This routine transforms the internal text encoding used by pMem to
-+** desiredEnc. It is an error if the string is already of the desired
-+** encoding, or if *pMem does not contain a string value.
- */
--#if (defined(__GNUC__) || defined(_MSC_VER)) && \
-- (defined(i386) || defined(__i386__) || defined(_M_IX86))
-+SQLITE_PRIVATE int sqlite3VdbeMemTranslate(Mem *pMem, u8 desiredEnc){
-+ int len; /* Maximum length of output string in bytes */
-+ unsigned char *zOut; /* Output buffer */
-+ unsigned char *zIn; /* Input iterator */
-+ unsigned char *zTerm; /* End of input */
-+ unsigned char *z; /* Output iterator */
-+ unsigned int c;
-
-- #if defined(__GNUC__)
-+ assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
-+ assert( pMem->flags&MEM_Str );
-+ assert( pMem->enc!=desiredEnc );
-+ assert( pMem->enc!=0 );
-+ assert( pMem->n>=0 );
-
-- __inline__ sqlite_uint64 sqlite3Hwtime(void){
-- unsigned int lo, hi;
-- __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
-- return (sqlite_uint64)hi << 32 | lo;
-+#if defined(TRANSLATE_TRACE) && defined(SQLITE_DEBUG)
-+ {
-+ char zBuf[100];
-+ sqlite3VdbeMemPrettyPrint(pMem, zBuf);
-+ fprintf(stderr, "INPUT: %s\n", zBuf);
- }
-+#endif
-
-- #elif defined(_MSC_VER)
--
-- __declspec(naked) __inline sqlite_uint64 __cdecl sqlite3Hwtime(void){
-- __asm {
-- rdtsc
-- ret ; return value at EDX:EAX
-- }
-+ /* If the translation is between UTF-16 little and big endian, then
-+ ** all that is required is to swap the byte order. This case is handled
-+ ** differently from the others.
-+ */
-+ if( pMem->enc!=SQLITE_UTF8 && desiredEnc!=SQLITE_UTF8 ){
-+ u8 temp;
-+ int rc;
-+ rc = sqlite3VdbeMemMakeWriteable(pMem);
-+ if( rc!=SQLITE_OK ){
-+ assert( rc==SQLITE_NOMEM );
-+ return SQLITE_NOMEM;
-+ }
-+ zIn = (u8*)pMem->z;
-+ zTerm = &zIn[pMem->n&~1];
-+ while( zIn<zTerm ){
-+ temp = *zIn;
-+ *zIn = *(zIn+1);
-+ zIn++;
-+ *zIn++ = temp;
-+ }
-+ pMem->enc = desiredEnc;
-+ goto translate_out;
- }
-
-- #endif
--
--#elif (defined(__GNUC__) && defined(__x86_64__))
-+ /* Set len to the maximum number of bytes required in the output buffer. */
-+ if( desiredEnc==SQLITE_UTF8 ){
-+ /* When converting from UTF-16, the maximum growth results from
-+ ** translating a 2-byte character to a 4-byte UTF-8 character.
-+ ** A single byte is required for the output string
-+ ** nul-terminator.
-+ */
-+ pMem->n &= ~1;
-+ len = pMem->n * 2 + 1;
-+ }else{
-+ /* When converting from UTF-8 to UTF-16 the maximum growth is caused
-+ ** when a 1-byte UTF-8 character is translated into a 2-byte UTF-16
-+ ** character. Two bytes are required in the output buffer for the
-+ ** nul-terminator.
-+ */
-+ len = pMem->n * 2 + 2;
-+ }
-
-- __inline__ sqlite_uint64 sqlite3Hwtime(void){
-- unsigned long val;
-- __asm__ __volatile__ ("rdtsc" : "=A" (val));
-- return val;
-+ /* Set zIn to point at the start of the input buffer and zTerm to point 1
-+ ** byte past the end.
-+ **
-+ ** Variable zOut is set to point at the output buffer, space obtained
-+ ** from sqlite3_malloc().
-+ */
-+ zIn = (u8*)pMem->z;
-+ zTerm = &zIn[pMem->n];
-+ zOut = sqlite3DbMallocRaw(pMem->db, len);
-+ if( !zOut ){
-+ return SQLITE_NOMEM;
- }
--
--#elif (defined(__GNUC__) && defined(__ppc__))
-+ z = zOut;
-
-- __inline__ sqlite_uint64 sqlite3Hwtime(void){
-- unsigned long long retval;
-- unsigned long junk;
-- __asm__ __volatile__ ("\n\
-- 1: mftbu %1\n\
-- mftb %L0\n\
-- mftbu %0\n\
-- cmpw %0,%1\n\
-- bne 1b"
-- : "=r" (retval), "=r" (junk));
-- return retval;
-+ if( pMem->enc==SQLITE_UTF8 ){
-+ if( desiredEnc==SQLITE_UTF16LE ){
-+ /* UTF-8 -> UTF-16 Little-endian */
-+ while( zIn<zTerm ){
-+ READ_UTF8(zIn, zTerm, c);
-+ WRITE_UTF16LE(z, c);
-+ }
-+ }else{
-+ assert( desiredEnc==SQLITE_UTF16BE );
-+ /* UTF-8 -> UTF-16 Big-endian */
-+ while( zIn<zTerm ){
-+ READ_UTF8(zIn, zTerm, c);
-+ WRITE_UTF16BE(z, c);
-+ }
-+ }
-+ pMem->n = (int)(z - zOut);
-+ *z++ = 0;
-+ }else{
-+ assert( desiredEnc==SQLITE_UTF8 );
-+ if( pMem->enc==SQLITE_UTF16LE ){
-+ /* UTF-16 Little-endian -> UTF-8 */
-+ while( zIn<zTerm ){
-+ READ_UTF16LE(zIn, zIn<zTerm, c);
-+ WRITE_UTF8(z, c);
-+ }
-+ }else{
-+ /* UTF-16 Big-endian -> UTF-8 */
-+ while( zIn<zTerm ){
-+ READ_UTF16BE(zIn, zIn<zTerm, c);
-+ WRITE_UTF8(z, c);
-+ }
-+ }
-+ pMem->n = (int)(z - zOut);
- }
-+ *z = 0;
-+ assert( (pMem->n+(desiredEnc==SQLITE_UTF8?1:2))<=len );
-
--#else
-+ sqlite3VdbeMemRelease(pMem);
-+ pMem->flags &= ~(MEM_Static|MEM_Dyn|MEM_Ephem);
-+ pMem->enc = desiredEnc;
-+ pMem->flags |= (MEM_Term|MEM_Dyn);
-+ pMem->z = (char*)zOut;
-+ pMem->zMalloc = pMem->z;
-
-- #error Need implementation of sqlite3Hwtime() for your platform.
-+translate_out:
-+#if defined(TRANSLATE_TRACE) && defined(SQLITE_DEBUG)
-+ {
-+ char zBuf[100];
-+ sqlite3VdbeMemPrettyPrint(pMem, zBuf);
-+ fprintf(stderr, "OUTPUT: %s\n", zBuf);
-+ }
-+#endif
-+ return SQLITE_OK;
-+}
-
-- /*
-- ** To compile without implementing sqlite3Hwtime() for your platform,
-- ** you can remove the above #error and use the following
-- ** stub function. You will lose timing support for many
-- ** of the debugging and testing utilities, but it should at
-- ** least compile and run.
-- */
--SQLITE_PRIVATE sqlite_uint64 sqlite3Hwtime(void){ return ((sqlite_uint64)0); }
-+/*
-+** This routine checks for a byte-order mark at the beginning of the
-+** UTF-16 string stored in *pMem. If one is present, it is removed and
-+** the encoding of the Mem adjusted. This routine does not do any
-+** byte-swapping, it just sets Mem.enc appropriately.
-+**
-+** The allocation (static, dynamic etc.) and encoding of the Mem may be
-+** changed by this function.
-+*/
-+SQLITE_PRIVATE int sqlite3VdbeMemHandleBom(Mem *pMem){
-+ int rc = SQLITE_OK;
-+ u8 bom = 0;
-
--#endif
-+ assert( pMem->n>=0 );
-+ if( pMem->n>1 ){
-+ u8 b1 = *(u8 *)pMem->z;
-+ u8 b2 = *(((u8 *)pMem->z) + 1);
-+ if( b1==0xFE && b2==0xFF ){
-+ bom = SQLITE_UTF16BE;
-+ }
-+ if( b1==0xFF && b2==0xFE ){
-+ bom = SQLITE_UTF16LE;
-+ }
-+ }
-+
-+ if( bom ){
-+ rc = sqlite3VdbeMemMakeWriteable(pMem);
-+ if( rc==SQLITE_OK ){
-+ pMem->n -= 2;
-+ memmove(pMem->z, &pMem->z[2], pMem->n);
-+ pMem->z[pMem->n] = '\0';
-+ pMem->z[pMem->n+1] = '\0';
-+ pMem->flags |= MEM_Term;
-+ pMem->enc = bom;
-+ }
-+ }
-+ return rc;
-+}
-+#endif /* SQLITE_OMIT_UTF16 */
-
--#endif /* !defined(_HWTIME_H_) */
-+/*
-+** pZ is a UTF-8 encoded unicode string. If nByte is less than zero,
-+** return the number of unicode characters in pZ up to (but not including)
-+** the first 0x00 byte. If nByte is not less than zero, return the
-+** number of unicode characters in the first nByte of pZ (or up to
-+** the first 0x00, whichever comes first).
-+*/
-+SQLITE_PRIVATE int sqlite3Utf8CharLen(const char *zIn, int nByte){
-+ int r = 0;
-+ const u8 *z = (const u8*)zIn;
-+ const u8 *zTerm;
-+ if( nByte>=0 ){
-+ zTerm = &z[nByte];
-+ }else{
-+ zTerm = (const u8*)(-1);
-+ }
-+ assert( z<=zTerm );
-+ while( *z!=0 && z<zTerm ){
-+ SQLITE_SKIP_UTF8(z);
-+ r++;
-+ }
-+ return r;
-+}
-
--/************** End of hwtime.h **********************************************/
--/************** Continuing where we left off in os_common.h ******************/
-+/* This test function is not currently used by the automated test-suite.
-+** Hence it is only available in debug builds.
-+*/
-+#if defined(SQLITE_TEST) && defined(SQLITE_DEBUG)
-+/*
-+** Translate UTF-8 to UTF-8.
-+**
-+** This has the effect of making sure that the string is well-formed
-+** UTF-8. Miscoded characters are removed.
-+**
-+** The translation is done in-place and aborted if the output
-+** overruns the input.
-+*/
-+SQLITE_PRIVATE int sqlite3Utf8To8(unsigned char *zIn){
-+ unsigned char *zOut = zIn;
-+ unsigned char *zStart = zIn;
-+ u32 c;
-
--static sqlite_uint64 g_start;
--static sqlite_uint64 g_elapsed;
--#define TIMER_START g_start=sqlite3Hwtime()
--#define TIMER_END g_elapsed=sqlite3Hwtime()-g_start
--#define TIMER_ELAPSED g_elapsed
--#else
--#define TIMER_START
--#define TIMER_END
--#define TIMER_ELAPSED ((sqlite_uint64)0)
-+ while( zIn[0] && zOut<=zIn ){
-+ c = sqlite3Utf8Read((const u8**)&zIn);
-+ if( c!=0xfffd ){
-+ WRITE_UTF8(zOut, c);
-+ }
-+ }
-+ *zOut = 0;
-+ return (int)(zOut - zStart);
-+}
- #endif
-
-+#ifndef SQLITE_OMIT_UTF16
- /*
--** If we compile with the SQLITE_TEST macro set, then the following block
--** of code will give us the ability to simulate a disk I/O error. This
--** is used for testing the I/O recovery logic.
-+** Convert a UTF-16 string in the native encoding into a UTF-8 string.
-+** Memory to hold the UTF-8 string is obtained from sqlite3_malloc and must
-+** be freed by the calling function.
-+**
-+** NULL is returned if there is an allocation error.
- */
--#ifdef SQLITE_TEST
--SQLITE_API int sqlite3_io_error_hit = 0; /* Total number of I/O Errors */
--SQLITE_API int sqlite3_io_error_hardhit = 0; /* Number of non-benign errors */
--SQLITE_API int sqlite3_io_error_pending = 0; /* Count down to first I/O error */
--SQLITE_API int sqlite3_io_error_persist = 0; /* True if I/O errors persist */
--SQLITE_API int sqlite3_io_error_benign = 0; /* True if errors are benign */
--SQLITE_API int sqlite3_diskfull_pending = 0;
--SQLITE_API int sqlite3_diskfull = 0;
--#define SimulateIOErrorBenign(X) sqlite3_io_error_benign=(X)
--#define SimulateIOError(CODE) \
-- if( (sqlite3_io_error_persist && sqlite3_io_error_hit) \
-- || sqlite3_io_error_pending-- == 1 ) \
-- { local_ioerr(); CODE; }
--static void local_ioerr(){
-- IOTRACE(("IOERR\n"));
-- sqlite3_io_error_hit++;
-- if( !sqlite3_io_error_benign ) sqlite3_io_error_hardhit++;
-+SQLITE_PRIVATE char *sqlite3Utf16to8(sqlite3 *db, const void *z, int nByte, u8 enc){
-+ Mem m;
-+ memset(&m, 0, sizeof(m));
-+ m.db = db;
-+ sqlite3VdbeMemSetStr(&m, z, nByte, enc, SQLITE_STATIC);
-+ sqlite3VdbeChangeEncoding(&m, SQLITE_UTF8);
-+ if( db->mallocFailed ){
-+ sqlite3VdbeMemRelease(&m);
-+ m.z = 0;
-+ }
-+ assert( (m.flags & MEM_Term)!=0 || db->mallocFailed );
-+ assert( (m.flags & MEM_Str)!=0 || db->mallocFailed );
-+ assert( (m.flags & MEM_Dyn)!=0 || db->mallocFailed );
-+ assert( m.z || db->mallocFailed );
-+ return m.z;
-+}
-+
-+/*
-+** Convert a UTF-8 string to the UTF-16 encoding specified by parameter
-+** enc. A pointer to the new string is returned, and the value of *pnOut
-+** is set to the length of the returned string in bytes. The call should
-+** arrange to call sqlite3DbFree() on the returned pointer when it is
-+** no longer required.
-+**
-+** If a malloc failure occurs, NULL is returned and the db.mallocFailed
-+** flag set.
-+*/
-+#ifdef SQLITE_ENABLE_STAT3
-+SQLITE_PRIVATE char *sqlite3Utf8to16(sqlite3 *db, u8 enc, char *z, int n, int *pnOut){
-+ Mem m;
-+ memset(&m, 0, sizeof(m));
-+ m.db = db;
-+ sqlite3VdbeMemSetStr(&m, z, n, SQLITE_UTF8, SQLITE_STATIC);
-+ if( sqlite3VdbeMemTranslate(&m, enc) ){
-+ assert( db->mallocFailed );
-+ return 0;
-+ }
-+ assert( m.z==m.zMalloc );
-+ *pnOut = m.n;
-+ return m.z;
- }
--#define SimulateDiskfullError(CODE) \
-- if( sqlite3_diskfull_pending ){ \
-- if( sqlite3_diskfull_pending == 1 ){ \
-- local_ioerr(); \
-- sqlite3_diskfull = 1; \
-- sqlite3_io_error_hit = 1; \
-- CODE; \
-- }else{ \
-- sqlite3_diskfull_pending--; \
-- } \
-- }
--#else
--#define SimulateIOErrorBenign(X)
--#define SimulateIOError(A)
--#define SimulateDiskfullError(A)
- #endif
-
- /*
--** When testing, keep a count of the number of open files.
-+** zIn is a UTF-16 encoded unicode string at least nChar characters long.
-+** Return the number of bytes in the first nChar unicode characters
-+** in pZ. nChar must be non-negative.
-+*/
-+SQLITE_PRIVATE int sqlite3Utf16ByteLen(const void *zIn, int nChar){
-+ int c;
-+ unsigned char const *z = zIn;
-+ int n = 0;
-+
-+ if( SQLITE_UTF16NATIVE==SQLITE_UTF16BE ){
-+ while( n<nChar ){
-+ READ_UTF16BE(z, 1, c);
-+ n++;
-+ }
-+ }else{
-+ while( n<nChar ){
-+ READ_UTF16LE(z, 1, c);
-+ n++;
-+ }
-+ }
-+ return (int)(z-(unsigned char const *)zIn);
-+}
-+
-+#if defined(SQLITE_TEST)
-+/*
-+** This routine is called from the TCL test function "translate_selftest".
-+** It checks that the primitives for serializing and deserializing
-+** characters in each encoding are inverses of each other.
-+*/
-+SQLITE_PRIVATE void sqlite3UtfSelfTest(void){
-+ unsigned int i, t;
-+ unsigned char zBuf[20];
-+ unsigned char *z;
-+ int n;
-+ unsigned int c;
-+
-+ for(i=0; i<0x00110000; i++){
-+ z = zBuf;
-+ WRITE_UTF8(z, i);
-+ n = (int)(z-zBuf);
-+ assert( n>0 && n<=4 );
-+ z[0] = 0;
-+ z = zBuf;
-+ c = sqlite3Utf8Read((const u8**)&z);
-+ t = i;
-+ if( i>=0xD800 && i<=0xDFFF ) t = 0xFFFD;
-+ if( (i&0xFFFFFFFE)==0xFFFE ) t = 0xFFFD;
-+ assert( c==t );
-+ assert( (z-zBuf)==n );
-+ }
-+ for(i=0; i<0x00110000; i++){
-+ if( i>=0xD800 && i<0xE000 ) continue;
-+ z = zBuf;
-+ WRITE_UTF16LE(z, i);
-+ n = (int)(z-zBuf);
-+ assert( n>0 && n<=4 );
-+ z[0] = 0;
-+ z = zBuf;
-+ READ_UTF16LE(z, 1, c);
-+ assert( c==i );
-+ assert( (z-zBuf)==n );
-+ }
-+ for(i=0; i<0x00110000; i++){
-+ if( i>=0xD800 && i<0xE000 ) continue;
-+ z = zBuf;
-+ WRITE_UTF16BE(z, i);
-+ n = (int)(z-zBuf);
-+ assert( n>0 && n<=4 );
-+ z[0] = 0;
-+ z = zBuf;
-+ READ_UTF16BE(z, 1, c);
-+ assert( c==i );
-+ assert( (z-zBuf)==n );
-+ }
-+}
-+#endif /* SQLITE_TEST */
-+#endif /* SQLITE_OMIT_UTF16 */
-+
-+/************** End of utf.c *************************************************/
-+/************** Begin file util.c ********************************************/
-+/*
-+** 2001 September 15
-+**
-+** The author disclaims copyright to this source code. In place of
-+** a legal notice, here is a blessing:
-+**
-+** May you do good and not evil.
-+** May you find forgiveness for yourself and forgive others.
-+** May you share freely, never taking more than you give.
-+**
-+*************************************************************************
-+** Utility functions used throughout sqlite.
-+**
-+** This file contains functions for allocating memory, comparing
-+** strings, and stuff like that.
-+**
- */
--#ifdef SQLITE_TEST
--SQLITE_API int sqlite3_open_file_count = 0;
--#define OpenCounter(X) sqlite3_open_file_count+=(X)
--#else
--#define OpenCounter(X)
-+/* #include <stdarg.h> */
-+#ifdef SQLITE_HAVE_ISNAN
-+# include <math.h>
- #endif
-
--#endif /* !defined(_OS_COMMON_H_) */
--
--/************** End of os_common.h *******************************************/
--/************** Continuing where we left off in os_unix.c ********************/
--
- /*
--** Define various macros that are missing from some systems.
-+** Routine needed to support the testcase() macro.
- */
--#ifndef O_LARGEFILE
--# define O_LARGEFILE 0
--#endif
--#ifdef SQLITE_DISABLE_LFS
--# undef O_LARGEFILE
--# define O_LARGEFILE 0
--#endif
--#ifndef O_NOFOLLOW
--# define O_NOFOLLOW 0
--#endif
--#ifndef O_BINARY
--# define O_BINARY 0
-+#ifdef SQLITE_COVERAGE_TEST
-+SQLITE_PRIVATE void sqlite3Coverage(int x){
-+ static unsigned dummy = 0;
-+ dummy += (unsigned)x;
-+}
- #endif
-
-+#ifndef SQLITE_OMIT_FLOATING_POINT
- /*
--** The threadid macro resolves to the thread-id or to 0. Used for
--** testing and debugging only.
-+** Return true if the floating point value is Not a Number (NaN).
-+**
-+** Use the math library isnan() function if compiled with SQLITE_HAVE_ISNAN.
-+** Otherwise, we have our own implementation that works on most systems.
- */
--#if SQLITE_THREADSAFE
--#define threadid pthread_self()
--#else
--#define threadid 0
-+SQLITE_PRIVATE int sqlite3IsNaN(double x){
-+ int rc; /* The value return */
-+#if !defined(SQLITE_HAVE_ISNAN)
-+ /*
-+ ** Systems that support the isnan() library function should probably
-+ ** make use of it by compiling with -DSQLITE_HAVE_ISNAN. But we have
-+ ** found that many systems do not have a working isnan() function so
-+ ** this implementation is provided as an alternative.
-+ **
-+ ** This NaN test sometimes fails if compiled on GCC with -ffast-math.
-+ ** On the other hand, the use of -ffast-math comes with the following
-+ ** warning:
-+ **
-+ ** This option [-ffast-math] should never be turned on by any
-+ ** -O option since it can result in incorrect output for programs
-+ ** which depend on an exact implementation of IEEE or ISO
-+ ** rules/specifications for math functions.
-+ **
-+ ** Under MSVC, this NaN test may fail if compiled with a floating-
-+ ** point precision mode other than /fp:precise. From the MSDN
-+ ** documentation:
-+ **
-+ ** The compiler [with /fp:precise] will properly handle comparisons
-+ ** involving NaN. For example, x != x evaluates to true if x is NaN
-+ ** ...
-+ */
-+#ifdef __FAST_MATH__
-+# error SQLite will not work correctly with the -ffast-math option of GCC.
- #endif
-+ volatile double y = x;
-+ volatile double z = y;
-+ rc = (y!=z);
-+#else /* if defined(SQLITE_HAVE_ISNAN) */
-+ rc = isnan(x);
-+#endif /* SQLITE_HAVE_ISNAN */
-+ testcase( rc );
-+ return rc;
-+}
-+#endif /* SQLITE_OMIT_FLOATING_POINT */
-
- /*
--** HAVE_MREMAP defaults to true on Linux and false everywhere else.
-+** Compute a string length that is limited to what can be stored in
-+** lower 30 bits of a 32-bit signed integer.
-+**
-+** The value returned will never be negative. Nor will it ever be greater
-+** than the actual length of the string. For very long strings (greater
-+** than 1GiB) the value returned might be less than the true string length.
- */
--#if !defined(HAVE_MREMAP)
--# if defined(__linux__) && defined(_GNU_SOURCE)
--# define HAVE_MREMAP 1
--# else
--# define HAVE_MREMAP 0
--# endif
--#endif
-+SQLITE_PRIVATE int sqlite3Strlen30(const char *z){
-+ const char *z2 = z;
-+ if( z==0 ) return 0;
-+ while( *z2 ){ z2++; }
-+ return 0x3fffffff & (int)(z2 - z);
-+}
-
- /*
--** Different Unix systems declare open() in different ways. Same use
--** open(const char*,int,mode_t). Others use open(const char*,int,...).
--** The difference is important when using a pointer to the function.
-+** Set the most recent error code and error string for the sqlite
-+** handle "db". The error code is set to "err_code".
- **
--** The safest way to deal with the problem is to always use this wrapper
--** which always has the same well-defined interface.
-+** If it is not NULL, string zFormat specifies the format of the
-+** error string in the style of the printf functions: The following
-+** format characters are allowed:
-+**
-+** %s Insert a string
-+** %z A string that should be freed after use
-+** %d Insert an integer
-+** %T Insert a token
-+** %S Insert the first element of a SrcList
-+**
-+** zFormat and any string tokens that follow it are assumed to be
-+** encoded in UTF-8.
-+**
-+** To clear the most recent error for sqlite handle "db", sqlite3Error
-+** should be called with err_code set to SQLITE_OK and zFormat set
-+** to NULL.
- */
--static int posixOpen(const char *zFile, int flags, int mode){
-- return open(zFile, flags, mode);
-+SQLITE_PRIVATE void sqlite3Error(sqlite3 *db, int err_code, const char *zFormat, ...){
-+ if( db && (db->pErr || (db->pErr = sqlite3ValueNew(db))!=0) ){
-+ db->errCode = err_code;
-+ if( zFormat ){
-+ char *z;
-+ va_list ap;
-+ va_start(ap, zFormat);
-+ z = sqlite3VMPrintf(db, zFormat, ap);
-+ va_end(ap);
-+ sqlite3ValueSetStr(db->pErr, -1, z, SQLITE_UTF8, SQLITE_DYNAMIC);
-+ }else{
-+ sqlite3ValueSetStr(db->pErr, 0, 0, SQLITE_UTF8, SQLITE_STATIC);
-+ }
-+ }
- }
-
- /*
--** On some systems, calls to fchown() will trigger a message in a security
--** log if they come from non-root processes. So avoid calling fchown() if
--** we are not running as root.
-+** Add an error message to pParse->zErrMsg and increment pParse->nErr.
-+** The following formatting characters are allowed:
-+**
-+** %s Insert a string
-+** %z A string that should be freed after use
-+** %d Insert an integer
-+** %T Insert a token
-+** %S Insert the first element of a SrcList
-+**
-+** This function should be used to report any error that occurs whilst
-+** compiling an SQL statement (i.e. within sqlite3_prepare()). The
-+** last thing the sqlite3_prepare() function does is copy the error
-+** stored by this function into the database handle using sqlite3Error().
-+** Function sqlite3Error() should be used during statement execution
-+** (sqlite3_step() etc.).
- */
--static int posixFchown(int fd, uid_t uid, gid_t gid){
-- return geteuid() ? 0 : fchown(fd,uid,gid);
-+SQLITE_PRIVATE void sqlite3ErrorMsg(Parse *pParse, const char *zFormat, ...){
-+ char *zMsg;
-+ va_list ap;
-+ sqlite3 *db = pParse->db;
-+ va_start(ap, zFormat);
-+ zMsg = sqlite3VMPrintf(db, zFormat, ap);
-+ va_end(ap);
-+ if( db->suppressErr ){
-+ sqlite3DbFree(db, zMsg);
-+ }else{
-+ pParse->nErr++;
-+ sqlite3DbFree(db, pParse->zErrMsg);
-+ pParse->zErrMsg = zMsg;
-+ pParse->rc = SQLITE_ERROR;
-+ }
- }
-
--/* Forward reference */
--static int openDirectory(const char*, int*);
--
- /*
--** Many system calls are accessed through pointer-to-functions so that
--** they may be overridden at runtime to facilitate fault injection during
--** testing and sandboxing. The following array holds the names and pointers
--** to all overrideable system calls.
-+** Convert an SQL-style quoted string into a normal string by removing
-+** the quote characters. The conversion is done in-place. If the
-+** input does not begin with a quote character, then this routine
-+** is a no-op.
-+**
-+** The input string must be zero-terminated. A new zero-terminator
-+** is added to the dequoted string.
-+**
-+** The return value is -1 if no dequoting occurs or the length of the
-+** dequoted string, exclusive of the zero terminator, if dequoting does
-+** occur.
-+**
-+** 2002-Feb-14: This routine is extended to remove MS-Access style
-+** brackets from around identifers. For example: "[a-b-c]" becomes
-+** "a-b-c".
- */
--static struct unix_syscall {
-- const char *zName; /* Name of the system call */
-- sqlite3_syscall_ptr pCurrent; /* Current value of the system call */
-- sqlite3_syscall_ptr pDefault; /* Default value */
--} aSyscall[] = {
-- { "open", (sqlite3_syscall_ptr)posixOpen, 0 },
--#define osOpen ((int(*)(const char*,int,int))aSyscall[0].pCurrent)
--
-- { "close", (sqlite3_syscall_ptr)close, 0 },
--#define osClose ((int(*)(int))aSyscall[1].pCurrent)
--
-- { "access", (sqlite3_syscall_ptr)access, 0 },
--#define osAccess ((int(*)(const char*,int))aSyscall[2].pCurrent)
--
-- { "getcwd", (sqlite3_syscall_ptr)getcwd, 0 },
--#define osGetcwd ((char*(*)(char*,size_t))aSyscall[3].pCurrent)
-+SQLITE_PRIVATE int sqlite3Dequote(char *z){
-+ char quote;
-+ int i, j;
-+ if( z==0 ) return -1;
-+ quote = z[0];
-+ switch( quote ){
-+ case '\'': break;
-+ case '"': break;
-+ case '`': break; /* For MySQL compatibility */
-+ case '[': quote = ']'; break; /* For MS SqlServer compatibility */
-+ default: return -1;
-+ }
-+ for(i=1, j=0; ALWAYS(z[i]); i++){
-+ if( z[i]==quote ){
-+ if( z[i+1]==quote ){
-+ z[j++] = quote;
-+ i++;
-+ }else{
-+ break;
-+ }
-+ }else{
-+ z[j++] = z[i];
-+ }
-+ }
-+ z[j] = 0;
-+ return j;
-+}
-
-- { "stat", (sqlite3_syscall_ptr)stat, 0 },
--#define osStat ((int(*)(const char*,struct stat*))aSyscall[4].pCurrent)
-+/* Convenient short-hand */
-+#define UpperToLower sqlite3UpperToLower
-
- /*
--** The DJGPP compiler environment looks mostly like Unix, but it
--** lacks the fcntl() system call. So redefine fcntl() to be something
--** that always succeeds. This means that locking does not occur under
--** DJGPP. But it is DOS - what did you expect?
-+** Some systems have stricmp(). Others have strcasecmp(). Because
-+** there is no consistency, we will define our own.
-+**
-+** IMPLEMENTATION-OF: R-30243-02494 The sqlite3_stricmp() and
-+** sqlite3_strnicmp() APIs allow applications and extensions to compare
-+** the contents of two buffers containing UTF-8 strings in a
-+** case-independent fashion, using the same definition of "case
-+** independence" that SQLite uses internally when comparing identifiers.
- */
--#ifdef __DJGPP__
-- { "fstat", 0, 0 },
--#define osFstat(a,b,c) 0
--#else
-- { "fstat", (sqlite3_syscall_ptr)fstat, 0 },
--#define osFstat ((int(*)(int,struct stat*))aSyscall[5].pCurrent)
--#endif
--
-- { "ftruncate", (sqlite3_syscall_ptr)ftruncate, 0 },
--#define osFtruncate ((int(*)(int,off_t))aSyscall[6].pCurrent)
--
-- { "fcntl", (sqlite3_syscall_ptr)fcntl, 0 },
--#define osFcntl ((int(*)(int,int,...))aSyscall[7].pCurrent)
--
-- { "read", (sqlite3_syscall_ptr)read, 0 },
--#define osRead ((ssize_t(*)(int,void*,size_t))aSyscall[8].pCurrent)
--
--#if defined(USE_PREAD) || SQLITE_ENABLE_LOCKING_STYLE
-- { "pread", (sqlite3_syscall_ptr)pread, 0 },
--#else
-- { "pread", (sqlite3_syscall_ptr)0, 0 },
--#endif
--#define osPread ((ssize_t(*)(int,void*,size_t,off_t))aSyscall[9].pCurrent)
--
--#if defined(USE_PREAD64)
-- { "pread64", (sqlite3_syscall_ptr)pread64, 0 },
--#else
-- { "pread64", (sqlite3_syscall_ptr)0, 0 },
--#endif
--#define osPread64 ((ssize_t(*)(int,void*,size_t,off_t))aSyscall[10].pCurrent)
--
-- { "write", (sqlite3_syscall_ptr)write, 0 },
--#define osWrite ((ssize_t(*)(int,const void*,size_t))aSyscall[11].pCurrent)
--
--#if defined(USE_PREAD) || SQLITE_ENABLE_LOCKING_STYLE
-- { "pwrite", (sqlite3_syscall_ptr)pwrite, 0 },
--#else
-- { "pwrite", (sqlite3_syscall_ptr)0, 0 },
--#endif
--#define osPwrite ((ssize_t(*)(int,const void*,size_t,off_t))\
-- aSyscall[12].pCurrent)
--
--#if defined(USE_PREAD64)
-- { "pwrite64", (sqlite3_syscall_ptr)pwrite64, 0 },
--#else
-- { "pwrite64", (sqlite3_syscall_ptr)0, 0 },
--#endif
--#define osPwrite64 ((ssize_t(*)(int,const void*,size_t,off_t))\
-- aSyscall[13].pCurrent)
--
-- { "fchmod", (sqlite3_syscall_ptr)fchmod, 0 },
--#define osFchmod ((int(*)(int,mode_t))aSyscall[14].pCurrent)
--
--#if defined(HAVE_POSIX_FALLOCATE) && HAVE_POSIX_FALLOCATE
-- { "fallocate", (sqlite3_syscall_ptr)posix_fallocate, 0 },
--#else
-- { "fallocate", (sqlite3_syscall_ptr)0, 0 },
--#endif
--#define osFallocate ((int(*)(int,off_t,off_t))aSyscall[15].pCurrent)
--
-- { "unlink", (sqlite3_syscall_ptr)unlink, 0 },
--#define osUnlink ((int(*)(const char*))aSyscall[16].pCurrent)
--
-- { "openDirectory", (sqlite3_syscall_ptr)openDirectory, 0 },
--#define osOpenDirectory ((int(*)(const char*,int*))aSyscall[17].pCurrent)
-+SQLITE_API int sqlite3_stricmp(const char *zLeft, const char *zRight){
-+ register unsigned char *a, *b;
-+ a = (unsigned char *)zLeft;
-+ b = (unsigned char *)zRight;
-+ while( *a!=0 && UpperToLower[*a]==UpperToLower[*b]){ a++; b++; }
-+ return UpperToLower[*a] - UpperToLower[*b];
-+}
-+SQLITE_API int sqlite3_strnicmp(const char *zLeft, const char *zRight, int N){
-+ register unsigned char *a, *b;
-+ a = (unsigned char *)zLeft;
-+ b = (unsigned char *)zRight;
-+ while( N-- > 0 && *a!=0 && UpperToLower[*a]==UpperToLower[*b]){ a++; b++; }
-+ return N<0 ? 0 : UpperToLower[*a] - UpperToLower[*b];
-+}
-
-- { "mkdir", (sqlite3_syscall_ptr)mkdir, 0 },
--#define osMkdir ((int(*)(const char*,mode_t))aSyscall[18].pCurrent)
-+/*
-+** The string z[] is an text representation of a real number.
-+** Convert this string to a double and write it into *pResult.
-+**
-+** The string z[] is length bytes in length (bytes, not characters) and
-+** uses the encoding enc. The string is not necessarily zero-terminated.
-+**
-+** Return TRUE if the result is a valid real number (or integer) and FALSE
-+** if the string is empty or contains extraneous text. Valid numbers
-+** are in one of these formats:
-+**
-+** [+-]digits[E[+-]digits]
-+** [+-]digits.[digits][E[+-]digits]
-+** [+-].digits[E[+-]digits]
-+**
-+** Leading and trailing whitespace is ignored for the purpose of determining
-+** validity.
-+**
-+** If some prefix of the input string is a valid number, this routine
-+** returns FALSE but it still converts the prefix and writes the result
-+** into *pResult.
-+*/
-+SQLITE_PRIVATE int sqlite3AtoF(const char *z, double *pResult, int length, u8 enc){
-+#ifndef SQLITE_OMIT_FLOATING_POINT
-+ int incr;
-+ const char *zEnd = z + length;
-+ /* sign * significand * (10 ^ (esign * exponent)) */
-+ int sign = 1; /* sign of significand */
-+ i64 s = 0; /* significand */
-+ int d = 0; /* adjust exponent for shifting decimal point */
-+ int esign = 1; /* sign of exponent */
-+ int e = 0; /* exponent */
-+ int eValid = 1; /* True exponent is either not used or is well-formed */
-+ double result;
-+ int nDigits = 0;
-+ int nonNum = 0;
-
-- { "rmdir", (sqlite3_syscall_ptr)rmdir, 0 },
--#define osRmdir ((int(*)(const char*))aSyscall[19].pCurrent)
-+ assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE );
-+ *pResult = 0.0; /* Default return value, in case of an error */
-
-- { "fchown", (sqlite3_syscall_ptr)posixFchown, 0 },
--#define osFchown ((int(*)(int,uid_t,gid_t))aSyscall[20].pCurrent)
-+ if( enc==SQLITE_UTF8 ){
-+ incr = 1;
-+ }else{
-+ int i;
-+ incr = 2;
-+ assert( SQLITE_UTF16LE==2 && SQLITE_UTF16BE==3 );
-+ for(i=3-enc; i<length && z[i]==0; i+=2){}
-+ nonNum = i<length;
-+ zEnd = z+i+enc-3;
-+ z += (enc&1);
-+ }
-
-- { "mmap", (sqlite3_syscall_ptr)mmap, 0 },
--#define osMmap ((void*(*)(void*,size_t,int,int,int,off_t))aSyscall[21].pCurrent)
-+ /* skip leading spaces */
-+ while( z<zEnd && sqlite3Isspace(*z) ) z+=incr;
-+ if( z>=zEnd ) return 0;
-
-- { "munmap", (sqlite3_syscall_ptr)munmap, 0 },
--#define osMunmap ((void*(*)(void*,size_t))aSyscall[22].pCurrent)
-+ /* get sign of significand */
-+ if( *z=='-' ){
-+ sign = -1;
-+ z+=incr;
-+ }else if( *z=='+' ){
-+ z+=incr;
-+ }
-
--#if HAVE_MREMAP
-- { "mremap", (sqlite3_syscall_ptr)mremap, 0 },
--#else
-- { "mremap", (sqlite3_syscall_ptr)0, 0 },
--#endif
--#define osMremap ((void*(*)(void*,size_t,size_t,int,...))aSyscall[23].pCurrent)
-+ /* skip leading zeroes */
-+ while( z<zEnd && z[0]=='0' ) z+=incr, nDigits++;
-
--}; /* End of the overrideable system calls */
-+ /* copy max significant digits to significand */
-+ while( z<zEnd && sqlite3Isdigit(*z) && s<((LARGEST_INT64-9)/10) ){
-+ s = s*10 + (*z - '0');
-+ z+=incr, nDigits++;
-+ }
-
--/*
--** This is the xSetSystemCall() method of sqlite3_vfs for all of the
--** "unix" VFSes. Return SQLITE_OK opon successfully updating the
--** system call pointer, or SQLITE_NOTFOUND if there is no configurable
--** system call named zName.
--*/
--static int unixSetSystemCall(
-- sqlite3_vfs *pNotUsed, /* The VFS pointer. Not used */
-- const char *zName, /* Name of system call to override */
-- sqlite3_syscall_ptr pNewFunc /* Pointer to new system call value */
--){
-- unsigned int i;
-- int rc = SQLITE_NOTFOUND;
-+ /* skip non-significant significand digits
-+ ** (increase exponent by d to shift decimal left) */
-+ while( z<zEnd && sqlite3Isdigit(*z) ) z+=incr, nDigits++, d++;
-+ if( z>=zEnd ) goto do_atof_calc;
-
-- UNUSED_PARAMETER(pNotUsed);
-- if( zName==0 ){
-- /* If no zName is given, restore all system calls to their default
-- ** settings and return NULL
-- */
-- rc = SQLITE_OK;
-- for(i=0; i<sizeof(aSyscall)/sizeof(aSyscall[0]); i++){
-- if( aSyscall[i].pDefault ){
-- aSyscall[i].pCurrent = aSyscall[i].pDefault;
-- }
-+ /* if decimal point is present */
-+ if( *z=='.' ){
-+ z+=incr;
-+ /* copy digits from after decimal to significand
-+ ** (decrease exponent by d to shift decimal right) */
-+ while( z<zEnd && sqlite3Isdigit(*z) && s<((LARGEST_INT64-9)/10) ){
-+ s = s*10 + (*z - '0');
-+ z+=incr, nDigits++, d--;
- }
-- }else{
-- /* If zName is specified, operate on only the one system call
-- ** specified.
-- */
-- for(i=0; i<sizeof(aSyscall)/sizeof(aSyscall[0]); i++){
-- if( strcmp(zName, aSyscall[i].zName)==0 ){
-- if( aSyscall[i].pDefault==0 ){
-- aSyscall[i].pDefault = aSyscall[i].pCurrent;
-- }
-- rc = SQLITE_OK;
-- if( pNewFunc==0 ) pNewFunc = aSyscall[i].pDefault;
-- aSyscall[i].pCurrent = pNewFunc;
-- break;
-- }
-+ /* skip non-significant digits */
-+ while( z<zEnd && sqlite3Isdigit(*z) ) z+=incr, nDigits++;
-+ }
-+ if( z>=zEnd ) goto do_atof_calc;
-+
-+ /* if exponent is present */
-+ if( *z=='e' || *z=='E' ){
-+ z+=incr;
-+ eValid = 0;
-+ if( z>=zEnd ) goto do_atof_calc;
-+ /* get sign of exponent */
-+ if( *z=='-' ){
-+ esign = -1;
-+ z+=incr;
-+ }else if( *z=='+' ){
-+ z+=incr;
-+ }
-+ /* copy digits to exponent */
-+ while( z<zEnd && sqlite3Isdigit(*z) ){
-+ e = e<10000 ? (e*10 + (*z - '0')) : 10000;
-+ z+=incr;
-+ eValid = 1;
- }
- }
-- return rc;
--}
--
--/*
--** Return the value of a system call. Return NULL if zName is not a
--** recognized system call name. NULL is also returned if the system call
--** is currently undefined.
--*/
--static sqlite3_syscall_ptr unixGetSystemCall(
-- sqlite3_vfs *pNotUsed,
-- const char *zName
--){
-- unsigned int i;
-
-- UNUSED_PARAMETER(pNotUsed);
-- for(i=0; i<sizeof(aSyscall)/sizeof(aSyscall[0]); i++){
-- if( strcmp(zName, aSyscall[i].zName)==0 ) return aSyscall[i].pCurrent;
-+ /* skip trailing spaces */
-+ if( nDigits && eValid ){
-+ while( z<zEnd && sqlite3Isspace(*z) ) z+=incr;
- }
-- return 0;
--}
-
--/*
--** Return the name of the first system call after zName. If zName==NULL
--** then return the name of the first system call. Return NULL if zName
--** is the last system call or if zName is not the name of a valid
--** system call.
--*/
--static const char *unixNextSystemCall(sqlite3_vfs *p, const char *zName){
-- int i = -1;
-+do_atof_calc:
-+ /* adjust exponent by d, and update sign */
-+ e = (e*esign) + d;
-+ if( e<0 ) {
-+ esign = -1;
-+ e *= -1;
-+ } else {
-+ esign = 1;
-+ }
-
-- UNUSED_PARAMETER(p);
-- if( zName ){
-- for(i=0; i<ArraySize(aSyscall)-1; i++){
-- if( strcmp(zName, aSyscall[i].zName)==0 ) break;
-+ /* if 0 significand */
-+ if( !s ) {
-+ /* In the IEEE 754 standard, zero is signed.
-+ ** Add the sign if we've seen at least one digit */
-+ result = (sign<0 && nDigits) ? -(double)0 : (double)0;
-+ } else {
-+ /* attempt to reduce exponent */
-+ if( esign>0 ){
-+ while( s<(LARGEST_INT64/10) && e>0 ) e--,s*=10;
-+ }else{
-+ while( !(s%10) && e>0 ) e--,s/=10;
- }
-- }
-- for(i++; i<ArraySize(aSyscall); i++){
-- if( aSyscall[i].pCurrent!=0 ) return aSyscall[i].zName;
-- }
-- return 0;
--}
-
--/*
--** Invoke open(). Do so multiple times, until it either succeeds or
--** fails for some reason other than EINTR.
--**
--** If the file creation mode "m" is 0 then set it to the default for
--** SQLite. The default is SQLITE_DEFAULT_FILE_PERMISSIONS (normally
--** 0644) as modified by the system umask. If m is not 0, then
--** make the file creation mode be exactly m ignoring the umask.
--**
--** The m parameter will be non-zero only when creating -wal, -journal,
--** and -shm files. We want those files to have *exactly* the same
--** permissions as their original database, unadulterated by the umask.
--** In that way, if a database file is -rw-rw-rw or -rw-rw-r-, and a
--** transaction crashes and leaves behind hot journals, then any
--** process that is able to write to the database will also be able to
--** recover the hot journals.
--*/
--static int robust_open(const char *z, int f, mode_t m){
-- int fd;
-- mode_t m2 = m ? m : SQLITE_DEFAULT_FILE_PERMISSIONS;
-- do{
--#if defined(O_CLOEXEC)
-- fd = osOpen(z,f|O_CLOEXEC,m2);
--#else
-- fd = osOpen(z,f,m2);
--#endif
-- }while( fd<0 && errno==EINTR );
-- if( fd>=0 ){
-- if( m!=0 ){
-- struct stat statbuf;
-- if( osFstat(fd, &statbuf)==0
-- && statbuf.st_size==0
-- && (statbuf.st_mode&0777)!=m
-- ){
-- osFchmod(fd, m);
-+ /* adjust the sign of significand */
-+ s = sign<0 ? -s : s;
-+
-+ /* if exponent, scale significand as appropriate
-+ ** and store in result. */
-+ if( e ){
-+ LONGDOUBLE_TYPE scale = 1.0;
-+ /* attempt to handle extremely small/large numbers better */
-+ if( e>307 && e<342 ){
-+ while( e%308 ) { scale *= 1.0e+1; e -= 1; }
-+ if( esign<0 ){
-+ result = s / scale;
-+ result /= 1.0e+308;
-+ }else{
-+ result = s * scale;
-+ result *= 1.0e+308;
-+ }
-+ }else if( e>=342 ){
-+ if( esign<0 ){
-+ result = 0.0*s;
-+ }else{
-+ result = 1e308*1e308*s; /* Infinity */
-+ }
-+ }else{
-+ /* 1.0e+22 is the largest power of 10 than can be
-+ ** represented exactly. */
-+ while( e%22 ) { scale *= 1.0e+1; e -= 1; }
-+ while( e>0 ) { scale *= 1.0e+22; e -= 22; }
-+ if( esign<0 ){
-+ result = s / scale;
-+ }else{
-+ result = s * scale;
-+ }
- }
-+ } else {
-+ result = (double)s;
- }
--#if defined(FD_CLOEXEC) && (!defined(O_CLOEXEC) || O_CLOEXEC==0)
-- osFcntl(fd, F_SETFD, osFcntl(fd, F_GETFD, 0) | FD_CLOEXEC);
--#endif
- }
-- return fd;
-+
-+ /* store the result */
-+ *pResult = result;
-+
-+ /* return true if number and no extra non-whitespace chracters after */
-+ return z>=zEnd && nDigits>0 && eValid && nonNum==0;
-+#else
-+ return !sqlite3Atoi64(z, pResult, length, enc);
-+#endif /* SQLITE_OMIT_FLOATING_POINT */
- }
-
- /*
--** Helper functions to obtain and relinquish the global mutex. The
--** global mutex is used to protect the unixInodeInfo and
--** vxworksFileId objects used by this file, all of which may be
--** shared by multiple threads.
-+** Compare the 19-character string zNum against the text representation
-+** value 2^63: 9223372036854775808. Return negative, zero, or positive
-+** if zNum is less than, equal to, or greater than the string.
-+** Note that zNum must contain exactly 19 characters.
- **
--** Function unixMutexHeld() is used to assert() that the global mutex
--** is held when required. This function is only used as part of assert()
--** statements. e.g.
-+** Unlike memcmp() this routine is guaranteed to return the difference
-+** in the values of the last digit if the only difference is in the
-+** last digit. So, for example,
- **
--** unixEnterMutex()
--** assert( unixMutexHeld() );
--** unixEnterLeave()
-+** compare2pow63("9223372036854775800", 1)
-+**
-+** will return -8.
- */
--static void unixEnterMutex(void){
-- sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
--}
--static void unixLeaveMutex(void){
-- sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
--}
--#ifdef SQLITE_DEBUG
--static int unixMutexHeld(void) {
-- return sqlite3_mutex_held(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
-+static int compare2pow63(const char *zNum, int incr){
-+ int c = 0;
-+ int i;
-+ /* 012345678901234567 */
-+ const char *pow63 = "922337203685477580";
-+ for(i=0; c==0 && i<18; i++){
-+ c = (zNum[i*incr]-pow63[i])*10;
-+ }
-+ if( c==0 ){
-+ c = zNum[18*incr] - '8';
-+ testcase( c==(-1) );
-+ testcase( c==0 );
-+ testcase( c==(+1) );
-+ }
-+ return c;
- }
--#endif
-
-
--#if defined(SQLITE_TEST) && defined(SQLITE_DEBUG)
- /*
--** Helper function for printing out trace information from debugging
--** binaries. This returns the string represetation of the supplied
--** integer lock-type.
-+** Convert zNum to a 64-bit signed integer.
-+**
-+** If the zNum value is representable as a 64-bit twos-complement
-+** integer, then write that value into *pNum and return 0.
-+**
-+** If zNum is exactly 9223372036854665808, return 2. This special
-+** case is broken out because while 9223372036854665808 cannot be a
-+** signed 64-bit integer, its negative -9223372036854665808 can be.
-+**
-+** If zNum is too big for a 64-bit integer and is not
-+** 9223372036854665808 or if zNum contains any non-numeric text,
-+** then return 1.
-+**
-+** length is the number of bytes in the string (bytes, not characters).
-+** The string is not necessarily zero-terminated. The encoding is
-+** given by enc.
- */
--static const char *azFileLock(int eFileLock){
-- switch( eFileLock ){
-- case NO_LOCK: return "NONE";
-- case SHARED_LOCK: return "SHARED";
-- case RESERVED_LOCK: return "RESERVED";
-- case PENDING_LOCK: return "PENDING";
-- case EXCLUSIVE_LOCK: return "EXCLUSIVE";
-+SQLITE_PRIVATE int sqlite3Atoi64(const char *zNum, i64 *pNum, int length, u8 enc){
-+ int incr;
-+ u64 u = 0;
-+ int neg = 0; /* assume positive */
-+ int i;
-+ int c = 0;
-+ int nonNum = 0;
-+ const char *zStart;
-+ const char *zEnd = zNum + length;
-+ assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE );
-+ if( enc==SQLITE_UTF8 ){
-+ incr = 1;
-+ }else{
-+ incr = 2;
-+ assert( SQLITE_UTF16LE==2 && SQLITE_UTF16BE==3 );
-+ for(i=3-enc; i<length && zNum[i]==0; i+=2){}
-+ nonNum = i<length;
-+ zEnd = zNum+i+enc-3;
-+ zNum += (enc&1);
-+ }
-+ while( zNum<zEnd && sqlite3Isspace(*zNum) ) zNum+=incr;
-+ if( zNum<zEnd ){
-+ if( *zNum=='-' ){
-+ neg = 1;
-+ zNum+=incr;
-+ }else if( *zNum=='+' ){
-+ zNum+=incr;
-+ }
-+ }
-+ zStart = zNum;
-+ while( zNum<zEnd && zNum[0]=='0' ){ zNum+=incr; } /* Skip leading zeros. */
-+ for(i=0; &zNum[i]<zEnd && (c=zNum[i])>='0' && c<='9'; i+=incr){
-+ u = u*10 + c - '0';
-+ }
-+ if( u>LARGEST_INT64 ){
-+ *pNum = SMALLEST_INT64;
-+ }else if( neg ){
-+ *pNum = -(i64)u;
-+ }else{
-+ *pNum = (i64)u;
-+ }
-+ testcase( i==18 );
-+ testcase( i==19 );
-+ testcase( i==20 );
-+ if( (c!=0 && &zNum[i]<zEnd) || (i==0 && zStart==zNum) || i>19*incr || nonNum ){
-+ /* zNum is empty or contains non-numeric text or is longer
-+ ** than 19 digits (thus guaranteeing that it is too large) */
-+ return 1;
-+ }else if( i<19*incr ){
-+ /* Less than 19 digits, so we know that it fits in 64 bits */
-+ assert( u<=LARGEST_INT64 );
-+ return 0;
-+ }else{
-+ /* zNum is a 19-digit numbers. Compare it against 9223372036854775808. */
-+ c = compare2pow63(zNum, incr);
-+ if( c<0 ){
-+ /* zNum is less than 9223372036854775808 so it fits */
-+ assert( u<=LARGEST_INT64 );
-+ return 0;
-+ }else if( c>0 ){
-+ /* zNum is greater than 9223372036854775808 so it overflows */
-+ return 1;
-+ }else{
-+ /* zNum is exactly 9223372036854775808. Fits if negative. The
-+ ** special case 2 overflow if positive */
-+ assert( u-1==LARGEST_INT64 );
-+ assert( (*pNum)==SMALLEST_INT64 );
-+ return neg ? 0 : 2;
-+ }
- }
-- return "ERROR";
- }
--#endif
-
--#ifdef SQLITE_LOCK_TRACE
- /*
--** Print out information about all locking operations.
-+** If zNum represents an integer that will fit in 32-bits, then set
-+** *pValue to that integer and return true. Otherwise return false.
- **
--** This routine is used for troubleshooting locks on multithreaded
--** platforms. Enable by compiling with the -DSQLITE_LOCK_TRACE
--** command-line option on the compiler. This code is normally
--** turned off.
-+** Any non-numeric characters that following zNum are ignored.
-+** This is different from sqlite3Atoi64() which requires the
-+** input number to be zero-terminated.
- */
--static int lockTrace(int fd, int op, struct flock *p){
-- char *zOpName, *zType;
-- int s;
-- int savedErrno;
-- if( op==F_GETLK ){
-- zOpName = "GETLK";
-- }else if( op==F_SETLK ){
-- zOpName = "SETLK";
-- }else{
-- s = osFcntl(fd, op, p);
-- sqlite3DebugPrintf("fcntl unknown %d %d %d\n", fd, op, s);
-- return s;
-+SQLITE_PRIVATE int sqlite3GetInt32(const char *zNum, int *pValue){
-+ sqlite_int64 v = 0;
-+ int i, c;
-+ int neg = 0;
-+ if( zNum[0]=='-' ){
-+ neg = 1;
-+ zNum++;
-+ }else if( zNum[0]=='+' ){
-+ zNum++;
- }
-- if( p->l_type==F_RDLCK ){
-- zType = "RDLCK";
-- }else if( p->l_type==F_WRLCK ){
-- zType = "WRLCK";
-- }else if( p->l_type==F_UNLCK ){
-- zType = "UNLCK";
-- }else{
-- assert( 0 );
-+ while( zNum[0]=='0' ) zNum++;
-+ for(i=0; i<11 && (c = zNum[i] - '0')>=0 && c<=9; i++){
-+ v = v*10 + c;
- }
-- assert( p->l_whence==SEEK_SET );
-- s = osFcntl(fd, op, p);
-- savedErrno = errno;
-- sqlite3DebugPrintf("fcntl %d %d %s %s %d %d %d %d\n",
-- threadid, fd, zOpName, zType, (int)p->l_start, (int)p->l_len,
-- (int)p->l_pid, s);
-- if( s==(-1) && op==F_SETLK && (p->l_type==F_RDLCK || p->l_type==F_WRLCK) ){
-- struct flock l2;
-- l2 = *p;
-- osFcntl(fd, F_GETLK, &l2);
-- if( l2.l_type==F_RDLCK ){
-- zType = "RDLCK";
-- }else if( l2.l_type==F_WRLCK ){
-- zType = "WRLCK";
-- }else if( l2.l_type==F_UNLCK ){
-- zType = "UNLCK";
-- }else{
-- assert( 0 );
-- }
-- sqlite3DebugPrintf("fcntl-failure-reason: %s %d %d %d\n",
-- zType, (int)l2.l_start, (int)l2.l_len, (int)l2.l_pid);
-+
-+ /* The longest decimal representation of a 32 bit integer is 10 digits:
-+ **
-+ ** 1234567890
-+ ** 2^31 -> 2147483648
-+ */
-+ testcase( i==10 );
-+ if( i>10 ){
-+ return 0;
- }
-- errno = savedErrno;
-- return s;
-+ testcase( v-neg==2147483647 );
-+ if( v-neg>2147483647 ){
-+ return 0;
-+ }
-+ if( neg ){
-+ v = -v;
-+ }
-+ *pValue = (int)v;
-+ return 1;
- }
--#undef osFcntl
--#define osFcntl lockTrace
--#endif /* SQLITE_LOCK_TRACE */
-
- /*
--** Retry ftruncate() calls that fail due to EINTR
-+** Return a 32-bit integer value extracted from a string. If the
-+** string is not an integer, just return 0.
- */
--static int robust_ftruncate(int h, sqlite3_int64 sz){
-- int rc;
-- do{ rc = osFtruncate(h,sz); }while( rc<0 && errno==EINTR );
-- return rc;
-+SQLITE_PRIVATE int sqlite3Atoi(const char *z){
-+ int x = 0;
-+ if( z ) sqlite3GetInt32(z, &x);
-+ return x;
- }
-
- /*
--** This routine translates a standard POSIX errno code into something
--** useful to the clients of the sqlite3 functions. Specifically, it is
--** intended to translate a variety of "try again" errors into SQLITE_BUSY
--** and a variety of "please close the file descriptor NOW" errors into
--** SQLITE_IOERR
--**
--** Errors during initialization of locks, or file system support for locks,
--** should handle ENOLCK, ENOTSUP, EOPNOTSUPP separately.
-+** The variable-length integer encoding is as follows:
-+**
-+** KEY:
-+** A = 0xxxxxxx 7 bits of data and one flag bit
-+** B = 1xxxxxxx 7 bits of data and one flag bit
-+** C = xxxxxxxx 8 bits of data
-+**
-+** 7 bits - A
-+** 14 bits - BA
-+** 21 bits - BBA
-+** 28 bits - BBBA
-+** 35 bits - BBBBA
-+** 42 bits - BBBBBA
-+** 49 bits - BBBBBBA
-+** 56 bits - BBBBBBBA
-+** 64 bits - BBBBBBBBC
- */
--static int sqliteErrorFromPosixError(int posixError, int sqliteIOErr) {
-- switch (posixError) {
--#if 0
-- /* At one point this code was not commented out. In theory, this branch
-- ** should never be hit, as this function should only be called after
-- ** a locking-related function (i.e. fcntl()) has returned non-zero with
-- ** the value of errno as the first argument. Since a system call has failed,
-- ** errno should be non-zero.
-- **
-- ** Despite this, if errno really is zero, we still don't want to return
-- ** SQLITE_OK. The system call failed, and *some* SQLite error should be
-- ** propagated back to the caller. Commenting this branch out means errno==0
-- ** will be handled by the "default:" case below.
-- */
-- case 0:
-- return SQLITE_OK;
--#endif
-
-- case EAGAIN:
-- case ETIMEDOUT:
-- case EBUSY:
-- case EINTR:
-- case ENOLCK:
-- /* random NFS retry error, unless during file system support
-- * introspection, in which it actually means what it says */
-- return SQLITE_BUSY;
--
-- case EACCES:
-- /* EACCES is like EAGAIN during locking operations, but not any other time*/
-- if( (sqliteIOErr == SQLITE_IOERR_LOCK) ||
-- (sqliteIOErr == SQLITE_IOERR_UNLOCK) ||
-- (sqliteIOErr == SQLITE_IOERR_RDLOCK) ||
-- (sqliteIOErr == SQLITE_IOERR_CHECKRESERVEDLOCK) ){
-- return SQLITE_BUSY;
-+/*
-+** Write a 64-bit variable-length integer to memory starting at p[0].
-+** The length of data write will be between 1 and 9 bytes. The number
-+** of bytes written is returned.
-+**
-+** A variable-length integer consists of the lower 7 bits of each byte
-+** for all bytes that have the 8th bit set and one byte with the 8th
-+** bit clear. Except, if we get to the 9th byte, it stores the full
-+** 8 bits and is the last byte.
-+*/
-+SQLITE_PRIVATE int sqlite3PutVarint(unsigned char *p, u64 v){
-+ int i, j, n;
-+ u8 buf[10];
-+ if( v & (((u64)0xff000000)<<32) ){
-+ p[8] = (u8)v;
-+ v >>= 8;
-+ for(i=7; i>=0; i--){
-+ p[i] = (u8)((v & 0x7f) | 0x80);
-+ v >>= 7;
- }
-- /* else fall through */
-- case EPERM:
-- return SQLITE_PERM;
--
-- /* EDEADLK is only possible if a call to fcntl(F_SETLKW) is made. And
-- ** this module never makes such a call. And the code in SQLite itself
-- ** asserts that SQLITE_IOERR_BLOCKED is never returned. For these reasons
-- ** this case is also commented out. If the system does set errno to EDEADLK,
-- ** the default SQLITE_IOERR_XXX code will be returned. */
--#if 0
-- case EDEADLK:
-- return SQLITE_IOERR_BLOCKED;
--#endif
--
--#if EOPNOTSUPP!=ENOTSUP
-- case EOPNOTSUPP:
-- /* something went terribly awry, unless during file system support
-- * introspection, in which it actually means what it says */
--#endif
--#ifdef ENOTSUP
-- case ENOTSUP:
-- /* invalid fd, unless during file system support introspection, in which
-- * it actually means what it says */
--#endif
-- case EIO:
-- case EBADF:
-- case EINVAL:
-- case ENOTCONN:
-- case ENODEV:
-- case ENXIO:
-- case ENOENT:
--#ifdef ESTALE /* ESTALE is not defined on Interix systems */
-- case ESTALE:
--#endif
-- case ENOSYS:
-- /* these should force the client to close the file and reconnect */
--
-- default:
-- return sqliteIOErr;
-+ return 9;
-+ }
-+ n = 0;
-+ do{
-+ buf[n++] = (u8)((v & 0x7f) | 0x80);
-+ v >>= 7;
-+ }while( v!=0 );
-+ buf[0] &= 0x7f;
-+ assert( n<=9 );
-+ for(i=0, j=n-1; j>=0; j--, i++){
-+ p[i] = buf[j];
- }
-+ return n;
- }
-
-+/*
-+** This routine is a faster version of sqlite3PutVarint() that only
-+** works for 32-bit positive integers and which is optimized for
-+** the common case of small integers. A MACRO version, putVarint32,
-+** is provided which inlines the single-byte case. All code should use
-+** the MACRO version as this function assumes the single-byte case has
-+** already been handled.
-+*/
-+SQLITE_PRIVATE int sqlite3PutVarint32(unsigned char *p, u32 v){
-+#ifndef putVarint32
-+ if( (v & ~0x7f)==0 ){
-+ p[0] = v;
-+ return 1;
-+ }
-+#endif
-+ if( (v & ~0x3fff)==0 ){
-+ p[0] = (u8)((v>>7) | 0x80);
-+ p[1] = (u8)(v & 0x7f);
-+ return 2;
-+ }
-+ return sqlite3PutVarint(p, v);
-+}
-
--/******************************************************************************
--****************** Begin Unique File ID Utility Used By VxWorks ***************
--**
--** On most versions of unix, we can get a unique ID for a file by concatenating
--** the device number and the inode number. But this does not work on VxWorks.
--** On VxWorks, a unique file id must be based on the canonical filename.
-+/*
-+** Bitmasks used by sqlite3GetVarint(). These precomputed constants
-+** are defined here rather than simply putting the constant expressions
-+** inline in order to work around bugs in the RVT compiler.
- **
--** A pointer to an instance of the following structure can be used as a
--** unique file ID in VxWorks. Each instance of this structure contains
--** a copy of the canonical filename. There is also a reference count.
--** The structure is reclaimed when the number of pointers to it drops to
--** zero.
-+** SLOT_2_0 A mask for (0x7f<<14) | 0x7f
- **
--** There are never very many files open at one time and lookups are not
--** a performance-critical path, so it is sufficient to put these
--** structures on a linked list.
-+** SLOT_4_2_0 A mask for (0x7f<<28) | SLOT_2_0
- */
--struct vxworksFileId {
-- struct vxworksFileId *pNext; /* Next in a list of them all */
-- int nRef; /* Number of references to this one */
-- int nName; /* Length of the zCanonicalName[] string */
-- char *zCanonicalName; /* Canonical filename */
--};
-+#define SLOT_2_0 0x001fc07f
-+#define SLOT_4_2_0 0xf01fc07f
-
--#if OS_VXWORKS
--/*
--** All unique filenames are held on a linked list headed by this
--** variable:
--*/
--static struct vxworksFileId *vxworksFileList = 0;
-
- /*
--** Simplify a filename into its canonical form
--** by making the following changes:
--**
--** * removing any trailing and duplicate /
--** * convert /./ into just /
--** * convert /A/../ where A is any simple name into just /
--**
--** Changes are made in-place. Return the new name length.
--**
--** The original filename is in z[0..n-1]. Return the number of
--** characters in the simplified name.
-+** Read a 64-bit variable-length integer from memory starting at p[0].
-+** Return the number of bytes read. The value is stored in *v.
- */
--static int vxworksSimplifyName(char *z, int n){
-- int i, j;
-- while( n>1 && z[n-1]=='/' ){ n--; }
-- for(i=j=0; i<n; i++){
-- if( z[i]=='/' ){
-- if( z[i+1]=='/' ) continue;
-- if( z[i+1]=='.' && i+2<n && z[i+2]=='/' ){
-- i += 1;
-- continue;
-- }
-- if( z[i+1]=='.' && i+3<n && z[i+2]=='.' && z[i+3]=='/' ){
-- while( j>0 && z[j-1]!='/' ){ j--; }
-- if( j>0 ){ j--; }
-- i += 2;
-- continue;
-- }
-- }
-- z[j++] = z[i];
-+SQLITE_PRIVATE u8 sqlite3GetVarint(const unsigned char *p, u64 *v){
-+ u32 a,b,s;
-+
-+ a = *p;
-+ /* a: p0 (unmasked) */
-+ if (!(a&0x80))
-+ {
-+ *v = a;
-+ return 1;
- }
-- z[j] = 0;
-- return j;
-+
-+ p++;
-+ b = *p;
-+ /* b: p1 (unmasked) */
-+ if (!(b&0x80))
-+ {
-+ a &= 0x7f;
-+ a = a<<7;
-+ a |= b;
-+ *v = a;
-+ return 2;
-+ }
-+
-+ /* Verify that constants are precomputed correctly */
-+ assert( SLOT_2_0 == ((0x7f<<14) | (0x7f)) );
-+ assert( SLOT_4_2_0 == ((0xfU<<28) | (0x7f<<14) | (0x7f)) );
-+
-+ p++;
-+ a = a<<14;
-+ a |= *p;
-+ /* a: p0<<14 | p2 (unmasked) */
-+ if (!(a&0x80))
-+ {
-+ a &= SLOT_2_0;
-+ b &= 0x7f;
-+ b = b<<7;
-+ a |= b;
-+ *v = a;
-+ return 3;
-+ }
-+
-+ /* CSE1 from below */
-+ a &= SLOT_2_0;
-+ p++;
-+ b = b<<14;
-+ b |= *p;
-+ /* b: p1<<14 | p3 (unmasked) */
-+ if (!(b&0x80))
-+ {
-+ b &= SLOT_2_0;
-+ /* moved CSE1 up */
-+ /* a &= (0x7f<<14)|(0x7f); */
-+ a = a<<7;
-+ a |= b;
-+ *v = a;
-+ return 4;
-+ }
-+
-+ /* a: p0<<14 | p2 (masked) */
-+ /* b: p1<<14 | p3 (unmasked) */
-+ /* 1:save off p0<<21 | p1<<14 | p2<<7 | p3 (masked) */
-+ /* moved CSE1 up */
-+ /* a &= (0x7f<<14)|(0x7f); */
-+ b &= SLOT_2_0;
-+ s = a;
-+ /* s: p0<<14 | p2 (masked) */
-+
-+ p++;
-+ a = a<<14;
-+ a |= *p;
-+ /* a: p0<<28 | p2<<14 | p4 (unmasked) */
-+ if (!(a&0x80))
-+ {
-+ /* we can skip these cause they were (effectively) done above in calc'ing s */
-+ /* a &= (0x7f<<28)|(0x7f<<14)|(0x7f); */
-+ /* b &= (0x7f<<14)|(0x7f); */
-+ b = b<<7;
-+ a |= b;
-+ s = s>>18;
-+ *v = ((u64)s)<<32 | a;
-+ return 5;
-+ }
-+
-+ /* 2:save off p0<<21 | p1<<14 | p2<<7 | p3 (masked) */
-+ s = s<<7;
-+ s |= b;
-+ /* s: p0<<21 | p1<<14 | p2<<7 | p3 (masked) */
-+
-+ p++;
-+ b = b<<14;
-+ b |= *p;
-+ /* b: p1<<28 | p3<<14 | p5 (unmasked) */
-+ if (!(b&0x80))
-+ {
-+ /* we can skip this cause it was (effectively) done above in calc'ing s */
-+ /* b &= (0x7f<<28)|(0x7f<<14)|(0x7f); */
-+ a &= SLOT_2_0;
-+ a = a<<7;
-+ a |= b;
-+ s = s>>18;
-+ *v = ((u64)s)<<32 | a;
-+ return 6;
-+ }
-+
-+ p++;
-+ a = a<<14;
-+ a |= *p;
-+ /* a: p2<<28 | p4<<14 | p6 (unmasked) */
-+ if (!(a&0x80))
-+ {
-+ a &= SLOT_4_2_0;
-+ b &= SLOT_2_0;
-+ b = b<<7;
-+ a |= b;
-+ s = s>>11;
-+ *v = ((u64)s)<<32 | a;
-+ return 7;
-+ }
-+
-+ /* CSE2 from below */
-+ a &= SLOT_2_0;
-+ p++;
-+ b = b<<14;
-+ b |= *p;
-+ /* b: p3<<28 | p5<<14 | p7 (unmasked) */
-+ if (!(b&0x80))
-+ {
-+ b &= SLOT_4_2_0;
-+ /* moved CSE2 up */
-+ /* a &= (0x7f<<14)|(0x7f); */
-+ a = a<<7;
-+ a |= b;
-+ s = s>>4;
-+ *v = ((u64)s)<<32 | a;
-+ return 8;
-+ }
-+
-+ p++;
-+ a = a<<15;
-+ a |= *p;
-+ /* a: p4<<29 | p6<<15 | p8 (unmasked) */
-+
-+ /* moved CSE2 up */
-+ /* a &= (0x7f<<29)|(0x7f<<15)|(0xff); */
-+ b &= SLOT_2_0;
-+ b = b<<8;
-+ a |= b;
-+
-+ s = s<<4;
-+ b = p[-4];
-+ b &= 0x7f;
-+ b = b>>3;
-+ s |= b;
-+
-+ *v = ((u64)s)<<32 | a;
-+
-+ return 9;
- }
-
- /*
--** Find a unique file ID for the given absolute pathname. Return
--** a pointer to the vxworksFileId object. This pointer is the unique
--** file ID.
-+** Read a 32-bit variable-length integer from memory starting at p[0].
-+** Return the number of bytes read. The value is stored in *v.
- **
--** The nRef field of the vxworksFileId object is incremented before
--** the object is returned. A new vxworksFileId object is created
--** and added to the global list if necessary.
-+** If the varint stored in p[0] is larger than can fit in a 32-bit unsigned
-+** integer, then set *v to 0xffffffff.
- **
--** If a memory allocation error occurs, return NULL.
-+** A MACRO version, getVarint32, is provided which inlines the
-+** single-byte case. All code should use the MACRO version as
-+** this function assumes the single-byte case has already been handled.
- */
--static struct vxworksFileId *vxworksFindFileId(const char *zAbsoluteName){
-- struct vxworksFileId *pNew; /* search key and new file ID */
-- struct vxworksFileId *pCandidate; /* For looping over existing file IDs */
-- int n; /* Length of zAbsoluteName string */
-+SQLITE_PRIVATE u8 sqlite3GetVarint32(const unsigned char *p, u32 *v){
-+ u32 a,b;
-
-- assert( zAbsoluteName[0]=='/' );
-- n = (int)strlen(zAbsoluteName);
-- pNew = sqlite3_malloc( sizeof(*pNew) + (n+1) );
-- if( pNew==0 ) return 0;
-- pNew->zCanonicalName = (char*)&pNew[1];
-- memcpy(pNew->zCanonicalName, zAbsoluteName, n+1);
-- n = vxworksSimplifyName(pNew->zCanonicalName, n);
-+ /* The 1-byte case. Overwhelmingly the most common. Handled inline
-+ ** by the getVarin32() macro */
-+ a = *p;
-+ /* a: p0 (unmasked) */
-+#ifndef getVarint32
-+ if (!(a&0x80))
-+ {
-+ /* Values between 0 and 127 */
-+ *v = a;
-+ return 1;
-+ }
-+#endif
-
-- /* Search for an existing entry that matching the canonical name.
-- ** If found, increment the reference count and return a pointer to
-- ** the existing file ID.
-+ /* The 2-byte case */
-+ p++;
-+ b = *p;
-+ /* b: p1 (unmasked) */
-+ if (!(b&0x80))
-+ {
-+ /* Values between 128 and 16383 */
-+ a &= 0x7f;
-+ a = a<<7;
-+ *v = a | b;
-+ return 2;
-+ }
-+
-+ /* The 3-byte case */
-+ p++;
-+ a = a<<14;
-+ a |= *p;
-+ /* a: p0<<14 | p2 (unmasked) */
-+ if (!(a&0x80))
-+ {
-+ /* Values between 16384 and 2097151 */
-+ a &= (0x7f<<14)|(0x7f);
-+ b &= 0x7f;
-+ b = b<<7;
-+ *v = a | b;
-+ return 3;
-+ }
-+
-+ /* A 32-bit varint is used to store size information in btrees.
-+ ** Objects are rarely larger than 2MiB limit of a 3-byte varint.
-+ ** A 3-byte varint is sufficient, for example, to record the size
-+ ** of a 1048569-byte BLOB or string.
-+ **
-+ ** We only unroll the first 1-, 2-, and 3- byte cases. The very
-+ ** rare larger cases can be handled by the slower 64-bit varint
-+ ** routine.
- */
-- unixEnterMutex();
-- for(pCandidate=vxworksFileList; pCandidate; pCandidate=pCandidate->pNext){
-- if( pCandidate->nName==n
-- && memcmp(pCandidate->zCanonicalName, pNew->zCanonicalName, n)==0
-- ){
-- sqlite3_free(pNew);
-- pCandidate->nRef++;
-- unixLeaveMutex();
-- return pCandidate;
-+#if 1
-+ {
-+ u64 v64;
-+ u8 n;
-+
-+ p -= 2;
-+ n = sqlite3GetVarint(p, &v64);
-+ assert( n>3 && n<=9 );
-+ if( (v64 & SQLITE_MAX_U32)!=v64 ){
-+ *v = 0xffffffff;
-+ }else{
-+ *v = (u32)v64;
- }
-+ return n;
- }
-
-- /* No match was found. We will make a new file ID */
-- pNew->nRef = 1;
-- pNew->nName = n;
-- pNew->pNext = vxworksFileList;
-- vxworksFileList = pNew;
-- unixLeaveMutex();
-- return pNew;
--}
-+#else
-+ /* For following code (kept for historical record only) shows an
-+ ** unrolling for the 3- and 4-byte varint cases. This code is
-+ ** slightly faster, but it is also larger and much harder to test.
-+ */
-+ p++;
-+ b = b<<14;
-+ b |= *p;
-+ /* b: p1<<14 | p3 (unmasked) */
-+ if (!(b&0x80))
-+ {
-+ /* Values between 2097152 and 268435455 */
-+ b &= (0x7f<<14)|(0x7f);
-+ a &= (0x7f<<14)|(0x7f);
-+ a = a<<7;
-+ *v = a | b;
-+ return 4;
-+ }
-
--/*
--** Decrement the reference count on a vxworksFileId object. Free
--** the object when the reference count reaches zero.
--*/
--static void vxworksReleaseFileId(struct vxworksFileId *pId){
-- unixEnterMutex();
-- assert( pId->nRef>0 );
-- pId->nRef--;
-- if( pId->nRef==0 ){
-- struct vxworksFileId **pp;
-- for(pp=&vxworksFileList; *pp && *pp!=pId; pp = &((*pp)->pNext)){}
-- assert( *pp==pId );
-- *pp = pId->pNext;
-- sqlite3_free(pId);
-+ p++;
-+ a = a<<14;
-+ a |= *p;
-+ /* a: p0<<28 | p2<<14 | p4 (unmasked) */
-+ if (!(a&0x80))
-+ {
-+ /* Values between 268435456 and 34359738367 */
-+ a &= SLOT_4_2_0;
-+ b &= SLOT_4_2_0;
-+ b = b<<7;
-+ *v = a | b;
-+ return 5;
- }
-- unixLeaveMutex();
--}
--#endif /* OS_VXWORKS */
--/*************** End of Unique File ID Utility Used By VxWorks ****************
--******************************************************************************/
-
-+ /* We can only reach this point when reading a corrupt database
-+ ** file. In that case we are not in any hurry. Use the (relatively
-+ ** slow) general-purpose sqlite3GetVarint() routine to extract the
-+ ** value. */
-+ {
-+ u64 v64;
-+ u8 n;
-
--/******************************************************************************
--*************************** Posix Advisory Locking ****************************
--**
--** POSIX advisory locks are broken by design. ANSI STD 1003.1 (1996)
--** section 6.5.2.2 lines 483 through 490 specify that when a process
--** sets or clears a lock, that operation overrides any prior locks set
--** by the same process. It does not explicitly say so, but this implies
--** that it overrides locks set by the same process using a different
--** file descriptor. Consider this test case:
--**
--** int fd1 = open("./file1", O_RDWR|O_CREAT, 0644);
--** int fd2 = open("./file2", O_RDWR|O_CREAT, 0644);
--**
--** Suppose ./file1 and ./file2 are really the same file (because
--** one is a hard or symbolic link to the other) then if you set
--** an exclusive lock on fd1, then try to get an exclusive lock
--** on fd2, it works. I would have expected the second lock to
--** fail since there was already a lock on the file due to fd1.
--** But not so. Since both locks came from the same process, the
--** second overrides the first, even though they were on different
--** file descriptors opened on different file names.
--**
--** This means that we cannot use POSIX locks to synchronize file access
--** among competing threads of the same process. POSIX locks will work fine
--** to synchronize access for threads in separate processes, but not
--** threads within the same process.
--**
--** To work around the problem, SQLite has to manage file locks internally
--** on its own. Whenever a new database is opened, we have to find the
--** specific inode of the database file (the inode is determined by the
--** st_dev and st_ino fields of the stat structure that fstat() fills in)
--** and check for locks already existing on that inode. When locks are
--** created or removed, we have to look at our own internal record of the
--** locks to see if another thread has previously set a lock on that same
--** inode.
--**
--** (Aside: The use of inode numbers as unique IDs does not work on VxWorks.
--** For VxWorks, we have to use the alternative unique ID system based on
--** canonical filename and implemented in the previous division.)
--**
--** The sqlite3_file structure for POSIX is no longer just an integer file
--** descriptor. It is now a structure that holds the integer file
--** descriptor and a pointer to a structure that describes the internal
--** locks on the corresponding inode. There is one locking structure
--** per inode, so if the same inode is opened twice, both unixFile structures
--** point to the same locking structure. The locking structure keeps
--** a reference count (so we will know when to delete it) and a "cnt"
--** field that tells us its internal lock status. cnt==0 means the
--** file is unlocked. cnt==-1 means the file has an exclusive lock.
--** cnt>0 means there are cnt shared locks on the file.
--**
--** Any attempt to lock or unlock a file first checks the locking
--** structure. The fcntl() system call is only invoked to set a
--** POSIX lock if the internal lock structure transitions between
--** a locked and an unlocked state.
--**
--** But wait: there are yet more problems with POSIX advisory locks.
--**
--** If you close a file descriptor that points to a file that has locks,
--** all locks on that file that are owned by the current process are
--** released. To work around this problem, each unixInodeInfo object
--** maintains a count of the number of pending locks on tha inode.
--** When an attempt is made to close an unixFile, if there are
--** other unixFile open on the same inode that are holding locks, the call
--** to close() the file descriptor is deferred until all of the locks clear.
--** The unixInodeInfo structure keeps a list of file descriptors that need to
--** be closed and that list is walked (and cleared) when the last lock
--** clears.
--**
--** Yet another problem: LinuxThreads do not play well with posix locks.
--**
--** Many older versions of linux use the LinuxThreads library which is
--** not posix compliant. Under LinuxThreads, a lock created by thread
--** A cannot be modified or overridden by a different thread B.
--** Only thread A can modify the lock. Locking behavior is correct
--** if the appliation uses the newer Native Posix Thread Library (NPTL)
--** on linux - with NPTL a lock created by thread A can override locks
--** in thread B. But there is no way to know at compile-time which
--** threading library is being used. So there is no way to know at
--** compile-time whether or not thread A can override locks on thread B.
--** One has to do a run-time check to discover the behavior of the
--** current process.
--**
--** SQLite used to support LinuxThreads. But support for LinuxThreads
--** was dropped beginning with version 3.7.0. SQLite will still work with
--** LinuxThreads provided that (1) there is no more than one connection
--** per database file in the same process and (2) database connections
--** do not move across threads.
-+ p -= 4;
-+ n = sqlite3GetVarint(p, &v64);
-+ assert( n>5 && n<=9 );
-+ *v = (u32)v64;
-+ return n;
-+ }
-+#endif
-+}
-+
-+/*
-+** Return the number of bytes that will be needed to store the given
-+** 64-bit integer.
- */
-+SQLITE_PRIVATE int sqlite3VarintLen(u64 v){
-+ int i = 0;
-+ do{
-+ i++;
-+ v >>= 7;
-+ }while( v!=0 && ALWAYS(i<9) );
-+ return i;
-+}
-+
-
- /*
--** An instance of the following structure serves as the key used
--** to locate a particular unixInodeInfo object.
-+** Read or write a four-byte big-endian integer value.
- */
--struct unixFileId {
-- dev_t dev; /* Device number */
--#if OS_VXWORKS
-- struct vxworksFileId *pId; /* Unique file ID for vxworks. */
--#else
-- ino_t ino; /* Inode number */
--#endif
--};
-+SQLITE_PRIVATE u32 sqlite3Get4byte(const u8 *p){
-+ return (p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3];
-+}
-+SQLITE_PRIVATE void sqlite3Put4byte(unsigned char *p, u32 v){
-+ p[0] = (u8)(v>>24);
-+ p[1] = (u8)(v>>16);
-+ p[2] = (u8)(v>>8);
-+ p[3] = (u8)v;
-+}
-+
-+
-
- /*
--** An instance of the following structure is allocated for each open
--** inode. Or, on LinuxThreads, there is one of these structures for
--** each inode opened by each thread.
--**
--** A single inode can have multiple file descriptors, so each unixFile
--** structure contains a pointer to an instance of this object and this
--** object keeps a count of the number of unixFile pointing to it.
-+** Translate a single byte of Hex into an integer.
-+** This routine only works if h really is a valid hexadecimal
-+** character: 0..9a..fA..F
- */
--struct unixInodeInfo {
-- struct unixFileId fileId; /* The lookup key */
-- int nShared; /* Number of SHARED locks held */
-- unsigned char eFileLock; /* One of SHARED_LOCK, RESERVED_LOCK etc. */
-- unsigned char bProcessLock; /* An exclusive process lock is held */
-- int nRef; /* Number of pointers to this structure */
-- unixShmNode *pShmNode; /* Shared memory associated with this inode */
-- int nLock; /* Number of outstanding file locks */
-- UnixUnusedFd *pUnused; /* Unused file descriptors to close */
-- unixInodeInfo *pNext; /* List of all unixInodeInfo objects */
-- unixInodeInfo *pPrev; /* .... doubly linked */
--#if SQLITE_ENABLE_LOCKING_STYLE
-- unsigned long long sharedByte; /* for AFP simulated shared lock */
-+SQLITE_PRIVATE u8 sqlite3HexToInt(int h){
-+ assert( (h>='0' && h<='9') || (h>='a' && h<='f') || (h>='A' && h<='F') );
-+#ifdef SQLITE_ASCII
-+ h += 9*(1&(h>>6));
- #endif
--#if OS_VXWORKS
-- sem_t *pSem; /* Named POSIX semaphore */
-- char aSemName[MAX_PATHNAME+2]; /* Name of that semaphore */
-+#ifdef SQLITE_EBCDIC
-+ h += 9*(1&~(h>>4));
- #endif
--};
-+ return (u8)(h & 0xf);
-+}
-
-+#if !defined(SQLITE_OMIT_BLOB_LITERAL) || defined(SQLITE_HAS_CODEC)
- /*
--** A lists of all unixInodeInfo objects.
-+** Convert a BLOB literal of the form "x'hhhhhh'" into its binary
-+** value. Return a pointer to its binary value. Space to hold the
-+** binary value has been obtained from malloc and must be freed by
-+** the calling routine.
- */
--static unixInodeInfo *inodeList = 0;
-+SQLITE_PRIVATE void *sqlite3HexToBlob(sqlite3 *db, const char *z, int n){
-+ char *zBlob;
-+ int i;
-+
-+ zBlob = (char *)sqlite3DbMallocRaw(db, n/2 + 1);
-+ n--;
-+ if( zBlob ){
-+ for(i=0; i<n; i+=2){
-+ zBlob[i/2] = (sqlite3HexToInt(z[i])<<4) | sqlite3HexToInt(z[i+1]);
-+ }
-+ zBlob[i/2] = 0;
-+ }
-+ return zBlob;
-+}
-+#endif /* !SQLITE_OMIT_BLOB_LITERAL || SQLITE_HAS_CODEC */
-
- /*
--**
--** This function - unixLogError_x(), is only ever called via the macro
--** unixLogError().
--**
--** It is invoked after an error occurs in an OS function and errno has been
--** set. It logs a message using sqlite3_log() containing the current value of
--** errno and, if possible, the human-readable equivalent from strerror() or
--** strerror_r().
--**
--** The first argument passed to the macro should be the error code that
--** will be returned to SQLite (e.g. SQLITE_IOERR_DELETE, SQLITE_CANTOPEN).
--** The two subsequent arguments should be the name of the OS function that
--** failed (e.g. "unlink", "open") and the associated file-system path,
--** if any.
-+** Log an error that is an API call on a connection pointer that should
-+** not have been used. The "type" of connection pointer is given as the
-+** argument. The zType is a word like "NULL" or "closed" or "invalid".
- */
--#define unixLogError(a,b,c) unixLogErrorAtLine(a,b,c,__LINE__)
--static int unixLogErrorAtLine(
-- int errcode, /* SQLite error code */
-- const char *zFunc, /* Name of OS function that failed */
-- const char *zPath, /* File path associated with error */
-- int iLine /* Source line number where error occurred */
--){
-- char *zErr; /* Message from strerror() or equivalent */
-- int iErrno = errno; /* Saved syscall error number */
--
-- /* If this is not a threadsafe build (SQLITE_THREADSAFE==0), then use
-- ** the strerror() function to obtain the human-readable error message
-- ** equivalent to errno. Otherwise, use strerror_r().
-- */
--#if SQLITE_THREADSAFE && defined(HAVE_STRERROR_R)
-- char aErr[80];
-- memset(aErr, 0, sizeof(aErr));
-- zErr = aErr;
--
-- /* If STRERROR_R_CHAR_P (set by autoconf scripts) or __USE_GNU is defined,
-- ** assume that the system provides the GNU version of strerror_r() that
-- ** returns a pointer to a buffer containing the error message. That pointer
-- ** may point to aErr[], or it may point to some static storage somewhere.
-- ** Otherwise, assume that the system provides the POSIX version of
-- ** strerror_r(), which always writes an error message into aErr[].
-- **
-- ** If the code incorrectly assumes that it is the POSIX version that is
-- ** available, the error message will often be an empty string. Not a
-- ** huge problem. Incorrectly concluding that the GNU version is available
-- ** could lead to a segfault though.
-- */
--#if defined(STRERROR_R_CHAR_P) || defined(__USE_GNU)
-- zErr =
--# endif
-- strerror_r(iErrno, aErr, sizeof(aErr)-1);
--
--#elif SQLITE_THREADSAFE
-- /* This is a threadsafe build, but strerror_r() is not available. */
-- zErr = "";
--#else
-- /* Non-threadsafe build, use strerror(). */
-- zErr = strerror(iErrno);
--#endif
--
-- if( zPath==0 ) zPath = "";
-- sqlite3_log(errcode,
-- "os_unix.c:%d: (%d) %s(%s) - %s",
-- iLine, iErrno, zFunc, zPath, zErr
-+static void logBadConnection(const char *zType){
-+ sqlite3_log(SQLITE_MISUSE,
-+ "API call with %s database connection pointer",
-+ zType
- );
--
-- return errcode;
- }
-
- /*
--** Close a file descriptor.
--**
--** We assume that close() almost always works, since it is only in a
--** very sick application or on a very sick platform that it might fail.
--** If it does fail, simply leak the file descriptor, but do log the
--** error.
-+** Check to make sure we have a valid db pointer. This test is not
-+** foolproof but it does provide some measure of protection against
-+** misuse of the interface such as passing in db pointers that are
-+** NULL or which have been previously closed. If this routine returns
-+** 1 it means that the db pointer is valid and 0 if it should not be
-+** dereferenced for any reason. The calling function should invoke
-+** SQLITE_MISUSE immediately.
- **
--** Note that it is not safe to retry close() after EINTR since the
--** file descriptor might have already been reused by another thread.
--** So we don't even try to recover from an EINTR. Just log the error
--** and move on.
-+** sqlite3SafetyCheckOk() requires that the db pointer be valid for
-+** use. sqlite3SafetyCheckSickOrOk() allows a db pointer that failed to
-+** open properly and is not fit for general use but which can be
-+** used as an argument to sqlite3_errmsg() or sqlite3_close().
- */
--static void robust_close(unixFile *pFile, int h, int lineno){
-- if( osClose(h) ){
-- unixLogErrorAtLine(SQLITE_IOERR_CLOSE, "close",
-- pFile ? pFile->zPath : 0, lineno);
-+SQLITE_PRIVATE int sqlite3SafetyCheckOk(sqlite3 *db){
-+ u32 magic;
-+ if( db==0 ){
-+ logBadConnection("NULL");
-+ return 0;
-+ }
-+ magic = db->magic;
-+ if( magic!=SQLITE_MAGIC_OPEN ){
-+ if( sqlite3SafetyCheckSickOrOk(db) ){
-+ testcase( sqlite3GlobalConfig.xLog!=0 );
-+ logBadConnection("unopened");
-+ }
-+ return 0;
-+ }else{
-+ return 1;
-+ }
-+}
-+SQLITE_PRIVATE int sqlite3SafetyCheckSickOrOk(sqlite3 *db){
-+ u32 magic;
-+ magic = db->magic;
-+ if( magic!=SQLITE_MAGIC_SICK &&
-+ magic!=SQLITE_MAGIC_OPEN &&
-+ magic!=SQLITE_MAGIC_BUSY ){
-+ testcase( sqlite3GlobalConfig.xLog!=0 );
-+ logBadConnection("invalid");
-+ return 0;
-+ }else{
-+ return 1;
- }
- }
-
- /*
--** Close all file descriptors accumuated in the unixInodeInfo->pUnused list.
--*/
--static void closePendingFds(unixFile *pFile){
-- unixInodeInfo *pInode = pFile->pInode;
-- UnixUnusedFd *p;
-- UnixUnusedFd *pNext;
-- for(p=pInode->pUnused; p; p=pNext){
-- pNext = p->pNext;
-- robust_close(pFile, p->fd, __LINE__);
-- sqlite3_free(p);
-+** Attempt to add, substract, or multiply the 64-bit signed value iB against
-+** the other 64-bit signed integer at *pA and store the result in *pA.
-+** Return 0 on success. Or if the operation would have resulted in an
-+** overflow, leave *pA unchanged and return 1.
-+*/
-+SQLITE_PRIVATE int sqlite3AddInt64(i64 *pA, i64 iB){
-+ i64 iA = *pA;
-+ testcase( iA==0 ); testcase( iA==1 );
-+ testcase( iB==-1 ); testcase( iB==0 );
-+ if( iB>=0 ){
-+ testcase( iA>0 && LARGEST_INT64 - iA == iB );
-+ testcase( iA>0 && LARGEST_INT64 - iA == iB - 1 );
-+ if( iA>0 && LARGEST_INT64 - iA < iB ) return 1;
-+ *pA += iB;
-+ }else{
-+ testcase( iA<0 && -(iA + LARGEST_INT64) == iB + 1 );
-+ testcase( iA<0 && -(iA + LARGEST_INT64) == iB + 2 );
-+ if( iA<0 && -(iA + LARGEST_INT64) > iB + 1 ) return 1;
-+ *pA += iB;
- }
-- pInode->pUnused = 0;
-+ return 0;
-+}
-+SQLITE_PRIVATE int sqlite3SubInt64(i64 *pA, i64 iB){
-+ testcase( iB==SMALLEST_INT64+1 );
-+ if( iB==SMALLEST_INT64 ){
-+ testcase( (*pA)==(-1) ); testcase( (*pA)==0 );
-+ if( (*pA)>=0 ) return 1;
-+ *pA -= iB;
-+ return 0;
-+ }else{
-+ return sqlite3AddInt64(pA, -iB);
-+ }
-+}
-+#define TWOPOWER32 (((i64)1)<<32)
-+#define TWOPOWER31 (((i64)1)<<31)
-+SQLITE_PRIVATE int sqlite3MulInt64(i64 *pA, i64 iB){
-+ i64 iA = *pA;
-+ i64 iA1, iA0, iB1, iB0, r;
-+
-+ iA1 = iA/TWOPOWER32;
-+ iA0 = iA % TWOPOWER32;
-+ iB1 = iB/TWOPOWER32;
-+ iB0 = iB % TWOPOWER32;
-+ if( iA1*iB1 != 0 ) return 1;
-+ assert( iA1*iB0==0 || iA0*iB1==0 );
-+ r = iA1*iB0 + iA0*iB1;
-+ testcase( r==(-TWOPOWER31)-1 );
-+ testcase( r==(-TWOPOWER31) );
-+ testcase( r==TWOPOWER31 );
-+ testcase( r==TWOPOWER31-1 );
-+ if( r<(-TWOPOWER31) || r>=TWOPOWER31 ) return 1;
-+ r *= TWOPOWER32;
-+ if( sqlite3AddInt64(&r, iA0*iB0) ) return 1;
-+ *pA = r;
-+ return 0;
- }
-
- /*
--** Release a unixInodeInfo structure previously allocated by findInodeInfo().
-+** Compute the absolute value of a 32-bit signed integer, of possible. Or
-+** if the integer has a value of -2147483648, return +2147483647
-+*/
-+SQLITE_PRIVATE int sqlite3AbsInt32(int x){
-+ if( x>=0 ) return x;
-+ if( x==(int)0x80000000 ) return 0x7fffffff;
-+ return -x;
-+}
-+
-+#ifdef SQLITE_ENABLE_8_3_NAMES
-+/*
-+** If SQLITE_ENABLE_8_3_NAMES is set at compile-time and if the database
-+** filename in zBaseFilename is a URI with the "8_3_names=1" parameter and
-+** if filename in z[] has a suffix (a.k.a. "extension") that is longer than
-+** three characters, then shorten the suffix on z[] to be the last three
-+** characters of the original suffix.
- **
--** The mutex entered using the unixEnterMutex() function must be held
--** when this function is called.
-+** If SQLITE_ENABLE_8_3_NAMES is set to 2 at compile-time, then always
-+** do the suffix shortening regardless of URI parameter.
-+**
-+** Examples:
-+**
-+** test.db-journal => test.nal
-+** test.db-wal => test.wal
-+** test.db-shm => test.shm
-+** test.db-mj7f3319fa => test.9fa
- */
--static void releaseInodeInfo(unixFile *pFile){
-- unixInodeInfo *pInode = pFile->pInode;
-- assert( unixMutexHeld() );
-- if( ALWAYS(pInode) ){
-- pInode->nRef--;
-- if( pInode->nRef==0 ){
-- assert( pInode->pShmNode==0 );
-- closePendingFds(pFile);
-- if( pInode->pPrev ){
-- assert( pInode->pPrev->pNext==pInode );
-- pInode->pPrev->pNext = pInode->pNext;
-- }else{
-- assert( inodeList==pInode );
-- inodeList = pInode->pNext;
-- }
-- if( pInode->pNext ){
-- assert( pInode->pNext->pPrev==pInode );
-- pInode->pNext->pPrev = pInode->pPrev;
-- }
-- sqlite3_free(pInode);
-- }
-+SQLITE_PRIVATE void sqlite3FileSuffix3(const char *zBaseFilename, char *z){
-+#if SQLITE_ENABLE_8_3_NAMES<2
-+ if( sqlite3_uri_boolean(zBaseFilename, "8_3_names", 0) )
-+#endif
-+ {
-+ int i, sz;
-+ sz = sqlite3Strlen30(z);
-+ for(i=sz-1; i>0 && z[i]!='/' && z[i]!='.'; i--){}
-+ if( z[i]=='.' && ALWAYS(sz>i+4) ) memmove(&z[i+1], &z[sz-3], 4);
- }
- }
-+#endif
-
-+/************** End of util.c ************************************************/
-+/************** Begin file hash.c ********************************************/
- /*
--** Given a file descriptor, locate the unixInodeInfo object that
--** describes that file descriptor. Create a new one if necessary. The
--** return value might be uninitialized if an error occurs.
-+** 2001 September 22
- **
--** The mutex entered using the unixEnterMutex() function must be held
--** when this function is called.
-+** The author disclaims copyright to this source code. In place of
-+** a legal notice, here is a blessing:
- **
--** Return an appropriate error code.
-+** May you do good and not evil.
-+** May you find forgiveness for yourself and forgive others.
-+** May you share freely, never taking more than you give.
-+**
-+*************************************************************************
-+** This is the implementation of generic hash-tables
-+** used in SQLite.
- */
--static int findInodeInfo(
-- unixFile *pFile, /* Unix file with file desc used in the key */
-- unixInodeInfo **ppInode /* Return the unixInodeInfo object here */
--){
-- int rc; /* System call return code */
-- int fd; /* The file descriptor for pFile */
-- struct unixFileId fileId; /* Lookup key for the unixInodeInfo */
-- struct stat statbuf; /* Low-level file information */
-- unixInodeInfo *pInode = 0; /* Candidate unixInodeInfo object */
-+/* #include <assert.h> */
-
-- assert( unixMutexHeld() );
-+/* Turn bulk memory into a hash table object by initializing the
-+** fields of the Hash structure.
-+**
-+** "pNew" is a pointer to the hash table that is to be initialized.
-+*/
-+SQLITE_PRIVATE void sqlite3HashInit(Hash *pNew){
-+ assert( pNew!=0 );
-+ pNew->first = 0;
-+ pNew->count = 0;
-+ pNew->htsize = 0;
-+ pNew->ht = 0;
-+}
-
-- /* Get low-level information about the file that we can used to
-- ** create a unique name for the file.
-- */
-- fd = pFile->h;
-- rc = osFstat(fd, &statbuf);
-- if( rc!=0 ){
-- pFile->lastErrno = errno;
--#ifdef EOVERFLOW
-- if( pFile->lastErrno==EOVERFLOW ) return SQLITE_NOLFS;
--#endif
-- return SQLITE_IOERR;
-- }
-+/* Remove all entries from a hash table. Reclaim all memory.
-+** Call this routine to delete a hash table or to reset a hash table
-+** to the empty state.
-+*/
-+SQLITE_PRIVATE void sqlite3HashClear(Hash *pH){
-+ HashElem *elem; /* For looping over all elements of the table */
-
--#ifdef __APPLE__
-- /* On OS X on an msdos filesystem, the inode number is reported
-- ** incorrectly for zero-size files. See ticket #3260. To work
-- ** around this problem (we consider it a bug in OS X, not SQLite)
-- ** we always increase the file size to 1 by writing a single byte
-- ** prior to accessing the inode number. The one byte written is
-- ** an ASCII 'S' character which also happens to be the first byte
-- ** in the header of every SQLite database. In this way, if there
-- ** is a race condition such that another thread has already populated
-- ** the first page of the database, no damage is done.
-- */
-- if( statbuf.st_size==0 && (pFile->fsFlags & SQLITE_FSFLAGS_IS_MSDOS)!=0 ){
-- do{ rc = osWrite(fd, "S", 1); }while( rc<0 && errno==EINTR );
-- if( rc!=1 ){
-- pFile->lastErrno = errno;
-- return SQLITE_IOERR;
-- }
-- rc = osFstat(fd, &statbuf);
-- if( rc!=0 ){
-- pFile->lastErrno = errno;
-- return SQLITE_IOERR;
-- }
-+ assert( pH!=0 );
-+ elem = pH->first;
-+ pH->first = 0;
-+ sqlite3_free(pH->ht);
-+ pH->ht = 0;
-+ pH->htsize = 0;
-+ while( elem ){
-+ HashElem *next_elem = elem->next;
-+ sqlite3_free(elem);
-+ elem = next_elem;
- }
--#endif
-+ pH->count = 0;
-+}
-
-- memset(&fileId, 0, sizeof(fileId));
-- fileId.dev = statbuf.st_dev;
--#if OS_VXWORKS
-- fileId.pId = pFile->pId;
--#else
-- fileId.ino = statbuf.st_ino;
--#endif
-- pInode = inodeList;
-- while( pInode && memcmp(&fileId, &pInode->fileId, sizeof(fileId)) ){
-- pInode = pInode->pNext;
-- }
-- if( pInode==0 ){
-- pInode = sqlite3_malloc( sizeof(*pInode) );
-- if( pInode==0 ){
-- return SQLITE_NOMEM;
-- }
-- memset(pInode, 0, sizeof(*pInode));
-- memcpy(&pInode->fileId, &fileId, sizeof(fileId));
-- pInode->nRef = 1;
-- pInode->pNext = inodeList;
-- pInode->pPrev = 0;
-- if( inodeList ) inodeList->pPrev = pInode;
-- inodeList = pInode;
-- }else{
-- pInode->nRef++;
-+/*
-+** The hashing function.
-+*/
-+static unsigned int strHash(const char *z, int nKey){
-+ int h = 0;
-+ assert( nKey>=0 );
-+ while( nKey > 0 ){
-+ h = (h<<3) ^ h ^ sqlite3UpperToLower[(unsigned char)*z++];
-+ nKey--;
- }
-- *ppInode = pInode;
-- return SQLITE_OK;
-+ return h;
- }
-
-
--/*
--** Check a unixFile that is a database. Verify the following:
--**
--** (1) There is exactly one hard link on the file
--** (2) The file is not a symbolic link
--** (3) The file has not been renamed or unlinked
--**
--** Issue sqlite3_log(SQLITE_WARNING,...) messages if anything is not right.
-+/* Link pNew element into the hash table pH. If pEntry!=0 then also
-+** insert pNew into the pEntry hash bucket.
- */
--static void verifyDbFile(unixFile *pFile){
-- struct stat buf;
-- int rc;
-- if( pFile->ctrlFlags & UNIXFILE_WARNED ){
-- /* One or more of the following warnings have already been issued. Do not
-- ** repeat them so as not to clutter the error log */
-- return;
-- }
-- rc = osFstat(pFile->h, &buf);
-- if( rc!=0 ){
-- sqlite3_log(SQLITE_WARNING, "cannot fstat db file %s", pFile->zPath);
-- pFile->ctrlFlags |= UNIXFILE_WARNED;
-- return;
-- }
-- if( buf.st_nlink==0 && (pFile->ctrlFlags & UNIXFILE_DELETE)==0 ){
-- sqlite3_log(SQLITE_WARNING, "file unlinked while open: %s", pFile->zPath);
-- pFile->ctrlFlags |= UNIXFILE_WARNED;
-- return;
-- }
-- if( buf.st_nlink>1 ){
-- sqlite3_log(SQLITE_WARNING, "multiple links to file: %s", pFile->zPath);
-- pFile->ctrlFlags |= UNIXFILE_WARNED;
-- return;
-+static void insertElement(
-+ Hash *pH, /* The complete hash table */
-+ struct _ht *pEntry, /* The entry into which pNew is inserted */
-+ HashElem *pNew /* The element to be inserted */
-+){
-+ HashElem *pHead; /* First element already in pEntry */
-+ if( pEntry ){
-+ pHead = pEntry->count ? pEntry->chain : 0;
-+ pEntry->count++;
-+ pEntry->chain = pNew;
-+ }else{
-+ pHead = 0;
- }
-- if( pFile->pInode!=0
-- && ((rc = osStat(pFile->zPath, &buf))!=0
-- || buf.st_ino!=pFile->pInode->fileId.ino)
-- ){
-- sqlite3_log(SQLITE_WARNING, "file renamed while open: %s", pFile->zPath);
-- pFile->ctrlFlags |= UNIXFILE_WARNED;
-- return;
-+ if( pHead ){
-+ pNew->next = pHead;
-+ pNew->prev = pHead->prev;
-+ if( pHead->prev ){ pHead->prev->next = pNew; }
-+ else { pH->first = pNew; }
-+ pHead->prev = pNew;
-+ }else{
-+ pNew->next = pH->first;
-+ if( pH->first ){ pH->first->prev = pNew; }
-+ pNew->prev = 0;
-+ pH->first = pNew;
- }
- }
-
-
--/*
--** This routine checks if there is a RESERVED lock held on the specified
--** file by this or any other process. If such a lock is held, set *pResOut
--** to a non-zero value otherwise *pResOut is set to zero. The return value
--** is set to SQLITE_OK unless an I/O error occurs during lock checking.
-+/* Resize the hash table so that it cantains "new_size" buckets.
-+**
-+** The hash table might fail to resize if sqlite3_malloc() fails or
-+** if the new size is the same as the prior size.
-+** Return TRUE if the resize occurs and false if not.
- */
--static int unixCheckReservedLock(sqlite3_file *id, int *pResOut){
-- int rc = SQLITE_OK;
-- int reserved = 0;
-- unixFile *pFile = (unixFile*)id;
-+static int rehash(Hash *pH, unsigned int new_size){
-+ struct _ht *new_ht; /* The new hash table */
-+ HashElem *elem, *next_elem; /* For looping over existing elements */
-
-- SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
-+#if SQLITE_MALLOC_SOFT_LIMIT>0
-+ if( new_size*sizeof(struct _ht)>SQLITE_MALLOC_SOFT_LIMIT ){
-+ new_size = SQLITE_MALLOC_SOFT_LIMIT/sizeof(struct _ht);
-+ }
-+ if( new_size==pH->htsize ) return 0;
-+#endif
-
-- assert( pFile );
-- unixEnterMutex(); /* Because pFile->pInode is shared across threads */
-+ /* The inability to allocates space for a larger hash table is
-+ ** a performance hit but it is not a fatal error. So mark the
-+ ** allocation as a benign. Use sqlite3Malloc()/memset(0) instead of
-+ ** sqlite3MallocZero() to make the allocation, as sqlite3MallocZero()
-+ ** only zeroes the requested number of bytes whereas this module will
-+ ** use the actual amount of space allocated for the hash table (which
-+ ** may be larger than the requested amount).
-+ */
-+ sqlite3BeginBenignMalloc();
-+ new_ht = (struct _ht *)sqlite3Malloc( new_size*sizeof(struct _ht) );
-+ sqlite3EndBenignMalloc();
-
-- /* Check if a thread in this process holds such a lock */
-- if( pFile->pInode->eFileLock>SHARED_LOCK ){
-- reserved = 1;
-+ if( new_ht==0 ) return 0;
-+ sqlite3_free(pH->ht);
-+ pH->ht = new_ht;
-+ pH->htsize = new_size = sqlite3MallocSize(new_ht)/sizeof(struct _ht);
-+ memset(new_ht, 0, new_size*sizeof(struct _ht));
-+ for(elem=pH->first, pH->first=0; elem; elem = next_elem){
-+ unsigned int h = strHash(elem->pKey, elem->nKey) % new_size;
-+ next_elem = elem->next;
-+ insertElement(pH, &new_ht[h], elem);
- }
-+ return 1;
-+}
-
-- /* Otherwise see if some other process holds it.
-- */
--#ifndef __DJGPP__
-- if( !reserved && !pFile->pInode->bProcessLock ){
-- struct flock lock;
-- lock.l_whence = SEEK_SET;
-- lock.l_start = RESERVED_BYTE;
-- lock.l_len = 1;
-- lock.l_type = F_WRLCK;
-- if( osFcntl(pFile->h, F_GETLK, &lock) ){
-- rc = SQLITE_IOERR_CHECKRESERVEDLOCK;
-- pFile->lastErrno = errno;
-- } else if( lock.l_type!=F_UNLCK ){
-- reserved = 1;
-+/* This function (for internal use only) locates an element in an
-+** hash table that matches the given key. The hash for this key has
-+** already been computed and is passed as the 4th parameter.
-+*/
-+static HashElem *findElementGivenHash(
-+ const Hash *pH, /* The pH to be searched */
-+ const char *pKey, /* The key we are searching for */
-+ int nKey, /* Bytes in key (not counting zero terminator) */
-+ unsigned int h /* The hash for this key. */
-+){
-+ HashElem *elem; /* Used to loop thru the element list */
-+ int count; /* Number of elements left to test */
-+
-+ if( pH->ht ){
-+ struct _ht *pEntry = &pH->ht[h];
-+ elem = pEntry->chain;
-+ count = pEntry->count;
-+ }else{
-+ elem = pH->first;
-+ count = pH->count;
-+ }
-+ while( count-- && ALWAYS(elem) ){
-+ if( elem->nKey==nKey && sqlite3StrNICmp(elem->pKey,pKey,nKey)==0 ){
-+ return elem;
- }
-+ elem = elem->next;
- }
--#endif
--
-- unixLeaveMutex();
-- OSTRACE(("TEST WR-LOCK %d %d %d (unix)\n", pFile->h, rc, reserved));
--
-- *pResOut = reserved;
-- return rc;
-+ return 0;
- }
-
--/*
--** Attempt to set a system-lock on the file pFile. The lock is
--** described by pLock.
--**
--** If the pFile was opened read/write from unix-excl, then the only lock
--** ever obtained is an exclusive lock, and it is obtained exactly once
--** the first time any lock is attempted. All subsequent system locking
--** operations become no-ops. Locking operations still happen internally,
--** in order to coordinate access between separate database connections
--** within this process, but all of that is handled in memory and the
--** operating system does not participate.
--**
--** This function is a pass-through to fcntl(F_SETLK) if pFile is using
--** any VFS other than "unix-excl" or if pFile is opened on "unix-excl"
--** and is read-only.
--**
--** Zero is returned if the call completes successfully, or -1 if a call
--** to fcntl() fails. In this case, errno is set appropriately (by fcntl()).
-+/* Remove a single entry from the hash table given a pointer to that
-+** element and a hash on the element's key.
- */
--static int unixFileLock(unixFile *pFile, struct flock *pLock){
-- int rc;
-- unixInodeInfo *pInode = pFile->pInode;
-- assert( unixMutexHeld() );
-- assert( pInode!=0 );
-- if( ((pFile->ctrlFlags & UNIXFILE_EXCL)!=0 || pInode->bProcessLock)
-- && ((pFile->ctrlFlags & UNIXFILE_RDONLY)==0)
-- ){
-- if( pInode->bProcessLock==0 ){
-- struct flock lock;
-- assert( pInode->nLock==0 );
-- lock.l_whence = SEEK_SET;
-- lock.l_start = SHARED_FIRST;
-- lock.l_len = SHARED_SIZE;
-- lock.l_type = F_WRLCK;
-- rc = osFcntl(pFile->h, F_SETLK, &lock);
-- if( rc<0 ) return rc;
-- pInode->bProcessLock = 1;
-- pInode->nLock++;
-- }else{
-- rc = 0;
-+static void removeElementGivenHash(
-+ Hash *pH, /* The pH containing "elem" */
-+ HashElem* elem, /* The element to be removed from the pH */
-+ unsigned int h /* Hash value for the element */
-+){
-+ struct _ht *pEntry;
-+ if( elem->prev ){
-+ elem->prev->next = elem->next;
-+ }else{
-+ pH->first = elem->next;
-+ }
-+ if( elem->next ){
-+ elem->next->prev = elem->prev;
-+ }
-+ if( pH->ht ){
-+ pEntry = &pH->ht[h];
-+ if( pEntry->chain==elem ){
-+ pEntry->chain = elem->next;
- }
-+ pEntry->count--;
-+ assert( pEntry->count>=0 );
-+ }
-+ sqlite3_free( elem );
-+ pH->count--;
-+ if( pH->count==0 ){
-+ assert( pH->first==0 );
-+ assert( pH->count==0 );
-+ sqlite3HashClear(pH);
-+ }
-+}
-+
-+/* Attempt to locate an element of the hash table pH with a key
-+** that matches pKey,nKey. Return the data for this element if it is
-+** found, or NULL if there is no match.
-+*/
-+SQLITE_PRIVATE void *sqlite3HashFind(const Hash *pH, const char *pKey, int nKey){
-+ HashElem *elem; /* The element that matches key */
-+ unsigned int h; /* A hash on key */
-+
-+ assert( pH!=0 );
-+ assert( pKey!=0 );
-+ assert( nKey>=0 );
-+ if( pH->ht ){
-+ h = strHash(pKey, nKey) % pH->htsize;
- }else{
-- rc = osFcntl(pFile->h, F_SETLK, pLock);
-+ h = 0;
- }
-- return rc;
-+ elem = findElementGivenHash(pH, pKey, nKey, h);
-+ return elem ? elem->data : 0;
- }
-
--/*
--** Lock the file with the lock specified by parameter eFileLock - one
--** of the following:
--**
--** (1) SHARED_LOCK
--** (2) RESERVED_LOCK
--** (3) PENDING_LOCK
--** (4) EXCLUSIVE_LOCK
-+/* Insert an element into the hash table pH. The key is pKey,nKey
-+** and the data is "data".
- **
--** Sometimes when requesting one lock state, additional lock states
--** are inserted in between. The locking might fail on one of the later
--** transitions leaving the lock state different from what it started but
--** still short of its goal. The following chart shows the allowed
--** transitions and the inserted intermediate states:
-+** If no element exists with a matching key, then a new
-+** element is created and NULL is returned.
- **
--** UNLOCKED -> SHARED
--** SHARED -> RESERVED
--** SHARED -> (PENDING) -> EXCLUSIVE
--** RESERVED -> (PENDING) -> EXCLUSIVE
--** PENDING -> EXCLUSIVE
-+** If another element already exists with the same key, then the
-+** new data replaces the old data and the old data is returned.
-+** The key is not copied in this instance. If a malloc fails, then
-+** the new data is returned and the hash table is unchanged.
- **
--** This routine will only increase a lock. Use the sqlite3OsUnlock()
--** routine to lower a locking level.
-+** If the "data" parameter to this function is NULL, then the
-+** element corresponding to "key" is removed from the hash table.
- */
--static int unixLock(sqlite3_file *id, int eFileLock){
-- /* The following describes the implementation of the various locks and
-- ** lock transitions in terms of the POSIX advisory shared and exclusive
-- ** lock primitives (called read-locks and write-locks below, to avoid
-- ** confusion with SQLite lock names). The algorithms are complicated
-- ** slightly in order to be compatible with windows systems simultaneously
-- ** accessing the same database file, in case that is ever required.
-- **
-- ** Symbols defined in os.h indentify the 'pending byte' and the 'reserved
-- ** byte', each single bytes at well known offsets, and the 'shared byte
-- ** range', a range of 510 bytes at a well known offset.
-- **
-- ** To obtain a SHARED lock, a read-lock is obtained on the 'pending
-- ** byte'. If this is successful, a random byte from the 'shared byte
-- ** range' is read-locked and the lock on the 'pending byte' released.
-- **
-- ** A process may only obtain a RESERVED lock after it has a SHARED lock.
-- ** A RESERVED lock is implemented by grabbing a write-lock on the
-- ** 'reserved byte'.
-- **
-- ** A process may only obtain a PENDING lock after it has obtained a
-- ** SHARED lock. A PENDING lock is implemented by obtaining a write-lock
-- ** on the 'pending byte'. This ensures that no new SHARED locks can be
-- ** obtained, but existing SHARED locks are allowed to persist. A process
-- ** does not have to obtain a RESERVED lock on the way to a PENDING lock.
-- ** This property is used by the algorithm for rolling back a journal file
-- ** after a crash.
-- **
-- ** An EXCLUSIVE lock, obtained after a PENDING lock is held, is
-- ** implemented by obtaining a write-lock on the entire 'shared byte
-- ** range'. Since all other locks require a read-lock on one of the bytes
-- ** within this range, this ensures that no other locks are held on the
-- ** database.
-- **
-- ** The reason a single byte cannot be used instead of the 'shared byte
-- ** range' is that some versions of windows do not support read-locks. By
-- ** locking a random byte from a range, concurrent SHARED locks may exist
-- ** even if the locking primitive used is always a write-lock.
-- */
-- int rc = SQLITE_OK;
-- unixFile *pFile = (unixFile*)id;
-- unixInodeInfo *pInode;
-- struct flock lock;
-- int tErrno = 0;
--
-- assert( pFile );
-- OSTRACE(("LOCK %d %s was %s(%s,%d) pid=%d (unix)\n", pFile->h,
-- azFileLock(eFileLock), azFileLock(pFile->eFileLock),
-- azFileLock(pFile->pInode->eFileLock), pFile->pInode->nShared , getpid()));
-+SQLITE_PRIVATE void *sqlite3HashInsert(Hash *pH, const char *pKey, int nKey, void *data){
-+ unsigned int h; /* the hash of the key modulo hash table size */
-+ HashElem *elem; /* Used to loop thru the element list */
-+ HashElem *new_elem; /* New element added to the pH */
-
-- /* If there is already a lock of this type or more restrictive on the
-- ** unixFile, do nothing. Don't use the end_lock: exit path, as
-- ** unixEnterMutex() hasn't been called yet.
-- */
-- if( pFile->eFileLock>=eFileLock ){
-- OSTRACE(("LOCK %d %s ok (already held) (unix)\n", pFile->h,
-- azFileLock(eFileLock)));
-- return SQLITE_OK;
-+ assert( pH!=0 );
-+ assert( pKey!=0 );
-+ assert( nKey>=0 );
-+ if( pH->htsize ){
-+ h = strHash(pKey, nKey) % pH->htsize;
-+ }else{
-+ h = 0;
- }
--
-- /* Make sure the locking sequence is correct.
-- ** (1) We never move from unlocked to anything higher than shared lock.
-- ** (2) SQLite never explicitly requests a pendig lock.
-- ** (3) A shared lock is always held when a reserve lock is requested.
-- */
-- assert( pFile->eFileLock!=NO_LOCK || eFileLock==SHARED_LOCK );
-- assert( eFileLock!=PENDING_LOCK );
-- assert( eFileLock!=RESERVED_LOCK || pFile->eFileLock==SHARED_LOCK );
--
-- /* This mutex is needed because pFile->pInode is shared across threads
-- */
-- unixEnterMutex();
-- pInode = pFile->pInode;
--
-- /* If some thread using this PID has a lock via a different unixFile*
-- ** handle that precludes the requested lock, return BUSY.
-- */
-- if( (pFile->eFileLock!=pInode->eFileLock &&
-- (pInode->eFileLock>=PENDING_LOCK || eFileLock>SHARED_LOCK))
-- ){
-- rc = SQLITE_BUSY;
-- goto end_lock;
-+ elem = findElementGivenHash(pH,pKey,nKey,h);
-+ if( elem ){
-+ void *old_data = elem->data;
-+ if( data==0 ){
-+ removeElementGivenHash(pH,elem,h);
-+ }else{
-+ elem->data = data;
-+ elem->pKey = pKey;
-+ assert(nKey==elem->nKey);
-+ }
-+ return old_data;
- }
--
-- /* If a SHARED lock is requested, and some thread using this PID already
-- ** has a SHARED or RESERVED lock, then increment reference counts and
-- ** return SQLITE_OK.
-- */
-- if( eFileLock==SHARED_LOCK &&
-- (pInode->eFileLock==SHARED_LOCK || pInode->eFileLock==RESERVED_LOCK) ){
-- assert( eFileLock==SHARED_LOCK );
-- assert( pFile->eFileLock==0 );
-- assert( pInode->nShared>0 );
-- pFile->eFileLock = SHARED_LOCK;
-- pInode->nShared++;
-- pInode->nLock++;
-- goto end_lock;
-+ if( data==0 ) return 0;
-+ new_elem = (HashElem*)sqlite3Malloc( sizeof(HashElem) );
-+ if( new_elem==0 ) return data;
-+ new_elem->pKey = pKey;
-+ new_elem->nKey = nKey;
-+ new_elem->data = data;
-+ pH->count++;
-+ if( pH->count>=10 && pH->count > 2*pH->htsize ){
-+ if( rehash(pH, pH->count*2) ){
-+ assert( pH->htsize>0 );
-+ h = strHash(pKey, nKey) % pH->htsize;
-+ }
-+ }
-+ if( pH->ht ){
-+ insertElement(pH, &pH->ht[h], new_elem);
-+ }else{
-+ insertElement(pH, 0, new_elem);
- }
-+ return 0;
-+}
-
-+/************** End of hash.c ************************************************/
-+/************** Begin file opcodes.c *****************************************/
-+/* Automatically generated. Do not edit */
-+/* See the mkopcodec.awk script for details. */
-+#if !defined(SQLITE_OMIT_EXPLAIN) || !defined(NDEBUG) || defined(VDBE_PROFILE) || defined(SQLITE_DEBUG)
-+SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
-+ static const char *const azName[] = { "?",
-+ /* 1 */ "Goto",
-+ /* 2 */ "Gosub",
-+ /* 3 */ "Return",
-+ /* 4 */ "Yield",
-+ /* 5 */ "HaltIfNull",
-+ /* 6 */ "Halt",
-+ /* 7 */ "Integer",
-+ /* 8 */ "Int64",
-+ /* 9 */ "String",
-+ /* 10 */ "Null",
-+ /* 11 */ "Blob",
-+ /* 12 */ "Variable",
-+ /* 13 */ "Move",
-+ /* 14 */ "Copy",
-+ /* 15 */ "SCopy",
-+ /* 16 */ "ResultRow",
-+ /* 17 */ "CollSeq",
-+ /* 18 */ "Function",
-+ /* 19 */ "Not",
-+ /* 20 */ "AddImm",
-+ /* 21 */ "MustBeInt",
-+ /* 22 */ "RealAffinity",
-+ /* 23 */ "Permutation",
-+ /* 24 */ "Compare",
-+ /* 25 */ "Jump",
-+ /* 26 */ "Once",
-+ /* 27 */ "If",
-+ /* 28 */ "IfNot",
-+ /* 29 */ "Column",
-+ /* 30 */ "Affinity",
-+ /* 31 */ "MakeRecord",
-+ /* 32 */ "Count",
-+ /* 33 */ "Savepoint",
-+ /* 34 */ "AutoCommit",
-+ /* 35 */ "Transaction",
-+ /* 36 */ "ReadCookie",
-+ /* 37 */ "SetCookie",
-+ /* 38 */ "VerifyCookie",
-+ /* 39 */ "OpenRead",
-+ /* 40 */ "OpenWrite",
-+ /* 41 */ "OpenAutoindex",
-+ /* 42 */ "OpenEphemeral",
-+ /* 43 */ "SorterOpen",
-+ /* 44 */ "OpenPseudo",
-+ /* 45 */ "Close",
-+ /* 46 */ "SeekLt",
-+ /* 47 */ "SeekLe",
-+ /* 48 */ "SeekGe",
-+ /* 49 */ "SeekGt",
-+ /* 50 */ "Seek",
-+ /* 51 */ "NotFound",
-+ /* 52 */ "Found",
-+ /* 53 */ "IsUnique",
-+ /* 54 */ "NotExists",
-+ /* 55 */ "Sequence",
-+ /* 56 */ "NewRowid",
-+ /* 57 */ "Insert",
-+ /* 58 */ "InsertInt",
-+ /* 59 */ "Delete",
-+ /* 60 */ "ResetCount",
-+ /* 61 */ "SorterCompare",
-+ /* 62 */ "SorterData",
-+ /* 63 */ "RowKey",
-+ /* 64 */ "RowData",
-+ /* 65 */ "Rowid",
-+ /* 66 */ "NullRow",
-+ /* 67 */ "Last",
-+ /* 68 */ "Or",
-+ /* 69 */ "And",
-+ /* 70 */ "SorterSort",
-+ /* 71 */ "Sort",
-+ /* 72 */ "Rewind",
-+ /* 73 */ "IsNull",
-+ /* 74 */ "NotNull",
-+ /* 75 */ "Ne",
-+ /* 76 */ "Eq",
-+ /* 77 */ "Gt",
-+ /* 78 */ "Le",
-+ /* 79 */ "Lt",
-+ /* 80 */ "Ge",
-+ /* 81 */ "SorterNext",
-+ /* 82 */ "BitAnd",
-+ /* 83 */ "BitOr",
-+ /* 84 */ "ShiftLeft",
-+ /* 85 */ "ShiftRight",
-+ /* 86 */ "Add",
-+ /* 87 */ "Subtract",
-+ /* 88 */ "Multiply",
-+ /* 89 */ "Divide",
-+ /* 90 */ "Remainder",
-+ /* 91 */ "Concat",
-+ /* 92 */ "Prev",
-+ /* 93 */ "BitNot",
-+ /* 94 */ "String8",
-+ /* 95 */ "Next",
-+ /* 96 */ "SorterInsert",
-+ /* 97 */ "IdxInsert",
-+ /* 98 */ "IdxDelete",
-+ /* 99 */ "IdxRowid",
-+ /* 100 */ "IdxLT",
-+ /* 101 */ "IdxGE",
-+ /* 102 */ "Destroy",
-+ /* 103 */ "Clear",
-+ /* 104 */ "CreateIndex",
-+ /* 105 */ "CreateTable",
-+ /* 106 */ "ParseSchema",
-+ /* 107 */ "LoadAnalysis",
-+ /* 108 */ "DropTable",
-+ /* 109 */ "DropIndex",
-+ /* 110 */ "DropTrigger",
-+ /* 111 */ "IntegrityCk",
-+ /* 112 */ "RowSetAdd",
-+ /* 113 */ "RowSetRead",
-+ /* 114 */ "RowSetTest",
-+ /* 115 */ "Program",
-+ /* 116 */ "Param",
-+ /* 117 */ "FkCounter",
-+ /* 118 */ "FkIfZero",
-+ /* 119 */ "MemMax",
-+ /* 120 */ "IfPos",
-+ /* 121 */ "IfNeg",
-+ /* 122 */ "IfZero",
-+ /* 123 */ "AggStep",
-+ /* 124 */ "AggFinal",
-+ /* 125 */ "Checkpoint",
-+ /* 126 */ "JournalMode",
-+ /* 127 */ "Vacuum",
-+ /* 128 */ "IncrVacuum",
-+ /* 129 */ "Expire",
-+ /* 130 */ "Real",
-+ /* 131 */ "TableLock",
-+ /* 132 */ "VBegin",
-+ /* 133 */ "VCreate",
-+ /* 134 */ "VDestroy",
-+ /* 135 */ "VOpen",
-+ /* 136 */ "VFilter",
-+ /* 137 */ "VColumn",
-+ /* 138 */ "VNext",
-+ /* 139 */ "VRename",
-+ /* 140 */ "VUpdate",
-+ /* 141 */ "ToText",
-+ /* 142 */ "ToBlob",
-+ /* 143 */ "ToNumeric",
-+ /* 144 */ "ToInt",
-+ /* 145 */ "ToReal",
-+ /* 146 */ "Pagecount",
-+ /* 147 */ "MaxPgcnt",
-+ /* 148 */ "Trace",
-+ /* 149 */ "Noop",
-+ /* 150 */ "Explain",
-+ };
-+ return azName[i];
-+}
-+#endif
-
-- /* A PENDING lock is needed before acquiring a SHARED lock and before
-- ** acquiring an EXCLUSIVE lock. For the SHARED lock, the PENDING will
-- ** be released.
-- */
-- lock.l_len = 1L;
-- lock.l_whence = SEEK_SET;
-- if( eFileLock==SHARED_LOCK
-- || (eFileLock==EXCLUSIVE_LOCK && pFile->eFileLock<PENDING_LOCK)
-- ){
-- lock.l_type = (eFileLock==SHARED_LOCK?F_RDLCK:F_WRLCK);
-- lock.l_start = PENDING_BYTE;
-- if( unixFileLock(pFile, &lock) ){
-- tErrno = errno;
-- rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
-- if( rc!=SQLITE_BUSY ){
-- pFile->lastErrno = tErrno;
-- }
-- goto end_lock;
-- }
-- }
-+/************** End of opcodes.c *********************************************/
-+/************** Begin file os_unix.c *****************************************/
-+/*
-+** 2004 May 22
-+**
-+** The author disclaims copyright to this source code. In place of
-+** a legal notice, here is a blessing:
-+**
-+** May you do good and not evil.
-+** May you find forgiveness for yourself and forgive others.
-+** May you share freely, never taking more than you give.
-+**
-+******************************************************************************
-+**
-+** This file contains the VFS implementation for unix-like operating systems
-+** include Linux, MacOSX, *BSD, QNX, VxWorks, AIX, HPUX, and others.
-+**
-+** There are actually several different VFS implementations in this file.
-+** The differences are in the way that file locking is done. The default
-+** implementation uses Posix Advisory Locks. Alternative implementations
-+** use flock(), dot-files, various proprietary locking schemas, or simply
-+** skip locking all together.
-+**
-+** This source file is organized into divisions where the logic for various
-+** subfunctions is contained within the appropriate division. PLEASE
-+** KEEP THE STRUCTURE OF THIS FILE INTACT. New code should be placed
-+** in the correct division and should be clearly labeled.
-+**
-+** The layout of divisions is as follows:
-+**
-+** * General-purpose declarations and utility functions.
-+** * Unique file ID logic used by VxWorks.
-+** * Various locking primitive implementations (all except proxy locking):
-+** + for Posix Advisory Locks
-+** + for no-op locks
-+** + for dot-file locks
-+** + for flock() locking
-+** + for named semaphore locks (VxWorks only)
-+** + for AFP filesystem locks (MacOSX only)
-+** * sqlite3_file methods not associated with locking.
-+** * Definitions of sqlite3_io_methods objects for all locking
-+** methods plus "finder" functions for each locking method.
-+** * sqlite3_vfs method implementations.
-+** * Locking primitives for the proxy uber-locking-method. (MacOSX only)
-+** * Definitions of sqlite3_vfs objects for all locking methods
-+** plus implementations of sqlite3_os_init() and sqlite3_os_end().
-+*/
-+#if SQLITE_OS_UNIX /* This file is used on unix only */
-
-+/* Use posix_fallocate() if it is available
-+*/
-+#if !defined(HAVE_POSIX_FALLOCATE) \
-+ && (_XOPEN_SOURCE >= 600 || _POSIX_C_SOURCE >= 200112L)
-+# define HAVE_POSIX_FALLOCATE 1
-+#endif
-
-- /* If control gets to this point, then actually go ahead and make
-- ** operating system calls for the specified lock.
-- */
-- if( eFileLock==SHARED_LOCK ){
-- assert( pInode->nShared==0 );
-- assert( pInode->eFileLock==0 );
-- assert( rc==SQLITE_OK );
-+/*
-+** There are various methods for file locking used for concurrency
-+** control:
-+**
-+** 1. POSIX locking (the default),
-+** 2. No locking,
-+** 3. Dot-file locking,
-+** 4. flock() locking,
-+** 5. AFP locking (OSX only),
-+** 6. Named POSIX semaphores (VXWorks only),
-+** 7. proxy locking. (OSX only)
-+**
-+** Styles 4, 5, and 7 are only available of SQLITE_ENABLE_LOCKING_STYLE
-+** is defined to 1. The SQLITE_ENABLE_LOCKING_STYLE also enables automatic
-+** selection of the appropriate locking style based on the filesystem
-+** where the database is located.
-+*/
-+#if !defined(SQLITE_ENABLE_LOCKING_STYLE)
-+# if defined(__APPLE__)
-+# define SQLITE_ENABLE_LOCKING_STYLE 1
-+# else
-+# define SQLITE_ENABLE_LOCKING_STYLE 0
-+# endif
-+#endif
-
-- /* Now get the read-lock */
-- lock.l_start = SHARED_FIRST;
-- lock.l_len = SHARED_SIZE;
-- if( unixFileLock(pFile, &lock) ){
-- tErrno = errno;
-- rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
-- }
-+/*
-+** Define the OS_VXWORKS pre-processor macro to 1 if building on
-+** vxworks, or 0 otherwise.
-+*/
-+#ifndef OS_VXWORKS
-+# if defined(__RTP__) || defined(_WRS_KERNEL)
-+# define OS_VXWORKS 1
-+# else
-+# define OS_VXWORKS 0
-+# endif
-+#endif
-
-- /* Drop the temporary PENDING lock */
-- lock.l_start = PENDING_BYTE;
-- lock.l_len = 1L;
-- lock.l_type = F_UNLCK;
-- if( unixFileLock(pFile, &lock) && rc==SQLITE_OK ){
-- /* This could happen with a network mount */
-- tErrno = errno;
-- rc = SQLITE_IOERR_UNLOCK;
-- }
-+/*
-+** These #defines should enable >2GB file support on Posix if the
-+** underlying operating system supports it. If the OS lacks
-+** large file support, these should be no-ops.
-+**
-+** Large file support can be disabled using the -DSQLITE_DISABLE_LFS switch
-+** on the compiler command line. This is necessary if you are compiling
-+** on a recent machine (ex: RedHat 7.2) but you want your code to work
-+** on an older machine (ex: RedHat 6.0). If you compile on RedHat 7.2
-+** without this option, LFS is enable. But LFS does not exist in the kernel
-+** in RedHat 6.0, so the code won't work. Hence, for maximum binary
-+** portability you should omit LFS.
-+**
-+** The previous paragraph was written in 2005. (This paragraph is written
-+** on 2008-11-28.) These days, all Linux kernels support large files, so
-+** you should probably leave LFS enabled. But some embedded platforms might
-+** lack LFS in which case the SQLITE_DISABLE_LFS macro might still be useful.
-+*/
-+#ifndef SQLITE_DISABLE_LFS
-+# define _LARGE_FILE 1
-+# ifndef _FILE_OFFSET_BITS
-+# define _FILE_OFFSET_BITS 64
-+# endif
-+# define _LARGEFILE_SOURCE 1
-+#endif
-
-- if( rc ){
-- if( rc!=SQLITE_BUSY ){
-- pFile->lastErrno = tErrno;
-- }
-- goto end_lock;
-- }else{
-- pFile->eFileLock = SHARED_LOCK;
-- pInode->nLock++;
-- pInode->nShared = 1;
-- }
-- }else if( eFileLock==EXCLUSIVE_LOCK && pInode->nShared>1 ){
-- /* We are trying for an exclusive lock but another thread in this
-- ** same process is still holding a shared lock. */
-- rc = SQLITE_BUSY;
-- }else{
-- /* The request was for a RESERVED or EXCLUSIVE lock. It is
-- ** assumed that there is a SHARED or greater lock on the file
-- ** already.
-- */
-- assert( 0!=pFile->eFileLock );
-- lock.l_type = F_WRLCK;
-+/*
-+** standard include files.
-+*/
-+#include <sys/types.h>
-+#include <sys/stat.h>
-+#include <fcntl.h>
-+#include <unistd.h>
-+/* #include <time.h> */
-+#include <sys/time.h>
-+#include <errno.h>
-+#if !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0
+/* #include <sys/mman.h> */
-+#endif
-
-- assert( eFileLock==RESERVED_LOCK || eFileLock==EXCLUSIVE_LOCK );
-- if( eFileLock==RESERVED_LOCK ){
-- lock.l_start = RESERVED_BYTE;
-- lock.l_len = 1L;
-- }else{
-- lock.l_start = SHARED_FIRST;
-- lock.l_len = SHARED_SIZE;
-- }
-
-- if( unixFileLock(pFile, &lock) ){
-- tErrno = errno;
-- rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
-- if( rc!=SQLITE_BUSY ){
-- pFile->lastErrno = tErrno;
-- }
-- }
-- }
--
-+#if SQLITE_ENABLE_LOCKING_STYLE
-+# include <sys/ioctl.h>
-+# if OS_VXWORKS
-+# include <semaphore.h>
-+# include <limits.h>
-+# else
-+# include <sys/file.h>
-+# include <sys/param.h>
-+# endif
-+#endif /* SQLITE_ENABLE_LOCKING_STYLE */
-
--#ifdef SQLITE_DEBUG
-- /* Set up the transaction-counter change checking flags when
-- ** transitioning from a SHARED to a RESERVED lock. The change
-- ** from SHARED to RESERVED marks the beginning of a normal
-- ** write operation (not a hot journal rollback).
-- */
-- if( rc==SQLITE_OK
-- && pFile->eFileLock<=SHARED_LOCK
-- && eFileLock==RESERVED_LOCK
-- ){
-- pFile->transCntrChng = 0;
-- pFile->dbUpdate = 0;
-- pFile->inNormalWrite = 1;
-- }
-+#if defined(__APPLE__) || (SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORKS)
-+# include <sys/mount.h>
- #endif
-
--
-- if( rc==SQLITE_OK ){
-- pFile->eFileLock = eFileLock;
-- pInode->eFileLock = eFileLock;
-- }else if( eFileLock==EXCLUSIVE_LOCK ){
-- pFile->eFileLock = PENDING_LOCK;
-- pInode->eFileLock = PENDING_LOCK;
-- }
--
--end_lock:
-- unixLeaveMutex();
-- OSTRACE(("LOCK %d %s %s (unix)\n", pFile->h, azFileLock(eFileLock),
-- rc==SQLITE_OK ? "ok" : "failed"));
-- return rc;
--}
-+#ifdef HAVE_UTIME
-+# include <utime.h>
-+#endif
-
- /*
--** Add the file descriptor used by file handle pFile to the corresponding
--** pUnused list.
-+** Allowed values of unixFile.fsFlags
- */
--static void setPendingFd(unixFile *pFile){
-- unixInodeInfo *pInode = pFile->pInode;
-- UnixUnusedFd *p = pFile->pUnused;
-- p->pNext = pInode->pUnused;
-- pInode->pUnused = p;
-- pFile->h = -1;
-- pFile->pUnused = 0;
--}
-+#define SQLITE_FSFLAGS_IS_MSDOS 0x1
-
- /*
--** Lower the locking level on file descriptor pFile to eFileLock. eFileLock
--** must be either NO_LOCK or SHARED_LOCK.
--**
--** If the locking level of the file descriptor is already at or below
--** the requested locking level, this routine is a no-op.
--**
--** If handleNFSUnlock is true, then on downgrading an EXCLUSIVE_LOCK to SHARED
--** the byte range is divided into 2 parts and the first part is unlocked then
--** set to a read lock, then the other part is simply unlocked. This works
--** around a bug in BSD NFS lockd (also seen on MacOSX 10.3+) that fails to
--** remove the write lock on a region when a read lock is set.
-+** If we are to be thread-safe, include the pthreads header and define
-+** the SQLITE_UNIX_THREADS macro.
- */
--static int posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){
-- unixFile *pFile = (unixFile*)id;
-- unixInodeInfo *pInode;
-- struct flock lock;
-- int rc = SQLITE_OK;
--
-- assert( pFile );
-- OSTRACE(("UNLOCK %d %d was %d(%d,%d) pid=%d (unix)\n", pFile->h, eFileLock,
-- pFile->eFileLock, pFile->pInode->eFileLock, pFile->pInode->nShared,
-- getpid()));
--
-- assert( eFileLock<=SHARED_LOCK );
-- if( pFile->eFileLock<=eFileLock ){
-- return SQLITE_OK;
-- }
-- unixEnterMutex();
-- pInode = pFile->pInode;
-- assert( pInode->nShared!=0 );
-- if( pFile->eFileLock>SHARED_LOCK ){
-- assert( pInode->eFileLock==pFile->eFileLock );
--
--#ifdef SQLITE_DEBUG
-- /* When reducing a lock such that other processes can start
-- ** reading the database file again, make sure that the
-- ** transaction counter was updated if any part of the database
-- ** file changed. If the transaction counter is not updated,
-- ** other connections to the same file might not realize that
-- ** the file has changed and hence might not know to flush their
-- ** cache. The use of a stale cache can lead to database corruption.
-- */
-- pFile->inNormalWrite = 0;
-+#if SQLITE_THREADSAFE
-+/* # include <pthread.h> */
-+# define SQLITE_UNIX_THREADS 1
- #endif
-
-- /* downgrading to a shared lock on NFS involves clearing the write lock
-- ** before establishing the readlock - to avoid a race condition we downgrade
-- ** the lock in 2 blocks, so that part of the range will be covered by a
-- ** write lock until the rest is covered by a read lock:
-- ** 1: [WWWWW]
-- ** 2: [....W]
-- ** 3: [RRRRW]
-- ** 4: [RRRR.]
-- */
-- if( eFileLock==SHARED_LOCK ){
--
--#if !defined(__APPLE__) || !SQLITE_ENABLE_LOCKING_STYLE
-- (void)handleNFSUnlock;
-- assert( handleNFSUnlock==0 );
-+/*
-+** Default permissions when creating a new file
-+*/
-+#ifndef SQLITE_DEFAULT_FILE_PERMISSIONS
-+# define SQLITE_DEFAULT_FILE_PERMISSIONS 0644
- #endif
--#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
-- if( handleNFSUnlock ){
-- int tErrno; /* Error code from system call errors */
-- off_t divSize = SHARED_SIZE - 1;
--
-- lock.l_type = F_UNLCK;
-- lock.l_whence = SEEK_SET;
-- lock.l_start = SHARED_FIRST;
-- lock.l_len = divSize;
-- if( unixFileLock(pFile, &lock)==(-1) ){
-- tErrno = errno;
-- rc = SQLITE_IOERR_UNLOCK;
-- if( IS_LOCK_ERROR(rc) ){
-- pFile->lastErrno = tErrno;
-- }
-- goto end_unlock;
-- }
-- lock.l_type = F_RDLCK;
-- lock.l_whence = SEEK_SET;
-- lock.l_start = SHARED_FIRST;
-- lock.l_len = divSize;
-- if( unixFileLock(pFile, &lock)==(-1) ){
-- tErrno = errno;
-- rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_RDLOCK);
-- if( IS_LOCK_ERROR(rc) ){
-- pFile->lastErrno = tErrno;
-- }
-- goto end_unlock;
-- }
-- lock.l_type = F_UNLCK;
-- lock.l_whence = SEEK_SET;
-- lock.l_start = SHARED_FIRST+divSize;
-- lock.l_len = SHARED_SIZE-divSize;
-- if( unixFileLock(pFile, &lock)==(-1) ){
-- tErrno = errno;
-- rc = SQLITE_IOERR_UNLOCK;
-- if( IS_LOCK_ERROR(rc) ){
-- pFile->lastErrno = tErrno;
-- }
-- goto end_unlock;
-- }
-- }else
--#endif /* defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE */
-- {
-- lock.l_type = F_RDLCK;
-- lock.l_whence = SEEK_SET;
-- lock.l_start = SHARED_FIRST;
-- lock.l_len = SHARED_SIZE;
-- if( unixFileLock(pFile, &lock) ){
-- /* In theory, the call to unixFileLock() cannot fail because another
-- ** process is holding an incompatible lock. If it does, this
-- ** indicates that the other process is not following the locking
-- ** protocol. If this happens, return SQLITE_IOERR_RDLOCK. Returning
-- ** SQLITE_BUSY would confuse the upper layer (in practice it causes
-- ** an assert to fail). */
-- rc = SQLITE_IOERR_RDLOCK;
-- pFile->lastErrno = errno;
-- goto end_unlock;
-- }
-- }
-- }
-- lock.l_type = F_UNLCK;
-- lock.l_whence = SEEK_SET;
-- lock.l_start = PENDING_BYTE;
-- lock.l_len = 2L; assert( PENDING_BYTE+1==RESERVED_BYTE );
-- if( unixFileLock(pFile, &lock)==0 ){
-- pInode->eFileLock = SHARED_LOCK;
-- }else{
-- rc = SQLITE_IOERR_UNLOCK;
-- pFile->lastErrno = errno;
-- goto end_unlock;
-- }
-- }
-- if( eFileLock==NO_LOCK ){
-- /* Decrement the shared lock counter. Release the lock using an
-- ** OS call only when all threads in this same process have released
-- ** the lock.
-- */
-- pInode->nShared--;
-- if( pInode->nShared==0 ){
-- lock.l_type = F_UNLCK;
-- lock.l_whence = SEEK_SET;
-- lock.l_start = lock.l_len = 0L;
-- if( unixFileLock(pFile, &lock)==0 ){
-- pInode->eFileLock = NO_LOCK;
-- }else{
-- rc = SQLITE_IOERR_UNLOCK;
-- pFile->lastErrno = errno;
-- pInode->eFileLock = NO_LOCK;
-- pFile->eFileLock = NO_LOCK;
-- }
-- }
--
-- /* Decrement the count of locks against this same file. When the
-- ** count reaches zero, close any other file descriptors whose close
-- ** was deferred because of outstanding locks.
-- */
-- pInode->nLock--;
-- assert( pInode->nLock>=0 );
-- if( pInode->nLock==0 ){
-- closePendingFds(pFile);
-- }
-- }
--
--end_unlock:
-- unixLeaveMutex();
-- if( rc==SQLITE_OK ) pFile->eFileLock = eFileLock;
-- return rc;
--}
-
- /*
--** Lower the locking level on file descriptor pFile to eFileLock. eFileLock
--** must be either NO_LOCK or SHARED_LOCK.
--**
--** If the locking level of the file descriptor is already at or below
--** the requested locking level, this routine is a no-op.
-+** Default permissions when creating auto proxy dir
- */
--static int unixUnlock(sqlite3_file *id, int eFileLock){
-- assert( eFileLock==SHARED_LOCK || ((unixFile *)id)->nFetchOut==0 );
-- return posixUnlock(id, eFileLock, 0);
--}
-+#ifndef SQLITE_DEFAULT_PROXYDIR_PERMISSIONS
-+# define SQLITE_DEFAULT_PROXYDIR_PERMISSIONS 0755
-+#endif
-
--static int unixMapfile(unixFile *pFd, i64 nByte);
--static void unixUnmapfile(unixFile *pFd);
-+/*
-+** Maximum supported path-length.
-+*/
-+#define MAX_PATHNAME 512
-
- /*
--** This function performs the parts of the "close file" operation
--** common to all locking schemes. It closes the directory and file
--** handles, if they are valid, and sets all fields of the unixFile
--** structure to 0.
--**
--** It is *not* necessary to hold the mutex when this routine is called,
--** even on VxWorks. A mutex will be acquired on VxWorks by the
--** vxworksReleaseFileId() routine.
-+** Only set the lastErrno if the error code is a real error and not
-+** a normal expected return code of SQLITE_BUSY or SQLITE_OK
- */
--static int closeUnixFile(sqlite3_file *id){
-- unixFile *pFile = (unixFile*)id;
-- unixUnmapfile(pFile);
-- if( pFile->h>=0 ){
-- robust_close(pFile, pFile->h, __LINE__);
-- pFile->h = -1;
-- }
--#if OS_VXWORKS
-- if( pFile->pId ){
-- if( pFile->ctrlFlags & UNIXFILE_DELETE ){
-- osUnlink(pFile->pId->zCanonicalName);
-- }
-- vxworksReleaseFileId(pFile->pId);
-- pFile->pId = 0;
-- }
--#endif
-- OSTRACE(("CLOSE %-3d\n", pFile->h));
-- OpenCounter(-1);
-- sqlite3_free(pFile->pUnused);
-- memset(pFile, 0, sizeof(unixFile));
-- return SQLITE_OK;
--}
-+#define IS_LOCK_ERROR(x) ((x != SQLITE_OK) && (x != SQLITE_BUSY))
-+
-+/* Forward references */
-+typedef struct unixShm unixShm; /* Connection shared memory */
-+typedef struct unixShmNode unixShmNode; /* Shared memory instance */
-+typedef struct unixInodeInfo unixInodeInfo; /* An i-node */
-+typedef struct UnixUnusedFd UnixUnusedFd; /* An unused file descriptor */
-
- /*
--** Close a file.
-+** Sometimes, after a file handle is closed by SQLite, the file descriptor
-+** cannot be closed immediately. In these cases, instances of the following
-+** structure are used to store the file descriptor while waiting for an
-+** opportunity to either close or reuse it.
- */
--static int unixClose(sqlite3_file *id){
-- int rc = SQLITE_OK;
-- unixFile *pFile = (unixFile *)id;
-- verifyDbFile(pFile);
-- unixUnlock(id, NO_LOCK);
-- unixEnterMutex();
-+struct UnixUnusedFd {
-+ int fd; /* File descriptor to close */
-+ int flags; /* Flags this file descriptor was opened with */
-+ UnixUnusedFd *pNext; /* Next unused file descriptor on same file */
-+};
-
-- /* unixFile.pInode is always valid here. Otherwise, a different close
-- ** routine (e.g. nolockClose()) would be called instead.
-+/*
-+** The unixFile structure is subclass of sqlite3_file specific to the unix
-+** VFS implementations.
-+*/
-+typedef struct unixFile unixFile;
-+struct unixFile {
-+ sqlite3_io_methods const *pMethod; /* Always the first entry */
-+ sqlite3_vfs *pVfs; /* The VFS that created this unixFile */
-+ unixInodeInfo *pInode; /* Info about locks on this inode */
-+ int h; /* The file descriptor */
-+ unsigned char eFileLock; /* The type of lock held on this fd */
-+ unsigned short int ctrlFlags; /* Behavioral bits. UNIXFILE_* flags */
-+ int lastErrno; /* The unix errno from last I/O error */
-+ void *lockingContext; /* Locking style specific state */
-+ UnixUnusedFd *pUnused; /* Pre-allocated UnixUnusedFd */
-+ const char *zPath; /* Name of the file */
-+ unixShm *pShm; /* Shared memory segment information */
-+ int szChunk; /* Configured by FCNTL_CHUNK_SIZE */
-+ int nFetchOut; /* Number of outstanding xFetch refs */
-+ sqlite3_int64 mmapSize; /* Usable size of mapping at pMapRegion */
-+ sqlite3_int64 mmapSizeActual; /* Actual size of mapping at pMapRegion */
-+ sqlite3_int64 mmapSizeMax; /* Configured FCNTL_MMAP_SIZE value */
-+ void *pMapRegion; /* Memory mapped region */
-+#ifdef __QNXNTO__
-+ int sectorSize; /* Device sector size */
-+ int deviceCharacteristics; /* Precomputed device characteristics */
-+#endif
-+#if SQLITE_ENABLE_LOCKING_STYLE
-+ int openFlags; /* The flags specified at open() */
-+#endif
-+#if SQLITE_ENABLE_LOCKING_STYLE || defined(__APPLE__)
-+ unsigned fsFlags; /* cached details from statfs() */
-+#endif
-+#if OS_VXWORKS
-+ struct vxworksFileId *pId; /* Unique file ID */
-+#endif
-+#ifdef SQLITE_DEBUG
-+ /* The next group of variables are used to track whether or not the
-+ ** transaction counter in bytes 24-27 of database files are updated
-+ ** whenever any part of the database changes. An assertion fault will
-+ ** occur if a file is updated without also updating the transaction
-+ ** counter. This test is made to avoid new problems similar to the
-+ ** one described by ticket #3584.
- */
-- assert( pFile->pInode->nLock>0 || pFile->pInode->bProcessLock==0 );
-- if( ALWAYS(pFile->pInode) && pFile->pInode->nLock ){
-- /* If there are outstanding locks, do not actually close the file just
-- ** yet because that would clear those locks. Instead, add the file
-- ** descriptor to pInode->pUnused list. It will be automatically closed
-- ** when the last lock is cleared.
-- */
-- setPendingFd(pFile);
-- }
-- releaseInodeInfo(pFile);
-- rc = closeUnixFile(id);
-- unixLeaveMutex();
-- return rc;
--}
--
--/************** End of the posix advisory lock implementation *****************
--******************************************************************************/
-+ unsigned char transCntrChng; /* True if the transaction counter changed */
-+ unsigned char dbUpdate; /* True if any part of database file changed */
-+ unsigned char inNormalWrite; /* True if in a normal write operation */
-
--/******************************************************************************
--****************************** No-op Locking **********************************
--**
--** Of the various locking implementations available, this is by far the
--** simplest: locking is ignored. No attempt is made to lock the database
--** file for reading or writing.
--**
--** This locking mode is appropriate for use on read-only databases
--** (ex: databases that are burned into CD-ROM, for example.) It can
--** also be used if the application employs some external mechanism to
--** prevent simultaneous access of the same database by two or more
--** database connections. But there is a serious risk of database
--** corruption if this locking mode is used in situations where multiple
--** database connections are accessing the same database file at the same
--** time and one or more of those connections are writing.
--*/
-+#endif
-
--static int nolockCheckReservedLock(sqlite3_file *NotUsed, int *pResOut){
-- UNUSED_PARAMETER(NotUsed);
-- *pResOut = 0;
-- return SQLITE_OK;
--}
--static int nolockLock(sqlite3_file *NotUsed, int NotUsed2){
-- UNUSED_PARAMETER2(NotUsed, NotUsed2);
-- return SQLITE_OK;
--}
--static int nolockUnlock(sqlite3_file *NotUsed, int NotUsed2){
-- UNUSED_PARAMETER2(NotUsed, NotUsed2);
-- return SQLITE_OK;
--}
-+#ifdef SQLITE_TEST
-+ /* In test mode, increase the size of this structure a bit so that
-+ ** it is larger than the struct CrashFile defined in test6.c.
-+ */
-+ char aPadding[32];
-+#endif
-+};
-
- /*
--** Close the file.
-+** Allowed values for the unixFile.ctrlFlags bitmask:
- */
--static int nolockClose(sqlite3_file *id) {
-- return closeUnixFile(id);
--}
--
--/******************* End of the no-op lock implementation *********************
--******************************************************************************/
-+#define UNIXFILE_EXCL 0x01 /* Connections from one process only */
-+#define UNIXFILE_RDONLY 0x02 /* Connection is read only */
-+#define UNIXFILE_PERSIST_WAL 0x04 /* Persistent WAL mode */
-+#ifndef SQLITE_DISABLE_DIRSYNC
-+# define UNIXFILE_DIRSYNC 0x08 /* Directory sync needed */
-+#else
-+# define UNIXFILE_DIRSYNC 0x00
-+#endif
-+#define UNIXFILE_PSOW 0x10 /* SQLITE_IOCAP_POWERSAFE_OVERWRITE */
-+#define UNIXFILE_DELETE 0x20 /* Delete on close */
-+#define UNIXFILE_URI 0x40 /* Filename might have query parameters */
-+#define UNIXFILE_NOLOCK 0x80 /* Do no file locking */
-+#define UNIXFILE_WARNED 0x0100 /* verifyDbFile() warnings have been issued */
-
--/******************************************************************************
--************************* Begin dot-file Locking ******************************
-+/*
-+** Include code that is common to all os_*.c files
-+*/
-+/************** Include os_common.h in the middle of os_unix.c ***************/
-+/************** Begin file os_common.h ***************************************/
-+/*
-+** 2004 May 22
- **
--** The dotfile locking implementation uses the existence of separate lock
--** files (really a directory) to control access to the database. This works
--** on just about every filesystem imaginable. But there are serious downsides:
-+** The author disclaims copyright to this source code. In place of
-+** a legal notice, here is a blessing:
- **
--** (1) There is zero concurrency. A single reader blocks all other
--** connections from reading or writing the database.
-+** May you do good and not evil.
-+** May you find forgiveness for yourself and forgive others.
-+** May you share freely, never taking more than you give.
- **
--** (2) An application crash or power loss can leave stale lock files
--** sitting around that need to be cleared manually.
-+******************************************************************************
- **
--** Nevertheless, a dotlock is an appropriate locking mode for use if no
--** other locking strategy is available.
-+** This file contains macros and a little bit of code that is common to
-+** all of the platform-specific files (os_*.c) and is #included into those
-+** files.
- **
--** Dotfile locking works by creating a subdirectory in the same directory as
--** the database and with the same name but with a ".lock" extension added.
--** The existence of a lock directory implies an EXCLUSIVE lock. All other
--** lock types (SHARED, RESERVED, PENDING) are mapped into EXCLUSIVE.
-+** This file should be #included by the os_*.c files only. It is not a
-+** general purpose header file.
- */
-+#ifndef _OS_COMMON_H_
-+#define _OS_COMMON_H_
-
- /*
--** The file suffix added to the data base filename in order to create the
--** lock directory.
-+** At least two bugs have slipped in because we changed the MEMORY_DEBUG
-+** macro to SQLITE_DEBUG and some older makefiles have not yet made the
-+** switch. The following code should catch this problem at compile-time.
- */
--#define DOTLOCK_SUFFIX ".lock"
-+#ifdef MEMORY_DEBUG
-+# error "The MEMORY_DEBUG macro is obsolete. Use SQLITE_DEBUG instead."
-+#endif
-+
-+#if defined(SQLITE_TEST) && defined(SQLITE_DEBUG)
-+# ifndef SQLITE_DEBUG_OS_TRACE
-+# define SQLITE_DEBUG_OS_TRACE 0
-+# endif
-+ int sqlite3OSTrace = SQLITE_DEBUG_OS_TRACE;
-+# define OSTRACE(X) if( sqlite3OSTrace ) sqlite3DebugPrintf X
-+#else
-+# define OSTRACE(X)
-+#endif
-
- /*
--** This routine checks if there is a RESERVED lock held on the specified
--** file by this or any other process. If such a lock is held, set *pResOut
--** to a non-zero value otherwise *pResOut is set to zero. The return value
--** is set to SQLITE_OK unless an I/O error occurs during lock checking.
--**
--** In dotfile locking, either a lock exists or it does not. So in this
--** variation of CheckReservedLock(), *pResOut is set to true if any lock
--** is held on the file and false if the file is unlocked.
-+** Macros for performance tracing. Normally turned off. Only works
-+** on i486 hardware.
- */
--static int dotlockCheckReservedLock(sqlite3_file *id, int *pResOut) {
-- int rc = SQLITE_OK;
-- int reserved = 0;
-- unixFile *pFile = (unixFile*)id;
--
-- SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
--
-- assert( pFile );
--
-- /* Check if a thread in this process holds such a lock */
-- if( pFile->eFileLock>SHARED_LOCK ){
-- /* Either this connection or some other connection in the same process
-- ** holds a lock on the file. No need to check further. */
-- reserved = 1;
-- }else{
-- /* The lock is held if and only if the lockfile exists */
-- const char *zLockFile = (const char*)pFile->lockingContext;
-- reserved = osAccess(zLockFile, 0)==0;
-- }
-- OSTRACE(("TEST WR-LOCK %d %d %d (dotlock)\n", pFile->h, rc, reserved));
-- *pResOut = reserved;
-- return rc;
--}
-+#ifdef SQLITE_PERFORMANCE_TRACE
-
-+/*
-+** hwtime.h contains inline assembler code for implementing
-+** high-performance timing routines.
-+*/
-+/************** Include hwtime.h in the middle of os_common.h ****************/
-+/************** Begin file hwtime.h ******************************************/
- /*
--** Lock the file with the lock specified by parameter eFileLock - one
--** of the following:
--**
--** (1) SHARED_LOCK
--** (2) RESERVED_LOCK
--** (3) PENDING_LOCK
--** (4) EXCLUSIVE_LOCK
-+** 2008 May 27
- **
--** Sometimes when requesting one lock state, additional lock states
--** are inserted in between. The locking might fail on one of the later
--** transitions leaving the lock state different from what it started but
--** still short of its goal. The following chart shows the allowed
--** transitions and the inserted intermediate states:
-+** The author disclaims copyright to this source code. In place of
-+** a legal notice, here is a blessing:
- **
--** UNLOCKED -> SHARED
--** SHARED -> RESERVED
--** SHARED -> (PENDING) -> EXCLUSIVE
--** RESERVED -> (PENDING) -> EXCLUSIVE
--** PENDING -> EXCLUSIVE
-+** May you do good and not evil.
-+** May you find forgiveness for yourself and forgive others.
-+** May you share freely, never taking more than you give.
- **
--** This routine will only increase a lock. Use the sqlite3OsUnlock()
--** routine to lower a locking level.
-+******************************************************************************
- **
--** With dotfile locking, we really only support state (4): EXCLUSIVE.
--** But we track the other locking levels internally.
-+** This file contains inline asm code for retrieving "high-performance"
-+** counters for x86 class CPUs.
- */
--static int dotlockLock(sqlite3_file *id, int eFileLock) {
-- unixFile *pFile = (unixFile*)id;
-- char *zLockFile = (char *)pFile->lockingContext;
-- int rc = SQLITE_OK;
-+#ifndef _HWTIME_H_
-+#define _HWTIME_H_
-
-+/*
-+** The following routine only works on pentium-class (or newer) processors.
-+** It uses the RDTSC opcode to read the cycle count value out of the
-+** processor and returns that value. This can be used for high-res
-+** profiling.
-+*/
-+#if (defined(__GNUC__) || defined(_MSC_VER)) && \
-+ (defined(i386) || defined(__i386__) || defined(_M_IX86))
-
-- /* If we have any lock, then the lock file already exists. All we have
-- ** to do is adjust our internal record of the lock level.
-- */
-- if( pFile->eFileLock > NO_LOCK ){
-- pFile->eFileLock = eFileLock;
-- /* Always update the timestamp on the old file */
--#ifdef HAVE_UTIME
-- utime(zLockFile, NULL);
--#else
-- utimes(zLockFile, NULL);
--#endif
-- return SQLITE_OK;
-+ #if defined(__GNUC__)
-+
-+ __inline__ sqlite_uint64 sqlite3Hwtime(void){
-+ unsigned int lo, hi;
-+ __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
-+ return (sqlite_uint64)hi << 32 | lo;
- }
--
-- /* grab an exclusive lock */
-- rc = osMkdir(zLockFile, 0777);
-- if( rc<0 ){
-- /* failed to open/create the lock directory */
-- int tErrno = errno;
-- if( EEXIST == tErrno ){
-- rc = SQLITE_BUSY;
-- } else {
-- rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
-- if( IS_LOCK_ERROR(rc) ){
-- pFile->lastErrno = tErrno;
-- }
-- }
-- return rc;
-- }
--
-- /* got it, set the type and return ok */
-- pFile->eFileLock = eFileLock;
-- return rc;
--}
-
--/*
--** Lower the locking level on file descriptor pFile to eFileLock. eFileLock
--** must be either NO_LOCK or SHARED_LOCK.
--**
--** If the locking level of the file descriptor is already at or below
--** the requested locking level, this routine is a no-op.
--**
--** When the locking level reaches NO_LOCK, delete the lock file.
--*/
--static int dotlockUnlock(sqlite3_file *id, int eFileLock) {
-- unixFile *pFile = (unixFile*)id;
-- char *zLockFile = (char *)pFile->lockingContext;
-- int rc;
-+ #elif defined(_MSC_VER)
-
-- assert( pFile );
-- OSTRACE(("UNLOCK %d %d was %d pid=%d (dotlock)\n", pFile->h, eFileLock,
-- pFile->eFileLock, getpid()));
-- assert( eFileLock<=SHARED_LOCK );
--
-- /* no-op if possible */
-- if( pFile->eFileLock==eFileLock ){
-- return SQLITE_OK;
-+ __declspec(naked) __inline sqlite_uint64 __cdecl sqlite3Hwtime(void){
-+ __asm {
-+ rdtsc
-+ ret ; return value at EDX:EAX
-+ }
- }
-
-- /* To downgrade to shared, simply update our internal notion of the
-- ** lock state. No need to mess with the file on disk.
-- */
-- if( eFileLock==SHARED_LOCK ){
-- pFile->eFileLock = SHARED_LOCK;
-- return SQLITE_OK;
-+ #endif
-+
-+#elif (defined(__GNUC__) && defined(__x86_64__))
-+
-+ __inline__ sqlite_uint64 sqlite3Hwtime(void){
-+ unsigned long val;
-+ __asm__ __volatile__ ("rdtsc" : "=A" (val));
-+ return val;
- }
--
-- /* To fully unlock the database, delete the lock file */
-- assert( eFileLock==NO_LOCK );
-- rc = osRmdir(zLockFile);
-- if( rc<0 && errno==ENOTDIR ) rc = osUnlink(zLockFile);
-- if( rc<0 ){
-- int tErrno = errno;
-- rc = 0;
-- if( ENOENT != tErrno ){
-- rc = SQLITE_IOERR_UNLOCK;
-- }
-- if( IS_LOCK_ERROR(rc) ){
-- pFile->lastErrno = tErrno;
-- }
-- return rc;
-+
-+#elif (defined(__GNUC__) && defined(__ppc__))
-+
-+ __inline__ sqlite_uint64 sqlite3Hwtime(void){
-+ unsigned long long retval;
-+ unsigned long junk;
-+ __asm__ __volatile__ ("\n\
-+ 1: mftbu %1\n\
-+ mftb %L0\n\
-+ mftbu %0\n\
-+ cmpw %0,%1\n\
-+ bne 1b"
-+ : "=r" (retval), "=r" (junk));
-+ return retval;
- }
-- pFile->eFileLock = NO_LOCK;
-- return SQLITE_OK;
--}
-+
-+#else
-+
-+ #error Need implementation of sqlite3Hwtime() for your platform.
-+
-+ /*
-+ ** To compile without implementing sqlite3Hwtime() for your platform,
-+ ** you can remove the above #error and use the following
-+ ** stub function. You will lose timing support for many
-+ ** of the debugging and testing utilities, but it should at
-+ ** least compile and run.
-+ */
-+SQLITE_PRIVATE sqlite_uint64 sqlite3Hwtime(void){ return ((sqlite_uint64)0); }
-+
-+#endif
-+
-+#endif /* !defined(_HWTIME_H_) */
-+
-+/************** End of hwtime.h **********************************************/
-+/************** Continuing where we left off in os_common.h ******************/
-+
-+static sqlite_uint64 g_start;
-+static sqlite_uint64 g_elapsed;
-+#define TIMER_START g_start=sqlite3Hwtime()
-+#define TIMER_END g_elapsed=sqlite3Hwtime()-g_start
-+#define TIMER_ELAPSED g_elapsed
-+#else
-+#define TIMER_START
-+#define TIMER_END
-+#define TIMER_ELAPSED ((sqlite_uint64)0)
-+#endif
-
- /*
--** Close a file. Make sure the lock has been released before closing.
-+** If we compile with the SQLITE_TEST macro set, then the following block
-+** of code will give us the ability to simulate a disk I/O error. This
-+** is used for testing the I/O recovery logic.
- */
--static int dotlockClose(sqlite3_file *id) {
-- int rc = SQLITE_OK;
-- if( id ){
-- unixFile *pFile = (unixFile*)id;
-- dotlockUnlock(id, NO_LOCK);
-- sqlite3_free(pFile->lockingContext);
-- rc = closeUnixFile(id);
-- }
-- return rc;
-+#ifdef SQLITE_TEST
-+SQLITE_API int sqlite3_io_error_hit = 0; /* Total number of I/O Errors */
-+SQLITE_API int sqlite3_io_error_hardhit = 0; /* Number of non-benign errors */
-+SQLITE_API int sqlite3_io_error_pending = 0; /* Count down to first I/O error */
-+SQLITE_API int sqlite3_io_error_persist = 0; /* True if I/O errors persist */
-+SQLITE_API int sqlite3_io_error_benign = 0; /* True if errors are benign */
-+SQLITE_API int sqlite3_diskfull_pending = 0;
-+SQLITE_API int sqlite3_diskfull = 0;
-+#define SimulateIOErrorBenign(X) sqlite3_io_error_benign=(X)
-+#define SimulateIOError(CODE) \
-+ if( (sqlite3_io_error_persist && sqlite3_io_error_hit) \
-+ || sqlite3_io_error_pending-- == 1 ) \
-+ { local_ioerr(); CODE; }
-+static void local_ioerr(){
-+ IOTRACE(("IOERR\n"));
-+ sqlite3_io_error_hit++;
-+ if( !sqlite3_io_error_benign ) sqlite3_io_error_hardhit++;
- }
--/****************** End of the dot-file lock implementation *******************
--******************************************************************************/
-+#define SimulateDiskfullError(CODE) \
-+ if( sqlite3_diskfull_pending ){ \
-+ if( sqlite3_diskfull_pending == 1 ){ \
-+ local_ioerr(); \
-+ sqlite3_diskfull = 1; \
-+ sqlite3_io_error_hit = 1; \
-+ CODE; \
-+ }else{ \
-+ sqlite3_diskfull_pending--; \
-+ } \
-+ }
-+#else
-+#define SimulateIOErrorBenign(X)
-+#define SimulateIOError(A)
-+#define SimulateDiskfullError(A)
-+#endif
-
--/******************************************************************************
--************************** Begin flock Locking ********************************
--**
--** Use the flock() system call to do file locking.
--**
--** flock() locking is like dot-file locking in that the various
--** fine-grain locking levels supported by SQLite are collapsed into
--** a single exclusive lock. In other words, SHARED, RESERVED, and
--** PENDING locks are the same thing as an EXCLUSIVE lock. SQLite
--** still works when you do this, but concurrency is reduced since
--** only a single process can be reading the database at a time.
--**
--** Omit this section if SQLITE_ENABLE_LOCKING_STYLE is turned off or if
--** compiling for VXWORKS.
-+/*
-+** When testing, keep a count of the number of open files.
- */
--#if SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORKS
-+#ifdef SQLITE_TEST
-+SQLITE_API int sqlite3_open_file_count = 0;
-+#define OpenCounter(X) sqlite3_open_file_count+=(X)
-+#else
-+#define OpenCounter(X)
-+#endif
-+
-+#endif /* !defined(_OS_COMMON_H_) */
-+
-+/************** End of os_common.h *******************************************/
-+/************** Continuing where we left off in os_unix.c ********************/
-+
-+/*
-+** Define various macros that are missing from some systems.
-+*/
-+#ifndef O_LARGEFILE
-+# define O_LARGEFILE 0
-+#endif
-+#ifdef SQLITE_DISABLE_LFS
-+# undef O_LARGEFILE
-+# define O_LARGEFILE 0
-+#endif
-+#ifndef O_NOFOLLOW
-+# define O_NOFOLLOW 0
-+#endif
-+#ifndef O_BINARY
-+# define O_BINARY 0
-+#endif
-
- /*
--** Retry flock() calls that fail with EINTR
-+** The threadid macro resolves to the thread-id or to 0. Used for
-+** testing and debugging only.
- */
--#ifdef EINTR
--static int robust_flock(int fd, int op){
-- int rc;
-- do{ rc = flock(fd,op); }while( rc<0 && errno==EINTR );
-- return rc;
--}
-+#if SQLITE_THREADSAFE
-+#define threadid pthread_self()
- #else
--# define robust_flock(a,b) flock(a,b)
-+#define threadid 0
- #endif
--
-
- /*
--** This routine checks if there is a RESERVED lock held on the specified
--** file by this or any other process. If such a lock is held, set *pResOut
--** to a non-zero value otherwise *pResOut is set to zero. The return value
--** is set to SQLITE_OK unless an I/O error occurs during lock checking.
-+** HAVE_MREMAP defaults to true on Linux and false everywhere else.
- */
--static int flockCheckReservedLock(sqlite3_file *id, int *pResOut){
-- int rc = SQLITE_OK;
-- int reserved = 0;
-- unixFile *pFile = (unixFile*)id;
--
-- SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
--
-- assert( pFile );
--
-- /* Check if a thread in this process holds such a lock */
-- if( pFile->eFileLock>SHARED_LOCK ){
-- reserved = 1;
-- }
--
-- /* Otherwise see if some other process holds it. */
-- if( !reserved ){
-- /* attempt to get the lock */
-- int lrc = robust_flock(pFile->h, LOCK_EX | LOCK_NB);
-- if( !lrc ){
-- /* got the lock, unlock it */
-- lrc = robust_flock(pFile->h, LOCK_UN);
-- if ( lrc ) {
-- int tErrno = errno;
-- /* unlock failed with an error */
-- lrc = SQLITE_IOERR_UNLOCK;
-- if( IS_LOCK_ERROR(lrc) ){
-- pFile->lastErrno = tErrno;
-- rc = lrc;
-- }
-- }
-- } else {
-- int tErrno = errno;
-- reserved = 1;
-- /* someone else might have it reserved */
-- lrc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
-- if( IS_LOCK_ERROR(lrc) ){
-- pFile->lastErrno = tErrno;
-- rc = lrc;
-- }
-- }
-- }
-- OSTRACE(("TEST WR-LOCK %d %d %d (flock)\n", pFile->h, rc, reserved));
--
--#ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS
-- if( (rc & SQLITE_IOERR) == SQLITE_IOERR ){
-- rc = SQLITE_OK;
-- reserved=1;
-- }
--#endif /* SQLITE_IGNORE_FLOCK_LOCK_ERRORS */
-- *pResOut = reserved;
-- return rc;
--}
-+#if !defined(HAVE_MREMAP)
-+# if defined(__linux__) && defined(_GNU_SOURCE)
-+# define HAVE_MREMAP 1
-+# else
-+# define HAVE_MREMAP 0
-+# endif
-+#endif
-
- /*
--** Lock the file with the lock specified by parameter eFileLock - one
--** of the following:
--**
--** (1) SHARED_LOCK
--** (2) RESERVED_LOCK
--** (3) PENDING_LOCK
--** (4) EXCLUSIVE_LOCK
--**
--** Sometimes when requesting one lock state, additional lock states
--** are inserted in between. The locking might fail on one of the later
--** transitions leaving the lock state different from what it started but
--** still short of its goal. The following chart shows the allowed
--** transitions and the inserted intermediate states:
--**
--** UNLOCKED -> SHARED
--** SHARED -> RESERVED
--** SHARED -> (PENDING) -> EXCLUSIVE
--** RESERVED -> (PENDING) -> EXCLUSIVE
--** PENDING -> EXCLUSIVE
--**
--** flock() only really support EXCLUSIVE locks. We track intermediate
--** lock states in the sqlite3_file structure, but all locks SHARED or
--** above are really EXCLUSIVE locks and exclude all other processes from
--** access the file.
-+** Different Unix systems declare open() in different ways. Same use
-+** open(const char*,int,mode_t). Others use open(const char*,int,...).
-+** The difference is important when using a pointer to the function.
- **
--** This routine will only increase a lock. Use the sqlite3OsUnlock()
--** routine to lower a locking level.
-+** The safest way to deal with the problem is to always use this wrapper
-+** which always has the same well-defined interface.
- */
--static int flockLock(sqlite3_file *id, int eFileLock) {
-- int rc = SQLITE_OK;
-- unixFile *pFile = (unixFile*)id;
--
-- assert( pFile );
--
-- /* if we already have a lock, it is exclusive.
-- ** Just adjust level and punt on outta here. */
-- if (pFile->eFileLock > NO_LOCK) {
-- pFile->eFileLock = eFileLock;
-- return SQLITE_OK;
-- }
--
-- /* grab an exclusive lock */
--
-- if (robust_flock(pFile->h, LOCK_EX | LOCK_NB)) {
-- int tErrno = errno;
-- /* didn't get, must be busy */
-- rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
-- if( IS_LOCK_ERROR(rc) ){
-- pFile->lastErrno = tErrno;
-- }
-- } else {
-- /* got it, set the type and return ok */
-- pFile->eFileLock = eFileLock;
-- }
-- OSTRACE(("LOCK %d %s %s (flock)\n", pFile->h, azFileLock(eFileLock),
-- rc==SQLITE_OK ? "ok" : "failed"));
--#ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS
-- if( (rc & SQLITE_IOERR) == SQLITE_IOERR ){
-- rc = SQLITE_BUSY;
-- }
--#endif /* SQLITE_IGNORE_FLOCK_LOCK_ERRORS */
-- return rc;
-+static int posixOpen(const char *zFile, int flags, int mode){
-+ return open(zFile, flags, mode);
- }
-
--
- /*
--** Lower the locking level on file descriptor pFile to eFileLock. eFileLock
--** must be either NO_LOCK or SHARED_LOCK.
--**
--** If the locking level of the file descriptor is already at or below
--** the requested locking level, this routine is a no-op.
-+** On some systems, calls to fchown() will trigger a message in a security
-+** log if they come from non-root processes. So avoid calling fchown() if
-+** we are not running as root.
- */
--static int flockUnlock(sqlite3_file *id, int eFileLock) {
-- unixFile *pFile = (unixFile*)id;
--
-- assert( pFile );
-- OSTRACE(("UNLOCK %d %d was %d pid=%d (flock)\n", pFile->h, eFileLock,
-- pFile->eFileLock, getpid()));
-- assert( eFileLock<=SHARED_LOCK );
--
-- /* no-op if possible */
-- if( pFile->eFileLock==eFileLock ){
-- return SQLITE_OK;
-- }
--
-- /* shared can just be set because we always have an exclusive */
-- if (eFileLock==SHARED_LOCK) {
-- pFile->eFileLock = eFileLock;
-- return SQLITE_OK;
-- }
--
-- /* no, really, unlock. */
-- if( robust_flock(pFile->h, LOCK_UN) ){
--#ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS
-- return SQLITE_OK;
--#endif /* SQLITE_IGNORE_FLOCK_LOCK_ERRORS */
-- return SQLITE_IOERR_UNLOCK;
-- }else{
-- pFile->eFileLock = NO_LOCK;
-- return SQLITE_OK;
-- }
-+static int posixFchown(int fd, uid_t uid, gid_t gid){
-+ return geteuid() ? 0 : fchown(fd,uid,gid);
- }
-
-+/* Forward reference */
-+static int openDirectory(const char*, int*);
-+
- /*
--** Close a file.
-+** Many system calls are accessed through pointer-to-functions so that
-+** they may be overridden at runtime to facilitate fault injection during
-+** testing and sandboxing. The following array holds the names and pointers
-+** to all overrideable system calls.
- */
--static int flockClose(sqlite3_file *id) {
-- int rc = SQLITE_OK;
-- if( id ){
-- flockUnlock(id, NO_LOCK);
-- rc = closeUnixFile(id);
-- }
-- return rc;
--}
-+static struct unix_syscall {
-+ const char *zName; /* Name of the system call */
-+ sqlite3_syscall_ptr pCurrent; /* Current value of the system call */
-+ sqlite3_syscall_ptr pDefault; /* Default value */
-+} aSyscall[] = {
-+ { "open", (sqlite3_syscall_ptr)posixOpen, 0 },
-+#define osOpen ((int(*)(const char*,int,int))aSyscall[0].pCurrent)
-
--#endif /* SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORK */
-+ { "close", (sqlite3_syscall_ptr)close, 0 },
-+#define osClose ((int(*)(int))aSyscall[1].pCurrent)
-
--/******************* End of the flock lock implementation *********************
--******************************************************************************/
-+ { "access", (sqlite3_syscall_ptr)access, 0 },
-+#define osAccess ((int(*)(const char*,int))aSyscall[2].pCurrent)
-
--/******************************************************************************
--************************ Begin Named Semaphore Locking ************************
--**
--** Named semaphore locking is only supported on VxWorks.
--**
--** Semaphore locking is like dot-lock and flock in that it really only
--** supports EXCLUSIVE locking. Only a single process can read or write
--** the database file at a time. This reduces potential concurrency, but
--** makes the lock implementation much easier.
--*/
--#if OS_VXWORKS
-+ { "getcwd", (sqlite3_syscall_ptr)getcwd, 0 },
-+#define osGetcwd ((char*(*)(char*,size_t))aSyscall[3].pCurrent)
-+
-+ { "stat", (sqlite3_syscall_ptr)stat, 0 },
-+#define osStat ((int(*)(const char*,struct stat*))aSyscall[4].pCurrent)
-
- /*
--** This routine checks if there is a RESERVED lock held on the specified
--** file by this or any other process. If such a lock is held, set *pResOut
--** to a non-zero value otherwise *pResOut is set to zero. The return value
--** is set to SQLITE_OK unless an I/O error occurs during lock checking.
-+** The DJGPP compiler environment looks mostly like Unix, but it
-+** lacks the fcntl() system call. So redefine fcntl() to be something
-+** that always succeeds. This means that locking does not occur under
-+** DJGPP. But it is DOS - what did you expect?
- */
--static int semCheckReservedLock(sqlite3_file *id, int *pResOut) {
-- int rc = SQLITE_OK;
-- int reserved = 0;
-- unixFile *pFile = (unixFile*)id;
-+#ifdef __DJGPP__
-+ { "fstat", 0, 0 },
-+#define osFstat(a,b,c) 0
-+#else
-+ { "fstat", (sqlite3_syscall_ptr)fstat, 0 },
-+#define osFstat ((int(*)(int,struct stat*))aSyscall[5].pCurrent)
-+#endif
-
-- SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
--
-- assert( pFile );
-+ { "ftruncate", (sqlite3_syscall_ptr)ftruncate, 0 },
-+#define osFtruncate ((int(*)(int,off_t))aSyscall[6].pCurrent)
-
-- /* Check if a thread in this process holds such a lock */
-- if( pFile->eFileLock>SHARED_LOCK ){
-- reserved = 1;
-- }
--
-- /* Otherwise see if some other process holds it. */
-- if( !reserved ){
-- sem_t *pSem = pFile->pInode->pSem;
-- struct stat statBuf;
-+ { "fcntl", (sqlite3_syscall_ptr)fcntl, 0 },
-+#define osFcntl ((int(*)(int,int,...))aSyscall[7].pCurrent)
-
-- if( sem_trywait(pSem)==-1 ){
-- int tErrno = errno;
-- if( EAGAIN != tErrno ){
-- rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_CHECKRESERVEDLOCK);
-- pFile->lastErrno = tErrno;
-- } else {
-- /* someone else has the lock when we are in NO_LOCK */
-- reserved = (pFile->eFileLock < SHARED_LOCK);
-- }
-- }else{
-- /* we could have it if we want it */
-- sem_post(pSem);
-- }
-- }
-- OSTRACE(("TEST WR-LOCK %d %d %d (sem)\n", pFile->h, rc, reserved));
-+ { "read", (sqlite3_syscall_ptr)read, 0 },
-+#define osRead ((ssize_t(*)(int,void*,size_t))aSyscall[8].pCurrent)
-
-- *pResOut = reserved;
-- return rc;
--}
-+#if defined(USE_PREAD) || SQLITE_ENABLE_LOCKING_STYLE
-+ { "pread", (sqlite3_syscall_ptr)pread, 0 },
-+#else
-+ { "pread", (sqlite3_syscall_ptr)0, 0 },
-+#endif
-+#define osPread ((ssize_t(*)(int,void*,size_t,off_t))aSyscall[9].pCurrent)
-+
-+#if defined(USE_PREAD64)
-+ { "pread64", (sqlite3_syscall_ptr)pread64, 0 },
-+#else
-+ { "pread64", (sqlite3_syscall_ptr)0, 0 },
-+#endif
-+#define osPread64 ((ssize_t(*)(int,void*,size_t,off_t))aSyscall[10].pCurrent)
-+
-+ { "write", (sqlite3_syscall_ptr)write, 0 },
-+#define osWrite ((ssize_t(*)(int,const void*,size_t))aSyscall[11].pCurrent)
-+
-+#if defined(USE_PREAD) || SQLITE_ENABLE_LOCKING_STYLE
-+ { "pwrite", (sqlite3_syscall_ptr)pwrite, 0 },
-+#else
-+ { "pwrite", (sqlite3_syscall_ptr)0, 0 },
-+#endif
-+#define osPwrite ((ssize_t(*)(int,const void*,size_t,off_t))\
-+ aSyscall[12].pCurrent)
-+
-+#if defined(USE_PREAD64)
-+ { "pwrite64", (sqlite3_syscall_ptr)pwrite64, 0 },
-+#else
-+ { "pwrite64", (sqlite3_syscall_ptr)0, 0 },
-+#endif
-+#define osPwrite64 ((ssize_t(*)(int,const void*,size_t,off_t))\
-+ aSyscall[13].pCurrent)
-+
-+ { "fchmod", (sqlite3_syscall_ptr)fchmod, 0 },
-+#define osFchmod ((int(*)(int,mode_t))aSyscall[14].pCurrent)
-+
-+#if defined(HAVE_POSIX_FALLOCATE) && HAVE_POSIX_FALLOCATE
-+ { "fallocate", (sqlite3_syscall_ptr)posix_fallocate, 0 },
-+#else
-+ { "fallocate", (sqlite3_syscall_ptr)0, 0 },
-+#endif
-+#define osFallocate ((int(*)(int,off_t,off_t))aSyscall[15].pCurrent)
-+
-+ { "unlink", (sqlite3_syscall_ptr)unlink, 0 },
-+#define osUnlink ((int(*)(const char*))aSyscall[16].pCurrent)
-+
-+ { "openDirectory", (sqlite3_syscall_ptr)openDirectory, 0 },
-+#define osOpenDirectory ((int(*)(const char*,int*))aSyscall[17].pCurrent)
-+
-+ { "mkdir", (sqlite3_syscall_ptr)mkdir, 0 },
-+#define osMkdir ((int(*)(const char*,mode_t))aSyscall[18].pCurrent)
-+
-+ { "rmdir", (sqlite3_syscall_ptr)rmdir, 0 },
-+#define osRmdir ((int(*)(const char*))aSyscall[19].pCurrent)
-+
-+ { "fchown", (sqlite3_syscall_ptr)posixFchown, 0 },
-+#define osFchown ((int(*)(int,uid_t,gid_t))aSyscall[20].pCurrent)
-+
-+ { "mmap", (sqlite3_syscall_ptr)mmap, 0 },
-+#define osMmap ((void*(*)(void*,size_t,int,int,int,off_t))aSyscall[21].pCurrent)
-+
-+ { "munmap", (sqlite3_syscall_ptr)munmap, 0 },
-+#define osMunmap ((void*(*)(void*,size_t))aSyscall[22].pCurrent)
-+
-+#if HAVE_MREMAP
-+ { "mremap", (sqlite3_syscall_ptr)mremap, 0 },
-+#else
-+ { "mremap", (sqlite3_syscall_ptr)0, 0 },
-+#endif
-+#define osMremap ((void*(*)(void*,size_t,size_t,int,...))aSyscall[23].pCurrent)
-+
-+}; /* End of the overrideable system calls */
-
- /*
--** Lock the file with the lock specified by parameter eFileLock - one
--** of the following:
--**
--** (1) SHARED_LOCK
--** (2) RESERVED_LOCK
--** (3) PENDING_LOCK
--** (4) EXCLUSIVE_LOCK
--**
--** Sometimes when requesting one lock state, additional lock states
--** are inserted in between. The locking might fail on one of the later
--** transitions leaving the lock state different from what it started but
--** still short of its goal. The following chart shows the allowed
--** transitions and the inserted intermediate states:
--**
--** UNLOCKED -> SHARED
--** SHARED -> RESERVED
--** SHARED -> (PENDING) -> EXCLUSIVE
--** RESERVED -> (PENDING) -> EXCLUSIVE
--** PENDING -> EXCLUSIVE
--**
--** Semaphore locks only really support EXCLUSIVE locks. We track intermediate
--** lock states in the sqlite3_file structure, but all locks SHARED or
--** above are really EXCLUSIVE locks and exclude all other processes from
--** access the file.
--**
--** This routine will only increase a lock. Use the sqlite3OsUnlock()
--** routine to lower a locking level.
-+** This is the xSetSystemCall() method of sqlite3_vfs for all of the
-+** "unix" VFSes. Return SQLITE_OK opon successfully updating the
-+** system call pointer, or SQLITE_NOTFOUND if there is no configurable
-+** system call named zName.
- */
--static int semLock(sqlite3_file *id, int eFileLock) {
-- unixFile *pFile = (unixFile*)id;
-- int fd;
-- sem_t *pSem = pFile->pInode->pSem;
-- int rc = SQLITE_OK;
-+static int unixSetSystemCall(
-+ sqlite3_vfs *pNotUsed, /* The VFS pointer. Not used */
-+ const char *zName, /* Name of system call to override */
-+ sqlite3_syscall_ptr pNewFunc /* Pointer to new system call value */
-+){
-+ unsigned int i;
-+ int rc = SQLITE_NOTFOUND;
-
-- /* if we already have a lock, it is exclusive.
-- ** Just adjust level and punt on outta here. */
-- if (pFile->eFileLock > NO_LOCK) {
-- pFile->eFileLock = eFileLock;
-+ UNUSED_PARAMETER(pNotUsed);
-+ if( zName==0 ){
-+ /* If no zName is given, restore all system calls to their default
-+ ** settings and return NULL
-+ */
- rc = SQLITE_OK;
-- goto sem_end_lock;
-- }
--
-- /* lock semaphore now but bail out when already locked. */
-- if( sem_trywait(pSem)==-1 ){
-- rc = SQLITE_BUSY;
-- goto sem_end_lock;
-+ for(i=0; i<sizeof(aSyscall)/sizeof(aSyscall[0]); i++){
-+ if( aSyscall[i].pDefault ){
-+ aSyscall[i].pCurrent = aSyscall[i].pDefault;
-+ }
-+ }
-+ }else{
-+ /* If zName is specified, operate on only the one system call
-+ ** specified.
-+ */
-+ for(i=0; i<sizeof(aSyscall)/sizeof(aSyscall[0]); i++){
-+ if( strcmp(zName, aSyscall[i].zName)==0 ){
-+ if( aSyscall[i].pDefault==0 ){
-+ aSyscall[i].pDefault = aSyscall[i].pCurrent;
-+ }
-+ rc = SQLITE_OK;
-+ if( pNewFunc==0 ) pNewFunc = aSyscall[i].pDefault;
-+ aSyscall[i].pCurrent = pNewFunc;
-+ break;
-+ }
-+ }
- }
--
-- /* got it, set the type and return ok */
-- pFile->eFileLock = eFileLock;
--
-- sem_end_lock:
- return rc;
- }
-
- /*
--** Lower the locking level on file descriptor pFile to eFileLock. eFileLock
--** must be either NO_LOCK or SHARED_LOCK.
--**
--** If the locking level of the file descriptor is already at or below
--** the requested locking level, this routine is a no-op.
-+** Return the value of a system call. Return NULL if zName is not a
-+** recognized system call name. NULL is also returned if the system call
-+** is currently undefined.
- */
--static int semUnlock(sqlite3_file *id, int eFileLock) {
-- unixFile *pFile = (unixFile*)id;
-- sem_t *pSem = pFile->pInode->pSem;
-+static sqlite3_syscall_ptr unixGetSystemCall(
-+ sqlite3_vfs *pNotUsed,
-+ const char *zName
-+){
-+ unsigned int i;
-
-- assert( pFile );
-- assert( pSem );
-- OSTRACE(("UNLOCK %d %d was %d pid=%d (sem)\n", pFile->h, eFileLock,
-- pFile->eFileLock, getpid()));
-- assert( eFileLock<=SHARED_LOCK );
--
-- /* no-op if possible */
-- if( pFile->eFileLock==eFileLock ){
-- return SQLITE_OK;
-- }
--
-- /* shared can just be set because we always have an exclusive */
-- if (eFileLock==SHARED_LOCK) {
-- pFile->eFileLock = eFileLock;
-- return SQLITE_OK;
-- }
--
-- /* no, really unlock. */
-- if ( sem_post(pSem)==-1 ) {
-- int rc, tErrno = errno;
-- rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK);
-- if( IS_LOCK_ERROR(rc) ){
-- pFile->lastErrno = tErrno;
-- }
-- return rc;
-+ UNUSED_PARAMETER(pNotUsed);
-+ for(i=0; i<sizeof(aSyscall)/sizeof(aSyscall[0]); i++){
-+ if( strcmp(zName, aSyscall[i].zName)==0 ) return aSyscall[i].pCurrent;
- }
-- pFile->eFileLock = NO_LOCK;
-- return SQLITE_OK;
-+ return 0;
- }
-
- /*
-- ** Close a file.
-- */
--static int semClose(sqlite3_file *id) {
-- if( id ){
-- unixFile *pFile = (unixFile*)id;
-- semUnlock(id, NO_LOCK);
-- assert( pFile );
-- unixEnterMutex();
-- releaseInodeInfo(pFile);
-- unixLeaveMutex();
-- closeUnixFile(id);
-+** Return the name of the first system call after zName. If zName==NULL
-+** then return the name of the first system call. Return NULL if zName
-+** is the last system call or if zName is not the name of a valid
-+** system call.
-+*/
-+static const char *unixNextSystemCall(sqlite3_vfs *p, const char *zName){
-+ int i = -1;
-+
-+ UNUSED_PARAMETER(p);
-+ if( zName ){
-+ for(i=0; i<ArraySize(aSyscall)-1; i++){
-+ if( strcmp(zName, aSyscall[i].zName)==0 ) break;
-+ }
- }
-- return SQLITE_OK;
-+ for(i++; i<ArraySize(aSyscall); i++){
-+ if( aSyscall[i].pCurrent!=0 ) return aSyscall[i].zName;
-+ }
-+ return 0;
- }
-
--#endif /* OS_VXWORKS */
- /*
--** Named semaphore locking is only available on VxWorks.
--**
--*************** End of the named semaphore lock implementation ****************
--******************************************************************************/
--
--
--/******************************************************************************
--*************************** Begin AFP Locking *********************************
-+** Invoke open(). Do so multiple times, until it either succeeds or
-+** fails for some reason other than EINTR.
- **
--** AFP is the Apple Filing Protocol. AFP is a network filesystem found
--** on Apple Macintosh computers - both OS9 and OSX.
-+** If the file creation mode "m" is 0 then set it to the default for
-+** SQLite. The default is SQLITE_DEFAULT_FILE_PERMISSIONS (normally
-+** 0644) as modified by the system umask. If m is not 0, then
-+** make the file creation mode be exactly m ignoring the umask.
- **
--** Third-party implementations of AFP are available. But this code here
--** only works on OSX.
-+** The m parameter will be non-zero only when creating -wal, -journal,
-+** and -shm files. We want those files to have *exactly* the same
-+** permissions as their original database, unadulterated by the umask.
-+** In that way, if a database file is -rw-rw-rw or -rw-rw-r-, and a
-+** transaction crashes and leaves behind hot journals, then any
-+** process that is able to write to the database will also be able to
-+** recover the hot journals.
- */
-+static int robust_open(const char *z, int f, mode_t m){
-+ int fd;
-+ mode_t m2 = m ? m : SQLITE_DEFAULT_FILE_PERMISSIONS;
-+ do{
-+#if defined(O_CLOEXEC)
-+ fd = osOpen(z,f|O_CLOEXEC,m2);
-+#else
-+ fd = osOpen(z,f,m2);
-+#endif
-+ }while( fd<0 && errno==EINTR );
-+ if( fd>=0 ){
-+ if( m!=0 ){
-+ struct stat statbuf;
-+ if( osFstat(fd, &statbuf)==0
-+ && statbuf.st_size==0
-+ && (statbuf.st_mode&0777)!=m
-+ ){
-+ osFchmod(fd, m);
-+ }
-+ }
-+#if defined(FD_CLOEXEC) && (!defined(O_CLOEXEC) || O_CLOEXEC==0)
-+ osFcntl(fd, F_SETFD, osFcntl(fd, F_GETFD, 0) | FD_CLOEXEC);
-+#endif
-+ }
-+ return fd;
-+}
-
--#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
- /*
--** The afpLockingContext structure contains all afp lock specific state
-+** Helper functions to obtain and relinquish the global mutex. The
-+** global mutex is used to protect the unixInodeInfo and
-+** vxworksFileId objects used by this file, all of which may be
-+** shared by multiple threads.
-+**
-+** Function unixMutexHeld() is used to assert() that the global mutex
-+** is held when required. This function is only used as part of assert()
-+** statements. e.g.
-+**
-+** unixEnterMutex()
-+** assert( unixMutexHeld() );
-+** unixEnterLeave()
- */
--typedef struct afpLockingContext afpLockingContext;
--struct afpLockingContext {
-- int reserved;
-- const char *dbPath; /* Name of the open file */
--};
--
--struct ByteRangeLockPB2
--{
-- unsigned long long offset; /* offset to first byte to lock */
-- unsigned long long length; /* nbr of bytes to lock */
-- unsigned long long retRangeStart; /* nbr of 1st byte locked if successful */
-- unsigned char unLockFlag; /* 1 = unlock, 0 = lock */
-- unsigned char startEndFlag; /* 1=rel to end of fork, 0=rel to start */
-- int fd; /* file desc to assoc this lock with */
--};
-+static void unixEnterMutex(void){
-+ sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
-+}
-+static void unixLeaveMutex(void){
-+ sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
-+}
-+#ifdef SQLITE_DEBUG
-+static int unixMutexHeld(void) {
-+ return sqlite3_mutex_held(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
-+}
-+#endif
-
--#define afpfsByteRangeLock2FSCTL _IOWR('z', 23, struct ByteRangeLockPB2)
-
-+#if defined(SQLITE_TEST) && defined(SQLITE_DEBUG)
- /*
--** This is a utility for setting or clearing a bit-range lock on an
--** AFP filesystem.
--**
--** Return SQLITE_OK on success, SQLITE_BUSY on failure.
-+** Helper function for printing out trace information from debugging
-+** binaries. This returns the string represetation of the supplied
-+** integer lock-type.
- */
--static int afpSetLock(
-- const char *path, /* Name of the file to be locked or unlocked */
-- unixFile *pFile, /* Open file descriptor on path */
-- unsigned long long offset, /* First byte to be locked */
-- unsigned long long length, /* Number of bytes to lock */
-- int setLockFlag /* True to set lock. False to clear lock */
--){
-- struct ByteRangeLockPB2 pb;
-- int err;
--
-- pb.unLockFlag = setLockFlag ? 0 : 1;
-- pb.startEndFlag = 0;
-- pb.offset = offset;
-- pb.length = length;
-- pb.fd = pFile->h;
--
-- OSTRACE(("AFPSETLOCK [%s] for %d%s in range %llx:%llx\n",
-- (setLockFlag?"ON":"OFF"), pFile->h, (pb.fd==-1?"[testval-1]":""),
-- offset, length));
-- err = fsctl(path, afpfsByteRangeLock2FSCTL, &pb, 0);
-- if ( err==-1 ) {
-- int rc;
-- int tErrno = errno;
-- OSTRACE(("AFPSETLOCK failed to fsctl() '%s' %d %s\n",
-- path, tErrno, strerror(tErrno)));
--#ifdef SQLITE_IGNORE_AFP_LOCK_ERRORS
-- rc = SQLITE_BUSY;
--#else
-- rc = sqliteErrorFromPosixError(tErrno,
-- setLockFlag ? SQLITE_IOERR_LOCK : SQLITE_IOERR_UNLOCK);
--#endif /* SQLITE_IGNORE_AFP_LOCK_ERRORS */
-- if( IS_LOCK_ERROR(rc) ){
-- pFile->lastErrno = tErrno;
-- }
-- return rc;
-- } else {
-- return SQLITE_OK;
-+static const char *azFileLock(int eFileLock){
-+ switch( eFileLock ){
-+ case NO_LOCK: return "NONE";
-+ case SHARED_LOCK: return "SHARED";
-+ case RESERVED_LOCK: return "RESERVED";
-+ case PENDING_LOCK: return "PENDING";
-+ case EXCLUSIVE_LOCK: return "EXCLUSIVE";
- }
-+ return "ERROR";
- }
-+#endif
-
-+#ifdef SQLITE_LOCK_TRACE
- /*
--** This routine checks if there is a RESERVED lock held on the specified
--** file by this or any other process. If such a lock is held, set *pResOut
--** to a non-zero value otherwise *pResOut is set to zero. The return value
--** is set to SQLITE_OK unless an I/O error occurs during lock checking.
-+** Print out information about all locking operations.
-+**
-+** This routine is used for troubleshooting locks on multithreaded
-+** platforms. Enable by compiling with the -DSQLITE_LOCK_TRACE
-+** command-line option on the compiler. This code is normally
-+** turned off.
- */
--static int afpCheckReservedLock(sqlite3_file *id, int *pResOut){
-- int rc = SQLITE_OK;
-- int reserved = 0;
-- unixFile *pFile = (unixFile*)id;
-- afpLockingContext *context;
--
-- SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
--
-- assert( pFile );
-- context = (afpLockingContext *) pFile->lockingContext;
-- if( context->reserved ){
-- *pResOut = 1;
-- return SQLITE_OK;
-+static int lockTrace(int fd, int op, struct flock *p){
-+ char *zOpName, *zType;
-+ int s;
-+ int savedErrno;
-+ if( op==F_GETLK ){
-+ zOpName = "GETLK";
-+ }else if( op==F_SETLK ){
-+ zOpName = "SETLK";
-+ }else{
-+ s = osFcntl(fd, op, p);
-+ sqlite3DebugPrintf("fcntl unknown %d %d %d\n", fd, op, s);
-+ return s;
- }
-- unixEnterMutex(); /* Because pFile->pInode is shared across threads */
--
-- /* Check if a thread in this process holds such a lock */
-- if( pFile->pInode->eFileLock>SHARED_LOCK ){
-- reserved = 1;
-+ if( p->l_type==F_RDLCK ){
-+ zType = "RDLCK";
-+ }else if( p->l_type==F_WRLCK ){
-+ zType = "WRLCK";
-+ }else if( p->l_type==F_UNLCK ){
-+ zType = "UNLCK";
-+ }else{
-+ assert( 0 );
- }
--
-- /* Otherwise see if some other process holds it.
-- */
-- if( !reserved ){
-- /* lock the RESERVED byte */
-- int lrc = afpSetLock(context->dbPath, pFile, RESERVED_BYTE, 1,1);
-- if( SQLITE_OK==lrc ){
-- /* if we succeeded in taking the reserved lock, unlock it to restore
-- ** the original state */
-- lrc = afpSetLock(context->dbPath, pFile, RESERVED_BYTE, 1, 0);
-- } else {
-- /* if we failed to get the lock then someone else must have it */
-- reserved = 1;
-- }
-- if( IS_LOCK_ERROR(lrc) ){
-- rc=lrc;
-+ assert( p->l_whence==SEEK_SET );
-+ s = osFcntl(fd, op, p);
-+ savedErrno = errno;
-+ sqlite3DebugPrintf("fcntl %d %d %s %s %d %d %d %d\n",
-+ threadid, fd, zOpName, zType, (int)p->l_start, (int)p->l_len,
-+ (int)p->l_pid, s);
-+ if( s==(-1) && op==F_SETLK && (p->l_type==F_RDLCK || p->l_type==F_WRLCK) ){
-+ struct flock l2;
-+ l2 = *p;
-+ osFcntl(fd, F_GETLK, &l2);
-+ if( l2.l_type==F_RDLCK ){
-+ zType = "RDLCK";
-+ }else if( l2.l_type==F_WRLCK ){
-+ zType = "WRLCK";
-+ }else if( l2.l_type==F_UNLCK ){
-+ zType = "UNLCK";
-+ }else{
-+ assert( 0 );
- }
-+ sqlite3DebugPrintf("fcntl-failure-reason: %s %d %d %d\n",
-+ zType, (int)l2.l_start, (int)l2.l_len, (int)l2.l_pid);
- }
--
-- unixLeaveMutex();
-- OSTRACE(("TEST WR-LOCK %d %d %d (afp)\n", pFile->h, rc, reserved));
--
-- *pResOut = reserved;
-- return rc;
-+ errno = savedErrno;
-+ return s;
- }
-+#undef osFcntl
-+#define osFcntl lockTrace
-+#endif /* SQLITE_LOCK_TRACE */
-
- /*
--** Lock the file with the lock specified by parameter eFileLock - one
--** of the following:
--**
--** (1) SHARED_LOCK
--** (2) RESERVED_LOCK
--** (3) PENDING_LOCK
--** (4) EXCLUSIVE_LOCK
--**
--** Sometimes when requesting one lock state, additional lock states
--** are inserted in between. The locking might fail on one of the later
--** transitions leaving the lock state different from what it started but
--** still short of its goal. The following chart shows the allowed
--** transitions and the inserted intermediate states:
--**
--** UNLOCKED -> SHARED
--** SHARED -> RESERVED
--** SHARED -> (PENDING) -> EXCLUSIVE
--** RESERVED -> (PENDING) -> EXCLUSIVE
--** PENDING -> EXCLUSIVE
--**
--** This routine will only increase a lock. Use the sqlite3OsUnlock()
--** routine to lower a locking level.
-+** Retry ftruncate() calls that fail due to EINTR
- */
--static int afpLock(sqlite3_file *id, int eFileLock){
-- int rc = SQLITE_OK;
-- unixFile *pFile = (unixFile*)id;
-- unixInodeInfo *pInode = pFile->pInode;
-- afpLockingContext *context = (afpLockingContext *) pFile->lockingContext;
--
-- assert( pFile );
-- OSTRACE(("LOCK %d %s was %s(%s,%d) pid=%d (afp)\n", pFile->h,
-- azFileLock(eFileLock), azFileLock(pFile->eFileLock),
-- azFileLock(pInode->eFileLock), pInode->nShared , getpid()));
-+static int robust_ftruncate(int h, sqlite3_int64 sz){
-+ int rc;
-+ do{ rc = osFtruncate(h,sz); }while( rc<0 && errno==EINTR );
-+ return rc;
-+}
-
-- /* If there is already a lock of this type or more restrictive on the
-- ** unixFile, do nothing. Don't use the afp_end_lock: exit path, as
-- ** unixEnterMutex() hasn't been called yet.
-+/*
-+** This routine translates a standard POSIX errno code into something
-+** useful to the clients of the sqlite3 functions. Specifically, it is
-+** intended to translate a variety of "try again" errors into SQLITE_BUSY
-+** and a variety of "please close the file descriptor NOW" errors into
-+** SQLITE_IOERR
-+**
-+** Errors during initialization of locks, or file system support for locks,
-+** should handle ENOLCK, ENOTSUP, EOPNOTSUPP separately.
-+*/
-+static int sqliteErrorFromPosixError(int posixError, int sqliteIOErr) {
-+ switch (posixError) {
-+#if 0
-+ /* At one point this code was not commented out. In theory, this branch
-+ ** should never be hit, as this function should only be called after
-+ ** a locking-related function (i.e. fcntl()) has returned non-zero with
-+ ** the value of errno as the first argument. Since a system call has failed,
-+ ** errno should be non-zero.
-+ **
-+ ** Despite this, if errno really is zero, we still don't want to return
-+ ** SQLITE_OK. The system call failed, and *some* SQLite error should be
-+ ** propagated back to the caller. Commenting this branch out means errno==0
-+ ** will be handled by the "default:" case below.
- */
-- if( pFile->eFileLock>=eFileLock ){
-- OSTRACE(("LOCK %d %s ok (already held) (afp)\n", pFile->h,
-- azFileLock(eFileLock)));
-+ case 0:
- return SQLITE_OK;
-- }
--
-- /* Make sure the locking sequence is correct
-- ** (1) We never move from unlocked to anything higher than shared lock.
-- ** (2) SQLite never explicitly requests a pendig lock.
-- ** (3) A shared lock is always held when a reserve lock is requested.
-- */
-- assert( pFile->eFileLock!=NO_LOCK || eFileLock==SHARED_LOCK );
-- assert( eFileLock!=PENDING_LOCK );
-- assert( eFileLock!=RESERVED_LOCK || pFile->eFileLock==SHARED_LOCK );
--
-- /* This mutex is needed because pFile->pInode is shared across threads
-- */
-- unixEnterMutex();
-- pInode = pFile->pInode;
-+#endif
-
-- /* If some thread using this PID has a lock via a different unixFile*
-- ** handle that precludes the requested lock, return BUSY.
-- */
-- if( (pFile->eFileLock!=pInode->eFileLock &&
-- (pInode->eFileLock>=PENDING_LOCK || eFileLock>SHARED_LOCK))
-- ){
-- rc = SQLITE_BUSY;
-- goto afp_end_lock;
-- }
--
-- /* If a SHARED lock is requested, and some thread using this PID already
-- ** has a SHARED or RESERVED lock, then increment reference counts and
-- ** return SQLITE_OK.
-- */
-- if( eFileLock==SHARED_LOCK &&
-- (pInode->eFileLock==SHARED_LOCK || pInode->eFileLock==RESERVED_LOCK) ){
-- assert( eFileLock==SHARED_LOCK );
-- assert( pFile->eFileLock==0 );
-- assert( pInode->nShared>0 );
-- pFile->eFileLock = SHARED_LOCK;
-- pInode->nShared++;
-- pInode->nLock++;
-- goto afp_end_lock;
-- }
-+ case EAGAIN:
-+ case ETIMEDOUT:
-+ case EBUSY:
-+ case EINTR:
-+ case ENOLCK:
-+ /* random NFS retry error, unless during file system support
-+ * introspection, in which it actually means what it says */
-+ return SQLITE_BUSY;
-
-- /* A PENDING lock is needed before acquiring a SHARED lock and before
-- ** acquiring an EXCLUSIVE lock. For the SHARED lock, the PENDING will
-- ** be released.
-- */
-- if( eFileLock==SHARED_LOCK
-- || (eFileLock==EXCLUSIVE_LOCK && pFile->eFileLock<PENDING_LOCK)
-- ){
-- int failed;
-- failed = afpSetLock(context->dbPath, pFile, PENDING_BYTE, 1, 1);
-- if (failed) {
-- rc = failed;
-- goto afp_end_lock;
-+ case EACCES:
-+ /* EACCES is like EAGAIN during locking operations, but not any other time*/
-+ if( (sqliteIOErr == SQLITE_IOERR_LOCK) ||
-+ (sqliteIOErr == SQLITE_IOERR_UNLOCK) ||
-+ (sqliteIOErr == SQLITE_IOERR_RDLOCK) ||
-+ (sqliteIOErr == SQLITE_IOERR_CHECKRESERVEDLOCK) ){
-+ return SQLITE_BUSY;
- }
-- }
--
-- /* If control gets to this point, then actually go ahead and make
-- ** operating system calls for the specified lock.
-- */
-- if( eFileLock==SHARED_LOCK ){
-- int lrc1, lrc2, lrc1Errno = 0;
-- long lk, mask;
-+ /* else fall through */
-+ case EPERM:
-+ return SQLITE_PERM;
-
-- assert( pInode->nShared==0 );
-- assert( pInode->eFileLock==0 );
--
-- mask = (sizeof(long)==8) ? LARGEST_INT64 : 0x7fffffff;
-- /* Now get the read-lock SHARED_LOCK */
-- /* note that the quality of the randomness doesn't matter that much */
-- lk = random();
-- pInode->sharedByte = (lk & mask)%(SHARED_SIZE - 1);
-- lrc1 = afpSetLock(context->dbPath, pFile,
-- SHARED_FIRST+pInode->sharedByte, 1, 1);
-- if( IS_LOCK_ERROR(lrc1) ){
-- lrc1Errno = pFile->lastErrno;
-- }
-- /* Drop the temporary PENDING lock */
-- lrc2 = afpSetLock(context->dbPath, pFile, PENDING_BYTE, 1, 0);
-+ /* EDEADLK is only possible if a call to fcntl(F_SETLKW) is made. And
-+ ** this module never makes such a call. And the code in SQLite itself
-+ ** asserts that SQLITE_IOERR_BLOCKED is never returned. For these reasons
-+ ** this case is also commented out. If the system does set errno to EDEADLK,
-+ ** the default SQLITE_IOERR_XXX code will be returned. */
-+#if 0
-+ case EDEADLK:
-+ return SQLITE_IOERR_BLOCKED;
-+#endif
-
-- if( IS_LOCK_ERROR(lrc1) ) {
-- pFile->lastErrno = lrc1Errno;
-- rc = lrc1;
-- goto afp_end_lock;
-- } else if( IS_LOCK_ERROR(lrc2) ){
-- rc = lrc2;
-- goto afp_end_lock;
-- } else if( lrc1 != SQLITE_OK ) {
-- rc = lrc1;
-- } else {
-- pFile->eFileLock = SHARED_LOCK;
-- pInode->nLock++;
-- pInode->nShared = 1;
-- }
-- }else if( eFileLock==EXCLUSIVE_LOCK && pInode->nShared>1 ){
-- /* We are trying for an exclusive lock but another thread in this
-- ** same process is still holding a shared lock. */
-- rc = SQLITE_BUSY;
-- }else{
-- /* The request was for a RESERVED or EXCLUSIVE lock. It is
-- ** assumed that there is a SHARED or greater lock on the file
-- ** already.
-- */
-- int failed = 0;
-- assert( 0!=pFile->eFileLock );
-- if (eFileLock >= RESERVED_LOCK && pFile->eFileLock < RESERVED_LOCK) {
-- /* Acquire a RESERVED lock */
-- failed = afpSetLock(context->dbPath, pFile, RESERVED_BYTE, 1,1);
-- if( !failed ){
-- context->reserved = 1;
-+#if EOPNOTSUPP!=ENOTSUP
-+ case EOPNOTSUPP:
-+ /* something went terribly awry, unless during file system support
-+ * introspection, in which it actually means what it says */
-+#endif
-+#ifdef ENOTSUP
-+ case ENOTSUP:
-+ /* invalid fd, unless during file system support introspection, in which
-+ * it actually means what it says */
-+#endif
-+ case EIO:
-+ case EBADF:
-+ case EINVAL:
-+ case ENOTCONN:
-+ case ENODEV:
-+ case ENXIO:
-+ case ENOENT:
-+#ifdef ESTALE /* ESTALE is not defined on Interix systems */
-+ case ESTALE:
-+#endif
-+ case ENOSYS:
-+ /* these should force the client to close the file and reconnect */
-+
-+ default:
-+ return sqliteIOErr;
-+ }
-+}
-+
-+
-+/******************************************************************************
-+****************** Begin Unique File ID Utility Used By VxWorks ***************
-+**
-+** On most versions of unix, we can get a unique ID for a file by concatenating
-+** the device number and the inode number. But this does not work on VxWorks.
-+** On VxWorks, a unique file id must be based on the canonical filename.
-+**
-+** A pointer to an instance of the following structure can be used as a
-+** unique file ID in VxWorks. Each instance of this structure contains
-+** a copy of the canonical filename. There is also a reference count.
-+** The structure is reclaimed when the number of pointers to it drops to
-+** zero.
-+**
-+** There are never very many files open at one time and lookups are not
-+** a performance-critical path, so it is sufficient to put these
-+** structures on a linked list.
-+*/
-+struct vxworksFileId {
-+ struct vxworksFileId *pNext; /* Next in a list of them all */
-+ int nRef; /* Number of references to this one */
-+ int nName; /* Length of the zCanonicalName[] string */
-+ char *zCanonicalName; /* Canonical filename */
-+};
-+
-+#if OS_VXWORKS
-+/*
-+** All unique filenames are held on a linked list headed by this
-+** variable:
-+*/
-+static struct vxworksFileId *vxworksFileList = 0;
-+
-+/*
-+** Simplify a filename into its canonical form
-+** by making the following changes:
-+**
-+** * removing any trailing and duplicate /
-+** * convert /./ into just /
-+** * convert /A/../ where A is any simple name into just /
-+**
-+** Changes are made in-place. Return the new name length.
-+**
-+** The original filename is in z[0..n-1]. Return the number of
-+** characters in the simplified name.
-+*/
-+static int vxworksSimplifyName(char *z, int n){
-+ int i, j;
-+ while( n>1 && z[n-1]=='/' ){ n--; }
-+ for(i=j=0; i<n; i++){
-+ if( z[i]=='/' ){
-+ if( z[i+1]=='/' ) continue;
-+ if( z[i+1]=='.' && i+2<n && z[i+2]=='/' ){
-+ i += 1;
-+ continue;
- }
-- }
-- if (!failed && eFileLock == EXCLUSIVE_LOCK) {
-- /* Acquire an EXCLUSIVE lock */
--
-- /* Remove the shared lock before trying the range. we'll need to
-- ** reestablish the shared lock if we can't get the afpUnlock
-- */
-- if( !(failed = afpSetLock(context->dbPath, pFile, SHARED_FIRST +
-- pInode->sharedByte, 1, 0)) ){
-- int failed2 = SQLITE_OK;
-- /* now attemmpt to get the exclusive lock range */
-- failed = afpSetLock(context->dbPath, pFile, SHARED_FIRST,
-- SHARED_SIZE, 1);
-- if( failed && (failed2 = afpSetLock(context->dbPath, pFile,
-- SHARED_FIRST + pInode->sharedByte, 1, 1)) ){
-- /* Can't reestablish the shared lock. Sqlite can't deal, this is
-- ** a critical I/O error
-- */
-- rc = ((failed & SQLITE_IOERR) == SQLITE_IOERR) ? failed2 :
-- SQLITE_IOERR_LOCK;
-- goto afp_end_lock;
-- }
-- }else{
-- rc = failed;
-+ if( z[i+1]=='.' && i+3<n && z[i+2]=='.' && z[i+3]=='/' ){
-+ while( j>0 && z[j-1]!='/' ){ j--; }
-+ if( j>0 ){ j--; }
-+ i += 2;
-+ continue;
- }
- }
-- if( failed ){
-- rc = failed;
-- }
-- }
--
-- if( rc==SQLITE_OK ){
-- pFile->eFileLock = eFileLock;
-- pInode->eFileLock = eFileLock;
-- }else if( eFileLock==EXCLUSIVE_LOCK ){
-- pFile->eFileLock = PENDING_LOCK;
-- pInode->eFileLock = PENDING_LOCK;
-+ z[j++] = z[i];
- }
--
--afp_end_lock:
-- unixLeaveMutex();
-- OSTRACE(("LOCK %d %s %s (afp)\n", pFile->h, azFileLock(eFileLock),
-- rc==SQLITE_OK ? "ok" : "failed"));
-- return rc;
-+ z[j] = 0;
-+ return j;
- }
-
- /*
--** Lower the locking level on file descriptor pFile to eFileLock. eFileLock
--** must be either NO_LOCK or SHARED_LOCK.
-+** Find a unique file ID for the given absolute pathname. Return
-+** a pointer to the vxworksFileId object. This pointer is the unique
-+** file ID.
- **
--** If the locking level of the file descriptor is already at or below
--** the requested locking level, this routine is a no-op.
-+** The nRef field of the vxworksFileId object is incremented before
-+** the object is returned. A new vxworksFileId object is created
-+** and added to the global list if necessary.
-+**
-+** If a memory allocation error occurs, return NULL.
- */
--static int afpUnlock(sqlite3_file *id, int eFileLock) {
-- int rc = SQLITE_OK;
-- unixFile *pFile = (unixFile*)id;
-- unixInodeInfo *pInode;
-- afpLockingContext *context = (afpLockingContext *) pFile->lockingContext;
-- int skipShared = 0;
--#ifdef SQLITE_TEST
-- int h = pFile->h;
--#endif
-+static struct vxworksFileId *vxworksFindFileId(const char *zAbsoluteName){
-+ struct vxworksFileId *pNew; /* search key and new file ID */
-+ struct vxworksFileId *pCandidate; /* For looping over existing file IDs */
-+ int n; /* Length of zAbsoluteName string */
-
-- assert( pFile );
-- OSTRACE(("UNLOCK %d %d was %d(%d,%d) pid=%d (afp)\n", pFile->h, eFileLock,
-- pFile->eFileLock, pFile->pInode->eFileLock, pFile->pInode->nShared,
-- getpid()));
-+ assert( zAbsoluteName[0]=='/' );
-+ n = (int)strlen(zAbsoluteName);
-+ pNew = sqlite3_malloc( sizeof(*pNew) + (n+1) );
-+ if( pNew==0 ) return 0;
-+ pNew->zCanonicalName = (char*)&pNew[1];
-+ memcpy(pNew->zCanonicalName, zAbsoluteName, n+1);
-+ n = vxworksSimplifyName(pNew->zCanonicalName, n);
-
-- assert( eFileLock<=SHARED_LOCK );
-- if( pFile->eFileLock<=eFileLock ){
-- return SQLITE_OK;
-- }
-+ /* Search for an existing entry that matching the canonical name.
-+ ** If found, increment the reference count and return a pointer to
-+ ** the existing file ID.
-+ */
- unixEnterMutex();
-- pInode = pFile->pInode;
-- assert( pInode->nShared!=0 );
-- if( pFile->eFileLock>SHARED_LOCK ){
-- assert( pInode->eFileLock==pFile->eFileLock );
-- SimulateIOErrorBenign(1);
-- SimulateIOError( h=(-1) )
-- SimulateIOErrorBenign(0);
--
--#ifdef SQLITE_DEBUG
-- /* When reducing a lock such that other processes can start
-- ** reading the database file again, make sure that the
-- ** transaction counter was updated if any part of the database
-- ** file changed. If the transaction counter is not updated,
-- ** other connections to the same file might not realize that
-- ** the file has changed and hence might not know to flush their
-- ** cache. The use of a stale cache can lead to database corruption.
-- */
-- assert( pFile->inNormalWrite==0
-- || pFile->dbUpdate==0
-- || pFile->transCntrChng==1 );
-- pFile->inNormalWrite = 0;
--#endif
--
-- if( pFile->eFileLock==EXCLUSIVE_LOCK ){
-- rc = afpSetLock(context->dbPath, pFile, SHARED_FIRST, SHARED_SIZE, 0);
-- if( rc==SQLITE_OK && (eFileLock==SHARED_LOCK || pInode->nShared>1) ){
-- /* only re-establish the shared lock if necessary */
-- int sharedLockByte = SHARED_FIRST+pInode->sharedByte;
-- rc = afpSetLock(context->dbPath, pFile, sharedLockByte, 1, 1);
-- } else {
-- skipShared = 1;
-- }
-- }
-- if( rc==SQLITE_OK && pFile->eFileLock>=PENDING_LOCK ){
-- rc = afpSetLock(context->dbPath, pFile, PENDING_BYTE, 1, 0);
-- }
-- if( rc==SQLITE_OK && pFile->eFileLock>=RESERVED_LOCK && context->reserved ){
-- rc = afpSetLock(context->dbPath, pFile, RESERVED_BYTE, 1, 0);
-- if( !rc ){
-- context->reserved = 0;
-- }
-- }
-- if( rc==SQLITE_OK && (eFileLock==SHARED_LOCK || pInode->nShared>1)){
-- pInode->eFileLock = SHARED_LOCK;
-+ for(pCandidate=vxworksFileList; pCandidate; pCandidate=pCandidate->pNext){
-+ if( pCandidate->nName==n
-+ && memcmp(pCandidate->zCanonicalName, pNew->zCanonicalName, n)==0
-+ ){
-+ sqlite3_free(pNew);
-+ pCandidate->nRef++;
-+ unixLeaveMutex();
-+ return pCandidate;
- }
- }
-- if( rc==SQLITE_OK && eFileLock==NO_LOCK ){
-
-- /* Decrement the shared lock counter. Release the lock using an
-- ** OS call only when all threads in this same process have released
-- ** the lock.
-- */
-- unsigned long long sharedLockByte = SHARED_FIRST+pInode->sharedByte;
-- pInode->nShared--;
-- if( pInode->nShared==0 ){
-- SimulateIOErrorBenign(1);
-- SimulateIOError( h=(-1) )
-- SimulateIOErrorBenign(0);
-- if( !skipShared ){
-- rc = afpSetLock(context->dbPath, pFile, sharedLockByte, 1, 0);
-- }
-- if( !rc ){
-- pInode->eFileLock = NO_LOCK;
-- pFile->eFileLock = NO_LOCK;
-- }
-- }
-- if( rc==SQLITE_OK ){
-- pInode->nLock--;
-- assert( pInode->nLock>=0 );
-- if( pInode->nLock==0 ){
-- closePendingFds(pFile);
-- }
-- }
-- }
--
-+ /* No match was found. We will make a new file ID */
-+ pNew->nRef = 1;
-+ pNew->nName = n;
-+ pNew->pNext = vxworksFileList;
-+ vxworksFileList = pNew;
- unixLeaveMutex();
-- if( rc==SQLITE_OK ) pFile->eFileLock = eFileLock;
-- return rc;
-+ return pNew;
- }
-
- /*
--** Close a file & cleanup AFP specific locking context
-+** Decrement the reference count on a vxworksFileId object. Free
-+** the object when the reference count reaches zero.
- */
--static int afpClose(sqlite3_file *id) {
-- int rc = SQLITE_OK;
-- if( id ){
-- unixFile *pFile = (unixFile*)id;
-- afpUnlock(id, NO_LOCK);
-- unixEnterMutex();
-- if( pFile->pInode && pFile->pInode->nLock ){
-- /* If there are outstanding locks, do not actually close the file just
-- ** yet because that would clear those locks. Instead, add the file
-- ** descriptor to pInode->aPending. It will be automatically closed when
-- ** the last lock is cleared.
-- */
-- setPendingFd(pFile);
-- }
-- releaseInodeInfo(pFile);
-- sqlite3_free(pFile->lockingContext);
-- rc = closeUnixFile(id);
-- unixLeaveMutex();
-+static void vxworksReleaseFileId(struct vxworksFileId *pId){
-+ unixEnterMutex();
-+ assert( pId->nRef>0 );
-+ pId->nRef--;
-+ if( pId->nRef==0 ){
-+ struct vxworksFileId **pp;
-+ for(pp=&vxworksFileList; *pp && *pp!=pId; pp = &((*pp)->pNext)){}
-+ assert( *pp==pId );
-+ *pp = pId->pNext;
-+ sqlite3_free(pId);
- }
-- return rc;
-+ unixLeaveMutex();
- }
--
--#endif /* defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE */
--/*
--** The code above is the AFP lock implementation. The code is specific
--** to MacOSX and does not work on other unix platforms. No alternative
--** is available. If you don't compile for a mac, then the "unix-afp"
--** VFS is not available.
--**
--********************* End of the AFP lock implementation **********************
-+#endif /* OS_VXWORKS */
-+/*************** End of Unique File ID Utility Used By VxWorks ****************
- ******************************************************************************/
-
--/******************************************************************************
--*************************** Begin NFS Locking ********************************/
--
--#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
--/*
-- ** Lower the locking level on file descriptor pFile to eFileLock. eFileLock
-- ** must be either NO_LOCK or SHARED_LOCK.
-- **
-- ** If the locking level of the file descriptor is already at or below
-- ** the requested locking level, this routine is a no-op.
-- */
--static int nfsUnlock(sqlite3_file *id, int eFileLock){
-- return posixUnlock(id, eFileLock, 1);
--}
--
--#endif /* defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE */
--/*
--** The code above is the NFS lock implementation. The code is specific
--** to MacOSX and does not work on other unix platforms. No alternative
--** is available.
--**
--********************* End of the NFS lock implementation **********************
--******************************************************************************/
-
- /******************************************************************************
--**************** Non-locking sqlite3_file methods *****************************
-+*************************** Posix Advisory Locking ****************************
- **
--** The next division contains implementations for all methods of the
--** sqlite3_file object other than the locking methods. The locking
--** methods were defined in divisions above (one locking method per
--** division). Those methods that are common to all locking modes
--** are gather together into this division.
-+** POSIX advisory locks are broken by design. ANSI STD 1003.1 (1996)
-+** section 6.5.2.2 lines 483 through 490 specify that when a process
-+** sets or clears a lock, that operation overrides any prior locks set
-+** by the same process. It does not explicitly say so, but this implies
-+** that it overrides locks set by the same process using a different
-+** file descriptor. Consider this test case:
-+**
-+** int fd1 = open("./file1", O_RDWR|O_CREAT, 0644);
-+** int fd2 = open("./file2", O_RDWR|O_CREAT, 0644);
-+**
-+** Suppose ./file1 and ./file2 are really the same file (because
-+** one is a hard or symbolic link to the other) then if you set
-+** an exclusive lock on fd1, then try to get an exclusive lock
-+** on fd2, it works. I would have expected the second lock to
-+** fail since there was already a lock on the file due to fd1.
-+** But not so. Since both locks came from the same process, the
-+** second overrides the first, even though they were on different
-+** file descriptors opened on different file names.
-+**
-+** This means that we cannot use POSIX locks to synchronize file access
-+** among competing threads of the same process. POSIX locks will work fine
-+** to synchronize access for threads in separate processes, but not
-+** threads within the same process.
-+**
-+** To work around the problem, SQLite has to manage file locks internally
-+** on its own. Whenever a new database is opened, we have to find the
-+** specific inode of the database file (the inode is determined by the
-+** st_dev and st_ino fields of the stat structure that fstat() fills in)
-+** and check for locks already existing on that inode. When locks are
-+** created or removed, we have to look at our own internal record of the
-+** locks to see if another thread has previously set a lock on that same
-+** inode.
-+**
-+** (Aside: The use of inode numbers as unique IDs does not work on VxWorks.
-+** For VxWorks, we have to use the alternative unique ID system based on
-+** canonical filename and implemented in the previous division.)
-+**
-+** The sqlite3_file structure for POSIX is no longer just an integer file
-+** descriptor. It is now a structure that holds the integer file
-+** descriptor and a pointer to a structure that describes the internal
-+** locks on the corresponding inode. There is one locking structure
-+** per inode, so if the same inode is opened twice, both unixFile structures
-+** point to the same locking structure. The locking structure keeps
-+** a reference count (so we will know when to delete it) and a "cnt"
-+** field that tells us its internal lock status. cnt==0 means the
-+** file is unlocked. cnt==-1 means the file has an exclusive lock.
-+** cnt>0 means there are cnt shared locks on the file.
-+**
-+** Any attempt to lock or unlock a file first checks the locking
-+** structure. The fcntl() system call is only invoked to set a
-+** POSIX lock if the internal lock structure transitions between
-+** a locked and an unlocked state.
-+**
-+** But wait: there are yet more problems with POSIX advisory locks.
-+**
-+** If you close a file descriptor that points to a file that has locks,
-+** all locks on that file that are owned by the current process are
-+** released. To work around this problem, each unixInodeInfo object
-+** maintains a count of the number of pending locks on tha inode.
-+** When an attempt is made to close an unixFile, if there are
-+** other unixFile open on the same inode that are holding locks, the call
-+** to close() the file descriptor is deferred until all of the locks clear.
-+** The unixInodeInfo structure keeps a list of file descriptors that need to
-+** be closed and that list is walked (and cleared) when the last lock
-+** clears.
-+**
-+** Yet another problem: LinuxThreads do not play well with posix locks.
-+**
-+** Many older versions of linux use the LinuxThreads library which is
-+** not posix compliant. Under LinuxThreads, a lock created by thread
-+** A cannot be modified or overridden by a different thread B.
-+** Only thread A can modify the lock. Locking behavior is correct
-+** if the appliation uses the newer Native Posix Thread Library (NPTL)
-+** on linux - with NPTL a lock created by thread A can override locks
-+** in thread B. But there is no way to know at compile-time which
-+** threading library is being used. So there is no way to know at
-+** compile-time whether or not thread A can override locks on thread B.
-+** One has to do a run-time check to discover the behavior of the
-+** current process.
-+**
-+** SQLite used to support LinuxThreads. But support for LinuxThreads
-+** was dropped beginning with version 3.7.0. SQLite will still work with
-+** LinuxThreads provided that (1) there is no more than one connection
-+** per database file in the same process and (2) database connections
-+** do not move across threads.
- */
-
- /*
--** Seek to the offset passed as the second argument, then read cnt
--** bytes into pBuf. Return the number of bytes actually read.
--**
--** NB: If you define USE_PREAD or USE_PREAD64, then it might also
--** be necessary to define _XOPEN_SOURCE to be 500. This varies from
--** one system to another. Since SQLite does not define USE_PREAD
--** any any form by default, we will not attempt to define _XOPEN_SOURCE.
--** See tickets #2741 and #2681.
--**
--** To avoid stomping the errno value on a failed read the lastErrno value
--** is set before returning.
-+** An instance of the following structure serves as the key used
-+** to locate a particular unixInodeInfo object.
- */
--static int seekAndRead(unixFile *id, sqlite3_int64 offset, void *pBuf, int cnt){
-- int got;
-- int prior = 0;
--#if (!defined(USE_PREAD) && !defined(USE_PREAD64))
-- i64 newOffset;
--#endif
-- TIMER_START;
-- assert( cnt==(cnt&0x1ffff) );
-- cnt &= 0x1ffff;
-- do{
--#if defined(USE_PREAD)
-- got = osPread(id->h, pBuf, cnt, offset);
-- SimulateIOError( got = -1 );
--#elif defined(USE_PREAD64)
-- got = osPread64(id->h, pBuf, cnt, offset);
-- SimulateIOError( got = -1 );
-+struct unixFileId {
-+ dev_t dev; /* Device number */
-+#if OS_VXWORKS
-+ struct vxworksFileId *pId; /* Unique file ID for vxworks. */
- #else
-- newOffset = lseek(id->h, offset, SEEK_SET);
-- SimulateIOError( newOffset-- );
-- if( newOffset!=offset ){
-- if( newOffset == -1 ){
-- ((unixFile*)id)->lastErrno = errno;
-- }else{
-- ((unixFile*)id)->lastErrno = 0;
-- }
-- return -1;
-- }
-- got = osRead(id->h, pBuf, cnt);
-+ ino_t ino; /* Inode number */
- #endif
-- if( got==cnt ) break;
-- if( got<0 ){
-- if( errno==EINTR ){ got = 1; continue; }
-- prior = 0;
-- ((unixFile*)id)->lastErrno = errno;
-- break;
-- }else if( got>0 ){
-- cnt -= got;
-- offset += got;
-- prior += got;
-- pBuf = (void*)(got + (char*)pBuf);
-- }
-- }while( got>0 );
-- TIMER_END;
-- OSTRACE(("READ %-3d %5d %7lld %llu\n",
-- id->h, got+prior, offset-prior, TIMER_ELAPSED));
-- return got+prior;
--}
-+};
-
- /*
--** Read data from a file into a buffer. Return SQLITE_OK if all
--** bytes were read successfully and SQLITE_IOERR if anything goes
--** wrong.
-+** An instance of the following structure is allocated for each open
-+** inode. Or, on LinuxThreads, there is one of these structures for
-+** each inode opened by each thread.
-+**
-+** A single inode can have multiple file descriptors, so each unixFile
-+** structure contains a pointer to an instance of this object and this
-+** object keeps a count of the number of unixFile pointing to it.
- */
--static int unixRead(
-- sqlite3_file *id,
-- void *pBuf,
-- int amt,
-- sqlite3_int64 offset
--){
-- unixFile *pFile = (unixFile *)id;
-- int got;
-- assert( id );
-- assert( offset>=0 );
-- assert( amt>0 );
--
-- /* If this is a database file (not a journal, master-journal or temp
-- ** file), the bytes in the locking range should never be read or written. */
--#if 0
-- assert( pFile->pUnused==0
-- || offset>=PENDING_BYTE+512
-- || offset+amt<=PENDING_BYTE
-- );
-+struct unixInodeInfo {
-+ struct unixFileId fileId; /* The lookup key */
-+ int nShared; /* Number of SHARED locks held */
-+ unsigned char eFileLock; /* One of SHARED_LOCK, RESERVED_LOCK etc. */
-+ unsigned char bProcessLock; /* An exclusive process lock is held */
-+ int nRef; /* Number of pointers to this structure */
-+ unixShmNode *pShmNode; /* Shared memory associated with this inode */
-+ int nLock; /* Number of outstanding file locks */
-+ UnixUnusedFd *pUnused; /* Unused file descriptors to close */
-+ unixInodeInfo *pNext; /* List of all unixInodeInfo objects */
-+ unixInodeInfo *pPrev; /* .... doubly linked */
-+#if SQLITE_ENABLE_LOCKING_STYLE
-+ unsigned long long sharedByte; /* for AFP simulated shared lock */
- #endif
--
--#if SQLITE_MAX_MMAP_SIZE>0
-- /* Deal with as much of this read request as possible by transfering
-- ** data from the memory mapping using memcpy(). */
-- if( offset<pFile->mmapSize ){
-- if( offset+amt <= pFile->mmapSize ){
-- memcpy(pBuf, &((u8 *)(pFile->pMapRegion))[offset], amt);
-- return SQLITE_OK;
-- }else{
-- int nCopy = pFile->mmapSize - offset;
-- memcpy(pBuf, &((u8 *)(pFile->pMapRegion))[offset], nCopy);
-- pBuf = &((u8 *)pBuf)[nCopy];
-- amt -= nCopy;
-- offset += nCopy;
-- }
-- }
-+#if OS_VXWORKS
-+ sem_t *pSem; /* Named POSIX semaphore */
-+ char aSemName[MAX_PATHNAME+2]; /* Name of that semaphore */
- #endif
-+};
-
-- got = seekAndRead(pFile, offset, pBuf, amt);
-- if( got==amt ){
-- return SQLITE_OK;
-- }else if( got<0 ){
-- /* lastErrno set by seekAndRead */
-- return SQLITE_IOERR_READ;
-- }else{
-- pFile->lastErrno = 0; /* not a system error */
-- /* Unread parts of the buffer must be zero-filled */
-- memset(&((char*)pBuf)[got], 0, amt-got);
-- return SQLITE_IOERR_SHORT_READ;
-- }
--}
-+/*
-+** A lists of all unixInodeInfo objects.
-+*/
-+static unixInodeInfo *inodeList = 0;
-
- /*
--** Attempt to seek the file-descriptor passed as the first argument to
--** absolute offset iOff, then attempt to write nBuf bytes of data from
--** pBuf to it. If an error occurs, return -1 and set *piErrno. Otherwise,
--** return the actual number of bytes written (which may be less than
--** nBuf).
-+**
-+** This function - unixLogError_x(), is only ever called via the macro
-+** unixLogError().
-+**
-+** It is invoked after an error occurs in an OS function and errno has been
-+** set. It logs a message using sqlite3_log() containing the current value of
-+** errno and, if possible, the human-readable equivalent from strerror() or
-+** strerror_r().
-+**
-+** The first argument passed to the macro should be the error code that
-+** will be returned to SQLite (e.g. SQLITE_IOERR_DELETE, SQLITE_CANTOPEN).
-+** The two subsequent arguments should be the name of the OS function that
-+** failed (e.g. "unlink", "open") and the associated file-system path,
-+** if any.
- */
--static int seekAndWriteFd(
-- int fd, /* File descriptor to write to */
-- i64 iOff, /* File offset to begin writing at */
-- const void *pBuf, /* Copy data from this buffer to the file */
-- int nBuf, /* Size of buffer pBuf in bytes */
-- int *piErrno /* OUT: Error number if error occurs */
-+#define unixLogError(a,b,c) unixLogErrorAtLine(a,b,c,__LINE__)
-+static int unixLogErrorAtLine(
-+ int errcode, /* SQLite error code */
-+ const char *zFunc, /* Name of OS function that failed */
-+ const char *zPath, /* File path associated with error */
-+ int iLine /* Source line number where error occurred */
- ){
-- int rc = 0; /* Value returned by system call */
-+ char *zErr; /* Message from strerror() or equivalent */
-+ int iErrno = errno; /* Saved syscall error number */
-
-- assert( nBuf==(nBuf&0x1ffff) );
-- nBuf &= 0x1ffff;
-- TIMER_START;
-+ /* If this is not a threadsafe build (SQLITE_THREADSAFE==0), then use
-+ ** the strerror() function to obtain the human-readable error message
-+ ** equivalent to errno. Otherwise, use strerror_r().
-+ */
-+#if SQLITE_THREADSAFE && defined(HAVE_STRERROR_R)
-+ char aErr[80];
-+ memset(aErr, 0, sizeof(aErr));
-+ zErr = aErr;
-
--#if defined(USE_PREAD)
-- do{ rc = osPwrite(fd, pBuf, nBuf, iOff); }while( rc<0 && errno==EINTR );
--#elif defined(USE_PREAD64)
-- do{ rc = osPwrite64(fd, pBuf, nBuf, iOff);}while( rc<0 && errno==EINTR);
--#else
-- do{
-- i64 iSeek = lseek(fd, iOff, SEEK_SET);
-- SimulateIOError( iSeek-- );
-+ /* If STRERROR_R_CHAR_P (set by autoconf scripts) or __USE_GNU is defined,
-+ ** assume that the system provides the GNU version of strerror_r() that
-+ ** returns a pointer to a buffer containing the error message. That pointer
-+ ** may point to aErr[], or it may point to some static storage somewhere.
-+ ** Otherwise, assume that the system provides the POSIX version of
-+ ** strerror_r(), which always writes an error message into aErr[].
-+ **
-+ ** If the code incorrectly assumes that it is the POSIX version that is
-+ ** available, the error message will often be an empty string. Not a
-+ ** huge problem. Incorrectly concluding that the GNU version is available
-+ ** could lead to a segfault though.
-+ */
-+#if defined(STRERROR_R_CHAR_P) || defined(__USE_GNU)
-+ zErr =
-+# endif
-+ strerror_r(iErrno, aErr, sizeof(aErr)-1);
-
-- if( iSeek!=iOff ){
-- if( piErrno ) *piErrno = (iSeek==-1 ? errno : 0);
-- return -1;
-- }
-- rc = osWrite(fd, pBuf, nBuf);
-- }while( rc<0 && errno==EINTR );
-+#elif SQLITE_THREADSAFE
-+ /* This is a threadsafe build, but strerror_r() is not available. */
-+ zErr = "";
-+#else
-+ /* Non-threadsafe build, use strerror(). */
-+ zErr = strerror(iErrno);
- #endif
-
-- TIMER_END;
-- OSTRACE(("WRITE %-3d %5d %7lld %llu\n", fd, rc, iOff, TIMER_ELAPSED));
-+ if( zPath==0 ) zPath = "";
-+ sqlite3_log(errcode,
-+ "os_unix.c:%d: (%d) %s(%s) - %s",
-+ iLine, iErrno, zFunc, zPath, zErr
-+ );
-
-- if( rc<0 && piErrno ) *piErrno = errno;
-- return rc;
-+ return errcode;
- }
-
--
- /*
--** Seek to the offset in id->offset then read cnt bytes into pBuf.
--** Return the number of bytes actually read. Update the offset.
-+** Close a file descriptor.
- **
--** To avoid stomping the errno value on a failed write the lastErrno value
--** is set before returning.
-+** We assume that close() almost always works, since it is only in a
-+** very sick application or on a very sick platform that it might fail.
-+** If it does fail, simply leak the file descriptor, but do log the
-+** error.
-+**
-+** Note that it is not safe to retry close() after EINTR since the
-+** file descriptor might have already been reused by another thread.
-+** So we don't even try to recover from an EINTR. Just log the error
-+** and move on.
- */
--static int seekAndWrite(unixFile *id, i64 offset, const void *pBuf, int cnt){
-- return seekAndWriteFd(id->h, offset, pBuf, cnt, &id->lastErrno);
-+static void robust_close(unixFile *pFile, int h, int lineno){
-+ if( osClose(h) ){
-+ unixLogErrorAtLine(SQLITE_IOERR_CLOSE, "close",
-+ pFile ? pFile->zPath : 0, lineno);
-+ }
- }
-
-+/*
-+** Close all file descriptors accumuated in the unixInodeInfo->pUnused list.
-+*/
-+static void closePendingFds(unixFile *pFile){
-+ unixInodeInfo *pInode = pFile->pInode;
-+ UnixUnusedFd *p;
-+ UnixUnusedFd *pNext;
-+ for(p=pInode->pUnused; p; p=pNext){
-+ pNext = p->pNext;
-+ robust_close(pFile, p->fd, __LINE__);
-+ sqlite3_free(p);
-+ }
-+ pInode->pUnused = 0;
-+}
-
- /*
--** Write data from a buffer into a file. Return SQLITE_OK on success
--** or some other error code on failure.
-+** Release a unixInodeInfo structure previously allocated by findInodeInfo().
-+**
-+** The mutex entered using the unixEnterMutex() function must be held
-+** when this function is called.
- */
--static int unixWrite(
-- sqlite3_file *id,
-- const void *pBuf,
-- int amt,
-- sqlite3_int64 offset
-+static void releaseInodeInfo(unixFile *pFile){
-+ unixInodeInfo *pInode = pFile->pInode;
-+ assert( unixMutexHeld() );
-+ if( ALWAYS(pInode) ){
-+ pInode->nRef--;
-+ if( pInode->nRef==0 ){
-+ assert( pInode->pShmNode==0 );
-+ closePendingFds(pFile);
-+ if( pInode->pPrev ){
-+ assert( pInode->pPrev->pNext==pInode );
-+ pInode->pPrev->pNext = pInode->pNext;
-+ }else{
-+ assert( inodeList==pInode );
-+ inodeList = pInode->pNext;
-+ }
-+ if( pInode->pNext ){
-+ assert( pInode->pNext->pPrev==pInode );
-+ pInode->pNext->pPrev = pInode->pPrev;
-+ }
-+ sqlite3_free(pInode);
-+ }
-+ }
-+}
-+
-+/*
-+** Given a file descriptor, locate the unixInodeInfo object that
-+** describes that file descriptor. Create a new one if necessary. The
-+** return value might be uninitialized if an error occurs.
-+**
-+** The mutex entered using the unixEnterMutex() function must be held
-+** when this function is called.
-+**
-+** Return an appropriate error code.
-+*/
-+static int findInodeInfo(
-+ unixFile *pFile, /* Unix file with file desc used in the key */
-+ unixInodeInfo **ppInode /* Return the unixInodeInfo object here */
- ){
-- unixFile *pFile = (unixFile*)id;
-- int wrote = 0;
-- assert( id );
-- assert( amt>0 );
-+ int rc; /* System call return code */
-+ int fd; /* The file descriptor for pFile */
-+ struct unixFileId fileId; /* Lookup key for the unixInodeInfo */
-+ struct stat statbuf; /* Low-level file information */
-+ unixInodeInfo *pInode = 0; /* Candidate unixInodeInfo object */
-
-- /* If this is a database file (not a journal, master-journal or temp
-- ** file), the bytes in the locking range should never be read or written. */
--#if 0
-- assert( pFile->pUnused==0
-- || offset>=PENDING_BYTE+512
-- || offset+amt<=PENDING_BYTE
-- );
--#endif
-+ assert( unixMutexHeld() );
-
--#ifdef SQLITE_DEBUG
-- /* If we are doing a normal write to a database file (as opposed to
-- ** doing a hot-journal rollback or a write to some file other than a
-- ** normal database file) then record the fact that the database
-- ** has changed. If the transaction counter is modified, record that
-- ** fact too.
-+ /* Get low-level information about the file that we can used to
-+ ** create a unique name for the file.
- */
-- if( pFile->inNormalWrite ){
-- pFile->dbUpdate = 1; /* The database has been modified */
-- if( offset<=24 && offset+amt>=27 ){
-- int rc;
-- char oldCntr[4];
-- SimulateIOErrorBenign(1);
-- rc = seekAndRead(pFile, 24, oldCntr, 4);
-- SimulateIOErrorBenign(0);
-- if( rc!=4 || memcmp(oldCntr, &((char*)pBuf)[24-offset], 4)!=0 ){
-- pFile->transCntrChng = 1; /* The transaction counter has changed */
-- }
-- }
-- }
-+ fd = pFile->h;
-+ rc = osFstat(fd, &statbuf);
-+ if( rc!=0 ){
-+ pFile->lastErrno = errno;
-+#ifdef EOVERFLOW
-+ if( pFile->lastErrno==EOVERFLOW ) return SQLITE_NOLFS;
- #endif
-+ return SQLITE_IOERR;
-+ }
-
--#if SQLITE_MAX_MMAP_SIZE>0
-- /* Deal with as much of this write request as possible by transfering
-- ** data from the memory mapping using memcpy(). */
-- if( offset<pFile->mmapSize ){
-- if( offset+amt <= pFile->mmapSize ){
-- memcpy(&((u8 *)(pFile->pMapRegion))[offset], pBuf, amt);
-- return SQLITE_OK;
-- }else{
-- int nCopy = pFile->mmapSize - offset;
-- memcpy(&((u8 *)(pFile->pMapRegion))[offset], pBuf, nCopy);
-- pBuf = &((u8 *)pBuf)[nCopy];
-- amt -= nCopy;
-- offset += nCopy;
-+#ifdef __APPLE__
-+ /* On OS X on an msdos filesystem, the inode number is reported
-+ ** incorrectly for zero-size files. See ticket #3260. To work
-+ ** around this problem (we consider it a bug in OS X, not SQLite)
-+ ** we always increase the file size to 1 by writing a single byte
-+ ** prior to accessing the inode number. The one byte written is
-+ ** an ASCII 'S' character which also happens to be the first byte
-+ ** in the header of every SQLite database. In this way, if there
-+ ** is a race condition such that another thread has already populated
-+ ** the first page of the database, no damage is done.
-+ */
-+ if( statbuf.st_size==0 && (pFile->fsFlags & SQLITE_FSFLAGS_IS_MSDOS)!=0 ){
-+ do{ rc = osWrite(fd, "S", 1); }while( rc<0 && errno==EINTR );
-+ if( rc!=1 ){
-+ pFile->lastErrno = errno;
-+ return SQLITE_IOERR;
-+ }
-+ rc = osFstat(fd, &statbuf);
-+ if( rc!=0 ){
-+ pFile->lastErrno = errno;
-+ return SQLITE_IOERR;
- }
- }
- #endif
-
-- while( amt>0 && (wrote = seekAndWrite(pFile, offset, pBuf, amt))>0 ){
-- amt -= wrote;
-- offset += wrote;
-- pBuf = &((char*)pBuf)[wrote];
-+ memset(&fileId, 0, sizeof(fileId));
-+ fileId.dev = statbuf.st_dev;
-+#if OS_VXWORKS
-+ fileId.pId = pFile->pId;
-+#else
-+ fileId.ino = statbuf.st_ino;
-+#endif
-+ pInode = inodeList;
-+ while( pInode && memcmp(&fileId, &pInode->fileId, sizeof(fileId)) ){
-+ pInode = pInode->pNext;
- }
-- SimulateIOError(( wrote=(-1), amt=1 ));
-- SimulateDiskfullError(( wrote=0, amt=1 ));
--
-- if( amt>0 ){
-- if( wrote<0 && pFile->lastErrno!=ENOSPC ){
-- /* lastErrno set by seekAndWrite */
-- return SQLITE_IOERR_WRITE;
-- }else{
-- pFile->lastErrno = 0; /* not a system error */
-- return SQLITE_FULL;
-+ if( pInode==0 ){
-+ pInode = sqlite3_malloc( sizeof(*pInode) );
-+ if( pInode==0 ){
-+ return SQLITE_NOMEM;
- }
-+ memset(pInode, 0, sizeof(*pInode));
-+ memcpy(&pInode->fileId, &fileId, sizeof(fileId));
-+ pInode->nRef = 1;
-+ pInode->pNext = inodeList;
-+ pInode->pPrev = 0;
-+ if( inodeList ) inodeList->pPrev = pInode;
-+ inodeList = pInode;
-+ }else{
-+ pInode->nRef++;
- }
--
-+ *ppInode = pInode;
- return SQLITE_OK;
- }
-
--#ifdef SQLITE_TEST
--/*
--** Count the number of fullsyncs and normal syncs. This is used to test
--** that syncs and fullsyncs are occurring at the right times.
--*/
--SQLITE_API int sqlite3_sync_count = 0;
--SQLITE_API int sqlite3_fullsync_count = 0;
--#endif
--
--/*
--** We do not trust systems to provide a working fdatasync(). Some do.
--** Others do no. To be safe, we will stick with the (slightly slower)
--** fsync(). If you know that your system does support fdatasync() correctly,
--** then simply compile with -Dfdatasync=fdatasync
--*/
--#if !defined(fdatasync)
--# define fdatasync fsync
--#endif
-
- /*
--** Define HAVE_FULLFSYNC to 0 or 1 depending on whether or not
--** the F_FULLFSYNC macro is defined. F_FULLFSYNC is currently
--** only available on Mac OS X. But that could change.
-+** Check a unixFile that is a database. Verify the following:
-+**
-+** (1) There is exactly one hard link on the file
-+** (2) The file is not a symbolic link
-+** (3) The file has not been renamed or unlinked
-+**
-+** Issue sqlite3_log(SQLITE_WARNING,...) messages if anything is not right.
- */
--#ifdef F_FULLFSYNC
--# define HAVE_FULLFSYNC 1
--#else
--# define HAVE_FULLFSYNC 0
--#endif
-+static void verifyDbFile(unixFile *pFile){
-+ struct stat buf;
-+ int rc;
-+ if( pFile->ctrlFlags & UNIXFILE_WARNED ){
-+ /* One or more of the following warnings have already been issued. Do not
-+ ** repeat them so as not to clutter the error log */
-+ return;
-+ }
-+ rc = osFstat(pFile->h, &buf);
-+ if( rc!=0 ){
-+ sqlite3_log(SQLITE_WARNING, "cannot fstat db file %s", pFile->zPath);
-+ pFile->ctrlFlags |= UNIXFILE_WARNED;
-+ return;
-+ }
-+ if( buf.st_nlink==0 && (pFile->ctrlFlags & UNIXFILE_DELETE)==0 ){
-+ sqlite3_log(SQLITE_WARNING, "file unlinked while open: %s", pFile->zPath);
-+ pFile->ctrlFlags |= UNIXFILE_WARNED;
-+ return;
-+ }
-+ if( buf.st_nlink>1 ){
-+ sqlite3_log(SQLITE_WARNING, "multiple links to file: %s", pFile->zPath);
-+ pFile->ctrlFlags |= UNIXFILE_WARNED;
-+ return;
-+ }
-+ if( pFile->pInode!=0
-+ && ((rc = osStat(pFile->zPath, &buf))!=0
-+ || buf.st_ino!=pFile->pInode->fileId.ino)
-+ ){
-+ sqlite3_log(SQLITE_WARNING, "file renamed while open: %s", pFile->zPath);
-+ pFile->ctrlFlags |= UNIXFILE_WARNED;
-+ return;
-+ }
-+}
-
-
- /*
--** The fsync() system call does not work as advertised on many
--** unix systems. The following procedure is an attempt to make
--** it work better.
--**
--** The SQLITE_NO_SYNC macro disables all fsync()s. This is useful
--** for testing when we want to run through the test suite quickly.
--** You are strongly advised *not* to deploy with SQLITE_NO_SYNC
--** enabled, however, since with SQLITE_NO_SYNC enabled, an OS crash
--** or power failure will likely corrupt the database file.
--**
--** SQLite sets the dataOnly flag if the size of the file is unchanged.
--** The idea behind dataOnly is that it should only write the file content
--** to disk, not the inode. We only set dataOnly if the file size is
--** unchanged since the file size is part of the inode. However,
--** Ted Ts'o tells us that fdatasync() will also write the inode if the
--** file size has changed. The only real difference between fdatasync()
--** and fsync(), Ted tells us, is that fdatasync() will not flush the
--** inode if the mtime or owner or other inode attributes have changed.
--** We only care about the file size, not the other file attributes, so
--** as far as SQLite is concerned, an fdatasync() is always adequate.
--** So, we always use fdatasync() if it is available, regardless of
--** the value of the dataOnly flag.
-+** This routine checks if there is a RESERVED lock held on the specified
-+** file by this or any other process. If such a lock is held, set *pResOut
-+** to a non-zero value otherwise *pResOut is set to zero. The return value
-+** is set to SQLITE_OK unless an I/O error occurs during lock checking.
- */
--static int full_fsync(int fd, int fullSync, int dataOnly){
-- int rc;
-+static int unixCheckReservedLock(sqlite3_file *id, int *pResOut){
-+ int rc = SQLITE_OK;
-+ int reserved = 0;
-+ unixFile *pFile = (unixFile*)id;
-
-- /* The following "ifdef/elif/else/" block has the same structure as
-- ** the one below. It is replicated here solely to avoid cluttering
-- ** up the real code with the UNUSED_PARAMETER() macros.
-- */
--#ifdef SQLITE_NO_SYNC
-- UNUSED_PARAMETER(fd);
-- UNUSED_PARAMETER(fullSync);
-- UNUSED_PARAMETER(dataOnly);
--#elif HAVE_FULLFSYNC
-- UNUSED_PARAMETER(dataOnly);
--#else
-- UNUSED_PARAMETER(fullSync);
-- UNUSED_PARAMETER(dataOnly);
--#endif
-+ SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
-
-- /* Record the number of times that we do a normal fsync() and
-- ** FULLSYNC. This is used during testing to verify that this procedure
-- ** gets called with the correct arguments.
-- */
--#ifdef SQLITE_TEST
-- if( fullSync ) sqlite3_fullsync_count++;
-- sqlite3_sync_count++;
--#endif
-+ assert( pFile );
-+ unixEnterMutex(); /* Because pFile->pInode is shared across threads */
-
-- /* If we compiled with the SQLITE_NO_SYNC flag, then syncing is a
-- ** no-op
-- */
--#ifdef SQLITE_NO_SYNC
-- rc = SQLITE_OK;
--#elif HAVE_FULLFSYNC
-- if( fullSync ){
-- rc = osFcntl(fd, F_FULLFSYNC, 0);
-- }else{
-- rc = 1;
-+ /* Check if a thread in this process holds such a lock */
-+ if( pFile->pInode->eFileLock>SHARED_LOCK ){
-+ reserved = 1;
- }
-- /* If the FULLFSYNC failed, fall back to attempting an fsync().
-- ** It shouldn't be possible for fullfsync to fail on the local
-- ** file system (on OSX), so failure indicates that FULLFSYNC
-- ** isn't supported for this file system. So, attempt an fsync
-- ** and (for now) ignore the overhead of a superfluous fcntl call.
-- ** It'd be better to detect fullfsync support once and avoid
-- ** the fcntl call every time sync is called.
-- */
-- if( rc ) rc = fsync(fd);
-
--#elif defined(__APPLE__)
-- /* fdatasync() on HFS+ doesn't yet flush the file size if it changed correctly
-- ** so currently we default to the macro that redefines fdatasync to fsync
-+ /* Otherwise see if some other process holds it.
- */
-- rc = fsync(fd);
--#else
-- rc = fdatasync(fd);
--#if OS_VXWORKS
-- if( rc==-1 && errno==ENOTSUP ){
-- rc = fsync(fd);
-+#ifndef __DJGPP__
-+ if( !reserved && !pFile->pInode->bProcessLock ){
-+ struct flock lock;
-+ lock.l_whence = SEEK_SET;
-+ lock.l_start = RESERVED_BYTE;
-+ lock.l_len = 1;
-+ lock.l_type = F_WRLCK;
-+ if( osFcntl(pFile->h, F_GETLK, &lock) ){
-+ rc = SQLITE_IOERR_CHECKRESERVEDLOCK;
-+ pFile->lastErrno = errno;
-+ } else if( lock.l_type!=F_UNLCK ){
-+ reserved = 1;
-+ }
- }
--#endif /* OS_VXWORKS */
--#endif /* ifdef SQLITE_NO_SYNC elif HAVE_FULLFSYNC */
-+#endif
-+
-+ unixLeaveMutex();
-+ OSTRACE(("TEST WR-LOCK %d %d %d (unix)\n", pFile->h, rc, reserved));
-
-- if( OS_VXWORKS && rc!= -1 ){
-- rc = 0;
-- }
-+ *pResOut = reserved;
- return rc;
- }
-
- /*
--** Open a file descriptor to the directory containing file zFilename.
--** If successful, *pFd is set to the opened file descriptor and
--** SQLITE_OK is returned. If an error occurs, either SQLITE_NOMEM
--** or SQLITE_CANTOPEN is returned and *pFd is set to an undefined
--** value.
--**
--** The directory file descriptor is used for only one thing - to
--** fsync() a directory to make sure file creation and deletion events
--** are flushed to disk. Such fsyncs are not needed on newer
--** journaling filesystems, but are required on older filesystems.
-+** Attempt to set a system-lock on the file pFile. The lock is
-+** described by pLock.
- **
--** This routine can be overridden using the xSetSysCall interface.
--** The ability to override this routine was added in support of the
--** chromium sandbox. Opening a directory is a security risk (we are
--** told) so making it overrideable allows the chromium sandbox to
--** replace this routine with a harmless no-op. To make this routine
--** a no-op, replace it with a stub that returns SQLITE_OK but leaves
--** *pFd set to a negative number.
-+** If the pFile was opened read/write from unix-excl, then the only lock
-+** ever obtained is an exclusive lock, and it is obtained exactly once
-+** the first time any lock is attempted. All subsequent system locking
-+** operations become no-ops. Locking operations still happen internally,
-+** in order to coordinate access between separate database connections
-+** within this process, but all of that is handled in memory and the
-+** operating system does not participate.
- **
--** If SQLITE_OK is returned, the caller is responsible for closing
--** the file descriptor *pFd using close().
--*/
--static int openDirectory(const char *zFilename, int *pFd){
-- int ii;
-- int fd = -1;
-- char zDirname[MAX_PATHNAME+1];
--
-- sqlite3_snprintf(MAX_PATHNAME, zDirname, "%s", zFilename);
-- for(ii=(int)strlen(zDirname); ii>1 && zDirname[ii]!='/'; ii--);
-- if( ii>0 ){
-- zDirname[ii] = '\0';
-- fd = robust_open(zDirname, O_RDONLY|O_BINARY, 0);
-- if( fd>=0 ){
-- OSTRACE(("OPENDIR %-3d %s\n", fd, zDirname));
-+** This function is a pass-through to fcntl(F_SETLK) if pFile is using
-+** any VFS other than "unix-excl" or if pFile is opened on "unix-excl"
-+** and is read-only.
-+**
-+** Zero is returned if the call completes successfully, or -1 if a call
-+** to fcntl() fails. In this case, errno is set appropriately (by fcntl()).
-+*/
-+static int unixFileLock(unixFile *pFile, struct flock *pLock){
-+ int rc;
-+ unixInodeInfo *pInode = pFile->pInode;
-+ assert( unixMutexHeld() );
-+ assert( pInode!=0 );
-+ if( ((pFile->ctrlFlags & UNIXFILE_EXCL)!=0 || pInode->bProcessLock)
-+ && ((pFile->ctrlFlags & UNIXFILE_RDONLY)==0)
-+ ){
-+ if( pInode->bProcessLock==0 ){
-+ struct flock lock;
-+ assert( pInode->nLock==0 );
-+ lock.l_whence = SEEK_SET;
-+ lock.l_start = SHARED_FIRST;
-+ lock.l_len = SHARED_SIZE;
-+ lock.l_type = F_WRLCK;
-+ rc = osFcntl(pFile->h, F_SETLK, &lock);
-+ if( rc<0 ) return rc;
-+ pInode->bProcessLock = 1;
-+ pInode->nLock++;
-+ }else{
-+ rc = 0;
- }
-+ }else{
-+ rc = osFcntl(pFile->h, F_SETLK, pLock);
- }
-- *pFd = fd;
-- return (fd>=0?SQLITE_OK:unixLogError(SQLITE_CANTOPEN_BKPT, "open", zDirname));
-+ return rc;
- }
-
- /*
--** Make sure all writes to a particular file are committed to disk.
-+** Lock the file with the lock specified by parameter eFileLock - one
-+** of the following:
- **
--** If dataOnly==0 then both the file itself and its metadata (file
--** size, access time, etc) are synced. If dataOnly!=0 then only the
--** file data is synced.
-+** (1) SHARED_LOCK
-+** (2) RESERVED_LOCK
-+** (3) PENDING_LOCK
-+** (4) EXCLUSIVE_LOCK
- **
--** Under Unix, also make sure that the directory entry for the file
--** has been created by fsync-ing the directory that contains the file.
--** If we do not do this and we encounter a power failure, the directory
--** entry for the journal might not exist after we reboot. The next
--** SQLite to access the file will not know that the journal exists (because
--** the directory entry for the journal was never created) and the transaction
--** will not roll back - possibly leading to database corruption.
-+** Sometimes when requesting one lock state, additional lock states
-+** are inserted in between. The locking might fail on one of the later
-+** transitions leaving the lock state different from what it started but
-+** still short of its goal. The following chart shows the allowed
-+** transitions and the inserted intermediate states:
-+**
-+** UNLOCKED -> SHARED
-+** SHARED -> RESERVED
-+** SHARED -> (PENDING) -> EXCLUSIVE
-+** RESERVED -> (PENDING) -> EXCLUSIVE
-+** PENDING -> EXCLUSIVE
-+**
-+** This routine will only increase a lock. Use the sqlite3OsUnlock()
-+** routine to lower a locking level.
- */
--static int unixSync(sqlite3_file *id, int flags){
-- int rc;
-+static int unixLock(sqlite3_file *id, int eFileLock){
-+ /* The following describes the implementation of the various locks and
-+ ** lock transitions in terms of the POSIX advisory shared and exclusive
-+ ** lock primitives (called read-locks and write-locks below, to avoid
-+ ** confusion with SQLite lock names). The algorithms are complicated
-+ ** slightly in order to be compatible with windows systems simultaneously
-+ ** accessing the same database file, in case that is ever required.
-+ **
-+ ** Symbols defined in os.h indentify the 'pending byte' and the 'reserved
-+ ** byte', each single bytes at well known offsets, and the 'shared byte
-+ ** range', a range of 510 bytes at a well known offset.
-+ **
-+ ** To obtain a SHARED lock, a read-lock is obtained on the 'pending
-+ ** byte'. If this is successful, a random byte from the 'shared byte
-+ ** range' is read-locked and the lock on the 'pending byte' released.
-+ **
-+ ** A process may only obtain a RESERVED lock after it has a SHARED lock.
-+ ** A RESERVED lock is implemented by grabbing a write-lock on the
-+ ** 'reserved byte'.
-+ **
-+ ** A process may only obtain a PENDING lock after it has obtained a
-+ ** SHARED lock. A PENDING lock is implemented by obtaining a write-lock
-+ ** on the 'pending byte'. This ensures that no new SHARED locks can be
-+ ** obtained, but existing SHARED locks are allowed to persist. A process
-+ ** does not have to obtain a RESERVED lock on the way to a PENDING lock.
-+ ** This property is used by the algorithm for rolling back a journal file
-+ ** after a crash.
-+ **
-+ ** An EXCLUSIVE lock, obtained after a PENDING lock is held, is
-+ ** implemented by obtaining a write-lock on the entire 'shared byte
-+ ** range'. Since all other locks require a read-lock on one of the bytes
-+ ** within this range, this ensures that no other locks are held on the
-+ ** database.
-+ **
-+ ** The reason a single byte cannot be used instead of the 'shared byte
-+ ** range' is that some versions of windows do not support read-locks. By
-+ ** locking a random byte from a range, concurrent SHARED locks may exist
-+ ** even if the locking primitive used is always a write-lock.
-+ */
-+ int rc = SQLITE_OK;
- unixFile *pFile = (unixFile*)id;
-+ unixInodeInfo *pInode;
-+ struct flock lock;
-+ int tErrno = 0;
-
-- int isDataOnly = (flags&SQLITE_SYNC_DATAONLY);
-- int isFullsync = (flags&0x0F)==SQLITE_SYNC_FULL;
-+ assert( pFile );
-+ OSTRACE(("LOCK %d %s was %s(%s,%d) pid=%d (unix)\n", pFile->h,
-+ azFileLock(eFileLock), azFileLock(pFile->eFileLock),
-+ azFileLock(pFile->pInode->eFileLock), pFile->pInode->nShared , getpid()));
-
-- /* Check that one of SQLITE_SYNC_NORMAL or FULL was passed */
-- assert((flags&0x0F)==SQLITE_SYNC_NORMAL
-- || (flags&0x0F)==SQLITE_SYNC_FULL
-- );
-+ /* If there is already a lock of this type or more restrictive on the
-+ ** unixFile, do nothing. Don't use the end_lock: exit path, as
-+ ** unixEnterMutex() hasn't been called yet.
-+ */
-+ if( pFile->eFileLock>=eFileLock ){
-+ OSTRACE(("LOCK %d %s ok (already held) (unix)\n", pFile->h,
-+ azFileLock(eFileLock)));
-+ return SQLITE_OK;
-+ }
-
-- /* Unix cannot, but some systems may return SQLITE_FULL from here. This
-- ** line is to test that doing so does not cause any problems.
-+ /* Make sure the locking sequence is correct.
-+ ** (1) We never move from unlocked to anything higher than shared lock.
-+ ** (2) SQLite never explicitly requests a pendig lock.
-+ ** (3) A shared lock is always held when a reserve lock is requested.
- */
-- SimulateDiskfullError( return SQLITE_FULL );
-+ assert( pFile->eFileLock!=NO_LOCK || eFileLock==SHARED_LOCK );
-+ assert( eFileLock!=PENDING_LOCK );
-+ assert( eFileLock!=RESERVED_LOCK || pFile->eFileLock==SHARED_LOCK );
-
-- assert( pFile );
-- OSTRACE(("SYNC %-3d\n", pFile->h));
-- rc = full_fsync(pFile->h, isFullsync, isDataOnly);
-- SimulateIOError( rc=1 );
-- if( rc ){
-- pFile->lastErrno = errno;
-- return unixLogError(SQLITE_IOERR_FSYNC, "full_fsync", pFile->zPath);
-+ /* This mutex is needed because pFile->pInode is shared across threads
-+ */
-+ unixEnterMutex();
-+ pInode = pFile->pInode;
-+
-+ /* If some thread using this PID has a lock via a different unixFile*
-+ ** handle that precludes the requested lock, return BUSY.
-+ */
-+ if( (pFile->eFileLock!=pInode->eFileLock &&
-+ (pInode->eFileLock>=PENDING_LOCK || eFileLock>SHARED_LOCK))
-+ ){
-+ rc = SQLITE_BUSY;
-+ goto end_lock;
- }
-
-- /* Also fsync the directory containing the file if the DIRSYNC flag
-- ** is set. This is a one-time occurrence. Many systems (examples: AIX)
-- ** are unable to fsync a directory, so ignore errors on the fsync.
-+ /* If a SHARED lock is requested, and some thread using this PID already
-+ ** has a SHARED or RESERVED lock, then increment reference counts and
-+ ** return SQLITE_OK.
- */
-- if( pFile->ctrlFlags & UNIXFILE_DIRSYNC ){
-- int dirfd;
-- OSTRACE(("DIRSYNC %s (have_fullfsync=%d fullsync=%d)\n", pFile->zPath,
-- HAVE_FULLFSYNC, isFullsync));
-- rc = osOpenDirectory(pFile->zPath, &dirfd);
-- if( rc==SQLITE_OK && dirfd>=0 ){
-- full_fsync(dirfd, 0, 0);
-- robust_close(pFile, dirfd, __LINE__);
-- }else if( rc==SQLITE_CANTOPEN ){
-- rc = SQLITE_OK;
-- }
-- pFile->ctrlFlags &= ~UNIXFILE_DIRSYNC;
-+ if( eFileLock==SHARED_LOCK &&
-+ (pInode->eFileLock==SHARED_LOCK || pInode->eFileLock==RESERVED_LOCK) ){
-+ assert( eFileLock==SHARED_LOCK );
-+ assert( pFile->eFileLock==0 );
-+ assert( pInode->nShared>0 );
-+ pFile->eFileLock = SHARED_LOCK;
-+ pInode->nShared++;
-+ pInode->nLock++;
-+ goto end_lock;
- }
-- return rc;
--}
-
--/*
--** Truncate an open file to a specified size
--*/
--static int unixTruncate(sqlite3_file *id, i64 nByte){
-- unixFile *pFile = (unixFile *)id;
-- int rc;
-- assert( pFile );
-- SimulateIOError( return SQLITE_IOERR_TRUNCATE );
-
-- /* If the user has configured a chunk-size for this file, truncate the
-- ** file so that it consists of an integer number of chunks (i.e. the
-- ** actual file size after the operation may be larger than the requested
-- ** size).
-+ /* A PENDING lock is needed before acquiring a SHARED lock and before
-+ ** acquiring an EXCLUSIVE lock. For the SHARED lock, the PENDING will
-+ ** be released.
- */
-- if( pFile->szChunk>0 ){
-- nByte = ((nByte + pFile->szChunk - 1)/pFile->szChunk) * pFile->szChunk;
-+ lock.l_len = 1L;
-+ lock.l_whence = SEEK_SET;
-+ if( eFileLock==SHARED_LOCK
-+ || (eFileLock==EXCLUSIVE_LOCK && pFile->eFileLock<PENDING_LOCK)
-+ ){
-+ lock.l_type = (eFileLock==SHARED_LOCK?F_RDLCK:F_WRLCK);
-+ lock.l_start = PENDING_BYTE;
-+ if( unixFileLock(pFile, &lock) ){
-+ tErrno = errno;
-+ rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
-+ if( rc!=SQLITE_BUSY ){
-+ pFile->lastErrno = tErrno;
-+ }
-+ goto end_lock;
-+ }
- }
-
-- rc = robust_ftruncate(pFile->h, (off_t)nByte);
-- if( rc ){
-- pFile->lastErrno = errno;
-- return unixLogError(SQLITE_IOERR_TRUNCATE, "ftruncate", pFile->zPath);
-- }else{
--#ifdef SQLITE_DEBUG
-- /* If we are doing a normal write to a database file (as opposed to
-- ** doing a hot-journal rollback or a write to some file other than a
-- ** normal database file) and we truncate the file to zero length,
-- ** that effectively updates the change counter. This might happen
-- ** when restoring a database using the backup API from a zero-length
-- ** source.
-- */
-- if( pFile->inNormalWrite && nByte==0 ){
-- pFile->transCntrChng = 1;
-+
-+ /* If control gets to this point, then actually go ahead and make
-+ ** operating system calls for the specified lock.
-+ */
-+ if( eFileLock==SHARED_LOCK ){
-+ assert( pInode->nShared==0 );
-+ assert( pInode->eFileLock==0 );
-+ assert( rc==SQLITE_OK );
-+
-+ /* Now get the read-lock */
-+ lock.l_start = SHARED_FIRST;
-+ lock.l_len = SHARED_SIZE;
-+ if( unixFileLock(pFile, &lock) ){
-+ tErrno = errno;
-+ rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
- }
--#endif
-
-- /* If the file was just truncated to a size smaller than the currently
-- ** mapped region, reduce the effective mapping size as well. SQLite will
-- ** use read() and write() to access data beyond this point from now on.
-+ /* Drop the temporary PENDING lock */
-+ lock.l_start = PENDING_BYTE;
-+ lock.l_len = 1L;
-+ lock.l_type = F_UNLCK;
-+ if( unixFileLock(pFile, &lock) && rc==SQLITE_OK ){
-+ /* This could happen with a network mount */
-+ tErrno = errno;
-+ rc = SQLITE_IOERR_UNLOCK;
-+ }
-+
-+ if( rc ){
-+ if( rc!=SQLITE_BUSY ){
-+ pFile->lastErrno = tErrno;
-+ }
-+ goto end_lock;
-+ }else{
-+ pFile->eFileLock = SHARED_LOCK;
-+ pInode->nLock++;
-+ pInode->nShared = 1;
-+ }
-+ }else if( eFileLock==EXCLUSIVE_LOCK && pInode->nShared>1 ){
-+ /* We are trying for an exclusive lock but another thread in this
-+ ** same process is still holding a shared lock. */
-+ rc = SQLITE_BUSY;
-+ }else{
-+ /* The request was for a RESERVED or EXCLUSIVE lock. It is
-+ ** assumed that there is a SHARED or greater lock on the file
-+ ** already.
- */
-- if( nByte<pFile->mmapSize ){
-- pFile->mmapSize = nByte;
-+ assert( 0!=pFile->eFileLock );
-+ lock.l_type = F_WRLCK;
-+
-+ assert( eFileLock==RESERVED_LOCK || eFileLock==EXCLUSIVE_LOCK );
-+ if( eFileLock==RESERVED_LOCK ){
-+ lock.l_start = RESERVED_BYTE;
-+ lock.l_len = 1L;
-+ }else{
-+ lock.l_start = SHARED_FIRST;
-+ lock.l_len = SHARED_SIZE;
- }
-
-- return SQLITE_OK;
-+ if( unixFileLock(pFile, &lock) ){
-+ tErrno = errno;
-+ rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
-+ if( rc!=SQLITE_BUSY ){
-+ pFile->lastErrno = tErrno;
-+ }
-+ }
- }
--}
-+
-
--/*
--** Determine the current size of a file in bytes
--*/
--static int unixFileSize(sqlite3_file *id, i64 *pSize){
-- int rc;
-- struct stat buf;
-- assert( id );
-- rc = osFstat(((unixFile*)id)->h, &buf);
-- SimulateIOError( rc=1 );
-- if( rc!=0 ){
-- ((unixFile*)id)->lastErrno = errno;
-- return SQLITE_IOERR_FSTAT;
-+#ifdef SQLITE_DEBUG
-+ /* Set up the transaction-counter change checking flags when
-+ ** transitioning from a SHARED to a RESERVED lock. The change
-+ ** from SHARED to RESERVED marks the beginning of a normal
-+ ** write operation (not a hot journal rollback).
-+ */
-+ if( rc==SQLITE_OK
-+ && pFile->eFileLock<=SHARED_LOCK
-+ && eFileLock==RESERVED_LOCK
-+ ){
-+ pFile->transCntrChng = 0;
-+ pFile->dbUpdate = 0;
-+ pFile->inNormalWrite = 1;
- }
-- *pSize = buf.st_size;
-+#endif
-
-- /* When opening a zero-size database, the findInodeInfo() procedure
-- ** writes a single byte into that file in order to work around a bug
-- ** in the OS-X msdos filesystem. In order to avoid problems with upper
-- ** layers, we need to report this file size as zero even though it is
-- ** really 1. Ticket #3260.
-- */
-- if( *pSize==1 ) *pSize = 0;
-
-+ if( rc==SQLITE_OK ){
-+ pFile->eFileLock = eFileLock;
-+ pInode->eFileLock = eFileLock;
-+ }else if( eFileLock==EXCLUSIVE_LOCK ){
-+ pFile->eFileLock = PENDING_LOCK;
-+ pInode->eFileLock = PENDING_LOCK;
-+ }
-
-- return SQLITE_OK;
-+end_lock:
-+ unixLeaveMutex();
-+ OSTRACE(("LOCK %d %s %s (unix)\n", pFile->h, azFileLock(eFileLock),
-+ rc==SQLITE_OK ? "ok" : "failed"));
-+ return rc;
- }
-
--#if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__)
- /*
--** Handler for proxy-locking file-control verbs. Defined below in the
--** proxying locking division.
-+** Add the file descriptor used by file handle pFile to the corresponding
-+** pUnused list.
- */
--static int proxyFileControl(sqlite3_file*,int,void*);
--#endif
-+static void setPendingFd(unixFile *pFile){
-+ unixInodeInfo *pInode = pFile->pInode;
-+ UnixUnusedFd *p = pFile->pUnused;
-+ p->pNext = pInode->pUnused;
-+ pInode->pUnused = p;
-+ pFile->h = -1;
-+ pFile->pUnused = 0;
-+}
-
--/*
--** This function is called to handle the SQLITE_FCNTL_SIZE_HINT
--** file-control operation. Enlarge the database to nBytes in size
--** (rounded up to the next chunk-size). If the database is already
--** nBytes or larger, this routine is a no-op.
-+/*
-+** Lower the locking level on file descriptor pFile to eFileLock. eFileLock
-+** must be either NO_LOCK or SHARED_LOCK.
-+**
-+** If the locking level of the file descriptor is already at or below
-+** the requested locking level, this routine is a no-op.
-+**
-+** If handleNFSUnlock is true, then on downgrading an EXCLUSIVE_LOCK to SHARED
-+** the byte range is divided into 2 parts and the first part is unlocked then
-+** set to a read lock, then the other part is simply unlocked. This works
-+** around a bug in BSD NFS lockd (also seen on MacOSX 10.3+) that fails to
-+** remove the write lock on a region when a read lock is set.
- */
--static int fcntlSizeHint(unixFile *pFile, i64 nByte){
-- if( pFile->szChunk>0 ){
-- i64 nSize; /* Required file size */
-- struct stat buf; /* Used to hold return values of fstat() */
--
-- if( osFstat(pFile->h, &buf) ) return SQLITE_IOERR_FSTAT;
-+static int posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){
-+ unixFile *pFile = (unixFile*)id;
-+ unixInodeInfo *pInode;
-+ struct flock lock;
-+ int rc = SQLITE_OK;
-
-- nSize = ((nByte+pFile->szChunk-1) / pFile->szChunk) * pFile->szChunk;
-- if( nSize>(i64)buf.st_size ){
-+ assert( pFile );
-+ OSTRACE(("UNLOCK %d %d was %d(%d,%d) pid=%d (unix)\n", pFile->h, eFileLock,
-+ pFile->eFileLock, pFile->pInode->eFileLock, pFile->pInode->nShared,
-+ getpid()));
-
--#if defined(HAVE_POSIX_FALLOCATE) && HAVE_POSIX_FALLOCATE
-- /* The code below is handling the return value of osFallocate()
-- ** correctly. posix_fallocate() is defined to "returns zero on success,
-- ** or an error number on failure". See the manpage for details. */
-- int err;
-- do{
-- err = osFallocate(pFile->h, buf.st_size, nSize-buf.st_size);
-- }while( err==EINTR );
-- if( err ) return SQLITE_IOERR_WRITE;
--#else
-- /* If the OS does not have posix_fallocate(), fake it. First use
-- ** ftruncate() to set the file size, then write a single byte to
-- ** the last byte in each block within the extended region. This
-- ** is the same technique used by glibc to implement posix_fallocate()
-- ** on systems that do not have a real fallocate() system call.
-- */
-- int nBlk = buf.st_blksize; /* File-system block size */
-- i64 iWrite; /* Next offset to write to */
-+ assert( eFileLock<=SHARED_LOCK );
-+ if( pFile->eFileLock<=eFileLock ){
-+ return SQLITE_OK;
-+ }
-+ unixEnterMutex();
-+ pInode = pFile->pInode;
-+ assert( pInode->nShared!=0 );
-+ if( pFile->eFileLock>SHARED_LOCK ){
-+ assert( pInode->eFileLock==pFile->eFileLock );
-
-- if( robust_ftruncate(pFile->h, nSize) ){
-- pFile->lastErrno = errno;
-- return unixLogError(SQLITE_IOERR_TRUNCATE, "ftruncate", pFile->zPath);
-- }
-- iWrite = ((buf.st_size + 2*nBlk - 1)/nBlk)*nBlk-1;
-- while( iWrite<nSize ){
-- int nWrite = seekAndWrite(pFile, iWrite, "", 1);
-- if( nWrite!=1 ) return SQLITE_IOERR_WRITE;
-- iWrite += nBlk;
-+#ifdef SQLITE_DEBUG
-+ /* When reducing a lock such that other processes can start
-+ ** reading the database file again, make sure that the
-+ ** transaction counter was updated if any part of the database
-+ ** file changed. If the transaction counter is not updated,
-+ ** other connections to the same file might not realize that
-+ ** the file has changed and hence might not know to flush their
-+ ** cache. The use of a stale cache can lead to database corruption.
-+ */
-+ pFile->inNormalWrite = 0;
-+#endif
-+
-+ /* downgrading to a shared lock on NFS involves clearing the write lock
-+ ** before establishing the readlock - to avoid a race condition we downgrade
-+ ** the lock in 2 blocks, so that part of the range will be covered by a
-+ ** write lock until the rest is covered by a read lock:
-+ ** 1: [WWWWW]
-+ ** 2: [....W]
-+ ** 3: [RRRRW]
-+ ** 4: [RRRR.]
-+ */
-+ if( eFileLock==SHARED_LOCK ){
-+
-+#if !defined(__APPLE__) || !SQLITE_ENABLE_LOCKING_STYLE
-+ (void)handleNFSUnlock;
-+ assert( handleNFSUnlock==0 );
-+#endif
-+#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
-+ if( handleNFSUnlock ){
-+ int tErrno; /* Error code from system call errors */
-+ off_t divSize = SHARED_SIZE - 1;
-+
-+ lock.l_type = F_UNLCK;
-+ lock.l_whence = SEEK_SET;
-+ lock.l_start = SHARED_FIRST;
-+ lock.l_len = divSize;
-+ if( unixFileLock(pFile, &lock)==(-1) ){
-+ tErrno = errno;
-+ rc = SQLITE_IOERR_UNLOCK;
-+ if( IS_LOCK_ERROR(rc) ){
-+ pFile->lastErrno = tErrno;
-+ }
-+ goto end_unlock;
-+ }
-+ lock.l_type = F_RDLCK;
-+ lock.l_whence = SEEK_SET;
-+ lock.l_start = SHARED_FIRST;
-+ lock.l_len = divSize;
-+ if( unixFileLock(pFile, &lock)==(-1) ){
-+ tErrno = errno;
-+ rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_RDLOCK);
-+ if( IS_LOCK_ERROR(rc) ){
-+ pFile->lastErrno = tErrno;
-+ }
-+ goto end_unlock;
-+ }
-+ lock.l_type = F_UNLCK;
-+ lock.l_whence = SEEK_SET;
-+ lock.l_start = SHARED_FIRST+divSize;
-+ lock.l_len = SHARED_SIZE-divSize;
-+ if( unixFileLock(pFile, &lock)==(-1) ){
-+ tErrno = errno;
-+ rc = SQLITE_IOERR_UNLOCK;
-+ if( IS_LOCK_ERROR(rc) ){
-+ pFile->lastErrno = tErrno;
-+ }
-+ goto end_unlock;
-+ }
-+ }else
-+#endif /* defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE */
-+ {
-+ lock.l_type = F_RDLCK;
-+ lock.l_whence = SEEK_SET;
-+ lock.l_start = SHARED_FIRST;
-+ lock.l_len = SHARED_SIZE;
-+ if( unixFileLock(pFile, &lock) ){
-+ /* In theory, the call to unixFileLock() cannot fail because another
-+ ** process is holding an incompatible lock. If it does, this
-+ ** indicates that the other process is not following the locking
-+ ** protocol. If this happens, return SQLITE_IOERR_RDLOCK. Returning
-+ ** SQLITE_BUSY would confuse the upper layer (in practice it causes
-+ ** an assert to fail). */
-+ rc = SQLITE_IOERR_RDLOCK;
-+ pFile->lastErrno = errno;
-+ goto end_unlock;
-+ }
- }
--#endif
-+ }
-+ lock.l_type = F_UNLCK;
-+ lock.l_whence = SEEK_SET;
-+ lock.l_start = PENDING_BYTE;
-+ lock.l_len = 2L; assert( PENDING_BYTE+1==RESERVED_BYTE );
-+ if( unixFileLock(pFile, &lock)==0 ){
-+ pInode->eFileLock = SHARED_LOCK;
-+ }else{
-+ rc = SQLITE_IOERR_UNLOCK;
-+ pFile->lastErrno = errno;
-+ goto end_unlock;
- }
- }
--
-- if( pFile->mmapSizeMax>0 && nByte>pFile->mmapSize ){
-- int rc;
-- if( pFile->szChunk<=0 ){
-- if( robust_ftruncate(pFile->h, nByte) ){
-+ if( eFileLock==NO_LOCK ){
-+ /* Decrement the shared lock counter. Release the lock using an
-+ ** OS call only when all threads in this same process have released
-+ ** the lock.
-+ */
-+ pInode->nShared--;
-+ if( pInode->nShared==0 ){
-+ lock.l_type = F_UNLCK;
-+ lock.l_whence = SEEK_SET;
-+ lock.l_start = lock.l_len = 0L;
-+ if( unixFileLock(pFile, &lock)==0 ){
-+ pInode->eFileLock = NO_LOCK;
-+ }else{
-+ rc = SQLITE_IOERR_UNLOCK;
- pFile->lastErrno = errno;
-- return unixLogError(SQLITE_IOERR_TRUNCATE, "ftruncate", pFile->zPath);
-+ pInode->eFileLock = NO_LOCK;
-+ pFile->eFileLock = NO_LOCK;
- }
- }
-
-- rc = unixMapfile(pFile, nByte);
-- return rc;
-+ /* Decrement the count of locks against this same file. When the
-+ ** count reaches zero, close any other file descriptors whose close
-+ ** was deferred because of outstanding locks.
-+ */
-+ pInode->nLock--;
-+ assert( pInode->nLock>=0 );
-+ if( pInode->nLock==0 ){
-+ closePendingFds(pFile);
-+ }
- }
-
-- return SQLITE_OK;
-+end_unlock:
-+ unixLeaveMutex();
-+ if( rc==SQLITE_OK ) pFile->eFileLock = eFileLock;
-+ return rc;
- }
-
- /*
--** If *pArg is inititially negative then this is a query. Set *pArg to
--** 1 or 0 depending on whether or not bit mask of pFile->ctrlFlags is set.
-+** Lower the locking level on file descriptor pFile to eFileLock. eFileLock
-+** must be either NO_LOCK or SHARED_LOCK.
- **
--** If *pArg is 0 or 1, then clear or set the mask bit of pFile->ctrlFlags.
-+** If the locking level of the file descriptor is already at or below
-+** the requested locking level, this routine is a no-op.
- */
--static void unixModeBit(unixFile *pFile, unsigned char mask, int *pArg){
-- if( *pArg<0 ){
-- *pArg = (pFile->ctrlFlags & mask)!=0;
-- }else if( (*pArg)==0 ){
-- pFile->ctrlFlags &= ~mask;
-- }else{
-- pFile->ctrlFlags |= mask;
-- }
-+static int unixUnlock(sqlite3_file *id, int eFileLock){
-+ assert( eFileLock==SHARED_LOCK || ((unixFile *)id)->nFetchOut==0 );
-+ return posixUnlock(id, eFileLock, 0);
- }
-
--/* Forward declaration */
--static int unixGetTempname(int nBuf, char *zBuf);
-+static int unixMapfile(unixFile *pFd, i64 nByte);
-+static void unixUnmapfile(unixFile *pFd);
-
- /*
--** Information and control of an open file handle.
-+** This function performs the parts of the "close file" operation
-+** common to all locking schemes. It closes the directory and file
-+** handles, if they are valid, and sets all fields of the unixFile
-+** structure to 0.
-+**
-+** It is *not* necessary to hold the mutex when this routine is called,
-+** even on VxWorks. A mutex will be acquired on VxWorks by the
-+** vxworksReleaseFileId() routine.
- */
--static int unixFileControl(sqlite3_file *id, int op, void *pArg){
-+static int closeUnixFile(sqlite3_file *id){
- unixFile *pFile = (unixFile*)id;
-- switch( op ){
-- case SQLITE_FCNTL_LOCKSTATE: {
-- *(int*)pArg = pFile->eFileLock;
-- return SQLITE_OK;
-- }
-- case SQLITE_LAST_ERRNO: {
-- *(int*)pArg = pFile->lastErrno;
-- return SQLITE_OK;
-- }
-- case SQLITE_FCNTL_CHUNK_SIZE: {
-- pFile->szChunk = *(int *)pArg;
-- return SQLITE_OK;
-- }
-- case SQLITE_FCNTL_SIZE_HINT: {
-- int rc;
-- SimulateIOErrorBenign(1);
-- rc = fcntlSizeHint(pFile, *(i64 *)pArg);
-- SimulateIOErrorBenign(0);
-- return rc;
-- }
-- case SQLITE_FCNTL_PERSIST_WAL: {
-- unixModeBit(pFile, UNIXFILE_PERSIST_WAL, (int*)pArg);
-- return SQLITE_OK;
-- }
-- case SQLITE_FCNTL_POWERSAFE_OVERWRITE: {
-- unixModeBit(pFile, UNIXFILE_PSOW, (int*)pArg);
-- return SQLITE_OK;
-- }
-- case SQLITE_FCNTL_VFSNAME: {
-- *(char**)pArg = sqlite3_mprintf("%s", pFile->pVfs->zName);
-- return SQLITE_OK;
-- }
-- case SQLITE_FCNTL_TEMPFILENAME: {
-- char *zTFile = sqlite3_malloc( pFile->pVfs->mxPathname );
-- if( zTFile ){
-- unixGetTempname(pFile->pVfs->mxPathname, zTFile);
-- *(char**)pArg = zTFile;
-- }
-- return SQLITE_OK;
-- }
-- case SQLITE_FCNTL_MMAP_SIZE: {
-- i64 newLimit = *(i64*)pArg;
-- if( newLimit>sqlite3GlobalConfig.mxMmap ){
-- newLimit = sqlite3GlobalConfig.mxMmap;
-- }
-- *(i64*)pArg = pFile->mmapSizeMax;
-- if( newLimit>=0 ){
-- pFile->mmapSizeMax = newLimit;
-- if( newLimit<pFile->mmapSize ) pFile->mmapSize = newLimit;
-- }
-- return SQLITE_OK;
-- }
--#ifdef SQLITE_DEBUG
-- /* The pager calls this method to signal that it has done
-- ** a rollback and that the database is therefore unchanged and
-- ** it hence it is OK for the transaction change counter to be
-- ** unchanged.
-- */
-- case SQLITE_FCNTL_DB_UNCHANGED: {
-- ((unixFile*)id)->dbUpdate = 0;
-- return SQLITE_OK;
-- }
--#endif
--#if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__)
-- case SQLITE_SET_LOCKPROXYFILE:
-- case SQLITE_GET_LOCKPROXYFILE: {
-- return proxyFileControl(id,op,pArg);
-+ unixUnmapfile(pFile);
-+ if( pFile->h>=0 ){
-+ robust_close(pFile, pFile->h, __LINE__);
-+ pFile->h = -1;
-+ }
-+#if OS_VXWORKS
-+ if( pFile->pId ){
-+ if( pFile->ctrlFlags & UNIXFILE_DELETE ){
-+ osUnlink(pFile->pId->zCanonicalName);
- }
--#endif /* SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__) */
-+ vxworksReleaseFileId(pFile->pId);
-+ pFile->pId = 0;
- }
-- return SQLITE_NOTFOUND;
-+#endif
-+ OSTRACE(("CLOSE %-3d\n", pFile->h));
-+ OpenCounter(-1);
-+ sqlite3_free(pFile->pUnused);
-+ memset(pFile, 0, sizeof(unixFile));
-+ return SQLITE_OK;
- }
-
- /*
--** Return the sector size in bytes of the underlying block device for
--** the specified file. This is almost always 512 bytes, but may be
--** larger for some devices.
--**
--** SQLite code assumes this function cannot fail. It also assumes that
--** if two files are created in the same file-system directory (i.e.
--** a database and its journal file) that the sector size will be the
--** same for both.
-+** Close a file.
- */
--#ifndef __QNXNTO__
--static int unixSectorSize(sqlite3_file *NotUsed){
-- UNUSED_PARAMETER(NotUsed);
-- return SQLITE_DEFAULT_SECTOR_SIZE;
-+static int unixClose(sqlite3_file *id){
-+ int rc = SQLITE_OK;
-+ unixFile *pFile = (unixFile *)id;
-+ verifyDbFile(pFile);
-+ unixUnlock(id, NO_LOCK);
-+ unixEnterMutex();
-+
-+ /* unixFile.pInode is always valid here. Otherwise, a different close
-+ ** routine (e.g. nolockClose()) would be called instead.
-+ */
-+ assert( pFile->pInode->nLock>0 || pFile->pInode->bProcessLock==0 );
-+ if( ALWAYS(pFile->pInode) && pFile->pInode->nLock ){
-+ /* If there are outstanding locks, do not actually close the file just
-+ ** yet because that would clear those locks. Instead, add the file
-+ ** descriptor to pInode->pUnused list. It will be automatically closed
-+ ** when the last lock is cleared.
-+ */
-+ setPendingFd(pFile);
-+ }
-+ releaseInodeInfo(pFile);
-+ rc = closeUnixFile(id);
-+ unixLeaveMutex();
-+ return rc;
- }
--#endif
-
--/*
--** The following version of unixSectorSize() is optimized for QNX.
-+/************** End of the posix advisory lock implementation *****************
-+******************************************************************************/
-+
-+/******************************************************************************
-+****************************** No-op Locking **********************************
-+**
-+** Of the various locking implementations available, this is by far the
-+** simplest: locking is ignored. No attempt is made to lock the database
-+** file for reading or writing.
-+**
-+** This locking mode is appropriate for use on read-only databases
-+** (ex: databases that are burned into CD-ROM, for example.) It can
-+** also be used if the application employs some external mechanism to
-+** prevent simultaneous access of the same database by two or more
-+** database connections. But there is a serious risk of database
-+** corruption if this locking mode is used in situations where multiple
-+** database connections are accessing the same database file at the same
-+** time and one or more of those connections are writing.
- */
--#ifdef __QNXNTO__
--#include <sys/dcmd_blk.h>
--#include <sys/statvfs.h>
--static int unixSectorSize(sqlite3_file *id){
-- unixFile *pFile = (unixFile*)id;
-- if( pFile->sectorSize == 0 ){
-- struct statvfs fsInfo;
--
-- /* Set defaults for non-supported filesystems */
-- pFile->sectorSize = SQLITE_DEFAULT_SECTOR_SIZE;
-- pFile->deviceCharacteristics = 0;
-- if( fstatvfs(pFile->h, &fsInfo) == -1 ) {
-- return pFile->sectorSize;
-- }
-
-- if( !strcmp(fsInfo.f_basetype, "tmp") ) {
-- pFile->sectorSize = fsInfo.f_bsize;
-- pFile->deviceCharacteristics =
-- SQLITE_IOCAP_ATOMIC4K | /* All ram filesystem writes are atomic */
-- SQLITE_IOCAP_SAFE_APPEND | /* growing the file does not occur until
-- ** the write succeeds */
-- SQLITE_IOCAP_SEQUENTIAL | /* The ram filesystem has no write behind
-- ** so it is ordered */
-- 0;
-- }else if( strstr(fsInfo.f_basetype, "etfs") ){
-- pFile->sectorSize = fsInfo.f_bsize;
-- pFile->deviceCharacteristics =
-- /* etfs cluster size writes are atomic */
-- (pFile->sectorSize / 512 * SQLITE_IOCAP_ATOMIC512) |
-- SQLITE_IOCAP_SAFE_APPEND | /* growing the file does not occur until
-- ** the write succeeds */
-- SQLITE_IOCAP_SEQUENTIAL | /* The ram filesystem has no write behind
-- ** so it is ordered */
-- 0;
-- }else if( !strcmp(fsInfo.f_basetype, "qnx6") ){
-- pFile->sectorSize = fsInfo.f_bsize;
-- pFile->deviceCharacteristics =
-- SQLITE_IOCAP_ATOMIC | /* All filesystem writes are atomic */
-- SQLITE_IOCAP_SAFE_APPEND | /* growing the file does not occur until
-- ** the write succeeds */
-- SQLITE_IOCAP_SEQUENTIAL | /* The ram filesystem has no write behind
-- ** so it is ordered */
-- 0;
-- }else if( !strcmp(fsInfo.f_basetype, "qnx4") ){
-- pFile->sectorSize = fsInfo.f_bsize;
-- pFile->deviceCharacteristics =
-- /* full bitset of atomics from max sector size and smaller */
-- ((pFile->sectorSize / 512 * SQLITE_IOCAP_ATOMIC512) << 1) - 2 |
-- SQLITE_IOCAP_SEQUENTIAL | /* The ram filesystem has no write behind
-- ** so it is ordered */
-- 0;
-- }else if( strstr(fsInfo.f_basetype, "dos") ){
-- pFile->sectorSize = fsInfo.f_bsize;
-- pFile->deviceCharacteristics =
-- /* full bitset of atomics from max sector size and smaller */
-- ((pFile->sectorSize / 512 * SQLITE_IOCAP_ATOMIC512) << 1) - 2 |
-- SQLITE_IOCAP_SEQUENTIAL | /* The ram filesystem has no write behind
-- ** so it is ordered */
-- 0;
-- }else{
-- pFile->deviceCharacteristics =
-- SQLITE_IOCAP_ATOMIC512 | /* blocks are atomic */
-- SQLITE_IOCAP_SAFE_APPEND | /* growing the file does not occur until
-- ** the write succeeds */
-- 0;
-- }
-- }
-- /* Last chance verification. If the sector size isn't a multiple of 512
-- ** then it isn't valid.*/
-- if( pFile->sectorSize % 512 != 0 ){
-- pFile->deviceCharacteristics = 0;
-- pFile->sectorSize = SQLITE_DEFAULT_SECTOR_SIZE;
-- }
-- return pFile->sectorSize;
-+static int nolockCheckReservedLock(sqlite3_file *NotUsed, int *pResOut){
-+ UNUSED_PARAMETER(NotUsed);
-+ *pResOut = 0;
-+ return SQLITE_OK;
-+}
-+static int nolockLock(sqlite3_file *NotUsed, int NotUsed2){
-+ UNUSED_PARAMETER2(NotUsed, NotUsed2);
-+ return SQLITE_OK;
-+}
-+static int nolockUnlock(sqlite3_file *NotUsed, int NotUsed2){
-+ UNUSED_PARAMETER2(NotUsed, NotUsed2);
-+ return SQLITE_OK;
- }
--#endif /* __QNXNTO__ */
-
- /*
--** Return the device characteristics for the file.
--**
--** This VFS is set up to return SQLITE_IOCAP_POWERSAFE_OVERWRITE by default.
--** However, that choice is contraversial since technically the underlying
--** file system does not always provide powersafe overwrites. (In other
--** words, after a power-loss event, parts of the file that were never
--** written might end up being altered.) However, non-PSOW behavior is very,
--** very rare. And asserting PSOW makes a large reduction in the amount
--** of required I/O for journaling, since a lot of padding is eliminated.
--** Hence, while POWERSAFE_OVERWRITE is on by default, there is a file-control
--** available to turn it off and URI query parameter available to turn it off.
-+** Close the file.
- */
--static int unixDeviceCharacteristics(sqlite3_file *id){
-- unixFile *p = (unixFile*)id;
-- int rc = 0;
--#ifdef __QNXNTO__
-- if( p->sectorSize==0 ) unixSectorSize(id);
-- rc = p->deviceCharacteristics;
--#endif
-- if( p->ctrlFlags & UNIXFILE_PSOW ){
-- rc |= SQLITE_IOCAP_POWERSAFE_OVERWRITE;
-- }
-- return rc;
-+static int nolockClose(sqlite3_file *id) {
-+ return closeUnixFile(id);
- }
-
--#ifndef SQLITE_OMIT_WAL
--
-+/******************* End of the no-op lock implementation *********************
-+******************************************************************************/
-
--/*
--** Object used to represent an shared memory buffer.
--**
--** When multiple threads all reference the same wal-index, each thread
--** has its own unixShm object, but they all point to a single instance
--** of this unixShmNode object. In other words, each wal-index is opened
--** only once per process.
--**
--** Each unixShmNode object is connected to a single unixInodeInfo object.
--** We could coalesce this object into unixInodeInfo, but that would mean
--** every open file that does not use shared memory (in other words, most
--** open files) would have to carry around this extra information. So
--** the unixInodeInfo object contains a pointer to this unixShmNode object
--** and the unixShmNode object is created only when needed.
--**
--** unixMutexHeld() must be true when creating or destroying
--** this object or while reading or writing the following fields:
--**
--** nRef
-+/******************************************************************************
-+************************* Begin dot-file Locking ******************************
- **
--** The following fields are read-only after the object is created:
--**
--** fid
--** zFilename
-+** The dotfile locking implementation uses the existence of separate lock
-+** files (really a directory) to control access to the database. This works
-+** on just about every filesystem imaginable. But there are serious downsides:
- **
--** Either unixShmNode.mutex must be held or unixShmNode.nRef==0 and
--** unixMutexHeld() is true when reading or writing any other field
--** in this structure.
--*/
--struct unixShmNode {
-- unixInodeInfo *pInode; /* unixInodeInfo that owns this SHM node */
-- sqlite3_mutex *mutex; /* Mutex to access this object */
-- char *zFilename; /* Name of the mmapped file */
-- int h; /* Open file descriptor */
-- int szRegion; /* Size of shared-memory regions */
-- u16 nRegion; /* Size of array apRegion */
-- u8 isReadonly; /* True if read-only */
-- char **apRegion; /* Array of mapped shared-memory regions */
-- int nRef; /* Number of unixShm objects pointing to this */
-- unixShm *pFirst; /* All unixShm objects pointing to this */
--#ifdef SQLITE_DEBUG
-- u8 exclMask; /* Mask of exclusive locks held */
-- u8 sharedMask; /* Mask of shared locks held */
-- u8 nextShmId; /* Next available unixShm.id value */
--#endif
--};
--
--/*
--** Structure used internally by this VFS to record the state of an
--** open shared memory connection.
-+** (1) There is zero concurrency. A single reader blocks all other
-+** connections from reading or writing the database.
- **
--** The following fields are initialized when this object is created and
--** are read-only thereafter:
-+** (2) An application crash or power loss can leave stale lock files
-+** sitting around that need to be cleared manually.
- **
--** unixShm.pFile
--** unixShm.id
-+** Nevertheless, a dotlock is an appropriate locking mode for use if no
-+** other locking strategy is available.
- **
--** All other fields are read/write. The unixShm.pFile->mutex must be held
--** while accessing any read/write fields.
-+** Dotfile locking works by creating a subdirectory in the same directory as
-+** the database and with the same name but with a ".lock" extension added.
-+** The existence of a lock directory implies an EXCLUSIVE lock. All other
-+** lock types (SHARED, RESERVED, PENDING) are mapped into EXCLUSIVE.
- */
--struct unixShm {
-- unixShmNode *pShmNode; /* The underlying unixShmNode object */
-- unixShm *pNext; /* Next unixShm with the same unixShmNode */
-- u8 hasMutex; /* True if holding the unixShmNode mutex */
-- u8 id; /* Id of this connection within its unixShmNode */
-- u16 sharedMask; /* Mask of shared locks held */
-- u16 exclMask; /* Mask of exclusive locks held */
--};
-
- /*
--** Constants used for locking
-+** The file suffix added to the data base filename in order to create the
-+** lock directory.
- */
--#define UNIX_SHM_BASE ((22+SQLITE_SHM_NLOCK)*4) /* first lock byte */
--#define UNIX_SHM_DMS (UNIX_SHM_BASE+SQLITE_SHM_NLOCK) /* deadman switch */
-+#define DOTLOCK_SUFFIX ".lock"
-
- /*
--** Apply posix advisory locks for all bytes from ofst through ofst+n-1.
-+** This routine checks if there is a RESERVED lock held on the specified
-+** file by this or any other process. If such a lock is held, set *pResOut
-+** to a non-zero value otherwise *pResOut is set to zero. The return value
-+** is set to SQLITE_OK unless an I/O error occurs during lock checking.
- **
--** Locks block if the mask is exactly UNIX_SHM_C and are non-blocking
--** otherwise.
-+** In dotfile locking, either a lock exists or it does not. So in this
-+** variation of CheckReservedLock(), *pResOut is set to true if any lock
-+** is held on the file and false if the file is unlocked.
- */
--static int unixShmSystemLock(
-- unixShmNode *pShmNode, /* Apply locks to this open shared-memory segment */
-- int lockType, /* F_UNLCK, F_RDLCK, or F_WRLCK */
-- int ofst, /* First byte of the locking range */
-- int n /* Number of bytes to lock */
--){
-- struct flock f; /* The posix advisory locking structure */
-- int rc = SQLITE_OK; /* Result code form fcntl() */
--
-- /* Access to the unixShmNode object is serialized by the caller */
-- assert( sqlite3_mutex_held(pShmNode->mutex) || pShmNode->nRef==0 );
--
-- /* Shared locks never span more than one byte */
-- assert( n==1 || lockType!=F_RDLCK );
--
-- /* Locks are within range */
-- assert( n>=1 && n<SQLITE_SHM_NLOCK );
--
-- if( pShmNode->h>=0 ){
-- /* Initialize the locking parameters */
-- memset(&f, 0, sizeof(f));
-- f.l_type = lockType;
-- f.l_whence = SEEK_SET;
-- f.l_start = ofst;
-- f.l_len = n;
--
-- rc = osFcntl(pShmNode->h, F_SETLK, &f);
-- rc = (rc!=(-1)) ? SQLITE_OK : SQLITE_BUSY;
-- }
--
-- /* Update the global lock state and do debug tracing */
--#ifdef SQLITE_DEBUG
-- { u16 mask;
-- OSTRACE(("SHM-LOCK "));
-- mask = (1<<(ofst+n)) - (1<<ofst);
-- if( rc==SQLITE_OK ){
-- if( lockType==F_UNLCK ){
-- OSTRACE(("unlock %d ok", ofst));
-- pShmNode->exclMask &= ~mask;
-- pShmNode->sharedMask &= ~mask;
-- }else if( lockType==F_RDLCK ){
-- OSTRACE(("read-lock %d ok", ofst));
-- pShmNode->exclMask &= ~mask;
-- pShmNode->sharedMask |= mask;
-- }else{
-- assert( lockType==F_WRLCK );
-- OSTRACE(("write-lock %d ok", ofst));
-- pShmNode->exclMask |= mask;
-- pShmNode->sharedMask &= ~mask;
-- }
-- }else{
-- if( lockType==F_UNLCK ){
-- OSTRACE(("unlock %d failed", ofst));
-- }else if( lockType==F_RDLCK ){
-- OSTRACE(("read-lock failed"));
-- }else{
-- assert( lockType==F_WRLCK );
-- OSTRACE(("write-lock %d failed", ofst));
-- }
-- }
-- OSTRACE((" - afterwards %03x,%03x\n",
-- pShmNode->sharedMask, pShmNode->exclMask));
-- }
--#endif
--
-- return rc;
--}
-+static int dotlockCheckReservedLock(sqlite3_file *id, int *pResOut) {
-+ int rc = SQLITE_OK;
-+ int reserved = 0;
-+ unixFile *pFile = (unixFile*)id;
-
-+ SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
-+
-+ assert( pFile );
-
--/*
--** Purge the unixShmNodeList list of all entries with unixShmNode.nRef==0.
--**
--** This is not a VFS shared-memory method; it is a utility function called
--** by VFS shared-memory methods.
--*/
--static void unixShmPurge(unixFile *pFd){
-- unixShmNode *p = pFd->pInode->pShmNode;
-- assert( unixMutexHeld() );
-- if( p && p->nRef==0 ){
-- int i;
-- assert( p->pInode==pFd->pInode );
-- sqlite3_mutex_free(p->mutex);
-- for(i=0; i<p->nRegion; i++){
-- if( p->h>=0 ){
-- osMunmap(p->apRegion[i], p->szRegion);
-- }else{
-- sqlite3_free(p->apRegion[i]);
-- }
-- }
-- sqlite3_free(p->apRegion);
-- if( p->h>=0 ){
-- robust_close(pFd, p->h, __LINE__);
-- p->h = -1;
-- }
-- p->pInode->pShmNode = 0;
-- sqlite3_free(p);
-+ /* Check if a thread in this process holds such a lock */
-+ if( pFile->eFileLock>SHARED_LOCK ){
-+ /* Either this connection or some other connection in the same process
-+ ** holds a lock on the file. No need to check further. */
-+ reserved = 1;
-+ }else{
-+ /* The lock is held if and only if the lockfile exists */
-+ const char *zLockFile = (const char*)pFile->lockingContext;
-+ reserved = osAccess(zLockFile, 0)==0;
- }
-+ OSTRACE(("TEST WR-LOCK %d %d %d (dotlock)\n", pFile->h, rc, reserved));
-+ *pResOut = reserved;
-+ return rc;
- }
-
- /*
--** Open a shared-memory area associated with open database file pDbFd.
--** This particular implementation uses mmapped files.
-+** Lock the file with the lock specified by parameter eFileLock - one
-+** of the following:
- **
--** The file used to implement shared-memory is in the same directory
--** as the open database file and has the same name as the open database
--** file with the "-shm" suffix added. For example, if the database file
--** is "/home/user1/config.db" then the file that is created and mmapped
--** for shared memory will be called "/home/user1/config.db-shm".
-+** (1) SHARED_LOCK
-+** (2) RESERVED_LOCK
-+** (3) PENDING_LOCK
-+** (4) EXCLUSIVE_LOCK
- **
--** Another approach to is to use files in /dev/shm or /dev/tmp or an
--** some other tmpfs mount. But if a file in a different directory
--** from the database file is used, then differing access permissions
--** or a chroot() might cause two different processes on the same
--** database to end up using different files for shared memory -
--** meaning that their memory would not really be shared - resulting
--** in database corruption. Nevertheless, this tmpfs file usage
--** can be enabled at compile-time using -DSQLITE_SHM_DIRECTORY="/dev/shm"
--** or the equivalent. The use of the SQLITE_SHM_DIRECTORY compile-time
--** option results in an incompatible build of SQLite; builds of SQLite
--** that with differing SQLITE_SHM_DIRECTORY settings attempt to use the
--** same database file at the same time, database corruption will likely
--** result. The SQLITE_SHM_DIRECTORY compile-time option is considered
--** "unsupported" and may go away in a future SQLite release.
-+** Sometimes when requesting one lock state, additional lock states
-+** are inserted in between. The locking might fail on one of the later
-+** transitions leaving the lock state different from what it started but
-+** still short of its goal. The following chart shows the allowed
-+** transitions and the inserted intermediate states:
- **
--** When opening a new shared-memory file, if no other instances of that
--** file are currently open, in this process or in other processes, then
--** the file must be truncated to zero length or have its header cleared.
-+** UNLOCKED -> SHARED
-+** SHARED -> RESERVED
-+** SHARED -> (PENDING) -> EXCLUSIVE
-+** RESERVED -> (PENDING) -> EXCLUSIVE
-+** PENDING -> EXCLUSIVE
- **
--** If the original database file (pDbFd) is using the "unix-excl" VFS
--** that means that an exclusive lock is held on the database file and
--** that no other processes are able to read or write the database. In
--** that case, we do not really need shared memory. No shared memory
--** file is created. The shared memory will be simulated with heap memory.
-+** This routine will only increase a lock. Use the sqlite3OsUnlock()
-+** routine to lower a locking level.
-+**
-+** With dotfile locking, we really only support state (4): EXCLUSIVE.
-+** But we track the other locking levels internally.
- */
--static int unixOpenSharedMemory(unixFile *pDbFd){
-- struct unixShm *p = 0; /* The connection to be opened */
-- struct unixShmNode *pShmNode; /* The underlying mmapped file */
-- int rc; /* Result code */
-- unixInodeInfo *pInode; /* The inode of fd */
-- char *zShmFilename; /* Name of the file used for SHM */
-- int nShmFilename; /* Size of the SHM filename in bytes */
-+static int dotlockLock(sqlite3_file *id, int eFileLock) {
-+ unixFile *pFile = (unixFile*)id;
-+ char *zLockFile = (char *)pFile->lockingContext;
-+ int rc = SQLITE_OK;
-
-- /* Allocate space for the new unixShm object. */
-- p = sqlite3_malloc( sizeof(*p) );
-- if( p==0 ) return SQLITE_NOMEM;
-- memset(p, 0, sizeof(*p));
-- assert( pDbFd->pShm==0 );
-
-- /* Check to see if a unixShmNode object already exists. Reuse an existing
-- ** one if present. Create a new one if necessary.
-+ /* If we have any lock, then the lock file already exists. All we have
-+ ** to do is adjust our internal record of the lock level.
- */
-- unixEnterMutex();
-- pInode = pDbFd->pInode;
-- pShmNode = pInode->pShmNode;
-- if( pShmNode==0 ){
-- struct stat sStat; /* fstat() info for database file */
--
-- /* Call fstat() to figure out the permissions on the database file. If
-- ** a new *-shm file is created, an attempt will be made to create it
-- ** with the same permissions.
-- */
-- if( osFstat(pDbFd->h, &sStat) && pInode->bProcessLock==0 ){
-- rc = SQLITE_IOERR_FSTAT;
-- goto shm_open_err;
-- }
--
--#ifdef SQLITE_SHM_DIRECTORY
-- nShmFilename = sizeof(SQLITE_SHM_DIRECTORY) + 31;
--#else
-- nShmFilename = 6 + (int)strlen(pDbFd->zPath);
--#endif
-- pShmNode = sqlite3_malloc( sizeof(*pShmNode) + nShmFilename );
-- if( pShmNode==0 ){
-- rc = SQLITE_NOMEM;
-- goto shm_open_err;
-- }
-- memset(pShmNode, 0, sizeof(*pShmNode)+nShmFilename);
-- zShmFilename = pShmNode->zFilename = (char*)&pShmNode[1];
--#ifdef SQLITE_SHM_DIRECTORY
-- sqlite3_snprintf(nShmFilename, zShmFilename,
-- SQLITE_SHM_DIRECTORY "/sqlite-shm-%x-%x",
-- (u32)sStat.st_ino, (u32)sStat.st_dev);
-+ if( pFile->eFileLock > NO_LOCK ){
-+ pFile->eFileLock = eFileLock;
-+ /* Always update the timestamp on the old file */
-+#ifdef HAVE_UTIME
-+ utime(zLockFile, NULL);
- #else
-- sqlite3_snprintf(nShmFilename, zShmFilename, "%s-shm", pDbFd->zPath);
-- sqlite3FileSuffix3(pDbFd->zPath, zShmFilename);
-+ utimes(zLockFile, NULL);
- #endif
-- pShmNode->h = -1;
-- pDbFd->pInode->pShmNode = pShmNode;
-- pShmNode->pInode = pDbFd->pInode;
-- pShmNode->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
-- if( pShmNode->mutex==0 ){
-- rc = SQLITE_NOMEM;
-- goto shm_open_err;
-- }
--
-- if( pInode->bProcessLock==0 ){
-- int openFlags = O_RDWR | O_CREAT;
-- if( sqlite3_uri_boolean(pDbFd->zPath, "readonly_shm", 0) ){
-- openFlags = O_RDONLY;
-- pShmNode->isReadonly = 1;
-- }
-- pShmNode->h = robust_open(zShmFilename, openFlags, (sStat.st_mode&0777));
-- if( pShmNode->h<0 ){
-- rc = unixLogError(SQLITE_CANTOPEN_BKPT, "open", zShmFilename);
-- goto shm_open_err;
-- }
--
-- /* If this process is running as root, make sure that the SHM file
-- ** is owned by the same user that owns the original database. Otherwise,
-- ** the original owner will not be able to connect.
-- */
-- osFchown(pShmNode->h, sStat.st_uid, sStat.st_gid);
-+ return SQLITE_OK;
-+ }
-
-- /* Check to see if another process is holding the dead-man switch.
-- ** If not, truncate the file to zero length.
-- */
-- rc = SQLITE_OK;
-- if( unixShmSystemLock(pShmNode, F_WRLCK, UNIX_SHM_DMS, 1)==SQLITE_OK ){
-- if( robust_ftruncate(pShmNode->h, 0) ){
-- rc = unixLogError(SQLITE_IOERR_SHMOPEN, "ftruncate", zShmFilename);
-- }
-- }
-- if( rc==SQLITE_OK ){
-- rc = unixShmSystemLock(pShmNode, F_RDLCK, UNIX_SHM_DMS, 1);
-+ /* grab an exclusive lock */
-+ rc = osMkdir(zLockFile, 0777);
-+ if( rc<0 ){
-+ /* failed to open/create the lock directory */
-+ int tErrno = errno;
-+ if( EEXIST == tErrno ){
-+ rc = SQLITE_BUSY;
-+ } else {
-+ rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
-+ if( IS_LOCK_ERROR(rc) ){
-+ pFile->lastErrno = tErrno;
- }
-- if( rc ) goto shm_open_err;
- }
-- }
--
-- /* Make the new connection a child of the unixShmNode */
-- p->pShmNode = pShmNode;
--#ifdef SQLITE_DEBUG
-- p->id = pShmNode->nextShmId++;
--#endif
-- pShmNode->nRef++;
-- pDbFd->pShm = p;
-- unixLeaveMutex();
--
-- /* The reference count on pShmNode has already been incremented under
-- ** the cover of the unixEnterMutex() mutex and the pointer from the
-- ** new (struct unixShm) object to the pShmNode has been set. All that is
-- ** left to do is to link the new object into the linked list starting
-- ** at pShmNode->pFirst. This must be done while holding the pShmNode->mutex
-- ** mutex.
-- */
-- sqlite3_mutex_enter(pShmNode->mutex);
-- p->pNext = pShmNode->pFirst;
-- pShmNode->pFirst = p;
-- sqlite3_mutex_leave(pShmNode->mutex);
-- return SQLITE_OK;
--
-- /* Jump here on any error */
--shm_open_err:
-- unixShmPurge(pDbFd); /* This call frees pShmNode if required */
-- sqlite3_free(p);
-- unixLeaveMutex();
-+ return rc;
-+ }
-+
-+ /* got it, set the type and return ok */
-+ pFile->eFileLock = eFileLock;
- return rc;
- }
-
- /*
--** This function is called to obtain a pointer to region iRegion of the
--** shared-memory associated with the database file fd. Shared-memory regions
--** are numbered starting from zero. Each shared-memory region is szRegion
--** bytes in size.
--**
--** If an error occurs, an error code is returned and *pp is set to NULL.
-+** Lower the locking level on file descriptor pFile to eFileLock. eFileLock
-+** must be either NO_LOCK or SHARED_LOCK.
- **
--** Otherwise, if the bExtend parameter is 0 and the requested shared-memory
--** region has not been allocated (by any client, including one running in a
--** separate process), then *pp is set to NULL and SQLITE_OK returned. If
--** bExtend is non-zero and the requested shared-memory region has not yet
--** been allocated, it is allocated by this function.
-+** If the locking level of the file descriptor is already at or below
-+** the requested locking level, this routine is a no-op.
- **
--** If the shared-memory region has already been allocated or is allocated by
--** this call as described above, then it is mapped into this processes
--** address space (if it is not already), *pp is set to point to the mapped
--** memory and SQLITE_OK returned.
-+** When the locking level reaches NO_LOCK, delete the lock file.
- */
--static int unixShmMap(
-- sqlite3_file *fd, /* Handle open on database file */
-- int iRegion, /* Region to retrieve */
-- int szRegion, /* Size of regions */
-- int bExtend, /* True to extend file if necessary */
-- void volatile **pp /* OUT: Mapped memory */
--){
-- unixFile *pDbFd = (unixFile*)fd;
-- unixShm *p;
-- unixShmNode *pShmNode;
-- int rc = SQLITE_OK;
-+static int dotlockUnlock(sqlite3_file *id, int eFileLock) {
-+ unixFile *pFile = (unixFile*)id;
-+ char *zLockFile = (char *)pFile->lockingContext;
-+ int rc;
-
-- /* If the shared-memory file has not yet been opened, open it now. */
-- if( pDbFd->pShm==0 ){
-- rc = unixOpenSharedMemory(pDbFd);
-- if( rc!=SQLITE_OK ) return rc;
-+ assert( pFile );
-+ OSTRACE(("UNLOCK %d %d was %d pid=%d (dotlock)\n", pFile->h, eFileLock,
-+ pFile->eFileLock, getpid()));
-+ assert( eFileLock<=SHARED_LOCK );
-+
-+ /* no-op if possible */
-+ if( pFile->eFileLock==eFileLock ){
-+ return SQLITE_OK;
- }
-
-- p = pDbFd->pShm;
-- pShmNode = p->pShmNode;
-- sqlite3_mutex_enter(pShmNode->mutex);
-- assert( szRegion==pShmNode->szRegion || pShmNode->nRegion==0 );
-- assert( pShmNode->pInode==pDbFd->pInode );
-- assert( pShmNode->h>=0 || pDbFd->pInode->bProcessLock==1 );
-- assert( pShmNode->h<0 || pDbFd->pInode->bProcessLock==0 );
--
-- if( pShmNode->nRegion<=iRegion ){
-- char **apNew; /* New apRegion[] array */
-- int nByte = (iRegion+1)*szRegion; /* Minimum required file size */
-- struct stat sStat; /* Used by fstat() */
--
-- pShmNode->szRegion = szRegion;
--
-- if( pShmNode->h>=0 ){
-- /* The requested region is not mapped into this processes address space.
-- ** Check to see if it has been allocated (i.e. if the wal-index file is
-- ** large enough to contain the requested region).
-- */
-- if( osFstat(pShmNode->h, &sStat) ){
-- rc = SQLITE_IOERR_SHMSIZE;
-- goto shmpage_out;
-- }
-+ /* To downgrade to shared, simply update our internal notion of the
-+ ** lock state. No need to mess with the file on disk.
-+ */
-+ if( eFileLock==SHARED_LOCK ){
-+ pFile->eFileLock = SHARED_LOCK;
-+ return SQLITE_OK;
-+ }
-
-- if( sStat.st_size<nByte ){
-- /* The requested memory region does not exist. If bExtend is set to
-- ** false, exit early. *pp will be set to NULL and SQLITE_OK returned.
-- */
-- if( !bExtend ){
-- goto shmpage_out;
-- }
--
-- /* Alternatively, if bExtend is true, extend the file. Do this by
-- ** writing a single byte to the end of each (OS) page being
-- ** allocated or extended. Technically, we need only write to the
-- ** last page in order to extend the file. But writing to all new
-- ** pages forces the OS to allocate them immediately, which reduces
-- ** the chances of SIGBUS while accessing the mapped region later on.
-- */
-- else{
-- static const int pgsz = 4096;
-- int iPg;
--
-- /* Write to the last byte of each newly allocated or extended page */
-- assert( (nByte % pgsz)==0 );
-- for(iPg=(sStat.st_size/pgsz); iPg<(nByte/pgsz); iPg++){
-- if( seekAndWriteFd(pShmNode->h, iPg*pgsz + pgsz-1, "", 1, 0)!=1 ){
-- const char *zFile = pShmNode->zFilename;
-- rc = unixLogError(SQLITE_IOERR_SHMSIZE, "write", zFile);
-- goto shmpage_out;
-- }
-- }
-- }
-- }
-- }
--
-- /* Map the requested memory region into this processes address space. */
-- apNew = (char **)sqlite3_realloc(
-- pShmNode->apRegion, (iRegion+1)*sizeof(char *)
-- );
-- if( !apNew ){
-- rc = SQLITE_IOERR_NOMEM;
-- goto shmpage_out;
-+ /* To fully unlock the database, delete the lock file */
-+ assert( eFileLock==NO_LOCK );
-+ rc = osRmdir(zLockFile);
-+ if( rc<0 && errno==ENOTDIR ) rc = osUnlink(zLockFile);
-+ if( rc<0 ){
-+ int tErrno = errno;
-+ rc = 0;
-+ if( ENOENT != tErrno ){
-+ rc = SQLITE_IOERR_UNLOCK;
- }
-- pShmNode->apRegion = apNew;
-- while(pShmNode->nRegion<=iRegion){
-- void *pMem;
-- if( pShmNode->h>=0 ){
-- pMem = osMmap(0, szRegion,
-- pShmNode->isReadonly ? PROT_READ : PROT_READ|PROT_WRITE,
-- MAP_SHARED, pShmNode->h, szRegion*(i64)pShmNode->nRegion
-- );
-- if( pMem==MAP_FAILED ){
-- rc = unixLogError(SQLITE_IOERR_SHMMAP, "mmap", pShmNode->zFilename);
-- goto shmpage_out;
-- }
-- }else{
-- pMem = sqlite3_malloc(szRegion);
-- if( pMem==0 ){
-- rc = SQLITE_NOMEM;
-- goto shmpage_out;
-- }
-- memset(pMem, 0, szRegion);
-- }
-- pShmNode->apRegion[pShmNode->nRegion] = pMem;
-- pShmNode->nRegion++;
-+ if( IS_LOCK_ERROR(rc) ){
-+ pFile->lastErrno = tErrno;
- }
-+ return rc;
- }
-+ pFile->eFileLock = NO_LOCK;
-+ return SQLITE_OK;
-+}
-
--shmpage_out:
-- if( pShmNode->nRegion>iRegion ){
-- *pp = pShmNode->apRegion[iRegion];
-- }else{
-- *pp = 0;
-+/*
-+** Close a file. Make sure the lock has been released before closing.
-+*/
-+static int dotlockClose(sqlite3_file *id) {
-+ int rc = SQLITE_OK;
-+ if( id ){
-+ unixFile *pFile = (unixFile*)id;
-+ dotlockUnlock(id, NO_LOCK);
-+ sqlite3_free(pFile->lockingContext);
-+ rc = closeUnixFile(id);
- }
-- if( pShmNode->isReadonly && rc==SQLITE_OK ) rc = SQLITE_READONLY;
-- sqlite3_mutex_leave(pShmNode->mutex);
- return rc;
- }
-+/****************** End of the dot-file lock implementation *******************
-+******************************************************************************/
-
--/*
--** Change the lock state for a shared-memory segment.
-+/******************************************************************************
-+************************** Begin flock Locking ********************************
- **
--** Note that the relationship between SHAREd and EXCLUSIVE locks is a little
--** different here than in posix. In xShmLock(), one can go from unlocked
--** to shared and back or from unlocked to exclusive and back. But one may
--** not go from shared to exclusive or from exclusive to shared.
-+** Use the flock() system call to do file locking.
-+**
-+** flock() locking is like dot-file locking in that the various
-+** fine-grain locking levels supported by SQLite are collapsed into
-+** a single exclusive lock. In other words, SHARED, RESERVED, and
-+** PENDING locks are the same thing as an EXCLUSIVE lock. SQLite
-+** still works when you do this, but concurrency is reduced since
-+** only a single process can be reading the database at a time.
-+**
-+** Omit this section if SQLITE_ENABLE_LOCKING_STYLE is turned off or if
-+** compiling for VXWORKS.
- */
--static int unixShmLock(
-- sqlite3_file *fd, /* Database file holding the shared memory */
-- int ofst, /* First lock to acquire or release */
-- int n, /* Number of locks to acquire or release */
-- int flags /* What to do with the lock */
--){
-- unixFile *pDbFd = (unixFile*)fd; /* Connection holding shared memory */
-- unixShm *p = pDbFd->pShm; /* The shared memory being locked */
-- unixShm *pX; /* For looping over all siblings */
-- unixShmNode *pShmNode = p->pShmNode; /* The underlying file iNode */
-- int rc = SQLITE_OK; /* Result code */
-- u16 mask; /* Mask of locks to take or release */
--
-- assert( pShmNode==pDbFd->pInode->pShmNode );
-- assert( pShmNode->pInode==pDbFd->pInode );
-- assert( ofst>=0 && ofst+n<=SQLITE_SHM_NLOCK );
-- assert( n>=1 );
-- assert( flags==(SQLITE_SHM_LOCK | SQLITE_SHM_SHARED)
-- || flags==(SQLITE_SHM_LOCK | SQLITE_SHM_EXCLUSIVE)
-- || flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED)
-- || flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE) );
-- assert( n==1 || (flags & SQLITE_SHM_EXCLUSIVE)!=0 );
-- assert( pShmNode->h>=0 || pDbFd->pInode->bProcessLock==1 );
-- assert( pShmNode->h<0 || pDbFd->pInode->bProcessLock==0 );
--
-- mask = (1<<(ofst+n)) - (1<<ofst);
-- assert( n>1 || mask==(1<<ofst) );
-- sqlite3_mutex_enter(pShmNode->mutex);
-- if( flags & SQLITE_SHM_UNLOCK ){
-- u16 allMask = 0; /* Mask of locks held by siblings */
--
-- /* See if any siblings hold this same lock */
-- for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
-- if( pX==p ) continue;
-- assert( (pX->exclMask & (p->exclMask|p->sharedMask))==0 );
-- allMask |= pX->sharedMask;
-- }
--
-- /* Unlock the system-level locks */
-- if( (mask & allMask)==0 ){
-- rc = unixShmSystemLock(pShmNode, F_UNLCK, ofst+UNIX_SHM_BASE, n);
-- }else{
-- rc = SQLITE_OK;
-- }
--
-- /* Undo the local locks */
-- if( rc==SQLITE_OK ){
-- p->exclMask &= ~mask;
-- p->sharedMask &= ~mask;
-- }
-- }else if( flags & SQLITE_SHM_SHARED ){
-- u16 allShared = 0; /* Union of locks held by connections other than "p" */
--
-- /* Find out which shared locks are already held by sibling connections.
-- ** If any sibling already holds an exclusive lock, go ahead and return
-- ** SQLITE_BUSY.
-- */
-- for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
-- if( (pX->exclMask & mask)!=0 ){
-- rc = SQLITE_BUSY;
-- break;
-- }
-- allShared |= pX->sharedMask;
-- }
-+#if SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORKS
-
-- /* Get shared locks at the system level, if necessary */
-- if( rc==SQLITE_OK ){
-- if( (allShared & mask)==0 ){
-- rc = unixShmSystemLock(pShmNode, F_RDLCK, ofst+UNIX_SHM_BASE, n);
-- }else{
-- rc = SQLITE_OK;
-- }
-- }
-+/*
-+** Retry flock() calls that fail with EINTR
-+*/
-+#ifdef EINTR
-+static int robust_flock(int fd, int op){
-+ int rc;
-+ do{ rc = flock(fd,op); }while( rc<0 && errno==EINTR );
-+ return rc;
-+}
-+#else
-+# define robust_flock(a,b) flock(a,b)
-+#endif
-+
-
-- /* Get the local shared locks */
-- if( rc==SQLITE_OK ){
-- p->sharedMask |= mask;
-- }
-- }else{
-- /* Make sure no sibling connections hold locks that will block this
-- ** lock. If any do, return SQLITE_BUSY right away.
-- */
-- for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
-- if( (pX->exclMask & mask)!=0 || (pX->sharedMask & mask)!=0 ){
-- rc = SQLITE_BUSY;
-- break;
-- }
-- }
-+/*
-+** This routine checks if there is a RESERVED lock held on the specified
-+** file by this or any other process. If such a lock is held, set *pResOut
-+** to a non-zero value otherwise *pResOut is set to zero. The return value
-+** is set to SQLITE_OK unless an I/O error occurs during lock checking.
-+*/
-+static int flockCheckReservedLock(sqlite3_file *id, int *pResOut){
-+ int rc = SQLITE_OK;
-+ int reserved = 0;
-+ unixFile *pFile = (unixFile*)id;
-
-- /* Get the exclusive locks at the system level. Then if successful
-- ** also mark the local connection as being locked.
-- */
-- if( rc==SQLITE_OK ){
-- rc = unixShmSystemLock(pShmNode, F_WRLCK, ofst+UNIX_SHM_BASE, n);
-- if( rc==SQLITE_OK ){
-- assert( (p->sharedMask & mask)==0 );
-- p->exclMask |= mask;
-+ SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
-+
-+ assert( pFile );
-+
-+ /* Check if a thread in this process holds such a lock */
-+ if( pFile->eFileLock>SHARED_LOCK ){
-+ reserved = 1;
-+ }
-+
-+ /* Otherwise see if some other process holds it. */
-+ if( !reserved ){
-+ /* attempt to get the lock */
-+ int lrc = robust_flock(pFile->h, LOCK_EX | LOCK_NB);
-+ if( !lrc ){
-+ /* got the lock, unlock it */
-+ lrc = robust_flock(pFile->h, LOCK_UN);
-+ if ( lrc ) {
-+ int tErrno = errno;
-+ /* unlock failed with an error */
-+ lrc = SQLITE_IOERR_UNLOCK;
-+ if( IS_LOCK_ERROR(lrc) ){
-+ pFile->lastErrno = tErrno;
-+ rc = lrc;
-+ }
-+ }
-+ } else {
-+ int tErrno = errno;
-+ reserved = 1;
-+ /* someone else might have it reserved */
-+ lrc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
-+ if( IS_LOCK_ERROR(lrc) ){
-+ pFile->lastErrno = tErrno;
-+ rc = lrc;
- }
- }
- }
-- sqlite3_mutex_leave(pShmNode->mutex);
-- OSTRACE(("SHM-LOCK shmid-%d, pid-%d got %03x,%03x\n",
-- p->id, getpid(), p->sharedMask, p->exclMask));
-+ OSTRACE(("TEST WR-LOCK %d %d %d (flock)\n", pFile->h, rc, reserved));
-+
-+#ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS
-+ if( (rc & SQLITE_IOERR) == SQLITE_IOERR ){
-+ rc = SQLITE_OK;
-+ reserved=1;
-+ }
-+#endif /* SQLITE_IGNORE_FLOCK_LOCK_ERRORS */
-+ *pResOut = reserved;
- return rc;
- }
-
- /*
--** Implement a memory barrier or memory fence on shared memory.
-+** Lock the file with the lock specified by parameter eFileLock - one
-+** of the following:
- **
--** All loads and stores begun before the barrier must complete before
--** any load or store begun after the barrier.
--*/
--static void unixShmBarrier(
-- sqlite3_file *fd /* Database file holding the shared memory */
--){
-- UNUSED_PARAMETER(fd);
-- unixEnterMutex();
-- unixLeaveMutex();
--}
--
--/*
--** Close a connection to shared-memory. Delete the underlying
--** storage if deleteFlag is true.
-+** (1) SHARED_LOCK
-+** (2) RESERVED_LOCK
-+** (3) PENDING_LOCK
-+** (4) EXCLUSIVE_LOCK
- **
--** If there is no shared memory associated with the connection then this
--** routine is a harmless no-op.
-+** Sometimes when requesting one lock state, additional lock states
-+** are inserted in between. The locking might fail on one of the later
-+** transitions leaving the lock state different from what it started but
-+** still short of its goal. The following chart shows the allowed
-+** transitions and the inserted intermediate states:
-+**
-+** UNLOCKED -> SHARED
-+** SHARED -> RESERVED
-+** SHARED -> (PENDING) -> EXCLUSIVE
-+** RESERVED -> (PENDING) -> EXCLUSIVE
-+** PENDING -> EXCLUSIVE
-+**
-+** flock() only really support EXCLUSIVE locks. We track intermediate
-+** lock states in the sqlite3_file structure, but all locks SHARED or
-+** above are really EXCLUSIVE locks and exclude all other processes from
-+** access the file.
-+**
-+** This routine will only increase a lock. Use the sqlite3OsUnlock()
-+** routine to lower a locking level.
- */
--static int unixShmUnmap(
-- sqlite3_file *fd, /* The underlying database file */
-- int deleteFlag /* Delete shared-memory if true */
--){
-- unixShm *p; /* The connection to be closed */
-- unixShmNode *pShmNode; /* The underlying shared-memory file */
-- unixShm **pp; /* For looping over sibling connections */
-- unixFile *pDbFd; /* The underlying database file */
--
-- pDbFd = (unixFile*)fd;
-- p = pDbFd->pShm;
-- if( p==0 ) return SQLITE_OK;
-- pShmNode = p->pShmNode;
--
-- assert( pShmNode==pDbFd->pInode->pShmNode );
-- assert( pShmNode->pInode==pDbFd->pInode );
--
-- /* Remove connection p from the set of connections associated
-- ** with pShmNode */
-- sqlite3_mutex_enter(pShmNode->mutex);
-- for(pp=&pShmNode->pFirst; (*pp)!=p; pp = &(*pp)->pNext){}
-- *pp = p->pNext;
-+static int flockLock(sqlite3_file *id, int eFileLock) {
-+ int rc = SQLITE_OK;
-+ unixFile *pFile = (unixFile*)id;
-
-- /* Free the connection p */
-- sqlite3_free(p);
-- pDbFd->pShm = 0;
-- sqlite3_mutex_leave(pShmNode->mutex);
-+ assert( pFile );
-
-- /* If pShmNode->nRef has reached 0, then close the underlying
-- ** shared-memory file, too */
-- unixEnterMutex();
-- assert( pShmNode->nRef>0 );
-- pShmNode->nRef--;
-- if( pShmNode->nRef==0 ){
-- if( deleteFlag && pShmNode->h>=0 ) osUnlink(pShmNode->zFilename);
-- unixShmPurge(pDbFd);
-+ /* if we already have a lock, it is exclusive.
-+ ** Just adjust level and punt on outta here. */
-+ if (pFile->eFileLock > NO_LOCK) {
-+ pFile->eFileLock = eFileLock;
-+ return SQLITE_OK;
- }
-- unixLeaveMutex();
--
-- return SQLITE_OK;
-+
-+ /* grab an exclusive lock */
-+
-+ if (robust_flock(pFile->h, LOCK_EX | LOCK_NB)) {
-+ int tErrno = errno;
-+ /* didn't get, must be busy */
-+ rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
-+ if( IS_LOCK_ERROR(rc) ){
-+ pFile->lastErrno = tErrno;
-+ }
-+ } else {
-+ /* got it, set the type and return ok */
-+ pFile->eFileLock = eFileLock;
-+ }
-+ OSTRACE(("LOCK %d %s %s (flock)\n", pFile->h, azFileLock(eFileLock),
-+ rc==SQLITE_OK ? "ok" : "failed"));
-+#ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS
-+ if( (rc & SQLITE_IOERR) == SQLITE_IOERR ){
-+ rc = SQLITE_BUSY;
-+ }
-+#endif /* SQLITE_IGNORE_FLOCK_LOCK_ERRORS */
-+ return rc;
- }
-
-
--#else
--# define unixShmMap 0
--# define unixShmLock 0
--# define unixShmBarrier 0
--# define unixShmUnmap 0
--#endif /* #ifndef SQLITE_OMIT_WAL */
--
- /*
--** If it is currently memory mapped, unmap file pFd.
-+** Lower the locking level on file descriptor pFile to eFileLock. eFileLock
-+** must be either NO_LOCK or SHARED_LOCK.
-+**
-+** If the locking level of the file descriptor is already at or below
-+** the requested locking level, this routine is a no-op.
- */
--static void unixUnmapfile(unixFile *pFd){
-- assert( pFd->nFetchOut==0 );
--#if SQLITE_MAX_MMAP_SIZE>0
-- if( pFd->pMapRegion ){
-- osMunmap(pFd->pMapRegion, pFd->mmapSizeActual);
-- pFd->pMapRegion = 0;
-- pFd->mmapSize = 0;
-- pFd->mmapSizeActual = 0;
-+static int flockUnlock(sqlite3_file *id, int eFileLock) {
-+ unixFile *pFile = (unixFile*)id;
-+
-+ assert( pFile );
-+ OSTRACE(("UNLOCK %d %d was %d pid=%d (flock)\n", pFile->h, eFileLock,
-+ pFile->eFileLock, getpid()));
-+ assert( eFileLock<=SHARED_LOCK );
-+
-+ /* no-op if possible */
-+ if( pFile->eFileLock==eFileLock ){
-+ return SQLITE_OK;
-+ }
-+
-+ /* shared can just be set because we always have an exclusive */
-+ if (eFileLock==SHARED_LOCK) {
-+ pFile->eFileLock = eFileLock;
-+ return SQLITE_OK;
-+ }
-+
-+ /* no, really, unlock. */
-+ if( robust_flock(pFile->h, LOCK_UN) ){
-+#ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS
-+ return SQLITE_OK;
-+#endif /* SQLITE_IGNORE_FLOCK_LOCK_ERRORS */
-+ return SQLITE_IOERR_UNLOCK;
-+ }else{
-+ pFile->eFileLock = NO_LOCK;
-+ return SQLITE_OK;
- }
--#endif
- }
-
--#if SQLITE_MAX_MMAP_SIZE>0
- /*
--** Return the system page size.
-+** Close a file.
- */
--static int unixGetPagesize(void){
--#if HAVE_MREMAP
-- return 512;
--#elif defined(_BSD_SOURCE)
-- return getpagesize();
--#else
-- return (int)sysconf(_SC_PAGESIZE);
--#endif
-+static int flockClose(sqlite3_file *id) {
-+ int rc = SQLITE_OK;
-+ if( id ){
-+ flockUnlock(id, NO_LOCK);
-+ rc = closeUnixFile(id);
-+ }
-+ return rc;
- }
--#endif /* SQLITE_MAX_MMAP_SIZE>0 */
-
--#if SQLITE_MAX_MMAP_SIZE>0
--/*
--** Attempt to set the size of the memory mapping maintained by file
--** descriptor pFd to nNew bytes. Any existing mapping is discarded.
--**
--** If successful, this function sets the following variables:
-+#endif /* SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORK */
-+
-+/******************* End of the flock lock implementation *********************
-+******************************************************************************/
-+
-+/******************************************************************************
-+************************ Begin Named Semaphore Locking ************************
- **
--** unixFile.pMapRegion
--** unixFile.mmapSize
--** unixFile.mmapSizeActual
-+** Named semaphore locking is only supported on VxWorks.
- **
--** If unsuccessful, an error message is logged via sqlite3_log() and
--** the three variables above are zeroed. In this case SQLite should
--** continue accessing the database using the xRead() and xWrite()
--** methods.
-+** Semaphore locking is like dot-lock and flock in that it really only
-+** supports EXCLUSIVE locking. Only a single process can read or write
-+** the database file at a time. This reduces potential concurrency, but
-+** makes the lock implementation much easier.
- */
--static void unixRemapfile(
-- unixFile *pFd, /* File descriptor object */
-- i64 nNew /* Required mapping size */
--){
-- const char *zErr = "mmap";
-- int h = pFd->h; /* File descriptor open on db file */
-- u8 *pOrig = (u8 *)pFd->pMapRegion; /* Pointer to current file mapping */
-- i64 nOrig = pFd->mmapSizeActual; /* Size of pOrig region in bytes */
-- u8 *pNew = 0; /* Location of new mapping */
-- int flags = PROT_READ; /* Flags to pass to mmap() */
--
-- assert( pFd->nFetchOut==0 );
-- assert( nNew>pFd->mmapSize );
-- assert( nNew<=pFd->mmapSizeMax );
-- assert( nNew>0 );
-- assert( pFd->mmapSizeActual>=pFd->mmapSize );
-- assert( MAP_FAILED!=0 );
-+#if OS_VXWORKS
-
-- if( (pFd->ctrlFlags & UNIXFILE_RDONLY)==0 ) flags |= PROT_WRITE;
-+/*
-+** This routine checks if there is a RESERVED lock held on the specified
-+** file by this or any other process. If such a lock is held, set *pResOut
-+** to a non-zero value otherwise *pResOut is set to zero. The return value
-+** is set to SQLITE_OK unless an I/O error occurs during lock checking.
-+*/
-+static int semCheckReservedLock(sqlite3_file *id, int *pResOut) {
-+ int rc = SQLITE_OK;
-+ int reserved = 0;
-+ unixFile *pFile = (unixFile*)id;
-
-- if( pOrig ){
-- const int szSyspage = unixGetPagesize();
-- i64 nReuse = (pFd->mmapSize & ~(szSyspage-1));
-- u8 *pReq = &pOrig[nReuse];
-+ SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
-+
-+ assert( pFile );
-
-- /* Unmap any pages of the existing mapping that cannot be reused. */
-- if( nReuse!=nOrig ){
-- osMunmap(pReq, nOrig-nReuse);
-- }
-+ /* Check if a thread in this process holds such a lock */
-+ if( pFile->eFileLock>SHARED_LOCK ){
-+ reserved = 1;
-+ }
-+
-+ /* Otherwise see if some other process holds it. */
-+ if( !reserved ){
-+ sem_t *pSem = pFile->pInode->pSem;
-+ struct stat statBuf;
-
--#if HAVE_MREMAP
-- pNew = osMremap(pOrig, nReuse, nNew, MREMAP_MAYMOVE);
-- zErr = "mremap";
--#else
-- pNew = osMmap(pReq, nNew-nReuse, flags, MAP_SHARED, h, nReuse);
-- if( pNew!=MAP_FAILED ){
-- if( pNew!=pReq ){
-- osMunmap(pNew, nNew - nReuse);
-- pNew = 0;
-- }else{
-- pNew = pOrig;
-+ if( sem_trywait(pSem)==-1 ){
-+ int tErrno = errno;
-+ if( EAGAIN != tErrno ){
-+ rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_CHECKRESERVEDLOCK);
-+ pFile->lastErrno = tErrno;
-+ } else {
-+ /* someone else has the lock when we are in NO_LOCK */
-+ reserved = (pFile->eFileLock < SHARED_LOCK);
- }
-+ }else{
-+ /* we could have it if we want it */
-+ sem_post(pSem);
- }
--#endif
--
-- /* The attempt to extend the existing mapping failed. Free it. */
-- if( pNew==MAP_FAILED || pNew==0 ){
-- osMunmap(pOrig, nReuse);
-- }
-- }
--
-- /* If pNew is still NULL, try to create an entirely new mapping. */
-- if( pNew==0 ){
-- pNew = osMmap(0, nNew, flags, MAP_SHARED, h, 0);
- }
-+ OSTRACE(("TEST WR-LOCK %d %d %d (sem)\n", pFile->h, rc, reserved));
-
-- if( pNew==MAP_FAILED ){
-- pNew = 0;
-- nNew = 0;
-- unixLogError(SQLITE_OK, zErr, pFd->zPath);
--
-- /* If the mmap() above failed, assume that all subsequent mmap() calls
-- ** will probably fail too. Fall back to using xRead/xWrite exclusively
-- ** in this case. */
-- pFd->mmapSizeMax = 0;
-- }
-- pFd->pMapRegion = (void *)pNew;
-- pFd->mmapSize = pFd->mmapSizeActual = nNew;
-+ *pResOut = reserved;
-+ return rc;
- }
--#endif
-
- /*
--** Memory map or remap the file opened by file-descriptor pFd (if the file
--** is already mapped, the existing mapping is replaced by the new). Or, if
--** there already exists a mapping for this file, and there are still
--** outstanding xFetch() references to it, this function is a no-op.
-+** Lock the file with the lock specified by parameter eFileLock - one
-+** of the following:
- **
--** If parameter nByte is non-negative, then it is the requested size of
--** the mapping to create. Otherwise, if nByte is less than zero, then the
--** requested size is the size of the file on disk. The actual size of the
--** created mapping is either the requested size or the value configured
--** using SQLITE_FCNTL_MMAP_LIMIT, whichever is smaller.
-+** (1) SHARED_LOCK
-+** (2) RESERVED_LOCK
-+** (3) PENDING_LOCK
-+** (4) EXCLUSIVE_LOCK
- **
--** SQLITE_OK is returned if no error occurs (even if the mapping is not
--** recreated as a result of outstanding references) or an SQLite error
--** code otherwise.
-+** Sometimes when requesting one lock state, additional lock states
-+** are inserted in between. The locking might fail on one of the later
-+** transitions leaving the lock state different from what it started but
-+** still short of its goal. The following chart shows the allowed
-+** transitions and the inserted intermediate states:
-+**
-+** UNLOCKED -> SHARED
-+** SHARED -> RESERVED
-+** SHARED -> (PENDING) -> EXCLUSIVE
-+** RESERVED -> (PENDING) -> EXCLUSIVE
-+** PENDING -> EXCLUSIVE
-+**
-+** Semaphore locks only really support EXCLUSIVE locks. We track intermediate
-+** lock states in the sqlite3_file structure, but all locks SHARED or
-+** above are really EXCLUSIVE locks and exclude all other processes from
-+** access the file.
-+**
-+** This routine will only increase a lock. Use the sqlite3OsUnlock()
-+** routine to lower a locking level.
- */
--static int unixMapfile(unixFile *pFd, i64 nByte){
--#if SQLITE_MAX_MMAP_SIZE>0
-- i64 nMap = nByte;
-- int rc;
--
-- assert( nMap>=0 || pFd->nFetchOut==0 );
-- if( pFd->nFetchOut>0 ) return SQLITE_OK;
-+static int semLock(sqlite3_file *id, int eFileLock) {
-+ unixFile *pFile = (unixFile*)id;
-+ int fd;
-+ sem_t *pSem = pFile->pInode->pSem;
-+ int rc = SQLITE_OK;
-
-- if( nMap<0 ){
-- struct stat statbuf; /* Low-level file information */
-- rc = osFstat(pFd->h, &statbuf);
-- if( rc!=SQLITE_OK ){
-- return SQLITE_IOERR_FSTAT;
-- }
-- nMap = statbuf.st_size;
-+ /* if we already have a lock, it is exclusive.
-+ ** Just adjust level and punt on outta here. */
-+ if (pFile->eFileLock > NO_LOCK) {
-+ pFile->eFileLock = eFileLock;
-+ rc = SQLITE_OK;
-+ goto sem_end_lock;
- }
-- if( nMap>pFd->mmapSizeMax ){
-- nMap = pFd->mmapSizeMax;
-+
-+ /* lock semaphore now but bail out when already locked. */
-+ if( sem_trywait(pSem)==-1 ){
-+ rc = SQLITE_BUSY;
-+ goto sem_end_lock;
- }
-
-- if( nMap!=pFd->mmapSize ){
-- if( nMap>0 ){
-- unixRemapfile(pFd, nMap);
-- }else{
-- unixUnmapfile(pFd);
-- }
-- }
--#endif
-+ /* got it, set the type and return ok */
-+ pFile->eFileLock = eFileLock;
-
-- return SQLITE_OK;
-+ sem_end_lock:
-+ return rc;
- }
-
- /*
--** If possible, return a pointer to a mapping of file fd starting at offset
--** iOff. The mapping must be valid for at least nAmt bytes.
--**
--** If such a pointer can be obtained, store it in *pp and return SQLITE_OK.
--** Or, if one cannot but no error occurs, set *pp to 0 and return SQLITE_OK.
--** Finally, if an error does occur, return an SQLite error code. The final
--** value of *pp is undefined in this case.
-+** Lower the locking level on file descriptor pFile to eFileLock. eFileLock
-+** must be either NO_LOCK or SHARED_LOCK.
- **
--** If this function does return a pointer, the caller must eventually
--** release the reference by calling unixUnfetch().
-+** If the locking level of the file descriptor is already at or below
-+** the requested locking level, this routine is a no-op.
- */
--static int unixFetch(sqlite3_file *fd, i64 iOff, int nAmt, void **pp){
--#if SQLITE_MAX_MMAP_SIZE>0
-- unixFile *pFd = (unixFile *)fd; /* The underlying database file */
--#endif
-- *pp = 0;
-+static int semUnlock(sqlite3_file *id, int eFileLock) {
-+ unixFile *pFile = (unixFile*)id;
-+ sem_t *pSem = pFile->pInode->pSem;
-
--#if SQLITE_MAX_MMAP_SIZE>0
-- if( pFd->mmapSizeMax>0 ){
-- if( pFd->pMapRegion==0 ){
-- int rc = unixMapfile(pFd, -1);
-- if( rc!=SQLITE_OK ) return rc;
-- }
-- if( pFd->mmapSize >= iOff+nAmt ){
-- *pp = &((u8 *)pFd->pMapRegion)[iOff];
-- pFd->nFetchOut++;
-+ assert( pFile );
-+ assert( pSem );
-+ OSTRACE(("UNLOCK %d %d was %d pid=%d (sem)\n", pFile->h, eFileLock,
-+ pFile->eFileLock, getpid()));
-+ assert( eFileLock<=SHARED_LOCK );
-+
-+ /* no-op if possible */
-+ if( pFile->eFileLock==eFileLock ){
-+ return SQLITE_OK;
-+ }
-+
-+ /* shared can just be set because we always have an exclusive */
-+ if (eFileLock==SHARED_LOCK) {
-+ pFile->eFileLock = eFileLock;
-+ return SQLITE_OK;
-+ }
-+
-+ /* no, really unlock. */
-+ if ( sem_post(pSem)==-1 ) {
-+ int rc, tErrno = errno;
-+ rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK);
-+ if( IS_LOCK_ERROR(rc) ){
-+ pFile->lastErrno = tErrno;
- }
-+ return rc;
- }
--#endif
-+ pFile->eFileLock = NO_LOCK;
- return SQLITE_OK;
- }
-
- /*
--** If the third argument is non-NULL, then this function releases a
--** reference obtained by an earlier call to unixFetch(). The second
--** argument passed to this function must be the same as the corresponding
--** argument that was passed to the unixFetch() invocation.
--**
--** Or, if the third argument is NULL, then this function is being called
--** to inform the VFS layer that, according to POSIX, any existing mapping
--** may now be invalid and should be unmapped.
--*/
--static int unixUnfetch(sqlite3_file *fd, i64 iOff, void *p){
-- unixFile *pFd = (unixFile *)fd; /* The underlying database file */
-- UNUSED_PARAMETER(iOff);
--
-- /* If p==0 (unmap the entire file) then there must be no outstanding
-- ** xFetch references. Or, if p!=0 (meaning it is an xFetch reference),
-- ** then there must be at least one outstanding. */
-- assert( (p==0)==(pFd->nFetchOut==0) );
--
-- /* If p!=0, it must match the iOff value. */
-- assert( p==0 || p==&((u8 *)pFd->pMapRegion)[iOff] );
--
-- if( p ){
-- pFd->nFetchOut--;
-- }else{
-- unixUnmapfile(pFd);
-+ ** Close a file.
-+ */
-+static int semClose(sqlite3_file *id) {
-+ if( id ){
-+ unixFile *pFile = (unixFile*)id;
-+ semUnlock(id, NO_LOCK);
-+ assert( pFile );
-+ unixEnterMutex();
-+ releaseInodeInfo(pFile);
-+ unixLeaveMutex();
-+ closeUnixFile(id);
- }
--
-- assert( pFd->nFetchOut>=0 );
- return SQLITE_OK;
- }
-
-+#endif /* OS_VXWORKS */
- /*
--** Here ends the implementation of all sqlite3_file methods.
-+** Named semaphore locking is only available on VxWorks.
- **
--********************** End sqlite3_file Methods *******************************
-+*************** End of the named semaphore lock implementation ****************
- ******************************************************************************/
-
--/*
--** This division contains definitions of sqlite3_io_methods objects that
--** implement various file locking strategies. It also contains definitions
--** of "finder" functions. A finder-function is used to locate the appropriate
--** sqlite3_io_methods object for a particular database file. The pAppData
--** field of the sqlite3_vfs VFS objects are initialized to be pointers to
--** the correct finder-function for that VFS.
--**
--** Most finder functions return a pointer to a fixed sqlite3_io_methods
--** object. The only interesting finder-function is autolockIoFinder, which
--** looks at the filesystem type and tries to guess the best locking
--** strategy from that.
--**
--** For finder-funtion F, two objects are created:
--**
--** (1) The real finder-function named "FImpt()".
--**
--** (2) A constant pointer to this function named just "F".
--**
--**
--** A pointer to the F pointer is used as the pAppData value for VFS
--** objects. We have to do this instead of letting pAppData point
--** directly at the finder-function since C90 rules prevent a void*
--** from be cast into a function pointer.
--**
--**
--** Each instance of this macro generates two objects:
-+
-+/******************************************************************************
-+*************************** Begin AFP Locking *********************************
- **
--** * A constant sqlite3_io_methods object call METHOD that has locking
--** methods CLOSE, LOCK, UNLOCK, CKRESLOCK.
-+** AFP is the Apple Filing Protocol. AFP is a network filesystem found
-+** on Apple Macintosh computers - both OS9 and OSX.
- **
--** * An I/O method finder function called FINDER that returns a pointer
--** to the METHOD object in the previous bullet.
-+** Third-party implementations of AFP are available. But this code here
-+** only works on OSX.
- */
--#define IOMETHODS(FINDER, METHOD, VERSION, CLOSE, LOCK, UNLOCK, CKLOCK) \
--static const sqlite3_io_methods METHOD = { \
-- VERSION, /* iVersion */ \
-- CLOSE, /* xClose */ \
-- unixRead, /* xRead */ \
-- unixWrite, /* xWrite */ \
-- unixTruncate, /* xTruncate */ \
-- unixSync, /* xSync */ \
-- unixFileSize, /* xFileSize */ \
-- LOCK, /* xLock */ \
-- UNLOCK, /* xUnlock */ \
-- CKLOCK, /* xCheckReservedLock */ \
-- unixFileControl, /* xFileControl */ \
-- unixSectorSize, /* xSectorSize */ \
-- unixDeviceCharacteristics, /* xDeviceCapabilities */ \
-- unixShmMap, /* xShmMap */ \
-- unixShmLock, /* xShmLock */ \
-- unixShmBarrier, /* xShmBarrier */ \
-- unixShmUnmap, /* xShmUnmap */ \
-- unixFetch, /* xFetch */ \
-- unixUnfetch, /* xUnfetch */ \
--}; \
--static const sqlite3_io_methods *FINDER##Impl(const char *z, unixFile *p){ \
-- UNUSED_PARAMETER(z); UNUSED_PARAMETER(p); \
-- return &METHOD; \
--} \
--static const sqlite3_io_methods *(*const FINDER)(const char*,unixFile *p) \
-- = FINDER##Impl;
-
-+#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
- /*
--** Here are all of the sqlite3_io_methods objects for each of the
--** locking strategies. Functions that return pointers to these methods
--** are also created.
-+** The afpLockingContext structure contains all afp lock specific state
- */
--IOMETHODS(
-- posixIoFinder, /* Finder function name */
-- posixIoMethods, /* sqlite3_io_methods object name */
-- 3, /* shared memory and mmap are enabled */
-- unixClose, /* xClose method */
-- unixLock, /* xLock method */
-- unixUnlock, /* xUnlock method */
-- unixCheckReservedLock /* xCheckReservedLock method */
--)
--IOMETHODS(
-- nolockIoFinder, /* Finder function name */
-- nolockIoMethods, /* sqlite3_io_methods object name */
-- 1, /* shared memory is disabled */
-- nolockClose, /* xClose method */
-- nolockLock, /* xLock method */
-- nolockUnlock, /* xUnlock method */
-- nolockCheckReservedLock /* xCheckReservedLock method */
--)
--IOMETHODS(
-- dotlockIoFinder, /* Finder function name */
-- dotlockIoMethods, /* sqlite3_io_methods object name */
-- 1, /* shared memory is disabled */
-- dotlockClose, /* xClose method */
-- dotlockLock, /* xLock method */
-- dotlockUnlock, /* xUnlock method */
-- dotlockCheckReservedLock /* xCheckReservedLock method */
--)
-+typedef struct afpLockingContext afpLockingContext;
-+struct afpLockingContext {
-+ int reserved;
-+ const char *dbPath; /* Name of the open file */
-+};
-
--#if SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORKS
--IOMETHODS(
-- flockIoFinder, /* Finder function name */
-- flockIoMethods, /* sqlite3_io_methods object name */
-- 1, /* shared memory is disabled */
-- flockClose, /* xClose method */
-- flockLock, /* xLock method */
-- flockUnlock, /* xUnlock method */
-- flockCheckReservedLock /* xCheckReservedLock method */
--)
--#endif
-+struct ByteRangeLockPB2
-+{
-+ unsigned long long offset; /* offset to first byte to lock */
-+ unsigned long long length; /* nbr of bytes to lock */
-+ unsigned long long retRangeStart; /* nbr of 1st byte locked if successful */
-+ unsigned char unLockFlag; /* 1 = unlock, 0 = lock */
-+ unsigned char startEndFlag; /* 1=rel to end of fork, 0=rel to start */
-+ int fd; /* file desc to assoc this lock with */
-+};
-
--#if OS_VXWORKS
--IOMETHODS(
-- semIoFinder, /* Finder function name */
-- semIoMethods, /* sqlite3_io_methods object name */
-- 1, /* shared memory is disabled */
-- semClose, /* xClose method */
-- semLock, /* xLock method */
-- semUnlock, /* xUnlock method */
-- semCheckReservedLock /* xCheckReservedLock method */
--)
--#endif
-+#define afpfsByteRangeLock2FSCTL _IOWR('z', 23, struct ByteRangeLockPB2)
-
--#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
--IOMETHODS(
-- afpIoFinder, /* Finder function name */
-- afpIoMethods, /* sqlite3_io_methods object name */
-- 1, /* shared memory is disabled */
-- afpClose, /* xClose method */
-- afpLock, /* xLock method */
-- afpUnlock, /* xUnlock method */
-- afpCheckReservedLock /* xCheckReservedLock method */
--)
--#endif
-+/*
-+** This is a utility for setting or clearing a bit-range lock on an
-+** AFP filesystem.
-+**
-+** Return SQLITE_OK on success, SQLITE_BUSY on failure.
-+*/
-+static int afpSetLock(
-+ const char *path, /* Name of the file to be locked or unlocked */
-+ unixFile *pFile, /* Open file descriptor on path */
-+ unsigned long long offset, /* First byte to be locked */
-+ unsigned long long length, /* Number of bytes to lock */
-+ int setLockFlag /* True to set lock. False to clear lock */
-+){
-+ struct ByteRangeLockPB2 pb;
-+ int err;
-+
-+ pb.unLockFlag = setLockFlag ? 0 : 1;
-+ pb.startEndFlag = 0;
-+ pb.offset = offset;
-+ pb.length = length;
-+ pb.fd = pFile->h;
-+
-+ OSTRACE(("AFPSETLOCK [%s] for %d%s in range %llx:%llx\n",
-+ (setLockFlag?"ON":"OFF"), pFile->h, (pb.fd==-1?"[testval-1]":""),
-+ offset, length));
-+ err = fsctl(path, afpfsByteRangeLock2FSCTL, &pb, 0);
-+ if ( err==-1 ) {
-+ int rc;
-+ int tErrno = errno;
-+ OSTRACE(("AFPSETLOCK failed to fsctl() '%s' %d %s\n",
-+ path, tErrno, strerror(tErrno)));
-+#ifdef SQLITE_IGNORE_AFP_LOCK_ERRORS
-+ rc = SQLITE_BUSY;
-+#else
-+ rc = sqliteErrorFromPosixError(tErrno,
-+ setLockFlag ? SQLITE_IOERR_LOCK : SQLITE_IOERR_UNLOCK);
-+#endif /* SQLITE_IGNORE_AFP_LOCK_ERRORS */
-+ if( IS_LOCK_ERROR(rc) ){
-+ pFile->lastErrno = tErrno;
-+ }
-+ return rc;
-+ } else {
-+ return SQLITE_OK;
-+ }
-+}
-
- /*
--** The proxy locking method is a "super-method" in the sense that it
--** opens secondary file descriptors for the conch and lock files and
--** it uses proxy, dot-file, AFP, and flock() locking methods on those
--** secondary files. For this reason, the division that implements
--** proxy locking is located much further down in the file. But we need
--** to go ahead and define the sqlite3_io_methods and finder function
--** for proxy locking here. So we forward declare the I/O methods.
-+** This routine checks if there is a RESERVED lock held on the specified
-+** file by this or any other process. If such a lock is held, set *pResOut
-+** to a non-zero value otherwise *pResOut is set to zero. The return value
-+** is set to SQLITE_OK unless an I/O error occurs during lock checking.
- */
--#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
--static int proxyClose(sqlite3_file*);
--static int proxyLock(sqlite3_file*, int);
--static int proxyUnlock(sqlite3_file*, int);
--static int proxyCheckReservedLock(sqlite3_file*, int*);
--IOMETHODS(
-- proxyIoFinder, /* Finder function name */
-- proxyIoMethods, /* sqlite3_io_methods object name */
-- 1, /* shared memory is disabled */
-- proxyClose, /* xClose method */
-- proxyLock, /* xLock method */
-- proxyUnlock, /* xUnlock method */
-- proxyCheckReservedLock /* xCheckReservedLock method */
--)
--#endif
-+static int afpCheckReservedLock(sqlite3_file *id, int *pResOut){
-+ int rc = SQLITE_OK;
-+ int reserved = 0;
-+ unixFile *pFile = (unixFile*)id;
-+ afpLockingContext *context;
-+
-+ SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
-+
-+ assert( pFile );
-+ context = (afpLockingContext *) pFile->lockingContext;
-+ if( context->reserved ){
-+ *pResOut = 1;
-+ return SQLITE_OK;
-+ }
-+ unixEnterMutex(); /* Because pFile->pInode is shared across threads */
-+
-+ /* Check if a thread in this process holds such a lock */
-+ if( pFile->pInode->eFileLock>SHARED_LOCK ){
-+ reserved = 1;
-+ }
-+
-+ /* Otherwise see if some other process holds it.
-+ */
-+ if( !reserved ){
-+ /* lock the RESERVED byte */
-+ int lrc = afpSetLock(context->dbPath, pFile, RESERVED_BYTE, 1,1);
-+ if( SQLITE_OK==lrc ){
-+ /* if we succeeded in taking the reserved lock, unlock it to restore
-+ ** the original state */
-+ lrc = afpSetLock(context->dbPath, pFile, RESERVED_BYTE, 1, 0);
-+ } else {
-+ /* if we failed to get the lock then someone else must have it */
-+ reserved = 1;
-+ }
-+ if( IS_LOCK_ERROR(lrc) ){
-+ rc=lrc;
-+ }
-+ }
-+
-+ unixLeaveMutex();
-+ OSTRACE(("TEST WR-LOCK %d %d %d (afp)\n", pFile->h, rc, reserved));
-+
-+ *pResOut = reserved;
-+ return rc;
-+}
-
--/* nfs lockd on OSX 10.3+ doesn't clear write locks when a read lock is set */
--#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
--IOMETHODS(
-- nfsIoFinder, /* Finder function name */
-- nfsIoMethods, /* sqlite3_io_methods object name */
-- 1, /* shared memory is disabled */
-- unixClose, /* xClose method */
-- unixLock, /* xLock method */
-- nfsUnlock, /* xUnlock method */
-- unixCheckReservedLock /* xCheckReservedLock method */
--)
--#endif
-+/*
-+** Lock the file with the lock specified by parameter eFileLock - one
-+** of the following:
-+**
-+** (1) SHARED_LOCK
-+** (2) RESERVED_LOCK
-+** (3) PENDING_LOCK
-+** (4) EXCLUSIVE_LOCK
-+**
-+** Sometimes when requesting one lock state, additional lock states
-+** are inserted in between. The locking might fail on one of the later
-+** transitions leaving the lock state different from what it started but
-+** still short of its goal. The following chart shows the allowed
-+** transitions and the inserted intermediate states:
-+**
-+** UNLOCKED -> SHARED
-+** SHARED -> RESERVED
-+** SHARED -> (PENDING) -> EXCLUSIVE
-+** RESERVED -> (PENDING) -> EXCLUSIVE
-+** PENDING -> EXCLUSIVE
-+**
-+** This routine will only increase a lock. Use the sqlite3OsUnlock()
-+** routine to lower a locking level.
-+*/
-+static int afpLock(sqlite3_file *id, int eFileLock){
-+ int rc = SQLITE_OK;
-+ unixFile *pFile = (unixFile*)id;
-+ unixInodeInfo *pInode = pFile->pInode;
-+ afpLockingContext *context = (afpLockingContext *) pFile->lockingContext;
-+
-+ assert( pFile );
-+ OSTRACE(("LOCK %d %s was %s(%s,%d) pid=%d (afp)\n", pFile->h,
-+ azFileLock(eFileLock), azFileLock(pFile->eFileLock),
-+ azFileLock(pInode->eFileLock), pInode->nShared , getpid()));
-+
-+ /* If there is already a lock of this type or more restrictive on the
-+ ** unixFile, do nothing. Don't use the afp_end_lock: exit path, as
-+ ** unixEnterMutex() hasn't been called yet.
-+ */
-+ if( pFile->eFileLock>=eFileLock ){
-+ OSTRACE(("LOCK %d %s ok (already held) (afp)\n", pFile->h,
-+ azFileLock(eFileLock)));
-+ return SQLITE_OK;
-+ }
-+
-+ /* Make sure the locking sequence is correct
-+ ** (1) We never move from unlocked to anything higher than shared lock.
-+ ** (2) SQLite never explicitly requests a pendig lock.
-+ ** (3) A shared lock is always held when a reserve lock is requested.
-+ */
-+ assert( pFile->eFileLock!=NO_LOCK || eFileLock==SHARED_LOCK );
-+ assert( eFileLock!=PENDING_LOCK );
-+ assert( eFileLock!=RESERVED_LOCK || pFile->eFileLock==SHARED_LOCK );
-+
-+ /* This mutex is needed because pFile->pInode is shared across threads
-+ */
-+ unixEnterMutex();
-+ pInode = pFile->pInode;
-+
-+ /* If some thread using this PID has a lock via a different unixFile*
-+ ** handle that precludes the requested lock, return BUSY.
-+ */
-+ if( (pFile->eFileLock!=pInode->eFileLock &&
-+ (pInode->eFileLock>=PENDING_LOCK || eFileLock>SHARED_LOCK))
-+ ){
-+ rc = SQLITE_BUSY;
-+ goto afp_end_lock;
-+ }
-+
-+ /* If a SHARED lock is requested, and some thread using this PID already
-+ ** has a SHARED or RESERVED lock, then increment reference counts and
-+ ** return SQLITE_OK.
-+ */
-+ if( eFileLock==SHARED_LOCK &&
-+ (pInode->eFileLock==SHARED_LOCK || pInode->eFileLock==RESERVED_LOCK) ){
-+ assert( eFileLock==SHARED_LOCK );
-+ assert( pFile->eFileLock==0 );
-+ assert( pInode->nShared>0 );
-+ pFile->eFileLock = SHARED_LOCK;
-+ pInode->nShared++;
-+ pInode->nLock++;
-+ goto afp_end_lock;
-+ }
-+
-+ /* A PENDING lock is needed before acquiring a SHARED lock and before
-+ ** acquiring an EXCLUSIVE lock. For the SHARED lock, the PENDING will
-+ ** be released.
-+ */
-+ if( eFileLock==SHARED_LOCK
-+ || (eFileLock==EXCLUSIVE_LOCK && pFile->eFileLock<PENDING_LOCK)
-+ ){
-+ int failed;
-+ failed = afpSetLock(context->dbPath, pFile, PENDING_BYTE, 1, 1);
-+ if (failed) {
-+ rc = failed;
-+ goto afp_end_lock;
-+ }
-+ }
-+
-+ /* If control gets to this point, then actually go ahead and make
-+ ** operating system calls for the specified lock.
-+ */
-+ if( eFileLock==SHARED_LOCK ){
-+ int lrc1, lrc2, lrc1Errno = 0;
-+ long lk, mask;
-+
-+ assert( pInode->nShared==0 );
-+ assert( pInode->eFileLock==0 );
-+
-+ mask = (sizeof(long)==8) ? LARGEST_INT64 : 0x7fffffff;
-+ /* Now get the read-lock SHARED_LOCK */
-+ /* note that the quality of the randomness doesn't matter that much */
-+ lk = random();
-+ pInode->sharedByte = (lk & mask)%(SHARED_SIZE - 1);
-+ lrc1 = afpSetLock(context->dbPath, pFile,
-+ SHARED_FIRST+pInode->sharedByte, 1, 1);
-+ if( IS_LOCK_ERROR(lrc1) ){
-+ lrc1Errno = pFile->lastErrno;
-+ }
-+ /* Drop the temporary PENDING lock */
-+ lrc2 = afpSetLock(context->dbPath, pFile, PENDING_BYTE, 1, 0);
-+
-+ if( IS_LOCK_ERROR(lrc1) ) {
-+ pFile->lastErrno = lrc1Errno;
-+ rc = lrc1;
-+ goto afp_end_lock;
-+ } else if( IS_LOCK_ERROR(lrc2) ){
-+ rc = lrc2;
-+ goto afp_end_lock;
-+ } else if( lrc1 != SQLITE_OK ) {
-+ rc = lrc1;
-+ } else {
-+ pFile->eFileLock = SHARED_LOCK;
-+ pInode->nLock++;
-+ pInode->nShared = 1;
-+ }
-+ }else if( eFileLock==EXCLUSIVE_LOCK && pInode->nShared>1 ){
-+ /* We are trying for an exclusive lock but another thread in this
-+ ** same process is still holding a shared lock. */
-+ rc = SQLITE_BUSY;
-+ }else{
-+ /* The request was for a RESERVED or EXCLUSIVE lock. It is
-+ ** assumed that there is a SHARED or greater lock on the file
-+ ** already.
-+ */
-+ int failed = 0;
-+ assert( 0!=pFile->eFileLock );
-+ if (eFileLock >= RESERVED_LOCK && pFile->eFileLock < RESERVED_LOCK) {
-+ /* Acquire a RESERVED lock */
-+ failed = afpSetLock(context->dbPath, pFile, RESERVED_BYTE, 1,1);
-+ if( !failed ){
-+ context->reserved = 1;
-+ }
-+ }
-+ if (!failed && eFileLock == EXCLUSIVE_LOCK) {
-+ /* Acquire an EXCLUSIVE lock */
-+
-+ /* Remove the shared lock before trying the range. we'll need to
-+ ** reestablish the shared lock if we can't get the afpUnlock
-+ */
-+ if( !(failed = afpSetLock(context->dbPath, pFile, SHARED_FIRST +
-+ pInode->sharedByte, 1, 0)) ){
-+ int failed2 = SQLITE_OK;
-+ /* now attemmpt to get the exclusive lock range */
-+ failed = afpSetLock(context->dbPath, pFile, SHARED_FIRST,
-+ SHARED_SIZE, 1);
-+ if( failed && (failed2 = afpSetLock(context->dbPath, pFile,
-+ SHARED_FIRST + pInode->sharedByte, 1, 1)) ){
-+ /* Can't reestablish the shared lock. Sqlite can't deal, this is
-+ ** a critical I/O error
-+ */
-+ rc = ((failed & SQLITE_IOERR) == SQLITE_IOERR) ? failed2 :
-+ SQLITE_IOERR_LOCK;
-+ goto afp_end_lock;
-+ }
-+ }else{
-+ rc = failed;
-+ }
-+ }
-+ if( failed ){
-+ rc = failed;
-+ }
-+ }
-+
-+ if( rc==SQLITE_OK ){
-+ pFile->eFileLock = eFileLock;
-+ pInode->eFileLock = eFileLock;
-+ }else if( eFileLock==EXCLUSIVE_LOCK ){
-+ pFile->eFileLock = PENDING_LOCK;
-+ pInode->eFileLock = PENDING_LOCK;
-+ }
-+
-+afp_end_lock:
-+ unixLeaveMutex();
-+ OSTRACE(("LOCK %d %s %s (afp)\n", pFile->h, azFileLock(eFileLock),
-+ rc==SQLITE_OK ? "ok" : "failed"));
-+ return rc;
-+}
-
--#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
--/*
--** This "finder" function attempts to determine the best locking strategy
--** for the database file "filePath". It then returns the sqlite3_io_methods
--** object that implements that strategy.
-+/*
-+** Lower the locking level on file descriptor pFile to eFileLock. eFileLock
-+** must be either NO_LOCK or SHARED_LOCK.
- **
--** This is for MacOSX only.
-+** If the locking level of the file descriptor is already at or below
-+** the requested locking level, this routine is a no-op.
- */
--static const sqlite3_io_methods *autolockIoFinderImpl(
-- const char *filePath, /* name of the database file */
-- unixFile *pNew /* open file object for the database file */
--){
-- static const struct Mapping {
-- const char *zFilesystem; /* Filesystem type name */
-- const sqlite3_io_methods *pMethods; /* Appropriate locking method */
-- } aMap[] = {
-- { "hfs", &posixIoMethods },
-- { "ufs", &posixIoMethods },
-- { "afpfs", &afpIoMethods },
-- { "smbfs", &afpIoMethods },
-- { "webdav", &nolockIoMethods },
-- { 0, 0 }
-- };
-- int i;
-- struct statfs fsInfo;
-- struct flock lockInfo;
-+static int afpUnlock(sqlite3_file *id, int eFileLock) {
-+ int rc = SQLITE_OK;
-+ unixFile *pFile = (unixFile*)id;
-+ unixInodeInfo *pInode;
-+ afpLockingContext *context = (afpLockingContext *) pFile->lockingContext;
-+ int skipShared = 0;
-+#ifdef SQLITE_TEST
-+ int h = pFile->h;
-+#endif
-
-- if( !filePath ){
-- /* If filePath==NULL that means we are dealing with a transient file
-- ** that does not need to be locked. */
-- return &nolockIoMethods;
-+ assert( pFile );
-+ OSTRACE(("UNLOCK %d %d was %d(%d,%d) pid=%d (afp)\n", pFile->h, eFileLock,
-+ pFile->eFileLock, pFile->pInode->eFileLock, pFile->pInode->nShared,
-+ getpid()));
-+
-+ assert( eFileLock<=SHARED_LOCK );
-+ if( pFile->eFileLock<=eFileLock ){
-+ return SQLITE_OK;
- }
-- if( statfs(filePath, &fsInfo) != -1 ){
-- if( fsInfo.f_flags & MNT_RDONLY ){
-- return &nolockIoMethods;
-+ unixEnterMutex();
-+ pInode = pFile->pInode;
-+ assert( pInode->nShared!=0 );
-+ if( pFile->eFileLock>SHARED_LOCK ){
-+ assert( pInode->eFileLock==pFile->eFileLock );
-+ SimulateIOErrorBenign(1);
-+ SimulateIOError( h=(-1) )
-+ SimulateIOErrorBenign(0);
-+
-+#ifdef SQLITE_DEBUG
-+ /* When reducing a lock such that other processes can start
-+ ** reading the database file again, make sure that the
-+ ** transaction counter was updated if any part of the database
-+ ** file changed. If the transaction counter is not updated,
-+ ** other connections to the same file might not realize that
-+ ** the file has changed and hence might not know to flush their
-+ ** cache. The use of a stale cache can lead to database corruption.
-+ */
-+ assert( pFile->inNormalWrite==0
-+ || pFile->dbUpdate==0
-+ || pFile->transCntrChng==1 );
-+ pFile->inNormalWrite = 0;
-+#endif
-+
-+ if( pFile->eFileLock==EXCLUSIVE_LOCK ){
-+ rc = afpSetLock(context->dbPath, pFile, SHARED_FIRST, SHARED_SIZE, 0);
-+ if( rc==SQLITE_OK && (eFileLock==SHARED_LOCK || pInode->nShared>1) ){
-+ /* only re-establish the shared lock if necessary */
-+ int sharedLockByte = SHARED_FIRST+pInode->sharedByte;
-+ rc = afpSetLock(context->dbPath, pFile, sharedLockByte, 1, 1);
-+ } else {
-+ skipShared = 1;
-+ }
- }
-- for(i=0; aMap[i].zFilesystem; i++){
-- if( strcmp(fsInfo.f_fstypename, aMap[i].zFilesystem)==0 ){
-- return aMap[i].pMethods;
-+ if( rc==SQLITE_OK && pFile->eFileLock>=PENDING_LOCK ){
-+ rc = afpSetLock(context->dbPath, pFile, PENDING_BYTE, 1, 0);
-+ }
-+ if( rc==SQLITE_OK && pFile->eFileLock>=RESERVED_LOCK && context->reserved ){
-+ rc = afpSetLock(context->dbPath, pFile, RESERVED_BYTE, 1, 0);
-+ if( !rc ){
-+ context->reserved = 0;
- }
- }
-+ if( rc==SQLITE_OK && (eFileLock==SHARED_LOCK || pInode->nShared>1)){
-+ pInode->eFileLock = SHARED_LOCK;
-+ }
- }
-+ if( rc==SQLITE_OK && eFileLock==NO_LOCK ){
-
-- /* Default case. Handles, amongst others, "nfs".
-- ** Test byte-range lock using fcntl(). If the call succeeds,
-- ** assume that the file-system supports POSIX style locks.
-- */
-- lockInfo.l_len = 1;
-- lockInfo.l_start = 0;
-- lockInfo.l_whence = SEEK_SET;
-- lockInfo.l_type = F_RDLCK;
-- if( osFcntl(pNew->h, F_GETLK, &lockInfo)!=-1 ) {
-- if( strcmp(fsInfo.f_fstypename, "nfs")==0 ){
-- return &nfsIoMethods;
-- } else {
-- return &posixIoMethods;
-+ /* Decrement the shared lock counter. Release the lock using an
-+ ** OS call only when all threads in this same process have released
-+ ** the lock.
-+ */
-+ unsigned long long sharedLockByte = SHARED_FIRST+pInode->sharedByte;
-+ pInode->nShared--;
-+ if( pInode->nShared==0 ){
-+ SimulateIOErrorBenign(1);
-+ SimulateIOError( h=(-1) )
-+ SimulateIOErrorBenign(0);
-+ if( !skipShared ){
-+ rc = afpSetLock(context->dbPath, pFile, sharedLockByte, 1, 0);
-+ }
-+ if( !rc ){
-+ pInode->eFileLock = NO_LOCK;
-+ pFile->eFileLock = NO_LOCK;
-+ }
-+ }
-+ if( rc==SQLITE_OK ){
-+ pInode->nLock--;
-+ assert( pInode->nLock>=0 );
-+ if( pInode->nLock==0 ){
-+ closePendingFds(pFile);
-+ }
- }
-- }else{
-- return &dotlockIoMethods;
- }
-+
-+ unixLeaveMutex();
-+ if( rc==SQLITE_OK ) pFile->eFileLock = eFileLock;
-+ return rc;
- }
--static const sqlite3_io_methods
-- *(*const autolockIoFinder)(const char*,unixFile*) = autolockIoFinderImpl;
--
--#endif /* defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE */
-
--#if OS_VXWORKS && SQLITE_ENABLE_LOCKING_STYLE
--/*
--** This "finder" function attempts to determine the best locking strategy
--** for the database file "filePath". It then returns the sqlite3_io_methods
--** object that implements that strategy.
--**
--** This is for VXWorks only.
-+/*
-+** Close a file & cleanup AFP specific locking context
- */
--static const sqlite3_io_methods *autolockIoFinderImpl(
-- const char *filePath, /* name of the database file */
-- unixFile *pNew /* the open file object */
--){
-- struct flock lockInfo;
--
-- if( !filePath ){
-- /* If filePath==NULL that means we are dealing with a transient file
-- ** that does not need to be locked. */
-- return &nolockIoMethods;
-- }
--
-- /* Test if fcntl() is supported and use POSIX style locks.
-- ** Otherwise fall back to the named semaphore method.
-- */
-- lockInfo.l_len = 1;
-- lockInfo.l_start = 0;
-- lockInfo.l_whence = SEEK_SET;
-- lockInfo.l_type = F_RDLCK;
-- if( osFcntl(pNew->h, F_GETLK, &lockInfo)!=-1 ) {
-- return &posixIoMethods;
-- }else{
-- return &semIoMethods;
-+static int afpClose(sqlite3_file *id) {
-+ int rc = SQLITE_OK;
-+ if( id ){
-+ unixFile *pFile = (unixFile*)id;
-+ afpUnlock(id, NO_LOCK);
-+ unixEnterMutex();
-+ if( pFile->pInode && pFile->pInode->nLock ){
-+ /* If there are outstanding locks, do not actually close the file just
-+ ** yet because that would clear those locks. Instead, add the file
-+ ** descriptor to pInode->aPending. It will be automatically closed when
-+ ** the last lock is cleared.
-+ */
-+ setPendingFd(pFile);
-+ }
-+ releaseInodeInfo(pFile);
-+ sqlite3_free(pFile->lockingContext);
-+ rc = closeUnixFile(id);
-+ unixLeaveMutex();
- }
-+ return rc;
- }
--static const sqlite3_io_methods
-- *(*const autolockIoFinder)(const char*,unixFile*) = autolockIoFinderImpl;
-
--#endif /* OS_VXWORKS && SQLITE_ENABLE_LOCKING_STYLE */
-+#endif /* defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE */
-+/*
-+** The code above is the AFP lock implementation. The code is specific
-+** to MacOSX and does not work on other unix platforms. No alternative
-+** is available. If you don't compile for a mac, then the "unix-afp"
-+** VFS is not available.
-+**
-+********************* End of the AFP lock implementation **********************
-+******************************************************************************/
-+
-+/******************************************************************************
-+*************************** Begin NFS Locking ********************************/
-
-+#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
- /*
--** An abstract type for a pointer to a IO method finder function:
--*/
--typedef const sqlite3_io_methods *(*finder_type)(const char*,unixFile*);
-+ ** Lower the locking level on file descriptor pFile to eFileLock. eFileLock
-+ ** must be either NO_LOCK or SHARED_LOCK.
-+ **
-+ ** If the locking level of the file descriptor is already at or below
-+ ** the requested locking level, this routine is a no-op.
-+ */
-+static int nfsUnlock(sqlite3_file *id, int eFileLock){
-+ return posixUnlock(id, eFileLock, 1);
-+}
-
-+#endif /* defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE */
-+/*
-+** The code above is the NFS lock implementation. The code is specific
-+** to MacOSX and does not work on other unix platforms. No alternative
-+** is available.
-+**
-+********************* End of the NFS lock implementation **********************
-+******************************************************************************/
-
--/****************************************************************************
--**************************** sqlite3_vfs methods ****************************
-+/******************************************************************************
-+**************** Non-locking sqlite3_file methods *****************************
- **
--** This division contains the implementation of methods on the
--** sqlite3_vfs object.
-+** The next division contains implementations for all methods of the
-+** sqlite3_file object other than the locking methods. The locking
-+** methods were defined in divisions above (one locking method per
-+** division). Those methods that are common to all locking modes
-+** are gather together into this division.
- */
-
- /*
--** Initialize the contents of the unixFile structure pointed to by pId.
-+** Seek to the offset passed as the second argument, then read cnt
-+** bytes into pBuf. Return the number of bytes actually read.
-+**
-+** NB: If you define USE_PREAD or USE_PREAD64, then it might also
-+** be necessary to define _XOPEN_SOURCE to be 500. This varies from
-+** one system to another. Since SQLite does not define USE_PREAD
-+** any any form by default, we will not attempt to define _XOPEN_SOURCE.
-+** See tickets #2741 and #2681.
-+**
-+** To avoid stomping the errno value on a failed read the lastErrno value
-+** is set before returning.
- */
--static int fillInUnixFile(
-- sqlite3_vfs *pVfs, /* Pointer to vfs object */
-- int h, /* Open file descriptor of file being opened */
-- sqlite3_file *pId, /* Write to the unixFile structure here */
-- const char *zFilename, /* Name of the file being opened */
-- int ctrlFlags /* Zero or more UNIXFILE_* values */
--){
-- const sqlite3_io_methods *pLockingStyle;
-- unixFile *pNew = (unixFile *)pId;
-- int rc = SQLITE_OK;
--
-- assert( pNew->pInode==NULL );
--
-- /* Usually the path zFilename should not be a relative pathname. The
-- ** exception is when opening the proxy "conch" file in builds that
-- ** include the special Apple locking styles.
-- */
--#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
-- assert( zFilename==0 || zFilename[0]=='/'
-- || pVfs->pAppData==(void*)&autolockIoFinder );
-+static int seekAndRead(unixFile *id, sqlite3_int64 offset, void *pBuf, int cnt){
-+ int got;
-+ int prior = 0;
-+#if (!defined(USE_PREAD) && !defined(USE_PREAD64))
-+ i64 newOffset;
-+#endif
-+ TIMER_START;
-+ assert( cnt==(cnt&0x1ffff) );
-+ cnt &= 0x1ffff;
-+ do{
-+#if defined(USE_PREAD)
-+ got = osPread(id->h, pBuf, cnt, offset);
-+ SimulateIOError( got = -1 );
-+#elif defined(USE_PREAD64)
-+ got = osPread64(id->h, pBuf, cnt, offset);
-+ SimulateIOError( got = -1 );
- #else
-- assert( zFilename==0 || zFilename[0]=='/' );
-+ newOffset = lseek(id->h, offset, SEEK_SET);
-+ SimulateIOError( newOffset-- );
-+ if( newOffset!=offset ){
-+ if( newOffset == -1 ){
-+ ((unixFile*)id)->lastErrno = errno;
-+ }else{
-+ ((unixFile*)id)->lastErrno = 0;
-+ }
-+ return -1;
-+ }
-+ got = osRead(id->h, pBuf, cnt);
- #endif
-+ if( got==cnt ) break;
-+ if( got<0 ){
-+ if( errno==EINTR ){ got = 1; continue; }
-+ prior = 0;
-+ ((unixFile*)id)->lastErrno = errno;
-+ break;
-+ }else if( got>0 ){
-+ cnt -= got;
-+ offset += got;
-+ prior += got;
-+ pBuf = (void*)(got + (char*)pBuf);
-+ }
-+ }while( got>0 );
-+ TIMER_END;
-+ OSTRACE(("READ %-3d %5d %7lld %llu\n",
-+ id->h, got+prior, offset-prior, TIMER_ELAPSED));
-+ return got+prior;
-+}
-
-- /* No locking occurs in temporary files */
-- assert( zFilename!=0 || (ctrlFlags & UNIXFILE_NOLOCK)!=0 );
-+/*
-+** Read data from a file into a buffer. Return SQLITE_OK if all
-+** bytes were read successfully and SQLITE_IOERR if anything goes
-+** wrong.
-+*/
-+static int unixRead(
-+ sqlite3_file *id,
-+ void *pBuf,
-+ int amt,
-+ sqlite3_int64 offset
-+){
-+ unixFile *pFile = (unixFile *)id;
-+ int got;
-+ assert( id );
-+ assert( offset>=0 );
-+ assert( amt>0 );
-
-- OSTRACE(("OPEN %-3d %s\n", h, zFilename));
-- pNew->h = h;
-- pNew->pVfs = pVfs;
-- pNew->zPath = zFilename;
-- pNew->ctrlFlags = (u8)ctrlFlags;
-- pNew->mmapSizeMax = sqlite3GlobalConfig.szMmap;
-- if( sqlite3_uri_boolean(((ctrlFlags & UNIXFILE_URI) ? zFilename : 0),
-- "psow", SQLITE_POWERSAFE_OVERWRITE) ){
-- pNew->ctrlFlags |= UNIXFILE_PSOW;
-- }
-- if( strcmp(pVfs->zName,"unix-excl")==0 ){
-- pNew->ctrlFlags |= UNIXFILE_EXCL;
-- }
-+ /* If this is a database file (not a journal, master-journal or temp
-+ ** file), the bytes in the locking range should never be read or written. */
-+#if 0
-+ assert( pFile->pUnused==0
-+ || offset>=PENDING_BYTE+512
-+ || offset+amt<=PENDING_BYTE
-+ );
-+#endif
-
--#if OS_VXWORKS
-- pNew->pId = vxworksFindFileId(zFilename);
-- if( pNew->pId==0 ){
-- ctrlFlags |= UNIXFILE_NOLOCK;
-- rc = SQLITE_NOMEM;
-+#if SQLITE_MAX_MMAP_SIZE>0
-+ /* Deal with as much of this read request as possible by transfering
-+ ** data from the memory mapping using memcpy(). */
-+ if( offset<pFile->mmapSize ){
-+ if( offset+amt <= pFile->mmapSize ){
-+ memcpy(pBuf, &((u8 *)(pFile->pMapRegion))[offset], amt);
-+ return SQLITE_OK;
-+ }else{
-+ int nCopy = pFile->mmapSize - offset;
-+ memcpy(pBuf, &((u8 *)(pFile->pMapRegion))[offset], nCopy);
-+ pBuf = &((u8 *)pBuf)[nCopy];
-+ amt -= nCopy;
-+ offset += nCopy;
-+ }
- }
- #endif
-
-- if( ctrlFlags & UNIXFILE_NOLOCK ){
-- pLockingStyle = &nolockIoMethods;
-+ got = seekAndRead(pFile, offset, pBuf, amt);
-+ if( got==amt ){
-+ return SQLITE_OK;
-+ }else if( got<0 ){
-+ /* lastErrno set by seekAndRead */
-+ return SQLITE_IOERR_READ;
- }else{
-- pLockingStyle = (**(finder_type*)pVfs->pAppData)(zFilename, pNew);
--#if SQLITE_ENABLE_LOCKING_STYLE
-- /* Cache zFilename in the locking context (AFP and dotlock override) for
-- ** proxyLock activation is possible (remote proxy is based on db name)
-- ** zFilename remains valid until file is closed, to support */
-- pNew->lockingContext = (void*)zFilename;
--#endif
-+ pFile->lastErrno = 0; /* not a system error */
-+ /* Unread parts of the buffer must be zero-filled */
-+ memset(&((char*)pBuf)[got], 0, amt-got);
-+ return SQLITE_IOERR_SHORT_READ;
- }
-+}
-
-- if( pLockingStyle == &posixIoMethods
--#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
-- || pLockingStyle == &nfsIoMethods
--#endif
-- ){
-- unixEnterMutex();
-- rc = findInodeInfo(pNew, &pNew->pInode);
-- if( rc!=SQLITE_OK ){
-- /* If an error occurred in findInodeInfo(), close the file descriptor
-- ** immediately, before releasing the mutex. findInodeInfo() may fail
-- ** in two scenarios:
-- **
-- ** (a) A call to fstat() failed.
-- ** (b) A malloc failed.
-- **
-- ** Scenario (b) may only occur if the process is holding no other
-- ** file descriptors open on the same file. If there were other file
-- ** descriptors on this file, then no malloc would be required by
-- ** findInodeInfo(). If this is the case, it is quite safe to close
-- ** handle h - as it is guaranteed that no posix locks will be released
-- ** by doing so.
-- **
-- ** If scenario (a) caused the error then things are not so safe. The
-- ** implicit assumption here is that if fstat() fails, things are in
-- ** such bad shape that dropping a lock or two doesn't matter much.
-- */
-- robust_close(pNew, h, __LINE__);
-- h = -1;
-+/*
-+** Attempt to seek the file-descriptor passed as the first argument to
-+** absolute offset iOff, then attempt to write nBuf bytes of data from
-+** pBuf to it. If an error occurs, return -1 and set *piErrno. Otherwise,
-+** return the actual number of bytes written (which may be less than
-+** nBuf).
-+*/
-+static int seekAndWriteFd(
-+ int fd, /* File descriptor to write to */
-+ i64 iOff, /* File offset to begin writing at */
-+ const void *pBuf, /* Copy data from this buffer to the file */
-+ int nBuf, /* Size of buffer pBuf in bytes */
-+ int *piErrno /* OUT: Error number if error occurs */
-+){
-+ int rc = 0; /* Value returned by system call */
-+
-+ assert( nBuf==(nBuf&0x1ffff) );
-+ nBuf &= 0x1ffff;
-+ TIMER_START;
-+
-+#if defined(USE_PREAD)
-+ do{ rc = osPwrite(fd, pBuf, nBuf, iOff); }while( rc<0 && errno==EINTR );
-+#elif defined(USE_PREAD64)
-+ do{ rc = osPwrite64(fd, pBuf, nBuf, iOff);}while( rc<0 && errno==EINTR);
-+#else
-+ do{
-+ i64 iSeek = lseek(fd, iOff, SEEK_SET);
-+ SimulateIOError( iSeek-- );
-+
-+ if( iSeek!=iOff ){
-+ if( piErrno ) *piErrno = (iSeek==-1 ? errno : 0);
-+ return -1;
- }
-- unixLeaveMutex();
-- }
-+ rc = osWrite(fd, pBuf, nBuf);
-+ }while( rc<0 && errno==EINTR );
-+#endif
-+
-+ TIMER_END;
-+ OSTRACE(("WRITE %-3d %5d %7lld %llu\n", fd, rc, iOff, TIMER_ELAPSED));
-+
-+ if( rc<0 && piErrno ) *piErrno = errno;
-+ return rc;
-+}
-+
-+
-+/*
-+** Seek to the offset in id->offset then read cnt bytes into pBuf.
-+** Return the number of bytes actually read. Update the offset.
-+**
-+** To avoid stomping the errno value on a failed write the lastErrno value
-+** is set before returning.
-+*/
-+static int seekAndWrite(unixFile *id, i64 offset, const void *pBuf, int cnt){
-+ return seekAndWriteFd(id->h, offset, pBuf, cnt, &id->lastErrno);
-+}
-+
-+
-+/*
-+** Write data from a buffer into a file. Return SQLITE_OK on success
-+** or some other error code on failure.
-+*/
-+static int unixWrite(
-+ sqlite3_file *id,
-+ const void *pBuf,
-+ int amt,
-+ sqlite3_int64 offset
-+){
-+ unixFile *pFile = (unixFile*)id;
-+ int wrote = 0;
-+ assert( id );
-+ assert( amt>0 );
-+
-+ /* If this is a database file (not a journal, master-journal or temp
-+ ** file), the bytes in the locking range should never be read or written. */
-+#if 0
-+ assert( pFile->pUnused==0
-+ || offset>=PENDING_BYTE+512
-+ || offset+amt<=PENDING_BYTE
-+ );
-+#endif
-
--#if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__)
-- else if( pLockingStyle == &afpIoMethods ){
-- /* AFP locking uses the file path so it needs to be included in
-- ** the afpLockingContext.
-- */
-- afpLockingContext *pCtx;
-- pNew->lockingContext = pCtx = sqlite3_malloc( sizeof(*pCtx) );
-- if( pCtx==0 ){
-- rc = SQLITE_NOMEM;
-- }else{
-- /* NB: zFilename exists and remains valid until the file is closed
-- ** according to requirement F11141. So we do not need to make a
-- ** copy of the filename. */
-- pCtx->dbPath = zFilename;
-- pCtx->reserved = 0;
-- srandomdev();
-- unixEnterMutex();
-- rc = findInodeInfo(pNew, &pNew->pInode);
-- if( rc!=SQLITE_OK ){
-- sqlite3_free(pNew->lockingContext);
-- robust_close(pNew, h, __LINE__);
-- h = -1;
-+#ifdef SQLITE_DEBUG
-+ /* If we are doing a normal write to a database file (as opposed to
-+ ** doing a hot-journal rollback or a write to some file other than a
-+ ** normal database file) then record the fact that the database
-+ ** has changed. If the transaction counter is modified, record that
-+ ** fact too.
-+ */
-+ if( pFile->inNormalWrite ){
-+ pFile->dbUpdate = 1; /* The database has been modified */
-+ if( offset<=24 && offset+amt>=27 ){
-+ int rc;
-+ char oldCntr[4];
-+ SimulateIOErrorBenign(1);
-+ rc = seekAndRead(pFile, 24, oldCntr, 4);
-+ SimulateIOErrorBenign(0);
-+ if( rc!=4 || memcmp(oldCntr, &((char*)pBuf)[24-offset], 4)!=0 ){
-+ pFile->transCntrChng = 1; /* The transaction counter has changed */
- }
-- unixLeaveMutex();
- }
- }
- #endif
-
-- else if( pLockingStyle == &dotlockIoMethods ){
-- /* Dotfile locking uses the file path so it needs to be included in
-- ** the dotlockLockingContext
-- */
-- char *zLockFile;
-- int nFilename;
-- assert( zFilename!=0 );
-- nFilename = (int)strlen(zFilename) + 6;
-- zLockFile = (char *)sqlite3_malloc(nFilename);
-- if( zLockFile==0 ){
-- rc = SQLITE_NOMEM;
-+#if SQLITE_MAX_MMAP_SIZE>0
-+ /* Deal with as much of this write request as possible by transfering
-+ ** data from the memory mapping using memcpy(). */
-+ if( offset<pFile->mmapSize ){
-+ if( offset+amt <= pFile->mmapSize ){
-+ memcpy(&((u8 *)(pFile->pMapRegion))[offset], pBuf, amt);
-+ return SQLITE_OK;
- }else{
-- sqlite3_snprintf(nFilename, zLockFile, "%s" DOTLOCK_SUFFIX, zFilename);
-+ int nCopy = pFile->mmapSize - offset;
-+ memcpy(&((u8 *)(pFile->pMapRegion))[offset], pBuf, nCopy);
-+ pBuf = &((u8 *)pBuf)[nCopy];
-+ amt -= nCopy;
-+ offset += nCopy;
- }
-- pNew->lockingContext = zLockFile;
- }
-+#endif
-
--#if OS_VXWORKS
-- else if( pLockingStyle == &semIoMethods ){
-- /* Named semaphore locking uses the file path so it needs to be
-- ** included in the semLockingContext
-- */
-- unixEnterMutex();
-- rc = findInodeInfo(pNew, &pNew->pInode);
-- if( (rc==SQLITE_OK) && (pNew->pInode->pSem==NULL) ){
-- char *zSemName = pNew->pInode->aSemName;
-- int n;
-- sqlite3_snprintf(MAX_PATHNAME, zSemName, "/%s.sem",
-- pNew->pId->zCanonicalName);
-- for( n=1; zSemName[n]; n++ )
-- if( zSemName[n]=='/' ) zSemName[n] = '_';
-- pNew->pInode->pSem = sem_open(zSemName, O_CREAT, 0666, 1);
-- if( pNew->pInode->pSem == SEM_FAILED ){
-- rc = SQLITE_NOMEM;
-- pNew->pInode->aSemName[0] = '\0';
-- }
-+ while( amt>0 && (wrote = seekAndWrite(pFile, offset, pBuf, amt))>0 ){
-+ amt -= wrote;
-+ offset += wrote;
-+ pBuf = &((char*)pBuf)[wrote];
-+ }
-+ SimulateIOError(( wrote=(-1), amt=1 ));
-+ SimulateDiskfullError(( wrote=0, amt=1 ));
-+
-+ if( amt>0 ){
-+ if( wrote<0 && pFile->lastErrno!=ENOSPC ){
-+ /* lastErrno set by seekAndWrite */
-+ return SQLITE_IOERR_WRITE;
-+ }else{
-+ pFile->lastErrno = 0; /* not a system error */
-+ return SQLITE_FULL;
- }
-- unixLeaveMutex();
- }
-+
-+ return SQLITE_OK;
-+}
-+
-+#ifdef SQLITE_TEST
-+/*
-+** Count the number of fullsyncs and normal syncs. This is used to test
-+** that syncs and fullsyncs are occurring at the right times.
-+*/
-+SQLITE_API int sqlite3_sync_count = 0;
-+SQLITE_API int sqlite3_fullsync_count = 0;
- #endif
--
-- pNew->lastErrno = 0;
--#if OS_VXWORKS
-- if( rc!=SQLITE_OK ){
-- if( h>=0 ) robust_close(pNew, h, __LINE__);
-- h = -1;
-- osUnlink(zFilename);
-- pNew->ctrlFlags |= UNIXFILE_DELETE;
-- }
-+
-+/*
-+** We do not trust systems to provide a working fdatasync(). Some do.
-+** Others do no. To be safe, we will stick with the (slightly slower)
-+** fsync(). If you know that your system does support fdatasync() correctly,
-+** then simply compile with -Dfdatasync=fdatasync
-+*/
-+#if !defined(fdatasync)
-+# define fdatasync fsync
- #endif
-- if( rc!=SQLITE_OK ){
-- if( h>=0 ) robust_close(pNew, h, __LINE__);
-- }else{
-- pNew->pMethod = pLockingStyle;
-- OpenCounter(+1);
-- verifyDbFile(pNew);
-- }
-- return rc;
--}
-
- /*
--** Return the name of a directory in which to put temporary files.
--** If no suitable temporary file directory can be found, return NULL.
-+** Define HAVE_FULLFSYNC to 0 or 1 depending on whether or not
-+** the F_FULLFSYNC macro is defined. F_FULLFSYNC is currently
-+** only available on Mac OS X. But that could change.
- */
--static const char *unixTempFileDir(void){
-- static const char *azDirs[] = {
-- 0,
-- 0,
-- "/var/tmp",
-- "/usr/tmp",
-- "/tmp",
-- 0 /* List terminator */
-- };
-- unsigned int i;
-- struct stat buf;
-- const char *zDir = 0;
-+#ifdef F_FULLFSYNC
-+# define HAVE_FULLFSYNC 1
-+#else
-+# define HAVE_FULLFSYNC 0
-+#endif
-
-- azDirs[0] = sqlite3_temp_directory;
-- if( !azDirs[1] ) azDirs[1] = getenv("TMPDIR");
-- for(i=0; i<sizeof(azDirs)/sizeof(azDirs[0]); zDir=azDirs[i++]){
-- if( zDir==0 ) continue;
-- if( osStat(zDir, &buf) ) continue;
-- if( !S_ISDIR(buf.st_mode) ) continue;
-- if( osAccess(zDir, 07) ) continue;
-- break;
-- }
-- return zDir;
--}
-
- /*
--** Create a temporary file name in zBuf. zBuf must be allocated
--** by the calling process and must be big enough to hold at least
--** pVfs->mxPathname bytes.
-+** The fsync() system call does not work as advertised on many
-+** unix systems. The following procedure is an attempt to make
-+** it work better.
-+**
-+** The SQLITE_NO_SYNC macro disables all fsync()s. This is useful
-+** for testing when we want to run through the test suite quickly.
-+** You are strongly advised *not* to deploy with SQLITE_NO_SYNC
-+** enabled, however, since with SQLITE_NO_SYNC enabled, an OS crash
-+** or power failure will likely corrupt the database file.
-+**
-+** SQLite sets the dataOnly flag if the size of the file is unchanged.
-+** The idea behind dataOnly is that it should only write the file content
-+** to disk, not the inode. We only set dataOnly if the file size is
-+** unchanged since the file size is part of the inode. However,
-+** Ted Ts'o tells us that fdatasync() will also write the inode if the
-+** file size has changed. The only real difference between fdatasync()
-+** and fsync(), Ted tells us, is that fdatasync() will not flush the
-+** inode if the mtime or owner or other inode attributes have changed.
-+** We only care about the file size, not the other file attributes, so
-+** as far as SQLite is concerned, an fdatasync() is always adequate.
-+** So, we always use fdatasync() if it is available, regardless of
-+** the value of the dataOnly flag.
- */
--static int unixGetTempname(int nBuf, char *zBuf){
-- static const unsigned char zChars[] =
-- "abcdefghijklmnopqrstuvwxyz"
-- "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
-- "0123456789";
-- unsigned int i, j;
-- const char *zDir;
-+static int full_fsync(int fd, int fullSync, int dataOnly){
-+ int rc;
-
-- /* It's odd to simulate an io-error here, but really this is just
-- ** using the io-error infrastructure to test that SQLite handles this
-- ** function failing.
-+ /* The following "ifdef/elif/else/" block has the same structure as
-+ ** the one below. It is replicated here solely to avoid cluttering
-+ ** up the real code with the UNUSED_PARAMETER() macros.
- */
-- SimulateIOError( return SQLITE_IOERR );
-+#ifdef SQLITE_NO_SYNC
-+ UNUSED_PARAMETER(fd);
-+ UNUSED_PARAMETER(fullSync);
-+ UNUSED_PARAMETER(dataOnly);
-+#elif HAVE_FULLFSYNC
-+ UNUSED_PARAMETER(dataOnly);
-+#else
-+ UNUSED_PARAMETER(fullSync);
-+ UNUSED_PARAMETER(dataOnly);
-+#endif
-
-- zDir = unixTempFileDir();
-- if( zDir==0 ) zDir = ".";
-+ /* Record the number of times that we do a normal fsync() and
-+ ** FULLSYNC. This is used during testing to verify that this procedure
-+ ** gets called with the correct arguments.
-+ */
-+#ifdef SQLITE_TEST
-+ if( fullSync ) sqlite3_fullsync_count++;
-+ sqlite3_sync_count++;
-+#endif
-
-- /* Check that the output buffer is large enough for the temporary file
-- ** name. If it is not, return SQLITE_ERROR.
-+ /* If we compiled with the SQLITE_NO_SYNC flag, then syncing is a
-+ ** no-op
- */
-- if( (strlen(zDir) + strlen(SQLITE_TEMP_FILE_PREFIX) + 18) >= (size_t)nBuf ){
-- return SQLITE_ERROR;
-+#ifdef SQLITE_NO_SYNC
-+ rc = SQLITE_OK;
-+#elif HAVE_FULLFSYNC
-+ if( fullSync ){
-+ rc = osFcntl(fd, F_FULLFSYNC, 0);
-+ }else{
-+ rc = 1;
-+ }
-+ /* If the FULLFSYNC failed, fall back to attempting an fsync().
-+ ** It shouldn't be possible for fullfsync to fail on the local
-+ ** file system (on OSX), so failure indicates that FULLFSYNC
-+ ** isn't supported for this file system. So, attempt an fsync
-+ ** and (for now) ignore the overhead of a superfluous fcntl call.
-+ ** It'd be better to detect fullfsync support once and avoid
-+ ** the fcntl call every time sync is called.
-+ */
-+ if( rc ) rc = fsync(fd);
-+
-+#elif defined(__APPLE__)
-+ /* fdatasync() on HFS+ doesn't yet flush the file size if it changed correctly
-+ ** so currently we default to the macro that redefines fdatasync to fsync
-+ */
-+ rc = fsync(fd);
-+#else
-+ rc = fdatasync(fd);
-+#if OS_VXWORKS
-+ if( rc==-1 && errno==ENOTSUP ){
-+ rc = fsync(fd);
- }
-+#endif /* OS_VXWORKS */
-+#endif /* ifdef SQLITE_NO_SYNC elif HAVE_FULLFSYNC */
-
-- do{
-- sqlite3_snprintf(nBuf-18, zBuf, "%s/"SQLITE_TEMP_FILE_PREFIX, zDir);
-- j = (int)strlen(zBuf);
-- sqlite3_randomness(15, &zBuf[j]);
-- for(i=0; i<15; i++, j++){
-- zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ];
-- }
-- zBuf[j] = 0;
-- zBuf[j+1] = 0;
-- }while( osAccess(zBuf,0)==0 );
-- return SQLITE_OK;
-+ if( OS_VXWORKS && rc!= -1 ){
-+ rc = 0;
-+ }
-+ return rc;
- }
-
--#if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__)
- /*
--** Routine to transform a unixFile into a proxy-locking unixFile.
--** Implementation in the proxy-lock division, but used by unixOpen()
--** if SQLITE_PREFER_PROXY_LOCKING is defined.
-+** Open a file descriptor to the directory containing file zFilename.
-+** If successful, *pFd is set to the opened file descriptor and
-+** SQLITE_OK is returned. If an error occurs, either SQLITE_NOMEM
-+** or SQLITE_CANTOPEN is returned and *pFd is set to an undefined
-+** value.
-+**
-+** The directory file descriptor is used for only one thing - to
-+** fsync() a directory to make sure file creation and deletion events
-+** are flushed to disk. Such fsyncs are not needed on newer
-+** journaling filesystems, but are required on older filesystems.
-+**
-+** This routine can be overridden using the xSetSysCall interface.
-+** The ability to override this routine was added in support of the
-+** chromium sandbox. Opening a directory is a security risk (we are
-+** told) so making it overrideable allows the chromium sandbox to
-+** replace this routine with a harmless no-op. To make this routine
-+** a no-op, replace it with a stub that returns SQLITE_OK but leaves
-+** *pFd set to a negative number.
-+**
-+** If SQLITE_OK is returned, the caller is responsible for closing
-+** the file descriptor *pFd using close().
- */
--static int proxyTransformUnixFile(unixFile*, const char*);
--#endif
-+static int openDirectory(const char *zFilename, int *pFd){
-+ int ii;
-+ int fd = -1;
-+ char zDirname[MAX_PATHNAME+1];
-+
-+ sqlite3_snprintf(MAX_PATHNAME, zDirname, "%s", zFilename);
-+ for(ii=(int)strlen(zDirname); ii>1 && zDirname[ii]!='/'; ii--);
-+ if( ii>0 ){
-+ zDirname[ii] = '\0';
-+ fd = robust_open(zDirname, O_RDONLY|O_BINARY, 0);
-+ if( fd>=0 ){
-+ OSTRACE(("OPENDIR %-3d %s\n", fd, zDirname));
-+ }
-+ }
-+ *pFd = fd;
-+ return (fd>=0?SQLITE_OK:unixLogError(SQLITE_CANTOPEN_BKPT, "open", zDirname));
-+}
-
- /*
--** Search for an unused file descriptor that was opened on the database
--** file (not a journal or master-journal file) identified by pathname
--** zPath with SQLITE_OPEN_XXX flags matching those passed as the second
--** argument to this function.
-+** Make sure all writes to a particular file are committed to disk.
- **
--** Such a file descriptor may exist if a database connection was closed
--** but the associated file descriptor could not be closed because some
--** other file descriptor open on the same file is holding a file-lock.
--** Refer to comments in the unixClose() function and the lengthy comment
--** describing "Posix Advisory Locking" at the start of this file for
--** further details. Also, ticket #4018.
-+** If dataOnly==0 then both the file itself and its metadata (file
-+** size, access time, etc) are synced. If dataOnly!=0 then only the
-+** file data is synced.
- **
--** If a suitable file descriptor is found, then it is returned. If no
--** such file descriptor is located, -1 is returned.
-+** Under Unix, also make sure that the directory entry for the file
-+** has been created by fsync-ing the directory that contains the file.
-+** If we do not do this and we encounter a power failure, the directory
-+** entry for the journal might not exist after we reboot. The next
-+** SQLite to access the file will not know that the journal exists (because
-+** the directory entry for the journal was never created) and the transaction
-+** will not roll back - possibly leading to database corruption.
- */
--static UnixUnusedFd *findReusableFd(const char *zPath, int flags){
-- UnixUnusedFd *pUnused = 0;
-+static int unixSync(sqlite3_file *id, int flags){
-+ int rc;
-+ unixFile *pFile = (unixFile*)id;
-
-- /* Do not search for an unused file descriptor on vxworks. Not because
-- ** vxworks would not benefit from the change (it might, we're not sure),
-- ** but because no way to test it is currently available. It is better
-- ** not to risk breaking vxworks support for the sake of such an obscure
-- ** feature. */
--#if !OS_VXWORKS
-- struct stat sStat; /* Results of stat() call */
-+ int isDataOnly = (flags&SQLITE_SYNC_DATAONLY);
-+ int isFullsync = (flags&0x0F)==SQLITE_SYNC_FULL;
-
-- /* A stat() call may fail for various reasons. If this happens, it is
-- ** almost certain that an open() call on the same path will also fail.
-- ** For this reason, if an error occurs in the stat() call here, it is
-- ** ignored and -1 is returned. The caller will try to open a new file
-- ** descriptor on the same path, fail, and return an error to SQLite.
-- **
-- ** Even if a subsequent open() call does succeed, the consequences of
-- ** not searching for a resusable file descriptor are not dire. */
-- if( 0==osStat(zPath, &sStat) ){
-- unixInodeInfo *pInode;
-+ /* Check that one of SQLITE_SYNC_NORMAL or FULL was passed */
-+ assert((flags&0x0F)==SQLITE_SYNC_NORMAL
-+ || (flags&0x0F)==SQLITE_SYNC_FULL
-+ );
-
-- unixEnterMutex();
-- pInode = inodeList;
-- while( pInode && (pInode->fileId.dev!=sStat.st_dev
-- || pInode->fileId.ino!=sStat.st_ino) ){
-- pInode = pInode->pNext;
-- }
-- if( pInode ){
-- UnixUnusedFd **pp;
-- for(pp=&pInode->pUnused; *pp && (*pp)->flags!=flags; pp=&((*pp)->pNext));
-- pUnused = *pp;
-- if( pUnused ){
-- *pp = pUnused->pNext;
-- }
-+ /* Unix cannot, but some systems may return SQLITE_FULL from here. This
-+ ** line is to test that doing so does not cause any problems.
-+ */
-+ SimulateDiskfullError( return SQLITE_FULL );
-+
-+ assert( pFile );
-+ OSTRACE(("SYNC %-3d\n", pFile->h));
-+ rc = full_fsync(pFile->h, isFullsync, isDataOnly);
-+ SimulateIOError( rc=1 );
-+ if( rc ){
-+ pFile->lastErrno = errno;
-+ return unixLogError(SQLITE_IOERR_FSYNC, "full_fsync", pFile->zPath);
-+ }
-+
-+ /* Also fsync the directory containing the file if the DIRSYNC flag
-+ ** is set. This is a one-time occurrence. Many systems (examples: AIX)
-+ ** are unable to fsync a directory, so ignore errors on the fsync.
-+ */
-+ if( pFile->ctrlFlags & UNIXFILE_DIRSYNC ){
-+ int dirfd;
-+ OSTRACE(("DIRSYNC %s (have_fullfsync=%d fullsync=%d)\n", pFile->zPath,
-+ HAVE_FULLFSYNC, isFullsync));
-+ rc = osOpenDirectory(pFile->zPath, &dirfd);
-+ if( rc==SQLITE_OK && dirfd>=0 ){
-+ full_fsync(dirfd, 0, 0);
-+ robust_close(pFile, dirfd, __LINE__);
-+ }else if( rc==SQLITE_CANTOPEN ){
-+ rc = SQLITE_OK;
- }
-- unixLeaveMutex();
-+ pFile->ctrlFlags &= ~UNIXFILE_DIRSYNC;
- }
--#endif /* if !OS_VXWORKS */
-- return pUnused;
-+ return rc;
- }
-
- /*
--** This function is called by unixOpen() to determine the unix permissions
--** to create new files with. If no error occurs, then SQLITE_OK is returned
--** and a value suitable for passing as the third argument to open(2) is
--** written to *pMode. If an IO error occurs, an SQLite error code is
--** returned and the value of *pMode is not modified.
--**
--** In most cases cases, this routine sets *pMode to 0, which will become
--** an indication to robust_open() to create the file using
--** SQLITE_DEFAULT_FILE_PERMISSIONS adjusted by the umask.
--** But if the file being opened is a WAL or regular journal file, then
--** this function queries the file-system for the permissions on the
--** corresponding database file and sets *pMode to this value. Whenever
--** possible, WAL and journal files are created using the same permissions
--** as the associated database file.
--**
--** If the SQLITE_ENABLE_8_3_NAMES option is enabled, then the
--** original filename is unavailable. But 8_3_NAMES is only used for
--** FAT filesystems and permissions do not matter there, so just use
--** the default permissions.
-+** Truncate an open file to a specified size
- */
--static int findCreateFileMode(
-- const char *zPath, /* Path of file (possibly) being created */
-- int flags, /* Flags passed as 4th argument to xOpen() */
-- mode_t *pMode, /* OUT: Permissions to open file with */
-- uid_t *pUid, /* OUT: uid to set on the file */
-- gid_t *pGid /* OUT: gid to set on the file */
--){
-- int rc = SQLITE_OK; /* Return Code */
-- *pMode = 0;
-- *pUid = 0;
-- *pGid = 0;
-- if( flags & (SQLITE_OPEN_WAL|SQLITE_OPEN_MAIN_JOURNAL) ){
-- char zDb[MAX_PATHNAME+1]; /* Database file path */
-- int nDb; /* Number of valid bytes in zDb */
-- struct stat sStat; /* Output of stat() on database file */
-+static int unixTruncate(sqlite3_file *id, i64 nByte){
-+ unixFile *pFile = (unixFile *)id;
-+ int rc;
-+ assert( pFile );
-+ SimulateIOError( return SQLITE_IOERR_TRUNCATE );
-
-- /* zPath is a path to a WAL or journal file. The following block derives
-- ** the path to the associated database file from zPath. This block handles
-- ** the following naming conventions:
-- **
-- ** "<path to db>-journal"
-- ** "<path to db>-wal"
-- ** "<path to db>-journalNN"
-- ** "<path to db>-walNN"
-- **
-- ** where NN is a decimal number. The NN naming schemes are
-- ** used by the test_multiplex.c module.
-- */
-- nDb = sqlite3Strlen30(zPath) - 1;
--#ifdef SQLITE_ENABLE_8_3_NAMES
-- while( nDb>0 && sqlite3Isalnum(zPath[nDb]) ) nDb--;
-- if( nDb==0 || zPath[nDb]!='-' ) return SQLITE_OK;
--#else
-- while( zPath[nDb]!='-' ){
-- assert( nDb>0 );
-- assert( zPath[nDb]!='\n' );
-- nDb--;
-+ /* If the user has configured a chunk-size for this file, truncate the
-+ ** file so that it consists of an integer number of chunks (i.e. the
-+ ** actual file size after the operation may be larger than the requested
-+ ** size).
-+ */
-+ if( pFile->szChunk>0 ){
-+ nByte = ((nByte + pFile->szChunk - 1)/pFile->szChunk) * pFile->szChunk;
-+ }
-+
-+ rc = robust_ftruncate(pFile->h, (off_t)nByte);
-+ if( rc ){
-+ pFile->lastErrno = errno;
-+ return unixLogError(SQLITE_IOERR_TRUNCATE, "ftruncate", pFile->zPath);
-+ }else{
-+#ifdef SQLITE_DEBUG
-+ /* If we are doing a normal write to a database file (as opposed to
-+ ** doing a hot-journal rollback or a write to some file other than a
-+ ** normal database file) and we truncate the file to zero length,
-+ ** that effectively updates the change counter. This might happen
-+ ** when restoring a database using the backup API from a zero-length
-+ ** source.
-+ */
-+ if( pFile->inNormalWrite && nByte==0 ){
-+ pFile->transCntrChng = 1;
- }
- #endif
-- memcpy(zDb, zPath, nDb);
-- zDb[nDb] = '\0';
-
-- if( 0==osStat(zDb, &sStat) ){
-- *pMode = sStat.st_mode & 0777;
-- *pUid = sStat.st_uid;
-- *pGid = sStat.st_gid;
-- }else{
-- rc = SQLITE_IOERR_FSTAT;
-+ /* If the file was just truncated to a size smaller than the currently
-+ ** mapped region, reduce the effective mapping size as well. SQLite will
-+ ** use read() and write() to access data beyond this point from now on.
-+ */
-+ if( nByte<pFile->mmapSize ){
-+ pFile->mmapSize = nByte;
- }
-- }else if( flags & SQLITE_OPEN_DELETEONCLOSE ){
-- *pMode = 0600;
-+
-+ return SQLITE_OK;
- }
-- return rc;
- }
-
- /*
--** Open the file zPath.
--**
--** Previously, the SQLite OS layer used three functions in place of this
--** one:
--**
--** sqlite3OsOpenReadWrite();
--** sqlite3OsOpenReadOnly();
--** sqlite3OsOpenExclusive();
--**
--** These calls correspond to the following combinations of flags:
--**
--** ReadWrite() -> (READWRITE | CREATE)
--** ReadOnly() -> (READONLY)
--** OpenExclusive() -> (READWRITE | CREATE | EXCLUSIVE)
--**
--** The old OpenExclusive() accepted a boolean argument - "delFlag". If
--** true, the file was configured to be automatically deleted when the
--** file handle closed. To achieve the same effect using this new
--** interface, add the DELETEONCLOSE flag to those specified above for
--** OpenExclusive().
-+** Determine the current size of a file in bytes
- */
--static int unixOpen(
-- sqlite3_vfs *pVfs, /* The VFS for which this is the xOpen method */
-- const char *zPath, /* Pathname of file to be opened */
-- sqlite3_file *pFile, /* The file descriptor to be filled in */
-- int flags, /* Input flags to control the opening */
-- int *pOutFlags /* Output flags returned to SQLite core */
--){
-- unixFile *p = (unixFile *)pFile;
-- int fd = -1; /* File descriptor returned by open() */
-- int openFlags = 0; /* Flags to pass to open() */
-- int eType = flags&0xFFFFFF00; /* Type of file to open */
-- int noLock; /* True to omit locking primitives */
-- int rc = SQLITE_OK; /* Function Return Code */
-- int ctrlFlags = 0; /* UNIXFILE_* flags */
--
-- int isExclusive = (flags & SQLITE_OPEN_EXCLUSIVE);
-- int isDelete = (flags & SQLITE_OPEN_DELETEONCLOSE);
-- int isCreate = (flags & SQLITE_OPEN_CREATE);
-- int isReadonly = (flags & SQLITE_OPEN_READONLY);
-- int isReadWrite = (flags & SQLITE_OPEN_READWRITE);
--#if SQLITE_ENABLE_LOCKING_STYLE
-- int isAutoProxy = (flags & SQLITE_OPEN_AUTOPROXY);
--#endif
--#if defined(__APPLE__) || SQLITE_ENABLE_LOCKING_STYLE
-- struct statfs fsInfo;
--#endif
-+static int unixFileSize(sqlite3_file *id, i64 *pSize){
-+ int rc;
-+ struct stat buf;
-+ assert( id );
-+ rc = osFstat(((unixFile*)id)->h, &buf);
-+ SimulateIOError( rc=1 );
-+ if( rc!=0 ){
-+ ((unixFile*)id)->lastErrno = errno;
-+ return SQLITE_IOERR_FSTAT;
-+ }
-+ *pSize = buf.st_size;
-
-- /* If creating a master or main-file journal, this function will open
-- ** a file-descriptor on the directory too. The first time unixSync()
-- ** is called the directory file descriptor will be fsync()ed and close()d.
-+ /* When opening a zero-size database, the findInodeInfo() procedure
-+ ** writes a single byte into that file in order to work around a bug
-+ ** in the OS-X msdos filesystem. In order to avoid problems with upper
-+ ** layers, we need to report this file size as zero even though it is
-+ ** really 1. Ticket #3260.
- */
-- int syncDir = (isCreate && (
-- eType==SQLITE_OPEN_MASTER_JOURNAL
-- || eType==SQLITE_OPEN_MAIN_JOURNAL
-- || eType==SQLITE_OPEN_WAL
-- ));
-+ if( *pSize==1 ) *pSize = 0;
-
-- /* If argument zPath is a NULL pointer, this function is required to open
-- ** a temporary file. Use this buffer to store the file name in.
-- */
-- char zTmpname[MAX_PATHNAME+2];
-- const char *zName = zPath;
-
-- /* Check the following statements are true:
-- **
-- ** (a) Exactly one of the READWRITE and READONLY flags must be set, and
-- ** (b) if CREATE is set, then READWRITE must also be set, and
-- ** (c) if EXCLUSIVE is set, then CREATE must also be set.
-- ** (d) if DELETEONCLOSE is set, then CREATE must also be set.
-- */
-- assert((isReadonly==0 || isReadWrite==0) && (isReadWrite || isReadonly));
-- assert(isCreate==0 || isReadWrite);
-- assert(isExclusive==0 || isCreate);
-- assert(isDelete==0 || isCreate);
-+ return SQLITE_OK;
-+}
-
-- /* The main DB, main journal, WAL file and master journal are never
-- ** automatically deleted. Nor are they ever temporary files. */
-- assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MAIN_DB );
-- assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MAIN_JOURNAL );
-- assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MASTER_JOURNAL );
-- assert( (!isDelete && zName) || eType!=SQLITE_OPEN_WAL );
-+#if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__)
-+/*
-+** Handler for proxy-locking file-control verbs. Defined below in the
-+** proxying locking division.
-+*/
-+static int proxyFileControl(sqlite3_file*,int,void*);
-+#endif
-
-- /* Assert that the upper layer has set one of the "file-type" flags. */
-- assert( eType==SQLITE_OPEN_MAIN_DB || eType==SQLITE_OPEN_TEMP_DB
-- || eType==SQLITE_OPEN_MAIN_JOURNAL || eType==SQLITE_OPEN_TEMP_JOURNAL
-- || eType==SQLITE_OPEN_SUBJOURNAL || eType==SQLITE_OPEN_MASTER_JOURNAL
-- || eType==SQLITE_OPEN_TRANSIENT_DB || eType==SQLITE_OPEN_WAL
-- );
-+/*
-+** This function is called to handle the SQLITE_FCNTL_SIZE_HINT
-+** file-control operation. Enlarge the database to nBytes in size
-+** (rounded up to the next chunk-size). If the database is already
-+** nBytes or larger, this routine is a no-op.
-+*/
-+static int fcntlSizeHint(unixFile *pFile, i64 nByte){
-+ if( pFile->szChunk>0 ){
-+ i64 nSize; /* Required file size */
-+ struct stat buf; /* Used to hold return values of fstat() */
-+
-+ if( osFstat(pFile->h, &buf) ) return SQLITE_IOERR_FSTAT;
-
-- memset(p, 0, sizeof(unixFile));
-+ nSize = ((nByte+pFile->szChunk-1) / pFile->szChunk) * pFile->szChunk;
-+ if( nSize>(i64)buf.st_size ){
-
-- if( eType==SQLITE_OPEN_MAIN_DB ){
-- UnixUnusedFd *pUnused;
-- pUnused = findReusableFd(zName, flags);
-- if( pUnused ){
-- fd = pUnused->fd;
-- }else{
-- pUnused = sqlite3_malloc(sizeof(*pUnused));
-- if( !pUnused ){
-- return SQLITE_NOMEM;
-+#if defined(HAVE_POSIX_FALLOCATE) && HAVE_POSIX_FALLOCATE
-+ /* The code below is handling the return value of osFallocate()
-+ ** correctly. posix_fallocate() is defined to "returns zero on success,
-+ ** or an error number on failure". See the manpage for details. */
-+ int err;
-+ do{
-+ err = osFallocate(pFile->h, buf.st_size, nSize-buf.st_size);
-+ }while( err==EINTR );
-+ if( err ) return SQLITE_IOERR_WRITE;
-+#else
-+ /* If the OS does not have posix_fallocate(), fake it. First use
-+ ** ftruncate() to set the file size, then write a single byte to
-+ ** the last byte in each block within the extended region. This
-+ ** is the same technique used by glibc to implement posix_fallocate()
-+ ** on systems that do not have a real fallocate() system call.
-+ */
-+ int nBlk = buf.st_blksize; /* File-system block size */
-+ i64 iWrite; /* Next offset to write to */
-+
-+ if( robust_ftruncate(pFile->h, nSize) ){
-+ pFile->lastErrno = errno;
-+ return unixLogError(SQLITE_IOERR_TRUNCATE, "ftruncate", pFile->zPath);
-+ }
-+ iWrite = ((buf.st_size + 2*nBlk - 1)/nBlk)*nBlk-1;
-+ while( iWrite<nSize ){
-+ int nWrite = seekAndWrite(pFile, iWrite, "", 1);
-+ if( nWrite!=1 ) return SQLITE_IOERR_WRITE;
-+ iWrite += nBlk;
- }
-+#endif
- }
-- p->pUnused = pUnused;
--
-- /* Database filenames are double-zero terminated if they are not
-- ** URIs with parameters. Hence, they can always be passed into
-- ** sqlite3_uri_parameter(). */
-- assert( (flags & SQLITE_OPEN_URI) || zName[strlen(zName)+1]==0 );
-+ }
-
-- }else if( !zName ){
-- /* If zName is NULL, the upper layer is requesting a temp file. */
-- assert(isDelete && !syncDir);
-- rc = unixGetTempname(MAX_PATHNAME+2, zTmpname);
-- if( rc!=SQLITE_OK ){
-- return rc;
-+ if( pFile->mmapSizeMax>0 && nByte>pFile->mmapSize ){
-+ int rc;
-+ if( pFile->szChunk<=0 ){
-+ if( robust_ftruncate(pFile->h, nByte) ){
-+ pFile->lastErrno = errno;
-+ return unixLogError(SQLITE_IOERR_TRUNCATE, "ftruncate", pFile->zPath);
-+ }
- }
-- zName = zTmpname;
-
-- /* Generated temporary filenames are always double-zero terminated
-- ** for use by sqlite3_uri_parameter(). */
-- assert( zName[strlen(zName)+1]==0 );
-+ rc = unixMapfile(pFile, nByte);
-+ return rc;
- }
-
-- /* Determine the value of the flags parameter passed to POSIX function
-- ** open(). These must be calculated even if open() is not called, as
-- ** they may be stored as part of the file handle and used by the
-- ** 'conch file' locking functions later on. */
-- if( isReadonly ) openFlags |= O_RDONLY;
-- if( isReadWrite ) openFlags |= O_RDWR;
-- if( isCreate ) openFlags |= O_CREAT;
-- if( isExclusive ) openFlags |= (O_EXCL|O_NOFOLLOW);
-- openFlags |= (O_LARGEFILE|O_BINARY);
-+ return SQLITE_OK;
-+}
-
-- if( fd<0 ){
-- mode_t openMode; /* Permissions to create file with */
-- uid_t uid; /* Userid for the file */
-- gid_t gid; /* Groupid for the file */
-- rc = findCreateFileMode(zName, flags, &openMode, &uid, &gid);
-- if( rc!=SQLITE_OK ){
-- assert( !p->pUnused );
-- assert( eType==SQLITE_OPEN_WAL || eType==SQLITE_OPEN_MAIN_JOURNAL );
-+/*
-+** If *pArg is inititially negative then this is a query. Set *pArg to
-+** 1 or 0 depending on whether or not bit mask of pFile->ctrlFlags is set.
-+**
-+** If *pArg is 0 or 1, then clear or set the mask bit of pFile->ctrlFlags.
-+*/
-+static void unixModeBit(unixFile *pFile, unsigned char mask, int *pArg){
-+ if( *pArg<0 ){
-+ *pArg = (pFile->ctrlFlags & mask)!=0;
-+ }else if( (*pArg)==0 ){
-+ pFile->ctrlFlags &= ~mask;
-+ }else{
-+ pFile->ctrlFlags |= mask;
-+ }
-+}
-+
-+/* Forward declaration */
-+static int unixGetTempname(int nBuf, char *zBuf);
-+
-+/*
-+** Information and control of an open file handle.
-+*/
-+static int unixFileControl(sqlite3_file *id, int op, void *pArg){
-+ unixFile *pFile = (unixFile*)id;
-+ switch( op ){
-+ case SQLITE_FCNTL_LOCKSTATE: {
-+ *(int*)pArg = pFile->eFileLock;
-+ return SQLITE_OK;
-+ }
-+ case SQLITE_LAST_ERRNO: {
-+ *(int*)pArg = pFile->lastErrno;
-+ return SQLITE_OK;
-+ }
-+ case SQLITE_FCNTL_CHUNK_SIZE: {
-+ pFile->szChunk = *(int *)pArg;
-+ return SQLITE_OK;
-+ }
-+ case SQLITE_FCNTL_SIZE_HINT: {
-+ int rc;
-+ SimulateIOErrorBenign(1);
-+ rc = fcntlSizeHint(pFile, *(i64 *)pArg);
-+ SimulateIOErrorBenign(0);
- return rc;
- }
-- fd = robust_open(zName, openFlags, openMode);
-- OSTRACE(("OPENX %-3d %s 0%o\n", fd, zName, openFlags));
-- if( fd<0 && errno!=EISDIR && isReadWrite && !isExclusive ){
-- /* Failed to open the file for read/write access. Try read-only. */
-- flags &= ~(SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE);
-- openFlags &= ~(O_RDWR|O_CREAT);
-- flags |= SQLITE_OPEN_READONLY;
-- openFlags |= O_RDONLY;
-- isReadonly = 1;
-- fd = robust_open(zName, openFlags, openMode);
-+ case SQLITE_FCNTL_PERSIST_WAL: {
-+ unixModeBit(pFile, UNIXFILE_PERSIST_WAL, (int*)pArg);
-+ return SQLITE_OK;
- }
-- if( fd<0 ){
-- rc = unixLogError(SQLITE_CANTOPEN_BKPT, "open", zName);
-- goto open_finished;
-+ case SQLITE_FCNTL_POWERSAFE_OVERWRITE: {
-+ unixModeBit(pFile, UNIXFILE_PSOW, (int*)pArg);
-+ return SQLITE_OK;
- }
--
-- /* If this process is running as root and if creating a new rollback
-- ** journal or WAL file, set the ownership of the journal or WAL to be
-- ** the same as the original database.
-+ case SQLITE_FCNTL_VFSNAME: {
-+ *(char**)pArg = sqlite3_mprintf("%s", pFile->pVfs->zName);
-+ return SQLITE_OK;
-+ }
-+ case SQLITE_FCNTL_TEMPFILENAME: {
-+ char *zTFile = sqlite3_malloc( pFile->pVfs->mxPathname );
-+ if( zTFile ){
-+ unixGetTempname(pFile->pVfs->mxPathname, zTFile);
-+ *(char**)pArg = zTFile;
-+ }
-+ return SQLITE_OK;
-+ }
-+ case SQLITE_FCNTL_MMAP_SIZE: {
-+ i64 newLimit = *(i64*)pArg;
-+ if( newLimit>sqlite3GlobalConfig.mxMmap ){
-+ newLimit = sqlite3GlobalConfig.mxMmap;
-+ }
-+ *(i64*)pArg = pFile->mmapSizeMax;
-+ if( newLimit>=0 ){
-+ pFile->mmapSizeMax = newLimit;
-+ if( newLimit<pFile->mmapSize ) pFile->mmapSize = newLimit;
-+ }
-+ return SQLITE_OK;
-+ }
-+#ifdef SQLITE_DEBUG
-+ /* The pager calls this method to signal that it has done
-+ ** a rollback and that the database is therefore unchanged and
-+ ** it hence it is OK for the transaction change counter to be
-+ ** unchanged.
- */
-- if( flags & (SQLITE_OPEN_WAL|SQLITE_OPEN_MAIN_JOURNAL) ){
-- osFchown(fd, uid, gid);
-+ case SQLITE_FCNTL_DB_UNCHANGED: {
-+ ((unixFile*)id)->dbUpdate = 0;
-+ return SQLITE_OK;
- }
-- }
-- assert( fd>=0 );
-- if( pOutFlags ){
-- *pOutFlags = flags;
-- }
--
-- if( p->pUnused ){
-- p->pUnused->fd = fd;
-- p->pUnused->flags = flags;
-- }
--
-- if( isDelete ){
--#if OS_VXWORKS
-- zPath = zName;
--#else
-- osUnlink(zName);
- #endif
-+#if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__)
-+ case SQLITE_SET_LOCKPROXYFILE:
-+ case SQLITE_GET_LOCKPROXYFILE: {
-+ return proxyFileControl(id,op,pArg);
-+ }
-+#endif /* SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__) */
- }
--#if SQLITE_ENABLE_LOCKING_STYLE
-- else{
-- p->openFlags = openFlags;
-- }
--#endif
--
-- noLock = eType!=SQLITE_OPEN_MAIN_DB;
-+ return SQLITE_NOTFOUND;
-+}
-
--
--#if defined(__APPLE__) || SQLITE_ENABLE_LOCKING_STYLE
-- if( fstatfs(fd, &fsInfo) == -1 ){
-- ((unixFile*)pFile)->lastErrno = errno;
-- robust_close(p, fd, __LINE__);
-- return SQLITE_IOERR_ACCESS;
-- }
-- if (0 == strncmp("msdos", fsInfo.f_fstypename, 5)) {
-- ((unixFile*)pFile)->fsFlags |= SQLITE_FSFLAGS_IS_MSDOS;
-- }
-+/*
-+** Return the sector size in bytes of the underlying block device for
-+** the specified file. This is almost always 512 bytes, but may be
-+** larger for some devices.
-+**
-+** SQLite code assumes this function cannot fail. It also assumes that
-+** if two files are created in the same file-system directory (i.e.
-+** a database and its journal file) that the sector size will be the
-+** same for both.
-+*/
-+#ifndef __QNXNTO__
-+static int unixSectorSize(sqlite3_file *NotUsed){
-+ UNUSED_PARAMETER(NotUsed);
-+ return SQLITE_DEFAULT_SECTOR_SIZE;
-+}
- #endif
-
-- /* Set up appropriate ctrlFlags */
-- if( isDelete ) ctrlFlags |= UNIXFILE_DELETE;
-- if( isReadonly ) ctrlFlags |= UNIXFILE_RDONLY;
-- if( noLock ) ctrlFlags |= UNIXFILE_NOLOCK;
-- if( syncDir ) ctrlFlags |= UNIXFILE_DIRSYNC;
-- if( flags & SQLITE_OPEN_URI ) ctrlFlags |= UNIXFILE_URI;
--
--#if SQLITE_ENABLE_LOCKING_STYLE
--#if SQLITE_PREFER_PROXY_LOCKING
-- isAutoProxy = 1;
--#endif
-- if( isAutoProxy && (zPath!=NULL) && (!noLock) && pVfs->xOpen ){
-- char *envforce = getenv("SQLITE_FORCE_PROXY_LOCKING");
-- int useProxy = 0;
-+/*
-+** The following version of unixSectorSize() is optimized for QNX.
-+*/
-+#ifdef __QNXNTO__
-+#include <sys/dcmd_blk.h>
-+#include <sys/statvfs.h>
-+static int unixSectorSize(sqlite3_file *id){
-+ unixFile *pFile = (unixFile*)id;
-+ if( pFile->sectorSize == 0 ){
-+ struct statvfs fsInfo;
-+
-+ /* Set defaults for non-supported filesystems */
-+ pFile->sectorSize = SQLITE_DEFAULT_SECTOR_SIZE;
-+ pFile->deviceCharacteristics = 0;
-+ if( fstatvfs(pFile->h, &fsInfo) == -1 ) {
-+ return pFile->sectorSize;
-+ }
-
-- /* SQLITE_FORCE_PROXY_LOCKING==1 means force always use proxy, 0 means
-- ** never use proxy, NULL means use proxy for non-local files only. */
-- if( envforce!=NULL ){
-- useProxy = atoi(envforce)>0;
-+ if( !strcmp(fsInfo.f_basetype, "tmp") ) {
-+ pFile->sectorSize = fsInfo.f_bsize;
-+ pFile->deviceCharacteristics =
-+ SQLITE_IOCAP_ATOMIC4K | /* All ram filesystem writes are atomic */
-+ SQLITE_IOCAP_SAFE_APPEND | /* growing the file does not occur until
-+ ** the write succeeds */
-+ SQLITE_IOCAP_SEQUENTIAL | /* The ram filesystem has no write behind
-+ ** so it is ordered */
-+ 0;
-+ }else if( strstr(fsInfo.f_basetype, "etfs") ){
-+ pFile->sectorSize = fsInfo.f_bsize;
-+ pFile->deviceCharacteristics =
-+ /* etfs cluster size writes are atomic */
-+ (pFile->sectorSize / 512 * SQLITE_IOCAP_ATOMIC512) |
-+ SQLITE_IOCAP_SAFE_APPEND | /* growing the file does not occur until
-+ ** the write succeeds */
-+ SQLITE_IOCAP_SEQUENTIAL | /* The ram filesystem has no write behind
-+ ** so it is ordered */
-+ 0;
-+ }else if( !strcmp(fsInfo.f_basetype, "qnx6") ){
-+ pFile->sectorSize = fsInfo.f_bsize;
-+ pFile->deviceCharacteristics =
-+ SQLITE_IOCAP_ATOMIC | /* All filesystem writes are atomic */
-+ SQLITE_IOCAP_SAFE_APPEND | /* growing the file does not occur until
-+ ** the write succeeds */
-+ SQLITE_IOCAP_SEQUENTIAL | /* The ram filesystem has no write behind
-+ ** so it is ordered */
-+ 0;
-+ }else if( !strcmp(fsInfo.f_basetype, "qnx4") ){
-+ pFile->sectorSize = fsInfo.f_bsize;
-+ pFile->deviceCharacteristics =
-+ /* full bitset of atomics from max sector size and smaller */
-+ ((pFile->sectorSize / 512 * SQLITE_IOCAP_ATOMIC512) << 1) - 2 |
-+ SQLITE_IOCAP_SEQUENTIAL | /* The ram filesystem has no write behind
-+ ** so it is ordered */
-+ 0;
-+ }else if( strstr(fsInfo.f_basetype, "dos") ){
-+ pFile->sectorSize = fsInfo.f_bsize;
-+ pFile->deviceCharacteristics =
-+ /* full bitset of atomics from max sector size and smaller */
-+ ((pFile->sectorSize / 512 * SQLITE_IOCAP_ATOMIC512) << 1) - 2 |
-+ SQLITE_IOCAP_SEQUENTIAL | /* The ram filesystem has no write behind
-+ ** so it is ordered */
-+ 0;
- }else{
-- if( statfs(zPath, &fsInfo) == -1 ){
-- /* In theory, the close(fd) call is sub-optimal. If the file opened
-- ** with fd is a database file, and there are other connections open
-- ** on that file that are currently holding advisory locks on it,
-- ** then the call to close() will cancel those locks. In practice,
-- ** we're assuming that statfs() doesn't fail very often. At least
-- ** not while other file descriptors opened by the same process on
-- ** the same file are working. */
-- p->lastErrno = errno;
-- robust_close(p, fd, __LINE__);
-- rc = SQLITE_IOERR_ACCESS;
-- goto open_finished;
-- }
-- useProxy = !(fsInfo.f_flags&MNT_LOCAL);
-- }
-- if( useProxy ){
-- rc = fillInUnixFile(pVfs, fd, pFile, zPath, ctrlFlags);
-- if( rc==SQLITE_OK ){
-- rc = proxyTransformUnixFile((unixFile*)pFile, ":auto:");
-- if( rc!=SQLITE_OK ){
-- /* Use unixClose to clean up the resources added in fillInUnixFile
-- ** and clear all the structure's references. Specifically,
-- ** pFile->pMethods will be NULL so sqlite3OsClose will be a no-op
-- */
-- unixClose(pFile);
-- return rc;
-- }
-- }
-- goto open_finished;
-+ pFile->deviceCharacteristics =
-+ SQLITE_IOCAP_ATOMIC512 | /* blocks are atomic */
-+ SQLITE_IOCAP_SAFE_APPEND | /* growing the file does not occur until
-+ ** the write succeeds */
-+ 0;
- }
- }
--#endif
--
-- rc = fillInUnixFile(pVfs, fd, pFile, zPath, ctrlFlags);
--
--open_finished:
-- if( rc!=SQLITE_OK ){
-- sqlite3_free(p->pUnused);
-+ /* Last chance verification. If the sector size isn't a multiple of 512
-+ ** then it isn't valid.*/
-+ if( pFile->sectorSize % 512 != 0 ){
-+ pFile->deviceCharacteristics = 0;
-+ pFile->sectorSize = SQLITE_DEFAULT_SECTOR_SIZE;
- }
-- return rc;
-+ return pFile->sectorSize;
- }
--
-+#endif /* __QNXNTO__ */
-
- /*
--** Delete the file at zPath. If the dirSync argument is true, fsync()
--** the directory after deleting the file.
-+** Return the device characteristics for the file.
-+**
-+** This VFS is set up to return SQLITE_IOCAP_POWERSAFE_OVERWRITE by default.
-+** However, that choice is contraversial since technically the underlying
-+** file system does not always provide powersafe overwrites. (In other
-+** words, after a power-loss event, parts of the file that were never
-+** written might end up being altered.) However, non-PSOW behavior is very,
-+** very rare. And asserting PSOW makes a large reduction in the amount
-+** of required I/O for journaling, since a lot of padding is eliminated.
-+** Hence, while POWERSAFE_OVERWRITE is on by default, there is a file-control
-+** available to turn it off and URI query parameter available to turn it off.
- */
--static int unixDelete(
-- sqlite3_vfs *NotUsed, /* VFS containing this as the xDelete method */
-- const char *zPath, /* Name of file to be deleted */
-- int dirSync /* If true, fsync() directory after deleting file */
--){
-- int rc = SQLITE_OK;
-- UNUSED_PARAMETER(NotUsed);
-- SimulateIOError(return SQLITE_IOERR_DELETE);
-- if( osUnlink(zPath)==(-1) ){
-- if( errno==ENOENT ){
-- rc = SQLITE_IOERR_DELETE_NOENT;
-- }else{
-- rc = unixLogError(SQLITE_IOERR_DELETE, "unlink", zPath);
-- }
-- return rc;
-- }
--#ifndef SQLITE_DISABLE_DIRSYNC
-- if( (dirSync & 1)!=0 ){
-- int fd;
-- rc = osOpenDirectory(zPath, &fd);
-- if( rc==SQLITE_OK ){
--#if OS_VXWORKS
-- if( fsync(fd)==-1 )
--#else
-- if( fsync(fd) )
-+static int unixDeviceCharacteristics(sqlite3_file *id){
-+ unixFile *p = (unixFile*)id;
-+ int rc = 0;
-+#ifdef __QNXNTO__
-+ if( p->sectorSize==0 ) unixSectorSize(id);
-+ rc = p->deviceCharacteristics;
- #endif
-- {
-- rc = unixLogError(SQLITE_IOERR_DIR_FSYNC, "fsync", zPath);
-- }
-- robust_close(0, fd, __LINE__);
-- }else if( rc==SQLITE_CANTOPEN ){
-- rc = SQLITE_OK;
-- }
-+ if( p->ctrlFlags & UNIXFILE_PSOW ){
-+ rc |= SQLITE_IOCAP_POWERSAFE_OVERWRITE;
- }
--#endif
- return rc;
- }
-
-+#ifndef SQLITE_OMIT_WAL
-+
-+
- /*
--** Test the existence of or access permissions of file zPath. The
--** test performed depends on the value of flags:
-+** Object used to represent an shared memory buffer.
- **
--** SQLITE_ACCESS_EXISTS: Return 1 if the file exists
--** SQLITE_ACCESS_READWRITE: Return 1 if the file is read and writable.
--** SQLITE_ACCESS_READONLY: Return 1 if the file is readable.
-+** When multiple threads all reference the same wal-index, each thread
-+** has its own unixShm object, but they all point to a single instance
-+** of this unixShmNode object. In other words, each wal-index is opened
-+** only once per process.
- **
--** Otherwise return 0.
-+** Each unixShmNode object is connected to a single unixInodeInfo object.
-+** We could coalesce this object into unixInodeInfo, but that would mean
-+** every open file that does not use shared memory (in other words, most
-+** open files) would have to carry around this extra information. So
-+** the unixInodeInfo object contains a pointer to this unixShmNode object
-+** and the unixShmNode object is created only when needed.
-+**
-+** unixMutexHeld() must be true when creating or destroying
-+** this object or while reading or writing the following fields:
-+**
-+** nRef
-+**
-+** The following fields are read-only after the object is created:
-+**
-+** fid
-+** zFilename
-+**
-+** Either unixShmNode.mutex must be held or unixShmNode.nRef==0 and
-+** unixMutexHeld() is true when reading or writing any other field
-+** in this structure.
- */
--static int unixAccess(
-- sqlite3_vfs *NotUsed, /* The VFS containing this xAccess method */
-- const char *zPath, /* Path of the file to examine */
-- int flags, /* What do we want to learn about the zPath file? */
-- int *pResOut /* Write result boolean here */
--){
-- int amode = 0;
-- UNUSED_PARAMETER(NotUsed);
-- SimulateIOError( return SQLITE_IOERR_ACCESS; );
-- switch( flags ){
-- case SQLITE_ACCESS_EXISTS:
-- amode = F_OK;
-- break;
-- case SQLITE_ACCESS_READWRITE:
-- amode = W_OK|R_OK;
-- break;
-- case SQLITE_ACCESS_READ:
-- amode = R_OK;
-- break;
-+struct unixShmNode {
-+ unixInodeInfo *pInode; /* unixInodeInfo that owns this SHM node */
-+ sqlite3_mutex *mutex; /* Mutex to access this object */
-+ char *zFilename; /* Name of the mmapped file */
-+ int h; /* Open file descriptor */
-+ int szRegion; /* Size of shared-memory regions */
-+ u16 nRegion; /* Size of array apRegion */
-+ u8 isReadonly; /* True if read-only */
-+ char **apRegion; /* Array of mapped shared-memory regions */
-+ int nRef; /* Number of unixShm objects pointing to this */
-+ unixShm *pFirst; /* All unixShm objects pointing to this */
-+#ifdef SQLITE_DEBUG
-+ u8 exclMask; /* Mask of exclusive locks held */
-+ u8 sharedMask; /* Mask of shared locks held */
-+ u8 nextShmId; /* Next available unixShm.id value */
-+#endif
-+};
-
-- default:
-- assert(!"Invalid flags argument");
-- }
-- *pResOut = (osAccess(zPath, amode)==0);
-- if( flags==SQLITE_ACCESS_EXISTS && *pResOut ){
-- struct stat buf;
-- if( 0==osStat(zPath, &buf) && buf.st_size==0 ){
-- *pResOut = 0;
-- }
-- }
-- return SQLITE_OK;
--}
-+/*
-+** Structure used internally by this VFS to record the state of an
-+** open shared memory connection.
-+**
-+** The following fields are initialized when this object is created and
-+** are read-only thereafter:
-+**
-+** unixShm.pFile
-+** unixShm.id
-+**
-+** All other fields are read/write. The unixShm.pFile->mutex must be held
-+** while accessing any read/write fields.
-+*/
-+struct unixShm {
-+ unixShmNode *pShmNode; /* The underlying unixShmNode object */
-+ unixShm *pNext; /* Next unixShm with the same unixShmNode */
-+ u8 hasMutex; /* True if holding the unixShmNode mutex */
-+ u8 id; /* Id of this connection within its unixShmNode */
-+ u16 sharedMask; /* Mask of shared locks held */
-+ u16 exclMask; /* Mask of exclusive locks held */
-+};
-
-+/*
-+** Constants used for locking
-+*/
-+#define UNIX_SHM_BASE ((22+SQLITE_SHM_NLOCK)*4) /* first lock byte */
-+#define UNIX_SHM_DMS (UNIX_SHM_BASE+SQLITE_SHM_NLOCK) /* deadman switch */
-
- /*
--** Turn a relative pathname into a full pathname. The relative path
--** is stored as a nul-terminated string in the buffer pointed to by
--** zPath.
-+** Apply posix advisory locks for all bytes from ofst through ofst+n-1.
- **
--** zOut points to a buffer of at least sqlite3_vfs.mxPathname bytes
--** (in this case, MAX_PATHNAME bytes). The full-path is written to
--** this buffer before returning.
-+** Locks block if the mask is exactly UNIX_SHM_C and are non-blocking
-+** otherwise.
- */
--static int unixFullPathname(
-- sqlite3_vfs *pVfs, /* Pointer to vfs object */
-- const char *zPath, /* Possibly relative input path */
-- int nOut, /* Size of output buffer in bytes */
-- char *zOut /* Output buffer */
-+static int unixShmSystemLock(
-+ unixShmNode *pShmNode, /* Apply locks to this open shared-memory segment */
-+ int lockType, /* F_UNLCK, F_RDLCK, or F_WRLCK */
-+ int ofst, /* First byte of the locking range */
-+ int n /* Number of bytes to lock */
- ){
-+ struct flock f; /* The posix advisory locking structure */
-+ int rc = SQLITE_OK; /* Result code form fcntl() */
-
-- /* It's odd to simulate an io-error here, but really this is just
-- ** using the io-error infrastructure to test that SQLite handles this
-- ** function failing. This function could fail if, for example, the
-- ** current working directory has been unlinked.
-- */
-- SimulateIOError( return SQLITE_ERROR );
-+ /* Access to the unixShmNode object is serialized by the caller */
-+ assert( sqlite3_mutex_held(pShmNode->mutex) || pShmNode->nRef==0 );
-
-- assert( pVfs->mxPathname==MAX_PATHNAME );
-- UNUSED_PARAMETER(pVfs);
-+ /* Shared locks never span more than one byte */
-+ assert( n==1 || lockType!=F_RDLCK );
-
-- zOut[nOut-1] = '\0';
-- if( zPath[0]=='/' ){
-- sqlite3_snprintf(nOut, zOut, "%s", zPath);
-+ /* Locks are within range */
-+ assert( n>=1 && n<SQLITE_SHM_NLOCK );
-+
-+ if( pShmNode->h>=0 ){
-+ /* Initialize the locking parameters */
-+ memset(&f, 0, sizeof(f));
-+ f.l_type = lockType;
-+ f.l_whence = SEEK_SET;
-+ f.l_start = ofst;
-+ f.l_len = n;
-+
-+ rc = osFcntl(pShmNode->h, F_SETLK, &f);
-+ rc = (rc!=(-1)) ? SQLITE_OK : SQLITE_BUSY;
-+ }
-+
-+ /* Update the global lock state and do debug tracing */
-+#ifdef SQLITE_DEBUG
-+ { u16 mask;
-+ OSTRACE(("SHM-LOCK "));
-+ mask = (1<<(ofst+n)) - (1<<ofst);
-+ if( rc==SQLITE_OK ){
-+ if( lockType==F_UNLCK ){
-+ OSTRACE(("unlock %d ok", ofst));
-+ pShmNode->exclMask &= ~mask;
-+ pShmNode->sharedMask &= ~mask;
-+ }else if( lockType==F_RDLCK ){
-+ OSTRACE(("read-lock %d ok", ofst));
-+ pShmNode->exclMask &= ~mask;
-+ pShmNode->sharedMask |= mask;
-+ }else{
-+ assert( lockType==F_WRLCK );
-+ OSTRACE(("write-lock %d ok", ofst));
-+ pShmNode->exclMask |= mask;
-+ pShmNode->sharedMask &= ~mask;
-+ }
- }else{
-- int nCwd;
-- if( osGetcwd(zOut, nOut-1)==0 ){
-- return unixLogError(SQLITE_CANTOPEN_BKPT, "getcwd", zPath);
-+ if( lockType==F_UNLCK ){
-+ OSTRACE(("unlock %d failed", ofst));
-+ }else if( lockType==F_RDLCK ){
-+ OSTRACE(("read-lock failed"));
-+ }else{
-+ assert( lockType==F_WRLCK );
-+ OSTRACE(("write-lock %d failed", ofst));
- }
-- nCwd = (int)strlen(zOut);
-- sqlite3_snprintf(nOut-nCwd, &zOut[nCwd], "/%s", zPath);
- }
-- return SQLITE_OK;
--}
--
-+ OSTRACE((" - afterwards %03x,%03x\n",
-+ pShmNode->sharedMask, pShmNode->exclMask));
-+ }
-+#endif
-
--#ifndef SQLITE_OMIT_LOAD_EXTENSION
--/*
--** Interfaces for opening a shared library, finding entry points
--** within the shared library, and closing the shared library.
--*/
--#include <dlfcn.h>
--static void *unixDlOpen(sqlite3_vfs *NotUsed, const char *zFilename){
-- UNUSED_PARAMETER(NotUsed);
-- return dlopen(zFilename, RTLD_NOW | RTLD_GLOBAL);
-+ return rc;
- }
-
-+
- /*
--** SQLite calls this function immediately after a call to unixDlSym() or
--** unixDlOpen() fails (returns a null pointer). If a more detailed error
--** message is available, it is written to zBufOut. If no error message
--** is available, zBufOut is left unmodified and SQLite uses a default
--** error message.
-+** Purge the unixShmNodeList list of all entries with unixShmNode.nRef==0.
-+**
-+** This is not a VFS shared-memory method; it is a utility function called
-+** by VFS shared-memory methods.
- */
--static void unixDlError(sqlite3_vfs *NotUsed, int nBuf, char *zBufOut){
-- const char *zErr;
-- UNUSED_PARAMETER(NotUsed);
-- unixEnterMutex();
-- zErr = dlerror();
-- if( zErr ){
-- sqlite3_snprintf(nBuf, zBufOut, "%s", zErr);
-+static void unixShmPurge(unixFile *pFd){
-+ unixShmNode *p = pFd->pInode->pShmNode;
-+ assert( unixMutexHeld() );
-+ if( p && p->nRef==0 ){
-+ int i;
-+ assert( p->pInode==pFd->pInode );
-+ sqlite3_mutex_free(p->mutex);
-+ for(i=0; i<p->nRegion; i++){
-+ if( p->h>=0 ){
-+ osMunmap(p->apRegion[i], p->szRegion);
-+ }else{
-+ sqlite3_free(p->apRegion[i]);
-+ }
-+ }
-+ sqlite3_free(p->apRegion);
-+ if( p->h>=0 ){
-+ robust_close(pFd, p->h, __LINE__);
-+ p->h = -1;
-+ }
-+ p->pInode->pShmNode = 0;
-+ sqlite3_free(p);
- }
-- unixLeaveMutex();
--}
--static void (*unixDlSym(sqlite3_vfs *NotUsed, void *p, const char*zSym))(void){
-- /*
-- ** GCC with -pedantic-errors says that C90 does not allow a void* to be
-- ** cast into a pointer to a function. And yet the library dlsym() routine
-- ** returns a void* which is really a pointer to a function. So how do we
-- ** use dlsym() with -pedantic-errors?
-- **
-- ** Variable x below is defined to be a pointer to a function taking
-- ** parameters void* and const char* and returning a pointer to a function.
-- ** We initialize x by assigning it a pointer to the dlsym() function.
-- ** (That assignment requires a cast.) Then we call the function that
-- ** x points to.
-- **
-- ** This work-around is unlikely to work correctly on any system where
-- ** you really cannot cast a function pointer into void*. But then, on the
-- ** other hand, dlsym() will not work on such a system either, so we have
-- ** not really lost anything.
-- */
-- void (*(*x)(void*,const char*))(void);
-- UNUSED_PARAMETER(NotUsed);
-- x = (void(*(*)(void*,const char*))(void))dlsym;
-- return (*x)(p, zSym);
--}
--static void unixDlClose(sqlite3_vfs *NotUsed, void *pHandle){
-- UNUSED_PARAMETER(NotUsed);
-- dlclose(pHandle);
- }
--#else /* if SQLITE_OMIT_LOAD_EXTENSION is defined: */
-- #define unixDlOpen 0
-- #define unixDlError 0
-- #define unixDlSym 0
-- #define unixDlClose 0
--#endif
-
- /*
--** Write nBuf bytes of random data to the supplied buffer zBuf.
-+** Open a shared-memory area associated with open database file pDbFd.
-+** This particular implementation uses mmapped files.
-+**
-+** The file used to implement shared-memory is in the same directory
-+** as the open database file and has the same name as the open database
-+** file with the "-shm" suffix added. For example, if the database file
-+** is "/home/user1/config.db" then the file that is created and mmapped
-+** for shared memory will be called "/home/user1/config.db-shm".
-+**
-+** Another approach to is to use files in /dev/shm or /dev/tmp or an
-+** some other tmpfs mount. But if a file in a different directory
-+** from the database file is used, then differing access permissions
-+** or a chroot() might cause two different processes on the same
-+** database to end up using different files for shared memory -
-+** meaning that their memory would not really be shared - resulting
-+** in database corruption. Nevertheless, this tmpfs file usage
-+** can be enabled at compile-time using -DSQLITE_SHM_DIRECTORY="/dev/shm"
-+** or the equivalent. The use of the SQLITE_SHM_DIRECTORY compile-time
-+** option results in an incompatible build of SQLite; builds of SQLite
-+** that with differing SQLITE_SHM_DIRECTORY settings attempt to use the
-+** same database file at the same time, database corruption will likely
-+** result. The SQLITE_SHM_DIRECTORY compile-time option is considered
-+** "unsupported" and may go away in a future SQLite release.
-+**
-+** When opening a new shared-memory file, if no other instances of that
-+** file are currently open, in this process or in other processes, then
-+** the file must be truncated to zero length or have its header cleared.
-+**
-+** If the original database file (pDbFd) is using the "unix-excl" VFS
-+** that means that an exclusive lock is held on the database file and
-+** that no other processes are able to read or write the database. In
-+** that case, we do not really need shared memory. No shared memory
-+** file is created. The shared memory will be simulated with heap memory.
- */
--static int unixRandomness(sqlite3_vfs *NotUsed, int nBuf, char *zBuf){
-- UNUSED_PARAMETER(NotUsed);
-- assert((size_t)nBuf>=(sizeof(time_t)+sizeof(int)));
-+static int unixOpenSharedMemory(unixFile *pDbFd){
-+ struct unixShm *p = 0; /* The connection to be opened */
-+ struct unixShmNode *pShmNode; /* The underlying mmapped file */
-+ int rc; /* Result code */
-+ unixInodeInfo *pInode; /* The inode of fd */
-+ char *zShmFilename; /* Name of the file used for SHM */
-+ int nShmFilename; /* Size of the SHM filename in bytes */
-
-- /* We have to initialize zBuf to prevent valgrind from reporting
-- ** errors. The reports issued by valgrind are incorrect - we would
-- ** prefer that the randomness be increased by making use of the
-- ** uninitialized space in zBuf - but valgrind errors tend to worry
-- ** some users. Rather than argue, it seems easier just to initialize
-- ** the whole array and silence valgrind, even if that means less randomness
-- ** in the random seed.
-- **
-- ** When testing, initializing zBuf[] to zero is all we do. That means
-- ** that we always use the same random number sequence. This makes the
-- ** tests repeatable.
-- */
-- memset(zBuf, 0, nBuf);
--#if !defined(SQLITE_TEST)
-- {
-- int pid, fd, got;
-- fd = robust_open("/dev/urandom", O_RDONLY, 0);
-- if( fd<0 ){
-- time_t t;
-- time(&t);
-- memcpy(zBuf, &t, sizeof(t));
-- pid = getpid();
-- memcpy(&zBuf[sizeof(t)], &pid, sizeof(pid));
-- assert( sizeof(t)+sizeof(pid)<=(size_t)nBuf );
-- nBuf = sizeof(t) + sizeof(pid);
-- }else{
-- do{ got = osRead(fd, zBuf, nBuf); }while( got<0 && errno==EINTR );
-- robust_close(0, fd, __LINE__);
-- }
-- }
--#endif
-- return nBuf;
--}
-+ /* Allocate space for the new unixShm object. */
-+ p = sqlite3_malloc( sizeof(*p) );
-+ if( p==0 ) return SQLITE_NOMEM;
-+ memset(p, 0, sizeof(*p));
-+ assert( pDbFd->pShm==0 );
-
-+ /* Check to see if a unixShmNode object already exists. Reuse an existing
-+ ** one if present. Create a new one if necessary.
-+ */
-+ unixEnterMutex();
-+ pInode = pDbFd->pInode;
-+ pShmNode = pInode->pShmNode;
-+ if( pShmNode==0 ){
-+ struct stat sStat; /* fstat() info for database file */
-
--/*
--** Sleep for a little while. Return the amount of time slept.
--** The argument is the number of microseconds we want to sleep.
--** The return value is the number of microseconds of sleep actually
--** requested from the underlying operating system, a number which
--** might be greater than or equal to the argument, but not less
--** than the argument.
--*/
--static int unixSleep(sqlite3_vfs *NotUsed, int microseconds){
--#if OS_VXWORKS
-- struct timespec sp;
-+ /* Call fstat() to figure out the permissions on the database file. If
-+ ** a new *-shm file is created, an attempt will be made to create it
-+ ** with the same permissions.
-+ */
-+ if( osFstat(pDbFd->h, &sStat) && pInode->bProcessLock==0 ){
-+ rc = SQLITE_IOERR_FSTAT;
-+ goto shm_open_err;
-+ }
-
-- sp.tv_sec = microseconds / 1000000;
-- sp.tv_nsec = (microseconds % 1000000) * 1000;
-- nanosleep(&sp, NULL);
-- UNUSED_PARAMETER(NotUsed);
-- return microseconds;
--#elif defined(HAVE_USLEEP) && HAVE_USLEEP
-- usleep(microseconds);
-- UNUSED_PARAMETER(NotUsed);
-- return microseconds;
-+#ifdef SQLITE_SHM_DIRECTORY
-+ nShmFilename = sizeof(SQLITE_SHM_DIRECTORY) + 31;
- #else
-- int seconds = (microseconds+999999)/1000000;
-- sleep(seconds);
-- UNUSED_PARAMETER(NotUsed);
-- return seconds*1000000;
-+ nShmFilename = 6 + (int)strlen(pDbFd->zPath);
- #endif
--}
-+ pShmNode = sqlite3_malloc( sizeof(*pShmNode) + nShmFilename );
-+ if( pShmNode==0 ){
-+ rc = SQLITE_NOMEM;
-+ goto shm_open_err;
-+ }
-+ memset(pShmNode, 0, sizeof(*pShmNode)+nShmFilename);
-+ zShmFilename = pShmNode->zFilename = (char*)&pShmNode[1];
-+#ifdef SQLITE_SHM_DIRECTORY
-+ sqlite3_snprintf(nShmFilename, zShmFilename,
-+ SQLITE_SHM_DIRECTORY "/sqlite-shm-%x-%x",
-+ (u32)sStat.st_ino, (u32)sStat.st_dev);
-+#else
-+ sqlite3_snprintf(nShmFilename, zShmFilename, "%s-shm", pDbFd->zPath);
-+ sqlite3FileSuffix3(pDbFd->zPath, zShmFilename);
-+#endif
-+ pShmNode->h = -1;
-+ pDbFd->pInode->pShmNode = pShmNode;
-+ pShmNode->pInode = pDbFd->pInode;
-+ pShmNode->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
-+ if( pShmNode->mutex==0 ){
-+ rc = SQLITE_NOMEM;
-+ goto shm_open_err;
-+ }
-+
-+ if( pInode->bProcessLock==0 ){
-+ int openFlags = O_RDWR | O_CREAT;
-+ if( sqlite3_uri_boolean(pDbFd->zPath, "readonly_shm", 0) ){
-+ openFlags = O_RDONLY;
-+ pShmNode->isReadonly = 1;
-+ }
-+ pShmNode->h = robust_open(zShmFilename, openFlags, (sStat.st_mode&0777));
-+ if( pShmNode->h<0 ){
-+ rc = unixLogError(SQLITE_CANTOPEN_BKPT, "open", zShmFilename);
-+ goto shm_open_err;
-+ }
-+
-+ /* If this process is running as root, make sure that the SHM file
-+ ** is owned by the same user that owns the original database. Otherwise,
-+ ** the original owner will not be able to connect.
-+ */
-+ osFchown(pShmNode->h, sStat.st_uid, sStat.st_gid);
-+
-+ /* Check to see if another process is holding the dead-man switch.
-+ ** If not, truncate the file to zero length.
-+ */
-+ rc = SQLITE_OK;
-+ if( unixShmSystemLock(pShmNode, F_WRLCK, UNIX_SHM_DMS, 1)==SQLITE_OK ){
-+ if( robust_ftruncate(pShmNode->h, 0) ){
-+ rc = unixLogError(SQLITE_IOERR_SHMOPEN, "ftruncate", zShmFilename);
-+ }
-+ }
-+ if( rc==SQLITE_OK ){
-+ rc = unixShmSystemLock(pShmNode, F_RDLCK, UNIX_SHM_DMS, 1);
-+ }
-+ if( rc ) goto shm_open_err;
-+ }
-+ }
-
--/*
--** The following variable, if set to a non-zero value, is interpreted as
--** the number of seconds since 1970 and is used to set the result of
--** sqlite3OsCurrentTime() during testing.
--*/
--#ifdef SQLITE_TEST
--SQLITE_API int sqlite3_current_time = 0; /* Fake system time in seconds since 1970. */
-+ /* Make the new connection a child of the unixShmNode */
-+ p->pShmNode = pShmNode;
-+#ifdef SQLITE_DEBUG
-+ p->id = pShmNode->nextShmId++;
- #endif
-+ pShmNode->nRef++;
-+ pDbFd->pShm = p;
-+ unixLeaveMutex();
-+
-+ /* The reference count on pShmNode has already been incremented under
-+ ** the cover of the unixEnterMutex() mutex and the pointer from the
-+ ** new (struct unixShm) object to the pShmNode has been set. All that is
-+ ** left to do is to link the new object into the linked list starting
-+ ** at pShmNode->pFirst. This must be done while holding the pShmNode->mutex
-+ ** mutex.
-+ */
-+ sqlite3_mutex_enter(pShmNode->mutex);
-+ p->pNext = pShmNode->pFirst;
-+ pShmNode->pFirst = p;
-+ sqlite3_mutex_leave(pShmNode->mutex);
-+ return SQLITE_OK;
-+
-+ /* Jump here on any error */
-+shm_open_err:
-+ unixShmPurge(pDbFd); /* This call frees pShmNode if required */
-+ sqlite3_free(p);
-+ unixLeaveMutex();
-+ return rc;
-+}
-
- /*
--** Find the current time (in Universal Coordinated Time). Write into *piNow
--** the current time and date as a Julian Day number times 86_400_000. In
--** other words, write into *piNow the number of milliseconds since the Julian
--** epoch of noon in Greenwich on November 24, 4714 B.C according to the
--** proleptic Gregorian calendar.
-+** This function is called to obtain a pointer to region iRegion of the
-+** shared-memory associated with the database file fd. Shared-memory regions
-+** are numbered starting from zero. Each shared-memory region is szRegion
-+** bytes in size.
- **
--** On success, return SQLITE_OK. Return SQLITE_ERROR if the time and date
--** cannot be found.
-+** If an error occurs, an error code is returned and *pp is set to NULL.
-+**
-+** Otherwise, if the bExtend parameter is 0 and the requested shared-memory
-+** region has not been allocated (by any client, including one running in a
-+** separate process), then *pp is set to NULL and SQLITE_OK returned. If
-+** bExtend is non-zero and the requested shared-memory region has not yet
-+** been allocated, it is allocated by this function.
-+**
-+** If the shared-memory region has already been allocated or is allocated by
-+** this call as described above, then it is mapped into this processes
-+** address space (if it is not already), *pp is set to point to the mapped
-+** memory and SQLITE_OK returned.
- */
--static int unixCurrentTimeInt64(sqlite3_vfs *NotUsed, sqlite3_int64 *piNow){
-- static const sqlite3_int64 unixEpoch = 24405875*(sqlite3_int64)8640000;
-+static int unixShmMap(
-+ sqlite3_file *fd, /* Handle open on database file */
-+ int iRegion, /* Region to retrieve */
-+ int szRegion, /* Size of regions */
-+ int bExtend, /* True to extend file if necessary */
-+ void volatile **pp /* OUT: Mapped memory */
-+){
-+ unixFile *pDbFd = (unixFile*)fd;
-+ unixShm *p;
-+ unixShmNode *pShmNode;
- int rc = SQLITE_OK;
--#if defined(NO_GETTOD)
-- time_t t;
-- time(&t);
-- *piNow = ((sqlite3_int64)t)*1000 + unixEpoch;
--#elif OS_VXWORKS
-- struct timespec sNow;
-- clock_gettime(CLOCK_REALTIME, &sNow);
-- *piNow = unixEpoch + 1000*(sqlite3_int64)sNow.tv_sec + sNow.tv_nsec/1000000;
--#else
-- struct timeval sNow;
-- if( gettimeofday(&sNow, 0)==0 ){
-- *piNow = unixEpoch + 1000*(sqlite3_int64)sNow.tv_sec + sNow.tv_usec/1000;
-- }else{
-- rc = SQLITE_ERROR;
-+
-+ /* If the shared-memory file has not yet been opened, open it now. */
-+ if( pDbFd->pShm==0 ){
-+ rc = unixOpenSharedMemory(pDbFd);
-+ if( rc!=SQLITE_OK ) return rc;
- }
--#endif
-
--#ifdef SQLITE_TEST
-- if( sqlite3_current_time ){
-- *piNow = 1000*(sqlite3_int64)sqlite3_current_time + unixEpoch;
-+ p = pDbFd->pShm;
-+ pShmNode = p->pShmNode;
-+ sqlite3_mutex_enter(pShmNode->mutex);
-+ assert( szRegion==pShmNode->szRegion || pShmNode->nRegion==0 );
-+ assert( pShmNode->pInode==pDbFd->pInode );
-+ assert( pShmNode->h>=0 || pDbFd->pInode->bProcessLock==1 );
-+ assert( pShmNode->h<0 || pDbFd->pInode->bProcessLock==0 );
-+
-+ if( pShmNode->nRegion<=iRegion ){
-+ char **apNew; /* New apRegion[] array */
-+ int nByte = (iRegion+1)*szRegion; /* Minimum required file size */
-+ struct stat sStat; /* Used by fstat() */
-+
-+ pShmNode->szRegion = szRegion;
-+
-+ if( pShmNode->h>=0 ){
-+ /* The requested region is not mapped into this processes address space.
-+ ** Check to see if it has been allocated (i.e. if the wal-index file is
-+ ** large enough to contain the requested region).
-+ */
-+ if( osFstat(pShmNode->h, &sStat) ){
-+ rc = SQLITE_IOERR_SHMSIZE;
-+ goto shmpage_out;
-+ }
-+
-+ if( sStat.st_size<nByte ){
-+ /* The requested memory region does not exist. If bExtend is set to
-+ ** false, exit early. *pp will be set to NULL and SQLITE_OK returned.
-+ */
-+ if( !bExtend ){
-+ goto shmpage_out;
-+ }
-+
-+ /* Alternatively, if bExtend is true, extend the file. Do this by
-+ ** writing a single byte to the end of each (OS) page being
-+ ** allocated or extended. Technically, we need only write to the
-+ ** last page in order to extend the file. But writing to all new
-+ ** pages forces the OS to allocate them immediately, which reduces
-+ ** the chances of SIGBUS while accessing the mapped region later on.
-+ */
-+ else{
-+ static const int pgsz = 4096;
-+ int iPg;
-+
-+ /* Write to the last byte of each newly allocated or extended page */
-+ assert( (nByte % pgsz)==0 );
-+ for(iPg=(sStat.st_size/pgsz); iPg<(nByte/pgsz); iPg++){
-+ if( seekAndWriteFd(pShmNode->h, iPg*pgsz + pgsz-1, "", 1, 0)!=1 ){
-+ const char *zFile = pShmNode->zFilename;
-+ rc = unixLogError(SQLITE_IOERR_SHMSIZE, "write", zFile);
-+ goto shmpage_out;
-+ }
-+ }
-+ }
-+ }
-+ }
-+
-+ /* Map the requested memory region into this processes address space. */
-+ apNew = (char **)sqlite3_realloc(
-+ pShmNode->apRegion, (iRegion+1)*sizeof(char *)
-+ );
-+ if( !apNew ){
-+ rc = SQLITE_IOERR_NOMEM;
-+ goto shmpage_out;
-+ }
-+ pShmNode->apRegion = apNew;
-+ while(pShmNode->nRegion<=iRegion){
-+ void *pMem;
-+ if( pShmNode->h>=0 ){
-+ pMem = osMmap(0, szRegion,
-+ pShmNode->isReadonly ? PROT_READ : PROT_READ|PROT_WRITE,
-+ MAP_SHARED, pShmNode->h, szRegion*(i64)pShmNode->nRegion
-+ );
-+ if( pMem==MAP_FAILED ){
-+ rc = unixLogError(SQLITE_IOERR_SHMMAP, "mmap", pShmNode->zFilename);
-+ goto shmpage_out;
-+ }
-+ }else{
-+ pMem = sqlite3_malloc(szRegion);
-+ if( pMem==0 ){
-+ rc = SQLITE_NOMEM;
-+ goto shmpage_out;
-+ }
-+ memset(pMem, 0, szRegion);
-+ }
-+ pShmNode->apRegion[pShmNode->nRegion] = pMem;
-+ pShmNode->nRegion++;
-+ }
- }
--#endif
-- UNUSED_PARAMETER(NotUsed);
-- return rc;
--}
-
--/*
--** Find the current time (in Universal Coordinated Time). Write the
--** current time and date as a Julian Day number into *prNow and
--** return 0. Return 1 if the time and date cannot be found.
--*/
--static int unixCurrentTime(sqlite3_vfs *NotUsed, double *prNow){
-- sqlite3_int64 i = 0;
-- int rc;
-- UNUSED_PARAMETER(NotUsed);
-- rc = unixCurrentTimeInt64(0, &i);
-- *prNow = i/86400000.0;
-+shmpage_out:
-+ if( pShmNode->nRegion>iRegion ){
-+ *pp = pShmNode->apRegion[iRegion];
-+ }else{
-+ *pp = 0;
-+ }
-+ if( pShmNode->isReadonly && rc==SQLITE_OK ) rc = SQLITE_READONLY;
-+ sqlite3_mutex_leave(pShmNode->mutex);
- return rc;
- }
-
- /*
--** We added the xGetLastError() method with the intention of providing
--** better low-level error messages when operating-system problems come up
--** during SQLite operation. But so far, none of that has been implemented
--** in the core. So this routine is never called. For now, it is merely
--** a place-holder.
--*/
--static int unixGetLastError(sqlite3_vfs *NotUsed, int NotUsed2, char *NotUsed3){
-- UNUSED_PARAMETER(NotUsed);
-- UNUSED_PARAMETER(NotUsed2);
-- UNUSED_PARAMETER(NotUsed3);
-- return 0;
--}
--
--
--/*
--************************ End of sqlite3_vfs methods ***************************
--******************************************************************************/
--
--/******************************************************************************
--************************** Begin Proxy Locking ********************************
--**
--** Proxy locking is a "uber-locking-method" in this sense: It uses the
--** other locking methods on secondary lock files. Proxy locking is a
--** meta-layer over top of the primitive locking implemented above. For
--** this reason, the division that implements of proxy locking is deferred
--** until late in the file (here) after all of the other I/O methods have
--** been defined - so that the primitive locking methods are available
--** as services to help with the implementation of proxy locking.
--**
--****
--**
--** The default locking schemes in SQLite use byte-range locks on the
--** database file to coordinate safe, concurrent access by multiple readers
--** and writers [http://sqlite.org/lockingv3.html]. The five file locking
--** states (UNLOCKED, PENDING, SHARED, RESERVED, EXCLUSIVE) are implemented
--** as POSIX read & write locks over fixed set of locations (via fsctl),
--** on AFP and SMB only exclusive byte-range locks are available via fsctl
--** with _IOWR('z', 23, struct ByteRangeLockPB2) to track the same 5 states.
--** To simulate a F_RDLCK on the shared range, on AFP a randomly selected
--** address in the shared range is taken for a SHARED lock, the entire
--** shared range is taken for an EXCLUSIVE lock):
--**
--** PENDING_BYTE 0x40000000
--** RESERVED_BYTE 0x40000001
--** SHARED_RANGE 0x40000002 -> 0x40000200
--**
--** This works well on the local file system, but shows a nearly 100x
--** slowdown in read performance on AFP because the AFP client disables
--** the read cache when byte-range locks are present. Enabling the read
--** cache exposes a cache coherency problem that is present on all OS X
--** supported network file systems. NFS and AFP both observe the
--** close-to-open semantics for ensuring cache coherency
--** [http://nfs.sourceforge.net/#faq_a8], which does not effectively
--** address the requirements for concurrent database access by multiple
--** readers and writers
--** [http://www.nabble.com/SQLite-on-NFS-cache-coherency-td15655701.html].
--**
--** To address the performance and cache coherency issues, proxy file locking
--** changes the way database access is controlled by limiting access to a
--** single host at a time and moving file locks off of the database file
--** and onto a proxy file on the local file system.
--**
--**
--** Using proxy locks
--** -----------------
--**
--** C APIs
--**
--** sqlite3_file_control(db, dbname, SQLITE_SET_LOCKPROXYFILE,
--** <proxy_path> | ":auto:");
--** sqlite3_file_control(db, dbname, SQLITE_GET_LOCKPROXYFILE, &<proxy_path>);
--**
--**
--** SQL pragmas
--**
--** PRAGMA [database.]lock_proxy_file=<proxy_path> | :auto:
--** PRAGMA [database.]lock_proxy_file
--**
--** Specifying ":auto:" means that if there is a conch file with a matching
--** host ID in it, the proxy path in the conch file will be used, otherwise
--** a proxy path based on the user's temp dir
--** (via confstr(_CS_DARWIN_USER_TEMP_DIR,...)) will be used and the
--** actual proxy file name is generated from the name and path of the
--** database file. For example:
--**
--** For database path "/Users/me/foo.db"
--** The lock path will be "<tmpdir>/sqliteplocks/_Users_me_foo.db:auto:")
--**
--** Once a lock proxy is configured for a database connection, it can not
--** be removed, however it may be switched to a different proxy path via
--** the above APIs (assuming the conch file is not being held by another
--** connection or process).
--**
--**
--** How proxy locking works
--** -----------------------
--**
--** Proxy file locking relies primarily on two new supporting files:
--**
--** * conch file to limit access to the database file to a single host
--** at a time
--**
--** * proxy file to act as a proxy for the advisory locks normally
--** taken on the database
--**
--** The conch file - to use a proxy file, sqlite must first "hold the conch"
--** by taking an sqlite-style shared lock on the conch file, reading the
--** contents and comparing the host's unique host ID (see below) and lock
--** proxy path against the values stored in the conch. The conch file is
--** stored in the same directory as the database file and the file name
--** is patterned after the database file name as ".<databasename>-conch".
--** If the conch file does not exist, or it's contents do not match the
--** host ID and/or proxy path, then the lock is escalated to an exclusive
--** lock and the conch file contents is updated with the host ID and proxy
--** path and the lock is downgraded to a shared lock again. If the conch
--** is held by another process (with a shared lock), the exclusive lock
--** will fail and SQLITE_BUSY is returned.
--**
--** The proxy file - a single-byte file used for all advisory file locks
--** normally taken on the database file. This allows for safe sharing
--** of the database file for multiple readers and writers on the same
--** host (the conch ensures that they all use the same local lock file).
--**
--** Requesting the lock proxy does not immediately take the conch, it is
--** only taken when the first request to lock database file is made.
--** This matches the semantics of the traditional locking behavior, where
--** opening a connection to a database file does not take a lock on it.
--** The shared lock and an open file descriptor are maintained until
--** the connection to the database is closed.
--**
--** The proxy file and the lock file are never deleted so they only need
--** to be created the first time they are used.
--**
--** Configuration options
--** ---------------------
--**
--** SQLITE_PREFER_PROXY_LOCKING
--**
--** Database files accessed on non-local file systems are
--** automatically configured for proxy locking, lock files are
--** named automatically using the same logic as
--** PRAGMA lock_proxy_file=":auto:"
--**
--** SQLITE_PROXY_DEBUG
--**
--** Enables the logging of error messages during host id file
--** retrieval and creation
--**
--** LOCKPROXYDIR
--**
--** Overrides the default directory used for lock proxy files that
--** are named automatically via the ":auto:" setting
--**
--** SQLITE_DEFAULT_PROXYDIR_PERMISSIONS
-+** Change the lock state for a shared-memory segment.
- **
--** Permissions to use when creating a directory for storing the
--** lock proxy files, only used when LOCKPROXYDIR is not set.
--**
--**
--** As mentioned above, when compiled with SQLITE_PREFER_PROXY_LOCKING,
--** setting the environment variable SQLITE_FORCE_PROXY_LOCKING to 1 will
--** force proxy locking to be used for every database file opened, and 0
--** will force automatic proxy locking to be disabled for all database
--** files (explicity calling the SQLITE_SET_LOCKPROXYFILE pragma or
--** sqlite_file_control API is not affected by SQLITE_FORCE_PROXY_LOCKING).
-+** Note that the relationship between SHAREd and EXCLUSIVE locks is a little
-+** different here than in posix. In xShmLock(), one can go from unlocked
-+** to shared and back or from unlocked to exclusive and back. But one may
-+** not go from shared to exclusive or from exclusive to shared.
- */
-+static int unixShmLock(
-+ sqlite3_file *fd, /* Database file holding the shared memory */
-+ int ofst, /* First lock to acquire or release */
-+ int n, /* Number of locks to acquire or release */
-+ int flags /* What to do with the lock */
-+){
-+ unixFile *pDbFd = (unixFile*)fd; /* Connection holding shared memory */
-+ unixShm *p = pDbFd->pShm; /* The shared memory being locked */
-+ unixShm *pX; /* For looping over all siblings */
-+ unixShmNode *pShmNode = p->pShmNode; /* The underlying file iNode */
-+ int rc = SQLITE_OK; /* Result code */
-+ u16 mask; /* Mask of locks to take or release */
-
--/*
--** Proxy locking is only available on MacOSX
--*/
--#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
-+ assert( pShmNode==pDbFd->pInode->pShmNode );
-+ assert( pShmNode->pInode==pDbFd->pInode );
-+ assert( ofst>=0 && ofst+n<=SQLITE_SHM_NLOCK );
-+ assert( n>=1 );
-+ assert( flags==(SQLITE_SHM_LOCK | SQLITE_SHM_SHARED)
-+ || flags==(SQLITE_SHM_LOCK | SQLITE_SHM_EXCLUSIVE)
-+ || flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED)
-+ || flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE) );
-+ assert( n==1 || (flags & SQLITE_SHM_EXCLUSIVE)!=0 );
-+ assert( pShmNode->h>=0 || pDbFd->pInode->bProcessLock==1 );
-+ assert( pShmNode->h<0 || pDbFd->pInode->bProcessLock==0 );
-
--/*
--** The proxyLockingContext has the path and file structures for the remote
--** and local proxy files in it
--*/
--typedef struct proxyLockingContext proxyLockingContext;
--struct proxyLockingContext {
-- unixFile *conchFile; /* Open conch file */
-- char *conchFilePath; /* Name of the conch file */
-- unixFile *lockProxy; /* Open proxy lock file */
-- char *lockProxyPath; /* Name of the proxy lock file */
-- char *dbPath; /* Name of the open file */
-- int conchHeld; /* 1 if the conch is held, -1 if lockless */
-- void *oldLockingContext; /* Original lockingcontext to restore on close */
-- sqlite3_io_methods const *pOldMethod; /* Original I/O methods for close */
--};
-+ mask = (1<<(ofst+n)) - (1<<ofst);
-+ assert( n>1 || mask==(1<<ofst) );
-+ sqlite3_mutex_enter(pShmNode->mutex);
-+ if( flags & SQLITE_SHM_UNLOCK ){
-+ u16 allMask = 0; /* Mask of locks held by siblings */
-
--/*
--** The proxy lock file path for the database at dbPath is written into lPath,
--** which must point to valid, writable memory large enough for a maxLen length
--** file path.
--*/
--static int proxyGetLockPath(const char *dbPath, char *lPath, size_t maxLen){
-- int len;
-- int dbLen;
-- int i;
-+ /* See if any siblings hold this same lock */
-+ for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
-+ if( pX==p ) continue;
-+ assert( (pX->exclMask & (p->exclMask|p->sharedMask))==0 );
-+ allMask |= pX->sharedMask;
-+ }
-
--#ifdef LOCKPROXYDIR
-- len = strlcpy(lPath, LOCKPROXYDIR, maxLen);
--#else
--# ifdef _CS_DARWIN_USER_TEMP_DIR
-- {
-- if( !confstr(_CS_DARWIN_USER_TEMP_DIR, lPath, maxLen) ){
-- OSTRACE(("GETLOCKPATH failed %s errno=%d pid=%d\n",
-- lPath, errno, getpid()));
-- return SQLITE_IOERR_LOCK;
-+ /* Unlock the system-level locks */
-+ if( (mask & allMask)==0 ){
-+ rc = unixShmSystemLock(pShmNode, F_UNLCK, ofst+UNIX_SHM_BASE, n);
-+ }else{
-+ rc = SQLITE_OK;
- }
-- len = strlcat(lPath, "sqliteplocks", maxLen);
-- }
--# else
-- len = strlcpy(lPath, "/tmp/", maxLen);
--# endif
--#endif
-
-- if( lPath[len-1]!='/' ){
-- len = strlcat(lPath, "/", maxLen);
-- }
--
-- /* transform the db path to a unique cache name */
-- dbLen = (int)strlen(dbPath);
-- for( i=0; i<dbLen && (i+len+7)<(int)maxLen; i++){
-- char c = dbPath[i];
-- lPath[i+len] = (c=='/')?'_':c;
-- }
-- lPath[i+len]='\0';
-- strlcat(lPath, ":auto:", maxLen);
-- OSTRACE(("GETLOCKPATH proxy lock path=%s pid=%d\n", lPath, getpid()));
-- return SQLITE_OK;
--}
-+ /* Undo the local locks */
-+ if( rc==SQLITE_OK ){
-+ p->exclMask &= ~mask;
-+ p->sharedMask &= ~mask;
-+ }
-+ }else if( flags & SQLITE_SHM_SHARED ){
-+ u16 allShared = 0; /* Union of locks held by connections other than "p" */
-
--/*
-- ** Creates the lock file and any missing directories in lockPath
-- */
--static int proxyCreateLockPath(const char *lockPath){
-- int i, len;
-- char buf[MAXPATHLEN];
-- int start = 0;
--
-- assert(lockPath!=NULL);
-- /* try to create all the intermediate directories */
-- len = (int)strlen(lockPath);
-- buf[0] = lockPath[0];
-- for( i=1; i<len; i++ ){
-- if( lockPath[i] == '/' && (i - start > 0) ){
-- /* only mkdir if leaf dir != "." or "/" or ".." */
-- if( i-start>2 || (i-start==1 && buf[start] != '.' && buf[start] != '/')
-- || (i-start==2 && buf[start] != '.' && buf[start+1] != '.') ){
-- buf[i]='\0';
-- if( osMkdir(buf, SQLITE_DEFAULT_PROXYDIR_PERMISSIONS) ){
-- int err=errno;
-- if( err!=EEXIST ) {
-- OSTRACE(("CREATELOCKPATH FAILED creating %s, "
-- "'%s' proxy lock path=%s pid=%d\n",
-- buf, strerror(err), lockPath, getpid()));
-- return err;
-- }
-- }
-+ /* Find out which shared locks are already held by sibling connections.
-+ ** If any sibling already holds an exclusive lock, go ahead and return
-+ ** SQLITE_BUSY.
-+ */
-+ for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
-+ if( (pX->exclMask & mask)!=0 ){
-+ rc = SQLITE_BUSY;
-+ break;
- }
-- start=i+1;
-+ allShared |= pX->sharedMask;
- }
-- buf[i] = lockPath[i];
-- }
-- OSTRACE(("CREATELOCKPATH proxy lock path=%s pid=%d\n", lockPath, getpid()));
-- return 0;
--}
--
--/*
--** Create a new VFS file descriptor (stored in memory obtained from
--** sqlite3_malloc) and open the file named "path" in the file descriptor.
--**
--** The caller is responsible not only for closing the file descriptor
--** but also for freeing the memory associated with the file descriptor.
--*/
--static int proxyCreateUnixFile(
-- const char *path, /* path for the new unixFile */
-- unixFile **ppFile, /* unixFile created and returned by ref */
-- int islockfile /* if non zero missing dirs will be created */
--) {
-- int fd = -1;
-- unixFile *pNew;
-- int rc = SQLITE_OK;
-- int openFlags = O_RDWR | O_CREAT;
-- sqlite3_vfs dummyVfs;
-- int terrno = 0;
-- UnixUnusedFd *pUnused = NULL;
-
-- /* 1. first try to open/create the file
-- ** 2. if that fails, and this is a lock file (not-conch), try creating
-- ** the parent directories and then try again.
-- ** 3. if that fails, try to open the file read-only
-- ** otherwise return BUSY (if lock file) or CANTOPEN for the conch file
-- */
-- pUnused = findReusableFd(path, openFlags);
-- if( pUnused ){
-- fd = pUnused->fd;
-- }else{
-- pUnused = sqlite3_malloc(sizeof(*pUnused));
-- if( !pUnused ){
-- return SQLITE_NOMEM;
-- }
-- }
-- if( fd<0 ){
-- fd = robust_open(path, openFlags, 0);
-- terrno = errno;
-- if( fd<0 && errno==ENOENT && islockfile ){
-- if( proxyCreateLockPath(path) == SQLITE_OK ){
-- fd = robust_open(path, openFlags, 0);
-+ /* Get shared locks at the system level, if necessary */
-+ if( rc==SQLITE_OK ){
-+ if( (allShared & mask)==0 ){
-+ rc = unixShmSystemLock(pShmNode, F_RDLCK, ofst+UNIX_SHM_BASE, n);
-+ }else{
-+ rc = SQLITE_OK;
- }
- }
-- }
-- if( fd<0 ){
-- openFlags = O_RDONLY;
-- fd = robust_open(path, openFlags, 0);
-- terrno = errno;
-- }
-- if( fd<0 ){
-- if( islockfile ){
-- return SQLITE_BUSY;
-+
-+ /* Get the local shared locks */
-+ if( rc==SQLITE_OK ){
-+ p->sharedMask |= mask;
- }
-- switch (terrno) {
-- case EACCES:
-- return SQLITE_PERM;
-- case EIO:
-- return SQLITE_IOERR_LOCK; /* even though it is the conch */
-- default:
-- return SQLITE_CANTOPEN_BKPT;
-+ }else{
-+ /* Make sure no sibling connections hold locks that will block this
-+ ** lock. If any do, return SQLITE_BUSY right away.
-+ */
-+ for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
-+ if( (pX->exclMask & mask)!=0 || (pX->sharedMask & mask)!=0 ){
-+ rc = SQLITE_BUSY;
-+ break;
-+ }
- }
-- }
--
-- pNew = (unixFile *)sqlite3_malloc(sizeof(*pNew));
-- if( pNew==NULL ){
-- rc = SQLITE_NOMEM;
-- goto end_create_proxy;
-- }
-- memset(pNew, 0, sizeof(unixFile));
-- pNew->openFlags = openFlags;
-- memset(&dummyVfs, 0, sizeof(dummyVfs));
-- dummyVfs.pAppData = (void*)&autolockIoFinder;
-- dummyVfs.zName = "dummy";
-- pUnused->fd = fd;
-- pUnused->flags = openFlags;
-- pNew->pUnused = pUnused;
-
-- rc = fillInUnixFile(&dummyVfs, fd, (sqlite3_file*)pNew, path, 0);
-- if( rc==SQLITE_OK ){
-- *ppFile = pNew;
-- return SQLITE_OK;
-+ /* Get the exclusive locks at the system level. Then if successful
-+ ** also mark the local connection as being locked.
-+ */
-+ if( rc==SQLITE_OK ){
-+ rc = unixShmSystemLock(pShmNode, F_WRLCK, ofst+UNIX_SHM_BASE, n);
-+ if( rc==SQLITE_OK ){
-+ assert( (p->sharedMask & mask)==0 );
-+ p->exclMask |= mask;
-+ }
-+ }
- }
--end_create_proxy:
-- robust_close(pNew, fd, __LINE__);
-- sqlite3_free(pNew);
-- sqlite3_free(pUnused);
-+ sqlite3_mutex_leave(pShmNode->mutex);
-+ OSTRACE(("SHM-LOCK shmid-%d, pid-%d got %03x,%03x\n",
-+ p->id, getpid(), p->sharedMask, p->exclMask));
- return rc;
- }
-
--#ifdef SQLITE_TEST
--/* simulate multiple hosts by creating unique hostid file paths */
--SQLITE_API int sqlite3_hostid_num = 0;
--#endif
-+/*
-+** Implement a memory barrier or memory fence on shared memory.
-+**
-+** All loads and stores begun before the barrier must complete before
-+** any load or store begun after the barrier.
-+*/
-+static void unixShmBarrier(
-+ sqlite3_file *fd /* Database file holding the shared memory */
-+){
-+ UNUSED_PARAMETER(fd);
-+ unixEnterMutex();
-+ unixLeaveMutex();
-+}
-
--#define PROXY_HOSTIDLEN 16 /* conch file host id length */
-+/*
-+** Close a connection to shared-memory. Delete the underlying
-+** storage if deleteFlag is true.
-+**
-+** If there is no shared memory associated with the connection then this
-+** routine is a harmless no-op.
-+*/
-+static int unixShmUnmap(
-+ sqlite3_file *fd, /* The underlying database file */
-+ int deleteFlag /* Delete shared-memory if true */
-+){
-+ unixShm *p; /* The connection to be closed */
-+ unixShmNode *pShmNode; /* The underlying shared-memory file */
-+ unixShm **pp; /* For looping over sibling connections */
-+ unixFile *pDbFd; /* The underlying database file */
-
--/* Not always defined in the headers as it ought to be */
--extern int gethostuuid(uuid_t id, const struct timespec *wait);
-+ pDbFd = (unixFile*)fd;
-+ p = pDbFd->pShm;
-+ if( p==0 ) return SQLITE_OK;
-+ pShmNode = p->pShmNode;
-
--/* get the host ID via gethostuuid(), pHostID must point to PROXY_HOSTIDLEN
--** bytes of writable memory.
--*/
--static int proxyGetHostID(unsigned char *pHostID, int *pError){
-- assert(PROXY_HOSTIDLEN == sizeof(uuid_t));
-- memset(pHostID, 0, PROXY_HOSTIDLEN);
--#if defined(__MAX_OS_X_VERSION_MIN_REQUIRED)\
-- && __MAC_OS_X_VERSION_MIN_REQUIRED<1050
-- {
-- static const struct timespec timeout = {1, 0}; /* 1 sec timeout */
-- if( gethostuuid(pHostID, &timeout) ){
-- int err = errno;
-- if( pError ){
-- *pError = err;
-- }
-- return SQLITE_IOERR;
-- }
-+ assert( pShmNode==pDbFd->pInode->pShmNode );
-+ assert( pShmNode->pInode==pDbFd->pInode );
-+
-+ /* Remove connection p from the set of connections associated
-+ ** with pShmNode */
-+ sqlite3_mutex_enter(pShmNode->mutex);
-+ for(pp=&pShmNode->pFirst; (*pp)!=p; pp = &(*pp)->pNext){}
-+ *pp = p->pNext;
-+
-+ /* Free the connection p */
-+ sqlite3_free(p);
-+ pDbFd->pShm = 0;
-+ sqlite3_mutex_leave(pShmNode->mutex);
-+
-+ /* If pShmNode->nRef has reached 0, then close the underlying
-+ ** shared-memory file, too */
-+ unixEnterMutex();
-+ assert( pShmNode->nRef>0 );
-+ pShmNode->nRef--;
-+ if( pShmNode->nRef==0 ){
-+ if( deleteFlag && pShmNode->h>=0 ) osUnlink(pShmNode->zFilename);
-+ unixShmPurge(pDbFd);
- }
-+ unixLeaveMutex();
-+
-+ return SQLITE_OK;
-+}
-+
-+
- #else
-- UNUSED_PARAMETER(pError);
--#endif
--#ifdef SQLITE_TEST
-- /* simulate multiple hosts by creating unique hostid file paths */
-- if( sqlite3_hostid_num != 0){
-- pHostID[0] = (char)(pHostID[0] + (char)(sqlite3_hostid_num & 0xFF));
-+# define unixShmMap 0
-+# define unixShmLock 0
-+# define unixShmBarrier 0
-+# define unixShmUnmap 0
-+#endif /* #ifndef SQLITE_OMIT_WAL */
-+
-+/*
-+** If it is currently memory mapped, unmap file pFd.
-+*/
-+static void unixUnmapfile(unixFile *pFd){
-+ assert( pFd->nFetchOut==0 );
-+#if SQLITE_MAX_MMAP_SIZE>0
-+ if( pFd->pMapRegion ){
-+ osMunmap(pFd->pMapRegion, pFd->mmapSizeActual);
-+ pFd->pMapRegion = 0;
-+ pFd->mmapSize = 0;
-+ pFd->mmapSizeActual = 0;
- }
- #endif
--
-- return SQLITE_OK;
- }
-
--/* The conch file contains the header, host id and lock file path
-- */
--#define PROXY_CONCHVERSION 2 /* 1-byte header, 16-byte host id, path */
--#define PROXY_HEADERLEN 1 /* conch file header length */
--#define PROXY_PATHINDEX (PROXY_HEADERLEN+PROXY_HOSTIDLEN)
--#define PROXY_MAXCONCHLEN (PROXY_HEADERLEN+PROXY_HOSTIDLEN+MAXPATHLEN)
-+#if SQLITE_MAX_MMAP_SIZE>0
-+/*
-+** Return the system page size.
-+*/
-+static int unixGetPagesize(void){
-+#if HAVE_MREMAP
-+ return 512;
-+#elif defined(_BSD_SOURCE)
-+ return getpagesize();
-+#else
-+ return (int)sysconf(_SC_PAGESIZE);
-+#endif
-+}
-+#endif /* SQLITE_MAX_MMAP_SIZE>0 */
-
--/*
--** Takes an open conch file, copies the contents to a new path and then moves
--** it back. The newly created file's file descriptor is assigned to the
--** conch file structure and finally the original conch file descriptor is
--** closed. Returns zero if successful.
-+#if SQLITE_MAX_MMAP_SIZE>0
-+/*
-+** Attempt to set the size of the memory mapping maintained by file
-+** descriptor pFd to nNew bytes. Any existing mapping is discarded.
-+**
-+** If successful, this function sets the following variables:
-+**
-+** unixFile.pMapRegion
-+** unixFile.mmapSize
-+** unixFile.mmapSizeActual
-+**
-+** If unsuccessful, an error message is logged via sqlite3_log() and
-+** the three variables above are zeroed. In this case SQLite should
-+** continue accessing the database using the xRead() and xWrite()
-+** methods.
- */
--static int proxyBreakConchLock(unixFile *pFile, uuid_t myHostID){
-- proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext;
-- unixFile *conchFile = pCtx->conchFile;
-- char tPath[MAXPATHLEN];
-- char buf[PROXY_MAXCONCHLEN];
-- char *cPath = pCtx->conchFilePath;
-- size_t readLen = 0;
-- size_t pathLen = 0;
-- char errmsg[64] = "";
-- int fd = -1;
-- int rc = -1;
-- UNUSED_PARAMETER(myHostID);
-+static void unixRemapfile(
-+ unixFile *pFd, /* File descriptor object */
-+ i64 nNew /* Required mapping size */
-+){
-+ const char *zErr = "mmap";
-+ int h = pFd->h; /* File descriptor open on db file */
-+ u8 *pOrig = (u8 *)pFd->pMapRegion; /* Pointer to current file mapping */
-+ i64 nOrig = pFd->mmapSizeActual; /* Size of pOrig region in bytes */
-+ u8 *pNew = 0; /* Location of new mapping */
-+ int flags = PROT_READ; /* Flags to pass to mmap() */
-
-- /* create a new path by replace the trailing '-conch' with '-break' */
-- pathLen = strlcpy(tPath, cPath, MAXPATHLEN);
-- if( pathLen>MAXPATHLEN || pathLen<6 ||
-- (strlcpy(&tPath[pathLen-5], "break", 6) != 5) ){
-- sqlite3_snprintf(sizeof(errmsg),errmsg,"path error (len %d)",(int)pathLen);
-- goto end_breaklock;
-- }
-- /* read the conch content */
-- readLen = osPread(conchFile->h, buf, PROXY_MAXCONCHLEN, 0);
-- if( readLen<PROXY_PATHINDEX ){
-- sqlite3_snprintf(sizeof(errmsg),errmsg,"read error (len %d)",(int)readLen);
-- goto end_breaklock;
-- }
-- /* write it out to the temporary break file */
-- fd = robust_open(tPath, (O_RDWR|O_CREAT|O_EXCL), 0);
-- if( fd<0 ){
-- sqlite3_snprintf(sizeof(errmsg), errmsg, "create failed (%d)", errno);
-- goto end_breaklock;
-- }
-- if( osPwrite(fd, buf, readLen, 0) != (ssize_t)readLen ){
-- sqlite3_snprintf(sizeof(errmsg), errmsg, "write failed (%d)", errno);
-- goto end_breaklock;
-- }
-- if( rename(tPath, cPath) ){
-- sqlite3_snprintf(sizeof(errmsg), errmsg, "rename failed (%d)", errno);
-- goto end_breaklock;
-- }
-- rc = 0;
-- fprintf(stderr, "broke stale lock on %s\n", cPath);
-- robust_close(pFile, conchFile->h, __LINE__);
-- conchFile->h = fd;
-- conchFile->openFlags = O_RDWR | O_CREAT;
-+ assert( pFd->nFetchOut==0 );
-+ assert( nNew>pFd->mmapSize );
-+ assert( nNew<=pFd->mmapSizeMax );
-+ assert( nNew>0 );
-+ assert( pFd->mmapSizeActual>=pFd->mmapSize );
-+ assert( MAP_FAILED!=0 );
-
--end_breaklock:
-- if( rc ){
-- if( fd>=0 ){
-- osUnlink(tPath);
-- robust_close(pFile, fd, __LINE__);
-+ if( (pFd->ctrlFlags & UNIXFILE_RDONLY)==0 ) flags |= PROT_WRITE;
-+
-+ if( pOrig ){
-+ const int szSyspage = unixGetPagesize();
-+ i64 nReuse = (pFd->mmapSize & ~(szSyspage-1));
-+ u8 *pReq = &pOrig[nReuse];
-+
-+ /* Unmap any pages of the existing mapping that cannot be reused. */
-+ if( nReuse!=nOrig ){
-+ osMunmap(pReq, nOrig-nReuse);
- }
-- fprintf(stderr, "failed to break stale lock on %s, %s\n", cPath, errmsg);
-- }
-- return rc;
--}
-
--/* Take the requested lock on the conch file and break a stale lock if the
--** host id matches.
--*/
--static int proxyConchLock(unixFile *pFile, uuid_t myHostID, int lockType){
-- proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext;
-- unixFile *conchFile = pCtx->conchFile;
-- int rc = SQLITE_OK;
-- int nTries = 0;
-- struct timespec conchModTime;
--
-- memset(&conchModTime, 0, sizeof(conchModTime));
-- do {
-- rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, lockType);
-- nTries ++;
-- if( rc==SQLITE_BUSY ){
-- /* If the lock failed (busy):
-- * 1st try: get the mod time of the conch, wait 0.5s and try again.
-- * 2nd try: fail if the mod time changed or host id is different, wait
-- * 10 sec and try again
-- * 3rd try: break the lock unless the mod time has changed.
-- */
-- struct stat buf;
-- if( osFstat(conchFile->h, &buf) ){
-- pFile->lastErrno = errno;
-- return SQLITE_IOERR_LOCK;
-- }
--
-- if( nTries==1 ){
-- conchModTime = buf.st_mtimespec;
-- usleep(500000); /* wait 0.5 sec and try the lock again*/
-- continue;
-+#if HAVE_MREMAP
-+ pNew = osMremap(pOrig, nReuse, nNew, MREMAP_MAYMOVE);
-+ zErr = "mremap";
-+#else
-+ pNew = osMmap(pReq, nNew-nReuse, flags, MAP_SHARED, h, nReuse);
-+ if( pNew!=MAP_FAILED ){
-+ if( pNew!=pReq ){
-+ osMunmap(pNew, nNew - nReuse);
-+ pNew = 0;
-+ }else{
-+ pNew = pOrig;
- }
-+ }
-+#endif
-
-- assert( nTries>1 );
-- if( conchModTime.tv_sec != buf.st_mtimespec.tv_sec ||
-- conchModTime.tv_nsec != buf.st_mtimespec.tv_nsec ){
-- return SQLITE_BUSY;
-- }
--
-- if( nTries==2 ){
-- char tBuf[PROXY_MAXCONCHLEN];
-- int len = osPread(conchFile->h, tBuf, PROXY_MAXCONCHLEN, 0);
-- if( len<0 ){
-- pFile->lastErrno = errno;
-- return SQLITE_IOERR_LOCK;
-- }
-- if( len>PROXY_PATHINDEX && tBuf[0]==(char)PROXY_CONCHVERSION){
-- /* don't break the lock if the host id doesn't match */
-- if( 0!=memcmp(&tBuf[PROXY_HEADERLEN], myHostID, PROXY_HOSTIDLEN) ){
-- return SQLITE_BUSY;
-- }
-- }else{
-- /* don't break the lock on short read or a version mismatch */
-- return SQLITE_BUSY;
-- }
-- usleep(10000000); /* wait 10 sec and try the lock again */
-- continue;
-- }
--
-- assert( nTries==3 );
-- if( 0==proxyBreakConchLock(pFile, myHostID) ){
-- rc = SQLITE_OK;
-- if( lockType==EXCLUSIVE_LOCK ){
-- rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, SHARED_LOCK);
-- }
-- if( !rc ){
-- rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, lockType);
-- }
-- }
-+ /* The attempt to extend the existing mapping failed. Free it. */
-+ if( pNew==MAP_FAILED || pNew==0 ){
-+ osMunmap(pOrig, nReuse);
- }
-- } while( rc==SQLITE_BUSY && nTries<3 );
--
-- return rc;
-+ }
-+
-+ /* If pNew is still NULL, try to create an entirely new mapping. */
-+ if( pNew==0 ){
-+ pNew = osMmap(0, nNew, flags, MAP_SHARED, h, 0);
-+ }
-+
-+ if( pNew==MAP_FAILED ){
-+ pNew = 0;
-+ nNew = 0;
-+ unixLogError(SQLITE_OK, zErr, pFd->zPath);
-+
-+ /* If the mmap() above failed, assume that all subsequent mmap() calls
-+ ** will probably fail too. Fall back to using xRead/xWrite exclusively
-+ ** in this case. */
-+ pFd->mmapSizeMax = 0;
-+ }
-+ pFd->pMapRegion = (void *)pNew;
-+ pFd->mmapSize = pFd->mmapSizeActual = nNew;
- }
-+#endif
-
--/* Takes the conch by taking a shared lock and read the contents conch, if
--** lockPath is non-NULL, the host ID and lock file path must match. A NULL
--** lockPath means that the lockPath in the conch file will be used if the
--** host IDs match, or a new lock path will be generated automatically
--** and written to the conch file.
-+/*
-+** Memory map or remap the file opened by file-descriptor pFd (if the file
-+** is already mapped, the existing mapping is replaced by the new). Or, if
-+** there already exists a mapping for this file, and there are still
-+** outstanding xFetch() references to it, this function is a no-op.
-+**
-+** If parameter nByte is non-negative, then it is the requested size of
-+** the mapping to create. Otherwise, if nByte is less than zero, then the
-+** requested size is the size of the file on disk. The actual size of the
-+** created mapping is either the requested size or the value configured
-+** using SQLITE_FCNTL_MMAP_LIMIT, whichever is smaller.
-+**
-+** SQLITE_OK is returned if no error occurs (even if the mapping is not
-+** recreated as a result of outstanding references) or an SQLite error
-+** code otherwise.
- */
--static int proxyTakeConch(unixFile *pFile){
-- proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext;
--
-- if( pCtx->conchHeld!=0 ){
-- return SQLITE_OK;
-- }else{
-- unixFile *conchFile = pCtx->conchFile;
-- uuid_t myHostID;
-- int pError = 0;
-- char readBuf[PROXY_MAXCONCHLEN];
-- char lockPath[MAXPATHLEN];
-- char *tempLockPath = NULL;
-- int rc = SQLITE_OK;
-- int createConch = 0;
-- int hostIdMatch = 0;
-- int readLen = 0;
-- int tryOldLockPath = 0;
-- int forceNewLockPath = 0;
--
-- OSTRACE(("TAKECONCH %d for %s pid=%d\n", conchFile->h,
-- (pCtx->lockProxyPath ? pCtx->lockProxyPath : ":auto:"), getpid()));
--
-- rc = proxyGetHostID(myHostID, &pError);
-- if( (rc&0xff)==SQLITE_IOERR ){
-- pFile->lastErrno = pError;
-- goto end_takeconch;
-- }
-- rc = proxyConchLock(pFile, myHostID, SHARED_LOCK);
-+static int unixMapfile(unixFile *pFd, i64 nByte){
-+#if SQLITE_MAX_MMAP_SIZE>0
-+ i64 nMap = nByte;
-+ int rc;
-+
-+ assert( nMap>=0 || pFd->nFetchOut==0 );
-+ if( pFd->nFetchOut>0 ) return SQLITE_OK;
-+
-+ if( nMap<0 ){
-+ struct stat statbuf; /* Low-level file information */
-+ rc = osFstat(pFd->h, &statbuf);
- if( rc!=SQLITE_OK ){
-- goto end_takeconch;
-+ return SQLITE_IOERR_FSTAT;
- }
-- /* read the existing conch file */
-- readLen = seekAndRead((unixFile*)conchFile, 0, readBuf, PROXY_MAXCONCHLEN);
-- if( readLen<0 ){
-- /* I/O error: lastErrno set by seekAndRead */
-- pFile->lastErrno = conchFile->lastErrno;
-- rc = SQLITE_IOERR_READ;
-- goto end_takeconch;
-- }else if( readLen<=(PROXY_HEADERLEN+PROXY_HOSTIDLEN) ||
-- readBuf[0]!=(char)PROXY_CONCHVERSION ){
-- /* a short read or version format mismatch means we need to create a new
-- ** conch file.
-- */
-- createConch = 1;
-+ nMap = statbuf.st_size;
-+ }
-+ if( nMap>pFd->mmapSizeMax ){
-+ nMap = pFd->mmapSizeMax;
-+ }
-+
-+ if( nMap!=pFd->mmapSize ){
-+ if( nMap>0 ){
-+ unixRemapfile(pFd, nMap);
-+ }else{
-+ unixUnmapfile(pFd);
- }
-- /* if the host id matches and the lock path already exists in the conch
-- ** we'll try to use the path there, if we can't open that path, we'll
-- ** retry with a new auto-generated path
-- */
-- do { /* in case we need to try again for an :auto: named lock file */
-+ }
-+#endif
-
-- if( !createConch && !forceNewLockPath ){
-- hostIdMatch = !memcmp(&readBuf[PROXY_HEADERLEN], myHostID,
-- PROXY_HOSTIDLEN);
-- /* if the conch has data compare the contents */
-- if( !pCtx->lockProxyPath ){
-- /* for auto-named local lock file, just check the host ID and we'll
-- ** use the local lock file path that's already in there
-- */
-- if( hostIdMatch ){
-- size_t pathLen = (readLen - PROXY_PATHINDEX);
--
-- if( pathLen>=MAXPATHLEN ){
-- pathLen=MAXPATHLEN-1;
-- }
-- memcpy(lockPath, &readBuf[PROXY_PATHINDEX], pathLen);
-- lockPath[pathLen] = 0;
-- tempLockPath = lockPath;
-- tryOldLockPath = 1;
-- /* create a copy of the lock path if the conch is taken */
-- goto end_takeconch;
-- }
-- }else if( hostIdMatch
-- && !strncmp(pCtx->lockProxyPath, &readBuf[PROXY_PATHINDEX],
-- readLen-PROXY_PATHINDEX)
-- ){
-- /* conch host and lock path match */
-- goto end_takeconch;
-- }
-- }
--
-- /* if the conch isn't writable and doesn't match, we can't take it */
-- if( (conchFile->openFlags&O_RDWR) == 0 ){
-- rc = SQLITE_BUSY;
-- goto end_takeconch;
-- }
--
-- /* either the conch didn't match or we need to create a new one */
-- if( !pCtx->lockProxyPath ){
-- proxyGetLockPath(pCtx->dbPath, lockPath, MAXPATHLEN);
-- tempLockPath = lockPath;
-- /* create a copy of the lock path _only_ if the conch is taken */
-- }
--
-- /* update conch with host and path (this will fail if other process
-- ** has a shared lock already), if the host id matches, use the big
-- ** stick.
-- */
-- futimes(conchFile->h, NULL);
-- if( hostIdMatch && !createConch ){
-- if( conchFile->pInode && conchFile->pInode->nShared>1 ){
-- /* We are trying for an exclusive lock but another thread in this
-- ** same process is still holding a shared lock. */
-- rc = SQLITE_BUSY;
-- } else {
-- rc = proxyConchLock(pFile, myHostID, EXCLUSIVE_LOCK);
-- }
-- }else{
-- rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, EXCLUSIVE_LOCK);
-- }
-- if( rc==SQLITE_OK ){
-- char writeBuffer[PROXY_MAXCONCHLEN];
-- int writeSize = 0;
--
-- writeBuffer[0] = (char)PROXY_CONCHVERSION;
-- memcpy(&writeBuffer[PROXY_HEADERLEN], myHostID, PROXY_HOSTIDLEN);
-- if( pCtx->lockProxyPath!=NULL ){
-- strlcpy(&writeBuffer[PROXY_PATHINDEX], pCtx->lockProxyPath, MAXPATHLEN);
-- }else{
-- strlcpy(&writeBuffer[PROXY_PATHINDEX], tempLockPath, MAXPATHLEN);
-- }
-- writeSize = PROXY_PATHINDEX + strlen(&writeBuffer[PROXY_PATHINDEX]);
-- robust_ftruncate(conchFile->h, writeSize);
-- rc = unixWrite((sqlite3_file *)conchFile, writeBuffer, writeSize, 0);
-- fsync(conchFile->h);
-- /* If we created a new conch file (not just updated the contents of a
-- ** valid conch file), try to match the permissions of the database
-- */
-- if( rc==SQLITE_OK && createConch ){
-- struct stat buf;
-- int err = osFstat(pFile->h, &buf);
-- if( err==0 ){
-- mode_t cmode = buf.st_mode&(S_IRUSR|S_IWUSR | S_IRGRP|S_IWGRP |
-- S_IROTH|S_IWOTH);
-- /* try to match the database file R/W permissions, ignore failure */
--#ifndef SQLITE_PROXY_DEBUG
-- osFchmod(conchFile->h, cmode);
--#else
-- do{
-- rc = osFchmod(conchFile->h, cmode);
-- }while( rc==(-1) && errno==EINTR );
-- if( rc!=0 ){
-- int code = errno;
-- fprintf(stderr, "fchmod %o FAILED with %d %s\n",
-- cmode, code, strerror(code));
-- } else {
-- fprintf(stderr, "fchmod %o SUCCEDED\n",cmode);
-- }
-- }else{
-- int code = errno;
-- fprintf(stderr, "STAT FAILED[%d] with %d %s\n",
-- err, code, strerror(code));
-+ return SQLITE_OK;
-+}
-+
-+/*
-+** If possible, return a pointer to a mapping of file fd starting at offset
-+** iOff. The mapping must be valid for at least nAmt bytes.
-+**
-+** If such a pointer can be obtained, store it in *pp and return SQLITE_OK.
-+** Or, if one cannot but no error occurs, set *pp to 0 and return SQLITE_OK.
-+** Finally, if an error does occur, return an SQLite error code. The final
-+** value of *pp is undefined in this case.
-+**
-+** If this function does return a pointer, the caller must eventually
-+** release the reference by calling unixUnfetch().
-+*/
-+static int unixFetch(sqlite3_file *fd, i64 iOff, int nAmt, void **pp){
-+#if SQLITE_MAX_MMAP_SIZE>0
-+ unixFile *pFd = (unixFile *)fd; /* The underlying database file */
- #endif
-- }
-- }
-- }
-- conchFile->pMethod->xUnlock((sqlite3_file*)conchFile, SHARED_LOCK);
--
-- end_takeconch:
-- OSTRACE(("TRANSPROXY: CLOSE %d\n", pFile->h));
-- if( rc==SQLITE_OK && pFile->openFlags ){
-- int fd;
-- if( pFile->h>=0 ){
-- robust_close(pFile, pFile->h, __LINE__);
-- }
-- pFile->h = -1;
-- fd = robust_open(pCtx->dbPath, pFile->openFlags, 0);
-- OSTRACE(("TRANSPROXY: OPEN %d\n", fd));
-- if( fd>=0 ){
-- pFile->h = fd;
-- }else{
-- rc=SQLITE_CANTOPEN_BKPT; /* SQLITE_BUSY? proxyTakeConch called
-- during locking */
-- }
-- }
-- if( rc==SQLITE_OK && !pCtx->lockProxy ){
-- char *path = tempLockPath ? tempLockPath : pCtx->lockProxyPath;
-- rc = proxyCreateUnixFile(path, &pCtx->lockProxy, 1);
-- if( rc!=SQLITE_OK && rc!=SQLITE_NOMEM && tryOldLockPath ){
-- /* we couldn't create the proxy lock file with the old lock file path
-- ** so try again via auto-naming
-- */
-- forceNewLockPath = 1;
-- tryOldLockPath = 0;
-- continue; /* go back to the do {} while start point, try again */
-- }
-- }
-- if( rc==SQLITE_OK ){
-- /* Need to make a copy of path if we extracted the value
-- ** from the conch file or the path was allocated on the stack
-- */
-- if( tempLockPath ){
-- pCtx->lockProxyPath = sqlite3DbStrDup(0, tempLockPath);
-- if( !pCtx->lockProxyPath ){
-- rc = SQLITE_NOMEM;
-- }
-- }
-- }
-- if( rc==SQLITE_OK ){
-- pCtx->conchHeld = 1;
--
-- if( pCtx->lockProxy->pMethod == &afpIoMethods ){
-- afpLockingContext *afpCtx;
-- afpCtx = (afpLockingContext *)pCtx->lockProxy->lockingContext;
-- afpCtx->dbPath = pCtx->lockProxyPath;
-- }
-- } else {
-- conchFile->pMethod->xUnlock((sqlite3_file*)conchFile, NO_LOCK);
-- }
-- OSTRACE(("TAKECONCH %d %s\n", conchFile->h,
-- rc==SQLITE_OK?"ok":"failed"));
-- return rc;
-- } while (1); /* in case we need to retry the :auto: lock file -
-- ** we should never get here except via the 'continue' call. */
-+ *pp = 0;
-+
-+#if SQLITE_MAX_MMAP_SIZE>0
-+ if( pFd->mmapSizeMax>0 ){
-+ if( pFd->pMapRegion==0 ){
-+ int rc = unixMapfile(pFd, -1);
-+ if( rc!=SQLITE_OK ) return rc;
-+ }
-+ if( pFd->mmapSize >= iOff+nAmt ){
-+ *pp = &((u8 *)pFd->pMapRegion)[iOff];
-+ pFd->nFetchOut++;
-+ }
- }
-+#endif
-+ return SQLITE_OK;
- }
-
- /*
--** If pFile holds a lock on a conch file, then release that lock.
-+** If the third argument is non-NULL, then this function releases a
-+** reference obtained by an earlier call to unixFetch(). The second
-+** argument passed to this function must be the same as the corresponding
-+** argument that was passed to the unixFetch() invocation.
-+**
-+** Or, if the third argument is NULL, then this function is being called
-+** to inform the VFS layer that, according to POSIX, any existing mapping
-+** may now be invalid and should be unmapped.
- */
--static int proxyReleaseConch(unixFile *pFile){
-- int rc = SQLITE_OK; /* Subroutine return code */
-- proxyLockingContext *pCtx; /* The locking context for the proxy lock */
-- unixFile *conchFile; /* Name of the conch file */
-+static int unixUnfetch(sqlite3_file *fd, i64 iOff, void *p){
-+ unixFile *pFd = (unixFile *)fd; /* The underlying database file */
-+ UNUSED_PARAMETER(iOff);
-
-- pCtx = (proxyLockingContext *)pFile->lockingContext;
-- conchFile = pCtx->conchFile;
-- OSTRACE(("RELEASECONCH %d for %s pid=%d\n", conchFile->h,
-- (pCtx->lockProxyPath ? pCtx->lockProxyPath : ":auto:"),
-- getpid()));
-- if( pCtx->conchHeld>0 ){
-- rc = conchFile->pMethod->xUnlock((sqlite3_file*)conchFile, NO_LOCK);
-+ /* If p==0 (unmap the entire file) then there must be no outstanding
-+ ** xFetch references. Or, if p!=0 (meaning it is an xFetch reference),
-+ ** then there must be at least one outstanding. */
-+ assert( (p==0)==(pFd->nFetchOut==0) );
-+
-+ /* If p!=0, it must match the iOff value. */
-+ assert( p==0 || p==&((u8 *)pFd->pMapRegion)[iOff] );
-+
-+ if( p ){
-+ pFd->nFetchOut--;
-+ }else{
-+ unixUnmapfile(pFd);
- }
-- pCtx->conchHeld = 0;
-- OSTRACE(("RELEASECONCH %d %s\n", conchFile->h,
-- (rc==SQLITE_OK ? "ok" : "failed")));
-- return rc;
-+
-+ assert( pFd->nFetchOut>=0 );
-+ return SQLITE_OK;
- }
-
- /*
--** Given the name of a database file, compute the name of its conch file.
--** Store the conch filename in memory obtained from sqlite3_malloc().
--** Make *pConchPath point to the new name. Return SQLITE_OK on success
--** or SQLITE_NOMEM if unable to obtain memory.
-+** Here ends the implementation of all sqlite3_file methods.
- **
--** The caller is responsible for ensuring that the allocated memory
--** space is eventually freed.
-+********************** End sqlite3_file Methods *******************************
-+******************************************************************************/
-+
-+/*
-+** This division contains definitions of sqlite3_io_methods objects that
-+** implement various file locking strategies. It also contains definitions
-+** of "finder" functions. A finder-function is used to locate the appropriate
-+** sqlite3_io_methods object for a particular database file. The pAppData
-+** field of the sqlite3_vfs VFS objects are initialized to be pointers to
-+** the correct finder-function for that VFS.
- **
--** *pConchPath is set to NULL if a memory allocation error occurs.
-+** Most finder functions return a pointer to a fixed sqlite3_io_methods
-+** object. The only interesting finder-function is autolockIoFinder, which
-+** looks at the filesystem type and tries to guess the best locking
-+** strategy from that.
-+**
-+** For finder-funtion F, two objects are created:
-+**
-+** (1) The real finder-function named "FImpt()".
-+**
-+** (2) A constant pointer to this function named just "F".
-+**
-+**
-+** A pointer to the F pointer is used as the pAppData value for VFS
-+** objects. We have to do this instead of letting pAppData point
-+** directly at the finder-function since C90 rules prevent a void*
-+** from be cast into a function pointer.
-+**
-+**
-+** Each instance of this macro generates two objects:
-+**
-+** * A constant sqlite3_io_methods object call METHOD that has locking
-+** methods CLOSE, LOCK, UNLOCK, CKRESLOCK.
-+**
-+** * An I/O method finder function called FINDER that returns a pointer
-+** to the METHOD object in the previous bullet.
- */
--static int proxyCreateConchPathname(char *dbPath, char **pConchPath){
-- int i; /* Loop counter */
-- int len = (int)strlen(dbPath); /* Length of database filename - dbPath */
-- char *conchPath; /* buffer in which to construct conch name */
-+#define IOMETHODS(FINDER, METHOD, VERSION, CLOSE, LOCK, UNLOCK, CKLOCK) \
-+static const sqlite3_io_methods METHOD = { \
-+ VERSION, /* iVersion */ \
-+ CLOSE, /* xClose */ \
-+ unixRead, /* xRead */ \
-+ unixWrite, /* xWrite */ \
-+ unixTruncate, /* xTruncate */ \
-+ unixSync, /* xSync */ \
-+ unixFileSize, /* xFileSize */ \
-+ LOCK, /* xLock */ \
-+ UNLOCK, /* xUnlock */ \
-+ CKLOCK, /* xCheckReservedLock */ \
-+ unixFileControl, /* xFileControl */ \
-+ unixSectorSize, /* xSectorSize */ \
-+ unixDeviceCharacteristics, /* xDeviceCapabilities */ \
-+ unixShmMap, /* xShmMap */ \
-+ unixShmLock, /* xShmLock */ \
-+ unixShmBarrier, /* xShmBarrier */ \
-+ unixShmUnmap, /* xShmUnmap */ \
-+ unixFetch, /* xFetch */ \
-+ unixUnfetch, /* xUnfetch */ \
-+}; \
-+static const sqlite3_io_methods *FINDER##Impl(const char *z, unixFile *p){ \
-+ UNUSED_PARAMETER(z); UNUSED_PARAMETER(p); \
-+ return &METHOD; \
-+} \
-+static const sqlite3_io_methods *(*const FINDER)(const char*,unixFile *p) \
-+ = FINDER##Impl;
-
-- /* Allocate space for the conch filename and initialize the name to
-- ** the name of the original database file. */
-- *pConchPath = conchPath = (char *)sqlite3_malloc(len + 8);
-- if( conchPath==0 ){
-- return SQLITE_NOMEM;
-+/*
-+** Here are all of the sqlite3_io_methods objects for each of the
-+** locking strategies. Functions that return pointers to these methods
-+** are also created.
-+*/
-+IOMETHODS(
-+ posixIoFinder, /* Finder function name */
-+ posixIoMethods, /* sqlite3_io_methods object name */
-+ 3, /* shared memory and mmap are enabled */
-+ unixClose, /* xClose method */
-+ unixLock, /* xLock method */
-+ unixUnlock, /* xUnlock method */
-+ unixCheckReservedLock /* xCheckReservedLock method */
-+)
-+IOMETHODS(
-+ nolockIoFinder, /* Finder function name */
-+ nolockIoMethods, /* sqlite3_io_methods object name */
-+ 1, /* shared memory is disabled */
-+ nolockClose, /* xClose method */
-+ nolockLock, /* xLock method */
-+ nolockUnlock, /* xUnlock method */
-+ nolockCheckReservedLock /* xCheckReservedLock method */
-+)
-+IOMETHODS(
-+ dotlockIoFinder, /* Finder function name */
-+ dotlockIoMethods, /* sqlite3_io_methods object name */
-+ 1, /* shared memory is disabled */
-+ dotlockClose, /* xClose method */
-+ dotlockLock, /* xLock method */
-+ dotlockUnlock, /* xUnlock method */
-+ dotlockCheckReservedLock /* xCheckReservedLock method */
-+)
-+
-+#if SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORKS
-+IOMETHODS(
-+ flockIoFinder, /* Finder function name */
-+ flockIoMethods, /* sqlite3_io_methods object name */
-+ 1, /* shared memory is disabled */
-+ flockClose, /* xClose method */
-+ flockLock, /* xLock method */
-+ flockUnlock, /* xUnlock method */
-+ flockCheckReservedLock /* xCheckReservedLock method */
-+)
-+#endif
-+
-+#if OS_VXWORKS
-+IOMETHODS(
-+ semIoFinder, /* Finder function name */
-+ semIoMethods, /* sqlite3_io_methods object name */
-+ 1, /* shared memory is disabled */
-+ semClose, /* xClose method */
-+ semLock, /* xLock method */
-+ semUnlock, /* xUnlock method */
-+ semCheckReservedLock /* xCheckReservedLock method */
-+)
-+#endif
-+
-+#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
-+IOMETHODS(
-+ afpIoFinder, /* Finder function name */
-+ afpIoMethods, /* sqlite3_io_methods object name */
-+ 1, /* shared memory is disabled */
-+ afpClose, /* xClose method */
-+ afpLock, /* xLock method */
-+ afpUnlock, /* xUnlock method */
-+ afpCheckReservedLock /* xCheckReservedLock method */
-+)
-+#endif
-+
-+/*
-+** The proxy locking method is a "super-method" in the sense that it
-+** opens secondary file descriptors for the conch and lock files and
-+** it uses proxy, dot-file, AFP, and flock() locking methods on those
-+** secondary files. For this reason, the division that implements
-+** proxy locking is located much further down in the file. But we need
-+** to go ahead and define the sqlite3_io_methods and finder function
-+** for proxy locking here. So we forward declare the I/O methods.
-+*/
-+#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
-+static int proxyClose(sqlite3_file*);
-+static int proxyLock(sqlite3_file*, int);
-+static int proxyUnlock(sqlite3_file*, int);
-+static int proxyCheckReservedLock(sqlite3_file*, int*);
-+IOMETHODS(
-+ proxyIoFinder, /* Finder function name */
-+ proxyIoMethods, /* sqlite3_io_methods object name */
-+ 1, /* shared memory is disabled */
-+ proxyClose, /* xClose method */
-+ proxyLock, /* xLock method */
-+ proxyUnlock, /* xUnlock method */
-+ proxyCheckReservedLock /* xCheckReservedLock method */
-+)
-+#endif
-+
-+/* nfs lockd on OSX 10.3+ doesn't clear write locks when a read lock is set */
-+#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
-+IOMETHODS(
-+ nfsIoFinder, /* Finder function name */
-+ nfsIoMethods, /* sqlite3_io_methods object name */
-+ 1, /* shared memory is disabled */
-+ unixClose, /* xClose method */
-+ unixLock, /* xLock method */
-+ nfsUnlock, /* xUnlock method */
-+ unixCheckReservedLock /* xCheckReservedLock method */
-+)
-+#endif
-+
-+#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
-+/*
-+** This "finder" function attempts to determine the best locking strategy
-+** for the database file "filePath". It then returns the sqlite3_io_methods
-+** object that implements that strategy.
-+**
-+** This is for MacOSX only.
-+*/
-+static const sqlite3_io_methods *autolockIoFinderImpl(
-+ const char *filePath, /* name of the database file */
-+ unixFile *pNew /* open file object for the database file */
-+){
-+ static const struct Mapping {
-+ const char *zFilesystem; /* Filesystem type name */
-+ const sqlite3_io_methods *pMethods; /* Appropriate locking method */
-+ } aMap[] = {
-+ { "hfs", &posixIoMethods },
-+ { "ufs", &posixIoMethods },
-+ { "afpfs", &afpIoMethods },
-+ { "smbfs", &afpIoMethods },
-+ { "webdav", &nolockIoMethods },
-+ { 0, 0 }
-+ };
-+ int i;
-+ struct statfs fsInfo;
-+ struct flock lockInfo;
-+
-+ if( !filePath ){
-+ /* If filePath==NULL that means we are dealing with a transient file
-+ ** that does not need to be locked. */
-+ return &nolockIoMethods;
- }
-- memcpy(conchPath, dbPath, len+1);
--
-- /* now insert a "." before the last / character */
-- for( i=(len-1); i>=0; i-- ){
-- if( conchPath[i]=='/' ){
-- i++;
-- break;
-+ if( statfs(filePath, &fsInfo) != -1 ){
-+ if( fsInfo.f_flags & MNT_RDONLY ){
-+ return &nolockIoMethods;
-+ }
-+ for(i=0; aMap[i].zFilesystem; i++){
-+ if( strcmp(fsInfo.f_fstypename, aMap[i].zFilesystem)==0 ){
-+ return aMap[i].pMethods;
-+ }
- }
- }
-- conchPath[i]='.';
-- while ( i<len ){
-- conchPath[i+1]=dbPath[i];
-- i++;
-- }
--
-- /* append the "-conch" suffix to the file */
-- memcpy(&conchPath[i+1], "-conch", 7);
-- assert( (int)strlen(conchPath) == len+7 );
-
-- return SQLITE_OK;
-+ /* Default case. Handles, amongst others, "nfs".
-+ ** Test byte-range lock using fcntl(). If the call succeeds,
-+ ** assume that the file-system supports POSIX style locks.
-+ */
-+ lockInfo.l_len = 1;
-+ lockInfo.l_start = 0;
-+ lockInfo.l_whence = SEEK_SET;
-+ lockInfo.l_type = F_RDLCK;
-+ if( osFcntl(pNew->h, F_GETLK, &lockInfo)!=-1 ) {
-+ if( strcmp(fsInfo.f_fstypename, "nfs")==0 ){
-+ return &nfsIoMethods;
-+ } else {
-+ return &posixIoMethods;
-+ }
-+ }else{
-+ return &dotlockIoMethods;
-+ }
- }
-+static const sqlite3_io_methods
-+ *(*const autolockIoFinder)(const char*,unixFile*) = autolockIoFinderImpl;
-
-+#endif /* defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE */
-
--/* Takes a fully configured proxy locking-style unix file and switches
--** the local lock file path
-+#if OS_VXWORKS && SQLITE_ENABLE_LOCKING_STYLE
-+/*
-+** This "finder" function attempts to determine the best locking strategy
-+** for the database file "filePath". It then returns the sqlite3_io_methods
-+** object that implements that strategy.
-+**
-+** This is for VXWorks only.
- */
--static int switchLockProxyPath(unixFile *pFile, const char *path) {
-- proxyLockingContext *pCtx = (proxyLockingContext*)pFile->lockingContext;
-- char *oldPath = pCtx->lockProxyPath;
-- int rc = SQLITE_OK;
-+static const sqlite3_io_methods *autolockIoFinderImpl(
-+ const char *filePath, /* name of the database file */
-+ unixFile *pNew /* the open file object */
-+){
-+ struct flock lockInfo;
-
-- if( pFile->eFileLock!=NO_LOCK ){
-- return SQLITE_BUSY;
-- }
-+ if( !filePath ){
-+ /* If filePath==NULL that means we are dealing with a transient file
-+ ** that does not need to be locked. */
-+ return &nolockIoMethods;
-+ }
-
-- /* nothing to do if the path is NULL, :auto: or matches the existing path */
-- if( !path || path[0]=='\0' || !strcmp(path, ":auto:") ||
-- (oldPath && !strncmp(oldPath, path, MAXPATHLEN)) ){
-- return SQLITE_OK;
-+ /* Test if fcntl() is supported and use POSIX style locks.
-+ ** Otherwise fall back to the named semaphore method.
-+ */
-+ lockInfo.l_len = 1;
-+ lockInfo.l_start = 0;
-+ lockInfo.l_whence = SEEK_SET;
-+ lockInfo.l_type = F_RDLCK;
-+ if( osFcntl(pNew->h, F_GETLK, &lockInfo)!=-1 ) {
-+ return &posixIoMethods;
- }else{
-- unixFile *lockProxy = pCtx->lockProxy;
-- pCtx->lockProxy=NULL;
-- pCtx->conchHeld = 0;
-- if( lockProxy!=NULL ){
-- rc=lockProxy->pMethod->xClose((sqlite3_file *)lockProxy);
-- if( rc ) return rc;
-- sqlite3_free(lockProxy);
-- }
-- sqlite3_free(oldPath);
-- pCtx->lockProxyPath = sqlite3DbStrDup(0, path);
-+ return &semIoMethods;
- }
--
-- return rc;
- }
-+static const sqlite3_io_methods
-+ *(*const autolockIoFinder)(const char*,unixFile*) = autolockIoFinderImpl;
-+
-+#endif /* OS_VXWORKS && SQLITE_ENABLE_LOCKING_STYLE */
-
- /*
--** pFile is a file that has been opened by a prior xOpen call. dbPath
--** is a string buffer at least MAXPATHLEN+1 characters in size.
-+** An abstract type for a pointer to a IO method finder function:
-+*/
-+typedef const sqlite3_io_methods *(*finder_type)(const char*,unixFile*);
-+
-+
-+/****************************************************************************
-+**************************** sqlite3_vfs methods ****************************
- **
--** This routine find the filename associated with pFile and writes it
--** int dbPath.
-+** This division contains the implementation of methods on the
-+** sqlite3_vfs object.
- */
--static int proxyGetDbPathForUnixFile(unixFile *pFile, char *dbPath){
--#if defined(__APPLE__)
-- if( pFile->pMethod == &afpIoMethods ){
-- /* afp style keeps a reference to the db path in the filePath field
-- ** of the struct */
-- assert( (int)strlen((char*)pFile->lockingContext)<=MAXPATHLEN );
-- strlcpy(dbPath, ((afpLockingContext *)pFile->lockingContext)->dbPath, MAXPATHLEN);
-- } else
--#endif
-- if( pFile->pMethod == &dotlockIoMethods ){
-- /* dot lock style uses the locking context to store the dot lock
-- ** file path */
-- int len = strlen((char *)pFile->lockingContext) - strlen(DOTLOCK_SUFFIX);
-- memcpy(dbPath, (char *)pFile->lockingContext, len + 1);
-- }else{
-- /* all other styles use the locking context to store the db file path */
-- assert( strlen((char*)pFile->lockingContext)<=MAXPATHLEN );
-- strlcpy(dbPath, (char *)pFile->lockingContext, MAXPATHLEN);
-- }
-- return SQLITE_OK;
--}
-
- /*
--** Takes an already filled in unix file and alters it so all file locking
--** will be performed on the local proxy lock file. The following fields
--** are preserved in the locking context so that they can be restored and
--** the unix structure properly cleaned up at close time:
--** ->lockingContext
--** ->pMethod
-+** Initialize the contents of the unixFile structure pointed to by pId.
- */
--static int proxyTransformUnixFile(unixFile *pFile, const char *path) {
-- proxyLockingContext *pCtx;
-- char dbPath[MAXPATHLEN+1]; /* Name of the database file */
-- char *lockPath=NULL;
-+static int fillInUnixFile(
-+ sqlite3_vfs *pVfs, /* Pointer to vfs object */
-+ int h, /* Open file descriptor of file being opened */
-+ sqlite3_file *pId, /* Write to the unixFile structure here */
-+ const char *zFilename, /* Name of the file being opened */
-+ int ctrlFlags /* Zero or more UNIXFILE_* values */
-+){
-+ const sqlite3_io_methods *pLockingStyle;
-+ unixFile *pNew = (unixFile *)pId;
- int rc = SQLITE_OK;
--
-- if( pFile->eFileLock!=NO_LOCK ){
-- return SQLITE_BUSY;
-+
-+ assert( pNew->pInode==NULL );
-+
-+ /* Usually the path zFilename should not be a relative pathname. The
-+ ** exception is when opening the proxy "conch" file in builds that
-+ ** include the special Apple locking styles.
-+ */
-+#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
-+ assert( zFilename==0 || zFilename[0]=='/'
-+ || pVfs->pAppData==(void*)&autolockIoFinder );
-+#else
-+ assert( zFilename==0 || zFilename[0]=='/' );
-+#endif
-+
-+ /* No locking occurs in temporary files */
-+ assert( zFilename!=0 || (ctrlFlags & UNIXFILE_NOLOCK)!=0 );
-+
-+ OSTRACE(("OPEN %-3d %s\n", h, zFilename));
-+ pNew->h = h;
-+ pNew->pVfs = pVfs;
-+ pNew->zPath = zFilename;
-+ pNew->ctrlFlags = (u8)ctrlFlags;
-+ pNew->mmapSizeMax = sqlite3GlobalConfig.szMmap;
-+ if( sqlite3_uri_boolean(((ctrlFlags & UNIXFILE_URI) ? zFilename : 0),
-+ "psow", SQLITE_POWERSAFE_OVERWRITE) ){
-+ pNew->ctrlFlags |= UNIXFILE_PSOW;
- }
-- proxyGetDbPathForUnixFile(pFile, dbPath);
-- if( !path || path[0]=='\0' || !strcmp(path, ":auto:") ){
-- lockPath=NULL;
-- }else{
-- lockPath=(char *)path;
-+ if( strcmp(pVfs->zName,"unix-excl")==0 ){
-+ pNew->ctrlFlags |= UNIXFILE_EXCL;
- }
--
-- OSTRACE(("TRANSPROXY %d for %s pid=%d\n", pFile->h,
-- (lockPath ? lockPath : ":auto:"), getpid()));
-
-- pCtx = sqlite3_malloc( sizeof(*pCtx) );
-- if( pCtx==0 ){
-- return SQLITE_NOMEM;
-+#if OS_VXWORKS
-+ pNew->pId = vxworksFindFileId(zFilename);
-+ if( pNew->pId==0 ){
-+ ctrlFlags |= UNIXFILE_NOLOCK;
-+ rc = SQLITE_NOMEM;
- }
-- memset(pCtx, 0, sizeof(*pCtx));
-+#endif
-
-- rc = proxyCreateConchPathname(dbPath, &pCtx->conchFilePath);
-- if( rc==SQLITE_OK ){
-- rc = proxyCreateUnixFile(pCtx->conchFilePath, &pCtx->conchFile, 0);
-- if( rc==SQLITE_CANTOPEN && ((pFile->openFlags&O_RDWR) == 0) ){
-- /* if (a) the open flags are not O_RDWR, (b) the conch isn't there, and
-- ** (c) the file system is read-only, then enable no-locking access.
-- ** Ugh, since O_RDONLY==0x0000 we test for !O_RDWR since unixOpen asserts
-- ** that openFlags will have only one of O_RDONLY or O_RDWR.
-+ if( ctrlFlags & UNIXFILE_NOLOCK ){
-+ pLockingStyle = &nolockIoMethods;
-+ }else{
-+ pLockingStyle = (**(finder_type*)pVfs->pAppData)(zFilename, pNew);
-+#if SQLITE_ENABLE_LOCKING_STYLE
-+ /* Cache zFilename in the locking context (AFP and dotlock override) for
-+ ** proxyLock activation is possible (remote proxy is based on db name)
-+ ** zFilename remains valid until file is closed, to support */
-+ pNew->lockingContext = (void*)zFilename;
-+#endif
-+ }
-+
-+ if( pLockingStyle == &posixIoMethods
-+#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
-+ || pLockingStyle == &nfsIoMethods
-+#endif
-+ ){
-+ unixEnterMutex();
-+ rc = findInodeInfo(pNew, &pNew->pInode);
-+ if( rc!=SQLITE_OK ){
-+ /* If an error occurred in findInodeInfo(), close the file descriptor
-+ ** immediately, before releasing the mutex. findInodeInfo() may fail
-+ ** in two scenarios:
-+ **
-+ ** (a) A call to fstat() failed.
-+ ** (b) A malloc failed.
-+ **
-+ ** Scenario (b) may only occur if the process is holding no other
-+ ** file descriptors open on the same file. If there were other file
-+ ** descriptors on this file, then no malloc would be required by
-+ ** findInodeInfo(). If this is the case, it is quite safe to close
-+ ** handle h - as it is guaranteed that no posix locks will be released
-+ ** by doing so.
-+ **
-+ ** If scenario (a) caused the error then things are not so safe. The
-+ ** implicit assumption here is that if fstat() fails, things are in
-+ ** such bad shape that dropping a lock or two doesn't matter much.
- */
-- struct statfs fsInfo;
-- struct stat conchInfo;
-- int goLockless = 0;
-+ robust_close(pNew, h, __LINE__);
-+ h = -1;
-+ }
-+ unixLeaveMutex();
-+ }
-
-- if( osStat(pCtx->conchFilePath, &conchInfo) == -1 ) {
-- int err = errno;
-- if( (err==ENOENT) && (statfs(dbPath, &fsInfo) != -1) ){
-- goLockless = (fsInfo.f_flags&MNT_RDONLY) == MNT_RDONLY;
-- }
-- }
-- if( goLockless ){
-- pCtx->conchHeld = -1; /* read only FS/ lockless */
-- rc = SQLITE_OK;
-+#if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__)
-+ else if( pLockingStyle == &afpIoMethods ){
-+ /* AFP locking uses the file path so it needs to be included in
-+ ** the afpLockingContext.
-+ */
-+ afpLockingContext *pCtx;
-+ pNew->lockingContext = pCtx = sqlite3_malloc( sizeof(*pCtx) );
-+ if( pCtx==0 ){
-+ rc = SQLITE_NOMEM;
-+ }else{
-+ /* NB: zFilename exists and remains valid until the file is closed
-+ ** according to requirement F11141. So we do not need to make a
-+ ** copy of the filename. */
-+ pCtx->dbPath = zFilename;
-+ pCtx->reserved = 0;
-+ srandomdev();
-+ unixEnterMutex();
-+ rc = findInodeInfo(pNew, &pNew->pInode);
-+ if( rc!=SQLITE_OK ){
-+ sqlite3_free(pNew->lockingContext);
-+ robust_close(pNew, h, __LINE__);
-+ h = -1;
- }
-+ unixLeaveMutex();
- }
-- }
-- if( rc==SQLITE_OK && lockPath ){
-- pCtx->lockProxyPath = sqlite3DbStrDup(0, lockPath);
- }
-+#endif
-
-- if( rc==SQLITE_OK ){
-- pCtx->dbPath = sqlite3DbStrDup(0, dbPath);
-- if( pCtx->dbPath==NULL ){
-+ else if( pLockingStyle == &dotlockIoMethods ){
-+ /* Dotfile locking uses the file path so it needs to be included in
-+ ** the dotlockLockingContext
-+ */
-+ char *zLockFile;
-+ int nFilename;
-+ assert( zFilename!=0 );
-+ nFilename = (int)strlen(zFilename) + 6;
-+ zLockFile = (char *)sqlite3_malloc(nFilename);
-+ if( zLockFile==0 ){
- rc = SQLITE_NOMEM;
-+ }else{
-+ sqlite3_snprintf(nFilename, zLockFile, "%s" DOTLOCK_SUFFIX, zFilename);
- }
-+ pNew->lockingContext = zLockFile;
- }
-- if( rc==SQLITE_OK ){
-- /* all memory is allocated, proxys are created and assigned,
-- ** switch the locking context and pMethod then return.
-+
-+#if OS_VXWORKS
-+ else if( pLockingStyle == &semIoMethods ){
-+ /* Named semaphore locking uses the file path so it needs to be
-+ ** included in the semLockingContext
- */
-- pCtx->oldLockingContext = pFile->lockingContext;
-- pFile->lockingContext = pCtx;
-- pCtx->pOldMethod = pFile->pMethod;
-- pFile->pMethod = &proxyIoMethods;
-- }else{
-- if( pCtx->conchFile ){
-- pCtx->conchFile->pMethod->xClose((sqlite3_file *)pCtx->conchFile);
-- sqlite3_free(pCtx->conchFile);
-+ unixEnterMutex();
-+ rc = findInodeInfo(pNew, &pNew->pInode);
-+ if( (rc==SQLITE_OK) && (pNew->pInode->pSem==NULL) ){
-+ char *zSemName = pNew->pInode->aSemName;
-+ int n;
-+ sqlite3_snprintf(MAX_PATHNAME, zSemName, "/%s.sem",
-+ pNew->pId->zCanonicalName);
-+ for( n=1; zSemName[n]; n++ )
-+ if( zSemName[n]=='/' ) zSemName[n] = '_';
-+ pNew->pInode->pSem = sem_open(zSemName, O_CREAT, 0666, 1);
-+ if( pNew->pInode->pSem == SEM_FAILED ){
-+ rc = SQLITE_NOMEM;
-+ pNew->pInode->aSemName[0] = '\0';
-+ }
- }
-- sqlite3DbFree(0, pCtx->lockProxyPath);
-- sqlite3_free(pCtx->conchFilePath);
-- sqlite3_free(pCtx);
-+ unixLeaveMutex();
-+ }
-+#endif
-+
-+ pNew->lastErrno = 0;
-+#if OS_VXWORKS
-+ if( rc!=SQLITE_OK ){
-+ if( h>=0 ) robust_close(pNew, h, __LINE__);
-+ h = -1;
-+ osUnlink(zFilename);
-+ pNew->ctrlFlags |= UNIXFILE_DELETE;
-+ }
-+#endif
-+ if( rc!=SQLITE_OK ){
-+ if( h>=0 ) robust_close(pNew, h, __LINE__);
-+ }else{
-+ pNew->pMethod = pLockingStyle;
-+ OpenCounter(+1);
-+ verifyDbFile(pNew);
- }
-- OSTRACE(("TRANSPROXY %d %s\n", pFile->h,
-- (rc==SQLITE_OK ? "ok" : "failed")));
- return rc;
- }
-
-+/*
-+** Return the name of a directory in which to put temporary files.
-+** If no suitable temporary file directory can be found, return NULL.
-+*/
-+static const char *unixTempFileDir(void){
-+ static const char *azDirs[] = {
-+ 0,
-+ 0,
-+ "/var/tmp",
-+ "/usr/tmp",
-+ "/tmp",
-+ 0 /* List terminator */
-+ };
-+ unsigned int i;
-+ struct stat buf;
-+ const char *zDir = 0;
-+
-+ azDirs[0] = sqlite3_temp_directory;
-+ if( !azDirs[1] ) azDirs[1] = getenv("TMPDIR");
-+ for(i=0; i<sizeof(azDirs)/sizeof(azDirs[0]); zDir=azDirs[i++]){
-+ if( zDir==0 ) continue;
-+ if( osStat(zDir, &buf) ) continue;
-+ if( !S_ISDIR(buf.st_mode) ) continue;
-+ if( osAccess(zDir, 07) ) continue;
-+ break;
-+ }
-+ return zDir;
-+}
-
- /*
--** This routine handles sqlite3_file_control() calls that are specific
--** to proxy locking.
-+** Create a temporary file name in zBuf. zBuf must be allocated
-+** by the calling process and must be big enough to hold at least
-+** pVfs->mxPathname bytes.
- */
--static int proxyFileControl(sqlite3_file *id, int op, void *pArg){
-- switch( op ){
-- case SQLITE_GET_LOCKPROXYFILE: {
-- unixFile *pFile = (unixFile*)id;
-- if( pFile->pMethod == &proxyIoMethods ){
-- proxyLockingContext *pCtx = (proxyLockingContext*)pFile->lockingContext;
-- proxyTakeConch(pFile);
-- if( pCtx->lockProxyPath ){
-- *(const char **)pArg = pCtx->lockProxyPath;
-- }else{
-- *(const char **)pArg = ":auto: (not held)";
-- }
-- } else {
-- *(const char **)pArg = NULL;
-- }
-- return SQLITE_OK;
-+static int unixGetTempname(int nBuf, char *zBuf){
-+ static const unsigned char zChars[] =
-+ "abcdefghijklmnopqrstuvwxyz"
-+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
-+ "0123456789";
-+ unsigned int i, j;
-+ const char *zDir;
-+
-+ /* It's odd to simulate an io-error here, but really this is just
-+ ** using the io-error infrastructure to test that SQLite handles this
-+ ** function failing.
-+ */
-+ SimulateIOError( return SQLITE_IOERR );
-+
-+ zDir = unixTempFileDir();
-+ if( zDir==0 ) zDir = ".";
-+
-+ /* Check that the output buffer is large enough for the temporary file
-+ ** name. If it is not, return SQLITE_ERROR.
-+ */
-+ if( (strlen(zDir) + strlen(SQLITE_TEMP_FILE_PREFIX) + 18) >= (size_t)nBuf ){
-+ return SQLITE_ERROR;
-+ }
-+
-+ do{
-+ sqlite3_snprintf(nBuf-18, zBuf, "%s/"SQLITE_TEMP_FILE_PREFIX, zDir);
-+ j = (int)strlen(zBuf);
-+ sqlite3_randomness(15, &zBuf[j]);
-+ for(i=0; i<15; i++, j++){
-+ zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ];
- }
-- case SQLITE_SET_LOCKPROXYFILE: {
-- unixFile *pFile = (unixFile*)id;
-- int rc = SQLITE_OK;
-- int isProxyStyle = (pFile->pMethod == &proxyIoMethods);
-- if( pArg==NULL || (const char *)pArg==0 ){
-- if( isProxyStyle ){
-- /* turn off proxy locking - not supported */
-- rc = SQLITE_ERROR /*SQLITE_PROTOCOL? SQLITE_MISUSE?*/;
-- }else{
-- /* turn off proxy locking - already off - NOOP */
-- rc = SQLITE_OK;
-- }
-- }else{
-- const char *proxyPath = (const char *)pArg;
-- if( isProxyStyle ){
-- proxyLockingContext *pCtx =
-- (proxyLockingContext*)pFile->lockingContext;
-- if( !strcmp(pArg, ":auto:")
-- || (pCtx->lockProxyPath &&
-- !strncmp(pCtx->lockProxyPath, proxyPath, MAXPATHLEN))
-- ){
-- rc = SQLITE_OK;
-- }else{
-- rc = switchLockProxyPath(pFile, proxyPath);
-- }
-- }else{
-- /* turn on proxy file locking */
-- rc = proxyTransformUnixFile(pFile, proxyPath);
-- }
-- }
-- return rc;
-+ zBuf[j] = 0;
-+ zBuf[j+1] = 0;
-+ }while( osAccess(zBuf,0)==0 );
-+ return SQLITE_OK;
-+}
-+
-+#if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__)
-+/*
-+** Routine to transform a unixFile into a proxy-locking unixFile.
-+** Implementation in the proxy-lock division, but used by unixOpen()
-+** if SQLITE_PREFER_PROXY_LOCKING is defined.
-+*/
-+static int proxyTransformUnixFile(unixFile*, const char*);
-+#endif
-+
-+/*
-+** Search for an unused file descriptor that was opened on the database
-+** file (not a journal or master-journal file) identified by pathname
-+** zPath with SQLITE_OPEN_XXX flags matching those passed as the second
-+** argument to this function.
-+**
-+** Such a file descriptor may exist if a database connection was closed
-+** but the associated file descriptor could not be closed because some
-+** other file descriptor open on the same file is holding a file-lock.
-+** Refer to comments in the unixClose() function and the lengthy comment
-+** describing "Posix Advisory Locking" at the start of this file for
-+** further details. Also, ticket #4018.
-+**
-+** If a suitable file descriptor is found, then it is returned. If no
-+** such file descriptor is located, -1 is returned.
-+*/
-+static UnixUnusedFd *findReusableFd(const char *zPath, int flags){
-+ UnixUnusedFd *pUnused = 0;
-+
-+ /* Do not search for an unused file descriptor on vxworks. Not because
-+ ** vxworks would not benefit from the change (it might, we're not sure),
-+ ** but because no way to test it is currently available. It is better
-+ ** not to risk breaking vxworks support for the sake of such an obscure
-+ ** feature. */
-+#if !OS_VXWORKS
-+ struct stat sStat; /* Results of stat() call */
-+
-+ /* A stat() call may fail for various reasons. If this happens, it is
-+ ** almost certain that an open() call on the same path will also fail.
-+ ** For this reason, if an error occurs in the stat() call here, it is
-+ ** ignored and -1 is returned. The caller will try to open a new file
-+ ** descriptor on the same path, fail, and return an error to SQLite.
-+ **
-+ ** Even if a subsequent open() call does succeed, the consequences of
-+ ** not searching for a resusable file descriptor are not dire. */
-+ if( 0==osStat(zPath, &sStat) ){
-+ unixInodeInfo *pInode;
-+
-+ unixEnterMutex();
-+ pInode = inodeList;
-+ while( pInode && (pInode->fileId.dev!=sStat.st_dev
-+ || pInode->fileId.ino!=sStat.st_ino) ){
-+ pInode = pInode->pNext;
- }
-- default: {
-- assert( 0 ); /* The call assures that only valid opcodes are sent */
-+ if( pInode ){
-+ UnixUnusedFd **pp;
-+ for(pp=&pInode->pUnused; *pp && (*pp)->flags!=flags; pp=&((*pp)->pNext));
-+ pUnused = *pp;
-+ if( pUnused ){
-+ *pp = pUnused->pNext;
-+ }
- }
-+ unixLeaveMutex();
- }
-- /*NOTREACHED*/
-- return SQLITE_ERROR;
-+#endif /* if !OS_VXWORKS */
-+ return pUnused;
- }
-
- /*
--** Within this division (the proxying locking implementation) the procedures
--** above this point are all utilities. The lock-related methods of the
--** proxy-locking sqlite3_io_method object follow.
-+** This function is called by unixOpen() to determine the unix permissions
-+** to create new files with. If no error occurs, then SQLITE_OK is returned
-+** and a value suitable for passing as the third argument to open(2) is
-+** written to *pMode. If an IO error occurs, an SQLite error code is
-+** returned and the value of *pMode is not modified.
-+**
-+** In most cases cases, this routine sets *pMode to 0, which will become
-+** an indication to robust_open() to create the file using
-+** SQLITE_DEFAULT_FILE_PERMISSIONS adjusted by the umask.
-+** But if the file being opened is a WAL or regular journal file, then
-+** this function queries the file-system for the permissions on the
-+** corresponding database file and sets *pMode to this value. Whenever
-+** possible, WAL and journal files are created using the same permissions
-+** as the associated database file.
-+**
-+** If the SQLITE_ENABLE_8_3_NAMES option is enabled, then the
-+** original filename is unavailable. But 8_3_NAMES is only used for
-+** FAT filesystems and permissions do not matter there, so just use
-+** the default permissions.
- */
-+static int findCreateFileMode(
-+ const char *zPath, /* Path of file (possibly) being created */
-+ int flags, /* Flags passed as 4th argument to xOpen() */
-+ mode_t *pMode, /* OUT: Permissions to open file with */
-+ uid_t *pUid, /* OUT: uid to set on the file */
-+ gid_t *pGid /* OUT: gid to set on the file */
-+){
-+ int rc = SQLITE_OK; /* Return Code */
-+ *pMode = 0;
-+ *pUid = 0;
-+ *pGid = 0;
-+ if( flags & (SQLITE_OPEN_WAL|SQLITE_OPEN_MAIN_JOURNAL) ){
-+ char zDb[MAX_PATHNAME+1]; /* Database file path */
-+ int nDb; /* Number of valid bytes in zDb */
-+ struct stat sStat; /* Output of stat() on database file */
-
-+ /* zPath is a path to a WAL or journal file. The following block derives
-+ ** the path to the associated database file from zPath. This block handles
-+ ** the following naming conventions:
-+ **
-+ ** "<path to db>-journal"
-+ ** "<path to db>-wal"
-+ ** "<path to db>-journalNN"
-+ ** "<path to db>-walNN"
-+ **
-+ ** where NN is a decimal number. The NN naming schemes are
-+ ** used by the test_multiplex.c module.
-+ */
-+ nDb = sqlite3Strlen30(zPath) - 1;
-+#ifdef SQLITE_ENABLE_8_3_NAMES
-+ while( nDb>0 && sqlite3Isalnum(zPath[nDb]) ) nDb--;
-+ if( nDb==0 || zPath[nDb]!='-' ) return SQLITE_OK;
-+#else
-+ while( zPath[nDb]!='-' ){
-+ assert( nDb>0 );
-+ assert( zPath[nDb]!='\n' );
-+ nDb--;
-+ }
-+#endif
-+ memcpy(zDb, zPath, nDb);
-+ zDb[nDb] = '\0';
-
--/*
--** This routine checks if there is a RESERVED lock held on the specified
--** file by this or any other process. If such a lock is held, set *pResOut
--** to a non-zero value otherwise *pResOut is set to zero. The return value
--** is set to SQLITE_OK unless an I/O error occurs during lock checking.
--*/
--static int proxyCheckReservedLock(sqlite3_file *id, int *pResOut) {
-- unixFile *pFile = (unixFile*)id;
-- int rc = proxyTakeConch(pFile);
-- if( rc==SQLITE_OK ){
-- proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext;
-- if( pCtx->conchHeld>0 ){
-- unixFile *proxy = pCtx->lockProxy;
-- return proxy->pMethod->xCheckReservedLock((sqlite3_file*)proxy, pResOut);
-- }else{ /* conchHeld < 0 is lockless */
-- pResOut=0;
-+ if( 0==osStat(zDb, &sStat) ){
-+ *pMode = sStat.st_mode & 0777;
-+ *pUid = sStat.st_uid;
-+ *pGid = sStat.st_gid;
-+ }else{
-+ rc = SQLITE_IOERR_FSTAT;
- }
-+ }else if( flags & SQLITE_OPEN_DELETEONCLOSE ){
-+ *pMode = 0600;
- }
- return rc;
- }
-
- /*
--** Lock the file with the lock specified by parameter eFileLock - one
--** of the following:
-+** Open the file zPath.
-+**
-+** Previously, the SQLite OS layer used three functions in place of this
-+** one:
- **
--** (1) SHARED_LOCK
--** (2) RESERVED_LOCK
--** (3) PENDING_LOCK
--** (4) EXCLUSIVE_LOCK
-+** sqlite3OsOpenReadWrite();
-+** sqlite3OsOpenReadOnly();
-+** sqlite3OsOpenExclusive();
- **
--** Sometimes when requesting one lock state, additional lock states
--** are inserted in between. The locking might fail on one of the later
--** transitions leaving the lock state different from what it started but
--** still short of its goal. The following chart shows the allowed
--** transitions and the inserted intermediate states:
-+** These calls correspond to the following combinations of flags:
- **
--** UNLOCKED -> SHARED
--** SHARED -> RESERVED
--** SHARED -> (PENDING) -> EXCLUSIVE
--** RESERVED -> (PENDING) -> EXCLUSIVE
--** PENDING -> EXCLUSIVE
-+** ReadWrite() -> (READWRITE | CREATE)
-+** ReadOnly() -> (READONLY)
-+** OpenExclusive() -> (READWRITE | CREATE | EXCLUSIVE)
- **
--** This routine will only increase a lock. Use the sqlite3OsUnlock()
--** routine to lower a locking level.
-+** The old OpenExclusive() accepted a boolean argument - "delFlag". If
-+** true, the file was configured to be automatically deleted when the
-+** file handle closed. To achieve the same effect using this new
-+** interface, add the DELETEONCLOSE flag to those specified above for
-+** OpenExclusive().
- */
--static int proxyLock(sqlite3_file *id, int eFileLock) {
-- unixFile *pFile = (unixFile*)id;
-- int rc = proxyTakeConch(pFile);
-- if( rc==SQLITE_OK ){
-- proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext;
-- if( pCtx->conchHeld>0 ){
-- unixFile *proxy = pCtx->lockProxy;
-- rc = proxy->pMethod->xLock((sqlite3_file*)proxy, eFileLock);
-- pFile->eFileLock = proxy->eFileLock;
-- }else{
-- /* conchHeld < 0 is lockless */
-- }
-- }
-- return rc;
--}
-+static int unixOpen(
-+ sqlite3_vfs *pVfs, /* The VFS for which this is the xOpen method */
-+ const char *zPath, /* Pathname of file to be opened */
-+ sqlite3_file *pFile, /* The file descriptor to be filled in */
-+ int flags, /* Input flags to control the opening */
-+ int *pOutFlags /* Output flags returned to SQLite core */
-+){
-+ unixFile *p = (unixFile *)pFile;
-+ int fd = -1; /* File descriptor returned by open() */
-+ int openFlags = 0; /* Flags to pass to open() */
-+ int eType = flags&0xFFFFFF00; /* Type of file to open */
-+ int noLock; /* True to omit locking primitives */
-+ int rc = SQLITE_OK; /* Function Return Code */
-+ int ctrlFlags = 0; /* UNIXFILE_* flags */
-
-+ int isExclusive = (flags & SQLITE_OPEN_EXCLUSIVE);
-+ int isDelete = (flags & SQLITE_OPEN_DELETEONCLOSE);
-+ int isCreate = (flags & SQLITE_OPEN_CREATE);
-+ int isReadonly = (flags & SQLITE_OPEN_READONLY);
-+ int isReadWrite = (flags & SQLITE_OPEN_READWRITE);
-+#if SQLITE_ENABLE_LOCKING_STYLE
-+ int isAutoProxy = (flags & SQLITE_OPEN_AUTOPROXY);
-+#endif
-+#if defined(__APPLE__) || SQLITE_ENABLE_LOCKING_STYLE
-+ struct statfs fsInfo;
-+#endif
-
--/*
--** Lower the locking level on file descriptor pFile to eFileLock. eFileLock
--** must be either NO_LOCK or SHARED_LOCK.
--**
--** If the locking level of the file descriptor is already at or below
--** the requested locking level, this routine is a no-op.
--*/
--static int proxyUnlock(sqlite3_file *id, int eFileLock) {
-- unixFile *pFile = (unixFile*)id;
-- int rc = proxyTakeConch(pFile);
-- if( rc==SQLITE_OK ){
-- proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext;
-- if( pCtx->conchHeld>0 ){
-- unixFile *proxy = pCtx->lockProxy;
-- rc = proxy->pMethod->xUnlock((sqlite3_file*)proxy, eFileLock);
-- pFile->eFileLock = proxy->eFileLock;
-+ /* If creating a master or main-file journal, this function will open
-+ ** a file-descriptor on the directory too. The first time unixSync()
-+ ** is called the directory file descriptor will be fsync()ed and close()d.
-+ */
-+ int syncDir = (isCreate && (
-+ eType==SQLITE_OPEN_MASTER_JOURNAL
-+ || eType==SQLITE_OPEN_MAIN_JOURNAL
-+ || eType==SQLITE_OPEN_WAL
-+ ));
-+
-+ /* If argument zPath is a NULL pointer, this function is required to open
-+ ** a temporary file. Use this buffer to store the file name in.
-+ */
-+ char zTmpname[MAX_PATHNAME+2];
-+ const char *zName = zPath;
-+
-+ /* Check the following statements are true:
-+ **
-+ ** (a) Exactly one of the READWRITE and READONLY flags must be set, and
-+ ** (b) if CREATE is set, then READWRITE must also be set, and
-+ ** (c) if EXCLUSIVE is set, then CREATE must also be set.
-+ ** (d) if DELETEONCLOSE is set, then CREATE must also be set.
-+ */
-+ assert((isReadonly==0 || isReadWrite==0) && (isReadWrite || isReadonly));
-+ assert(isCreate==0 || isReadWrite);
-+ assert(isExclusive==0 || isCreate);
-+ assert(isDelete==0 || isCreate);
-+
-+ /* The main DB, main journal, WAL file and master journal are never
-+ ** automatically deleted. Nor are they ever temporary files. */
-+ assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MAIN_DB );
-+ assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MAIN_JOURNAL );
-+ assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MASTER_JOURNAL );
-+ assert( (!isDelete && zName) || eType!=SQLITE_OPEN_WAL );
-+
-+ /* Assert that the upper layer has set one of the "file-type" flags. */
-+ assert( eType==SQLITE_OPEN_MAIN_DB || eType==SQLITE_OPEN_TEMP_DB
-+ || eType==SQLITE_OPEN_MAIN_JOURNAL || eType==SQLITE_OPEN_TEMP_JOURNAL
-+ || eType==SQLITE_OPEN_SUBJOURNAL || eType==SQLITE_OPEN_MASTER_JOURNAL
-+ || eType==SQLITE_OPEN_TRANSIENT_DB || eType==SQLITE_OPEN_WAL
-+ );
-+
-+ memset(p, 0, sizeof(unixFile));
-+
-+ if( eType==SQLITE_OPEN_MAIN_DB ){
-+ UnixUnusedFd *pUnused;
-+ pUnused = findReusableFd(zName, flags);
-+ if( pUnused ){
-+ fd = pUnused->fd;
- }else{
-- /* conchHeld < 0 is lockless */
-+ pUnused = sqlite3_malloc(sizeof(*pUnused));
-+ if( !pUnused ){
-+ return SQLITE_NOMEM;
-+ }
- }
-- }
-- return rc;
--}
-+ p->pUnused = pUnused;
-
--/*
--** Close a file that uses proxy locks.
--*/
--static int proxyClose(sqlite3_file *id) {
-- if( id ){
-- unixFile *pFile = (unixFile*)id;
-- proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext;
-- unixFile *lockProxy = pCtx->lockProxy;
-- unixFile *conchFile = pCtx->conchFile;
-- int rc = SQLITE_OK;
--
-- if( lockProxy ){
-- rc = lockProxy->pMethod->xUnlock((sqlite3_file*)lockProxy, NO_LOCK);
-- if( rc ) return rc;
-- rc = lockProxy->pMethod->xClose((sqlite3_file*)lockProxy);
-- if( rc ) return rc;
-- sqlite3_free(lockProxy);
-- pCtx->lockProxy = 0;
-- }
-- if( conchFile ){
-- if( pCtx->conchHeld ){
-- rc = proxyReleaseConch(pFile);
-- if( rc ) return rc;
-- }
-- rc = conchFile->pMethod->xClose((sqlite3_file*)conchFile);
-- if( rc ) return rc;
-- sqlite3_free(conchFile);
-+ /* Database filenames are double-zero terminated if they are not
-+ ** URIs with parameters. Hence, they can always be passed into
-+ ** sqlite3_uri_parameter(). */
-+ assert( (flags & SQLITE_OPEN_URI) || zName[strlen(zName)+1]==0 );
-+
-+ }else if( !zName ){
-+ /* If zName is NULL, the upper layer is requesting a temp file. */
-+ assert(isDelete && !syncDir);
-+ rc = unixGetTempname(MAX_PATHNAME+2, zTmpname);
-+ if( rc!=SQLITE_OK ){
-+ return rc;
- }
-- sqlite3DbFree(0, pCtx->lockProxyPath);
-- sqlite3_free(pCtx->conchFilePath);
-- sqlite3DbFree(0, pCtx->dbPath);
-- /* restore the original locking context and pMethod then close it */
-- pFile->lockingContext = pCtx->oldLockingContext;
-- pFile->pMethod = pCtx->pOldMethod;
-- sqlite3_free(pCtx);
-- return pFile->pMethod->xClose(id);
-+ zName = zTmpname;
-+
-+ /* Generated temporary filenames are always double-zero terminated
-+ ** for use by sqlite3_uri_parameter(). */
-+ assert( zName[strlen(zName)+1]==0 );
- }
-- return SQLITE_OK;
--}
-
-+ /* Determine the value of the flags parameter passed to POSIX function
-+ ** open(). These must be calculated even if open() is not called, as
-+ ** they may be stored as part of the file handle and used by the
-+ ** 'conch file' locking functions later on. */
-+ if( isReadonly ) openFlags |= O_RDONLY;
-+ if( isReadWrite ) openFlags |= O_RDWR;
-+ if( isCreate ) openFlags |= O_CREAT;
-+ if( isExclusive ) openFlags |= (O_EXCL|O_NOFOLLOW);
-+ openFlags |= (O_LARGEFILE|O_BINARY);
-
-+ if( fd<0 ){
-+ mode_t openMode; /* Permissions to create file with */
-+ uid_t uid; /* Userid for the file */
-+ gid_t gid; /* Groupid for the file */
-+ rc = findCreateFileMode(zName, flags, &openMode, &uid, &gid);
-+ if( rc!=SQLITE_OK ){
-+ assert( !p->pUnused );
-+ assert( eType==SQLITE_OPEN_WAL || eType==SQLITE_OPEN_MAIN_JOURNAL );
-+ return rc;
-+ }
-+ fd = robust_open(zName, openFlags, openMode);
-+ OSTRACE(("OPENX %-3d %s 0%o\n", fd, zName, openFlags));
-+ if( fd<0 && errno!=EISDIR && isReadWrite && !isExclusive ){
-+ /* Failed to open the file for read/write access. Try read-only. */
-+ flags &= ~(SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE);
-+ openFlags &= ~(O_RDWR|O_CREAT);
-+ flags |= SQLITE_OPEN_READONLY;
-+ openFlags |= O_RDONLY;
-+ isReadonly = 1;
-+ fd = robust_open(zName, openFlags, openMode);
-+ }
-+ if( fd<0 ){
-+ rc = unixLogError(SQLITE_CANTOPEN_BKPT, "open", zName);
-+ goto open_finished;
-+ }
-
--#endif /* defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE */
--/*
--** The proxy locking style is intended for use with AFP filesystems.
--** And since AFP is only supported on MacOSX, the proxy locking is also
--** restricted to MacOSX.
--**
--**
--******************* End of the proxy lock implementation **********************
--******************************************************************************/
-+ /* If this process is running as root and if creating a new rollback
-+ ** journal or WAL file, set the ownership of the journal or WAL to be
-+ ** the same as the original database.
-+ */
-+ if( flags & (SQLITE_OPEN_WAL|SQLITE_OPEN_MAIN_JOURNAL) ){
-+ osFchown(fd, uid, gid);
-+ }
-+ }
-+ assert( fd>=0 );
-+ if( pOutFlags ){
-+ *pOutFlags = flags;
-+ }
-
--/*
--** Initialize the operating system interface.
--**
--** This routine registers all VFS implementations for unix-like operating
--** systems. This routine, and the sqlite3_os_end() routine that follows,
--** should be the only routines in this file that are visible from other
--** files.
--**
--** This routine is called once during SQLite initialization and by a
--** single thread. The memory allocation and mutex subsystems have not
--** necessarily been initialized when this routine is called, and so they
--** should not be used.
--*/
--SQLITE_API int sqlite3_os_init(void){
-- /*
-- ** The following macro defines an initializer for an sqlite3_vfs object.
-- ** The name of the VFS is NAME. The pAppData is a pointer to a pointer
-- ** to the "finder" function. (pAppData is a pointer to a pointer because
-- ** silly C90 rules prohibit a void* from being cast to a function pointer
-- ** and so we have to go through the intermediate pointer to avoid problems
-- ** when compiling with -pedantic-errors on GCC.)
-- **
-- ** The FINDER parameter to this macro is the name of the pointer to the
-- ** finder-function. The finder-function returns a pointer to the
-- ** sqlite_io_methods object that implements the desired locking
-- ** behaviors. See the division above that contains the IOMETHODS
-- ** macro for addition information on finder-functions.
-- **
-- ** Most finders simply return a pointer to a fixed sqlite3_io_methods
-- ** object. But the "autolockIoFinder" available on MacOSX does a little
-- ** more than that; it looks at the filesystem type that hosts the
-- ** database file and tries to choose an locking method appropriate for
-- ** that filesystem time.
-- */
-- #define UNIXVFS(VFSNAME, FINDER) { \
-- 3, /* iVersion */ \
-- sizeof(unixFile), /* szOsFile */ \
-- MAX_PATHNAME, /* mxPathname */ \
-- 0, /* pNext */ \
-- VFSNAME, /* zName */ \
-- (void*)&FINDER, /* pAppData */ \
-- unixOpen, /* xOpen */ \
-- unixDelete, /* xDelete */ \
-- unixAccess, /* xAccess */ \
-- unixFullPathname, /* xFullPathname */ \
-- unixDlOpen, /* xDlOpen */ \
-- unixDlError, /* xDlError */ \
-- unixDlSym, /* xDlSym */ \
-- unixDlClose, /* xDlClose */ \
-- unixRandomness, /* xRandomness */ \
-- unixSleep, /* xSleep */ \
-- unixCurrentTime, /* xCurrentTime */ \
-- unixGetLastError, /* xGetLastError */ \
-- unixCurrentTimeInt64, /* xCurrentTimeInt64 */ \
-- unixSetSystemCall, /* xSetSystemCall */ \
-- unixGetSystemCall, /* xGetSystemCall */ \
-- unixNextSystemCall, /* xNextSystemCall */ \
-+ if( p->pUnused ){
-+ p->pUnused->fd = fd;
-+ p->pUnused->flags = flags;
- }
-
-- /*
-- ** All default VFSes for unix are contained in the following array.
-- **
-- ** Note that the sqlite3_vfs.pNext field of the VFS object is modified
-- ** by the SQLite core when the VFS is registered. So the following
-- ** array cannot be const.
-- */
-- static sqlite3_vfs aVfs[] = {
--#if SQLITE_ENABLE_LOCKING_STYLE && (OS_VXWORKS || defined(__APPLE__))
-- UNIXVFS("unix", autolockIoFinder ),
--#else
-- UNIXVFS("unix", posixIoFinder ),
--#endif
-- UNIXVFS("unix-none", nolockIoFinder ),
-- UNIXVFS("unix-dotfile", dotlockIoFinder ),
-- UNIXVFS("unix-excl", posixIoFinder ),
-+ if( isDelete ){
- #if OS_VXWORKS
-- UNIXVFS("unix-namedsem", semIoFinder ),
-+ zPath = zName;
-+#else
-+ osUnlink(zName);
- #endif
-+ }
- #if SQLITE_ENABLE_LOCKING_STYLE
-- UNIXVFS("unix-posix", posixIoFinder ),
--#if !OS_VXWORKS
-- UNIXVFS("unix-flock", flockIoFinder ),
-+ else{
-+ p->openFlags = openFlags;
-+ }
-+#endif
-+
-+ noLock = eType!=SQLITE_OPEN_MAIN_DB;
-+
-+
-+#if defined(__APPLE__) || SQLITE_ENABLE_LOCKING_STYLE
-+ if( fstatfs(fd, &fsInfo) == -1 ){
-+ ((unixFile*)pFile)->lastErrno = errno;
-+ robust_close(p, fd, __LINE__);
-+ return SQLITE_IOERR_ACCESS;
-+ }
-+ if (0 == strncmp("msdos", fsInfo.f_fstypename, 5)) {
-+ ((unixFile*)pFile)->fsFlags |= SQLITE_FSFLAGS_IS_MSDOS;
-+ }
- #endif
-+
-+ /* Set up appropriate ctrlFlags */
-+ if( isDelete ) ctrlFlags |= UNIXFILE_DELETE;
-+ if( isReadonly ) ctrlFlags |= UNIXFILE_RDONLY;
-+ if( noLock ) ctrlFlags |= UNIXFILE_NOLOCK;
-+ if( syncDir ) ctrlFlags |= UNIXFILE_DIRSYNC;
-+ if( flags & SQLITE_OPEN_URI ) ctrlFlags |= UNIXFILE_URI;
-+
-+#if SQLITE_ENABLE_LOCKING_STYLE
-+#if SQLITE_PREFER_PROXY_LOCKING
-+ isAutoProxy = 1;
- #endif
--#if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__)
-- UNIXVFS("unix-afp", afpIoFinder ),
-- UNIXVFS("unix-nfs", nfsIoFinder ),
-- UNIXVFS("unix-proxy", proxyIoFinder ),
-+ if( isAutoProxy && (zPath!=NULL) && (!noLock) && pVfs->xOpen ){
-+ char *envforce = getenv("SQLITE_FORCE_PROXY_LOCKING");
-+ int useProxy = 0;
-+
-+ /* SQLITE_FORCE_PROXY_LOCKING==1 means force always use proxy, 0 means
-+ ** never use proxy, NULL means use proxy for non-local files only. */
-+ if( envforce!=NULL ){
-+ useProxy = atoi(envforce)>0;
-+ }else{
-+ if( statfs(zPath, &fsInfo) == -1 ){
-+ /* In theory, the close(fd) call is sub-optimal. If the file opened
-+ ** with fd is a database file, and there are other connections open
-+ ** on that file that are currently holding advisory locks on it,
-+ ** then the call to close() will cancel those locks. In practice,
-+ ** we're assuming that statfs() doesn't fail very often. At least
-+ ** not while other file descriptors opened by the same process on
-+ ** the same file are working. */
-+ p->lastErrno = errno;
-+ robust_close(p, fd, __LINE__);
-+ rc = SQLITE_IOERR_ACCESS;
-+ goto open_finished;
-+ }
-+ useProxy = !(fsInfo.f_flags&MNT_LOCAL);
-+ }
-+ if( useProxy ){
-+ rc = fillInUnixFile(pVfs, fd, pFile, zPath, ctrlFlags);
-+ if( rc==SQLITE_OK ){
-+ rc = proxyTransformUnixFile((unixFile*)pFile, ":auto:");
-+ if( rc!=SQLITE_OK ){
-+ /* Use unixClose to clean up the resources added in fillInUnixFile
-+ ** and clear all the structure's references. Specifically,
-+ ** pFile->pMethods will be NULL so sqlite3OsClose will be a no-op
-+ */
-+ unixClose(pFile);
-+ return rc;
-+ }
-+ }
-+ goto open_finished;
-+ }
-+ }
- #endif
-- };
-- unsigned int i; /* Loop counter */
--
-- /* Double-check that the aSyscall[] array has been constructed
-- ** correctly. See ticket [bb3a86e890c8e96ab] */
-- assert( ArraySize(aSyscall)==24 );
-+
-+ rc = fillInUnixFile(pVfs, fd, pFile, zPath, ctrlFlags);
-
-- /* Register all VFSes defined in the aVfs[] array */
-- for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){
-- sqlite3_vfs_register(&aVfs[i], i==0);
-+open_finished:
-+ if( rc!=SQLITE_OK ){
-+ sqlite3_free(p->pUnused);
- }
-- return SQLITE_OK;
--}
--
--/*
--** Shutdown the operating system interface.
--**
--** Some operating systems might need to do some cleanup in this routine,
--** to release dynamically allocated objects. But not on unix.
--** This routine is a no-op for unix.
--*/
--SQLITE_API int sqlite3_os_end(void){
-- return SQLITE_OK;
-+ return rc;
- }
--
--#endif /* SQLITE_OS_UNIX */
-
--/************** End of os_unix.c *********************************************/
--/************** Begin file os_win.c ******************************************/
--/*
--** 2004 May 22
--**
--** The author disclaims copyright to this source code. In place of
--** a legal notice, here is a blessing:
--**
--** May you do good and not evil.
--** May you find forgiveness for yourself and forgive others.
--** May you share freely, never taking more than you give.
--**
--******************************************************************************
--**
--** This file contains code that is specific to Windows.
--*/
--#if SQLITE_OS_WIN /* This file is used for Windows only */
--
--#ifdef __CYGWIN__
--# include <sys/cygwin.h>
--#endif
--
--/*
--** Include code that is common to all os_*.c files
--*/
--/************** Include os_common.h in the middle of os_win.c ****************/
--/************** Begin file os_common.h ***************************************/
--/*
--** 2004 May 22
--**
--** The author disclaims copyright to this source code. In place of
--** a legal notice, here is a blessing:
--**
--** May you do good and not evil.
--** May you find forgiveness for yourself and forgive others.
--** May you share freely, never taking more than you give.
--**
--******************************************************************************
--**
--** This file contains macros and a little bit of code that is common to
--** all of the platform-specific files (os_*.c) and is #included into those
--** files.
--**
--** This file should be #included by the os_*.c files only. It is not a
--** general purpose header file.
--*/
--#ifndef _OS_COMMON_H_
--#define _OS_COMMON_H_
-
- /*
--** At least two bugs have slipped in because we changed the MEMORY_DEBUG
--** macro to SQLITE_DEBUG and some older makefiles have not yet made the
--** switch. The following code should catch this problem at compile-time.
-+** Delete the file at zPath. If the dirSync argument is true, fsync()
-+** the directory after deleting the file.
- */
--#ifdef MEMORY_DEBUG
--# error "The MEMORY_DEBUG macro is obsolete. Use SQLITE_DEBUG instead."
--#endif
--
--#if defined(SQLITE_TEST) && defined(SQLITE_DEBUG)
--# ifndef SQLITE_DEBUG_OS_TRACE
--# define SQLITE_DEBUG_OS_TRACE 0
--# endif
-- int sqlite3OSTrace = SQLITE_DEBUG_OS_TRACE;
--# define OSTRACE(X) if( sqlite3OSTrace ) sqlite3DebugPrintf X
-+static int unixDelete(
-+ sqlite3_vfs *NotUsed, /* VFS containing this as the xDelete method */
-+ const char *zPath, /* Name of file to be deleted */
-+ int dirSync /* If true, fsync() directory after deleting file */
-+){
-+ int rc = SQLITE_OK;
-+ UNUSED_PARAMETER(NotUsed);
-+ SimulateIOError(return SQLITE_IOERR_DELETE);
-+ if( osUnlink(zPath)==(-1) ){
-+ if( errno==ENOENT ){
-+ rc = SQLITE_IOERR_DELETE_NOENT;
-+ }else{
-+ rc = unixLogError(SQLITE_IOERR_DELETE, "unlink", zPath);
-+ }
-+ return rc;
-+ }
-+#ifndef SQLITE_DISABLE_DIRSYNC
-+ if( (dirSync & 1)!=0 ){
-+ int fd;
-+ rc = osOpenDirectory(zPath, &fd);
-+ if( rc==SQLITE_OK ){
-+#if OS_VXWORKS
-+ if( fsync(fd)==-1 )
- #else
--# define OSTRACE(X)
-+ if( fsync(fd) )
- #endif
-+ {
-+ rc = unixLogError(SQLITE_IOERR_DIR_FSYNC, "fsync", zPath);
-+ }
-+ robust_close(0, fd, __LINE__);
-+ }else if( rc==SQLITE_CANTOPEN ){
-+ rc = SQLITE_OK;
-+ }
-+ }
-+#endif
-+ return rc;
-+}
-
- /*
--** Macros for performance tracing. Normally turned off. Only works
--** on i486 hardware.
--*/
--#ifdef SQLITE_PERFORMANCE_TRACE
--
--/*
--** hwtime.h contains inline assembler code for implementing
--** high-performance timing routines.
--*/
--/************** Include hwtime.h in the middle of os_common.h ****************/
--/************** Begin file hwtime.h ******************************************/
--/*
--** 2008 May 27
--**
--** The author disclaims copyright to this source code. In place of
--** a legal notice, here is a blessing:
--**
--** May you do good and not evil.
--** May you find forgiveness for yourself and forgive others.
--** May you share freely, never taking more than you give.
-+** Test the existence of or access permissions of file zPath. The
-+** test performed depends on the value of flags:
- **
--******************************************************************************
-+** SQLITE_ACCESS_EXISTS: Return 1 if the file exists
-+** SQLITE_ACCESS_READWRITE: Return 1 if the file is read and writable.
-+** SQLITE_ACCESS_READONLY: Return 1 if the file is readable.
- **
--** This file contains inline asm code for retrieving "high-performance"
--** counters for x86 class CPUs.
--*/
--#ifndef _HWTIME_H_
--#define _HWTIME_H_
--
--/*
--** The following routine only works on pentium-class (or newer) processors.
--** It uses the RDTSC opcode to read the cycle count value out of the
--** processor and returns that value. This can be used for high-res
--** profiling.
-+** Otherwise return 0.
- */
--#if (defined(__GNUC__) || defined(_MSC_VER)) && \
-- (defined(i386) || defined(__i386__) || defined(_M_IX86))
--
-- #if defined(__GNUC__)
--
-- __inline__ sqlite_uint64 sqlite3Hwtime(void){
-- unsigned int lo, hi;
-- __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
-- return (sqlite_uint64)hi << 32 | lo;
-- }
--
-- #elif defined(_MSC_VER)
--
-- __declspec(naked) __inline sqlite_uint64 __cdecl sqlite3Hwtime(void){
-- __asm {
-- rdtsc
-- ret ; return value at EDX:EAX
-- }
-- }
--
-- #endif
--
--#elif (defined(__GNUC__) && defined(__x86_64__))
-+static int unixAccess(
-+ sqlite3_vfs *NotUsed, /* The VFS containing this xAccess method */
-+ const char *zPath, /* Path of the file to examine */
-+ int flags, /* What do we want to learn about the zPath file? */
-+ int *pResOut /* Write result boolean here */
-+){
-+ int amode = 0;
-+ UNUSED_PARAMETER(NotUsed);
-+ SimulateIOError( return SQLITE_IOERR_ACCESS; );
-+ switch( flags ){
-+ case SQLITE_ACCESS_EXISTS:
-+ amode = F_OK;
-+ break;
-+ case SQLITE_ACCESS_READWRITE:
-+ amode = W_OK|R_OK;
-+ break;
-+ case SQLITE_ACCESS_READ:
-+ amode = R_OK;
-+ break;
-
-- __inline__ sqlite_uint64 sqlite3Hwtime(void){
-- unsigned long val;
-- __asm__ __volatile__ ("rdtsc" : "=A" (val));
-- return val;
-+ default:
-+ assert(!"Invalid flags argument");
- }
--
--#elif (defined(__GNUC__) && defined(__ppc__))
--
-- __inline__ sqlite_uint64 sqlite3Hwtime(void){
-- unsigned long long retval;
-- unsigned long junk;
-- __asm__ __volatile__ ("\n\
-- 1: mftbu %1\n\
-- mftb %L0\n\
-- mftbu %0\n\
-- cmpw %0,%1\n\
-- bne 1b"
-- : "=r" (retval), "=r" (junk));
-- return retval;
-+ *pResOut = (osAccess(zPath, amode)==0);
-+ if( flags==SQLITE_ACCESS_EXISTS && *pResOut ){
-+ struct stat buf;
-+ if( 0==osStat(zPath, &buf) && buf.st_size==0 ){
-+ *pResOut = 0;
-+ }
- }
-+ return SQLITE_OK;
-+}
-
--#else
-
-- #error Need implementation of sqlite3Hwtime() for your platform.
-+/*
-+** Turn a relative pathname into a full pathname. The relative path
-+** is stored as a nul-terminated string in the buffer pointed to by
-+** zPath.
-+**
-+** zOut points to a buffer of at least sqlite3_vfs.mxPathname bytes
-+** (in this case, MAX_PATHNAME bytes). The full-path is written to
-+** this buffer before returning.
-+*/
-+static int unixFullPathname(
-+ sqlite3_vfs *pVfs, /* Pointer to vfs object */
-+ const char *zPath, /* Possibly relative input path */
-+ int nOut, /* Size of output buffer in bytes */
-+ char *zOut /* Output buffer */
-+){
-
-- /*
-- ** To compile without implementing sqlite3Hwtime() for your platform,
-- ** you can remove the above #error and use the following
-- ** stub function. You will lose timing support for many
-- ** of the debugging and testing utilities, but it should at
-- ** least compile and run.
-+ /* It's odd to simulate an io-error here, but really this is just
-+ ** using the io-error infrastructure to test that SQLite handles this
-+ ** function failing. This function could fail if, for example, the
-+ ** current working directory has been unlinked.
- */
--SQLITE_PRIVATE sqlite_uint64 sqlite3Hwtime(void){ return ((sqlite_uint64)0); }
--
--#endif
-+ SimulateIOError( return SQLITE_ERROR );
-
--#endif /* !defined(_HWTIME_H_) */
-+ assert( pVfs->mxPathname==MAX_PATHNAME );
-+ UNUSED_PARAMETER(pVfs);
-
--/************** End of hwtime.h **********************************************/
--/************** Continuing where we left off in os_common.h ******************/
-+ zOut[nOut-1] = '\0';
-+ if( zPath[0]=='/' ){
-+ sqlite3_snprintf(nOut, zOut, "%s", zPath);
-+ }else{
-+ int nCwd;
-+ if( osGetcwd(zOut, nOut-1)==0 ){
-+ return unixLogError(SQLITE_CANTOPEN_BKPT, "getcwd", zPath);
-+ }
-+ nCwd = (int)strlen(zOut);
-+ sqlite3_snprintf(nOut-nCwd, &zOut[nCwd], "/%s", zPath);
-+ }
-+ return SQLITE_OK;
-+}
-
--static sqlite_uint64 g_start;
--static sqlite_uint64 g_elapsed;
--#define TIMER_START g_start=sqlite3Hwtime()
--#define TIMER_END g_elapsed=sqlite3Hwtime()-g_start
--#define TIMER_ELAPSED g_elapsed
--#else
--#define TIMER_START
--#define TIMER_END
--#define TIMER_ELAPSED ((sqlite_uint64)0)
--#endif
-
-+#ifndef SQLITE_OMIT_LOAD_EXTENSION
- /*
--** If we compile with the SQLITE_TEST macro set, then the following block
--** of code will give us the ability to simulate a disk I/O error. This
--** is used for testing the I/O recovery logic.
-+** Interfaces for opening a shared library, finding entry points
-+** within the shared library, and closing the shared library.
- */
--#ifdef SQLITE_TEST
--SQLITE_API int sqlite3_io_error_hit = 0; /* Total number of I/O Errors */
--SQLITE_API int sqlite3_io_error_hardhit = 0; /* Number of non-benign errors */
--SQLITE_API int sqlite3_io_error_pending = 0; /* Count down to first I/O error */
--SQLITE_API int sqlite3_io_error_persist = 0; /* True if I/O errors persist */
--SQLITE_API int sqlite3_io_error_benign = 0; /* True if errors are benign */
--SQLITE_API int sqlite3_diskfull_pending = 0;
--SQLITE_API int sqlite3_diskfull = 0;
--#define SimulateIOErrorBenign(X) sqlite3_io_error_benign=(X)
--#define SimulateIOError(CODE) \
-- if( (sqlite3_io_error_persist && sqlite3_io_error_hit) \
-- || sqlite3_io_error_pending-- == 1 ) \
-- { local_ioerr(); CODE; }
--static void local_ioerr(){
-- IOTRACE(("IOERR\n"));
-- sqlite3_io_error_hit++;
-- if( !sqlite3_io_error_benign ) sqlite3_io_error_hardhit++;
-+#include <dlfcn.h>
-+static void *unixDlOpen(sqlite3_vfs *NotUsed, const char *zFilename){
-+ UNUSED_PARAMETER(NotUsed);
-+ return dlopen(zFilename, RTLD_NOW | RTLD_GLOBAL);
- }
--#define SimulateDiskfullError(CODE) \
-- if( sqlite3_diskfull_pending ){ \
-- if( sqlite3_diskfull_pending == 1 ){ \
-- local_ioerr(); \
-- sqlite3_diskfull = 1; \
-- sqlite3_io_error_hit = 1; \
-- CODE; \
-- }else{ \
-- sqlite3_diskfull_pending--; \
-- } \
-- }
--#else
--#define SimulateIOErrorBenign(X)
--#define SimulateIOError(A)
--#define SimulateDiskfullError(A)
--#endif
-
- /*
--** When testing, keep a count of the number of open files.
-+** SQLite calls this function immediately after a call to unixDlSym() or
-+** unixDlOpen() fails (returns a null pointer). If a more detailed error
-+** message is available, it is written to zBufOut. If no error message
-+** is available, zBufOut is left unmodified and SQLite uses a default
-+** error message.
- */
--#ifdef SQLITE_TEST
--SQLITE_API int sqlite3_open_file_count = 0;
--#define OpenCounter(X) sqlite3_open_file_count+=(X)
--#else
--#define OpenCounter(X)
-+static void unixDlError(sqlite3_vfs *NotUsed, int nBuf, char *zBufOut){
-+ const char *zErr;
-+ UNUSED_PARAMETER(NotUsed);
-+ unixEnterMutex();
-+ zErr = dlerror();
-+ if( zErr ){
-+ sqlite3_snprintf(nBuf, zBufOut, "%s", zErr);
-+ }
-+ unixLeaveMutex();
-+}
-+static void (*unixDlSym(sqlite3_vfs *NotUsed, void *p, const char*zSym))(void){
-+ /*
-+ ** GCC with -pedantic-errors says that C90 does not allow a void* to be
-+ ** cast into a pointer to a function. And yet the library dlsym() routine
-+ ** returns a void* which is really a pointer to a function. So how do we
-+ ** use dlsym() with -pedantic-errors?
-+ **
-+ ** Variable x below is defined to be a pointer to a function taking
-+ ** parameters void* and const char* and returning a pointer to a function.
-+ ** We initialize x by assigning it a pointer to the dlsym() function.
-+ ** (That assignment requires a cast.) Then we call the function that
-+ ** x points to.
-+ **
-+ ** This work-around is unlikely to work correctly on any system where
-+ ** you really cannot cast a function pointer into void*. But then, on the
-+ ** other hand, dlsym() will not work on such a system either, so we have
-+ ** not really lost anything.
-+ */
-+ void (*(*x)(void*,const char*))(void);
-+ UNUSED_PARAMETER(NotUsed);
-+ x = (void(*(*)(void*,const char*))(void))dlsym;
-+ return (*x)(p, zSym);
-+}
-+static void unixDlClose(sqlite3_vfs *NotUsed, void *pHandle){
-+ UNUSED_PARAMETER(NotUsed);
-+ dlclose(pHandle);
-+}
-+#else /* if SQLITE_OMIT_LOAD_EXTENSION is defined: */
-+ #define unixDlOpen 0
-+ #define unixDlError 0
-+ #define unixDlSym 0
-+ #define unixDlClose 0
- #endif
-
--#endif /* !defined(_OS_COMMON_H_) */
--
--/************** End of os_common.h *******************************************/
--/************** Continuing where we left off in os_win.c *********************/
--
- /*
--** Compiling and using WAL mode requires several APIs that are only
--** available in Windows platforms based on the NT kernel.
-+** Write nBuf bytes of random data to the supplied buffer zBuf.
- */
--#if !SQLITE_OS_WINNT && !defined(SQLITE_OMIT_WAL)
--# error "WAL mode requires support from the Windows NT kernel, compile\
-- with SQLITE_OMIT_WAL."
-+static int unixRandomness(sqlite3_vfs *NotUsed, int nBuf, char *zBuf){
-+ UNUSED_PARAMETER(NotUsed);
-+ assert((size_t)nBuf>=(sizeof(time_t)+sizeof(int)));
-+
-+ /* We have to initialize zBuf to prevent valgrind from reporting
-+ ** errors. The reports issued by valgrind are incorrect - we would
-+ ** prefer that the randomness be increased by making use of the
-+ ** uninitialized space in zBuf - but valgrind errors tend to worry
-+ ** some users. Rather than argue, it seems easier just to initialize
-+ ** the whole array and silence valgrind, even if that means less randomness
-+ ** in the random seed.
-+ **
-+ ** When testing, initializing zBuf[] to zero is all we do. That means
-+ ** that we always use the same random number sequence. This makes the
-+ ** tests repeatable.
-+ */
-+ memset(zBuf, 0, nBuf);
-+#if !defined(SQLITE_TEST)
-+ {
-+ int pid, fd, got;
-+ fd = robust_open("/dev/urandom", O_RDONLY, 0);
-+ if( fd<0 ){
-+ time_t t;
-+ time(&t);
-+ memcpy(zBuf, &t, sizeof(t));
-+ pid = getpid();
-+ memcpy(&zBuf[sizeof(t)], &pid, sizeof(pid));
-+ assert( sizeof(t)+sizeof(pid)<=(size_t)nBuf );
-+ nBuf = sizeof(t) + sizeof(pid);
-+ }else{
-+ do{ got = osRead(fd, zBuf, nBuf); }while( got<0 && errno==EINTR );
-+ robust_close(0, fd, __LINE__);
-+ }
-+ }
- #endif
-+ return nBuf;
-+}
-+
-
- /*
--** Are most of the Win32 ANSI APIs available (i.e. with certain exceptions
--** based on the sub-platform)?
-+** Sleep for a little while. Return the amount of time slept.
-+** The argument is the number of microseconds we want to sleep.
-+** The return value is the number of microseconds of sleep actually
-+** requested from the underlying operating system, a number which
-+** might be greater than or equal to the argument, but not less
-+** than the argument.
- */
--#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT
--# define SQLITE_WIN32_HAS_ANSI
-+static int unixSleep(sqlite3_vfs *NotUsed, int microseconds){
-+#if OS_VXWORKS
-+ struct timespec sp;
-+
-+ sp.tv_sec = microseconds / 1000000;
-+ sp.tv_nsec = (microseconds % 1000000) * 1000;
-+ nanosleep(&sp, NULL);
-+ UNUSED_PARAMETER(NotUsed);
-+ return microseconds;
-+#elif defined(HAVE_USLEEP) && HAVE_USLEEP
-+ usleep(microseconds);
-+ UNUSED_PARAMETER(NotUsed);
-+ return microseconds;
-+#else
-+ int seconds = (microseconds+999999)/1000000;
-+ sleep(seconds);
-+ UNUSED_PARAMETER(NotUsed);
-+ return seconds*1000000;
- #endif
-+}
-
- /*
--** Are most of the Win32 Unicode APIs available (i.e. with certain exceptions
--** based on the sub-platform)?
-+** The following variable, if set to a non-zero value, is interpreted as
-+** the number of seconds since 1970 and is used to set the result of
-+** sqlite3OsCurrentTime() during testing.
- */
--#if SQLITE_OS_WINCE || SQLITE_OS_WINNT || SQLITE_OS_WINRT
--# define SQLITE_WIN32_HAS_WIDE
-+#ifdef SQLITE_TEST
-+SQLITE_API int sqlite3_current_time = 0; /* Fake system time in seconds since 1970. */
- #endif
-
- /*
--** Do we need to manually define the Win32 file mapping APIs for use with WAL
--** mode (e.g. these APIs are available in the Windows CE SDK; however, they
--** are not present in the header file)?
--*/
--#if SQLITE_WIN32_FILEMAPPING_API && !defined(SQLITE_OMIT_WAL)
--/*
--** Two of the file mapping APIs are different under WinRT. Figure out which
--** set we need.
-+** Find the current time (in Universal Coordinated Time). Write into *piNow
-+** the current time and date as a Julian Day number times 86_400_000. In
-+** other words, write into *piNow the number of milliseconds since the Julian
-+** epoch of noon in Greenwich on November 24, 4714 B.C according to the
-+** proleptic Gregorian calendar.
-+**
-+** On success, return SQLITE_OK. Return SQLITE_ERROR if the time and date
-+** cannot be found.
- */
--#if SQLITE_OS_WINRT
--WINBASEAPI HANDLE WINAPI CreateFileMappingFromApp(HANDLE, \
-- LPSECURITY_ATTRIBUTES, ULONG, ULONG64, LPCWSTR);
--
--WINBASEAPI LPVOID WINAPI MapViewOfFileFromApp(HANDLE, ULONG, ULONG64, SIZE_T);
-+static int unixCurrentTimeInt64(sqlite3_vfs *NotUsed, sqlite3_int64 *piNow){
-+ static const sqlite3_int64 unixEpoch = 24405875*(sqlite3_int64)8640000;
-+ int rc = SQLITE_OK;
-+#if defined(NO_GETTOD)
-+ time_t t;
-+ time(&t);
-+ *piNow = ((sqlite3_int64)t)*1000 + unixEpoch;
-+#elif OS_VXWORKS
-+ struct timespec sNow;
-+ clock_gettime(CLOCK_REALTIME, &sNow);
-+ *piNow = unixEpoch + 1000*(sqlite3_int64)sNow.tv_sec + sNow.tv_nsec/1000000;
- #else
--#if defined(SQLITE_WIN32_HAS_ANSI)
--WINBASEAPI HANDLE WINAPI CreateFileMappingA(HANDLE, LPSECURITY_ATTRIBUTES, \
-- DWORD, DWORD, DWORD, LPCSTR);
--#endif /* defined(SQLITE_WIN32_HAS_ANSI) */
--
--#if defined(SQLITE_WIN32_HAS_WIDE)
--WINBASEAPI HANDLE WINAPI CreateFileMappingW(HANDLE, LPSECURITY_ATTRIBUTES, \
-- DWORD, DWORD, DWORD, LPCWSTR);
--#endif /* defined(SQLITE_WIN32_HAS_WIDE) */
--
--WINBASEAPI LPVOID WINAPI MapViewOfFile(HANDLE, DWORD, DWORD, DWORD, SIZE_T);
--#endif /* SQLITE_OS_WINRT */
-+ struct timeval sNow;
-+ if( gettimeofday(&sNow, 0)==0 ){
-+ *piNow = unixEpoch + 1000*(sqlite3_int64)sNow.tv_sec + sNow.tv_usec/1000;
-+ }else{
-+ rc = SQLITE_ERROR;
-+ }
-+#endif
-
--/*
--** This file mapping API is common to both Win32 and WinRT.
--*/
--WINBASEAPI BOOL WINAPI UnmapViewOfFile(LPCVOID);
--#endif /* SQLITE_WIN32_FILEMAPPING_API && !defined(SQLITE_OMIT_WAL) */
-+#ifdef SQLITE_TEST
-+ if( sqlite3_current_time ){
-+ *piNow = 1000*(sqlite3_int64)sqlite3_current_time + unixEpoch;
-+ }
-+#endif
-+ UNUSED_PARAMETER(NotUsed);
-+ return rc;
-+}
-
- /*
--** Macro to find the minimum of two numeric values.
-+** Find the current time (in Universal Coordinated Time). Write the
-+** current time and date as a Julian Day number into *prNow and
-+** return 0. Return 1 if the time and date cannot be found.
- */
--#ifndef MIN
--# define MIN(x,y) ((x)<(y)?(x):(y))
--#endif
-+static int unixCurrentTime(sqlite3_vfs *NotUsed, double *prNow){
-+ sqlite3_int64 i = 0;
-+ int rc;
-+ UNUSED_PARAMETER(NotUsed);
-+ rc = unixCurrentTimeInt64(0, &i);
-+ *prNow = i/86400000.0;
-+ return rc;
-+}
-
- /*
--** Some Microsoft compilers lack this definition.
-+** We added the xGetLastError() method with the intention of providing
-+** better low-level error messages when operating-system problems come up
-+** during SQLite operation. But so far, none of that has been implemented
-+** in the core. So this routine is never called. For now, it is merely
-+** a place-holder.
- */
--#ifndef INVALID_FILE_ATTRIBUTES
--# define INVALID_FILE_ATTRIBUTES ((DWORD)-1)
--#endif
-+static int unixGetLastError(sqlite3_vfs *NotUsed, int NotUsed2, char *NotUsed3){
-+ UNUSED_PARAMETER(NotUsed);
-+ UNUSED_PARAMETER(NotUsed2);
-+ UNUSED_PARAMETER(NotUsed3);
-+ return 0;
-+}
-
--#ifndef FILE_FLAG_MASK
--# define FILE_FLAG_MASK (0xFF3C0000)
--#endif
-
--#ifndef FILE_ATTRIBUTE_MASK
--# define FILE_ATTRIBUTE_MASK (0x0003FFF7)
--#endif
-+/*
-+************************ End of sqlite3_vfs methods ***************************
-+******************************************************************************/
-
--#ifndef SQLITE_OMIT_WAL
--/* Forward references */
--typedef struct winShm winShm; /* A connection to shared-memory */
--typedef struct winShmNode winShmNode; /* A region of shared-memory */
--#endif
-+/******************************************************************************
-+************************** Begin Proxy Locking ********************************
-+**
-+** Proxy locking is a "uber-locking-method" in this sense: It uses the
-+** other locking methods on secondary lock files. Proxy locking is a
-+** meta-layer over top of the primitive locking implemented above. For
-+** this reason, the division that implements of proxy locking is deferred
-+** until late in the file (here) after all of the other I/O methods have
-+** been defined - so that the primitive locking methods are available
-+** as services to help with the implementation of proxy locking.
-+**
-+****
-+**
-+** The default locking schemes in SQLite use byte-range locks on the
-+** database file to coordinate safe, concurrent access by multiple readers
-+** and writers [http://sqlite.org/lockingv3.html]. The five file locking
-+** states (UNLOCKED, PENDING, SHARED, RESERVED, EXCLUSIVE) are implemented
-+** as POSIX read & write locks over fixed set of locations (via fsctl),
-+** on AFP and SMB only exclusive byte-range locks are available via fsctl
-+** with _IOWR('z', 23, struct ByteRangeLockPB2) to track the same 5 states.
-+** To simulate a F_RDLCK on the shared range, on AFP a randomly selected
-+** address in the shared range is taken for a SHARED lock, the entire
-+** shared range is taken for an EXCLUSIVE lock):
-+**
-+** PENDING_BYTE 0x40000000
-+** RESERVED_BYTE 0x40000001
-+** SHARED_RANGE 0x40000002 -> 0x40000200
-+**
-+** This works well on the local file system, but shows a nearly 100x
-+** slowdown in read performance on AFP because the AFP client disables
-+** the read cache when byte-range locks are present. Enabling the read
-+** cache exposes a cache coherency problem that is present on all OS X
-+** supported network file systems. NFS and AFP both observe the
-+** close-to-open semantics for ensuring cache coherency
-+** [http://nfs.sourceforge.net/#faq_a8], which does not effectively
-+** address the requirements for concurrent database access by multiple
-+** readers and writers
-+** [http://www.nabble.com/SQLite-on-NFS-cache-coherency-td15655701.html].
-+**
-+** To address the performance and cache coherency issues, proxy file locking
-+** changes the way database access is controlled by limiting access to a
-+** single host at a time and moving file locks off of the database file
-+** and onto a proxy file on the local file system.
-+**
-+**
-+** Using proxy locks
-+** -----------------
-+**
-+** C APIs
-+**
-+** sqlite3_file_control(db, dbname, SQLITE_SET_LOCKPROXYFILE,
-+** <proxy_path> | ":auto:");
-+** sqlite3_file_control(db, dbname, SQLITE_GET_LOCKPROXYFILE, &<proxy_path>);
-+**
-+**
-+** SQL pragmas
-+**
-+** PRAGMA [database.]lock_proxy_file=<proxy_path> | :auto:
-+** PRAGMA [database.]lock_proxy_file
-+**
-+** Specifying ":auto:" means that if there is a conch file with a matching
-+** host ID in it, the proxy path in the conch file will be used, otherwise
-+** a proxy path based on the user's temp dir
-+** (via confstr(_CS_DARWIN_USER_TEMP_DIR,...)) will be used and the
-+** actual proxy file name is generated from the name and path of the
-+** database file. For example:
-+**
-+** For database path "/Users/me/foo.db"
-+** The lock path will be "<tmpdir>/sqliteplocks/_Users_me_foo.db:auto:")
-+**
-+** Once a lock proxy is configured for a database connection, it can not
-+** be removed, however it may be switched to a different proxy path via
-+** the above APIs (assuming the conch file is not being held by another
-+** connection or process).
-+**
-+**
-+** How proxy locking works
-+** -----------------------
-+**
-+** Proxy file locking relies primarily on two new supporting files:
-+**
-+** * conch file to limit access to the database file to a single host
-+** at a time
-+**
-+** * proxy file to act as a proxy for the advisory locks normally
-+** taken on the database
-+**
-+** The conch file - to use a proxy file, sqlite must first "hold the conch"
-+** by taking an sqlite-style shared lock on the conch file, reading the
-+** contents and comparing the host's unique host ID (see below) and lock
-+** proxy path against the values stored in the conch. The conch file is
-+** stored in the same directory as the database file and the file name
-+** is patterned after the database file name as ".<databasename>-conch".
-+** If the conch file does not exist, or it's contents do not match the
-+** host ID and/or proxy path, then the lock is escalated to an exclusive
-+** lock and the conch file contents is updated with the host ID and proxy
-+** path and the lock is downgraded to a shared lock again. If the conch
-+** is held by another process (with a shared lock), the exclusive lock
-+** will fail and SQLITE_BUSY is returned.
-+**
-+** The proxy file - a single-byte file used for all advisory file locks
-+** normally taken on the database file. This allows for safe sharing
-+** of the database file for multiple readers and writers on the same
-+** host (the conch ensures that they all use the same local lock file).
-+**
-+** Requesting the lock proxy does not immediately take the conch, it is
-+** only taken when the first request to lock database file is made.
-+** This matches the semantics of the traditional locking behavior, where
-+** opening a connection to a database file does not take a lock on it.
-+** The shared lock and an open file descriptor are maintained until
-+** the connection to the database is closed.
-+**
-+** The proxy file and the lock file are never deleted so they only need
-+** to be created the first time they are used.
-+**
-+** Configuration options
-+** ---------------------
-+**
-+** SQLITE_PREFER_PROXY_LOCKING
-+**
-+** Database files accessed on non-local file systems are
-+** automatically configured for proxy locking, lock files are
-+** named automatically using the same logic as
-+** PRAGMA lock_proxy_file=":auto:"
-+**
-+** SQLITE_PROXY_DEBUG
-+**
-+** Enables the logging of error messages during host id file
-+** retrieval and creation
-+**
-+** LOCKPROXYDIR
-+**
-+** Overrides the default directory used for lock proxy files that
-+** are named automatically via the ":auto:" setting
-+**
-+** SQLITE_DEFAULT_PROXYDIR_PERMISSIONS
-+**
-+** Permissions to use when creating a directory for storing the
-+** lock proxy files, only used when LOCKPROXYDIR is not set.
-+**
-+**
-+** As mentioned above, when compiled with SQLITE_PREFER_PROXY_LOCKING,
-+** setting the environment variable SQLITE_FORCE_PROXY_LOCKING to 1 will
-+** force proxy locking to be used for every database file opened, and 0
-+** will force automatic proxy locking to be disabled for all database
-+** files (explicity calling the SQLITE_SET_LOCKPROXYFILE pragma or
-+** sqlite_file_control API is not affected by SQLITE_FORCE_PROXY_LOCKING).
-+*/
-
- /*
--** WinCE lacks native support for file locking so we have to fake it
--** with some code of our own.
-+** Proxy locking is only available on MacOSX
- */
--#if SQLITE_OS_WINCE
--typedef struct winceLock {
-- int nReaders; /* Number of reader locks obtained */
-- BOOL bPending; /* Indicates a pending lock has been obtained */
-- BOOL bReserved; /* Indicates a reserved lock has been obtained */
-- BOOL bExclusive; /* Indicates an exclusive lock has been obtained */
--} winceLock;
--#endif
-+#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
-
- /*
--** The winFile structure is a subclass of sqlite3_file* specific to the win32
--** portability layer.
-+** The proxyLockingContext has the path and file structures for the remote
-+** and local proxy files in it
- */
--typedef struct winFile winFile;
--struct winFile {
-- const sqlite3_io_methods *pMethod; /*** Must be first ***/
-- sqlite3_vfs *pVfs; /* The VFS used to open this file */
-- HANDLE h; /* Handle for accessing the file */
-- u8 locktype; /* Type of lock currently held on this file */
-- short sharedLockByte; /* Randomly chosen byte used as a shared lock */
-- u8 ctrlFlags; /* Flags. See WINFILE_* below */
-- DWORD lastErrno; /* The Windows errno from the last I/O error */
--#ifndef SQLITE_OMIT_WAL
-- winShm *pShm; /* Instance of shared memory on this file */
--#endif
-- const char *zPath; /* Full pathname of this file */
-- int szChunk; /* Chunk size configured by FCNTL_CHUNK_SIZE */
--#if SQLITE_OS_WINCE
-- LPWSTR zDeleteOnClose; /* Name of file to delete when closing */
-- HANDLE hMutex; /* Mutex used to control access to shared lock */
-- HANDLE hShared; /* Shared memory segment used for locking */
-- winceLock local; /* Locks obtained by this instance of winFile */
-- winceLock *shared; /* Global shared lock memory for the file */
--#endif
--#if SQLITE_MAX_MMAP_SIZE>0
-- int nFetchOut; /* Number of outstanding xFetch references */
-- HANDLE hMap; /* Handle for accessing memory mapping */
-- void *pMapRegion; /* Area memory mapped */
-- sqlite3_int64 mmapSize; /* Usable size of mapped region */
-- sqlite3_int64 mmapSizeActual; /* Actual size of mapped region */
-- sqlite3_int64 mmapSizeMax; /* Configured FCNTL_MMAP_SIZE value */
--#endif
-+typedef struct proxyLockingContext proxyLockingContext;
-+struct proxyLockingContext {
-+ unixFile *conchFile; /* Open conch file */
-+ char *conchFilePath; /* Name of the conch file */
-+ unixFile *lockProxy; /* Open proxy lock file */
-+ char *lockProxyPath; /* Name of the proxy lock file */
-+ char *dbPath; /* Name of the open file */
-+ int conchHeld; /* 1 if the conch is held, -1 if lockless */
-+ void *oldLockingContext; /* Original lockingcontext to restore on close */
-+ sqlite3_io_methods const *pOldMethod; /* Original I/O methods for close */
- };
-
--/*
--** Allowed values for winFile.ctrlFlags
-+/*
-+** The proxy lock file path for the database at dbPath is written into lPath,
-+** which must point to valid, writable memory large enough for a maxLen length
-+** file path.
- */
--#define WINFILE_RDONLY 0x02 /* Connection is read only */
--#define WINFILE_PERSIST_WAL 0x04 /* Persistent WAL mode */
--#define WINFILE_PSOW 0x10 /* SQLITE_IOCAP_POWERSAFE_OVERWRITE */
-+static int proxyGetLockPath(const char *dbPath, char *lPath, size_t maxLen){
-+ int len;
-+ int dbLen;
-+ int i;
-
--/*
-- * The size of the buffer used by sqlite3_win32_write_debug().
-- */
--#ifndef SQLITE_WIN32_DBG_BUF_SIZE
--# define SQLITE_WIN32_DBG_BUF_SIZE ((int)(4096-sizeof(DWORD)))
-+#ifdef LOCKPROXYDIR
-+ len = strlcpy(lPath, LOCKPROXYDIR, maxLen);
-+#else
-+# ifdef _CS_DARWIN_USER_TEMP_DIR
-+ {
-+ if( !confstr(_CS_DARWIN_USER_TEMP_DIR, lPath, maxLen) ){
-+ OSTRACE(("GETLOCKPATH failed %s errno=%d pid=%d\n",
-+ lPath, errno, getpid()));
-+ return SQLITE_IOERR_LOCK;
-+ }
-+ len = strlcat(lPath, "sqliteplocks", maxLen);
-+ }
-+# else
-+ len = strlcpy(lPath, "/tmp/", maxLen);
-+# endif
- #endif
-
--/*
-- * The value used with sqlite3_win32_set_directory() to specify that
-- * the data directory should be changed.
-- */
--#ifndef SQLITE_WIN32_DATA_DIRECTORY_TYPE
--# define SQLITE_WIN32_DATA_DIRECTORY_TYPE (1)
--#endif
-+ if( lPath[len-1]!='/' ){
-+ len = strlcat(lPath, "/", maxLen);
-+ }
-+
-+ /* transform the db path to a unique cache name */
-+ dbLen = (int)strlen(dbPath);
-+ for( i=0; i<dbLen && (i+len+7)<(int)maxLen; i++){
-+ char c = dbPath[i];
-+ lPath[i+len] = (c=='/')?'_':c;
-+ }
-+ lPath[i+len]='\0';
-+ strlcat(lPath, ":auto:", maxLen);
-+ OSTRACE(("GETLOCKPATH proxy lock path=%s pid=%d\n", lPath, getpid()));
-+ return SQLITE_OK;
-+}
-
--/*
-- * The value used with sqlite3_win32_set_directory() to specify that
-- * the temporary directory should be changed.
-+/*
-+ ** Creates the lock file and any missing directories in lockPath
- */
--#ifndef SQLITE_WIN32_TEMP_DIRECTORY_TYPE
--# define SQLITE_WIN32_TEMP_DIRECTORY_TYPE (2)
--#endif
-+static int proxyCreateLockPath(const char *lockPath){
-+ int i, len;
-+ char buf[MAXPATHLEN];
-+ int start = 0;
-+
-+ assert(lockPath!=NULL);
-+ /* try to create all the intermediate directories */
-+ len = (int)strlen(lockPath);
-+ buf[0] = lockPath[0];
-+ for( i=1; i<len; i++ ){
-+ if( lockPath[i] == '/' && (i - start > 0) ){
-+ /* only mkdir if leaf dir != "." or "/" or ".." */
-+ if( i-start>2 || (i-start==1 && buf[start] != '.' && buf[start] != '/')
-+ || (i-start==2 && buf[start] != '.' && buf[start+1] != '.') ){
-+ buf[i]='\0';
-+ if( osMkdir(buf, SQLITE_DEFAULT_PROXYDIR_PERMISSIONS) ){
-+ int err=errno;
-+ if( err!=EEXIST ) {
-+ OSTRACE(("CREATELOCKPATH FAILED creating %s, "
-+ "'%s' proxy lock path=%s pid=%d\n",
-+ buf, strerror(err), lockPath, getpid()));
-+ return err;
-+ }
-+ }
-+ }
-+ start=i+1;
-+ }
-+ buf[i] = lockPath[i];
-+ }
-+ OSTRACE(("CREATELOCKPATH proxy lock path=%s pid=%d\n", lockPath, getpid()));
-+ return 0;
-+}
-
- /*
-- * If compiled with SQLITE_WIN32_MALLOC on Windows, we will use the
-- * various Win32 API heap functions instead of our own.
-- */
--#ifdef SQLITE_WIN32_MALLOC
-+** Create a new VFS file descriptor (stored in memory obtained from
-+** sqlite3_malloc) and open the file named "path" in the file descriptor.
-+**
-+** The caller is responsible not only for closing the file descriptor
-+** but also for freeing the memory associated with the file descriptor.
-+*/
-+static int proxyCreateUnixFile(
-+ const char *path, /* path for the new unixFile */
-+ unixFile **ppFile, /* unixFile created and returned by ref */
-+ int islockfile /* if non zero missing dirs will be created */
-+) {
-+ int fd = -1;
-+ unixFile *pNew;
-+ int rc = SQLITE_OK;
-+ int openFlags = O_RDWR | O_CREAT;
-+ sqlite3_vfs dummyVfs;
-+ int terrno = 0;
-+ UnixUnusedFd *pUnused = NULL;
-
--/*
-- * If this is non-zero, an isolated heap will be created by the native Win32
-- * allocator subsystem; otherwise, the default process heap will be used. This
-- * setting has no effect when compiling for WinRT. By default, this is enabled
-- * and an isolated heap will be created to store all allocated data.
-- *
-- ******************************************************************************
-- * WARNING: It is important to note that when this setting is non-zero and the
-- * winMemShutdown function is called (e.g. by the sqlite3_shutdown
-- * function), all data that was allocated using the isolated heap will
-- * be freed immediately and any attempt to access any of that freed
-- * data will almost certainly result in an immediate access violation.
-- ******************************************************************************
-- */
--#ifndef SQLITE_WIN32_HEAP_CREATE
--# define SQLITE_WIN32_HEAP_CREATE (TRUE)
-+ /* 1. first try to open/create the file
-+ ** 2. if that fails, and this is a lock file (not-conch), try creating
-+ ** the parent directories and then try again.
-+ ** 3. if that fails, try to open the file read-only
-+ ** otherwise return BUSY (if lock file) or CANTOPEN for the conch file
-+ */
-+ pUnused = findReusableFd(path, openFlags);
-+ if( pUnused ){
-+ fd = pUnused->fd;
-+ }else{
-+ pUnused = sqlite3_malloc(sizeof(*pUnused));
-+ if( !pUnused ){
-+ return SQLITE_NOMEM;
-+ }
-+ }
-+ if( fd<0 ){
-+ fd = robust_open(path, openFlags, 0);
-+ terrno = errno;
-+ if( fd<0 && errno==ENOENT && islockfile ){
-+ if( proxyCreateLockPath(path) == SQLITE_OK ){
-+ fd = robust_open(path, openFlags, 0);
-+ }
-+ }
-+ }
-+ if( fd<0 ){
-+ openFlags = O_RDONLY;
-+ fd = robust_open(path, openFlags, 0);
-+ terrno = errno;
-+ }
-+ if( fd<0 ){
-+ if( islockfile ){
-+ return SQLITE_BUSY;
-+ }
-+ switch (terrno) {
-+ case EACCES:
-+ return SQLITE_PERM;
-+ case EIO:
-+ return SQLITE_IOERR_LOCK; /* even though it is the conch */
-+ default:
-+ return SQLITE_CANTOPEN_BKPT;
-+ }
-+ }
-+
-+ pNew = (unixFile *)sqlite3_malloc(sizeof(*pNew));
-+ if( pNew==NULL ){
-+ rc = SQLITE_NOMEM;
-+ goto end_create_proxy;
-+ }
-+ memset(pNew, 0, sizeof(unixFile));
-+ pNew->openFlags = openFlags;
-+ memset(&dummyVfs, 0, sizeof(dummyVfs));
-+ dummyVfs.pAppData = (void*)&autolockIoFinder;
-+ dummyVfs.zName = "dummy";
-+ pUnused->fd = fd;
-+ pUnused->flags = openFlags;
-+ pNew->pUnused = pUnused;
-+
-+ rc = fillInUnixFile(&dummyVfs, fd, (sqlite3_file*)pNew, path, 0);
-+ if( rc==SQLITE_OK ){
-+ *ppFile = pNew;
-+ return SQLITE_OK;
-+ }
-+end_create_proxy:
-+ robust_close(pNew, fd, __LINE__);
-+ sqlite3_free(pNew);
-+ sqlite3_free(pUnused);
-+ return rc;
-+}
-+
-+#ifdef SQLITE_TEST
-+/* simulate multiple hosts by creating unique hostid file paths */
-+SQLITE_API int sqlite3_hostid_num = 0;
- #endif
-
--/*
-- * The initial size of the Win32-specific heap. This value may be zero.
-- */
--#ifndef SQLITE_WIN32_HEAP_INIT_SIZE
--# define SQLITE_WIN32_HEAP_INIT_SIZE ((SQLITE_DEFAULT_CACHE_SIZE) * \
-- (SQLITE_DEFAULT_PAGE_SIZE) + 4194304)
-+#define PROXY_HOSTIDLEN 16 /* conch file host id length */
-+
-+/* Not always defined in the headers as it ought to be */
-+extern int gethostuuid(uuid_t id, const struct timespec *wait);
-+
-+/* get the host ID via gethostuuid(), pHostID must point to PROXY_HOSTIDLEN
-+** bytes of writable memory.
-+*/
-+static int proxyGetHostID(unsigned char *pHostID, int *pError){
-+ assert(PROXY_HOSTIDLEN == sizeof(uuid_t));
-+ memset(pHostID, 0, PROXY_HOSTIDLEN);
-+#if defined(__MAX_OS_X_VERSION_MIN_REQUIRED)\
-+ && __MAC_OS_X_VERSION_MIN_REQUIRED<1050
-+ {
-+ static const struct timespec timeout = {1, 0}; /* 1 sec timeout */
-+ if( gethostuuid(pHostID, &timeout) ){
-+ int err = errno;
-+ if( pError ){
-+ *pError = err;
-+ }
-+ return SQLITE_IOERR;
-+ }
-+ }
-+#else
-+ UNUSED_PARAMETER(pError);
- #endif
--
--/*
-- * The maximum size of the Win32-specific heap. This value may be zero.
-- */
--#ifndef SQLITE_WIN32_HEAP_MAX_SIZE
--# define SQLITE_WIN32_HEAP_MAX_SIZE (0)
-+#ifdef SQLITE_TEST
-+ /* simulate multiple hosts by creating unique hostid file paths */
-+ if( sqlite3_hostid_num != 0){
-+ pHostID[0] = (char)(pHostID[0] + (char)(sqlite3_hostid_num & 0xFF));
-+ }
- #endif
-+
-+ return SQLITE_OK;
-+}
-
--/*
-- * The extra flags to use in calls to the Win32 heap APIs. This value may be
-- * zero for the default behavior.
-+/* The conch file contains the header, host id and lock file path
- */
--#ifndef SQLITE_WIN32_HEAP_FLAGS
--# define SQLITE_WIN32_HEAP_FLAGS (0)
--#endif
-+#define PROXY_CONCHVERSION 2 /* 1-byte header, 16-byte host id, path */
-+#define PROXY_HEADERLEN 1 /* conch file header length */
-+#define PROXY_PATHINDEX (PROXY_HEADERLEN+PROXY_HOSTIDLEN)
-+#define PROXY_MAXCONCHLEN (PROXY_HEADERLEN+PROXY_HOSTIDLEN+MAXPATHLEN)
-
--/*
--** The winMemData structure stores information required by the Win32-specific
--** sqlite3_mem_methods implementation.
-+/*
-+** Takes an open conch file, copies the contents to a new path and then moves
-+** it back. The newly created file's file descriptor is assigned to the
-+** conch file structure and finally the original conch file descriptor is
-+** closed. Returns zero if successful.
- */
--typedef struct winMemData winMemData;
--struct winMemData {
--#ifndef NDEBUG
-- u32 magic; /* Magic number to detect structure corruption. */
--#endif
-- HANDLE hHeap; /* The handle to our heap. */
-- BOOL bOwned; /* Do we own the heap (i.e. destroy it on shutdown)? */
--};
-+static int proxyBreakConchLock(unixFile *pFile, uuid_t myHostID){
-+ proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext;
-+ unixFile *conchFile = pCtx->conchFile;
-+ char tPath[MAXPATHLEN];
-+ char buf[PROXY_MAXCONCHLEN];
-+ char *cPath = pCtx->conchFilePath;
-+ size_t readLen = 0;
-+ size_t pathLen = 0;
-+ char errmsg[64] = "";
-+ int fd = -1;
-+ int rc = -1;
-+ UNUSED_PARAMETER(myHostID);
-
--#ifndef NDEBUG
--#define WINMEM_MAGIC 0x42b2830b
--#endif
-+ /* create a new path by replace the trailing '-conch' with '-break' */
-+ pathLen = strlcpy(tPath, cPath, MAXPATHLEN);
-+ if( pathLen>MAXPATHLEN || pathLen<6 ||
-+ (strlcpy(&tPath[pathLen-5], "break", 6) != 5) ){
-+ sqlite3_snprintf(sizeof(errmsg),errmsg,"path error (len %d)",(int)pathLen);
-+ goto end_breaklock;
-+ }
-+ /* read the conch content */
-+ readLen = osPread(conchFile->h, buf, PROXY_MAXCONCHLEN, 0);
-+ if( readLen<PROXY_PATHINDEX ){
-+ sqlite3_snprintf(sizeof(errmsg),errmsg,"read error (len %d)",(int)readLen);
-+ goto end_breaklock;
-+ }
-+ /* write it out to the temporary break file */
-+ fd = robust_open(tPath, (O_RDWR|O_CREAT|O_EXCL), 0);
-+ if( fd<0 ){
-+ sqlite3_snprintf(sizeof(errmsg), errmsg, "create failed (%d)", errno);
-+ goto end_breaklock;
-+ }
-+ if( osPwrite(fd, buf, readLen, 0) != (ssize_t)readLen ){
-+ sqlite3_snprintf(sizeof(errmsg), errmsg, "write failed (%d)", errno);
-+ goto end_breaklock;
-+ }
-+ if( rename(tPath, cPath) ){
-+ sqlite3_snprintf(sizeof(errmsg), errmsg, "rename failed (%d)", errno);
-+ goto end_breaklock;
-+ }
-+ rc = 0;
-+ fprintf(stderr, "broke stale lock on %s\n", cPath);
-+ robust_close(pFile, conchFile->h, __LINE__);
-+ conchFile->h = fd;
-+ conchFile->openFlags = O_RDWR | O_CREAT;
-
--static struct winMemData win_mem_data = {
--#ifndef NDEBUG
-- WINMEM_MAGIC,
--#endif
-- NULL, FALSE
--};
-+end_breaklock:
-+ if( rc ){
-+ if( fd>=0 ){
-+ osUnlink(tPath);
-+ robust_close(pFile, fd, __LINE__);
-+ }
-+ fprintf(stderr, "failed to break stale lock on %s, %s\n", cPath, errmsg);
-+ }
-+ return rc;
-+}
-
--#ifndef NDEBUG
--#define winMemAssertMagic() assert( win_mem_data.magic==WINMEM_MAGIC )
--#else
--#define winMemAssertMagic()
--#endif
-+/* Take the requested lock on the conch file and break a stale lock if the
-+** host id matches.
-+*/
-+static int proxyConchLock(unixFile *pFile, uuid_t myHostID, int lockType){
-+ proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext;
-+ unixFile *conchFile = pCtx->conchFile;
-+ int rc = SQLITE_OK;
-+ int nTries = 0;
-+ struct timespec conchModTime;
-+
-+ memset(&conchModTime, 0, sizeof(conchModTime));
-+ do {
-+ rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, lockType);
-+ nTries ++;
-+ if( rc==SQLITE_BUSY ){
-+ /* If the lock failed (busy):
-+ * 1st try: get the mod time of the conch, wait 0.5s and try again.
-+ * 2nd try: fail if the mod time changed or host id is different, wait
-+ * 10 sec and try again
-+ * 3rd try: break the lock unless the mod time has changed.
-+ */
-+ struct stat buf;
-+ if( osFstat(conchFile->h, &buf) ){
-+ pFile->lastErrno = errno;
-+ return SQLITE_IOERR_LOCK;
-+ }
-+
-+ if( nTries==1 ){
-+ conchModTime = buf.st_mtimespec;
-+ usleep(500000); /* wait 0.5 sec and try the lock again*/
-+ continue;
-+ }
-
--#define winMemGetHeap() win_mem_data.hHeap
-+ assert( nTries>1 );
-+ if( conchModTime.tv_sec != buf.st_mtimespec.tv_sec ||
-+ conchModTime.tv_nsec != buf.st_mtimespec.tv_nsec ){
-+ return SQLITE_BUSY;
-+ }
-+
-+ if( nTries==2 ){
-+ char tBuf[PROXY_MAXCONCHLEN];
-+ int len = osPread(conchFile->h, tBuf, PROXY_MAXCONCHLEN, 0);
-+ if( len<0 ){
-+ pFile->lastErrno = errno;
-+ return SQLITE_IOERR_LOCK;
-+ }
-+ if( len>PROXY_PATHINDEX && tBuf[0]==(char)PROXY_CONCHVERSION){
-+ /* don't break the lock if the host id doesn't match */
-+ if( 0!=memcmp(&tBuf[PROXY_HEADERLEN], myHostID, PROXY_HOSTIDLEN) ){
-+ return SQLITE_BUSY;
-+ }
-+ }else{
-+ /* don't break the lock on short read or a version mismatch */
-+ return SQLITE_BUSY;
-+ }
-+ usleep(10000000); /* wait 10 sec and try the lock again */
-+ continue;
-+ }
-+
-+ assert( nTries==3 );
-+ if( 0==proxyBreakConchLock(pFile, myHostID) ){
-+ rc = SQLITE_OK;
-+ if( lockType==EXCLUSIVE_LOCK ){
-+ rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, SHARED_LOCK);
-+ }
-+ if( !rc ){
-+ rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, lockType);
-+ }
-+ }
-+ }
-+ } while( rc==SQLITE_BUSY && nTries<3 );
-+
-+ return rc;
-+}
-
--static void *winMemMalloc(int nBytes);
--static void winMemFree(void *pPrior);
--static void *winMemRealloc(void *pPrior, int nBytes);
--static int winMemSize(void *p);
--static int winMemRoundup(int n);
--static int winMemInit(void *pAppData);
--static void winMemShutdown(void *pAppData);
-+/* Takes the conch by taking a shared lock and read the contents conch, if
-+** lockPath is non-NULL, the host ID and lock file path must match. A NULL
-+** lockPath means that the lockPath in the conch file will be used if the
-+** host IDs match, or a new lock path will be generated automatically
-+** and written to the conch file.
-+*/
-+static int proxyTakeConch(unixFile *pFile){
-+ proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext;
-+
-+ if( pCtx->conchHeld!=0 ){
-+ return SQLITE_OK;
-+ }else{
-+ unixFile *conchFile = pCtx->conchFile;
-+ uuid_t myHostID;
-+ int pError = 0;
-+ char readBuf[PROXY_MAXCONCHLEN];
-+ char lockPath[MAXPATHLEN];
-+ char *tempLockPath = NULL;
-+ int rc = SQLITE_OK;
-+ int createConch = 0;
-+ int hostIdMatch = 0;
-+ int readLen = 0;
-+ int tryOldLockPath = 0;
-+ int forceNewLockPath = 0;
-+
-+ OSTRACE(("TAKECONCH %d for %s pid=%d\n", conchFile->h,
-+ (pCtx->lockProxyPath ? pCtx->lockProxyPath : ":auto:"), getpid()));
-
--SQLITE_PRIVATE const sqlite3_mem_methods *sqlite3MemGetWin32(void);
--#endif /* SQLITE_WIN32_MALLOC */
-+ rc = proxyGetHostID(myHostID, &pError);
-+ if( (rc&0xff)==SQLITE_IOERR ){
-+ pFile->lastErrno = pError;
-+ goto end_takeconch;
-+ }
-+ rc = proxyConchLock(pFile, myHostID, SHARED_LOCK);
-+ if( rc!=SQLITE_OK ){
-+ goto end_takeconch;
-+ }
-+ /* read the existing conch file */
-+ readLen = seekAndRead((unixFile*)conchFile, 0, readBuf, PROXY_MAXCONCHLEN);
-+ if( readLen<0 ){
-+ /* I/O error: lastErrno set by seekAndRead */
-+ pFile->lastErrno = conchFile->lastErrno;
-+ rc = SQLITE_IOERR_READ;
-+ goto end_takeconch;
-+ }else if( readLen<=(PROXY_HEADERLEN+PROXY_HOSTIDLEN) ||
-+ readBuf[0]!=(char)PROXY_CONCHVERSION ){
-+ /* a short read or version format mismatch means we need to create a new
-+ ** conch file.
-+ */
-+ createConch = 1;
-+ }
-+ /* if the host id matches and the lock path already exists in the conch
-+ ** we'll try to use the path there, if we can't open that path, we'll
-+ ** retry with a new auto-generated path
-+ */
-+ do { /* in case we need to try again for an :auto: named lock file */
-
--/*
--** The following variable is (normally) set once and never changes
--** thereafter. It records whether the operating system is Win9x
--** or WinNT.
--**
--** 0: Operating system unknown.
--** 1: Operating system is Win9x.
--** 2: Operating system is WinNT.
--**
--** In order to facilitate testing on a WinNT system, the test fixture
--** can manually set this value to 1 to emulate Win98 behavior.
--*/
--#ifdef SQLITE_TEST
--SQLITE_API int sqlite3_os_type = 0;
-+ if( !createConch && !forceNewLockPath ){
-+ hostIdMatch = !memcmp(&readBuf[PROXY_HEADERLEN], myHostID,
-+ PROXY_HOSTIDLEN);
-+ /* if the conch has data compare the contents */
-+ if( !pCtx->lockProxyPath ){
-+ /* for auto-named local lock file, just check the host ID and we'll
-+ ** use the local lock file path that's already in there
-+ */
-+ if( hostIdMatch ){
-+ size_t pathLen = (readLen - PROXY_PATHINDEX);
-+
-+ if( pathLen>=MAXPATHLEN ){
-+ pathLen=MAXPATHLEN-1;
-+ }
-+ memcpy(lockPath, &readBuf[PROXY_PATHINDEX], pathLen);
-+ lockPath[pathLen] = 0;
-+ tempLockPath = lockPath;
-+ tryOldLockPath = 1;
-+ /* create a copy of the lock path if the conch is taken */
-+ goto end_takeconch;
-+ }
-+ }else if( hostIdMatch
-+ && !strncmp(pCtx->lockProxyPath, &readBuf[PROXY_PATHINDEX],
-+ readLen-PROXY_PATHINDEX)
-+ ){
-+ /* conch host and lock path match */
-+ goto end_takeconch;
-+ }
-+ }
-+
-+ /* if the conch isn't writable and doesn't match, we can't take it */
-+ if( (conchFile->openFlags&O_RDWR) == 0 ){
-+ rc = SQLITE_BUSY;
-+ goto end_takeconch;
-+ }
-+
-+ /* either the conch didn't match or we need to create a new one */
-+ if( !pCtx->lockProxyPath ){
-+ proxyGetLockPath(pCtx->dbPath, lockPath, MAXPATHLEN);
-+ tempLockPath = lockPath;
-+ /* create a copy of the lock path _only_ if the conch is taken */
-+ }
-+
-+ /* update conch with host and path (this will fail if other process
-+ ** has a shared lock already), if the host id matches, use the big
-+ ** stick.
-+ */
-+ futimes(conchFile->h, NULL);
-+ if( hostIdMatch && !createConch ){
-+ if( conchFile->pInode && conchFile->pInode->nShared>1 ){
-+ /* We are trying for an exclusive lock but another thread in this
-+ ** same process is still holding a shared lock. */
-+ rc = SQLITE_BUSY;
-+ } else {
-+ rc = proxyConchLock(pFile, myHostID, EXCLUSIVE_LOCK);
-+ }
-+ }else{
-+ rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, EXCLUSIVE_LOCK);
-+ }
-+ if( rc==SQLITE_OK ){
-+ char writeBuffer[PROXY_MAXCONCHLEN];
-+ int writeSize = 0;
-+
-+ writeBuffer[0] = (char)PROXY_CONCHVERSION;
-+ memcpy(&writeBuffer[PROXY_HEADERLEN], myHostID, PROXY_HOSTIDLEN);
-+ if( pCtx->lockProxyPath!=NULL ){
-+ strlcpy(&writeBuffer[PROXY_PATHINDEX], pCtx->lockProxyPath, MAXPATHLEN);
-+ }else{
-+ strlcpy(&writeBuffer[PROXY_PATHINDEX], tempLockPath, MAXPATHLEN);
-+ }
-+ writeSize = PROXY_PATHINDEX + strlen(&writeBuffer[PROXY_PATHINDEX]);
-+ robust_ftruncate(conchFile->h, writeSize);
-+ rc = unixWrite((sqlite3_file *)conchFile, writeBuffer, writeSize, 0);
-+ fsync(conchFile->h);
-+ /* If we created a new conch file (not just updated the contents of a
-+ ** valid conch file), try to match the permissions of the database
-+ */
-+ if( rc==SQLITE_OK && createConch ){
-+ struct stat buf;
-+ int err = osFstat(pFile->h, &buf);
-+ if( err==0 ){
-+ mode_t cmode = buf.st_mode&(S_IRUSR|S_IWUSR | S_IRGRP|S_IWGRP |
-+ S_IROTH|S_IWOTH);
-+ /* try to match the database file R/W permissions, ignore failure */
-+#ifndef SQLITE_PROXY_DEBUG
-+ osFchmod(conchFile->h, cmode);
- #else
--static int sqlite3_os_type = 0;
--#endif
--
--#ifndef SYSCALL
--# define SYSCALL sqlite3_syscall_ptr
-+ do{
-+ rc = osFchmod(conchFile->h, cmode);
-+ }while( rc==(-1) && errno==EINTR );
-+ if( rc!=0 ){
-+ int code = errno;
-+ fprintf(stderr, "fchmod %o FAILED with %d %s\n",
-+ cmode, code, strerror(code));
-+ } else {
-+ fprintf(stderr, "fchmod %o SUCCEDED\n",cmode);
-+ }
-+ }else{
-+ int code = errno;
-+ fprintf(stderr, "STAT FAILED[%d] with %d %s\n",
-+ err, code, strerror(code));
- #endif
-+ }
-+ }
-+ }
-+ conchFile->pMethod->xUnlock((sqlite3_file*)conchFile, SHARED_LOCK);
-+
-+ end_takeconch:
-+ OSTRACE(("TRANSPROXY: CLOSE %d\n", pFile->h));
-+ if( rc==SQLITE_OK && pFile->openFlags ){
-+ int fd;
-+ if( pFile->h>=0 ){
-+ robust_close(pFile, pFile->h, __LINE__);
-+ }
-+ pFile->h = -1;
-+ fd = robust_open(pCtx->dbPath, pFile->openFlags, 0);
-+ OSTRACE(("TRANSPROXY: OPEN %d\n", fd));
-+ if( fd>=0 ){
-+ pFile->h = fd;
-+ }else{
-+ rc=SQLITE_CANTOPEN_BKPT; /* SQLITE_BUSY? proxyTakeConch called
-+ during locking */
-+ }
-+ }
-+ if( rc==SQLITE_OK && !pCtx->lockProxy ){
-+ char *path = tempLockPath ? tempLockPath : pCtx->lockProxyPath;
-+ rc = proxyCreateUnixFile(path, &pCtx->lockProxy, 1);
-+ if( rc!=SQLITE_OK && rc!=SQLITE_NOMEM && tryOldLockPath ){
-+ /* we couldn't create the proxy lock file with the old lock file path
-+ ** so try again via auto-naming
-+ */
-+ forceNewLockPath = 1;
-+ tryOldLockPath = 0;
-+ continue; /* go back to the do {} while start point, try again */
-+ }
-+ }
-+ if( rc==SQLITE_OK ){
-+ /* Need to make a copy of path if we extracted the value
-+ ** from the conch file or the path was allocated on the stack
-+ */
-+ if( tempLockPath ){
-+ pCtx->lockProxyPath = sqlite3DbStrDup(0, tempLockPath);
-+ if( !pCtx->lockProxyPath ){
-+ rc = SQLITE_NOMEM;
-+ }
-+ }
-+ }
-+ if( rc==SQLITE_OK ){
-+ pCtx->conchHeld = 1;
-+
-+ if( pCtx->lockProxy->pMethod == &afpIoMethods ){
-+ afpLockingContext *afpCtx;
-+ afpCtx = (afpLockingContext *)pCtx->lockProxy->lockingContext;
-+ afpCtx->dbPath = pCtx->lockProxyPath;
-+ }
-+ } else {
-+ conchFile->pMethod->xUnlock((sqlite3_file*)conchFile, NO_LOCK);
-+ }
-+ OSTRACE(("TAKECONCH %d %s\n", conchFile->h,
-+ rc==SQLITE_OK?"ok":"failed"));
-+ return rc;
-+ } while (1); /* in case we need to retry the :auto: lock file -
-+ ** we should never get here except via the 'continue' call. */
-+ }
-+}
-
- /*
--** This function is not available on Windows CE or WinRT.
-- */
-+** If pFile holds a lock on a conch file, then release that lock.
-+*/
-+static int proxyReleaseConch(unixFile *pFile){
-+ int rc = SQLITE_OK; /* Subroutine return code */
-+ proxyLockingContext *pCtx; /* The locking context for the proxy lock */
-+ unixFile *conchFile; /* Name of the conch file */
-
--#if SQLITE_OS_WINCE || SQLITE_OS_WINRT
--# define osAreFileApisANSI() 1
--#endif
-+ pCtx = (proxyLockingContext *)pFile->lockingContext;
-+ conchFile = pCtx->conchFile;
-+ OSTRACE(("RELEASECONCH %d for %s pid=%d\n", conchFile->h,
-+ (pCtx->lockProxyPath ? pCtx->lockProxyPath : ":auto:"),
-+ getpid()));
-+ if( pCtx->conchHeld>0 ){
-+ rc = conchFile->pMethod->xUnlock((sqlite3_file*)conchFile, NO_LOCK);
-+ }
-+ pCtx->conchHeld = 0;
-+ OSTRACE(("RELEASECONCH %d %s\n", conchFile->h,
-+ (rc==SQLITE_OK ? "ok" : "failed")));
-+ return rc;
-+}
-
- /*
--** Many system calls are accessed through pointer-to-functions so that
--** they may be overridden at runtime to facilitate fault injection during
--** testing and sandboxing. The following array holds the names and pointers
--** to all overrideable system calls.
-+** Given the name of a database file, compute the name of its conch file.
-+** Store the conch filename in memory obtained from sqlite3_malloc().
-+** Make *pConchPath point to the new name. Return SQLITE_OK on success
-+** or SQLITE_NOMEM if unable to obtain memory.
-+**
-+** The caller is responsible for ensuring that the allocated memory
-+** space is eventually freed.
-+**
-+** *pConchPath is set to NULL if a memory allocation error occurs.
- */
--static struct win_syscall {
-- const char *zName; /* Name of the system call */
-- sqlite3_syscall_ptr pCurrent; /* Current value of the system call */
-- sqlite3_syscall_ptr pDefault; /* Default value */
--} aSyscall[] = {
--#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT
-- { "AreFileApisANSI", (SYSCALL)AreFileApisANSI, 0 },
--#else
-- { "AreFileApisANSI", (SYSCALL)0, 0 },
--#endif
--
--#ifndef osAreFileApisANSI
--#define osAreFileApisANSI ((BOOL(WINAPI*)(VOID))aSyscall[0].pCurrent)
--#endif
--
--#if SQLITE_OS_WINCE && defined(SQLITE_WIN32_HAS_WIDE)
-- { "CharLowerW", (SYSCALL)CharLowerW, 0 },
--#else
-- { "CharLowerW", (SYSCALL)0, 0 },
--#endif
-+static int proxyCreateConchPathname(char *dbPath, char **pConchPath){
-+ int i; /* Loop counter */
-+ int len = (int)strlen(dbPath); /* Length of database filename - dbPath */
-+ char *conchPath; /* buffer in which to construct conch name */
-
--#define osCharLowerW ((LPWSTR(WINAPI*)(LPWSTR))aSyscall[1].pCurrent)
-+ /* Allocate space for the conch filename and initialize the name to
-+ ** the name of the original database file. */
-+ *pConchPath = conchPath = (char *)sqlite3_malloc(len + 8);
-+ if( conchPath==0 ){
-+ return SQLITE_NOMEM;
-+ }
-+ memcpy(conchPath, dbPath, len+1);
-+
-+ /* now insert a "." before the last / character */
-+ for( i=(len-1); i>=0; i-- ){
-+ if( conchPath[i]=='/' ){
-+ i++;
-+ break;
-+ }
-+ }
-+ conchPath[i]='.';
-+ while ( i<len ){
-+ conchPath[i+1]=dbPath[i];
-+ i++;
-+ }
-
--#if SQLITE_OS_WINCE && defined(SQLITE_WIN32_HAS_WIDE)
-- { "CharUpperW", (SYSCALL)CharUpperW, 0 },
--#else
-- { "CharUpperW", (SYSCALL)0, 0 },
--#endif
-+ /* append the "-conch" suffix to the file */
-+ memcpy(&conchPath[i+1], "-conch", 7);
-+ assert( (int)strlen(conchPath) == len+7 );
-
--#define osCharUpperW ((LPWSTR(WINAPI*)(LPWSTR))aSyscall[2].pCurrent)
-+ return SQLITE_OK;
-+}
-
-- { "CloseHandle", (SYSCALL)CloseHandle, 0 },
-
--#define osCloseHandle ((BOOL(WINAPI*)(HANDLE))aSyscall[3].pCurrent)
-+/* Takes a fully configured proxy locking-style unix file and switches
-+** the local lock file path
-+*/
-+static int switchLockProxyPath(unixFile *pFile, const char *path) {
-+ proxyLockingContext *pCtx = (proxyLockingContext*)pFile->lockingContext;
-+ char *oldPath = pCtx->lockProxyPath;
-+ int rc = SQLITE_OK;
-
--#if defined(SQLITE_WIN32_HAS_ANSI)
-- { "CreateFileA", (SYSCALL)CreateFileA, 0 },
--#else
-- { "CreateFileA", (SYSCALL)0, 0 },
--#endif
-+ if( pFile->eFileLock!=NO_LOCK ){
-+ return SQLITE_BUSY;
-+ }
-
--#define osCreateFileA ((HANDLE(WINAPI*)(LPCSTR,DWORD,DWORD, \
-- LPSECURITY_ATTRIBUTES,DWORD,DWORD,HANDLE))aSyscall[4].pCurrent)
-+ /* nothing to do if the path is NULL, :auto: or matches the existing path */
-+ if( !path || path[0]=='\0' || !strcmp(path, ":auto:") ||
-+ (oldPath && !strncmp(oldPath, path, MAXPATHLEN)) ){
-+ return SQLITE_OK;
-+ }else{
-+ unixFile *lockProxy = pCtx->lockProxy;
-+ pCtx->lockProxy=NULL;
-+ pCtx->conchHeld = 0;
-+ if( lockProxy!=NULL ){
-+ rc=lockProxy->pMethod->xClose((sqlite3_file *)lockProxy);
-+ if( rc ) return rc;
-+ sqlite3_free(lockProxy);
-+ }
-+ sqlite3_free(oldPath);
-+ pCtx->lockProxyPath = sqlite3DbStrDup(0, path);
-+ }
-+
-+ return rc;
-+}
-
--#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE)
-- { "CreateFileW", (SYSCALL)CreateFileW, 0 },
--#else
-- { "CreateFileW", (SYSCALL)0, 0 },
-+/*
-+** pFile is a file that has been opened by a prior xOpen call. dbPath
-+** is a string buffer at least MAXPATHLEN+1 characters in size.
-+**
-+** This routine find the filename associated with pFile and writes it
-+** int dbPath.
-+*/
-+static int proxyGetDbPathForUnixFile(unixFile *pFile, char *dbPath){
-+#if defined(__APPLE__)
-+ if( pFile->pMethod == &afpIoMethods ){
-+ /* afp style keeps a reference to the db path in the filePath field
-+ ** of the struct */
-+ assert( (int)strlen((char*)pFile->lockingContext)<=MAXPATHLEN );
-+ strlcpy(dbPath, ((afpLockingContext *)pFile->lockingContext)->dbPath, MAXPATHLEN);
-+ } else
- #endif
-+ if( pFile->pMethod == &dotlockIoMethods ){
-+ /* dot lock style uses the locking context to store the dot lock
-+ ** file path */
-+ int len = strlen((char *)pFile->lockingContext) - strlen(DOTLOCK_SUFFIX);
-+ memcpy(dbPath, (char *)pFile->lockingContext, len + 1);
-+ }else{
-+ /* all other styles use the locking context to store the db file path */
-+ assert( strlen((char*)pFile->lockingContext)<=MAXPATHLEN );
-+ strlcpy(dbPath, (char *)pFile->lockingContext, MAXPATHLEN);
-+ }
-+ return SQLITE_OK;
-+}
-
--#define osCreateFileW ((HANDLE(WINAPI*)(LPCWSTR,DWORD,DWORD, \
-- LPSECURITY_ATTRIBUTES,DWORD,DWORD,HANDLE))aSyscall[5].pCurrent)
--
--#if (!SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_ANSI) && \
-- !defined(SQLITE_OMIT_WAL))
-- { "CreateFileMappingA", (SYSCALL)CreateFileMappingA, 0 },
--#else
-- { "CreateFileMappingA", (SYSCALL)0, 0 },
--#endif
-+/*
-+** Takes an already filled in unix file and alters it so all file locking
-+** will be performed on the local proxy lock file. The following fields
-+** are preserved in the locking context so that they can be restored and
-+** the unix structure properly cleaned up at close time:
-+** ->lockingContext
-+** ->pMethod
-+*/
-+static int proxyTransformUnixFile(unixFile *pFile, const char *path) {
-+ proxyLockingContext *pCtx;
-+ char dbPath[MAXPATHLEN+1]; /* Name of the database file */
-+ char *lockPath=NULL;
-+ int rc = SQLITE_OK;
-+
-+ if( pFile->eFileLock!=NO_LOCK ){
-+ return SQLITE_BUSY;
-+ }
-+ proxyGetDbPathForUnixFile(pFile, dbPath);
-+ if( !path || path[0]=='\0' || !strcmp(path, ":auto:") ){
-+ lockPath=NULL;
-+ }else{
-+ lockPath=(char *)path;
-+ }
-+
-+ OSTRACE(("TRANSPROXY %d for %s pid=%d\n", pFile->h,
-+ (lockPath ? lockPath : ":auto:"), getpid()));
-
--#define osCreateFileMappingA ((HANDLE(WINAPI*)(HANDLE,LPSECURITY_ATTRIBUTES, \
-- DWORD,DWORD,DWORD,LPCSTR))aSyscall[6].pCurrent)
-+ pCtx = sqlite3_malloc( sizeof(*pCtx) );
-+ if( pCtx==0 ){
-+ return SQLITE_NOMEM;
-+ }
-+ memset(pCtx, 0, sizeof(*pCtx));
-
--#if SQLITE_OS_WINCE || (!SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) && \
-- !defined(SQLITE_OMIT_WAL))
-- { "CreateFileMappingW", (SYSCALL)CreateFileMappingW, 0 },
--#else
-- { "CreateFileMappingW", (SYSCALL)0, 0 },
--#endif
-+ rc = proxyCreateConchPathname(dbPath, &pCtx->conchFilePath);
-+ if( rc==SQLITE_OK ){
-+ rc = proxyCreateUnixFile(pCtx->conchFilePath, &pCtx->conchFile, 0);
-+ if( rc==SQLITE_CANTOPEN && ((pFile->openFlags&O_RDWR) == 0) ){
-+ /* if (a) the open flags are not O_RDWR, (b) the conch isn't there, and
-+ ** (c) the file system is read-only, then enable no-locking access.
-+ ** Ugh, since O_RDONLY==0x0000 we test for !O_RDWR since unixOpen asserts
-+ ** that openFlags will have only one of O_RDONLY or O_RDWR.
-+ */
-+ struct statfs fsInfo;
-+ struct stat conchInfo;
-+ int goLockless = 0;
-
--#define osCreateFileMappingW ((HANDLE(WINAPI*)(HANDLE,LPSECURITY_ATTRIBUTES, \
-- DWORD,DWORD,DWORD,LPCWSTR))aSyscall[7].pCurrent)
-+ if( osStat(pCtx->conchFilePath, &conchInfo) == -1 ) {
-+ int err = errno;
-+ if( (err==ENOENT) && (statfs(dbPath, &fsInfo) != -1) ){
-+ goLockless = (fsInfo.f_flags&MNT_RDONLY) == MNT_RDONLY;
-+ }
-+ }
-+ if( goLockless ){
-+ pCtx->conchHeld = -1; /* read only FS/ lockless */
-+ rc = SQLITE_OK;
-+ }
-+ }
-+ }
-+ if( rc==SQLITE_OK && lockPath ){
-+ pCtx->lockProxyPath = sqlite3DbStrDup(0, lockPath);
-+ }
-
--#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE)
-- { "CreateMutexW", (SYSCALL)CreateMutexW, 0 },
--#else
-- { "CreateMutexW", (SYSCALL)0, 0 },
--#endif
-+ if( rc==SQLITE_OK ){
-+ pCtx->dbPath = sqlite3DbStrDup(0, dbPath);
-+ if( pCtx->dbPath==NULL ){
-+ rc = SQLITE_NOMEM;
-+ }
-+ }
-+ if( rc==SQLITE_OK ){
-+ /* all memory is allocated, proxys are created and assigned,
-+ ** switch the locking context and pMethod then return.
-+ */
-+ pCtx->oldLockingContext = pFile->lockingContext;
-+ pFile->lockingContext = pCtx;
-+ pCtx->pOldMethod = pFile->pMethod;
-+ pFile->pMethod = &proxyIoMethods;
-+ }else{
-+ if( pCtx->conchFile ){
-+ pCtx->conchFile->pMethod->xClose((sqlite3_file *)pCtx->conchFile);
-+ sqlite3_free(pCtx->conchFile);
-+ }
-+ sqlite3DbFree(0, pCtx->lockProxyPath);
-+ sqlite3_free(pCtx->conchFilePath);
-+ sqlite3_free(pCtx);
-+ }
-+ OSTRACE(("TRANSPROXY %d %s\n", pFile->h,
-+ (rc==SQLITE_OK ? "ok" : "failed")));
-+ return rc;
-+}
-
--#define osCreateMutexW ((HANDLE(WINAPI*)(LPSECURITY_ATTRIBUTES,BOOL, \
-- LPCWSTR))aSyscall[8].pCurrent)
-
--#if defined(SQLITE_WIN32_HAS_ANSI)
-- { "DeleteFileA", (SYSCALL)DeleteFileA, 0 },
--#else
-- { "DeleteFileA", (SYSCALL)0, 0 },
--#endif
-+/*
-+** This routine handles sqlite3_file_control() calls that are specific
-+** to proxy locking.
-+*/
-+static int proxyFileControl(sqlite3_file *id, int op, void *pArg){
-+ switch( op ){
-+ case SQLITE_GET_LOCKPROXYFILE: {
-+ unixFile *pFile = (unixFile*)id;
-+ if( pFile->pMethod == &proxyIoMethods ){
-+ proxyLockingContext *pCtx = (proxyLockingContext*)pFile->lockingContext;
-+ proxyTakeConch(pFile);
-+ if( pCtx->lockProxyPath ){
-+ *(const char **)pArg = pCtx->lockProxyPath;
-+ }else{
-+ *(const char **)pArg = ":auto: (not held)";
-+ }
-+ } else {
-+ *(const char **)pArg = NULL;
-+ }
-+ return SQLITE_OK;
-+ }
-+ case SQLITE_SET_LOCKPROXYFILE: {
-+ unixFile *pFile = (unixFile*)id;
-+ int rc = SQLITE_OK;
-+ int isProxyStyle = (pFile->pMethod == &proxyIoMethods);
-+ if( pArg==NULL || (const char *)pArg==0 ){
-+ if( isProxyStyle ){
-+ /* turn off proxy locking - not supported */
-+ rc = SQLITE_ERROR /*SQLITE_PROTOCOL? SQLITE_MISUSE?*/;
-+ }else{
-+ /* turn off proxy locking - already off - NOOP */
-+ rc = SQLITE_OK;
-+ }
-+ }else{
-+ const char *proxyPath = (const char *)pArg;
-+ if( isProxyStyle ){
-+ proxyLockingContext *pCtx =
-+ (proxyLockingContext*)pFile->lockingContext;
-+ if( !strcmp(pArg, ":auto:")
-+ || (pCtx->lockProxyPath &&
-+ !strncmp(pCtx->lockProxyPath, proxyPath, MAXPATHLEN))
-+ ){
-+ rc = SQLITE_OK;
-+ }else{
-+ rc = switchLockProxyPath(pFile, proxyPath);
-+ }
-+ }else{
-+ /* turn on proxy file locking */
-+ rc = proxyTransformUnixFile(pFile, proxyPath);
-+ }
-+ }
-+ return rc;
-+ }
-+ default: {
-+ assert( 0 ); /* The call assures that only valid opcodes are sent */
-+ }
-+ }
-+ /*NOTREACHED*/
-+ return SQLITE_ERROR;
-+}
-
--#define osDeleteFileA ((BOOL(WINAPI*)(LPCSTR))aSyscall[9].pCurrent)
-+/*
-+** Within this division (the proxying locking implementation) the procedures
-+** above this point are all utilities. The lock-related methods of the
-+** proxy-locking sqlite3_io_method object follow.
-+*/
-
--#if defined(SQLITE_WIN32_HAS_WIDE)
-- { "DeleteFileW", (SYSCALL)DeleteFileW, 0 },
--#else
-- { "DeleteFileW", (SYSCALL)0, 0 },
--#endif
-
--#define osDeleteFileW ((BOOL(WINAPI*)(LPCWSTR))aSyscall[10].pCurrent)
-+/*
-+** This routine checks if there is a RESERVED lock held on the specified
-+** file by this or any other process. If such a lock is held, set *pResOut
-+** to a non-zero value otherwise *pResOut is set to zero. The return value
-+** is set to SQLITE_OK unless an I/O error occurs during lock checking.
-+*/
-+static int proxyCheckReservedLock(sqlite3_file *id, int *pResOut) {
-+ unixFile *pFile = (unixFile*)id;
-+ int rc = proxyTakeConch(pFile);
-+ if( rc==SQLITE_OK ){
-+ proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext;
-+ if( pCtx->conchHeld>0 ){
-+ unixFile *proxy = pCtx->lockProxy;
-+ return proxy->pMethod->xCheckReservedLock((sqlite3_file*)proxy, pResOut);
-+ }else{ /* conchHeld < 0 is lockless */
-+ pResOut=0;
-+ }
-+ }
-+ return rc;
-+}
-
--#if SQLITE_OS_WINCE
-- { "FileTimeToLocalFileTime", (SYSCALL)FileTimeToLocalFileTime, 0 },
--#else
-- { "FileTimeToLocalFileTime", (SYSCALL)0, 0 },
--#endif
-+/*
-+** Lock the file with the lock specified by parameter eFileLock - one
-+** of the following:
-+**
-+** (1) SHARED_LOCK
-+** (2) RESERVED_LOCK
-+** (3) PENDING_LOCK
-+** (4) EXCLUSIVE_LOCK
-+**
-+** Sometimes when requesting one lock state, additional lock states
-+** are inserted in between. The locking might fail on one of the later
-+** transitions leaving the lock state different from what it started but
-+** still short of its goal. The following chart shows the allowed
-+** transitions and the inserted intermediate states:
-+**
-+** UNLOCKED -> SHARED
-+** SHARED -> RESERVED
-+** SHARED -> (PENDING) -> EXCLUSIVE
-+** RESERVED -> (PENDING) -> EXCLUSIVE
-+** PENDING -> EXCLUSIVE
-+**
-+** This routine will only increase a lock. Use the sqlite3OsUnlock()
-+** routine to lower a locking level.
-+*/
-+static int proxyLock(sqlite3_file *id, int eFileLock) {
-+ unixFile *pFile = (unixFile*)id;
-+ int rc = proxyTakeConch(pFile);
-+ if( rc==SQLITE_OK ){
-+ proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext;
-+ if( pCtx->conchHeld>0 ){
-+ unixFile *proxy = pCtx->lockProxy;
-+ rc = proxy->pMethod->xLock((sqlite3_file*)proxy, eFileLock);
-+ pFile->eFileLock = proxy->eFileLock;
-+ }else{
-+ /* conchHeld < 0 is lockless */
-+ }
-+ }
-+ return rc;
-+}
-
--#define osFileTimeToLocalFileTime ((BOOL(WINAPI*)(CONST FILETIME*, \
-- LPFILETIME))aSyscall[11].pCurrent)
-
--#if SQLITE_OS_WINCE
-- { "FileTimeToSystemTime", (SYSCALL)FileTimeToSystemTime, 0 },
--#else
-- { "FileTimeToSystemTime", (SYSCALL)0, 0 },
--#endif
-+/*
-+** Lower the locking level on file descriptor pFile to eFileLock. eFileLock
-+** must be either NO_LOCK or SHARED_LOCK.
-+**
-+** If the locking level of the file descriptor is already at or below
-+** the requested locking level, this routine is a no-op.
-+*/
-+static int proxyUnlock(sqlite3_file *id, int eFileLock) {
-+ unixFile *pFile = (unixFile*)id;
-+ int rc = proxyTakeConch(pFile);
-+ if( rc==SQLITE_OK ){
-+ proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext;
-+ if( pCtx->conchHeld>0 ){
-+ unixFile *proxy = pCtx->lockProxy;
-+ rc = proxy->pMethod->xUnlock((sqlite3_file*)proxy, eFileLock);
-+ pFile->eFileLock = proxy->eFileLock;
-+ }else{
-+ /* conchHeld < 0 is lockless */
-+ }
-+ }
-+ return rc;
-+}
-
--#define osFileTimeToSystemTime ((BOOL(WINAPI*)(CONST FILETIME*, \
-- LPSYSTEMTIME))aSyscall[12].pCurrent)
-+/*
-+** Close a file that uses proxy locks.
-+*/
-+static int proxyClose(sqlite3_file *id) {
-+ if( id ){
-+ unixFile *pFile = (unixFile*)id;
-+ proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext;
-+ unixFile *lockProxy = pCtx->lockProxy;
-+ unixFile *conchFile = pCtx->conchFile;
-+ int rc = SQLITE_OK;
-+
-+ if( lockProxy ){
-+ rc = lockProxy->pMethod->xUnlock((sqlite3_file*)lockProxy, NO_LOCK);
-+ if( rc ) return rc;
-+ rc = lockProxy->pMethod->xClose((sqlite3_file*)lockProxy);
-+ if( rc ) return rc;
-+ sqlite3_free(lockProxy);
-+ pCtx->lockProxy = 0;
-+ }
-+ if( conchFile ){
-+ if( pCtx->conchHeld ){
-+ rc = proxyReleaseConch(pFile);
-+ if( rc ) return rc;
-+ }
-+ rc = conchFile->pMethod->xClose((sqlite3_file*)conchFile);
-+ if( rc ) return rc;
-+ sqlite3_free(conchFile);
-+ }
-+ sqlite3DbFree(0, pCtx->lockProxyPath);
-+ sqlite3_free(pCtx->conchFilePath);
-+ sqlite3DbFree(0, pCtx->dbPath);
-+ /* restore the original locking context and pMethod then close it */
-+ pFile->lockingContext = pCtx->oldLockingContext;
-+ pFile->pMethod = pCtx->pOldMethod;
-+ sqlite3_free(pCtx);
-+ return pFile->pMethod->xClose(id);
-+ }
-+ return SQLITE_OK;
-+}
-
-- { "FlushFileBuffers", (SYSCALL)FlushFileBuffers, 0 },
-
--#define osFlushFileBuffers ((BOOL(WINAPI*)(HANDLE))aSyscall[13].pCurrent)
-
--#if defined(SQLITE_WIN32_HAS_ANSI)
-- { "FormatMessageA", (SYSCALL)FormatMessageA, 0 },
--#else
-- { "FormatMessageA", (SYSCALL)0, 0 },
--#endif
-+#endif /* defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE */
-+/*
-+** The proxy locking style is intended for use with AFP filesystems.
-+** And since AFP is only supported on MacOSX, the proxy locking is also
-+** restricted to MacOSX.
-+**
-+**
-+******************* End of the proxy lock implementation **********************
-+******************************************************************************/
-
--#define osFormatMessageA ((DWORD(WINAPI*)(DWORD,LPCVOID,DWORD,DWORD,LPSTR, \
-- DWORD,va_list*))aSyscall[14].pCurrent)
-+/*
-+** Initialize the operating system interface.
-+**
-+** This routine registers all VFS implementations for unix-like operating
-+** systems. This routine, and the sqlite3_os_end() routine that follows,
-+** should be the only routines in this file that are visible from other
-+** files.
-+**
-+** This routine is called once during SQLite initialization and by a
-+** single thread. The memory allocation and mutex subsystems have not
-+** necessarily been initialized when this routine is called, and so they
-+** should not be used.
-+*/
-+SQLITE_API int sqlite3_os_init(void){
-+ /*
-+ ** The following macro defines an initializer for an sqlite3_vfs object.
-+ ** The name of the VFS is NAME. The pAppData is a pointer to a pointer
-+ ** to the "finder" function. (pAppData is a pointer to a pointer because
-+ ** silly C90 rules prohibit a void* from being cast to a function pointer
-+ ** and so we have to go through the intermediate pointer to avoid problems
-+ ** when compiling with -pedantic-errors on GCC.)
-+ **
-+ ** The FINDER parameter to this macro is the name of the pointer to the
-+ ** finder-function. The finder-function returns a pointer to the
-+ ** sqlite_io_methods object that implements the desired locking
-+ ** behaviors. See the division above that contains the IOMETHODS
-+ ** macro for addition information on finder-functions.
-+ **
-+ ** Most finders simply return a pointer to a fixed sqlite3_io_methods
-+ ** object. But the "autolockIoFinder" available on MacOSX does a little
-+ ** more than that; it looks at the filesystem type that hosts the
-+ ** database file and tries to choose an locking method appropriate for
-+ ** that filesystem time.
-+ */
-+ #define UNIXVFS(VFSNAME, FINDER) { \
-+ 3, /* iVersion */ \
-+ sizeof(unixFile), /* szOsFile */ \
-+ MAX_PATHNAME, /* mxPathname */ \
-+ 0, /* pNext */ \
-+ VFSNAME, /* zName */ \
-+ (void*)&FINDER, /* pAppData */ \
-+ unixOpen, /* xOpen */ \
-+ unixDelete, /* xDelete */ \
-+ unixAccess, /* xAccess */ \
-+ unixFullPathname, /* xFullPathname */ \
-+ unixDlOpen, /* xDlOpen */ \
-+ unixDlError, /* xDlError */ \
-+ unixDlSym, /* xDlSym */ \
-+ unixDlClose, /* xDlClose */ \
-+ unixRandomness, /* xRandomness */ \
-+ unixSleep, /* xSleep */ \
-+ unixCurrentTime, /* xCurrentTime */ \
-+ unixGetLastError, /* xGetLastError */ \
-+ unixCurrentTimeInt64, /* xCurrentTimeInt64 */ \
-+ unixSetSystemCall, /* xSetSystemCall */ \
-+ unixGetSystemCall, /* xGetSystemCall */ \
-+ unixNextSystemCall, /* xNextSystemCall */ \
-+ }
-
--#if defined(SQLITE_WIN32_HAS_WIDE)
-- { "FormatMessageW", (SYSCALL)FormatMessageW, 0 },
-+ /*
-+ ** All default VFSes for unix are contained in the following array.
-+ **
-+ ** Note that the sqlite3_vfs.pNext field of the VFS object is modified
-+ ** by the SQLite core when the VFS is registered. So the following
-+ ** array cannot be const.
-+ */
-+ static sqlite3_vfs aVfs[] = {
-+#if SQLITE_ENABLE_LOCKING_STYLE && (OS_VXWORKS || defined(__APPLE__))
-+ UNIXVFS("unix", autolockIoFinder ),
- #else
-- { "FormatMessageW", (SYSCALL)0, 0 },
-+ UNIXVFS("unix", posixIoFinder ),
- #endif
--
--#define osFormatMessageW ((DWORD(WINAPI*)(DWORD,LPCVOID,DWORD,DWORD,LPWSTR, \
-- DWORD,va_list*))aSyscall[15].pCurrent)
--
--#if !defined(SQLITE_OMIT_LOAD_EXTENSION)
-- { "FreeLibrary", (SYSCALL)FreeLibrary, 0 },
--#else
-- { "FreeLibrary", (SYSCALL)0, 0 },
-+ UNIXVFS("unix-none", nolockIoFinder ),
-+ UNIXVFS("unix-dotfile", dotlockIoFinder ),
-+ UNIXVFS("unix-excl", posixIoFinder ),
-+#if OS_VXWORKS
-+ UNIXVFS("unix-namedsem", semIoFinder ),
-+#endif
-+#if SQLITE_ENABLE_LOCKING_STYLE
-+ UNIXVFS("unix-posix", posixIoFinder ),
-+#if !OS_VXWORKS
-+ UNIXVFS("unix-flock", flockIoFinder ),
- #endif
--
--#define osFreeLibrary ((BOOL(WINAPI*)(HMODULE))aSyscall[16].pCurrent)
--
-- { "GetCurrentProcessId", (SYSCALL)GetCurrentProcessId, 0 },
--
--#define osGetCurrentProcessId ((DWORD(WINAPI*)(VOID))aSyscall[17].pCurrent)
--
--#if !SQLITE_OS_WINCE && defined(SQLITE_WIN32_HAS_ANSI)
-- { "GetDiskFreeSpaceA", (SYSCALL)GetDiskFreeSpaceA, 0 },
--#else
-- { "GetDiskFreeSpaceA", (SYSCALL)0, 0 },
- #endif
--
--#define osGetDiskFreeSpaceA ((BOOL(WINAPI*)(LPCSTR,LPDWORD,LPDWORD,LPDWORD, \
-- LPDWORD))aSyscall[18].pCurrent)
--
--#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE)
-- { "GetDiskFreeSpaceW", (SYSCALL)GetDiskFreeSpaceW, 0 },
--#else
-- { "GetDiskFreeSpaceW", (SYSCALL)0, 0 },
-+#if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__)
-+ UNIXVFS("unix-afp", afpIoFinder ),
-+ UNIXVFS("unix-nfs", nfsIoFinder ),
-+ UNIXVFS("unix-proxy", proxyIoFinder ),
- #endif
-+ };
-+ unsigned int i; /* Loop counter */
-
--#define osGetDiskFreeSpaceW ((BOOL(WINAPI*)(LPCWSTR,LPDWORD,LPDWORD,LPDWORD, \
-- LPDWORD))aSyscall[19].pCurrent)
--
--#if defined(SQLITE_WIN32_HAS_ANSI)
-- { "GetFileAttributesA", (SYSCALL)GetFileAttributesA, 0 },
--#else
-- { "GetFileAttributesA", (SYSCALL)0, 0 },
--#endif
-+ /* Double-check that the aSyscall[] array has been constructed
-+ ** correctly. See ticket [bb3a86e890c8e96ab] */
-+ assert( ArraySize(aSyscall)==24 );
-
--#define osGetFileAttributesA ((DWORD(WINAPI*)(LPCSTR))aSyscall[20].pCurrent)
-+ /* Register all VFSes defined in the aVfs[] array */
-+ for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){
-+ sqlite3_vfs_register(&aVfs[i], i==0);
-+ }
-+ return SQLITE_OK;
-+}
-
--#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE)
-- { "GetFileAttributesW", (SYSCALL)GetFileAttributesW, 0 },
--#else
-- { "GetFileAttributesW", (SYSCALL)0, 0 },
--#endif
-+/*
-+** Shutdown the operating system interface.
-+**
-+** Some operating systems might need to do some cleanup in this routine,
-+** to release dynamically allocated objects. But not on unix.
-+** This routine is a no-op for unix.
-+*/
-+SQLITE_API int sqlite3_os_end(void){
-+ return SQLITE_OK;
-+}
-+
-+#endif /* SQLITE_OS_UNIX */
-
--#define osGetFileAttributesW ((DWORD(WINAPI*)(LPCWSTR))aSyscall[21].pCurrent)
-+/************** End of os_unix.c *********************************************/
-+/************** Begin file os_win.c ******************************************/
-+/*
-+** 2004 May 22
-+**
-+** The author disclaims copyright to this source code. In place of
-+** a legal notice, here is a blessing:
-+**
-+** May you do good and not evil.
-+** May you find forgiveness for yourself and forgive others.
-+** May you share freely, never taking more than you give.
-+**
-+******************************************************************************
-+**
-+** This file contains code that is specific to Windows.
-+*/
-+#if SQLITE_OS_WIN /* This file is used for Windows only */
-
--#if defined(SQLITE_WIN32_HAS_WIDE)
-- { "GetFileAttributesExW", (SYSCALL)GetFileAttributesExW, 0 },
--#else
-- { "GetFileAttributesExW", (SYSCALL)0, 0 },
-+#ifdef __CYGWIN__
-+# include <sys/cygwin.h>
- #endif
-
--#define osGetFileAttributesExW ((BOOL(WINAPI*)(LPCWSTR,GET_FILEEX_INFO_LEVELS, \
-- LPVOID))aSyscall[22].pCurrent)
-+/*
-+** Include code that is common to all os_*.c files
-+*/
-+/************** Include os_common.h in the middle of os_win.c ****************/
-+/************** Begin file os_common.h ***************************************/
-+/*
-+** 2004 May 22
-+**
-+** The author disclaims copyright to this source code. In place of
-+** a legal notice, here is a blessing:
-+**
-+** May you do good and not evil.
-+** May you find forgiveness for yourself and forgive others.
-+** May you share freely, never taking more than you give.
-+**
-+******************************************************************************
-+**
-+** This file contains macros and a little bit of code that is common to
-+** all of the platform-specific files (os_*.c) and is #included into those
-+** files.
-+**
-+** This file should be #included by the os_*.c files only. It is not a
-+** general purpose header file.
-+*/
-+#ifndef _OS_COMMON_H_
-+#define _OS_COMMON_H_
-
--#if !SQLITE_OS_WINRT
-- { "GetFileSize", (SYSCALL)GetFileSize, 0 },
--#else
-- { "GetFileSize", (SYSCALL)0, 0 },
-+/*
-+** At least two bugs have slipped in because we changed the MEMORY_DEBUG
-+** macro to SQLITE_DEBUG and some older makefiles have not yet made the
-+** switch. The following code should catch this problem at compile-time.
-+*/
-+#ifdef MEMORY_DEBUG
-+# error "The MEMORY_DEBUG macro is obsolete. Use SQLITE_DEBUG instead."
- #endif
-
--#define osGetFileSize ((DWORD(WINAPI*)(HANDLE,LPDWORD))aSyscall[23].pCurrent)
--
--#if !SQLITE_OS_WINCE && defined(SQLITE_WIN32_HAS_ANSI)
-- { "GetFullPathNameA", (SYSCALL)GetFullPathNameA, 0 },
-+#if defined(SQLITE_TEST) && defined(SQLITE_DEBUG)
-+# ifndef SQLITE_DEBUG_OS_TRACE
-+# define SQLITE_DEBUG_OS_TRACE 0
-+# endif
-+ int sqlite3OSTrace = SQLITE_DEBUG_OS_TRACE;
-+# define OSTRACE(X) if( sqlite3OSTrace ) sqlite3DebugPrintf X
- #else
-- { "GetFullPathNameA", (SYSCALL)0, 0 },
-+# define OSTRACE(X)
- #endif
-
--#define osGetFullPathNameA ((DWORD(WINAPI*)(LPCSTR,DWORD,LPSTR, \
-- LPSTR*))aSyscall[24].pCurrent)
-+/*
-+** Macros for performance tracing. Normally turned off. Only works
-+** on i486 hardware.
-+*/
-+#ifdef SQLITE_PERFORMANCE_TRACE
-
--#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE)
-- { "GetFullPathNameW", (SYSCALL)GetFullPathNameW, 0 },
--#else
-- { "GetFullPathNameW", (SYSCALL)0, 0 },
--#endif
-+/*
-+** hwtime.h contains inline assembler code for implementing
-+** high-performance timing routines.
-+*/
-+/************** Include hwtime.h in the middle of os_common.h ****************/
-+/************** Begin file hwtime.h ******************************************/
-+/*
-+** 2008 May 27
-+**
-+** The author disclaims copyright to this source code. In place of
-+** a legal notice, here is a blessing:
-+**
-+** May you do good and not evil.
-+** May you find forgiveness for yourself and forgive others.
-+** May you share freely, never taking more than you give.
-+**
-+******************************************************************************
-+**
-+** This file contains inline asm code for retrieving "high-performance"
-+** counters for x86 class CPUs.
-+*/
-+#ifndef _HWTIME_H_
-+#define _HWTIME_H_
-
--#define osGetFullPathNameW ((DWORD(WINAPI*)(LPCWSTR,DWORD,LPWSTR, \
-- LPWSTR*))aSyscall[25].pCurrent)
-+/*
-+** The following routine only works on pentium-class (or newer) processors.
-+** It uses the RDTSC opcode to read the cycle count value out of the
-+** processor and returns that value. This can be used for high-res
-+** profiling.
-+*/
-+#if (defined(__GNUC__) || defined(_MSC_VER)) && \
-+ (defined(i386) || defined(__i386__) || defined(_M_IX86))
-
-- { "GetLastError", (SYSCALL)GetLastError, 0 },
-+ #if defined(__GNUC__)
-
--#define osGetLastError ((DWORD(WINAPI*)(VOID))aSyscall[26].pCurrent)
-+ __inline__ sqlite_uint64 sqlite3Hwtime(void){
-+ unsigned int lo, hi;
-+ __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
-+ return (sqlite_uint64)hi << 32 | lo;
-+ }
-
--#if !defined(SQLITE_OMIT_LOAD_EXTENSION)
--#if SQLITE_OS_WINCE
-- /* The GetProcAddressA() routine is only available on Windows CE. */
-- { "GetProcAddressA", (SYSCALL)GetProcAddressA, 0 },
--#else
-- /* All other Windows platforms expect GetProcAddress() to take
-- ** an ANSI string regardless of the _UNICODE setting */
-- { "GetProcAddressA", (SYSCALL)GetProcAddress, 0 },
--#endif
--#else
-- { "GetProcAddressA", (SYSCALL)0, 0 },
--#endif
-+ #elif defined(_MSC_VER)
-
--#define osGetProcAddressA ((FARPROC(WINAPI*)(HMODULE, \
-- LPCSTR))aSyscall[27].pCurrent)
-+ __declspec(naked) __inline sqlite_uint64 __cdecl sqlite3Hwtime(void){
-+ __asm {
-+ rdtsc
-+ ret ; return value at EDX:EAX
-+ }
-+ }
-
--#if !SQLITE_OS_WINRT
-- { "GetSystemInfo", (SYSCALL)GetSystemInfo, 0 },
--#else
-- { "GetSystemInfo", (SYSCALL)0, 0 },
--#endif
-+ #endif
-
--#define osGetSystemInfo ((VOID(WINAPI*)(LPSYSTEM_INFO))aSyscall[28].pCurrent)
-+#elif (defined(__GNUC__) && defined(__x86_64__))
-
-- { "GetSystemTime", (SYSCALL)GetSystemTime, 0 },
-+ __inline__ sqlite_uint64 sqlite3Hwtime(void){
-+ unsigned long val;
-+ __asm__ __volatile__ ("rdtsc" : "=A" (val));
-+ return val;
-+ }
-+
-+#elif (defined(__GNUC__) && defined(__ppc__))
-
--#define osGetSystemTime ((VOID(WINAPI*)(LPSYSTEMTIME))aSyscall[29].pCurrent)
-+ __inline__ sqlite_uint64 sqlite3Hwtime(void){
-+ unsigned long long retval;
-+ unsigned long junk;
-+ __asm__ __volatile__ ("\n\
-+ 1: mftbu %1\n\
-+ mftb %L0\n\
-+ mftbu %0\n\
-+ cmpw %0,%1\n\
-+ bne 1b"
-+ : "=r" (retval), "=r" (junk));
-+ return retval;
-+ }
-
--#if !SQLITE_OS_WINCE
-- { "GetSystemTimeAsFileTime", (SYSCALL)GetSystemTimeAsFileTime, 0 },
- #else
-- { "GetSystemTimeAsFileTime", (SYSCALL)0, 0 },
--#endif
-
--#define osGetSystemTimeAsFileTime ((VOID(WINAPI*)( \
-- LPFILETIME))aSyscall[30].pCurrent)
-+ #error Need implementation of sqlite3Hwtime() for your platform.
-+
-+ /*
-+ ** To compile without implementing sqlite3Hwtime() for your platform,
-+ ** you can remove the above #error and use the following
-+ ** stub function. You will lose timing support for many
-+ ** of the debugging and testing utilities, but it should at
-+ ** least compile and run.
-+ */
-+SQLITE_PRIVATE sqlite_uint64 sqlite3Hwtime(void){ return ((sqlite_uint64)0); }
-
--#if defined(SQLITE_WIN32_HAS_ANSI)
-- { "GetTempPathA", (SYSCALL)GetTempPathA, 0 },
--#else
-- { "GetTempPathA", (SYSCALL)0, 0 },
- #endif
-
--#define osGetTempPathA ((DWORD(WINAPI*)(DWORD,LPSTR))aSyscall[31].pCurrent)
-+#endif /* !defined(_HWTIME_H_) */
-
--#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE)
-- { "GetTempPathW", (SYSCALL)GetTempPathW, 0 },
-+/************** End of hwtime.h **********************************************/
-+/************** Continuing where we left off in os_common.h ******************/
-+
-+static sqlite_uint64 g_start;
-+static sqlite_uint64 g_elapsed;
-+#define TIMER_START g_start=sqlite3Hwtime()
-+#define TIMER_END g_elapsed=sqlite3Hwtime()-g_start
-+#define TIMER_ELAPSED g_elapsed
- #else
-- { "GetTempPathW", (SYSCALL)0, 0 },
-+#define TIMER_START
-+#define TIMER_END
-+#define TIMER_ELAPSED ((sqlite_uint64)0)
- #endif
-
--#define osGetTempPathW ((DWORD(WINAPI*)(DWORD,LPWSTR))aSyscall[32].pCurrent)
--
--#if !SQLITE_OS_WINRT
-- { "GetTickCount", (SYSCALL)GetTickCount, 0 },
-+/*
-+** If we compile with the SQLITE_TEST macro set, then the following block
-+** of code will give us the ability to simulate a disk I/O error. This
-+** is used for testing the I/O recovery logic.
-+*/
-+#ifdef SQLITE_TEST
-+SQLITE_API int sqlite3_io_error_hit = 0; /* Total number of I/O Errors */
-+SQLITE_API int sqlite3_io_error_hardhit = 0; /* Number of non-benign errors */
-+SQLITE_API int sqlite3_io_error_pending = 0; /* Count down to first I/O error */
-+SQLITE_API int sqlite3_io_error_persist = 0; /* True if I/O errors persist */
-+SQLITE_API int sqlite3_io_error_benign = 0; /* True if errors are benign */
-+SQLITE_API int sqlite3_diskfull_pending = 0;
-+SQLITE_API int sqlite3_diskfull = 0;
-+#define SimulateIOErrorBenign(X) sqlite3_io_error_benign=(X)
-+#define SimulateIOError(CODE) \
-+ if( (sqlite3_io_error_persist && sqlite3_io_error_hit) \
-+ || sqlite3_io_error_pending-- == 1 ) \
-+ { local_ioerr(); CODE; }
-+static void local_ioerr(){
-+ IOTRACE(("IOERR\n"));
-+ sqlite3_io_error_hit++;
-+ if( !sqlite3_io_error_benign ) sqlite3_io_error_hardhit++;
-+}
-+#define SimulateDiskfullError(CODE) \
-+ if( sqlite3_diskfull_pending ){ \
-+ if( sqlite3_diskfull_pending == 1 ){ \
-+ local_ioerr(); \
-+ sqlite3_diskfull = 1; \
-+ sqlite3_io_error_hit = 1; \
-+ CODE; \
-+ }else{ \
-+ sqlite3_diskfull_pending--; \
-+ } \
-+ }
- #else
-- { "GetTickCount", (SYSCALL)0, 0 },
-+#define SimulateIOErrorBenign(X)
-+#define SimulateIOError(A)
-+#define SimulateDiskfullError(A)
- #endif
-
--#define osGetTickCount ((DWORD(WINAPI*)(VOID))aSyscall[33].pCurrent)
--
--#if defined(SQLITE_WIN32_HAS_ANSI)
-- { "GetVersionExA", (SYSCALL)GetVersionExA, 0 },
-+/*
-+** When testing, keep a count of the number of open files.
-+*/
-+#ifdef SQLITE_TEST
-+SQLITE_API int sqlite3_open_file_count = 0;
-+#define OpenCounter(X) sqlite3_open_file_count+=(X)
- #else
-- { "GetVersionExA", (SYSCALL)0, 0 },
-+#define OpenCounter(X)
- #endif
-
--#define osGetVersionExA ((BOOL(WINAPI*)( \
-- LPOSVERSIONINFOA))aSyscall[34].pCurrent)
--
-- { "HeapAlloc", (SYSCALL)HeapAlloc, 0 },
-+#endif /* !defined(_OS_COMMON_H_) */
-
--#define osHeapAlloc ((LPVOID(WINAPI*)(HANDLE,DWORD, \
-- SIZE_T))aSyscall[35].pCurrent)
-+/************** End of os_common.h *******************************************/
-+/************** Continuing where we left off in os_win.c *********************/
-
--#if !SQLITE_OS_WINRT
-- { "HeapCreate", (SYSCALL)HeapCreate, 0 },
--#else
-- { "HeapCreate", (SYSCALL)0, 0 },
-+/*
-+** Compiling and using WAL mode requires several APIs that are only
-+** available in Windows platforms based on the NT kernel.
-+*/
-+#if !SQLITE_OS_WINNT && !defined(SQLITE_OMIT_WAL)
-+# error "WAL mode requires support from the Windows NT kernel, compile\
-+ with SQLITE_OMIT_WAL."
- #endif
-
--#define osHeapCreate ((HANDLE(WINAPI*)(DWORD,SIZE_T, \
-- SIZE_T))aSyscall[36].pCurrent)
--
--#if !SQLITE_OS_WINRT
-- { "HeapDestroy", (SYSCALL)HeapDestroy, 0 },
--#else
-- { "HeapDestroy", (SYSCALL)0, 0 },
-+/*
-+** Are most of the Win32 ANSI APIs available (i.e. with certain exceptions
-+** based on the sub-platform)?
-+*/
-+#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT
-+# define SQLITE_WIN32_HAS_ANSI
- #endif
-
--#define osHeapDestroy ((BOOL(WINAPI*)(HANDLE))aSyscall[37].pCurrent)
--
-- { "HeapFree", (SYSCALL)HeapFree, 0 },
-+/*
-+** Are most of the Win32 Unicode APIs available (i.e. with certain exceptions
-+** based on the sub-platform)?
-+*/
-+#if SQLITE_OS_WINCE || SQLITE_OS_WINNT || SQLITE_OS_WINRT
-+# define SQLITE_WIN32_HAS_WIDE
-+#endif
-
--#define osHeapFree ((BOOL(WINAPI*)(HANDLE,DWORD,LPVOID))aSyscall[38].pCurrent)
-+/*
-+** Do we need to manually define the Win32 file mapping APIs for use with WAL
-+** mode (e.g. these APIs are available in the Windows CE SDK; however, they
-+** are not present in the header file)?
-+*/
-+#if SQLITE_WIN32_FILEMAPPING_API && !defined(SQLITE_OMIT_WAL)
-+/*
-+** Two of the file mapping APIs are different under WinRT. Figure out which
-+** set we need.
-+*/
-+#if SQLITE_OS_WINRT
-+WINBASEAPI HANDLE WINAPI CreateFileMappingFromApp(HANDLE, \
-+ LPSECURITY_ATTRIBUTES, ULONG, ULONG64, LPCWSTR);
-
-- { "HeapReAlloc", (SYSCALL)HeapReAlloc, 0 },
-+WINBASEAPI LPVOID WINAPI MapViewOfFileFromApp(HANDLE, ULONG, ULONG64, SIZE_T);
-+#else
-+#if defined(SQLITE_WIN32_HAS_ANSI)
-+WINBASEAPI HANDLE WINAPI CreateFileMappingA(HANDLE, LPSECURITY_ATTRIBUTES, \
-+ DWORD, DWORD, DWORD, LPCSTR);
-+#endif /* defined(SQLITE_WIN32_HAS_ANSI) */
-
--#define osHeapReAlloc ((LPVOID(WINAPI*)(HANDLE,DWORD,LPVOID, \
-- SIZE_T))aSyscall[39].pCurrent)
-+#if defined(SQLITE_WIN32_HAS_WIDE)
-+WINBASEAPI HANDLE WINAPI CreateFileMappingW(HANDLE, LPSECURITY_ATTRIBUTES, \
-+ DWORD, DWORD, DWORD, LPCWSTR);
-+#endif /* defined(SQLITE_WIN32_HAS_WIDE) */
-
-- { "HeapSize", (SYSCALL)HeapSize, 0 },
-+WINBASEAPI LPVOID WINAPI MapViewOfFile(HANDLE, DWORD, DWORD, DWORD, SIZE_T);
-+#endif /* SQLITE_OS_WINRT */
-
--#define osHeapSize ((SIZE_T(WINAPI*)(HANDLE,DWORD, \
-- LPCVOID))aSyscall[40].pCurrent)
-+/*
-+** This file mapping API is common to both Win32 and WinRT.
-+*/
-+WINBASEAPI BOOL WINAPI UnmapViewOfFile(LPCVOID);
-+#endif /* SQLITE_WIN32_FILEMAPPING_API && !defined(SQLITE_OMIT_WAL) */
-
--#if !SQLITE_OS_WINRT
-- { "HeapValidate", (SYSCALL)HeapValidate, 0 },
--#else
-- { "HeapValidate", (SYSCALL)0, 0 },
-+/*
-+** Macro to find the minimum of two numeric values.
-+*/
-+#ifndef MIN
-+# define MIN(x,y) ((x)<(y)?(x):(y))
- #endif
-
--#define osHeapValidate ((BOOL(WINAPI*)(HANDLE,DWORD, \
-- LPCVOID))aSyscall[41].pCurrent)
--
--#if defined(SQLITE_WIN32_HAS_ANSI) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
-- { "LoadLibraryA", (SYSCALL)LoadLibraryA, 0 },
--#else
-- { "LoadLibraryA", (SYSCALL)0, 0 },
-+/*
-+** Some Microsoft compilers lack this definition.
-+*/
-+#ifndef INVALID_FILE_ATTRIBUTES
-+# define INVALID_FILE_ATTRIBUTES ((DWORD)-1)
- #endif
-
--#define osLoadLibraryA ((HMODULE(WINAPI*)(LPCSTR))aSyscall[42].pCurrent)
--
--#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) && \
-- !defined(SQLITE_OMIT_LOAD_EXTENSION)
-- { "LoadLibraryW", (SYSCALL)LoadLibraryW, 0 },
--#else
-- { "LoadLibraryW", (SYSCALL)0, 0 },
-+#ifndef FILE_FLAG_MASK
-+# define FILE_FLAG_MASK (0xFF3C0000)
- #endif
-
--#define osLoadLibraryW ((HMODULE(WINAPI*)(LPCWSTR))aSyscall[43].pCurrent)
--
--#if !SQLITE_OS_WINRT
-- { "LocalFree", (SYSCALL)LocalFree, 0 },
--#else
-- { "LocalFree", (SYSCALL)0, 0 },
-+#ifndef FILE_ATTRIBUTE_MASK
-+# define FILE_ATTRIBUTE_MASK (0x0003FFF7)
- #endif
-
--#define osLocalFree ((HLOCAL(WINAPI*)(HLOCAL))aSyscall[44].pCurrent)
--
--#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT
-- { "LockFile", (SYSCALL)LockFile, 0 },
--#else
-- { "LockFile", (SYSCALL)0, 0 },
-+#ifndef SQLITE_OMIT_WAL
-+/* Forward references */
-+typedef struct winShm winShm; /* A connection to shared-memory */
-+typedef struct winShmNode winShmNode; /* A region of shared-memory */
- #endif
-
--#ifndef osLockFile
--#define osLockFile ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \
-- DWORD))aSyscall[45].pCurrent)
-+/*
-+** WinCE lacks native support for file locking so we have to fake it
-+** with some code of our own.
-+*/
-+#if SQLITE_OS_WINCE
-+typedef struct winceLock {
-+ int nReaders; /* Number of reader locks obtained */
-+ BOOL bPending; /* Indicates a pending lock has been obtained */
-+ BOOL bReserved; /* Indicates a reserved lock has been obtained */
-+ BOOL bExclusive; /* Indicates an exclusive lock has been obtained */
-+} winceLock;
- #endif
-
--#if !SQLITE_OS_WINCE
-- { "LockFileEx", (SYSCALL)LockFileEx, 0 },
--#else
-- { "LockFileEx", (SYSCALL)0, 0 },
-+/*
-+** The winFile structure is a subclass of sqlite3_file* specific to the win32
-+** portability layer.
-+*/
-+typedef struct winFile winFile;
-+struct winFile {
-+ const sqlite3_io_methods *pMethod; /*** Must be first ***/
-+ sqlite3_vfs *pVfs; /* The VFS used to open this file */
-+ HANDLE h; /* Handle for accessing the file */
-+ u8 locktype; /* Type of lock currently held on this file */
-+ short sharedLockByte; /* Randomly chosen byte used as a shared lock */
-+ u8 ctrlFlags; /* Flags. See WINFILE_* below */
-+ DWORD lastErrno; /* The Windows errno from the last I/O error */
-+#ifndef SQLITE_OMIT_WAL
-+ winShm *pShm; /* Instance of shared memory on this file */
- #endif
--
--#ifndef osLockFileEx
--#define osLockFileEx ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD,DWORD, \
-- LPOVERLAPPED))aSyscall[46].pCurrent)
-+ const char *zPath; /* Full pathname of this file */
-+ int szChunk; /* Chunk size configured by FCNTL_CHUNK_SIZE */
-+#if SQLITE_OS_WINCE
-+ LPWSTR zDeleteOnClose; /* Name of file to delete when closing */
-+ HANDLE hMutex; /* Mutex used to control access to shared lock */
-+ HANDLE hShared; /* Shared memory segment used for locking */
-+ winceLock local; /* Locks obtained by this instance of winFile */
-+ winceLock *shared; /* Global shared lock memory for the file */
- #endif
--
--#if SQLITE_OS_WINCE || (!SQLITE_OS_WINRT && !defined(SQLITE_OMIT_WAL))
-- { "MapViewOfFile", (SYSCALL)MapViewOfFile, 0 },
--#else
-- { "MapViewOfFile", (SYSCALL)0, 0 },
-+#if SQLITE_MAX_MMAP_SIZE>0
-+ int nFetchOut; /* Number of outstanding xFetch references */
-+ HANDLE hMap; /* Handle for accessing memory mapping */
-+ void *pMapRegion; /* Area memory mapped */
-+ sqlite3_int64 mmapSize; /* Usable size of mapped region */
-+ sqlite3_int64 mmapSizeActual; /* Actual size of mapped region */
-+ sqlite3_int64 mmapSizeMax; /* Configured FCNTL_MMAP_SIZE value */
- #endif
-+};
-
--#define osMapViewOfFile ((LPVOID(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \
-- SIZE_T))aSyscall[47].pCurrent)
--
-- { "MultiByteToWideChar", (SYSCALL)MultiByteToWideChar, 0 },
--
--#define osMultiByteToWideChar ((int(WINAPI*)(UINT,DWORD,LPCSTR,int,LPWSTR, \
-- int))aSyscall[48].pCurrent)
--
-- { "QueryPerformanceCounter", (SYSCALL)QueryPerformanceCounter, 0 },
--
--#define osQueryPerformanceCounter ((BOOL(WINAPI*)( \
-- LARGE_INTEGER*))aSyscall[49].pCurrent)
--
-- { "ReadFile", (SYSCALL)ReadFile, 0 },
--
--#define osReadFile ((BOOL(WINAPI*)(HANDLE,LPVOID,DWORD,LPDWORD, \
-- LPOVERLAPPED))aSyscall[50].pCurrent)
--
-- { "SetEndOfFile", (SYSCALL)SetEndOfFile, 0 },
--
--#define osSetEndOfFile ((BOOL(WINAPI*)(HANDLE))aSyscall[51].pCurrent)
-+/*
-+** Allowed values for winFile.ctrlFlags
-+*/
-+#define WINFILE_RDONLY 0x02 /* Connection is read only */
-+#define WINFILE_PERSIST_WAL 0x04 /* Persistent WAL mode */
-+#define WINFILE_PSOW 0x10 /* SQLITE_IOCAP_POWERSAFE_OVERWRITE */
-
--#if !SQLITE_OS_WINRT
-- { "SetFilePointer", (SYSCALL)SetFilePointer, 0 },
--#else
-- { "SetFilePointer", (SYSCALL)0, 0 },
-+/*
-+ * The size of the buffer used by sqlite3_win32_write_debug().
-+ */
-+#ifndef SQLITE_WIN32_DBG_BUF_SIZE
-+# define SQLITE_WIN32_DBG_BUF_SIZE ((int)(4096-sizeof(DWORD)))
- #endif
-
--#define osSetFilePointer ((DWORD(WINAPI*)(HANDLE,LONG,PLONG, \
-- DWORD))aSyscall[52].pCurrent)
--
--#if !SQLITE_OS_WINRT
-- { "Sleep", (SYSCALL)Sleep, 0 },
--#else
-- { "Sleep", (SYSCALL)0, 0 },
-+/*
-+ * The value used with sqlite3_win32_set_directory() to specify that
-+ * the data directory should be changed.
-+ */
-+#ifndef SQLITE_WIN32_DATA_DIRECTORY_TYPE
-+# define SQLITE_WIN32_DATA_DIRECTORY_TYPE (1)
- #endif
-
--#define osSleep ((VOID(WINAPI*)(DWORD))aSyscall[53].pCurrent)
--
-- { "SystemTimeToFileTime", (SYSCALL)SystemTimeToFileTime, 0 },
-+/*
-+ * The value used with sqlite3_win32_set_directory() to specify that
-+ * the temporary directory should be changed.
-+ */
-+#ifndef SQLITE_WIN32_TEMP_DIRECTORY_TYPE
-+# define SQLITE_WIN32_TEMP_DIRECTORY_TYPE (2)
-+#endif
-
--#define osSystemTimeToFileTime ((BOOL(WINAPI*)(CONST SYSTEMTIME*, \
-- LPFILETIME))aSyscall[54].pCurrent)
-+/*
-+ * If compiled with SQLITE_WIN32_MALLOC on Windows, we will use the
-+ * various Win32 API heap functions instead of our own.
-+ */
-+#ifdef SQLITE_WIN32_MALLOC
-
--#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT
-- { "UnlockFile", (SYSCALL)UnlockFile, 0 },
--#else
-- { "UnlockFile", (SYSCALL)0, 0 },
-+/*
-+ * If this is non-zero, an isolated heap will be created by the native Win32
-+ * allocator subsystem; otherwise, the default process heap will be used. This
-+ * setting has no effect when compiling for WinRT. By default, this is enabled
-+ * and an isolated heap will be created to store all allocated data.
-+ *
-+ ******************************************************************************
-+ * WARNING: It is important to note that when this setting is non-zero and the
-+ * winMemShutdown function is called (e.g. by the sqlite3_shutdown
-+ * function), all data that was allocated using the isolated heap will
-+ * be freed immediately and any attempt to access any of that freed
-+ * data will almost certainly result in an immediate access violation.
-+ ******************************************************************************
-+ */
-+#ifndef SQLITE_WIN32_HEAP_CREATE
-+# define SQLITE_WIN32_HEAP_CREATE (TRUE)
- #endif
-
--#ifndef osUnlockFile
--#define osUnlockFile ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \
-- DWORD))aSyscall[55].pCurrent)
-+/*
-+ * The initial size of the Win32-specific heap. This value may be zero.
-+ */
-+#ifndef SQLITE_WIN32_HEAP_INIT_SIZE
-+# define SQLITE_WIN32_HEAP_INIT_SIZE ((SQLITE_DEFAULT_CACHE_SIZE) * \
-+ (SQLITE_DEFAULT_PAGE_SIZE) + 4194304)
- #endif
-
--#if !SQLITE_OS_WINCE
-- { "UnlockFileEx", (SYSCALL)UnlockFileEx, 0 },
--#else
-- { "UnlockFileEx", (SYSCALL)0, 0 },
-+/*
-+ * The maximum size of the Win32-specific heap. This value may be zero.
-+ */
-+#ifndef SQLITE_WIN32_HEAP_MAX_SIZE
-+# define SQLITE_WIN32_HEAP_MAX_SIZE (0)
- #endif
-
--#define osUnlockFileEx ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \
-- LPOVERLAPPED))aSyscall[56].pCurrent)
--
--#if SQLITE_OS_WINCE || !defined(SQLITE_OMIT_WAL)
-- { "UnmapViewOfFile", (SYSCALL)UnmapViewOfFile, 0 },
--#else
-- { "UnmapViewOfFile", (SYSCALL)0, 0 },
-+/*
-+ * The extra flags to use in calls to the Win32 heap APIs. This value may be
-+ * zero for the default behavior.
-+ */
-+#ifndef SQLITE_WIN32_HEAP_FLAGS
-+# define SQLITE_WIN32_HEAP_FLAGS (0)
- #endif
-
--#define osUnmapViewOfFile ((BOOL(WINAPI*)(LPCVOID))aSyscall[57].pCurrent)
--
-- { "WideCharToMultiByte", (SYSCALL)WideCharToMultiByte, 0 },
--
--#define osWideCharToMultiByte ((int(WINAPI*)(UINT,DWORD,LPCWSTR,int,LPSTR,int, \
-- LPCSTR,LPBOOL))aSyscall[58].pCurrent)
--
-- { "WriteFile", (SYSCALL)WriteFile, 0 },
--
--#define osWriteFile ((BOOL(WINAPI*)(HANDLE,LPCVOID,DWORD,LPDWORD, \
-- LPOVERLAPPED))aSyscall[59].pCurrent)
-+/*
-+** The winMemData structure stores information required by the Win32-specific
-+** sqlite3_mem_methods implementation.
-+*/
-+typedef struct winMemData winMemData;
-+struct winMemData {
-+#ifndef NDEBUG
-+ u32 magic; /* Magic number to detect structure corruption. */
-+#endif
-+ HANDLE hHeap; /* The handle to our heap. */
-+ BOOL bOwned; /* Do we own the heap (i.e. destroy it on shutdown)? */
-+};
-
--#if SQLITE_OS_WINRT
-- { "CreateEventExW", (SYSCALL)CreateEventExW, 0 },
--#else
-- { "CreateEventExW", (SYSCALL)0, 0 },
-+#ifndef NDEBUG
-+#define WINMEM_MAGIC 0x42b2830b
- #endif
-
--#define osCreateEventExW ((HANDLE(WINAPI*)(LPSECURITY_ATTRIBUTES,LPCWSTR, \
-- DWORD,DWORD))aSyscall[60].pCurrent)
-+static struct winMemData win_mem_data = {
-+#ifndef NDEBUG
-+ WINMEM_MAGIC,
-+#endif
-+ NULL, FALSE
-+};
-
--#if !SQLITE_OS_WINRT
-- { "WaitForSingleObject", (SYSCALL)WaitForSingleObject, 0 },
-+#ifndef NDEBUG
-+#define winMemAssertMagic() assert( win_mem_data.magic==WINMEM_MAGIC )
- #else
-- { "WaitForSingleObject", (SYSCALL)0, 0 },
-+#define winMemAssertMagic()
- #endif
-
--#define osWaitForSingleObject ((DWORD(WINAPI*)(HANDLE, \
-- DWORD))aSyscall[61].pCurrent)
-+#define winMemGetHeap() win_mem_data.hHeap
-
--#if SQLITE_OS_WINRT
-- { "WaitForSingleObjectEx", (SYSCALL)WaitForSingleObjectEx, 0 },
--#else
-- { "WaitForSingleObjectEx", (SYSCALL)0, 0 },
--#endif
-+static void *winMemMalloc(int nBytes);
-+static void winMemFree(void *pPrior);
-+static void *winMemRealloc(void *pPrior, int nBytes);
-+static int winMemSize(void *p);
-+static int winMemRoundup(int n);
-+static int winMemInit(void *pAppData);
-+static void winMemShutdown(void *pAppData);
-
--#define osWaitForSingleObjectEx ((DWORD(WINAPI*)(HANDLE,DWORD, \
-- BOOL))aSyscall[62].pCurrent)
-+SQLITE_PRIVATE const sqlite3_mem_methods *sqlite3MemGetWin32(void);
-+#endif /* SQLITE_WIN32_MALLOC */
-
--#if SQLITE_OS_WINRT
-- { "SetFilePointerEx", (SYSCALL)SetFilePointerEx, 0 },
-+/*
-+** The following variable is (normally) set once and never changes
-+** thereafter. It records whether the operating system is Win9x
-+** or WinNT.
-+**
-+** 0: Operating system unknown.
-+** 1: Operating system is Win9x.
-+** 2: Operating system is WinNT.
-+**
-+** In order to facilitate testing on a WinNT system, the test fixture
-+** can manually set this value to 1 to emulate Win98 behavior.
-+*/
-+#ifdef SQLITE_TEST
-+SQLITE_API int sqlite3_os_type = 0;
- #else
-- { "SetFilePointerEx", (SYSCALL)0, 0 },
-+static int sqlite3_os_type = 0;
- #endif
-
--#define osSetFilePointerEx ((BOOL(WINAPI*)(HANDLE,LARGE_INTEGER, \
-- PLARGE_INTEGER,DWORD))aSyscall[63].pCurrent)
--
--#if SQLITE_OS_WINRT
-- { "GetFileInformationByHandleEx", (SYSCALL)GetFileInformationByHandleEx, 0 },
--#else
-- { "GetFileInformationByHandleEx", (SYSCALL)0, 0 },
-+#ifndef SYSCALL
-+# define SYSCALL sqlite3_syscall_ptr
- #endif
-
--#define osGetFileInformationByHandleEx ((BOOL(WINAPI*)(HANDLE, \
-- FILE_INFO_BY_HANDLE_CLASS,LPVOID,DWORD))aSyscall[64].pCurrent)
-+/*
-+** This function is not available on Windows CE or WinRT.
-+ */
-
--#if SQLITE_OS_WINRT && !defined(SQLITE_OMIT_WAL)
-- { "MapViewOfFileFromApp", (SYSCALL)MapViewOfFileFromApp, 0 },
--#else
-- { "MapViewOfFileFromApp", (SYSCALL)0, 0 },
-+#if SQLITE_OS_WINCE || SQLITE_OS_WINRT
-+# define osAreFileApisANSI() 1
- #endif
-
--#define osMapViewOfFileFromApp ((LPVOID(WINAPI*)(HANDLE,ULONG,ULONG64, \
-- SIZE_T))aSyscall[65].pCurrent)
--
--#if SQLITE_OS_WINRT
-- { "CreateFile2", (SYSCALL)CreateFile2, 0 },
-+/*
-+** Many system calls are accessed through pointer-to-functions so that
-+** they may be overridden at runtime to facilitate fault injection during
-+** testing and sandboxing. The following array holds the names and pointers
-+** to all overrideable system calls.
-+*/
-+static struct win_syscall {
-+ const char *zName; /* Name of the system call */
-+ sqlite3_syscall_ptr pCurrent; /* Current value of the system call */
-+ sqlite3_syscall_ptr pDefault; /* Default value */
-+} aSyscall[] = {
-+#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT
-+ { "AreFileApisANSI", (SYSCALL)AreFileApisANSI, 0 },
- #else
-- { "CreateFile2", (SYSCALL)0, 0 },
-+ { "AreFileApisANSI", (SYSCALL)0, 0 },
- #endif
-
--#define osCreateFile2 ((HANDLE(WINAPI*)(LPCWSTR,DWORD,DWORD,DWORD, \
-- LPCREATEFILE2_EXTENDED_PARAMETERS))aSyscall[66].pCurrent)
-+#ifndef osAreFileApisANSI
-+#define osAreFileApisANSI ((BOOL(WINAPI*)(VOID))aSyscall[0].pCurrent)
-+#endif
-
--#if SQLITE_OS_WINRT && !defined(SQLITE_OMIT_LOAD_EXTENSION)
-- { "LoadPackagedLibrary", (SYSCALL)LoadPackagedLibrary, 0 },
-+#if SQLITE_OS_WINCE && defined(SQLITE_WIN32_HAS_WIDE)
-+ { "CharLowerW", (SYSCALL)CharLowerW, 0 },
- #else
-- { "LoadPackagedLibrary", (SYSCALL)0, 0 },
-+ { "CharLowerW", (SYSCALL)0, 0 },
- #endif
-
--#define osLoadPackagedLibrary ((HMODULE(WINAPI*)(LPCWSTR, \
-- DWORD))aSyscall[67].pCurrent)
-+#define osCharLowerW ((LPWSTR(WINAPI*)(LPWSTR))aSyscall[1].pCurrent)
-
--#if SQLITE_OS_WINRT
-- { "GetTickCount64", (SYSCALL)GetTickCount64, 0 },
-+#if SQLITE_OS_WINCE && defined(SQLITE_WIN32_HAS_WIDE)
-+ { "CharUpperW", (SYSCALL)CharUpperW, 0 },
- #else
-- { "GetTickCount64", (SYSCALL)0, 0 },
-+ { "CharUpperW", (SYSCALL)0, 0 },
- #endif
-
--#define osGetTickCount64 ((ULONGLONG(WINAPI*)(VOID))aSyscall[68].pCurrent)
-+#define osCharUpperW ((LPWSTR(WINAPI*)(LPWSTR))aSyscall[2].pCurrent)
-
--#if SQLITE_OS_WINRT
-- { "GetNativeSystemInfo", (SYSCALL)GetNativeSystemInfo, 0 },
--#else
-- { "GetNativeSystemInfo", (SYSCALL)0, 0 },
--#endif
-+ { "CloseHandle", (SYSCALL)CloseHandle, 0 },
-
--#define osGetNativeSystemInfo ((VOID(WINAPI*)( \
-- LPSYSTEM_INFO))aSyscall[69].pCurrent)
-+#define osCloseHandle ((BOOL(WINAPI*)(HANDLE))aSyscall[3].pCurrent)
-
- #if defined(SQLITE_WIN32_HAS_ANSI)
-- { "OutputDebugStringA", (SYSCALL)OutputDebugStringA, 0 },
-+ { "CreateFileA", (SYSCALL)CreateFileA, 0 },
- #else
-- { "OutputDebugStringA", (SYSCALL)0, 0 },
-+ { "CreateFileA", (SYSCALL)0, 0 },
- #endif
-
--#define osOutputDebugStringA ((VOID(WINAPI*)(LPCSTR))aSyscall[70].pCurrent)
-+#define osCreateFileA ((HANDLE(WINAPI*)(LPCSTR,DWORD,DWORD, \
-+ LPSECURITY_ATTRIBUTES,DWORD,DWORD,HANDLE))aSyscall[4].pCurrent)
-
--#if defined(SQLITE_WIN32_HAS_WIDE)
-- { "OutputDebugStringW", (SYSCALL)OutputDebugStringW, 0 },
-+#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE)
-+ { "CreateFileW", (SYSCALL)CreateFileW, 0 },
- #else
-- { "OutputDebugStringW", (SYSCALL)0, 0 },
-+ { "CreateFileW", (SYSCALL)0, 0 },
- #endif
-
--#define osOutputDebugStringW ((VOID(WINAPI*)(LPCWSTR))aSyscall[71].pCurrent)
--
-- { "GetProcessHeap", (SYSCALL)GetProcessHeap, 0 },
--
--#define osGetProcessHeap ((HANDLE(WINAPI*)(VOID))aSyscall[72].pCurrent)
-+#define osCreateFileW ((HANDLE(WINAPI*)(LPCWSTR,DWORD,DWORD, \
-+ LPSECURITY_ATTRIBUTES,DWORD,DWORD,HANDLE))aSyscall[5].pCurrent)
-
--#if SQLITE_OS_WINRT && !defined(SQLITE_OMIT_WAL)
-- { "CreateFileMappingFromApp", (SYSCALL)CreateFileMappingFromApp, 0 },
-+#if (!SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_ANSI) && \
-+ !defined(SQLITE_OMIT_WAL))
-+ { "CreateFileMappingA", (SYSCALL)CreateFileMappingA, 0 },
- #else
-- { "CreateFileMappingFromApp", (SYSCALL)0, 0 },
-+ { "CreateFileMappingA", (SYSCALL)0, 0 },
- #endif
-
--#define osCreateFileMappingFromApp ((HANDLE(WINAPI*)(HANDLE, \
-- LPSECURITY_ATTRIBUTES,ULONG,ULONG64,LPCWSTR))aSyscall[73].pCurrent)
--
--}; /* End of the overrideable system calls */
--
--/*
--** This is the xSetSystemCall() method of sqlite3_vfs for all of the
--** "win32" VFSes. Return SQLITE_OK opon successfully updating the
--** system call pointer, or SQLITE_NOTFOUND if there is no configurable
--** system call named zName.
--*/
--static int winSetSystemCall(
-- sqlite3_vfs *pNotUsed, /* The VFS pointer. Not used */
-- const char *zName, /* Name of system call to override */
-- sqlite3_syscall_ptr pNewFunc /* Pointer to new system call value */
--){
-- unsigned int i;
-- int rc = SQLITE_NOTFOUND;
--
-- UNUSED_PARAMETER(pNotUsed);
-- if( zName==0 ){
-- /* If no zName is given, restore all system calls to their default
-- ** settings and return NULL
-- */
-- rc = SQLITE_OK;
-- for(i=0; i<sizeof(aSyscall)/sizeof(aSyscall[0]); i++){
-- if( aSyscall[i].pDefault ){
-- aSyscall[i].pCurrent = aSyscall[i].pDefault;
-- }
-- }
-- }else{
-- /* If zName is specified, operate on only the one system call
-- ** specified.
-- */
-- for(i=0; i<sizeof(aSyscall)/sizeof(aSyscall[0]); i++){
-- if( strcmp(zName, aSyscall[i].zName)==0 ){
-- if( aSyscall[i].pDefault==0 ){
-- aSyscall[i].pDefault = aSyscall[i].pCurrent;
-- }
-- rc = SQLITE_OK;
-- if( pNewFunc==0 ) pNewFunc = aSyscall[i].pDefault;
-- aSyscall[i].pCurrent = pNewFunc;
-- break;
-- }
-- }
-- }
-- return rc;
--}
--
--/*
--** Return the value of a system call. Return NULL if zName is not a
--** recognized system call name. NULL is also returned if the system call
--** is currently undefined.
--*/
--static sqlite3_syscall_ptr winGetSystemCall(
-- sqlite3_vfs *pNotUsed,
-- const char *zName
--){
-- unsigned int i;
--
-- UNUSED_PARAMETER(pNotUsed);
-- for(i=0; i<sizeof(aSyscall)/sizeof(aSyscall[0]); i++){
-- if( strcmp(zName, aSyscall[i].zName)==0 ) return aSyscall[i].pCurrent;
-- }
-- return 0;
--}
--
--/*
--** Return the name of the first system call after zName. If zName==NULL
--** then return the name of the first system call. Return NULL if zName
--** is the last system call or if zName is not the name of a valid
--** system call.
--*/
--static const char *winNextSystemCall(sqlite3_vfs *p, const char *zName){
-- int i = -1;
--
-- UNUSED_PARAMETER(p);
-- if( zName ){
-- for(i=0; i<ArraySize(aSyscall)-1; i++){
-- if( strcmp(zName, aSyscall[i].zName)==0 ) break;
-- }
-- }
-- for(i++; i<ArraySize(aSyscall); i++){
-- if( aSyscall[i].pCurrent!=0 ) return aSyscall[i].zName;
-- }
-- return 0;
--}
--
--/*
--** This function outputs the specified (ANSI) string to the Win32 debugger
--** (if available).
--*/
-+#define osCreateFileMappingA ((HANDLE(WINAPI*)(HANDLE,LPSECURITY_ATTRIBUTES, \
-+ DWORD,DWORD,DWORD,LPCSTR))aSyscall[6].pCurrent)
-
--SQLITE_API void sqlite3_win32_write_debug(const char *zBuf, int nBuf){
-- char zDbgBuf[SQLITE_WIN32_DBG_BUF_SIZE];
-- int nMin = MIN(nBuf, (SQLITE_WIN32_DBG_BUF_SIZE - 1)); /* may be negative. */
-- if( nMin<-1 ) nMin = -1; /* all negative values become -1. */
-- assert( nMin==-1 || nMin==0 || nMin<SQLITE_WIN32_DBG_BUF_SIZE );
--#if defined(SQLITE_WIN32_HAS_ANSI)
-- if( nMin>0 ){
-- memset(zDbgBuf, 0, SQLITE_WIN32_DBG_BUF_SIZE);
-- memcpy(zDbgBuf, zBuf, nMin);
-- osOutputDebugStringA(zDbgBuf);
-- }else{
-- osOutputDebugStringA(zBuf);
-- }
--#elif defined(SQLITE_WIN32_HAS_WIDE)
-- memset(zDbgBuf, 0, SQLITE_WIN32_DBG_BUF_SIZE);
-- if ( osMultiByteToWideChar(
-- osAreFileApisANSI() ? CP_ACP : CP_OEMCP, 0, zBuf,
-- nMin, (LPWSTR)zDbgBuf, SQLITE_WIN32_DBG_BUF_SIZE/sizeof(WCHAR))<=0 ){
-- return;
-- }
-- osOutputDebugStringW((LPCWSTR)zDbgBuf);
-+#if SQLITE_OS_WINCE || (!SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) && \
-+ !defined(SQLITE_OMIT_WAL))
-+ { "CreateFileMappingW", (SYSCALL)CreateFileMappingW, 0 },
- #else
-- if( nMin>0 ){
-- memset(zDbgBuf, 0, SQLITE_WIN32_DBG_BUF_SIZE);
-- memcpy(zDbgBuf, zBuf, nMin);
-- fprintf(stderr, "%s", zDbgBuf);
-- }else{
-- fprintf(stderr, "%s", zBuf);
-- }
--#endif
--}
--
--/*
--** The following routine suspends the current thread for at least ms
--** milliseconds. This is equivalent to the Win32 Sleep() interface.
--*/
--#if SQLITE_OS_WINRT
--static HANDLE sleepObj = NULL;
-+ { "CreateFileMappingW", (SYSCALL)0, 0 },
- #endif
-
--SQLITE_API void sqlite3_win32_sleep(DWORD milliseconds){
--#if SQLITE_OS_WINRT
-- if ( sleepObj==NULL ){
-- sleepObj = osCreateEventExW(NULL, NULL, CREATE_EVENT_MANUAL_RESET,
-- SYNCHRONIZE);
-- }
-- assert( sleepObj!=NULL );
-- osWaitForSingleObjectEx(sleepObj, milliseconds, FALSE);
--#else
-- osSleep(milliseconds);
--#endif
--}
-+#define osCreateFileMappingW ((HANDLE(WINAPI*)(HANDLE,LPSECURITY_ATTRIBUTES, \
-+ DWORD,DWORD,DWORD,LPCWSTR))aSyscall[7].pCurrent)
-
--/*
--** Return true (non-zero) if we are running under WinNT, Win2K, WinXP,
--** or WinCE. Return false (zero) for Win95, Win98, or WinME.
--**
--** Here is an interesting observation: Win95, Win98, and WinME lack
--** the LockFileEx() API. But we can still statically link against that
--** API as long as we don't call it when running Win95/98/ME. A call to
--** this routine is used to determine if the host is Win95/98/ME or
--** WinNT/2K/XP so that we will know whether or not we can safely call
--** the LockFileEx() API.
--*/
--#if SQLITE_OS_WINCE || SQLITE_OS_WINRT
--# define isNT() (1)
--#elif !defined(SQLITE_WIN32_HAS_WIDE)
--# define isNT() (0)
-+#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE)
-+ { "CreateMutexW", (SYSCALL)CreateMutexW, 0 },
- #else
-- static int isNT(void){
-- if( sqlite3_os_type==0 ){
-- OSVERSIONINFOA sInfo;
-- sInfo.dwOSVersionInfoSize = sizeof(sInfo);
-- osGetVersionExA(&sInfo);
-- sqlite3_os_type = sInfo.dwPlatformId==VER_PLATFORM_WIN32_NT ? 2 : 1;
-- }
-- return sqlite3_os_type==2;
-- }
-+ { "CreateMutexW", (SYSCALL)0, 0 },
- #endif
-
--#ifdef SQLITE_WIN32_MALLOC
--/*
--** Allocate nBytes of memory.
--*/
--static void *winMemMalloc(int nBytes){
-- HANDLE hHeap;
-- void *p;
-+#define osCreateMutexW ((HANDLE(WINAPI*)(LPSECURITY_ATTRIBUTES,BOOL, \
-+ LPCWSTR))aSyscall[8].pCurrent)
-
-- winMemAssertMagic();
-- hHeap = winMemGetHeap();
-- assert( hHeap!=0 );
-- assert( hHeap!=INVALID_HANDLE_VALUE );
--#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE)
-- assert ( osHeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) );
-+#if defined(SQLITE_WIN32_HAS_ANSI)
-+ { "DeleteFileA", (SYSCALL)DeleteFileA, 0 },
-+#else
-+ { "DeleteFileA", (SYSCALL)0, 0 },
- #endif
-- assert( nBytes>=0 );
-- p = osHeapAlloc(hHeap, SQLITE_WIN32_HEAP_FLAGS, (SIZE_T)nBytes);
-- if( !p ){
-- sqlite3_log(SQLITE_NOMEM, "failed to HeapAlloc %u bytes (%d), heap=%p",
-- nBytes, osGetLastError(), (void*)hHeap);
-- }
-- return p;
--}
-
--/*
--** Free memory.
--*/
--static void winMemFree(void *pPrior){
-- HANDLE hHeap;
-+#define osDeleteFileA ((BOOL(WINAPI*)(LPCSTR))aSyscall[9].pCurrent)
-
-- winMemAssertMagic();
-- hHeap = winMemGetHeap();
-- assert( hHeap!=0 );
-- assert( hHeap!=INVALID_HANDLE_VALUE );
--#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE)
-- assert ( osHeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior) );
-+#if defined(SQLITE_WIN32_HAS_WIDE)
-+ { "DeleteFileW", (SYSCALL)DeleteFileW, 0 },
-+#else
-+ { "DeleteFileW", (SYSCALL)0, 0 },
- #endif
-- if( !pPrior ) return; /* Passing NULL to HeapFree is undefined. */
-- if( !osHeapFree(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior) ){
-- sqlite3_log(SQLITE_NOMEM, "failed to HeapFree block %p (%d), heap=%p",
-- pPrior, osGetLastError(), (void*)hHeap);
-- }
--}
-
--/*
--** Change the size of an existing memory allocation
--*/
--static void *winMemRealloc(void *pPrior, int nBytes){
-- HANDLE hHeap;
-- void *p;
-+#define osDeleteFileW ((BOOL(WINAPI*)(LPCWSTR))aSyscall[10].pCurrent)
-
-- winMemAssertMagic();
-- hHeap = winMemGetHeap();
-- assert( hHeap!=0 );
-- assert( hHeap!=INVALID_HANDLE_VALUE );
--#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE)
-- assert ( osHeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior) );
-+#if SQLITE_OS_WINCE
-+ { "FileTimeToLocalFileTime", (SYSCALL)FileTimeToLocalFileTime, 0 },
-+#else
-+ { "FileTimeToLocalFileTime", (SYSCALL)0, 0 },
- #endif
-- assert( nBytes>=0 );
-- if( !pPrior ){
-- p = osHeapAlloc(hHeap, SQLITE_WIN32_HEAP_FLAGS, (SIZE_T)nBytes);
-- }else{
-- p = osHeapReAlloc(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior, (SIZE_T)nBytes);
-- }
-- if( !p ){
-- sqlite3_log(SQLITE_NOMEM, "failed to %s %u bytes (%d), heap=%p",
-- pPrior ? "HeapReAlloc" : "HeapAlloc", nBytes, osGetLastError(),
-- (void*)hHeap);
-- }
-- return p;
--}
-
--/*
--** Return the size of an outstanding allocation, in bytes.
--*/
--static int winMemSize(void *p){
-- HANDLE hHeap;
-- SIZE_T n;
-+#define osFileTimeToLocalFileTime ((BOOL(WINAPI*)(CONST FILETIME*, \
-+ LPFILETIME))aSyscall[11].pCurrent)
-
-- winMemAssertMagic();
-- hHeap = winMemGetHeap();
-- assert( hHeap!=0 );
-- assert( hHeap!=INVALID_HANDLE_VALUE );
--#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE)
-- assert ( osHeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) );
-+#if SQLITE_OS_WINCE
-+ { "FileTimeToSystemTime", (SYSCALL)FileTimeToSystemTime, 0 },
-+#else
-+ { "FileTimeToSystemTime", (SYSCALL)0, 0 },
- #endif
-- if( !p ) return 0;
-- n = osHeapSize(hHeap, SQLITE_WIN32_HEAP_FLAGS, p);
-- if( n==(SIZE_T)-1 ){
-- sqlite3_log(SQLITE_NOMEM, "failed to HeapSize block %p (%d), heap=%p",
-- p, osGetLastError(), (void*)hHeap);
-- return 0;
-- }
-- return (int)n;
--}
-
--/*
--** Round up a request size to the next valid allocation size.
--*/
--static int winMemRoundup(int n){
-- return n;
--}
-+#define osFileTimeToSystemTime ((BOOL(WINAPI*)(CONST FILETIME*, \
-+ LPSYSTEMTIME))aSyscall[12].pCurrent)
-
--/*
--** Initialize this module.
--*/
--static int winMemInit(void *pAppData){
-- winMemData *pWinMemData = (winMemData *)pAppData;
-+ { "FlushFileBuffers", (SYSCALL)FlushFileBuffers, 0 },
-
-- if( !pWinMemData ) return SQLITE_ERROR;
-- assert( pWinMemData->magic==WINMEM_MAGIC );
-+#define osFlushFileBuffers ((BOOL(WINAPI*)(HANDLE))aSyscall[13].pCurrent)
-
--#if !SQLITE_OS_WINRT && SQLITE_WIN32_HEAP_CREATE
-- if( !pWinMemData->hHeap ){
-- pWinMemData->hHeap = osHeapCreate(SQLITE_WIN32_HEAP_FLAGS,
-- SQLITE_WIN32_HEAP_INIT_SIZE,
-- SQLITE_WIN32_HEAP_MAX_SIZE);
-- if( !pWinMemData->hHeap ){
-- sqlite3_log(SQLITE_NOMEM,
-- "failed to HeapCreate (%d), flags=%u, initSize=%u, maxSize=%u",
-- osGetLastError(), SQLITE_WIN32_HEAP_FLAGS,
-- SQLITE_WIN32_HEAP_INIT_SIZE, SQLITE_WIN32_HEAP_MAX_SIZE);
-- return SQLITE_NOMEM;
-- }
-- pWinMemData->bOwned = TRUE;
-- assert( pWinMemData->bOwned );
-- }
-+#if defined(SQLITE_WIN32_HAS_ANSI)
-+ { "FormatMessageA", (SYSCALL)FormatMessageA, 0 },
- #else
-- pWinMemData->hHeap = osGetProcessHeap();
-- if( !pWinMemData->hHeap ){
-- sqlite3_log(SQLITE_NOMEM,
-- "failed to GetProcessHeap (%d)", osGetLastError());
-- return SQLITE_NOMEM;
-- }
-- pWinMemData->bOwned = FALSE;
-- assert( !pWinMemData->bOwned );
-+ { "FormatMessageA", (SYSCALL)0, 0 },
- #endif
-- assert( pWinMemData->hHeap!=0 );
-- assert( pWinMemData->hHeap!=INVALID_HANDLE_VALUE );
--#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE)
-- assert( osHeapValidate(pWinMemData->hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) );
-+
-+#define osFormatMessageA ((DWORD(WINAPI*)(DWORD,LPCVOID,DWORD,DWORD,LPSTR, \
-+ DWORD,va_list*))aSyscall[14].pCurrent)
-+
-+#if defined(SQLITE_WIN32_HAS_WIDE)
-+ { "FormatMessageW", (SYSCALL)FormatMessageW, 0 },
-+#else
-+ { "FormatMessageW", (SYSCALL)0, 0 },
- #endif
-- return SQLITE_OK;
--}
-
--/*
--** Deinitialize this module.
--*/
--static void winMemShutdown(void *pAppData){
-- winMemData *pWinMemData = (winMemData *)pAppData;
-+#define osFormatMessageW ((DWORD(WINAPI*)(DWORD,LPCVOID,DWORD,DWORD,LPWSTR, \
-+ DWORD,va_list*))aSyscall[15].pCurrent)
-
-- if( !pWinMemData ) return;
-- if( pWinMemData->hHeap ){
-- assert( pWinMemData->hHeap!=INVALID_HANDLE_VALUE );
--#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE)
-- assert( osHeapValidate(pWinMemData->hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) );
-+#if !defined(SQLITE_OMIT_LOAD_EXTENSION)
-+ { "FreeLibrary", (SYSCALL)FreeLibrary, 0 },
-+#else
-+ { "FreeLibrary", (SYSCALL)0, 0 },
- #endif
-- if( pWinMemData->bOwned ){
-- if( !osHeapDestroy(pWinMemData->hHeap) ){
-- sqlite3_log(SQLITE_NOMEM, "failed to HeapDestroy (%d), heap=%p",
-- osGetLastError(), (void*)pWinMemData->hHeap);
-- }
-- pWinMemData->bOwned = FALSE;
-- }
-- pWinMemData->hHeap = NULL;
-- }
--}
-
--/*
--** Populate the low-level memory allocation function pointers in
--** sqlite3GlobalConfig.m with pointers to the routines in this file. The
--** arguments specify the block of memory to manage.
--**
--** This routine is only called by sqlite3_config(), and therefore
--** is not required to be threadsafe (it is not).
--*/
--SQLITE_PRIVATE const sqlite3_mem_methods *sqlite3MemGetWin32(void){
-- static const sqlite3_mem_methods winMemMethods = {
-- winMemMalloc,
-- winMemFree,
-- winMemRealloc,
-- winMemSize,
-- winMemRoundup,
-- winMemInit,
-- winMemShutdown,
-- &win_mem_data
-- };
-- return &winMemMethods;
--}
-+#define osFreeLibrary ((BOOL(WINAPI*)(HMODULE))aSyscall[16].pCurrent)
-
--SQLITE_PRIVATE void sqlite3MemSetDefault(void){
-- sqlite3_config(SQLITE_CONFIG_MALLOC, sqlite3MemGetWin32());
--}
--#endif /* SQLITE_WIN32_MALLOC */
-+ { "GetCurrentProcessId", (SYSCALL)GetCurrentProcessId, 0 },
-
--/*
--** Convert a UTF-8 string to Microsoft Unicode (UTF-16?).
--**
--** Space to hold the returned string is obtained from malloc.
--*/
--static LPWSTR utf8ToUnicode(const char *zFilename){
-- int nChar;
-- LPWSTR zWideFilename;
-+#define osGetCurrentProcessId ((DWORD(WINAPI*)(VOID))aSyscall[17].pCurrent)
-
-- nChar = osMultiByteToWideChar(CP_UTF8, 0, zFilename, -1, NULL, 0);
-- if( nChar==0 ){
-- return 0;
-- }
-- zWideFilename = sqlite3MallocZero( nChar*sizeof(zWideFilename[0]) );
-- if( zWideFilename==0 ){
-- return 0;
-- }
-- nChar = osMultiByteToWideChar(CP_UTF8, 0, zFilename, -1, zWideFilename,
-- nChar);
-- if( nChar==0 ){
-- sqlite3_free(zWideFilename);
-- zWideFilename = 0;
-- }
-- return zWideFilename;
--}
-+#if !SQLITE_OS_WINCE && defined(SQLITE_WIN32_HAS_ANSI)
-+ { "GetDiskFreeSpaceA", (SYSCALL)GetDiskFreeSpaceA, 0 },
-+#else
-+ { "GetDiskFreeSpaceA", (SYSCALL)0, 0 },
-+#endif
-
--/*
--** Convert Microsoft Unicode to UTF-8. Space to hold the returned string is
--** obtained from sqlite3_malloc().
--*/
--static char *unicodeToUtf8(LPCWSTR zWideFilename){
-- int nByte;
-- char *zFilename;
-+#define osGetDiskFreeSpaceA ((BOOL(WINAPI*)(LPCSTR,LPDWORD,LPDWORD,LPDWORD, \
-+ LPDWORD))aSyscall[18].pCurrent)
-
-- nByte = osWideCharToMultiByte(CP_UTF8, 0, zWideFilename, -1, 0, 0, 0, 0);
-- if( nByte == 0 ){
-- return 0;
-- }
-- zFilename = sqlite3MallocZero( nByte );
-- if( zFilename==0 ){
-- return 0;
-- }
-- nByte = osWideCharToMultiByte(CP_UTF8, 0, zWideFilename, -1, zFilename, nByte,
-- 0, 0);
-- if( nByte == 0 ){
-- sqlite3_free(zFilename);
-- zFilename = 0;
-- }
-- return zFilename;
--}
-+#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE)
-+ { "GetDiskFreeSpaceW", (SYSCALL)GetDiskFreeSpaceW, 0 },
-+#else
-+ { "GetDiskFreeSpaceW", (SYSCALL)0, 0 },
-+#endif
-
--/*
--** Convert an ANSI string to Microsoft Unicode, based on the
--** current codepage settings for file apis.
--**
--** Space to hold the returned string is obtained
--** from sqlite3_malloc.
--*/
--static LPWSTR mbcsToUnicode(const char *zFilename){
-- int nByte;
-- LPWSTR zMbcsFilename;
-- int codepage = osAreFileApisANSI() ? CP_ACP : CP_OEMCP;
-+#define osGetDiskFreeSpaceW ((BOOL(WINAPI*)(LPCWSTR,LPDWORD,LPDWORD,LPDWORD, \
-+ LPDWORD))aSyscall[19].pCurrent)
-
-- nByte = osMultiByteToWideChar(codepage, 0, zFilename, -1, NULL,
-- 0)*sizeof(WCHAR);
-- if( nByte==0 ){
-- return 0;
-- }
-- zMbcsFilename = sqlite3MallocZero( nByte*sizeof(zMbcsFilename[0]) );
-- if( zMbcsFilename==0 ){
-- return 0;
-- }
-- nByte = osMultiByteToWideChar(codepage, 0, zFilename, -1, zMbcsFilename,
-- nByte);
-- if( nByte==0 ){
-- sqlite3_free(zMbcsFilename);
-- zMbcsFilename = 0;
-- }
-- return zMbcsFilename;
--}
-+#if defined(SQLITE_WIN32_HAS_ANSI)
-+ { "GetFileAttributesA", (SYSCALL)GetFileAttributesA, 0 },
-+#else
-+ { "GetFileAttributesA", (SYSCALL)0, 0 },
-+#endif
-
--/*
--** Convert Microsoft Unicode to multi-byte character string, based on the
--** user's ANSI codepage.
--**
--** Space to hold the returned string is obtained from
--** sqlite3_malloc().
--*/
--static char *unicodeToMbcs(LPCWSTR zWideFilename){
-- int nByte;
-- char *zFilename;
-- int codepage = osAreFileApisANSI() ? CP_ACP : CP_OEMCP;
-+#define osGetFileAttributesA ((DWORD(WINAPI*)(LPCSTR))aSyscall[20].pCurrent)
-
-- nByte = osWideCharToMultiByte(codepage, 0, zWideFilename, -1, 0, 0, 0, 0);
-- if( nByte == 0 ){
-- return 0;
-- }
-- zFilename = sqlite3MallocZero( nByte );
-- if( zFilename==0 ){
-- return 0;
-- }
-- nByte = osWideCharToMultiByte(codepage, 0, zWideFilename, -1, zFilename,
-- nByte, 0, 0);
-- if( nByte == 0 ){
-- sqlite3_free(zFilename);
-- zFilename = 0;
-- }
-- return zFilename;
--}
-+#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE)
-+ { "GetFileAttributesW", (SYSCALL)GetFileAttributesW, 0 },
-+#else
-+ { "GetFileAttributesW", (SYSCALL)0, 0 },
-+#endif
-
--/*
--** Convert multibyte character string to UTF-8. Space to hold the
--** returned string is obtained from sqlite3_malloc().
--*/
--SQLITE_API char *sqlite3_win32_mbcs_to_utf8(const char *zFilename){
-- char *zFilenameUtf8;
-- LPWSTR zTmpWide;
-+#define osGetFileAttributesW ((DWORD(WINAPI*)(LPCWSTR))aSyscall[21].pCurrent)
-
-- zTmpWide = mbcsToUnicode(zFilename);
-- if( zTmpWide==0 ){
-- return 0;
-- }
-- zFilenameUtf8 = unicodeToUtf8(zTmpWide);
-- sqlite3_free(zTmpWide);
-- return zFilenameUtf8;
--}
-+#if defined(SQLITE_WIN32_HAS_WIDE)
-+ { "GetFileAttributesExW", (SYSCALL)GetFileAttributesExW, 0 },
-+#else
-+ { "GetFileAttributesExW", (SYSCALL)0, 0 },
-+#endif
-
--/*
--** Convert UTF-8 to multibyte character string. Space to hold the
--** returned string is obtained from sqlite3_malloc().
--*/
--SQLITE_API char *sqlite3_win32_utf8_to_mbcs(const char *zFilename){
-- char *zFilenameMbcs;
-- LPWSTR zTmpWide;
-+#define osGetFileAttributesExW ((BOOL(WINAPI*)(LPCWSTR,GET_FILEEX_INFO_LEVELS, \
-+ LPVOID))aSyscall[22].pCurrent)
-
-- zTmpWide = utf8ToUnicode(zFilename);
-- if( zTmpWide==0 ){
-- return 0;
-- }
-- zFilenameMbcs = unicodeToMbcs(zTmpWide);
-- sqlite3_free(zTmpWide);
-- return zFilenameMbcs;
--}
-+#if !SQLITE_OS_WINRT
-+ { "GetFileSize", (SYSCALL)GetFileSize, 0 },
-+#else
-+ { "GetFileSize", (SYSCALL)0, 0 },
-+#endif
-
--/*
--** This function sets the data directory or the temporary directory based on
--** the provided arguments. The type argument must be 1 in order to set the
--** data directory or 2 in order to set the temporary directory. The zValue
--** argument is the name of the directory to use. The return value will be
--** SQLITE_OK if successful.
--*/
--SQLITE_API int sqlite3_win32_set_directory(DWORD type, LPCWSTR zValue){
-- char **ppDirectory = 0;
--#ifndef SQLITE_OMIT_AUTOINIT
-- int rc = sqlite3_initialize();
-- if( rc ) return rc;
-+#define osGetFileSize ((DWORD(WINAPI*)(HANDLE,LPDWORD))aSyscall[23].pCurrent)
-+
-+#if !SQLITE_OS_WINCE && defined(SQLITE_WIN32_HAS_ANSI)
-+ { "GetFullPathNameA", (SYSCALL)GetFullPathNameA, 0 },
-+#else
-+ { "GetFullPathNameA", (SYSCALL)0, 0 },
- #endif
-- if( type==SQLITE_WIN32_DATA_DIRECTORY_TYPE ){
-- ppDirectory = &sqlite3_data_directory;
-- }else if( type==SQLITE_WIN32_TEMP_DIRECTORY_TYPE ){
-- ppDirectory = &sqlite3_temp_directory;
-- }
-- assert( !ppDirectory || type==SQLITE_WIN32_DATA_DIRECTORY_TYPE
-- || type==SQLITE_WIN32_TEMP_DIRECTORY_TYPE
-- );
-- assert( !ppDirectory || sqlite3MemdebugHasType(*ppDirectory, MEMTYPE_HEAP) );
-- if( ppDirectory ){
-- char *zValueUtf8 = 0;
-- if( zValue && zValue[0] ){
-- zValueUtf8 = unicodeToUtf8(zValue);
-- if ( zValueUtf8==0 ){
-- return SQLITE_NOMEM;
-- }
-- }
-- sqlite3_free(*ppDirectory);
-- *ppDirectory = zValueUtf8;
-- return SQLITE_OK;
-- }
-- return SQLITE_ERROR;
--}
-
--/*
--** The return value of getLastErrorMsg
--** is zero if the error message fits in the buffer, or non-zero
--** otherwise (if the message was truncated).
--*/
--static int getLastErrorMsg(DWORD lastErrno, int nBuf, char *zBuf){
-- /* FormatMessage returns 0 on failure. Otherwise it
-- ** returns the number of TCHARs written to the output
-- ** buffer, excluding the terminating null char.
-- */
-- DWORD dwLen = 0;
-- char *zOut = 0;
-+#define osGetFullPathNameA ((DWORD(WINAPI*)(LPCSTR,DWORD,LPSTR, \
-+ LPSTR*))aSyscall[24].pCurrent)
-
-- if( isNT() ){
--#if SQLITE_OS_WINRT
-- WCHAR zTempWide[MAX_PATH+1]; /* NOTE: Somewhat arbitrary. */
-- dwLen = osFormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM |
-- FORMAT_MESSAGE_IGNORE_INSERTS,
-- NULL,
-- lastErrno,
-- 0,
-- zTempWide,
-- MAX_PATH,
-- 0);
-+#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE)
-+ { "GetFullPathNameW", (SYSCALL)GetFullPathNameW, 0 },
- #else
-- LPWSTR zTempWide = NULL;
-- dwLen = osFormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |
-- FORMAT_MESSAGE_FROM_SYSTEM |
-- FORMAT_MESSAGE_IGNORE_INSERTS,
-- NULL,
-- lastErrno,
-- 0,
-- (LPWSTR) &zTempWide,
-- 0,
-- 0);
-+ { "GetFullPathNameW", (SYSCALL)0, 0 },
- #endif
-- if( dwLen > 0 ){
-- /* allocate a buffer and convert to UTF8 */
-- sqlite3BeginBenignMalloc();
-- zOut = unicodeToUtf8(zTempWide);
-- sqlite3EndBenignMalloc();
-+
-+#define osGetFullPathNameW ((DWORD(WINAPI*)(LPCWSTR,DWORD,LPWSTR, \
-+ LPWSTR*))aSyscall[25].pCurrent)
-+
-+ { "GetLastError", (SYSCALL)GetLastError, 0 },
-+
-+#define osGetLastError ((DWORD(WINAPI*)(VOID))aSyscall[26].pCurrent)
-+
-+#if !defined(SQLITE_OMIT_LOAD_EXTENSION)
-+#if SQLITE_OS_WINCE
-+ /* The GetProcAddressA() routine is only available on Windows CE. */
-+ { "GetProcAddressA", (SYSCALL)GetProcAddressA, 0 },
-+#else
-+ /* All other Windows platforms expect GetProcAddress() to take
-+ ** an ANSI string regardless of the _UNICODE setting */
-+ { "GetProcAddressA", (SYSCALL)GetProcAddress, 0 },
-+#endif
-+#else
-+ { "GetProcAddressA", (SYSCALL)0, 0 },
-+#endif
-+
-+#define osGetProcAddressA ((FARPROC(WINAPI*)(HMODULE, \
-+ LPCSTR))aSyscall[27].pCurrent)
-+
- #if !SQLITE_OS_WINRT
-- /* free the system buffer allocated by FormatMessage */
-- osLocalFree(zTempWide);
-+ { "GetSystemInfo", (SYSCALL)GetSystemInfo, 0 },
-+#else
-+ { "GetSystemInfo", (SYSCALL)0, 0 },
- #endif
-- }
-- }
--#ifdef SQLITE_WIN32_HAS_ANSI
-- else{
-- char *zTemp = NULL;
-- dwLen = osFormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER |
-- FORMAT_MESSAGE_FROM_SYSTEM |
-- FORMAT_MESSAGE_IGNORE_INSERTS,
-- NULL,
-- lastErrno,
-- 0,
-- (LPSTR) &zTemp,
-- 0,
-- 0);
-- if( dwLen > 0 ){
-- /* allocate a buffer and convert to UTF8 */
-- sqlite3BeginBenignMalloc();
-- zOut = sqlite3_win32_mbcs_to_utf8(zTemp);
-- sqlite3EndBenignMalloc();
-- /* free the system buffer allocated by FormatMessage */
-- osLocalFree(zTemp);
-- }
-- }
-+
-+#define osGetSystemInfo ((VOID(WINAPI*)(LPSYSTEM_INFO))aSyscall[28].pCurrent)
-+
-+ { "GetSystemTime", (SYSCALL)GetSystemTime, 0 },
-+
-+#define osGetSystemTime ((VOID(WINAPI*)(LPSYSTEMTIME))aSyscall[29].pCurrent)
-+
-+#if !SQLITE_OS_WINCE
-+ { "GetSystemTimeAsFileTime", (SYSCALL)GetSystemTimeAsFileTime, 0 },
-+#else
-+ { "GetSystemTimeAsFileTime", (SYSCALL)0, 0 },
-+#endif
-+
-+#define osGetSystemTimeAsFileTime ((VOID(WINAPI*)( \
-+ LPFILETIME))aSyscall[30].pCurrent)
-+
-+#if defined(SQLITE_WIN32_HAS_ANSI)
-+ { "GetTempPathA", (SYSCALL)GetTempPathA, 0 },
-+#else
-+ { "GetTempPathA", (SYSCALL)0, 0 },
- #endif
-- if( 0 == dwLen ){
-- sqlite3_snprintf(nBuf, zBuf, "OsError 0x%lx (%lu)", lastErrno, lastErrno);
-- }else{
-- /* copy a maximum of nBuf chars to output buffer */
-- sqlite3_snprintf(nBuf, zBuf, "%s", zOut);
-- /* free the UTF8 buffer */
-- sqlite3_free(zOut);
-- }
-- return 0;
--}
-
--/*
--**
--** This function - winLogErrorAtLine() - is only ever called via the macro
--** winLogError().
--**
--** This routine is invoked after an error occurs in an OS function.
--** It logs a message using sqlite3_log() containing the current value of
--** error code and, if possible, the human-readable equivalent from
--** FormatMessage.
--**
--** The first argument passed to the macro should be the error code that
--** will be returned to SQLite (e.g. SQLITE_IOERR_DELETE, SQLITE_CANTOPEN).
--** The two subsequent arguments should be the name of the OS function that
--** failed and the associated file-system path, if any.
--*/
--#define winLogError(a,b,c,d) winLogErrorAtLine(a,b,c,d,__LINE__)
--static int winLogErrorAtLine(
-- int errcode, /* SQLite error code */
-- DWORD lastErrno, /* Win32 last error */
-- const char *zFunc, /* Name of OS function that failed */
-- const char *zPath, /* File path associated with error */
-- int iLine /* Source line number where error occurred */
--){
-- char zMsg[500]; /* Human readable error text */
-- int i; /* Loop counter */
-+#define osGetTempPathA ((DWORD(WINAPI*)(DWORD,LPSTR))aSyscall[31].pCurrent)
-
-- zMsg[0] = 0;
-- getLastErrorMsg(lastErrno, sizeof(zMsg), zMsg);
-- assert( errcode!=SQLITE_OK );
-- if( zPath==0 ) zPath = "";
-- for(i=0; zMsg[i] && zMsg[i]!='\r' && zMsg[i]!='\n'; i++){}
-- zMsg[i] = 0;
-- sqlite3_log(errcode,
-- "os_win.c:%d: (%lu) %s(%s) - %s",
-- iLine, lastErrno, zFunc, zPath, zMsg
-- );
-+#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE)
-+ { "GetTempPathW", (SYSCALL)GetTempPathW, 0 },
-+#else
-+ { "GetTempPathW", (SYSCALL)0, 0 },
-+#endif
-
-- return errcode;
--}
-+#define osGetTempPathW ((DWORD(WINAPI*)(DWORD,LPWSTR))aSyscall[32].pCurrent)
-
--/*
--** The number of times that a ReadFile(), WriteFile(), and DeleteFile()
--** will be retried following a locking error - probably caused by
--** antivirus software. Also the initial delay before the first retry.
--** The delay increases linearly with each retry.
--*/
--#ifndef SQLITE_WIN32_IOERR_RETRY
--# define SQLITE_WIN32_IOERR_RETRY 10
-+#if !SQLITE_OS_WINRT
-+ { "GetTickCount", (SYSCALL)GetTickCount, 0 },
-+#else
-+ { "GetTickCount", (SYSCALL)0, 0 },
- #endif
--#ifndef SQLITE_WIN32_IOERR_RETRY_DELAY
--# define SQLITE_WIN32_IOERR_RETRY_DELAY 25
-+
-+#define osGetTickCount ((DWORD(WINAPI*)(VOID))aSyscall[33].pCurrent)
-+
-+#if defined(SQLITE_WIN32_HAS_ANSI)
-+ { "GetVersionExA", (SYSCALL)GetVersionExA, 0 },
-+#else
-+ { "GetVersionExA", (SYSCALL)0, 0 },
- #endif
--static int win32IoerrRetry = SQLITE_WIN32_IOERR_RETRY;
--static int win32IoerrRetryDelay = SQLITE_WIN32_IOERR_RETRY_DELAY;
-
--/*
--** If a ReadFile() or WriteFile() error occurs, invoke this routine
--** to see if it should be retried. Return TRUE to retry. Return FALSE
--** to give up with an error.
--*/
--static int retryIoerr(int *pnRetry, DWORD *pError){
-- DWORD e = osGetLastError();
-- if( *pnRetry>=win32IoerrRetry ){
-- if( pError ){
-- *pError = e;
-- }
-- return 0;
-- }
-- if( e==ERROR_ACCESS_DENIED ||
-- e==ERROR_LOCK_VIOLATION ||
-- e==ERROR_SHARING_VIOLATION ){
-- sqlite3_win32_sleep(win32IoerrRetryDelay*(1+*pnRetry));
-- ++*pnRetry;
-- return 1;
-- }
-- if( pError ){
-- *pError = e;
-- }
-- return 0;
--}
-+#define osGetVersionExA ((BOOL(WINAPI*)( \
-+ LPOSVERSIONINFOA))aSyscall[34].pCurrent)
-
--/*
--** Log a I/O error retry episode.
--*/
--static void logIoerr(int nRetry){
-- if( nRetry ){
-- sqlite3_log(SQLITE_IOERR,
-- "delayed %dms for lock/sharing conflict",
-- win32IoerrRetryDelay*nRetry*(nRetry+1)/2
-- );
-- }
--}
-+ { "HeapAlloc", (SYSCALL)HeapAlloc, 0 },
-
--#if SQLITE_OS_WINCE
--/*************************************************************************
--** This section contains code for WinCE only.
--*/
--#if !defined(SQLITE_MSVC_LOCALTIME_API) || !SQLITE_MSVC_LOCALTIME_API
--/*
--** The MSVC CRT on Windows CE may not have a localtime() function. So
--** create a substitute.
--*/
--/* #include <time.h> */
--struct tm *__cdecl localtime(const time_t *t)
--{
-- static struct tm y;
-- FILETIME uTm, lTm;
-- SYSTEMTIME pTm;
-- sqlite3_int64 t64;
-- t64 = *t;
-- t64 = (t64 + 11644473600)*10000000;
-- uTm.dwLowDateTime = (DWORD)(t64 & 0xFFFFFFFF);
-- uTm.dwHighDateTime= (DWORD)(t64 >> 32);
-- osFileTimeToLocalFileTime(&uTm,&lTm);
-- osFileTimeToSystemTime(&lTm,&pTm);
-- y.tm_year = pTm.wYear - 1900;
-- y.tm_mon = pTm.wMonth - 1;
-- y.tm_wday = pTm.wDayOfWeek;
-- y.tm_mday = pTm.wDay;
-- y.tm_hour = pTm.wHour;
-- y.tm_min = pTm.wMinute;
-- y.tm_sec = pTm.wSecond;
-- return &y;
--}
-+#define osHeapAlloc ((LPVOID(WINAPI*)(HANDLE,DWORD, \
-+ SIZE_T))aSyscall[35].pCurrent)
-+
-+#if !SQLITE_OS_WINRT
-+ { "HeapCreate", (SYSCALL)HeapCreate, 0 },
-+#else
-+ { "HeapCreate", (SYSCALL)0, 0 },
- #endif
-
--#define HANDLE_TO_WINFILE(a) (winFile*)&((char*)a)[-(int)offsetof(winFile,h)]
-+#define osHeapCreate ((HANDLE(WINAPI*)(DWORD,SIZE_T, \
-+ SIZE_T))aSyscall[36].pCurrent)
-
--/*
--** Acquire a lock on the handle h
--*/
--static void winceMutexAcquire(HANDLE h){
-- DWORD dwErr;
-- do {
-- dwErr = osWaitForSingleObject(h, INFINITE);
-- } while (dwErr != WAIT_OBJECT_0 && dwErr != WAIT_ABANDONED);
--}
--/*
--** Release a lock acquired by winceMutexAcquire()
--*/
--#define winceMutexRelease(h) ReleaseMutex(h)
-+#if !SQLITE_OS_WINRT
-+ { "HeapDestroy", (SYSCALL)HeapDestroy, 0 },
-+#else
-+ { "HeapDestroy", (SYSCALL)0, 0 },
-+#endif
-
--/*
--** Create the mutex and shared memory used for locking in the file
--** descriptor pFile
--*/
--static int winceCreateLock(const char *zFilename, winFile *pFile){
-- LPWSTR zTok;
-- LPWSTR zName;
-- DWORD lastErrno;
-- BOOL bLogged = FALSE;
-- BOOL bInit = TRUE;
-+#define osHeapDestroy ((BOOL(WINAPI*)(HANDLE))aSyscall[37].pCurrent)
-
-- zName = utf8ToUnicode(zFilename);
-- if( zName==0 ){
-- /* out of memory */
-- return SQLITE_IOERR_NOMEM;
-- }
-+ { "HeapFree", (SYSCALL)HeapFree, 0 },
-
-- /* Initialize the local lockdata */
-- memset(&pFile->local, 0, sizeof(pFile->local));
-+#define osHeapFree ((BOOL(WINAPI*)(HANDLE,DWORD,LPVOID))aSyscall[38].pCurrent)
-
-- /* Replace the backslashes from the filename and lowercase it
-- ** to derive a mutex name. */
-- zTok = osCharLowerW(zName);
-- for (;*zTok;zTok++){
-- if (*zTok == '\\') *zTok = '_';
-- }
-+ { "HeapReAlloc", (SYSCALL)HeapReAlloc, 0 },
-
-- /* Create/open the named mutex */
-- pFile->hMutex = osCreateMutexW(NULL, FALSE, zName);
-- if (!pFile->hMutex){
-- pFile->lastErrno = osGetLastError();
-- winLogError(SQLITE_IOERR, pFile->lastErrno,
-- "winceCreateLock1", zFilename);
-- sqlite3_free(zName);
-- return SQLITE_IOERR;
-- }
-+#define osHeapReAlloc ((LPVOID(WINAPI*)(HANDLE,DWORD,LPVOID, \
-+ SIZE_T))aSyscall[39].pCurrent)
-
-- /* Acquire the mutex before continuing */
-- winceMutexAcquire(pFile->hMutex);
--
-- /* Since the names of named mutexes, semaphores, file mappings etc are
-- ** case-sensitive, take advantage of that by uppercasing the mutex name
-- ** and using that as the shared filemapping name.
-- */
-- osCharUpperW(zName);
-- pFile->hShared = osCreateFileMappingW(INVALID_HANDLE_VALUE, NULL,
-- PAGE_READWRITE, 0, sizeof(winceLock),
-- zName);
-+ { "HeapSize", (SYSCALL)HeapSize, 0 },
-
-- /* Set a flag that indicates we're the first to create the memory so it
-- ** must be zero-initialized */
-- lastErrno = osGetLastError();
-- if (lastErrno == ERROR_ALREADY_EXISTS){
-- bInit = FALSE;
-- }
-+#define osHeapSize ((SIZE_T(WINAPI*)(HANDLE,DWORD, \
-+ LPCVOID))aSyscall[40].pCurrent)
-
-- sqlite3_free(zName);
-+#if !SQLITE_OS_WINRT
-+ { "HeapValidate", (SYSCALL)HeapValidate, 0 },
-+#else
-+ { "HeapValidate", (SYSCALL)0, 0 },
-+#endif
-
-- /* If we succeeded in making the shared memory handle, map it. */
-- if( pFile->hShared ){
-- pFile->shared = (winceLock*)osMapViewOfFile(pFile->hShared,
-- FILE_MAP_READ|FILE_MAP_WRITE, 0, 0, sizeof(winceLock));
-- /* If mapping failed, close the shared memory handle and erase it */
-- if( !pFile->shared ){
-- pFile->lastErrno = osGetLastError();
-- winLogError(SQLITE_IOERR, pFile->lastErrno,
-- "winceCreateLock2", zFilename);
-- bLogged = TRUE;
-- osCloseHandle(pFile->hShared);
-- pFile->hShared = NULL;
-- }
-- }
-+#define osHeapValidate ((BOOL(WINAPI*)(HANDLE,DWORD, \
-+ LPCVOID))aSyscall[41].pCurrent)
-
-- /* If shared memory could not be created, then close the mutex and fail */
-- if( pFile->hShared==NULL ){
-- if( !bLogged ){
-- pFile->lastErrno = lastErrno;
-- winLogError(SQLITE_IOERR, pFile->lastErrno,
-- "winceCreateLock3", zFilename);
-- bLogged = TRUE;
-- }
-- winceMutexRelease(pFile->hMutex);
-- osCloseHandle(pFile->hMutex);
-- pFile->hMutex = NULL;
-- return SQLITE_IOERR;
-- }
--
-- /* Initialize the shared memory if we're supposed to */
-- if( bInit ){
-- memset(pFile->shared, 0, sizeof(winceLock));
-- }
-+#if defined(SQLITE_WIN32_HAS_ANSI) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
-+ { "LoadLibraryA", (SYSCALL)LoadLibraryA, 0 },
-+#else
-+ { "LoadLibraryA", (SYSCALL)0, 0 },
-+#endif
-
-- winceMutexRelease(pFile->hMutex);
-- return SQLITE_OK;
--}
-+#define osLoadLibraryA ((HMODULE(WINAPI*)(LPCSTR))aSyscall[42].pCurrent)
-
--/*
--** Destroy the part of winFile that deals with wince locks
--*/
--static void winceDestroyLock(winFile *pFile){
-- if (pFile->hMutex){
-- /* Acquire the mutex */
-- winceMutexAcquire(pFile->hMutex);
-+#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) && \
-+ !defined(SQLITE_OMIT_LOAD_EXTENSION)
-+ { "LoadLibraryW", (SYSCALL)LoadLibraryW, 0 },
-+#else
-+ { "LoadLibraryW", (SYSCALL)0, 0 },
-+#endif
-
-- /* The following blocks should probably assert in debug mode, but they
-- are to cleanup in case any locks remained open */
-- if (pFile->local.nReaders){
-- pFile->shared->nReaders --;
-- }
-- if (pFile->local.bReserved){
-- pFile->shared->bReserved = FALSE;
-- }
-- if (pFile->local.bPending){
-- pFile->shared->bPending = FALSE;
-- }
-- if (pFile->local.bExclusive){
-- pFile->shared->bExclusive = FALSE;
-- }
-+#define osLoadLibraryW ((HMODULE(WINAPI*)(LPCWSTR))aSyscall[43].pCurrent)
-
-- /* De-reference and close our copy of the shared memory handle */
-- osUnmapViewOfFile(pFile->shared);
-- osCloseHandle(pFile->hShared);
-+#if !SQLITE_OS_WINRT
-+ { "LocalFree", (SYSCALL)LocalFree, 0 },
-+#else
-+ { "LocalFree", (SYSCALL)0, 0 },
-+#endif
-
-- /* Done with the mutex */
-- winceMutexRelease(pFile->hMutex);
-- osCloseHandle(pFile->hMutex);
-- pFile->hMutex = NULL;
-- }
--}
-+#define osLocalFree ((HLOCAL(WINAPI*)(HLOCAL))aSyscall[44].pCurrent)
-
--/*
--** An implementation of the LockFile() API of Windows for CE
--*/
--static BOOL winceLockFile(
-- LPHANDLE phFile,
-- DWORD dwFileOffsetLow,
-- DWORD dwFileOffsetHigh,
-- DWORD nNumberOfBytesToLockLow,
-- DWORD nNumberOfBytesToLockHigh
--){
-- winFile *pFile = HANDLE_TO_WINFILE(phFile);
-- BOOL bReturn = FALSE;
-+#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT
-+ { "LockFile", (SYSCALL)LockFile, 0 },
-+#else
-+ { "LockFile", (SYSCALL)0, 0 },
-+#endif
-
-- UNUSED_PARAMETER(dwFileOffsetHigh);
-- UNUSED_PARAMETER(nNumberOfBytesToLockHigh);
-+#ifndef osLockFile
-+#define osLockFile ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \
-+ DWORD))aSyscall[45].pCurrent)
-+#endif
-
-- if (!pFile->hMutex) return TRUE;
-- winceMutexAcquire(pFile->hMutex);
-+#if !SQLITE_OS_WINCE
-+ { "LockFileEx", (SYSCALL)LockFileEx, 0 },
-+#else
-+ { "LockFileEx", (SYSCALL)0, 0 },
-+#endif
-
-- /* Wanting an exclusive lock? */
-- if (dwFileOffsetLow == (DWORD)SHARED_FIRST
-- && nNumberOfBytesToLockLow == (DWORD)SHARED_SIZE){
-- if (pFile->shared->nReaders == 0 && pFile->shared->bExclusive == 0){
-- pFile->shared->bExclusive = TRUE;
-- pFile->local.bExclusive = TRUE;
-- bReturn = TRUE;
-- }
-- }
-+#ifndef osLockFileEx
-+#define osLockFileEx ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD,DWORD, \
-+ LPOVERLAPPED))aSyscall[46].pCurrent)
-+#endif
-
-- /* Want a read-only lock? */
-- else if (dwFileOffsetLow == (DWORD)SHARED_FIRST &&
-- nNumberOfBytesToLockLow == 1){
-- if (pFile->shared->bExclusive == 0){
-- pFile->local.nReaders ++;
-- if (pFile->local.nReaders == 1){
-- pFile->shared->nReaders ++;
-- }
-- bReturn = TRUE;
-- }
-- }
-+#if SQLITE_OS_WINCE || (!SQLITE_OS_WINRT && !defined(SQLITE_OMIT_WAL))
-+ { "MapViewOfFile", (SYSCALL)MapViewOfFile, 0 },
-+#else
-+ { "MapViewOfFile", (SYSCALL)0, 0 },
-+#endif
-
-- /* Want a pending lock? */
-- else if (dwFileOffsetLow == (DWORD)PENDING_BYTE
-- && nNumberOfBytesToLockLow == 1){
-- /* If no pending lock has been acquired, then acquire it */
-- if (pFile->shared->bPending == 0) {
-- pFile->shared->bPending = TRUE;
-- pFile->local.bPending = TRUE;
-- bReturn = TRUE;
-- }
-- }
-+#define osMapViewOfFile ((LPVOID(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \
-+ SIZE_T))aSyscall[47].pCurrent)
-
-- /* Want a reserved lock? */
-- else if (dwFileOffsetLow == (DWORD)RESERVED_BYTE
-- && nNumberOfBytesToLockLow == 1){
-- if (pFile->shared->bReserved == 0) {
-- pFile->shared->bReserved = TRUE;
-- pFile->local.bReserved = TRUE;
-- bReturn = TRUE;
-- }
-- }
-+ { "MultiByteToWideChar", (SYSCALL)MultiByteToWideChar, 0 },
-
-- winceMutexRelease(pFile->hMutex);
-- return bReturn;
--}
-+#define osMultiByteToWideChar ((int(WINAPI*)(UINT,DWORD,LPCSTR,int,LPWSTR, \
-+ int))aSyscall[48].pCurrent)
-
--/*
--** An implementation of the UnlockFile API of Windows for CE
--*/
--static BOOL winceUnlockFile(
-- LPHANDLE phFile,
-- DWORD dwFileOffsetLow,
-- DWORD dwFileOffsetHigh,
-- DWORD nNumberOfBytesToUnlockLow,
-- DWORD nNumberOfBytesToUnlockHigh
--){
-- winFile *pFile = HANDLE_TO_WINFILE(phFile);
-- BOOL bReturn = FALSE;
-+ { "QueryPerformanceCounter", (SYSCALL)QueryPerformanceCounter, 0 },
-
-- UNUSED_PARAMETER(dwFileOffsetHigh);
-- UNUSED_PARAMETER(nNumberOfBytesToUnlockHigh);
-+#define osQueryPerformanceCounter ((BOOL(WINAPI*)( \
-+ LARGE_INTEGER*))aSyscall[49].pCurrent)
-
-- if (!pFile->hMutex) return TRUE;
-- winceMutexAcquire(pFile->hMutex);
-+ { "ReadFile", (SYSCALL)ReadFile, 0 },
-
-- /* Releasing a reader lock or an exclusive lock */
-- if (dwFileOffsetLow == (DWORD)SHARED_FIRST){
-- /* Did we have an exclusive lock? */
-- if (pFile->local.bExclusive){
-- assert(nNumberOfBytesToUnlockLow == (DWORD)SHARED_SIZE);
-- pFile->local.bExclusive = FALSE;
-- pFile->shared->bExclusive = FALSE;
-- bReturn = TRUE;
-- }
-+#define osReadFile ((BOOL(WINAPI*)(HANDLE,LPVOID,DWORD,LPDWORD, \
-+ LPOVERLAPPED))aSyscall[50].pCurrent)
-
-- /* Did we just have a reader lock? */
-- else if (pFile->local.nReaders){
-- assert(nNumberOfBytesToUnlockLow == (DWORD)SHARED_SIZE
-- || nNumberOfBytesToUnlockLow == 1);
-- pFile->local.nReaders --;
-- if (pFile->local.nReaders == 0)
-- {
-- pFile->shared->nReaders --;
-- }
-- bReturn = TRUE;
-- }
-- }
-+ { "SetEndOfFile", (SYSCALL)SetEndOfFile, 0 },
-
-- /* Releasing a pending lock */
-- else if (dwFileOffsetLow == (DWORD)PENDING_BYTE
-- && nNumberOfBytesToUnlockLow == 1){
-- if (pFile->local.bPending){
-- pFile->local.bPending = FALSE;
-- pFile->shared->bPending = FALSE;
-- bReturn = TRUE;
-- }
-- }
-- /* Releasing a reserved lock */
-- else if (dwFileOffsetLow == (DWORD)RESERVED_BYTE
-- && nNumberOfBytesToUnlockLow == 1){
-- if (pFile->local.bReserved) {
-- pFile->local.bReserved = FALSE;
-- pFile->shared->bReserved = FALSE;
-- bReturn = TRUE;
-- }
-- }
-+#define osSetEndOfFile ((BOOL(WINAPI*)(HANDLE))aSyscall[51].pCurrent)
-
-- winceMutexRelease(pFile->hMutex);
-- return bReturn;
--}
--/*
--** End of the special code for wince
--*****************************************************************************/
--#endif /* SQLITE_OS_WINCE */
-+#if !SQLITE_OS_WINRT
-+ { "SetFilePointer", (SYSCALL)SetFilePointer, 0 },
-+#else
-+ { "SetFilePointer", (SYSCALL)0, 0 },
-+#endif
-
--/*
--** Lock a file region.
--*/
--static BOOL winLockFile(
-- LPHANDLE phFile,
-- DWORD flags,
-- DWORD offsetLow,
-- DWORD offsetHigh,
-- DWORD numBytesLow,
-- DWORD numBytesHigh
--){
--#if SQLITE_OS_WINCE
-- /*
-- ** NOTE: Windows CE is handled differently here due its lack of the Win32
-- ** API LockFile.
-- */
-- return winceLockFile(phFile, offsetLow, offsetHigh,
-- numBytesLow, numBytesHigh);
-+#define osSetFilePointer ((DWORD(WINAPI*)(HANDLE,LONG,PLONG, \
-+ DWORD))aSyscall[52].pCurrent)
-+
-+#if !SQLITE_OS_WINRT
-+ { "Sleep", (SYSCALL)Sleep, 0 },
-+#else
-+ { "Sleep", (SYSCALL)0, 0 },
-+#endif
-+
-+#define osSleep ((VOID(WINAPI*)(DWORD))aSyscall[53].pCurrent)
-+
-+ { "SystemTimeToFileTime", (SYSCALL)SystemTimeToFileTime, 0 },
-+
-+#define osSystemTimeToFileTime ((BOOL(WINAPI*)(CONST SYSTEMTIME*, \
-+ LPFILETIME))aSyscall[54].pCurrent)
-+
-+#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT
-+ { "UnlockFile", (SYSCALL)UnlockFile, 0 },
- #else
-- if( isNT() ){
-- OVERLAPPED ovlp;
-- memset(&ovlp, 0, sizeof(OVERLAPPED));
-- ovlp.Offset = offsetLow;
-- ovlp.OffsetHigh = offsetHigh;
-- return osLockFileEx(*phFile, flags, 0, numBytesLow, numBytesHigh, &ovlp);
-- }else{
-- return osLockFile(*phFile, offsetLow, offsetHigh, numBytesLow,
-- numBytesHigh);
-- }
-+ { "UnlockFile", (SYSCALL)0, 0 },
- #endif
--}
-
--/*
--** Unlock a file region.
-- */
--static BOOL winUnlockFile(
-- LPHANDLE phFile,
-- DWORD offsetLow,
-- DWORD offsetHigh,
-- DWORD numBytesLow,
-- DWORD numBytesHigh
--){
--#if SQLITE_OS_WINCE
-- /*
-- ** NOTE: Windows CE is handled differently here due its lack of the Win32
-- ** API UnlockFile.
-- */
-- return winceUnlockFile(phFile, offsetLow, offsetHigh,
-- numBytesLow, numBytesHigh);
-+#ifndef osUnlockFile
-+#define osUnlockFile ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \
-+ DWORD))aSyscall[55].pCurrent)
-+#endif
-+
-+#if !SQLITE_OS_WINCE
-+ { "UnlockFileEx", (SYSCALL)UnlockFileEx, 0 },
- #else
-- if( isNT() ){
-- OVERLAPPED ovlp;
-- memset(&ovlp, 0, sizeof(OVERLAPPED));
-- ovlp.Offset = offsetLow;
-- ovlp.OffsetHigh = offsetHigh;
-- return osUnlockFileEx(*phFile, 0, numBytesLow, numBytesHigh, &ovlp);
-- }else{
-- return osUnlockFile(*phFile, offsetLow, offsetHigh, numBytesLow,
-- numBytesHigh);
-- }
-+ { "UnlockFileEx", (SYSCALL)0, 0 },
- #endif
--}
-
--/*****************************************************************************
--** The next group of routines implement the I/O methods specified
--** by the sqlite3_io_methods object.
--******************************************************************************/
-+#define osUnlockFileEx ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \
-+ LPOVERLAPPED))aSyscall[56].pCurrent)
-
--/*
--** Some Microsoft compilers lack this definition.
--*/
--#ifndef INVALID_SET_FILE_POINTER
--# define INVALID_SET_FILE_POINTER ((DWORD)-1)
-+#if SQLITE_OS_WINCE || !defined(SQLITE_OMIT_WAL)
-+ { "UnmapViewOfFile", (SYSCALL)UnmapViewOfFile, 0 },
-+#else
-+ { "UnmapViewOfFile", (SYSCALL)0, 0 },
- #endif
-
--/*
--** Move the current position of the file handle passed as the first
--** argument to offset iOffset within the file. If successful, return 0.
--** Otherwise, set pFile->lastErrno and return non-zero.
--*/
--static int seekWinFile(winFile *pFile, sqlite3_int64 iOffset){
--#if !SQLITE_OS_WINRT
-- LONG upperBits; /* Most sig. 32 bits of new offset */
-- LONG lowerBits; /* Least sig. 32 bits of new offset */
-- DWORD dwRet; /* Value returned by SetFilePointer() */
-- DWORD lastErrno; /* Value returned by GetLastError() */
-+#define osUnmapViewOfFile ((BOOL(WINAPI*)(LPCVOID))aSyscall[57].pCurrent)
-
-- OSTRACE(("SEEK file=%p, offset=%lld\n", pFile->h, iOffset));
-+ { "WideCharToMultiByte", (SYSCALL)WideCharToMultiByte, 0 },
-
-- upperBits = (LONG)((iOffset>>32) & 0x7fffffff);
-- lowerBits = (LONG)(iOffset & 0xffffffff);
-+#define osWideCharToMultiByte ((int(WINAPI*)(UINT,DWORD,LPCWSTR,int,LPSTR,int, \
-+ LPCSTR,LPBOOL))aSyscall[58].pCurrent)
-
-- /* API oddity: If successful, SetFilePointer() returns a dword
-- ** containing the lower 32-bits of the new file-offset. Or, if it fails,
-- ** it returns INVALID_SET_FILE_POINTER. However according to MSDN,
-- ** INVALID_SET_FILE_POINTER may also be a valid new offset. So to determine
-- ** whether an error has actually occurred, it is also necessary to call
-- ** GetLastError().
-- */
-- dwRet = osSetFilePointer(pFile->h, lowerBits, &upperBits, FILE_BEGIN);
-+ { "WriteFile", (SYSCALL)WriteFile, 0 },
-
-- if( (dwRet==INVALID_SET_FILE_POINTER
-- && ((lastErrno = osGetLastError())!=NO_ERROR)) ){
-- pFile->lastErrno = lastErrno;
-- winLogError(SQLITE_IOERR_SEEK, pFile->lastErrno,
-- "seekWinFile", pFile->zPath);
-- OSTRACE(("SEEK file=%p, rc=SQLITE_IOERR_SEEK\n", pFile->h));
-- return 1;
-- }
-+#define osWriteFile ((BOOL(WINAPI*)(HANDLE,LPCVOID,DWORD,LPDWORD, \
-+ LPOVERLAPPED))aSyscall[59].pCurrent)
-
-- OSTRACE(("SEEK file=%p, rc=SQLITE_OK\n", pFile->h));
-- return 0;
-+#if SQLITE_OS_WINRT
-+ { "CreateEventExW", (SYSCALL)CreateEventExW, 0 },
- #else
-- /*
-- ** Same as above, except that this implementation works for WinRT.
-- */
-+ { "CreateEventExW", (SYSCALL)0, 0 },
-+#endif
-
-- LARGE_INTEGER x; /* The new offset */
-- BOOL bRet; /* Value returned by SetFilePointerEx() */
-+#define osCreateEventExW ((HANDLE(WINAPI*)(LPSECURITY_ATTRIBUTES,LPCWSTR, \
-+ DWORD,DWORD))aSyscall[60].pCurrent)
-
-- x.QuadPart = iOffset;
-- bRet = osSetFilePointerEx(pFile->h, x, 0, FILE_BEGIN);
-+#if !SQLITE_OS_WINRT
-+ { "WaitForSingleObject", (SYSCALL)WaitForSingleObject, 0 },
-+#else
-+ { "WaitForSingleObject", (SYSCALL)0, 0 },
-+#endif
-
-- if(!bRet){
-- pFile->lastErrno = osGetLastError();
-- winLogError(SQLITE_IOERR_SEEK, pFile->lastErrno,
-- "seekWinFile", pFile->zPath);
-- OSTRACE(("SEEK file=%p, rc=SQLITE_IOERR_SEEK\n", pFile->h));
-- return 1;
-- }
-+#define osWaitForSingleObject ((DWORD(WINAPI*)(HANDLE, \
-+ DWORD))aSyscall[61].pCurrent)
-
-- OSTRACE(("SEEK file=%p, rc=SQLITE_OK\n", pFile->h));
-- return 0;
-+#if SQLITE_OS_WINRT
-+ { "WaitForSingleObjectEx", (SYSCALL)WaitForSingleObjectEx, 0 },
-+#else
-+ { "WaitForSingleObjectEx", (SYSCALL)0, 0 },
- #endif
--}
-
--#if SQLITE_MAX_MMAP_SIZE>0
--/* Forward references to VFS methods */
--static int winUnmapfile(winFile*);
-+#define osWaitForSingleObjectEx ((DWORD(WINAPI*)(HANDLE,DWORD, \
-+ BOOL))aSyscall[62].pCurrent)
-+
-+#if SQLITE_OS_WINRT
-+ { "SetFilePointerEx", (SYSCALL)SetFilePointerEx, 0 },
-+#else
-+ { "SetFilePointerEx", (SYSCALL)0, 0 },
- #endif
-
--/*
--** Close a file.
--**
--** It is reported that an attempt to close a handle might sometimes
--** fail. This is a very unreasonable result, but Windows is notorious
--** for being unreasonable so I do not doubt that it might happen. If
--** the close fails, we pause for 100 milliseconds and try again. As
--** many as MX_CLOSE_ATTEMPT attempts to close the handle are made before
--** giving up and returning an error.
--*/
--#define MX_CLOSE_ATTEMPT 3
--static int winClose(sqlite3_file *id){
-- int rc, cnt = 0;
-- winFile *pFile = (winFile*)id;
-+#define osSetFilePointerEx ((BOOL(WINAPI*)(HANDLE,LARGE_INTEGER, \
-+ PLARGE_INTEGER,DWORD))aSyscall[63].pCurrent)
-
-- assert( id!=0 );
--#ifndef SQLITE_OMIT_WAL
-- assert( pFile->pShm==0 );
-+#if SQLITE_OS_WINRT
-+ { "GetFileInformationByHandleEx", (SYSCALL)GetFileInformationByHandleEx, 0 },
-+#else
-+ { "GetFileInformationByHandleEx", (SYSCALL)0, 0 },
- #endif
-- assert( pFile->h!=NULL && pFile->h!=INVALID_HANDLE_VALUE );
-- OSTRACE(("CLOSE file=%p\n", pFile->h));
-
--#if SQLITE_MAX_MMAP_SIZE>0
-- rc = winUnmapfile(pFile);
-- if( rc!=SQLITE_OK ) return rc;
--#endif
-+#define osGetFileInformationByHandleEx ((BOOL(WINAPI*)(HANDLE, \
-+ FILE_INFO_BY_HANDLE_CLASS,LPVOID,DWORD))aSyscall[64].pCurrent)
-
-- do{
-- rc = osCloseHandle(pFile->h);
-- /* SimulateIOError( rc=0; cnt=MX_CLOSE_ATTEMPT; ); */
-- }while( rc==0 && ++cnt < MX_CLOSE_ATTEMPT && (sqlite3_win32_sleep(100), 1) );
--#if SQLITE_OS_WINCE
--#define WINCE_DELETION_ATTEMPTS 3
-- winceDestroyLock(pFile);
-- if( pFile->zDeleteOnClose ){
-- int cnt = 0;
-- while(
-- osDeleteFileW(pFile->zDeleteOnClose)==0
-- && osGetFileAttributesW(pFile->zDeleteOnClose)!=0xffffffff
-- && cnt++ < WINCE_DELETION_ATTEMPTS
-- ){
-- sqlite3_win32_sleep(100); /* Wait a little before trying again */
-- }
-- sqlite3_free(pFile->zDeleteOnClose);
-- }
-+#if SQLITE_OS_WINRT && !defined(SQLITE_OMIT_WAL)
-+ { "MapViewOfFileFromApp", (SYSCALL)MapViewOfFileFromApp, 0 },
-+#else
-+ { "MapViewOfFileFromApp", (SYSCALL)0, 0 },
- #endif
-- if( rc ){
-- pFile->h = NULL;
-- }
-- OpenCounter(-1);
-- OSTRACE(("CLOSE file=%p, rc=%s\n", pFile->h, rc ? "ok" : "failed"));
-- return rc ? SQLITE_OK
-- : winLogError(SQLITE_IOERR_CLOSE, osGetLastError(),
-- "winClose", pFile->zPath);
--}
-
--/*
--** Read data from a file into a buffer. Return SQLITE_OK if all
--** bytes were read successfully and SQLITE_IOERR if anything goes
--** wrong.
--*/
--static int winRead(
-- sqlite3_file *id, /* File to read from */
-- void *pBuf, /* Write content into this buffer */
-- int amt, /* Number of bytes to read */
-- sqlite3_int64 offset /* Begin reading at this offset */
--){
--#if !SQLITE_OS_WINCE
-- OVERLAPPED overlapped; /* The offset for ReadFile. */
-+#define osMapViewOfFileFromApp ((LPVOID(WINAPI*)(HANDLE,ULONG,ULONG64, \
-+ SIZE_T))aSyscall[65].pCurrent)
-+
-+#if SQLITE_OS_WINRT
-+ { "CreateFile2", (SYSCALL)CreateFile2, 0 },
-+#else
-+ { "CreateFile2", (SYSCALL)0, 0 },
- #endif
-- winFile *pFile = (winFile*)id; /* file handle */
-- DWORD nRead; /* Number of bytes actually read from file */
-- int nRetry = 0; /* Number of retrys */
-
-- assert( id!=0 );
-- assert( amt>0 );
-- assert( offset>=0 );
-- SimulateIOError(return SQLITE_IOERR_READ);
-- OSTRACE(("READ file=%p, buffer=%p, amount=%d, offset=%lld, lock=%d\n",
-- pFile->h, pBuf, amt, offset, pFile->locktype));
-+#define osCreateFile2 ((HANDLE(WINAPI*)(LPCWSTR,DWORD,DWORD,DWORD, \
-+ LPCREATEFILE2_EXTENDED_PARAMETERS))aSyscall[66].pCurrent)
-
--#if SQLITE_MAX_MMAP_SIZE>0
-- /* Deal with as much of this read request as possible by transfering
-- ** data from the memory mapping using memcpy(). */
-- if( offset<pFile->mmapSize ){
-- if( offset+amt <= pFile->mmapSize ){
-- memcpy(pBuf, &((u8 *)(pFile->pMapRegion))[offset], amt);
-- OSTRACE(("READ-MMAP file=%p, rc=SQLITE_OK\n", pFile->h));
-- return SQLITE_OK;
-- }else{
-- int nCopy = (int)(pFile->mmapSize - offset);
-- memcpy(pBuf, &((u8 *)(pFile->pMapRegion))[offset], nCopy);
-- pBuf = &((u8 *)pBuf)[nCopy];
-- amt -= nCopy;
-- offset += nCopy;
-- }
-- }
-+#if SQLITE_OS_WINRT && !defined(SQLITE_OMIT_LOAD_EXTENSION)
-+ { "LoadPackagedLibrary", (SYSCALL)LoadPackagedLibrary, 0 },
-+#else
-+ { "LoadPackagedLibrary", (SYSCALL)0, 0 },
- #endif
-
--#if SQLITE_OS_WINCE
-- if( seekWinFile(pFile, offset) ){
-- OSTRACE(("READ file=%p, rc=SQLITE_FULL\n", pFile->h));
-- return SQLITE_FULL;
-- }
-- while( !osReadFile(pFile->h, pBuf, amt, &nRead, 0) ){
-+#define osLoadPackagedLibrary ((HMODULE(WINAPI*)(LPCWSTR, \
-+ DWORD))aSyscall[67].pCurrent)
-+
-+#if SQLITE_OS_WINRT
-+ { "GetTickCount64", (SYSCALL)GetTickCount64, 0 },
- #else
-- memset(&overlapped, 0, sizeof(OVERLAPPED));
-- overlapped.Offset = (LONG)(offset & 0xffffffff);
-- overlapped.OffsetHigh = (LONG)((offset>>32) & 0x7fffffff);
-- while( !osReadFile(pFile->h, pBuf, amt, &nRead, &overlapped) &&
-- osGetLastError()!=ERROR_HANDLE_EOF ){
-+ { "GetTickCount64", (SYSCALL)0, 0 },
- #endif
-- DWORD lastErrno;
-- if( retryIoerr(&nRetry, &lastErrno) ) continue;
-- pFile->lastErrno = lastErrno;
-- OSTRACE(("READ file=%p, rc=SQLITE_IOERR_READ\n", pFile->h));
-- return winLogError(SQLITE_IOERR_READ, pFile->lastErrno,
-- "winRead", pFile->zPath);
-- }
-- logIoerr(nRetry);
-- if( nRead<(DWORD)amt ){
-- /* Unread parts of the buffer must be zero-filled */
-- memset(&((char*)pBuf)[nRead], 0, amt-nRead);
-- OSTRACE(("READ file=%p, rc=SQLITE_IOERR_SHORT_READ\n", pFile->h));
-- return SQLITE_IOERR_SHORT_READ;
-- }
--
-- OSTRACE(("READ file=%p, rc=SQLITE_OK\n", pFile->h));
-- return SQLITE_OK;
--}
-
--/*
--** Write data from a buffer into a file. Return SQLITE_OK on success
--** or some other error code on failure.
--*/
--static int winWrite(
-- sqlite3_file *id, /* File to write into */
-- const void *pBuf, /* The bytes to be written */
-- int amt, /* Number of bytes to write */
-- sqlite3_int64 offset /* Offset into the file to begin writing at */
--){
-- int rc = 0; /* True if error has occurred, else false */
-- winFile *pFile = (winFile*)id; /* File handle */
-- int nRetry = 0; /* Number of retries */
-+#define osGetTickCount64 ((ULONGLONG(WINAPI*)(VOID))aSyscall[68].pCurrent)
-
-- assert( amt>0 );
-- assert( pFile );
-- SimulateIOError(return SQLITE_IOERR_WRITE);
-- SimulateDiskfullError(return SQLITE_FULL);
-+#if SQLITE_OS_WINRT
-+ { "GetNativeSystemInfo", (SYSCALL)GetNativeSystemInfo, 0 },
-+#else
-+ { "GetNativeSystemInfo", (SYSCALL)0, 0 },
-+#endif
-
-- OSTRACE(("WRITE file=%p, buffer=%p, amount=%d, offset=%lld, lock=%d\n",
-- pFile->h, pBuf, amt, offset, pFile->locktype));
-+#define osGetNativeSystemInfo ((VOID(WINAPI*)( \
-+ LPSYSTEM_INFO))aSyscall[69].pCurrent)
-
--#if SQLITE_MAX_MMAP_SIZE>0
-- /* Deal with as much of this write request as possible by transfering
-- ** data from the memory mapping using memcpy(). */
-- if( offset<pFile->mmapSize ){
-- if( offset+amt <= pFile->mmapSize ){
-- memcpy(&((u8 *)(pFile->pMapRegion))[offset], pBuf, amt);
-- OSTRACE(("WRITE-MMAP file=%p, rc=SQLITE_OK\n", pFile->h));
-- return SQLITE_OK;
-- }else{
-- int nCopy = (int)(pFile->mmapSize - offset);
-- memcpy(&((u8 *)(pFile->pMapRegion))[offset], pBuf, nCopy);
-- pBuf = &((u8 *)pBuf)[nCopy];
-- amt -= nCopy;
-- offset += nCopy;
-- }
-- }
-+#if defined(SQLITE_WIN32_HAS_ANSI)
-+ { "OutputDebugStringA", (SYSCALL)OutputDebugStringA, 0 },
-+#else
-+ { "OutputDebugStringA", (SYSCALL)0, 0 },
- #endif
-
--#if SQLITE_OS_WINCE
-- rc = seekWinFile(pFile, offset);
-- if( rc==0 ){
-+#define osOutputDebugStringA ((VOID(WINAPI*)(LPCSTR))aSyscall[70].pCurrent)
-+
-+#if defined(SQLITE_WIN32_HAS_WIDE)
-+ { "OutputDebugStringW", (SYSCALL)OutputDebugStringW, 0 },
- #else
-- {
--#endif
--#if !SQLITE_OS_WINCE
-- OVERLAPPED overlapped; /* The offset for WriteFile. */
-+ { "OutputDebugStringW", (SYSCALL)0, 0 },
- #endif
-- u8 *aRem = (u8 *)pBuf; /* Data yet to be written */
-- int nRem = amt; /* Number of bytes yet to be written */
-- DWORD nWrite; /* Bytes written by each WriteFile() call */
-- DWORD lastErrno = NO_ERROR; /* Value returned by GetLastError() */
-
--#if !SQLITE_OS_WINCE
-- memset(&overlapped, 0, sizeof(OVERLAPPED));
-- overlapped.Offset = (LONG)(offset & 0xffffffff);
-- overlapped.OffsetHigh = (LONG)((offset>>32) & 0x7fffffff);
--#endif
-+#define osOutputDebugStringW ((VOID(WINAPI*)(LPCWSTR))aSyscall[71].pCurrent)
-
-- while( nRem>0 ){
--#if SQLITE_OS_WINCE
-- if( !osWriteFile(pFile->h, aRem, nRem, &nWrite, 0) ){
-+ { "GetProcessHeap", (SYSCALL)GetProcessHeap, 0 },
-+
-+#define osGetProcessHeap ((HANDLE(WINAPI*)(VOID))aSyscall[72].pCurrent)
-+
-+#if SQLITE_OS_WINRT && !defined(SQLITE_OMIT_WAL)
-+ { "CreateFileMappingFromApp", (SYSCALL)CreateFileMappingFromApp, 0 },
- #else
-- if( !osWriteFile(pFile->h, aRem, nRem, &nWrite, &overlapped) ){
-+ { "CreateFileMappingFromApp", (SYSCALL)0, 0 },
- #endif
-- if( retryIoerr(&nRetry, &lastErrno) ) continue;
-- break;
-+
-+#define osCreateFileMappingFromApp ((HANDLE(WINAPI*)(HANDLE, \
-+ LPSECURITY_ATTRIBUTES,ULONG,ULONG64,LPCWSTR))aSyscall[73].pCurrent)
-+
-+}; /* End of the overrideable system calls */
-+
-+/*
-+** This is the xSetSystemCall() method of sqlite3_vfs for all of the
-+** "win32" VFSes. Return SQLITE_OK opon successfully updating the
-+** system call pointer, or SQLITE_NOTFOUND if there is no configurable
-+** system call named zName.
-+*/
-+static int winSetSystemCall(
-+ sqlite3_vfs *pNotUsed, /* The VFS pointer. Not used */
-+ const char *zName, /* Name of system call to override */
-+ sqlite3_syscall_ptr pNewFunc /* Pointer to new system call value */
-+){
-+ unsigned int i;
-+ int rc = SQLITE_NOTFOUND;
-+
-+ UNUSED_PARAMETER(pNotUsed);
-+ if( zName==0 ){
-+ /* If no zName is given, restore all system calls to their default
-+ ** settings and return NULL
-+ */
-+ rc = SQLITE_OK;
-+ for(i=0; i<sizeof(aSyscall)/sizeof(aSyscall[0]); i++){
-+ if( aSyscall[i].pDefault ){
-+ aSyscall[i].pCurrent = aSyscall[i].pDefault;
- }
-- assert( nWrite==0 || nWrite<=(DWORD)nRem );
-- if( nWrite==0 || nWrite>(DWORD)nRem ){
-- lastErrno = osGetLastError();
-+ }
-+ }else{
-+ /* If zName is specified, operate on only the one system call
-+ ** specified.
-+ */
-+ for(i=0; i<sizeof(aSyscall)/sizeof(aSyscall[0]); i++){
-+ if( strcmp(zName, aSyscall[i].zName)==0 ){
-+ if( aSyscall[i].pDefault==0 ){
-+ aSyscall[i].pDefault = aSyscall[i].pCurrent;
-+ }
-+ rc = SQLITE_OK;
-+ if( pNewFunc==0 ) pNewFunc = aSyscall[i].pDefault;
-+ aSyscall[i].pCurrent = pNewFunc;
- break;
- }
--#if !SQLITE_OS_WINCE
-- offset += nWrite;
-- overlapped.Offset = (LONG)(offset & 0xffffffff);
-- overlapped.OffsetHigh = (LONG)((offset>>32) & 0x7fffffff);
--#endif
-- aRem += nWrite;
-- nRem -= nWrite;
-- }
-- if( nRem>0 ){
-- pFile->lastErrno = lastErrno;
-- rc = 1;
-- }
-- }
--
-- if( rc ){
-- if( ( pFile->lastErrno==ERROR_HANDLE_DISK_FULL )
-- || ( pFile->lastErrno==ERROR_DISK_FULL )){
-- OSTRACE(("WRITE file=%p, rc=SQLITE_FULL\n", pFile->h));
-- return SQLITE_FULL;
- }
-- OSTRACE(("WRITE file=%p, rc=SQLITE_IOERR_WRITE\n", pFile->h));
-- return winLogError(SQLITE_IOERR_WRITE, pFile->lastErrno,
-- "winWrite", pFile->zPath);
-- }else{
-- logIoerr(nRetry);
- }
-- OSTRACE(("WRITE file=%p, rc=SQLITE_OK\n", pFile->h));
-- return SQLITE_OK;
-+ return rc;
- }
-
- /*
--** Truncate an open file to a specified size
-+** Return the value of a system call. Return NULL if zName is not a
-+** recognized system call name. NULL is also returned if the system call
-+** is currently undefined.
- */
--static int winTruncate(sqlite3_file *id, sqlite3_int64 nByte){
-- winFile *pFile = (winFile*)id; /* File handle object */
-- int rc = SQLITE_OK; /* Return code for this function */
-- DWORD lastErrno;
--
-- assert( pFile );
-- SimulateIOError(return SQLITE_IOERR_TRUNCATE);
-- OSTRACE(("TRUNCATE file=%p, size=%lld, lock=%d\n",
-- pFile->h, nByte, pFile->locktype));
--
-- /* If the user has configured a chunk-size for this file, truncate the
-- ** file so that it consists of an integer number of chunks (i.e. the
-- ** actual file size after the operation may be larger than the requested
-- ** size).
-- */
-- if( pFile->szChunk>0 ){
-- nByte = ((nByte + pFile->szChunk - 1)/pFile->szChunk) * pFile->szChunk;
-- }
--
-- /* SetEndOfFile() returns non-zero when successful, or zero when it fails. */
-- if( seekWinFile(pFile, nByte) ){
-- rc = winLogError(SQLITE_IOERR_TRUNCATE, pFile->lastErrno,
-- "winTruncate1", pFile->zPath);
-- }else if( 0==osSetEndOfFile(pFile->h) &&
-- ((lastErrno = osGetLastError())!=ERROR_USER_MAPPED_FILE) ){
-- pFile->lastErrno = lastErrno;
-- rc = winLogError(SQLITE_IOERR_TRUNCATE, pFile->lastErrno,
-- "winTruncate2", pFile->zPath);
-- }
-+static sqlite3_syscall_ptr winGetSystemCall(
-+ sqlite3_vfs *pNotUsed,
-+ const char *zName
-+){
-+ unsigned int i;
-
--#if SQLITE_MAX_MMAP_SIZE>0
-- /* If the file was truncated to a size smaller than the currently
-- ** mapped region, reduce the effective mapping size as well. SQLite will
-- ** use read() and write() to access data beyond this point from now on.
-- */
-- if( pFile->pMapRegion && nByte<pFile->mmapSize ){
-- pFile->mmapSize = nByte;
-+ UNUSED_PARAMETER(pNotUsed);
-+ for(i=0; i<sizeof(aSyscall)/sizeof(aSyscall[0]); i++){
-+ if( strcmp(zName, aSyscall[i].zName)==0 ) return aSyscall[i].pCurrent;
- }
--#endif
--
-- OSTRACE(("TRUNCATE file=%p, rc=%s\n", pFile->h, sqlite3ErrName(rc)));
-- return rc;
-+ return 0;
- }
-
--#ifdef SQLITE_TEST
--/*
--** Count the number of fullsyncs and normal syncs. This is used to test
--** that syncs and fullsyncs are occuring at the right times.
--*/
--SQLITE_API int sqlite3_sync_count = 0;
--SQLITE_API int sqlite3_fullsync_count = 0;
--#endif
--
- /*
--** Make sure all writes to a particular file are committed to disk.
-+** Return the name of the first system call after zName. If zName==NULL
-+** then return the name of the first system call. Return NULL if zName
-+** is the last system call or if zName is not the name of a valid
-+** system call.
- */
--static int winSync(sqlite3_file *id, int flags){
--#ifndef SQLITE_NO_SYNC
-- /*
-- ** Used only when SQLITE_NO_SYNC is not defined.
-- */
-- BOOL rc;
--#endif
--#if !defined(NDEBUG) || !defined(SQLITE_NO_SYNC) || \
-- (defined(SQLITE_TEST) && defined(SQLITE_DEBUG))
-- /*
-- ** Used when SQLITE_NO_SYNC is not defined and by the assert() and/or
-- ** OSTRACE() macros.
-- */
-- winFile *pFile = (winFile*)id;
--#else
-- UNUSED_PARAMETER(id);
--#endif
--
-- assert( pFile );
-- /* Check that one of SQLITE_SYNC_NORMAL or FULL was passed */
-- assert((flags&0x0F)==SQLITE_SYNC_NORMAL
-- || (flags&0x0F)==SQLITE_SYNC_FULL
-- );
-+static const char *winNextSystemCall(sqlite3_vfs *p, const char *zName){
-+ int i = -1;
-
-- /* Unix cannot, but some systems may return SQLITE_FULL from here. This
-- ** line is to test that doing so does not cause any problems.
-- */
-- SimulateDiskfullError( return SQLITE_FULL );
-+ UNUSED_PARAMETER(p);
-+ if( zName ){
-+ for(i=0; i<ArraySize(aSyscall)-1; i++){
-+ if( strcmp(zName, aSyscall[i].zName)==0 ) break;
-+ }
-+ }
-+ for(i++; i<ArraySize(aSyscall); i++){
-+ if( aSyscall[i].pCurrent!=0 ) return aSyscall[i].zName;
-+ }
-+ return 0;
-+}
-
-- OSTRACE(("SYNC file=%p, flags=%x, lock=%d\n",
-- pFile->h, flags, pFile->locktype));
-+/*
-+** This function outputs the specified (ANSI) string to the Win32 debugger
-+** (if available).
-+*/
-
--#ifndef SQLITE_TEST
-- UNUSED_PARAMETER(flags);
--#else
-- if( (flags&0x0F)==SQLITE_SYNC_FULL ){
-- sqlite3_fullsync_count++;
-+SQLITE_API void sqlite3_win32_write_debug(const char *zBuf, int nBuf){
-+ char zDbgBuf[SQLITE_WIN32_DBG_BUF_SIZE];
-+ int nMin = MIN(nBuf, (SQLITE_WIN32_DBG_BUF_SIZE - 1)); /* may be negative. */
-+ if( nMin<-1 ) nMin = -1; /* all negative values become -1. */
-+ assert( nMin==-1 || nMin==0 || nMin<SQLITE_WIN32_DBG_BUF_SIZE );
-+#if defined(SQLITE_WIN32_HAS_ANSI)
-+ if( nMin>0 ){
-+ memset(zDbgBuf, 0, SQLITE_WIN32_DBG_BUF_SIZE);
-+ memcpy(zDbgBuf, zBuf, nMin);
-+ osOutputDebugStringA(zDbgBuf);
-+ }else{
-+ osOutputDebugStringA(zBuf);
- }
-- sqlite3_sync_count++;
--#endif
--
-- /* If we compiled with the SQLITE_NO_SYNC flag, then syncing is a
-- ** no-op
-- */
--#ifdef SQLITE_NO_SYNC
-- return SQLITE_OK;
-+#elif defined(SQLITE_WIN32_HAS_WIDE)
-+ memset(zDbgBuf, 0, SQLITE_WIN32_DBG_BUF_SIZE);
-+ if ( osMultiByteToWideChar(
-+ osAreFileApisANSI() ? CP_ACP : CP_OEMCP, 0, zBuf,
-+ nMin, (LPWSTR)zDbgBuf, SQLITE_WIN32_DBG_BUF_SIZE/sizeof(WCHAR))<=0 ){
-+ return;
-+ }
-+ osOutputDebugStringW((LPCWSTR)zDbgBuf);
- #else
-- rc = osFlushFileBuffers(pFile->h);
-- SimulateIOError( rc=FALSE );
-- if( rc ){
-- OSTRACE(("SYNC file=%p, rc=SQLITE_OK\n", pFile->h));
-- return SQLITE_OK;
-+ if( nMin>0 ){
-+ memset(zDbgBuf, 0, SQLITE_WIN32_DBG_BUF_SIZE);
-+ memcpy(zDbgBuf, zBuf, nMin);
-+ fprintf(stderr, "%s", zDbgBuf);
- }else{
-- pFile->lastErrno = osGetLastError();
-- OSTRACE(("SYNC file=%p, rc=SQLITE_IOERR_FSYNC\n", pFile->h));
-- return winLogError(SQLITE_IOERR_FSYNC, pFile->lastErrno,
-- "winSync", pFile->zPath);
-+ fprintf(stderr, "%s", zBuf);
- }
- #endif
- }
-
- /*
--** Determine the current size of a file in bytes
-+** The following routine suspends the current thread for at least ms
-+** milliseconds. This is equivalent to the Win32 Sleep() interface.
- */
--static int winFileSize(sqlite3_file *id, sqlite3_int64 *pSize){
-- winFile *pFile = (winFile*)id;
-- int rc = SQLITE_OK;
--
-- assert( id!=0 );
-- assert( pSize!=0 );
-- SimulateIOError(return SQLITE_IOERR_FSTAT);
-- OSTRACE(("SIZE file=%p, pSize=%p\n", pFile->h, pSize));
-+#if SQLITE_OS_WINRT
-+static HANDLE sleepObj = NULL;
-+#endif
-
-+SQLITE_API void sqlite3_win32_sleep(DWORD milliseconds){
- #if SQLITE_OS_WINRT
-- {
-- FILE_STANDARD_INFO info;
-- if( osGetFileInformationByHandleEx(pFile->h, FileStandardInfo,
-- &info, sizeof(info)) ){
-- *pSize = info.EndOfFile.QuadPart;
-- }else{
-- pFile->lastErrno = osGetLastError();
-- rc = winLogError(SQLITE_IOERR_FSTAT, pFile->lastErrno,
-- "winFileSize", pFile->zPath);
-- }
-+ if ( sleepObj==NULL ){
-+ sleepObj = osCreateEventExW(NULL, NULL, CREATE_EVENT_MANUAL_RESET,
-+ SYNCHRONIZE);
- }
-+ assert( sleepObj!=NULL );
-+ osWaitForSingleObjectEx(sleepObj, milliseconds, FALSE);
- #else
-- {
-- DWORD upperBits;
-- DWORD lowerBits;
-- DWORD lastErrno;
--
-- lowerBits = osGetFileSize(pFile->h, &upperBits);
-- *pSize = (((sqlite3_int64)upperBits)<<32) + lowerBits;
-- if( (lowerBits == INVALID_FILE_SIZE)
-- && ((lastErrno = osGetLastError())!=NO_ERROR) ){
-- pFile->lastErrno = lastErrno;
-- rc = winLogError(SQLITE_IOERR_FSTAT, pFile->lastErrno,
-- "winFileSize", pFile->zPath);
-- }
-- }
-+ osSleep(milliseconds);
- #endif
-- OSTRACE(("SIZE file=%p, pSize=%p, *pSize=%lld, rc=%s\n",
-- pFile->h, pSize, *pSize, sqlite3ErrName(rc)));
-- return rc;
- }
-
- /*
--** LOCKFILE_FAIL_IMMEDIATELY is undefined on some Windows systems.
-+** Return true (non-zero) if we are running under WinNT, Win2K, WinXP,
-+** or WinCE. Return false (zero) for Win95, Win98, or WinME.
-+**
-+** Here is an interesting observation: Win95, Win98, and WinME lack
-+** the LockFileEx() API. But we can still statically link against that
-+** API as long as we don't call it when running Win95/98/ME. A call to
-+** this routine is used to determine if the host is Win95/98/ME or
-+** WinNT/2K/XP so that we will know whether or not we can safely call
-+** the LockFileEx() API.
- */
--#ifndef LOCKFILE_FAIL_IMMEDIATELY
--# define LOCKFILE_FAIL_IMMEDIATELY 1
--#endif
--
--#ifndef LOCKFILE_EXCLUSIVE_LOCK
--# define LOCKFILE_EXCLUSIVE_LOCK 2
-+#if SQLITE_OS_WINCE || SQLITE_OS_WINRT
-+# define isNT() (1)
-+#elif !defined(SQLITE_WIN32_HAS_WIDE)
-+# define isNT() (0)
-+#else
-+ static int isNT(void){
-+ if( sqlite3_os_type==0 ){
-+ OSVERSIONINFOA sInfo;
-+ sInfo.dwOSVersionInfoSize = sizeof(sInfo);
-+ osGetVersionExA(&sInfo);
-+ sqlite3_os_type = sInfo.dwPlatformId==VER_PLATFORM_WIN32_NT ? 2 : 1;
-+ }
-+ return sqlite3_os_type==2;
-+ }
- #endif
-
-+#ifdef SQLITE_WIN32_MALLOC
- /*
--** Historically, SQLite has used both the LockFile and LockFileEx functions.
--** When the LockFile function was used, it was always expected to fail
--** immediately if the lock could not be obtained. Also, it always expected to
--** obtain an exclusive lock. These flags are used with the LockFileEx function
--** and reflect those expectations; therefore, they should not be changed.
-+** Allocate nBytes of memory.
- */
--#ifndef SQLITE_LOCKFILE_FLAGS
--# define SQLITE_LOCKFILE_FLAGS (LOCKFILE_FAIL_IMMEDIATELY | \
-- LOCKFILE_EXCLUSIVE_LOCK)
-+static void *winMemMalloc(int nBytes){
-+ HANDLE hHeap;
-+ void *p;
-+
-+ winMemAssertMagic();
-+ hHeap = winMemGetHeap();
-+ assert( hHeap!=0 );
-+ assert( hHeap!=INVALID_HANDLE_VALUE );
-+#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE)
-+ assert ( osHeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) );
- #endif
-+ assert( nBytes>=0 );
-+ p = osHeapAlloc(hHeap, SQLITE_WIN32_HEAP_FLAGS, (SIZE_T)nBytes);
-+ if( !p ){
-+ sqlite3_log(SQLITE_NOMEM, "failed to HeapAlloc %u bytes (%d), heap=%p",
-+ nBytes, osGetLastError(), (void*)hHeap);
-+ }
-+ return p;
-+}
-
- /*
--** Currently, SQLite never calls the LockFileEx function without wanting the
--** call to fail immediately if the lock cannot be obtained.
-+** Free memory.
- */
--#ifndef SQLITE_LOCKFILEEX_FLAGS
--# define SQLITE_LOCKFILEEX_FLAGS (LOCKFILE_FAIL_IMMEDIATELY)
-+static void winMemFree(void *pPrior){
-+ HANDLE hHeap;
-+
-+ winMemAssertMagic();
-+ hHeap = winMemGetHeap();
-+ assert( hHeap!=0 );
-+ assert( hHeap!=INVALID_HANDLE_VALUE );
-+#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE)
-+ assert ( osHeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior) );
- #endif
-+ if( !pPrior ) return; /* Passing NULL to HeapFree is undefined. */
-+ if( !osHeapFree(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior) ){
-+ sqlite3_log(SQLITE_NOMEM, "failed to HeapFree block %p (%d), heap=%p",
-+ pPrior, osGetLastError(), (void*)hHeap);
-+ }
-+}
-
- /*
--** Acquire a reader lock.
--** Different API routines are called depending on whether or not this
--** is Win9x or WinNT.
-+** Change the size of an existing memory allocation
- */
--static int getReadLock(winFile *pFile){
-- int res;
-- OSTRACE(("READ-LOCK file=%p, lock=%d\n", pFile->h, pFile->locktype));
-- if( isNT() ){
--#if SQLITE_OS_WINCE
-- /*
-- ** NOTE: Windows CE is handled differently here due its lack of the Win32
-- ** API LockFileEx.
-- */
-- res = winceLockFile(&pFile->h, SHARED_FIRST, 0, 1, 0);
--#else
-- res = winLockFile(&pFile->h, SQLITE_LOCKFILEEX_FLAGS, SHARED_FIRST, 0,
-- SHARED_SIZE, 0);
-+static void *winMemRealloc(void *pPrior, int nBytes){
-+ HANDLE hHeap;
-+ void *p;
-+
-+ winMemAssertMagic();
-+ hHeap = winMemGetHeap();
-+ assert( hHeap!=0 );
-+ assert( hHeap!=INVALID_HANDLE_VALUE );
-+#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE)
-+ assert ( osHeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior) );
- #endif
-+ assert( nBytes>=0 );
-+ if( !pPrior ){
-+ p = osHeapAlloc(hHeap, SQLITE_WIN32_HEAP_FLAGS, (SIZE_T)nBytes);
-+ }else{
-+ p = osHeapReAlloc(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior, (SIZE_T)nBytes);
- }
--#ifdef SQLITE_WIN32_HAS_ANSI
-- else{
-- int lk;
-- sqlite3_randomness(sizeof(lk), &lk);
-- pFile->sharedLockByte = (short)((lk & 0x7fffffff)%(SHARED_SIZE - 1));
-- res = winLockFile(&pFile->h, SQLITE_LOCKFILE_FLAGS,
-- SHARED_FIRST+pFile->sharedLockByte, 0, 1, 0);
-- }
--#endif
-- if( res == 0 ){
-- pFile->lastErrno = osGetLastError();
-- /* No need to log a failure to lock */
-+ if( !p ){
-+ sqlite3_log(SQLITE_NOMEM, "failed to %s %u bytes (%d), heap=%p",
-+ pPrior ? "HeapReAlloc" : "HeapAlloc", nBytes, osGetLastError(),
-+ (void*)hHeap);
- }
-- OSTRACE(("READ-LOCK file=%p, rc=%s\n", pFile->h, sqlite3ErrName(res)));
-- return res;
-+ return p;
- }
-
- /*
--** Undo a readlock
-+** Return the size of an outstanding allocation, in bytes.
- */
--static int unlockReadLock(winFile *pFile){
-- int res;
-- DWORD lastErrno;
-- OSTRACE(("READ-UNLOCK file=%p, lock=%d\n", pFile->h, pFile->locktype));
-- if( isNT() ){
-- res = winUnlockFile(&pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0);
-- }
--#ifdef SQLITE_WIN32_HAS_ANSI
-- else{
-- res = winUnlockFile(&pFile->h, SHARED_FIRST+pFile->sharedLockByte, 0, 1, 0);
-- }
-+static int winMemSize(void *p){
-+ HANDLE hHeap;
-+ SIZE_T n;
-+
-+ winMemAssertMagic();
-+ hHeap = winMemGetHeap();
-+ assert( hHeap!=0 );
-+ assert( hHeap!=INVALID_HANDLE_VALUE );
-+#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE)
-+ assert ( osHeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) );
- #endif
-- if( res==0 && ((lastErrno = osGetLastError())!=ERROR_NOT_LOCKED) ){
-- pFile->lastErrno = lastErrno;
-- winLogError(SQLITE_IOERR_UNLOCK, pFile->lastErrno,
-- "unlockReadLock", pFile->zPath);
-+ if( !p ) return 0;
-+ n = osHeapSize(hHeap, SQLITE_WIN32_HEAP_FLAGS, p);
-+ if( n==(SIZE_T)-1 ){
-+ sqlite3_log(SQLITE_NOMEM, "failed to HeapSize block %p (%d), heap=%p",
-+ p, osGetLastError(), (void*)hHeap);
-+ return 0;
- }
-- OSTRACE(("READ-UNLOCK file=%p, rc=%s\n", pFile->h, sqlite3ErrName(res)));
-- return res;
-+ return (int)n;
- }
-
- /*
--** Lock the file with the lock specified by parameter locktype - one
--** of the following:
--**
--** (1) SHARED_LOCK
--** (2) RESERVED_LOCK
--** (3) PENDING_LOCK
--** (4) EXCLUSIVE_LOCK
--**
--** Sometimes when requesting one lock state, additional lock states
--** are inserted in between. The locking might fail on one of the later
--** transitions leaving the lock state different from what it started but
--** still short of its goal. The following chart shows the allowed
--** transitions and the inserted intermediate states:
--**
--** UNLOCKED -> SHARED
--** SHARED -> RESERVED
--** SHARED -> (PENDING) -> EXCLUSIVE
--** RESERVED -> (PENDING) -> EXCLUSIVE
--** PENDING -> EXCLUSIVE
--**
--** This routine will only increase a lock. The winUnlock() routine
--** erases all locks at once and returns us immediately to locking level 0.
--** It is not possible to lower the locking level one step at a time. You
--** must go straight to locking level 0.
-+** Round up a request size to the next valid allocation size.
- */
--static int winLock(sqlite3_file *id, int locktype){
-- int rc = SQLITE_OK; /* Return code from subroutines */
-- int res = 1; /* Result of a Windows lock call */
-- int newLocktype; /* Set pFile->locktype to this value before exiting */
-- int gotPendingLock = 0;/* True if we acquired a PENDING lock this time */
-- winFile *pFile = (winFile*)id;
-- DWORD lastErrno = NO_ERROR;
--
-- assert( id!=0 );
-- OSTRACE(("LOCK file=%p, oldLock=%d(%d), newLock=%d\n",
-- pFile->h, pFile->locktype, pFile->sharedLockByte, locktype));
-+static int winMemRoundup(int n){
-+ return n;
-+}
-
-- /* If there is already a lock of this type or more restrictive on the
-- ** OsFile, do nothing. Don't use the end_lock: exit path, as
-- ** sqlite3OsEnterMutex() hasn't been called yet.
-- */
-- if( pFile->locktype>=locktype ){
-- OSTRACE(("LOCK-HELD file=%p, rc=SQLITE_OK\n", pFile->h));
-- return SQLITE_OK;
-- }
-+/*
-+** Initialize this module.
-+*/
-+static int winMemInit(void *pAppData){
-+ winMemData *pWinMemData = (winMemData *)pAppData;
-
-- /* Make sure the locking sequence is correct
-- */
-- assert( pFile->locktype!=NO_LOCK || locktype==SHARED_LOCK );
-- assert( locktype!=PENDING_LOCK );
-- assert( locktype!=RESERVED_LOCK || pFile->locktype==SHARED_LOCK );
-+ if( !pWinMemData ) return SQLITE_ERROR;
-+ assert( pWinMemData->magic==WINMEM_MAGIC );
-
-- /* Lock the PENDING_LOCK byte if we need to acquire a PENDING lock or
-- ** a SHARED lock. If we are acquiring a SHARED lock, the acquisition of
-- ** the PENDING_LOCK byte is temporary.
-- */
-- newLocktype = pFile->locktype;
-- if( (pFile->locktype==NO_LOCK)
-- || ( (locktype==EXCLUSIVE_LOCK)
-- && (pFile->locktype==RESERVED_LOCK))
-- ){
-- int cnt = 3;
-- while( cnt-->0 && (res = winLockFile(&pFile->h, SQLITE_LOCKFILE_FLAGS,
-- PENDING_BYTE, 0, 1, 0))==0 ){
-- /* Try 3 times to get the pending lock. This is needed to work
-- ** around problems caused by indexing and/or anti-virus software on
-- ** Windows systems.
-- ** If you are using this code as a model for alternative VFSes, do not
-- ** copy this retry logic. It is a hack intended for Windows only.
-- */
-- OSTRACE(("LOCK-PENDING-FAIL file=%p, count=%d, rc=%s\n",
-- pFile->h, cnt, sqlite3ErrName(res)));
-- if( cnt ) sqlite3_win32_sleep(1);
-- }
-- gotPendingLock = res;
-- if( !res ){
-- lastErrno = osGetLastError();
-+#if !SQLITE_OS_WINRT && SQLITE_WIN32_HEAP_CREATE
-+ if( !pWinMemData->hHeap ){
-+ pWinMemData->hHeap = osHeapCreate(SQLITE_WIN32_HEAP_FLAGS,
-+ SQLITE_WIN32_HEAP_INIT_SIZE,
-+ SQLITE_WIN32_HEAP_MAX_SIZE);
-+ if( !pWinMemData->hHeap ){
-+ sqlite3_log(SQLITE_NOMEM,
-+ "failed to HeapCreate (%d), flags=%u, initSize=%u, maxSize=%u",
-+ osGetLastError(), SQLITE_WIN32_HEAP_FLAGS,
-+ SQLITE_WIN32_HEAP_INIT_SIZE, SQLITE_WIN32_HEAP_MAX_SIZE);
-+ return SQLITE_NOMEM;
- }
-+ pWinMemData->bOwned = TRUE;
-+ assert( pWinMemData->bOwned );
- }
--
-- /* Acquire a shared lock
-- */
-- if( locktype==SHARED_LOCK && res ){
-- assert( pFile->locktype==NO_LOCK );
-- res = getReadLock(pFile);
-- if( res ){
-- newLocktype = SHARED_LOCK;
-- }else{
-- lastErrno = osGetLastError();
-- }
-+#else
-+ pWinMemData->hHeap = osGetProcessHeap();
-+ if( !pWinMemData->hHeap ){
-+ sqlite3_log(SQLITE_NOMEM,
-+ "failed to GetProcessHeap (%d)", osGetLastError());
-+ return SQLITE_NOMEM;
- }
-+ pWinMemData->bOwned = FALSE;
-+ assert( !pWinMemData->bOwned );
-+#endif
-+ assert( pWinMemData->hHeap!=0 );
-+ assert( pWinMemData->hHeap!=INVALID_HANDLE_VALUE );
-+#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE)
-+ assert( osHeapValidate(pWinMemData->hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) );
-+#endif
-+ return SQLITE_OK;
-+}
-
-- /* Acquire a RESERVED lock
-- */
-- if( locktype==RESERVED_LOCK && res ){
-- assert( pFile->locktype==SHARED_LOCK );
-- res = winLockFile(&pFile->h, SQLITE_LOCKFILE_FLAGS, RESERVED_BYTE, 0, 1, 0);
-- if( res ){
-- newLocktype = RESERVED_LOCK;
-- }else{
-- lastErrno = osGetLastError();
-+/*
-+** Deinitialize this module.
-+*/
-+static void winMemShutdown(void *pAppData){
-+ winMemData *pWinMemData = (winMemData *)pAppData;
-+
-+ if( !pWinMemData ) return;
-+ if( pWinMemData->hHeap ){
-+ assert( pWinMemData->hHeap!=INVALID_HANDLE_VALUE );
-+#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE)
-+ assert( osHeapValidate(pWinMemData->hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) );
-+#endif
-+ if( pWinMemData->bOwned ){
-+ if( !osHeapDestroy(pWinMemData->hHeap) ){
-+ sqlite3_log(SQLITE_NOMEM, "failed to HeapDestroy (%d), heap=%p",
-+ osGetLastError(), (void*)pWinMemData->hHeap);
-+ }
-+ pWinMemData->bOwned = FALSE;
- }
-+ pWinMemData->hHeap = NULL;
- }
-+}
-
-- /* Acquire a PENDING lock
-- */
-- if( locktype==EXCLUSIVE_LOCK && res ){
-- newLocktype = PENDING_LOCK;
-- gotPendingLock = 0;
-- }
-+/*
-+** Populate the low-level memory allocation function pointers in
-+** sqlite3GlobalConfig.m with pointers to the routines in this file. The
-+** arguments specify the block of memory to manage.
-+**
-+** This routine is only called by sqlite3_config(), and therefore
-+** is not required to be threadsafe (it is not).
-+*/
-+SQLITE_PRIVATE const sqlite3_mem_methods *sqlite3MemGetWin32(void){
-+ static const sqlite3_mem_methods winMemMethods = {
-+ winMemMalloc,
-+ winMemFree,
-+ winMemRealloc,
-+ winMemSize,
-+ winMemRoundup,
-+ winMemInit,
-+ winMemShutdown,
-+ &win_mem_data
-+ };
-+ return &winMemMethods;
-+}
-
-- /* Acquire an EXCLUSIVE lock
-- */
-- if( locktype==EXCLUSIVE_LOCK && res ){
-- assert( pFile->locktype>=SHARED_LOCK );
-- res = unlockReadLock(pFile);
-- res = winLockFile(&pFile->h, SQLITE_LOCKFILE_FLAGS, SHARED_FIRST, 0,
-- SHARED_SIZE, 0);
-- if( res ){
-- newLocktype = EXCLUSIVE_LOCK;
-- }else{
-- lastErrno = osGetLastError();
-- getReadLock(pFile);
-- }
-- }
-+SQLITE_PRIVATE void sqlite3MemSetDefault(void){
-+ sqlite3_config(SQLITE_CONFIG_MALLOC, sqlite3MemGetWin32());
-+}
-+#endif /* SQLITE_WIN32_MALLOC */
-+
-+/*
-+** Convert a UTF-8 string to Microsoft Unicode (UTF-16?).
-+**
-+** Space to hold the returned string is obtained from malloc.
-+*/
-+static LPWSTR utf8ToUnicode(const char *zFilename){
-+ int nChar;
-+ LPWSTR zWideFilename;
-
-- /* If we are holding a PENDING lock that ought to be released, then
-- ** release it now.
-- */
-- if( gotPendingLock && locktype==SHARED_LOCK ){
-- winUnlockFile(&pFile->h, PENDING_BYTE, 0, 1, 0);
-+ nChar = osMultiByteToWideChar(CP_UTF8, 0, zFilename, -1, NULL, 0);
-+ if( nChar==0 ){
-+ return 0;
- }
--
-- /* Update the state of the lock has held in the file descriptor then
-- ** return the appropriate result code.
-- */
-- if( res ){
-- rc = SQLITE_OK;
-- }else{
-- OSTRACE(("LOCK-FAIL file=%p, wanted=%d, got=%d\n",
-- pFile->h, locktype, newLocktype));
-- pFile->lastErrno = lastErrno;
-- rc = SQLITE_BUSY;
-+ zWideFilename = sqlite3MallocZero( nChar*sizeof(zWideFilename[0]) );
-+ if( zWideFilename==0 ){
-+ return 0;
- }
-- pFile->locktype = (u8)newLocktype;
-- OSTRACE(("LOCK file=%p, lock=%d, rc=%s\n",
-- pFile->h, pFile->locktype, sqlite3ErrName(rc)));
-- return rc;
-+ nChar = osMultiByteToWideChar(CP_UTF8, 0, zFilename, -1, zWideFilename,
-+ nChar);
-+ if( nChar==0 ){
-+ sqlite3_free(zWideFilename);
-+ zWideFilename = 0;
-+ }
-+ return zWideFilename;
- }
-
- /*
--** This routine checks if there is a RESERVED lock held on the specified
--** file by this or any other process. If such a lock is held, return
--** non-zero, otherwise zero.
-+** Convert Microsoft Unicode to UTF-8. Space to hold the returned string is
-+** obtained from sqlite3_malloc().
- */
--static int winCheckReservedLock(sqlite3_file *id, int *pResOut){
-- int rc;
-- winFile *pFile = (winFile*)id;
--
-- SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
-- OSTRACE(("TEST-WR-LOCK file=%p, pResOut=%p\n", pFile->h, pResOut));
-+static char *unicodeToUtf8(LPCWSTR zWideFilename){
-+ int nByte;
-+ char *zFilename;
-
-- assert( id!=0 );
-- if( pFile->locktype>=RESERVED_LOCK ){
-- rc = 1;
-- OSTRACE(("TEST-WR-LOCK file=%p, rc=%d (local)\n", pFile->h, rc));
-- }else{
-- rc = winLockFile(&pFile->h, SQLITE_LOCKFILEEX_FLAGS,RESERVED_BYTE, 0, 1, 0);
-- if( rc ){
-- winUnlockFile(&pFile->h, RESERVED_BYTE, 0, 1, 0);
-- }
-- rc = !rc;
-- OSTRACE(("TEST-WR-LOCK file=%p, rc=%d (remote)\n", pFile->h, rc));
-+ nByte = osWideCharToMultiByte(CP_UTF8, 0, zWideFilename, -1, 0, 0, 0, 0);
-+ if( nByte == 0 ){
-+ return 0;
- }
-- *pResOut = rc;
-- OSTRACE(("TEST-WR-LOCK file=%p, pResOut=%p, *pResOut=%d, rc=SQLITE_OK\n",
-- pFile->h, pResOut, *pResOut));
-- return SQLITE_OK;
-+ zFilename = sqlite3MallocZero( nByte );
-+ if( zFilename==0 ){
-+ return 0;
-+ }
-+ nByte = osWideCharToMultiByte(CP_UTF8, 0, zWideFilename, -1, zFilename, nByte,
-+ 0, 0);
-+ if( nByte == 0 ){
-+ sqlite3_free(zFilename);
-+ zFilename = 0;
-+ }
-+ return zFilename;
- }
-
- /*
--** Lower the locking level on file descriptor id to locktype. locktype
--** must be either NO_LOCK or SHARED_LOCK.
--**
--** If the locking level of the file descriptor is already at or below
--** the requested locking level, this routine is a no-op.
--**
--** It is not possible for this routine to fail if the second argument
--** is NO_LOCK. If the second argument is SHARED_LOCK then this routine
--** might return SQLITE_IOERR;
-+** Convert an ANSI string to Microsoft Unicode, based on the
-+** current codepage settings for file apis.
-+**
-+** Space to hold the returned string is obtained
-+** from sqlite3_malloc.
- */
--static int winUnlock(sqlite3_file *id, int locktype){
-- int type;
-- winFile *pFile = (winFile*)id;
-- int rc = SQLITE_OK;
-- assert( pFile!=0 );
-- assert( locktype<=SHARED_LOCK );
-- OSTRACE(("UNLOCK file=%p, oldLock=%d(%d), newLock=%d\n",
-- pFile->h, pFile->locktype, pFile->sharedLockByte, locktype));
-- type = pFile->locktype;
-- if( type>=EXCLUSIVE_LOCK ){
-- winUnlockFile(&pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0);
-- if( locktype==SHARED_LOCK && !getReadLock(pFile) ){
-- /* This should never happen. We should always be able to
-- ** reacquire the read lock */
-- rc = winLogError(SQLITE_IOERR_UNLOCK, osGetLastError(),
-- "winUnlock", pFile->zPath);
-- }
-- }
-- if( type>=RESERVED_LOCK ){
-- winUnlockFile(&pFile->h, RESERVED_BYTE, 0, 1, 0);
-+static LPWSTR mbcsToUnicode(const char *zFilename){
-+ int nByte;
-+ LPWSTR zMbcsFilename;
-+ int codepage = osAreFileApisANSI() ? CP_ACP : CP_OEMCP;
-+
-+ nByte = osMultiByteToWideChar(codepage, 0, zFilename, -1, NULL,
-+ 0)*sizeof(WCHAR);
-+ if( nByte==0 ){
-+ return 0;
- }
-- if( locktype==NO_LOCK && type>=SHARED_LOCK ){
-- unlockReadLock(pFile);
-+ zMbcsFilename = sqlite3MallocZero( nByte*sizeof(zMbcsFilename[0]) );
-+ if( zMbcsFilename==0 ){
-+ return 0;
- }
-- if( type>=PENDING_LOCK ){
-- winUnlockFile(&pFile->h, PENDING_BYTE, 0, 1, 0);
-+ nByte = osMultiByteToWideChar(codepage, 0, zFilename, -1, zMbcsFilename,
-+ nByte);
-+ if( nByte==0 ){
-+ sqlite3_free(zMbcsFilename);
-+ zMbcsFilename = 0;
- }
-- pFile->locktype = (u8)locktype;
-- OSTRACE(("UNLOCK file=%p, lock=%d, rc=%s\n",
-- pFile->h, pFile->locktype, sqlite3ErrName(rc)));
-- return rc;
-+ return zMbcsFilename;
- }
-
- /*
--** If *pArg is inititially negative then this is a query. Set *pArg to
--** 1 or 0 depending on whether or not bit mask of pFile->ctrlFlags is set.
-+** Convert Microsoft Unicode to multi-byte character string, based on the
-+** user's ANSI codepage.
- **
--** If *pArg is 0 or 1, then clear or set the mask bit of pFile->ctrlFlags.
-+** Space to hold the returned string is obtained from
-+** sqlite3_malloc().
- */
--static void winModeBit(winFile *pFile, unsigned char mask, int *pArg){
-- if( *pArg<0 ){
-- *pArg = (pFile->ctrlFlags & mask)!=0;
-- }else if( (*pArg)==0 ){
-- pFile->ctrlFlags &= ~mask;
-- }else{
-- pFile->ctrlFlags |= mask;
-+static char *unicodeToMbcs(LPCWSTR zWideFilename){
-+ int nByte;
-+ char *zFilename;
-+ int codepage = osAreFileApisANSI() ? CP_ACP : CP_OEMCP;
-+
-+ nByte = osWideCharToMultiByte(codepage, 0, zWideFilename, -1, 0, 0, 0, 0);
-+ if( nByte == 0 ){
-+ return 0;
-+ }
-+ zFilename = sqlite3MallocZero( nByte );
-+ if( zFilename==0 ){
-+ return 0;
- }
-+ nByte = osWideCharToMultiByte(codepage, 0, zWideFilename, -1, zFilename,
-+ nByte, 0, 0);
-+ if( nByte == 0 ){
-+ sqlite3_free(zFilename);
-+ zFilename = 0;
-+ }
-+ return zFilename;
- }
-
--/* Forward declaration */
--static int getTempname(int nBuf, char *zBuf);
--
- /*
--** Control and query of the open file handle.
-+** Convert multibyte character string to UTF-8. Space to hold the
-+** returned string is obtained from sqlite3_malloc().
- */
--static int winFileControl(sqlite3_file *id, int op, void *pArg){
-- winFile *pFile = (winFile*)id;
-- OSTRACE(("FCNTL file=%p, op=%d, pArg=%p\n", pFile->h, op, pArg));
-- switch( op ){
-- case SQLITE_FCNTL_LOCKSTATE: {
-- *(int*)pArg = pFile->locktype;
-- OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
-- return SQLITE_OK;
-- }
-- case SQLITE_LAST_ERRNO: {
-- *(int*)pArg = (int)pFile->lastErrno;
-- OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
-- return SQLITE_OK;
-- }
-- case SQLITE_FCNTL_CHUNK_SIZE: {
-- pFile->szChunk = *(int *)pArg;
-- OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
-- return SQLITE_OK;
-- }
-- case SQLITE_FCNTL_SIZE_HINT: {
-- if( pFile->szChunk>0 ){
-- sqlite3_int64 oldSz;
-- int rc = winFileSize(id, &oldSz);
-- if( rc==SQLITE_OK ){
-- sqlite3_int64 newSz = *(sqlite3_int64*)pArg;
-- if( newSz>oldSz ){
-- SimulateIOErrorBenign(1);
-- rc = winTruncate(id, newSz);
-- SimulateIOErrorBenign(0);
-- }
-- }
-- OSTRACE(("FCNTL file=%p, rc=%s\n", pFile->h, sqlite3ErrName(rc)));
-- return rc;
-- }
-- OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
-- return SQLITE_OK;
-- }
-- case SQLITE_FCNTL_PERSIST_WAL: {
-- winModeBit(pFile, WINFILE_PERSIST_WAL, (int*)pArg);
-- OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
-- return SQLITE_OK;
-- }
-- case SQLITE_FCNTL_POWERSAFE_OVERWRITE: {
-- winModeBit(pFile, WINFILE_PSOW, (int*)pArg);
-- OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
-- return SQLITE_OK;
-- }
-- case SQLITE_FCNTL_VFSNAME: {
-- *(char**)pArg = sqlite3_mprintf("win32");
-- OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
-- return SQLITE_OK;
-- }
-- case SQLITE_FCNTL_WIN32_AV_RETRY: {
-- int *a = (int*)pArg;
-- if( a[0]>0 ){
-- win32IoerrRetry = a[0];
-- }else{
-- a[0] = win32IoerrRetry;
-- }
-- if( a[1]>0 ){
-- win32IoerrRetryDelay = a[1];
-- }else{
-- a[1] = win32IoerrRetryDelay;
-- }
-- OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
-- return SQLITE_OK;
-- }
-- case SQLITE_FCNTL_TEMPFILENAME: {
-- char *zTFile = sqlite3MallocZero( pFile->pVfs->mxPathname );
-- if( zTFile ){
-- getTempname(pFile->pVfs->mxPathname, zTFile);
-- *(char**)pArg = zTFile;
-- }
-- OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
-- return SQLITE_OK;
-- }
--#if SQLITE_MAX_MMAP_SIZE>0
-- case SQLITE_FCNTL_MMAP_SIZE: {
-- i64 newLimit = *(i64*)pArg;
-- if( newLimit>sqlite3GlobalConfig.mxMmap ){
-- newLimit = sqlite3GlobalConfig.mxMmap;
-- }
-- *(i64*)pArg = pFile->mmapSizeMax;
-- if( newLimit>=0 ) pFile->mmapSizeMax = newLimit;
-- OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
-- return SQLITE_OK;
-- }
--#endif
-+SQLITE_API char *sqlite3_win32_mbcs_to_utf8(const char *zFilename){
-+ char *zFilenameUtf8;
-+ LPWSTR zTmpWide;
-+
-+ zTmpWide = mbcsToUnicode(zFilename);
-+ if( zTmpWide==0 ){
-+ return 0;
- }
-- OSTRACE(("FCNTL file=%p, rc=SQLITE_NOTFOUND\n", pFile->h));
-- return SQLITE_NOTFOUND;
-+ zFilenameUtf8 = unicodeToUtf8(zTmpWide);
-+ sqlite3_free(zTmpWide);
-+ return zFilenameUtf8;
- }
-
- /*
--** Return the sector size in bytes of the underlying block device for
--** the specified file. This is almost always 512 bytes, but may be
--** larger for some devices.
--**
--** SQLite code assumes this function cannot fail. It also assumes that
--** if two files are created in the same file-system directory (i.e.
--** a database and its journal file) that the sector size will be the
--** same for both.
-+** Convert UTF-8 to multibyte character string. Space to hold the
-+** returned string is obtained from sqlite3_malloc().
- */
--static int winSectorSize(sqlite3_file *id){
-- (void)id;
-- return SQLITE_DEFAULT_SECTOR_SIZE;
-+SQLITE_API char *sqlite3_win32_utf8_to_mbcs(const char *zFilename){
-+ char *zFilenameMbcs;
-+ LPWSTR zTmpWide;
-+
-+ zTmpWide = utf8ToUnicode(zFilename);
-+ if( zTmpWide==0 ){
-+ return 0;
-+ }
-+ zFilenameMbcs = unicodeToMbcs(zTmpWide);
-+ sqlite3_free(zTmpWide);
-+ return zFilenameMbcs;
- }
-
- /*
--** Return a vector of device characteristics.
-+** This function sets the data directory or the temporary directory based on
-+** the provided arguments. The type argument must be 1 in order to set the
-+** data directory or 2 in order to set the temporary directory. The zValue
-+** argument is the name of the directory to use. The return value will be
-+** SQLITE_OK if successful.
- */
--static int winDeviceCharacteristics(sqlite3_file *id){
-- winFile *p = (winFile*)id;
-- return SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN |
-- ((p->ctrlFlags & WINFILE_PSOW)?SQLITE_IOCAP_POWERSAFE_OVERWRITE:0);
-+SQLITE_API int sqlite3_win32_set_directory(DWORD type, LPCWSTR zValue){
-+ char **ppDirectory = 0;
-+#ifndef SQLITE_OMIT_AUTOINIT
-+ int rc = sqlite3_initialize();
-+ if( rc ) return rc;
-+#endif
-+ if( type==SQLITE_WIN32_DATA_DIRECTORY_TYPE ){
-+ ppDirectory = &sqlite3_data_directory;
-+ }else if( type==SQLITE_WIN32_TEMP_DIRECTORY_TYPE ){
-+ ppDirectory = &sqlite3_temp_directory;
-+ }
-+ assert( !ppDirectory || type==SQLITE_WIN32_DATA_DIRECTORY_TYPE
-+ || type==SQLITE_WIN32_TEMP_DIRECTORY_TYPE
-+ );
-+ assert( !ppDirectory || sqlite3MemdebugHasType(*ppDirectory, MEMTYPE_HEAP) );
-+ if( ppDirectory ){
-+ char *zValueUtf8 = 0;
-+ if( zValue && zValue[0] ){
-+ zValueUtf8 = unicodeToUtf8(zValue);
-+ if ( zValueUtf8==0 ){
-+ return SQLITE_NOMEM;
-+ }
-+ }
-+ sqlite3_free(*ppDirectory);
-+ *ppDirectory = zValueUtf8;
-+ return SQLITE_OK;
-+ }
-+ return SQLITE_ERROR;
- }
-
--/*
--** Windows will only let you create file view mappings
--** on allocation size granularity boundaries.
--** During sqlite3_os_init() we do a GetSystemInfo()
--** to get the granularity size.
--*/
--SYSTEM_INFO winSysInfo;
--
--#ifndef SQLITE_OMIT_WAL
--
- /*
--** Helper functions to obtain and relinquish the global mutex. The
--** global mutex is used to protect the winLockInfo objects used by
--** this file, all of which may be shared by multiple threads.
--**
--** Function winShmMutexHeld() is used to assert() that the global mutex
--** is held when required. This function is only used as part of assert()
--** statements. e.g.
--**
--** winShmEnterMutex()
--** assert( winShmMutexHeld() );
--** winShmLeaveMutex()
-+** The return value of getLastErrorMsg
-+** is zero if the error message fits in the buffer, or non-zero
-+** otherwise (if the message was truncated).
- */
--static void winShmEnterMutex(void){
-- sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
--}
--static void winShmLeaveMutex(void){
-- sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
--}
--#ifdef SQLITE_DEBUG
--static int winShmMutexHeld(void) {
-- return sqlite3_mutex_held(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
--}
-+static int getLastErrorMsg(DWORD lastErrno, int nBuf, char *zBuf){
-+ /* FormatMessage returns 0 on failure. Otherwise it
-+ ** returns the number of TCHARs written to the output
-+ ** buffer, excluding the terminating null char.
-+ */
-+ DWORD dwLen = 0;
-+ char *zOut = 0;
-+
-+ if( isNT() ){
-+#if SQLITE_OS_WINRT
-+ WCHAR zTempWide[MAX_PATH+1]; /* NOTE: Somewhat arbitrary. */
-+ dwLen = osFormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM |
-+ FORMAT_MESSAGE_IGNORE_INSERTS,
-+ NULL,
-+ lastErrno,
-+ 0,
-+ zTempWide,
-+ MAX_PATH,
-+ 0);
-+#else
-+ LPWSTR zTempWide = NULL;
-+ dwLen = osFormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |
-+ FORMAT_MESSAGE_FROM_SYSTEM |
-+ FORMAT_MESSAGE_IGNORE_INSERTS,
-+ NULL,
-+ lastErrno,
-+ 0,
-+ (LPWSTR) &zTempWide,
-+ 0,
-+ 0);
-+#endif
-+ if( dwLen > 0 ){
-+ /* allocate a buffer and convert to UTF8 */
-+ sqlite3BeginBenignMalloc();
-+ zOut = unicodeToUtf8(zTempWide);
-+ sqlite3EndBenignMalloc();
-+#if !SQLITE_OS_WINRT
-+ /* free the system buffer allocated by FormatMessage */
-+ osLocalFree(zTempWide);
- #endif
-+ }
-+ }
-+#ifdef SQLITE_WIN32_HAS_ANSI
-+ else{
-+ char *zTemp = NULL;
-+ dwLen = osFormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER |
-+ FORMAT_MESSAGE_FROM_SYSTEM |
-+ FORMAT_MESSAGE_IGNORE_INSERTS,
-+ NULL,
-+ lastErrno,
-+ 0,
-+ (LPSTR) &zTemp,
-+ 0,
-+ 0);
-+ if( dwLen > 0 ){
-+ /* allocate a buffer and convert to UTF8 */
-+ sqlite3BeginBenignMalloc();
-+ zOut = sqlite3_win32_mbcs_to_utf8(zTemp);
-+ sqlite3EndBenignMalloc();
-+ /* free the system buffer allocated by FormatMessage */
-+ osLocalFree(zTemp);
-+ }
-+ }
-+#endif
-+ if( 0 == dwLen ){
-+ sqlite3_snprintf(nBuf, zBuf, "OsError 0x%lx (%lu)", lastErrno, lastErrno);
-+ }else{
-+ /* copy a maximum of nBuf chars to output buffer */
-+ sqlite3_snprintf(nBuf, zBuf, "%s", zOut);
-+ /* free the UTF8 buffer */
-+ sqlite3_free(zOut);
-+ }
-+ return 0;
-+}
-
- /*
--** Object used to represent a single file opened and mmapped to provide
--** shared memory. When multiple threads all reference the same
--** log-summary, each thread has its own winFile object, but they all
--** point to a single instance of this object. In other words, each
--** log-summary is opened only once per process.
--**
--** winShmMutexHeld() must be true when creating or destroying
--** this object or while reading or writing the following fields:
--**
--** nRef
--** pNext
- **
--** The following fields are read-only after the object is created:
--**
--** fid
--** zFilename
-+** This function - winLogErrorAtLine() - is only ever called via the macro
-+** winLogError().
- **
--** Either winShmNode.mutex must be held or winShmNode.nRef==0 and
--** winShmMutexHeld() is true when reading or writing any other field
--** in this structure.
-+** This routine is invoked after an error occurs in an OS function.
-+** It logs a message using sqlite3_log() containing the current value of
-+** error code and, if possible, the human-readable equivalent from
-+** FormatMessage.
- **
-+** The first argument passed to the macro should be the error code that
-+** will be returned to SQLite (e.g. SQLITE_IOERR_DELETE, SQLITE_CANTOPEN).
-+** The two subsequent arguments should be the name of the OS function that
-+** failed and the associated file-system path, if any.
- */
--struct winShmNode {
-- sqlite3_mutex *mutex; /* Mutex to access this object */
-- char *zFilename; /* Name of the file */
-- winFile hFile; /* File handle from winOpen */
--
-- int szRegion; /* Size of shared-memory regions */
-- int nRegion; /* Size of array apRegion */
-- struct ShmRegion {
-- HANDLE hMap; /* File handle from CreateFileMapping */
-- void *pMap;
-- } *aRegion;
-- DWORD lastErrno; /* The Windows errno from the last I/O error */
-+#define winLogError(a,b,c,d) winLogErrorAtLine(a,b,c,d,__LINE__)
-+static int winLogErrorAtLine(
-+ int errcode, /* SQLite error code */
-+ DWORD lastErrno, /* Win32 last error */
-+ const char *zFunc, /* Name of OS function that failed */
-+ const char *zPath, /* File path associated with error */
-+ int iLine /* Source line number where error occurred */
-+){
-+ char zMsg[500]; /* Human readable error text */
-+ int i; /* Loop counter */
-
-- int nRef; /* Number of winShm objects pointing to this */
-- winShm *pFirst; /* All winShm objects pointing to this */
-- winShmNode *pNext; /* Next in list of all winShmNode objects */
--#ifdef SQLITE_DEBUG
-- u8 nextShmId; /* Next available winShm.id value */
--#endif
--};
-+ zMsg[0] = 0;
-+ getLastErrorMsg(lastErrno, sizeof(zMsg), zMsg);
-+ assert( errcode!=SQLITE_OK );
-+ if( zPath==0 ) zPath = "";
-+ for(i=0; zMsg[i] && zMsg[i]!='\r' && zMsg[i]!='\n'; i++){}
-+ zMsg[i] = 0;
-+ sqlite3_log(errcode,
-+ "os_win.c:%d: (%lu) %s(%s) - %s",
-+ iLine, lastErrno, zFunc, zPath, zMsg
-+ );
-
--/*
--** A global array of all winShmNode objects.
--**
--** The winShmMutexHeld() must be true while reading or writing this list.
--*/
--static winShmNode *winShmNodeList = 0;
-+ return errcode;
-+}
-
- /*
--** Structure used internally by this VFS to record the state of an
--** open shared memory connection.
--**
--** The following fields are initialized when this object is created and
--** are read-only thereafter:
--**
--** winShm.pShmNode
--** winShm.id
--**
--** All other fields are read/write. The winShm.pShmNode->mutex must be held
--** while accessing any read/write fields.
-+** The number of times that a ReadFile(), WriteFile(), and DeleteFile()
-+** will be retried following a locking error - probably caused by
-+** antivirus software. Also the initial delay before the first retry.
-+** The delay increases linearly with each retry.
- */
--struct winShm {
-- winShmNode *pShmNode; /* The underlying winShmNode object */
-- winShm *pNext; /* Next winShm with the same winShmNode */
-- u8 hasMutex; /* True if holding the winShmNode mutex */
-- u16 sharedMask; /* Mask of shared locks held */
-- u16 exclMask; /* Mask of exclusive locks held */
--#ifdef SQLITE_DEBUG
-- u8 id; /* Id of this connection with its winShmNode */
-+#ifndef SQLITE_WIN32_IOERR_RETRY
-+# define SQLITE_WIN32_IOERR_RETRY 10
- #endif
--};
-+#ifndef SQLITE_WIN32_IOERR_RETRY_DELAY
-+# define SQLITE_WIN32_IOERR_RETRY_DELAY 25
-+#endif
-+static int win32IoerrRetry = SQLITE_WIN32_IOERR_RETRY;
-+static int win32IoerrRetryDelay = SQLITE_WIN32_IOERR_RETRY_DELAY;
-
- /*
--** Constants used for locking
-+** If a ReadFile() or WriteFile() error occurs, invoke this routine
-+** to see if it should be retried. Return TRUE to retry. Return FALSE
-+** to give up with an error.
- */
--#define WIN_SHM_BASE ((22+SQLITE_SHM_NLOCK)*4) /* first lock byte */
--#define WIN_SHM_DMS (WIN_SHM_BASE+SQLITE_SHM_NLOCK) /* deadman switch */
-+static int retryIoerr(int *pnRetry, DWORD *pError){
-+ DWORD e = osGetLastError();
-+ if( *pnRetry>=win32IoerrRetry ){
-+ if( pError ){
-+ *pError = e;
-+ }
-+ return 0;
-+ }
-+ if( e==ERROR_ACCESS_DENIED ||
-+ e==ERROR_LOCK_VIOLATION ||
-+ e==ERROR_SHARING_VIOLATION ){
-+ sqlite3_win32_sleep(win32IoerrRetryDelay*(1+*pnRetry));
-+ ++*pnRetry;
-+ return 1;
-+ }
-+ if( pError ){
-+ *pError = e;
-+ }
-+ return 0;
-+}
-
- /*
--** Apply advisory locks for all n bytes beginning at ofst.
-+** Log a I/O error retry episode.
- */
--#define _SHM_UNLCK 1
--#define _SHM_RDLCK 2
--#define _SHM_WRLCK 3
--static int winShmSystemLock(
-- winShmNode *pFile, /* Apply locks to this open shared-memory segment */
-- int lockType, /* _SHM_UNLCK, _SHM_RDLCK, or _SHM_WRLCK */
-- int ofst, /* Offset to first byte to be locked/unlocked */
-- int nByte /* Number of bytes to lock or unlock */
--){
-- int rc = 0; /* Result code form Lock/UnlockFileEx() */
--
-- /* Access to the winShmNode object is serialized by the caller */
-- assert( sqlite3_mutex_held(pFile->mutex) || pFile->nRef==0 );
--
-- OSTRACE(("SHM-LOCK file=%p, lock=%d, offset=%d, size=%d\n",
-- pFile->hFile.h, lockType, ofst, nByte));
--
-- /* Release/Acquire the system-level lock */
-- if( lockType==_SHM_UNLCK ){
-- rc = winUnlockFile(&pFile->hFile.h, ofst, 0, nByte, 0);
-- }else{
-- /* Initialize the locking parameters */
-- DWORD dwFlags = LOCKFILE_FAIL_IMMEDIATELY;
-- if( lockType == _SHM_WRLCK ) dwFlags |= LOCKFILE_EXCLUSIVE_LOCK;
-- rc = winLockFile(&pFile->hFile.h, dwFlags, ofst, 0, nByte, 0);
-- }
--
-- if( rc!= 0 ){
-- rc = SQLITE_OK;
-- }else{
-- pFile->lastErrno = osGetLastError();
-- rc = SQLITE_BUSY;
-+static void logIoerr(int nRetry){
-+ if( nRetry ){
-+ sqlite3_log(SQLITE_IOERR,
-+ "delayed %dms for lock/sharing conflict",
-+ win32IoerrRetryDelay*nRetry*(nRetry+1)/2
-+ );
- }
-+}
-
-- OSTRACE(("SHM-LOCK file=%p, func=%s, errno=%lu, rc=%s\n",
-- pFile->hFile.h, (lockType == _SHM_UNLCK) ? "winUnlockFile" :
-- "winLockFile", pFile->lastErrno, sqlite3ErrName(rc)));
--
-- return rc;
-+#if SQLITE_OS_WINCE
-+/*************************************************************************
-+** This section contains code for WinCE only.
-+*/
-+#if !defined(SQLITE_MSVC_LOCALTIME_API) || !SQLITE_MSVC_LOCALTIME_API
-+/*
-+** The MSVC CRT on Windows CE may not have a localtime() function. So
-+** create a substitute.
-+*/
-+/* #include <time.h> */
-+struct tm *__cdecl localtime(const time_t *t)
-+{
-+ static struct tm y;
-+ FILETIME uTm, lTm;
-+ SYSTEMTIME pTm;
-+ sqlite3_int64 t64;
-+ t64 = *t;
-+ t64 = (t64 + 11644473600)*10000000;
-+ uTm.dwLowDateTime = (DWORD)(t64 & 0xFFFFFFFF);
-+ uTm.dwHighDateTime= (DWORD)(t64 >> 32);
-+ osFileTimeToLocalFileTime(&uTm,&lTm);
-+ osFileTimeToSystemTime(&lTm,&pTm);
-+ y.tm_year = pTm.wYear - 1900;
-+ y.tm_mon = pTm.wMonth - 1;
-+ y.tm_wday = pTm.wDayOfWeek;
-+ y.tm_mday = pTm.wDay;
-+ y.tm_hour = pTm.wHour;
-+ y.tm_min = pTm.wMinute;
-+ y.tm_sec = pTm.wSecond;
-+ return &y;
- }
-+#endif
-
--/* Forward references to VFS methods */
--static int winOpen(sqlite3_vfs*,const char*,sqlite3_file*,int,int*);
--static int winDelete(sqlite3_vfs *,const char*,int);
-+#define HANDLE_TO_WINFILE(a) (winFile*)&((char*)a)[-(int)offsetof(winFile,h)]
-
- /*
--** Purge the winShmNodeList list of all entries with winShmNode.nRef==0.
--**
--** This is not a VFS shared-memory method; it is a utility function called
--** by VFS shared-memory methods.
-+** Acquire a lock on the handle h
- */
--static void winShmPurge(sqlite3_vfs *pVfs, int deleteFlag){
-- winShmNode **pp;
-- winShmNode *p;
-- BOOL bRc;
-- assert( winShmMutexHeld() );
-- OSTRACE(("SHM-PURGE pid=%lu, deleteFlag=%d\n",
-- osGetCurrentProcessId(), deleteFlag));
-- pp = &winShmNodeList;
-- while( (p = *pp)!=0 ){
-- if( p->nRef==0 ){
-- int i;
-- if( p->mutex ) sqlite3_mutex_free(p->mutex);
-- for(i=0; i<p->nRegion; i++){
-- bRc = osUnmapViewOfFile(p->aRegion[i].pMap);
-- OSTRACE(("SHM-PURGE-UNMAP pid=%lu, region=%d, rc=%s\n",
-- osGetCurrentProcessId(), i, bRc ? "ok" : "failed"));
-- bRc = osCloseHandle(p->aRegion[i].hMap);
-- OSTRACE(("SHM-PURGE-CLOSE pid=%lu, region=%d, rc=%s\n",
-- osGetCurrentProcessId(), i, bRc ? "ok" : "failed"));
-- }
-- if( p->hFile.h!=NULL && p->hFile.h!=INVALID_HANDLE_VALUE ){
-- SimulateIOErrorBenign(1);
-- winClose((sqlite3_file *)&p->hFile);
-- SimulateIOErrorBenign(0);
-- }
-- if( deleteFlag ){
-- SimulateIOErrorBenign(1);
-- sqlite3BeginBenignMalloc();
-- winDelete(pVfs, p->zFilename, 0);
-- sqlite3EndBenignMalloc();
-- SimulateIOErrorBenign(0);
-- }
-- *pp = p->pNext;
-- sqlite3_free(p->aRegion);
-- sqlite3_free(p);
-- }else{
-- pp = &p->pNext;
-- }
-- }
-+static void winceMutexAcquire(HANDLE h){
-+ DWORD dwErr;
-+ do {
-+ dwErr = osWaitForSingleObject(h, INFINITE);
-+ } while (dwErr != WAIT_OBJECT_0 && dwErr != WAIT_ABANDONED);
- }
--
- /*
--** Open the shared-memory area associated with database file pDbFd.
--**
--** When opening a new shared-memory file, if no other instances of that
--** file are currently open, in this process or in other processes, then
--** the file must be truncated to zero length or have its header cleared.
-+** Release a lock acquired by winceMutexAcquire()
- */
--static int winOpenSharedMemory(winFile *pDbFd){
-- struct winShm *p; /* The connection to be opened */
-- struct winShmNode *pShmNode = 0; /* The underlying mmapped file */
-- int rc; /* Result code */
-- struct winShmNode *pNew; /* Newly allocated winShmNode */
-- int nName; /* Size of zName in bytes */
-+#define winceMutexRelease(h) ReleaseMutex(h)
-
-- assert( pDbFd->pShm==0 ); /* Not previously opened */
-+/*
-+** Create the mutex and shared memory used for locking in the file
-+** descriptor pFile
-+*/
-+static int winceCreateLock(const char *zFilename, winFile *pFile){
-+ LPWSTR zTok;
-+ LPWSTR zName;
-+ DWORD lastErrno;
-+ BOOL bLogged = FALSE;
-+ BOOL bInit = TRUE;
-
-- /* Allocate space for the new sqlite3_shm object. Also speculatively
-- ** allocate space for a new winShmNode and filename.
-- */
-- p = sqlite3MallocZero( sizeof(*p) );
-- if( p==0 ) return SQLITE_IOERR_NOMEM;
-- nName = sqlite3Strlen30(pDbFd->zPath);
-- pNew = sqlite3MallocZero( sizeof(*pShmNode) + nName + 17 );
-- if( pNew==0 ){
-- sqlite3_free(p);
-+ zName = utf8ToUnicode(zFilename);
-+ if( zName==0 ){
-+ /* out of memory */
- return SQLITE_IOERR_NOMEM;
- }
-- pNew->zFilename = (char*)&pNew[1];
-- sqlite3_snprintf(nName+15, pNew->zFilename, "%s-shm", pDbFd->zPath);
-- sqlite3FileSuffix3(pDbFd->zPath, pNew->zFilename);
-
-- /* Look to see if there is an existing winShmNode that can be used.
-- ** If no matching winShmNode currently exists, create a new one.
-+ /* Initialize the local lockdata */
-+ memset(&pFile->local, 0, sizeof(pFile->local));
-+
-+ /* Replace the backslashes from the filename and lowercase it
-+ ** to derive a mutex name. */
-+ zTok = osCharLowerW(zName);
-+ for (;*zTok;zTok++){
-+ if (*zTok == '\\') *zTok = '_';
-+ }
-+
-+ /* Create/open the named mutex */
-+ pFile->hMutex = osCreateMutexW(NULL, FALSE, zName);
-+ if (!pFile->hMutex){
-+ pFile->lastErrno = osGetLastError();
-+ winLogError(SQLITE_IOERR, pFile->lastErrno,
-+ "winceCreateLock1", zFilename);
-+ sqlite3_free(zName);
-+ return SQLITE_IOERR;
-+ }
-+
-+ /* Acquire the mutex before continuing */
-+ winceMutexAcquire(pFile->hMutex);
-+
-+ /* Since the names of named mutexes, semaphores, file mappings etc are
-+ ** case-sensitive, take advantage of that by uppercasing the mutex name
-+ ** and using that as the shared filemapping name.
- */
-- winShmEnterMutex();
-- for(pShmNode = winShmNodeList; pShmNode; pShmNode=pShmNode->pNext){
-- /* TBD need to come up with better match here. Perhaps
-- ** use FILE_ID_BOTH_DIR_INFO Structure.
-- */
-- if( sqlite3StrICmp(pShmNode->zFilename, pNew->zFilename)==0 ) break;
-+ osCharUpperW(zName);
-+ pFile->hShared = osCreateFileMappingW(INVALID_HANDLE_VALUE, NULL,
-+ PAGE_READWRITE, 0, sizeof(winceLock),
-+ zName);
-+
-+ /* Set a flag that indicates we're the first to create the memory so it
-+ ** must be zero-initialized */
-+ lastErrno = osGetLastError();
-+ if (lastErrno == ERROR_ALREADY_EXISTS){
-+ bInit = FALSE;
- }
-- if( pShmNode ){
-- sqlite3_free(pNew);
-- }else{
-- pShmNode = pNew;
-- pNew = 0;
-- ((winFile*)(&pShmNode->hFile))->h = INVALID_HANDLE_VALUE;
-- pShmNode->pNext = winShmNodeList;
-- winShmNodeList = pShmNode;
-
-- pShmNode->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
-- if( pShmNode->mutex==0 ){
-- rc = SQLITE_IOERR_NOMEM;
-- goto shm_open_err;
-- }
-+ sqlite3_free(zName);
-
-- rc = winOpen(pDbFd->pVfs,
-- pShmNode->zFilename, /* Name of the file (UTF-8) */
-- (sqlite3_file*)&pShmNode->hFile, /* File handle here */
-- SQLITE_OPEN_WAL | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE,
-- 0);
-- if( SQLITE_OK!=rc ){
-- goto shm_open_err;
-+ /* If we succeeded in making the shared memory handle, map it. */
-+ if( pFile->hShared ){
-+ pFile->shared = (winceLock*)osMapViewOfFile(pFile->hShared,
-+ FILE_MAP_READ|FILE_MAP_WRITE, 0, 0, sizeof(winceLock));
-+ /* If mapping failed, close the shared memory handle and erase it */
-+ if( !pFile->shared ){
-+ pFile->lastErrno = osGetLastError();
-+ winLogError(SQLITE_IOERR, pFile->lastErrno,
-+ "winceCreateLock2", zFilename);
-+ bLogged = TRUE;
-+ osCloseHandle(pFile->hShared);
-+ pFile->hShared = NULL;
- }
-+ }
-
-- /* Check to see if another process is holding the dead-man switch.
-- ** If not, truncate the file to zero length.
-- */
-- if( winShmSystemLock(pShmNode, _SHM_WRLCK, WIN_SHM_DMS, 1)==SQLITE_OK ){
-- rc = winTruncate((sqlite3_file *)&pShmNode->hFile, 0);
-- if( rc!=SQLITE_OK ){
-- rc = winLogError(SQLITE_IOERR_SHMOPEN, osGetLastError(),
-- "winOpenShm", pDbFd->zPath);
-- }
-- }
-- if( rc==SQLITE_OK ){
-- winShmSystemLock(pShmNode, _SHM_UNLCK, WIN_SHM_DMS, 1);
-- rc = winShmSystemLock(pShmNode, _SHM_RDLCK, WIN_SHM_DMS, 1);
-+ /* If shared memory could not be created, then close the mutex and fail */
-+ if( pFile->hShared==NULL ){
-+ if( !bLogged ){
-+ pFile->lastErrno = lastErrno;
-+ winLogError(SQLITE_IOERR, pFile->lastErrno,
-+ "winceCreateLock3", zFilename);
-+ bLogged = TRUE;
- }
-- if( rc ) goto shm_open_err;
-+ winceMutexRelease(pFile->hMutex);
-+ osCloseHandle(pFile->hMutex);
-+ pFile->hMutex = NULL;
-+ return SQLITE_IOERR;
-+ }
-+
-+ /* Initialize the shared memory if we're supposed to */
-+ if( bInit ){
-+ memset(pFile->shared, 0, sizeof(winceLock));
- }
-
-- /* Make the new connection a child of the winShmNode */
-- p->pShmNode = pShmNode;
--#ifdef SQLITE_DEBUG
-- p->id = pShmNode->nextShmId++;
--#endif
-- pShmNode->nRef++;
-- pDbFd->pShm = p;
-- winShmLeaveMutex();
--
-- /* The reference count on pShmNode has already been incremented under
-- ** the cover of the winShmEnterMutex() mutex and the pointer from the
-- ** new (struct winShm) object to the pShmNode has been set. All that is
-- ** left to do is to link the new object into the linked list starting
-- ** at pShmNode->pFirst. This must be done while holding the pShmNode->mutex
-- ** mutex.
-- */
-- sqlite3_mutex_enter(pShmNode->mutex);
-- p->pNext = pShmNode->pFirst;
-- pShmNode->pFirst = p;
-- sqlite3_mutex_leave(pShmNode->mutex);
-+ winceMutexRelease(pFile->hMutex);
- return SQLITE_OK;
--
-- /* Jump here on any error */
--shm_open_err:
-- winShmSystemLock(pShmNode, _SHM_UNLCK, WIN_SHM_DMS, 1);
-- winShmPurge(pDbFd->pVfs, 0); /* This call frees pShmNode if required */
-- sqlite3_free(p);
-- sqlite3_free(pNew);
-- winShmLeaveMutex();
-- return rc;
- }
-
- /*
--** Close a connection to shared-memory. Delete the underlying
--** storage if deleteFlag is true.
-+** Destroy the part of winFile that deals with wince locks
- */
--static int winShmUnmap(
-- sqlite3_file *fd, /* Database holding shared memory */
-- int deleteFlag /* Delete after closing if true */
--){
-- winFile *pDbFd; /* Database holding shared-memory */
-- winShm *p; /* The connection to be closed */
-- winShmNode *pShmNode; /* The underlying shared-memory file */
-- winShm **pp; /* For looping over sibling connections */
--
-- pDbFd = (winFile*)fd;
-- p = pDbFd->pShm;
-- if( p==0 ) return SQLITE_OK;
-- pShmNode = p->pShmNode;
-+static void winceDestroyLock(winFile *pFile){
-+ if (pFile->hMutex){
-+ /* Acquire the mutex */
-+ winceMutexAcquire(pFile->hMutex);
-
-- /* Remove connection p from the set of connections associated
-- ** with pShmNode */
-- sqlite3_mutex_enter(pShmNode->mutex);
-- for(pp=&pShmNode->pFirst; (*pp)!=p; pp = &(*pp)->pNext){}
-- *pp = p->pNext;
-+ /* The following blocks should probably assert in debug mode, but they
-+ are to cleanup in case any locks remained open */
-+ if (pFile->local.nReaders){
-+ pFile->shared->nReaders --;
-+ }
-+ if (pFile->local.bReserved){
-+ pFile->shared->bReserved = FALSE;
-+ }
-+ if (pFile->local.bPending){
-+ pFile->shared->bPending = FALSE;
-+ }
-+ if (pFile->local.bExclusive){
-+ pFile->shared->bExclusive = FALSE;
-+ }
-
-- /* Free the connection p */
-- sqlite3_free(p);
-- pDbFd->pShm = 0;
-- sqlite3_mutex_leave(pShmNode->mutex);
-+ /* De-reference and close our copy of the shared memory handle */
-+ osUnmapViewOfFile(pFile->shared);
-+ osCloseHandle(pFile->hShared);
-
-- /* If pShmNode->nRef has reached 0, then close the underlying
-- ** shared-memory file, too */
-- winShmEnterMutex();
-- assert( pShmNode->nRef>0 );
-- pShmNode->nRef--;
-- if( pShmNode->nRef==0 ){
-- winShmPurge(pDbFd->pVfs, deleteFlag);
-+ /* Done with the mutex */
-+ winceMutexRelease(pFile->hMutex);
-+ osCloseHandle(pFile->hMutex);
-+ pFile->hMutex = NULL;
- }
-- winShmLeaveMutex();
--
-- return SQLITE_OK;
- }
-
--/*
--** Change the lock state for a shared-memory segment.
-+/*
-+** An implementation of the LockFile() API of Windows for CE
- */
--static int winShmLock(
-- sqlite3_file *fd, /* Database file holding the shared memory */
-- int ofst, /* First lock to acquire or release */
-- int n, /* Number of locks to acquire or release */
-- int flags /* What to do with the lock */
-+static BOOL winceLockFile(
-+ LPHANDLE phFile,
-+ DWORD dwFileOffsetLow,
-+ DWORD dwFileOffsetHigh,
-+ DWORD nNumberOfBytesToLockLow,
-+ DWORD nNumberOfBytesToLockHigh
- ){
-- winFile *pDbFd = (winFile*)fd; /* Connection holding shared memory */
-- winShm *p = pDbFd->pShm; /* The shared memory being locked */
-- winShm *pX; /* For looping over all siblings */
-- winShmNode *pShmNode = p->pShmNode;
-- int rc = SQLITE_OK; /* Result code */
-- u16 mask; /* Mask of locks to take or release */
-+ winFile *pFile = HANDLE_TO_WINFILE(phFile);
-+ BOOL bReturn = FALSE;
-
-- assert( ofst>=0 && ofst+n<=SQLITE_SHM_NLOCK );
-- assert( n>=1 );
-- assert( flags==(SQLITE_SHM_LOCK | SQLITE_SHM_SHARED)
-- || flags==(SQLITE_SHM_LOCK | SQLITE_SHM_EXCLUSIVE)
-- || flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED)
-- || flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE) );
-- assert( n==1 || (flags & SQLITE_SHM_EXCLUSIVE)!=0 );
-+ UNUSED_PARAMETER(dwFileOffsetHigh);
-+ UNUSED_PARAMETER(nNumberOfBytesToLockHigh);
-
-- mask = (u16)((1U<<(ofst+n)) - (1U<<ofst));
-- assert( n>1 || mask==(1<<ofst) );
-- sqlite3_mutex_enter(pShmNode->mutex);
-- if( flags & SQLITE_SHM_UNLOCK ){
-- u16 allMask = 0; /* Mask of locks held by siblings */
-+ if (!pFile->hMutex) return TRUE;
-+ winceMutexAcquire(pFile->hMutex);
-
-- /* See if any siblings hold this same lock */
-- for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
-- if( pX==p ) continue;
-- assert( (pX->exclMask & (p->exclMask|p->sharedMask))==0 );
-- allMask |= pX->sharedMask;
-+ /* Wanting an exclusive lock? */
-+ if (dwFileOffsetLow == (DWORD)SHARED_FIRST
-+ && nNumberOfBytesToLockLow == (DWORD)SHARED_SIZE){
-+ if (pFile->shared->nReaders == 0 && pFile->shared->bExclusive == 0){
-+ pFile->shared->bExclusive = TRUE;
-+ pFile->local.bExclusive = TRUE;
-+ bReturn = TRUE;
-+ }
-+ }
-+
-+ /* Want a read-only lock? */
-+ else if (dwFileOffsetLow == (DWORD)SHARED_FIRST &&
-+ nNumberOfBytesToLockLow == 1){
-+ if (pFile->shared->bExclusive == 0){
-+ pFile->local.nReaders ++;
-+ if (pFile->local.nReaders == 1){
-+ pFile->shared->nReaders ++;
-+ }
-+ bReturn = TRUE;
-+ }
-+ }
-+
-+ /* Want a pending lock? */
-+ else if (dwFileOffsetLow == (DWORD)PENDING_BYTE
-+ && nNumberOfBytesToLockLow == 1){
-+ /* If no pending lock has been acquired, then acquire it */
-+ if (pFile->shared->bPending == 0) {
-+ pFile->shared->bPending = TRUE;
-+ pFile->local.bPending = TRUE;
-+ bReturn = TRUE;
- }
-+ }
-
-- /* Unlock the system-level locks */
-- if( (mask & allMask)==0 ){
-- rc = winShmSystemLock(pShmNode, _SHM_UNLCK, ofst+WIN_SHM_BASE, n);
-- }else{
-- rc = SQLITE_OK;
-+ /* Want a reserved lock? */
-+ else if (dwFileOffsetLow == (DWORD)RESERVED_BYTE
-+ && nNumberOfBytesToLockLow == 1){
-+ if (pFile->shared->bReserved == 0) {
-+ pFile->shared->bReserved = TRUE;
-+ pFile->local.bReserved = TRUE;
-+ bReturn = TRUE;
- }
-+ }
-
-- /* Undo the local locks */
-- if( rc==SQLITE_OK ){
-- p->exclMask &= ~mask;
-- p->sharedMask &= ~mask;
-- }
-- }else if( flags & SQLITE_SHM_SHARED ){
-- u16 allShared = 0; /* Union of locks held by connections other than "p" */
-+ winceMutexRelease(pFile->hMutex);
-+ return bReturn;
-+}
-
-- /* Find out which shared locks are already held by sibling connections.
-- ** If any sibling already holds an exclusive lock, go ahead and return
-- ** SQLITE_BUSY.
-- */
-- for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
-- if( (pX->exclMask & mask)!=0 ){
-- rc = SQLITE_BUSY;
-- break;
-- }
-- allShared |= pX->sharedMask;
-+/*
-+** An implementation of the UnlockFile API of Windows for CE
-+*/
-+static BOOL winceUnlockFile(
-+ LPHANDLE phFile,
-+ DWORD dwFileOffsetLow,
-+ DWORD dwFileOffsetHigh,
-+ DWORD nNumberOfBytesToUnlockLow,
-+ DWORD nNumberOfBytesToUnlockHigh
-+){
-+ winFile *pFile = HANDLE_TO_WINFILE(phFile);
-+ BOOL bReturn = FALSE;
-+
-+ UNUSED_PARAMETER(dwFileOffsetHigh);
-+ UNUSED_PARAMETER(nNumberOfBytesToUnlockHigh);
-+
-+ if (!pFile->hMutex) return TRUE;
-+ winceMutexAcquire(pFile->hMutex);
-+
-+ /* Releasing a reader lock or an exclusive lock */
-+ if (dwFileOffsetLow == (DWORD)SHARED_FIRST){
-+ /* Did we have an exclusive lock? */
-+ if (pFile->local.bExclusive){
-+ assert(nNumberOfBytesToUnlockLow == (DWORD)SHARED_SIZE);
-+ pFile->local.bExclusive = FALSE;
-+ pFile->shared->bExclusive = FALSE;
-+ bReturn = TRUE;
- }
-
-- /* Get shared locks at the system level, if necessary */
-- if( rc==SQLITE_OK ){
-- if( (allShared & mask)==0 ){
-- rc = winShmSystemLock(pShmNode, _SHM_RDLCK, ofst+WIN_SHM_BASE, n);
-- }else{
-- rc = SQLITE_OK;
-+ /* Did we just have a reader lock? */
-+ else if (pFile->local.nReaders){
-+ assert(nNumberOfBytesToUnlockLow == (DWORD)SHARED_SIZE
-+ || nNumberOfBytesToUnlockLow == 1);
-+ pFile->local.nReaders --;
-+ if (pFile->local.nReaders == 0)
-+ {
-+ pFile->shared->nReaders --;
- }
-+ bReturn = TRUE;
- }
-+ }
-
-- /* Get the local shared locks */
-- if( rc==SQLITE_OK ){
-- p->sharedMask |= mask;
-- }
-- }else{
-- /* Make sure no sibling connections hold locks that will block this
-- ** lock. If any do, return SQLITE_BUSY right away.
-- */
-- for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
-- if( (pX->exclMask & mask)!=0 || (pX->sharedMask & mask)!=0 ){
-- rc = SQLITE_BUSY;
-- break;
-- }
-+ /* Releasing a pending lock */
-+ else if (dwFileOffsetLow == (DWORD)PENDING_BYTE
-+ && nNumberOfBytesToUnlockLow == 1){
-+ if (pFile->local.bPending){
-+ pFile->local.bPending = FALSE;
-+ pFile->shared->bPending = FALSE;
-+ bReturn = TRUE;
- }
--
-- /* Get the exclusive locks at the system level. Then if successful
-- ** also mark the local connection as being locked.
-- */
-- if( rc==SQLITE_OK ){
-- rc = winShmSystemLock(pShmNode, _SHM_WRLCK, ofst+WIN_SHM_BASE, n);
-- if( rc==SQLITE_OK ){
-- assert( (p->sharedMask & mask)==0 );
-- p->exclMask |= mask;
-- }
-+ }
-+ /* Releasing a reserved lock */
-+ else if (dwFileOffsetLow == (DWORD)RESERVED_BYTE
-+ && nNumberOfBytesToUnlockLow == 1){
-+ if (pFile->local.bReserved) {
-+ pFile->local.bReserved = FALSE;
-+ pFile->shared->bReserved = FALSE;
-+ bReturn = TRUE;
- }
- }
-- sqlite3_mutex_leave(pShmNode->mutex);
-- OSTRACE(("SHM-LOCK pid=%lu, id=%d, sharedMask=%03x, exclMask=%03x, rc=%s\n",
-- osGetCurrentProcessId(), p->id, p->sharedMask, p->exclMask,
-- sqlite3ErrName(rc)));
-- return rc;
-+
-+ winceMutexRelease(pFile->hMutex);
-+ return bReturn;
- }
-+/*
-+** End of the special code for wince
-+*****************************************************************************/
-+#endif /* SQLITE_OS_WINCE */
-
- /*
--** Implement a memory barrier or memory fence on shared memory.
--**
--** All loads and stores begun before the barrier must complete before
--** any load or store begun after the barrier.
-+** Lock a file region.
- */
--static void winShmBarrier(
-- sqlite3_file *fd /* Database holding the shared memory */
-+static BOOL winLockFile(
-+ LPHANDLE phFile,
-+ DWORD flags,
-+ DWORD offsetLow,
-+ DWORD offsetHigh,
-+ DWORD numBytesLow,
-+ DWORD numBytesHigh
- ){
-- UNUSED_PARAMETER(fd);
-- /* MemoryBarrier(); // does not work -- do not know why not */
-- winShmEnterMutex();
-- winShmLeaveMutex();
-+#if SQLITE_OS_WINCE
-+ /*
-+ ** NOTE: Windows CE is handled differently here due its lack of the Win32
-+ ** API LockFile.
-+ */
-+ return winceLockFile(phFile, offsetLow, offsetHigh,
-+ numBytesLow, numBytesHigh);
-+#else
-+ if( isNT() ){
-+ OVERLAPPED ovlp;
-+ memset(&ovlp, 0, sizeof(OVERLAPPED));
-+ ovlp.Offset = offsetLow;
-+ ovlp.OffsetHigh = offsetHigh;
-+ return osLockFileEx(*phFile, flags, 0, numBytesLow, numBytesHigh, &ovlp);
-+ }else{
-+ return osLockFile(*phFile, offsetLow, offsetHigh, numBytesLow,
-+ numBytesHigh);
-+ }
-+#endif
- }
-
- /*
--** This function is called to obtain a pointer to region iRegion of the
--** shared-memory associated with the database file fd. Shared-memory regions
--** are numbered starting from zero. Each shared-memory region is szRegion
--** bytes in size.
--**
--** If an error occurs, an error code is returned and *pp is set to NULL.
--**
--** Otherwise, if the isWrite parameter is 0 and the requested shared-memory
--** region has not been allocated (by any client, including one running in a
--** separate process), then *pp is set to NULL and SQLITE_OK returned. If
--** isWrite is non-zero and the requested shared-memory region has not yet
--** been allocated, it is allocated by this function.
--**
--** If the shared-memory region has already been allocated or is allocated by
--** this call as described above, then it is mapped into this processes
--** address space (if it is not already), *pp is set to point to the mapped
--** memory and SQLITE_OK returned.
--*/
--static int winShmMap(
-- sqlite3_file *fd, /* Handle open on database file */
-- int iRegion, /* Region to retrieve */
-- int szRegion, /* Size of regions */
-- int isWrite, /* True to extend file if necessary */
-- void volatile **pp /* OUT: Mapped memory */
-+** Unlock a file region.
-+ */
-+static BOOL winUnlockFile(
-+ LPHANDLE phFile,
-+ DWORD offsetLow,
-+ DWORD offsetHigh,
-+ DWORD numBytesLow,
-+ DWORD numBytesHigh
- ){
-- winFile *pDbFd = (winFile*)fd;
-- winShm *p = pDbFd->pShm;
-- winShmNode *pShmNode;
-- int rc = SQLITE_OK;
-+#if SQLITE_OS_WINCE
-+ /*
-+ ** NOTE: Windows CE is handled differently here due its lack of the Win32
-+ ** API UnlockFile.
-+ */
-+ return winceUnlockFile(phFile, offsetLow, offsetHigh,
-+ numBytesLow, numBytesHigh);
-+#else
-+ if( isNT() ){
-+ OVERLAPPED ovlp;
-+ memset(&ovlp, 0, sizeof(OVERLAPPED));
-+ ovlp.Offset = offsetLow;
-+ ovlp.OffsetHigh = offsetHigh;
-+ return osUnlockFileEx(*phFile, 0, numBytesLow, numBytesHigh, &ovlp);
-+ }else{
-+ return osUnlockFile(*phFile, offsetLow, offsetHigh, numBytesLow,
-+ numBytesHigh);
-+ }
-+#endif
-+}
-
-- if( !p ){
-- rc = winOpenSharedMemory(pDbFd);
-- if( rc!=SQLITE_OK ) return rc;
-- p = pDbFd->pShm;
-+/*****************************************************************************
-+** The next group of routines implement the I/O methods specified
-+** by the sqlite3_io_methods object.
-+******************************************************************************/
-+
-+/*
-+** Some Microsoft compilers lack this definition.
-+*/
-+#ifndef INVALID_SET_FILE_POINTER
-+# define INVALID_SET_FILE_POINTER ((DWORD)-1)
-+#endif
-+
-+/*
-+** Move the current position of the file handle passed as the first
-+** argument to offset iOffset within the file. If successful, return 0.
-+** Otherwise, set pFile->lastErrno and return non-zero.
-+*/
-+static int seekWinFile(winFile *pFile, sqlite3_int64 iOffset){
-+#if !SQLITE_OS_WINRT
-+ LONG upperBits; /* Most sig. 32 bits of new offset */
-+ LONG lowerBits; /* Least sig. 32 bits of new offset */
-+ DWORD dwRet; /* Value returned by SetFilePointer() */
-+ DWORD lastErrno; /* Value returned by GetLastError() */
-+
-+ OSTRACE(("SEEK file=%p, offset=%lld\n", pFile->h, iOffset));
-+
-+ upperBits = (LONG)((iOffset>>32) & 0x7fffffff);
-+ lowerBits = (LONG)(iOffset & 0xffffffff);
-+
-+ /* API oddity: If successful, SetFilePointer() returns a dword
-+ ** containing the lower 32-bits of the new file-offset. Or, if it fails,
-+ ** it returns INVALID_SET_FILE_POINTER. However according to MSDN,
-+ ** INVALID_SET_FILE_POINTER may also be a valid new offset. So to determine
-+ ** whether an error has actually occurred, it is also necessary to call
-+ ** GetLastError().
-+ */
-+ dwRet = osSetFilePointer(pFile->h, lowerBits, &upperBits, FILE_BEGIN);
-+
-+ if( (dwRet==INVALID_SET_FILE_POINTER
-+ && ((lastErrno = osGetLastError())!=NO_ERROR)) ){
-+ pFile->lastErrno = lastErrno;
-+ winLogError(SQLITE_IOERR_SEEK, pFile->lastErrno,
-+ "seekWinFile", pFile->zPath);
-+ OSTRACE(("SEEK file=%p, rc=SQLITE_IOERR_SEEK\n", pFile->h));
-+ return 1;
- }
-- pShmNode = p->pShmNode;
-
-- sqlite3_mutex_enter(pShmNode->mutex);
-- assert( szRegion==pShmNode->szRegion || pShmNode->nRegion==0 );
-+ OSTRACE(("SEEK file=%p, rc=SQLITE_OK\n", pFile->h));
-+ return 0;
-+#else
-+ /*
-+ ** Same as above, except that this implementation works for WinRT.
-+ */
-
-- if( pShmNode->nRegion<=iRegion ){
-- struct ShmRegion *apNew; /* New aRegion[] array */
-- int nByte = (iRegion+1)*szRegion; /* Minimum required file size */
-- sqlite3_int64 sz; /* Current size of wal-index file */
-+ LARGE_INTEGER x; /* The new offset */
-+ BOOL bRet; /* Value returned by SetFilePointerEx() */
-
-- pShmNode->szRegion = szRegion;
-+ x.QuadPart = iOffset;
-+ bRet = osSetFilePointerEx(pFile->h, x, 0, FILE_BEGIN);
-
-- /* The requested region is not mapped into this processes address space.
-- ** Check to see if it has been allocated (i.e. if the wal-index file is
-- ** large enough to contain the requested region).
-- */
-- rc = winFileSize((sqlite3_file *)&pShmNode->hFile, &sz);
-- if( rc!=SQLITE_OK ){
-- rc = winLogError(SQLITE_IOERR_SHMSIZE, osGetLastError(),
-- "winShmMap1", pDbFd->zPath);
-- goto shmpage_out;
-- }
-+ if(!bRet){
-+ pFile->lastErrno = osGetLastError();
-+ winLogError(SQLITE_IOERR_SEEK, pFile->lastErrno,
-+ "seekWinFile", pFile->zPath);
-+ OSTRACE(("SEEK file=%p, rc=SQLITE_IOERR_SEEK\n", pFile->h));
-+ return 1;
-+ }
-
-- if( sz<nByte ){
-- /* The requested memory region does not exist. If isWrite is set to
-- ** zero, exit early. *pp will be set to NULL and SQLITE_OK returned.
-- **
-- ** Alternatively, if isWrite is non-zero, use ftruncate() to allocate
-- ** the requested memory region.
-- */
-- if( !isWrite ) goto shmpage_out;
-- rc = winTruncate((sqlite3_file *)&pShmNode->hFile, nByte);
-- if( rc!=SQLITE_OK ){
-- rc = winLogError(SQLITE_IOERR_SHMSIZE, osGetLastError(),
-- "winShmMap2", pDbFd->zPath);
-- goto shmpage_out;
-- }
-- }
-+ OSTRACE(("SEEK file=%p, rc=SQLITE_OK\n", pFile->h));
-+ return 0;
-+#endif
-+}
-
-- /* Map the requested memory region into this processes address space. */
-- apNew = (struct ShmRegion *)sqlite3_realloc(
-- pShmNode->aRegion, (iRegion+1)*sizeof(apNew[0])
-- );
-- if( !apNew ){
-- rc = SQLITE_IOERR_NOMEM;
-- goto shmpage_out;
-- }
-- pShmNode->aRegion = apNew;
-+#if SQLITE_MAX_MMAP_SIZE>0
-+/* Forward references to VFS methods */
-+static int winUnmapfile(winFile*);
-+#endif
-
-- while( pShmNode->nRegion<=iRegion ){
-- HANDLE hMap = NULL; /* file-mapping handle */
-- void *pMap = 0; /* Mapped memory region */
--
--#if SQLITE_OS_WINRT
-- hMap = osCreateFileMappingFromApp(pShmNode->hFile.h,
-- NULL, PAGE_READWRITE, nByte, NULL
-- );
--#elif defined(SQLITE_WIN32_HAS_WIDE)
-- hMap = osCreateFileMappingW(pShmNode->hFile.h,
-- NULL, PAGE_READWRITE, 0, nByte, NULL
-- );
--#elif defined(SQLITE_WIN32_HAS_ANSI)
-- hMap = osCreateFileMappingA(pShmNode->hFile.h,
-- NULL, PAGE_READWRITE, 0, nByte, NULL
-- );
-+/*
-+** Close a file.
-+**
-+** It is reported that an attempt to close a handle might sometimes
-+** fail. This is a very unreasonable result, but Windows is notorious
-+** for being unreasonable so I do not doubt that it might happen. If
-+** the close fails, we pause for 100 milliseconds and try again. As
-+** many as MX_CLOSE_ATTEMPT attempts to close the handle are made before
-+** giving up and returning an error.
-+*/
-+#define MX_CLOSE_ATTEMPT 3
-+static int winClose(sqlite3_file *id){
-+ int rc, cnt = 0;
-+ winFile *pFile = (winFile*)id;
-+
-+ assert( id!=0 );
-+#ifndef SQLITE_OMIT_WAL
-+ assert( pFile->pShm==0 );
- #endif
-- OSTRACE(("SHM-MAP-CREATE pid=%lu, region=%d, size=%d, rc=%s\n",
-- osGetCurrentProcessId(), pShmNode->nRegion, nByte,
-- hMap ? "ok" : "failed"));
-- if( hMap ){
-- int iOffset = pShmNode->nRegion*szRegion;
-- int iOffsetShift = iOffset % winSysInfo.dwAllocationGranularity;
--#if SQLITE_OS_WINRT
-- pMap = osMapViewOfFileFromApp(hMap, FILE_MAP_WRITE | FILE_MAP_READ,
-- iOffset - iOffsetShift, szRegion + iOffsetShift
-- );
--#else
-- pMap = osMapViewOfFile(hMap, FILE_MAP_WRITE | FILE_MAP_READ,
-- 0, iOffset - iOffsetShift, szRegion + iOffsetShift
-- );
-+ assert( pFile->h!=NULL && pFile->h!=INVALID_HANDLE_VALUE );
-+ OSTRACE(("CLOSE file=%p\n", pFile->h));
-+
-+#if SQLITE_MAX_MMAP_SIZE>0
-+ rc = winUnmapfile(pFile);
-+ if( rc!=SQLITE_OK ) return rc;
- #endif
-- OSTRACE(("SHM-MAP-MAP pid=%lu, region=%d, offset=%d, size=%d, rc=%s\n",
-- osGetCurrentProcessId(), pShmNode->nRegion, iOffset,
-- szRegion, pMap ? "ok" : "failed"));
-- }
-- if( !pMap ){
-- pShmNode->lastErrno = osGetLastError();
-- rc = winLogError(SQLITE_IOERR_SHMMAP, pShmNode->lastErrno,
-- "winShmMap3", pDbFd->zPath);
-- if( hMap ) osCloseHandle(hMap);
-- goto shmpage_out;
-- }
-
-- pShmNode->aRegion[pShmNode->nRegion].pMap = pMap;
-- pShmNode->aRegion[pShmNode->nRegion].hMap = hMap;
-- pShmNode->nRegion++;
-+ do{
-+ rc = osCloseHandle(pFile->h);
-+ /* SimulateIOError( rc=0; cnt=MX_CLOSE_ATTEMPT; ); */
-+ }while( rc==0 && ++cnt < MX_CLOSE_ATTEMPT && (sqlite3_win32_sleep(100), 1) );
-+#if SQLITE_OS_WINCE
-+#define WINCE_DELETION_ATTEMPTS 3
-+ winceDestroyLock(pFile);
-+ if( pFile->zDeleteOnClose ){
-+ int cnt = 0;
-+ while(
-+ osDeleteFileW(pFile->zDeleteOnClose)==0
-+ && osGetFileAttributesW(pFile->zDeleteOnClose)!=0xffffffff
-+ && cnt++ < WINCE_DELETION_ATTEMPTS
-+ ){
-+ sqlite3_win32_sleep(100); /* Wait a little before trying again */
- }
-+ sqlite3_free(pFile->zDeleteOnClose);
- }
--
--shmpage_out:
-- if( pShmNode->nRegion>iRegion ){
-- int iOffset = iRegion*szRegion;
-- int iOffsetShift = iOffset % winSysInfo.dwAllocationGranularity;
-- char *p = (char *)pShmNode->aRegion[iRegion].pMap;
-- *pp = (void *)&p[iOffsetShift];
-- }else{
-- *pp = 0;
-+#endif
-+ if( rc ){
-+ pFile->h = NULL;
- }
-- sqlite3_mutex_leave(pShmNode->mutex);
-- return rc;
-+ OpenCounter(-1);
-+ OSTRACE(("CLOSE file=%p, rc=%s\n", pFile->h, rc ? "ok" : "failed"));
-+ return rc ? SQLITE_OK
-+ : winLogError(SQLITE_IOERR_CLOSE, osGetLastError(),
-+ "winClose", pFile->zPath);
- }
-
--#else
--# define winShmMap 0
--# define winShmLock 0
--# define winShmBarrier 0
--# define winShmUnmap 0
--#endif /* #ifndef SQLITE_OMIT_WAL */
--
- /*
--** Cleans up the mapped region of the specified file, if any.
-+** Read data from a file into a buffer. Return SQLITE_OK if all
-+** bytes were read successfully and SQLITE_IOERR if anything goes
-+** wrong.
- */
-+static int winRead(
-+ sqlite3_file *id, /* File to read from */
-+ void *pBuf, /* Write content into this buffer */
-+ int amt, /* Number of bytes to read */
-+ sqlite3_int64 offset /* Begin reading at this offset */
-+){
-+#if !SQLITE_OS_WINCE
-+ OVERLAPPED overlapped; /* The offset for ReadFile. */
-+#endif
-+ winFile *pFile = (winFile*)id; /* file handle */
-+ DWORD nRead; /* Number of bytes actually read from file */
-+ int nRetry = 0; /* Number of retrys */
-+
-+ assert( id!=0 );
-+ assert( amt>0 );
-+ assert( offset>=0 );
-+ SimulateIOError(return SQLITE_IOERR_READ);
-+ OSTRACE(("READ file=%p, buffer=%p, amount=%d, offset=%lld, lock=%d\n",
-+ pFile->h, pBuf, amt, offset, pFile->locktype));
-+
- #if SQLITE_MAX_MMAP_SIZE>0
--static int winUnmapfile(winFile *pFile){
-- assert( pFile!=0 );
-- OSTRACE(("UNMAP-FILE pid=%lu, pFile=%p, hMap=%p, pMapRegion=%p, "
-- "mmapSize=%lld, mmapSizeActual=%lld, mmapSizeMax=%lld\n",
-- osGetCurrentProcessId(), pFile, pFile->hMap, pFile->pMapRegion,
-- pFile->mmapSize, pFile->mmapSizeActual, pFile->mmapSizeMax));
-- if( pFile->pMapRegion ){
-- if( !osUnmapViewOfFile(pFile->pMapRegion) ){
-- pFile->lastErrno = osGetLastError();
-- OSTRACE(("UNMAP-FILE pid=%lu, pFile=%p, pMapRegion=%p, "
-- "rc=SQLITE_IOERR_MMAP\n", osGetCurrentProcessId(), pFile,
-- pFile->pMapRegion));
-- return winLogError(SQLITE_IOERR_MMAP, pFile->lastErrno,
-- "winUnmap1", pFile->zPath);
-+ /* Deal with as much of this read request as possible by transfering
-+ ** data from the memory mapping using memcpy(). */
-+ if( offset<pFile->mmapSize ){
-+ if( offset+amt <= pFile->mmapSize ){
-+ memcpy(pBuf, &((u8 *)(pFile->pMapRegion))[offset], amt);
-+ OSTRACE(("READ-MMAP file=%p, rc=SQLITE_OK\n", pFile->h));
-+ return SQLITE_OK;
-+ }else{
-+ int nCopy = (int)(pFile->mmapSize - offset);
-+ memcpy(pBuf, &((u8 *)(pFile->pMapRegion))[offset], nCopy);
-+ pBuf = &((u8 *)pBuf)[nCopy];
-+ amt -= nCopy;
-+ offset += nCopy;
- }
-- pFile->pMapRegion = 0;
-- pFile->mmapSize = 0;
-- pFile->mmapSizeActual = 0;
- }
-- if( pFile->hMap!=NULL ){
-- if( !osCloseHandle(pFile->hMap) ){
-- pFile->lastErrno = osGetLastError();
-- OSTRACE(("UNMAP-FILE pid=%lu, pFile=%p, hMap=%p, rc=SQLITE_IOERR_MMAP\n",
-- osGetCurrentProcessId(), pFile, pFile->hMap));
-- return winLogError(SQLITE_IOERR_MMAP, pFile->lastErrno,
-- "winUnmap2", pFile->zPath);
-- }
-- pFile->hMap = NULL;
-+#endif
-+
-+#if SQLITE_OS_WINCE
-+ if( seekWinFile(pFile, offset) ){
-+ OSTRACE(("READ file=%p, rc=SQLITE_FULL\n", pFile->h));
-+ return SQLITE_FULL;
-+ }
-+ while( !osReadFile(pFile->h, pBuf, amt, &nRead, 0) ){
-+#else
-+ memset(&overlapped, 0, sizeof(OVERLAPPED));
-+ overlapped.Offset = (LONG)(offset & 0xffffffff);
-+ overlapped.OffsetHigh = (LONG)((offset>>32) & 0x7fffffff);
-+ while( !osReadFile(pFile->h, pBuf, amt, &nRead, &overlapped) &&
-+ osGetLastError()!=ERROR_HANDLE_EOF ){
-+#endif
-+ DWORD lastErrno;
-+ if( retryIoerr(&nRetry, &lastErrno) ) continue;
-+ pFile->lastErrno = lastErrno;
-+ OSTRACE(("READ file=%p, rc=SQLITE_IOERR_READ\n", pFile->h));
-+ return winLogError(SQLITE_IOERR_READ, pFile->lastErrno,
-+ "winRead", pFile->zPath);
-+ }
-+ logIoerr(nRetry);
-+ if( nRead<(DWORD)amt ){
-+ /* Unread parts of the buffer must be zero-filled */
-+ memset(&((char*)pBuf)[nRead], 0, amt-nRead);
-+ OSTRACE(("READ file=%p, rc=SQLITE_IOERR_SHORT_READ\n", pFile->h));
-+ return SQLITE_IOERR_SHORT_READ;
- }
-- OSTRACE(("UNMAP-FILE pid=%lu, pFile=%p, rc=SQLITE_OK\n",
-- osGetCurrentProcessId(), pFile));
-+
-+ OSTRACE(("READ file=%p, rc=SQLITE_OK\n", pFile->h));
- return SQLITE_OK;
- }
-
- /*
--** Memory map or remap the file opened by file-descriptor pFd (if the file
--** is already mapped, the existing mapping is replaced by the new). Or, if
--** there already exists a mapping for this file, and there are still
--** outstanding xFetch() references to it, this function is a no-op.
--**
--** If parameter nByte is non-negative, then it is the requested size of
--** the mapping to create. Otherwise, if nByte is less than zero, then the
--** requested size is the size of the file on disk. The actual size of the
--** created mapping is either the requested size or the value configured
--** using SQLITE_FCNTL_MMAP_SIZE, whichever is smaller.
--**
--** SQLITE_OK is returned if no error occurs (even if the mapping is not
--** recreated as a result of outstanding references) or an SQLite error
--** code otherwise.
-+** Write data from a buffer into a file. Return SQLITE_OK on success
-+** or some other error code on failure.
- */
--static int winMapfile(winFile *pFd, sqlite3_int64 nByte){
-- sqlite3_int64 nMap = nByte;
-- int rc;
-+static int winWrite(
-+ sqlite3_file *id, /* File to write into */
-+ const void *pBuf, /* The bytes to be written */
-+ int amt, /* Number of bytes to write */
-+ sqlite3_int64 offset /* Offset into the file to begin writing at */
-+){
-+ int rc = 0; /* True if error has occurred, else false */
-+ winFile *pFile = (winFile*)id; /* File handle */
-+ int nRetry = 0; /* Number of retries */
-
-- assert( nMap>=0 || pFd->nFetchOut==0 );
-- OSTRACE(("MAP-FILE pid=%lu, pFile=%p, size=%lld\n",
-- osGetCurrentProcessId(), pFd, nByte));
-+ assert( amt>0 );
-+ assert( pFile );
-+ SimulateIOError(return SQLITE_IOERR_WRITE);
-+ SimulateDiskfullError(return SQLITE_FULL);
-
-- if( pFd->nFetchOut>0 ) return SQLITE_OK;
-+ OSTRACE(("WRITE file=%p, buffer=%p, amount=%d, offset=%lld, lock=%d\n",
-+ pFile->h, pBuf, amt, offset, pFile->locktype));
-
-- if( nMap<0 ){
-- rc = winFileSize((sqlite3_file*)pFd, &nMap);
-- if( rc ){
-- OSTRACE(("MAP-FILE pid=%lu, pFile=%p, rc=SQLITE_IOERR_FSTAT\n",
-- osGetCurrentProcessId(), pFd));
-- return SQLITE_IOERR_FSTAT;
-+#if SQLITE_MAX_MMAP_SIZE>0
-+ /* Deal with as much of this write request as possible by transfering
-+ ** data from the memory mapping using memcpy(). */
-+ if( offset<pFile->mmapSize ){
-+ if( offset+amt <= pFile->mmapSize ){
-+ memcpy(&((u8 *)(pFile->pMapRegion))[offset], pBuf, amt);
-+ OSTRACE(("WRITE-MMAP file=%p, rc=SQLITE_OK\n", pFile->h));
-+ return SQLITE_OK;
-+ }else{
-+ int nCopy = (int)(pFile->mmapSize - offset);
-+ memcpy(&((u8 *)(pFile->pMapRegion))[offset], pBuf, nCopy);
-+ pBuf = &((u8 *)pBuf)[nCopy];
-+ amt -= nCopy;
-+ offset += nCopy;
- }
- }
-- if( nMap>pFd->mmapSizeMax ){
-- nMap = pFd->mmapSizeMax;
-- }
-- nMap &= ~(sqlite3_int64)(winSysInfo.dwPageSize - 1);
--
-- if( nMap==0 && pFd->mmapSize>0 ){
-- winUnmapfile(pFd);
-- }
-- if( nMap!=pFd->mmapSize ){
-- void *pNew = 0;
-- DWORD protect = PAGE_READONLY;
-- DWORD flags = FILE_MAP_READ;
-+#endif
-
-- winUnmapfile(pFd);
-- if( (pFd->ctrlFlags & WINFILE_RDONLY)==0 ){
-- protect = PAGE_READWRITE;
-- flags |= FILE_MAP_WRITE;
-- }
--#if SQLITE_OS_WINRT
-- pFd->hMap = osCreateFileMappingFromApp(pFd->h, NULL, protect, nMap, NULL);
--#elif defined(SQLITE_WIN32_HAS_WIDE)
-- pFd->hMap = osCreateFileMappingW(pFd->h, NULL, protect,
-- (DWORD)((nMap>>32) & 0xffffffff),
-- (DWORD)(nMap & 0xffffffff), NULL);
--#elif defined(SQLITE_WIN32_HAS_ANSI)
-- pFd->hMap = osCreateFileMappingA(pFd->h, NULL, protect,
-- (DWORD)((nMap>>32) & 0xffffffff),
-- (DWORD)(nMap & 0xffffffff), NULL);
-+#if SQLITE_OS_WINCE
-+ rc = seekWinFile(pFile, offset);
-+ if( rc==0 ){
-+#else
-+ {
- #endif
-- if( pFd->hMap==NULL ){
-- pFd->lastErrno = osGetLastError();
-- rc = winLogError(SQLITE_IOERR_MMAP, pFd->lastErrno,
-- "winMapfile", pFd->zPath);
-- /* Log the error, but continue normal operation using xRead/xWrite */
-- OSTRACE(("MAP-FILE-CREATE pid=%lu, pFile=%p, rc=SQLITE_IOERR_MMAP\n",
-- osGetCurrentProcessId(), pFd));
-- return SQLITE_OK;
-- }
-- assert( (nMap % winSysInfo.dwPageSize)==0 );
--#if SQLITE_OS_WINRT
-- pNew = osMapViewOfFileFromApp(pFd->hMap, flags, 0, nMap);
-+#if !SQLITE_OS_WINCE
-+ OVERLAPPED overlapped; /* The offset for WriteFile. */
-+#endif
-+ u8 *aRem = (u8 *)pBuf; /* Data yet to be written */
-+ int nRem = amt; /* Number of bytes yet to be written */
-+ DWORD nWrite; /* Bytes written by each WriteFile() call */
-+ DWORD lastErrno = NO_ERROR; /* Value returned by GetLastError() */
-+
-+#if !SQLITE_OS_WINCE
-+ memset(&overlapped, 0, sizeof(OVERLAPPED));
-+ overlapped.Offset = (LONG)(offset & 0xffffffff);
-+ overlapped.OffsetHigh = (LONG)((offset>>32) & 0x7fffffff);
-+#endif
-+
-+ while( nRem>0 ){
-+#if SQLITE_OS_WINCE
-+ if( !osWriteFile(pFile->h, aRem, nRem, &nWrite, 0) ){
- #else
-- assert( sizeof(SIZE_T)==sizeof(sqlite3_int64) || nMap<=0xffffffff );
-- pNew = osMapViewOfFile(pFd->hMap, flags, 0, 0, (SIZE_T)nMap);
-+ if( !osWriteFile(pFile->h, aRem, nRem, &nWrite, &overlapped) ){
- #endif
-- if( pNew==NULL ){
-- osCloseHandle(pFd->hMap);
-- pFd->hMap = NULL;
-- pFd->lastErrno = osGetLastError();
-- winLogError(SQLITE_IOERR_MMAP, pFd->lastErrno,
-- "winMapfile", pFd->zPath);
-- OSTRACE(("MAP-FILE-MAP pid=%lu, pFile=%p, rc=SQLITE_IOERR_MMAP\n",
-- osGetCurrentProcessId(), pFd));
-- return SQLITE_OK;
-+ if( retryIoerr(&nRetry, &lastErrno) ) continue;
-+ break;
-+ }
-+ assert( nWrite==0 || nWrite<=(DWORD)nRem );
-+ if( nWrite==0 || nWrite>(DWORD)nRem ){
-+ lastErrno = osGetLastError();
-+ break;
-+ }
-+#if !SQLITE_OS_WINCE
-+ offset += nWrite;
-+ overlapped.Offset = (LONG)(offset & 0xffffffff);
-+ overlapped.OffsetHigh = (LONG)((offset>>32) & 0x7fffffff);
-+#endif
-+ aRem += nWrite;
-+ nRem -= nWrite;
-+ }
-+ if( nRem>0 ){
-+ pFile->lastErrno = lastErrno;
-+ rc = 1;
- }
-- pFd->pMapRegion = pNew;
-- pFd->mmapSize = nMap;
-- pFd->mmapSizeActual = nMap;
- }
-
-- OSTRACE(("MAP-FILE pid=%lu, pFile=%p, rc=SQLITE_OK\n",
-- osGetCurrentProcessId(), pFd));
-+ if( rc ){
-+ if( ( pFile->lastErrno==ERROR_HANDLE_DISK_FULL )
-+ || ( pFile->lastErrno==ERROR_DISK_FULL )){
-+ OSTRACE(("WRITE file=%p, rc=SQLITE_FULL\n", pFile->h));
-+ return SQLITE_FULL;
-+ }
-+ OSTRACE(("WRITE file=%p, rc=SQLITE_IOERR_WRITE\n", pFile->h));
-+ return winLogError(SQLITE_IOERR_WRITE, pFile->lastErrno,
-+ "winWrite", pFile->zPath);
-+ }else{
-+ logIoerr(nRetry);
-+ }
-+ OSTRACE(("WRITE file=%p, rc=SQLITE_OK\n", pFile->h));
- return SQLITE_OK;
- }
--#endif /* SQLITE_MAX_MMAP_SIZE>0 */
-
- /*
--** If possible, return a pointer to a mapping of file fd starting at offset
--** iOff. The mapping must be valid for at least nAmt bytes.
--**
--** If such a pointer can be obtained, store it in *pp and return SQLITE_OK.
--** Or, if one cannot but no error occurs, set *pp to 0 and return SQLITE_OK.
--** Finally, if an error does occur, return an SQLite error code. The final
--** value of *pp is undefined in this case.
--**
--** If this function does return a pointer, the caller must eventually
--** release the reference by calling winUnfetch().
-+** Truncate an open file to a specified size
- */
--static int winFetch(sqlite3_file *fd, i64 iOff, int nAmt, void **pp){
--#if SQLITE_MAX_MMAP_SIZE>0
-- winFile *pFd = (winFile*)fd; /* The underlying database file */
--#endif
-- *pp = 0;
-+static int winTruncate(sqlite3_file *id, sqlite3_int64 nByte){
-+ winFile *pFile = (winFile*)id; /* File handle object */
-+ int rc = SQLITE_OK; /* Return code for this function */
-+ DWORD lastErrno;
-
-- OSTRACE(("FETCH pid=%lu, pFile=%p, offset=%lld, amount=%d, pp=%p\n",
-- osGetCurrentProcessId(), fd, iOff, nAmt, pp));
-+ assert( pFile );
-+ SimulateIOError(return SQLITE_IOERR_TRUNCATE);
-+ OSTRACE(("TRUNCATE file=%p, size=%lld, lock=%d\n",
-+ pFile->h, nByte, pFile->locktype));
-+
-+ /* If the user has configured a chunk-size for this file, truncate the
-+ ** file so that it consists of an integer number of chunks (i.e. the
-+ ** actual file size after the operation may be larger than the requested
-+ ** size).
-+ */
-+ if( pFile->szChunk>0 ){
-+ nByte = ((nByte + pFile->szChunk - 1)/pFile->szChunk) * pFile->szChunk;
-+ }
-+
-+ /* SetEndOfFile() returns non-zero when successful, or zero when it fails. */
-+ if( seekWinFile(pFile, nByte) ){
-+ rc = winLogError(SQLITE_IOERR_TRUNCATE, pFile->lastErrno,
-+ "winTruncate1", pFile->zPath);
-+ }else if( 0==osSetEndOfFile(pFile->h) &&
-+ ((lastErrno = osGetLastError())!=ERROR_USER_MAPPED_FILE) ){
-+ pFile->lastErrno = lastErrno;
-+ rc = winLogError(SQLITE_IOERR_TRUNCATE, pFile->lastErrno,
-+ "winTruncate2", pFile->zPath);
-+ }
-
- #if SQLITE_MAX_MMAP_SIZE>0
-- if( pFd->mmapSizeMax>0 ){
-- if( pFd->pMapRegion==0 ){
-- int rc = winMapfile(pFd, -1);
-- if( rc!=SQLITE_OK ){
-- OSTRACE(("FETCH pid=%lu, pFile=%p, rc=%s\n",
-- osGetCurrentProcessId(), pFd, sqlite3ErrName(rc)));
-- return rc;
-- }
-- }
-- if( pFd->mmapSize >= iOff+nAmt ){
-- *pp = &((u8 *)pFd->pMapRegion)[iOff];
-- pFd->nFetchOut++;
-- }
-+ /* If the file was truncated to a size smaller than the currently
-+ ** mapped region, reduce the effective mapping size as well. SQLite will
-+ ** use read() and write() to access data beyond this point from now on.
-+ */
-+ if( pFile->pMapRegion && nByte<pFile->mmapSize ){
-+ pFile->mmapSize = nByte;
- }
- #endif
-
-- OSTRACE(("FETCH pid=%lu, pFile=%p, pp=%p, *pp=%p, rc=SQLITE_OK\n",
-- osGetCurrentProcessId(), fd, pp, *pp));
-- return SQLITE_OK;
-+ OSTRACE(("TRUNCATE file=%p, rc=%s\n", pFile->h, sqlite3ErrName(rc)));
-+ return rc;
- }
-
-+#ifdef SQLITE_TEST
- /*
--** If the third argument is non-NULL, then this function releases a
--** reference obtained by an earlier call to winFetch(). The second
--** argument passed to this function must be the same as the corresponding
--** argument that was passed to the winFetch() invocation.
--**
--** Or, if the third argument is NULL, then this function is being called
--** to inform the VFS layer that, according to POSIX, any existing mapping
--** may now be invalid and should be unmapped.
-+** Count the number of fullsyncs and normal syncs. This is used to test
-+** that syncs and fullsyncs are occuring at the right times.
- */
--static int winUnfetch(sqlite3_file *fd, i64 iOff, void *p){
--#if SQLITE_MAX_MMAP_SIZE>0
-- winFile *pFd = (winFile*)fd; /* The underlying database file */
-+SQLITE_API int sqlite3_sync_count = 0;
-+SQLITE_API int sqlite3_fullsync_count = 0;
-+#endif
-
-- /* If p==0 (unmap the entire file) then there must be no outstanding
-- ** xFetch references. Or, if p!=0 (meaning it is an xFetch reference),
-- ** then there must be at least one outstanding. */
-- assert( (p==0)==(pFd->nFetchOut==0) );
-+/*
-+** Make sure all writes to a particular file are committed to disk.
-+*/
-+static int winSync(sqlite3_file *id, int flags){
-+#ifndef SQLITE_NO_SYNC
-+ /*
-+ ** Used only when SQLITE_NO_SYNC is not defined.
-+ */
-+ BOOL rc;
-+#endif
-+#if !defined(NDEBUG) || !defined(SQLITE_NO_SYNC) || \
-+ (defined(SQLITE_TEST) && defined(SQLITE_DEBUG))
-+ /*
-+ ** Used when SQLITE_NO_SYNC is not defined and by the assert() and/or
-+ ** OSTRACE() macros.
-+ */
-+ winFile *pFile = (winFile*)id;
-+#else
-+ UNUSED_PARAMETER(id);
-+#endif
-
-- /* If p!=0, it must match the iOff value. */
-- assert( p==0 || p==&((u8 *)pFd->pMapRegion)[iOff] );
-+ assert( pFile );
-+ /* Check that one of SQLITE_SYNC_NORMAL or FULL was passed */
-+ assert((flags&0x0F)==SQLITE_SYNC_NORMAL
-+ || (flags&0x0F)==SQLITE_SYNC_FULL
-+ );
-
-- OSTRACE(("UNFETCH pid=%lu, pFile=%p, offset=%lld, p=%p\n",
-- osGetCurrentProcessId(), pFd, iOff, p));
-+ /* Unix cannot, but some systems may return SQLITE_FULL from here. This
-+ ** line is to test that doing so does not cause any problems.
-+ */
-+ SimulateDiskfullError( return SQLITE_FULL );
-
-- if( p ){
-- pFd->nFetchOut--;
-- }else{
-- /* FIXME: If Windows truly always prevents truncating or deleting a
-- ** file while a mapping is held, then the following winUnmapfile() call
-- ** is unnecessary can can be omitted - potentially improving
-- ** performance. */
-- winUnmapfile(pFd);
-- }
-+ OSTRACE(("SYNC file=%p, flags=%x, lock=%d\n",
-+ pFile->h, flags, pFile->locktype));
-
-- assert( pFd->nFetchOut>=0 );
-+#ifndef SQLITE_TEST
-+ UNUSED_PARAMETER(flags);
-+#else
-+ if( (flags&0x0F)==SQLITE_SYNC_FULL ){
-+ sqlite3_fullsync_count++;
-+ }
-+ sqlite3_sync_count++;
- #endif
-
-- OSTRACE(("UNFETCH pid=%lu, pFile=%p, rc=SQLITE_OK\n",
-- osGetCurrentProcessId(), fd));
-+ /* If we compiled with the SQLITE_NO_SYNC flag, then syncing is a
-+ ** no-op
-+ */
-+#ifdef SQLITE_NO_SYNC
- return SQLITE_OK;
-+#else
-+ rc = osFlushFileBuffers(pFile->h);
-+ SimulateIOError( rc=FALSE );
-+ if( rc ){
-+ OSTRACE(("SYNC file=%p, rc=SQLITE_OK\n", pFile->h));
-+ return SQLITE_OK;
-+ }else{
-+ pFile->lastErrno = osGetLastError();
-+ OSTRACE(("SYNC file=%p, rc=SQLITE_IOERR_FSYNC\n", pFile->h));
-+ return winLogError(SQLITE_IOERR_FSYNC, pFile->lastErrno,
-+ "winSync", pFile->zPath);
-+ }
-+#endif
- }
-
- /*
--** Here ends the implementation of all sqlite3_file methods.
--**
--********************** End sqlite3_file Methods *******************************
--******************************************************************************/
--
--/*
--** This vector defines all the methods that can operate on an
--** sqlite3_file for win32.
-+** Determine the current size of a file in bytes
- */
--static const sqlite3_io_methods winIoMethod = {
-- 3, /* iVersion */
-- winClose, /* xClose */
-- winRead, /* xRead */
-- winWrite, /* xWrite */
-- winTruncate, /* xTruncate */
-- winSync, /* xSync */
-- winFileSize, /* xFileSize */
-- winLock, /* xLock */
-- winUnlock, /* xUnlock */
-- winCheckReservedLock, /* xCheckReservedLock */
-- winFileControl, /* xFileControl */
-- winSectorSize, /* xSectorSize */
-- winDeviceCharacteristics, /* xDeviceCharacteristics */
-- winShmMap, /* xShmMap */
-- winShmLock, /* xShmLock */
-- winShmBarrier, /* xShmBarrier */
-- winShmUnmap, /* xShmUnmap */
-- winFetch, /* xFetch */
-- winUnfetch /* xUnfetch */
--};
-+static int winFileSize(sqlite3_file *id, sqlite3_int64 *pSize){
-+ winFile *pFile = (winFile*)id;
-+ int rc = SQLITE_OK;
-
--/****************************************************************************
--**************************** sqlite3_vfs methods ****************************
--**
--** This division contains the implementation of methods on the
--** sqlite3_vfs object.
--*/
-+ assert( id!=0 );
-+ assert( pSize!=0 );
-+ SimulateIOError(return SQLITE_IOERR_FSTAT);
-+ OSTRACE(("SIZE file=%p, pSize=%p\n", pFile->h, pSize));
-
--/*
--** Convert a UTF-8 filename into whatever form the underlying
--** operating system wants filenames in. Space to hold the result
--** is obtained from malloc and must be freed by the calling
--** function.
--*/
--static void *convertUtf8Filename(const char *zFilename){
-- void *zConverted = 0;
-- if( isNT() ){
-- zConverted = utf8ToUnicode(zFilename);
-+#if SQLITE_OS_WINRT
-+ {
-+ FILE_STANDARD_INFO info;
-+ if( osGetFileInformationByHandleEx(pFile->h, FileStandardInfo,
-+ &info, sizeof(info)) ){
-+ *pSize = info.EndOfFile.QuadPart;
-+ }else{
-+ pFile->lastErrno = osGetLastError();
-+ rc = winLogError(SQLITE_IOERR_FSTAT, pFile->lastErrno,
-+ "winFileSize", pFile->zPath);
-+ }
- }
--#ifdef SQLITE_WIN32_HAS_ANSI
-- else{
-- zConverted = sqlite3_win32_utf8_to_mbcs(zFilename);
-+#else
-+ {
-+ DWORD upperBits;
-+ DWORD lowerBits;
-+ DWORD lastErrno;
-+
-+ lowerBits = osGetFileSize(pFile->h, &upperBits);
-+ *pSize = (((sqlite3_int64)upperBits)<<32) + lowerBits;
-+ if( (lowerBits == INVALID_FILE_SIZE)
-+ && ((lastErrno = osGetLastError())!=NO_ERROR) ){
-+ pFile->lastErrno = lastErrno;
-+ rc = winLogError(SQLITE_IOERR_FSTAT, pFile->lastErrno,
-+ "winFileSize", pFile->zPath);
-+ }
- }
- #endif
-- /* caller will handle out of memory */
-- return zConverted;
-+ OSTRACE(("SIZE file=%p, pSize=%p, *pSize=%lld, rc=%s\n",
-+ pFile->h, pSize, *pSize, sqlite3ErrName(rc)));
-+ return rc;
- }
-
- /*
--** Create a temporary file name in zBuf. zBuf must be big enough to
--** hold at pVfs->mxPathname characters.
-+** LOCKFILE_FAIL_IMMEDIATELY is undefined on some Windows systems.
- */
--static int getTempname(int nBuf, char *zBuf){
-- static char zChars[] =
-- "abcdefghijklmnopqrstuvwxyz"
-- "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
-- "0123456789";
-- size_t i, j;
-- int nTempPath;
-- char zTempPath[MAX_PATH+2];
-+#ifndef LOCKFILE_FAIL_IMMEDIATELY
-+# define LOCKFILE_FAIL_IMMEDIATELY 1
-+#endif
-
-- /* It's odd to simulate an io-error here, but really this is just
-- ** using the io-error infrastructure to test that SQLite handles this
-- ** function failing.
-- */
-- SimulateIOError( return SQLITE_IOERR );
-+#ifndef LOCKFILE_EXCLUSIVE_LOCK
-+# define LOCKFILE_EXCLUSIVE_LOCK 2
-+#endif
-
-- memset(zTempPath, 0, MAX_PATH+2);
-+/*
-+** Historically, SQLite has used both the LockFile and LockFileEx functions.
-+** When the LockFile function was used, it was always expected to fail
-+** immediately if the lock could not be obtained. Also, it always expected to
-+** obtain an exclusive lock. These flags are used with the LockFileEx function
-+** and reflect those expectations; therefore, they should not be changed.
-+*/
-+#ifndef SQLITE_LOCKFILE_FLAGS
-+# define SQLITE_LOCKFILE_FLAGS (LOCKFILE_FAIL_IMMEDIATELY | \
-+ LOCKFILE_EXCLUSIVE_LOCK)
-+#endif
-
-- if( sqlite3_temp_directory ){
-- sqlite3_snprintf(MAX_PATH-30, zTempPath, "%s", sqlite3_temp_directory);
-- }
--#if !SQLITE_OS_WINRT
-- else if( isNT() ){
-- char *zMulti;
-- WCHAR zWidePath[MAX_PATH];
-- osGetTempPathW(MAX_PATH-30, zWidePath);
-- zMulti = unicodeToUtf8(zWidePath);
-- if( zMulti ){
-- sqlite3_snprintf(MAX_PATH-30, zTempPath, "%s", zMulti);
-- sqlite3_free(zMulti);
-- }else{
-- OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n"));
-- return SQLITE_IOERR_NOMEM;
-- }
-+/*
-+** Currently, SQLite never calls the LockFileEx function without wanting the
-+** call to fail immediately if the lock cannot be obtained.
-+*/
-+#ifndef SQLITE_LOCKFILEEX_FLAGS
-+# define SQLITE_LOCKFILEEX_FLAGS (LOCKFILE_FAIL_IMMEDIATELY)
-+#endif
-+
-+/*
-+** Acquire a reader lock.
-+** Different API routines are called depending on whether or not this
-+** is Win9x or WinNT.
-+*/
-+static int getReadLock(winFile *pFile){
-+ int res;
-+ OSTRACE(("READ-LOCK file=%p, lock=%d\n", pFile->h, pFile->locktype));
-+ if( isNT() ){
-+#if SQLITE_OS_WINCE
-+ /*
-+ ** NOTE: Windows CE is handled differently here due its lack of the Win32
-+ ** API LockFileEx.
-+ */
-+ res = winceLockFile(&pFile->h, SHARED_FIRST, 0, 1, 0);
-+#else
-+ res = winLockFile(&pFile->h, SQLITE_LOCKFILEEX_FLAGS, SHARED_FIRST, 0,
-+ SHARED_SIZE, 0);
-+#endif
- }
- #ifdef SQLITE_WIN32_HAS_ANSI
- else{
-- char *zUtf8;
-- char zMbcsPath[MAX_PATH];
-- osGetTempPathA(MAX_PATH-30, zMbcsPath);
-- zUtf8 = sqlite3_win32_mbcs_to_utf8(zMbcsPath);
-- if( zUtf8 ){
-- sqlite3_snprintf(MAX_PATH-30, zTempPath, "%s", zUtf8);
-- sqlite3_free(zUtf8);
-- }else{
-- OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n"));
-- return SQLITE_IOERR_NOMEM;
-- }
-+ int lk;
-+ sqlite3_randomness(sizeof(lk), &lk);
-+ pFile->sharedLockByte = (short)((lk & 0x7fffffff)%(SHARED_SIZE - 1));
-+ res = winLockFile(&pFile->h, SQLITE_LOCKFILE_FLAGS,
-+ SHARED_FIRST+pFile->sharedLockByte, 0, 1, 0);
- }
- #endif
--#endif
--
-- /* Check that the output buffer is large enough for the temporary file
-- ** name. If it is not, return SQLITE_ERROR.
-- */
-- nTempPath = sqlite3Strlen30(zTempPath);
--
-- if( (nTempPath + sqlite3Strlen30(SQLITE_TEMP_FILE_PREFIX) + 18) >= nBuf ){
-- OSTRACE(("TEMP-FILENAME rc=SQLITE_ERROR\n"));
-- return SQLITE_ERROR;
-- }
--
-- for(i=nTempPath; i>0 && zTempPath[i-1]=='\\'; i--){}
-- zTempPath[i] = 0;
--
-- sqlite3_snprintf(nBuf-18, zBuf, (nTempPath > 0) ?
-- "%s\\"SQLITE_TEMP_FILE_PREFIX : SQLITE_TEMP_FILE_PREFIX,
-- zTempPath);
-- j = sqlite3Strlen30(zBuf);
-- sqlite3_randomness(15, &zBuf[j]);
-- for(i=0; i<15; i++, j++){
-- zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ];
-+ if( res == 0 ){
-+ pFile->lastErrno = osGetLastError();
-+ /* No need to log a failure to lock */
- }
-- zBuf[j] = 0;
-- zBuf[j+1] = 0;
--
-- OSTRACE(("TEMP-FILENAME name=%s, rc=SQLITE_OK\n", zBuf));
-- return SQLITE_OK;
-+ OSTRACE(("READ-LOCK file=%p, rc=%s\n", pFile->h, sqlite3ErrName(res)));
-+ return res;
- }
-
- /*
--** Return TRUE if the named file is really a directory. Return false if
--** it is something other than a directory, or if there is any kind of memory
--** allocation failure.
-+** Undo a readlock
- */
--static int winIsDir(const void *zConverted){
-- DWORD attr;
-- int rc = 0;
-+static int unlockReadLock(winFile *pFile){
-+ int res;
- DWORD lastErrno;
--
-+ OSTRACE(("READ-UNLOCK file=%p, lock=%d\n", pFile->h, pFile->locktype));
- if( isNT() ){
-- int cnt = 0;
-- WIN32_FILE_ATTRIBUTE_DATA sAttrData;
-- memset(&sAttrData, 0, sizeof(sAttrData));
-- while( !(rc = osGetFileAttributesExW((LPCWSTR)zConverted,
-- GetFileExInfoStandard,
-- &sAttrData)) && retryIoerr(&cnt, &lastErrno) ){}
-- if( !rc ){
-- return 0; /* Invalid name? */
-- }
-- attr = sAttrData.dwFileAttributes;
--#if SQLITE_OS_WINCE==0
-- }else{
-- attr = osGetFileAttributesA((char*)zConverted);
-+ res = winUnlockFile(&pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0);
-+ }
-+#ifdef SQLITE_WIN32_HAS_ANSI
-+ else{
-+ res = winUnlockFile(&pFile->h, SHARED_FIRST+pFile->sharedLockByte, 0, 1, 0);
-+ }
- #endif
-+ if( res==0 && ((lastErrno = osGetLastError())!=ERROR_NOT_LOCKED) ){
-+ pFile->lastErrno = lastErrno;
-+ winLogError(SQLITE_IOERR_UNLOCK, pFile->lastErrno,
-+ "unlockReadLock", pFile->zPath);
- }
-- return (attr!=INVALID_FILE_ATTRIBUTES) && (attr&FILE_ATTRIBUTE_DIRECTORY);
-+ OSTRACE(("READ-UNLOCK file=%p, rc=%s\n", pFile->h, sqlite3ErrName(res)));
-+ return res;
- }
-
- /*
--** Open a file.
-+** Lock the file with the lock specified by parameter locktype - one
-+** of the following:
-+**
-+** (1) SHARED_LOCK
-+** (2) RESERVED_LOCK
-+** (3) PENDING_LOCK
-+** (4) EXCLUSIVE_LOCK
-+**
-+** Sometimes when requesting one lock state, additional lock states
-+** are inserted in between. The locking might fail on one of the later
-+** transitions leaving the lock state different from what it started but
-+** still short of its goal. The following chart shows the allowed
-+** transitions and the inserted intermediate states:
-+**
-+** UNLOCKED -> SHARED
-+** SHARED -> RESERVED
-+** SHARED -> (PENDING) -> EXCLUSIVE
-+** RESERVED -> (PENDING) -> EXCLUSIVE
-+** PENDING -> EXCLUSIVE
-+**
-+** This routine will only increase a lock. The winUnlock() routine
-+** erases all locks at once and returns us immediately to locking level 0.
-+** It is not possible to lower the locking level one step at a time. You
-+** must go straight to locking level 0.
- */
--static int winOpen(
-- sqlite3_vfs *pVfs, /* Not used */
-- const char *zName, /* Name of the file (UTF-8) */
-- sqlite3_file *id, /* Write the SQLite file handle here */
-- int flags, /* Open mode flags */
-- int *pOutFlags /* Status return flags */
--){
-- HANDLE h;
-- DWORD lastErrno;
-- DWORD dwDesiredAccess;
-- DWORD dwShareMode;
-- DWORD dwCreationDisposition;
-- DWORD dwFlagsAndAttributes = 0;
--#if SQLITE_OS_WINCE
-- int isTemp = 0;
--#endif
-+static int winLock(sqlite3_file *id, int locktype){
-+ int rc = SQLITE_OK; /* Return code from subroutines */
-+ int res = 1; /* Result of a Windows lock call */
-+ int newLocktype; /* Set pFile->locktype to this value before exiting */
-+ int gotPendingLock = 0;/* True if we acquired a PENDING lock this time */
- winFile *pFile = (winFile*)id;
-- void *zConverted; /* Filename in OS encoding */
-- const char *zUtf8Name = zName; /* Filename in UTF-8 encoding */
-- int cnt = 0;
--
-- /* If argument zPath is a NULL pointer, this function is required to open
-- ** a temporary file. Use this buffer to store the file name in.
-- */
-- char zTmpname[MAX_PATH+2]; /* Buffer used to create temp filename */
--
-- int rc = SQLITE_OK; /* Function Return Code */
--#if !defined(NDEBUG) || SQLITE_OS_WINCE
-- int eType = flags&0xFFFFFF00; /* Type of file to open */
--#endif
--
-- int isExclusive = (flags & SQLITE_OPEN_EXCLUSIVE);
-- int isDelete = (flags & SQLITE_OPEN_DELETEONCLOSE);
-- int isCreate = (flags & SQLITE_OPEN_CREATE);
-- int isReadonly = (flags & SQLITE_OPEN_READONLY);
-- int isReadWrite = (flags & SQLITE_OPEN_READWRITE);
--
--#ifndef NDEBUG
-- int isOpenJournal = (isCreate && (
-- eType==SQLITE_OPEN_MASTER_JOURNAL
-- || eType==SQLITE_OPEN_MAIN_JOURNAL
-- || eType==SQLITE_OPEN_WAL
-- ));
--#endif
-+ DWORD lastErrno = NO_ERROR;
-
-- OSTRACE(("OPEN name=%s, pFile=%p, flags=%x, pOutFlags=%p\n",
-- zUtf8Name, id, flags, pOutFlags));
-+ assert( id!=0 );
-+ OSTRACE(("LOCK file=%p, oldLock=%d(%d), newLock=%d\n",
-+ pFile->h, pFile->locktype, pFile->sharedLockByte, locktype));
-
-- /* Check the following statements are true:
-- **
-- ** (a) Exactly one of the READWRITE and READONLY flags must be set, and
-- ** (b) if CREATE is set, then READWRITE must also be set, and
-- ** (c) if EXCLUSIVE is set, then CREATE must also be set.
-- ** (d) if DELETEONCLOSE is set, then CREATE must also be set.
-+ /* If there is already a lock of this type or more restrictive on the
-+ ** OsFile, do nothing. Don't use the end_lock: exit path, as
-+ ** sqlite3OsEnterMutex() hasn't been called yet.
- */
-- assert((isReadonly==0 || isReadWrite==0) && (isReadWrite || isReadonly));
-- assert(isCreate==0 || isReadWrite);
-- assert(isExclusive==0 || isCreate);
-- assert(isDelete==0 || isCreate);
--
-- /* The main DB, main journal, WAL file and master journal are never
-- ** automatically deleted. Nor are they ever temporary files. */
-- assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MAIN_DB );
-- assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MAIN_JOURNAL );
-- assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MASTER_JOURNAL );
-- assert( (!isDelete && zName) || eType!=SQLITE_OPEN_WAL );
-+ if( pFile->locktype>=locktype ){
-+ OSTRACE(("LOCK-HELD file=%p, rc=SQLITE_OK\n", pFile->h));
-+ return SQLITE_OK;
-+ }
-
-- /* Assert that the upper layer has set one of the "file-type" flags. */
-- assert( eType==SQLITE_OPEN_MAIN_DB || eType==SQLITE_OPEN_TEMP_DB
-- || eType==SQLITE_OPEN_MAIN_JOURNAL || eType==SQLITE_OPEN_TEMP_JOURNAL
-- || eType==SQLITE_OPEN_SUBJOURNAL || eType==SQLITE_OPEN_MASTER_JOURNAL
-- || eType==SQLITE_OPEN_TRANSIENT_DB || eType==SQLITE_OPEN_WAL
-- );
-+ /* Make sure the locking sequence is correct
-+ */
-+ assert( pFile->locktype!=NO_LOCK || locktype==SHARED_LOCK );
-+ assert( locktype!=PENDING_LOCK );
-+ assert( locktype!=RESERVED_LOCK || pFile->locktype==SHARED_LOCK );
-
-- assert( pFile!=0 );
-- memset(pFile, 0, sizeof(winFile));
-- pFile->h = INVALID_HANDLE_VALUE;
-+ /* Lock the PENDING_LOCK byte if we need to acquire a PENDING lock or
-+ ** a SHARED lock. If we are acquiring a SHARED lock, the acquisition of
-+ ** the PENDING_LOCK byte is temporary.
-+ */
-+ newLocktype = pFile->locktype;
-+ if( (pFile->locktype==NO_LOCK)
-+ || ( (locktype==EXCLUSIVE_LOCK)
-+ && (pFile->locktype==RESERVED_LOCK))
-+ ){
-+ int cnt = 3;
-+ while( cnt-->0 && (res = winLockFile(&pFile->h, SQLITE_LOCKFILE_FLAGS,
-+ PENDING_BYTE, 0, 1, 0))==0 ){
-+ /* Try 3 times to get the pending lock. This is needed to work
-+ ** around problems caused by indexing and/or anti-virus software on
-+ ** Windows systems.
-+ ** If you are using this code as a model for alternative VFSes, do not
-+ ** copy this retry logic. It is a hack intended for Windows only.
-+ */
-+ OSTRACE(("LOCK-PENDING-FAIL file=%p, count=%d, rc=%s\n",
-+ pFile->h, cnt, sqlite3ErrName(res)));
-+ if( cnt ) sqlite3_win32_sleep(1);
-+ }
-+ gotPendingLock = res;
-+ if( !res ){
-+ lastErrno = osGetLastError();
-+ }
-+ }
-
--#if SQLITE_OS_WINRT
-- if( !sqlite3_temp_directory ){
-- sqlite3_log(SQLITE_ERROR,
-- "sqlite3_temp_directory variable should be set for WinRT");
-+ /* Acquire a shared lock
-+ */
-+ if( locktype==SHARED_LOCK && res ){
-+ assert( pFile->locktype==NO_LOCK );
-+ res = getReadLock(pFile);
-+ if( res ){
-+ newLocktype = SHARED_LOCK;
-+ }else{
-+ lastErrno = osGetLastError();
-+ }
- }
--#endif
-
-- /* If the second argument to this function is NULL, generate a
-- ** temporary file name to use
-+ /* Acquire a RESERVED lock
- */
-- if( !zUtf8Name ){
-- assert(isDelete && !isOpenJournal);
-- memset(zTmpname, 0, MAX_PATH+2);
-- rc = getTempname(MAX_PATH+2, zTmpname);
-- if( rc!=SQLITE_OK ){
-- OSTRACE(("OPEN name=%s, rc=%s", zUtf8Name, sqlite3ErrName(rc)));
-- return rc;
-+ if( locktype==RESERVED_LOCK && res ){
-+ assert( pFile->locktype==SHARED_LOCK );
-+ res = winLockFile(&pFile->h, SQLITE_LOCKFILE_FLAGS, RESERVED_BYTE, 0, 1, 0);
-+ if( res ){
-+ newLocktype = RESERVED_LOCK;
-+ }else{
-+ lastErrno = osGetLastError();
- }
-- zUtf8Name = zTmpname;
- }
-
-- /* Database filenames are double-zero terminated if they are not
-- ** URIs with parameters. Hence, they can always be passed into
-- ** sqlite3_uri_parameter().
-+ /* Acquire a PENDING lock
- */
-- assert( (eType!=SQLITE_OPEN_MAIN_DB) || (flags & SQLITE_OPEN_URI) ||
-- zUtf8Name[strlen(zUtf8Name)+1]==0 );
-+ if( locktype==EXCLUSIVE_LOCK && res ){
-+ newLocktype = PENDING_LOCK;
-+ gotPendingLock = 0;
-+ }
-
-- /* Convert the filename to the system encoding. */
-- zConverted = convertUtf8Filename(zUtf8Name);
-- if( zConverted==0 ){
-- OSTRACE(("OPEN name=%s, rc=SQLITE_IOERR_NOMEM", zUtf8Name));
-- return SQLITE_IOERR_NOMEM;
-+ /* Acquire an EXCLUSIVE lock
-+ */
-+ if( locktype==EXCLUSIVE_LOCK && res ){
-+ assert( pFile->locktype>=SHARED_LOCK );
-+ res = unlockReadLock(pFile);
-+ res = winLockFile(&pFile->h, SQLITE_LOCKFILE_FLAGS, SHARED_FIRST, 0,
-+ SHARED_SIZE, 0);
-+ if( res ){
-+ newLocktype = EXCLUSIVE_LOCK;
-+ }else{
-+ lastErrno = osGetLastError();
-+ getReadLock(pFile);
-+ }
- }
-
-- if( winIsDir(zConverted) ){
-- sqlite3_free(zConverted);
-- OSTRACE(("OPEN name=%s, rc=SQLITE_CANTOPEN_ISDIR", zUtf8Name));
-- return SQLITE_CANTOPEN_ISDIR;
-+ /* If we are holding a PENDING lock that ought to be released, then
-+ ** release it now.
-+ */
-+ if( gotPendingLock && locktype==SHARED_LOCK ){
-+ winUnlockFile(&pFile->h, PENDING_BYTE, 0, 1, 0);
- }
-
-- if( isReadWrite ){
-- dwDesiredAccess = GENERIC_READ | GENERIC_WRITE;
-+ /* Update the state of the lock has held in the file descriptor then
-+ ** return the appropriate result code.
-+ */
-+ if( res ){
-+ rc = SQLITE_OK;
- }else{
-- dwDesiredAccess = GENERIC_READ;
-+ OSTRACE(("LOCK-FAIL file=%p, wanted=%d, got=%d\n",
-+ pFile->h, locktype, newLocktype));
-+ pFile->lastErrno = lastErrno;
-+ rc = SQLITE_BUSY;
- }
-+ pFile->locktype = (u8)newLocktype;
-+ OSTRACE(("LOCK file=%p, lock=%d, rc=%s\n",
-+ pFile->h, pFile->locktype, sqlite3ErrName(rc)));
-+ return rc;
-+}
-
-- /* SQLITE_OPEN_EXCLUSIVE is used to make sure that a new file is
-- ** created. SQLite doesn't use it to indicate "exclusive access"
-- ** as it is usually understood.
-- */
-- if( isExclusive ){
-- /* Creates a new file, only if it does not already exist. */
-- /* If the file exists, it fails. */
-- dwCreationDisposition = CREATE_NEW;
-- }else if( isCreate ){
-- /* Open existing file, or create if it doesn't exist */
-- dwCreationDisposition = OPEN_ALWAYS;
-+/*
-+** This routine checks if there is a RESERVED lock held on the specified
-+** file by this or any other process. If such a lock is held, return
-+** non-zero, otherwise zero.
-+*/
-+static int winCheckReservedLock(sqlite3_file *id, int *pResOut){
-+ int rc;
-+ winFile *pFile = (winFile*)id;
-+
-+ SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
-+ OSTRACE(("TEST-WR-LOCK file=%p, pResOut=%p\n", pFile->h, pResOut));
-+
-+ assert( id!=0 );
-+ if( pFile->locktype>=RESERVED_LOCK ){
-+ rc = 1;
-+ OSTRACE(("TEST-WR-LOCK file=%p, rc=%d (local)\n", pFile->h, rc));
- }else{
-- /* Opens a file, only if it exists. */
-- dwCreationDisposition = OPEN_EXISTING;
-+ rc = winLockFile(&pFile->h, SQLITE_LOCKFILEEX_FLAGS,RESERVED_BYTE, 0, 1, 0);
-+ if( rc ){
-+ winUnlockFile(&pFile->h, RESERVED_BYTE, 0, 1, 0);
-+ }
-+ rc = !rc;
-+ OSTRACE(("TEST-WR-LOCK file=%p, rc=%d (remote)\n", pFile->h, rc));
- }
-+ *pResOut = rc;
-+ OSTRACE(("TEST-WR-LOCK file=%p, pResOut=%p, *pResOut=%d, rc=SQLITE_OK\n",
-+ pFile->h, pResOut, *pResOut));
-+ return SQLITE_OK;
-+}
-
-- dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
-+/*
-+** Lower the locking level on file descriptor id to locktype. locktype
-+** must be either NO_LOCK or SHARED_LOCK.
-+**
-+** If the locking level of the file descriptor is already at or below
-+** the requested locking level, this routine is a no-op.
-+**
-+** It is not possible for this routine to fail if the second argument
-+** is NO_LOCK. If the second argument is SHARED_LOCK then this routine
-+** might return SQLITE_IOERR;
-+*/
-+static int winUnlock(sqlite3_file *id, int locktype){
-+ int type;
-+ winFile *pFile = (winFile*)id;
-+ int rc = SQLITE_OK;
-+ assert( pFile!=0 );
-+ assert( locktype<=SHARED_LOCK );
-+ OSTRACE(("UNLOCK file=%p, oldLock=%d(%d), newLock=%d\n",
-+ pFile->h, pFile->locktype, pFile->sharedLockByte, locktype));
-+ type = pFile->locktype;
-+ if( type>=EXCLUSIVE_LOCK ){
-+ winUnlockFile(&pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0);
-+ if( locktype==SHARED_LOCK && !getReadLock(pFile) ){
-+ /* This should never happen. We should always be able to
-+ ** reacquire the read lock */
-+ rc = winLogError(SQLITE_IOERR_UNLOCK, osGetLastError(),
-+ "winUnlock", pFile->zPath);
-+ }
-+ }
-+ if( type>=RESERVED_LOCK ){
-+ winUnlockFile(&pFile->h, RESERVED_BYTE, 0, 1, 0);
-+ }
-+ if( locktype==NO_LOCK && type>=SHARED_LOCK ){
-+ unlockReadLock(pFile);
-+ }
-+ if( type>=PENDING_LOCK ){
-+ winUnlockFile(&pFile->h, PENDING_BYTE, 0, 1, 0);
-+ }
-+ pFile->locktype = (u8)locktype;
-+ OSTRACE(("UNLOCK file=%p, lock=%d, rc=%s\n",
-+ pFile->h, pFile->locktype, sqlite3ErrName(rc)));
-+ return rc;
-+}
-
-- if( isDelete ){
--#if SQLITE_OS_WINCE
-- dwFlagsAndAttributes = FILE_ATTRIBUTE_HIDDEN;
-- isTemp = 1;
--#else
-- dwFlagsAndAttributes = FILE_ATTRIBUTE_TEMPORARY
-- | FILE_ATTRIBUTE_HIDDEN
-- | FILE_FLAG_DELETE_ON_CLOSE;
--#endif
-+/*
-+** If *pArg is inititially negative then this is a query. Set *pArg to
-+** 1 or 0 depending on whether or not bit mask of pFile->ctrlFlags is set.
-+**
-+** If *pArg is 0 or 1, then clear or set the mask bit of pFile->ctrlFlags.
-+*/
-+static void winModeBit(winFile *pFile, unsigned char mask, int *pArg){
-+ if( *pArg<0 ){
-+ *pArg = (pFile->ctrlFlags & mask)!=0;
-+ }else if( (*pArg)==0 ){
-+ pFile->ctrlFlags &= ~mask;
- }else{
-- dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL;
-+ pFile->ctrlFlags |= mask;
- }
-- /* Reports from the internet are that performance is always
-- ** better if FILE_FLAG_RANDOM_ACCESS is used. Ticket #2699. */
--#if SQLITE_OS_WINCE
-- dwFlagsAndAttributes |= FILE_FLAG_RANDOM_ACCESS;
--#endif
-+}
-
-- if( isNT() ){
--#if SQLITE_OS_WINRT
-- CREATEFILE2_EXTENDED_PARAMETERS extendedParameters;
-- extendedParameters.dwSize = sizeof(CREATEFILE2_EXTENDED_PARAMETERS);
-- extendedParameters.dwFileAttributes =
-- dwFlagsAndAttributes & FILE_ATTRIBUTE_MASK;
-- extendedParameters.dwFileFlags = dwFlagsAndAttributes & FILE_FLAG_MASK;
-- extendedParameters.dwSecurityQosFlags = SECURITY_ANONYMOUS;
-- extendedParameters.lpSecurityAttributes = NULL;
-- extendedParameters.hTemplateFile = NULL;
-- while( (h = osCreateFile2((LPCWSTR)zConverted,
-- dwDesiredAccess,
-- dwShareMode,
-- dwCreationDisposition,
-- &extendedParameters))==INVALID_HANDLE_VALUE &&
-- retryIoerr(&cnt, &lastErrno) ){
-- /* Noop */
-+/* Forward declaration */
-+static int getTempname(int nBuf, char *zBuf);
-+
-+/*
-+** Control and query of the open file handle.
-+*/
-+static int winFileControl(sqlite3_file *id, int op, void *pArg){
-+ winFile *pFile = (winFile*)id;
-+ OSTRACE(("FCNTL file=%p, op=%d, pArg=%p\n", pFile->h, op, pArg));
-+ switch( op ){
-+ case SQLITE_FCNTL_LOCKSTATE: {
-+ *(int*)pArg = pFile->locktype;
-+ OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
-+ return SQLITE_OK;
-+ }
-+ case SQLITE_LAST_ERRNO: {
-+ *(int*)pArg = (int)pFile->lastErrno;
-+ OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
-+ return SQLITE_OK;
-+ }
-+ case SQLITE_FCNTL_CHUNK_SIZE: {
-+ pFile->szChunk = *(int *)pArg;
-+ OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
-+ return SQLITE_OK;
-+ }
-+ case SQLITE_FCNTL_SIZE_HINT: {
-+ if( pFile->szChunk>0 ){
-+ sqlite3_int64 oldSz;
-+ int rc = winFileSize(id, &oldSz);
-+ if( rc==SQLITE_OK ){
-+ sqlite3_int64 newSz = *(sqlite3_int64*)pArg;
-+ if( newSz>oldSz ){
-+ SimulateIOErrorBenign(1);
-+ rc = winTruncate(id, newSz);
-+ SimulateIOErrorBenign(0);
-+ }
-+ }
-+ OSTRACE(("FCNTL file=%p, rc=%s\n", pFile->h, sqlite3ErrName(rc)));
-+ return rc;
-+ }
-+ OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
-+ return SQLITE_OK;
-+ }
-+ case SQLITE_FCNTL_PERSIST_WAL: {
-+ winModeBit(pFile, WINFILE_PERSIST_WAL, (int*)pArg);
-+ OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
-+ return SQLITE_OK;
-+ }
-+ case SQLITE_FCNTL_POWERSAFE_OVERWRITE: {
-+ winModeBit(pFile, WINFILE_PSOW, (int*)pArg);
-+ OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
-+ return SQLITE_OK;
-+ }
-+ case SQLITE_FCNTL_VFSNAME: {
-+ *(char**)pArg = sqlite3_mprintf("win32");
-+ OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
-+ return SQLITE_OK;
- }
--#else
-- while( (h = osCreateFileW((LPCWSTR)zConverted,
-- dwDesiredAccess,
-- dwShareMode, NULL,
-- dwCreationDisposition,
-- dwFlagsAndAttributes,
-- NULL))==INVALID_HANDLE_VALUE &&
-- retryIoerr(&cnt, &lastErrno) ){
-- /* Noop */
-+ case SQLITE_FCNTL_WIN32_AV_RETRY: {
-+ int *a = (int*)pArg;
-+ if( a[0]>0 ){
-+ win32IoerrRetry = a[0];
-+ }else{
-+ a[0] = win32IoerrRetry;
-+ }
-+ if( a[1]>0 ){
-+ win32IoerrRetryDelay = a[1];
-+ }else{
-+ a[1] = win32IoerrRetryDelay;
-+ }
-+ OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
-+ return SQLITE_OK;
- }
--#endif
-- }
--#ifdef SQLITE_WIN32_HAS_ANSI
-- else{
-- while( (h = osCreateFileA((LPCSTR)zConverted,
-- dwDesiredAccess,
-- dwShareMode, NULL,
-- dwCreationDisposition,
-- dwFlagsAndAttributes,
-- NULL))==INVALID_HANDLE_VALUE &&
-- retryIoerr(&cnt, &lastErrno) ){
-- /* Noop */
-+ case SQLITE_FCNTL_TEMPFILENAME: {
-+ char *zTFile = sqlite3MallocZero( pFile->pVfs->mxPathname );
-+ if( zTFile ){
-+ getTempname(pFile->pVfs->mxPathname, zTFile);
-+ *(char**)pArg = zTFile;
-+ }
-+ OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
-+ return SQLITE_OK;
- }
-- }
--#endif
-- logIoerr(cnt);
--
-- OSTRACE(("OPEN file=%p, name=%s, access=%lx, rc=%s\n", h, zUtf8Name,
-- dwDesiredAccess, (h==INVALID_HANDLE_VALUE) ? "failed" : "ok"));
--
-- if( h==INVALID_HANDLE_VALUE ){
-- pFile->lastErrno = lastErrno;
-- winLogError(SQLITE_CANTOPEN, pFile->lastErrno, "winOpen", zUtf8Name);
-- sqlite3_free(zConverted);
-- if( isReadWrite && !isExclusive ){
-- return winOpen(pVfs, zName, id,
-- ((flags|SQLITE_OPEN_READONLY) &
-- ~(SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE)),
-- pOutFlags);
-- }else{
-- return SQLITE_CANTOPEN_BKPT;
-+#if SQLITE_MAX_MMAP_SIZE>0
-+ case SQLITE_FCNTL_MMAP_SIZE: {
-+ i64 newLimit = *(i64*)pArg;
-+ if( newLimit>sqlite3GlobalConfig.mxMmap ){
-+ newLimit = sqlite3GlobalConfig.mxMmap;
-+ }
-+ *(i64*)pArg = pFile->mmapSizeMax;
-+ if( newLimit>=0 ) pFile->mmapSizeMax = newLimit;
-+ OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
-+ return SQLITE_OK;
- }
-+#endif
- }
-+ OSTRACE(("FCNTL file=%p, rc=SQLITE_NOTFOUND\n", pFile->h));
-+ return SQLITE_NOTFOUND;
-+}
-
-- if( pOutFlags ){
-- if( isReadWrite ){
-- *pOutFlags = SQLITE_OPEN_READWRITE;
-- }else{
-- *pOutFlags = SQLITE_OPEN_READONLY;
-- }
-- }
-+/*
-+** Return the sector size in bytes of the underlying block device for
-+** the specified file. This is almost always 512 bytes, but may be
-+** larger for some devices.
-+**
-+** SQLite code assumes this function cannot fail. It also assumes that
-+** if two files are created in the same file-system directory (i.e.
-+** a database and its journal file) that the sector size will be the
-+** same for both.
-+*/
-+static int winSectorSize(sqlite3_file *id){
-+ (void)id;
-+ return SQLITE_DEFAULT_SECTOR_SIZE;
-+}
-
-- OSTRACE(("OPEN file=%p, name=%s, access=%lx, pOutFlags=%p, *pOutFlags=%d, "
-- "rc=%s\n", h, zUtf8Name, dwDesiredAccess, pOutFlags, pOutFlags ?
-- *pOutFlags : 0, (h==INVALID_HANDLE_VALUE) ? "failed" : "ok"));
-+/*
-+** Return a vector of device characteristics.
-+*/
-+static int winDeviceCharacteristics(sqlite3_file *id){
-+ winFile *p = (winFile*)id;
-+ return SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN |
-+ ((p->ctrlFlags & WINFILE_PSOW)?SQLITE_IOCAP_POWERSAFE_OVERWRITE:0);
-+}
-
--#if SQLITE_OS_WINCE
-- if( isReadWrite && eType==SQLITE_OPEN_MAIN_DB
-- && (rc = winceCreateLock(zName, pFile))!=SQLITE_OK
-- ){
-- osCloseHandle(h);
-- sqlite3_free(zConverted);
-- OSTRACE(("OPEN-CE-LOCK name=%s, rc=%s\n", zName, sqlite3ErrName(rc)));
-- return rc;
-- }
-- if( isTemp ){
-- pFile->zDeleteOnClose = zConverted;
-- }else
--#endif
-- {
-- sqlite3_free(zConverted);
-- }
-+/*
-+** Windows will only let you create file view mappings
-+** on allocation size granularity boundaries.
-+** During sqlite3_os_init() we do a GetSystemInfo()
-+** to get the granularity size.
-+*/
-+SYSTEM_INFO winSysInfo;
-
-- pFile->pMethod = &winIoMethod;
-- pFile->pVfs = pVfs;
-- pFile->h = h;
-- if( isReadonly ){
-- pFile->ctrlFlags |= WINFILE_RDONLY;
-- }
-- if( sqlite3_uri_boolean(zName, "psow", SQLITE_POWERSAFE_OVERWRITE) ){
-- pFile->ctrlFlags |= WINFILE_PSOW;
-- }
-- pFile->lastErrno = NO_ERROR;
-- pFile->zPath = zName;
--#if SQLITE_MAX_MMAP_SIZE>0
-- pFile->hMap = NULL;
-- pFile->pMapRegion = 0;
-- pFile->mmapSize = 0;
-- pFile->mmapSizeActual = 0;
-- pFile->mmapSizeMax = sqlite3GlobalConfig.szMmap;
--#endif
-+#ifndef SQLITE_OMIT_WAL
-
-- OpenCounter(+1);
-- return rc;
-+/*
-+** Helper functions to obtain and relinquish the global mutex. The
-+** global mutex is used to protect the winLockInfo objects used by
-+** this file, all of which may be shared by multiple threads.
-+**
-+** Function winShmMutexHeld() is used to assert() that the global mutex
-+** is held when required. This function is only used as part of assert()
-+** statements. e.g.
-+**
-+** winShmEnterMutex()
-+** assert( winShmMutexHeld() );
-+** winShmLeaveMutex()
-+*/
-+static void winShmEnterMutex(void){
-+ sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
- }
-+static void winShmLeaveMutex(void){
-+ sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
-+}
-+#ifdef SQLITE_DEBUG
-+static int winShmMutexHeld(void) {
-+ return sqlite3_mutex_held(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
-+}
-+#endif
-
- /*
--** Delete the named file.
-+** Object used to represent a single file opened and mmapped to provide
-+** shared memory. When multiple threads all reference the same
-+** log-summary, each thread has its own winFile object, but they all
-+** point to a single instance of this object. In other words, each
-+** log-summary is opened only once per process.
-+**
-+** winShmMutexHeld() must be true when creating or destroying
-+** this object or while reading or writing the following fields:
-+**
-+** nRef
-+** pNext
-+**
-+** The following fields are read-only after the object is created:
-+**
-+** fid
-+** zFilename
-+**
-+** Either winShmNode.mutex must be held or winShmNode.nRef==0 and
-+** winShmMutexHeld() is true when reading or writing any other field
-+** in this structure.
- **
--** Note that Windows does not allow a file to be deleted if some other
--** process has it open. Sometimes a virus scanner or indexing program
--** will open a journal file shortly after it is created in order to do
--** whatever it does. While this other process is holding the
--** file open, we will be unable to delete it. To work around this
--** problem, we delay 100 milliseconds and try to delete again. Up
--** to MX_DELETION_ATTEMPTs deletion attempts are run before giving
--** up and returning an error.
- */
--static int winDelete(
-- sqlite3_vfs *pVfs, /* Not used on win32 */
-- const char *zFilename, /* Name of file to delete */
-- int syncDir /* Not used on win32 */
--){
-- int cnt = 0;
-- int rc;
-- DWORD attr;
-- DWORD lastErrno;
-- void *zConverted;
-- UNUSED_PARAMETER(pVfs);
-- UNUSED_PARAMETER(syncDir);
-+struct winShmNode {
-+ sqlite3_mutex *mutex; /* Mutex to access this object */
-+ char *zFilename; /* Name of the file */
-+ winFile hFile; /* File handle from winOpen */
-
-- SimulateIOError(return SQLITE_IOERR_DELETE);
-- OSTRACE(("DELETE name=%s, syncDir=%d\n", zFilename, syncDir));
-+ int szRegion; /* Size of shared-memory regions */
-+ int nRegion; /* Size of array apRegion */
-+ struct ShmRegion {
-+ HANDLE hMap; /* File handle from CreateFileMapping */
-+ void *pMap;
-+ } *aRegion;
-+ DWORD lastErrno; /* The Windows errno from the last I/O error */
-
-- zConverted = convertUtf8Filename(zFilename);
-- if( zConverted==0 ){
-- return SQLITE_IOERR_NOMEM;
-- }
-- if( isNT() ){
-- do {
--#if SQLITE_OS_WINRT
-- WIN32_FILE_ATTRIBUTE_DATA sAttrData;
-- memset(&sAttrData, 0, sizeof(sAttrData));
-- if ( osGetFileAttributesExW(zConverted, GetFileExInfoStandard,
-- &sAttrData) ){
-- attr = sAttrData.dwFileAttributes;
-- }else{
-- lastErrno = osGetLastError();
-- if( lastErrno==ERROR_FILE_NOT_FOUND
-- || lastErrno==ERROR_PATH_NOT_FOUND ){
-- rc = SQLITE_IOERR_DELETE_NOENT; /* Already gone? */
-- }else{
-- rc = SQLITE_ERROR;
-- }
-- break;
-- }
--#else
-- attr = osGetFileAttributesW(zConverted);
-+ int nRef; /* Number of winShm objects pointing to this */
-+ winShm *pFirst; /* All winShm objects pointing to this */
-+ winShmNode *pNext; /* Next in list of all winShmNode objects */
-+#ifdef SQLITE_DEBUG
-+ u8 nextShmId; /* Next available winShm.id value */
- #endif
-- if ( attr==INVALID_FILE_ATTRIBUTES ){
-- lastErrno = osGetLastError();
-- if( lastErrno==ERROR_FILE_NOT_FOUND
-- || lastErrno==ERROR_PATH_NOT_FOUND ){
-- rc = SQLITE_IOERR_DELETE_NOENT; /* Already gone? */
-- }else{
-- rc = SQLITE_ERROR;
-- }
-- break;
-- }
-- if ( attr&FILE_ATTRIBUTE_DIRECTORY ){
-- rc = SQLITE_ERROR; /* Files only. */
-- break;
-- }
-- if ( osDeleteFileW(zConverted) ){
-- rc = SQLITE_OK; /* Deleted OK. */
-- break;
-- }
-- if ( !retryIoerr(&cnt, &lastErrno) ){
-- rc = SQLITE_ERROR; /* No more retries. */
-- break;
-- }
-- } while(1);
-- }
--#ifdef SQLITE_WIN32_HAS_ANSI
-- else{
-- do {
-- attr = osGetFileAttributesA(zConverted);
-- if ( attr==INVALID_FILE_ATTRIBUTES ){
-- lastErrno = osGetLastError();
-- if( lastErrno==ERROR_FILE_NOT_FOUND
-- || lastErrno==ERROR_PATH_NOT_FOUND ){
-- rc = SQLITE_IOERR_DELETE_NOENT; /* Already gone? */
-- }else{
-- rc = SQLITE_ERROR;
-- }
-- break;
-- }
-- if ( attr&FILE_ATTRIBUTE_DIRECTORY ){
-- rc = SQLITE_ERROR; /* Files only. */
-- break;
-- }
-- if ( osDeleteFileA(zConverted) ){
-- rc = SQLITE_OK; /* Deleted OK. */
-- break;
-- }
-- if ( !retryIoerr(&cnt, &lastErrno) ){
-- rc = SQLITE_ERROR; /* No more retries. */
-- break;
-- }
-- } while(1);
-- }
-+};
-+
-+/*
-+** A global array of all winShmNode objects.
-+**
-+** The winShmMutexHeld() must be true while reading or writing this list.
-+*/
-+static winShmNode *winShmNodeList = 0;
-+
-+/*
-+** Structure used internally by this VFS to record the state of an
-+** open shared memory connection.
-+**
-+** The following fields are initialized when this object is created and
-+** are read-only thereafter:
-+**
-+** winShm.pShmNode
-+** winShm.id
-+**
-+** All other fields are read/write. The winShm.pShmNode->mutex must be held
-+** while accessing any read/write fields.
-+*/
-+struct winShm {
-+ winShmNode *pShmNode; /* The underlying winShmNode object */
-+ winShm *pNext; /* Next winShm with the same winShmNode */
-+ u8 hasMutex; /* True if holding the winShmNode mutex */
-+ u16 sharedMask; /* Mask of shared locks held */
-+ u16 exclMask; /* Mask of exclusive locks held */
-+#ifdef SQLITE_DEBUG
-+ u8 id; /* Id of this connection with its winShmNode */
- #endif
-- if( rc && rc!=SQLITE_IOERR_DELETE_NOENT ){
-- rc = winLogError(SQLITE_IOERR_DELETE, lastErrno,
-- "winDelete", zFilename);
-- }else{
-- logIoerr(cnt);
-- }
-- sqlite3_free(zConverted);
-- OSTRACE(("DELETE name=%s, rc=%s\n", zFilename, sqlite3ErrName(rc)));
-- return rc;
--}
-+};
-
- /*
--** Check the existence and status of a file.
-+** Constants used for locking
- */
--static int winAccess(
-- sqlite3_vfs *pVfs, /* Not used on win32 */
-- const char *zFilename, /* Name of file to check */
-- int flags, /* Type of test to make on this file */
-- int *pResOut /* OUT: Result */
-+#define WIN_SHM_BASE ((22+SQLITE_SHM_NLOCK)*4) /* first lock byte */
-+#define WIN_SHM_DMS (WIN_SHM_BASE+SQLITE_SHM_NLOCK) /* deadman switch */
-+
-+/*
-+** Apply advisory locks for all n bytes beginning at ofst.
-+*/
-+#define _SHM_UNLCK 1
-+#define _SHM_RDLCK 2
-+#define _SHM_WRLCK 3
-+static int winShmSystemLock(
-+ winShmNode *pFile, /* Apply locks to this open shared-memory segment */
-+ int lockType, /* _SHM_UNLCK, _SHM_RDLCK, or _SHM_WRLCK */
-+ int ofst, /* Offset to first byte to be locked/unlocked */
-+ int nByte /* Number of bytes to lock or unlock */
- ){
-- DWORD attr;
-- int rc = 0;
-- DWORD lastErrno;
-- void *zConverted;
-- UNUSED_PARAMETER(pVfs);
-+ int rc = 0; /* Result code form Lock/UnlockFileEx() */
-
-- SimulateIOError( return SQLITE_IOERR_ACCESS; );
-- OSTRACE(("ACCESS name=%s, flags=%x, pResOut=%p\n",
-- zFilename, flags, pResOut));
-+ /* Access to the winShmNode object is serialized by the caller */
-+ assert( sqlite3_mutex_held(pFile->mutex) || pFile->nRef==0 );
-
-- zConverted = convertUtf8Filename(zFilename);
-- if( zConverted==0 ){
-- OSTRACE(("ACCESS name=%s, rc=SQLITE_IOERR_NOMEM\n", zFilename));
-- return SQLITE_IOERR_NOMEM;
-- }
-- if( isNT() ){
-- int cnt = 0;
-- WIN32_FILE_ATTRIBUTE_DATA sAttrData;
-- memset(&sAttrData, 0, sizeof(sAttrData));
-- while( !(rc = osGetFileAttributesExW((LPCWSTR)zConverted,
-- GetFileExInfoStandard,
-- &sAttrData)) && retryIoerr(&cnt, &lastErrno) ){}
-- if( rc ){
-- /* For an SQLITE_ACCESS_EXISTS query, treat a zero-length file
-- ** as if it does not exist.
-- */
-- if( flags==SQLITE_ACCESS_EXISTS
-- && sAttrData.nFileSizeHigh==0
-- && sAttrData.nFileSizeLow==0 ){
-- attr = INVALID_FILE_ATTRIBUTES;
-- }else{
-- attr = sAttrData.dwFileAttributes;
-- }
-- }else{
-- logIoerr(cnt);
-- if( lastErrno!=ERROR_FILE_NOT_FOUND && lastErrno!=ERROR_PATH_NOT_FOUND ){
-- winLogError(SQLITE_IOERR_ACCESS, lastErrno, "winAccess", zFilename);
-- sqlite3_free(zConverted);
-- return SQLITE_IOERR_ACCESS;
-- }else{
-- attr = INVALID_FILE_ATTRIBUTES;
-- }
-- }
-- }
--#ifdef SQLITE_WIN32_HAS_ANSI
-- else{
-- attr = osGetFileAttributesA((char*)zConverted);
-+ OSTRACE(("SHM-LOCK file=%p, lock=%d, offset=%d, size=%d\n",
-+ pFile->hFile.h, lockType, ofst, nByte));
-+
-+ /* Release/Acquire the system-level lock */
-+ if( lockType==_SHM_UNLCK ){
-+ rc = winUnlockFile(&pFile->hFile.h, ofst, 0, nByte, 0);
-+ }else{
-+ /* Initialize the locking parameters */
-+ DWORD dwFlags = LOCKFILE_FAIL_IMMEDIATELY;
-+ if( lockType == _SHM_WRLCK ) dwFlags |= LOCKFILE_EXCLUSIVE_LOCK;
-+ rc = winLockFile(&pFile->hFile.h, dwFlags, ofst, 0, nByte, 0);
- }
--#endif
-- sqlite3_free(zConverted);
-- switch( flags ){
-- case SQLITE_ACCESS_READ:
-- case SQLITE_ACCESS_EXISTS:
-- rc = attr!=INVALID_FILE_ATTRIBUTES;
-- break;
-- case SQLITE_ACCESS_READWRITE:
-- rc = attr!=INVALID_FILE_ATTRIBUTES &&
-- (attr & FILE_ATTRIBUTE_READONLY)==0;
-- break;
-- default:
-- assert(!"Invalid flags argument");
-+
-+ if( rc!= 0 ){
-+ rc = SQLITE_OK;
-+ }else{
-+ pFile->lastErrno = osGetLastError();
-+ rc = SQLITE_BUSY;
- }
-- *pResOut = rc;
-- OSTRACE(("ACCESS name=%s, pResOut=%p, *pResOut=%d, rc=SQLITE_OK\n",
-- zFilename, pResOut, *pResOut));
-- return SQLITE_OK;
-+
-+ OSTRACE(("SHM-LOCK file=%p, func=%s, errno=%lu, rc=%s\n",
-+ pFile->hFile.h, (lockType == _SHM_UNLCK) ? "winUnlockFile" :
-+ "winLockFile", pFile->lastErrno, sqlite3ErrName(rc)));
-+
-+ return rc;
- }
-
-+/* Forward references to VFS methods */
-+static int winOpen(sqlite3_vfs*,const char*,sqlite3_file*,int,int*);
-+static int winDelete(sqlite3_vfs *,const char*,int);
-
- /*
--** Returns non-zero if the specified path name should be used verbatim. If
--** non-zero is returned from this function, the calling function must simply
--** use the provided path name verbatim -OR- resolve it into a full path name
--** using the GetFullPathName Win32 API function (if available).
-+** Purge the winShmNodeList list of all entries with winShmNode.nRef==0.
-+**
-+** This is not a VFS shared-memory method; it is a utility function called
-+** by VFS shared-memory methods.
- */
--static BOOL winIsVerbatimPathname(
-- const char *zPathname
--){
-- /*
-- ** If the path name starts with a forward slash or a backslash, it is either
-- ** a legal UNC name, a volume relative path, or an absolute path name in the
-- ** "Unix" format on Windows. There is no easy way to differentiate between
-- ** the final two cases; therefore, we return the safer return value of TRUE
-- ** so that callers of this function will simply use it verbatim.
-- */
-- if ( zPathname[0]=='/' || zPathname[0]=='\\' ){
-- return TRUE;
-- }
--
-- /*
-- ** If the path name starts with a letter and a colon it is either a volume
-- ** relative path or an absolute path. Callers of this function must not
-- ** attempt to treat it as a relative path name (i.e. they should simply use
-- ** it verbatim).
-- */
-- if ( sqlite3Isalpha(zPathname[0]) && zPathname[1]==':' ){
-- return TRUE;
-+static void winShmPurge(sqlite3_vfs *pVfs, int deleteFlag){
-+ winShmNode **pp;
-+ winShmNode *p;
-+ BOOL bRc;
-+ assert( winShmMutexHeld() );
-+ OSTRACE(("SHM-PURGE pid=%lu, deleteFlag=%d\n",
-+ osGetCurrentProcessId(), deleteFlag));
-+ pp = &winShmNodeList;
-+ while( (p = *pp)!=0 ){
-+ if( p->nRef==0 ){
-+ int i;
-+ if( p->mutex ) sqlite3_mutex_free(p->mutex);
-+ for(i=0; i<p->nRegion; i++){
-+ bRc = osUnmapViewOfFile(p->aRegion[i].pMap);
-+ OSTRACE(("SHM-PURGE-UNMAP pid=%lu, region=%d, rc=%s\n",
-+ osGetCurrentProcessId(), i, bRc ? "ok" : "failed"));
-+ bRc = osCloseHandle(p->aRegion[i].hMap);
-+ OSTRACE(("SHM-PURGE-CLOSE pid=%lu, region=%d, rc=%s\n",
-+ osGetCurrentProcessId(), i, bRc ? "ok" : "failed"));
-+ }
-+ if( p->hFile.h!=NULL && p->hFile.h!=INVALID_HANDLE_VALUE ){
-+ SimulateIOErrorBenign(1);
-+ winClose((sqlite3_file *)&p->hFile);
-+ SimulateIOErrorBenign(0);
-+ }
-+ if( deleteFlag ){
-+ SimulateIOErrorBenign(1);
-+ sqlite3BeginBenignMalloc();
-+ winDelete(pVfs, p->zFilename, 0);
-+ sqlite3EndBenignMalloc();
-+ SimulateIOErrorBenign(0);
-+ }
-+ *pp = p->pNext;
-+ sqlite3_free(p->aRegion);
-+ sqlite3_free(p);
-+ }else{
-+ pp = &p->pNext;
-+ }
- }
--
-- /*
-- ** If we get to this point, the path name should almost certainly be a purely
-- ** relative one (i.e. not a UNC name, not absolute, and not volume relative).
-- */
-- return FALSE;
- }
-
- /*
--** Turn a relative pathname into a full pathname. Write the full
--** pathname into zOut[]. zOut[] will be at least pVfs->mxPathname
--** bytes in size.
-+** Open the shared-memory area associated with database file pDbFd.
-+**
-+** When opening a new shared-memory file, if no other instances of that
-+** file are currently open, in this process or in other processes, then
-+** the file must be truncated to zero length or have its header cleared.
- */
--static int winFullPathname(
-- sqlite3_vfs *pVfs, /* Pointer to vfs object */
-- const char *zRelative, /* Possibly relative input path */
-- int nFull, /* Size of output buffer in bytes */
-- char *zFull /* Output buffer */
--){
--
--#if defined(__CYGWIN__)
-- SimulateIOError( return SQLITE_ERROR );
-- UNUSED_PARAMETER(nFull);
-- assert( pVfs->mxPathname>=MAX_PATH );
-- assert( nFull>=pVfs->mxPathname );
-- if ( sqlite3_data_directory && !winIsVerbatimPathname(zRelative) ){
-- /*
-- ** NOTE: We are dealing with a relative path name and the data
-- ** directory has been set. Therefore, use it as the basis
-- ** for converting the relative path name to an absolute
-- ** one by prepending the data directory and a slash.
-- */
-- char zOut[MAX_PATH+1];
-- memset(zOut, 0, MAX_PATH+1);
-- cygwin_conv_path(CCP_POSIX_TO_WIN_A|CCP_RELATIVE, zRelative, zOut,
-- MAX_PATH+1);
-- sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s\\%s",
-- sqlite3_data_directory, zOut);
-- }else{
-- cygwin_conv_path(CCP_POSIX_TO_WIN_A, zRelative, zFull, nFull);
-- }
-- return SQLITE_OK;
--#endif
--
--#if (SQLITE_OS_WINCE || SQLITE_OS_WINRT) && !defined(__CYGWIN__)
-- SimulateIOError( return SQLITE_ERROR );
-- /* WinCE has no concept of a relative pathname, or so I am told. */
-- /* WinRT has no way to convert a relative path to an absolute one. */
-- if ( sqlite3_data_directory && !winIsVerbatimPathname(zRelative) ){
-- /*
-- ** NOTE: We are dealing with a relative path name and the data
-- ** directory has been set. Therefore, use it as the basis
-- ** for converting the relative path name to an absolute
-- ** one by prepending the data directory and a backslash.
-- */
-- sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s\\%s",
-- sqlite3_data_directory, zRelative);
-- }else{
-- sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s", zRelative);
-- }
-- return SQLITE_OK;
--#endif
-+static int winOpenSharedMemory(winFile *pDbFd){
-+ struct winShm *p; /* The connection to be opened */
-+ struct winShmNode *pShmNode = 0; /* The underlying mmapped file */
-+ int rc; /* Result code */
-+ struct winShmNode *pNew; /* Newly allocated winShmNode */
-+ int nName; /* Size of zName in bytes */
-
--#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && !defined(__CYGWIN__)
-- DWORD nByte;
-- void *zConverted;
-- char *zOut;
-+ assert( pDbFd->pShm==0 ); /* Not previously opened */
-
-- /* If this path name begins with "/X:", where "X" is any alphabetic
-- ** character, discard the initial "/" from the pathname.
-+ /* Allocate space for the new sqlite3_shm object. Also speculatively
-+ ** allocate space for a new winShmNode and filename.
- */
-- if( zRelative[0]=='/' && sqlite3Isalpha(zRelative[1]) && zRelative[2]==':' ){
-- zRelative++;
-+ p = sqlite3MallocZero( sizeof(*p) );
-+ if( p==0 ) return SQLITE_IOERR_NOMEM;
-+ nName = sqlite3Strlen30(pDbFd->zPath);
-+ pNew = sqlite3MallocZero( sizeof(*pShmNode) + nName + 17 );
-+ if( pNew==0 ){
-+ sqlite3_free(p);
-+ return SQLITE_IOERR_NOMEM;
- }
-+ pNew->zFilename = (char*)&pNew[1];
-+ sqlite3_snprintf(nName+15, pNew->zFilename, "%s-shm", pDbFd->zPath);
-+ sqlite3FileSuffix3(pDbFd->zPath, pNew->zFilename);
-
-- /* It's odd to simulate an io-error here, but really this is just
-- ** using the io-error infrastructure to test that SQLite handles this
-- ** function failing. This function could fail if, for example, the
-- ** current working directory has been unlinked.
-+ /* Look to see if there is an existing winShmNode that can be used.
-+ ** If no matching winShmNode currently exists, create a new one.
- */
-- SimulateIOError( return SQLITE_ERROR );
-- if ( sqlite3_data_directory && !winIsVerbatimPathname(zRelative) ){
-- /*
-- ** NOTE: We are dealing with a relative path name and the data
-- ** directory has been set. Therefore, use it as the basis
-- ** for converting the relative path name to an absolute
-- ** one by prepending the data directory and a backslash.
-+ winShmEnterMutex();
-+ for(pShmNode = winShmNodeList; pShmNode; pShmNode=pShmNode->pNext){
-+ /* TBD need to come up with better match here. Perhaps
-+ ** use FILE_ID_BOTH_DIR_INFO Structure.
- */
-- sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s\\%s",
-- sqlite3_data_directory, zRelative);
-- return SQLITE_OK;
-- }
-- zConverted = convertUtf8Filename(zRelative);
-- if( zConverted==0 ){
-- return SQLITE_IOERR_NOMEM;
-+ if( sqlite3StrICmp(pShmNode->zFilename, pNew->zFilename)==0 ) break;
- }
-- if( isNT() ){
-- LPWSTR zTemp;
-- nByte = osGetFullPathNameW((LPCWSTR)zConverted, 0, 0, 0);
-- if( nByte==0 ){
-- winLogError(SQLITE_ERROR, osGetLastError(),
-- "GetFullPathNameW1", zConverted);
-- sqlite3_free(zConverted);
-- return SQLITE_CANTOPEN_FULLPATH;
-- }
-- nByte += 3;
-- zTemp = sqlite3MallocZero( nByte*sizeof(zTemp[0]) );
-- if( zTemp==0 ){
-- sqlite3_free(zConverted);
-- return SQLITE_IOERR_NOMEM;
-- }
-- nByte = osGetFullPathNameW((LPCWSTR)zConverted, nByte, zTemp, 0);
-- if( nByte==0 ){
-- winLogError(SQLITE_ERROR, osGetLastError(),
-- "GetFullPathNameW2", zConverted);
-- sqlite3_free(zConverted);
-- sqlite3_free(zTemp);
-- return SQLITE_CANTOPEN_FULLPATH;
-+ if( pShmNode ){
-+ sqlite3_free(pNew);
-+ }else{
-+ pShmNode = pNew;
-+ pNew = 0;
-+ ((winFile*)(&pShmNode->hFile))->h = INVALID_HANDLE_VALUE;
-+ pShmNode->pNext = winShmNodeList;
-+ winShmNodeList = pShmNode;
-+
-+ pShmNode->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
-+ if( pShmNode->mutex==0 ){
-+ rc = SQLITE_IOERR_NOMEM;
-+ goto shm_open_err;
- }
-- sqlite3_free(zConverted);
-- zOut = unicodeToUtf8(zTemp);
-- sqlite3_free(zTemp);
-- }
--#ifdef SQLITE_WIN32_HAS_ANSI
-- else{
-- char *zTemp;
-- nByte = osGetFullPathNameA((char*)zConverted, 0, 0, 0);
-- if( nByte==0 ){
-- winLogError(SQLITE_ERROR, osGetLastError(),
-- "GetFullPathNameA1", zConverted);
-- sqlite3_free(zConverted);
-- return SQLITE_CANTOPEN_FULLPATH;
-+
-+ rc = winOpen(pDbFd->pVfs,
-+ pShmNode->zFilename, /* Name of the file (UTF-8) */
-+ (sqlite3_file*)&pShmNode->hFile, /* File handle here */
-+ SQLITE_OPEN_WAL | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE,
-+ 0);
-+ if( SQLITE_OK!=rc ){
-+ goto shm_open_err;
- }
-- nByte += 3;
-- zTemp = sqlite3MallocZero( nByte*sizeof(zTemp[0]) );
-- if( zTemp==0 ){
-- sqlite3_free(zConverted);
-- return SQLITE_IOERR_NOMEM;
-+
-+ /* Check to see if another process is holding the dead-man switch.
-+ ** If not, truncate the file to zero length.
-+ */
-+ if( winShmSystemLock(pShmNode, _SHM_WRLCK, WIN_SHM_DMS, 1)==SQLITE_OK ){
-+ rc = winTruncate((sqlite3_file *)&pShmNode->hFile, 0);
-+ if( rc!=SQLITE_OK ){
-+ rc = winLogError(SQLITE_IOERR_SHMOPEN, osGetLastError(),
-+ "winOpenShm", pDbFd->zPath);
-+ }
- }
-- nByte = osGetFullPathNameA((char*)zConverted, nByte, zTemp, 0);
-- if( nByte==0 ){
-- winLogError(SQLITE_ERROR, osGetLastError(),
-- "GetFullPathNameA2", zConverted);
-- sqlite3_free(zConverted);
-- sqlite3_free(zTemp);
-- return SQLITE_CANTOPEN_FULLPATH;
-+ if( rc==SQLITE_OK ){
-+ winShmSystemLock(pShmNode, _SHM_UNLCK, WIN_SHM_DMS, 1);
-+ rc = winShmSystemLock(pShmNode, _SHM_RDLCK, WIN_SHM_DMS, 1);
- }
-- sqlite3_free(zConverted);
-- zOut = sqlite3_win32_mbcs_to_utf8(zTemp);
-- sqlite3_free(zTemp);
-- }
--#endif
-- if( zOut ){
-- sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s", zOut);
-- sqlite3_free(zOut);
-- return SQLITE_OK;
-- }else{
-- return SQLITE_IOERR_NOMEM;
-+ if( rc ) goto shm_open_err;
- }
-+
-+ /* Make the new connection a child of the winShmNode */
-+ p->pShmNode = pShmNode;
-+#ifdef SQLITE_DEBUG
-+ p->id = pShmNode->nextShmId++;
- #endif
-+ pShmNode->nRef++;
-+ pDbFd->pShm = p;
-+ winShmLeaveMutex();
-+
-+ /* The reference count on pShmNode has already been incremented under
-+ ** the cover of the winShmEnterMutex() mutex and the pointer from the
-+ ** new (struct winShm) object to the pShmNode has been set. All that is
-+ ** left to do is to link the new object into the linked list starting
-+ ** at pShmNode->pFirst. This must be done while holding the pShmNode->mutex
-+ ** mutex.
-+ */
-+ sqlite3_mutex_enter(pShmNode->mutex);
-+ p->pNext = pShmNode->pFirst;
-+ pShmNode->pFirst = p;
-+ sqlite3_mutex_leave(pShmNode->mutex);
-+ return SQLITE_OK;
-+
-+ /* Jump here on any error */
-+shm_open_err:
-+ winShmSystemLock(pShmNode, _SHM_UNLCK, WIN_SHM_DMS, 1);
-+ winShmPurge(pDbFd->pVfs, 0); /* This call frees pShmNode if required */
-+ sqlite3_free(p);
-+ sqlite3_free(pNew);
-+ winShmLeaveMutex();
-+ return rc;
- }
-
--#ifndef SQLITE_OMIT_LOAD_EXTENSION
--/*
--** Interfaces for opening a shared library, finding entry points
--** within the shared library, and closing the shared library.
--*/
- /*
--** Interfaces for opening a shared library, finding entry points
--** within the shared library, and closing the shared library.
-+** Close a connection to shared-memory. Delete the underlying
-+** storage if deleteFlag is true.
- */
--static void *winDlOpen(sqlite3_vfs *pVfs, const char *zFilename){
-- HANDLE h;
-- void *zConverted = convertUtf8Filename(zFilename);
-- UNUSED_PARAMETER(pVfs);
-- if( zConverted==0 ){
-- return 0;
-- }
-- if( isNT() ){
--#if SQLITE_OS_WINRT
-- h = osLoadPackagedLibrary((LPCWSTR)zConverted, 0);
--#else
-- h = osLoadLibraryW((LPCWSTR)zConverted);
--#endif
-- }
--#ifdef SQLITE_WIN32_HAS_ANSI
-- else{
-- h = osLoadLibraryA((char*)zConverted);
-- }
--#endif
-- sqlite3_free(zConverted);
-- return (void*)h;
--}
--static void winDlError(sqlite3_vfs *pVfs, int nBuf, char *zBufOut){
-- UNUSED_PARAMETER(pVfs);
-- getLastErrorMsg(osGetLastError(), nBuf, zBufOut);
--}
--static void (*winDlSym(sqlite3_vfs *pVfs,void *pH,const char *zSym))(void){
-- UNUSED_PARAMETER(pVfs);
-- return (void(*)(void))osGetProcAddressA((HANDLE)pH, zSym);
--}
--static void winDlClose(sqlite3_vfs *pVfs, void *pHandle){
-- UNUSED_PARAMETER(pVfs);
-- osFreeLibrary((HANDLE)pHandle);
--}
--#else /* if SQLITE_OMIT_LOAD_EXTENSION is defined: */
-- #define winDlOpen 0
-- #define winDlError 0
-- #define winDlSym 0
-- #define winDlClose 0
--#endif
-+static int winShmUnmap(
-+ sqlite3_file *fd, /* Database holding shared memory */
-+ int deleteFlag /* Delete after closing if true */
-+){
-+ winFile *pDbFd; /* Database holding shared-memory */
-+ winShm *p; /* The connection to be closed */
-+ winShmNode *pShmNode; /* The underlying shared-memory file */
-+ winShm **pp; /* For looping over sibling connections */
-
-+ pDbFd = (winFile*)fd;
-+ p = pDbFd->pShm;
-+ if( p==0 ) return SQLITE_OK;
-+ pShmNode = p->pShmNode;
-
--/*
--** Write up to nBuf bytes of randomness into zBuf.
--*/
--static int winRandomness(sqlite3_vfs *pVfs, int nBuf, char *zBuf){
-- int n = 0;
-- UNUSED_PARAMETER(pVfs);
--#if defined(SQLITE_TEST)
-- n = nBuf;
-- memset(zBuf, 0, nBuf);
--#else
-- if( sizeof(SYSTEMTIME)<=nBuf-n ){
-- SYSTEMTIME x;
-- osGetSystemTime(&x);
-- memcpy(&zBuf[n], &x, sizeof(x));
-- n += sizeof(x);
-- }
-- if( sizeof(DWORD)<=nBuf-n ){
-- DWORD pid = osGetCurrentProcessId();
-- memcpy(&zBuf[n], &pid, sizeof(pid));
-- n += sizeof(pid);
-- }
--#if SQLITE_OS_WINRT
-- if( sizeof(ULONGLONG)<=nBuf-n ){
-- ULONGLONG cnt = osGetTickCount64();
-- memcpy(&zBuf[n], &cnt, sizeof(cnt));
-- n += sizeof(cnt);
-- }
--#else
-- if( sizeof(DWORD)<=nBuf-n ){
-- DWORD cnt = osGetTickCount();
-- memcpy(&zBuf[n], &cnt, sizeof(cnt));
-- n += sizeof(cnt);
-- }
--#endif
-- if( sizeof(LARGE_INTEGER)<=nBuf-n ){
-- LARGE_INTEGER i;
-- osQueryPerformanceCounter(&i);
-- memcpy(&zBuf[n], &i, sizeof(i));
-- n += sizeof(i);
-- }
--#endif
-- return n;
--}
-+ /* Remove connection p from the set of connections associated
-+ ** with pShmNode */
-+ sqlite3_mutex_enter(pShmNode->mutex);
-+ for(pp=&pShmNode->pFirst; (*pp)!=p; pp = &(*pp)->pNext){}
-+ *pp = p->pNext;
-
-+ /* Free the connection p */
-+ sqlite3_free(p);
-+ pDbFd->pShm = 0;
-+ sqlite3_mutex_leave(pShmNode->mutex);
-
--/*
--** Sleep for a little while. Return the amount of time slept.
--*/
--static int winSleep(sqlite3_vfs *pVfs, int microsec){
-- sqlite3_win32_sleep((microsec+999)/1000);
-- UNUSED_PARAMETER(pVfs);
-- return ((microsec+999)/1000)*1000;
-+ /* If pShmNode->nRef has reached 0, then close the underlying
-+ ** shared-memory file, too */
-+ winShmEnterMutex();
-+ assert( pShmNode->nRef>0 );
-+ pShmNode->nRef--;
-+ if( pShmNode->nRef==0 ){
-+ winShmPurge(pDbFd->pVfs, deleteFlag);
-+ }
-+ winShmLeaveMutex();
-+
-+ return SQLITE_OK;
- }
-
- /*
--** The following variable, if set to a non-zero value, is interpreted as
--** the number of seconds since 1970 and is used to set the result of
--** sqlite3OsCurrentTime() during testing.
-+** Change the lock state for a shared-memory segment.
- */
--#ifdef SQLITE_TEST
--SQLITE_API int sqlite3_current_time = 0; /* Fake system time in seconds since 1970. */
--#endif
-+static int winShmLock(
-+ sqlite3_file *fd, /* Database file holding the shared memory */
-+ int ofst, /* First lock to acquire or release */
-+ int n, /* Number of locks to acquire or release */
-+ int flags /* What to do with the lock */
-+){
-+ winFile *pDbFd = (winFile*)fd; /* Connection holding shared memory */
-+ winShm *p = pDbFd->pShm; /* The shared memory being locked */
-+ winShm *pX; /* For looping over all siblings */
-+ winShmNode *pShmNode = p->pShmNode;
-+ int rc = SQLITE_OK; /* Result code */
-+ u16 mask; /* Mask of locks to take or release */
-
--/*
--** Find the current time (in Universal Coordinated Time). Write into *piNow
--** the current time and date as a Julian Day number times 86_400_000. In
--** other words, write into *piNow the number of milliseconds since the Julian
--** epoch of noon in Greenwich on November 24, 4714 B.C according to the
--** proleptic Gregorian calendar.
--**
--** On success, return SQLITE_OK. Return SQLITE_ERROR if the time and date
--** cannot be found.
--*/
--static int winCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *piNow){
-- /* FILETIME structure is a 64-bit value representing the number of
-- 100-nanosecond intervals since January 1, 1601 (= JD 2305813.5).
-- */
-- FILETIME ft;
-- static const sqlite3_int64 winFiletimeEpoch = 23058135*(sqlite3_int64)8640000;
--#ifdef SQLITE_TEST
-- static const sqlite3_int64 unixEpoch = 24405875*(sqlite3_int64)8640000;
--#endif
-- /* 2^32 - to avoid use of LL and warnings in gcc */
-- static const sqlite3_int64 max32BitValue =
-- (sqlite3_int64)2000000000 + (sqlite3_int64)2000000000 +
-- (sqlite3_int64)294967296;
-+ assert( ofst>=0 && ofst+n<=SQLITE_SHM_NLOCK );
-+ assert( n>=1 );
-+ assert( flags==(SQLITE_SHM_LOCK | SQLITE_SHM_SHARED)
-+ || flags==(SQLITE_SHM_LOCK | SQLITE_SHM_EXCLUSIVE)
-+ || flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED)
-+ || flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE) );
-+ assert( n==1 || (flags & SQLITE_SHM_EXCLUSIVE)!=0 );
-
--#if SQLITE_OS_WINCE
-- SYSTEMTIME time;
-- osGetSystemTime(&time);
-- /* if SystemTimeToFileTime() fails, it returns zero. */
-- if (!osSystemTimeToFileTime(&time,&ft)){
-- return SQLITE_ERROR;
-- }
--#else
-- osGetSystemTimeAsFileTime( &ft );
--#endif
-+ mask = (u16)((1U<<(ofst+n)) - (1U<<ofst));
-+ assert( n>1 || mask==(1<<ofst) );
-+ sqlite3_mutex_enter(pShmNode->mutex);
-+ if( flags & SQLITE_SHM_UNLOCK ){
-+ u16 allMask = 0; /* Mask of locks held by siblings */
-
-- *piNow = winFiletimeEpoch +
-- ((((sqlite3_int64)ft.dwHighDateTime)*max32BitValue) +
-- (sqlite3_int64)ft.dwLowDateTime)/(sqlite3_int64)10000;
-+ /* See if any siblings hold this same lock */
-+ for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
-+ if( pX==p ) continue;
-+ assert( (pX->exclMask & (p->exclMask|p->sharedMask))==0 );
-+ allMask |= pX->sharedMask;
-+ }
-
--#ifdef SQLITE_TEST
-- if( sqlite3_current_time ){
-- *piNow = 1000*(sqlite3_int64)sqlite3_current_time + unixEpoch;
-+ /* Unlock the system-level locks */
-+ if( (mask & allMask)==0 ){
-+ rc = winShmSystemLock(pShmNode, _SHM_UNLCK, ofst+WIN_SHM_BASE, n);
-+ }else{
-+ rc = SQLITE_OK;
-+ }
-+
-+ /* Undo the local locks */
-+ if( rc==SQLITE_OK ){
-+ p->exclMask &= ~mask;
-+ p->sharedMask &= ~mask;
-+ }
-+ }else if( flags & SQLITE_SHM_SHARED ){
-+ u16 allShared = 0; /* Union of locks held by connections other than "p" */
-+
-+ /* Find out which shared locks are already held by sibling connections.
-+ ** If any sibling already holds an exclusive lock, go ahead and return
-+ ** SQLITE_BUSY.
-+ */
-+ for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
-+ if( (pX->exclMask & mask)!=0 ){
-+ rc = SQLITE_BUSY;
-+ break;
-+ }
-+ allShared |= pX->sharedMask;
-+ }
-+
-+ /* Get shared locks at the system level, if necessary */
-+ if( rc==SQLITE_OK ){
-+ if( (allShared & mask)==0 ){
-+ rc = winShmSystemLock(pShmNode, _SHM_RDLCK, ofst+WIN_SHM_BASE, n);
-+ }else{
-+ rc = SQLITE_OK;
-+ }
-+ }
-+
-+ /* Get the local shared locks */
-+ if( rc==SQLITE_OK ){
-+ p->sharedMask |= mask;
-+ }
-+ }else{
-+ /* Make sure no sibling connections hold locks that will block this
-+ ** lock. If any do, return SQLITE_BUSY right away.
-+ */
-+ for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
-+ if( (pX->exclMask & mask)!=0 || (pX->sharedMask & mask)!=0 ){
-+ rc = SQLITE_BUSY;
-+ break;
-+ }
-+ }
-+
-+ /* Get the exclusive locks at the system level. Then if successful
-+ ** also mark the local connection as being locked.
-+ */
-+ if( rc==SQLITE_OK ){
-+ rc = winShmSystemLock(pShmNode, _SHM_WRLCK, ofst+WIN_SHM_BASE, n);
-+ if( rc==SQLITE_OK ){
-+ assert( (p->sharedMask & mask)==0 );
-+ p->exclMask |= mask;
-+ }
-+ }
- }
--#endif
-- UNUSED_PARAMETER(pVfs);
-- return SQLITE_OK;
-+ sqlite3_mutex_leave(pShmNode->mutex);
-+ OSTRACE(("SHM-LOCK pid=%lu, id=%d, sharedMask=%03x, exclMask=%03x, rc=%s\n",
-+ osGetCurrentProcessId(), p->id, p->sharedMask, p->exclMask,
-+ sqlite3ErrName(rc)));
-+ return rc;
- }
-
- /*
--** Find the current time (in Universal Coordinated Time). Write the
--** current time and date as a Julian Day number into *prNow and
--** return 0. Return 1 if the time and date cannot be found.
-+** Implement a memory barrier or memory fence on shared memory.
-+**
-+** All loads and stores begun before the barrier must complete before
-+** any load or store begun after the barrier.
- */
--static int winCurrentTime(sqlite3_vfs *pVfs, double *prNow){
-- int rc;
-- sqlite3_int64 i;
-- rc = winCurrentTimeInt64(pVfs, &i);
-- if( !rc ){
-- *prNow = i/86400000.0;
-- }
-- return rc;
-+static void winShmBarrier(
-+ sqlite3_file *fd /* Database holding the shared memory */
-+){
-+ UNUSED_PARAMETER(fd);
-+ /* MemoryBarrier(); // does not work -- do not know why not */
-+ winShmEnterMutex();
-+ winShmLeaveMutex();
- }
-
- /*
--** The idea is that this function works like a combination of
--** GetLastError() and FormatMessage() on Windows (or errno and
--** strerror_r() on Unix). After an error is returned by an OS
--** function, SQLite calls this function with zBuf pointing to
--** a buffer of nBuf bytes. The OS layer should populate the
--** buffer with a nul-terminated UTF-8 encoded error message
--** describing the last IO error to have occurred within the calling
--** thread.
--**
--** If the error message is too large for the supplied buffer,
--** it should be truncated. The return value of xGetLastError
--** is zero if the error message fits in the buffer, or non-zero
--** otherwise (if the message was truncated). If non-zero is returned,
--** then it is not necessary to include the nul-terminator character
--** in the output buffer.
-+** This function is called to obtain a pointer to region iRegion of the
-+** shared-memory associated with the database file fd. Shared-memory regions
-+** are numbered starting from zero. Each shared-memory region is szRegion
-+** bytes in size.
- **
--** Not supplying an error message will have no adverse effect
--** on SQLite. It is fine to have an implementation that never
--** returns an error message:
-+** If an error occurs, an error code is returned and *pp is set to NULL.
- **
--** int xGetLastError(sqlite3_vfs *pVfs, int nBuf, char *zBuf){
--** assert(zBuf[0]=='\0');
--** return 0;
--** }
-+** Otherwise, if the isWrite parameter is 0 and the requested shared-memory
-+** region has not been allocated (by any client, including one running in a
-+** separate process), then *pp is set to NULL and SQLITE_OK returned. If
-+** isWrite is non-zero and the requested shared-memory region has not yet
-+** been allocated, it is allocated by this function.
- **
--** However if an error message is supplied, it will be incorporated
--** by sqlite into the error message available to the user using
--** sqlite3_errmsg(), possibly making IO errors easier to debug.
-+** If the shared-memory region has already been allocated or is allocated by
-+** this call as described above, then it is mapped into this processes
-+** address space (if it is not already), *pp is set to point to the mapped
-+** memory and SQLITE_OK returned.
- */
--static int winGetLastError(sqlite3_vfs *pVfs, int nBuf, char *zBuf){
-- UNUSED_PARAMETER(pVfs);
-- return getLastErrorMsg(osGetLastError(), nBuf, zBuf);
--}
-+static int winShmMap(
-+ sqlite3_file *fd, /* Handle open on database file */
-+ int iRegion, /* Region to retrieve */
-+ int szRegion, /* Size of regions */
-+ int isWrite, /* True to extend file if necessary */
-+ void volatile **pp /* OUT: Mapped memory */
-+){
-+ winFile *pDbFd = (winFile*)fd;
-+ winShm *p = pDbFd->pShm;
-+ winShmNode *pShmNode;
-+ int rc = SQLITE_OK;
-
--/*
--** Initialize and deinitialize the operating system interface.
--*/
--SQLITE_API int sqlite3_os_init(void){
-- static sqlite3_vfs winVfs = {
-- 3, /* iVersion */
-- sizeof(winFile), /* szOsFile */
-- MAX_PATH, /* mxPathname */
-- 0, /* pNext */
-- "win32", /* zName */
-- 0, /* pAppData */
-- winOpen, /* xOpen */
-- winDelete, /* xDelete */
-- winAccess, /* xAccess */
-- winFullPathname, /* xFullPathname */
-- winDlOpen, /* xDlOpen */
-- winDlError, /* xDlError */
-- winDlSym, /* xDlSym */
-- winDlClose, /* xDlClose */
-- winRandomness, /* xRandomness */
-- winSleep, /* xSleep */
-- winCurrentTime, /* xCurrentTime */
-- winGetLastError, /* xGetLastError */
-- winCurrentTimeInt64, /* xCurrentTimeInt64 */
-- winSetSystemCall, /* xSetSystemCall */
-- winGetSystemCall, /* xGetSystemCall */
-- winNextSystemCall, /* xNextSystemCall */
-- };
-+ if( !p ){
-+ rc = winOpenSharedMemory(pDbFd);
-+ if( rc!=SQLITE_OK ) return rc;
-+ p = pDbFd->pShm;
-+ }
-+ pShmNode = p->pShmNode;
-
-- /* Double-check that the aSyscall[] array has been constructed
-- ** correctly. See ticket [bb3a86e890c8e96ab] */
-- assert( ArraySize(aSyscall)==74 );
-+ sqlite3_mutex_enter(pShmNode->mutex);
-+ assert( szRegion==pShmNode->szRegion || pShmNode->nRegion==0 );
-
-- /* get memory map allocation granularity */
-- memset(&winSysInfo, 0, sizeof(SYSTEM_INFO));
-+ if( pShmNode->nRegion<=iRegion ){
-+ struct ShmRegion *apNew; /* New aRegion[] array */
-+ int nByte = (iRegion+1)*szRegion; /* Minimum required file size */
-+ sqlite3_int64 sz; /* Current size of wal-index file */
-+
-+ pShmNode->szRegion = szRegion;
-+
-+ /* The requested region is not mapped into this processes address space.
-+ ** Check to see if it has been allocated (i.e. if the wal-index file is
-+ ** large enough to contain the requested region).
-+ */
-+ rc = winFileSize((sqlite3_file *)&pShmNode->hFile, &sz);
-+ if( rc!=SQLITE_OK ){
-+ rc = winLogError(SQLITE_IOERR_SHMSIZE, osGetLastError(),
-+ "winShmMap1", pDbFd->zPath);
-+ goto shmpage_out;
-+ }
-+
-+ if( sz<nByte ){
-+ /* The requested memory region does not exist. If isWrite is set to
-+ ** zero, exit early. *pp will be set to NULL and SQLITE_OK returned.
-+ **
-+ ** Alternatively, if isWrite is non-zero, use ftruncate() to allocate
-+ ** the requested memory region.
-+ */
-+ if( !isWrite ) goto shmpage_out;
-+ rc = winTruncate((sqlite3_file *)&pShmNode->hFile, nByte);
-+ if( rc!=SQLITE_OK ){
-+ rc = winLogError(SQLITE_IOERR_SHMSIZE, osGetLastError(),
-+ "winShmMap2", pDbFd->zPath);
-+ goto shmpage_out;
-+ }
-+ }
-+
-+ /* Map the requested memory region into this processes address space. */
-+ apNew = (struct ShmRegion *)sqlite3_realloc(
-+ pShmNode->aRegion, (iRegion+1)*sizeof(apNew[0])
-+ );
-+ if( !apNew ){
-+ rc = SQLITE_IOERR_NOMEM;
-+ goto shmpage_out;
-+ }
-+ pShmNode->aRegion = apNew;
-+
-+ while( pShmNode->nRegion<=iRegion ){
-+ HANDLE hMap = NULL; /* file-mapping handle */
-+ void *pMap = 0; /* Mapped memory region */
-+
- #if SQLITE_OS_WINRT
-- osGetNativeSystemInfo(&winSysInfo);
-+ hMap = osCreateFileMappingFromApp(pShmNode->hFile.h,
-+ NULL, PAGE_READWRITE, nByte, NULL
-+ );
-+#elif defined(SQLITE_WIN32_HAS_WIDE)
-+ hMap = osCreateFileMappingW(pShmNode->hFile.h,
-+ NULL, PAGE_READWRITE, 0, nByte, NULL
-+ );
-+#elif defined(SQLITE_WIN32_HAS_ANSI)
-+ hMap = osCreateFileMappingA(pShmNode->hFile.h,
-+ NULL, PAGE_READWRITE, 0, nByte, NULL
-+ );
-+#endif
-+ OSTRACE(("SHM-MAP-CREATE pid=%lu, region=%d, size=%d, rc=%s\n",
-+ osGetCurrentProcessId(), pShmNode->nRegion, nByte,
-+ hMap ? "ok" : "failed"));
-+ if( hMap ){
-+ int iOffset = pShmNode->nRegion*szRegion;
-+ int iOffsetShift = iOffset % winSysInfo.dwAllocationGranularity;
-+#if SQLITE_OS_WINRT
-+ pMap = osMapViewOfFileFromApp(hMap, FILE_MAP_WRITE | FILE_MAP_READ,
-+ iOffset - iOffsetShift, szRegion + iOffsetShift
-+ );
- #else
-- osGetSystemInfo(&winSysInfo);
-+ pMap = osMapViewOfFile(hMap, FILE_MAP_WRITE | FILE_MAP_READ,
-+ 0, iOffset - iOffsetShift, szRegion + iOffsetShift
-+ );
- #endif
-- assert( winSysInfo.dwAllocationGranularity>0 );
-- assert( winSysInfo.dwPageSize>0 );
-+ OSTRACE(("SHM-MAP-MAP pid=%lu, region=%d, offset=%d, size=%d, rc=%s\n",
-+ osGetCurrentProcessId(), pShmNode->nRegion, iOffset,
-+ szRegion, pMap ? "ok" : "failed"));
-+ }
-+ if( !pMap ){
-+ pShmNode->lastErrno = osGetLastError();
-+ rc = winLogError(SQLITE_IOERR_SHMMAP, pShmNode->lastErrno,
-+ "winShmMap3", pDbFd->zPath);
-+ if( hMap ) osCloseHandle(hMap);
-+ goto shmpage_out;
-+ }
-
-- sqlite3_vfs_register(&winVfs, 1);
-- return SQLITE_OK;
--}
-+ pShmNode->aRegion[pShmNode->nRegion].pMap = pMap;
-+ pShmNode->aRegion[pShmNode->nRegion].hMap = hMap;
-+ pShmNode->nRegion++;
-+ }
-+ }
-
--SQLITE_API int sqlite3_os_end(void){
--#if SQLITE_OS_WINRT
-- if( sleepObj!=NULL ){
-- osCloseHandle(sleepObj);
-- sleepObj = NULL;
-+shmpage_out:
-+ if( pShmNode->nRegion>iRegion ){
-+ int iOffset = iRegion*szRegion;
-+ int iOffsetShift = iOffset % winSysInfo.dwAllocationGranularity;
-+ char *p = (char *)pShmNode->aRegion[iRegion].pMap;
-+ *pp = (void *)&p[iOffsetShift];
-+ }else{
-+ *pp = 0;
- }
--#endif
-- return SQLITE_OK;
-+ sqlite3_mutex_leave(pShmNode->mutex);
-+ return rc;
- }
-
--#endif /* SQLITE_OS_WIN */
-+#else
-+# define winShmMap 0
-+# define winShmLock 0
-+# define winShmBarrier 0
-+# define winShmUnmap 0
-+#endif /* #ifndef SQLITE_OMIT_WAL */
-
--/************** End of os_win.c **********************************************/
--/************** Begin file bitvec.c ******************************************/
- /*
--** 2008 February 16
--**
--** The author disclaims copyright to this source code. In place of
--** a legal notice, here is a blessing:
--**
--** May you do good and not evil.
--** May you find forgiveness for yourself and forgive others.
--** May you share freely, never taking more than you give.
--**
--*************************************************************************
--** This file implements an object that represents a fixed-length
--** bitmap. Bits are numbered starting with 1.
--**
--** A bitmap is used to record which pages of a database file have been
--** journalled during a transaction, or which pages have the "dont-write"
--** property. Usually only a few pages are meet either condition.
--** So the bitmap is usually sparse and has low cardinality.
--** But sometimes (for example when during a DROP of a large table) most
--** or all of the pages in a database can get journalled. In those cases,
--** the bitmap becomes dense with high cardinality. The algorithm needs
--** to handle both cases well.
--**
--** The size of the bitmap is fixed when the object is created.
--**
--** All bits are clear when the bitmap is created. Individual bits
--** may be set or cleared one at a time.
--**
--** Test operations are about 100 times more common that set operations.
--** Clear operations are exceedingly rare. There are usually between
--** 5 and 500 set operations per Bitvec object, though the number of sets can
--** sometimes grow into tens of thousands or larger. The size of the
--** Bitvec object is the number of pages in the database file at the
--** start of a transaction, and is thus usually less than a few thousand,
--** but can be as large as 2 billion for a really big database.
-+** Cleans up the mapped region of the specified file, if any.
- */
--
--/* Size of the Bitvec structure in bytes. */
--#define BITVEC_SZ 512
--
--/* Round the union size down to the nearest pointer boundary, since that's how
--** it will be aligned within the Bitvec struct. */
--#define BITVEC_USIZE (((BITVEC_SZ-(3*sizeof(u32)))/sizeof(Bitvec*))*sizeof(Bitvec*))
--
--/* Type of the array "element" for the bitmap representation.
--** Should be a power of 2, and ideally, evenly divide into BITVEC_USIZE.
--** Setting this to the "natural word" size of your CPU may improve
--** performance. */
--#define BITVEC_TELEM u8
--/* Size, in bits, of the bitmap element. */
--#define BITVEC_SZELEM 8
--/* Number of elements in a bitmap array. */
--#define BITVEC_NELEM (BITVEC_USIZE/sizeof(BITVEC_TELEM))
--/* Number of bits in the bitmap array. */
--#define BITVEC_NBIT (BITVEC_NELEM*BITVEC_SZELEM)
--
--/* Number of u32 values in hash table. */
--#define BITVEC_NINT (BITVEC_USIZE/sizeof(u32))
--/* Maximum number of entries in hash table before
--** sub-dividing and re-hashing. */
--#define BITVEC_MXHASH (BITVEC_NINT/2)
--/* Hashing function for the aHash representation.
--** Empirical testing showed that the *37 multiplier
--** (an arbitrary prime)in the hash function provided
--** no fewer collisions than the no-op *1. */
--#define BITVEC_HASH(X) (((X)*1)%BITVEC_NINT)
--
--#define BITVEC_NPTR (BITVEC_USIZE/sizeof(Bitvec *))
--
-+#if SQLITE_MAX_MMAP_SIZE>0
-+static int winUnmapfile(winFile *pFile){
-+ assert( pFile!=0 );
-+ OSTRACE(("UNMAP-FILE pid=%lu, pFile=%p, hMap=%p, pMapRegion=%p, "
-+ "mmapSize=%lld, mmapSizeActual=%lld, mmapSizeMax=%lld\n",
-+ osGetCurrentProcessId(), pFile, pFile->hMap, pFile->pMapRegion,
-+ pFile->mmapSize, pFile->mmapSizeActual, pFile->mmapSizeMax));
-+ if( pFile->pMapRegion ){
-+ if( !osUnmapViewOfFile(pFile->pMapRegion) ){
-+ pFile->lastErrno = osGetLastError();
-+ OSTRACE(("UNMAP-FILE pid=%lu, pFile=%p, pMapRegion=%p, "
-+ "rc=SQLITE_IOERR_MMAP\n", osGetCurrentProcessId(), pFile,
-+ pFile->pMapRegion));
-+ return winLogError(SQLITE_IOERR_MMAP, pFile->lastErrno,
-+ "winUnmap1", pFile->zPath);
-+ }
-+ pFile->pMapRegion = 0;
-+ pFile->mmapSize = 0;
-+ pFile->mmapSizeActual = 0;
-+ }
-+ if( pFile->hMap!=NULL ){
-+ if( !osCloseHandle(pFile->hMap) ){
-+ pFile->lastErrno = osGetLastError();
-+ OSTRACE(("UNMAP-FILE pid=%lu, pFile=%p, hMap=%p, rc=SQLITE_IOERR_MMAP\n",
-+ osGetCurrentProcessId(), pFile, pFile->hMap));
-+ return winLogError(SQLITE_IOERR_MMAP, pFile->lastErrno,
-+ "winUnmap2", pFile->zPath);
-+ }
-+ pFile->hMap = NULL;
-+ }
-+ OSTRACE(("UNMAP-FILE pid=%lu, pFile=%p, rc=SQLITE_OK\n",
-+ osGetCurrentProcessId(), pFile));
-+ return SQLITE_OK;
-+}
-
- /*
--** A bitmap is an instance of the following structure.
--**
--** This bitmap records the existence of zero or more bits
--** with values between 1 and iSize, inclusive.
--**
--** There are three possible representations of the bitmap.
--** If iSize<=BITVEC_NBIT, then Bitvec.u.aBitmap[] is a straight
--** bitmap. The least significant bit is bit 1.
-+** Memory map or remap the file opened by file-descriptor pFd (if the file
-+** is already mapped, the existing mapping is replaced by the new). Or, if
-+** there already exists a mapping for this file, and there are still
-+** outstanding xFetch() references to it, this function is a no-op.
- **
--** If iSize>BITVEC_NBIT and iDivisor==0 then Bitvec.u.aHash[] is
--** a hash table that will hold up to BITVEC_MXHASH distinct values.
-+** If parameter nByte is non-negative, then it is the requested size of
-+** the mapping to create. Otherwise, if nByte is less than zero, then the
-+** requested size is the size of the file on disk. The actual size of the
-+** created mapping is either the requested size or the value configured
-+** using SQLITE_FCNTL_MMAP_SIZE, whichever is smaller.
- **
--** Otherwise, the value i is redirected into one of BITVEC_NPTR
--** sub-bitmaps pointed to by Bitvec.u.apSub[]. Each subbitmap
--** handles up to iDivisor separate values of i. apSub[0] holds
--** values between 1 and iDivisor. apSub[1] holds values between
--** iDivisor+1 and 2*iDivisor. apSub[N] holds values between
--** N*iDivisor+1 and (N+1)*iDivisor. Each subbitmap is normalized
--** to hold deal with values between 1 and iDivisor.
-+** SQLITE_OK is returned if no error occurs (even if the mapping is not
-+** recreated as a result of outstanding references) or an SQLite error
-+** code otherwise.
- */
--struct Bitvec {
-- u32 iSize; /* Maximum bit index. Max iSize is 4,294,967,296. */
-- u32 nSet; /* Number of bits that are set - only valid for aHash
-- ** element. Max is BITVEC_NINT. For BITVEC_SZ of 512,
-- ** this would be 125. */
-- u32 iDivisor; /* Number of bits handled by each apSub[] entry. */
-- /* Should >=0 for apSub element. */
-- /* Max iDivisor is max(u32) / BITVEC_NPTR + 1. */
-- /* For a BITVEC_SZ of 512, this would be 34,359,739. */
-- union {
-- BITVEC_TELEM aBitmap[BITVEC_NELEM]; /* Bitmap representation */
-- u32 aHash[BITVEC_NINT]; /* Hash table representation */
-- Bitvec *apSub[BITVEC_NPTR]; /* Recursive representation */
-- } u;
--};
-+static int winMapfile(winFile *pFd, sqlite3_int64 nByte){
-+ sqlite3_int64 nMap = nByte;
-+ int rc;
-
--/*
--** Create a new bitmap object able to handle bits between 0 and iSize,
--** inclusive. Return a pointer to the new object. Return NULL if
--** malloc fails.
--*/
--SQLITE_PRIVATE Bitvec *sqlite3BitvecCreate(u32 iSize){
-- Bitvec *p;
-- assert( sizeof(*p)==BITVEC_SZ );
-- p = sqlite3MallocZero( sizeof(*p) );
-- if( p ){
-- p->iSize = iSize;
-- }
-- return p;
--}
-+ assert( nMap>=0 || pFd->nFetchOut==0 );
-+ OSTRACE(("MAP-FILE pid=%lu, pFile=%p, size=%lld\n",
-+ osGetCurrentProcessId(), pFd, nByte));
-
--/*
--** Check to see if the i-th bit is set. Return true or false.
--** If p is NULL (if the bitmap has not been created) or if
--** i is out of range, then return false.
--*/
--SQLITE_PRIVATE int sqlite3BitvecTest(Bitvec *p, u32 i){
-- if( p==0 ) return 0;
-- if( i>p->iSize || i==0 ) return 0;
-- i--;
-- while( p->iDivisor ){
-- u32 bin = i/p->iDivisor;
-- i = i%p->iDivisor;
-- p = p->u.apSub[bin];
-- if (!p) {
-- return 0;
-+ if( pFd->nFetchOut>0 ) return SQLITE_OK;
-+
-+ if( nMap<0 ){
-+ rc = winFileSize((sqlite3_file*)pFd, &nMap);
-+ if( rc ){
-+ OSTRACE(("MAP-FILE pid=%lu, pFile=%p, rc=SQLITE_IOERR_FSTAT\n",
-+ osGetCurrentProcessId(), pFd));
-+ return SQLITE_IOERR_FSTAT;
- }
- }
-- if( p->iSize<=BITVEC_NBIT ){
-- return (p->u.aBitmap[i/BITVEC_SZELEM] & (1<<(i&(BITVEC_SZELEM-1))))!=0;
-- } else{
-- u32 h = BITVEC_HASH(i++);
-- while( p->u.aHash[h] ){
-- if( p->u.aHash[h]==i ) return 1;
-- h = (h+1) % BITVEC_NINT;
-+ if( nMap>pFd->mmapSizeMax ){
-+ nMap = pFd->mmapSizeMax;
-+ }
-+ nMap &= ~(sqlite3_int64)(winSysInfo.dwPageSize - 1);
-+
-+ if( nMap==0 && pFd->mmapSize>0 ){
-+ winUnmapfile(pFd);
-+ }
-+ if( nMap!=pFd->mmapSize ){
-+ void *pNew = 0;
-+ DWORD protect = PAGE_READONLY;
-+ DWORD flags = FILE_MAP_READ;
-+
-+ winUnmapfile(pFd);
-+ if( (pFd->ctrlFlags & WINFILE_RDONLY)==0 ){
-+ protect = PAGE_READWRITE;
-+ flags |= FILE_MAP_WRITE;
- }
-- return 0;
-+#if SQLITE_OS_WINRT
-+ pFd->hMap = osCreateFileMappingFromApp(pFd->h, NULL, protect, nMap, NULL);
-+#elif defined(SQLITE_WIN32_HAS_WIDE)
-+ pFd->hMap = osCreateFileMappingW(pFd->h, NULL, protect,
-+ (DWORD)((nMap>>32) & 0xffffffff),
-+ (DWORD)(nMap & 0xffffffff), NULL);
-+#elif defined(SQLITE_WIN32_HAS_ANSI)
-+ pFd->hMap = osCreateFileMappingA(pFd->h, NULL, protect,
-+ (DWORD)((nMap>>32) & 0xffffffff),
-+ (DWORD)(nMap & 0xffffffff), NULL);
-+#endif
-+ if( pFd->hMap==NULL ){
-+ pFd->lastErrno = osGetLastError();
-+ rc = winLogError(SQLITE_IOERR_MMAP, pFd->lastErrno,
-+ "winMapfile", pFd->zPath);
-+ /* Log the error, but continue normal operation using xRead/xWrite */
-+ OSTRACE(("MAP-FILE-CREATE pid=%lu, pFile=%p, rc=SQLITE_IOERR_MMAP\n",
-+ osGetCurrentProcessId(), pFd));
-+ return SQLITE_OK;
-+ }
-+ assert( (nMap % winSysInfo.dwPageSize)==0 );
-+#if SQLITE_OS_WINRT
-+ pNew = osMapViewOfFileFromApp(pFd->hMap, flags, 0, nMap);
-+#else
-+ assert( sizeof(SIZE_T)==sizeof(sqlite3_int64) || nMap<=0xffffffff );
-+ pNew = osMapViewOfFile(pFd->hMap, flags, 0, 0, (SIZE_T)nMap);
-+#endif
-+ if( pNew==NULL ){
-+ osCloseHandle(pFd->hMap);
-+ pFd->hMap = NULL;
-+ pFd->lastErrno = osGetLastError();
-+ winLogError(SQLITE_IOERR_MMAP, pFd->lastErrno,
-+ "winMapfile", pFd->zPath);
-+ OSTRACE(("MAP-FILE-MAP pid=%lu, pFile=%p, rc=SQLITE_IOERR_MMAP\n",
-+ osGetCurrentProcessId(), pFd));
-+ return SQLITE_OK;
-+ }
-+ pFd->pMapRegion = pNew;
-+ pFd->mmapSize = nMap;
-+ pFd->mmapSizeActual = nMap;
- }
-+
-+ OSTRACE(("MAP-FILE pid=%lu, pFile=%p, rc=SQLITE_OK\n",
-+ osGetCurrentProcessId(), pFd));
-+ return SQLITE_OK;
- }
-+#endif /* SQLITE_MAX_MMAP_SIZE>0 */
-
- /*
--** Set the i-th bit. Return 0 on success and an error code if
--** anything goes wrong.
-+** If possible, return a pointer to a mapping of file fd starting at offset
-+** iOff. The mapping must be valid for at least nAmt bytes.
- **
--** This routine might cause sub-bitmaps to be allocated. Failing
--** to get the memory needed to hold the sub-bitmap is the only
--** that can go wrong with an insert, assuming p and i are valid.
-+** If such a pointer can be obtained, store it in *pp and return SQLITE_OK.
-+** Or, if one cannot but no error occurs, set *pp to 0 and return SQLITE_OK.
-+** Finally, if an error does occur, return an SQLite error code. The final
-+** value of *pp is undefined in this case.
- **
--** The calling function must ensure that p is a valid Bitvec object
--** and that the value for "i" is within range of the Bitvec object.
--** Otherwise the behavior is undefined.
-+** If this function does return a pointer, the caller must eventually
-+** release the reference by calling winUnfetch().
- */
--SQLITE_PRIVATE int sqlite3BitvecSet(Bitvec *p, u32 i){
-- u32 h;
-- if( p==0 ) return SQLITE_OK;
-- assert( i>0 );
-- assert( i<=p->iSize );
-- i--;
-- while((p->iSize > BITVEC_NBIT) && p->iDivisor) {
-- u32 bin = i/p->iDivisor;
-- i = i%p->iDivisor;
-- if( p->u.apSub[bin]==0 ){
-- p->u.apSub[bin] = sqlite3BitvecCreate( p->iDivisor );
-- if( p->u.apSub[bin]==0 ) return SQLITE_NOMEM;
-- }
-- p = p->u.apSub[bin];
-- }
-- if( p->iSize<=BITVEC_NBIT ){
-- p->u.aBitmap[i/BITVEC_SZELEM] |= 1 << (i&(BITVEC_SZELEM-1));
-- return SQLITE_OK;
-- }
-- h = BITVEC_HASH(i++);
-- /* if there wasn't a hash collision, and this doesn't */
-- /* completely fill the hash, then just add it without */
-- /* worring about sub-dividing and re-hashing. */
-- if( !p->u.aHash[h] ){
-- if (p->nSet<(BITVEC_NINT-1)) {
-- goto bitvec_set_end;
-- } else {
-- goto bitvec_set_rehash;
-- }
-- }
-- /* there was a collision, check to see if it's already */
-- /* in hash, if not, try to find a spot for it */
-- do {
-- if( p->u.aHash[h]==i ) return SQLITE_OK;
-- h++;
-- if( h>=BITVEC_NINT ) h = 0;
-- } while( p->u.aHash[h] );
-- /* we didn't find it in the hash. h points to the first */
-- /* available free spot. check to see if this is going to */
-- /* make our hash too "full". */
--bitvec_set_rehash:
-- if( p->nSet>=BITVEC_MXHASH ){
-- unsigned int j;
-- int rc;
-- u32 *aiValues = sqlite3StackAllocRaw(0, sizeof(p->u.aHash));
-- if( aiValues==0 ){
-- return SQLITE_NOMEM;
-- }else{
-- memcpy(aiValues, p->u.aHash, sizeof(p->u.aHash));
-- memset(p->u.apSub, 0, sizeof(p->u.apSub));
-- p->iDivisor = (p->iSize + BITVEC_NPTR - 1)/BITVEC_NPTR;
-- rc = sqlite3BitvecSet(p, i);
-- for(j=0; j<BITVEC_NINT; j++){
-- if( aiValues[j] ) rc |= sqlite3BitvecSet(p, aiValues[j]);
-+static int winFetch(sqlite3_file *fd, i64 iOff, int nAmt, void **pp){
-+#if SQLITE_MAX_MMAP_SIZE>0
-+ winFile *pFd = (winFile*)fd; /* The underlying database file */
-+#endif
-+ *pp = 0;
-+
-+ OSTRACE(("FETCH pid=%lu, pFile=%p, offset=%lld, amount=%d, pp=%p\n",
-+ osGetCurrentProcessId(), fd, iOff, nAmt, pp));
-+
-+#if SQLITE_MAX_MMAP_SIZE>0
-+ if( pFd->mmapSizeMax>0 ){
-+ if( pFd->pMapRegion==0 ){
-+ int rc = winMapfile(pFd, -1);
-+ if( rc!=SQLITE_OK ){
-+ OSTRACE(("FETCH pid=%lu, pFile=%p, rc=%s\n",
-+ osGetCurrentProcessId(), pFd, sqlite3ErrName(rc)));
-+ return rc;
- }
-- sqlite3StackFree(0, aiValues);
-- return rc;
-+ }
-+ if( pFd->mmapSize >= iOff+nAmt ){
-+ *pp = &((u8 *)pFd->pMapRegion)[iOff];
-+ pFd->nFetchOut++;
- }
- }
--bitvec_set_end:
-- p->nSet++;
-- p->u.aHash[h] = i;
-+#endif
-+
-+ OSTRACE(("FETCH pid=%lu, pFile=%p, pp=%p, *pp=%p, rc=SQLITE_OK\n",
-+ osGetCurrentProcessId(), fd, pp, *pp));
- return SQLITE_OK;
- }
-
- /*
--** Clear the i-th bit.
-+** If the third argument is non-NULL, then this function releases a
-+** reference obtained by an earlier call to winFetch(). The second
-+** argument passed to this function must be the same as the corresponding
-+** argument that was passed to the winFetch() invocation.
- **
--** pBuf must be a pointer to at least BITVEC_SZ bytes of temporary storage
--** that BitvecClear can use to rebuilt its hash table.
-+** Or, if the third argument is NULL, then this function is being called
-+** to inform the VFS layer that, according to POSIX, any existing mapping
-+** may now be invalid and should be unmapped.
- */
--SQLITE_PRIVATE void sqlite3BitvecClear(Bitvec *p, u32 i, void *pBuf){
-- if( p==0 ) return;
-- assert( i>0 );
-- i--;
-- while( p->iDivisor ){
-- u32 bin = i/p->iDivisor;
-- i = i%p->iDivisor;
-- p = p->u.apSub[bin];
-- if (!p) {
-- return;
-- }
-- }
-- if( p->iSize<=BITVEC_NBIT ){
-- p->u.aBitmap[i/BITVEC_SZELEM] &= ~(1 << (i&(BITVEC_SZELEM-1)));
-+static int winUnfetch(sqlite3_file *fd, i64 iOff, void *p){
-+#if SQLITE_MAX_MMAP_SIZE>0
-+ winFile *pFd = (winFile*)fd; /* The underlying database file */
-+
-+ /* If p==0 (unmap the entire file) then there must be no outstanding
-+ ** xFetch references. Or, if p!=0 (meaning it is an xFetch reference),
-+ ** then there must be at least one outstanding. */
-+ assert( (p==0)==(pFd->nFetchOut==0) );
-+
-+ /* If p!=0, it must match the iOff value. */
-+ assert( p==0 || p==&((u8 *)pFd->pMapRegion)[iOff] );
-+
-+ OSTRACE(("UNFETCH pid=%lu, pFile=%p, offset=%lld, p=%p\n",
-+ osGetCurrentProcessId(), pFd, iOff, p));
-+
-+ if( p ){
-+ pFd->nFetchOut--;
- }else{
-- unsigned int j;
-- u32 *aiValues = pBuf;
-- memcpy(aiValues, p->u.aHash, sizeof(p->u.aHash));
-- memset(p->u.aHash, 0, sizeof(p->u.aHash));
-- p->nSet = 0;
-- for(j=0; j<BITVEC_NINT; j++){
-- if( aiValues[j] && aiValues[j]!=(i+1) ){
-- u32 h = BITVEC_HASH(aiValues[j]-1);
-- p->nSet++;
-- while( p->u.aHash[h] ){
-- h++;
-- if( h>=BITVEC_NINT ) h = 0;
-- }
-- p->u.aHash[h] = aiValues[j];
-- }
-- }
-+ /* FIXME: If Windows truly always prevents truncating or deleting a
-+ ** file while a mapping is held, then the following winUnmapfile() call
-+ ** is unnecessary can can be omitted - potentially improving
-+ ** performance. */
-+ winUnmapfile(pFd);
- }
-+
-+ assert( pFd->nFetchOut>=0 );
-+#endif
-+
-+ OSTRACE(("UNFETCH pid=%lu, pFile=%p, rc=SQLITE_OK\n",
-+ osGetCurrentProcessId(), fd));
-+ return SQLITE_OK;
- }
-
- /*
--** Destroy a bitmap object. Reclaim all memory used.
--*/
--SQLITE_PRIVATE void sqlite3BitvecDestroy(Bitvec *p){
-- if( p==0 ) return;
-- if( p->iDivisor ){
-- unsigned int i;
-- for(i=0; i<BITVEC_NPTR; i++){
-- sqlite3BitvecDestroy(p->u.apSub[i]);
-- }
-- }
-- sqlite3_free(p);
--}
-+** Here ends the implementation of all sqlite3_file methods.
-+**
-+********************** End sqlite3_file Methods *******************************
-+******************************************************************************/
-
- /*
--** Return the value of the iSize parameter specified when Bitvec *p
--** was created.
-+** This vector defines all the methods that can operate on an
-+** sqlite3_file for win32.
-+*/
-+static const sqlite3_io_methods winIoMethod = {
-+ 3, /* iVersion */
-+ winClose, /* xClose */
-+ winRead, /* xRead */
-+ winWrite, /* xWrite */
-+ winTruncate, /* xTruncate */
-+ winSync, /* xSync */
-+ winFileSize, /* xFileSize */
-+ winLock, /* xLock */
-+ winUnlock, /* xUnlock */
-+ winCheckReservedLock, /* xCheckReservedLock */
-+ winFileControl, /* xFileControl */
-+ winSectorSize, /* xSectorSize */
-+ winDeviceCharacteristics, /* xDeviceCharacteristics */
-+ winShmMap, /* xShmMap */
-+ winShmLock, /* xShmLock */
-+ winShmBarrier, /* xShmBarrier */
-+ winShmUnmap, /* xShmUnmap */
-+ winFetch, /* xFetch */
-+ winUnfetch /* xUnfetch */
-+};
-+
-+/****************************************************************************
-+**************************** sqlite3_vfs methods ****************************
-+**
-+** This division contains the implementation of methods on the
-+** sqlite3_vfs object.
- */
--SQLITE_PRIVATE u32 sqlite3BitvecSize(Bitvec *p){
-- return p->iSize;
--}
-
--#ifndef SQLITE_OMIT_BUILTIN_TEST
- /*
--** Let V[] be an array of unsigned characters sufficient to hold
--** up to N bits. Let I be an integer between 0 and N. 0<=I<N.
--** Then the following macros can be used to set, clear, or test
--** individual bits within V.
-+** Convert a UTF-8 filename into whatever form the underlying
-+** operating system wants filenames in. Space to hold the result
-+** is obtained from malloc and must be freed by the calling
-+** function.
- */
--#define SETBIT(V,I) V[I>>3] |= (1<<(I&7))
--#define CLEARBIT(V,I) V[I>>3] &= ~(1<<(I&7))
--#define TESTBIT(V,I) (V[I>>3]&(1<<(I&7)))!=0
-+static void *convertUtf8Filename(const char *zFilename){
-+ void *zConverted = 0;
-+ if( isNT() ){
-+ zConverted = utf8ToUnicode(zFilename);
-+ }
-+#ifdef SQLITE_WIN32_HAS_ANSI
-+ else{
-+ zConverted = sqlite3_win32_utf8_to_mbcs(zFilename);
-+ }
-+#endif
-+ /* caller will handle out of memory */
-+ return zConverted;
-+}
-
- /*
--** This routine runs an extensive test of the Bitvec code.
--**
--** The input is an array of integers that acts as a program
--** to test the Bitvec. The integers are opcodes followed
--** by 0, 1, or 3 operands, depending on the opcode. Another
--** opcode follows immediately after the last operand.
--**
--** There are 6 opcodes numbered from 0 through 5. 0 is the
--** "halt" opcode and causes the test to end.
--**
--** 0 Halt and return the number of errors
--** 1 N S X Set N bits beginning with S and incrementing by X
--** 2 N S X Clear N bits beginning with S and incrementing by X
--** 3 N Set N randomly chosen bits
--** 4 N Clear N randomly chosen bits
--** 5 N S X Set N bits from S increment X in array only, not in bitvec
--**
--** The opcodes 1 through 4 perform set and clear operations are performed
--** on both a Bitvec object and on a linear array of bits obtained from malloc.
--** Opcode 5 works on the linear array only, not on the Bitvec.
--** Opcode 5 is used to deliberately induce a fault in order to
--** confirm that error detection works.
--**
--** At the conclusion of the test the linear array is compared
--** against the Bitvec object. If there are any differences,
--** an error is returned. If they are the same, zero is returned.
--**
--** If a memory allocation error occurs, return -1.
-+** Create a temporary file name in zBuf. zBuf must be big enough to
-+** hold at pVfs->mxPathname characters.
- */
--SQLITE_PRIVATE int sqlite3BitvecBuiltinTest(int sz, int *aOp){
-- Bitvec *pBitvec = 0;
-- unsigned char *pV = 0;
-- int rc = -1;
-- int i, nx, pc, op;
-- void *pTmpSpace;
-+static int getTempname(int nBuf, char *zBuf){
-+ static char zChars[] =
-+ "abcdefghijklmnopqrstuvwxyz"
-+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
-+ "0123456789";
-+ size_t i, j;
-+ int nTempPath;
-+ char zTempPath[MAX_PATH+2];
-
-- /* Allocate the Bitvec to be tested and a linear array of
-- ** bits to act as the reference */
-- pBitvec = sqlite3BitvecCreate( sz );
-- pV = sqlite3MallocZero( (sz+7)/8 + 1 );
-- pTmpSpace = sqlite3_malloc(BITVEC_SZ);
-- if( pBitvec==0 || pV==0 || pTmpSpace==0 ) goto bitvec_end;
-+ /* It's odd to simulate an io-error here, but really this is just
-+ ** using the io-error infrastructure to test that SQLite handles this
-+ ** function failing.
-+ */
-+ SimulateIOError( return SQLITE_IOERR );
-
-- /* NULL pBitvec tests */
-- sqlite3BitvecSet(0, 1);
-- sqlite3BitvecClear(0, 1, pTmpSpace);
-+ memset(zTempPath, 0, MAX_PATH+2);
-
-- /* Run the program */
-- pc = 0;
-- while( (op = aOp[pc])!=0 ){
-- switch( op ){
-- case 1:
-- case 2:
-- case 5: {
-- nx = 4;
-- i = aOp[pc+2] - 1;
-- aOp[pc+2] += aOp[pc+3];
-- break;
-- }
-- case 3:
-- case 4:
-- default: {
-- nx = 2;
-- sqlite3_randomness(sizeof(i), &i);
-- break;
-- }
-+ if( sqlite3_temp_directory ){
-+ sqlite3_snprintf(MAX_PATH-30, zTempPath, "%s", sqlite3_temp_directory);
-+ }
-+#if !SQLITE_OS_WINRT
-+ else if( isNT() ){
-+ char *zMulti;
-+ WCHAR zWidePath[MAX_PATH];
-+ osGetTempPathW(MAX_PATH-30, zWidePath);
-+ zMulti = unicodeToUtf8(zWidePath);
-+ if( zMulti ){
-+ sqlite3_snprintf(MAX_PATH-30, zTempPath, "%s", zMulti);
-+ sqlite3_free(zMulti);
-+ }else{
-+ OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n"));
-+ return SQLITE_IOERR_NOMEM;
- }
-- if( (--aOp[pc+1]) > 0 ) nx = 0;
-- pc += nx;
-- i = (i & 0x7fffffff)%sz;
-- if( (op & 1)!=0 ){
-- SETBIT(pV, (i+1));
-- if( op!=5 ){
-- if( sqlite3BitvecSet(pBitvec, i+1) ) goto bitvec_end;
-- }
-+ }
-+#ifdef SQLITE_WIN32_HAS_ANSI
-+ else{
-+ char *zUtf8;
-+ char zMbcsPath[MAX_PATH];
-+ osGetTempPathA(MAX_PATH-30, zMbcsPath);
-+ zUtf8 = sqlite3_win32_mbcs_to_utf8(zMbcsPath);
-+ if( zUtf8 ){
-+ sqlite3_snprintf(MAX_PATH-30, zTempPath, "%s", zUtf8);
-+ sqlite3_free(zUtf8);
- }else{
-- CLEARBIT(pV, (i+1));
-- sqlite3BitvecClear(pBitvec, i+1, pTmpSpace);
-+ OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n"));
-+ return SQLITE_IOERR_NOMEM;
- }
- }
-+#endif
-+#endif
-
-- /* Test to make sure the linear array exactly matches the
-- ** Bitvec object. Start with the assumption that they do
-- ** match (rc==0). Change rc to non-zero if a discrepancy
-- ** is found.
-+ /* Check that the output buffer is large enough for the temporary file
-+ ** name. If it is not, return SQLITE_ERROR.
- */
-- rc = sqlite3BitvecTest(0,0) + sqlite3BitvecTest(pBitvec, sz+1)
-- + sqlite3BitvecTest(pBitvec, 0)
-- + (sqlite3BitvecSize(pBitvec) - sz);
-- for(i=1; i<=sz; i++){
-- if( (TESTBIT(pV,i))!=sqlite3BitvecTest(pBitvec,i) ){
-- rc = i;
-- break;
-- }
-+ nTempPath = sqlite3Strlen30(zTempPath);
-+
-+ if( (nTempPath + sqlite3Strlen30(SQLITE_TEMP_FILE_PREFIX) + 18) >= nBuf ){
-+ OSTRACE(("TEMP-FILENAME rc=SQLITE_ERROR\n"));
-+ return SQLITE_ERROR;
- }
-
-- /* Free allocated structure */
--bitvec_end:
-- sqlite3_free(pTmpSpace);
-- sqlite3_free(pV);
-- sqlite3BitvecDestroy(pBitvec);
-- return rc;
-+ for(i=nTempPath; i>0 && zTempPath[i-1]=='\\'; i--){}
-+ zTempPath[i] = 0;
-+
-+ sqlite3_snprintf(nBuf-18, zBuf, (nTempPath > 0) ?
-+ "%s\\"SQLITE_TEMP_FILE_PREFIX : SQLITE_TEMP_FILE_PREFIX,
-+ zTempPath);
-+ j = sqlite3Strlen30(zBuf);
-+ sqlite3_randomness(15, &zBuf[j]);
-+ for(i=0; i<15; i++, j++){
-+ zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ];
-+ }
-+ zBuf[j] = 0;
-+ zBuf[j+1] = 0;
-+
-+ OSTRACE(("TEMP-FILENAME name=%s, rc=SQLITE_OK\n", zBuf));
-+ return SQLITE_OK;
- }
--#endif /* SQLITE_OMIT_BUILTIN_TEST */
-
--/************** End of bitvec.c **********************************************/
--/************** Begin file pcache.c ******************************************/
- /*
--** 2008 August 05
--**
--** The author disclaims copyright to this source code. In place of
--** a legal notice, here is a blessing:
--**
--** May you do good and not evil.
--** May you find forgiveness for yourself and forgive others.
--** May you share freely, never taking more than you give.
--**
--*************************************************************************
--** This file implements that page cache.
-+** Return TRUE if the named file is really a directory. Return false if
-+** it is something other than a directory, or if there is any kind of memory
-+** allocation failure.
-+*/
-+static int winIsDir(const void *zConverted){
-+ DWORD attr;
-+ int rc = 0;
-+ DWORD lastErrno;
-+
-+ if( isNT() ){
-+ int cnt = 0;
-+ WIN32_FILE_ATTRIBUTE_DATA sAttrData;
-+ memset(&sAttrData, 0, sizeof(sAttrData));
-+ while( !(rc = osGetFileAttributesExW((LPCWSTR)zConverted,
-+ GetFileExInfoStandard,
-+ &sAttrData)) && retryIoerr(&cnt, &lastErrno) ){}
-+ if( !rc ){
-+ return 0; /* Invalid name? */
-+ }
-+ attr = sAttrData.dwFileAttributes;
-+#if SQLITE_OS_WINCE==0
-+ }else{
-+ attr = osGetFileAttributesA((char*)zConverted);
-+#endif
-+ }
-+ return (attr!=INVALID_FILE_ATTRIBUTES) && (attr&FILE_ATTRIBUTE_DIRECTORY);
-+}
-+
-+/*
-+** Open a file.
- */
-+static int winOpen(
-+ sqlite3_vfs *pVfs, /* Not used */
-+ const char *zName, /* Name of the file (UTF-8) */
-+ sqlite3_file *id, /* Write the SQLite file handle here */
-+ int flags, /* Open mode flags */
-+ int *pOutFlags /* Status return flags */
-+){
-+ HANDLE h;
-+ DWORD lastErrno;
-+ DWORD dwDesiredAccess;
-+ DWORD dwShareMode;
-+ DWORD dwCreationDisposition;
-+ DWORD dwFlagsAndAttributes = 0;
-+#if SQLITE_OS_WINCE
-+ int isTemp = 0;
-+#endif
-+ winFile *pFile = (winFile*)id;
-+ void *zConverted; /* Filename in OS encoding */
-+ const char *zUtf8Name = zName; /* Filename in UTF-8 encoding */
-+ int cnt = 0;
-+
-+ /* If argument zPath is a NULL pointer, this function is required to open
-+ ** a temporary file. Use this buffer to store the file name in.
-+ */
-+ char zTmpname[MAX_PATH+2]; /* Buffer used to create temp filename */
-+
-+ int rc = SQLITE_OK; /* Function Return Code */
-+#if !defined(NDEBUG) || SQLITE_OS_WINCE
-+ int eType = flags&0xFFFFFF00; /* Type of file to open */
-+#endif
-+
-+ int isExclusive = (flags & SQLITE_OPEN_EXCLUSIVE);
-+ int isDelete = (flags & SQLITE_OPEN_DELETEONCLOSE);
-+ int isCreate = (flags & SQLITE_OPEN_CREATE);
-+ int isReadonly = (flags & SQLITE_OPEN_READONLY);
-+ int isReadWrite = (flags & SQLITE_OPEN_READWRITE);
-+
-+#ifndef NDEBUG
-+ int isOpenJournal = (isCreate && (
-+ eType==SQLITE_OPEN_MASTER_JOURNAL
-+ || eType==SQLITE_OPEN_MAIN_JOURNAL
-+ || eType==SQLITE_OPEN_WAL
-+ ));
-+#endif
-+
-+ OSTRACE(("OPEN name=%s, pFile=%p, flags=%x, pOutFlags=%p\n",
-+ zUtf8Name, id, flags, pOutFlags));
-+
-+ /* Check the following statements are true:
-+ **
-+ ** (a) Exactly one of the READWRITE and READONLY flags must be set, and
-+ ** (b) if CREATE is set, then READWRITE must also be set, and
-+ ** (c) if EXCLUSIVE is set, then CREATE must also be set.
-+ ** (d) if DELETEONCLOSE is set, then CREATE must also be set.
-+ */
-+ assert((isReadonly==0 || isReadWrite==0) && (isReadWrite || isReadonly));
-+ assert(isCreate==0 || isReadWrite);
-+ assert(isExclusive==0 || isCreate);
-+ assert(isDelete==0 || isCreate);
-
--/*
--** A complete page cache is an instance of this structure.
--*/
--struct PCache {
-- PgHdr *pDirty, *pDirtyTail; /* List of dirty pages in LRU order */
-- PgHdr *pSynced; /* Last synced page in dirty page list */
-- int nRef; /* Number of referenced pages */
-- int szCache; /* Configured cache size */
-- int szPage; /* Size of every page in this cache */
-- int szExtra; /* Size of extra space for each page */
-- int bPurgeable; /* True if pages are on backing store */
-- int (*xStress)(void*,PgHdr*); /* Call to try make a page clean */
-- void *pStress; /* Argument to xStress */
-- sqlite3_pcache *pCache; /* Pluggable cache module */
-- PgHdr *pPage1; /* Reference to page 1 */
--};
-+ /* The main DB, main journal, WAL file and master journal are never
-+ ** automatically deleted. Nor are they ever temporary files. */
-+ assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MAIN_DB );
-+ assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MAIN_JOURNAL );
-+ assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MASTER_JOURNAL );
-+ assert( (!isDelete && zName) || eType!=SQLITE_OPEN_WAL );
-
--/*
--** Some of the assert() macros in this code are too expensive to run
--** even during normal debugging. Use them only rarely on long-running
--** tests. Enable the expensive asserts using the
--** -DSQLITE_ENABLE_EXPENSIVE_ASSERT=1 compile-time option.
--*/
--#ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT
--# define expensive_assert(X) assert(X)
--#else
--# define expensive_assert(X)
--#endif
-+ /* Assert that the upper layer has set one of the "file-type" flags. */
-+ assert( eType==SQLITE_OPEN_MAIN_DB || eType==SQLITE_OPEN_TEMP_DB
-+ || eType==SQLITE_OPEN_MAIN_JOURNAL || eType==SQLITE_OPEN_TEMP_JOURNAL
-+ || eType==SQLITE_OPEN_SUBJOURNAL || eType==SQLITE_OPEN_MASTER_JOURNAL
-+ || eType==SQLITE_OPEN_TRANSIENT_DB || eType==SQLITE_OPEN_WAL
-+ );
-
--/********************************** Linked List Management ********************/
-+ assert( pFile!=0 );
-+ memset(pFile, 0, sizeof(winFile));
-+ pFile->h = INVALID_HANDLE_VALUE;
-
--#if !defined(NDEBUG) && defined(SQLITE_ENABLE_EXPENSIVE_ASSERT)
--/*
--** Check that the pCache->pSynced variable is set correctly. If it
--** is not, either fail an assert or return zero. Otherwise, return
--** non-zero. This is only used in debugging builds, as follows:
--**
--** expensive_assert( pcacheCheckSynced(pCache) );
--*/
--static int pcacheCheckSynced(PCache *pCache){
-- PgHdr *p;
-- for(p=pCache->pDirtyTail; p!=pCache->pSynced; p=p->pDirtyPrev){
-- assert( p->nRef || (p->flags&PGHDR_NEED_SYNC) );
-+#if SQLITE_OS_WINRT
-+ if( !sqlite3_temp_directory ){
-+ sqlite3_log(SQLITE_ERROR,
-+ "sqlite3_temp_directory variable should be set for WinRT");
- }
-- return (p==0 || p->nRef || (p->flags&PGHDR_NEED_SYNC)==0);
--}
--#endif /* !NDEBUG && SQLITE_ENABLE_EXPENSIVE_ASSERT */
-+#endif
-
--/*
--** Remove page pPage from the list of dirty pages.
--*/
--static void pcacheRemoveFromDirtyList(PgHdr *pPage){
-- PCache *p = pPage->pCache;
-+ /* If the second argument to this function is NULL, generate a
-+ ** temporary file name to use
-+ */
-+ if( !zUtf8Name ){
-+ assert(isDelete && !isOpenJournal);
-+ memset(zTmpname, 0, MAX_PATH+2);
-+ rc = getTempname(MAX_PATH+2, zTmpname);
-+ if( rc!=SQLITE_OK ){
-+ OSTRACE(("OPEN name=%s, rc=%s", zUtf8Name, sqlite3ErrName(rc)));
-+ return rc;
-+ }
-+ zUtf8Name = zTmpname;
-+ }
-
-- assert( pPage->pDirtyNext || pPage==p->pDirtyTail );
-- assert( pPage->pDirtyPrev || pPage==p->pDirty );
-+ /* Database filenames are double-zero terminated if they are not
-+ ** URIs with parameters. Hence, they can always be passed into
-+ ** sqlite3_uri_parameter().
-+ */
-+ assert( (eType!=SQLITE_OPEN_MAIN_DB) || (flags & SQLITE_OPEN_URI) ||
-+ zUtf8Name[strlen(zUtf8Name)+1]==0 );
-
-- /* Update the PCache1.pSynced variable if necessary. */
-- if( p->pSynced==pPage ){
-- PgHdr *pSynced = pPage->pDirtyPrev;
-- while( pSynced && (pSynced->flags&PGHDR_NEED_SYNC) ){
-- pSynced = pSynced->pDirtyPrev;
-- }
-- p->pSynced = pSynced;
-+ /* Convert the filename to the system encoding. */
-+ zConverted = convertUtf8Filename(zUtf8Name);
-+ if( zConverted==0 ){
-+ OSTRACE(("OPEN name=%s, rc=SQLITE_IOERR_NOMEM", zUtf8Name));
-+ return SQLITE_IOERR_NOMEM;
- }
-
-- if( pPage->pDirtyNext ){
-- pPage->pDirtyNext->pDirtyPrev = pPage->pDirtyPrev;
-- }else{
-- assert( pPage==p->pDirtyTail );
-- p->pDirtyTail = pPage->pDirtyPrev;
-+ if( winIsDir(zConverted) ){
-+ sqlite3_free(zConverted);
-+ OSTRACE(("OPEN name=%s, rc=SQLITE_CANTOPEN_ISDIR", zUtf8Name));
-+ return SQLITE_CANTOPEN_ISDIR;
- }
-- if( pPage->pDirtyPrev ){
-- pPage->pDirtyPrev->pDirtyNext = pPage->pDirtyNext;
-+
-+ if( isReadWrite ){
-+ dwDesiredAccess = GENERIC_READ | GENERIC_WRITE;
- }else{
-- assert( pPage==p->pDirty );
-- p->pDirty = pPage->pDirtyNext;
-+ dwDesiredAccess = GENERIC_READ;
- }
-- pPage->pDirtyNext = 0;
-- pPage->pDirtyPrev = 0;
--
-- expensive_assert( pcacheCheckSynced(p) );
--}
-
--/*
--** Add page pPage to the head of the dirty list (PCache1.pDirty is set to
--** pPage).
--*/
--static void pcacheAddToDirtyList(PgHdr *pPage){
-- PCache *p = pPage->pCache;
-+ /* SQLITE_OPEN_EXCLUSIVE is used to make sure that a new file is
-+ ** created. SQLite doesn't use it to indicate "exclusive access"
-+ ** as it is usually understood.
-+ */
-+ if( isExclusive ){
-+ /* Creates a new file, only if it does not already exist. */
-+ /* If the file exists, it fails. */
-+ dwCreationDisposition = CREATE_NEW;
-+ }else if( isCreate ){
-+ /* Open existing file, or create if it doesn't exist */
-+ dwCreationDisposition = OPEN_ALWAYS;
-+ }else{
-+ /* Opens a file, only if it exists. */
-+ dwCreationDisposition = OPEN_EXISTING;
-+ }
-
-- assert( pPage->pDirtyNext==0 && pPage->pDirtyPrev==0 && p->pDirty!=pPage );
-+ dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
-
-- pPage->pDirtyNext = p->pDirty;
-- if( pPage->pDirtyNext ){
-- assert( pPage->pDirtyNext->pDirtyPrev==0 );
-- pPage->pDirtyNext->pDirtyPrev = pPage;
-+ if( isDelete ){
-+#if SQLITE_OS_WINCE
-+ dwFlagsAndAttributes = FILE_ATTRIBUTE_HIDDEN;
-+ isTemp = 1;
-+#else
-+ dwFlagsAndAttributes = FILE_ATTRIBUTE_TEMPORARY
-+ | FILE_ATTRIBUTE_HIDDEN
-+ | FILE_FLAG_DELETE_ON_CLOSE;
-+#endif
-+ }else{
-+ dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL;
- }
-- p->pDirty = pPage;
-- if( !p->pDirtyTail ){
-- p->pDirtyTail = pPage;
-+ /* Reports from the internet are that performance is always
-+ ** better if FILE_FLAG_RANDOM_ACCESS is used. Ticket #2699. */
-+#if SQLITE_OS_WINCE
-+ dwFlagsAndAttributes |= FILE_FLAG_RANDOM_ACCESS;
-+#endif
-+
-+ if( isNT() ){
-+#if SQLITE_OS_WINRT
-+ CREATEFILE2_EXTENDED_PARAMETERS extendedParameters;
-+ extendedParameters.dwSize = sizeof(CREATEFILE2_EXTENDED_PARAMETERS);
-+ extendedParameters.dwFileAttributes =
-+ dwFlagsAndAttributes & FILE_ATTRIBUTE_MASK;
-+ extendedParameters.dwFileFlags = dwFlagsAndAttributes & FILE_FLAG_MASK;
-+ extendedParameters.dwSecurityQosFlags = SECURITY_ANONYMOUS;
-+ extendedParameters.lpSecurityAttributes = NULL;
-+ extendedParameters.hTemplateFile = NULL;
-+ while( (h = osCreateFile2((LPCWSTR)zConverted,
-+ dwDesiredAccess,
-+ dwShareMode,
-+ dwCreationDisposition,
-+ &extendedParameters))==INVALID_HANDLE_VALUE &&
-+ retryIoerr(&cnt, &lastErrno) ){
-+ /* Noop */
-+ }
-+#else
-+ while( (h = osCreateFileW((LPCWSTR)zConverted,
-+ dwDesiredAccess,
-+ dwShareMode, NULL,
-+ dwCreationDisposition,
-+ dwFlagsAndAttributes,
-+ NULL))==INVALID_HANDLE_VALUE &&
-+ retryIoerr(&cnt, &lastErrno) ){
-+ /* Noop */
-+ }
-+#endif
- }
-- if( !p->pSynced && 0==(pPage->flags&PGHDR_NEED_SYNC) ){
-- p->pSynced = pPage;
-+#ifdef SQLITE_WIN32_HAS_ANSI
-+ else{
-+ while( (h = osCreateFileA((LPCSTR)zConverted,
-+ dwDesiredAccess,
-+ dwShareMode, NULL,
-+ dwCreationDisposition,
-+ dwFlagsAndAttributes,
-+ NULL))==INVALID_HANDLE_VALUE &&
-+ retryIoerr(&cnt, &lastErrno) ){
-+ /* Noop */
-+ }
- }
-- expensive_assert( pcacheCheckSynced(p) );
--}
-+#endif
-+ logIoerr(cnt);
-
--/*
--** Wrapper around the pluggable caches xUnpin method. If the cache is
--** being used for an in-memory database, this function is a no-op.
--*/
--static void pcacheUnpin(PgHdr *p){
-- PCache *pCache = p->pCache;
-- if( pCache->bPurgeable ){
-- if( p->pgno==1 ){
-- pCache->pPage1 = 0;
-+ OSTRACE(("OPEN file=%p, name=%s, access=%lx, rc=%s\n", h, zUtf8Name,
-+ dwDesiredAccess, (h==INVALID_HANDLE_VALUE) ? "failed" : "ok"));
-+
-+ if( h==INVALID_HANDLE_VALUE ){
-+ pFile->lastErrno = lastErrno;
-+ winLogError(SQLITE_CANTOPEN, pFile->lastErrno, "winOpen", zUtf8Name);
-+ sqlite3_free(zConverted);
-+ if( isReadWrite && !isExclusive ){
-+ return winOpen(pVfs, zName, id,
-+ ((flags|SQLITE_OPEN_READONLY) &
-+ ~(SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE)),
-+ pOutFlags);
-+ }else{
-+ return SQLITE_CANTOPEN_BKPT;
- }
-- sqlite3GlobalConfig.pcache2.xUnpin(pCache->pCache, p->pPage, 0);
- }
--}
-
--/*************************************************** General Interfaces ******
--**
--** Initialize and shutdown the page cache subsystem. Neither of these
--** functions are threadsafe.
--*/
--SQLITE_PRIVATE int sqlite3PcacheInitialize(void){
-- if( sqlite3GlobalConfig.pcache2.xInit==0 ){
-- /* IMPLEMENTATION-OF: R-26801-64137 If the xInit() method is NULL, then the
-- ** built-in default page cache is used instead of the application defined
-- ** page cache. */
-- sqlite3PCacheSetDefault();
-- }
-- return sqlite3GlobalConfig.pcache2.xInit(sqlite3GlobalConfig.pcache2.pArg);
--}
--SQLITE_PRIVATE void sqlite3PcacheShutdown(void){
-- if( sqlite3GlobalConfig.pcache2.xShutdown ){
-- /* IMPLEMENTATION-OF: R-26000-56589 The xShutdown() method may be NULL. */
-- sqlite3GlobalConfig.pcache2.xShutdown(sqlite3GlobalConfig.pcache2.pArg);
-+ if( pOutFlags ){
-+ if( isReadWrite ){
-+ *pOutFlags = SQLITE_OPEN_READWRITE;
-+ }else{
-+ *pOutFlags = SQLITE_OPEN_READONLY;
-+ }
- }
--}
--
--/*
--** Return the size in bytes of a PCache object.
--*/
--SQLITE_PRIVATE int sqlite3PcacheSize(void){ return sizeof(PCache); }
-
--/*
--** Create a new PCache object. Storage space to hold the object
--** has already been allocated and is passed in as the p pointer.
--** The caller discovers how much space needs to be allocated by
--** calling sqlite3PcacheSize().
--*/
--SQLITE_PRIVATE void sqlite3PcacheOpen(
-- int szPage, /* Size of every page */
-- int szExtra, /* Extra space associated with each page */
-- int bPurgeable, /* True if pages are on backing store */
-- int (*xStress)(void*,PgHdr*),/* Call to try to make pages clean */
-- void *pStress, /* Argument to xStress */
-- PCache *p /* Preallocated space for the PCache */
--){
-- memset(p, 0, sizeof(PCache));
-- p->szPage = szPage;
-- p->szExtra = szExtra;
-- p->bPurgeable = bPurgeable;
-- p->xStress = xStress;
-- p->pStress = pStress;
-- p->szCache = 100;
--}
-+ OSTRACE(("OPEN file=%p, name=%s, access=%lx, pOutFlags=%p, *pOutFlags=%d, "
-+ "rc=%s\n", h, zUtf8Name, dwDesiredAccess, pOutFlags, pOutFlags ?
-+ *pOutFlags : 0, (h==INVALID_HANDLE_VALUE) ? "failed" : "ok"));
-
--/*
--** Change the page size for PCache object. The caller must ensure that there
--** are no outstanding page references when this function is called.
--*/
--SQLITE_PRIVATE void sqlite3PcacheSetPageSize(PCache *pCache, int szPage){
-- assert( pCache->nRef==0 && pCache->pDirty==0 );
-- if( pCache->pCache ){
-- sqlite3GlobalConfig.pcache2.xDestroy(pCache->pCache);
-- pCache->pCache = 0;
-- pCache->pPage1 = 0;
-+#if SQLITE_OS_WINCE
-+ if( isReadWrite && eType==SQLITE_OPEN_MAIN_DB
-+ && (rc = winceCreateLock(zName, pFile))!=SQLITE_OK
-+ ){
-+ osCloseHandle(h);
-+ sqlite3_free(zConverted);
-+ OSTRACE(("OPEN-CE-LOCK name=%s, rc=%s\n", zName, sqlite3ErrName(rc)));
-+ return rc;
-+ }
-+ if( isTemp ){
-+ pFile->zDeleteOnClose = zConverted;
-+ }else
-+#endif
-+ {
-+ sqlite3_free(zConverted);
- }
-- pCache->szPage = szPage;
--}
-
--/*
--** Compute the number of pages of cache requested.
--*/
--static int numberOfCachePages(PCache *p){
-- if( p->szCache>=0 ){
-- return p->szCache;
-- }else{
-- return (int)((-1024*(i64)p->szCache)/(p->szPage+p->szExtra));
-+ pFile->pMethod = &winIoMethod;
-+ pFile->pVfs = pVfs;
-+ pFile->h = h;
-+ if( isReadonly ){
-+ pFile->ctrlFlags |= WINFILE_RDONLY;
-+ }
-+ if( sqlite3_uri_boolean(zName, "psow", SQLITE_POWERSAFE_OVERWRITE) ){
-+ pFile->ctrlFlags |= WINFILE_PSOW;
- }
-+ pFile->lastErrno = NO_ERROR;
-+ pFile->zPath = zName;
-+#if SQLITE_MAX_MMAP_SIZE>0
-+ pFile->hMap = NULL;
-+ pFile->pMapRegion = 0;
-+ pFile->mmapSize = 0;
-+ pFile->mmapSizeActual = 0;
-+ pFile->mmapSizeMax = sqlite3GlobalConfig.szMmap;
-+#endif
-+
-+ OpenCounter(+1);
-+ return rc;
- }
-
- /*
--** Try to obtain a page from the cache.
-+** Delete the named file.
-+**
-+** Note that Windows does not allow a file to be deleted if some other
-+** process has it open. Sometimes a virus scanner or indexing program
-+** will open a journal file shortly after it is created in order to do
-+** whatever it does. While this other process is holding the
-+** file open, we will be unable to delete it. To work around this
-+** problem, we delay 100 milliseconds and try to delete again. Up
-+** to MX_DELETION_ATTEMPTs deletion attempts are run before giving
-+** up and returning an error.
- */
--SQLITE_PRIVATE int sqlite3PcacheFetch(
-- PCache *pCache, /* Obtain the page from this cache */
-- Pgno pgno, /* Page number to obtain */
-- int createFlag, /* If true, create page if it does not exist already */
-- PgHdr **ppPage /* Write the page here */
-+static int winDelete(
-+ sqlite3_vfs *pVfs, /* Not used on win32 */
-+ const char *zFilename, /* Name of file to delete */
-+ int syncDir /* Not used on win32 */
- ){
-- sqlite3_pcache_page *pPage = 0;
-- PgHdr *pPgHdr = 0;
-- int eCreate;
--
-- assert( pCache!=0 );
-- assert( createFlag==1 || createFlag==0 );
-- assert( pgno>0 );
-+ int cnt = 0;
-+ int rc;
-+ DWORD attr;
-+ DWORD lastErrno;
-+ void *zConverted;
-+ UNUSED_PARAMETER(pVfs);
-+ UNUSED_PARAMETER(syncDir);
-
-- /* If the pluggable cache (sqlite3_pcache*) has not been allocated,
-- ** allocate it now.
-- */
-- if( !pCache->pCache && createFlag ){
-- sqlite3_pcache *p;
-- p = sqlite3GlobalConfig.pcache2.xCreate(
-- pCache->szPage, pCache->szExtra + sizeof(PgHdr), pCache->bPurgeable
-- );
-- if( !p ){
-- return SQLITE_NOMEM;
-- }
-- sqlite3GlobalConfig.pcache2.xCachesize(p, numberOfCachePages(pCache));
-- pCache->pCache = p;
-- }
-+ SimulateIOError(return SQLITE_IOERR_DELETE);
-+ OSTRACE(("DELETE name=%s, syncDir=%d\n", zFilename, syncDir));
-
-- eCreate = createFlag * (1 + (!pCache->bPurgeable || !pCache->pDirty));
-- if( pCache->pCache ){
-- pPage = sqlite3GlobalConfig.pcache2.xFetch(pCache->pCache, pgno, eCreate);
-+ zConverted = convertUtf8Filename(zFilename);
-+ if( zConverted==0 ){
-+ return SQLITE_IOERR_NOMEM;
- }
--
-- if( !pPage && eCreate==1 ){
-- PgHdr *pPg;
--
-- /* Find a dirty page to write-out and recycle. First try to find a
-- ** page that does not require a journal-sync (one with PGHDR_NEED_SYNC
-- ** cleared), but if that is not possible settle for any other
-- ** unreferenced dirty page.
-- */
-- expensive_assert( pcacheCheckSynced(pCache) );
-- for(pPg=pCache->pSynced;
-- pPg && (pPg->nRef || (pPg->flags&PGHDR_NEED_SYNC));
-- pPg=pPg->pDirtyPrev
-- );
-- pCache->pSynced = pPg;
-- if( !pPg ){
-- for(pPg=pCache->pDirtyTail; pPg && pPg->nRef; pPg=pPg->pDirtyPrev);
-- }
-- if( pPg ){
-- int rc;
--#ifdef SQLITE_LOG_CACHE_SPILL
-- sqlite3_log(SQLITE_FULL,
-- "spill page %d making room for %d - cache used: %d/%d",
-- pPg->pgno, pgno,
-- sqlite3GlobalConfig.pcache.xPagecount(pCache->pCache),
-- numberOfCachePages(pCache));
-+ if( isNT() ){
-+ do {
-+#if SQLITE_OS_WINRT
-+ WIN32_FILE_ATTRIBUTE_DATA sAttrData;
-+ memset(&sAttrData, 0, sizeof(sAttrData));
-+ if ( osGetFileAttributesExW(zConverted, GetFileExInfoStandard,
-+ &sAttrData) ){
-+ attr = sAttrData.dwFileAttributes;
-+ }else{
-+ lastErrno = osGetLastError();
-+ if( lastErrno==ERROR_FILE_NOT_FOUND
-+ || lastErrno==ERROR_PATH_NOT_FOUND ){
-+ rc = SQLITE_IOERR_DELETE_NOENT; /* Already gone? */
-+ }else{
-+ rc = SQLITE_ERROR;
-+ }
-+ break;
-+ }
-+#else
-+ attr = osGetFileAttributesW(zConverted);
- #endif
-- rc = pCache->xStress(pCache->pStress, pPg);
-- if( rc!=SQLITE_OK && rc!=SQLITE_BUSY ){
-- return rc;
-+ if ( attr==INVALID_FILE_ATTRIBUTES ){
-+ lastErrno = osGetLastError();
-+ if( lastErrno==ERROR_FILE_NOT_FOUND
-+ || lastErrno==ERROR_PATH_NOT_FOUND ){
-+ rc = SQLITE_IOERR_DELETE_NOENT; /* Already gone? */
-+ }else{
-+ rc = SQLITE_ERROR;
-+ }
-+ break;
- }
-- }
--
-- pPage = sqlite3GlobalConfig.pcache2.xFetch(pCache->pCache, pgno, 2);
-+ if ( attr&FILE_ATTRIBUTE_DIRECTORY ){
-+ rc = SQLITE_ERROR; /* Files only. */
-+ break;
-+ }
-+ if ( osDeleteFileW(zConverted) ){
-+ rc = SQLITE_OK; /* Deleted OK. */
-+ break;
-+ }
-+ if ( !retryIoerr(&cnt, &lastErrno) ){
-+ rc = SQLITE_ERROR; /* No more retries. */
-+ break;
-+ }
-+ } while(1);
- }
--
-- if( pPage ){
-- pPgHdr = (PgHdr *)pPage->pExtra;
--
-- if( !pPgHdr->pPage ){
-- memset(pPgHdr, 0, sizeof(PgHdr));
-- pPgHdr->pPage = pPage;
-- pPgHdr->pData = pPage->pBuf;
-- pPgHdr->pExtra = (void *)&pPgHdr[1];
-- memset(pPgHdr->pExtra, 0, pCache->szExtra);
-- pPgHdr->pCache = pCache;
-- pPgHdr->pgno = pgno;
-- }
-- assert( pPgHdr->pCache==pCache );
-- assert( pPgHdr->pgno==pgno );
-- assert( pPgHdr->pData==pPage->pBuf );
-- assert( pPgHdr->pExtra==(void *)&pPgHdr[1] );
--
-- if( 0==pPgHdr->nRef ){
-- pCache->nRef++;
-- }
-- pPgHdr->nRef++;
-- if( pgno==1 ){
-- pCache->pPage1 = pPgHdr;
-- }
-+#ifdef SQLITE_WIN32_HAS_ANSI
-+ else{
-+ do {
-+ attr = osGetFileAttributesA(zConverted);
-+ if ( attr==INVALID_FILE_ATTRIBUTES ){
-+ lastErrno = osGetLastError();
-+ if( lastErrno==ERROR_FILE_NOT_FOUND
-+ || lastErrno==ERROR_PATH_NOT_FOUND ){
-+ rc = SQLITE_IOERR_DELETE_NOENT; /* Already gone? */
-+ }else{
-+ rc = SQLITE_ERROR;
-+ }
-+ break;
-+ }
-+ if ( attr&FILE_ATTRIBUTE_DIRECTORY ){
-+ rc = SQLITE_ERROR; /* Files only. */
-+ break;
-+ }
-+ if ( osDeleteFileA(zConverted) ){
-+ rc = SQLITE_OK; /* Deleted OK. */
-+ break;
-+ }
-+ if ( !retryIoerr(&cnt, &lastErrno) ){
-+ rc = SQLITE_ERROR; /* No more retries. */
-+ break;
-+ }
-+ } while(1);
- }
-- *ppPage = pPgHdr;
-- return (pPgHdr==0 && eCreate) ? SQLITE_NOMEM : SQLITE_OK;
-+#endif
-+ if( rc && rc!=SQLITE_IOERR_DELETE_NOENT ){
-+ rc = winLogError(SQLITE_IOERR_DELETE, lastErrno,
-+ "winDelete", zFilename);
-+ }else{
-+ logIoerr(cnt);
-+ }
-+ sqlite3_free(zConverted);
-+ OSTRACE(("DELETE name=%s, rc=%s\n", zFilename, sqlite3ErrName(rc)));
-+ return rc;
- }
-
- /*
--** Decrement the reference count on a page. If the page is clean and the
--** reference count drops to 0, then it is made elible for recycling.
-+** Check the existence and status of a file.
- */
--SQLITE_PRIVATE void sqlite3PcacheRelease(PgHdr *p){
-- assert( p->nRef>0 );
-- p->nRef--;
-- if( p->nRef==0 ){
-- PCache *pCache = p->pCache;
-- pCache->nRef--;
-- if( (p->flags&PGHDR_DIRTY)==0 ){
-- pcacheUnpin(p);
-+static int winAccess(
-+ sqlite3_vfs *pVfs, /* Not used on win32 */
-+ const char *zFilename, /* Name of file to check */
-+ int flags, /* Type of test to make on this file */
-+ int *pResOut /* OUT: Result */
-+){
-+ DWORD attr;
-+ int rc = 0;
-+ DWORD lastErrno;
-+ void *zConverted;
-+ UNUSED_PARAMETER(pVfs);
-+
-+ SimulateIOError( return SQLITE_IOERR_ACCESS; );
-+ OSTRACE(("ACCESS name=%s, flags=%x, pResOut=%p\n",
-+ zFilename, flags, pResOut));
-+
-+ zConverted = convertUtf8Filename(zFilename);
-+ if( zConverted==0 ){
-+ OSTRACE(("ACCESS name=%s, rc=SQLITE_IOERR_NOMEM\n", zFilename));
-+ return SQLITE_IOERR_NOMEM;
-+ }
-+ if( isNT() ){
-+ int cnt = 0;
-+ WIN32_FILE_ATTRIBUTE_DATA sAttrData;
-+ memset(&sAttrData, 0, sizeof(sAttrData));
-+ while( !(rc = osGetFileAttributesExW((LPCWSTR)zConverted,
-+ GetFileExInfoStandard,
-+ &sAttrData)) && retryIoerr(&cnt, &lastErrno) ){}
-+ if( rc ){
-+ /* For an SQLITE_ACCESS_EXISTS query, treat a zero-length file
-+ ** as if it does not exist.
-+ */
-+ if( flags==SQLITE_ACCESS_EXISTS
-+ && sAttrData.nFileSizeHigh==0
-+ && sAttrData.nFileSizeLow==0 ){
-+ attr = INVALID_FILE_ATTRIBUTES;
-+ }else{
-+ attr = sAttrData.dwFileAttributes;
-+ }
- }else{
-- /* Move the page to the head of the dirty list. */
-- pcacheRemoveFromDirtyList(p);
-- pcacheAddToDirtyList(p);
-+ logIoerr(cnt);
-+ if( lastErrno!=ERROR_FILE_NOT_FOUND && lastErrno!=ERROR_PATH_NOT_FOUND ){
-+ winLogError(SQLITE_IOERR_ACCESS, lastErrno, "winAccess", zFilename);
-+ sqlite3_free(zConverted);
-+ return SQLITE_IOERR_ACCESS;
-+ }else{
-+ attr = INVALID_FILE_ATTRIBUTES;
-+ }
- }
- }
--}
--
--/*
--** Increase the reference count of a supplied page by 1.
--*/
--SQLITE_PRIVATE void sqlite3PcacheRef(PgHdr *p){
-- assert(p->nRef>0);
-- p->nRef++;
--}
--
--/*
--** Drop a page from the cache. There must be exactly one reference to the
--** page. This function deletes that reference, so after it returns the
--** page pointed to by p is invalid.
--*/
--SQLITE_PRIVATE void sqlite3PcacheDrop(PgHdr *p){
-- PCache *pCache;
-- assert( p->nRef==1 );
-- if( p->flags&PGHDR_DIRTY ){
-- pcacheRemoveFromDirtyList(p);
-+#ifdef SQLITE_WIN32_HAS_ANSI
-+ else{
-+ attr = osGetFileAttributesA((char*)zConverted);
- }
-- pCache = p->pCache;
-- pCache->nRef--;
-- if( p->pgno==1 ){
-- pCache->pPage1 = 0;
-+#endif
-+ sqlite3_free(zConverted);
-+ switch( flags ){
-+ case SQLITE_ACCESS_READ:
-+ case SQLITE_ACCESS_EXISTS:
-+ rc = attr!=INVALID_FILE_ATTRIBUTES;
-+ break;
-+ case SQLITE_ACCESS_READWRITE:
-+ rc = attr!=INVALID_FILE_ATTRIBUTES &&
-+ (attr & FILE_ATTRIBUTE_READONLY)==0;
-+ break;
-+ default:
-+ assert(!"Invalid flags argument");
- }
-- sqlite3GlobalConfig.pcache2.xUnpin(pCache->pCache, p->pPage, 1);
-+ *pResOut = rc;
-+ OSTRACE(("ACCESS name=%s, pResOut=%p, *pResOut=%d, rc=SQLITE_OK\n",
-+ zFilename, pResOut, *pResOut));
-+ return SQLITE_OK;
- }
-
-+
- /*
--** Make sure the page is marked as dirty. If it isn't dirty already,
--** make it so.
-+** Returns non-zero if the specified path name should be used verbatim. If
-+** non-zero is returned from this function, the calling function must simply
-+** use the provided path name verbatim -OR- resolve it into a full path name
-+** using the GetFullPathName Win32 API function (if available).
- */
--SQLITE_PRIVATE void sqlite3PcacheMakeDirty(PgHdr *p){
-- p->flags &= ~PGHDR_DONT_WRITE;
-- assert( p->nRef>0 );
-- if( 0==(p->flags & PGHDR_DIRTY) ){
-- p->flags |= PGHDR_DIRTY;
-- pcacheAddToDirtyList( p);
-+static BOOL winIsVerbatimPathname(
-+ const char *zPathname
-+){
-+ /*
-+ ** If the path name starts with a forward slash or a backslash, it is either
-+ ** a legal UNC name, a volume relative path, or an absolute path name in the
-+ ** "Unix" format on Windows. There is no easy way to differentiate between
-+ ** the final two cases; therefore, we return the safer return value of TRUE
-+ ** so that callers of this function will simply use it verbatim.
-+ */
-+ if ( zPathname[0]=='/' || zPathname[0]=='\\' ){
-+ return TRUE;
- }
--}
-
--/*
--** Make sure the page is marked as clean. If it isn't clean already,
--** make it so.
--*/
--SQLITE_PRIVATE void sqlite3PcacheMakeClean(PgHdr *p){
-- if( (p->flags & PGHDR_DIRTY) ){
-- pcacheRemoveFromDirtyList(p);
-- p->flags &= ~(PGHDR_DIRTY|PGHDR_NEED_SYNC);
-- if( p->nRef==0 ){
-- pcacheUnpin(p);
-- }
-+ /*
-+ ** If the path name starts with a letter and a colon it is either a volume
-+ ** relative path or an absolute path. Callers of this function must not
-+ ** attempt to treat it as a relative path name (i.e. they should simply use
-+ ** it verbatim).
-+ */
-+ if ( sqlite3Isalpha(zPathname[0]) && zPathname[1]==':' ){
-+ return TRUE;
- }
-+
-+ /*
-+ ** If we get to this point, the path name should almost certainly be a purely
-+ ** relative one (i.e. not a UNC name, not absolute, and not volume relative).
-+ */
-+ return FALSE;
- }
-
- /*
--** Make every page in the cache clean.
-+** Turn a relative pathname into a full pathname. Write the full
-+** pathname into zOut[]. zOut[] will be at least pVfs->mxPathname
-+** bytes in size.
- */
--SQLITE_PRIVATE void sqlite3PcacheCleanAll(PCache *pCache){
-- PgHdr *p;
-- while( (p = pCache->pDirty)!=0 ){
-- sqlite3PcacheMakeClean(p);
-+static int winFullPathname(
-+ sqlite3_vfs *pVfs, /* Pointer to vfs object */
-+ const char *zRelative, /* Possibly relative input path */
-+ int nFull, /* Size of output buffer in bytes */
-+ char *zFull /* Output buffer */
-+){
-+
-+#if defined(__CYGWIN__)
-+ SimulateIOError( return SQLITE_ERROR );
-+ UNUSED_PARAMETER(nFull);
-+ assert( pVfs->mxPathname>=MAX_PATH );
-+ assert( nFull>=pVfs->mxPathname );
-+ if ( sqlite3_data_directory && !winIsVerbatimPathname(zRelative) ){
-+ /*
-+ ** NOTE: We are dealing with a relative path name and the data
-+ ** directory has been set. Therefore, use it as the basis
-+ ** for converting the relative path name to an absolute
-+ ** one by prepending the data directory and a slash.
-+ */
-+ char zOut[MAX_PATH+1];
-+ memset(zOut, 0, MAX_PATH+1);
-+ cygwin_conv_path(CCP_POSIX_TO_WIN_A|CCP_RELATIVE, zRelative, zOut,
-+ MAX_PATH+1);
-+ sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s\\%s",
-+ sqlite3_data_directory, zOut);
-+ }else{
-+ cygwin_conv_path(CCP_POSIX_TO_WIN_A, zRelative, zFull, nFull);
- }
--}
-+ return SQLITE_OK;
-+#endif
-
--/*
--** Clear the PGHDR_NEED_SYNC flag from all dirty pages.
--*/
--SQLITE_PRIVATE void sqlite3PcacheClearSyncFlags(PCache *pCache){
-- PgHdr *p;
-- for(p=pCache->pDirty; p; p=p->pDirtyNext){
-- p->flags &= ~PGHDR_NEED_SYNC;
-+#if (SQLITE_OS_WINCE || SQLITE_OS_WINRT) && !defined(__CYGWIN__)
-+ SimulateIOError( return SQLITE_ERROR );
-+ /* WinCE has no concept of a relative pathname, or so I am told. */
-+ /* WinRT has no way to convert a relative path to an absolute one. */
-+ if ( sqlite3_data_directory && !winIsVerbatimPathname(zRelative) ){
-+ /*
-+ ** NOTE: We are dealing with a relative path name and the data
-+ ** directory has been set. Therefore, use it as the basis
-+ ** for converting the relative path name to an absolute
-+ ** one by prepending the data directory and a backslash.
-+ */
-+ sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s\\%s",
-+ sqlite3_data_directory, zRelative);
-+ }else{
-+ sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s", zRelative);
- }
-- pCache->pSynced = pCache->pDirtyTail;
--}
-+ return SQLITE_OK;
-+#endif
-
--/*
--** Change the page number of page p to newPgno.
--*/
--SQLITE_PRIVATE void sqlite3PcacheMove(PgHdr *p, Pgno newPgno){
-- PCache *pCache = p->pCache;
-- assert( p->nRef>0 );
-- assert( newPgno>0 );
-- sqlite3GlobalConfig.pcache2.xRekey(pCache->pCache, p->pPage, p->pgno,newPgno);
-- p->pgno = newPgno;
-- if( (p->flags&PGHDR_DIRTY) && (p->flags&PGHDR_NEED_SYNC) ){
-- pcacheRemoveFromDirtyList(p);
-- pcacheAddToDirtyList(p);
-+#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && !defined(__CYGWIN__)
-+ DWORD nByte;
-+ void *zConverted;
-+ char *zOut;
-+
-+ /* If this path name begins with "/X:", where "X" is any alphabetic
-+ ** character, discard the initial "/" from the pathname.
-+ */
-+ if( zRelative[0]=='/' && sqlite3Isalpha(zRelative[1]) && zRelative[2]==':' ){
-+ zRelative++;
- }
--}
-
--/*
--** Drop every cache entry whose page number is greater than "pgno". The
--** caller must ensure that there are no outstanding references to any pages
--** other than page 1 with a page number greater than pgno.
--**
--** If there is a reference to page 1 and the pgno parameter passed to this
--** function is 0, then the data area associated with page 1 is zeroed, but
--** the page object is not dropped.
--*/
--SQLITE_PRIVATE void sqlite3PcacheTruncate(PCache *pCache, Pgno pgno){
-- if( pCache->pCache ){
-- PgHdr *p;
-- PgHdr *pNext;
-- for(p=pCache->pDirty; p; p=pNext){
-- pNext = p->pDirtyNext;
-- /* This routine never gets call with a positive pgno except right
-- ** after sqlite3PcacheCleanAll(). So if there are dirty pages,
-- ** it must be that pgno==0.
-- */
-- assert( p->pgno>0 );
-- if( ALWAYS(p->pgno>pgno) ){
-- assert( p->flags&PGHDR_DIRTY );
-- sqlite3PcacheMakeClean(p);
-- }
-+ /* It's odd to simulate an io-error here, but really this is just
-+ ** using the io-error infrastructure to test that SQLite handles this
-+ ** function failing. This function could fail if, for example, the
-+ ** current working directory has been unlinked.
-+ */
-+ SimulateIOError( return SQLITE_ERROR );
-+ if ( sqlite3_data_directory && !winIsVerbatimPathname(zRelative) ){
-+ /*
-+ ** NOTE: We are dealing with a relative path name and the data
-+ ** directory has been set. Therefore, use it as the basis
-+ ** for converting the relative path name to an absolute
-+ ** one by prepending the data directory and a backslash.
-+ */
-+ sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s\\%s",
-+ sqlite3_data_directory, zRelative);
-+ return SQLITE_OK;
-+ }
-+ zConverted = convertUtf8Filename(zRelative);
-+ if( zConverted==0 ){
-+ return SQLITE_IOERR_NOMEM;
-+ }
-+ if( isNT() ){
-+ LPWSTR zTemp;
-+ nByte = osGetFullPathNameW((LPCWSTR)zConverted, 0, 0, 0);
-+ if( nByte==0 ){
-+ winLogError(SQLITE_ERROR, osGetLastError(),
-+ "GetFullPathNameW1", zConverted);
-+ sqlite3_free(zConverted);
-+ return SQLITE_CANTOPEN_FULLPATH;
- }
-- if( pgno==0 && pCache->pPage1 ){
-- memset(pCache->pPage1->pData, 0, pCache->szPage);
-- pgno = 1;
-+ nByte += 3;
-+ zTemp = sqlite3MallocZero( nByte*sizeof(zTemp[0]) );
-+ if( zTemp==0 ){
-+ sqlite3_free(zConverted);
-+ return SQLITE_IOERR_NOMEM;
- }
-- sqlite3GlobalConfig.pcache2.xTruncate(pCache->pCache, pgno+1);
-+ nByte = osGetFullPathNameW((LPCWSTR)zConverted, nByte, zTemp, 0);
-+ if( nByte==0 ){
-+ winLogError(SQLITE_ERROR, osGetLastError(),
-+ "GetFullPathNameW2", zConverted);
-+ sqlite3_free(zConverted);
-+ sqlite3_free(zTemp);
-+ return SQLITE_CANTOPEN_FULLPATH;
-+ }
-+ sqlite3_free(zConverted);
-+ zOut = unicodeToUtf8(zTemp);
-+ sqlite3_free(zTemp);
- }
--}
--
--/*
--** Close a cache.
--*/
--SQLITE_PRIVATE void sqlite3PcacheClose(PCache *pCache){
-- if( pCache->pCache ){
-- sqlite3GlobalConfig.pcache2.xDestroy(pCache->pCache);
-+#ifdef SQLITE_WIN32_HAS_ANSI
-+ else{
-+ char *zTemp;
-+ nByte = osGetFullPathNameA((char*)zConverted, 0, 0, 0);
-+ if( nByte==0 ){
-+ winLogError(SQLITE_ERROR, osGetLastError(),
-+ "GetFullPathNameA1", zConverted);
-+ sqlite3_free(zConverted);
-+ return SQLITE_CANTOPEN_FULLPATH;
-+ }
-+ nByte += 3;
-+ zTemp = sqlite3MallocZero( nByte*sizeof(zTemp[0]) );
-+ if( zTemp==0 ){
-+ sqlite3_free(zConverted);
-+ return SQLITE_IOERR_NOMEM;
-+ }
-+ nByte = osGetFullPathNameA((char*)zConverted, nByte, zTemp, 0);
-+ if( nByte==0 ){
-+ winLogError(SQLITE_ERROR, osGetLastError(),
-+ "GetFullPathNameA2", zConverted);
-+ sqlite3_free(zConverted);
-+ sqlite3_free(zTemp);
-+ return SQLITE_CANTOPEN_FULLPATH;
-+ }
-+ sqlite3_free(zConverted);
-+ zOut = sqlite3_win32_mbcs_to_utf8(zTemp);
-+ sqlite3_free(zTemp);
-+ }
-+#endif
-+ if( zOut ){
-+ sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s", zOut);
-+ sqlite3_free(zOut);
-+ return SQLITE_OK;
-+ }else{
-+ return SQLITE_IOERR_NOMEM;
- }
-+#endif
- }
-
--/*
--** Discard the contents of the cache.
-+#ifndef SQLITE_OMIT_LOAD_EXTENSION
-+/*
-+** Interfaces for opening a shared library, finding entry points
-+** within the shared library, and closing the shared library.
- */
--SQLITE_PRIVATE void sqlite3PcacheClear(PCache *pCache){
-- sqlite3PcacheTruncate(pCache, 0);
--}
--
- /*
--** Merge two lists of pages connected by pDirty and in pgno order.
--** Do not both fixing the pDirtyPrev pointers.
-+** Interfaces for opening a shared library, finding entry points
-+** within the shared library, and closing the shared library.
- */
--static PgHdr *pcacheMergeDirtyList(PgHdr *pA, PgHdr *pB){
-- PgHdr result, *pTail;
-- pTail = &result;
-- while( pA && pB ){
-- if( pA->pgno<pB->pgno ){
-- pTail->pDirty = pA;
-- pTail = pA;
-- pA = pA->pDirty;
-- }else{
-- pTail->pDirty = pB;
-- pTail = pB;
-- pB = pB->pDirty;
-- }
-+static void *winDlOpen(sqlite3_vfs *pVfs, const char *zFilename){
-+ HANDLE h;
-+ void *zConverted = convertUtf8Filename(zFilename);
-+ UNUSED_PARAMETER(pVfs);
-+ if( zConverted==0 ){
-+ return 0;
- }
-- if( pA ){
-- pTail->pDirty = pA;
-- }else if( pB ){
-- pTail->pDirty = pB;
-- }else{
-- pTail->pDirty = 0;
-+ if( isNT() ){
-+#if SQLITE_OS_WINRT
-+ h = osLoadPackagedLibrary((LPCWSTR)zConverted, 0);
-+#else
-+ h = osLoadLibraryW((LPCWSTR)zConverted);
-+#endif
- }
-- return result.pDirty;
-+#ifdef SQLITE_WIN32_HAS_ANSI
-+ else{
-+ h = osLoadLibraryA((char*)zConverted);
-+ }
-+#endif
-+ sqlite3_free(zConverted);
-+ return (void*)h;
-+}
-+static void winDlError(sqlite3_vfs *pVfs, int nBuf, char *zBufOut){
-+ UNUSED_PARAMETER(pVfs);
-+ getLastErrorMsg(osGetLastError(), nBuf, zBufOut);
-+}
-+static void (*winDlSym(sqlite3_vfs *pVfs,void *pH,const char *zSym))(void){
-+ UNUSED_PARAMETER(pVfs);
-+ return (void(*)(void))osGetProcAddressA((HANDLE)pH, zSym);
-+}
-+static void winDlClose(sqlite3_vfs *pVfs, void *pHandle){
-+ UNUSED_PARAMETER(pVfs);
-+ osFreeLibrary((HANDLE)pHandle);
- }
-+#else /* if SQLITE_OMIT_LOAD_EXTENSION is defined: */
-+ #define winDlOpen 0
-+ #define winDlError 0
-+ #define winDlSym 0
-+ #define winDlClose 0
-+#endif
-+
-
- /*
--** Sort the list of pages in accending order by pgno. Pages are
--** connected by pDirty pointers. The pDirtyPrev pointers are
--** corrupted by this sort.
--**
--** Since there cannot be more than 2^31 distinct pages in a database,
--** there cannot be more than 31 buckets required by the merge sorter.
--** One extra bucket is added to catch overflow in case something
--** ever changes to make the previous sentence incorrect.
-+** Write up to nBuf bytes of randomness into zBuf.
- */
--#define N_SORT_BUCKET 32
--static PgHdr *pcacheSortDirtyList(PgHdr *pIn){
-- PgHdr *a[N_SORT_BUCKET], *p;
-- int i;
-- memset(a, 0, sizeof(a));
-- while( pIn ){
-- p = pIn;
-- pIn = p->pDirty;
-- p->pDirty = 0;
-- for(i=0; ALWAYS(i<N_SORT_BUCKET-1); i++){
-- if( a[i]==0 ){
-- a[i] = p;
-- break;
-- }else{
-- p = pcacheMergeDirtyList(a[i], p);
-- a[i] = 0;
-- }
-- }
-- if( NEVER(i==N_SORT_BUCKET-1) ){
-- /* To get here, there need to be 2^(N_SORT_BUCKET) elements in
-- ** the input list. But that is impossible.
-- */
-- a[i] = pcacheMergeDirtyList(a[i], p);
-- }
-+static int winRandomness(sqlite3_vfs *pVfs, int nBuf, char *zBuf){
-+ int n = 0;
-+ UNUSED_PARAMETER(pVfs);
-+#if defined(SQLITE_TEST)
-+ n = nBuf;
-+ memset(zBuf, 0, nBuf);
-+#else
-+ if( sizeof(SYSTEMTIME)<=nBuf-n ){
-+ SYSTEMTIME x;
-+ osGetSystemTime(&x);
-+ memcpy(&zBuf[n], &x, sizeof(x));
-+ n += sizeof(x);
- }
-- p = a[0];
-- for(i=1; i<N_SORT_BUCKET; i++){
-- p = pcacheMergeDirtyList(p, a[i]);
-+ if( sizeof(DWORD)<=nBuf-n ){
-+ DWORD pid = osGetCurrentProcessId();
-+ memcpy(&zBuf[n], &pid, sizeof(pid));
-+ n += sizeof(pid);
- }
-- return p;
-+#if SQLITE_OS_WINRT
-+ if( sizeof(ULONGLONG)<=nBuf-n ){
-+ ULONGLONG cnt = osGetTickCount64();
-+ memcpy(&zBuf[n], &cnt, sizeof(cnt));
-+ n += sizeof(cnt);
-+ }
-+#else
-+ if( sizeof(DWORD)<=nBuf-n ){
-+ DWORD cnt = osGetTickCount();
-+ memcpy(&zBuf[n], &cnt, sizeof(cnt));
-+ n += sizeof(cnt);
-+ }
-+#endif
-+ if( sizeof(LARGE_INTEGER)<=nBuf-n ){
-+ LARGE_INTEGER i;
-+ osQueryPerformanceCounter(&i);
-+ memcpy(&zBuf[n], &i, sizeof(i));
-+ n += sizeof(i);
-+ }
-+#endif
-+ return n;
- }
-
-+
- /*
--** Return a list of all dirty pages in the cache, sorted by page number.
-+** Sleep for a little while. Return the amount of time slept.
- */
--SQLITE_PRIVATE PgHdr *sqlite3PcacheDirtyList(PCache *pCache){
-- PgHdr *p;
-- for(p=pCache->pDirty; p; p=p->pDirtyNext){
-- p->pDirty = p->pDirtyNext;
-- }
-- return pcacheSortDirtyList(pCache->pDirty);
-+static int winSleep(sqlite3_vfs *pVfs, int microsec){
-+ sqlite3_win32_sleep((microsec+999)/1000);
-+ UNUSED_PARAMETER(pVfs);
-+ return ((microsec+999)/1000)*1000;
- }
-
--/*
--** Return the total number of referenced pages held by the cache.
-+/*
-+** The following variable, if set to a non-zero value, is interpreted as
-+** the number of seconds since 1970 and is used to set the result of
-+** sqlite3OsCurrentTime() during testing.
- */
--SQLITE_PRIVATE int sqlite3PcacheRefCount(PCache *pCache){
-- return pCache->nRef;
--}
-+#ifdef SQLITE_TEST
-+SQLITE_API int sqlite3_current_time = 0; /* Fake system time in seconds since 1970. */
-+#endif
-
- /*
--** Return the number of references to the page supplied as an argument.
-+** Find the current time (in Universal Coordinated Time). Write into *piNow
-+** the current time and date as a Julian Day number times 86_400_000. In
-+** other words, write into *piNow the number of milliseconds since the Julian
-+** epoch of noon in Greenwich on November 24, 4714 B.C according to the
-+** proleptic Gregorian calendar.
-+**
-+** On success, return SQLITE_OK. Return SQLITE_ERROR if the time and date
-+** cannot be found.
- */
--SQLITE_PRIVATE int sqlite3PcachePageRefcount(PgHdr *p){
-- return p->nRef;
--}
-+static int winCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *piNow){
-+ /* FILETIME structure is a 64-bit value representing the number of
-+ 100-nanosecond intervals since January 1, 1601 (= JD 2305813.5).
-+ */
-+ FILETIME ft;
-+ static const sqlite3_int64 winFiletimeEpoch = 23058135*(sqlite3_int64)8640000;
-+#ifdef SQLITE_TEST
-+ static const sqlite3_int64 unixEpoch = 24405875*(sqlite3_int64)8640000;
-+#endif
-+ /* 2^32 - to avoid use of LL and warnings in gcc */
-+ static const sqlite3_int64 max32BitValue =
-+ (sqlite3_int64)2000000000 + (sqlite3_int64)2000000000 +
-+ (sqlite3_int64)294967296;
-
--/*
--** Return the total number of pages in the cache.
--*/
--SQLITE_PRIVATE int sqlite3PcachePagecount(PCache *pCache){
-- int nPage = 0;
-- if( pCache->pCache ){
-- nPage = sqlite3GlobalConfig.pcache2.xPagecount(pCache->pCache);
-+#if SQLITE_OS_WINCE
-+ SYSTEMTIME time;
-+ osGetSystemTime(&time);
-+ /* if SystemTimeToFileTime() fails, it returns zero. */
-+ if (!osSystemTimeToFileTime(&time,&ft)){
-+ return SQLITE_ERROR;
- }
-- return nPage;
--}
-+#else
-+ osGetSystemTimeAsFileTime( &ft );
-+#endif
-+
-+ *piNow = winFiletimeEpoch +
-+ ((((sqlite3_int64)ft.dwHighDateTime)*max32BitValue) +
-+ (sqlite3_int64)ft.dwLowDateTime)/(sqlite3_int64)10000;
-
- #ifdef SQLITE_TEST
--/*
--** Get the suggested cache-size value.
--*/
--SQLITE_PRIVATE int sqlite3PcacheGetCachesize(PCache *pCache){
-- return numberOfCachePages(pCache);
--}
-+ if( sqlite3_current_time ){
-+ *piNow = 1000*(sqlite3_int64)sqlite3_current_time + unixEpoch;
-+ }
- #endif
-+ UNUSED_PARAMETER(pVfs);
-+ return SQLITE_OK;
-+}
-
- /*
--** Set the suggested cache-size value.
-+** Find the current time (in Universal Coordinated Time). Write the
-+** current time and date as a Julian Day number into *prNow and
-+** return 0. Return 1 if the time and date cannot be found.
- */
--SQLITE_PRIVATE void sqlite3PcacheSetCachesize(PCache *pCache, int mxPage){
-- pCache->szCache = mxPage;
-- if( pCache->pCache ){
-- sqlite3GlobalConfig.pcache2.xCachesize(pCache->pCache,
-- numberOfCachePages(pCache));
-+static int winCurrentTime(sqlite3_vfs *pVfs, double *prNow){
-+ int rc;
-+ sqlite3_int64 i;
-+ rc = winCurrentTimeInt64(pVfs, &i);
-+ if( !rc ){
-+ *prNow = i/86400000.0;
- }
-+ return rc;
- }
-
- /*
--** Free up as much memory as possible from the page cache.
-+** The idea is that this function works like a combination of
-+** GetLastError() and FormatMessage() on Windows (or errno and
-+** strerror_r() on Unix). After an error is returned by an OS
-+** function, SQLite calls this function with zBuf pointing to
-+** a buffer of nBuf bytes. The OS layer should populate the
-+** buffer with a nul-terminated UTF-8 encoded error message
-+** describing the last IO error to have occurred within the calling
-+** thread.
-+**
-+** If the error message is too large for the supplied buffer,
-+** it should be truncated. The return value of xGetLastError
-+** is zero if the error message fits in the buffer, or non-zero
-+** otherwise (if the message was truncated). If non-zero is returned,
-+** then it is not necessary to include the nul-terminator character
-+** in the output buffer.
-+**
-+** Not supplying an error message will have no adverse effect
-+** on SQLite. It is fine to have an implementation that never
-+** returns an error message:
-+**
-+** int xGetLastError(sqlite3_vfs *pVfs, int nBuf, char *zBuf){
-+** assert(zBuf[0]=='\0');
-+** return 0;
-+** }
-+**
-+** However if an error message is supplied, it will be incorporated
-+** by sqlite into the error message available to the user using
-+** sqlite3_errmsg(), possibly making IO errors easier to debug.
- */
--SQLITE_PRIVATE void sqlite3PcacheShrink(PCache *pCache){
-- if( pCache->pCache ){
-- sqlite3GlobalConfig.pcache2.xShrink(pCache->pCache);
-- }
-+static int winGetLastError(sqlite3_vfs *pVfs, int nBuf, char *zBuf){
-+ UNUSED_PARAMETER(pVfs);
-+ return getLastErrorMsg(osGetLastError(), nBuf, zBuf);
- }
-
--#if defined(SQLITE_CHECK_PAGES) || defined(SQLITE_DEBUG)
- /*
--** For all dirty pages currently in the cache, invoke the specified
--** callback. This is only used if the SQLITE_CHECK_PAGES macro is
--** defined.
-+** Initialize and deinitialize the operating system interface.
- */
--SQLITE_PRIVATE void sqlite3PcacheIterateDirty(PCache *pCache, void (*xIter)(PgHdr *)){
-- PgHdr *pDirty;
-- for(pDirty=pCache->pDirty; pDirty; pDirty=pDirty->pDirtyNext){
-- xIter(pDirty);
-- }
-+SQLITE_API int sqlite3_os_init(void){
-+ static sqlite3_vfs winVfs = {
-+ 3, /* iVersion */
-+ sizeof(winFile), /* szOsFile */
-+ MAX_PATH, /* mxPathname */
-+ 0, /* pNext */
-+ "win32", /* zName */
-+ 0, /* pAppData */
-+ winOpen, /* xOpen */
-+ winDelete, /* xDelete */
-+ winAccess, /* xAccess */
-+ winFullPathname, /* xFullPathname */
-+ winDlOpen, /* xDlOpen */
-+ winDlError, /* xDlError */
-+ winDlSym, /* xDlSym */
-+ winDlClose, /* xDlClose */
-+ winRandomness, /* xRandomness */
-+ winSleep, /* xSleep */
-+ winCurrentTime, /* xCurrentTime */
-+ winGetLastError, /* xGetLastError */
-+ winCurrentTimeInt64, /* xCurrentTimeInt64 */
-+ winSetSystemCall, /* xSetSystemCall */
-+ winGetSystemCall, /* xGetSystemCall */
-+ winNextSystemCall, /* xNextSystemCall */
-+ };
-+
-+ /* Double-check that the aSyscall[] array has been constructed
-+ ** correctly. See ticket [bb3a86e890c8e96ab] */
-+ assert( ArraySize(aSyscall)==74 );
-+
-+ /* get memory map allocation granularity */
-+ memset(&winSysInfo, 0, sizeof(SYSTEM_INFO));
-+#if SQLITE_OS_WINRT
-+ osGetNativeSystemInfo(&winSysInfo);
-+#else
-+ osGetSystemInfo(&winSysInfo);
-+#endif
-+ assert( winSysInfo.dwAllocationGranularity>0 );
-+ assert( winSysInfo.dwPageSize>0 );
-+
-+ sqlite3_vfs_register(&winVfs, 1);
-+ return SQLITE_OK;
- }
-+
-+SQLITE_API int sqlite3_os_end(void){
-+#if SQLITE_OS_WINRT
-+ if( sleepObj!=NULL ){
-+ osCloseHandle(sleepObj);
-+ sleepObj = NULL;
-+ }
- #endif
-+ return SQLITE_OK;
-+}
-
--/************** End of pcache.c **********************************************/
--/************** Begin file pcache1.c *****************************************/
-+#endif /* SQLITE_OS_WIN */
-+
-+/************** End of os_win.c **********************************************/
-+/************** Begin file bitvec.c ******************************************/
- /*
--** 2008 November 05
-+** 2008 February 16
- **
- ** The author disclaims copyright to this source code. In place of
- ** a legal notice, here is a blessing:
-@@ -36670,1019 +38675,1027 @@
- ** May you share freely, never taking more than you give.
- **
- *************************************************************************
-+** This file implements an object that represents a fixed-length
-+** bitmap. Bits are numbered starting with 1.
- **
--** This file implements the default page cache implementation (the
--** sqlite3_pcache interface). It also contains part of the implementation
--** of the SQLITE_CONFIG_PAGECACHE and sqlite3_release_memory() features.
--** If the default page cache implementation is overriden, then neither of
--** these two features are available.
--*/
--
--
--typedef struct PCache1 PCache1;
--typedef struct PgHdr1 PgHdr1;
--typedef struct PgFreeslot PgFreeslot;
--typedef struct PGroup PGroup;
--
--/* Each page cache (or PCache) belongs to a PGroup. A PGroup is a set
--** of one or more PCaches that are able to recycle each others unpinned
--** pages when they are under memory pressure. A PGroup is an instance of
--** the following object.
--**
--** This page cache implementation works in one of two modes:
--**
--** (1) Every PCache is the sole member of its own PGroup. There is
--** one PGroup per PCache.
--**
--** (2) There is a single global PGroup that all PCaches are a member
--** of.
-+** A bitmap is used to record which pages of a database file have been
-+** journalled during a transaction, or which pages have the "dont-write"
-+** property. Usually only a few pages are meet either condition.
-+** So the bitmap is usually sparse and has low cardinality.
-+** But sometimes (for example when during a DROP of a large table) most
-+** or all of the pages in a database can get journalled. In those cases,
-+** the bitmap becomes dense with high cardinality. The algorithm needs
-+** to handle both cases well.
- **
--** Mode 1 uses more memory (since PCache instances are not able to rob
--** unused pages from other PCaches) but it also operates without a mutex,
--** and is therefore often faster. Mode 2 requires a mutex in order to be
--** threadsafe, but recycles pages more efficiently.
-+** The size of the bitmap is fixed when the object is created.
- **
--** For mode (1), PGroup.mutex is NULL. For mode (2) there is only a single
--** PGroup which is the pcache1.grp global variable and its mutex is
--** SQLITE_MUTEX_STATIC_LRU.
--*/
--struct PGroup {
-- sqlite3_mutex *mutex; /* MUTEX_STATIC_LRU or NULL */
-- unsigned int nMaxPage; /* Sum of nMax for purgeable caches */
-- unsigned int nMinPage; /* Sum of nMin for purgeable caches */
-- unsigned int mxPinned; /* nMaxpage + 10 - nMinPage */
-- unsigned int nCurrentPage; /* Number of purgeable pages allocated */
-- PgHdr1 *pLruHead, *pLruTail; /* LRU list of unpinned pages */
--};
--
--/* Each page cache is an instance of the following object. Every
--** open database file (including each in-memory database and each
--** temporary or transient database) has a single page cache which
--** is an instance of this object.
-+** All bits are clear when the bitmap is created. Individual bits
-+** may be set or cleared one at a time.
- **
--** Pointers to structures of this type are cast and returned as
--** opaque sqlite3_pcache* handles.
--*/
--struct PCache1 {
-- /* Cache configuration parameters. Page size (szPage) and the purgeable
-- ** flag (bPurgeable) are set when the cache is created. nMax may be
-- ** modified at any time by a call to the pcache1Cachesize() method.
-- ** The PGroup mutex must be held when accessing nMax.
-- */
-- PGroup *pGroup; /* PGroup this cache belongs to */
-- int szPage; /* Size of allocated pages in bytes */
-- int szExtra; /* Size of extra space in bytes */
-- int bPurgeable; /* True if cache is purgeable */
-- unsigned int nMin; /* Minimum number of pages reserved */
-- unsigned int nMax; /* Configured "cache_size" value */
-- unsigned int n90pct; /* nMax*9/10 */
-- unsigned int iMaxKey; /* Largest key seen since xTruncate() */
--
-- /* Hash table of all pages. The following variables may only be accessed
-- ** when the accessor is holding the PGroup mutex.
-- */
-- unsigned int nRecyclable; /* Number of pages in the LRU list */
-- unsigned int nPage; /* Total number of pages in apHash */
-- unsigned int nHash; /* Number of slots in apHash[] */
-- PgHdr1 **apHash; /* Hash table for fast lookup by key */
--};
--
--/*
--** Each cache entry is represented by an instance of the following
--** structure. Unless SQLITE_PCACHE_SEPARATE_HEADER is defined, a buffer of
--** PgHdr1.pCache->szPage bytes is allocated directly before this structure
--** in memory.
-+** Test operations are about 100 times more common that set operations.
-+** Clear operations are exceedingly rare. There are usually between
-+** 5 and 500 set operations per Bitvec object, though the number of sets can
-+** sometimes grow into tens of thousands or larger. The size of the
-+** Bitvec object is the number of pages in the database file at the
-+** start of a transaction, and is thus usually less than a few thousand,
-+** but can be as large as 2 billion for a really big database.
- */
--struct PgHdr1 {
-- sqlite3_pcache_page page;
-- unsigned int iKey; /* Key value (page number) */
-- PgHdr1 *pNext; /* Next in hash table chain */
-- PCache1 *pCache; /* Cache that currently owns this page */
-- PgHdr1 *pLruNext; /* Next in LRU list of unpinned pages */
-- PgHdr1 *pLruPrev; /* Previous in LRU list of unpinned pages */
--};
-
--/*
--** Free slots in the allocator used to divide up the buffer provided using
--** the SQLITE_CONFIG_PAGECACHE mechanism.
--*/
--struct PgFreeslot {
-- PgFreeslot *pNext; /* Next free slot */
--};
-+/* Size of the Bitvec structure in bytes. */
-+#define BITVEC_SZ 512
-
--/*
--** Global data used by this cache.
--*/
--static SQLITE_WSD struct PCacheGlobal {
-- PGroup grp; /* The global PGroup for mode (2) */
-+/* Round the union size down to the nearest pointer boundary, since that's how
-+** it will be aligned within the Bitvec struct. */
-+#define BITVEC_USIZE (((BITVEC_SZ-(3*sizeof(u32)))/sizeof(Bitvec*))*sizeof(Bitvec*))
-
-- /* Variables related to SQLITE_CONFIG_PAGECACHE settings. The
-- ** szSlot, nSlot, pStart, pEnd, nReserve, and isInit values are all
-- ** fixed at sqlite3_initialize() time and do not require mutex protection.
-- ** The nFreeSlot and pFree values do require mutex protection.
-- */
-- int isInit; /* True if initialized */
-- int szSlot; /* Size of each free slot */
-- int nSlot; /* The number of pcache slots */
-- int nReserve; /* Try to keep nFreeSlot above this */
-- void *pStart, *pEnd; /* Bounds of pagecache malloc range */
-- /* Above requires no mutex. Use mutex below for variable that follow. */
-- sqlite3_mutex *mutex; /* Mutex for accessing the following: */
-- PgFreeslot *pFree; /* Free page blocks */
-- int nFreeSlot; /* Number of unused pcache slots */
-- /* The following value requires a mutex to change. We skip the mutex on
-- ** reading because (1) most platforms read a 32-bit integer atomically and
-- ** (2) even if an incorrect value is read, no great harm is done since this
-- ** is really just an optimization. */
-- int bUnderPressure; /* True if low on PAGECACHE memory */
--} pcache1_g;
-+/* Type of the array "element" for the bitmap representation.
-+** Should be a power of 2, and ideally, evenly divide into BITVEC_USIZE.
-+** Setting this to the "natural word" size of your CPU may improve
-+** performance. */
-+#define BITVEC_TELEM u8
-+/* Size, in bits, of the bitmap element. */
-+#define BITVEC_SZELEM 8
-+/* Number of elements in a bitmap array. */
-+#define BITVEC_NELEM (BITVEC_USIZE/sizeof(BITVEC_TELEM))
-+/* Number of bits in the bitmap array. */
-+#define BITVEC_NBIT (BITVEC_NELEM*BITVEC_SZELEM)
-
--/*
--** All code in this file should access the global structure above via the
--** alias "pcache1". This ensures that the WSD emulation is used when
--** compiling for systems that do not support real WSD.
--*/
--#define pcache1 (GLOBAL(struct PCacheGlobal, pcache1_g))
-+/* Number of u32 values in hash table. */
-+#define BITVEC_NINT (BITVEC_USIZE/sizeof(u32))
-+/* Maximum number of entries in hash table before
-+** sub-dividing and re-hashing. */
-+#define BITVEC_MXHASH (BITVEC_NINT/2)
-+/* Hashing function for the aHash representation.
-+** Empirical testing showed that the *37 multiplier
-+** (an arbitrary prime)in the hash function provided
-+** no fewer collisions than the no-op *1. */
-+#define BITVEC_HASH(X) (((X)*1)%BITVEC_NINT)
-
--/*
--** Macros to enter and leave the PCache LRU mutex.
--*/
--#define pcache1EnterMutex(X) sqlite3_mutex_enter((X)->mutex)
--#define pcache1LeaveMutex(X) sqlite3_mutex_leave((X)->mutex)
-+#define BITVEC_NPTR (BITVEC_USIZE/sizeof(Bitvec *))
-
--/******************************************************************************/
--/******** Page Allocation/SQLITE_CONFIG_PCACHE Related Functions **************/
-
- /*
--** This function is called during initialization if a static buffer is
--** supplied to use for the page-cache by passing the SQLITE_CONFIG_PAGECACHE
--** verb to sqlite3_config(). Parameter pBuf points to an allocation large
--** enough to contain 'n' buffers of 'sz' bytes each.
-+** A bitmap is an instance of the following structure.
- **
--** This routine is called from sqlite3_initialize() and so it is guaranteed
--** to be serialized already. There is no need for further mutexing.
-+** This bitmap records the existence of zero or more bits
-+** with values between 1 and iSize, inclusive.
-+**
-+** There are three possible representations of the bitmap.
-+** If iSize<=BITVEC_NBIT, then Bitvec.u.aBitmap[] is a straight
-+** bitmap. The least significant bit is bit 1.
-+**
-+** If iSize>BITVEC_NBIT and iDivisor==0 then Bitvec.u.aHash[] is
-+** a hash table that will hold up to BITVEC_MXHASH distinct values.
-+**
-+** Otherwise, the value i is redirected into one of BITVEC_NPTR
-+** sub-bitmaps pointed to by Bitvec.u.apSub[]. Each subbitmap
-+** handles up to iDivisor separate values of i. apSub[0] holds
-+** values between 1 and iDivisor. apSub[1] holds values between
-+** iDivisor+1 and 2*iDivisor. apSub[N] holds values between
-+** N*iDivisor+1 and (N+1)*iDivisor. Each subbitmap is normalized
-+** to hold deal with values between 1 and iDivisor.
- */
--SQLITE_PRIVATE void sqlite3PCacheBufferSetup(void *pBuf, int sz, int n){
-- if( pcache1.isInit ){
-- PgFreeslot *p;
-- sz = ROUNDDOWN8(sz);
-- pcache1.szSlot = sz;
-- pcache1.nSlot = pcache1.nFreeSlot = n;
-- pcache1.nReserve = n>90 ? 10 : (n/10 + 1);
-- pcache1.pStart = pBuf;
-- pcache1.pFree = 0;
-- pcache1.bUnderPressure = 0;
-- while( n-- ){
-- p = (PgFreeslot*)pBuf;
-- p->pNext = pcache1.pFree;
-- pcache1.pFree = p;
-- pBuf = (void*)&((char*)pBuf)[sz];
-- }
-- pcache1.pEnd = pBuf;
-- }
--}
-+struct Bitvec {
-+ u32 iSize; /* Maximum bit index. Max iSize is 4,294,967,296. */
-+ u32 nSet; /* Number of bits that are set - only valid for aHash
-+ ** element. Max is BITVEC_NINT. For BITVEC_SZ of 512,
-+ ** this would be 125. */
-+ u32 iDivisor; /* Number of bits handled by each apSub[] entry. */
-+ /* Should >=0 for apSub element. */
-+ /* Max iDivisor is max(u32) / BITVEC_NPTR + 1. */
-+ /* For a BITVEC_SZ of 512, this would be 34,359,739. */
-+ union {
-+ BITVEC_TELEM aBitmap[BITVEC_NELEM]; /* Bitmap representation */
-+ u32 aHash[BITVEC_NINT]; /* Hash table representation */
-+ Bitvec *apSub[BITVEC_NPTR]; /* Recursive representation */
-+ } u;
-+};
-
- /*
--** Malloc function used within this file to allocate space from the buffer
--** configured using sqlite3_config(SQLITE_CONFIG_PAGECACHE) option. If no
--** such buffer exists or there is no space left in it, this function falls
--** back to sqlite3Malloc().
--**
--** Multiple threads can run this routine at the same time. Global variables
--** in pcache1 need to be protected via mutex.
--*/
--static void *pcache1Alloc(int nByte){
-- void *p = 0;
-- assert( sqlite3_mutex_notheld(pcache1.grp.mutex) );
-- sqlite3StatusSet(SQLITE_STATUS_PAGECACHE_SIZE, nByte);
-- if( nByte<=pcache1.szSlot ){
-- sqlite3_mutex_enter(pcache1.mutex);
-- p = (PgHdr1 *)pcache1.pFree;
-- if( p ){
-- pcache1.pFree = pcache1.pFree->pNext;
-- pcache1.nFreeSlot--;
-- pcache1.bUnderPressure = pcache1.nFreeSlot<pcache1.nReserve;
-- assert( pcache1.nFreeSlot>=0 );
-- sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_USED, 1);
-- }
-- sqlite3_mutex_leave(pcache1.mutex);
-- }
-- if( p==0 ){
-- /* Memory is not available in the SQLITE_CONFIG_PAGECACHE pool. Get
-- ** it from sqlite3Malloc instead.
-- */
-- p = sqlite3Malloc(nByte);
--#ifndef SQLITE_DISABLE_PAGECACHE_OVERFLOW_STATS
-- if( p ){
-- int sz = sqlite3MallocSize(p);
-- sqlite3_mutex_enter(pcache1.mutex);
-- sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_OVERFLOW, sz);
-- sqlite3_mutex_leave(pcache1.mutex);
-- }
--#endif
-- sqlite3MemdebugSetType(p, MEMTYPE_PCACHE);
-+** Create a new bitmap object able to handle bits between 0 and iSize,
-+** inclusive. Return a pointer to the new object. Return NULL if
-+** malloc fails.
-+*/
-+SQLITE_PRIVATE Bitvec *sqlite3BitvecCreate(u32 iSize){
-+ Bitvec *p;
-+ assert( sizeof(*p)==BITVEC_SZ );
-+ p = sqlite3MallocZero( sizeof(*p) );
-+ if( p ){
-+ p->iSize = iSize;
- }
- return p;
- }
-
- /*
--** Free an allocated buffer obtained from pcache1Alloc().
-+** Check to see if the i-th bit is set. Return true or false.
-+** If p is NULL (if the bitmap has not been created) or if
-+** i is out of range, then return false.
- */
--static int pcache1Free(void *p){
-- int nFreed = 0;
-+SQLITE_PRIVATE int sqlite3BitvecTest(Bitvec *p, u32 i){
- if( p==0 ) return 0;
-- if( p>=pcache1.pStart && p<pcache1.pEnd ){
-- PgFreeslot *pSlot;
-- sqlite3_mutex_enter(pcache1.mutex);
-- sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_USED, -1);
-- pSlot = (PgFreeslot*)p;
-- pSlot->pNext = pcache1.pFree;
-- pcache1.pFree = pSlot;
-- pcache1.nFreeSlot++;
-- pcache1.bUnderPressure = pcache1.nFreeSlot<pcache1.nReserve;
-- assert( pcache1.nFreeSlot<=pcache1.nSlot );
-- sqlite3_mutex_leave(pcache1.mutex);
-- }else{
-- assert( sqlite3MemdebugHasType(p, MEMTYPE_PCACHE) );
-- sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
-- nFreed = sqlite3MallocSize(p);
--#ifndef SQLITE_DISABLE_PAGECACHE_OVERFLOW_STATS
-- sqlite3_mutex_enter(pcache1.mutex);
-- sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_OVERFLOW, -nFreed);
-- sqlite3_mutex_leave(pcache1.mutex);
--#endif
-- sqlite3_free(p);
-+ if( i>p->iSize || i==0 ) return 0;
-+ i--;
-+ while( p->iDivisor ){
-+ u32 bin = i/p->iDivisor;
-+ i = i%p->iDivisor;
-+ p = p->u.apSub[bin];
-+ if (!p) {
-+ return 0;
-+ }
-+ }
-+ if( p->iSize<=BITVEC_NBIT ){
-+ return (p->u.aBitmap[i/BITVEC_SZELEM] & (1<<(i&(BITVEC_SZELEM-1))))!=0;
-+ } else{
-+ u32 h = BITVEC_HASH(i++);
-+ while( p->u.aHash[h] ){
-+ if( p->u.aHash[h]==i ) return 1;
-+ h = (h+1) % BITVEC_NINT;
-+ }
-+ return 0;
- }
-- return nFreed;
- }
-
--#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
- /*
--** Return the size of a pcache allocation
-+** Set the i-th bit. Return 0 on success and an error code if
-+** anything goes wrong.
-+**
-+** This routine might cause sub-bitmaps to be allocated. Failing
-+** to get the memory needed to hold the sub-bitmap is the only
-+** that can go wrong with an insert, assuming p and i are valid.
-+**
-+** The calling function must ensure that p is a valid Bitvec object
-+** and that the value for "i" is within range of the Bitvec object.
-+** Otherwise the behavior is undefined.
- */
--static int pcache1MemSize(void *p){
-- if( p>=pcache1.pStart && p<pcache1.pEnd ){
-- return pcache1.szSlot;
-- }else{
-- int iSize;
-- assert( sqlite3MemdebugHasType(p, MEMTYPE_PCACHE) );
-- sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
-- iSize = sqlite3MallocSize(p);
-- sqlite3MemdebugSetType(p, MEMTYPE_PCACHE);
-- return iSize;
-+SQLITE_PRIVATE int sqlite3BitvecSet(Bitvec *p, u32 i){
-+ u32 h;
-+ if( p==0 ) return SQLITE_OK;
-+ assert( i>0 );
-+ assert( i<=p->iSize );
-+ i--;
-+ while((p->iSize > BITVEC_NBIT) && p->iDivisor) {
-+ u32 bin = i/p->iDivisor;
-+ i = i%p->iDivisor;
-+ if( p->u.apSub[bin]==0 ){
-+ p->u.apSub[bin] = sqlite3BitvecCreate( p->iDivisor );
-+ if( p->u.apSub[bin]==0 ) return SQLITE_NOMEM;
-+ }
-+ p = p->u.apSub[bin];
-+ }
-+ if( p->iSize<=BITVEC_NBIT ){
-+ p->u.aBitmap[i/BITVEC_SZELEM] |= 1 << (i&(BITVEC_SZELEM-1));
-+ return SQLITE_OK;
-+ }
-+ h = BITVEC_HASH(i++);
-+ /* if there wasn't a hash collision, and this doesn't */
-+ /* completely fill the hash, then just add it without */
-+ /* worring about sub-dividing and re-hashing. */
-+ if( !p->u.aHash[h] ){
-+ if (p->nSet<(BITVEC_NINT-1)) {
-+ goto bitvec_set_end;
-+ } else {
-+ goto bitvec_set_rehash;
-+ }
-+ }
-+ /* there was a collision, check to see if it's already */
-+ /* in hash, if not, try to find a spot for it */
-+ do {
-+ if( p->u.aHash[h]==i ) return SQLITE_OK;
-+ h++;
-+ if( h>=BITVEC_NINT ) h = 0;
-+ } while( p->u.aHash[h] );
-+ /* we didn't find it in the hash. h points to the first */
-+ /* available free spot. check to see if this is going to */
-+ /* make our hash too "full". */
-+bitvec_set_rehash:
-+ if( p->nSet>=BITVEC_MXHASH ){
-+ unsigned int j;
-+ int rc;
-+ u32 *aiValues = sqlite3StackAllocRaw(0, sizeof(p->u.aHash));
-+ if( aiValues==0 ){
-+ return SQLITE_NOMEM;
-+ }else{
-+ memcpy(aiValues, p->u.aHash, sizeof(p->u.aHash));
-+ memset(p->u.apSub, 0, sizeof(p->u.apSub));
-+ p->iDivisor = (p->iSize + BITVEC_NPTR - 1)/BITVEC_NPTR;
-+ rc = sqlite3BitvecSet(p, i);
-+ for(j=0; j<BITVEC_NINT; j++){
-+ if( aiValues[j] ) rc |= sqlite3BitvecSet(p, aiValues[j]);
-+ }
-+ sqlite3StackFree(0, aiValues);
-+ return rc;
-+ }
- }
-+bitvec_set_end:
-+ p->nSet++;
-+ p->u.aHash[h] = i;
-+ return SQLITE_OK;
- }
--#endif /* SQLITE_ENABLE_MEMORY_MANAGEMENT */
-
- /*
--** Allocate a new page object initially associated with cache pCache.
-+** Clear the i-th bit.
-+**
-+** pBuf must be a pointer to at least BITVEC_SZ bytes of temporary storage
-+** that BitvecClear can use to rebuilt its hash table.
- */
--static PgHdr1 *pcache1AllocPage(PCache1 *pCache){
-- PgHdr1 *p = 0;
-- void *pPg;
--
-- /* The group mutex must be released before pcache1Alloc() is called. This
-- ** is because it may call sqlite3_release_memory(), which assumes that
-- ** this mutex is not held. */
-- assert( sqlite3_mutex_held(pCache->pGroup->mutex) );
-- pcache1LeaveMutex(pCache->pGroup);
--#ifdef SQLITE_PCACHE_SEPARATE_HEADER
-- pPg = pcache1Alloc(pCache->szPage);
-- p = sqlite3Malloc(sizeof(PgHdr1) + pCache->szExtra);
-- if( !pPg || !p ){
-- pcache1Free(pPg);
-- sqlite3_free(p);
-- pPg = 0;
-+SQLITE_PRIVATE void sqlite3BitvecClear(Bitvec *p, u32 i, void *pBuf){
-+ if( p==0 ) return;
-+ assert( i>0 );
-+ i--;
-+ while( p->iDivisor ){
-+ u32 bin = i/p->iDivisor;
-+ i = i%p->iDivisor;
-+ p = p->u.apSub[bin];
-+ if (!p) {
-+ return;
-+ }
- }
--#else
-- pPg = pcache1Alloc(sizeof(PgHdr1) + pCache->szPage + pCache->szExtra);
-- p = (PgHdr1 *)&((u8 *)pPg)[pCache->szPage];
--#endif
-- pcache1EnterMutex(pCache->pGroup);
--
-- if( pPg ){
-- p->page.pBuf = pPg;
-- p->page.pExtra = &p[1];
-- if( pCache->bPurgeable ){
-- pCache->pGroup->nCurrentPage++;
-+ if( p->iSize<=BITVEC_NBIT ){
-+ p->u.aBitmap[i/BITVEC_SZELEM] &= ~(1 << (i&(BITVEC_SZELEM-1)));
-+ }else{
-+ unsigned int j;
-+ u32 *aiValues = pBuf;
-+ memcpy(aiValues, p->u.aHash, sizeof(p->u.aHash));
-+ memset(p->u.aHash, 0, sizeof(p->u.aHash));
-+ p->nSet = 0;
-+ for(j=0; j<BITVEC_NINT; j++){
-+ if( aiValues[j] && aiValues[j]!=(i+1) ){
-+ u32 h = BITVEC_HASH(aiValues[j]-1);
-+ p->nSet++;
-+ while( p->u.aHash[h] ){
-+ h++;
-+ if( h>=BITVEC_NINT ) h = 0;
-+ }
-+ p->u.aHash[h] = aiValues[j];
-+ }
- }
-- return p;
- }
-- return 0;
- }
-
- /*
--** Free a page object allocated by pcache1AllocPage().
--**
--** The pointer is allowed to be NULL, which is prudent. But it turns out
--** that the current implementation happens to never call this routine
--** with a NULL pointer, so we mark the NULL test with ALWAYS().
-+** Destroy a bitmap object. Reclaim all memory used.
- */
--static void pcache1FreePage(PgHdr1 *p){
-- if( ALWAYS(p) ){
-- PCache1 *pCache = p->pCache;
-- assert( sqlite3_mutex_held(p->pCache->pGroup->mutex) );
-- pcache1Free(p->page.pBuf);
--#ifdef SQLITE_PCACHE_SEPARATE_HEADER
-- sqlite3_free(p);
--#endif
-- if( pCache->bPurgeable ){
-- pCache->pGroup->nCurrentPage--;
-+SQLITE_PRIVATE void sqlite3BitvecDestroy(Bitvec *p){
-+ if( p==0 ) return;
-+ if( p->iDivisor ){
-+ unsigned int i;
-+ for(i=0; i<BITVEC_NPTR; i++){
-+ sqlite3BitvecDestroy(p->u.apSub[i]);
- }
- }
-+ sqlite3_free(p);
- }
-
- /*
--** Malloc function used by SQLite to obtain space from the buffer configured
--** using sqlite3_config(SQLITE_CONFIG_PAGECACHE) option. If no such buffer
--** exists, this function falls back to sqlite3Malloc().
-+** Return the value of the iSize parameter specified when Bitvec *p
-+** was created.
- */
--SQLITE_PRIVATE void *sqlite3PageMalloc(int sz){
-- return pcache1Alloc(sz);
-+SQLITE_PRIVATE u32 sqlite3BitvecSize(Bitvec *p){
-+ return p->iSize;
- }
-
-+#ifndef SQLITE_OMIT_BUILTIN_TEST
- /*
--** Free an allocated buffer obtained from sqlite3PageMalloc().
-+** Let V[] be an array of unsigned characters sufficient to hold
-+** up to N bits. Let I be an integer between 0 and N. 0<=I<N.
-+** Then the following macros can be used to set, clear, or test
-+** individual bits within V.
- */
--SQLITE_PRIVATE void sqlite3PageFree(void *p){
-- pcache1Free(p);
--}
--
-+#define SETBIT(V,I) V[I>>3] |= (1<<(I&7))
-+#define CLEARBIT(V,I) V[I>>3] &= ~(1<<(I&7))
-+#define TESTBIT(V,I) (V[I>>3]&(1<<(I&7)))!=0
-
- /*
--** Return true if it desirable to avoid allocating a new page cache
--** entry.
-+** This routine runs an extensive test of the Bitvec code.
- **
--** If memory was allocated specifically to the page cache using
--** SQLITE_CONFIG_PAGECACHE but that memory has all been used, then
--** it is desirable to avoid allocating a new page cache entry because
--** presumably SQLITE_CONFIG_PAGECACHE was suppose to be sufficient
--** for all page cache needs and we should not need to spill the
--** allocation onto the heap.
-+** The input is an array of integers that acts as a program
-+** to test the Bitvec. The integers are opcodes followed
-+** by 0, 1, or 3 operands, depending on the opcode. Another
-+** opcode follows immediately after the last operand.
- **
--** Or, the heap is used for all page cache memory but the heap is
--** under memory pressure, then again it is desirable to avoid
--** allocating a new page cache entry in order to avoid stressing
--** the heap even further.
--*/
--static int pcache1UnderMemoryPressure(PCache1 *pCache){
-- if( pcache1.nSlot && (pCache->szPage+pCache->szExtra)<=pcache1.szSlot ){
-- return pcache1.bUnderPressure;
-- }else{
-- return sqlite3HeapNearlyFull();
-- }
--}
--
--/******************************************************************************/
--/******** General Implementation Functions ************************************/
--
--/*
--** This function is used to resize the hash table used by the cache passed
--** as the first argument.
-+** There are 6 opcodes numbered from 0 through 5. 0 is the
-+** "halt" opcode and causes the test to end.
- **
--** The PCache mutex must be held when this function is called.
-+** 0 Halt and return the number of errors
-+** 1 N S X Set N bits beginning with S and incrementing by X
-+** 2 N S X Clear N bits beginning with S and incrementing by X
-+** 3 N Set N randomly chosen bits
-+** 4 N Clear N randomly chosen bits
-+** 5 N S X Set N bits from S increment X in array only, not in bitvec
-+**
-+** The opcodes 1 through 4 perform set and clear operations are performed
-+** on both a Bitvec object and on a linear array of bits obtained from malloc.
-+** Opcode 5 works on the linear array only, not on the Bitvec.
-+** Opcode 5 is used to deliberately induce a fault in order to
-+** confirm that error detection works.
-+**
-+** At the conclusion of the test the linear array is compared
-+** against the Bitvec object. If there are any differences,
-+** an error is returned. If they are the same, zero is returned.
-+**
-+** If a memory allocation error occurs, return -1.
- */
--static int pcache1ResizeHash(PCache1 *p){
-- PgHdr1 **apNew;
-- unsigned int nNew;
-- unsigned int i;
-+SQLITE_PRIVATE int sqlite3BitvecBuiltinTest(int sz, int *aOp){
-+ Bitvec *pBitvec = 0;
-+ unsigned char *pV = 0;
-+ int rc = -1;
-+ int i, nx, pc, op;
-+ void *pTmpSpace;
-
-- assert( sqlite3_mutex_held(p->pGroup->mutex) );
-+ /* Allocate the Bitvec to be tested and a linear array of
-+ ** bits to act as the reference */
-+ pBitvec = sqlite3BitvecCreate( sz );
-+ pV = sqlite3MallocZero( (sz+7)/8 + 1 );
-+ pTmpSpace = sqlite3_malloc(BITVEC_SZ);
-+ if( pBitvec==0 || pV==0 || pTmpSpace==0 ) goto bitvec_end;
-
-- nNew = p->nHash*2;
-- if( nNew<256 ){
-- nNew = 256;
-- }
-+ /* NULL pBitvec tests */
-+ sqlite3BitvecSet(0, 1);
-+ sqlite3BitvecClear(0, 1, pTmpSpace);
-
-- pcache1LeaveMutex(p->pGroup);
-- if( p->nHash ){ sqlite3BeginBenignMalloc(); }
-- apNew = (PgHdr1 **)sqlite3MallocZero(sizeof(PgHdr1 *)*nNew);
-- if( p->nHash ){ sqlite3EndBenignMalloc(); }
-- pcache1EnterMutex(p->pGroup);
-- if( apNew ){
-- for(i=0; i<p->nHash; i++){
-- PgHdr1 *pPage;
-- PgHdr1 *pNext = p->apHash[i];
-- while( (pPage = pNext)!=0 ){
-- unsigned int h = pPage->iKey % nNew;
-- pNext = pPage->pNext;
-- pPage->pNext = apNew[h];
-- apNew[h] = pPage;
-+ /* Run the program */
-+ pc = 0;
-+ while( (op = aOp[pc])!=0 ){
-+ switch( op ){
-+ case 1:
-+ case 2:
-+ case 5: {
-+ nx = 4;
-+ i = aOp[pc+2] - 1;
-+ aOp[pc+2] += aOp[pc+3];
-+ break;
-+ }
-+ case 3:
-+ case 4:
-+ default: {
-+ nx = 2;
-+ sqlite3_randomness(sizeof(i), &i);
-+ break;
- }
- }
-- sqlite3_free(p->apHash);
-- p->apHash = apNew;
-- p->nHash = nNew;
-+ if( (--aOp[pc+1]) > 0 ) nx = 0;
-+ pc += nx;
-+ i = (i & 0x7fffffff)%sz;
-+ if( (op & 1)!=0 ){
-+ SETBIT(pV, (i+1));
-+ if( op!=5 ){
-+ if( sqlite3BitvecSet(pBitvec, i+1) ) goto bitvec_end;
-+ }
-+ }else{
-+ CLEARBIT(pV, (i+1));
-+ sqlite3BitvecClear(pBitvec, i+1, pTmpSpace);
-+ }
- }
-
-- return (p->apHash ? SQLITE_OK : SQLITE_NOMEM);
-+ /* Test to make sure the linear array exactly matches the
-+ ** Bitvec object. Start with the assumption that they do
-+ ** match (rc==0). Change rc to non-zero if a discrepancy
-+ ** is found.
-+ */
-+ rc = sqlite3BitvecTest(0,0) + sqlite3BitvecTest(pBitvec, sz+1)
-+ + sqlite3BitvecTest(pBitvec, 0)
-+ + (sqlite3BitvecSize(pBitvec) - sz);
-+ for(i=1; i<=sz; i++){
-+ if( (TESTBIT(pV,i))!=sqlite3BitvecTest(pBitvec,i) ){
-+ rc = i;
-+ break;
-+ }
-+ }
-+
-+ /* Free allocated structure */
-+bitvec_end:
-+ sqlite3_free(pTmpSpace);
-+ sqlite3_free(pV);
-+ sqlite3BitvecDestroy(pBitvec);
-+ return rc;
- }
-+#endif /* SQLITE_OMIT_BUILTIN_TEST */
-
-+/************** End of bitvec.c **********************************************/
-+/************** Begin file pcache.c ******************************************/
- /*
--** This function is used internally to remove the page pPage from the
--** PGroup LRU list, if is part of it. If pPage is not part of the PGroup
--** LRU list, then this function is a no-op.
-+** 2008 August 05
- **
--** The PGroup mutex must be held when this function is called.
-+** The author disclaims copyright to this source code. In place of
-+** a legal notice, here is a blessing:
- **
--** If pPage is NULL then this routine is a no-op.
-+** May you do good and not evil.
-+** May you find forgiveness for yourself and forgive others.
-+** May you share freely, never taking more than you give.
-+**
-+*************************************************************************
-+** This file implements that page cache.
- */
--static void pcache1PinPage(PgHdr1 *pPage){
-- PCache1 *pCache;
-- PGroup *pGroup;
-
-- if( pPage==0 ) return;
-- pCache = pPage->pCache;
-- pGroup = pCache->pGroup;
-- assert( sqlite3_mutex_held(pGroup->mutex) );
-- if( pPage->pLruNext || pPage==pGroup->pLruTail ){
-- if( pPage->pLruPrev ){
-- pPage->pLruPrev->pLruNext = pPage->pLruNext;
-- }
-- if( pPage->pLruNext ){
-- pPage->pLruNext->pLruPrev = pPage->pLruPrev;
-- }
-- if( pGroup->pLruHead==pPage ){
-- pGroup->pLruHead = pPage->pLruNext;
-- }
-- if( pGroup->pLruTail==pPage ){
-- pGroup->pLruTail = pPage->pLruPrev;
-- }
-- pPage->pLruNext = 0;
-- pPage->pLruPrev = 0;
-- pPage->pCache->nRecyclable--;
-- }
--}
-+/*
-+** A complete page cache is an instance of this structure.
-+*/
-+struct PCache {
-+ PgHdr *pDirty, *pDirtyTail; /* List of dirty pages in LRU order */
-+ PgHdr *pSynced; /* Last synced page in dirty page list */
-+ int nRef; /* Number of referenced pages */
-+ int szCache; /* Configured cache size */
-+ int szPage; /* Size of every page in this cache */
-+ int szExtra; /* Size of extra space for each page */
-+ int bPurgeable; /* True if pages are on backing store */
-+ int (*xStress)(void*,PgHdr*); /* Call to try make a page clean */
-+ void *pStress; /* Argument to xStress */
-+ sqlite3_pcache *pCache; /* Pluggable cache module */
-+ PgHdr *pPage1; /* Reference to page 1 */
-+};
-+
-+/*
-+** Some of the assert() macros in this code are too expensive to run
-+** even during normal debugging. Use them only rarely on long-running
-+** tests. Enable the expensive asserts using the
-+** -DSQLITE_ENABLE_EXPENSIVE_ASSERT=1 compile-time option.
-+*/
-+#ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT
-+# define expensive_assert(X) assert(X)
-+#else
-+# define expensive_assert(X)
-+#endif
-
-+/********************************** Linked List Management ********************/
-
-+#if !defined(NDEBUG) && defined(SQLITE_ENABLE_EXPENSIVE_ASSERT)
- /*
--** Remove the page supplied as an argument from the hash table
--** (PCache1.apHash structure) that it is currently stored in.
-+** Check that the pCache->pSynced variable is set correctly. If it
-+** is not, either fail an assert or return zero. Otherwise, return
-+** non-zero. This is only used in debugging builds, as follows:
- **
--** The PGroup mutex must be held when this function is called.
-+** expensive_assert( pcacheCheckSynced(pCache) );
- */
--static void pcache1RemoveFromHash(PgHdr1 *pPage){
-- unsigned int h;
-- PCache1 *pCache = pPage->pCache;
-- PgHdr1 **pp;
-+static int pcacheCheckSynced(PCache *pCache){
-+ PgHdr *p;
-+ for(p=pCache->pDirtyTail; p!=pCache->pSynced; p=p->pDirtyPrev){
-+ assert( p->nRef || (p->flags&PGHDR_NEED_SYNC) );
-+ }
-+ return (p==0 || p->nRef || (p->flags&PGHDR_NEED_SYNC)==0);
-+}
-+#endif /* !NDEBUG && SQLITE_ENABLE_EXPENSIVE_ASSERT */
-
-- assert( sqlite3_mutex_held(pCache->pGroup->mutex) );
-- h = pPage->iKey % pCache->nHash;
-- for(pp=&pCache->apHash[h]; (*pp)!=pPage; pp=&(*pp)->pNext);
-- *pp = (*pp)->pNext;
-+/*
-+** Remove page pPage from the list of dirty pages.
-+*/
-+static void pcacheRemoveFromDirtyList(PgHdr *pPage){
-+ PCache *p = pPage->pCache;
-+
-+ assert( pPage->pDirtyNext || pPage==p->pDirtyTail );
-+ assert( pPage->pDirtyPrev || pPage==p->pDirty );
-+
-+ /* Update the PCache1.pSynced variable if necessary. */
-+ if( p->pSynced==pPage ){
-+ PgHdr *pSynced = pPage->pDirtyPrev;
-+ while( pSynced && (pSynced->flags&PGHDR_NEED_SYNC) ){
-+ pSynced = pSynced->pDirtyPrev;
-+ }
-+ p->pSynced = pSynced;
-+ }
-+
-+ if( pPage->pDirtyNext ){
-+ pPage->pDirtyNext->pDirtyPrev = pPage->pDirtyPrev;
-+ }else{
-+ assert( pPage==p->pDirtyTail );
-+ p->pDirtyTail = pPage->pDirtyPrev;
-+ }
-+ if( pPage->pDirtyPrev ){
-+ pPage->pDirtyPrev->pDirtyNext = pPage->pDirtyNext;
-+ }else{
-+ assert( pPage==p->pDirty );
-+ p->pDirty = pPage->pDirtyNext;
-+ }
-+ pPage->pDirtyNext = 0;
-+ pPage->pDirtyPrev = 0;
-
-- pCache->nPage--;
-+ expensive_assert( pcacheCheckSynced(p) );
- }
-
- /*
--** If there are currently more than nMaxPage pages allocated, try
--** to recycle pages to reduce the number allocated to nMaxPage.
-+** Add page pPage to the head of the dirty list (PCache1.pDirty is set to
-+** pPage).
- */
--static void pcache1EnforceMaxPage(PGroup *pGroup){
-- assert( sqlite3_mutex_held(pGroup->mutex) );
-- while( pGroup->nCurrentPage>pGroup->nMaxPage && pGroup->pLruTail ){
-- PgHdr1 *p = pGroup->pLruTail;
-- assert( p->pCache->pGroup==pGroup );
-- pcache1PinPage(p);
-- pcache1RemoveFromHash(p);
-- pcache1FreePage(p);
-+static void pcacheAddToDirtyList(PgHdr *pPage){
-+ PCache *p = pPage->pCache;
-+
-+ assert( pPage->pDirtyNext==0 && pPage->pDirtyPrev==0 && p->pDirty!=pPage );
-+
-+ pPage->pDirtyNext = p->pDirty;
-+ if( pPage->pDirtyNext ){
-+ assert( pPage->pDirtyNext->pDirtyPrev==0 );
-+ pPage->pDirtyNext->pDirtyPrev = pPage;
- }
-+ p->pDirty = pPage;
-+ if( !p->pDirtyTail ){
-+ p->pDirtyTail = pPage;
-+ }
-+ if( !p->pSynced && 0==(pPage->flags&PGHDR_NEED_SYNC) ){
-+ p->pSynced = pPage;
-+ }
-+ expensive_assert( pcacheCheckSynced(p) );
- }
-
- /*
--** Discard all pages from cache pCache with a page number (key value)
--** greater than or equal to iLimit. Any pinned pages that meet this
--** criteria are unpinned before they are discarded.
--**
--** The PCache mutex must be held when this function is called.
-+** Wrapper around the pluggable caches xUnpin method. If the cache is
-+** being used for an in-memory database, this function is a no-op.
- */
--static void pcache1TruncateUnsafe(
-- PCache1 *pCache, /* The cache to truncate */
-- unsigned int iLimit /* Drop pages with this pgno or larger */
--){
-- TESTONLY( unsigned int nPage = 0; ) /* To assert pCache->nPage is correct */
-- unsigned int h;
-- assert( sqlite3_mutex_held(pCache->pGroup->mutex) );
-- for(h=0; h<pCache->nHash; h++){
-- PgHdr1 **pp = &pCache->apHash[h];
-- PgHdr1 *pPage;
-- while( (pPage = *pp)!=0 ){
-- if( pPage->iKey>=iLimit ){
-- pCache->nPage--;
-- *pp = pPage->pNext;
-- pcache1PinPage(pPage);
-- pcache1FreePage(pPage);
-- }else{
-- pp = &pPage->pNext;
-- TESTONLY( nPage++; )
-- }
-+static void pcacheUnpin(PgHdr *p){
-+ PCache *pCache = p->pCache;
-+ if( pCache->bPurgeable ){
-+ if( p->pgno==1 ){
-+ pCache->pPage1 = 0;
- }
-+ sqlite3GlobalConfig.pcache2.xUnpin(pCache->pCache, p->pPage, 0);
- }
-- assert( pCache->nPage==nPage );
- }
-
--/******************************************************************************/
--/******** sqlite3_pcache Methods **********************************************/
--
--/*
--** Implementation of the sqlite3_pcache.xInit method.
-+/*************************************************** General Interfaces ******
-+**
-+** Initialize and shutdown the page cache subsystem. Neither of these
-+** functions are threadsafe.
- */
--static int pcache1Init(void *NotUsed){
-- UNUSED_PARAMETER(NotUsed);
-- assert( pcache1.isInit==0 );
-- memset(&pcache1, 0, sizeof(pcache1));
-- if( sqlite3GlobalConfig.bCoreMutex ){
-- pcache1.grp.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_LRU);
-- pcache1.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_PMEM);
-+SQLITE_PRIVATE int sqlite3PcacheInitialize(void){
-+ if( sqlite3GlobalConfig.pcache2.xInit==0 ){
-+ /* IMPLEMENTATION-OF: R-26801-64137 If the xInit() method is NULL, then the
-+ ** built-in default page cache is used instead of the application defined
-+ ** page cache. */
-+ sqlite3PCacheSetDefault();
- }
-- pcache1.grp.mxPinned = 10;
-- pcache1.isInit = 1;
-- return SQLITE_OK;
-+ return sqlite3GlobalConfig.pcache2.xInit(sqlite3GlobalConfig.pcache2.pArg);
- }
--
--/*
--** Implementation of the sqlite3_pcache.xShutdown method.
--** Note that the static mutex allocated in xInit does
--** not need to be freed.
--*/
--static void pcache1Shutdown(void *NotUsed){
-- UNUSED_PARAMETER(NotUsed);
-- assert( pcache1.isInit!=0 );
-- memset(&pcache1, 0, sizeof(pcache1));
-+SQLITE_PRIVATE void sqlite3PcacheShutdown(void){
-+ if( sqlite3GlobalConfig.pcache2.xShutdown ){
-+ /* IMPLEMENTATION-OF: R-26000-56589 The xShutdown() method may be NULL. */
-+ sqlite3GlobalConfig.pcache2.xShutdown(sqlite3GlobalConfig.pcache2.pArg);
-+ }
- }
-
- /*
--** Implementation of the sqlite3_pcache.xCreate method.
--**
--** Allocate a new cache.
-+** Return the size in bytes of a PCache object.
- */
--static sqlite3_pcache *pcache1Create(int szPage, int szExtra, int bPurgeable){
-- PCache1 *pCache; /* The newly created page cache */
-- PGroup *pGroup; /* The group the new page cache will belong to */
-- int sz; /* Bytes of memory required to allocate the new cache */
--
-- /*
-- ** The seperateCache variable is true if each PCache has its own private
-- ** PGroup. In other words, separateCache is true for mode (1) where no
-- ** mutexing is required.
-- **
-- ** * Always use a unified cache (mode-2) if ENABLE_MEMORY_MANAGEMENT
-- **
-- ** * Always use a unified cache in single-threaded applications
-- **
-- ** * Otherwise (if multi-threaded and ENABLE_MEMORY_MANAGEMENT is off)
-- ** use separate caches (mode-1)
-- */
--#if defined(SQLITE_ENABLE_MEMORY_MANAGEMENT) || SQLITE_THREADSAFE==0
-- const int separateCache = 0;
--#else
-- int separateCache = sqlite3GlobalConfig.bCoreMutex>0;
--#endif
--
-- assert( (szPage & (szPage-1))==0 && szPage>=512 && szPage<=65536 );
-- assert( szExtra < 300 );
--
-- sz = sizeof(PCache1) + sizeof(PGroup)*separateCache;
-- pCache = (PCache1 *)sqlite3MallocZero(sz);
-- if( pCache ){
-- if( separateCache ){
-- pGroup = (PGroup*)&pCache[1];
-- pGroup->mxPinned = 10;
-- }else{
-- pGroup = &pcache1.grp;
-- }
-- pCache->pGroup = pGroup;
-- pCache->szPage = szPage;
-- pCache->szExtra = szExtra;
-- pCache->bPurgeable = (bPurgeable ? 1 : 0);
-- if( bPurgeable ){
-- pCache->nMin = 10;
-- pcache1EnterMutex(pGroup);
-- pGroup->nMinPage += pCache->nMin;
-- pGroup->mxPinned = pGroup->nMaxPage + 10 - pGroup->nMinPage;
-- pcache1LeaveMutex(pGroup);
-- }
-- }
-- return (sqlite3_pcache *)pCache;
--}
-+SQLITE_PRIVATE int sqlite3PcacheSize(void){ return sizeof(PCache); }
-
- /*
--** Implementation of the sqlite3_pcache.xCachesize method.
--**
--** Configure the cache_size limit for a cache.
-+** Create a new PCache object. Storage space to hold the object
-+** has already been allocated and is passed in as the p pointer.
-+** The caller discovers how much space needs to be allocated by
-+** calling sqlite3PcacheSize().
- */
--static void pcache1Cachesize(sqlite3_pcache *p, int nMax){
-- PCache1 *pCache = (PCache1 *)p;
-- if( pCache->bPurgeable ){
-- PGroup *pGroup = pCache->pGroup;
-- pcache1EnterMutex(pGroup);
-- pGroup->nMaxPage += (nMax - pCache->nMax);
-- pGroup->mxPinned = pGroup->nMaxPage + 10 - pGroup->nMinPage;
-- pCache->nMax = nMax;
-- pCache->n90pct = pCache->nMax*9/10;
-- pcache1EnforceMaxPage(pGroup);
-- pcache1LeaveMutex(pGroup);
-- }
-+SQLITE_PRIVATE void sqlite3PcacheOpen(
-+ int szPage, /* Size of every page */
-+ int szExtra, /* Extra space associated with each page */
-+ int bPurgeable, /* True if pages are on backing store */
-+ int (*xStress)(void*,PgHdr*),/* Call to try to make pages clean */
-+ void *pStress, /* Argument to xStress */
-+ PCache *p /* Preallocated space for the PCache */
-+){
-+ memset(p, 0, sizeof(PCache));
-+ p->szPage = szPage;
-+ p->szExtra = szExtra;
-+ p->bPurgeable = bPurgeable;
-+ p->xStress = xStress;
-+ p->pStress = pStress;
-+ p->szCache = 100;
- }
-
- /*
--** Implementation of the sqlite3_pcache.xShrink method.
--**
--** Free up as much memory as possible.
-+** Change the page size for PCache object. The caller must ensure that there
-+** are no outstanding page references when this function is called.
- */
--static void pcache1Shrink(sqlite3_pcache *p){
-- PCache1 *pCache = (PCache1*)p;
-- if( pCache->bPurgeable ){
-- PGroup *pGroup = pCache->pGroup;
-- int savedMaxPage;
-- pcache1EnterMutex(pGroup);
-- savedMaxPage = pGroup->nMaxPage;
-- pGroup->nMaxPage = 0;
-- pcache1EnforceMaxPage(pGroup);
-- pGroup->nMaxPage = savedMaxPage;
-- pcache1LeaveMutex(pGroup);
-+SQLITE_PRIVATE void sqlite3PcacheSetPageSize(PCache *pCache, int szPage){
-+ assert( pCache->nRef==0 && pCache->pDirty==0 );
-+ if( pCache->pCache ){
-+ sqlite3GlobalConfig.pcache2.xDestroy(pCache->pCache);
-+ pCache->pCache = 0;
-+ pCache->pPage1 = 0;
- }
-+ pCache->szPage = szPage;
- }
-
- /*
--** Implementation of the sqlite3_pcache.xPagecount method.
-+** Compute the number of pages of cache requested.
- */
--static int pcache1Pagecount(sqlite3_pcache *p){
-- int n;
-- PCache1 *pCache = (PCache1*)p;
-- pcache1EnterMutex(pCache->pGroup);
-- n = pCache->nPage;
-- pcache1LeaveMutex(pCache->pGroup);
-- return n;
-+static int numberOfCachePages(PCache *p){
-+ if( p->szCache>=0 ){
-+ return p->szCache;
-+ }else{
-+ return (int)((-1024*(i64)p->szCache)/(p->szPage+p->szExtra));
-+ }
- }
-
- /*
--** Implementation of the sqlite3_pcache.xFetch method.
--**
--** Fetch a page by key value.
--**
--** Whether or not a new page may be allocated by this function depends on
--** the value of the createFlag argument. 0 means do not allocate a new
--** page. 1 means allocate a new page if space is easily available. 2
--** means to try really hard to allocate a new page.
--**
--** For a non-purgeable cache (a cache used as the storage for an in-memory
--** database) there is really no difference between createFlag 1 and 2. So
--** the calling function (pcache.c) will never have a createFlag of 1 on
--** a non-purgeable cache.
--**
--** There are three different approaches to obtaining space for a page,
--** depending on the value of parameter createFlag (which may be 0, 1 or 2).
--**
--** 1. Regardless of the value of createFlag, the cache is searched for a
--** copy of the requested page. If one is found, it is returned.
--**
--** 2. If createFlag==0 and the page is not already in the cache, NULL is
--** returned.
--**
--** 3. If createFlag is 1, and the page is not already in the cache, then
--** return NULL (do not allocate a new page) if any of the following
--** conditions are true:
--**
--** (a) the number of pages pinned by the cache is greater than
--** PCache1.nMax, or
--**
--** (b) the number of pages pinned by the cache is greater than
--** the sum of nMax for all purgeable caches, less the sum of
--** nMin for all other purgeable caches, or
--**
--** 4. If none of the first three conditions apply and the cache is marked
--** as purgeable, and if one of the following is true:
--**
--** (a) The number of pages allocated for the cache is already
--** PCache1.nMax, or
--**
--** (b) The number of pages allocated for all purgeable caches is
--** already equal to or greater than the sum of nMax for all
--** purgeable caches,
--**
--** (c) The system is under memory pressure and wants to avoid
--** unnecessary pages cache entry allocations
--**
--** then attempt to recycle a page from the LRU list. If it is the right
--** size, return the recycled buffer. Otherwise, free the buffer and
--** proceed to step 5.
--**
--** 5. Otherwise, allocate and return a new page buffer.
-+** Try to obtain a page from the cache.
- */
--static sqlite3_pcache_page *pcache1Fetch(
-- sqlite3_pcache *p,
-- unsigned int iKey,
-- int createFlag
-+SQLITE_PRIVATE int sqlite3PcacheFetch(
-+ PCache *pCache, /* Obtain the page from this cache */
-+ Pgno pgno, /* Page number to obtain */
-+ int createFlag, /* If true, create page if it does not exist already */
-+ PgHdr **ppPage /* Write the page here */
- ){
-- unsigned int nPinned;
-- PCache1 *pCache = (PCache1 *)p;
-- PGroup *pGroup;
-- PgHdr1 *pPage = 0;
-+ sqlite3_pcache_page *pPage = 0;
-+ PgHdr *pPgHdr = 0;
-+ int eCreate;
-
-- assert( pCache->bPurgeable || createFlag!=1 );
-- assert( pCache->bPurgeable || pCache->nMin==0 );
-- assert( pCache->bPurgeable==0 || pCache->nMin==10 );
-- assert( pCache->nMin==0 || pCache->bPurgeable );
-- pcache1EnterMutex(pGroup = pCache->pGroup);
-+ assert( pCache!=0 );
-+ assert( createFlag==1 || createFlag==0 );
-+ assert( pgno>0 );
-
-- /* Step 1: Search the hash table for an existing entry. */
-- if( pCache->nHash>0 ){
-- unsigned int h = iKey % pCache->nHash;
-- for(pPage=pCache->apHash[h]; pPage&&pPage->iKey!=iKey; pPage=pPage->pNext);
-+ /* If the pluggable cache (sqlite3_pcache*) has not been allocated,
-+ ** allocate it now.
-+ */
-+ if( !pCache->pCache && createFlag ){
-+ sqlite3_pcache *p;
-+ p = sqlite3GlobalConfig.pcache2.xCreate(
-+ pCache->szPage, pCache->szExtra + sizeof(PgHdr), pCache->bPurgeable
-+ );
-+ if( !p ){
-+ return SQLITE_NOMEM;
-+ }
-+ sqlite3GlobalConfig.pcache2.xCachesize(p, numberOfCachePages(pCache));
-+ pCache->pCache = p;
- }
-
-- /* Step 2: Abort if no existing page is found and createFlag is 0 */
-- if( pPage || createFlag==0 ){
-- pcache1PinPage(pPage);
-- goto fetch_out;
-+ eCreate = createFlag * (1 + (!pCache->bPurgeable || !pCache->pDirty));
-+ if( pCache->pCache ){
-+ pPage = sqlite3GlobalConfig.pcache2.xFetch(pCache->pCache, pgno, eCreate);
- }
-
-- /* The pGroup local variable will normally be initialized by the
-- ** pcache1EnterMutex() macro above. But if SQLITE_MUTEX_OMIT is defined,
-- ** then pcache1EnterMutex() is a no-op, so we have to initialize the
-- ** local variable here. Delaying the initialization of pGroup is an
-- ** optimization: The common case is to exit the module before reaching
-- ** this point.
-- */
--#ifdef SQLITE_MUTEX_OMIT
-- pGroup = pCache->pGroup;
-+ if( !pPage && eCreate==1 ){
-+ PgHdr *pPg;
-+
-+ /* Find a dirty page to write-out and recycle. First try to find a
-+ ** page that does not require a journal-sync (one with PGHDR_NEED_SYNC
-+ ** cleared), but if that is not possible settle for any other
-+ ** unreferenced dirty page.
-+ */
-+ expensive_assert( pcacheCheckSynced(pCache) );
-+ for(pPg=pCache->pSynced;
-+ pPg && (pPg->nRef || (pPg->flags&PGHDR_NEED_SYNC));
-+ pPg=pPg->pDirtyPrev
-+ );
-+ pCache->pSynced = pPg;
-+ if( !pPg ){
-+ for(pPg=pCache->pDirtyTail; pPg && pPg->nRef; pPg=pPg->pDirtyPrev);
-+ }
-+ if( pPg ){
-+ int rc;
-+#ifdef SQLITE_LOG_CACHE_SPILL
-+ sqlite3_log(SQLITE_FULL,
-+ "spill page %d making room for %d - cache used: %d/%d",
-+ pPg->pgno, pgno,
-+ sqlite3GlobalConfig.pcache.xPagecount(pCache->pCache),
-+ numberOfCachePages(pCache));
- #endif
-+ rc = pCache->xStress(pCache->pStress, pPg);
-+ if( rc!=SQLITE_OK && rc!=SQLITE_BUSY ){
-+ return rc;
-+ }
-+ }
-
-- /* Step 3: Abort if createFlag is 1 but the cache is nearly full */
-- assert( pCache->nPage >= pCache->nRecyclable );
-- nPinned = pCache->nPage - pCache->nRecyclable;
-- assert( pGroup->mxPinned == pGroup->nMaxPage + 10 - pGroup->nMinPage );
-- assert( pCache->n90pct == pCache->nMax*9/10 );
-- if( createFlag==1 && (
-- nPinned>=pGroup->mxPinned
-- || nPinned>=pCache->n90pct
-- || pcache1UnderMemoryPressure(pCache)
-- )){
-- goto fetch_out;
-+ pPage = sqlite3GlobalConfig.pcache2.xFetch(pCache->pCache, pgno, 2);
- }
-
-- if( pCache->nPage>=pCache->nHash && pcache1ResizeHash(pCache) ){
-- goto fetch_out;
-- }
-+ if( pPage ){
-+ pPgHdr = (PgHdr *)pPage->pExtra;
-
-- /* Step 4. Try to recycle a page. */
-- if( pCache->bPurgeable && pGroup->pLruTail && (
-- (pCache->nPage+1>=pCache->nMax)
-- || pGroup->nCurrentPage>=pGroup->nMaxPage
-- || pcache1UnderMemoryPressure(pCache)
-- )){
-- PCache1 *pOther;
-- pPage = pGroup->pLruTail;
-- pcache1RemoveFromHash(pPage);
-- pcache1PinPage(pPage);
-- pOther = pPage->pCache;
-+ if( !pPgHdr->pPage ){
-+ memset(pPgHdr, 0, sizeof(PgHdr));
-+ pPgHdr->pPage = pPage;
-+ pPgHdr->pData = pPage->pBuf;
-+ pPgHdr->pExtra = (void *)&pPgHdr[1];
-+ memset(pPgHdr->pExtra, 0, pCache->szExtra);
-+ pPgHdr->pCache = pCache;
-+ pPgHdr->pgno = pgno;
-+ }
-+ assert( pPgHdr->pCache==pCache );
-+ assert( pPgHdr->pgno==pgno );
-+ assert( pPgHdr->pData==pPage->pBuf );
-+ assert( pPgHdr->pExtra==(void *)&pPgHdr[1] );
-
-- /* We want to verify that szPage and szExtra are the same for pOther
-- ** and pCache. Assert that we can verify this by comparing sums. */
-- assert( (pCache->szPage & (pCache->szPage-1))==0 && pCache->szPage>=512 );
-- assert( pCache->szExtra<512 );
-- assert( (pOther->szPage & (pOther->szPage-1))==0 && pOther->szPage>=512 );
-- assert( pOther->szExtra<512 );
-+ if( 0==pPgHdr->nRef ){
-+ pCache->nRef++;
-+ }
-+ pPgHdr->nRef++;
-+ if( pgno==1 ){
-+ pCache->pPage1 = pPgHdr;
-+ }
-+ }
-+ *ppPage = pPgHdr;
-+ return (pPgHdr==0 && eCreate) ? SQLITE_NOMEM : SQLITE_OK;
-+}
-
-- if( pOther->szPage+pOther->szExtra != pCache->szPage+pCache->szExtra ){
-- pcache1FreePage(pPage);
-- pPage = 0;
-+/*
-+** Decrement the reference count on a page. If the page is clean and the
-+** reference count drops to 0, then it is made elible for recycling.
-+*/
-+SQLITE_PRIVATE void sqlite3PcacheRelease(PgHdr *p){
-+ assert( p->nRef>0 );
-+ p->nRef--;
-+ if( p->nRef==0 ){
-+ PCache *pCache = p->pCache;
-+ pCache->nRef--;
-+ if( (p->flags&PGHDR_DIRTY)==0 ){
-+ pcacheUnpin(p);
- }else{
-- pGroup->nCurrentPage -= (pOther->bPurgeable - pCache->bPurgeable);
-+ /* Move the page to the head of the dirty list. */
-+ pcacheRemoveFromDirtyList(p);
-+ pcacheAddToDirtyList(p);
- }
- }
-+}
-
-- /* Step 5. If a usable page buffer has still not been found,
-- ** attempt to allocate a new one.
-- */
-- if( !pPage ){
-- if( createFlag==1 ) sqlite3BeginBenignMalloc();
-- pPage = pcache1AllocPage(pCache);
-- if( createFlag==1 ) sqlite3EndBenignMalloc();
-+/*
-+** Increase the reference count of a supplied page by 1.
-+*/
-+SQLITE_PRIVATE void sqlite3PcacheRef(PgHdr *p){
-+ assert(p->nRef>0);
-+ p->nRef++;
-+}
-+
-+/*
-+** Drop a page from the cache. There must be exactly one reference to the
-+** page. This function deletes that reference, so after it returns the
-+** page pointed to by p is invalid.
-+*/
-+SQLITE_PRIVATE void sqlite3PcacheDrop(PgHdr *p){
-+ PCache *pCache;
-+ assert( p->nRef==1 );
-+ if( p->flags&PGHDR_DIRTY ){
-+ pcacheRemoveFromDirtyList(p);
-+ }
-+ pCache = p->pCache;
-+ pCache->nRef--;
-+ if( p->pgno==1 ){
-+ pCache->pPage1 = 0;
-+ }
-+ sqlite3GlobalConfig.pcache2.xUnpin(pCache->pCache, p->pPage, 1);
-+}
-+
-+/*
-+** Make sure the page is marked as dirty. If it isn't dirty already,
-+** make it so.
-+*/
-+SQLITE_PRIVATE void sqlite3PcacheMakeDirty(PgHdr *p){
-+ p->flags &= ~PGHDR_DONT_WRITE;
-+ assert( p->nRef>0 );
-+ if( 0==(p->flags & PGHDR_DIRTY) ){
-+ p->flags |= PGHDR_DIRTY;
-+ pcacheAddToDirtyList( p);
-+ }
-+}
-+
-+/*
-+** Make sure the page is marked as clean. If it isn't clean already,
-+** make it so.
-+*/
-+SQLITE_PRIVATE void sqlite3PcacheMakeClean(PgHdr *p){
-+ if( (p->flags & PGHDR_DIRTY) ){
-+ pcacheRemoveFromDirtyList(p);
-+ p->flags &= ~(PGHDR_DIRTY|PGHDR_NEED_SYNC);
-+ if( p->nRef==0 ){
-+ pcacheUnpin(p);
-+ }
- }
-+}
-
-- if( pPage ){
-- unsigned int h = iKey % pCache->nHash;
-- pCache->nPage++;
-- pPage->iKey = iKey;
-- pPage->pNext = pCache->apHash[h];
-- pPage->pCache = pCache;
-- pPage->pLruPrev = 0;
-- pPage->pLruNext = 0;
-- *(void **)pPage->page.pExtra = 0;
-- pCache->apHash[h] = pPage;
-+/*
-+** Make every page in the cache clean.
-+*/
-+SQLITE_PRIVATE void sqlite3PcacheCleanAll(PCache *pCache){
-+ PgHdr *p;
-+ while( (p = pCache->pDirty)!=0 ){
-+ sqlite3PcacheMakeClean(p);
- }
-+}
-
--fetch_out:
-- if( pPage && iKey>pCache->iMaxKey ){
-- pCache->iMaxKey = iKey;
-+/*
-+** Clear the PGHDR_NEED_SYNC flag from all dirty pages.
-+*/
-+SQLITE_PRIVATE void sqlite3PcacheClearSyncFlags(PCache *pCache){
-+ PgHdr *p;
-+ for(p=pCache->pDirty; p; p=p->pDirtyNext){
-+ p->flags &= ~PGHDR_NEED_SYNC;
- }
-- pcache1LeaveMutex(pGroup);
-- return &pPage->page;
-+ pCache->pSynced = pCache->pDirtyTail;
- }
-
-+/*
-+** Change the page number of page p to newPgno.
-+*/
-+SQLITE_PRIVATE void sqlite3PcacheMove(PgHdr *p, Pgno newPgno){
-+ PCache *pCache = p->pCache;
-+ assert( p->nRef>0 );
-+ assert( newPgno>0 );
-+ sqlite3GlobalConfig.pcache2.xRekey(pCache->pCache, p->pPage, p->pgno,newPgno);
-+ p->pgno = newPgno;
-+ if( (p->flags&PGHDR_DIRTY) && (p->flags&PGHDR_NEED_SYNC) ){
-+ pcacheRemoveFromDirtyList(p);
-+ pcacheAddToDirtyList(p);
-+ }
-+}
-
- /*
--** Implementation of the sqlite3_pcache.xUnpin method.
-+** Drop every cache entry whose page number is greater than "pgno". The
-+** caller must ensure that there are no outstanding references to any pages
-+** other than page 1 with a page number greater than pgno.
- **
--** Mark a page as unpinned (eligible for asynchronous recycling).
-+** If there is a reference to page 1 and the pgno parameter passed to this
-+** function is 0, then the data area associated with page 1 is zeroed, but
-+** the page object is not dropped.
- */
--static void pcache1Unpin(
-- sqlite3_pcache *p,
-- sqlite3_pcache_page *pPg,
-- int reuseUnlikely
--){
-- PCache1 *pCache = (PCache1 *)p;
-- PgHdr1 *pPage = (PgHdr1 *)pPg;
-- PGroup *pGroup = pCache->pGroup;
--
-- assert( pPage->pCache==pCache );
-- pcache1EnterMutex(pGroup);
-+SQLITE_PRIVATE void sqlite3PcacheTruncate(PCache *pCache, Pgno pgno){
-+ if( pCache->pCache ){
-+ PgHdr *p;
-+ PgHdr *pNext;
-+ for(p=pCache->pDirty; p; p=pNext){
-+ pNext = p->pDirtyNext;
-+ /* This routine never gets call with a positive pgno except right
-+ ** after sqlite3PcacheCleanAll(). So if there are dirty pages,
-+ ** it must be that pgno==0.
-+ */
-+ assert( p->pgno>0 );
-+ if( ALWAYS(p->pgno>pgno) ){
-+ assert( p->flags&PGHDR_DIRTY );
-+ sqlite3PcacheMakeClean(p);
-+ }
-+ }
-+ if( pgno==0 && pCache->pPage1 ){
-+ memset(pCache->pPage1->pData, 0, pCache->szPage);
-+ pgno = 1;
-+ }
-+ sqlite3GlobalConfig.pcache2.xTruncate(pCache->pCache, pgno+1);
-+ }
-+}
-
-- /* It is an error to call this function if the page is already
-- ** part of the PGroup LRU list.
-- */
-- assert( pPage->pLruPrev==0 && pPage->pLruNext==0 );
-- assert( pGroup->pLruHead!=pPage && pGroup->pLruTail!=pPage );
-+/*
-+** Close a cache.
-+*/
-+SQLITE_PRIVATE void sqlite3PcacheClose(PCache *pCache){
-+ if( pCache->pCache ){
-+ sqlite3GlobalConfig.pcache2.xDestroy(pCache->pCache);
-+ }
-+}
-
-- if( reuseUnlikely || pGroup->nCurrentPage>pGroup->nMaxPage ){
-- pcache1RemoveFromHash(pPage);
-- pcache1FreePage(pPage);
-- }else{
-- /* Add the page to the PGroup LRU list. */
-- if( pGroup->pLruHead ){
-- pGroup->pLruHead->pLruPrev = pPage;
-- pPage->pLruNext = pGroup->pLruHead;
-- pGroup->pLruHead = pPage;
-+/*
-+** Discard the contents of the cache.
-+*/
-+SQLITE_PRIVATE void sqlite3PcacheClear(PCache *pCache){
-+ sqlite3PcacheTruncate(pCache, 0);
-+}
-+
-+/*
-+** Merge two lists of pages connected by pDirty and in pgno order.
-+** Do not both fixing the pDirtyPrev pointers.
-+*/
-+static PgHdr *pcacheMergeDirtyList(PgHdr *pA, PgHdr *pB){
-+ PgHdr result, *pTail;
-+ pTail = &result;
-+ while( pA && pB ){
-+ if( pA->pgno<pB->pgno ){
-+ pTail->pDirty = pA;
-+ pTail = pA;
-+ pA = pA->pDirty;
- }else{
-- pGroup->pLruTail = pPage;
-- pGroup->pLruHead = pPage;
-+ pTail->pDirty = pB;
-+ pTail = pB;
-+ pB = pB->pDirty;
- }
-- pCache->nRecyclable++;
- }
--
-- pcache1LeaveMutex(pCache->pGroup);
-+ if( pA ){
-+ pTail->pDirty = pA;
-+ }else if( pB ){
-+ pTail->pDirty = pB;
-+ }else{
-+ pTail->pDirty = 0;
-+ }
-+ return result.pDirty;
- }
-
- /*
--** Implementation of the sqlite3_pcache.xRekey method.
-+** Sort the list of pages in accending order by pgno. Pages are
-+** connected by pDirty pointers. The pDirtyPrev pointers are
-+** corrupted by this sort.
-+**
-+** Since there cannot be more than 2^31 distinct pages in a database,
-+** there cannot be more than 31 buckets required by the merge sorter.
-+** One extra bucket is added to catch overflow in case something
-+** ever changes to make the previous sentence incorrect.
- */
--static void pcache1Rekey(
-- sqlite3_pcache *p,
-- sqlite3_pcache_page *pPg,
-- unsigned int iOld,
-- unsigned int iNew
--){
-- PCache1 *pCache = (PCache1 *)p;
-- PgHdr1 *pPage = (PgHdr1 *)pPg;
-- PgHdr1 **pp;
-- unsigned int h;
-- assert( pPage->iKey==iOld );
-- assert( pPage->pCache==pCache );
--
-- pcache1EnterMutex(pCache->pGroup);
--
-- h = iOld%pCache->nHash;
-- pp = &pCache->apHash[h];
-- while( (*pp)!=pPage ){
-- pp = &(*pp)->pNext;
-+#define N_SORT_BUCKET 32
-+static PgHdr *pcacheSortDirtyList(PgHdr *pIn){
-+ PgHdr *a[N_SORT_BUCKET], *p;
-+ int i;
-+ memset(a, 0, sizeof(a));
-+ while( pIn ){
-+ p = pIn;
-+ pIn = p->pDirty;
-+ p->pDirty = 0;
-+ for(i=0; ALWAYS(i<N_SORT_BUCKET-1); i++){
-+ if( a[i]==0 ){
-+ a[i] = p;
-+ break;
-+ }else{
-+ p = pcacheMergeDirtyList(a[i], p);
-+ a[i] = 0;
-+ }
-+ }
-+ if( NEVER(i==N_SORT_BUCKET-1) ){
-+ /* To get here, there need to be 2^(N_SORT_BUCKET) elements in
-+ ** the input list. But that is impossible.
-+ */
-+ a[i] = pcacheMergeDirtyList(a[i], p);
-+ }
- }
-- *pp = pPage->pNext;
-+ p = a[0];
-+ for(i=1; i<N_SORT_BUCKET; i++){
-+ p = pcacheMergeDirtyList(p, a[i]);
-+ }
-+ return p;
-+}
-
-- h = iNew%pCache->nHash;
-- pPage->iKey = iNew;
-- pPage->pNext = pCache->apHash[h];
-- pCache->apHash[h] = pPage;
-- if( iNew>pCache->iMaxKey ){
-- pCache->iMaxKey = iNew;
-+/*
-+** Return a list of all dirty pages in the cache, sorted by page number.
-+*/
-+SQLITE_PRIVATE PgHdr *sqlite3PcacheDirtyList(PCache *pCache){
-+ PgHdr *p;
-+ for(p=pCache->pDirty; p; p=p->pDirtyNext){
-+ p->pDirty = p->pDirtyNext;
- }
-+ return pcacheSortDirtyList(pCache->pDirty);
-+}
-
-- pcache1LeaveMutex(pCache->pGroup);
-+/*
-+** Return the total number of referenced pages held by the cache.
-+*/
-+SQLITE_PRIVATE int sqlite3PcacheRefCount(PCache *pCache){
-+ return pCache->nRef;
- }
-
- /*
--** Implementation of the sqlite3_pcache.xTruncate method.
--**
--** Discard all unpinned pages in the cache with a page number equal to
--** or greater than parameter iLimit. Any pinned pages with a page number
--** equal to or greater than iLimit are implicitly unpinned.
-+** Return the number of references to the page supplied as an argument.
- */
--static void pcache1Truncate(sqlite3_pcache *p, unsigned int iLimit){
-- PCache1 *pCache = (PCache1 *)p;
-- pcache1EnterMutex(pCache->pGroup);
-- if( iLimit<=pCache->iMaxKey ){
-- pcache1TruncateUnsafe(pCache, iLimit);
-- pCache->iMaxKey = iLimit-1;
-+SQLITE_PRIVATE int sqlite3PcachePageRefcount(PgHdr *p){
-+ return p->nRef;
-+}
-+
-+/*
-+** Return the total number of pages in the cache.
-+*/
-+SQLITE_PRIVATE int sqlite3PcachePagecount(PCache *pCache){
-+ int nPage = 0;
-+ if( pCache->pCache ){
-+ nPage = sqlite3GlobalConfig.pcache2.xPagecount(pCache->pCache);
- }
-- pcache1LeaveMutex(pCache->pGroup);
-+ return nPage;
- }
-
-+#ifdef SQLITE_TEST
- /*
--** Implementation of the sqlite3_pcache.xDestroy method.
--**
--** Destroy a cache allocated using pcache1Create().
-+** Get the suggested cache-size value.
- */
--static void pcache1Destroy(sqlite3_pcache *p){
-- PCache1 *pCache = (PCache1 *)p;
-- PGroup *pGroup = pCache->pGroup;
-- assert( pCache->bPurgeable || (pCache->nMax==0 && pCache->nMin==0) );
-- pcache1EnterMutex(pGroup);
-- pcache1TruncateUnsafe(pCache, 0);
-- assert( pGroup->nMaxPage >= pCache->nMax );
-- pGroup->nMaxPage -= pCache->nMax;
-- assert( pGroup->nMinPage >= pCache->nMin );
-- pGroup->nMinPage -= pCache->nMin;
-- pGroup->mxPinned = pGroup->nMaxPage + 10 - pGroup->nMinPage;
-- pcache1EnforceMaxPage(pGroup);
-- pcache1LeaveMutex(pGroup);
-- sqlite3_free(pCache->apHash);
-- sqlite3_free(pCache);
-+SQLITE_PRIVATE int sqlite3PcacheGetCachesize(PCache *pCache){
-+ return numberOfCachePages(pCache);
- }
-+#endif
-
- /*
--** This function is called during initialization (sqlite3_initialize()) to
--** install the default pluggable cache module, assuming the user has not
--** already provided an alternative.
-+** Set the suggested cache-size value.
- */
--SQLITE_PRIVATE void sqlite3PCacheSetDefault(void){
-- static const sqlite3_pcache_methods2 defaultMethods = {
-- 1, /* iVersion */
-- 0, /* pArg */
-- pcache1Init, /* xInit */
-- pcache1Shutdown, /* xShutdown */
-- pcache1Create, /* xCreate */
-- pcache1Cachesize, /* xCachesize */
-- pcache1Pagecount, /* xPagecount */
-- pcache1Fetch, /* xFetch */
-- pcache1Unpin, /* xUnpin */
-- pcache1Rekey, /* xRekey */
-- pcache1Truncate, /* xTruncate */
-- pcache1Destroy, /* xDestroy */
-- pcache1Shrink /* xShrink */
-- };
-- sqlite3_config(SQLITE_CONFIG_PCACHE2, &defaultMethods);
-+SQLITE_PRIVATE void sqlite3PcacheSetCachesize(PCache *pCache, int mxPage){
-+ pCache->szCache = mxPage;
-+ if( pCache->pCache ){
-+ sqlite3GlobalConfig.pcache2.xCachesize(pCache->pCache,
-+ numberOfCachePages(pCache));
-+ }
- }
-
--#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
- /*
--** This function is called to free superfluous dynamically allocated memory
--** held by the pager system. Memory in use by any SQLite pager allocated
--** by the current thread may be sqlite3_free()ed.
--**
--** nReq is the number of bytes of memory required. Once this much has
--** been released, the function returns. The return value is the total number
--** of bytes of memory released.
-+** Free up as much memory as possible from the page cache.
- */
--SQLITE_PRIVATE int sqlite3PcacheReleaseMemory(int nReq){
-- int nFree = 0;
-- assert( sqlite3_mutex_notheld(pcache1.grp.mutex) );
-- assert( sqlite3_mutex_notheld(pcache1.mutex) );
-- if( pcache1.pStart==0 ){
-- PgHdr1 *p;
-- pcache1EnterMutex(&pcache1.grp);
-- while( (nReq<0 || nFree<nReq) && ((p=pcache1.grp.pLruTail)!=0) ){
-- nFree += pcache1MemSize(p->page.pBuf);
--#ifdef SQLITE_PCACHE_SEPARATE_HEADER
-- nFree += sqlite3MemSize(p);
--#endif
-- pcache1PinPage(p);
-- pcache1RemoveFromHash(p);
-- pcache1FreePage(p);
-- }
-- pcache1LeaveMutex(&pcache1.grp);
-+SQLITE_PRIVATE void sqlite3PcacheShrink(PCache *pCache){
-+ if( pCache->pCache ){
-+ sqlite3GlobalConfig.pcache2.xShrink(pCache->pCache);
- }
-- return nFree;
- }
--#endif /* SQLITE_ENABLE_MEMORY_MANAGEMENT */
-
--#ifdef SQLITE_TEST
-+#if defined(SQLITE_CHECK_PAGES) || defined(SQLITE_DEBUG)
- /*
--** This function is used by test procedures to inspect the internal state
--** of the global cache.
-+** For all dirty pages currently in the cache, invoke the specified
-+** callback. This is only used if the SQLITE_CHECK_PAGES macro is
-+** defined.
- */
--SQLITE_PRIVATE void sqlite3PcacheStats(
-- int *pnCurrent, /* OUT: Total number of pages cached */
-- int *pnMax, /* OUT: Global maximum cache size */
-- int *pnMin, /* OUT: Sum of PCache1.nMin for purgeable caches */
-- int *pnRecyclable /* OUT: Total number of pages available for recycling */
--){
-- PgHdr1 *p;
-- int nRecyclable = 0;
-- for(p=pcache1.grp.pLruHead; p; p=p->pLruNext){
-- nRecyclable++;
-+SQLITE_PRIVATE void sqlite3PcacheIterateDirty(PCache *pCache, void (*xIter)(PgHdr *)){
-+ PgHdr *pDirty;
-+ for(pDirty=pCache->pDirty; pDirty; pDirty=pDirty->pDirtyNext){
-+ xIter(pDirty);
- }
-- *pnCurrent = pcache1.grp.nCurrentPage;
-- *pnMax = (int)pcache1.grp.nMaxPage;
-- *pnMin = (int)pcache1.grp.nMinPage;
-- *pnRecyclable = nRecyclable;
- }
- #endif
-
--/************** End of pcache1.c *********************************************/
--/************** Begin file rowset.c ******************************************/
-+/************** End of pcache.c **********************************************/
-+/************** Begin file pcache1.c *****************************************/
- /*
--** 2008 December 3
-+** 2008 November 05
- **
- ** The author disclaims copyright to this source code. In place of
- ** a legal notice, here is a blessing:
-@@ -37693,3176 +39706,3005 @@
- **
- *************************************************************************
- **
--** This module implements an object we call a "RowSet".
--**
--** The RowSet object is a collection of rowids. Rowids
--** are inserted into the RowSet in an arbitrary order. Inserts
--** can be intermixed with tests to see if a given rowid has been
--** previously inserted into the RowSet.
--**
--** After all inserts are finished, it is possible to extract the
--** elements of the RowSet in sorted order. Once this extraction
--** process has started, no new elements may be inserted.
--**
--** Hence, the primitive operations for a RowSet are:
--**
--** CREATE
--** INSERT
--** TEST
--** SMALLEST
--** DESTROY
-+** This file implements the default page cache implementation (the
-+** sqlite3_pcache interface). It also contains part of the implementation
-+** of the SQLITE_CONFIG_PAGECACHE and sqlite3_release_memory() features.
-+** If the default page cache implementation is overriden, then neither of
-+** these two features are available.
-+*/
-+
-+
-+typedef struct PCache1 PCache1;
-+typedef struct PgHdr1 PgHdr1;
-+typedef struct PgFreeslot PgFreeslot;
-+typedef struct PGroup PGroup;
-+
-+/* Each page cache (or PCache) belongs to a PGroup. A PGroup is a set
-+** of one or more PCaches that are able to recycle each others unpinned
-+** pages when they are under memory pressure. A PGroup is an instance of
-+** the following object.
- **
--** The CREATE and DESTROY primitives are the constructor and destructor,
--** obviously. The INSERT primitive adds a new element to the RowSet.
--** TEST checks to see if an element is already in the RowSet. SMALLEST
--** extracts the least value from the RowSet.
-+** This page cache implementation works in one of two modes:
- **
--** The INSERT primitive might allocate additional memory. Memory is
--** allocated in chunks so most INSERTs do no allocation. There is an
--** upper bound on the size of allocated memory. No memory is freed
--** until DESTROY.
-+** (1) Every PCache is the sole member of its own PGroup. There is
-+** one PGroup per PCache.
- **
--** The TEST primitive includes a "batch" number. The TEST primitive
--** will only see elements that were inserted before the last change
--** in the batch number. In other words, if an INSERT occurs between
--** two TESTs where the TESTs have the same batch nubmer, then the
--** value added by the INSERT will not be visible to the second TEST.
--** The initial batch number is zero, so if the very first TEST contains
--** a non-zero batch number, it will see all prior INSERTs.
-+** (2) There is a single global PGroup that all PCaches are a member
-+** of.
- **
--** No INSERTs may occurs after a SMALLEST. An assertion will fail if
--** that is attempted.
-+** Mode 1 uses more memory (since PCache instances are not able to rob
-+** unused pages from other PCaches) but it also operates without a mutex,
-+** and is therefore often faster. Mode 2 requires a mutex in order to be
-+** threadsafe, but recycles pages more efficiently.
- **
--** The cost of an INSERT is roughly constant. (Sometime new memory
--** has to be allocated on an INSERT.) The cost of a TEST with a new
--** batch number is O(NlogN) where N is the number of elements in the RowSet.
--** The cost of a TEST using the same batch number is O(logN). The cost
--** of the first SMALLEST is O(NlogN). Second and subsequent SMALLEST
--** primitives are constant time. The cost of DESTROY is O(N).
-+** For mode (1), PGroup.mutex is NULL. For mode (2) there is only a single
-+** PGroup which is the pcache1.grp global variable and its mutex is
-+** SQLITE_MUTEX_STATIC_LRU.
-+*/
-+struct PGroup {
-+ sqlite3_mutex *mutex; /* MUTEX_STATIC_LRU or NULL */
-+ unsigned int nMaxPage; /* Sum of nMax for purgeable caches */
-+ unsigned int nMinPage; /* Sum of nMin for purgeable caches */
-+ unsigned int mxPinned; /* nMaxpage + 10 - nMinPage */
-+ unsigned int nCurrentPage; /* Number of purgeable pages allocated */
-+ PgHdr1 *pLruHead, *pLruTail; /* LRU list of unpinned pages */
-+};
-+
-+/* Each page cache is an instance of the following object. Every
-+** open database file (including each in-memory database and each
-+** temporary or transient database) has a single page cache which
-+** is an instance of this object.
- **
--** There is an added cost of O(N) when switching between TEST and
--** SMALLEST primitives.
-+** Pointers to structures of this type are cast and returned as
-+** opaque sqlite3_pcache* handles.
-+*/
-+struct PCache1 {
-+ /* Cache configuration parameters. Page size (szPage) and the purgeable
-+ ** flag (bPurgeable) are set when the cache is created. nMax may be
-+ ** modified at any time by a call to the pcache1Cachesize() method.
-+ ** The PGroup mutex must be held when accessing nMax.
-+ */
-+ PGroup *pGroup; /* PGroup this cache belongs to */
-+ int szPage; /* Size of allocated pages in bytes */
-+ int szExtra; /* Size of extra space in bytes */
-+ int bPurgeable; /* True if cache is purgeable */
-+ unsigned int nMin; /* Minimum number of pages reserved */
-+ unsigned int nMax; /* Configured "cache_size" value */
-+ unsigned int n90pct; /* nMax*9/10 */
-+ unsigned int iMaxKey; /* Largest key seen since xTruncate() */
-+
-+ /* Hash table of all pages. The following variables may only be accessed
-+ ** when the accessor is holding the PGroup mutex.
-+ */
-+ unsigned int nRecyclable; /* Number of pages in the LRU list */
-+ unsigned int nPage; /* Total number of pages in apHash */
-+ unsigned int nHash; /* Number of slots in apHash[] */
-+ PgHdr1 **apHash; /* Hash table for fast lookup by key */
-+};
-+
-+/*
-+** Each cache entry is represented by an instance of the following
-+** structure. Unless SQLITE_PCACHE_SEPARATE_HEADER is defined, a buffer of
-+** PgHdr1.pCache->szPage bytes is allocated directly before this structure
-+** in memory.
-+*/
-+struct PgHdr1 {
-+ sqlite3_pcache_page page;
-+ unsigned int iKey; /* Key value (page number) */
-+ PgHdr1 *pNext; /* Next in hash table chain */
-+ PCache1 *pCache; /* Cache that currently owns this page */
-+ PgHdr1 *pLruNext; /* Next in LRU list of unpinned pages */
-+ PgHdr1 *pLruPrev; /* Previous in LRU list of unpinned pages */
-+};
-+
-+/*
-+** Free slots in the allocator used to divide up the buffer provided using
-+** the SQLITE_CONFIG_PAGECACHE mechanism.
-+*/
-+struct PgFreeslot {
-+ PgFreeslot *pNext; /* Next free slot */
-+};
-+
-+/*
-+** Global data used by this cache.
- */
-+static SQLITE_WSD struct PCacheGlobal {
-+ PGroup grp; /* The global PGroup for mode (2) */
-+
-+ /* Variables related to SQLITE_CONFIG_PAGECACHE settings. The
-+ ** szSlot, nSlot, pStart, pEnd, nReserve, and isInit values are all
-+ ** fixed at sqlite3_initialize() time and do not require mutex protection.
-+ ** The nFreeSlot and pFree values do require mutex protection.
-+ */
-+ int isInit; /* True if initialized */
-+ int szSlot; /* Size of each free slot */
-+ int nSlot; /* The number of pcache slots */
-+ int nReserve; /* Try to keep nFreeSlot above this */
-+ void *pStart, *pEnd; /* Bounds of pagecache malloc range */
-+ /* Above requires no mutex. Use mutex below for variable that follow. */
-+ sqlite3_mutex *mutex; /* Mutex for accessing the following: */
-+ PgFreeslot *pFree; /* Free page blocks */
-+ int nFreeSlot; /* Number of unused pcache slots */
-+ /* The following value requires a mutex to change. We skip the mutex on
-+ ** reading because (1) most platforms read a 32-bit integer atomically and
-+ ** (2) even if an incorrect value is read, no great harm is done since this
-+ ** is really just an optimization. */
-+ int bUnderPressure; /* True if low on PAGECACHE memory */
-+} pcache1_g;
-
-+/*
-+** All code in this file should access the global structure above via the
-+** alias "pcache1". This ensures that the WSD emulation is used when
-+** compiling for systems that do not support real WSD.
-+*/
-+#define pcache1 (GLOBAL(struct PCacheGlobal, pcache1_g))
-
- /*
--** Target size for allocation chunks.
-+** Macros to enter and leave the PCache LRU mutex.
- */
--#define ROWSET_ALLOCATION_SIZE 1024
-+#define pcache1EnterMutex(X) sqlite3_mutex_enter((X)->mutex)
-+#define pcache1LeaveMutex(X) sqlite3_mutex_leave((X)->mutex)
-+
-+/******************************************************************************/
-+/******** Page Allocation/SQLITE_CONFIG_PCACHE Related Functions **************/
-
- /*
--** The number of rowset entries per allocation chunk.
-+** This function is called during initialization if a static buffer is
-+** supplied to use for the page-cache by passing the SQLITE_CONFIG_PAGECACHE
-+** verb to sqlite3_config(). Parameter pBuf points to an allocation large
-+** enough to contain 'n' buffers of 'sz' bytes each.
-+**
-+** This routine is called from sqlite3_initialize() and so it is guaranteed
-+** to be serialized already. There is no need for further mutexing.
- */
--#define ROWSET_ENTRY_PER_CHUNK \
-- ((ROWSET_ALLOCATION_SIZE-8)/sizeof(struct RowSetEntry))
-+SQLITE_PRIVATE void sqlite3PCacheBufferSetup(void *pBuf, int sz, int n){
-+ if( pcache1.isInit ){
-+ PgFreeslot *p;
-+ sz = ROUNDDOWN8(sz);
-+ pcache1.szSlot = sz;
-+ pcache1.nSlot = pcache1.nFreeSlot = n;
-+ pcache1.nReserve = n>90 ? 10 : (n/10 + 1);
-+ pcache1.pStart = pBuf;
-+ pcache1.pFree = 0;
-+ pcache1.bUnderPressure = 0;
-+ while( n-- ){
-+ p = (PgFreeslot*)pBuf;
-+ p->pNext = pcache1.pFree;
-+ pcache1.pFree = p;
-+ pBuf = (void*)&((char*)pBuf)[sz];
-+ }
-+ pcache1.pEnd = pBuf;
-+ }
-+}
-
- /*
--** Each entry in a RowSet is an instance of the following object.
-+** Malloc function used within this file to allocate space from the buffer
-+** configured using sqlite3_config(SQLITE_CONFIG_PAGECACHE) option. If no
-+** such buffer exists or there is no space left in it, this function falls
-+** back to sqlite3Malloc().
- **
--** This same object is reused to store a linked list of trees of RowSetEntry
--** objects. In that alternative use, pRight points to the next entry
--** in the list, pLeft points to the tree, and v is unused. The
--** RowSet.pForest value points to the head of this forest list.
-+** Multiple threads can run this routine at the same time. Global variables
-+** in pcache1 need to be protected via mutex.
- */
--struct RowSetEntry {
-- i64 v; /* ROWID value for this entry */
-- struct RowSetEntry *pRight; /* Right subtree (larger entries) or list */
-- struct RowSetEntry *pLeft; /* Left subtree (smaller entries) */
--};
-+static void *pcache1Alloc(int nByte){
-+ void *p = 0;
-+ assert( sqlite3_mutex_notheld(pcache1.grp.mutex) );
-+ sqlite3StatusSet(SQLITE_STATUS_PAGECACHE_SIZE, nByte);
-+ if( nByte<=pcache1.szSlot ){
-+ sqlite3_mutex_enter(pcache1.mutex);
-+ p = (PgHdr1 *)pcache1.pFree;
-+ if( p ){
-+ pcache1.pFree = pcache1.pFree->pNext;
-+ pcache1.nFreeSlot--;
-+ pcache1.bUnderPressure = pcache1.nFreeSlot<pcache1.nReserve;
-+ assert( pcache1.nFreeSlot>=0 );
-+ sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_USED, 1);
-+ }
-+ sqlite3_mutex_leave(pcache1.mutex);
-+ }
-+ if( p==0 ){
-+ /* Memory is not available in the SQLITE_CONFIG_PAGECACHE pool. Get
-+ ** it from sqlite3Malloc instead.
-+ */
-+ p = sqlite3Malloc(nByte);
-+#ifndef SQLITE_DISABLE_PAGECACHE_OVERFLOW_STATS
-+ if( p ){
-+ int sz = sqlite3MallocSize(p);
-+ sqlite3_mutex_enter(pcache1.mutex);
-+ sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_OVERFLOW, sz);
-+ sqlite3_mutex_leave(pcache1.mutex);
-+ }
-+#endif
-+ sqlite3MemdebugSetType(p, MEMTYPE_PCACHE);
-+ }
-+ return p;
-+}
-
- /*
--** RowSetEntry objects are allocated in large chunks (instances of the
--** following structure) to reduce memory allocation overhead. The
--** chunks are kept on a linked list so that they can be deallocated
--** when the RowSet is destroyed.
-+** Free an allocated buffer obtained from pcache1Alloc().
- */
--struct RowSetChunk {
-- struct RowSetChunk *pNextChunk; /* Next chunk on list of them all */
-- struct RowSetEntry aEntry[ROWSET_ENTRY_PER_CHUNK]; /* Allocated entries */
--};
-+static int pcache1Free(void *p){
-+ int nFreed = 0;
-+ if( p==0 ) return 0;
-+ if( p>=pcache1.pStart && p<pcache1.pEnd ){
-+ PgFreeslot *pSlot;
-+ sqlite3_mutex_enter(pcache1.mutex);
-+ sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_USED, -1);
-+ pSlot = (PgFreeslot*)p;
-+ pSlot->pNext = pcache1.pFree;
-+ pcache1.pFree = pSlot;
-+ pcache1.nFreeSlot++;
-+ pcache1.bUnderPressure = pcache1.nFreeSlot<pcache1.nReserve;
-+ assert( pcache1.nFreeSlot<=pcache1.nSlot );
-+ sqlite3_mutex_leave(pcache1.mutex);
-+ }else{
-+ assert( sqlite3MemdebugHasType(p, MEMTYPE_PCACHE) );
-+ sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
-+ nFreed = sqlite3MallocSize(p);
-+#ifndef SQLITE_DISABLE_PAGECACHE_OVERFLOW_STATS
-+ sqlite3_mutex_enter(pcache1.mutex);
-+ sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_OVERFLOW, -nFreed);
-+ sqlite3_mutex_leave(pcache1.mutex);
-+#endif
-+ sqlite3_free(p);
-+ }
-+ return nFreed;
-+}
-
-+#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
- /*
--** A RowSet in an instance of the following structure.
--**
--** A typedef of this structure if found in sqliteInt.h.
-+** Return the size of a pcache allocation
- */
--struct RowSet {
-- struct RowSetChunk *pChunk; /* List of all chunk allocations */
-- sqlite3 *db; /* The database connection */
-- struct RowSetEntry *pEntry; /* List of entries using pRight */
-- struct RowSetEntry *pLast; /* Last entry on the pEntry list */
-- struct RowSetEntry *pFresh; /* Source of new entry objects */
-- struct RowSetEntry *pForest; /* List of binary trees of entries */
-- u16 nFresh; /* Number of objects on pFresh */
-- u8 rsFlags; /* Various flags */
-- u8 iBatch; /* Current insert batch */
--};
-+static int pcache1MemSize(void *p){
-+ if( p>=pcache1.pStart && p<pcache1.pEnd ){
-+ return pcache1.szSlot;
-+ }else{
-+ int iSize;
-+ assert( sqlite3MemdebugHasType(p, MEMTYPE_PCACHE) );
-+ sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
-+ iSize = sqlite3MallocSize(p);
-+ sqlite3MemdebugSetType(p, MEMTYPE_PCACHE);
-+ return iSize;
-+ }
-+}
-+#endif /* SQLITE_ENABLE_MEMORY_MANAGEMENT */
-
- /*
--** Allowed values for RowSet.rsFlags
-+** Allocate a new page object initially associated with cache pCache.
- */
--#define ROWSET_SORTED 0x01 /* True if RowSet.pEntry is sorted */
--#define ROWSET_NEXT 0x02 /* True if sqlite3RowSetNext() has been called */
-+static PgHdr1 *pcache1AllocPage(PCache1 *pCache){
-+ PgHdr1 *p = 0;
-+ void *pPg;
-+
-+ /* The group mutex must be released before pcache1Alloc() is called. This
-+ ** is because it may call sqlite3_release_memory(), which assumes that
-+ ** this mutex is not held. */
-+ assert( sqlite3_mutex_held(pCache->pGroup->mutex) );
-+ pcache1LeaveMutex(pCache->pGroup);
-+#ifdef SQLITE_PCACHE_SEPARATE_HEADER
-+ pPg = pcache1Alloc(pCache->szPage);
-+ p = sqlite3Malloc(sizeof(PgHdr1) + pCache->szExtra);
-+ if( !pPg || !p ){
-+ pcache1Free(pPg);
-+ sqlite3_free(p);
-+ pPg = 0;
-+ }
-+#else
-+ pPg = pcache1Alloc(sizeof(PgHdr1) + pCache->szPage + pCache->szExtra);
-+ p = (PgHdr1 *)&((u8 *)pPg)[pCache->szPage];
-+#endif
-+ pcache1EnterMutex(pCache->pGroup);
-+
-+ if( pPg ){
-+ p->page.pBuf = pPg;
-+ p->page.pExtra = &p[1];
-+ if( pCache->bPurgeable ){
-+ pCache->pGroup->nCurrentPage++;
-+ }
-+ return p;
-+ }
-+ return 0;
-+}
-
- /*
--** Turn bulk memory into a RowSet object. N bytes of memory
--** are available at pSpace. The db pointer is used as a memory context
--** for any subsequent allocations that need to occur.
--** Return a pointer to the new RowSet object.
-+** Free a page object allocated by pcache1AllocPage().
- **
--** It must be the case that N is sufficient to make a Rowset. If not
--** an assertion fault occurs.
--**
--** If N is larger than the minimum, use the surplus as an initial
--** allocation of entries available to be filled.
-+** The pointer is allowed to be NULL, which is prudent. But it turns out
-+** that the current implementation happens to never call this routine
-+** with a NULL pointer, so we mark the NULL test with ALWAYS().
- */
--SQLITE_PRIVATE RowSet *sqlite3RowSetInit(sqlite3 *db, void *pSpace, unsigned int N){
-- RowSet *p;
-- assert( N >= ROUND8(sizeof(*p)) );
-- p = pSpace;
-- p->pChunk = 0;
-- p->db = db;
-- p->pEntry = 0;
-- p->pLast = 0;
-- p->pForest = 0;
-- p->pFresh = (struct RowSetEntry*)(ROUND8(sizeof(*p)) + (char*)p);
-- p->nFresh = (u16)((N - ROUND8(sizeof(*p)))/sizeof(struct RowSetEntry));
-- p->rsFlags = ROWSET_SORTED;
-- p->iBatch = 0;
-- return p;
-+static void pcache1FreePage(PgHdr1 *p){
-+ if( ALWAYS(p) ){
-+ PCache1 *pCache = p->pCache;
-+ assert( sqlite3_mutex_held(p->pCache->pGroup->mutex) );
-+ pcache1Free(p->page.pBuf);
-+#ifdef SQLITE_PCACHE_SEPARATE_HEADER
-+ sqlite3_free(p);
-+#endif
-+ if( pCache->bPurgeable ){
-+ pCache->pGroup->nCurrentPage--;
-+ }
-+ }
- }
-
- /*
--** Deallocate all chunks from a RowSet. This frees all memory that
--** the RowSet has allocated over its lifetime. This routine is
--** the destructor for the RowSet.
-+** Malloc function used by SQLite to obtain space from the buffer configured
-+** using sqlite3_config(SQLITE_CONFIG_PAGECACHE) option. If no such buffer
-+** exists, this function falls back to sqlite3Malloc().
- */
--SQLITE_PRIVATE void sqlite3RowSetClear(RowSet *p){
-- struct RowSetChunk *pChunk, *pNextChunk;
-- for(pChunk=p->pChunk; pChunk; pChunk = pNextChunk){
-- pNextChunk = pChunk->pNextChunk;
-- sqlite3DbFree(p->db, pChunk);
-- }
-- p->pChunk = 0;
-- p->nFresh = 0;
-- p->pEntry = 0;
-- p->pLast = 0;
-- p->pForest = 0;
-- p->rsFlags = ROWSET_SORTED;
-+SQLITE_PRIVATE void *sqlite3PageMalloc(int sz){
-+ return pcache1Alloc(sz);
- }
-
- /*
--** Allocate a new RowSetEntry object that is associated with the
--** given RowSet. Return a pointer to the new and completely uninitialized
--** objected.
-+** Free an allocated buffer obtained from sqlite3PageMalloc().
-+*/
-+SQLITE_PRIVATE void sqlite3PageFree(void *p){
-+ pcache1Free(p);
-+}
-+
-+
-+/*
-+** Return true if it desirable to avoid allocating a new page cache
-+** entry.
- **
--** In an OOM situation, the RowSet.db->mallocFailed flag is set and this
--** routine returns NULL.
-+** If memory was allocated specifically to the page cache using
-+** SQLITE_CONFIG_PAGECACHE but that memory has all been used, then
-+** it is desirable to avoid allocating a new page cache entry because
-+** presumably SQLITE_CONFIG_PAGECACHE was suppose to be sufficient
-+** for all page cache needs and we should not need to spill the
-+** allocation onto the heap.
-+**
-+** Or, the heap is used for all page cache memory but the heap is
-+** under memory pressure, then again it is desirable to avoid
-+** allocating a new page cache entry in order to avoid stressing
-+** the heap even further.
- */
--static struct RowSetEntry *rowSetEntryAlloc(RowSet *p){
-- assert( p!=0 );
-- if( p->nFresh==0 ){
-- struct RowSetChunk *pNew;
-- pNew = sqlite3DbMallocRaw(p->db, sizeof(*pNew));
-- if( pNew==0 ){
-- return 0;
-- }
-- pNew->pNextChunk = p->pChunk;
-- p->pChunk = pNew;
-- p->pFresh = pNew->aEntry;
-- p->nFresh = ROWSET_ENTRY_PER_CHUNK;
-+static int pcache1UnderMemoryPressure(PCache1 *pCache){
-+ if( pcache1.nSlot && (pCache->szPage+pCache->szExtra)<=pcache1.szSlot ){
-+ return pcache1.bUnderPressure;
-+ }else{
-+ return sqlite3HeapNearlyFull();
- }
-- p->nFresh--;
-- return p->pFresh++;
- }
-
-+/******************************************************************************/
-+/******** General Implementation Functions ************************************/
-+
- /*
--** Insert a new value into a RowSet.
-+** This function is used to resize the hash table used by the cache passed
-+** as the first argument.
- **
--** The mallocFailed flag of the database connection is set if a
--** memory allocation fails.
-+** The PCache mutex must be held when this function is called.
- */
--SQLITE_PRIVATE void sqlite3RowSetInsert(RowSet *p, i64 rowid){
-- struct RowSetEntry *pEntry; /* The new entry */
-- struct RowSetEntry *pLast; /* The last prior entry */
-+static int pcache1ResizeHash(PCache1 *p){
-+ PgHdr1 **apNew;
-+ unsigned int nNew;
-+ unsigned int i;
-
-- /* This routine is never called after sqlite3RowSetNext() */
-- assert( p!=0 && (p->rsFlags & ROWSET_NEXT)==0 );
-+ assert( sqlite3_mutex_held(p->pGroup->mutex) );
-
-- pEntry = rowSetEntryAlloc(p);
-- if( pEntry==0 ) return;
-- pEntry->v = rowid;
-- pEntry->pRight = 0;
-- pLast = p->pLast;
-- if( pLast ){
-- if( (p->rsFlags & ROWSET_SORTED)!=0 && rowid<=pLast->v ){
-- p->rsFlags &= ~ROWSET_SORTED;
-+ nNew = p->nHash*2;
-+ if( nNew<256 ){
-+ nNew = 256;
-+ }
-+
-+ pcache1LeaveMutex(p->pGroup);
-+ if( p->nHash ){ sqlite3BeginBenignMalloc(); }
-+ apNew = (PgHdr1 **)sqlite3MallocZero(sizeof(PgHdr1 *)*nNew);
-+ if( p->nHash ){ sqlite3EndBenignMalloc(); }
-+ pcache1EnterMutex(p->pGroup);
-+ if( apNew ){
-+ for(i=0; i<p->nHash; i++){
-+ PgHdr1 *pPage;
-+ PgHdr1 *pNext = p->apHash[i];
-+ while( (pPage = pNext)!=0 ){
-+ unsigned int h = pPage->iKey % nNew;
-+ pNext = pPage->pNext;
-+ pPage->pNext = apNew[h];
-+ apNew[h] = pPage;
-+ }
- }
-- pLast->pRight = pEntry;
-- }else{
-- p->pEntry = pEntry;
-+ sqlite3_free(p->apHash);
-+ p->apHash = apNew;
-+ p->nHash = nNew;
- }
-- p->pLast = pEntry;
-+
-+ return (p->apHash ? SQLITE_OK : SQLITE_NOMEM);
- }
-
- /*
--** Merge two lists of RowSetEntry objects. Remove duplicates.
-+** This function is used internally to remove the page pPage from the
-+** PGroup LRU list, if is part of it. If pPage is not part of the PGroup
-+** LRU list, then this function is a no-op.
- **
--** The input lists are connected via pRight pointers and are
--** assumed to each already be in sorted order.
-+** The PGroup mutex must be held when this function is called.
-+**
-+** If pPage is NULL then this routine is a no-op.
- */
--static struct RowSetEntry *rowSetEntryMerge(
-- struct RowSetEntry *pA, /* First sorted list to be merged */
-- struct RowSetEntry *pB /* Second sorted list to be merged */
--){
-- struct RowSetEntry head;
-- struct RowSetEntry *pTail;
-+static void pcache1PinPage(PgHdr1 *pPage){
-+ PCache1 *pCache;
-+ PGroup *pGroup;
-
-- pTail = &head;
-- while( pA && pB ){
-- assert( pA->pRight==0 || pA->v<=pA->pRight->v );
-- assert( pB->pRight==0 || pB->v<=pB->pRight->v );
-- if( pA->v<pB->v ){
-- pTail->pRight = pA;
-- pA = pA->pRight;
-- pTail = pTail->pRight;
-- }else if( pB->v<pA->v ){
-- pTail->pRight = pB;
-- pB = pB->pRight;
-- pTail = pTail->pRight;
-- }else{
-- pA = pA->pRight;
-+ if( pPage==0 ) return;
-+ pCache = pPage->pCache;
-+ pGroup = pCache->pGroup;
-+ assert( sqlite3_mutex_held(pGroup->mutex) );
-+ if( pPage->pLruNext || pPage==pGroup->pLruTail ){
-+ if( pPage->pLruPrev ){
-+ pPage->pLruPrev->pLruNext = pPage->pLruNext;
- }
-+ if( pPage->pLruNext ){
-+ pPage->pLruNext->pLruPrev = pPage->pLruPrev;
-+ }
-+ if( pGroup->pLruHead==pPage ){
-+ pGroup->pLruHead = pPage->pLruNext;
-+ }
-+ if( pGroup->pLruTail==pPage ){
-+ pGroup->pLruTail = pPage->pLruPrev;
-+ }
-+ pPage->pLruNext = 0;
-+ pPage->pLruPrev = 0;
-+ pPage->pCache->nRecyclable--;
- }
-- if( pA ){
-- assert( pA->pRight==0 || pA->v<=pA->pRight->v );
-- pTail->pRight = pA;
-- }else{
-- assert( pB==0 || pB->pRight==0 || pB->v<=pB->pRight->v );
-- pTail->pRight = pB;
-- }
-- return head.pRight;
- }
-
-+
- /*
--** Sort all elements on the list of RowSetEntry objects into order of
--** increasing v.
--*/
--static struct RowSetEntry *rowSetEntrySort(struct RowSetEntry *pIn){
-- unsigned int i;
-- struct RowSetEntry *pNext, *aBucket[40];
-+** Remove the page supplied as an argument from the hash table
-+** (PCache1.apHash structure) that it is currently stored in.
-+**
-+** The PGroup mutex must be held when this function is called.
-+*/
-+static void pcache1RemoveFromHash(PgHdr1 *pPage){
-+ unsigned int h;
-+ PCache1 *pCache = pPage->pCache;
-+ PgHdr1 **pp;
-
-- memset(aBucket, 0, sizeof(aBucket));
-- while( pIn ){
-- pNext = pIn->pRight;
-- pIn->pRight = 0;
-- for(i=0; aBucket[i]; i++){
-- pIn = rowSetEntryMerge(aBucket[i], pIn);
-- aBucket[i] = 0;
-- }
-- aBucket[i] = pIn;
-- pIn = pNext;
-- }
-- pIn = 0;
-- for(i=0; i<sizeof(aBucket)/sizeof(aBucket[0]); i++){
-- pIn = rowSetEntryMerge(pIn, aBucket[i]);
-- }
-- return pIn;
-+ assert( sqlite3_mutex_held(pCache->pGroup->mutex) );
-+ h = pPage->iKey % pCache->nHash;
-+ for(pp=&pCache->apHash[h]; (*pp)!=pPage; pp=&(*pp)->pNext);
-+ *pp = (*pp)->pNext;
-+
-+ pCache->nPage--;
- }
-
-+/*
-+** If there are currently more than nMaxPage pages allocated, try
-+** to recycle pages to reduce the number allocated to nMaxPage.
-+*/
-+static void pcache1EnforceMaxPage(PGroup *pGroup){
-+ assert( sqlite3_mutex_held(pGroup->mutex) );
-+ while( pGroup->nCurrentPage>pGroup->nMaxPage && pGroup->pLruTail ){
-+ PgHdr1 *p = pGroup->pLruTail;
-+ assert( p->pCache->pGroup==pGroup );
-+ pcache1PinPage(p);
-+ pcache1RemoveFromHash(p);
-+ pcache1FreePage(p);
-+ }
-+}
-
- /*
--** The input, pIn, is a binary tree (or subtree) of RowSetEntry objects.
--** Convert this tree into a linked list connected by the pRight pointers
--** and return pointers to the first and last elements of the new list.
-+** Discard all pages from cache pCache with a page number (key value)
-+** greater than or equal to iLimit. Any pinned pages that meet this
-+** criteria are unpinned before they are discarded.
-+**
-+** The PCache mutex must be held when this function is called.
- */
--static void rowSetTreeToList(
-- struct RowSetEntry *pIn, /* Root of the input tree */
-- struct RowSetEntry **ppFirst, /* Write head of the output list here */
-- struct RowSetEntry **ppLast /* Write tail of the output list here */
-+static void pcache1TruncateUnsafe(
-+ PCache1 *pCache, /* The cache to truncate */
-+ unsigned int iLimit /* Drop pages with this pgno or larger */
- ){
-- assert( pIn!=0 );
-- if( pIn->pLeft ){
-- struct RowSetEntry *p;
-- rowSetTreeToList(pIn->pLeft, ppFirst, &p);
-- p->pRight = pIn;
-- }else{
-- *ppFirst = pIn;
-- }
-- if( pIn->pRight ){
-- rowSetTreeToList(pIn->pRight, &pIn->pRight, ppLast);
-- }else{
-- *ppLast = pIn;
-+ TESTONLY( unsigned int nPage = 0; ) /* To assert pCache->nPage is correct */
-+ unsigned int h;
-+ assert( sqlite3_mutex_held(pCache->pGroup->mutex) );
-+ for(h=0; h<pCache->nHash; h++){
-+ PgHdr1 **pp = &pCache->apHash[h];
-+ PgHdr1 *pPage;
-+ while( (pPage = *pp)!=0 ){
-+ if( pPage->iKey>=iLimit ){
-+ pCache->nPage--;
-+ *pp = pPage->pNext;
-+ pcache1PinPage(pPage);
-+ pcache1FreePage(pPage);
-+ }else{
-+ pp = &pPage->pNext;
-+ TESTONLY( nPage++; )
-+ }
-+ }
- }
-- assert( (*ppLast)->pRight==0 );
-+ assert( pCache->nPage==nPage );
- }
-
-+/******************************************************************************/
-+/******** sqlite3_pcache Methods **********************************************/
-
- /*
--** Convert a sorted list of elements (connected by pRight) into a binary
--** tree with depth of iDepth. A depth of 1 means the tree contains a single
--** node taken from the head of *ppList. A depth of 2 means a tree with
--** three nodes. And so forth.
--**
--** Use as many entries from the input list as required and update the
--** *ppList to point to the unused elements of the list. If the input
--** list contains too few elements, then construct an incomplete tree
--** and leave *ppList set to NULL.
--**
--** Return a pointer to the root of the constructed binary tree.
-+** Implementation of the sqlite3_pcache.xInit method.
- */
--static struct RowSetEntry *rowSetNDeepTree(
-- struct RowSetEntry **ppList,
-- int iDepth
--){
-- struct RowSetEntry *p; /* Root of the new tree */
-- struct RowSetEntry *pLeft; /* Left subtree */
-- if( *ppList==0 ){
-- return 0;
-- }
-- if( iDepth==1 ){
-- p = *ppList;
-- *ppList = p->pRight;
-- p->pLeft = p->pRight = 0;
-- return p;
-- }
-- pLeft = rowSetNDeepTree(ppList, iDepth-1);
-- p = *ppList;
-- if( p==0 ){
-- return pLeft;
-+static int pcache1Init(void *NotUsed){
-+ UNUSED_PARAMETER(NotUsed);
-+ assert( pcache1.isInit==0 );
-+ memset(&pcache1, 0, sizeof(pcache1));
-+ if( sqlite3GlobalConfig.bCoreMutex ){
-+ pcache1.grp.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_LRU);
-+ pcache1.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_PMEM);
- }
-- p->pLeft = pLeft;
-- *ppList = p->pRight;
-- p->pRight = rowSetNDeepTree(ppList, iDepth-1);
-- return p;
-+ pcache1.grp.mxPinned = 10;
-+ pcache1.isInit = 1;
-+ return SQLITE_OK;
- }
-
- /*
--** Convert a sorted list of elements into a binary tree. Make the tree
--** as deep as it needs to be in order to contain the entire list.
-+** Implementation of the sqlite3_pcache.xShutdown method.
-+** Note that the static mutex allocated in xInit does
-+** not need to be freed.
- */
--static struct RowSetEntry *rowSetListToTree(struct RowSetEntry *pList){
-- int iDepth; /* Depth of the tree so far */
-- struct RowSetEntry *p; /* Current tree root */
-- struct RowSetEntry *pLeft; /* Left subtree */
--
-- assert( pList!=0 );
-- p = pList;
-- pList = p->pRight;
-- p->pLeft = p->pRight = 0;
-- for(iDepth=1; pList; iDepth++){
-- pLeft = p;
-- p = pList;
-- pList = p->pRight;
-- p->pLeft = pLeft;
-- p->pRight = rowSetNDeepTree(&pList, iDepth);
-- }
-- return p;
-+static void pcache1Shutdown(void *NotUsed){
-+ UNUSED_PARAMETER(NotUsed);
-+ assert( pcache1.isInit!=0 );
-+ memset(&pcache1, 0, sizeof(pcache1));
- }
-
- /*
--** Take all the entries on p->pEntry and on the trees in p->pForest and
--** sort them all together into one big ordered list on p->pEntry.
-+** Implementation of the sqlite3_pcache.xCreate method.
- **
--** This routine should only be called once in the life of a RowSet.
-+** Allocate a new cache.
- */
--static void rowSetToList(RowSet *p){
-+static sqlite3_pcache *pcache1Create(int szPage, int szExtra, int bPurgeable){
-+ PCache1 *pCache; /* The newly created page cache */
-+ PGroup *pGroup; /* The group the new page cache will belong to */
-+ int sz; /* Bytes of memory required to allocate the new cache */
-
-- /* This routine is called only once */
-- assert( p!=0 && (p->rsFlags & ROWSET_NEXT)==0 );
-+ /*
-+ ** The seperateCache variable is true if each PCache has its own private
-+ ** PGroup. In other words, separateCache is true for mode (1) where no
-+ ** mutexing is required.
-+ **
-+ ** * Always use a unified cache (mode-2) if ENABLE_MEMORY_MANAGEMENT
-+ **
-+ ** * Always use a unified cache in single-threaded applications
-+ **
-+ ** * Otherwise (if multi-threaded and ENABLE_MEMORY_MANAGEMENT is off)
-+ ** use separate caches (mode-1)
-+ */
-+#if defined(SQLITE_ENABLE_MEMORY_MANAGEMENT) || SQLITE_THREADSAFE==0
-+ const int separateCache = 0;
-+#else
-+ int separateCache = sqlite3GlobalConfig.bCoreMutex>0;
-+#endif
-
-- if( (p->rsFlags & ROWSET_SORTED)==0 ){
-- p->pEntry = rowSetEntrySort(p->pEntry);
-- }
-+ assert( (szPage & (szPage-1))==0 && szPage>=512 && szPage<=65536 );
-+ assert( szExtra < 300 );
-
-- /* While this module could theoretically support it, sqlite3RowSetNext()
-- ** is never called after sqlite3RowSetText() for the same RowSet. So
-- ** there is never a forest to deal with. Should this change, simply
-- ** remove the assert() and the #if 0. */
-- assert( p->pForest==0 );
--#if 0
-- while( p->pForest ){
-- struct RowSetEntry *pTree = p->pForest->pLeft;
-- if( pTree ){
-- struct RowSetEntry *pHead, *pTail;
-- rowSetTreeToList(pTree, &pHead, &pTail);
-- p->pEntry = rowSetEntryMerge(p->pEntry, pHead);
-+ sz = sizeof(PCache1) + sizeof(PGroup)*separateCache;
-+ pCache = (PCache1 *)sqlite3MallocZero(sz);
-+ if( pCache ){
-+ if( separateCache ){
-+ pGroup = (PGroup*)&pCache[1];
-+ pGroup->mxPinned = 10;
-+ }else{
-+ pGroup = &pcache1.grp;
-+ }
-+ pCache->pGroup = pGroup;
-+ pCache->szPage = szPage;
-+ pCache->szExtra = szExtra;
-+ pCache->bPurgeable = (bPurgeable ? 1 : 0);
-+ if( bPurgeable ){
-+ pCache->nMin = 10;
-+ pcache1EnterMutex(pGroup);
-+ pGroup->nMinPage += pCache->nMin;
-+ pGroup->mxPinned = pGroup->nMaxPage + 10 - pGroup->nMinPage;
-+ pcache1LeaveMutex(pGroup);
- }
-- p->pForest = p->pForest->pRight;
- }
--#endif
-- p->rsFlags |= ROWSET_NEXT; /* Verify this routine is never called again */
-+ return (sqlite3_pcache *)pCache;
- }
-
- /*
--** Extract the smallest element from the RowSet.
--** Write the element into *pRowid. Return 1 on success. Return
--** 0 if the RowSet is already empty.
-+** Implementation of the sqlite3_pcache.xCachesize method.
- **
--** After this routine has been called, the sqlite3RowSetInsert()
--** routine may not be called again.
-+** Configure the cache_size limit for a cache.
- */
--SQLITE_PRIVATE int sqlite3RowSetNext(RowSet *p, i64 *pRowid){
-- assert( p!=0 );
--
-- /* Merge the forest into a single sorted list on first call */
-- if( (p->rsFlags & ROWSET_NEXT)==0 ) rowSetToList(p);
--
-- /* Return the next entry on the list */
-- if( p->pEntry ){
-- *pRowid = p->pEntry->v;
-- p->pEntry = p->pEntry->pRight;
-- if( p->pEntry==0 ){
-- sqlite3RowSetClear(p);
-- }
-- return 1;
-- }else{
-- return 0;
-+static void pcache1Cachesize(sqlite3_pcache *p, int nMax){
-+ PCache1 *pCache = (PCache1 *)p;
-+ if( pCache->bPurgeable ){
-+ PGroup *pGroup = pCache->pGroup;
-+ pcache1EnterMutex(pGroup);
-+ pGroup->nMaxPage += (nMax - pCache->nMax);
-+ pGroup->mxPinned = pGroup->nMaxPage + 10 - pGroup->nMinPage;
-+ pCache->nMax = nMax;
-+ pCache->n90pct = pCache->nMax*9/10;
-+ pcache1EnforceMaxPage(pGroup);
-+ pcache1LeaveMutex(pGroup);
- }
- }
-
- /*
--** Check to see if element iRowid was inserted into the rowset as
--** part of any insert batch prior to iBatch. Return 1 or 0.
-+** Implementation of the sqlite3_pcache.xShrink method.
- **
--** If this is the first test of a new batch and if there exist entires
--** on pRowSet->pEntry, then sort those entires into the forest at
--** pRowSet->pForest so that they can be tested.
-+** Free up as much memory as possible.
- */
--SQLITE_PRIVATE int sqlite3RowSetTest(RowSet *pRowSet, u8 iBatch, sqlite3_int64 iRowid){
-- struct RowSetEntry *p, *pTree;
--
-- /* This routine is never called after sqlite3RowSetNext() */
-- assert( pRowSet!=0 && (pRowSet->rsFlags & ROWSET_NEXT)==0 );
--
-- /* Sort entries into the forest on the first test of a new batch
-- */
-- if( iBatch!=pRowSet->iBatch ){
-- p = pRowSet->pEntry;
-- if( p ){
-- struct RowSetEntry **ppPrevTree = &pRowSet->pForest;
-- if( (pRowSet->rsFlags & ROWSET_SORTED)==0 ){
-- p = rowSetEntrySort(p);
-- }
-- for(pTree = pRowSet->pForest; pTree; pTree=pTree->pRight){
-- ppPrevTree = &pTree->pRight;
-- if( pTree->pLeft==0 ){
-- pTree->pLeft = rowSetListToTree(p);
-- break;
-- }else{
-- struct RowSetEntry *pAux, *pTail;
-- rowSetTreeToList(pTree->pLeft, &pAux, &pTail);
-- pTree->pLeft = 0;
-- p = rowSetEntryMerge(pAux, p);
-- }
-- }
-- if( pTree==0 ){
-- *ppPrevTree = pTree = rowSetEntryAlloc(pRowSet);
-- if( pTree ){
-- pTree->v = 0;
-- pTree->pRight = 0;
-- pTree->pLeft = rowSetListToTree(p);
-- }
-- }
-- pRowSet->pEntry = 0;
-- pRowSet->pLast = 0;
-- pRowSet->rsFlags |= ROWSET_SORTED;
-- }
-- pRowSet->iBatch = iBatch;
-+static void pcache1Shrink(sqlite3_pcache *p){
-+ PCache1 *pCache = (PCache1*)p;
-+ if( pCache->bPurgeable ){
-+ PGroup *pGroup = pCache->pGroup;
-+ int savedMaxPage;
-+ pcache1EnterMutex(pGroup);
-+ savedMaxPage = pGroup->nMaxPage;
-+ pGroup->nMaxPage = 0;
-+ pcache1EnforceMaxPage(pGroup);
-+ pGroup->nMaxPage = savedMaxPage;
-+ pcache1LeaveMutex(pGroup);
- }
-+}
-
-- /* Test to see if the iRowid value appears anywhere in the forest.
-- ** Return 1 if it does and 0 if not.
-- */
-- for(pTree = pRowSet->pForest; pTree; pTree=pTree->pRight){
-- p = pTree->pLeft;
-- while( p ){
-- if( p->v<iRowid ){
-- p = p->pRight;
-- }else if( p->v>iRowid ){
-- p = p->pLeft;
-- }else{
-- return 1;
-- }
-- }
-- }
-- return 0;
-+/*
-+** Implementation of the sqlite3_pcache.xPagecount method.
-+*/
-+static int pcache1Pagecount(sqlite3_pcache *p){
-+ int n;
-+ PCache1 *pCache = (PCache1*)p;
-+ pcache1EnterMutex(pCache->pGroup);
-+ n = pCache->nPage;
-+ pcache1LeaveMutex(pCache->pGroup);
-+ return n;
- }
-
--/************** End of rowset.c **********************************************/
--/************** Begin file pager.c *******************************************/
- /*
--** 2001 September 15
-+** Implementation of the sqlite3_pcache.xFetch method.
- **
--** The author disclaims copyright to this source code. In place of
--** a legal notice, here is a blessing:
-+** Fetch a page by key value.
- **
--** May you do good and not evil.
--** May you find forgiveness for yourself and forgive others.
--** May you share freely, never taking more than you give.
-+** Whether or not a new page may be allocated by this function depends on
-+** the value of the createFlag argument. 0 means do not allocate a new
-+** page. 1 means allocate a new page if space is easily available. 2
-+** means to try really hard to allocate a new page.
- **
--*************************************************************************
--** This is the implementation of the page cache subsystem or "pager".
--**
--** The pager is used to access a database disk file. It implements
--** atomic commit and rollback through the use of a journal file that
--** is separate from the database file. The pager also implements file
--** locking to prevent two processes from writing the same database
--** file simultaneously, or one process from reading the database while
--** another is writing.
--*/
--#ifndef SQLITE_OMIT_DISKIO
--/************** Include wal.h in the middle of pager.c ***********************/
--/************** Begin file wal.h *********************************************/
--/*
--** 2010 February 1
-+** For a non-purgeable cache (a cache used as the storage for an in-memory
-+** database) there is really no difference between createFlag 1 and 2. So
-+** the calling function (pcache.c) will never have a createFlag of 1 on
-+** a non-purgeable cache.
- **
--** The author disclaims copyright to this source code. In place of
--** a legal notice, here is a blessing:
-+** There are three different approaches to obtaining space for a page,
-+** depending on the value of parameter createFlag (which may be 0, 1 or 2).
- **
--** May you do good and not evil.
--** May you find forgiveness for yourself and forgive others.
--** May you share freely, never taking more than you give.
-+** 1. Regardless of the value of createFlag, the cache is searched for a
-+** copy of the requested page. If one is found, it is returned.
- **
--*************************************************************************
--** This header file defines the interface to the write-ahead logging
--** system. Refer to the comments below and the header comment attached to
--** the implementation of each function in log.c for further details.
-+** 2. If createFlag==0 and the page is not already in the cache, NULL is
-+** returned.
-+**
-+** 3. If createFlag is 1, and the page is not already in the cache, then
-+** return NULL (do not allocate a new page) if any of the following
-+** conditions are true:
-+**
-+** (a) the number of pages pinned by the cache is greater than
-+** PCache1.nMax, or
-+**
-+** (b) the number of pages pinned by the cache is greater than
-+** the sum of nMax for all purgeable caches, less the sum of
-+** nMin for all other purgeable caches, or
-+**
-+** 4. If none of the first three conditions apply and the cache is marked
-+** as purgeable, and if one of the following is true:
-+**
-+** (a) The number of pages allocated for the cache is already
-+** PCache1.nMax, or
-+**
-+** (b) The number of pages allocated for all purgeable caches is
-+** already equal to or greater than the sum of nMax for all
-+** purgeable caches,
-+**
-+** (c) The system is under memory pressure and wants to avoid
-+** unnecessary pages cache entry allocations
-+**
-+** then attempt to recycle a page from the LRU list. If it is the right
-+** size, return the recycled buffer. Otherwise, free the buffer and
-+** proceed to step 5.
-+**
-+** 5. Otherwise, allocate and return a new page buffer.
- */
-+static sqlite3_pcache_page *pcache1Fetch(
-+ sqlite3_pcache *p,
-+ unsigned int iKey,
-+ int createFlag
-+){
-+ unsigned int nPinned;
-+ PCache1 *pCache = (PCache1 *)p;
-+ PGroup *pGroup;
-+ PgHdr1 *pPage = 0;
-
--#ifndef _WAL_H_
--#define _WAL_H_
--
--
--/* Additional values that can be added to the sync_flags argument of
--** sqlite3WalFrames():
--*/
--#define WAL_SYNC_TRANSACTIONS 0x20 /* Sync at the end of each transaction */
--#define SQLITE_SYNC_MASK 0x13 /* Mask off the SQLITE_SYNC_* values */
-+ assert( pCache->bPurgeable || createFlag!=1 );
-+ assert( pCache->bPurgeable || pCache->nMin==0 );
-+ assert( pCache->bPurgeable==0 || pCache->nMin==10 );
-+ assert( pCache->nMin==0 || pCache->bPurgeable );
-+ pcache1EnterMutex(pGroup = pCache->pGroup);
-
--#ifdef SQLITE_OMIT_WAL
--# define sqlite3WalOpen(x,y,z) 0
--# define sqlite3WalLimit(x,y)
--# define sqlite3WalClose(w,x,y,z) 0
--# define sqlite3WalBeginReadTransaction(y,z) 0
--# define sqlite3WalEndReadTransaction(z)
--# define sqlite3WalDbsize(y) 0
--# define sqlite3WalBeginWriteTransaction(y) 0
--# define sqlite3WalEndWriteTransaction(x) 0
--# define sqlite3WalUndo(x,y,z) 0
--# define sqlite3WalSavepoint(y,z)
--# define sqlite3WalSavepointUndo(y,z) 0
--# define sqlite3WalFrames(u,v,w,x,y,z) 0
--# define sqlite3WalCheckpoint(r,s,t,u,v,w,x,y,z) 0
--# define sqlite3WalCallback(z) 0
--# define sqlite3WalExclusiveMode(y,z) 0
--# define sqlite3WalHeapMemory(z) 0
--# define sqlite3WalFramesize(z) 0
--# define sqlite3WalFindFrame(x,y,z) 0
--#else
-+ /* Step 1: Search the hash table for an existing entry. */
-+ if( pCache->nHash>0 ){
-+ unsigned int h = iKey % pCache->nHash;
-+ for(pPage=pCache->apHash[h]; pPage&&pPage->iKey!=iKey; pPage=pPage->pNext);
-+ }
-
--#define WAL_SAVEPOINT_NDATA 4
-+ /* Step 2: Abort if no existing page is found and createFlag is 0 */
-+ if( pPage || createFlag==0 ){
-+ pcache1PinPage(pPage);
-+ goto fetch_out;
-+ }
-
--/* Connection to a write-ahead log (WAL) file.
--** There is one object of this type for each pager.
--*/
--typedef struct Wal Wal;
-+ /* The pGroup local variable will normally be initialized by the
-+ ** pcache1EnterMutex() macro above. But if SQLITE_MUTEX_OMIT is defined,
-+ ** then pcache1EnterMutex() is a no-op, so we have to initialize the
-+ ** local variable here. Delaying the initialization of pGroup is an
-+ ** optimization: The common case is to exit the module before reaching
-+ ** this point.
-+ */
-+#ifdef SQLITE_MUTEX_OMIT
-+ pGroup = pCache->pGroup;
-+#endif
-
--/* Open and close a connection to a write-ahead log. */
--SQLITE_PRIVATE int sqlite3WalOpen(sqlite3_vfs*, sqlite3_file*, const char *, int, i64, Wal**);
--SQLITE_PRIVATE int sqlite3WalClose(Wal *pWal, int sync_flags, int, u8 *);
-+ /* Step 3: Abort if createFlag is 1 but the cache is nearly full */
-+ assert( pCache->nPage >= pCache->nRecyclable );
-+ nPinned = pCache->nPage - pCache->nRecyclable;
-+ assert( pGroup->mxPinned == pGroup->nMaxPage + 10 - pGroup->nMinPage );
-+ assert( pCache->n90pct == pCache->nMax*9/10 );
-+ if( createFlag==1 && (
-+ nPinned>=pGroup->mxPinned
-+ || nPinned>=pCache->n90pct
-+ || pcache1UnderMemoryPressure(pCache)
-+ )){
-+ goto fetch_out;
-+ }
-
--/* Set the limiting size of a WAL file. */
--SQLITE_PRIVATE void sqlite3WalLimit(Wal*, i64);
-+ if( pCache->nPage>=pCache->nHash && pcache1ResizeHash(pCache) ){
-+ goto fetch_out;
-+ }
-
--/* Used by readers to open (lock) and close (unlock) a snapshot. A
--** snapshot is like a read-transaction. It is the state of the database
--** at an instant in time. sqlite3WalOpenSnapshot gets a read lock and
--** preserves the current state even if the other threads or processes
--** write to or checkpoint the WAL. sqlite3WalCloseSnapshot() closes the
--** transaction and releases the lock.
--*/
--SQLITE_PRIVATE int sqlite3WalBeginReadTransaction(Wal *pWal, int *);
--SQLITE_PRIVATE void sqlite3WalEndReadTransaction(Wal *pWal);
-+ /* Step 4. Try to recycle a page. */
-+ if( pCache->bPurgeable && pGroup->pLruTail && (
-+ (pCache->nPage+1>=pCache->nMax)
-+ || pGroup->nCurrentPage>=pGroup->nMaxPage
-+ || pcache1UnderMemoryPressure(pCache)
-+ )){
-+ PCache1 *pOther;
-+ pPage = pGroup->pLruTail;
-+ pcache1RemoveFromHash(pPage);
-+ pcache1PinPage(pPage);
-+ pOther = pPage->pCache;
-
--/* Read a page from the write-ahead log, if it is present. */
--SQLITE_PRIVATE int sqlite3WalFindFrame(Wal *, Pgno, u32 *);
--SQLITE_PRIVATE int sqlite3WalReadFrame(Wal *, u32, int, u8 *);
-+ /* We want to verify that szPage and szExtra are the same for pOther
-+ ** and pCache. Assert that we can verify this by comparing sums. */
-+ assert( (pCache->szPage & (pCache->szPage-1))==0 && pCache->szPage>=512 );
-+ assert( pCache->szExtra<512 );
-+ assert( (pOther->szPage & (pOther->szPage-1))==0 && pOther->szPage>=512 );
-+ assert( pOther->szExtra<512 );
-
--/* If the WAL is not empty, return the size of the database. */
--SQLITE_PRIVATE Pgno sqlite3WalDbsize(Wal *pWal);
-+ if( pOther->szPage+pOther->szExtra != pCache->szPage+pCache->szExtra ){
-+ pcache1FreePage(pPage);
-+ pPage = 0;
-+ }else{
-+ pGroup->nCurrentPage -= (pOther->bPurgeable - pCache->bPurgeable);
-+ }
-+ }
-
--/* Obtain or release the WRITER lock. */
--SQLITE_PRIVATE int sqlite3WalBeginWriteTransaction(Wal *pWal);
--SQLITE_PRIVATE int sqlite3WalEndWriteTransaction(Wal *pWal);
-+ /* Step 5. If a usable page buffer has still not been found,
-+ ** attempt to allocate a new one.
-+ */
-+ if( !pPage ){
-+ if( createFlag==1 ) sqlite3BeginBenignMalloc();
-+ pPage = pcache1AllocPage(pCache);
-+ if( createFlag==1 ) sqlite3EndBenignMalloc();
-+ }
-
--/* Undo any frames written (but not committed) to the log */
--SQLITE_PRIVATE int sqlite3WalUndo(Wal *pWal, int (*xUndo)(void *, Pgno), void *pUndoCtx);
-+ if( pPage ){
-+ unsigned int h = iKey % pCache->nHash;
-+ pCache->nPage++;
-+ pPage->iKey = iKey;
-+ pPage->pNext = pCache->apHash[h];
-+ pPage->pCache = pCache;
-+ pPage->pLruPrev = 0;
-+ pPage->pLruNext = 0;
-+ *(void **)pPage->page.pExtra = 0;
-+ pCache->apHash[h] = pPage;
-+ }
-
--/* Return an integer that records the current (uncommitted) write
--** position in the WAL */
--SQLITE_PRIVATE void sqlite3WalSavepoint(Wal *pWal, u32 *aWalData);
-+fetch_out:
-+ if( pPage && iKey>pCache->iMaxKey ){
-+ pCache->iMaxKey = iKey;
-+ }
-+ pcache1LeaveMutex(pGroup);
-+ return &pPage->page;
-+}
-
--/* Move the write position of the WAL back to iFrame. Called in
--** response to a ROLLBACK TO command. */
--SQLITE_PRIVATE int sqlite3WalSavepointUndo(Wal *pWal, u32 *aWalData);
-
--/* Write a frame or frames to the log. */
--SQLITE_PRIVATE int sqlite3WalFrames(Wal *pWal, int, PgHdr *, Pgno, int, int);
-+/*
-+** Implementation of the sqlite3_pcache.xUnpin method.
-+**
-+** Mark a page as unpinned (eligible for asynchronous recycling).
-+*/
-+static void pcache1Unpin(
-+ sqlite3_pcache *p,
-+ sqlite3_pcache_page *pPg,
-+ int reuseUnlikely
-+){
-+ PCache1 *pCache = (PCache1 *)p;
-+ PgHdr1 *pPage = (PgHdr1 *)pPg;
-+ PGroup *pGroup = pCache->pGroup;
-+
-+ assert( pPage->pCache==pCache );
-+ pcache1EnterMutex(pGroup);
-
--/* Copy pages from the log to the database file */
--SQLITE_PRIVATE int sqlite3WalCheckpoint(
-- Wal *pWal, /* Write-ahead log connection */
-- int eMode, /* One of PASSIVE, FULL and RESTART */
-- int (*xBusy)(void*), /* Function to call when busy */
-- void *pBusyArg, /* Context argument for xBusyHandler */
-- int sync_flags, /* Flags to sync db file with (or 0) */
-- int nBuf, /* Size of buffer nBuf */
-- u8 *zBuf, /* Temporary buffer to use */
-- int *pnLog, /* OUT: Number of frames in WAL */
-- int *pnCkpt /* OUT: Number of backfilled frames in WAL */
--);
-+ /* It is an error to call this function if the page is already
-+ ** part of the PGroup LRU list.
-+ */
-+ assert( pPage->pLruPrev==0 && pPage->pLruNext==0 );
-+ assert( pGroup->pLruHead!=pPage && pGroup->pLruTail!=pPage );
-
--/* Return the value to pass to a sqlite3_wal_hook callback, the
--** number of frames in the WAL at the point of the last commit since
--** sqlite3WalCallback() was called. If no commits have occurred since
--** the last call, then return 0.
--*/
--SQLITE_PRIVATE int sqlite3WalCallback(Wal *pWal);
-+ if( reuseUnlikely || pGroup->nCurrentPage>pGroup->nMaxPage ){
-+ pcache1RemoveFromHash(pPage);
-+ pcache1FreePage(pPage);
-+ }else{
-+ /* Add the page to the PGroup LRU list. */
-+ if( pGroup->pLruHead ){
-+ pGroup->pLruHead->pLruPrev = pPage;
-+ pPage->pLruNext = pGroup->pLruHead;
-+ pGroup->pLruHead = pPage;
-+ }else{
-+ pGroup->pLruTail = pPage;
-+ pGroup->pLruHead = pPage;
-+ }
-+ pCache->nRecyclable++;
-+ }
-
--/* Tell the wal layer that an EXCLUSIVE lock has been obtained (or released)
--** by the pager layer on the database file.
--*/
--SQLITE_PRIVATE int sqlite3WalExclusiveMode(Wal *pWal, int op);
-+ pcache1LeaveMutex(pCache->pGroup);
-+}
-
--/* Return true if the argument is non-NULL and the WAL module is using
--** heap-memory for the wal-index. Otherwise, if the argument is NULL or the
--** WAL module is using shared-memory, return false.
-+/*
-+** Implementation of the sqlite3_pcache.xRekey method.
- */
--SQLITE_PRIVATE int sqlite3WalHeapMemory(Wal *pWal);
-+static void pcache1Rekey(
-+ sqlite3_pcache *p,
-+ sqlite3_pcache_page *pPg,
-+ unsigned int iOld,
-+ unsigned int iNew
-+){
-+ PCache1 *pCache = (PCache1 *)p;
-+ PgHdr1 *pPage = (PgHdr1 *)pPg;
-+ PgHdr1 **pp;
-+ unsigned int h;
-+ assert( pPage->iKey==iOld );
-+ assert( pPage->pCache==pCache );
-
--#ifdef SQLITE_ENABLE_ZIPVFS
--/* If the WAL file is not empty, return the number of bytes of content
--** stored in each frame (i.e. the db page-size when the WAL was created).
--*/
--SQLITE_PRIVATE int sqlite3WalFramesize(Wal *pWal);
--#endif
-+ pcache1EnterMutex(pCache->pGroup);
-
--#endif /* ifndef SQLITE_OMIT_WAL */
--#endif /* _WAL_H_ */
-+ h = iOld%pCache->nHash;
-+ pp = &pCache->apHash[h];
-+ while( (*pp)!=pPage ){
-+ pp = &(*pp)->pNext;
-+ }
-+ *pp = pPage->pNext;
-
--/************** End of wal.h *************************************************/
--/************** Continuing where we left off in pager.c **********************/
-+ h = iNew%pCache->nHash;
-+ pPage->iKey = iNew;
-+ pPage->pNext = pCache->apHash[h];
-+ pCache->apHash[h] = pPage;
-+ if( iNew>pCache->iMaxKey ){
-+ pCache->iMaxKey = iNew;
-+ }
-
-+ pcache1LeaveMutex(pCache->pGroup);
-+}
-
--/******************* NOTES ON THE DESIGN OF THE PAGER ************************
--**
--** This comment block describes invariants that hold when using a rollback
--** journal. These invariants do not apply for journal_mode=WAL,
--** journal_mode=MEMORY, or journal_mode=OFF.
--**
--** Within this comment block, a page is deemed to have been synced
--** automatically as soon as it is written when PRAGMA synchronous=OFF.
--** Otherwise, the page is not synced until the xSync method of the VFS
--** is called successfully on the file containing the page.
--**
--** Definition: A page of the database file is said to be "overwriteable" if
--** one or more of the following are true about the page:
--**
--** (a) The original content of the page as it was at the beginning of
--** the transaction has been written into the rollback journal and
--** synced.
--**
--** (b) The page was a freelist leaf page at the start of the transaction.
--**
--** (c) The page number is greater than the largest page that existed in
--** the database file at the start of the transaction.
--**
--** (1) A page of the database file is never overwritten unless one of the
--** following are true:
--**
--** (a) The page and all other pages on the same sector are overwriteable.
--**
--** (b) The atomic page write optimization is enabled, and the entire
--** transaction other than the update of the transaction sequence
--** number consists of a single page change.
--**
--** (2) The content of a page written into the rollback journal exactly matches
--** both the content in the database when the rollback journal was written
--** and the content in the database at the beginning of the current
--** transaction.
--**
--** (3) Writes to the database file are an integer multiple of the page size
--** in length and are aligned on a page boundary.
--**
--** (4) Reads from the database file are either aligned on a page boundary and
--** an integer multiple of the page size in length or are taken from the
--** first 100 bytes of the database file.
--**
--** (5) All writes to the database file are synced prior to the rollback journal
--** being deleted, truncated, or zeroed.
--**
--** (6) If a master journal file is used, then all writes to the database file
--** are synced prior to the master journal being deleted.
--**
--** Definition: Two databases (or the same database at two points it time)
--** are said to be "logically equivalent" if they give the same answer to
--** all queries. Note in particular the content of freelist leaf
--** pages can be changed arbitarily without effecting the logical equivalence
--** of the database.
--**
--** (7) At any time, if any subset, including the empty set and the total set,
--** of the unsynced changes to a rollback journal are removed and the
--** journal is rolled back, the resulting database file will be logical
--** equivalent to the database file at the beginning of the transaction.
--**
--** (8) When a transaction is rolled back, the xTruncate method of the VFS
--** is called to restore the database file to the same size it was at
--** the beginning of the transaction. (In some VFSes, the xTruncate
--** method is a no-op, but that does not change the fact the SQLite will
--** invoke it.)
--**
--** (9) Whenever the database file is modified, at least one bit in the range
--** of bytes from 24 through 39 inclusive will be changed prior to releasing
--** the EXCLUSIVE lock, thus signaling other connections on the same
--** database to flush their caches.
--**
--** (10) The pattern of bits in bytes 24 through 39 shall not repeat in less
--** than one billion transactions.
--**
--** (11) A database file is well-formed at the beginning and at the conclusion
--** of every transaction.
--**
--** (12) An EXCLUSIVE lock is held on the database file when writing to
--** the database file.
-+/*
-+** Implementation of the sqlite3_pcache.xTruncate method.
- **
--** (13) A SHARED lock is held on the database file while reading any
--** content out of the database file.
-+** Discard all unpinned pages in the cache with a page number equal to
-+** or greater than parameter iLimit. Any pinned pages with a page number
-+** equal to or greater than iLimit are implicitly unpinned.
-+*/
-+static void pcache1Truncate(sqlite3_pcache *p, unsigned int iLimit){
-+ PCache1 *pCache = (PCache1 *)p;
-+ pcache1EnterMutex(pCache->pGroup);
-+ if( iLimit<=pCache->iMaxKey ){
-+ pcache1TruncateUnsafe(pCache, iLimit);
-+ pCache->iMaxKey = iLimit-1;
-+ }
-+ pcache1LeaveMutex(pCache->pGroup);
-+}
-+
-+/*
-+** Implementation of the sqlite3_pcache.xDestroy method.
- **
--******************************************************************************/
-+** Destroy a cache allocated using pcache1Create().
-+*/
-+static void pcache1Destroy(sqlite3_pcache *p){
-+ PCache1 *pCache = (PCache1 *)p;
-+ PGroup *pGroup = pCache->pGroup;
-+ assert( pCache->bPurgeable || (pCache->nMax==0 && pCache->nMin==0) );
-+ pcache1EnterMutex(pGroup);
-+ pcache1TruncateUnsafe(pCache, 0);
-+ assert( pGroup->nMaxPage >= pCache->nMax );
-+ pGroup->nMaxPage -= pCache->nMax;
-+ assert( pGroup->nMinPage >= pCache->nMin );
-+ pGroup->nMinPage -= pCache->nMin;
-+ pGroup->mxPinned = pGroup->nMaxPage + 10 - pGroup->nMinPage;
-+ pcache1EnforceMaxPage(pGroup);
-+ pcache1LeaveMutex(pGroup);
-+ sqlite3_free(pCache->apHash);
-+ sqlite3_free(pCache);
-+}
-
- /*
--** Macros for troubleshooting. Normally turned off
-+** This function is called during initialization (sqlite3_initialize()) to
-+** install the default pluggable cache module, assuming the user has not
-+** already provided an alternative.
- */
--#if 0
--int sqlite3PagerTrace=1; /* True to enable tracing */
--#define sqlite3DebugPrintf printf
--#define PAGERTRACE(X) if( sqlite3PagerTrace ){ sqlite3DebugPrintf X; }
--#else
--#define PAGERTRACE(X)
--#endif
-+SQLITE_PRIVATE void sqlite3PCacheSetDefault(void){
-+ static const sqlite3_pcache_methods2 defaultMethods = {
-+ 1, /* iVersion */
-+ 0, /* pArg */
-+ pcache1Init, /* xInit */
-+ pcache1Shutdown, /* xShutdown */
-+ pcache1Create, /* xCreate */
-+ pcache1Cachesize, /* xCachesize */
-+ pcache1Pagecount, /* xPagecount */
-+ pcache1Fetch, /* xFetch */
-+ pcache1Unpin, /* xUnpin */
-+ pcache1Rekey, /* xRekey */
-+ pcache1Truncate, /* xTruncate */
-+ pcache1Destroy, /* xDestroy */
-+ pcache1Shrink /* xShrink */
-+ };
-+ sqlite3_config(SQLITE_CONFIG_PCACHE2, &defaultMethods);
-+}
-
-+#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
- /*
--** The following two macros are used within the PAGERTRACE() macros above
--** to print out file-descriptors.
-+** This function is called to free superfluous dynamically allocated memory
-+** held by the pager system. Memory in use by any SQLite pager allocated
-+** by the current thread may be sqlite3_free()ed.
- **
--** PAGERID() takes a pointer to a Pager struct as its argument. The
--** associated file-descriptor is returned. FILEHANDLEID() takes an sqlite3_file
--** struct as its argument.
-+** nReq is the number of bytes of memory required. Once this much has
-+** been released, the function returns. The return value is the total number
-+** of bytes of memory released.
- */
--#define PAGERID(p) ((int)(p->fd))
--#define FILEHANDLEID(fd) ((int)fd)
-+SQLITE_PRIVATE int sqlite3PcacheReleaseMemory(int nReq){
-+ int nFree = 0;
-+ assert( sqlite3_mutex_notheld(pcache1.grp.mutex) );
-+ assert( sqlite3_mutex_notheld(pcache1.mutex) );
-+ if( pcache1.pStart==0 ){
-+ PgHdr1 *p;
-+ pcache1EnterMutex(&pcache1.grp);
-+ while( (nReq<0 || nFree<nReq) && ((p=pcache1.grp.pLruTail)!=0) ){
-+ nFree += pcache1MemSize(p->page.pBuf);
-+#ifdef SQLITE_PCACHE_SEPARATE_HEADER
-+ nFree += sqlite3MemSize(p);
-+#endif
-+ pcache1PinPage(p);
-+ pcache1RemoveFromHash(p);
-+ pcache1FreePage(p);
-+ }
-+ pcache1LeaveMutex(&pcache1.grp);
-+ }
-+ return nFree;
-+}
-+#endif /* SQLITE_ENABLE_MEMORY_MANAGEMENT */
-
-+#ifdef SQLITE_TEST
- /*
--** The Pager.eState variable stores the current 'state' of a pager. A
--** pager may be in any one of the seven states shown in the following
--** state diagram.
--**
--** OPEN <------+------+
--** | | |
--** V | |
--** +---------> READER-------+ |
--** | | |
--** | V |
--** |<-------WRITER_LOCKED------> ERROR
--** | | ^
--** | V |
--** |<------WRITER_CACHEMOD-------->|
--** | | |
--** | V |
--** |<-------WRITER_DBMOD---------->|
--** | | |
--** | V |
--** +<------WRITER_FINISHED-------->+
--**
--**
--** List of state transitions and the C [function] that performs each:
--**
--** OPEN -> READER [sqlite3PagerSharedLock]
--** READER -> OPEN [pager_unlock]
--**
--** READER -> WRITER_LOCKED [sqlite3PagerBegin]
--** WRITER_LOCKED -> WRITER_CACHEMOD [pager_open_journal]
--** WRITER_CACHEMOD -> WRITER_DBMOD [syncJournal]
--** WRITER_DBMOD -> WRITER_FINISHED [sqlite3PagerCommitPhaseOne]
--** WRITER_*** -> READER [pager_end_transaction]
--**
--** WRITER_*** -> ERROR [pager_error]
--** ERROR -> OPEN [pager_unlock]
--**
--**
--** OPEN:
--**
--** The pager starts up in this state. Nothing is guaranteed in this
--** state - the file may or may not be locked and the database size is
--** unknown. The database may not be read or written.
--**
--** * No read or write transaction is active.
--** * Any lock, or no lock at all, may be held on the database file.
--** * The dbSize, dbOrigSize and dbFileSize variables may not be trusted.
--**
--** READER:
--**
--** In this state all the requirements for reading the database in
--** rollback (non-WAL) mode are met. Unless the pager is (or recently
--** was) in exclusive-locking mode, a user-level read transaction is
--** open. The database size is known in this state.
--**
--** A connection running with locking_mode=normal enters this state when
--** it opens a read-transaction on the database and returns to state
--** OPEN after the read-transaction is completed. However a connection
--** running in locking_mode=exclusive (including temp databases) remains in
--** this state even after the read-transaction is closed. The only way
--** a locking_mode=exclusive connection can transition from READER to OPEN
--** is via the ERROR state (see below).
--**
--** * A read transaction may be active (but a write-transaction cannot).
--** * A SHARED or greater lock is held on the database file.
--** * The dbSize variable may be trusted (even if a user-level read
--** transaction is not active). The dbOrigSize and dbFileSize variables
--** may not be trusted at this point.
--** * If the database is a WAL database, then the WAL connection is open.
--** * Even if a read-transaction is not open, it is guaranteed that
--** there is no hot-journal in the file-system.
--**
--** WRITER_LOCKED:
--**
--** The pager moves to this state from READER when a write-transaction
--** is first opened on the database. In WRITER_LOCKED state, all locks
--** required to start a write-transaction are held, but no actual
--** modifications to the cache or database have taken place.
--**
--** In rollback mode, a RESERVED or (if the transaction was opened with
--** BEGIN EXCLUSIVE) EXCLUSIVE lock is obtained on the database file when
--** moving to this state, but the journal file is not written to or opened
--** to in this state. If the transaction is committed or rolled back while
--** in WRITER_LOCKED state, all that is required is to unlock the database
--** file.
--**
--** IN WAL mode, WalBeginWriteTransaction() is called to lock the log file.
--** If the connection is running with locking_mode=exclusive, an attempt
--** is made to obtain an EXCLUSIVE lock on the database file.
--**
--** * A write transaction is active.
--** * If the connection is open in rollback-mode, a RESERVED or greater
--** lock is held on the database file.
--** * If the connection is open in WAL-mode, a WAL write transaction
--** is open (i.e. sqlite3WalBeginWriteTransaction() has been successfully
--** called).
--** * The dbSize, dbOrigSize and dbFileSize variables are all valid.
--** * The contents of the pager cache have not been modified.
--** * The journal file may or may not be open.
--** * Nothing (not even the first header) has been written to the journal.
--**
--** WRITER_CACHEMOD:
--**
--** A pager moves from WRITER_LOCKED state to this state when a page is
--** first modified by the upper layer. In rollback mode the journal file
--** is opened (if it is not already open) and a header written to the
--** start of it. The database file on disk has not been modified.
--**
--** * A write transaction is active.
--** * A RESERVED or greater lock is held on the database file.
--** * The journal file is open and the first header has been written
--** to it, but the header has not been synced to disk.
--** * The contents of the page cache have been modified.
--**
--** WRITER_DBMOD:
--**
--** The pager transitions from WRITER_CACHEMOD into WRITER_DBMOD state
--** when it modifies the contents of the database file. WAL connections
--** never enter this state (since they do not modify the database file,
--** just the log file).
--**
--** * A write transaction is active.
--** * An EXCLUSIVE or greater lock is held on the database file.
--** * The journal file is open and the first header has been written
--** and synced to disk.
--** * The contents of the page cache have been modified (and possibly
--** written to disk).
--**
--** WRITER_FINISHED:
--**
--** It is not possible for a WAL connection to enter this state.
--**
--** A rollback-mode pager changes to WRITER_FINISHED state from WRITER_DBMOD
--** state after the entire transaction has been successfully written into the
--** database file. In this state the transaction may be committed simply
--** by finalizing the journal file. Once in WRITER_FINISHED state, it is
--** not possible to modify the database further. At this point, the upper
--** layer must either commit or rollback the transaction.
--**
--** * A write transaction is active.
--** * An EXCLUSIVE or greater lock is held on the database file.
--** * All writing and syncing of journal and database data has finished.
--** If no error occurred, all that remains is to finalize the journal to
--** commit the transaction. If an error did occur, the caller will need
--** to rollback the transaction.
--**
--** ERROR:
--**
--** The ERROR state is entered when an IO or disk-full error (including
--** SQLITE_IOERR_NOMEM) occurs at a point in the code that makes it
--** difficult to be sure that the in-memory pager state (cache contents,
--** db size etc.) are consistent with the contents of the file-system.
--**
--** Temporary pager files may enter the ERROR state, but in-memory pagers
--** cannot.
--**
--** For example, if an IO error occurs while performing a rollback,
--** the contents of the page-cache may be left in an inconsistent state.
--** At this point it would be dangerous to change back to READER state
--** (as usually happens after a rollback). Any subsequent readers might
--** report database corruption (due to the inconsistent cache), and if
--** they upgrade to writers, they may inadvertently corrupt the database
--** file. To avoid this hazard, the pager switches into the ERROR state
--** instead of READER following such an error.
--**
--** Once it has entered the ERROR state, any attempt to use the pager
--** to read or write data returns an error. Eventually, once all
--** outstanding transactions have been abandoned, the pager is able to
--** transition back to OPEN state, discarding the contents of the
--** page-cache and any other in-memory state at the same time. Everything
--** is reloaded from disk (and, if necessary, hot-journal rollback peformed)
--** when a read-transaction is next opened on the pager (transitioning
--** the pager into READER state). At that point the system has recovered
--** from the error.
--**
--** Specifically, the pager jumps into the ERROR state if:
--**
--** 1. An error occurs while attempting a rollback. This happens in
--** function sqlite3PagerRollback().
--**
--** 2. An error occurs while attempting to finalize a journal file
--** following a commit in function sqlite3PagerCommitPhaseTwo().
-+** This function is used by test procedures to inspect the internal state
-+** of the global cache.
-+*/
-+SQLITE_PRIVATE void sqlite3PcacheStats(
-+ int *pnCurrent, /* OUT: Total number of pages cached */
-+ int *pnMax, /* OUT: Global maximum cache size */
-+ int *pnMin, /* OUT: Sum of PCache1.nMin for purgeable caches */
-+ int *pnRecyclable /* OUT: Total number of pages available for recycling */
-+){
-+ PgHdr1 *p;
-+ int nRecyclable = 0;
-+ for(p=pcache1.grp.pLruHead; p; p=p->pLruNext){
-+ nRecyclable++;
-+ }
-+ *pnCurrent = pcache1.grp.nCurrentPage;
-+ *pnMax = (int)pcache1.grp.nMaxPage;
-+ *pnMin = (int)pcache1.grp.nMinPage;
-+ *pnRecyclable = nRecyclable;
-+}
-+#endif
-+
-+/************** End of pcache1.c *********************************************/
-+/************** Begin file rowset.c ******************************************/
-+/*
-+** 2008 December 3
- **
--** 3. An error occurs while attempting to write to the journal or
--** database file in function pagerStress() in order to free up
--** memory.
-+** The author disclaims copyright to this source code. In place of
-+** a legal notice, here is a blessing:
- **
--** In other cases, the error is returned to the b-tree layer. The b-tree
--** layer then attempts a rollback operation. If the error condition
--** persists, the pager enters the ERROR state via condition (1) above.
-+** May you do good and not evil.
-+** May you find forgiveness for yourself and forgive others.
-+** May you share freely, never taking more than you give.
- **
--** Condition (3) is necessary because it can be triggered by a read-only
--** statement executed within a transaction. In this case, if the error
--** code were simply returned to the user, the b-tree layer would not
--** automatically attempt a rollback, as it assumes that an error in a
--** read-only statement cannot leave the pager in an internally inconsistent
--** state.
-+*************************************************************************
- **
--** * The Pager.errCode variable is set to something other than SQLITE_OK.
--** * There are one or more outstanding references to pages (after the
--** last reference is dropped the pager should move back to OPEN state).
--** * The pager is not an in-memory pager.
--**
-+** This module implements an object we call a "RowSet".
- **
--** Notes:
-+** The RowSet object is a collection of rowids. Rowids
-+** are inserted into the RowSet in an arbitrary order. Inserts
-+** can be intermixed with tests to see if a given rowid has been
-+** previously inserted into the RowSet.
- **
--** * A pager is never in WRITER_DBMOD or WRITER_FINISHED state if the
--** connection is open in WAL mode. A WAL connection is always in one
--** of the first four states.
-+** After all inserts are finished, it is possible to extract the
-+** elements of the RowSet in sorted order. Once this extraction
-+** process has started, no new elements may be inserted.
- **
--** * Normally, a connection open in exclusive mode is never in PAGER_OPEN
--** state. There are two exceptions: immediately after exclusive-mode has
--** been turned on (and before any read or write transactions are
--** executed), and when the pager is leaving the "error state".
-+** Hence, the primitive operations for a RowSet are:
- **
--** * See also: assert_pager_state().
--*/
--#define PAGER_OPEN 0
--#define PAGER_READER 1
--#define PAGER_WRITER_LOCKED 2
--#define PAGER_WRITER_CACHEMOD 3
--#define PAGER_WRITER_DBMOD 4
--#define PAGER_WRITER_FINISHED 5
--#define PAGER_ERROR 6
--
--/*
--** The Pager.eLock variable is almost always set to one of the
--** following locking-states, according to the lock currently held on
--** the database file: NO_LOCK, SHARED_LOCK, RESERVED_LOCK or EXCLUSIVE_LOCK.
--** This variable is kept up to date as locks are taken and released by
--** the pagerLockDb() and pagerUnlockDb() wrappers.
-+** CREATE
-+** INSERT
-+** TEST
-+** SMALLEST
-+** DESTROY
- **
--** If the VFS xLock() or xUnlock() returns an error other than SQLITE_BUSY
--** (i.e. one of the SQLITE_IOERR subtypes), it is not clear whether or not
--** the operation was successful. In these circumstances pagerLockDb() and
--** pagerUnlockDb() take a conservative approach - eLock is always updated
--** when unlocking the file, and only updated when locking the file if the
--** VFS call is successful. This way, the Pager.eLock variable may be set
--** to a less exclusive (lower) value than the lock that is actually held
--** at the system level, but it is never set to a more exclusive value.
-+** The CREATE and DESTROY primitives are the constructor and destructor,
-+** obviously. The INSERT primitive adds a new element to the RowSet.
-+** TEST checks to see if an element is already in the RowSet. SMALLEST
-+** extracts the least value from the RowSet.
- **
--** This is usually safe. If an xUnlock fails or appears to fail, there may
--** be a few redundant xLock() calls or a lock may be held for longer than
--** required, but nothing really goes wrong.
-+** The INSERT primitive might allocate additional memory. Memory is
-+** allocated in chunks so most INSERTs do no allocation. There is an
-+** upper bound on the size of allocated memory. No memory is freed
-+** until DESTROY.
- **
--** The exception is when the database file is unlocked as the pager moves
--** from ERROR to OPEN state. At this point there may be a hot-journal file
--** in the file-system that needs to be rolled back (as part of a OPEN->SHARED
--** transition, by the same pager or any other). If the call to xUnlock()
--** fails at this point and the pager is left holding an EXCLUSIVE lock, this
--** can confuse the call to xCheckReservedLock() call made later as part
--** of hot-journal detection.
-+** The TEST primitive includes a "batch" number. The TEST primitive
-+** will only see elements that were inserted before the last change
-+** in the batch number. In other words, if an INSERT occurs between
-+** two TESTs where the TESTs have the same batch nubmer, then the
-+** value added by the INSERT will not be visible to the second TEST.
-+** The initial batch number is zero, so if the very first TEST contains
-+** a non-zero batch number, it will see all prior INSERTs.
- **
--** xCheckReservedLock() is defined as returning true "if there is a RESERVED
--** lock held by this process or any others". So xCheckReservedLock may
--** return true because the caller itself is holding an EXCLUSIVE lock (but
--** doesn't know it because of a previous error in xUnlock). If this happens
--** a hot-journal may be mistaken for a journal being created by an active
--** transaction in another process, causing SQLite to read from the database
--** without rolling it back.
-+** No INSERTs may occurs after a SMALLEST. An assertion will fail if
-+** that is attempted.
- **
--** To work around this, if a call to xUnlock() fails when unlocking the
--** database in the ERROR state, Pager.eLock is set to UNKNOWN_LOCK. It
--** is only changed back to a real locking state after a successful call
--** to xLock(EXCLUSIVE). Also, the code to do the OPEN->SHARED state transition
--** omits the check for a hot-journal if Pager.eLock is set to UNKNOWN_LOCK
--** lock. Instead, it assumes a hot-journal exists and obtains an EXCLUSIVE
--** lock on the database file before attempting to roll it back. See function
--** PagerSharedLock() for more detail.
-+** The cost of an INSERT is roughly constant. (Sometime new memory
-+** has to be allocated on an INSERT.) The cost of a TEST with a new
-+** batch number is O(NlogN) where N is the number of elements in the RowSet.
-+** The cost of a TEST using the same batch number is O(logN). The cost
-+** of the first SMALLEST is O(NlogN). Second and subsequent SMALLEST
-+** primitives are constant time. The cost of DESTROY is O(N).
- **
--** Pager.eLock may only be set to UNKNOWN_LOCK when the pager is in
--** PAGER_OPEN state.
-+** There is an added cost of O(N) when switching between TEST and
-+** SMALLEST primitives.
- */
--#define UNKNOWN_LOCK (EXCLUSIVE_LOCK+1)
-+
-
- /*
--** A macro used for invoking the codec if there is one
-+** Target size for allocation chunks.
- */
--#ifdef SQLITE_HAS_CODEC
--# define CODEC1(P,D,N,X,E) \
-- if( P->xCodec && P->xCodec(P->pCodec,D,N,X)==0 ){ E; }
--# define CODEC2(P,D,N,X,E,O) \
-- if( P->xCodec==0 ){ O=(char*)D; }else \
-- if( (O=(char*)(P->xCodec(P->pCodec,D,N,X)))==0 ){ E; }
--#else
--# define CODEC1(P,D,N,X,E) /* NO-OP */
--# define CODEC2(P,D,N,X,E,O) O=(char*)D
--#endif
-+#define ROWSET_ALLOCATION_SIZE 1024
-
- /*
--** The maximum allowed sector size. 64KiB. If the xSectorsize() method
--** returns a value larger than this, then MAX_SECTOR_SIZE is used instead.
--** This could conceivably cause corruption following a power failure on
--** such a system. This is currently an undocumented limit.
-+** The number of rowset entries per allocation chunk.
- */
--#define MAX_SECTOR_SIZE 0x10000
-+#define ROWSET_ENTRY_PER_CHUNK \
-+ ((ROWSET_ALLOCATION_SIZE-8)/sizeof(struct RowSetEntry))
-
- /*
--** An instance of the following structure is allocated for each active
--** savepoint and statement transaction in the system. All such structures
--** are stored in the Pager.aSavepoint[] array, which is allocated and
--** resized using sqlite3Realloc().
-+** Each entry in a RowSet is an instance of the following object.
- **
--** When a savepoint is created, the PagerSavepoint.iHdrOffset field is
--** set to 0. If a journal-header is written into the main journal while
--** the savepoint is active, then iHdrOffset is set to the byte offset
--** immediately following the last journal record written into the main
--** journal before the journal-header. This is required during savepoint
--** rollback (see pagerPlaybackSavepoint()).
-+** This same object is reused to store a linked list of trees of RowSetEntry
-+** objects. In that alternative use, pRight points to the next entry
-+** in the list, pLeft points to the tree, and v is unused. The
-+** RowSet.pForest value points to the head of this forest list.
- */
--typedef struct PagerSavepoint PagerSavepoint;
--struct PagerSavepoint {
-- i64 iOffset; /* Starting offset in main journal */
-- i64 iHdrOffset; /* See above */
-- Bitvec *pInSavepoint; /* Set of pages in this savepoint */
-- Pgno nOrig; /* Original number of pages in file */
-- Pgno iSubRec; /* Index of first record in sub-journal */
--#ifndef SQLITE_OMIT_WAL
-- u32 aWalData[WAL_SAVEPOINT_NDATA]; /* WAL savepoint context */
--#endif
-+struct RowSetEntry {
-+ i64 v; /* ROWID value for this entry */
-+ struct RowSetEntry *pRight; /* Right subtree (larger entries) or list */
-+ struct RowSetEntry *pLeft; /* Left subtree (smaller entries) */
- };
-
- /*
--** A open page cache is an instance of struct Pager. A description of
--** some of the more important member variables follows:
--**
--** eState
--**
--** The current 'state' of the pager object. See the comment and state
--** diagram above for a description of the pager state.
--**
--** eLock
--**
--** For a real on-disk database, the current lock held on the database file -
--** NO_LOCK, SHARED_LOCK, RESERVED_LOCK or EXCLUSIVE_LOCK.
--**
--** For a temporary or in-memory database (neither of which require any
--** locks), this variable is always set to EXCLUSIVE_LOCK. Since such
--** databases always have Pager.exclusiveMode==1, this tricks the pager
--** logic into thinking that it already has all the locks it will ever
--** need (and no reason to release them).
--**
--** In some (obscure) circumstances, this variable may also be set to
--** UNKNOWN_LOCK. See the comment above the #define of UNKNOWN_LOCK for
--** details.
--**
--** changeCountDone
--**
--** This boolean variable is used to make sure that the change-counter
--** (the 4-byte header field at byte offset 24 of the database file) is
--** not updated more often than necessary.
--**
--** It is set to true when the change-counter field is updated, which
--** can only happen if an exclusive lock is held on the database file.
--** It is cleared (set to false) whenever an exclusive lock is
--** relinquished on the database file. Each time a transaction is committed,
--** The changeCountDone flag is inspected. If it is true, the work of
--** updating the change-counter is omitted for the current transaction.
--**
--** This mechanism means that when running in exclusive mode, a connection
--** need only update the change-counter once, for the first transaction
--** committed.
--**
--** setMaster
--**
--** When PagerCommitPhaseOne() is called to commit a transaction, it may
--** (or may not) specify a master-journal name to be written into the
--** journal file before it is synced to disk.
--**
--** Whether or not a journal file contains a master-journal pointer affects
--** the way in which the journal file is finalized after the transaction is
--** committed or rolled back when running in "journal_mode=PERSIST" mode.
--** If a journal file does not contain a master-journal pointer, it is
--** finalized by overwriting the first journal header with zeroes. If
--** it does contain a master-journal pointer the journal file is finalized
--** by truncating it to zero bytes, just as if the connection were
--** running in "journal_mode=truncate" mode.
--**
--** Journal files that contain master journal pointers cannot be finalized
--** simply by overwriting the first journal-header with zeroes, as the
--** master journal pointer could interfere with hot-journal rollback of any
--** subsequently interrupted transaction that reuses the journal file.
--**
--** The flag is cleared as soon as the journal file is finalized (either
--** by PagerCommitPhaseTwo or PagerRollback). If an IO error prevents the
--** journal file from being successfully finalized, the setMaster flag
--** is cleared anyway (and the pager will move to ERROR state).
--**
--** doNotSpill, doNotSyncSpill
-+** RowSetEntry objects are allocated in large chunks (instances of the
-+** following structure) to reduce memory allocation overhead. The
-+** chunks are kept on a linked list so that they can be deallocated
-+** when the RowSet is destroyed.
-+*/
-+struct RowSetChunk {
-+ struct RowSetChunk *pNextChunk; /* Next chunk on list of them all */
-+ struct RowSetEntry aEntry[ROWSET_ENTRY_PER_CHUNK]; /* Allocated entries */
-+};
-+
-+/*
-+** A RowSet in an instance of the following structure.
- **
--** These two boolean variables control the behavior of cache-spills
--** (calls made by the pcache module to the pagerStress() routine to
--** write cached data to the file-system in order to free up memory).
-+** A typedef of this structure if found in sqliteInt.h.
-+*/
-+struct RowSet {
-+ struct RowSetChunk *pChunk; /* List of all chunk allocations */
-+ sqlite3 *db; /* The database connection */
-+ struct RowSetEntry *pEntry; /* List of entries using pRight */
-+ struct RowSetEntry *pLast; /* Last entry on the pEntry list */
-+ struct RowSetEntry *pFresh; /* Source of new entry objects */
-+ struct RowSetEntry *pForest; /* List of binary trees of entries */
-+ u16 nFresh; /* Number of objects on pFresh */
-+ u8 rsFlags; /* Various flags */
-+ u8 iBatch; /* Current insert batch */
-+};
-+
-+/*
-+** Allowed values for RowSet.rsFlags
-+*/
-+#define ROWSET_SORTED 0x01 /* True if RowSet.pEntry is sorted */
-+#define ROWSET_NEXT 0x02 /* True if sqlite3RowSetNext() has been called */
-+
-+/*
-+** Turn bulk memory into a RowSet object. N bytes of memory
-+** are available at pSpace. The db pointer is used as a memory context
-+** for any subsequent allocations that need to occur.
-+** Return a pointer to the new RowSet object.
- **
--** When doNotSpill is non-zero, writing to the database from pagerStress()
--** is disabled altogether. This is done in a very obscure case that
--** comes up during savepoint rollback that requires the pcache module
--** to allocate a new page to prevent the journal file from being written
--** while it is being traversed by code in pager_playback().
-+** It must be the case that N is sufficient to make a Rowset. If not
-+** an assertion fault occurs.
- **
--** If doNotSyncSpill is non-zero, writing to the database from pagerStress()
--** is permitted, but syncing the journal file is not. This flag is set
--** by sqlite3PagerWrite() when the file-system sector-size is larger than
--** the database page-size in order to prevent a journal sync from happening
--** in between the journalling of two pages on the same sector.
--**
--** subjInMemory
--**
--** This is a boolean variable. If true, then any required sub-journal
--** is opened as an in-memory journal file. If false, then in-memory
--** sub-journals are only used for in-memory pager files.
--**
--** This variable is updated by the upper layer each time a new
--** write-transaction is opened.
--**
--** dbSize, dbOrigSize, dbFileSize
--**
--** Variable dbSize is set to the number of pages in the database file.
--** It is valid in PAGER_READER and higher states (all states except for
--** OPEN and ERROR).
--**
--** dbSize is set based on the size of the database file, which may be
--** larger than the size of the database (the value stored at offset
--** 28 of the database header by the btree). If the size of the file
--** is not an integer multiple of the page-size, the value stored in
--** dbSize is rounded down (i.e. a 5KB file with 2K page-size has dbSize==2).
--** Except, any file that is greater than 0 bytes in size is considered
--** to have at least one page. (i.e. a 1KB file with 2K page-size leads
--** to dbSize==1).
--**
--** During a write-transaction, if pages with page-numbers greater than
--** dbSize are modified in the cache, dbSize is updated accordingly.
--** Similarly, if the database is truncated using PagerTruncateImage(),
--** dbSize is updated.
--**
--** Variables dbOrigSize and dbFileSize are valid in states
--** PAGER_WRITER_LOCKED and higher. dbOrigSize is a copy of the dbSize
--** variable at the start of the transaction. It is used during rollback,
--** and to determine whether or not pages need to be journalled before
--** being modified.
--**
--** Throughout a write-transaction, dbFileSize contains the size of
--** the file on disk in pages. It is set to a copy of dbSize when the
--** write-transaction is first opened, and updated when VFS calls are made
--** to write or truncate the database file on disk.
--**
--** The only reason the dbFileSize variable is required is to suppress
--** unnecessary calls to xTruncate() after committing a transaction. If,
--** when a transaction is committed, the dbFileSize variable indicates
--** that the database file is larger than the database image (Pager.dbSize),
--** pager_truncate() is called. The pager_truncate() call uses xFilesize()
--** to measure the database file on disk, and then truncates it if required.
--** dbFileSize is not used when rolling back a transaction. In this case
--** pager_truncate() is called unconditionally (which means there may be
--** a call to xFilesize() that is not strictly required). In either case,
--** pager_truncate() may cause the file to become smaller or larger.
--**
--** dbHintSize
--**
--** The dbHintSize variable is used to limit the number of calls made to
--** the VFS xFileControl(FCNTL_SIZE_HINT) method.
--**
--** dbHintSize is set to a copy of the dbSize variable when a
--** write-transaction is opened (at the same time as dbFileSize and
--** dbOrigSize). If the xFileControl(FCNTL_SIZE_HINT) method is called,
--** dbHintSize is increased to the number of pages that correspond to the
--** size-hint passed to the method call. See pager_write_pagelist() for
--** details.
--**
--** errCode
-+** If N is larger than the minimum, use the surplus as an initial
-+** allocation of entries available to be filled.
-+*/
-+SQLITE_PRIVATE RowSet *sqlite3RowSetInit(sqlite3 *db, void *pSpace, unsigned int N){
-+ RowSet *p;
-+ assert( N >= ROUND8(sizeof(*p)) );
-+ p = pSpace;
-+ p->pChunk = 0;
-+ p->db = db;
-+ p->pEntry = 0;
-+ p->pLast = 0;
-+ p->pForest = 0;
-+ p->pFresh = (struct RowSetEntry*)(ROUND8(sizeof(*p)) + (char*)p);
-+ p->nFresh = (u16)((N - ROUND8(sizeof(*p)))/sizeof(struct RowSetEntry));
-+ p->rsFlags = ROWSET_SORTED;
-+ p->iBatch = 0;
-+ return p;
-+}
-+
-+/*
-+** Deallocate all chunks from a RowSet. This frees all memory that
-+** the RowSet has allocated over its lifetime. This routine is
-+** the destructor for the RowSet.
-+*/
-+SQLITE_PRIVATE void sqlite3RowSetClear(RowSet *p){
-+ struct RowSetChunk *pChunk, *pNextChunk;
-+ for(pChunk=p->pChunk; pChunk; pChunk = pNextChunk){
-+ pNextChunk = pChunk->pNextChunk;
-+ sqlite3DbFree(p->db, pChunk);
-+ }
-+ p->pChunk = 0;
-+ p->nFresh = 0;
-+ p->pEntry = 0;
-+ p->pLast = 0;
-+ p->pForest = 0;
-+ p->rsFlags = ROWSET_SORTED;
-+}
-+
-+/*
-+** Allocate a new RowSetEntry object that is associated with the
-+** given RowSet. Return a pointer to the new and completely uninitialized
-+** objected.
- **
--** The Pager.errCode variable is only ever used in PAGER_ERROR state. It
--** is set to zero in all other states. In PAGER_ERROR state, Pager.errCode
--** is always set to SQLITE_FULL, SQLITE_IOERR or one of the SQLITE_IOERR_XXX
--** sub-codes.
-+** In an OOM situation, the RowSet.db->mallocFailed flag is set and this
-+** routine returns NULL.
- */
--struct Pager {
-- sqlite3_vfs *pVfs; /* OS functions to use for IO */
-- u8 exclusiveMode; /* Boolean. True if locking_mode==EXCLUSIVE */
-- u8 journalMode; /* One of the PAGER_JOURNALMODE_* values */
-- u8 useJournal; /* Use a rollback journal on this file */
-- u8 noSync; /* Do not sync the journal if true */
-- u8 fullSync; /* Do extra syncs of the journal for robustness */
-- u8 ckptSyncFlags; /* SYNC_NORMAL or SYNC_FULL for checkpoint */
-- u8 walSyncFlags; /* SYNC_NORMAL or SYNC_FULL for wal writes */
-- u8 syncFlags; /* SYNC_NORMAL or SYNC_FULL otherwise */
-- u8 tempFile; /* zFilename is a temporary file */
-- u8 readOnly; /* True for a read-only database */
-- u8 memDb; /* True to inhibit all file I/O */
-+static struct RowSetEntry *rowSetEntryAlloc(RowSet *p){
-+ assert( p!=0 );
-+ if( p->nFresh==0 ){
-+ struct RowSetChunk *pNew;
-+ pNew = sqlite3DbMallocRaw(p->db, sizeof(*pNew));
-+ if( pNew==0 ){
-+ return 0;
-+ }
-+ pNew->pNextChunk = p->pChunk;
-+ p->pChunk = pNew;
-+ p->pFresh = pNew->aEntry;
-+ p->nFresh = ROWSET_ENTRY_PER_CHUNK;
-+ }
-+ p->nFresh--;
-+ return p->pFresh++;
-+}
-
-- /**************************************************************************
-- ** The following block contains those class members that change during
-- ** routine opertion. Class members not in this block are either fixed
-- ** when the pager is first created or else only change when there is a
-- ** significant mode change (such as changing the page_size, locking_mode,
-- ** or the journal_mode). From another view, these class members describe
-- ** the "state" of the pager, while other class members describe the
-- ** "configuration" of the pager.
-- */
-- u8 eState; /* Pager state (OPEN, READER, WRITER_LOCKED..) */
-- u8 eLock; /* Current lock held on database file */
-- u8 changeCountDone; /* Set after incrementing the change-counter */
-- u8 setMaster; /* True if a m-j name has been written to jrnl */
-- u8 doNotSpill; /* Do not spill the cache when non-zero */
-- u8 doNotSyncSpill; /* Do not do a spill that requires jrnl sync */
-- u8 subjInMemory; /* True to use in-memory sub-journals */
-- Pgno dbSize; /* Number of pages in the database */
-- Pgno dbOrigSize; /* dbSize before the current transaction */
-- Pgno dbFileSize; /* Number of pages in the database file */
-- Pgno dbHintSize; /* Value passed to FCNTL_SIZE_HINT call */
-- int errCode; /* One of several kinds of errors */
-- int nRec; /* Pages journalled since last j-header written */
-- u32 cksumInit; /* Quasi-random value added to every checksum */
-- u32 nSubRec; /* Number of records written to sub-journal */
-- Bitvec *pInJournal; /* One bit for each page in the database file */
-- sqlite3_file *fd; /* File descriptor for database */
-- sqlite3_file *jfd; /* File descriptor for main journal */
-- sqlite3_file *sjfd; /* File descriptor for sub-journal */
-- i64 journalOff; /* Current write offset in the journal file */
-- i64 journalHdr; /* Byte offset to previous journal header */
-- sqlite3_backup *pBackup; /* Pointer to list of ongoing backup processes */
-- PagerSavepoint *aSavepoint; /* Array of active savepoints */
-- int nSavepoint; /* Number of elements in aSavepoint[] */
-- char dbFileVers[16]; /* Changes whenever database file changes */
-+/*
-+** Insert a new value into a RowSet.
-+**
-+** The mallocFailed flag of the database connection is set if a
-+** memory allocation fails.
-+*/
-+SQLITE_PRIVATE void sqlite3RowSetInsert(RowSet *p, i64 rowid){
-+ struct RowSetEntry *pEntry; /* The new entry */
-+ struct RowSetEntry *pLast; /* The last prior entry */
-
-- u8 bUseFetch; /* True to use xFetch() */
-- int nMmapOut; /* Number of mmap pages currently outstanding */
-- sqlite3_int64 szMmap; /* Desired maximum mmap size */
-- PgHdr *pMmapFreelist; /* List of free mmap page headers (pDirty) */
-- /*
-- ** End of the routinely-changing class members
-- ***************************************************************************/
-+ /* This routine is never called after sqlite3RowSetNext() */
-+ assert( p!=0 && (p->rsFlags & ROWSET_NEXT)==0 );
-
-- u16 nExtra; /* Add this many bytes to each in-memory page */
-- i16 nReserve; /* Number of unused bytes at end of each page */
-- u32 vfsFlags; /* Flags for sqlite3_vfs.xOpen() */
-- u32 sectorSize; /* Assumed sector size during rollback */
-- int pageSize; /* Number of bytes in a page */
-- Pgno mxPgno; /* Maximum allowed size of the database */
-- i64 journalSizeLimit; /* Size limit for persistent journal files */
-- char *zFilename; /* Name of the database file */
-- char *zJournal; /* Name of the journal file */
-- int (*xBusyHandler)(void*); /* Function to call when busy */
-- void *pBusyHandlerArg; /* Context argument for xBusyHandler */
-- int aStat[3]; /* Total cache hits, misses and writes */
--#ifdef SQLITE_TEST
-- int nRead; /* Database pages read */
--#endif
-- void (*xReiniter)(DbPage*); /* Call this routine when reloading pages */
--#ifdef SQLITE_HAS_CODEC
-- void *(*xCodec)(void*,void*,Pgno,int); /* Routine for en/decoding data */
-- void (*xCodecSizeChng)(void*,int,int); /* Notify of page size changes */
-- void (*xCodecFree)(void*); /* Destructor for the codec */
-- void *pCodec; /* First argument to xCodec... methods */
--#endif
-- char *pTmpSpace; /* Pager.pageSize bytes of space for tmp use */
-- PCache *pPCache; /* Pointer to page cache object */
--#ifndef SQLITE_OMIT_WAL
-- Wal *pWal; /* Write-ahead log used by "journal_mode=wal" */
-- char *zWal; /* File name for write-ahead log */
--#endif
--};
-+ pEntry = rowSetEntryAlloc(p);
-+ if( pEntry==0 ) return;
-+ pEntry->v = rowid;
-+ pEntry->pRight = 0;
-+ pLast = p->pLast;
-+ if( pLast ){
-+ if( (p->rsFlags & ROWSET_SORTED)!=0 && rowid<=pLast->v ){
-+ p->rsFlags &= ~ROWSET_SORTED;
-+ }
-+ pLast->pRight = pEntry;
-+ }else{
-+ p->pEntry = pEntry;
-+ }
-+ p->pLast = pEntry;
-+}
-
- /*
--** Indexes for use with Pager.aStat[]. The Pager.aStat[] array contains
--** the values accessed by passing SQLITE_DBSTATUS_CACHE_HIT, CACHE_MISS
--** or CACHE_WRITE to sqlite3_db_status().
-+** Merge two lists of RowSetEntry objects. Remove duplicates.
-+**
-+** The input lists are connected via pRight pointers and are
-+** assumed to each already be in sorted order.
- */
--#define PAGER_STAT_HIT 0
--#define PAGER_STAT_MISS 1
--#define PAGER_STAT_WRITE 2
-+static struct RowSetEntry *rowSetEntryMerge(
-+ struct RowSetEntry *pA, /* First sorted list to be merged */
-+ struct RowSetEntry *pB /* Second sorted list to be merged */
-+){
-+ struct RowSetEntry head;
-+ struct RowSetEntry *pTail;
-+
-+ pTail = &head;
-+ while( pA && pB ){
-+ assert( pA->pRight==0 || pA->v<=pA->pRight->v );
-+ assert( pB->pRight==0 || pB->v<=pB->pRight->v );
-+ if( pA->v<pB->v ){
-+ pTail->pRight = pA;
-+ pA = pA->pRight;
-+ pTail = pTail->pRight;
-+ }else if( pB->v<pA->v ){
-+ pTail->pRight = pB;
-+ pB = pB->pRight;
-+ pTail = pTail->pRight;
-+ }else{
-+ pA = pA->pRight;
-+ }
-+ }
-+ if( pA ){
-+ assert( pA->pRight==0 || pA->v<=pA->pRight->v );
-+ pTail->pRight = pA;
-+ }else{
-+ assert( pB==0 || pB->pRight==0 || pB->v<=pB->pRight->v );
-+ pTail->pRight = pB;
-+ }
-+ return head.pRight;
-+}
-
- /*
--** The following global variables hold counters used for
--** testing purposes only. These variables do not exist in
--** a non-testing build. These variables are not thread-safe.
--*/
--#ifdef SQLITE_TEST
--SQLITE_API int sqlite3_pager_readdb_count = 0; /* Number of full pages read from DB */
--SQLITE_API int sqlite3_pager_writedb_count = 0; /* Number of full pages written to DB */
--SQLITE_API int sqlite3_pager_writej_count = 0; /* Number of pages written to journal */
--# define PAGER_INCR(v) v++
--#else
--# define PAGER_INCR(v)
--#endif
-+** Sort all elements on the list of RowSetEntry objects into order of
-+** increasing v.
-+*/
-+static struct RowSetEntry *rowSetEntrySort(struct RowSetEntry *pIn){
-+ unsigned int i;
-+ struct RowSetEntry *pNext, *aBucket[40];
-
-+ memset(aBucket, 0, sizeof(aBucket));
-+ while( pIn ){
-+ pNext = pIn->pRight;
-+ pIn->pRight = 0;
-+ for(i=0; aBucket[i]; i++){
-+ pIn = rowSetEntryMerge(aBucket[i], pIn);
-+ aBucket[i] = 0;
-+ }
-+ aBucket[i] = pIn;
-+ pIn = pNext;
-+ }
-+ pIn = 0;
-+ for(i=0; i<sizeof(aBucket)/sizeof(aBucket[0]); i++){
-+ pIn = rowSetEntryMerge(pIn, aBucket[i]);
-+ }
-+ return pIn;
-+}
-
-
- /*
--** Journal files begin with the following magic string. The data
--** was obtained from /dev/random. It is used only as a sanity check.
--**
--** Since version 2.8.0, the journal format contains additional sanity
--** checking information. If the power fails while the journal is being
--** written, semi-random garbage data might appear in the journal
--** file after power is restored. If an attempt is then made
--** to roll the journal back, the database could be corrupted. The additional
--** sanity checking data is an attempt to discover the garbage in the
--** journal and ignore it.
--**
--** The sanity checking information for the new journal format consists
--** of a 32-bit checksum on each page of data. The checksum covers both
--** the page number and the pPager->pageSize bytes of data for the page.
--** This cksum is initialized to a 32-bit random value that appears in the
--** journal file right after the header. The random initializer is important,
--** because garbage data that appears at the end of a journal is likely
--** data that was once in other files that have now been deleted. If the
--** garbage data came from an obsolete journal file, the checksums might
--** be correct. But by initializing the checksum to random value which
--** is different for every journal, we minimize that risk.
-+** The input, pIn, is a binary tree (or subtree) of RowSetEntry objects.
-+** Convert this tree into a linked list connected by the pRight pointers
-+** and return pointers to the first and last elements of the new list.
- */
--static const unsigned char aJournalMagic[] = {
-- 0xd9, 0xd5, 0x05, 0xf9, 0x20, 0xa1, 0x63, 0xd7,
--};
-+static void rowSetTreeToList(
-+ struct RowSetEntry *pIn, /* Root of the input tree */
-+ struct RowSetEntry **ppFirst, /* Write head of the output list here */
-+ struct RowSetEntry **ppLast /* Write tail of the output list here */
-+){
-+ assert( pIn!=0 );
-+ if( pIn->pLeft ){
-+ struct RowSetEntry *p;
-+ rowSetTreeToList(pIn->pLeft, ppFirst, &p);
-+ p->pRight = pIn;
-+ }else{
-+ *ppFirst = pIn;
-+ }
-+ if( pIn->pRight ){
-+ rowSetTreeToList(pIn->pRight, &pIn->pRight, ppLast);
-+ }else{
-+ *ppLast = pIn;
-+ }
-+ assert( (*ppLast)->pRight==0 );
-+}
-
--/*
--** The size of the of each page record in the journal is given by
--** the following macro.
--*/
--#define JOURNAL_PG_SZ(pPager) ((pPager->pageSize) + 8)
-
- /*
--** The journal header size for this pager. This is usually the same
--** size as a single disk sector. See also setSectorSize().
-+** Convert a sorted list of elements (connected by pRight) into a binary
-+** tree with depth of iDepth. A depth of 1 means the tree contains a single
-+** node taken from the head of *ppList. A depth of 2 means a tree with
-+** three nodes. And so forth.
-+**
-+** Use as many entries from the input list as required and update the
-+** *ppList to point to the unused elements of the list. If the input
-+** list contains too few elements, then construct an incomplete tree
-+** and leave *ppList set to NULL.
-+**
-+** Return a pointer to the root of the constructed binary tree.
- */
--#define JOURNAL_HDR_SZ(pPager) (pPager->sectorSize)
-+static struct RowSetEntry *rowSetNDeepTree(
-+ struct RowSetEntry **ppList,
-+ int iDepth
-+){
-+ struct RowSetEntry *p; /* Root of the new tree */
-+ struct RowSetEntry *pLeft; /* Left subtree */
-+ if( *ppList==0 ){
-+ return 0;
-+ }
-+ if( iDepth==1 ){
-+ p = *ppList;
-+ *ppList = p->pRight;
-+ p->pLeft = p->pRight = 0;
-+ return p;
-+ }
-+ pLeft = rowSetNDeepTree(ppList, iDepth-1);
-+ p = *ppList;
-+ if( p==0 ){
-+ return pLeft;
-+ }
-+ p->pLeft = pLeft;
-+ *ppList = p->pRight;
-+ p->pRight = rowSetNDeepTree(ppList, iDepth-1);
-+ return p;
-+}
-
- /*
--** The macro MEMDB is true if we are dealing with an in-memory database.
--** We do this as a macro so that if the SQLITE_OMIT_MEMORYDB macro is set,
--** the value of MEMDB will be a constant and the compiler will optimize
--** out code that would never execute.
-+** Convert a sorted list of elements into a binary tree. Make the tree
-+** as deep as it needs to be in order to contain the entire list.
- */
--#ifdef SQLITE_OMIT_MEMORYDB
--# define MEMDB 0
--#else
--# define MEMDB pPager->memDb
--#endif
-+static struct RowSetEntry *rowSetListToTree(struct RowSetEntry *pList){
-+ int iDepth; /* Depth of the tree so far */
-+ struct RowSetEntry *p; /* Current tree root */
-+ struct RowSetEntry *pLeft; /* Left subtree */
-
--/*
--** The macro USEFETCH is true if we are allowed to use the xFetch and xUnfetch
--** interfaces to access the database using memory-mapped I/O.
--*/
--#if SQLITE_MAX_MMAP_SIZE>0
--# define USEFETCH(x) ((x)->bUseFetch)
--#else
--# define USEFETCH(x) 0
--#endif
-+ assert( pList!=0 );
-+ p = pList;
-+ pList = p->pRight;
-+ p->pLeft = p->pRight = 0;
-+ for(iDepth=1; pList; iDepth++){
-+ pLeft = p;
-+ p = pList;
-+ pList = p->pRight;
-+ p->pLeft = pLeft;
-+ p->pRight = rowSetNDeepTree(&pList, iDepth);
-+ }
-+ return p;
-+}
-
- /*
--** The maximum legal page number is (2^31 - 1).
-+** Take all the entries on p->pEntry and on the trees in p->pForest and
-+** sort them all together into one big ordered list on p->pEntry.
-+**
-+** This routine should only be called once in the life of a RowSet.
- */
--#define PAGER_MAX_PGNO 2147483647
-+static void rowSetToList(RowSet *p){
-+
-+ /* This routine is called only once */
-+ assert( p!=0 && (p->rsFlags & ROWSET_NEXT)==0 );
-+
-+ if( (p->rsFlags & ROWSET_SORTED)==0 ){
-+ p->pEntry = rowSetEntrySort(p->pEntry);
-+ }
-+
-+ /* While this module could theoretically support it, sqlite3RowSetNext()
-+ ** is never called after sqlite3RowSetText() for the same RowSet. So
-+ ** there is never a forest to deal with. Should this change, simply
-+ ** remove the assert() and the #if 0. */
-+ assert( p->pForest==0 );
-+#if 0
-+ while( p->pForest ){
-+ struct RowSetEntry *pTree = p->pForest->pLeft;
-+ if( pTree ){
-+ struct RowSetEntry *pHead, *pTail;
-+ rowSetTreeToList(pTree, &pHead, &pTail);
-+ p->pEntry = rowSetEntryMerge(p->pEntry, pHead);
-+ }
-+ p->pForest = p->pForest->pRight;
-+ }
-+#endif
-+ p->rsFlags |= ROWSET_NEXT; /* Verify this routine is never called again */
-+}
-
- /*
--** The argument to this macro is a file descriptor (type sqlite3_file*).
--** Return 0 if it is not open, or non-zero (but not 1) if it is.
--**
--** This is so that expressions can be written as:
--**
--** if( isOpen(pPager->jfd) ){ ...
--**
--** instead of
-+** Extract the smallest element from the RowSet.
-+** Write the element into *pRowid. Return 1 on success. Return
-+** 0 if the RowSet is already empty.
- **
--** if( pPager->jfd->pMethods ){ ...
-+** After this routine has been called, the sqlite3RowSetInsert()
-+** routine may not be called again.
- */
--#define isOpen(pFd) ((pFd)->pMethods)
-+SQLITE_PRIVATE int sqlite3RowSetNext(RowSet *p, i64 *pRowid){
-+ assert( p!=0 );
-
--/*
--** Return true if this pager uses a write-ahead log instead of the usual
--** rollback journal. Otherwise false.
--*/
--#ifndef SQLITE_OMIT_WAL
--static int pagerUseWal(Pager *pPager){
-- return (pPager->pWal!=0);
-+ /* Merge the forest into a single sorted list on first call */
-+ if( (p->rsFlags & ROWSET_NEXT)==0 ) rowSetToList(p);
-+
-+ /* Return the next entry on the list */
-+ if( p->pEntry ){
-+ *pRowid = p->pEntry->v;
-+ p->pEntry = p->pEntry->pRight;
-+ if( p->pEntry==0 ){
-+ sqlite3RowSetClear(p);
-+ }
-+ return 1;
-+ }else{
-+ return 0;
-+ }
- }
--#else
--# define pagerUseWal(x) 0
--# define pagerRollbackWal(x) 0
--# define pagerWalFrames(v,w,x,y) 0
--# define pagerOpenWalIfPresent(z) SQLITE_OK
--# define pagerBeginReadTransaction(z) SQLITE_OK
--#endif
-
--#ifndef NDEBUG
- /*
--** Usage:
--**
--** assert( assert_pager_state(pPager) );
-+** Check to see if element iRowid was inserted into the rowset as
-+** part of any insert batch prior to iBatch. Return 1 or 0.
- **
--** This function runs many asserts to try to find inconsistencies in
--** the internal state of the Pager object.
-+** If this is the first test of a new batch and if there exist entires
-+** on pRowSet->pEntry, then sort those entires into the forest at
-+** pRowSet->pForest so that they can be tested.
- */
--static int assert_pager_state(Pager *p){
-- Pager *pPager = p;
--
-- /* State must be valid. */
-- assert( p->eState==PAGER_OPEN
-- || p->eState==PAGER_READER
-- || p->eState==PAGER_WRITER_LOCKED
-- || p->eState==PAGER_WRITER_CACHEMOD
-- || p->eState==PAGER_WRITER_DBMOD
-- || p->eState==PAGER_WRITER_FINISHED
-- || p->eState==PAGER_ERROR
-- );
-+SQLITE_PRIVATE int sqlite3RowSetTest(RowSet *pRowSet, u8 iBatch, sqlite3_int64 iRowid){
-+ struct RowSetEntry *p, *pTree;
-
-- /* Regardless of the current state, a temp-file connection always behaves
-- ** as if it has an exclusive lock on the database file. It never updates
-- ** the change-counter field, so the changeCountDone flag is always set.
-- */
-- assert( p->tempFile==0 || p->eLock==EXCLUSIVE_LOCK );
-- assert( p->tempFile==0 || pPager->changeCountDone );
-+ /* This routine is never called after sqlite3RowSetNext() */
-+ assert( pRowSet!=0 && (pRowSet->rsFlags & ROWSET_NEXT)==0 );
-
-- /* If the useJournal flag is clear, the journal-mode must be "OFF".
-- ** And if the journal-mode is "OFF", the journal file must not be open.
-+ /* Sort entries into the forest on the first test of a new batch
- */
-- assert( p->journalMode==PAGER_JOURNALMODE_OFF || p->useJournal );
-- assert( p->journalMode!=PAGER_JOURNALMODE_OFF || !isOpen(p->jfd) );
-+ if( iBatch!=pRowSet->iBatch ){
-+ p = pRowSet->pEntry;
-+ if( p ){
-+ struct RowSetEntry **ppPrevTree = &pRowSet->pForest;
-+ if( (pRowSet->rsFlags & ROWSET_SORTED)==0 ){
-+ p = rowSetEntrySort(p);
-+ }
-+ for(pTree = pRowSet->pForest; pTree; pTree=pTree->pRight){
-+ ppPrevTree = &pTree->pRight;
-+ if( pTree->pLeft==0 ){
-+ pTree->pLeft = rowSetListToTree(p);
-+ break;
-+ }else{
-+ struct RowSetEntry *pAux, *pTail;
-+ rowSetTreeToList(pTree->pLeft, &pAux, &pTail);
-+ pTree->pLeft = 0;
-+ p = rowSetEntryMerge(pAux, p);
-+ }
-+ }
-+ if( pTree==0 ){
-+ *ppPrevTree = pTree = rowSetEntryAlloc(pRowSet);
-+ if( pTree ){
-+ pTree->v = 0;
-+ pTree->pRight = 0;
-+ pTree->pLeft = rowSetListToTree(p);
-+ }
-+ }
-+ pRowSet->pEntry = 0;
-+ pRowSet->pLast = 0;
-+ pRowSet->rsFlags |= ROWSET_SORTED;
-+ }
-+ pRowSet->iBatch = iBatch;
-+ }
-
-- /* Check that MEMDB implies noSync. And an in-memory journal. Since
-- ** this means an in-memory pager performs no IO at all, it cannot encounter
-- ** either SQLITE_IOERR or SQLITE_FULL during rollback or while finalizing
-- ** a journal file. (although the in-memory journal implementation may
-- ** return SQLITE_IOERR_NOMEM while the journal file is being written). It
-- ** is therefore not possible for an in-memory pager to enter the ERROR
-- ** state.
-+ /* Test to see if the iRowid value appears anywhere in the forest.
-+ ** Return 1 if it does and 0 if not.
- */
-- if( MEMDB ){
-- assert( p->noSync );
-- assert( p->journalMode==PAGER_JOURNALMODE_OFF
-- || p->journalMode==PAGER_JOURNALMODE_MEMORY
-- );
-- assert( p->eState!=PAGER_ERROR && p->eState!=PAGER_OPEN );
-- assert( pagerUseWal(p)==0 );
-+ for(pTree = pRowSet->pForest; pTree; pTree=pTree->pRight){
-+ p = pTree->pLeft;
-+ while( p ){
-+ if( p->v<iRowid ){
-+ p = p->pRight;
-+ }else if( p->v>iRowid ){
-+ p = p->pLeft;
-+ }else{
-+ return 1;
-+ }
-+ }
- }
-+ return 0;
-+}
-
-- /* If changeCountDone is set, a RESERVED lock or greater must be held
-- ** on the file.
-- */
-- assert( pPager->changeCountDone==0 || pPager->eLock>=RESERVED_LOCK );
-- assert( p->eLock!=PENDING_LOCK );
-+/************** End of rowset.c **********************************************/
-+/************** Begin file pager.c *******************************************/
-+/*
-+** 2001 September 15
-+**
-+** The author disclaims copyright to this source code. In place of
-+** a legal notice, here is a blessing:
-+**
-+** May you do good and not evil.
-+** May you find forgiveness for yourself and forgive others.
-+** May you share freely, never taking more than you give.
-+**
-+*************************************************************************
-+** This is the implementation of the page cache subsystem or "pager".
-+**
-+** The pager is used to access a database disk file. It implements
-+** atomic commit and rollback through the use of a journal file that
-+** is separate from the database file. The pager also implements file
-+** locking to prevent two processes from writing the same database
-+** file simultaneously, or one process from reading the database while
-+** another is writing.
-+*/
-+#ifndef SQLITE_OMIT_DISKIO
-+/************** Include wal.h in the middle of pager.c ***********************/
-+/************** Begin file wal.h *********************************************/
-+/*
-+** 2010 February 1
-+**
-+** The author disclaims copyright to this source code. In place of
-+** a legal notice, here is a blessing:
-+**
-+** May you do good and not evil.
-+** May you find forgiveness for yourself and forgive others.
-+** May you share freely, never taking more than you give.
-+**
-+*************************************************************************
-+** This header file defines the interface to the write-ahead logging
-+** system. Refer to the comments below and the header comment attached to
-+** the implementation of each function in log.c for further details.
-+*/
-
-- switch( p->eState ){
-- case PAGER_OPEN:
-- assert( !MEMDB );
-- assert( pPager->errCode==SQLITE_OK );
-- assert( sqlite3PcacheRefCount(pPager->pPCache)==0 || pPager->tempFile );
-- break;
-+#ifndef _WAL_H_
-+#define _WAL_H_
-
-- case PAGER_READER:
-- assert( pPager->errCode==SQLITE_OK );
-- assert( p->eLock!=UNKNOWN_LOCK );
-- assert( p->eLock>=SHARED_LOCK );
-- break;
-
-- case PAGER_WRITER_LOCKED:
-- assert( p->eLock!=UNKNOWN_LOCK );
-- assert( pPager->errCode==SQLITE_OK );
-- if( !pagerUseWal(pPager) ){
-- assert( p->eLock>=RESERVED_LOCK );
-- }
-- assert( pPager->dbSize==pPager->dbOrigSize );
-- assert( pPager->dbOrigSize==pPager->dbFileSize );
-- assert( pPager->dbOrigSize==pPager->dbHintSize );
-- assert( pPager->setMaster==0 );
-- break;
-+/* Additional values that can be added to the sync_flags argument of
-+** sqlite3WalFrames():
-+*/
-+#define WAL_SYNC_TRANSACTIONS 0x20 /* Sync at the end of each transaction */
-+#define SQLITE_SYNC_MASK 0x13 /* Mask off the SQLITE_SYNC_* values */
-
-- case PAGER_WRITER_CACHEMOD:
-- assert( p->eLock!=UNKNOWN_LOCK );
-- assert( pPager->errCode==SQLITE_OK );
-- if( !pagerUseWal(pPager) ){
-- /* It is possible that if journal_mode=wal here that neither the
-- ** journal file nor the WAL file are open. This happens during
-- ** a rollback transaction that switches from journal_mode=off
-- ** to journal_mode=wal.
-- */
-- assert( p->eLock>=RESERVED_LOCK );
-- assert( isOpen(p->jfd)
-- || p->journalMode==PAGER_JOURNALMODE_OFF
-- || p->journalMode==PAGER_JOURNALMODE_WAL
-- );
-- }
-- assert( pPager->dbOrigSize==pPager->dbFileSize );
-- assert( pPager->dbOrigSize==pPager->dbHintSize );
-- break;
-+#ifdef SQLITE_OMIT_WAL
-+# define sqlite3WalOpen(x,y,z) 0
-+# define sqlite3WalLimit(x,y)
-+# define sqlite3WalClose(w,x,y,z) 0
-+# define sqlite3WalBeginReadTransaction(y,z) 0
-+# define sqlite3WalEndReadTransaction(z)
-+# define sqlite3WalDbsize(y) 0
-+# define sqlite3WalBeginWriteTransaction(y) 0
-+# define sqlite3WalEndWriteTransaction(x) 0
-+# define sqlite3WalUndo(x,y,z) 0
-+# define sqlite3WalSavepoint(y,z)
-+# define sqlite3WalSavepointUndo(y,z) 0
-+# define sqlite3WalFrames(u,v,w,x,y,z) 0
-+# define sqlite3WalCheckpoint(r,s,t,u,v,w,x,y,z) 0
-+# define sqlite3WalCallback(z) 0
-+# define sqlite3WalExclusiveMode(y,z) 0
-+# define sqlite3WalHeapMemory(z) 0
-+# define sqlite3WalFramesize(z) 0
-+# define sqlite3WalFindFrame(x,y,z) 0
-+#else
-
-- case PAGER_WRITER_DBMOD:
-- assert( p->eLock==EXCLUSIVE_LOCK );
-- assert( pPager->errCode==SQLITE_OK );
-- assert( !pagerUseWal(pPager) );
-- assert( p->eLock>=EXCLUSIVE_LOCK );
-- assert( isOpen(p->jfd)
-- || p->journalMode==PAGER_JOURNALMODE_OFF
-- || p->journalMode==PAGER_JOURNALMODE_WAL
-- );
-- assert( pPager->dbOrigSize<=pPager->dbHintSize );
-- break;
-+#define WAL_SAVEPOINT_NDATA 4
-
-- case PAGER_WRITER_FINISHED:
-- assert( p->eLock==EXCLUSIVE_LOCK );
-- assert( pPager->errCode==SQLITE_OK );
-- assert( !pagerUseWal(pPager) );
-- assert( isOpen(p->jfd)
-- || p->journalMode==PAGER_JOURNALMODE_OFF
-- || p->journalMode==PAGER_JOURNALMODE_WAL
-- );
-- break;
-+/* Connection to a write-ahead log (WAL) file.
-+** There is one object of this type for each pager.
-+*/
-+typedef struct Wal Wal;
-
-- case PAGER_ERROR:
-- /* There must be at least one outstanding reference to the pager if
-- ** in ERROR state. Otherwise the pager should have already dropped
-- ** back to OPEN state.
-- */
-- assert( pPager->errCode!=SQLITE_OK );
-- assert( sqlite3PcacheRefCount(pPager->pPCache)>0 );
-- break;
-- }
-+/* Open and close a connection to a write-ahead log. */
-+SQLITE_PRIVATE int sqlite3WalOpen(sqlite3_vfs*, sqlite3_file*, const char *, int, i64, Wal**);
-+SQLITE_PRIVATE int sqlite3WalClose(Wal *pWal, int sync_flags, int, u8 *);
-
-- return 1;
--}
--#endif /* ifndef NDEBUG */
-+/* Set the limiting size of a WAL file. */
-+SQLITE_PRIVATE void sqlite3WalLimit(Wal*, i64);
-
--#ifdef SQLITE_DEBUG
--/*
--** Return a pointer to a human readable string in a static buffer
--** containing the state of the Pager object passed as an argument. This
--** is intended to be used within debuggers. For example, as an alternative
--** to "print *pPager" in gdb:
--**
--** (gdb) printf "%s", print_pager_state(pPager)
-+/* Used by readers to open (lock) and close (unlock) a snapshot. A
-+** snapshot is like a read-transaction. It is the state of the database
-+** at an instant in time. sqlite3WalOpenSnapshot gets a read lock and
-+** preserves the current state even if the other threads or processes
-+** write to or checkpoint the WAL. sqlite3WalCloseSnapshot() closes the
-+** transaction and releases the lock.
- */
--static char *print_pager_state(Pager *p){
-- static char zRet[1024];
-+SQLITE_PRIVATE int sqlite3WalBeginReadTransaction(Wal *pWal, int *);
-+SQLITE_PRIVATE void sqlite3WalEndReadTransaction(Wal *pWal);
-
-- sqlite3_snprintf(1024, zRet,
-- "Filename: %s\n"
-- "State: %s errCode=%d\n"
-- "Lock: %s\n"
-- "Locking mode: locking_mode=%s\n"
-- "Journal mode: journal_mode=%s\n"
-- "Backing store: tempFile=%d memDb=%d useJournal=%d\n"
-- "Journal: journalOff=%lld journalHdr=%lld\n"
-- "Size: dbsize=%d dbOrigSize=%d dbFileSize=%d\n"
-- , p->zFilename
-- , p->eState==PAGER_OPEN ? "OPEN" :
-- p->eState==PAGER_READER ? "READER" :
-- p->eState==PAGER_WRITER_LOCKED ? "WRITER_LOCKED" :
-- p->eState==PAGER_WRITER_CACHEMOD ? "WRITER_CACHEMOD" :
-- p->eState==PAGER_WRITER_DBMOD ? "WRITER_DBMOD" :
-- p->eState==PAGER_WRITER_FINISHED ? "WRITER_FINISHED" :
-- p->eState==PAGER_ERROR ? "ERROR" : "?error?"
-- , (int)p->errCode
-- , p->eLock==NO_LOCK ? "NO_LOCK" :
-- p->eLock==RESERVED_LOCK ? "RESERVED" :
-- p->eLock==EXCLUSIVE_LOCK ? "EXCLUSIVE" :
-- p->eLock==SHARED_LOCK ? "SHARED" :
-- p->eLock==UNKNOWN_LOCK ? "UNKNOWN" : "?error?"
-- , p->exclusiveMode ? "exclusive" : "normal"
-- , p->journalMode==PAGER_JOURNALMODE_MEMORY ? "memory" :
-- p->journalMode==PAGER_JOURNALMODE_OFF ? "off" :
-- p->journalMode==PAGER_JOURNALMODE_DELETE ? "delete" :
-- p->journalMode==PAGER_JOURNALMODE_PERSIST ? "persist" :
-- p->journalMode==PAGER_JOURNALMODE_TRUNCATE ? "truncate" :
-- p->journalMode==PAGER_JOURNALMODE_WAL ? "wal" : "?error?"
-- , (int)p->tempFile, (int)p->memDb, (int)p->useJournal
-- , p->journalOff, p->journalHdr
-- , (int)p->dbSize, (int)p->dbOrigSize, (int)p->dbFileSize
-- );
-+/* Read a page from the write-ahead log, if it is present. */
-+SQLITE_PRIVATE int sqlite3WalFindFrame(Wal *, Pgno, u32 *);
-+SQLITE_PRIVATE int sqlite3WalReadFrame(Wal *, u32, int, u8 *);
-
-- return zRet;
--}
--#endif
-+/* If the WAL is not empty, return the size of the database. */
-+SQLITE_PRIVATE Pgno sqlite3WalDbsize(Wal *pWal);
-
--/*
--** Return true if it is necessary to write page *pPg into the sub-journal.
--** A page needs to be written into the sub-journal if there exists one
--** or more open savepoints for which:
--**
--** * The page-number is less than or equal to PagerSavepoint.nOrig, and
--** * The bit corresponding to the page-number is not set in
--** PagerSavepoint.pInSavepoint.
-+/* Obtain or release the WRITER lock. */
-+SQLITE_PRIVATE int sqlite3WalBeginWriteTransaction(Wal *pWal);
-+SQLITE_PRIVATE int sqlite3WalEndWriteTransaction(Wal *pWal);
-+
-+/* Undo any frames written (but not committed) to the log */
-+SQLITE_PRIVATE int sqlite3WalUndo(Wal *pWal, int (*xUndo)(void *, Pgno), void *pUndoCtx);
-+
-+/* Return an integer that records the current (uncommitted) write
-+** position in the WAL */
-+SQLITE_PRIVATE void sqlite3WalSavepoint(Wal *pWal, u32 *aWalData);
-+
-+/* Move the write position of the WAL back to iFrame. Called in
-+** response to a ROLLBACK TO command. */
-+SQLITE_PRIVATE int sqlite3WalSavepointUndo(Wal *pWal, u32 *aWalData);
-+
-+/* Write a frame or frames to the log. */
-+SQLITE_PRIVATE int sqlite3WalFrames(Wal *pWal, int, PgHdr *, Pgno, int, int);
-+
-+/* Copy pages from the log to the database file */
-+SQLITE_PRIVATE int sqlite3WalCheckpoint(
-+ Wal *pWal, /* Write-ahead log connection */
-+ int eMode, /* One of PASSIVE, FULL and RESTART */
-+ int (*xBusy)(void*), /* Function to call when busy */
-+ void *pBusyArg, /* Context argument for xBusyHandler */
-+ int sync_flags, /* Flags to sync db file with (or 0) */
-+ int nBuf, /* Size of buffer nBuf */
-+ u8 *zBuf, /* Temporary buffer to use */
-+ int *pnLog, /* OUT: Number of frames in WAL */
-+ int *pnCkpt /* OUT: Number of backfilled frames in WAL */
-+);
-+
-+/* Return the value to pass to a sqlite3_wal_hook callback, the
-+** number of frames in the WAL at the point of the last commit since
-+** sqlite3WalCallback() was called. If no commits have occurred since
-+** the last call, then return 0.
- */
--static int subjRequiresPage(PgHdr *pPg){
-- Pgno pgno = pPg->pgno;
-- Pager *pPager = pPg->pPager;
-- int i;
-- for(i=0; i<pPager->nSavepoint; i++){
-- PagerSavepoint *p = &pPager->aSavepoint[i];
-- if( p->nOrig>=pgno && 0==sqlite3BitvecTest(p->pInSavepoint, pgno) ){
-- return 1;
-- }
-- }
-- return 0;
--}
-+SQLITE_PRIVATE int sqlite3WalCallback(Wal *pWal);
-
--/*
--** Return true if the page is already in the journal file.
-+/* Tell the wal layer that an EXCLUSIVE lock has been obtained (or released)
-+** by the pager layer on the database file.
- */
--static int pageInJournal(PgHdr *pPg){
-- return sqlite3BitvecTest(pPg->pPager->pInJournal, pPg->pgno);
--}
-+SQLITE_PRIVATE int sqlite3WalExclusiveMode(Wal *pWal, int op);
-
--/*
--** Read a 32-bit integer from the given file descriptor. Store the integer
--** that is read in *pRes. Return SQLITE_OK if everything worked, or an
--** error code is something goes wrong.
--**
--** All values are stored on disk as big-endian.
-+/* Return true if the argument is non-NULL and the WAL module is using
-+** heap-memory for the wal-index. Otherwise, if the argument is NULL or the
-+** WAL module is using shared-memory, return false.
- */
--static int read32bits(sqlite3_file *fd, i64 offset, u32 *pRes){
-- unsigned char ac[4];
-- int rc = sqlite3OsRead(fd, ac, sizeof(ac), offset);
-- if( rc==SQLITE_OK ){
-- *pRes = sqlite3Get4byte(ac);
-- }
-- return rc;
--}
-+SQLITE_PRIVATE int sqlite3WalHeapMemory(Wal *pWal);
-
--/*
--** Write a 32-bit integer into a string buffer in big-endian byte order.
-+#ifdef SQLITE_ENABLE_ZIPVFS
-+/* If the WAL file is not empty, return the number of bytes of content
-+** stored in each frame (i.e. the db page-size when the WAL was created).
- */
--#define put32bits(A,B) sqlite3Put4byte((u8*)A,B)
-+SQLITE_PRIVATE int sqlite3WalFramesize(Wal *pWal);
-+#endif
-+
-+#endif /* ifndef SQLITE_OMIT_WAL */
-+#endif /* _WAL_H_ */
-
-+/************** End of wal.h *************************************************/
-+/************** Continuing where we left off in pager.c **********************/
-+
-+
-+/******************* NOTES ON THE DESIGN OF THE PAGER ************************
-+**
-+** This comment block describes invariants that hold when using a rollback
-+** journal. These invariants do not apply for journal_mode=WAL,
-+** journal_mode=MEMORY, or journal_mode=OFF.
-+**
-+** Within this comment block, a page is deemed to have been synced
-+** automatically as soon as it is written when PRAGMA synchronous=OFF.
-+** Otherwise, the page is not synced until the xSync method of the VFS
-+** is called successfully on the file containing the page.
-+**
-+** Definition: A page of the database file is said to be "overwriteable" if
-+** one or more of the following are true about the page:
-+**
-+** (a) The original content of the page as it was at the beginning of
-+** the transaction has been written into the rollback journal and
-+** synced.
-+**
-+** (b) The page was a freelist leaf page at the start of the transaction.
-+**
-+** (c) The page number is greater than the largest page that existed in
-+** the database file at the start of the transaction.
-+**
-+** (1) A page of the database file is never overwritten unless one of the
-+** following are true:
-+**
-+** (a) The page and all other pages on the same sector are overwriteable.
-+**
-+** (b) The atomic page write optimization is enabled, and the entire
-+** transaction other than the update of the transaction sequence
-+** number consists of a single page change.
-+**
-+** (2) The content of a page written into the rollback journal exactly matches
-+** both the content in the database when the rollback journal was written
-+** and the content in the database at the beginning of the current
-+** transaction.
-+**
-+** (3) Writes to the database file are an integer multiple of the page size
-+** in length and are aligned on a page boundary.
-+**
-+** (4) Reads from the database file are either aligned on a page boundary and
-+** an integer multiple of the page size in length or are taken from the
-+** first 100 bytes of the database file.
-+**
-+** (5) All writes to the database file are synced prior to the rollback journal
-+** being deleted, truncated, or zeroed.
-+**
-+** (6) If a master journal file is used, then all writes to the database file
-+** are synced prior to the master journal being deleted.
-+**
-+** Definition: Two databases (or the same database at two points it time)
-+** are said to be "logically equivalent" if they give the same answer to
-+** all queries. Note in particular the content of freelist leaf
-+** pages can be changed arbitarily without effecting the logical equivalence
-+** of the database.
-+**
-+** (7) At any time, if any subset, including the empty set and the total set,
-+** of the unsynced changes to a rollback journal are removed and the
-+** journal is rolled back, the resulting database file will be logical
-+** equivalent to the database file at the beginning of the transaction.
-+**
-+** (8) When a transaction is rolled back, the xTruncate method of the VFS
-+** is called to restore the database file to the same size it was at
-+** the beginning of the transaction. (In some VFSes, the xTruncate
-+** method is a no-op, but that does not change the fact the SQLite will
-+** invoke it.)
-+**
-+** (9) Whenever the database file is modified, at least one bit in the range
-+** of bytes from 24 through 39 inclusive will be changed prior to releasing
-+** the EXCLUSIVE lock, thus signaling other connections on the same
-+** database to flush their caches.
-+**
-+** (10) The pattern of bits in bytes 24 through 39 shall not repeat in less
-+** than one billion transactions.
-+**
-+** (11) A database file is well-formed at the beginning and at the conclusion
-+** of every transaction.
-+**
-+** (12) An EXCLUSIVE lock is held on the database file when writing to
-+** the database file.
-+**
-+** (13) A SHARED lock is held on the database file while reading any
-+** content out of the database file.
-+**
-+******************************************************************************/
-
- /*
--** Write a 32-bit integer into the given file descriptor. Return SQLITE_OK
--** on success or an error code is something goes wrong.
-+** Macros for troubleshooting. Normally turned off
- */
--static int write32bits(sqlite3_file *fd, i64 offset, u32 val){
-- char ac[4];
-- put32bits(ac, val);
-- return sqlite3OsWrite(fd, ac, 4, offset);
--}
-+#if 0
-+int sqlite3PagerTrace=1; /* True to enable tracing */
-+#define sqlite3DebugPrintf printf
-+#define PAGERTRACE(X) if( sqlite3PagerTrace ){ sqlite3DebugPrintf X; }
-+#else
-+#define PAGERTRACE(X)
-+#endif
-
- /*
--** Unlock the database file to level eLock, which must be either NO_LOCK
--** or SHARED_LOCK. Regardless of whether or not the call to xUnlock()
--** succeeds, set the Pager.eLock variable to match the (attempted) new lock.
-+** The following two macros are used within the PAGERTRACE() macros above
-+** to print out file-descriptors.
- **
--** Except, if Pager.eLock is set to UNKNOWN_LOCK when this function is
--** called, do not modify it. See the comment above the #define of
--** UNKNOWN_LOCK for an explanation of this.
-+** PAGERID() takes a pointer to a Pager struct as its argument. The
-+** associated file-descriptor is returned. FILEHANDLEID() takes an sqlite3_file
-+** struct as its argument.
- */
--static int pagerUnlockDb(Pager *pPager, int eLock){
-- int rc = SQLITE_OK;
--
-- assert( !pPager->exclusiveMode || pPager->eLock==eLock );
-- assert( eLock==NO_LOCK || eLock==SHARED_LOCK );
-- assert( eLock!=NO_LOCK || pagerUseWal(pPager)==0 );
-- if( isOpen(pPager->fd) ){
-- assert( pPager->eLock>=eLock );
-- rc = sqlite3OsUnlock(pPager->fd, eLock);
-- if( pPager->eLock!=UNKNOWN_LOCK ){
-- pPager->eLock = (u8)eLock;
-- }
-- IOTRACE(("UNLOCK %p %d\n", pPager, eLock))
-- }
-- return rc;
--}
-+#define PAGERID(p) ((int)(p->fd))
-+#define FILEHANDLEID(fd) ((int)fd)
-
- /*
--** Lock the database file to level eLock, which must be either SHARED_LOCK,
--** RESERVED_LOCK or EXCLUSIVE_LOCK. If the caller is successful, set the
--** Pager.eLock variable to the new locking state.
-+** The Pager.eState variable stores the current 'state' of a pager. A
-+** pager may be in any one of the seven states shown in the following
-+** state diagram.
-+**
-+** OPEN <------+------+
-+** | | |
-+** V | |
-+** +---------> READER-------+ |
-+** | | |
-+** | V |
-+** |<-------WRITER_LOCKED------> ERROR
-+** | | ^
-+** | V |
-+** |<------WRITER_CACHEMOD-------->|
-+** | | |
-+** | V |
-+** |<-------WRITER_DBMOD---------->|
-+** | | |
-+** | V |
-+** +<------WRITER_FINISHED-------->+
-+**
-+**
-+** List of state transitions and the C [function] that performs each:
-+**
-+** OPEN -> READER [sqlite3PagerSharedLock]
-+** READER -> OPEN [pager_unlock]
-+**
-+** READER -> WRITER_LOCKED [sqlite3PagerBegin]
-+** WRITER_LOCKED -> WRITER_CACHEMOD [pager_open_journal]
-+** WRITER_CACHEMOD -> WRITER_DBMOD [syncJournal]
-+** WRITER_DBMOD -> WRITER_FINISHED [sqlite3PagerCommitPhaseOne]
-+** WRITER_*** -> READER [pager_end_transaction]
-+**
-+** WRITER_*** -> ERROR [pager_error]
-+** ERROR -> OPEN [pager_unlock]
-+**
-+**
-+** OPEN:
-+**
-+** The pager starts up in this state. Nothing is guaranteed in this
-+** state - the file may or may not be locked and the database size is
-+** unknown. The database may not be read or written.
-+**
-+** * No read or write transaction is active.
-+** * Any lock, or no lock at all, may be held on the database file.
-+** * The dbSize, dbOrigSize and dbFileSize variables may not be trusted.
-+**
-+** READER:
-+**
-+** In this state all the requirements for reading the database in
-+** rollback (non-WAL) mode are met. Unless the pager is (or recently
-+** was) in exclusive-locking mode, a user-level read transaction is
-+** open. The database size is known in this state.
-+**
-+** A connection running with locking_mode=normal enters this state when
-+** it opens a read-transaction on the database and returns to state
-+** OPEN after the read-transaction is completed. However a connection
-+** running in locking_mode=exclusive (including temp databases) remains in
-+** this state even after the read-transaction is closed. The only way
-+** a locking_mode=exclusive connection can transition from READER to OPEN
-+** is via the ERROR state (see below).
-+**
-+** * A read transaction may be active (but a write-transaction cannot).
-+** * A SHARED or greater lock is held on the database file.
-+** * The dbSize variable may be trusted (even if a user-level read
-+** transaction is not active). The dbOrigSize and dbFileSize variables
-+** may not be trusted at this point.
-+** * If the database is a WAL database, then the WAL connection is open.
-+** * Even if a read-transaction is not open, it is guaranteed that
-+** there is no hot-journal in the file-system.
-+**
-+** WRITER_LOCKED:
-+**
-+** The pager moves to this state from READER when a write-transaction
-+** is first opened on the database. In WRITER_LOCKED state, all locks
-+** required to start a write-transaction are held, but no actual
-+** modifications to the cache or database have taken place.
-+**
-+** In rollback mode, a RESERVED or (if the transaction was opened with
-+** BEGIN EXCLUSIVE) EXCLUSIVE lock is obtained on the database file when
-+** moving to this state, but the journal file is not written to or opened
-+** to in this state. If the transaction is committed or rolled back while
-+** in WRITER_LOCKED state, all that is required is to unlock the database
-+** file.
-+**
-+** IN WAL mode, WalBeginWriteTransaction() is called to lock the log file.
-+** If the connection is running with locking_mode=exclusive, an attempt
-+** is made to obtain an EXCLUSIVE lock on the database file.
-+**
-+** * A write transaction is active.
-+** * If the connection is open in rollback-mode, a RESERVED or greater
-+** lock is held on the database file.
-+** * If the connection is open in WAL-mode, a WAL write transaction
-+** is open (i.e. sqlite3WalBeginWriteTransaction() has been successfully
-+** called).
-+** * The dbSize, dbOrigSize and dbFileSize variables are all valid.
-+** * The contents of the pager cache have not been modified.
-+** * The journal file may or may not be open.
-+** * Nothing (not even the first header) has been written to the journal.
-+**
-+** WRITER_CACHEMOD:
-+**
-+** A pager moves from WRITER_LOCKED state to this state when a page is
-+** first modified by the upper layer. In rollback mode the journal file
-+** is opened (if it is not already open) and a header written to the
-+** start of it. The database file on disk has not been modified.
-+**
-+** * A write transaction is active.
-+** * A RESERVED or greater lock is held on the database file.
-+** * The journal file is open and the first header has been written
-+** to it, but the header has not been synced to disk.
-+** * The contents of the page cache have been modified.
-+**
-+** WRITER_DBMOD:
-+**
-+** The pager transitions from WRITER_CACHEMOD into WRITER_DBMOD state
-+** when it modifies the contents of the database file. WAL connections
-+** never enter this state (since they do not modify the database file,
-+** just the log file).
-+**
-+** * A write transaction is active.
-+** * An EXCLUSIVE or greater lock is held on the database file.
-+** * The journal file is open and the first header has been written
-+** and synced to disk.
-+** * The contents of the page cache have been modified (and possibly
-+** written to disk).
-+**
-+** WRITER_FINISHED:
-+**
-+** It is not possible for a WAL connection to enter this state.
-+**
-+** A rollback-mode pager changes to WRITER_FINISHED state from WRITER_DBMOD
-+** state after the entire transaction has been successfully written into the
-+** database file. In this state the transaction may be committed simply
-+** by finalizing the journal file. Once in WRITER_FINISHED state, it is
-+** not possible to modify the database further. At this point, the upper
-+** layer must either commit or rollback the transaction.
-+**
-+** * A write transaction is active.
-+** * An EXCLUSIVE or greater lock is held on the database file.
-+** * All writing and syncing of journal and database data has finished.
-+** If no error occurred, all that remains is to finalize the journal to
-+** commit the transaction. If an error did occur, the caller will need
-+** to rollback the transaction.
-+**
-+** ERROR:
-+**
-+** The ERROR state is entered when an IO or disk-full error (including
-+** SQLITE_IOERR_NOMEM) occurs at a point in the code that makes it
-+** difficult to be sure that the in-memory pager state (cache contents,
-+** db size etc.) are consistent with the contents of the file-system.
-+**
-+** Temporary pager files may enter the ERROR state, but in-memory pagers
-+** cannot.
-+**
-+** For example, if an IO error occurs while performing a rollback,
-+** the contents of the page-cache may be left in an inconsistent state.
-+** At this point it would be dangerous to change back to READER state
-+** (as usually happens after a rollback). Any subsequent readers might
-+** report database corruption (due to the inconsistent cache), and if
-+** they upgrade to writers, they may inadvertently corrupt the database
-+** file. To avoid this hazard, the pager switches into the ERROR state
-+** instead of READER following such an error.
-+**
-+** Once it has entered the ERROR state, any attempt to use the pager
-+** to read or write data returns an error. Eventually, once all
-+** outstanding transactions have been abandoned, the pager is able to
-+** transition back to OPEN state, discarding the contents of the
-+** page-cache and any other in-memory state at the same time. Everything
-+** is reloaded from disk (and, if necessary, hot-journal rollback peformed)
-+** when a read-transaction is next opened on the pager (transitioning
-+** the pager into READER state). At that point the system has recovered
-+** from the error.
-+**
-+** Specifically, the pager jumps into the ERROR state if:
-+**
-+** 1. An error occurs while attempting a rollback. This happens in
-+** function sqlite3PagerRollback().
-+**
-+** 2. An error occurs while attempting to finalize a journal file
-+** following a commit in function sqlite3PagerCommitPhaseTwo().
-+**
-+** 3. An error occurs while attempting to write to the journal or
-+** database file in function pagerStress() in order to free up
-+** memory.
-+**
-+** In other cases, the error is returned to the b-tree layer. The b-tree
-+** layer then attempts a rollback operation. If the error condition
-+** persists, the pager enters the ERROR state via condition (1) above.
-+**
-+** Condition (3) is necessary because it can be triggered by a read-only
-+** statement executed within a transaction. In this case, if the error
-+** code were simply returned to the user, the b-tree layer would not
-+** automatically attempt a rollback, as it assumes that an error in a
-+** read-only statement cannot leave the pager in an internally inconsistent
-+** state.
- **
--** Except, if Pager.eLock is set to UNKNOWN_LOCK when this function is
--** called, do not modify it unless the new locking state is EXCLUSIVE_LOCK.
--** See the comment above the #define of UNKNOWN_LOCK for an explanation
--** of this.
-+** * The Pager.errCode variable is set to something other than SQLITE_OK.
-+** * There are one or more outstanding references to pages (after the
-+** last reference is dropped the pager should move back to OPEN state).
-+** * The pager is not an in-memory pager.
-+**
-+**
-+** Notes:
-+**
-+** * A pager is never in WRITER_DBMOD or WRITER_FINISHED state if the
-+** connection is open in WAL mode. A WAL connection is always in one
-+** of the first four states.
-+**
-+** * Normally, a connection open in exclusive mode is never in PAGER_OPEN
-+** state. There are two exceptions: immediately after exclusive-mode has
-+** been turned on (and before any read or write transactions are
-+** executed), and when the pager is leaving the "error state".
-+**
-+** * See also: assert_pager_state().
- */
--static int pagerLockDb(Pager *pPager, int eLock){
-- int rc = SQLITE_OK;
--
-- assert( eLock==SHARED_LOCK || eLock==RESERVED_LOCK || eLock==EXCLUSIVE_LOCK );
-- if( pPager->eLock<eLock || pPager->eLock==UNKNOWN_LOCK ){
-- rc = sqlite3OsLock(pPager->fd, eLock);
-- if( rc==SQLITE_OK && (pPager->eLock!=UNKNOWN_LOCK||eLock==EXCLUSIVE_LOCK) ){
-- pPager->eLock = (u8)eLock;
-- IOTRACE(("LOCK %p %d\n", pPager, eLock))
-- }
-- }
-- return rc;
--}
-+#define PAGER_OPEN 0
-+#define PAGER_READER 1
-+#define PAGER_WRITER_LOCKED 2
-+#define PAGER_WRITER_CACHEMOD 3
-+#define PAGER_WRITER_DBMOD 4
-+#define PAGER_WRITER_FINISHED 5
-+#define PAGER_ERROR 6
-
- /*
--** This function determines whether or not the atomic-write optimization
--** can be used with this pager. The optimization can be used if:
-+** The Pager.eLock variable is almost always set to one of the
-+** following locking-states, according to the lock currently held on
-+** the database file: NO_LOCK, SHARED_LOCK, RESERVED_LOCK or EXCLUSIVE_LOCK.
-+** This variable is kept up to date as locks are taken and released by
-+** the pagerLockDb() and pagerUnlockDb() wrappers.
- **
--** (a) the value returned by OsDeviceCharacteristics() indicates that
--** a database page may be written atomically, and
--** (b) the value returned by OsSectorSize() is less than or equal
--** to the page size.
-+** If the VFS xLock() or xUnlock() returns an error other than SQLITE_BUSY
-+** (i.e. one of the SQLITE_IOERR subtypes), it is not clear whether or not
-+** the operation was successful. In these circumstances pagerLockDb() and
-+** pagerUnlockDb() take a conservative approach - eLock is always updated
-+** when unlocking the file, and only updated when locking the file if the
-+** VFS call is successful. This way, the Pager.eLock variable may be set
-+** to a less exclusive (lower) value than the lock that is actually held
-+** at the system level, but it is never set to a more exclusive value.
- **
--** The optimization is also always enabled for temporary files. It is
--** an error to call this function if pPager is opened on an in-memory
--** database.
-+** This is usually safe. If an xUnlock fails or appears to fail, there may
-+** be a few redundant xLock() calls or a lock may be held for longer than
-+** required, but nothing really goes wrong.
- **
--** If the optimization cannot be used, 0 is returned. If it can be used,
--** then the value returned is the size of the journal file when it
--** contains rollback data for exactly one page.
-+** The exception is when the database file is unlocked as the pager moves
-+** from ERROR to OPEN state. At this point there may be a hot-journal file
-+** in the file-system that needs to be rolled back (as part of a OPEN->SHARED
-+** transition, by the same pager or any other). If the call to xUnlock()
-+** fails at this point and the pager is left holding an EXCLUSIVE lock, this
-+** can confuse the call to xCheckReservedLock() call made later as part
-+** of hot-journal detection.
-+**
-+** xCheckReservedLock() is defined as returning true "if there is a RESERVED
-+** lock held by this process or any others". So xCheckReservedLock may
-+** return true because the caller itself is holding an EXCLUSIVE lock (but
-+** doesn't know it because of a previous error in xUnlock). If this happens
-+** a hot-journal may be mistaken for a journal being created by an active
-+** transaction in another process, causing SQLite to read from the database
-+** without rolling it back.
-+**
-+** To work around this, if a call to xUnlock() fails when unlocking the
-+** database in the ERROR state, Pager.eLock is set to UNKNOWN_LOCK. It
-+** is only changed back to a real locking state after a successful call
-+** to xLock(EXCLUSIVE). Also, the code to do the OPEN->SHARED state transition
-+** omits the check for a hot-journal if Pager.eLock is set to UNKNOWN_LOCK
-+** lock. Instead, it assumes a hot-journal exists and obtains an EXCLUSIVE
-+** lock on the database file before attempting to roll it back. See function
-+** PagerSharedLock() for more detail.
-+**
-+** Pager.eLock may only be set to UNKNOWN_LOCK when the pager is in
-+** PAGER_OPEN state.
- */
--#ifdef SQLITE_ENABLE_ATOMIC_WRITE
--static int jrnlBufferSize(Pager *pPager){
-- assert( !MEMDB );
-- if( !pPager->tempFile ){
-- int dc; /* Device characteristics */
-- int nSector; /* Sector size */
-- int szPage; /* Page size */
--
-- assert( isOpen(pPager->fd) );
-- dc = sqlite3OsDeviceCharacteristics(pPager->fd);
-- nSector = pPager->sectorSize;
-- szPage = pPager->pageSize;
--
-- assert(SQLITE_IOCAP_ATOMIC512==(512>>8));
-- assert(SQLITE_IOCAP_ATOMIC64K==(65536>>8));
-- if( 0==(dc&(SQLITE_IOCAP_ATOMIC|(szPage>>8)) || nSector>szPage) ){
-- return 0;
-- }
-- }
--
-- return JOURNAL_HDR_SZ(pPager) + JOURNAL_PG_SZ(pPager);
--}
--#endif
-+#define UNKNOWN_LOCK (EXCLUSIVE_LOCK+1)
-
- /*
--** If SQLITE_CHECK_PAGES is defined then we do some sanity checking
--** on the cache using a hash function. This is used for testing
--** and debugging only.
-+** A macro used for invoking the codec if there is one
- */
--#ifdef SQLITE_CHECK_PAGES
-+#ifdef SQLITE_HAS_CODEC
-+# define CODEC1(P,D,N,X,E) \
-+ if( P->xCodec && P->xCodec(P->pCodec,D,N,X)==0 ){ E; }
-+# define CODEC2(P,D,N,X,E,O) \
-+ if( P->xCodec==0 ){ O=(char*)D; }else \
-+ if( (O=(char*)(P->xCodec(P->pCodec,D,N,X)))==0 ){ E; }
-+#else
-+# define CODEC1(P,D,N,X,E) /* NO-OP */
-+# define CODEC2(P,D,N,X,E,O) O=(char*)D
-+#endif
-+
- /*
--** Return a 32-bit hash of the page data for pPage.
-+** The maximum allowed sector size. 64KiB. If the xSectorsize() method
-+** returns a value larger than this, then MAX_SECTOR_SIZE is used instead.
-+** This could conceivably cause corruption following a power failure on
-+** such a system. This is currently an undocumented limit.
- */
--static u32 pager_datahash(int nByte, unsigned char *pData){
-- u32 hash = 0;
-- int i;
-- for(i=0; i<nByte; i++){
-- hash = (hash*1039) + pData[i];
-- }
-- return hash;
--}
--static u32 pager_pagehash(PgHdr *pPage){
-- return pager_datahash(pPage->pPager->pageSize, (unsigned char *)pPage->pData);
--}
--static void pager_set_pagehash(PgHdr *pPage){
-- pPage->pageHash = pager_pagehash(pPage);
--}
-+#define MAX_SECTOR_SIZE 0x10000
-
- /*
--** The CHECK_PAGE macro takes a PgHdr* as an argument. If SQLITE_CHECK_PAGES
--** is defined, and NDEBUG is not defined, an assert() statement checks
--** that the page is either dirty or still matches the calculated page-hash.
-+** An instance of the following structure is allocated for each active
-+** savepoint and statement transaction in the system. All such structures
-+** are stored in the Pager.aSavepoint[] array, which is allocated and
-+** resized using sqlite3Realloc().
-+**
-+** When a savepoint is created, the PagerSavepoint.iHdrOffset field is
-+** set to 0. If a journal-header is written into the main journal while
-+** the savepoint is active, then iHdrOffset is set to the byte offset
-+** immediately following the last journal record written into the main
-+** journal before the journal-header. This is required during savepoint
-+** rollback (see pagerPlaybackSavepoint()).
- */
--#define CHECK_PAGE(x) checkPage(x)
--static void checkPage(PgHdr *pPg){
-- Pager *pPager = pPg->pPager;
-- assert( pPager->eState!=PAGER_ERROR );
-- assert( (pPg->flags&PGHDR_DIRTY) || pPg->pageHash==pager_pagehash(pPg) );
--}
--
--#else
--#define pager_datahash(X,Y) 0
--#define pager_pagehash(X) 0
--#define pager_set_pagehash(X)
--#define CHECK_PAGE(x)
--#endif /* SQLITE_CHECK_PAGES */
-+typedef struct PagerSavepoint PagerSavepoint;
-+struct PagerSavepoint {
-+ i64 iOffset; /* Starting offset in main journal */
-+ i64 iHdrOffset; /* See above */
-+ Bitvec *pInSavepoint; /* Set of pages in this savepoint */
-+ Pgno nOrig; /* Original number of pages in file */
-+ Pgno iSubRec; /* Index of first record in sub-journal */
-+#ifndef SQLITE_OMIT_WAL
-+ u32 aWalData[WAL_SAVEPOINT_NDATA]; /* WAL savepoint context */
-+#endif
-+};
-
- /*
--** When this is called the journal file for pager pPager must be open.
--** This function attempts to read a master journal file name from the
--** end of the file and, if successful, copies it into memory supplied
--** by the caller. See comments above writeMasterJournal() for the format
--** used to store a master journal file name at the end of a journal file.
-+** A open page cache is an instance of struct Pager. A description of
-+** some of the more important member variables follows:
- **
--** zMaster must point to a buffer of at least nMaster bytes allocated by
--** the caller. This should be sqlite3_vfs.mxPathname+1 (to ensure there is
--** enough space to write the master journal name). If the master journal
--** name in the journal is longer than nMaster bytes (including a
--** nul-terminator), then this is handled as if no master journal name
--** were present in the journal.
-+** eState
- **
--** If a master journal file name is present at the end of the journal
--** file, then it is copied into the buffer pointed to by zMaster. A
--** nul-terminator byte is appended to the buffer following the master
--** journal file name.
-+** The current 'state' of the pager object. See the comment and state
-+** diagram above for a description of the pager state.
- **
--** If it is determined that no master journal file name is present
--** zMaster[0] is set to 0 and SQLITE_OK returned.
-+** eLock
- **
--** If an error occurs while reading from the journal file, an SQLite
--** error code is returned.
-+** For a real on-disk database, the current lock held on the database file -
-+** NO_LOCK, SHARED_LOCK, RESERVED_LOCK or EXCLUSIVE_LOCK.
-+**
-+** For a temporary or in-memory database (neither of which require any
-+** locks), this variable is always set to EXCLUSIVE_LOCK. Since such
-+** databases always have Pager.exclusiveMode==1, this tricks the pager
-+** logic into thinking that it already has all the locks it will ever
-+** need (and no reason to release them).
-+**
-+** In some (obscure) circumstances, this variable may also be set to
-+** UNKNOWN_LOCK. See the comment above the #define of UNKNOWN_LOCK for
-+** details.
-+**
-+** changeCountDone
-+**
-+** This boolean variable is used to make sure that the change-counter
-+** (the 4-byte header field at byte offset 24 of the database file) is
-+** not updated more often than necessary.
-+**
-+** It is set to true when the change-counter field is updated, which
-+** can only happen if an exclusive lock is held on the database file.
-+** It is cleared (set to false) whenever an exclusive lock is
-+** relinquished on the database file. Each time a transaction is committed,
-+** The changeCountDone flag is inspected. If it is true, the work of
-+** updating the change-counter is omitted for the current transaction.
-+**
-+** This mechanism means that when running in exclusive mode, a connection
-+** need only update the change-counter once, for the first transaction
-+** committed.
-+**
-+** setMaster
-+**
-+** When PagerCommitPhaseOne() is called to commit a transaction, it may
-+** (or may not) specify a master-journal name to be written into the
-+** journal file before it is synced to disk.
-+**
-+** Whether or not a journal file contains a master-journal pointer affects
-+** the way in which the journal file is finalized after the transaction is
-+** committed or rolled back when running in "journal_mode=PERSIST" mode.
-+** If a journal file does not contain a master-journal pointer, it is
-+** finalized by overwriting the first journal header with zeroes. If
-+** it does contain a master-journal pointer the journal file is finalized
-+** by truncating it to zero bytes, just as if the connection were
-+** running in "journal_mode=truncate" mode.
-+**
-+** Journal files that contain master journal pointers cannot be finalized
-+** simply by overwriting the first journal-header with zeroes, as the
-+** master journal pointer could interfere with hot-journal rollback of any
-+** subsequently interrupted transaction that reuses the journal file.
-+**
-+** The flag is cleared as soon as the journal file is finalized (either
-+** by PagerCommitPhaseTwo or PagerRollback). If an IO error prevents the
-+** journal file from being successfully finalized, the setMaster flag
-+** is cleared anyway (and the pager will move to ERROR state).
-+**
-+** doNotSpill, doNotSyncSpill
-+**
-+** These two boolean variables control the behavior of cache-spills
-+** (calls made by the pcache module to the pagerStress() routine to
-+** write cached data to the file-system in order to free up memory).
-+**
-+** When doNotSpill is non-zero, writing to the database from pagerStress()
-+** is disabled altogether. This is done in a very obscure case that
-+** comes up during savepoint rollback that requires the pcache module
-+** to allocate a new page to prevent the journal file from being written
-+** while it is being traversed by code in pager_playback().
-+**
-+** If doNotSyncSpill is non-zero, writing to the database from pagerStress()
-+** is permitted, but syncing the journal file is not. This flag is set
-+** by sqlite3PagerWrite() when the file-system sector-size is larger than
-+** the database page-size in order to prevent a journal sync from happening
-+** in between the journalling of two pages on the same sector.
-+**
-+** subjInMemory
-+**
-+** This is a boolean variable. If true, then any required sub-journal
-+** is opened as an in-memory journal file. If false, then in-memory
-+** sub-journals are only used for in-memory pager files.
-+**
-+** This variable is updated by the upper layer each time a new
-+** write-transaction is opened.
-+**
-+** dbSize, dbOrigSize, dbFileSize
-+**
-+** Variable dbSize is set to the number of pages in the database file.
-+** It is valid in PAGER_READER and higher states (all states except for
-+** OPEN and ERROR).
-+**
-+** dbSize is set based on the size of the database file, which may be
-+** larger than the size of the database (the value stored at offset
-+** 28 of the database header by the btree). If the size of the file
-+** is not an integer multiple of the page-size, the value stored in
-+** dbSize is rounded down (i.e. a 5KB file with 2K page-size has dbSize==2).
-+** Except, any file that is greater than 0 bytes in size is considered
-+** to have at least one page. (i.e. a 1KB file with 2K page-size leads
-+** to dbSize==1).
-+**
-+** During a write-transaction, if pages with page-numbers greater than
-+** dbSize are modified in the cache, dbSize is updated accordingly.
-+** Similarly, if the database is truncated using PagerTruncateImage(),
-+** dbSize is updated.
-+**
-+** Variables dbOrigSize and dbFileSize are valid in states
-+** PAGER_WRITER_LOCKED and higher. dbOrigSize is a copy of the dbSize
-+** variable at the start of the transaction. It is used during rollback,
-+** and to determine whether or not pages need to be journalled before
-+** being modified.
-+**
-+** Throughout a write-transaction, dbFileSize contains the size of
-+** the file on disk in pages. It is set to a copy of dbSize when the
-+** write-transaction is first opened, and updated when VFS calls are made
-+** to write or truncate the database file on disk.
-+**
-+** The only reason the dbFileSize variable is required is to suppress
-+** unnecessary calls to xTruncate() after committing a transaction. If,
-+** when a transaction is committed, the dbFileSize variable indicates
-+** that the database file is larger than the database image (Pager.dbSize),
-+** pager_truncate() is called. The pager_truncate() call uses xFilesize()
-+** to measure the database file on disk, and then truncates it if required.
-+** dbFileSize is not used when rolling back a transaction. In this case
-+** pager_truncate() is called unconditionally (which means there may be
-+** a call to xFilesize() that is not strictly required). In either case,
-+** pager_truncate() may cause the file to become smaller or larger.
-+**
-+** dbHintSize
-+**
-+** The dbHintSize variable is used to limit the number of calls made to
-+** the VFS xFileControl(FCNTL_SIZE_HINT) method.
-+**
-+** dbHintSize is set to a copy of the dbSize variable when a
-+** write-transaction is opened (at the same time as dbFileSize and
-+** dbOrigSize). If the xFileControl(FCNTL_SIZE_HINT) method is called,
-+** dbHintSize is increased to the number of pages that correspond to the
-+** size-hint passed to the method call. See pager_write_pagelist() for
-+** details.
-+**
-+** errCode
-+**
-+** The Pager.errCode variable is only ever used in PAGER_ERROR state. It
-+** is set to zero in all other states. In PAGER_ERROR state, Pager.errCode
-+** is always set to SQLITE_FULL, SQLITE_IOERR or one of the SQLITE_IOERR_XXX
-+** sub-codes.
- */
--static int readMasterJournal(sqlite3_file *pJrnl, char *zMaster, u32 nMaster){
-- int rc; /* Return code */
-- u32 len; /* Length in bytes of master journal name */
-- i64 szJ; /* Total size in bytes of journal file pJrnl */
-- u32 cksum; /* MJ checksum value read from journal */
-- u32 u; /* Unsigned loop counter */
-- unsigned char aMagic[8]; /* A buffer to hold the magic header */
-- zMaster[0] = '\0';
-+struct Pager {
-+ sqlite3_vfs *pVfs; /* OS functions to use for IO */
-+ u8 exclusiveMode; /* Boolean. True if locking_mode==EXCLUSIVE */
-+ u8 journalMode; /* One of the PAGER_JOURNALMODE_* values */
-+ u8 useJournal; /* Use a rollback journal on this file */
-+ u8 noSync; /* Do not sync the journal if true */
-+ u8 fullSync; /* Do extra syncs of the journal for robustness */
-+ u8 ckptSyncFlags; /* SYNC_NORMAL or SYNC_FULL for checkpoint */
-+ u8 walSyncFlags; /* SYNC_NORMAL or SYNC_FULL for wal writes */
-+ u8 syncFlags; /* SYNC_NORMAL or SYNC_FULL otherwise */
-+ u8 tempFile; /* zFilename is a temporary file */
-+ u8 readOnly; /* True for a read-only database */
-+ u8 memDb; /* True to inhibit all file I/O */
-
-- if( SQLITE_OK!=(rc = sqlite3OsFileSize(pJrnl, &szJ))
-- || szJ<16
-- || SQLITE_OK!=(rc = read32bits(pJrnl, szJ-16, &len))
-- || len>=nMaster
-- || SQLITE_OK!=(rc = read32bits(pJrnl, szJ-12, &cksum))
-- || SQLITE_OK!=(rc = sqlite3OsRead(pJrnl, aMagic, 8, szJ-8))
-- || memcmp(aMagic, aJournalMagic, 8)
-- || SQLITE_OK!=(rc = sqlite3OsRead(pJrnl, zMaster, len, szJ-16-len))
-- ){
-- return rc;
-- }
-+ /**************************************************************************
-+ ** The following block contains those class members that change during
-+ ** routine opertion. Class members not in this block are either fixed
-+ ** when the pager is first created or else only change when there is a
-+ ** significant mode change (such as changing the page_size, locking_mode,
-+ ** or the journal_mode). From another view, these class members describe
-+ ** the "state" of the pager, while other class members describe the
-+ ** "configuration" of the pager.
-+ */
-+ u8 eState; /* Pager state (OPEN, READER, WRITER_LOCKED..) */
-+ u8 eLock; /* Current lock held on database file */
-+ u8 changeCountDone; /* Set after incrementing the change-counter */
-+ u8 setMaster; /* True if a m-j name has been written to jrnl */
-+ u8 doNotSpill; /* Do not spill the cache when non-zero */
-+ u8 doNotSyncSpill; /* Do not do a spill that requires jrnl sync */
-+ u8 subjInMemory; /* True to use in-memory sub-journals */
-+ Pgno dbSize; /* Number of pages in the database */
-+ Pgno dbOrigSize; /* dbSize before the current transaction */
-+ Pgno dbFileSize; /* Number of pages in the database file */
-+ Pgno dbHintSize; /* Value passed to FCNTL_SIZE_HINT call */
-+ int errCode; /* One of several kinds of errors */
-+ int nRec; /* Pages journalled since last j-header written */
-+ u32 cksumInit; /* Quasi-random value added to every checksum */
-+ u32 nSubRec; /* Number of records written to sub-journal */
-+ Bitvec *pInJournal; /* One bit for each page in the database file */
-+ sqlite3_file *fd; /* File descriptor for database */
-+ sqlite3_file *jfd; /* File descriptor for main journal */
-+ sqlite3_file *sjfd; /* File descriptor for sub-journal */
-+ i64 journalOff; /* Current write offset in the journal file */
-+ i64 journalHdr; /* Byte offset to previous journal header */
-+ sqlite3_backup *pBackup; /* Pointer to list of ongoing backup processes */
-+ PagerSavepoint *aSavepoint; /* Array of active savepoints */
-+ int nSavepoint; /* Number of elements in aSavepoint[] */
-+ char dbFileVers[16]; /* Changes whenever database file changes */
-
-- /* See if the checksum matches the master journal name */
-- for(u=0; u<len; u++){
-- cksum -= zMaster[u];
-- }
-- if( cksum ){
-- /* If the checksum doesn't add up, then one or more of the disk sectors
-- ** containing the master journal filename is corrupted. This means
-- ** definitely roll back, so just return SQLITE_OK and report a (nul)
-- ** master-journal filename.
-- */
-- len = 0;
-- }
-- zMaster[len] = '\0';
--
-- return SQLITE_OK;
--}
-+ u8 bUseFetch; /* True to use xFetch() */
-+ int nMmapOut; /* Number of mmap pages currently outstanding */
-+ sqlite3_int64 szMmap; /* Desired maximum mmap size */
-+ PgHdr *pMmapFreelist; /* List of free mmap page headers (pDirty) */
-+ /*
-+ ** End of the routinely-changing class members
-+ ***************************************************************************/
-+
-+ u16 nExtra; /* Add this many bytes to each in-memory page */
-+ i16 nReserve; /* Number of unused bytes at end of each page */
-+ u32 vfsFlags; /* Flags for sqlite3_vfs.xOpen() */
-+ u32 sectorSize; /* Assumed sector size during rollback */
-+ int pageSize; /* Number of bytes in a page */
-+ Pgno mxPgno; /* Maximum allowed size of the database */
-+ i64 journalSizeLimit; /* Size limit for persistent journal files */
-+ char *zFilename; /* Name of the database file */
-+ char *zJournal; /* Name of the journal file */
-+ int (*xBusyHandler)(void*); /* Function to call when busy */
-+ void *pBusyHandlerArg; /* Context argument for xBusyHandler */
-+ int aStat[3]; /* Total cache hits, misses and writes */
-+#ifdef SQLITE_TEST
-+ int nRead; /* Database pages read */
-+#endif
-+ void (*xReiniter)(DbPage*); /* Call this routine when reloading pages */
-+#ifdef SQLITE_HAS_CODEC
-+ void *(*xCodec)(void*,void*,Pgno,int); /* Routine for en/decoding data */
-+ void (*xCodecSizeChng)(void*,int,int); /* Notify of page size changes */
-+ void (*xCodecFree)(void*); /* Destructor for the codec */
-+ void *pCodec; /* First argument to xCodec... methods */
-+#endif
-+ char *pTmpSpace; /* Pager.pageSize bytes of space for tmp use */
-+ PCache *pPCache; /* Pointer to page cache object */
-+#ifndef SQLITE_OMIT_WAL
-+ Wal *pWal; /* Write-ahead log used by "journal_mode=wal" */
-+ char *zWal; /* File name for write-ahead log */
-+#endif
-+};
-
- /*
--** Return the offset of the sector boundary at or immediately
--** following the value in pPager->journalOff, assuming a sector
--** size of pPager->sectorSize bytes.
--**
--** i.e for a sector size of 512:
--**
--** Pager.journalOff Return value
--** ---------------------------------------
--** 0 0
--** 512 512
--** 100 512
--** 2000 2048
--**
--*/
--static i64 journalHdrOffset(Pager *pPager){
-- i64 offset = 0;
-- i64 c = pPager->journalOff;
-- if( c ){
-- offset = ((c-1)/JOURNAL_HDR_SZ(pPager) + 1) * JOURNAL_HDR_SZ(pPager);
-- }
-- assert( offset%JOURNAL_HDR_SZ(pPager)==0 );
-- assert( offset>=c );
-- assert( (offset-c)<JOURNAL_HDR_SZ(pPager) );
-- return offset;
--}
-+** Indexes for use with Pager.aStat[]. The Pager.aStat[] array contains
-+** the values accessed by passing SQLITE_DBSTATUS_CACHE_HIT, CACHE_MISS
-+** or CACHE_WRITE to sqlite3_db_status().
-+*/
-+#define PAGER_STAT_HIT 0
-+#define PAGER_STAT_MISS 1
-+#define PAGER_STAT_WRITE 2
-
- /*
--** The journal file must be open when this function is called.
--**
--** This function is a no-op if the journal file has not been written to
--** within the current transaction (i.e. if Pager.journalOff==0).
--**
--** If doTruncate is non-zero or the Pager.journalSizeLimit variable is
--** set to 0, then truncate the journal file to zero bytes in size. Otherwise,
--** zero the 28-byte header at the start of the journal file. In either case,
--** if the pager is not in no-sync mode, sync the journal file immediately
--** after writing or truncating it.
--**
--** If Pager.journalSizeLimit is set to a positive, non-zero value, and
--** following the truncation or zeroing described above the size of the
--** journal file in bytes is larger than this value, then truncate the
--** journal file to Pager.journalSizeLimit bytes. The journal file does
--** not need to be synced following this operation.
--**
--** If an IO error occurs, abandon processing and return the IO error code.
--** Otherwise, return SQLITE_OK.
-+** The following global variables hold counters used for
-+** testing purposes only. These variables do not exist in
-+** a non-testing build. These variables are not thread-safe.
- */
--static int zeroJournalHdr(Pager *pPager, int doTruncate){
-- int rc = SQLITE_OK; /* Return code */
-- assert( isOpen(pPager->jfd) );
-- if( pPager->journalOff ){
-- const i64 iLimit = pPager->journalSizeLimit; /* Local cache of jsl */
-+#ifdef SQLITE_TEST
-+SQLITE_API int sqlite3_pager_readdb_count = 0; /* Number of full pages read from DB */
-+SQLITE_API int sqlite3_pager_writedb_count = 0; /* Number of full pages written to DB */
-+SQLITE_API int sqlite3_pager_writej_count = 0; /* Number of pages written to journal */
-+# define PAGER_INCR(v) v++
-+#else
-+# define PAGER_INCR(v)
-+#endif
-
-- IOTRACE(("JZEROHDR %p\n", pPager))
-- if( doTruncate || iLimit==0 ){
-- rc = sqlite3OsTruncate(pPager->jfd, 0);
-- }else{
-- static const char zeroHdr[28] = {0};
-- rc = sqlite3OsWrite(pPager->jfd, zeroHdr, sizeof(zeroHdr), 0);
-- }
-- if( rc==SQLITE_OK && !pPager->noSync ){
-- rc = sqlite3OsSync(pPager->jfd, SQLITE_SYNC_DATAONLY|pPager->syncFlags);
-- }
-
-- /* At this point the transaction is committed but the write lock
-- ** is still held on the file. If there is a size limit configured for
-- ** the persistent journal and the journal file currently consumes more
-- ** space than that limit allows for, truncate it now. There is no need
-- ** to sync the file following this operation.
-- */
-- if( rc==SQLITE_OK && iLimit>0 ){
-- i64 sz;
-- rc = sqlite3OsFileSize(pPager->jfd, &sz);
-- if( rc==SQLITE_OK && sz>iLimit ){
-- rc = sqlite3OsTruncate(pPager->jfd, iLimit);
-- }
-- }
-- }
-- return rc;
--}
-
- /*
--** The journal file must be open when this routine is called. A journal
--** header (JOURNAL_HDR_SZ bytes) is written into the journal file at the
--** current location.
-+** Journal files begin with the following magic string. The data
-+** was obtained from /dev/random. It is used only as a sanity check.
- **
--** The format for the journal header is as follows:
--** - 8 bytes: Magic identifying journal format.
--** - 4 bytes: Number of records in journal, or -1 no-sync mode is on.
--** - 4 bytes: Random number used for page hash.
--** - 4 bytes: Initial database page count.
--** - 4 bytes: Sector size used by the process that wrote this journal.
--** - 4 bytes: Database page size.
--**
--** Followed by (JOURNAL_HDR_SZ - 28) bytes of unused space.
-+** Since version 2.8.0, the journal format contains additional sanity
-+** checking information. If the power fails while the journal is being
-+** written, semi-random garbage data might appear in the journal
-+** file after power is restored. If an attempt is then made
-+** to roll the journal back, the database could be corrupted. The additional
-+** sanity checking data is an attempt to discover the garbage in the
-+** journal and ignore it.
-+**
-+** The sanity checking information for the new journal format consists
-+** of a 32-bit checksum on each page of data. The checksum covers both
-+** the page number and the pPager->pageSize bytes of data for the page.
-+** This cksum is initialized to a 32-bit random value that appears in the
-+** journal file right after the header. The random initializer is important,
-+** because garbage data that appears at the end of a journal is likely
-+** data that was once in other files that have now been deleted. If the
-+** garbage data came from an obsolete journal file, the checksums might
-+** be correct. But by initializing the checksum to random value which
-+** is different for every journal, we minimize that risk.
- */
--static int writeJournalHdr(Pager *pPager){
-- int rc = SQLITE_OK; /* Return code */
-- char *zHeader = pPager->pTmpSpace; /* Temporary space used to build header */
-- u32 nHeader = (u32)pPager->pageSize;/* Size of buffer pointed to by zHeader */
-- u32 nWrite; /* Bytes of header sector written */
-- int ii; /* Loop counter */
--
-- assert( isOpen(pPager->jfd) ); /* Journal file must be open. */
--
-- if( nHeader>JOURNAL_HDR_SZ(pPager) ){
-- nHeader = JOURNAL_HDR_SZ(pPager);
-- }
--
-- /* If there are active savepoints and any of them were created
-- ** since the most recent journal header was written, update the
-- ** PagerSavepoint.iHdrOffset fields now.
-- */
-- for(ii=0; ii<pPager->nSavepoint; ii++){
-- if( pPager->aSavepoint[ii].iHdrOffset==0 ){
-- pPager->aSavepoint[ii].iHdrOffset = pPager->journalOff;
-- }
-- }
-+static const unsigned char aJournalMagic[] = {
-+ 0xd9, 0xd5, 0x05, 0xf9, 0x20, 0xa1, 0x63, 0xd7,
-+};
-
-- pPager->journalHdr = pPager->journalOff = journalHdrOffset(pPager);
-+/*
-+** The size of the of each page record in the journal is given by
-+** the following macro.
-+*/
-+#define JOURNAL_PG_SZ(pPager) ((pPager->pageSize) + 8)
-
-- /*
-- ** Write the nRec Field - the number of page records that follow this
-- ** journal header. Normally, zero is written to this value at this time.
-- ** After the records are added to the journal (and the journal synced,
-- ** if in full-sync mode), the zero is overwritten with the true number
-- ** of records (see syncJournal()).
-- **
-- ** A faster alternative is to write 0xFFFFFFFF to the nRec field. When
-- ** reading the journal this value tells SQLite to assume that the
-- ** rest of the journal file contains valid page records. This assumption
-- ** is dangerous, as if a failure occurred whilst writing to the journal
-- ** file it may contain some garbage data. There are two scenarios
-- ** where this risk can be ignored:
-- **
-- ** * When the pager is in no-sync mode. Corruption can follow a
-- ** power failure in this case anyway.
-- **
-- ** * When the SQLITE_IOCAP_SAFE_APPEND flag is set. This guarantees
-- ** that garbage data is never appended to the journal file.
-- */
-- assert( isOpen(pPager->fd) || pPager->noSync );
-- if( pPager->noSync || (pPager->journalMode==PAGER_JOURNALMODE_MEMORY)
-- || (sqlite3OsDeviceCharacteristics(pPager->fd)&SQLITE_IOCAP_SAFE_APPEND)
-- ){
-- memcpy(zHeader, aJournalMagic, sizeof(aJournalMagic));
-- put32bits(&zHeader[sizeof(aJournalMagic)], 0xffffffff);
-- }else{
-- memset(zHeader, 0, sizeof(aJournalMagic)+4);
-- }
-+/*
-+** The journal header size for this pager. This is usually the same
-+** size as a single disk sector. See also setSectorSize().
-+*/
-+#define JOURNAL_HDR_SZ(pPager) (pPager->sectorSize)
-
-- /* The random check-hash initializer */
-- sqlite3_randomness(sizeof(pPager->cksumInit), &pPager->cksumInit);
-- put32bits(&zHeader[sizeof(aJournalMagic)+4], pPager->cksumInit);
-- /* The initial database size */
-- put32bits(&zHeader[sizeof(aJournalMagic)+8], pPager->dbOrigSize);
-- /* The assumed sector size for this process */
-- put32bits(&zHeader[sizeof(aJournalMagic)+12], pPager->sectorSize);
-+/*
-+** The macro MEMDB is true if we are dealing with an in-memory database.
-+** We do this as a macro so that if the SQLITE_OMIT_MEMORYDB macro is set,
-+** the value of MEMDB will be a constant and the compiler will optimize
-+** out code that would never execute.
-+*/
-+#ifdef SQLITE_OMIT_MEMORYDB
-+# define MEMDB 0
-+#else
-+# define MEMDB pPager->memDb
-+#endif
-
-- /* The page size */
-- put32bits(&zHeader[sizeof(aJournalMagic)+16], pPager->pageSize);
-+/*
-+** The macro USEFETCH is true if we are allowed to use the xFetch and xUnfetch
-+** interfaces to access the database using memory-mapped I/O.
-+*/
-+#if SQLITE_MAX_MMAP_SIZE>0
-+# define USEFETCH(x) ((x)->bUseFetch)
-+#else
-+# define USEFETCH(x) 0
-+#endif
-
-- /* Initializing the tail of the buffer is not necessary. Everything
-- ** works find if the following memset() is omitted. But initializing
-- ** the memory prevents valgrind from complaining, so we are willing to
-- ** take the performance hit.
-- */
-- memset(&zHeader[sizeof(aJournalMagic)+20], 0,
-- nHeader-(sizeof(aJournalMagic)+20));
-+/*
-+** The maximum legal page number is (2^31 - 1).
-+*/
-+#define PAGER_MAX_PGNO 2147483647
-
-- /* In theory, it is only necessary to write the 28 bytes that the
-- ** journal header consumes to the journal file here. Then increment the
-- ** Pager.journalOff variable by JOURNAL_HDR_SZ so that the next
-- ** record is written to the following sector (leaving a gap in the file
-- ** that will be implicitly filled in by the OS).
-- **
-- ** However it has been discovered that on some systems this pattern can
-- ** be significantly slower than contiguously writing data to the file,
-- ** even if that means explicitly writing data to the block of
-- ** (JOURNAL_HDR_SZ - 28) bytes that will not be used. So that is what
-- ** is done.
-- **
-- ** The loop is required here in case the sector-size is larger than the
-- ** database page size. Since the zHeader buffer is only Pager.pageSize
-- ** bytes in size, more than one call to sqlite3OsWrite() may be required
-- ** to populate the entire journal header sector.
-- */
-- for(nWrite=0; rc==SQLITE_OK&&nWrite<JOURNAL_HDR_SZ(pPager); nWrite+=nHeader){
-- IOTRACE(("JHDR %p %lld %d\n", pPager, pPager->journalHdr, nHeader))
-- rc = sqlite3OsWrite(pPager->jfd, zHeader, nHeader, pPager->journalOff);
-- assert( pPager->journalHdr <= pPager->journalOff );
-- pPager->journalOff += nHeader;
-- }
-+/*
-+** The argument to this macro is a file descriptor (type sqlite3_file*).
-+** Return 0 if it is not open, or non-zero (but not 1) if it is.
-+**
-+** This is so that expressions can be written as:
-+**
-+** if( isOpen(pPager->jfd) ){ ...
-+**
-+** instead of
-+**
-+** if( pPager->jfd->pMethods ){ ...
-+*/
-+#define isOpen(pFd) ((pFd)->pMethods)
-
-- return rc;
-+/*
-+** Return true if this pager uses a write-ahead log instead of the usual
-+** rollback journal. Otherwise false.
-+*/
-+#ifndef SQLITE_OMIT_WAL
-+static int pagerUseWal(Pager *pPager){
-+ return (pPager->pWal!=0);
- }
-+#else
-+# define pagerUseWal(x) 0
-+# define pagerRollbackWal(x) 0
-+# define pagerWalFrames(v,w,x,y) 0
-+# define pagerOpenWalIfPresent(z) SQLITE_OK
-+# define pagerBeginReadTransaction(z) SQLITE_OK
-+#endif
-
-+#ifndef NDEBUG
- /*
--** The journal file must be open when this is called. A journal header file
--** (JOURNAL_HDR_SZ bytes) is read from the current location in the journal
--** file. The current location in the journal file is given by
--** pPager->journalOff. See comments above function writeJournalHdr() for
--** a description of the journal header format.
-+** Usage:
- **
--** If the header is read successfully, *pNRec is set to the number of
--** page records following this header and *pDbSize is set to the size of the
--** database before the transaction began, in pages. Also, pPager->cksumInit
--** is set to the value read from the journal header. SQLITE_OK is returned
--** in this case.
-+** assert( assert_pager_state(pPager) );
- **
--** If the journal header file appears to be corrupted, SQLITE_DONE is
--** returned and *pNRec and *PDbSize are undefined. If JOURNAL_HDR_SZ bytes
--** cannot be read from the journal file an error code is returned.
-+** This function runs many asserts to try to find inconsistencies in
-+** the internal state of the Pager object.
- */
--static int readJournalHdr(
-- Pager *pPager, /* Pager object */
-- int isHot,
-- i64 journalSize, /* Size of the open journal file in bytes */
-- u32 *pNRec, /* OUT: Value read from the nRec field */
-- u32 *pDbSize /* OUT: Value of original database size field */
--){
-- int rc; /* Return code */
-- unsigned char aMagic[8]; /* A buffer to hold the magic header */
-- i64 iHdrOff; /* Offset of journal header being read */
-+static int assert_pager_state(Pager *p){
-+ Pager *pPager = p;
-
-- assert( isOpen(pPager->jfd) ); /* Journal file must be open. */
-+ /* State must be valid. */
-+ assert( p->eState==PAGER_OPEN
-+ || p->eState==PAGER_READER
-+ || p->eState==PAGER_WRITER_LOCKED
-+ || p->eState==PAGER_WRITER_CACHEMOD
-+ || p->eState==PAGER_WRITER_DBMOD
-+ || p->eState==PAGER_WRITER_FINISHED
-+ || p->eState==PAGER_ERROR
-+ );
-
-- /* Advance Pager.journalOff to the start of the next sector. If the
-- ** journal file is too small for there to be a header stored at this
-- ** point, return SQLITE_DONE.
-+ /* Regardless of the current state, a temp-file connection always behaves
-+ ** as if it has an exclusive lock on the database file. It never updates
-+ ** the change-counter field, so the changeCountDone flag is always set.
- */
-- pPager->journalOff = journalHdrOffset(pPager);
-- if( pPager->journalOff+JOURNAL_HDR_SZ(pPager) > journalSize ){
-- return SQLITE_DONE;
-- }
-- iHdrOff = pPager->journalOff;
-+ assert( p->tempFile==0 || p->eLock==EXCLUSIVE_LOCK );
-+ assert( p->tempFile==0 || pPager->changeCountDone );
-
-- /* Read in the first 8 bytes of the journal header. If they do not match
-- ** the magic string found at the start of each journal header, return
-- ** SQLITE_DONE. If an IO error occurs, return an error code. Otherwise,
-- ** proceed.
-+ /* If the useJournal flag is clear, the journal-mode must be "OFF".
-+ ** And if the journal-mode is "OFF", the journal file must not be open.
- */
-- if( isHot || iHdrOff!=pPager->journalHdr ){
-- rc = sqlite3OsRead(pPager->jfd, aMagic, sizeof(aMagic), iHdrOff);
-- if( rc ){
-- return rc;
-- }
-- if( memcmp(aMagic, aJournalMagic, sizeof(aMagic))!=0 ){
-- return SQLITE_DONE;
-- }
-- }
-+ assert( p->journalMode==PAGER_JOURNALMODE_OFF || p->useJournal );
-+ assert( p->journalMode!=PAGER_JOURNALMODE_OFF || !isOpen(p->jfd) );
-
-- /* Read the first three 32-bit fields of the journal header: The nRec
-- ** field, the checksum-initializer and the database size at the start
-- ** of the transaction. Return an error code if anything goes wrong.
-+ /* Check that MEMDB implies noSync. And an in-memory journal. Since
-+ ** this means an in-memory pager performs no IO at all, it cannot encounter
-+ ** either SQLITE_IOERR or SQLITE_FULL during rollback or while finalizing
-+ ** a journal file. (although the in-memory journal implementation may
-+ ** return SQLITE_IOERR_NOMEM while the journal file is being written). It
-+ ** is therefore not possible for an in-memory pager to enter the ERROR
-+ ** state.
- */
-- if( SQLITE_OK!=(rc = read32bits(pPager->jfd, iHdrOff+8, pNRec))
-- || SQLITE_OK!=(rc = read32bits(pPager->jfd, iHdrOff+12, &pPager->cksumInit))
-- || SQLITE_OK!=(rc = read32bits(pPager->jfd, iHdrOff+16, pDbSize))
-- ){
-- return rc;
-- }
--
-- if( pPager->journalOff==0 ){
-- u32 iPageSize; /* Page-size field of journal header */
-- u32 iSectorSize; /* Sector-size field of journal header */
--
-- /* Read the page-size and sector-size journal header fields. */
-- if( SQLITE_OK!=(rc = read32bits(pPager->jfd, iHdrOff+20, &iSectorSize))
-- || SQLITE_OK!=(rc = read32bits(pPager->jfd, iHdrOff+24, &iPageSize))
-- ){
-- return rc;
-- }
--
-- /* Versions of SQLite prior to 3.5.8 set the page-size field of the
-- ** journal header to zero. In this case, assume that the Pager.pageSize
-- ** variable is already set to the correct page size.
-- */
-- if( iPageSize==0 ){
-- iPageSize = pPager->pageSize;
-- }
--
-- /* Check that the values read from the page-size and sector-size fields
-- ** are within range. To be 'in range', both values need to be a power
-- ** of two greater than or equal to 512 or 32, and not greater than their
-- ** respective compile time maximum limits.
-- */
-- if( iPageSize<512 || iSectorSize<32
-- || iPageSize>SQLITE_MAX_PAGE_SIZE || iSectorSize>MAX_SECTOR_SIZE
-- || ((iPageSize-1)&iPageSize)!=0 || ((iSectorSize-1)&iSectorSize)!=0
-- ){
-- /* If the either the page-size or sector-size in the journal-header is
-- ** invalid, then the process that wrote the journal-header must have
-- ** crashed before the header was synced. In this case stop reading
-- ** the journal file here.
-- */
-- return SQLITE_DONE;
-- }
--
-- /* Update the page-size to match the value read from the journal.
-- ** Use a testcase() macro to make sure that malloc failure within
-- ** PagerSetPagesize() is tested.
-- */
-- rc = sqlite3PagerSetPagesize(pPager, &iPageSize, -1);
-- testcase( rc!=SQLITE_OK );
--
-- /* Update the assumed sector-size to match the value used by
-- ** the process that created this journal. If this journal was
-- ** created by a process other than this one, then this routine
-- ** is being called from within pager_playback(). The local value
-- ** of Pager.sectorSize is restored at the end of that routine.
-- */
-- pPager->sectorSize = iSectorSize;
-+ if( MEMDB ){
-+ assert( p->noSync );
-+ assert( p->journalMode==PAGER_JOURNALMODE_OFF
-+ || p->journalMode==PAGER_JOURNALMODE_MEMORY
-+ );
-+ assert( p->eState!=PAGER_ERROR && p->eState!=PAGER_OPEN );
-+ assert( pagerUseWal(p)==0 );
- }
-
-- pPager->journalOff += JOURNAL_HDR_SZ(pPager);
-- return rc;
--}
-+ /* If changeCountDone is set, a RESERVED lock or greater must be held
-+ ** on the file.
-+ */
-+ assert( pPager->changeCountDone==0 || pPager->eLock>=RESERVED_LOCK );
-+ assert( p->eLock!=PENDING_LOCK );
-
-+ switch( p->eState ){
-+ case PAGER_OPEN:
-+ assert( !MEMDB );
-+ assert( pPager->errCode==SQLITE_OK );
-+ assert( sqlite3PcacheRefCount(pPager->pPCache)==0 || pPager->tempFile );
-+ break;
-
--/*
--** Write the supplied master journal name into the journal file for pager
--** pPager at the current location. The master journal name must be the last
--** thing written to a journal file. If the pager is in full-sync mode, the
--** journal file descriptor is advanced to the next sector boundary before
--** anything is written. The format is:
--**
--** + 4 bytes: PAGER_MJ_PGNO.
--** + N bytes: Master journal filename in utf-8.
--** + 4 bytes: N (length of master journal name in bytes, no nul-terminator).
--** + 4 bytes: Master journal name checksum.
--** + 8 bytes: aJournalMagic[].
--**
--** The master journal page checksum is the sum of the bytes in the master
--** journal name, where each byte is interpreted as a signed 8-bit integer.
--**
--** If zMaster is a NULL pointer (occurs for a single database transaction),
--** this call is a no-op.
--*/
--static int writeMasterJournal(Pager *pPager, const char *zMaster){
-- int rc; /* Return code */
-- int nMaster; /* Length of string zMaster */
-- i64 iHdrOff; /* Offset of header in journal file */
-- i64 jrnlSize; /* Size of journal file on disk */
-- u32 cksum = 0; /* Checksum of string zMaster */
-+ case PAGER_READER:
-+ assert( pPager->errCode==SQLITE_OK );
-+ assert( p->eLock!=UNKNOWN_LOCK );
-+ assert( p->eLock>=SHARED_LOCK );
-+ break;
-
-- assert( pPager->setMaster==0 );
-- assert( !pagerUseWal(pPager) );
-+ case PAGER_WRITER_LOCKED:
-+ assert( p->eLock!=UNKNOWN_LOCK );
-+ assert( pPager->errCode==SQLITE_OK );
-+ if( !pagerUseWal(pPager) ){
-+ assert( p->eLock>=RESERVED_LOCK );
-+ }
-+ assert( pPager->dbSize==pPager->dbOrigSize );
-+ assert( pPager->dbOrigSize==pPager->dbFileSize );
-+ assert( pPager->dbOrigSize==pPager->dbHintSize );
-+ assert( pPager->setMaster==0 );
-+ break;
-
-- if( !zMaster
-- || pPager->journalMode==PAGER_JOURNALMODE_MEMORY
-- || pPager->journalMode==PAGER_JOURNALMODE_OFF
-- ){
-- return SQLITE_OK;
-- }
-- pPager->setMaster = 1;
-- assert( isOpen(pPager->jfd) );
-- assert( pPager->journalHdr <= pPager->journalOff );
-+ case PAGER_WRITER_CACHEMOD:
-+ assert( p->eLock!=UNKNOWN_LOCK );
-+ assert( pPager->errCode==SQLITE_OK );
-+ if( !pagerUseWal(pPager) ){
-+ /* It is possible that if journal_mode=wal here that neither the
-+ ** journal file nor the WAL file are open. This happens during
-+ ** a rollback transaction that switches from journal_mode=off
-+ ** to journal_mode=wal.
-+ */
-+ assert( p->eLock>=RESERVED_LOCK );
-+ assert( isOpen(p->jfd)
-+ || p->journalMode==PAGER_JOURNALMODE_OFF
-+ || p->journalMode==PAGER_JOURNALMODE_WAL
-+ );
-+ }
-+ assert( pPager->dbOrigSize==pPager->dbFileSize );
-+ assert( pPager->dbOrigSize==pPager->dbHintSize );
-+ break;
-
-- /* Calculate the length in bytes and the checksum of zMaster */
-- for(nMaster=0; zMaster[nMaster]; nMaster++){
-- cksum += zMaster[nMaster];
-- }
-+ case PAGER_WRITER_DBMOD:
-+ assert( p->eLock==EXCLUSIVE_LOCK );
-+ assert( pPager->errCode==SQLITE_OK );
-+ assert( !pagerUseWal(pPager) );
-+ assert( p->eLock>=EXCLUSIVE_LOCK );
-+ assert( isOpen(p->jfd)
-+ || p->journalMode==PAGER_JOURNALMODE_OFF
-+ || p->journalMode==PAGER_JOURNALMODE_WAL
-+ );
-+ assert( pPager->dbOrigSize<=pPager->dbHintSize );
-+ break;
-
-- /* If in full-sync mode, advance to the next disk sector before writing
-- ** the master journal name. This is in case the previous page written to
-- ** the journal has already been synced.
-- */
-- if( pPager->fullSync ){
-- pPager->journalOff = journalHdrOffset(pPager);
-- }
-- iHdrOff = pPager->journalOff;
-+ case PAGER_WRITER_FINISHED:
-+ assert( p->eLock==EXCLUSIVE_LOCK );
-+ assert( pPager->errCode==SQLITE_OK );
-+ assert( !pagerUseWal(pPager) );
-+ assert( isOpen(p->jfd)
-+ || p->journalMode==PAGER_JOURNALMODE_OFF
-+ || p->journalMode==PAGER_JOURNALMODE_WAL
-+ );
-+ break;
-
-- /* Write the master journal data to the end of the journal file. If
-- ** an error occurs, return the error code to the caller.
-- */
-- if( (0 != (rc = write32bits(pPager->jfd, iHdrOff, PAGER_MJ_PGNO(pPager))))
-- || (0 != (rc = sqlite3OsWrite(pPager->jfd, zMaster, nMaster, iHdrOff+4)))
-- || (0 != (rc = write32bits(pPager->jfd, iHdrOff+4+nMaster, nMaster)))
-- || (0 != (rc = write32bits(pPager->jfd, iHdrOff+4+nMaster+4, cksum)))
-- || (0 != (rc = sqlite3OsWrite(pPager->jfd, aJournalMagic, 8, iHdrOff+4+nMaster+8)))
-- ){
-- return rc;
-+ case PAGER_ERROR:
-+ /* There must be at least one outstanding reference to the pager if
-+ ** in ERROR state. Otherwise the pager should have already dropped
-+ ** back to OPEN state.
-+ */
-+ assert( pPager->errCode!=SQLITE_OK );
-+ assert( sqlite3PcacheRefCount(pPager->pPCache)>0 );
-+ break;
- }
-- pPager->journalOff += (nMaster+20);
-
-- /* If the pager is in peristent-journal mode, then the physical
-- ** journal-file may extend past the end of the master-journal name
-- ** and 8 bytes of magic data just written to the file. This is
-- ** dangerous because the code to rollback a hot-journal file
-- ** will not be able to find the master-journal name to determine
-- ** whether or not the journal is hot.
-- **
-- ** Easiest thing to do in this scenario is to truncate the journal
-- ** file to the required size.
-- */
-- if( SQLITE_OK==(rc = sqlite3OsFileSize(pPager->jfd, &jrnlSize))
-- && jrnlSize>pPager->journalOff
-- ){
-- rc = sqlite3OsTruncate(pPager->jfd, pPager->journalOff);
-- }
-- return rc;
-+ return 1;
- }
-+#endif /* ifndef NDEBUG */
-
-+#ifdef SQLITE_DEBUG
- /*
--** Find a page in the hash table given its page number. Return
--** a pointer to the page or NULL if the requested page is not
--** already in memory.
-+** Return a pointer to a human readable string in a static buffer
-+** containing the state of the Pager object passed as an argument. This
-+** is intended to be used within debuggers. For example, as an alternative
-+** to "print *pPager" in gdb:
-+**
-+** (gdb) printf "%s", print_pager_state(pPager)
- */
--static PgHdr *pager_lookup(Pager *pPager, Pgno pgno){
-- PgHdr *p; /* Return value */
-+static char *print_pager_state(Pager *p){
-+ static char zRet[1024];
-
-- /* It is not possible for a call to PcacheFetch() with createFlag==0 to
-- ** fail, since no attempt to allocate dynamic memory will be made.
-- */
-- (void)sqlite3PcacheFetch(pPager->pPCache, pgno, 0, &p);
-- return p;
-+ sqlite3_snprintf(1024, zRet,
-+ "Filename: %s\n"
-+ "State: %s errCode=%d\n"
-+ "Lock: %s\n"
-+ "Locking mode: locking_mode=%s\n"
-+ "Journal mode: journal_mode=%s\n"
-+ "Backing store: tempFile=%d memDb=%d useJournal=%d\n"
-+ "Journal: journalOff=%lld journalHdr=%lld\n"
-+ "Size: dbsize=%d dbOrigSize=%d dbFileSize=%d\n"
-+ , p->zFilename
-+ , p->eState==PAGER_OPEN ? "OPEN" :
-+ p->eState==PAGER_READER ? "READER" :
-+ p->eState==PAGER_WRITER_LOCKED ? "WRITER_LOCKED" :
-+ p->eState==PAGER_WRITER_CACHEMOD ? "WRITER_CACHEMOD" :
-+ p->eState==PAGER_WRITER_DBMOD ? "WRITER_DBMOD" :
-+ p->eState==PAGER_WRITER_FINISHED ? "WRITER_FINISHED" :
-+ p->eState==PAGER_ERROR ? "ERROR" : "?error?"
-+ , (int)p->errCode
-+ , p->eLock==NO_LOCK ? "NO_LOCK" :
-+ p->eLock==RESERVED_LOCK ? "RESERVED" :
-+ p->eLock==EXCLUSIVE_LOCK ? "EXCLUSIVE" :
-+ p->eLock==SHARED_LOCK ? "SHARED" :
-+ p->eLock==UNKNOWN_LOCK ? "UNKNOWN" : "?error?"
-+ , p->exclusiveMode ? "exclusive" : "normal"
-+ , p->journalMode==PAGER_JOURNALMODE_MEMORY ? "memory" :
-+ p->journalMode==PAGER_JOURNALMODE_OFF ? "off" :
-+ p->journalMode==PAGER_JOURNALMODE_DELETE ? "delete" :
-+ p->journalMode==PAGER_JOURNALMODE_PERSIST ? "persist" :
-+ p->journalMode==PAGER_JOURNALMODE_TRUNCATE ? "truncate" :
-+ p->journalMode==PAGER_JOURNALMODE_WAL ? "wal" : "?error?"
-+ , (int)p->tempFile, (int)p->memDb, (int)p->useJournal
-+ , p->journalOff, p->journalHdr
-+ , (int)p->dbSize, (int)p->dbOrigSize, (int)p->dbFileSize
-+ );
-+
-+ return zRet;
- }
-+#endif
-
- /*
--** Discard the entire contents of the in-memory page-cache.
-+** Return true if it is necessary to write page *pPg into the sub-journal.
-+** A page needs to be written into the sub-journal if there exists one
-+** or more open savepoints for which:
-+**
-+** * The page-number is less than or equal to PagerSavepoint.nOrig, and
-+** * The bit corresponding to the page-number is not set in
-+** PagerSavepoint.pInSavepoint.
- */
--static void pager_reset(Pager *pPager){
-- sqlite3BackupRestart(pPager->pBackup);
-- sqlite3PcacheClear(pPager->pPCache);
-+static int subjRequiresPage(PgHdr *pPg){
-+ Pgno pgno = pPg->pgno;
-+ Pager *pPager = pPg->pPager;
-+ int i;
-+ for(i=0; i<pPager->nSavepoint; i++){
-+ PagerSavepoint *p = &pPager->aSavepoint[i];
-+ if( p->nOrig>=pgno && 0==sqlite3BitvecTest(p->pInSavepoint, pgno) ){
-+ return 1;
-+ }
-+ }
-+ return 0;
- }
-
- /*
--** Free all structures in the Pager.aSavepoint[] array and set both
--** Pager.aSavepoint and Pager.nSavepoint to zero. Close the sub-journal
--** if it is open and the pager is not in exclusive mode.
-+** Return true if the page is already in the journal file.
- */
--static void releaseAllSavepoints(Pager *pPager){
-- int ii; /* Iterator for looping through Pager.aSavepoint */
-- for(ii=0; ii<pPager->nSavepoint; ii++){
-- sqlite3BitvecDestroy(pPager->aSavepoint[ii].pInSavepoint);
-- }
-- if( !pPager->exclusiveMode || sqlite3IsMemJournal(pPager->sjfd) ){
-- sqlite3OsClose(pPager->sjfd);
-- }
-- sqlite3_free(pPager->aSavepoint);
-- pPager->aSavepoint = 0;
-- pPager->nSavepoint = 0;
-- pPager->nSubRec = 0;
-+static int pageInJournal(PgHdr *pPg){
-+ return sqlite3BitvecTest(pPg->pPager->pInJournal, pPg->pgno);
- }
-
- /*
--** Set the bit number pgno in the PagerSavepoint.pInSavepoint
--** bitvecs of all open savepoints. Return SQLITE_OK if successful
--** or SQLITE_NOMEM if a malloc failure occurs.
-+** Read a 32-bit integer from the given file descriptor. Store the integer
-+** that is read in *pRes. Return SQLITE_OK if everything worked, or an
-+** error code is something goes wrong.
-+**
-+** All values are stored on disk as big-endian.
- */
--static int addToSavepointBitvecs(Pager *pPager, Pgno pgno){
-- int ii; /* Loop counter */
-- int rc = SQLITE_OK; /* Result code */
--
-- for(ii=0; ii<pPager->nSavepoint; ii++){
-- PagerSavepoint *p = &pPager->aSavepoint[ii];
-- if( pgno<=p->nOrig ){
-- rc |= sqlite3BitvecSet(p->pInSavepoint, pgno);
-- testcase( rc==SQLITE_NOMEM );
-- assert( rc==SQLITE_OK || rc==SQLITE_NOMEM );
-- }
-+static int read32bits(sqlite3_file *fd, i64 offset, u32 *pRes){
-+ unsigned char ac[4];
-+ int rc = sqlite3OsRead(fd, ac, sizeof(ac), offset);
-+ if( rc==SQLITE_OK ){
-+ *pRes = sqlite3Get4byte(ac);
- }
- return rc;
- }
-
- /*
--** This function is a no-op if the pager is in exclusive mode and not
--** in the ERROR state. Otherwise, it switches the pager to PAGER_OPEN
--** state.
--**
--** If the pager is not in exclusive-access mode, the database file is
--** completely unlocked. If the file is unlocked and the file-system does
--** not exhibit the UNDELETABLE_WHEN_OPEN property, the journal file is
--** closed (if it is open).
--**
--** If the pager is in ERROR state when this function is called, the
--** contents of the pager cache are discarded before switching back to
--** the OPEN state. Regardless of whether the pager is in exclusive-mode
--** or not, any journal file left in the file-system will be treated
--** as a hot-journal and rolled back the next time a read-transaction
--** is opened (by this or by any other connection).
-+** Write a 32-bit integer into a string buffer in big-endian byte order.
- */
--static void pager_unlock(Pager *pPager){
--
-- assert( pPager->eState==PAGER_READER
-- || pPager->eState==PAGER_OPEN
-- || pPager->eState==PAGER_ERROR
-- );
--
-- sqlite3BitvecDestroy(pPager->pInJournal);
-- pPager->pInJournal = 0;
-- releaseAllSavepoints(pPager);
--
-- if( pagerUseWal(pPager) ){
-- assert( !isOpen(pPager->jfd) );
-- sqlite3WalEndReadTransaction(pPager->pWal);
-- pPager->eState = PAGER_OPEN;
-- }else if( !pPager->exclusiveMode ){
-- int rc; /* Error code returned by pagerUnlockDb() */
-- int iDc = isOpen(pPager->fd)?sqlite3OsDeviceCharacteristics(pPager->fd):0;
--
-- /* If the operating system support deletion of open files, then
-- ** close the journal file when dropping the database lock. Otherwise
-- ** another connection with journal_mode=delete might delete the file
-- ** out from under us.
-- */
-- assert( (PAGER_JOURNALMODE_MEMORY & 5)!=1 );
-- assert( (PAGER_JOURNALMODE_OFF & 5)!=1 );
-- assert( (PAGER_JOURNALMODE_WAL & 5)!=1 );
-- assert( (PAGER_JOURNALMODE_DELETE & 5)!=1 );
-- assert( (PAGER_JOURNALMODE_TRUNCATE & 5)==1 );
-- assert( (PAGER_JOURNALMODE_PERSIST & 5)==1 );
-- if( 0==(iDc & SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN)
-- || 1!=(pPager->journalMode & 5)
-- ){
-- sqlite3OsClose(pPager->jfd);
-- }
--
-- /* If the pager is in the ERROR state and the call to unlock the database
-- ** file fails, set the current lock to UNKNOWN_LOCK. See the comment
-- ** above the #define for UNKNOWN_LOCK for an explanation of why this
-- ** is necessary.
-- */
-- rc = pagerUnlockDb(pPager, NO_LOCK);
-- if( rc!=SQLITE_OK && pPager->eState==PAGER_ERROR ){
-- pPager->eLock = UNKNOWN_LOCK;
-- }
--
-- /* The pager state may be changed from PAGER_ERROR to PAGER_OPEN here
-- ** without clearing the error code. This is intentional - the error
-- ** code is cleared and the cache reset in the block below.
-- */
-- assert( pPager->errCode || pPager->eState!=PAGER_ERROR );
-- pPager->changeCountDone = 0;
-- pPager->eState = PAGER_OPEN;
-- }
-+#define put32bits(A,B) sqlite3Put4byte((u8*)A,B)
-
-- /* If Pager.errCode is set, the contents of the pager cache cannot be
-- ** trusted. Now that there are no outstanding references to the pager,
-- ** it can safely move back to PAGER_OPEN state. This happens in both
-- ** normal and exclusive-locking mode.
-- */
-- if( pPager->errCode ){
-- assert( !MEMDB );
-- pager_reset(pPager);
-- pPager->changeCountDone = pPager->tempFile;
-- pPager->eState = PAGER_OPEN;
-- pPager->errCode = SQLITE_OK;
-- }
-
-- pPager->journalOff = 0;
-- pPager->journalHdr = 0;
-- pPager->setMaster = 0;
-+/*
-+** Write a 32-bit integer into the given file descriptor. Return SQLITE_OK
-+** on success or an error code is something goes wrong.
-+*/
-+static int write32bits(sqlite3_file *fd, i64 offset, u32 val){
-+ char ac[4];
-+ put32bits(ac, val);
-+ return sqlite3OsWrite(fd, ac, 4, offset);
- }
-
- /*
--** This function is called whenever an IOERR or FULL error that requires
--** the pager to transition into the ERROR state may ahve occurred.
--** The first argument is a pointer to the pager structure, the second
--** the error-code about to be returned by a pager API function. The
--** value returned is a copy of the second argument to this function.
--**
--** If the second argument is SQLITE_FULL, SQLITE_IOERR or one of the
--** IOERR sub-codes, the pager enters the ERROR state and the error code
--** is stored in Pager.errCode. While the pager remains in the ERROR state,
--** all major API calls on the Pager will immediately return Pager.errCode.
-+** Unlock the database file to level eLock, which must be either NO_LOCK
-+** or SHARED_LOCK. Regardless of whether or not the call to xUnlock()
-+** succeeds, set the Pager.eLock variable to match the (attempted) new lock.
- **
--** The ERROR state indicates that the contents of the pager-cache
--** cannot be trusted. This state can be cleared by completely discarding
--** the contents of the pager-cache. If a transaction was active when
--** the persistent error occurred, then the rollback journal may need
--** to be replayed to restore the contents of the database file (as if
--** it were a hot-journal).
-+** Except, if Pager.eLock is set to UNKNOWN_LOCK when this function is
-+** called, do not modify it. See the comment above the #define of
-+** UNKNOWN_LOCK for an explanation of this.
- */
--static int pager_error(Pager *pPager, int rc){
-- int rc2 = rc & 0xff;
-- assert( rc==SQLITE_OK || !MEMDB );
-- assert(
-- pPager->errCode==SQLITE_FULL ||
-- pPager->errCode==SQLITE_OK ||
-- (pPager->errCode & 0xff)==SQLITE_IOERR
-- );
-- if( rc2==SQLITE_FULL || rc2==SQLITE_IOERR ){
-- pPager->errCode = rc;
-- pPager->eState = PAGER_ERROR;
-+static int pagerUnlockDb(Pager *pPager, int eLock){
-+ int rc = SQLITE_OK;
-+
-+ assert( !pPager->exclusiveMode || pPager->eLock==eLock );
-+ assert( eLock==NO_LOCK || eLock==SHARED_LOCK );
-+ assert( eLock!=NO_LOCK || pagerUseWal(pPager)==0 );
-+ if( isOpen(pPager->fd) ){
-+ assert( pPager->eLock>=eLock );
-+ rc = sqlite3OsUnlock(pPager->fd, eLock);
-+ if( pPager->eLock!=UNKNOWN_LOCK ){
-+ pPager->eLock = (u8)eLock;
-+ }
-+ IOTRACE(("UNLOCK %p %d\n", pPager, eLock))
- }
- return rc;
- }
-
--static int pager_truncate(Pager *pPager, Pgno nPage);
--
- /*
--** This routine ends a transaction. A transaction is usually ended by
--** either a COMMIT or a ROLLBACK operation. This routine may be called
--** after rollback of a hot-journal, or if an error occurs while opening
--** the journal file or writing the very first journal-header of a
--** database transaction.
--**
--** This routine is never called in PAGER_ERROR state. If it is called
--** in PAGER_NONE or PAGER_SHARED state and the lock held is less
--** exclusive than a RESERVED lock, it is a no-op.
--**
--** Otherwise, any active savepoints are released.
--**
--** If the journal file is open, then it is "finalized". Once a journal
--** file has been finalized it is not possible to use it to roll back a
--** transaction. Nor will it be considered to be a hot-journal by this
--** or any other database connection. Exactly how a journal is finalized
--** depends on whether or not the pager is running in exclusive mode and
--** the current journal-mode (Pager.journalMode value), as follows:
--**
--** journalMode==MEMORY
--** Journal file descriptor is simply closed. This destroys an
--** in-memory journal.
--**
--** journalMode==TRUNCATE
--** Journal file is truncated to zero bytes in size.
--**
--** journalMode==PERSIST
--** The first 28 bytes of the journal file are zeroed. This invalidates
--** the first journal header in the file, and hence the entire journal
--** file. An invalid journal file cannot be rolled back.
--**
--** journalMode==DELETE
--** The journal file is closed and deleted using sqlite3OsDelete().
--**
--** If the pager is running in exclusive mode, this method of finalizing
--** the journal file is never used. Instead, if the journalMode is
--** DELETE and the pager is in exclusive mode, the method described under
--** journalMode==PERSIST is used instead.
--**
--** After the journal is finalized, the pager moves to PAGER_READER state.
--** If running in non-exclusive rollback mode, the lock on the file is
--** downgraded to a SHARED_LOCK.
-+** Lock the database file to level eLock, which must be either SHARED_LOCK,
-+** RESERVED_LOCK or EXCLUSIVE_LOCK. If the caller is successful, set the
-+** Pager.eLock variable to the new locking state.
- **
--** SQLITE_OK is returned if no error occurs. If an error occurs during
--** any of the IO operations to finalize the journal file or unlock the
--** database then the IO error code is returned to the user. If the
--** operation to finalize the journal file fails, then the code still
--** tries to unlock the database file if not in exclusive mode. If the
--** unlock operation fails as well, then the first error code related
--** to the first error encountered (the journal finalization one) is
--** returned.
-+** Except, if Pager.eLock is set to UNKNOWN_LOCK when this function is
-+** called, do not modify it unless the new locking state is EXCLUSIVE_LOCK.
-+** See the comment above the #define of UNKNOWN_LOCK for an explanation
-+** of this.
- */
--static int pager_end_transaction(Pager *pPager, int hasMaster, int bCommit){
-- int rc = SQLITE_OK; /* Error code from journal finalization operation */
-- int rc2 = SQLITE_OK; /* Error code from db file unlock operation */
--
-- /* Do nothing if the pager does not have an open write transaction
-- ** or at least a RESERVED lock. This function may be called when there
-- ** is no write-transaction active but a RESERVED or greater lock is
-- ** held under two circumstances:
-- **
-- ** 1. After a successful hot-journal rollback, it is called with
-- ** eState==PAGER_NONE and eLock==EXCLUSIVE_LOCK.
-- **
-- ** 2. If a connection with locking_mode=exclusive holding an EXCLUSIVE
-- ** lock switches back to locking_mode=normal and then executes a
-- ** read-transaction, this function is called with eState==PAGER_READER
-- ** and eLock==EXCLUSIVE_LOCK when the read-transaction is closed.
-- */
-- assert( assert_pager_state(pPager) );
-- assert( pPager->eState!=PAGER_ERROR );
-- if( pPager->eState<PAGER_WRITER_LOCKED && pPager->eLock<RESERVED_LOCK ){
-- return SQLITE_OK;
-- }
--
-- releaseAllSavepoints(pPager);
-- assert( isOpen(pPager->jfd) || pPager->pInJournal==0 );
-- if( isOpen(pPager->jfd) ){
-- assert( !pagerUseWal(pPager) );
--
-- /* Finalize the journal file. */
-- if( sqlite3IsMemJournal(pPager->jfd) ){
-- assert( pPager->journalMode==PAGER_JOURNALMODE_MEMORY );
-- sqlite3OsClose(pPager->jfd);
-- }else if( pPager->journalMode==PAGER_JOURNALMODE_TRUNCATE ){
-- if( pPager->journalOff==0 ){
-- rc = SQLITE_OK;
-- }else{
-- rc = sqlite3OsTruncate(pPager->jfd, 0);
-- }
-- pPager->journalOff = 0;
-- }else if( pPager->journalMode==PAGER_JOURNALMODE_PERSIST
-- || (pPager->exclusiveMode && pPager->journalMode!=PAGER_JOURNALMODE_WAL)
-- ){
-- rc = zeroJournalHdr(pPager, hasMaster);
-- pPager->journalOff = 0;
-- }else{
-- /* This branch may be executed with Pager.journalMode==MEMORY if
-- ** a hot-journal was just rolled back. In this case the journal
-- ** file should be closed and deleted. If this connection writes to
-- ** the database file, it will do so using an in-memory journal.
-- */
-- int bDelete = (!pPager->tempFile && sqlite3JournalExists(pPager->jfd));
-- assert( pPager->journalMode==PAGER_JOURNALMODE_DELETE
-- || pPager->journalMode==PAGER_JOURNALMODE_MEMORY
-- || pPager->journalMode==PAGER_JOURNALMODE_WAL
-- );
-- sqlite3OsClose(pPager->jfd);
-- if( bDelete ){
-- rc = sqlite3OsDelete(pPager->pVfs, pPager->zJournal, 0);
-- }
-- }
-- }
-+static int pagerLockDb(Pager *pPager, int eLock){
-+ int rc = SQLITE_OK;
-
--#ifdef SQLITE_CHECK_PAGES
-- sqlite3PcacheIterateDirty(pPager->pPCache, pager_set_pagehash);
-- if( pPager->dbSize==0 && sqlite3PcacheRefCount(pPager->pPCache)>0 ){
-- PgHdr *p = pager_lookup(pPager, 1);
-- if( p ){
-- p->pageHash = 0;
-- sqlite3PagerUnref(p);
-+ assert( eLock==SHARED_LOCK || eLock==RESERVED_LOCK || eLock==EXCLUSIVE_LOCK );
-+ if( pPager->eLock<eLock || pPager->eLock==UNKNOWN_LOCK ){
-+ rc = sqlite3OsLock(pPager->fd, eLock);
-+ if( rc==SQLITE_OK && (pPager->eLock!=UNKNOWN_LOCK||eLock==EXCLUSIVE_LOCK) ){
-+ pPager->eLock = (u8)eLock;
-+ IOTRACE(("LOCK %p %d\n", pPager, eLock))
- }
- }
--#endif
--
-- sqlite3BitvecDestroy(pPager->pInJournal);
-- pPager->pInJournal = 0;
-- pPager->nRec = 0;
-- sqlite3PcacheCleanAll(pPager->pPCache);
-- sqlite3PcacheTruncate(pPager->pPCache, pPager->dbSize);
--
-- if( pagerUseWal(pPager) ){
-- /* Drop the WAL write-lock, if any. Also, if the connection was in
-- ** locking_mode=exclusive mode but is no longer, drop the EXCLUSIVE
-- ** lock held on the database file.
-- */
-- rc2 = sqlite3WalEndWriteTransaction(pPager->pWal);
-- assert( rc2==SQLITE_OK );
-- }else if( rc==SQLITE_OK && bCommit && pPager->dbFileSize>pPager->dbSize ){
-- /* This branch is taken when committing a transaction in rollback-journal
-- ** mode if the database file on disk is larger than the database image.
-- ** At this point the journal has been finalized and the transaction
-- ** successfully committed, but the EXCLUSIVE lock is still held on the
-- ** file. So it is safe to truncate the database file to its minimum
-- ** required size. */
-- assert( pPager->eLock==EXCLUSIVE_LOCK );
-- rc = pager_truncate(pPager, pPager->dbSize);
-- }
--
-- if( !pPager->exclusiveMode
-- && (!pagerUseWal(pPager) || sqlite3WalExclusiveMode(pPager->pWal, 0))
-- ){
-- rc2 = pagerUnlockDb(pPager, SHARED_LOCK);
-- pPager->changeCountDone = 0;
-- }
-- pPager->eState = PAGER_READER;
-- pPager->setMaster = 0;
--
-- return (rc==SQLITE_OK?rc2:rc);
-+ return rc;
- }
-
- /*
--** Execute a rollback if a transaction is active and unlock the
--** database file.
-+** This function determines whether or not the atomic-write optimization
-+** can be used with this pager. The optimization can be used if:
- **
--** If the pager has already entered the ERROR state, do not attempt
--** the rollback at this time. Instead, pager_unlock() is called. The
--** call to pager_unlock() will discard all in-memory pages, unlock
--** the database file and move the pager back to OPEN state. If this
--** means that there is a hot-journal left in the file-system, the next
--** connection to obtain a shared lock on the pager (which may be this one)
--** will roll it back.
-+** (a) the value returned by OsDeviceCharacteristics() indicates that
-+** a database page may be written atomically, and
-+** (b) the value returned by OsSectorSize() is less than or equal
-+** to the page size.
- **
--** If the pager has not already entered the ERROR state, but an IO or
--** malloc error occurs during a rollback, then this will itself cause
--** the pager to enter the ERROR state. Which will be cleared by the
--** call to pager_unlock(), as described above.
-+** The optimization is also always enabled for temporary files. It is
-+** an error to call this function if pPager is opened on an in-memory
-+** database.
-+**
-+** If the optimization cannot be used, 0 is returned. If it can be used,
-+** then the value returned is the size of the journal file when it
-+** contains rollback data for exactly one page.
- */
--static void pagerUnlockAndRollback(Pager *pPager){
-- if( pPager->eState!=PAGER_ERROR && pPager->eState!=PAGER_OPEN ){
-- assert( assert_pager_state(pPager) );
-- if( pPager->eState>=PAGER_WRITER_LOCKED ){
-- sqlite3BeginBenignMalloc();
-- sqlite3PagerRollback(pPager);
-- sqlite3EndBenignMalloc();
-- }else if( !pPager->exclusiveMode ){
-- assert( pPager->eState==PAGER_READER );
-- pager_end_transaction(pPager, 0, 0);
-+#ifdef SQLITE_ENABLE_ATOMIC_WRITE
-+static int jrnlBufferSize(Pager *pPager){
-+ assert( !MEMDB );
-+ if( !pPager->tempFile ){
-+ int dc; /* Device characteristics */
-+ int nSector; /* Sector size */
-+ int szPage; /* Page size */
-+
-+ assert( isOpen(pPager->fd) );
-+ dc = sqlite3OsDeviceCharacteristics(pPager->fd);
-+ nSector = pPager->sectorSize;
-+ szPage = pPager->pageSize;
-+
-+ assert(SQLITE_IOCAP_ATOMIC512==(512>>8));
-+ assert(SQLITE_IOCAP_ATOMIC64K==(65536>>8));
-+ if( 0==(dc&(SQLITE_IOCAP_ATOMIC|(szPage>>8)) || nSector>szPage) ){
-+ return 0;
- }
- }
-- pager_unlock(pPager);
-+
-+ return JOURNAL_HDR_SZ(pPager) + JOURNAL_PG_SZ(pPager);
- }
-+#endif
-
- /*
--** Parameter aData must point to a buffer of pPager->pageSize bytes
--** of data. Compute and return a checksum based ont the contents of the
--** page of data and the current value of pPager->cksumInit.
--**
--** This is not a real checksum. It is really just the sum of the
--** random initial value (pPager->cksumInit) and every 200th byte
--** of the page data, starting with byte offset (pPager->pageSize%200).
--** Each byte is interpreted as an 8-bit unsigned integer.
--**
--** Changing the formula used to compute this checksum results in an
--** incompatible journal file format.
--**
--** If journal corruption occurs due to a power failure, the most likely
--** scenario is that one end or the other of the record will be changed.
--** It is much less likely that the two ends of the journal record will be
--** correct and the middle be corrupt. Thus, this "checksum" scheme,
--** though fast and simple, catches the mostly likely kind of corruption.
-+** If SQLITE_CHECK_PAGES is defined then we do some sanity checking
-+** on the cache using a hash function. This is used for testing
-+** and debugging only.
- */
--static u32 pager_cksum(Pager *pPager, const u8 *aData){
-- u32 cksum = pPager->cksumInit; /* Checksum value to return */
-- int i = pPager->pageSize-200; /* Loop counter */
-- while( i>0 ){
-- cksum += aData[i];
-- i -= 200;
-+#ifdef SQLITE_CHECK_PAGES
-+/*
-+** Return a 32-bit hash of the page data for pPage.
-+*/
-+static u32 pager_datahash(int nByte, unsigned char *pData){
-+ u32 hash = 0;
-+ int i;
-+ for(i=0; i<nByte; i++){
-+ hash = (hash*1039) + pData[i];
- }
-- return cksum;
-+ return hash;
-+}
-+static u32 pager_pagehash(PgHdr *pPage){
-+ return pager_datahash(pPage->pPager->pageSize, (unsigned char *)pPage->pData);
-+}
-+static void pager_set_pagehash(PgHdr *pPage){
-+ pPage->pageHash = pager_pagehash(pPage);
- }
-
- /*
--** Report the current page size and number of reserved bytes back
--** to the codec.
-+** The CHECK_PAGE macro takes a PgHdr* as an argument. If SQLITE_CHECK_PAGES
-+** is defined, and NDEBUG is not defined, an assert() statement checks
-+** that the page is either dirty or still matches the calculated page-hash.
- */
--#ifdef SQLITE_HAS_CODEC
--static void pagerReportSize(Pager *pPager){
-- if( pPager->xCodecSizeChng ){
-- pPager->xCodecSizeChng(pPager->pCodec, pPager->pageSize,
-- (int)pPager->nReserve);
-- }
-+#define CHECK_PAGE(x) checkPage(x)
-+static void checkPage(PgHdr *pPg){
-+ Pager *pPager = pPg->pPager;
-+ assert( pPager->eState!=PAGER_ERROR );
-+ assert( (pPg->flags&PGHDR_DIRTY) || pPg->pageHash==pager_pagehash(pPg) );
- }
-+
- #else
--# define pagerReportSize(X) /* No-op if we do not support a codec */
--#endif
-+#define pager_datahash(X,Y) 0
-+#define pager_pagehash(X) 0
-+#define pager_set_pagehash(X)
-+#define CHECK_PAGE(x)
-+#endif /* SQLITE_CHECK_PAGES */
-
- /*
--** Read a single page from either the journal file (if isMainJrnl==1) or
--** from the sub-journal (if isMainJrnl==0) and playback that page.
--** The page begins at offset *pOffset into the file. The *pOffset
--** value is increased to the start of the next page in the journal.
--**
--** The main rollback journal uses checksums - the statement journal does
--** not.
--**
--** If the page number of the page record read from the (sub-)journal file
--** is greater than the current value of Pager.dbSize, then playback is
--** skipped and SQLITE_OK is returned.
-+** When this is called the journal file for pager pPager must be open.
-+** This function attempts to read a master journal file name from the
-+** end of the file and, if successful, copies it into memory supplied
-+** by the caller. See comments above writeMasterJournal() for the format
-+** used to store a master journal file name at the end of a journal file.
- **
--** If pDone is not NULL, then it is a record of pages that have already
--** been played back. If the page at *pOffset has already been played back
--** (if the corresponding pDone bit is set) then skip the playback.
--** Make sure the pDone bit corresponding to the *pOffset page is set
--** prior to returning.
-+** zMaster must point to a buffer of at least nMaster bytes allocated by
-+** the caller. This should be sqlite3_vfs.mxPathname+1 (to ensure there is
-+** enough space to write the master journal name). If the master journal
-+** name in the journal is longer than nMaster bytes (including a
-+** nul-terminator), then this is handled as if no master journal name
-+** were present in the journal.
- **
--** If the page record is successfully read from the (sub-)journal file
--** and played back, then SQLITE_OK is returned. If an IO error occurs
--** while reading the record from the (sub-)journal file or while writing
--** to the database file, then the IO error code is returned. If data
--** is successfully read from the (sub-)journal file but appears to be
--** corrupted, SQLITE_DONE is returned. Data is considered corrupted in
--** two circumstances:
--**
--** * If the record page-number is illegal (0 or PAGER_MJ_PGNO), or
--** * If the record is being rolled back from the main journal file
--** and the checksum field does not match the record content.
-+** If a master journal file name is present at the end of the journal
-+** file, then it is copied into the buffer pointed to by zMaster. A
-+** nul-terminator byte is appended to the buffer following the master
-+** journal file name.
- **
--** Neither of these two scenarios are possible during a savepoint rollback.
-+** If it is determined that no master journal file name is present
-+** zMaster[0] is set to 0 and SQLITE_OK returned.
- **
--** If this is a savepoint rollback, then memory may have to be dynamically
--** allocated by this function. If this is the case and an allocation fails,
--** SQLITE_NOMEM is returned.
-+** If an error occurs while reading from the journal file, an SQLite
-+** error code is returned.
- */
--static int pager_playback_one_page(
-- Pager *pPager, /* The pager being played back */
-- i64 *pOffset, /* Offset of record to playback */
-- Bitvec *pDone, /* Bitvec of pages already played back */
-- int isMainJrnl, /* 1 -> main journal. 0 -> sub-journal. */
-- int isSavepnt /* True for a savepoint rollback */
--){
-- int rc;
-- PgHdr *pPg; /* An existing page in the cache */
-- Pgno pgno; /* The page number of a page in journal */
-- u32 cksum; /* Checksum used for sanity checking */
-- char *aData; /* Temporary storage for the page */
-- sqlite3_file *jfd; /* The file descriptor for the journal file */
-- int isSynced; /* True if journal page is synced */
--
-- assert( (isMainJrnl&~1)==0 ); /* isMainJrnl is 0 or 1 */
-- assert( (isSavepnt&~1)==0 ); /* isSavepnt is 0 or 1 */
-- assert( isMainJrnl || pDone ); /* pDone always used on sub-journals */
-- assert( isSavepnt || pDone==0 ); /* pDone never used on non-savepoint */
--
-- aData = pPager->pTmpSpace;
-- assert( aData ); /* Temp storage must have already been allocated */
-- assert( pagerUseWal(pPager)==0 || (!isMainJrnl && isSavepnt) );
--
-- /* Either the state is greater than PAGER_WRITER_CACHEMOD (a transaction
-- ** or savepoint rollback done at the request of the caller) or this is
-- ** a hot-journal rollback. If it is a hot-journal rollback, the pager
-- ** is in state OPEN and holds an EXCLUSIVE lock. Hot-journal rollback
-- ** only reads from the main journal, not the sub-journal.
-- */
-- assert( pPager->eState>=PAGER_WRITER_CACHEMOD
-- || (pPager->eState==PAGER_OPEN && pPager->eLock==EXCLUSIVE_LOCK)
-- );
-- assert( pPager->eState>=PAGER_WRITER_CACHEMOD || isMainJrnl );
--
-- /* Read the page number and page data from the journal or sub-journal
-- ** file. Return an error code to the caller if an IO error occurs.
-- */
-- jfd = isMainJrnl ? pPager->jfd : pPager->sjfd;
-- rc = read32bits(jfd, *pOffset, &pgno);
-- if( rc!=SQLITE_OK ) return rc;
-- rc = sqlite3OsRead(jfd, (u8*)aData, pPager->pageSize, (*pOffset)+4);
-- if( rc!=SQLITE_OK ) return rc;
-- *pOffset += pPager->pageSize + 4 + isMainJrnl*4;
--
-- /* Sanity checking on the page. This is more important that I originally
-- ** thought. If a power failure occurs while the journal is being written,
-- ** it could cause invalid data to be written into the journal. We need to
-- ** detect this invalid data (with high probability) and ignore it.
-- */
-- if( pgno==0 || pgno==PAGER_MJ_PGNO(pPager) ){
-- assert( !isSavepnt );
-- return SQLITE_DONE;
-- }
-- if( pgno>(Pgno)pPager->dbSize || sqlite3BitvecTest(pDone, pgno) ){
-- return SQLITE_OK;
-- }
-- if( isMainJrnl ){
-- rc = read32bits(jfd, (*pOffset)-4, &cksum);
-- if( rc ) return rc;
-- if( !isSavepnt && pager_cksum(pPager, (u8*)aData)!=cksum ){
-- return SQLITE_DONE;
-- }
-- }
-+static int readMasterJournal(sqlite3_file *pJrnl, char *zMaster, u32 nMaster){
-+ int rc; /* Return code */
-+ u32 len; /* Length in bytes of master journal name */
-+ i64 szJ; /* Total size in bytes of journal file pJrnl */
-+ u32 cksum; /* MJ checksum value read from journal */
-+ u32 u; /* Unsigned loop counter */
-+ unsigned char aMagic[8]; /* A buffer to hold the magic header */
-+ zMaster[0] = '\0';
-
-- /* If this page has already been played by before during the current
-- ** rollback, then don't bother to play it back again.
-- */
-- if( pDone && (rc = sqlite3BitvecSet(pDone, pgno))!=SQLITE_OK ){
-+ if( SQLITE_OK!=(rc = sqlite3OsFileSize(pJrnl, &szJ))
-+ || szJ<16
-+ || SQLITE_OK!=(rc = read32bits(pJrnl, szJ-16, &len))
-+ || len>=nMaster
-+ || SQLITE_OK!=(rc = read32bits(pJrnl, szJ-12, &cksum))
-+ || SQLITE_OK!=(rc = sqlite3OsRead(pJrnl, aMagic, 8, szJ-8))
-+ || memcmp(aMagic, aJournalMagic, 8)
-+ || SQLITE_OK!=(rc = sqlite3OsRead(pJrnl, zMaster, len, szJ-16-len))
-+ ){
- return rc;
- }
-
-- /* When playing back page 1, restore the nReserve setting
-- */
-- if( pgno==1 && pPager->nReserve!=((u8*)aData)[20] ){
-- pPager->nReserve = ((u8*)aData)[20];
-- pagerReportSize(pPager);
-- }
--
-- /* If the pager is in CACHEMOD state, then there must be a copy of this
-- ** page in the pager cache. In this case just update the pager cache,
-- ** not the database file. The page is left marked dirty in this case.
-- **
-- ** An exception to the above rule: If the database is in no-sync mode
-- ** and a page is moved during an incremental vacuum then the page may
-- ** not be in the pager cache. Later: if a malloc() or IO error occurs
-- ** during a Movepage() call, then the page may not be in the cache
-- ** either. So the condition described in the above paragraph is not
-- ** assert()able.
-- **
-- ** If in WRITER_DBMOD, WRITER_FINISHED or OPEN state, then we update the
-- ** pager cache if it exists and the main file. The page is then marked
-- ** not dirty. Since this code is only executed in PAGER_OPEN state for
-- ** a hot-journal rollback, it is guaranteed that the page-cache is empty
-- ** if the pager is in OPEN state.
-- **
-- ** Ticket #1171: The statement journal might contain page content that is
-- ** different from the page content at the start of the transaction.
-- ** This occurs when a page is changed prior to the start of a statement
-- ** then changed again within the statement. When rolling back such a
-- ** statement we must not write to the original database unless we know
-- ** for certain that original page contents are synced into the main rollback
-- ** journal. Otherwise, a power loss might leave modified data in the
-- ** database file without an entry in the rollback journal that can
-- ** restore the database to its original form. Two conditions must be
-- ** met before writing to the database files. (1) the database must be
-- ** locked. (2) we know that the original page content is fully synced
-- ** in the main journal either because the page is not in cache or else
-- ** the page is marked as needSync==0.
-- **
-- ** 2008-04-14: When attempting to vacuum a corrupt database file, it
-- ** is possible to fail a statement on a database that does not yet exist.
-- ** Do not attempt to write if database file has never been opened.
-- */
-- if( pagerUseWal(pPager) ){
-- pPg = 0;
-- }else{
-- pPg = pager_lookup(pPager, pgno);
-- }
-- assert( pPg || !MEMDB );
-- assert( pPager->eState!=PAGER_OPEN || pPg==0 );
-- PAGERTRACE(("PLAYBACK %d page %d hash(%08x) %s\n",
-- PAGERID(pPager), pgno, pager_datahash(pPager->pageSize, (u8*)aData),
-- (isMainJrnl?"main-journal":"sub-journal")
-- ));
-- if( isMainJrnl ){
-- isSynced = pPager->noSync || (*pOffset <= pPager->journalHdr);
-- }else{
-- isSynced = (pPg==0 || 0==(pPg->flags & PGHDR_NEED_SYNC));
-- }
-- if( isOpen(pPager->fd)
-- && (pPager->eState>=PAGER_WRITER_DBMOD || pPager->eState==PAGER_OPEN)
-- && isSynced
-- ){
-- i64 ofst = (pgno-1)*(i64)pPager->pageSize;
-- testcase( !isSavepnt && pPg!=0 && (pPg->flags&PGHDR_NEED_SYNC)!=0 );
-- assert( !pagerUseWal(pPager) );
-- rc = sqlite3OsWrite(pPager->fd, (u8 *)aData, pPager->pageSize, ofst);
-- if( pgno>pPager->dbFileSize ){
-- pPager->dbFileSize = pgno;
-- }
-- if( pPager->pBackup ){
-- CODEC1(pPager, aData, pgno, 3, rc=SQLITE_NOMEM);
-- sqlite3BackupUpdate(pPager->pBackup, pgno, (u8*)aData);
-- CODEC2(pPager, aData, pgno, 7, rc=SQLITE_NOMEM, aData);
-- }
-- }else if( !isMainJrnl && pPg==0 ){
-- /* If this is a rollback of a savepoint and data was not written to
-- ** the database and the page is not in-memory, there is a potential
-- ** problem. When the page is next fetched by the b-tree layer, it
-- ** will be read from the database file, which may or may not be
-- ** current.
-- **
-- ** There are a couple of different ways this can happen. All are quite
-- ** obscure. When running in synchronous mode, this can only happen
-- ** if the page is on the free-list at the start of the transaction, then
-- ** populated, then moved using sqlite3PagerMovepage().
-- **
-- ** The solution is to add an in-memory page to the cache containing
-- ** the data just read from the sub-journal. Mark the page as dirty
-- ** and if the pager requires a journal-sync, then mark the page as
-- ** requiring a journal-sync before it is written.
-- */
-- assert( isSavepnt );
-- assert( pPager->doNotSpill==0 );
-- pPager->doNotSpill++;
-- rc = sqlite3PagerAcquire(pPager, pgno, &pPg, 1);
-- assert( pPager->doNotSpill==1 );
-- pPager->doNotSpill--;
-- if( rc!=SQLITE_OK ) return rc;
-- pPg->flags &= ~PGHDR_NEED_READ;
-- sqlite3PcacheMakeDirty(pPg);
-+ /* See if the checksum matches the master journal name */
-+ for(u=0; u<len; u++){
-+ cksum -= zMaster[u];
- }
-- if( pPg ){
-- /* No page should ever be explicitly rolled back that is in use, except
-- ** for page 1 which is held in use in order to keep the lock on the
-- ** database active. However such a page may be rolled back as a result
-- ** of an internal error resulting in an automatic call to
-- ** sqlite3PagerRollback().
-+ if( cksum ){
-+ /* If the checksum doesn't add up, then one or more of the disk sectors
-+ ** containing the master journal filename is corrupted. This means
-+ ** definitely roll back, so just return SQLITE_OK and report a (nul)
-+ ** master-journal filename.
- */
-- void *pData;
-- pData = pPg->pData;
-- memcpy(pData, (u8*)aData, pPager->pageSize);
-- pPager->xReiniter(pPg);
-- if( isMainJrnl && (!isSavepnt || *pOffset<=pPager->journalHdr) ){
-- /* If the contents of this page were just restored from the main
-- ** journal file, then its content must be as they were when the
-- ** transaction was first opened. In this case we can mark the page
-- ** as clean, since there will be no need to write it out to the
-- ** database.
-- **
-- ** There is one exception to this rule. If the page is being rolled
-- ** back as part of a savepoint (or statement) rollback from an
-- ** unsynced portion of the main journal file, then it is not safe
-- ** to mark the page as clean. This is because marking the page as
-- ** clean will clear the PGHDR_NEED_SYNC flag. Since the page is
-- ** already in the journal file (recorded in Pager.pInJournal) and
-- ** the PGHDR_NEED_SYNC flag is cleared, if the page is written to
-- ** again within this transaction, it will be marked as dirty but
-- ** the PGHDR_NEED_SYNC flag will not be set. It could then potentially
-- ** be written out into the database file before its journal file
-- ** segment is synced. If a crash occurs during or following this,
-- ** database corruption may ensue.
-- */
-- assert( !pagerUseWal(pPager) );
-- sqlite3PcacheMakeClean(pPg);
-- }
-- pager_set_pagehash(pPg);
--
-- /* If this was page 1, then restore the value of Pager.dbFileVers.
-- ** Do this before any decoding. */
-- if( pgno==1 ){
-- memcpy(&pPager->dbFileVers, &((u8*)pData)[24],sizeof(pPager->dbFileVers));
-- }
--
-- /* Decode the page just read from disk */
-- CODEC1(pPager, pData, pPg->pgno, 3, rc=SQLITE_NOMEM);
-- sqlite3PcacheRelease(pPg);
-+ len = 0;
- }
-- return rc;
-+ zMaster[len] = '\0';
-+
-+ return SQLITE_OK;
- }
-
- /*
--** Parameter zMaster is the name of a master journal file. A single journal
--** file that referred to the master journal file has just been rolled back.
--** This routine checks if it is possible to delete the master journal file,
--** and does so if it is.
--**
--** Argument zMaster may point to Pager.pTmpSpace. So that buffer is not
--** available for use within this function.
--**
--** When a master journal file is created, it is populated with the names
--** of all of its child journals, one after another, formatted as utf-8
--** encoded text. The end of each child journal file is marked with a
--** nul-terminator byte (0x00). i.e. the entire contents of a master journal
--** file for a transaction involving two databases might be:
--**
--** "/home/bill/a.db-journal\x00/home/bill/b.db-journal\x00"
--**
--** A master journal file may only be deleted once all of its child
--** journals have been rolled back.
--**
--** This function reads the contents of the master-journal file into
--** memory and loops through each of the child journal names. For
--** each child journal, it checks if:
--**
--** * if the child journal exists, and if so
--** * if the child journal contains a reference to master journal
--** file zMaster
--**
--** If a child journal can be found that matches both of the criteria
--** above, this function returns without doing anything. Otherwise, if
--** no such child journal can be found, file zMaster is deleted from
--** the file-system using sqlite3OsDelete().
-+** Return the offset of the sector boundary at or immediately
-+** following the value in pPager->journalOff, assuming a sector
-+** size of pPager->sectorSize bytes.
- **
--** If an IO error within this function, an error code is returned. This
--** function allocates memory by calling sqlite3Malloc(). If an allocation
--** fails, SQLITE_NOMEM is returned. Otherwise, if no IO or malloc errors
--** occur, SQLITE_OK is returned.
-+** i.e for a sector size of 512:
- **
--** TODO: This function allocates a single block of memory to load
--** the entire contents of the master journal file. This could be
--** a couple of kilobytes or so - potentially larger than the page
--** size.
-+** Pager.journalOff Return value
-+** ---------------------------------------
-+** 0 0
-+** 512 512
-+** 100 512
-+** 2000 2048
-+**
- */
--static int pager_delmaster(Pager *pPager, const char *zMaster){
-- sqlite3_vfs *pVfs = pPager->pVfs;
-- int rc; /* Return code */
-- sqlite3_file *pMaster; /* Malloc'd master-journal file descriptor */
-- sqlite3_file *pJournal; /* Malloc'd child-journal file descriptor */
-- char *zMasterJournal = 0; /* Contents of master journal file */
-- i64 nMasterJournal; /* Size of master journal file */
-- char *zJournal; /* Pointer to one journal within MJ file */
-- char *zMasterPtr; /* Space to hold MJ filename from a journal file */
-- int nMasterPtr; /* Amount of space allocated to zMasterPtr[] */
--
-- /* Allocate space for both the pJournal and pMaster file descriptors.
-- ** If successful, open the master journal file for reading.
-- */
-- pMaster = (sqlite3_file *)sqlite3MallocZero(pVfs->szOsFile * 2);
-- pJournal = (sqlite3_file *)(((u8 *)pMaster) + pVfs->szOsFile);
-- if( !pMaster ){
-- rc = SQLITE_NOMEM;
-- }else{
-- const int flags = (SQLITE_OPEN_READONLY|SQLITE_OPEN_MASTER_JOURNAL);
-- rc = sqlite3OsOpen(pVfs, zMaster, pMaster, flags, 0);
-- }
-- if( rc!=SQLITE_OK ) goto delmaster_out;
--
-- /* Load the entire master journal file into space obtained from
-- ** sqlite3_malloc() and pointed to by zMasterJournal. Also obtain
-- ** sufficient space (in zMasterPtr) to hold the names of master
-- ** journal files extracted from regular rollback-journals.
-- */
-- rc = sqlite3OsFileSize(pMaster, &nMasterJournal);
-- if( rc!=SQLITE_OK ) goto delmaster_out;
-- nMasterPtr = pVfs->mxPathname+1;
-- zMasterJournal = sqlite3Malloc((int)nMasterJournal + nMasterPtr + 1);
-- if( !zMasterJournal ){
-- rc = SQLITE_NOMEM;
-- goto delmaster_out;
-- }
-- zMasterPtr = &zMasterJournal[nMasterJournal+1];
-- rc = sqlite3OsRead(pMaster, zMasterJournal, (int)nMasterJournal, 0);
-- if( rc!=SQLITE_OK ) goto delmaster_out;
-- zMasterJournal[nMasterJournal] = 0;
--
-- zJournal = zMasterJournal;
-- while( (zJournal-zMasterJournal)<nMasterJournal ){
-- int exists;
-- rc = sqlite3OsAccess(pVfs, zJournal, SQLITE_ACCESS_EXISTS, &exists);
-- if( rc!=SQLITE_OK ){
-- goto delmaster_out;
-- }
-- if( exists ){
-- /* One of the journals pointed to by the master journal exists.
-- ** Open it and check if it points at the master journal. If
-- ** so, return without deleting the master journal file.
-- */
-- int c;
-- int flags = (SQLITE_OPEN_READONLY|SQLITE_OPEN_MAIN_JOURNAL);
-- rc = sqlite3OsOpen(pVfs, zJournal, pJournal, flags, 0);
-- if( rc!=SQLITE_OK ){
-- goto delmaster_out;
-- }
--
-- rc = readMasterJournal(pJournal, zMasterPtr, nMasterPtr);
-- sqlite3OsClose(pJournal);
-- if( rc!=SQLITE_OK ){
-- goto delmaster_out;
-- }
--
-- c = zMasterPtr[0]!=0 && strcmp(zMasterPtr, zMaster)==0;
-- if( c ){
-- /* We have a match. Do not delete the master journal file. */
-- goto delmaster_out;
-- }
-- }
-- zJournal += (sqlite3Strlen30(zJournal)+1);
-- }
--
-- sqlite3OsClose(pMaster);
-- rc = sqlite3OsDelete(pVfs, zMaster, 0);
--
--delmaster_out:
-- sqlite3_free(zMasterJournal);
-- if( pMaster ){
-- sqlite3OsClose(pMaster);
-- assert( !isOpen(pJournal) );
-- sqlite3_free(pMaster);
-+static i64 journalHdrOffset(Pager *pPager){
-+ i64 offset = 0;
-+ i64 c = pPager->journalOff;
-+ if( c ){
-+ offset = ((c-1)/JOURNAL_HDR_SZ(pPager) + 1) * JOURNAL_HDR_SZ(pPager);
- }
-- return rc;
-+ assert( offset%JOURNAL_HDR_SZ(pPager)==0 );
-+ assert( offset>=c );
-+ assert( (offset-c)<JOURNAL_HDR_SZ(pPager) );
-+ return offset;
- }
-
--
- /*
--** This function is used to change the actual size of the database
--** file in the file-system. This only happens when committing a transaction,
--** or rolling back a transaction (including rolling back a hot-journal).
-+** The journal file must be open when this function is called.
- **
--** If the main database file is not open, or the pager is not in either
--** DBMOD or OPEN state, this function is a no-op. Otherwise, the size
--** of the file is changed to nPage pages (nPage*pPager->pageSize bytes).
--** If the file on disk is currently larger than nPage pages, then use the VFS
--** xTruncate() method to truncate it.
-+** This function is a no-op if the journal file has not been written to
-+** within the current transaction (i.e. if Pager.journalOff==0).
- **
--** Or, it might might be the case that the file on disk is smaller than
--** nPage pages. Some operating system implementations can get confused if
--** you try to truncate a file to some size that is larger than it
--** currently is, so detect this case and write a single zero byte to
--** the end of the new file instead.
-+** If doTruncate is non-zero or the Pager.journalSizeLimit variable is
-+** set to 0, then truncate the journal file to zero bytes in size. Otherwise,
-+** zero the 28-byte header at the start of the journal file. In either case,
-+** if the pager is not in no-sync mode, sync the journal file immediately
-+** after writing or truncating it.
- **
--** If successful, return SQLITE_OK. If an IO error occurs while modifying
--** the database file, return the error code to the caller.
-+** If Pager.journalSizeLimit is set to a positive, non-zero value, and
-+** following the truncation or zeroing described above the size of the
-+** journal file in bytes is larger than this value, then truncate the
-+** journal file to Pager.journalSizeLimit bytes. The journal file does
-+** not need to be synced following this operation.
-+**
-+** If an IO error occurs, abandon processing and return the IO error code.
-+** Otherwise, return SQLITE_OK.
- */
--static int pager_truncate(Pager *pPager, Pgno nPage){
-- int rc = SQLITE_OK;
-- assert( pPager->eState!=PAGER_ERROR );
-- assert( pPager->eState!=PAGER_READER );
--
-- if( isOpen(pPager->fd)
-- && (pPager->eState>=PAGER_WRITER_DBMOD || pPager->eState==PAGER_OPEN)
-- ){
-- i64 currentSize, newSize;
-- int szPage = pPager->pageSize;
-- assert( pPager->eLock==EXCLUSIVE_LOCK );
-- /* TODO: Is it safe to use Pager.dbFileSize here? */
-- rc = sqlite3OsFileSize(pPager->fd, ¤tSize);
-- newSize = szPage*(i64)nPage;
-- if( rc==SQLITE_OK && currentSize!=newSize ){
-- if( currentSize>newSize ){
-- rc = sqlite3OsTruncate(pPager->fd, newSize);
-- }else if( (currentSize+szPage)<=newSize ){
-- char *pTmp = pPager->pTmpSpace;
-- memset(pTmp, 0, szPage);
-- testcase( (newSize-szPage) == currentSize );
-- testcase( (newSize-szPage) > currentSize );
-- rc = sqlite3OsWrite(pPager->fd, pTmp, szPage, newSize-szPage);
-- }
-- if( rc==SQLITE_OK ){
-- pPager->dbFileSize = nPage;
-+static int zeroJournalHdr(Pager *pPager, int doTruncate){
-+ int rc = SQLITE_OK; /* Return code */
-+ assert( isOpen(pPager->jfd) );
-+ if( pPager->journalOff ){
-+ const i64 iLimit = pPager->journalSizeLimit; /* Local cache of jsl */
-+
-+ IOTRACE(("JZEROHDR %p\n", pPager))
-+ if( doTruncate || iLimit==0 ){
-+ rc = sqlite3OsTruncate(pPager->jfd, 0);
-+ }else{
-+ static const char zeroHdr[28] = {0};
-+ rc = sqlite3OsWrite(pPager->jfd, zeroHdr, sizeof(zeroHdr), 0);
-+ }
-+ if( rc==SQLITE_OK && !pPager->noSync ){
-+ rc = sqlite3OsSync(pPager->jfd, SQLITE_SYNC_DATAONLY|pPager->syncFlags);
-+ }
-+
-+ /* At this point the transaction is committed but the write lock
-+ ** is still held on the file. If there is a size limit configured for
-+ ** the persistent journal and the journal file currently consumes more
-+ ** space than that limit allows for, truncate it now. There is no need
-+ ** to sync the file following this operation.
-+ */
-+ if( rc==SQLITE_OK && iLimit>0 ){
-+ i64 sz;
-+ rc = sqlite3OsFileSize(pPager->jfd, &sz);
-+ if( rc==SQLITE_OK && sz>iLimit ){
-+ rc = sqlite3OsTruncate(pPager->jfd, iLimit);
- }
- }
- }
-@@ -40870,8409 +42712,8969 @@
- }
-
- /*
--** Return a sanitized version of the sector-size of OS file pFile. The
--** return value is guaranteed to lie between 32 and MAX_SECTOR_SIZE.
-+** The journal file must be open when this routine is called. A journal
-+** header (JOURNAL_HDR_SZ bytes) is written into the journal file at the
-+** current location.
-+**
-+** The format for the journal header is as follows:
-+** - 8 bytes: Magic identifying journal format.
-+** - 4 bytes: Number of records in journal, or -1 no-sync mode is on.
-+** - 4 bytes: Random number used for page hash.
-+** - 4 bytes: Initial database page count.
-+** - 4 bytes: Sector size used by the process that wrote this journal.
-+** - 4 bytes: Database page size.
-+**
-+** Followed by (JOURNAL_HDR_SZ - 28) bytes of unused space.
- */
--SQLITE_PRIVATE int sqlite3SectorSize(sqlite3_file *pFile){
-- int iRet = sqlite3OsSectorSize(pFile);
-- if( iRet<32 ){
-- iRet = 512;
-- }else if( iRet>MAX_SECTOR_SIZE ){
-- assert( MAX_SECTOR_SIZE>=512 );
-- iRet = MAX_SECTOR_SIZE;
-+static int writeJournalHdr(Pager *pPager){
-+ int rc = SQLITE_OK; /* Return code */
-+ char *zHeader = pPager->pTmpSpace; /* Temporary space used to build header */
-+ u32 nHeader = (u32)pPager->pageSize;/* Size of buffer pointed to by zHeader */
-+ u32 nWrite; /* Bytes of header sector written */
-+ int ii; /* Loop counter */
-+
-+ assert( isOpen(pPager->jfd) ); /* Journal file must be open. */
-+
-+ if( nHeader>JOURNAL_HDR_SZ(pPager) ){
-+ nHeader = JOURNAL_HDR_SZ(pPager);
- }
-- return iRet;
--}
-
--/*
--** Set the value of the Pager.sectorSize variable for the given
--** pager based on the value returned by the xSectorSize method
--** of the open database file. The sector size will be used used
--** to determine the size and alignment of journal header and
--** master journal pointers within created journal files.
--**
--** For temporary files the effective sector size is always 512 bytes.
--**
--** Otherwise, for non-temporary files, the effective sector size is
--** the value returned by the xSectorSize() method rounded up to 32 if
--** it is less than 32, or rounded down to MAX_SECTOR_SIZE if it
--** is greater than MAX_SECTOR_SIZE.
--**
--** If the file has the SQLITE_IOCAP_POWERSAFE_OVERWRITE property, then set
--** the effective sector size to its minimum value (512). The purpose of
--** pPager->sectorSize is to define the "blast radius" of bytes that
--** might change if a crash occurs while writing to a single byte in
--** that range. But with POWERSAFE_OVERWRITE, the blast radius is zero
--** (that is what POWERSAFE_OVERWRITE means), so we minimize the sector
--** size. For backwards compatibility of the rollback journal file format,
--** we cannot reduce the effective sector size below 512.
--*/
--static void setSectorSize(Pager *pPager){
-- assert( isOpen(pPager->fd) || pPager->tempFile );
-+ /* If there are active savepoints and any of them were created
-+ ** since the most recent journal header was written, update the
-+ ** PagerSavepoint.iHdrOffset fields now.
-+ */
-+ for(ii=0; ii<pPager->nSavepoint; ii++){
-+ if( pPager->aSavepoint[ii].iHdrOffset==0 ){
-+ pPager->aSavepoint[ii].iHdrOffset = pPager->journalOff;
-+ }
-+ }
-
-- if( pPager->tempFile
-- || (sqlite3OsDeviceCharacteristics(pPager->fd) &
-- SQLITE_IOCAP_POWERSAFE_OVERWRITE)!=0
-+ pPager->journalHdr = pPager->journalOff = journalHdrOffset(pPager);
-+
-+ /*
-+ ** Write the nRec Field - the number of page records that follow this
-+ ** journal header. Normally, zero is written to this value at this time.
-+ ** After the records are added to the journal (and the journal synced,
-+ ** if in full-sync mode), the zero is overwritten with the true number
-+ ** of records (see syncJournal()).
-+ **
-+ ** A faster alternative is to write 0xFFFFFFFF to the nRec field. When
-+ ** reading the journal this value tells SQLite to assume that the
-+ ** rest of the journal file contains valid page records. This assumption
-+ ** is dangerous, as if a failure occurred whilst writing to the journal
-+ ** file it may contain some garbage data. There are two scenarios
-+ ** where this risk can be ignored:
-+ **
-+ ** * When the pager is in no-sync mode. Corruption can follow a
-+ ** power failure in this case anyway.
-+ **
-+ ** * When the SQLITE_IOCAP_SAFE_APPEND flag is set. This guarantees
-+ ** that garbage data is never appended to the journal file.
-+ */
-+ assert( isOpen(pPager->fd) || pPager->noSync );
-+ if( pPager->noSync || (pPager->journalMode==PAGER_JOURNALMODE_MEMORY)
-+ || (sqlite3OsDeviceCharacteristics(pPager->fd)&SQLITE_IOCAP_SAFE_APPEND)
- ){
-- /* Sector size doesn't matter for temporary files. Also, the file
-- ** may not have been opened yet, in which case the OsSectorSize()
-- ** call will segfault. */
-- pPager->sectorSize = 512;
-+ memcpy(zHeader, aJournalMagic, sizeof(aJournalMagic));
-+ put32bits(&zHeader[sizeof(aJournalMagic)], 0xffffffff);
- }else{
-- pPager->sectorSize = sqlite3SectorSize(pPager->fd);
-+ memset(zHeader, 0, sizeof(aJournalMagic)+4);
-+ }
-+
-+ /* The random check-hash initializer */
-+ sqlite3_randomness(sizeof(pPager->cksumInit), &pPager->cksumInit);
-+ put32bits(&zHeader[sizeof(aJournalMagic)+4], pPager->cksumInit);
-+ /* The initial database size */
-+ put32bits(&zHeader[sizeof(aJournalMagic)+8], pPager->dbOrigSize);
-+ /* The assumed sector size for this process */
-+ put32bits(&zHeader[sizeof(aJournalMagic)+12], pPager->sectorSize);
-+
-+ /* The page size */
-+ put32bits(&zHeader[sizeof(aJournalMagic)+16], pPager->pageSize);
-+
-+ /* Initializing the tail of the buffer is not necessary. Everything
-+ ** works find if the following memset() is omitted. But initializing
-+ ** the memory prevents valgrind from complaining, so we are willing to
-+ ** take the performance hit.
-+ */
-+ memset(&zHeader[sizeof(aJournalMagic)+20], 0,
-+ nHeader-(sizeof(aJournalMagic)+20));
-+
-+ /* In theory, it is only necessary to write the 28 bytes that the
-+ ** journal header consumes to the journal file here. Then increment the
-+ ** Pager.journalOff variable by JOURNAL_HDR_SZ so that the next
-+ ** record is written to the following sector (leaving a gap in the file
-+ ** that will be implicitly filled in by the OS).
-+ **
-+ ** However it has been discovered that on some systems this pattern can
-+ ** be significantly slower than contiguously writing data to the file,
-+ ** even if that means explicitly writing data to the block of
-+ ** (JOURNAL_HDR_SZ - 28) bytes that will not be used. So that is what
-+ ** is done.
-+ **
-+ ** The loop is required here in case the sector-size is larger than the
-+ ** database page size. Since the zHeader buffer is only Pager.pageSize
-+ ** bytes in size, more than one call to sqlite3OsWrite() may be required
-+ ** to populate the entire journal header sector.
-+ */
-+ for(nWrite=0; rc==SQLITE_OK&&nWrite<JOURNAL_HDR_SZ(pPager); nWrite+=nHeader){
-+ IOTRACE(("JHDR %p %lld %d\n", pPager, pPager->journalHdr, nHeader))
-+ rc = sqlite3OsWrite(pPager->jfd, zHeader, nHeader, pPager->journalOff);
-+ assert( pPager->journalHdr <= pPager->journalOff );
-+ pPager->journalOff += nHeader;
- }
-+
-+ return rc;
- }
-
- /*
--** Playback the journal and thus restore the database file to
--** the state it was in before we started making changes.
--**
--** The journal file format is as follows:
--**
--** (1) 8 byte prefix. A copy of aJournalMagic[].
--** (2) 4 byte big-endian integer which is the number of valid page records
--** in the journal. If this value is 0xffffffff, then compute the
--** number of page records from the journal size.
--** (3) 4 byte big-endian integer which is the initial value for the
--** sanity checksum.
--** (4) 4 byte integer which is the number of pages to truncate the
--** database to during a rollback.
--** (5) 4 byte big-endian integer which is the sector size. The header
--** is this many bytes in size.
--** (6) 4 byte big-endian integer which is the page size.
--** (7) zero padding out to the next sector size.
--** (8) Zero or more pages instances, each as follows:
--** + 4 byte page number.
--** + pPager->pageSize bytes of data.
--** + 4 byte checksum
--**
--** When we speak of the journal header, we mean the first 7 items above.
--** Each entry in the journal is an instance of the 8th item.
--**
--** Call the value from the second bullet "nRec". nRec is the number of
--** valid page entries in the journal. In most cases, you can compute the
--** value of nRec from the size of the journal file. But if a power
--** failure occurred while the journal was being written, it could be the
--** case that the size of the journal file had already been increased but
--** the extra entries had not yet made it safely to disk. In such a case,
--** the value of nRec computed from the file size would be too large. For
--** that reason, we always use the nRec value in the header.
--**
--** If the nRec value is 0xffffffff it means that nRec should be computed
--** from the file size. This value is used when the user selects the
--** no-sync option for the journal. A power failure could lead to corruption
--** in this case. But for things like temporary table (which will be
--** deleted when the power is restored) we don't care.
--**
--** If the file opened as the journal file is not a well-formed
--** journal file then all pages up to the first corrupted page are rolled
--** back (or no pages if the journal header is corrupted). The journal file
--** is then deleted and SQLITE_OK returned, just as if no corruption had
--** been encountered.
-+** The journal file must be open when this is called. A journal header file
-+** (JOURNAL_HDR_SZ bytes) is read from the current location in the journal
-+** file. The current location in the journal file is given by
-+** pPager->journalOff. See comments above function writeJournalHdr() for
-+** a description of the journal header format.
- **
--** If an I/O or malloc() error occurs, the journal-file is not deleted
--** and an error code is returned.
-+** If the header is read successfully, *pNRec is set to the number of
-+** page records following this header and *pDbSize is set to the size of the
-+** database before the transaction began, in pages. Also, pPager->cksumInit
-+** is set to the value read from the journal header. SQLITE_OK is returned
-+** in this case.
- **
--** The isHot parameter indicates that we are trying to rollback a journal
--** that might be a hot journal. Or, it could be that the journal is
--** preserved because of JOURNALMODE_PERSIST or JOURNALMODE_TRUNCATE.
--** If the journal really is hot, reset the pager cache prior rolling
--** back any content. If the journal is merely persistent, no reset is
--** needed.
-+** If the journal header file appears to be corrupted, SQLITE_DONE is
-+** returned and *pNRec and *PDbSize are undefined. If JOURNAL_HDR_SZ bytes
-+** cannot be read from the journal file an error code is returned.
- */
--static int pager_playback(Pager *pPager, int isHot){
-- sqlite3_vfs *pVfs = pPager->pVfs;
-- i64 szJ; /* Size of the journal file in bytes */
-- u32 nRec; /* Number of Records in the journal */
-- u32 u; /* Unsigned loop counter */
-- Pgno mxPg = 0; /* Size of the original file in pages */
-- int rc; /* Result code of a subroutine */
-- int res = 1; /* Value returned by sqlite3OsAccess() */
-- char *zMaster = 0; /* Name of master journal file if any */
-- int needPagerReset; /* True to reset page prior to first page rollback */
-- int nPlayback = 0; /* Total number of pages restored from journal */
-+static int readJournalHdr(
-+ Pager *pPager, /* Pager object */
-+ int isHot,
-+ i64 journalSize, /* Size of the open journal file in bytes */
-+ u32 *pNRec, /* OUT: Value read from the nRec field */
-+ u32 *pDbSize /* OUT: Value of original database size field */
-+){
-+ int rc; /* Return code */
-+ unsigned char aMagic[8]; /* A buffer to hold the magic header */
-+ i64 iHdrOff; /* Offset of journal header being read */
-
-- /* Figure out how many records are in the journal. Abort early if
-- ** the journal is empty.
-+ assert( isOpen(pPager->jfd) ); /* Journal file must be open. */
-+
-+ /* Advance Pager.journalOff to the start of the next sector. If the
-+ ** journal file is too small for there to be a header stored at this
-+ ** point, return SQLITE_DONE.
- */
-- assert( isOpen(pPager->jfd) );
-- rc = sqlite3OsFileSize(pPager->jfd, &szJ);
-- if( rc!=SQLITE_OK ){
-- goto end_playback;
-+ pPager->journalOff = journalHdrOffset(pPager);
-+ if( pPager->journalOff+JOURNAL_HDR_SZ(pPager) > journalSize ){
-+ return SQLITE_DONE;
- }
-+ iHdrOff = pPager->journalOff;
-
-- /* Read the master journal name from the journal, if it is present.
-- ** If a master journal file name is specified, but the file is not
-- ** present on disk, then the journal is not hot and does not need to be
-- ** played back.
-- **
-- ** TODO: Technically the following is an error because it assumes that
-- ** buffer Pager.pTmpSpace is (mxPathname+1) bytes or larger. i.e. that
-- ** (pPager->pageSize >= pPager->pVfs->mxPathname+1). Using os_unix.c,
-- ** mxPathname is 512, which is the same as the minimum allowable value
-- ** for pageSize.
-+ /* Read in the first 8 bytes of the journal header. If they do not match
-+ ** the magic string found at the start of each journal header, return
-+ ** SQLITE_DONE. If an IO error occurs, return an error code. Otherwise,
-+ ** proceed.
- */
-- zMaster = pPager->pTmpSpace;
-- rc = readMasterJournal(pPager->jfd, zMaster, pPager->pVfs->mxPathname+1);
-- if( rc==SQLITE_OK && zMaster[0] ){
-- rc = sqlite3OsAccess(pVfs, zMaster, SQLITE_ACCESS_EXISTS, &res);
-- }
-- zMaster = 0;
-- if( rc!=SQLITE_OK || !res ){
-- goto end_playback;
-+ if( isHot || iHdrOff!=pPager->journalHdr ){
-+ rc = sqlite3OsRead(pPager->jfd, aMagic, sizeof(aMagic), iHdrOff);
-+ if( rc ){
-+ return rc;
-+ }
-+ if( memcmp(aMagic, aJournalMagic, sizeof(aMagic))!=0 ){
-+ return SQLITE_DONE;
-+ }
- }
-- pPager->journalOff = 0;
-- needPagerReset = isHot;
-
-- /* This loop terminates either when a readJournalHdr() or
-- ** pager_playback_one_page() call returns SQLITE_DONE or an IO error
-- ** occurs.
-+ /* Read the first three 32-bit fields of the journal header: The nRec
-+ ** field, the checksum-initializer and the database size at the start
-+ ** of the transaction. Return an error code if anything goes wrong.
- */
-- while( 1 ){
-- /* Read the next journal header from the journal file. If there are
-- ** not enough bytes left in the journal file for a complete header, or
-- ** it is corrupted, then a process must have failed while writing it.
-- ** This indicates nothing more needs to be rolled back.
-- */
-- rc = readJournalHdr(pPager, isHot, szJ, &nRec, &mxPg);
-- if( rc!=SQLITE_OK ){
-- if( rc==SQLITE_DONE ){
-- rc = SQLITE_OK;
-- }
-- goto end_playback;
-- }
-+ if( SQLITE_OK!=(rc = read32bits(pPager->jfd, iHdrOff+8, pNRec))
-+ || SQLITE_OK!=(rc = read32bits(pPager->jfd, iHdrOff+12, &pPager->cksumInit))
-+ || SQLITE_OK!=(rc = read32bits(pPager->jfd, iHdrOff+16, pDbSize))
-+ ){
-+ return rc;
-+ }
-
-- /* If nRec is 0xffffffff, then this journal was created by a process
-- ** working in no-sync mode. This means that the rest of the journal
-- ** file consists of pages, there are no more journal headers. Compute
-- ** the value of nRec based on this assumption.
-- */
-- if( nRec==0xffffffff ){
-- assert( pPager->journalOff==JOURNAL_HDR_SZ(pPager) );
-- nRec = (int)((szJ - JOURNAL_HDR_SZ(pPager))/JOURNAL_PG_SZ(pPager));
-- }
-+ if( pPager->journalOff==0 ){
-+ u32 iPageSize; /* Page-size field of journal header */
-+ u32 iSectorSize; /* Sector-size field of journal header */
-
-- /* If nRec is 0 and this rollback is of a transaction created by this
-- ** process and if this is the final header in the journal, then it means
-- ** that this part of the journal was being filled but has not yet been
-- ** synced to disk. Compute the number of pages based on the remaining
-- ** size of the file.
-- **
-- ** The third term of the test was added to fix ticket #2565.
-- ** When rolling back a hot journal, nRec==0 always means that the next
-- ** chunk of the journal contains zero pages to be rolled back. But
-- ** when doing a ROLLBACK and the nRec==0 chunk is the last chunk in
-- ** the journal, it means that the journal might contain additional
-- ** pages that need to be rolled back and that the number of pages
-- ** should be computed based on the journal file size.
-- */
-- if( nRec==0 && !isHot &&
-- pPager->journalHdr+JOURNAL_HDR_SZ(pPager)==pPager->journalOff ){
-- nRec = (int)((szJ - pPager->journalOff) / JOURNAL_PG_SZ(pPager));
-+ /* Read the page-size and sector-size journal header fields. */
-+ if( SQLITE_OK!=(rc = read32bits(pPager->jfd, iHdrOff+20, &iSectorSize))
-+ || SQLITE_OK!=(rc = read32bits(pPager->jfd, iHdrOff+24, &iPageSize))
-+ ){
-+ return rc;
- }
-
-- /* If this is the first header read from the journal, truncate the
-- ** database file back to its original size.
-+ /* Versions of SQLite prior to 3.5.8 set the page-size field of the
-+ ** journal header to zero. In this case, assume that the Pager.pageSize
-+ ** variable is already set to the correct page size.
- */
-- if( pPager->journalOff==JOURNAL_HDR_SZ(pPager) ){
-- rc = pager_truncate(pPager, mxPg);
-- if( rc!=SQLITE_OK ){
-- goto end_playback;
-- }
-- pPager->dbSize = mxPg;
-+ if( iPageSize==0 ){
-+ iPageSize = pPager->pageSize;
- }
-
-- /* Copy original pages out of the journal and back into the
-- ** database file and/or page cache.
-+ /* Check that the values read from the page-size and sector-size fields
-+ ** are within range. To be 'in range', both values need to be a power
-+ ** of two greater than or equal to 512 or 32, and not greater than their
-+ ** respective compile time maximum limits.
- */
-- for(u=0; u<nRec; u++){
-- if( needPagerReset ){
-- pager_reset(pPager);
-- needPagerReset = 0;
-- }
-- rc = pager_playback_one_page(pPager,&pPager->journalOff,0,1,0);
-- if( rc==SQLITE_OK ){
-- nPlayback++;
-- }else{
-- if( rc==SQLITE_DONE ){
-- pPager->journalOff = szJ;
-- break;
-- }else if( rc==SQLITE_IOERR_SHORT_READ ){
-- /* If the journal has been truncated, simply stop reading and
-- ** processing the journal. This might happen if the journal was
-- ** not completely written and synced prior to a crash. In that
-- ** case, the database should have never been written in the
-- ** first place so it is OK to simply abandon the rollback. */
-- rc = SQLITE_OK;
-- goto end_playback;
-- }else{
-- /* If we are unable to rollback, quit and return the error
-- ** code. This will cause the pager to enter the error state
-- ** so that no further harm will be done. Perhaps the next
-- ** process to come along will be able to rollback the database.
-- */
-- goto end_playback;
-- }
-- }
-- }
-- }
-- /*NOTREACHED*/
-- assert( 0 );
--
--end_playback:
-- /* Following a rollback, the database file should be back in its original
-- ** state prior to the start of the transaction, so invoke the
-- ** SQLITE_FCNTL_DB_UNCHANGED file-control method to disable the
-- ** assertion that the transaction counter was modified.
-- */
--#ifdef SQLITE_DEBUG
-- if( pPager->fd->pMethods ){
-- sqlite3OsFileControlHint(pPager->fd,SQLITE_FCNTL_DB_UNCHANGED,0);
-- }
--#endif
--
-- /* If this playback is happening automatically as a result of an IO or
-- ** malloc error that occurred after the change-counter was updated but
-- ** before the transaction was committed, then the change-counter
-- ** modification may just have been reverted. If this happens in exclusive
-- ** mode, then subsequent transactions performed by the connection will not
-- ** update the change-counter at all. This may lead to cache inconsistency
-- ** problems for other processes at some point in the future. So, just
-- ** in case this has happened, clear the changeCountDone flag now.
-- */
-- pPager->changeCountDone = pPager->tempFile;
-+ if( iPageSize<512 || iSectorSize<32
-+ || iPageSize>SQLITE_MAX_PAGE_SIZE || iSectorSize>MAX_SECTOR_SIZE
-+ || ((iPageSize-1)&iPageSize)!=0 || ((iSectorSize-1)&iSectorSize)!=0
-+ ){
-+ /* If the either the page-size or sector-size in the journal-header is
-+ ** invalid, then the process that wrote the journal-header must have
-+ ** crashed before the header was synced. In this case stop reading
-+ ** the journal file here.
-+ */
-+ return SQLITE_DONE;
-+ }
-
-- if( rc==SQLITE_OK ){
-- zMaster = pPager->pTmpSpace;
-- rc = readMasterJournal(pPager->jfd, zMaster, pPager->pVfs->mxPathname+1);
-- testcase( rc!=SQLITE_OK );
-- }
-- if( rc==SQLITE_OK
-- && (pPager->eState>=PAGER_WRITER_DBMOD || pPager->eState==PAGER_OPEN)
-- ){
-- rc = sqlite3PagerSync(pPager);
-- }
-- if( rc==SQLITE_OK ){
-- rc = pager_end_transaction(pPager, zMaster[0]!='\0', 0);
-- testcase( rc!=SQLITE_OK );
-- }
-- if( rc==SQLITE_OK && zMaster[0] && res ){
-- /* If there was a master journal and this routine will return success,
-- ** see if it is possible to delete the master journal.
-+ /* Update the page-size to match the value read from the journal.
-+ ** Use a testcase() macro to make sure that malloc failure within
-+ ** PagerSetPagesize() is tested.
- */
-- rc = pager_delmaster(pPager, zMaster);
-+ rc = sqlite3PagerSetPagesize(pPager, &iPageSize, -1);
- testcase( rc!=SQLITE_OK );
-- }
-- if( isHot && nPlayback ){
-- sqlite3_log(SQLITE_NOTICE_RECOVER_ROLLBACK, "recovered %d pages from %s",
-- nPlayback, pPager->zJournal);
-+
-+ /* Update the assumed sector-size to match the value used by
-+ ** the process that created this journal. If this journal was
-+ ** created by a process other than this one, then this routine
-+ ** is being called from within pager_playback(). The local value
-+ ** of Pager.sectorSize is restored at the end of that routine.
-+ */
-+ pPager->sectorSize = iSectorSize;
- }
-
-- /* The Pager.sectorSize variable may have been updated while rolling
-- ** back a journal created by a process with a different sector size
-- ** value. Reset it to the correct value for this process.
-- */
-- setSectorSize(pPager);
-+ pPager->journalOff += JOURNAL_HDR_SZ(pPager);
- return rc;
- }
-
-
- /*
--** Read the content for page pPg out of the database file and into
--** pPg->pData. A shared lock or greater must be held on the database
--** file before this function is called.
-+** Write the supplied master journal name into the journal file for pager
-+** pPager at the current location. The master journal name must be the last
-+** thing written to a journal file. If the pager is in full-sync mode, the
-+** journal file descriptor is advanced to the next sector boundary before
-+** anything is written. The format is:
- **
--** If page 1 is read, then the value of Pager.dbFileVers[] is set to
--** the value read from the database file.
-+** + 4 bytes: PAGER_MJ_PGNO.
-+** + N bytes: Master journal filename in utf-8.
-+** + 4 bytes: N (length of master journal name in bytes, no nul-terminator).
-+** + 4 bytes: Master journal name checksum.
-+** + 8 bytes: aJournalMagic[].
- **
--** If an IO error occurs, then the IO error is returned to the caller.
--** Otherwise, SQLITE_OK is returned.
-+** The master journal page checksum is the sum of the bytes in the master
-+** journal name, where each byte is interpreted as a signed 8-bit integer.
-+**
-+** If zMaster is a NULL pointer (occurs for a single database transaction),
-+** this call is a no-op.
- */
--static int readDbPage(PgHdr *pPg, u32 iFrame){
-- Pager *pPager = pPg->pPager; /* Pager object associated with page pPg */
-- Pgno pgno = pPg->pgno; /* Page number to read */
-- int rc = SQLITE_OK; /* Return code */
-- int pgsz = pPager->pageSize; /* Number of bytes to read */
-+static int writeMasterJournal(Pager *pPager, const char *zMaster){
-+ int rc; /* Return code */
-+ int nMaster; /* Length of string zMaster */
-+ i64 iHdrOff; /* Offset of header in journal file */
-+ i64 jrnlSize; /* Size of journal file on disk */
-+ u32 cksum = 0; /* Checksum of string zMaster */
-
-- assert( pPager->eState>=PAGER_READER && !MEMDB );
-- assert( isOpen(pPager->fd) );
-+ assert( pPager->setMaster==0 );
-+ assert( !pagerUseWal(pPager) );
-
-- if( NEVER(!isOpen(pPager->fd)) ){
-- assert( pPager->tempFile );
-- memset(pPg->pData, 0, pPager->pageSize);
-+ if( !zMaster
-+ || pPager->journalMode==PAGER_JOURNALMODE_MEMORY
-+ || pPager->journalMode==PAGER_JOURNALMODE_OFF
-+ ){
- return SQLITE_OK;
- }
-+ pPager->setMaster = 1;
-+ assert( isOpen(pPager->jfd) );
-+ assert( pPager->journalHdr <= pPager->journalOff );
-
--#ifndef SQLITE_OMIT_WAL
-- if( iFrame ){
-- /* Try to pull the page from the write-ahead log. */
-- rc = sqlite3WalReadFrame(pPager->pWal, iFrame, pgsz, pPg->pData);
-- }else
--#endif
-- {
-- i64 iOffset = (pgno-1)*(i64)pPager->pageSize;
-- rc = sqlite3OsRead(pPager->fd, pPg->pData, pgsz, iOffset);
-- if( rc==SQLITE_IOERR_SHORT_READ ){
-- rc = SQLITE_OK;
-- }
-+ /* Calculate the length in bytes and the checksum of zMaster */
-+ for(nMaster=0; zMaster[nMaster]; nMaster++){
-+ cksum += zMaster[nMaster];
- }
-
-- if( pgno==1 ){
-- if( rc ){
-- /* If the read is unsuccessful, set the dbFileVers[] to something
-- ** that will never be a valid file version. dbFileVers[] is a copy
-- ** of bytes 24..39 of the database. Bytes 28..31 should always be
-- ** zero or the size of the database in page. Bytes 32..35 and 35..39
-- ** should be page numbers which are never 0xffffffff. So filling
-- ** pPager->dbFileVers[] with all 0xff bytes should suffice.
-- **
-- ** For an encrypted database, the situation is more complex: bytes
-- ** 24..39 of the database are white noise. But the probability of
-- ** white noising equaling 16 bytes of 0xff is vanishingly small so
-- ** we should still be ok.
-- */
-- memset(pPager->dbFileVers, 0xff, sizeof(pPager->dbFileVers));
-- }else{
-- u8 *dbFileVers = &((u8*)pPg->pData)[24];
-- memcpy(&pPager->dbFileVers, dbFileVers, sizeof(pPager->dbFileVers));
-- }
-+ /* If in full-sync mode, advance to the next disk sector before writing
-+ ** the master journal name. This is in case the previous page written to
-+ ** the journal has already been synced.
-+ */
-+ if( pPager->fullSync ){
-+ pPager->journalOff = journalHdrOffset(pPager);
- }
-- CODEC1(pPager, pPg->pData, pgno, 3, rc = SQLITE_NOMEM);
-+ iHdrOff = pPager->journalOff;
-
-- PAGER_INCR(sqlite3_pager_readdb_count);
-- PAGER_INCR(pPager->nRead);
-- IOTRACE(("PGIN %p %d\n", pPager, pgno));
-- PAGERTRACE(("FETCH %d page %d hash(%08x)\n",
-- PAGERID(pPager), pgno, pager_pagehash(pPg)));
-+ /* Write the master journal data to the end of the journal file. If
-+ ** an error occurs, return the error code to the caller.
-+ */
-+ if( (0 != (rc = write32bits(pPager->jfd, iHdrOff, PAGER_MJ_PGNO(pPager))))
-+ || (0 != (rc = sqlite3OsWrite(pPager->jfd, zMaster, nMaster, iHdrOff+4)))
-+ || (0 != (rc = write32bits(pPager->jfd, iHdrOff+4+nMaster, nMaster)))
-+ || (0 != (rc = write32bits(pPager->jfd, iHdrOff+4+nMaster+4, cksum)))
-+ || (0 != (rc = sqlite3OsWrite(pPager->jfd, aJournalMagic, 8, iHdrOff+4+nMaster+8)))
-+ ){
-+ return rc;
-+ }
-+ pPager->journalOff += (nMaster+20);
-
-+ /* If the pager is in peristent-journal mode, then the physical
-+ ** journal-file may extend past the end of the master-journal name
-+ ** and 8 bytes of magic data just written to the file. This is
-+ ** dangerous because the code to rollback a hot-journal file
-+ ** will not be able to find the master-journal name to determine
-+ ** whether or not the journal is hot.
-+ **
-+ ** Easiest thing to do in this scenario is to truncate the journal
-+ ** file to the required size.
-+ */
-+ if( SQLITE_OK==(rc = sqlite3OsFileSize(pPager->jfd, &jrnlSize))
-+ && jrnlSize>pPager->journalOff
-+ ){
-+ rc = sqlite3OsTruncate(pPager->jfd, pPager->journalOff);
-+ }
- return rc;
- }
-
- /*
--** Update the value of the change-counter at offsets 24 and 92 in
--** the header and the sqlite version number at offset 96.
--**
--** This is an unconditional update. See also the pager_incr_changecounter()
--** routine which only updates the change-counter if the update is actually
--** needed, as determined by the pPager->changeCountDone state variable.
-+** Find a page in the hash table given its page number. Return
-+** a pointer to the page or NULL if the requested page is not
-+** already in memory.
- */
--static void pager_write_changecounter(PgHdr *pPg){
-- u32 change_counter;
--
-- /* Increment the value just read and write it back to byte 24. */
-- change_counter = sqlite3Get4byte((u8*)pPg->pPager->dbFileVers)+1;
-- put32bits(((char*)pPg->pData)+24, change_counter);
-+static PgHdr *pager_lookup(Pager *pPager, Pgno pgno){
-+ PgHdr *p; /* Return value */
-
-- /* Also store the SQLite version number in bytes 96..99 and in
-- ** bytes 92..95 store the change counter for which the version number
-- ** is valid. */
-- put32bits(((char*)pPg->pData)+92, change_counter);
-- put32bits(((char*)pPg->pData)+96, SQLITE_VERSION_NUMBER);
-+ /* It is not possible for a call to PcacheFetch() with createFlag==0 to
-+ ** fail, since no attempt to allocate dynamic memory will be made.
-+ */
-+ (void)sqlite3PcacheFetch(pPager->pPCache, pgno, 0, &p);
-+ return p;
- }
-
--#ifndef SQLITE_OMIT_WAL
- /*
--** This function is invoked once for each page that has already been
--** written into the log file when a WAL transaction is rolled back.
--** Parameter iPg is the page number of said page. The pCtx argument
--** is actually a pointer to the Pager structure.
--**
--** If page iPg is present in the cache, and has no outstanding references,
--** it is discarded. Otherwise, if there are one or more outstanding
--** references, the page content is reloaded from the database. If the
--** attempt to reload content from the database is required and fails,
--** return an SQLite error code. Otherwise, SQLITE_OK.
-+** Discard the entire contents of the in-memory page-cache.
- */
--static int pagerUndoCallback(void *pCtx, Pgno iPg){
-- int rc = SQLITE_OK;
-- Pager *pPager = (Pager *)pCtx;
-- PgHdr *pPg;
--
-- assert( pagerUseWal(pPager) );
-- pPg = sqlite3PagerLookup(pPager, iPg);
-- if( pPg ){
-- if( sqlite3PcachePageRefcount(pPg)==1 ){
-- sqlite3PcacheDrop(pPg);
-- }else{
-- u32 iFrame = 0;
-- rc = sqlite3WalFindFrame(pPager->pWal, pPg->pgno, &iFrame);
-- if( rc==SQLITE_OK ){
-- rc = readDbPage(pPg, iFrame);
-- }
-- if( rc==SQLITE_OK ){
-- pPager->xReiniter(pPg);
-- }
-- sqlite3PagerUnref(pPg);
-- }
-- }
--
-- /* Normally, if a transaction is rolled back, any backup processes are
-- ** updated as data is copied out of the rollback journal and into the
-- ** database. This is not generally possible with a WAL database, as
-- ** rollback involves simply truncating the log file. Therefore, if one
-- ** or more frames have already been written to the log (and therefore
-- ** also copied into the backup databases) as part of this transaction,
-- ** the backups must be restarted.
-- */
-+static void pager_reset(Pager *pPager){
- sqlite3BackupRestart(pPager->pBackup);
--
-- return rc;
-+ sqlite3PcacheClear(pPager->pPCache);
- }
-
- /*
--** This function is called to rollback a transaction on a WAL database.
-+** Free all structures in the Pager.aSavepoint[] array and set both
-+** Pager.aSavepoint and Pager.nSavepoint to zero. Close the sub-journal
-+** if it is open and the pager is not in exclusive mode.
- */
--static int pagerRollbackWal(Pager *pPager){
-- int rc; /* Return Code */
-- PgHdr *pList; /* List of dirty pages to revert */
--
-- /* For all pages in the cache that are currently dirty or have already
-- ** been written (but not committed) to the log file, do one of the
-- ** following:
-- **
-- ** + Discard the cached page (if refcount==0), or
-- ** + Reload page content from the database (if refcount>0).
-- */
-- pPager->dbSize = pPager->dbOrigSize;
-- rc = sqlite3WalUndo(pPager->pWal, pagerUndoCallback, (void *)pPager);
-- pList = sqlite3PcacheDirtyList(pPager->pPCache);
-- while( pList && rc==SQLITE_OK ){
-- PgHdr *pNext = pList->pDirty;
-- rc = pagerUndoCallback((void *)pPager, pList->pgno);
-- pList = pNext;
-+static void releaseAllSavepoints(Pager *pPager){
-+ int ii; /* Iterator for looping through Pager.aSavepoint */
-+ for(ii=0; ii<pPager->nSavepoint; ii++){
-+ sqlite3BitvecDestroy(pPager->aSavepoint[ii].pInSavepoint);
- }
--
-- return rc;
-+ if( !pPager->exclusiveMode || sqlite3IsMemJournal(pPager->sjfd) ){
-+ sqlite3OsClose(pPager->sjfd);
-+ }
-+ sqlite3_free(pPager->aSavepoint);
-+ pPager->aSavepoint = 0;
-+ pPager->nSavepoint = 0;
-+ pPager->nSubRec = 0;
- }
-
- /*
--** This function is a wrapper around sqlite3WalFrames(). As well as logging
--** the contents of the list of pages headed by pList (connected by pDirty),
--** this function notifies any active backup processes that the pages have
--** changed.
--**
--** The list of pages passed into this routine is always sorted by page number.
--** Hence, if page 1 appears anywhere on the list, it will be the first page.
--*/
--static int pagerWalFrames(
-- Pager *pPager, /* Pager object */
-- PgHdr *pList, /* List of frames to log */
-- Pgno nTruncate, /* Database size after this commit */
-- int isCommit /* True if this is a commit */
--){
-- int rc; /* Return code */
-- int nList; /* Number of pages in pList */
--#if defined(SQLITE_DEBUG) || defined(SQLITE_CHECK_PAGES)
-- PgHdr *p; /* For looping over pages */
--#endif
--
-- assert( pPager->pWal );
-- assert( pList );
--#ifdef SQLITE_DEBUG
-- /* Verify that the page list is in accending order */
-- for(p=pList; p && p->pDirty; p=p->pDirty){
-- assert( p->pgno < p->pDirty->pgno );
-- }
--#endif
--
-- assert( pList->pDirty==0 || isCommit );
-- if( isCommit ){
-- /* If a WAL transaction is being committed, there is no point in writing
-- ** any pages with page numbers greater than nTruncate into the WAL file.
-- ** They will never be read by any client. So remove them from the pDirty
-- ** list here. */
-- PgHdr *p;
-- PgHdr **ppNext = &pList;
-- nList = 0;
-- for(p=pList; (*ppNext = p)!=0; p=p->pDirty){
-- if( p->pgno<=nTruncate ){
-- ppNext = &p->pDirty;
-- nList++;
-- }
-- }
-- assert( pList );
-- }else{
-- nList = 1;
-- }
-- pPager->aStat[PAGER_STAT_WRITE] += nList;
-+** Set the bit number pgno in the PagerSavepoint.pInSavepoint
-+** bitvecs of all open savepoints. Return SQLITE_OK if successful
-+** or SQLITE_NOMEM if a malloc failure occurs.
-+*/
-+static int addToSavepointBitvecs(Pager *pPager, Pgno pgno){
-+ int ii; /* Loop counter */
-+ int rc = SQLITE_OK; /* Result code */
-
-- if( pList->pgno==1 ) pager_write_changecounter(pList);
-- rc = sqlite3WalFrames(pPager->pWal,
-- pPager->pageSize, pList, nTruncate, isCommit, pPager->walSyncFlags
-- );
-- if( rc==SQLITE_OK && pPager->pBackup ){
-- PgHdr *p;
-- for(p=pList; p; p=p->pDirty){
-- sqlite3BackupUpdate(pPager->pBackup, p->pgno, (u8 *)p->pData);
-+ for(ii=0; ii<pPager->nSavepoint; ii++){
-+ PagerSavepoint *p = &pPager->aSavepoint[ii];
-+ if( pgno<=p->nOrig ){
-+ rc |= sqlite3BitvecSet(p->pInSavepoint, pgno);
-+ testcase( rc==SQLITE_NOMEM );
-+ assert( rc==SQLITE_OK || rc==SQLITE_NOMEM );
- }
- }
--
--#ifdef SQLITE_CHECK_PAGES
-- pList = sqlite3PcacheDirtyList(pPager->pPCache);
-- for(p=pList; p; p=p->pDirty){
-- pager_set_pagehash(p);
-- }
--#endif
--
- return rc;
- }
-
- /*
--** Begin a read transaction on the WAL.
-+** This function is a no-op if the pager is in exclusive mode and not
-+** in the ERROR state. Otherwise, it switches the pager to PAGER_OPEN
-+** state.
- **
--** This routine used to be called "pagerOpenSnapshot()" because it essentially
--** makes a snapshot of the database at the current point in time and preserves
--** that snapshot for use by the reader in spite of concurrently changes by
--** other writers or checkpointers.
-+** If the pager is not in exclusive-access mode, the database file is
-+** completely unlocked. If the file is unlocked and the file-system does
-+** not exhibit the UNDELETABLE_WHEN_OPEN property, the journal file is
-+** closed (if it is open).
-+**
-+** If the pager is in ERROR state when this function is called, the
-+** contents of the pager cache are discarded before switching back to
-+** the OPEN state. Regardless of whether the pager is in exclusive-mode
-+** or not, any journal file left in the file-system will be treated
-+** as a hot-journal and rolled back the next time a read-transaction
-+** is opened (by this or by any other connection).
- */
--static int pagerBeginReadTransaction(Pager *pPager){
-- int rc; /* Return code */
-- int changed = 0; /* True if cache must be reset */
--
-- assert( pagerUseWal(pPager) );
-- assert( pPager->eState==PAGER_OPEN || pPager->eState==PAGER_READER );
--
-- /* sqlite3WalEndReadTransaction() was not called for the previous
-- ** transaction in locking_mode=EXCLUSIVE. So call it now. If we
-- ** are in locking_mode=NORMAL and EndRead() was previously called,
-- ** the duplicate call is harmless.
-- */
-- sqlite3WalEndReadTransaction(pPager->pWal);
-+static void pager_unlock(Pager *pPager){
-
-- rc = sqlite3WalBeginReadTransaction(pPager->pWal, &changed);
-- if( rc!=SQLITE_OK || changed ){
-- pager_reset(pPager);
-- if( USEFETCH(pPager) ) sqlite3OsUnfetch(pPager->fd, 0, 0);
-- }
-+ assert( pPager->eState==PAGER_READER
-+ || pPager->eState==PAGER_OPEN
-+ || pPager->eState==PAGER_ERROR
-+ );
-
-- return rc;
--}
--#endif
-+ sqlite3BitvecDestroy(pPager->pInJournal);
-+ pPager->pInJournal = 0;
-+ releaseAllSavepoints(pPager);
-
--/*
--** This function is called as part of the transition from PAGER_OPEN
--** to PAGER_READER state to determine the size of the database file
--** in pages (assuming the page size currently stored in Pager.pageSize).
--**
--** If no error occurs, SQLITE_OK is returned and the size of the database
--** in pages is stored in *pnPage. Otherwise, an error code (perhaps
--** SQLITE_IOERR_FSTAT) is returned and *pnPage is left unmodified.
--*/
--static int pagerPagecount(Pager *pPager, Pgno *pnPage){
-- Pgno nPage; /* Value to return via *pnPage */
-+ if( pagerUseWal(pPager) ){
-+ assert( !isOpen(pPager->jfd) );
-+ sqlite3WalEndReadTransaction(pPager->pWal);
-+ pPager->eState = PAGER_OPEN;
-+ }else if( !pPager->exclusiveMode ){
-+ int rc; /* Error code returned by pagerUnlockDb() */
-+ int iDc = isOpen(pPager->fd)?sqlite3OsDeviceCharacteristics(pPager->fd):0;
-
-- /* Query the WAL sub-system for the database size. The WalDbsize()
-- ** function returns zero if the WAL is not open (i.e. Pager.pWal==0), or
-- ** if the database size is not available. The database size is not
-- ** available from the WAL sub-system if the log file is empty or
-- ** contains no valid committed transactions.
-- */
-- assert( pPager->eState==PAGER_OPEN );
-- assert( pPager->eLock>=SHARED_LOCK );
-- nPage = sqlite3WalDbsize(pPager->pWal);
-+ /* If the operating system support deletion of open files, then
-+ ** close the journal file when dropping the database lock. Otherwise
-+ ** another connection with journal_mode=delete might delete the file
-+ ** out from under us.
-+ */
-+ assert( (PAGER_JOURNALMODE_MEMORY & 5)!=1 );
-+ assert( (PAGER_JOURNALMODE_OFF & 5)!=1 );
-+ assert( (PAGER_JOURNALMODE_WAL & 5)!=1 );
-+ assert( (PAGER_JOURNALMODE_DELETE & 5)!=1 );
-+ assert( (PAGER_JOURNALMODE_TRUNCATE & 5)==1 );
-+ assert( (PAGER_JOURNALMODE_PERSIST & 5)==1 );
-+ if( 0==(iDc & SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN)
-+ || 1!=(pPager->journalMode & 5)
-+ ){
-+ sqlite3OsClose(pPager->jfd);
-+ }
-
-- /* If the database size was not available from the WAL sub-system,
-- ** determine it based on the size of the database file. If the size
-- ** of the database file is not an integer multiple of the page-size,
-- ** round down to the nearest page. Except, any file larger than 0
-- ** bytes in size is considered to contain at least one page.
-- */
-- if( nPage==0 ){
-- i64 n = 0; /* Size of db file in bytes */
-- assert( isOpen(pPager->fd) || pPager->tempFile );
-- if( isOpen(pPager->fd) ){
-- int rc = sqlite3OsFileSize(pPager->fd, &n);
-- if( rc!=SQLITE_OK ){
-- return rc;
-- }
-+ /* If the pager is in the ERROR state and the call to unlock the database
-+ ** file fails, set the current lock to UNKNOWN_LOCK. See the comment
-+ ** above the #define for UNKNOWN_LOCK for an explanation of why this
-+ ** is necessary.
-+ */
-+ rc = pagerUnlockDb(pPager, NO_LOCK);
-+ if( rc!=SQLITE_OK && pPager->eState==PAGER_ERROR ){
-+ pPager->eLock = UNKNOWN_LOCK;
- }
-- nPage = (Pgno)((n+pPager->pageSize-1) / pPager->pageSize);
-+
-+ /* The pager state may be changed from PAGER_ERROR to PAGER_OPEN here
-+ ** without clearing the error code. This is intentional - the error
-+ ** code is cleared and the cache reset in the block below.
-+ */
-+ assert( pPager->errCode || pPager->eState!=PAGER_ERROR );
-+ pPager->changeCountDone = 0;
-+ pPager->eState = PAGER_OPEN;
- }
-
-- /* If the current number of pages in the file is greater than the
-- ** configured maximum pager number, increase the allowed limit so
-- ** that the file can be read.
-+ /* If Pager.errCode is set, the contents of the pager cache cannot be
-+ ** trusted. Now that there are no outstanding references to the pager,
-+ ** it can safely move back to PAGER_OPEN state. This happens in both
-+ ** normal and exclusive-locking mode.
- */
-- if( nPage>pPager->mxPgno ){
-- pPager->mxPgno = (Pgno)nPage;
-+ if( pPager->errCode ){
-+ assert( !MEMDB );
-+ pager_reset(pPager);
-+ pPager->changeCountDone = pPager->tempFile;
-+ pPager->eState = PAGER_OPEN;
-+ pPager->errCode = SQLITE_OK;
- }
-
-- *pnPage = nPage;
-- return SQLITE_OK;
--}
--
--#ifndef SQLITE_OMIT_WAL
--/*
--** Check if the *-wal file that corresponds to the database opened by pPager
--** exists if the database is not empy, or verify that the *-wal file does
--** not exist (by deleting it) if the database file is empty.
--**
--** If the database is not empty and the *-wal file exists, open the pager
--** in WAL mode. If the database is empty or if no *-wal file exists and
--** if no error occurs, make sure Pager.journalMode is not set to
--** PAGER_JOURNALMODE_WAL.
-+ pPager->journalOff = 0;
-+ pPager->journalHdr = 0;
-+ pPager->setMaster = 0;
-+}
-+
-+/*
-+** This function is called whenever an IOERR or FULL error that requires
-+** the pager to transition into the ERROR state may ahve occurred.
-+** The first argument is a pointer to the pager structure, the second
-+** the error-code about to be returned by a pager API function. The
-+** value returned is a copy of the second argument to this function.
- **
--** Return SQLITE_OK or an error code.
-+** If the second argument is SQLITE_FULL, SQLITE_IOERR or one of the
-+** IOERR sub-codes, the pager enters the ERROR state and the error code
-+** is stored in Pager.errCode. While the pager remains in the ERROR state,
-+** all major API calls on the Pager will immediately return Pager.errCode.
- **
--** The caller must hold a SHARED lock on the database file to call this
--** function. Because an EXCLUSIVE lock on the db file is required to delete
--** a WAL on a none-empty database, this ensures there is no race condition
--** between the xAccess() below and an xDelete() being executed by some
--** other connection.
-+** The ERROR state indicates that the contents of the pager-cache
-+** cannot be trusted. This state can be cleared by completely discarding
-+** the contents of the pager-cache. If a transaction was active when
-+** the persistent error occurred, then the rollback journal may need
-+** to be replayed to restore the contents of the database file (as if
-+** it were a hot-journal).
- */
--static int pagerOpenWalIfPresent(Pager *pPager){
-- int rc = SQLITE_OK;
-- assert( pPager->eState==PAGER_OPEN );
-- assert( pPager->eLock>=SHARED_LOCK );
--
-- if( !pPager->tempFile ){
-- int isWal; /* True if WAL file exists */
-- Pgno nPage; /* Size of the database file */
--
-- rc = pagerPagecount(pPager, &nPage);
-- if( rc ) return rc;
-- if( nPage==0 ){
-- rc = sqlite3OsDelete(pPager->pVfs, pPager->zWal, 0);
-- if( rc==SQLITE_IOERR_DELETE_NOENT ) rc = SQLITE_OK;
-- isWal = 0;
-- }else{
-- rc = sqlite3OsAccess(
-- pPager->pVfs, pPager->zWal, SQLITE_ACCESS_EXISTS, &isWal
-- );
-- }
-- if( rc==SQLITE_OK ){
-- if( isWal ){
-- testcase( sqlite3PcachePagecount(pPager->pPCache)==0 );
-- rc = sqlite3PagerOpenWal(pPager, 0);
-- }else if( pPager->journalMode==PAGER_JOURNALMODE_WAL ){
-- pPager->journalMode = PAGER_JOURNALMODE_DELETE;
-- }
-- }
-+static int pager_error(Pager *pPager, int rc){
-+ int rc2 = rc & 0xff;
-+ assert( rc==SQLITE_OK || !MEMDB );
-+ assert(
-+ pPager->errCode==SQLITE_FULL ||
-+ pPager->errCode==SQLITE_OK ||
-+ (pPager->errCode & 0xff)==SQLITE_IOERR
-+ );
-+ if( rc2==SQLITE_FULL || rc2==SQLITE_IOERR ){
-+ pPager->errCode = rc;
-+ pPager->eState = PAGER_ERROR;
- }
- return rc;
- }
--#endif
-+
-+static int pager_truncate(Pager *pPager, Pgno nPage);
-
- /*
--** Playback savepoint pSavepoint. Or, if pSavepoint==NULL, then playback
--** the entire master journal file. The case pSavepoint==NULL occurs when
--** a ROLLBACK TO command is invoked on a SAVEPOINT that is a transaction
--** savepoint.
-+** This routine ends a transaction. A transaction is usually ended by
-+** either a COMMIT or a ROLLBACK operation. This routine may be called
-+** after rollback of a hot-journal, or if an error occurs while opening
-+** the journal file or writing the very first journal-header of a
-+** database transaction.
-+**
-+** This routine is never called in PAGER_ERROR state. If it is called
-+** in PAGER_NONE or PAGER_SHARED state and the lock held is less
-+** exclusive than a RESERVED lock, it is a no-op.
- **
--** When pSavepoint is not NULL (meaning a non-transaction savepoint is
--** being rolled back), then the rollback consists of up to three stages,
--** performed in the order specified:
-+** Otherwise, any active savepoints are released.
- **
--** * Pages are played back from the main journal starting at byte
--** offset PagerSavepoint.iOffset and continuing to
--** PagerSavepoint.iHdrOffset, or to the end of the main journal
--** file if PagerSavepoint.iHdrOffset is zero.
-+** If the journal file is open, then it is "finalized". Once a journal
-+** file has been finalized it is not possible to use it to roll back a
-+** transaction. Nor will it be considered to be a hot-journal by this
-+** or any other database connection. Exactly how a journal is finalized
-+** depends on whether or not the pager is running in exclusive mode and
-+** the current journal-mode (Pager.journalMode value), as follows:
- **
--** * If PagerSavepoint.iHdrOffset is not zero, then pages are played
--** back starting from the journal header immediately following
--** PagerSavepoint.iHdrOffset to the end of the main journal file.
-+** journalMode==MEMORY
-+** Journal file descriptor is simply closed. This destroys an
-+** in-memory journal.
- **
--** * Pages are then played back from the sub-journal file, starting
--** with the PagerSavepoint.iSubRec and continuing to the end of
--** the journal file.
-+** journalMode==TRUNCATE
-+** Journal file is truncated to zero bytes in size.
- **
--** Throughout the rollback process, each time a page is rolled back, the
--** corresponding bit is set in a bitvec structure (variable pDone in the
--** implementation below). This is used to ensure that a page is only
--** rolled back the first time it is encountered in either journal.
-+** journalMode==PERSIST
-+** The first 28 bytes of the journal file are zeroed. This invalidates
-+** the first journal header in the file, and hence the entire journal
-+** file. An invalid journal file cannot be rolled back.
- **
--** If pSavepoint is NULL, then pages are only played back from the main
--** journal file. There is no need for a bitvec in this case.
-+** journalMode==DELETE
-+** The journal file is closed and deleted using sqlite3OsDelete().
- **
--** In either case, before playback commences the Pager.dbSize variable
--** is reset to the value that it held at the start of the savepoint
--** (or transaction). No page with a page-number greater than this value
--** is played back. If one is encountered it is simply skipped.
-+** If the pager is running in exclusive mode, this method of finalizing
-+** the journal file is never used. Instead, if the journalMode is
-+** DELETE and the pager is in exclusive mode, the method described under
-+** journalMode==PERSIST is used instead.
-+**
-+** After the journal is finalized, the pager moves to PAGER_READER state.
-+** If running in non-exclusive rollback mode, the lock on the file is
-+** downgraded to a SHARED_LOCK.
-+**
-+** SQLITE_OK is returned if no error occurs. If an error occurs during
-+** any of the IO operations to finalize the journal file or unlock the
-+** database then the IO error code is returned to the user. If the
-+** operation to finalize the journal file fails, then the code still
-+** tries to unlock the database file if not in exclusive mode. If the
-+** unlock operation fails as well, then the first error code related
-+** to the first error encountered (the journal finalization one) is
-+** returned.
- */
--static int pagerPlaybackSavepoint(Pager *pPager, PagerSavepoint *pSavepoint){
-- i64 szJ; /* Effective size of the main journal */
-- i64 iHdrOff; /* End of first segment of main-journal records */
-- int rc = SQLITE_OK; /* Return code */
-- Bitvec *pDone = 0; /* Bitvec to ensure pages played back only once */
--
-- assert( pPager->eState!=PAGER_ERROR );
-- assert( pPager->eState>=PAGER_WRITER_LOCKED );
--
-- /* Allocate a bitvec to use to store the set of pages rolled back */
-- if( pSavepoint ){
-- pDone = sqlite3BitvecCreate(pSavepoint->nOrig);
-- if( !pDone ){
-- return SQLITE_NOMEM;
-- }
-- }
-+static int pager_end_transaction(Pager *pPager, int hasMaster, int bCommit){
-+ int rc = SQLITE_OK; /* Error code from journal finalization operation */
-+ int rc2 = SQLITE_OK; /* Error code from db file unlock operation */
-
-- /* Set the database size back to the value it was before the savepoint
-- ** being reverted was opened.
-+ /* Do nothing if the pager does not have an open write transaction
-+ ** or at least a RESERVED lock. This function may be called when there
-+ ** is no write-transaction active but a RESERVED or greater lock is
-+ ** held under two circumstances:
-+ **
-+ ** 1. After a successful hot-journal rollback, it is called with
-+ ** eState==PAGER_NONE and eLock==EXCLUSIVE_LOCK.
-+ **
-+ ** 2. If a connection with locking_mode=exclusive holding an EXCLUSIVE
-+ ** lock switches back to locking_mode=normal and then executes a
-+ ** read-transaction, this function is called with eState==PAGER_READER
-+ ** and eLock==EXCLUSIVE_LOCK when the read-transaction is closed.
- */
-- pPager->dbSize = pSavepoint ? pSavepoint->nOrig : pPager->dbOrigSize;
-- pPager->changeCountDone = pPager->tempFile;
--
-- if( !pSavepoint && pagerUseWal(pPager) ){
-- return pagerRollbackWal(pPager);
-+ assert( assert_pager_state(pPager) );
-+ assert( pPager->eState!=PAGER_ERROR );
-+ if( pPager->eState<PAGER_WRITER_LOCKED && pPager->eLock<RESERVED_LOCK ){
-+ return SQLITE_OK;
- }
-
-- /* Use pPager->journalOff as the effective size of the main rollback
-- ** journal. The actual file might be larger than this in
-- ** PAGER_JOURNALMODE_TRUNCATE or PAGER_JOURNALMODE_PERSIST. But anything
-- ** past pPager->journalOff is off-limits to us.
-- */
-- szJ = pPager->journalOff;
-- assert( pagerUseWal(pPager)==0 || szJ==0 );
-+ releaseAllSavepoints(pPager);
-+ assert( isOpen(pPager->jfd) || pPager->pInJournal==0 );
-+ if( isOpen(pPager->jfd) ){
-+ assert( !pagerUseWal(pPager) );
-
-- /* Begin by rolling back records from the main journal starting at
-- ** PagerSavepoint.iOffset and continuing to the next journal header.
-- ** There might be records in the main journal that have a page number
-- ** greater than the current database size (pPager->dbSize) but those
-- ** will be skipped automatically. Pages are added to pDone as they
-- ** are played back.
-- */
-- if( pSavepoint && !pagerUseWal(pPager) ){
-- iHdrOff = pSavepoint->iHdrOffset ? pSavepoint->iHdrOffset : szJ;
-- pPager->journalOff = pSavepoint->iOffset;
-- while( rc==SQLITE_OK && pPager->journalOff<iHdrOff ){
-- rc = pager_playback_one_page(pPager, &pPager->journalOff, pDone, 1, 1);
-+ /* Finalize the journal file. */
-+ if( sqlite3IsMemJournal(pPager->jfd) ){
-+ assert( pPager->journalMode==PAGER_JOURNALMODE_MEMORY );
-+ sqlite3OsClose(pPager->jfd);
-+ }else if( pPager->journalMode==PAGER_JOURNALMODE_TRUNCATE ){
-+ if( pPager->journalOff==0 ){
-+ rc = SQLITE_OK;
-+ }else{
-+ rc = sqlite3OsTruncate(pPager->jfd, 0);
-+ }
-+ pPager->journalOff = 0;
-+ }else if( pPager->journalMode==PAGER_JOURNALMODE_PERSIST
-+ || (pPager->exclusiveMode && pPager->journalMode!=PAGER_JOURNALMODE_WAL)
-+ ){
-+ rc = zeroJournalHdr(pPager, hasMaster);
-+ pPager->journalOff = 0;
-+ }else{
-+ /* This branch may be executed with Pager.journalMode==MEMORY if
-+ ** a hot-journal was just rolled back. In this case the journal
-+ ** file should be closed and deleted. If this connection writes to
-+ ** the database file, it will do so using an in-memory journal.
-+ */
-+ int bDelete = (!pPager->tempFile && sqlite3JournalExists(pPager->jfd));
-+ assert( pPager->journalMode==PAGER_JOURNALMODE_DELETE
-+ || pPager->journalMode==PAGER_JOURNALMODE_MEMORY
-+ || pPager->journalMode==PAGER_JOURNALMODE_WAL
-+ );
-+ sqlite3OsClose(pPager->jfd);
-+ if( bDelete ){
-+ rc = sqlite3OsDelete(pPager->pVfs, pPager->zJournal, 0);
-+ }
- }
-- assert( rc!=SQLITE_DONE );
-- }else{
-- pPager->journalOff = 0;
- }
-
-- /* Continue rolling back records out of the main journal starting at
-- ** the first journal header seen and continuing until the effective end
-- ** of the main journal file. Continue to skip out-of-range pages and
-- ** continue adding pages rolled back to pDone.
-- */
-- while( rc==SQLITE_OK && pPager->journalOff<szJ ){
-- u32 ii; /* Loop counter */
-- u32 nJRec = 0; /* Number of Journal Records */
-- u32 dummy;
-- rc = readJournalHdr(pPager, 0, szJ, &nJRec, &dummy);
-- assert( rc!=SQLITE_DONE );
--
-- /*
-- ** The "pPager->journalHdr+JOURNAL_HDR_SZ(pPager)==pPager->journalOff"
-- ** test is related to ticket #2565. See the discussion in the
-- ** pager_playback() function for additional information.
-- */
-- if( nJRec==0
-- && pPager->journalHdr+JOURNAL_HDR_SZ(pPager)==pPager->journalOff
-- ){
-- nJRec = (u32)((szJ - pPager->journalOff)/JOURNAL_PG_SZ(pPager));
-- }
-- for(ii=0; rc==SQLITE_OK && ii<nJRec && pPager->journalOff<szJ; ii++){
-- rc = pager_playback_one_page(pPager, &pPager->journalOff, pDone, 1, 1);
-+#ifdef SQLITE_CHECK_PAGES
-+ sqlite3PcacheIterateDirty(pPager->pPCache, pager_set_pagehash);
-+ if( pPager->dbSize==0 && sqlite3PcacheRefCount(pPager->pPCache)>0 ){
-+ PgHdr *p = pager_lookup(pPager, 1);
-+ if( p ){
-+ p->pageHash = 0;
-+ sqlite3PagerUnref(p);
- }
-- assert( rc!=SQLITE_DONE );
- }
-- assert( rc!=SQLITE_OK || pPager->journalOff>=szJ );
-+#endif
-
-- /* Finally, rollback pages from the sub-journal. Page that were
-- ** previously rolled back out of the main journal (and are hence in pDone)
-- ** will be skipped. Out-of-range pages are also skipped.
-- */
-- if( pSavepoint ){
-- u32 ii; /* Loop counter */
-- i64 offset = (i64)pSavepoint->iSubRec*(4+pPager->pageSize);
-+ sqlite3BitvecDestroy(pPager->pInJournal);
-+ pPager->pInJournal = 0;
-+ pPager->nRec = 0;
-+ sqlite3PcacheCleanAll(pPager->pPCache);
-+ sqlite3PcacheTruncate(pPager->pPCache, pPager->dbSize);
-
-- if( pagerUseWal(pPager) ){
-- rc = sqlite3WalSavepointUndo(pPager->pWal, pSavepoint->aWalData);
-- }
-- for(ii=pSavepoint->iSubRec; rc==SQLITE_OK && ii<pPager->nSubRec; ii++){
-- assert( offset==(i64)ii*(4+pPager->pageSize) );
-- rc = pager_playback_one_page(pPager, &offset, pDone, 0, 1);
-- }
-- assert( rc!=SQLITE_DONE );
-+ if( pagerUseWal(pPager) ){
-+ /* Drop the WAL write-lock, if any. Also, if the connection was in
-+ ** locking_mode=exclusive mode but is no longer, drop the EXCLUSIVE
-+ ** lock held on the database file.
-+ */
-+ rc2 = sqlite3WalEndWriteTransaction(pPager->pWal);
-+ assert( rc2==SQLITE_OK );
-+ }else if( rc==SQLITE_OK && bCommit && pPager->dbFileSize>pPager->dbSize ){
-+ /* This branch is taken when committing a transaction in rollback-journal
-+ ** mode if the database file on disk is larger than the database image.
-+ ** At this point the journal has been finalized and the transaction
-+ ** successfully committed, but the EXCLUSIVE lock is still held on the
-+ ** file. So it is safe to truncate the database file to its minimum
-+ ** required size. */
-+ assert( pPager->eLock==EXCLUSIVE_LOCK );
-+ rc = pager_truncate(pPager, pPager->dbSize);
- }
-
-- sqlite3BitvecDestroy(pDone);
-- if( rc==SQLITE_OK ){
-- pPager->journalOff = szJ;
-+ if( !pPager->exclusiveMode
-+ && (!pagerUseWal(pPager) || sqlite3WalExclusiveMode(pPager->pWal, 0))
-+ ){
-+ rc2 = pagerUnlockDb(pPager, SHARED_LOCK);
-+ pPager->changeCountDone = 0;
- }
-+ pPager->eState = PAGER_READER;
-+ pPager->setMaster = 0;
-
-- return rc;
--}
--
--/*
--** Change the maximum number of in-memory pages that are allowed.
--*/
--SQLITE_PRIVATE void sqlite3PagerSetCachesize(Pager *pPager, int mxPage){
-- sqlite3PcacheSetCachesize(pPager->pPCache, mxPage);
-+ return (rc==SQLITE_OK?rc2:rc);
- }
-
- /*
--** Invoke SQLITE_FCNTL_MMAP_SIZE based on the current value of szMmap.
-+** Execute a rollback if a transaction is active and unlock the
-+** database file.
-+**
-+** If the pager has already entered the ERROR state, do not attempt
-+** the rollback at this time. Instead, pager_unlock() is called. The
-+** call to pager_unlock() will discard all in-memory pages, unlock
-+** the database file and move the pager back to OPEN state. If this
-+** means that there is a hot-journal left in the file-system, the next
-+** connection to obtain a shared lock on the pager (which may be this one)
-+** will roll it back.
-+**
-+** If the pager has not already entered the ERROR state, but an IO or
-+** malloc error occurs during a rollback, then this will itself cause
-+** the pager to enter the ERROR state. Which will be cleared by the
-+** call to pager_unlock(), as described above.
- */
--static void pagerFixMaplimit(Pager *pPager){
--#if SQLITE_MAX_MMAP_SIZE>0
-- sqlite3_file *fd = pPager->fd;
-- if( isOpen(fd) ){
-- sqlite3_int64 sz;
-- pPager->bUseFetch = (fd->pMethods->iVersion>=3) && pPager->szMmap>0;
-- sz = pPager->szMmap;
-- sqlite3OsFileControlHint(pPager->fd, SQLITE_FCNTL_MMAP_SIZE, &sz);
-+static void pagerUnlockAndRollback(Pager *pPager){
-+ if( pPager->eState!=PAGER_ERROR && pPager->eState!=PAGER_OPEN ){
-+ assert( assert_pager_state(pPager) );
-+ if( pPager->eState>=PAGER_WRITER_LOCKED ){
-+ sqlite3BeginBenignMalloc();
-+ sqlite3PagerRollback(pPager);
-+ sqlite3EndBenignMalloc();
-+ }else if( !pPager->exclusiveMode ){
-+ assert( pPager->eState==PAGER_READER );
-+ pager_end_transaction(pPager, 0, 0);
-+ }
- }
--#endif
--}
--
--/*
--** Change the maximum size of any memory mapping made of the database file.
--*/
--SQLITE_PRIVATE void sqlite3PagerSetMmapLimit(Pager *pPager, sqlite3_int64 szMmap){
-- pPager->szMmap = szMmap;
-- pagerFixMaplimit(pPager);
--}
--
--/*
--** Free as much memory as possible from the pager.
--*/
--SQLITE_PRIVATE void sqlite3PagerShrink(Pager *pPager){
-- sqlite3PcacheShrink(pPager->pPCache);
-+ pager_unlock(pPager);
- }
-
- /*
--** Adjust the robustness of the database to damage due to OS crashes
--** or power failures by changing the number of syncs()s when writing
--** the rollback journal. There are three levels:
--**
--** OFF sqlite3OsSync() is never called. This is the default
--** for temporary and transient files.
--**
--** NORMAL The journal is synced once before writes begin on the
--** database. This is normally adequate protection, but
--** it is theoretically possible, though very unlikely,
--** that an inopertune power failure could leave the journal
--** in a state which would cause damage to the database
--** when it is rolled back.
--**
--** FULL The journal is synced twice before writes begin on the
--** database (with some additional information - the nRec field
--** of the journal header - being written in between the two
--** syncs). If we assume that writing a
--** single disk sector is atomic, then this mode provides
--** assurance that the journal will not be corrupted to the
--** point of causing damage to the database during rollback.
-+** Parameter aData must point to a buffer of pPager->pageSize bytes
-+** of data. Compute and return a checksum based ont the contents of the
-+** page of data and the current value of pPager->cksumInit.
- **
--** The above is for a rollback-journal mode. For WAL mode, OFF continues
--** to mean that no syncs ever occur. NORMAL means that the WAL is synced
--** prior to the start of checkpoint and that the database file is synced
--** at the conclusion of the checkpoint if the entire content of the WAL
--** was written back into the database. But no sync operations occur for
--** an ordinary commit in NORMAL mode with WAL. FULL means that the WAL
--** file is synced following each commit operation, in addition to the
--** syncs associated with NORMAL.
-+** This is not a real checksum. It is really just the sum of the
-+** random initial value (pPager->cksumInit) and every 200th byte
-+** of the page data, starting with byte offset (pPager->pageSize%200).
-+** Each byte is interpreted as an 8-bit unsigned integer.
- **
--** Do not confuse synchronous=FULL with SQLITE_SYNC_FULL. The
--** SQLITE_SYNC_FULL macro means to use the MacOSX-style full-fsync
--** using fcntl(F_FULLFSYNC). SQLITE_SYNC_NORMAL means to do an
--** ordinary fsync() call. There is no difference between SQLITE_SYNC_FULL
--** and SQLITE_SYNC_NORMAL on platforms other than MacOSX. But the
--** synchronous=FULL versus synchronous=NORMAL setting determines when
--** the xSync primitive is called and is relevant to all platforms.
-+** Changing the formula used to compute this checksum results in an
-+** incompatible journal file format.
- **
--** Numeric values associated with these states are OFF==1, NORMAL=2,
--** and FULL=3.
-+** If journal corruption occurs due to a power failure, the most likely
-+** scenario is that one end or the other of the record will be changed.
-+** It is much less likely that the two ends of the journal record will be
-+** correct and the middle be corrupt. Thus, this "checksum" scheme,
-+** though fast and simple, catches the mostly likely kind of corruption.
- */
--#ifndef SQLITE_OMIT_PAGER_PRAGMAS
--SQLITE_PRIVATE void sqlite3PagerSetSafetyLevel(
-- Pager *pPager, /* The pager to set safety level for */
-- int level, /* PRAGMA synchronous. 1=OFF, 2=NORMAL, 3=FULL */
-- int bFullFsync, /* PRAGMA fullfsync */
-- int bCkptFullFsync /* PRAGMA checkpoint_fullfsync */
--){
-- assert( level>=1 && level<=3 );
-- pPager->noSync = (level==1 || pPager->tempFile) ?1:0;
-- pPager->fullSync = (level==3 && !pPager->tempFile) ?1:0;
-- if( pPager->noSync ){
-- pPager->syncFlags = 0;
-- pPager->ckptSyncFlags = 0;
-- }else if( bFullFsync ){
-- pPager->syncFlags = SQLITE_SYNC_FULL;
-- pPager->ckptSyncFlags = SQLITE_SYNC_FULL;
-- }else if( bCkptFullFsync ){
-- pPager->syncFlags = SQLITE_SYNC_NORMAL;
-- pPager->ckptSyncFlags = SQLITE_SYNC_FULL;
-- }else{
-- pPager->syncFlags = SQLITE_SYNC_NORMAL;
-- pPager->ckptSyncFlags = SQLITE_SYNC_NORMAL;
-- }
-- pPager->walSyncFlags = pPager->syncFlags;
-- if( pPager->fullSync ){
-- pPager->walSyncFlags |= WAL_SYNC_TRANSACTIONS;
-+static u32 pager_cksum(Pager *pPager, const u8 *aData){
-+ u32 cksum = pPager->cksumInit; /* Checksum value to return */
-+ int i = pPager->pageSize-200; /* Loop counter */
-+ while( i>0 ){
-+ cksum += aData[i];
-+ i -= 200;
- }
-+ return cksum;
- }
--#endif
-
- /*
--** The following global variable is incremented whenever the library
--** attempts to open a temporary file. This information is used for
--** testing and analysis only.
-+** Report the current page size and number of reserved bytes back
-+** to the codec.
- */
--#ifdef SQLITE_TEST
--SQLITE_API int sqlite3_opentemp_count = 0;
-+#ifdef SQLITE_HAS_CODEC
-+static void pagerReportSize(Pager *pPager){
-+ if( pPager->xCodecSizeChng ){
-+ pPager->xCodecSizeChng(pPager->pCodec, pPager->pageSize,
-+ (int)pPager->nReserve);
-+ }
-+}
-+#else
-+# define pagerReportSize(X) /* No-op if we do not support a codec */
#endif
- /*
--** Open a temporary file.
-+** Read a single page from either the journal file (if isMainJrnl==1) or
-+** from the sub-journal (if isMainJrnl==0) and playback that page.
-+** The page begins at offset *pOffset into the file. The *pOffset
-+** value is increased to the start of the next page in the journal.
- **
--** Write the file descriptor into *pFile. Return SQLITE_OK on success
--** or some other error code if we fail. The OS will automatically
--** delete the temporary file when it is closed.
-+** The main rollback journal uses checksums - the statement journal does
-+** not.
-+**
-+** If the page number of the page record read from the (sub-)journal file
-+** is greater than the current value of Pager.dbSize, then playback is
-+** skipped and SQLITE_OK is returned.
-+**
-+** If pDone is not NULL, then it is a record of pages that have already
-+** been played back. If the page at *pOffset has already been played back
-+** (if the corresponding pDone bit is set) then skip the playback.
-+** Make sure the pDone bit corresponding to the *pOffset page is set
-+** prior to returning.
-+**
-+** If the page record is successfully read from the (sub-)journal file
-+** and played back, then SQLITE_OK is returned. If an IO error occurs
-+** while reading the record from the (sub-)journal file or while writing
-+** to the database file, then the IO error code is returned. If data
-+** is successfully read from the (sub-)journal file but appears to be
-+** corrupted, SQLITE_DONE is returned. Data is considered corrupted in
-+** two circumstances:
-+**
-+** * If the record page-number is illegal (0 or PAGER_MJ_PGNO), or
-+** * If the record is being rolled back from the main journal file
-+** and the checksum field does not match the record content.
- **
--** The flags passed to the VFS layer xOpen() call are those specified
--** by parameter vfsFlags ORed with the following:
-+** Neither of these two scenarios are possible during a savepoint rollback.
- **
--** SQLITE_OPEN_READWRITE
--** SQLITE_OPEN_CREATE
--** SQLITE_OPEN_EXCLUSIVE
--** SQLITE_OPEN_DELETEONCLOSE
-+** If this is a savepoint rollback, then memory may have to be dynamically
-+** allocated by this function. If this is the case and an allocation fails,
-+** SQLITE_NOMEM is returned.
- */
--static int pagerOpentemp(
-- Pager *pPager, /* The pager object */
-- sqlite3_file *pFile, /* Write the file descriptor here */
-- int vfsFlags /* Flags passed through to the VFS */
-+static int pager_playback_one_page(
-+ Pager *pPager, /* The pager being played back */
-+ i64 *pOffset, /* Offset of record to playback */
-+ Bitvec *pDone, /* Bitvec of pages already played back */
-+ int isMainJrnl, /* 1 -> main journal. 0 -> sub-journal. */
-+ int isSavepnt /* True for a savepoint rollback */
- ){
-- int rc; /* Return code */
-+ int rc;
-+ PgHdr *pPg; /* An existing page in the cache */
-+ Pgno pgno; /* The page number of a page in journal */
-+ u32 cksum; /* Checksum used for sanity checking */
-+ char *aData; /* Temporary storage for the page */
-+ sqlite3_file *jfd; /* The file descriptor for the journal file */
-+ int isSynced; /* True if journal page is synced */
-
--#ifdef SQLITE_TEST
-- sqlite3_opentemp_count++; /* Used for testing and analysis only */
--#endif
-+ assert( (isMainJrnl&~1)==0 ); /* isMainJrnl is 0 or 1 */
-+ assert( (isSavepnt&~1)==0 ); /* isSavepnt is 0 or 1 */
-+ assert( isMainJrnl || pDone ); /* pDone always used on sub-journals */
-+ assert( isSavepnt || pDone==0 ); /* pDone never used on non-savepoint */
-
-- vfsFlags |= SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE |
-- SQLITE_OPEN_EXCLUSIVE | SQLITE_OPEN_DELETEONCLOSE;
-- rc = sqlite3OsOpen(pPager->pVfs, 0, pFile, vfsFlags, 0);
-- assert( rc!=SQLITE_OK || isOpen(pFile) );
-- return rc;
--}
-+ aData = pPager->pTmpSpace;
-+ assert( aData ); /* Temp storage must have already been allocated */
-+ assert( pagerUseWal(pPager)==0 || (!isMainJrnl && isSavepnt) );
-
--/*
--** Set the busy handler function.
--**
--** The pager invokes the busy-handler if sqlite3OsLock() returns
--** SQLITE_BUSY when trying to upgrade from no-lock to a SHARED lock,
--** or when trying to upgrade from a RESERVED lock to an EXCLUSIVE
--** lock. It does *not* invoke the busy handler when upgrading from
--** SHARED to RESERVED, or when upgrading from SHARED to EXCLUSIVE
--** (which occurs during hot-journal rollback). Summary:
--**
--** Transition | Invokes xBusyHandler
--** --------------------------------------------------------
--** NO_LOCK -> SHARED_LOCK | Yes
--** SHARED_LOCK -> RESERVED_LOCK | No
--** SHARED_LOCK -> EXCLUSIVE_LOCK | No
--** RESERVED_LOCK -> EXCLUSIVE_LOCK | Yes
--**
--** If the busy-handler callback returns non-zero, the lock is
--** retried. If it returns zero, then the SQLITE_BUSY error is
--** returned to the caller of the pager API function.
--*/
--SQLITE_PRIVATE void sqlite3PagerSetBusyhandler(
-- Pager *pPager, /* Pager object */
-- int (*xBusyHandler)(void *), /* Pointer to busy-handler function */
-- void *pBusyHandlerArg /* Argument to pass to xBusyHandler */
--){
-- pPager->xBusyHandler = xBusyHandler;
-- pPager->pBusyHandlerArg = pBusyHandlerArg;
-+ /* Either the state is greater than PAGER_WRITER_CACHEMOD (a transaction
-+ ** or savepoint rollback done at the request of the caller) or this is
-+ ** a hot-journal rollback. If it is a hot-journal rollback, the pager
-+ ** is in state OPEN and holds an EXCLUSIVE lock. Hot-journal rollback
-+ ** only reads from the main journal, not the sub-journal.
-+ */
-+ assert( pPager->eState>=PAGER_WRITER_CACHEMOD
-+ || (pPager->eState==PAGER_OPEN && pPager->eLock==EXCLUSIVE_LOCK)
-+ );
-+ assert( pPager->eState>=PAGER_WRITER_CACHEMOD || isMainJrnl );
-
-- if( isOpen(pPager->fd) ){
-- void **ap = (void **)&pPager->xBusyHandler;
-- assert( ((int(*)(void *))(ap[0]))==xBusyHandler );
-- assert( ap[1]==pBusyHandlerArg );
-- sqlite3OsFileControlHint(pPager->fd, SQLITE_FCNTL_BUSYHANDLER, (void *)ap);
-+ /* Read the page number and page data from the journal or sub-journal
-+ ** file. Return an error code to the caller if an IO error occurs.
-+ */
-+ jfd = isMainJrnl ? pPager->jfd : pPager->sjfd;
-+ rc = read32bits(jfd, *pOffset, &pgno);
-+ if( rc!=SQLITE_OK ) return rc;
-+ rc = sqlite3OsRead(jfd, (u8*)aData, pPager->pageSize, (*pOffset)+4);
-+ if( rc!=SQLITE_OK ) return rc;
-+ *pOffset += pPager->pageSize + 4 + isMainJrnl*4;
-+
-+ /* Sanity checking on the page. This is more important that I originally
-+ ** thought. If a power failure occurs while the journal is being written,
-+ ** it could cause invalid data to be written into the journal. We need to
-+ ** detect this invalid data (with high probability) and ignore it.
-+ */
-+ if( pgno==0 || pgno==PAGER_MJ_PGNO(pPager) ){
-+ assert( !isSavepnt );
-+ return SQLITE_DONE;
-+ }
-+ if( pgno>(Pgno)pPager->dbSize || sqlite3BitvecTest(pDone, pgno) ){
-+ return SQLITE_OK;
-+ }
-+ if( isMainJrnl ){
-+ rc = read32bits(jfd, (*pOffset)-4, &cksum);
-+ if( rc ) return rc;
-+ if( !isSavepnt && pager_cksum(pPager, (u8*)aData)!=cksum ){
-+ return SQLITE_DONE;
-+ }
-+ }
-+
-+ /* If this page has already been played by before during the current
-+ ** rollback, then don't bother to play it back again.
-+ */
-+ if( pDone && (rc = sqlite3BitvecSet(pDone, pgno))!=SQLITE_OK ){
-+ return rc;
-+ }
-+
-+ /* When playing back page 1, restore the nReserve setting
-+ */
-+ if( pgno==1 && pPager->nReserve!=((u8*)aData)[20] ){
-+ pPager->nReserve = ((u8*)aData)[20];
-+ pagerReportSize(pPager);
-+ }
-+
-+ /* If the pager is in CACHEMOD state, then there must be a copy of this
-+ ** page in the pager cache. In this case just update the pager cache,
-+ ** not the database file. The page is left marked dirty in this case.
-+ **
-+ ** An exception to the above rule: If the database is in no-sync mode
-+ ** and a page is moved during an incremental vacuum then the page may
-+ ** not be in the pager cache. Later: if a malloc() or IO error occurs
-+ ** during a Movepage() call, then the page may not be in the cache
-+ ** either. So the condition described in the above paragraph is not
-+ ** assert()able.
-+ **
-+ ** If in WRITER_DBMOD, WRITER_FINISHED or OPEN state, then we update the
-+ ** pager cache if it exists and the main file. The page is then marked
-+ ** not dirty. Since this code is only executed in PAGER_OPEN state for
-+ ** a hot-journal rollback, it is guaranteed that the page-cache is empty
-+ ** if the pager is in OPEN state.
-+ **
-+ ** Ticket #1171: The statement journal might contain page content that is
-+ ** different from the page content at the start of the transaction.
-+ ** This occurs when a page is changed prior to the start of a statement
-+ ** then changed again within the statement. When rolling back such a
-+ ** statement we must not write to the original database unless we know
-+ ** for certain that original page contents are synced into the main rollback
-+ ** journal. Otherwise, a power loss might leave modified data in the
-+ ** database file without an entry in the rollback journal that can
-+ ** restore the database to its original form. Two conditions must be
-+ ** met before writing to the database files. (1) the database must be
-+ ** locked. (2) we know that the original page content is fully synced
-+ ** in the main journal either because the page is not in cache or else
-+ ** the page is marked as needSync==0.
-+ **
-+ ** 2008-04-14: When attempting to vacuum a corrupt database file, it
-+ ** is possible to fail a statement on a database that does not yet exist.
-+ ** Do not attempt to write if database file has never been opened.
-+ */
-+ if( pagerUseWal(pPager) ){
-+ pPg = 0;
-+ }else{
-+ pPg = pager_lookup(pPager, pgno);
-+ }
-+ assert( pPg || !MEMDB );
-+ assert( pPager->eState!=PAGER_OPEN || pPg==0 );
-+ PAGERTRACE(("PLAYBACK %d page %d hash(%08x) %s\n",
-+ PAGERID(pPager), pgno, pager_datahash(pPager->pageSize, (u8*)aData),
-+ (isMainJrnl?"main-journal":"sub-journal")
-+ ));
-+ if( isMainJrnl ){
-+ isSynced = pPager->noSync || (*pOffset <= pPager->journalHdr);
-+ }else{
-+ isSynced = (pPg==0 || 0==(pPg->flags & PGHDR_NEED_SYNC));
-+ }
-+ if( isOpen(pPager->fd)
-+ && (pPager->eState>=PAGER_WRITER_DBMOD || pPager->eState==PAGER_OPEN)
-+ && isSynced
-+ ){
-+ i64 ofst = (pgno-1)*(i64)pPager->pageSize;
-+ testcase( !isSavepnt && pPg!=0 && (pPg->flags&PGHDR_NEED_SYNC)!=0 );
-+ assert( !pagerUseWal(pPager) );
-+ rc = sqlite3OsWrite(pPager->fd, (u8 *)aData, pPager->pageSize, ofst);
-+ if( pgno>pPager->dbFileSize ){
-+ pPager->dbFileSize = pgno;
-+ }
-+ if( pPager->pBackup ){
-+ CODEC1(pPager, aData, pgno, 3, rc=SQLITE_NOMEM);
-+ sqlite3BackupUpdate(pPager->pBackup, pgno, (u8*)aData);
-+ CODEC2(pPager, aData, pgno, 7, rc=SQLITE_NOMEM, aData);
-+ }
-+ }else if( !isMainJrnl && pPg==0 ){
-+ /* If this is a rollback of a savepoint and data was not written to
-+ ** the database and the page is not in-memory, there is a potential
-+ ** problem. When the page is next fetched by the b-tree layer, it
-+ ** will be read from the database file, which may or may not be
-+ ** current.
-+ **
-+ ** There are a couple of different ways this can happen. All are quite
-+ ** obscure. When running in synchronous mode, this can only happen
-+ ** if the page is on the free-list at the start of the transaction, then
-+ ** populated, then moved using sqlite3PagerMovepage().
-+ **
-+ ** The solution is to add an in-memory page to the cache containing
-+ ** the data just read from the sub-journal. Mark the page as dirty
-+ ** and if the pager requires a journal-sync, then mark the page as
-+ ** requiring a journal-sync before it is written.
-+ */
-+ assert( isSavepnt );
-+ assert( pPager->doNotSpill==0 );
-+ pPager->doNotSpill++;
-+ rc = sqlite3PagerAcquire(pPager, pgno, &pPg, 1);
-+ assert( pPager->doNotSpill==1 );
-+ pPager->doNotSpill--;
-+ if( rc!=SQLITE_OK ) return rc;
-+ pPg->flags &= ~PGHDR_NEED_READ;
-+ sqlite3PcacheMakeDirty(pPg);
-+ }
-+ if( pPg ){
-+ /* No page should ever be explicitly rolled back that is in use, except
-+ ** for page 1 which is held in use in order to keep the lock on the
-+ ** database active. However such a page may be rolled back as a result
-+ ** of an internal error resulting in an automatic call to
-+ ** sqlite3PagerRollback().
-+ */
-+ void *pData;
-+ pData = pPg->pData;
-+ memcpy(pData, (u8*)aData, pPager->pageSize);
-+ pPager->xReiniter(pPg);
-+ if( isMainJrnl && (!isSavepnt || *pOffset<=pPager->journalHdr) ){
-+ /* If the contents of this page were just restored from the main
-+ ** journal file, then its content must be as they were when the
-+ ** transaction was first opened. In this case we can mark the page
-+ ** as clean, since there will be no need to write it out to the
-+ ** database.
-+ **
-+ ** There is one exception to this rule. If the page is being rolled
-+ ** back as part of a savepoint (or statement) rollback from an
-+ ** unsynced portion of the main journal file, then it is not safe
-+ ** to mark the page as clean. This is because marking the page as
-+ ** clean will clear the PGHDR_NEED_SYNC flag. Since the page is
-+ ** already in the journal file (recorded in Pager.pInJournal) and
-+ ** the PGHDR_NEED_SYNC flag is cleared, if the page is written to
-+ ** again within this transaction, it will be marked as dirty but
-+ ** the PGHDR_NEED_SYNC flag will not be set. It could then potentially
-+ ** be written out into the database file before its journal file
-+ ** segment is synced. If a crash occurs during or following this,
-+ ** database corruption may ensue.
-+ */
-+ assert( !pagerUseWal(pPager) );
-+ sqlite3PcacheMakeClean(pPg);
-+ }
-+ pager_set_pagehash(pPg);
-+
-+ /* If this was page 1, then restore the value of Pager.dbFileVers.
-+ ** Do this before any decoding. */
-+ if( pgno==1 ){
-+ memcpy(&pPager->dbFileVers, &((u8*)pData)[24],sizeof(pPager->dbFileVers));
-+ }
-+
-+ /* Decode the page just read from disk */
-+ CODEC1(pPager, pData, pPg->pgno, 3, rc=SQLITE_NOMEM);
-+ sqlite3PcacheRelease(pPg);
- }
-+ return rc;
- }
-
- /*
--** Change the page size used by the Pager object. The new page size
--** is passed in *pPageSize.
-+** Parameter zMaster is the name of a master journal file. A single journal
-+** file that referred to the master journal file has just been rolled back.
-+** This routine checks if it is possible to delete the master journal file,
-+** and does so if it is.
- **
--** If the pager is in the error state when this function is called, it
--** is a no-op. The value returned is the error state error code (i.e.
--** one of SQLITE_IOERR, an SQLITE_IOERR_xxx sub-code or SQLITE_FULL).
-+** Argument zMaster may point to Pager.pTmpSpace. So that buffer is not
-+** available for use within this function.
- **
--** Otherwise, if all of the following are true:
-+** When a master journal file is created, it is populated with the names
-+** of all of its child journals, one after another, formatted as utf-8
-+** encoded text. The end of each child journal file is marked with a
-+** nul-terminator byte (0x00). i.e. the entire contents of a master journal
-+** file for a transaction involving two databases might be:
- **
--** * the new page size (value of *pPageSize) is valid (a power
--** of two between 512 and SQLITE_MAX_PAGE_SIZE, inclusive), and
-+** "/home/bill/a.db-journal\x00/home/bill/b.db-journal\x00"
- **
--** * there are no outstanding page references, and
-+** A master journal file may only be deleted once all of its child
-+** journals have been rolled back.
- **
--** * the database is either not an in-memory database or it is
--** an in-memory database that currently consists of zero pages.
-+** This function reads the contents of the master-journal file into
-+** memory and loops through each of the child journal names. For
-+** each child journal, it checks if:
- **
--** then the pager object page size is set to *pPageSize.
-+** * if the child journal exists, and if so
-+** * if the child journal contains a reference to master journal
-+** file zMaster
- **
--** If the page size is changed, then this function uses sqlite3PagerMalloc()
--** to obtain a new Pager.pTmpSpace buffer. If this allocation attempt
--** fails, SQLITE_NOMEM is returned and the page size remains unchanged.
--** In all other cases, SQLITE_OK is returned.
-+** If a child journal can be found that matches both of the criteria
-+** above, this function returns without doing anything. Otherwise, if
-+** no such child journal can be found, file zMaster is deleted from
-+** the file-system using sqlite3OsDelete().
- **
--** If the page size is not changed, either because one of the enumerated
--** conditions above is not true, the pager was in error state when this
--** function was called, or because the memory allocation attempt failed,
--** then *pPageSize is set to the old, retained page size before returning.
-+** If an IO error within this function, an error code is returned. This
-+** function allocates memory by calling sqlite3Malloc(). If an allocation
-+** fails, SQLITE_NOMEM is returned. Otherwise, if no IO or malloc errors
-+** occur, SQLITE_OK is returned.
-+**
-+** TODO: This function allocates a single block of memory to load
-+** the entire contents of the master journal file. This could be
-+** a couple of kilobytes or so - potentially larger than the page
-+** size.
- */
--SQLITE_PRIVATE int sqlite3PagerSetPagesize(Pager *pPager, u32 *pPageSize, int nReserve){
-- int rc = SQLITE_OK;
-+static int pager_delmaster(Pager *pPager, const char *zMaster){
-+ sqlite3_vfs *pVfs = pPager->pVfs;
-+ int rc; /* Return code */
-+ sqlite3_file *pMaster; /* Malloc'd master-journal file descriptor */
-+ sqlite3_file *pJournal; /* Malloc'd child-journal file descriptor */
-+ char *zMasterJournal = 0; /* Contents of master journal file */
-+ i64 nMasterJournal; /* Size of master journal file */
-+ char *zJournal; /* Pointer to one journal within MJ file */
-+ char *zMasterPtr; /* Space to hold MJ filename from a journal file */
-+ int nMasterPtr; /* Amount of space allocated to zMasterPtr[] */
-
-- /* It is not possible to do a full assert_pager_state() here, as this
-- ** function may be called from within PagerOpen(), before the state
-- ** of the Pager object is internally consistent.
-- **
-- ** At one point this function returned an error if the pager was in
-- ** PAGER_ERROR state. But since PAGER_ERROR state guarantees that
-- ** there is at least one outstanding page reference, this function
-- ** is a no-op for that case anyhow.
-+ /* Allocate space for both the pJournal and pMaster file descriptors.
-+ ** If successful, open the master journal file for reading.
- */
-+ pMaster = (sqlite3_file *)sqlite3MallocZero(pVfs->szOsFile * 2);
-+ pJournal = (sqlite3_file *)(((u8 *)pMaster) + pVfs->szOsFile);
-+ if( !pMaster ){
-+ rc = SQLITE_NOMEM;
-+ }else{
-+ const int flags = (SQLITE_OPEN_READONLY|SQLITE_OPEN_MASTER_JOURNAL);
-+ rc = sqlite3OsOpen(pVfs, zMaster, pMaster, flags, 0);
-+ }
-+ if( rc!=SQLITE_OK ) goto delmaster_out;
-
-- u32 pageSize = *pPageSize;
-- assert( pageSize==0 || (pageSize>=512 && pageSize<=SQLITE_MAX_PAGE_SIZE) );
-- if( (pPager->memDb==0 || pPager->dbSize==0)
-- && sqlite3PcacheRefCount(pPager->pPCache)==0
-- && pageSize && pageSize!=(u32)pPager->pageSize
-- ){
-- char *pNew = NULL; /* New temp space */
-- i64 nByte = 0;
-+ /* Load the entire master journal file into space obtained from
-+ ** sqlite3_malloc() and pointed to by zMasterJournal. Also obtain
-+ ** sufficient space (in zMasterPtr) to hold the names of master
-+ ** journal files extracted from regular rollback-journals.
-+ */
-+ rc = sqlite3OsFileSize(pMaster, &nMasterJournal);
-+ if( rc!=SQLITE_OK ) goto delmaster_out;
-+ nMasterPtr = pVfs->mxPathname+1;
-+ zMasterJournal = sqlite3Malloc((int)nMasterJournal + nMasterPtr + 1);
-+ if( !zMasterJournal ){
-+ rc = SQLITE_NOMEM;
-+ goto delmaster_out;
-+ }
-+ zMasterPtr = &zMasterJournal[nMasterJournal+1];
-+ rc = sqlite3OsRead(pMaster, zMasterJournal, (int)nMasterJournal, 0);
-+ if( rc!=SQLITE_OK ) goto delmaster_out;
-+ zMasterJournal[nMasterJournal] = 0;
-
-- if( pPager->eState>PAGER_OPEN && isOpen(pPager->fd) ){
-- rc = sqlite3OsFileSize(pPager->fd, &nByte);
-- }
-- if( rc==SQLITE_OK ){
-- pNew = (char *)sqlite3PageMalloc(pageSize);
-- if( !pNew ) rc = SQLITE_NOMEM;
-+ zJournal = zMasterJournal;
-+ while( (zJournal-zMasterJournal)<nMasterJournal ){
-+ int exists;
-+ rc = sqlite3OsAccess(pVfs, zJournal, SQLITE_ACCESS_EXISTS, &exists);
-+ if( rc!=SQLITE_OK ){
-+ goto delmaster_out;
- }
-+ if( exists ){
-+ /* One of the journals pointed to by the master journal exists.
-+ ** Open it and check if it points at the master journal. If
-+ ** so, return without deleting the master journal file.
-+ */
-+ int c;
-+ int flags = (SQLITE_OPEN_READONLY|SQLITE_OPEN_MAIN_JOURNAL);
-+ rc = sqlite3OsOpen(pVfs, zJournal, pJournal, flags, 0);
-+ if( rc!=SQLITE_OK ){
-+ goto delmaster_out;
-+ }
-
-- if( rc==SQLITE_OK ){
-- pager_reset(pPager);
-- pPager->dbSize = (Pgno)((nByte+pageSize-1)/pageSize);
-- pPager->pageSize = pageSize;
-- sqlite3PageFree(pPager->pTmpSpace);
-- pPager->pTmpSpace = pNew;
-- sqlite3PcacheSetPageSize(pPager->pPCache, pageSize);
-+ rc = readMasterJournal(pJournal, zMasterPtr, nMasterPtr);
-+ sqlite3OsClose(pJournal);
-+ if( rc!=SQLITE_OK ){
-+ goto delmaster_out;
-+ }
-+
-+ c = zMasterPtr[0]!=0 && strcmp(zMasterPtr, zMaster)==0;
-+ if( c ){
-+ /* We have a match. Do not delete the master journal file. */
-+ goto delmaster_out;
-+ }
- }
-+ zJournal += (sqlite3Strlen30(zJournal)+1);
- }
-+
-+ sqlite3OsClose(pMaster);
-+ rc = sqlite3OsDelete(pVfs, zMaster, 0);
-
-- *pPageSize = pPager->pageSize;
-- if( rc==SQLITE_OK ){
-- if( nReserve<0 ) nReserve = pPager->nReserve;
-- assert( nReserve>=0 && nReserve<1000 );
-- pPager->nReserve = (i16)nReserve;
-- pagerReportSize(pPager);
-- pagerFixMaplimit(pPager);
-+delmaster_out:
-+ sqlite3_free(zMasterJournal);
-+ if( pMaster ){
-+ sqlite3OsClose(pMaster);
-+ assert( !isOpen(pJournal) );
-+ sqlite3_free(pMaster);
- }
- return rc;
- }
-
--/*
--** Return a pointer to the "temporary page" buffer held internally
--** by the pager. This is a buffer that is big enough to hold the
--** entire content of a database page. This buffer is used internally
--** during rollback and will be overwritten whenever a rollback
--** occurs. But other modules are free to use it too, as long as
--** no rollbacks are happening.
--*/
--SQLITE_PRIVATE void *sqlite3PagerTempSpace(Pager *pPager){
-- return pPager->pTmpSpace;
--}
--
--/*
--** Attempt to set the maximum database page count if mxPage is positive.
--** Make no changes if mxPage is zero or negative. And never reduce the
--** maximum page count below the current size of the database.
--**
--** Regardless of mxPage, return the current maximum page count.
--*/
--SQLITE_PRIVATE int sqlite3PagerMaxPageCount(Pager *pPager, int mxPage){
-- if( mxPage>0 ){
-- pPager->mxPgno = mxPage;
-- }
-- assert( pPager->eState!=PAGER_OPEN ); /* Called only by OP_MaxPgcnt */
-- assert( pPager->mxPgno>=pPager->dbSize ); /* OP_MaxPgcnt enforces this */
-- return pPager->mxPgno;
--}
- /*
--** The following set of routines are used to disable the simulated
--** I/O error mechanism. These routines are used to avoid simulated
--** errors in places where we do not care about errors.
-+** This function is used to change the actual size of the database
-+** file in the file-system. This only happens when committing a transaction,
-+** or rolling back a transaction (including rolling back a hot-journal).
- **
--** Unless -DSQLITE_TEST=1 is used, these routines are all no-ops
--** and generate no code.
--*/
--#ifdef SQLITE_TEST
--SQLITE_API extern int sqlite3_io_error_pending;
--SQLITE_API extern int sqlite3_io_error_hit;
--static int saved_cnt;
--void disable_simulated_io_errors(void){
-- saved_cnt = sqlite3_io_error_pending;
-- sqlite3_io_error_pending = -1;
--}
--void enable_simulated_io_errors(void){
-- sqlite3_io_error_pending = saved_cnt;
--}
--#else
--# define disable_simulated_io_errors()
--# define enable_simulated_io_errors()
--#endif
--
--/*
--** Read the first N bytes from the beginning of the file into memory
--** that pDest points to.
-+** If the main database file is not open, or the pager is not in either
-+** DBMOD or OPEN state, this function is a no-op. Otherwise, the size
-+** of the file is changed to nPage pages (nPage*pPager->pageSize bytes).
-+** If the file on disk is currently larger than nPage pages, then use the VFS
-+** xTruncate() method to truncate it.
- **
--** If the pager was opened on a transient file (zFilename==""), or
--** opened on a file less than N bytes in size, the output buffer is
--** zeroed and SQLITE_OK returned. The rationale for this is that this
--** function is used to read database headers, and a new transient or
--** zero sized database has a header than consists entirely of zeroes.
-+** Or, it might might be the case that the file on disk is smaller than
-+** nPage pages. Some operating system implementations can get confused if
-+** you try to truncate a file to some size that is larger than it
-+** currently is, so detect this case and write a single zero byte to
-+** the end of the new file instead.
- **
--** If any IO error apart from SQLITE_IOERR_SHORT_READ is encountered,
--** the error code is returned to the caller and the contents of the
--** output buffer undefined.
-+** If successful, return SQLITE_OK. If an IO error occurs while modifying
-+** the database file, return the error code to the caller.
- */
--SQLITE_PRIVATE int sqlite3PagerReadFileheader(Pager *pPager, int N, unsigned char *pDest){
-+static int pager_truncate(Pager *pPager, Pgno nPage){
- int rc = SQLITE_OK;
-- memset(pDest, 0, N);
-- assert( isOpen(pPager->fd) || pPager->tempFile );
--
-- /* This routine is only called by btree immediately after creating
-- ** the Pager object. There has not been an opportunity to transition
-- ** to WAL mode yet.
-- */
-- assert( !pagerUseWal(pPager) );
--
-- if( isOpen(pPager->fd) ){
-- IOTRACE(("DBHDR %p 0 %d\n", pPager, N))
-- rc = sqlite3OsRead(pPager->fd, pDest, N, 0);
-- if( rc==SQLITE_IOERR_SHORT_READ ){
-- rc = SQLITE_OK;
-+ assert( pPager->eState!=PAGER_ERROR );
-+ assert( pPager->eState!=PAGER_READER );
-+
-+ if( isOpen(pPager->fd)
-+ && (pPager->eState>=PAGER_WRITER_DBMOD || pPager->eState==PAGER_OPEN)
-+ ){
-+ i64 currentSize, newSize;
-+ int szPage = pPager->pageSize;
-+ assert( pPager->eLock==EXCLUSIVE_LOCK );
-+ /* TODO: Is it safe to use Pager.dbFileSize here? */
-+ rc = sqlite3OsFileSize(pPager->fd, ¤tSize);
-+ newSize = szPage*(i64)nPage;
-+ if( rc==SQLITE_OK && currentSize!=newSize ){
-+ if( currentSize>newSize ){
-+ rc = sqlite3OsTruncate(pPager->fd, newSize);
-+ }else if( (currentSize+szPage)<=newSize ){
-+ char *pTmp = pPager->pTmpSpace;
-+ memset(pTmp, 0, szPage);
-+ testcase( (newSize-szPage) == currentSize );
-+ testcase( (newSize-szPage) > currentSize );
-+ rc = sqlite3OsWrite(pPager->fd, pTmp, szPage, newSize-szPage);
-+ }
-+ if( rc==SQLITE_OK ){
-+ pPager->dbFileSize = nPage;
-+ }
- }
- }
- return rc;
+@@ -45519,7 +48898,39 @@
}
-
- /*
--** This function may only be called when a read-transaction is open on
--** the pager. It returns the total number of pages in the database.
--**
--** However, if the file is between 1 and <page-size> bytes in size, then
--** this is considered a 1 page file.
-+** Return a sanitized version of the sector-size of OS file pFile. The
-+** return value is guaranteed to lie between 32 and MAX_SECTOR_SIZE.
- */
--SQLITE_PRIVATE void sqlite3PagerPagecount(Pager *pPager, int *pnPage){
-- assert( pPager->eState>=PAGER_READER );
-- assert( pPager->eState!=PAGER_WRITER_FINISHED );
-- *pnPage = (int)pPager->dbSize;
-+SQLITE_PRIVATE int sqlite3SectorSize(sqlite3_file *pFile){
-+ int iRet = sqlite3OsSectorSize(pFile);
-+ if( iRet<32 ){
-+ iRet = 512;
-+ }else if( iRet>MAX_SECTOR_SIZE ){
-+ assert( MAX_SECTOR_SIZE>=512 );
-+ iRet = MAX_SECTOR_SIZE;
-+ }
-+ return iRet;
- }
-
--
- /*
--** Try to obtain a lock of type locktype on the database file. If
--** a similar or greater lock is already held, this function is a no-op
--** (returning SQLITE_OK immediately).
-+** Set the value of the Pager.sectorSize variable for the given
-+** pager based on the value returned by the xSectorSize method
-+** of the open database file. The sector size will be used used
-+** to determine the size and alignment of journal header and
-+** master journal pointers within created journal files.
- **
--** Otherwise, attempt to obtain the lock using sqlite3OsLock(). Invoke
--** the busy callback if the lock is currently not available. Repeat
--** until the busy callback returns false or until the attempt to
--** obtain the lock succeeds.
-+** For temporary files the effective sector size is always 512 bytes.
- **
--** Return SQLITE_OK on success and an error code if we cannot obtain
--** the lock. If the lock is obtained successfully, set the Pager.state
--** variable to locktype before returning.
-+** Otherwise, for non-temporary files, the effective sector size is
-+** the value returned by the xSectorSize() method rounded up to 32 if
-+** it is less than 32, or rounded down to MAX_SECTOR_SIZE if it
-+** is greater than MAX_SECTOR_SIZE.
-+**
-+** If the file has the SQLITE_IOCAP_POWERSAFE_OVERWRITE property, then set
-+** the effective sector size to its minimum value (512). The purpose of
-+** pPager->sectorSize is to define the "blast radius" of bytes that
-+** might change if a crash occurs while writing to a single byte in
-+** that range. But with POWERSAFE_OVERWRITE, the blast radius is zero
-+** (that is what POWERSAFE_OVERWRITE means), so we minimize the sector
-+** size. For backwards compatibility of the rollback journal file format,
-+** we cannot reduce the effective sector size below 512.
- */
--static int pager_wait_on_lock(Pager *pPager, int locktype){
-- int rc; /* Return code */
--
-- /* Check that this is either a no-op (because the requested lock is
-- ** already held, or one of the transistions that the busy-handler
-- ** may be invoked during, according to the comment above
-- ** sqlite3PagerSetBusyhandler().
-- */
-- assert( (pPager->eLock>=locktype)
-- || (pPager->eLock==NO_LOCK && locktype==SHARED_LOCK)
-- || (pPager->eLock==RESERVED_LOCK && locktype==EXCLUSIVE_LOCK)
-- );
-+static void setSectorSize(Pager *pPager){
-+ assert( isOpen(pPager->fd) || pPager->tempFile );
-
-- do {
-- rc = pagerLockDb(pPager, locktype);
-- }while( rc==SQLITE_BUSY && pPager->xBusyHandler(pPager->pBusyHandlerArg) );
-- return rc;
-+ if( pPager->tempFile
-+ || (sqlite3OsDeviceCharacteristics(pPager->fd) &
-+ SQLITE_IOCAP_POWERSAFE_OVERWRITE)!=0
-+ ){
-+ /* Sector size doesn't matter for temporary files. Also, the file
-+ ** may not have been opened yet, in which case the OsSectorSize()
-+ ** call will segfault. */
-+ pPager->sectorSize = 512;
-+ }else{
-+ pPager->sectorSize = sqlite3SectorSize(pPager->fd);
-+ }
- }
-
- /*
--** Function assertTruncateConstraint(pPager) checks that one of the
--** following is true for all dirty pages currently in the page-cache:
-+** Playback the journal and thus restore the database file to
-+** the state it was in before we started making changes.
- **
--** a) The page number is less than or equal to the size of the
--** current database image, in pages, OR
-+** The journal file format is as follows:
- **
--** b) if the page content were written at this time, it would not
--** be necessary to write the current content out to the sub-journal
--** (as determined by function subjRequiresPage()).
-+** (1) 8 byte prefix. A copy of aJournalMagic[].
-+** (2) 4 byte big-endian integer which is the number of valid page records
-+** in the journal. If this value is 0xffffffff, then compute the
-+** number of page records from the journal size.
-+** (3) 4 byte big-endian integer which is the initial value for the
-+** sanity checksum.
-+** (4) 4 byte integer which is the number of pages to truncate the
-+** database to during a rollback.
-+** (5) 4 byte big-endian integer which is the sector size. The header
-+** is this many bytes in size.
-+** (6) 4 byte big-endian integer which is the page size.
-+** (7) zero padding out to the next sector size.
-+** (8) Zero or more pages instances, each as follows:
-+** + 4 byte page number.
-+** + pPager->pageSize bytes of data.
-+** + 4 byte checksum
- **
--** If the condition asserted by this function were not true, and the
--** dirty page were to be discarded from the cache via the pagerStress()
--** routine, pagerStress() would not write the current page content to
--** the database file. If a savepoint transaction were rolled back after
--** this happened, the correct behavior would be to restore the current
--** content of the page. However, since this content is not present in either
--** the database file or the portion of the rollback journal and
--** sub-journal rolled back the content could not be restored and the
--** database image would become corrupt. It is therefore fortunate that
--** this circumstance cannot arise.
--*/
--#if defined(SQLITE_DEBUG)
--static void assertTruncateConstraintCb(PgHdr *pPg){
-- assert( pPg->flags&PGHDR_DIRTY );
-- assert( !subjRequiresPage(pPg) || pPg->pgno<=pPg->pPager->dbSize );
--}
--static void assertTruncateConstraint(Pager *pPager){
-- sqlite3PcacheIterateDirty(pPager->pPCache, assertTruncateConstraintCb);
--}
--#else
--# define assertTruncateConstraint(pPager)
--#endif
--
--/*
--** Truncate the in-memory database file image to nPage pages. This
--** function does not actually modify the database file on disk. It
--** just sets the internal state of the pager object so that the
--** truncation will be done when the current transaction is committed.
-+** When we speak of the journal header, we mean the first 7 items above.
-+** Each entry in the journal is an instance of the 8th item.
- **
--** This function is only called right before committing a transaction.
--** Once this function has been called, the transaction must either be
--** rolled back or committed. It is not safe to call this function and
--** then continue writing to the database.
--*/
--SQLITE_PRIVATE void sqlite3PagerTruncateImage(Pager *pPager, Pgno nPage){
-- assert( pPager->dbSize>=nPage );
-- assert( pPager->eState>=PAGER_WRITER_CACHEMOD );
-- pPager->dbSize = nPage;
--
-- /* At one point the code here called assertTruncateConstraint() to
-- ** ensure that all pages being truncated away by this operation are,
-- ** if one or more savepoints are open, present in the savepoint
-- ** journal so that they can be restored if the savepoint is rolled
-- ** back. This is no longer necessary as this function is now only
-- ** called right before committing a transaction. So although the
-- ** Pager object may still have open savepoints (Pager.nSavepoint!=0),
-- ** they cannot be rolled back. So the assertTruncateConstraint() call
-- ** is no longer correct. */
--}
--
--
--/*
--** This function is called before attempting a hot-journal rollback. It
--** syncs the journal file to disk, then sets pPager->journalHdr to the
--** size of the journal file so that the pager_playback() routine knows
--** that the entire journal file has been synced.
-+** Call the value from the second bullet "nRec". nRec is the number of
-+** valid page entries in the journal. In most cases, you can compute the
-+** value of nRec from the size of the journal file. But if a power
-+** failure occurred while the journal was being written, it could be the
-+** case that the size of the journal file had already been increased but
-+** the extra entries had not yet made it safely to disk. In such a case,
-+** the value of nRec computed from the file size would be too large. For
-+** that reason, we always use the nRec value in the header.
- **
--** Syncing a hot-journal to disk before attempting to roll it back ensures
--** that if a power-failure occurs during the rollback, the process that
--** attempts rollback following system recovery sees the same journal
--** content as this process.
-+** If the nRec value is 0xffffffff it means that nRec should be computed
-+** from the file size. This value is used when the user selects the
-+** no-sync option for the journal. A power failure could lead to corruption
-+** in this case. But for things like temporary table (which will be
-+** deleted when the power is restored) we don't care.
- **
--** If everything goes as planned, SQLITE_OK is returned. Otherwise,
--** an SQLite error code.
-+** If the file opened as the journal file is not a well-formed
-+** journal file then all pages up to the first corrupted page are rolled
-+** back (or no pages if the journal header is corrupted). The journal file
-+** is then deleted and SQLITE_OK returned, just as if no corruption had
-+** been encountered.
-+**
-+** If an I/O or malloc() error occurs, the journal-file is not deleted
-+** and an error code is returned.
-+**
-+** The isHot parameter indicates that we are trying to rollback a journal
-+** that might be a hot journal. Or, it could be that the journal is
-+** preserved because of JOURNALMODE_PERSIST or JOURNALMODE_TRUNCATE.
-+** If the journal really is hot, reset the pager cache prior rolling
-+** back any content. If the journal is merely persistent, no reset is
-+** needed.
- */
--static int pagerSyncHotJournal(Pager *pPager){
-- int rc = SQLITE_OK;
-- if( !pPager->noSync ){
-- rc = sqlite3OsSync(pPager->jfd, SQLITE_SYNC_NORMAL);
-+static int pager_playback(Pager *pPager, int isHot){
-+ sqlite3_vfs *pVfs = pPager->pVfs;
-+ i64 szJ; /* Size of the journal file in bytes */
-+ u32 nRec; /* Number of Records in the journal */
-+ u32 u; /* Unsigned loop counter */
-+ Pgno mxPg = 0; /* Size of the original file in pages */
-+ int rc; /* Result code of a subroutine */
-+ int res = 1; /* Value returned by sqlite3OsAccess() */
-+ char *zMaster = 0; /* Name of master journal file if any */
-+ int needPagerReset; /* True to reset page prior to first page rollback */
-+ int nPlayback = 0; /* Total number of pages restored from journal */
-+
-+ /* Figure out how many records are in the journal. Abort early if
-+ ** the journal is empty.
-+ */
-+ assert( isOpen(pPager->jfd) );
-+ rc = sqlite3OsFileSize(pPager->jfd, &szJ);
-+ if( rc!=SQLITE_OK ){
-+ goto end_playback;
- }
-- if( rc==SQLITE_OK ){
-- rc = sqlite3OsFileSize(pPager->jfd, &pPager->journalHdr);
-+
-+ /* Read the master journal name from the journal, if it is present.
-+ ** If a master journal file name is specified, but the file is not
-+ ** present on disk, then the journal is not hot and does not need to be
-+ ** played back.
-+ **
-+ ** TODO: Technically the following is an error because it assumes that
-+ ** buffer Pager.pTmpSpace is (mxPathname+1) bytes or larger. i.e. that
-+ ** (pPager->pageSize >= pPager->pVfs->mxPathname+1). Using os_unix.c,
-+ ** mxPathname is 512, which is the same as the minimum allowable value
-+ ** for pageSize.
-+ */
-+ zMaster = pPager->pTmpSpace;
-+ rc = readMasterJournal(pPager->jfd, zMaster, pPager->pVfs->mxPathname+1);
-+ if( rc==SQLITE_OK && zMaster[0] ){
-+ rc = sqlite3OsAccess(pVfs, zMaster, SQLITE_ACCESS_EXISTS, &res);
- }
-- return rc;
--}
-+ zMaster = 0;
-+ if( rc!=SQLITE_OK || !res ){
-+ goto end_playback;
-+ }
-+ pPager->journalOff = 0;
-+ needPagerReset = isHot;
-
--/*
--** Obtain a reference to a memory mapped page object for page number pgno.
--** The new object will use the pointer pData, obtained from xFetch().
--** If successful, set *ppPage to point to the new page reference
--** and return SQLITE_OK. Otherwise, return an SQLite error code and set
--** *ppPage to zero.
--**
--** Page references obtained by calling this function should be released
--** by calling pagerReleaseMapPage().
--*/
--static int pagerAcquireMapPage(
-- Pager *pPager, /* Pager object */
-- Pgno pgno, /* Page number */
-- void *pData, /* xFetch()'d data for this page */
-- PgHdr **ppPage /* OUT: Acquired page object */
--){
-- PgHdr *p; /* Memory mapped page to return */
-+ /* This loop terminates either when a readJournalHdr() or
-+ ** pager_playback_one_page() call returns SQLITE_DONE or an IO error
-+ ** occurs.
-+ */
-+ while( 1 ){
-+ /* Read the next journal header from the journal file. If there are
-+ ** not enough bytes left in the journal file for a complete header, or
-+ ** it is corrupted, then a process must have failed while writing it.
-+ ** This indicates nothing more needs to be rolled back.
-+ */
-+ rc = readJournalHdr(pPager, isHot, szJ, &nRec, &mxPg);
-+ if( rc!=SQLITE_OK ){
-+ if( rc==SQLITE_DONE ){
-+ rc = SQLITE_OK;
-+ }
-+ goto end_playback;
-+ }
-
-- if( pPager->pMmapFreelist ){
-- *ppPage = p = pPager->pMmapFreelist;
-- pPager->pMmapFreelist = p->pDirty;
-- p->pDirty = 0;
-- memset(p->pExtra, 0, pPager->nExtra);
-- }else{
-- *ppPage = p = (PgHdr *)sqlite3MallocZero(sizeof(PgHdr) + pPager->nExtra);
-- if( p==0 ){
-- sqlite3OsUnfetch(pPager->fd, (i64)(pgno-1) * pPager->pageSize, pData);
-- return SQLITE_NOMEM;
-+ /* If nRec is 0xffffffff, then this journal was created by a process
-+ ** working in no-sync mode. This means that the rest of the journal
-+ ** file consists of pages, there are no more journal headers. Compute
-+ ** the value of nRec based on this assumption.
-+ */
-+ if( nRec==0xffffffff ){
-+ assert( pPager->journalOff==JOURNAL_HDR_SZ(pPager) );
-+ nRec = (int)((szJ - JOURNAL_HDR_SZ(pPager))/JOURNAL_PG_SZ(pPager));
- }
-- p->pExtra = (void *)&p[1];
-- p->flags = PGHDR_MMAP;
-- p->nRef = 1;
-- p->pPager = pPager;
-- }
-
-- assert( p->pExtra==(void *)&p[1] );
-- assert( p->pPage==0 );
-- assert( p->flags==PGHDR_MMAP );
-- assert( p->pPager==pPager );
-- assert( p->nRef==1 );
-+ /* If nRec is 0 and this rollback is of a transaction created by this
-+ ** process and if this is the final header in the journal, then it means
-+ ** that this part of the journal was being filled but has not yet been
-+ ** synced to disk. Compute the number of pages based on the remaining
-+ ** size of the file.
-+ **
-+ ** The third term of the test was added to fix ticket #2565.
-+ ** When rolling back a hot journal, nRec==0 always means that the next
-+ ** chunk of the journal contains zero pages to be rolled back. But
-+ ** when doing a ROLLBACK and the nRec==0 chunk is the last chunk in
-+ ** the journal, it means that the journal might contain additional
-+ ** pages that need to be rolled back and that the number of pages
-+ ** should be computed based on the journal file size.
-+ */
-+ if( nRec==0 && !isHot &&
-+ pPager->journalHdr+JOURNAL_HDR_SZ(pPager)==pPager->journalOff ){
-+ nRec = (int)((szJ - pPager->journalOff) / JOURNAL_PG_SZ(pPager));
-+ }
-
-- p->pgno = pgno;
-- p->pData = pData;
-- pPager->nMmapOut++;
-+ /* If this is the first header read from the journal, truncate the
-+ ** database file back to its original size.
-+ */
-+ if( pPager->journalOff==JOURNAL_HDR_SZ(pPager) ){
-+ rc = pager_truncate(pPager, mxPg);
-+ if( rc!=SQLITE_OK ){
-+ goto end_playback;
-+ }
-+ pPager->dbSize = mxPg;
-+ }
-
-- return SQLITE_OK;
--}
-+ /* Copy original pages out of the journal and back into the
-+ ** database file and/or page cache.
-+ */
-+ for(u=0; u<nRec; u++){
-+ if( needPagerReset ){
-+ pager_reset(pPager);
-+ needPagerReset = 0;
-+ }
-+ rc = pager_playback_one_page(pPager,&pPager->journalOff,0,1,0);
-+ if( rc==SQLITE_OK ){
-+ nPlayback++;
-+ }else{
-+ if( rc==SQLITE_DONE ){
-+ pPager->journalOff = szJ;
-+ break;
-+ }else if( rc==SQLITE_IOERR_SHORT_READ ){
-+ /* If the journal has been truncated, simply stop reading and
-+ ** processing the journal. This might happen if the journal was
-+ ** not completely written and synced prior to a crash. In that
-+ ** case, the database should have never been written in the
-+ ** first place so it is OK to simply abandon the rollback. */
-+ rc = SQLITE_OK;
-+ goto end_playback;
-+ }else{
-+ /* If we are unable to rollback, quit and return the error
-+ ** code. This will cause the pager to enter the error state
-+ ** so that no further harm will be done. Perhaps the next
-+ ** process to come along will be able to rollback the database.
-+ */
-+ goto end_playback;
-+ }
-+ }
-+ }
-+ }
-+ /*NOTREACHED*/
-+ assert( 0 );
-
--/*
--** Release a reference to page pPg. pPg must have been returned by an
--** earlier call to pagerAcquireMapPage().
--*/
--static void pagerReleaseMapPage(PgHdr *pPg){
-- Pager *pPager = pPg->pPager;
-- pPager->nMmapOut--;
-- pPg->pDirty = pPager->pMmapFreelist;
-- pPager->pMmapFreelist = pPg;
-+end_playback:
-+ /* Following a rollback, the database file should be back in its original
-+ ** state prior to the start of the transaction, so invoke the
-+ ** SQLITE_FCNTL_DB_UNCHANGED file-control method to disable the
-+ ** assertion that the transaction counter was modified.
-+ */
-+#ifdef SQLITE_DEBUG
-+ if( pPager->fd->pMethods ){
-+ sqlite3OsFileControlHint(pPager->fd,SQLITE_FCNTL_DB_UNCHANGED,0);
-+ }
-+#endif
-
-- assert( pPager->fd->pMethods->iVersion>=3 );
-- sqlite3OsUnfetch(pPager->fd, (i64)(pPg->pgno-1)*pPager->pageSize, pPg->pData);
--}
-+ /* If this playback is happening automatically as a result of an IO or
-+ ** malloc error that occurred after the change-counter was updated but
-+ ** before the transaction was committed, then the change-counter
-+ ** modification may just have been reverted. If this happens in exclusive
-+ ** mode, then subsequent transactions performed by the connection will not
-+ ** update the change-counter at all. This may lead to cache inconsistency
-+ ** problems for other processes at some point in the future. So, just
-+ ** in case this has happened, clear the changeCountDone flag now.
-+ */
-+ pPager->changeCountDone = pPager->tempFile;
-
--/*
--** Free all PgHdr objects stored in the Pager.pMmapFreelist list.
--*/
--static void pagerFreeMapHdrs(Pager *pPager){
-- PgHdr *p;
-- PgHdr *pNext;
-- for(p=pPager->pMmapFreelist; p; p=pNext){
-- pNext = p->pDirty;
-- sqlite3_free(p);
-+ if( rc==SQLITE_OK ){
-+ zMaster = pPager->pTmpSpace;
-+ rc = readMasterJournal(pPager->jfd, zMaster, pPager->pVfs->mxPathname+1);
-+ testcase( rc!=SQLITE_OK );
-+ }
-+ if( rc==SQLITE_OK
-+ && (pPager->eState>=PAGER_WRITER_DBMOD || pPager->eState==PAGER_OPEN)
-+ ){
-+ rc = sqlite3PagerSync(pPager);
-+ }
-+ if( rc==SQLITE_OK ){
-+ rc = pager_end_transaction(pPager, zMaster[0]!='\0', 0);
-+ testcase( rc!=SQLITE_OK );
-+ }
-+ if( rc==SQLITE_OK && zMaster[0] && res ){
-+ /* If there was a master journal and this routine will return success,
-+ ** see if it is possible to delete the master journal.
-+ */
-+ rc = pager_delmaster(pPager, zMaster);
-+ testcase( rc!=SQLITE_OK );
- }
-+ if( isHot && nPlayback ){
-+ sqlite3_log(SQLITE_NOTICE_RECOVER_ROLLBACK, "recovered %d pages from %s",
-+ nPlayback, pPager->zJournal);
-+ }
-+
-+ /* The Pager.sectorSize variable may have been updated while rolling
-+ ** back a journal created by a process with a different sector size
-+ ** value. Reset it to the correct value for this process.
-+ */
-+ setSectorSize(pPager);
-+ return rc;
- }
-
-
- /*
--** Shutdown the page cache. Free all memory and close all files.
-+** Read the content for page pPg out of the database file and into
-+** pPg->pData. A shared lock or greater must be held on the database
-+** file before this function is called.
- **
--** If a transaction was in progress when this routine is called, that
--** transaction is rolled back. All outstanding pages are invalidated
--** and their memory is freed. Any attempt to use a page associated
--** with this page cache after this function returns will likely
--** result in a coredump.
-+** If page 1 is read, then the value of Pager.dbFileVers[] is set to
-+** the value read from the database file.
- **
--** This function always succeeds. If a transaction is active an attempt
--** is made to roll it back. If an error occurs during the rollback
--** a hot journal may be left in the filesystem but no error is returned
--** to the caller.
-+** If an IO error occurs, then the IO error is returned to the caller.
-+** Otherwise, SQLITE_OK is returned.
- */
--SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager){
-- u8 *pTmp = (u8 *)pPager->pTmpSpace;
-+static int readDbPage(PgHdr *pPg, u32 iFrame){
-+ Pager *pPager = pPg->pPager; /* Pager object associated with page pPg */
-+ Pgno pgno = pPg->pgno; /* Page number to read */
-+ int rc = SQLITE_OK; /* Return code */
-+ int pgsz = pPager->pageSize; /* Number of bytes to read */
-+
-+ assert( pPager->eState>=PAGER_READER && !MEMDB );
-+ assert( isOpen(pPager->fd) );
-+
-+ if( NEVER(!isOpen(pPager->fd)) ){
-+ assert( pPager->tempFile );
-+ memset(pPg->pData, 0, pPager->pageSize);
-+ return SQLITE_OK;
-+ }
-
-- assert( assert_pager_state(pPager) );
-- disable_simulated_io_errors();
-- sqlite3BeginBenignMalloc();
-- pagerFreeMapHdrs(pPager);
-- /* pPager->errCode = 0; */
-- pPager->exclusiveMode = 0;
- #ifndef SQLITE_OMIT_WAL
-- sqlite3WalClose(pPager->pWal, pPager->ckptSyncFlags, pPager->pageSize, pTmp);
-- pPager->pWal = 0;
-+ if( iFrame ){
-+ /* Try to pull the page from the write-ahead log. */
-+ rc = sqlite3WalReadFrame(pPager->pWal, iFrame, pgsz, pPg->pData);
-+ }else
#endif
-- pager_reset(pPager);
-- if( MEMDB ){
-- pager_unlock(pPager);
-- }else{
-- /* If it is open, sync the journal file before calling UnlockAndRollback.
-- ** If this is not done, then an unsynced portion of the open journal
-- ** file may be played back into the database. If a power failure occurs
-- ** while this is happening, the database could become corrupt.
-- **
-- ** If an error occurs while trying to sync the journal, shift the pager
-- ** into the ERROR state. This causes UnlockAndRollback to unlock the
-- ** database and close the journal file without attempting to roll it
-- ** back or finalize it. The next database user will have to do hot-journal
-- ** rollback before accessing the database file.
-- */
-- if( isOpen(pPager->jfd) ){
-- pager_error(pPager, pagerSyncHotJournal(pPager));
-+ {
-+ i64 iOffset = (pgno-1)*(i64)pPager->pageSize;
-+ rc = sqlite3OsRead(pPager->fd, pPg->pData, pgsz, iOffset);
-+ if( rc==SQLITE_IOERR_SHORT_READ ){
-+ rc = SQLITE_OK;
- }
-- pagerUnlockAndRollback(pPager);
- }
-- sqlite3EndBenignMalloc();
-- enable_simulated_io_errors();
-- PAGERTRACE(("CLOSE %d\n", PAGERID(pPager)));
-- IOTRACE(("CLOSE %p\n", pPager))
-- sqlite3OsClose(pPager->jfd);
-- sqlite3OsClose(pPager->fd);
-- sqlite3PageFree(pTmp);
-- sqlite3PcacheClose(pPager->pPCache);
-
--#ifdef SQLITE_HAS_CODEC
-- if( pPager->xCodecFree ) pPager->xCodecFree(pPager->pCodec);
--#endif
-+ if( pgno==1 ){
-+ if( rc ){
-+ /* If the read is unsuccessful, set the dbFileVers[] to something
-+ ** that will never be a valid file version. dbFileVers[] is a copy
-+ ** of bytes 24..39 of the database. Bytes 28..31 should always be
-+ ** zero or the size of the database in page. Bytes 32..35 and 35..39
-+ ** should be page numbers which are never 0xffffffff. So filling
-+ ** pPager->dbFileVers[] with all 0xff bytes should suffice.
-+ **
-+ ** For an encrypted database, the situation is more complex: bytes
-+ ** 24..39 of the database are white noise. But the probability of
-+ ** white noising equaling 16 bytes of 0xff is vanishingly small so
-+ ** we should still be ok.
-+ */
-+ memset(pPager->dbFileVers, 0xff, sizeof(pPager->dbFileVers));
-+ }else{
-+ u8 *dbFileVers = &((u8*)pPg->pData)[24];
-+ memcpy(&pPager->dbFileVers, dbFileVers, sizeof(pPager->dbFileVers));
-+ }
-+ }
-+ CODEC1(pPager, pPg->pData, pgno, 3, rc = SQLITE_NOMEM);
-
-- assert( !pPager->aSavepoint && !pPager->pInJournal );
-- assert( !isOpen(pPager->jfd) && !isOpen(pPager->sjfd) );
-+ PAGER_INCR(sqlite3_pager_readdb_count);
-+ PAGER_INCR(pPager->nRead);
-+ IOTRACE(("PGIN %p %d\n", pPager, pgno));
-+ PAGERTRACE(("FETCH %d page %d hash(%08x)\n",
-+ PAGERID(pPager), pgno, pager_pagehash(pPg)));
-
-- sqlite3_free(pPager);
-- return SQLITE_OK;
-+ return rc;
- }
-
--#if !defined(NDEBUG) || defined(SQLITE_TEST)
- /*
--** Return the page number for page pPg.
-+** Update the value of the change-counter at offsets 24 and 92 in
-+** the header and the sqlite version number at offset 96.
-+**
-+** This is an unconditional update. See also the pager_incr_changecounter()
-+** routine which only updates the change-counter if the update is actually
-+** needed, as determined by the pPager->changeCountDone state variable.
- */
--SQLITE_PRIVATE Pgno sqlite3PagerPagenumber(DbPage *pPg){
-- return pPg->pgno;
--}
--#endif
-+static void pager_write_changecounter(PgHdr *pPg){
-+ u32 change_counter;
-
--/*
--** Increment the reference count for page pPg.
--*/
--SQLITE_PRIVATE void sqlite3PagerRef(DbPage *pPg){
-- sqlite3PcacheRef(pPg);
-+ /* Increment the value just read and write it back to byte 24. */
-+ change_counter = sqlite3Get4byte((u8*)pPg->pPager->dbFileVers)+1;
-+ put32bits(((char*)pPg->pData)+24, change_counter);
-+
-+ /* Also store the SQLite version number in bytes 96..99 and in
-+ ** bytes 92..95 store the change counter for which the version number
-+ ** is valid. */
-+ put32bits(((char*)pPg->pData)+92, change_counter);
-+ put32bits(((char*)pPg->pData)+96, SQLITE_VERSION_NUMBER);
- }
-
-+#ifndef SQLITE_OMIT_WAL
- /*
--** Sync the journal. In other words, make sure all the pages that have
--** been written to the journal have actually reached the surface of the
--** disk and can be restored in the event of a hot-journal rollback.
--**
--** If the Pager.noSync flag is set, then this function is a no-op.
--** Otherwise, the actions required depend on the journal-mode and the
--** device characteristics of the file-system, as follows:
--**
--** * If the journal file is an in-memory journal file, no action need
--** be taken.
--**
--** * Otherwise, if the device does not support the SAFE_APPEND property,
--** then the nRec field of the most recently written journal header
--** is updated to contain the number of journal records that have
--** been written following it. If the pager is operating in full-sync
--** mode, then the journal file is synced before this field is updated.
--**
--** * If the device does not support the SEQUENTIAL property, then
--** journal file is synced.
--**
--** Or, in pseudo-code:
--**
--** if( NOT <in-memory journal> ){
--** if( NOT SAFE_APPEND ){
--** if( <full-sync mode> ) xSync(<journal file>);
--** <update nRec field>
--** }
--** if( NOT SEQUENTIAL ) xSync(<journal file>);
--** }
-+** This function is invoked once for each page that has already been
-+** written into the log file when a WAL transaction is rolled back.
-+** Parameter iPg is the page number of said page. The pCtx argument
-+** is actually a pointer to the Pager structure.
- **
--** If successful, this routine clears the PGHDR_NEED_SYNC flag of every
--** page currently held in memory before returning SQLITE_OK. If an IO
--** error is encountered, then the IO error code is returned to the caller.
-+** If page iPg is present in the cache, and has no outstanding references,
-+** it is discarded. Otherwise, if there are one or more outstanding
-+** references, the page content is reloaded from the database. If the
-+** attempt to reload content from the database is required and fails,
-+** return an SQLite error code. Otherwise, SQLITE_OK.
- */
--static int syncJournal(Pager *pPager, int newHdr){
-- int rc; /* Return code */
--
-- assert( pPager->eState==PAGER_WRITER_CACHEMOD
-- || pPager->eState==PAGER_WRITER_DBMOD
-- );
-- assert( assert_pager_state(pPager) );
-- assert( !pagerUseWal(pPager) );
--
-- rc = sqlite3PagerExclusiveLock(pPager);
-- if( rc!=SQLITE_OK ) return rc;
--
-- if( !pPager->noSync ){
-- assert( !pPager->tempFile );
-- if( isOpen(pPager->jfd) && pPager->journalMode!=PAGER_JOURNALMODE_MEMORY ){
-- const int iDc = sqlite3OsDeviceCharacteristics(pPager->fd);
-- assert( isOpen(pPager->jfd) );
--
-- if( 0==(iDc&SQLITE_IOCAP_SAFE_APPEND) ){
-- /* This block deals with an obscure problem. If the last connection
-- ** that wrote to this database was operating in persistent-journal
-- ** mode, then the journal file may at this point actually be larger
-- ** than Pager.journalOff bytes. If the next thing in the journal
-- ** file happens to be a journal-header (written as part of the
-- ** previous connection's transaction), and a crash or power-failure
-- ** occurs after nRec is updated but before this connection writes
-- ** anything else to the journal file (or commits/rolls back its
-- ** transaction), then SQLite may become confused when doing the
-- ** hot-journal rollback following recovery. It may roll back all
-- ** of this connections data, then proceed to rolling back the old,
-- ** out-of-date data that follows it. Database corruption.
-- **
-- ** To work around this, if the journal file does appear to contain
-- ** a valid header following Pager.journalOff, then write a 0x00
-- ** byte to the start of it to prevent it from being recognized.
-- **
-- ** Variable iNextHdrOffset is set to the offset at which this
-- ** problematic header will occur, if it exists. aMagic is used
-- ** as a temporary buffer to inspect the first couple of bytes of
-- ** the potential journal header.
-- */
-- i64 iNextHdrOffset;
-- u8 aMagic[8];
-- u8 zHeader[sizeof(aJournalMagic)+4];
--
-- memcpy(zHeader, aJournalMagic, sizeof(aJournalMagic));
-- put32bits(&zHeader[sizeof(aJournalMagic)], pPager->nRec);
--
-- iNextHdrOffset = journalHdrOffset(pPager);
-- rc = sqlite3OsRead(pPager->jfd, aMagic, 8, iNextHdrOffset);
-- if( rc==SQLITE_OK && 0==memcmp(aMagic, aJournalMagic, 8) ){
-- static const u8 zerobyte = 0;
-- rc = sqlite3OsWrite(pPager->jfd, &zerobyte, 1, iNextHdrOffset);
-- }
-- if( rc!=SQLITE_OK && rc!=SQLITE_IOERR_SHORT_READ ){
-- return rc;
-- }
-+static int pagerUndoCallback(void *pCtx, Pgno iPg){
-+ int rc = SQLITE_OK;
-+ Pager *pPager = (Pager *)pCtx;
-+ PgHdr *pPg;
-
-- /* Write the nRec value into the journal file header. If in
-- ** full-synchronous mode, sync the journal first. This ensures that
-- ** all data has really hit the disk before nRec is updated to mark
-- ** it as a candidate for rollback.
-- **
-- ** This is not required if the persistent media supports the
-- ** SAFE_APPEND property. Because in this case it is not possible
-- ** for garbage data to be appended to the file, the nRec field
-- ** is populated with 0xFFFFFFFF when the journal header is written
-- ** and never needs to be updated.
-- */
-- if( pPager->fullSync && 0==(iDc&SQLITE_IOCAP_SEQUENTIAL) ){
-- PAGERTRACE(("SYNC journal of %d\n", PAGERID(pPager)));
-- IOTRACE(("JSYNC %p\n", pPager))
-- rc = sqlite3OsSync(pPager->jfd, pPager->syncFlags);
-- if( rc!=SQLITE_OK ) return rc;
-- }
-- IOTRACE(("JHDR %p %lld\n", pPager, pPager->journalHdr));
-- rc = sqlite3OsWrite(
-- pPager->jfd, zHeader, sizeof(zHeader), pPager->journalHdr
-- );
-- if( rc!=SQLITE_OK ) return rc;
-- }
-- if( 0==(iDc&SQLITE_IOCAP_SEQUENTIAL) ){
-- PAGERTRACE(("SYNC journal of %d\n", PAGERID(pPager)));
-- IOTRACE(("JSYNC %p\n", pPager))
-- rc = sqlite3OsSync(pPager->jfd, pPager->syncFlags|
-- (pPager->syncFlags==SQLITE_SYNC_FULL?SQLITE_SYNC_DATAONLY:0)
-- );
-- if( rc!=SQLITE_OK ) return rc;
-+ assert( pagerUseWal(pPager) );
-+ pPg = sqlite3PagerLookup(pPager, iPg);
-+ if( pPg ){
-+ if( sqlite3PcachePageRefcount(pPg)==1 ){
-+ sqlite3PcacheDrop(pPg);
-+ }else{
-+ u32 iFrame = 0;
-+ rc = sqlite3WalFindFrame(pPager->pWal, pPg->pgno, &iFrame);
-+ if( rc==SQLITE_OK ){
-+ rc = readDbPage(pPg, iFrame);
- }
--
-- pPager->journalHdr = pPager->journalOff;
-- if( newHdr && 0==(iDc&SQLITE_IOCAP_SAFE_APPEND) ){
-- pPager->nRec = 0;
-- rc = writeJournalHdr(pPager);
-- if( rc!=SQLITE_OK ) return rc;
-+ if( rc==SQLITE_OK ){
-+ pPager->xReiniter(pPg);
- }
-- }else{
-- pPager->journalHdr = pPager->journalOff;
-+ sqlite3PagerUnref(pPg);
- }
- }
-
-- /* Unless the pager is in noSync mode, the journal file was just
-- ** successfully synced. Either way, clear the PGHDR_NEED_SYNC flag on
-- ** all pages.
-+ /* Normally, if a transaction is rolled back, any backup processes are
-+ ** updated as data is copied out of the rollback journal and into the
-+ ** database. This is not generally possible with a WAL database, as
-+ ** rollback involves simply truncating the log file. Therefore, if one
-+ ** or more frames have already been written to the log (and therefore
-+ ** also copied into the backup databases) as part of this transaction,
-+ ** the backups must be restarted.
- */
-- sqlite3PcacheClearSyncFlags(pPager->pPCache);
-- pPager->eState = PAGER_WRITER_DBMOD;
-- assert( assert_pager_state(pPager) );
-- return SQLITE_OK;
-+ sqlite3BackupRestart(pPager->pBackup);
-+
-+ return rc;
- }
-
- /*
--** The argument is the first in a linked list of dirty pages connected
--** by the PgHdr.pDirty pointer. This function writes each one of the
--** in-memory pages in the list to the database file. The argument may
--** be NULL, representing an empty list. In this case this function is
--** a no-op.
--**
--** The pager must hold at least a RESERVED lock when this function
--** is called. Before writing anything to the database file, this lock
--** is upgraded to an EXCLUSIVE lock. If the lock cannot be obtained,
--** SQLITE_BUSY is returned and no data is written to the database file.
--**
--** If the pager is a temp-file pager and the actual file-system file
--** is not yet open, it is created and opened before any data is
--** written out.
--**
--** Once the lock has been upgraded and, if necessary, the file opened,
--** the pages are written out to the database file in list order. Writing
--** a page is skipped if it meets either of the following criteria:
--**
--** * The page number is greater than Pager.dbSize, or
--** * The PGHDR_DONT_WRITE flag is set on the page.
--**
--** If writing out a page causes the database file to grow, Pager.dbFileSize
--** is updated accordingly. If page 1 is written out, then the value cached
--** in Pager.dbFileVers[] is updated to match the new value stored in
--** the database file.
--**
--** If everything is successful, SQLITE_OK is returned. If an IO error
--** occurs, an IO error code is returned. Or, if the EXCLUSIVE lock cannot
--** be obtained, SQLITE_BUSY is returned.
-+** This function is called to rollback a transaction on a WAL database.
- */
--static int pager_write_pagelist(Pager *pPager, PgHdr *pList){
-- int rc = SQLITE_OK; /* Return code */
--
-- /* This function is only called for rollback pagers in WRITER_DBMOD state. */
-- assert( !pagerUseWal(pPager) );
-- assert( pPager->eState==PAGER_WRITER_DBMOD );
-- assert( pPager->eLock==EXCLUSIVE_LOCK );
--
-- /* If the file is a temp-file has not yet been opened, open it now. It
-- ** is not possible for rc to be other than SQLITE_OK if this branch
-- ** is taken, as pager_wait_on_lock() is a no-op for temp-files.
-- */
-- if( !isOpen(pPager->fd) ){
-- assert( pPager->tempFile && rc==SQLITE_OK );
-- rc = pagerOpentemp(pPager, pPager->fd, pPager->vfsFlags);
-- }
-+static int pagerRollbackWal(Pager *pPager){
-+ int rc; /* Return Code */
-+ PgHdr *pList; /* List of dirty pages to revert */
-
-- /* Before the first write, give the VFS a hint of what the final
-- ** file size will be.
-+ /* For all pages in the cache that are currently dirty or have already
-+ ** been written (but not committed) to the log file, do one of the
-+ ** following:
-+ **
-+ ** + Discard the cached page (if refcount==0), or
-+ ** + Reload page content from the database (if refcount>0).
- */
-- assert( rc!=SQLITE_OK || isOpen(pPager->fd) );
-- if( rc==SQLITE_OK
-- && (pList->pDirty ? pPager->dbSize : pList->pgno+1)>pPager->dbHintSize
-- ){
-- sqlite3_int64 szFile = pPager->pageSize * (sqlite3_int64)pPager->dbSize;
-- sqlite3OsFileControlHint(pPager->fd, SQLITE_FCNTL_SIZE_HINT, &szFile);
-- pPager->dbHintSize = pPager->dbSize;
-+ pPager->dbSize = pPager->dbOrigSize;
-+ rc = sqlite3WalUndo(pPager->pWal, pagerUndoCallback, (void *)pPager);
-+ pList = sqlite3PcacheDirtyList(pPager->pPCache);
-+ while( pList && rc==SQLITE_OK ){
-+ PgHdr *pNext = pList->pDirty;
-+ rc = pagerUndoCallback((void *)pPager, pList->pgno);
-+ pList = pNext;
- }
-
-- while( rc==SQLITE_OK && pList ){
-- Pgno pgno = pList->pgno;
--
-- /* If there are dirty pages in the page cache with page numbers greater
-- ** than Pager.dbSize, this means sqlite3PagerTruncateImage() was called to
-- ** make the file smaller (presumably by auto-vacuum code). Do not write
-- ** any such pages to the file.
-- **
-- ** Also, do not write out any page that has the PGHDR_DONT_WRITE flag
-- ** set (set by sqlite3PagerDontWrite()).
-- */
-- if( pgno<=pPager->dbSize && 0==(pList->flags&PGHDR_DONT_WRITE) ){
-- i64 offset = (pgno-1)*(i64)pPager->pageSize; /* Offset to write */
-- char *pData; /* Data to write */
--
-- assert( (pList->flags&PGHDR_NEED_SYNC)==0 );
-- if( pList->pgno==1 ) pager_write_changecounter(pList);
-+ return rc;
-+}
-
-- /* Encode the database */
-- CODEC2(pPager, pList->pData, pgno, 6, return SQLITE_NOMEM, pData);
-+/*
-+** This function is a wrapper around sqlite3WalFrames(). As well as logging
-+** the contents of the list of pages headed by pList (connected by pDirty),
-+** this function notifies any active backup processes that the pages have
-+** changed.
-+**
-+** The list of pages passed into this routine is always sorted by page number.
-+** Hence, if page 1 appears anywhere on the list, it will be the first page.
-+*/
-+static int pagerWalFrames(
-+ Pager *pPager, /* Pager object */
-+ PgHdr *pList, /* List of frames to log */
-+ Pgno nTruncate, /* Database size after this commit */
-+ int isCommit /* True if this is a commit */
-+){
-+ int rc; /* Return code */
-+ int nList; /* Number of pages in pList */
-+#if defined(SQLITE_DEBUG) || defined(SQLITE_CHECK_PAGES)
-+ PgHdr *p; /* For looping over pages */
-+#endif
-- /* Write out the page data. */
-- rc = sqlite3OsWrite(pPager->fd, pData, pPager->pageSize, offset);
-+ assert( pPager->pWal );
-+ assert( pList );
-+#ifdef SQLITE_DEBUG
-+ /* Verify that the page list is in accending order */
-+ for(p=pList; p && p->pDirty; p=p->pDirty){
-+ assert( p->pgno < p->pDirty->pgno );
-+ }
-+#endif
-
-- /* If page 1 was just written, update Pager.dbFileVers to match
-- ** the value now stored in the database file. If writing this
-- ** page caused the database file to grow, update dbFileSize.
-- */
-- if( pgno==1 ){
-- memcpy(&pPager->dbFileVers, &pData[24], sizeof(pPager->dbFileVers));
-- }
-- if( pgno>pPager->dbFileSize ){
-- pPager->dbFileSize = pgno;
-+ assert( pList->pDirty==0 || isCommit );
-+ if( isCommit ){
-+ /* If a WAL transaction is being committed, there is no point in writing
-+ ** any pages with page numbers greater than nTruncate into the WAL file.
-+ ** They will never be read by any client. So remove them from the pDirty
-+ ** list here. */
-+ PgHdr *p;
-+ PgHdr **ppNext = &pList;
-+ nList = 0;
-+ for(p=pList; (*ppNext = p)!=0; p=p->pDirty){
-+ if( p->pgno<=nTruncate ){
-+ ppNext = &p->pDirty;
-+ nList++;
- }
-- pPager->aStat[PAGER_STAT_WRITE]++;
--
-- /* Update any backup objects copying the contents of this pager. */
-- sqlite3BackupUpdate(pPager->pBackup, pgno, (u8*)pList->pData);
-+ }
-+ assert( pList );
-+ }else{
-+ nList = 1;
-+ }
-+ pPager->aStat[PAGER_STAT_WRITE] += nList;
-
-- PAGERTRACE(("STORE %d page %d hash(%08x)\n",
-- PAGERID(pPager), pgno, pager_pagehash(pList)));
-- IOTRACE(("PGOUT %p %d\n", pPager, pgno));
-- PAGER_INCR(sqlite3_pager_writedb_count);
-- }else{
-- PAGERTRACE(("NOSTORE %d page %d\n", PAGERID(pPager), pgno));
-+ if( pList->pgno==1 ) pager_write_changecounter(pList);
-+ rc = sqlite3WalFrames(pPager->pWal,
-+ pPager->pageSize, pList, nTruncate, isCommit, pPager->walSyncFlags
-+ );
-+ if( rc==SQLITE_OK && pPager->pBackup ){
-+ PgHdr *p;
-+ for(p=pList; p; p=p->pDirty){
-+ sqlite3BackupUpdate(pPager->pBackup, p->pgno, (u8 *)p->pData);
- }
-- pager_set_pagehash(pList);
-- pList = pList->pDirty;
- }
-
-+#ifdef SQLITE_CHECK_PAGES
-+ pList = sqlite3PcacheDirtyList(pPager->pPCache);
-+ for(p=pList; p; p=p->pDirty){
-+ pager_set_pagehash(p);
-+ }
-+#endif
-+
- return rc;
- }
-
- /*
--** Ensure that the sub-journal file is open. If it is already open, this
--** function is a no-op.
-+** Begin a read transaction on the WAL.
- **
--** SQLITE_OK is returned if everything goes according to plan. An
--** SQLITE_IOERR_XXX error code is returned if a call to sqlite3OsOpen()
--** fails.
-+** This routine used to be called "pagerOpenSnapshot()" because it essentially
-+** makes a snapshot of the database at the current point in time and preserves
-+** that snapshot for use by the reader in spite of concurrently changes by
-+** other writers or checkpointers.
- */
--static int openSubJournal(Pager *pPager){
-- int rc = SQLITE_OK;
-- if( !isOpen(pPager->sjfd) ){
-- if( pPager->journalMode==PAGER_JOURNALMODE_MEMORY || pPager->subjInMemory ){
-- sqlite3MemJournalOpen(pPager->sjfd);
-- }else{
-- rc = pagerOpentemp(pPager, pPager->sjfd, SQLITE_OPEN_SUBJOURNAL);
-- }
-+static int pagerBeginReadTransaction(Pager *pPager){
-+ int rc; /* Return code */
-+ int changed = 0; /* True if cache must be reset */
-+
-+ assert( pagerUseWal(pPager) );
-+ assert( pPager->eState==PAGER_OPEN || pPager->eState==PAGER_READER );
-+
-+ /* sqlite3WalEndReadTransaction() was not called for the previous
-+ ** transaction in locking_mode=EXCLUSIVE. So call it now. If we
-+ ** are in locking_mode=NORMAL and EndRead() was previously called,
-+ ** the duplicate call is harmless.
-+ */
-+ sqlite3WalEndReadTransaction(pPager->pWal);
-+
-+ rc = sqlite3WalBeginReadTransaction(pPager->pWal, &changed);
-+ if( rc!=SQLITE_OK || changed ){
-+ pager_reset(pPager);
-+ if( USEFETCH(pPager) ) sqlite3OsUnfetch(pPager->fd, 0, 0);
- }
-+
- return rc;
- }
-+#endif
-
- /*
--** Append a record of the current state of page pPg to the sub-journal.
--** It is the callers responsibility to use subjRequiresPage() to check
--** that it is really required before calling this function.
--**
--** If successful, set the bit corresponding to pPg->pgno in the bitvecs
--** for all open savepoints before returning.
-+** This function is called as part of the transition from PAGER_OPEN
-+** to PAGER_READER state to determine the size of the database file
-+** in pages (assuming the page size currently stored in Pager.pageSize).
- **
--** This function returns SQLITE_OK if everything is successful, an IO
--** error code if the attempt to write to the sub-journal fails, or
--** SQLITE_NOMEM if a malloc fails while setting a bit in a savepoint
--** bitvec.
-+** If no error occurs, SQLITE_OK is returned and the size of the database
-+** in pages is stored in *pnPage. Otherwise, an error code (perhaps
-+** SQLITE_IOERR_FSTAT) is returned and *pnPage is left unmodified.
- */
--static int subjournalPage(PgHdr *pPg){
-- int rc = SQLITE_OK;
-- Pager *pPager = pPg->pPager;
-- if( pPager->journalMode!=PAGER_JOURNALMODE_OFF ){
-+static int pagerPagecount(Pager *pPager, Pgno *pnPage){
-+ Pgno nPage; /* Value to return via *pnPage */
-
-- /* Open the sub-journal, if it has not already been opened */
-- assert( pPager->useJournal );
-- assert( isOpen(pPager->jfd) || pagerUseWal(pPager) );
-- assert( isOpen(pPager->sjfd) || pPager->nSubRec==0 );
-- assert( pagerUseWal(pPager)
-- || pageInJournal(pPg)
-- || pPg->pgno>pPager->dbOrigSize
-- );
-- rc = openSubJournal(pPager);
-+ /* Query the WAL sub-system for the database size. The WalDbsize()
-+ ** function returns zero if the WAL is not open (i.e. Pager.pWal==0), or
-+ ** if the database size is not available. The database size is not
-+ ** available from the WAL sub-system if the log file is empty or
-+ ** contains no valid committed transactions.
-+ */
-+ assert( pPager->eState==PAGER_OPEN );
-+ assert( pPager->eLock>=SHARED_LOCK );
-+ nPage = sqlite3WalDbsize(pPager->pWal);
-
-- /* If the sub-journal was opened successfully (or was already open),
-- ** write the journal record into the file. */
-- if( rc==SQLITE_OK ){
-- void *pData = pPg->pData;
-- i64 offset = (i64)pPager->nSubRec*(4+pPager->pageSize);
-- char *pData2;
--
-- CODEC2(pPager, pData, pPg->pgno, 7, return SQLITE_NOMEM, pData2);
-- PAGERTRACE(("STMT-JOURNAL %d page %d\n", PAGERID(pPager), pPg->pgno));
-- rc = write32bits(pPager->sjfd, offset, pPg->pgno);
-- if( rc==SQLITE_OK ){
-- rc = sqlite3OsWrite(pPager->sjfd, pData2, pPager->pageSize, offset+4);
-+ /* If the database size was not available from the WAL sub-system,
-+ ** determine it based on the size of the database file. If the size
-+ ** of the database file is not an integer multiple of the page-size,
-+ ** round down to the nearest page. Except, any file larger than 0
-+ ** bytes in size is considered to contain at least one page.
-+ */
-+ if( nPage==0 ){
-+ i64 n = 0; /* Size of db file in bytes */
-+ assert( isOpen(pPager->fd) || pPager->tempFile );
-+ if( isOpen(pPager->fd) ){
-+ int rc = sqlite3OsFileSize(pPager->fd, &n);
-+ if( rc!=SQLITE_OK ){
-+ return rc;
- }
- }
-+ nPage = (Pgno)((n+pPager->pageSize-1) / pPager->pageSize);
- }
-- if( rc==SQLITE_OK ){
-- pPager->nSubRec++;
-- assert( pPager->nSavepoint>0 );
-- rc = addToSavepointBitvecs(pPager, pPg->pgno);
-+
-+ /* If the current number of pages in the file is greater than the
-+ ** configured maximum pager number, increase the allowed limit so
-+ ** that the file can be read.
-+ */
-+ if( nPage>pPager->mxPgno ){
-+ pPager->mxPgno = (Pgno)nPage;
- }
-- return rc;
-+
-+ *pnPage = nPage;
-+ return SQLITE_OK;
- }
-
-+#ifndef SQLITE_OMIT_WAL
- /*
--** This function is called by the pcache layer when it has reached some
--** soft memory limit. The first argument is a pointer to a Pager object
--** (cast as a void*). The pager is always 'purgeable' (not an in-memory
--** database). The second argument is a reference to a page that is
--** currently dirty but has no outstanding references. The page
--** is always associated with the Pager object passed as the first
--** argument.
-+** Check if the *-wal file that corresponds to the database opened by pPager
-+** exists if the database is not empy, or verify that the *-wal file does
-+** not exist (by deleting it) if the database file is empty.
- **
--** The job of this function is to make pPg clean by writing its contents
--** out to the database file, if possible. This may involve syncing the
--** journal file.
-+** If the database is not empty and the *-wal file exists, open the pager
-+** in WAL mode. If the database is empty or if no *-wal file exists and
-+** if no error occurs, make sure Pager.journalMode is not set to
-+** PAGER_JOURNALMODE_WAL.
- **
--** If successful, sqlite3PcacheMakeClean() is called on the page and
--** SQLITE_OK returned. If an IO error occurs while trying to make the
--** page clean, the IO error code is returned. If the page cannot be
--** made clean for some other reason, but no error occurs, then SQLITE_OK
--** is returned by sqlite3PcacheMakeClean() is not called.
-+** Return SQLITE_OK or an error code.
-+**
-+** The caller must hold a SHARED lock on the database file to call this
-+** function. Because an EXCLUSIVE lock on the db file is required to delete
-+** a WAL on a none-empty database, this ensures there is no race condition
-+** between the xAccess() below and an xDelete() being executed by some
-+** other connection.
- */
--static int pagerStress(void *p, PgHdr *pPg){
-- Pager *pPager = (Pager *)p;
-+static int pagerOpenWalIfPresent(Pager *pPager){
- int rc = SQLITE_OK;
-+ assert( pPager->eState==PAGER_OPEN );
-+ assert( pPager->eLock>=SHARED_LOCK );
-
-- assert( pPg->pPager==pPager );
-- assert( pPg->flags&PGHDR_DIRTY );
--
-- /* The doNotSyncSpill flag is set during times when doing a sync of
-- ** journal (and adding a new header) is not allowed. This occurs
-- ** during calls to sqlite3PagerWrite() while trying to journal multiple
-- ** pages belonging to the same sector.
-- **
-- ** The doNotSpill flag inhibits all cache spilling regardless of whether
-- ** or not a sync is required. This is set during a rollback.
-- **
-- ** Spilling is also prohibited when in an error state since that could
-- ** lead to database corruption. In the current implementaton it
-- ** is impossible for sqlite3PcacheFetch() to be called with createFlag==1
-- ** while in the error state, hence it is impossible for this routine to
-- ** be called in the error state. Nevertheless, we include a NEVER()
-- ** test for the error state as a safeguard against future changes.
-- */
-- if( NEVER(pPager->errCode) ) return SQLITE_OK;
-- if( pPager->doNotSpill ) return SQLITE_OK;
-- if( pPager->doNotSyncSpill && (pPg->flags & PGHDR_NEED_SYNC)!=0 ){
-- return SQLITE_OK;
-- }
-+ if( !pPager->tempFile ){
-+ int isWal; /* True if WAL file exists */
-+ Pgno nPage; /* Size of the database file */
-
-- pPg->pDirty = 0;
-- if( pagerUseWal(pPager) ){
-- /* Write a single frame for this page to the log. */
-- if( subjRequiresPage(pPg) ){
-- rc = subjournalPage(pPg);
-- }
-- if( rc==SQLITE_OK ){
-- rc = pagerWalFrames(pPager, pPg, 0, 0);
-- }
-- }else{
--
-- /* Sync the journal file if required. */
-- if( pPg->flags&PGHDR_NEED_SYNC
-- || pPager->eState==PAGER_WRITER_CACHEMOD
-- ){
-- rc = syncJournal(pPager, 1);
-- }
--
-- /* If the page number of this page is larger than the current size of
-- ** the database image, it may need to be written to the sub-journal.
-- ** This is because the call to pager_write_pagelist() below will not
-- ** actually write data to the file in this case.
-- **
-- ** Consider the following sequence of events:
-- **
-- ** BEGIN;
-- ** <journal page X>
-- ** <modify page X>
-- ** SAVEPOINT sp;
-- ** <shrink database file to Y pages>
-- ** pagerStress(page X)
-- ** ROLLBACK TO sp;
-- **
-- ** If (X>Y), then when pagerStress is called page X will not be written
-- ** out to the database file, but will be dropped from the cache. Then,
-- ** following the "ROLLBACK TO sp" statement, reading page X will read
-- ** data from the database file. This will be the copy of page X as it
-- ** was when the transaction started, not as it was when "SAVEPOINT sp"
-- ** was executed.
-- **
-- ** The solution is to write the current data for page X into the
-- ** sub-journal file now (if it is not already there), so that it will
-- ** be restored to its current value when the "ROLLBACK TO sp" is
-- ** executed.
-- */
-- if( NEVER(
-- rc==SQLITE_OK && pPg->pgno>pPager->dbSize && subjRequiresPage(pPg)
-- ) ){
-- rc = subjournalPage(pPg);
-+ rc = pagerPagecount(pPager, &nPage);
-+ if( rc ) return rc;
-+ if( nPage==0 ){
-+ rc = sqlite3OsDelete(pPager->pVfs, pPager->zWal, 0);
-+ if( rc==SQLITE_IOERR_DELETE_NOENT ) rc = SQLITE_OK;
-+ isWal = 0;
-+ }else{
-+ rc = sqlite3OsAccess(
-+ pPager->pVfs, pPager->zWal, SQLITE_ACCESS_EXISTS, &isWal
-+ );
- }
--
-- /* Write the contents of the page out to the database file. */
- if( rc==SQLITE_OK ){
-- assert( (pPg->flags&PGHDR_NEED_SYNC)==0 );
-- rc = pager_write_pagelist(pPager, pPg);
-+ if( isWal ){
-+ testcase( sqlite3PcachePagecount(pPager->pPCache)==0 );
-+ rc = sqlite3PagerOpenWal(pPager, 0);
-+ }else if( pPager->journalMode==PAGER_JOURNALMODE_WAL ){
-+ pPager->journalMode = PAGER_JOURNALMODE_DELETE;
-+ }
- }
- }
--
-- /* Mark the page as clean. */
-- if( rc==SQLITE_OK ){
-- PAGERTRACE(("STRESS %d page %d\n", PAGERID(pPager), pPg->pgno));
-- sqlite3PcacheMakeClean(pPg);
-- }
--
-- return pager_error(pPager, rc);
-+ return rc;
- }
--
-+#endif
-
- /*
--** Allocate and initialize a new Pager object and put a pointer to it
--** in *ppPager. The pager should eventually be freed by passing it
--** to sqlite3PagerClose().
-+** Playback savepoint pSavepoint. Or, if pSavepoint==NULL, then playback
-+** the entire master journal file. The case pSavepoint==NULL occurs when
-+** a ROLLBACK TO command is invoked on a SAVEPOINT that is a transaction
-+** savepoint.
- **
--** The zFilename argument is the path to the database file to open.
--** If zFilename is NULL then a randomly-named temporary file is created
--** and used as the file to be cached. Temporary files are be deleted
--** automatically when they are closed. If zFilename is ":memory:" then
--** all information is held in cache. It is never written to disk.
--** This can be used to implement an in-memory database.
-+** When pSavepoint is not NULL (meaning a non-transaction savepoint is
-+** being rolled back), then the rollback consists of up to three stages,
-+** performed in the order specified:
- **
--** The nExtra parameter specifies the number of bytes of space allocated
--** along with each page reference. This space is available to the user
--** via the sqlite3PagerGetExtra() API.
-+** * Pages are played back from the main journal starting at byte
-+** offset PagerSavepoint.iOffset and continuing to
-+** PagerSavepoint.iHdrOffset, or to the end of the main journal
-+** file if PagerSavepoint.iHdrOffset is zero.
- **
--** The flags argument is used to specify properties that affect the
--** operation of the pager. It should be passed some bitwise combination
--** of the PAGER_* flags.
-+** * If PagerSavepoint.iHdrOffset is not zero, then pages are played
-+** back starting from the journal header immediately following
-+** PagerSavepoint.iHdrOffset to the end of the main journal file.
- **
--** The vfsFlags parameter is a bitmask to pass to the flags parameter
--** of the xOpen() method of the supplied VFS when opening files.
-+** * Pages are then played back from the sub-journal file, starting
-+** with the PagerSavepoint.iSubRec and continuing to the end of
-+** the journal file.
- **
--** If the pager object is allocated and the specified file opened
--** successfully, SQLITE_OK is returned and *ppPager set to point to
--** the new pager object. If an error occurs, *ppPager is set to NULL
--** and error code returned. This function may return SQLITE_NOMEM
--** (sqlite3Malloc() is used to allocate memory), SQLITE_CANTOPEN or
--** various SQLITE_IO_XXX errors.
-+** Throughout the rollback process, each time a page is rolled back, the
-+** corresponding bit is set in a bitvec structure (variable pDone in the
-+** implementation below). This is used to ensure that a page is only
-+** rolled back the first time it is encountered in either journal.
-+**
-+** If pSavepoint is NULL, then pages are only played back from the main
-+** journal file. There is no need for a bitvec in this case.
-+**
-+** In either case, before playback commences the Pager.dbSize variable
-+** is reset to the value that it held at the start of the savepoint
-+** (or transaction). No page with a page-number greater than this value
-+** is played back. If one is encountered it is simply skipped.
- */
--SQLITE_PRIVATE int sqlite3PagerOpen(
-- sqlite3_vfs *pVfs, /* The virtual file system to use */
-- Pager **ppPager, /* OUT: Return the Pager structure here */
-- const char *zFilename, /* Name of the database file to open */
-- int nExtra, /* Extra bytes append to each in-memory page */
-- int flags, /* flags controlling this file */
-- int vfsFlags, /* flags passed through to sqlite3_vfs.xOpen() */
-- void (*xReinit)(DbPage*) /* Function to reinitialize pages */
--){
-- u8 *pPtr;
-- Pager *pPager = 0; /* Pager object to allocate and return */
-+static int pagerPlaybackSavepoint(Pager *pPager, PagerSavepoint *pSavepoint){
-+ i64 szJ; /* Effective size of the main journal */
-+ i64 iHdrOff; /* End of first segment of main-journal records */
- int rc = SQLITE_OK; /* Return code */
-- int tempFile = 0; /* True for temp files (incl. in-memory files) */
-- int memDb = 0; /* True if this is an in-memory file */
-- int readOnly = 0; /* True if this is a read-only file */
-- int journalFileSize; /* Bytes to allocate for each journal fd */
-- char *zPathname = 0; /* Full path to database file */
-- int nPathname = 0; /* Number of bytes in zPathname */
-- int useJournal = (flags & PAGER_OMIT_JOURNAL)==0; /* False to omit journal */
-- int pcacheSize = sqlite3PcacheSize(); /* Bytes to allocate for PCache */
-- u32 szPageDflt = SQLITE_DEFAULT_PAGE_SIZE; /* Default page size */
-- const char *zUri = 0; /* URI args to copy */
-- int nUri = 0; /* Number of bytes of URI args at *zUri */
-+ Bitvec *pDone = 0; /* Bitvec to ensure pages played back only once */
-
-- /* Figure out how much space is required for each journal file-handle
-- ** (there are two of them, the main journal and the sub-journal). This
-- ** is the maximum space required for an in-memory journal file handle
-- ** and a regular journal file-handle. Note that a "regular journal-handle"
-- ** may be a wrapper capable of caching the first portion of the journal
-- ** file in memory to implement the atomic-write optimization (see
-- ** source file journal.c).
-- */
-- if( sqlite3JournalSize(pVfs)>sqlite3MemJournalSize() ){
-- journalFileSize = ROUND8(sqlite3JournalSize(pVfs));
-- }else{
-- journalFileSize = ROUND8(sqlite3MemJournalSize());
-+ assert( pPager->eState!=PAGER_ERROR );
-+ assert( pPager->eState>=PAGER_WRITER_LOCKED );
-+
-+ /* Allocate a bitvec to use to store the set of pages rolled back */
-+ if( pSavepoint ){
-+ pDone = sqlite3BitvecCreate(pSavepoint->nOrig);
-+ if( !pDone ){
-+ return SQLITE_NOMEM;
-+ }
- }
-
-- /* Set the output variable to NULL in case an error occurs. */
-- *ppPager = 0;
-+ /* Set the database size back to the value it was before the savepoint
-+ ** being reverted was opened.
-+ */
-+ pPager->dbSize = pSavepoint ? pSavepoint->nOrig : pPager->dbOrigSize;
-+ pPager->changeCountDone = pPager->tempFile;
-
--#ifndef SQLITE_OMIT_MEMORYDB
-- if( flags & PAGER_MEMORY ){
-- memDb = 1;
-- if( zFilename && zFilename[0] ){
-- zPathname = sqlite3DbStrDup(0, zFilename);
-- if( zPathname==0 ) return SQLITE_NOMEM;
-- nPathname = sqlite3Strlen30(zPathname);
-- zFilename = 0;
-- }
-+ if( !pSavepoint && pagerUseWal(pPager) ){
-+ return pagerRollbackWal(pPager);
- }
--#endif
-
-- /* Compute and store the full pathname in an allocated buffer pointed
-- ** to by zPathname, length nPathname. Or, if this is a temporary file,
-- ** leave both nPathname and zPathname set to 0.
-+ /* Use pPager->journalOff as the effective size of the main rollback
-+ ** journal. The actual file might be larger than this in
-+ ** PAGER_JOURNALMODE_TRUNCATE or PAGER_JOURNALMODE_PERSIST. But anything
-+ ** past pPager->journalOff is off-limits to us.
- */
-- if( zFilename && zFilename[0] ){
-- const char *z;
-- nPathname = pVfs->mxPathname+1;
-- zPathname = sqlite3DbMallocRaw(0, nPathname*2);
-- if( zPathname==0 ){
-- return SQLITE_NOMEM;
-- }
-- zPathname[0] = 0; /* Make sure initialized even if FullPathname() fails */
-- rc = sqlite3OsFullPathname(pVfs, zFilename, nPathname, zPathname);
-- nPathname = sqlite3Strlen30(zPathname);
-- z = zUri = &zFilename[sqlite3Strlen30(zFilename)+1];
-- while( *z ){
-- z += sqlite3Strlen30(z)+1;
-- z += sqlite3Strlen30(z)+1;
-- }
-- nUri = (int)(&z[1] - zUri);
-- assert( nUri>=0 );
-- if( rc==SQLITE_OK && nPathname+8>pVfs->mxPathname ){
-- /* This branch is taken when the journal path required by
-- ** the database being opened will be more than pVfs->mxPathname
-- ** bytes in length. This means the database cannot be opened,
-- ** as it will not be possible to open the journal file or even
-- ** check for a hot-journal before reading.
-- */
-- rc = SQLITE_CANTOPEN_BKPT;
-- }
-- if( rc!=SQLITE_OK ){
-- sqlite3DbFree(0, zPathname);
-- return rc;
-+ szJ = pPager->journalOff;
-+ assert( pagerUseWal(pPager)==0 || szJ==0 );
-+
-+ /* Begin by rolling back records from the main journal starting at
-+ ** PagerSavepoint.iOffset and continuing to the next journal header.
-+ ** There might be records in the main journal that have a page number
-+ ** greater than the current database size (pPager->dbSize) but those
-+ ** will be skipped automatically. Pages are added to pDone as they
-+ ** are played back.
-+ */
-+ if( pSavepoint && !pagerUseWal(pPager) ){
-+ iHdrOff = pSavepoint->iHdrOffset ? pSavepoint->iHdrOffset : szJ;
-+ pPager->journalOff = pSavepoint->iOffset;
-+ while( rc==SQLITE_OK && pPager->journalOff<iHdrOff ){
-+ rc = pager_playback_one_page(pPager, &pPager->journalOff, pDone, 1, 1);
- }
-+ assert( rc!=SQLITE_DONE );
-+ }else{
-+ pPager->journalOff = 0;
- }
-
-- /* Allocate memory for the Pager structure, PCache object, the
-- ** three file descriptors, the database file name and the journal
-- ** file name. The layout in memory is as follows:
-- **
-- ** Pager object (sizeof(Pager) bytes)
-- ** PCache object (sqlite3PcacheSize() bytes)
-- ** Database file handle (pVfs->szOsFile bytes)
-- ** Sub-journal file handle (journalFileSize bytes)
-- ** Main journal file handle (journalFileSize bytes)
-- ** Database file name (nPathname+1 bytes)
-- ** Journal file name (nPathname+8+1 bytes)
-+ /* Continue rolling back records out of the main journal starting at
-+ ** the first journal header seen and continuing until the effective end
-+ ** of the main journal file. Continue to skip out-of-range pages and
-+ ** continue adding pages rolled back to pDone.
- */
-- pPtr = (u8 *)sqlite3MallocZero(
-- ROUND8(sizeof(*pPager)) + /* Pager structure */
-- ROUND8(pcacheSize) + /* PCache object */
-- ROUND8(pVfs->szOsFile) + /* The main db file */
-- journalFileSize * 2 + /* The two journal files */
-- nPathname + 1 + nUri + /* zFilename */
-- nPathname + 8 + 2 /* zJournal */
--#ifndef SQLITE_OMIT_WAL
-- + nPathname + 4 + 2 /* zWal */
--#endif
-- );
-- assert( EIGHT_BYTE_ALIGNMENT(SQLITE_INT_TO_PTR(journalFileSize)) );
-- if( !pPtr ){
-- sqlite3DbFree(0, zPathname);
-- return SQLITE_NOMEM;
-- }
-- pPager = (Pager*)(pPtr);
-- pPager->pPCache = (PCache*)(pPtr += ROUND8(sizeof(*pPager)));
-- pPager->fd = (sqlite3_file*)(pPtr += ROUND8(pcacheSize));
-- pPager->sjfd = (sqlite3_file*)(pPtr += ROUND8(pVfs->szOsFile));
-- pPager->jfd = (sqlite3_file*)(pPtr += journalFileSize);
-- pPager->zFilename = (char*)(pPtr += journalFileSize);
-- assert( EIGHT_BYTE_ALIGNMENT(pPager->jfd) );
-+ while( rc==SQLITE_OK && pPager->journalOff<szJ ){
-+ u32 ii; /* Loop counter */
-+ u32 nJRec = 0; /* Number of Journal Records */
-+ u32 dummy;
-+ rc = readJournalHdr(pPager, 0, szJ, &nJRec, &dummy);
-+ assert( rc!=SQLITE_DONE );
-
-- /* Fill in the Pager.zFilename and Pager.zJournal buffers, if required. */
-- if( zPathname ){
-- assert( nPathname>0 );
-- pPager->zJournal = (char*)(pPtr += nPathname + 1 + nUri);
-- memcpy(pPager->zFilename, zPathname, nPathname);
-- if( nUri ) memcpy(&pPager->zFilename[nPathname+1], zUri, nUri);
-- memcpy(pPager->zJournal, zPathname, nPathname);
-- memcpy(&pPager->zJournal[nPathname], "-journal\000", 8+2);
-- sqlite3FileSuffix3(pPager->zFilename, pPager->zJournal);
--#ifndef SQLITE_OMIT_WAL
-- pPager->zWal = &pPager->zJournal[nPathname+8+1];
-- memcpy(pPager->zWal, zPathname, nPathname);
-- memcpy(&pPager->zWal[nPathname], "-wal\000", 4+1);
-- sqlite3FileSuffix3(pPager->zFilename, pPager->zWal);
--#endif
-- sqlite3DbFree(0, zPathname);
-+ /*
-+ ** The "pPager->journalHdr+JOURNAL_HDR_SZ(pPager)==pPager->journalOff"
-+ ** test is related to ticket #2565. See the discussion in the
-+ ** pager_playback() function for additional information.
-+ */
-+ if( nJRec==0
-+ && pPager->journalHdr+JOURNAL_HDR_SZ(pPager)==pPager->journalOff
-+ ){
-+ nJRec = (u32)((szJ - pPager->journalOff)/JOURNAL_PG_SZ(pPager));
-+ }
-+ for(ii=0; rc==SQLITE_OK && ii<nJRec && pPager->journalOff<szJ; ii++){
-+ rc = pager_playback_one_page(pPager, &pPager->journalOff, pDone, 1, 1);
-+ }
-+ assert( rc!=SQLITE_DONE );
- }
-- pPager->pVfs = pVfs;
-- pPager->vfsFlags = vfsFlags;
-+ assert( rc!=SQLITE_OK || pPager->journalOff>=szJ );
-
-- /* Open the pager file.
-+ /* Finally, rollback pages from the sub-journal. Page that were
-+ ** previously rolled back out of the main journal (and are hence in pDone)
-+ ** will be skipped. Out-of-range pages are also skipped.
- */
-- if( zFilename && zFilename[0] ){
-- int fout = 0; /* VFS flags returned by xOpen() */
-- rc = sqlite3OsOpen(pVfs, pPager->zFilename, pPager->fd, vfsFlags, &fout);
-- assert( !memDb );
-- readOnly = (fout&SQLITE_OPEN_READONLY);
-+ if( pSavepoint ){
-+ u32 ii; /* Loop counter */
-+ i64 offset = (i64)pSavepoint->iSubRec*(4+pPager->pageSize);
-
-- /* If the file was successfully opened for read/write access,
-- ** choose a default page size in case we have to create the
-- ** database file. The default page size is the maximum of:
-- **
-- ** + SQLITE_DEFAULT_PAGE_SIZE,
-- ** + The value returned by sqlite3OsSectorSize()
-- ** + The largest page size that can be written atomically.
-- */
-- if( rc==SQLITE_OK && !readOnly ){
-- setSectorSize(pPager);
-- assert(SQLITE_DEFAULT_PAGE_SIZE<=SQLITE_MAX_DEFAULT_PAGE_SIZE);
-- if( szPageDflt<pPager->sectorSize ){
-- if( pPager->sectorSize>SQLITE_MAX_DEFAULT_PAGE_SIZE ){
-- szPageDflt = SQLITE_MAX_DEFAULT_PAGE_SIZE;
-- }else{
-- szPageDflt = (u32)pPager->sectorSize;
-- }
-- }
--#ifdef SQLITE_ENABLE_ATOMIC_WRITE
-- {
-- int iDc = sqlite3OsDeviceCharacteristics(pPager->fd);
-- int ii;
-- assert(SQLITE_IOCAP_ATOMIC512==(512>>8));
-- assert(SQLITE_IOCAP_ATOMIC64K==(65536>>8));
-- assert(SQLITE_MAX_DEFAULT_PAGE_SIZE<=65536);
-- for(ii=szPageDflt; ii<=SQLITE_MAX_DEFAULT_PAGE_SIZE; ii=ii*2){
-- if( iDc&(SQLITE_IOCAP_ATOMIC|(ii>>8)) ){
-- szPageDflt = ii;
-- }
-- }
-- }
--#endif
-+ if( pagerUseWal(pPager) ){
-+ rc = sqlite3WalSavepointUndo(pPager->pWal, pSavepoint->aWalData);
-+ }
-+ for(ii=pSavepoint->iSubRec; rc==SQLITE_OK && ii<pPager->nSubRec; ii++){
-+ assert( offset==(i64)ii*(4+pPager->pageSize) );
-+ rc = pager_playback_one_page(pPager, &offset, pDone, 0, 1);
- }
-- }else{
-- /* If a temporary file is requested, it is not opened immediately.
-- ** In this case we accept the default page size and delay actually
-- ** opening the file until the first call to OsWrite().
-- **
-- ** This branch is also run for an in-memory database. An in-memory
-- ** database is the same as a temp-file that is never written out to
-- ** disk and uses an in-memory rollback journal.
-- */
-- tempFile = 1;
-- pPager->eState = PAGER_READER;
-- pPager->eLock = EXCLUSIVE_LOCK;
-- readOnly = (vfsFlags&SQLITE_OPEN_READONLY);
-+ assert( rc!=SQLITE_DONE );
- }
-
-- /* The following call to PagerSetPagesize() serves to set the value of
-- ** Pager.pageSize and to allocate the Pager.pTmpSpace buffer.
-- */
-+ sqlite3BitvecDestroy(pDone);
- if( rc==SQLITE_OK ){
-- assert( pPager->memDb==0 );
-- rc = sqlite3PagerSetPagesize(pPager, &szPageDflt, -1);
-- testcase( rc!=SQLITE_OK );
-+ pPager->journalOff = szJ;
- }
-
-- /* If an error occurred in either of the blocks above, free the
-- ** Pager structure and close the file.
-- */
-- if( rc!=SQLITE_OK ){
-- assert( !pPager->pTmpSpace );
-- sqlite3OsClose(pPager->fd);
-- sqlite3_free(pPager);
-- return rc;
-+ return rc;
-+}
-+
-+/*
-+** Change the maximum number of in-memory pages that are allowed.
-+*/
-+SQLITE_PRIVATE void sqlite3PagerSetCachesize(Pager *pPager, int mxPage){
-+ sqlite3PcacheSetCachesize(pPager->pPCache, mxPage);
-+}
-+
-+/*
-+** Invoke SQLITE_FCNTL_MMAP_SIZE based on the current value of szMmap.
-+*/
-+static void pagerFixMaplimit(Pager *pPager){
-+#if SQLITE_MAX_MMAP_SIZE>0
-+ sqlite3_file *fd = pPager->fd;
-+ if( isOpen(fd) ){
-+ sqlite3_int64 sz;
-+ pPager->bUseFetch = (fd->pMethods->iVersion>=3) && pPager->szMmap>0;
-+ sz = pPager->szMmap;
-+ sqlite3OsFileControlHint(pPager->fd, SQLITE_FCNTL_MMAP_SIZE, &sz);
- }
-+#endif
-+}
-
-- /* Initialize the PCache object. */
-- assert( nExtra<1000 );
-- nExtra = ROUND8(nExtra);
-- sqlite3PcacheOpen(szPageDflt, nExtra, !memDb,
-- !memDb?pagerStress:0, (void *)pPager, pPager->pPCache);
-+/*
-+** Change the maximum size of any memory mapping made of the database file.
-+*/
-+SQLITE_PRIVATE void sqlite3PagerSetMmapLimit(Pager *pPager, sqlite3_int64 szMmap){
-+ pPager->szMmap = szMmap;
-+ pagerFixMaplimit(pPager);
-+}
-
-- PAGERTRACE(("OPEN %d %s\n", FILEHANDLEID(pPager->fd), pPager->zFilename));
-- IOTRACE(("OPEN %p %s\n", pPager, pPager->zFilename))
-+/*
-+** Free as much memory as possible from the pager.
-+*/
-+SQLITE_PRIVATE void sqlite3PagerShrink(Pager *pPager){
-+ sqlite3PcacheShrink(pPager->pPCache);
-+}
-
-- pPager->useJournal = (u8)useJournal;
-- /* pPager->stmtOpen = 0; */
-- /* pPager->stmtInUse = 0; */
-- /* pPager->nRef = 0; */
-- /* pPager->stmtSize = 0; */
-- /* pPager->stmtJSize = 0; */
-- /* pPager->nPage = 0; */
-- pPager->mxPgno = SQLITE_MAX_PAGE_COUNT;
-- /* pPager->state = PAGER_UNLOCK; */
--#if 0
-- assert( pPager->state == (tempFile ? PAGER_EXCLUSIVE : PAGER_UNLOCK) );
--#endif
-- /* pPager->errMask = 0; */
-- pPager->tempFile = (u8)tempFile;
-- assert( tempFile==PAGER_LOCKINGMODE_NORMAL
-- || tempFile==PAGER_LOCKINGMODE_EXCLUSIVE );
-- assert( PAGER_LOCKINGMODE_EXCLUSIVE==1 );
-- pPager->exclusiveMode = (u8)tempFile;
-- pPager->changeCountDone = pPager->tempFile;
-- pPager->memDb = (u8)memDb;
-- pPager->readOnly = (u8)readOnly;
-- assert( useJournal || pPager->tempFile );
-- pPager->noSync = pPager->tempFile;
-+/*
-+** Adjust the robustness of the database to damage due to OS crashes
-+** or power failures by changing the number of syncs()s when writing
-+** the rollback journal. There are three levels:
-+**
-+** OFF sqlite3OsSync() is never called. This is the default
-+** for temporary and transient files.
-+**
-+** NORMAL The journal is synced once before writes begin on the
-+** database. This is normally adequate protection, but
-+** it is theoretically possible, though very unlikely,
-+** that an inopertune power failure could leave the journal
-+** in a state which would cause damage to the database
-+** when it is rolled back.
-+**
-+** FULL The journal is synced twice before writes begin on the
-+** database (with some additional information - the nRec field
-+** of the journal header - being written in between the two
-+** syncs). If we assume that writing a
-+** single disk sector is atomic, then this mode provides
-+** assurance that the journal will not be corrupted to the
-+** point of causing damage to the database during rollback.
-+**
-+** The above is for a rollback-journal mode. For WAL mode, OFF continues
-+** to mean that no syncs ever occur. NORMAL means that the WAL is synced
-+** prior to the start of checkpoint and that the database file is synced
-+** at the conclusion of the checkpoint if the entire content of the WAL
-+** was written back into the database. But no sync operations occur for
-+** an ordinary commit in NORMAL mode with WAL. FULL means that the WAL
-+** file is synced following each commit operation, in addition to the
-+** syncs associated with NORMAL.
-+**
-+** Do not confuse synchronous=FULL with SQLITE_SYNC_FULL. The
-+** SQLITE_SYNC_FULL macro means to use the MacOSX-style full-fsync
-+** using fcntl(F_FULLFSYNC). SQLITE_SYNC_NORMAL means to do an
-+** ordinary fsync() call. There is no difference between SQLITE_SYNC_FULL
-+** and SQLITE_SYNC_NORMAL on platforms other than MacOSX. But the
-+** synchronous=FULL versus synchronous=NORMAL setting determines when
-+** the xSync primitive is called and is relevant to all platforms.
-+**
-+** Numeric values associated with these states are OFF==1, NORMAL=2,
-+** and FULL=3.
-+*/
-+#ifndef SQLITE_OMIT_PAGER_PRAGMAS
-+SQLITE_PRIVATE void sqlite3PagerSetSafetyLevel(
-+ Pager *pPager, /* The pager to set safety level for */
-+ int level, /* PRAGMA synchronous. 1=OFF, 2=NORMAL, 3=FULL */
-+ int bFullFsync, /* PRAGMA fullfsync */
-+ int bCkptFullFsync /* PRAGMA checkpoint_fullfsync */
-+){
-+ assert( level>=1 && level<=3 );
-+ pPager->noSync = (level==1 || pPager->tempFile) ?1:0;
-+ pPager->fullSync = (level==3 && !pPager->tempFile) ?1:0;
- if( pPager->noSync ){
-- assert( pPager->fullSync==0 );
-- assert( pPager->syncFlags==0 );
-- assert( pPager->walSyncFlags==0 );
-- assert( pPager->ckptSyncFlags==0 );
-+ pPager->syncFlags = 0;
-+ pPager->ckptSyncFlags = 0;
-+ }else if( bFullFsync ){
-+ pPager->syncFlags = SQLITE_SYNC_FULL;
-+ pPager->ckptSyncFlags = SQLITE_SYNC_FULL;
-+ }else if( bCkptFullFsync ){
-+ pPager->syncFlags = SQLITE_SYNC_NORMAL;
-+ pPager->ckptSyncFlags = SQLITE_SYNC_FULL;
- }else{
-- pPager->fullSync = 1;
- pPager->syncFlags = SQLITE_SYNC_NORMAL;
-- pPager->walSyncFlags = SQLITE_SYNC_NORMAL | WAL_SYNC_TRANSACTIONS;
- pPager->ckptSyncFlags = SQLITE_SYNC_NORMAL;
- }
-- /* pPager->pFirst = 0; */
-- /* pPager->pFirstSynced = 0; */
-- /* pPager->pLast = 0; */
-- pPager->nExtra = (u16)nExtra;
-- pPager->journalSizeLimit = SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT;
-- assert( isOpen(pPager->fd) || tempFile );
-- setSectorSize(pPager);
-- if( !useJournal ){
-- pPager->journalMode = PAGER_JOURNALMODE_OFF;
-- }else if( memDb ){
-- pPager->journalMode = PAGER_JOURNALMODE_MEMORY;
-+ pPager->walSyncFlags = pPager->syncFlags;
-+ if( pPager->fullSync ){
-+ pPager->walSyncFlags |= WAL_SYNC_TRANSACTIONS;
- }
-- /* pPager->xBusyHandler = 0; */
-- /* pPager->pBusyHandlerArg = 0; */
-- pPager->xReiniter = xReinit;
-- /* memset(pPager->aHash, 0, sizeof(pPager->aHash)); */
-- /* pPager->szMmap = SQLITE_DEFAULT_MMAP_SIZE // will be set by btree.c */
-+}
-+#endif
-
-- *ppPager = pPager;
-- return SQLITE_OK;
-+/*
-+** The following global variable is incremented whenever the library
-+** attempts to open a temporary file. This information is used for
-+** testing and analysis only.
-+*/
-+#ifdef SQLITE_TEST
-+SQLITE_API int sqlite3_opentemp_count = 0;
-+#endif
-+
-+/*
-+** Open a temporary file.
-+**
-+** Write the file descriptor into *pFile. Return SQLITE_OK on success
-+** or some other error code if we fail. The OS will automatically
-+** delete the temporary file when it is closed.
-+**
-+** The flags passed to the VFS layer xOpen() call are those specified
-+** by parameter vfsFlags ORed with the following:
-+**
-+** SQLITE_OPEN_READWRITE
-+** SQLITE_OPEN_CREATE
-+** SQLITE_OPEN_EXCLUSIVE
-+** SQLITE_OPEN_DELETEONCLOSE
-+*/
-+static int pagerOpentemp(
-+ Pager *pPager, /* The pager object */
-+ sqlite3_file *pFile, /* Write the file descriptor here */
-+ int vfsFlags /* Flags passed through to the VFS */
-+){
-+ int rc; /* Return code */
-+
-+#ifdef SQLITE_TEST
-+ sqlite3_opentemp_count++; /* Used for testing and analysis only */
-+#endif
-+
-+ vfsFlags |= SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE |
-+ SQLITE_OPEN_EXCLUSIVE | SQLITE_OPEN_DELETEONCLOSE;
-+ rc = sqlite3OsOpen(pPager->pVfs, 0, pFile, vfsFlags, 0);
-+ assert( rc!=SQLITE_OK || isOpen(pFile) );
-+ return rc;
- }
-
-+/*
-+** Set the busy handler function.
-+**
-+** The pager invokes the busy-handler if sqlite3OsLock() returns
-+** SQLITE_BUSY when trying to upgrade from no-lock to a SHARED lock,
-+** or when trying to upgrade from a RESERVED lock to an EXCLUSIVE
-+** lock. It does *not* invoke the busy handler when upgrading from
-+** SHARED to RESERVED, or when upgrading from SHARED to EXCLUSIVE
-+** (which occurs during hot-journal rollback). Summary:
-+**
-+** Transition | Invokes xBusyHandler
-+** --------------------------------------------------------
-+** NO_LOCK -> SHARED_LOCK | Yes
-+** SHARED_LOCK -> RESERVED_LOCK | No
-+** SHARED_LOCK -> EXCLUSIVE_LOCK | No
-+** RESERVED_LOCK -> EXCLUSIVE_LOCK | Yes
-+**
-+** If the busy-handler callback returns non-zero, the lock is
-+** retried. If it returns zero, then the SQLITE_BUSY error is
-+** returned to the caller of the pager API function.
-+*/
-+SQLITE_PRIVATE void sqlite3PagerSetBusyhandler(
-+ Pager *pPager, /* Pager object */
-+ int (*xBusyHandler)(void *), /* Pointer to busy-handler function */
-+ void *pBusyHandlerArg /* Argument to pass to xBusyHandler */
-+){
-+ pPager->xBusyHandler = xBusyHandler;
-+ pPager->pBusyHandlerArg = pBusyHandlerArg;
-
-+ if( isOpen(pPager->fd) ){
-+ void **ap = (void **)&pPager->xBusyHandler;
-+ assert( ((int(*)(void *))(ap[0]))==xBusyHandler );
-+ assert( ap[1]==pBusyHandlerArg );
-+ sqlite3OsFileControlHint(pPager->fd, SQLITE_FCNTL_BUSYHANDLER, (void *)ap);
-+ }
-+}
-
- /*
--** This function is called after transitioning from PAGER_UNLOCK to
--** PAGER_SHARED state. It tests if there is a hot journal present in
--** the file-system for the given pager. A hot journal is one that
--** needs to be played back. According to this function, a hot-journal
--** file exists if the following criteria are met:
-+** Change the page size used by the Pager object. The new page size
-+** is passed in *pPageSize.
- **
--** * The journal file exists in the file system, and
--** * No process holds a RESERVED or greater lock on the database file, and
--** * The database file itself is greater than 0 bytes in size, and
--** * The first byte of the journal file exists and is not 0x00.
-+** If the pager is in the error state when this function is called, it
-+** is a no-op. The value returned is the error state error code (i.e.
-+** one of SQLITE_IOERR, an SQLITE_IOERR_xxx sub-code or SQLITE_FULL).
- **
--** If the current size of the database file is 0 but a journal file
--** exists, that is probably an old journal left over from a prior
--** database with the same name. In this case the journal file is
--** just deleted using OsDelete, *pExists is set to 0 and SQLITE_OK
--** is returned.
-+** Otherwise, if all of the following are true:
- **
--** This routine does not check if there is a master journal filename
--** at the end of the file. If there is, and that master journal file
--** does not exist, then the journal file is not really hot. In this
--** case this routine will return a false-positive. The pager_playback()
--** routine will discover that the journal file is not really hot and
--** will not roll it back.
-+** * the new page size (value of *pPageSize) is valid (a power
-+** of two between 512 and SQLITE_MAX_PAGE_SIZE, inclusive), and
- **
--** If a hot-journal file is found to exist, *pExists is set to 1 and
--** SQLITE_OK returned. If no hot-journal file is present, *pExists is
--** set to 0 and SQLITE_OK returned. If an IO error occurs while trying
--** to determine whether or not a hot-journal file exists, the IO error
--** code is returned and the value of *pExists is undefined.
-+** * there are no outstanding page references, and
-+**
-+** * the database is either not an in-memory database or it is
-+** an in-memory database that currently consists of zero pages.
-+**
-+** then the pager object page size is set to *pPageSize.
-+**
-+** If the page size is changed, then this function uses sqlite3PagerMalloc()
-+** to obtain a new Pager.pTmpSpace buffer. If this allocation attempt
-+** fails, SQLITE_NOMEM is returned and the page size remains unchanged.
-+** In all other cases, SQLITE_OK is returned.
-+**
-+** If the page size is not changed, either because one of the enumerated
-+** conditions above is not true, the pager was in error state when this
-+** function was called, or because the memory allocation attempt failed,
-+** then *pPageSize is set to the old, retained page size before returning.
- */
--static int hasHotJournal(Pager *pPager, int *pExists){
-- sqlite3_vfs * const pVfs = pPager->pVfs;
-- int rc = SQLITE_OK; /* Return code */
-- int exists = 1; /* True if a journal file is present */
-- int jrnlOpen = !!isOpen(pPager->jfd);
-+SQLITE_PRIVATE int sqlite3PagerSetPagesize(Pager *pPager, u32 *pPageSize, int nReserve){
-+ int rc = SQLITE_OK;
-
-- assert( pPager->useJournal );
-- assert( isOpen(pPager->fd) );
-- assert( pPager->eState==PAGER_OPEN );
-+ /* It is not possible to do a full assert_pager_state() here, as this
-+ ** function may be called from within PagerOpen(), before the state
-+ ** of the Pager object is internally consistent.
-+ **
-+ ** At one point this function returned an error if the pager was in
-+ ** PAGER_ERROR state. But since PAGER_ERROR state guarantees that
-+ ** there is at least one outstanding page reference, this function
-+ ** is a no-op for that case anyhow.
-+ */
-
-- assert( jrnlOpen==0 || ( sqlite3OsDeviceCharacteristics(pPager->jfd) &
-- SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN
-- ));
-+ u32 pageSize = *pPageSize;
-+ assert( pageSize==0 || (pageSize>=512 && pageSize<=SQLITE_MAX_PAGE_SIZE) );
-+ if( (pPager->memDb==0 || pPager->dbSize==0)
-+ && sqlite3PcacheRefCount(pPager->pPCache)==0
-+ && pageSize && pageSize!=(u32)pPager->pageSize
-+ ){
-+ char *pNew = NULL; /* New temp space */
-+ i64 nByte = 0;
-
-- *pExists = 0;
-- if( !jrnlOpen ){
-- rc = sqlite3OsAccess(pVfs, pPager->zJournal, SQLITE_ACCESS_EXISTS, &exists);
-+ if( pPager->eState>PAGER_OPEN && isOpen(pPager->fd) ){
-+ rc = sqlite3OsFileSize(pPager->fd, &nByte);
-+ }
-+ if( rc==SQLITE_OK ){
-+ pNew = (char *)sqlite3PageMalloc(pageSize);
-+ if( !pNew ) rc = SQLITE_NOMEM;
-+ }
-+
-+ if( rc==SQLITE_OK ){
-+ pager_reset(pPager);
-+ pPager->dbSize = (Pgno)((nByte+pageSize-1)/pageSize);
-+ pPager->pageSize = pageSize;
-+ sqlite3PageFree(pPager->pTmpSpace);
-+ pPager->pTmpSpace = pNew;
-+ sqlite3PcacheSetPageSize(pPager->pPCache, pageSize);
-+ }
- }
-- if( rc==SQLITE_OK && exists ){
-- int locked = 0; /* True if some process holds a RESERVED lock */
-
-- /* Race condition here: Another process might have been holding the
-- ** the RESERVED lock and have a journal open at the sqlite3OsAccess()
-- ** call above, but then delete the journal and drop the lock before
-- ** we get to the following sqlite3OsCheckReservedLock() call. If that
-- ** is the case, this routine might think there is a hot journal when
-- ** in fact there is none. This results in a false-positive which will
-- ** be dealt with by the playback routine. Ticket #3883.
-- */
-- rc = sqlite3OsCheckReservedLock(pPager->fd, &locked);
-- if( rc==SQLITE_OK && !locked ){
-- Pgno nPage; /* Number of pages in database file */
-+ *pPageSize = pPager->pageSize;
-+ if( rc==SQLITE_OK ){
-+ if( nReserve<0 ) nReserve = pPager->nReserve;
-+ assert( nReserve>=0 && nReserve<1000 );
-+ pPager->nReserve = (i16)nReserve;
-+ pagerReportSize(pPager);
-+ pagerFixMaplimit(pPager);
-+ }
-+ return rc;
-+}
-
-- /* Check the size of the database file. If it consists of 0 pages,
-- ** then delete the journal file. See the header comment above for
-- ** the reasoning here. Delete the obsolete journal file under
-- ** a RESERVED lock to avoid race conditions and to avoid violating
-- ** [H33020].
-- */
-- rc = pagerPagecount(pPager, &nPage);
-- if( rc==SQLITE_OK ){
-- if( nPage==0 ){
-- sqlite3BeginBenignMalloc();
-- if( pagerLockDb(pPager, RESERVED_LOCK)==SQLITE_OK ){
-- sqlite3OsDelete(pVfs, pPager->zJournal, 0);
-- if( !pPager->exclusiveMode ) pagerUnlockDb(pPager, SHARED_LOCK);
-- }
-- sqlite3EndBenignMalloc();
-- }else{
-- /* The journal file exists and no other connection has a reserved
-- ** or greater lock on the database file. Now check that there is
-- ** at least one non-zero bytes at the start of the journal file.
-- ** If there is, then we consider this journal to be hot. If not,
-- ** it can be ignored.
-- */
-- if( !jrnlOpen ){
-- int f = SQLITE_OPEN_READONLY|SQLITE_OPEN_MAIN_JOURNAL;
-- rc = sqlite3OsOpen(pVfs, pPager->zJournal, pPager->jfd, f, &f);
-- }
-- if( rc==SQLITE_OK ){
-- u8 first = 0;
-- rc = sqlite3OsRead(pPager->jfd, (void *)&first, 1, 0);
-- if( rc==SQLITE_IOERR_SHORT_READ ){
-- rc = SQLITE_OK;
-- }
-- if( !jrnlOpen ){
-- sqlite3OsClose(pPager->jfd);
-- }
-- *pExists = (first!=0);
-- }else if( rc==SQLITE_CANTOPEN ){
-- /* If we cannot open the rollback journal file in order to see if
-- ** its has a zero header, that might be due to an I/O error, or
-- ** it might be due to the race condition described above and in
-- ** ticket #3883. Either way, assume that the journal is hot.
-- ** This might be a false positive. But if it is, then the
-- ** automatic journal playback and recovery mechanism will deal
-- ** with it under an EXCLUSIVE lock where we do not need to
-- ** worry so much with race conditions.
-- */
-- *pExists = 1;
-- rc = SQLITE_OK;
-- }
-- }
-- }
-+/*
-+** Return a pointer to the "temporary page" buffer held internally
-+** by the pager. This is a buffer that is big enough to hold the
-+** entire content of a database page. This buffer is used internally
-+** during rollback and will be overwritten whenever a rollback
-+** occurs. But other modules are free to use it too, as long as
-+** no rollbacks are happening.
-+*/
-+SQLITE_PRIVATE void *sqlite3PagerTempSpace(Pager *pPager){
-+ return pPager->pTmpSpace;
-+}
-+
-+/*
-+** Attempt to set the maximum database page count if mxPage is positive.
-+** Make no changes if mxPage is zero or negative. And never reduce the
-+** maximum page count below the current size of the database.
-+**
-+** Regardless of mxPage, return the current maximum page count.
-+*/
-+SQLITE_PRIVATE int sqlite3PagerMaxPageCount(Pager *pPager, int mxPage){
-+ if( mxPage>0 ){
-+ pPager->mxPgno = mxPage;
-+ }
-+ assert( pPager->eState!=PAGER_OPEN ); /* Called only by OP_MaxPgcnt */
-+ assert( pPager->mxPgno>=pPager->dbSize ); /* OP_MaxPgcnt enforces this */
-+ return pPager->mxPgno;
-+}
-+
-+/*
-+** The following set of routines are used to disable the simulated
-+** I/O error mechanism. These routines are used to avoid simulated
-+** errors in places where we do not care about errors.
-+**
-+** Unless -DSQLITE_TEST=1 is used, these routines are all no-ops
-+** and generate no code.
-+*/
-+#ifdef SQLITE_TEST
-+SQLITE_API extern int sqlite3_io_error_pending;
-+SQLITE_API extern int sqlite3_io_error_hit;
-+static int saved_cnt;
-+void disable_simulated_io_errors(void){
-+ saved_cnt = sqlite3_io_error_pending;
-+ sqlite3_io_error_pending = -1;
-+}
-+void enable_simulated_io_errors(void){
-+ sqlite3_io_error_pending = saved_cnt;
-+}
-+#else
-+# define disable_simulated_io_errors()
-+# define enable_simulated_io_errors()
-+#endif
-+
-+/*
-+** Read the first N bytes from the beginning of the file into memory
-+** that pDest points to.
-+**
-+** If the pager was opened on a transient file (zFilename==""), or
-+** opened on a file less than N bytes in size, the output buffer is
-+** zeroed and SQLITE_OK returned. The rationale for this is that this
-+** function is used to read database headers, and a new transient or
-+** zero sized database has a header than consists entirely of zeroes.
-+**
-+** If any IO error apart from SQLITE_IOERR_SHORT_READ is encountered,
-+** the error code is returned to the caller and the contents of the
-+** output buffer undefined.
-+*/
-+SQLITE_PRIVATE int sqlite3PagerReadFileheader(Pager *pPager, int N, unsigned char *pDest){
-+ int rc = SQLITE_OK;
-+ memset(pDest, 0, N);
-+ assert( isOpen(pPager->fd) || pPager->tempFile );
-+
-+ /* This routine is only called by btree immediately after creating
-+ ** the Pager object. There has not been an opportunity to transition
-+ ** to WAL mode yet.
-+ */
-+ assert( !pagerUseWal(pPager) );
-+
-+ if( isOpen(pPager->fd) ){
-+ IOTRACE(("DBHDR %p 0 %d\n", pPager, N))
-+ rc = sqlite3OsRead(pPager->fd, pDest, N, 0);
-+ if( rc==SQLITE_IOERR_SHORT_READ ){
-+ rc = SQLITE_OK;
- }
- }
--
- return rc;
- }
-
- /*
--** This function is called to obtain a shared lock on the database file.
--** It is illegal to call sqlite3PagerAcquire() until after this function
--** has been successfully called. If a shared-lock is already held when
--** this function is called, it is a no-op.
--**
--** The following operations are also performed by this function.
-+** This function may only be called when a read-transaction is open on
-+** the pager. It returns the total number of pages in the database.
- **
--** 1) If the pager is currently in PAGER_OPEN state (no lock held
--** on the database file), then an attempt is made to obtain a
--** SHARED lock on the database file. Immediately after obtaining
--** the SHARED lock, the file-system is checked for a hot-journal,
--** which is played back if present. Following any hot-journal
--** rollback, the contents of the cache are validated by checking
--** the 'change-counter' field of the database file header and
--** discarded if they are found to be invalid.
-+** However, if the file is between 1 and <page-size> bytes in size, then
-+** this is considered a 1 page file.
-+*/
-+SQLITE_PRIVATE void sqlite3PagerPagecount(Pager *pPager, int *pnPage){
-+ assert( pPager->eState>=PAGER_READER );
-+ assert( pPager->eState!=PAGER_WRITER_FINISHED );
-+ *pnPage = (int)pPager->dbSize;
-+}
-+
-+
-+/*
-+** Try to obtain a lock of type locktype on the database file. If
-+** a similar or greater lock is already held, this function is a no-op
-+** (returning SQLITE_OK immediately).
- **
--** 2) If the pager is running in exclusive-mode, and there are currently
--** no outstanding references to any pages, and is in the error state,
--** then an attempt is made to clear the error state by discarding
--** the contents of the page cache and rolling back any open journal
--** file.
-+** Otherwise, attempt to obtain the lock using sqlite3OsLock(). Invoke
-+** the busy callback if the lock is currently not available. Repeat
-+** until the busy callback returns false or until the attempt to
-+** obtain the lock succeeds.
- **
--** If everything is successful, SQLITE_OK is returned. If an IO error
--** occurs while locking the database, checking for a hot-journal file or
--** rolling back a journal file, the IO error code is returned.
-+** Return SQLITE_OK on success and an error code if we cannot obtain
-+** the lock. If the lock is obtained successfully, set the Pager.state
-+** variable to locktype before returning.
- */
--SQLITE_PRIVATE int sqlite3PagerSharedLock(Pager *pPager){
-- int rc = SQLITE_OK; /* Return code */
-+static int pager_wait_on_lock(Pager *pPager, int locktype){
-+ int rc; /* Return code */
-
-- /* This routine is only called from b-tree and only when there are no
-- ** outstanding pages. This implies that the pager state should either
-- ** be OPEN or READER. READER is only possible if the pager is or was in
-- ** exclusive access mode.
-+ /* Check that this is either a no-op (because the requested lock is
-+ ** already held, or one of the transistions that the busy-handler
-+ ** may be invoked during, according to the comment above
-+ ** sqlite3PagerSetBusyhandler().
- */
-- assert( sqlite3PcacheRefCount(pPager->pPCache)==0 );
-- assert( assert_pager_state(pPager) );
-- assert( pPager->eState==PAGER_OPEN || pPager->eState==PAGER_READER );
-- if( NEVER(MEMDB && pPager->errCode) ){ return pPager->errCode; }
-+ assert( (pPager->eLock>=locktype)
-+ || (pPager->eLock==NO_LOCK && locktype==SHARED_LOCK)
-+ || (pPager->eLock==RESERVED_LOCK && locktype==EXCLUSIVE_LOCK)
-+ );
-
-- if( !pagerUseWal(pPager) && pPager->eState==PAGER_OPEN ){
-- int bHotJournal = 1; /* True if there exists a hot journal-file */
-+ do {
-+ rc = pagerLockDb(pPager, locktype);
-+ }while( rc==SQLITE_BUSY && pPager->xBusyHandler(pPager->pBusyHandlerArg) );
-+ return rc;
-+}
-
-- assert( !MEMDB );
-+/*
-+** Function assertTruncateConstraint(pPager) checks that one of the
-+** following is true for all dirty pages currently in the page-cache:
-+**
-+** a) The page number is less than or equal to the size of the
-+** current database image, in pages, OR
-+**
-+** b) if the page content were written at this time, it would not
-+** be necessary to write the current content out to the sub-journal
-+** (as determined by function subjRequiresPage()).
-+**
-+** If the condition asserted by this function were not true, and the
-+** dirty page were to be discarded from the cache via the pagerStress()
-+** routine, pagerStress() would not write the current page content to
-+** the database file. If a savepoint transaction were rolled back after
-+** this happened, the correct behavior would be to restore the current
-+** content of the page. However, since this content is not present in either
-+** the database file or the portion of the rollback journal and
-+** sub-journal rolled back the content could not be restored and the
-+** database image would become corrupt. It is therefore fortunate that
-+** this circumstance cannot arise.
-+*/
-+#if defined(SQLITE_DEBUG)
-+static void assertTruncateConstraintCb(PgHdr *pPg){
-+ assert( pPg->flags&PGHDR_DIRTY );
-+ assert( !subjRequiresPage(pPg) || pPg->pgno<=pPg->pPager->dbSize );
-+}
-+static void assertTruncateConstraint(Pager *pPager){
-+ sqlite3PcacheIterateDirty(pPager->pPCache, assertTruncateConstraintCb);
-+}
-+#else
-+# define assertTruncateConstraint(pPager)
-+#endif
-
-- rc = pager_wait_on_lock(pPager, SHARED_LOCK);
-- if( rc!=SQLITE_OK ){
-- assert( pPager->eLock==NO_LOCK || pPager->eLock==UNKNOWN_LOCK );
-- goto failed;
-- }
-+/*
-+** Truncate the in-memory database file image to nPage pages. This
-+** function does not actually modify the database file on disk. It
-+** just sets the internal state of the pager object so that the
-+** truncation will be done when the current transaction is committed.
-+**
-+** This function is only called right before committing a transaction.
-+** Once this function has been called, the transaction must either be
-+** rolled back or committed. It is not safe to call this function and
-+** then continue writing to the database.
-+*/
-+SQLITE_PRIVATE void sqlite3PagerTruncateImage(Pager *pPager, Pgno nPage){
-+ assert( pPager->dbSize>=nPage );
-+ assert( pPager->eState>=PAGER_WRITER_CACHEMOD );
-+ pPager->dbSize = nPage;
-
-- /* If a journal file exists, and there is no RESERVED lock on the
-- ** database file, then it either needs to be played back or deleted.
-- */
-- if( pPager->eLock<=SHARED_LOCK ){
-- rc = hasHotJournal(pPager, &bHotJournal);
-- }
-- if( rc!=SQLITE_OK ){
-- goto failed;
-- }
-- if( bHotJournal ){
-- if( pPager->readOnly ){
-- rc = SQLITE_READONLY_ROLLBACK;
-- goto failed;
-- }
-+ /* At one point the code here called assertTruncateConstraint() to
-+ ** ensure that all pages being truncated away by this operation are,
-+ ** if one or more savepoints are open, present in the savepoint
-+ ** journal so that they can be restored if the savepoint is rolled
-+ ** back. This is no longer necessary as this function is now only
-+ ** called right before committing a transaction. So although the
-+ ** Pager object may still have open savepoints (Pager.nSavepoint!=0),
-+ ** they cannot be rolled back. So the assertTruncateConstraint() call
-+ ** is no longer correct. */
-+}
-
-- /* Get an EXCLUSIVE lock on the database file. At this point it is
-- ** important that a RESERVED lock is not obtained on the way to the
-- ** EXCLUSIVE lock. If it were, another process might open the
-- ** database file, detect the RESERVED lock, and conclude that the
-- ** database is safe to read while this process is still rolling the
-- ** hot-journal back.
-- **
-- ** Because the intermediate RESERVED lock is not requested, any
-- ** other process attempting to access the database file will get to
-- ** this point in the code and fail to obtain its own EXCLUSIVE lock
-- ** on the database file.
-- **
-- ** Unless the pager is in locking_mode=exclusive mode, the lock is
-- ** downgraded to SHARED_LOCK before this function returns.
-- */
-- rc = pagerLockDb(pPager, EXCLUSIVE_LOCK);
-- if( rc!=SQLITE_OK ){
-- goto failed;
-- }
--
-- /* If it is not already open and the file exists on disk, open the
-- ** journal for read/write access. Write access is required because
-- ** in exclusive-access mode the file descriptor will be kept open
-- ** and possibly used for a transaction later on. Also, write-access
-- ** is usually required to finalize the journal in journal_mode=persist
-- ** mode (and also for journal_mode=truncate on some systems).
-- **
-- ** If the journal does not exist, it usually means that some
-- ** other connection managed to get in and roll it back before
-- ** this connection obtained the exclusive lock above. Or, it
-- ** may mean that the pager was in the error-state when this
-- ** function was called and the journal file does not exist.
-- */
-- if( !isOpen(pPager->jfd) ){
-- sqlite3_vfs * const pVfs = pPager->pVfs;
-- int bExists; /* True if journal file exists */
-- rc = sqlite3OsAccess(
-- pVfs, pPager->zJournal, SQLITE_ACCESS_EXISTS, &bExists);
-- if( rc==SQLITE_OK && bExists ){
-- int fout = 0;
-- int f = SQLITE_OPEN_READWRITE|SQLITE_OPEN_MAIN_JOURNAL;
-- assert( !pPager->tempFile );
-- rc = sqlite3OsOpen(pVfs, pPager->zJournal, pPager->jfd, f, &fout);
-- assert( rc!=SQLITE_OK || isOpen(pPager->jfd) );
-- if( rc==SQLITE_OK && fout&SQLITE_OPEN_READONLY ){
-- rc = SQLITE_CANTOPEN_BKPT;
-- sqlite3OsClose(pPager->jfd);
-- }
-- }
-- }
--
-- /* Playback and delete the journal. Drop the database write
-- ** lock and reacquire the read lock. Purge the cache before
-- ** playing back the hot-journal so that we don't end up with
-- ** an inconsistent cache. Sync the hot journal before playing
-- ** it back since the process that crashed and left the hot journal
-- ** probably did not sync it and we are required to always sync
-- ** the journal before playing it back.
-- */
-- if( isOpen(pPager->jfd) ){
-- assert( rc==SQLITE_OK );
-- rc = pagerSyncHotJournal(pPager);
-- if( rc==SQLITE_OK ){
-- rc = pager_playback(pPager, 1);
-- pPager->eState = PAGER_OPEN;
-- }
-- }else if( !pPager->exclusiveMode ){
-- pagerUnlockDb(pPager, SHARED_LOCK);
-- }
-
-- if( rc!=SQLITE_OK ){
-- /* This branch is taken if an error occurs while trying to open
-- ** or roll back a hot-journal while holding an EXCLUSIVE lock. The
-- ** pager_unlock() routine will be called before returning to unlock
-- ** the file. If the unlock attempt fails, then Pager.eLock must be
-- ** set to UNKNOWN_LOCK (see the comment above the #define for
-- ** UNKNOWN_LOCK above for an explanation).
-- **
-- ** In order to get pager_unlock() to do this, set Pager.eState to
-- ** PAGER_ERROR now. This is not actually counted as a transition
-- ** to ERROR state in the state diagram at the top of this file,
-- ** since we know that the same call to pager_unlock() will very
-- ** shortly transition the pager object to the OPEN state. Calling
-- ** assert_pager_state() would fail now, as it should not be possible
-- ** to be in ERROR state when there are zero outstanding page
-- ** references.
-- */
-- pager_error(pPager, rc);
-- goto failed;
-- }
-+/*
-+** This function is called before attempting a hot-journal rollback. It
-+** syncs the journal file to disk, then sets pPager->journalHdr to the
-+** size of the journal file so that the pager_playback() routine knows
-+** that the entire journal file has been synced.
-+**
-+** Syncing a hot-journal to disk before attempting to roll it back ensures
-+** that if a power-failure occurs during the rollback, the process that
-+** attempts rollback following system recovery sees the same journal
-+** content as this process.
-+**
-+** If everything goes as planned, SQLITE_OK is returned. Otherwise,
-+** an SQLite error code.
-+*/
-+static int pagerSyncHotJournal(Pager *pPager){
-+ int rc = SQLITE_OK;
-+ if( !pPager->noSync ){
-+ rc = sqlite3OsSync(pPager->jfd, SQLITE_SYNC_NORMAL);
-+ }
-+ if( rc==SQLITE_OK ){
-+ rc = sqlite3OsFileSize(pPager->jfd, &pPager->journalHdr);
-+ }
-+ return rc;
-+}
-
-- assert( pPager->eState==PAGER_OPEN );
-- assert( (pPager->eLock==SHARED_LOCK)
-- || (pPager->exclusiveMode && pPager->eLock>SHARED_LOCK)
-- );
-+/*
-+** Obtain a reference to a memory mapped page object for page number pgno.
-+** The new object will use the pointer pData, obtained from xFetch().
-+** If successful, set *ppPage to point to the new page reference
-+** and return SQLITE_OK. Otherwise, return an SQLite error code and set
-+** *ppPage to zero.
-+**
-+** Page references obtained by calling this function should be released
-+** by calling pagerReleaseMapPage().
-+*/
-+static int pagerAcquireMapPage(
-+ Pager *pPager, /* Pager object */
-+ Pgno pgno, /* Page number */
-+ void *pData, /* xFetch()'d data for this page */
-+ PgHdr **ppPage /* OUT: Acquired page object */
-+){
-+ PgHdr *p; /* Memory mapped page to return */
-+
-+ if( pPager->pMmapFreelist ){
-+ *ppPage = p = pPager->pMmapFreelist;
-+ pPager->pMmapFreelist = p->pDirty;
-+ p->pDirty = 0;
-+ memset(p->pExtra, 0, pPager->nExtra);
-+ }else{
-+ *ppPage = p = (PgHdr *)sqlite3MallocZero(sizeof(PgHdr) + pPager->nExtra);
-+ if( p==0 ){
-+ sqlite3OsUnfetch(pPager->fd, (i64)(pgno-1) * pPager->pageSize, pData);
-+ return SQLITE_NOMEM;
- }
-+ p->pExtra = (void *)&p[1];
-+ p->flags = PGHDR_MMAP;
-+ p->nRef = 1;
-+ p->pPager = pPager;
-+ }
-
-- if( !pPager->tempFile && (
-- pPager->pBackup
-- || sqlite3PcachePagecount(pPager->pPCache)>0
-- || USEFETCH(pPager)
-- )){
-- /* The shared-lock has just been acquired on the database file
-- ** and there are already pages in the cache (from a previous
-- ** read or write transaction). Check to see if the database
-- ** has been modified. If the database has changed, flush the
-- ** cache.
-- **
-- ** Database changes is detected by looking at 15 bytes beginning
-- ** at offset 24 into the file. The first 4 of these 16 bytes are
-- ** a 32-bit counter that is incremented with each change. The
-- ** other bytes change randomly with each file change when
-- ** a codec is in use.
-- **
-- ** There is a vanishingly small chance that a change will not be
-- ** detected. The chance of an undetected change is so small that
-- ** it can be neglected.
-- */
-- Pgno nPage = 0;
-- char dbFileVers[sizeof(pPager->dbFileVers)];
-+ assert( p->pExtra==(void *)&p[1] );
-+ assert( p->pPage==0 );
-+ assert( p->flags==PGHDR_MMAP );
-+ assert( p->pPager==pPager );
-+ assert( p->nRef==1 );
-
-- rc = pagerPagecount(pPager, &nPage);
-- if( rc ) goto failed;
-+ p->pgno = pgno;
-+ p->pData = pData;
-+ pPager->nMmapOut++;
-
-- if( nPage>0 ){
-- IOTRACE(("CKVERS %p %d\n", pPager, sizeof(dbFileVers)));
-- rc = sqlite3OsRead(pPager->fd, &dbFileVers, sizeof(dbFileVers), 24);
-- if( rc!=SQLITE_OK && rc!=SQLITE_IOERR_SHORT_READ ){
-- goto failed;
-- }
-- }else{
-- memset(dbFileVers, 0, sizeof(dbFileVers));
-- }
-+ return SQLITE_OK;
-+}
-
-- if( memcmp(pPager->dbFileVers, dbFileVers, sizeof(dbFileVers))!=0 ){
-- pager_reset(pPager);
-+/*
-+** Release a reference to page pPg. pPg must have been returned by an
-+** earlier call to pagerAcquireMapPage().
-+*/
-+static void pagerReleaseMapPage(PgHdr *pPg){
-+ Pager *pPager = pPg->pPager;
-+ pPager->nMmapOut--;
-+ pPg->pDirty = pPager->pMmapFreelist;
-+ pPager->pMmapFreelist = pPg;
-
-- /* Unmap the database file. It is possible that external processes
-- ** may have truncated the database file and then extended it back
-- ** to its original size while this process was not holding a lock.
-- ** In this case there may exist a Pager.pMap mapping that appears
-- ** to be the right size but is not actually valid. Avoid this
-- ** possibility by unmapping the db here. */
-- if( USEFETCH(pPager) ){
-- sqlite3OsUnfetch(pPager->fd, 0, 0);
-- }
-- }
-- }
-+ assert( pPager->fd->pMethods->iVersion>=3 );
-+ sqlite3OsUnfetch(pPager->fd, (i64)(pPg->pgno-1)*pPager->pageSize, pPg->pData);
-+}
-
-- /* If there is a WAL file in the file-system, open this database in WAL
-- ** mode. Otherwise, the following function call is a no-op.
-- */
-- rc = pagerOpenWalIfPresent(pPager);
--#ifndef SQLITE_OMIT_WAL
-- assert( pPager->pWal==0 || rc==SQLITE_OK );
--#endif
-+/*
-+** Free all PgHdr objects stored in the Pager.pMmapFreelist list.
-+*/
-+static void pagerFreeMapHdrs(Pager *pPager){
-+ PgHdr *p;
-+ PgHdr *pNext;
-+ for(p=pPager->pMmapFreelist; p; p=pNext){
-+ pNext = p->pDirty;
-+ sqlite3_free(p);
- }
-+}
-
-- if( pagerUseWal(pPager) ){
-- assert( rc==SQLITE_OK );
-- rc = pagerBeginReadTransaction(pPager);
-- }
-
-- if( pPager->eState==PAGER_OPEN && rc==SQLITE_OK ){
-- rc = pagerPagecount(pPager, &pPager->dbSize);
-- }
-+/*
-+** Shutdown the page cache. Free all memory and close all files.
-+**
-+** If a transaction was in progress when this routine is called, that
-+** transaction is rolled back. All outstanding pages are invalidated
-+** and their memory is freed. Any attempt to use a page associated
-+** with this page cache after this function returns will likely
-+** result in a coredump.
-+**
-+** This function always succeeds. If a transaction is active an attempt
-+** is made to roll it back. If an error occurs during the rollback
-+** a hot journal may be left in the filesystem but no error is returned
-+** to the caller.
-+*/
-+SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager){
-+ u8 *pTmp = (u8 *)pPager->pTmpSpace;
-
-- failed:
-- if( rc!=SQLITE_OK ){
-- assert( !MEMDB );
-+ assert( assert_pager_state(pPager) );
-+ disable_simulated_io_errors();
-+ sqlite3BeginBenignMalloc();
-+ pagerFreeMapHdrs(pPager);
-+ /* pPager->errCode = 0; */
-+ pPager->exclusiveMode = 0;
-+#ifndef SQLITE_OMIT_WAL
-+ sqlite3WalClose(pPager->pWal, pPager->ckptSyncFlags, pPager->pageSize, pTmp);
-+ pPager->pWal = 0;
-+#endif
-+ pager_reset(pPager);
-+ if( MEMDB ){
- pager_unlock(pPager);
-- assert( pPager->eState==PAGER_OPEN );
- }else{
-- pPager->eState = PAGER_READER;
-+ /* If it is open, sync the journal file before calling UnlockAndRollback.
-+ ** If this is not done, then an unsynced portion of the open journal
-+ ** file may be played back into the database. If a power failure occurs
-+ ** while this is happening, the database could become corrupt.
-+ **
-+ ** If an error occurs while trying to sync the journal, shift the pager
-+ ** into the ERROR state. This causes UnlockAndRollback to unlock the
-+ ** database and close the journal file without attempting to roll it
-+ ** back or finalize it. The next database user will have to do hot-journal
-+ ** rollback before accessing the database file.
-+ */
-+ if( isOpen(pPager->jfd) ){
-+ pager_error(pPager, pagerSyncHotJournal(pPager));
-+ }
-+ pagerUnlockAndRollback(pPager);
- }
-- return rc;
-+ sqlite3EndBenignMalloc();
-+ enable_simulated_io_errors();
-+ PAGERTRACE(("CLOSE %d\n", PAGERID(pPager)));
-+ IOTRACE(("CLOSE %p\n", pPager))
-+ sqlite3OsClose(pPager->jfd);
-+ sqlite3OsClose(pPager->fd);
-+ sqlite3PageFree(pTmp);
-+ sqlite3PcacheClose(pPager->pPCache);
+-#endif /* SQLITE_OMIT_DISKIO */
++#endif /* SQLITE_OMIT_DISKIO */
+
++/* BEGIN SQLCIPHER */
+#ifdef SQLITE_HAS_CODEC
-+ if( pPager->xCodecFree ) pPager->xCodecFree(pPager->pCodec);
-+#endif
-+
-+ assert( !pPager->aSavepoint && !pPager->pInJournal );
-+ assert( !isOpen(pPager->jfd) && !isOpen(pPager->sjfd) );
-+
-+ sqlite3_free(pPager);
-+ return SQLITE_OK;
- }
-
-+#if !defined(NDEBUG) || defined(SQLITE_TEST)
- /*
--** If the reference count has reached zero, rollback any active
--** transaction and unlock the pager.
--**
--** Except, in locking_mode=EXCLUSIVE when there is nothing to in
--** the rollback journal, the unlock is not performed and there is
--** nothing to rollback, so this routine is a no-op.
--*/
--static void pagerUnlockIfUnused(Pager *pPager){
-- if( pPager->nMmapOut==0 && (sqlite3PcacheRefCount(pPager->pPCache)==0) ){
-- pagerUnlockAndRollback(pPager);
-- }
-+** Return the page number for page pPg.
-+*/
-+SQLITE_PRIVATE Pgno sqlite3PagerPagenumber(DbPage *pPg){
-+ return pPg->pgno;
- }
-+#endif
-
- /*
--** Acquire a reference to page number pgno in pager pPager (a page
--** reference has type DbPage*). If the requested reference is
--** successfully obtained, it is copied to *ppPage and SQLITE_OK returned.
--**
--** If the requested page is already in the cache, it is returned.
--** Otherwise, a new page object is allocated and populated with data
--** read from the database file. In some cases, the pcache module may
--** choose not to allocate a new page object and may reuse an existing
--** object with no outstanding references.
--**
--** The extra data appended to a page is always initialized to zeros the
--** first time a page is loaded into memory. If the page requested is
--** already in the cache when this function is called, then the extra
--** data is left as it was when the page object was last used.
--**
--** If the database image is smaller than the requested page or if a
--** non-zero value is passed as the noContent parameter and the
--** requested page is not already stored in the cache, then no
--** actual disk read occurs. In this case the memory image of the
--** page is initialized to all zeros.
-+** Increment the reference count for page pPg.
-+*/
-+SQLITE_PRIVATE void sqlite3PagerRef(DbPage *pPg){
-+ sqlite3PcacheRef(pPg);
++SQLITE_PRIVATE void sqlite3pager_get_codec(Pager *pPager, void **ctx) {
++ *ctx = pPager->pCodec;
+}
+
-+/*
-+** Sync the journal. In other words, make sure all the pages that have
-+** been written to the journal have actually reached the surface of the
-+** disk and can be restored in the event of a hot-journal rollback.
- **
--** If noContent is true, it means that we do not care about the contents
--** of the page. This occurs in two seperate scenarios:
-+** If the Pager.noSync flag is set, then this function is a no-op.
-+** Otherwise, the actions required depend on the journal-mode and the
-+** device characteristics of the file-system, as follows:
- **
--** a) When reading a free-list leaf page from the database, and
-+** * If the journal file is an in-memory journal file, no action need
-+** be taken.
- **
--** b) When a savepoint is being rolled back and we need to load
--** a new page into the cache to be filled with the data read
--** from the savepoint journal.
-+** * Otherwise, if the device does not support the SAFE_APPEND property,
-+** then the nRec field of the most recently written journal header
-+** is updated to contain the number of journal records that have
-+** been written following it. If the pager is operating in full-sync
-+** mode, then the journal file is synced before this field is updated.
- **
--** If noContent is true, then the data returned is zeroed instead of
--** being read from the database. Additionally, the bits corresponding
--** to pgno in Pager.pInJournal (bitvec of pages already written to the
--** journal file) and the PagerSavepoint.pInSavepoint bitvecs of any open
--** savepoints are set. This means if the page is made writable at any
--** point in the future, using a call to sqlite3PagerWrite(), its contents
--** will not be journaled. This saves IO.
-+** * If the device does not support the SEQUENTIAL property, then
-+** journal file is synced.
- **
--** The acquisition might fail for several reasons. In all cases,
--** an appropriate error code is returned and *ppPage is set to NULL.
-+** Or, in pseudo-code:
- **
--** See also sqlite3PagerLookup(). Both this routine and Lookup() attempt
--** to find a page in the in-memory cache first. If the page is not already
--** in memory, this routine goes to disk to read it in whereas Lookup()
--** just returns 0. This routine acquires a read-lock the first time it
--** has to go to disk, and could also playback an old journal if necessary.
--** Since Lookup() never goes to disk, it never has to deal with locks
--** or journal files.
-+** if( NOT <in-memory journal> ){
-+** if( NOT SAFE_APPEND ){
-+** if( <full-sync mode> ) xSync(<journal file>);
-+** <update nRec field>
-+** }
-+** if( NOT SEQUENTIAL ) xSync(<journal file>);
-+** }
-+**
-+** If successful, this routine clears the PGHDR_NEED_SYNC flag of every
-+** page currently held in memory before returning SQLITE_OK. If an IO
-+** error is encountered, then the IO error code is returned to the caller.
- */
--SQLITE_PRIVATE int sqlite3PagerAcquire(
-- Pager *pPager, /* The pager open on the database file */
-- Pgno pgno, /* Page number to fetch */
-- DbPage **ppPage, /* Write a pointer to the page here */
-- int flags /* PAGER_ACQUIRE_XXX flags */
--){
-- int rc = SQLITE_OK;
-- PgHdr *pPg = 0;
-- u32 iFrame = 0; /* Frame to read from WAL file */
-- const int noContent = (flags & PAGER_ACQUIRE_NOCONTENT);
-+static int syncJournal(Pager *pPager, int newHdr){
-+ int rc; /* Return code */
-
-- /* It is acceptable to use a read-only (mmap) page for any page except
-- ** page 1 if there is no write-transaction open or the ACQUIRE_READONLY
-- ** flag was specified by the caller. And so long as the db is not a
-- ** temporary or in-memory database. */
-- const int bMmapOk = (pgno!=1 && USEFETCH(pPager)
-- && (pPager->eState==PAGER_READER || (flags & PAGER_ACQUIRE_READONLY))
--#ifdef SQLITE_HAS_CODEC
-- && pPager->xCodec==0
--#endif
-+ assert( pPager->eState==PAGER_WRITER_CACHEMOD
-+ || pPager->eState==PAGER_WRITER_DBMOD
- );
--
-- assert( pPager->eState>=PAGER_READER );
- assert( assert_pager_state(pPager) );
-- assert( noContent==0 || bMmapOk==0 );
--
-- if( pgno==0 ){
-- return SQLITE_CORRUPT_BKPT;
-- }
-+ assert( !pagerUseWal(pPager) );
-
-- /* If the pager is in the error state, return an error immediately.
-- ** Otherwise, request the page from the PCache layer. */
-- if( pPager->errCode!=SQLITE_OK ){
-- rc = pPager->errCode;
-- }else{
-+ rc = sqlite3PagerExclusiveLock(pPager);
-+ if( rc!=SQLITE_OK ) return rc;
-
-- if( bMmapOk && pagerUseWal(pPager) ){
-- rc = sqlite3WalFindFrame(pPager->pWal, pgno, &iFrame);
-- if( rc!=SQLITE_OK ) goto pager_acquire_err;
-- }
-+ if( !pPager->noSync ){
-+ assert( !pPager->tempFile );
-+ if( isOpen(pPager->jfd) && pPager->journalMode!=PAGER_JOURNALMODE_MEMORY ){
-+ const int iDc = sqlite3OsDeviceCharacteristics(pPager->fd);
-+ assert( isOpen(pPager->jfd) );
-
-- if( iFrame==0 && bMmapOk ){
-- void *pData = 0;
-+ if( 0==(iDc&SQLITE_IOCAP_SAFE_APPEND) ){
-+ /* This block deals with an obscure problem. If the last connection
-+ ** that wrote to this database was operating in persistent-journal
-+ ** mode, then the journal file may at this point actually be larger
-+ ** than Pager.journalOff bytes. If the next thing in the journal
-+ ** file happens to be a journal-header (written as part of the
-+ ** previous connection's transaction), and a crash or power-failure
-+ ** occurs after nRec is updated but before this connection writes
-+ ** anything else to the journal file (or commits/rolls back its
-+ ** transaction), then SQLite may become confused when doing the
-+ ** hot-journal rollback following recovery. It may roll back all
-+ ** of this connections data, then proceed to rolling back the old,
-+ ** out-of-date data that follows it. Database corruption.
-+ **
-+ ** To work around this, if the journal file does appear to contain
-+ ** a valid header following Pager.journalOff, then write a 0x00
-+ ** byte to the start of it to prevent it from being recognized.
-+ **
-+ ** Variable iNextHdrOffset is set to the offset at which this
-+ ** problematic header will occur, if it exists. aMagic is used
-+ ** as a temporary buffer to inspect the first couple of bytes of
-+ ** the potential journal header.
-+ */
-+ i64 iNextHdrOffset;
-+ u8 aMagic[8];
-+ u8 zHeader[sizeof(aJournalMagic)+4];
-
-- rc = sqlite3OsFetch(pPager->fd,
-- (i64)(pgno-1) * pPager->pageSize, pPager->pageSize, &pData
-- );
-+ memcpy(zHeader, aJournalMagic, sizeof(aJournalMagic));
-+ put32bits(&zHeader[sizeof(aJournalMagic)], pPager->nRec);
-
-- if( rc==SQLITE_OK && pData ){
-- if( pPager->eState>PAGER_READER ){
-- (void)sqlite3PcacheFetch(pPager->pPCache, pgno, 0, &pPg);
-+ iNextHdrOffset = journalHdrOffset(pPager);
-+ rc = sqlite3OsRead(pPager->jfd, aMagic, 8, iNextHdrOffset);
-+ if( rc==SQLITE_OK && 0==memcmp(aMagic, aJournalMagic, 8) ){
-+ static const u8 zerobyte = 0;
-+ rc = sqlite3OsWrite(pPager->jfd, &zerobyte, 1, iNextHdrOffset);
- }
-- if( pPg==0 ){
-- rc = pagerAcquireMapPage(pPager, pgno, pData, &pPg);
-- }else{
-- sqlite3OsUnfetch(pPager->fd, (i64)(pgno-1)*pPager->pageSize, pData);
-+ if( rc!=SQLITE_OK && rc!=SQLITE_IOERR_SHORT_READ ){
-+ return rc;
- }
-- if( pPg ){
-- assert( rc==SQLITE_OK );
-- *ppPage = pPg;
-- return SQLITE_OK;
-+
-+ /* Write the nRec value into the journal file header. If in
-+ ** full-synchronous mode, sync the journal first. This ensures that
-+ ** all data has really hit the disk before nRec is updated to mark
-+ ** it as a candidate for rollback.
-+ **
-+ ** This is not required if the persistent media supports the
-+ ** SAFE_APPEND property. Because in this case it is not possible
-+ ** for garbage data to be appended to the file, the nRec field
-+ ** is populated with 0xFFFFFFFF when the journal header is written
-+ ** and never needs to be updated.
-+ */
-+ if( pPager->fullSync && 0==(iDc&SQLITE_IOCAP_SEQUENTIAL) ){
-+ PAGERTRACE(("SYNC journal of %d\n", PAGERID(pPager)));
-+ IOTRACE(("JSYNC %p\n", pPager))
-+ rc = sqlite3OsSync(pPager->jfd, pPager->syncFlags);
-+ if( rc!=SQLITE_OK ) return rc;
- }
-+ IOTRACE(("JHDR %p %lld\n", pPager, pPager->journalHdr));
-+ rc = sqlite3OsWrite(
-+ pPager->jfd, zHeader, sizeof(zHeader), pPager->journalHdr
-+ );
-+ if( rc!=SQLITE_OK ) return rc;
- }
-- if( rc!=SQLITE_OK ){
-- goto pager_acquire_err;
-+ if( 0==(iDc&SQLITE_IOCAP_SEQUENTIAL) ){
-+ PAGERTRACE(("SYNC journal of %d\n", PAGERID(pPager)));
-+ IOTRACE(("JSYNC %p\n", pPager))
-+ rc = sqlite3OsSync(pPager->jfd, pPager->syncFlags|
-+ (pPager->syncFlags==SQLITE_SYNC_FULL?SQLITE_SYNC_DATAONLY:0)
-+ );
-+ if( rc!=SQLITE_OK ) return rc;
-+ }
-+
-+ pPager->journalHdr = pPager->journalOff;
-+ if( newHdr && 0==(iDc&SQLITE_IOCAP_SAFE_APPEND) ){
-+ pPager->nRec = 0;
-+ rc = writeJournalHdr(pPager);
-+ if( rc!=SQLITE_OK ) return rc;
- }
-+ }else{
-+ pPager->journalHdr = pPager->journalOff;
- }
-+ }
-
-- rc = sqlite3PcacheFetch(pPager->pPCache, pgno, 1, ppPage);
-+ /* Unless the pager is in noSync mode, the journal file was just
-+ ** successfully synced. Either way, clear the PGHDR_NEED_SYNC flag on
-+ ** all pages.
-+ */
-+ sqlite3PcacheClearSyncFlags(pPager->pPCache);
-+ pPager->eState = PAGER_WRITER_DBMOD;
-+ assert( assert_pager_state(pPager) );
-+ return SQLITE_OK;
++SQLITE_PRIVATE int sqlite3pager_is_mj_pgno(Pager *pPager, Pgno pgno) {
++ return (PAGER_MJ_PGNO(pPager) == pgno) ? 1 : 0;
+}
+
-+/*
-+** The argument is the first in a linked list of dirty pages connected
-+** by the PgHdr.pDirty pointer. This function writes each one of the
-+** in-memory pages in the list to the database file. The argument may
-+** be NULL, representing an empty list. In this case this function is
-+** a no-op.
-+**
-+** The pager must hold at least a RESERVED lock when this function
-+** is called. Before writing anything to the database file, this lock
-+** is upgraded to an EXCLUSIVE lock. If the lock cannot be obtained,
-+** SQLITE_BUSY is returned and no data is written to the database file.
-+**
-+** If the pager is a temp-file pager and the actual file-system file
-+** is not yet open, it is created and opened before any data is
-+** written out.
-+**
-+** Once the lock has been upgraded and, if necessary, the file opened,
-+** the pages are written out to the database file in list order. Writing
-+** a page is skipped if it meets either of the following criteria:
-+**
-+** * The page number is greater than Pager.dbSize, or
-+** * The PGHDR_DONT_WRITE flag is set on the page.
-+**
-+** If writing out a page causes the database file to grow, Pager.dbFileSize
-+** is updated accordingly. If page 1 is written out, then the value cached
-+** in Pager.dbFileVers[] is updated to match the new value stored in
-+** the database file.
-+**
-+** If everything is successful, SQLITE_OK is returned. If an IO error
-+** occurs, an IO error code is returned. Or, if the EXCLUSIVE lock cannot
-+** be obtained, SQLITE_BUSY is returned.
-+*/
-+static int pager_write_pagelist(Pager *pPager, PgHdr *pList){
-+ int rc = SQLITE_OK; /* Return code */
-+
-+ /* This function is only called for rollback pagers in WRITER_DBMOD state. */
-+ assert( !pagerUseWal(pPager) );
-+ assert( pPager->eState==PAGER_WRITER_DBMOD );
-+ assert( pPager->eLock==EXCLUSIVE_LOCK );
-+
-+ /* If the file is a temp-file has not yet been opened, open it now. It
-+ ** is not possible for rc to be other than SQLITE_OK if this branch
-+ ** is taken, as pager_wait_on_lock() is a no-op for temp-files.
-+ */
-+ if( !isOpen(pPager->fd) ){
-+ assert( pPager->tempFile && rc==SQLITE_OK );
-+ rc = pagerOpentemp(pPager, pPager->fd, pPager->vfsFlags);
- }
-
-- if( rc!=SQLITE_OK ){
-- /* Either the call to sqlite3PcacheFetch() returned an error or the
-- ** pager was already in the error-state when this function was called.
-- ** Set pPg to 0 and jump to the exception handler. */
-- pPg = 0;
-- goto pager_acquire_err;
-+ /* Before the first write, give the VFS a hint of what the final
-+ ** file size will be.
-+ */
-+ assert( rc!=SQLITE_OK || isOpen(pPager->fd) );
-+ if( rc==SQLITE_OK
-+ && (pList->pDirty ? pPager->dbSize : pList->pgno+1)>pPager->dbHintSize
-+ ){
-+ sqlite3_int64 szFile = pPager->pageSize * (sqlite3_int64)pPager->dbSize;
-+ sqlite3OsFileControlHint(pPager->fd, SQLITE_FCNTL_SIZE_HINT, &szFile);
-+ pPager->dbHintSize = pPager->dbSize;
- }
-- assert( (*ppPage)->pgno==pgno );
-- assert( (*ppPage)->pPager==pPager || (*ppPage)->pPager==0 );
-
-- if( (*ppPage)->pPager && !noContent ){
-- /* In this case the pcache already contains an initialized copy of
-- ** the page. Return without further ado. */
-- assert( pgno<=PAGER_MAX_PGNO && pgno!=PAGER_MJ_PGNO(pPager) );
-- pPager->aStat[PAGER_STAT_HIT]++;
-- return SQLITE_OK;
-+ while( rc==SQLITE_OK && pList ){
-+ Pgno pgno = pList->pgno;
-
-- }else{
-- /* The pager cache has created a new page. Its content needs to
-- ** be initialized. */
-+ /* If there are dirty pages in the page cache with page numbers greater
-+ ** than Pager.dbSize, this means sqlite3PagerTruncateImage() was called to
-+ ** make the file smaller (presumably by auto-vacuum code). Do not write
-+ ** any such pages to the file.
-+ **
-+ ** Also, do not write out any page that has the PGHDR_DONT_WRITE flag
-+ ** set (set by sqlite3PagerDontWrite()).
-+ */
-+ if( pgno<=pPager->dbSize && 0==(pList->flags&PGHDR_DONT_WRITE) ){
-+ i64 offset = (pgno-1)*(i64)pPager->pageSize; /* Offset to write */
-+ char *pData; /* Data to write */
-
-- pPg = *ppPage;
-- pPg->pPager = pPager;
-+ assert( (pList->flags&PGHDR_NEED_SYNC)==0 );
-+ if( pList->pgno==1 ) pager_write_changecounter(pList);
-
-- /* The maximum page number is 2^31. Return SQLITE_CORRUPT if a page
-- ** number greater than this, or the unused locking-page, is requested. */
-- if( pgno>PAGER_MAX_PGNO || pgno==PAGER_MJ_PGNO(pPager) ){
-- rc = SQLITE_CORRUPT_BKPT;
-- goto pager_acquire_err;
-- }
-+ /* Encode the database */
-+ CODEC2(pPager, pList->pData, pgno, 6, return SQLITE_NOMEM, pData);
-
-- if( MEMDB || pPager->dbSize<pgno || noContent || !isOpen(pPager->fd) ){
-- if( pgno>pPager->mxPgno ){
-- rc = SQLITE_FULL;
-- goto pager_acquire_err;
-- }
-- if( noContent ){
-- /* Failure to set the bits in the InJournal bit-vectors is benign.
-- ** It merely means that we might do some extra work to journal a
-- ** page that does not need to be journaled. Nevertheless, be sure
-- ** to test the case where a malloc error occurs while trying to set
-- ** a bit in a bit vector.
-- */
-- sqlite3BeginBenignMalloc();
-- if( pgno<=pPager->dbOrigSize ){
-- TESTONLY( rc = ) sqlite3BitvecSet(pPager->pInJournal, pgno);
-- testcase( rc==SQLITE_NOMEM );
-- }
-- TESTONLY( rc = ) addToSavepointBitvecs(pPager, pgno);
-- testcase( rc==SQLITE_NOMEM );
-- sqlite3EndBenignMalloc();
-- }
-- memset(pPg->pData, 0, pPager->pageSize);
-- IOTRACE(("ZERO %p %d\n", pPager, pgno));
-- }else{
-- if( pagerUseWal(pPager) && bMmapOk==0 ){
-- rc = sqlite3WalFindFrame(pPager->pWal, pgno, &iFrame);
-- if( rc!=SQLITE_OK ) goto pager_acquire_err;
-+ /* Write out the page data. */
-+ rc = sqlite3OsWrite(pPager->fd, pData, pPager->pageSize, offset);
-+
-+ /* If page 1 was just written, update Pager.dbFileVers to match
-+ ** the value now stored in the database file. If writing this
-+ ** page caused the database file to grow, update dbFileSize.
-+ */
-+ if( pgno==1 ){
-+ memcpy(&pPager->dbFileVers, &pData[24], sizeof(pPager->dbFileVers));
- }
-- assert( pPg->pPager==pPager );
-- pPager->aStat[PAGER_STAT_MISS]++;
-- rc = readDbPage(pPg, iFrame);
-- if( rc!=SQLITE_OK ){
-- goto pager_acquire_err;
-+ if( pgno>pPager->dbFileSize ){
-+ pPager->dbFileSize = pgno;
- }
-- }
-- pager_set_pagehash(pPg);
-- }
-+ pPager->aStat[PAGER_STAT_WRITE]++;
-
-- return SQLITE_OK;
-+ /* Update any backup objects copying the contents of this pager. */
-+ sqlite3BackupUpdate(pPager->pBackup, pgno, (u8*)pList->pData);
-
--pager_acquire_err:
-- assert( rc!=SQLITE_OK );
-- if( pPg ){
-- sqlite3PcacheDrop(pPg);
-+ PAGERTRACE(("STORE %d page %d hash(%08x)\n",
-+ PAGERID(pPager), pgno, pager_pagehash(pList)));
-+ IOTRACE(("PGOUT %p %d\n", pPager, pgno));
-+ PAGER_INCR(sqlite3_pager_writedb_count);
-+ }else{
-+ PAGERTRACE(("NOSTORE %d page %d\n", PAGERID(pPager), pgno));
-+ }
-+ pager_set_pagehash(pList);
-+ pList = pList->pDirty;
- }
-- pagerUnlockIfUnused(pPager);
-
-- *ppPage = 0;
- return rc;
- }
-
- /*
--** Acquire a page if it is already in the in-memory cache. Do
--** not read the page from disk. Return a pointer to the page,
--** or 0 if the page is not in cache.
--**
--** See also sqlite3PagerGet(). The difference between this routine
--** and sqlite3PagerGet() is that _get() will go to the disk and read
--** in the page if the page is not already in cache. This routine
--** returns NULL if the page is not in cache or if a disk I/O error
--** has ever happened.
--*/
--SQLITE_PRIVATE DbPage *sqlite3PagerLookup(Pager *pPager, Pgno pgno){
-- PgHdr *pPg = 0;
-- assert( pPager!=0 );
-- assert( pgno!=0 );
-- assert( pPager->pPCache!=0 );
-- assert( pPager->eState>=PAGER_READER && pPager->eState!=PAGER_ERROR );
-- sqlite3PcacheFetch(pPager->pPCache, pgno, 0, &pPg);
-- return pPg;
--}
--
--/*
--** Release a page reference.
-+** Ensure that the sub-journal file is open. If it is already open, this
-+** function is a no-op.
- **
--** If the number of references to the page drop to zero, then the
--** page is added to the LRU list. When all references to all pages
--** are released, a rollback occurs and the lock on the database is
--** removed.
-+** SQLITE_OK is returned if everything goes according to plan. An
-+** SQLITE_IOERR_XXX error code is returned if a call to sqlite3OsOpen()
-+** fails.
- */
--SQLITE_PRIVATE void sqlite3PagerUnref(DbPage *pPg){
-- if( pPg ){
-- Pager *pPager = pPg->pPager;
-- if( pPg->flags & PGHDR_MMAP ){
-- pagerReleaseMapPage(pPg);
-+static int openSubJournal(Pager *pPager){
-+ int rc = SQLITE_OK;
-+ if( !isOpen(pPager->sjfd) ){
-+ if( pPager->journalMode==PAGER_JOURNALMODE_MEMORY || pPager->subjInMemory ){
-+ sqlite3MemJournalOpen(pPager->sjfd);
- }else{
-- sqlite3PcacheRelease(pPg);
-+ rc = pagerOpentemp(pPager, pPager->sjfd, SQLITE_OPEN_SUBJOURNAL);
- }
-- pagerUnlockIfUnused(pPager);
- }
-+ return rc;
- }
-
- /*
--** This function is called at the start of every write transaction.
--** There must already be a RESERVED or EXCLUSIVE lock on the database
--** file when this routine is called.
--**
--** Open the journal file for pager pPager and write a journal header
--** to the start of it. If there are active savepoints, open the sub-journal
--** as well. This function is only used when the journal file is being
--** opened to write a rollback log for a transaction. It is not used
--** when opening a hot journal file to roll it back.
--**
--** If the journal file is already open (as it may be in exclusive mode),
--** then this function just writes a journal header to the start of the
--** already open file.
-+** Append a record of the current state of page pPg to the sub-journal.
-+** It is the callers responsibility to use subjRequiresPage() to check
-+** that it is really required before calling this function.
- **
--** Whether or not the journal file is opened by this function, the
--** Pager.pInJournal bitvec structure is allocated.
-+** If successful, set the bit corresponding to pPg->pgno in the bitvecs
-+** for all open savepoints before returning.
- **
--** Return SQLITE_OK if everything is successful. Otherwise, return
--** SQLITE_NOMEM if the attempt to allocate Pager.pInJournal fails, or
--** an IO error code if opening or writing the journal file fails.
-+** This function returns SQLITE_OK if everything is successful, an IO
-+** error code if the attempt to write to the sub-journal fails, or
-+** SQLITE_NOMEM if a malloc fails while setting a bit in a savepoint
-+** bitvec.
- */
--static int pager_open_journal(Pager *pPager){
-- int rc = SQLITE_OK; /* Return code */
-- sqlite3_vfs * const pVfs = pPager->pVfs; /* Local cache of vfs pointer */
-+static int subjournalPage(PgHdr *pPg){
-+ int rc = SQLITE_OK;
-+ Pager *pPager = pPg->pPager;
-+ if( pPager->journalMode!=PAGER_JOURNALMODE_OFF ){
-
-- assert( pPager->eState==PAGER_WRITER_LOCKED );
-- assert( assert_pager_state(pPager) );
-- assert( pPager->pInJournal==0 );
--
-- /* If already in the error state, this function is a no-op. But on
-- ** the other hand, this routine is never called if we are already in
-- ** an error state. */
-- if( NEVER(pPager->errCode) ) return pPager->errCode;
-+ /* Open the sub-journal, if it has not already been opened */
-+ assert( pPager->useJournal );
-+ assert( isOpen(pPager->jfd) || pagerUseWal(pPager) );
-+ assert( isOpen(pPager->sjfd) || pPager->nSubRec==0 );
-+ assert( pagerUseWal(pPager)
-+ || pageInJournal(pPg)
-+ || pPg->pgno>pPager->dbOrigSize
-+ );
-+ rc = openSubJournal(pPager);
-
-- if( !pagerUseWal(pPager) && pPager->journalMode!=PAGER_JOURNALMODE_OFF ){
-- pPager->pInJournal = sqlite3BitvecCreate(pPager->dbSize);
-- if( pPager->pInJournal==0 ){
-- return SQLITE_NOMEM;
-- }
-+ /* If the sub-journal was opened successfully (or was already open),
-+ ** write the journal record into the file. */
-+ if( rc==SQLITE_OK ){
-+ void *pData = pPg->pData;
-+ i64 offset = (i64)pPager->nSubRec*(4+pPager->pageSize);
-+ char *pData2;
-
-- /* Open the journal file if it is not already open. */
-- if( !isOpen(pPager->jfd) ){
-- if( pPager->journalMode==PAGER_JOURNALMODE_MEMORY ){
-- sqlite3MemJournalOpen(pPager->jfd);
-- }else{
-- const int flags = /* VFS flags to open journal file */
-- SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|
-- (pPager->tempFile ?
-- (SQLITE_OPEN_DELETEONCLOSE|SQLITE_OPEN_TEMP_JOURNAL):
-- (SQLITE_OPEN_MAIN_JOURNAL)
-- );
-- #ifdef SQLITE_ENABLE_ATOMIC_WRITE
-- rc = sqlite3JournalOpen(
-- pVfs, pPager->zJournal, pPager->jfd, flags, jrnlBufferSize(pPager)
-- );
-- #else
-- rc = sqlite3OsOpen(pVfs, pPager->zJournal, pPager->jfd, flags, 0);
-- #endif
-+ CODEC2(pPager, pData, pPg->pgno, 7, return SQLITE_NOMEM, pData2);
-+ PAGERTRACE(("STMT-JOURNAL %d page %d\n", PAGERID(pPager), pPg->pgno));
-+ rc = write32bits(pPager->sjfd, offset, pPg->pgno);
-+ if( rc==SQLITE_OK ){
-+ rc = sqlite3OsWrite(pPager->sjfd, pData2, pPager->pageSize, offset+4);
- }
-- assert( rc!=SQLITE_OK || isOpen(pPager->jfd) );
-- }
--
--
-- /* Write the first journal header to the journal file and open
-- ** the sub-journal if necessary.
-- */
-- if( rc==SQLITE_OK ){
-- /* TODO: Check if all of these are really required. */
-- pPager->nRec = 0;
-- pPager->journalOff = 0;
-- pPager->setMaster = 0;
-- pPager->journalHdr = 0;
-- rc = writeJournalHdr(pPager);
- }
- }
--
-- if( rc!=SQLITE_OK ){
-- sqlite3BitvecDestroy(pPager->pInJournal);
-- pPager->pInJournal = 0;
-- }else{
-- assert( pPager->eState==PAGER_WRITER_LOCKED );
-- pPager->eState = PAGER_WRITER_CACHEMOD;
-- }
--
-+ if( rc==SQLITE_OK ){
-+ pPager->nSubRec++;
-+ assert( pPager->nSavepoint>0 );
-+ rc = addToSavepointBitvecs(pPager, pPg->pgno);
-+ }
- return rc;
- }
-
- /*
--** Begin a write-transaction on the specified pager object. If a
--** write-transaction has already been opened, this function is a no-op.
-+** This function is called by the pcache layer when it has reached some
-+** soft memory limit. The first argument is a pointer to a Pager object
-+** (cast as a void*). The pager is always 'purgeable' (not an in-memory
-+** database). The second argument is a reference to a page that is
-+** currently dirty but has no outstanding references. The page
-+** is always associated with the Pager object passed as the first
-+** argument.
- **
--** If the exFlag argument is false, then acquire at least a RESERVED
--** lock on the database file. If exFlag is true, then acquire at least
--** an EXCLUSIVE lock. If such a lock is already held, no locking
--** functions need be called.
-+** The job of this function is to make pPg clean by writing its contents
-+** out to the database file, if possible. This may involve syncing the
-+** journal file.
- **
--** If the subjInMemory argument is non-zero, then any sub-journal opened
--** within this transaction will be opened as an in-memory file. This
--** has no effect if the sub-journal is already opened (as it may be when
--** running in exclusive mode) or if the transaction does not require a
--** sub-journal. If the subjInMemory argument is zero, then any required
--** sub-journal is implemented in-memory if pPager is an in-memory database,
--** or using a temporary file otherwise.
-+** If successful, sqlite3PcacheMakeClean() is called on the page and
-+** SQLITE_OK returned. If an IO error occurs while trying to make the
-+** page clean, the IO error code is returned. If the page cannot be
-+** made clean for some other reason, but no error occurs, then SQLITE_OK
-+** is returned by sqlite3PcacheMakeClean() is not called.
- */
--SQLITE_PRIVATE int sqlite3PagerBegin(Pager *pPager, int exFlag, int subjInMemory){
-+static int pagerStress(void *p, PgHdr *pPg){
-+ Pager *pPager = (Pager *)p;
- int rc = SQLITE_OK;
-
-- if( pPager->errCode ) return pPager->errCode;
-- assert( pPager->eState>=PAGER_READER && pPager->eState<PAGER_ERROR );
-- pPager->subjInMemory = (u8)subjInMemory;
--
-- if( ALWAYS(pPager->eState==PAGER_READER) ){
-- assert( pPager->pInJournal==0 );
-+ assert( pPg->pPager==pPager );
-+ assert( pPg->flags&PGHDR_DIRTY );
-
-- if( pagerUseWal(pPager) ){
-- /* If the pager is configured to use locking_mode=exclusive, and an
-- ** exclusive lock on the database is not already held, obtain it now.
-- */
-- if( pPager->exclusiveMode && sqlite3WalExclusiveMode(pPager->pWal, -1) ){
-- rc = pagerLockDb(pPager, EXCLUSIVE_LOCK);
-- if( rc!=SQLITE_OK ){
-- return rc;
-- }
-- sqlite3WalExclusiveMode(pPager->pWal, 1);
-- }
-+ /* The doNotSyncSpill flag is set during times when doing a sync of
-+ ** journal (and adding a new header) is not allowed. This occurs
-+ ** during calls to sqlite3PagerWrite() while trying to journal multiple
-+ ** pages belonging to the same sector.
-+ **
-+ ** The doNotSpill flag inhibits all cache spilling regardless of whether
-+ ** or not a sync is required. This is set during a rollback.
-+ **
-+ ** Spilling is also prohibited when in an error state since that could
-+ ** lead to database corruption. In the current implementaton it
-+ ** is impossible for sqlite3PcacheFetch() to be called with createFlag==1
-+ ** while in the error state, hence it is impossible for this routine to
-+ ** be called in the error state. Nevertheless, we include a NEVER()
-+ ** test for the error state as a safeguard against future changes.
-+ */
-+ if( NEVER(pPager->errCode) ) return SQLITE_OK;
-+ if( pPager->doNotSpill ) return SQLITE_OK;
-+ if( pPager->doNotSyncSpill && (pPg->flags & PGHDR_NEED_SYNC)!=0 ){
-+ return SQLITE_OK;
-+ }
-
-- /* Grab the write lock on the log file. If successful, upgrade to
-- ** PAGER_RESERVED state. Otherwise, return an error code to the caller.
-- ** The busy-handler is not invoked if another connection already
-- ** holds the write-lock. If possible, the upper layer will call it.
-- */
-- rc = sqlite3WalBeginWriteTransaction(pPager->pWal);
-- }else{
-- /* Obtain a RESERVED lock on the database file. If the exFlag parameter
-- ** is true, then immediately upgrade this to an EXCLUSIVE lock. The
-- ** busy-handler callback can be used when upgrading to the EXCLUSIVE
-- ** lock, but not when obtaining the RESERVED lock.
-- */
-- rc = pagerLockDb(pPager, RESERVED_LOCK);
-- if( rc==SQLITE_OK && exFlag ){
-- rc = pager_wait_on_lock(pPager, EXCLUSIVE_LOCK);
-- }
-+ pPg->pDirty = 0;
-+ if( pagerUseWal(pPager) ){
-+ /* Write a single frame for this page to the log. */
-+ if( subjRequiresPage(pPg) ){
-+ rc = subjournalPage(pPg);
- }
--
- if( rc==SQLITE_OK ){
-- /* Change to WRITER_LOCKED state.
-- **
-- ** WAL mode sets Pager.eState to PAGER_WRITER_LOCKED or CACHEMOD
-- ** when it has an open transaction, but never to DBMOD or FINISHED.
-- ** This is because in those states the code to roll back savepoint
-- ** transactions may copy data from the sub-journal into the database
-- ** file as well as into the page cache. Which would be incorrect in
-- ** WAL mode.
-- */
-- pPager->eState = PAGER_WRITER_LOCKED;
-- pPager->dbHintSize = pPager->dbSize;
-- pPager->dbFileSize = pPager->dbSize;
-- pPager->dbOrigSize = pPager->dbSize;
-- pPager->journalOff = 0;
-+ rc = pagerWalFrames(pPager, pPg, 0, 0);
-+ }
-+ }else{
-+
-+ /* Sync the journal file if required. */
-+ if( pPg->flags&PGHDR_NEED_SYNC
-+ || pPager->eState==PAGER_WRITER_CACHEMOD
-+ ){
-+ rc = syncJournal(pPager, 1);
-+ }
-+
-+ /* If the page number of this page is larger than the current size of
-+ ** the database image, it may need to be written to the sub-journal.
-+ ** This is because the call to pager_write_pagelist() below will not
-+ ** actually write data to the file in this case.
-+ **
-+ ** Consider the following sequence of events:
-+ **
-+ ** BEGIN;
-+ ** <journal page X>
-+ ** <modify page X>
-+ ** SAVEPOINT sp;
-+ ** <shrink database file to Y pages>
-+ ** pagerStress(page X)
-+ ** ROLLBACK TO sp;
-+ **
-+ ** If (X>Y), then when pagerStress is called page X will not be written
-+ ** out to the database file, but will be dropped from the cache. Then,
-+ ** following the "ROLLBACK TO sp" statement, reading page X will read
-+ ** data from the database file. This will be the copy of page X as it
-+ ** was when the transaction started, not as it was when "SAVEPOINT sp"
-+ ** was executed.
-+ **
-+ ** The solution is to write the current data for page X into the
-+ ** sub-journal file now (if it is not already there), so that it will
-+ ** be restored to its current value when the "ROLLBACK TO sp" is
-+ ** executed.
-+ */
-+ if( NEVER(
-+ rc==SQLITE_OK && pPg->pgno>pPager->dbSize && subjRequiresPage(pPg)
-+ ) ){
-+ rc = subjournalPage(pPg);
-+ }
-+
-+ /* Write the contents of the page out to the database file. */
-+ if( rc==SQLITE_OK ){
-+ assert( (pPg->flags&PGHDR_NEED_SYNC)==0 );
-+ rc = pager_write_pagelist(pPager, pPg);
- }
-+ }
-
-- assert( rc==SQLITE_OK || pPager->eState==PAGER_READER );
-- assert( rc!=SQLITE_OK || pPager->eState==PAGER_WRITER_LOCKED );
-- assert( assert_pager_state(pPager) );
-+ /* Mark the page as clean. */
-+ if( rc==SQLITE_OK ){
-+ PAGERTRACE(("STRESS %d page %d\n", PAGERID(pPager), pPg->pgno));
-+ sqlite3PcacheMakeClean(pPg);
- }
-
-- PAGERTRACE(("TRANSACTION %d\n", PAGERID(pPager)));
-- return rc;
-+ return pager_error(pPager, rc);
- }
-
-+
- /*
--** Mark a single data page as writeable. The page is written into the
--** main journal or sub-journal as required. If the page is written into
--** one of the journals, the corresponding bit is set in the
--** Pager.pInJournal bitvec and the PagerSavepoint.pInSavepoint bitvecs
--** of any open savepoints as appropriate.
-+** Allocate and initialize a new Pager object and put a pointer to it
-+** in *ppPager. The pager should eventually be freed by passing it
-+** to sqlite3PagerClose().
-+**
-+** The zFilename argument is the path to the database file to open.
-+** If zFilename is NULL then a randomly-named temporary file is created
-+** and used as the file to be cached. Temporary files are be deleted
-+** automatically when they are closed. If zFilename is ":memory:" then
-+** all information is held in cache. It is never written to disk.
-+** This can be used to implement an in-memory database.
-+**
-+** The nExtra parameter specifies the number of bytes of space allocated
-+** along with each page reference. This space is available to the user
-+** via the sqlite3PagerGetExtra() API.
-+**
-+** The flags argument is used to specify properties that affect the
-+** operation of the pager. It should be passed some bitwise combination
-+** of the PAGER_* flags.
-+**
-+** The vfsFlags parameter is a bitmask to pass to the flags parameter
-+** of the xOpen() method of the supplied VFS when opening files.
-+**
-+** If the pager object is allocated and the specified file opened
-+** successfully, SQLITE_OK is returned and *ppPager set to point to
-+** the new pager object. If an error occurs, *ppPager is set to NULL
-+** and error code returned. This function may return SQLITE_NOMEM
-+** (sqlite3Malloc() is used to allocate memory), SQLITE_CANTOPEN or
-+** various SQLITE_IO_XXX errors.
- */
--static int pager_write(PgHdr *pPg){
-- void *pData = pPg->pData;
-- Pager *pPager = pPg->pPager;
-- int rc = SQLITE_OK;
-+SQLITE_PRIVATE int sqlite3PagerOpen(
-+ sqlite3_vfs *pVfs, /* The virtual file system to use */
-+ Pager **ppPager, /* OUT: Return the Pager structure here */
-+ const char *zFilename, /* Name of the database file to open */
-+ int nExtra, /* Extra bytes append to each in-memory page */
-+ int flags, /* flags controlling this file */
-+ int vfsFlags, /* flags passed through to sqlite3_vfs.xOpen() */
-+ void (*xReinit)(DbPage*) /* Function to reinitialize pages */
-+){
-+ u8 *pPtr;
-+ Pager *pPager = 0; /* Pager object to allocate and return */
-+ int rc = SQLITE_OK; /* Return code */
-+ int tempFile = 0; /* True for temp files (incl. in-memory files) */
-+ int memDb = 0; /* True if this is an in-memory file */
-+ int readOnly = 0; /* True if this is a read-only file */
-+ int journalFileSize; /* Bytes to allocate for each journal fd */
-+ char *zPathname = 0; /* Full path to database file */
-+ int nPathname = 0; /* Number of bytes in zPathname */
-+ int useJournal = (flags & PAGER_OMIT_JOURNAL)==0; /* False to omit journal */
-+ int pcacheSize = sqlite3PcacheSize(); /* Bytes to allocate for PCache */
-+ u32 szPageDflt = SQLITE_DEFAULT_PAGE_SIZE; /* Default page size */
-+ const char *zUri = 0; /* URI args to copy */
-+ int nUri = 0; /* Number of bytes of URI args at *zUri */
-
-- /* This routine is not called unless a write-transaction has already
-- ** been started. The journal file may or may not be open at this point.
-- ** It is never called in the ERROR state.
-+ /* Figure out how much space is required for each journal file-handle
-+ ** (there are two of them, the main journal and the sub-journal). This
-+ ** is the maximum space required for an in-memory journal file handle
-+ ** and a regular journal file-handle. Note that a "regular journal-handle"
-+ ** may be a wrapper capable of caching the first portion of the journal
-+ ** file in memory to implement the atomic-write optimization (see
-+ ** source file journal.c).
- */
-- assert( pPager->eState==PAGER_WRITER_LOCKED
-- || pPager->eState==PAGER_WRITER_CACHEMOD
-- || pPager->eState==PAGER_WRITER_DBMOD
-- );
-- assert( assert_pager_state(pPager) );
--
-- /* If an error has been previously detected, report the same error
-- ** again. This should not happen, but the check provides robustness. */
-- if( NEVER(pPager->errCode) ) return pPager->errCode;
-+ if( sqlite3JournalSize(pVfs)>sqlite3MemJournalSize() ){
-+ journalFileSize = ROUND8(sqlite3JournalSize(pVfs));
-+ }else{
-+ journalFileSize = ROUND8(sqlite3MemJournalSize());
-+ }
-
-- /* Higher-level routines never call this function if database is not
-- ** writable. But check anyway, just for robustness. */
-- if( NEVER(pPager->readOnly) ) return SQLITE_PERM;
-+ /* Set the output variable to NULL in case an error occurs. */
-+ *ppPager = 0;
-
-- CHECK_PAGE(pPg);
-+#ifndef SQLITE_OMIT_MEMORYDB
-+ if( flags & PAGER_MEMORY ){
-+ memDb = 1;
-+ if( zFilename && zFilename[0] ){
-+ zPathname = sqlite3DbStrDup(0, zFilename);
-+ if( zPathname==0 ) return SQLITE_NOMEM;
-+ nPathname = sqlite3Strlen30(zPathname);
-+ zFilename = 0;
-+ }
-+ }
-+#endif
-
-- /* The journal file needs to be opened. Higher level routines have already
-- ** obtained the necessary locks to begin the write-transaction, but the
-- ** rollback journal might not yet be open. Open it now if this is the case.
-- **
-- ** This is done before calling sqlite3PcacheMakeDirty() on the page.
-- ** Otherwise, if it were done after calling sqlite3PcacheMakeDirty(), then
-- ** an error might occur and the pager would end up in WRITER_LOCKED state
-- ** with pages marked as dirty in the cache.
-+ /* Compute and store the full pathname in an allocated buffer pointed
-+ ** to by zPathname, length nPathname. Or, if this is a temporary file,
-+ ** leave both nPathname and zPathname set to 0.
- */
-- if( pPager->eState==PAGER_WRITER_LOCKED ){
-- rc = pager_open_journal(pPager);
-- if( rc!=SQLITE_OK ) return rc;
-+ if( zFilename && zFilename[0] ){
-+ const char *z;
-+ nPathname = pVfs->mxPathname+1;
-+ zPathname = sqlite3DbMallocRaw(0, nPathname*2);
-+ if( zPathname==0 ){
-+ return SQLITE_NOMEM;
-+ }
-+ zPathname[0] = 0; /* Make sure initialized even if FullPathname() fails */
-+ rc = sqlite3OsFullPathname(pVfs, zFilename, nPathname, zPathname);
-+ nPathname = sqlite3Strlen30(zPathname);
-+ z = zUri = &zFilename[sqlite3Strlen30(zFilename)+1];
-+ while( *z ){
-+ z += sqlite3Strlen30(z)+1;
-+ z += sqlite3Strlen30(z)+1;
-+ }
-+ nUri = (int)(&z[1] - zUri);
-+ assert( nUri>=0 );
-+ if( rc==SQLITE_OK && nPathname+8>pVfs->mxPathname ){
-+ /* This branch is taken when the journal path required by
-+ ** the database being opened will be more than pVfs->mxPathname
-+ ** bytes in length. This means the database cannot be opened,
-+ ** as it will not be possible to open the journal file or even
-+ ** check for a hot-journal before reading.
-+ */
-+ rc = SQLITE_CANTOPEN_BKPT;
-+ }
-+ if( rc!=SQLITE_OK ){
-+ sqlite3DbFree(0, zPathname);
-+ return rc;
-+ }
- }
-- assert( pPager->eState>=PAGER_WRITER_CACHEMOD );
-- assert( assert_pager_state(pPager) );
-
-- /* Mark the page as dirty. If the page has already been written
-- ** to the journal then we can return right away.
-+ /* Allocate memory for the Pager structure, PCache object, the
-+ ** three file descriptors, the database file name and the journal
-+ ** file name. The layout in memory is as follows:
-+ **
-+ ** Pager object (sizeof(Pager) bytes)
-+ ** PCache object (sqlite3PcacheSize() bytes)
-+ ** Database file handle (pVfs->szOsFile bytes)
-+ ** Sub-journal file handle (journalFileSize bytes)
-+ ** Main journal file handle (journalFileSize bytes)
-+ ** Database file name (nPathname+1 bytes)
-+ ** Journal file name (nPathname+8+1 bytes)
- */
-- sqlite3PcacheMakeDirty(pPg);
-- if( pageInJournal(pPg) && !subjRequiresPage(pPg) ){
-- assert( !pagerUseWal(pPager) );
-- }else{
--
-- /* The transaction journal now exists and we have a RESERVED or an
-- ** EXCLUSIVE lock on the main database file. Write the current page to
-- ** the transaction journal if it is not there already.
-- */
-- if( !pageInJournal(pPg) && !pagerUseWal(pPager) ){
-- assert( pagerUseWal(pPager)==0 );
-- if( pPg->pgno<=pPager->dbOrigSize && isOpen(pPager->jfd) ){
-- u32 cksum;
-- char *pData2;
-- i64 iOff = pPager->journalOff;
--
-- /* We should never write to the journal file the page that
-- ** contains the database locks. The following assert verifies
-- ** that we do not. */
-- assert( pPg->pgno!=PAGER_MJ_PGNO(pPager) );
--
-- assert( pPager->journalHdr<=pPager->journalOff );
-- CODEC2(pPager, pData, pPg->pgno, 7, return SQLITE_NOMEM, pData2);
-- cksum = pager_cksum(pPager, (u8*)pData2);
--
-- /* Even if an IO or diskfull error occurs while journalling the
-- ** page in the block above, set the need-sync flag for the page.
-- ** Otherwise, when the transaction is rolled back, the logic in
-- ** playback_one_page() will think that the page needs to be restored
-- ** in the database file. And if an IO error occurs while doing so,
-- ** then corruption may follow.
-- */
-- pPg->flags |= PGHDR_NEED_SYNC;
-+ pPtr = (u8 *)sqlite3MallocZero(
-+ ROUND8(sizeof(*pPager)) + /* Pager structure */
-+ ROUND8(pcacheSize) + /* PCache object */
-+ ROUND8(pVfs->szOsFile) + /* The main db file */
-+ journalFileSize * 2 + /* The two journal files */
-+ nPathname + 1 + nUri + /* zFilename */
-+ nPathname + 8 + 2 /* zJournal */
-+#ifndef SQLITE_OMIT_WAL
-+ + nPathname + 4 + 2 /* zWal */
-+#endif
-+ );
-+ assert( EIGHT_BYTE_ALIGNMENT(SQLITE_INT_TO_PTR(journalFileSize)) );
-+ if( !pPtr ){
-+ sqlite3DbFree(0, zPathname);
-+ return SQLITE_NOMEM;
-+ }
-+ pPager = (Pager*)(pPtr);
-+ pPager->pPCache = (PCache*)(pPtr += ROUND8(sizeof(*pPager)));
-+ pPager->fd = (sqlite3_file*)(pPtr += ROUND8(pcacheSize));
-+ pPager->sjfd = (sqlite3_file*)(pPtr += ROUND8(pVfs->szOsFile));
-+ pPager->jfd = (sqlite3_file*)(pPtr += journalFileSize);
-+ pPager->zFilename = (char*)(pPtr += journalFileSize);
-+ assert( EIGHT_BYTE_ALIGNMENT(pPager->jfd) );
-
-- rc = write32bits(pPager->jfd, iOff, pPg->pgno);
-- if( rc!=SQLITE_OK ) return rc;
-- rc = sqlite3OsWrite(pPager->jfd, pData2, pPager->pageSize, iOff+4);
-- if( rc!=SQLITE_OK ) return rc;
-- rc = write32bits(pPager->jfd, iOff+pPager->pageSize+4, cksum);
-- if( rc!=SQLITE_OK ) return rc;
-+ /* Fill in the Pager.zFilename and Pager.zJournal buffers, if required. */
-+ if( zPathname ){
-+ assert( nPathname>0 );
-+ pPager->zJournal = (char*)(pPtr += nPathname + 1 + nUri);
-+ memcpy(pPager->zFilename, zPathname, nPathname);
-+ if( nUri ) memcpy(&pPager->zFilename[nPathname+1], zUri, nUri);
-+ memcpy(pPager->zJournal, zPathname, nPathname);
-+ memcpy(&pPager->zJournal[nPathname], "-journal\000", 8+2);
-+ sqlite3FileSuffix3(pPager->zFilename, pPager->zJournal);
-+#ifndef SQLITE_OMIT_WAL
-+ pPager->zWal = &pPager->zJournal[nPathname+8+1];
-+ memcpy(pPager->zWal, zPathname, nPathname);
-+ memcpy(&pPager->zWal[nPathname], "-wal\000", 4+1);
-+ sqlite3FileSuffix3(pPager->zFilename, pPager->zWal);
-+#endif
-+ sqlite3DbFree(0, zPathname);
-+ }
-+ pPager->pVfs = pVfs;
-+ pPager->vfsFlags = vfsFlags;
-
-- IOTRACE(("JOUT %p %d %lld %d\n", pPager, pPg->pgno,
-- pPager->journalOff, pPager->pageSize));
-- PAGER_INCR(sqlite3_pager_writej_count);
-- PAGERTRACE(("JOURNAL %d page %d needSync=%d hash(%08x)\n",
-- PAGERID(pPager), pPg->pgno,
-- ((pPg->flags&PGHDR_NEED_SYNC)?1:0), pager_pagehash(pPg)));
-+ /* Open the pager file.
-+ */
-+ if( zFilename && zFilename[0] ){
-+ int fout = 0; /* VFS flags returned by xOpen() */
-+ rc = sqlite3OsOpen(pVfs, pPager->zFilename, pPager->fd, vfsFlags, &fout);
-+ assert( !memDb );
-+ readOnly = (fout&SQLITE_OPEN_READONLY);
-
-- pPager->journalOff += 8 + pPager->pageSize;
-- pPager->nRec++;
-- assert( pPager->pInJournal!=0 );
-- rc = sqlite3BitvecSet(pPager->pInJournal, pPg->pgno);
-- testcase( rc==SQLITE_NOMEM );
-- assert( rc==SQLITE_OK || rc==SQLITE_NOMEM );
-- rc |= addToSavepointBitvecs(pPager, pPg->pgno);
-- if( rc!=SQLITE_OK ){
-- assert( rc==SQLITE_NOMEM );
-- return rc;
-+ /* If the file was successfully opened for read/write access,
-+ ** choose a default page size in case we have to create the
-+ ** database file. The default page size is the maximum of:
-+ **
-+ ** + SQLITE_DEFAULT_PAGE_SIZE,
-+ ** + The value returned by sqlite3OsSectorSize()
-+ ** + The largest page size that can be written atomically.
-+ */
-+ if( rc==SQLITE_OK && !readOnly ){
-+ setSectorSize(pPager);
-+ assert(SQLITE_DEFAULT_PAGE_SIZE<=SQLITE_MAX_DEFAULT_PAGE_SIZE);
-+ if( szPageDflt<pPager->sectorSize ){
-+ if( pPager->sectorSize>SQLITE_MAX_DEFAULT_PAGE_SIZE ){
-+ szPageDflt = SQLITE_MAX_DEFAULT_PAGE_SIZE;
-+ }else{
-+ szPageDflt = (u32)pPager->sectorSize;
- }
-- }else{
-- if( pPager->eState!=PAGER_WRITER_DBMOD ){
-- pPg->flags |= PGHDR_NEED_SYNC;
-+ }
-+#ifdef SQLITE_ENABLE_ATOMIC_WRITE
-+ {
-+ int iDc = sqlite3OsDeviceCharacteristics(pPager->fd);
-+ int ii;
-+ assert(SQLITE_IOCAP_ATOMIC512==(512>>8));
-+ assert(SQLITE_IOCAP_ATOMIC64K==(65536>>8));
-+ assert(SQLITE_MAX_DEFAULT_PAGE_SIZE<=65536);
-+ for(ii=szPageDflt; ii<=SQLITE_MAX_DEFAULT_PAGE_SIZE; ii=ii*2){
-+ if( iDc&(SQLITE_IOCAP_ATOMIC|(ii>>8)) ){
-+ szPageDflt = ii;
-+ }
- }
-- PAGERTRACE(("APPEND %d page %d needSync=%d\n",
-- PAGERID(pPager), pPg->pgno,
-- ((pPg->flags&PGHDR_NEED_SYNC)?1:0)));
- }
-+#endif
- }
--
-- /* If the statement journal is open and the page is not in it,
-- ** then write the current page to the statement journal. Note that
-- ** the statement journal format differs from the standard journal format
-- ** in that it omits the checksums and the header.
-- */
-- if( subjRequiresPage(pPg) ){
-- rc = subjournalPage(pPg);
-- }
-+ }else{
-+ /* If a temporary file is requested, it is not opened immediately.
-+ ** In this case we accept the default page size and delay actually
-+ ** opening the file until the first call to OsWrite().
-+ **
-+ ** This branch is also run for an in-memory database. An in-memory
-+ ** database is the same as a temp-file that is never written out to
-+ ** disk and uses an in-memory rollback journal.
-+ */
-+ tempFile = 1;
-+ pPager->eState = PAGER_READER;
-+ pPager->eLock = EXCLUSIVE_LOCK;
-+ readOnly = (vfsFlags&SQLITE_OPEN_READONLY);
-+ }
-+
-+ /* The following call to PagerSetPagesize() serves to set the value of
-+ ** Pager.pageSize and to allocate the Pager.pTmpSpace buffer.
-+ */
-+ if( rc==SQLITE_OK ){
-+ assert( pPager->memDb==0 );
-+ rc = sqlite3PagerSetPagesize(pPager, &szPageDflt, -1);
-+ testcase( rc!=SQLITE_OK );
-+ }
-+
-+ /* If an error occurred in either of the blocks above, free the
-+ ** Pager structure and close the file.
-+ */
-+ if( rc!=SQLITE_OK ){
-+ assert( !pPager->pTmpSpace );
-+ sqlite3OsClose(pPager->fd);
-+ sqlite3_free(pPager);
-+ return rc;
- }
-
-- /* Update the database size and return.
-- */
-- if( pPager->dbSize<pPg->pgno ){
-- pPager->dbSize = pPg->pgno;
-+ /* Initialize the PCache object. */
-+ assert( nExtra<1000 );
-+ nExtra = ROUND8(nExtra);
-+ sqlite3PcacheOpen(szPageDflt, nExtra, !memDb,
-+ !memDb?pagerStress:0, (void *)pPager, pPager->pPCache);
-+
-+ PAGERTRACE(("OPEN %d %s\n", FILEHANDLEID(pPager->fd), pPager->zFilename));
-+ IOTRACE(("OPEN %p %s\n", pPager, pPager->zFilename))
-+
-+ pPager->useJournal = (u8)useJournal;
-+ /* pPager->stmtOpen = 0; */
-+ /* pPager->stmtInUse = 0; */
-+ /* pPager->nRef = 0; */
-+ /* pPager->stmtSize = 0; */
-+ /* pPager->stmtJSize = 0; */
-+ /* pPager->nPage = 0; */
-+ pPager->mxPgno = SQLITE_MAX_PAGE_COUNT;
-+ /* pPager->state = PAGER_UNLOCK; */
-+#if 0
-+ assert( pPager->state == (tempFile ? PAGER_EXCLUSIVE : PAGER_UNLOCK) );
-+#endif
-+ /* pPager->errMask = 0; */
-+ pPager->tempFile = (u8)tempFile;
-+ assert( tempFile==PAGER_LOCKINGMODE_NORMAL
-+ || tempFile==PAGER_LOCKINGMODE_EXCLUSIVE );
-+ assert( PAGER_LOCKINGMODE_EXCLUSIVE==1 );
-+ pPager->exclusiveMode = (u8)tempFile;
-+ pPager->changeCountDone = pPager->tempFile;
-+ pPager->memDb = (u8)memDb;
-+ pPager->readOnly = (u8)readOnly;
-+ assert( useJournal || pPager->tempFile );
-+ pPager->noSync = pPager->tempFile;
-+ if( pPager->noSync ){
-+ assert( pPager->fullSync==0 );
-+ assert( pPager->syncFlags==0 );
-+ assert( pPager->walSyncFlags==0 );
-+ assert( pPager->ckptSyncFlags==0 );
-+ }else{
-+ pPager->fullSync = 1;
-+ pPager->syncFlags = SQLITE_SYNC_NORMAL;
-+ pPager->walSyncFlags = SQLITE_SYNC_NORMAL | WAL_SYNC_TRANSACTIONS;
-+ pPager->ckptSyncFlags = SQLITE_SYNC_NORMAL;
- }
-- return rc;
-+ /* pPager->pFirst = 0; */
-+ /* pPager->pFirstSynced = 0; */
-+ /* pPager->pLast = 0; */
-+ pPager->nExtra = (u16)nExtra;
-+ pPager->journalSizeLimit = SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT;
-+ assert( isOpen(pPager->fd) || tempFile );
-+ setSectorSize(pPager);
-+ if( !useJournal ){
-+ pPager->journalMode = PAGER_JOURNALMODE_OFF;
-+ }else if( memDb ){
-+ pPager->journalMode = PAGER_JOURNALMODE_MEMORY;
-+ }
-+ /* pPager->xBusyHandler = 0; */
-+ /* pPager->pBusyHandlerArg = 0; */
-+ pPager->xReiniter = xReinit;
-+ /* memset(pPager->aHash, 0, sizeof(pPager->aHash)); */
-+ /* pPager->szMmap = SQLITE_DEFAULT_MMAP_SIZE // will be set by btree.c */
-+
-+ *ppPager = pPager;
-+ return SQLITE_OK;
- }
-
-+
-+
- /*
--** Mark a data page as writeable. This routine must be called before
--** making changes to a page. The caller must check the return value
--** of this function and be careful not to change any page data unless
--** this routine returns SQLITE_OK.
-+** This function is called after transitioning from PAGER_UNLOCK to
-+** PAGER_SHARED state. It tests if there is a hot journal present in
-+** the file-system for the given pager. A hot journal is one that
-+** needs to be played back. According to this function, a hot-journal
-+** file exists if the following criteria are met:
- **
--** The difference between this function and pager_write() is that this
--** function also deals with the special case where 2 or more pages
--** fit on a single disk sector. In this case all co-resident pages
--** must have been written to the journal file before returning.
-+** * The journal file exists in the file system, and
-+** * No process holds a RESERVED or greater lock on the database file, and
-+** * The database file itself is greater than 0 bytes in size, and
-+** * The first byte of the journal file exists and is not 0x00.
- **
--** If an error occurs, SQLITE_NOMEM or an IO error code is returned
--** as appropriate. Otherwise, SQLITE_OK.
-+** If the current size of the database file is 0 but a journal file
-+** exists, that is probably an old journal left over from a prior
-+** database with the same name. In this case the journal file is
-+** just deleted using OsDelete, *pExists is set to 0 and SQLITE_OK
-+** is returned.
-+**
-+** This routine does not check if there is a master journal filename
-+** at the end of the file. If there is, and that master journal file
-+** does not exist, then the journal file is not really hot. In this
-+** case this routine will return a false-positive. The pager_playback()
-+** routine will discover that the journal file is not really hot and
-+** will not roll it back.
-+**
-+** If a hot-journal file is found to exist, *pExists is set to 1 and
-+** SQLITE_OK returned. If no hot-journal file is present, *pExists is
-+** set to 0 and SQLITE_OK returned. If an IO error occurs while trying
-+** to determine whether or not a hot-journal file exists, the IO error
-+** code is returned and the value of *pExists is undefined.
- */
--SQLITE_PRIVATE int sqlite3PagerWrite(DbPage *pDbPage){
-- int rc = SQLITE_OK;
--
-- PgHdr *pPg = pDbPage;
-- Pager *pPager = pPg->pPager;
-- Pgno nPagePerSector = (pPager->sectorSize/pPager->pageSize);
-+static int hasHotJournal(Pager *pPager, int *pExists){
-+ sqlite3_vfs * const pVfs = pPager->pVfs;
-+ int rc = SQLITE_OK; /* Return code */
-+ int exists = 1; /* True if a journal file is present */
-+ int jrnlOpen = !!isOpen(pPager->jfd);
-
-- assert( (pPg->flags & PGHDR_MMAP)==0 );
-- assert( pPager->eState>=PAGER_WRITER_LOCKED );
-- assert( pPager->eState!=PAGER_ERROR );
-- assert( assert_pager_state(pPager) );
-+ assert( pPager->useJournal );
-+ assert( isOpen(pPager->fd) );
-+ assert( pPager->eState==PAGER_OPEN );
-
-- if( nPagePerSector>1 ){
-- Pgno nPageCount; /* Total number of pages in database file */
-- Pgno pg1; /* First page of the sector pPg is located on. */
-- int nPage = 0; /* Number of pages starting at pg1 to journal */
-- int ii; /* Loop counter */
-- int needSync = 0; /* True if any page has PGHDR_NEED_SYNC */
-+ assert( jrnlOpen==0 || ( sqlite3OsDeviceCharacteristics(pPager->jfd) &
-+ SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN
-+ ));
-
-- /* Set the doNotSyncSpill flag to 1. This is because we cannot allow
-- ** a journal header to be written between the pages journaled by
-- ** this function.
-- */
-- assert( !MEMDB );
-- assert( pPager->doNotSyncSpill==0 );
-- pPager->doNotSyncSpill++;
-+ *pExists = 0;
-+ if( !jrnlOpen ){
-+ rc = sqlite3OsAccess(pVfs, pPager->zJournal, SQLITE_ACCESS_EXISTS, &exists);
-+ }
-+ if( rc==SQLITE_OK && exists ){
-+ int locked = 0; /* True if some process holds a RESERVED lock */
-
-- /* This trick assumes that both the page-size and sector-size are
-- ** an integer power of 2. It sets variable pg1 to the identifier
-- ** of the first page of the sector pPg is located on.
-+ /* Race condition here: Another process might have been holding the
-+ ** the RESERVED lock and have a journal open at the sqlite3OsAccess()
-+ ** call above, but then delete the journal and drop the lock before
-+ ** we get to the following sqlite3OsCheckReservedLock() call. If that
-+ ** is the case, this routine might think there is a hot journal when
-+ ** in fact there is none. This results in a false-positive which will
-+ ** be dealt with by the playback routine. Ticket #3883.
- */
-- pg1 = ((pPg->pgno-1) & ~(nPagePerSector-1)) + 1;
--
-- nPageCount = pPager->dbSize;
-- if( pPg->pgno>nPageCount ){
-- nPage = (pPg->pgno - pg1)+1;
-- }else if( (pg1+nPagePerSector-1)>nPageCount ){
-- nPage = nPageCount+1-pg1;
-- }else{
-- nPage = nPagePerSector;
-- }
-- assert(nPage>0);
-- assert(pg1<=pPg->pgno);
-- assert((pg1+nPage)>pPg->pgno);
-+ rc = sqlite3OsCheckReservedLock(pPager->fd, &locked);
-+ if( rc==SQLITE_OK && !locked ){
-+ Pgno nPage; /* Number of pages in database file */
-
-- for(ii=0; ii<nPage && rc==SQLITE_OK; ii++){
-- Pgno pg = pg1+ii;
-- PgHdr *pPage;
-- if( pg==pPg->pgno || !sqlite3BitvecTest(pPager->pInJournal, pg) ){
-- if( pg!=PAGER_MJ_PGNO(pPager) ){
-- rc = sqlite3PagerGet(pPager, pg, &pPage);
-+ /* Check the size of the database file. If it consists of 0 pages,
-+ ** then delete the journal file. See the header comment above for
-+ ** the reasoning here. Delete the obsolete journal file under
-+ ** a RESERVED lock to avoid race conditions and to avoid violating
-+ ** [H33020].
-+ */
-+ rc = pagerPagecount(pPager, &nPage);
-+ if( rc==SQLITE_OK ){
-+ if( nPage==0 ){
-+ sqlite3BeginBenignMalloc();
-+ if( pagerLockDb(pPager, RESERVED_LOCK)==SQLITE_OK ){
-+ sqlite3OsDelete(pVfs, pPager->zJournal, 0);
-+ if( !pPager->exclusiveMode ) pagerUnlockDb(pPager, SHARED_LOCK);
-+ }
-+ sqlite3EndBenignMalloc();
-+ }else{
-+ /* The journal file exists and no other connection has a reserved
-+ ** or greater lock on the database file. Now check that there is
-+ ** at least one non-zero bytes at the start of the journal file.
-+ ** If there is, then we consider this journal to be hot. If not,
-+ ** it can be ignored.
-+ */
-+ if( !jrnlOpen ){
-+ int f = SQLITE_OPEN_READONLY|SQLITE_OPEN_MAIN_JOURNAL;
-+ rc = sqlite3OsOpen(pVfs, pPager->zJournal, pPager->jfd, f, &f);
-+ }
- if( rc==SQLITE_OK ){
-- rc = pager_write(pPage);
-- if( pPage->flags&PGHDR_NEED_SYNC ){
-- needSync = 1;
-+ u8 first = 0;
-+ rc = sqlite3OsRead(pPager->jfd, (void *)&first, 1, 0);
-+ if( rc==SQLITE_IOERR_SHORT_READ ){
-+ rc = SQLITE_OK;
- }
-- sqlite3PagerUnref(pPage);
-+ if( !jrnlOpen ){
-+ sqlite3OsClose(pPager->jfd);
-+ }
-+ *pExists = (first!=0);
-+ }else if( rc==SQLITE_CANTOPEN ){
-+ /* If we cannot open the rollback journal file in order to see if
-+ ** its has a zero header, that might be due to an I/O error, or
-+ ** it might be due to the race condition described above and in
-+ ** ticket #3883. Either way, assume that the journal is hot.
-+ ** This might be a false positive. But if it is, then the
-+ ** automatic journal playback and recovery mechanism will deal
-+ ** with it under an EXCLUSIVE lock where we do not need to
-+ ** worry so much with race conditions.
-+ */
-+ *pExists = 1;
-+ rc = SQLITE_OK;
- }
- }
-- }else if( (pPage = pager_lookup(pPager, pg))!=0 ){
-- if( pPage->flags&PGHDR_NEED_SYNC ){
-- needSync = 1;
-- }
-- sqlite3PagerUnref(pPage);
-- }
-- }
--
-- /* If the PGHDR_NEED_SYNC flag is set for any of the nPage pages
-- ** starting at pg1, then it needs to be set for all of them. Because
-- ** writing to any of these nPage pages may damage the others, the
-- ** journal file must contain sync()ed copies of all of them
-- ** before any of them can be written out to the database file.
-- */
-- if( rc==SQLITE_OK && needSync ){
-- assert( !MEMDB );
-- for(ii=0; ii<nPage; ii++){
-- PgHdr *pPage = pager_lookup(pPager, pg1+ii);
-- if( pPage ){
-- pPage->flags |= PGHDR_NEED_SYNC;
-- sqlite3PagerUnref(pPage);
-- }
- }
- }
--
-- assert( pPager->doNotSyncSpill==1 );
-- pPager->doNotSyncSpill--;
-- }else{
-- rc = pager_write(pDbPage);
- }
-- return rc;
--}
-
--/*
--** Return TRUE if the page given in the argument was previously passed
--** to sqlite3PagerWrite(). In other words, return TRUE if it is ok
--** to change the content of the page.
--*/
--#ifndef NDEBUG
--SQLITE_PRIVATE int sqlite3PagerIswriteable(DbPage *pPg){
-- return pPg->flags&PGHDR_DIRTY;
-+ return rc;
- }
--#endif
-
- /*
--** A call to this routine tells the pager that it is not necessary to
--** write the information on page pPg back to the disk, even though
--** that page might be marked as dirty. This happens, for example, when
--** the page has been added as a leaf of the freelist and so its
--** content no longer matters.
--**
--** The overlying software layer calls this routine when all of the data
--** on the given page is unused. The pager marks the page as clean so
--** that it does not get written to disk.
-+** This function is called to obtain a shared lock on the database file.
-+** It is illegal to call sqlite3PagerAcquire() until after this function
-+** has been successfully called. If a shared-lock is already held when
-+** this function is called, it is a no-op.
- **
--** Tests show that this optimization can quadruple the speed of large
--** DELETE operations.
--*/
--SQLITE_PRIVATE void sqlite3PagerDontWrite(PgHdr *pPg){
-- Pager *pPager = pPg->pPager;
-- if( (pPg->flags&PGHDR_DIRTY) && pPager->nSavepoint==0 ){
-- PAGERTRACE(("DONT_WRITE page %d of %d\n", pPg->pgno, PAGERID(pPager)));
-- IOTRACE(("CLEAN %p %d\n", pPager, pPg->pgno))
-- pPg->flags |= PGHDR_DONT_WRITE;
-- pager_set_pagehash(pPg);
-- }
--}
--
--/*
--** This routine is called to increment the value of the database file
--** change-counter, stored as a 4-byte big-endian integer starting at
--** byte offset 24 of the pager file. The secondary change counter at
--** 92 is also updated, as is the SQLite version number at offset 96.
-+** The following operations are also performed by this function.
- **
--** But this only happens if the pPager->changeCountDone flag is false.
--** To avoid excess churning of page 1, the update only happens once.
--** See also the pager_write_changecounter() routine that does an
--** unconditional update of the change counters.
-+** 1) If the pager is currently in PAGER_OPEN state (no lock held
-+** on the database file), then an attempt is made to obtain a
-+** SHARED lock on the database file. Immediately after obtaining
-+** the SHARED lock, the file-system is checked for a hot-journal,
-+** which is played back if present. Following any hot-journal
-+** rollback, the contents of the cache are validated by checking
-+** the 'change-counter' field of the database file header and
-+** discarded if they are found to be invalid.
- **
--** If the isDirectMode flag is zero, then this is done by calling
--** sqlite3PagerWrite() on page 1, then modifying the contents of the
--** page data. In this case the file will be updated when the current
--** transaction is committed.
-+** 2) If the pager is running in exclusive-mode, and there are currently
-+** no outstanding references to any pages, and is in the error state,
-+** then an attempt is made to clear the error state by discarding
-+** the contents of the page cache and rolling back any open journal
-+** file.
- **
--** The isDirectMode flag may only be non-zero if the library was compiled
--** with the SQLITE_ENABLE_ATOMIC_WRITE macro defined. In this case,
--** if isDirect is non-zero, then the database file is updated directly
--** by writing an updated version of page 1 using a call to the
--** sqlite3OsWrite() function.
-+** If everything is successful, SQLITE_OK is returned. If an IO error
-+** occurs while locking the database, checking for a hot-journal file or
-+** rolling back a journal file, the IO error code is returned.
- */
--static int pager_incr_changecounter(Pager *pPager, int isDirectMode){
-- int rc = SQLITE_OK;
--
-- assert( pPager->eState==PAGER_WRITER_CACHEMOD
-- || pPager->eState==PAGER_WRITER_DBMOD
-- );
-- assert( assert_pager_state(pPager) );
-+SQLITE_PRIVATE int sqlite3PagerSharedLock(Pager *pPager){
-+ int rc = SQLITE_OK; /* Return code */
-
-- /* Declare and initialize constant integer 'isDirect'. If the
-- ** atomic-write optimization is enabled in this build, then isDirect
-- ** is initialized to the value passed as the isDirectMode parameter
-- ** to this function. Otherwise, it is always set to zero.
-- **
-- ** The idea is that if the atomic-write optimization is not
-- ** enabled at compile time, the compiler can omit the tests of
-- ** 'isDirect' below, as well as the block enclosed in the
-- ** "if( isDirect )" condition.
-+ /* This routine is only called from b-tree and only when there are no
-+ ** outstanding pages. This implies that the pager state should either
-+ ** be OPEN or READER. READER is only possible if the pager is or was in
-+ ** exclusive access mode.
- */
--#ifndef SQLITE_ENABLE_ATOMIC_WRITE
--# define DIRECT_MODE 0
-- assert( isDirectMode==0 );
-- UNUSED_PARAMETER(isDirectMode);
--#else
--# define DIRECT_MODE isDirectMode
--#endif
-+ assert( sqlite3PcacheRefCount(pPager->pPCache)==0 );
-+ assert( assert_pager_state(pPager) );
-+ assert( pPager->eState==PAGER_OPEN || pPager->eState==PAGER_READER );
-+ if( NEVER(MEMDB && pPager->errCode) ){ return pPager->errCode; }
-
-- if( !pPager->changeCountDone && ALWAYS(pPager->dbSize>0) ){
-- PgHdr *pPgHdr; /* Reference to page 1 */
-+ if( !pagerUseWal(pPager) && pPager->eState==PAGER_OPEN ){
-+ int bHotJournal = 1; /* True if there exists a hot journal-file */
-
-- assert( !pPager->tempFile && isOpen(pPager->fd) );
-+ assert( !MEMDB );
-
-- /* Open page 1 of the file for writing. */
-- rc = sqlite3PagerGet(pPager, 1, &pPgHdr);
-- assert( pPgHdr==0 || rc==SQLITE_OK );
-+ rc = pager_wait_on_lock(pPager, SHARED_LOCK);
-+ if( rc!=SQLITE_OK ){
-+ assert( pPager->eLock==NO_LOCK || pPager->eLock==UNKNOWN_LOCK );
-+ goto failed;
-+ }
-
-- /* If page one was fetched successfully, and this function is not
-- ** operating in direct-mode, make page 1 writable. When not in
-- ** direct mode, page 1 is always held in cache and hence the PagerGet()
-- ** above is always successful - hence the ALWAYS on rc==SQLITE_OK.
-+ /* If a journal file exists, and there is no RESERVED lock on the
-+ ** database file, then it either needs to be played back or deleted.
- */
-- if( !DIRECT_MODE && ALWAYS(rc==SQLITE_OK) ){
-- rc = sqlite3PagerWrite(pPgHdr);
-+ if( pPager->eLock<=SHARED_LOCK ){
-+ rc = hasHotJournal(pPager, &bHotJournal);
-+ }
-+ if( rc!=SQLITE_OK ){
-+ goto failed;
-+ }
-+ if( bHotJournal ){
-+ if( pPager->readOnly ){
-+ rc = SQLITE_READONLY_ROLLBACK;
-+ goto failed;
-+ }
-+
-+ /* Get an EXCLUSIVE lock on the database file. At this point it is
-+ ** important that a RESERVED lock is not obtained on the way to the
-+ ** EXCLUSIVE lock. If it were, another process might open the
-+ ** database file, detect the RESERVED lock, and conclude that the
-+ ** database is safe to read while this process is still rolling the
-+ ** hot-journal back.
-+ **
-+ ** Because the intermediate RESERVED lock is not requested, any
-+ ** other process attempting to access the database file will get to
-+ ** this point in the code and fail to obtain its own EXCLUSIVE lock
-+ ** on the database file.
-+ **
-+ ** Unless the pager is in locking_mode=exclusive mode, the lock is
-+ ** downgraded to SHARED_LOCK before this function returns.
-+ */
-+ rc = pagerLockDb(pPager, EXCLUSIVE_LOCK);
-+ if( rc!=SQLITE_OK ){
-+ goto failed;
-+ }
-+
-+ /* If it is not already open and the file exists on disk, open the
-+ ** journal for read/write access. Write access is required because
-+ ** in exclusive-access mode the file descriptor will be kept open
-+ ** and possibly used for a transaction later on. Also, write-access
-+ ** is usually required to finalize the journal in journal_mode=persist
-+ ** mode (and also for journal_mode=truncate on some systems).
-+ **
-+ ** If the journal does not exist, it usually means that some
-+ ** other connection managed to get in and roll it back before
-+ ** this connection obtained the exclusive lock above. Or, it
-+ ** may mean that the pager was in the error-state when this
-+ ** function was called and the journal file does not exist.
-+ */
-+ if( !isOpen(pPager->jfd) ){
-+ sqlite3_vfs * const pVfs = pPager->pVfs;
-+ int bExists; /* True if journal file exists */
-+ rc = sqlite3OsAccess(
-+ pVfs, pPager->zJournal, SQLITE_ACCESS_EXISTS, &bExists);
-+ if( rc==SQLITE_OK && bExists ){
-+ int fout = 0;
-+ int f = SQLITE_OPEN_READWRITE|SQLITE_OPEN_MAIN_JOURNAL;
-+ assert( !pPager->tempFile );
-+ rc = sqlite3OsOpen(pVfs, pPager->zJournal, pPager->jfd, f, &fout);
-+ assert( rc!=SQLITE_OK || isOpen(pPager->jfd) );
-+ if( rc==SQLITE_OK && fout&SQLITE_OPEN_READONLY ){
-+ rc = SQLITE_CANTOPEN_BKPT;
-+ sqlite3OsClose(pPager->jfd);
-+ }
-+ }
-+ }
-+
-+ /* Playback and delete the journal. Drop the database write
-+ ** lock and reacquire the read lock. Purge the cache before
-+ ** playing back the hot-journal so that we don't end up with
-+ ** an inconsistent cache. Sync the hot journal before playing
-+ ** it back since the process that crashed and left the hot journal
-+ ** probably did not sync it and we are required to always sync
-+ ** the journal before playing it back.
-+ */
-+ if( isOpen(pPager->jfd) ){
-+ assert( rc==SQLITE_OK );
-+ rc = pagerSyncHotJournal(pPager);
-+ if( rc==SQLITE_OK ){
-+ rc = pager_playback(pPager, 1);
-+ pPager->eState = PAGER_OPEN;
-+ }
-+ }else if( !pPager->exclusiveMode ){
-+ pagerUnlockDb(pPager, SHARED_LOCK);
-+ }
-+
-+ if( rc!=SQLITE_OK ){
-+ /* This branch is taken if an error occurs while trying to open
-+ ** or roll back a hot-journal while holding an EXCLUSIVE lock. The
-+ ** pager_unlock() routine will be called before returning to unlock
-+ ** the file. If the unlock attempt fails, then Pager.eLock must be
-+ ** set to UNKNOWN_LOCK (see the comment above the #define for
-+ ** UNKNOWN_LOCK above for an explanation).
-+ **
-+ ** In order to get pager_unlock() to do this, set Pager.eState to
-+ ** PAGER_ERROR now. This is not actually counted as a transition
-+ ** to ERROR state in the state diagram at the top of this file,
-+ ** since we know that the same call to pager_unlock() will very
-+ ** shortly transition the pager object to the OPEN state. Calling
-+ ** assert_pager_state() would fail now, as it should not be possible
-+ ** to be in ERROR state when there are zero outstanding page
-+ ** references.
-+ */
-+ pager_error(pPager, rc);
-+ goto failed;
-+ }
-+
-+ assert( pPager->eState==PAGER_OPEN );
-+ assert( (pPager->eLock==SHARED_LOCK)
-+ || (pPager->exclusiveMode && pPager->eLock>SHARED_LOCK)
-+ );
- }
-
-- if( rc==SQLITE_OK ){
-- /* Actually do the update of the change counter */
-- pager_write_changecounter(pPgHdr);
-+ if( !pPager->tempFile && (
-+ pPager->pBackup
-+ || sqlite3PcachePagecount(pPager->pPCache)>0
-+ || USEFETCH(pPager)
-+ )){
-+ /* The shared-lock has just been acquired on the database file
-+ ** and there are already pages in the cache (from a previous
-+ ** read or write transaction). Check to see if the database
-+ ** has been modified. If the database has changed, flush the
-+ ** cache.
-+ **
-+ ** Database changes is detected by looking at 15 bytes beginning
-+ ** at offset 24 into the file. The first 4 of these 16 bytes are
-+ ** a 32-bit counter that is incremented with each change. The
-+ ** other bytes change randomly with each file change when
-+ ** a codec is in use.
-+ **
-+ ** There is a vanishingly small chance that a change will not be
-+ ** detected. The chance of an undetected change is so small that
-+ ** it can be neglected.
-+ */
-+ Pgno nPage = 0;
-+ char dbFileVers[sizeof(pPager->dbFileVers)];
-+
-+ rc = pagerPagecount(pPager, &nPage);
-+ if( rc ) goto failed;
-
-- /* If running in direct mode, write the contents of page 1 to the file. */
-- if( DIRECT_MODE ){
-- const void *zBuf;
-- assert( pPager->dbFileSize>0 );
-- CODEC2(pPager, pPgHdr->pData, 1, 6, rc=SQLITE_NOMEM, zBuf);
-- if( rc==SQLITE_OK ){
-- rc = sqlite3OsWrite(pPager->fd, zBuf, pPager->pageSize, 0);
-- pPager->aStat[PAGER_STAT_WRITE]++;
-- }
-- if( rc==SQLITE_OK ){
-- /* Update the pager's copy of the change-counter. Otherwise, the
-- ** next time a read transaction is opened the cache will be
-- ** flushed (as the change-counter values will not match). */
-- const void *pCopy = (const void *)&((const char *)zBuf)[24];
-- memcpy(&pPager->dbFileVers, pCopy, sizeof(pPager->dbFileVers));
-- pPager->changeCountDone = 1;
-+ if( nPage>0 ){
-+ IOTRACE(("CKVERS %p %d\n", pPager, sizeof(dbFileVers)));
-+ rc = sqlite3OsRead(pPager->fd, &dbFileVers, sizeof(dbFileVers), 24);
-+ if( rc!=SQLITE_OK && rc!=SQLITE_IOERR_SHORT_READ ){
-+ goto failed;
- }
- }else{
-- pPager->changeCountDone = 1;
-+ memset(dbFileVers, 0, sizeof(dbFileVers));
-+ }
-+
-+ if( memcmp(pPager->dbFileVers, dbFileVers, sizeof(dbFileVers))!=0 ){
-+ pager_reset(pPager);
-+
-+ /* Unmap the database file. It is possible that external processes
-+ ** may have truncated the database file and then extended it back
-+ ** to its original size while this process was not holding a lock.
-+ ** In this case there may exist a Pager.pMap mapping that appears
-+ ** to be the right size but is not actually valid. Avoid this
-+ ** possibility by unmapping the db here. */
-+ if( USEFETCH(pPager) ){
-+ sqlite3OsUnfetch(pPager->fd, 0, 0);
-+ }
- }
- }
-
-- /* Release the page reference. */
-- sqlite3PagerUnref(pPgHdr);
-+ /* If there is a WAL file in the file-system, open this database in WAL
-+ ** mode. Otherwise, the following function call is a no-op.
-+ */
-+ rc = pagerOpenWalIfPresent(pPager);
-+#ifndef SQLITE_OMIT_WAL
-+ assert( pPager->pWal==0 || rc==SQLITE_OK );
-+#endif
- }
-- return rc;
--}
-
--/*
--** Sync the database file to disk. This is a no-op for in-memory databases
--** or pages with the Pager.noSync flag set.
--**
--** If successful, or if called on a pager for which it is a no-op, this
--** function returns SQLITE_OK. Otherwise, an IO error code is returned.
--*/
--SQLITE_PRIVATE int sqlite3PagerSync(Pager *pPager){
-- int rc = SQLITE_OK;
-- if( !pPager->noSync ){
-- assert( !MEMDB );
-- rc = sqlite3OsSync(pPager->fd, pPager->syncFlags);
-- }else if( isOpen(pPager->fd) ){
-+ if( pagerUseWal(pPager) ){
-+ assert( rc==SQLITE_OK );
-+ rc = pagerBeginReadTransaction(pPager);
-+ }
-+
-+ if( pPager->eState==PAGER_OPEN && rc==SQLITE_OK ){
-+ rc = pagerPagecount(pPager, &pPager->dbSize);
-+ }
-+
-+ failed:
-+ if( rc!=SQLITE_OK ){
- assert( !MEMDB );
-- rc = sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_SYNC_OMITTED, 0);
-- if( rc==SQLITE_NOTFOUND ){
-- rc = SQLITE_OK;
-- }
-+ pager_unlock(pPager);
-+ assert( pPager->eState==PAGER_OPEN );
-+ }else{
-+ pPager->eState = PAGER_READER;
- }
- return rc;
- }
-
- /*
--** This function may only be called while a write-transaction is active in
--** rollback. If the connection is in WAL mode, this call is a no-op.
--** Otherwise, if the connection does not already have an EXCLUSIVE lock on
--** the database file, an attempt is made to obtain one.
-+** If the reference count has reached zero, rollback any active
-+** transaction and unlock the pager.
- **
--** If the EXCLUSIVE lock is already held or the attempt to obtain it is
--** successful, or the connection is in WAL mode, SQLITE_OK is returned.
--** Otherwise, either SQLITE_BUSY or an SQLITE_IOERR_XXX error code is
--** returned.
--*/
--SQLITE_PRIVATE int sqlite3PagerExclusiveLock(Pager *pPager){
-- int rc = SQLITE_OK;
-- assert( pPager->eState==PAGER_WRITER_CACHEMOD
-- || pPager->eState==PAGER_WRITER_DBMOD
-- || pPager->eState==PAGER_WRITER_LOCKED
-- );
-- assert( assert_pager_state(pPager) );
-- if( 0==pagerUseWal(pPager) ){
-- rc = pager_wait_on_lock(pPager, EXCLUSIVE_LOCK);
-+** Except, in locking_mode=EXCLUSIVE when there is nothing to in
-+** the rollback journal, the unlock is not performed and there is
-+** nothing to rollback, so this routine is a no-op.
-+*/
-+static void pagerUnlockIfUnused(Pager *pPager){
-+ if( pPager->nMmapOut==0 && (sqlite3PcacheRefCount(pPager->pPCache)==0) ){
-+ pagerUnlockAndRollback(pPager);
- }
-- return rc;
- }
-
- /*
--** Sync the database file for the pager pPager. zMaster points to the name
--** of a master journal file that should be written into the individual
--** journal file. zMaster may be NULL, which is interpreted as no master
--** journal (a single database transaction).
-+** Acquire a reference to page number pgno in pager pPager (a page
-+** reference has type DbPage*). If the requested reference is
-+** successfully obtained, it is copied to *ppPage and SQLITE_OK returned.
- **
--** This routine ensures that:
-+** If the requested page is already in the cache, it is returned.
-+** Otherwise, a new page object is allocated and populated with data
-+** read from the database file. In some cases, the pcache module may
-+** choose not to allocate a new page object and may reuse an existing
-+** object with no outstanding references.
- **
--** * The database file change-counter is updated,
--** * the journal is synced (unless the atomic-write optimization is used),
--** * all dirty pages are written to the database file,
--** * the database file is truncated (if required), and
--** * the database file synced.
-+** The extra data appended to a page is always initialized to zeros the
-+** first time a page is loaded into memory. If the page requested is
-+** already in the cache when this function is called, then the extra
-+** data is left as it was when the page object was last used.
- **
--** The only thing that remains to commit the transaction is to finalize
--** (delete, truncate or zero the first part of) the journal file (or
--** delete the master journal file if specified).
-+** If the database image is smaller than the requested page or if a
-+** non-zero value is passed as the noContent parameter and the
-+** requested page is not already stored in the cache, then no
-+** actual disk read occurs. In this case the memory image of the
-+** page is initialized to all zeros.
- **
--** Note that if zMaster==NULL, this does not overwrite a previous value
--** passed to an sqlite3PagerCommitPhaseOne() call.
-+** If noContent is true, it means that we do not care about the contents
-+** of the page. This occurs in two seperate scenarios:
- **
--** If the final parameter - noSync - is true, then the database file itself
--** is not synced. The caller must call sqlite3PagerSync() directly to
--** sync the database file before calling CommitPhaseTwo() to delete the
--** journal file in this case.
-+** a) When reading a free-list leaf page from the database, and
-+**
-+** b) When a savepoint is being rolled back and we need to load
-+** a new page into the cache to be filled with the data read
-+** from the savepoint journal.
-+**
-+** If noContent is true, then the data returned is zeroed instead of
-+** being read from the database. Additionally, the bits corresponding
-+** to pgno in Pager.pInJournal (bitvec of pages already written to the
-+** journal file) and the PagerSavepoint.pInSavepoint bitvecs of any open
-+** savepoints are set. This means if the page is made writable at any
-+** point in the future, using a call to sqlite3PagerWrite(), its contents
-+** will not be journaled. This saves IO.
-+**
-+** The acquisition might fail for several reasons. In all cases,
-+** an appropriate error code is returned and *ppPage is set to NULL.
-+**
-+** See also sqlite3PagerLookup(). Both this routine and Lookup() attempt
-+** to find a page in the in-memory cache first. If the page is not already
-+** in memory, this routine goes to disk to read it in whereas Lookup()
-+** just returns 0. This routine acquires a read-lock the first time it
-+** has to go to disk, and could also playback an old journal if necessary.
-+** Since Lookup() never goes to disk, it never has to deal with locks
-+** or journal files.
- */
--SQLITE_PRIVATE int sqlite3PagerCommitPhaseOne(
-- Pager *pPager, /* Pager object */
-- const char *zMaster, /* If not NULL, the master journal name */
-- int noSync /* True to omit the xSync on the db file */
-+SQLITE_PRIVATE int sqlite3PagerAcquire(
-+ Pager *pPager, /* The pager open on the database file */
-+ Pgno pgno, /* Page number to fetch */
-+ DbPage **ppPage, /* Write a pointer to the page here */
-+ int flags /* PAGER_ACQUIRE_XXX flags */
- ){
-- int rc = SQLITE_OK; /* Return code */
-+ int rc = SQLITE_OK;
-+ PgHdr *pPg = 0;
-+ u32 iFrame = 0; /* Frame to read from WAL file */
-+ const int noContent = (flags & PAGER_ACQUIRE_NOCONTENT);
-
-- assert( pPager->eState==PAGER_WRITER_LOCKED
-- || pPager->eState==PAGER_WRITER_CACHEMOD
-- || pPager->eState==PAGER_WRITER_DBMOD
-- || pPager->eState==PAGER_ERROR
-+ /* It is acceptable to use a read-only (mmap) page for any page except
-+ ** page 1 if there is no write-transaction open or the ACQUIRE_READONLY
-+ ** flag was specified by the caller. And so long as the db is not a
-+ ** temporary or in-memory database. */
-+ const int bMmapOk = (pgno!=1 && USEFETCH(pPager)
-+ && (pPager->eState==PAGER_READER || (flags & PAGER_ACQUIRE_READONLY))
-+#ifdef SQLITE_HAS_CODEC
-+ && pPager->xCodec==0
-+#endif
- );
-+
-+ assert( pPager->eState>=PAGER_READER );
- assert( assert_pager_state(pPager) );
-+ assert( noContent==0 || bMmapOk==0 );
-
-- /* If a prior error occurred, report that error again. */
-- if( NEVER(pPager->errCode) ) return pPager->errCode;
-+ if( pgno==0 ){
-+ return SQLITE_CORRUPT_BKPT;
-+ }
-
-- PAGERTRACE(("DATABASE SYNC: File=%s zMaster=%s nSize=%d\n",
-- pPager->zFilename, zMaster, pPager->dbSize));
-+ /* If the pager is in the error state, return an error immediately.
-+ ** Otherwise, request the page from the PCache layer. */
-+ if( pPager->errCode!=SQLITE_OK ){
-+ rc = pPager->errCode;
-+ }else{
-
-- /* If no database changes have been made, return early. */
-- if( pPager->eState<PAGER_WRITER_CACHEMOD ) return SQLITE_OK;
-+ if( bMmapOk && pagerUseWal(pPager) ){
-+ rc = sqlite3WalFindFrame(pPager->pWal, pgno, &iFrame);
-+ if( rc!=SQLITE_OK ) goto pager_acquire_err;
-+ }
-
-- if( MEMDB ){
-- /* If this is an in-memory db, or no pages have been written to, or this
-- ** function has already been called, it is mostly a no-op. However, any
-- ** backup in progress needs to be restarted.
-- */
-- sqlite3BackupRestart(pPager->pBackup);
-- }else{
-- if( pagerUseWal(pPager) ){
-- PgHdr *pList = sqlite3PcacheDirtyList(pPager->pPCache);
-- PgHdr *pPageOne = 0;
-- if( pList==0 ){
-- /* Must have at least one page for the WAL commit flag.
-- ** Ticket [2d1a5c67dfc2363e44f29d9bbd57f] 2011-05-18 */
-- rc = sqlite3PagerGet(pPager, 1, &pPageOne);
-- pList = pPageOne;
-- pList->pDirty = 0;
-- }
-- assert( rc==SQLITE_OK );
-- if( ALWAYS(pList) ){
-- rc = pagerWalFrames(pPager, pList, pPager->dbSize, 1);
-- }
-- sqlite3PagerUnref(pPageOne);
-- if( rc==SQLITE_OK ){
-- sqlite3PcacheCleanAll(pPager->pPCache);
-- }
-- }else{
-- /* The following block updates the change-counter. Exactly how it
-- ** does this depends on whether or not the atomic-update optimization
-- ** was enabled at compile time, and if this transaction meets the
-- ** runtime criteria to use the operation:
-- **
-- ** * The file-system supports the atomic-write property for
-- ** blocks of size page-size, and
-- ** * This commit is not part of a multi-file transaction, and
-- ** * Exactly one page has been modified and store in the journal file.
-- **
-- ** If the optimization was not enabled at compile time, then the
-- ** pager_incr_changecounter() function is called to update the change
-- ** counter in 'indirect-mode'. If the optimization is compiled in but
-- ** is not applicable to this transaction, call sqlite3JournalCreate()
-- ** to make sure the journal file has actually been created, then call
-- ** pager_incr_changecounter() to update the change-counter in indirect
-- ** mode.
-- **
-- ** Otherwise, if the optimization is both enabled and applicable,
-- ** then call pager_incr_changecounter() to update the change-counter
-- ** in 'direct' mode. In this case the journal file will never be
-- ** created for this transaction.
-- */
-- #ifdef SQLITE_ENABLE_ATOMIC_WRITE
-- PgHdr *pPg;
-- assert( isOpen(pPager->jfd)
-- || pPager->journalMode==PAGER_JOURNALMODE_OFF
-- || pPager->journalMode==PAGER_JOURNALMODE_WAL
-+ if( iFrame==0 && bMmapOk ){
-+ void *pData = 0;
-+
-+ rc = sqlite3OsFetch(pPager->fd,
-+ (i64)(pgno-1) * pPager->pageSize, pPager->pageSize, &pData
- );
-- if( !zMaster && isOpen(pPager->jfd)
-- && pPager->journalOff==jrnlBufferSize(pPager)
-- && pPager->dbSize>=pPager->dbOrigSize
-- && (0==(pPg = sqlite3PcacheDirtyList(pPager->pPCache)) || 0==pPg->pDirty)
-- ){
-- /* Update the db file change counter via the direct-write method. The
-- ** following call will modify the in-memory representation of page 1
-- ** to include the updated change counter and then write page 1
-- ** directly to the database file. Because of the atomic-write
-- ** property of the host file-system, this is safe.
-- */
-- rc = pager_incr_changecounter(pPager, 1);
-- }else{
-- rc = sqlite3JournalCreate(pPager->jfd);
-- if( rc==SQLITE_OK ){
-- rc = pager_incr_changecounter(pPager, 0);
-+
-+ if( rc==SQLITE_OK && pData ){
-+ if( pPager->eState>PAGER_READER ){
-+ (void)sqlite3PcacheFetch(pPager->pPCache, pgno, 0, &pPg);
-+ }
-+ if( pPg==0 ){
-+ rc = pagerAcquireMapPage(pPager, pgno, pData, &pPg);
-+ }else{
-+ sqlite3OsUnfetch(pPager->fd, (i64)(pgno-1)*pPager->pageSize, pData);
-+ }
-+ if( pPg ){
-+ assert( rc==SQLITE_OK );
-+ *ppPage = pPg;
-+ return SQLITE_OK;
- }
- }
-- #else
-- rc = pager_incr_changecounter(pPager, 0);
-- #endif
-- if( rc!=SQLITE_OK ) goto commit_phase_one_exit;
--
-- /* Write the master journal name into the journal file. If a master
-- ** journal file name has already been written to the journal file,
-- ** or if zMaster is NULL (no master journal), then this call is a no-op.
-- */
-- rc = writeMasterJournal(pPager, zMaster);
-- if( rc!=SQLITE_OK ) goto commit_phase_one_exit;
--
-- /* Sync the journal file and write all dirty pages to the database.
-- ** If the atomic-update optimization is being used, this sync will not
-- ** create the journal file or perform any real IO.
-- **
-- ** Because the change-counter page was just modified, unless the
-- ** atomic-update optimization is used it is almost certain that the
-- ** journal requires a sync here. However, in locking_mode=exclusive
-- ** on a system under memory pressure it is just possible that this is
-- ** not the case. In this case it is likely enough that the redundant
-- ** xSync() call will be changed to a no-op by the OS anyhow.
-- */
-- rc = syncJournal(pPager, 0);
-- if( rc!=SQLITE_OK ) goto commit_phase_one_exit;
--
-- rc = pager_write_pagelist(pPager,sqlite3PcacheDirtyList(pPager->pPCache));
- if( rc!=SQLITE_OK ){
-- assert( rc!=SQLITE_IOERR_BLOCKED );
-- goto commit_phase_one_exit;
-+ goto pager_acquire_err;
- }
-- sqlite3PcacheCleanAll(pPager->pPCache);
-+ }
-
-- /* If the file on disk is smaller than the database image, use
-- ** pager_truncate to grow the file here. This can happen if the database
-- ** image was extended as part of the current transaction and then the
-- ** last page in the db image moved to the free-list. In this case the
-- ** last page is never written out to disk, leaving the database file
-- ** undersized. Fix this now if it is the case. */
-- if( pPager->dbSize>pPager->dbFileSize ){
-- Pgno nNew = pPager->dbSize - (pPager->dbSize==PAGER_MJ_PGNO(pPager));
-- assert( pPager->eState==PAGER_WRITER_DBMOD );
-- rc = pager_truncate(pPager, nNew);
-- if( rc!=SQLITE_OK ) goto commit_phase_one_exit;
-+ rc = sqlite3PcacheFetch(pPager->pPCache, pgno, 1, ppPage);
-+ }
-+
-+ if( rc!=SQLITE_OK ){
-+ /* Either the call to sqlite3PcacheFetch() returned an error or the
-+ ** pager was already in the error-state when this function was called.
-+ ** Set pPg to 0 and jump to the exception handler. */
-+ pPg = 0;
-+ goto pager_acquire_err;
-+ }
-+ assert( (*ppPage)->pgno==pgno );
-+ assert( (*ppPage)->pPager==pPager || (*ppPage)->pPager==0 );
-+
-+ if( (*ppPage)->pPager && !noContent ){
-+ /* In this case the pcache already contains an initialized copy of
-+ ** the page. Return without further ado. */
-+ assert( pgno<=PAGER_MAX_PGNO && pgno!=PAGER_MJ_PGNO(pPager) );
-+ pPager->aStat[PAGER_STAT_HIT]++;
-+ return SQLITE_OK;
-+
-+ }else{
-+ /* The pager cache has created a new page. Its content needs to
-+ ** be initialized. */
-+
-+ pPg = *ppPage;
-+ pPg->pPager = pPager;
-+
-+ /* The maximum page number is 2^31. Return SQLITE_CORRUPT if a page
-+ ** number greater than this, or the unused locking-page, is requested. */
-+ if( pgno>PAGER_MAX_PGNO || pgno==PAGER_MJ_PGNO(pPager) ){
-+ rc = SQLITE_CORRUPT_BKPT;
-+ goto pager_acquire_err;
-+ }
-+
-+ if( MEMDB || pPager->dbSize<pgno || noContent || !isOpen(pPager->fd) ){
-+ if( pgno>pPager->mxPgno ){
-+ rc = SQLITE_FULL;
-+ goto pager_acquire_err;
- }
--
-- /* Finally, sync the database file. */
-- if( !noSync ){
-- rc = sqlite3PagerSync(pPager);
-+ if( noContent ){
-+ /* Failure to set the bits in the InJournal bit-vectors is benign.
-+ ** It merely means that we might do some extra work to journal a
-+ ** page that does not need to be journaled. Nevertheless, be sure
-+ ** to test the case where a malloc error occurs while trying to set
-+ ** a bit in a bit vector.
-+ */
-+ sqlite3BeginBenignMalloc();
-+ if( pgno<=pPager->dbOrigSize ){
-+ TESTONLY( rc = ) sqlite3BitvecSet(pPager->pInJournal, pgno);
-+ testcase( rc==SQLITE_NOMEM );
-+ }
-+ TESTONLY( rc = ) addToSavepointBitvecs(pPager, pgno);
-+ testcase( rc==SQLITE_NOMEM );
-+ sqlite3EndBenignMalloc();
-+ }
-+ memset(pPg->pData, 0, pPager->pageSize);
-+ IOTRACE(("ZERO %p %d\n", pPager, pgno));
-+ }else{
-+ if( pagerUseWal(pPager) && bMmapOk==0 ){
-+ rc = sqlite3WalFindFrame(pPager->pWal, pgno, &iFrame);
-+ if( rc!=SQLITE_OK ) goto pager_acquire_err;
-+ }
-+ assert( pPg->pPager==pPager );
-+ pPager->aStat[PAGER_STAT_MISS]++;
-+ rc = readDbPage(pPg, iFrame);
-+ if( rc!=SQLITE_OK ){
-+ goto pager_acquire_err;
- }
-- IOTRACE(("DBSYNC %p\n", pPager))
- }
-+ pager_set_pagehash(pPg);
- }
-
--commit_phase_one_exit:
-- if( rc==SQLITE_OK && !pagerUseWal(pPager) ){
-- pPager->eState = PAGER_WRITER_FINISHED;
-+ return SQLITE_OK;
-+
-+pager_acquire_err:
-+ assert( rc!=SQLITE_OK );
-+ if( pPg ){
-+ sqlite3PcacheDrop(pPg);
- }
-+ pagerUnlockIfUnused(pPager);
-+
-+ *ppPage = 0;
- return rc;
- }
-
--
- /*
--** When this function is called, the database file has been completely
--** updated to reflect the changes made by the current transaction and
--** synced to disk. The journal file still exists in the file-system
--** though, and if a failure occurs at this point it will eventually
--** be used as a hot-journal and the current transaction rolled back.
--**
--** This function finalizes the journal file, either by deleting,
--** truncating or partially zeroing it, so that it cannot be used
--** for hot-journal rollback. Once this is done the transaction is
--** irrevocably committed.
-+** Acquire a page if it is already in the in-memory cache. Do
-+** not read the page from disk. Return a pointer to the page,
-+** or 0 if the page is not in cache.
- **
--** If an error occurs, an IO error code is returned and the pager
--** moves into the error state. Otherwise, SQLITE_OK is returned.
-+** See also sqlite3PagerGet(). The difference between this routine
-+** and sqlite3PagerGet() is that _get() will go to the disk and read
-+** in the page if the page is not already in cache. This routine
-+** returns NULL if the page is not in cache or if a disk I/O error
-+** has ever happened.
- */
--SQLITE_PRIVATE int sqlite3PagerCommitPhaseTwo(Pager *pPager){
-- int rc = SQLITE_OK; /* Return code */
--
-- /* This routine should not be called if a prior error has occurred.
-- ** But if (due to a coding error elsewhere in the system) it does get
-- ** called, just return the same error code without doing anything. */
-- if( NEVER(pPager->errCode) ) return pPager->errCode;
--
-- assert( pPager->eState==PAGER_WRITER_LOCKED
-- || pPager->eState==PAGER_WRITER_FINISHED
-- || (pagerUseWal(pPager) && pPager->eState==PAGER_WRITER_CACHEMOD)
-- );
-- assert( assert_pager_state(pPager) );
-+SQLITE_PRIVATE DbPage *sqlite3PagerLookup(Pager *pPager, Pgno pgno){
-+ PgHdr *pPg = 0;
-+ assert( pPager!=0 );
-+ assert( pgno!=0 );
-+ assert( pPager->pPCache!=0 );
-+ assert( pPager->eState>=PAGER_READER && pPager->eState!=PAGER_ERROR );
-+ sqlite3PcacheFetch(pPager->pPCache, pgno, 0, &pPg);
-+ return pPg;
++SQLITE_PRIVATE sqlite3_file *sqlite3Pager_get_fd(Pager *pPager) {
++ return (isOpen(pPager->fd)) ? pPager->fd : NULL;
+}
-
-- /* An optimization. If the database was not actually modified during
-- ** this transaction, the pager is running in exclusive-mode and is
-- ** using persistent journals, then this function is a no-op.
-- **
-- ** The start of the journal file currently contains a single journal
-- ** header with the nRec field set to 0. If such a journal is used as
-- ** a hot-journal during hot-journal rollback, 0 changes will be made
-- ** to the database file. So there is no need to zero the journal
-- ** header. Since the pager is in exclusive mode, there is no need
-- ** to drop any locks either.
-- */
-- if( pPager->eState==PAGER_WRITER_LOCKED
-- && pPager->exclusiveMode
-- && pPager->journalMode==PAGER_JOURNALMODE_PERSIST
-- ){
-- assert( pPager->journalOff==JOURNAL_HDR_SZ(pPager) || !pPager->journalOff );
-- pPager->eState = PAGER_READER;
-- return SQLITE_OK;
-+/*
-+** Release a page reference.
-+**
-+** If the number of references to the page drop to zero, then the
-+** page is added to the LRU list. When all references to all pages
-+** are released, a rollback occurs and the lock on the database is
-+** removed.
-+*/
-+SQLITE_PRIVATE void sqlite3PagerUnref(DbPage *pPg){
-+ if( pPg ){
-+ Pager *pPager = pPg->pPager;
-+ if( pPg->flags & PGHDR_MMAP ){
-+ pagerReleaseMapPage(pPg);
-+ }else{
-+ sqlite3PcacheRelease(pPg);
-+ }
-+ pagerUnlockIfUnused(pPager);
- }
--
-- PAGERTRACE(("COMMIT %d\n", PAGERID(pPager)));
-- rc = pager_end_transaction(pPager, pPager->setMaster, 1);
-- return pager_error(pPager, rc);
- }
-
- /*
--** If a write transaction is open, then all changes made within the
--** transaction are reverted and the current write-transaction is closed.
--** The pager falls back to PAGER_READER state if successful, or PAGER_ERROR
--** state if an error occurs.
--**
--** If the pager is already in PAGER_ERROR state when this function is called,
--** it returns Pager.errCode immediately. No work is performed in this case.
--**
--** Otherwise, in rollback mode, this function performs two functions:
-+** This function is called at the start of every write transaction.
-+** There must already be a RESERVED or EXCLUSIVE lock on the database
-+** file when this routine is called.
- **
--** 1) It rolls back the journal file, restoring all database file and
--** in-memory cache pages to the state they were in when the transaction
--** was opened, and
-+** Open the journal file for pager pPager and write a journal header
-+** to the start of it. If there are active savepoints, open the sub-journal
-+** as well. This function is only used when the journal file is being
-+** opened to write a rollback log for a transaction. It is not used
-+** when opening a hot journal file to roll it back.
- **
--** 2) It finalizes the journal file, so that it is not used for hot
--** rollback at any point in the future.
-+** If the journal file is already open (as it may be in exclusive mode),
-+** then this function just writes a journal header to the start of the
-+** already open file.
- **
--** Finalization of the journal file (task 2) is only performed if the
--** rollback is successful.
-+** Whether or not the journal file is opened by this function, the
-+** Pager.pInJournal bitvec structure is allocated.
- **
--** In WAL mode, all cache-entries containing data modified within the
--** current transaction are either expelled from the cache or reverted to
--** their pre-transaction state by re-reading data from the database or
--** WAL files. The WAL transaction is then closed.
-+** Return SQLITE_OK if everything is successful. Otherwise, return
-+** SQLITE_NOMEM if the attempt to allocate Pager.pInJournal fails, or
-+** an IO error code if opening or writing the journal file fails.
- */
--SQLITE_PRIVATE int sqlite3PagerRollback(Pager *pPager){
-- int rc = SQLITE_OK; /* Return code */
-- PAGERTRACE(("ROLLBACK %d\n", PAGERID(pPager)));
-+static int pager_open_journal(Pager *pPager){
-+ int rc = SQLITE_OK; /* Return code */
-+ sqlite3_vfs * const pVfs = pPager->pVfs; /* Local cache of vfs pointer */
-
-- /* PagerRollback() is a no-op if called in READER or OPEN state. If
-- ** the pager is already in the ERROR state, the rollback is not
-- ** attempted here. Instead, the error code is returned to the caller.
-- */
-+ assert( pPager->eState==PAGER_WRITER_LOCKED );
- assert( assert_pager_state(pPager) );
-- if( pPager->eState==PAGER_ERROR ) return pPager->errCode;
-- if( pPager->eState<=PAGER_READER ) return SQLITE_OK;
-+ assert( pPager->pInJournal==0 );
-+
-+ /* If already in the error state, this function is a no-op. But on
-+ ** the other hand, this routine is never called if we are already in
-+ ** an error state. */
-+ if( NEVER(pPager->errCode) ) return pPager->errCode;
-
-- if( pagerUseWal(pPager) ){
-- int rc2;
-- rc = sqlite3PagerSavepoint(pPager, SAVEPOINT_ROLLBACK, -1);
-- rc2 = pager_end_transaction(pPager, pPager->setMaster, 0);
-- if( rc==SQLITE_OK ) rc = rc2;
-- }else if( !isOpen(pPager->jfd) || pPager->eState==PAGER_WRITER_LOCKED ){
-- int eState = pPager->eState;
-- rc = pager_end_transaction(pPager, 0, 0);
-- if( !MEMDB && eState>PAGER_WRITER_LOCKED ){
-- /* This can happen using journal_mode=off. Move the pager to the error
-- ** state to indicate that the contents of the cache may not be trusted.
-- ** Any active readers will get SQLITE_ABORT.
-- */
-- pPager->errCode = SQLITE_ABORT;
-- pPager->eState = PAGER_ERROR;
-- return rc;
-+ if( !pagerUseWal(pPager) && pPager->journalMode!=PAGER_JOURNALMODE_OFF ){
-+ pPager->pInJournal = sqlite3BitvecCreate(pPager->dbSize);
-+ if( pPager->pInJournal==0 ){
-+ return SQLITE_NOMEM;
-+ }
-+
-+ /* Open the journal file if it is not already open. */
-+ if( !isOpen(pPager->jfd) ){
-+ if( pPager->journalMode==PAGER_JOURNALMODE_MEMORY ){
-+ sqlite3MemJournalOpen(pPager->jfd);
-+ }else{
-+ const int flags = /* VFS flags to open journal file */
-+ SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|
-+ (pPager->tempFile ?
-+ (SQLITE_OPEN_DELETEONCLOSE|SQLITE_OPEN_TEMP_JOURNAL):
-+ (SQLITE_OPEN_MAIN_JOURNAL)
-+ );
-+ #ifdef SQLITE_ENABLE_ATOMIC_WRITE
-+ rc = sqlite3JournalOpen(
-+ pVfs, pPager->zJournal, pPager->jfd, flags, jrnlBufferSize(pPager)
-+ );
-+ #else
-+ rc = sqlite3OsOpen(pVfs, pPager->zJournal, pPager->jfd, flags, 0);
-+ #endif
-+ }
-+ assert( rc!=SQLITE_OK || isOpen(pPager->jfd) );
-+ }
-+
-+
-+ /* Write the first journal header to the journal file and open
-+ ** the sub-journal if necessary.
-+ */
-+ if( rc==SQLITE_OK ){
-+ /* TODO: Check if all of these are really required. */
-+ pPager->nRec = 0;
-+ pPager->journalOff = 0;
-+ pPager->setMaster = 0;
-+ pPager->journalHdr = 0;
-+ rc = writeJournalHdr(pPager);
- }
-- }else{
-- rc = pager_playback(pPager, 0);
- }
-
-- assert( pPager->eState==PAGER_READER || rc!=SQLITE_OK );
-- assert( rc==SQLITE_OK || rc==SQLITE_FULL || rc==SQLITE_CORRUPT
-- || rc==SQLITE_NOMEM || (rc&0xFF)==SQLITE_IOERR );
-+ if( rc!=SQLITE_OK ){
-+ sqlite3BitvecDestroy(pPager->pInJournal);
-+ pPager->pInJournal = 0;
-+ }else{
-+ assert( pPager->eState==PAGER_WRITER_LOCKED );
-+ pPager->eState = PAGER_WRITER_CACHEMOD;
-+ }
-
-- /* If an error occurs during a ROLLBACK, we can no longer trust the pager
-- ** cache. So call pager_error() on the way out to make any error persistent.
-- */
-- return pager_error(pPager, rc);
-+ return rc;
- }
-
- /*
--** Return TRUE if the database file is opened read-only. Return FALSE
--** if the database is (in theory) writable.
-+** Begin a write-transaction on the specified pager object. If a
-+** write-transaction has already been opened, this function is a no-op.
-+**
-+** If the exFlag argument is false, then acquire at least a RESERVED
-+** lock on the database file. If exFlag is true, then acquire at least
-+** an EXCLUSIVE lock. If such a lock is already held, no locking
-+** functions need be called.
-+**
-+** If the subjInMemory argument is non-zero, then any sub-journal opened
-+** within this transaction will be opened as an in-memory file. This
-+** has no effect if the sub-journal is already opened (as it may be when
-+** running in exclusive mode) or if the transaction does not require a
-+** sub-journal. If the subjInMemory argument is zero, then any required
-+** sub-journal is implemented in-memory if pPager is an in-memory database,
-+** or using a temporary file otherwise.
- */
--SQLITE_PRIVATE u8 sqlite3PagerIsreadonly(Pager *pPager){
-- return pPager->readOnly;
--}
-+SQLITE_PRIVATE int sqlite3PagerBegin(Pager *pPager, int exFlag, int subjInMemory){
-+ int rc = SQLITE_OK;
-
--/*
--** Return the number of references to the pager.
--*/
--SQLITE_PRIVATE int sqlite3PagerRefcount(Pager *pPager){
-- return sqlite3PcacheRefCount(pPager->pPCache);
--}
-+ if( pPager->errCode ) return pPager->errCode;
-+ assert( pPager->eState>=PAGER_READER && pPager->eState<PAGER_ERROR );
-+ pPager->subjInMemory = (u8)subjInMemory;
-
--/*
--** Return the approximate number of bytes of memory currently
--** used by the pager and its associated cache.
--*/
--SQLITE_PRIVATE int sqlite3PagerMemUsed(Pager *pPager){
-- int perPageSize = pPager->pageSize + pPager->nExtra + sizeof(PgHdr)
-- + 5*sizeof(void*);
-- return perPageSize*sqlite3PcachePagecount(pPager->pPCache)
-- + sqlite3MallocSize(pPager)
-- + pPager->pageSize;
--}
-+ if( ALWAYS(pPager->eState==PAGER_READER) ){
-+ assert( pPager->pInJournal==0 );
-
--/*
--** Return the number of references to the specified page.
--*/
--SQLITE_PRIVATE int sqlite3PagerPageRefcount(DbPage *pPage){
-- return sqlite3PcachePageRefcount(pPage);
--}
-+ if( pagerUseWal(pPager) ){
-+ /* If the pager is configured to use locking_mode=exclusive, and an
-+ ** exclusive lock on the database is not already held, obtain it now.
-+ */
-+ if( pPager->exclusiveMode && sqlite3WalExclusiveMode(pPager->pWal, -1) ){
-+ rc = pagerLockDb(pPager, EXCLUSIVE_LOCK);
-+ if( rc!=SQLITE_OK ){
-+ return rc;
-+ }
-+ sqlite3WalExclusiveMode(pPager->pWal, 1);
-+ }
-
--#ifdef SQLITE_TEST
--/*
--** This routine is used for testing and analysis only.
--*/
--SQLITE_PRIVATE int *sqlite3PagerStats(Pager *pPager){
-- static int a[11];
-- a[0] = sqlite3PcacheRefCount(pPager->pPCache);
-- a[1] = sqlite3PcachePagecount(pPager->pPCache);
-- a[2] = sqlite3PcacheGetCachesize(pPager->pPCache);
-- a[3] = pPager->eState==PAGER_OPEN ? -1 : (int) pPager->dbSize;
-- a[4] = pPager->eState;
-- a[5] = pPager->errCode;
-- a[6] = pPager->aStat[PAGER_STAT_HIT];
-- a[7] = pPager->aStat[PAGER_STAT_MISS];
-- a[8] = 0; /* Used to be pPager->nOvfl */
-- a[9] = pPager->nRead;
-- a[10] = pPager->aStat[PAGER_STAT_WRITE];
-- return a;
-+ /* Grab the write lock on the log file. If successful, upgrade to
-+ ** PAGER_RESERVED state. Otherwise, return an error code to the caller.
-+ ** The busy-handler is not invoked if another connection already
-+ ** holds the write-lock. If possible, the upper layer will call it.
-+ */
-+ rc = sqlite3WalBeginWriteTransaction(pPager->pWal);
-+ }else{
-+ /* Obtain a RESERVED lock on the database file. If the exFlag parameter
-+ ** is true, then immediately upgrade this to an EXCLUSIVE lock. The
-+ ** busy-handler callback can be used when upgrading to the EXCLUSIVE
-+ ** lock, but not when obtaining the RESERVED lock.
-+ */
-+ rc = pagerLockDb(pPager, RESERVED_LOCK);
-+ if( rc==SQLITE_OK && exFlag ){
-+ rc = pager_wait_on_lock(pPager, EXCLUSIVE_LOCK);
-+ }
-+ }
-+
-+ if( rc==SQLITE_OK ){
-+ /* Change to WRITER_LOCKED state.
-+ **
-+ ** WAL mode sets Pager.eState to PAGER_WRITER_LOCKED or CACHEMOD
-+ ** when it has an open transaction, but never to DBMOD or FINISHED.
-+ ** This is because in those states the code to roll back savepoint
-+ ** transactions may copy data from the sub-journal into the database
-+ ** file as well as into the page cache. Which would be incorrect in
-+ ** WAL mode.
-+ */
-+ pPager->eState = PAGER_WRITER_LOCKED;
-+ pPager->dbHintSize = pPager->dbSize;
-+ pPager->dbFileSize = pPager->dbSize;
-+ pPager->dbOrigSize = pPager->dbSize;
-+ pPager->journalOff = 0;
-+ }
-+
-+ assert( rc==SQLITE_OK || pPager->eState==PAGER_READER );
-+ assert( rc!=SQLITE_OK || pPager->eState==PAGER_WRITER_LOCKED );
-+ assert( assert_pager_state(pPager) );
-+ }
+
-+ PAGERTRACE(("TRANSACTION %d\n", PAGERID(pPager)));
-+ return rc;
- }
--#endif
-
- /*
--** Parameter eStat must be either SQLITE_DBSTATUS_CACHE_HIT or
--** SQLITE_DBSTATUS_CACHE_MISS. Before returning, *pnVal is incremented by the
--** current cache hit or miss count, according to the value of eStat. If the
--** reset parameter is non-zero, the cache hit or miss count is zeroed before
--** returning.
-+** Mark a single data page as writeable. The page is written into the
-+** main journal or sub-journal as required. If the page is written into
-+** one of the journals, the corresponding bit is set in the
-+** Pager.pInJournal bitvec and the PagerSavepoint.pInSavepoint bitvecs
-+** of any open savepoints as appropriate.
- */
--SQLITE_PRIVATE void sqlite3PagerCacheStat(Pager *pPager, int eStat, int reset, int *pnVal){
-+static int pager_write(PgHdr *pPg){
-+ void *pData = pPg->pData;
-+ Pager *pPager = pPg->pPager;
-+ int rc = SQLITE_OK;
-
-- assert( eStat==SQLITE_DBSTATUS_CACHE_HIT
-- || eStat==SQLITE_DBSTATUS_CACHE_MISS
-- || eStat==SQLITE_DBSTATUS_CACHE_WRITE
-+ /* This routine is not called unless a write-transaction has already
-+ ** been started. The journal file may or may not be open at this point.
-+ ** It is never called in the ERROR state.
-+ */
-+ assert( pPager->eState==PAGER_WRITER_LOCKED
-+ || pPager->eState==PAGER_WRITER_CACHEMOD
-+ || pPager->eState==PAGER_WRITER_DBMOD
- );
-+ assert( assert_pager_state(pPager) );
-
-- assert( SQLITE_DBSTATUS_CACHE_HIT+1==SQLITE_DBSTATUS_CACHE_MISS );
-- assert( SQLITE_DBSTATUS_CACHE_HIT+2==SQLITE_DBSTATUS_CACHE_WRITE );
-- assert( PAGER_STAT_HIT==0 && PAGER_STAT_MISS==1 && PAGER_STAT_WRITE==2 );
-+ /* If an error has been previously detected, report the same error
-+ ** again. This should not happen, but the check provides robustness. */
-+ if( NEVER(pPager->errCode) ) return pPager->errCode;
-
-- *pnVal += pPager->aStat[eStat - SQLITE_DBSTATUS_CACHE_HIT];
-- if( reset ){
-- pPager->aStat[eStat - SQLITE_DBSTATUS_CACHE_HIT] = 0;
-+ /* Higher-level routines never call this function if database is not
-+ ** writable. But check anyway, just for robustness. */
-+ if( NEVER(pPager->readOnly) ) return SQLITE_PERM;
-+
-+ CHECK_PAGE(pPg);
-+
-+ /* The journal file needs to be opened. Higher level routines have already
-+ ** obtained the necessary locks to begin the write-transaction, but the
-+ ** rollback journal might not yet be open. Open it now if this is the case.
-+ **
-+ ** This is done before calling sqlite3PcacheMakeDirty() on the page.
-+ ** Otherwise, if it were done after calling sqlite3PcacheMakeDirty(), then
-+ ** an error might occur and the pager would end up in WRITER_LOCKED state
-+ ** with pages marked as dirty in the cache.
-+ */
-+ if( pPager->eState==PAGER_WRITER_LOCKED ){
-+ rc = pager_open_journal(pPager);
-+ if( rc!=SQLITE_OK ) return rc;
- }
--}
-+ assert( pPager->eState>=PAGER_WRITER_CACHEMOD );
-+ assert( assert_pager_state(pPager) );
-
--/*
--** Return true if this is an in-memory pager.
--*/
--SQLITE_PRIVATE int sqlite3PagerIsMemdb(Pager *pPager){
-- return MEMDB;
--}
-+ /* Mark the page as dirty. If the page has already been written
-+ ** to the journal then we can return right away.
-+ */
-+ sqlite3PcacheMakeDirty(pPg);
-+ if( pageInJournal(pPg) && !subjRequiresPage(pPg) ){
-+ assert( !pagerUseWal(pPager) );
-+ }else{
-+
-+ /* The transaction journal now exists and we have a RESERVED or an
-+ ** EXCLUSIVE lock on the main database file. Write the current page to
-+ ** the transaction journal if it is not there already.
-+ */
-+ if( !pageInJournal(pPg) && !pagerUseWal(pPager) ){
-+ assert( pagerUseWal(pPager)==0 );
-+ if( pPg->pgno<=pPager->dbOrigSize && isOpen(pPager->jfd) ){
-+ u32 cksum;
-+ char *pData2;
-+ i64 iOff = pPager->journalOff;
-
--/*
--** Check that there are at least nSavepoint savepoints open. If there are
--** currently less than nSavepoints open, then open one or more savepoints
--** to make up the difference. If the number of savepoints is already
--** equal to nSavepoint, then this function is a no-op.
--**
--** If a memory allocation fails, SQLITE_NOMEM is returned. If an error
--** occurs while opening the sub-journal file, then an IO error code is
--** returned. Otherwise, SQLITE_OK.
--*/
--SQLITE_PRIVATE int sqlite3PagerOpenSavepoint(Pager *pPager, int nSavepoint){
-- int rc = SQLITE_OK; /* Return code */
-- int nCurrent = pPager->nSavepoint; /* Current number of savepoints */
-+ /* We should never write to the journal file the page that
-+ ** contains the database locks. The following assert verifies
-+ ** that we do not. */
-+ assert( pPg->pgno!=PAGER_MJ_PGNO(pPager) );
-
-- assert( pPager->eState>=PAGER_WRITER_LOCKED );
-- assert( assert_pager_state(pPager) );
-+ assert( pPager->journalHdr<=pPager->journalOff );
-+ CODEC2(pPager, pData, pPg->pgno, 7, return SQLITE_NOMEM, pData2);
-+ cksum = pager_cksum(pPager, (u8*)pData2);
-
-- if( nSavepoint>nCurrent && pPager->useJournal ){
-- int ii; /* Iterator variable */
-- PagerSavepoint *aNew; /* New Pager.aSavepoint array */
-+ /* Even if an IO or diskfull error occurs while journalling the
-+ ** page in the block above, set the need-sync flag for the page.
-+ ** Otherwise, when the transaction is rolled back, the logic in
-+ ** playback_one_page() will think that the page needs to be restored
-+ ** in the database file. And if an IO error occurs while doing so,
-+ ** then corruption may follow.
-+ */
-+ pPg->flags |= PGHDR_NEED_SYNC;
-
-- /* Grow the Pager.aSavepoint array using realloc(). Return SQLITE_NOMEM
-- ** if the allocation fails. Otherwise, zero the new portion in case a
-- ** malloc failure occurs while populating it in the for(...) loop below.
-- */
-- aNew = (PagerSavepoint *)sqlite3Realloc(
-- pPager->aSavepoint, sizeof(PagerSavepoint)*nSavepoint
-- );
-- if( !aNew ){
-- return SQLITE_NOMEM;
-- }
-- memset(&aNew[nCurrent], 0, (nSavepoint-nCurrent) * sizeof(PagerSavepoint));
-- pPager->aSavepoint = aNew;
-+ rc = write32bits(pPager->jfd, iOff, pPg->pgno);
-+ if( rc!=SQLITE_OK ) return rc;
-+ rc = sqlite3OsWrite(pPager->jfd, pData2, pPager->pageSize, iOff+4);
-+ if( rc!=SQLITE_OK ) return rc;
-+ rc = write32bits(pPager->jfd, iOff+pPager->pageSize+4, cksum);
-+ if( rc!=SQLITE_OK ) return rc;
-
-- /* Populate the PagerSavepoint structures just allocated. */
-- for(ii=nCurrent; ii<nSavepoint; ii++){
-- aNew[ii].nOrig = pPager->dbSize;
-- if( isOpen(pPager->jfd) && pPager->journalOff>0 ){
-- aNew[ii].iOffset = pPager->journalOff;
-+ IOTRACE(("JOUT %p %d %lld %d\n", pPager, pPg->pgno,
-+ pPager->journalOff, pPager->pageSize));
-+ PAGER_INCR(sqlite3_pager_writej_count);
-+ PAGERTRACE(("JOURNAL %d page %d needSync=%d hash(%08x)\n",
-+ PAGERID(pPager), pPg->pgno,
-+ ((pPg->flags&PGHDR_NEED_SYNC)?1:0), pager_pagehash(pPg)));
-+
-+ pPager->journalOff += 8 + pPager->pageSize;
-+ pPager->nRec++;
-+ assert( pPager->pInJournal!=0 );
-+ rc = sqlite3BitvecSet(pPager->pInJournal, pPg->pgno);
-+ testcase( rc==SQLITE_NOMEM );
-+ assert( rc==SQLITE_OK || rc==SQLITE_NOMEM );
-+ rc |= addToSavepointBitvecs(pPager, pPg->pgno);
-+ if( rc!=SQLITE_OK ){
-+ assert( rc==SQLITE_NOMEM );
-+ return rc;
-+ }
- }else{
-- aNew[ii].iOffset = JOURNAL_HDR_SZ(pPager);
-- }
-- aNew[ii].iSubRec = pPager->nSubRec;
-- aNew[ii].pInSavepoint = sqlite3BitvecCreate(pPager->dbSize);
-- if( !aNew[ii].pInSavepoint ){
-- return SQLITE_NOMEM;
-- }
-- if( pagerUseWal(pPager) ){
-- sqlite3WalSavepoint(pPager->pWal, aNew[ii].aWalData);
-+ if( pPager->eState!=PAGER_WRITER_DBMOD ){
-+ pPg->flags |= PGHDR_NEED_SYNC;
-+ }
-+ PAGERTRACE(("APPEND %d page %d needSync=%d\n",
-+ PAGERID(pPager), pPg->pgno,
-+ ((pPg->flags&PGHDR_NEED_SYNC)?1:0)));
- }
-- pPager->nSavepoint = ii+1;
- }
-- assert( pPager->nSavepoint==nSavepoint );
-- assertTruncateConstraint(pPager);
-+
-+ /* If the statement journal is open and the page is not in it,
-+ ** then write the current page to the statement journal. Note that
-+ ** the statement journal format differs from the standard journal format
-+ ** in that it omits the checksums and the header.
-+ */
-+ if( subjRequiresPage(pPg) ){
-+ rc = subjournalPage(pPg);
-+ }
- }
-
-+ /* Update the database size and return.
-+ */
-+ if( pPager->dbSize<pPg->pgno ){
-+ pPager->dbSize = pPg->pgno;
-+ }
- return rc;
- }
-
- /*
--** This function is called to rollback or release (commit) a savepoint.
--** The savepoint to release or rollback need not be the most recently
--** created savepoint.
--**
--** Parameter op is always either SAVEPOINT_ROLLBACK or SAVEPOINT_RELEASE.
--** If it is SAVEPOINT_RELEASE, then release and destroy the savepoint with
--** index iSavepoint. If it is SAVEPOINT_ROLLBACK, then rollback all changes
--** that have occurred since the specified savepoint was created.
--**
--** The savepoint to rollback or release is identified by parameter
--** iSavepoint. A value of 0 means to operate on the outermost savepoint
--** (the first created). A value of (Pager.nSavepoint-1) means operate
--** on the most recently created savepoint. If iSavepoint is greater than
--** (Pager.nSavepoint-1), then this function is a no-op.
--**
--** If a negative value is passed to this function, then the current
--** transaction is rolled back. This is different to calling
--** sqlite3PagerRollback() because this function does not terminate
--** the transaction or unlock the database, it just restores the
--** contents of the database to its original state.
-+** Mark a data page as writeable. This routine must be called before
-+** making changes to a page. The caller must check the return value
-+** of this function and be careful not to change any page data unless
-+** this routine returns SQLITE_OK.
- **
--** In any case, all savepoints with an index greater than iSavepoint
--** are destroyed. If this is a release operation (op==SAVEPOINT_RELEASE),
--** then savepoint iSavepoint is also destroyed.
-+** The difference between this function and pager_write() is that this
-+** function also deals with the special case where 2 or more pages
-+** fit on a single disk sector. In this case all co-resident pages
-+** must have been written to the journal file before returning.
- **
--** This function may return SQLITE_NOMEM if a memory allocation fails,
--** or an IO error code if an IO error occurs while rolling back a
--** savepoint. If no errors occur, SQLITE_OK is returned.
--*/
--SQLITE_PRIVATE int sqlite3PagerSavepoint(Pager *pPager, int op, int iSavepoint){
-- int rc = pPager->errCode; /* Return code */
-+** If an error occurs, SQLITE_NOMEM or an IO error code is returned
-+** as appropriate. Otherwise, SQLITE_OK.
-+*/
-+SQLITE_PRIVATE int sqlite3PagerWrite(DbPage *pDbPage){
-+ int rc = SQLITE_OK;
-
-- assert( op==SAVEPOINT_RELEASE || op==SAVEPOINT_ROLLBACK );
-- assert( iSavepoint>=0 || op==SAVEPOINT_ROLLBACK );
-+ PgHdr *pPg = pDbPage;
-+ Pager *pPager = pPg->pPager;
-+ Pgno nPagePerSector = (pPager->sectorSize/pPager->pageSize);
-
-- if( rc==SQLITE_OK && iSavepoint<pPager->nSavepoint ){
-- int ii; /* Iterator variable */
-- int nNew; /* Number of remaining savepoints after this op. */
-+ assert( (pPg->flags & PGHDR_MMAP)==0 );
-+ assert( pPager->eState>=PAGER_WRITER_LOCKED );
-+ assert( pPager->eState!=PAGER_ERROR );
-+ assert( assert_pager_state(pPager) );
-+
-+ if( nPagePerSector>1 ){
-+ Pgno nPageCount; /* Total number of pages in database file */
-+ Pgno pg1; /* First page of the sector pPg is located on. */
-+ int nPage = 0; /* Number of pages starting at pg1 to journal */
-+ int ii; /* Loop counter */
-+ int needSync = 0; /* True if any page has PGHDR_NEED_SYNC */
-+
-+ /* Set the doNotSyncSpill flag to 1. This is because we cannot allow
-+ ** a journal header to be written between the pages journaled by
-+ ** this function.
-+ */
-+ assert( !MEMDB );
-+ assert( pPager->doNotSyncSpill==0 );
-+ pPager->doNotSyncSpill++;
-
-- /* Figure out how many savepoints will still be active after this
-- ** operation. Store this value in nNew. Then free resources associated
-- ** with any savepoints that are destroyed by this operation.
-+ /* This trick assumes that both the page-size and sector-size are
-+ ** an integer power of 2. It sets variable pg1 to the identifier
-+ ** of the first page of the sector pPg is located on.
- */
-- nNew = iSavepoint + (( op==SAVEPOINT_RELEASE ) ? 0 : 1);
-- for(ii=nNew; ii<pPager->nSavepoint; ii++){
-- sqlite3BitvecDestroy(pPager->aSavepoint[ii].pInSavepoint);
-+ pg1 = ((pPg->pgno-1) & ~(nPagePerSector-1)) + 1;
-+
-+ nPageCount = pPager->dbSize;
-+ if( pPg->pgno>nPageCount ){
-+ nPage = (pPg->pgno - pg1)+1;
-+ }else if( (pg1+nPagePerSector-1)>nPageCount ){
-+ nPage = nPageCount+1-pg1;
-+ }else{
-+ nPage = nPagePerSector;
- }
-- pPager->nSavepoint = nNew;
-+ assert(nPage>0);
-+ assert(pg1<=pPg->pgno);
-+ assert((pg1+nPage)>pPg->pgno);
-
-- /* If this is a release of the outermost savepoint, truncate
-- ** the sub-journal to zero bytes in size. */
-- if( op==SAVEPOINT_RELEASE ){
-- if( nNew==0 && isOpen(pPager->sjfd) ){
-- /* Only truncate if it is an in-memory sub-journal. */
-- if( sqlite3IsMemJournal(pPager->sjfd) ){
-- rc = sqlite3OsTruncate(pPager->sjfd, 0);
-- assert( rc==SQLITE_OK );
-+ for(ii=0; ii<nPage && rc==SQLITE_OK; ii++){
-+ Pgno pg = pg1+ii;
-+ PgHdr *pPage;
-+ if( pg==pPg->pgno || !sqlite3BitvecTest(pPager->pInJournal, pg) ){
-+ if( pg!=PAGER_MJ_PGNO(pPager) ){
-+ rc = sqlite3PagerGet(pPager, pg, &pPage);
-+ if( rc==SQLITE_OK ){
-+ rc = pager_write(pPage);
-+ if( pPage->flags&PGHDR_NEED_SYNC ){
-+ needSync = 1;
-+ }
-+ sqlite3PagerUnref(pPage);
-+ }
- }
-- pPager->nSubRec = 0;
-+ }else if( (pPage = pager_lookup(pPager, pg))!=0 ){
-+ if( pPage->flags&PGHDR_NEED_SYNC ){
-+ needSync = 1;
-+ }
-+ sqlite3PagerUnref(pPage);
- }
- }
-- /* Else this is a rollback operation, playback the specified savepoint.
-- ** If this is a temp-file, it is possible that the journal file has
-- ** not yet been opened. In this case there have been no changes to
-- ** the database file, so the playback operation can be skipped.
-+
-+ /* If the PGHDR_NEED_SYNC flag is set for any of the nPage pages
-+ ** starting at pg1, then it needs to be set for all of them. Because
-+ ** writing to any of these nPage pages may damage the others, the
-+ ** journal file must contain sync()ed copies of all of them
-+ ** before any of them can be written out to the database file.
- */
-- else if( pagerUseWal(pPager) || isOpen(pPager->jfd) ){
-- PagerSavepoint *pSavepoint = (nNew==0)?0:&pPager->aSavepoint[nNew-1];
-- rc = pagerPlaybackSavepoint(pPager, pSavepoint);
-- assert(rc!=SQLITE_DONE);
-+ if( rc==SQLITE_OK && needSync ){
-+ assert( !MEMDB );
-+ for(ii=0; ii<nPage; ii++){
-+ PgHdr *pPage = pager_lookup(pPager, pg1+ii);
-+ if( pPage ){
-+ pPage->flags |= PGHDR_NEED_SYNC;
-+ sqlite3PagerUnref(pPage);
-+ }
-+ }
- }
-- }
-
-+ assert( pPager->doNotSyncSpill==1 );
-+ pPager->doNotSyncSpill--;
-+ }else{
-+ rc = pager_write(pDbPage);
-+ }
- return rc;
- }
-
- /*
--** Return the full pathname of the database file.
--**
--** Except, if the pager is in-memory only, then return an empty string if
--** nullIfMemDb is true. This routine is called with nullIfMemDb==1 when
--** used to report the filename to the user, for compatibility with legacy
--** behavior. But when the Btree needs to know the filename for matching to
--** shared cache, it uses nullIfMemDb==0 so that in-memory databases can
--** participate in shared-cache.
-+** Return TRUE if the page given in the argument was previously passed
-+** to sqlite3PagerWrite(). In other words, return TRUE if it is ok
-+** to change the content of the page.
- */
--SQLITE_PRIVATE const char *sqlite3PagerFilename(Pager *pPager, int nullIfMemDb){
-- return (nullIfMemDb && pPager->memDb) ? "" : pPager->zFilename;
-+#ifndef NDEBUG
-+SQLITE_PRIVATE int sqlite3PagerIswriteable(DbPage *pPg){
-+ return pPg->flags&PGHDR_DIRTY;
- }
-+#endif
-
- /*
--** Return the VFS structure for the pager.
-+** A call to this routine tells the pager that it is not necessary to
-+** write the information on page pPg back to the disk, even though
-+** that page might be marked as dirty. This happens, for example, when
-+** the page has been added as a leaf of the freelist and so its
-+** content no longer matters.
-+**
-+** The overlying software layer calls this routine when all of the data
-+** on the given page is unused. The pager marks the page as clean so
-+** that it does not get written to disk.
-+**
-+** Tests show that this optimization can quadruple the speed of large
-+** DELETE operations.
- */
--SQLITE_PRIVATE const sqlite3_vfs *sqlite3PagerVfs(Pager *pPager){
-- return pPager->pVfs;
-+SQLITE_PRIVATE void sqlite3PagerDontWrite(PgHdr *pPg){
-+ Pager *pPager = pPg->pPager;
-+ if( (pPg->flags&PGHDR_DIRTY) && pPager->nSavepoint==0 ){
-+ PAGERTRACE(("DONT_WRITE page %d of %d\n", pPg->pgno, PAGERID(pPager)));
-+ IOTRACE(("CLEAN %p %d\n", pPager, pPg->pgno))
-+ pPg->flags |= PGHDR_DONT_WRITE;
-+ pager_set_pagehash(pPg);
-+ }
- }
-
- /*
--** Return the file handle for the database file associated
--** with the pager. This might return NULL if the file has
--** not yet been opened.
-+** This routine is called to increment the value of the database file
-+** change-counter, stored as a 4-byte big-endian integer starting at
-+** byte offset 24 of the pager file. The secondary change counter at
-+** 92 is also updated, as is the SQLite version number at offset 96.
-+**
-+** But this only happens if the pPager->changeCountDone flag is false.
-+** To avoid excess churning of page 1, the update only happens once.
-+** See also the pager_write_changecounter() routine that does an
-+** unconditional update of the change counters.
-+**
-+** If the isDirectMode flag is zero, then this is done by calling
-+** sqlite3PagerWrite() on page 1, then modifying the contents of the
-+** page data. In this case the file will be updated when the current
-+** transaction is committed.
-+**
-+** The isDirectMode flag may only be non-zero if the library was compiled
-+** with the SQLITE_ENABLE_ATOMIC_WRITE macro defined. In this case,
-+** if isDirect is non-zero, then the database file is updated directly
-+** by writing an updated version of page 1 using a call to the
-+** sqlite3OsWrite() function.
- */
--SQLITE_PRIVATE sqlite3_file *sqlite3PagerFile(Pager *pPager){
-- return pPager->fd;
--}
-+static int pager_incr_changecounter(Pager *pPager, int isDirectMode){
-+ int rc = SQLITE_OK;
-
--/*
--** Return the full pathname of the journal file.
--*/
--SQLITE_PRIVATE const char *sqlite3PagerJournalname(Pager *pPager){
-- return pPager->zJournal;
-+ assert( pPager->eState==PAGER_WRITER_CACHEMOD
-+ || pPager->eState==PAGER_WRITER_DBMOD
-+ );
-+ assert( assert_pager_state(pPager) );
-+
-+ /* Declare and initialize constant integer 'isDirect'. If the
-+ ** atomic-write optimization is enabled in this build, then isDirect
-+ ** is initialized to the value passed as the isDirectMode parameter
-+ ** to this function. Otherwise, it is always set to zero.
-+ **
-+ ** The idea is that if the atomic-write optimization is not
-+ ** enabled at compile time, the compiler can omit the tests of
-+ ** 'isDirect' below, as well as the block enclosed in the
-+ ** "if( isDirect )" condition.
-+ */
-+#ifndef SQLITE_ENABLE_ATOMIC_WRITE
-+# define DIRECT_MODE 0
-+ assert( isDirectMode==0 );
-+ UNUSED_PARAMETER(isDirectMode);
-+#else
-+# define DIRECT_MODE isDirectMode
-+#endif
-+
-+ if( !pPager->changeCountDone && ALWAYS(pPager->dbSize>0) ){
-+ PgHdr *pPgHdr; /* Reference to page 1 */
-+
-+ assert( !pPager->tempFile && isOpen(pPager->fd) );
-+
-+ /* Open page 1 of the file for writing. */
-+ rc = sqlite3PagerGet(pPager, 1, &pPgHdr);
-+ assert( pPgHdr==0 || rc==SQLITE_OK );
-+
-+ /* If page one was fetched successfully, and this function is not
-+ ** operating in direct-mode, make page 1 writable. When not in
-+ ** direct mode, page 1 is always held in cache and hence the PagerGet()
-+ ** above is always successful - hence the ALWAYS on rc==SQLITE_OK.
-+ */
-+ if( !DIRECT_MODE && ALWAYS(rc==SQLITE_OK) ){
-+ rc = sqlite3PagerWrite(pPgHdr);
-+ }
-+
-+ if( rc==SQLITE_OK ){
-+ /* Actually do the update of the change counter */
-+ pager_write_changecounter(pPgHdr);
-+
-+ /* If running in direct mode, write the contents of page 1 to the file. */
-+ if( DIRECT_MODE ){
-+ const void *zBuf;
-+ assert( pPager->dbFileSize>0 );
-+ CODEC2(pPager, pPgHdr->pData, 1, 6, rc=SQLITE_NOMEM, zBuf);
-+ if( rc==SQLITE_OK ){
-+ rc = sqlite3OsWrite(pPager->fd, zBuf, pPager->pageSize, 0);
-+ pPager->aStat[PAGER_STAT_WRITE]++;
-+ }
-+ if( rc==SQLITE_OK ){
-+ /* Update the pager's copy of the change-counter. Otherwise, the
-+ ** next time a read transaction is opened the cache will be
-+ ** flushed (as the change-counter values will not match). */
-+ const void *pCopy = (const void *)&((const char *)zBuf)[24];
-+ memcpy(&pPager->dbFileVers, pCopy, sizeof(pPager->dbFileVers));
-+ pPager->changeCountDone = 1;
-+ }
-+ }else{
-+ pPager->changeCountDone = 1;
-+ }
-+ }
-+
-+ /* Release the page reference. */
-+ sqlite3PagerUnref(pPgHdr);
-+ }
-+ return rc;
- }
-
- /*
--** Return true if fsync() calls are disabled for this pager. Return FALSE
--** if fsync()s are executed normally.
-+** Sync the database file to disk. This is a no-op for in-memory databases
-+** or pages with the Pager.noSync flag set.
-+**
-+** If successful, or if called on a pager for which it is a no-op, this
-+** function returns SQLITE_OK. Otherwise, an IO error code is returned.
- */
--SQLITE_PRIVATE int sqlite3PagerNosync(Pager *pPager){
-- return pPager->noSync;
-+SQLITE_PRIVATE int sqlite3PagerSync(Pager *pPager){
-+ int rc = SQLITE_OK;
-+ if( !pPager->noSync ){
-+ assert( !MEMDB );
-+ rc = sqlite3OsSync(pPager->fd, pPager->syncFlags);
-+ }else if( isOpen(pPager->fd) ){
-+ assert( !MEMDB );
-+ rc = sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_SYNC_OMITTED, 0);
-+ if( rc==SQLITE_NOTFOUND ){
-+ rc = SQLITE_OK;
-+ }
-+ }
-+ return rc;
- }
-
--#ifdef SQLITE_HAS_CODEC
- /*
--** Set or retrieve the codec for this pager
-+** This function may only be called while a write-transaction is active in
-+** rollback. If the connection is in WAL mode, this call is a no-op.
-+** Otherwise, if the connection does not already have an EXCLUSIVE lock on
-+** the database file, an attempt is made to obtain one.
-+**
-+** If the EXCLUSIVE lock is already held or the attempt to obtain it is
-+** successful, or the connection is in WAL mode, SQLITE_OK is returned.
-+** Otherwise, either SQLITE_BUSY or an SQLITE_IOERR_XXX error code is
-+** returned.
- */
--SQLITE_PRIVATE void sqlite3PagerSetCodec(
-- Pager *pPager,
-- void *(*xCodec)(void*,void*,Pgno,int),
-- void (*xCodecSizeChng)(void*,int,int),
-- void (*xCodecFree)(void*),
-- void *pCodec
--){
-- if( pPager->xCodecFree ) pPager->xCodecFree(pPager->pCodec);
-- pPager->xCodec = pPager->memDb ? 0 : xCodec;
-- pPager->xCodecSizeChng = xCodecSizeChng;
-- pPager->xCodecFree = xCodecFree;
-- pPager->pCodec = pCodec;
-- pagerReportSize(pPager);
--}
--SQLITE_PRIVATE void *sqlite3PagerGetCodec(Pager *pPager){
-- return pPager->pCodec;
-+SQLITE_PRIVATE int sqlite3PagerExclusiveLock(Pager *pPager){
-+ int rc = SQLITE_OK;
-+ assert( pPager->eState==PAGER_WRITER_CACHEMOD
-+ || pPager->eState==PAGER_WRITER_DBMOD
-+ || pPager->eState==PAGER_WRITER_LOCKED
-+ );
-+ assert( assert_pager_state(pPager) );
-+ if( 0==pagerUseWal(pPager) ){
-+ rc = pager_wait_on_lock(pPager, EXCLUSIVE_LOCK);
-+ }
-+ return rc;
- }
--#endif
-
--#ifndef SQLITE_OMIT_AUTOVACUUM
- /*
--** Move the page pPg to location pgno in the file.
-+** Sync the database file for the pager pPager. zMaster points to the name
-+** of a master journal file that should be written into the individual
-+** journal file. zMaster may be NULL, which is interpreted as no master
-+** journal (a single database transaction).
- **
--** There must be no references to the page previously located at
--** pgno (which we call pPgOld) though that page is allowed to be
--** in cache. If the page previously located at pgno is not already
--** in the rollback journal, it is not put there by by this routine.
-+** This routine ensures that:
- **
--** References to the page pPg remain valid. Updating any
--** meta-data associated with pPg (i.e. data stored in the nExtra bytes
--** allocated along with the page) is the responsibility of the caller.
-+** * The database file change-counter is updated,
-+** * the journal is synced (unless the atomic-write optimization is used),
-+** * all dirty pages are written to the database file,
-+** * the database file is truncated (if required), and
-+** * the database file synced.
- **
--** A transaction must be active when this routine is called. It used to be
--** required that a statement transaction was not active, but this restriction
--** has been removed (CREATE INDEX needs to move a page when a statement
--** transaction is active).
-+** The only thing that remains to commit the transaction is to finalize
-+** (delete, truncate or zero the first part of) the journal file (or
-+** delete the master journal file if specified).
- **
--** If the fourth argument, isCommit, is non-zero, then this page is being
--** moved as part of a database reorganization just before the transaction
--** is being committed. In this case, it is guaranteed that the database page
--** pPg refers to will not be written to again within this transaction.
-+** Note that if zMaster==NULL, this does not overwrite a previous value
-+** passed to an sqlite3PagerCommitPhaseOne() call.
- **
--** This function may return SQLITE_NOMEM or an IO error code if an error
--** occurs. Otherwise, it returns SQLITE_OK.
-+** If the final parameter - noSync - is true, then the database file itself
-+** is not synced. The caller must call sqlite3PagerSync() directly to
-+** sync the database file before calling CommitPhaseTwo() to delete the
-+** journal file in this case.
- */
--SQLITE_PRIVATE int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno, int isCommit){
-- PgHdr *pPgOld; /* The page being overwritten. */
-- Pgno needSyncPgno = 0; /* Old value of pPg->pgno, if sync is required */
-- int rc; /* Return code */
-- Pgno origPgno; /* The original page number */
-+SQLITE_PRIVATE int sqlite3PagerCommitPhaseOne(
-+ Pager *pPager, /* Pager object */
-+ const char *zMaster, /* If not NULL, the master journal name */
-+ int noSync /* True to omit the xSync on the db file */
-+){
-+ int rc = SQLITE_OK; /* Return code */
-
-- assert( pPg->nRef>0 );
-- assert( pPager->eState==PAGER_WRITER_CACHEMOD
-+ assert( pPager->eState==PAGER_WRITER_LOCKED
-+ || pPager->eState==PAGER_WRITER_CACHEMOD
- || pPager->eState==PAGER_WRITER_DBMOD
-+ || pPager->eState==PAGER_ERROR
- );
- assert( assert_pager_state(pPager) );
-
-- /* In order to be able to rollback, an in-memory database must journal
-- ** the page we are moving from.
-- */
-- if( MEMDB ){
-- rc = sqlite3PagerWrite(pPg);
-- if( rc ) return rc;
-- }
--
-- /* If the page being moved is dirty and has not been saved by the latest
-- ** savepoint, then save the current contents of the page into the
-- ** sub-journal now. This is required to handle the following scenario:
-- **
-- ** BEGIN;
-- ** <journal page X, then modify it in memory>
-- ** SAVEPOINT one;
-- ** <Move page X to location Y>
-- ** ROLLBACK TO one;
-- **
-- ** If page X were not written to the sub-journal here, it would not
-- ** be possible to restore its contents when the "ROLLBACK TO one"
-- ** statement were is processed.
-- **
-- ** subjournalPage() may need to allocate space to store pPg->pgno into
-- ** one or more savepoint bitvecs. This is the reason this function
-- ** may return SQLITE_NOMEM.
-- */
-- if( pPg->flags&PGHDR_DIRTY
-- && subjRequiresPage(pPg)
-- && SQLITE_OK!=(rc = subjournalPage(pPg))
-- ){
-- return rc;
-- }
--
-- PAGERTRACE(("MOVE %d page %d (needSync=%d) moves to %d\n",
-- PAGERID(pPager), pPg->pgno, (pPg->flags&PGHDR_NEED_SYNC)?1:0, pgno));
-- IOTRACE(("MOVE %p %d %d\n", pPager, pPg->pgno, pgno))
--
-- /* If the journal needs to be sync()ed before page pPg->pgno can
-- ** be written to, store pPg->pgno in local variable needSyncPgno.
-- **
-- ** If the isCommit flag is set, there is no need to remember that
-- ** the journal needs to be sync()ed before database page pPg->pgno
-- ** can be written to. The caller has already promised not to write to it.
-- */
-- if( (pPg->flags&PGHDR_NEED_SYNC) && !isCommit ){
-- needSyncPgno = pPg->pgno;
-- assert( pPager->journalMode==PAGER_JOURNALMODE_OFF ||
-- pageInJournal(pPg) || pPg->pgno>pPager->dbOrigSize );
-- assert( pPg->flags&PGHDR_DIRTY );
-- }
-+ /* If a prior error occurred, report that error again. */
-+ if( NEVER(pPager->errCode) ) return pPager->errCode;
-
-- /* If the cache contains a page with page-number pgno, remove it
-- ** from its hash chain. Also, if the PGHDR_NEED_SYNC flag was set for
-- ** page pgno before the 'move' operation, it needs to be retained
-- ** for the page moved there.
-- */
-- pPg->flags &= ~PGHDR_NEED_SYNC;
-- pPgOld = pager_lookup(pPager, pgno);
-- assert( !pPgOld || pPgOld->nRef==1 );
-- if( pPgOld ){
-- pPg->flags |= (pPgOld->flags&PGHDR_NEED_SYNC);
-- if( MEMDB ){
-- /* Do not discard pages from an in-memory database since we might
-- ** need to rollback later. Just move the page out of the way. */
-- sqlite3PcacheMove(pPgOld, pPager->dbSize+1);
-- }else{
-- sqlite3PcacheDrop(pPgOld);
-- }
-- }
-+ PAGERTRACE(("DATABASE SYNC: File=%s zMaster=%s nSize=%d\n",
-+ pPager->zFilename, zMaster, pPager->dbSize));
-
-- origPgno = pPg->pgno;
-- sqlite3PcacheMove(pPg, pgno);
-- sqlite3PcacheMakeDirty(pPg);
-+ /* If no database changes have been made, return early. */
-+ if( pPager->eState<PAGER_WRITER_CACHEMOD ) return SQLITE_OK;
-
-- /* For an in-memory database, make sure the original page continues
-- ** to exist, in case the transaction needs to roll back. Use pPgOld
-- ** as the original page since it has already been allocated.
-- */
- if( MEMDB ){
-- assert( pPgOld );
-- sqlite3PcacheMove(pPgOld, origPgno);
-- sqlite3PagerUnref(pPgOld);
-- }
-+ /* If this is an in-memory db, or no pages have been written to, or this
-+ ** function has already been called, it is mostly a no-op. However, any
-+ ** backup in progress needs to be restarted.
-+ */
-+ sqlite3BackupRestart(pPager->pBackup);
-+ }else{
-+ if( pagerUseWal(pPager) ){
-+ PgHdr *pList = sqlite3PcacheDirtyList(pPager->pPCache);
-+ PgHdr *pPageOne = 0;
-+ if( pList==0 ){
-+ /* Must have at least one page for the WAL commit flag.
-+ ** Ticket [2d1a5c67dfc2363e44f29d9bbd57f] 2011-05-18 */
-+ rc = sqlite3PagerGet(pPager, 1, &pPageOne);
-+ pList = pPageOne;
-+ pList->pDirty = 0;
-+ }
-+ assert( rc==SQLITE_OK );
-+ if( ALWAYS(pList) ){
-+ rc = pagerWalFrames(pPager, pList, pPager->dbSize, 1);
-+ }
-+ sqlite3PagerUnref(pPageOne);
-+ if( rc==SQLITE_OK ){
-+ sqlite3PcacheCleanAll(pPager->pPCache);
-+ }
-+ }else{
-+ /* The following block updates the change-counter. Exactly how it
-+ ** does this depends on whether or not the atomic-update optimization
-+ ** was enabled at compile time, and if this transaction meets the
-+ ** runtime criteria to use the operation:
-+ **
-+ ** * The file-system supports the atomic-write property for
-+ ** blocks of size page-size, and
-+ ** * This commit is not part of a multi-file transaction, and
-+ ** * Exactly one page has been modified and store in the journal file.
-+ **
-+ ** If the optimization was not enabled at compile time, then the
-+ ** pager_incr_changecounter() function is called to update the change
-+ ** counter in 'indirect-mode'. If the optimization is compiled in but
-+ ** is not applicable to this transaction, call sqlite3JournalCreate()
-+ ** to make sure the journal file has actually been created, then call
-+ ** pager_incr_changecounter() to update the change-counter in indirect
-+ ** mode.
-+ **
-+ ** Otherwise, if the optimization is both enabled and applicable,
-+ ** then call pager_incr_changecounter() to update the change-counter
-+ ** in 'direct' mode. In this case the journal file will never be
-+ ** created for this transaction.
-+ */
-+ #ifdef SQLITE_ENABLE_ATOMIC_WRITE
-+ PgHdr *pPg;
-+ assert( isOpen(pPager->jfd)
-+ || pPager->journalMode==PAGER_JOURNALMODE_OFF
-+ || pPager->journalMode==PAGER_JOURNALMODE_WAL
-+ );
-+ if( !zMaster && isOpen(pPager->jfd)
-+ && pPager->journalOff==jrnlBufferSize(pPager)
-+ && pPager->dbSize>=pPager->dbOrigSize
-+ && (0==(pPg = sqlite3PcacheDirtyList(pPager->pPCache)) || 0==pPg->pDirty)
-+ ){
-+ /* Update the db file change counter via the direct-write method. The
-+ ** following call will modify the in-memory representation of page 1
-+ ** to include the updated change counter and then write page 1
-+ ** directly to the database file. Because of the atomic-write
-+ ** property of the host file-system, this is safe.
-+ */
-+ rc = pager_incr_changecounter(pPager, 1);
-+ }else{
-+ rc = sqlite3JournalCreate(pPager->jfd);
-+ if( rc==SQLITE_OK ){
-+ rc = pager_incr_changecounter(pPager, 0);
-+ }
-+ }
-+ #else
-+ rc = pager_incr_changecounter(pPager, 0);
-+ #endif
-+ if( rc!=SQLITE_OK ) goto commit_phase_one_exit;
-+
-+ /* Write the master journal name into the journal file. If a master
-+ ** journal file name has already been written to the journal file,
-+ ** or if zMaster is NULL (no master journal), then this call is a no-op.
-+ */
-+ rc = writeMasterJournal(pPager, zMaster);
-+ if( rc!=SQLITE_OK ) goto commit_phase_one_exit;
-+
-+ /* Sync the journal file and write all dirty pages to the database.
-+ ** If the atomic-update optimization is being used, this sync will not
-+ ** create the journal file or perform any real IO.
-+ **
-+ ** Because the change-counter page was just modified, unless the
-+ ** atomic-update optimization is used it is almost certain that the
-+ ** journal requires a sync here. However, in locking_mode=exclusive
-+ ** on a system under memory pressure it is just possible that this is
-+ ** not the case. In this case it is likely enough that the redundant
-+ ** xSync() call will be changed to a no-op by the OS anyhow.
-+ */
-+ rc = syncJournal(pPager, 0);
-+ if( rc!=SQLITE_OK ) goto commit_phase_one_exit;
-+
-+ rc = pager_write_pagelist(pPager,sqlite3PcacheDirtyList(pPager->pPCache));
-+ if( rc!=SQLITE_OK ){
-+ assert( rc!=SQLITE_IOERR_BLOCKED );
-+ goto commit_phase_one_exit;
-+ }
-+ sqlite3PcacheCleanAll(pPager->pPCache);
-
-- if( needSyncPgno ){
-- /* If needSyncPgno is non-zero, then the journal file needs to be
-- ** sync()ed before any data is written to database file page needSyncPgno.
-- ** Currently, no such page exists in the page-cache and the
-- ** "is journaled" bitvec flag has been set. This needs to be remedied by
-- ** loading the page into the pager-cache and setting the PGHDR_NEED_SYNC
-- ** flag.
-- **
-- ** If the attempt to load the page into the page-cache fails, (due
-- ** to a malloc() or IO failure), clear the bit in the pInJournal[]
-- ** array. Otherwise, if the page is loaded and written again in
-- ** this transaction, it may be written to the database file before
-- ** it is synced into the journal file. This way, it may end up in
-- ** the journal file twice, but that is not a problem.
-- */
-- PgHdr *pPgHdr;
-- rc = sqlite3PagerGet(pPager, needSyncPgno, &pPgHdr);
-- if( rc!=SQLITE_OK ){
-- if( needSyncPgno<=pPager->dbOrigSize ){
-- assert( pPager->pTmpSpace!=0 );
-- sqlite3BitvecClear(pPager->pInJournal, needSyncPgno, pPager->pTmpSpace);
-+ /* If the file on disk is smaller than the database image, use
-+ ** pager_truncate to grow the file here. This can happen if the database
-+ ** image was extended as part of the current transaction and then the
-+ ** last page in the db image moved to the free-list. In this case the
-+ ** last page is never written out to disk, leaving the database file
-+ ** undersized. Fix this now if it is the case. */
-+ if( pPager->dbSize>pPager->dbFileSize ){
-+ Pgno nNew = pPager->dbSize - (pPager->dbSize==PAGER_MJ_PGNO(pPager));
-+ assert( pPager->eState==PAGER_WRITER_DBMOD );
-+ rc = pager_truncate(pPager, nNew);
-+ if( rc!=SQLITE_OK ) goto commit_phase_one_exit;
- }
-- return rc;
-+
-+ /* Finally, sync the database file. */
-+ if( !noSync ){
-+ rc = sqlite3PagerSync(pPager);
-+ }
-+ IOTRACE(("DBSYNC %p\n", pPager))
- }
-- pPgHdr->flags |= PGHDR_NEED_SYNC;
-- sqlite3PcacheMakeDirty(pPgHdr);
-- sqlite3PagerUnref(pPgHdr);
- }
-
-- return SQLITE_OK;
--}
--#endif
--
--/*
--** Return a pointer to the data for the specified page.
--*/
--SQLITE_PRIVATE void *sqlite3PagerGetData(DbPage *pPg){
-- assert( pPg->nRef>0 || pPg->pPager->memDb );
-- return pPg->pData;
-+commit_phase_one_exit:
-+ if( rc==SQLITE_OK && !pagerUseWal(pPager) ){
-+ pPager->eState = PAGER_WRITER_FINISHED;
-+ }
-+ return rc;
- }
-
--/*
--** Return a pointer to the Pager.nExtra bytes of "extra" space
--** allocated along with the specified page.
--*/
--SQLITE_PRIVATE void *sqlite3PagerGetExtra(DbPage *pPg){
-- return pPg->pExtra;
--}
-
- /*
--** Get/set the locking-mode for this pager. Parameter eMode must be one
--** of PAGER_LOCKINGMODE_QUERY, PAGER_LOCKINGMODE_NORMAL or
--** PAGER_LOCKINGMODE_EXCLUSIVE. If the parameter is not _QUERY, then
--** the locking-mode is set to the value specified.
-+** When this function is called, the database file has been completely
-+** updated to reflect the changes made by the current transaction and
-+** synced to disk. The journal file still exists in the file-system
-+** though, and if a failure occurs at this point it will eventually
-+** be used as a hot-journal and the current transaction rolled back.
- **
--** The returned value is either PAGER_LOCKINGMODE_NORMAL or
--** PAGER_LOCKINGMODE_EXCLUSIVE, indicating the current (possibly updated)
--** locking-mode.
-+** This function finalizes the journal file, either by deleting,
-+** truncating or partially zeroing it, so that it cannot be used
-+** for hot-journal rollback. Once this is done the transaction is
-+** irrevocably committed.
-+**
-+** If an error occurs, an IO error code is returned and the pager
-+** moves into the error state. Otherwise, SQLITE_OK is returned.
- */
--SQLITE_PRIVATE int sqlite3PagerLockingMode(Pager *pPager, int eMode){
-- assert( eMode==PAGER_LOCKINGMODE_QUERY
-- || eMode==PAGER_LOCKINGMODE_NORMAL
-- || eMode==PAGER_LOCKINGMODE_EXCLUSIVE );
-- assert( PAGER_LOCKINGMODE_QUERY<0 );
-- assert( PAGER_LOCKINGMODE_NORMAL>=0 && PAGER_LOCKINGMODE_EXCLUSIVE>=0 );
-- assert( pPager->exclusiveMode || 0==sqlite3WalHeapMemory(pPager->pWal) );
-- if( eMode>=0 && !pPager->tempFile && !sqlite3WalHeapMemory(pPager->pWal) ){
-- pPager->exclusiveMode = (u8)eMode;
-+SQLITE_PRIVATE int sqlite3PagerCommitPhaseTwo(Pager *pPager){
-+ int rc = SQLITE_OK; /* Return code */
-+
-+ /* This routine should not be called if a prior error has occurred.
-+ ** But if (due to a coding error elsewhere in the system) it does get
-+ ** called, just return the same error code without doing anything. */
-+ if( NEVER(pPager->errCode) ) return pPager->errCode;
-+
-+ assert( pPager->eState==PAGER_WRITER_LOCKED
-+ || pPager->eState==PAGER_WRITER_FINISHED
-+ || (pagerUseWal(pPager) && pPager->eState==PAGER_WRITER_CACHEMOD)
-+ );
-+ assert( assert_pager_state(pPager) );
-+
-+ /* An optimization. If the database was not actually modified during
-+ ** this transaction, the pager is running in exclusive-mode and is
-+ ** using persistent journals, then this function is a no-op.
-+ **
-+ ** The start of the journal file currently contains a single journal
-+ ** header with the nRec field set to 0. If such a journal is used as
-+ ** a hot-journal during hot-journal rollback, 0 changes will be made
-+ ** to the database file. So there is no need to zero the journal
-+ ** header. Since the pager is in exclusive mode, there is no need
-+ ** to drop any locks either.
-+ */
-+ if( pPager->eState==PAGER_WRITER_LOCKED
-+ && pPager->exclusiveMode
-+ && pPager->journalMode==PAGER_JOURNALMODE_PERSIST
-+ ){
-+ assert( pPager->journalOff==JOURNAL_HDR_SZ(pPager) || !pPager->journalOff );
-+ pPager->eState = PAGER_READER;
-+ return SQLITE_OK;
- }
-- return (int)pPager->exclusiveMode;
-+
-+ PAGERTRACE(("COMMIT %d\n", PAGERID(pPager)));
-+ rc = pager_end_transaction(pPager, pPager->setMaster, 1);
-+ return pager_error(pPager, rc);
- }
-
- /*
--** Set the journal-mode for this pager. Parameter eMode must be one of:
-+** If a write transaction is open, then all changes made within the
-+** transaction are reverted and the current write-transaction is closed.
-+** The pager falls back to PAGER_READER state if successful, or PAGER_ERROR
-+** state if an error occurs.
- **
--** PAGER_JOURNALMODE_DELETE
--** PAGER_JOURNALMODE_TRUNCATE
--** PAGER_JOURNALMODE_PERSIST
--** PAGER_JOURNALMODE_OFF
--** PAGER_JOURNALMODE_MEMORY
--** PAGER_JOURNALMODE_WAL
-+** If the pager is already in PAGER_ERROR state when this function is called,
-+** it returns Pager.errCode immediately. No work is performed in this case.
- **
--** The journalmode is set to the value specified if the change is allowed.
--** The change may be disallowed for the following reasons:
-+** Otherwise, in rollback mode, this function performs two functions:
- **
--** * An in-memory database can only have its journal_mode set to _OFF
--** or _MEMORY.
-+** 1) It rolls back the journal file, restoring all database file and
-+** in-memory cache pages to the state they were in when the transaction
-+** was opened, and
- **
--** * Temporary databases cannot have _WAL journalmode.
-+** 2) It finalizes the journal file, so that it is not used for hot
-+** rollback at any point in the future.
- **
--** The returned indicate the current (possibly updated) journal-mode.
-+** Finalization of the journal file (task 2) is only performed if the
-+** rollback is successful.
-+**
-+** In WAL mode, all cache-entries containing data modified within the
-+** current transaction are either expelled from the cache or reverted to
-+** their pre-transaction state by re-reading data from the database or
-+** WAL files. The WAL transaction is then closed.
- */
--SQLITE_PRIVATE int sqlite3PagerSetJournalMode(Pager *pPager, int eMode){
-- u8 eOld = pPager->journalMode; /* Prior journalmode */
--
--#ifdef SQLITE_DEBUG
-- /* The print_pager_state() routine is intended to be used by the debugger
-- ** only. We invoke it once here to suppress a compiler warning. */
-- print_pager_state(pPager);
--#endif
--
--
-- /* The eMode parameter is always valid */
-- assert( eMode==PAGER_JOURNALMODE_DELETE
-- || eMode==PAGER_JOURNALMODE_TRUNCATE
-- || eMode==PAGER_JOURNALMODE_PERSIST
-- || eMode==PAGER_JOURNALMODE_OFF
-- || eMode==PAGER_JOURNALMODE_WAL
-- || eMode==PAGER_JOURNALMODE_MEMORY );
--
-- /* This routine is only called from the OP_JournalMode opcode, and
-- ** the logic there will never allow a temporary file to be changed
-- ** to WAL mode.
-- */
-- assert( pPager->tempFile==0 || eMode!=PAGER_JOURNALMODE_WAL );
-+SQLITE_PRIVATE int sqlite3PagerRollback(Pager *pPager){
-+ int rc = SQLITE_OK; /* Return code */
-+ PAGERTRACE(("ROLLBACK %d\n", PAGERID(pPager)));
-
-- /* Do allow the journalmode of an in-memory database to be set to
-- ** anything other than MEMORY or OFF
-+ /* PagerRollback() is a no-op if called in READER or OPEN state. If
-+ ** the pager is already in the ERROR state, the rollback is not
-+ ** attempted here. Instead, the error code is returned to the caller.
- */
-- if( MEMDB ){
-- assert( eOld==PAGER_JOURNALMODE_MEMORY || eOld==PAGER_JOURNALMODE_OFF );
-- if( eMode!=PAGER_JOURNALMODE_MEMORY && eMode!=PAGER_JOURNALMODE_OFF ){
-- eMode = eOld;
-- }
-- }
--
-- if( eMode!=eOld ){
--
-- /* Change the journal mode. */
-- assert( pPager->eState!=PAGER_ERROR );
-- pPager->journalMode = (u8)eMode;
--
-- /* When transistioning from TRUNCATE or PERSIST to any other journal
-- ** mode except WAL, unless the pager is in locking_mode=exclusive mode,
-- ** delete the journal file.
-- */
-- assert( (PAGER_JOURNALMODE_TRUNCATE & 5)==1 );
-- assert( (PAGER_JOURNALMODE_PERSIST & 5)==1 );
-- assert( (PAGER_JOURNALMODE_DELETE & 5)==0 );
-- assert( (PAGER_JOURNALMODE_MEMORY & 5)==4 );
-- assert( (PAGER_JOURNALMODE_OFF & 5)==0 );
-- assert( (PAGER_JOURNALMODE_WAL & 5)==5 );
--
-- assert( isOpen(pPager->fd) || pPager->exclusiveMode );
-- if( !pPager->exclusiveMode && (eOld & 5)==1 && (eMode & 1)==0 ){
-+ assert( assert_pager_state(pPager) );
-+ if( pPager->eState==PAGER_ERROR ) return pPager->errCode;
-+ if( pPager->eState<=PAGER_READER ) return SQLITE_OK;
-
-- /* In this case we would like to delete the journal file. If it is
-- ** not possible, then that is not a problem. Deleting the journal file
-- ** here is an optimization only.
-- **
-- ** Before deleting the journal file, obtain a RESERVED lock on the
-- ** database file. This ensures that the journal file is not deleted
-- ** while it is in use by some other client.
-+ if( pagerUseWal(pPager) ){
-+ int rc2;
-+ rc = sqlite3PagerSavepoint(pPager, SAVEPOINT_ROLLBACK, -1);
-+ rc2 = pager_end_transaction(pPager, pPager->setMaster, 0);
-+ if( rc==SQLITE_OK ) rc = rc2;
-+ }else if( !isOpen(pPager->jfd) || pPager->eState==PAGER_WRITER_LOCKED ){
-+ int eState = pPager->eState;
-+ rc = pager_end_transaction(pPager, 0, 0);
-+ if( !MEMDB && eState>PAGER_WRITER_LOCKED ){
-+ /* This can happen using journal_mode=off. Move the pager to the error
-+ ** state to indicate that the contents of the cache may not be trusted.
-+ ** Any active readers will get SQLITE_ABORT.
- */
-- sqlite3OsClose(pPager->jfd);
-- if( pPager->eLock>=RESERVED_LOCK ){
-- sqlite3OsDelete(pPager->pVfs, pPager->zJournal, 0);
-- }else{
-- int rc = SQLITE_OK;
-- int state = pPager->eState;
-- assert( state==PAGER_OPEN || state==PAGER_READER );
-- if( state==PAGER_OPEN ){
-- rc = sqlite3PagerSharedLock(pPager);
-- }
-- if( pPager->eState==PAGER_READER ){
-- assert( rc==SQLITE_OK );
-- rc = pagerLockDb(pPager, RESERVED_LOCK);
-- }
-- if( rc==SQLITE_OK ){
-- sqlite3OsDelete(pPager->pVfs, pPager->zJournal, 0);
-- }
-- if( rc==SQLITE_OK && state==PAGER_READER ){
-- pagerUnlockDb(pPager, SHARED_LOCK);
-- }else if( state==PAGER_OPEN ){
-- pager_unlock(pPager);
-- }
-- assert( state==pPager->eState );
-- }
-+ pPager->errCode = SQLITE_ABORT;
-+ pPager->eState = PAGER_ERROR;
-+ return rc;
- }
-+ }else{
-+ rc = pager_playback(pPager, 0);
- }
-
-- /* Return the new journal mode */
-- return (int)pPager->journalMode;
-+ assert( pPager->eState==PAGER_READER || rc!=SQLITE_OK );
-+ assert( rc==SQLITE_OK || rc==SQLITE_FULL || rc==SQLITE_CORRUPT
-+ || rc==SQLITE_NOMEM || (rc&0xFF)==SQLITE_IOERR );
-+
-+ /* If an error occurs during a ROLLBACK, we can no longer trust the pager
-+ ** cache. So call pager_error() on the way out to make any error persistent.
-+ */
-+ return pager_error(pPager, rc);
- }
-
- /*
--** Return the current journal mode.
-+** Return TRUE if the database file is opened read-only. Return FALSE
-+** if the database is (in theory) writable.
- */
--SQLITE_PRIVATE int sqlite3PagerGetJournalMode(Pager *pPager){
-- return (int)pPager->journalMode;
-+SQLITE_PRIVATE u8 sqlite3PagerIsreadonly(Pager *pPager){
-+ return pPager->readOnly;
- }
-
- /*
--** Return TRUE if the pager is in a state where it is OK to change the
--** journalmode. Journalmode changes can only happen when the database
--** is unmodified.
-+** Return the number of references to the pager.
- */
--SQLITE_PRIVATE int sqlite3PagerOkToChangeJournalMode(Pager *pPager){
-- assert( assert_pager_state(pPager) );
-- if( pPager->eState>=PAGER_WRITER_CACHEMOD ) return 0;
-- if( NEVER(isOpen(pPager->jfd) && pPager->journalOff>0) ) return 0;
-- return 1;
-+SQLITE_PRIVATE int sqlite3PagerRefcount(Pager *pPager){
-+ return sqlite3PcacheRefCount(pPager->pPCache);
- }
-
- /*
--** Get/set the size-limit used for persistent journal files.
--**
--** Setting the size limit to -1 means no limit is enforced.
--** An attempt to set a limit smaller than -1 is a no-op.
-+** Return the approximate number of bytes of memory currently
-+** used by the pager and its associated cache.
- */
--SQLITE_PRIVATE i64 sqlite3PagerJournalSizeLimit(Pager *pPager, i64 iLimit){
-- if( iLimit>=-1 ){
-- pPager->journalSizeLimit = iLimit;
-- sqlite3WalLimit(pPager->pWal, iLimit);
-- }
-- return pPager->journalSizeLimit;
-+SQLITE_PRIVATE int sqlite3PagerMemUsed(Pager *pPager){
-+ int perPageSize = pPager->pageSize + pPager->nExtra + sizeof(PgHdr)
-+ + 5*sizeof(void*);
-+ return perPageSize*sqlite3PcachePagecount(pPager->pPCache)
-+ + sqlite3MallocSize(pPager)
-+ + pPager->pageSize;
- }
-
- /*
--** Return a pointer to the pPager->pBackup variable. The backup module
--** in backup.c maintains the content of this variable. This module
--** uses it opaquely as an argument to sqlite3BackupRestart() and
--** sqlite3BackupUpdate() only.
-+** Return the number of references to the specified page.
- */
--SQLITE_PRIVATE sqlite3_backup **sqlite3PagerBackupPtr(Pager *pPager){
-- return &pPager->pBackup;
-+SQLITE_PRIVATE int sqlite3PagerPageRefcount(DbPage *pPage){
-+ return sqlite3PcachePageRefcount(pPage);
- }
-
--#ifndef SQLITE_OMIT_VACUUM
-+#ifdef SQLITE_TEST
- /*
--** Unless this is an in-memory or temporary database, clear the pager cache.
-+** This routine is used for testing and analysis only.
- */
--SQLITE_PRIVATE void sqlite3PagerClearCache(Pager *pPager){
-- if( !MEMDB && pPager->tempFile==0 ) pager_reset(pPager);
-+SQLITE_PRIVATE int *sqlite3PagerStats(Pager *pPager){
-+ static int a[11];
-+ a[0] = sqlite3PcacheRefCount(pPager->pPCache);
-+ a[1] = sqlite3PcachePagecount(pPager->pPCache);
-+ a[2] = sqlite3PcacheGetCachesize(pPager->pPCache);
-+ a[3] = pPager->eState==PAGER_OPEN ? -1 : (int) pPager->dbSize;
-+ a[4] = pPager->eState;
-+ a[5] = pPager->errCode;
-+ a[6] = pPager->aStat[PAGER_STAT_HIT];
-+ a[7] = pPager->aStat[PAGER_STAT_MISS];
-+ a[8] = 0; /* Used to be pPager->nOvfl */
-+ a[9] = pPager->nRead;
-+ a[10] = pPager->aStat[PAGER_STAT_WRITE];
-+ return a;
- }
- #endif
-
--#ifndef SQLITE_OMIT_WAL
- /*
--** This function is called when the user invokes "PRAGMA wal_checkpoint",
--** "PRAGMA wal_blocking_checkpoint" or calls the sqlite3_wal_checkpoint()
--** or wal_blocking_checkpoint() API functions.
--**
--** Parameter eMode is one of SQLITE_CHECKPOINT_PASSIVE, FULL or RESTART.
-+** Parameter eStat must be either SQLITE_DBSTATUS_CACHE_HIT or
-+** SQLITE_DBSTATUS_CACHE_MISS. Before returning, *pnVal is incremented by the
-+** current cache hit or miss count, according to the value of eStat. If the
-+** reset parameter is non-zero, the cache hit or miss count is zeroed before
-+** returning.
- */
--SQLITE_PRIVATE int sqlite3PagerCheckpoint(Pager *pPager, int eMode, int *pnLog, int *pnCkpt){
-- int rc = SQLITE_OK;
-- if( pPager->pWal ){
-- rc = sqlite3WalCheckpoint(pPager->pWal, eMode,
-- pPager->xBusyHandler, pPager->pBusyHandlerArg,
-- pPager->ckptSyncFlags, pPager->pageSize, (u8 *)pPager->pTmpSpace,
-- pnLog, pnCkpt
-- );
-- }
-- return rc;
--}
-+SQLITE_PRIVATE void sqlite3PagerCacheStat(Pager *pPager, int eStat, int reset, int *pnVal){
-
--SQLITE_PRIVATE int sqlite3PagerWalCallback(Pager *pPager){
-- return sqlite3WalCallback(pPager->pWal);
--}
-+ assert( eStat==SQLITE_DBSTATUS_CACHE_HIT
-+ || eStat==SQLITE_DBSTATUS_CACHE_MISS
-+ || eStat==SQLITE_DBSTATUS_CACHE_WRITE
-+ );
-
--/*
--** Return true if the underlying VFS for the given pager supports the
--** primitives necessary for write-ahead logging.
--*/
--SQLITE_PRIVATE int sqlite3PagerWalSupported(Pager *pPager){
-- const sqlite3_io_methods *pMethods = pPager->fd->pMethods;
-- return pPager->exclusiveMode || (pMethods->iVersion>=2 && pMethods->xShmMap);
-+ assert( SQLITE_DBSTATUS_CACHE_HIT+1==SQLITE_DBSTATUS_CACHE_MISS );
-+ assert( SQLITE_DBSTATUS_CACHE_HIT+2==SQLITE_DBSTATUS_CACHE_WRITE );
-+ assert( PAGER_STAT_HIT==0 && PAGER_STAT_MISS==1 && PAGER_STAT_WRITE==2 );
-+
-+ *pnVal += pPager->aStat[eStat - SQLITE_DBSTATUS_CACHE_HIT];
-+ if( reset ){
-+ pPager->aStat[eStat - SQLITE_DBSTATUS_CACHE_HIT] = 0;
-+ }
- }
-
- /*
--** Attempt to take an exclusive lock on the database file. If a PENDING lock
--** is obtained instead, immediately release it.
-+** Return true if this is an in-memory pager.
- */
--static int pagerExclusiveLock(Pager *pPager){
-- int rc; /* Return code */
--
-- assert( pPager->eLock==SHARED_LOCK || pPager->eLock==EXCLUSIVE_LOCK );
-- rc = pagerLockDb(pPager, EXCLUSIVE_LOCK);
-- if( rc!=SQLITE_OK ){
-- /* If the attempt to grab the exclusive lock failed, release the
-- ** pending lock that may have been obtained instead. */
-- pagerUnlockDb(pPager, SHARED_LOCK);
-- }
--
-- return rc;
-+SQLITE_PRIVATE int sqlite3PagerIsMemdb(Pager *pPager){
-+ return MEMDB;
- }
-
- /*
--** Call sqlite3WalOpen() to open the WAL handle. If the pager is in
--** exclusive-locking mode when this function is called, take an EXCLUSIVE
--** lock on the database file and use heap-memory to store the wal-index
--** in. Otherwise, use the normal shared-memory.
-+** Check that there are at least nSavepoint savepoints open. If there are
-+** currently less than nSavepoints open, then open one or more savepoints
-+** to make up the difference. If the number of savepoints is already
-+** equal to nSavepoint, then this function is a no-op.
-+**
-+** If a memory allocation fails, SQLITE_NOMEM is returned. If an error
-+** occurs while opening the sub-journal file, then an IO error code is
-+** returned. Otherwise, SQLITE_OK.
- */
--static int pagerOpenWal(Pager *pPager){
-- int rc = SQLITE_OK;
-+SQLITE_PRIVATE int sqlite3PagerOpenSavepoint(Pager *pPager, int nSavepoint){
-+ int rc = SQLITE_OK; /* Return code */
-+ int nCurrent = pPager->nSavepoint; /* Current number of savepoints */
-
-- assert( pPager->pWal==0 && pPager->tempFile==0 );
-- assert( pPager->eLock==SHARED_LOCK || pPager->eLock==EXCLUSIVE_LOCK );
-+ assert( pPager->eState>=PAGER_WRITER_LOCKED );
-+ assert( assert_pager_state(pPager) );
-
-- /* If the pager is already in exclusive-mode, the WAL module will use
-- ** heap-memory for the wal-index instead of the VFS shared-memory
-- ** implementation. Take the exclusive lock now, before opening the WAL
-- ** file, to make sure this is safe.
-- */
-- if( pPager->exclusiveMode ){
-- rc = pagerExclusiveLock(pPager);
-- }
-+ if( nSavepoint>nCurrent && pPager->useJournal ){
-+ int ii; /* Iterator variable */
-+ PagerSavepoint *aNew; /* New Pager.aSavepoint array */
-
-- /* Open the connection to the log file. If this operation fails,
-- ** (e.g. due to malloc() failure), return an error code.
-- */
-- if( rc==SQLITE_OK ){
-- rc = sqlite3WalOpen(pPager->pVfs,
-- pPager->fd, pPager->zWal, pPager->exclusiveMode,
-- pPager->journalSizeLimit, &pPager->pWal
-+ /* Grow the Pager.aSavepoint array using realloc(). Return SQLITE_NOMEM
-+ ** if the allocation fails. Otherwise, zero the new portion in case a
-+ ** malloc failure occurs while populating it in the for(...) loop below.
-+ */
-+ aNew = (PagerSavepoint *)sqlite3Realloc(
-+ pPager->aSavepoint, sizeof(PagerSavepoint)*nSavepoint
- );
-+ if( !aNew ){
-+ return SQLITE_NOMEM;
-+ }
-+ memset(&aNew[nCurrent], 0, (nSavepoint-nCurrent) * sizeof(PagerSavepoint));
-+ pPager->aSavepoint = aNew;
-+
-+ /* Populate the PagerSavepoint structures just allocated. */
-+ for(ii=nCurrent; ii<nSavepoint; ii++){
-+ aNew[ii].nOrig = pPager->dbSize;
-+ if( isOpen(pPager->jfd) && pPager->journalOff>0 ){
-+ aNew[ii].iOffset = pPager->journalOff;
-+ }else{
-+ aNew[ii].iOffset = JOURNAL_HDR_SZ(pPager);
-+ }
-+ aNew[ii].iSubRec = pPager->nSubRec;
-+ aNew[ii].pInSavepoint = sqlite3BitvecCreate(pPager->dbSize);
-+ if( !aNew[ii].pInSavepoint ){
-+ return SQLITE_NOMEM;
-+ }
-+ if( pagerUseWal(pPager) ){
-+ sqlite3WalSavepoint(pPager->pWal, aNew[ii].aWalData);
-+ }
-+ pPager->nSavepoint = ii+1;
-+ }
-+ assert( pPager->nSavepoint==nSavepoint );
-+ assertTruncateConstraint(pPager);
- }
-- pagerFixMaplimit(pPager);
-
- return rc;
- }
-
--
- /*
--** The caller must be holding a SHARED lock on the database file to call
--** this function.
-+** This function is called to rollback or release (commit) a savepoint.
-+** The savepoint to release or rollback need not be the most recently
-+** created savepoint.
-+**
-+** Parameter op is always either SAVEPOINT_ROLLBACK or SAVEPOINT_RELEASE.
-+** If it is SAVEPOINT_RELEASE, then release and destroy the savepoint with
-+** index iSavepoint. If it is SAVEPOINT_ROLLBACK, then rollback all changes
-+** that have occurred since the specified savepoint was created.
-+**
-+** The savepoint to rollback or release is identified by parameter
-+** iSavepoint. A value of 0 means to operate on the outermost savepoint
-+** (the first created). A value of (Pager.nSavepoint-1) means operate
-+** on the most recently created savepoint. If iSavepoint is greater than
-+** (Pager.nSavepoint-1), then this function is a no-op.
- **
--** If the pager passed as the first argument is open on a real database
--** file (not a temp file or an in-memory database), and the WAL file
--** is not already open, make an attempt to open it now. If successful,
--** return SQLITE_OK. If an error occurs or the VFS used by the pager does
--** not support the xShmXXX() methods, return an error code. *pbOpen is
--** not modified in either case.
-+** If a negative value is passed to this function, then the current
-+** transaction is rolled back. This is different to calling
-+** sqlite3PagerRollback() because this function does not terminate
-+** the transaction or unlock the database, it just restores the
-+** contents of the database to its original state.
- **
--** If the pager is open on a temp-file (or in-memory database), or if
--** the WAL file is already open, set *pbOpen to 1 and return SQLITE_OK
--** without doing anything.
--*/
--SQLITE_PRIVATE int sqlite3PagerOpenWal(
-- Pager *pPager, /* Pager object */
-- int *pbOpen /* OUT: Set to true if call is a no-op */
--){
-- int rc = SQLITE_OK; /* Return code */
-+** In any case, all savepoints with an index greater than iSavepoint
-+** are destroyed. If this is a release operation (op==SAVEPOINT_RELEASE),
-+** then savepoint iSavepoint is also destroyed.
-+**
-+** This function may return SQLITE_NOMEM if a memory allocation fails,
-+** or an IO error code if an IO error occurs while rolling back a
-+** savepoint. If no errors occur, SQLITE_OK is returned.
-+*/
-+SQLITE_PRIVATE int sqlite3PagerSavepoint(Pager *pPager, int op, int iSavepoint){
-+ int rc = pPager->errCode; /* Return code */
-
-- assert( assert_pager_state(pPager) );
-- assert( pPager->eState==PAGER_OPEN || pbOpen );
-- assert( pPager->eState==PAGER_READER || !pbOpen );
-- assert( pbOpen==0 || *pbOpen==0 );
-- assert( pbOpen!=0 || (!pPager->tempFile && !pPager->pWal) );
-+ assert( op==SAVEPOINT_RELEASE || op==SAVEPOINT_ROLLBACK );
-+ assert( iSavepoint>=0 || op==SAVEPOINT_ROLLBACK );
-
-- if( !pPager->tempFile && !pPager->pWal ){
-- if( !sqlite3PagerWalSupported(pPager) ) return SQLITE_CANTOPEN;
-+ if( rc==SQLITE_OK && iSavepoint<pPager->nSavepoint ){
-+ int ii; /* Iterator variable */
-+ int nNew; /* Number of remaining savepoints after this op. */
-
-- /* Close any rollback journal previously open */
-- sqlite3OsClose(pPager->jfd);
-+ /* Figure out how many savepoints will still be active after this
-+ ** operation. Store this value in nNew. Then free resources associated
-+ ** with any savepoints that are destroyed by this operation.
-+ */
-+ nNew = iSavepoint + (( op==SAVEPOINT_RELEASE ) ? 0 : 1);
-+ for(ii=nNew; ii<pPager->nSavepoint; ii++){
-+ sqlite3BitvecDestroy(pPager->aSavepoint[ii].pInSavepoint);
-+ }
-+ pPager->nSavepoint = nNew;
-
-- rc = pagerOpenWal(pPager);
-- if( rc==SQLITE_OK ){
-- pPager->journalMode = PAGER_JOURNALMODE_WAL;
-- pPager->eState = PAGER_OPEN;
-+ /* If this is a release of the outermost savepoint, truncate
-+ ** the sub-journal to zero bytes in size. */
-+ if( op==SAVEPOINT_RELEASE ){
-+ if( nNew==0 && isOpen(pPager->sjfd) ){
-+ /* Only truncate if it is an in-memory sub-journal. */
-+ if( sqlite3IsMemJournal(pPager->sjfd) ){
-+ rc = sqlite3OsTruncate(pPager->sjfd, 0);
-+ assert( rc==SQLITE_OK );
-+ }
-+ pPager->nSubRec = 0;
-+ }
-+ }
-+ /* Else this is a rollback operation, playback the specified savepoint.
-+ ** If this is a temp-file, it is possible that the journal file has
-+ ** not yet been opened. In this case there have been no changes to
-+ ** the database file, so the playback operation can be skipped.
-+ */
-+ else if( pagerUseWal(pPager) || isOpen(pPager->jfd) ){
-+ PagerSavepoint *pSavepoint = (nNew==0)?0:&pPager->aSavepoint[nNew-1];
-+ rc = pagerPlaybackSavepoint(pPager, pSavepoint);
-+ assert(rc!=SQLITE_DONE);
- }
-- }else{
-- *pbOpen = 1;
- }
-
- return rc;
- }
-
- /*
--** This function is called to close the connection to the log file prior
--** to switching from WAL to rollback mode.
-+** Return the full pathname of the database file.
- **
--** Before closing the log file, this function attempts to take an
--** EXCLUSIVE lock on the database file. If this cannot be obtained, an
--** error (SQLITE_BUSY) is returned and the log connection is not closed.
--** If successful, the EXCLUSIVE lock is not released before returning.
-+** Except, if the pager is in-memory only, then return an empty string if
-+** nullIfMemDb is true. This routine is called with nullIfMemDb==1 when
-+** used to report the filename to the user, for compatibility with legacy
-+** behavior. But when the Btree needs to know the filename for matching to
-+** shared cache, it uses nullIfMemDb==0 so that in-memory databases can
-+** participate in shared-cache.
- */
--SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager){
-- int rc = SQLITE_OK;
-+SQLITE_PRIVATE const char *sqlite3PagerFilename(Pager *pPager, int nullIfMemDb){
-+ return (nullIfMemDb && pPager->memDb) ? "" : pPager->zFilename;
-+}
-
-- assert( pPager->journalMode==PAGER_JOURNALMODE_WAL );
-+/*
-+** Return the VFS structure for the pager.
-+*/
-+SQLITE_PRIVATE const sqlite3_vfs *sqlite3PagerVfs(Pager *pPager){
-+ return pPager->pVfs;
-+}
-
-- /* If the log file is not already open, but does exist in the file-system,
-- ** it may need to be checkpointed before the connection can switch to
-- ** rollback mode. Open it now so this can happen.
-- */
-- if( !pPager->pWal ){
-- int logexists = 0;
-- rc = pagerLockDb(pPager, SHARED_LOCK);
-- if( rc==SQLITE_OK ){
-- rc = sqlite3OsAccess(
-- pPager->pVfs, pPager->zWal, SQLITE_ACCESS_EXISTS, &logexists
-- );
-- }
-- if( rc==SQLITE_OK && logexists ){
-- rc = pagerOpenWal(pPager);
-- }
-- }
--
-- /* Checkpoint and close the log. Because an EXCLUSIVE lock is held on
-- ** the database file, the log and log-summary files will be deleted.
-- */
-- if( rc==SQLITE_OK && pPager->pWal ){
-- rc = pagerExclusiveLock(pPager);
-- if( rc==SQLITE_OK ){
-- rc = sqlite3WalClose(pPager->pWal, pPager->ckptSyncFlags,
-- pPager->pageSize, (u8*)pPager->pTmpSpace);
-- pPager->pWal = 0;
-- pagerFixMaplimit(pPager);
-- }
-- }
-- return rc;
-+/*
-+** Return the file handle for the database file associated
-+** with the pager. This might return NULL if the file has
-+** not yet been opened.
-+*/
-+SQLITE_PRIVATE sqlite3_file *sqlite3PagerFile(Pager *pPager){
-+ return pPager->fd;
- }
-
--#endif /* !SQLITE_OMIT_WAL */
-+/*
-+** Return the full pathname of the journal file.
-+*/
-+SQLITE_PRIVATE const char *sqlite3PagerJournalname(Pager *pPager){
-+ return pPager->zJournal;
-+}
-
--#ifdef SQLITE_ENABLE_ZIPVFS
- /*
--** A read-lock must be held on the pager when this function is called. If
--** the pager is in WAL mode and the WAL file currently contains one or more
--** frames, return the size in bytes of the page images stored within the
--** WAL frames. Otherwise, if this is not a WAL database or the WAL file
--** is empty, return 0.
-+** Return true if fsync() calls are disabled for this pager. Return FALSE
-+** if fsync()s are executed normally.
- */
--SQLITE_PRIVATE int sqlite3PagerWalFramesize(Pager *pPager){
-- assert( pPager->eState==PAGER_READER );
-- return sqlite3WalFramesize(pPager->pWal);
-+SQLITE_PRIVATE int sqlite3PagerNosync(Pager *pPager){
-+ return pPager->noSync;
- }
--#endif
-
- #ifdef SQLITE_HAS_CODEC
- /*
--** This function is called by the wal module when writing page content
--** into the log file.
--**
--** This function returns a pointer to a buffer containing the encrypted
--** page content. If a malloc fails, this function may return NULL.
-+** Set or retrieve the codec for this pager
- */
--SQLITE_PRIVATE void *sqlite3PagerCodec(PgHdr *pPg){
-- void *aData = 0;
-- CODEC2(pPg->pPager, pPg->pData, pPg->pgno, 6, return 0, aData);
-- return aData;
-+SQLITE_PRIVATE void sqlite3PagerSetCodec(
++SQLITE_PRIVATE void sqlite3pager_sqlite3PagerSetCodec(
+ Pager *pPager,
+ void *(*xCodec)(void*,void*,Pgno,int),
+ void (*xCodecSizeChng)(void*,int,int),
+ void (*xCodecFree)(void*),
+ void *pCodec
+){
-+ if( pPager->xCodecFree ) pPager->xCodecFree(pPager->pCodec);
-+ pPager->xCodec = pPager->memDb ? 0 : xCodec;
-+ pPager->xCodecSizeChng = xCodecSizeChng;
-+ pPager->xCodecFree = xCodecFree;
-+ pPager->pCodec = pCodec;
-+ pagerReportSize(pPager);
- }
--#endif /* SQLITE_HAS_CODEC */
--
--#endif /* SQLITE_OMIT_DISKIO */
-+SQLITE_PRIVATE void *sqlite3PagerGetCodec(Pager *pPager){
-+ return pPager->pCodec;
++ sqlite3PagerSetCodec(pPager, xCodec, xCodecSizeChng, xCodecFree, pCodec);
+}
-+#endif
-
--/************** End of pager.c ***********************************************/
--/************** Begin file wal.c *********************************************/
-+#ifndef SQLITE_OMIT_AUTOVACUUM
- /*
--** 2010 February 1
--**
--** The author disclaims copyright to this source code. In place of
--** a legal notice, here is a blessing:
--**
--** May you do good and not evil.
--** May you find forgiveness for yourself and forgive others.
--** May you share freely, never taking more than you give.
--**
--*************************************************************************
--**
--** This file contains the implementation of a write-ahead log (WAL) used in
--** "journal_mode=WAL" mode.
--**
--** WRITE-AHEAD LOG (WAL) FILE FORMAT
--**
--** A WAL file consists of a header followed by zero or more "frames".
--** Each frame records the revised content of a single page from the
--** database file. All changes to the database are recorded by writing
--** frames into the WAL. Transactions commit when a frame is written that
--** contains a commit marker. A single WAL can and usually does record
--** multiple transactions. Periodically, the content of the WAL is
--** transferred back into the database file in an operation called a
--** "checkpoint".
--**
--** A single WAL file can be used multiple times. In other words, the
--** WAL can fill up with frames and then be checkpointed and then new
--** frames can overwrite the old ones. A WAL always grows from beginning
--** toward the end. Checksums and counters attached to each frame are
--** used to determine which frames within the WAL are valid and which
--** are leftovers from prior checkpoints.
--**
--** The WAL header is 32 bytes in size and consists of the following eight
--** big-endian 32-bit unsigned integer values:
--**
--** 0: Magic number. 0x377f0682 or 0x377f0683
--** 4: File format version. Currently 3007000
--** 8: Database page size. Example: 1024
--** 12: Checkpoint sequence number
--** 16: Salt-1, random integer incremented with each checkpoint
--** 20: Salt-2, a different random integer changing with each ckpt
--** 24: Checksum-1 (first part of checksum for first 24 bytes of header).
--** 28: Checksum-2 (second part of checksum for first 24 bytes of header).
--**
--** Immediately following the wal-header are zero or more frames. Each
--** frame consists of a 24-byte frame-header followed by a <page-size> bytes
--** of page data. The frame-header is six big-endian 32-bit unsigned
--** integer values, as follows:
--**
--** 0: Page number.
--** 4: For commit records, the size of the database image in pages
--** after the commit. For all other records, zero.
--** 8: Salt-1 (copied from the header)
--** 12: Salt-2 (copied from the header)
--** 16: Checksum-1.
--** 20: Checksum-2.
--**
--** A frame is considered valid if and only if the following conditions are
--** true:
--**
--** (1) The salt-1 and salt-2 values in the frame-header match
--** salt values in the wal-header
--**
--** (2) The checksum values in the final 8 bytes of the frame-header
--** exactly match the checksum computed consecutively on the
--** WAL header and the first 8 bytes and the content of all frames
--** up to and including the current frame.
--**
--** The checksum is computed using 32-bit big-endian integers if the
--** magic number in the first 4 bytes of the WAL is 0x377f0683 and it
--** is computed using little-endian if the magic number is 0x377f0682.
--** The checksum values are always stored in the frame header in a
--** big-endian format regardless of which byte order is used to compute
--** the checksum. The checksum is computed by interpreting the input as
--** an even number of unsigned 32-bit integers: x[0] through x[N]. The
--** algorithm used for the checksum is as follows:
--**
--** for i from 0 to n-1 step 2:
--** s0 += x[i] + s1;
--** s1 += x[i+1] + s0;
--** endfor
--**
--** Note that s0 and s1 are both weighted checksums using fibonacci weights
--** in reverse order (the largest fibonacci weight occurs on the first element
--** of the sequence being summed.) The s1 value spans all 32-bit
--** terms of the sequence whereas s0 omits the final term.
--**
--** On a checkpoint, the WAL is first VFS.xSync-ed, then valid content of the
--** WAL is transferred into the database, then the database is VFS.xSync-ed.
--** The VFS.xSync operations serve as write barriers - all writes launched
--** before the xSync must complete before any write that launches after the
--** xSync begins.
--**
--** After each checkpoint, the salt-1 value is incremented and the salt-2
--** value is randomized. This prevents old and new frames in the WAL from
--** being considered valid at the same time and being checkpointing together
--** following a crash.
--**
--** READER ALGORITHM
--**
--** To read a page from the database (call it page number P), a reader
--** first checks the WAL to see if it contains page P. If so, then the
--** last valid instance of page P that is a followed by a commit frame
--** or is a commit frame itself becomes the value read. If the WAL
--** contains no copies of page P that are valid and which are a commit
--** frame or are followed by a commit frame, then page P is read from
--** the database file.
--**
--** To start a read transaction, the reader records the index of the last
--** valid frame in the WAL. The reader uses this recorded "mxFrame" value
--** for all subsequent read operations. New transactions can be appended
--** to the WAL, but as long as the reader uses its original mxFrame value
--** and ignores the newly appended content, it will see a consistent snapshot
--** of the database from a single point in time. This technique allows
--** multiple concurrent readers to view different versions of the database
--** content simultaneously.
--**
--** The reader algorithm in the previous paragraphs works correctly, but
--** because frames for page P can appear anywhere within the WAL, the
--** reader has to scan the entire WAL looking for page P frames. If the
--** WAL is large (multiple megabytes is typical) that scan can be slow,
--** and read performance suffers. To overcome this problem, a separate
--** data structure called the wal-index is maintained to expedite the
--** search for frames of a particular page.
--**
--** WAL-INDEX FORMAT
--**
--** Conceptually, the wal-index is shared memory, though VFS implementations
--** might choose to implement the wal-index using a mmapped file. Because
--** the wal-index is shared memory, SQLite does not support journal_mode=WAL
--** on a network filesystem. All users of the database must be able to
--** share memory.
--**
--** The wal-index is transient. After a crash, the wal-index can (and should
--** be) reconstructed from the original WAL file. In fact, the VFS is required
--** to either truncate or zero the header of the wal-index when the last
--** connection to it closes. Because the wal-index is transient, it can
--** use an architecture-specific format; it does not have to be cross-platform.
--** Hence, unlike the database and WAL file formats which store all values
--** as big endian, the wal-index can store multi-byte values in the native
--** byte order of the host computer.
--**
--** The purpose of the wal-index is to answer this question quickly: Given
--** a page number P and a maximum frame index M, return the index of the
--** last frame in the wal before frame M for page P in the WAL, or return
--** NULL if there are no frames for page P in the WAL prior to M.
--**
--** The wal-index consists of a header region, followed by an one or
--** more index blocks.
--**
--** The wal-index header contains the total number of frames within the WAL
--** in the mxFrame field.
--**
--** Each index block except for the first contains information on
--** HASHTABLE_NPAGE frames. The first index block contains information on
--** HASHTABLE_NPAGE_ONE frames. The values of HASHTABLE_NPAGE_ONE and
--** HASHTABLE_NPAGE are selected so that together the wal-index header and
--** first index block are the same size as all other index blocks in the
--** wal-index.
--**
--** Each index block contains two sections, a page-mapping that contains the
--** database page number associated with each wal frame, and a hash-table
--** that allows readers to query an index block for a specific page number.
--** The page-mapping is an array of HASHTABLE_NPAGE (or HASHTABLE_NPAGE_ONE
--** for the first index block) 32-bit page numbers. The first entry in the
--** first index-block contains the database page number corresponding to the
--** first frame in the WAL file. The first entry in the second index block
--** in the WAL file corresponds to the (HASHTABLE_NPAGE_ONE+1)th frame in
--** the log, and so on.
--**
--** The last index block in a wal-index usually contains less than the full
--** complement of HASHTABLE_NPAGE (or HASHTABLE_NPAGE_ONE) page-numbers,
--** depending on the contents of the WAL file. This does not change the
--** allocated size of the page-mapping array - the page-mapping array merely
--** contains unused entries.
--**
--** Even without using the hash table, the last frame for page P
--** can be found by scanning the page-mapping sections of each index block
--** starting with the last index block and moving toward the first, and
--** within each index block, starting at the end and moving toward the
--** beginning. The first entry that equals P corresponds to the frame
--** holding the content for that page.
--**
--** The hash table consists of HASHTABLE_NSLOT 16-bit unsigned integers.
--** HASHTABLE_NSLOT = 2*HASHTABLE_NPAGE, and there is one entry in the
--** hash table for each page number in the mapping section, so the hash
--** table is never more than half full. The expected number of collisions
--** prior to finding a match is 1. Each entry of the hash table is an
--** 1-based index of an entry in the mapping section of the same
--** index block. Let K be the 1-based index of the largest entry in
--** the mapping section. (For index blocks other than the last, K will
--** always be exactly HASHTABLE_NPAGE (4096) and for the last index block
--** K will be (mxFrame%HASHTABLE_NPAGE).) Unused slots of the hash table
--** contain a value of 0.
--**
--** To look for page P in the hash table, first compute a hash iKey on
--** P as follows:
-+** Move the page pPg to location pgno in the file.
- **
--** iKey = (P * 383) % HASHTABLE_NSLOT
-+** There must be no references to the page previously located at
-+** pgno (which we call pPgOld) though that page is allowed to be
-+** in cache. If the page previously located at pgno is not already
-+** in the rollback journal, it is not put there by by this routine.
- **
--** Then start scanning entries of the hash table, starting with iKey
--** (wrapping around to the beginning when the end of the hash table is
--** reached) until an unused hash slot is found. Let the first unused slot
--** be at index iUnused. (iUnused might be less than iKey if there was
--** wrap-around.) Because the hash table is never more than half full,
--** the search is guaranteed to eventually hit an unused entry. Let
--** iMax be the value between iKey and iUnused, closest to iUnused,
--** where aHash[iMax]==P. If there is no iMax entry (if there exists
--** no hash slot such that aHash[i]==p) then page P is not in the
--** current index block. Otherwise the iMax-th mapping entry of the
--** current index block corresponds to the last entry that references
--** page P.
-+** References to the page pPg remain valid. Updating any
-+** meta-data associated with pPg (i.e. data stored in the nExtra bytes
-+** allocated along with the page) is the responsibility of the caller.
- **
--** A hash search begins with the last index block and moves toward the
--** first index block, looking for entries corresponding to page P. On
--** average, only two or three slots in each index block need to be
--** examined in order to either find the last entry for page P, or to
--** establish that no such entry exists in the block. Each index block
--** holds over 4000 entries. So two or three index blocks are sufficient
--** to cover a typical 10 megabyte WAL file, assuming 1K pages. 8 or 10
--** comparisons (on average) suffice to either locate a frame in the
--** WAL or to establish that the frame does not exist in the WAL. This
--** is much faster than scanning the entire 10MB WAL.
-+** A transaction must be active when this routine is called. It used to be
-+** required that a statement transaction was not active, but this restriction
-+** has been removed (CREATE INDEX needs to move a page when a statement
-+** transaction is active).
- **
--** Note that entries are added in order of increasing K. Hence, one
--** reader might be using some value K0 and a second reader that started
--** at a later time (after additional transactions were added to the WAL
--** and to the wal-index) might be using a different value K1, where K1>K0.
--** Both readers can use the same hash table and mapping section to get
--** the correct result. There may be entries in the hash table with
--** K>K0 but to the first reader, those entries will appear to be unused
--** slots in the hash table and so the first reader will get an answer as
--** if no values greater than K0 had ever been inserted into the hash table
--** in the first place - which is what reader one wants. Meanwhile, the
--** second reader using K1 will see additional values that were inserted
--** later, which is exactly what reader two wants.
-+** If the fourth argument, isCommit, is non-zero, then this page is being
-+** moved as part of a database reorganization just before the transaction
-+** is being committed. In this case, it is guaranteed that the database page
-+** pPg refers to will not be written to again within this transaction.
- **
--** When a rollback occurs, the value of K is decreased. Hash table entries
--** that correspond to frames greater than the new K value are removed
--** from the hash table at this point.
-+** This function may return SQLITE_NOMEM or an IO error code if an error
-+** occurs. Otherwise, it returns SQLITE_OK.
- */
--#ifndef SQLITE_OMIT_WAL
-+SQLITE_PRIVATE int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno, int isCommit){
-+ PgHdr *pPgOld; /* The page being overwritten. */
-+ Pgno needSyncPgno = 0; /* Old value of pPg->pgno, if sync is required */
-+ int rc; /* Return code */
-+ Pgno origPgno; /* The original page number */
-+
-+ assert( pPg->nRef>0 );
-+ assert( pPager->eState==PAGER_WRITER_CACHEMOD
-+ || pPager->eState==PAGER_WRITER_DBMOD
-+ );
-+ assert( assert_pager_state(pPager) );
-+
-+ /* In order to be able to rollback, an in-memory database must journal
-+ ** the page we are moving from.
-+ */
-+ if( MEMDB ){
-+ rc = sqlite3PagerWrite(pPg);
-+ if( rc ) return rc;
-+ }
-+
-+ /* If the page being moved is dirty and has not been saved by the latest
-+ ** savepoint, then save the current contents of the page into the
-+ ** sub-journal now. This is required to handle the following scenario:
-+ **
-+ ** BEGIN;
-+ ** <journal page X, then modify it in memory>
-+ ** SAVEPOINT one;
-+ ** <Move page X to location Y>
-+ ** ROLLBACK TO one;
-+ **
-+ ** If page X were not written to the sub-journal here, it would not
-+ ** be possible to restore its contents when the "ROLLBACK TO one"
-+ ** statement were is processed.
-+ **
-+ ** subjournalPage() may need to allocate space to store pPg->pgno into
-+ ** one or more savepoint bitvecs. This is the reason this function
-+ ** may return SQLITE_NOMEM.
-+ */
-+ if( pPg->flags&PGHDR_DIRTY
-+ && subjRequiresPage(pPg)
-+ && SQLITE_OK!=(rc = subjournalPage(pPg))
-+ ){
-+ return rc;
-+ }
-+
-+ PAGERTRACE(("MOVE %d page %d (needSync=%d) moves to %d\n",
-+ PAGERID(pPager), pPg->pgno, (pPg->flags&PGHDR_NEED_SYNC)?1:0, pgno));
-+ IOTRACE(("MOVE %p %d %d\n", pPager, pPg->pgno, pgno))
-+
-+ /* If the journal needs to be sync()ed before page pPg->pgno can
-+ ** be written to, store pPg->pgno in local variable needSyncPgno.
-+ **
-+ ** If the isCommit flag is set, there is no need to remember that
-+ ** the journal needs to be sync()ed before database page pPg->pgno
-+ ** can be written to. The caller has already promised not to write to it.
-+ */
-+ if( (pPg->flags&PGHDR_NEED_SYNC) && !isCommit ){
-+ needSyncPgno = pPg->pgno;
-+ assert( pPager->journalMode==PAGER_JOURNALMODE_OFF ||
-+ pageInJournal(pPg) || pPg->pgno>pPager->dbOrigSize );
-+ assert( pPg->flags&PGHDR_DIRTY );
-+ }
-
-+ /* If the cache contains a page with page-number pgno, remove it
-+ ** from its hash chain. Also, if the PGHDR_NEED_SYNC flag was set for
-+ ** page pgno before the 'move' operation, it needs to be retained
-+ ** for the page moved there.
-+ */
-+ pPg->flags &= ~PGHDR_NEED_SYNC;
-+ pPgOld = pager_lookup(pPager, pgno);
-+ assert( !pPgOld || pPgOld->nRef==1 );
-+ if( pPgOld ){
-+ pPg->flags |= (pPgOld->flags&PGHDR_NEED_SYNC);
-+ if( MEMDB ){
-+ /* Do not discard pages from an in-memory database since we might
-+ ** need to rollback later. Just move the page out of the way. */
-+ sqlite3PcacheMove(pPgOld, pPager->dbSize+1);
-+ }else{
-+ sqlite3PcacheDrop(pPgOld);
-+ }
-+ }
-
--/*
--** Trace output macros
--*/
--#if defined(SQLITE_TEST) && defined(SQLITE_DEBUG)
--SQLITE_PRIVATE int sqlite3WalTrace = 0;
--# define WALTRACE(X) if(sqlite3WalTrace) sqlite3DebugPrintf X
--#else
--# define WALTRACE(X)
-+ origPgno = pPg->pgno;
-+ sqlite3PcacheMove(pPg, pgno);
-+ sqlite3PcacheMakeDirty(pPg);
-+
-+ /* For an in-memory database, make sure the original page continues
-+ ** to exist, in case the transaction needs to roll back. Use pPgOld
-+ ** as the original page since it has already been allocated.
-+ */
-+ if( MEMDB ){
-+ assert( pPgOld );
-+ sqlite3PcacheMove(pPgOld, origPgno);
-+ sqlite3PagerUnref(pPgOld);
-+ }
+
-+ if( needSyncPgno ){
-+ /* If needSyncPgno is non-zero, then the journal file needs to be
-+ ** sync()ed before any data is written to database file page needSyncPgno.
-+ ** Currently, no such page exists in the page-cache and the
-+ ** "is journaled" bitvec flag has been set. This needs to be remedied by
-+ ** loading the page into the pager-cache and setting the PGHDR_NEED_SYNC
-+ ** flag.
-+ **
-+ ** If the attempt to load the page into the page-cache fails, (due
-+ ** to a malloc() or IO failure), clear the bit in the pInJournal[]
-+ ** array. Otherwise, if the page is loaded and written again in
-+ ** this transaction, it may be written to the database file before
-+ ** it is synced into the journal file. This way, it may end up in
-+ ** the journal file twice, but that is not a problem.
-+ */
-+ PgHdr *pPgHdr;
-+ rc = sqlite3PagerGet(pPager, needSyncPgno, &pPgHdr);
-+ if( rc!=SQLITE_OK ){
-+ if( needSyncPgno<=pPager->dbOrigSize ){
-+ assert( pPager->pTmpSpace!=0 );
-+ sqlite3BitvecClear(pPager->pInJournal, needSyncPgno, pPager->pTmpSpace);
-+ }
-+ return rc;
-+ }
-+ pPgHdr->flags |= PGHDR_NEED_SYNC;
-+ sqlite3PcacheMakeDirty(pPgHdr);
-+ sqlite3PagerUnref(pPgHdr);
-+ }
-+
-+ return SQLITE_OK;
-+}
- #endif
-
- /*
--** The maximum (and only) versions of the wal and wal-index formats
--** that may be interpreted by this version of SQLite.
--**
--** If a client begins recovering a WAL file and finds that (a) the checksum
--** values in the wal-header are correct and (b) the version field is not
--** WAL_MAX_VERSION, recovery fails and SQLite returns SQLITE_CANTOPEN.
--**
--** Similarly, if a client successfully reads a wal-index header (i.e. the
--** checksum test is successful) and finds that the version field is not
--** WALINDEX_MAX_VERSION, then no read-transaction is opened and SQLite
--** returns SQLITE_CANTOPEN.
-+** Return a pointer to the data for the specified page.
- */
--#define WAL_MAX_VERSION 3007000
--#define WALINDEX_MAX_VERSION 3007000
-+SQLITE_PRIVATE void *sqlite3PagerGetData(DbPage *pPg){
-+ assert( pPg->nRef>0 || pPg->pPager->memDb );
-+ return pPg->pData;
-+}
-
- /*
--** Indices of various locking bytes. WAL_NREADER is the number
--** of available reader locks and should be at least 3.
-+** Return a pointer to the Pager.nExtra bytes of "extra" space
-+** allocated along with the specified page.
- */
--#define WAL_WRITE_LOCK 0
--#define WAL_ALL_BUT_WRITE 1
--#define WAL_CKPT_LOCK 1
--#define WAL_RECOVER_LOCK 2
--#define WAL_READ_LOCK(I) (3+(I))
--#define WAL_NREADER (SQLITE_SHM_NLOCK-3)
--
--
--/* Object declarations */
--typedef struct WalIndexHdr WalIndexHdr;
--typedef struct WalIterator WalIterator;
--typedef struct WalCkptInfo WalCkptInfo;
--
-+SQLITE_PRIVATE void *sqlite3PagerGetExtra(DbPage *pPg){
-+ return pPg->pExtra;
-+}
-
- /*
--** The following object holds a copy of the wal-index header content.
--**
--** The actual header in the wal-index consists of two copies of this
--** object.
-+** Get/set the locking-mode for this pager. Parameter eMode must be one
-+** of PAGER_LOCKINGMODE_QUERY, PAGER_LOCKINGMODE_NORMAL or
-+** PAGER_LOCKINGMODE_EXCLUSIVE. If the parameter is not _QUERY, then
-+** the locking-mode is set to the value specified.
- **
--** The szPage value can be any power of 2 between 512 and 32768, inclusive.
--** Or it can be 1 to represent a 65536-byte page. The latter case was
--** added in 3.7.1 when support for 64K pages was added.
-+** The returned value is either PAGER_LOCKINGMODE_NORMAL or
-+** PAGER_LOCKINGMODE_EXCLUSIVE, indicating the current (possibly updated)
-+** locking-mode.
- */
--struct WalIndexHdr {
-- u32 iVersion; /* Wal-index version */
-- u32 unused; /* Unused (padding) field */
-- u32 iChange; /* Counter incremented each transaction */
-- u8 isInit; /* 1 when initialized */
-- u8 bigEndCksum; /* True if checksums in WAL are big-endian */
-- u16 szPage; /* Database page size in bytes. 1==64K */
-- u32 mxFrame; /* Index of last valid frame in the WAL */
-- u32 nPage; /* Size of database in pages */
-- u32 aFrameCksum[2]; /* Checksum of last frame in log */
-- u32 aSalt[2]; /* Two salt values copied from WAL header */
-- u32 aCksum[2]; /* Checksum over all prior fields */
--};
-+SQLITE_PRIVATE int sqlite3PagerLockingMode(Pager *pPager, int eMode){
-+ assert( eMode==PAGER_LOCKINGMODE_QUERY
-+ || eMode==PAGER_LOCKINGMODE_NORMAL
-+ || eMode==PAGER_LOCKINGMODE_EXCLUSIVE );
-+ assert( PAGER_LOCKINGMODE_QUERY<0 );
-+ assert( PAGER_LOCKINGMODE_NORMAL>=0 && PAGER_LOCKINGMODE_EXCLUSIVE>=0 );
-+ assert( pPager->exclusiveMode || 0==sqlite3WalHeapMemory(pPager->pWal) );
-+ if( eMode>=0 && !pPager->tempFile && !sqlite3WalHeapMemory(pPager->pWal) ){
-+ pPager->exclusiveMode = (u8)eMode;
-+ }
-+ return (int)pPager->exclusiveMode;
++SQLITE_PRIVATE void sqlite3pager_sqlite3PagerSetError( Pager *pPager, int error) {
++ pPager->errCode = error;
+}
-
- /*
--** A copy of the following object occurs in the wal-index immediately
--** following the second copy of the WalIndexHdr. This object stores
--** information used by checkpoint.
--**
--** nBackfill is the number of frames in the WAL that have been written
--** back into the database. (We call the act of moving content from WAL to
--** database "backfilling".) The nBackfill number is never greater than
--** WalIndexHdr.mxFrame. nBackfill can only be increased by threads
--** holding the WAL_CKPT_LOCK lock (which includes a recovery thread).
--** However, a WAL_WRITE_LOCK thread can move the value of nBackfill from
--** mxFrame back to zero when the WAL is reset.
-+** Set the journal-mode for this pager. Parameter eMode must be one of:
- **
--** There is one entry in aReadMark[] for each reader lock. If a reader
--** holds read-lock K, then the value in aReadMark[K] is no greater than
--** the mxFrame for that reader. The value READMARK_NOT_USED (0xffffffff)
--** for any aReadMark[] means that entry is unused. aReadMark[0] is
--** a special case; its value is never used and it exists as a place-holder
--** to avoid having to offset aReadMark[] indexs by one. Readers holding
--** WAL_READ_LOCK(0) always ignore the entire WAL and read all content
--** directly from the database.
-+** PAGER_JOURNALMODE_DELETE
-+** PAGER_JOURNALMODE_TRUNCATE
-+** PAGER_JOURNALMODE_PERSIST
-+** PAGER_JOURNALMODE_OFF
-+** PAGER_JOURNALMODE_MEMORY
-+** PAGER_JOURNALMODE_WAL
- **
--** The value of aReadMark[K] may only be changed by a thread that
--** is holding an exclusive lock on WAL_READ_LOCK(K). Thus, the value of
--** aReadMark[K] cannot changed while there is a reader is using that mark
--** since the reader will be holding a shared lock on WAL_READ_LOCK(K).
-+** The journalmode is set to the value specified if the change is allowed.
-+** The change may be disallowed for the following reasons:
- **
--** The checkpointer may only transfer frames from WAL to database where
--** the frame numbers are less than or equal to every aReadMark[] that is
--** in use (that is, every aReadMark[j] for which there is a corresponding
--** WAL_READ_LOCK(j)). New readers (usually) pick the aReadMark[] with the
--** largest value and will increase an unused aReadMark[] to mxFrame if there
--** is not already an aReadMark[] equal to mxFrame. The exception to the
--** previous sentence is when nBackfill equals mxFrame (meaning that everything
--** in the WAL has been backfilled into the database) then new readers
--** will choose aReadMark[0] which has value 0 and hence such reader will
--** get all their all content directly from the database file and ignore
--** the WAL.
-+** * An in-memory database can only have its journal_mode set to _OFF
-+** or _MEMORY.
- **
--** Writers normally append new frames to the end of the WAL. However,
--** if nBackfill equals mxFrame (meaning that all WAL content has been
--** written back into the database) and if no readers are using the WAL
--** (in other words, if there are no WAL_READ_LOCK(i) where i>0) then
--** the writer will first "reset" the WAL back to the beginning and start
--** writing new content beginning at frame 1.
-+** * Temporary databases cannot have _WAL journalmode.
- **
--** We assume that 32-bit loads are atomic and so no locks are needed in
--** order to read from any aReadMark[] entries.
-+** The returned indicate the current (possibly updated) journal-mode.
- */
--struct WalCkptInfo {
-- u32 nBackfill; /* Number of WAL frames backfilled into DB */
-- u32 aReadMark[WAL_NREADER]; /* Reader marks */
--};
--#define READMARK_NOT_USED 0xffffffff
-+SQLITE_PRIVATE int sqlite3PagerSetJournalMode(Pager *pPager, int eMode){
-+ u8 eOld = pPager->journalMode; /* Prior journalmode */
-
-+#ifdef SQLITE_DEBUG
-+ /* The print_pager_state() routine is intended to be used by the debugger
-+ ** only. We invoke it once here to suppress a compiler warning. */
-+ print_pager_state(pPager);
-+#endif
-
--/* A block of WALINDEX_LOCK_RESERVED bytes beginning at
--** WALINDEX_LOCK_OFFSET is reserved for locks. Since some systems
--** only support mandatory file-locks, we do not read or write data
--** from the region of the file on which locks are applied.
--*/
--#define WALINDEX_LOCK_OFFSET (sizeof(WalIndexHdr)*2 + sizeof(WalCkptInfo))
--#define WALINDEX_LOCK_RESERVED 16
--#define WALINDEX_HDR_SIZE (WALINDEX_LOCK_OFFSET+WALINDEX_LOCK_RESERVED)
-
--/* Size of header before each frame in wal */
--#define WAL_FRAME_HDRSIZE 24
-+ /* The eMode parameter is always valid */
-+ assert( eMode==PAGER_JOURNALMODE_DELETE
-+ || eMode==PAGER_JOURNALMODE_TRUNCATE
-+ || eMode==PAGER_JOURNALMODE_PERSIST
-+ || eMode==PAGER_JOURNALMODE_OFF
-+ || eMode==PAGER_JOURNALMODE_WAL
-+ || eMode==PAGER_JOURNALMODE_MEMORY );
-
--/* Size of write ahead log header, including checksum. */
--/* #define WAL_HDRSIZE 24 */
--#define WAL_HDRSIZE 32
-+ /* This routine is only called from the OP_JournalMode opcode, and
-+ ** the logic there will never allow a temporary file to be changed
-+ ** to WAL mode.
-+ */
-+ assert( pPager->tempFile==0 || eMode!=PAGER_JOURNALMODE_WAL );
-
--/* WAL magic value. Either this value, or the same value with the least
--** significant bit also set (WAL_MAGIC | 0x00000001) is stored in 32-bit
--** big-endian format in the first 4 bytes of a WAL file.
--**
--** If the LSB is set, then the checksums for each frame within the WAL
--** file are calculated by treating all data as an array of 32-bit
--** big-endian words. Otherwise, they are calculated by interpreting
--** all data as 32-bit little-endian words.
--*/
--#define WAL_MAGIC 0x377f0682
-+ /* Do allow the journalmode of an in-memory database to be set to
-+ ** anything other than MEMORY or OFF
-+ */
-+ if( MEMDB ){
-+ assert( eOld==PAGER_JOURNALMODE_MEMORY || eOld==PAGER_JOURNALMODE_OFF );
-+ if( eMode!=PAGER_JOURNALMODE_MEMORY && eMode!=PAGER_JOURNALMODE_OFF ){
-+ eMode = eOld;
-+ }
-+ }
-
--/*
--** Return the offset of frame iFrame in the write-ahead log file,
--** assuming a database page size of szPage bytes. The offset returned
--** is to the start of the write-ahead log frame-header.
--*/
--#define walFrameOffset(iFrame, szPage) ( \
-- WAL_HDRSIZE + ((iFrame)-1)*(i64)((szPage)+WAL_FRAME_HDRSIZE) \
--)
-+ if( eMode!=eOld ){
-+
-+ /* Change the journal mode. */
-+ assert( pPager->eState!=PAGER_ERROR );
-+ pPager->journalMode = (u8)eMode;
-+
-+ /* When transistioning from TRUNCATE or PERSIST to any other journal
-+ ** mode except WAL, unless the pager is in locking_mode=exclusive mode,
-+ ** delete the journal file.
-+ */
-+ assert( (PAGER_JOURNALMODE_TRUNCATE & 5)==1 );
-+ assert( (PAGER_JOURNALMODE_PERSIST & 5)==1 );
-+ assert( (PAGER_JOURNALMODE_DELETE & 5)==0 );
-+ assert( (PAGER_JOURNALMODE_MEMORY & 5)==4 );
-+ assert( (PAGER_JOURNALMODE_OFF & 5)==0 );
-+ assert( (PAGER_JOURNALMODE_WAL & 5)==5 );
-+
-+ assert( isOpen(pPager->fd) || pPager->exclusiveMode );
-+ if( !pPager->exclusiveMode && (eOld & 5)==1 && (eMode & 1)==0 ){
-+
-+ /* In this case we would like to delete the journal file. If it is
-+ ** not possible, then that is not a problem. Deleting the journal file
-+ ** here is an optimization only.
-+ **
-+ ** Before deleting the journal file, obtain a RESERVED lock on the
-+ ** database file. This ensures that the journal file is not deleted
-+ ** while it is in use by some other client.
-+ */
-+ sqlite3OsClose(pPager->jfd);
-+ if( pPager->eLock>=RESERVED_LOCK ){
-+ sqlite3OsDelete(pPager->pVfs, pPager->zJournal, 0);
-+ }else{
-+ int rc = SQLITE_OK;
-+ int state = pPager->eState;
-+ assert( state==PAGER_OPEN || state==PAGER_READER );
-+ if( state==PAGER_OPEN ){
-+ rc = sqlite3PagerSharedLock(pPager);
-+ }
-+ if( pPager->eState==PAGER_READER ){
-+ assert( rc==SQLITE_OK );
-+ rc = pagerLockDb(pPager, RESERVED_LOCK);
-+ }
-+ if( rc==SQLITE_OK ){
-+ sqlite3OsDelete(pPager->pVfs, pPager->zJournal, 0);
-+ }
-+ if( rc==SQLITE_OK && state==PAGER_READER ){
-+ pagerUnlockDb(pPager, SHARED_LOCK);
-+ }else if( state==PAGER_OPEN ){
-+ pager_unlock(pPager);
-+ }
-+ assert( state==pPager->eState );
-+ }
-+ }
-+ }
+
-+ /* Return the new journal mode */
-+ return (int)pPager->journalMode;
-+}
-
- /*
--** An open write-ahead log file is represented by an instance of the
--** following object.
-+** Return the current journal mode.
- */
--struct Wal {
-- sqlite3_vfs *pVfs; /* The VFS used to create pDbFd */
-- sqlite3_file *pDbFd; /* File handle for the database file */
-- sqlite3_file *pWalFd; /* File handle for WAL file */
-- u32 iCallback; /* Value to pass to log callback (or 0) */
-- i64 mxWalSize; /* Truncate WAL to this size upon reset */
-- int nWiData; /* Size of array apWiData */
-- int szFirstBlock; /* Size of first block written to WAL file */
-- volatile u32 **apWiData; /* Pointer to wal-index content in memory */
-- u32 szPage; /* Database page size */
-- i16 readLock; /* Which read lock is being held. -1 for none */
-- u8 syncFlags; /* Flags to use to sync header writes */
-- u8 exclusiveMode; /* Non-zero if connection is in exclusive mode */
-- u8 writeLock; /* True if in a write transaction */
-- u8 ckptLock; /* True if holding a checkpoint lock */
-- u8 readOnly; /* WAL_RDWR, WAL_RDONLY, or WAL_SHM_RDONLY */
-- u8 truncateOnCommit; /* True to truncate WAL file on commit */
-- u8 syncHeader; /* Fsync the WAL header if true */
-- u8 padToSectorBoundary; /* Pad transactions out to the next sector */
-- WalIndexHdr hdr; /* Wal-index header for current transaction */
-- const char *zWalName; /* Name of WAL file */
-- u32 nCkpt; /* Checkpoint sequence counter in the wal-header */
--#ifdef SQLITE_DEBUG
-- u8 lockError; /* True if a locking error has occurred */
--#endif
--};
-+SQLITE_PRIVATE int sqlite3PagerGetJournalMode(Pager *pPager){
-+ return (int)pPager->journalMode;
-+}
-
- /*
--** Candidate values for Wal.exclusiveMode.
-+** Return TRUE if the pager is in a state where it is OK to change the
-+** journalmode. Journalmode changes can only happen when the database
-+** is unmodified.
- */
--#define WAL_NORMAL_MODE 0
--#define WAL_EXCLUSIVE_MODE 1
--#define WAL_HEAPMEMORY_MODE 2
-+SQLITE_PRIVATE int sqlite3PagerOkToChangeJournalMode(Pager *pPager){
-+ assert( assert_pager_state(pPager) );
-+ if( pPager->eState>=PAGER_WRITER_CACHEMOD ) return 0;
-+ if( NEVER(isOpen(pPager->jfd) && pPager->journalOff>0) ) return 0;
-+ return 1;
-+}
-
- /*
--** Possible values for WAL.readOnly
-+** Get/set the size-limit used for persistent journal files.
-+**
-+** Setting the size limit to -1 means no limit is enforced.
-+** An attempt to set a limit smaller than -1 is a no-op.
- */
--#define WAL_RDWR 0 /* Normal read/write connection */
--#define WAL_RDONLY 1 /* The WAL file is readonly */
--#define WAL_SHM_RDONLY 2 /* The SHM file is readonly */
-+SQLITE_PRIVATE i64 sqlite3PagerJournalSizeLimit(Pager *pPager, i64 iLimit){
-+ if( iLimit>=-1 ){
-+ pPager->journalSizeLimit = iLimit;
-+ sqlite3WalLimit(pPager->pWal, iLimit);
-+ }
-+ return pPager->journalSizeLimit;
-+}
-
- /*
--** Each page of the wal-index mapping contains a hash-table made up of
--** an array of HASHTABLE_NSLOT elements of the following type.
-+** Return a pointer to the pPager->pBackup variable. The backup module
-+** in backup.c maintains the content of this variable. This module
-+** uses it opaquely as an argument to sqlite3BackupRestart() and
-+** sqlite3BackupUpdate() only.
- */
--typedef u16 ht_slot;
-+SQLITE_PRIVATE sqlite3_backup **sqlite3PagerBackupPtr(Pager *pPager){
-+ return &pPager->pBackup;
-+}
-
-+#ifndef SQLITE_OMIT_VACUUM
- /*
--** This structure is used to implement an iterator that loops through
--** all frames in the WAL in database page order. Where two or more frames
--** correspond to the same database page, the iterator visits only the
--** frame most recently written to the WAL (in other words, the frame with
--** the largest index).
--**
--** The internals of this structure are only accessed by:
--**
--** walIteratorInit() - Create a new iterator,
--** walIteratorNext() - Step an iterator,
--** walIteratorFree() - Free an iterator.
--**
--** This functionality is used by the checkpoint code (see walCheckpoint()).
-+** Unless this is an in-memory or temporary database, clear the pager cache.
- */
--struct WalIterator {
-- int iPrior; /* Last result returned from the iterator */
-- int nSegment; /* Number of entries in aSegment[] */
-- struct WalSegment {
-- int iNext; /* Next slot in aIndex[] not yet returned */
-- ht_slot *aIndex; /* i0, i1, i2... such that aPgno[iN] ascend */
-- u32 *aPgno; /* Array of page numbers. */
-- int nEntry; /* Nr. of entries in aPgno[] and aIndex[] */
-- int iZero; /* Frame number associated with aPgno[0] */
-- } aSegment[1]; /* One for every 32KB page in the wal-index */
--};
-+SQLITE_PRIVATE void sqlite3PagerClearCache(Pager *pPager){
-+ if( !MEMDB && pPager->tempFile==0 ) pager_reset(pPager);
-+}
+#endif
++/* END SQLCIPHER */
++
-+#ifndef SQLITE_OMIT_WAL
- /*
--** Define the parameters of the hash tables in the wal-index file. There
--** is a hash-table following every HASHTABLE_NPAGE page numbers in the
--** wal-index.
-+** This function is called when the user invokes "PRAGMA wal_checkpoint",
-+** "PRAGMA wal_blocking_checkpoint" or calls the sqlite3_wal_checkpoint()
-+** or wal_blocking_checkpoint() API functions.
- **
--** Changing any of these constants will alter the wal-index format and
--** create incompatibilities.
--*/
--#define HASHTABLE_NPAGE 4096 /* Must be power of 2 */
--#define HASHTABLE_HASH_1 383 /* Should be prime */
--#define HASHTABLE_NSLOT (HASHTABLE_NPAGE*2) /* Must be a power of 2 */
--
--/*
--** The block of page numbers associated with the first hash-table in a
--** wal-index is smaller than usual. This is so that there is a complete
--** hash-table on each aligned 32KB page of the wal-index.
-+** Parameter eMode is one of SQLITE_CHECKPOINT_PASSIVE, FULL or RESTART.
- */
--#define HASHTABLE_NPAGE_ONE (HASHTABLE_NPAGE - (WALINDEX_HDR_SIZE/sizeof(u32)))
-+SQLITE_PRIVATE int sqlite3PagerCheckpoint(Pager *pPager, int eMode, int *pnLog, int *pnCkpt){
-+ int rc = SQLITE_OK;
-+ if( pPager->pWal ){
-+ rc = sqlite3WalCheckpoint(pPager->pWal, eMode,
-+ pPager->xBusyHandler, pPager->pBusyHandlerArg,
-+ pPager->ckptSyncFlags, pPager->pageSize, (u8 *)pPager->pTmpSpace,
-+ pnLog, pnCkpt
-+ );
-+ }
-+ return rc;
-+}
-
--/* The wal-index is divided into pages of WALINDEX_PGSZ bytes each. */
--#define WALINDEX_PGSZ ( \
-- sizeof(ht_slot)*HASHTABLE_NSLOT + HASHTABLE_NPAGE*sizeof(u32) \
--)
-+SQLITE_PRIVATE int sqlite3PagerWalCallback(Pager *pPager){
-+ return sqlite3WalCallback(pPager->pWal);
-+}
-
- /*
--** Obtain a pointer to the iPage'th page of the wal-index. The wal-index
--** is broken into pages of WALINDEX_PGSZ bytes. Wal-index pages are
--** numbered from zero.
--**
--** If this call is successful, *ppPage is set to point to the wal-index
--** page and SQLITE_OK is returned. If an error (an OOM or VFS error) occurs,
--** then an SQLite error code is returned and *ppPage is set to 0.
-+** Return true if the underlying VFS for the given pager supports the
-+** primitives necessary for write-ahead logging.
- */
--static int walIndexPage(Wal *pWal, int iPage, volatile u32 **ppPage){
-- int rc = SQLITE_OK;
-+SQLITE_PRIVATE int sqlite3PagerWalSupported(Pager *pPager){
-+ const sqlite3_io_methods *pMethods = pPager->fd->pMethods;
-+ return pPager->exclusiveMode || (pMethods->iVersion>=2 && pMethods->xShmMap);
-+}
-
-- /* Enlarge the pWal->apWiData[] array if required */
-- if( pWal->nWiData<=iPage ){
-- int nByte = sizeof(u32*)*(iPage+1);
-- volatile u32 **apNew;
+ /************** End of pager.c ***********************************************/
+ /************** Begin file wal.c *********************************************/
+@@ -46046,3267 +49457,2596 @@
+ if( pWal->nWiData<=iPage ){
+ int nByte = sizeof(u32*)*(iPage+1);
+ volatile u32 **apNew;
- apNew = (volatile u32 **)sqlite3_realloc((void *)pWal->apWiData, nByte);
- if( !apNew ){
- *ppPage = 0;
@@ -64224,13 +3906,7 @@
- pWal->apWiData = apNew;
- pWal->nWiData = iPage+1;
- }
-+/*
-+** Attempt to take an exclusive lock on the database file. If a PENDING lock
-+** is obtained instead, immediately release it.
-+*/
-+static int pagerExclusiveLock(Pager *pPager){
-+ int rc; /* Return code */
-
+-
- /* Request a pointer to the required page from the VFS */
- if( pWal->apWiData[iPage]==0 ){
- if( pWal->exclusiveMode==WAL_HEAPMEMORY_MODE ){
@@ -64245,65 +3921,29 @@
- rc = SQLITE_OK;
- }
- }
-+ assert( pPager->eLock==SHARED_LOCK || pPager->eLock==EXCLUSIVE_LOCK );
-+ rc = pagerLockDb(pPager, EXCLUSIVE_LOCK);
-+ if( rc!=SQLITE_OK ){
-+ /* If the attempt to grab the exclusive lock failed, release the
-+ ** pending lock that may have been obtained instead. */
-+ pagerUnlockDb(pPager, SHARED_LOCK);
- }
-
+- }
+-
- *ppPage = pWal->apWiData[iPage];
- assert( iPage==0 || *ppPage || rc!=SQLITE_OK );
- return rc;
- }
-
- /*
+- return rc;
+-}
+-
+-/*
-** Return a pointer to the WalCkptInfo structure in the wal-index.
-+** Call sqlite3WalOpen() to open the WAL handle. If the pager is in
-+** exclusive-locking mode when this function is called, take an EXCLUSIVE
-+** lock on the database file and use heap-memory to store the wal-index
-+** in. Otherwise, use the normal shared-memory.
- */
+-*/
-static volatile WalCkptInfo *walCkptInfo(Wal *pWal){
- assert( pWal->nWiData>0 && pWal->apWiData[0] );
- return (volatile WalCkptInfo*)&(pWal->apWiData[0][sizeof(WalIndexHdr)/2]);
-}
-+static int pagerOpenWal(Pager *pPager){
-+ int rc = SQLITE_OK;
-
+-
-/*
-** Return a pointer to the WalIndexHdr structure in the wal-index.
-*/
-static volatile WalIndexHdr *walIndexHdr(Wal *pWal){
- assert( pWal->nWiData>0 && pWal->apWiData[0] );
- return (volatile WalIndexHdr*)pWal->apWiData[0];
-+ assert( pPager->pWal==0 && pPager->tempFile==0 );
-+ assert( pPager->eLock==SHARED_LOCK || pPager->eLock==EXCLUSIVE_LOCK );
-+
-+ /* If the pager is already in exclusive-mode, the WAL module will use
-+ ** heap-memory for the wal-index instead of the VFS shared-memory
-+ ** implementation. Take the exclusive lock now, before opening the WAL
-+ ** file, to make sure this is safe.
-+ */
-+ if( pPager->exclusiveMode ){
-+ rc = pagerExclusiveLock(pPager);
-+ }
-+
-+ /* Open the connection to the log file. If this operation fails,
-+ ** (e.g. due to malloc() failure), return an error code.
-+ */
-+ if( rc==SQLITE_OK ){
-+ rc = sqlite3WalOpen(pPager->pVfs,
-+ pPager->fd, pPager->zWal, pPager->exclusiveMode,
-+ pPager->journalSizeLimit, &pPager->pWal
-+ );
-+ }
-+ pagerFixMaplimit(pPager);
-+
-+ return rc;
- }
-
+-}
+-
-/*
-** The argument to this macro must be of type u32. On a little-endian
-** architecture, it returns the u32 value that results from interpreting
@@ -64315,148 +3955,65 @@
- (((x)&0x000000FF)<<24) + (((x)&0x0000FF00)<<8) \
- + (((x)&0x00FF0000)>>8) + (((x)&0xFF000000)>>24) \
-)
-
- /*
+-
+-/*
-** Generate or extend an 8 byte checksum based on the data in
-** array aByte[] and the initial values of aIn[0] and aIn[1] (or
-** initial values of 0 and 0 if aIn==NULL).
-+** The caller must be holding a SHARED lock on the database file to call
-+** this function.
- **
+-**
-** The checksum is written back into aOut[] before returning.
-+** If the pager passed as the first argument is open on a real database
-+** file (not a temp file or an in-memory database), and the WAL file
-+** is not already open, make an attempt to open it now. If successful,
-+** return SQLITE_OK. If an error occurs or the VFS used by the pager does
-+** not support the xShmXXX() methods, return an error code. *pbOpen is
-+** not modified in either case.
- **
+-**
-** nByte must be a positive multiple of 8.
-+** If the pager is open on a temp-file (or in-memory database), or if
-+** the WAL file is already open, set *pbOpen to 1 and return SQLITE_OK
-+** without doing anything.
- */
+-*/
-static void walChecksumBytes(
- int nativeCksum, /* True for native byte-order, false for non-native */
- u8 *a, /* Content to be checksummed */
- int nByte, /* Bytes of content in a[]. Must be a multiple of 8. */
- const u32 *aIn, /* Initial checksum value input */
- u32 *aOut /* OUT: Final checksum value output */
-+SQLITE_PRIVATE int sqlite3PagerOpenWal(
-+ Pager *pPager, /* Pager object */
-+ int *pbOpen /* OUT: Set to true if call is a no-op */
- ){
+-){
- u32 s1, s2;
- u32 *aData = (u32 *)a;
- u32 *aEnd = (u32 *)&a[nByte];
-+ int rc = SQLITE_OK; /* Return code */
-
+-
- if( aIn ){
- s1 = aIn[0];
- s2 = aIn[1];
- }else{
- s1 = s2 = 0;
- }
-+ assert( assert_pager_state(pPager) );
-+ assert( pPager->eState==PAGER_OPEN || pbOpen );
-+ assert( pPager->eState==PAGER_READER || !pbOpen );
-+ assert( pbOpen==0 || *pbOpen==0 );
-+ assert( pbOpen!=0 || (!pPager->tempFile && !pPager->pWal) );
-
+-
- assert( nByte>=8 );
- assert( (nByte&0x00000007)==0 );
-+ if( !pPager->tempFile && !pPager->pWal ){
-+ if( !sqlite3PagerWalSupported(pPager) ) return SQLITE_CANTOPEN;
-
+-
- if( nativeCksum ){
- do {
- s1 += *aData++ + s2;
- s2 += *aData++ + s1;
- }while( aData<aEnd );
-+ /* Close any rollback journal previously open */
-+ sqlite3OsClose(pPager->jfd);
-+
-+ rc = pagerOpenWal(pPager);
-+ if( rc==SQLITE_OK ){
-+ pPager->journalMode = PAGER_JOURNALMODE_WAL;
-+ pPager->eState = PAGER_OPEN;
-+ }
- }else{
+- }else{
- do {
- s1 += BYTESWAP32(aData[0]) + s2;
- s2 += BYTESWAP32(aData[1]) + s1;
- aData += 2;
- }while( aData<aEnd );
-+ *pbOpen = 1;
- }
-
+- }
+-
- aOut[0] = s1;
- aOut[1] = s2;
-+ return rc;
- }
-
+-}
+-
-static void walShmBarrier(Wal *pWal){
- if( pWal->exclusiveMode!=WAL_HEAPMEMORY_MODE ){
- sqlite3OsShmBarrier(pWal->pDbFd);
-+/*
-+** This function is called to close the connection to the log file prior
-+** to switching from WAL to rollback mode.
-+**
-+** Before closing the log file, this function attempts to take an
-+** EXCLUSIVE lock on the database file. If this cannot be obtained, an
-+** error (SQLITE_BUSY) is returned and the log connection is not closed.
-+** If successful, the EXCLUSIVE lock is not released before returning.
-+*/
-+SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager){
-+ int rc = SQLITE_OK;
-+
-+ assert( pPager->journalMode==PAGER_JOURNALMODE_WAL );
-+
-+ /* If the log file is not already open, but does exist in the file-system,
-+ ** it may need to be checkpointed before the connection can switch to
-+ ** rollback mode. Open it now so this can happen.
-+ */
-+ if( !pPager->pWal ){
-+ int logexists = 0;
-+ rc = pagerLockDb(pPager, SHARED_LOCK);
-+ if( rc==SQLITE_OK ){
-+ rc = sqlite3OsAccess(
-+ pPager->pVfs, pPager->zWal, SQLITE_ACCESS_EXISTS, &logexists
-+ );
-+ }
-+ if( rc==SQLITE_OK && logexists ){
-+ rc = pagerOpenWal(pPager);
-+ }
-+ }
-+
-+ /* Checkpoint and close the log. Because an EXCLUSIVE lock is held on
-+ ** the database file, the log and log-summary files will be deleted.
-+ */
-+ if( rc==SQLITE_OK && pPager->pWal ){
-+ rc = pagerExclusiveLock(pPager);
-+ if( rc==SQLITE_OK ){
-+ rc = sqlite3WalClose(pPager->pWal, pPager->ckptSyncFlags,
-+ pPager->pageSize, (u8*)pPager->pTmpSpace);
-+ pPager->pWal = 0;
-+ pagerFixMaplimit(pPager);
-+ }
- }
-+ return rc;
- }
-
-+#endif /* !SQLITE_OMIT_WAL */
-+
-+#ifdef SQLITE_ENABLE_ZIPVFS
- /*
+- }
+-}
+-
+-/*
-** Write the header information in pWal->hdr into the wal-index.
-**
-** The checksum on pWal->hdr is updated before it is written.
-+** A read-lock must be held on the pager when this function is called. If
-+** the pager is in WAL mode and the WAL file currently contains one or more
-+** frames, return the size in bytes of the page images stored within the
-+** WAL frames. Otherwise, if this is not a WAL database or the WAL file
-+** is empty, return 0.
- */
+-*/
-static void walIndexWriteHdr(Wal *pWal){
- volatile WalIndexHdr *aHdr = walIndexHdr(pWal);
- const int nCksum = offsetof(WalIndexHdr, aCksum);
@@ -64468,20 +4025,13 @@
- memcpy((void *)&aHdr[1], (void *)&pWal->hdr, sizeof(WalIndexHdr));
- walShmBarrier(pWal);
- memcpy((void *)&aHdr[0], (void *)&pWal->hdr, sizeof(WalIndexHdr));
-+SQLITE_PRIVATE int sqlite3PagerWalFramesize(Pager *pPager){
-+ assert( pPager->eState==PAGER_READER );
-+ return sqlite3WalFramesize(pPager->pWal);
- }
-+#endif
-
-+#ifdef SQLITE_HAS_CODEC
- /*
+-}
+-
+-/*
-** This function encodes a single frame header and writes it to a buffer
-** supplied by the caller. A frame-header is made up of a series of
-** 4-byte big-endian integers, as follows:
-+** This function is called by the wal module when writing page content
-+** into the log file.
- **
+-**
-** 0: Page number.
-** 4: For commit records, the size of the database image in pages
-** after the commit. For all other records, zero.
@@ -64489,9 +4039,7 @@
-** 12: Salt-2 (copied from the wal-header)
-** 16: Checksum-1.
-** 20: Checksum-2.
-+** This function returns a pointer to a buffer containing the encrypted
-+** page content. If a malloc fails, this function may return NULL.
- */
+-*/
-static void walEncodeFrame(
- Wal *pWal, /* The write-ahead log */
- u32 iPage, /* Database page number for frame */
@@ -64505,26 +4053,15 @@
- sqlite3Put4byte(&aFrame[0], iPage);
- sqlite3Put4byte(&aFrame[4], nTruncate);
- memcpy(&aFrame[8], pWal->hdr.aSalt, 8);
-+SQLITE_PRIVATE void *sqlite3PagerCodec(PgHdr *pPg){
-+ void *aData = 0;
-+ CODEC2(pPg->pPager, pPg->pData, pPg->pgno, 6, return 0, aData);
-+ return aData;
-+}
-+#endif /* SQLITE_HAS_CODEC */
-
+-
- nativeCksum = (pWal->hdr.bigEndCksum==SQLITE_BIGENDIAN);
- walChecksumBytes(nativeCksum, aFrame, 8, aCksum, aCksum);
- walChecksumBytes(nativeCksum, aData, pWal->szPage, aCksum, aCksum);
-+#endif /* SQLITE_OMIT_DISKIO */
-
+-
- sqlite3Put4byte(&aFrame[16], aCksum[0]);
- sqlite3Put4byte(&aFrame[20], aCksum[1]);
-+/* BEGIN SQLCIPHER */
-+#ifdef SQLITE_HAS_CODEC
-+SQLITE_PRIVATE void sqlite3pager_get_codec(Pager *pPager, void **ctx) {
-+ *ctx = pPager->pCodec;
- }
-
+-}
+-
-/*
-** Check to see if the frame with header in aFrame[] and content
-** in aData[] is valid. If it is a valid frame, fill *piPage and
@@ -64536,47 +4073,26 @@
- u32 *pnTruncate, /* OUT: New db size (or 0 if not commit) */
- u8 *aData, /* Pointer to page data (for checksum) */
- u8 *aFrame /* Frame data */
-+SQLITE_PRIVATE int sqlite3pager_is_mj_pgno(Pager *pPager, Pgno pgno) {
-+ return (PAGER_MJ_PGNO(pPager) == pgno) ? 1 : 0;
-+}
-+
-+SQLITE_PRIVATE sqlite3_file *sqlite3Pager_get_fd(Pager *pPager) {
-+ return (isOpen(pPager->fd)) ? pPager->fd : NULL;
-+}
-+
-+SQLITE_PRIVATE void sqlite3pager_sqlite3PagerSetCodec(
-+ Pager *pPager,
-+ void *(*xCodec)(void*,void*,Pgno,int),
-+ void (*xCodecSizeChng)(void*,int,int),
-+ void (*xCodecFree)(void*),
-+ void *pCodec
- ){
+-){
- int nativeCksum; /* True for native byte-order checksums */
- u32 *aCksum = pWal->hdr.aFrameCksum;
- u32 pgno; /* Page number of the frame */
- assert( WAL_FRAME_HDRSIZE==24 );
-+ sqlite3PagerSetCodec(pPager, xCodec, xCodecSizeChng, xCodecFree, pCodec);
-+}
-
+-
- /* A frame is only valid if the salt values in the frame-header
- ** match the salt values in the wal-header.
- */
- if( memcmp(&pWal->hdr.aSalt, &aFrame[8], 8)!=0 ){
- return 0;
- }
-+SQLITE_PRIVATE void sqlite3pager_sqlite3PagerSetError( Pager *pPager, int error) {
-+ pPager->errCode = error;
-+}
-
+-
- /* A frame is only valid if the page number is creater than zero.
- */
- pgno = sqlite3Get4byte(&aFrame[0]);
- if( pgno==0 ){
- return 0;
- }
-+#endif
-+/* END SQLCIPHER */
-
+-
- /* A frame is only valid if a checksum of the WAL header,
- ** all prior frams, the first 16 bytes of this frame-header,
- ** and the frame-data matches the checksum in the last 8
@@ -64591,7 +4107,7 @@
- /* Checksum failed. */
- return 0;
- }
-
+-
- /* If we reach this point, the frame is valid. Return the page number
- ** and the new database size.
- */
@@ -64599,259 +4115,13 @@
- *pnTruncate = sqlite3Get4byte(&aFrame[4]);
- return 1;
-}
-+/************** End of pager.c ***********************************************/
-+/************** Begin file wal.c *********************************************/
-+/*
-+** 2010 February 1
-+**
-+** The author disclaims copyright to this source code. In place of
-+** a legal notice, here is a blessing:
-+**
-+** May you do good and not evil.
-+** May you find forgiveness for yourself and forgive others.
-+** May you share freely, never taking more than you give.
-+**
-+*************************************************************************
-+**
-+** This file contains the implementation of a write-ahead log (WAL) used in
-+** "journal_mode=WAL" mode.
-+**
-+** WRITE-AHEAD LOG (WAL) FILE FORMAT
-+**
-+** A WAL file consists of a header followed by zero or more "frames".
-+** Each frame records the revised content of a single page from the
-+** database file. All changes to the database are recorded by writing
-+** frames into the WAL. Transactions commit when a frame is written that
-+** contains a commit marker. A single WAL can and usually does record
-+** multiple transactions. Periodically, the content of the WAL is
-+** transferred back into the database file in an operation called a
-+** "checkpoint".
-+**
-+** A single WAL file can be used multiple times. In other words, the
-+** WAL can fill up with frames and then be checkpointed and then new
-+** frames can overwrite the old ones. A WAL always grows from beginning
-+** toward the end. Checksums and counters attached to each frame are
-+** used to determine which frames within the WAL are valid and which
-+** are leftovers from prior checkpoints.
-+**
-+** The WAL header is 32 bytes in size and consists of the following eight
-+** big-endian 32-bit unsigned integer values:
-+**
-+** 0: Magic number. 0x377f0682 or 0x377f0683
-+** 4: File format version. Currently 3007000
-+** 8: Database page size. Example: 1024
-+** 12: Checkpoint sequence number
-+** 16: Salt-1, random integer incremented with each checkpoint
-+** 20: Salt-2, a different random integer changing with each ckpt
-+** 24: Checksum-1 (first part of checksum for first 24 bytes of header).
-+** 28: Checksum-2 (second part of checksum for first 24 bytes of header).
-+**
-+** Immediately following the wal-header are zero or more frames. Each
-+** frame consists of a 24-byte frame-header followed by a <page-size> bytes
-+** of page data. The frame-header is six big-endian 32-bit unsigned
-+** integer values, as follows:
-+**
-+** 0: Page number.
-+** 4: For commit records, the size of the database image in pages
-+** after the commit. For all other records, zero.
-+** 8: Salt-1 (copied from the header)
-+** 12: Salt-2 (copied from the header)
-+** 16: Checksum-1.
-+** 20: Checksum-2.
-+**
-+** A frame is considered valid if and only if the following conditions are
-+** true:
-+**
-+** (1) The salt-1 and salt-2 values in the frame-header match
-+** salt values in the wal-header
-+**
-+** (2) The checksum values in the final 8 bytes of the frame-header
-+** exactly match the checksum computed consecutively on the
-+** WAL header and the first 8 bytes and the content of all frames
-+** up to and including the current frame.
-+**
-+** The checksum is computed using 32-bit big-endian integers if the
-+** magic number in the first 4 bytes of the WAL is 0x377f0683 and it
-+** is computed using little-endian if the magic number is 0x377f0682.
-+** The checksum values are always stored in the frame header in a
-+** big-endian format regardless of which byte order is used to compute
-+** the checksum. The checksum is computed by interpreting the input as
-+** an even number of unsigned 32-bit integers: x[0] through x[N]. The
-+** algorithm used for the checksum is as follows:
-+**
-+** for i from 0 to n-1 step 2:
-+** s0 += x[i] + s1;
-+** s1 += x[i+1] + s0;
-+** endfor
-+**
-+** Note that s0 and s1 are both weighted checksums using fibonacci weights
-+** in reverse order (the largest fibonacci weight occurs on the first element
-+** of the sequence being summed.) The s1 value spans all 32-bit
-+** terms of the sequence whereas s0 omits the final term.
-+**
-+** On a checkpoint, the WAL is first VFS.xSync-ed, then valid content of the
-+** WAL is transferred into the database, then the database is VFS.xSync-ed.
-+** The VFS.xSync operations serve as write barriers - all writes launched
-+** before the xSync must complete before any write that launches after the
-+** xSync begins.
-+**
-+** After each checkpoint, the salt-1 value is incremented and the salt-2
-+** value is randomized. This prevents old and new frames in the WAL from
-+** being considered valid at the same time and being checkpointing together
-+** following a crash.
-+**
-+** READER ALGORITHM
-+**
-+** To read a page from the database (call it page number P), a reader
-+** first checks the WAL to see if it contains page P. If so, then the
-+** last valid instance of page P that is a followed by a commit frame
-+** or is a commit frame itself becomes the value read. If the WAL
-+** contains no copies of page P that are valid and which are a commit
-+** frame or are followed by a commit frame, then page P is read from
-+** the database file.
-+**
-+** To start a read transaction, the reader records the index of the last
-+** valid frame in the WAL. The reader uses this recorded "mxFrame" value
-+** for all subsequent read operations. New transactions can be appended
-+** to the WAL, but as long as the reader uses its original mxFrame value
-+** and ignores the newly appended content, it will see a consistent snapshot
-+** of the database from a single point in time. This technique allows
-+** multiple concurrent readers to view different versions of the database
-+** content simultaneously.
-+**
-+** The reader algorithm in the previous paragraphs works correctly, but
-+** because frames for page P can appear anywhere within the WAL, the
-+** reader has to scan the entire WAL looking for page P frames. If the
-+** WAL is large (multiple megabytes is typical) that scan can be slow,
-+** and read performance suffers. To overcome this problem, a separate
-+** data structure called the wal-index is maintained to expedite the
-+** search for frames of a particular page.
-+**
-+** WAL-INDEX FORMAT
-+**
-+** Conceptually, the wal-index is shared memory, though VFS implementations
-+** might choose to implement the wal-index using a mmapped file. Because
-+** the wal-index is shared memory, SQLite does not support journal_mode=WAL
-+** on a network filesystem. All users of the database must be able to
-+** share memory.
-+**
-+** The wal-index is transient. After a crash, the wal-index can (and should
-+** be) reconstructed from the original WAL file. In fact, the VFS is required
-+** to either truncate or zero the header of the wal-index when the last
-+** connection to it closes. Because the wal-index is transient, it can
-+** use an architecture-specific format; it does not have to be cross-platform.
-+** Hence, unlike the database and WAL file formats which store all values
-+** as big endian, the wal-index can store multi-byte values in the native
-+** byte order of the host computer.
-+**
-+** The purpose of the wal-index is to answer this question quickly: Given
-+** a page number P and a maximum frame index M, return the index of the
-+** last frame in the wal before frame M for page P in the WAL, or return
-+** NULL if there are no frames for page P in the WAL prior to M.
-+**
-+** The wal-index consists of a header region, followed by an one or
-+** more index blocks.
-+**
-+** The wal-index header contains the total number of frames within the WAL
-+** in the mxFrame field.
-+**
-+** Each index block except for the first contains information on
-+** HASHTABLE_NPAGE frames. The first index block contains information on
-+** HASHTABLE_NPAGE_ONE frames. The values of HASHTABLE_NPAGE_ONE and
-+** HASHTABLE_NPAGE are selected so that together the wal-index header and
-+** first index block are the same size as all other index blocks in the
-+** wal-index.
-+**
-+** Each index block contains two sections, a page-mapping that contains the
-+** database page number associated with each wal frame, and a hash-table
-+** that allows readers to query an index block for a specific page number.
-+** The page-mapping is an array of HASHTABLE_NPAGE (or HASHTABLE_NPAGE_ONE
-+** for the first index block) 32-bit page numbers. The first entry in the
-+** first index-block contains the database page number corresponding to the
-+** first frame in the WAL file. The first entry in the second index block
-+** in the WAL file corresponds to the (HASHTABLE_NPAGE_ONE+1)th frame in
-+** the log, and so on.
-+**
-+** The last index block in a wal-index usually contains less than the full
-+** complement of HASHTABLE_NPAGE (or HASHTABLE_NPAGE_ONE) page-numbers,
-+** depending on the contents of the WAL file. This does not change the
-+** allocated size of the page-mapping array - the page-mapping array merely
-+** contains unused entries.
-+**
-+** Even without using the hash table, the last frame for page P
-+** can be found by scanning the page-mapping sections of each index block
-+** starting with the last index block and moving toward the first, and
-+** within each index block, starting at the end and moving toward the
-+** beginning. The first entry that equals P corresponds to the frame
-+** holding the content for that page.
-+**
-+** The hash table consists of HASHTABLE_NSLOT 16-bit unsigned integers.
-+** HASHTABLE_NSLOT = 2*HASHTABLE_NPAGE, and there is one entry in the
-+** hash table for each page number in the mapping section, so the hash
-+** table is never more than half full. The expected number of collisions
-+** prior to finding a match is 1. Each entry of the hash table is an
-+** 1-based index of an entry in the mapping section of the same
-+** index block. Let K be the 1-based index of the largest entry in
-+** the mapping section. (For index blocks other than the last, K will
-+** always be exactly HASHTABLE_NPAGE (4096) and for the last index block
-+** K will be (mxFrame%HASHTABLE_NPAGE).) Unused slots of the hash table
-+** contain a value of 0.
-+**
-+** To look for page P in the hash table, first compute a hash iKey on
-+** P as follows:
-+**
-+** iKey = (P * 383) % HASHTABLE_NSLOT
-+**
-+** Then start scanning entries of the hash table, starting with iKey
-+** (wrapping around to the beginning when the end of the hash table is
-+** reached) until an unused hash slot is found. Let the first unused slot
-+** be at index iUnused. (iUnused might be less than iKey if there was
-+** wrap-around.) Because the hash table is never more than half full,
-+** the search is guaranteed to eventually hit an unused entry. Let
-+** iMax be the value between iKey and iUnused, closest to iUnused,
-+** where aHash[iMax]==P. If there is no iMax entry (if there exists
-+** no hash slot such that aHash[i]==p) then page P is not in the
-+** current index block. Otherwise the iMax-th mapping entry of the
-+** current index block corresponds to the last entry that references
-+** page P.
-+**
-+** A hash search begins with the last index block and moves toward the
-+** first index block, looking for entries corresponding to page P. On
-+** average, only two or three slots in each index block need to be
-+** examined in order to either find the last entry for page P, or to
-+** establish that no such entry exists in the block. Each index block
-+** holds over 4000 entries. So two or three index blocks are sufficient
-+** to cover a typical 10 megabyte WAL file, assuming 1K pages. 8 or 10
-+** comparisons (on average) suffice to either locate a frame in the
-+** WAL or to establish that the frame does not exist in the WAL. This
-+** is much faster than scanning the entire 10MB WAL.
-+**
-+** Note that entries are added in order of increasing K. Hence, one
-+** reader might be using some value K0 and a second reader that started
-+** at a later time (after additional transactions were added to the WAL
-+** and to the wal-index) might be using a different value K1, where K1>K0.
-+** Both readers can use the same hash table and mapping section to get
-+** the correct result. There may be entries in the hash table with
-+** K>K0 but to the first reader, those entries will appear to be unused
-+** slots in the hash table and so the first reader will get an answer as
-+** if no values greater than K0 had ever been inserted into the hash table
-+** in the first place - which is what reader one wants. Meanwhile, the
-+** second reader using K1 will see additional values that were inserted
-+** later, which is exactly what reader two wants.
-+**
-+** When a rollback occurs, the value of K is decreased. Hash table entries
-+** that correspond to frames greater than the new K value are removed
-+** from the hash table at this point.
-+*/
-+#ifndef SQLITE_OMIT_WAL
-
-
+-
+-
-#if defined(SQLITE_TEST) && defined(SQLITE_DEBUG)
- /*
+-/*
-** Names of locks. This routine is used to provide debugging output and is not
-** a part of an ordinary build.
-+** Trace output macros
- */
+-*/
-static const char *walLockName(int lockIdx){
- if( lockIdx==WAL_WRITE_LOCK ){
- return "WRITE-LOCK";
@@ -64868,30 +4138,14 @@
-}
-#endif /*defined(SQLITE_TEST) || defined(SQLITE_DEBUG) */
-
-+#if defined(SQLITE_TEST) && defined(SQLITE_DEBUG)
-+SQLITE_PRIVATE int sqlite3WalTrace = 0;
-+# define WALTRACE(X) if(sqlite3WalTrace) sqlite3DebugPrintf X
-+#else
-+# define WALTRACE(X)
-+#endif
-
- /*
+-
+-/*
-** Set or release locks on the WAL. Locks are either shared or exclusive.
-** A lock cannot be moved directly between shared and exclusive - it must go
-** through the unlocked state first.
-+** The maximum (and only) versions of the wal and wal-index formats
-+** that may be interpreted by this version of SQLite.
- **
+-**
-** In locking_mode=EXCLUSIVE, all of these routines become no-ops.
-+** If a client begins recovering a WAL file and finds that (a) the checksum
-+** values in the wal-header are correct and (b) the version field is not
-+** WAL_MAX_VERSION, recovery fails and SQLite returns SQLITE_CANTOPEN.
-+**
-+** Similarly, if a client successfully reads a wal-index header (i.e. the
-+** checksum test is successful) and finds that the version field is not
-+** WALINDEX_MAX_VERSION, then no read-transaction is opened and SQLite
-+** returns SQLITE_CANTOPEN.
- */
+-*/
-static int walLockShared(Wal *pWal, int lockIdx){
- int rc;
- if( pWal->exclusiveMode ) return SQLITE_OK;
@@ -64925,10 +4179,8 @@
- WALTRACE(("WAL%p: release EXCLUSIVE-%s cnt=%d\n", pWal,
- walLockName(lockIdx), n));
-}
-+#define WAL_MAX_VERSION 3007000
-+#define WALINDEX_MAX_VERSION 3007000
-
- /*
+-
+-/*
-** Compute a hash on a page number. The resulting hash value must land
-** between 0 and (HASHTABLE_NSLOT-1). The walHashNext() function advances
-** the hash to the next value in the event of a collision.
@@ -64955,9 +4207,7 @@
-**
-** Finally, set *paPgno so that *paPgno[1] is the page number of the
-** first frame indexed by the hash table, frame (*piZero+1).
-+** Indices of various locking bytes. WAL_NREADER is the number
-+** of available reader locks and should be at least 3.
- */
+-*/
-static int walHashGet(
- Wal *pWal, /* WAL handle */
- int iHash, /* Find the iHash'th table */
@@ -64970,17 +4220,11 @@
-
- rc = walIndexPage(pWal, iHash, &aPgno);
- assert( rc==SQLITE_OK || iHash>0 );
-+#define WAL_WRITE_LOCK 0
-+#define WAL_ALL_BUT_WRITE 1
-+#define WAL_CKPT_LOCK 1
-+#define WAL_RECOVER_LOCK 2
-+#define WAL_READ_LOCK(I) (3+(I))
-+#define WAL_NREADER (SQLITE_SHM_NLOCK-3)
-
+-
- if( rc==SQLITE_OK ){
- u32 iZero;
- volatile ht_slot *aHash;
-
+-
- aHash = (volatile ht_slot *)&aPgno[HASHTABLE_NPAGE];
- if( iHash==0 ){
- aPgno = &aPgno[WALINDEX_HDR_SIZE/sizeof(u32)];
@@ -64995,11 +4239,7 @@
- }
- return rc;
-}
-+/* Object declarations */
-+typedef struct WalIndexHdr WalIndexHdr;
-+typedef struct WalIterator WalIterator;
-+typedef struct WalCkptInfo WalCkptInfo;
-
+-
-/*
-** Return the number of the wal-index page that contains the hash-table
-** and page-number array that contain entries corresponding to WAL frame
@@ -65016,18 +4256,10 @@
- );
- return iHash;
-}
-
- /*
+-
+-/*
-** Return the page number associated with frame iFrame in this WAL.
-+** The following object holds a copy of the wal-index header content.
-+**
-+** The actual header in the wal-index consists of two copies of this
-+** object.
-+**
-+** The szPage value can be any power of 2 between 512 and 32768, inclusive.
-+** Or it can be 1 to represent a 65536-byte page. The latter case was
-+** added in 3.7.1 when support for 64K pages was added.
- */
+-*/
-static u32 walFramePgno(Wal *pWal, u32 iFrame){
- int iHash = walFramePage(iFrame);
- if( iHash==0 ){
@@ -65035,77 +4267,19 @@
- }
- return pWal->apWiData[iHash][(iFrame-1-HASHTABLE_NPAGE_ONE)%HASHTABLE_NPAGE];
-}
-+struct WalIndexHdr {
-+ u32 iVersion; /* Wal-index version */
-+ u32 unused; /* Unused (padding) field */
-+ u32 iChange; /* Counter incremented each transaction */
-+ u8 isInit; /* 1 when initialized */
-+ u8 bigEndCksum; /* True if checksums in WAL are big-endian */
-+ u16 szPage; /* Database page size in bytes. 1==64K */
-+ u32 mxFrame; /* Index of last valid frame in the WAL */
-+ u32 nPage; /* Size of database in pages */
-+ u32 aFrameCksum[2]; /* Checksum of last frame in log */
-+ u32 aSalt[2]; /* Two salt values copied from WAL header */
-+ u32 aCksum[2]; /* Checksum over all prior fields */
-+};
-
- /*
+-
+-/*
-** Remove entries from the hash table that point to WAL slots greater
-** than pWal->hdr.mxFrame.
-+** A copy of the following object occurs in the wal-index immediately
-+** following the second copy of the WalIndexHdr. This object stores
-+** information used by checkpoint.
- **
+-**
-** This function is called whenever pWal->hdr.mxFrame is decreased due
-** to a rollback or savepoint.
-+** nBackfill is the number of frames in the WAL that have been written
-+** back into the database. (We call the act of moving content from WAL to
-+** database "backfilling".) The nBackfill number is never greater than
-+** WalIndexHdr.mxFrame. nBackfill can only be increased by threads
-+** holding the WAL_CKPT_LOCK lock (which includes a recovery thread).
-+** However, a WAL_WRITE_LOCK thread can move the value of nBackfill from
-+** mxFrame back to zero when the WAL is reset.
- **
+-**
-** At most only the hash table containing pWal->hdr.mxFrame needs to be
-** updated. Any later hash tables will be automatically cleared when
-** pWal->hdr.mxFrame advances to the point where those hash tables are
-** actually needed.
-+** There is one entry in aReadMark[] for each reader lock. If a reader
-+** holds read-lock K, then the value in aReadMark[K] is no greater than
-+** the mxFrame for that reader. The value READMARK_NOT_USED (0xffffffff)
-+** for any aReadMark[] means that entry is unused. aReadMark[0] is
-+** a special case; its value is never used and it exists as a place-holder
-+** to avoid having to offset aReadMark[] indexs by one. Readers holding
-+** WAL_READ_LOCK(0) always ignore the entire WAL and read all content
-+** directly from the database.
-+**
-+** The value of aReadMark[K] may only be changed by a thread that
-+** is holding an exclusive lock on WAL_READ_LOCK(K). Thus, the value of
-+** aReadMark[K] cannot changed while there is a reader is using that mark
-+** since the reader will be holding a shared lock on WAL_READ_LOCK(K).
-+**
-+** The checkpointer may only transfer frames from WAL to database where
-+** the frame numbers are less than or equal to every aReadMark[] that is
-+** in use (that is, every aReadMark[j] for which there is a corresponding
-+** WAL_READ_LOCK(j)). New readers (usually) pick the aReadMark[] with the
-+** largest value and will increase an unused aReadMark[] to mxFrame if there
-+** is not already an aReadMark[] equal to mxFrame. The exception to the
-+** previous sentence is when nBackfill equals mxFrame (meaning that everything
-+** in the WAL has been backfilled into the database) then new readers
-+** will choose aReadMark[0] which has value 0 and hence such reader will
-+** get all their all content directly from the database file and ignore
-+** the WAL.
-+**
-+** Writers normally append new frames to the end of the WAL. However,
-+** if nBackfill equals mxFrame (meaning that all WAL content has been
-+** written back into the database) and if no readers are using the WAL
-+** (in other words, if there are no WAL_READ_LOCK(i) where i>0) then
-+** the writer will first "reset" the WAL back to the beginning and start
-+** writing new content beginning at frame 1.
-+**
-+** We assume that 32-bit loads are atomic and so no locks are needed in
-+** order to read from any aReadMark[] entries.
- */
+-*/
-static void walCleanupHash(Wal *pWal){
- volatile ht_slot *aHash = 0; /* Pointer to hash table to clear */
- volatile u32 *aPgno = 0; /* Page number array for hash table */
@@ -65118,14 +4292,9 @@
- testcase( pWal->hdr.mxFrame==HASHTABLE_NPAGE_ONE-1 );
- testcase( pWal->hdr.mxFrame==HASHTABLE_NPAGE_ONE );
- testcase( pWal->hdr.mxFrame==HASHTABLE_NPAGE_ONE+1 );
-+struct WalCkptInfo {
-+ u32 nBackfill; /* Number of WAL frames backfilled into DB */
-+ u32 aReadMark[WAL_NREADER]; /* Reader marks */
-+};
-+#define READMARK_NOT_USED 0xffffffff
-
+-
- if( pWal->hdr.mxFrame==0 ) return;
-
+-
- /* Obtain pointers to the hash-table and page-number array containing
- ** the entry that corresponds to frame pWal->hdr.mxFrame. It is guaranteed
- ** that the page said hash-table and array reside on is already mapped.
@@ -65133,15 +4302,7 @@
- assert( pWal->nWiData>walFramePage(pWal->hdr.mxFrame) );
- assert( pWal->apWiData[walFramePage(pWal->hdr.mxFrame)] );
- walHashGet(pWal, walFramePage(pWal->hdr.mxFrame), &aHash, &aPgno, &iZero);
-+/* A block of WALINDEX_LOCK_RESERVED bytes beginning at
-+** WALINDEX_LOCK_OFFSET is reserved for locks. Since some systems
-+** only support mandatory file-locks, we do not read or write data
-+** from the region of the file on which locks are applied.
-+*/
-+#define WALINDEX_LOCK_OFFSET (sizeof(WalIndexHdr)*2 + sizeof(WalCkptInfo))
-+#define WALINDEX_LOCK_RESERVED 16
-+#define WALINDEX_HDR_SIZE (WALINDEX_LOCK_OFFSET+WALINDEX_LOCK_RESERVED)
-
+-
- /* Zero all hash-table entries that correspond to frame numbers greater
- ** than pWal->hdr.mxFrame.
- */
@@ -65158,9 +4319,7 @@
- */
- nByte = (int)((char *)aHash - (char *)&aPgno[iLimit+1]);
- memset((void *)&aPgno[iLimit+1], 0, nByte);
-+/* Size of header before each frame in wal */
-+#define WAL_FRAME_HDRSIZE 24
-
+-
-#ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT
- /* Verify that the every entry in the mapping region is still reachable
- ** via the hash table even after the cleanup.
@@ -65177,28 +4336,12 @@
- }
-#endif /* SQLITE_ENABLE_EXPENSIVE_ASSERT */
-}
-+/* Size of write ahead log header, including checksum. */
-+/* #define WAL_HDRSIZE 24 */
-+#define WAL_HDRSIZE 32
-
-+/* WAL magic value. Either this value, or the same value with the least
-+** significant bit also set (WAL_MAGIC | 0x00000001) is stored in 32-bit
-+** big-endian format in the first 4 bytes of a WAL file.
-+**
-+** If the LSB is set, then the checksums for each frame within the WAL
-+** file are calculated by treating all data as an array of 32-bit
-+** big-endian words. Otherwise, they are calculated by interpreting
-+** all data as 32-bit little-endian words.
-+*/
-+#define WAL_MAGIC 0x377f0682
-
- /*
+-
+-
+-/*
-** Set an entry in the wal-index that will map database page number
-** pPage into WAL frame iFrame.
-+** Return the offset of frame iFrame in the write-ahead log file,
-+** assuming a database page size of szPage bytes. The offset returned
-+** is to the start of the write-ahead log frame-header.
- */
+-*/
-static int walIndexAppend(Wal *pWal, u32 iFrame, u32 iPage){
- int rc; /* Return code */
- u32 iZero = 0; /* One less than frame number of aPgno[1] */
@@ -65214,10 +4357,7 @@
- int iKey; /* Hash table key */
- int idx; /* Value to write to hash-table slot */
- int nCollide; /* Number of hash collisions */
-+#define walFrameOffset(iFrame, szPage) ( \
-+ WAL_HDRSIZE + ((iFrame)-1)*(i64)((szPage)+WAL_FRAME_HDRSIZE) \
-+)
-
+-
- idx = iFrame - iZero;
- assert( idx <= HASHTABLE_NSLOT/2 + 1 );
-
@@ -65228,37 +4368,7 @@
- int nByte = (int)((u8 *)&aHash[HASHTABLE_NSLOT] - (u8 *)&aPgno[1]);
- memset((void*)&aPgno[1], 0, nByte);
- }
-+/*
-+** An open write-ahead log file is represented by an instance of the
-+** following object.
-+*/
-+struct Wal {
-+ sqlite3_vfs *pVfs; /* The VFS used to create pDbFd */
-+ sqlite3_file *pDbFd; /* File handle for the database file */
-+ sqlite3_file *pWalFd; /* File handle for WAL file */
-+ u32 iCallback; /* Value to pass to log callback (or 0) */
-+ i64 mxWalSize; /* Truncate WAL to this size upon reset */
-+ int nWiData; /* Size of array apWiData */
-+ int szFirstBlock; /* Size of first block written to WAL file */
-+ volatile u32 **apWiData; /* Pointer to wal-index content in memory */
-+ u32 szPage; /* Database page size */
-+ i16 readLock; /* Which read lock is being held. -1 for none */
-+ u8 syncFlags; /* Flags to use to sync header writes */
-+ u8 exclusiveMode; /* Non-zero if connection is in exclusive mode */
-+ u8 writeLock; /* True if in a write transaction */
-+ u8 ckptLock; /* True if holding a checkpoint lock */
-+ u8 readOnly; /* WAL_RDWR, WAL_RDONLY, or WAL_SHM_RDONLY */
-+ u8 truncateOnCommit; /* True to truncate WAL file on commit */
-+ u8 syncHeader; /* Fsync the WAL header if true */
-+ u8 padToSectorBoundary; /* Pad transactions out to the next sector */
-+ WalIndexHdr hdr; /* Wal-index header for current transaction */
-+ const char *zWalName; /* Name of WAL file */
-+ u32 nCkpt; /* Checkpoint sequence counter in the wal-header */
-+#ifdef SQLITE_DEBUG
-+ u8 lockError; /* True if a locking error has occurred */
-+#endif
-+};
-
+-
- /* If the entry in aPgno[] is already set, then the previous writer
- ** must have exited unexpectedly in the middle of a transaction (after
- ** writing one or more dirty pages to the WAL to free up memory).
@@ -65269,13 +4379,7 @@
- walCleanupHash(pWal);
- assert( !aPgno[idx] );
- }
-+/*
-+** Candidate values for Wal.exclusiveMode.
-+*/
-+#define WAL_NORMAL_MODE 0
-+#define WAL_EXCLUSIVE_MODE 1
-+#define WAL_HEAPMEMORY_MODE 2
-
+-
- /* Write the aPgno[] array entry and the hash-table slot. */
- nCollide = idx;
- for(iKey=walHash(iPage); aHash[iKey]; iKey=walNextHash(iKey)){
@@ -65283,13 +4387,7 @@
- }
- aPgno[idx] = iPage;
- aHash[iKey] = (ht_slot)idx;
-+/*
-+** Possible values for WAL.readOnly
-+*/
-+#define WAL_RDWR 0 /* Normal read/write connection */
-+#define WAL_RDONLY 1 /* The WAL file is readonly */
-+#define WAL_SHM_RDONLY 2 /* The SHM file is readonly */
-
+-
-#ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT
- /* Verify that the number of entries in the hash table exactly equals
- ** the number of entries in the mapping region.
@@ -65299,12 +4397,16 @@
- int nEntry = 0; /* Number of entries in the hash table */
- for(i=0; i<HASHTABLE_NSLOT; i++){ if( aHash[i] ) nEntry++; }
- assert( nEntry==idx );
-- }
-+/*
-+** Each page of the wal-index mapping contains a hash-table made up of
-+** an array of HASHTABLE_NSLOT elements of the following type.
-+*/
-+typedef u16 ht_slot;
++ apNew = (volatile u32 **)sqlite3_realloc((void *)pWal->apWiData, nByte);
++ if( !apNew ){
++ *ppPage = 0;
++ return SQLITE_NOMEM;
+ }
++ memset((void*)&apNew[pWal->nWiData], 0,
++ sizeof(u32*)*(iPage+1-pWal->nWiData));
++ pWal->apWiData = apNew;
++ pWal->nWiData = iPage+1;
++ }
- /* Verify that the every entry in the mapping region is reachable
- ** via the hash table. This turns out to be a really, really expensive
@@ -65318,78 +4420,47 @@
- if( aHash[iKey]==i ) break;
- }
- assert( aHash[iKey]==i );
-- }
-- }
++ /* Request a pointer to the required page from the VFS */
++ if( pWal->apWiData[iPage]==0 ){
++ if( pWal->exclusiveMode==WAL_HEAPMEMORY_MODE ){
++ pWal->apWiData[iPage] = (u32 volatile *)sqlite3MallocZero(WALINDEX_PGSZ);
++ if( !pWal->apWiData[iPage] ) rc = SQLITE_NOMEM;
++ }else{
++ rc = sqlite3OsShmMap(pWal->pDbFd, iPage, WALINDEX_PGSZ,
++ pWal->writeLock, (void volatile **)&pWal->apWiData[iPage]
++ );
++ if( rc==SQLITE_READONLY ){
++ pWal->readOnly |= WAL_SHM_RDONLY;
++ rc = SQLITE_OK;
+ }
+ }
-#endif /* SQLITE_ENABLE_EXPENSIVE_ASSERT */
-- }
-+/*
-+** This structure is used to implement an iterator that loops through
-+** all frames in the WAL in database page order. Where two or more frames
-+** correspond to the same database page, the iterator visits only the
-+** frame most recently written to the WAL (in other words, the frame with
-+** the largest index).
-+**
-+** The internals of this structure are only accessed by:
-+**
-+** walIteratorInit() - Create a new iterator,
-+** walIteratorNext() - Step an iterator,
-+** walIteratorFree() - Free an iterator.
-+**
-+** This functionality is used by the checkpoint code (see walCheckpoint()).
-+*/
-+struct WalIterator {
-+ int iPrior; /* Last result returned from the iterator */
-+ int nSegment; /* Number of entries in aSegment[] */
-+ struct WalSegment {
-+ int iNext; /* Next slot in aIndex[] not yet returned */
-+ ht_slot *aIndex; /* i0, i1, i2... such that aPgno[iN] ascend */
-+ u32 *aPgno; /* Array of page numbers. */
-+ int nEntry; /* Nr. of entries in aPgno[] and aIndex[] */
-+ int iZero; /* Frame number associated with aPgno[0] */
-+ } aSegment[1]; /* One for every 32KB page in the wal-index */
-+};
+ }
-+/*
-+** Define the parameters of the hash tables in the wal-index file. There
-+** is a hash-table following every HASHTABLE_NPAGE page numbers in the
-+** wal-index.
-+**
-+** Changing any of these constants will alter the wal-index format and
-+** create incompatibilities.
-+*/
-+#define HASHTABLE_NPAGE 4096 /* Must be power of 2 */
-+#define HASHTABLE_HASH_1 383 /* Should be prime */
-+#define HASHTABLE_NSLOT (HASHTABLE_NPAGE*2) /* Must be a power of 2 */
+-
++ *ppPage = pWal->apWiData[iPage];
++ assert( iPage==0 || *ppPage || rc!=SQLITE_OK );
+ return rc;
+ }
-- return rc;
--}
-+/*
-+** The block of page numbers associated with the first hash-table in a
-+** wal-index is smaller than usual. This is so that there is a complete
-+** hash-table on each aligned 32KB page of the wal-index.
++/*
++** Return a pointer to the WalCkptInfo structure in the wal-index.
+*/
-+#define HASHTABLE_NPAGE_ONE (HASHTABLE_NPAGE - (WALINDEX_HDR_SIZE/sizeof(u32)))
-
-+/* The wal-index is divided into pages of WALINDEX_PGSZ bytes each. */
-+#define WALINDEX_PGSZ ( \
-+ sizeof(ht_slot)*HASHTABLE_NSLOT + HASHTABLE_NPAGE*sizeof(u32) \
-+)
++static volatile WalCkptInfo *walCkptInfo(Wal *pWal){
++ assert( pWal->nWiData>0 && pWal->apWiData[0] );
++ return (volatile WalCkptInfo*)&(pWal->apWiData[0][sizeof(WalIndexHdr)/2]);
++}
/*
-** Recover the wal-index by reading the write-ahead log file.
-+** Obtain a pointer to the iPage'th page of the wal-index. The wal-index
-+** is broken into pages of WALINDEX_PGSZ bytes. Wal-index pages are
-+** numbered from zero.
- **
+-**
-** This routine first tries to establish an exclusive lock on the
-** wal-index to prevent other threads/processes from doing anything
-** with the WAL or wal-index while recovery is running. The
-** WAL_RECOVER_LOCK is also held so that other threads will know
-** that this thread is running recovery. If unable to establish
-** the necessary locks, this routine returns SQLITE_BUSY.
-+** If this call is successful, *ppPage is set to point to the wal-index
-+** page and SQLITE_OK is returned. If an error (an OOM or VFS error) occurs,
-+** then an SQLite error code is returned and *ppPage is set to 0.
++** Return a pointer to the WalIndexHdr structure in the wal-index.
*/
-static int walIndexRecover(Wal *pWal){
- int rc; /* Return Code */
@@ -65397,7 +4468,11 @@
- u32 aFrameCksum[2] = {0, 0};
- int iLock; /* Lock offset to lock for checkpoint */
- int nLock; /* Number of locks to hold */
--
++static volatile WalIndexHdr *walIndexHdr(Wal *pWal){
++ assert( pWal->nWiData>0 && pWal->apWiData[0] );
++ return (volatile WalIndexHdr*)pWal->apWiData[0];
++}
+
- /* Obtain an exclusive lock on all byte in the locking range not already
- ** locked by the caller. The caller is guaranteed to have locked the
- ** WAL_WRITE_LOCK byte, and may have also locked the WAL_CKPT_LOCK byte.
@@ -65415,27 +4490,47 @@
- return rc;
- }
- WALTRACE(("WAL%p: recovery begin...\n", pWal));
--
++/*
++** The argument to this macro must be of type u32. On a little-endian
++** architecture, it returns the u32 value that results from interpreting
++** the 4 bytes as a big-endian value. On a big-endian architecture, it
++** returns the value that would be produced by intepreting the 4 bytes
++** of the input value as a little-endian integer.
++*/
++#define BYTESWAP32(x) ( \
++ (((x)&0x000000FF)<<24) + (((x)&0x0000FF00)<<8) \
++ + (((x)&0x00FF0000)>>8) + (((x)&0xFF000000)>>24) \
++)
+
- memset(&pWal->hdr, 0, sizeof(WalIndexHdr));
-+static int walIndexPage(Wal *pWal, int iPage, volatile u32 **ppPage){
-+ int rc = SQLITE_OK;
++/*
++** Generate or extend an 8 byte checksum based on the data in
++** array aByte[] and the initial values of aIn[0] and aIn[1] (or
++** initial values of 0 and 0 if aIn==NULL).
++**
++** The checksum is written back into aOut[] before returning.
++**
++** nByte must be a positive multiple of 8.
++*/
++static void walChecksumBytes(
++ int nativeCksum, /* True for native byte-order, false for non-native */
++ u8 *a, /* Content to be checksummed */
++ int nByte, /* Bytes of content in a[]. Must be a multiple of 8. */
++ const u32 *aIn, /* Initial checksum value input */
++ u32 *aOut /* OUT: Final checksum value output */
++){
++ u32 s1, s2;
++ u32 *aData = (u32 *)a;
++ u32 *aEnd = (u32 *)&a[nByte];
- rc = sqlite3OsFileSize(pWal->pWalFd, &nSize);
- if( rc!=SQLITE_OK ){
- goto recovery_error;
-+ /* Enlarge the pWal->apWiData[] array if required */
-+ if( pWal->nWiData<=iPage ){
-+ int nByte = sizeof(u32*)*(iPage+1);
-+ volatile u32 **apNew;
-+ apNew = (volatile u32 **)sqlite3_realloc((void *)pWal->apWiData, nByte);
-+ if( !apNew ){
-+ *ppPage = 0;
-+ return SQLITE_NOMEM;
-+ }
-+ memset((void*)&apNew[pWal->nWiData], 0,
-+ sizeof(u32*)*(iPage+1-pWal->nWiData));
-+ pWal->apWiData = apNew;
-+ pWal->nWiData = iPage+1;
++ if( aIn ){
++ s1 = aIn[0];
++ s2 = aIn[1];
++ }else{
++ s1 = s2 = 0;
}
- if( nSize>WAL_HDRSIZE ){
@@ -65454,22 +4549,8 @@
- rc = sqlite3OsRead(pWal->pWalFd, aBuf, WAL_HDRSIZE, 0);
- if( rc!=SQLITE_OK ){
- goto recovery_error;
-+ /* Request a pointer to the required page from the VFS */
-+ if( pWal->apWiData[iPage]==0 ){
-+ if( pWal->exclusiveMode==WAL_HEAPMEMORY_MODE ){
-+ pWal->apWiData[iPage] = (u32 volatile *)sqlite3MallocZero(WALINDEX_PGSZ);
-+ if( !pWal->apWiData[iPage] ) rc = SQLITE_NOMEM;
-+ }else{
-+ rc = sqlite3OsShmMap(pWal->pDbFd, iPage, WALINDEX_PGSZ,
-+ pWal->writeLock, (void volatile **)&pWal->apWiData[iPage]
-+ );
-+ if( rc==SQLITE_READONLY ){
-+ pWal->readOnly |= WAL_SHM_RDONLY;
-+ rc = SQLITE_OK;
-+ }
- }
-+ }
-
+- }
+-
- /* If the database page size is not a power of two, or is greater than
- ** SQLITE_MAX_PAGE_SIZE, conclude that the WAL file contains no valid
- ** data. Similarly, if the 'magic' value is invalid, ignore the whole
@@ -65488,11 +4569,7 @@
- pWal->szPage = szPage;
- pWal->nCkpt = sqlite3Get4byte(&aBuf[12]);
- memcpy(&pWal->hdr.aSalt, &aBuf[16], 8);
-+ *ppPage = pWal->apWiData[iPage];
-+ assert( iPage==0 || *ppPage || rc!=SQLITE_OK );
-+ return rc;
-+}
-
+-
- /* Verify that the WAL header checksum is correct */
- walChecksumBytes(pWal->hdr.bigEndCksum==SQLITE_BIGENDIAN,
- aBuf, WAL_HDRSIZE-2*4, 0, pWal->hdr.aFrameCksum
@@ -65502,14 +4579,7 @@
- ){
- goto finished;
- }
-+/*
-+** Return a pointer to the WalCkptInfo structure in the wal-index.
-+*/
-+static volatile WalCkptInfo *walCkptInfo(Wal *pWal){
-+ assert( pWal->nWiData>0 && pWal->apWiData[0] );
-+ return (volatile WalCkptInfo*)&(pWal->apWiData[0][sizeof(WalIndexHdr)/2]);
-+}
-
+-
- /* Verify that the version number on the WAL format is one that
- ** are able to understand */
- version = sqlite3Get4byte(&aBuf[4]);
@@ -65517,14 +4587,7 @@
- rc = SQLITE_CANTOPEN_BKPT;
- goto finished;
- }
-+/*
-+** Return a pointer to the WalIndexHdr structure in the wal-index.
-+*/
-+static volatile WalIndexHdr *walIndexHdr(Wal *pWal){
-+ assert( pWal->nWiData>0 && pWal->apWiData[0] );
-+ return (volatile WalIndexHdr*)pWal->apWiData[0];
-+}
-
+-
- /* Malloc a buffer to read frames into. */
- szFrame = szPage + WAL_FRAME_HDRSIZE;
- aFrame = (u8 *)sqlite3_malloc(szFrame);
@@ -65533,43 +4596,13 @@
- goto recovery_error;
- }
- aData = &aFrame[WAL_FRAME_HDRSIZE];
-+/*
-+** The argument to this macro must be of type u32. On a little-endian
-+** architecture, it returns the u32 value that results from interpreting
-+** the 4 bytes as a big-endian value. On a big-endian architecture, it
-+** returns the value that would be produced by intepreting the 4 bytes
-+** of the input value as a little-endian integer.
-+*/
-+#define BYTESWAP32(x) ( \
-+ (((x)&0x000000FF)<<24) + (((x)&0x0000FF00)<<8) \
-+ + (((x)&0x00FF0000)>>8) + (((x)&0xFF000000)>>24) \
-+)
-
+-
- /* Read all frames from the log file. */
- iFrame = 0;
- for(iOffset=WAL_HDRSIZE; (iOffset+szFrame)<=nSize; iOffset+=szFrame){
- u32 pgno; /* Database page number for frame */
- u32 nTruncate; /* dbsize field from frame header */
-+/*
-+** Generate or extend an 8 byte checksum based on the data in
-+** array aByte[] and the initial values of aIn[0] and aIn[1] (or
-+** initial values of 0 and 0 if aIn==NULL).
-+**
-+** The checksum is written back into aOut[] before returning.
-+**
-+** nByte must be a positive multiple of 8.
-+*/
-+static void walChecksumBytes(
-+ int nativeCksum, /* True for native byte-order, false for non-native */
-+ u8 *a, /* Content to be checksummed */
-+ int nByte, /* Bytes of content in a[]. Must be a multiple of 8. */
-+ const u32 *aIn, /* Initial checksum value input */
-+ u32 *aOut /* OUT: Final checksum value output */
-+){
-+ u32 s1, s2;
-+ u32 *aData = (u32 *)a;
-+ u32 *aEnd = (u32 *)&a[nByte];
-
+-
- /* Read and decode the next log frame. */
- iFrame++;
- rc = sqlite3OsRead(pWal->pWalFd, aFrame, szFrame, iOffset);
@@ -65578,13 +4611,7 @@
- if( !isValid ) break;
- rc = walIndexAppend(pWal, iFrame, pgno);
- if( rc!=SQLITE_OK ) break;
-+ if( aIn ){
-+ s1 = aIn[0];
-+ s2 = aIn[1];
-+ }else{
-+ s1 = s2 = 0;
-+ }
-
+-
- /* If nTruncate is non-zero, this is a commit record. */
- if( nTruncate ){
- pWal->hdr.mxFrame = iFrame;
@@ -66505,6 +5532,12 @@
+ u32 magic; /* Magic value read from WAL header */
+ u32 version; /* Magic value read from WAL header */
+ int isValid; /* True if this frame is valid */
++
++ /* Read in the WAL header. */
++ rc = sqlite3OsRead(pWal->pWalFd, aBuf, WAL_HDRSIZE, 0);
++ if( rc!=SQLITE_OK ){
++ goto recovery_error;
++ }
- /* Compute in mxSafeFrame the index of the last frame of the WAL that is
- ** safe to write into the database. Frames beyond mxSafeFrame might
@@ -66527,18 +5560,6 @@
- }else{
- goto walcheckpoint_out;
- }
-+ /* Read in the WAL header. */
-+ rc = sqlite3OsRead(pWal->pWalFd, aBuf, WAL_HDRSIZE, 0);
-+ if( rc!=SQLITE_OK ){
-+ goto recovery_error;
- }
-- }
-
-- if( pInfo->nBackfill<mxSafeFrame
-- && (rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_READ_LOCK(0), 1))==SQLITE_OK
-- ){
-- i64 nSize; /* Current size of database file */
-- u32 nBackfill = pInfo->nBackfill;
+ /* If the database page size is not a power of two, or is greater than
+ ** SQLITE_MAX_PAGE_SIZE, conclude that the WAL file contains no valid
+ ** data. Similarly, if the 'magic' value is invalid, ignore the whole
@@ -66552,15 +5573,18 @@
+ || szPage<512
+ ){
+ goto finished;
-+ }
+ }
+- }
+ pWal->hdr.bigEndCksum = (u8)(magic&0x00000001);
+ pWal->szPage = szPage;
+ pWal->nCkpt = sqlite3Get4byte(&aBuf[12]);
+ memcpy(&pWal->hdr.aSalt, &aBuf[16], 8);
-- /* Sync the WAL to disk */
-- if( sync_flags ){
-- rc = sqlite3OsSync(pWal->pWalFd, sync_flags);
+- if( pInfo->nBackfill<mxSafeFrame
+- && (rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_READ_LOCK(0), 1))==SQLITE_OK
+- ){
+- i64 nSize; /* Current size of database file */
+- u32 nBackfill = pInfo->nBackfill;
+ /* Verify that the WAL header checksum is correct */
+ walChecksumBytes(pWal->hdr.bigEndCksum==SQLITE_BIGENDIAN,
+ aBuf, WAL_HDRSIZE-2*4, 0, pWal->hdr.aFrameCksum
@@ -66569,6 +5593,17 @@
+ || pWal->hdr.aFrameCksum[1]!=sqlite3Get4byte(&aBuf[28])
+ ){
+ goto finished;
++ }
+
+- /* Sync the WAL to disk */
+- if( sync_flags ){
+- rc = sqlite3OsSync(pWal->pWalFd, sync_flags);
++ /* Verify that the version number on the WAL format is one that
++ ** are able to understand */
++ version = sqlite3Get4byte(&aBuf[4]);
++ if( version!=WAL_MAX_VERSION ){
++ rc = SQLITE_CANTOPEN_BKPT;
++ goto finished;
}
- /* If the database may grow as a result of this checkpoint, hint
@@ -66580,14 +5615,6 @@
- if( rc==SQLITE_OK && nSize<nReq ){
- sqlite3OsFileControlHint(pWal->pDbFd, SQLITE_FCNTL_SIZE_HINT, &nReq);
- }
-+ /* Verify that the version number on the WAL format is one that
-+ ** are able to understand */
-+ version = sqlite3Get4byte(&aBuf[4]);
-+ if( version!=WAL_MAX_VERSION ){
-+ rc = SQLITE_CANTOPEN_BKPT;
-+ goto finished;
-+ }
-+
+ /* Malloc a buffer to read frames into. */
+ szFrame = szPage + WAL_FRAME_HDRSIZE;
+ aFrame = (u8 *)sqlite3_malloc(szFrame);
@@ -67759,7 +6786,7 @@
- if( memcmp(&pWal->hdr, (void *)walIndexHdr(pWal), sizeof(WalIndexHdr))!=0 ){
- walUnlockExclusive(pWal, WAL_WRITE_LOCK, 1);
- pWal->writeLock = 0;
-- rc = SQLITE_BUSY;
+- rc = SQLITE_BUSY_SNAPSHOT;
+ mxSafeFrame = pWal->hdr.mxFrame;
+ mxPage = pWal->hdr.nPage;
+ for(i=1; i<WAL_NREADER; i++){
@@ -68078,19 +7105,13 @@
/*
-** Write out a single frame of the WAL
-+** Close a connection to a log file.
- */
+-*/
-static int walWriteOneFrame(
- WalWriter *p, /* Where to write the frame */
- PgHdr *pPage, /* The page of the frame to be written */
- int nTruncate, /* The commit flag. Usually 0. >0 for commit */
- sqlite3_int64 iOffset /* Byte offset at which to write */
-+SQLITE_PRIVATE int sqlite3WalClose(
-+ Wal *pWal, /* Wal to close */
-+ int sync_flags, /* Flags to pass to OsSync() (or 0) */
-+ int nBuf,
-+ u8 *zBuf /* Buffer of at least nBuf bytes */
- ){
+-){
- int rc; /* Result code from subfunctions */
- void *pData; /* Data actually written */
- u8 aFrame[WAL_FRAME_HDRSIZE]; /* Buffer to assemble frame-header in */
@@ -68104,10 +7125,45 @@
- if( rc ) return rc;
- /* Write the page data */
- rc = walWriteToLog(p, pData, p->szPage, iOffset+sizeof(aFrame));
+- return rc;
+-}
+-
+-/*
+-** Write a set of frames to the log. The caller must hold the write-lock
+-** on the log file (obtained using sqlite3WalBeginWriteTransaction()).
++** Close a connection to a log file.
+ */
+-SQLITE_PRIVATE int sqlite3WalFrames(
+- Wal *pWal, /* Wal handle to write to */
+- int szPage, /* Database page-size in bytes */
+- PgHdr *pList, /* List of dirty pages to write */
+- Pgno nTruncate, /* Database size after this commit */
+- int isCommit, /* True if this is a commit */
+- int sync_flags /* Flags to pass to OsSync() (or 0) */
++SQLITE_PRIVATE int sqlite3WalClose(
++ Wal *pWal, /* Wal to close */
++ int sync_flags, /* Flags to pass to OsSync() (or 0) */
++ int nBuf,
++ u8 *zBuf /* Buffer of at least nBuf bytes */
+ ){
+- int rc; /* Used to catch return codes */
+- u32 iFrame; /* Next frame address */
+- PgHdr *p; /* Iterator to run through pList with. */
+- PgHdr *pLast = 0; /* Last frame in list */
+- int nExtra = 0; /* Number of extra copies of last page */
+- int szFrame; /* The size of a single frame */
+- i64 iOffset; /* Next byte to write in WAL file */
+- WalWriter w; /* The writer */
+-
+- assert( pList );
+- assert( pWal->writeLock );
+ int rc = SQLITE_OK;
+ if( pWal ){
+ int isDelete = 0; /* True to unlink wal and wal-index files */
-+
+
+- /* If this frame set completes a transaction, then nTruncate>0. If
+- ** nTruncate==0 then this frame set does not complete the transaction. */
+- assert( (isCommit!=0)==(nTruncate!=0) );
+ /* If an EXCLUSIVE lock can be obtained on the database file (using the
+ ** ordinary, rollback-mode locking methods, this guarantees that the
+ ** connection associated with this log file is the only connection to
@@ -68145,7 +7201,11 @@
+ }
+ }
+ }
-+
+
+-#if defined(SQLITE_TEST) && defined(SQLITE_DEBUG)
+- { int cnt; for(cnt=0, p=pList; p; p=p->pDirty, cnt++){}
+- WALTRACE(("WAL%p: frame write begin. %d frames. mxFrame=%d. %s\n",
+- pWal, cnt, pWal->hdr.mxFrame, isCommit ? "Commit" : "Spill"));
+ walIndexClose(pWal, isDelete);
+ sqlite3OsClose(pWal->pWalFd);
+ if( isDelete ){
@@ -68156,13 +7216,17 @@
+ WALTRACE(("WAL%p: closed\n", pWal));
+ sqlite3_free((void *)pWal->apWiData);
+ sqlite3_free(pWal);
-+ }
- return rc;
- }
+ }
+-#endif
++ return rc;
++}
--/*
--** Write a set of frames to the log. The caller must hold the write-lock
--** on the log file (obtained using sqlite3WalBeginWriteTransaction()).
+- /* See if it is possible to write these frames into the start of the
+- ** log file, instead of appending to it at pWal->hdr.mxFrame.
+- */
+- if( SQLITE_OK!=(rc = walRestartLog(pWal)) ){
+- return rc;
+- }
+/*
+** Try to read the wal-index header. Return 0 on success and 1 if
+** there is a problem.
@@ -68179,73 +7243,12 @@
+**
+** If the checksum cannot be verified return non-zero. If the header
+** is read successfully and the checksum verified, return zero.
- */
--SQLITE_PRIVATE int sqlite3WalFrames(
-- Wal *pWal, /* Wal handle to write to */
-- int szPage, /* Database page-size in bytes */
-- PgHdr *pList, /* List of dirty pages to write */
-- Pgno nTruncate, /* Database size after this commit */
-- int isCommit, /* True if this is a commit */
-- int sync_flags /* Flags to pass to OsSync() (or 0) */
--){
-- int rc; /* Used to catch return codes */
-- u32 iFrame; /* Next frame address */
-- PgHdr *p; /* Iterator to run through pList with. */
-- PgHdr *pLast = 0; /* Last frame in list */
-- int nExtra = 0; /* Number of extra copies of last page */
-- int szFrame; /* The size of a single frame */
-- i64 iOffset; /* Next byte to write in WAL file */
-- WalWriter w; /* The writer */
++*/
+static int walIndexTryHdr(Wal *pWal, int *pChanged){
+ u32 aCksum[2]; /* Checksum on the header content */
+ WalIndexHdr h1, h2; /* Two copies of the header content */
+ WalIndexHdr volatile *aHdr; /* Header in shared memory */
-- assert( pList );
-- assert( pWal->writeLock );
-+ /* The first page of the wal-index must be mapped at this point. */
-+ assert( pWal->nWiData>0 && pWal->apWiData[0] );
-
-- /* If this frame set completes a transaction, then nTruncate>0. If
-- ** nTruncate==0 then this frame set does not complete the transaction. */
-- assert( (isCommit!=0)==(nTruncate!=0) );
-+ /* Read the header. This might happen concurrently with a write to the
-+ ** same area of shared memory on a different CPU in a SMP,
-+ ** meaning it is possible that an inconsistent snapshot is read
-+ ** from the file. If this happens, return non-zero.
-+ **
-+ ** There are two copies of the header at the beginning of the wal-index.
-+ ** When reading, read [0] first then [1]. Writes are in the reverse order.
-+ ** Memory barriers are used to prevent the compiler or the hardware from
-+ ** reordering the reads and writes.
-+ */
-+ aHdr = walIndexHdr(pWal);
-+ memcpy(&h1, (void *)&aHdr[0], sizeof(h1));
-+ walShmBarrier(pWal);
-+ memcpy(&h2, (void *)&aHdr[1], sizeof(h2));
-
--#if defined(SQLITE_TEST) && defined(SQLITE_DEBUG)
-- { int cnt; for(cnt=0, p=pList; p; p=p->pDirty, cnt++){}
-- WALTRACE(("WAL%p: frame write begin. %d frames. mxFrame=%d. %s\n",
-- pWal, cnt, pWal->hdr.mxFrame, isCommit ? "Commit" : "Spill"));
-+ if( memcmp(&h1, &h2, sizeof(h1))!=0 ){
-+ return 1; /* Dirty read */
-+ }
-+ if( h1.isInit==0 ){
-+ return 1; /* Malformed header - probably all zeros */
- }
--#endif
--
-- /* See if it is possible to write these frames into the start of the
-- ** log file, instead of appending to it at pWal->hdr.mxFrame.
-- */
-- if( SQLITE_OK!=(rc = walRestartLog(pWal)) ){
-- return rc;
-+ walChecksumBytes(1, (u8*)&h1, sizeof(h1)-sizeof(h1.aCksum), 0, aCksum);
-+ if( aCksum[0]!=h1.aCksum[0] || aCksum[1]!=h1.aCksum[1] ){
-+ return 1; /* Checksum does not match */
- }
-
- /* If this is the first frame written into the log, write the WAL
- ** header to the start of the WAL file. See comments at the top of
- ** this source file for a description of the WAL header format.
@@ -68254,7 +7257,9 @@
- if( iFrame==0 ){
- u8 aWalHdr[WAL_HDRSIZE]; /* Buffer to assemble wal-header in */
- u32 aCksum[2]; /* Checksum for wal-header */
--
++ /* The first page of the wal-index must be mapped at this point. */
++ assert( pWal->nWiData>0 && pWal->apWiData[0] );
+
- sqlite3Put4byte(&aWalHdr[0], (WAL_MAGIC | SQLITE_BIGENDIAN));
- sqlite3Put4byte(&aWalHdr[4], WAL_MAX_VERSION);
- sqlite3Put4byte(&aWalHdr[8], szPage);
@@ -68270,13 +7275,37 @@
- pWal->hdr.aFrameCksum[0] = aCksum[0];
- pWal->hdr.aFrameCksum[1] = aCksum[1];
- pWal->truncateOnCommit = 1;
--
++ /* Read the header. This might happen concurrently with a write to the
++ ** same area of shared memory on a different CPU in a SMP,
++ ** meaning it is possible that an inconsistent snapshot is read
++ ** from the file. If this happens, return non-zero.
++ **
++ ** There are two copies of the header at the beginning of the wal-index.
++ ** When reading, read [0] first then [1]. Writes are in the reverse order.
++ ** Memory barriers are used to prevent the compiler or the hardware from
++ ** reordering the reads and writes.
++ */
++ aHdr = walIndexHdr(pWal);
++ memcpy(&h1, (void *)&aHdr[0], sizeof(h1));
++ walShmBarrier(pWal);
++ memcpy(&h2, (void *)&aHdr[1], sizeof(h2));
+
- rc = sqlite3OsWrite(pWal->pWalFd, aWalHdr, sizeof(aWalHdr), 0);
- WALTRACE(("WAL%p: wal-header write %s\n", pWal, rc ? "failed" : "ok"));
- if( rc!=SQLITE_OK ){
- return rc;
- }
--
++ if( memcmp(&h1, &h2, sizeof(h1))!=0 ){
++ return 1; /* Dirty read */
++ }
++ if( h1.isInit==0 ){
++ return 1; /* Malformed header - probably all zeros */
++ }
++ walChecksumBytes(1, (u8*)&h1, sizeof(h1)-sizeof(h1.aCksum), 0, aCksum);
++ if( aCksum[0]!=h1.aCksum[0] || aCksum[1]!=h1.aCksum[1] ){
++ return 1; /* Checksum does not match */
++ }
+
- /* Sync the header (unless SQLITE_IOCAP_SEQUENTIAL is true or unless
- ** all syncing is turned off by PRAGMA synchronous=OFF). Otherwise
- ** an out-of-order write following a WAL restart could result in
@@ -69280,7 +8309,7 @@
+ if( memcmp(&pWal->hdr, (void *)walIndexHdr(pWal), sizeof(WalIndexHdr))!=0 ){
+ walUnlockExclusive(pWal, WAL_WRITE_LOCK, 1);
+ pWal->writeLock = 0;
-+ rc = SQLITE_BUSY;
++ rc = SQLITE_BUSY_SNAPSHOT;
+ }
+
+ return rc;
@@ -70059,14 +9088,19 @@
-/*
-** Potential values for BtCursor.eState.
-**
--** CURSOR_VALID:
--** Cursor points to a valid entry. getPayload() etc. may be called.
--**
-** CURSOR_INVALID:
-** Cursor does not point to a valid entry. This can happen (for example)
-** because the table is empty or because BtreeCursorFirst() has not been
-** called.
-**
+-** CURSOR_VALID:
+-** Cursor points to a valid entry. getPayload() etc. may be called.
+-**
+-** CURSOR_SKIPNEXT:
+-** Cursor is valid except that the Cursor.skipNext field is non-zero
+-** indicating that the next sqlite3BtreeNext() or sqlite3BtreePrevious()
+-** operation should be a no-op.
+-**
-** CURSOR_REQUIRESEEK:
-** The table that this cursor was opened on still exists, but has been
-** modified since the cursor was last used. The cursor position is saved
@@ -70083,8 +9117,9 @@
-*/
-#define CURSOR_INVALID 0
-#define CURSOR_VALID 1
--#define CURSOR_REQUIRESEEK 2
--#define CURSOR_FAULT 3
+-#define CURSOR_SKIPNEXT 2
+-#define CURSOR_REQUIRESEEK 3
+-#define CURSOR_FAULT 4
+ /* Copy data from the log to the database file. */
+ if( rc==SQLITE_OK ){
+ if( pWal->hdr.mxFrame && walPagesize(pWal)!=nBuf ){
@@ -70334,7 +9369,7 @@
#ifndef SQLITE_OMIT_SHARED_CACHE
#if SQLITE_THREADSAFE
-@@ -88696,10 +91098,24 @@
+@@ -88995,10 +91735,24 @@
*/
SQLITE_PRIVATE void sqlite3RegisterBuiltinFunctions(sqlite3 *db){
int rc = sqlite3_overload_function(db, "MATCH", 2);
@@ -70359,34 +9394,34 @@
}
/*
-@@ -93695,6 +96111,12 @@
+@@ -94082,6 +96836,12 @@
sqlite3 *db = pParse->db; /* The database connection */
Db *pDb; /* The specific database being pragmaed */
Vdbe *v = sqlite3GetVdbe(pParse); /* Prepared statement */
+/* BEGIN SQLCIPHER */
+#ifdef SQLITE_HAS_CODEC
-+ extern int codec_pragma(sqlite3*, int, Parse *, const char *, const char *);
++ extern int sqlcipher_codec_pragma(sqlite3*, int, Parse *, const char *, const char *);
+#endif
+/* END SQLCIPHER */
+
if( v==0 ) return;
sqlite3VdbeRunOnlyOnce(v);
-@@ -93755,6 +96177,13 @@
+@@ -94142,6 +96902,13 @@
pParse->rc = rc;
}else
+/* BEGIN SQLCIPHER */
+#ifdef SQLITE_HAS_CODEC
-+ if(codec_pragma(db, iDb, pParse, zLeft, zRight)) {
-+ /* codec_pragma executes internal */
++ if(sqlcipher_codec_pragma(db, iDb, pParse, zLeft, zRight)) {
++ /* sqlcipher_codec_pragma executes internal */
+ }else
+ #endif
+/* END SQLCIPHER */
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && !defined(SQLITE_OMIT_DEPRECATED)
/*
-@@ -94348,60 +96777,6 @@
+@@ -94739,60 +97506,6 @@
#ifndef SQLITE_OMIT_SCHEMA_PRAGMAS
/*
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]