summaryrefslogtreecommitdiff
path: root/dist/sqlite3.c
diff options
context:
space:
mode:
Diffstat (limited to 'dist/sqlite3.c')
-rw-r--r--dist/sqlite3.c21108
1 files changed, 7150 insertions, 13958 deletions
diff --git a/dist/sqlite3.c b/dist/sqlite3.c
index c702520..cc77c23 100644
--- a/dist/sqlite3.c
+++ b/dist/sqlite3.c
@@ -1,6 +1,6 @@
/******************************************************************************
** This file is an amalgamation of many separate C source files from SQLite
-** version 3.7.0. By combining all the individual C code files into this
+** version 3.6.22. By combining all the individual C code files into this
** single large file, the entire code can be compiled as a one translation
** unit. This allows many compilers to do optimizations that would not be
** possible if the files were compiled separately. Performance improvements
@@ -9,7 +9,7 @@
**
** This file is all you need to compile SQLite. To use SQLite in other
** programs, you need this file and the "sqlite3.h" header file that defines
-** the programming interface to the SQLite library. (If you do not have
+** the programming interface to the SQLite library. (If you do not have
** the "sqlite3.h" header file at hand, you will find a copy embedded within
** the text of this file. Search for "Begin file sqlite3.h" to find the start
** of the embedded sqlite3.h header file.) Additional code files may be needed
@@ -91,7 +91,7 @@
** May you share freely, never taking more than you give.
**
*************************************************************************
-**
+**
** This file defines various limits of what SQLite can process.
*/
@@ -139,9 +139,9 @@
#endif
/*
-** The maximum depth of an expression tree. This is limited to
-** some extent by SQLITE_MAX_SQL_LENGTH. But sometime you might
-** want to place more severe limits on the complexity of an
+** The maximum depth of an expression tree. This is limited to
+** some extent by SQLITE_MAX_SQL_LENGTH. But sometime you might
+** want to place more severe limits on the complexity of an
** expression.
**
** A value of 0 used to mean that the limit was not enforced.
@@ -191,14 +191,6 @@
#endif
/*
-** The default number of frames to accumulate in the log file before
-** checkpointing the database in WAL mode.
-*/
-#ifndef SQLITE_DEFAULT_WAL_AUTOCHECKPOINT
-# define SQLITE_DEFAULT_WAL_AUTOCHECKPOINT 1000
-#endif
-
-/*
** The maximum number of attached databases. This must be between 0
** and 30. The upper bound on 30 is because a 32-bit integer bitmap
** is used internally to track attached databases.
@@ -221,8 +213,8 @@
**
** If this limit is changed, then the compiled library is technically
** incompatible with an SQLite library compiled with a different limit. If
-** a process operating on a database with a page-size of 65536 bytes
-** crashes, then an instance of SQLite compiled with the default page-size
+** a process operating on a database with a page-size of 65536 bytes
+** crashes, then an instance of SQLite compiled with the default page-size
** limit will not be able to rollback the aborted transaction. This could
** lead to database corruption.
*/
@@ -281,7 +273,7 @@
** Maximum depth of recursion for triggers.
**
** A value of 1 means that a trigger program will not be able to itself
-** fire any triggers. A value of 0 means that no trigger programs at all
+** fire any triggers. A value of 0 means that no trigger programs at all
** may be executed.
*/
#ifndef SQLITE_MAX_TRIGGER_DEPTH
@@ -315,43 +307,41 @@
#include <inttypes.h>
#endif
-/*
-** The number of samples of an index that SQLite takes in order to
-** construct a histogram of the table content when running ANALYZE
-** and with SQLITE_ENABLE_STAT2
-*/
#define SQLITE_INDEX_SAMPLES 10
/*
-** The following macros are used to cast pointers to integers and
-** integers to pointers. The way you do this varies from one compiler
-** to the next, so we have developed the following set of #if statements
-** to generate appropriate macros for a wide range of compilers.
+** This macro is used to "hide" some ugliness in casting an int
+** value to a ptr value under the MSVC 64-bit compiler. Casting
+** non 64-bit values to ptr types results in a "hard" error with
+** the MSVC 64-bit compiler which this attempts to avoid.
+**
+** A simple compiler pragma or casting sequence could not be found
+** to correct this in all situations, so this macro was introduced.
**
-** The correct "ANSI" way to do this is to use the intptr_t type.
-** Unfortunately, that typedef is not available on all compilers, or
-** if it is available, it requires an #include of specific headers
-** that vary from one machine to the next.
+** It could be argued that the intptr_t type could be used in this
+** case, but that type is not available on all compilers, or
+** requires the #include of specific headers which differs between
+** platforms.
**
** Ticket #3860: The llvm-gcc-4.2 compiler from Apple chokes on
** the ((void*)&((char*)0)[X]) construct. But MSVC chokes on ((void*)(X)).
** So we have to define the macros in different ways depending on the
** compiler.
*/
-#if defined(__PTRDIFF_TYPE__) /* This case should work for GCC */
-# define SQLITE_INT_TO_PTR(X) ((void*)(__PTRDIFF_TYPE__)(X))
-# define SQLITE_PTR_TO_INT(X) ((int)(__PTRDIFF_TYPE__)(X))
-#elif !defined(__GNUC__) /* Works for compilers other than LLVM */
-# define SQLITE_INT_TO_PTR(X) ((void*)&((char*)0)[X])
-# define SQLITE_PTR_TO_INT(X) ((int)(((char*)X)-(char*)0))
-#elif defined(HAVE_STDINT_H) /* Use this case if we have ANSI headers */
-# define SQLITE_INT_TO_PTR(X) ((void*)(intptr_t)(X))
-# define SQLITE_PTR_TO_INT(X) ((int)(intptr_t)(X))
-#else /* Generates a warning - but it always works */
-# define SQLITE_INT_TO_PTR(X) ((void*)(X))
-# define SQLITE_PTR_TO_INT(X) ((int)(X))
+#if defined(__GNUC__)
+# if defined(HAVE_STDINT_H)
+# define SQLITE_INT_TO_PTR(X) ((void*)(intptr_t)(X))
+# define SQLITE_PTR_TO_INT(X) ((int)(intptr_t)(X))
+# else
+# define SQLITE_INT_TO_PTR(X) ((void*)(X))
+# define SQLITE_PTR_TO_INT(X) ((int)(X))
+# endif
+#else
+# define SQLITE_INT_TO_PTR(X) ((void*)&((char*)0)[X])
+# define SQLITE_PTR_TO_INT(X) ((int)(((char*)X)-(char*)0))
#endif
+
/*
** The SQLITE_THREADSAFE macro must be defined as either 0 or 1.
** Older versions of SQLite used an optional THREADSAFE macro.
@@ -367,7 +357,7 @@
/*
** The SQLITE_DEFAULT_MEMSTATUS macro must be defined as either 0 or 1.
-** It determines whether or not the features related to
+** It determines whether or not the features related to
** SQLITE_CONFIG_MEMSTATUS are available by default or not. This value can
** be overridden at runtime using the sqlite3_config() API.
*/
@@ -381,18 +371,23 @@
**
** SQLITE_SYSTEM_MALLOC // Use normal system malloc()
** SQLITE_MEMDEBUG // Debugging version of system malloc()
-**
-** (Historical note: There used to be several other options, but we've
-** pared it down to just these two.)
+** SQLITE_MEMORY_SIZE // internal allocator #1
+** SQLITE_MMAP_HEAP_SIZE // internal mmap() allocator
+** SQLITE_POW2_MEMORY_SIZE // internal power-of-two allocator
**
** If none of the above are defined, then set SQLITE_SYSTEM_MALLOC as
** the default.
*/
-#if defined(SQLITE_SYSTEM_MALLOC)+defined(SQLITE_MEMDEBUG)>1
+#if defined(SQLITE_SYSTEM_MALLOC)+defined(SQLITE_MEMDEBUG)+\
+ defined(SQLITE_MEMORY_SIZE)+defined(SQLITE_MMAP_HEAP_SIZE)+\
+ defined(SQLITE_POW2_MEMORY_SIZE)>1
# error "At most one of the following compile-time configuration options\
- is allows: SQLITE_SYSTEM_MALLOC, SQLITE_MEMDEBUG"
+ is allows: SQLITE_SYSTEM_MALLOC, SQLITE_MEMDEBUG, SQLITE_MEMORY_SIZE,\
+ SQLITE_MMAP_HEAP_SIZE, SQLITE_POW2_MEMORY_SIZE"
#endif
-#if defined(SQLITE_SYSTEM_MALLOC)+defined(SQLITE_MEMDEBUG)==0
+#if defined(SQLITE_SYSTEM_MALLOC)+defined(SQLITE_MEMDEBUG)+\
+ defined(SQLITE_MEMORY_SIZE)+defined(SQLITE_MMAP_HEAP_SIZE)+\
+ defined(SQLITE_POW2_MEMORY_SIZE)==0
# define SQLITE_SYSTEM_MALLOC 1
#endif
@@ -435,12 +430,12 @@
** option is set. Thus NDEBUG becomes an opt-in rather than an opt-out
** feature.
*/
-#if !defined(NDEBUG) && !defined(SQLITE_DEBUG)
+#if !defined(NDEBUG) && !defined(SQLITE_DEBUG)
# define NDEBUG 1
#endif
/*
-** The testcase() macro is used to aid in coverage testing. When
+** The testcase() macro is used to aid in coverage testing. When
** doing coverage testing, the condition inside the argument to
** testcase() must be evaluated both true and false in order to
** get full branch coverage. The testcase() macro is inserted
@@ -486,7 +481,7 @@ SQLITE_PRIVATE void sqlite3Coverage(int);
#endif
/*
-** The ALWAYS and NEVER macros surround boolean expressions which
+** The ALWAYS and NEVER macros surround boolean expressions which
** are intended to always be true or false, respectively. Such
** expressions could be omitted from the code completely. But they
** are included in a few cases in order to enhance the resilience
@@ -636,13 +631,13 @@ extern "C" {
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
-#define SQLITE_VERSION "3.7.0"
-#define SQLITE_VERSION_NUMBER 3007000
-#define SQLITE_SOURCE_ID "2010-05-24 12:34:15 51fd38152b92db637d1d346fca35ec2d3e4d4f57"
+#define SQLITE_VERSION "3.6.22"
+#define SQLITE_VERSION_NUMBER 3006022
+#define SQLITE_SOURCE_ID "2010-03-22 23:55:10 82dd61fccff3e4c77e060e5734cd4b4e2eeb7c32"
/*
** CAPI3REF: Run-Time Library Version Numbers
-** KEYWORDS: sqlite3_version, sqlite3_sourceid
+** KEYWORDS: sqlite3_version
**
** These interfaces provide the same information as the [SQLITE_VERSION],
** [SQLITE_VERSION_NUMBER], and [SQLITE_SOURCE_ID] C preprocessor macros
@@ -664,9 +659,9 @@ extern "C" {
** function is provided for use in DLLs since DLL users usually do not have
** direct access to string constants within the DLL. ^The
** sqlite3_libversion_number() function returns an integer equal to
-** [SQLITE_VERSION_NUMBER]. ^The sqlite3_sourceid() function returns
-** a pointer to a string constant whose value is the same as the
-** [SQLITE_SOURCE_ID] C preprocessor macro.
+** [SQLITE_VERSION_NUMBER]. ^The sqlite3_sourceid() function a pointer
+** to a string constant whose value is the same as the [SQLITE_SOURCE_ID]
+** C preprocessor macro.
**
** See also: [sqlite_version()] and [sqlite_source_id()].
*/
@@ -676,33 +671,6 @@ SQLITE_API const char *sqlite3_sourceid(void);
SQLITE_API int sqlite3_libversion_number(void);
/*
-** CAPI3REF: Run-Time Library Compilation Options Diagnostics
-**
-** ^The sqlite3_compileoption_used() function returns 0 or 1
-** indicating whether the specified option was defined at
-** compile time. ^The SQLITE_ prefix may be omitted from the
-** option name passed to sqlite3_compileoption_used().
-**
-** ^The sqlite3_compileoption_get() function allows interating
-** over the list of options that were defined at compile time by
-** returning the N-th compile time option string. ^If N is out of range,
-** sqlite3_compileoption_get() returns a NULL pointer. ^The SQLITE_
-** prefix is omitted from any strings returned by
-** sqlite3_compileoption_get().
-**
-** ^Support for the diagnostic functions sqlite3_compileoption_used()
-** and sqlite3_compileoption_get() may be omitted by specifing the
-** [SQLITE_OMIT_COMPILEOPTION_DIAGS] option at compile time.
-**
-** See also: SQL functions [sqlite_compileoption_used()] and
-** [sqlite_compileoption_get()] and the [compile_options pragma].
-*/
-#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
-SQLITE_API int sqlite3_compileoption_used(const char *zOptName);
-SQLITE_API const char *sqlite3_compileoption_get(int N);
-#endif
-
-/*
** CAPI3REF: Test To See If The Library Is Threadsafe
**
** ^The sqlite3_threadsafe() function returns zero if and only if
@@ -712,7 +680,7 @@ SQLITE_API const char *sqlite3_compileoption_get(int N);
** SQLite can be compiled with or without mutexes. When
** the [SQLITE_THREADSAFE] C preprocessor macro is 1 or 2, mutexes
** are enabled and SQLite is threadsafe. When the
-** [SQLITE_THREADSAFE] macro is 0,
+** [SQLITE_THREADSAFE] macro is 0,
** the mutexes are omitted. Without the mutexes, it is not safe
** to use SQLite concurrently from more than one thread.
**
@@ -768,7 +736,7 @@ typedef struct sqlite3 sqlite3;
**
** ^The sqlite3_int64 and sqlite_int64 types can store integer values
** between -9223372036854775808 and +9223372036854775807 inclusive. ^The
-** sqlite3_uint64 and sqlite_uint64 types can store integer values
+** sqlite3_uint64 and sqlite_uint64 types can store integer values
** between 0 and +18446744073709551615 inclusive.
*/
#ifdef SQLITE_INT64_TYPE
@@ -813,7 +781,7 @@ typedef sqlite_uint64 sqlite3_uint64;
** pointer or an [sqlite3] object pointer obtained
** from [sqlite3_open()], [sqlite3_open16()], or
** [sqlite3_open_v2()], and not previously closed.
-** ^Calling sqlite3_close() with a NULL pointer argument is a
+** ^Calling sqlite3_close() with a NULL pointer argument is a
** harmless no-op.
*/
SQLITE_API int sqlite3_close(sqlite3 *);
@@ -831,7 +799,7 @@ typedef int (*sqlite3_callback)(void*,int,char**, char**);
** The sqlite3_exec() interface is a convenience wrapper around
** [sqlite3_prepare_v2()], [sqlite3_step()], and [sqlite3_finalize()],
** that allows an application to run multiple statements of SQL
-** without having to use a lot of C code.
+** without having to use a lot of C code.
**
** ^The sqlite3_exec() interface runs zero or more UTF-8 encoded,
** semicolon-separate SQL statements passed into its 2nd argument,
@@ -871,7 +839,7 @@ typedef int (*sqlite3_callback)(void*,int,char**, char**);
** from [sqlite3_column_name()].
**
** ^If the 2nd parameter to sqlite3_exec() is a NULL pointer, a pointer
-** to an empty string, or a pointer that contains only whitespace and/or
+** to an empty string, or a pointer that contains only whitespace and/or
** SQL comments, then no SQL statements are evaluated and the database
** is not changed.
**
@@ -993,7 +961,6 @@ SQLITE_API int sqlite3_exec(
#define SQLITE_OPEN_CREATE 0x00000004 /* Ok for sqlite3_open_v2() */
#define SQLITE_OPEN_DELETEONCLOSE 0x00000008 /* VFS only */
#define SQLITE_OPEN_EXCLUSIVE 0x00000010 /* VFS only */
-#define SQLITE_OPEN_AUTOPROXY 0x00000020 /* VFS only */
#define SQLITE_OPEN_MAIN_DB 0x00000100 /* VFS only */
#define SQLITE_OPEN_TEMP_DB 0x00000200 /* VFS only */
#define SQLITE_OPEN_TRANSIENT_DB 0x00000400 /* VFS only */
@@ -1072,7 +1039,7 @@ SQLITE_API int sqlite3_exec(
/*
** CAPI3REF: OS Interface Open File Handle
**
-** An [sqlite3_file] object represents an open file in the
+** An [sqlite3_file] object represents an open file in the
** [sqlite3_vfs | OS interface layer]. Individual OS interface
** implementations will
** want to subclass this object by appending additional fields
@@ -1094,7 +1061,7 @@ struct sqlite3_file {
** This object defines the methods used to perform various operations
** against the open file represented by the [sqlite3_file] object.
**
-** If the xOpen method sets the sqlite3_file.pMethods element
+** If the xOpen method sets the sqlite3_file.pMethods element
** to a non-NULL pointer, then the sqlite3_io_methods.xClose method
** may be invoked even if the xOpen reported that it failed. The
** only way to prevent a call to xClose following a failed xOpen
@@ -1187,15 +1154,6 @@ struct sqlite3_io_methods {
int (*xFileControl)(sqlite3_file*, int op, void *pArg);
int (*xSectorSize)(sqlite3_file*);
int (*xDeviceCharacteristics)(sqlite3_file*);
- /* Methods above are valid for version 1 */
- int (*xShmOpen)(sqlite3_file*);
- int (*xShmSize)(sqlite3_file*, int reqSize, int *pNewSize);
- int (*xShmGet)(sqlite3_file*, int reqSize, int *pSize, void volatile**);
- int (*xShmRelease)(sqlite3_file*);
- int (*xShmLock)(sqlite3_file*, int desiredLock, int *gotLock);
- void (*xShmBarrier)(sqlite3_file*);
- int (*xShmClose)(sqlite3_file*, int deleteFlag);
- /* Methods above are valid for version 2 */
/* Additional methods may be added in future releases */
};
@@ -1213,19 +1171,11 @@ struct sqlite3_io_methods {
** into an integer that the pArg argument points to. This capability
** is used during testing and only needs to be supported when SQLITE_TEST
** is defined.
-**
-** The [SQLITE_FCNTL_SIZE_HINT] opcode is used by SQLite to give the VFS
-** layer a hint of how large the database file will grow to be during the
-** current transaction. This hint is not guaranteed to be accurate but it
-** is often close. The underlying VFS might choose to preallocate database
-** file space based on this hint in order to help writes to the database
-** file run faster.
*/
#define SQLITE_FCNTL_LOCKSTATE 1
#define SQLITE_GET_LOCKPROXYFILE 2
#define SQLITE_SET_LOCKPROXYFILE 3
#define SQLITE_LAST_ERRNO 4
-#define SQLITE_FCNTL_SIZE_HINT 5
/*
** CAPI3REF: Mutex Handle
@@ -1281,14 +1231,14 @@ typedef struct sqlite3_mutex sqlite3_mutex;
** the [sqlite3_file] can safely store a pointer to the
** filename if it needs to remember the filename for some reason.
** If the zFilename parameter is xOpen is a NULL pointer then xOpen
-** must invent its own temporary name for the file. Whenever the
+** must invent its own temporary name for the file. Whenever the
** xFilename parameter is NULL it will also be the case that the
** flags parameter will include [SQLITE_OPEN_DELETEONCLOSE].
**
** The flags argument to xOpen() includes all bits set in
** the flags argument to [sqlite3_open_v2()]. Or if [sqlite3_open()]
** or [sqlite3_open16()] is used, then flags includes at least
-** [SQLITE_OPEN_READWRITE] | [SQLITE_OPEN_CREATE].
+** [SQLITE_OPEN_READWRITE] | [SQLITE_OPEN_CREATE].
** If xOpen() opens a file read-only then it sets *pOutFlags to
** include [SQLITE_OPEN_READONLY]. Other bits in *pOutFlags may be set.
**
@@ -1328,10 +1278,10 @@ typedef struct sqlite3_mutex sqlite3_mutex;
** The [SQLITE_OPEN_EXCLUSIVE] flag is always used in conjunction
** with the [SQLITE_OPEN_CREATE] flag, which are both directly
** analogous to the O_EXCL and O_CREAT flags of the POSIX open()
-** API. The SQLITE_OPEN_EXCLUSIVE flag, when paired with the
+** API. The SQLITE_OPEN_EXCLUSIVE flag, when paired with the
** SQLITE_OPEN_CREATE, is used to indicate that file should always
** be created, and that it is an error if it already exists.
-** It is <i>not</i> used to indicate the file should be opened
+** It is <i>not</i> used to indicate the file should be opened
** for exclusive access.
**
** At least szOsFile bytes of memory are allocated by SQLite
@@ -1370,7 +1320,7 @@ typedef struct sqlite3_mutex sqlite3_mutex;
*/
typedef struct sqlite3_vfs sqlite3_vfs;
struct sqlite3_vfs {
- int iVersion; /* Structure version number (currently 2) */
+ int iVersion; /* Structure version number */
int szOsFile; /* Size of subclassed sqlite3_file */
int mxPathname; /* Maximum file pathname length */
sqlite3_vfs *pNext; /* Next registered VFS */
@@ -1389,17 +1339,8 @@ struct sqlite3_vfs {
int (*xSleep)(sqlite3_vfs*, int microseconds);
int (*xCurrentTime)(sqlite3_vfs*, double*);
int (*xGetLastError)(sqlite3_vfs*, int, char *);
- /*
- ** The methods above are in version 1 of the sqlite_vfs object
- ** definition. Those that follow are added in version 2 or later
- */
- int (*xRename)(sqlite3_vfs*, const char *zOld, const char *zNew, int dirSync);
- int (*xCurrentTimeInt64)(sqlite3_vfs*, sqlite3_int64*);
- /*
- ** The methods above are in versions 1 and 2 of the sqlite_vfs object.
- ** New fields may be appended in figure versions. The iVersion
- ** value will increment whenever this happens.
- */
+ /* New fields may be appended in figure versions. The iVersion
+ ** value will increment whenever this happens. */
};
/*
@@ -1420,20 +1361,6 @@ struct sqlite3_vfs {
#define SQLITE_ACCESS_READ 2
/*
-** CAPI3REF: Flags for the xShmLock VFS method
-**
-** These integer constants define the various locking states that
-** an sqlite3_shm object can be in.
-*/
-#define SQLITE_SHM_UNLOCK 0
-#define SQLITE_SHM_READ 1
-#define SQLITE_SHM_READ_FULL 2
-#define SQLITE_SHM_WRITE 3
-#define SQLITE_SHM_PENDING 4
-#define SQLITE_SHM_CHECKPOINT 5
-#define SQLITE_SHM_RECOVER 6
-
-/*
** CAPI3REF: Initialize The SQLite Library
**
** ^The sqlite3_initialize() routine initializes the
@@ -1542,10 +1469,11 @@ SQLITE_API int sqlite3_os_end(void);
** ^If the option is unknown or SQLite is unable to set the option
** then this routine returns a non-zero [error code].
*/
-SQLITE_API int sqlite3_config(int, ...);
+SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_config(int, ...);
/*
** CAPI3REF: Configure database connections
+** EXPERIMENTAL
**
** The sqlite3_db_config() interface is used to make configuration
** changes to a [database connection]. The interface is similar to
@@ -1553,7 +1481,7 @@ SQLITE_API int sqlite3_config(int, ...);
** [database connection] (specified in the first argument). The
** sqlite3_db_config() interface should only be used immediately after
** the database connection is created using [sqlite3_open()],
-** [sqlite3_open16()], or [sqlite3_open_v2()].
+** [sqlite3_open16()], or [sqlite3_open_v2()].
**
** The second argument to sqlite3_db_config(D,V,...) is the
** configuration verb - an integer code that indicates what
@@ -1565,10 +1493,11 @@ SQLITE_API int sqlite3_config(int, ...);
** ^Calls to sqlite3_db_config() return SQLITE_OK if and only if
** the call is considered successful.
*/
-SQLITE_API int sqlite3_db_config(sqlite3*, int op, ...);
+SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_db_config(sqlite3*, int op, ...);
/*
** CAPI3REF: Memory Allocation Routines
+** EXPERIMENTAL
**
** An instance of this object defines the interface between SQLite
** and low-level memory allocation routines.
@@ -1576,7 +1505,7 @@ SQLITE_API int sqlite3_db_config(sqlite3*, int op, ...);
** This object is used in only one place in the SQLite interface.
** A pointer to an instance of this object is the argument to
** [sqlite3_config()] when the configuration option is
-** [SQLITE_CONFIG_MALLOC] or [SQLITE_CONFIG_GETMALLOC].
+** [SQLITE_CONFIG_MALLOC] or [SQLITE_CONFIG_GETMALLOC].
** By creating an instance of this object
** and passing it to [sqlite3_config]([SQLITE_CONFIG_MALLOC])
** during configuration, an application can specify an alternative
@@ -1612,7 +1541,7 @@ SQLITE_API int sqlite3_db_config(sqlite3*, int op, ...);
** allocators round up memory allocations at least to the next multiple
** of 8. Some allocators round up to a larger multiple or to a power of 2.
** Every memory allocation request coming in through [sqlite3_malloc()]
-** or [sqlite3_realloc()] first calls xRoundup. If xRoundup returns 0,
+** or [sqlite3_realloc()] first calls xRoundup. If xRoundup returns 0,
** that causes the corresponding memory allocation to fail.
**
** The xInit method initializes the memory allocator. (For example,
@@ -1650,6 +1579,7 @@ struct sqlite3_mem_methods {
/*
** CAPI3REF: Configuration Options
+** EXPERIMENTAL
**
** These constants are the available integer configuration options that
** can be passed as the first argument to the [sqlite3_config()] interface.
@@ -1669,7 +1599,7 @@ struct sqlite3_mem_methods {
** by a single thread. ^If SQLite is compiled with
** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then
** it is not possible to change the [threading mode] from its default
-** value of Single-thread and so [sqlite3_config()] will return
+** value of Single-thread and so [sqlite3_config()] will return
** [SQLITE_ERROR] if called with the SQLITE_CONFIG_SINGLETHREAD
** configuration option.</dd>
**
@@ -1720,9 +1650,9 @@ struct sqlite3_mem_methods {
** tracks memory usage, for example. </dd>
**
** <dt>SQLITE_CONFIG_MEMSTATUS</dt>
-** <dd> ^This option takes single argument of type int, interpreted as a
-** boolean, which enables or disables the collection of memory allocation
-** statistics. ^(When memory allocation statistics are disabled, the
+** <dd> ^This option takes single argument of type int, interpreted as a
+** boolean, which enables or disables the collection of memory allocation
+** statistics. ^(When memory allocation statistics are disabled, the
** following SQLite interfaces become non-operational:
** <ul>
** <li> [sqlite3_memory_used()]
@@ -1748,13 +1678,13 @@ struct sqlite3_mem_methods {
** ^SQLite will use no more than one scratch buffer per thread. So
** N should be set to the expected maximum number of threads. ^SQLite will
** never require a scratch buffer that is more than 6 times the database
-** page size. ^If SQLite needs needs additional scratch memory beyond
-** what is provided by this configuration option, then
+** page size. ^If SQLite needs needs additional scratch memory beyond
+** what is provided by this configuration option, then
** [sqlite3_malloc()] will be used to obtain the memory needed.</dd>
**
** <dt>SQLITE_CONFIG_PAGECACHE</dt>
** <dd> ^This option specifies a static memory buffer that SQLite can use for
-** the database page cache with the default page cache implemenation.
+** the database page cache with the default page cache implemenation.
** This configuration should not be used if an application-define page
** cache implementation is loaded using the SQLITE_CONFIG_PCACHE option.
** There are three arguments to this option: A pointer to 8-byte aligned
@@ -1769,7 +1699,7 @@ struct sqlite3_mem_methods {
** memory needs for the first N pages that it adds to cache. ^If additional
** page cache memory is needed beyond what is provided by this option, then
** SQLite goes to [sqlite3_malloc()] for the additional storage space.
-** ^The implementation might use one or more of the N buffers to hold
+** ^The implementation might use one or more of the N buffers to hold
** memory accounting information. The pointer in the first argument must
** be aligned to an 8-byte boundary or subsequent behavior of SQLite
** will be undefined.</dd>
@@ -1835,24 +1765,6 @@ struct sqlite3_mem_methods {
** [sqlite3_pcache_methods] object. SQLite copies of the current
** page cache implementation into that object.)^ </dd>
**
-** <dt>SQLITE_CONFIG_LOG</dt>
-** <dd> ^The SQLITE_CONFIG_LOG option takes two arguments: a pointer to a
-** function with a call signature of void(*)(void*,int,const char*),
-** and a pointer to void. ^If the function pointer is not NULL, it is
-** invoked by [sqlite3_log()] to process each logging event. ^If the
-** function pointer is NULL, the [sqlite3_log()] interface becomes a no-op.
-** ^The void pointer that is the second argument to SQLITE_CONFIG_LOG is
-** passed through as the first parameter to the application-defined logger
-** function whenever that function is invoked. ^The second parameter to
-** the logger function is a copy of the first parameter to the corresponding
-** [sqlite3_log()] call and is intended to be a [result code] or an
-** [extended result code]. ^The third parameter passed to the logger is
-** log message after formatting via [sqlite3_snprintf()].
-** The SQLite logging interface is not reentrant; the logger function
-** supplied by the application must not invoke any SQLite interface.
-** In a multi-threaded application, the application-defined logger
-** function must be threadsafe. </dd>
-**
** </dl>
*/
#define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */
@@ -1866,14 +1778,15 @@ struct sqlite3_mem_methods {
#define SQLITE_CONFIG_MEMSTATUS 9 /* boolean */
#define SQLITE_CONFIG_MUTEX 10 /* sqlite3_mutex_methods* */
#define SQLITE_CONFIG_GETMUTEX 11 /* sqlite3_mutex_methods* */
-/* previously SQLITE_CONFIG_CHUNKALLOC 12 which is now unused. */
+/* previously SQLITE_CONFIG_CHUNKALLOC 12 which is now unused. */
#define SQLITE_CONFIG_LOOKASIDE 13 /* int int */
#define SQLITE_CONFIG_PCACHE 14 /* sqlite3_pcache_methods* */
#define SQLITE_CONFIG_GETPCACHE 15 /* sqlite3_pcache_methods* */
#define SQLITE_CONFIG_LOG 16 /* xFunc, void* */
/*
-** CAPI3REF: Database Connection Configuration Options
+** CAPI3REF: Configuration Options
+** EXPERIMENTAL
**
** These constants are the available integer configuration options that
** can be passed as the second argument to the [sqlite3_db_config()] interface.
@@ -1887,7 +1800,7 @@ struct sqlite3_mem_methods {
**
** <dl>
** <dt>SQLITE_DBCONFIG_LOOKASIDE</dt>
-** <dd> ^This option takes three additional arguments that determine the
+** <dd> ^This option takes three additional arguments that determine the
** [lookaside memory allocator] configuration for the [database connection].
** ^The first argument (the third parameter to [sqlite3_db_config()] is a
** pointer to an memory buffer to use for lookaside memory.
@@ -1983,7 +1896,7 @@ SQLITE_API sqlite3_int64 sqlite3_last_insert_rowid(sqlite3*);
** mechanisms do not count as direct row changes.)^
**
** A "trigger context" is a scope of execution that begins and
-** ends with the script of a [CREATE TRIGGER | trigger].
+** ends with the script of a [CREATE TRIGGER | trigger].
** Most SQL statements are
** evaluated outside of any trigger. This is the "top level"
** trigger context. If a trigger fires from the top level, a
@@ -2026,7 +1939,7 @@ SQLITE_API int sqlite3_changes(sqlite3*);
** the count does not include changes used to implement [REPLACE] constraints,
** do rollbacks or ABORT processing, or [DROP TABLE] processing. The
** count does not include rows of views that fire an [INSTEAD OF trigger],
-** though if the INSTEAD OF trigger makes changes of its own, those changes
+** though if the INSTEAD OF trigger makes changes of its own, those changes
** are counted.)^
** ^The sqlite3_total_changes() function counts the changes as soon as
** the statement that makes them is completed (when the statement handle
@@ -2066,7 +1979,7 @@ SQLITE_API int sqlite3_total_changes(sqlite3*);
**
** ^The sqlite3_interrupt(D) call is in effect until all currently running
** SQL statements on [database connection] D complete. ^Any new SQL statements
-** that are started after the sqlite3_interrupt() call and before the
+** that are started after the sqlite3_interrupt() call and before the
** running statements reaches zero are interrupted as if they had been
** running prior to the sqlite3_interrupt() call. ^New SQL statements
** that are started after the running statement count reaches zero are
@@ -2101,7 +2014,7 @@ SQLITE_API void sqlite3_interrupt(sqlite3*);
** ^These routines do not parse the SQL statements thus
** will not detect syntactically incorrect SQL.
**
-** ^(If SQLite has not been initialized using [sqlite3_initialize()] prior
+** ^(If SQLite has not been initialized using [sqlite3_initialize()] prior
** to invoking sqlite3_complete16() then sqlite3_initialize() is invoked
** automatically by sqlite3_complete16(). If that initialization fails,
** then the return value from sqlite3_complete16() will be non-zero
@@ -2176,7 +2089,7 @@ SQLITE_API int sqlite3_complete16(const void *sql);
** The busy callback should not take any actions which modify the
** database connection that invoked the busy handler. Any such actions
** result in undefined behavior.
-**
+**
** A busy handler must not close the database connection
** or [prepared statement] that invoked the busy handler.
*/
@@ -2518,7 +2431,7 @@ SQLITE_API void sqlite3_randomness(int N, void *P);
** requested is ok. ^When the callback returns [SQLITE_DENY], the
** [sqlite3_prepare_v2()] or equivalent call that triggered the
** authorizer will fail with an error message explaining that
-** access is denied.
+** access is denied.
**
** ^The first parameter to the authorizer callback is a copy of the third
** parameter to the sqlite3_set_authorizer() interface. ^The second parameter
@@ -2565,7 +2478,7 @@ SQLITE_API void sqlite3_randomness(int N, void *P);
** database connections for the meaning of "modify" in this paragraph.
**
** ^When [sqlite3_prepare_v2()] is used to prepare a statement, the
-** statement might be re-prepared during [sqlite3_step()] due to a
+** statement might be re-prepared during [sqlite3_step()] due to a
** schema change. Hence, the application should ensure that the
** correct authorizer callback remains in place during the [sqlite3_step()].
**
@@ -2649,6 +2562,7 @@ SQLITE_API int sqlite3_set_authorizer(
/*
** CAPI3REF: Tracing And Profiling Functions
+** EXPERIMENTAL
**
** These routines register callback functions that can be used for
** tracing and profiling the execution of SQL statements.
@@ -2666,7 +2580,7 @@ SQLITE_API int sqlite3_set_authorizer(
** the original statement text and an estimate of wall-clock time
** of how long that statement took to run.
*/
-SQLITE_API void *sqlite3_trace(sqlite3*, void(*xTrace)(void*,const char*), void*);
+SQLITE_API SQLITE_EXPERIMENTAL void *sqlite3_trace(sqlite3*, void(*xTrace)(void*,const char*), void*);
SQLITE_API SQLITE_EXPERIMENTAL void *sqlite3_profile(sqlite3*,
void(*xProfile)(void*,const char*,sqlite3_uint64), void*);
@@ -2719,7 +2633,7 @@ SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
** except that it accepts two additional parameters for additional control
** over the new database connection. ^(The flags parameter to
** sqlite3_open_v2() can take one of
-** the following three values, optionally combined with the
+** the following three values, optionally combined with the
** [SQLITE_OPEN_NOMUTEX], [SQLITE_OPEN_FULLMUTEX], [SQLITE_OPEN_SHAREDCACHE],
** and/or [SQLITE_OPEN_PRIVATECACHE] flags:)^
**
@@ -2803,7 +2717,7 @@ SQLITE_API int sqlite3_open_v2(
** associated with a [database connection]. If a prior API call failed
** but the most recent API call succeeded, the return value from
** sqlite3_errcode() is undefined. ^The sqlite3_extended_errcode()
-** interface is the same except that it always returns the
+** interface is the same except that it always returns the
** [extended result code] even when extended result codes are
** disabled.
**
@@ -2870,9 +2784,9 @@ typedef struct sqlite3_stmt sqlite3_stmt;
** new limit for that construct. The function returns the old limit.)^
**
** ^If the new limit is a negative number, the limit is unchanged.
-** ^(For the limit category of SQLITE_LIMIT_XYZ there is a
+** ^(For the limit category of SQLITE_LIMIT_XYZ there is a
** [limits | hard upper bound]
-** set by a compile-time C preprocessor macro named
+** set by a compile-time C preprocessor macro named
** [limits | SQLITE_MAX_XYZ].
** (The "_LIMIT_" in the name is changed to "_MAX_".))^
** ^Attempts to increase a limit above its hard upper bound are
@@ -3030,9 +2944,9 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal);
** <li>
** ^If the value of a [parameter | host parameter] in the WHERE clause might
** change the query plan for a statement, then the statement may be
-** automatically recompiled (as if there had been a schema change) on the first
-** [sqlite3_step()] call following any change to the
-** [sqlite3_bind_text | bindings] of the [parameter].
+** automatically recompiled (as if there had been a schema change) on the first
+** [sqlite3_step()] call following any change to the
+** [sqlite3_bind_text | bindings] of the [parameter].
** </li>
** </ol>
*/
@@ -3094,7 +3008,7 @@ SQLITE_API const char *sqlite3_sql(sqlite3_stmt *pStmt);
** sqlite3_value object but no mutex is held for an unprotected
** sqlite3_value object. If SQLite is compiled to be single-threaded
** (with [SQLITE_THREADSAFE=0] and with [sqlite3_threadsafe()] returning 0)
-** or if SQLite is run in one of reduced mutex modes
+** or if SQLite is run in one of reduced mutex modes
** [SQLITE_CONFIG_SINGLETHREAD] or [SQLITE_CONFIG_MULTITHREAD]
** then there is no distinction between protected and unprotected
** sqlite3_value objects and they can be used interchangeably. However,
@@ -3459,14 +3373,6 @@ SQLITE_API const void *sqlite3_column_decltype16(sqlite3_stmt*,int);
** be the case that the same database connection is being used by two or
** more threads at the same moment in time.
**
-** For all versions of SQLite up to and including 3.6.23.1, it was required
-** after sqlite3_step() returned anything other than [SQLITE_ROW] that
-** [sqlite3_reset()] be called before any subsequent invocation of
-** sqlite3_step(). Failure to invoke [sqlite3_reset()] in this way would
-** result in an [SQLITE_MISUSE] return from sqlite3_step(). But after
-** version 3.6.23.1, sqlite3_step() began calling [sqlite3_reset()]
-** automatically in this circumstance rather than returning [SQLITE_MISUSE].
-**
** <b>Goofy Interface Alert:</b> In the legacy interface, the sqlite3_step()
** API always returns a generic error code, [SQLITE_ERROR], following any
** error other than [SQLITE_BUSY] and [SQLITE_MISUSE]. You must call
@@ -3793,7 +3699,7 @@ SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt);
** nArg parameter is a better match than a function implementation with
** a negative nArg. ^A function where the preferred text encoding
** matches the database encoding is a better
-** match than a function where the encoding is different.
+** match than a function where the encoding is different.
** ^A function where the encoding difference is between UTF16le and UTF16be
** is a closer match than a function where the encoding difference is
** between UTF8 and UTF16.
@@ -3801,7 +3707,7 @@ SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt);
** ^Built-in functions may be overloaded by new application-defined functions.
** ^The first application-defined function with a given name overrides all
** built-in functions in the same [database connection] with the same name.
-** ^Subsequent application-defined functions of the same name only override
+** ^Subsequent application-defined functions of the same name only override
** prior application-defined functions that are an exact match for the
** number of parameters and preferred encoding.
**
@@ -3849,7 +3755,7 @@ SQLITE_API int sqlite3_create_function16(
** DEPRECATED
**
** These functions are [deprecated]. In order to maintain
-** backwards compatibility with older code, these functions continue
+** backwards compatibility with older code, these functions continue
** to be supported. However, new applications should avoid
** the use of these functions. To help encourage people to avoid
** using these functions, we are not going to tell you what they do.
@@ -3927,7 +3833,7 @@ SQLITE_API int sqlite3_value_numeric_type(sqlite3_value*);
** Implementions of aggregate SQL functions use this
** routine to allocate memory for storing their state.
**
-** ^The first time the sqlite3_aggregate_context(C,N) routine is called
+** ^The first time the sqlite3_aggregate_context(C,N) routine is called
** for a particular aggregate function, SQLite
** allocates N of memory, zeroes out that memory, and returns a pointer
** to the new memory. ^On second and subsequent calls to
@@ -3949,7 +3855,7 @@ SQLITE_API int sqlite3_value_numeric_type(sqlite3_value*);
** the same aggregate function instance will not resize the memory
** allocation.)^
**
-** ^SQLite automatically frees the memory allocated by
+** ^SQLite automatically frees the memory allocated by
** sqlite3_aggregate_context() when the aggregate query concludes.
**
** The first parameter must be a copy of the
@@ -4220,24 +4126,24 @@ SQLITE_API void sqlite3_result_zeroblob(sqlite3_context*, int n);
** See also: [sqlite3_collation_needed()] and [sqlite3_collation_needed16()].
*/
SQLITE_API int sqlite3_create_collation(
- sqlite3*,
- const char *zName,
- int eTextRep,
+ sqlite3*,
+ const char *zName,
+ int eTextRep,
void*,
int(*xCompare)(void*,int,const void*,int,const void*)
);
SQLITE_API int sqlite3_create_collation_v2(
- sqlite3*,
- const char *zName,
- int eTextRep,
+ sqlite3*,
+ const char *zName,
+ int eTextRep,
void*,
int(*xCompare)(void*,int,const void*,int,const void*),
void(*xDestroy)(void*)
);
SQLITE_API int sqlite3_create_collation16(
- sqlite3*,
+ sqlite3*,
const void *zName,
- int eTextRep,
+ int eTextRep,
void*,
int(*xCompare)(void*,int,const void*,int,const void*)
);
@@ -4269,17 +4175,16 @@ SQLITE_API int sqlite3_create_collation16(
** [sqlite3_create_collation_v2()].
*/
SQLITE_API int sqlite3_collation_needed(
- sqlite3*,
- void*,
+ sqlite3*,
+ void*,
void(*)(void*,sqlite3*,int eTextRep,const char*)
);
SQLITE_API int sqlite3_collation_needed16(
- sqlite3*,
+ sqlite3*,
void*,
void(*)(void*,sqlite3*,int eTextRep,const void*)
);
-#ifdef SQLITE_HAS_CODEC
/*
** Specify the key for an encrypted database. This routine should be
** called right after sqlite3_open().
@@ -4306,25 +4211,6 @@ SQLITE_API int sqlite3_rekey(
);
/*
-** Specify the activation key for a SEE database. Unless
-** activated, none of the SEE routines will work.
-*/
-SQLITE_API void sqlite3_activate_see(
- const char *zPassPhrase /* Activation phrase */
-);
-#endif
-
-#ifdef SQLITE_ENABLE_CEROD
-/*
-** Specify the activation key for a CEROD database. Unless
-** activated, none of the CEROD routines will work.
-*/
-SQLITE_API void sqlite3_activate_cerod(
- const char *zPassPhrase /* Activation phrase */
-);
-#endif
-
-/*
** CAPI3REF: Suspend Execution For A Short Time
**
** ^The sqlite3_sleep() function causes the current thread to suspend execution
@@ -4362,7 +4248,7 @@ SQLITE_API int sqlite3_sleep(int);
** ^The [temp_store_directory pragma] may modify this variable and cause
** it to point to memory obtained from [sqlite3_malloc]. ^Furthermore,
** the [temp_store_directory pragma] always assumes that any string
-** that this variable points to is held in memory obtained from
+** that this variable points to is held in memory obtained from
** [sqlite3_malloc] and the pragma may attempt to free that memory
** using [sqlite3_free].
** Hence, if this variable is modified directly, either it should be
@@ -4462,6 +4348,8 @@ SQLITE_API sqlite3_stmt *sqlite3_next_stmt(sqlite3 *pDb, sqlite3_stmt *pStmt);
** an error or constraint causes an implicit rollback to occur.
** ^The rollback callback is not invoked if a transaction is
** automatically rolled back because the database connection is closed.
+** ^The rollback callback is not invoked if a transaction is
+** rolled back because a commit callback returned non-zero.
**
** See also the [sqlite3_update_hook()] interface.
*/
@@ -4515,7 +4403,7 @@ SQLITE_API void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*);
** interfaces.
*/
SQLITE_API void *sqlite3_update_hook(
- sqlite3*,
+ sqlite3*,
void(*)(void *,int ,char const *,char const *,sqlite3_int64),
void*
);
@@ -4747,6 +4635,8 @@ SQLITE_API int sqlite3_auto_extension(void (*xEntryPoint)(void));
SQLITE_API void sqlite3_reset_auto_extension(void);
/*
+****** EXPERIMENTAL - subject to change without notice **************
+**
** The interface to the virtual-table mechanism is currently considered
** to be experimental. The interface might change in incompatible ways.
** If this is a problem for you, do not use the interface at this time.
@@ -4766,9 +4656,10 @@ typedef struct sqlite3_module sqlite3_module;
/*
** CAPI3REF: Virtual Table Object
** KEYWORDS: sqlite3_module {virtual table module}
+** EXPERIMENTAL
**
-** This structure, sometimes called a a "virtual table module",
-** defines the implementation of a [virtual tables].
+** This structure, sometimes called a a "virtual table module",
+** defines the implementation of a [virtual tables].
** This structure consists mostly of methods for the module.
**
** ^A virtual table module is created by filling in a persistent
@@ -4812,6 +4703,7 @@ struct sqlite3_module {
/*
** CAPI3REF: Virtual Table Indexing Information
** KEYWORDS: sqlite3_index_info
+** EXPERIMENTAL
**
** The sqlite3_index_info structure and its substructures is used to
** pass information into and receive the reply from the [xBestIndex]
@@ -4893,6 +4785,7 @@ struct sqlite3_index_info {
/*
** CAPI3REF: Register A Virtual Table Implementation
+** EXPERIMENTAL
**
** ^These routines are used to register a new [virtual table module] name.
** ^Module names must be registered before
@@ -4900,7 +4793,7 @@ struct sqlite3_index_info {
** preexisting [virtual table] for the module.
**
** ^The module name is registered on the [database connection] specified
-** by the first parameter. ^The name of the module is given by the
+** by the first parameter. ^The name of the module is given by the
** second parameter. ^The third parameter is a pointer to
** the implementation of the [virtual table module]. ^The fourth
** parameter is an arbitrary client data pointer that is passed through
@@ -4914,13 +4807,13 @@ struct sqlite3_index_info {
** interface is equivalent to sqlite3_create_module_v2() with a NULL
** destructor.
*/
-SQLITE_API int sqlite3_create_module(
+SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_create_module(
sqlite3 *db, /* SQLite connection to register module with */
const char *zName, /* Name of the module */
const sqlite3_module *p, /* Methods for the module */
void *pClientData /* Client data for xCreate/xConnect */
);
-SQLITE_API int sqlite3_create_module_v2(
+SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_create_module_v2(
sqlite3 *db, /* SQLite connection to register module with */
const char *zName, /* Name of the module */
const sqlite3_module *p, /* Methods for the module */
@@ -4931,6 +4824,7 @@ SQLITE_API int sqlite3_create_module_v2(
/*
** CAPI3REF: Virtual Table Instance Object
** KEYWORDS: sqlite3_vtab
+** EXPERIMENTAL
**
** Every [virtual table module] implementation uses a subclass
** of this object to describe a particular instance
@@ -4956,6 +4850,7 @@ struct sqlite3_vtab {
/*
** CAPI3REF: Virtual Table Cursor Object
** KEYWORDS: sqlite3_vtab_cursor {virtual table cursor}
+** EXPERIMENTAL
**
** Every [virtual table module] implementation uses a subclass of the
** following structure to describe cursors that point into the
@@ -4977,19 +4872,21 @@ struct sqlite3_vtab_cursor {
/*
** CAPI3REF: Declare The Schema Of A Virtual Table
+** EXPERIMENTAL
**
** ^The [xCreate] and [xConnect] methods of a
** [virtual table module] call this interface
** to declare the format (the names and datatypes of the columns) of
** the virtual tables they implement.
*/
-SQLITE_API int sqlite3_declare_vtab(sqlite3*, const char *zSQL);
+SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_declare_vtab(sqlite3*, const char *zSQL);
/*
** CAPI3REF: Overload A Function For A Virtual Table
+** EXPERIMENTAL
**
** ^(Virtual tables can provide alternative implementations of functions
-** using the [xFindFunction] method of the [virtual table module].
+** using the [xFindFunction] method of the [virtual table module].
** But global versions of those functions
** must exist in order to be overloaded.)^
**
@@ -5001,7 +4898,7 @@ SQLITE_API int sqlite3_declare_vtab(sqlite3*, const char *zSQL);
** purpose is to be a placeholder function that can be overloaded
** by a [virtual table].
*/
-SQLITE_API int sqlite3_overload_function(sqlite3*, const char *zFuncName, int nArg);
+SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_overload_function(sqlite3*, const char *zFuncName, int nArg);
/*
** The interface to the virtual-table mechanism defined above (back up
@@ -5011,6 +4908,8 @@ SQLITE_API int sqlite3_overload_function(sqlite3*, const char *zFuncName, int nA
**
** When the virtual-table mechanism stabilizes, we will declare the
** interface fixed, support it indefinitely, and remove this comment.
+**
+****** EXPERIMENTAL - subject to change without notice **************
*/
/*
@@ -5040,8 +4939,8 @@ typedef struct sqlite3_blob sqlite3_blob;
**
** ^If the flags parameter is non-zero, then the BLOB is opened for read
** and write access. ^If it is zero, the BLOB is opened for read access.
-** ^It is not possible to open a column that is part of an index or primary
-** key for writing. ^If [foreign key constraints] are enabled, it is
+** ^It is not possible to open a column that is part of an index or primary
+** key for writing. ^If [foreign key constraints] are enabled, it is
** not possible to open a column that is part of a [child key] for writing.
**
** ^Note that the database name is not the filename that contains
@@ -5120,7 +5019,7 @@ SQLITE_API int sqlite3_blob_close(sqlite3_blob *);
/*
** CAPI3REF: Return The Size Of An Open BLOB
**
-** ^Returns the size in bytes of the BLOB accessible via the
+** ^Returns the size in bytes of the BLOB accessible via the
** successfully opened [BLOB handle] in its only argument. ^The
** incremental blob I/O routines can only read or overwriting existing
** blob content; they cannot change the size of a blob.
@@ -5353,6 +5252,7 @@ SQLITE_API void sqlite3_mutex_leave(sqlite3_mutex*);
/*
** CAPI3REF: Mutex Methods Object
+** EXPERIMENTAL
**
** An instance of this structure defines the low-level routines
** used to allocate and use mutexes.
@@ -5486,7 +5386,7 @@ SQLITE_API int sqlite3_mutex_notheld(sqlite3_mutex*);
/*
** CAPI3REF: Retrieve the mutex for a database connection
**
-** ^This interface returns a pointer the [sqlite3_mutex] object that
+** ^This interface returns a pointer the [sqlite3_mutex] object that
** serializes access to the [database connection] given in the argument
** when the [threading mode] is Serialized.
** ^If the [threading mode] is Single-thread or Multi-thread then this
@@ -5569,6 +5469,7 @@ SQLITE_API int sqlite3_test_control(int op, ...);
/*
** CAPI3REF: SQLite Runtime Status
+** EXPERIMENTAL
**
** ^This interface is used to retrieve runtime status information
** about the preformance of SQLite, and optionally to reset various
@@ -5596,11 +5497,12 @@ SQLITE_API int sqlite3_test_control(int op, ...);
**
** See also: [sqlite3_db_status()]
*/
-SQLITE_API int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag);
+SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag);
/*
** CAPI3REF: Status Parameters
+** EXPERIMENTAL
**
** These integer constants designate various run-time status parameters
** that can be returned by [sqlite3_status()].
@@ -5620,12 +5522,12 @@ SQLITE_API int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetF
** <dd>This parameter records the largest memory allocation request
** handed to [sqlite3_malloc()] or [sqlite3_realloc()] (or their
** internal equivalents). Only the value returned in the
-** *pHighwater parameter to [sqlite3_status()] is of interest.
+** *pHighwater parameter to [sqlite3_status()] is of interest.
** The value written into the *pCurrent parameter is undefined.</dd>)^
**
** ^(<dt>SQLITE_STATUS_PAGECACHE_USED</dt>
** <dd>This parameter returns the number of pages used out of the
-** [pagecache memory allocator] that was configured using
+** [pagecache memory allocator] that was configured using
** [SQLITE_CONFIG_PAGECACHE]. The
** value returned is in pages, not in bytes.</dd>)^
**
@@ -5641,7 +5543,7 @@ SQLITE_API int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetF
** ^(<dt>SQLITE_STATUS_PAGECACHE_SIZE</dt>
** <dd>This parameter records the largest memory allocation request
** handed to [pagecache memory allocator]. Only the value returned in the
-** *pHighwater parameter to [sqlite3_status()] is of interest.
+** *pHighwater parameter to [sqlite3_status()] is of interest.
** The value written into the *pCurrent parameter is undefined.</dd>)^
**
** ^(<dt>SQLITE_STATUS_SCRATCH_USED</dt>
@@ -5665,7 +5567,7 @@ SQLITE_API int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetF
** ^(<dt>SQLITE_STATUS_SCRATCH_SIZE</dt>
** <dd>This parameter records the largest memory allocation request
** handed to [scratch memory allocator]. Only the value returned in the
-** *pHighwater parameter to [sqlite3_status()] is of interest.
+** *pHighwater parameter to [sqlite3_status()] is of interest.
** The value written into the *pCurrent parameter is undefined.</dd>)^
**
** ^(<dt>SQLITE_STATUS_PARSER_STACK</dt>
@@ -5687,15 +5589,14 @@ SQLITE_API int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetF
/*
** CAPI3REF: Database Connection Status
+** EXPERIMENTAL
**
-** ^This interface is used to retrieve runtime status information
+** ^This interface is used to retrieve runtime status information
** about a single [database connection]. ^The first argument is the
** database connection object to be interrogated. ^The second argument
-** is an integer constant, taken from the set of
-** [SQLITE_DBSTATUS_LOOKASIDE_USED | SQLITE_DBSTATUS_*] macros, that
-** determiness the parameter to interrogate. The set of
-** [SQLITE_DBSTATUS_LOOKASIDE_USED | SQLITE_DBSTATUS_*] macros is likely
-** to grow in future releases of SQLite.
+** is the parameter to interrogate. ^Currently, the only allowed value
+** for the second parameter is [SQLITE_DBSTATUS_LOOKASIDE_USED].
+** Additional options will likely appear in future releases of SQLite.
**
** ^The current value of the requested parameter is written into *pCur
** and the highest instantaneous value is written into *pHiwtr. ^If
@@ -5704,10 +5605,11 @@ SQLITE_API int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetF
**
** See also: [sqlite3_status()] and [sqlite3_stmt_status()].
*/
-SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg);
+SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg);
/*
** CAPI3REF: Status Parameters for database connections
+** EXPERIMENTAL
**
** These constants are the available integer "verbs" that can be passed as
** the second argument to the [sqlite3_db_status()] interface.
@@ -5722,21 +5624,14 @@ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int r
** ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_USED</dt>
** <dd>This parameter returns the number of lookaside memory slots currently
** checked out.</dd>)^
-**
-** <dt>SQLITE_DBSTATUS_CACHE_USED</dt>
-** <dd>^This parameter returns the approximate number of of bytes of heap
-** memory used by all pager caches associated with the database connection.
-** ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_USED is always 0.
-** checked out.</dd>)^
** </dl>
*/
#define SQLITE_DBSTATUS_LOOKASIDE_USED 0
-#define SQLITE_DBSTATUS_CACHE_USED 1
-#define SQLITE_DBSTATUS_MAX 1 /* Largest defined DBSTATUS */
/*
** CAPI3REF: Prepared Statement Status
+** EXPERIMENTAL
**
** ^(Each prepared statement maintains various
** [SQLITE_STMTSTATUS_SORT | counters] that measure the number
@@ -5745,7 +5640,7 @@ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int r
** statements. For example, if the number of table steps greatly exceeds
** the number of table searches or result rows, that would tend to indicate
** that the prepared statement is using a full table scan rather than
-** an index.
+** an index.
**
** ^(This interface is used to retrieve and reset counter values from
** a [prepared statement]. The first argument is the prepared statement
@@ -5758,10 +5653,11 @@ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int r
**
** See also: [sqlite3_status()] and [sqlite3_db_status()].
*/
-SQLITE_API int sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg);
+SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg);
/*
** CAPI3REF: Status Parameters for prepared statements
+** EXPERIMENTAL
**
** These preprocessor macros define integer codes that name counter
** values associated with the [sqlite3_stmt_status()] interface.
@@ -5771,7 +5667,7 @@ SQLITE_API int sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg);
** <dt>SQLITE_STMTSTATUS_FULLSCAN_STEP</dt>
** <dd>^This is the number of times that SQLite has stepped forward in
** a table as part of a full table scan. Large numbers for this counter
-** may indicate opportunities for performance improvement through
+** may indicate opportunities for performance improvement through
** careful use of indices.</dd>
**
** <dt>SQLITE_STMTSTATUS_SORT</dt>
@@ -5779,21 +5675,14 @@ 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 through careful use of indices.</dd>
**
-** <dt>SQLITE_STMTSTATUS_AUTOINDEX</dt>
-** <dd>^This is the number of rows inserted into transient indices that
-** were created automatically in order to help joins run faster.
-** 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>
-**
** </dl>
*/
#define SQLITE_STMTSTATUS_FULLSCAN_STEP 1
#define SQLITE_STMTSTATUS_SORT 2
-#define SQLITE_STMTSTATUS_AUTOINDEX 3
/*
** CAPI3REF: Custom Page Cache Object
+** EXPERIMENTAL
**
** The sqlite3_pcache type is opaque. It is implemented by
** the pluggable module. The SQLite core has no knowledge of
@@ -5808,16 +5697,17 @@ typedef struct sqlite3_pcache sqlite3_pcache;
/*
** CAPI3REF: Application Defined Page Cache.
** KEYWORDS: {page cache}
+** EXPERIMENTAL
**
** ^(The [sqlite3_config]([SQLITE_CONFIG_PCACHE], ...) interface can
-** register an alternative page cache implementation by passing in an
-** instance of the sqlite3_pcache_methods structure.)^ The majority of the
-** heap memory used by SQLite is used by the page cache to cache data read
-** from, or ready to be written to, the database file. By implementing a
-** custom page cache using this API, an application can control more
-** precisely the amount of memory consumed by SQLite, the way in which
-** that memory is allocated and released, and the policies used to
-** determine exactly which parts of a database file are cached and for
+** register an alternative page cache implementation by passing in an
+** instance of the sqlite3_pcache_methods structure.)^ The majority of the
+** heap memory used by SQLite is used by the page cache to cache data read
+** from, or ready to be written to, the database file. By implementing a
+** custom page cache using this API, an application can control more
+** precisely the amount of memory consumed by SQLite, the way in which
+** that memory is allocated and released, and the policies used to
+** determine exactly which parts of a database file are cached and for
** how long.
**
** ^(The contents of the sqlite3_pcache_methods structure are copied to an
@@ -5829,10 +5719,10 @@ typedef struct sqlite3_pcache sqlite3_pcache;
** (usually only once during the lifetime of the process). ^(The xInit()
** method is passed a copy of the sqlite3_pcache_methods.pArg value.)^
** ^The xInit() method can set up up global structures and/or any mutexes
-** required by the custom page cache implementation.
+** required by the custom page cache implementation.
**
-** ^The xShutdown() method is called from within [sqlite3_shutdown()],
-** if the application invokes this API. It can be used to clean up
+** ^The xShutdown() method is called from within [sqlite3_shutdown()],
+** if the application invokes this API. It can be used to clean up
** any outstanding resources before process shutdown, if required.
**
** ^SQLite holds a [SQLITE_MUTEX_RECURSIVE] mutex when it invokes
@@ -5873,11 +5763,11 @@ typedef struct sqlite3_pcache sqlite3_pcache;
**
** ^The xPagecount() method should return the number of pages currently
** stored in the cache.
-**
-** ^The xFetch() method is used to fetch a page and return a pointer to it.
+**
+** ^The xFetch() method is used to fetch a page and return a pointer to it.
** ^A 'page', in this context, is a buffer of szPage bytes aligned at an
** 8-byte boundary. ^The page to be fetched is determined by the key. ^The
-** mimimum key value is 1. After it has been retrieved using xFetch, the page
+** mimimum key value is 1. After it has been retrieved using xFetch, the page
** is considered to be "pinned".
**
** ^If the requested page is already in the page cache, then the page cache
@@ -5904,14 +5794,14 @@ typedef struct sqlite3_pcache sqlite3_pcache;
**
** ^xUnpin() is called by SQLite with a pointer to a currently pinned page
** as its second argument. ^(If the third parameter, discard, is non-zero,
-** then the page should be evicted from the cache. In this case SQLite
+** then the page should be evicted from the cache. In this case SQLite
** assumes that the next time the page is retrieved from the cache using
** the xFetch() method, it will be zeroed.)^ ^If the discard parameter is
** zero, then the page is considered to be unpinned. ^The cache implementation
** may choose to evict unpinned pages at any time.
**
-** ^(The cache is not required to perform any reference counting. A single
-** call to xUnpin() unpins the page regardless of the number of prior calls
+** ^(The cache is not required to perform any reference counting. A single
+** call to xUnpin() unpins the page regardless of the number of prior calls
** to xFetch().)^
**
** ^The xRekey() method is used to change the key value associated with the
@@ -5949,6 +5839,7 @@ struct sqlite3_pcache_methods {
/*
** CAPI3REF: Online Backup Object
+** EXPERIMENTAL
**
** The sqlite3_backup object records state information about an ongoing
** online backup operation. ^The sqlite3_backup object is created by
@@ -5961,41 +5852,42 @@ typedef struct sqlite3_backup sqlite3_backup;
/*
** CAPI3REF: Online Backup API.
+** EXPERIMENTAL
**
** The backup API copies the content of one database into another.
** It is useful either for creating backups of databases or
-** for copying in-memory databases to or from persistent files.
+** for copying in-memory databases to or from persistent files.
**
** See Also: [Using the SQLite Online Backup API]
**
-** ^Exclusive access is required to the destination database for the
+** ^Exclusive access is required to the destination database for the
** duration of the operation. ^However the source database is only
** read-locked while it is actually being read; it is not locked
** continuously for the entire backup operation. ^Thus, the backup may be
** performed on a live source database without preventing other users from
** reading or writing to the source database while the backup is underway.
-**
-** ^(To perform a backup operation:
+**
+** ^(To perform a backup operation:
** <ol>
** <li><b>sqlite3_backup_init()</b> is called once to initialize the
-** backup,
-** <li><b>sqlite3_backup_step()</b> is called one or more times to transfer
+** backup,
+** <li><b>sqlite3_backup_step()</b> is called one or more times to transfer
** the data between the two databases, and finally
-** <li><b>sqlite3_backup_finish()</b> is called to release all resources
-** associated with the backup operation.
+** <li><b>sqlite3_backup_finish()</b> is called to release all resources
+** associated with the backup operation.
** </ol>)^
** There should be exactly one call to sqlite3_backup_finish() for each
** successful call to sqlite3_backup_init().
**
** <b>sqlite3_backup_init()</b>
**
-** ^The D and N arguments to sqlite3_backup_init(D,N,S,M) are the
-** [database connection] associated with the destination database
+** ^The D and N arguments to sqlite3_backup_init(D,N,S,M) are the
+** [database connection] associated with the destination database
** and the database name, respectively.
** ^The database name is "main" for the main database, "temp" for the
** temporary database, or the name specified after the AS keyword in
** an [ATTACH] statement for an attached database.
-** ^The S and M arguments passed to
+** ^The S and M arguments passed to
** sqlite3_backup_init(D,N,S,M) identify the [database connection]
** and database name of the source database, respectively.
** ^The source and destination [database connections] (parameters S and D)
@@ -6011,14 +5903,14 @@ typedef struct sqlite3_backup sqlite3_backup;
** ^A successful call to sqlite3_backup_init() returns a pointer to an
** [sqlite3_backup] object.
** ^The [sqlite3_backup] object may be used with the sqlite3_backup_step() and
-** sqlite3_backup_finish() functions to perform the specified backup
+** sqlite3_backup_finish() functions to perform the specified backup
** operation.
**
** <b>sqlite3_backup_step()</b>
**
-** ^Function sqlite3_backup_step(B,N) will copy up to N pages between
+** ^Function sqlite3_backup_step(B,N) will copy up to N pages between
** the source and destination databases specified by [sqlite3_backup] object B.
-** ^If N is negative, all remaining source pages are copied.
+** ^If N is negative, all remaining source pages are copied.
** ^If sqlite3_backup_step(B,N) successfully copies N pages and there
** are still more pages to be copied, then the function resturns [SQLITE_OK].
** ^If sqlite3_backup_step(B,N) successfully finishes copying all pages
@@ -6029,19 +5921,15 @@ typedef struct sqlite3_backup sqlite3_backup;
** [SQLITE_NOMEM], [SQLITE_BUSY], [SQLITE_LOCKED], or an
** [SQLITE_IOERR_ACCESS | SQLITE_IOERR_XXX] extended error code.
**
-** ^(The sqlite3_backup_step() might return [SQLITE_READONLY] if
-** <ol>
-** <li> the destination database was opened read-only, or
-** <li> the destination database is using write-ahead-log journaling
-** and the destination and source page sizes differ, or
-** <li> The destination database is an in-memory database and the
-** destination and source page sizes differ.
-** </ol>)^
+** ^The sqlite3_backup_step() might return [SQLITE_READONLY] if the destination
+** database was opened read-only or if
+** the destination is an in-memory database with a different page size
+** from the source database.
**
** ^If sqlite3_backup_step() cannot obtain a required file-system lock, then
** the [sqlite3_busy_handler | busy-handler function]
-** is invoked (if one is specified). ^If the
-** busy-handler returns non-zero before the lock is available, then
+** is invoked (if one is specified). ^If the
+** busy-handler returns non-zero before the lock is available, then
** [SQLITE_BUSY] is returned to the caller. ^In this case the call to
** sqlite3_backup_step() can be retried later. ^If the source
** [database connection]
@@ -6049,15 +5937,15 @@ typedef struct sqlite3_backup sqlite3_backup;
** is called, then [SQLITE_LOCKED] is returned immediately. ^Again, in this
** case the call to sqlite3_backup_step() can be retried later on. ^(If
** [SQLITE_IOERR_ACCESS | SQLITE_IOERR_XXX], [SQLITE_NOMEM], or
-** [SQLITE_READONLY] is returned, then
-** there is no point in retrying the call to sqlite3_backup_step(). These
-** errors are considered fatal.)^ The application must accept
-** that the backup operation has failed and pass the backup operation handle
+** [SQLITE_READONLY] is returned, then
+** there is no point in retrying the call to sqlite3_backup_step(). These
+** errors are considered fatal.)^ The application must accept
+** that the backup operation has failed and pass the backup operation handle
** to the sqlite3_backup_finish() to release associated resources.
**
** ^The first call to sqlite3_backup_step() obtains an exclusive lock
-** on the destination file. ^The exclusive lock is not released until either
-** sqlite3_backup_finish() is called or the backup operation is complete
+** on the destination file. ^The exclusive lock is not released until either
+** sqlite3_backup_finish() is called or the backup operation is complete
** and sqlite3_backup_step() returns [SQLITE_DONE]. ^Every call to
** sqlite3_backup_step() obtains a [shared lock] on the source database that
** lasts for the duration of the sqlite3_backup_step() call.
@@ -6066,18 +5954,18 @@ typedef struct sqlite3_backup sqlite3_backup;
** through the backup process. ^If the source database is modified by an
** external process or via a database connection other than the one being
** used by the backup operation, then the backup will be automatically
-** restarted by the next call to sqlite3_backup_step(). ^If the source
+** restarted by the next call to sqlite3_backup_step(). ^If the source
** database is modified by the using the same database connection as is used
** by the backup operation, then the backup database is automatically
** updated at the same time.
**
** <b>sqlite3_backup_finish()</b>
**
-** When sqlite3_backup_step() has returned [SQLITE_DONE], or when the
+** When sqlite3_backup_step() has returned [SQLITE_DONE], or when the
** application wishes to abandon the backup operation, the application
** should destroy the [sqlite3_backup] by passing it to sqlite3_backup_finish().
** ^The sqlite3_backup_finish() interfaces releases all
-** resources associated with the [sqlite3_backup] object.
+** resources associated with the [sqlite3_backup] object.
** ^If sqlite3_backup_step() has not yet returned [SQLITE_DONE], then any
** active write-transaction on the destination database is rolled back.
** The [sqlite3_backup] object is invalid
@@ -6116,8 +6004,8 @@ typedef struct sqlite3_backup sqlite3_backup;
** connections, then the source database connection may be used concurrently
** from within other threads.
**
-** However, the application must guarantee that the destination
-** [database connection] is not passed to any other API (by any thread) after
+** However, the application must guarantee that the destination
+** [database connection] is not passed to any other API (by any thread) after
** sqlite3_backup_init() is called and before the corresponding call to
** sqlite3_backup_finish(). SQLite does not currently check to see
** if the application incorrectly accesses the destination [database connection]
@@ -6128,11 +6016,11 @@ typedef struct sqlite3_backup sqlite3_backup;
** If running in [shared cache mode], the application must
** guarantee that the shared cache used by the destination database
** is not accessed while the backup is running. In practice this means
-** that the application must guarantee that the disk file being
+** that the application must guarantee that the disk file being
** backed up to is not accessed by any connection within the process,
** not just the specific connection that was passed to sqlite3_backup_init().
**
-** The [sqlite3_backup] object itself is partially threadsafe. Multiple
+** The [sqlite3_backup] object itself is partially threadsafe. Multiple
** threads may safely make multiple concurrent calls to sqlite3_backup_step().
** However, the sqlite3_backup_remaining() and sqlite3_backup_pagecount()
** APIs are not strictly speaking threadsafe. If they are invoked at the
@@ -6152,12 +6040,13 @@ SQLITE_API int sqlite3_backup_pagecount(sqlite3_backup *p);
/*
** CAPI3REF: Unlock Notification
+** EXPERIMENTAL
**
** ^When running in shared-cache mode, a database operation may fail with
** an [SQLITE_LOCKED] error if the required locks on the shared-cache or
** individual tables within the shared-cache cannot be obtained. See
-** [SQLite Shared-Cache Mode] for a description of shared-cache locking.
-** ^This API may be used to register a callback that SQLite will invoke
+** [SQLite Shared-Cache Mode] for a description of shared-cache locking.
+** ^This API may be used to register a callback that SQLite will invoke
** when the connection currently holding the required lock relinquishes it.
** ^This API is only available if the library was compiled with the
** [SQLITE_ENABLE_UNLOCK_NOTIFY] C-preprocessor symbol defined.
@@ -6165,14 +6054,14 @@ SQLITE_API int sqlite3_backup_pagecount(sqlite3_backup *p);
** See Also: [Using the SQLite Unlock Notification Feature].
**
** ^Shared-cache locks are released when a database connection concludes
-** its current transaction, either by committing it or rolling it back.
+** its current transaction, either by committing it or rolling it back.
**
** ^When a connection (known as the blocked connection) fails to obtain a
** shared-cache lock and SQLITE_LOCKED is returned to the caller, the
** identity of the database connection (the blocking connection) that
-** has locked the required resource is stored internally. ^After an
+** has locked the required resource is stored internally. ^After an
** application receives an SQLITE_LOCKED error, it may call the
-** sqlite3_unlock_notify() method with the blocked connection handle as
+** sqlite3_unlock_notify() method with the blocked connection handle as
** the first argument to register for a callback that will be invoked
** when the blocking connections current transaction is concluded. ^The
** callback is invoked from within the [sqlite3_step] or [sqlite3_close]
@@ -6186,15 +6075,15 @@ SQLITE_API int sqlite3_backup_pagecount(sqlite3_backup *p);
**
** ^If the blocked connection is attempting to obtain a write-lock on a
** shared-cache table, and more than one other connection currently holds
-** a read-lock on the same table, then SQLite arbitrarily selects one of
+** a read-lock on the same table, then SQLite arbitrarily selects one of
** the other connections to use as the blocking connection.
**
-** ^(There may be at most one unlock-notify callback registered by a
+** ^(There may be at most one unlock-notify callback registered by a
** blocked connection. If sqlite3_unlock_notify() is called when the
** blocked connection already has a registered unlock-notify callback,
** then the new callback replaces the old.)^ ^If sqlite3_unlock_notify() is
** called with a NULL pointer as its second argument, then any existing
-** unlock-notify callback is cancelled. ^The blocked connections
+** unlock-notify callback is cancelled. ^The blocked connections
** unlock-notify callback may also be canceled by closing the blocked
** connection using [sqlite3_close()].
**
@@ -6207,7 +6096,7 @@ SQLITE_API int sqlite3_backup_pagecount(sqlite3_backup *p);
**
** <b>Callback Invocation Details</b>
**
-** When an unlock-notify callback is registered, the application provides a
+** When an unlock-notify callback is registered, the application provides a
** single void* pointer that is passed to the callback when it is invoked.
** However, the signature of the callback function allows SQLite to pass
** it an array of void* context pointers. The first argument passed to
@@ -6220,12 +6109,12 @@ SQLITE_API int sqlite3_backup_pagecount(sqlite3_backup *p);
** same callback function, then instead of invoking the callback function
** multiple times, it is invoked once with the set of void* context pointers
** specified by the blocked connections bundled together into an array.
-** This gives the application an opportunity to prioritize any actions
+** This gives the application an opportunity to prioritize any actions
** related to the set of unblocked database connections.
**
** <b>Deadlock Detection</b>
**
-** Assuming that after registering for an unlock-notify callback a
+** Assuming that after registering for an unlock-notify callback a
** database waits for the callback to be issued before taking any further
** action (a reasonable assumption), then using this API may cause the
** application to deadlock. For example, if connection X is waiting for
@@ -6248,7 +6137,7 @@ SQLITE_API int sqlite3_backup_pagecount(sqlite3_backup *p);
**
** <b>The "DROP TABLE" Exception</b>
**
-** When a call to [sqlite3_step()] returns SQLITE_LOCKED, it is almost
+** When a call to [sqlite3_step()] returns SQLITE_LOCKED, it is almost
** always appropriate to call sqlite3_unlock_notify(). There is however,
** one exception. When executing a "DROP TABLE" or "DROP INDEX" statement,
** SQLite checks if there are any currently executing SELECT statements
@@ -6261,7 +6150,7 @@ SQLITE_API int sqlite3_backup_pagecount(sqlite3_backup *p);
** One way around this problem is to check the extended error code returned
** by an sqlite3_step() call. ^(If there is a blocking connection, then the
** extended error code is set to SQLITE_LOCKED_SHAREDCACHE. Otherwise, in
-** the special "DROP TABLE/INDEX" case, the extended error code is just
+** the special "DROP TABLE/INDEX" case, the extended error code is just
** SQLITE_LOCKED.)^
*/
SQLITE_API int sqlite3_unlock_notify(
@@ -6273,29 +6162,27 @@ SQLITE_API int sqlite3_unlock_notify(
/*
** CAPI3REF: String Comparison
+** EXPERIMENTAL
**
** ^The [sqlite3_strnicmp()] API allows applications and extensions to
** compare the contents of two buffers containing UTF-8 strings in a
-** case-indendent fashion, using the same definition of case independence
+** case-indendent fashion, using the same definition of case independence
** that SQLite uses internally when comparing identifiers.
*/
SQLITE_API int sqlite3_strnicmp(const char *, const char *, int);
/*
** CAPI3REF: Error Logging Interface
+** EXPERIMENTAL
**
** ^The [sqlite3_log()] interface writes a message into the error log
-** established by the [SQLITE_CONFIG_LOG] option to [sqlite3_config()].
-** ^If logging is enabled, the zFormat string and subsequent arguments are
-** used with [sqlite3_snprintf()] to generate the final output string.
+** established by the [SQLITE_CONFIG_ERRORLOG] option to [sqlite3_config()].
**
** The sqlite3_log() interface is intended for use by extensions such as
** virtual tables, collating functions, and SQL functions. While there is
** nothing to prevent an application from calling sqlite3_log(), doing so
** is considered bad form.
**
-** The zFormat string must not be NULL.
-**
** To avoid deadlocks and other threading problems, the sqlite3_log() routine
** will not use dynamically allocated memory. The log message is stored in
** a fixed-length buffer on the stack. If the log message is longer than
@@ -6305,89 +6192,6 @@ SQLITE_API int sqlite3_strnicmp(const char *, const char *, int);
SQLITE_API void sqlite3_log(int iErrCode, const char *zFormat, ...);
/*
-** CAPI3REF: Write-Ahead Log Commit Hook
-**
-** ^The [sqlite3_wal_hook()] function is used to register a callback that
-** will be invoked each time a database connection commits data to a
-** [write-ahead log] (i.e. whenever a transaction is committed in
-** [journal_mode | journal_mode=WAL mode]).
-**
-** ^The callback is invoked by SQLite after the commit has taken place and
-** the associated write-lock on the database released, so the implementation
-** may read, write or [checkpoint] the database as required.
-**
-** ^The first parameter passed to the callback function when it is invoked
-** is a copy of the third parameter passed to sqlite3_wal_hook() when
-** registering the callback. ^The second is a copy of the database handle.
-** ^The third parameter is the name of the database that was written to -
-** either "main" or the name of an ATTACHed database. ^The fourth parameter
-** is the number of pages currently in the write-ahead log file,
-** including those that were just committed.
-**
-** The callback function should normally return SQLITE_OK. ^If an error
-** code is returned, that error will propagate back up through the
-** SQLite code base to cause the statement that provoked the callback
-** to report an error, though the commit will have still occurred. If the
-** callback returns SQLITE_ROW or SQLITE_DONE, or if it returns a value
-** that does not correspond to any valid SQLite error code, the results
-** are undefined.
-**
-** A single database handle may have at most a single write-ahead log callback
-** registered at one time. ^Calling [sqlite3_wal_hook()] replaces any
-** previously registered write-ahead log callback. Note that the
-** [sqlite3_wal_autocheckpoint()] interface and the
-** [wal_autocheckpoint pragma] both invoke [sqlite3_wal_hook()] and will
-** those overwrite any prior [sqlite3_wal_hook()] settings.
-*/
-SQLITE_API void *sqlite3_wal_hook(
- sqlite3*,
- int(*)(void *,sqlite3*,const char*,int),
- void*
-);
-
-/*
-** CAPI3REF: Configure an auto-checkpoint
-**
-** ^The [sqlite3_wal_autocheckpoint(D,N)] is a wrapper around
-** [sqlite3_wal_hook()] that causes any database on [database connection] D
-** to automatically [checkpoint]
-** after committing a transaction if there are N or
-** more frames in the [write-ahead log] file. ^Passing zero or
-** a negative value as the nFrame parameter disables automatic
-** checkpoints entirely.
-**
-** ^The callback registered by this function replaces any existing callback
-** registered using [sqlite3_wal_hook()]. ^Likewise, registering a callback
-** using [sqlite3_wal_hook()] disables the automatic checkpoint mechanism
-** configured by this function.
-**
-** ^The [wal_autocheckpoint pragma] can be used to invoke this interface
-** from SQL.
-**
-** ^Every new [database connection] defaults to having the auto-checkpoint
-** enabled with a threshold of 1000 pages. The use of this interface
-** is only necessary if the default setting is found to be suboptimal
-** for a particular application.
-*/
-SQLITE_API int sqlite3_wal_autocheckpoint(sqlite3 *db, int N);
-
-/*
-** CAPI3REF: Checkpoint a database
-**
-** ^The [sqlite3_wal_checkpoint(D,X)] interface causes database named X
-** on [database connection] D to be [checkpointed]. ^If X is NULL or an
-** empty string, then a checkpoint is run on all databases of
-** connection D. ^If the database connection D is not in
-** [WAL | write-ahead log mode] then this interface is a harmless no-op.
-**
-** ^The [wal_checkpoint pragma] can be used to invoke this interface
-** from SQL. ^The [sqlite3_wal_autocheckpoint()] interface and the
-** [wal_autocheckpoint pragma] can be used to cause this interface to be
-** run whenever the WAL reaches a certain size threshold.
-*/
-SQLITE_API int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb);
-
-/*
** Undo the hack that converts floating point types to integer for
** builds on processors without floating point support.
*/
@@ -6447,7 +6251,7 @@ typedef struct HashElem HashElem;
** element pointed to plus the next _ht.count-1 elements in the list.
**
** Hash.htsize and Hash.ht may be zero. In that case lookup is done
-** by a linear search of the global list. For small tables, the
+** by a linear search of the global list. For small tables, the
** Hash.ht table is never allocated because if there are few elements
** in the table, it is faster to do a linear search than to manage
** the hash table.
@@ -6462,7 +6266,7 @@ struct Hash {
} *ht;
};
-/* Each element in the hash table is an instance of the following
+/* Each element in the hash table is an instance of the following
** structure. All elements are stored on a single doubly-linked list.
**
** Again, this structure is intended to be opaque, but it can't really
@@ -6683,7 +6487,6 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash*);
*/
#ifdef SQLITE_OMIT_FLOATING_POINT
# define double sqlite_int64
-# define float sqlite_int64
# define LONGDOUBLE_TYPE sqlite_int64
# ifndef SQLITE_BIG_DBL
# define SQLITE_BIG_DBL (((sqlite3_int64)1)<<50)
@@ -6699,7 +6502,7 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash*);
/*
** OMIT_TEMPDB is set to 1 if SQLITE_OMIT_TEMPDB is defined, or 0
-** afterward. Having this macro allows us to cause the C compiler
+** afterward. Having this macro allows us to cause the C compiler
** to omit code used by TEMP tables without messy #ifndef statements.
*/
#ifdef SQLITE_OMIT_TEMPDB
@@ -6709,6 +6512,20 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash*);
#endif
/*
+** If the following macro is set to 1, then NULL values are considered
+** distinct when determining whether or not two entries are the same
+** in a UNIQUE index. This is the way PostgreSQL, Oracle, DB2, MySQL,
+** OCELOT, and Firebird all work. The SQL92 spec explicitly says this
+** is the way things are suppose to work.
+**
+** If the following macro is set to 0, the NULLs are indistinct for
+** a UNIQUE index. In this mode, you can only have a single NULL entry
+** for a column declared UNIQUE. This is the way Informix and SQL Server
+** work.
+*/
+#define NULL_DISTINCT_FOR_UNIQUE 1
+
+/*
** The "file format" number is an integer that is incremented whenever
** the VDBE-level file format changes. The following macros define the
** the default file format for new databases and the maximum file format
@@ -6719,10 +6536,6 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash*);
# define SQLITE_DEFAULT_FILE_FORMAT 1
#endif
-/*
-** Determine whether triggers are recursive by default. This can be
-** changed at run-time using a pragma.
-*/
#ifndef SQLITE_DEFAULT_RECURSIVE_TRIGGERS
# define SQLITE_DEFAULT_RECURSIVE_TRIGGERS 0
#endif
@@ -6842,7 +6655,7 @@ SQLITE_PRIVATE const int sqlite3one;
#define LARGEST_INT64 (0xffffffff|(((i64)0x7fffffff)<<32))
#define SMALLEST_INT64 (((i64)-1) - LARGEST_INT64)
-/*
+/*
** Round up a number to the next larger multiple of 8. This is used
** to force 8-byte alignment on 64-bit architectures.
*/
@@ -6871,7 +6684,7 @@ SQLITE_PRIVATE const int sqlite3one;
/*
** An instance of the following structure is used to store the busy-handler
-** callback for a given sqlite handle.
+** callback for a given sqlite handle.
**
** The sqlite.busyHandler member of the sqlite struct contains the busy
** callback for the database handle. Each pager opened via the sqlite
@@ -6936,16 +6749,16 @@ struct BusyHandler {
SQLITE_API int sqlite3_wsd_init(int N, int J);
SQLITE_API void *sqlite3_wsd_find(void *K, int L);
#else
- #define SQLITE_WSD
+ #define SQLITE_WSD
#define GLOBAL(t,v) v
#define sqlite3GlobalConfig sqlite3Config
#endif
/*
** The following macros are used to suppress compiler warnings and to
-** make it clear to human readers when a function parameter is deliberately
+** make it clear to human readers when a function parameter is deliberately
** left unused within the body of a function. This usually happens when
-** a function is called via a function pointer. For example the
+** a function is called via a function pointer. For example the
** implementation of an SQL aggregate step callback may not use the
** parameter indicating the number of arguments passed to the aggregate,
** if it knows that this is enforced elsewhere.
@@ -6967,6 +6780,7 @@ typedef struct AggInfo AggInfo;
typedef struct AuthContext AuthContext;
typedef struct AutoincInfo AutoincInfo;
typedef struct Bitvec Bitvec;
+typedef struct RowSet RowSet;
typedef struct CollSeq CollSeq;
typedef struct Column Column;
typedef struct Db Db;
@@ -6987,7 +6801,6 @@ typedef struct LookasideSlot LookasideSlot;
typedef struct Module Module;
typedef struct NameContext NameContext;
typedef struct Parse Parse;
-typedef struct RowSet RowSet;
typedef struct Savepoint Savepoint;
typedef struct Select Select;
typedef struct SrcList SrcList;
@@ -6995,9 +6808,9 @@ typedef struct StrAccum StrAccum;
typedef struct Table Table;
typedef struct TableLock TableLock;
typedef struct Token Token;
-typedef struct Trigger Trigger;
typedef struct TriggerPrg TriggerPrg;
typedef struct TriggerStep TriggerStep;
+typedef struct Trigger Trigger;
typedef struct UnpackedRecord UnpackedRecord;
typedef struct VTable VTable;
typedef struct Walker Walker;
@@ -7006,7 +6819,7 @@ typedef struct WhereInfo WhereInfo;
typedef struct WhereLevel WhereLevel;
/*
-** Defer sourcing vdbe.h and btree.h until after the "u8" and
+** Defer sourcing vdbe.h and btree.h until after the "u8" and
** "BusyHandler" typedefs. vdbe.h also requires a few of the opaque
** pointer types (i.e. FuncDef) defined above.
*/
@@ -7095,8 +6908,6 @@ SQLITE_PRIVATE int sqlite3BtreeSyncDisabled(Btree*);
SQLITE_PRIVATE int sqlite3BtreeSetPageSize(Btree *p, int nPagesize, int nReserve, int eFix);
SQLITE_PRIVATE int sqlite3BtreeGetPageSize(Btree*);
SQLITE_PRIVATE int sqlite3BtreeMaxPageCount(Btree*,int);
-SQLITE_PRIVATE u32 sqlite3BtreeLastPage(Btree*);
-SQLITE_PRIVATE int sqlite3BtreeSecureDelete(Btree*,int);
SQLITE_PRIVATE int sqlite3BtreeGetReserve(Btree*);
SQLITE_PRIVATE int sqlite3BtreeSetAutoVacuum(Btree *, int);
SQLITE_PRIVATE int sqlite3BtreeGetAutoVacuum(Btree *);
@@ -7137,7 +6948,7 @@ SQLITE_PRIVATE int sqlite3BtreeUpdateMeta(Btree*, int idx, u32 value);
/*
** The second parameter to sqlite3BtreeGetMeta or sqlite3BtreeUpdateMeta
-** should be one of the following values. The integer values are assigned
+** should be one of the following values. The integer values are assigned
** to constants so that the offset of the corresponding field in an
** SQLite database header may be found using the following formula:
**
@@ -7200,8 +7011,6 @@ SQLITE_PRIVATE int sqlite3BtreePutData(BtCursor*, u32 offset, u32 amt, void*);
SQLITE_PRIVATE void sqlite3BtreeCacheOverflow(BtCursor *);
SQLITE_PRIVATE void sqlite3BtreeClearCursor(BtCursor *);
-SQLITE_PRIVATE int sqlite3BtreeSetVersion(Btree *pBt, int iVersion);
-
#ifndef NDEBUG
SQLITE_PRIVATE int sqlite3BtreeCursorIsValid(BtCursor*);
#endif
@@ -7224,7 +7033,7 @@ SQLITE_PRIVATE void sqlite3BtreeCursorList(Btree*);
SQLITE_PRIVATE void sqlite3BtreeEnter(Btree*);
SQLITE_PRIVATE void sqlite3BtreeEnterAll(sqlite3*);
#else
-# define sqlite3BtreeEnter(X)
+# define sqlite3BtreeEnter(X)
# define sqlite3BtreeEnterAll(X)
#endif
@@ -7391,7 +7200,7 @@ typedef struct VdbeOpList VdbeOpList;
#define P4_KEYINFO_STATIC (-17)
/*
-** The Vdbe.aColName array contains 5n Mem structures, where n is the
+** The Vdbe.aColName array contains 5n Mem structures, where n is the
** number of columns of data returned by the statement.
*/
#define COLNAME_NAME 0
@@ -7411,7 +7220,7 @@ typedef struct VdbeOpList VdbeOpList;
/*
** The following macro converts a relative address in the p2 field
-** of a VdbeOp structure into a negative number so that
+** of a VdbeOp structure into a negative number so that
** sqlite3VdbeAddOpList() knows that the address is relative. Calling
** the macro again restores the address.
*/
@@ -7492,83 +7301,83 @@ typedef struct VdbeOpList VdbeOpList;
#define OP_VerifyCookie 37
#define OP_OpenRead 38
#define OP_OpenWrite 39
-#define OP_OpenAutoindex 40
-#define OP_OpenEphemeral 41
-#define OP_OpenPseudo 42
-#define OP_Close 43
-#define OP_SeekLt 44
-#define OP_SeekLe 45
-#define OP_SeekGe 46
-#define OP_SeekGt 47
-#define OP_Seek 48
-#define OP_NotFound 49
-#define OP_Found 50
-#define OP_IsUnique 51
-#define OP_NotExists 52
-#define OP_Sequence 53
-#define OP_NewRowid 54
-#define OP_Insert 55
-#define OP_InsertInt 56
-#define OP_Delete 57
-#define OP_ResetCount 58
-#define OP_RowKey 59
-#define OP_RowData 60
-#define OP_Rowid 61
-#define OP_NullRow 62
-#define OP_Last 63
-#define OP_Sort 64
-#define OP_Rewind 65
-#define OP_Prev 66
-#define OP_Next 67
-#define OP_IdxInsert 70
-#define OP_IdxDelete 71
-#define OP_IdxRowid 72
-#define OP_IdxLT 81
-#define OP_IdxGE 92
-#define OP_Destroy 95
-#define OP_Clear 96
-#define OP_CreateIndex 97
-#define OP_CreateTable 98
-#define OP_ParseSchema 99
-#define OP_LoadAnalysis 100
-#define OP_DropTable 101
-#define OP_DropIndex 102
-#define OP_DropTrigger 103
-#define OP_IntegrityCk 104
-#define OP_RowSetAdd 105
-#define OP_RowSetRead 106
-#define OP_RowSetTest 107
-#define OP_Program 108
-#define OP_Param 109
-#define OP_FkCounter 110
-#define OP_FkIfZero 111
-#define OP_MemMax 112
-#define OP_IfPos 113
-#define OP_IfNeg 114
-#define OP_IfZero 115
-#define OP_AggStep 116
-#define OP_AggFinal 117
-#define OP_Checkpoint 118
-#define OP_JournalMode 119
-#define OP_Vacuum 120
-#define OP_IncrVacuum 121
-#define OP_Expire 122
-#define OP_TableLock 123
-#define OP_VBegin 124
-#define OP_VCreate 125
-#define OP_VDestroy 126
-#define OP_VOpen 127
-#define OP_VFilter 128
-#define OP_VColumn 129
-#define OP_VNext 131
-#define OP_VRename 132
-#define OP_VUpdate 133
-#define OP_Pagecount 134
-#define OP_Trace 135
-#define OP_Noop 136
-#define OP_Explain 137
+#define OP_OpenEphemeral 40
+#define OP_OpenPseudo 41
+#define OP_Close 42
+#define OP_SeekLt 43
+#define OP_SeekLe 44
+#define OP_SeekGe 45
+#define OP_SeekGt 46
+#define OP_Seek 47
+#define OP_NotFound 48
+#define OP_Found 49
+#define OP_IsUnique 50
+#define OP_NotExists 51
+#define OP_Sequence 52
+#define OP_NewRowid 53
+#define OP_Insert 54
+#define OP_InsertInt 55
+#define OP_Delete 56
+#define OP_ResetCount 57
+#define OP_RowKey 58
+#define OP_RowData 59
+#define OP_Rowid 60
+#define OP_NullRow 61
+#define OP_Last 62
+#define OP_Sort 63
+#define OP_Rewind 64
+#define OP_Prev 65
+#define OP_Next 66
+#define OP_IdxInsert 67
+#define OP_IdxDelete 70
+#define OP_IdxRowid 71
+#define OP_IdxLT 72
+#define OP_IdxGE 81
+#define OP_Destroy 92
+#define OP_Clear 95
+#define OP_CreateIndex 96
+#define OP_CreateTable 97
+#define OP_ParseSchema 98
+#define OP_LoadAnalysis 99
+#define OP_DropTable 100
+#define OP_DropIndex 101
+#define OP_DropTrigger 102
+#define OP_IntegrityCk 103
+#define OP_RowSetAdd 104
+#define OP_RowSetRead 105
+#define OP_RowSetTest 106
+#define OP_Program 107
+#define OP_Param 108
+#define OP_FkCounter 109
+#define OP_FkIfZero 110
+#define OP_MemMax 111
+#define OP_IfPos 112
+#define OP_IfNeg 113
+#define OP_IfZero 114
+#define OP_AggStep 115
+#define OP_AggFinal 116
+#define OP_Vacuum 117
+#define OP_IncrVacuum 118
+#define OP_Expire 119
+#define OP_TableLock 120
+#define OP_VBegin 121
+#define OP_VCreate 122
+#define OP_VDestroy 123
+#define OP_VOpen 124
+#define OP_VFilter 125
+#define OP_VColumn 126
+#define OP_VNext 127
+#define OP_VRename 128
+#define OP_VUpdate 129
+#define OP_Pagecount 131
+#define OP_Trace 132
+#define OP_Noop 133
+#define OP_Explain 134
/* The following opcode values are never used */
+#define OP_NotUsed_135 135
+#define OP_NotUsed_136 136
+#define OP_NotUsed_137 137
#define OP_NotUsed_138 138
#define OP_NotUsed_139 139
#define OP_NotUsed_140 140
@@ -7587,22 +7396,22 @@ typedef struct VdbeOpList VdbeOpList;
#define OPFLG_OUT3 0x0040 /* out3: P3 is an output */
#define OPFLG_INITIALIZER {\
/* 0 */ 0x00, 0x01, 0x05, 0x04, 0x04, 0x10, 0x00, 0x02,\
-/* 8 */ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x24, 0x24,\
+/* 8 */ 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x24, 0x24,\
/* 16 */ 0x00, 0x00, 0x00, 0x24, 0x04, 0x05, 0x04, 0x00,\
/* 24 */ 0x00, 0x01, 0x05, 0x05, 0x00, 0x00, 0x00, 0x02,\
/* 32 */ 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00,\
-/* 40 */ 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11,\
-/* 48 */ 0x08, 0x11, 0x11, 0x11, 0x11, 0x02, 0x02, 0x00,\
-/* 56 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01,\
-/* 64 */ 0x01, 0x01, 0x01, 0x01, 0x4c, 0x4c, 0x08, 0x00,\
-/* 72 */ 0x02, 0x05, 0x05, 0x15, 0x15, 0x15, 0x15, 0x15,\
+/* 40 */ 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, 0x08,\
+/* 48 */ 0x11, 0x11, 0x11, 0x11, 0x02, 0x02, 0x00, 0x00,\
+/* 56 */ 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x01,\
+/* 64 */ 0x01, 0x01, 0x01, 0x08, 0x4c, 0x4c, 0x00, 0x02,\
+/* 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, 0x02,\
-/* 96 */ 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,\
-/* 104 */ 0x00, 0x0c, 0x45, 0x15, 0x01, 0x02, 0x00, 0x01,\
-/* 112 */ 0x08, 0x05, 0x05, 0x05, 0x00, 0x00, 0x00, 0x02,\
-/* 120 */ 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
-/* 128 */ 0x01, 0x00, 0x02, 0x01, 0x00, 0x00, 0x02, 0x00,\
+/* 88 */ 0x4c, 0x4c, 0x4c, 0x4c, 0x02, 0x24, 0x02, 0x00,\
+/* 96 */ 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
+/* 104 */ 0x0c, 0x45, 0x15, 0x01, 0x02, 0x00, 0x01, 0x08,\
+/* 112 */ 0x05, 0x05, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00,\
+/* 120 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01,\
+/* 128 */ 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00,\
/* 136 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x04,\
/* 144 */ 0x04, 0x04,}
@@ -7698,8 +7507,8 @@ SQLITE_PRIVATE void sqlite3VdbeNoopComment(Vdbe*, const char*, ...);
#define _PAGER_H_
/*
-** Default maximum size for persistent journal files. A negative
-** value means no limit. This value may be overridden using the
+** Default maximum size for persistent journal files. A negative
+** value means no limit. This value may be overridden using the
** sqlite3PagerJournalSizeLimit() API. See also "PRAGMA journal_size_limit".
*/
#ifndef SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT
@@ -7725,9 +7534,9 @@ typedef struct PgHdr DbPage;
/*
** Page number PAGER_MJ_PGNO is never used in an SQLite database (it is
** reserved for working around a windows/posix incompatibility). It is
-** used in the journal to signify that the remainder of the journal file
+** used in the journal to signify that the remainder of the journal file
** is devoted to storing a master journal name - there are no more pages to
-** roll back. See comments for function writeMasterJournal() in pager.c
+** roll back. See comments for function writeMasterJournal() in pager.c
** for details.
*/
#define PAGER_MJ_PGNO(x) ((Pgno)((PENDING_BYTE/((x)->pageSize))+1))
@@ -7756,15 +7565,14 @@ typedef struct PgHdr DbPage;
#define PAGER_JOURNALMODE_OFF 2 /* Journal omitted. */
#define PAGER_JOURNALMODE_TRUNCATE 3 /* Commit by truncating journal */
#define PAGER_JOURNALMODE_MEMORY 4 /* In-memory journal file */
-#define PAGER_JOURNALMODE_WAL 5 /* Use write-ahead logging */
/*
** The remainder of this file contains the declarations of the functions
-** that make up the Pager sub-system API. See source code comments for
+** that make up the Pager sub-system API. See source code comments for
** a detailed description of each routine.
*/
-/* Open and close a Pager connection. */
+/* Open and close a Pager connection. */
SQLITE_PRIVATE int sqlite3PagerOpen(
sqlite3_vfs*,
Pager **ppPager,
@@ -7788,7 +7596,7 @@ SQLITE_PRIVATE int sqlite3PagerJournalMode(Pager *, int);
SQLITE_PRIVATE i64 sqlite3PagerJournalSizeLimit(Pager *, i64);
SQLITE_PRIVATE sqlite3_backup **sqlite3PagerBackupPtr(Pager*);
-/* Functions used to obtain and release page references. */
+/* Functions used to obtain and release page references. */
SQLITE_PRIVATE int sqlite3PagerAcquire(Pager *pPager, Pgno pgno, DbPage **ppPage, int clrFlag);
#define sqlite3PagerGet(A,B,C) sqlite3PagerAcquire(A,B,C,0)
SQLITE_PRIVATE DbPage *sqlite3PagerLookup(Pager *pPager, Pgno pgno);
@@ -7800,8 +7608,8 @@ SQLITE_PRIVATE int sqlite3PagerWrite(DbPage*);
SQLITE_PRIVATE void sqlite3PagerDontWrite(DbPage*);
SQLITE_PRIVATE int sqlite3PagerMovepage(Pager*,DbPage*,Pgno,int);
SQLITE_PRIVATE int sqlite3PagerPageRefcount(DbPage*);
-SQLITE_PRIVATE void *sqlite3PagerGetData(DbPage *);
-SQLITE_PRIVATE void *sqlite3PagerGetExtra(DbPage *);
+SQLITE_PRIVATE void *sqlite3PagerGetData(DbPage *);
+SQLITE_PRIVATE void *sqlite3PagerGetExtra(DbPage *);
/* Functions used to manage pager transactions and savepoints. */
SQLITE_PRIVATE int sqlite3PagerPagecount(Pager*, int*);
@@ -7814,16 +7622,9 @@ SQLITE_PRIVATE int sqlite3PagerOpenSavepoint(Pager *pPager, int n);
SQLITE_PRIVATE int sqlite3PagerSavepoint(Pager *pPager, int op, int iSavepoint);
SQLITE_PRIVATE int sqlite3PagerSharedLock(Pager *pPager);
-SQLITE_PRIVATE int sqlite3PagerCheckpoint(Pager *pPager);
-SQLITE_PRIVATE int sqlite3PagerWalSupported(Pager *pPager);
-SQLITE_PRIVATE int sqlite3PagerWalCallback(Pager *pPager);
-SQLITE_PRIVATE int sqlite3PagerOpenWal(Pager *pPager, int *pisOpen);
-SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager);
-
/* Functions used to query pager state and configuration. */
SQLITE_PRIVATE u8 sqlite3PagerIsreadonly(Pager*);
SQLITE_PRIVATE int sqlite3PagerRefcount(Pager*);
-SQLITE_PRIVATE int sqlite3PagerMemUsed(Pager*);
SQLITE_PRIVATE const char *sqlite3PagerFilename(Pager*);
SQLITE_PRIVATE const sqlite3_vfs *sqlite3PagerVfs(Pager*);
SQLITE_PRIVATE sqlite3_file *sqlite3PagerFile(Pager*);
@@ -7868,7 +7669,7 @@ SQLITE_PRIVATE void sqlite3PagerRefdump(Pager*);
**
*************************************************************************
** This header file defines the interface that the sqlite page cache
-** subsystem.
+** subsystem.
*/
#ifndef _PCACHE_H_
@@ -7941,7 +7742,7 @@ SQLITE_PRIVATE void sqlite3PcacheSetPageSize(PCache *, int);
SQLITE_PRIVATE int sqlite3PcacheSize(void);
/* One release per successful fetch. Page is pinned until released.
-** Reference counted.
+** Reference counted.
*/
SQLITE_PRIVATE int sqlite3PcacheFetch(PCache*, Pgno, int createFlag, PgHdr**);
SQLITE_PRIVATE void sqlite3PcacheRelease(PgHdr*);
@@ -7982,7 +7783,7 @@ SQLITE_PRIVATE int sqlite3PcachePagecount(PCache*);
#if defined(SQLITE_CHECK_PAGES) || defined(SQLITE_DEBUG)
/* Iterate through all dirty pages currently stored in the cache. This
-** interface is only available if SQLITE_CHECK_PAGES is defined when the
+** interface is only available if SQLITE_CHECK_PAGES is defined when the
** library is built.
*/
SQLITE_PRIVATE void sqlite3PcacheIterateDirty(PCache *pCache, void (*xIter)(PgHdr *));
@@ -8042,8 +7843,8 @@ SQLITE_PRIVATE void sqlite3PCacheSetDefault(void);
/*
** Figure out if we are dealing with Unix, Windows, or some other
** operating system. After the following block of preprocess macros,
-** all of SQLITE_OS_UNIX, SQLITE_OS_WIN, SQLITE_OS_OS2, and SQLITE_OS_OTHER
-** will defined to either 1 or 0. One of the four will be 1. The other
+** all of SQLITE_OS_UNIX, SQLITE_OS_WIN, SQLITE_OS_OS2, and SQLITE_OS_OTHER
+** will defined to either 1 or 0. One of the four will be 1. The other
** three will be 0.
*/
#if defined(SQLITE_OS_OTHER)
@@ -8145,10 +7946,10 @@ SQLITE_PRIVATE void sqlite3PCacheSetDefault(void);
** 2006-10-31: The default prefix used to be "sqlite_". But then
** Mcafee started using SQLite in their anti-virus product and it
** started putting files with the "sqlite" name in the c:/temp folder.
-** This annoyed many windows users. Those users would then do a
+** This annoyed many windows users. Those users would then do a
** Google search for "sqlite", find the telephone numbers of the
** developers and call to wake them up at night and complain.
-** For this reason, the default name prefix is changed to be "sqlite"
+** For this reason, the default name prefix is changed to be "sqlite"
** spelled backwards. So the temp files are still identified, but
** anybody smart enough to figure out the code is also likely smart
** enough to know that calling the developer will not help get rid
@@ -8189,9 +7990,9 @@ SQLITE_PRIVATE void sqlite3PCacheSetDefault(void);
** UnlockFile().
**
** LockFile() prevents not just writing but also reading by other processes.
-** A SHARED_LOCK is obtained by locking a single randomly-chosen
-** byte out of a specific range of bytes. The lock byte is obtained at
-** random so two separate readers can probably access the file at the
+** A SHARED_LOCK is obtained by locking a single randomly-chosen
+** byte out of a specific range of bytes. The lock byte is obtained at
+** random so two separate readers can probably access the file at the
** same time, unless they are unlucky and choose the same lock byte.
** An EXCLUSIVE_LOCK is obtained by locking all bytes in the range.
** There can only be one writer. A RESERVED_LOCK is obtained by locking
@@ -8210,7 +8011,7 @@ SQLITE_PRIVATE void sqlite3PCacheSetDefault(void);
** The following #defines specify the range of bytes used for locking.
** SHARED_SIZE is the number of bytes available in the pool from which
** a random byte is selected for a shared lock. The pool of bytes for
-** shared locks begins at SHARED_FIRST.
+** shared locks begins at SHARED_FIRST.
**
** The same locking strategy and
** byte ranges are used for Unix. This leaves open the possiblity of having
@@ -8226,7 +8027,7 @@ SQLITE_PRIVATE void sqlite3PCacheSetDefault(void);
** that all locks will fit on a single page even at the minimum page size.
** PENDING_BYTE defines the beginning of the locks. By default PENDING_BYTE
** is set high so that we don't have to allocate an unused page except
-** for very large databases. But one should test the page skipping logic
+** for very large databases. But one should test the page skipping logic
** by setting PENDING_BYTE low and running the entire regression suite.
**
** Changing the value of PENDING_BYTE results in a subtly incompatible
@@ -8246,8 +8047,8 @@ SQLITE_PRIVATE void sqlite3PCacheSetDefault(void);
*/
SQLITE_PRIVATE int sqlite3OsInit(void);
-/*
-** Functions for accessing sqlite3_file methods
+/*
+** Functions for accessing sqlite3_file methods
*/
SQLITE_PRIVATE int sqlite3OsClose(sqlite3_file*);
SQLITE_PRIVATE int sqlite3OsRead(sqlite3_file*, void*, int amt, i64 offset);
@@ -8262,16 +8063,9 @@ SQLITE_PRIVATE int sqlite3OsFileControl(sqlite3_file*,int,void*);
#define SQLITE_FCNTL_DB_UNCHANGED 0xca093fa0
SQLITE_PRIVATE int sqlite3OsSectorSize(sqlite3_file *id);
SQLITE_PRIVATE int sqlite3OsDeviceCharacteristics(sqlite3_file *id);
-SQLITE_PRIVATE int sqlite3OsShmOpen(sqlite3_file *id);
-SQLITE_PRIVATE int sqlite3OsShmSize(sqlite3_file *id, int, int*);
-SQLITE_PRIVATE int sqlite3OsShmGet(sqlite3_file *id, int, int*, void volatile**);
-SQLITE_PRIVATE int sqlite3OsShmRelease(sqlite3_file *id);
-SQLITE_PRIVATE int sqlite3OsShmLock(sqlite3_file *id, int, int*);
-SQLITE_PRIVATE void sqlite3OsShmBarrier(sqlite3_file *id);
-SQLITE_PRIVATE int sqlite3OsShmClose(sqlite3_file *id, int);
-/*
-** Functions for accessing sqlite3_vfs methods
+/*
+** Functions for accessing sqlite3_vfs methods
*/
SQLITE_PRIVATE int sqlite3OsOpen(sqlite3_vfs *, const char *, sqlite3_file*, int, int *);
SQLITE_PRIVATE int sqlite3OsDelete(sqlite3_vfs *, const char *, int);
@@ -8285,10 +8079,10 @@ SQLITE_PRIVATE void sqlite3OsDlClose(sqlite3_vfs *, void *);
#endif /* SQLITE_OMIT_LOAD_EXTENSION */
SQLITE_PRIVATE int sqlite3OsRandomness(sqlite3_vfs *, int, char *);
SQLITE_PRIVATE int sqlite3OsSleep(sqlite3_vfs *, int);
-SQLITE_PRIVATE int sqlite3OsCurrentTimeInt64(sqlite3_vfs *, sqlite3_int64*);
+SQLITE_PRIVATE int sqlite3OsCurrentTime(sqlite3_vfs *, double*);
/*
-** Convenience functions for opening and closing files using
+** Convenience functions for opening and closing files using
** sqlite3_malloc() to obtain space for the file-handle structure.
*/
SQLITE_PRIVATE int sqlite3OsOpenMalloc(sqlite3_vfs *, const char *, sqlite3_file **, int,int*);
@@ -8396,10 +8190,10 @@ struct Db {
**
** If there are no virtual tables configured in this schema, the
** Schema.db variable is set to NULL. After the first virtual table
-** has been added, it is set to point to the database connection
+** has been added, it is set to point to the database connection
** used to create the connection. Once a virtual table has been
-** added to the Schema structure and the Schema.db variable populated,
-** only that database connection may use the Schema to prepare
+** added to the Schema structure and the Schema.db variable populated,
+** only that database connection may use the Schema to prepare
** statements.
*/
struct Schema {
@@ -8419,8 +8213,8 @@ struct Schema {
};
/*
-** These macros can be used to test, set, or clear bits in the
-** Db.pSchema->flags field.
+** These macros can be used to test, set, or clear bits in the
+** Db.flags field.
*/
#define DbHasProperty(D,I,P) (((D)->aDb[I].pSchema->flags&(P))==(P))
#define DbHasAnyProperty(D,I,P) (((D)->aDb[I].pSchema->flags&(P))!=0)
@@ -8428,7 +8222,7 @@ struct Schema {
#define DbClearProperty(D,I,P) (D)->aDb[I].pSchema->flags&=~(P)
/*
-** Allowed values for the DB.pSchema->flags field.
+** Allowed values for the DB.flags field.
**
** The DB_SchemaLoaded flag is set after the database schema has been
** read into internal hash tables.
@@ -8492,7 +8286,7 @@ struct FuncDefHash {
};
/*
-** Each database connection is an instance of the following structure.
+** Each database is an instance of the following structure.
**
** The sqlite.lastRowid records the last insert rowid generated by an
** insert statement. Inserts on views do not affect its value. Each
@@ -8556,16 +8350,12 @@ struct sqlite3 {
void *pTraceArg; /* Argument to the trace function */
void (*xProfile)(void*,const char*,u64); /* Profiling function */
void *pProfileArg; /* Argument to profile function */
- void *pCommitArg; /* Argument to xCommitCallback() */
+ void *pCommitArg; /* Argument to xCommitCallback() */
int (*xCommitCallback)(void*); /* Invoked at every commit. */
- void *pRollbackArg; /* Argument to xRollbackCallback() */
+ void *pRollbackArg; /* Argument to xRollbackCallback() */
void (*xRollbackCallback)(void*); /* Invoked at every commit. */
void *pUpdateArg;
void (*xUpdateCallback)(void*,int, const char*,const char*,sqlite_int64);
-#ifndef SQLITE_OMIT_WAL
- int (*xWalCallback)(void *, sqlite3 *, const char *, int);
- void *pWalArg;
-#endif
void(*xCollNeeded)(void*,sqlite3*,int eTextRep,const char*);
void(*xCollNeeded16)(void*,sqlite3*,int eTextRep,const void*);
void *pCollNeededArg;
@@ -8606,8 +8396,8 @@ struct sqlite3 {
i64 nDeferredCons; /* Net deferred constraints this transaction. */
#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
- /* The following variables are all protected by the STATIC_MASTER
- ** mutex, not by sqlite3.mutex. They are used by code in notify.c.
+ /* The following variables are all protected by the STATIC_MASTER
+ ** mutex, not by sqlite3.mutex. They are used by code in notify.c.
**
** When X.pUnlockConnection==Y, that means that X is waiting for Y to
** unlock so that it can proceed.
@@ -8644,7 +8434,7 @@ struct sqlite3 {
#define SQLITE_SqlTrace 0x00004000 /* Debug print SQL as it executes */
#define SQLITE_VdbeListing 0x00008000 /* Debug listings of VDBE programs */
#define SQLITE_WriteSchema 0x00010000 /* OK to update SQLITE_MASTER */
-#define SQLITE_NoReadlock 0x00020000 /* Readlocks are omitted when
+#define SQLITE_NoReadlock 0x00020000 /* Readlocks are omitted when
** accessing read-only databases */
#define SQLITE_IgnoreChecks 0x00040000 /* Do not enforce check constraints */
#define SQLITE_ReadUncommitted 0x0080000 /* For shared-cache mode */
@@ -8655,8 +8445,6 @@ struct sqlite3 {
#define SQLITE_ReverseOrder 0x01000000 /* Reverse unordered SELECTs */
#define SQLITE_RecTriggers 0x02000000 /* Enable recursive triggers */
#define SQLITE_ForeignKeys 0x04000000 /* Enforce foreign key constraints */
-#define SQLITE_AutoIndex 0x08000000 /* Enable automatic indexes */
-#define SQLITE_PreferBuiltin 0x10000000 /* Preference to built-in funcs */
/*
** Bits of the sqlite3.flags field that are used by the
@@ -8668,8 +8456,7 @@ struct sqlite3 {
#define SQLITE_IndexSort 0x04 /* Disable indexes for sorting */
#define SQLITE_IndexSearch 0x08 /* Disable indexes for searching */
#define SQLITE_IndexCover 0x10 /* Disable index covering table */
-#define SQLITE_GroupByOrder 0x20 /* Disable GROUPBY cover of ORDERBY */
-#define SQLITE_OptMask 0xff /* Mask of all disablable opts */
+#define SQLITE_OptMask 0x1f /* Mask of all disablable opts */
/*
** Possible values for the sqlite.magic field.
@@ -8717,10 +8504,10 @@ struct FuncDef {
** used to create the initializers for the FuncDef structures.
**
** FUNCTION(zName, nArg, iArg, bNC, xFunc)
-** Used to create a scalar function definition of a function zName
+** Used to create a scalar function definition of a function zName
** implemented by C function xFunc that accepts nArg arguments. The
** value passed as iArg is cast to a (void*) and made available
-** as the user-data (sqlite3_user_data()) for the function. If
+** as the user-data (sqlite3_user_data()) for the function. If
** argument bNC is true, then the SQLITE_FUNC_NEEDCOLL flag is set.
**
** AGGREGATE(zName, nArg, iArg, bNC, xStep, xFinal)
@@ -8730,8 +8517,8 @@ struct FuncDef {
** FUNCTION().
**
** LIKEFUNC(zName, nArg, pArg, flags)
-** Used to create a scalar function definition of a function zName
-** that accepts nArg arguments and is implemented by a call to C
+** Used to create a scalar function definition of a function zName
+** that accepts nArg arguments and is implemented by a call to C
** function likeFunc. Argument pArg is cast to a (void *) and made
** available as the function user-data (sqlite3_user_data()). The
** FuncDef.flags variable is set to the value passed as the flags
@@ -8849,7 +8636,7 @@ struct CollSeq {
**
** These used to have mnemonic name like 'i' for SQLITE_AFF_INTEGER and
** 't' for SQLITE_AFF_TEXT. But we can save a little space and improve
-** the speed a little by numbering the values consecutively.
+** the speed a little by numbering the values consecutively.
**
** But rather than start with 0 or 1, we begin with 'a'. That way,
** when multiple affinity types are concatenated into a string and
@@ -8868,7 +8655,7 @@ struct CollSeq {
/*
** The SQLITE_AFF_MASK values masks off the significant bits of an
-** affinity value.
+** affinity value.
*/
#define SQLITE_AFF_MASK 0x67
@@ -8882,20 +8669,20 @@ struct CollSeq {
/*
** An object of this type is created for each virtual table present in
-** the database schema.
+** the database schema.
**
** If the database schema is shared, then there is one instance of this
** structure for each database connection (sqlite3*) that uses the shared
** schema. This is because each database connection requires its own unique
-** instance of the sqlite3_vtab* handle used to access the virtual table
-** implementation. sqlite3_vtab* handles can not be shared between
-** database connections, even when the rest of the in-memory database
+** instance of the sqlite3_vtab* handle used to access the virtual table
+** implementation. sqlite3_vtab* handles can not be shared between
+** database connections, even when the rest of the in-memory database
** schema is shared, as the implementation often stores the database
** connection handle passed to it via the xConnect() or xCreate() method
** during initialization internally. This database connection handle may
-** then used by the virtual table implementation to access real tables
-** within the database. So that they appear as part of the callers
-** transaction, these accesses need to be made via the same database
+** then used by the virtual table implementation to access real tables
+** within the database. So that they appear as part of the callers
+** transaction, these accesses need to be made via the same database
** connection as that used to execute SQL operations on the virtual table.
**
** All VTable objects that correspond to a single table in a shared
@@ -8907,19 +8694,19 @@ struct CollSeq {
** sqlite3_vtab* handle in the compiled query.
**
** When an in-memory Table object is deleted (for example when the
-** schema is being reloaded for some reason), the VTable objects are not
-** deleted and the sqlite3_vtab* handles are not xDisconnect()ed
+** schema is being reloaded for some reason), the VTable objects are not
+** deleted and the sqlite3_vtab* handles are not xDisconnect()ed
** immediately. Instead, they are moved from the Table.pVTable list to
** another linked list headed by the sqlite3.pDisconnect member of the
-** corresponding sqlite3 structure. They are then deleted/xDisconnected
+** corresponding sqlite3 structure. They are then deleted/xDisconnected
** next time a statement is prepared using said sqlite3*. This is done
** to avoid deadlock issues involving multiple sqlite3.mutex mutexes.
** Refer to comments above function sqlite3VtabUnlockList() for an
** explanation as to why it is safe to add an entry to an sqlite3.pDisconnect
** list without holding the corresponding sqlite3.mutex mutex.
**
-** The memory for objects of this type is always allocated by
-** sqlite3DbMalloc(), using the connection handle stored in VTable.db as
+** The memory for objects of this type is always allocated by
+** sqlite3DbMalloc(), using the connection handle stored in VTable.db as
** the first argument.
*/
struct VTable {
@@ -8954,10 +8741,10 @@ struct VTable {
** in sqlite.aDb[]. 0 is for the main database and 1 is for the file that
** holds temporary tables and indices. If TF_Ephemeral is set
** then the table is stored in a file that is automatically deleted
-** when the VDBE cursor to the table is closed. In this case Table.tnum
+** when the VDBE cursor to the table is closed. In this case Table.tnum
** refers VDBE cursor number that holds the table open, not to the root
** page number. Transient tables are used to hold the results of a
-** sub-query that appears instead of a real table name in the FROM clause
+** sub-query that appears instead of a real table name in the FROM clause
** of a SELECT statement.
*/
struct Table {
@@ -9072,7 +8859,7 @@ struct FKey {
** key is set to NULL. CASCADE means that a DELETE or UPDATE of the
** referenced table row is propagated into the row that holds the
** foreign key.
-**
+**
** The following symbolic values are used to record which type
** of action to take.
*/
@@ -9093,7 +8880,7 @@ struct FKey {
/*
** An instance of the following structure is passed as the first
-** argument to sqlite3VdbeKeyCompare and is used to control the
+** argument to sqlite3VdbeKeyCompare and is used to control the
** comparison of the two index keys.
*/
struct KeyInfo {
@@ -9150,7 +8937,7 @@ struct UnpackedRecord {
** In the Table structure describing Ex1, nCol==3 because there are
** three columns in the table. In the Index structure describing
** Ex2, nColumn==2 since 2 of the 3 columns of Ex1 are indexed.
-** The value of aiColumn is {2, 0}. aiColumn[0]==2 because the
+** The value of aiColumn is {2, 0}. aiColumn[0]==2 because the
** first column to be indexed (c3) has an index of 2 in Ex1.aCol[].
** The second column to be indexed (c1) has an index of 0 in
** Ex1.aCol[], hence Ex2.aiColumn[1]==0.
@@ -9158,7 +8945,7 @@ struct UnpackedRecord {
** The Index.onError field determines whether or not the indexed columns
** must be unique and what to do if they are not. When Index.onError=OE_None,
** it means this is not a unique index. Otherwise it is a unique index
-** and the value of Index.onError indicate the which conflict resolution
+** and the value of Index.onError indicate the which conflict resolution
** algorithm to employ whenever an attempt is made to insert a non-unique
** element.
*/
@@ -9180,7 +8967,7 @@ struct Index {
};
/*
-** Each sample stored in the sqlite_stat2 table is represented in memory
+** Each sample stored in the sqlite_stat2 table is represented in memory
** using a structure of this type.
*/
struct IndexSample {
@@ -9275,9 +9062,9 @@ typedef int ynVar;
** to represent the greater-than-or-equal-to operator in the expression
** tree.
**
-** If the expression is an SQL literal (TK_INTEGER, TK_FLOAT, TK_BLOB,
+** If the expression is an SQL literal (TK_INTEGER, TK_FLOAT, TK_BLOB,
** or TK_STRING), then Expr.token contains the text of the SQL literal. If
-** the expression is a variable (TK_VARIABLE), then Expr.token contains the
+** the expression is a variable (TK_VARIABLE), then Expr.token contains the
** variable name. Finally, if the expression is an SQL function (TK_FUNCTION),
** then Expr.token contains the name of the function.
**
@@ -9288,7 +9075,7 @@ typedef int ynVar;
** a CASE expression or an IN expression of the form "<lhs> IN (<y>, <z>...)".
** Expr.x.pSelect is used if the expression is a sub-select or an expression of
** the form "<lhs> IN (SELECT ...)". If the EP_xIsSelect bit is set in the
-** Expr.flags mask, then Expr.x.pSelect is valid. Otherwise, Expr.x.pList is
+** Expr.flags mask, then Expr.x.pSelect is valid. Otherwise, Expr.x.pList is
** valid.
**
** An expression of the form ID or ID.ID refers to a column in a table.
@@ -9299,8 +9086,8 @@ typedef int ynVar;
** value is also stored in the Expr.iAgg column in the aggregate so that
** it can be accessed after all aggregates are computed.
**
-** If the expression is an unbound variable marker (a question mark
-** character '?' in the original SQL) then the Expr.iTable holds the index
+** If the expression is an unbound variable marker (a question mark
+** character '?' in the original SQL) then the Expr.iTable holds the index
** number for that variable.
**
** If the expression is a subquery then Expr.iColumn holds an integer
@@ -9339,7 +9126,7 @@ struct Expr {
/* If the EP_TokenOnly flag is set in the Expr.flags mask, then no
** space is allocated for the fields below this point. An attempt to
- ** access them will result in a segfault or malfunction.
+ ** access them will result in a segfault or malfunction.
*********************************************************************/
Expr *pLeft; /* Left subnode */
@@ -9410,7 +9197,7 @@ struct Expr {
#endif
/*
-** These macros can be used to test, set, or clear bits in the
+** These macros can be used to test, set, or clear bits in the
** Expr.flags field.
*/
#define ExprHasProperty(E,P) (((E)->flags&(P))==(P))
@@ -9419,8 +9206,8 @@ struct Expr {
#define ExprClearProperty(E,P) (E)->flags&=~(P)
/*
-** Macros to determine the number of bytes required by a normal Expr
-** struct, an Expr struct with the EP_Reduced flag set in Expr.flags
+** Macros to determine the number of bytes required by a normal Expr
+** struct, an Expr struct with the EP_Reduced flag set in Expr.flags
** and an Expr struct with the EP_TokenOnly flag set.
*/
#define EXPR_FULLSIZE sizeof(Expr) /* Full size */
@@ -9428,7 +9215,7 @@ struct Expr {
#define EXPR_TOKENONLYSIZE offsetof(Expr,pLeft) /* Fewer features */
/*
-** Flags passed to the sqlite3ExprDup() function. See the header comment
+** Flags passed to the sqlite3ExprDup() function. See the header comment
** above sqlite3ExprDup() for details.
*/
#define EXPRDUP_REDUCE 0x0001 /* Used reduced-size Expr nodes */
@@ -9520,9 +9307,6 @@ typedef u64 Bitmask;
** and the next table on the list. The parser builds the list this way.
** But sqlite3SrcListShiftJoinType() later shifts the jointypes so that each
** jointype expresses the join between the table and the previous table.
-**
-** In the colUsed field, the high-order bit (bit 63) is set if the table
-** 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 */
@@ -9634,7 +9418,7 @@ struct WhereLevel {
#define WHERE_ORDERBY_MAX 0x0002 /* ORDER BY processing for max() func */
#define WHERE_ONEPASS_DESIRED 0x0004 /* Want to do one-pass UPDATE/DELETE */
#define WHERE_DUPLICATES_OK 0x0008 /* Ok to return a row more than once */
-#define WHERE_OMIT_OPEN 0x0010 /* Table cursors are already open */
+#define WHERE_OMIT_OPEN 0x0010 /* Table cursor are already open */
#define WHERE_OMIT_CLOSE 0x0020 /* Omit close of table & index cursors */
#define WHERE_FORCE_TABLE 0x0040 /* Do not use an index-only search */
#define WHERE_ONETABLE_ONLY 0x0080 /* Only code the 1st table in pTabList */
@@ -9657,7 +9441,6 @@ struct WhereInfo {
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 */
WhereLevel a[1]; /* Information about each nest loop in WHERE */
};
@@ -9670,12 +9453,12 @@ struct WhereInfo {
** pEList corresponds to the result set of a SELECT and is NULL for
** other statements.
**
-** NameContexts can be nested. When resolving names, the inner-most
+** NameContexts can be nested. When resolving names, the inner-most
** context is searched first. If no match is found, the next outer
** context is checked. If there is still no match, the next context
** is checked. This process continues until either a match is found
** or all contexts are check. When a match is found, the nRef member of
-** the context containing the match is incremented.
+** the context containing the match is incremented.
**
** Each subquery gets a new NameContext. The pNext field points to the
** NameContext in the parent query. Thus the process of scanning the
@@ -9780,7 +9563,7 @@ struct SelectDest {
};
/*
-** During code generation of statements that do inserts into AUTOINCREMENT
+** During code generation of statements that do inserts into AUTOINCREMENT
** tables, the following information is attached to the Table.u.autoInc.p
** pointer of each autoincrement table to record some side information that
** the code generator needs. We have to keep per-table autoincrement
@@ -9803,7 +9586,7 @@ struct AutoincInfo {
#endif
/*
-** At least one instance of the following structure is created for each
+** At least one instance of the following structure is created for each
** trigger that may be fired while parsing an INSERT, UPDATE or DELETE
** statement. All such objects are stored in the linked list headed at
** Parse.pTriggerPrg and deleted once statement compilation has been
@@ -9816,7 +9599,7 @@ struct AutoincInfo {
** values for both pTrigger and orconf.
**
** The TriggerPrg.aColmask[0] variable is set to a mask of old.* columns
-** accessed (or set to 0 for triggers fired as a result of INSERT
+** accessed (or set to 0 for triggers fired as a result of INSERT
** statements). Similarly, the TriggerPrg.aColmask[1] variable is set to
** a mask of new.* columns used by the program.
*/
@@ -9838,7 +9621,7 @@ struct TriggerPrg {
** is constant but the second part is reset at the beginning and end of
** each recursion.
**
-** The nTableLock and aTableLock variables are only used if the shared-cache
+** The nTableLock and aTableLock variables are only used if the shared-cache
** feature is enabled (if sqlite3Tsd()->useSharedData is true). They are
** used to store the set of table-locks required by the statement being
** compiled. Function sqlite3TableLock() is used to add entries to the
@@ -9899,7 +9682,6 @@ struct Parse {
u8 eTriggerOp; /* TK_UPDATE, TK_INSERT or TK_DELETE */
u8 eOrconf; /* Default ON CONFLICT policy for trigger steps */
u8 disableTriggers; /* True to disable triggers */
- double nQueryLoop; /* Estimated number of iterations of a query */
/* Above is constant between recursions. Below is reset before and after
** each recursion */
@@ -9957,10 +9739,10 @@ struct AuthContext {
/*
* Each trigger present in the database schema is stored as an instance of
- * struct Trigger.
+ * struct Trigger.
*
* Pointers to instances of struct Trigger are stored in two ways.
- * 1. In the "trigHash" hash table (part of the sqlite3* that represents the
+ * 1. In the "trigHash" hash table (part of the sqlite3* that represents the
* database). This allows Trigger structures to be retrieved by name.
* 2. All triggers associated with a single table form a linked list, using the
* pNext member of struct Trigger. A pointer to the first element of the
@@ -9986,7 +9768,7 @@ struct Trigger {
/*
** A trigger is either a BEFORE or an AFTER trigger. The following constants
-** determine which.
+** determine which.
**
** If there are multiple triggers, you might of some BEFORE and some AFTER.
** In that cases, the constants below can be ORed together.
@@ -9996,15 +9778,15 @@ struct Trigger {
/*
* An instance of struct TriggerStep is used to store a single SQL statement
- * that is a part of a trigger-program.
+ * that is a part of a trigger-program.
*
* Instances of struct TriggerStep are stored in a singly linked list (linked
- * using the "pNext" member) referenced by the "step_list" member of the
+ * using the "pNext" member) referenced by the "step_list" member of the
* associated struct Trigger instance. The first element of the linked list is
* the first step of the trigger-program.
- *
+ *
* The "op" member indicates whether this is a "DELETE", "INSERT", "UPDATE" or
- * "SELECT" statement. The meanings of the other members is determined by the
+ * "SELECT" statement. The meanings of the other members is determined by the
* value of "op" as follows:
*
* (op == TK_INSERT)
@@ -10014,7 +9796,7 @@ struct Trigger {
* target -> A token holding the quoted name of the table to insert into.
* pExprList -> If this is an INSERT INTO ... VALUES ... statement, then
* this stores values to be inserted. Otherwise NULL.
- * pIdList -> If this is an INSERT INTO ... (<column-names>) VALUES ...
+ * pIdList -> If this is an INSERT INTO ... (<column-names>) VALUES ...
* statement, then this stores the column-names to be
* inserted into.
*
@@ -10022,7 +9804,7 @@ struct Trigger {
* target -> A token holding the quoted name of the table to delete from.
* pWhere -> The WHERE clause of the DELETE statement if one is specified.
* Otherwise NULL.
- *
+ *
* (op == TK_UPDATE)
* target -> A token holding the quoted name of the table to update rows of.
* pWhere -> The WHERE clause of the UPDATE statement if one is specified.
@@ -10030,7 +9812,7 @@ struct Trigger {
* pExprList -> A list of the columns to update and the expressions to update
* them to. See sqlite3Update() documentation of "pChanges"
* argument.
- *
+ *
*/
struct TriggerStep {
u8 op; /* One of TK_DELETE, TK_UPDATE, TK_INSERT, TK_SELECT */
@@ -10048,7 +9830,7 @@ struct TriggerStep {
/*
** The following structure contains information used by the sqliteFix...
** routines as they walk the parse tree to make database references
-** explicit.
+** explicit.
*/
typedef struct DbFixer DbFixer;
struct DbFixer {
@@ -10178,15 +9960,6 @@ SQLITE_PRIVATE int sqlite3CantopenError(int);
/*
-** FTS4 is really an extension for FTS3. It is enabled using the
-** SQLITE_ENABLE_FTS3 macro. But to avoid confusion we also all
-** the SQLITE_ENABLE_FTS4 macro to serve as an alisse for SQLITE_ENABLE_FTS3.
-*/
-#if defined(SQLITE_ENABLE_FTS4) && !defined(SQLITE_ENABLE_FTS3)
-# define SQLITE_ENABLE_FTS3
-#endif
-
-/*
** The ctype.h header is needed for non-ASCII systems. It is also
** needed by FTS3 when FTS3 is included in the amalgamation.
*/
@@ -10259,7 +10032,7 @@ SQLITE_PRIVATE int sqlite3MemoryAlarm(void (*)(void*, sqlite3_int64, int), void*
#ifdef SQLITE_USE_ALLOCA
# define sqlite3StackAllocRaw(D,N) alloca(N)
# define sqlite3StackAllocZero(D,N) memset(alloca(N), 0, N)
-# define sqlite3StackFree(D,P)
+# define sqlite3StackFree(D,P)
#else
# define sqlite3StackAllocRaw(D,N) sqlite3DbMallocRaw(D,N)
# define sqlite3StackAllocZero(D,N) sqlite3DbMallocZero(D,N)
@@ -10276,7 +10049,6 @@ SQLITE_PRIVATE const sqlite3_mem_methods *sqlite3MemGetMemsys5(void);
#ifndef SQLITE_MUTEX_OMIT
SQLITE_PRIVATE sqlite3_mutex_methods *sqlite3DefaultMutex(void);
-SQLITE_PRIVATE sqlite3_mutex_methods *sqlite3NoopMutex(void);
SQLITE_PRIVATE sqlite3_mutex *sqlite3MutexAlloc(int);
SQLITE_PRIVATE int sqlite3MutexInit(void);
SQLITE_PRIVATE int sqlite3MutexEnd(void);
@@ -10286,11 +10058,7 @@ SQLITE_PRIVATE int sqlite3StatusValue(int);
SQLITE_PRIVATE void sqlite3StatusAdd(int, int);
SQLITE_PRIVATE void sqlite3StatusSet(int, int);
-#ifndef SQLITE_OMIT_FLOATING_POINT
-SQLITE_PRIVATE int sqlite3IsNaN(double);
-#else
-# define sqlite3IsNaN(X) 0
-#endif
+SQLITE_PRIVATE int sqlite3IsNaN(double);
SQLITE_PRIVATE void sqlite3VXPrintf(StrAccum*, int, const char*, va_list);
#ifndef SQLITE_OMIT_TRACE
@@ -10408,7 +10176,6 @@ SQLITE_PRIVATE void sqlite3Update(Parse*, SrcList*, ExprList*, Expr*, int);
SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(Parse*, SrcList*, Expr*, ExprList**, u16);
SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo*);
SQLITE_PRIVATE int sqlite3ExprCodeGetColumn(Parse*, Table*, int, int, int);
-SQLITE_PRIVATE void sqlite3ExprCodeGetColumnOfTable(Vdbe*, Table*, int, int, int);
SQLITE_PRIVATE void sqlite3ExprCodeMove(Parse*, int, int, int);
SQLITE_PRIVATE void sqlite3ExprCodeCopy(Parse*, int, int, int);
SQLITE_PRIVATE void sqlite3ExprCacheStore(Parse*, int, int, int);
@@ -10435,7 +10202,6 @@ 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 void sqlite3ExprAnalyzeAggregates(NameContext*, Expr*);
SQLITE_PRIVATE void sqlite3ExprAnalyzeAggList(NameContext*,ExprList*);
SQLITE_PRIVATE Vdbe *sqlite3GetVdbe(Parse*);
@@ -10556,7 +10322,7 @@ SQLITE_PRIVATE int sqlite3Utf8Read(const u8*, const u8**);
** Routines to read and write variable-length integers. These used to
** be defined locally, but now we use the varint routines in the util.c
** file. Code should use the MACRO forms below, as the Varint32 versions
-** are coded to assume the single byte case is already handled (which
+** are coded to assume the single byte case is already handled (which
** the MACRO form does).
*/
SQLITE_PRIVATE int sqlite3PutVarint(unsigned char*, u64);
@@ -10609,11 +10375,11 @@ SQLITE_PRIVATE void sqlite3VdbeSetChanges(sqlite3 *, int);
SQLITE_PRIVATE const void *sqlite3ValueText(sqlite3_value*, u8);
SQLITE_PRIVATE int sqlite3ValueBytes(sqlite3_value*, u8);
-SQLITE_PRIVATE void sqlite3ValueSetStr(sqlite3_value*, int, const void *,u8,
+SQLITE_PRIVATE void sqlite3ValueSetStr(sqlite3_value*, int, const void *,u8,
void(*)(void*));
SQLITE_PRIVATE void sqlite3ValueFree(sqlite3_value*);
SQLITE_PRIVATE sqlite3_value *sqlite3ValueNew(sqlite3 *);
-SQLITE_PRIVATE char *sqlite3Utf16to8(sqlite3 *, const void*, int, u8);
+SQLITE_PRIVATE char *sqlite3Utf16to8(sqlite3 *, const void*, int);
#ifdef SQLITE_ENABLE_STAT2
SQLITE_PRIVATE char *sqlite3Utf8to16(sqlite3 *, u8, char *, int, int *);
#endif
@@ -10629,7 +10395,7 @@ SQLITE_PRIVATE int sqlite3PendingByte;
#endif
SQLITE_PRIVATE void sqlite3RootPageMoved(Db*, int, int);
SQLITE_PRIVATE void sqlite3Reindex(Parse*, Token*, Token*);
-SQLITE_PRIVATE void sqlite3AlterFunctions(void);
+SQLITE_PRIVATE void sqlite3AlterFunctions(sqlite3*);
SQLITE_PRIVATE void sqlite3AlterRenameTable(Parse*, SrcList*, Token*);
SQLITE_PRIVATE int sqlite3GetToken(const unsigned char *, int *);
SQLITE_PRIVATE void sqlite3NestedParse(Parse*, const char*, ...);
@@ -10658,7 +10424,7 @@ SQLITE_PRIVATE void sqlite3SchemaFree(void *);
SQLITE_PRIVATE Schema *sqlite3SchemaGet(sqlite3 *, Btree *);
SQLITE_PRIVATE int sqlite3SchemaToIndex(sqlite3 *db, Schema *);
SQLITE_PRIVATE KeyInfo *sqlite3IndexKeyinfo(Parse *, Index *);
-SQLITE_PRIVATE int sqlite3CreateFunc(sqlite3 *, const char *, int, int, void *,
+SQLITE_PRIVATE int sqlite3CreateFunc(sqlite3 *, const char *, int, int, void *,
void (*)(sqlite3_context*,int,sqlite3_value **),
void (*)(sqlite3_context*,int,sqlite3_value **), void (*)(sqlite3_context*));
SQLITE_PRIVATE int sqlite3ApiExit(sqlite3 *db, int);
@@ -10707,7 +10473,7 @@ SQLITE_PRIVATE int sqlite3Utf8To8(unsigned char*);
# define sqlite3VtabRollback(X)
# define sqlite3VtabCommit(X)
# define sqlite3VtabInSync(db) 0
-# define sqlite3VtabLock(X)
+# define sqlite3VtabLock(X)
# define sqlite3VtabUnlock(X)
# define sqlite3VtabUnlockList(X)
#else
@@ -10738,15 +10504,12 @@ SQLITE_PRIVATE void sqlite3ExprListCheckLength(Parse*, ExprList*, const char*);
SQLITE_PRIVATE CollSeq *sqlite3BinaryCompareCollSeq(Parse *, Expr *, Expr *);
SQLITE_PRIVATE int sqlite3TempInMemory(const sqlite3*);
SQLITE_PRIVATE VTable *sqlite3GetVTable(sqlite3*, Table*);
-SQLITE_PRIVATE const char *sqlite3JournalModename(int);
-SQLITE_PRIVATE int sqlite3Checkpoint(sqlite3*, int);
-SQLITE_PRIVATE int sqlite3WalDefaultHook(void*,sqlite3*,const char*,int);
/* Declarations for functions in fkey.c. All of these are replaced by
** no-op macros if OMIT_FOREIGN_KEY is defined. In this case no foreign
** key functionality is available. If OMIT_TRIGGER is defined but
** OMIT_FOREIGN_KEY is not, only some of the functions are no-oped. In
-** this case foreign keys are parsed, but no other functionality is
+** this case foreign keys are parsed, but no other functionality is
** provided (enforcement of FK constraints requires the triggers sub-system).
*/
#if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER)
@@ -10836,7 +10599,7 @@ SQLITE_PRIVATE void sqlite3ParserTrace(FILE*, char *);
/*
** If the SQLITE_ENABLE IOTRACE exists then the global variable
** sqlite3IoTrace is a pointer to a printf-like routine used to
-** print I/O tracing messages.
+** print I/O tracing messages.
*/
#ifdef SQLITE_ENABLE_IOTRACE
# define IOTRACE(A) if( sqlite3IoTrace ){ sqlite3IoTrace A; }
@@ -10847,46 +10610,7 @@ SQLITE_PRIVATE void (*sqlite3IoTrace)(const char*,...);
# define sqlite3VdbeIOTraceSql(X)
#endif
-/*
-** These routines are available for the mem2.c debugging memory allocator
-** only. They are used to verify that different "types" of memory
-** allocations are properly tracked by the system.
-**
-** sqlite3MemdebugSetType() sets the "type" of an allocation to one of
-** the MEMTYPE_* macros defined below. The type must be a bitmask with
-** a single bit set.
-**
-** sqlite3MemdebugHasType() returns true if any of the bits in its second
-** argument match the type set by the previous sqlite3MemdebugSetType().
-** sqlite3MemdebugHasType() is intended for use inside assert() statements.
-** For example:
-**
-** assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) );
-**
-** Perhaps the most important point is the difference between MEMTYPE_HEAP
-** and MEMTYPE_DB. If an allocation is MEMTYPE_DB, that means it might have
-** been allocated by lookaside, except the allocation was too large or
-** lookaside was already full. It is important to verify that allocations
-** that might have been satisfied by lookaside are not passed back to
-** non-lookaside free() routines. Asserts such as the example above are
-** placed on the non-lookaside free() routines to verify this constraint.
-**
-** All of this is no-op for a production build. It only comes into
-** play when the SQLITE_MEMDEBUG compile-time option is used.
-*/
-#ifdef SQLITE_MEMDEBUG
-SQLITE_PRIVATE void sqlite3MemdebugSetType(void*,u8);
-SQLITE_PRIVATE int sqlite3MemdebugHasType(void*,u8);
-#else
-# define sqlite3MemdebugSetType(X,Y) /* no-op */
-# define sqlite3MemdebugHasType(X,Y) 1
#endif
-#define MEMTYPE_HEAP 0x01 /* General heap allocations */
-#define MEMTYPE_DB 0x02 /* Associated with a database connection */
-#define MEMTYPE_SCRATCH 0x04 /* Scratch allocations */
-#define MEMTYPE_PCACHE 0x08 /* Page cache allocations */
-
-#endif /* _SQLITEINT_H_ */
/************** End of sqliteInt.h *******************************************/
/************** Begin file global.c ******************************************/
@@ -10906,7 +10630,7 @@ SQLITE_PRIVATE int sqlite3MemdebugHasType(void*,u8);
*/
/* An array to map all upper-case characters into their corresponding
-** lower-case character.
+** 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
@@ -10972,7 +10696,7 @@ SQLITE_PRIVATE const unsigned char sqlite3UpperToLower[] = {
** Standard function tolower() is implemented using the sqlite3UpperToLower[]
** array. tolower() is used more often than toupper() by SQLite.
**
-** Bit 0x40 is set if the character non-alphanumeric and can be used in an
+** 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
** part of an identifier is 0x46.
@@ -11091,401 +10815,11 @@ SQLITE_PRIVATE int sqlite3PendingByte = 0x40000000;
** Properties of opcodes. The OPFLG_INITIALIZER macro is
** created by mkopcodeh.awk during compilation. Data is obtained
** from the comments following the "case OP_xxxx:" statements in
-** the vdbe.c file.
+** the vdbe.c file.
*/
SQLITE_PRIVATE const unsigned char sqlite3OpcodeProperty[] = OPFLG_INITIALIZER;
/************** End of global.c **********************************************/
-/************** Begin file ctime.c *******************************************/
-/*
-** 2010 February 23
-**
-** 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 routines used to report what compile-time options
-** SQLite was built with.
-*/
-
-#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
-
-
-/*
-** 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.
-*/
-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)
-
-#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
-#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_STAT2
- "ENABLE_STAT2",
-#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
-#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_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_COMPILEOPTION_DIAGS
- "OMIT_COMPILEOPTION_DIAGS",
-#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_GLOBALRECOVER
- "OMIT_GLOBALRECOVER",
-#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_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_SECURE_DELETE
- "SECURE_DELETE",
-#endif
-#ifdef SQLITE_SMALL_STACK
- "SMALL_STACK",
-#endif
-#ifdef SQLITE_SOUNDEX
- "SOUNDEX",
-#endif
-#ifdef SQLITE_TCL
- "TCL",
-#endif
-#ifdef SQLITE_TEMP_STORE
- "TEMP_STORE=" CTIMEOPT_VAL(SQLITE_TEMP_STORE),
-#endif
-#ifdef SQLITE_TEST
- "TEST",
-#endif
-#ifdef SQLITE_THREADSAFE
- "THREADSAFE=" CTIMEOPT_VAL(SQLITE_THREADSAFE),
-#endif
-#ifdef SQLITE_USE_ALLOCA
- "USE_ALLOCA",
-#endif
-#ifdef SQLITE_ZERO_MALLOC
- "ZERO_MALLOC"
-#endif
-};
-
-/*
-** 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);
-
- /* 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)
- && ( (azCompileOpt[i][n]==0) || (azCompileOpt[i][n]=='=') ) ) return 1;
- }
- return 0;
-}
-
-/*
-** 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];
- }
- return 0;
-}
-
-#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */
-
-/************** End of ctime.c ***********************************************/
/************** Begin file status.c ******************************************/
/*
** 2008 June 18
@@ -11600,26 +10934,6 @@ SQLITE_API int sqlite3_db_status(
}
break;
}
-
- /*
- ** 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;
- for(i=0; i<db->nDb; i++){
- Btree *pBt = db->aDb[i].pBt;
- if( pBt ){
- Pager *pPager = sqlite3BtreePager(pBt);
- totalUsed += sqlite3PagerMemUsed(pPager);
- }
- }
- *pCurrent = totalUsed;
- *pHighwater = 0;
- break;
- }
default: {
return SQLITE_ERROR;
}
@@ -11641,7 +10955,7 @@ SQLITE_API int sqlite3_db_status(
**
*************************************************************************
** This file contains the C functions that implement date and time
-** functions for SQLite.
+** functions for SQLite.
**
** There is only one exported symbol in this file - the function
** sqlite3RegisterDateTimeFunctions() found at the bottom of the file.
@@ -11650,7 +10964,7 @@ SQLITE_API int sqlite3_db_status(
** 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.
+** calendar system.
**
** 1970-01-01 00:00:00 is JD 2440587.5
** 2000-01-01 00:00:00 is JD 2451544.5
@@ -11680,14 +10994,14 @@ SQLITE_API int sqlite3_db_status(
/*
** 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
+** 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
+** already, check for an MSVC build environment that provides
** localtime_s().
*/
#if !defined(HAVE_LOCALTIME_R) && !defined(HAVE_LOCALTIME_S) && \
@@ -11942,8 +11256,10 @@ static int parseYyyyMmDd(const char *zDate, DateTime *p){
** Set the time to the current time reported by the VFS
*/
static void setDateTimeToCurrent(sqlite3_context *context, DateTime *p){
+ double r;
sqlite3 *db = sqlite3_context_db_handle(context);
- sqlite3OsCurrentTimeInt64(db->pVfs, &p->iJD);
+ sqlite3OsCurrentTime(db->pVfs, &r);
+ p->iJD = (sqlite3_int64)(r*86400000.0 + 0.5);
p->validJD = 1;
}
@@ -11954,7 +11270,7 @@ static void setDateTimeToCurrent(sqlite3_context *context, DateTime *p){
** The following are acceptable forms for the input string:
**
** YYYY-MM-DD HH:MM:SS.FFF +/-HH:MM
-** DDDD.DD
+** DDDD.DD
** now
**
** In the first form, the +/-HH:MM is always optional. The fractional
@@ -11964,8 +11280,8 @@ static void setDateTimeToCurrent(sqlite3_context *context, DateTime *p){
** as there is a year and date.
*/
static int parseDateOrTime(
- sqlite3_context *context,
- const char *zDate,
+ sqlite3_context *context,
+ const char *zDate,
DateTime *p
){
int isRealNum; /* Return from sqlite3IsNumber(). Not used */
@@ -12341,9 +11657,9 @@ static int parseModifier(const char *zMod, DateTime *p){
** then assume a default value of "now" for argv[0].
*/
static int isDate(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv,
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv,
DateTime *p
){
int i;
@@ -12664,15 +11980,22 @@ static void currentTimeFunc(
time_t t;
char *zFormat = (char *)sqlite3_user_data(context);
sqlite3 *db;
- sqlite3_int64 iT;
+ double rT;
char zBuf[20];
UNUSED_PARAMETER(argc);
UNUSED_PARAMETER(argv);
db = sqlite3_context_db_handle(context);
- sqlite3OsCurrentTimeInt64(db->pVfs, &iT);
- t = iT/1000 - 10000*(sqlite3_int64)21086676;
+ sqlite3OsCurrentTime(db->pVfs, &rT);
+#ifndef SQLITE_OMIT_FLOATING_POINT
+ t = 86400.0*(rT - 2440587.5) + 0.5;
+#else
+ /* without floating point support, rT will have
+ ** already lost fractional day precision.
+ */
+ t = 86400 * (rT - 2440587) - 43200;
+#endif
#ifdef HAVE_GMTIME_R
{
struct tm sNow;
@@ -12711,8 +12034,8 @@ SQLITE_PRIVATE void sqlite3RegisterDateTimeFunctions(void){
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),
+ STR_FUNCTION(current_timestamp, 0, "%Y-%m-%d", 0, currentTimeFunc),
+ STR_FUNCTION(current_date, 0, "%Y-%m-%d %H:%M:%S", 0, currentTimeFunc),
#endif
};
int i;
@@ -12751,7 +12074,7 @@ SQLITE_PRIVATE void sqlite3RegisterDateTimeFunctions(void){
** 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
+** The following functions are instrumented for malloc() failure
** testing:
**
** sqlite3OsOpen()
@@ -12825,46 +12148,25 @@ SQLITE_PRIVATE int sqlite3OsSectorSize(sqlite3_file *id){
SQLITE_PRIVATE int sqlite3OsDeviceCharacteristics(sqlite3_file *id){
return id->pMethods->xDeviceCharacteristics(id);
}
-SQLITE_PRIVATE int sqlite3OsShmOpen(sqlite3_file *id){
- return id->pMethods->xShmOpen(id);
-}
-SQLITE_PRIVATE int sqlite3OsShmSize(sqlite3_file *id, int reqSize, int *pNewSize){
- return id->pMethods->xShmSize(id, reqSize, pNewSize);
-}
-SQLITE_PRIVATE int sqlite3OsShmGet(sqlite3_file *id,int reqSize,int *pSize,void volatile **pp){
- return id->pMethods->xShmGet(id, reqSize, pSize, pp);
-}
-SQLITE_PRIVATE int sqlite3OsShmRelease(sqlite3_file *id){
- return id->pMethods->xShmRelease(id);
-}
-SQLITE_PRIVATE int sqlite3OsShmLock(sqlite3_file *id, int desiredLock, int *pGotLock){
- return id->pMethods->xShmLock(id, desiredLock, pGotLock);
-}
-SQLITE_PRIVATE void sqlite3OsShmBarrier(sqlite3_file *id){
- id->pMethods->xShmBarrier(id);
-}
-SQLITE_PRIVATE int sqlite3OsShmClose(sqlite3_file *id, int deleteFlag){
- return id->pMethods->xShmClose(id, deleteFlag);
-}
/*
** 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,
+ sqlite3_vfs *pVfs,
+ const char *zPath,
+ sqlite3_file *pFile,
+ int flags,
int *pFlagsOut
){
int rc;
DO_OS_MALLOC_TEST(0);
- /* 0x7f3f is a mask of SQLITE_OPEN_ flags that are valid to be passed
+ /* 0x7f1f 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 & 0x7f3f, pFlagsOut);
+ rc = pVfs->xOpen(pVfs, zPath, pFile, flags & 0x7f1f, pFlagsOut);
assert( rc==SQLITE_OK || pFile->pMethods==0 );
return rc;
}
@@ -12872,18 +12174,18 @@ SQLITE_PRIVATE int sqlite3OsDelete(sqlite3_vfs *pVfs, const char *zPath, int dir
return pVfs->xDelete(pVfs, zPath, dirSync);
}
SQLITE_PRIVATE int sqlite3OsAccess(
- sqlite3_vfs *pVfs,
- const char *zPath,
- int flags,
+ 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,
+ sqlite3_vfs *pVfs,
+ const char *zPath,
+ int nPathOut,
char *zPathOut
){
zPathOut[0] = 0;
@@ -12909,22 +12211,14 @@ SQLITE_PRIVATE int sqlite3OsRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufO
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;
- 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 sqlite3OsCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){
+ return pVfs->xCurrentTime(pVfs, pTimeOut);
}
SQLITE_PRIVATE int sqlite3OsOpenMalloc(
- sqlite3_vfs *pVfs,
- const char *zFile,
- sqlite3_file **ppFile,
+ sqlite3_vfs *pVfs,
+ const char *zFile,
+ sqlite3_file **ppFile,
int flags,
int *pOutFlags
){
@@ -13066,17 +12360,17 @@ SQLITE_API int sqlite3_vfs_unregister(sqlite3_vfs *pVfs){
**
*************************************************************************
**
-** This file contains code to support the concept of "benign"
+** 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).
+** 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
+** 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.
*/
@@ -13295,6 +12589,7 @@ static void *sqlite3MemRealloc(void *pPrior, int nByte){
sqlite3_int64 *p = (sqlite3_int64*)pPrior;
assert( pPrior!=0 && nByte>0 );
nByte = ROUND8(nByte);
+ p = (sqlite3_int64*)pPrior;
p--;
p = realloc(p, nByte+8 );
if( p ){
@@ -13413,8 +12708,7 @@ struct MemBlockHdr {
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 */
+ short nTitle; /* Bytes of title; includes '\0' */
int iForeGuard; /* Guard word for sanity */
};
@@ -13436,7 +12730,7 @@ struct MemBlockHdr {
** when this module is combined with other in the amalgamation.
*/
static struct {
-
+
/*
** Mutex to control access to the memory allocation subsystem.
*/
@@ -13447,7 +12741,7 @@ static struct {
*/
struct MemBlockHdr *pFirst;
struct MemBlockHdr *pLast;
-
+
/*
** The number of levels of backtrace to save in new allocations.
*/
@@ -13460,7 +12754,7 @@ static struct {
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.
*/
@@ -13519,7 +12813,7 @@ static struct MemBlockHdr *sqlite3MemsysGetHeader(void *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
+ ** to rounding up to an 8 byte boundary to ensure
** they haven't been overwritten.
*/
while( nReserve-- > p->iSize ) assert( pU8[nReserve]==0x65 );
@@ -13622,7 +12916,6 @@ static void *sqlite3MemMalloc(int nByte){
}
mem.pLast = pHdr;
pHdr->iForeGuard = FOREGUARD;
- pHdr->eType = MEMTYPE_HEAP;
pHdr->nBacktraceSlots = mem.nBacktrace;
pHdr->nTitle = mem.nTitle;
if( mem.nBacktrace ){
@@ -13648,7 +12941,7 @@ static void *sqlite3MemMalloc(int nByte){
p = (void*)pInt;
}
sqlite3_mutex_leave(mem.mutex);
- return p;
+ return p;
}
/*
@@ -13658,8 +12951,7 @@ static void sqlite3MemFree(void *pPrior){
struct MemBlockHdr *pHdr;
void **pBt;
char *z;
- assert( sqlite3GlobalConfig.bMemstat || sqlite3GlobalConfig.bCoreMutex==0
- || mem.mutex!=0 );
+ assert( sqlite3GlobalConfig.bMemstat || mem.mutex!=0 );
pHdr = sqlite3MemsysGetHeader(pPrior);
pBt = (void**)pHdr;
pBt -= pHdr->nBacktraceSlots;
@@ -13684,15 +12976,15 @@ static void sqlite3MemFree(void *pPrior){
randomFill(z, sizeof(void*)*pHdr->nBacktraceSlots + sizeof(*pHdr) +
pHdr->iSize + sizeof(int) + pHdr->nTitle);
free(z);
- sqlite3_mutex_leave(mem.mutex);
+ 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
+** 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.
*/
@@ -13731,47 +13023,6 @@ SQLITE_PRIVATE void sqlite3MemSetDefault(void){
}
/*
-** Set the "type" of an allocation.
-*/
-SQLITE_PRIVATE void sqlite3MemdebugSetType(void *p, u8 eType){
- if( p ){
- 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.
-**
-** This routine is designed for use within an assert() statement, to
-** verify the type of an allocation. For example:
-**
-** assert( sqlite3MemdebugHasType(p, MEMTYPE_DB) );
-*/
-SQLITE_PRIVATE int sqlite3MemdebugHasType(void *p, u8 eType){
- int rc = 1;
- if( p ){
- struct MemBlockHdr *pHdr;
- pHdr = sqlite3MemsysGetHeader(p);
- assert( pHdr->iForeGuard==FOREGUARD ); /* Allocation is valid */
- assert( (pHdr->eType & (pHdr->eType-1))==0 ); /* Only one type bit set */
- if( (pHdr->eType&eType)==0 ){
- void **pBt;
- pBt = (void**)pHdr;
- pBt -= pHdr->nBacktraceSlots;
- backtrace_symbols_fd(pBt, pHdr->nBacktrace, fileno(stderr));
- fprintf(stderr, "\n");
- rc = 0;
- }
- }
- 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.
@@ -13810,7 +13061,7 @@ SQLITE_PRIVATE void sqlite3MemdebugSync(){
}
/*
-** Open the file indicated and write a log of all unfreed memory
+** Open the file indicated and write a log of all unfreed memory
** allocations into that log.
*/
SQLITE_PRIVATE void sqlite3MemdebugDump(const char *zFilename){
@@ -13827,7 +13078,7 @@ SQLITE_PRIVATE void sqlite3MemdebugDump(const char *zFilename){
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",
+ fprintf(out, "**** %lld bytes at %p from %s ****\n",
pHdr->iSize, &pHdr[1], pHdr->nTitle ? z : "???");
if( pHdr->nBacktrace ){
fflush(out);
@@ -13840,7 +13091,7 @@ SQLITE_PRIVATE void sqlite3MemdebugDump(const char *zFilename){
fprintf(out, "COUNTS:\n");
for(i=0; i<NCSIZE-1; i++){
if( mem.nAlloc[i] ){
- fprintf(out, " %5d: %10d %10d %10d\n",
+ fprintf(out, " %5d: %10d %10d %10d\n",
i*8, mem.nAlloc[i], mem.nCurrent[i], mem.mxCurrent[i]);
}
}
@@ -13881,12 +13132,12 @@ SQLITE_PRIVATE int sqlite3MemdebugMallocCount(){
**
*************************************************************************
** This file contains the C functions that implement a memory
-** allocation subsystem for use by SQLite.
+** allocation subsystem for use by 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()
+** 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.
@@ -13916,8 +13167,8 @@ SQLITE_PRIVATE int sqlite3MemdebugMallocCount(){
#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 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
@@ -13940,10 +13191,10 @@ SQLITE_PRIVATE int sqlite3MemdebugMallocCount(){
**
** 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[]
+** 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
+** 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.
*/
@@ -13979,12 +13230,12 @@ static SQLITE_WSD struct Mem3Global {
** 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.
*/
@@ -14000,7 +13251,7 @@ static SQLITE_WSD struct Mem3Global {
u32 szMaster;
/*
- ** Array of lists of free blocks according to the block size
+ ** Array of lists of free blocks according to the block size
** for smaller chunks, or a hash on the block size for larger
** chunks.
*/
@@ -14031,7 +13282,7 @@ static void memsys3UnlinkFromList(u32 i, u32 *pRoot){
}
/*
-** Unlink the chunk at index i from
+** Unlink the chunk at index i from
** whatever list is currently a member of.
*/
static void memsys3Unlink(u32 i){
@@ -14115,8 +13366,8 @@ static void memsys3OutOfMemory(int nByte){
/*
-** Chunk i is a free chunk that has been unlinked. Adjust its
-** size parameters for check-out and return a pointer to the
+** 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){
@@ -14169,12 +13420,12 @@ static void *memsys3FromMaster(u32 nBlock){
/*
** *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[].
+** mem3.aiSmall[] or mem3.aiHash[].
**
** This routine examines all entries on the given list and tries
-** to coalesce each entries with adjacent free chunks.
+** to coalesce each entries with adjacent free chunks.
**
-** If it sees a chunk that is larger than mem3.iMaster, it replaces
+** 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
@@ -14265,7 +13516,7 @@ static void *memsys3MallocUnsafe(int nByte){
}
- /* STEP 3:
+ /* 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
@@ -14372,7 +13623,7 @@ static void *memsys3Malloc(int nBytes){
memsys3Enter();
p = memsys3MallocUnsafe(nBytes);
memsys3Leave();
- return (void*)p;
+ return (void*)p;
}
/*
@@ -14453,7 +13704,7 @@ static void memsys3Shutdown(void *NotUsed){
/*
-** Open the file indicated and write a log of all unfreed memory
+** Open the file indicated and write a log of all unfreed memory
** allocations into that log.
*/
SQLITE_PRIVATE void sqlite3Memsys3Dump(const char *zFilename){
@@ -14504,7 +13755,7 @@ SQLITE_PRIVATE void sqlite3Memsys3Dump(const char *zFilename){
fprintf(out, " %p(%d)", &mem3.aPool[j],
(mem3.aPool[j-1].u.hdr.size4x/4)*8-8);
}
- fprintf(out, "\n");
+ fprintf(out, "\n");
}
for(i=0; i<N_HASH; i++){
if( mem3.aiHash[i]==0 ) continue;
@@ -14513,7 +13764,7 @@ SQLITE_PRIVATE void sqlite3Memsys3Dump(const char *zFilename){
fprintf(out, " %p(%d)", &mem3.aPool[j],
(mem3.aPool[j-1].u.hdr.size4x/4)*8-8);
}
- fprintf(out, "\n");
+ fprintf(out, "\n");
}
fprintf(out, "master=%d\n", mem3.iMaster);
fprintf(out, "nowUsed=%d\n", mem3.nPool*8 - mem3.szMaster*8);
@@ -14530,7 +13781,7 @@ SQLITE_PRIVATE void sqlite3Memsys3Dump(const char *zFilename){
}
/*
-** This routine is the only routine in this file with external
+** This routine is the only routine in this file with external
** linkage.
**
** Populate the low-level memory allocation function pointers in
@@ -14570,12 +13821,12 @@ SQLITE_PRIVATE const sqlite3_mem_methods *sqlite3MemGetMemsys3(void){
**
*************************************************************************
** This file contains the C functions that implement a memory
-** allocation subsystem for use by SQLite.
+** 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()
+** 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.
@@ -14595,12 +13846,12 @@ SQLITE_PRIVATE const sqlite3_mem_methods *sqlite3MemGetMemsys3(void){
** 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
+** 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
@@ -14610,7 +13861,7 @@ SQLITE_PRIVATE const sqlite3_mem_methods *sqlite3MemGetMemsys3(void){
*/
/*
-** This version of the memory allocator is used only when
+** This version of the memory allocator is used only when
** SQLITE_ENABLE_MEMSYS5 is defined.
*/
#ifdef SQLITE_ENABLE_MEMSYS5
@@ -14655,7 +13906,7 @@ static SQLITE_WSD struct Mem5Global {
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.
*/
@@ -14672,7 +13923,7 @@ static SQLITE_WSD struct Mem5Global {
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.
@@ -14770,7 +14021,7 @@ static int memsys5Size(void *p){
/*
** Find the first entry on the freelist iLogsize. Unlink that
-** entry and return its index.
+** entry and return its index.
*/
static int memsys5UnlinkFirst(int iLogsize){
int i;
@@ -14863,7 +14114,7 @@ static void memsys5FreeUnsafe(void *pOld){
u32 size, iLogsize;
int iBlock;
- /* Set iBlock to the index of the block pointed to by pOld in
+ /* 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;
@@ -14922,7 +14173,7 @@ static void *memsys5Malloc(int nBytes){
p = memsys5MallocUnsafe(nBytes);
memsys5Leave();
}
- return (void*)p;
+ return (void*)p;
}
/*
@@ -14935,14 +14186,14 @@ static void memsys5Free(void *pPrior){
assert( pPrior!=0 );
memsys5Enter();
memsys5FreeUnsafe(pPrior);
- memsys5Leave();
+ memsys5Leave();
}
/*
** Change the size of an existing memory allocation.
**
** The outer layer memory allocator prevents this routine from
-** being called with pPrior==0.
+** 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
@@ -15076,7 +14327,7 @@ static void memsys5Shutdown(void *NotUsed){
#ifdef SQLITE_TEST
/*
-** Open the file indicated and write a log of all unfreed memory
+** Open the file indicated and write a log of all unfreed memory
** allocations into that log.
*/
SQLITE_PRIVATE void sqlite3Memsys5Dump(const char *zFilename){
@@ -15118,7 +14369,7 @@ SQLITE_PRIVATE void sqlite3Memsys5Dump(const char *zFilename){
#endif
/*
-** This routine is the only routine in this file with external
+** 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.
*/
@@ -15170,28 +14421,25 @@ static SQLITE_WSD int mutexIsInit = 0;
/*
** Initialize the mutex system.
*/
-SQLITE_PRIVATE int sqlite3MutexInit(void){
+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 *pFrom;
- sqlite3_mutex_methods *pTo = &sqlite3GlobalConfig.mutex;
+ if( sqlite3GlobalConfig.bCoreMutex ){
+ 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 *pFrom = sqlite3DefaultMutex();
+ 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;
}
- 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();
}
- rc = sqlite3GlobalConfig.mutex.xMutexInit();
#ifdef SQLITE_DEBUG
GLOBAL(int, mutexIsInit) = 1;
@@ -15268,7 +14516,7 @@ SQLITE_API int sqlite3_mutex_try(sqlite3_mutex *p){
/*
** The sqlite3_mutex_leave() routine exits a mutex that was previously
-** entered by the same thread. The behavior is undefined if the mutex
+** 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.
*/
@@ -15323,14 +14571,15 @@ SQLITE_API int sqlite3_mutex_notheld(sqlite3_mutex *p){
** called correctly.
*/
-#ifndef SQLITE_MUTEX_OMIT
-#ifndef SQLITE_DEBUG
+#if defined(SQLITE_MUTEX_NOOP) && !defined(SQLITE_DEBUG)
/*
** Stub routines for all mutex methods.
**
** This routines provide no mutual exclusion or error checking.
*/
+static int noopMutexHeld(sqlite3_mutex *p){ return 1; }
+static int noopMutexNotheld(sqlite3_mutex *p){ return 1; }
static int noopMutexInit(void){ return SQLITE_OK; }
static int noopMutexEnd(void){ return SQLITE_OK; }
static sqlite3_mutex *noopMutexAlloc(int id){ return (sqlite3_mutex*)8; }
@@ -15339,7 +14588,7 @@ static void noopMutexEnter(sqlite3_mutex *p){ return; }
static int noopMutexTry(sqlite3_mutex *p){ return SQLITE_OK; }
static void noopMutexLeave(sqlite3_mutex *p){ return; }
-SQLITE_PRIVATE sqlite3_mutex_methods *sqlite3NoopMutex(void){
+SQLITE_PRIVATE sqlite3_mutex_methods *sqlite3DefaultMutex(void){
static sqlite3_mutex_methods sMutex = {
noopMutexInit,
noopMutexEnd,
@@ -15349,15 +14598,15 @@ SQLITE_PRIVATE sqlite3_mutex_methods *sqlite3NoopMutex(void){
noopMutexTry,
noopMutexLeave,
- 0,
- 0,
+ noopMutexHeld,
+ noopMutexNotheld
};
return &sMutex;
}
-#endif /* !SQLITE_DEBUG */
+#endif /* defined(SQLITE_MUTEX_NOOP) && !defined(SQLITE_DEBUG) */
-#ifdef SQLITE_DEBUG
+#if defined(SQLITE_MUTEX_NOOP) && defined(SQLITE_DEBUG)
/*
** In this implementation, error checking is provided for testing
** and debugging purposes. The mutexes still do not provide any
@@ -15367,21 +14616,19 @@ SQLITE_PRIVATE sqlite3_mutex_methods *sqlite3NoopMutex(void){
/*
** The mutex object
*/
-typedef struct sqlite3_debug_mutex {
+struct sqlite3_mutex {
int id; /* The mutex type */
int cnt; /* Number of entries without a matching leave */
-} sqlite3_debug_mutex;
+};
/*
** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are
** intended for use inside assert() statements.
*/
-static int debugMutexHeld(sqlite3_mutex *pX){
- sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX;
+static int debugMutexHeld(sqlite3_mutex *p){
return p==0 || p->cnt>0;
}
-static int debugMutexNotheld(sqlite3_mutex *pX){
- sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX;
+static int debugMutexNotheld(sqlite3_mutex *p){
return p==0 || p->cnt==0;
}
@@ -15394,11 +14641,11 @@ static int debugMutexEnd(void){ return SQLITE_OK; }
/*
** 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.
+** that means that a mutex could not be allocated.
*/
static sqlite3_mutex *debugMutexAlloc(int id){
- static sqlite3_debug_mutex aStatic[6];
- sqlite3_debug_mutex *pNew = 0;
+ static sqlite3_mutex aStatic[6];
+ sqlite3_mutex *pNew = 0;
switch( id ){
case SQLITE_MUTEX_FAST:
case SQLITE_MUTEX_RECURSIVE: {
@@ -15417,14 +14664,13 @@ static sqlite3_mutex *debugMutexAlloc(int id){
break;
}
}
- return (sqlite3_mutex*)pNew;
+ return pNew;
}
/*
** This routine deallocates a previously allocated mutex.
*/
-static void debugMutexFree(sqlite3_mutex *pX){
- sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX;
+static void debugMutexFree(sqlite3_mutex *p){
assert( p->cnt==0 );
assert( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE );
sqlite3_free(p);
@@ -15441,14 +14687,12 @@ static void debugMutexFree(sqlite3_mutex *pX){
** can enter. If the same thread tries to enter any other kind of mutex
** more than once, the behavior is undefined.
*/
-static void debugMutexEnter(sqlite3_mutex *pX){
- sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX;
- assert( p->id==SQLITE_MUTEX_RECURSIVE || debugMutexNotheld(pX) );
+static void debugMutexEnter(sqlite3_mutex *p){
+ assert( p->id==SQLITE_MUTEX_RECURSIVE || debugMutexNotheld(p) );
p->cnt++;
}
-static int debugMutexTry(sqlite3_mutex *pX){
- sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX;
- assert( p->id==SQLITE_MUTEX_RECURSIVE || debugMutexNotheld(pX) );
+static int debugMutexTry(sqlite3_mutex *p){
+ assert( p->id==SQLITE_MUTEX_RECURSIVE || debugMutexNotheld(p) );
p->cnt++;
return SQLITE_OK;
}
@@ -15459,14 +14703,13 @@ static int debugMutexTry(sqlite3_mutex *pX){
** is undefined if the mutex is not currently entered or
** is not currently allocated. SQLite will never do either.
*/
-static void debugMutexLeave(sqlite3_mutex *pX){
- sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX;
- assert( debugMutexHeld(pX) );
+static void debugMutexLeave(sqlite3_mutex *p){
+ assert( debugMutexHeld(p) );
p->cnt--;
- assert( p->id==SQLITE_MUTEX_RECURSIVE || debugMutexNotheld(pX) );
+ assert( p->id==SQLITE_MUTEX_RECURSIVE || debugMutexNotheld(p) );
}
-SQLITE_PRIVATE sqlite3_mutex_methods *sqlite3NoopMutex(void){
+SQLITE_PRIVATE sqlite3_mutex_methods *sqlite3DefaultMutex(void){
static sqlite3_mutex_methods sMutex = {
debugMutexInit,
debugMutexEnd,
@@ -15482,18 +14725,7 @@ SQLITE_PRIVATE sqlite3_mutex_methods *sqlite3NoopMutex(void){
return &sMutex;
}
-#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 *sqlite3DefaultMutex(void){
- return sqliteNoopMutex();
-}
-#endif /* SQLITE_MUTEX_NOOP */
-#endif /* SQLITE_MUTEX_OMIT */
+#endif /* defined(SQLITE_MUTEX_NOOP) && defined(SQLITE_DEBUG) */
/************** End of mutex_noop.c ******************************************/
/************** Begin file mutex_os2.c ***************************************/
@@ -15544,7 +14776,7 @@ static int os2MutexEnd(void){ return SQLITE_OK; }
/*
** 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.
+** 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:
**
@@ -15795,33 +15027,23 @@ SQLITE_PRIVATE sqlite3_mutex_methods *sqlite3DefaultMutex(void){
#include <pthread.h>
-/*
-** 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.
-*/
-#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 nRef; /* Number of entrances */
+ pthread_t owner; /* Thread that is within this mutex */
+#ifdef SQLITE_DEBUG
int trace; /* True to trace changes */
#endif
};
-#if SQLITE_MUTEX_NREF
+#ifdef SQLITE_DEBUG
#define SQLITE3_MUTEX_INITIALIZER { PTHREAD_MUTEX_INITIALIZER, 0, 0, (pthread_t)0, 0 }
#else
-#define SQLITE3_MUTEX_INITIALIZER { PTHREAD_MUTEX_INITIALIZER }
+#define SQLITE3_MUTEX_INITIALIZER { PTHREAD_MUTEX_INITIALIZER, 0, 0, (pthread_t)0 }
#endif
/*
@@ -15830,7 +15052,7 @@ struct sqlite3_mutex {
** 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
+** 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.
@@ -15893,7 +15115,7 @@ static int pthreadMutexEnd(void){ return SQLITE_OK; }
**
** 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
+** 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.
*/
@@ -15923,18 +15145,14 @@ static sqlite3_mutex *pthreadMutexAlloc(int iType){
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;
@@ -15943,9 +15161,7 @@ static sqlite3_mutex *pthreadMutexAlloc(int iType){
assert( iType-2 >= 0 );
assert( iType-2 < ArraySize(staticMutexes) );
p = &staticMutexes[iType-2];
-#if SQLITE_MUTEX_NREF
p->id = iType;
-#endif
break;
}
}
@@ -15985,7 +15201,7 @@ static void pthreadMutexEnter(sqlite3_mutex *p){
** 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
+ ** 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.
@@ -16005,11 +15221,9 @@ static void pthreadMutexEnter(sqlite3_mutex *p){
/* Use the built-in recursive mutexes if they are available.
*/
pthread_mutex_lock(&p->mutex);
-#if SQLITE_MUTEX_NREF
p->owner = pthread_self();
p->nRef++;
#endif
-#endif
#ifdef SQLITE_DEBUG
if( p->trace ){
@@ -16027,7 +15241,7 @@ static int pthreadMutexTry(sqlite3_mutex *p){
** 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
+ ** 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.
@@ -16050,10 +15264,8 @@ static int pthreadMutexTry(sqlite3_mutex *p){
/* 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{
rc = SQLITE_BUSY;
@@ -16076,9 +15288,7 @@ static int pthreadMutexTry(sqlite3_mutex *p){
*/
static void pthreadMutexLeave(sqlite3_mutex *p){
assert( pthreadMutexHeld(p) );
-#if SQLITE_MUTEX_NREF
p->nRef--;
-#endif
assert( p->nRef==0 || p->id==SQLITE_MUTEX_RECURSIVE );
#ifdef SQLITE_HOMEGROWN_RECURSIVE_MUTEX
@@ -16147,18 +15357,9 @@ SQLITE_PRIVATE sqlite3_mutex_methods *sqlite3DefaultMutex(void){
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
+ int nRef; /* Number of enterances */
+ DWORD owner; /* Thread holding this mutex */
};
-#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,
@@ -16172,9 +15373,9 @@ struct sqlite3_mutex {
** the LockFileEx() API.
**
** mutexIsNT() is only used for the TryEnterCriticalSection() API call,
-** which is only available if your application was compiled with
+** 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
+** call to TryEnterCriticalSection() is #ifdef'ed out, so #ifdef
** this out as well.
*/
#if 0
@@ -16202,12 +15403,8 @@ struct sqlite3_mutex {
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);
+ return p->nRef==0 || p->owner!=GetCurrentThreadId();
}
#endif
@@ -16215,14 +15412,7 @@ static int winMutexNotheld(sqlite3_mutex *p){
/*
** 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 sqlite3_mutex winMutex_staticMutexes[6];
static int winMutex_isInit = 0;
/* As winMutexInit() and winMutexEnd() are called as part
** of the sqlite3_initialize and sqlite3_shutdown()
@@ -16231,7 +15421,7 @@ static int winMutex_isInit = 0;
*/
static long winMutex_lock = 0;
-static int winMutexInit(void){
+static int winMutexInit(void){
/* The first to increment to 1 does actual initialization */
if( InterlockedCompareExchange(&winMutex_lock, 1, 0)==0 ){
int i;
@@ -16245,11 +15435,11 @@ static int winMutexInit(void){
Sleep(1);
}
}
- return SQLITE_OK;
+ return SQLITE_OK;
}
-static int winMutexEnd(void){
- /* The first to decrement to 0 does actual shutdown
+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 ){
@@ -16260,7 +15450,7 @@ static int winMutexEnd(void){
winMutex_isInit = 0;
}
}
- return SQLITE_OK;
+ return SQLITE_OK;
}
/*
@@ -16301,7 +15491,7 @@ static int winMutexEnd(void){
**
** 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
+** 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.
*/
@@ -16312,10 +15502,8 @@ static sqlite3_mutex *winMutexAlloc(int iType){
case SQLITE_MUTEX_FAST:
case SQLITE_MUTEX_RECURSIVE: {
p = sqlite3MallocZero( sizeof(*p) );
- if( p ){
-#ifdef SQLITE_DEBUG
+ if( p ){
p->id = iType;
-#endif
InitializeCriticalSection(&p->mutex);
}
break;
@@ -16325,9 +15513,7 @@ static sqlite3_mutex *winMutexAlloc(int iType){
assert( iType-2 >= 0 );
assert( iType-2 < ArraySize(winMutex_staticMutexes) );
p = &winMutex_staticMutexes[iType-2];
-#ifdef SQLITE_DEBUG
p->id = iType;
-#endif
break;
}
}
@@ -16360,29 +15546,18 @@ static void winMutexFree(sqlite3_mutex *p){
** more than once, the behavior is undefined.
*/
static void winMutexEnter(sqlite3_mutex *p){
-#ifdef SQLITE_DEBUG
- DWORD tid = GetCurrentThreadId();
- assert( p->id==SQLITE_MUTEX_RECURSIVE || winMutexNotheld2(p, tid) );
-#endif
+ assert( p->id==SQLITE_MUTEX_RECURSIVE || winMutexNotheld(p) );
EnterCriticalSection(&p->mutex);
-#ifdef SQLITE_DEBUG
- p->owner = tid;
+ p->owner = GetCurrentThreadId();
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) );
+ assert( p->id==SQLITE_MUTEX_RECURSIVE || winMutexNotheld(p) );
/*
** 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.
+ ** fail.
**
** The TryEnterCriticalSection() interface is only available on WinNT.
** And some windows compilers complain if you try to use it without
@@ -16392,18 +15567,13 @@ static int winMutexTry(sqlite3_mutex *p){
*/
#if 0
if( mutexIsNT() && TryEnterCriticalSection(&p->mutex) ){
- p->owner = tid;
+ p->owner = GetCurrentThreadId();
p->nRef++;
rc = SQLITE_OK;
}
#else
UNUSED_PARAMETER(p);
#endif
-#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;
}
@@ -16414,19 +15584,11 @@ static int winMutexTry(sqlite3_mutex *p){
** is not currently allocated. SQLite will never do either.
*/
static void winMutexLeave(sqlite3_mutex *p){
-#ifndef NDEBUG
- DWORD tid = GetCurrentThreadId();
assert( p->nRef>0 );
- assert( p->owner==tid );
+ assert( p->owner==GetCurrentThreadId() );
p->nRef--;
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 *sqlite3DefaultMutex(void){
@@ -16474,7 +15636,7 @@ SQLITE_PRIVATE sqlite3_mutex_methods *sqlite3DefaultMutex(void){
** limit.
*/
static void softHeapLimitEnforcer(
- void *NotUsed,
+ void *NotUsed,
sqlite3_int64 NotUsed2,
int allocSize
){
@@ -16483,7 +15645,7 @@ static void softHeapLimitEnforcer(
}
/*
-** Set the soft heap-size limit for the library. Passing a zero or
+** Set the soft heap-size limit for the library. Passing a zero or
** negative value indicates no limit.
*/
SQLITE_API void sqlite3_soft_heap_limit(int n){
@@ -16662,7 +15824,7 @@ SQLITE_API int sqlite3_memory_alarm(
#endif
/*
-** Trigger the alarm
+** Trigger the alarm
*/
static void sqlite3MallocAlarm(int nByte){
void (*xCallback)(void*,sqlite3_int64,int);
@@ -16777,7 +15939,7 @@ SQLITE_PRIVATE void *sqlite3ScratchMalloc(int n){
if( sqlite3GlobalConfig.szScratch<n ){
goto scratch_overflow;
- }else{
+ }else{
sqlite3_mutex_enter(mem0.mutex);
if( mem0.nScratchFree==0 ){
sqlite3_mutex_leave(mem0.mutex);
@@ -16809,11 +15971,10 @@ scratch_overflow:
}else{
p = sqlite3GlobalConfig.m.xMalloc(n);
}
- sqlite3MemdebugSetType(p, MEMTYPE_SCRATCH);
#if SQLITE_THREADSAFE==0 && !defined(NDEBUG)
scratchAllocOut = p!=0;
#endif
- return p;
+ return p;
}
SQLITE_PRIVATE void sqlite3ScratchFree(void *p){
if( p ){
@@ -16830,8 +15991,6 @@ SQLITE_PRIVATE void sqlite3ScratchFree(void *p){
if( sqlite3GlobalConfig.pScratch==0
|| p<sqlite3GlobalConfig.pScratch
|| p>=(void*)mem0.aScratchFree ){
- assert( sqlite3MemdebugHasType(p, MEMTYPE_SCRATCH) );
- sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
if( sqlite3GlobalConfig.bMemstat ){
int iSize = sqlite3MallocSize(p);
sqlite3_mutex_enter(mem0.mutex);
@@ -16872,7 +16031,6 @@ static int isLookaside(sqlite3 *db, void *p){
** sqlite3Malloc() or sqlite3_malloc().
*/
SQLITE_PRIVATE int sqlite3MallocSize(void *p){
- assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) );
return sqlite3GlobalConfig.m.xSize(p);
}
SQLITE_PRIVATE int sqlite3DbMallocSize(sqlite3 *db, void *p){
@@ -16880,8 +16038,6 @@ SQLITE_PRIVATE int sqlite3DbMallocSize(sqlite3 *db, void *p){
if( isLookaside(db, p) ){
return db->lookaside.sz;
}else{
- assert( sqlite3MemdebugHasType(p,
- db ? (MEMTYPE_DB|MEMTYPE_HEAP) : MEMTYPE_HEAP) );
return sqlite3GlobalConfig.m.xSize(p);
}
}
@@ -16891,7 +16047,6 @@ SQLITE_PRIVATE int sqlite3DbMallocSize(sqlite3 *db, void *p){
*/
SQLITE_API void sqlite3_free(void *p){
if( p==0 ) return;
- assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) );
if( sqlite3GlobalConfig.bMemstat ){
sqlite3_mutex_enter(mem0.mutex);
sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, -sqlite3MallocSize(p));
@@ -16914,8 +16069,6 @@ SQLITE_PRIVATE void sqlite3DbFree(sqlite3 *db, void *p){
db->lookaside.pFree = pBuf;
db->lookaside.nOut--;
}else{
- assert( sqlite3MemdebugHasType(p, MEMTYPE_DB|MEMTYPE_HEAP) );
- sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
sqlite3_free(p);
}
}
@@ -16944,11 +16097,10 @@ SQLITE_PRIVATE void *sqlite3Realloc(void *pOld, int nBytes){
}else if( sqlite3GlobalConfig.bMemstat ){
sqlite3_mutex_enter(mem0.mutex);
sqlite3StatusSet(SQLITE_STATUS_MALLOC_SIZE, nBytes);
- if( sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED)+nNew-nOld >=
+ if( sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED)+nNew-nOld >=
mem0.alarmThreshold ){
sqlite3MallocAlarm(nNew-nOld);
}
- assert( sqlite3MemdebugHasType(pOld, MEMTYPE_HEAP) );
pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew);
if( pNew==0 && mem0.alarmCallback ){
sqlite3MallocAlarm(nBytes);
@@ -16979,7 +16131,7 @@ SQLITE_API void *sqlite3_realloc(void *pOld, int n){
/*
** Allocate and zero memory.
-*/
+*/
SQLITE_PRIVATE void *sqlite3MallocZero(int n){
void *p = sqlite3Malloc(n);
if( p ){
@@ -17046,8 +16198,6 @@ SQLITE_PRIVATE void *sqlite3DbMallocRaw(sqlite3 *db, int n){
if( !p && db ){
db->mallocFailed = 1;
}
- sqlite3MemdebugSetType(p,
- (db && db->lookaside.bEnabled) ? MEMTYPE_DB : MEMTYPE_HEAP);
return p;
}
@@ -17073,14 +16223,10 @@ SQLITE_PRIVATE void *sqlite3DbRealloc(sqlite3 *db, void *p, int n){
sqlite3DbFree(db, p);
}
}else{
- assert( sqlite3MemdebugHasType(p, MEMTYPE_DB|MEMTYPE_HEAP) );
- sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
pNew = sqlite3_realloc(p, n);
if( !pNew ){
db->mallocFailed = 1;
}
- sqlite3MemdebugSetType(pNew,
- db->lookaside.bEnabled ? MEMTYPE_DB : MEMTYPE_HEAP);
}
}
return pNew;
@@ -17100,9 +16246,9 @@ SQLITE_PRIVATE void *sqlite3DbReallocOrFree(sqlite3 *db, void *p, int n){
}
/*
-** Make a copy of a string in memory obtained from sqliteMalloc(). These
+** 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
+** 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.
*/
@@ -17152,13 +16298,13 @@ SQLITE_PRIVATE void sqlite3SetString(char **pz, sqlite3 *db, const char *zFormat
/*
-** This function must be called before exiting any API function (i.e.
+** 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.
+** 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())
@@ -17166,7 +16312,7 @@ SQLITE_PRIVATE void sqlite3SetString(char **pz, sqlite3 *db, const char *zFormat
*/
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
+ ** 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) );
@@ -17459,7 +16605,7 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
break;
}
/* Find out what flags are present */
- flag_leftjustify = flag_plussign = flag_blanksign =
+ flag_leftjustify = flag_plussign = flag_blanksign =
flag_alternateform = flag_altform2 = flag_zeropad = 0;
done = 0;
do{
@@ -17641,9 +16787,7 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
case etEXP:
case etGENERIC:
realvalue = va_arg(ap,double);
-#ifdef SQLITE_OMIT_FLOATING_POINT
- length = 0;
-#else
+#ifndef SQLITE_OMIT_FLOATING_POINT
if( precision<0 ) precision = 6; /* Set default precision */
if( precision>etBUFSIZE/2-10 ) precision = etBUFSIZE/2-10;
if( realvalue<0.0 ){
@@ -17789,7 +16933,7 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
while( nPad-- ) bufpt[i++] = '0';
length = width;
}
-#endif /* !defined(SQLITE_OMIT_FLOATING_POINT) */
+#endif
break;
case etSIZE:
*(va_arg(ap,int*)) = pAccum->nChar;
@@ -17836,7 +16980,7 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
isnull = escarg==0;
if( isnull ) escarg = (xtype==etSQLESCAPE2 ? "NULL" : "(NULL)");
k = precision;
- for(i=n=0; k!=0 && (ch=escarg[i])!=0; i++, k--){
+ for(i=n=0; (ch=escarg[i])!=0 && k!=0; i++, k--){
if( ch==q ) n++;
}
needQuote = !isnull && xtype==etSQLESCAPE2;
@@ -18130,8 +17274,12 @@ SQLITE_API char *sqlite3_snprintf(int n, char *zBuf, const char *zFormat, ...){
** mutex is held.
*/
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 */
+ StrAccum acc; /* String accumulator */
+#ifdef SQLITE_SMALL_STACK
+ char zMsg[150]; /* Complete log message */
+#else
+ char zMsg[400]; /* Complete log message */
+#endif
sqlite3StrAccumInit(&acc, zMsg, sizeof(zMsg), 0);
acc.useMalloc = 0;
@@ -18345,7 +17493,7 @@ SQLITE_PRIVATE void sqlite3PrngResetState(void){
** May you share freely, never taking more than you give.
**
*************************************************************************
-** This file contains routines used to translate between UTF-8,
+** This file contains routines used to translate between UTF-8,
** UTF-16, UTF-16BE, and UTF-16LE.
**
** Notes on UTF-8:
@@ -18409,7 +17557,7 @@ typedef unsigned char Bool;
** 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.
**
@@ -18439,7 +17587,7 @@ struct VdbeCursor {
sqlite3_vtab_cursor *pVtabCursor; /* The cursor for a virtual table */
const sqlite3_module *pModule; /* Module for cursor pVtabCursor */
- /* Result of last sqlite3BtreeMoveto() done by an OP_NotExists or
+ /* Result of last sqlite3BtreeMoveto() done by an OP_NotExists or
** OP_IsUnique opcode on this cursor. */
int seekResult;
@@ -18464,7 +17612,7 @@ 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,
+** 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.
@@ -18537,7 +17685,7 @@ struct Mem {
** 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
+** set, then the string is nul terminated. The MEM_Int and MEM_Real
** flags may coexist with the MEM_Str flag.
**
** Multiple of these values can appear in Mem.flags. But only one
@@ -18641,7 +17789,7 @@ struct Set {
** 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
+** malloc failure when SQLite is invoked recursively by a virtual table
** method function.
*/
struct Vdbe {
@@ -18684,7 +17832,7 @@ struct Vdbe {
int btreeMask; /* Bitmask of db->aDb[] entries referenced */
i64 startTime; /* Time when query started - used for profiling */
BtreeMutexArray aMutex; /* An array of Btree used here and needing locks */
- int aCounter[3]; /* Counters used by sqlite3_stmt_status() */
+ int aCounter[2]; /* Counters used by sqlite3_stmt_status() */
char *zSql; /* Text of the SQL statement that generated this */
void *pFree; /* Free this when deleting the vdbe */
i64 nFkConstraint; /* Number of imm. FK constraints this VM */
@@ -18736,11 +17884,7 @@ 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 sqlite3VdbeMemSetDouble(Mem*, double);
SQLITE_PRIVATE void sqlite3VdbeMemSetNull(Mem*);
SQLITE_PRIVATE void sqlite3VdbeMemSetZeroBlob(Mem*,int);
SQLITE_PRIVATE void sqlite3VdbeMemSetRowSet(Mem*);
@@ -18948,7 +18092,7 @@ SQLITE_PRIVATE int sqlite3Utf8Read(
/*
** 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
@@ -18979,7 +18123,7 @@ SQLITE_PRIVATE int sqlite3VdbeMemTranslate(Mem *pMem, u8 desiredEnc){
}
#endif
- /* If the translation is between UTF-16 little and big endian, then
+ /* 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.
*/
@@ -19059,13 +18203,13 @@ SQLITE_PRIVATE int sqlite3VdbeMemTranslate(Mem *pMem, u8 desiredEnc){
if( pMem->enc==SQLITE_UTF16LE ){
/* UTF-16 Little-endian -> UTF-8 */
while( zIn<zTerm ){
- READ_UTF16LE(zIn, zIn<zTerm, c);
+ 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);
+ READ_UTF16BE(zIn, zIn<zTerm, c);
WRITE_UTF8(z, c);
}
}
@@ -19093,7 +18237,7 @@ translate_out:
}
/*
-** This routine checks for a byte-order mark at the beginning of the
+** 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.
@@ -19116,7 +18260,7 @@ SQLITE_PRIVATE int sqlite3VdbeMemHandleBom(Mem *pMem){
bom = SQLITE_UTF16LE;
}
}
-
+
if( bom ){
rc = sqlite3VdbeMemMakeWriteable(pMem);
if( rc==SQLITE_OK ){
@@ -19136,7 +18280,7 @@ SQLITE_PRIVATE int sqlite3VdbeMemHandleBom(Mem *pMem){
** 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
+** 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){
@@ -19156,7 +18300,7 @@ SQLITE_PRIVATE int sqlite3Utf8CharLen(const char *zIn, int nByte){
return r;
}
-/* This test function is not currently used by the automated test-suite.
+/* 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)
@@ -19193,11 +18337,11 @@ SQLITE_PRIVATE int sqlite3Utf8To8(unsigned char *zIn){
**
** NULL is returned if there is an allocation error.
*/
-SQLITE_PRIVATE char *sqlite3Utf16to8(sqlite3 *db, const void *z, int nByte, u8 enc){
+SQLITE_PRIVATE char *sqlite3Utf16to8(sqlite3 *db, const void *z, int nByte){
Mem m;
memset(&m, 0, sizeof(m));
m.db = db;
- sqlite3VdbeMemSetStr(&m, z, nByte, enc, SQLITE_STATIC);
+ sqlite3VdbeMemSetStr(&m, z, nByte, SQLITE_UTF16NATIVE, SQLITE_STATIC);
sqlite3VdbeChangeEncoding(&m, SQLITE_UTF8);
if( db->mallocFailed ){
sqlite3VdbeMemRelease(&m);
@@ -19205,9 +18349,7 @@ SQLITE_PRIVATE char *sqlite3Utf16to8(sqlite3 *db, const void *z, int nByte, u8 e
}
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;
+ return (m.flags & MEM_Dyn)!=0 ? m.z : sqlite3DbStrDup(db, m.z);
}
/*
@@ -19216,7 +18358,7 @@ SQLITE_PRIVATE char *sqlite3Utf16to8(sqlite3 *db, const void *z, int nByte, u8 e
** 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.
*/
@@ -19245,7 +18387,7 @@ 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);
@@ -19348,7 +18490,6 @@ SQLITE_PRIVATE void sqlite3Coverage(int x){
}
#endif
-#ifndef SQLITE_OMIT_FLOATING_POINT
/*
** Return true if the floating point value is Not a Number (NaN).
**
@@ -19370,15 +18511,15 @@ SQLITE_PRIVATE int sqlite3IsNaN(double x){
**
** 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
+ ** 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
+ ** 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
+ ** 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__
@@ -19393,7 +18534,6 @@ SQLITE_PRIVATE int sqlite3IsNaN(double x){
testcase( rc );
return rc;
}
-#endif /* SQLITE_OMIT_FLOATING_POINT */
/*
** Compute a string length that is limited to what can be stored in
@@ -19571,7 +18711,6 @@ SQLITE_PRIVATE int sqlite3IsNumber(const char *z, int *realnum, u8 enc){
z += incr;
*realnum = 0;
while( sqlite3Isdigit(*z) ){ z += incr; }
-#ifndef SQLITE_OMIT_FLOATING_POINT
if( *z=='.' ){
z += incr;
if( !sqlite3Isdigit(*z) ) return 0;
@@ -19585,7 +18724,6 @@ SQLITE_PRIVATE int sqlite3IsNumber(const char *z, int *realnum, u8 enc){
while( sqlite3Isdigit(*z) ){ z += incr; }
*realnum = 1;
}
-#endif
return *z==0;
}
@@ -19704,7 +18842,7 @@ SQLITE_PRIVATE int sqlite3AtoF(const char *z, double *pResult){
result *= 1.0e+308;
}
}else{
- /* 1.0e+22 is the largest power of 10 than can be
+ /* 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; }
@@ -19747,9 +18885,6 @@ static int compare2pow63(const char *zNum){
c = memcmp(zNum,"922337203685477580",18)*10;
if( c==0 ){
c = zNum[18] - '8';
- testcase( c==(-1) );
- testcase( c==0 );
- testcase( c==(+1) );
}
return c;
}
@@ -19786,9 +18921,6 @@ SQLITE_PRIVATE int sqlite3Atoi64(const char *zNum, i64 *pNum){
v = v*10 + c - '0';
}
*pNum = neg ? -v : v;
- testcase( i==18 );
- testcase( i==19 );
- testcase( i==20 );
if( c!=0 || (i==0 && zStart==zNum) || i>19 ){
/* zNum is empty or contains non-numeric text or is longer
** than 19 digits (thus guaranting that it is too large) */
@@ -19832,9 +18964,6 @@ SQLITE_PRIVATE int sqlite3FitsIn64Bits(const char *zNum, int negFlag){
zNum++; /* Skip leading zeros. Ticket #2454 */
}
for(i=0; zNum[i]; i++){ assert( zNum[i]>='0' && zNum[i]<='9' ); }
- testcase( i==18 );
- testcase( i==19 );
- testcase( i==20 );
if( i<19 ){
/* Guaranteed to fit if less than 19 digits */
return 1;
@@ -19875,11 +19004,9 @@ SQLITE_PRIVATE int sqlite3GetInt32(const char *zNum, int *pValue){
** 1234567890
** 2^31 -> 2147483648
*/
- testcase( i==10 );
if( i>10 ){
return 0;
}
- testcase( v-neg==2147483647 );
if( v-neg>2147483647 ){
return 0;
}
@@ -19930,7 +19057,7 @@ SQLITE_PRIVATE int sqlite3PutVarint(unsigned char *p, u64 v){
v >>= 7;
}
return 9;
- }
+ }
n = 0;
do{
buf[n++] = (u8)((v & 0x7f) | 0x80);
@@ -19968,19 +19095,6 @@ SQLITE_PRIVATE int sqlite3PutVarint32(unsigned char *p, u32 v){
}
/*
-** 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
-*/
-#define SLOT_2_0 0x001fc07f
-#define SLOT_4_2_0 0xf01fc07f
-
-
-/*
** 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.
*/
@@ -20007,17 +19121,13 @@ SQLITE_PRIVATE u8 sqlite3GetVarint(const unsigned char *p, u64 *v){
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;
+ a &= (0x7f<<14)|(0x7f);
b &= 0x7f;
b = b<<7;
a |= b;
@@ -20026,14 +19136,14 @@ SQLITE_PRIVATE u8 sqlite3GetVarint(const unsigned char *p, u64 *v){
}
/* CSE1 from below */
- a &= SLOT_2_0;
+ a &= (0x7f<<14)|(0x7f);
p++;
b = b<<14;
b |= *p;
/* b: p1<<14 | p3 (unmasked) */
if (!(b&0x80))
{
- b &= SLOT_2_0;
+ b &= (0x7f<<14)|(0x7f);
/* moved CSE1 up */
/* a &= (0x7f<<14)|(0x7f); */
a = a<<7;
@@ -20047,7 +19157,7 @@ SQLITE_PRIVATE u8 sqlite3GetVarint(const unsigned char *p, u64 *v){
/* 1:save off p0<<21 | p1<<14 | p2<<7 | p3 (masked) */
/* moved CSE1 up */
/* a &= (0x7f<<14)|(0x7f); */
- b &= SLOT_2_0;
+ b &= (0x7f<<14)|(0x7f);
s = a;
/* s: p0<<14 | p2 (masked) */
@@ -20080,7 +19190,7 @@ SQLITE_PRIVATE u8 sqlite3GetVarint(const unsigned char *p, u64 *v){
{
/* 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 &= (0x7f<<14)|(0x7f);
a = a<<7;
a |= b;
s = s>>18;
@@ -20094,8 +19204,8 @@ SQLITE_PRIVATE u8 sqlite3GetVarint(const unsigned char *p, u64 *v){
/* a: p2<<28 | p4<<14 | p6 (unmasked) */
if (!(a&0x80))
{
- a &= SLOT_4_2_0;
- b &= SLOT_2_0;
+ a &= (0x1f<<28)|(0x7f<<14)|(0x7f);
+ b &= (0x7f<<14)|(0x7f);
b = b<<7;
a |= b;
s = s>>11;
@@ -20104,14 +19214,14 @@ SQLITE_PRIVATE u8 sqlite3GetVarint(const unsigned char *p, u64 *v){
}
/* CSE2 from below */
- a &= SLOT_2_0;
+ a &= (0x7f<<14)|(0x7f);
p++;
b = b<<14;
b |= *p;
/* b: p3<<28 | p5<<14 | p7 (unmasked) */
if (!(b&0x80))
{
- b &= SLOT_4_2_0;
+ b &= (0x1f<<28)|(0x7f<<14)|(0x7f);
/* moved CSE2 up */
/* a &= (0x7f<<14)|(0x7f); */
a = a<<7;
@@ -20128,7 +19238,7 @@ SQLITE_PRIVATE u8 sqlite3GetVarint(const unsigned char *p, u64 *v){
/* moved CSE2 up */
/* a &= (0x7f<<29)|(0x7f<<15)|(0xff); */
- b &= SLOT_2_0;
+ b &= (0x7f<<14)|(0x7f);
b = b<<8;
a |= b;
@@ -20150,8 +19260,8 @@ SQLITE_PRIVATE u8 sqlite3GetVarint(const unsigned char *p, u64 *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
+** 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.
*/
SQLITE_PRIVATE u8 sqlite3GetVarint32(const unsigned char *p, u32 *v){
@@ -20248,9 +19358,9 @@ SQLITE_PRIVATE u8 sqlite3GetVarint32(const unsigned char *p, u32 *v){
/* 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;
+ /* Walues between 268435456 and 34359738367 */
+ a &= (0x1f<<28)|(0x7f<<14)|(0x7f);
+ b &= (0x1f<<28)|(0x7f<<14)|(0x7f);
b = b<<7;
*v = a | b;
return 5;
@@ -20349,7 +19459,7 @@ SQLITE_PRIVATE void *sqlite3HexToBlob(sqlite3 *db, const char *z, int n){
** argument. The zType is a word like "NULL" or "closed" or "invalid".
*/
static void logBadConnection(const char *zType){
- sqlite3_log(SQLITE_MISUSE,
+ sqlite3_log(SQLITE_MISUSE,
"API call with %s database connection pointer",
zType
);
@@ -20377,8 +19487,7 @@ SQLITE_PRIVATE int sqlite3SafetyCheckOk(sqlite3 *db){
}
magic = db->magic;
if( magic!=SQLITE_MAGIC_OPEN ){
- if( sqlite3SafetyCheckSickOrOk(db) ){
- testcase( sqlite3GlobalConfig.xLog!=0 );
+ if( !sqlite3SafetyCheckSickOrOk(db) ){
logBadConnection("unopened");
}
return 0;
@@ -20392,7 +19501,6 @@ SQLITE_PRIVATE int sqlite3SafetyCheckSickOrOk(sqlite3 *db){
if( magic!=SQLITE_MAGIC_SICK &&
magic!=SQLITE_MAGIC_OPEN &&
magic!=SQLITE_MAGIC_BUSY ){
- testcase( sqlite3GlobalConfig.xLog!=0 );
logBadConnection("invalid");
return 0;
}else{
@@ -20556,7 +19664,7 @@ static HashElem *findElementGivenHash(
count = pH->count;
}
while( count-- && ALWAYS(elem) ){
- if( elem->nKey==nKey && sqlite3StrNICmp(elem->pKey,pKey,nKey)==0 ){
+ if( elem->nKey==nKey && sqlite3StrNICmp(elem->pKey,pKey,nKey)==0 ){
return elem;
}
elem = elem->next;
@@ -20574,7 +19682,7 @@ static void removeElementGivenHash(
){
struct _ht *pEntry;
if( elem->prev ){
- elem->prev->next = elem->next;
+ elem->prev->next = elem->next;
}else{
pH->first = elem->next;
}
@@ -20724,39 +19832,39 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
/* 37 */ "VerifyCookie",
/* 38 */ "OpenRead",
/* 39 */ "OpenWrite",
- /* 40 */ "OpenAutoindex",
- /* 41 */ "OpenEphemeral",
- /* 42 */ "OpenPseudo",
- /* 43 */ "Close",
- /* 44 */ "SeekLt",
- /* 45 */ "SeekLe",
- /* 46 */ "SeekGe",
- /* 47 */ "SeekGt",
- /* 48 */ "Seek",
- /* 49 */ "NotFound",
- /* 50 */ "Found",
- /* 51 */ "IsUnique",
- /* 52 */ "NotExists",
- /* 53 */ "Sequence",
- /* 54 */ "NewRowid",
- /* 55 */ "Insert",
- /* 56 */ "InsertInt",
- /* 57 */ "Delete",
- /* 58 */ "ResetCount",
- /* 59 */ "RowKey",
- /* 60 */ "RowData",
- /* 61 */ "Rowid",
- /* 62 */ "NullRow",
- /* 63 */ "Last",
- /* 64 */ "Sort",
- /* 65 */ "Rewind",
- /* 66 */ "Prev",
- /* 67 */ "Next",
+ /* 40 */ "OpenEphemeral",
+ /* 41 */ "OpenPseudo",
+ /* 42 */ "Close",
+ /* 43 */ "SeekLt",
+ /* 44 */ "SeekLe",
+ /* 45 */ "SeekGe",
+ /* 46 */ "SeekGt",
+ /* 47 */ "Seek",
+ /* 48 */ "NotFound",
+ /* 49 */ "Found",
+ /* 50 */ "IsUnique",
+ /* 51 */ "NotExists",
+ /* 52 */ "Sequence",
+ /* 53 */ "NewRowid",
+ /* 54 */ "Insert",
+ /* 55 */ "InsertInt",
+ /* 56 */ "Delete",
+ /* 57 */ "ResetCount",
+ /* 58 */ "RowKey",
+ /* 59 */ "RowData",
+ /* 60 */ "Rowid",
+ /* 61 */ "NullRow",
+ /* 62 */ "Last",
+ /* 63 */ "Sort",
+ /* 64 */ "Rewind",
+ /* 65 */ "Prev",
+ /* 66 */ "Next",
+ /* 67 */ "IdxInsert",
/* 68 */ "Or",
/* 69 */ "And",
- /* 70 */ "IdxInsert",
- /* 71 */ "IdxDelete",
- /* 72 */ "IdxRowid",
+ /* 70 */ "IdxDelete",
+ /* 71 */ "IdxRowid",
+ /* 72 */ "IdxLT",
/* 73 */ "IsNull",
/* 74 */ "NotNull",
/* 75 */ "Ne",
@@ -20765,7 +19873,7 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
/* 78 */ "Le",
/* 79 */ "Lt",
/* 80 */ "Ge",
- /* 81 */ "IdxLT",
+ /* 81 */ "IdxGE",
/* 82 */ "BitAnd",
/* 83 */ "BitOr",
/* 84 */ "ShiftLeft",
@@ -20776,52 +19884,52 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
/* 89 */ "Divide",
/* 90 */ "Remainder",
/* 91 */ "Concat",
- /* 92 */ "IdxGE",
+ /* 92 */ "Destroy",
/* 93 */ "BitNot",
/* 94 */ "String8",
- /* 95 */ "Destroy",
- /* 96 */ "Clear",
- /* 97 */ "CreateIndex",
- /* 98 */ "CreateTable",
- /* 99 */ "ParseSchema",
- /* 100 */ "LoadAnalysis",
- /* 101 */ "DropTable",
- /* 102 */ "DropIndex",
- /* 103 */ "DropTrigger",
- /* 104 */ "IntegrityCk",
- /* 105 */ "RowSetAdd",
- /* 106 */ "RowSetRead",
- /* 107 */ "RowSetTest",
- /* 108 */ "Program",
- /* 109 */ "Param",
- /* 110 */ "FkCounter",
- /* 111 */ "FkIfZero",
- /* 112 */ "MemMax",
- /* 113 */ "IfPos",
- /* 114 */ "IfNeg",
- /* 115 */ "IfZero",
- /* 116 */ "AggStep",
- /* 117 */ "AggFinal",
- /* 118 */ "Checkpoint",
- /* 119 */ "JournalMode",
- /* 120 */ "Vacuum",
- /* 121 */ "IncrVacuum",
- /* 122 */ "Expire",
- /* 123 */ "TableLock",
- /* 124 */ "VBegin",
- /* 125 */ "VCreate",
- /* 126 */ "VDestroy",
- /* 127 */ "VOpen",
- /* 128 */ "VFilter",
- /* 129 */ "VColumn",
+ /* 95 */ "Clear",
+ /* 96 */ "CreateIndex",
+ /* 97 */ "CreateTable",
+ /* 98 */ "ParseSchema",
+ /* 99 */ "LoadAnalysis",
+ /* 100 */ "DropTable",
+ /* 101 */ "DropIndex",
+ /* 102 */ "DropTrigger",
+ /* 103 */ "IntegrityCk",
+ /* 104 */ "RowSetAdd",
+ /* 105 */ "RowSetRead",
+ /* 106 */ "RowSetTest",
+ /* 107 */ "Program",
+ /* 108 */ "Param",
+ /* 109 */ "FkCounter",
+ /* 110 */ "FkIfZero",
+ /* 111 */ "MemMax",
+ /* 112 */ "IfPos",
+ /* 113 */ "IfNeg",
+ /* 114 */ "IfZero",
+ /* 115 */ "AggStep",
+ /* 116 */ "AggFinal",
+ /* 117 */ "Vacuum",
+ /* 118 */ "IncrVacuum",
+ /* 119 */ "Expire",
+ /* 120 */ "TableLock",
+ /* 121 */ "VBegin",
+ /* 122 */ "VCreate",
+ /* 123 */ "VDestroy",
+ /* 124 */ "VOpen",
+ /* 125 */ "VFilter",
+ /* 126 */ "VColumn",
+ /* 127 */ "VNext",
+ /* 128 */ "VRename",
+ /* 129 */ "VUpdate",
/* 130 */ "Real",
- /* 131 */ "VNext",
- /* 132 */ "VRename",
- /* 133 */ "VUpdate",
- /* 134 */ "Pagecount",
- /* 135 */ "Trace",
- /* 136 */ "Noop",
- /* 137 */ "Explain",
+ /* 131 */ "Pagecount",
+ /* 132 */ "Trace",
+ /* 133 */ "Noop",
+ /* 134 */ "Explain",
+ /* 135 */ "NotUsed_135",
+ /* 136 */ "NotUsed_136",
+ /* 137 */ "NotUsed_137",
/* 138 */ "NotUsed_138",
/* 139 */ "NotUsed_139",
/* 140 */ "NotUsed_140",
@@ -20926,9 +20034,23 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
#ifdef SQLITE_DEBUG
SQLITE_PRIVATE int sqlite3OSTrace = 0;
-#define OSTRACE(X) if( sqlite3OSTrace ) sqlite3DebugPrintf X
+#define OSTRACE1(X) if( sqlite3OSTrace ) sqlite3DebugPrintf(X)
+#define OSTRACE2(X,Y) if( sqlite3OSTrace ) sqlite3DebugPrintf(X,Y)
+#define OSTRACE3(X,Y,Z) if( sqlite3OSTrace ) sqlite3DebugPrintf(X,Y,Z)
+#define OSTRACE4(X,Y,Z,A) if( sqlite3OSTrace ) sqlite3DebugPrintf(X,Y,Z,A)
+#define OSTRACE5(X,Y,Z,A,B) if( sqlite3OSTrace ) sqlite3DebugPrintf(X,Y,Z,A,B)
+#define OSTRACE6(X,Y,Z,A,B,C) \
+ if(sqlite3OSTrace) sqlite3DebugPrintf(X,Y,Z,A,B,C)
+#define OSTRACE7(X,Y,Z,A,B,C,D) \
+ if(sqlite3OSTrace) sqlite3DebugPrintf(X,Y,Z,A,B,C,D)
#else
-#define OSTRACE(X)
+#define OSTRACE1(X)
+#define OSTRACE2(X,Y)
+#define OSTRACE3(X,Y,Z)
+#define OSTRACE4(X,Y,Z,A)
+#define OSTRACE5(X,Y,Z,A,B)
+#define OSTRACE6(X,Y,Z,A,B,C)
+#define OSTRACE7(X,Y,Z,A,B,C,D)
#endif
/*
@@ -20937,8 +20059,8 @@ SQLITE_PRIVATE int sqlite3OSTrace = 0;
*/
#ifdef SQLITE_PERFORMANCE_TRACE
-/*
-** hwtime.h contains inline assembler code for implementing
+/*
+** hwtime.h contains inline assembler code for implementing
** high-performance timing routines.
*/
/************** Include hwtime.h in the middle of os_common.h ****************/
@@ -20996,7 +20118,7 @@ SQLITE_PRIVATE int sqlite3OSTrace = 0;
__asm__ __volatile__ ("rdtsc" : "=A" (val));
return val;
}
-
+
#elif (defined(__GNUC__) && defined(__ppc__))
__inline__ sqlite_uint64 sqlite3Hwtime(void){
@@ -21124,7 +20246,7 @@ static int os2Close( sqlite3_file *id ){
APIRET rc = NO_ERROR;
os2File *pFile;
if( id && (pFile = (os2File*)id) != 0 ){
- OSTRACE(( "CLOSE %d\n", pFile->h ));
+ OSTRACE2( "CLOSE %d\n", pFile->h );
rc = DosClose( pFile->h );
pFile->locktype = NO_LOCK;
if( pFile->pathToDel != NULL ){
@@ -21155,7 +20277,7 @@ static int os2Read(
os2File *pFile = (os2File*)id;
assert( id!=0 );
SimulateIOError( return SQLITE_IOERR_READ );
- OSTRACE(( "READ %d lock=%d\n", pFile->h, pFile->locktype ));
+ OSTRACE3( "READ %d lock=%d\n", pFile->h, pFile->locktype );
if( DosSetFilePtr(pFile->h, offset, FILE_BEGIN, &fileLocation) != NO_ERROR ){
return SQLITE_IOERR;
}
@@ -21188,7 +20310,7 @@ static int os2Write(
assert( id!=0 );
SimulateIOError( return SQLITE_IOERR_WRITE );
SimulateDiskfullError( return SQLITE_FULL );
- OSTRACE(( "WRITE %d lock=%d\n", pFile->h, pFile->locktype ));
+ OSTRACE3( "WRITE %d lock=%d\n", pFile->h, pFile->locktype );
if( DosSetFilePtr(pFile->h, offset, FILE_BEGIN, &fileLocation) != NO_ERROR ){
return SQLITE_IOERR;
}
@@ -21210,7 +20332,7 @@ static int os2Write(
static int os2Truncate( sqlite3_file *id, i64 nByte ){
APIRET rc = NO_ERROR;
os2File *pFile = (os2File*)id;
- OSTRACE(( "TRUNCATE %d %lld\n", pFile->h, nByte ));
+ OSTRACE3( "TRUNCATE %d %lld\n", pFile->h, nByte );
SimulateIOError( return SQLITE_IOERR_TRUNCATE );
rc = DosSetFileSize( pFile->h, nByte );
return rc == NO_ERROR ? SQLITE_OK : SQLITE_IOERR_TRUNCATE;
@@ -21230,7 +20352,7 @@ SQLITE_API int sqlite3_fullsync_count = 0;
*/
static int os2Sync( sqlite3_file *id, int flags ){
os2File *pFile = (os2File*)id;
- OSTRACE(( "SYNC %d lock=%d\n", pFile->h, pFile->locktype ));
+ OSTRACE3( "SYNC %d lock=%d\n", pFile->h, pFile->locktype );
#ifdef SQLITE_TEST
if( flags & SQLITE_SYNC_FULL){
sqlite3_fullsync_count++;
@@ -21280,7 +20402,7 @@ static int getReadLock( os2File *pFile ){
UnlockArea.lOffset = 0L;
UnlockArea.lRange = 0L;
res = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, LOCK_TIMEOUT, 1L );
- OSTRACE(( "GETREADLOCK %d res=%d\n", pFile->h, res ));
+ OSTRACE3( "GETREADLOCK %d res=%d\n", pFile->h, res );
return res;
}
@@ -21298,7 +20420,7 @@ static int unlockReadLock( os2File *id ){
UnlockArea.lOffset = SHARED_FIRST;
UnlockArea.lRange = SHARED_SIZE;
res = DosSetFileLocks( id->h, &UnlockArea, &LockArea, LOCK_TIMEOUT, 1L );
- OSTRACE(( "UNLOCK-READLOCK file handle=%d res=%d?\n", id->h, res ));
+ OSTRACE3( "UNLOCK-READLOCK file handle=%d res=%d?\n", id->h, res );
return res;
}
@@ -21339,14 +20461,14 @@ static int os2Lock( sqlite3_file *id, int locktype ){
memset(&LockArea, 0, sizeof(LockArea));
memset(&UnlockArea, 0, sizeof(UnlockArea));
assert( pFile!=0 );
- OSTRACE(( "LOCK %d %d was %d\n", pFile->h, locktype, pFile->locktype ));
+ OSTRACE4( "LOCK %d %d was %d\n", pFile->h, locktype, pFile->locktype );
/* If there is already a lock of this type or more restrictive on the
** os2File, do nothing. Don't use the end_lock: exit path, as
** sqlite3_mutex_enter() hasn't been called yet.
*/
if( pFile->locktype>=locktype ){
- OSTRACE(( "LOCK %d %d ok (already held)\n", pFile->h, locktype ));
+ OSTRACE3( "LOCK %d %d ok (already held)\n", pFile->h, locktype );
return SQLITE_OK;
}
@@ -21373,7 +20495,7 @@ static int os2Lock( sqlite3_file *id, int locktype ){
res = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, 100L, 0L );
if( res == NO_ERROR ){
gotPendingLock = 1;
- OSTRACE(( "LOCK %d pending lock boolean set. res=%d\n", pFile->h, res ));
+ OSTRACE3( "LOCK %d pending lock boolean set. res=%d\n", pFile->h, res );
}
}
@@ -21385,7 +20507,7 @@ static int os2Lock( sqlite3_file *id, int locktype ){
if( res == NO_ERROR ){
newLocktype = SHARED_LOCK;
}
- OSTRACE(( "LOCK %d acquire shared lock. res=%d\n", pFile->h, res ));
+ OSTRACE3( "LOCK %d acquire shared lock. res=%d\n", pFile->h, res );
}
/* Acquire a RESERVED lock
@@ -21400,7 +20522,7 @@ static int os2Lock( sqlite3_file *id, int locktype ){
if( res == NO_ERROR ){
newLocktype = RESERVED_LOCK;
}
- OSTRACE(( "LOCK %d acquire reserved lock. res=%d\n", pFile->h, res ));
+ OSTRACE3( "LOCK %d acquire reserved lock. res=%d\n", pFile->h, res );
}
/* Acquire a PENDING lock
@@ -21408,8 +20530,7 @@ static int os2Lock( sqlite3_file *id, int locktype ){
if( locktype==EXCLUSIVE_LOCK && res == NO_ERROR ){
newLocktype = PENDING_LOCK;
gotPendingLock = 0;
- OSTRACE(( "LOCK %d acquire pending lock. pending lock boolean unset.\n",
- pFile->h ));
+ OSTRACE2( "LOCK %d acquire pending lock. pending lock boolean unset.\n", pFile->h );
}
/* Acquire an EXCLUSIVE lock
@@ -21417,7 +20538,7 @@ static int os2Lock( sqlite3_file *id, int locktype ){
if( locktype==EXCLUSIVE_LOCK && res == NO_ERROR ){
assert( pFile->locktype>=SHARED_LOCK );
res = unlockReadLock(pFile);
- OSTRACE(( "unreadlock = %d\n", res ));
+ OSTRACE2( "unreadlock = %d\n", res );
LockArea.lOffset = SHARED_FIRST;
LockArea.lRange = SHARED_SIZE;
UnlockArea.lOffset = 0L;
@@ -21426,10 +20547,10 @@ static int os2Lock( sqlite3_file *id, int locktype ){
if( res == NO_ERROR ){
newLocktype = EXCLUSIVE_LOCK;
}else{
- OSTRACE(( "OS/2 error-code = %d\n", res ));
+ OSTRACE2( "OS/2 error-code = %d\n", res );
getReadLock(pFile);
}
- OSTRACE(( "LOCK %d acquire exclusive lock. res=%d\n", pFile->h, res ));
+ OSTRACE3( "LOCK %d acquire exclusive lock. res=%d\n", pFile->h, res );
}
/* If we are holding a PENDING lock that ought to be released, then
@@ -21442,7 +20563,7 @@ static int os2Lock( sqlite3_file *id, int locktype ){
UnlockArea.lOffset = PENDING_BYTE;
UnlockArea.lRange = 1L;
r = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, LOCK_TIMEOUT, 0L );
- OSTRACE(( "LOCK %d unlocking pending/is shared. r=%d\n", pFile->h, r ));
+ OSTRACE3( "LOCK %d unlocking pending/is shared. r=%d\n", pFile->h, r );
}
/* Update the state of the lock has held in the file descriptor then
@@ -21451,12 +20572,12 @@ static int os2Lock( sqlite3_file *id, int locktype ){
if( res == NO_ERROR ){
rc = SQLITE_OK;
}else{
- OSTRACE(( "LOCK FAILED %d trying for %d but got %d\n", pFile->h,
- locktype, newLocktype ));
+ OSTRACE4( "LOCK FAILED %d trying for %d but got %d\n", pFile->h,
+ locktype, newLocktype );
rc = SQLITE_BUSY;
}
pFile->locktype = newLocktype;
- OSTRACE(( "LOCK %d now %d\n", pFile->h, pFile->locktype ));
+ OSTRACE3( "LOCK %d now %d\n", pFile->h, pFile->locktype );
return rc;
}
@@ -21471,7 +20592,7 @@ static int os2CheckReservedLock( sqlite3_file *id, int *pOut ){
assert( pFile!=0 );
if( pFile->locktype>=RESERVED_LOCK ){
r = 1;
- OSTRACE(( "TEST WR-LOCK %d %d (local)\n", pFile->h, r ));
+ OSTRACE3( "TEST WR-LOCK %d %d (local)\n", pFile->h, r );
}else{
FILELOCK LockArea,
UnlockArea;
@@ -21483,7 +20604,7 @@ static int os2CheckReservedLock( sqlite3_file *id, int *pOut ){
UnlockArea.lOffset = 0L;
UnlockArea.lRange = 0L;
rc = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, LOCK_TIMEOUT, 0L );
- OSTRACE(( "TEST WR-LOCK %d lock reserved byte rc=%d\n", pFile->h, rc ));
+ OSTRACE3( "TEST WR-LOCK %d lock reserved byte rc=%d\n", pFile->h, rc );
if( rc == NO_ERROR ){
APIRET rcu = NO_ERROR; /* return code for unlocking */
LockArea.lOffset = 0L;
@@ -21491,10 +20612,10 @@ static int os2CheckReservedLock( sqlite3_file *id, int *pOut ){
UnlockArea.lOffset = RESERVED_BYTE;
UnlockArea.lRange = 1L;
rcu = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, LOCK_TIMEOUT, 0L );
- OSTRACE(( "TEST WR-LOCK %d unlock reserved byte r=%d\n", pFile->h, rcu ));
+ OSTRACE3( "TEST WR-LOCK %d unlock reserved byte r=%d\n", pFile->h, rcu );
}
r = !(rc == NO_ERROR);
- OSTRACE(( "TEST WR-LOCK %d %d (remote)\n", pFile->h, r ));
+ OSTRACE3( "TEST WR-LOCK %d %d (remote)\n", pFile->h, r );
}
*pOut = r;
return SQLITE_OK;
@@ -21522,7 +20643,7 @@ static int os2Unlock( sqlite3_file *id, int locktype ){
memset(&UnlockArea, 0, sizeof(UnlockArea));
assert( pFile!=0 );
assert( locktype<=SHARED_LOCK );
- OSTRACE(( "UNLOCK %d to %d was %d\n", pFile->h, locktype, pFile->locktype ));
+ OSTRACE4( "UNLOCK %d to %d was %d\n", pFile->h, locktype, pFile->locktype );
type = pFile->locktype;
if( type>=EXCLUSIVE_LOCK ){
LockArea.lOffset = 0L;
@@ -21530,11 +20651,11 @@ static int os2Unlock( sqlite3_file *id, int locktype ){
UnlockArea.lOffset = SHARED_FIRST;
UnlockArea.lRange = SHARED_SIZE;
res = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, LOCK_TIMEOUT, 0L );
- OSTRACE(( "UNLOCK %d exclusive lock res=%d\n", pFile->h, res ));
+ OSTRACE3( "UNLOCK %d exclusive lock res=%d\n", pFile->h, res );
if( locktype==SHARED_LOCK && getReadLock(pFile) != NO_ERROR ){
/* This should never happen. We should always be able to
** reacquire the read lock */
- OSTRACE(( "UNLOCK %d to %d getReadLock() failed\n", pFile->h, locktype ));
+ OSTRACE3( "UNLOCK %d to %d getReadLock() failed\n", pFile->h, locktype );
rc = SQLITE_IOERR_UNLOCK;
}
}
@@ -21544,12 +20665,11 @@ static int os2Unlock( sqlite3_file *id, int locktype ){
UnlockArea.lOffset = RESERVED_BYTE;
UnlockArea.lRange = 1L;
res = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, LOCK_TIMEOUT, 0L );
- OSTRACE(( "UNLOCK %d reserved res=%d\n", pFile->h, res ));
+ OSTRACE3( "UNLOCK %d reserved res=%d\n", pFile->h, res );
}
if( locktype==NO_LOCK && type>=SHARED_LOCK ){
res = unlockReadLock(pFile);
- OSTRACE(( "UNLOCK %d is %d want %d res=%d\n",
- pFile->h, type, locktype, res ));
+ OSTRACE5( "UNLOCK %d is %d want %d res=%d\n", pFile->h, type, locktype, res );
}
if( type>=PENDING_LOCK ){
LockArea.lOffset = 0L;
@@ -21557,10 +20677,10 @@ static int os2Unlock( sqlite3_file *id, int locktype ){
UnlockArea.lOffset = PENDING_BYTE;
UnlockArea.lRange = 1L;
res = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, LOCK_TIMEOUT, 0L );
- OSTRACE(( "UNLOCK %d pending res=%d\n", pFile->h, res ));
+ OSTRACE3( "UNLOCK %d pending res=%d\n", pFile->h, res );
}
pFile->locktype = locktype;
- OSTRACE(( "UNLOCK %d now %d\n", pFile->h, pFile->locktype ));
+ OSTRACE3( "UNLOCK %d now %d\n", pFile->h, pFile->locktype );
return rc;
}
@@ -21571,8 +20691,7 @@ static int os2FileControl(sqlite3_file *id, int op, void *pArg){
switch( op ){
case SQLITE_FCNTL_LOCKSTATE: {
*(int*)pArg = ((os2File*)id)->locktype;
- OSTRACE(( "FCNTL_LOCKSTATE %d lock=%d\n",
- ((os2File*)id)->h, ((os2File*)id)->locktype ));
+ OSTRACE3( "FCNTL_LOCKSTATE %d lock=%d\n", ((os2File*)id)->h, ((os2File*)id)->locktype );
return SQLITE_OK;
}
}
@@ -21759,7 +20878,7 @@ static int getTempname(int nBuf, char *zBuf ){
zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ];
}
zBuf[j] = 0;
- OSTRACE(( "TEMP FILENAME: %s\n", zBuf ));
+ OSTRACE2( "TEMP FILENAME: %s\n", zBuf );
return SQLITE_OK;
}
@@ -21808,8 +20927,8 @@ static int os2Open(
char *zNameCp;
char zTmpname[CCHMAXPATH+1]; /* Buffer to hold name of temp file */
- /* If the second argument to this function is NULL, generate a
- ** temporary file name to use
+ /* If the second argument to this function is NULL, generate a
+ ** temporary file name to use
*/
if( !zName ){
int rc = getTempname(CCHMAXPATH+1, zTmpname);
@@ -21822,30 +20941,30 @@ static int os2Open(
memset( pFile, 0, sizeof(*pFile) );
- OSTRACE( "OPEN want %d\n", flags ));
+ OSTRACE2( "OPEN want %d\n", flags );
if( flags & SQLITE_OPEN_READWRITE ){
ulOpenMode |= OPEN_ACCESS_READWRITE;
- OSTRACE(( "OPEN read/write\n" ));
+ OSTRACE1( "OPEN read/write\n" );
}else{
ulOpenMode |= OPEN_ACCESS_READONLY;
- OSTRACE(( "OPEN read only\n" ));
+ OSTRACE1( "OPEN read only\n" );
}
if( flags & SQLITE_OPEN_CREATE ){
ulOpenFlags |= OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_CREATE_IF_NEW;
- OSTRACE(( "OPEN open new/create\n" ));
+ OSTRACE1( "OPEN open new/create\n" );
}else{
ulOpenFlags |= OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_FAIL_IF_NEW;
- OSTRACE(( "OPEN open existing\n" ));
+ OSTRACE1( "OPEN open existing\n" );
}
if( flags & SQLITE_OPEN_MAIN_DB ){
ulOpenMode |= OPEN_SHARE_DENYNONE;
- OSTRACE(( "OPEN share read/write\n" ));
+ OSTRACE1( "OPEN share read/write\n" );
}else{
ulOpenMode |= OPEN_SHARE_DENYWRITE;
- OSTRACE(( "OPEN share read only\n" ));
+ OSTRACE1( "OPEN share read only\n" );
}
if( flags & SQLITE_OPEN_DELETEONCLOSE ){
@@ -21855,10 +20974,10 @@ static int os2Open(
#endif
os2FullPathname( pVfs, zName, CCHMAXPATH, pathUtf8 );
pFile->pathToDel = convertUtf8PathToCp( pathUtf8 );
- OSTRACE(( "OPEN hidden/delete on close file attributes\n" ));
+ OSTRACE1( "OPEN hidden/delete on close file attributes\n" );
}else{
pFile->pathToDel = NULL;
- OSTRACE(( "OPEN normal file attribute\n" ));
+ OSTRACE1( "OPEN normal file attribute\n" );
}
/* always open in random access mode for possibly better speed */
@@ -21877,14 +20996,13 @@ static int os2Open(
(PEAOP2)NULL );
free( zNameCp );
if( rc != NO_ERROR ){
- OSTRACE(( "OPEN Invalid handle rc=%d: zName=%s, ulAction=%#lx, ulAttr=%#lx, ulFlags=%#lx, ulMode=%#lx\n",
- rc, zName, ulAction, ulFileAttribute, ulOpenFlags, ulOpenMode ));
+ OSTRACE7( "OPEN Invalid handle rc=%d: zName=%s, ulAction=%#lx, ulAttr=%#lx, ulFlags=%#lx, ulMode=%#lx\n",
+ rc, zName, ulAction, ulFileAttribute, ulOpenFlags, ulOpenMode );
if( pFile->pathToDel )
free( pFile->pathToDel );
pFile->pathToDel = NULL;
if( flags & SQLITE_OPEN_READWRITE ){
- OSTRACE(( "OPEN %d Invalid handle\n",
- ((flags | SQLITE_OPEN_READONLY) & ~SQLITE_OPEN_READWRITE) ));
+ OSTRACE2( "OPEN %d Invalid handle\n", ((flags | SQLITE_OPEN_READONLY) & ~SQLITE_OPEN_READWRITE) );
return os2Open( pVfs, zName, id,
((flags | SQLITE_OPEN_READONLY) & ~SQLITE_OPEN_READWRITE),
pOutFlags );
@@ -21900,7 +21018,7 @@ static int os2Open(
pFile->pMethod = &os2IoMethod;
pFile->h = h;
OpenCounter(+1);
- OSTRACE(( "OPEN %d pOutFlags=%d\n", pFile->h, pOutFlags ));
+ OSTRACE3( "OPEN %d pOutFlags=%d\n", pFile->h, pOutFlags );
return SQLITE_OK;
}
@@ -21917,7 +21035,7 @@ static int os2Delete(
SimulateIOError( return SQLITE_IOERR_DELETE );
rc = DosDelete( (PSZ)zFilenameCp );
free( zFilenameCp );
- OSTRACE(( "DELETE \"%s\"\n", zFilename ));
+ OSTRACE2( "DELETE \"%s\"\n", zFilename );
return rc == NO_ERROR ? SQLITE_OK : SQLITE_IOERR_DELETE;
}
@@ -21938,17 +21056,17 @@ static int os2Access(
rc = DosQueryPathInfo( (PSZ)zFilenameCp, FIL_STANDARD,
&fsts3ConfigInfo, sizeof(FILESTATUS3) );
free( zFilenameCp );
- OSTRACE(( "ACCESS fsts3ConfigInfo.attrFile=%d flags=%d rc=%d\n",
- fsts3ConfigInfo.attrFile, flags, rc ));
+ OSTRACE4( "ACCESS fsts3ConfigInfo.attrFile=%d flags=%d rc=%d\n",
+ fsts3ConfigInfo.attrFile, flags, rc );
switch( flags ){
case SQLITE_ACCESS_READ:
case SQLITE_ACCESS_EXISTS:
rc = (rc == NO_ERROR);
- OSTRACE(( "ACCESS %s access of read and exists rc=%d\n", zFilename, rc));
+ OSTRACE3( "ACCESS %s access of read and exists rc=%d\n", zFilename, rc );
break;
case SQLITE_ACCESS_READWRITE:
rc = (rc == NO_ERROR) && ( (fsts3ConfigInfo.attrFile & FILE_READONLY) == 0 );
- OSTRACE(( "ACCESS %s access of read/write rc=%d\n", zFilename, rc ));
+ OSTRACE3( "ACCESS %s access of read/write rc=%d\n", zFilename, rc );
break;
default:
assert( !"Invalid flags argument" );
@@ -22158,7 +21276,7 @@ SQLITE_API int sqlite3_os_init(void){
os2Randomness, /* xRandomness */
os2Sleep, /* xSleep */
os2CurrentTime, /* xCurrentTime */
- os2GetLastError, /* xGetLastError */
+ os2GetLastError /* xGetLastError */
};
sqlite3_vfs_register(&os2Vfs, 1);
initUconvObjects();
@@ -22235,7 +21353,7 @@ SQLITE_API int sqlite3_os_end(void){
** 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.
+** where the database is located.
*/
#if !defined(SQLITE_ENABLE_LOCKING_STYLE)
# if defined(__APPLE__)
@@ -22246,7 +21364,7 @@ SQLITE_API int sqlite3_os_end(void){
#endif
/*
-** Define the OS_VXWORKS pre-processor macro to 1 if building on
+** Define the OS_VXWORKS pre-processor macro to 1 if building on
** vxworks, or 0 otherwise.
*/
#ifndef OS_VXWORKS
@@ -22292,7 +21410,6 @@ SQLITE_API int sqlite3_os_end(void){
#include <unistd.h>
#include <sys/time.h>
#include <errno.h>
-#include <sys/mman.h>
#if SQLITE_ENABLE_LOCKING_STYLE
# include <sys/ioctl.h>
@@ -22302,18 +21419,10 @@ SQLITE_API int sqlite3_os_end(void){
# else
# include <sys/file.h>
# include <sys/param.h>
+# include <sys/mount.h>
# endif
#endif /* SQLITE_ENABLE_LOCKING_STYLE */
-#if defined(__APPLE__) || (SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORKS)
-# include <sys/mount.h>
-#endif
-
-/*
-** Allowed values of unixFile.fsFlags
-*/
-#define SQLITE_FSFLAGS_IS_MSDOS 0x1
-
/*
** If we are to be thread-safe, include the pthreads header and define
** the SQLITE_UNIX_THREADS macro.
@@ -22342,16 +21451,11 @@ SQLITE_API int sqlite3_os_end(void){
#define MAX_PATHNAME 512
/*
-** Only set the lastErrno if the error code is a real error and not
+** 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
*/
#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 */
/*
** Sometimes, after a file handle is closed by SQLite, the file descriptor
@@ -22359,6 +21463,7 @@ typedef struct UnixUnusedFd UnixUnusedFd; /* An unused file descriptor */
** structure are used to store the file descriptor while waiting for an
** opportunity to either close or reuse it.
*/
+typedef struct UnixUnusedFd UnixUnusedFd;
struct UnixUnusedFd {
int fd; /* File descriptor to close */
int flags; /* Flags this file descriptor was opened with */
@@ -22372,25 +21477,24 @@ struct UnixUnusedFd {
typedef struct unixFile unixFile;
struct unixFile {
sqlite3_io_methods const *pMethod; /* Always the first entry */
- unixInodeInfo *pInode; /* Info about locks on this inode */
- int h; /* The file descriptor */
- int dirfd; /* File descriptor for the directory */
- unsigned char eFileLock; /* The type of lock held on this fd */
- int lastErrno; /* The unix errno from last I/O error */
- void *lockingContext; /* Locking style specific state */
- UnixUnusedFd *pUnused; /* Pre-allocated UnixUnusedFd */
- int fileFlags; /* Miscellanous flags */
- const char *zPath; /* Name of the file */
- unixShm *pShm; /* Shared memory segment information */
+ struct unixOpenCnt *pOpen; /* Info about all open fd's on this inode */
+ struct unixLockInfo *pLock; /* Info about locks on this inode */
+ int h; /* The file descriptor */
+ int dirfd; /* File descriptor for the directory */
+ unsigned char locktype; /* The type of lock held on this fd */
+ int lastErrno; /* The unix errno from the last I/O error */
+ void *lockingContext; /* Locking style specific state */
+ UnixUnusedFd *pUnused; /* Pre-allocated UnixUnusedFd */
+ int fileFlags; /* Miscellanous flags */
#if SQLITE_ENABLE_LOCKING_STYLE
- int openFlags; /* The flags specified at open() */
+ int openFlags; /* The flags specified at open() */
#endif
-#if SQLITE_ENABLE_LOCKING_STYLE || defined(__APPLE__)
- unsigned fsFlags; /* cached details from statfs() */
+#if SQLITE_THREADSAFE && defined(__linux__)
+ pthread_t tid; /* The thread that "owns" this unixFile */
#endif
#if OS_VXWORKS
- int isDelete; /* Delete on close if true */
- struct vxworksFileId *pId; /* Unique file ID */
+ int isDelete; /* Delete on close if true */
+ struct vxworksFileId *pId; /* Unique file ID */
#endif
#ifndef NDEBUG
/* The next group of variables are used to track whether or not the
@@ -22398,14 +21502,14 @@ struct unixFile {
** 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.
+ ** 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 */
#endif
#ifdef SQLITE_TEST
- /* In test mode, increase the size of this structure a bit so that
+ /* 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];
@@ -22455,9 +21559,23 @@ struct unixFile {
#ifdef SQLITE_DEBUG
SQLITE_PRIVATE int sqlite3OSTrace = 0;
-#define OSTRACE(X) if( sqlite3OSTrace ) sqlite3DebugPrintf X
+#define OSTRACE1(X) if( sqlite3OSTrace ) sqlite3DebugPrintf(X)
+#define OSTRACE2(X,Y) if( sqlite3OSTrace ) sqlite3DebugPrintf(X,Y)
+#define OSTRACE3(X,Y,Z) if( sqlite3OSTrace ) sqlite3DebugPrintf(X,Y,Z)
+#define OSTRACE4(X,Y,Z,A) if( sqlite3OSTrace ) sqlite3DebugPrintf(X,Y,Z,A)
+#define OSTRACE5(X,Y,Z,A,B) if( sqlite3OSTrace ) sqlite3DebugPrintf(X,Y,Z,A,B)
+#define OSTRACE6(X,Y,Z,A,B,C) \
+ if(sqlite3OSTrace) sqlite3DebugPrintf(X,Y,Z,A,B,C)
+#define OSTRACE7(X,Y,Z,A,B,C,D) \
+ if(sqlite3OSTrace) sqlite3DebugPrintf(X,Y,Z,A,B,C,D)
#else
-#define OSTRACE(X)
+#define OSTRACE1(X)
+#define OSTRACE2(X,Y)
+#define OSTRACE3(X,Y,Z)
+#define OSTRACE4(X,Y,Z,A)
+#define OSTRACE5(X,Y,Z,A,B)
+#define OSTRACE6(X,Y,Z,A,B,C)
+#define OSTRACE7(X,Y,Z,A,B,C,D)
#endif
/*
@@ -22466,8 +21584,8 @@ SQLITE_PRIVATE int sqlite3OSTrace = 0;
*/
#ifdef SQLITE_PERFORMANCE_TRACE
-/*
-** hwtime.h contains inline assembler code for implementing
+/*
+** hwtime.h contains inline assembler code for implementing
** high-performance timing routines.
*/
/************** Include hwtime.h in the middle of os_common.h ****************/
@@ -22525,7 +21643,7 @@ SQLITE_PRIVATE int sqlite3OSTrace = 0;
__asm__ __volatile__ ("rdtsc" : "=A" (val));
return val;
}
-
+
#elif (defined(__GNUC__) && defined(__ppc__))
__inline__ sqlite_uint64 sqlite3Hwtime(void){
@@ -22667,12 +21785,12 @@ SQLITE_API int sqlite3_open_file_count = 0;
/*
** 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
+** global mutex is used to protect the unixOpenCnt, unixLockInfo 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()
+** 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()
@@ -22698,8 +21816,8 @@ static int unixMutexHeld(void) {
** binaries. This returns the string represetation of the supplied
** integer lock-type.
*/
-static const char *azFileLock(int eFileLock){
- switch( eFileLock ){
+static const char *locktypeName(int locktype){
+ switch( locktype ){
case NO_LOCK: return "NONE";
case SHARED_LOCK: return "SHARED";
case RESERVED_LOCK: return "RESERVED";
@@ -22775,49 +21893,49 @@ static int lockTrace(int fd, int op, struct flock *p){
** 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
+** 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) {
- case 0:
+ case 0:
return SQLITE_OK;
-
+
case EAGAIN:
case ETIMEDOUT:
case EBUSY:
case EINTR:
- case ENOLCK:
- /* random NFS retry error, unless during file system support
+ 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:
+
+ case EACCES:
/* EACCES is like EAGAIN during locking operations, but not any other time*/
- if( (sqliteIOErr == SQLITE_IOERR_LOCK) ||
- (sqliteIOErr == SQLITE_IOERR_UNLOCK) ||
+ if( (sqliteIOErr == SQLITE_IOERR_LOCK) ||
+ (sqliteIOErr == SQLITE_IOERR_UNLOCK) ||
(sqliteIOErr == SQLITE_IOERR_RDLOCK) ||
(sqliteIOErr == SQLITE_IOERR_CHECKRESERVEDLOCK) ){
return SQLITE_BUSY;
}
/* else fall through */
- case EPERM:
+ case EPERM:
return SQLITE_PERM;
-
+
case EDEADLK:
return SQLITE_IOERR_BLOCKED;
-
+
#if EOPNOTSUPP!=ENOTSUP
- case EOPNOTSUPP:
- /* something went terribly awry, unless during file system support
+ 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
+ case ENOTSUP:
+ /* invalid fd, unless during file system support introspection, in which
* it actually means what it says */
#endif
case EIO:
@@ -22830,8 +21948,8 @@ static int sqliteErrorFromPosixError(int posixError, int sqliteIOErr) {
case ESTALE:
case ENOSYS:
/* these should force the client to close the file and reconnect */
-
- default:
+
+ default:
return sqliteIOErr;
}
}
@@ -22847,7 +21965,7 @@ static int sqliteErrorFromPosixError(int posixError, int sqliteIOErr) {
**
** 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.
+** 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.
**
@@ -22863,7 +21981,7 @@ struct vxworksFileId {
};
#if OS_VXWORKS
-/*
+/*
** All unique filenames are held on a linked list headed by this
** variable:
*/
@@ -22935,7 +22053,7 @@ static struct vxworksFileId *vxworksFindFileId(const char *zAbsoluteName){
*/
unixEnterMutex();
for(pCandidate=vxworksFileList; pCandidate; pCandidate=pCandidate->pNext){
- if( pCandidate->nName==n
+ if( pCandidate->nName==n
&& memcmp(pCandidate->zCanonicalName, pNew->zCanonicalName, n)==0
){
sqlite3_free(pNew);
@@ -23028,7 +22146,7 @@ static void vxworksReleaseFileId(struct vxworksFileId *pId){
** 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
+** 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.
**
@@ -23036,12 +22154,13 @@ static void vxworksReleaseFileId(struct vxworksFileId *pId){
**
** 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
+** released. To work around this problem, each unixFile structure contains
+** a pointer to an unixOpenCnt structure. There is one unixOpenCnt structure
+** per open inode, which means that multiple unixFile can point to a single
+** unixOpenCnt. 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
+** The unixOpenCnt structure keeps a list of file descriptors that need to
** be closed and that list is walked (and cleared) when the last lock
** clears.
**
@@ -23056,19 +22175,46 @@ static void vxworksReleaseFileId(struct vxworksFileId *pId){
** 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
+** We have 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.
-*/
+** On systems where thread A is unable to modify locks created by
+** thread B, we have to keep track of which thread created each
+** lock. Hence there is an extra field in the key to the unixLockInfo
+** structure to record this information. And on those systems it
+** is illegal to begin a transaction in one thread and finish it
+** in another. For this latter restriction, there is no work-around.
+** It is a limitation of LinuxThreads.
+*/
+
+/*
+** Set or check the unixFile.tid field. This field is set when an unixFile
+** is first opened. All subsequent uses of the unixFile verify that the
+** same thread is operating on the unixFile. Some operating systems do
+** not allow locks to be overridden by other threads and that restriction
+** means that sqlite3* database handles cannot be moved from one thread
+** to another while locks are held.
+**
+** Version 3.3.1 (2006-01-15): unixFile can be moved from one thread to
+** another as long as we are running on a system that supports threads
+** overriding each others locks (which is now the most common behavior)
+** or if no locks are held. But the unixFile.pLock field needs to be
+** recomputed because its key includes the thread-id. See the
+** transferOwnership() function below for additional information
+*/
+#if SQLITE_THREADSAFE && defined(__linux__)
+# define SET_THREADID(X) (X)->tid = pthread_self()
+# define CHECK_THREADID(X) (threadsOverrideEachOthersLocks==0 && \
+ !pthread_equal((X)->tid, pthread_self()))
+#else
+# define SET_THREADID(X)
+# define CHECK_THREADID(X) 0
+#endif
/*
** An instance of the following structure serves as the key used
-** to locate a particular unixInodeInfo object.
+** to locate a particular unixOpenCnt structure given its inode. This
+** is the same as the unixLockKey except that the thread ID is omitted.
*/
struct unixFileId {
dev_t dev; /* Device number */
@@ -23080,6 +22226,23 @@ struct unixFileId {
};
/*
+** An instance of the following structure serves as the key used
+** to locate a particular unixLockInfo structure given its inode.
+**
+** If threads cannot override each others locks (LinuxThreads), then we
+** set the unixLockKey.tid field to the thread ID. If threads can override
+** each others locks (Posix and NPTL) then tid is always set to zero.
+** tid is omitted if we compile without threading support or on an OS
+** other than linux.
+*/
+struct unixLockKey {
+ struct unixFileId fid; /* Unique identifier for the file */
+#if SQLITE_THREADSAFE && defined(__linux__)
+ pthread_t tid; /* Thread ID of lock owner. Zero if not using LinuxThreads */
+#endif
+};
+
+/*
** 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.
@@ -23088,77 +22251,227 @@ struct unixFileId {
** structure contains a pointer to an instance of this object and this
** object keeps a count of the number of unixFile pointing to it.
*/
-struct unixInodeInfo {
- struct unixFileId fileId; /* The lookup key */
- int nShared; /* Number of SHARED locks held */
- int eFileLock; /* One of SHARED_LOCK, RESERVED_LOCK etc. */
+struct unixLockInfo {
+ struct unixLockKey lockKey; /* The lookup key */
+ int cnt; /* Number of SHARED locks held */
+ int locktype; /* One of SHARED_LOCK, RESERVED_LOCK etc. */
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 defined(SQLITE_ENABLE_LOCKING_STYLE)
- unsigned long long sharedByte; /* for AFP simulated shared lock */
-#endif
+ struct unixLockInfo *pNext; /* List of all unixLockInfo objects */
+ struct unixLockInfo *pPrev; /* .... doubly linked */
+};
+
+/*
+** An instance of the following structure is allocated for each open
+** inode. This structure keeps track of the number of locks on that
+** inode. If a close is attempted against an inode that is holding
+** locks, the close is deferred until all locks clear by adding the
+** file descriptor to be closed to the pending list.
+**
+** TODO: Consider changing this so that there is only a single file
+** descriptor for each open file, even when it is opened multiple times.
+** The close() system call would only occur when the last database
+** using the file closes.
+*/
+struct unixOpenCnt {
+ struct unixFileId fileId; /* The lookup key */
+ int nRef; /* Number of pointers to this structure */
+ int nLock; /* Number of outstanding locks */
+ UnixUnusedFd *pUnused; /* Unused file descriptors to close */
#if OS_VXWORKS
- sem_t *pSem; /* Named POSIX semaphore */
- char aSemName[MAX_PATHNAME+2]; /* Name of that semaphore */
+ sem_t *pSem; /* Named POSIX semaphore */
+ char aSemName[MAX_PATHNAME+2]; /* Name of that semaphore */
+#endif
+ struct unixOpenCnt *pNext, *pPrev; /* List of all unixOpenCnt objects */
+};
+
+/*
+** Lists of all unixLockInfo and unixOpenCnt objects. These used to be hash
+** tables. But the number of objects is rarely more than a dozen and
+** never exceeds a few thousand. And lookup is not on a critical
+** path so a simple linked list will suffice.
+*/
+static struct unixLockInfo *lockList = 0;
+static struct unixOpenCnt *openList = 0;
+
+/*
+** This variable remembers whether or not threads can override each others
+** locks.
+**
+** 0: No. Threads cannot override each others locks. (LinuxThreads)
+** 1: Yes. Threads can override each others locks. (Posix & NLPT)
+** -1: We don't know yet.
+**
+** On some systems, we know at compile-time if threads can override each
+** others locks. On those systems, the SQLITE_THREAD_OVERRIDE_LOCK macro
+** will be set appropriately. On other systems, we have to check at
+** runtime. On these latter systems, SQLTIE_THREAD_OVERRIDE_LOCK is
+** undefined.
+**
+** This variable normally has file scope only. But during testing, we make
+** it a global so that the test code can change its value in order to verify
+** that the right stuff happens in either case.
+*/
+#if SQLITE_THREADSAFE && defined(__linux__)
+# ifndef SQLITE_THREAD_OVERRIDE_LOCK
+# define SQLITE_THREAD_OVERRIDE_LOCK -1
+# endif
+# ifdef SQLITE_TEST
+int threadsOverrideEachOthersLocks = SQLITE_THREAD_OVERRIDE_LOCK;
+# else
+static int threadsOverrideEachOthersLocks = SQLITE_THREAD_OVERRIDE_LOCK;
+# endif
#endif
+
+/*
+** This structure holds information passed into individual test
+** threads by the testThreadLockingBehavior() routine.
+*/
+struct threadTestData {
+ int fd; /* File to be locked */
+ struct flock lock; /* The locking operation */
+ int result; /* Result of the locking operation */
};
+#if SQLITE_THREADSAFE && defined(__linux__)
+/*
+** This function is used as the main routine for a thread launched by
+** testThreadLockingBehavior(). It tests whether the shared-lock obtained
+** by the main thread in testThreadLockingBehavior() conflicts with a
+** hypothetical write-lock obtained by this thread on the same file.
+**
+** The write-lock is not actually acquired, as this is not possible if
+** the file is open in read-only mode (see ticket #3472).
+*/
+static void *threadLockingTest(void *pArg){
+ struct threadTestData *pData = (struct threadTestData*)pArg;
+ pData->result = fcntl(pData->fd, F_GETLK, &pData->lock);
+ return pArg;
+}
+#endif /* SQLITE_THREADSAFE && defined(__linux__) */
+
+
+#if SQLITE_THREADSAFE && defined(__linux__)
/*
-** A lists of all unixInodeInfo objects.
+** This procedure attempts to determine whether or not threads
+** can override each others locks then sets the
+** threadsOverrideEachOthersLocks variable appropriately.
+*/
+static void testThreadLockingBehavior(int fd_orig){
+ int fd;
+ int rc;
+ struct threadTestData d;
+ struct flock l;
+ pthread_t t;
+
+ fd = dup(fd_orig);
+ if( fd<0 ) return;
+ memset(&l, 0, sizeof(l));
+ l.l_type = F_RDLCK;
+ l.l_len = 1;
+ l.l_start = 0;
+ l.l_whence = SEEK_SET;
+ rc = fcntl(fd_orig, F_SETLK, &l);
+ if( rc!=0 ) return;
+ memset(&d, 0, sizeof(d));
+ d.fd = fd;
+ d.lock = l;
+ d.lock.l_type = F_WRLCK;
+ if( pthread_create(&t, 0, threadLockingTest, &d)==0 ){
+ pthread_join(t, 0);
+ }
+ close(fd);
+ if( d.result!=0 ) return;
+ threadsOverrideEachOthersLocks = (d.lock.l_type==F_UNLCK);
+}
+#endif /* SQLITE_THREADSAFE && defined(__linux__) */
+
+/*
+** Release a unixLockInfo structure previously allocated by findLockInfo().
+**
+** The mutex entered using the unixEnterMutex() function must be held
+** when this function is called.
*/
-static unixInodeInfo *inodeList = 0;
+static void releaseLockInfo(struct unixLockInfo *pLock){
+ assert( unixMutexHeld() );
+ if( pLock ){
+ pLock->nRef--;
+ if( pLock->nRef==0 ){
+ if( pLock->pPrev ){
+ assert( pLock->pPrev->pNext==pLock );
+ pLock->pPrev->pNext = pLock->pNext;
+ }else{
+ assert( lockList==pLock );
+ lockList = pLock->pNext;
+ }
+ if( pLock->pNext ){
+ assert( pLock->pNext->pPrev==pLock );
+ pLock->pNext->pPrev = pLock->pPrev;
+ }
+ sqlite3_free(pLock);
+ }
+ }
+}
/*
-** Release a unixInodeInfo structure previously allocated by findInodeInfo().
+** Release a unixOpenCnt structure previously allocated by findLockInfo().
**
** The mutex entered using the unixEnterMutex() function must be held
** when this function is called.
*/
-static void releaseInodeInfo(unixInodeInfo *pInode){
+static void releaseOpenCnt(struct unixOpenCnt *pOpen){
assert( unixMutexHeld() );
- if( pInode ){
- pInode->nRef--;
- if( pInode->nRef==0 ){
- assert( pInode->pShmNode==0 );
- if( pInode->pPrev ){
- assert( pInode->pPrev->pNext==pInode );
- pInode->pPrev->pNext = pInode->pNext;
+ if( pOpen ){
+ pOpen->nRef--;
+ if( pOpen->nRef==0 ){
+ if( pOpen->pPrev ){
+ assert( pOpen->pPrev->pNext==pOpen );
+ pOpen->pPrev->pNext = pOpen->pNext;
}else{
- assert( inodeList==pInode );
- inodeList = pInode->pNext;
+ assert( openList==pOpen );
+ openList = pOpen->pNext;
}
- if( pInode->pNext ){
- assert( pInode->pNext->pPrev==pInode );
- pInode->pNext->pPrev = pInode->pPrev;
+ if( pOpen->pNext ){
+ assert( pOpen->pNext->pPrev==pOpen );
+ pOpen->pNext->pPrev = pOpen->pPrev;
}
- sqlite3_free(pInode);
+#if SQLITE_THREADSAFE && defined(__linux__)
+ assert( !pOpen->pUnused || threadsOverrideEachOthersLocks==0 );
+#endif
+
+ /* If pOpen->pUnused is not null, then memory and file-descriptors
+ ** are leaked.
+ **
+ ** This will only happen if, under Linuxthreads, the user has opened
+ ** a transaction in one thread, then attempts to close the database
+ ** handle from another thread (without first unlocking the db file).
+ ** This is a misuse. */
+ sqlite3_free(pOpen);
}
}
}
/*
-** 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.
+** Given a file descriptor, locate unixLockInfo and unixOpenCnt structures that
+** describes that file descriptor. Create new ones if necessary. The
+** return values 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(
+static int findLockInfo(
unixFile *pFile, /* Unix file with file desc used in the key */
- unixInodeInfo **ppInode /* Return the unixInodeInfo object here */
+ struct unixLockInfo **ppLock, /* Return the unixLockInfo structure here */
+ struct unixOpenCnt **ppOpen /* Return the unixOpenCnt structure here */
){
int rc; /* System call return code */
int fd; /* The file descriptor for pFile */
- struct unixFileId fileId; /* Lookup key for the unixInodeInfo */
+ struct unixLockKey lockKey; /* Lookup key for the unixLockInfo structure */
+ struct unixFileId fileId; /* Lookup key for the unixOpenCnt struct */
struct stat statbuf; /* Low-level file information */
- unixInodeInfo *pInode = 0; /* Candidate unixInodeInfo object */
+ struct unixLockInfo *pLock = 0;/* Candidate unixLockInfo object */
+ struct unixOpenCnt *pOpen; /* Candidate unixOpenCnt object */
assert( unixMutexHeld() );
@@ -23186,10 +22499,9 @@ static int findInodeInfo(
** 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 ){
+ if( statbuf.st_size==0 ){
rc = write(fd, "S", 1);
if( rc!=1 ){
- pFile->lastErrno = errno;
return SQLITE_IOERR;
}
rc = fstat(fd, &statbuf);
@@ -23200,36 +22512,120 @@ static int findInodeInfo(
}
#endif
- memset(&fileId, 0, sizeof(fileId));
- fileId.dev = statbuf.st_dev;
+ memset(&lockKey, 0, sizeof(lockKey));
+ lockKey.fid.dev = statbuf.st_dev;
#if OS_VXWORKS
- fileId.pId = pFile->pId;
+ lockKey.fid.pId = pFile->pId;
#else
- fileId.ino = statbuf.st_ino;
+ lockKey.fid.ino = statbuf.st_ino;
#endif
- pInode = inodeList;
- while( pInode && memcmp(&fileId, &pInode->fileId, sizeof(fileId)) ){
- pInode = pInode->pNext;
+#if SQLITE_THREADSAFE && defined(__linux__)
+ if( threadsOverrideEachOthersLocks<0 ){
+ testThreadLockingBehavior(fd);
}
- if( pInode==0 ){
- pInode = sqlite3_malloc( sizeof(*pInode) );
- if( pInode==0 ){
- return SQLITE_NOMEM;
+ lockKey.tid = threadsOverrideEachOthersLocks ? 0 : pthread_self();
+#endif
+ fileId = lockKey.fid;
+ if( ppLock!=0 ){
+ pLock = lockList;
+ while( pLock && memcmp(&lockKey, &pLock->lockKey, sizeof(lockKey)) ){
+ pLock = pLock->pNext;
}
- 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++;
+ if( pLock==0 ){
+ pLock = sqlite3_malloc( sizeof(*pLock) );
+ if( pLock==0 ){
+ rc = SQLITE_NOMEM;
+ goto exit_findlockinfo;
+ }
+ memcpy(&pLock->lockKey,&lockKey,sizeof(lockKey));
+ pLock->nRef = 1;
+ pLock->cnt = 0;
+ pLock->locktype = 0;
+ pLock->pNext = lockList;
+ pLock->pPrev = 0;
+ if( lockList ) lockList->pPrev = pLock;
+ lockList = pLock;
+ }else{
+ pLock->nRef++;
+ }
+ *ppLock = pLock;
}
- *ppInode = pInode;
- return SQLITE_OK;
+ if( ppOpen!=0 ){
+ pOpen = openList;
+ while( pOpen && memcmp(&fileId, &pOpen->fileId, sizeof(fileId)) ){
+ pOpen = pOpen->pNext;
+ }
+ if( pOpen==0 ){
+ pOpen = sqlite3_malloc( sizeof(*pOpen) );
+ if( pOpen==0 ){
+ releaseLockInfo(pLock);
+ rc = SQLITE_NOMEM;
+ goto exit_findlockinfo;
+ }
+ memset(pOpen, 0, sizeof(*pOpen));
+ pOpen->fileId = fileId;
+ pOpen->nRef = 1;
+ pOpen->pNext = openList;
+ if( openList ) openList->pPrev = pOpen;
+ openList = pOpen;
+ }else{
+ pOpen->nRef++;
+ }
+ *ppOpen = pOpen;
+ }
+
+exit_findlockinfo:
+ return rc;
}
+/*
+** If we are currently in a different thread than the thread that the
+** unixFile argument belongs to, then transfer ownership of the unixFile
+** over to the current thread.
+**
+** A unixFile is only owned by a thread on systems that use LinuxThreads.
+**
+** Ownership transfer is only allowed if the unixFile is currently unlocked.
+** If the unixFile is locked and an ownership is wrong, then return
+** SQLITE_MISUSE. SQLITE_OK is returned if everything works.
+*/
+#if SQLITE_THREADSAFE && defined(__linux__)
+static int transferOwnership(unixFile *pFile){
+ int rc;
+ pthread_t hSelf;
+ if( threadsOverrideEachOthersLocks ){
+ /* Ownership transfers not needed on this system */
+ return SQLITE_OK;
+ }
+ hSelf = pthread_self();
+ if( pthread_equal(pFile->tid, hSelf) ){
+ /* We are still in the same thread */
+ OSTRACE1("No-transfer, same thread\n");
+ return SQLITE_OK;
+ }
+ if( pFile->locktype!=NO_LOCK ){
+ /* We cannot change ownership while we are holding a lock! */
+ return SQLITE_MISUSE_BKPT;
+ }
+ OSTRACE4("Transfer ownership of %d from %d to %d\n",
+ pFile->h, pFile->tid, hSelf);
+ pFile->tid = hSelf;
+ if (pFile->pLock != NULL) {
+ releaseLockInfo(pFile->pLock);
+ rc = findLockInfo(pFile, &pFile->pLock, 0);
+ OSTRACE5("LOCK %d is now %s(%s,%d)\n", pFile->h,
+ locktypeName(pFile->locktype),
+ locktypeName(pFile->pLock->locktype), pFile->pLock->cnt);
+ return rc;
+ } else {
+ return SQLITE_OK;
+ }
+}
+#else /* if not SQLITE_THREADSAFE */
+ /* On single-threaded builds, ownership transfer is a no-op */
+# define transferOwnership(X) SQLITE_OK
+#endif /* SQLITE_THREADSAFE */
+
/*
** This routine checks if there is a RESERVED lock held on the specified
@@ -23245,10 +22641,10 @@ static int unixCheckReservedLock(sqlite3_file *id, int *pResOut){
SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
assert( pFile );
- unixEnterMutex(); /* Because pFile->pInode is shared across threads */
+ unixEnterMutex(); /* Because pFile->pLock is shared across threads */
/* Check if a thread in this process holds such a lock */
- if( pFile->pInode->eFileLock>SHARED_LOCK ){
+ if( pFile->pLock->locktype>SHARED_LOCK ){
reserved = 1;
}
@@ -23270,16 +22666,72 @@ static int unixCheckReservedLock(sqlite3_file *id, int *pResOut){
}
}
#endif
-
+
unixLeaveMutex();
- OSTRACE(("TEST WR-LOCK %d %d %d (unix)\n", pFile->h, rc, reserved));
+ OSTRACE4("TEST WR-LOCK %d %d %d (unix)\n", pFile->h, rc, reserved);
*pResOut = reserved;
return rc;
}
/*
-** Lock the file with the lock specified by parameter eFileLock - one
+** Perform a file locking operation on a range of bytes in a file.
+** The "op" parameter should be one of F_RDLCK, F_WRLCK, or F_UNLCK.
+** Return 0 on success or -1 for failure. On failure, write the error
+** code into *pErrcode.
+**
+** If the SQLITE_WHOLE_FILE_LOCKING bit is clear, then only lock
+** the range of bytes on the locking page between SHARED_FIRST and
+** SHARED_SIZE. If SQLITE_WHOLE_FILE_LOCKING is set, then lock all
+** bytes from 0 up to but not including PENDING_BYTE, and all bytes
+** that follow SHARED_FIRST.
+**
+** In other words, of SQLITE_WHOLE_FILE_LOCKING if false (the historical
+** default case) then only lock a small range of bytes from SHARED_FIRST
+** through SHARED_FIRST+SHARED_SIZE-1. But if SQLITE_WHOLE_FILE_LOCKING is
+** true then lock every byte in the file except for PENDING_BYTE and
+** RESERVED_BYTE.
+**
+** SQLITE_WHOLE_FILE_LOCKING=true overlaps SQLITE_WHOLE_FILE_LOCKING=false
+** and so the locking schemes are compatible. One type of lock will
+** effectively exclude the other type. The reason for using the
+** SQLITE_WHOLE_FILE_LOCKING=true is that by indicating the full range
+** of bytes to be read or written, we give hints to NFS to help it
+** maintain cache coherency. On the other hand, whole file locking
+** is slower, so we don't want to use it except for NFS.
+*/
+static int rangeLock(unixFile *pFile, int op, int *pErrcode){
+ struct flock lock;
+ int rc;
+ lock.l_type = op;
+ lock.l_start = SHARED_FIRST;
+ lock.l_whence = SEEK_SET;
+ if( (pFile->fileFlags & SQLITE_WHOLE_FILE_LOCKING)==0 ){
+ lock.l_len = SHARED_SIZE;
+ rc = fcntl(pFile->h, F_SETLK, &lock);
+ *pErrcode = errno;
+ }else{
+ lock.l_len = 0;
+ rc = fcntl(pFile->h, F_SETLK, &lock);
+ *pErrcode = errno;
+ if( NEVER(op==F_UNLCK) || rc!=(-1) ){
+ lock.l_start = 0;
+ lock.l_len = PENDING_BYTE;
+ rc = fcntl(pFile->h, F_SETLK, &lock);
+ if( ALWAYS(op!=F_UNLCK) && rc==(-1) ){
+ *pErrcode = errno;
+ lock.l_type = F_UNLCK;
+ lock.l_start = SHARED_FIRST;
+ lock.l_len = 0;
+ fcntl(pFile->h, F_SETLK, &lock);
+ }
+ }
+ }
+ return rc;
+}
+
+/*
+** Lock the file with the lock specified by parameter locktype - one
** of the following:
**
** (1) SHARED_LOCK
@@ -23302,7 +22754,7 @@ static int unixCheckReservedLock(sqlite3_file *id, int *pResOut){
** This routine will only increase a lock. Use the sqlite3OsUnlock()
** routine to lower a locking level.
*/
-static int unixLock(sqlite3_file *id, int eFileLock){
+static int unixLock(sqlite3_file *id, int locktype){
/* 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
@@ -23320,7 +22772,7 @@ static int unixLock(sqlite3_file *id, int eFileLock){
**
** 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'.
+ ** '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
@@ -23334,7 +22786,7 @@ static int unixLock(sqlite3_file *id, int eFileLock){
** 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.
+ ** 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
@@ -23343,23 +22795,23 @@ static int unixLock(sqlite3_file *id, int eFileLock){
*/
int rc = SQLITE_OK;
unixFile *pFile = (unixFile*)id;
- unixInodeInfo *pInode = pFile->pInode;
+ struct unixLockInfo *pLock = pFile->pLock;
struct flock lock;
int s = 0;
- int tErrno = 0;
+ int tErrno;
assert( pFile );
- OSTRACE(("LOCK %d %s was %s(%s,%d) pid=%d (unix)\n", pFile->h,
- azFileLock(eFileLock), azFileLock(pFile->eFileLock),
- azFileLock(pInode->eFileLock), pInode->nShared , getpid()));
+ OSTRACE7("LOCK %d %s was %s(%s,%d) pid=%d (unix)\n", pFile->h,
+ locktypeName(locktype), locktypeName(pFile->locktype),
+ locktypeName(pLock->locktype), pLock->cnt , getpid());
/* 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)));
+ if( pFile->locktype>=locktype ){
+ OSTRACE3("LOCK %d %s ok (already held) (unix)\n", pFile->h,
+ locktypeName(locktype));
return SQLITE_OK;
}
@@ -23368,20 +22820,28 @@ static int unixLock(sqlite3_file *id, int eFileLock){
** (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 );
+ assert( pFile->locktype!=NO_LOCK || locktype==SHARED_LOCK );
+ assert( locktype!=PENDING_LOCK );
+ assert( locktype!=RESERVED_LOCK || pFile->locktype==SHARED_LOCK );
- /* This mutex is needed because pFile->pInode is shared across threads
+ /* This mutex is needed because pFile->pLock is shared across threads
*/
unixEnterMutex();
- pInode = pFile->pInode;
+
+ /* Make sure the current thread owns the pFile.
+ */
+ rc = transferOwnership(pFile);
+ if( rc!=SQLITE_OK ){
+ unixLeaveMutex();
+ return rc;
+ }
+ pLock = pFile->pLock;
/* 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))
+ if( (pFile->locktype!=pLock->locktype &&
+ (pLock->locktype>=PENDING_LOCK || locktype>SHARED_LOCK))
){
rc = SQLITE_BUSY;
goto end_lock;
@@ -23391,14 +22851,14 @@ static int unixLock(sqlite3_file *id, int eFileLock){
** 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++;
+ if( locktype==SHARED_LOCK &&
+ (pLock->locktype==SHARED_LOCK || pLock->locktype==RESERVED_LOCK) ){
+ assert( locktype==SHARED_LOCK );
+ assert( pFile->locktype==0 );
+ assert( pLock->cnt>0 );
+ pFile->locktype = SHARED_LOCK;
+ pLock->cnt++;
+ pFile->pOpen->nLock++;
goto end_lock;
}
@@ -23409,10 +22869,10 @@ static int unixLock(sqlite3_file *id, int eFileLock){
*/
lock.l_len = 1L;
lock.l_whence = SEEK_SET;
- if( eFileLock==SHARED_LOCK
- || (eFileLock==EXCLUSIVE_LOCK && pFile->eFileLock<PENDING_LOCK)
+ if( locktype==SHARED_LOCK
+ || (locktype==EXCLUSIVE_LOCK && pFile->locktype<PENDING_LOCK)
){
- lock.l_type = (eFileLock==SHARED_LOCK?F_RDLCK:F_WRLCK);
+ lock.l_type = (locktype==SHARED_LOCK?F_RDLCK:F_WRLCK);
lock.l_start = PENDING_BYTE;
s = fcntl(pFile->h, F_SETLK, &lock);
if( s==(-1) ){
@@ -23429,16 +22889,13 @@ static int unixLock(sqlite3_file *id, int eFileLock){
/* 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 );
+ if( locktype==SHARED_LOCK ){
+ assert( pLock->cnt==0 );
+ assert( pLock->locktype==0 );
/* Now get the read-lock */
- lock.l_start = SHARED_FIRST;
- lock.l_len = SHARED_SIZE;
- if( (s = fcntl(pFile->h, F_SETLK, &lock))==(-1) ){
- tErrno = errno;
- }
+ s = rangeLock(pFile, F_RDLCK, &tErrno);
+
/* Drop the temporary PENDING lock */
lock.l_start = PENDING_BYTE;
lock.l_len = 1L;
@@ -23446,8 +22903,8 @@ static int unixLock(sqlite3_file *id, int eFileLock){
if( fcntl(pFile->h, F_SETLK, &lock)!=0 ){
if( s != -1 ){
/* This could happen with a network mount */
- tErrno = errno;
- rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK);
+ tErrno = errno;
+ rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK);
if( IS_LOCK_ERROR(rc) ){
pFile->lastErrno = tErrno;
}
@@ -23460,11 +22917,11 @@ static int unixLock(sqlite3_file *id, int eFileLock){
pFile->lastErrno = tErrno;
}
}else{
- pFile->eFileLock = SHARED_LOCK;
- pInode->nLock++;
- pInode->nShared = 1;
+ pFile->locktype = SHARED_LOCK;
+ pFile->pOpen->nLock++;
+ pLock->cnt = 1;
}
- }else if( eFileLock==EXCLUSIVE_LOCK && pInode->nShared>1 ){
+ }else if( locktype==EXCLUSIVE_LOCK && pLock->cnt>1 ){
/* We are trying for an exclusive lock but another thread in this
** same process is still holding a shared lock. */
rc = SQLITE_BUSY;
@@ -23473,29 +22930,28 @@ static int unixLock(sqlite3_file *id, int eFileLock){
** assumed that there is a SHARED or greater lock on the file
** already.
*/
- assert( 0!=pFile->eFileLock );
+ assert( 0!=pFile->locktype );
lock.l_type = F_WRLCK;
- switch( eFileLock ){
+ switch( locktype ){
case RESERVED_LOCK:
lock.l_start = RESERVED_BYTE;
+ s = fcntl(pFile->h, F_SETLK, &lock);
+ tErrno = errno;
break;
case EXCLUSIVE_LOCK:
- lock.l_start = SHARED_FIRST;
- lock.l_len = SHARED_SIZE;
+ s = rangeLock(pFile, F_WRLCK, &tErrno);
break;
default:
assert(0);
}
- s = fcntl(pFile->h, F_SETLK, &lock);
if( s==(-1) ){
- tErrno = errno;
rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
if( IS_LOCK_ERROR(rc) ){
pFile->lastErrno = tErrno;
}
}
}
-
+
#ifndef NDEBUG
/* Set up the transaction-counter change checking flags when
@@ -23504,8 +22960,8 @@ static int unixLock(sqlite3_file *id, int eFileLock){
** write operation (not a hot journal rollback).
*/
if( rc==SQLITE_OK
- && pFile->eFileLock<=SHARED_LOCK
- && eFileLock==RESERVED_LOCK
+ && pFile->locktype<=SHARED_LOCK
+ && locktype==RESERVED_LOCK
){
pFile->transCntrChng = 0;
pFile->dbUpdate = 0;
@@ -23515,36 +22971,36 @@ static int unixLock(sqlite3_file *id, int eFileLock){
if( rc==SQLITE_OK ){
- pFile->eFileLock = eFileLock;
- pInode->eFileLock = eFileLock;
- }else if( eFileLock==EXCLUSIVE_LOCK ){
- pFile->eFileLock = PENDING_LOCK;
- pInode->eFileLock = PENDING_LOCK;
+ pFile->locktype = locktype;
+ pLock->locktype = locktype;
+ }else if( locktype==EXCLUSIVE_LOCK ){
+ pFile->locktype = PENDING_LOCK;
+ pLock->locktype = PENDING_LOCK;
}
end_lock:
unixLeaveMutex();
- OSTRACE(("LOCK %d %s %s (unix)\n", pFile->h, azFileLock(eFileLock),
- rc==SQLITE_OK ? "ok" : "failed"));
+ OSTRACE4("LOCK %d %s %s (unix)\n", pFile->h, locktypeName(locktype),
+ rc==SQLITE_OK ? "ok" : "failed");
return rc;
}
/*
-** Close all file descriptors accumuated in the unixInodeInfo->pUnused list.
+** Close all file descriptors accumuated in the unixOpenCnt->pUnused list.
** If all such file descriptors are closed without error, the list is
** cleared and SQLITE_OK returned.
**
** Otherwise, if an error occurs, then successfully closed file descriptor
-** entries are removed from the list, and SQLITE_IOERR_CLOSE returned.
+** entries are removed from the list, and SQLITE_IOERR_CLOSE returned.
** not deleted and SQLITE_IOERR_CLOSE returned.
-*/
+*/
static int closePendingFds(unixFile *pFile){
int rc = SQLITE_OK;
- unixInodeInfo *pInode = pFile->pInode;
+ struct unixOpenCnt *pOpen = pFile->pOpen;
UnixUnusedFd *pError = 0;
UnixUnusedFd *p;
UnixUnusedFd *pNext;
- for(p=pInode->pUnused; p; p=pNext){
+ for(p=pOpen->pUnused; p; p=pNext){
pNext = p->pNext;
if( close(p->fd) ){
pFile->lastErrno = errno;
@@ -23555,7 +23011,7 @@ static int closePendingFds(unixFile *pFile){
sqlite3_free(p);
}
}
- pInode->pUnused = pError;
+ pOpen->pUnused = pError;
return rc;
}
@@ -23564,50 +23020,46 @@ static int closePendingFds(unixFile *pFile){
** pUnused list.
*/
static void setPendingFd(unixFile *pFile){
- unixInodeInfo *pInode = pFile->pInode;
+ struct unixOpenCnt *pOpen = pFile->pOpen;
UnixUnusedFd *p = pFile->pUnused;
- p->pNext = pInode->pUnused;
- pInode->pUnused = p;
+ p->pNext = pOpen->pUnused;
+ pOpen->pUnused = p;
pFile->h = -1;
pFile->pUnused = 0;
}
/*
-** Lower the locking level on file descriptor pFile to eFileLock. eFileLock
+** Lower the locking level on file descriptor pFile 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.
-**
-** 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 _posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){
- unixFile *pFile = (unixFile*)id;
- unixInodeInfo *pInode;
- struct flock lock;
- int rc = SQLITE_OK;
- int h;
+static int unixUnlock(sqlite3_file *id, int locktype){
+ unixFile *pFile = (unixFile*)id; /* The open file */
+ struct unixLockInfo *pLock; /* Structure describing current lock state */
+ struct flock lock; /* Information passed into fcntl() */
+ int rc = SQLITE_OK; /* Return code from this interface */
+ int h; /* The underlying file descriptor */
int tErrno; /* Error code from system call errors */
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()));
+ OSTRACE7("UNLOCK %d %d was %d(%d,%d) pid=%d (unix)\n", pFile->h, locktype,
+ pFile->locktype, pFile->pLock->locktype, pFile->pLock->cnt, getpid());
- assert( eFileLock<=SHARED_LOCK );
- if( pFile->eFileLock<=eFileLock ){
+ assert( locktype<=SHARED_LOCK );
+ if( pFile->locktype<=locktype ){
return SQLITE_OK;
}
+ if( CHECK_THREADID(pFile) ){
+ return SQLITE_MISUSE_BKPT;
+ }
unixEnterMutex();
h = pFile->h;
- pInode = pFile->pInode;
- assert( pInode->nShared!=0 );
- if( pFile->eFileLock>SHARED_LOCK ){
- assert( pInode->eFileLock==pFile->eFileLock );
+ pLock = pFile->pLock;
+ assert( pLock->cnt!=0 );
+ if( pFile->locktype>SHARED_LOCK ){
+ assert( pLock->locktype==pFile->locktype );
SimulateIOErrorBenign(1);
SimulateIOError( h=(-1) )
SimulateIOErrorBenign(0);
@@ -23621,76 +23073,20 @@ static int _posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){
** the file has changed and hence might not know to flush their
** cache. The use of a stale cache can lead to database corruption.
*/
-#if 0
assert( pFile->inNormalWrite==0
|| pFile->dbUpdate==0
|| pFile->transCntrChng==1 );
-#endif
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( handleNFSUnlock ){
- 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( fcntl(h, F_SETLK, &lock)==(-1) ){
- tErrno = errno;
- rc = sqliteErrorFromPosixError(tErrno, 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( fcntl(h, F_SETLK, &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( fcntl(h, F_SETLK, &lock)==(-1) ){
- tErrno = errno;
- rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK);
- if( IS_LOCK_ERROR(rc) ){
- pFile->lastErrno = tErrno;
- }
- goto end_unlock;
- }
- }else{
- lock.l_type = F_RDLCK;
- lock.l_whence = SEEK_SET;
- lock.l_start = SHARED_FIRST;
- lock.l_len = SHARED_SIZE;
- if( fcntl(h, F_SETLK, &lock)==(-1) ){
- tErrno = errno;
- rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_RDLOCK);
- if( IS_LOCK_ERROR(rc) ){
- pFile->lastErrno = tErrno;
- }
- goto end_unlock;
+ if( locktype==SHARED_LOCK ){
+ if( rangeLock(pFile, F_RDLCK, &tErrno)==(-1) ){
+ rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_RDLOCK);
+ if( IS_LOCK_ERROR(rc) ){
+ pFile->lastErrno = tErrno;
}
+ goto end_unlock;
}
}
lock.l_type = F_UNLCK;
@@ -23698,7 +23094,7 @@ static int _posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){
lock.l_start = PENDING_BYTE;
lock.l_len = 2L; assert( PENDING_BYTE+1==RESERVED_BYTE );
if( fcntl(h, F_SETLK, &lock)!=(-1) ){
- pInode->eFileLock = SHARED_LOCK;
+ pLock->locktype = SHARED_LOCK;
}else{
tErrno = errno;
rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK);
@@ -23708,13 +23104,15 @@ static int _posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){
goto end_unlock;
}
}
- if( eFileLock==NO_LOCK ){
+ if( locktype==NO_LOCK ){
+ struct unixOpenCnt *pOpen;
+
/* 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 ){
+ pLock->cnt--;
+ if( pLock->cnt==0 ){
lock.l_type = F_UNLCK;
lock.l_whence = SEEK_SET;
lock.l_start = lock.l_len = 0L;
@@ -23722,15 +23120,15 @@ static int _posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){
SimulateIOError( h=(-1) )
SimulateIOErrorBenign(0);
if( fcntl(h, F_SETLK, &lock)!=(-1) ){
- pInode->eFileLock = NO_LOCK;
+ pLock->locktype = NO_LOCK;
}else{
tErrno = errno;
rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK);
if( IS_LOCK_ERROR(rc) ){
pFile->lastErrno = tErrno;
}
- pInode->eFileLock = NO_LOCK;
- pFile->eFileLock = NO_LOCK;
+ pLock->locktype = NO_LOCK;
+ pFile->locktype = NO_LOCK;
}
}
@@ -23738,35 +23136,25 @@ static int _posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){
** 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 ){
+ pOpen = pFile->pOpen;
+ pOpen->nLock--;
+ assert( pOpen->nLock>=0 );
+ if( pOpen->nLock==0 ){
int rc2 = closePendingFds(pFile);
if( rc==SQLITE_OK ){
rc = rc2;
}
}
}
-
+
end_unlock:
unixLeaveMutex();
- if( rc==SQLITE_OK ) pFile->eFileLock = eFileLock;
+ if( rc==SQLITE_OK ) pFile->locktype = locktype;
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.
-*/
-static int unixUnlock(sqlite3_file *id, int eFileLock){
- return _posixUnlock(id, eFileLock, 0);
-}
-
-/*
-** This function performs the parts of the "close file" operation
+** 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.
@@ -23803,7 +23191,7 @@ static int closeUnixFile(sqlite3_file *id){
pFile->pId = 0;
}
#endif
- OSTRACE(("CLOSE %-3d\n", pFile->h));
+ OSTRACE2("CLOSE %-3d\n", pFile->h);
OpenCounter(-1);
sqlite3_free(pFile->pUnused);
memset(pFile, 0, sizeof(unixFile));
@@ -23820,15 +23208,16 @@ static int unixClose(sqlite3_file *id){
unixFile *pFile = (unixFile *)id;
unixUnlock(id, NO_LOCK);
unixEnterMutex();
- if( pFile->pInode && pFile->pInode->nLock ){
+ if( pFile->pOpen && pFile->pOpen->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
+ ** descriptor to pOpen->pUnused list. It will be automatically closed
** when the last lock is cleared.
*/
setPendingFd(pFile);
}
- releaseInodeInfo(pFile->pInode);
+ releaseLockInfo(pFile->pLock);
+ releaseOpenCnt(pFile->pOpen);
rc = closeUnixFile(id);
unixLeaveMutex();
}
@@ -23923,11 +23312,11 @@ static int dotlockCheckReservedLock(sqlite3_file *id, int *pResOut) {
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 ){
+ if( pFile->locktype>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;
@@ -23936,13 +23325,13 @@ static int dotlockCheckReservedLock(sqlite3_file *id, int *pResOut) {
const char *zLockFile = (const char*)pFile->lockingContext;
reserved = access(zLockFile, 0)==0;
}
- OSTRACE(("TEST WR-LOCK %d %d %d (dotlock)\n", pFile->h, rc, reserved));
+ OSTRACE4("TEST WR-LOCK %d %d %d (dotlock)\n", pFile->h, rc, reserved);
*pResOut = reserved;
return rc;
}
/*
-** Lock the file with the lock specified by parameter eFileLock - one
+** Lock the file with the lock specified by parameter locktype - one
** of the following:
**
** (1) SHARED_LOCK
@@ -23968,7 +23357,7 @@ static int dotlockCheckReservedLock(sqlite3_file *id, int *pResOut) {
** With dotfile locking, we really only support state (4): EXCLUSIVE.
** But we track the other locking levels internally.
*/
-static int dotlockLock(sqlite3_file *id, int eFileLock) {
+static int dotlockLock(sqlite3_file *id, int locktype) {
unixFile *pFile = (unixFile*)id;
int fd;
char *zLockFile = (char *)pFile->lockingContext;
@@ -23978,15 +23367,15 @@ static int dotlockLock(sqlite3_file *id, int eFileLock) {
/* 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;
+ if( pFile->locktype > NO_LOCK ){
+ pFile->locktype = locktype;
#if !OS_VXWORKS
/* Always update the timestamp on the old file */
utimes(zLockFile, NULL);
#endif
return SQLITE_OK;
}
-
+
/* grab an exclusive lock */
fd = open(zLockFile,O_RDONLY|O_CREAT|O_EXCL,0600);
if( fd<0 ){
@@ -24001,19 +23390,19 @@ static int dotlockLock(sqlite3_file *id, int eFileLock) {
}
}
return rc;
- }
+ }
if( close(fd) ){
pFile->lastErrno = errno;
rc = SQLITE_IOERR_CLOSE;
}
-
+
/* got it, set the type and return ok */
- pFile->eFileLock = eFileLock;
+ pFile->locktype = locktype;
return rc;
}
/*
-** Lower the locking level on file descriptor pFile to eFileLock. eFileLock
+** Lower the locking level on file descriptor pFile to locktype. locktype
** must be either NO_LOCK or SHARED_LOCK.
**
** If the locking level of the file descriptor is already at or below
@@ -24021,30 +23410,30 @@ static int dotlockLock(sqlite3_file *id, int eFileLock) {
**
** When the locking level reaches NO_LOCK, delete the lock file.
*/
-static int dotlockUnlock(sqlite3_file *id, int eFileLock) {
+static int dotlockUnlock(sqlite3_file *id, int locktype) {
unixFile *pFile = (unixFile*)id;
char *zLockFile = (char *)pFile->lockingContext;
assert( pFile );
- OSTRACE(("UNLOCK %d %d was %d pid=%d (dotlock)\n", pFile->h, eFileLock,
- pFile->eFileLock, getpid()));
- assert( eFileLock<=SHARED_LOCK );
-
+ OSTRACE5("UNLOCK %d %d was %d pid=%d (dotlock)\n", pFile->h, locktype,
+ pFile->locktype, getpid());
+ assert( locktype<=SHARED_LOCK );
+
/* no-op if possible */
- if( pFile->eFileLock==eFileLock ){
+ if( pFile->locktype==locktype ){
return SQLITE_OK;
}
/* 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;
+ if( locktype==SHARED_LOCK ){
+ pFile->locktype = SHARED_LOCK;
return SQLITE_OK;
}
-
+
/* To fully unlock the database, delete the lock file */
- assert( eFileLock==NO_LOCK );
+ assert( locktype==NO_LOCK );
if( unlink(zLockFile) ){
int rc = 0;
int tErrno = errno;
@@ -24054,9 +23443,9 @@ static int dotlockUnlock(sqlite3_file *id, int eFileLock) {
if( IS_LOCK_ERROR(rc) ){
pFile->lastErrno = tErrno;
}
- return rc;
+ return rc;
}
- pFile->eFileLock = NO_LOCK;
+ pFile->locktype = NO_LOCK;
return SQLITE_OK;
}
@@ -24103,16 +23492,16 @@ 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 ){
+ if( pFile->locktype>SHARED_LOCK ){
reserved = 1;
}
-
+
/* Otherwise see if some other process holds it. */
if( !reserved ){
/* attempt to get the lock */
@@ -24123,7 +23512,7 @@ static int flockCheckReservedLock(sqlite3_file *id, int *pResOut){
if ( lrc ) {
int tErrno = errno;
/* unlock failed with an error */
- lrc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK);
+ lrc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK);
if( IS_LOCK_ERROR(lrc) ){
pFile->lastErrno = tErrno;
rc = lrc;
@@ -24133,14 +23522,14 @@ static int flockCheckReservedLock(sqlite3_file *id, int *pResOut){
int tErrno = errno;
reserved = 1;
/* someone else might have it reserved */
- lrc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
+ 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));
+ OSTRACE4("TEST WR-LOCK %d %d %d (flock)\n", pFile->h, rc, reserved);
#ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS
if( (rc & SQLITE_IOERR) == SQLITE_IOERR ){
@@ -24153,7 +23542,7 @@ static int flockCheckReservedLock(sqlite3_file *id, int *pResOut){
}
/*
-** Lock the file with the lock specified by parameter eFileLock - one
+** Lock the file with the lock specified by parameter locktype - one
** of the following:
**
** (1) SHARED_LOCK
@@ -24181,21 +23570,21 @@ static int flockCheckReservedLock(sqlite3_file *id, int *pResOut){
** This routine will only increase a lock. Use the sqlite3OsUnlock()
** routine to lower a locking level.
*/
-static int flockLock(sqlite3_file *id, int eFileLock) {
+static int flockLock(sqlite3_file *id, int locktype) {
int rc = SQLITE_OK;
unixFile *pFile = (unixFile*)id;
assert( pFile );
- /* if we already have a lock, it is exclusive.
+ /* 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;
+ if (pFile->locktype > NO_LOCK) {
+ pFile->locktype = locktype;
return SQLITE_OK;
}
-
+
/* grab an exclusive lock */
-
+
if (flock(pFile->h, LOCK_EX | LOCK_NB)) {
int tErrno = errno;
/* didn't get, must be busy */
@@ -24205,10 +23594,10 @@ static int flockLock(sqlite3_file *id, int eFileLock) {
}
} else {
/* got it, set the type and return ok */
- pFile->eFileLock = eFileLock;
+ pFile->locktype = locktype;
}
- OSTRACE(("LOCK %d %s %s (flock)\n", pFile->h, azFileLock(eFileLock),
- rc==SQLITE_OK ? "ok" : "failed"));
+ OSTRACE4("LOCK %d %s %s (flock)\n", pFile->h, locktypeName(locktype),
+ rc==SQLITE_OK ? "ok" : "failed");
#ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS
if( (rc & SQLITE_IOERR) == SQLITE_IOERR ){
rc = SQLITE_BUSY;
@@ -24219,31 +23608,31 @@ static int flockLock(sqlite3_file *id, int eFileLock) {
/*
-** Lower the locking level on file descriptor pFile to eFileLock. eFileLock
+** Lower the locking level on file descriptor pFile 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.
*/
-static int flockUnlock(sqlite3_file *id, int eFileLock) {
+static int flockUnlock(sqlite3_file *id, int locktype) {
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 );
-
+ OSTRACE5("UNLOCK %d %d was %d pid=%d (flock)\n", pFile->h, locktype,
+ pFile->locktype, getpid());
+ assert( locktype<=SHARED_LOCK );
+
/* no-op if possible */
- if( pFile->eFileLock==eFileLock ){
+ if( pFile->locktype==locktype ){
return SQLITE_OK;
}
-
+
/* shared can just be set because we always have an exclusive */
- if (eFileLock==SHARED_LOCK) {
- pFile->eFileLock = eFileLock;
+ if (locktype==SHARED_LOCK) {
+ pFile->locktype = locktype;
return SQLITE_OK;
}
-
+
/* no, really, unlock. */
int rc = flock(pFile->h, LOCK_UN);
if (rc) {
@@ -24257,10 +23646,10 @@ static int flockUnlock(sqlite3_file *id, int eFileLock) {
r = SQLITE_BUSY;
}
#endif /* SQLITE_IGNORE_FLOCK_LOCK_ERRORS */
-
+
return r;
} else {
- pFile->eFileLock = NO_LOCK;
+ pFile->locktype = NO_LOCK;
return SQLITE_OK;
}
}
@@ -24304,17 +23693,17 @@ static int semCheckReservedLock(sqlite3_file *id, int *pResOut) {
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 ){
+ if( pFile->locktype>SHARED_LOCK ){
reserved = 1;
}
-
+
/* Otherwise see if some other process holds it. */
if( !reserved ){
- sem_t *pSem = pFile->pInode->pSem;
+ sem_t *pSem = pFile->pOpen->pSem;
struct stat statBuf;
if( sem_trywait(pSem)==-1 ){
@@ -24324,21 +23713,21 @@ static int semCheckReservedLock(sqlite3_file *id, int *pResOut) {
pFile->lastErrno = tErrno;
} else {
/* someone else has the lock when we are in NO_LOCK */
- reserved = (pFile->eFileLock < SHARED_LOCK);
+ reserved = (pFile->locktype < 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));
+ OSTRACE4("TEST WR-LOCK %d %d %d (sem)\n", pFile->h, rc, reserved);
*pResOut = reserved;
return rc;
}
/*
-** Lock the file with the lock specified by parameter eFileLock - one
+** Lock the file with the lock specified by parameter locktype - one
** of the following:
**
** (1) SHARED_LOCK
@@ -24366,20 +23755,20 @@ static int semCheckReservedLock(sqlite3_file *id, int *pResOut) {
** This routine will only increase a lock. Use the sqlite3OsUnlock()
** routine to lower a locking level.
*/
-static int semLock(sqlite3_file *id, int eFileLock) {
+static int semLock(sqlite3_file *id, int locktype) {
unixFile *pFile = (unixFile*)id;
int fd;
- sem_t *pSem = pFile->pInode->pSem;
+ sem_t *pSem = pFile->pOpen->pSem;
int rc = SQLITE_OK;
- /* if we already have a lock, it is exclusive.
+ /* 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;
+ if (pFile->locktype > NO_LOCK) {
+ pFile->locktype = locktype;
rc = SQLITE_OK;
goto sem_end_lock;
}
-
+
/* lock semaphore now but bail out when already locked. */
if( sem_trywait(pSem)==-1 ){
rc = SQLITE_BUSY;
@@ -24387,40 +23776,40 @@ static int semLock(sqlite3_file *id, int eFileLock) {
}
/* got it, set the type and return ok */
- pFile->eFileLock = eFileLock;
+ pFile->locktype = locktype;
sem_end_lock:
return rc;
}
/*
-** Lower the locking level on file descriptor pFile to eFileLock. eFileLock
+** Lower the locking level on file descriptor pFile 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.
*/
-static int semUnlock(sqlite3_file *id, int eFileLock) {
+static int semUnlock(sqlite3_file *id, int locktype) {
unixFile *pFile = (unixFile*)id;
- sem_t *pSem = pFile->pInode->pSem;
+ sem_t *pSem = pFile->pOpen->pSem;
assert( pFile );
assert( pSem );
- OSTRACE(("UNLOCK %d %d was %d pid=%d (sem)\n", pFile->h, eFileLock,
- pFile->eFileLock, getpid()));
- assert( eFileLock<=SHARED_LOCK );
-
+ OSTRACE5("UNLOCK %d %d was %d pid=%d (sem)\n", pFile->h, locktype,
+ pFile->locktype, getpid());
+ assert( locktype<=SHARED_LOCK );
+
/* no-op if possible */
- if( pFile->eFileLock==eFileLock ){
+ if( pFile->locktype==locktype ){
return SQLITE_OK;
}
-
+
/* shared can just be set because we always have an exclusive */
- if (eFileLock==SHARED_LOCK) {
- pFile->eFileLock = eFileLock;
+ if (locktype==SHARED_LOCK) {
+ pFile->locktype = locktype;
return SQLITE_OK;
}
-
+
/* no, really unlock. */
if ( sem_post(pSem)==-1 ) {
int rc, tErrno = errno;
@@ -24428,9 +23817,9 @@ static int semUnlock(sqlite3_file *id, int eFileLock) {
if( IS_LOCK_ERROR(rc) ){
pFile->lastErrno = tErrno;
}
- return rc;
+ return rc;
}
- pFile->eFileLock = NO_LOCK;
+ pFile->locktype = NO_LOCK;
return SQLITE_OK;
}
@@ -24443,7 +23832,8 @@ static int semClose(sqlite3_file *id) {
semUnlock(id, NO_LOCK);
assert( pFile );
unixEnterMutex();
- releaseLockInfo(pFile->pInode);
+ releaseLockInfo(pFile->pLock);
+ releaseOpenCnt(pFile->pOpen);
unixLeaveMutex();
closeUnixFile(id);
}
@@ -24474,7 +23864,7 @@ static int semClose(sqlite3_file *id) {
*/
typedef struct afpLockingContext afpLockingContext;
struct afpLockingContext {
- int reserved;
+ unsigned long long sharedByte;
const char *dbPath; /* Name of the open file */
};
@@ -24493,7 +23883,7 @@ struct ByteRangeLockPB2
/*
** 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(
@@ -24505,22 +23895,22 @@ static int afpSetLock(
){
struct ByteRangeLockPB2 pb;
int err;
-
+
pb.unLockFlag = setLockFlag ? 0 : 1;
pb.startEndFlag = 0;
pb.offset = offset;
- pb.length = length;
+ pb.length = length;
pb.fd = pFile->h;
-
- OSTRACE(("AFPSETLOCK [%s] for %d%s in range %llx:%llx\n",
+
+ OSTRACE6("AFPSETLOCK [%s] for %d%s in range %llx:%llx\n",
(setLockFlag?"ON":"OFF"), pFile->h, (pb.fd==-1?"[testval-1]":""),
- offset, length));
+ 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)));
+ OSTRACE4("AFPSETLOCK failed to fsctl() '%s' %d %s\n",
+ path, tErrno, strerror(tErrno));
#ifdef SQLITE_IGNORE_AFP_LOCK_ERRORS
rc = SQLITE_BUSY;
#else
@@ -24546,27 +23936,22 @@ static int afpCheckReservedLock(sqlite3_file *id, int *pResOut){
int rc = SQLITE_OK;
int reserved = 0;
unixFile *pFile = (unixFile*)id;
-
+
SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
-
+
assert( pFile );
afpLockingContext *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 ){
+ if( pFile->locktype>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);
+ 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 */
@@ -24579,16 +23964,15 @@ static int afpCheckReservedLock(sqlite3_file *id, int *pResOut){
rc=lrc;
}
}
-
- unixLeaveMutex();
- OSTRACE(("TEST WR-LOCK %d %d %d (afp)\n", pFile->h, rc, reserved));
-
+
+ OSTRACE4("TEST WR-LOCK %d %d %d (afp)\n", pFile->h, rc, reserved);
+
*pResOut = reserved;
return rc;
}
/*
-** Lock the file with the lock specified by parameter eFileLock - one
+** Lock the file with the lock specified by parameter locktype - one
** of the following:
**
** (1) SHARED_LOCK
@@ -24611,72 +23995,49 @@ static int afpCheckReservedLock(sqlite3_file *id, int *pResOut){
** This routine will only increase a lock. Use the sqlite3OsUnlock()
** routine to lower a locking level.
*/
-static int afpLock(sqlite3_file *id, int eFileLock){
+static int afpLock(sqlite3_file *id, int locktype){
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()));
+ OSTRACE5("LOCK %d %s was %s pid=%d (afp)\n", pFile->h,
+ locktypeName(locktype), locktypeName(pFile->locktype), 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)));
+ if( pFile->locktype>=locktype ){
+ OSTRACE3("LOCK %d %s ok (already held) (afp)\n", pFile->h,
+ locktypeName(locktype));
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
+ assert( pFile->locktype!=NO_LOCK || locktype==SHARED_LOCK );
+ assert( locktype!=PENDING_LOCK );
+ assert( locktype!=RESERVED_LOCK || pFile->locktype==SHARED_LOCK );
+
+ /* This mutex is needed because pFile->pLock 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.
+ /* Make sure the current thread owns the pFile.
*/
- 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;
+ rc = transferOwnership(pFile);
+ if( rc!=SQLITE_OK ){
+ unixLeaveMutex();
+ return rc;
}
-
+
/* 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)
+ if( locktype==SHARED_LOCK
+ || (locktype==EXCLUSIVE_LOCK && pFile->locktype<PENDING_LOCK)
){
int failed;
failed = afpSetLock(context->dbPath, pFile, PENDING_BYTE, 1, 1);
@@ -24685,30 +24046,26 @@ static int afpLock(sqlite3_file *id, int eFileLock){
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;
- long lk, mask;
-
- assert( pInode->nShared==0 );
- assert( pInode->eFileLock==0 );
-
- mask = (sizeof(long)==8) ? LARGEST_INT64 : 0x7fffffff;
+ if( locktype==SHARED_LOCK ){
+ int lk, lrc1, lrc2;
+ int lrc1Errno = 0;
+
/* 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);
+ lk = random();
+ context->sharedByte = (lk & 0x7fffffff)%(SHARED_SIZE - 1);
+ lrc1 = afpSetLock(context->dbPath, pFile,
+ SHARED_FIRST+context->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;
@@ -24719,203 +24076,148 @@ static int afpLock(sqlite3_file *id, int eFileLock){
} else if( lrc1 != SQLITE_OK ) {
rc = lrc1;
} else {
- pFile->eFileLock = SHARED_LOCK;
- pInode->nLock++;
- pInode->nShared = 1;
+ pFile->locktype = SHARED_LOCK;
+ pFile->pOpen->nLock++;
}
- }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) {
+ assert( 0!=pFile->locktype );
+ if (locktype >= RESERVED_LOCK && pFile->locktype < 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) {
+ if (!failed && locktype == EXCLUSIVE_LOCK) {
/* Acquire an EXCLUSIVE lock */
-
- /* Remove the shared lock before trying the range. we'll need to
+
+ /* 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)) ){
+ context->sharedByte, 1, 0)) ){
int failed2 = SQLITE_OK;
/* now attemmpt to get the exclusive lock range */
- failed = afpSetLock(context->dbPath, pFile, SHARED_FIRST,
+ failed = afpSetLock(context->dbPath, pFile, SHARED_FIRST,
SHARED_SIZE, 1);
- if( failed && (failed2 = afpSetLock(context->dbPath, pFile,
- SHARED_FIRST + pInode->sharedByte, 1, 1)) ){
+ if( failed && (failed2 = afpSetLock(context->dbPath, pFile,
+ SHARED_FIRST + context->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 :
+ rc = ((failed & SQLITE_IOERR) == SQLITE_IOERR) ? failed2 :
SQLITE_IOERR_LOCK;
goto afp_end_lock;
- }
+ }
}else{
- rc = failed;
+ 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;
+ pFile->locktype = locktype;
+ }else if( locktype==EXCLUSIVE_LOCK ){
+ pFile->locktype = PENDING_LOCK;
}
-
+
afp_end_lock:
unixLeaveMutex();
- OSTRACE(("LOCK %d %s %s (afp)\n", pFile->h, azFileLock(eFileLock),
- rc==SQLITE_OK ? "ok" : "failed"));
+ OSTRACE4("LOCK %d %s %s (afp)\n", pFile->h, locktypeName(locktype),
+ rc==SQLITE_OK ? "ok" : "failed");
return rc;
}
/*
-** Lower the locking level on file descriptor pFile to eFileLock. eFileLock
+** Lower the locking level on file descriptor pFile 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.
*/
-static int afpUnlock(sqlite3_file *id, int eFileLock) {
+static int afpUnlock(sqlite3_file *id, int locktype) {
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
+ afpLockingContext *pCtx = (afpLockingContext *) pFile->lockingContext;
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()));
+ OSTRACE5("UNLOCK %d %d was %d pid=%d (afp)\n", pFile->h, locktype,
+ pFile->locktype, getpid());
- assert( eFileLock<=SHARED_LOCK );
- if( pFile->eFileLock<=eFileLock ){
+ assert( locktype<=SHARED_LOCK );
+ if( pFile->locktype<=locktype ){
return SQLITE_OK;
}
+ if( CHECK_THREADID(pFile) ){
+ return SQLITE_MISUSE_BKPT;
+ }
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);
-
-#ifndef NDEBUG
- /* 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) ){
+ if( pFile->locktype>SHARED_LOCK ){
+
+ if( pFile->locktype==EXCLUSIVE_LOCK ){
+ rc = afpSetLock(pCtx->dbPath, pFile, SHARED_FIRST, SHARED_SIZE, 0);
+ if( rc==SQLITE_OK && locktype==SHARED_LOCK ){
/* 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;
+ int sharedLockByte = SHARED_FIRST+pCtx->sharedByte;
+ rc = afpSetLock(pCtx->dbPath, pFile, sharedLockByte, 1, 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;
+ if( rc==SQLITE_OK && pFile->locktype>=PENDING_LOCK ){
+ rc = afpSetLock(pCtx->dbPath, pFile, PENDING_BYTE, 1, 0);
+ }
+ if( rc==SQLITE_OK && pFile->locktype>=RESERVED_LOCK ){
+ rc = afpSetLock(pCtx->dbPath, pFile, RESERVED_BYTE, 1, 0);
}
+ }else if( locktype==NO_LOCK ){
+ /* clear the shared lock */
+ int sharedLockByte = SHARED_FIRST+pCtx->sharedByte;
+ rc = afpSetLock(pCtx->dbPath, pFile, sharedLockByte, 1, 0);
}
- 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 ){
+ if( rc==SQLITE_OK ){
+ if( locktype==NO_LOCK ){
+ struct unixOpenCnt *pOpen = pFile->pOpen;
+ pOpen->nLock--;
+ assert( pOpen->nLock>=0 );
+ if( pOpen->nLock==0 ){
rc = closePendingFds(pFile);
}
}
}
-
unixLeaveMutex();
- if( rc==SQLITE_OK ) pFile->eFileLock = eFileLock;
+ if( rc==SQLITE_OK ){
+ pFile->locktype = locktype;
+ }
return rc;
}
/*
-** Close a file & cleanup AFP specific locking context
+** Close a file & cleanup AFP specific locking context
*/
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( pFile->pOpen && pFile->pOpen->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
+ ** descriptor to pOpen->aPending. It will be automatically closed when
** the last lock is cleared.
*/
setPendingFd(pFile);
}
- releaseLockInfo(pFile->pInode);
+ releaseOpenCnt(pFile->pOpen);
sqlite3_free(pFile->lockingContext);
- rc = closeUnixFile(id);
+ closeUnixFile(id);
unixLeaveMutex();
}
- return rc;
+ return SQLITE_OK;
}
#endif /* defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE */
@@ -24928,34 +24230,11 @@ static int afpClose(sqlite3_file *id) {
********************* End of the AFP lock implementation **********************
******************************************************************************/
-/******************************************************************************
-*************************** 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 *****************************
**
-** The next division contains implementations for all methods of the
+** 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
@@ -24963,7 +24242,7 @@ static int nfsUnlock(sqlite3_file *id, int eFileLock){
*/
/*
-** Seek to the offset passed as the second argument, then read cnt
+** 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
@@ -24977,9 +24256,7 @@ static int nfsUnlock(sqlite3_file *id, int eFileLock){
*/
static int seekAndRead(unixFile *id, sqlite3_int64 offset, void *pBuf, int cnt){
int got;
-#if (!defined(USE_PREAD) && !defined(USE_PREAD64))
i64 newOffset;
-#endif
TIMER_START;
#if defined(USE_PREAD)
got = pread(id->h, pBuf, cnt, offset);
@@ -24994,7 +24271,7 @@ static int seekAndRead(unixFile *id, sqlite3_int64 offset, void *pBuf, int cnt){
if( newOffset == -1 ){
((unixFile*)id)->lastErrno = errno;
}else{
- ((unixFile*)id)->lastErrno = 0;
+ ((unixFile*)id)->lastErrno = 0;
}
return -1;
}
@@ -25004,7 +24281,7 @@ static int seekAndRead(unixFile *id, sqlite3_int64 offset, void *pBuf, int cnt){
if( got<0 ){
((unixFile*)id)->lastErrno = errno;
}
- OSTRACE(("READ %-3d %5d %7lld %llu\n", id->h, got, offset, TIMER_ELAPSED));
+ OSTRACE5("READ %-3d %5d %7lld %llu\n", id->h, got, offset, TIMER_ELAPSED);
return got;
}
@@ -25014,8 +24291,8 @@ static int seekAndRead(unixFile *id, sqlite3_int64 offset, void *pBuf, int cnt){
** wrong.
*/
static int unixRead(
- sqlite3_file *id,
- void *pBuf,
+ sqlite3_file *id,
+ void *pBuf,
int amt,
sqlite3_int64 offset
){
@@ -25025,12 +24302,10 @@ static int unixRead(
/* 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
+ || offset+amt<=PENDING_BYTE
);
-#endif
got = seekAndRead(pFile, offset, pBuf, amt);
if( got==amt ){
@@ -25055,9 +24330,7 @@ static int unixRead(
*/
static int seekAndWrite(unixFile *id, i64 offset, const void *pBuf, int cnt){
int got;
-#if (!defined(USE_PREAD) && !defined(USE_PREAD64))
i64 newOffset;
-#endif
TIMER_START;
#if defined(USE_PREAD)
got = pwrite(id->h, pBuf, cnt, offset);
@@ -25069,7 +24342,7 @@ static int seekAndWrite(unixFile *id, i64 offset, const void *pBuf, int cnt){
if( newOffset == -1 ){
((unixFile*)id)->lastErrno = errno;
}else{
- ((unixFile*)id)->lastErrno = 0;
+ ((unixFile*)id)->lastErrno = 0;
}
return -1;
}
@@ -25080,7 +24353,7 @@ static int seekAndWrite(unixFile *id, i64 offset, const void *pBuf, int cnt){
((unixFile*)id)->lastErrno = errno;
}
- OSTRACE(("WRITE %-3d %5d %7lld %llu\n", id->h, got, offset, TIMER_ELAPSED));
+ OSTRACE5("WRITE %-3d %5d %7lld %llu\n", id->h, got, offset, TIMER_ELAPSED);
return got;
}
@@ -25090,10 +24363,10 @@ static int seekAndWrite(unixFile *id, i64 offset, const void *pBuf, int cnt){
** or some other error code on failure.
*/
static int unixWrite(
- sqlite3_file *id,
- const void *pBuf,
+ sqlite3_file *id,
+ const void *pBuf,
int amt,
- sqlite3_int64 offset
+ sqlite3_int64 offset
){
unixFile *pFile = (unixFile*)id;
int wrote = 0;
@@ -25102,12 +24375,10 @@ static int unixWrite(
/* 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
+ || offset+amt<=PENDING_BYTE
);
-#endif
#ifndef NDEBUG
/* If we are doing a normal write to a database file (as opposed to
@@ -25194,8 +24465,8 @@ SQLITE_API int sqlite3_fullsync_count = 0;
**
** 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,
+** 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
@@ -25209,7 +24480,7 @@ static int full_fsync(int fd, int fullSync, int dataOnly){
int rc;
/* The following "ifdef/elif/else/" block has the same structure as
- ** the one below. It is replicated here solely to avoid cluttering
+ ** the one below. It is replicated here solely to avoid cluttering
** up the real code with the UNUSED_PARAMETER() macros.
*/
#ifdef SQLITE_NO_SYNC
@@ -25223,7 +24494,7 @@ static int full_fsync(int fd, int fullSync, int dataOnly){
UNUSED_PARAMETER(dataOnly);
#endif
- /* Record the number of times that we do a normal fsync() and
+ /* 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.
*/
@@ -25244,21 +24515,16 @@ static int full_fsync(int fd, int fullSync, int dataOnly){
rc = 1;
}
/* If the FULLFSYNC failed, fall back to attempting an fsync().
- ** It shouldn't be possible for fullfsync to fail on the local
+ ** 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
+ ** 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
+#else
rc = fdatasync(fd);
#if OS_VXWORKS
if( rc==-1 && errno==ENOTSUP ){
@@ -25306,7 +24572,7 @@ static int unixSync(sqlite3_file *id, int flags){
SimulateDiskfullError( return SQLITE_FULL );
assert( pFile );
- OSTRACE(("SYNC %-3d\n", pFile->h));
+ OSTRACE2("SYNC %-3d\n", pFile->h);
rc = full_fsync(pFile->h, isFullsync, isDataOnly);
SimulateIOError( rc=1 );
if( rc ){
@@ -25315,8 +24581,8 @@ static int unixSync(sqlite3_file *id, int flags){
}
if( pFile->dirfd>=0 ){
int err;
- OSTRACE(("DIRSYNC %-3d (have_fullfsync=%d fullsync=%d)\n", pFile->dirfd,
- HAVE_FULLFSYNC, isFullsync));
+ OSTRACE4("DIRSYNC %-3d (have_fullfsync=%d fullsync=%d)\n", pFile->dirfd,
+ HAVE_FULLFSYNC, isFullsync);
#ifndef SQLITE_DISABLE_DIRSYNC
/* The directory sync is only attempted if full_fsync is
** turned off or unavailable. If a full_fsync occurred above,
@@ -25388,7 +24654,7 @@ static int unixFileSize(sqlite3_file *id, i64 *pSize){
}
*pSize = buf.st_size;
- /* When opening a zero-size database, the findInodeInfo() procedure
+ /* When opening a zero-size database, the findLockInfo() 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
@@ -25415,21 +24681,13 @@ static int proxyFileControl(sqlite3_file*,int,void*);
static int unixFileControl(sqlite3_file *id, int op, void *pArg){
switch( op ){
case SQLITE_FCNTL_LOCKSTATE: {
- *(int*)pArg = ((unixFile*)id)->eFileLock;
+ *(int*)pArg = ((unixFile*)id)->locktype;
return SQLITE_OK;
}
case SQLITE_LAST_ERRNO: {
*(int*)pArg = ((unixFile*)id)->lastErrno;
return SQLITE_OK;
}
- case SQLITE_FCNTL_SIZE_HINT: {
-#if 0 /* No performance advantage seen on Linux */
- sqlite3_int64 szFile = *(sqlite3_int64*)pArg;
- unixFile *pFile = (unixFile*)id;
- ftruncate(pFile->h, szFile);
-#endif
- return SQLITE_OK;
- }
#ifndef NDEBUG
/* The pager calls this method to signal that it has done
** a rollback and that the database is therefore unchanged and
@@ -25474,822 +24732,6 @@ static int unixDeviceCharacteristics(sqlite3_file *NotUsed){
return 0;
}
-#ifndef SQLITE_OMIT_WAL
-
-
-/*
-** 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
-**
-** 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.
-**
-** To avoid deadlocks, mutex and mutexBuf are always released in the
-** reverse order that they are acquired. mutexBuf is always acquired
-** first and released last. This invariant is check by asserting
-** sqlite3_mutex_notheld() on mutex whenever mutexBuf is acquired or
-** released.
-*/
-struct unixShmNode {
- unixInodeInfo *pInode; /* unixInodeInfo that owns this SHM node */
- sqlite3_mutex *mutex; /* Mutex to access this object */
- sqlite3_mutex *mutexBuf; /* Mutex to access zBuf[] */
- char *zFilename; /* Name of the mmapped file */
- int h; /* Open file descriptor */
- int szMap; /* Size of the mapping into memory */
- char *pMMapBuf; /* Where currently mmapped(). NULL if unmapped */
- 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.
-**
-** 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 lockState; /* Current lock state */
- u8 hasMutex; /* True if holding the unixShmNode mutex */
- u8 hasMutexBuf; /* True if holding pFile->mutexBuf */
- u8 sharedMask; /* Mask of shared locks held */
- u8 exclMask; /* Mask of exclusive locks held */
-#ifdef SQLITE_DEBUG
- u8 id; /* Id of this connection within its unixShmNode */
-#endif
-};
-
-/*
-** Size increment by which shared memory grows
-*/
-#define SQLITE_UNIX_SHM_INCR 4096
-
-/*
-** Constants used for locking
-*/
-#define UNIX_SHM_BASE 32 /* Byte offset of the first lock byte */
-#define UNIX_SHM_DMS 0x01 /* Mask for Dead-Man-Switch lock */
-#define UNIX_SHM_A 0x10 /* Mask for region locks... */
-#define UNIX_SHM_B 0x20
-#define UNIX_SHM_C 0x40
-#define UNIX_SHM_D 0x80
-
-#ifdef SQLITE_DEBUG
-/*
-** Return a pointer to a nul-terminated string in static memory that
-** describes a locking mask. The string is of the form "MSABCD" with
-** each character representing a lock. "M" for MUTEX, "S" for DMS,
-** and "A" through "D" for the region locks. If a lock is held, the
-** letter is shown. If the lock is not held, the letter is converted
-** to ".".
-**
-** This routine is for debugging purposes only and does not appear
-** in a production build.
-*/
-static const char *unixShmLockString(u8 mask){
- static char zBuf[48];
- static int iBuf = 0;
- char *z;
-
- z = &zBuf[iBuf];
- iBuf += 8;
- if( iBuf>=sizeof(zBuf) ) iBuf = 0;
-
- z[0] = (mask & UNIX_SHM_DMS) ? 'S' : '.';
- z[1] = (mask & UNIX_SHM_A) ? 'A' : '.';
- z[2] = (mask & UNIX_SHM_B) ? 'B' : '.';
- z[3] = (mask & UNIX_SHM_C) ? 'C' : '.';
- z[4] = (mask & UNIX_SHM_D) ? 'D' : '.';
- z[5] = 0;
- return z;
-}
-#endif /* SQLITE_DEBUG */
-
-/*
-** Apply posix advisory locks for all bytes identified in lockMask.
-**
-** lockMask might contain multiple bits but all bits are guaranteed
-** to be contiguous.
-**
-** Locks block if the mask is exactly UNIX_SHM_C and are non-blocking
-** otherwise.
-*/
-static int unixShmSystemLock(
- unixShmNode *pShmNode, /* Apply locks to this open shared-memory segment */
- int lockType, /* F_UNLCK, F_RDLCK, or F_WRLCK */
- u8 lockMask /* Which bytes to lock or unlock */
-){
- struct flock f; /* The posix advisory locking structure */
- int lockOp; /* The opcode for fcntl() */
- int i; /* Offset into the locking byte range */
- int rc; /* Result code form fcntl() */
- u8 mask; /* Mask of bits in lockMask */
-
- /* Access to the unixShmNode object is serialized by the caller */
- assert( sqlite3_mutex_held(pShmNode->mutex) || pShmNode->nRef==0 );
-
- /* Initialize the locking parameters */
- memset(&f, 0, sizeof(f));
- f.l_type = lockType;
- f.l_whence = SEEK_SET;
- if( lockMask==UNIX_SHM_C && lockType!=F_UNLCK ){
- lockOp = F_SETLKW;
- OSTRACE(("SHM-LOCK requesting blocking lock\n"));
- }else{
- lockOp = F_SETLK;
- }
-
- /* Find the first bit in lockMask that is set */
- for(i=0, mask=0x01; mask!=0 && (lockMask&mask)==0; mask <<= 1, i++){}
- assert( mask!=0 );
- f.l_start = i+UNIX_SHM_BASE;
- f.l_len = 1;
-
- /* Extend the locking range for each additional bit that is set */
- mask <<= 1;
- while( mask!=0 && (lockMask & mask)!=0 ){
- f.l_len++;
- mask <<= 1;
- }
-
- /* Verify that all bits set in lockMask are contiguous */
- assert( mask==0 || (lockMask & ~(mask | (mask-1)))==0 );
-
- /* Acquire the system-level lock */
- rc = fcntl(pShmNode->h, lockOp, &f);
- rc = (rc!=(-1)) ? SQLITE_OK : SQLITE_BUSY;
-
- /* Update the global lock state and do debug tracing */
-#ifdef SQLITE_DEBUG
- OSTRACE(("SHM-LOCK "));
- if( rc==SQLITE_OK ){
- if( lockType==F_UNLCK ){
- OSTRACE(("unlock ok"));
- pShmNode->exclMask &= ~lockMask;
- pShmNode->sharedMask &= ~lockMask;
- }else if( lockType==F_RDLCK ){
- OSTRACE(("read-lock ok"));
- pShmNode->exclMask &= ~lockMask;
- pShmNode->sharedMask |= lockMask;
- }else{
- assert( lockType==F_WRLCK );
- OSTRACE(("write-lock ok"));
- pShmNode->exclMask |= lockMask;
- pShmNode->sharedMask &= ~lockMask;
- }
- }else{
- if( lockType==F_UNLCK ){
- OSTRACE(("unlock failed"));
- }else if( lockType==F_RDLCK ){
- OSTRACE(("read-lock failed"));
- }else{
- assert( lockType==F_WRLCK );
- OSTRACE(("write-lock failed"));
- }
- }
- OSTRACE((" - change requested %s - afterwards %s:%s\n",
- unixShmLockString(lockMask),
- unixShmLockString(pShmNode->sharedMask),
- unixShmLockString(pShmNode->exclMask)));
-#endif
-
- return rc;
-}
-
-/*
-** For connection p, unlock all of the locks identified by the unlockMask
-** parameter.
-*/
-static int unixShmUnlock(
- unixShmNode *pShmNode, /* The underlying shared-memory file */
- unixShm *p, /* The connection to be unlocked */
- u8 unlockMask /* Mask of locks to be unlocked */
-){
- int rc; /* Result code */
- unixShm *pX; /* For looping over all sibling connections */
- u8 allMask; /* Union of locks held by connections other than "p" */
-
- /* Access to the unixShmNode object is serialized by the caller */
- assert( sqlite3_mutex_held(pShmNode->mutex) );
-
- /* Compute locks held by sibling connections */
- allMask = 0;
- 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( (unlockMask & allMask)!=unlockMask ){
- rc = unixShmSystemLock(pShmNode, F_UNLCK, unlockMask & ~allMask);
- }else{
- rc = SQLITE_OK;
- }
-
- /* Undo the local locks */
- if( rc==SQLITE_OK ){
- p->exclMask &= ~unlockMask;
- p->sharedMask &= ~unlockMask;
- }
- return rc;
-}
-
-/*
-** Get reader locks for connection p on all locks in the readMask parameter.
-*/
-static int unixShmSharedLock(
- unixShmNode *pShmNode, /* The underlying shared-memory file */
- unixShm *p, /* The connection to get the shared locks */
- u8 readMask /* Mask of shared locks to be acquired */
-){
- int rc; /* Result code */
- unixShm *pX; /* For looping over all sibling connections */
- u8 allShared; /* Union of locks held by connections other than "p" */
-
- /* Access to the unixShmNode object is serialized by the caller */
- assert( sqlite3_mutex_held(pShmNode->mutex) );
-
- /* 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.
- */
- allShared = 0;
- for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
- if( pX==p ) continue;
- if( (pX->exclMask & readMask)!=0 ) return SQLITE_BUSY;
- allShared |= pX->sharedMask;
- }
-
- /* Get shared locks at the system level, if necessary */
- if( (~allShared) & readMask ){
- rc = unixShmSystemLock(pShmNode, F_RDLCK, readMask);
- }else{
- rc = SQLITE_OK;
- }
-
- /* Get the local shared locks */
- if( rc==SQLITE_OK ){
- p->sharedMask |= readMask;
- }
- return rc;
-}
-
-/*
-** For connection p, get an exclusive lock on all locks identified in
-** the writeMask parameter.
-*/
-static int unixShmExclusiveLock(
- unixShmNode *pShmNode, /* The underlying shared-memory file */
- unixShm *p, /* The connection to get the exclusive locks */
- u8 writeMask /* Mask of exclusive locks to be acquired */
-){
- int rc; /* Result code */
- unixShm *pX; /* For looping over all sibling connections */
-
- /* Access to the unixShmNode object is serialized by the caller */
- assert( sqlite3_mutex_held(pShmNode->mutex) );
-
- /* 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==p ) continue;
- if( (pX->exclMask & writeMask)!=0 ) return SQLITE_BUSY;
- if( (pX->sharedMask & writeMask)!=0 ) return SQLITE_BUSY;
- }
-
- /* Get the exclusive locks at the system level. Then if successful
- ** also mark the local connection as being locked.
- */
- rc = unixShmSystemLock(pShmNode, F_WRLCK, writeMask);
- if( rc==SQLITE_OK ){
- p->sharedMask &= ~writeMask;
- p->exclMask |= writeMask;
- }
- return rc;
-}
-
-/*
-** 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 ){
- assert( p->pInode==pFd->pInode );
- if( p->mutex ) sqlite3_mutex_free(p->mutex);
- if( p->mutexBuf ) sqlite3_mutex_free(p->mutexBuf);
- if( p->h>=0 ) close(p->h);
- p->pInode->pShmNode = 0;
- sqlite3_free(p);
- }
-}
-
-/*
-** Open a shared-memory area. This particular implementation uses
-** mmapped files.
-**
-** zName is a filename used to identify the shared-memory area. The
-** implementation does not (and perhaps should not) use this name
-** directly, but rather use it as a template for finding an appropriate
-** name for the shared-memory storage. In this implementation, the
-** string "-index" is appended to zName and used as the name of the
-** mmapped file.
-**
-** 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 unixShmOpen(
- sqlite3_file *fd /* The file descriptor of the associated database */
-){
- struct unixShm *p = 0; /* The connection to be opened */
- struct unixShmNode *pShmNode = 0; /* The underlying mmapped file */
- int rc; /* Result code */
- struct unixFile *pDbFd; /* Underlying database file */
- int nPath; /* Size of pDbFd->zPath in bytes */
-
- /* Allocate space for the new sqlite3_shm object.
- */
- p = sqlite3_malloc( sizeof(*p) );
- if( p==0 ) return SQLITE_NOMEM;
- memset(p, 0, sizeof(*p));
- pDbFd = (struct unixFile*)fd;
- 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();
- pShmNode = pDbFd->pInode->pShmNode;
- if( pShmNode==0 ){
- nPath = strlen(pDbFd->zPath);
- pShmNode = sqlite3_malloc( sizeof(*pShmNode) + nPath + 15 );
- if( pShmNode==0 ){
- rc = SQLITE_NOMEM;
- goto shm_open_err;
- }
- memset(pShmNode, 0, sizeof(*pShmNode));
- pShmNode->zFilename = (char*)&pShmNode[1];
- sqlite3_snprintf(nPath+15, pShmNode->zFilename,
- "%s-wal-index", pDbFd->zPath);
- 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;
- }
- pShmNode->mutexBuf = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
- if( pShmNode->mutexBuf==0 ){
- rc = SQLITE_NOMEM;
- goto shm_open_err;
- }
-
- pShmNode->h = open(pShmNode->zFilename, O_RDWR|O_CREAT, 0664);
- if( pShmNode->h<0 ){
- rc = SQLITE_CANTOPEN_BKPT;
- goto shm_open_err;
- }
-
- /* 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)==SQLITE_OK ){
- if( ftruncate(pShmNode->h, 0) ){
- rc = SQLITE_IOERR;
- }
- }
- if( rc==SQLITE_OK ){
- rc = unixShmSystemLock(pShmNode, F_RDLCK, UNIX_SHM_DMS);
- }
- if( rc ) goto shm_open_err;
- }
-
- /* Make the new connection a child of the unixShmNode */
- p->pShmNode = pShmNode;
- p->pNext = pShmNode->pFirst;
-#ifdef SQLITE_DEBUG
- p->id = pShmNode->nextShmId++;
-#endif
- pShmNode->pFirst = p;
- pShmNode->nRef++;
- pDbFd->pShm = p;
- unixLeaveMutex();
- 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;
-}
-
-/*
-** Close a connection to shared-memory. Delete the underlying
-** storage if deleteFlag is true.
-*/
-static int unixShmClose(
- 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 );
-
- /* Verify that the connection being closed holds no locks */
- assert( p->exclMask==0 );
- assert( p->sharedMask==0 );
-
- /* 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 ) unlink(pShmNode->zFilename);
- unixShmPurge(pDbFd);
- }
- unixLeaveMutex();
-
- return SQLITE_OK;
-}
-
-/*
-** Query and/or changes the size of the underlying storage for
-** a shared-memory segment. The reqSize parameter is the new size
-** of the underlying storage, or -1 to do just a query. The size
-** of the underlying storage (after resizing if resizing occurs) is
-** written into pNewSize.
-**
-** This routine does not (necessarily) change the size of the mapping
-** of the underlying storage into memory. Use xShmGet() to change
-** the mapping size.
-**
-** The reqSize parameter is the minimum size requested. The implementation
-** is free to expand the storage to some larger amount if it chooses.
-*/
-static int unixShmSize(
- sqlite3_file *fd, /* The open database file holding SHM */
- int reqSize, /* Requested size. -1 for query only */
- int *pNewSize /* Write new size here */
-){
- unixFile *pDbFd = (unixFile*)fd;
- unixShm *p = pDbFd->pShm;
- unixShmNode *pShmNode = p->pShmNode;
- int rc = SQLITE_OK;
- struct stat sStat;
-
- assert( pShmNode==pDbFd->pInode->pShmNode );
- assert( pShmNode->pInode==pDbFd->pInode );
-
- /* On a query, this loop runs once. When reqSize>=0, the loop potentially
- ** runs twice, except if the actual size is already greater than or equal
- ** to the requested size, reqSize is set to -1 on the first iteration and
- ** the loop only runs once.
- */
- while( 1 ){
- if( fstat(pShmNode->h, &sStat)==0 ){
- *pNewSize = (int)sStat.st_size;
- if( reqSize>=0 && reqSize<=(int)sStat.st_size ) break;
- }else{
- *pNewSize = 0;
- rc = SQLITE_IOERR;
- break;
- }
- if( reqSize<0 ) break;
- reqSize = (reqSize + SQLITE_UNIX_SHM_INCR - 1)/SQLITE_UNIX_SHM_INCR;
- reqSize *= SQLITE_UNIX_SHM_INCR;
- rc = ftruncate(pShmNode->h, reqSize);
- reqSize = -1;
- }
- return rc;
-}
-
-
-/*
-** Map the shared storage into memory. The minimum size of the
-** mapping should be reqMapSize if reqMapSize is positive. If
-** reqMapSize is zero or negative, the implementation can choose
-** whatever mapping size is convenient.
-**
-** *ppBuf is made to point to the memory which is a mapping of the
-** underlying storage. A mutex is acquired to prevent other threads
-** from running while *ppBuf is in use in order to prevent other threads
-** remapping *ppBuf out from under this thread. The unixShmRelease()
-** call will release the mutex. However, if the lock state is CHECKPOINT,
-** the mutex is not acquired because CHECKPOINT will never remap the
-** buffer. RECOVER might remap, though, so CHECKPOINT will acquire
-** the mutex if and when it promotes to RECOVER.
-**
-** RECOVER needs to be atomic. The same mutex that prevents *ppBuf from
-** being remapped also prevents more than one thread from being in
-** RECOVER at a time. But, RECOVER sometimes wants to remap itself.
-** To prevent RECOVER from losing its lock while remapping, the
-** mutex is not released by unixShmRelease() when in RECOVER.
-**
-** *pNewMapSize is set to the size of the mapping.
-**
-** *ppBuf and *pNewMapSize might be NULL and zero if no space has
-** yet been allocated to the underlying storage.
-*/
-static int unixShmGet(
- sqlite3_file *fd, /* Database file holding shared memory */
- int reqMapSize, /* Requested size of mapping. -1 means don't care */
- int *pNewMapSize, /* Write new size of mapping here */
- void volatile **ppBuf /* Write mapping buffer origin here */
-){
- unixFile *pDbFd = (unixFile*)fd;
- unixShm *p = pDbFd->pShm;
- unixShmNode *pShmNode = p->pShmNode;
- int rc = SQLITE_OK;
-
- assert( pShmNode==pDbFd->pInode->pShmNode );
- assert( pShmNode->pInode==pDbFd->pInode );
-
- if( p->lockState!=SQLITE_SHM_CHECKPOINT && p->hasMutexBuf==0 ){
- assert( sqlite3_mutex_notheld(pShmNode->mutex) );
- sqlite3_mutex_enter(pShmNode->mutexBuf);
- p->hasMutexBuf = 1;
- }
- sqlite3_mutex_enter(pShmNode->mutex);
- if( pShmNode->szMap==0 || reqMapSize>pShmNode->szMap ){
- int actualSize;
- if( unixShmSize(fd, -1, &actualSize)==SQLITE_OK
- && reqMapSize<actualSize
- ){
- reqMapSize = actualSize;
- }
- if( pShmNode->pMMapBuf ){
- munmap(pShmNode->pMMapBuf, pShmNode->szMap);
- }
- pShmNode->pMMapBuf = mmap(0, reqMapSize, PROT_READ|PROT_WRITE, MAP_SHARED,
- pShmNode->h, 0);
- pShmNode->szMap = pShmNode->pMMapBuf ? reqMapSize : 0;
- }
- *pNewMapSize = pShmNode->szMap;
- *ppBuf = pShmNode->pMMapBuf;
- sqlite3_mutex_leave(pShmNode->mutex);
- return rc;
-}
-
-/*
-** Release the lock held on the shared memory segment to that other
-** threads are free to resize it if necessary.
-**
-** If the lock is not currently held, this routine is a harmless no-op.
-**
-** If the shared-memory object is in lock state RECOVER, then we do not
-** really want to release the lock, so in that case too, this routine
-** is a no-op.
-*/
-static int unixShmRelease(sqlite3_file *fd){
- unixFile *pDbFd = (unixFile*)fd;
- unixShm *p = pDbFd->pShm;
-
- if( p->hasMutexBuf && p->lockState!=SQLITE_SHM_RECOVER ){
- assert( sqlite3_mutex_notheld(p->pShmNode->mutex) );
- sqlite3_mutex_leave(p->pShmNode->mutexBuf);
- p->hasMutexBuf = 0;
- }
- return SQLITE_OK;
-}
-
-/*
-** Symbolic names for LOCK states used for debugging.
-*/
-#ifdef SQLITE_DEBUG
-static const char *azLkName[] = {
- "UNLOCK",
- "READ",
- "READ_FULL",
- "WRITE",
- "PENDING",
- "CHECKPOINT",
- "RECOVER"
-};
-#endif
-
-
-/*
-** Change the lock state for a shared-memory segment.
-*/
-static int unixShmLock(
- sqlite3_file *fd, /* Database file holding the shared memory */
- int desiredLock, /* One of SQLITE_SHM_xxxxx locking states */
- int *pGotLock /* The lock you actually got */
-){
- unixFile *pDbFd = (unixFile*)fd;
- unixShm *p = pDbFd->pShm;
- unixShmNode *pShmNode = p->pShmNode;
- int rc = SQLITE_PROTOCOL;
-
- assert( pShmNode==pDbFd->pInode->pShmNode );
- assert( pShmNode->pInode==pDbFd->pInode );
-
- /* Note that SQLITE_SHM_READ_FULL and SQLITE_SHM_PENDING are never
- ** directly requested; they are side effects from requesting
- ** SQLITE_SHM_READ and SQLITE_SHM_CHECKPOINT, respectively.
- */
- assert( desiredLock==SQLITE_SHM_UNLOCK
- || desiredLock==SQLITE_SHM_READ
- || desiredLock==SQLITE_SHM_WRITE
- || desiredLock==SQLITE_SHM_CHECKPOINT
- || desiredLock==SQLITE_SHM_RECOVER );
-
- /* Return directly if this is just a lock state query, or if
- ** the connection is already in the desired locking state.
- */
- if( desiredLock==p->lockState
- || (desiredLock==SQLITE_SHM_READ && p->lockState==SQLITE_SHM_READ_FULL)
- ){
- OSTRACE(("SHM-LOCK shmid-%d, pid-%d request %s and got %s\n",
- p->id, getpid(), azLkName[desiredLock], azLkName[p->lockState]));
- if( pGotLock ) *pGotLock = p->lockState;
- return SQLITE_OK;
- }
-
- OSTRACE(("SHM-LOCK shmid-%d, pid-%d request %s->%s\n",
- p->id, getpid(), azLkName[p->lockState], azLkName[desiredLock]));
-
- if( desiredLock==SQLITE_SHM_RECOVER && !p->hasMutexBuf ){
- assert( sqlite3_mutex_notheld(pShmNode->mutex) );
- sqlite3_mutex_enter(pShmNode->mutexBuf);
- p->hasMutexBuf = 1;
- }
- sqlite3_mutex_enter(pShmNode->mutex);
- switch( desiredLock ){
- case SQLITE_SHM_UNLOCK: {
- assert( p->lockState!=SQLITE_SHM_RECOVER );
- unixShmUnlock(pShmNode, p, UNIX_SHM_A|UNIX_SHM_B|UNIX_SHM_C|UNIX_SHM_D);
- rc = SQLITE_OK;
- p->lockState = SQLITE_SHM_UNLOCK;
- break;
- }
- case SQLITE_SHM_READ: {
- if( p->lockState==SQLITE_SHM_UNLOCK ){
- int nAttempt;
- rc = SQLITE_BUSY;
- assert( p->lockState==SQLITE_SHM_UNLOCK );
- for(nAttempt=0; nAttempt<5 && rc==SQLITE_BUSY; nAttempt++){
- rc = unixShmSharedLock(pShmNode, p, UNIX_SHM_A|UNIX_SHM_B);
- if( rc==SQLITE_BUSY ){
- rc = unixShmSharedLock(pShmNode, p, UNIX_SHM_D);
- if( rc==SQLITE_OK ){
- p->lockState = SQLITE_SHM_READ_FULL;
- }
- }else{
- unixShmUnlock(pShmNode, p, UNIX_SHM_B);
- p->lockState = SQLITE_SHM_READ;
- }
- }
- }else{
- assert( p->lockState==SQLITE_SHM_WRITE
- || p->lockState==SQLITE_SHM_RECOVER );
- rc = unixShmSharedLock(pShmNode, p, UNIX_SHM_A);
- unixShmUnlock(pShmNode, p, UNIX_SHM_C|UNIX_SHM_D);
- p->lockState = SQLITE_SHM_READ;
- }
- break;
- }
- case SQLITE_SHM_WRITE: {
- assert( p->lockState==SQLITE_SHM_READ
- || p->lockState==SQLITE_SHM_READ_FULL );
- rc = unixShmExclusiveLock(pShmNode, p, UNIX_SHM_C|UNIX_SHM_D);
- if( rc==SQLITE_OK ){
- p->lockState = SQLITE_SHM_WRITE;
- }
- break;
- }
- case SQLITE_SHM_CHECKPOINT: {
- assert( p->lockState==SQLITE_SHM_UNLOCK
- || p->lockState==SQLITE_SHM_PENDING
- );
- if( p->lockState==SQLITE_SHM_UNLOCK ){
- rc = unixShmExclusiveLock(pShmNode, p, UNIX_SHM_B|UNIX_SHM_C);
- if( rc==SQLITE_OK ){
- p->lockState = SQLITE_SHM_PENDING;
- }
- }
- if( p->lockState==SQLITE_SHM_PENDING ){
- rc = unixShmExclusiveLock(pShmNode, p, UNIX_SHM_A);
- if( rc==SQLITE_OK ){
- p->lockState = SQLITE_SHM_CHECKPOINT;
- }
- }
- break;
- }
- default: {
- assert( desiredLock==SQLITE_SHM_RECOVER );
- assert( p->lockState==SQLITE_SHM_READ
- || p->lockState==SQLITE_SHM_READ_FULL
- );
- assert( sqlite3_mutex_held(pShmNode->mutexBuf) );
- rc = unixShmExclusiveLock(pShmNode, p, UNIX_SHM_C);
- if( rc==SQLITE_OK ){
- p->lockState = SQLITE_SHM_RECOVER;
- }
- break;
- }
- }
- sqlite3_mutex_leave(pShmNode->mutex);
- OSTRACE(("SHM-LOCK shmid-%d, pid-%d got %s\n",
- p->id, getpid(), azLkName[p->lockState]));
- if( pGotLock ) *pGotLock = p->lockState;
- return rc;
-}
-
-/*
-** 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 */
-){
-#ifdef __GNUC__
- __sync_synchronize();
-#else
- unixMutexEnter();
- unixMutexLeave();
-#endif
-}
-
-
-#else
-# define unixShmOpen 0
-# define unixShmSize 0
-# define unixShmGet 0
-# define unixShmRelease 0
-# define unixShmLock 0
-# define unixShmBarrier 0
-# define unixShmClose 0
-#endif /* #ifndef SQLITE_OMIT_WAL */
-
/*
** Here ends the implementation of all sqlite3_file methods.
**
@@ -26330,9 +24772,9 @@ static void unixShmBarrier(
** * An I/O method finder function called FINDER that returns a pointer
** to the METHOD object in the previous bullet.
*/
-#define IOMETHODS(FINDER, METHOD, VERSION, CLOSE, LOCK, UNLOCK, CKLOCK) \
+#define IOMETHODS(FINDER, METHOD, CLOSE, LOCK, UNLOCK, CKLOCK) \
static const sqlite3_io_methods METHOD = { \
- VERSION, /* iVersion */ \
+ 1, /* iVersion */ \
CLOSE, /* xClose */ \
unixRead, /* xRead */ \
unixWrite, /* xWrite */ \
@@ -26344,14 +24786,7 @@ static const sqlite3_io_methods METHOD = { \
CKLOCK, /* xCheckReservedLock */ \
unixFileControl, /* xFileControl */ \
unixSectorSize, /* xSectorSize */ \
- unixDeviceCharacteristics, /* xDeviceCapabilities */ \
- unixShmOpen, /* xShmOpen */ \
- unixShmSize, /* xShmSize */ \
- unixShmGet, /* xShmGet */ \
- unixShmRelease, /* xShmRelease */ \
- unixShmLock, /* xShmLock */ \
- unixShmBarrier, /* xShmBarrier */ \
- unixShmClose /* xShmClose */ \
+ unixDeviceCharacteristics /* xDeviceCapabilities */ \
}; \
static const sqlite3_io_methods *FINDER##Impl(const char *z, unixFile *p){ \
UNUSED_PARAMETER(z); UNUSED_PARAMETER(p); \
@@ -26368,7 +24803,6 @@ static const sqlite3_io_methods *(*const FINDER)(const char*,unixFile *p) \
IOMETHODS(
posixIoFinder, /* Finder function name */
posixIoMethods, /* sqlite3_io_methods object name */
- 2, /* ShmOpen is enabled */
unixClose, /* xClose method */
unixLock, /* xLock method */
unixUnlock, /* xUnlock method */
@@ -26377,7 +24811,6 @@ IOMETHODS(
IOMETHODS(
nolockIoFinder, /* Finder function name */
nolockIoMethods, /* sqlite3_io_methods object name */
- 1, /* ShmOpen is disabled */
nolockClose, /* xClose method */
nolockLock, /* xLock method */
nolockUnlock, /* xUnlock method */
@@ -26386,7 +24819,6 @@ IOMETHODS(
IOMETHODS(
dotlockIoFinder, /* Finder function name */
dotlockIoMethods, /* sqlite3_io_methods object name */
- 1, /* ShmOpen is disabled */
dotlockClose, /* xClose method */
dotlockLock, /* xLock method */
dotlockUnlock, /* xUnlock method */
@@ -26397,7 +24829,6 @@ IOMETHODS(
IOMETHODS(
flockIoFinder, /* Finder function name */
flockIoMethods, /* sqlite3_io_methods object name */
- 1, /* ShmOpen is disabled */
flockClose, /* xClose method */
flockLock, /* xLock method */
flockUnlock, /* xUnlock method */
@@ -26409,7 +24840,6 @@ IOMETHODS(
IOMETHODS(
semIoFinder, /* Finder function name */
semIoMethods, /* sqlite3_io_methods object name */
- 1, /* ShmOpen is disabled */
semClose, /* xClose method */
semLock, /* xLock method */
semUnlock, /* xUnlock method */
@@ -26421,7 +24851,6 @@ IOMETHODS(
IOMETHODS(
afpIoFinder, /* Finder function name */
afpIoMethods, /* sqlite3_io_methods object name */
- 1, /* ShmOpen is disabled */
afpClose, /* xClose method */
afpLock, /* xLock method */
afpUnlock, /* xUnlock method */
@@ -26430,6 +24859,23 @@ IOMETHODS(
#endif
/*
+** The "Whole File Locking" finder returns the same set of methods as
+** the posix locking finder. But it also sets the SQLITE_WHOLE_FILE_LOCKING
+** flag to force the posix advisory locks to cover the whole file instead
+** of just a small span of bytes near the 1GiB boundary. Whole File Locking
+** is useful on NFS-mounted files since it helps NFS to maintain cache
+** coherency. But it is a detriment to other filesystems since it runs
+** slower.
+*/
+static const sqlite3_io_methods *posixWflIoFinderImpl(const char*z, unixFile*p){
+ UNUSED_PARAMETER(z);
+ p->fileFlags = SQLITE_WHOLE_FILE_LOCKING;
+ return &posixIoMethods;
+}
+static const sqlite3_io_methods
+ *(*const posixWflIoFinder)(const char*,unixFile *p) = posixWflIoFinderImpl;
+
+/*
** 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
@@ -26446,7 +24892,6 @@ static int proxyCheckReservedLock(sqlite3_file*, int*);
IOMETHODS(
proxyIoFinder, /* Finder function name */
proxyIoMethods, /* sqlite3_io_methods object name */
- 1, /* ShmOpen is disabled */
proxyClose, /* xClose method */
proxyLock, /* xLock method */
proxyUnlock, /* xUnlock method */
@@ -26454,22 +24899,10 @@ IOMETHODS(
)
#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, /* ShmOpen 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
+/*
+** 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.
**
@@ -26486,7 +24919,11 @@ static const sqlite3_io_methods *autolockIoFinderImpl(
{ "hfs", &posixIoMethods },
{ "ufs", &posixIoMethods },
{ "afpfs", &afpIoMethods },
+#ifdef SQLITE_ENABLE_AFP_LOCKING_SMB
{ "smbfs", &afpIoMethods },
+#else
+ { "smbfs", &flockIoMethods },
+#endif
{ "webdav", &nolockIoMethods },
{ 0, 0 }
};
@@ -26511,31 +24948,28 @@ static const sqlite3_io_methods *autolockIoFinderImpl(
}
/* 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.
+ ** 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( fcntl(pNew->h, F_GETLK, &lockInfo)!=-1 ) {
- if( strcmp(fsInfo.f_fstypename, "nfs")==0 ){
- return &nfsIoMethods;
- } else {
- return &posixIoMethods;
- }
+ pNew->fileFlags = SQLITE_WHOLE_FILE_LOCKING;
+ return &posixIoMethods;
}else{
return &dotlockIoMethods;
}
}
-static const sqlite3_io_methods
+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
+/*
+** 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.
**
@@ -26566,7 +25000,7 @@ static const sqlite3_io_methods *autolockIoFinderImpl(
return &semIoMethods;
}
}
-static const sqlite3_io_methods
+static const sqlite3_io_methods
*(*const autolockIoFinder)(const char*,unixFile*) = autolockIoFinderImpl;
#endif /* OS_VXWORKS && SQLITE_ENABLE_LOCKING_STYLE */
@@ -26600,19 +25034,19 @@ static int fillInUnixFile(
unixFile *pNew = (unixFile *)pId;
int rc = SQLITE_OK;
- assert( pNew->pInode==NULL );
+ assert( pNew->pLock==NULL );
+ assert( pNew->pOpen==NULL );
- /* Parameter isDelete is only used on vxworks. Express this explicitly
+ /* Parameter isDelete is only used on vxworks. Express this explicitly
** here to prevent compiler warnings about unused parameters.
*/
UNUSED_PARAMETER(isDelete);
- OSTRACE(("OPEN %-3d %s\n", h, zFilename));
+ OSTRACE3("OPEN %-3d %s\n", h, zFilename);
pNew->h = h;
pNew->dirfd = dirfd;
+ SET_THREADID(pNew);
pNew->fileFlags = 0;
- assert( zFilename==0 || zFilename[0]=='/' ); /* Never a relative pathname */
- pNew->zPath = zFilename;
#if OS_VXWORKS
pNew->pId = vxworksFindFileId(zFilename);
@@ -26634,16 +25068,12 @@ static int fillInUnixFile(
#endif
}
- if( pLockingStyle == &posixIoMethods
-#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
- || pLockingStyle == &nfsIoMethods
-#endif
- ){
+ if( pLockingStyle == &posixIoMethods ){
unixEnterMutex();
- rc = findInodeInfo(pNew, &pNew->pInode);
+ rc = findLockInfo(pNew, &pNew->pLock, &pNew->pOpen);
if( rc!=SQLITE_OK ){
- /* If an error occured in findInodeInfo(), close the file descriptor
- ** immediately, before releasing the mutex. findInodeInfo() may fail
+ /* If an error occured in findLockInfo(), close the file descriptor
+ ** immediately, before releasing the mutex. findLockInfo() may fail
** in two scenarios:
**
** (a) A call to fstat() failed.
@@ -26652,7 +25082,7 @@ static int fillInUnixFile(
** 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
+ ** findLockInfo(). 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.
**
@@ -26680,23 +25110,17 @@ static int fillInUnixFile(
** 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);
- close(h);
- h = -1;
- }
- unixLeaveMutex();
+ rc = findLockInfo(pNew, NULL, &pNew->pOpen);
+ unixLeaveMutex();
}
}
#endif
else if( pLockingStyle == &dotlockIoMethods ){
/* Dotfile locking uses the file path so it needs to be included in
- ** the dotlockLockingContext
+ ** the dotlockLockingContext
*/
char *zLockFile;
int nFilename;
@@ -26716,29 +25140,27 @@ static int fillInUnixFile(
** included in the semLockingContext
*/
unixEnterMutex();
- rc = findInodeInfo(pNew, &pNew->pInode);
- if( (rc==SQLITE_OK) && (pNew->pInode->pSem==NULL) ){
- char *zSemName = pNew->pInode->aSemName;
+ rc = findLockInfo(pNew, &pNew->pLock, &pNew->pOpen);
+ if( (rc==SQLITE_OK) && (pNew->pOpen->pSem==NULL) ){
+ char *zSemName = pNew->pOpen->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 ){
+ pNew->pOpen->pSem = sem_open(zSemName, O_CREAT, 0666, 1);
+ if( pNew->pOpen->pSem == SEM_FAILED ){
rc = SQLITE_NOMEM;
- pNew->pInode->aSemName[0] = '\0';
+ pNew->pOpen->aSemName[0] = '\0';
}
}
unixLeaveMutex();
}
#endif
-
+
pNew->lastErrno = 0;
#if OS_VXWORKS
if( rc!=SQLITE_OK ){
- if( h>=0 ) close(h);
- h = -1;
unlink(zFilename);
isDelete = 0;
}
@@ -26778,7 +25200,7 @@ static int openDirectory(const char *zFilename, int *pFd){
#ifdef FD_CLOEXEC
fcntl(fd, F_SETFD, fcntl(fd, F_GETFD, 0) | FD_CLOEXEC);
#endif
- OSTRACE(("OPENDIR %-3d %s\n", fd, zDirname));
+ OSTRACE3("OPENDIR %-3d %s\n", fd, zDirname);
}
}
*pFd = fd;
@@ -26809,7 +25231,7 @@ static int getTempname(int nBuf, char *zBuf){
/* 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.
+ ** function failing.
*/
SimulateIOError( return SQLITE_IOERR );
@@ -26817,7 +25239,7 @@ static int getTempname(int nBuf, char *zBuf){
if (NULL == azDirs[1]) {
azDirs[1] = getenv("TMPDIR");
}
-
+
for(i=0; i<sizeof(azDirs)/sizeof(azDirs[0]); i++){
if( azDirs[i]==0 ) continue;
if( stat(azDirs[i], &buf) ) continue;
@@ -26827,7 +25249,7 @@ static int getTempname(int nBuf, char *zBuf){
break;
}
- /* Check that the output buffer is large enough for the temporary file
+ /* 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) + 17) >= (size_t)nBuf ){
@@ -26856,7 +25278,7 @@ static int proxyTransformUnixFile(unixFile*, const char*);
#endif
/*
-** Search for an unused file descriptor that was opened on the database
+** 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.
@@ -26865,7 +25287,7 @@ static int proxyTransformUnixFile(unixFile*, const char*);
** 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
+** 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
@@ -26876,8 +25298,8 @@ static UnixUnusedFd *findReusableFd(const char *zPath, int flags){
/* 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
+ ** 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 */
@@ -26891,17 +25313,17 @@ static UnixUnusedFd *findReusableFd(const char *zPath, int flags){
** Even if a subsequent open() call does succeed, the consequences of
** not searching for a resusable file descriptor are not dire. */
if( 0==stat(zPath, &sStat) ){
- unixInodeInfo *pInode;
+ struct unixOpenCnt *pOpen;
unixEnterMutex();
- pInode = inodeList;
- while( pInode && (pInode->fileId.dev!=sStat.st_dev
- || pInode->fileId.ino!=sStat.st_ino) ){
- pInode = pInode->pNext;
+ pOpen = openList;
+ while( pOpen && (pOpen->fileId.dev!=sStat.st_dev
+ || pOpen->fileId.ino!=sStat.st_ino) ){
+ pOpen = pOpen->pNext;
}
- if( pInode ){
+ if( pOpen ){
UnixUnusedFd **pp;
- for(pp=&pInode->pUnused; *pp && (*pp)->flags!=flags; pp=&((*pp)->pNext));
+ for(pp=&pOpen->pUnused; *pp && (*pp)->flags!=flags; pp=&((*pp)->pNext));
pUnused = *pp;
if( pUnused ){
*pp = pUnused->pNext;
@@ -26915,7 +25337,7 @@ static UnixUnusedFd *findReusableFd(const char *zPath, int flags){
/*
** Open the file zPath.
-**
+**
** Previously, the SQLite OS layer used three functions in place of this
** one:
**
@@ -26926,13 +25348,13 @@ static UnixUnusedFd *findReusableFd(const char *zPath, int flags){
** These calls correspond to the following combinations of flags:
**
** ReadWrite() -> (READWRITE | CREATE)
-** ReadOnly() -> (READONLY)
+** 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
+** file handle closed. To achieve the same effect using this new
+** interface, add the DELETEONCLOSE flag to those specified above for
** OpenExclusive().
*/
static int unixOpen(
@@ -26955,15 +25377,12 @@ static int unixOpen(
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 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 isOpenDirectory = (isCreate &&
+ int isOpenDirectory = (isCreate &&
(eType==SQLITE_OPEN_MASTER_JOURNAL || eType==SQLITE_OPEN_MAIN_JOURNAL)
);
@@ -26973,9 +25392,9 @@ static int unixOpen(
char zTmpname[MAX_PATHNAME+1];
const char *zName = zPath;
- /* Check the following statements are true:
+ /* Check the following statements are true:
**
- ** (a) Exactly one of the READWRITE and READONLY flags must be set, and
+ ** (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.
@@ -26992,9 +25411,9 @@ static int unixOpen(
assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MASTER_JOURNAL );
/* 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
+ 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
);
@@ -27024,7 +25443,7 @@ static int unixOpen(
/* 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
+ ** 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;
@@ -27035,7 +25454,7 @@ static int unixOpen(
if( fd<0 ){
mode_t openMode = (isDelete?0600:SQLITE_DEFAULT_FILE_PERMISSIONS);
fd = open(zName, openFlags, openMode);
- OSTRACE(("OPENX %-3d %s 0%o\n", fd, zName, openFlags));
+ OSTRACE4("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);
@@ -27091,29 +25510,12 @@ static int unixOpen(
noLock = eType!=SQLITE_OPEN_MAIN_DB;
-
-#if defined(__APPLE__) || SQLITE_ENABLE_LOCKING_STYLE
- struct statfs fsInfo;
- if( fstatfs(fd, &fsInfo) == -1 ){
- ((unixFile*)pFile)->lastErrno = errno;
- if( dirfd>=0 ) close(dirfd); /* silently leak if fail, in error */
- close(fd); /* silently leak if fail, in error */
- return SQLITE_IOERR_ACCESS;
- }
- if (0 == strncmp("msdos", fsInfo.f_fstypename, 5)) {
- ((unixFile*)pFile)->fsFlags |= SQLITE_FSFLAGS_IS_MSDOS;
- }
-#endif
-
-#if SQLITE_ENABLE_LOCKING_STYLE
#if SQLITE_PREFER_PROXY_LOCKING
- isAutoProxy = 1;
-#endif
- if( isAutoProxy && (zPath!=NULL) && (!noLock) && pVfs->xOpen ){
+ if( 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
+ /* 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;
@@ -27141,20 +25543,12 @@ static int unixOpen(
rc = fillInUnixFile(pVfs, fd, dirfd, pFile, zPath, noLock, isDelete);
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
-
+
rc = fillInUnixFile(pVfs, fd, dirfd, pFile, zPath, noLock, isDelete);
open_finished:
if( rc!=SQLITE_OK ){
@@ -27240,9 +25634,9 @@ static int unixAccess(
/*
** 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.
+** zPath.
**
-** zOut points to a buffer of at least sqlite3_vfs.mxPathname bytes
+** 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.
*/
@@ -27307,7 +25701,7 @@ static void unixDlError(sqlite3_vfs *NotUsed, int nBuf, char *zBufOut){
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
@@ -27317,7 +25711,7 @@ static void (*unixDlSym(sqlite3_vfs *NotUsed, void *p, const char*zSym))(void){
** 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.
+ ** 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
@@ -27421,33 +25815,32 @@ SQLITE_API int sqlite3_current_time = 0; /* Fake system time in seconds since 1
#endif
/*
-** 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 0. Return 1 if the time and date cannot be found.
+** 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 unixCurrentTimeInt64(sqlite3_vfs *NotUsed, sqlite3_int64 *piNow){
- static const sqlite3_int64 unixEpoch = 24405875*(sqlite3_int64)8640000;
-#if defined(NO_GETTOD)
+static int unixCurrentTime(sqlite3_vfs *NotUsed, double *prNow){
+#if defined(SQLITE_OMIT_FLOATING_POINT)
+ time_t t;
+ time(&t);
+ *prNow = (((sqlite3_int64)t)/8640 + 24405875)/10;
+#elif defined(NO_GETTOD)
time_t t;
time(&t);
- *piNow = ((sqlite3_int64)i)*1000 + unixEpoch;
+ *prNow = t/86400.0 + 2440587.5;
#elif OS_VXWORKS
struct timespec sNow;
clock_gettime(CLOCK_REALTIME, &sNow);
- *piNow = unixEpoch + 1000*(sqlite3_int64)sNow.tv_sec + sNow.tv_nsec/1000000;
+ *prNow = 2440587.5 + sNow.tv_sec/86400.0 + sNow.tv_nsec/86400000000000.0;
#else
struct timeval sNow;
gettimeofday(&sNow, 0);
- *piNow = unixEpoch + 1000*(sqlite3_int64)sNow.tv_sec + sNow.tv_usec/1000;
+ *prNow = 2440587.5 + sNow.tv_sec/86400.0 + sNow.tv_usec/86400000000.0;
#endif
#ifdef SQLITE_TEST
if( sqlite3_current_time ){
- *piNow = 1000*(sqlite3_int64)sqlite3_current_time + unixEpoch;
+ *prNow = sqlite3_current_time/86400.0 + 2440587.5;
}
#endif
UNUSED_PARAMETER(NotUsed);
@@ -27455,18 +25848,6 @@ static int unixCurrentTimeInt64(sqlite3_vfs *NotUsed, sqlite3_int64 *piNow){
}
/*
-** 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;
- unixCurrentTimeInt64(0, &i);
- *prNow = i/86400000.0;
- return 0;
-}
-
-/*
** 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
@@ -27480,7 +25861,6 @@ static int unixGetLastError(sqlite3_vfs *NotUsed, int NotUsed2, char *NotUsed3){
return 0;
}
-
/*
************************ End of sqlite3_vfs methods ***************************
******************************************************************************/
@@ -27509,7 +25889,7 @@ static int unixGetLastError(sqlite3_vfs *NotUsed, int NotUsed2, char *NotUsed3){
** address in the shared range is taken for a SHARED lock, the entire
** shared range is taken for an EXCLUSIVE lock):
**
-** PENDING_BYTE 0x40000000
+** PENDING_BYTE 0x40000000
** RESERVED_BYTE 0x40000001
** SHARED_RANGE 0x40000002 -> 0x40000200
**
@@ -27527,7 +25907,7 @@ static int unixGetLastError(sqlite3_vfs *NotUsed, int NotUsed2, char *NotUsed3){
** 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.
+** and onto a proxy file on the local file system.
**
**
** Using proxy locks
@@ -27552,19 +25932,19 @@ static int unixGetLastError(sqlite3_vfs *NotUsed, int NotUsed2, char *NotUsed3){
** actual proxy file name is generated from the name and path of the
** database file. For example:
**
-** For database path "/Users/me/foo.db"
+** 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).
+** connection or process).
**
**
** How proxy locking works
** -----------------------
**
-** Proxy file locking relies primarily on two new supporting files:
+** 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
@@ -27590,12 +25970,17 @@ static int unixGetLastError(sqlite3_vfs *NotUsed, int NotUsed2, char *NotUsed3){
** 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).
**
+** There is a third file - the host ID file - used as a persistent record
+** of a unique identifier for the host, a 128-byte unique host id file
+** in the path defined by the HOSTIDPATH macro (default value is
+** /Library/Caches/.com.apple.sqliteConchHostId).
+**
** Requesting the lock proxy does not immediately take the conch, it is
-** only taken when the first request to lock database file is made.
+** 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 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.
@@ -27609,12 +25994,16 @@ static int unixGetLastError(sqlite3_vfs *NotUsed, int NotUsed2, char *NotUsed3){
** 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
**
+** HOSTIDPATH
+**
+** Overrides the default host ID file path location
+**
** LOCKPROXYDIR
**
** Overrides the default directory used for lock proxy files that
@@ -27624,8 +26013,8 @@ static int unixGetLastError(sqlite3_vfs *NotUsed, int NotUsed2, char *NotUsed3){
**
** 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
@@ -27635,12 +26024,17 @@ static int unixGetLastError(sqlite3_vfs *NotUsed, int NotUsed2, char *NotUsed3){
*/
/*
-** Proxy locking is only available on MacOSX
+** Proxy locking is only available on MacOSX
*/
#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
+#ifdef SQLITE_TEST
+/* simulate multiple hosts by creating unique hostid file paths */
+SQLITE_API int sqlite3_hostid_num = 0;
+#endif
+
/*
-** The proxyLockingContext has the path and file structures for the remote
+** The proxyLockingContext has the path and file structures for the remote
** and local proxy files in it
*/
typedef struct proxyLockingContext proxyLockingContext;
@@ -27650,16 +26044,134 @@ struct proxyLockingContext {
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 */
+ int conchHeld; /* True if the conch is currently held */
void *oldLockingContext; /* Original lockingcontext to restore on close */
sqlite3_io_methods const *pOldMethod; /* Original I/O methods for close */
};
-/*
-** 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.
+/* HOSTIDLEN and CONCHLEN both include space for the string
+** terminating nul
+*/
+#define HOSTIDLEN 128
+#define CONCHLEN (MAXPATHLEN+HOSTIDLEN+1)
+#ifndef HOSTIDPATH
+# define HOSTIDPATH "/Library/Caches/.com.apple.sqliteConchHostId"
+#endif
+
+/* basically a copy of unixRandomness with different
+** test behavior built in */
+static int proxyGenerateHostID(char *pHostID){
+ int pid, fd, len;
+ unsigned char *key = (unsigned char *)pHostID;
+
+ memset(key, 0, HOSTIDLEN);
+ len = 0;
+ fd = open("/dev/urandom", O_RDONLY);
+ if( fd>=0 ){
+ len = read(fd, key, HOSTIDLEN);
+ close(fd); /* silently leak the fd if it fails */
+ }
+ if( len < HOSTIDLEN ){
+ time_t t;
+ time(&t);
+ memcpy(key, &t, sizeof(t));
+ pid = getpid();
+ memcpy(&key[sizeof(t)], &pid, sizeof(pid));
+ }
+
+#ifdef MAKE_PRETTY_HOSTID
+ {
+ int i;
+ /* filter the bytes into printable ascii characters and NUL terminate */
+ key[(HOSTIDLEN-1)] = 0x00;
+ for( i=0; i<(HOSTIDLEN-1); i++ ){
+ unsigned char pa = key[i]&0x7F;
+ if( pa<0x20 ){
+ key[i] = (key[i]&0x80 == 0x80) ? pa+0x40 : pa+0x20;
+ }else if( pa==0x7F ){
+ key[i] = (key[i]&0x80 == 0x80) ? pa=0x20 : pa+0x7E;
+ }
+ }
+ }
+#endif
+ return SQLITE_OK;
+}
+
+/* writes the host id path to path, path should be an pre-allocated buffer
+** with enough space for a path
+*/
+static void proxyGetHostIDPath(char *path, size_t len){
+ strlcpy(path, HOSTIDPATH, len);
+#ifdef SQLITE_TEST
+ if( sqlite3_hostid_num>0 ){
+ char suffix[2] = "1";
+ suffix[0] = suffix[0] + sqlite3_hostid_num;
+ strlcat(path, suffix, len);
+ }
+#endif
+ OSTRACE3("GETHOSTIDPATH %s pid=%d\n", path, getpid());
+}
+
+/* get the host ID from a sqlite hostid file stored in the
+** user-specific tmp directory, create the ID if it's not there already
*/
+static int proxyGetHostID(char *pHostID, int *pError){
+ int fd;
+ char path[MAXPATHLEN];
+ size_t len;
+ int rc=SQLITE_OK;
+
+ proxyGetHostIDPath(path, MAXPATHLEN);
+ /* try to create the host ID file, if it already exists read the contents */
+ fd = open(path, O_CREAT|O_WRONLY|O_EXCL, 0644);
+ if( fd<0 ){
+ int err=errno;
+
+ if( err!=EEXIST ){
+#ifdef SQLITE_PROXY_DEBUG /* set the sqlite error message instead */
+ fprintf(stderr, "sqlite error creating host ID file %s: %s\n",
+ path, strerror(err));
+#endif
+ return SQLITE_PERM;
+ }
+ /* couldn't create the file, read it instead */
+ fd = open(path, O_RDONLY|O_EXCL);
+ if( fd<0 ){
+#ifdef SQLITE_PROXY_DEBUG /* set the sqlite error message instead */
+ int err = errno;
+ fprintf(stderr, "sqlite error opening host ID file %s: %s\n",
+ path, strerror(err));
+#endif
+ return SQLITE_PERM;
+ }
+ len = pread(fd, pHostID, HOSTIDLEN, 0);
+ if( len<0 ){
+ *pError = errno;
+ rc = SQLITE_IOERR_READ;
+ }else if( len<HOSTIDLEN ){
+ *pError = 0;
+ rc = SQLITE_IOERR_SHORT_READ;
+ }
+ close(fd); /* silently leak the fd if it fails */
+ OSTRACE3("GETHOSTID read %s pid=%d\n", pHostID, getpid());
+ return rc;
+ }else{
+ /* we're creating the host ID file (use a random string of bytes) */
+ proxyGenerateHostID(pHostID);
+ len = pwrite(fd, pHostID, HOSTIDLEN, 0);
+ if( len<0 ){
+ *pError = errno;
+ rc = SQLITE_IOERR_WRITE;
+ }else if( len<HOSTIDLEN ){
+ *pError = 0;
+ rc = SQLITE_IOERR_WRITE;
+ }
+ close(fd); /* silently leak the fd if it fails */
+ OSTRACE3("GETHOSTID wrote %s pid=%d\n", pHostID, getpid());
+ return rc;
+ }
+}
+
static int proxyGetLockPath(const char *dbPath, char *lPath, size_t maxLen){
int len;
int dbLen;
@@ -27670,12 +26182,21 @@ static int proxyGetLockPath(const char *dbPath, char *lPath, size_t 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;
+ confstr(_CS_DARWIN_USER_TEMP_DIR, lPath, maxLen);
+ len = strlcat(lPath, "sqliteplocks", maxLen);
+ if( mkdir(lPath, SQLITE_DEFAULT_PROXYDIR_PERMISSIONS) ){
+ /* if mkdir fails, handle as lock file creation failure */
+# ifdef SQLITE_DEBUG
+ int err = errno;
+ if( err!=EEXIST ){
+ fprintf(stderr, "proxyGetLockPath: mkdir(%s,0%o) error %d %s\n", lPath,
+ SQLITE_DEFAULT_PROXYDIR_PERMISSIONS, err, strerror(err));
+ }
+# endif
+ }else{
+ OSTRACE3("GETLOCKPATH mkdir %s pid=%d\n", lPath, getpid());
}
- len = strlcat(lPath, "sqliteplocks", maxLen);
+
}
# else
len = strlcpy(lPath, "/tmp/", maxLen);
@@ -27685,7 +26206,7 @@ static int proxyGetLockPath(const char *dbPath, char *lPath, size_t maxLen){
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)<maxLen; i++){
@@ -27694,72 +26215,39 @@ static int proxyGetLockPath(const char *dbPath, char *lPath, size_t maxLen){
}
lPath[i+len]='\0';
strlcat(lPath, ":auto:", maxLen);
- OSTRACE(("GETLOCKPATH proxy lock path=%s pid=%d\n", lPath, getpid()));
return SQLITE_OK;
}
/*
- ** 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( mkdir(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;
-}
-
-/*
** 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;
- int dirfd = -1;
+static int proxyCreateUnixFile(const char *path, unixFile **ppFile) {
unixFile *pNew;
+ int flags = SQLITE_OPEN_MAIN_DB|SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE;
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
+ pNew = (unixFile *)sqlite3_malloc(sizeof(unixFile));
+ if( !pNew ){
+ return SQLITE_NOMEM;
+ }
+ memset(pNew, 0, sizeof(unixFile));
+
+ /* Call unixOpen() to open the proxy file. The flags passed to unixOpen()
+ ** suggest that the file being opened is a "main database". This is
+ ** necessary as other file types do not necessarily support locking. It
+ ** is better to use unixOpen() instead of opening the file directly with
+ ** open(), as unixOpen() sets up the various mechanisms required to
+ ** make sure a call to close() does not cause the system to discard
+ ** POSIX locks prematurely.
+ **
+ ** It is important that the xOpen member of the VFS object passed to
+ ** unixOpen() is NULL. This tells unixOpen() may try to open a proxy-file
+ ** for the proxy-file (creating a potential infinite loop).
*/
pUnused = findReusableFd(path, openFlags);
if( pUnused ){
@@ -27791,13 +26279,13 @@ static int proxyCreateUnixFile(
switch (terrno) {
case EACCES:
return SQLITE_PERM;
- case EIO:
+ 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;
@@ -27806,308 +26294,195 @@ static int proxyCreateUnixFile(
memset(pNew, 0, sizeof(unixFile));
pNew->openFlags = openFlags;
dummyVfs.pAppData = (void*)&autolockIoFinder;
- pUnused->fd = fd;
- pUnused->flags = openFlags;
- pNew->pUnused = pUnused;
-
- rc = fillInUnixFile(&dummyVfs, fd, dirfd, (sqlite3_file*)pNew, path, 0, 0);
- if( rc==SQLITE_OK ){
- *ppFile = pNew;
- return SQLITE_OK;
- }
-end_create_proxy:
- close(fd); /* silently leak fd if error, we're already in error */
- 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
-
-#define PROXY_HOSTIDLEN 16 /* conch file host id length */
-
-/* get the host ID via gethostuuid(), pHostID must point to PROXY_HOSTIDLEN
-** bytes of writable memory.
-*/
-static int proxyGetHostID(unsigned char *pHostID, int *pError){
- struct timespec timeout = {1, 0}; /* 1 sec timeout */
-
- assert(PROXY_HOSTIDLEN == sizeof(uuid_t));
- memset(pHostID, 0, PROXY_HOSTIDLEN);
- if( gethostuuid(pHostID, &timeout) ){
- int err = errno;
- if( pError ){
- *pError = err;
- }
- return SQLITE_IOERR;
+ dummyVfs.xOpen = 0;
+ rc = unixOpen(&dummyVfs, path, (sqlite3_file *)pNew, flags, &flags);
+ if( rc==SQLITE_OK && (flags&SQLITE_OPEN_READONLY) ){
+ pNew->pMethod->xClose((sqlite3_file *)pNew);
+ rc = SQLITE_CANTOPEN;
}
-#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 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)
-
-/*
-** 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.
-*/
-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;
- /* 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) ){
- sprintf(errmsg, "path error (len %d)", (int)pathLen);
- goto end_breaklock;
- }
- /* read the conch content */
- readLen = pread(conchFile->h, buf, PROXY_MAXCONCHLEN, 0);
- if( readLen<PROXY_PATHINDEX ){
- sprintf(errmsg, "read error (len %d)", (int)readLen);
- goto end_breaklock;
- }
- /* write it out to the temporary break file */
- fd = open(tPath, (O_RDWR|O_CREAT|O_EXCL), SQLITE_DEFAULT_FILE_PERMISSIONS);
- if( fd<0 ){
- sprintf(errmsg, "create failed (%d)", errno);
- goto end_breaklock;
- }
- if( pwrite(fd, buf, readLen, 0) != readLen ){
- sprintf(errmsg, "write failed (%d)", errno);
- goto end_breaklock;
- }
- if( rename(tPath, cPath) ){
- sprintf(errmsg, "rename failed (%d)", errno);
- goto end_breaklock;
- }
- rc = 0;
- fprintf(stderr, "broke stale lock on %s\n", cPath);
- close(conchFile->h);
- conchFile->h = fd;
- conchFile->openFlags = O_RDWR | O_CREAT;
-
-end_breaklock:
- if( rc ){
- if( fd>=0 ){
- unlink(tPath);
- close(fd);
- }
- fprintf(stderr, "failed to break stale lock on %s, %s\n", cPath, errmsg);
+ if( rc!=SQLITE_OK ){
+ sqlite3_free(pNew);
+ pNew = 0;
}
- 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;
-
- 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( fstat(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;
- }
-
- 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 = pread(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 );
+ *ppFile = pNew;
return rc;
}
-/* 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
+/* 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 ){
+ 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 testValue[CONCHLEN];
+ char conchValue[CONCHLEN];
char lockPath[MAXPATHLEN];
- char *tempLockPath = NULL;
+ char *tLockPath = 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;
+ int readRc = SQLITE_OK;
+ int syncPerms = 0;
+
+ OSTRACE4("TAKECONCH %d for %s pid=%d\n", conchFile->h,
+ (pCtx->lockProxyPath ? pCtx->lockProxyPath : ":auto:"), getpid());
+
+ rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, SHARED_LOCK);
+ if( rc==SQLITE_OK ){
+ int pError = 0;
+ memset(testValue, 0, CONCHLEN); /* conch is fixed size */
+ rc = proxyGetHostID(testValue, &pError);
+ if( (rc&0xff)==SQLITE_IOERR ){
+ pFile->lastErrno = pError;
+ }
+ if( pCtx->lockProxyPath ){
+ strlcpy(&testValue[HOSTIDLEN], pCtx->lockProxyPath, MAXPATHLEN);
+ }
}
- 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.
+
+ readRc = unixRead((sqlite3_file *)conchFile, conchValue, CONCHLEN, 0);
+ if( readRc!=SQLITE_IOERR_SHORT_READ ){
+ if( readRc!=SQLITE_OK ){
+ if( (rc&0xff)==SQLITE_IOERR ){
+ pFile->lastErrno = conchFile->lastErrno;
+ }
+ rc = readRc;
+ goto end_takeconch;
+ }
+ /* 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( !memcmp(testValue, conchValue, HOSTIDLEN) ){
+ tLockPath = (char *)&conchValue[HOSTIDLEN];
+ goto end_takeconch;
+ }
+ }else{
+ /* we've got the conch if conchValue matches our path and host ID */
+ if( !memcmp(testValue, conchValue, CONCHLEN) ){
+ goto end_takeconch;
+ }
+ }
+ }else{
+ /* a short read means we're "creating" the conch (even though it could
+ ** have been user-intervention), if we acquire the exclusive lock,
+ ** we'll try to match the current on-disk permissions of the database
*/
- 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 */
-
- 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;
+ syncPerms = 1;
+ }
+
+ /* either conch was emtpy or didn't match */
+ if( !pCtx->lockProxyPath ){
+ proxyGetLockPath(pCtx->dbPath, lockPath, MAXPATHLEN);
+ tLockPath = lockPath;
+ strlcpy(&testValue[HOSTIDLEN], lockPath, MAXPATHLEN);
+ }
+
+ /* update conch with host and path (this will fail if other process
+ ** has a shared lock already) */
+ rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, EXCLUSIVE_LOCK);
+ if( rc==SQLITE_OK ){
+ rc = unixWrite((sqlite3_file *)conchFile, testValue, CONCHLEN, 0);
+ if( rc==SQLITE_OK && syncPerms ){
+ struct stat buf;
+ int err = fstat(pFile->h, &buf);
+ if( err==0 ){
+ /* try to match the database file permissions, ignore failure */
+#ifndef SQLITE_PROXY_DEBUG
+ fchmod(conchFile->h, buf.st_mode);
+#else
+ if( fchmod(conchFile->h, buf.st_mode)!=0 ){
+ int code = errno;
+ fprintf(stderr, "fchmod %o FAILED with %d %s\n",
+ buf.st_mode, code, strerror(code));
+ } else {
+ fprintf(stderr, "fchmod %o SUCCEDED\n",buf.st_mode);
}
- }else if( hostIdMatch
- && !strncmp(pCtx->lockProxyPath, &readBuf[PROXY_PATHINDEX],
- readLen-PROXY_PATHINDEX)
- ){
- /* conch host and lock path match */
- goto end_takeconch;
+ }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:
+ OSTRACE2("TRANSPROXY: CLOSE %d\n", pFile->h);
+ if( rc==SQLITE_OK && pFile->openFlags ){
+ if( pFile->h>=0 ){
+#ifdef STRICT_CLOSE_ERROR
+ if( close(pFile->h) ){
+ pFile->lastErrno = errno;
+ return SQLITE_IOERR_CLOSE;
+ }
+#else
+ close(pFile->h); /* silently leak fd if fail */
+#endif
+ }
+ pFile->h = -1;
+ int fd = open(pCtx->dbPath, pFile->openFlags,
+ SQLITE_DEFAULT_FILE_PERMISSIONS);
+ OSTRACE2("TRANSPROXY: OPEN %d\n", fd);
+ if( fd>=0 ){
+ pFile->h = fd;
+ }else{
+ rc=SQLITE_CANTOPEN; /* SQLITE_BUSY? proxyTakeConch called
+ during locking */
+ }
+ }
+ if( rc==SQLITE_OK && !pCtx->lockProxy ){
+ char *path = tLockPath ? tLockPath : pCtx->lockProxyPath;
+ /* ACS: Need to make a copy of path sometimes */
+ rc = proxyCreateUnixFile(path, &pCtx->lockProxy);
+ }
+ if( rc==SQLITE_OK ){
+ pCtx->conchHeld = 1;
+ if( tLockPath ){
+ pCtx->lockProxyPath = sqlite3DbStrDup(0, tLockPath);
+ if( pCtx->lockProxy->pMethod == &afpIoMethods ){
+ ((afpLockingContext *)pCtx->lockProxy->lockingContext)->dbPath =
+ pCtx->lockProxyPath;
+ }
+ }
+>>>>>>> BEGIN MERGE CONFLICT
+
/* 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 ){
+ if( conchFile->pLock && conchFile->pLock->cnt>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 {
+ } else {
rc = proxyConchLock(pFile, myHostID, EXCLUSIVE_LOCK);
}
}else{
@@ -28116,7 +26491,7 @@ static int proxyTakeConch(unixFile *pFile){
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 ){
@@ -28128,8 +26503,8 @@ static int proxyTakeConch(unixFile *pFile){
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 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;
@@ -28150,16 +26525,16 @@ static int proxyTakeConch(unixFile *pFile){
}
}else{
int code = errno;
- fprintf(stderr, "STAT FAILED[%d] with %d %s\n",
+ 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));
+ OSTRACE2("TRANSPROXY: CLOSE %d\n", pFile->h);
if( rc==SQLITE_OK && pFile->openFlags ){
if( pFile->h>=0 ){
#ifdef STRICT_CLOSE_ERROR
@@ -28174,7 +26549,7 @@ static int proxyTakeConch(unixFile *pFile){
pFile->h = -1;
int fd = open(pCtx->dbPath, pFile->openFlags,
SQLITE_DEFAULT_FILE_PERMISSIONS);
- OSTRACE(("TRANSPROXY: OPEN %d\n", fd));
+ OSTRACE2("TRANSPROXY: OPEN %d\n", fd);
if( fd>=0 ){
pFile->h = fd;
}else{
@@ -28187,7 +26562,7 @@ static int proxyTakeConch(unixFile *pFile){
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
+ ** so try again via auto-naming
*/
forceNewLockPath = 1;
tryOldLockPath = 0;
@@ -28207,7 +26582,7 @@ static int proxyTakeConch(unixFile *pFile){
}
if( rc==SQLITE_OK ){
pCtx->conchHeld = 1;
-
+
if( pCtx->lockProxy->pMethod == &afpIoMethods ){
afpLockingContext *afpCtx;
afpCtx = (afpLockingContext *)pCtx->lockProxy->lockingContext;
@@ -28216,11 +26591,16 @@ static int proxyTakeConch(unixFile *pFile){
} else {
conchFile->pMethod->xUnlock((sqlite3_file*)conchFile, NO_LOCK);
}
- OSTRACE(("TAKECONCH %d %s\n", conchFile->h,
- rc==SQLITE_OK?"ok":"failed"));
+ OSTRACE3("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. */
+ } while (1); /* in case we need to retry the :auto: lock file - we should never get here except via the 'continue' call. */
+============================
+ } else {
+ conchFile->pMethod->xUnlock((sqlite3_file*)conchFile, NO_LOCK);
+ }
+ OSTRACE3("TAKECONCH %d %s\n", conchFile->h, rc==SQLITE_OK?"ok":"failed");
+ return rc;
+<<<<<<< END MERGE CONFLICT
}
}
@@ -28228,21 +26608,19 @@ static int proxyTakeConch(unixFile *pFile){
** 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 */
+ int rc; /* Subroutine return code */
proxyLockingContext *pCtx; /* The locking context for the proxy lock */
unixFile *conchFile; /* Name of the conch file */
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);
- }
+ OSTRACE4("RELEASECONCH %d for %s pid=%d\n", conchFile->h,
+ (pCtx->lockProxyPath ? pCtx->lockProxyPath : ":auto:"),
+ getpid());
pCtx->conchHeld = 0;
- OSTRACE(("RELEASECONCH %d %s\n", conchFile->h,
- (rc==SQLITE_OK ? "ok" : "failed")));
+ rc = conchFile->pMethod->xUnlock((sqlite3_file*)conchFile, NO_LOCK);
+ OSTRACE3("RELEASECONCH %d %s\n", conchFile->h,
+ (rc==SQLITE_OK ? "ok" : "failed"));
return rc;
}
@@ -28263,13 +26641,13 @@ static int proxyCreateConchPathname(char *dbPath, char **pConchPath){
char *conchPath; /* buffer in which to construct conch name */
/* Allocate space for the conch filename and initialize the name to
- ** the name of the original database file. */
+ ** 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]=='/' ){
@@ -28292,16 +26670,16 @@ static int proxyCreateConchPathname(char *dbPath, char **pConchPath){
/* Takes a fully configured proxy locking-style unix file and switches
-** the local lock file path
+** 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( pFile->eFileLock!=NO_LOCK ){
+ if( pFile->locktype!=NO_LOCK ){
return SQLITE_BUSY;
- }
+ }
/* nothing to do if the path is NULL, :auto: or matches the existing path */
if( !path || path[0]=='\0' || !strcmp(path, ":auto:") ||
@@ -28319,7 +26697,7 @@ static int switchLockProxyPath(unixFile *pFile, const char *path) {
sqlite3_free(oldPath);
pCtx->lockProxyPath = sqlite3DbStrDup(0, path);
}
-
+
return rc;
}
@@ -28333,11 +26711,11 @@ static int switchLockProxyPath(unixFile *pFile, const char *path) {
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
+ /* 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
+ strcpy(dbPath, ((afpLockingContext *)pFile->lockingContext)->dbPath);
+ }else
#endif
if( pFile->pMethod == &dotlockIoMethods ){
/* dot lock style uses the locking context to store the dot lock
@@ -28347,15 +26725,15 @@ static int proxyGetDbPathForUnixFile(unixFile *pFile, char *dbPath){
}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);
+ strcpy(dbPath, (char *)pFile->lockingContext);
}
return SQLITE_OK;
}
/*
-** Takes an already filled in unix file and alters it so all file locking
+** 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
+** are preserved in the locking context so that they can be restored and
** the unix structure properly cleaned up at close time:
** ->lockingContext
** ->pMethod
@@ -28365,8 +26743,8 @@ static int proxyTransformUnixFile(unixFile *pFile, const char *path) {
char dbPath[MAXPATHLEN+1]; /* Name of the database file */
char *lockPath=NULL;
int rc = SQLITE_OK;
-
- if( pFile->eFileLock!=NO_LOCK ){
+
+ if( pFile->locktype!=NO_LOCK ){
return SQLITE_BUSY;
}
proxyGetDbPathForUnixFile(pFile, dbPath);
@@ -28375,9 +26753,9 @@ static int proxyTransformUnixFile(unixFile *pFile, const char *path) {
}else{
lockPath=(char *)path;
}
-
- OSTRACE(("TRANSPROXY %d for %s pid=%d\n", pFile->h,
- (lockPath ? lockPath : ":auto:"), getpid()));
+
+ OSTRACE4("TRANSPROXY %d for %s pid=%d\n", pFile->h,
+ (lockPath ? lockPath : ":auto:"), getpid());
pCtx = sqlite3_malloc( sizeof(*pCtx) );
if( pCtx==0 ){
@@ -28387,58 +26765,32 @@ static int proxyTransformUnixFile(unixFile *pFile, const char *path) {
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;
-
- if( stat(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;
- }
- }
- }
+ rc = proxyCreateUnixFile(pCtx->conchFilePath, &pCtx->conchFile);
+ }
if( rc==SQLITE_OK && lockPath ){
pCtx->lockProxyPath = sqlite3DbStrDup(0, lockPath);
}
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,
+ /* all memory is allocated, proxys are created and assigned,
** switch the locking context and pMethod then return.
*/
+ pCtx->dbPath = sqlite3DbStrDup(0, dbPath);
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);
+ if( pCtx->conchFile ){
+ rc = pCtx->conchFile->pMethod->xClose((sqlite3_file *)pCtx->conchFile);
+ if( rc ) return rc;
sqlite3_free(pCtx->conchFile);
}
- sqlite3_free(pCtx->lockProxyPath);
- sqlite3_free(pCtx->conchFilePath);
+ sqlite3_free(pCtx->conchFilePath);
sqlite3_free(pCtx);
}
- OSTRACE(("TRANSPROXY %d %s\n", pFile->h,
- (rc==SQLITE_OK ? "ok" : "failed")));
+ OSTRACE3("TRANSPROXY %d %s\n", pFile->h,
+ (rc==SQLITE_OK ? "ok" : "failed"));
return rc;
}
@@ -28479,9 +26831,9 @@ static int proxyFileControl(sqlite3_file *id, int op, void *pArg){
}else{
const char *proxyPath = (const char *)pArg;
if( isProxyStyle ){
- proxyLockingContext *pCtx =
+ proxyLockingContext *pCtx =
(proxyLockingContext*)pFile->lockingContext;
- if( !strcmp(pArg, ":auto:")
+ if( !strcmp(pArg, ":auto:")
|| (pCtx->lockProxyPath &&
!strncmp(pCtx->lockProxyPath, proxyPath, MAXPATHLEN))
){
@@ -28522,18 +26874,14 @@ static int proxyCheckReservedLock(sqlite3_file *id, int *pResOut) {
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;
- }
+ unixFile *proxy = pCtx->lockProxy;
+ return proxy->pMethod->xCheckReservedLock((sqlite3_file*)proxy, pResOut);
}
return rc;
}
/*
-** Lock the file with the lock specified by parameter eFileLock - one
+** Lock the file with the lock specified by parameter locktype - one
** of the following:
**
** (1) SHARED_LOCK
@@ -28556,42 +26904,34 @@ static int proxyCheckReservedLock(sqlite3_file *id, int *pResOut) {
** This routine will only increase a lock. Use the sqlite3OsUnlock()
** routine to lower a locking level.
*/
-static int proxyLock(sqlite3_file *id, int eFileLock) {
+static int proxyLock(sqlite3_file *id, int locktype) {
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 */
- }
+ unixFile *proxy = pCtx->lockProxy;
+ rc = proxy->pMethod->xLock((sqlite3_file*)proxy, locktype);
+ pFile->locktype = proxy->locktype;
}
return rc;
}
/*
-** Lower the locking level on file descriptor pFile to eFileLock. eFileLock
+** Lower the locking level on file descriptor pFile 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.
*/
-static int proxyUnlock(sqlite3_file *id, int eFileLock) {
+static int proxyUnlock(sqlite3_file *id, int locktype) {
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 */
- }
+ unixFile *proxy = pCtx->lockProxy;
+ rc = proxy->pMethod->xUnlock((sqlite3_file*)proxy, locktype);
+ pFile->locktype = proxy->locktype;
}
return rc;
}
@@ -28606,7 +26946,7 @@ static int proxyClose(sqlite3_file *id) {
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;
@@ -28643,7 +26983,7 @@ static int proxyClose(sqlite3_file *id) {
** 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 **********************
******************************************************************************/
@@ -28661,8 +27001,8 @@ static int proxyClose(sqlite3_file *id) {
** necessarily been initialized when this routine is called, and so they
** should not be used.
*/
-SQLITE_API int sqlite3_os_init(void){
- /*
+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
@@ -28678,12 +27018,12 @@ SQLITE_API int sqlite3_os_init(void){
**
** 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
+ ** 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) { \
- 2, /* iVersion */ \
+ 1, /* iVersion */ \
sizeof(unixFile), /* szOsFile */ \
MAX_PATHNAME, /* mxPathname */ \
0, /* pNext */ \
@@ -28700,9 +27040,7 @@ SQLITE_API int sqlite3_os_init(void){
unixRandomness, /* xRandomness */ \
unixSleep, /* xSleep */ \
unixCurrentTime, /* xCurrentTime */ \
- unixGetLastError, /* xGetLastError */ \
- 0, /* xRename */ \
- unixCurrentTimeInt64, /* xCurrentTimeInt64 */ \
+ unixGetLastError /* xGetLastError */ \
}
/*
@@ -28720,6 +27058,7 @@ SQLITE_API int sqlite3_os_init(void){
#endif
UNIXVFS("unix-none", nolockIoFinder ),
UNIXVFS("unix-dotfile", dotlockIoFinder ),
+ UNIXVFS("unix-wfl", posixWflIoFinder ),
#if OS_VXWORKS
UNIXVFS("unix-namedsem", semIoFinder ),
#endif
@@ -28731,7 +27070,6 @@ SQLITE_API int sqlite3_os_init(void){
#endif
#if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__)
UNIXVFS("unix-afp", afpIoFinder ),
- UNIXVFS("unix-nfs", nfsIoFinder ),
UNIXVFS("unix-proxy", proxyIoFinder ),
#endif
};
@@ -28741,7 +27079,7 @@ SQLITE_API int sqlite3_os_init(void){
for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){
sqlite3_vfs_register(&aVfs[i], i==0);
}
- return SQLITE_OK;
+ return SQLITE_OK;
}
/*
@@ -28751,10 +27089,10 @@ SQLITE_API int sqlite3_os_init(void){
** 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;
+SQLITE_API int sqlite3_os_end(void){
+ return SQLITE_OK;
}
-
+
#endif /* SQLITE_OS_UNIX */
/************** End of os_unix.c *********************************************/
@@ -28853,9 +27191,23 @@ SQLITE_API int sqlite3_os_end(void){
#ifdef SQLITE_DEBUG
SQLITE_PRIVATE int sqlite3OSTrace = 0;
-#define OSTRACE(X) if( sqlite3OSTrace ) sqlite3DebugPrintf X
+#define OSTRACE1(X) if( sqlite3OSTrace ) sqlite3DebugPrintf(X)
+#define OSTRACE2(X,Y) if( sqlite3OSTrace ) sqlite3DebugPrintf(X,Y)
+#define OSTRACE3(X,Y,Z) if( sqlite3OSTrace ) sqlite3DebugPrintf(X,Y,Z)
+#define OSTRACE4(X,Y,Z,A) if( sqlite3OSTrace ) sqlite3DebugPrintf(X,Y,Z,A)
+#define OSTRACE5(X,Y,Z,A,B) if( sqlite3OSTrace ) sqlite3DebugPrintf(X,Y,Z,A,B)
+#define OSTRACE6(X,Y,Z,A,B,C) \
+ if(sqlite3OSTrace) sqlite3DebugPrintf(X,Y,Z,A,B,C)
+#define OSTRACE7(X,Y,Z,A,B,C,D) \
+ if(sqlite3OSTrace) sqlite3DebugPrintf(X,Y,Z,A,B,C,D)
#else
-#define OSTRACE(X)
+#define OSTRACE1(X)
+#define OSTRACE2(X,Y)
+#define OSTRACE3(X,Y,Z)
+#define OSTRACE4(X,Y,Z,A)
+#define OSTRACE5(X,Y,Z,A,B)
+#define OSTRACE6(X,Y,Z,A,B,C)
+#define OSTRACE7(X,Y,Z,A,B,C,D)
#endif
/*
@@ -28864,8 +27216,8 @@ SQLITE_PRIVATE int sqlite3OSTrace = 0;
*/
#ifdef SQLITE_PERFORMANCE_TRACE
-/*
-** hwtime.h contains inline assembler code for implementing
+/*
+** hwtime.h contains inline assembler code for implementing
** high-performance timing routines.
*/
/************** Include hwtime.h in the middle of os_common.h ****************/
@@ -28923,7 +27275,7 @@ SQLITE_PRIVATE int sqlite3OSTrace = 0;
__asm__ __volatile__ ("rdtsc" : "=A" (val));
return val;
}
-
+
#elif (defined(__GNUC__) && defined(__ppc__))
__inline__ sqlite_uint64 sqlite3Hwtime(void){
@@ -29029,7 +27381,7 @@ SQLITE_API int sqlite3_open_file_count = 0;
** Some microsoft compilers lack this definition.
*/
#ifndef INVALID_FILE_ATTRIBUTES
-# define INVALID_FILE_ATTRIBUTES ((DWORD)-1)
+# define INVALID_FILE_ATTRIBUTES ((DWORD)-1)
#endif
/*
@@ -29041,10 +27393,6 @@ SQLITE_API int sqlite3_open_file_count = 0;
# define FormatMessageW(a,b,c,d,e,f,g) 0
#endif
-/* Forward references */
-typedef struct winShm winShm; /* A connection to shared-memory */
-typedef struct winShmNode winShmNode; /* A region of shared-memory */
-
/*
** WinCE lacks native support for file locking so we have to fake it
** with some code of our own.
@@ -29064,18 +27412,15 @@ typedef struct winceLock {
*/
typedef struct winFile winFile;
struct winFile {
- const sqlite3_io_methods *pMethod; /*** Must be first ***/
- sqlite3_vfs *pVfs; /* The VFS used to open this file */
+ const sqlite3_io_methods *pMethod;/* Must be first */
HANDLE h; /* Handle for accessing the file */
unsigned char locktype; /* Type of lock currently held on this file */
short sharedLockByte; /* Randomly chosen byte used as a shared lock */
DWORD lastErrno; /* The Windows errno from the last I/O error */
DWORD sectorSize; /* Sector size of the device file is on */
- winShm *pShm; /* Instance of shared memory on this file */
- const char *zPath; /* Full pathname of this file */
#if SQLITE_OS_WINCE
WCHAR *zDeleteOnClose; /* Name of file to delete when closing */
- HANDLE hMutex; /* Mutex used to control access to shared lock */
+ 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 */
@@ -29134,7 +27479,7 @@ static int sqlite3_os_type = 0;
#endif /* SQLITE_OS_WINCE */
/*
-** Convert a UTF-8 string to microsoft unicode (UTF-16?).
+** Convert a UTF-8 string to microsoft unicode (UTF-16?).
**
** Space to hold the returned string is obtained from malloc.
*/
@@ -29180,7 +27525,7 @@ static char *unicodeToUtf8(const WCHAR *zWideFilename){
/*
** 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 malloc.
*/
@@ -29246,7 +27591,7 @@ SQLITE_API char *sqlite3_win32_mbcs_to_utf8(const char *zFilename){
}
/*
-** Convert UTF-8 to multibyte character string. Space to hold the
+** Convert UTF-8 to multibyte character string. Space to hold the
** returned string is obtained from malloc().
*/
static char *utf8ToMbcs(const char *zFilename){
@@ -29344,17 +27689,17 @@ static BOOL winceCreateLock(const char *zFilename, winFile *pFile){
/* Acquire the mutex before continuing */
winceMutexAcquire(pFile->hMutex);
-
- /* Since the names of named mutexes, semaphores, file mappings etc are
+
+ /* 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.
*/
CharUpperW(zName);
pFile->hShared = CreateFileMappingW(INVALID_HANDLE_VALUE, NULL,
PAGE_READWRITE, 0, sizeof(winceLock),
- zName);
+ zName);
- /* Set a flag that indicates we're the first to create the memory so it
+ /* Set a flag that indicates we're the first to create the memory so it
** must be zero-initialized */
if (GetLastError() == ERROR_ALREADY_EXISTS){
bInit = FALSE;
@@ -29364,7 +27709,7 @@ static BOOL winceCreateLock(const char *zFilename, winFile *pFile){
/* If we succeeded in making the shared memory handle, map it. */
if (pFile->hShared){
- pFile->shared = (winceLock*)MapViewOfFile(pFile->hShared,
+ pFile->shared = (winceLock*)MapViewOfFile(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){
@@ -29381,7 +27726,7 @@ static BOOL winceCreateLock(const char *zFilename, winFile *pFile){
pFile->hMutex = NULL;
return FALSE;
}
-
+
/* Initialize the shared memory if we're supposed to */
if (bInit) {
ZeroMemory(pFile->shared, sizeof(winceLock));
@@ -29419,13 +27764,13 @@ static void winceDestroyLock(winFile *pFile){
CloseHandle(pFile->hShared);
/* Done with the mutex */
- winceMutexRelease(pFile->hMutex);
+ winceMutexRelease(pFile->hMutex);
CloseHandle(pFile->hMutex);
pFile->hMutex = NULL;
}
}
-/*
+/*
** An implementation of the LockFile() API of windows for wince
*/
static BOOL winceLockFile(
@@ -29600,8 +27945,7 @@ static int winClose(sqlite3_file *id){
winFile *pFile = (winFile*)id;
assert( id!=0 );
- assert( pFile->pShm==0 );
- OSTRACE(("CLOSE %d\n", pFile->h));
+ OSTRACE2("CLOSE %d\n", pFile->h);
do{
rc = CloseHandle(pFile->h);
}while( rc==0 && ++cnt < MX_CLOSE_ATTEMPT && (Sleep(100), 1) );
@@ -29612,7 +27956,7 @@ static int winClose(sqlite3_file *id){
int cnt = 0;
while(
DeleteFileW(pFile->zDeleteOnClose)==0
- && GetFileAttributesW(pFile->zDeleteOnClose)!=0xffffffff
+ && GetFileAttributesW(pFile->zDeleteOnClose)!=0xffffffff
&& cnt++ < WINCE_DELETION_ATTEMPTS
){
Sleep(100); /* Wait a little before trying again */
@@ -29620,7 +27964,6 @@ static int winClose(sqlite3_file *id){
free(pFile->zDeleteOnClose);
}
#endif
- OSTRACE(("CLOSE %d %s\n", pFile->h, rc ? "ok" : "failed"));
OpenCounter(-1);
return rc ? SQLITE_OK : SQLITE_IOERR;
}
@@ -29652,7 +27995,7 @@ static int winRead(
assert( id!=0 );
SimulateIOError(return SQLITE_IOERR_READ);
- OSTRACE(("READ %d lock=%d\n", pFile->h, pFile->locktype));
+ OSTRACE3("READ %d lock=%d\n", pFile->h, pFile->locktype);
rc = SetFilePointer(pFile->h, lowerBits, &upperBits, FILE_BEGIN);
if( rc==INVALID_SET_FILE_POINTER && (error=GetLastError())!=NO_ERROR ){
pFile->lastErrno = error;
@@ -29691,7 +28034,7 @@ static int winWrite(
assert( id!=0 );
SimulateIOError(return SQLITE_IOERR_WRITE);
SimulateDiskfullError(return SQLITE_FULL);
- OSTRACE(("WRITE %d lock=%d\n", pFile->h, pFile->locktype));
+ OSTRACE3("WRITE %d lock=%d\n", pFile->h, pFile->locktype);
rc = SetFilePointer(pFile->h, lowerBits, &upperBits, FILE_BEGIN);
if( rc==INVALID_SET_FILE_POINTER && (error=GetLastError())!=NO_ERROR ){
pFile->lastErrno = error;
@@ -29719,25 +28062,24 @@ static int winWrite(
static int winTruncate(sqlite3_file *id, sqlite3_int64 nByte){
LONG upperBits = (LONG)((nByte>>32) & 0x7fffffff);
LONG lowerBits = (LONG)(nByte & 0xffffffff);
- DWORD dwRet;
+ DWORD rc;
winFile *pFile = (winFile*)id;
DWORD error;
- int rc = SQLITE_OK;
assert( id!=0 );
- OSTRACE(("TRUNCATE %d %lld\n", pFile->h, nByte));
+ OSTRACE3("TRUNCATE %d %lld\n", pFile->h, nByte);
SimulateIOError(return SQLITE_IOERR_TRUNCATE);
- dwRet = SetFilePointer(pFile->h, lowerBits, &upperBits, FILE_BEGIN);
- if( dwRet==INVALID_SET_FILE_POINTER && (error=GetLastError())!=NO_ERROR ){
+ rc = SetFilePointer(pFile->h, lowerBits, &upperBits, FILE_BEGIN);
+ if( rc==INVALID_SET_FILE_POINTER && (error=GetLastError())!=NO_ERROR ){
pFile->lastErrno = error;
- rc = SQLITE_IOERR_TRUNCATE;
+ return SQLITE_IOERR_TRUNCATE;
+ }
/* SetEndOfFile will fail if nByte is negative */
- }else if( !SetEndOfFile(pFile->h) ){
+ if( !SetEndOfFile(pFile->h) ){
pFile->lastErrno = GetLastError();
- rc = SQLITE_IOERR_TRUNCATE;
+ return SQLITE_IOERR_TRUNCATE;
}
- OSTRACE(("TRUNCATE %d %lld %s\n", pFile->h, nByte, rc==SQLITE_OK ? "ok" : "failed"));
- return rc;
+ return SQLITE_OK;
}
#ifdef SQLITE_TEST
@@ -29757,7 +28099,7 @@ static int winSync(sqlite3_file *id, int flags){
winFile *pFile = (winFile*)id;
assert( id!=0 );
- OSTRACE(("SYNC %d lock=%d\n", pFile->h, pFile->locktype));
+ OSTRACE3("SYNC %d lock=%d\n", pFile->h, pFile->locktype);
#else
UNUSED_PARAMETER(id);
#endif
@@ -29827,7 +28169,7 @@ static int getReadLock(winFile *pFile){
ovlp.hEvent = 0;
res = LockFileEx(pFile->h, LOCKFILE_FAIL_IMMEDIATELY,
0, SHARED_SIZE, 0, &ovlp);
-/* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed.
+/* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed.
*/
#if SQLITE_OS_WINCE==0
}else{
@@ -29850,7 +28192,7 @@ static int unlockReadLock(winFile *pFile){
int res;
if( isNT() ){
res = UnlockFile(pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0);
-/* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed.
+/* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed.
*/
#if SQLITE_OS_WINCE==0
}else{
@@ -29898,8 +28240,8 @@ static int winLock(sqlite3_file *id, int locktype){
DWORD error = NO_ERROR;
assert( id!=0 );
- OSTRACE(("LOCK %d %d was %d(%d)\n",
- pFile->h, locktype, pFile->locktype, pFile->sharedLockByte));
+ OSTRACE5("LOCK %d %d was %d(%d)\n",
+ pFile->h, locktype, pFile->locktype, pFile->sharedLockByte);
/* 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
@@ -29929,7 +28271,7 @@ static int winLock(sqlite3_file *id, int locktype){
/* Try 3 times to get the pending lock. The pending lock might be
** held by another reader process who will release it momentarily.
*/
- OSTRACE(("could not get a PENDING lock. cnt=%d\n", cnt));
+ OSTRACE2("could not get a PENDING lock. cnt=%d\n", cnt);
Sleep(1);
}
gotPendingLock = res;
@@ -29974,13 +28316,13 @@ static int winLock(sqlite3_file *id, int locktype){
if( locktype==EXCLUSIVE_LOCK && res ){
assert( pFile->locktype>=SHARED_LOCK );
res = unlockReadLock(pFile);
- OSTRACE(("unreadlock = %d\n", res));
+ OSTRACE2("unreadlock = %d\n", res);
res = LockFile(pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0);
if( res ){
newLocktype = EXCLUSIVE_LOCK;
}else{
error = GetLastError();
- OSTRACE(("error-code = %d\n", error));
+ OSTRACE2("error-code = %d\n", error);
getReadLock(pFile);
}
}
@@ -29998,8 +28340,8 @@ static int winLock(sqlite3_file *id, int locktype){
if( res ){
rc = SQLITE_OK;
}else{
- OSTRACE(("LOCK FAILED %d trying for %d but got %d\n", pFile->h,
- locktype, newLocktype));
+ OSTRACE4("LOCK FAILED %d trying for %d but got %d\n", pFile->h,
+ locktype, newLocktype);
pFile->lastErrno = error;
rc = SQLITE_BUSY;
}
@@ -30019,14 +28361,14 @@ static int winCheckReservedLock(sqlite3_file *id, int *pResOut){
assert( id!=0 );
if( pFile->locktype>=RESERVED_LOCK ){
rc = 1;
- OSTRACE(("TEST WR-LOCK %d %d (local)\n", pFile->h, rc));
+ OSTRACE3("TEST WR-LOCK %d %d (local)\n", pFile->h, rc);
}else{
rc = LockFile(pFile->h, RESERVED_BYTE, 0, 1, 0);
if( rc ){
UnlockFile(pFile->h, RESERVED_BYTE, 0, 1, 0);
}
rc = !rc;
- OSTRACE(("TEST WR-LOCK %d %d (remote)\n", pFile->h, rc));
+ OSTRACE3("TEST WR-LOCK %d %d (remote)\n", pFile->h, rc);
}
*pResOut = rc;
return SQLITE_OK;
@@ -30049,8 +28391,8 @@ static int winUnlock(sqlite3_file *id, int locktype){
int rc = SQLITE_OK;
assert( pFile!=0 );
assert( locktype<=SHARED_LOCK );
- OSTRACE(("UNLOCK %d to %d was %d(%d)\n", pFile->h, locktype,
- pFile->locktype, pFile->sharedLockByte));
+ OSTRACE5("UNLOCK %d to %d was %d(%d)\n", pFile->h, locktype,
+ pFile->locktype, pFile->sharedLockByte);
type = pFile->locktype;
if( type>=EXCLUSIVE_LOCK ){
UnlockFile(pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0);
@@ -30086,11 +28428,6 @@ static int winFileControl(sqlite3_file *id, int op, void *pArg){
*(int*)pArg = (int)((winFile*)id)->lastErrno;
return SQLITE_OK;
}
- case SQLITE_FCNTL_SIZE_HINT: {
- sqlite3_int64 sz = *(sqlite3_int64*)pArg;
- winTruncate(id, sz);
- return SQLITE_OK;
- }
}
return SQLITE_ERROR;
}
@@ -30118,963 +28455,12 @@ static int winDeviceCharacteristics(sqlite3_file *id){
return 0;
}
-/****************************************************************************
-********************************* Shared Memory *****************************
-**
-** The next subdivision of code manages the shared-memory primitives.
-*/
-#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() );
-** winEnterLeave()
-*/
-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
-
-/*
-** 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.
-**
-** To avoid deadlocks, mutex and mutexBuf are always released in the
-** reverse order that they are acquired. mutexBuf is always acquired
-** first and released last. This invariant is check by asserting
-** sqlite3_mutex_notheld() on mutex whenever mutexBuf is acquired or
-** released.
-*/
-struct winShmNode {
- sqlite3_mutex *mutex; /* Mutex to access this object */
- sqlite3_mutex *mutexBuf; /* Mutex to access zBuf[] */
- char *zFilename; /* Name of the file */
- winFile hFile; /* File handle from winOpen */
- HANDLE hMap; /* File handle from CreateFileMapping */
- DWORD lastErrno; /* The Windows errno from the last I/O error */
- int szMap; /* Size of the mapping of file into memory */
- char *pMMapBuf; /* Where currently mmapped(). NULL if unmapped */
- 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 exclMask; /* Mask of exclusive locks held */
- u8 sharedMask; /* Mask of shared locks held */
- u8 nextShmId; /* Next available winShm.id value */
-#endif
-};
-
-/*
-** 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.
-**
-** winShm.pFile->mutex must be held while reading or writing the
-** winShm.pNext and winShm.locks[] elements.
-**
-** The winShm.pFile element is initialized when the object is created
-** and is read-only thereafter.
-*/
-struct winShm {
- winShmNode *pShmNode; /* The underlying winShmNode object */
- winShm *pNext; /* Next winShm with the same winShmNode */
- u8 lockState; /* Current lock state */
- u8 hasMutex; /* True if holding the winShmNode mutex */
- u8 hasMutexBuf; /* True if holding pFile->mutexBuf */
- u8 sharedMask; /* Mask of shared locks held */
- u8 exclMask; /* Mask of exclusive locks held */
-#ifdef SQLITE_DEBUG
- u8 id; /* Id of this connection with its winShmNode */
-#endif
-};
-
-/*
-** Size increment by which shared memory grows
-*/
-#define SQLITE_WIN_SHM_INCR 4096
-
-/*
-** Constants used for locking
-*/
-#define WIN_SHM_BASE 32 /* Byte offset of the first lock byte */
-#define WIN_SHM_DMS 0x01 /* Mask for Dead-Man-Switch lock */
-#define WIN_SHM_A 0x10 /* Mask for region locks... */
-#define WIN_SHM_B 0x20
-#define WIN_SHM_C 0x40
-#define WIN_SHM_D 0x80
-
-#ifdef SQLITE_DEBUG
-/*
-** Return a pointer to a nul-terminated string in static memory that
-** describes a locking mask. The string is of the form "MSABCD" with
-** each character representing a lock. "M" for MUTEX, "S" for DMS,
-** and "A" through "D" for the region locks. If a lock is held, the
-** letter is shown. If the lock is not held, the letter is converted
-** to ".".
-**
-** This routine is for debugging purposes only and does not appear
-** in a production build.
-*/
-static const char *winShmLockString(u8 mask){
- static char zBuf[48];
- static int iBuf = 0;
- char *z;
-
- z = &zBuf[iBuf];
- iBuf += 8;
- if( iBuf>=sizeof(zBuf) ) iBuf = 0;
-
- z[0] = (mask & WIN_SHM_DMS) ? 'S' : '.';
- z[1] = (mask & WIN_SHM_A) ? 'A' : '.';
- z[2] = (mask & WIN_SHM_B) ? 'B' : '.';
- z[3] = (mask & WIN_SHM_C) ? 'C' : '.';
- z[4] = (mask & WIN_SHM_D) ? 'D' : '.';
- z[5] = 0;
- return z;
-}
-#endif /* SQLITE_DEBUG */
-
-/*
-** Apply posix advisory locks for all bytes identified in lockMask.
-**
-** lockMask might contain multiple bits but all bits are guaranteed
-** to be contiguous.
-**
-** Locks block if the mask is exactly WIN_SHM_C and are non-blocking
-** otherwise.
-*/
-#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 */
- u8 lockMask /* Which bytes to lock or unlock */
-){
- OVERLAPPED ovlp;
- DWORD dwFlags;
- int nBytes; /* Number of bytes to lock */
- int i; /* Offset into the locking byte range */
- int rc = 0; /* Result code form Lock/UnlockFileEx() */
- u8 mask; /* Mask of bits in lockMask */
-
- /* Access to the winShmNode object is serialized by the caller */
- assert( sqlite3_mutex_held(pFile->mutex) || pFile->nRef==0 );
-
- /* Initialize the locking parameters */
- if( lockMask==WIN_SHM_C && lockType!=_SHM_UNLCK ){
- dwFlags = 0;
- OSTRACE(("SHM-LOCK %d requesting blocking lock %s\n",
- pFile->hFile.h,
- winShmLockString(lockMask)));
- }else{
- dwFlags = LOCKFILE_FAIL_IMMEDIATELY;
- OSTRACE(("SHM-LOCK %d requesting %s %s\n",
- pFile->hFile.h,
- lockType!=_SHM_UNLCK ? "lock" : "unlock",
- winShmLockString(lockMask)));
- }
- if( lockType == _SHM_WRLCK ) dwFlags |= LOCKFILE_EXCLUSIVE_LOCK;
-
- /* Find the first bit in lockMask that is set */
- for(i=0, mask=0x01; mask!=0 && (lockMask&mask)==0; mask <<= 1, i++){}
- assert( mask!=0 );
- memset(&ovlp, 0, sizeof(OVERLAPPED));
- ovlp.Offset = i+WIN_SHM_BASE;
- nBytes = 1;
-
- /* Extend the locking range for each additional bit that is set */
- mask <<= 1;
- while( mask!=0 && (lockMask & mask)!=0 ){
- nBytes++;
- mask <<= 1;
- }
-
- /* Verify that all bits set in lockMask are contiguous */
- assert( mask==0 || (lockMask & ~(mask | (mask-1)))==0 );
-
- /* Release/Acquire the system-level lock */
- if( lockType==_SHM_UNLCK ){
- for(i=0; i<nBytes; i++, ovlp.Offset++){
- rc = UnlockFileEx(pFile->hFile.h, 0, 1, 0, &ovlp);
- if( !rc ) break;
- }
- }else{
- /* release old individual byte locks (if any)
- ** and set new individual byte locks */
- for(i=0; i<nBytes; i++, ovlp.Offset++){
- UnlockFileEx(pFile->hFile.h, 0, 1, 0, &ovlp);
- rc = LockFileEx(pFile->hFile.h, dwFlags, 0, 1, 0, &ovlp);
- if( !rc ) break;
- }
- }
- if( !rc ){
- OSTRACE(("SHM-LOCK %d %s ERROR 0x%08lx\n",
- pFile->hFile.h,
- lockType==_SHM_UNLCK ? "UnlockFileEx" : "LockFileEx",
- GetLastError()));
- /* release individual byte locks (if any) */
- ovlp.Offset-=i;
- for(i=0; i<nBytes; i++, ovlp.Offset++){
- UnlockFileEx(pFile->hFile.h, 0, 1, 0, &ovlp);
- }
- }
- rc = (rc!=0) ? SQLITE_OK : SQLITE_BUSY;
-
- /* Update the global lock state and do debug tracing */
-#ifdef SQLITE_DEBUG
- OSTRACE(("SHM-LOCK %d ", pFile->hFile.h));
- if( rc==SQLITE_OK ){
- if( lockType==_SHM_UNLCK ){
- OSTRACE(("unlock ok"));
- pFile->exclMask &= ~lockMask;
- pFile->sharedMask &= ~lockMask;
- }else if( lockType==_SHM_RDLCK ){
- OSTRACE(("read-lock ok"));
- pFile->exclMask &= ~lockMask;
- pFile->sharedMask |= lockMask;
- }else{
- assert( lockType==_SHM_WRLCK );
- OSTRACE(("write-lock ok"));
- pFile->exclMask |= lockMask;
- pFile->sharedMask &= ~lockMask;
- }
- }else{
- if( lockType==_SHM_UNLCK ){
- OSTRACE(("unlock failed"));
- }else if( lockType==_SHM_RDLCK ){
- OSTRACE(("read-lock failed"));
- }else{
- assert( lockType==_SHM_WRLCK );
- OSTRACE(("write-lock failed"));
- }
- }
- OSTRACE((" - change requested %s - afterwards %s:%s\n",
- winShmLockString(lockMask),
- winShmLockString(pFile->sharedMask),
- winShmLockString(pFile->exclMask)));
-#endif
-
- return rc;
-}
-
-/*
-** For connection p, unlock all of the locks identified by the unlockMask
-** parameter.
-*/
-static int winShmUnlock(
- winShmNode *pFile, /* The underlying shared-memory file */
- winShm *p, /* The connection to be unlocked */
- u8 unlockMask /* Mask of locks to be unlocked */
-){
- int rc; /* Result code */
- winShm *pX; /* For looping over all sibling connections */
- u8 allMask; /* Union of locks held by connections other than "p" */
-
- /* Access to the winShmNode object is serialized by the caller */
- assert( sqlite3_mutex_held(pFile->mutex) );
-
- /* don't attempt to unlock anything we don't have locks for */
- if( (unlockMask & (p->exclMask|p->sharedMask)) != unlockMask ){
- OSTRACE(("SHM-LOCK %d unlocking more than we have locked - requested %s - have %s\n",
- pFile->hFile.h,
- winShmLockString(unlockMask),
- winShmLockString(p->exclMask|p->sharedMask)));
- unlockMask &= (p->exclMask|p->sharedMask);
- }
-
- /* Compute locks held by sibling connections */
- allMask = 0;
- for(pX=pFile->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( (unlockMask & allMask)!=unlockMask ){
- rc = winShmSystemLock(pFile, _SHM_UNLCK, unlockMask & ~allMask);
- }else{
- rc = SQLITE_OK;
- }
-
- /* Undo the local locks */
- if( rc==SQLITE_OK ){
- p->exclMask &= ~unlockMask;
- p->sharedMask &= ~unlockMask;
- }
- return rc;
-}
-
-/*
-** Get reader locks for connection p on all locks in the readMask parameter.
-*/
-static int winShmSharedLock(
- winShmNode *pFile, /* The underlying shared-memory file */
- winShm *p, /* The connection to get the shared locks */
- u8 readMask /* Mask of shared locks to be acquired */
-){
- int rc; /* Result code */
- winShm *pX; /* For looping over all sibling connections */
- u8 allShared; /* Union of locks held by connections other than "p" */
-
- /* Access to the winShmNode object is serialized by the caller */
- assert( sqlite3_mutex_held(pFile->mutex) );
-
- /* 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.
- */
- allShared = 0;
- for(pX=pFile->pFirst; pX; pX=pX->pNext){
- if( pX==p ) continue;
- if( (pX->exclMask & readMask)!=0 ) return SQLITE_BUSY;
- allShared |= pX->sharedMask;
- }
-
- /* Get shared locks at the system level, if necessary */
- if( (~allShared) & readMask ){
- rc = winShmSystemLock(pFile, _SHM_RDLCK, readMask);
- }else{
- rc = SQLITE_OK;
- }
-
- /* Get the local shared locks */
- if( rc==SQLITE_OK ){
- p->sharedMask |= readMask;
- }
- return rc;
-}
-
-/*
-** For connection p, get an exclusive lock on all locks identified in
-** the writeMask parameter.
-*/
-static int winShmExclusiveLock(
- winShmNode *pFile, /* The underlying shared-memory file */
- winShm *p, /* The connection to get the exclusive locks */
- u8 writeMask /* Mask of exclusive locks to be acquired */
-){
- int rc; /* Result code */
- winShm *pX; /* For looping over all sibling connections */
-
- /* Access to the winShmNode object is serialized by the caller */
- assert( sqlite3_mutex_held(pFile->mutex) );
-
- /* Make sure no sibling connections hold locks that will block this
- ** lock. If any do, return SQLITE_BUSY right away.
- */
- for(pX=pFile->pFirst; pX; pX=pX->pNext){
- if( pX==p ) continue;
- if( (pX->exclMask & writeMask)!=0 ) return SQLITE_BUSY;
- if( (pX->sharedMask & writeMask)!=0 ) return SQLITE_BUSY;
- }
-
- /* Get the exclusive locks at the system level. Then if successful
- ** also mark the local connection as being locked.
- */
- rc = winShmSystemLock(pFile, _SHM_WRLCK, writeMask);
- if( rc==SQLITE_OK ){
- p->sharedMask &= ~writeMask;
- p->exclMask |= writeMask;
- }
- return rc;
-}
-
-/*
-** 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 void winShmPurge(void){
- winShmNode **pp;
- winShmNode *p;
- assert( winShmMutexHeld() );
- pp = &winShmNodeList;
- while( (p = *pp)!=0 ){
- if( p->nRef==0 ){
- if( p->mutex ) sqlite3_mutex_free(p->mutex);
- if( p->mutexBuf ) sqlite3_mutex_free(p->mutexBuf);
- if( p->pMMapBuf ){
- UnmapViewOfFile(p->pMMapBuf);
- }
- if( INVALID_HANDLE_VALUE != p->hMap ){
- CloseHandle(p->hMap);
- }
- if( p->hFile.h != INVALID_HANDLE_VALUE ) {
- winClose((sqlite3_file *)&p->hFile);
- }
- *pp = p->pNext;
- sqlite3_free(p);
- }else{
- pp = &p->pNext;
- }
- }
-}
-
-/* Forward references to VFS methods */
-static int winOpen(sqlite3_vfs*,const char*,sqlite3_file*,int,int*);
-static int winDelete(sqlite3_vfs *,const char*,int);
-
-/*
-** Open a shared-memory area. This particular implementation uses
-** mmapped files.
-**
-** zName is a filename used to identify the shared-memory area. The
-** implementation does not (and perhaps should not) use this name
-** directly, but rather use it as a template for finding an appropriate
-** name for the shared-memory storage. In this implementation, the
-** string "-index" is appended to zName and used as the name of the
-** mmapped file.
-**
-** 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 winShmOpen(
- sqlite3_file *fd /* The file to which to attach shared memory */
-){
- struct winFile *pDbFd; /* Database to which to attach SHM */
- 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 */
-
- pDbFd = (winFile*)fd;
- assert( pDbFd->pShm==0 ); /* Not previously opened */
-
- /* Allocate space for the new sqlite3_shm object. Also speculatively
- ** allocate space for a new winShmNode and filename.
- */
- p = sqlite3_malloc( sizeof(*p) );
- if( p==0 ) return SQLITE_NOMEM;
- memset(p, 0, sizeof(*p));
- nName = sqlite3Strlen30(pDbFd->zPath);
- pNew = sqlite3_malloc( sizeof(*pShmNode) + nName + 15 );
- if( pNew==0 ){
- sqlite3_free(p);
- return SQLITE_NOMEM;
- }
- memset(pNew, 0, sizeof(*pNew));
- pNew->zFilename = (char*)&pNew[1];
- sqlite3_snprintf(nName+15, pNew->zFilename, "%s-wal-index", pDbFd->zPath);
-
- /* Look to see if there is an existing winShmNode that can be used.
- ** If no matching winShmNode currently exists, create a new one.
- */
- 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;
- }
- if( pShmNode ){
- sqlite3_free(pNew);
- }else{
- pShmNode = pNew;
- pNew = 0;
- pShmNode->pMMapBuf = NULL;
- pShmNode->hMap = INVALID_HANDLE_VALUE;
- ((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_NOMEM;
- goto shm_open_err;
- }
- pShmNode->mutexBuf = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
- if( pShmNode->mutexBuf==0 ){
- rc = SQLITE_NOMEM;
- goto shm_open_err;
- }
- rc = winOpen(pDbFd->pVfs,
- pShmNode->zFilename, /* Name of the file (UTF-8) */
- (sqlite3_file*)&pShmNode->hFile, /* File handle here */
- SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, /* Mode flags */
- 0);
- if( SQLITE_OK!=rc ){
- rc = SQLITE_CANTOPEN_BKPT;
- goto shm_open_err;
- }
-
- /* 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)==SQLITE_OK ){
- rc = winTruncate((sqlite3_file *)&pShmNode->hFile, 0);
- }
- if( rc==SQLITE_OK ){
- rc = winShmSystemLock(pShmNode, _SHM_RDLCK, WIN_SHM_DMS);
- }
- if( rc ) goto shm_open_err;
- }
-
- /* Make the new connection a child of the winShmNode */
- p->pShmNode = pShmNode;
- p->pNext = pShmNode->pFirst;
-#ifdef SQLITE_DEBUG
- p->id = pShmNode->nextShmId++;
-#endif
- pShmNode->pFirst = p;
- pShmNode->nRef++;
- pDbFd->pShm = p;
- winShmLeaveMutex();
- return SQLITE_OK;
-
- /* Jump here on any error */
-shm_open_err:
- winShmSystemLock(pShmNode, _SHM_UNLCK, WIN_SHM_DMS);
- winShmPurge(); /* 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.
-*/
-static int winShmClose(
- 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;
- pShmNode = p->pShmNode;
-
- /* Verify that the connection being closed holds no locks */
- assert( p->exclMask==0 );
- assert( p->sharedMask==0 );
-
- /* 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 */
- winShmEnterMutex();
- assert( pShmNode->nRef>0 );
- pShmNode->nRef--;
- if( pShmNode->nRef==0 ){
- if( deleteFlag ) winDelete(pDbFd->pVfs, pShmNode->zFilename, 0);
- winShmPurge();
- }
- winShmLeaveMutex();
-
- return SQLITE_OK;
-}
-
-/*
-** Query and/or changes the size of the underlying storage for
-** a shared-memory segment. The reqSize parameter is the new size
-** of the underlying storage, or -1 to do just a query. The size
-** of the underlying storage (after resizing if resizing occurs) is
-** written into pNewSize.
-**
-** This routine does not (necessarily) change the size of the mapping
-** of the underlying storage into memory. Use xShmGet() to change
-** the mapping size.
-**
-** The reqSize parameter is the minimum size requested. The implementation
-** is free to expand the storage to some larger amount if it chooses.
-*/
-static int winShmSize(
- sqlite3_file *fd, /* Database holding the shared memory */
- int reqSize, /* Requested size. -1 for query only */
- int *pNewSize /* Write new size here */
-){
- winFile *pDbFd = (winFile*)fd;
- winShm *p = pDbFd->pShm;
- winShmNode *pShmNode = p->pShmNode;
- int rc = SQLITE_OK;
-
- *pNewSize = 0;
- if( reqSize>=0 ){
- sqlite3_int64 sz;
- rc = winFileSize((sqlite3_file *)&pShmNode->hFile, &sz);
- if( SQLITE_OK==rc ){
- reqSize = (reqSize + SQLITE_WIN_SHM_INCR - 1)/SQLITE_WIN_SHM_INCR;
- reqSize *= SQLITE_WIN_SHM_INCR;
- if( reqSize>sz ){
- rc = winTruncate((sqlite3_file *)&pShmNode->hFile, reqSize);
- }
- }
- }
- if( SQLITE_OK==rc ){
- sqlite3_int64 sz;
- rc = winFileSize((sqlite3_file *)&pShmNode->hFile, &sz);
- if( SQLITE_OK==rc ){
- *pNewSize = (int)sz;
- }else{
- rc = SQLITE_IOERR;
- }
- }
- return rc;
-}
-
-
-/*
-** Map the shared storage into memory. The minimum size of the
-** mapping should be reqMapSize if reqMapSize is positive. If
-** reqMapSize is zero or negative, the implementation can choose
-** whatever mapping size is convenient.
-**
-** *ppBuf is made to point to the memory which is a mapping of the
-** underlying storage. A mutex is acquired to prevent other threads
-** from running while *ppBuf is in use in order to prevent other threads
-** remapping *ppBuf out from under this thread. The winShmRelease()
-** call will release the mutex. However, if the lock state is CHECKPOINT,
-** the mutex is not acquired because CHECKPOINT will never remap the
-** buffer. RECOVER might remap, though, so CHECKPOINT will acquire
-** the mutex if and when it promotes to RECOVER.
-**
-** RECOVER needs to be atomic. The same mutex that prevents *ppBuf from
-** being remapped also prevents more than one thread from being in
-** RECOVER at a time. But, RECOVER sometimes wants to remap itself.
-** To prevent RECOVER from losing its lock while remapping, the
-** mutex is not released by winShmRelease() when in RECOVER.
-**
-** *pNewMapSize is set to the size of the mapping.
-**
-** *ppBuf and *pNewMapSize might be NULL and zero if no space has
-** yet been allocated to the underlying storage.
-*/
-static int winShmGet(
- sqlite3_file *fd, /* The database file holding the shared memory */
- int reqMapSize, /* Requested size of mapping. -1 means don't care */
- int *pNewMapSize, /* Write new size of mapping here */
- void **ppBuf /* Write mapping buffer origin here */
-){
- winFile *pDbFd = (winFile*)fd;
- winShm *p = pDbFd->pShm;
- winShmNode *pShmNode = p->pShmNode;
- int rc = SQLITE_OK;
-
- if( p->lockState!=SQLITE_SHM_CHECKPOINT && p->hasMutexBuf==0 ){
- assert( sqlite3_mutex_notheld(pShmNode->mutex) );
- sqlite3_mutex_enter(pShmNode->mutexBuf);
- p->hasMutexBuf = 1;
- }
- sqlite3_mutex_enter(pShmNode->mutex);
- if( pShmNode->szMap==0 || reqMapSize>pShmNode->szMap ){
- int actualSize;
- if( winShmSize(fd, -1, &actualSize)==SQLITE_OK
- && reqMapSize<actualSize
- ){
- reqMapSize = actualSize;
- }
- if( pShmNode->pMMapBuf ){
- if( !UnmapViewOfFile(pShmNode->pMMapBuf) ){
- pShmNode->lastErrno = GetLastError();
- rc = SQLITE_IOERR;
- }
- CloseHandle(pShmNode->hMap);
- pShmNode->hMap = INVALID_HANDLE_VALUE;
- }
- if( SQLITE_OK == rc ){
- pShmNode->pMMapBuf = 0;
- if( reqMapSize == 0 ){
- /* can't create 0 byte file mapping in Windows */
- pShmNode->szMap = 0;
- }else{
- /* create the file mapping object */
- if( INVALID_HANDLE_VALUE == pShmNode->hMap ){
- /* TBD provide an object name to each file
- ** mapping so it can be re-used across processes.
- */
- pShmNode->hMap = CreateFileMapping(pShmNode->hFile.h,
- NULL,
- PAGE_READWRITE,
- 0,
- reqMapSize,
- NULL);
- }
- if( NULL==pShmNode->hMap ){
- pShmNode->lastErrno = GetLastError();
- rc = SQLITE_IOERR;
- pShmNode->szMap = 0;
- pShmNode->hMap = INVALID_HANDLE_VALUE;
- }else{
- pShmNode->pMMapBuf = MapViewOfFile(pShmNode->hMap,
- FILE_MAP_WRITE | FILE_MAP_READ,
- 0,
- 0,
- reqMapSize);
- if( !pShmNode->pMMapBuf ){
- pShmNode->lastErrno = GetLastError();
- rc = SQLITE_IOERR;
- pShmNode->szMap = 0;
- }else{
- pShmNode->szMap = reqMapSize;
- }
- }
- }
- }
- }
- *pNewMapSize = pShmNode->szMap;
- *ppBuf = pShmNode->pMMapBuf;
- sqlite3_mutex_leave(pShmNode->mutex);
- return rc;
-}
-
-/*
-** Release the lock held on the shared memory segment so that other
-** threads are free to resize it if necessary.
-**
-** If the lock is not currently held, this routine is a harmless no-op.
-**
-** If the shared-memory object is in lock state RECOVER, then we do not
-** really want to release the lock, so in that case too, this routine
-** is a no-op.
-*/
-static int winShmRelease(sqlite3_file *fd){
- winFile *pDbFd = (winFile*)fd;
- winShm *p = pDbFd->pShm;
- if( p->hasMutexBuf && p->lockState!=SQLITE_SHM_RECOVER ){
- winShmNode *pShmNode = p->pShmNode;
- assert( sqlite3_mutex_notheld(pShmNode->mutex) );
- sqlite3_mutex_leave(pShmNode->mutexBuf);
- p->hasMutexBuf = 0;
- }
- return SQLITE_OK;
-}
-
-/*
-** Symbolic names for LOCK states used for debugging.
-*/
-#ifdef SQLITE_DEBUG
-static const char *azLkName[] = {
- "UNLOCK",
- "READ",
- "READ_FULL",
- "WRITE",
- "PENDING",
- "CHECKPOINT",
- "RECOVER"
-};
-#endif
-
-
-/*
-** Change the lock state for a shared-memory segment.
-*/
-static int winShmLock(
- sqlite3_file *fd, /* Database holding the shared memory */
- int desiredLock, /* One of SQLITE_SHM_xxxxx locking states */
- int *pGotLock /* The lock you actually got */
-){
- winFile *pDbFd = (winFile*)fd;
- winShm *p = pDbFd->pShm;
- winShmNode *pShmNode = p->pShmNode;
- int rc = SQLITE_PROTOCOL;
-
- /* Note that SQLITE_SHM_READ_FULL and SQLITE_SHM_PENDING are never
- ** directly requested; they are side effects from requesting
- ** SQLITE_SHM_READ and SQLITE_SHM_CHECKPOINT, respectively.
- */
- assert( desiredLock==SQLITE_SHM_UNLOCK
- || desiredLock==SQLITE_SHM_READ
- || desiredLock==SQLITE_SHM_WRITE
- || desiredLock==SQLITE_SHM_CHECKPOINT
- || desiredLock==SQLITE_SHM_RECOVER );
-
- /* Return directly if this is just a lock state query, or if
- ** the connection is already in the desired locking state.
- */
- if( desiredLock==p->lockState
- || (desiredLock==SQLITE_SHM_READ && p->lockState==SQLITE_SHM_READ_FULL)
- ){
- OSTRACE(("SHM-LOCK %d shmid-%d, pid-%d request %s and got %s\n",
- pShmNode->hFile.h,
- p->id, (int)GetCurrentProcessId(), azLkName[desiredLock],
- azLkName[p->lockState]));
- if( pGotLock ) *pGotLock = p->lockState;
- return SQLITE_OK;
- }
-
- OSTRACE(("SHM-LOCK %d shmid-%d, pid-%d request %s->%s\n",
- pShmNode->hFile.h,
- p->id, (int)GetCurrentProcessId(), azLkName[p->lockState],
- azLkName[desiredLock]));
-
- if( desiredLock==SQLITE_SHM_RECOVER && !p->hasMutexBuf ){
- assert( sqlite3_mutex_notheld(pShmNode->mutex) );
- sqlite3_mutex_enter(pShmNode->mutexBuf);
- p->hasMutexBuf = 1;
- }
- sqlite3_mutex_enter(pShmNode->mutex);
- switch( desiredLock ){
- case SQLITE_SHM_UNLOCK: {
- assert( p->lockState!=SQLITE_SHM_RECOVER );
- winShmUnlock(pShmNode, p, WIN_SHM_A|WIN_SHM_B|WIN_SHM_C|WIN_SHM_D);
- rc = SQLITE_OK;
- p->lockState = SQLITE_SHM_UNLOCK;
- break;
- }
- case SQLITE_SHM_READ: {
- if( p->lockState==SQLITE_SHM_UNLOCK ){
- int nAttempt;
- rc = SQLITE_BUSY;
- assert( p->lockState==SQLITE_SHM_UNLOCK );
- for(nAttempt=0; nAttempt<5 && rc==SQLITE_BUSY; nAttempt++){
- rc = winShmSharedLock(pShmNode, p, WIN_SHM_A|WIN_SHM_B);
- if( rc==SQLITE_BUSY ){
- rc = winShmSharedLock(pShmNode, p, WIN_SHM_D);
- if( rc==SQLITE_OK ){
- p->lockState = SQLITE_SHM_READ_FULL;
- }
- }else{
- winShmUnlock(pShmNode, p, WIN_SHM_B);
- p->lockState = SQLITE_SHM_READ;
- }
- }
- }else{
- assert( p->lockState==SQLITE_SHM_WRITE
- || p->lockState==SQLITE_SHM_RECOVER );
- rc = winShmSharedLock(pShmNode, p, WIN_SHM_A);
- winShmUnlock(pShmNode, p, WIN_SHM_C|WIN_SHM_D);
- p->lockState = SQLITE_SHM_READ;
- }
- break;
- }
- case SQLITE_SHM_WRITE: {
- assert( p->lockState==SQLITE_SHM_READ
- || p->lockState==SQLITE_SHM_READ_FULL );
- rc = winShmExclusiveLock(pShmNode, p, WIN_SHM_C|WIN_SHM_D);
- if( rc==SQLITE_OK ){
- p->lockState = SQLITE_SHM_WRITE;
- }
- break;
- }
- case SQLITE_SHM_CHECKPOINT: {
- assert( p->lockState==SQLITE_SHM_UNLOCK
- || p->lockState==SQLITE_SHM_PENDING
- );
- if( p->lockState==SQLITE_SHM_UNLOCK ){
- rc = winShmExclusiveLock(pShmNode, p, WIN_SHM_B|WIN_SHM_C);
- if( rc==SQLITE_OK ){
- p->lockState = SQLITE_SHM_PENDING;
- }
- }
- if( p->lockState==SQLITE_SHM_PENDING ){
- rc = winShmExclusiveLock(pShmNode, p, WIN_SHM_A);
- if( rc==SQLITE_OK ){
- p->lockState = SQLITE_SHM_CHECKPOINT;
- }
- }
- break;
- }
- default: {
- assert( desiredLock==SQLITE_SHM_RECOVER );
- assert( p->lockState==SQLITE_SHM_READ
- || p->lockState==SQLITE_SHM_READ_FULL
- );
- assert( sqlite3_mutex_held(pShmNode->mutexBuf) );
- rc = winShmExclusiveLock(pShmNode, p, WIN_SHM_C);
- if( rc==SQLITE_OK ){
- p->lockState = SQLITE_SHM_RECOVER;
- }
- break;
- }
- }
- sqlite3_mutex_leave(pShmNode->mutex);
- OSTRACE(("SHM-LOCK %d shmid-%d, pid-%d got %s\n",
- pShmNode->hFile.h,
- p->id, (int)GetCurrentProcessId(), azLkName[p->lockState]));
- if( pGotLock ) *pGotLock = p->lockState;
- return rc;
-}
-
-/*
-** 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 winShmBarrier(
- sqlite3_file *fd /* Database holding the shared memory */
-){
- /* MemoryBarrier(); // does not work -- do not know why not */
- winShmEnterMutex();
- winShmLeaveMutex();
-}
-
-#else
-# define winShmOpen 0
-# define winShmSize 0
-# define winShmGet 0
-# define winShmRelease 0
-# define winShmLock 0
-# define winShmBarrier 0
-# define winShmClose 0
-#endif /* #ifndef SQLITE_OMIT_WAL */
-/*
-***************************** End Shared Memory *****************************
-****************************************************************************/
-
/*
** This vector defines all the methods that can operate on an
** sqlite3_file for win32.
*/
static const sqlite3_io_methods winIoMethod = {
- 2, /* iVersion */
+ 1, /* iVersion */
winClose,
winRead,
winWrite,
@@ -31086,14 +28472,7 @@ static const sqlite3_io_methods winIoMethod = {
winCheckReservedLock,
winFileControl,
winSectorSize,
- winDeviceCharacteristics,
- winShmOpen, /* xShmOpen */
- winShmSize, /* xShmSize */
- winShmGet, /* xShmGet */
- winShmRelease, /* xShmRelease */
- winShmLock, /* xShmLock */
- winShmBarrier, /* xShmBarrier */
- winShmClose /* xShmClose */
+ winDeviceCharacteristics
};
/***************************************************************************
@@ -31112,7 +28491,7 @@ static void *convertUtf8Filename(const char *zFilename){
void *zConverted = 0;
if( isNT() ){
zConverted = utf8ToUnicode(zFilename);
-/* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed.
+/* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed.
*/
#if SQLITE_OS_WINCE==0
}else{
@@ -31147,7 +28526,7 @@ static int getTempname(int nBuf, char *zBuf){
}else{
return SQLITE_NOMEM;
}
-/* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed.
+/* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed.
** Since the ASCII version of these Windows API do not exist for WINCE,
** it's important to not reference them for WINCE builds.
*/
@@ -31175,8 +28554,8 @@ static int getTempname(int nBuf, char *zBuf){
zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ];
}
zBuf[j] = 0;
- OSTRACE(("TEMP FILENAME: %s\n", zBuf));
- return SQLITE_OK;
+ OSTRACE2("TEMP FILENAME: %s\n", zBuf);
+ return SQLITE_OK;
}
/*
@@ -31208,7 +28587,7 @@ static int getLastErrorMsg(int nBuf, char *zBuf){
/* free the system buffer allocated by FormatMessage */
LocalFree(zTempWide);
}
-/* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed.
+/* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed.
** Since the ASCII version of these Windows API do not exist for WINCE,
** it's important to not reference them for WINCE builds.
*/
@@ -31267,10 +28646,8 @@ static int winOpen(
assert( id!=0 );
UNUSED_PARAMETER(pVfs);
- pFile->h = INVALID_HANDLE_VALUE;
-
- /* If the second argument to this function is NULL, generate a
- ** temporary file name to use
+ /* If the second argument to this function is NULL, generate a
+ ** temporary file name to use
*/
if( !zUtf8Name ){
int rc = getTempname(MAX_PATH+1, zTmpname);
@@ -31291,8 +28668,8 @@ static int winOpen(
}else{
dwDesiredAccess = GENERIC_READ;
}
- /* SQLITE_OPEN_EXCLUSIVE is used to make sure that a new file is
- ** created. SQLite doesn't use it to indicate "exclusive access"
+ /* 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.
*/
assert(!(flags & SQLITE_OPEN_EXCLUSIVE) || (flags & SQLITE_OPEN_CREATE));
@@ -31334,7 +28711,7 @@ static int winOpen(
dwFlagsAndAttributes,
NULL
);
-/* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed.
+/* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed.
** Since the ASCII version of these Windows API do not exist for WINCE,
** it's important to not reference them for WINCE builds.
*/
@@ -31350,13 +28727,10 @@ static int winOpen(
);
#endif
}
- OSTRACE(("OPEN %d %s 0x%lx %s\n",
- h, zName, dwDesiredAccess,
- h==INVALID_HANDLE_VALUE ? "failed" : "ok"));
if( h==INVALID_HANDLE_VALUE ){
free(zConverted);
if( flags & SQLITE_OPEN_READWRITE ){
- return winOpen(pVfs, zName, id,
+ return winOpen(pVfs, zName, id,
((flags|SQLITE_OPEN_READONLY)&~SQLITE_OPEN_READWRITE), pOutFlags);
}else{
return SQLITE_CANTOPEN_BKPT;
@@ -31373,9 +28747,6 @@ static int winOpen(
pFile->pMethod = &winIoMethod;
pFile->h = h;
pFile->lastErrno = NO_ERROR;
- pFile->pVfs = pVfs;
- pFile->pShm = 0;
- pFile->zPath = zName;
pFile->sectorSize = getSectorSize(pVfs, zUtf8Name);
#if SQLITE_OS_WINCE
if( (flags & (SQLITE_OPEN_READWRITE|SQLITE_OPEN_MAIN_DB)) ==
@@ -31432,7 +28803,7 @@ static int winDelete(
|| ((error = GetLastError()) == ERROR_ACCESS_DENIED))
&& (++cnt < MX_DELETION_ATTEMPTS)
&& (Sleep(100), 1) );
-/* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed.
+/* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed.
** Since the ASCII version of these Windows API do not exist for WINCE,
** it's important to not reference them for WINCE builds.
*/
@@ -31447,11 +28818,8 @@ static int winDelete(
#endif
}
free(zConverted);
- OSTRACE(("DELETE \"%s\" %s\n", zFilename,
- ( (rc==INVALID_FILE_ATTRIBUTES) && (error==ERROR_FILE_NOT_FOUND)) ?
- "ok" : "failed" ));
-
- return ( (rc == INVALID_FILE_ATTRIBUTES)
+ OSTRACE2("DELETE \"%s\"\n", zFilename);
+ return ( (rc == INVALID_FILE_ATTRIBUTES)
&& (error == ERROR_FILE_NOT_FOUND)) ? SQLITE_OK : SQLITE_IOERR_DELETE;
}
@@ -31473,7 +28841,7 @@ static int winAccess(
}
if( isNT() ){
attr = GetFileAttributesW((WCHAR*)zConverted);
-/* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed.
+/* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed.
** Since the ASCII version of these Windows API do not exist for WINCE,
** it's important to not reference them for WINCE builds.
*/
@@ -31510,7 +28878,7 @@ static int winFullPathname(
int nFull, /* Size of output buffer in bytes */
char *zFull /* Output buffer */
){
-
+
#if defined(__CYGWIN__)
UNUSED_PARAMETER(nFull);
cygwin_conv_to_full_win32_path(zRelative, zFull);
@@ -31542,7 +28910,7 @@ static int winFullPathname(
free(zConverted);
zOut = unicodeToUtf8(zTemp);
free(zTemp);
-/* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed.
+/* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed.
** Since the ASCII version of these Windows API do not exist for WINCE,
** it's important to not reference them for WINCE builds.
*/
@@ -31636,7 +29004,7 @@ static int getSectorSize(
}
}
#endif
- return (int) bytesPerSector;
+ return (int) bytesPerSector;
}
#ifndef SQLITE_OMIT_LOAD_EXTENSION
@@ -31657,7 +29025,7 @@ static void *winDlOpen(sqlite3_vfs *pVfs, const char *zFilename){
}
if( isNT() ){
h = LoadLibraryW((WCHAR*)zConverted);
-/* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed.
+/* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed.
** Since the ASCII version of these Windows API do not exist for WINCE,
** it's important to not reference them for WINCE builds.
*/
@@ -31743,34 +29111,36 @@ static int winSleep(sqlite3_vfs *pVfs, int microsec){
}
/*
-** 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.
+** The following variable, if set to a non-zero value, becomes the result
+** returned from sqlite3OsCurrentTime(). This is used for testing.
*/
#ifdef SQLITE_TEST
-SQLITE_API int sqlite3_current_time = 0; /* Fake system time in seconds since 1970. */
+SQLITE_API int sqlite3_current_time = 0;
#endif
/*
-** 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 0. Return 1 if the time and date cannot be found.
+** 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 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).
- */
+int winCurrentTime(sqlite3_vfs *pVfs, double *prNow){
FILETIME ft;
- static const sqlite3_int64 winFiletimeEpoch = 23058135*(sqlite3_int64)8640000;
-#ifdef SQLITE_TEST
- static const sqlite3_int64 unixEpoch = 24405875*(sqlite3_int64)8640000;
-#endif
+ /* FILETIME structure is a 64-bit value representing the number of
+ 100-nanosecond intervals since January 1, 1601 (= JD 2305813.5).
+ */
+ sqlite3_int64 timeW; /* Whole days */
+ sqlite3_int64 timeF; /* Fractional Days */
+
+ /* Number of 100-nanosecond intervals in a single day */
+ static const sqlite3_int64 ntuPerDay =
+ 10000000*(sqlite3_int64)86400;
+
+ /* Number of 100-nanosecond intervals in half of a day */
+ static const sqlite3_int64 ntuPerHalfDay =
+ 10000000*(sqlite3_int64)43200;
+
/* 2^32 - to avoid use of LL and warnings in gcc */
- static const sqlite3_int64 max32BitValue =
+ static const sqlite3_int64 max32BitValue =
(sqlite3_int64)2000000000 + (sqlite3_int64)2000000000 + (sqlite3_int64)294967296;
#if SQLITE_OS_WINCE
@@ -31783,36 +29153,24 @@ static int winCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *piNow){
#else
GetSystemTimeAsFileTime( &ft );
#endif
-
- *piNow = winFiletimeEpoch +
- ((((sqlite3_int64)ft.dwHighDateTime)*max32BitValue) +
- (sqlite3_int64)ft.dwLowDateTime)/(sqlite3_int64)1000;
-
+ UNUSED_PARAMETER(pVfs);
+ timeW = (((sqlite3_int64)ft.dwHighDateTime)*max32BitValue) + (sqlite3_int64)ft.dwLowDateTime;
+ timeF = timeW % ntuPerDay; /* fractional days (100-nanoseconds) */
+ timeW = timeW / ntuPerDay; /* whole days */
+ timeW = timeW + 2305813; /* add whole days (from 2305813.5) */
+ timeF = timeF + ntuPerHalfDay; /* add half a day (from 2305813.5) */
+ timeW = timeW + (timeF/ntuPerDay); /* add whole day if half day made one */
+ timeF = timeF % ntuPerDay; /* compute new fractional days */
+ *prNow = (double)timeW + ((double)timeF / (double)ntuPerDay);
#ifdef SQLITE_TEST
if( sqlite3_current_time ){
- *piNow = 1000*(sqlite3_int64)sqlite3_current_time + unixEpoch;
+ *prNow = ((double)sqlite3_current_time + (double)43200) / (double)86400 + (double)2440587;
}
#endif
- UNUSED_PARAMETER(pVfs);
return 0;
}
/*
-** 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.
-*/
-int winCurrentTime(sqlite3_vfs *pVfs, double *prNow){
- int rc;
- sqlite3_int64 i;
- rc = winCurrentTimeInt64(pVfs, &i);
- if( !rc ){
- *prNow = i/86400000.0;
- }
- return rc;
-}
-
-/*
** 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
@@ -31847,39 +29205,36 @@ static int winGetLastError(sqlite3_vfs *pVfs, int nBuf, char *zBuf){
return getLastErrorMsg(nBuf, zBuf);
}
-
-
/*
** Initialize and deinitialize the operating system interface.
*/
SQLITE_API int sqlite3_os_init(void){
static sqlite3_vfs winVfs = {
- 2, /* 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 */
- 0, /* xRename */
- winCurrentTimeInt64, /* xCurrentTimeInt64 */
+ 1, /* 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 */
};
sqlite3_vfs_register(&winVfs, 1);
- return SQLITE_OK;
+ return SQLITE_OK;
}
-SQLITE_API int sqlite3_os_end(void){
+SQLITE_API int sqlite3_os_end(void){
return SQLITE_OK;
}
@@ -31906,8 +29261,8 @@ SQLITE_API int sqlite3_os_end(void){
** 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
+** 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.
@@ -31927,12 +29282,12 @@ SQLITE_API int sqlite3_os_end(void){
/* Size of the Bitvec structure in bytes. */
#define BITVEC_SZ (sizeof(void*)*128) /* 512 on 32bit. 1024 on 64bit */
-/* Round the union size down to the nearest pointer boundary, since that's how
+/* 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.
+/* 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
@@ -31945,12 +29300,12 @@ SQLITE_API int sqlite3_os_end(void){
/* Number of u32 values in hash table. */
#define BITVEC_NINT (BITVEC_USIZE/sizeof(u32))
-/* Maximum number of entries in hash table before
+/* 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
+** 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)
@@ -31996,7 +29351,7 @@ struct Bitvec {
/*
** Create a new bitmap object able to handle bits between 0 and iSize,
-** inclusive. Return a pointer to the new object. Return NULL if
+** inclusive. Return a pointer to the new object. Return NULL if
** malloc fails.
*/
SQLITE_PRIVATE Bitvec *sqlite3BitvecCreate(u32 iSize){
@@ -32250,7 +29605,7 @@ SQLITE_PRIVATE int sqlite3BitvecBuiltinTest(int sz, int *aOp){
break;
}
case 3:
- case 4:
+ case 4:
default: {
nx = 2;
sqlite3_randomness(sizeof(i), &i);
@@ -32435,7 +29790,7 @@ static void pcacheUnpin(PgHdr *p){
/*************************************************** General Interfaces ******
**
-** Initialize and shutdown the page cache subsystem. Neither of these
+** Initialize and shutdown the page cache subsystem. Neither of these
** functions are threadsafe.
*/
SQLITE_PRIVATE int sqlite3PcacheInitialize(void){
@@ -32457,8 +29812,8 @@ 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
+** 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(
@@ -32531,14 +29886,14 @@ SQLITE_PRIVATE int sqlite3PcacheFetch(
if( !pPage && eCreate==1 ){
PgHdr *pPg;
- /* Find a dirty page to write-out and recycle. First try to find a
+ /* 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
+ ** 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));
+ for(pPg=pCache->pSynced;
+ pPg && (pPg->nRef || (pPg->flags&PGHDR_NEED_SYNC));
pPg=pPg->pDirtyPrev
);
pCache->pSynced = pPg;
@@ -32676,7 +30031,7 @@ SQLITE_PRIVATE void sqlite3PcacheClearSyncFlags(PCache *pCache){
}
/*
-** Change the page number of page p to newPgno.
+** Change the page number of page p to newPgno.
*/
SQLITE_PRIVATE void sqlite3PcacheMove(PgHdr *p, Pgno newPgno){
PCache *pCache = p->pCache;
@@ -32705,12 +30060,7 @@ SQLITE_PRIVATE void sqlite3PcacheTruncate(PCache *pCache, Pgno pgno){
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) ){
+ if( p->pgno>pgno ){
assert( p->flags&PGHDR_DIRTY );
sqlite3PcacheMakeClean(p);
}
@@ -32732,7 +30082,7 @@ SQLITE_PRIVATE void sqlite3PcacheClose(PCache *pCache){
}
}
-/*
+/*
** Discard the contents of the cache.
*/
SQLITE_PRIVATE void sqlite3PcacheClear(PCache *pCache){
@@ -32820,7 +30170,7 @@ SQLITE_PRIVATE PgHdr *sqlite3PcacheDirtyList(PCache *pCache){
return pcacheSortDirtyList(pCache->pDirty);
}
-/*
+/*
** Return the total number of referenced pages held by the cache.
*/
SQLITE_PRIVATE int sqlite3PcacheRefCount(PCache *pCache){
@@ -32834,7 +30184,7 @@ SQLITE_PRIVATE int sqlite3PcachePageRefcount(PgHdr *p){
return p->nRef;
}
-/*
+/*
** Return the total number of pages in the cache.
*/
SQLITE_PRIVATE int sqlite3PcachePagecount(PCache *pCache){
@@ -32904,12 +30254,12 @@ typedef struct PCache1 PCache1;
typedef struct PgHdr1 PgHdr1;
typedef struct PgFreeslot PgFreeslot;
-/* Pointers to structures of this type are cast and returned as
+/* 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
+ ** flag (bPurgeable) are set when the cache is created. nMax may be
** modified at any time by a call to the pcache1CacheSize() method.
** The global mutex must be held when accessing nMax.
*/
@@ -32919,7 +30269,7 @@ struct PCache1 {
unsigned int nMax; /* Configured "cache_size" value */
/* Hash table of all pages. The following variables may only be accessed
- ** when the accessor is holding the global mutex (see pcache1EnterMutex()
+ ** when the accessor is holding the global mutex (see pcache1EnterMutex()
** and pcache1LeaveMutex()).
*/
unsigned int nRecyclable; /* Number of pages in the LRU list */
@@ -32931,9 +30281,9 @@ struct PCache1 {
};
/*
-** Each cache entry is represented by an instance of the following
-** structure. A buffer of PgHdr1.pCache->szPage bytes is allocated
-** directly before this structure in memory (see the PGHDR1_TO_PAGE()
+** Each cache entry is represented by an instance of the following
+** structure. A buffer of PgHdr1.pCache->szPage bytes is allocated
+** directly before this structure in memory (see the PGHDR1_TO_PAGE()
** macro below).
*/
struct PgHdr1 {
@@ -33002,7 +30352,7 @@ static SQLITE_WSD struct PCacheGlobal {
/******** Page Allocation/SQLITE_CONFIG_PCACHE Related Functions **************/
/*
-** This function is called during initialization if a static buffer is
+** 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.
@@ -33026,8 +30376,8 @@ SQLITE_PRIVATE void sqlite3PCacheBufferSetup(void *pBuf, int sz, int n){
/*
** 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
+** 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().
*/
static void *pcache1Alloc(int nByte){
@@ -33042,8 +30392,8 @@ static void *pcache1Alloc(int nByte){
}else{
/* Allocate a new buffer using sqlite3Malloc. Before doing so, exit the
- ** global pcache mutex and unlock the pager-cache object pCache. This is
- ** so that if the attempt to allocate a new buffer causes the the
+ ** global pcache mutex and unlock the pager-cache object pCache. This is
+ ** so that if the attempt to allocate a new buffer causes the the
** configured soft-heap-limit to be breached, it will be possible to
** reclaim memory from this pager-cache.
*/
@@ -33054,7 +30404,6 @@ static void *pcache1Alloc(int nByte){
int sz = sqlite3MallocSize(p);
sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_OVERFLOW, sz);
}
- sqlite3MemdebugSetType(p, MEMTYPE_PCACHE);
}
return p;
}
@@ -33072,10 +30421,7 @@ static void pcache1Free(void *p){
pSlot->pNext = pcache1.pFree;
pcache1.pFree = pSlot;
}else{
- int iSize;
- assert( sqlite3MemdebugHasType(p, MEMTYPE_PCACHE) );
- sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
- iSize = sqlite3MallocSize(p);
+ int iSize = sqlite3MallocSize(p);
sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_OVERFLOW, -iSize);
sqlite3_free(p);
}
@@ -33184,7 +30530,7 @@ static int pcache1ResizeHash(PCache1 *p){
}
/*
-** This function is used internally to remove the page pPage from the
+** This function is used internally to remove the page pPage from the
** global LRU list, if is part of it. If pPage is not part of the global
** LRU list, then this function is a no-op.
**
@@ -33213,7 +30559,7 @@ static void pcache1PinPage(PgHdr1 *pPage){
/*
-** Remove the page supplied as an argument from the hash table
+** Remove the page supplied as an argument from the hash table
** (PCache1.apHash structure) that it is currently stored in.
**
** The global mutex must be held when this function is called.
@@ -33245,21 +30591,21 @@ static void pcache1EnforceMaxPage(void){
}
/*
-** Discard all pages from cache pCache with a page number (key value)
-** greater than or equal to iLimit. Any pinned pages that meet this
+** 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 global mutex must be held when this function is called.
*/
static void pcache1TruncateUnsafe(
- PCache1 *pCache,
- unsigned int iLimit
+ PCache1 *pCache,
+ unsigned int iLimit
){
TESTONLY( unsigned int nPage = 0; ) /* Used to assert pCache->nPage is correct */
unsigned int h;
assert( sqlite3_mutex_held(pcache1.mutex) );
for(h=0; h<pCache->nHash; h++){
- PgHdr1 **pp = &pCache->apHash[h];
+ PgHdr1 **pp = &pCache->apHash[h];
PgHdr1 *pPage;
while( (pPage = *pp)!=0 ){
if( pPage->iKey>=iLimit ){
@@ -33295,7 +30641,7 @@ static int pcache1Init(void *NotUsed){
/*
** Implementation of the sqlite3_pcache.xShutdown method.
-** Note that the static mutex allocated in xInit does
+** Note that the static mutex allocated in xInit does
** not need to be freed.
*/
static void pcache1Shutdown(void *NotUsed){
@@ -33328,7 +30674,7 @@ static sqlite3_pcache *pcache1Create(int szPage, int bPurgeable){
}
/*
-** Implementation of the sqlite3_pcache.xCachesize method.
+** Implementation of the sqlite3_pcache.xCachesize method.
**
** Configure the cache_size limit for a cache.
*/
@@ -33344,7 +30690,7 @@ static void pcache1Cachesize(sqlite3_pcache *p, int nMax){
}
/*
-** Implementation of the sqlite3_pcache.xPagecount method.
+** Implementation of the sqlite3_pcache.xPagecount method.
*/
static int pcache1Pagecount(sqlite3_pcache *p){
int n;
@@ -33355,13 +30701,13 @@ static int pcache1Pagecount(sqlite3_pcache *p){
}
/*
-** Implementation of the sqlite3_pcache.xFetch method.
+** 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
+** 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
@@ -33372,7 +30718,7 @@ static int pcache1Pagecount(sqlite3_pcache *p){
** 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
+** 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
@@ -33384,13 +30730,13 @@ static int pcache1Pagecount(sqlite3_pcache *p){
** (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.
+** the sum of nMax for all purgeable caches, less the sum of
+** nMin for all other purgeable caches.
**
** 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
+** (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
@@ -33399,7 +30745,7 @@ static int pcache1Pagecount(sqlite3_pcache *p){
**
** 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.
+** proceed to step 5.
**
** 5. Otherwise, allocate and return a new page buffer.
*/
@@ -33451,8 +30797,8 @@ static void *pcache1Fetch(sqlite3_pcache *p, unsigned int iKey, int createFlag){
}
}
- /* Step 5. If a usable page buffer has still not been found,
- ** attempt to allocate a new one.
+ /* Step 5. If a usable page buffer has still not been found,
+ ** attempt to allocate a new one.
*/
if( !pPage ){
pPage = pcache1AllocPage(pCache);
@@ -33488,11 +30834,11 @@ fetch_out:
static void pcache1Unpin(sqlite3_pcache *p, void *pPg, int reuseUnlikely){
PCache1 *pCache = (PCache1 *)p;
PgHdr1 *pPage = PAGE_TO_PGHDR1(pCache, pPg);
-
+
assert( pPage->pCache==pCache );
pcache1EnterMutex();
- /* It is an error to call this function if the page is already
+ /* It is an error to call this function if the page is already
** part of the global LRU list.
*/
assert( pPage->pLruPrev==0 && pPage->pLruNext==0 );
@@ -33503,7 +30849,7 @@ static void pcache1Unpin(sqlite3_pcache *p, void *pPg, int reuseUnlikely){
pcache1FreePage(pPage);
}else{
/* Add the page to the global LRU list. Normally, the page is added to
- ** the head of the list (last page to be recycled). However, if the
+ ** the head of the list (last page to be recycled). However, if the
** reuseUnlikely flag passed to this function is true, the page is added
** to the tail of the list (first page to be recycled).
*/
@@ -33522,7 +30868,7 @@ static void pcache1Unpin(sqlite3_pcache *p, void *pPg, int reuseUnlikely){
}
/*
-** Implementation of the sqlite3_pcache.xRekey method.
+** Implementation of the sqlite3_pcache.xRekey method.
*/
static void pcache1Rekey(
sqlite3_pcache *p,
@@ -33533,7 +30879,7 @@ static void pcache1Rekey(
PCache1 *pCache = (PCache1 *)p;
PgHdr1 *pPage = PAGE_TO_PGHDR1(pCache, pPg);
PgHdr1 **pp;
- unsigned int h;
+ unsigned int h;
assert( pPage->iKey==iOld );
assert( pPage->pCache==pCache );
@@ -33558,7 +30904,7 @@ static void pcache1Rekey(
}
/*
-** Implementation of the sqlite3_pcache.xTruncate method.
+** 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
@@ -33575,7 +30921,7 @@ static void pcache1Truncate(sqlite3_pcache *p, unsigned int iLimit){
}
/*
-** Implementation of the sqlite3_pcache.xDestroy method.
+** Implementation of the sqlite3_pcache.xDestroy method.
**
** Destroy a cache allocated using pcache1Create().
*/
@@ -33620,7 +30966,7 @@ SQLITE_PRIVATE void sqlite3PCacheSetDefault(void){
** 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
+** been released, the function returns. The return value is the total number
** of bytes of memory released.
*/
SQLITE_PRIVATE int sqlite3PcacheReleaseMemory(int nReq){
@@ -33702,7 +31048,7 @@ SQLITE_PRIVATE void sqlite3PcacheStats(
** extracts the least value from the RowSet.
**
** The INSERT primitive might allocate additional memory. Memory is
-** allocated in chunks so most INSERTs do no allocation. There is an
+** 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.
**
@@ -33743,7 +31089,7 @@ SQLITE_PRIVATE void sqlite3PcacheStats(
/*
** Each entry in a RowSet is an instance of the following object.
*/
-struct RowSetEntry {
+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) */
@@ -33785,7 +31131,7 @@ struct RowSet {
**
** 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.
*/
@@ -33865,7 +31211,7 @@ SQLITE_PRIVATE void sqlite3RowSetInsert(RowSet *p, i64 rowid){
/*
** Merge two lists of RowSetEntry objects. Remove duplicates.
**
-** The input lists are connected via pRight pointers and are
+** The input lists are connected via pRight pointers and are
** assumed to each already be in sorted order.
*/
static struct RowSetEntry *rowSetMerge(
@@ -33903,7 +31249,7 @@ static struct RowSetEntry *rowSetMerge(
/*
** Sort all elements on the pEntry list of the RowSet into ascending order.
-*/
+*/
static void rowSetSort(RowSet *p){
unsigned int i;
struct RowSetEntry *pEntry;
@@ -34043,7 +31389,7 @@ static void rowSetToList(RowSet *p){
** 0 if the RowSet is already empty.
**
** After this routine has been called, the sqlite3RowSetInsert()
-** routine may not be called again.
+** routine may not be called again.
*/
SQLITE_PRIVATE int sqlite3RowSetNext(RowSet *p, i64 *pRowid){
rowSetToList(p);
@@ -34101,7 +31447,7 @@ SQLITE_PRIVATE int sqlite3RowSetTest(RowSet *pRowSet, u8 iBatch, sqlite3_int64 i
**
*************************************************************************
** 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
@@ -34110,195 +31456,6 @@ SQLITE_PRIVATE int sqlite3RowSetTest(RowSet *pRowSet, u8 iBatch, sqlite3_int64 i
** 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.
-*/
-
-#ifndef _WAL_H_
-#define _WAL_H_
-
-
-#ifdef SQLITE_OMIT_WAL
-# define sqlite3WalOpen(x,y,z) 0
-# define sqlite3WalClose(w,x,y,z) 0
-# define sqlite3WalOpenSnapshot(y,z) 0
-# define sqlite3WalCloseSnapshot(z)
-# define sqlite3WalRead(v,w,x,y,z) 0
-# define sqlite3WalDbsize(y,z)
-# define sqlite3WalWriteLock(y,z) 0
-# define sqlite3WalUndo(x,y,z) 0
-# define sqlite3WalSavepoint(z) 0
-# define sqlite3WalSavepointUndo(y,z) 0
-# define sqlite3WalFrames(u,v,w,x,y,z) 0
-# define sqlite3WalCheckpoint(u,v,w,x,y,z) 0
-# define sqlite3WalCallback(z) 0
-#else
-
-/* Connection to a write-ahead log (WAL) file.
-** There is one object of this type for each pager.
-*/
-typedef struct Wal Wal;
-
-/* Open and close a connection to a write-ahead log. */
-SQLITE_PRIVATE int sqlite3WalOpen(sqlite3_vfs*, sqlite3_file*, const char *zName, Wal**);
-SQLITE_PRIVATE int sqlite3WalClose(Wal *pWal, int sync_flags, int, u8 *);
-
-/* 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 sqlite3WalOpenSnapshot(Wal *pWal, int *);
-SQLITE_PRIVATE void sqlite3WalCloseSnapshot(Wal *pWal);
-
-/* Read a page from the write-ahead log, if it is present. */
-SQLITE_PRIVATE int sqlite3WalRead(Wal *pWal, Pgno pgno, int *pInWal, int nOut, u8 *pOut);
-
-/* Return the size of the database as it existed at the beginning
-** of the snapshot */
-SQLITE_PRIVATE void sqlite3WalDbsize(Wal *pWal, Pgno *pPgno);
-
-/* Obtain or release the WRITER lock. */
-SQLITE_PRIVATE int sqlite3WalWriteLock(Wal *pWal, int op);
-
-/* 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 u32 sqlite3WalSavepoint(Wal *pWal);
-
-/* 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 iFrame);
-
-/* 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 sync_flags, /* Flags to sync db file with (or 0) */
- int nBuf, /* Size of buffer nBuf */
- u8 *zBuf, /* Temporary buffer to use */
- int (*xBusyHandler)(void *), /* Pointer to busy-handler function */
- void *pBusyHandlerArg /* Argument to pass to xBusyHandler */
-);
-
-/* 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);
-
-/* 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);
-
-#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 ************************
-**
-** 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 to 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 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.
-**
-** (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.
-*/
/*
** Macros for troubleshooting. Normally turned off
@@ -34313,7 +31470,7 @@ int sqlite3PagerTrace=1; /* True to enable tracing */
/*
** The following two macros are used within the PAGERTRACE() macros above
-** to print out file-descriptors.
+** to print out file-descriptors.
**
** PAGERID() takes a pointer to a Pager struct as its argument. The
** associated file-descriptor is returned. FILEHANDLEID() takes an sqlite3_file
@@ -34326,7 +31483,7 @@ int sqlite3PagerTrace=1; /* True to enable tracing */
** The page cache as a whole is always in one of the following
** states:
**
-** PAGER_UNLOCK The page cache is not currently reading or
+** PAGER_UNLOCK The page cache is not currently reading or
** writing the database file. There is no
** data held in memory. This is the initial
** state.
@@ -34352,7 +31509,7 @@ int sqlite3PagerTrace=1; /* True to enable tracing */
** after all dirty pages have been written to the
** database file and the file has been synced to
** disk. All that remains to do is to remove or
-** truncate the journal file and the transaction
+** truncate the journal file and the transaction
** will be committed.
**
** The page cache comes up in PAGER_UNLOCK. The first time a
@@ -34391,7 +31548,7 @@ int sqlite3PagerTrace=1; /* True to enable tracing */
#endif
/*
-** The maximum allowed sector size. 64KiB. If the xSectorsize() method
+** 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.
@@ -34406,7 +31563,7 @@ int sqlite3PagerTrace=1; /* True to enable tracing */
**
** 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
+** 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()).
@@ -34418,7 +31575,6 @@ struct PagerSavepoint {
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 */
- u32 iFrame; /* Last frame in WAL when savepoint opened */
};
/*
@@ -34452,18 +31608,18 @@ struct PagerSavepoint {
**
** 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.
+** 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
+** 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
+** 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
+** This mechanism means that when running in exclusive mode, a connection
** need only update the change-counter once, for the first transaction
** committed.
**
@@ -34477,16 +31633,15 @@ struct PagerSavepoint {
**
** journalStarted
**
-** This flag is set whenever the the main journal is opened and
-** initialized
+** This flag is set whenever the the main journal is synced.
**
-** The point of this flag is that it must be set after the
+** The point of this flag is that it must be set after the
** first journal header in a journal file has been synced to disk.
-** After this has happened, new pages appended to the database
+** After this has happened, new pages appended to the database
** do not need the PGHDR_NEED_SYNC flag set, as they do not need
** to wait for a journal sync before they can be written out to
** the database file (see function pager_write()).
-**
+**
** setMaster
**
** This variable is used to ensure that the master journal file name
@@ -34498,16 +31653,13 @@ struct PagerSavepoint {
** then attempts to upgrade to an exclusive lock. If this attempt
** fails, then SQLITE_BUSY may be returned to the user and the user
** may attempt to commit the transaction again later (calling
-** CommitPhaseOne() again). This flag is used to ensure that the
+** CommitPhaseOne() again). This flag is used to ensure that the
** master journal name is only written to the journal file the first
** time CommitPhaseOne() is called.
**
** doNotSync
**
-** When enabled, cache spills are prohibited and the journal file cannot
-** be synced. This variable is set and cleared by sqlite3PagerWrite()
-** in order to prevent a journal sync from happening in between the
-** journalling of two pages on the same sector.
+** This variable is set and cleared by sqlite3PagerWrite().
**
** needSync
**
@@ -34537,12 +31689,12 @@ struct Pager {
/* The following block contains those class members that are dynamically
** modified during normal operations. The other variables in this structure
** are either constant throughout the lifetime of the pager, or else
- ** used to store configuration parameters that affect the way the pager
+ ** used to store configuration parameters that affect the way the pager
** operates.
**
** The 'state' variable is described in more detail along with the
** descriptions of the values it may take - PAGER_UNLOCK etc. Many of the
- ** other variables in this block are described in the comment directly
+ ** other variables in this block are described in the comment directly
** above this class definition.
*/
u8 state; /* PAGER_UNLOCK, _SHARED, _RESERVED, etc. */
@@ -34567,7 +31719,6 @@ struct Pager {
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 */
- i64 journalSizeLimit; /* Size limit for persistent journal files */
PagerSavepoint *aSavepoint; /* Array of active savepoints */
int nSavepoint; /* Number of elements in aSavepoint[] */
char dbFileVers[16]; /* Changes whenever database file changes */
@@ -34594,11 +31745,9 @@ struct Pager {
void *pCodec; /* First argument to xCodec... methods */
#endif
char *pTmpSpace; /* Pager.pageSize bytes of space for tmp use */
+ i64 journalSizeLimit; /* Size limit for persistent journal files */
PCache *pPCache; /* Pointer to page cache object */
sqlite3_backup *pBackup; /* Pointer to list of ongoing backup processes */
-#ifndef SQLITE_OMIT_WAL
- Wal *pWal; /* Write-ahead log used by "journal_mode=wal" */
-#endif
};
/*
@@ -34651,7 +31800,7 @@ static const unsigned char aJournalMagic[] = {
#define JOURNAL_PG_SZ(pPager) ((pPager->pageSize) + 8)
/*
-** The journal header size for this pager. This is usually the same
+** 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)
@@ -34673,7 +31822,7 @@ static const unsigned char aJournalMagic[] = {
*/
#define PAGER_MAX_PGNO 2147483647
-#ifndef NDEBUG
+#ifndef NDEBUG
/*
** Usage:
**
@@ -34860,8 +32009,8 @@ static void checkPage(PgHdr *pPg){
/*
** 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
+** 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.
**
@@ -34877,7 +32026,7 @@ static void checkPage(PgHdr *pPg){
** nul-terminator byte is appended to the buffer following the master
** journal file name.
**
-** If it is determined that no master journal file name is present
+** If it is determined that no master journal file name is present
** zMaster[0] is set to 0 and SQLITE_OK returned.
**
** If an error occurs while reading from the journal file, an SQLite
@@ -34895,7 +32044,7 @@ static int readMasterJournal(sqlite3_file *pJrnl, char *zMaster, u32 nMaster){
if( SQLITE_OK!=(rc = sqlite3OsFileSize(pJrnl, &szJ))
|| szJ<16
|| SQLITE_OK!=(rc = read32bits(pJrnl, szJ-16, &len))
- || len>=nMaster
+ || len>=nMaster
|| SQLITE_OK!=(rc = read32bits(pJrnl, szJ-12, &cksum))
|| SQLITE_OK!=(rc = sqlite3OsRead(pJrnl, aMagic, 8, szJ-8))
|| memcmp(aMagic, aJournalMagic, 8)
@@ -34917,13 +32066,13 @@ static int readMasterJournal(sqlite3_file *pJrnl, char *zMaster, u32 nMaster){
len = 0;
}
zMaster[len] = '\0';
-
+
return SQLITE_OK;
}
/*
-** Return the offset of the sector boundary at or immediately
-** following the value in pPager->journalOff, assuming a sector
+** 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:
@@ -34934,7 +32083,7 @@ static int readMasterJournal(sqlite3_file *pJrnl, char *zMaster, u32 nMaster){
** 512 512
** 100 512
** 2000 2048
-**
+**
*/
static i64 journalHdrOffset(Pager *pPager){
i64 offset = 0;
@@ -34956,12 +32105,12 @@ static i64 journalHdrOffset(Pager *pPager){
**
** 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
+** 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
+** 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.
@@ -34986,8 +32135,8 @@ static int zeroJournalHdr(Pager *pPager, int doTruncate){
rc = sqlite3OsSync(pPager->jfd, SQLITE_SYNC_DATAONLY|pPager->sync_flags);
}
- /* 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
+ /* 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.
@@ -35015,7 +32164,7 @@ static int zeroJournalHdr(Pager *pPager, int doTruncate){
** - 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.
*/
static int writeJournalHdr(Pager *pPager){
@@ -35031,8 +32180,8 @@ static int writeJournalHdr(Pager *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
+ /* 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++){
@@ -35043,10 +32192,10 @@ static int writeJournalHdr(Pager *pPager){
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,
+ ** 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()).
**
@@ -35065,7 +32214,7 @@ static int writeJournalHdr(Pager *pPager){
*/
assert( isOpen(pPager->fd) || pPager->noSync );
if( (pPager->noSync) || (pPager->journalMode==PAGER_JOURNALMODE_MEMORY)
- || (sqlite3OsDeviceCharacteristics(pPager->fd)&SQLITE_IOCAP_SAFE_APPEND)
+ || (sqlite3OsDeviceCharacteristics(pPager->fd)&SQLITE_IOCAP_SAFE_APPEND)
){
memcpy(zHeader, aJournalMagic, sizeof(aJournalMagic));
put32bits(&zHeader[sizeof(aJournalMagic)], 0xffffffff);
@@ -35073,7 +32222,7 @@ static int writeJournalHdr(Pager *pPager){
memset(zHeader, 0, sizeof(aJournalMagic)+4);
}
- /* The random check-hash initialiser */
+ /* The random check-hash initialiser */
sqlite3_randomness(sizeof(pPager->cksumInit), &pPager->cksumInit);
put32bits(&zHeader[sizeof(aJournalMagic)+4], pPager->cksumInit);
/* The initial database size */
@@ -35092,27 +32241,26 @@ static int writeJournalHdr(Pager *pPager){
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
+ /* 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
+ ** 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
+ ** 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.
+ ** is done.
**
- ** The loop is required here in case the sector-size is larger than the
+ ** 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;
}
@@ -35199,23 +32347,23 @@ static int readJournalHdr(
/* 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
+ ** 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
+ || ((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
+ /* 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
+ /* 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.
*/
iPageSize16 = (u16)iPageSize;
@@ -35223,7 +32371,7 @@ static int readJournalHdr(
testcase( rc!=SQLITE_OK );
assert( rc!=SQLITE_OK || iPageSize16==(u16)iPageSize );
- /* Update the assumed sector-size to match the value used by
+ /* 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
@@ -35253,7 +32401,7 @@ static int readJournalHdr(
** 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),
+** 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){
@@ -35264,14 +32412,13 @@ static int writeMasterJournal(Pager *pPager, const char *zMaster){
u32 cksum = 0; /* Checksum of string zMaster */
if( !zMaster || pPager->setMaster
- || pPager->journalMode==PAGER_JOURNALMODE_MEMORY
- || pPager->journalMode==PAGER_JOURNALMODE_OFF
+ || 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 );
/* Calculate the length in bytes and the checksum of zMaster */
for(nMaster=0; zMaster[nMaster]; nMaster++){
@@ -35301,16 +32448,16 @@ static int writeMasterJournal(Pager *pPager, const char *zMaster){
pPager->journalOff += (nMaster+20);
pPager->needSync = !pPager->noSync;
- /* If the pager is in peristent-journal mode, then the physical
+ /* 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
+ ** 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.
+ ** 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
+ ** 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
){
@@ -35321,7 +32468,7 @@ static int writeMasterJournal(Pager *pPager, const char *zMaster){
/*
** 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
+** a pointer to the page or NULL if the requested page is not
** already in memory.
*/
static PgHdr *pager_lookup(Pager *pPager, Pgno pgno){
@@ -35368,7 +32515,7 @@ static void releaseAllSavepoints(Pager *pPager){
}
/*
-** Set the bit number pgno in the PagerSavepoint.pInSavepoint
+** 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.
*/
@@ -35388,26 +32535,10 @@ static int addToSavepointBitvecs(Pager *pPager, Pgno pgno){
}
/*
-** 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,z) 0
-# define pagerOpenWalIfPresent(z) SQLITE_OK
-# define pagerOpenSnapshot(z) SQLITE_OK
-#endif
-
-/*
** Unlock the database file. This function is a no-op if the pager
** is in exclusive mode.
**
-** If the pager is currently in error state, discard the contents of
+** If the pager is currently in error state, discard the contents of
** the cache and reset the Pager structure internal state. If there is
** an open journal-file, then the next time a shared-lock is obtained
** on the pager file (by this or any other process), it will be
@@ -35415,7 +32546,7 @@ static int pagerUseWal(Pager *pPager){
*/
static void pager_unlock(Pager *pPager){
if( !pPager->exclusiveMode ){
- int rc = SQLITE_OK; /* Return code */
+ int rc; /* Return code */
/* Always close the journal file when dropping the database lock.
** Otherwise, another connection with journal_mode=delete might
@@ -35428,17 +32559,12 @@ static void pager_unlock(Pager *pPager){
/* If the file is unlocked, somebody else might change it. The
** values stored in Pager.dbSize etc. might become invalid if
- ** this happens. One can argue that this doesn't need to be cleared
+ ** this happens. TODO: Really, this doesn't need to be cleared
** until the change-counter check fails in PagerSharedLock().
- ** Clearing the page size cache here is being conservative.
*/
pPager->dbSizeValid = 0;
- if( pagerUseWal(pPager) ){
- sqlite3WalCloseSnapshot(pPager->pWal);
- }else{
- rc = osUnlock(pPager->fd, NO_LOCK);
- }
+ rc = osUnlock(pPager->fd, NO_LOCK);
if( rc ){
pPager->errCode = rc;
}
@@ -35463,18 +32589,18 @@ static void pager_unlock(Pager *pPager){
/*
** This function should be called when an IOERR, CORRUPT or FULL error
-** may have 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.
+** may have 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_IOERR, SQLITE_CORRUPT, or SQLITE_FULL
** the error becomes persistent. Until the persisten error is cleared,
-** subsequent API calls on this Pager will immediately return the same
+** subsequent API calls on this Pager will immediately return the same
** error code.
**
-** A persistent error indicates that the contents of the pager-cache
-** cannot be trusted. This state can be cleared by completely discarding
+** A persistent error 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
@@ -35495,10 +32621,10 @@ static int pager_error(Pager *pPager, int rc){
}
/*
-** Execute a rollback if a transaction is active and unlock the
-** database file.
+** 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
+** 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 clear the error state. If this means that
@@ -35507,7 +32633,7 @@ static int pager_error(Pager *pPager, int rc){
** 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
+** 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.
*/
@@ -35521,26 +32647,26 @@ static void pagerUnlockAndRollback(Pager *pPager){
}
/*
-** This routine ends a transaction. A transaction is usually ended by
-** either a COMMIT or a ROLLBACK operation. This routine may be called
+** 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.
-**
+**
** If the pager is in PAGER_SHARED or PAGER_UNLOCK state when this
** routine is called, it is a no-op (returns SQLITE_OK).
**
** 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
+** 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
+** Journal file descriptor is simply closed. This destroys an
** in-memory journal.
**
** journalMode==TRUNCATE
@@ -35569,7 +32695,7 @@ static void pagerUnlockAndRollback(Pager *pPager){
**
** 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
+** 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
@@ -35587,7 +32713,6 @@ static int pager_end_transaction(Pager *pPager, int hasMaster){
assert( isOpen(pPager->jfd) || pPager->pInJournal==0 );
if( isOpen(pPager->jfd) ){
- assert( !pagerUseWal(pPager) );
/* Finalize the journal file. */
if( sqlite3IsMemJournal(pPager->jfd) ){
@@ -35601,8 +32726,8 @@ static int pager_end_transaction(Pager *pPager, int hasMaster){
}
pPager->journalOff = 0;
pPager->journalStarted = 0;
- }else if( pPager->journalMode==PAGER_JOURNALMODE_PERSIST
- || (pPager->exclusiveMode && pPager->journalMode!=PAGER_JOURNALMODE_WAL)
+ }else if( pPager->exclusiveMode
+ || pPager->journalMode==PAGER_JOURNALMODE_PERSIST
){
rc = zeroJournalHdr(pPager, hasMaster);
pager_error(pPager, rc);
@@ -35612,11 +32737,9 @@ static int pager_end_transaction(Pager *pPager, int hasMaster){
/* 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.
- */
- assert( pPager->journalMode==PAGER_JOURNALMODE_DELETE
- || pPager->journalMode==PAGER_JOURNALMODE_MEMORY
- || pPager->journalMode==PAGER_JOURNALMODE_WAL
+ ** the database file, it will do so using an in-memory journal. */
+ assert( pPager->journalMode==PAGER_JOURNALMODE_DELETE
+ || pPager->journalMode==PAGER_JOURNALMODE_MEMORY
);
sqlite3OsClose(pPager->jfd);
if( !pPager->tempFile ){
@@ -35627,27 +32750,14 @@ static int pager_end_transaction(Pager *pPager, int hasMaster){
#ifdef SQLITE_CHECK_PAGES
sqlite3PcacheIterateDirty(pPager->pPCache, pager_set_pagehash);
#endif
- }
- sqlite3BitvecDestroy(pPager->pInJournal);
- pPager->pInJournal = 0;
- pPager->nRec = 0;
- sqlite3PcacheCleanAll(pPager->pPCache);
- if( pagerUseWal(pPager) ){
- rc2 = sqlite3WalWriteLock(pPager->pWal, 0);
- pPager->state = PAGER_SHARED;
+ sqlite3PcacheCleanAll(pPager->pPCache);
+ sqlite3BitvecDestroy(pPager->pInJournal);
+ pPager->pInJournal = 0;
+ pPager->nRec = 0;
+ }
- /* If the connection was in locking_mode=exclusive mode but is no longer,
- ** drop the EXCLUSIVE lock held on the database file.
- */
- if( rc2==SQLITE_OK
- && !pPager->exclusiveMode
- && sqlite3WalExclusiveMode(pPager->pWal, -1)
- ){
- sqlite3WalExclusiveMode(pPager->pWal, 0);
- rc2 = osUnlock(pPager->fd, SHARED_LOCK);
- }
- }else if( !pPager->exclusiveMode ){
+ if( !pPager->exclusiveMode ){
rc2 = osUnlock(pPager->fd, SHARED_LOCK);
pPager->state = PAGER_SHARED;
pPager->changeCountDone = 0;
@@ -35658,7 +32768,7 @@ static int pager_end_transaction(Pager *pPager, int hasMaster){
pPager->needSync = 0;
pPager->dbModified = 0;
- /* TODO: Is this optimal? Why is the db size invalidated here
+ /* TODO: Is this optimal? Why is the db size invalidated here
** when the database file is not unlocked? */
pPager->dbOrigSize = 0;
sqlite3PcacheTruncate(pPager->pPCache, pPager->dbSize);
@@ -35671,10 +32781,10 @@ static int pager_end_transaction(Pager *pPager, int hasMaster){
/*
** Parameter aData must point to a buffer of pPager->pageSize bytes
-** of data. Compute and return a checksum based ont the contents of the
+** 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
+** 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.
@@ -35682,8 +32792,8 @@ static int pager_end_transaction(Pager *pPager, int hasMaster){
** 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.
+** 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.
@@ -35725,7 +32835,7 @@ static u32 pager_cksum(Pager *pPager, const u8 *aData){
** 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.
@@ -35738,10 +32848,11 @@ static u32 pager_cksum(Pager *pPager, const u8 *aData){
*/
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 isUnsync, /* True if reading from unsynced main journal */
+ i64 *pOffset, /* Offset of record to playback */
+ int isSavepnt, /* True for a savepoint rollback */
+ Bitvec *pDone /* Bitvec of pages already played back */
){
int rc;
PgHdr *pPg; /* An existing page in the cache */
@@ -35749,7 +32860,6 @@ static int pager_playback_one_page(
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 */
@@ -35758,7 +32868,6 @@ static int pager_playback_one_page(
aData = pPager->pTmpSpace;
assert( aData ); /* Temp storage must have already been allocated */
- assert( pagerUseWal(pPager)==0 || (!isMainJrnl && isSavepnt) );
/* 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.
@@ -35828,28 +32937,18 @@ static int pager_playback_one_page(
** 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);
- }
+ pPg = pager_lookup(pPager, pgno);
assert( pPg || !MEMDB );
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( (pPager->state>=PAGER_EXCLUSIVE)
+ && (pPg==0 || 0==(pPg->flags&PGHDR_NEED_SYNC))
&& isOpen(pPager->fd)
- && isSynced
+ && !isUnsync
){
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;
@@ -35862,18 +32961,18 @@ static int pager_playback_one_page(
}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.
+ ** 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
+ ** 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
+ ** 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 );
@@ -35895,14 +32994,13 @@ static int pager_playback_one_page(
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
+ /* 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.
+ ** as clean, since there will be no need to write it out to the.
**
** There is one exception to this rule. If the page is being rolled
- ** back as part of a savepoint (or statement) rollback from an
+ ** 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
@@ -35914,7 +33012,6 @@ static int pager_playback_one_page(
** segment is synced. If a crash occurs during or following this,
** database corruption may ensue.
*/
- assert( !pagerUseWal(pPager) );
sqlite3PcacheMakeClean(pPg);
}
#ifdef SQLITE_CHECK_PAGES
@@ -35939,26 +33036,26 @@ static int pager_playback_one_page(
** 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
+** 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
+** 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
+** 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
+** 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
+** * 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
@@ -35968,12 +33065,12 @@ static int pager_playback_one_page(
**
** 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
+** 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
+** a couple of kilobytes or so - potentially larger than the page
** size.
*/
static int pager_delmaster(Pager *pPager, const char *zMaster){
@@ -36006,7 +33103,7 @@ static int pager_delmaster(Pager *pPager, const char *zMaster){
int nMasterPtr = pVfs->mxPathname+1;
/* Load the entire master journal file into space obtained from
- ** sqlite3_malloc() and pointed to by zMasterJournal.
+ ** sqlite3_malloc() and pointed to by zMasterJournal.
*/
zMasterJournal = sqlite3Malloc((int)nMasterJournal + nMasterPtr + 1);
if( !zMasterJournal ){
@@ -36052,13 +33149,13 @@ static int pager_delmaster(Pager *pPager, const char *zMaster){
zJournal += (sqlite3Strlen30(zJournal)+1);
}
}
-
+
rc = sqlite3OsDelete(pVfs, zMaster, 0);
delmaster_out:
if( zMasterJournal ){
sqlite3_free(zMasterJournal);
- }
+ }
if( pMaster ){
sqlite3OsClose(pMaster);
assert( !isOpen(pJournal) );
@@ -36069,7 +33166,7 @@ delmaster_out:
/*
-** This function is used to change the actual size of the database
+** 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).
**
@@ -36079,10 +33176,10 @@ delmaster_out:
** on disk is currently larger than nPage pages, then use the VFS
** xTruncate() method to truncate it.
**
-** 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
+** 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 successful, return SQLITE_OK. If an IO error occurs while modifying
@@ -36112,8 +33209,8 @@ static int pager_truncate(Pager *pPager, Pgno nPage){
/*
** 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
+** 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.
@@ -36144,15 +33241,15 @@ static void setSectorSize(Pager *pPager){
/*
** Playback the journal and thus restore the database file to
-** the state it was in before we started making changes.
+** the state it was in before we started making changes.
**
-** The journal file format is as follows:
+** 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
+** (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.
@@ -36181,7 +33278,7 @@ static void setSectorSize(Pager *pPager){
** 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.
+** 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
@@ -36193,7 +33290,7 @@ static void setSectorSize(Pager *pPager){
** 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
+** 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
@@ -36242,18 +33339,20 @@ static int pager_playback(Pager *pPager, int isHot){
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.
+ /* This loop terminates either when a readJournalHdr() or
+ ** pager_playback_one_page() call returns SQLITE_DONE or an IO error
+ ** occurs.
*/
while( 1 ){
+ int isUnsync = 0;
+
/* 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 of 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_OK ){
if( rc==SQLITE_DONE ){
rc = SQLITE_OK;
}
@@ -36281,12 +33380,13 @@ static int pager_playback(Pager *pPager, int isHot){
** 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
+ ** 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));
+ isUnsync = 1;
}
/* If this is the first header read from the journal, truncate the
@@ -36300,7 +33400,7 @@ static int pager_playback(Pager *pPager, int isHot){
pPager->dbSize = mxPg;
}
- /* Copy original pages out of the journal and back into the
+ /* Copy original pages out of the journal and back into the
** database file and/or page cache.
*/
for(u=0; u<nRec; u++){
@@ -36308,20 +33408,12 @@ static int pager_playback(Pager *pPager, int isHot){
pager_reset(pPager);
needPagerReset = 0;
}
- rc = pager_playback_one_page(pPager,&pPager->journalOff,0,1,0);
+ rc = pager_playback_one_page(pPager,1,isUnsync,&pPager->journalOff,0,0);
if( rc!=SQLITE_OK ){
if( rc==SQLITE_DONE ){
rc = SQLITE_OK;
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
@@ -36347,10 +33439,10 @@ end_playback:
sqlite3OsFileControl(pPager->fd,SQLITE_FCNTL_DB_UNCHANGED,0)>=SQLITE_OK
);
- /* 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
+ /* 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
@@ -36366,9 +33458,6 @@ end_playback:
if( rc==SQLITE_OK && pPager->noSync==0 && pPager->state>=PAGER_EXCLUSIVE ){
rc = sqlite3OsSync(pPager->fd, pPager->sync_flags);
}
- if( rc==SQLITE_OK && pPager->noSync==0 && pPager->state>=PAGER_EXCLUSIVE ){
- rc = sqlite3OsSync(pPager->fd, pPager->sync_flags);
- }
if( rc==SQLITE_OK ){
rc = pager_end_transaction(pPager, zMaster[0]!='\0');
testcase( rc!=SQLITE_OK );
@@ -36389,273 +33478,23 @@ end_playback:
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.
-**
-** If page 1 is read, then the value of Pager.dbFileVers[] is set to
-** the value read from the database file.
-**
-** If an IO error occurs, then the IO error is returned to the caller.
-** Otherwise, SQLITE_OK is returned.
-*/
-static int readDbPage(PgHdr *pPg){
- 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 isInWal = 0; /* True if page is in log file */
- int pgsz = pPager->pageSize; /* Number of bytes to read */
-
- assert( pPager->state>=PAGER_SHARED && !MEMDB );
- assert( isOpen(pPager->fd) );
-
- if( NEVER(!isOpen(pPager->fd)) ){
- assert( pPager->tempFile );
- memset(pPg->pData, 0, pPager->pageSize);
- return SQLITE_OK;
- }
-
- if( pagerUseWal(pPager) ){
- /* Try to pull the page from the write-ahead log. */
- rc = sqlite3WalRead(pPager->pWal, pgno, &isInWal, pgsz, pPg->pData);
- }
- if( rc==SQLITE_OK && !isInWal ){
- i64 iOffset = (pgno-1)*(i64)pPager->pageSize;
- rc = sqlite3OsRead(pPager->fd, pPg->pData, pgsz, iOffset);
- if( rc==SQLITE_IOERR_SHORT_READ ){
- rc = SQLITE_OK;
- }
- }
-
- 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. 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);
-
- 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)));
-
- return rc;
-}
-
-#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.
-*/
-static int pagerUndoCallback(void *pCtx, Pgno iPg){
- int rc = SQLITE_OK;
- Pager *pPager = (Pager *)pCtx;
- PgHdr *pPg;
-
- pPg = sqlite3PagerLookup(pPager, iPg);
- if( pPg ){
- if( sqlite3PcachePageRefcount(pPg)==1 ){
- sqlite3PcacheDrop(pPg);
- }else{
- rc = readDbPage(pPg);
- 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.
- */
- sqlite3BackupRestart(pPager->pBackup);
-
- return rc;
-}
-
-/*
-** This function is called to rollback a transaction on a WAL database.
-*/
-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;
- }
-
- return rc;
-}
-
-/*
-** 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.
-*/
-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 sync_flags /* Flags to pass to OsSync() (or 0) */
-){
- int rc; /* Return code */
-
- assert( pPager->pWal );
- rc = sqlite3WalFrames(pPager->pWal,
- pPager->pageSize, pList, nTruncate, isCommit, sync_flags
- );
- if( rc==SQLITE_OK && pPager->pBackup ){
- PgHdr *p;
- for(p=pList; p; p=p->pDirty){
- sqlite3BackupUpdate(pPager->pBackup, p->pgno, (u8 *)p->pData);
- }
- }
- return rc;
-}
-
-/*
-** Open a WAL snapshot on the log file this pager is connected to.
-*/
-static int pagerOpenSnapshot(Pager *pPager){
- int rc; /* Return code */
- int changed = 0; /* True if cache must be reset */
-
- assert( pagerUseWal(pPager) );
-
- rc = sqlite3WalOpenSnapshot(pPager->pWal, &changed);
- if( rc==SQLITE_OK ){
- int dummy;
- if( changed ){
- pager_reset(pPager);
- assert( pPager->errCode || pPager->dbSizeValid==0 );
- }
- rc = sqlite3PagerPagecount(pPager, &dummy);
- }
- pPager->state = PAGER_SHARED;
-
- return rc;
-}
-
-/*
-** Check if the *-wal file that corresponds to the database opened by pPager
-** exists. Assuming no error occurs, set *pExists to 1 if the file exists,
-** or 0 otherwise and return SQLITE_OK. If an IO or OOM error occurs, return
-** an SQLite error code.
-*/
-static int pagerHasWAL(Pager *pPager, int *pExists){
- int rc; /* Return code */
-
- if( !pPager->tempFile ){
- char *zWal = sqlite3_mprintf("%s-wal", pPager->zFilename);
- if( !zWal ){
- rc = SQLITE_NOMEM;
- }else{
- rc = sqlite3OsAccess(pPager->pVfs, zWal, SQLITE_ACCESS_EXISTS, pExists);
- sqlite3_free(zWal);
- }
- }else{
- rc = SQLITE_OK;
- *pExists = 0;
- }
- return rc;
-}
-
-/*
-** Check if the *-wal file that corresponds to the database opened by pPager
-** exists. If it does, open the pager in WAL mode. Otherwise, if no error
-** occurs, make sure Pager.journalMode is not set to PAGER_JOURNALMODE_WAL.
-** If an IO or OOM error occurs, return an SQLite error code.
-**
-** If the WAL file is opened, also open a snapshot (read transaction).
-**
-** 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, this ensures there is no race condition between the xAccess()
-** below and an xDelete() being executed by some other connection.
-*/
-static int pagerOpenWalIfPresent(Pager *pPager){
- int rc = SQLITE_OK;
- if( !pPager->tempFile ){
- int isWal; /* True if WAL file exists */
- rc = pagerHasWAL(pPager, &isWal);
- if( rc==SQLITE_OK ){
- if( isWal ){
- pager_reset(pPager);
- rc = sqlite3PagerOpenWal(pPager, 0);
- if( rc==SQLITE_OK ){
- rc = pagerOpenSnapshot(pPager);
- }
- }else if( pPager->journalMode==PAGER_JOURNALMODE_WAL ){
- pPager->journalMode = PAGER_JOURNALMODE_DELETE;
- }
- }
- }
- return rc;
-}
-#endif
-
/*
** 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
+** 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.
**
-** When pSavepoint is not NULL (meaning a non-transaction savepoint is
+** 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:
**
** * Pages are played back from the main journal starting at byte
-** offset PagerSavepoint.iOffset and continuing to
+** offset PagerSavepoint.iOffset and continuing to
** PagerSavepoint.iHdrOffset, or to the end of the main journal
** file if PagerSavepoint.iHdrOffset is zero.
**
** * If PagerSavepoint.iHdrOffset is not zero, then pages are played
-** back starting from the journal header immediately following
+** back starting from the journal header immediately following
** PagerSavepoint.iHdrOffset to the end of the main journal file.
**
** * Pages are then played back from the sub-journal file, starting
@@ -36671,7 +33510,7 @@ static int pagerOpenWalIfPresent(Pager *pPager){
** 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
+** 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.
*/
@@ -36691,22 +33530,17 @@ static int pagerPlaybackSavepoint(Pager *pPager, PagerSavepoint *pSavepoint){
}
}
- /* Set the database size back to the value it was before the savepoint
+ /* Set the database size back to the value it was before the savepoint
** being reverted was opened.
*/
pPager->dbSize = pSavepoint ? pSavepoint->nOrig : pPager->dbOrigSize;
- if( !pSavepoint && pagerUseWal(pPager) ){
- return pagerRollbackWal(pPager);
- }
-
/* 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 );
/* Begin by rolling back records from the main journal starting at
** PagerSavepoint.iOffset and continuing to the next journal header.
@@ -36715,11 +33549,11 @@ static int pagerPlaybackSavepoint(Pager *pPager, PagerSavepoint *pSavepoint){
** will be skipped automatically. Pages are added to pDone as they
** are played back.
*/
- if( pSavepoint && !pagerUseWal(pPager) ){
+ if( pSavepoint ){
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);
+ rc = pager_playback_one_page(pPager, 1, 0, &pPager->journalOff, 1, pDone);
}
assert( rc!=SQLITE_DONE );
}else{
@@ -36743,13 +33577,13 @@ static int pagerPlaybackSavepoint(Pager *pPager, PagerSavepoint *pSavepoint){
** test is related to ticket #2565. See the discussion in the
** pager_playback() function for additional information.
*/
- if( nJRec==0
+ 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);
+ rc = pager_playback_one_page(pPager, 1, 0, &pPager->journalOff, 1, pDone);
}
assert( rc!=SQLITE_DONE );
}
@@ -36762,13 +33596,9 @@ static int pagerPlaybackSavepoint(Pager *pPager, PagerSavepoint *pSavepoint){
if( pSavepoint ){
u32 ii; /* Loop counter */
i64 offset = pSavepoint->iSubRec*(4+pPager->pageSize);
-
- if( pagerUseWal(pPager) ){
- rc = sqlite3WalSavepointUndo(pPager->pWal, pSavepoint->iFrame);
- }
for(ii=pSavepoint->iSubRec; rc==SQLITE_OK && ii<pPager->nSubRec; ii++){
assert( offset==ii*(4+pPager->pageSize) );
- rc = pager_playback_one_page(pPager, &offset, pDone, 0, 1);
+ rc = pager_playback_one_page(pPager, 0, 0, &offset, 1, pDone);
}
assert( rc!=SQLITE_DONE );
}
@@ -36777,7 +33607,6 @@ static int pagerPlaybackSavepoint(Pager *pPager, PagerSavepoint *pSavepoint){
if( rc==SQLITE_OK ){
pPager->journalOff = szJ;
}
-
return rc;
}
@@ -36826,7 +33655,7 @@ SQLITE_PRIVATE void sqlite3PagerSetSafetyLevel(Pager *pPager, int level, int bFu
/*
** The following global variable is incremented whenever the library
** attempts to open a temporary file. This information is used for
-** testing and analysis only.
+** testing and analysis only.
*/
#ifdef SQLITE_TEST
SQLITE_API int sqlite3_opentemp_count = 0;
@@ -36835,8 +33664,8 @@ SQLITE_API int sqlite3_opentemp_count = 0;
/*
** 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
+** 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
@@ -36868,9 +33697,9 @@ static int pagerOpentemp(
/*
** Set the busy handler function.
**
-** The pager invokes the busy-handler if sqlite3OsLock() returns
+** 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
+** 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:
@@ -36882,7 +33711,7 @@ static int pagerOpentemp(
** SHARED_LOCK -> EXCLUSIVE_LOCK | No
** RESERVED_LOCK -> EXCLUSIVE_LOCK | Yes
**
-** If the busy-handler callback returns non-zero, the lock is
+** 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.
*/
@@ -36890,7 +33719,7 @@ 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;
}
@@ -36911,16 +33740,16 @@ static void pagerReportSize(Pager *pPager){
#endif
/*
-** Change the page size used by the Pager object. The new page size
+** Change the page size used by the Pager object. The new page size
** is passed in *pPageSize.
**
** 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.
+** is a no-op. The value returned is the error state error code (i.e.
** one of SQLITE_IOERR, SQLITE_CORRUPT or SQLITE_FULL).
**
** Otherwise, if all of the following are true:
**
-** * the new page size (value of *pPageSize) is valid (a power
+** * the new page size (value of *pPageSize) is valid (a power
** of two between 512 and SQLITE_MAX_PAGE_SIZE, inclusive), and
**
** * there are no outstanding page references, and
@@ -36930,14 +33759,14 @@ static void pagerReportSize(Pager *pPager){
**
** 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.
+** 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,
+** function was called, or because the memory allocation attempt failed,
** then *pPageSize is set to the old, retained page size before returning.
*/
SQLITE_PRIVATE int sqlite3PagerSetPagesize(Pager *pPager, u16 *pPageSize, int nReserve){
@@ -36947,8 +33776,8 @@ SQLITE_PRIVATE int sqlite3PagerSetPagesize(Pager *pPager, u16 *pPageSize, int nR
u16 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!=pPager->pageSize
+ && sqlite3PcacheRefCount(pPager->pPCache)==0
+ && pageSize && pageSize!=pPager->pageSize
){
char *pNew = (char *)sqlite3PageMalloc(pageSize);
if( !pNew ){
@@ -36983,21 +33812,17 @@ SQLITE_PRIVATE void *sqlite3PagerTempSpace(Pager *pPager){
}
/*
-** Attempt to set the maximum database page count if mxPage is positive.
+** 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){
- int nPage;
if( mxPage>0 ){
pPager->mxPgno = mxPage;
}
- if( pPager->state!=PAGER_UNLOCK ){
- sqlite3PagerPagecount(pPager, &nPage);
- assert( pPager->mxPgno>=nPage );
- }
+ sqlite3PagerPagecount(pPager, 0);
return pPager->mxPgno;
}
@@ -37027,11 +33852,11 @@ void enable_simulated_io_errors(void){
/*
** Read the first N bytes from the beginning of the file into memory
-** that pDest points to.
+** 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
+** 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.
**
@@ -37043,15 +33868,6 @@ SQLITE_PRIVATE int sqlite3PagerReadFileheader(Pager *pPager, int N, unsigned cha
int rc = SQLITE_OK;
memset(pDest, 0, N);
assert( isOpen(pPager->fd) || pPager->tempFile );
-
- if( pagerUseWal(pPager) ){
- int isInWal = 0;
- rc = sqlite3WalRead(pPager->pWal, 1, &isInWal, N, pDest);
- if( rc!=SQLITE_OK || isInWal ){
- return rc;
- }
- }
-
if( isOpen(pPager->fd) ){
IOTRACE(("DBHDR %p 0 %d\n", pPager, N))
rc = sqlite3OsRead(pPager->fd, pDest, N, 0);
@@ -37063,9 +33879,9 @@ SQLITE_PRIVATE int sqlite3PagerReadFileheader(Pager *pPager, int N, unsigned cha
}
/*
-** Return the total number of pages in the database file associated
+** Return the total number of pages in the database file associated
** with pPager. Normally, this is calculated as (<db file size>/<page-size>).
-** However, if the file is between 1 and <page-size> bytes in size, then
+** However, if the file is between 1 and <page-size> bytes in size, then
** this is considered a 1 page file.
**
** If the pager is in error state when this function is called, then the
@@ -37078,7 +33894,12 @@ SQLITE_PRIVATE int sqlite3PagerReadFileheader(Pager *pPager, int N, unsigned cha
** and *pnPage is set to the number of pages in the database.
*/
SQLITE_PRIVATE int sqlite3PagerPagecount(Pager *pPager, int *pnPage){
- Pgno nPage = 0; /* Value to return via *pnPage */
+ Pgno nPage; /* Value to return via *pnPage */
+
+ /* If the pager is already in the error state, return the error code. */
+ if( pPager->errCode ){
+ return pPager->errCode;
+ }
/* Determine the number of pages in the file. Store this in nPage. */
if( pPager->dbSizeValid ){
@@ -37087,23 +33908,15 @@ SQLITE_PRIVATE int sqlite3PagerPagecount(Pager *pPager, int *pnPage){
int rc; /* Error returned by OsFileSize() */
i64 n = 0; /* File size in bytes returned by OsFileSize() */
- if( pagerUseWal(pPager) && pPager->state!=PAGER_UNLOCK ){
- sqlite3WalDbsize(pPager->pWal, &nPage);
+ assert( isOpen(pPager->fd) || pPager->tempFile );
+ if( isOpen(pPager->fd) && (0 != (rc = sqlite3OsFileSize(pPager->fd, &n))) ){
+ pager_error(pPager, rc);
+ return rc;
}
-
- if( nPage==0 ){
- assert( isOpen(pPager->fd) || pPager->tempFile );
- if( isOpen(pPager->fd) ){
- if( SQLITE_OK!=(rc = sqlite3OsFileSize(pPager->fd, &n)) ){
- pager_error(pPager, rc);
- return rc;
- }
- }
- if( n>0 && n<pPager->pageSize ){
- nPage = 1;
- }else{
- nPage = (Pgno)(n / pPager->pageSize);
- }
+ if( n>0 && n<pPager->pageSize ){
+ nPage = 1;
+ }else{
+ nPage = (Pgno)(n / pPager->pageSize);
}
if( pPager->state!=PAGER_UNLOCK ){
pPager->dbSize = nPage;
@@ -37112,7 +33925,7 @@ SQLITE_PRIVATE int sqlite3PagerPagecount(Pager *pPager, int *pnPage){
}
}
- /* If the current number of pages in the file is greater than the
+ /* 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.
*/
@@ -37121,7 +33934,9 @@ SQLITE_PRIVATE int sqlite3PagerPagecount(Pager *pPager, int *pnPage){
}
/* Set the output variable and return SQLITE_OK */
- *pnPage = nPage;
+ if( pnPage ){
+ *pnPage = nPage;
+ }
return SQLITE_OK;
}
@@ -37131,13 +33946,13 @@ SQLITE_PRIVATE int sqlite3PagerPagecount(Pager *pPager, int *pnPage){
** a similar or greater lock is already held, this function is a no-op
** (returning SQLITE_OK immediately).
**
-** 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
+** 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.
**
** 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
+** the lock. If the lock is obtained successfully, set the Pager.state
** variable to locktype before returning.
*/
static int pager_wait_on_lock(Pager *pPager, int locktype){
@@ -37154,7 +33969,7 @@ static int pager_wait_on_lock(Pager *pPager, int locktype){
assert( pPager->state>=PAGER_SHARED || pPager->dbSizeValid==0 );
assert( pPager->state>=PAGER_SHARED || pPager->dbModified==0 );
- /* Check that this is either a no-op (because the requested lock is
+ /* 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().
@@ -37179,10 +33994,10 @@ static int pager_wait_on_lock(Pager *pPager, int locktype){
}
/*
-** Function assertTruncateConstraint(pPager) checks that one of the
+** 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
+** 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
@@ -37195,9 +34010,9 @@ static int pager_wait_on_lock(Pager *pPager, int locktype){
** the database file. If a savepoint transaction were rolled back after
** this happened, the correct behaviour 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
+** 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
+** database image would become corrupt. It is therefore fortunate that
** this circumstance cannot arise.
*/
#if defined(SQLITE_DEBUG)
@@ -37213,9 +34028,9 @@ static void assertTruncateConstraint(Pager *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
+** 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.
*/
SQLITE_PRIVATE void sqlite3PagerTruncateImage(Pager *pPager, Pgno nPage){
@@ -37226,32 +34041,6 @@ SQLITE_PRIVATE void sqlite3PagerTruncateImage(Pager *pPager, Pgno nPage){
assertTruncateConstraint(pPager);
}
-
-/*
-** 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;
-}
-
/*
** Shutdown the page cache. Free all memory and close all files.
**
@@ -37262,37 +34051,26 @@ static int pagerSyncHotJournal(Pager *pPager){
** 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
+** 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;
-
disable_simulated_io_errors();
sqlite3BeginBenignMalloc();
pPager->errCode = 0;
pPager->exclusiveMode = 0;
-#ifndef SQLITE_OMIT_WAL
- sqlite3WalClose(pPager->pWal,
- (pPager->noSync ? 0 : pPager->sync_flags),
- pPager->pageSize, pTmp
- );
- pPager->pWal = 0;
-#endif
pager_reset(pPager);
if( MEMDB ){
pager_unlock(pPager);
}else{
- /* Set Pager.journalHdr to -1 for the benefit of the pager_playback()
+ /* Set Pager.journalHdr to -1 for the benefit of the pager_playback()
** call which may be made from within pagerUnlockAndRollback(). If it
** is not -1, then the unsynced portion of an open journal file may
** be played back into the database. If a power failure occurs while
** this is happening, the database may become corrupt.
*/
- if( isOpen(pPager->jfd) ){
- pPager->errCode = pagerSyncHotJournal(pPager);
- }
+ pPager->journalHdr = -1;
pagerUnlockAndRollback(pPager);
}
sqlite3EndBenignMalloc();
@@ -37300,7 +34078,7 @@ SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager){
PAGERTRACE(("CLOSE %d\n", PAGERID(pPager)));
IOTRACE(("CLOSE %p\n", pPager))
sqlite3OsClose(pPager->fd);
- sqlite3PageFree(pTmp);
+ sqlite3PageFree(pPager->pTmpSpace);
sqlite3PcacheClose(pPager->pPCache);
#ifdef SQLITE_HAS_CODEC
@@ -37348,7 +34126,7 @@ SQLITE_PRIVATE void sqlite3PagerRef(DbPage *pPg){
** 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
+** * If the device does not support the SEQUENTIAL property, then
** journal file is synced.
**
** Or, in pseudo-code:
@@ -37357,14 +34135,14 @@ SQLITE_PRIVATE void sqlite3PagerRef(DbPage *pPg){
** if( NOT SAFE_APPEND ){
** if( <full-sync mode> ) xSync(<journal file>);
** <update nRec field>
-** }
+** }
** if( NOT SEQUENTIAL ) xSync(<journal file>);
** }
**
** The Pager.needSync flag is never be set for temporary files, or any
** file operating in no-sync mode (Pager.noSync set to non-zero).
**
-** If successful, this routine clears the PGHDR_NEED_SYNC flag of every
+** 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.
*/
@@ -37382,10 +34160,10 @@ static int syncJournal(Pager *pPager){
** 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
+ ** previous connections 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.
@@ -37395,16 +34173,16 @@ static int syncJournal(Pager *pPager){
** 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
+ ** 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];
+ u8 zHeader[sizeof(aJournalMagic)+4];
- memcpy(zHeader, aJournalMagic, sizeof(aJournalMagic));
- put32bits(&zHeader[sizeof(aJournalMagic)], pPager->nRec);
+ memcpy(zHeader, aJournalMagic, sizeof(aJournalMagic));
+ put32bits(&zHeader[sizeof(aJournalMagic)], pPager->nRec);
iNextHdrOffset = journalHdrOffset(pPager);
rc = sqlite3OsRead(pPager->jfd, aMagic, 8, iNextHdrOffset);
@@ -37422,7 +34200,7 @@ static int syncJournal(Pager *pPager){
** 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
+ ** 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.
@@ -37436,25 +34214,24 @@ static int syncJournal(Pager *pPager){
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->sync_flags|
+ rc = sqlite3OsSync(pPager->jfd, pPager->sync_flags|
(pPager->sync_flags==SQLITE_SYNC_FULL?SQLITE_SYNC_DATAONLY:0)
);
if( rc!=SQLITE_OK ) return rc;
}
}
- /* The journal file was just successfully synced. Set Pager.needSync
+ /* The journal file was just successfully synced. Set Pager.needSync
** to zero and clear the PGHDR_NEED_SYNC flag on all pagess.
*/
pPager->needSync = 0;
pPager->journalStarted = 1;
- pPager->journalHdr = pPager->journalOff;
sqlite3PcacheClearSyncFlags(pPager->pPCache);
}
@@ -37472,9 +34249,9 @@ static int syncJournal(Pager *pPager){
** 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
+** 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,
@@ -37489,7 +34266,7 @@ static int syncJournal(Pager *pPager){
** 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
+** 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.
*/
@@ -37516,7 +34293,6 @@ static int pager_write_pagelist(PgHdr *pList){
** EXCLUSIVE, it means the database file has been changed and any rollback
** will require a journal playback.
*/
- assert( !pagerUseWal(pList->pPager) );
assert( pPager->state>=PAGER_RESERVED );
rc = pager_wait_on_lock(pPager, EXCLUSIVE_LOCK);
@@ -37529,14 +34305,6 @@ static int pager_write_pagelist(PgHdr *pList){
rc = pagerOpentemp(pPager, pPager->fd, pPager->vfsFlags);
}
- /* Before the first write, give the VFS a hint of what the final
- ** file size will be.
- */
- if( pPager->dbSize > (pPager->dbOrigSize+1) && isOpen(pPager->fd) ){
- sqlite3_int64 szFile = pPager->pageSize * (sqlite3_int64)pPager->dbSize;
- sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_SIZE_HINT, &szFile);
- }
-
while( rc==SQLITE_OK && pList ){
Pgno pgno = pList->pgno;
@@ -37546,11 +34314,13 @@ static int pager_write_pagelist(PgHdr *pList){
** any such pages to the file.
**
** Also, do not write out any page that has the PGHDR_DONT_WRITE flag
- ** set (set by sqlite3PagerDontWrite()).
+ ** set (set by sqlite3PagerDontWrite()). Note that if compiled with
+ ** SQLITE_SECURE_DELETE the PGHDR_DONT_WRITE bit is never set and so
+ ** the second test is always true.
*/
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 */
+ char *pData; /* Data to write */
/* Encode the database */
CODEC2(pPager, pList->pData, pgno, 6, return SQLITE_NOMEM, pData);
@@ -37559,8 +34329,8 @@ static int pager_write_pagelist(PgHdr *pList){
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.
+ ** 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));
@@ -37590,15 +34360,15 @@ static int pager_write_pagelist(PgHdr *pList){
}
/*
-** Append a record of the current state of page pPg to the sub-journal.
-** It is the callers responsibility to use subjRequiresPage() to check
+** 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 returns SQLITE_OK if everything is successful, an IO
-** error code if the attempt to write to the sub-journal fails, or
+** 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.
*/
@@ -37612,11 +34382,8 @@ static int subjournalPage(PgHdr *pPg){
CODEC2(pPager, pData, pPg->pgno, 7, return SQLITE_NOMEM, pData2);
PAGERTRACE(("STMT-JOURNAL %d page %d\n", PAGERID(pPager), pPg->pgno));
-
- assert( pagerUseWal(pPager)
- || pageInJournal(pPg)
- || pPg->pgno>pPager->dbOrigSize
- );
+
+ assert( pageInJournal(pPg) || pPg->pgno>pPager->dbOrigSize );
rc = write32bits(pPager->sjfd, offset, pPg->pgno);
if( rc==SQLITE_OK ){
rc = sqlite3OsWrite(pPager->sjfd, pData2, pPager->pageSize, offset+4);
@@ -37630,18 +34397,19 @@ static int subjournalPage(PgHdr *pPg){
return rc;
}
+
/*
** 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
+** 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
+** is always associated with the Pager object passed as the first
** argument.
**
** 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.
+** journal file.
**
** If successful, sqlite3PcacheMakeClean() is called on the page and
** SQLITE_OK returned. If an IO error occurs while trying to make the
@@ -37656,84 +34424,74 @@ static int pagerStress(void *p, PgHdr *pPg){
assert( pPg->pPager==pPager );
assert( pPg->flags&PGHDR_DIRTY );
- 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, 0);
- }
- }else{
- /* The doNotSync flag is set by the sqlite3PagerWrite() function while it
- ** is journalling a set of two or more database pages that are stored
- ** on the same disk sector. Syncing the journal is not allowed while
- ** this is happening as it is important that all members of such a
- ** set of pages are synced to disk together. So, if the page this function
- ** is trying to make clean will require a journal sync and the doNotSync
- ** flag is set, return without doing anything. The pcache layer will
- ** just have to go ahead and allocate a new page buffer instead of
- ** reusing pPg.
- **
- ** Similarly, if the pager has already entered the error state, do not
- ** try to write the contents of pPg to disk.
- */
- if( NEVER(pPager->errCode)
- || (pPager->doNotSync && pPg->flags&PGHDR_NEED_SYNC)
- ){
- return SQLITE_OK;
- }
+ /* The doNotSync flag is set by the sqlite3PagerWrite() function while it
+ ** is journalling a set of two or more database pages that are stored
+ ** on the same disk sector. Syncing the journal is not allowed while
+ ** this is happening as it is important that all members of such a
+ ** set of pages are synced to disk together. So, if the page this function
+ ** is trying to make clean will require a journal sync and the doNotSync
+ ** flag is set, return without doing anything. The pcache layer will
+ ** just have to go ahead and allocate a new page buffer instead of
+ ** reusing pPg.
+ **
+ ** Similarly, if the pager has already entered the error state, do not
+ ** try to write the contents of pPg to disk.
+ */
+ if( NEVER(pPager->errCode)
+ || (pPager->doNotSync && pPg->flags&PGHDR_NEED_SYNC)
+ ){
+ return SQLITE_OK;
+ }
- /* Sync the journal file if required. */
- if( pPg->flags&PGHDR_NEED_SYNC ){
- rc = syncJournal(pPager);
- if( rc==SQLITE_OK && pPager->fullSync &&
- !(pPager->journalMode==PAGER_JOURNALMODE_MEMORY) &&
- !(sqlite3OsDeviceCharacteristics(pPager->fd)&SQLITE_IOCAP_SAFE_APPEND)
- ){
- pPager->nRec = 0;
- rc = writeJournalHdr(pPager);
- }
+ /* Sync the journal file if required. */
+ if( pPg->flags&PGHDR_NEED_SYNC ){
+ rc = syncJournal(pPager);
+ if( rc==SQLITE_OK && pPager->fullSync &&
+ !(pPager->journalMode==PAGER_JOURNALMODE_MEMORY) &&
+ !(sqlite3OsDeviceCharacteristics(pPager->fd)&SQLITE_IOCAP_SAFE_APPEND)
+ ){
+ pPager->nRec = 0;
+ rc = writeJournalHdr(pPager);
}
+ }
- /* 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);
- }
+ /* 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 ){
- rc = pager_write_pagelist(pPg);
- }
+ /* Write the contents of the page out to the database file. */
+ if( rc==SQLITE_OK ){
+ pPg->pDirty = 0;
+ rc = pager_write_pagelist(pPg);
}
/* Mark the page as clean. */
@@ -37754,8 +34512,8 @@ static int pagerStress(void *p, PgHdr *pPg){
** 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.
+** 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
@@ -37767,13 +34525,13 @@ static int pagerStress(void *p, PgHdr *pPg){
** of the PAGER_OMIT_JOURNAL and PAGER_NO_READLOCK flags.
**
** The vfsFlags parameter is a bitmask to pass to the flags parameter
-** of the xOpen() method of the supplied VFS when opening files.
+** of the xOpen() method of the supplied VFS when opening files.
**
-** If the pager object is allocated and the specified file opened
+** 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
+** (sqlite3Malloc() is used to allocate memory), SQLITE_CANTOPEN or
** various SQLITE_IO_XXX errors.
*/
SQLITE_PRIVATE int sqlite3PagerOpen(
@@ -37801,10 +34559,10 @@ SQLITE_PRIVATE int sqlite3PagerOpen(
/* 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
+ ** 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
+ ** file in memory to implement the atomic-write optimization (see
** source file journal.c).
*/
if( sqlite3JournalSize(pVfs)>sqlite3MemJournalSize() ){
@@ -37854,7 +34612,7 @@ SQLITE_PRIVATE int sqlite3PagerOpen(
}
/* Allocate memory for the Pager structure, PCache object, the
- ** three file descriptors, the database file name and the journal
+ ** three file descriptors, the database file name and the journal
** file name. The layout in memory is as follows:
**
** Pager object (sizeof(Pager) bytes)
@@ -37869,7 +34627,7 @@ SQLITE_PRIVATE int sqlite3PagerOpen(
ROUND8(sizeof(*pPager)) + /* Pager structure */
ROUND8(pcacheSize) + /* PCache object */
ROUND8(pVfs->szOsFile) + /* The main db file */
- journalFileSize * 2 + /* The two journal files */
+ journalFileSize * 2 + /* The two journal files */
nPathname + 1 + /* zFilename */
nPathname + 8 + 1 /* zJournal */
);
@@ -37946,13 +34704,13 @@ SQLITE_PRIVATE int sqlite3PagerOpen(
** 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->state = PAGER_EXCLUSIVE;
readOnly = (vfsFlags&SQLITE_OPEN_READONLY);
}
- /* The following call to PagerSetPagesize() serves to set the value of
+ /* The following call to PagerSetPagesize() serves to set the value of
** Pager.pageSize and to allocate the Pager.pTmpSpace buffer.
*/
if( rc==SQLITE_OK ){
@@ -37961,7 +34719,7 @@ SQLITE_PRIVATE int sqlite3PagerOpen(
testcase( rc!=SQLITE_OK );
}
- /* If an error occurred in either of the blocks above, free the
+ /* If an error occurred in either of the blocks above, free the
** Pager structure and close the file.
*/
if( rc!=SQLITE_OK ){
@@ -37994,10 +34752,10 @@ SQLITE_PRIVATE int sqlite3PagerOpen(
assert( pPager->state == (tempFile ? PAGER_EXCLUSIVE : PAGER_UNLOCK) );
/* pPager->errMask = 0; */
pPager->tempFile = (u8)tempFile;
- assert( tempFile==PAGER_LOCKINGMODE_NORMAL
+ assert( tempFile==PAGER_LOCKINGMODE_NORMAL
|| tempFile==PAGER_LOCKINGMODE_EXCLUSIVE );
assert( PAGER_LOCKINGMODE_EXCLUSIVE==1 );
- pPager->exclusiveMode = (u8)tempFile;
+ pPager->exclusiveMode = (u8)tempFile;
pPager->changeCountDone = pPager->tempFile;
pPager->memDb = (u8)memDb;
pPager->readOnly = (u8)readOnly;
@@ -38022,7 +34780,6 @@ SQLITE_PRIVATE int sqlite3PagerOpen(
/* pPager->pBusyHandlerArg = 0; */
pPager->xReiniter = xReinit;
/* memset(pPager->aHash, 0, sizeof(pPager->aHash)); */
-
*ppPager = pPager;
return SQLITE_OK;
}
@@ -38032,7 +34789,7 @@ SQLITE_PRIVATE int sqlite3PagerOpen(
/*
** 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
+** 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:
**
@@ -38051,10 +34808,10 @@ SQLITE_PRIVATE int sqlite3PagerOpen(
** 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.
+** 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
+** 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
@@ -38077,7 +34834,7 @@ static int hasHotJournal(Pager *pPager, int *pExists){
int locked; /* 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()
+ ** 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
@@ -38089,7 +34846,7 @@ static int hasHotJournal(Pager *pPager, int *pExists){
int nPage;
/* Check the size of the database file. If it consists of 0 pages,
- ** then delete the journal file. See the header comment above for
+ ** 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].
@@ -38107,7 +34864,7 @@ static int hasHotJournal(Pager *pPager, int *pExists){
/* 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,
+ ** If there is, then we consider this journal to be hot. If not,
** it can be ignored.
*/
int f = SQLITE_OPEN_READONLY|SQLITE_OPEN_MAIN_JOURNAL;
@@ -38142,6 +34899,51 @@ static int hasHotJournal(Pager *pPager, int *pExists){
}
/*
+** 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 page 1 is read, then the value of Pager.dbFileVers[] is set to
+** the value read from the database file.
+**
+** If an IO error occurs, then the IO error is returned to the caller.
+** Otherwise, SQLITE_OK is returned.
+*/
+static int readDbPage(PgHdr *pPg){
+ Pager *pPager = pPg->pPager; /* Pager object associated with page pPg */
+ Pgno pgno = pPg->pgno; /* Page number to read */
+ int rc; /* Return code */
+ i64 iOffset; /* Byte offset of file to read from */
+
+ assert( pPager->state>=PAGER_SHARED && !MEMDB );
+ assert( isOpen(pPager->fd) );
+
+ if( NEVER(!isOpen(pPager->fd)) ){
+ assert( pPager->tempFile );
+ memset(pPg->pData, 0, pPager->pageSize);
+ return SQLITE_OK;
+ }
+ iOffset = (pgno-1)*(i64)pPager->pageSize;
+ rc = sqlite3OsRead(pPager->fd, pPg->pData, pPager->pageSize, iOffset);
+ if( rc==SQLITE_IOERR_SHORT_READ ){
+ rc = SQLITE_OK;
+ }
+ if( pgno==1 ){
+ u8 *dbFileVers = &((u8*)pPg->pData)[24];
+ memcpy(&pPager->dbFileVers, dbFileVers, sizeof(pPager->dbFileVers));
+ }
+ CODEC1(pPager, pPg->pData, pgno, 3, rc = SQLITE_NOMEM);
+
+ 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)));
+
+ 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
@@ -38153,7 +34955,7 @@ static int hasHotJournal(Pager *pPager, int *pExists){
** 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
+** 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.
@@ -38194,9 +34996,7 @@ SQLITE_PRIVATE int sqlite3PagerSharedLock(Pager *pPager){
pager_reset(pPager);
}
- if( pagerUseWal(pPager) ){
- rc = pagerOpenSnapshot(pPager);
- }else if( pPager->state==PAGER_UNLOCK || isErrorReset ){
+ if( pPager->state==PAGER_UNLOCK || isErrorReset ){
sqlite3_vfs * const pVfs = pPager->pVfs;
int isHotJournal = 0;
assert( !MEMDB );
@@ -38228,12 +35028,12 @@ SQLITE_PRIVATE int sqlite3PagerSharedLock(Pager *pPager){
** 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
+ ** 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
+ ** 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.
*/
if( pPager->state<EXCLUSIVE_LOCK ){
@@ -38244,8 +35044,8 @@ SQLITE_PRIVATE int sqlite3PagerSharedLock(Pager *pPager){
}
pPager->state = PAGER_EXCLUSIVE;
}
-
- /* Open the journal for read/write access. This is because in
+
+ /* Open the journal for read/write access. This is because in
** exclusive-access mode the file descriptor will be kept open and
** possibly used for a transaction later on. On some systems, the
** OsTruncate() call used in exclusive-access mode also requires
@@ -38266,9 +35066,9 @@ SQLITE_PRIVATE int sqlite3PagerSharedLock(Pager *pPager){
sqlite3OsClose(pPager->jfd);
}
}else{
- /* 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
+ /* 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. */
rc = pager_end_transaction(pPager, 0);
@@ -38279,28 +35079,19 @@ SQLITE_PRIVATE int sqlite3PagerSharedLock(Pager *pPager){
goto failed;
}
- /* Reset the journal status fields to indicates that we have no
- ** rollback journal at this time. */
+ /* TODO: Why are these cleared here? Is it necessary? */
pPager->journalStarted = 0;
pPager->journalOff = 0;
pPager->setMaster = 0;
pPager->journalHdr = 0;
-
- /* Make sure the journal file has been synced to disk. */
-
+
/* 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.
+ ** an inconsistent cache.
*/
if( isOpen(pPager->jfd) ){
- rc = pagerSyncHotJournal(pPager);
- if( rc==SQLITE_OK ){
- rc = pager_playback(pPager, 1);
- }
+ rc = pager_playback(pPager, 1);
if( rc!=SQLITE_OK ){
rc = pager_error(pPager, rc);
goto failed;
@@ -38323,21 +35114,21 @@ SQLITE_PRIVATE int sqlite3PagerSharedLock(Pager *pPager){
** 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
+ **
+ ** 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.
*/
- int nPage;
char dbFileVers[sizeof(pPager->dbFileVers)];
- sqlite3PagerPagecount(pPager, &nPage);
+ sqlite3PagerPagecount(pPager, 0);
if( pPager->errCode ){
rc = pPager->errCode;
goto failed;
}
- if( nPage>0 ){
+ assert( pPager->dbSizeValid );
+ if( pPager->dbSize>0 ){
IOTRACE(("CKVERS %p %d\n", pPager, sizeof(dbFileVers)));
rc = sqlite3OsRead(pPager->fd, &dbFileVers, sizeof(dbFileVers), 24);
if( rc!=SQLITE_OK ){
@@ -38352,11 +35143,6 @@ SQLITE_PRIVATE int sqlite3PagerSharedLock(Pager *pPager){
}
}
assert( pPager->exclusiveMode || pPager->state==PAGER_SHARED );
-
- /* 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);
}
failed:
@@ -38374,10 +35160,10 @@ SQLITE_PRIVATE int sqlite3PagerSharedLock(Pager *pPager){
** 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( (sqlite3PcacheRefCount(pPager->pPCache)==0)
- && (!pPager->exclusiveMode || pPager->journalOff>0)
+ && (!pPager->exclusiveMode || pPager->journalOff>0)
){
pagerUnlockAndRollback(pPager);
}
@@ -38385,25 +35171,25 @@ static void pagerUnlockIfUnused(Pager *pPager){
/*
** Acquire a reference to page number pgno in pager pPager (a page
-** reference has type DbPage*). If the requested reference is
+** 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.
+** 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
+** 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.
+** 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.
**
** If noContent is true, it means that we do not care about the contents
** of the page. This occurs in two seperate scenarios:
@@ -38411,7 +35197,7 @@ static void pagerUnlockIfUnused(Pager *pPager){
** 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
+** a new page into the cache to populate with the data read
** from the savepoint journal.
**
** If noContent is true, then the data returned is zeroed instead of
@@ -38449,7 +35235,7 @@ SQLITE_PRIVATE int sqlite3PagerAcquire(
return SQLITE_CORRUPT_BKPT;
}
- /* If the pager is in the error state, return an error immediately.
+ /* 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 && pPager->errCode!=SQLITE_FULL ){
rc = pPager->errCode;
@@ -38467,7 +35253,7 @@ SQLITE_PRIVATE int sqlite3PagerAcquire(
assert( (*ppPage)->pgno==pgno );
assert( (*ppPage)->pPager==pPager || (*ppPage)->pPager==0 );
- if( (*ppPage)->pPager && !noContent ){
+ if( (*ppPage)->pPager ){
/* 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) );
@@ -38475,7 +35261,7 @@ SQLITE_PRIVATE int sqlite3PagerAcquire(
return SQLITE_OK;
}else{
- /* The pager cache has created a new page. Its content needs to
+ /* The pager cache has created a new page. Its content needs to
** be initialized. */
int nMax;
@@ -38497,14 +35283,14 @@ SQLITE_PRIVATE int sqlite3PagerAcquire(
if( MEMDB || nMax<(int)pgno || noContent || !isOpen(pPager->fd) ){
if( pgno>pPager->mxPgno ){
- rc = SQLITE_FULL;
- goto pager_acquire_err;
+ 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
+ ** 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();
@@ -38546,14 +35332,14 @@ pager_acquire_err:
/*
** 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. Also, return 0 if the
+** or 0 if the page is not in cache. Also, return 0 if the
** pager is in PAGER_UNLOCK state when this function is called,
** or if the pager is in an error state other than SQLITE_FULL.
**
** 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
+** 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){
@@ -38587,13 +35373,13 @@ SQLITE_PRIVATE void sqlite3PagerUnref(DbPage *pPg){
** sub-journal file is open too. If the main journal is not open,
** this function is a no-op.
**
-** SQLITE_OK is returned if everything goes according to plan.
-** An SQLITE_IOERR_XXX error code is returned if a call to
+** SQLITE_OK is returned if everything goes according to plan.
+** An SQLITE_IOERR_XXX error code is returned if a call to
** sqlite3OsOpen() fails.
*/
static int openSubJournal(Pager *pPager){
int rc = SQLITE_OK;
- if( (pagerUseWal(pPager) || isOpen(pPager->jfd)) && !isOpen(pPager->sjfd) ){
+ if( isOpen(pPager->jfd) && !isOpen(pPager->sjfd) ){
if( pPager->journalMode==PAGER_JOURNALMODE_MEMORY || pPager->subjInMemory ){
sqlite3MemJournalOpen(pPager->sjfd);
}else{
@@ -38605,45 +35391,47 @@ static int openSubJournal(Pager *pPager){
/*
** This function is called at the start of every write transaction.
-** There must already be a RESERVED or EXCLUSIVE lock on the database
+** 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
+** 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.
+** already open file.
**
** Whether or not the journal file is opened by this function, the
** Pager.pInJournal bitvec structure is allocated.
**
-** Return SQLITE_OK if everything is successful. Otherwise, return
-** SQLITE_NOMEM if the attempt to allocate Pager.pInJournal fails, or
+** 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.
*/
static int pager_open_journal(Pager *pPager){
int rc = SQLITE_OK; /* Return code */
- int nPage; /* Size of database file */
sqlite3_vfs * const pVfs = pPager->pVfs; /* Local cache of vfs pointer */
assert( pPager->state>=PAGER_RESERVED );
assert( pPager->useJournal );
assert( pPager->journalMode!=PAGER_JOURNALMODE_OFF );
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;
+ /* TODO: Is it really possible to get here with dbSizeValid==0? If not,
+ ** the call to PagerPagecount() can be removed.
+ */
testcase( pPager->dbSizeValid==0 );
- rc = sqlite3PagerPagecount(pPager, &nPage);
- if( rc ) return rc;
- pPager->pInJournal = sqlite3BitvecCreate(nPage);
+ sqlite3PagerPagecount(pPager, 0);
+
+ pPager->pInJournal = sqlite3BitvecCreate(pPager->dbSize);
if( pPager->pInJournal==0 ){
return SQLITE_NOMEM;
}
@@ -38655,7 +35443,7 @@ static int pager_open_journal(Pager *pPager){
}else{
const int flags = /* VFS flags to open journal file */
SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|
- (pPager->tempFile ?
+ (pPager->tempFile ?
(SQLITE_OPEN_DELETEONCLOSE|SQLITE_OPEN_TEMP_JOURNAL):
(SQLITE_OPEN_MAIN_JOURNAL)
);
@@ -38671,7 +35459,7 @@ static int pager_open_journal(Pager *pPager){
}
- /* Write the first journal header to the journal file and open
+ /* Write the first journal header to the journal file and open
** the sub-journal if necessary.
*/
if( rc==SQLITE_OK ){
@@ -38697,17 +35485,17 @@ static int pager_open_journal(Pager *pPager){
}
/*
-** Begin a write-transaction on the specified pager object. If a
+** 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
+** an EXCLUSIVE lock. If such a lock is already held, no locking
** functions need be called.
**
-** If this is not a temporary or in-memory file and, the journal file is
-** opened if it has not been already. For a temporary file, the opening
-** of the journal file is deferred until there is an actual need to
+** If this is not a temporary or in-memory file and, the journal file is
+** opened if it has not been already. For a temporary file, the opening
+** of the journal file is deferred until there is an actual need to
** write to the journal. TODO: Why handle temporary files differently?
**
** If the journal file is opened (or if it is already open), then a
@@ -38718,79 +35506,43 @@ static int pager_open_journal(Pager *pPager){
** 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,
+** sub-journal is implemented in-memory if pPager is an in-memory database,
** or using a temporary file otherwise.
*/
SQLITE_PRIVATE int sqlite3PagerBegin(Pager *pPager, int exFlag, int subjInMemory){
int rc = SQLITE_OK;
assert( pPager->state!=PAGER_UNLOCK );
pPager->subjInMemory = (u8)subjInMemory;
-
if( pPager->state==PAGER_SHARED ){
assert( pPager->pInJournal==0 );
assert( !MEMDB && !pPager->tempFile );
- 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 = sqlite3OsLock(pPager->fd, EXCLUSIVE_LOCK);
- pPager->state = PAGER_SHARED;
- if( rc!=SQLITE_OK ){
- return rc;
- }
- sqlite3WalExclusiveMode(pPager->pWal, 1);
- }
-
- /* 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.
- **
- ** WAL mode sets Pager.state to PAGER_RESERVED when it has an open
- ** transaction, but never to PAGER_EXCLUSIVE. This is because in
- ** PAGER_EXCLUSIVE state 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.
- */
- rc = sqlite3WalWriteLock(pPager->pWal, 1);
- if( rc==SQLITE_OK ){
- pPager->dbOrigSize = pPager->dbSize;
- pPager->state = PAGER_RESERVED;
- pPager->journalOff = 0;
- }
-
- assert( rc!=SQLITE_OK || pPager->state==PAGER_RESERVED );
- assert( rc==SQLITE_OK || pPager->state==PAGER_SHARED );
- }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 = sqlite3OsLock(pPager->fd, RESERVED_LOCK);
- if( rc==SQLITE_OK ){
- pPager->state = PAGER_RESERVED;
- if( exFlag ){
- rc = pager_wait_on_lock(pPager, EXCLUSIVE_LOCK);
- }
+ /* 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 = sqlite3OsLock(pPager->fd, RESERVED_LOCK);
+ if( rc==SQLITE_OK ){
+ pPager->state = PAGER_RESERVED;
+ if( exFlag ){
+ rc = pager_wait_on_lock(pPager, EXCLUSIVE_LOCK);
}
}
- /* No need to open the journal file at this time. It will be
- ** opened before it is written to. If we defer opening the journal,
- ** we might save the work of creating a file if the transaction
- ** ends up being a no-op.
+ /* If the required locks were successfully obtained, open the journal
+ ** file and write the first journal-header to it.
*/
+ if( rc==SQLITE_OK && pPager->journalMode!=PAGER_JOURNALMODE_OFF ){
+ rc = pager_open_journal(pPager);
+ }
}else if( isOpen(pPager->jfd) && pPager->journalOff==0 ){
/* This happens when the pager was in exclusive-access mode the last
** time a (read or write) transaction was successfully concluded
- ** by this connection. Instead of deleting the journal file it was
+ ** by this connection. Instead of deleting the journal file it was
** kept open and either was truncated to 0 bytes or its header was
** overwritten with zeros.
*/
- assert( pagerUseWal(pPager)==0 );
assert( pPager->nRec==0 );
assert( pPager->dbOrigSize==0 );
assert( pPager->pInJournal==0 );
@@ -38798,6 +35550,7 @@ SQLITE_PRIVATE int sqlite3PagerBegin(Pager *pPager, int exFlag, int subjInMemory
}
PAGERTRACE(("TRANSACTION %d\n", PAGERID(pPager)));
+ assert( !isOpen(pPager->jfd) || pPager->journalOff>0 || rc!=SQLITE_OK );
if( rc!=SQLITE_OK ){
assert( !pPager->dbModified );
/* Ignore any IO error that occurs within pager_end_transaction(). The
@@ -38811,9 +35564,9 @@ SQLITE_PRIVATE int sqlite3PagerBegin(Pager *pPager, int exFlag, int subjInMemory
}
/*
-** Mark a single data page as writeable. The page is written into the
+** 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
+** 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.
*/
@@ -38827,8 +35580,8 @@ static int pager_write(PgHdr *pPg){
*/
assert( pPager->state>=PAGER_RESERVED );
- /* If an error has been previously detected, report the same error
- ** again.
+ /* If an error has been previously detected, we should not be
+ ** calling this routine. Repeat the error for robustness.
*/
if( NEVER(pPager->errCode) ) return pPager->errCode;
@@ -38845,7 +35598,6 @@ static int pager_write(PgHdr *pPg){
*/
sqlite3PcacheMakeDirty(pPg);
if( pageInJournal(pPg) && !subjRequiresPage(pPg) ){
- assert( !pagerUseWal(pPager) );
pPager->dbModified = 1;
}else{
@@ -38854,29 +35606,25 @@ static int pager_write(PgHdr *pPg){
** or both.
**
** Higher level routines should have already started a transaction,
- ** which means they have acquired the necessary locks but the rollback
- ** journal might not yet be open.
+ ** which means they have acquired the necessary locks and opened
+ ** a rollback journal. Double-check to makes sure this is the case.
*/
rc = sqlite3PagerBegin(pPager, 0, pPager->subjInMemory);
- if( rc!=SQLITE_OK ){
+ if( NEVER(rc!=SQLITE_OK) ){
return rc;
}
- if( !isOpen(pPager->jfd)
- && pPager->journalMode!=PAGER_JOURNALMODE_OFF
- && !pagerUseWal(pPager)
- ){
+ if( !isOpen(pPager->jfd) && pPager->journalMode!=PAGER_JOURNALMODE_OFF ){
assert( pPager->useJournal );
rc = pager_open_journal(pPager);
if( rc!=SQLITE_OK ) return rc;
}
pPager->dbModified = 1;
-
+
/* 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) && isOpen(pPager->jfd) ){
- assert( !pagerUseWal(pPager) );
if( pPg->pgno<=pPager->dbOrigSize ){
u32 cksum;
char *pData2;
@@ -38885,8 +35633,6 @@ static int pager_write(PgHdr *pPg){
** 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);
rc = write32bits(pPager->jfd, pPager->journalOff, pPg->pgno);
@@ -38899,11 +35645,11 @@ static int pager_write(PgHdr *pPg){
rc = write32bits(pPager->jfd, pPager->journalOff, cksum);
pPager->journalOff += 4;
}
- IOTRACE(("JOUT %p %d %lld %d\n", pPager, pPg->pgno,
+ 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,
+ PAGERID(pPager), pPg->pgno,
((pPg->flags&PGHDR_NEED_SYNC)?1:0), pager_pagehash(pPg)));
/* Even if an IO or diskfull error occurred while journalling the
@@ -38918,7 +35664,7 @@ static int pager_write(PgHdr *pPg){
pPager->needSync = 1;
}
- /* An error has occurred writing to the journal file. The
+ /* An error has occurred writing to the journal file. The
** transaction will be rolled back by the layer above.
*/
if( rc!=SQLITE_OK ){
@@ -38945,7 +35691,7 @@ static int pager_write(PgHdr *pPg){
((pPg->flags&PGHDR_NEED_SYNC)?1:0)));
}
}
-
+
/* 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
@@ -38966,9 +35712,9 @@ static int pager_write(PgHdr *pPg){
}
/*
-** 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
+** 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.
**
** The difference between this function and pager_write() is that this
@@ -39006,8 +35752,7 @@ SQLITE_PRIVATE int sqlite3PagerWrite(DbPage *pDbPage){
*/
pg1 = ((pPg->pgno-1) & ~(nPagePerSector-1)) + 1;
- rc = sqlite3PagerPagecount(pPager, (int *)&nPageCount);
- if( rc ) return rc;
+ sqlite3PagerPagecount(pPager, (int *)&nPageCount);
if( pPg->pgno>nPageCount ){
nPage = (pPg->pgno - pg1)+1;
}else if( (pg1+nPagePerSector-1)>nPageCount ){
@@ -39042,7 +35787,7 @@ SQLITE_PRIVATE int sqlite3PagerWrite(DbPage *pDbPage){
}
}
- /* If the PGHDR_NEED_SYNC flag is set for any of the nPage pages
+ /* 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
@@ -39079,6 +35824,7 @@ SQLITE_PRIVATE int sqlite3PagerIswriteable(DbPage *pPg){
}
#endif
+#ifndef SQLITE_SECURE_DELETE
/*
** 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
@@ -39090,7 +35836,7 @@ SQLITE_PRIVATE int sqlite3PagerIswriteable(DbPage *pPg){
** 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
+** Tests show that this optimization can quadruple the speed of large
** DELETE operations.
*/
SQLITE_PRIVATE void sqlite3PagerDontWrite(PgHdr *pPg){
@@ -39104,13 +35850,14 @@ SQLITE_PRIVATE void sqlite3PagerDontWrite(PgHdr *pPg){
#endif
}
}
+#endif /* !defined(SQLITE_SECURE_DELETE) */
/*
-** This routine is called to increment the value of the database file
-** change-counter, stored as a 4-byte big-endian integer starting at
+** 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.
**
-** If the isDirectMode flag is zero, then this is done by calling
+** 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.
@@ -39118,7 +35865,7 @@ SQLITE_PRIVATE void sqlite3PagerDontWrite(PgHdr *pPg){
** 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
+** by writing an updated version of page 1 using a call to the
** sqlite3OsWrite() function.
*/
static int pager_incr_changecounter(Pager *pPager, int isDirectMode){
@@ -39154,7 +35901,7 @@ static int pager_incr_changecounter(Pager *pPager, int isDirectMode){
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
+ ** 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.
*/
@@ -39168,9 +35915,6 @@ static int pager_incr_changecounter(Pager *pPager, int isDirectMode){
change_counter++;
put32bits(((char*)pPgHdr->pData)+24, change_counter);
- /* Also store the SQLite version number in bytes 96..99 */
- put32bits(((char*)pPgHdr->pData)+96, SQLITE_VERSION_NUMBER);
-
/* If running in direct mode, write the contents of page 1 to the file. */
if( DIRECT_MODE ){
const void *zBuf = pPgHdr->pData;
@@ -39218,12 +35962,12 @@ SQLITE_PRIVATE int sqlite3PagerSync(Pager *pPager){
**
** * 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,
+** * all dirty pages are written to the database file,
** * the database file is truncated (if required), and
-** * the database file synced.
+** * the database file synced.
**
-** The only thing that remains to commit the transaction is to finalize
-** (delete, truncate or zero the first part of) the journal file (or
+** 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).
**
** Note that if zMaster==NULL, this does not overwrite a previous value
@@ -39244,10 +35988,12 @@ SQLITE_PRIVATE int sqlite3PagerCommitPhaseOne(
/* The dbOrigSize is never set if journal_mode=OFF */
assert( pPager->journalMode!=PAGER_JOURNALMODE_OFF || pPager->dbOrigSize==0 );
- /* If a prior error occurred, report that error again. */
+ /* If a prior error occurred, this routine should not be called. ROLLBACK
+ ** is the appropriate response to an error, not COMMIT. Guard against
+ ** coding errors by repeating the prior error. */
if( NEVER(pPager->errCode) ) return pPager->errCode;
- PAGERTRACE(("DATABASE SYNC: File=%s zMaster=%s nSize=%d\n",
+ PAGERTRACE(("DATABASE SYNC: File=%s zMaster=%s nSize=%d\n",
pPager->zFilename, zMaster, pPager->dbSize));
if( MEMDB && pPager->dbModified ){
@@ -39257,137 +36003,128 @@ SQLITE_PRIVATE int sqlite3PagerCommitPhaseOne(
*/
sqlite3BackupRestart(pPager->pBackup);
}else if( pPager->state!=PAGER_SYNCED && pPager->dbModified ){
- if( pagerUseWal(pPager) ){
- PgHdr *pList = sqlite3PcacheDirtyList(pPager->pPCache);
- if( pList ){
- rc = pagerWalFrames(pPager, pList, pPager->dbSize, 1,
- (pPager->fullSync ? pPager->sync_flags : 0)
- );
- }
- 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.
+
+ /* 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 );
+ if( !zMaster && isOpen(pPager->jfd)
+ && pPager->journalOff==jrnlBufferSize(pPager)
+ && pPager->dbSize>=pPager->dbFileSize
+ && (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.
*/
- #ifdef SQLITE_ENABLE_ATOMIC_WRITE
- PgHdr *pPg;
- assert( isOpen(pPager->jfd) || pPager->journalMode==PAGER_JOURNALMODE_OFF );
- if( !zMaster && isOpen(pPager->jfd)
- && pPager->journalOff==jrnlBufferSize(pPager)
- && pPager->dbSize>=pPager->dbFileSize
- && (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);
- }
+ 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;
+ }
+#else
+ rc = pager_incr_changecounter(pPager, 0);
+#endif
+ if( rc!=SQLITE_OK ) goto commit_phase_one_exit;
- /* If this transaction has made the database smaller, then all pages
- ** being discarded by the truncation must be written to the journal
- ** file. This can only happen in auto-vacuum mode.
- **
- ** Before reading the pages with page numbers larger than the
- ** current value of Pager.dbSize, set dbSize back to the value
- ** that it took at the start of the transaction. Otherwise, the
- ** calls to sqlite3PagerGet() return zeroed pages instead of
- ** reading data from the database file.
- **
- ** When journal_mode==OFF the dbOrigSize is always zero, so this
- ** block never runs if journal_mode=OFF.
- */
- #ifndef SQLITE_OMIT_AUTOVACUUM
- if( pPager->dbSize<pPager->dbOrigSize
- && ALWAYS(pPager->journalMode!=PAGER_JOURNALMODE_OFF)
- ){
- Pgno i; /* Iterator variable */
- const Pgno iSkip = PAGER_MJ_PGNO(pPager); /* Pending lock page */
- const Pgno dbSize = pPager->dbSize; /* Database image size */
- pPager->dbSize = pPager->dbOrigSize;
- for( i=dbSize+1; i<=pPager->dbOrigSize; i++ ){
- if( !sqlite3BitvecTest(pPager->pInJournal, i) && i!=iSkip ){
- PgHdr *pPage; /* Page to journal */
- rc = sqlite3PagerGet(pPager, i, &pPage);
- if( rc!=SQLITE_OK ) goto commit_phase_one_exit;
- rc = sqlite3PagerWrite(pPage);
- sqlite3PagerUnref(pPage);
- if( rc!=SQLITE_OK ) goto commit_phase_one_exit;
- }
+ /* If this transaction has made the database smaller, then all pages
+ ** being discarded by the truncation must be written to the journal
+ ** file. This can only happen in auto-vacuum mode.
+ **
+ ** Before reading the pages with page numbers larger than the
+ ** current value of Pager.dbSize, set dbSize back to the value
+ ** that it took at the start of the transaction. Otherwise, the
+ ** calls to sqlite3PagerGet() return zeroed pages instead of
+ ** reading data from the database file.
+ **
+ ** When journal_mode==OFF the dbOrigSize is always zero, so this
+ ** block never runs if journal_mode=OFF.
+ */
+#ifndef SQLITE_OMIT_AUTOVACUUM
+ if( pPager->dbSize<pPager->dbOrigSize
+ && ALWAYS(pPager->journalMode!=PAGER_JOURNALMODE_OFF)
+ ){
+ Pgno i; /* Iterator variable */
+ const Pgno iSkip = PAGER_MJ_PGNO(pPager); /* Pending lock page */
+ const Pgno dbSize = pPager->dbSize; /* Database image size */
+ pPager->dbSize = pPager->dbOrigSize;
+ for( i=dbSize+1; i<=pPager->dbOrigSize; i++ ){
+ if( !sqlite3BitvecTest(pPager->pInJournal, i) && i!=iSkip ){
+ PgHdr *pPage; /* Page to journal */
+ rc = sqlite3PagerGet(pPager, i, &pPage);
+ if( rc!=SQLITE_OK ) goto commit_phase_one_exit;
+ rc = sqlite3PagerWrite(pPage);
+ sqlite3PagerUnref(pPage);
+ if( rc!=SQLITE_OK ) goto commit_phase_one_exit;
}
- pPager->dbSize = dbSize;
- }
- #endif
+ }
+ pPager->dbSize = dbSize;
+ }
+#endif
- /* 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;
+ /* 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. If the atomic-update optimization is being
- ** used, this call will not create the journal file or perform any
- ** real IO.
- */
- rc = syncJournal(pPager);
- if( rc!=SQLITE_OK ) goto commit_phase_one_exit;
+ /* Sync the journal file. If the atomic-update optimization is being
+ ** used, this call will not create the journal file or perform any
+ ** real IO.
+ */
+ rc = syncJournal(pPager);
+ if( rc!=SQLITE_OK ) goto commit_phase_one_exit;
- /* Write all dirty pages to the database file. */
- rc = pager_write_pagelist(sqlite3PcacheDirtyList(pPager->pPCache));
- if( rc!=SQLITE_OK ){
- assert( rc!=SQLITE_IOERR_BLOCKED );
- goto commit_phase_one_exit;
- }
- sqlite3PcacheCleanAll(pPager->pPCache);
+ /* Write all dirty pages to the database file. */
+ rc = pager_write_pagelist(sqlite3PcacheDirtyList(pPager->pPCache));
+ if( rc!=SQLITE_OK ){
+ assert( rc!=SQLITE_IOERR_BLOCKED );
+ goto commit_phase_one_exit;
+ }
+ sqlite3PcacheCleanAll(pPager->pPCache);
- /* If the file on disk is not the same size as the database image,
- ** then use pager_truncate to grow or shrink the file here.
- */
- if( pPager->dbSize!=pPager->dbFileSize ){
- Pgno nNew = pPager->dbSize - (pPager->dbSize==PAGER_MJ_PGNO(pPager));
- assert( pPager->state>=PAGER_EXCLUSIVE );
- rc = pager_truncate(pPager, nNew);
- if( rc!=SQLITE_OK ) goto commit_phase_one_exit;
- }
+ /* If the file on disk is not the same size as the database image,
+ ** then use pager_truncate to grow or shrink the file here.
+ */
+ if( pPager->dbSize!=pPager->dbFileSize ){
+ Pgno nNew = pPager->dbSize - (pPager->dbSize==PAGER_MJ_PGNO(pPager));
+ assert( pPager->state>=PAGER_EXCLUSIVE );
+ rc = pager_truncate(pPager, nNew);
+ if( rc!=SQLITE_OK ) goto commit_phase_one_exit;
+ }
- /* Finally, sync the database file. */
- if( !pPager->noSync && !noSync ){
- rc = sqlite3OsSync(pPager->fd, pPager->sync_flags);
- }
- IOTRACE(("DBSYNC %p\n", pPager))
+ /* Finally, sync the database file. */
+ if( !pPager->noSync && !noSync ){
+ rc = sqlite3OsSync(pPager->fd, pPager->sync_flags);
}
+ IOTRACE(("DBSYNC %p\n", pPager))
pPager->state = PAGER_SYNCED;
}
@@ -39400,12 +36137,12 @@ commit_phase_one_exit:
/*
** 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
+** 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
+** 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.
**
@@ -39430,14 +36167,14 @@ SQLITE_PRIVATE int sqlite3PagerCommitPhaseTwo(Pager *pPager){
** 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
+ ** 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
+ ** 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->dbModified==0 && pPager->exclusiveMode
+ if( pPager->dbModified==0 && pPager->exclusiveMode
&& pPager->journalMode==PAGER_JOURNALMODE_PERSIST
){
assert( pPager->journalOff==JOURNAL_HDR_SZ(pPager) );
@@ -39455,7 +36192,7 @@ SQLITE_PRIVATE int sqlite3PagerCommitPhaseTwo(Pager *pPager){
**
** This function performs two tasks:
**
-** 1) It rolls back the journal file, restoring all database file and
+** 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
** 2) It finalizes the journal file, so that it is not used for hot
@@ -39467,24 +36204,24 @@ SQLITE_PRIVATE int sqlite3PagerCommitPhaseTwo(Pager *pPager){
** then only (2) is performed. In this case there is no journal file
** to roll back.
**
-** * If in an error state other than SQLITE_FULL, then task (1) is
+** * If in an error state other than SQLITE_FULL, then task (1) is
** performed. If successful, task (2). Regardless of the outcome
** of either, the error state error code is returned to the caller
** (i.e. either SQLITE_IOERR or SQLITE_CORRUPT).
**
** * If the pager is in PAGER_RESERVED state, then attempt (1). Whether
** or not (1) is succussful, also attempt (2). If successful, return
-** SQLITE_OK. Otherwise, enter the error state and return the first
-** error code encountered.
+** SQLITE_OK. Otherwise, enter the error state and return the first
+** error code encountered.
**
-** In this case there is no chance that the database was written to.
-** So is safe to finalize the journal file even if the playback
+** In this case there is no chance that the database was written to.
+** So is safe to finalize the journal file even if the playback
** (operation 1) failed. However the pager must enter the error state
** as the contents of the in-memory cache are now suspect.
**
** * Finally, if in PAGER_EXCLUSIVE state, then attempt (1). Only
** attempt (2) if (1) is successful. Return SQLITE_OK if successful,
-** otherwise enter the error state and return the error code from the
+** otherwise enter the error state and return the error code from the
** failing operation.
**
** In this case the database file may have been written to. So if the
@@ -39496,14 +36233,7 @@ SQLITE_PRIVATE int sqlite3PagerCommitPhaseTwo(Pager *pPager){
SQLITE_PRIVATE int sqlite3PagerRollback(Pager *pPager){
int rc = SQLITE_OK; /* Return code */
PAGERTRACE(("ROLLBACK %d\n", PAGERID(pPager)));
- if( pagerUseWal(pPager) ){
- int rc2;
-
- rc = sqlite3PagerSavepoint(pPager, SAVEPOINT_ROLLBACK, -1);
- rc2 = pager_end_transaction(pPager, pPager->setMaster);
- if( rc==SQLITE_OK ) rc = rc2;
- rc = pager_error(pPager, rc);
- }else if( !pPager->dbModified || !isOpen(pPager->jfd) ){
+ if( !pPager->dbModified || !isOpen(pPager->jfd) ){
rc = pager_end_transaction(pPager, pPager->setMaster);
}else if( pPager->errCode && pPager->errCode!=SQLITE_FULL ){
if( pPager->state>=PAGER_EXCLUSIVE ){
@@ -39527,7 +36257,7 @@ SQLITE_PRIVATE int sqlite3PagerRollback(Pager *pPager){
}
/* 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
+ ** cache. So call pager_error() on the way out to make any error
** persistent.
*/
rc = pager_error(pPager, rc);
@@ -39551,16 +36281,6 @@ SQLITE_PRIVATE int sqlite3PagerRefcount(Pager *pPager){
}
/*
-** 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 + 20;
- return perPageSize*sqlite3PcachePagecount(pPager->pPCache)
- + sqlite3MallocSize(pPager);
-}
-
-/*
** Return the number of references to the specified page.
*/
SQLITE_PRIVATE int sqlite3PagerPageRefcount(DbPage *pPage){
@@ -39601,7 +36321,7 @@ SQLITE_PRIVATE int sqlite3PagerIsMemdb(Pager *pPager){
** 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
+** 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.
*/
@@ -39612,13 +36332,14 @@ SQLITE_PRIVATE int sqlite3PagerOpenSavepoint(Pager *pPager, int nSavepoint){
if( nSavepoint>nCurrent && pPager->useJournal ){
int ii; /* Iterator variable */
PagerSavepoint *aNew; /* New Pager.aSavepoint array */
- int nPage; /* Size of database file */
- rc = sqlite3PagerPagecount(pPager, &nPage);
- if( rc ) return rc;
+ /* Either there is no active journal or the sub-journal is open or
+ ** the journal is always stored in memory */
+ assert( pPager->nSavepoint==0 || isOpen(pPager->sjfd) ||
+ pPager->journalMode==PAGER_JOURNALMODE_MEMORY );
/* Grow the Pager.aSavepoint array using realloc(). Return SQLITE_NOMEM
- ** if the allocation fails. Otherwise, zero the new portion in case a
+ ** 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(
@@ -39633,20 +36354,18 @@ SQLITE_PRIVATE int sqlite3PagerOpenSavepoint(Pager *pPager, int nSavepoint){
/* Populate the PagerSavepoint structures just allocated. */
for(ii=nCurrent; ii<nSavepoint; ii++){
- aNew[ii].nOrig = nPage;
- if( isOpen(pPager->jfd) && pPager->journalOff>0 ){
+ assert( pPager->dbSizeValid );
+ aNew[ii].nOrig = pPager->dbSize;
+ if( isOpen(pPager->jfd) && ALWAYS(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(nPage);
+ aNew[ii].pInSavepoint = sqlite3BitvecCreate(pPager->dbSize);
if( !aNew[ii].pInSavepoint ){
return SQLITE_NOMEM;
}
- if( pagerUseWal(pPager) ){
- aNew[ii].iFrame = sqlite3WalSavepoint(pPager->pWal);
- }
}
/* Open the sub-journal, if it is not already opened. */
@@ -39659,7 +36378,7 @@ SQLITE_PRIVATE int sqlite3PagerOpenSavepoint(Pager *pPager, int nSavepoint){
/*
** This function is called to rollback or release (commit) a savepoint.
-** The savepoint to release or rollback need not be the most recently
+** The savepoint to release or rollback need not be the most recently
** created savepoint.
**
** Parameter op is always either SAVEPOINT_ROLLBACK or SAVEPOINT_RELEASE.
@@ -39667,26 +36386,26 @@ SQLITE_PRIVATE int sqlite3PagerOpenSavepoint(Pager *pPager, int nSavepoint){
** 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
+** 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
+** 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.
+** the transaction or unlock the database, it just restores the
+** contents of the database to its original state.
**
-** In any case, all savepoints with an index greater than iSavepoint
+** 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
+** 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 = SQLITE_OK;
@@ -39698,7 +36417,7 @@ SQLITE_PRIVATE int sqlite3PagerSavepoint(Pager *pPager, int op, int iSavepoint){
int nNew; /* Number of remaining savepoints after this op. */
/* Figure out how many savepoints will still be active after this
- ** operation. Store this value in nNew. Then free resources associated
+ ** 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);
@@ -39707,14 +36426,13 @@ SQLITE_PRIVATE int sqlite3PagerSavepoint(Pager *pPager, int op, int iSavepoint){
}
pPager->nSavepoint = nNew;
- /* If this is a release of the outermost savepoint, truncate
+ /* 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;
}
@@ -39724,12 +36442,12 @@ SQLITE_PRIVATE int sqlite3PagerSavepoint(Pager *pPager, int op, int iSavepoint){
** 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) ){
+ else if( isOpen(pPager->jfd) ){
PagerSavepoint *pSavepoint = (nNew==0)?0:&pPager->aSavepoint[nNew-1];
rc = pagerPlaybackSavepoint(pPager, pSavepoint);
assert(rc!=SQLITE_DONE);
}
-
+
}
return rc;
}
@@ -39814,8 +36532,8 @@ static void *sqlite3PagerGetCodec(Pager *pPager){
** transaction is active).
**
** 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
+** 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.
**
** This function may return SQLITE_NOMEM or an IO error code if an error
@@ -39838,7 +36556,7 @@ SQLITE_PRIVATE int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno, i
}
/* 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
+ ** savepoint, then save the current contents of the page into the
** sub-journal now. This is required to handle the following scenario:
**
** BEGIN;
@@ -39862,7 +36580,7 @@ SQLITE_PRIVATE int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno, i
return rc;
}
- PAGERTRACE(("MOVE %d page %d (needSync=%d) moves to %d\n",
+ 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))
@@ -39870,7 +36588,7 @@ SQLITE_PRIVATE int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno, i
** 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
+ ** 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 ){
@@ -39881,8 +36599,8 @@ SQLITE_PRIVATE int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno, i
}
/* If the cache contains a page with page-number pgno, remove it
- ** from its hash chain. Also, if the PgHdr.needSync was set for
- ** page pgno before the 'move' operation, it needs to be retained
+ ** from its hash chain. Also, if the PgHdr.needSync was set for
+ ** page pgno before the 'move' operation, it needs to be retained
** for the page moved there.
*/
pPg->flags &= ~PGHDR_NEED_SYNC;
@@ -39906,11 +36624,11 @@ SQLITE_PRIVATE int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno, i
pPager->dbModified = 1;
if( needSyncPgno ){
- /* If needSyncPgno is non-zero, then the journal file needs to be
+ /* 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
+ ** 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.needSync
+ ** loading the page into the pager-cache and setting the PgHdr.needSync
** flag.
**
** If the attempt to load the page into the page-cache fails, (due
@@ -39963,7 +36681,7 @@ SQLITE_PRIVATE void *sqlite3PagerGetData(DbPage *pPg){
}
/*
-** Return a pointer to the Pager.nExtra bytes of "extra" space
+** Return a pointer to the Pager.nExtra bytes of "extra" space
** allocated along with the specified page.
*/
SQLITE_PRIVATE void *sqlite3PagerGetExtra(DbPage *pPg){
@@ -39972,7 +36690,7 @@ SQLITE_PRIVATE void *sqlite3PagerGetExtra(DbPage *pPg){
/*
** Get/set the locking-mode for this pager. Parameter eMode must be one
-** of PAGER_LOCKINGMODE_QUERY, PAGER_LOCKINGMODE_NORMAL or
+** 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.
**
@@ -40001,10 +36719,9 @@ SQLITE_PRIVATE int sqlite3PagerLockingMode(Pager *pPager, int eMode){
** PAGER_JOURNALMODE_PERSIST
** PAGER_JOURNALMODE_OFF
** PAGER_JOURNALMODE_MEMORY
-** PAGER_JOURNALMODE_WAL
**
** If the parameter is not _QUERY, then the journal_mode is set to the
-** value specified if the change is allowed. The change may be disallowed
+** value specified if the change is allowed. The change is disallowed
** for the following reasons:
**
** * An in-memory database can only have its journal_mode set to _OFF
@@ -40019,34 +36736,18 @@ SQLITE_PRIVATE int sqlite3PagerJournalMode(Pager *pPager, int eMode){
|| eMode==PAGER_JOURNALMODE_DELETE
|| eMode==PAGER_JOURNALMODE_TRUNCATE
|| eMode==PAGER_JOURNALMODE_PERSIST
- || eMode==PAGER_JOURNALMODE_OFF
- || eMode==PAGER_JOURNALMODE_WAL
+ || eMode==PAGER_JOURNALMODE_OFF
|| eMode==PAGER_JOURNALMODE_MEMORY );
assert( PAGER_JOURNALMODE_QUERY<0 );
-
- if( eMode==PAGER_JOURNALMODE_WAL
- && pPager->journalMode==PAGER_JOURNALMODE_DELETE
- ){
- pPager->journalMode = PAGER_JOURNALMODE_WAL;
- }else if( eMode>=0
- && (pPager->tempFile==0 || eMode!=PAGER_JOURNALMODE_WAL)
- && (!MEMDB || eMode==PAGER_JOURNALMODE_MEMORY||eMode==PAGER_JOURNALMODE_OFF)
+ if( eMode>=0
+ && (!MEMDB || eMode==PAGER_JOURNALMODE_MEMORY
+ || eMode==PAGER_JOURNALMODE_OFF)
&& !pPager->dbModified
&& (!isOpen(pPager->jfd) || 0==pPager->journalOff)
){
if( isOpen(pPager->jfd) ){
sqlite3OsClose(pPager->jfd);
}
- assert( (PAGER_JOURNALMODE_TRUNCATE & 1)==1 );
- assert( (PAGER_JOURNALMODE_PERSIST & 1)==1 );
- assert( (PAGER_JOURNALMODE_DELETE & 1)==0 );
- assert( (PAGER_JOURNALMODE_MEMORY & 1)==0 );
- assert( (PAGER_JOURNALMODE_OFF & 1)==0 );
- if( (pPager->journalMode & 1)==1 && (eMode & 1)==0
- && !pPager->exclusiveMode ){
- sqlite3OsDelete(pPager->pVfs, pPager->zJournal, 0);
- }
-
pPager->journalMode = (u8)eMode;
}
return (int)pPager->journalMode;
@@ -40075,2006 +36776,9 @@ SQLITE_PRIVATE sqlite3_backup **sqlite3PagerBackupPtr(Pager *pPager){
return &pPager->pBackup;
}
-#ifndef SQLITE_OMIT_WAL
-/*
-** This function is called when the user invokes "PRAGMA checkpoint".
-*/
-SQLITE_PRIVATE int sqlite3PagerCheckpoint(Pager *pPager){
- int rc = SQLITE_OK;
- if( pPager->pWal ){
- u8 *zBuf = (u8 *)pPager->pTmpSpace;
- rc = sqlite3WalCheckpoint(pPager->pWal,
- (pPager->noSync ? 0 : pPager->sync_flags),
- pPager->pageSize, zBuf,
- pPager->xBusyHandler, pPager->pBusyHandlerArg
- );
- }
- return rc;
-}
-
-SQLITE_PRIVATE int sqlite3PagerWalCallback(Pager *pPager){
- return sqlite3WalCallback(pPager->pWal);
-}
-
-/*
-** 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 pMethods->iVersion>=2 && pMethods->xShmOpen!=0;
-}
-
-/*
-** Open a connection to the write-ahead log file for pager pPager. If
-** the log connection is already open, this function is a no-op.
-**
-** The caller must be holding a SHARED lock on the database file to call
-** this function.
-*/
-SQLITE_PRIVATE int sqlite3PagerOpenWal(Pager *pPager, int *pisOpen){
- int rc = SQLITE_OK; /* Return code */
-
- assert( pPager->state>=PAGER_SHARED );
- if( !pPager->pWal ){
- if( !sqlite3PagerWalSupported(pPager) ) return SQLITE_CANTOPEN;
-
- /* Open the connection to the log file. If this operation fails,
- ** (e.g. due to malloc() failure), unlock the database file and
- ** return an error code.
- */
- rc = sqlite3WalOpen(pPager->pVfs, pPager->fd,
- pPager->zFilename, &pPager->pWal);
- if( rc==SQLITE_OK ){
- pPager->journalMode = PAGER_JOURNALMODE_WAL;
- }
- }else{
- *pisOpen = 1;
- }
-
- return rc;
-}
-
-/*
-** 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 = sqlite3OsLock(pPager->fd, SQLITE_LOCK_SHARED);
- if( rc==SQLITE_OK ){
- rc = pagerHasWAL(pPager, &logexists);
- }
- if( rc==SQLITE_OK && logexists ){
- rc = sqlite3WalOpen(pPager->pVfs, pPager->fd,
- pPager->zFilename, &pPager->pWal);
- }
- }
-
- /* 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 = sqlite3OsLock(pPager->fd, SQLITE_LOCK_EXCLUSIVE);
- if( rc==SQLITE_OK ){
- rc = sqlite3WalClose(pPager->pWal,
- (pPager->noSync ? 0 : pPager->sync_flags),
- pPager->pageSize, (u8*)pPager->pTmpSpace
- );
- pPager->pWal = 0;
- }else{
- /* If we cannot get an EXCLUSIVE lock, downgrade the PENDING lock
- ** that we did get back to SHARED. */
- sqlite3OsUnlock(pPager->fd, SQLITE_LOCK_SHARED);
- }
- }
- return rc;
-}
-#endif
-
#endif /* SQLITE_OMIT_DISKIO */
/************** 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 24 bytes in size and consists of the following six
-** big-endian 32-bit unsigned integer values:
-**
-** 0: Magic number. 0x377f0682 (big endian)
-** 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
-**
-** 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 broken into 6 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
-** (a) the first 16 bytes of the frame-header, and
-** (b) the frame data.
-**
-** 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 server 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 or is followed by a commit frame
-** become the value read. If the WAL contains no copies of page P that
-** are valid and which are or are followed by a commit frame, then page
-** P is read from the database file.
-**
-** The reader algorithm in the previous paragraph 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, return the index of the last frame for page P in the WAL,
-** or return NULL if there are no frames for page P in the WAL.
-**
-** 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 the mxFrame field. Each index block contains information on
-** HASHTABLE_NPAGE frames. Each index block contains two sections, a
-** mapping which is a database page number for each frame, and a hash
-** table used to look up frames by page number. The mapping section is
-** an array of HASHTABLE_NPAGE 32-bit page numbers. The first entry on the
-** array is the page number for the first frame; the second entry is the
-** page number for the second frame; and so forth. The last index block
-** holds a total of (mxFrame%HASHTABLE_NPAGE) page numbers. All index
-** blocks other than the last are completely full with HASHTABLE_NPAGE
-** page numbers. All index blocks are the same size; the mapping section
-** of the last index block merely contains unused entries if mxFrame is
-** not an even multiple of HASHTABLE_NPAGE.
-**
-** Even without using the hash table, the last frame for page P
-** can be found by scanning the 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 greater than K. Note that no hash table slot ever
-** contains a zero value.
-**
-** 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
-
-
-
-/* Object declarations */
-typedef struct WalIndexHdr WalIndexHdr;
-typedef struct WalIterator WalIterator;
-
-
-/*
-** 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.
-*/
-struct WalIndexHdr {
- u32 iChange; /* Counter incremented each transaction */
- u16 bigEndCksum; /* True if checksums in WAL are big-endian */
- u16 szPage; /* Database page size in bytes */
- u32 mxFrame; /* Index of last valid frame in the WAL */
- u32 nPage; /* Size of database in pages */
- u32 aSalt[2]; /* Salt-1 and salt-2 values copied from WAL header */
- u32 aCksum[2]; /* Checksum over all prior fields */
-};
-
-/* 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)
-#define WALINDEX_LOCK_RESERVED 8
-
-/* Size of header before each frame in wal */
-#define WAL_FRAME_HDRSIZE 24
-
-/* Size of write ahead log header */
-#define WAL_HDRSIZE 24
-
-/* 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
-
-/*
-** 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)*((szPage)+WAL_FRAME_HDRSIZE) \
-)
-
-/*
-** 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 pFd */
- 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) */
- int szWIndex; /* Size of the wal-index that is mapped in mem */
- volatile u32 *pWiData; /* Pointer to wal-index content in memory */
- u8 lockState; /* SQLITE_SHM_xxxx constant showing lock state */
- u8 readerType; /* SQLITE_SHM_READ or SQLITE_SHM_READ_FULL */
- u8 exclusiveMode; /* Non-zero if connection is in exclusive mode */
- u8 isWindexOpen; /* True if ShmOpen() called on pDbFd */
- WalIndexHdr hdr; /* Wal-index for current snapshot */
- char *zWalName; /* Name of WAL file */
- int szPage; /* Database page size */
- u32 nCkpt; /* Checkpoint sequence counter in the wal-header */
-};
-
-
-/*
-** 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; /* Size of the aSegment[] array */
- int nFinal; /* Elements in aSegment[nSegment-1] */
- struct WalSegment {
- int iNext; /* Next slot in aIndex[] not previously returned */
- u8 *aIndex; /* i0, i1, i2... such that aPgno[iN] ascending */
- u32 *aPgno; /* 256 page numbers. Pointer to Wal.pWiData */
- } aSegment[1]; /* One for every 256 entries in the WAL */
-};
-
-/*
-** 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) \
-)
-
-/*
-** 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];
-
- if( aIn ){
- s1 = aIn[0];
- s2 = aIn[1];
- }else{
- s1 = s2 = 0;
- }
-
- assert( nByte>=8 );
- assert( (nByte&0x00000007)==0 );
-
- if( nativeCksum ){
- do {
- s1 += *aData++ + s2;
- s2 += *aData++ + s1;
- }while( aData<aEnd );
- }else{
- do {
- s1 += BYTESWAP32(aData[0]) + s2;
- s2 += BYTESWAP32(aData[1]) + s1;
- aData += 2;
- }while( aData<aEnd );
- }
-
- aOut[0] = s1;
- aOut[1] = s2;
-}
-
-/*
-** Attempt to change the lock status.
-**
-** When changing the lock status to SQLITE_SHM_READ, store the
-** type of reader lock (either SQLITE_SHM_READ or SQLITE_SHM_READ_FULL)
-** in pWal->readerType.
-*/
-static int walSetLock(Wal *pWal, int desiredStatus){
- int rc = SQLITE_OK; /* Return code */
- if( pWal->exclusiveMode || pWal->lockState==desiredStatus ){
- pWal->lockState = desiredStatus;
- }else{
- int got = pWal->lockState;
- rc = sqlite3OsShmLock(pWal->pDbFd, desiredStatus, &got);
- pWal->lockState = got;
- if( got==SQLITE_SHM_READ_FULL || got==SQLITE_SHM_READ ){
- pWal->readerType = got;
- pWal->lockState = SQLITE_SHM_READ;
- }
- }
- return rc;
-}
-
-/*
-** Write the header information in pWal->hdr into the wal-index.
-**
-** The checksum on pWal->hdr is updated before it is written.
-*/
-static void walIndexWriteHdr(Wal *pWal){
- WalIndexHdr *aHdr;
- walChecksumBytes(1, (u8*)&pWal->hdr,
- sizeof(pWal->hdr) - sizeof(pWal->hdr.aCksum),
- 0, pWal->hdr.aCksum);
- aHdr = (WalIndexHdr*)pWal->pWiData;
- memcpy(&aHdr[1], &pWal->hdr, sizeof(pWal->hdr));
- sqlite3OsShmBarrier(pWal->pDbFd);
- memcpy(&aHdr[0], &pWal->hdr, sizeof(pWal->hdr));
-}
-
-/*
-** 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:
-**
-** 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 wal-header)
-** 12: Salt-2 (copied from the wal-header)
-** 16: Checksum-1.
-** 20: Checksum-2.
-*/
-static void walEncodeFrame(
- Wal *pWal, /* The write-ahead log */
- u32 iPage, /* Database page number for frame */
- u32 nTruncate, /* New db size (or 0 for non-commit frames) */
- u8 *aData, /* Pointer to page data */
- u8 *aFrame /* OUT: Write encoded frame here */
-){
- int nativeCksum; /* True for native byte-order checksums */
- u32 aCksum[2];
- assert( WAL_FRAME_HDRSIZE==24 );
- sqlite3Put4byte(&aFrame[0], iPage);
- sqlite3Put4byte(&aFrame[4], nTruncate);
- memcpy(&aFrame[8], pWal->hdr.aSalt, 8);
-
- nativeCksum = (pWal->hdr.bigEndCksum==SQLITE_BIGENDIAN);
- walChecksumBytes(nativeCksum, aFrame, 16, 0, aCksum);
- walChecksumBytes(nativeCksum, aData, pWal->szPage, aCksum, aCksum);
-
- sqlite3Put4byte(&aFrame[16], aCksum[0]);
- sqlite3Put4byte(&aFrame[20], aCksum[1]);
-}
-
-/*
-** 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
-** *pnTruncate and return true. Return if the frame is not valid.
-*/
-static int walDecodeFrame(
- Wal *pWal, /* The write-ahead log */
- u32 *piPage, /* OUT: Database page number for frame */
- u32 *pnTruncate, /* OUT: New db size (or 0 if not commit) */
- u8 *aData, /* Pointer to page data (for checksum) */
- u8 *aFrame /* Frame data */
-){
- int nativeCksum; /* True for native byte-order checksums */
- u32 aCksum[2];
- assert( WAL_FRAME_HDRSIZE==24 );
-
- /* 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;
- }
-
- /* A frame is only valid if a checksum of the first 16 bytes
- ** of the frame-header, and the frame-data matches
- ** the checksum in the last 8 bytes of the frame-header.
- */
- nativeCksum = (pWal->hdr.bigEndCksum==SQLITE_BIGENDIAN);
- walChecksumBytes(nativeCksum, aFrame, 16, 0, aCksum);
- walChecksumBytes(nativeCksum, aData, pWal->szPage, aCksum, aCksum);
- if( aCksum[0]!=sqlite3Get4byte(&aFrame[16])
- || aCksum[1]!=sqlite3Get4byte(&aFrame[20])
- ){
- /* Checksum failed. */
- return 0;
- }
-
- /* If we reach this point, the frame is valid. Return the page number
- ** and the new database size.
- */
- *piPage = sqlite3Get4byte(&aFrame[0]);
- *pnTruncate = sqlite3Get4byte(&aFrame[4]);
- return 1;
-}
-
-/*
-** 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 and multiple of 256 */
-#define HASHTABLE_DATATYPE u16
-#define HASHTABLE_HASH_1 383 /* Should be prime */
-#define HASHTABLE_NSLOT (HASHTABLE_NPAGE*2) /* Must be a power of 2 */
-#define HASHTABLE_NBYTE (sizeof(HASHTABLE_DATATYPE)*HASHTABLE_NSLOT)
-
-/*
-** Return the index in the Wal.pWiData array that corresponds to
-** frame iFrame.
-**
-** Wal.pWiData is an array of u32 elements that is the wal-index.
-** The array begins with a header and is then followed by alternating
-** "map" and "hash-table" blocks. Each "map" block consists of
-** HASHTABLE_NPAGE u32 elements which are page numbers corresponding
-** to frames in the WAL file.
-**
-** This routine returns an index X such that Wal.pWiData[X] is part
-** of a "map" block that contains the page number of the iFrame-th
-** frame in the WAL file.
-*/
-static int walIndexEntry(u32 iFrame){
- return (
- (WALINDEX_LOCK_OFFSET+WALINDEX_LOCK_RESERVED)/sizeof(u32)
- + (((iFrame-1)/HASHTABLE_NPAGE) * HASHTABLE_NBYTE)/sizeof(u32)
- + (iFrame-1)
- );
-}
-
-/*
-** Return the minimum mapping size in bytes that can be used to read the
-** wal-index up to and including frame iFrame. If iFrame is the last frame
-** in a block of 256 frames, the returned byte-count includes the space
-** required by the 256-byte index block.
-*/
-static int walMappingSize(u32 iFrame){
- const int nByte = (sizeof(u32)*HASHTABLE_NPAGE + HASHTABLE_NBYTE) ;
- return ( WALINDEX_LOCK_OFFSET
- + WALINDEX_LOCK_RESERVED
- + nByte * ((iFrame + HASHTABLE_NPAGE - 1)/HASHTABLE_NPAGE)
- );
-}
-
-/*
-** Release our reference to the wal-index memory map, if we are holding
-** it.
-*/
-static void walIndexUnmap(Wal *pWal){
- if( pWal->pWiData ){
- sqlite3OsShmRelease(pWal->pDbFd);
- pWal->pWiData = 0;
- }
-}
-
-/*
-** Map the wal-index file into memory if it isn't already.
-**
-** The reqSize parameter is the minimum required size of the mapping.
-** A value of -1 means "don't care".
-*/
-static int walIndexMap(Wal *pWal, int reqSize){
- int rc = SQLITE_OK;
- if( pWal->pWiData==0 || reqSize>pWal->szWIndex ){
- walIndexUnmap(pWal);
- rc = sqlite3OsShmGet(pWal->pDbFd, reqSize, &pWal->szWIndex,
- (void volatile**)(char volatile*)&pWal->pWiData);
- if( rc==SQLITE_OK && pWal->pWiData==0 ){
- /* Make sure pWal->pWiData is not NULL while we are holding the
- ** lock on the mapping. */
- assert( pWal->szWIndex==0 );
- pWal->pWiData = &pWal->iCallback;
- }
- if( rc!=SQLITE_OK ){
- walIndexUnmap(pWal);
- }
- }
- return rc;
-}
-
-/*
-** Remap the wal-index so that the mapping covers the full size
-** of the underlying file.
-**
-** If enlargeTo is non-negative, then increase the size of the underlying
-** storage to be at least as big as enlargeTo before remapping.
-*/
-static int walIndexRemap(Wal *pWal, int enlargeTo){
- int rc;
- int sz;
- rc = sqlite3OsShmSize(pWal->pDbFd, enlargeTo, &sz);
- if( rc==SQLITE_OK && sz>pWal->szWIndex ){
- walIndexUnmap(pWal);
- rc = walIndexMap(pWal, sz);
- }
- return rc;
-}
-
-/*
-** Increment by which to increase the wal-index file size.
-*/
-#define WALINDEX_MMAP_INCREMENT (64*1024)
-
-
-/*
-** Compute a hash on a page number. The resulting hash value must land
-** between 0 and (HASHTABLE_NSLOT-1).
-*/
-static int walHash(u32 iPage){
- assert( iPage>0 );
- assert( (HASHTABLE_NSLOT & (HASHTABLE_NSLOT-1))==0 );
- return (iPage*HASHTABLE_HASH_1) & (HASHTABLE_NSLOT-1);
-}
-static int walNextHash(int iPriorHash){
- return (iPriorHash+1)&(HASHTABLE_NSLOT-1);
-}
-
-
-/*
-** Find the hash table and (section of the) page number array used to
-** store data for WAL frame iFrame.
-**
-** Set output variable *paHash to point to the start of the hash table
-** in the wal-index file. Set *piZero to one less than the frame
-** number of the first frame indexed by this hash table. If a
-** slot in the hash table is set to N, it refers to frame number
-** (*piZero+N) in the log.
-**
-** Finally, set *paPgno such that for all frames F between (*piZero+1) and
-** (*piZero+HASHTABLE_NPAGE), (*paPgno)[F] is the database page number
-** associated with frame F.
-*/
-static void walHashFind(
- Wal *pWal, /* WAL handle */
- u32 iFrame, /* Find the hash table indexing this frame */
- volatile HASHTABLE_DATATYPE **paHash, /* OUT: Pointer to hash index */
- volatile u32 **paPgno, /* OUT: Pointer to page number array */
- u32 *piZero /* OUT: Frame associated with *paPgno[0] */
-){
- u32 iZero;
- volatile u32 *aPgno;
- volatile HASHTABLE_DATATYPE *aHash;
-
- iZero = ((iFrame-1)/HASHTABLE_NPAGE) * HASHTABLE_NPAGE;
- aPgno = &pWal->pWiData[walIndexEntry(iZero+1)-iZero-1];
- aHash = (HASHTABLE_DATATYPE *)&aPgno[iZero+HASHTABLE_NPAGE+1];
-
- /* Assert that:
- **
- ** + the mapping is large enough for this hash-table, and
- **
- ** + that aPgno[iZero+1] really is the database page number associated
- ** with the first frame indexed by this hash table.
- */
- assert( (u32*)(&aHash[HASHTABLE_NSLOT])<=&pWal->pWiData[pWal->szWIndex/4] );
- assert( walIndexEntry(iZero+1)==(&aPgno[iZero+1] - pWal->pWiData) );
-
- *paHash = aHash;
- *paPgno = aPgno;
- *piZero = iZero;
-}
-
-
-/*
-** Set an entry in the wal-index that will map database page number
-** pPage into WAL frame iFrame.
-*/
-static int walIndexAppend(Wal *pWal, u32 iFrame, u32 iPage){
- int rc; /* Return code */
- int nMapping; /* Required mapping size in bytes */
-
- /* Make sure the wal-index is mapped. Enlarge the mapping if required. */
- nMapping = walMappingSize(iFrame);
- rc = walIndexMap(pWal, -1);
- while( rc==SQLITE_OK && nMapping>pWal->szWIndex ){
- int nByte = pWal->szWIndex + WALINDEX_MMAP_INCREMENT;
- rc = walIndexRemap(pWal, nByte);
- }
-
- /* Assuming the wal-index file was successfully mapped, find the hash
- ** table and section of of the page number array that pertain to frame
- ** iFrame of the WAL. Then populate the page number array and the hash
- ** table entry.
- */
- if( rc==SQLITE_OK ){
- int iKey; /* Hash table key */
- u32 iZero; /* One less than frame number of aPgno[1] */
- volatile u32 *aPgno; /* Page number array */
- volatile HASHTABLE_DATATYPE *aHash; /* Hash table */
- int idx; /* Value to write to hash-table slot */
- TESTONLY( int nCollide = 0; /* Number of hash collisions */ )
-
- walHashFind(pWal, iFrame, &aHash, &aPgno, &iZero);
- idx = iFrame - iZero;
- if( idx==1 ) memset((void*)aHash, 0, HASHTABLE_NBYTE);
- assert( idx <= HASHTABLE_NSLOT/2 + 1 );
- aPgno[iFrame] = iPage;
- for(iKey=walHash(iPage); aHash[iKey]; iKey=walNextHash(iKey)){
- assert( nCollide++ < idx );
- }
- aHash[iKey] = idx;
-
-#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.
- */
- {
- int i; /* Loop counter */
- int nEntry = 0; /* Number of entries in the hash table */
- for(i=0; i<HASHTABLE_NSLOT; i++){ if( aHash[i] ) nEntry++; }
- assert( nEntry==idx );
- }
-
- /* Verify that the every entry in the mapping region is reachable
- ** via the hash table. This turns out to be a really, really expensive
- ** thing to check, so only do this occasionally - not on every
- ** iteration.
- */
- if( (idx&0x3ff)==0 ){
- int i; /* Loop counter */
- for(i=1; i<=idx; i++){
- for(iKey=walHash(aPgno[i+iZero]); aHash[iKey]; iKey=walNextHash(iKey)){
- if( aHash[iKey]==i ) break;
- }
- assert( aHash[iKey]==i );
- }
- }
-#endif /* SQLITE_ENABLE_EXPENSIVE_ASSERT */
- }
-
-
- return rc;
-}
-
-
-/*
-** Recover the wal-index by reading the write-ahead log file.
-** The caller must hold RECOVER lock on the wal-index file.
-*/
-static int walIndexRecover(Wal *pWal){
- int rc; /* Return Code */
- i64 nSize; /* Size of log file */
- WalIndexHdr hdr; /* Recovered wal-index header */
-
- assert( pWal->lockState>SQLITE_SHM_READ );
- memset(&hdr, 0, sizeof(hdr));
-
- rc = sqlite3OsFileSize(pWal->pWalFd, &nSize);
- if( rc!=SQLITE_OK ){
- return rc;
- }
-
- if( nSize>WAL_HDRSIZE ){
- u8 aBuf[WAL_HDRSIZE]; /* Buffer to load WAL header into */
- u8 *aFrame = 0; /* Malloc'd buffer to load entire frame */
- int szFrame; /* Number of bytes in buffer aFrame[] */
- u8 *aData; /* Pointer to data part of aFrame buffer */
- int iFrame; /* Index of last frame read */
- i64 iOffset; /* Next offset to read from log file */
- int szPage; /* Page size according to the log */
- u32 magic; /* Magic value read from WAL header */
-
- /* Read in the WAL header. */
- rc = sqlite3OsRead(pWal->pWalFd, aBuf, WAL_HDRSIZE, 0);
- if( rc!=SQLITE_OK ){
- return rc;
- }
-
- /* 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
- ** WAL file.
- */
- magic = sqlite3Get4byte(&aBuf[0]);
- szPage = sqlite3Get4byte(&aBuf[8]);
- if( (magic&0xFFFFFFFE)!=WAL_MAGIC
- || szPage&(szPage-1)
- || szPage>SQLITE_MAX_PAGE_SIZE
- || szPage<512
- ){
- goto finished;
- }
- hdr.bigEndCksum = pWal->hdr.bigEndCksum = (magic&0x00000001);
- pWal->szPage = szPage;
- pWal->nCkpt = sqlite3Get4byte(&aBuf[12]);
- memcpy(&pWal->hdr.aSalt, &aBuf[16], 8);
-
- /* Malloc a buffer to read frames into. */
- szFrame = szPage + WAL_FRAME_HDRSIZE;
- aFrame = (u8 *)sqlite3_malloc(szFrame);
- if( !aFrame ){
- return SQLITE_NOMEM;
- }
- aData = &aFrame[WAL_FRAME_HDRSIZE];
-
- /* 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 */
- int isValid; /* True if this frame is valid */
-
- /* Read and decode the next log frame. */
- rc = sqlite3OsRead(pWal->pWalFd, aFrame, szFrame, iOffset);
- if( rc!=SQLITE_OK ) break;
- isValid = walDecodeFrame(pWal, &pgno, &nTruncate, aData, aFrame);
- if( !isValid ) break;
- rc = walIndexAppend(pWal, ++iFrame, pgno);
- if( rc!=SQLITE_OK ) break;
-
- /* If nTruncate is non-zero, this is a commit record. */
- if( nTruncate ){
- hdr.mxFrame = iFrame;
- hdr.nPage = nTruncate;
- hdr.szPage = szPage;
- }
- }
-
- sqlite3_free(aFrame);
- }else{
- memset(&hdr, 0, sizeof(hdr));
- }
-
-finished:
- if( rc==SQLITE_OK && hdr.mxFrame==0 ){
- rc = walIndexRemap(pWal, WALINDEX_MMAP_INCREMENT);
- }
- if( rc==SQLITE_OK ){
- memcpy(&pWal->hdr, &hdr, sizeof(hdr));
- walIndexWriteHdr(pWal);
- }
- return rc;
-}
-
-/*
-** Close an open wal-index.
-*/
-static void walIndexClose(Wal *pWal, int isDelete){
- if( pWal->isWindexOpen ){
- int notUsed;
- sqlite3OsShmLock(pWal->pDbFd, SQLITE_SHM_UNLOCK, &notUsed);
- sqlite3OsShmClose(pWal->pDbFd, isDelete);
- pWal->isWindexOpen = 0;
- }
-}
-
-/*
-** Open a connection to the log file associated with database zDb. The
-** database file does not actually have to exist. zDb is used only to
-** figure out the name of the log file to open. If the log file does not
-** exist it is created by this call.
-**
-** A SHARED lock should be held on the database file when this function
-** is called. The purpose of this SHARED lock is to prevent any other
-** client from unlinking the log or wal-index file. If another process
-** were to do this just after this client opened one of these files, the
-** system would be badly broken.
-**
-** If the log file is successfully opened, SQLITE_OK is returned and
-** *ppWal is set to point to a new WAL handle. If an error occurs,
-** an SQLite error code is returned and *ppWal is left unmodified.
-*/
-SQLITE_PRIVATE int sqlite3WalOpen(
- sqlite3_vfs *pVfs, /* vfs module to open wal and wal-index */
- sqlite3_file *pDbFd, /* The open database file */
- const char *zDbName, /* Name of the database file */
- Wal **ppWal /* OUT: Allocated Wal handle */
-){
- int rc; /* Return Code */
- Wal *pRet; /* Object to allocate and return */
- int flags; /* Flags passed to OsOpen() */
- char *zWal; /* Name of write-ahead log file */
- int nWal; /* Length of zWal in bytes */
-
- assert( zDbName && zDbName[0] );
- assert( pDbFd );
-
- /* Allocate an instance of struct Wal to return. */
- *ppWal = 0;
- nWal = sqlite3Strlen30(zDbName) + 5;
- pRet = (Wal*)sqlite3MallocZero(sizeof(Wal) + pVfs->szOsFile + nWal);
- if( !pRet ){
- return SQLITE_NOMEM;
- }
-
- pRet->pVfs = pVfs;
- pRet->pWalFd = (sqlite3_file *)&pRet[1];
- pRet->pDbFd = pDbFd;
- sqlite3_randomness(8, &pRet->hdr.aSalt);
- pRet->zWalName = zWal = pVfs->szOsFile + (char*)pRet->pWalFd;
- sqlite3_snprintf(nWal, zWal, "%s-wal", zDbName);
- rc = sqlite3OsShmOpen(pDbFd);
-
- /* Open file handle on the write-ahead log file. */
- if( rc==SQLITE_OK ){
- pRet->isWindexOpen = 1;
- flags = (SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|SQLITE_OPEN_MAIN_JOURNAL);
- rc = sqlite3OsOpen(pVfs, zWal, pRet->pWalFd, flags, &flags);
- }
-
- if( rc!=SQLITE_OK ){
- walIndexClose(pRet, 0);
- sqlite3OsClose(pRet->pWalFd);
- sqlite3_free(pRet);
- }else{
- *ppWal = pRet;
- }
- return rc;
-}
-
-/*
-** Find the smallest page number out of all pages held in the WAL that
-** has not been returned by any prior invocation of this method on the
-** same WalIterator object. Write into *piFrame the frame index where
-** that page was last written into the WAL. Write into *piPage the page
-** number.
-**
-** Return 0 on success. If there are no pages in the WAL with a page
-** number larger than *piPage, then return 1.
-*/
-static int walIteratorNext(
- WalIterator *p, /* Iterator */
- u32 *piPage, /* OUT: The page number of the next page */
- u32 *piFrame /* OUT: Wal frame index of next page */
-){
- u32 iMin; /* Result pgno must be greater than iMin */
- u32 iRet = 0xFFFFFFFF; /* 0xffffffff is never a valid page number */
- int i; /* For looping through segments */
- int nBlock = p->nFinal; /* Number of entries in current segment */
-
- iMin = p->iPrior;
- assert( iMin<0xffffffff );
- for(i=p->nSegment-1; i>=0; i--){
- struct WalSegment *pSegment = &p->aSegment[i];
- while( pSegment->iNext<nBlock ){
- u32 iPg = pSegment->aPgno[pSegment->aIndex[pSegment->iNext]];
- if( iPg>iMin ){
- if( iPg<iRet ){
- iRet = iPg;
- *piFrame = i*256 + 1 + pSegment->aIndex[pSegment->iNext];
- }
- break;
- }
- pSegment->iNext++;
- }
- nBlock = 256;
- }
-
- *piPage = p->iPrior = iRet;
- return (iRet==0xFFFFFFFF);
-}
-
-
-static void walMergesort8(
- Pgno *aContent, /* Pages in wal */
- u8 *aBuffer, /* Buffer of at least *pnList items to use */
- u8 *aList, /* IN/OUT: List to sort */
- int *pnList /* IN/OUT: Number of elements in aList[] */
-){
- int nList = *pnList;
- if( nList>1 ){
- int nLeft = nList / 2; /* Elements in left list */
- int nRight = nList - nLeft; /* Elements in right list */
- u8 *aLeft = aList; /* Left list */
- u8 *aRight = &aList[nLeft]; /* Right list */
- int iLeft = 0; /* Current index in aLeft */
- int iRight = 0; /* Current index in aright */
- int iOut = 0; /* Current index in output buffer */
-
- /* TODO: Change to non-recursive version. */
- walMergesort8(aContent, aBuffer, aLeft, &nLeft);
- walMergesort8(aContent, aBuffer, aRight, &nRight);
-
- while( iRight<nRight || iLeft<nLeft ){
- u8 logpage;
- Pgno dbpage;
-
- if( (iLeft<nLeft)
- && (iRight>=nRight || aContent[aLeft[iLeft]]<aContent[aRight[iRight]])
- ){
- logpage = aLeft[iLeft++];
- }else{
- logpage = aRight[iRight++];
- }
- dbpage = aContent[logpage];
-
- aBuffer[iOut++] = logpage;
- if( iLeft<nLeft && aContent[aLeft[iLeft]]==dbpage ) iLeft++;
-
- assert( iLeft>=nLeft || aContent[aLeft[iLeft]]>dbpage );
- assert( iRight>=nRight || aContent[aRight[iRight]]>dbpage );
- }
- memcpy(aList, aBuffer, sizeof(aList[0])*iOut);
- *pnList = iOut;
- }
-
-#ifdef SQLITE_DEBUG
- {
- int i;
- for(i=1; i<*pnList; i++){
- assert( aContent[aList[i]] > aContent[aList[i-1]] );
- }
- }
-#endif
-}
-
-/*
-** Map the wal-index into memory owned by this thread, if it is not
-** mapped already. Then construct a WalInterator object that can be
-** used to loop over all pages in the WAL in ascending order.
-**
-** On success, make *pp point to the newly allocated WalInterator object
-** return SQLITE_OK. Otherwise, leave *pp unchanged and return an error
-** code.
-**
-** The calling routine should invoke walIteratorFree() to destroy the
-** WalIterator object when it has finished with it. The caller must
-** also unmap the wal-index. But the wal-index must not be unmapped
-** prior to the WalIterator object being destroyed.
-*/
-static int walIteratorInit(Wal *pWal, WalIterator **pp){
- u32 *aData; /* Content of the wal-index file */
- WalIterator *p; /* Return value */
- int nSegment; /* Number of segments to merge */
- u32 iLast; /* Last frame in log */
- int nByte; /* Number of bytes to allocate */
- int i; /* Iterator variable */
- int nFinal; /* Number of unindexed entries */
- u8 *aTmp; /* Temp space used by merge-sort */
- int rc; /* Return code of walIndexMap() */
- u8 *aSpace; /* Surplus space on the end of the allocation */
-
- /* Make sure the wal-index is mapped into local memory */
- rc = walIndexMap(pWal, walMappingSize(pWal->hdr.mxFrame));
- if( rc!=SQLITE_OK ){
- return rc;
- }
-
- /* This routine only runs while holding SQLITE_SHM_CHECKPOINT. No other
- ** thread is able to write to shared memory while this routine is
- ** running (or, indeed, while the WalIterator object exists). Hence,
- ** we can cast off the volatile qualifacation from shared memory
- */
- assert( pWal->lockState==SQLITE_SHM_CHECKPOINT );
- aData = (u32*)pWal->pWiData;
-
- /* Allocate space for the WalIterator object */
- iLast = pWal->hdr.mxFrame;
- nSegment = (iLast >> 8) + 1;
- nFinal = (iLast & 0x000000FF);
- nByte = sizeof(WalIterator) + (nSegment+1)*(sizeof(struct WalSegment)+256);
- p = (WalIterator *)sqlite3_malloc(nByte);
- if( !p ){
- return SQLITE_NOMEM;
- }
- memset(p, 0, nByte);
-
- /* Initialize the WalIterator object. Each 256-entry segment is
- ** presorted in order to make iterating through all entries much
- ** faster.
- */
- p->nSegment = nSegment;
- aSpace = (u8 *)&p->aSegment[nSegment];
- aTmp = &aSpace[nSegment*256];
- for(i=0; i<nSegment; i++){
- int j;
- int nIndex = (i==nSegment-1) ? nFinal : 256;
- p->aSegment[i].aPgno = &aData[walIndexEntry(i*256+1)];
- p->aSegment[i].aIndex = aSpace;
- for(j=0; j<nIndex; j++){
- aSpace[j] = j;
- }
- walMergesort8(p->aSegment[i].aPgno, aTmp, aSpace, &nIndex);
- memset(&aSpace[nIndex], aSpace[nIndex-1], 256-nIndex);
- aSpace += 256;
- p->nFinal = nIndex;
- }
-
- /* Return the fully initializd WalIterator object */
- *pp = p;
- return SQLITE_OK ;
-}
-
-/*
-** Free an iterator allocated by walIteratorInit().
-*/
-static void walIteratorFree(WalIterator *p){
- sqlite3_free(p);
-}
-
-/*
-** Checkpoint the contents of the log file.
-*/
-static int walCheckpoint(
- Wal *pWal, /* Wal connection */
- int sync_flags, /* Flags for OsSync() (or 0) */
- int nBuf, /* Size of zBuf in bytes */
- u8 *zBuf /* Temporary buffer to use */
-){
- int rc; /* Return code */
- int szPage = pWal->hdr.szPage; /* Database page-size */
- WalIterator *pIter = 0; /* Wal iterator context */
- u32 iDbpage = 0; /* Next database page to write */
- u32 iFrame = 0; /* Wal frame containing data for iDbpage */
-
- /* Allocate the iterator */
- rc = walIteratorInit(pWal, &pIter);
- if( rc!=SQLITE_OK || pWal->hdr.mxFrame==0 ){
- goto out;
- }
-
- if( pWal->hdr.szPage!=nBuf ){
- rc = SQLITE_CORRUPT_BKPT;
- goto out;
- }
-
- /* Sync the log file to disk */
- if( sync_flags ){
- rc = sqlite3OsSync(pWal->pWalFd, sync_flags);
- if( rc!=SQLITE_OK ) goto out;
- }
-
- /* Iterate through the contents of the log, copying data to the db file. */
- while( 0==walIteratorNext(pIter, &iDbpage, &iFrame) ){
- rc = sqlite3OsRead(pWal->pWalFd, zBuf, szPage,
- walFrameOffset(iFrame, szPage) + WAL_FRAME_HDRSIZE
- );
- if( rc!=SQLITE_OK ) goto out;
- rc = sqlite3OsWrite(pWal->pDbFd, zBuf, szPage, (iDbpage-1)*szPage);
- if( rc!=SQLITE_OK ) goto out;
- }
-
- /* Truncate the database file */
- rc = sqlite3OsTruncate(pWal->pDbFd, ((i64)pWal->hdr.nPage*(i64)szPage));
- if( rc!=SQLITE_OK ) goto out;
-
- /* Sync the database file. If successful, update the wal-index. */
- if( sync_flags ){
- rc = sqlite3OsSync(pWal->pDbFd, sync_flags);
- if( rc!=SQLITE_OK ) goto out;
- }
- pWal->hdr.mxFrame = 0;
- pWal->nCkpt++;
- sqlite3Put4byte((u8*)pWal->hdr.aSalt,
- 1 + sqlite3Get4byte((u8*)pWal->hdr.aSalt));
- sqlite3_randomness(4, &pWal->hdr.aSalt[1]);
- walIndexWriteHdr(pWal);
-
- out:
- walIteratorFree(pIter);
- return rc;
-}
-
-/*
-** Close a connection to a log file.
-*/
-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 = SQLITE_OK;
- if( pWal ){
- int isDelete = 0; /* True to unlink wal and wal-index files */
-
- /* 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
- ** the database. In this case checkpoint the database and unlink both
- ** the wal and wal-index files.
- **
- ** The EXCLUSIVE lock is not released before returning.
- */
- rc = sqlite3OsLock(pWal->pDbFd, SQLITE_LOCK_EXCLUSIVE);
- if( rc==SQLITE_OK ){
- rc = sqlite3WalCheckpoint(pWal, sync_flags, nBuf, zBuf, 0, 0);
- if( rc==SQLITE_OK ){
- isDelete = 1;
- }
- walIndexUnmap(pWal);
- }
-
- walIndexClose(pWal, isDelete);
- sqlite3OsClose(pWal->pWalFd);
- if( isDelete ){
- sqlite3OsDelete(pWal->pVfs, pWal->zWalName, 0);
- }
- sqlite3_free(pWal);
- }
- return rc;
-}
-
-/*
-** Try to read the wal-index header. Return 0 on success and 1 if
-** there is a problem.
-**
-** The wal-index is in shared memory. Another thread or process might
-** be writing the header at the same time this procedure is trying to
-** read it, which might result in inconsistency. A dirty read is detected
-** by verifying a checksum on the header.
-**
-** If and only if the read is consistent and the header is different from
-** pWal->hdr, then pWal->hdr is updated to the content of the new header
-** and *pChanged is set to 1.
-**
-** If the checksum cannot be verified return non-zero. If the header
-** is read successfully and the checksum verified, return zero.
-*/
-int walIndexTryHdr(Wal *pWal, int *pChanged){
- u32 aCksum[2]; /* Checksum on the header content */
- WalIndexHdr h1, h2; /* Two copies of the header content */
- WalIndexHdr *aHdr; /* Header in shared memory */
-
- assert( pWal->pWiData );
- if( pWal->szWIndex==0 ){
- /* The wal-index is of size 0 bytes. This is handled in the same way
- ** as an invalid header. The caller will run recovery to construct
- ** a valid wal-index file before accessing the database.
- */
- return 1;
- }
-
- /* Read the header. The caller may or may not have an exclusive
- ** (WRITE, PENDING, CHECKPOINT or RECOVER) lock on the wal-index
- ** file, 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->pWiData;
- memcpy(&h1, &aHdr[0], sizeof(h1));
- sqlite3OsShmBarrier(pWal->pDbFd);
- memcpy(&h2, &aHdr[1], sizeof(h2));
-
- if( memcmp(&h1, &h2, sizeof(h1))!=0 ){
- return 1; /* Dirty read */
- }
- if( h1.szPage==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 */
- }
-
- if( memcmp(&pWal->hdr, &h1, sizeof(WalIndexHdr)) ){
- *pChanged = 1;
- memcpy(&pWal->hdr, &h1, sizeof(WalIndexHdr));
- pWal->szPage = pWal->hdr.szPage;
- }
-
- /* The header was successfully read. Return zero. */
- return 0;
-}
-
-/*
-** Read the wal-index header from the wal-index and into pWal->hdr.
-** If the wal-header appears to be corrupt, try to recover the log
-** before returning.
-**
-** Set *pChanged to 1 if the wal-index header value in pWal->hdr is
-** changed by this opertion. If pWal->hdr is unchanged, set *pChanged
-** to 0.
-**
-** This routine also maps the wal-index content into memory and assigns
-** ownership of that mapping to the current thread. In some implementations,
-** only one thread at a time can hold a mapping of the wal-index. Hence,
-** the caller should strive to invoke walIndexUnmap() as soon as possible
-** after this routine returns.
-**
-** If the wal-index header is successfully read, return SQLITE_OK.
-** Otherwise an SQLite error code.
-*/
-static int walIndexReadHdr(Wal *pWal, int *pChanged){
- int rc; /* Return code */
- int lockState; /* pWal->lockState before running recovery */
-
- assert( pWal->lockState>=SQLITE_SHM_READ );
- assert( pChanged );
- rc = walIndexMap(pWal, -1);
- if( rc!=SQLITE_OK ){
- return rc;
- }
-
- /* First attempt to read the wal-index header. This may fail for one
- ** of two reasons: (a) the wal-index does not yet exist or has been
- ** corrupted and needs to be constructed by running recovery, or (b)
- ** the caller is only holding a READ lock and made a dirty read of
- ** the wal-index header.
- **
- ** A dirty read of the wal-index header occurs if another thread or
- ** process happens to be writing to the wal-index header at roughly
- ** the same time as this thread is reading it. In this case it is
- ** possible that an inconsistent header is read (which is detected
- ** using the header checksum mechanism).
- */
- if( walIndexTryHdr(pWal, pChanged)==0 ){
- return SQLITE_OK;
- }
-
- /* If the first attempt to read the header failed, lock the wal-index
- ** file with an exclusive lock and try again. If the header checksum
- ** verification fails again, we can be sure that it is not simply a
- ** dirty read, but that the wal-index really does need to be
- ** reconstructed by running log recovery.
- **
- ** In the paragraph above, an "exclusive lock" may be any of WRITE,
- ** PENDING, CHECKPOINT or RECOVER. If any of these are already held,
- ** no locking operations are required. If the caller currently holds
- ** a READ lock, then upgrade to a RECOVER lock before re-reading the
- ** wal-index header and revert to a READ lock before returning.
- */
- lockState = pWal->lockState;
- if( lockState>SQLITE_SHM_READ
- || SQLITE_OK==(rc = walSetLock(pWal, SQLITE_SHM_RECOVER))
- ){
- if( walIndexTryHdr(pWal, pChanged) ){
- *pChanged = 1;
- rc = walIndexRecover(pWal);
- }
- if( lockState==SQLITE_SHM_READ ){
- walSetLock(pWal, SQLITE_SHM_READ);
- }
- }
-
- return rc;
-}
-
-/*
-** Take a snapshot of the state of the WAL and wal-index for the current
-** instant in time. The current thread will continue to use this snapshot.
-** Other threads might containing appending to the WAL and wal-index but
-** the extra content appended will be ignored by the current thread.
-**
-** A snapshot is like a read transaction.
-**
-** No other threads are allowed to run a checkpoint while this thread is
-** holding the snapshot since a checkpoint would remove data out from under
-** this thread.
-**
-** If this call obtains a new read-lock and the database contents have been
-** modified since the most recent call to WalCloseSnapshot() on this Wal
-** connection, then *pChanged is set to 1 before returning. Otherwise, it
-** is left unmodified. This is used by the pager layer to determine whether
-** or not any cached pages may be safely reused.
-*/
-SQLITE_PRIVATE int sqlite3WalOpenSnapshot(Wal *pWal, int *pChanged){
- int rc; /* Return code */
-
- rc = walSetLock(pWal, SQLITE_SHM_READ);
- assert( rc!=SQLITE_OK || pWal->lockState==SQLITE_SHM_READ );
-
- if( rc==SQLITE_OK ){
- rc = walIndexReadHdr(pWal, pChanged);
- if( rc!=SQLITE_OK ){
- /* An error occured while attempting log recovery. */
- sqlite3WalCloseSnapshot(pWal);
- }
- }
-
- walIndexUnmap(pWal);
- return rc;
-}
-
-/*
-** Unlock the current snapshot.
-*/
-SQLITE_PRIVATE void sqlite3WalCloseSnapshot(Wal *pWal){
- assert( pWal->lockState==SQLITE_SHM_READ
- || pWal->lockState==SQLITE_SHM_UNLOCK
- );
- walSetLock(pWal, SQLITE_SHM_UNLOCK);
-}
-
-/*
-** Read a page from the log, if it is present.
-*/
-SQLITE_PRIVATE int sqlite3WalRead(
- Wal *pWal, /* WAL handle */
- Pgno pgno, /* Database page number to read data for */
- int *pInWal, /* OUT: True if data is read from WAL */
- int nOut, /* Size of buffer pOut in bytes */
- u8 *pOut /* Buffer to write page data to */
-){
- int rc; /* Return code */
- u32 iRead = 0; /* If !=0, WAL frame to return data from */
- u32 iLast = pWal->hdr.mxFrame; /* Last page in WAL for this reader */
- int iHash; /* Used to loop through N hash tables */
-
- /* If the "last page" field of the wal-index header snapshot is 0, then
- ** no data will be read from the wal under any circumstances. Return early
- ** in this case to avoid the walIndexMap/Unmap overhead.
- */
- if( iLast==0 ){
- *pInWal = 0;
- return SQLITE_OK;
- }
-
- /* Ensure the wal-index is mapped. */
- assert( pWal->lockState==SQLITE_SHM_READ||pWal->lockState==SQLITE_SHM_WRITE );
- rc = walIndexMap(pWal, walMappingSize(iLast));
- if( rc!=SQLITE_OK ){
- return rc;
- }
-
- /* Search the hash table or tables for an entry matching page number
- ** pgno. Each iteration of the following for() loop searches one
- ** hash table (each hash table indexes up to HASHTABLE_NPAGE frames).
- **
- ** This code may run concurrently to the code in walIndexAppend()
- ** that adds entries to the wal-index (and possibly to this hash
- ** table). This means the value just read from the hash
- ** slot (aHash[iKey]) may have been added before or after the
- ** current read transaction was opened. Values added after the
- ** read transaction was opened may have been written incorrectly -
- ** i.e. these slots may contain garbage data. However, we assume
- ** that any slots written before the current read transaction was
- ** opened remain unmodified.
- **
- ** For the reasons above, the if(...) condition featured in the inner
- ** loop of the following block is more stringent that would be required
- ** if we had exclusive access to the hash-table:
- **
- ** (aPgno[iFrame]==pgno):
- ** This condition filters out normal hash-table collisions.
- **
- ** (iFrame<=iLast):
- ** This condition filters out entries that were added to the hash
- ** table after the current read-transaction had started.
- **
- ** (iFrame>iRead):
- ** This filters out a dangerous class of garbage data. The
- ** garbage hash slot may refer to a frame with the correct page
- ** number, but not the most recent version of the frame. For
- ** example, if at the start of the read-transaction the WAL
- ** contains three copies of the desired page in frames 2, 3 and 4,
- ** the hash table may contain the following:
- **
- ** { ..., 2, 3, 4, 99, 99, ..... }
- **
- ** The correct answer is to read data from frame 4. But a
- ** dirty-read may potentially cause the hash-table to appear as
- ** follows to the reader:
- **
- ** { ..., 2, 3, 4, 3, 99, ..... }
- **
- ** Without this part of the if(...) clause, the reader might
- ** incorrectly read data from frame 3 instead of 4. This would be
- ** an error.
- **
- ** It is not actually clear to the developers that such a dirty-read
- ** can occur. But if it does, it should not cause any problems.
- */
- for(iHash=iLast; iHash>0 && iRead==0; iHash-=HASHTABLE_NPAGE){
- volatile HASHTABLE_DATATYPE *aHash; /* Pointer to hash table */
- volatile u32 *aPgno; /* Pointer to array of page numbers */
- u32 iZero; /* Frame number corresponding to aPgno[0] */
- int iKey; /* Hash slot index */
- int mxHash; /* upper bound on aHash[] values */
-
- walHashFind(pWal, iHash, &aHash, &aPgno, &iZero);
- mxHash = iLast - iZero;
- if( mxHash > HASHTABLE_NPAGE ) mxHash = HASHTABLE_NPAGE;
- for(iKey=walHash(pgno); aHash[iKey]; iKey=walNextHash(iKey)){
- u32 iFrame = aHash[iKey] + iZero;
- if( iFrame<=iLast && aPgno[iFrame]==pgno && iFrame>iRead ){
- iRead = iFrame;
- }
- }
- }
- assert( iRead==0 || pWal->pWiData[walIndexEntry(iRead)]==pgno );
-
-#ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT
- /* If expensive assert() statements are available, do a linear search
- ** of the wal-index file content. Make sure the results agree with the
- ** result obtained using the hash indexes above. */
- {
- u32 iRead2 = 0;
- u32 iTest;
- for(iTest=iLast; iTest>0; iTest--){
- if( pWal->pWiData[walIndexEntry(iTest)]==pgno ){
- iRead2 = iTest;
- break;
- }
- }
- assert( iRead==iRead2 );
- }
-#endif
-
- /* If iRead is non-zero, then it is the log frame number that contains the
- ** required page. Read and return data from the log file.
- */
- walIndexUnmap(pWal);
- if( iRead ){
- i64 iOffset = walFrameOffset(iRead, pWal->hdr.szPage) + WAL_FRAME_HDRSIZE;
- *pInWal = 1;
- return sqlite3OsRead(pWal->pWalFd, pOut, nOut, iOffset);
- }
-
- *pInWal = 0;
- return SQLITE_OK;
-}
-
-
-/*
-** Set *pPgno to the size of the database file (or zero, if unknown).
-*/
-SQLITE_PRIVATE void sqlite3WalDbsize(Wal *pWal, Pgno *pPgno){
- assert( pWal->lockState==SQLITE_SHM_READ
- || pWal->lockState==SQLITE_SHM_WRITE );
- *pPgno = pWal->hdr.nPage;
-}
-
-/*
-** This function returns SQLITE_OK if the caller may write to the database.
-** Otherwise, if the caller is operating on a snapshot that has already
-** been overwritten by another writer, SQLITE_BUSY is returned.
-*/
-SQLITE_PRIVATE int sqlite3WalWriteLock(Wal *pWal, int op){
- int rc = SQLITE_OK;
- if( op ){
- assert( pWal->lockState==SQLITE_SHM_READ );
- rc = walSetLock(pWal, SQLITE_SHM_WRITE);
-
- /* If this connection is not reading the most recent database snapshot,
- ** it is not possible to write to the database. In this case release
- ** the write locks and return SQLITE_BUSY.
- */
- if( rc==SQLITE_OK ){
- rc = walIndexMap(pWal, sizeof(WalIndexHdr));
- if( rc==SQLITE_OK
- && memcmp(&pWal->hdr, (void*)pWal->pWiData, sizeof(WalIndexHdr))
- ){
- rc = SQLITE_BUSY;
- }
- walIndexUnmap(pWal);
- if( rc!=SQLITE_OK ){
- walSetLock(pWal, SQLITE_SHM_READ);
- }
- }
- }else if( pWal->lockState==SQLITE_SHM_WRITE ){
- rc = walSetLock(pWal, SQLITE_SHM_READ);
- }
- return rc;
-}
-
-/*
-** Remove entries from the hash table that point to WAL slots greater
-** than pWal->hdr.mxFrame.
-**
-** This function is called whenever pWal->hdr.mxFrame is decreased due
-** to a rollback or savepoint.
-**
-** At most only the very last hash table 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.
-*/
-static void walCleanupHash(Wal *pWal){
- volatile HASHTABLE_DATATYPE *aHash; /* Pointer to hash table to clear */
- volatile u32 *aPgno; /* Unused return from walHashFind() */
- u32 iZero; /* frame == (aHash[x]+iZero) */
- int iLimit; /* Zero values greater than this */
-
- assert( pWal->lockState==SQLITE_SHM_WRITE );
- walHashFind(pWal, pWal->hdr.mxFrame+1, &aHash, &aPgno, &iZero);
- iLimit = pWal->hdr.mxFrame - iZero;
- if( iLimit>0 ){
- int i; /* Used to iterate through aHash[] */
- for(i=0; i<HASHTABLE_NSLOT; i++){
- if( aHash[i]>iLimit ){
- aHash[i] = 0;
- }
- }
- }
-
-#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.
- */
- {
- int i; /* Loop counter */
- int iKey; /* Hash key */
- for(i=1; i<=iLimit; i++){
- for(iKey=walHash(aPgno[i+iZero]); aHash[iKey]; iKey=walNextHash(iKey)){
- if( aHash[iKey]==i ) break;
- }
- assert( aHash[iKey]==i );
- }
- }
-#endif /* SQLITE_ENABLE_EXPENSIVE_ASSERT */
-}
-
-/*
-** If any data has been written (but not committed) to the log file, this
-** function moves the write-pointer back to the start of the transaction.
-**
-** Additionally, the callback function is invoked for each frame written
-** to the log since the start of the transaction. If the callback returns
-** other than SQLITE_OK, it is not invoked again and the error code is
-** returned to the caller.
-**
-** Otherwise, if the callback function does not return an error, this
-** function returns SQLITE_OK.
-*/
-SQLITE_PRIVATE int sqlite3WalUndo(Wal *pWal, int (*xUndo)(void *, Pgno), void *pUndoCtx){
- int rc = SQLITE_OK;
- if( pWal->lockState==SQLITE_SHM_WRITE ){
- int unused;
- Pgno iMax = pWal->hdr.mxFrame;
- Pgno iFrame;
-
- assert( pWal->pWiData==0 );
- rc = walIndexReadHdr(pWal, &unused);
- if( rc==SQLITE_OK ){
- walCleanupHash(pWal);
- for(iFrame=pWal->hdr.mxFrame+1; rc==SQLITE_OK && iFrame<=iMax; iFrame++){
- assert( pWal->lockState==SQLITE_SHM_WRITE );
- rc = xUndo(pUndoCtx, pWal->pWiData[walIndexEntry(iFrame)]);
- }
- }
- walIndexUnmap(pWal);
- }
- return rc;
-}
-
-/* Return an integer that records the current (uncommitted) write
-** position in the WAL
-*/
-SQLITE_PRIVATE u32 sqlite3WalSavepoint(Wal *pWal){
- assert( pWal->lockState==SQLITE_SHM_WRITE );
- return pWal->hdr.mxFrame;
-}
-
-/* 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 iFrame){
- int rc = SQLITE_OK;
- assert( pWal->lockState==SQLITE_SHM_WRITE );
-
- assert( iFrame<=pWal->hdr.mxFrame );
- if( iFrame<pWal->hdr.mxFrame ){
- rc = walIndexMap(pWal, walMappingSize(pWal->hdr.mxFrame));
- pWal->hdr.mxFrame = iFrame;
- if( rc==SQLITE_OK ){
- walCleanupHash(pWal);
- walIndexUnmap(pWal);
- }
- }
- return rc;
-}
-
-/*
-** Write a set of frames to the log. The caller must hold the write-lock
-** on the log file (obtained using sqlite3WalWriteLock()).
-*/
-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 */
- u8 aFrame[WAL_FRAME_HDRSIZE]; /* Buffer to assemble frame-header in */
- PgHdr *p; /* Iterator to run through pList with. */
- PgHdr *pLast = 0; /* Last frame in list */
- int nLast = 0; /* Number of extra copies of last page */
-
- assert( pList );
- assert( pWal->lockState==SQLITE_SHM_WRITE );
- assert( pWal->pWiData==0 );
-
- /* 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.
- */
- iFrame = pWal->hdr.mxFrame;
- if( iFrame==0 ){
- u8 aWalHdr[WAL_HDRSIZE]; /* Buffer to assembly wal-header in */
- sqlite3Put4byte(&aWalHdr[0], (WAL_MAGIC | SQLITE_BIGENDIAN));
- sqlite3Put4byte(&aWalHdr[4], 3007000);
- sqlite3Put4byte(&aWalHdr[8], szPage);
- pWal->szPage = szPage;
- pWal->hdr.bigEndCksum = SQLITE_BIGENDIAN;
- sqlite3Put4byte(&aWalHdr[12], pWal->nCkpt);
- memcpy(&aWalHdr[16], pWal->hdr.aSalt, 8);
- rc = sqlite3OsWrite(pWal->pWalFd, aWalHdr, sizeof(aWalHdr), 0);
- if( rc!=SQLITE_OK ){
- return rc;
- }
- }
- assert( pWal->szPage==szPage );
-
- /* Write the log file. */
- for(p=pList; p; p=p->pDirty){
- u32 nDbsize; /* Db-size field for frame header */
- i64 iOffset; /* Write offset in log file */
-
- iOffset = walFrameOffset(++iFrame, szPage);
-
- /* Populate and write the frame header */
- nDbsize = (isCommit && p->pDirty==0) ? nTruncate : 0;
- walEncodeFrame(pWal, p->pgno, nDbsize, p->pData, aFrame);
- rc = sqlite3OsWrite(pWal->pWalFd, aFrame, sizeof(aFrame), iOffset);
- if( rc!=SQLITE_OK ){
- return rc;
- }
-
- /* Write the page data */
- rc = sqlite3OsWrite(pWal->pWalFd, p->pData, szPage, iOffset+sizeof(aFrame));
- if( rc!=SQLITE_OK ){
- return rc;
- }
- pLast = p;
- }
-
- /* Sync the log file if the 'isSync' flag was specified. */
- if( sync_flags ){
- i64 iSegment = sqlite3OsSectorSize(pWal->pWalFd);
- i64 iOffset = walFrameOffset(iFrame+1, szPage);
-
- assert( isCommit );
- assert( iSegment>0 );
-
- iSegment = (((iOffset+iSegment-1)/iSegment) * iSegment);
- while( iOffset<iSegment ){
- walEncodeFrame(pWal, pLast->pgno, nTruncate, pLast->pData, aFrame);
- rc = sqlite3OsWrite(pWal->pWalFd, aFrame, sizeof(aFrame), iOffset);
- if( rc!=SQLITE_OK ){
- return rc;
- }
-
- iOffset += WAL_FRAME_HDRSIZE;
- rc = sqlite3OsWrite(pWal->pWalFd, pLast->pData, szPage, iOffset);
- if( rc!=SQLITE_OK ){
- return rc;
- }
- nLast++;
- iOffset += szPage;
- }
-
- rc = sqlite3OsSync(pWal->pWalFd, sync_flags);
- }
- assert( pWal->pWiData==0 );
-
- /* Append data to the wal-index. It is not necessary to lock the
- ** wal-index to do this as the SQLITE_SHM_WRITE lock held on the wal-index
- ** guarantees that there are no other writers, and no data that may
- ** be in use by existing readers is being overwritten.
- */
- iFrame = pWal->hdr.mxFrame;
- for(p=pList; p && rc==SQLITE_OK; p=p->pDirty){
- iFrame++;
- rc = walIndexAppend(pWal, iFrame, p->pgno);
- }
- while( nLast>0 && rc==SQLITE_OK ){
- iFrame++;
- nLast--;
- rc = walIndexAppend(pWal, iFrame, pLast->pgno);
- }
-
- if( rc==SQLITE_OK ){
- /* Update the private copy of the header. */
- pWal->hdr.szPage = szPage;
- pWal->hdr.mxFrame = iFrame;
- if( isCommit ){
- pWal->hdr.iChange++;
- pWal->hdr.nPage = nTruncate;
- }
- /* If this is a commit, update the wal-index header too. */
- if( isCommit ){
- walIndexWriteHdr(pWal);
- pWal->iCallback = iFrame;
- }
- }
-
- walIndexUnmap(pWal);
- return rc;
-}
-
-/*
-** Checkpoint the database:
-**
-** 1. Acquire a CHECKPOINT lock
-** 2. Copy the contents of the log into the database file.
-** 3. Zero the wal-index header (so new readers will ignore the log).
-** 4. Drop the CHECKPOINT lock.
-*/
-SQLITE_PRIVATE int sqlite3WalCheckpoint(
- Wal *pWal, /* Wal connection */
- int sync_flags, /* Flags to sync db file with (or 0) */
- int nBuf, /* Size of temporary buffer */
- u8 *zBuf, /* Temporary buffer to use */
- int (*xBusyHandler)(void *), /* Pointer to busy-handler function */
- void *pBusyHandlerArg /* Argument to pass to xBusyHandler */
-){
- int rc; /* Return code */
- int isChanged = 0; /* True if a new wal-index header is loaded */
-
- assert( pWal->pWiData==0 );
-
- /* Get the CHECKPOINT lock.
- **
- ** Normally, the connection will be in UNLOCK state at this point. But
- ** if the connection is in exclusive-mode it may still be in READ state
- ** even though the upper layer has no active read-transaction (because
- ** WalCloseSnapshot() is not called in exclusive mode). The state will
- ** be set to UNLOCK when this function returns. This is Ok.
- */
- assert( (pWal->lockState==SQLITE_SHM_UNLOCK)
- || (pWal->lockState==SQLITE_SHM_READ) );
- walSetLock(pWal, SQLITE_SHM_UNLOCK);
- do {
- rc = walSetLock(pWal, SQLITE_SHM_CHECKPOINT);
- }while( rc==SQLITE_BUSY && xBusyHandler(pBusyHandlerArg) );
- if( rc!=SQLITE_OK ){
- walSetLock(pWal, SQLITE_SHM_UNLOCK);
- return rc;
- }
-
- /* Copy data from the log to the database file. */
- rc = walIndexReadHdr(pWal, &isChanged);
- if( rc==SQLITE_OK ){
- rc = walCheckpoint(pWal, sync_flags, nBuf, zBuf);
- }
- if( isChanged ){
- /* If a new wal-index header was loaded before the checkpoint was
- ** performed, then the pager-cache associated with pWal is now
- ** out of date. So zero the cached wal-index header to ensure that
- ** next time the pager opens a snapshot on this database it knows that
- ** the cache needs to be reset.
- */
- memset(&pWal->hdr, 0, sizeof(WalIndexHdr));
- }
-
- /* Release the locks. */
- walIndexUnmap(pWal);
- walSetLock(pWal, SQLITE_SHM_UNLOCK);
- return rc;
-}
-
-/* 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){
- u32 ret = 0;
- if( pWal ){
- ret = pWal->iCallback;
- pWal->iCallback = 0;
- }
- return (int)ret;
-}
-
-/*
-** This function is called to set or query the exclusive-mode flag
-** associated with the WAL connection passed as the first argument. The
-** exclusive-mode flag should be set to indicate that the caller is
-** holding an EXCLUSIVE lock on the database file (it does this in
-** locking_mode=exclusive mode). If the EXCLUSIVE lock is to be dropped,
-** the flag set by this function should be cleared before doing so.
-**
-** The value of the exclusive-mode flag may only be modified when
-** the WAL connection is in READ state.
-**
-** When the flag is set, this module does not call the VFS xShmLock()
-** method to obtain any locks on the wal-index (as it assumes it
-** has exclusive access to the wal and wal-index files anyhow). It
-** continues to hold (and does not drop) the existing READ lock on
-** the wal-index.
-**
-** To set or clear the flag, the "op" parameter is passed 1 or 0,
-** respectively. To query the flag, pass -1. In all cases, the value
-** returned is the value of the exclusive-mode flag (after its value
-** has been modified, if applicable).
-*/
-SQLITE_PRIVATE int sqlite3WalExclusiveMode(Wal *pWal, int op){
- if( op>=0 ){
- assert( pWal->lockState==SQLITE_SHM_READ );
- pWal->exclusiveMode = (u8)op;
- }
- return pWal->exclusiveMode;
-}
-
-#endif /* #ifndef SQLITE_OMIT_WAL */
-
-/************** End of wal.c *************************************************/
/************** Begin file btmutex.c *****************************************/
/*
** 2007 August 27
@@ -42126,16 +36830,16 @@ SQLITE_PRIVATE int sqlite3WalExclusiveMode(Wal *pWal, int op){
** on Ptr(N) and its subpages have values greater than Key(N-1). And
** so forth.
**
-** Finding a particular key requires reading O(log(M)) pages from the
+** Finding a particular key requires reading O(log(M)) pages from the
** disk where M is the number of entries in the tree.
**
-** In this implementation, a single file can hold one or more separate
+** In this implementation, a single file can hold one or more separate
** BTrees. Each BTree is identified by the index of its root page. The
** key and data for any entry are combined to form the "payload". A
** fixed amount of payload can be carried directly on the database
** page. If the payload is larger than the preset amount then surplus
** bytes are stored on overflow pages. The payload for an entry
-** and the preceding pointer are combined to form a "Cell". Each
+** and the preceding pointer are combined to form a "Cell". Each
** page has a small header which contains the Ptr(N) pointer and other
** information such as the size of key and data.
**
@@ -42153,7 +36857,7 @@ SQLITE_PRIVATE int sqlite3WalExclusiveMode(Wal *pWal, int op){
**
** OFFSET SIZE DESCRIPTION
** 0 16 Header string: "SQLite format 3\000"
-** 16 2 Page size in bytes.
+** 16 2 Page size in bytes.
** 18 1 File format write version
** 19 1 File format read version
** 20 1 Bytes of unused space at the end of each page
@@ -42264,7 +36968,7 @@ SQLITE_PRIVATE int sqlite3WalExclusiveMode(Wal *pWal, int op){
** contiguous or in order, but cell pointers are contiguous and in order.
**
** Cell content makes use of variable length integers. A variable
-** length integer is 1 to 9 bytes where the lower 7 bits of each
+** length integer is 1 to 9 bytes where the lower 7 bits of each
** byte are used. The integer consists of all bytes that have bit 8 set and
** the first byte with bit 8 clear. The most significant byte of the integer
** appears first. A variable-length integer may not be more than 9 bytes long.
@@ -42335,7 +37039,7 @@ typedef struct BtLock BtLock;
** -DSQLITE_FILE_HEADER="..." on the compiler command-line. The
** header must be exactly 16 bytes including the zero-terminator so
** the string itself should be 15 characters long. If you change
-** the header, then your custom library will not be able to read
+** the header, then your custom library will not be able to read
** databases generated by the standard tools and the standard tools
** will not be able to read databases created by your custom library.
*/
@@ -42398,7 +37102,7 @@ struct MemPage {
/*
** A linked list of the following structures is stored at BtShared.pLock.
-** Locks are added (or upgraded from READ_LOCK to WRITE_LOCK) when a cursor
+** Locks are added (or upgraded from READ_LOCK to WRITE_LOCK) when a cursor
** is opened on the table with root page BtShared.iTable. Locks are removed
** from this list when a transaction is committed or rolled back, or when
** a btree handle is closed.
@@ -42422,7 +37126,7 @@ struct BtLock {
** see the internals of this structure and only deals with pointers to
** this structure.
**
-** For some database files, the same underlying database cache might be
+** For some database files, the same underlying database cache might be
** shared between multiple connections. In that case, each connection
** has it own instance of this object. But each instance of this object
** points to the same BtShared object. The database cache and the
@@ -42430,7 +37134,7 @@ struct BtLock {
** the BtShared object.
**
** All fields in this structure are accessed under sqlite3.mutex.
-** The pBt pointer itself may not be changed while there exists cursors
+** The pBt pointer itself may not be changed while there exists cursors
** in the referenced BtShared that point back to this Btree since those
** cursors have to do go through this Btree to find their BtShared and
** they often do so without holding sqlite3.mutex.
@@ -42463,7 +37167,7 @@ struct Btree {
/*
** An instance of this object represents a single database file.
-**
+**
** A single database file can be in use as the same time by two
** or more database connections. When two or more connections are
** sharing the same database file, each connection has it own
@@ -42503,8 +37207,6 @@ struct BtShared {
MemPage *pPage1; /* First page of the database */
u8 readOnly; /* True if the underlying file is readonly */
u8 pageSizeFixed; /* True if the page size can no longer be changed */
- u8 secureDelete; /* True if secure_delete is enabled */
- u8 initiallyEmpty; /* Database is empty at start of transaction */
#ifndef SQLITE_OMIT_AUTOVACUUM
u8 autoVacuum; /* True if auto-vacuum is enabled */
u8 incrVacuum; /* True if incr-vacuum is enabled */
@@ -42516,9 +37218,7 @@ struct BtShared {
u16 maxLeaf; /* Maximum local payload in a LEAFDATA table */
u16 minLeaf; /* Minimum local payload in a LEAFDATA table */
u8 inTransaction; /* Transaction state */
- u8 doNotUseWAL; /* If true, do not open write-ahead-log file */
int nTransaction; /* Number of open transactions (read + write) */
- u32 nPage; /* Number of pages in the database */
void *pSchema; /* Pointer to space allocated by sqlite3BtreeSchema() */
void (*xFreeSchema)(void*); /* Destructor for BtShared.pSchema */
sqlite3_mutex *mutex; /* Non-recursive mutex required to access this struct */
@@ -42574,7 +37274,7 @@ struct CellInfo {
** particular database connection identified BtCursor.pBtree.db.
**
** Fields in this structure are accessed under the BtShared.mutex
-** found at self->pBt->mutex.
+** found at self->pBt->mutex.
*/
struct BtCursor {
Btree *pBtree; /* The Btree to which this cursor belongs */
@@ -42607,14 +37307,14 @@ struct BtCursor {
** 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)
+** 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_REQUIRESEEK:
-** The table that this cursor was opened on still exists, but has been
+** 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
-** in variables BtCursor.pKey and BtCursor.nKey. When a cursor is in
+** in variables BtCursor.pKey and BtCursor.nKey. When a cursor is in
** this state, restoreCursorPosition() can be called to attempt to
** seek the cursor to the saved position.
**
@@ -42630,13 +37330,13 @@ struct BtCursor {
#define CURSOR_REQUIRESEEK 2
#define CURSOR_FAULT 3
-/*
+/*
** The database page the PENDING_BYTE occupies. This page is never used.
*/
# define PENDING_BYTE_PAGE(pBt) PAGER_MJ_PGNO(pBt)
/*
-** These macros define the location of the pointer-map entry for a
+** These macros define the location of the pointer-map entry for a
** database page. The first argument to each is the number of usable
** bytes on each page of the database (often 1024). The second is the
** page number to look up in the pointer map.
@@ -42671,10 +37371,10 @@ struct BtCursor {
** PTRMAP_ROOTPAGE: The database page is a root-page. The page-number is not
** used in this case.
**
-** PTRMAP_FREEPAGE: The database page is an unused (free) page. The page-number
+** PTRMAP_FREEPAGE: The database page is an unused (free) page. The page-number
** is not used in this case.
**
-** PTRMAP_OVERFLOW1: The database page is the first page in a list of
+** PTRMAP_OVERFLOW1: The database page is the first page in a list of
** overflow pages. The page number identifies the page that
** contains the cell with a pointer to this overflow page.
**
@@ -42696,13 +37396,13 @@ struct BtCursor {
*/
#define btreeIntegrity(p) \
assert( p->pBt->inTransaction!=TRANS_NONE || p->pBt->nTransaction==0 ); \
- assert( p->pBt->inTransaction>=p->inTrans );
+ assert( p->pBt->inTransaction>=p->inTrans );
/*
** The ISAUTOVACUUM macro is used within balance_nonroot() to determine
** if the database supports auto-vacuum or not. Because it is used
-** within an expression that is an argument to another macro
+** within an expression that is an argument to another macro
** (sqliteMallocRaw), it is not possible to use conditional compilation.
** So, this macro is defined instead.
*/
@@ -42975,7 +37675,7 @@ SQLITE_PRIVATE int sqlite3BtreeHoldsAllMutexes(sqlite3 *db){
#endif /* NDEBUG */
/*
-** Add a new Btree pointer to a BtreeMutexArray.
+** Add a new Btree pointer to a BtreeMutexArray.
** if the pointer can possibly be shared with
** another database connection.
**
@@ -43121,7 +37821,7 @@ int sqlite3BtreeTrace=1; /* True to enable tracing */
/*
** A list of BtShared objects that are eligible for participation
** in shared cache. This variable has file scope during normal builds,
-** but the test harness needs to access it so we make it global for
+** but the test harness needs to access it so we make it global for
** test builds.
**
** Access to this variable is protected by SQLITE_MUTEX_STATIC_MASTER.
@@ -43156,7 +37856,7 @@ SQLITE_API int sqlite3_enable_shared_cache(int enable){
** manipulate entries in the BtShared.pLock linked list used to store
** shared-cache table level locks. If the library is compiled with the
** shared-cache feature disabled, then there is only ever one user
- ** of each BtShared structure and so this locking is not necessary.
+ ** of each BtShared structure and so this locking is not necessary.
** So define the lock related functions as no-ops.
*/
#define querySharedCacheTableLock(a,b,c) SQLITE_OK
@@ -43173,15 +37873,15 @@ SQLITE_API int sqlite3_enable_shared_cache(int enable){
/*
**** This function is only used as part of an assert() statement. ***
**
-** Check to see if pBtree holds the required locks to read or write to the
+** Check to see if pBtree holds the required locks to read or write to the
** table with root page iRoot. Return 1 if it does and 0 if not.
**
-** For example, when writing to a table with root-page iRoot via
+** For example, when writing to a table with root-page iRoot via
** Btree connection pBtree:
**
** assert( hasSharedCacheTableLock(pBtree, iRoot, 0, WRITE_LOCK) );
**
-** When writing to an index that resides in a sharable database, the
+** When writing to an index that resides in a sharable database, the
** caller should have first obtained a lock specifying the root page of
** the corresponding table. This makes things a bit more complicated,
** as this module treats each table as a separate structure. To determine
@@ -43203,7 +37903,7 @@ static int hasSharedCacheTableLock(
BtLock *pLock;
/* If this database is not shareable, or if the client is reading
- ** and has the read-uncommitted flag set, then no lock is required.
+ ** and has the read-uncommitted flag set, then no lock is required.
** Return true immediately.
*/
if( (pBtree->sharable==0)
@@ -43237,13 +37937,13 @@ static int hasSharedCacheTableLock(
iTab = iRoot;
}
- /* Search for the required lock. Either a write-lock on root-page iTab, a
+ /* Search for the required lock. Either a write-lock on root-page iTab, a
** write-lock on the schema table, or (if the client is reading) a
** read-lock on iTab will suffice. Return 1 if any of these are found. */
for(pLock=pBtree->pBt->pLock; pLock; pLock=pLock->pNext){
- if( pLock->pBtree==pBtree
+ if( pLock->pBtree==pBtree
&& (pLock->iTable==iTab || (pLock->eLock==WRITE_LOCK && pLock->iTable==1))
- && pLock->eLock>=eLockType
+ && pLock->eLock>=eLockType
){
return 1;
}
@@ -43276,7 +37976,7 @@ static int hasSharedCacheTableLock(
static int hasReadConflicts(Btree *pBtree, Pgno iRoot){
BtCursor *p;
for(p=pBtree->pBt->pCursor; p; p=p->pNext){
- if( p->pgnoRoot==iRoot
+ if( p->pgnoRoot==iRoot
&& p->pBtree!=pBtree
&& 0==(p->pBtree->db->flags & SQLITE_ReadUncommitted)
){
@@ -43288,7 +37988,7 @@ static int hasReadConflicts(Btree *pBtree, Pgno iRoot){
#endif /* #ifdef SQLITE_DEBUG */
/*
-** Query to see if Btree handle p may obtain a lock of type eLock
+** Query to see if Btree handle p may obtain a lock of type eLock
** (READ_LOCK or WRITE_LOCK) on the table with root-page iTab. Return
** SQLITE_OK if the lock may be obtained (by calling
** setSharedCacheTableLock()), or SQLITE_LOCKED if not.
@@ -43301,14 +38001,14 @@ static int querySharedCacheTableLock(Btree *p, Pgno iTab, u8 eLock){
assert( eLock==READ_LOCK || eLock==WRITE_LOCK );
assert( p->db!=0 );
assert( !(p->db->flags&SQLITE_ReadUncommitted)||eLock==WRITE_LOCK||iTab==1 );
-
+
/* If requesting a write-lock, then the Btree must have an open write
- ** transaction on this file. And, obviously, for this to be so there
+ ** transaction on this file. And, obviously, for this to be so there
** must be an open write transaction on the file itself.
*/
assert( eLock==READ_LOCK || (p==pBt->pWriter && p->inTrans==TRANS_WRITE) );
assert( eLock==READ_LOCK || pBt->inTransaction==TRANS_WRITE );
-
+
/* This routine is a no-op if the shared-cache is not enabled */
if( !p->sharable ){
return SQLITE_OK;
@@ -43323,7 +38023,7 @@ static int querySharedCacheTableLock(Btree *p, Pgno iTab, u8 eLock){
}
for(pIter=pBt->pLock; pIter; pIter=pIter->pNext){
- /* The condition (pIter->eLock!=eLock) in the following if(...)
+ /* The condition (pIter->eLock!=eLock) in the following if(...)
** statement is a simplification of:
**
** (eLock==WRITE_LOCK || pIter->eLock==WRITE_LOCK)
@@ -43350,7 +38050,7 @@ static int querySharedCacheTableLock(Btree *p, Pgno iTab, u8 eLock){
#ifndef SQLITE_OMIT_SHARED_CACHE
/*
** Add a lock on the table with root-page iTable to the shared-btree used
-** by Btree handle p. Parameter eLock must be either READ_LOCK or
+** by Btree handle p. Parameter eLock must be either READ_LOCK or
** WRITE_LOCK.
**
** This function assumes the following:
@@ -43362,7 +38062,7 @@ static int querySharedCacheTableLock(Btree *p, Pgno iTab, u8 eLock){
** with the requested lock (i.e. querySharedCacheTableLock() has
** already been called and returned SQLITE_OK).
**
-** SQLITE_OK is returned if the lock is added successfully. SQLITE_NOMEM
+** SQLITE_OK is returned if the lock is added successfully. SQLITE_NOMEM
** is returned if a malloc attempt fails.
*/
static int setSharedCacheTableLock(Btree *p, Pgno iTable, u8 eLock){
@@ -43376,11 +38076,11 @@ static int setSharedCacheTableLock(Btree *p, Pgno iTable, u8 eLock){
/* A connection with the read-uncommitted flag set will never try to
** obtain a read-lock using this function. The only read-lock obtained
- ** by a connection in read-uncommitted mode is on the sqlite_master
+ ** by a connection in read-uncommitted mode is on the sqlite_master
** table, and that lock is obtained in BtreeBeginTrans(). */
assert( 0==(p->db->flags&SQLITE_ReadUncommitted) || eLock==WRITE_LOCK );
- /* This function should only be called on a sharable b-tree after it
+ /* This function should only be called on a sharable b-tree after it
** has been determined that no other b-tree holds a conflicting lock. */
assert( p->sharable );
assert( SQLITE_OK==querySharedCacheTableLock(p, iTable, eLock) );
@@ -43425,7 +38125,7 @@ static int setSharedCacheTableLock(Btree *p, Pgno iTable, u8 eLock){
** Release all the table locks (locks obtained via calls to
** the setSharedCacheTableLock() procedure) held by Btree object p.
**
-** This function assumes that Btree p has an open read or write
+** This function assumes that Btree p has an open read or write
** transaction. If it does not, then the BtShared.isPending variable
** may be incorrectly cleared.
*/
@@ -43458,7 +38158,7 @@ static void clearAllSharedCacheTableLocks(Btree *p){
pBt->isExclusive = 0;
pBt->isPending = 0;
}else if( pBt->nTransaction==2 ){
- /* This function is called when Btree p is concluding its
+ /* This function is called when Btree p is concluding its
** transaction. If there currently exists a writer, and p is not
** that writer, then the number of locks held by connections other
** than the writer must be about to drop to zero. In this case
@@ -43562,8 +38262,8 @@ static void invalidateIncrblobCursors(
#endif /* SQLITE_OMIT_INCRBLOB */
/*
-** Set bit pgno of the BtShared.pHasContent bitvec. This is called
-** when a page that previously contained data becomes a free-list leaf
+** Set bit pgno of the BtShared.pHasContent bitvec. This is called
+** when a page that previously contained data becomes a free-list leaf
** page.
**
** The BtShared.pHasContent bitvec exists to work around an obscure
@@ -43589,7 +38289,7 @@ static void invalidateIncrblobCursors(
** may be lost. In the event of a rollback, it may not be possible
** to restore the database to its original configuration.
**
-** The solution is the BtShared.pHasContent bitvec. Whenever a page is
+** The solution is the BtShared.pHasContent bitvec. Whenever a page is
** moved to become a free-list leaf page, the corresponding bit is
** set in the bitvec. Whenever a leaf page is extracted from the free-list,
** optimization 2 above is omitted if the corresponding bit is already
@@ -43599,8 +38299,11 @@ static void invalidateIncrblobCursors(
static int btreeSetHasContent(BtShared *pBt, Pgno pgno){
int rc = SQLITE_OK;
if( !pBt->pHasContent ){
- assert( pgno<=pBt->nPage );
- pBt->pHasContent = sqlite3BitvecCreate(pBt->nPage);
+ int nPage = 100;
+ sqlite3PagerPagecount(pBt->pPager, &nPage);
+ /* If sqlite3PagerPagecount() fails there is no harm because the
+ ** nPage variable is unchanged from its default value of 100 */
+ pBt->pHasContent = sqlite3BitvecCreate((u32)nPage);
if( !pBt->pHasContent ){
rc = SQLITE_NOMEM;
}
@@ -43633,11 +38336,11 @@ static void btreeClearHasContent(BtShared *pBt){
}
/*
-** Save the current cursor position in the variables BtCursor.nKey
+** Save the current cursor position in the variables BtCursor.nKey
** and BtCursor.pKey. The cursor's state is set to CURSOR_REQUIRESEEK.
**
** The caller must ensure that the cursor is valid (has eState==CURSOR_VALID)
-** prior to calling this routine.
+** prior to calling this routine.
*/
static int saveCursorPosition(BtCursor *pCur){
int rc;
@@ -43652,7 +38355,7 @@ static int saveCursorPosition(BtCursor *pCur){
/* If this is an intKey table, then the above call to BtreeKeySize()
** stores the integer key in pCur->nKey. In this case this value is
** all that is required. Otherwise, if pCur is not open on an intKey
- ** table, then malloc space for and store the pCur->nKey bytes of key
+ ** table, then malloc space for and store the pCur->nKey bytes of key
** data.
*/
if( 0==pCur->apPage[0]->intKey ){
@@ -43694,7 +38397,7 @@ static int saveAllCursors(BtShared *pBt, Pgno iRoot, BtCursor *pExcept){
assert( sqlite3_mutex_held(pBt->mutex) );
assert( pExcept==0 || pExcept->pBt==pBt );
for(p=pBt->pCursor; p; p=p->pNext){
- if( p!=pExcept && (0==iRoot || p->pgnoRoot==iRoot) &&
+ if( p!=pExcept && (0==iRoot || p->pgnoRoot==iRoot) &&
p->eState==CURSOR_VALID ){
int rc = saveCursorPosition(p);
if( SQLITE_OK!=rc ){
@@ -43748,9 +38451,9 @@ static int btreeMoveto(
/*
** Restore the cursor to the position it was in (or as close to as possible)
-** when saveCursorPosition() was called. Note that this call deletes the
+** when saveCursorPosition() was called. Note that this call deletes the
** saved position info stored by saveCursorPosition(), so there can be
-** at most one effective restoreCursorPosition() call after each
+** at most one effective restoreCursorPosition() call after each
** saveCursorPosition().
*/
static int btreeRestoreCursorPosition(BtCursor *pCur){
@@ -43811,7 +38514,7 @@ static Pgno ptrmapPageno(BtShared *pBt, Pgno pgno){
assert( sqlite3_mutex_held(pBt->mutex) );
nPagesPerMapPage = (pBt->usableSize/5)+1;
iPtrMap = (pgno-2)/nPagesPerMapPage;
- ret = (iPtrMap*nPagesPerMapPage) + 2;
+ ret = (iPtrMap*nPagesPerMapPage) + 2;
if( ret==PENDING_BYTE_PAGE(pBt) ){
ret++;
}
@@ -43945,8 +38648,8 @@ static u8 *findOverflowCell(MemPage *pPage, int iCell){
/*
** Parse a cell content block and fill in the CellInfo structure. There
-** are two versions of this function. btreeParseCell() takes a
-** cell index as the second argument and btreeParseCellPtr()
+** are two versions of this function. btreeParseCell() takes a
+** cell index as the second argument and btreeParseCellPtr()
** takes a pointer to the body of the cell as its second argument.
**
** Within this file, the parseCell() macro can be called instead of
@@ -44060,7 +38763,7 @@ static u16 cellSizePtr(MemPage *pPage, u8 *pCell){
nSize = 0;
}
- /* pIter now points at the 64-bit integer key value, a variable length
+ /* pIter now points at the 64-bit integer key value, a variable length
** integer. The following block moves pIter to point at the first byte
** past the end of the key value. */
pEnd = &pIter[9];
@@ -44166,7 +38869,7 @@ static int defragmentPage(MemPage *pPage){
testcase( pc==iCellLast );
#if !defined(SQLITE_ENABLE_OVERSIZE_CELL_CHECK)
/* These conditions have already been verified in btreeInitPage()
- ** if SQLITE_ENABLE_OVERSIZE_CELL_CHECK is defined
+ ** if SQLITE_ENABLE_OVERSIZE_CELL_CHECK is defined
*/
if( pc<iCellFirst || pc>iCellLast ){
return SQLITE_CORRUPT_BKPT;
@@ -44224,7 +38927,7 @@ static int allocateSpace(MemPage *pPage, int nByte, int *pIdx){
int gap; /* First byte of gap between cell pointers and cell content */
int rc; /* Integer return code */
int usableSize; /* Usable size of the page */
-
+
assert( sqlite3PagerIswriteable(pPage->pDbPage) );
assert( pPage->pBt );
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
@@ -44249,8 +38952,8 @@ static int allocateSpace(MemPage *pPage, int nByte, int *pIdx){
if( rc ) return rc;
top = get2byte(&data[hdr+5]);
}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
+ /* 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.
*/
int pc, addr;
@@ -44327,11 +39030,11 @@ static int freeSpace(MemPage *pPage, int start, int size){
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
assert( size>=0 ); /* Minimum cell size is 4 */
- if( pPage->pBt->secureDelete ){
- /* Overwrite deleted information with zeros when the secure_delete
- ** option is enabled */
- memset(&data[start], 0, size);
- }
+#ifdef SQLITE_SECURE_DELETE
+ /* Overwrite deleted information with zeros when the SECURE_DELETE
+ ** option is enabled at compile-time */
+ memset(&data[start], 0, size);
+#endif
/* Add the space back into the linked list of freeblocks. Note that
** even though the freeblock list was checked by btreeInitPage(),
@@ -44437,7 +39140,7 @@ static int decodeFlags(MemPage *pPage, int flagByte){
** Initialize the auxiliary information for a disk block.
**
** Return SQLITE_OK on success. If we see that the page does
-** not contain a well-formed database page, then return
+** not contain a well-formed database page, then return
** SQLITE_CORRUPT. Note that a return of SQLITE_OK does not
** guarantee that the page is well-formed. It only shows that
** we failed to detect any corruption.
@@ -44481,10 +39184,10 @@ static int btreeInitPage(MemPage *pPage){
testcase( pPage->nCell==MX_CELL(pBt) );
/* A malformed database page might cause us to read past the end
- ** of page when parsing a cell.
+ ** of page when parsing a cell.
**
** The following block of code checks early to see if a cell extends
- ** past the end of a page boundary and causes SQLITE_CORRUPT to be
+ ** past the end of a page boundary and causes SQLITE_CORRUPT to be
** returned if it does.
*/
iCellFirst = cellOffset + 2*pPage->nCell;
@@ -44509,7 +39212,7 @@ static int btreeInitPage(MemPage *pPage){
}
}
if( !pPage->leaf ) iCellLast++;
- }
+ }
#endif
/* Compute the total free space on the page */
@@ -44519,14 +39222,14 @@ static int btreeInitPage(MemPage *pPage){
u16 next, size;
if( pc<iCellFirst || pc>iCellLast ){
/* Start of free block is off the page */
- return SQLITE_CORRUPT_BKPT;
+ return SQLITE_CORRUPT_BKPT;
}
next = get2byte(&data[pc]);
size = get2byte(&data[pc+2]);
if( (next>0 && next<=pc+size+3) || pc+size>usableSize ){
/* Free blocks must be in ascending order. And the last byte of
** the free-block must lie on the database page. */
- return SQLITE_CORRUPT_BKPT;
+ return SQLITE_CORRUPT_BKPT;
}
nFree = nFree + size;
pc = next;
@@ -44540,7 +39243,7 @@ static int btreeInitPage(MemPage *pPage){
** area, according to the page header, lies within the page.
*/
if( nFree>usableSize ){
- return SQLITE_CORRUPT_BKPT;
+ return SQLITE_CORRUPT_BKPT;
}
pPage->nFree = (u16)(nFree - iCellFirst);
pPage->isInit = 1;
@@ -44563,9 +39266,9 @@ static void zeroPage(MemPage *pPage, int flags){
assert( sqlite3PagerGetData(pPage->pDbPage) == data );
assert( sqlite3PagerIswriteable(pPage->pDbPage) );
assert( sqlite3_mutex_held(pBt->mutex) );
- if( pBt->secureDelete ){
- memset(&data[hdr], 0, pBt->usableSize - hdr);
- }
+#ifdef SQLITE_SECURE_DELETE
+ memset(&data[hdr], 0, pBt->usableSize - hdr);
+#endif
data[hdr] = (char)flags;
first = hdr + 8 + 4*((flags&PTF_LEAF)==0 ?1:0);
memset(&data[hdr+1], 0, 4);
@@ -44594,7 +39297,7 @@ static MemPage *btreePageFromDbPage(DbPage *pDbPage, Pgno pgno, BtShared *pBt){
pPage->pBt = pBt;
pPage->pgno = pgno;
pPage->hdrOffset = pPage->pgno==1 ? 100 : 0;
- return pPage;
+ return pPage;
}
/*
@@ -44643,18 +39346,18 @@ static MemPage *btreePageLookup(BtShared *pBt, Pgno pgno){
** Return the size of the database file in pages. If there is any kind of
** error, return ((unsigned int)-1).
*/
-static Pgno btreePagecount(BtShared *pBt){
- return pBt->nPage;
-}
-SQLITE_PRIVATE u32 sqlite3BtreeLastPage(Btree *p){
- assert( sqlite3BtreeHoldsMutex(p) );
- assert( ((p->pBt->nPage)&0x8000000)==0 );
- return (int)btreePagecount(p->pBt);
+static Pgno pagerPagecount(BtShared *pBt){
+ int nPage = -1;
+ int rc;
+ assert( pBt->pPage1 );
+ rc = sqlite3PagerPagecount(pBt->pPager, &nPage);
+ assert( rc==SQLITE_OK || nPage==-1 );
+ return (Pgno)nPage;
}
/*
** Get a page from the pager and initialize it. This routine is just a
-** convenience wrapper around separate calls to btreeGetPage() and
+** convenience wrapper around separate calls to btreeGetPage() and
** btreeInitPage().
**
** If an error occurs, then the value *ppPage is set to is undefined. It
@@ -44666,11 +39369,9 @@ static int getAndInitPage(
MemPage **ppPage /* Write the page pointer here */
){
int rc;
+ TESTONLY( Pgno iLastPg = pagerPagecount(pBt); )
assert( sqlite3_mutex_held(pBt->mutex) );
- if( pgno<=0 || pgno>btreePagecount(pBt) ){
- return SQLITE_CORRUPT_BKPT;
- }
rc = btreeGetPage(pBt, pgno, ppPage, 0);
if( rc==SQLITE_OK ){
rc = btreeInitPage(*ppPage);
@@ -44678,6 +39379,15 @@ static int getAndInitPage(
releasePage(*ppPage);
}
}
+
+ /* If the requested page number was either 0 or greater than the page
+ ** number of the last page in the database, this function should return
+ ** SQLITE_CORRUPT or some other error (i.e. SQLITE_FULL). Check that this
+ ** is the case. */
+ assert( (pgno>0 && pgno<=iLastPg) || rc!=SQLITE_OK );
+ testcase( pgno==0 );
+ testcase( pgno==iLastPg );
+
return rc;
}
@@ -44735,7 +39445,7 @@ static int btreeInvokeBusyHandler(void *pArg){
/*
** Open a database file.
-**
+**
** zFilename is the name of the database file. If zFilename is NULL
** a new database with a random name is created. This randomly named
** database file will be deleted when sqlite3BtreeClose() is called.
@@ -44763,9 +39473,9 @@ SQLITE_PRIVATE int sqlite3BtreeOpen(
u8 nReserve; /* Byte of unused space on each page */
unsigned char zDbHeader[100]; /* Database header content */
- /* Set the variable isMemdb to true for an in-memory database, or
+ /* Set the variable isMemdb to true for an in-memory database, or
** false for a file-based database. This symbol is only required if
- ** either of the shared-data or autovacuum features are compiled
+ ** either of the shared-data or autovacuum features are compiled
** into the library.
*/
#if !defined(SQLITE_OMIT_SHARED_CACHE) || !defined(SQLITE_OMIT_AUTOVACUUM)
@@ -44857,7 +39567,7 @@ SQLITE_PRIVATE int sqlite3BtreeOpen(
assert( sizeof(u32)==4 );
assert( sizeof(u16)==2 );
assert( sizeof(Pgno)==4 );
-
+
pBt = sqlite3MallocZero( sizeof(*pBt) );
if( pBt==0 ){
rc = SQLITE_NOMEM;
@@ -44874,13 +39584,10 @@ SQLITE_PRIVATE int sqlite3BtreeOpen(
pBt->db = db;
sqlite3PagerSetBusyhandler(pBt->pPager, btreeInvokeBusyHandler, pBt);
p->pBt = pBt;
-
+
pBt->pCursor = 0;
pBt->pPage1 = 0;
pBt->readOnly = sqlite3PagerIsreadonly(pBt->pPager);
-#ifdef SQLITE_SECURE_DELETE
- pBt->secureDelete = 1;
-#endif
pBt->pageSize = get2byte(&zDbHeader[16]);
if( pBt->pageSize<512 || pBt->pageSize>SQLITE_MAX_PAGE_SIZE
|| ((pBt->pageSize-1)&pBt->pageSize)!=0 ){
@@ -44910,7 +39617,7 @@ SQLITE_PRIVATE int sqlite3BtreeOpen(
if( rc ) goto btree_open_out;
pBt->usableSize = pBt->pageSize - nReserve;
assert( (pBt->pageSize & 7)==0 ); /* 8-byte alignment of pageSize */
-
+
#if !defined(SQLITE_OMIT_SHARED_CACHE) && !defined(SQLITE_OMIT_DISKIO)
/* Add the new BtShared object to the linked list sharable BtShareds.
*/
@@ -45024,7 +39731,7 @@ static int removeFromSharingList(BtShared *pBt){
}
/*
-** Make sure pBt->pTmpSpace points to an allocation of
+** Make sure pBt->pTmpSpace points to an allocation of
** MX_CELL_SIZE(pBt) bytes.
*/
static void allocateTempSpace(BtShared *pBt){
@@ -45068,7 +39775,7 @@ SQLITE_PRIVATE int sqlite3BtreeClose(Btree *p){
sqlite3BtreeLeave(p);
/* If there are still other outstanding references to the shared-btree
- ** structure, return now. The remainder of this procedure cleans
+ ** structure, return now. The remainder of this procedure cleans
** up the shared-btree.
*/
assert( p->wantToLock==0 && p->locked==0 );
@@ -45149,7 +39856,7 @@ SQLITE_PRIVATE int sqlite3BtreeSetSafetyLevel(Btree *p, int level, int fullSync)
SQLITE_PRIVATE int sqlite3BtreeSyncDisabled(Btree *p){
BtShared *pBt = p->pBt;
int rc;
- assert( sqlite3_mutex_held(p->db->mutex) );
+ assert( sqlite3_mutex_held(p->db->mutex) );
sqlite3BtreeEnter(p);
assert( pBt && pBt->pPager );
rc = sqlite3PagerNosync(pBt->pPager);
@@ -45160,7 +39867,7 @@ SQLITE_PRIVATE int sqlite3BtreeSyncDisabled(Btree *p){
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) || !defined(SQLITE_OMIT_VACUUM)
/*
** Change the default pages size and the number of reserved bytes per page.
-** Or, if the page size has already been fixed, return SQLITE_READONLY
+** Or, if the page size has already been fixed, return SQLITE_READONLY
** without changing anything.
**
** The page size must be a power of 2 between 512 and 65536. If the page
@@ -45237,29 +39944,12 @@ SQLITE_PRIVATE int sqlite3BtreeMaxPageCount(Btree *p, int mxPage){
sqlite3BtreeLeave(p);
return n;
}
-
-/*
-** Set the secureDelete flag if newFlag is 0 or 1. If newFlag is -1,
-** then make no changes. Always return the value of the secureDelete
-** setting after the change.
-*/
-SQLITE_PRIVATE int sqlite3BtreeSecureDelete(Btree *p, int newFlag){
- int b;
- if( p==0 ) return 0;
- sqlite3BtreeEnter(p);
- if( newFlag>=0 ){
- p->pBt->secureDelete = (newFlag!=0) ? 1 : 0;
- }
- b = p->pBt->secureDelete;
- sqlite3BtreeLeave(p);
- return b;
-}
#endif /* !defined(SQLITE_OMIT_PAGER_PRAGMAS) || !defined(SQLITE_OMIT_VACUUM) */
/*
** Change the 'auto-vacuum' property of the database. If the 'autoVacuum'
** parameter is non-zero, then auto-vacuum mode is enabled. If zero, it
-** is disabled. The default value for the auto-vacuum property is
+** is disabled. The default value for the auto-vacuum property is
** determined by the SQLITE_DEFAULT_AUTOVACUUM macro.
*/
SQLITE_PRIVATE int sqlite3BtreeSetAutoVacuum(Btree *p, int autoVacuum){
@@ -45283,7 +39973,7 @@ SQLITE_PRIVATE int sqlite3BtreeSetAutoVacuum(Btree *p, int autoVacuum){
}
/*
-** Return the value of the 'auto-vacuum' property. If auto-vacuum is
+** Return the value of the 'auto-vacuum' property. If auto-vacuum is
** enabled 1 is returned. Otherwise 0.
*/
SQLITE_PRIVATE int sqlite3BtreeGetAutoVacuum(Btree *p){
@@ -45310,14 +40000,12 @@ SQLITE_PRIVATE int sqlite3BtreeGetAutoVacuum(Btree *p){
** SQLITE_OK is returned on success. If the file is not a
** well-formed database file, then SQLITE_CORRUPT is returned.
** SQLITE_BUSY is returned if the database is locked. SQLITE_NOMEM
-** is returned if we run out of memory.
+** is returned if we run out of memory.
*/
static int lockBtree(BtShared *pBt){
- int rc; /* Result code from subfunctions */
- MemPage *pPage1; /* Page 1 of the database file */
- int nPage; /* Number of pages in the database */
- int nPageFile = 0; /* Number of pages in the database file */
- int nPageHeader; /* Number of pages in the database according to hdr */
+ int rc;
+ MemPage *pPage1;
+ int nPage;
assert( sqlite3_mutex_held(pBt->mutex) );
assert( pBt->pPage1==0 );
@@ -45327,16 +40015,12 @@ static int lockBtree(BtShared *pBt){
if( rc!=SQLITE_OK ) return rc;
/* Do some checking to help insure the file we opened really is
- ** a valid database file.
+ ** a valid database file.
*/
- nPage = nPageHeader = get4byte(28+(u8*)pPage1->aData);
- if( (rc = sqlite3PagerPagecount(pBt->pPager, &nPageFile))!=SQLITE_OK ){;
+ rc = sqlite3PagerPagecount(pBt->pPager, &nPage);
+ if( rc!=SQLITE_OK ){
goto page1_init_failed;
- }
- if( nPage==0 ){
- nPage = nPageFile;
- }
- if( nPage>0 ){
+ }else if( nPage>0 ){
int pageSize;
int usableSize;
u8 *page1 = pPage1->aData;
@@ -45344,42 +40028,12 @@ static int lockBtree(BtShared *pBt){
if( memcmp(page1, zMagicHeader, 16)!=0 ){
goto page1_init_failed;
}
-
-#ifdef SQLITE_OMIT_WAL
if( page1[18]>1 ){
pBt->readOnly = 1;
}
if( page1[19]>1 ){
goto page1_init_failed;
}
-#else
- if( page1[18]>2 ){
- pBt->readOnly = 1;
- }
- if( page1[19]>2 ){
- goto page1_init_failed;
- }
-
- /* If the write version is set to 2, this database should be accessed
- ** in WAL mode. If the log is not already open, open it now. Then
- ** return SQLITE_OK and return without populating BtShared.pPage1.
- ** The caller detects this and calls this function again. This is
- ** required as the version of page 1 currently in the page1 buffer
- ** may not be the latest version - there may be a newer one in the log
- ** file.
- */
- if( page1[19]==2 && pBt->doNotUseWAL==0 ){
- int isOpen = 0;
- rc = sqlite3PagerOpenWal(pBt->pPager, &isOpen);
- if( rc!=SQLITE_OK ){
- goto page1_init_failed;
- }else if( isOpen==0 ){
- releasePage(pPage1);
- return SQLITE_OK;
- }
- rc = SQLITE_NOTADB;
- }
-#endif
/* The maximum embedded fraction must be exactly 25%. And the minimum
** embedded fraction must be 12.5% for both leaf-data and non-leaf-data.
@@ -45412,10 +40066,6 @@ static int lockBtree(BtShared *pBt){
pageSize-usableSize);
return rc;
}
- if( nPageHeader>nPageFile ){
- rc = SQLITE_CORRUPT_BKPT;
- goto page1_init_failed;
- }
if( usableSize<480 ){
goto page1_init_failed;
}
@@ -45446,7 +40096,6 @@ static int lockBtree(BtShared *pBt){
pBt->minLeaf = (pBt->usableSize-12)*32/255 - 23;
assert( pBt->maxLeaf + 23 <= MX_CELL_SIZE(pBt) );
pBt->pPage1 = pPage1;
- pBt->nPage = nPage;
return SQLITE_OK;
page1_init_failed:
@@ -45458,7 +40107,7 @@ page1_init_failed:
/*
** If there are no outstanding cursors and we are not in the middle
** of a transaction but there is a read lock on the database, then
-** this routine unrefs the first page of the database file which
+** this routine unrefs the first page of the database file which
** has the effect of releasing the read lock.
**
** If there is a transaction in progress, this routine is a no-op.
@@ -45484,10 +40133,12 @@ static int newDatabase(BtShared *pBt){
MemPage *pP1;
unsigned char *data;
int rc;
+ int nPage;
assert( sqlite3_mutex_held(pBt->mutex) );
- if( pBt->nPage>0 ){
- return SQLITE_OK;
+ rc = sqlite3PagerPagecount(pBt->pPager, &nPage);
+ if( rc!=SQLITE_OK || nPage>0 ){
+ return rc;
}
pP1 = pBt->pPage1;
assert( pP1!=0 );
@@ -45513,8 +40164,6 @@ static int newDatabase(BtShared *pBt){
put4byte(&data[36 + 4*4], pBt->autoVacuum);
put4byte(&data[36 + 7*4], pBt->incrVacuum);
#endif
- pBt->nPage = 1;
- data[31] = 1;
return SQLITE_OK;
}
@@ -45527,8 +40176,8 @@ static int newDatabase(BtShared *pBt){
** upgraded to exclusive by calling this routine a second time - the
** exclusivity flag only works for a new transaction.
**
-** A write-transaction must be started before attempting any
-** changes to the database. None of the following routines
+** A write-transaction must be started before attempting any
+** changes to the database. None of the following routines
** will work unless a transaction is started first:
**
** sqlite3BtreeCreateTable()
@@ -45542,7 +40191,7 @@ static int newDatabase(BtShared *pBt){
** If an initial attempt to acquire the lock fails because of lock contention
** and the database was previously unlocked, then invoke the busy handler
** if there is one. But if there was previously a read-lock, do not
-** invoke the busy handler - just return SQLITE_BUSY. SQLITE_BUSY is
+** invoke the busy handler - just return SQLITE_BUSY. SQLITE_BUSY is
** returned when there is already a read-lock in order to avoid a deadlock.
**
** Suppose there are two processes A and B. A has a read lock and B has
@@ -45576,7 +40225,7 @@ SQLITE_PRIVATE int sqlite3BtreeBeginTrans(Btree *p, int wrflag){
}
#ifndef SQLITE_OMIT_SHARED_CACHE
- /* If another database handle has already opened a write transaction
+ /* If another database handle has already opened a write transaction
** on this shared-btree structure and a second write transaction is
** requested, return SQLITE_LOCKED.
*/
@@ -45598,18 +40247,17 @@ SQLITE_PRIVATE int sqlite3BtreeBeginTrans(Btree *p, int wrflag){
}
#endif
- /* Any read-only or read-write transaction implies a read-lock on
- ** page 1. So if some other shared-cache client already has a write-lock
+ /* Any read-only or read-write transaction implies a read-lock on
+ ** page 1. So if some other shared-cache client already has a write-lock
** on page 1, the transaction cannot be opened. */
rc = querySharedCacheTableLock(p, MASTER_ROOT, READ_LOCK);
if( SQLITE_OK!=rc ) goto trans_begun;
- pBt->initiallyEmpty = pBt->nPage==0;
do {
/* Call lockBtree() until either pBt->pPage1 is populated or
** lockBtree() returns something other than SQLITE_OK. lockBtree()
** may return SQLITE_OK but leave pBt->pPage1 set to 0 if after
- ** reading page 1 it discovers that the page-size of the database
+ ** reading page 1 it discovers that the page-size of the database
** file is not pBt->pageSize. In this case lockBtree() will update
** pBt->pageSize to the page-size of the file on disk.
*/
@@ -45625,7 +40273,7 @@ SQLITE_PRIVATE int sqlite3BtreeBeginTrans(Btree *p, int wrflag){
}
}
}
-
+
if( rc!=SQLITE_OK ){
unlockBtreeIfUnused(pBt);
}
@@ -45720,7 +40368,7 @@ set_child_ptrmaps_out:
** that it points to iTo. Parameter eType describes the type of pointer to
** be modified, as follows:
**
-** PTRMAP_BTREE: pPage is a btree-page. The pointer points at a child
+** PTRMAP_BTREE: pPage is a btree-page. The pointer points at a child
** page of pPage.
**
** PTRMAP_OVERFLOW1: pPage is a btree-page. The pointer points at an overflow
@@ -45764,9 +40412,9 @@ static int modifyPagePointer(MemPage *pPage, Pgno iFrom, Pgno iTo, u8 eType){
}
}
}
-
+
if( i==nCell ){
- if( eType!=PTRMAP_BTREE ||
+ if( eType!=PTRMAP_BTREE ||
get4byte(&pPage->aData[pPage->hdrOffset+8])!=iFrom ){
return SQLITE_CORRUPT_BKPT;
}
@@ -45780,11 +40428,11 @@ static int modifyPagePointer(MemPage *pPage, Pgno iFrom, Pgno iTo, u8 eType){
/*
-** Move the open database page pDbPage to location iFreePage in the
+** Move the open database page pDbPage to location iFreePage in the
** database. The pDbPage reference remains valid.
**
** The isCommit flag indicates that there is no need to remember that
-** the journal needs to be sync()ed before database page pDbPage->pgno
+** the journal needs to be sync()ed before database page pDbPage->pgno
** can be written to. The caller has already promised not to write to that
** page.
*/
@@ -45801,13 +40449,13 @@ static int relocatePage(
Pager *pPager = pBt->pPager;
int rc;
- assert( eType==PTRMAP_OVERFLOW2 || eType==PTRMAP_OVERFLOW1 ||
+ assert( eType==PTRMAP_OVERFLOW2 || eType==PTRMAP_OVERFLOW1 ||
eType==PTRMAP_BTREE || eType==PTRMAP_ROOTPAGE );
assert( sqlite3_mutex_held(pBt->mutex) );
assert( pDbPage->pBt==pBt );
/* Move page iDbPage from its current location to page number iFreePage */
- TRACE(("AUTOVACUUM: Moving %d to free page %d (ptr page %d type %d)\n",
+ TRACE(("AUTOVACUUM: Moving %d to free page %d (ptr page %d type %d)\n",
iDbPage, iFreePage, iPtrPage, eType));
rc = sqlite3PagerMovepage(pPager, pDbPage->pDbPage, iFreePage, isCommit);
if( rc!=SQLITE_OK ){
@@ -45869,14 +40517,14 @@ static int allocateBtreePage(BtShared *, MemPage **, Pgno *, Pgno, u8);
** return SQLITE_OK. If there is no work to do (and therefore no
** point in calling this function again), return SQLITE_DONE.
**
-** More specificly, this function attempts to re-organize the
+** More specificly, this function attempts to re-organize the
** database so that the last page of the file currently in use
** is no longer in use.
**
** If the nFin parameter is non-zero, this function assumes
** that the caller will keep calling incrVacuumStep() until
** it returns SQLITE_DONE or an error, and that nFin is the
-** number of pages the database file will contain after this
+** number of pages the database file will contain after this
** process is complete. If nFin is zero, it is assumed that
** incrVacuumStep() will be called a finite amount of times
** which may or may not empty the freelist. A full autovacuum
@@ -45884,12 +40532,12 @@ static int allocateBtreePage(BtShared *, MemPage **, Pgno *, Pgno, u8);
*/
static int incrVacuumStep(BtShared *pBt, Pgno nFin, Pgno iLastPg){
Pgno nFreeList; /* Number of pages still on the free-list */
- int rc;
assert( sqlite3_mutex_held(pBt->mutex) );
assert( iLastPg>nFin );
if( !PTRMAP_ISPAGE(pBt, iLastPg) && iLastPg!=PENDING_BYTE_PAGE(pBt) ){
+ int rc;
u8 eType;
Pgno iPtrPage;
@@ -45910,7 +40558,7 @@ static int incrVacuumStep(BtShared *pBt, Pgno nFin, Pgno iLastPg){
if( nFin==0 ){
/* Remove the page from the files free-list. This is not required
** if nFin is non-zero. In that case, the free-list will be
- ** truncated to zero after this function returns, so it doesn't
+ ** truncated to zero after this function returns, so it doesn't
** matter if it still contains some garbage entries.
*/
Pgno iFreePg;
@@ -45948,7 +40596,7 @@ static int incrVacuumStep(BtShared *pBt, Pgno nFin, Pgno iLastPg){
releasePage(pFreePg);
}while( nFin!=0 && iFreePg>nFin );
assert( iFreePg<iLastPg );
-
+
rc = sqlite3PagerWrite(pLastPg->pDbPage);
if( rc==SQLITE_OK ){
rc = relocatePage(pBt, pLastPg, eType, iPtrPage, iFreePg, nFin!=0);
@@ -45965,7 +40613,7 @@ static int incrVacuumStep(BtShared *pBt, Pgno nFin, Pgno iLastPg){
while( iLastPg==PENDING_BYTE_PAGE(pBt)||PTRMAP_ISPAGE(pBt, iLastPg) ){
if( PTRMAP_ISPAGE(pBt, iLastPg) ){
MemPage *pPg;
- rc = btreeGetPage(pBt, iLastPg, &pPg, 0);
+ int rc = btreeGetPage(pBt, iLastPg, &pPg, 0);
if( rc!=SQLITE_OK ){
return rc;
}
@@ -45978,7 +40626,6 @@ static int incrVacuumStep(BtShared *pBt, Pgno nFin, Pgno iLastPg){
iLastPg--;
}
sqlite3PagerTruncateImage(pBt->pPager, iLastPg);
- pBt->nPage = iLastPg;
}
return SQLITE_OK;
}
@@ -45989,7 +40636,7 @@ static int incrVacuumStep(BtShared *pBt, Pgno nFin, Pgno iLastPg){
**
** If the incremental vacuum is finished after this function has run,
** SQLITE_DONE is returned. If it is not finished, but no error occurred,
-** SQLITE_OK is returned. Otherwise an SQLite error code.
+** SQLITE_OK is returned. Otherwise an SQLite error code.
*/
SQLITE_PRIVATE int sqlite3BtreeIncrVacuum(Btree *p){
int rc;
@@ -46001,11 +40648,7 @@ SQLITE_PRIVATE int sqlite3BtreeIncrVacuum(Btree *p){
rc = SQLITE_DONE;
}else{
invalidateAllOverflowCache(pBt);
- rc = incrVacuumStep(pBt, 0, btreePagecount(pBt));
- if( rc==SQLITE_OK ){
- rc = sqlite3PagerWrite(pBt->pPage1->pDbPage);
- put4byte(&pBt->pPage1->aData[28], pBt->nPage);
- }
+ rc = incrVacuumStep(pBt, 0, pagerPagecount(pBt));
}
sqlite3BtreeLeave(p);
return rc;
@@ -46016,7 +40659,7 @@ SQLITE_PRIVATE int sqlite3BtreeIncrVacuum(Btree *p){
** is commited 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.
+** the database file should be truncated to during the commit process.
** i.e. the database has been reorganized so that only the first *pnTrunc
** pages are in use.
*/
@@ -46036,7 +40679,7 @@ static int autoVacuumCommit(BtShared *pBt){
int nEntry; /* Number of entries on one ptrmap page */
Pgno nOrig; /* Database size before freeing */
- nOrig = btreePagecount(pBt);
+ nOrig = pagerPagecount(pBt);
if( PTRMAP_ISPAGE(pBt, nOrig) || nOrig==PENDING_BYTE_PAGE(pBt) ){
/* It is not possible to create a database for which the final page
** is either a pointer-map page or the pending-byte page. If one
@@ -46061,12 +40704,11 @@ static int autoVacuumCommit(BtShared *pBt){
rc = incrVacuumStep(pBt, nFin, iFree);
}
if( (rc==SQLITE_DONE || rc==SQLITE_OK) && nFree>0 ){
+ rc = SQLITE_OK;
rc = sqlite3PagerWrite(pBt->pPage1->pDbPage);
put4byte(&pBt->pPage1->aData[32], 0);
put4byte(&pBt->pPage1->aData[36], 0);
- put4byte(&pBt->pPage1->aData[28], nFin);
sqlite3PagerTruncateImage(pBt->pPager, nFin);
- pBt->nPage = nFin;
}
if( rc!=SQLITE_OK ){
sqlite3PagerRollback(pPager);
@@ -46098,7 +40740,7 @@ static int autoVacuumCommit(BtShared *pBt){
**
** Otherwise, sync the database file for the btree pBt. zMaster points to
** the name of a master journal file that should be written into the
-** individual journal file, or is NULL, indicating no master journal file
+** individual journal file, or is NULL, indicating no master journal file
** (single database transaction).
**
** When this is called, the master journal should already have been
@@ -46143,8 +40785,8 @@ static void btreeEndTransaction(Btree *p){
downgradeAllSharedCacheTableLocks(p);
p->inTrans = TRANS_READ;
}else{
- /* If the handle had any kind of transaction open, decrement the
- ** transaction count of the shared btree. If the transaction count
+ /* If the handle had any kind of transaction open, decrement the
+ ** transaction count of the shared btree. If the transaction count
** reaches 0, set the shared state to TRANS_NONE. The unlockBtreeIfUnused()
** call below will unlock the pager. */
if( p->inTrans!=TRANS_NONE ){
@@ -46155,7 +40797,7 @@ static void btreeEndTransaction(Btree *p){
}
}
- /* Set the current transaction state to TRANS_NONE and unlock the
+ /* Set the current transaction state to TRANS_NONE and unlock the
** pager if this call closed the only read or write transaction. */
p->inTrans = TRANS_NONE;
unlockBtreeIfUnused(pBt);
@@ -46185,7 +40827,7 @@ SQLITE_PRIVATE int sqlite3BtreeCommitPhaseTwo(Btree *p){
sqlite3BtreeEnter(p);
btreeIntegrity(p);
- /* If the handle has a write-transaction open, commit the shared-btrees
+ /* If the handle has a write-transaction open, commit the shared-btrees
** transaction and set the shared state to TRANS_READ.
*/
if( p->inTrans==TRANS_WRITE ){
@@ -46234,7 +40876,7 @@ static int countWriteCursors(BtShared *pBt){
BtCursor *pCur;
int r = 0;
for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){
- if( pCur->wrFlag && pCur->eState!=CURSOR_FAULT ) r++;
+ if( pCur->wrFlag && pCur->eState!=CURSOR_FAULT ) r++;
}
return r;
}
@@ -46293,9 +40935,9 @@ SQLITE_PRIVATE int sqlite3BtreeRollback(Btree *p){
if( rc!=SQLITE_OK ){
/* This is a horrible situation. An IO or malloc() error occurred whilst
** trying to save cursor positions. If this is an automatic rollback (as
- ** the result of a constraint, malloc() failure or IO error) then
+ ** the result of a constraint, malloc() failure or IO error) then
** the cache may be internally inconsistent (not contain valid trees) so
- ** we cannot simply return the error to the caller. Instead, abort
+ ** we cannot simply return the error to the caller. Instead, abort
** all queries that may be using any of the cursors that failed to save.
*/
sqlite3BtreeTripAllCursors(p, rc);
@@ -46316,11 +40958,6 @@ SQLITE_PRIVATE int sqlite3BtreeRollback(Btree *p){
** call btreeGetPage() on page 1 again to make
** sure pPage1->aData is set correctly. */
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);
- testcase( pBt->nPage!=nPage );
- pBt->nPage = nPage;
releasePage(pPage1);
}
assert( countWriteCursors(pBt)==0 );
@@ -46334,8 +40971,8 @@ SQLITE_PRIVATE int sqlite3BtreeRollback(Btree *p){
/*
** Start a statement subtransaction. The subtransaction can can be rolled
-** back independently of the main transaction. You must start a transaction
-** before starting a subtransaction. The subtransaction is ended automatically
+** back independently of the main transaction. You must start a transaction
+** before starting a subtransaction. The subtransaction is ended automatically
** if the main transaction commits or rolls back.
**
** Statement subtransactions are used around individual SQL statements
@@ -46358,13 +40995,17 @@ SQLITE_PRIVATE int sqlite3BtreeBeginStmt(Btree *p, int iStatement){
assert( pBt->readOnly==0 );
assert( iStatement>0 );
assert( iStatement>p->db->nSavepoint );
- assert( pBt->inTransaction==TRANS_WRITE );
- /* At the pager level, a statement transaction is a savepoint with
- ** an index greater than all savepoints created explicitly using
- ** SQL statements. It is illegal to open, release or rollback any
- ** such savepoints while the statement transaction savepoint is active.
- */
- rc = sqlite3PagerOpenSavepoint(pBt->pPager, iStatement);
+ if( NEVER(p->inTrans!=TRANS_WRITE || pBt->readOnly) ){
+ rc = SQLITE_INTERNAL;
+ }else{
+ assert( pBt->inTransaction==TRANS_WRITE );
+ /* At the pager level, a statement transaction is a savepoint with
+ ** an index greater than all savepoints created explicitly using
+ ** SQL statements. It is illegal to open, release or rollback any
+ ** such savepoints while the statement transaction savepoint is active.
+ */
+ rc = sqlite3PagerOpenSavepoint(pBt->pPager, iStatement);
+ }
sqlite3BtreeLeave(p);
return rc;
}
@@ -46372,11 +41013,11 @@ SQLITE_PRIVATE int sqlite3BtreeBeginStmt(Btree *p, int iStatement){
/*
** The second argument to this function, op, is always SAVEPOINT_ROLLBACK
** or SAVEPOINT_RELEASE. This function either releases or rolls back the
-** savepoint identified by parameter iSavepoint, depending on the value
+** savepoint identified by parameter iSavepoint, depending on the value
** of op.
**
** Normally, iSavepoint is greater than or equal to zero. However, if op is
-** SAVEPOINT_ROLLBACK, then iSavepoint may also be -1. In this case the
+** SAVEPOINT_ROLLBACK, then iSavepoint may also be -1. In this case the
** contents of the entire transaction are rolled back. This is different
** from a normal transaction rollback, as no locks are released and the
** transaction remains open.
@@ -46390,12 +41031,7 @@ SQLITE_PRIVATE int sqlite3BtreeSavepoint(Btree *p, int op, int iSavepoint){
sqlite3BtreeEnter(p);
rc = sqlite3PagerSavepoint(pBt->pPager, op, iSavepoint);
if( rc==SQLITE_OK ){
- if( iSavepoint<0 && pBt->initiallyEmpty ) pBt->nPage = 0;
rc = newDatabase(pBt);
- pBt->nPage = get4byte(28 + pBt->pPage1->aData);
- if( pBt->nPage==0 ){
- sqlite3PagerPagecount(pBt->pPager, (int*)&pBt->nPage);
- }
}
sqlite3BtreeLeave(p);
}
@@ -46446,9 +41082,9 @@ static int btreeCursor(
assert( sqlite3BtreeHoldsMutex(p) );
assert( wrFlag==0 || wrFlag==1 );
- /* The following assert statements verify that if this is a sharable
- ** b-tree database, the connection is holding the required table locks,
- ** and that no other connection has any open cursor that conflicts with
+ /* The following assert statements verify that if this is a sharable
+ ** b-tree database, the connection is holding the required table locks,
+ ** and that no other connection has any open cursor that conflicts with
** this lock. */
assert( hasSharedCacheTableLock(p, iTable, pKeyInfo!=0, wrFlag+1) );
assert( wrFlag==0 || !hasReadConflicts(p, iTable) );
@@ -46461,7 +41097,7 @@ static int btreeCursor(
if( NEVER(wrFlag && pBt->readOnly) ){
return SQLITE_READONLY;
}
- if( iTable==1 && btreePagecount(pBt)==0 ){
+ if( iTable==1 && pagerPagecount(pBt)==0 ){
return SQLITE_EMPTY;
}
@@ -46643,14 +41279,14 @@ SQLITE_PRIVATE int sqlite3BtreeCursorIsValid(BtCursor *pCur){
/*
** Set *pSize to the size of the buffer needed to hold the value of
** the key for the current entry. If the cursor is not pointing
-** to a valid entry, *pSize is set to 0.
+** to a valid entry, *pSize is set to 0.
**
** For a table with the INTKEY flag set, this routine returns the key
** itself, not the number of bytes in the key.
**
** The caller must position the cursor prior to invoking this routine.
-**
-** This routine cannot fail. It always returns SQLITE_OK.
+**
+** This routine cannot fail. It always returns SQLITE_OK.
*/
SQLITE_PRIVATE int sqlite3BtreeKeySize(BtCursor *pCur, i64 *pSize){
assert( cursorHoldsMutex(pCur) );
@@ -46686,15 +41322,15 @@ SQLITE_PRIVATE int sqlite3BtreeDataSize(BtCursor *pCur, u32 *pSize){
/*
** Given the page number of an overflow page in the database (parameter
-** ovfl), this function finds the page number of the next page in the
+** ovfl), this function finds the page number of the next page in the
** linked list of overflow pages. If possible, it uses the auto-vacuum
-** pointer-map data instead of reading the content of page ovfl to do so.
+** pointer-map data instead of reading the content of page ovfl to do so.
**
** If an error occurs an SQLite error code is returned. Otherwise:
**
-** The page number of the next overflow page in the linked list is
-** written to *pPgnoNext. If page ovfl is the last page in its linked
-** list, *pPgnoNext is set to zero.
+** The page number of the next overflow page in the linked list is
+** written to *pPgnoNext. If page ovfl is the last page in its linked
+** list, *pPgnoNext is set to zero.
**
** If ppPage is not NULL, and a reference to the MemPage object corresponding
** to page number pOvfl was obtained, then *ppPage is set to point to that
@@ -46718,9 +41354,9 @@ static int getOverflowPage(
#ifndef SQLITE_OMIT_AUTOVACUUM
/* Try to find the next page in the overflow list using the
- ** autovacuum pointer-map pages. Guess that the next page in
- ** the overflow list is page number (ovfl+1). If that guess turns
- ** out to be wrong, fall back to loading the data of page
+ ** autovacuum pointer-map pages. Guess that the next page in
+ ** the overflow list is page number (ovfl+1). If that guess turns
+ ** out to be wrong, fall back to loading the data of page
** number ovfl to determine the next page number.
*/
if( pBt->autoVacuum ){
@@ -46732,7 +41368,7 @@ static int getOverflowPage(
iGuess++;
}
- if( iGuess<=btreePagecount(pBt) ){
+ if( iGuess<=pagerPagecount(pBt) ){
rc = ptrmapGet(pBt, iGuess, &eType, &pgno);
if( rc==SQLITE_OK && eType==PTRMAP_OVERFLOW2 && pgno==ovfl ){
next = iGuess;
@@ -46807,7 +41443,7 @@ static int copyPayload(
**
** If the BtCursor.isIncrblobHandle flag is set, and the current
** cursor entry uses one or more overflow pages, this function
-** allocates space for and lazily popluates the overflow page-list
+** allocates space for and lazily popluates the overflow page-list
** cache array (BtCursor.aOverflow). Subsequent calls use this
** cache to make seeking to the supplied offset more efficient.
**
@@ -46824,7 +41460,7 @@ static int accessPayload(
BtCursor *pCur, /* Cursor pointing to entry to read from */
u32 offset, /* Begin reading this far into payload */
u32 amt, /* Read this many bytes */
- unsigned char *pBuf, /* Write the bytes into this buffer */
+ unsigned char *pBuf, /* Write the bytes into this buffer */
int eOp /* zero to read. non-zero to write. */
){
unsigned char *aPayload;
@@ -46843,7 +41479,7 @@ static int accessPayload(
aPayload = pCur->info.pCell + pCur->info.nHeader;
nKey = (pPage->intKey ? 0 : (int)pCur->info.nKey);
- if( NEVER(offset+amt > nKey+pCur->info.nData)
+ if( NEVER(offset+amt > nKey+pCur->info.nData)
|| &aPayload[pCur->info.nLocal] > &pPage->aData[pBt->usableSize]
){
/* Trying to read or write past the end of the data is an error */
@@ -46919,7 +41555,7 @@ static int accessPayload(
#ifndef SQLITE_OMIT_INCRBLOB
if( pCur->aOverflow && pCur->aOverflow[iIdx+1] ){
nextPage = pCur->aOverflow[iIdx+1];
- } else
+ } else
#endif
rc = getOverflowPage(pBt, nextPage, 0, &nextPage);
offset -= ovflSize;
@@ -47002,7 +41638,7 @@ SQLITE_PRIVATE int sqlite3BtreeData(BtCursor *pCur, u32 offset, u32 amt, void *p
}
/*
-** Return a pointer to payload information from the entry that the
+** Return a pointer to payload information from the entry that the
** pCur cursor is pointing to. The pointer is to the beginning of
** the key if skipKey==0 and it points to the beginning of data if
** skipKey==1. The number of bytes of available key/data is written
@@ -47129,7 +41765,7 @@ static int moveToChild(BtCursor *pCur, u32 newPgno){
#ifndef NDEBUG
/*
-** Page pParent is an internal (non-leaf) tree page. This function
+** Page pParent is an internal (non-leaf) tree page. This function
** asserts that page number iChild is the left-child if the iIdx'th
** cell in page pParent. Or, if iIdx is equal to the total number of
** cells in pParent, that page number iChild is the right-child of
@@ -47144,7 +41780,7 @@ static void assertParentIndex(MemPage *pParent, int iIdx, Pgno iChild){
}
}
#else
-# define assertParentIndex(x,y,z)
+# define assertParentIndex(x,y,z)
#endif
/*
@@ -47161,8 +41797,8 @@ static void moveToParent(BtCursor *pCur){
assert( pCur->iPage>0 );
assert( pCur->apPage[pCur->iPage] );
assertParentIndex(
- pCur->apPage[pCur->iPage-1],
- pCur->aiIdx[pCur->iPage-1],
+ pCur->apPage[pCur->iPage-1],
+ pCur->aiIdx[pCur->iPage-1],
pCur->apPage[pCur->iPage]->pgno
);
releasePage(pCur->apPage[pCur->iPage]);
@@ -47176,19 +41812,19 @@ static void moveToParent(BtCursor *pCur){
**
** If the table has a virtual root page, then the cursor is moved to point
** to the virtual root page instead of the actual root page. A table has a
-** virtual root page when the actual root page contains no cells and a
+** virtual root page when the actual root page contains no cells and a
** single child page. This can only happen with the table rooted at page 1.
**
-** If the b-tree structure is empty, the cursor state is set to
+** If the b-tree structure is empty, the cursor state is set to
** CURSOR_INVALID. Otherwise, the cursor is set to point to the first
** cell located on the root (or virtual root) page and the cursor state
** is set to CURSOR_VALID.
**
** If this function returns successfully, it may be assumed that the
-** page-header flags indicate that the [virtual] root-page is the expected
+** page-header flags indicate that the [virtual] root-page is the expected
** kind of b-tree page (i.e. if when opening the cursor the caller did not
** specify a KeyInfo structure the flags byte is set to 0x05 or 0x0D,
-** indicating a table b-tree, or if the caller did specify a KeyInfo
+** indicating a table b-tree, or if the caller did specify a KeyInfo
** structure the flags byte is set to 0x02 or 0x0A, indicating an index
** b-tree).
*/
@@ -47236,8 +41872,8 @@ static int moveToRoot(BtCursor *pCur){
/* Assert that the root page is of the correct type. This must be the
** case as the call to this function that loaded the root-page (either
- ** this call or a previous invocation) would have detected corruption
- ** if the assumption were not true, and it is not possible for the flags
+ ** this call or a previous invocation) would have detected corruption
+ ** if the assumption were not true, and it is not possible for the flags
** byte to have been modified while this cursor is holding a reference
** to the page. */
pRoot = pCur->apPage[0];
@@ -47343,14 +41979,14 @@ SQLITE_PRIVATE int sqlite3BtreeFirst(BtCursor *pCur, int *pRes){
*/
SQLITE_PRIVATE int sqlite3BtreeLast(BtCursor *pCur, int *pRes){
int rc;
-
+
assert( cursorHoldsMutex(pCur) );
assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
/* If the cursor already points to the last entry, this is a no-op. */
if( CURSOR_VALID==pCur->eState && pCur->atLast ){
#ifdef SQLITE_DEBUG
- /* This block serves to assert() that the cursor really does point
+ /* This block serves to assert() that the cursor really does point
** to the last entry in the b-tree. */
int ii;
for(ii=0; ii<pCur->iPage; ii++){
@@ -47377,10 +42013,10 @@ SQLITE_PRIVATE int sqlite3BtreeLast(BtCursor *pCur, int *pRes){
return rc;
}
-/* Move the cursor so that it points to an entry near the key
+/* Move the cursor so that it points to an entry near the key
** specified by pIdxKey or intKey. Return a success code.
**
-** For INTKEY tables, the intKey parameter is used. pIdxKey
+** For INTKEY tables, the intKey parameter is used. pIdxKey
** must be NULL. For index tables, pIdxKey is used and intKey
** is ignored.
**
@@ -47390,7 +42026,7 @@ SQLITE_PRIVATE int sqlite3BtreeLast(BtCursor *pCur, int *pRes){
** before or after the key.
**
** An integer is written into *pRes which is the result of
-** comparing the key with the entry to which the cursor is
+** comparing the key with the entry to which the cursor is
** pointing. The meaning of the integer written into
** *pRes is as follows:
**
@@ -47421,8 +42057,8 @@ SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked(
/* If the cursor is already positioned at the point we are trying
** to move to, then just return without doing any work */
- if( pCur->eState==CURSOR_VALID && pCur->validNKey
- && pCur->apPage[0]->intKey
+ if( pCur->eState==CURSOR_VALID && pCur->validNKey
+ && pCur->apPage[0]->intKey
){
if( pCur->info.nKey==intKey ){
*pRes = 0;
@@ -47495,9 +42131,9 @@ SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked(
/* The maximum supported page-size is 32768 bytes. This means that
** the maximum number of record bytes stored on an index B-Tree
** page is at most 8198 bytes, which may be stored as a 2-byte
- ** varint. This information is used to attempt to avoid parsing
- ** the entire cell by checking for the cases where the record is
- ** stored entirely within the b-tree page by inspecting the first
+ ** varint. This information is used to attempt to avoid parsing
+ ** the entire cell by checking for the cases where the record is
+ ** stored entirely within the b-tree page by inspecting the first
** 2 bytes of the cell.
*/
int nCell = pCell[0];
@@ -47506,10 +42142,10 @@ SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked(
** single byte varint and the record fits entirely on the main
** b-tree page. */
c = sqlite3VdbeRecordCompare(nCell, (void*)&pCell[1], pIdxKey);
- }else if( !(pCell[1] & 0x80)
+ }else if( !(pCell[1] & 0x80)
&& (nCell = ((nCell&0x7f)<<7) + pCell[1])<=pPage->maxLocal
){
- /* The record-size field is a 2 byte varint and the record
+ /* The record-size field is a 2 byte varint and the record
** fits entirely on the main b-tree page. */
c = sqlite3VdbeRecordCompare(nCell, (void*)&pCell[2], pIdxKey);
}else{
@@ -47738,19 +42374,19 @@ SQLITE_PRIVATE int sqlite3BtreePrevious(BtCursor *pCur, int *pRes){
** an error. *ppPage and *pPgno are undefined in the event of an error.
** Do not invoke sqlite3PagerUnref() on *ppPage if an error is returned.
**
-** If the "nearby" parameter is not 0, then a (feeble) effort is made to
+** If the "nearby" parameter is not 0, then a (feeble) effort is made to
** locate a page close to the page number "nearby". This can be used in an
** attempt to keep related pages close to each other in the database file,
** which in turn can make database access faster.
**
-** If the "exact" parameter is not 0, and the page-number nearby exists
+** If the "exact" parameter is not 0, and the page-number nearby exists
** anywhere on the free-list, then it is guarenteed to be returned. This
** is only used by auto-vacuum databases when allocating a new table.
*/
static int allocateBtreePage(
- BtShared *pBt,
- MemPage **ppPage,
- Pgno *pPgno,
+ BtShared *pBt,
+ MemPage **ppPage,
+ Pgno *pPgno,
Pgno nearby,
u8 exact
){
@@ -47764,7 +42400,7 @@ static int allocateBtreePage(
assert( sqlite3_mutex_held(pBt->mutex) );
pPage1 = pBt->pPage1;
- mxPage = btreePagecount(pBt);
+ mxPage = pagerPagecount(pBt);
n = get4byte(&pPage1->aData[36]);
testcase( n==mxPage-1 );
if( n>=mxPage ){
@@ -47774,7 +42410,7 @@ static int allocateBtreePage(
/* There are pages on the freelist. Reuse one of those pages. */
Pgno iTrunk;
u8 searchList = 0; /* If the free-list must be searched for 'nearby' */
-
+
/* If the 'exact' parameter was true and a query of the pointer-map
** shows that the page 'nearby' is somewhere on the free-list, then
** the entire-list will be searched for that page.
@@ -47824,8 +42460,8 @@ static int allocateBtreePage(
k = get4byte(&pTrunk->aData[4]);
if( k==0 && !searchList ){
- /* The trunk has no leaves and the list is not being searched.
- ** So extract the trunk page itself and use it as the newly
+ /* The trunk has no leaves and the list is not being searched.
+ ** So extract the trunk page itself and use it as the newly
** allocated page */
assert( pPrevTrunk==0 );
rc = sqlite3PagerWrite(pTrunk->pDbPage);
@@ -47860,13 +42496,13 @@ static int allocateBtreePage(
memcpy(&pPrevTrunk->aData[0], &pTrunk->aData[0], 4);
}
}else{
- /* The trunk page is required by the caller but it contains
+ /* The trunk page is required by the caller but it contains
** pointers to free-list leaves. The first leaf becomes a trunk
** page in this case.
*/
MemPage *pNewTrunk;
Pgno iNewTrunk = get4byte(&pTrunk->aData[8]);
- if( iNewTrunk>mxPage ){
+ if( iNewTrunk>mxPage ){
rc = SQLITE_CORRUPT_BKPT;
goto end_allocate_page;
}
@@ -47960,35 +42596,35 @@ static int allocateBtreePage(
}else{
/* There are no pages on the freelist, so create a new page at the
** end of the file */
- rc = sqlite3PagerWrite(pBt->pPage1->pDbPage);
- if( rc ) return rc;
- pBt->nPage++;
- if( pBt->nPage==PENDING_BYTE_PAGE(pBt) ) pBt->nPage++;
+ int nPage = pagerPagecount(pBt);
+ *pPgno = nPage + 1;
+
+ if( *pPgno==PENDING_BYTE_PAGE(pBt) ){
+ (*pPgno)++;
+ }
#ifndef SQLITE_OMIT_AUTOVACUUM
- if( pBt->autoVacuum && PTRMAP_ISPAGE(pBt, pBt->nPage) ){
+ if( pBt->autoVacuum && PTRMAP_ISPAGE(pBt, *pPgno) ){
/* If *pPgno refers to a pointer-map page, allocate two new pages
** at the end of the file instead of one. The first allocated page
** becomes a new pointer-map page, the second is used by the caller.
*/
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, 1);
+ TRACE(("ALLOCATE: %d from end of file (pointer-map page)\n", *pPgno));
+ assert( *pPgno!=PENDING_BYTE_PAGE(pBt) );
+ rc = btreeGetPage(pBt, *pPgno, &pPg, 0);
if( rc==SQLITE_OK ){
rc = sqlite3PagerWrite(pPg->pDbPage);
releasePage(pPg);
}
if( rc ) return rc;
- pBt->nPage++;
- if( pBt->nPage==PENDING_BYTE_PAGE(pBt) ){ pBt->nPage++; }
+ (*pPgno)++;
+ if( *pPgno==PENDING_BYTE_PAGE(pBt) ){ (*pPgno)++; }
}
#endif
- put4byte(28 + (u8*)pBt->pPage1->aData, pBt->nPage);
- *pPgno = pBt->nPage;
assert( *pPgno!=PENDING_BYTE_PAGE(pBt) );
- rc = btreeGetPage(pBt, *pPgno, ppPage, 1);
+ rc = btreeGetPage(pBt, *pPgno, ppPage, 0);
if( rc ) return rc;
rc = sqlite3PagerWrite((*ppPage)->pDbPage);
if( rc!=SQLITE_OK ){
@@ -48015,12 +42651,12 @@ end_allocate_page:
}
/*
-** This function is used to add page iPage to the database file free-list.
+** This function is used to add page iPage to the database file free-list.
** It is assumed that the page is not already a part of the free-list.
**
** The value passed as the second argument to this function is optional.
-** If the caller happens to have a pointer to the MemPage object
-** corresponding to page iPage handy, it may pass it as the second value.
+** If the caller happens to have a pointer to the MemPage object
+** corresponding to page iPage handy, it may pass it as the second value.
** Otherwise, it may pass NULL.
**
** If a pointer to a MemPage object is passed as the second argument,
@@ -48028,7 +42664,7 @@ end_allocate_page:
*/
static int freePage2(BtShared *pBt, MemPage *pMemPage, Pgno iPage){
MemPage *pTrunk = 0; /* Free-list trunk page */
- Pgno iTrunk = 0; /* Page number of free-list trunk page */
+ Pgno iTrunk = 0; /* Page number of free-list trunk page */
MemPage *pPage1 = pBt->pPage1; /* Local reference to page 1 */
MemPage *pPage; /* Page being freed. May be NULL. */
int rc; /* Return Code */
@@ -48051,17 +42687,17 @@ static int freePage2(BtShared *pBt, MemPage *pMemPage, Pgno iPage){
nFree = get4byte(&pPage1->aData[36]);
put4byte(&pPage1->aData[36], nFree+1);
- if( pBt->secureDelete ){
- /* If the secure_delete option is enabled, then
- ** always fully overwrite deleted information with zeros.
- */
- if( (!pPage && ((rc = btreeGetPage(pBt, iPage, &pPage, 0))!=0) )
- || ((rc = sqlite3PagerWrite(pPage->pDbPage))!=0)
- ){
- goto freepage_out;
- }
- memset(pPage->aData, 0, pPage->pBt->pageSize);
+#ifdef SQLITE_SECURE_DELETE
+ /* If the SQLITE_SECURE_DELETE compile-time option is enabled, then
+ ** always fully overwrite deleted information with zeros.
+ */
+ if( (!pPage && (rc = btreeGetPage(pBt, iPage, &pPage, 0)))
+ || (rc = sqlite3PagerWrite(pPage->pDbPage))
+ ){
+ goto freepage_out;
}
+ memset(pPage->aData, 0, pPage->pBt->pageSize);
+#endif
/* If the database supports auto-vacuum, write an entry in the pointer-map
** to indicate that the page is free.
@@ -48112,9 +42748,11 @@ static int freePage2(BtShared *pBt, MemPage *pMemPage, Pgno iPage){
if( rc==SQLITE_OK ){
put4byte(&pTrunk->aData[4], nLeaf+1);
put4byte(&pTrunk->aData[8+nLeaf*4], iPage);
- if( pPage && !pBt->secureDelete ){
+#ifndef SQLITE_SECURE_DELETE
+ if( pPage ){
sqlite3PagerDontWrite(pPage->pDbPage);
}
+#endif
rc = btreeSetHasContent(pBt, iPage);
}
TRACE(("FREE-PAGE: %d leaf on trunk page %d\n",pPage->pgno,pTrunk->pgno));
@@ -48124,7 +42762,7 @@ static int freePage2(BtShared *pBt, MemPage *pMemPage, Pgno iPage){
/* If control flows to this point, then it was not possible to add the
** the page being freed as a leaf page of the first trunk in the free-list.
- ** Possibly because the free-list is empty, or possibly because the
+ ** Possibly because the free-list is empty, or possibly because the
** 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.
*/
@@ -48178,9 +42816,9 @@ static int clearCell(MemPage *pPage, unsigned char *pCell){
while( nOvfl-- ){
Pgno iNext = 0;
MemPage *pOvfl = 0;
- if( ovflPgno<2 || ovflPgno>btreePagecount(pBt) ){
- /* 0 is not a legal page number and page 1 cannot be an
- ** overflow page. Therefore if ovflPgno<2 or past the end of the
+ if( ovflPgno<2 || ovflPgno>pagerPagecount(pBt) ){
+ /* 0 is not a legal page number and page 1 cannot be an
+ ** overflow page. Therefore if ovflPgno<2 or past the end of the
** file the database must be corrupt. */
return SQLITE_CORRUPT_BKPT;
}
@@ -48188,25 +42826,7 @@ static int clearCell(MemPage *pPage, unsigned char *pCell){
rc = getOverflowPage(pBt, ovflPgno, &pOvfl, &iNext);
if( rc ) return rc;
}
-
- if( ( pOvfl || ((pOvfl = btreePageLookup(pBt, ovflPgno))!=0) )
- && sqlite3PagerPageRefcount(pOvfl->pDbPage)!=1
- ){
- /* There is no reason any cursor should have an outstanding reference
- ** to an overflow page belonging to a cell that is being deleted/updated.
- ** So if there exists more than one reference to this page, then it
- ** must not really be an overflow page and the database must be corrupt.
- ** It is helpful to detect this before calling freePage2(), as
- ** freePage2() may zero the page contents if secure-delete mode is
- ** enabled. If this 'overflow' page happens to be a page that the
- ** caller is iterating through or using in some other way, this
- ** can be problematic.
- */
- rc = SQLITE_CORRUPT_BKPT;
- }else{
- rc = freePage2(pBt, pOvfl, ovflPgno);
- }
-
+ rc = freePage2(pBt, pOvfl, ovflPgno);
if( pOvfl ){
sqlite3PagerUnref(pOvfl->pDbPage);
}
@@ -48271,14 +42891,14 @@ static int fillInCell(
assert( info.nHeader==nHeader );
assert( info.nKey==nKey );
assert( info.nData==(u32)(nData+nZero) );
-
+
/* Fill in the payload */
nPayload = nData + nZero;
if( pPage->intKey ){
pSrc = pData;
nSrc = nData;
nData = 0;
- }else{
+ }else{
if( NEVER(nKey>0x7fffffff || pKey==0) ){
return SQLITE_CORRUPT_BKPT;
}
@@ -48298,8 +42918,8 @@ static int fillInCell(
if( pBt->autoVacuum ){
do{
pgnoOvfl++;
- } while(
- PTRMAP_ISPAGE(pBt, pgnoOvfl) || pgnoOvfl==PENDING_BYTE_PAGE(pBt)
+ } while(
+ PTRMAP_ISPAGE(pBt, pgnoOvfl) || pgnoOvfl==PENDING_BYTE_PAGE(pBt)
);
}
#endif
@@ -48307,9 +42927,9 @@ static int fillInCell(
#ifndef SQLITE_OMIT_AUTOVACUUM
/* If the database supports auto-vacuum, and the second or subsequent
** overflow page is being allocated, add an entry to the pointer-map
- ** for that page now.
+ ** for that page now.
**
- ** If this is the first overflow page, then write a partial entry
+ ** If this is the first overflow page, then write a partial entry
** to the pointer-map. If we write nothing to this pointer-map slot,
** then the optimistic overflow chain processing in clearCell()
** may misinterpret the uninitialised values and delete the
@@ -48432,13 +43052,13 @@ static void dropCell(MemPage *pPage, int idx, int sz, int *pRC){
** will not fit, then make a copy of the cell content into pTemp if
** pTemp is not null. Regardless of pTemp, allocate a new entry
** in pPage->aOvfl[] and make it point to the cell content (either
-** in pTemp or the original pCell) and also record its index.
-** Allocating a new entry in pPage->aCell[] implies that
+** in pTemp or the original pCell) and also record its index.
+** Allocating a new entry in pPage->aCell[] implies that
** pPage->nOverflow is incremented.
**
** If nSkip is non-zero, then do not copy the first nSkip bytes of the
** cell. The caller will overwrite them after this function returns. If
-** nSkip is non-zero, then pCell may not point to an invalid memory location
+** nSkip is non-zero, then pCell may not point to an invalid memory location
** (but pCell+nSkip is always valid).
*/
static void insertCell(
@@ -48450,7 +43070,7 @@ static void insertCell(
Pgno iChild, /* If non-zero, replace first 4 bytes with this value */
int *pRC /* Read and write return code from here */
){
- int idx = 0; /* Where to write new cell content in data[] */
+ int idx; /* Where to write new cell content in data[] */
int j; /* Loop counter */
int end; /* First byte past the last cell pointer in data[] */
int ins; /* Index in data[] where new cell pointer is inserted */
@@ -48616,7 +43236,7 @@ static int balance_quick(MemPage *pParent, MemPage *pPage, u8 *pSpace){
if( pPage->nCell<=0 ) return SQLITE_CORRUPT_BKPT;
- /* Allocate a new page. This page will become the right-sibling of
+ /* Allocate a new page. This page will become the right-sibling of
** pPage. Make the parent page writable, so that the new divider cell
** may be inserted. If both these operations are successful, proceed.
*/
@@ -48635,7 +43255,7 @@ static int balance_quick(MemPage *pParent, MemPage *pPage, u8 *pSpace){
assemblePage(pNew, 1, &pCell, &szCell);
/* If this is an auto-vacuum database, update the pointer map
- ** with entries for the new page, and any pointer from the
+ ** with entries for the new page, and any pointer from the
** cell on the page to an overflow page. If either of these
** operations fails, the return code is set, but the contents
** of the parent page are still manipulated by thh code below.
@@ -48649,14 +43269,14 @@ static int balance_quick(MemPage *pParent, MemPage *pPage, u8 *pSpace){
ptrmapPutOvflPtr(pNew, pCell, &rc);
}
}
-
+
/* Create a divider cell to insert into pParent. The divider cell
** consists of a 4-byte page number (the page number of pPage) and
** a variable length key value (which must be the same value as the
** largest key on pPage).
**
- ** To find the largest key value on pPage, first find the right-most
- ** cell on pPage. The first two fields of this cell are the
+ ** To find the largest key value on pPage, first find the right-most
+ ** cell on pPage. The first two fields of this cell are the
** record-length (a variable length integer at most 32-bits in size)
** and the key value (a variable length integer, may have any value).
** The first of the while(...) loops below skips over the record-length
@@ -48675,7 +43295,7 @@ static int balance_quick(MemPage *pParent, MemPage *pPage, u8 *pSpace){
/* Set the right-child pointer of pParent to point to the new page. */
put4byte(&pParent->aData[pParent->hdrOffset+8], pgnoNew);
-
+
/* Release the reference to the new page. */
releasePage(pNew);
}
@@ -48687,7 +43307,7 @@ static int balance_quick(MemPage *pParent, MemPage *pPage, u8 *pSpace){
#if 0
/*
** This function does not contribute anything to the operation of SQLite.
-** it is sometimes activated temporarily while debugging code responsible
+** it is sometimes activated temporarily while debugging code responsible
** for setting pointer-map entries.
*/
static int ptrmapCheckPages(MemPage **apPage, int nPage){
@@ -48702,7 +43322,7 @@ static int ptrmapCheckPages(MemPage **apPage, int nPage){
for(j=0; j<pPage->nCell; j++){
CellInfo info;
u8 *z;
-
+
z = findCell(pPage, j);
btreeParseCellPtr(pPage, z, &info);
if( info.iOverflow ){
@@ -48727,7 +43347,7 @@ static int ptrmapCheckPages(MemPage **apPage, int nPage){
#endif
/*
-** This function is used to copy the contents of the b-tree node stored
+** This function is used to copy the contents of the b-tree node stored
** on page pFrom to page pTo. If page pFrom was not a leaf page, then
** the pointer-map entries for each child page are updated so that the
** parent page stored in the pointer map is page pTo. If pFrom contained
@@ -48735,11 +43355,11 @@ static int ptrmapCheckPages(MemPage **apPage, int nPage){
** map entries are also updated so that the parent page is page pTo.
**
** If pFrom is currently carrying any overflow cells (entries in the
-** MemPage.aOvfl[] array), they are not copied to pTo.
+** MemPage.aOvfl[] array), they are not copied to pTo.
**
** Before returning, page pTo is reinitialized using btreeInitPage().
**
-** The performance of this function is not critical. It is only used by
+** The performance of this function is not critical. It is only used by
** the balance_shallower() and balance_deeper() procedures, neither of
** which are called often under normal circumstances.
*/
@@ -48752,20 +43372,20 @@ static void copyNodeContent(MemPage *pFrom, MemPage *pTo, int *pRC){
int const iToHdr = ((pTo->pgno==1) ? 100 : 0);
int rc;
int iData;
-
-
+
+
assert( pFrom->isInit );
assert( pFrom->nFree>=iToHdr );
assert( get2byte(&aFrom[iFromHdr+5])<=pBt->usableSize );
-
+
/* Copy the b-tree node content from page pFrom to page pTo. */
iData = get2byte(&aFrom[iFromHdr+5]);
memcpy(&aTo[iData], &aFrom[iData], pBt->usableSize-iData);
memcpy(&aTo[iToHdr], &aFrom[iFromHdr], pFrom->cellOffset + 2*pFrom->nCell);
-
+
/* Reinitialize page pTo so that the contents of the MemPage structure
** match the new data. The initialization of pTo can actually fail under
- ** fairly obscure circumstances, even though it is a copy of initialized
+ ** fairly obscure circumstances, even though it is a copy of initialized
** page pFrom.
*/
pTo->isInit = 0;
@@ -48774,7 +43394,7 @@ static void copyNodeContent(MemPage *pFrom, MemPage *pTo, int *pRC){
*pRC = rc;
return;
}
-
+
/* If this is an auto-vacuum database, update the pointer-map entries
** for any b-tree or overflow pages that pTo now contains the pointers to.
*/
@@ -48789,13 +43409,13 @@ static void copyNodeContent(MemPage *pFrom, MemPage *pTo, int *pRC){
** (hereafter "the page") and up to 2 siblings so that all pages have about the
** same amount of free space. Usually a single sibling on either side of the
** page are used in the balancing, though both siblings might come from one
-** side if the page is the first or last child of its parent. If the page
+** side if the page is the first or last child of its parent. If the page
** has fewer than 2 siblings (something which can only happen if the page
** is a root page or a child of a root page) then all available siblings
** participate in the balancing.
**
-** The number of siblings of the page might be increased or decreased by
-** one or two in an effort to keep pages nearly full but not over full.
+** The number of siblings of the page might be increased or decreased by
+** one or two in an effort to keep pages nearly full but not over full.
**
** Note that when this routine is called, some of the cells on the page
** might not actually be stored in MemPage.aData[]. This can happen
@@ -48806,7 +43426,7 @@ static void copyNodeContent(MemPage *pFrom, MemPage *pTo, int *pRC){
** inserted into or removed from the parent page (pParent). Doing so
** may cause the parent page to become overfull or underfull. If this
** happens, it is the responsibility of the caller to invoke the correct
-** balancing routine to fix this problem (see the balance() routine).
+** balancing routine to fix this problem (see the balance() routine).
**
** If this routine fails for any reason, it might leave the database
** in a corrupted state. So if this routine fails, the database should
@@ -48821,7 +43441,7 @@ static void copyNodeContent(MemPage *pFrom, MemPage *pTo, int *pRC){
** of the page-size, the aOvflSpace[] buffer is guaranteed to be large
** enough for all overflow cells.
**
-** If aOvflSpace is set to a null pointer, this function returns
+** If aOvflSpace is set to a null pointer, this function returns
** SQLITE_NOMEM.
*/
static int balance_nonroot(
@@ -48867,7 +43487,7 @@ static int balance_nonroot(
#endif
/* At this point pParent may have at most one overflow cell. And if
- ** this overflow cell is present, it must be the cell with
+ ** this overflow cell is present, it must be the cell with
** index iParentIdx. This scenario comes about when this function
** is called (indirectly) from sqlite3BtreeDelete().
*/
@@ -48878,11 +43498,11 @@ static int balance_nonroot(
return SQLITE_NOMEM;
}
- /* Find the sibling pages to balance. Also locate the cells in pParent
- ** that divide the siblings. An attempt is made to find NN siblings on
- ** either side of pPage. More siblings are taken from one side, however,
+ /* Find the sibling pages to balance. Also locate the cells in pParent
+ ** that divide the siblings. An attempt is made to find NN siblings on
+ ** either side of pPage. More siblings are taken from one side, however,
** if there are fewer than NN siblings on the other side. If pParent
- ** has NB or fewer children then all children of pParent are taken.
+ ** has NB or fewer children then all children of pParent are taken.
**
** This loop also drops the divider cells from the parent page. This
** way, the remainder of the function does not have to deal with any
@@ -48895,7 +43515,7 @@ static int balance_nonroot(
nOld = i+1;
}else{
nOld = 3;
- if( iParentIdx==0 ){
+ if( iParentIdx==0 ){
nxDiv = 0;
}else if( iParentIdx==i ){
nxDiv = i-2;
@@ -48934,24 +43554,17 @@ static int balance_nonroot(
** This is safe because dropping a cell only overwrites the first
** four bytes of it, and this function does not need the first
** four bytes of the divider cell. So the pointer is safe to use
- ** later on.
+ ** later on.
**
** Unless SQLite is compiled in secure-delete mode. In this case,
** the dropCell() routine will overwrite the entire cell with zeroes.
** In this case, temporarily copy the cell into the aOvflSpace[]
** buffer. It will be copied out again as soon as the aSpace[] buffer
** is allocated. */
- if( pBt->secureDelete ){
- int iOff = SQLITE_PTR_TO_INT(apDiv[i]) - SQLITE_PTR_TO_INT(pParent->aData);
- if( (iOff+szNew[i])>pBt->usableSize ){
- rc = SQLITE_CORRUPT_BKPT;
- memset(apOld, 0, (i+1)*sizeof(MemPage*));
- goto balance_cleanup;
- }else{
- memcpy(&aOvflSpace[iOff], apDiv[i], szNew[i]);
- apDiv[i] = &aOvflSpace[apDiv[i]-pParent->aData];
- }
- }
+#ifdef SQLITE_SECURE_DELETE
+ memcpy(&aOvflSpace[apDiv[i]-pParent->aData], apDiv[i], szNew[i]);
+ apDiv[i] = &aOvflSpace[apDiv[i]-pParent->aData];
+#endif
dropCell(pParent, i+nxDiv-pParent->nOverflow, szNew[i], &rc);
}
}
@@ -48969,7 +43582,7 @@ static int balance_nonroot(
+ nMaxCells*sizeof(u16) /* szCell */
+ pBt->pageSize /* aSpace1 */
+ k*nOld; /* Page copies (apCopy) */
- apCell = sqlite3ScratchMalloc( szScratch );
+ apCell = sqlite3ScratchMalloc( szScratch );
if( apCell==0 ){
rc = SQLITE_NOMEM;
goto balance_cleanup;
@@ -48998,7 +43611,7 @@ static int balance_nonroot(
leafData = apOld[0]->hasData;
for(i=0; i<nOld; i++){
int limit;
-
+
/* Before doing anything else, take a copy of the i'th original sibling
** The rest of this function will use data from the copies rather
** that the original pages since the original pages will be in the
@@ -49049,7 +43662,7 @@ static int balance_nonroot(
** Figure out the number of pages needed to hold all nCell cells.
** Store this number in "k". Also compute szNew[] which is the total
** size of all cells on the i-th page and cntNew[] which is the index
- ** in apCell[] of the cell that divides page i from page i+1.
+ ** in apCell[] of the cell that divides page i from page i+1.
** cntNew[k] should equal nCell.
**
** Values computed by this block:
@@ -49059,7 +43672,7 @@ static int balance_nonroot(
** cntNew[i]: Index in apCell[] and szCell[] for the first cell to
** the right of the i-th sibling page.
** usableSpace: Number of bytes of space available on each sibling.
- **
+ **
*/
usableSpace = pBt->usableSize - 12 + leafCorrection;
for(subtotal=k=i=0; i<nCell; i++){
@@ -49116,7 +43729,7 @@ static int balance_nonroot(
assert( cntNew[0]>0 || (pParent->pgno==1 && pParent->nCell==0) );
TRACE(("BALANCE: old: %d %d %d ",
- apOld[0]->pgno,
+ apOld[0]->pgno,
nOld>=2 ? apOld[1]->pgno : 0,
nOld>=3 ? apOld[2]->pgno : 0
));
@@ -49238,9 +43851,9 @@ static int balance_nonroot(
if( !pNew->leaf ){
memcpy(&pNew->aData[8], pCell, 4);
}else if( leafData ){
- /* If the tree is a leaf-data tree, and the siblings are leaves,
- ** then there is no divider cell in apCell[]. Instead, the divider
- ** cell consists of the integer key for the right-most cell of
+ /* If the tree is a leaf-data tree, and the siblings are leaves,
+ ** then there is no divider cell in apCell[]. Instead, the divider
+ ** cell consists of the integer key for the right-most cell of
** the sibling-page assembled above only.
*/
CellInfo info;
@@ -49253,9 +43866,9 @@ static int balance_nonroot(
pCell -= 4;
/* Obscure case for non-leaf-data trees: If the cell at pCell was
** previously stored on a leaf node, and its reported size was 4
- ** bytes, then it may actually be smaller than this
+ ** bytes, then it may actually be smaller than this
** (see btreeParseCellPtr(), 4 bytes is the minimum size of
- ** any cell). But it is important to pass the correct size to
+ ** any cell). But it is important to pass the correct size to
** insertCell(), so reparse the cell now.
**
** Note that this can never happen in an SQLite data file, as all
@@ -49293,8 +43906,8 @@ static int balance_nonroot(
** b-tree structure by one. This is described as the "balance-shallower"
** sub-algorithm in some documentation.
**
- ** If this is an auto-vacuum database, the call to copyNodeContent()
- ** sets all pointer-map entries corresponding to database image pages
+ ** If this is an auto-vacuum database, the call to copyNodeContent()
+ ** sets all pointer-map entries corresponding to database image pages
** for which the pointer is stored within the content being copied.
**
** The second assert below verifies that the child page is defragmented
@@ -49302,13 +43915,13 @@ static int balance_nonroot(
** is important if the parent page happens to be page 1 of the database
** image. */
assert( nNew==1 );
- assert( apNew[0]->nFree ==
- (get2byte(&apNew[0]->aData[5])-apNew[0]->cellOffset-apNew[0]->nCell*2)
+ assert( apNew[0]->nFree ==
+ (get2byte(&apNew[0]->aData[5])-apNew[0]->cellOffset-apNew[0]->nCell*2)
);
copyNodeContent(apNew[0], pParent, &rc);
freePage(apNew[0], &rc);
}else if( ISAUTOVACUUM ){
- /* Fix the pointer-map entries for all the cells that were shifted around.
+ /* Fix the pointer-map entries for all the cells that were shifted around.
** There are several different types of pointer-map entries that need to
** be dealt with by this routine. Some of these have been set already, but
** many have not. The following is a summary:
@@ -49320,7 +43933,7 @@ static int balance_nonroot(
** of those.
**
** 2) The pointer-map entries associated with the first overflow
- ** page in any overflow chains used by new divider cells. These
+ ** page in any overflow chains used by new divider cells. These
** have also already been taken care of by the insertCell() code.
**
** 3) If the sibling pages are not leaves, then the child pages of
@@ -49358,7 +43971,7 @@ static int balance_nonroot(
nOverflow = pOld->nOverflow;
iOverflow = i + !leafData + pOld->aOvfl[0].idx;
}
- isDivider = !leafData;
+ isDivider = !leafData;
}
assert(nOverflow>0 || iOverflow<i );
@@ -49404,7 +44017,7 @@ static int balance_nonroot(
#if 0
/* The ptrmapCheckPages() contains assert() statements that verify that
- ** all pointer map pages are set correctly. This is helpful while
+ ** all pointer map pages are set correctly. This is helpful while
** debugging. This is usually disabled because a corrupt database may
** cause an assert() statement to fail. */
ptrmapCheckPages(apNew, nNew);
@@ -49438,15 +44051,15 @@ balance_cleanup:
**
** A new child page is allocated and the contents of the current root
** page, including overflow cells, are copied into the child. The root
-** page is then overwritten to make it an empty page with the right-child
+** page is then overwritten to make it an empty page with the right-child
** pointer pointing to the new page.
**
-** Before returning, all pointer-map entries corresponding to pages
+** Before returning, all pointer-map entries corresponding to pages
** that the new child-page now contains pointers to are updated. The
** entry corresponding to the new right-child pointer of the root
** page is also updated.
**
-** If successful, *ppChild is set to contain a reference to the child
+** If successful, *ppChild is set to contain a reference to the child
** page and SQLITE_OK is returned. In this case the caller is required
** to call releasePage() on *ppChild exactly once. If an error occurs,
** an error code is returned and *ppChild is set to 0.
@@ -49460,7 +44073,7 @@ static int balance_deeper(MemPage *pRoot, MemPage **ppChild){
assert( pRoot->nOverflow>0 );
assert( sqlite3_mutex_held(pBt->mutex) );
- /* Make pRoot, the root page of the b-tree, writable. Allocate a new
+ /* Make pRoot, the root page of the b-tree, writable. Allocate a new
** page that will become the new right-child of pPage. Copy the contents
** of the node stored on pRoot into the new child page.
*/
@@ -49498,7 +44111,7 @@ static int balance_deeper(MemPage *pRoot, MemPage **ppChild){
/*
** The page that pCur currently points to has just been modified in
** some way. This function figures out if this modification means the
-** tree needs to be balanced, and if so calls the appropriate balancing
+** tree needs to be balanced, and if so calls the appropriate balancing
** routine. Balancing routines are:
**
** balance_quick()
@@ -49524,7 +44137,7 @@ static int balance(BtCursor *pCur){
** balance_deeper() function to create a new child for the root-page
** and copy the current contents of the root-page to it. The
** next iteration of the do-loop will balance the child page.
- */
+ */
assert( (balance_deeper_called++)==0 );
rc = balance_deeper(pPage, &pCur->apPage[1]);
if( rc==SQLITE_OK ){
@@ -49554,10 +44167,10 @@ static int balance(BtCursor *pCur){
/* Call balance_quick() to create a new sibling of pPage on which
** to store the overflow cell. balance_quick() inserts a new cell
** into pParent, which may cause pParent overflow. If this
- ** happens, the next interation of the do-loop will balance pParent
+ ** happens, the next interation of the do-loop will balance pParent
** use either balance_nonroot() or balance_deeper(). Until this
** happens, the overflow cell is stored in the aBalanceQuickSpace[]
- ** buffer.
+ ** buffer.
**
** The purpose of the following assert() is to check that only a
** single call to balance_quick() is made for each call to this
@@ -49574,24 +44187,24 @@ static int balance(BtCursor *pCur){
** modifying the contents of pParent, which may cause pParent to
** become overfull or underfull. The next iteration of the do-loop
** will balance the parent page to correct this.
- **
+ **
** If the parent page becomes overfull, the overflow cell or cells
- ** are stored in the pSpace buffer allocated immediately below.
+ ** are stored in the pSpace buffer allocated immediately below.
** A subsequent iteration of the do-loop will deal with this by
** calling balance_nonroot() (balance_deeper() may be called first,
** but it doesn't deal with overflow cells - just moves them to a
- ** different page). Once this subsequent call to balance_nonroot()
+ ** different page). Once this subsequent call to balance_nonroot()
** has completed, it is safe to release the pSpace buffer used by
- ** the previous call, as the overflow cell data will have been
+ ** the previous call, as the overflow cell data will have been
** copied either into the body of a database page or into the new
** pSpace buffer passed to the latter call to balance_nonroot().
*/
u8 *pSpace = sqlite3PageMalloc(pCur->pBt->pageSize);
rc = balance_nonroot(pParent, iIdx, pSpace, iPage==1);
if( pFree ){
- /* If pFree is not NULL, it points to the pSpace buffer used
+ /* If pFree is not NULL, it points to the pSpace buffer used
** by a previous call to balance_nonroot(). Its contents are
- ** now stored either on real database pages or within the
+ ** now stored either on real database pages or within the
** new pSpace buffer, so it may be safely freed here. */
sqlite3PageFree(pFree);
}
@@ -49631,8 +44244,8 @@ static int balance(BtCursor *pCur){
** MovetoUnpacked() to seek cursor pCur to (pKey, nKey) has already
** been performed. seekResult is the search result returned (a negative
** number if pCur points at an entry that is smaller than (pKey, nKey), or
-** a positive value if pCur points at an etry that is larger than
-** (pKey, nKey)).
+** a positive value if pCur points at an etry that is larger than
+** (pKey, nKey)).
**
** If the seekResult parameter is non-zero, then the caller guarantees that
** cursor pCur is pointing at the existing copy of a row that is to be
@@ -49674,7 +44287,7 @@ SQLITE_PRIVATE int sqlite3BtreeInsert(
** blob of associated data. */
assert( (pKey==0)==(pCur->pKeyInfo==0) );
- /* If this is an insert into a table b-tree, invalidate any incrblob
+ /* If this is an insert into a table b-tree, invalidate any incrblob
** cursors open on the row being replaced (assuming this is a replace
** operation - if it is not, the following is a no-op). */
if( pCur->pKeyInfo==0 ){
@@ -49685,8 +44298,8 @@ SQLITE_PRIVATE int sqlite3BtreeInsert(
**
** In some cases, the call to btreeMoveto() below is a no-op. For
** example, when inserting data into a table with auto-generated integer
- ** keys, the VDBE layer invokes sqlite3BtreeLast() to figure out the
- ** integer key to use. It then calls this function to actually insert the
+ ** keys, the VDBE layer invokes sqlite3BtreeLast() to figure out the
+ ** integer key to use. It then calls this function to actually insert the
** data into the intkey B-Tree. In this case btreeMoveto() recognizes
** that the cursor is already where it needs to be and returns without
** doing any work. To avoid thwarting these optimizations, it is important
@@ -49740,7 +44353,7 @@ SQLITE_PRIVATE int sqlite3BtreeInsert(
insertCell(pPage, idx, newCell, szNew, 0, 0, &rc);
assert( rc!=SQLITE_OK || pPage->nCell>0 || pPage->nOverflow>0 );
- /* If no error has occured and pPage has an overflow cell, call balance()
+ /* If no error has occured and pPage has an overflow cell, call balance()
** to redistribute the cells within the tree. Since balance() may move
** the cursor, zero the BtCursor.info.nSize and BtCursor.validNKey
** variables.
@@ -49766,7 +44379,7 @@ SQLITE_PRIVATE int sqlite3BtreeInsert(
rc = balance(pCur);
/* Must make sure nOverflow is reset to zero even if the balance()
- ** fails. Internal data structure corruption will result otherwise.
+ ** fails. Internal data structure corruption will result otherwise.
** Also, set the cursor state to invalid. This stops saveCursorPosition()
** from trying to save the current position of the cursor. */
pCur->apPage[pCur->iPage]->nOverflow = 0;
@@ -49784,12 +44397,12 @@ end_insert:
*/
SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor *pCur){
Btree *p = pCur->pBtree;
- BtShared *pBt = p->pBt;
+ BtShared *pBt = p->pBt;
int rc; /* Return code */
MemPage *pPage; /* Page to delete cell from */
unsigned char *pCell; /* Pointer to cell to delete */
int iCellIdx; /* Index of cell to delete */
- int iCellDepth; /* Depth of node containing pCell */
+ int iCellDepth; /* Depth of node containing pCell */
assert( cursorHoldsMutex(pCur) );
assert( pBt->inTransaction==TRANS_WRITE );
@@ -49798,7 +44411,7 @@ SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor *pCur){
assert( hasSharedCacheTableLock(p, pCur->pgnoRoot, pCur->pKeyInfo!=0, 2) );
assert( !hasReadConflicts(p, pCur->pgnoRoot) );
- if( NEVER(pCur->aiIdx[pCur->iPage]>=pCur->apPage[pCur->iPage]->nCell)
+ if( NEVER(pCur->aiIdx[pCur->iPage]>=pCur->apPage[pCur->iPage]->nCell)
|| NEVER(pCur->eState!=CURSOR_VALID)
){
return SQLITE_ERROR; /* Something has gone awry. */
@@ -49829,9 +44442,9 @@ SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor *pCur){
}
/* Save the positions of any other cursors open on this table before
- ** making any modifications. Make the page containing the entry to be
- ** deleted writable. Then free any overflow pages associated with the
- ** entry and finally remove the cell itself from within the page.
+ ** making any modifications. Make the page containing the entry to be
+ ** deleted writable. Then free any overflow pages associated with the
+ ** entry and finally remove the cell itself from within the page.
*/
rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur);
if( rc ) return rc;
@@ -49878,7 +44491,7 @@ SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor *pCur){
** on the leaf node first. If the balance proceeds far enough up the
** tree that we can be sure that any problem in the internal node has
** been corrected, so be it. Otherwise, after balancing the leaf node,
- ** walk the cursor up the tree to the internal node and balance it as
+ ** walk the cursor up the tree to the internal node and balance it as
** well. */
rc = balance(pCur);
if( rc==SQLITE_OK && pCur->iPage>iCellDepth ){
@@ -50002,7 +44615,7 @@ static int btreeCreateTable(Btree *p, int *piTable, int flags){
}
}else{
pRoot = pPageMove;
- }
+ }
/* Update the pointer-map and meta-data with the new root-page number. */
ptrmapPut(pBt, pgnoRoot, PTRMAP_ROOTPAGE, 0, &rc);
@@ -50010,14 +44623,8 @@ static int btreeCreateTable(Btree *p, int *piTable, int flags){
releasePage(pRoot);
return rc;
}
-
- /* When the new root page was allocated, page 1 was made writable in
- ** order either to increase the database filesize, or to decrement the
- ** freelist count. Hence, the sqlite3BtreeUpdateMeta() call cannot fail.
- */
- assert( sqlite3PagerIswriteable(pBt->pPage1->pDbPage) );
rc = sqlite3BtreeUpdateMeta(p, 4, pgnoRoot);
- if( NEVER(rc) ){
+ if( rc ){
releasePage(pRoot);
return rc;
}
@@ -50057,7 +44664,7 @@ static int clearDatabasePage(
int i;
assert( sqlite3_mutex_held(pBt->mutex) );
- if( pgno>btreePagecount(pBt) ){
+ if( pgno>pagerPagecount(pBt) ){
return SQLITE_CORRUPT_BKPT;
}
@@ -50131,12 +44738,12 @@ SQLITE_PRIVATE int sqlite3BtreeClearTable(Btree *p, int iTable, int *pnChange){
** cursors on the table.
**
** If AUTOVACUUM is enabled and the page at iTable is not the last
-** root page in the database file, then the last root page
+** root page in the database file, then the last root page
** in the database file is moved into the slot formerly occupied by
** iTable and that last slot formerly occupied by the last root page
** is added to the freelist instead of iTable. In this say, all
** root pages are kept at the beginning of the database file, which
-** is necessary for AUTOVACUUM to work right. *piMoved is set to the
+** is necessary for AUTOVACUUM to work right. *piMoved is set to the
** page number that used to be the last root page in the file before
** the move. If no page gets moved, *piMoved is set to 0.
** The last root page is recorded in meta[3] and the value of
@@ -50153,7 +44760,7 @@ static int btreeDropTable(Btree *p, Pgno iTable, int *piMoved){
/* It is illegal to drop a table if any cursors are open on the
** database. This is because in auto-vacuum mode the backend may
** need to move another root-page to fill a gap left by the deleted
- ** root page. If an open cursor was using this page a problem would
+ ** root page. If an open cursor was using this page a problem would
** occur.
**
** This error is caught long before control reaches this point.
@@ -50184,7 +44791,7 @@ static int btreeDropTable(Btree *p, Pgno iTable, int *piMoved){
if( iTable==maxRootPgno ){
/* If the table being dropped is the table with the largest root-page
- ** number in the database, put the root page on the free list.
+ ** number in the database, put the root page on the free list.
*/
freePage(pPage, &rc);
releasePage(pPage);
@@ -50193,7 +44800,7 @@ static int btreeDropTable(Btree *p, Pgno iTable, int *piMoved){
}
}else{
/* The table being dropped does not have the largest root-page
- ** number in the database. So move the page that does into the
+ ** number in the database. So move the page that does into the
** gap left by the deleted root-page.
*/
MemPage *pMove;
@@ -50238,12 +44845,12 @@ static int btreeDropTable(Btree *p, Pgno iTable, int *piMoved){
}else{
/* If sqlite3BtreeDropTable was called on page 1.
** This really never should happen except in a corrupt
- ** database.
+ ** database.
*/
zeroPage(pPage, PTF_INTKEY|PTF_LEAF );
releasePage(pPage);
}
- return rc;
+ return rc;
}
SQLITE_PRIVATE int sqlite3BtreeDropTable(Btree *p, int iTable, int *piMoved){
int rc;
@@ -50262,7 +44869,7 @@ SQLITE_PRIVATE int sqlite3BtreeDropTable(Btree *p, int iTable, int *piMoved){
** is the number of free pages currently in the database. Meta[1]
** through meta[15] are available for use by higher layers. Meta[0]
** is read-only, the others are read/write.
-**
+**
** The schema layer numbers meta values differently. At the schema
** layer (and the SetCookie and ReadCookie opcodes) the number of
** free pages is not visible. So Cookie[0] is the same as Meta[1].
@@ -50320,7 +44927,7 @@ SQLITE_PRIVATE int sqlite3BtreeUpdateMeta(Btree *p, int idx, u32 iMeta){
** The first argument, pCur, is a cursor opened on some b-tree. Count the
** number of entries in the b-tree and write the result to *pnEntry.
**
-** SQLITE_OK is returned if the operation is successfully executed.
+** SQLITE_OK is returned if the operation is successfully executed.
** Otherwise, if an error is encountered (i.e. an IO error or database
** corruption) an SQLite error code is returned.
*/
@@ -50330,13 +44937,13 @@ SQLITE_PRIVATE int sqlite3BtreeCount(BtCursor *pCur, i64 *pnEntry){
rc = moveToRoot(pCur);
/* Unless an error occurs, the following loop runs one iteration for each
- ** page in the B-Tree structure (not including overflow pages).
+ ** page in the B-Tree structure (not including overflow pages).
*/
while( rc==SQLITE_OK ){
int iIdx; /* Index of child node in parent */
MemPage *pPage; /* Current page of the b-tree */
- /* If this is a leaf page or the tree is not an int-key tree, then
+ /* If this is a leaf page or the tree is not an int-key tree, then
** this page contains countable entries. Increment the entry counter
** accordingly.
*/
@@ -50345,7 +44952,7 @@ SQLITE_PRIVATE int sqlite3BtreeCount(BtCursor *pCur, i64 *pnEntry){
nEntry += pPage->nCell;
}
- /* pPage is a leaf node. This loop navigates the cursor so that it
+ /* pPage is a leaf node. This loop navigates the cursor so that it
** points to the first interior cell that it points to the parent of
** the next page in the tree that has not yet been visited. The
** pCur->aiIdx[pCur->iPage] value is set to the index of the parent cell
@@ -50369,7 +44976,7 @@ SQLITE_PRIVATE int sqlite3BtreeCount(BtCursor *pCur, i64 *pnEntry){
pPage = pCur->apPage[pCur->iPage];
}
- /* Descend to the child node of the cell that the cursor currently
+ /* Descend to the child node of the cell that the cursor currently
** points at. This is the right-child if (iIdx==pPage->nCell).
*/
iIdx = pCur->aiIdx[pCur->iPage];
@@ -50446,7 +45053,7 @@ static int checkRef(IntegrityCk *pCheck, Pgno iPage, char *zContext){
#ifndef SQLITE_OMIT_AUTOVACUUM
/*
-** Check that the entry in the pointer-map for page iChild maps to
+** Check that the entry in the pointer-map for page iChild maps to
** page iParent, pointer type ptrType. If not, append an error message
** to pCheck.
*/
@@ -50469,8 +45076,8 @@ static void checkPtrmap(
}
if( ePtrmapType!=eType || iPtrmapParent!=iParent ){
- checkAppendMsg(pCheck, zContext,
- "Bad ptr map entry key=%d expected=(%d,%d) got=(%d,%d)",
+ checkAppendMsg(pCheck, zContext,
+ "Bad ptr map entry key=%d expected=(%d,%d) got=(%d,%d)",
iChild, eType, iParent, ePtrmapType, iPtrmapParent);
}
}
@@ -50552,7 +45159,7 @@ static void checkList(
** Do various sanity checks on a single page of a tree. Return
** the tree depth. Root pages return 0. Parents of root pages
** return 1, and so forth.
-**
+**
** These checks are done:
**
** 1. Make sure that cells and freeblocks do not overlap
@@ -50570,7 +45177,7 @@ static int checkTreePage(
IntegrityCk *pCheck, /* Context for the sanity check */
int iPage, /* Page number of the page to check */
char *zParentContext, /* Parent context */
- i64 *pnParentMinKey,
+ i64 *pnParentMinKey,
i64 *pnParentMaxKey
){
MemPage *pPage;
@@ -50604,7 +45211,7 @@ static int checkTreePage(
pPage->isInit = 0;
if( (rc = btreeInitPage(pPage))!=0 ){
assert( rc==SQLITE_CORRUPT ); /* The only possible error from InitPage */
- checkAppendMsg(pCheck, zContext,
+ checkAppendMsg(pCheck, zContext,
"btreeInitPage() returns error code %d", rc);
releasePage(pPage);
return 0;
@@ -50631,13 +45238,13 @@ static int checkTreePage(
else if( i==0 ) nMinKey = nMaxKey = info.nKey;
else{
if( info.nKey <= nMaxKey ){
- checkAppendMsg(pCheck, zContext,
+ checkAppendMsg(pCheck, zContext,
"Rowid %lld out of order (previous was %lld)", info.nKey, nMaxKey);
}
nMaxKey = info.nKey;
}
assert( sz==info.nPayload );
- if( (sz>info.nLocal)
+ if( (sz>info.nLocal)
&& (&pCell[info.iOverflow]<=&pPage->aData[pBt->usableSize])
){
int nPage = (sz - info.nLocal + usableSize - 5)/(usableSize - 4);
@@ -50669,7 +45276,7 @@ static int checkTreePage(
if( !pPage->leaf ){
pgno = get4byte(&pPage->aData[pPage->hdrOffset+8]);
- sqlite3_snprintf(sizeof(zContext), zContext,
+ sqlite3_snprintf(sizeof(zContext), zContext,
"On page %d at right child: ", iPage);
#ifndef SQLITE_OMIT_AUTOVACUUM
if( pBt->autoVacuum ){
@@ -50678,7 +45285,7 @@ static int checkTreePage(
#endif
checkTreePage(pCheck, pgno, zContext, NULL, !pPage->nCell ? NULL : &nMaxKey);
}
-
+
/* For intKey leaf pages, check that the min/max keys are in order
** with any left/parent/right pages.
*/
@@ -50688,18 +45295,18 @@ static int checkTreePage(
/* if we are the left most child page */
if( !pnParentMaxKey ){
if( nMaxKey > *pnParentMinKey ){
- checkAppendMsg(pCheck, zContext,
+ checkAppendMsg(pCheck, zContext,
"Rowid %lld out of order (max larger than parent min of %lld)",
nMaxKey, *pnParentMinKey);
}
}else{
if( nMinKey <= *pnParentMinKey ){
- checkAppendMsg(pCheck, zContext,
+ checkAppendMsg(pCheck, zContext,
"Rowid %lld out of order (min less than parent min of %lld)",
nMinKey, *pnParentMinKey);
}
if( nMaxKey > *pnParentMaxKey ){
- checkAppendMsg(pCheck, zContext,
+ checkAppendMsg(pCheck, zContext,
"Rowid %lld out of order (max larger than parent max of %lld)",
nMaxKey, *pnParentMaxKey);
}
@@ -50708,7 +45315,7 @@ static int checkTreePage(
/* else if we're a right child page */
} else if( pnParentMaxKey ){
if( nMinKey <= *pnParentMaxKey ){
- checkAppendMsg(pCheck, zContext,
+ checkAppendMsg(pCheck, zContext,
"Rowid %lld out of order (min less than parent max of %lld)",
nMinKey, *pnParentMaxKey);
}
@@ -50737,7 +45344,7 @@ static int checkTreePage(
size = cellSizePtr(pPage, &data[pc]);
}
if( (pc+size-1)>=usableSize ){
- checkAppendMsg(pCheck, 0,
+ checkAppendMsg(pCheck, 0,
"Corruption detected in cell %d on page %d",i,iPage);
}else{
for(j=pc+size-1; j>=pc; j--) hit[j]++;
@@ -50765,7 +45372,7 @@ static int checkTreePage(
}
}
if( cnt!=data[hdr+7] ){
- checkAppendMsg(pCheck, 0,
+ checkAppendMsg(pCheck, 0,
"Fragmentation of %d bytes reported as %d on page %d",
cnt, data[hdr+7], iPage);
}
@@ -50808,7 +45415,7 @@ SQLITE_PRIVATE char *sqlite3BtreeIntegrityCheck(
nRef = sqlite3PagerRefcount(pBt->pPager);
sCheck.pBt = pBt;
sCheck.pPager = pBt->pPager;
- sCheck.nPage = btreePagecount(sCheck.pBt);
+ sCheck.nPage = pagerPagecount(sCheck.pBt);
sCheck.mxErr = mxErr;
sCheck.nErr = 0;
sCheck.mallocFailed = 0;
@@ -50858,11 +45465,11 @@ SQLITE_PRIVATE char *sqlite3BtreeIntegrityCheck(
/* If the database supports auto-vacuum, make sure no tables contain
** references to pointer-map pages.
*/
- if( sCheck.anRef[i]==0 &&
+ if( sCheck.anRef[i]==0 &&
(PTRMAP_PAGENO(pBt, i)!=i || !pBt->autoVacuum) ){
checkAppendMsg(&sCheck, 0, "Page %d is never used", i);
}
- if( sCheck.anRef[i]!=0 &&
+ if( sCheck.anRef[i]!=0 &&
(PTRMAP_PAGENO(pBt, i)==i && pBt->autoVacuum) ){
checkAppendMsg(&sCheck, 0, "Pointer map page %d is referenced", i);
}
@@ -50874,7 +45481,7 @@ SQLITE_PRIVATE char *sqlite3BtreeIntegrityCheck(
** of the integrity check.
*/
if( NEVER(nRef != sqlite3PagerRefcount(pBt->pPager)) ){
- checkAppendMsg(&sCheck, 0,
+ checkAppendMsg(&sCheck, 0,
"Outstanding page count goes from %d to %d during this analysis",
nRef, sqlite3PagerRefcount(pBt->pPager)
);
@@ -50945,20 +45552,20 @@ SQLITE_PRIVATE int sqlite3BtreeIsInBackup(Btree *p){
/*
** This function returns a pointer to a blob of memory associated with
** a single shared-btree. The memory is used by client code for its own
-** purposes (for example, to store a high-level schema associated with
+** purposes (for example, to store a high-level schema associated with
** the shared-btree). The btree layer manages reference counting issues.
**
** The first time this is called on a shared-btree, nBytes bytes of memory
-** are allocated, zeroed, and returned to the caller. For each subsequent
+** are allocated, zeroed, and returned to the caller. For each subsequent
** call the nBytes parameter is ignored and a pointer to the same blob
-** of memory returned.
+** of memory returned.
**
** If the nBytes parameter is 0 and the blob of memory has not yet been
** allocated, a null pointer is returned. If the blob has already been
** allocated, it is returned as normal.
**
-** Just before the shared-btree is closed, the function passed as the
-** xFree argument when the memory allocation was made is invoked on the
+** Just before the shared-btree is closed, the function passed as the
+** xFree argument when the memory allocation was made is invoked on the
** blob of allocated memory. This function should not call sqlite3_free()
** on the memory, the btree layer does that.
*/
@@ -50974,8 +45581,8 @@ SQLITE_PRIVATE void *sqlite3BtreeSchema(Btree *p, int nBytes, void(*xFree)(void
}
/*
-** Return SQLITE_LOCKED_SHAREDCACHE if another user of the same shared
-** btree as the argument handle holds an exclusive lock on the
+** Return SQLITE_LOCKED_SHAREDCACHE if another user of the same shared
+** btree as the argument handle holds an exclusive lock on the
** sqlite_master table. Otherwise SQLITE_OK.
*/
SQLITE_PRIVATE int sqlite3BtreeSchemaLocked(Btree *p){
@@ -51016,11 +45623,11 @@ SQLITE_PRIVATE int sqlite3BtreeLockTable(Btree *p, int iTab, u8 isWriteLock){
#ifndef SQLITE_OMIT_INCRBLOB
/*
-** Argument pCsr must be a cursor opened for writing on an
-** INTKEY table currently pointing at a valid table entry.
+** Argument pCsr must be a cursor opened for writing on an
+** INTKEY table currently pointing at a valid table entry.
** This function modifies the data stored as part of that entry.
**
-** Only the data content may only be modified, it is not possible to
+** Only the data content may only be modified, it is not possible to
** change the length of the data stored. If this function is called with
** parameters that attempt to write past the end of the existing data,
** no modifications are made and SQLITE_CORRUPT is returned.
@@ -51040,7 +45647,7 @@ SQLITE_PRIVATE int sqlite3BtreePutData(BtCursor *pCsr, u32 offset, u32 amt, void
return SQLITE_ABORT;
}
- /* Check some assumptions:
+ /* Check some assumptions:
** (a) the cursor is open for writing,
** (b) there is a read/write transaction open,
** (c) the connection holds a write-lock on the table (if required),
@@ -51058,8 +45665,8 @@ SQLITE_PRIVATE int sqlite3BtreePutData(BtCursor *pCsr, u32 offset, u32 amt, void
return accessPayload(pCsr, offset, amt, (unsigned char *)z, 1);
}
-/*
-** Set a flag on this cursor to cache the locations of pages from the
+/*
+** Set a flag on this cursor to cache the locations of pages from the
** overflow list for the current row. This is used by cursors opened
** for incremental blob IO only.
**
@@ -51077,42 +45684,6 @@ SQLITE_PRIVATE void sqlite3BtreeCacheOverflow(BtCursor *pCur){
}
#endif
-/*
-** Set both the "read version" (single byte at byte offset 18) and
-** "write version" (single byte at byte offset 19) fields in the database
-** header to iVersion.
-*/
-SQLITE_PRIVATE int sqlite3BtreeSetVersion(Btree *pBtree, int iVersion){
- BtShared *pBt = pBtree->pBt;
- int rc; /* Return code */
-
- assert( pBtree->inTrans==TRANS_NONE );
- assert( iVersion==1 || iVersion==2 );
-
- /* If setting the version fields to 1, do not automatically open the
- ** WAL connection, even if the version fields are currently set to 2.
- */
- pBt->doNotUseWAL = (iVersion==1);
-
- rc = sqlite3BtreeBeginTrans(pBtree, 0);
- if( rc==SQLITE_OK ){
- u8 *aData = pBt->pPage1->aData;
- if( aData[18]!=(u8)iVersion || aData[19]!=(u8)iVersion ){
- rc = sqlite3BtreeBeginTrans(pBtree, 2);
- if( rc==SQLITE_OK ){
- rc = sqlite3PagerWrite(pBt->pPage1->pDbPage);
- if( rc==SQLITE_OK ){
- aData[18] = (u8)iVersion;
- aData[19] = (u8)iVersion;
- }
- }
- }
- }
-
- pBt->doNotUseWAL = 0;
- return rc;
-}
-
/************** End of btree.c ***********************************************/
/************** Begin file backup.c ******************************************/
/*
@@ -51126,7 +45697,7 @@ SQLITE_PRIVATE int sqlite3BtreeSetVersion(Btree *pBtree, int iVersion){
** May you share freely, never taking more than you give.
**
*************************************************************************
-** This file contains the implementation of the sqlite3_backup_XXX()
+** This file contains the implementation of the sqlite3_backup_XXX()
** API functions and the related features.
*/
@@ -51167,15 +45738,15 @@ struct sqlite3_backup {
** Once it has been created using backup_init(), a single sqlite3_backup
** structure may be accessed via two groups of thread-safe entry points:
**
-** * Via the sqlite3_backup_XXX() API function backup_step() and
+** * Via the sqlite3_backup_XXX() API function backup_step() and
** backup_finish(). Both these functions obtain the source database
-** handle mutex and the mutex associated with the source BtShared
+** handle mutex and the mutex associated with the source BtShared
** structure, in that order.
**
** * Via the BackupUpdate() and BackupRestart() functions, which are
** invoked by the pager layer to report various state changes in
** the page cache associated with the source database. The mutex
-** associated with the source database BtShared structure will always
+** associated with the source database BtShared structure will always
** be held when either of these functions are invoked.
**
** The other sqlite3_backup_XXX() API functions, backup_remaining() and
@@ -51196,8 +45767,8 @@ struct sqlite3_backup {
** in connection handle pDb. If such a database cannot be found, return
** a NULL pointer and write an error message to pErrorDb.
**
-** If the "temp" database is requested, it may need to be opened by this
-** function. If an error occurs while doing so, return 0 and write an
+** If the "temp" database is requested, it may need to be opened by this
+** function. If an error occurs while doing so, return 0 and write an
** error message to pErrorDb.
*/
static Btree *findBtree(sqlite3 *pErrorDb, sqlite3 *pDb, const char *zDb){
@@ -51301,7 +45872,7 @@ SQLITE_API sqlite3_backup *sqlite3_backup_init(
}
/*
-** Argument rc is an SQLite error code. Return true if this error is
+** Argument rc is an SQLite error code. Return true if this error is
** considered fatal if encountered during a backup operation. All errors
** are considered fatal except for SQLITE_BUSY and SQLITE_LOCKED.
*/
@@ -51310,8 +45881,8 @@ static int isFatalError(int rc){
}
/*
-** Parameter zSrcData points to a buffer containing the data for
-** page iSrcPg from the source database. Copy this data into the
+** Parameter zSrcData points to a buffer containing the data for
+** page iSrcPg from the source database. Copy this data into the
** destination database.
*/
static int backupOnePage(sqlite3_backup *p, Pgno iSrcPg, const u8 *zSrcData){
@@ -51330,13 +45901,13 @@ static int backupOnePage(sqlite3_backup *p, Pgno iSrcPg, const u8 *zSrcData){
assert( zSrcData );
/* Catch the case where the destination is an in-memory database and the
- ** page sizes of the source and destination differ.
+ ** page sizes of the source and destination differ.
*/
- if( nSrcPgsz!=nDestPgsz && sqlite3PagerIsMemdb(pDestPager) ){
+ if( nSrcPgsz!=nDestPgsz && sqlite3PagerIsMemdb(sqlite3BtreePager(p->pDest)) ){
rc = SQLITE_READONLY;
}
- /* This loop runs once for each destination page spanned by the source
+ /* This loop runs once for each destination page spanned by the source
** page. For each iteration, variable iOff is set to the byte offset
** of the destination page.
*/
@@ -51355,7 +45926,7 @@ static int backupOnePage(sqlite3_backup *p, Pgno iSrcPg, const u8 *zSrcData){
** Then clear the Btree layer MemPage.isInit flag. Both this module
** and the pager code use this trick (clearing the first byte
** of the page 'extra' space to invalidate the Btree layers
- ** cached parse of the page). MemPage.isInit is marked
+ ** cached parse of the page). MemPage.isInit is marked
** "MUST BE FIRST" for this purpose.
*/
memcpy(zOut, zIn, nCopy);
@@ -51372,7 +45943,7 @@ static int backupOnePage(sqlite3_backup *p, Pgno iSrcPg, const u8 *zSrcData){
** exactly iSize bytes. If pFile is not larger than iSize bytes, then
** this function is a no-op.
**
-** Return SQLITE_OK if everything is successful, or an SQLite error
+** Return SQLITE_OK if everything is successful, or an SQLite error
** code if an error occurs.
*/
static int backupTruncateFile(sqlite3_file *pFile, i64 iSize){
@@ -51402,9 +45973,6 @@ static void attachBackupObject(sqlite3_backup *p){
*/
SQLITE_API int sqlite3_backup_step(sqlite3_backup *p, int nPage){
int rc;
- int destMode; /* Destination journal mode */
- int pgszSrc = 0; /* Source page size */
- int pgszDest = 0; /* Destination page size */
sqlite3_mutex_enter(p->pSrcDb->mutex);
sqlite3BtreeEnter(p->pSrc);
@@ -51431,7 +45999,7 @@ SQLITE_API int sqlite3_backup_step(sqlite3_backup *p, int nPage){
/* Lock the destination database, if it is not locked already. */
if( SQLITE_OK==rc && p->bDestLocked==0
- && SQLITE_OK==(rc = sqlite3BtreeBeginTrans(p->pDest, 2))
+ && SQLITE_OK==(rc = sqlite3BtreeBeginTrans(p->pDest, 2))
){
p->bDestLocked = 1;
sqlite3BtreeGetMeta(p->pDest, BTREE_SCHEMA_VERSION, &p->iDestSchema);
@@ -51445,22 +46013,13 @@ SQLITE_API int sqlite3_backup_step(sqlite3_backup *p, int nPage){
rc = sqlite3BtreeBeginTrans(p->pSrc, 0);
bCloseTrans = 1;
}
-
- /* Do not allow backup if the destination database is in WAL mode
- ** and the page sizes are different between source and destination */
- pgszSrc = sqlite3BtreeGetPageSize(p->pSrc);
- pgszDest = sqlite3BtreeGetPageSize(p->pDest);
- destMode = sqlite3PagerJournalMode(sqlite3BtreePager(p->pDest),
- PAGER_JOURNALMODE_QUERY);
- if( SQLITE_OK==rc && destMode==PAGER_JOURNALMODE_WAL && pgszSrc!=pgszDest ){
- rc = SQLITE_READONLY;
- }
-
+
/* Now that there is a read-lock on the source database, query the
** source pager for the number of pages in the database.
*/
- nSrcPage = (int)sqlite3BtreeLastPage(p->pSrc);
- assert( nSrcPage>=0 );
+ if( rc==SQLITE_OK ){
+ rc = sqlite3PagerPagecount(pSrcPager, &nSrcPage);
+ }
for(ii=0; (nPage<0 || ii<nPage) && p->iNext<=(Pgno)nSrcPage && !rc; ii++){
const Pgno iSrcPg = p->iNext; /* Source page number */
if( iSrcPg!=PENDING_BYTE_PAGE(p->pSrc->pBt) ){
@@ -51482,81 +46041,81 @@ SQLITE_API int sqlite3_backup_step(sqlite3_backup *p, int nPage){
attachBackupObject(p);
}
}
-
+
/* Update the schema version field in the destination database. This
** is to make sure that the schema-version really does change in
** the case where the source and destination databases have the
** same schema version.
*/
- if( rc==SQLITE_DONE
+ if( rc==SQLITE_DONE
&& (rc = sqlite3BtreeUpdateMeta(p->pDest,1,p->iDestSchema+1))==SQLITE_OK
){
+ const int nSrcPagesize = sqlite3BtreeGetPageSize(p->pSrc);
+ const int nDestPagesize = sqlite3BtreeGetPageSize(p->pDest);
int nDestTruncate;
-
+
if( p->pDestDb ){
sqlite3ResetInternalSchema(p->pDestDb, 0);
}
/* Set nDestTruncate to the final number of pages in the destination
** database. The complication here is that the destination page
- ** size may be different to the source page size.
+ ** size may be different to the source page size.
**
- ** If the source page size is smaller than the destination page size,
+ ** If the source page size is smaller than the destination page size,
** round up. In this case the call to sqlite3OsTruncate() below will
** fix the size of the file. However it is important to call
- ** sqlite3PagerTruncateImage() here so that any pages in the
+ ** sqlite3PagerTruncateImage() here so that any pages in the
** destination file that lie beyond the nDestTruncate page mark are
** journalled by PagerCommitPhaseOne() before they are destroyed
** by the file truncation.
*/
- assert( pgszSrc==sqlite3BtreeGetPageSize(p->pSrc) );
- assert( pgszDest==sqlite3BtreeGetPageSize(p->pDest) );
- if( pgszSrc<pgszDest ){
- int ratio = pgszDest/pgszSrc;
+ if( nSrcPagesize<nDestPagesize ){
+ int ratio = nDestPagesize/nSrcPagesize;
nDestTruncate = (nSrcPage+ratio-1)/ratio;
if( nDestTruncate==(int)PENDING_BYTE_PAGE(p->pDest->pBt) ){
nDestTruncate--;
}
}else{
- nDestTruncate = nSrcPage * (pgszSrc/pgszDest);
+ nDestTruncate = nSrcPage * (nSrcPagesize/nDestPagesize);
}
sqlite3PagerTruncateImage(pDestPager, nDestTruncate);
- if( pgszSrc<pgszDest ){
+ if( nSrcPagesize<nDestPagesize ){
/* If the source page-size is smaller than the destination page-size,
** two extra things may need to happen:
**
** * The destination may need to be truncated, and
**
- ** * Data stored on the pages immediately following the
+ ** * Data stored on the pages immediately following the
** pending-byte page in the source database may need to be
** copied into the destination database.
*/
- const i64 iSize = (i64)pgszSrc * (i64)nSrcPage;
+ const i64 iSize = (i64)nSrcPagesize * (i64)nSrcPage;
sqlite3_file * const pFile = sqlite3PagerFile(pDestPager);
assert( pFile );
- assert( (i64)nDestTruncate*(i64)pgszDest >= iSize || (
+ assert( (i64)nDestTruncate*(i64)nDestPagesize >= iSize || (
nDestTruncate==(int)(PENDING_BYTE_PAGE(p->pDest->pBt)-1)
- && iSize>=PENDING_BYTE && iSize<=PENDING_BYTE+pgszDest
+ && iSize>=PENDING_BYTE && iSize<=PENDING_BYTE+nDestPagesize
));
if( SQLITE_OK==(rc = sqlite3PagerCommitPhaseOne(pDestPager, 0, 1))
&& SQLITE_OK==(rc = backupTruncateFile(pFile, iSize))
&& SQLITE_OK==(rc = sqlite3PagerSync(pDestPager))
){
i64 iOff;
- i64 iEnd = MIN(PENDING_BYTE + pgszDest, iSize);
+ i64 iEnd = MIN(PENDING_BYTE + nDestPagesize, iSize);
for(
- iOff=PENDING_BYTE+pgszSrc;
- rc==SQLITE_OK && iOff<iEnd;
- iOff+=pgszSrc
+ iOff=PENDING_BYTE+nSrcPagesize;
+ rc==SQLITE_OK && iOff<iEnd;
+ iOff+=nSrcPagesize
){
PgHdr *pSrcPg = 0;
- const Pgno iSrcPg = (Pgno)((iOff/pgszSrc)+1);
+ const Pgno iSrcPg = (Pgno)((iOff/nSrcPagesize)+1);
rc = sqlite3PagerGet(pSrcPager, iSrcPg, &pSrcPg);
if( rc==SQLITE_OK ){
u8 *zData = sqlite3PagerGetData(pSrcPg);
- rc = sqlite3OsWrite(pFile, zData, pgszSrc, iOff);
+ rc = sqlite3OsWrite(pFile, zData, nSrcPagesize, iOff);
}
sqlite3PagerUnref(pSrcPg);
}
@@ -51564,7 +46123,7 @@ SQLITE_API int sqlite3_backup_step(sqlite3_backup *p, int nPage){
}else{
rc = sqlite3PagerCommitPhaseOne(pDestPager, 0, 0);
}
-
+
/* Finish committing the transaction to the destination database. */
if( SQLITE_OK==rc
&& SQLITE_OK==(rc = sqlite3BtreeCommitPhaseTwo(p->pDest))
@@ -51572,7 +46131,7 @@ SQLITE_API int sqlite3_backup_step(sqlite3_backup *p, int nPage){
rc = SQLITE_DONE;
}
}
-
+
/* If bCloseTrans is true, then this function opened a read transaction
** on the source database. Close the read transaction here. There is
** no need to check the return values of the btree methods here, as
@@ -51584,7 +46143,7 @@ SQLITE_API int sqlite3_backup_step(sqlite3_backup *p, int nPage){
TESTONLY( rc2 |= ) sqlite3BtreeCommitPhaseTwo(p->pSrc);
assert( rc2==SQLITE_OK );
}
-
+
p->rc = rc;
}
if( p->pDestDb ){
@@ -51652,7 +46211,7 @@ SQLITE_API int sqlite3_backup_remaining(sqlite3_backup *p){
}
/*
-** Return the total number of pages in the source database as of the most
+** Return the total number of pages in the source database as of the most
** recent call to sqlite3_backup_step().
*/
SQLITE_API int sqlite3_backup_pagecount(sqlite3_backup *p){
@@ -51661,7 +46220,7 @@ SQLITE_API int sqlite3_backup_pagecount(sqlite3_backup *p){
/*
** This function is called after the contents of page iPage of the
-** source database have been modified. If page iPage has already been
+** source database have been modified. If page iPage has already been
** copied into the destination database, then the data written to the
** destination is now invalidated. The destination copy of iPage needs
** to be updated with the new data before the backup operation is
@@ -51693,7 +46252,7 @@ SQLITE_PRIVATE void sqlite3BackupUpdate(sqlite3_backup *pBackup, Pgno iPage, con
** Restart the backup process. This is called when the pager layer
** detects that the database has been modified by an external database
** connection. In this case there is no way of knowing which of the
-** pages that have been copied into the destination database are still
+** pages that have been copied into the destination database are still
** valid and which are not, so the entire process needs to be restarted.
**
** It is assumed that the mutex associated with the BtShared object
@@ -51713,8 +46272,8 @@ SQLITE_PRIVATE void sqlite3BackupRestart(sqlite3_backup *pBackup){
** Copy the complete content of pBtFrom into pBtTo. A transaction
** must be active for both files.
**
-** The size of file pTo may be reduced by this operation. If anything
-** goes wrong, the transaction on pTo is rolled back. If successful, the
+** The size of file pTo may be reduced by this operation. If anything
+** goes wrong, the transaction on pTo is rolled back. If successful, the
** transaction is committed before returning.
*/
SQLITE_PRIVATE int sqlite3BtreeCopyFile(Btree *pTo, Btree *pFrom){
@@ -51736,9 +46295,9 @@ SQLITE_PRIVATE int sqlite3BtreeCopyFile(Btree *pTo, Btree *pFrom){
/* 0x7FFFFFFF is the hard limit for the number of pages in a database
** file. By passing this as the number of pages to copy to
- ** sqlite3_backup_step(), we can guarantee that the copy finishes
+ ** sqlite3_backup_step(), we can guarantee that the copy finishes
** within a single call (unless an error occurs). The assert() statement
- ** checks this assumption - (p->rc) should be set to either SQLITE_DONE
+ ** checks this assumption - (p->rc) should be set to either SQLITE_DONE
** or an error code.
*/
sqlite3_backup_step(&b, 0x7FFFFFFF);
@@ -51818,23 +46377,23 @@ SQLITE_PRIVATE int sqlite3VdbeChangeEncoding(Mem *pMem, int desiredEnc){
}
/*
-** Make sure pMem->z points to a writable allocation of at least
+** Make sure pMem->z points to a writable allocation of at least
** n bytes.
**
** If the memory cell currently contains string or blob data
-** and the third argument passed to this function is true, the
+** and the third argument passed to this function is true, the
** current content of the cell is preserved. Otherwise, it may
-** be discarded.
+** be discarded.
**
** This function sets the MEM_Dyn flag and clears any xDel callback.
-** It also clears MEM_Ephem and MEM_Static. If the preserve flag is
+** It also clears MEM_Ephem and MEM_Static. If the preserve flag is
** not set, Mem.n is zeroed.
*/
SQLITE_PRIVATE int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve){
assert( 1 >=
((pMem->zMalloc && pMem->zMalloc==pMem->z) ? 1 : 0) +
- (((pMem->flags&MEM_Dyn)&&pMem->xDel) ? 1 : 0) +
- ((pMem->flags&MEM_Ephem) ? 1 : 0) +
+ (((pMem->flags&MEM_Dyn)&&pMem->xDel) ? 1 : 0) +
+ ((pMem->flags&MEM_Ephem) ? 1 : 0) +
((pMem->flags&MEM_Static) ? 1 : 0)
);
assert( (pMem->flags&MEM_RowSet)==0 );
@@ -51973,7 +46532,7 @@ SQLITE_PRIVATE int sqlite3VdbeMemStringify(Mem *pMem, int enc){
/* For a Real or Integer, use sqlite3_mprintf() to produce the UTF-8
** string representation of the value. Then, if the required encoding
** is UTF-16le or UTF-16be do a translation.
- **
+ **
** FIX ME: It would be better if sqlite3_snprintf() could do UTF-16.
*/
if( fg & MEM_Int ){
@@ -52071,10 +46630,6 @@ SQLITE_PRIVATE void sqlite3VdbeMemRelease(Mem *p){
** before attempting the conversion.
*/
static i64 doubleToInt64(double r){
-#ifdef SQLITE_OMIT_FLOATING_POINT
- /* When floating-point is omitted, double and int64 are the same thing */
- return r;
-#else
/*
** Many compilers we encounter do not define constants for the
** minimum and maximum 64-bit integers, or they define them
@@ -52096,7 +46651,6 @@ static i64 doubleToInt64(double r){
}else{
return (i64)r;
}
-#endif
}
/*
@@ -52224,26 +46778,21 @@ SQLITE_PRIVATE int sqlite3VdbeMemRealify(Mem *pMem){
/*
** Convert pMem so that it has types MEM_Real or MEM_Int or both.
** Invalidate any prior representations.
-**
-** Every effort is made to force the conversion, even if the input
-** is a string that does not look completely like a number. Convert
-** as much of the string as we can and ignore the rest.
*/
SQLITE_PRIVATE int sqlite3VdbeMemNumerify(Mem *pMem){
- int rc;
+ double r1, r2;
+ i64 i;
assert( (pMem->flags & (MEM_Int|MEM_Real|MEM_Null))==0 );
assert( (pMem->flags & (MEM_Blob|MEM_Str))!=0 );
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
- rc = sqlite3VdbeChangeEncoding(pMem, SQLITE_UTF8);
- if( rc ) return rc;
- rc = sqlite3VdbeMemNulTerminate(pMem);
- if( rc ) return rc;
- if( sqlite3Atoi64(pMem->z, &pMem->u.i) ){
- MemSetTypeFlag(pMem, MEM_Int);
+ r1 = sqlite3VdbeRealValue(pMem);
+ i = doubleToInt64(r1);
+ r2 = (double)i;
+ if( r1==r2 ){
+ sqlite3VdbeMemIntegerify(pMem);
}else{
- pMem->r = sqlite3VdbeRealValue(pMem);
+ pMem->r = r1;
MemSetTypeFlag(pMem, MEM_Real);
- sqlite3VdbeIntegerAffinity(pMem);
}
return SQLITE_OK;
}
@@ -52295,7 +46844,6 @@ SQLITE_PRIVATE void sqlite3VdbeMemSetInt64(Mem *pMem, i64 val){
pMem->type = SQLITE_INTEGER;
}
-#ifndef SQLITE_OMIT_FLOATING_POINT
/*
** Delete any previous value and set the value stored in *pMem to val,
** manifest type REAL.
@@ -52310,7 +46858,6 @@ SQLITE_PRIVATE void sqlite3VdbeMemSetDouble(Mem *pMem, double val){
pMem->type = SQLITE_FLOAT;
}
}
-#endif
/*
** Delete any previous value and set the value of pMem to be an
@@ -52326,7 +46873,7 @@ SQLITE_PRIVATE void sqlite3VdbeMemSetRowSet(Mem *pMem){
pMem->flags = MEM_Null;
}else{
assert( pMem->zMalloc );
- pMem->u.pRowSet = sqlite3RowSetInit(db, pMem->zMalloc,
+ pMem->u.pRowSet = sqlite3RowSetInit(db, pMem->zMalloc,
sqlite3DbMallocSize(db, pMem->zMalloc));
assert( pMem->u.pRowSet!=0 );
pMem->flags = MEM_RowSet;
@@ -52346,7 +46893,7 @@ SQLITE_PRIVATE int sqlite3VdbeMemTooBig(Mem *p){
}
return n>p->db->aLimit[SQLITE_LIMIT_LENGTH];
}
- return 0;
+ return 0;
}
/*
@@ -52365,7 +46912,7 @@ SQLITE_PRIVATE void sqlite3VdbeMemShallowCopy(Mem *pTo, const Mem *pFrom, int sr
sqlite3VdbeMemReleaseExternal(pTo);
memcpy(pTo, pFrom, MEMCELLSIZE);
pTo->xDel = 0;
- if( (pFrom->flags&MEM_Static)==0 ){
+ if( (pFrom->flags&MEM_Dyn)!=0 || pFrom->z==pFrom->zMalloc ){
pTo->flags &= ~(MEM_Dyn|MEM_Static|MEM_Ephem);
assert( srcType==MEM_Ephem || srcType==MEM_Static );
pTo->flags |= srcType;
@@ -52416,8 +46963,8 @@ SQLITE_PRIVATE void sqlite3VdbeMemMove(Mem *pTo, Mem *pFrom){
** Change the value of a Mem to be a string or a BLOB.
**
** The memory management strategy depends on the value of the xDel
-** parameter. If the value passed is SQLITE_TRANSIENT, then the
-** string is copied into a (possibly existing) buffer managed by the
+** parameter. If the value passed is SQLITE_TRANSIENT, then the
+** string is copied into a (possibly existing) buffer managed by the
** Mem structure. Otherwise, any existing buffer is freed and the
** pointer copied.
**
@@ -52526,7 +47073,7 @@ SQLITE_PRIVATE int sqlite3MemCompare(const Mem *pMem1, const Mem *pMem2, const C
f2 = pMem2->flags;
combined_flags = f1|f2;
assert( (combined_flags & MEM_RowSet)==0 );
-
+
/* If one value is NULL, it is less than the other. If both values
** are NULL, return 0.
*/
@@ -52581,7 +47128,7 @@ SQLITE_PRIVATE int sqlite3MemCompare(const Mem *pMem1, const Mem *pMem2, const C
}
assert( pMem1->enc==pMem2->enc );
- assert( pMem1->enc==SQLITE_UTF8 ||
+ assert( pMem1->enc==SQLITE_UTF8 ||
pMem1->enc==SQLITE_UTF16LE || pMem1->enc==SQLITE_UTF16BE );
/* The collation sequence must be defined at this point, even if
@@ -52617,7 +47164,7 @@ SQLITE_PRIVATE int sqlite3MemCompare(const Mem *pMem1, const Mem *pMem2, const C
/* If a NULL pointer was passed as the collate function, fall through
** to the blob case and use memcmp(). */
}
-
+
/* Both values must be blobs. Compare using memcmp(). */
rc = memcmp(pMem1->z, pMem2->z, (pMem1->n>pMem2->n)?pMem2->n:pMem1->n);
if( rc==0 ){
@@ -52652,7 +47199,7 @@ SQLITE_PRIVATE int sqlite3VdbeMemFromBtree(
assert( sqlite3BtreeCursorIsValid(pCur) );
- /* Note: the calls to BtreeKeyFetch() and DataFetch() below assert()
+ /* Note: the calls to BtreeKeyFetch() and DataFetch() below assert()
** that both the BtShared and database handle mutexes are held. */
assert( (pMem->flags & MEM_RowSet)==0 );
if( key ){
@@ -52936,7 +47483,7 @@ SQLITE_PRIVATE void sqlite3VdbeSetSql(Vdbe *p, const char *z, int n, int isPrepa
*/
SQLITE_API const char *sqlite3_sql(sqlite3_stmt *pStmt){
Vdbe *p = (Vdbe *)pStmt;
- return (p && p->isPrepareV2) ? p->zSql : 0;
+ return (p->isPrepareV2 ? p->zSql : 0);
}
/*
@@ -52970,12 +47517,12 @@ SQLITE_PRIVATE void sqlite3VdbeTrace(Vdbe *p, FILE *trace){
#endif
/*
-** Resize the Vdbe.aOp array so that it is at least one op larger than
+** Resize the Vdbe.aOp array so that it is at least one op larger than
** it was.
**
** If an out-of-memory error occurs while resizing the array, return
-** SQLITE_NOMEM. In this case Vdbe.aOp and Vdbe.nOpAlloc remain
-** unchanged (this is so that any opcodes already allocated can be
+** SQLITE_NOMEM. In this case Vdbe.aOp and Vdbe.nOpAlloc remain
+** unchanged (this is so that any opcodes already allocated can be
** correctly deallocated along with the rest of the Vdbe).
*/
static int growOpArray(Vdbe *p){
@@ -53136,19 +47683,19 @@ SQLITE_PRIVATE void sqlite3VdbeRunOnlyOnce(Vdbe *p){
/*
** The following type and function are used to iterate through all opcodes
-** in a Vdbe main program and each of the sub-programs (triggers) it may
+** in a Vdbe main program and each of the sub-programs (triggers) it may
** invoke directly or indirectly. It should be used as follows:
**
** Op *pOp;
** VdbeOpIter sIter;
**
** memset(&sIter, 0, sizeof(sIter));
-** sIter.v = v; // v is of type Vdbe*
+** sIter.v = v; // v is of type Vdbe*
** while( (pOp = opIterNext(&sIter)) ){
** // Do something with pOp
** }
** sqlite3DbFree(v->db, sIter.apSub);
-**
+**
*/
typedef struct VdbeOpIter VdbeOpIter;
struct VdbeOpIter {
@@ -53181,7 +47728,7 @@ static Op *opIterNext(VdbeOpIter *p){
p->iSub++;
p->iAddr = 0;
}
-
+
if( pRet->p4type==P4_SUBPROGRAM ){
int nByte = (p->nSub+1)*sizeof(SubProgram*);
int j;
@@ -53231,11 +47778,11 @@ SQLITE_PRIVATE int sqlite3VdbeAssertMayAbort(Vdbe *v, int mayAbort){
while( (pOp = opIterNext(&sIter))!=0 ){
int opcode = pOp->opcode;
- if( opcode==OP_Destroy || opcode==OP_VUpdate || opcode==OP_VRename
+ if( opcode==OP_Destroy || opcode==OP_VUpdate || opcode==OP_VRename
#ifndef SQLITE_OMIT_FOREIGN_KEY
- || (opcode==OP_FkCounter && pOp->p1==0 && pOp->p2==1)
+ || (opcode==OP_FkCounter && pOp->p1==0 && pOp->p2==1)
#endif
- || ((opcode==OP_Halt || opcode==OP_HaltIfNull)
+ || ((opcode==OP_Halt || opcode==OP_HaltIfNull)
&& (pOp->p1==SQLITE_CONSTRAINT && pOp->p2==OE_Abort))
){
hasAbort = 1;
@@ -53260,8 +47807,8 @@ SQLITE_PRIVATE int sqlite3VdbeAssertMayAbort(Vdbe *v, int mayAbort){
**
** This routine is called once after all opcodes have been inserted.
**
-** Variable *pMaxFuncArgs is set to the maximum value of any P2 argument
-** to an OP_Function, OP_AggStep or OP_VFilter opcode. This is used by
+** Variable *pMaxFuncArgs is set to the maximum value of any P2 argument
+** to an OP_Function, OP_AggStep or OP_VFilter opcode. This is used by
** sqlite3VdbeMakeReady() to size the Vdbe.apArg[] array.
**
** The Op.opflags field is set on all opcodes.
@@ -53314,12 +47861,12 @@ SQLITE_PRIVATE int sqlite3VdbeCurrentAddr(Vdbe *p){
/*
** This function returns a pointer to the array of opcodes associated with
** the Vdbe passed as the first argument. It is the callers responsibility
-** to arrange for the returned array to be eventually freed using the
+** to arrange for the returned array to be eventually freed using the
** vdbeFreeOpArray() function.
**
** Before returning, *pnOp is set to the number of entries in the returned
-** array. Also, *pnMaxArg is set to the larger of its current value and
-** the number of entries in the Vdbe.apArg[] array required to execute the
+** array. Also, *pnMaxArg is set to the larger of its current value and
+** the number of entries in the Vdbe.apArg[] array required to execute the
** returned program.
*/
SQLITE_PRIVATE VdbeOp *sqlite3VdbeTakeOpArray(Vdbe *p, int *pnOp, int *pnMaxArg){
@@ -53488,8 +48035,8 @@ static void freeP4(sqlite3 *db, int p4type, void *p4){
/*
** Free the space allocated for aOp and any p4 values allocated for the
-** opcodes contained within. If aOp is not NULL it is assumed to contain
-** nOp entries.
+** opcodes contained within. If aOp is not NULL it is assumed to contain
+** nOp entries.
*/
static void vdbeFreeOpArray(sqlite3 *db, Op *aOp, int nOp){
if( aOp ){
@@ -53498,7 +48045,7 @@ static void vdbeFreeOpArray(sqlite3 *db, Op *aOp, int nOp){
freeP4(db, pOp->p4type, pOp->p4.p);
#ifdef SQLITE_DEBUG
sqlite3DbFree(db, pOp->zComment);
-#endif
+#endif
}
}
sqlite3DbFree(db, aOp);
@@ -53565,10 +48112,10 @@ SQLITE_PRIVATE void sqlite3VdbeChangeToNoop(Vdbe *p, int addr, int N){
** A copy is made of the KeyInfo structure into memory obtained from
** sqlite3_malloc, to be freed when the Vdbe is finalized.
** n==P4_KEYINFO_HANDOFF indicates that zP4 points to a KeyInfo structure
-** stored in memory that the caller has obtained from sqlite3_malloc. The
+** stored in memory that the caller has obtained from sqlite3_malloc. The
** caller should not free the allocation, it will be freed when the Vdbe is
** finalized.
-**
+**
** Other values of n (P4_STATIC, P4_COLLSEQ etc.) indicate that zP4 points
** to a string or structure that is guaranteed to exist for the lifetime of
** the Vdbe. In these cases we can just copy the pointer.
@@ -53613,7 +48160,7 @@ SQLITE_PRIVATE void sqlite3VdbeChangeP4(Vdbe *p, int addr, const char *zP4, int
pOp->p4.pKeyInfo = pKeyInfo;
if( pKeyInfo ){
u8 *aSortOrder;
- memcpy((char*)pKeyInfo, zP4, nByte - nField);
+ memcpy(pKeyInfo, zP4, nByte);
aSortOrder = pKeyInfo->aSortOrder;
if( aSortOrder ){
pKeyInfo->aSortOrder = (unsigned char*)&pKeyInfo->aColl[nField];
@@ -53820,11 +48367,6 @@ static char *displayP4(Op *pOp, char *zTemp, int nTemp){
/*
** Declare to the Vdbe that the BTree object at db->aDb[i] is used.
-**
-** The prepared statement has to know in advance which Btree objects
-** will be used so that it can acquire mutexes on them all in sorted
-** order (via sqlite3VdbeMutexArrayEnter(). Mutexes are acquired
-** in order (and released in reverse order) to avoid deadlocks.
*/
SQLITE_PRIVATE void sqlite3VdbeUsesBtree(Vdbe *p, int i){
int mask;
@@ -53848,7 +48390,7 @@ SQLITE_PRIVATE void sqlite3VdbePrintOp(FILE *pOut, int pc, Op *pOp){
static const char *zFormat1 = "%4d %-13s %4d %4d %4d %-4s %.2X %s\n";
if( pOut==0 ) pOut = stdout;
zP4 = displayP4(pOp, zPtr, sizeof(zPtr));
- fprintf(pOut, zFormat1, pc,
+ fprintf(pOut, zFormat1, pc,
sqlite3OpcodeName(pOp->opcode), pOp->p1, pOp->p2, pOp->p3, zP4, pOp->p5,
#ifdef SQLITE_DEBUG
pOp->zComment ? pOp->zComment : ""
@@ -53872,15 +48414,15 @@ static void releaseMemArray(Mem *p, int N){
assert( (&p[1])==pEnd || p[0].db==p[1].db );
/* This block is really an inlined version of sqlite3VdbeMemRelease()
- ** that takes advantage of the fact that the memory cell value is
+ ** that takes advantage of the fact that the memory cell value is
** being set to NULL after releasing any dynamic resources.
**
- ** The justification for duplicating code is that according to
- ** callgrind, this causes a certain test case to hit the CPU 4.7
- ** percent less (x86 linux, gcc version 4.1.2, -O6) than if
+ ** The justification for duplicating code is that according to
+ ** callgrind, this causes a certain test case to hit the CPU 4.7
+ ** percent less (x86 linux, gcc version 4.1.2, -O6) than if
** sqlite3MemRelease() were called from here. With -O2, this jumps
- ** to 6.6 percent. The test case is inserting 1000 rows into a table
- ** with no indexes using a single prepared INSERT statement, bind()
+ ** to 6.6 percent. The test case is inserting 1000 rows into a table
+ ** with no indexes using a single prepared INSERT statement, bind()
** and reset(). Inserts are grouped into a transaction.
*/
if( p->flags&(MEM_Agg|MEM_Dyn|MEM_Frame|MEM_RowSet) ){
@@ -54014,7 +48556,7 @@ SQLITE_PRIVATE int sqlite3VdbeList(
pMem->type = SQLITE_INTEGER;
pMem->u.i = i; /* Program counter */
pMem++;
-
+
pMem->flags = MEM_Static|MEM_Str|MEM_Term;
pMem->z = (char*)sqlite3OpcodeName(pOp->opcode); /* Opcode */
assert( pMem->z!=0 );
@@ -54087,7 +48629,7 @@ SQLITE_PRIVATE int sqlite3VdbeList(
pMem->type = SQLITE_TEXT;
pMem->enc = SQLITE_UTF8;
pMem++;
-
+
#ifdef SQLITE_DEBUG
if( pOp->zComment ){
pMem->flags = MEM_Str|MEM_Term;
@@ -54202,7 +48744,7 @@ static void *allocSpace(
** Prepare a virtual machine for execution. This involves things such
** as allocating stack space and initializing the program counter.
** After the VDBE has be prepped, it can be executed by one or more
-** calls to sqlite3VdbeExec().
+** calls to sqlite3VdbeExec().
**
** This is the only way to move a VDBE from VDBE_MAGIC_INIT to
** VDBE_MAGIC_RUN.
@@ -54210,7 +48752,7 @@ static void *allocSpace(
** This function may be called more than once on a single virtual machine.
** The first call is made while compiling the SQL statement. Subsequent
** calls are made as part of the process of resetting a statement to be
-** re-executed (from a call to sqlite3_reset()). The nVar, nMem, nCursor
+** re-executed (from a call to sqlite3_reset()). The nVar, nMem, nCursor
** and isExplain parameters are only passed correct values the first time
** the function is called. On subsequent calls, from sqlite3_reset(), nVar
** is passed -1 and nMem, nCursor and isExplain are all passed zero.
@@ -54240,7 +48782,7 @@ SQLITE_PRIVATE void sqlite3VdbeMakeReady(
/* For each cursor required, also allocate a memory cell. Memory
** cells (nMem+1-nCursor)..nMem, inclusive, will never be used by
** the vdbe program. Instead they are used to allocate space for
- ** VdbeCursor/BtCursor structures. The blob of memory associated with
+ ** VdbeCursor/BtCursor structures. The blob of memory associated with
** cursor 0 is stored in memory cell nMem. Memory cell (nMem-1)
** stores the blob of memory associated with cursor 1, etc.
**
@@ -54248,7 +48790,7 @@ SQLITE_PRIVATE void sqlite3VdbeMakeReady(
*/
nMem += nCursor;
- /* Allocate space for memory registers, SQL variables, VDBE cursors and
+ /* Allocate space for memory registers, SQL variables, VDBE cursors and
** an array to marshal SQL function arguments in. This is only done the
** first time this function is called for a given VDBE, not when it is
** being called from sqlite3_reset() to reset the virtual machine.
@@ -54268,10 +48810,10 @@ SQLITE_PRIVATE void sqlite3VdbeMakeReady(
assert( EIGHT_BYTE_ALIGNMENT(zCsr) );
/* Memory for registers, parameters, cursor, etc, is allocated in two
- ** passes. On the first pass, we try to reuse unused space at the
+ ** passes. On the first pass, we try to reuse unused space at the
** end of the opcode array. If we are unable to satisfy all memory
** requirements by reusing the opcode array tail, then the second
- ** pass will fill in the rest using a fresh allocation.
+ ** pass will fill in the rest using a fresh allocation.
**
** This two-pass approach that reuses as much memory as possible from
** the leftover space at the end of the opcode array can significantly
@@ -54324,7 +48866,6 @@ SQLITE_PRIVATE void sqlite3VdbeMakeReady(
p->cacheCtr = 1;
p->minWriteFileFormat = 255;
p->iStatement = 0;
- p->nFkConstraint = 0;
#ifdef VDBE_PROFILE
{
int i;
@@ -54337,7 +48878,7 @@ SQLITE_PRIVATE void sqlite3VdbeMakeReady(
}
/*
-** Close a VDBE cursor and release all the resources that cursor
+** Close a VDBE cursor and release all the resources that cursor
** happens to hold.
*/
SQLITE_PRIVATE void sqlite3VdbeFreeCursor(Vdbe *p, VdbeCursor *pCx){
@@ -54383,7 +48924,7 @@ SQLITE_PRIVATE int sqlite3VdbeFrameRestore(VdbeFrame *pFrame){
/*
** Close all cursors.
**
-** Also release any dynamic memory held by the VM in the Vdbe.aMem memory
+** Also release any dynamic memory held by the VM in the Vdbe.aMem memory
** cell array. This is necessary as the memory cell array may contain
** pointers to VdbeFrame objects, which may in turn contain pointers to
** open cursors.
@@ -54423,7 +48964,7 @@ static void Cleanup(Vdbe *p){
sqlite3 *db = p->db;
#ifdef SQLITE_DEBUG
- /* Execute assert() statements to ensure that the Vdbe.apCsr[] and
+ /* Execute assert() statements to ensure that the Vdbe.apCsr[] and
** Vdbe.aMem[] arrays have already been cleaned up. */
int i;
for(i=0; i<p->nCursor; i++) assert( p->apCsr==0 || p->apCsr[i]==0 );
@@ -54504,15 +49045,15 @@ static int vdbeCommit(sqlite3 *db, Vdbe *p){
int needXcommit = 0;
#ifdef SQLITE_OMIT_VIRTUALTABLE
- /* With this option, sqlite3VtabSync() is defined to be simply
- ** SQLITE_OK so p is not used.
+ /* With this option, sqlite3VtabSync() is defined to be simply
+ ** SQLITE_OK so p is not used.
*/
UNUSED_PARAMETER(p);
#endif
/* Before doing anything else, call the xSync() callback for any
** virtual module tables written in this transaction. This has to
- ** be done before determining whether a master journal file is
+ ** be done before determining whether a master journal file is
** required, as an xSync() callback may add an attached database
** to the transaction.
*/
@@ -54522,12 +49063,12 @@ static int vdbeCommit(sqlite3 *db, Vdbe *p){
}
/* This loop determines (a) if the commit hook should be invoked and
- ** (b) how many database files have open write transactions, not
- ** including the temp database. (b) is important because if more than
+ ** (b) how many database files have open write transactions, not
+ ** including the temp database. (b) is important because if more than
** one database file has an open write transaction, a master journal
** file is required for an atomic commit.
- */
- for(i=0; i<db->nDb; i++){
+ */
+ for(i=0; i<db->nDb; i++){
Btree *pBt = db->aDb[i].pBt;
if( sqlite3BtreeIsInTrans(pBt) ){
needXcommit = 1;
@@ -54548,8 +49089,8 @@ static int vdbeCommit(sqlite3 *db, Vdbe *p){
** master-journal.
**
** If the return value of sqlite3BtreeGetFilename() is a zero length
- ** string, it means the main database is :memory: or a temp file. In
- ** that case we do not support atomic multi-file commits, so use the
+ ** string, it means the main database is :memory: or a temp file. In
+ ** that case we do not support atomic multi-file commits, so use the
** simple case then too.
*/
if( 0==sqlite3Strlen30(sqlite3BtreeGetFilename(db->aDb[0].pBt))
@@ -54562,7 +49103,7 @@ static int vdbeCommit(sqlite3 *db, Vdbe *p){
}
}
- /* Do the commit only if all databases successfully complete phase 1.
+ /* Do the commit only if all databases successfully complete phase 1.
** If one of the BtreeCommitPhaseOne() calls fails, this indicates an
** IO error while deleting or truncating a journal file. It is unlikely,
** but could happen. In this case abandon processing and return the error.
@@ -54605,7 +49146,7 @@ static int vdbeCommit(sqlite3 *db, Vdbe *p){
}while( rc==SQLITE_OK && res );
if( rc==SQLITE_OK ){
/* Open the master journal. */
- rc = sqlite3OsOpenMalloc(pVfs, zMaster, &pMaster,
+ rc = sqlite3OsOpenMalloc(pVfs, zMaster, &pMaster,
SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|
SQLITE_OPEN_EXCLUSIVE|SQLITE_OPEN_MASTER_JOURNAL, 0
);
@@ -54614,7 +49155,7 @@ static int vdbeCommit(sqlite3 *db, Vdbe *p){
sqlite3DbFree(db, zMaster);
return rc;
}
-
+
/* Write the name of each database file in the transaction into the new
** master journal file. If an error occurs at this point close
** and delete the master journal file. All the individual journal files
@@ -54645,7 +49186,7 @@ static int vdbeCommit(sqlite3 *db, Vdbe *p){
/* Sync the master journal file. If the IOCAP_SEQUENTIAL device
** flag is set this is not required.
*/
- if( needSync
+ if( needSync
&& 0==(sqlite3OsDeviceCharacteristics(pMaster)&SQLITE_IOCAP_SEQUENTIAL)
&& SQLITE_OK!=(rc = sqlite3OsSync(pMaster, SQLITE_SYNC_NORMAL))
){
@@ -54665,7 +49206,7 @@ static int vdbeCommit(sqlite3 *db, Vdbe *p){
** in case the master journal file name was written into the journal
** file before the failure occurred.
*/
- for(i=0; rc==SQLITE_OK && i<db->nDb; i++){
+ for(i=0; rc==SQLITE_OK && i<db->nDb; i++){
Btree *pBt = db->aDb[i].pBt;
if( pBt ){
rc = sqlite3BtreeCommitPhaseOne(pBt, zMaster);
@@ -54697,7 +49238,7 @@ static int vdbeCommit(sqlite3 *db, Vdbe *p){
*/
disable_simulated_io_errors();
sqlite3BeginBenignMalloc();
- for(i=0; i<db->nDb; i++){
+ for(i=0; i<db->nDb; i++){
Btree *pBt = db->aDb[i].pBt;
if( pBt ){
sqlite3BtreeCommitPhaseTwo(pBt);
@@ -54713,7 +49254,7 @@ static int vdbeCommit(sqlite3 *db, Vdbe *p){
return rc;
}
-/*
+/*
** This routine checks that the sqlite3.activeVdbeCnt 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.
@@ -54743,7 +49284,7 @@ static void checkActiveVdbeCnt(sqlite3 *db){
#endif
/*
-** For every Btree that in database connection db which
+** For every Btree that in database connection db which
** has been modified, "trip" or invalidate each cursor in
** that Btree might have been modified so that the cursor
** can never be used again. This happens when a rollback
@@ -54772,17 +49313,17 @@ static void invalidateCursorsOnModifiedBtrees(sqlite3 *db){
** If the Vdbe passed as the first argument opened a statement-transaction,
** 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
+** transaction is rolled back. If eOp is SAVEPOINT_RELEASE, then the
** statement transaction is commtted.
**
-** If an IO error occurs, an SQLITE_IOERR_XXX error code is returned.
+** If an IO error occurs, an SQLITE_IOERR_XXX error code is returned.
** Otherwise SQLITE_OK.
*/
SQLITE_PRIVATE int sqlite3VdbeCloseStatement(Vdbe *p, int eOp){
sqlite3 *const db = p->db;
int rc = SQLITE_OK;
- /* If p->iStatement is greater than zero, then this Vdbe opened a
+ /* If p->iStatement is greater than zero, then this Vdbe opened a
** statement transaction that should be closed here. The only exception
** is that an IO error may have occured, causing an emergency rollback.
** In this case (db->nStatement==0), and there is nothing to do.
@@ -54795,7 +49336,7 @@ SQLITE_PRIVATE int sqlite3VdbeCloseStatement(Vdbe *p, int eOp){
assert( db->nStatement>0 );
assert( p->iStatement==(db->nStatement+db->nSavepoint) );
- for(i=0; i<db->nDb; i++){
+ for(i=0; i<db->nDb; i++){
int rc2 = SQLITE_OK;
Btree *pBt = db->aDb[i].pBt;
if( pBt ){
@@ -54813,8 +49354,8 @@ SQLITE_PRIVATE int sqlite3VdbeCloseStatement(Vdbe *p, int eOp){
db->nStatement--;
p->iStatement = 0;
- /* If the statement transaction is being rolled back, also restore the
- ** database handles deferred constraint counter to the value it had when
+ /* If the statement transaction is being rolled back, also restore the
+ ** database handles deferred constraint counter to the value it had when
** the statement transaction was opened. */
if( eOp==SAVEPOINT_ROLLBACK ){
db->nDeferredCons = p->nStmtDefCons;
@@ -54832,7 +49373,7 @@ SQLITE_PRIVATE int sqlite3VdbeCloseStatement(Vdbe *p, int eOp){
**
** If SQLite is not threadsafe but does support shared-cache mode, then
** sqlite3BtreeEnterAll() is invoked to set the BtShared.db variables
-** of all of BtShared structures accessible via the database handle
+** of all of BtShared structures accessible via the database handle
** associated with the VM. Of course only a subset of these structures
** will be accessed by the VM, and we could use Vdbe.btreeMask to figure
** that subset out, but there is no advantage to doing so.
@@ -54851,12 +49392,12 @@ SQLITE_PRIVATE void sqlite3VdbeMutexArrayEnter(Vdbe *p){
#endif
/*
-** This function is called when a transaction opened by the database
-** handle associated with the VM passed as an argument is about to be
+** This function is called when a transaction opened by the database
+** handle associated with the VM passed as an argument is about to be
** committed. If there are outstanding deferred foreign key constraint
** violations, return SQLITE_ERROR. Otherwise, SQLITE_OK.
**
-** If there are outstanding FK violations and this function returns
+** If there are outstanding FK violations and this function returns
** SQLITE_ERROR, set the result of the VM to SQLITE_CONSTRAINT and write
** an error message to it. Then return SQLITE_ERROR.
*/
@@ -54892,7 +49433,7 @@ SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe *p){
/* This function contains the logic that determines if a statement or
** transaction will be committed or rolled back as a result of the
- ** execution of this virtual machine.
+ ** execution of this virtual machine.
**
** If any of the following errors occur:
**
@@ -54952,25 +49493,25 @@ SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe *p){
if( p->rc==SQLITE_OK ){
sqlite3VdbeCheckFk(p, 0);
}
-
- /* If the auto-commit flag is set and this is the only active writer
- ** VM, then we do either a commit or rollback of the current transaction.
+
+ /* If the auto-commit flag is set and this is the only active writer
+ ** VM, then we do either a commit or rollback of the current transaction.
**
- ** Note: This block also runs if one of the special errors handled
- ** above has occurred.
+ ** Note: This block also runs if one of the special errors handled
+ ** above has occurred.
*/
- if( !sqlite3VtabInSync(db)
- && db->autoCommit
- && db->writeVdbeCnt==(p->readOnly==0)
+ if( !sqlite3VtabInSync(db)
+ && db->autoCommit
+ && db->writeVdbeCnt==(p->readOnly==0)
){
if( p->rc==SQLITE_OK || (p->errorAction==OE_Fail && !isSpecialError) ){
if( sqlite3VdbeCheckFk(p, 1) ){
sqlite3BtreeMutexArrayLeave(&p->aMutex);
return SQLITE_ERROR;
}
- /* The auto-commit flag is true, the vdbe program was successful
+ /* The auto-commit flag is true, the vdbe program was successful
** or hit an 'OR FAIL' constraint and there are no deferred foreign
- ** key constraints to hold up the transaction. This means a commit
+ ** key constraints to hold up the transaction. This means a commit
** is required. */
rc = vdbeCommit(db, p);
if( rc==SQLITE_BUSY ){
@@ -54999,29 +49540,24 @@ SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe *p){
db->autoCommit = 1;
}
}
-
+
/* If eStatementOp is non-zero, then a statement transaction needs to
** be committed or rolled back. Call sqlite3VdbeCloseStatement() to
** do so. If this operation returns an error, and the current statement
- ** error code is SQLITE_OK or SQLITE_CONSTRAINT, then promote the
- ** current statement error code.
- **
- ** Note that sqlite3VdbeCloseStatement() can only fail if eStatementOp
- ** is SAVEPOINT_ROLLBACK. But if p->rc==SQLITE_OK then eStatementOp
- ** must be SAVEPOINT_RELEASE. Hence the NEVER(p->rc==SQLITE_OK) in
- ** the following code.
+ ** error code is SQLITE_OK or SQLITE_CONSTRAINT, then set the error
+ ** code to the new value.
*/
if( eStatementOp ){
rc = sqlite3VdbeCloseStatement(p, eStatementOp);
- if( rc && (NEVER(p->rc==SQLITE_OK) || p->rc==SQLITE_CONSTRAINT) ){
+ if( rc && (p->rc==SQLITE_OK || p->rc==SQLITE_CONSTRAINT) ){
p->rc = rc;
sqlite3DbFree(db, p->zErrMsg);
p->zErrMsg = 0;
}
}
-
+
/* If this was an INSERT, UPDATE or DELETE and no statement transaction
- ** has been rolled back, update the database connection change-counter.
+ ** has been rolled back, update the database connection change-counter.
*/
if( p->changeCntOn ){
if( eStatementOp!=SAVEPOINT_ROLLBACK ){
@@ -55031,7 +49567,7 @@ SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe *p){
}
p->nChange = 0;
}
-
+
/* Rollback or commit any schema changes that occurred. */
if( p->rc!=SQLITE_OK && db->flags&SQLITE_InternChanges ){
sqlite3ResetInternalSchema(db, 0);
@@ -55057,7 +49593,7 @@ SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe *p){
}
/* If the auto-commit flag is set to true, then any locks that were held
- ** by connection db have now been released. Call sqlite3ConnectionUnlocked()
+ ** by connection db have now been released. Call sqlite3ConnectionUnlocked()
** to invoke any required unlock-notify callbacks.
*/
if( db->autoCommit ){
@@ -55159,7 +49695,7 @@ SQLITE_PRIVATE int sqlite3VdbeReset(Vdbe *p){
p->magic = VDBE_MAGIC_INIT;
return p->rc & db->errMask;
}
-
+
/*
** Clean up and delete a VDBE after execution. Return an integer which is
** the result code. Write any error message text into *pzErrMsg.
@@ -55218,7 +49754,6 @@ SQLITE_PRIVATE void sqlite3VdbeDelete(Vdbe *p){
sqlite3DbFree(db, p->zSql);
p->magic = VDBE_MAGIC_DEAD;
sqlite3DbFree(db, p->pFree);
- p->db = 0;
sqlite3DbFree(db, p);
}
@@ -55360,8 +49895,8 @@ SQLITE_PRIVATE u32 sqlite3VdbeSerialTypeLen(u32 serial_type){
}
/*
-** If we are on an architecture with mixed-endian floating
-** points (ex: ARM7) then swap the lower 4 bytes with the
+** If we are on an architecture with mixed-endian floating
+** points (ex: ARM7) then swap the lower 4 bytes with the
** upper 4 bytes. Return the result.
**
** For most architectures, this is a no-op.
@@ -55383,7 +49918,7 @@ SQLITE_PRIVATE u32 sqlite3VdbeSerialTypeLen(u32 serial_type){
** (2007-08-30) Frank van Vugt has studied this problem closely
** and has send his findings to the SQLite developers. Frank
** writes that some Linux kernels offer floating point hardware
-** emulation that uses only 32-bit mantissas instead of a full
+** emulation that uses only 32-bit mantissas instead of a full
** 48-bits as required by the IEEE standard. (This is the
** CONFIG_FPE_FASTFPE option.) On such systems, floating point
** byte swapping becomes very complicated. To avoid problems,
@@ -55413,7 +49948,7 @@ static u64 floatSwap(u64 in){
#endif
/*
-** Write the serialized data blob for the value stored in pMem into
+** Write the serialized data blob for the value stored in pMem into
** buf. It is assumed that the caller has allocated sufficient space.
** Return the number of bytes written.
**
@@ -55429,7 +49964,7 @@ static u64 floatSwap(u64 in){
** Return the number of bytes actually written into buf[]. The number
** of bytes in the zero-filled tail is included in the return value only
** if those bytes were zeroed in buf[].
-*/
+*/
SQLITE_PRIVATE u32 sqlite3VdbeSerialPut(u8 *buf, int nBuf, Mem *pMem, int file_format){
u32 serial_type = sqlite3VdbeSerialType(pMem, file_format);
u32 len;
@@ -55479,7 +50014,7 @@ SQLITE_PRIVATE u32 sqlite3VdbeSerialPut(u8 *buf, int nBuf, Mem *pMem, int file_f
/*
** Deserialize the data blob pointed to by buf as serial type serial_type
** and store the result in pMem. Return the number of bytes read.
-*/
+*/
SQLITE_PRIVATE u32 sqlite3VdbeSerialGet(
const unsigned char *buf, /* Buffer to deserialize from */
u32 serial_type, /* Serial type to deserialize */
@@ -55586,7 +50121,7 @@ SQLITE_PRIVATE u32 sqlite3VdbeSerialGet(
**
** The returned structure should be closed by a call to
** sqlite3VdbeDeleteUnpackedRecord().
-*/
+*/
SQLITE_PRIVATE UnpackedRecord *sqlite3VdbeRecordUnpack(
KeyInfo *pKeyInfo, /* Information about the record format */
int nKey, /* Size of the binary record */
@@ -55603,10 +50138,10 @@ SQLITE_PRIVATE UnpackedRecord *sqlite3VdbeRecordUnpack(
u32 szHdr;
Mem *pMem;
int nOff; /* Increase pSpace by this much to 8-byte align it */
-
+
/*
** We want to shift the pointer pSpace up such that it is 8-byte aligned.
- ** Thus, we need to calculate a value, nOff, between 0 and 7, to shift
+ ** Thus, we need to calculate a value, nOff, between 0 and 7, to shift
** it by. If pSpace is already 8-byte aligned, nOff should be zero.
*/
nOff = (8 - (SQLITE_PTR_TO_INT(pSpace) & 7)) & 7;
@@ -55670,14 +50205,14 @@ SQLITE_PRIVATE void sqlite3VdbeDeleteUnpackedRecord(UnpackedRecord *p){
/*
** This function compares the two table rows or index records
** specified by {nKey1, pKey1} and pPKey2. It returns a negative, zero
-** or positive integer if key1 is less than, equal to or
+** or positive integer if key1 is less than, equal to or
** greater than key2. The {nKey1, pKey1} key must be a blob
** created by th OP_MakeRecord opcode of the VDBE. The pPKey2
** key must be a parsed key such as obtained from
** sqlite3VdbeParseRecord.
**
** Key1 and Key2 do not have to contain the same number of fields.
-** The key with fewer fields is usually compares less than the
+** The key with fewer fields is usually compares less than the
** longer key. However if the UNPACKED_INCRKEY flags in pPKey2 is set
** and the common prefixes are equal, then key1 is less than key2.
** Or if the UNPACKED_MATCH_PREFIX flag is set and the prefixes are
@@ -55715,13 +50250,13 @@ SQLITE_PRIVATE int sqlite3VdbeRecordCompare(
/* Compilers may complain that mem1.u.i is potentially uninitialized.
** We could initialize it, as shown here, to silence those complaints.
- ** But in fact, mem1.u.i will never actually be used initialized, and doing
+ ** But in fact, mem1.u.i will never actually be used initialized, and doing
** the unnecessary initialization has a measurable negative performance
** impact, since this routine is a very high runner. And so, we choose
** to ignore the compiler warnings and leave this variable uninitialized.
*/
/* mem1.u.i = 0; // not needed, here to silence compiler warning */
-
+
idx1 = getVarint32(aKey1, szHdr1);
d1 = szHdr1;
if( pPKey2->flags & UNPACKED_IGNORE_ROWID ){
@@ -55750,9 +50285,9 @@ SQLITE_PRIVATE int sqlite3VdbeRecordCompare(
if( pKeyInfo->aSortOrder && i<nField && pKeyInfo->aSortOrder[i] ){
rc = -rc;
}
-
+
/* If the PREFIX_SEARCH flag is set and all fields except the final
- ** rowid field were equal, then clear the PREFIX_SEARCH flag and set
+ ** rowid field were equal, then clear the PREFIX_SEARCH flag and set
** pPKey2->rowid to the value of the rowid field in (pKey1, nKey1).
** This is used by the OP_IsUnique opcode.
*/
@@ -55762,7 +50297,7 @@ SQLITE_PRIVATE int sqlite3VdbeRecordCompare(
pPKey2->flags &= ~UNPACKED_PREFIX_SEARCH;
pPKey2->rowid = mem1.u.i;
}
-
+
return rc;
}
i++;
@@ -55778,7 +50313,7 @@ SQLITE_PRIVATE int sqlite3VdbeRecordCompare(
** all the fields up to that point were equal. If the UNPACKED_INCRKEY
** flag is set, then break the tie by treating key2 as larger.
** If the UPACKED_PREFIX_MATCH flag is set, then keys with common prefixes
- ** are considered to be equal. Otherwise, the longer key is the
+ ** are considered to be equal. Otherwise, the longer key is the
** larger. As it happens, the pPKey2 will always be the longer
** if there is a difference.
*/
@@ -55792,7 +50327,7 @@ SQLITE_PRIVATE int sqlite3VdbeRecordCompare(
}
return rc;
}
-
+
/*
** pCur points at an index entry created using the OP_MakeRecord opcode.
@@ -55815,7 +50350,7 @@ SQLITE_PRIVATE int sqlite3VdbeIdxRowid(sqlite3 *db, BtCursor *pCur, i64 *rowid){
/* Get the size of the index entry. Only indices entries of less
** than 2GiB are support - anything large must be database corruption.
** Any corruption is detected in sqlite3BtreeParseCellPtr(), though, so
- ** this code can safely assume that nCellKey is 32-bits
+ ** this code can safely assume that nCellKey is 32-bits
*/
assert( sqlite3BtreeCursorIsValid(pCur) );
rc = sqlite3BtreeKeySize(pCur, &nCellKey);
@@ -55879,7 +50414,7 @@ idx_rowid_corruption:
**
** pUnpacked is either created without a rowid or is truncated so that it
** omits the rowid at the end. The rowid at the end of the index entry
-** is ignored as well. Hence, this routine only compares the prefixes
+** is ignored as well. Hence, this routine only compares the prefixes
** of the keys prior to the final rowid, not the entire key.
*/
SQLITE_PRIVATE int sqlite3VdbeIdxKeyCompare(
@@ -55914,7 +50449,7 @@ SQLITE_PRIVATE int sqlite3VdbeIdxKeyCompare(
/*
** This routine sets the value to be returned by subsequent calls to
-** sqlite3_changes() on the database handle 'db'.
+** sqlite3_changes() on the database handle 'db'.
*/
SQLITE_PRIVATE void sqlite3VdbeSetChanges(sqlite3 *db, int nChange){
assert( sqlite3_mutex_held(db->mutex) );
@@ -55956,7 +50491,7 @@ SQLITE_PRIVATE sqlite3 *sqlite3VdbeDb(Vdbe *v){
/*
** Return a pointer to an sqlite3_value structure containing the value bound
-** parameter iVar of VM v. Except, if the value is an SQL NULL, return
+** parameter iVar of VM v. Except, if the value is an SQL NULL, return
** 0 instead. Unless it is NULL, apply affinity aff (one of the SQLITE_AFF_*
** constants) to the value before returning it.
**
@@ -56194,9 +50729,9 @@ static void setResultStrOrError(
}
}
SQLITE_API void sqlite3_result_blob(
- sqlite3_context *pCtx,
- const void *z,
- int n,
+ sqlite3_context *pCtx,
+ const void *z,
+ int n,
void (*xDel)(void *)
){
assert( n>=0 );
@@ -56232,8 +50767,8 @@ SQLITE_API void sqlite3_result_null(sqlite3_context *pCtx){
sqlite3VdbeMemSetNull(&pCtx->s);
}
SQLITE_API void sqlite3_result_text(
- sqlite3_context *pCtx,
- const char *z,
+ sqlite3_context *pCtx,
+ const char *z,
int n,
void (*xDel)(void *)
){
@@ -56242,27 +50777,27 @@ SQLITE_API void sqlite3_result_text(
}
#ifndef SQLITE_OMIT_UTF16
SQLITE_API void sqlite3_result_text16(
- sqlite3_context *pCtx,
- const void *z,
- int n,
+ sqlite3_context *pCtx,
+ const void *z,
+ int n,
void (*xDel)(void *)
){
assert( sqlite3_mutex_held(pCtx->s.db->mutex) );
setResultStrOrError(pCtx, z, n, SQLITE_UTF16NATIVE, xDel);
}
SQLITE_API void sqlite3_result_text16be(
- sqlite3_context *pCtx,
- const void *z,
- int n,
+ sqlite3_context *pCtx,
+ const void *z,
+ int n,
void (*xDel)(void *)
){
assert( sqlite3_mutex_held(pCtx->s.db->mutex) );
setResultStrOrError(pCtx, z, n, SQLITE_UTF16BE, xDel);
}
SQLITE_API void sqlite3_result_text16le(
- sqlite3_context *pCtx,
- const void *z,
- int n,
+ sqlite3_context *pCtx,
+ const void *z,
+ int n,
void (*xDel)(void *)
){
assert( sqlite3_mutex_held(pCtx->s.db->mutex) );
@@ -56280,7 +50815,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;
if( pCtx->s.flags & MEM_Null ){
- sqlite3VdbeMemSetStr(&pCtx->s, sqlite3ErrStr(errCode), -1,
+ sqlite3VdbeMemSetStr(&pCtx->s, sqlite3ErrStr(errCode), -1,
SQLITE_UTF8, SQLITE_STATIC);
}
}
@@ -56289,7 +50824,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;
- sqlite3VdbeMemSetStr(&pCtx->s, "string or blob too big", -1,
+ sqlite3VdbeMemSetStr(&pCtx->s, "string or blob too big", -1,
SQLITE_UTF8, SQLITE_STATIC);
}
@@ -56302,32 +50837,11 @@ SQLITE_API void sqlite3_result_error_nomem(sqlite3_context *pCtx){
}
/*
-** This function is called after a transaction has been committed. It
-** invokes callbacks registered with sqlite3_wal_hook() as required.
-*/
-static int doWalCallbacks(sqlite3 *db){
- int rc = SQLITE_OK;
-#ifndef SQLITE_OMIT_WAL
- int i;
- for(i=0; i<db->nDb; i++){
- Btree *pBt = db->aDb[i].pBt;
- if( pBt ){
- int nEntry = sqlite3PagerWalCallback(sqlite3BtreePager(pBt));
- if( db->xWalCallback && nEntry>0 && rc==SQLITE_OK ){
- rc = db->xWalCallback(db->pWalArg, db, db->aDb[i].zName, nEntry);
- }
- }
- }
-#endif
- return rc;
-}
-
-/*
** Execute the statement pStmt, either until a row of data is ready, the
** statement is completely executed or an error occurs.
**
** This routine implements the bulk of the logic behind the sqlite_step()
-** API. The only thing omitted is the automatic recompile if a
+** API. The only thing omitted is the automatic recompile if a
** schema change has occurred. That detail is handled by the
** outer sqlite3_step() wrapper procedure.
*/
@@ -56337,23 +50851,21 @@ static int sqlite3Step(Vdbe *p){
assert(p);
if( p->magic!=VDBE_MAGIC_RUN ){
- /* We used to require that sqlite3_reset() be called before retrying
- ** sqlite3_step() after any error. But after 3.6.23, we changed this
- ** so that sqlite3_reset() would be called automatically instead of
- ** throwing the error.
- */
- sqlite3_reset((sqlite3_stmt*)p);
+ sqlite3_log(SQLITE_MISUSE,
+ "attempt to step a halted statement: [%s]", p->zSql);
+ return SQLITE_MISUSE_BKPT;
}
- /* Check that malloc() has not failed. If it has, return early. */
+ /* Assert that malloc() has not failed */
db = p->db;
if( db->mallocFailed ){
- p->rc = SQLITE_NOMEM;
return SQLITE_NOMEM;
}
if( p->pc<=0 && p->expired ){
- p->rc = SQLITE_SCHEMA;
+ if( p->rc==SQLITE_OK ){
+ p->rc = SQLITE_SCHEMA;
+ }
rc = SQLITE_ERROR;
goto end_of_step;
}
@@ -56370,7 +50882,9 @@ static int sqlite3Step(Vdbe *p){
#ifndef SQLITE_OMIT_TRACE
if( db->xProfile && !db->init.busy ){
- sqlite3OsCurrentTimeInt64(db->pVfs, &p->startTime);
+ double rNow;
+ sqlite3OsCurrentTime(db->pVfs, &rNow);
+ p->startTime = (u64)((rNow - (int)rNow)*3600.0*24.0*1000000000.0);
}
#endif
@@ -56391,33 +50905,29 @@ static int sqlite3Step(Vdbe *p){
/* Invoke the profile callback if there is one
*/
if( rc!=SQLITE_ROW && db->xProfile && !db->init.busy && p->zSql ){
- sqlite3_int64 iNow;
- sqlite3OsCurrentTimeInt64(db->pVfs, &iNow);
- db->xProfile(db->pProfileArg, p->zSql, iNow - p->startTime);
- }
-#endif
+ double rNow;
+ u64 elapseTime;
- if( rc==SQLITE_DONE ){
- assert( p->rc==SQLITE_OK );
- p->rc = doWalCallbacks(db);
- if( p->rc!=SQLITE_OK ){
- rc = SQLITE_ERROR;
- }
+ sqlite3OsCurrentTime(db->pVfs, &rNow);
+ elapseTime = (u64)((rNow - (int)rNow)*3600.0*24.0*1000000000.0);
+ elapseTime -= p->startTime;
+ db->xProfile(db->pProfileArg, p->zSql, elapseTime);
}
+#endif
db->errCode = rc;
if( SQLITE_NOMEM==sqlite3ApiExit(p->db, p->rc) ){
p->rc = SQLITE_NOMEM;
}
end_of_step:
- /* At this point local variable rc holds the value that should be
- ** returned if this statement was compiled using the legacy
+ /* At this point local variable rc holds the value that should be
+ ** returned if this statement was compiled using the legacy
** sqlite3_prepare() interface. According to the docs, this can only
- ** be one of the values in the first assert() below. Variable p->rc
- ** contains the value that would be returned if sqlite3_finalize()
+ ** be one of the values in the first assert() below. Variable p->rc
+ ** contains the value that would be returned if sqlite3_finalize()
** were called on statement p.
*/
- assert( rc==SQLITE_ROW || rc==SQLITE_DONE || rc==SQLITE_ERROR
+ assert( rc==SQLITE_ROW || rc==SQLITE_DONE || rc==SQLITE_ERROR
|| rc==SQLITE_BUSY || rc==SQLITE_MISUSE
);
assert( p->rc!=SQLITE_ROW && p->rc!=SQLITE_DONE );
@@ -56425,7 +50935,7 @@ end_of_step:
/* If this statement was prepared using sqlite3_prepare_v2(), and an
** error has occured, then return the error code in p->rc to the
** caller. Set the error code in the database handle to the same value.
- */
+ */
rc = db->errCode = p->rc;
}
return (rc&db->errMask);
@@ -56454,16 +50964,16 @@ SQLITE_API int sqlite3_step(sqlite3_stmt *pStmt){
sqlite3_reset(pStmt);
v->expired = 0;
}
- if( rc2!=SQLITE_OK && ALWAYS(v->isPrepareV2) && ALWAYS(db->pErr) ){
- /* This case occurs after failing to recompile an sql statement.
- ** The error message from the SQL compiler has already been loaded
- ** into the database handle. This block copies the error message
+ if( rc2!=SQLITE_OK && v->isPrepareV2 && db->pErr ){
+ /* This case occurs after failing to recompile an sql statement.
+ ** The error message from the SQL compiler has already been loaded
+ ** into the database handle. This block copies the error message
** from the database handle into the statement and sets the statement
- ** program counter to 0 to ensure that when the statement is
+ ** program counter to 0 to ensure that when the statement is
** finalized or reset the parser error message is available via
** sqlite3_errmsg() and sqlite3_errcode().
*/
- const char *zErr = (const char *)sqlite3_value_text(db->pErr);
+ const char *zErr = (const char *)sqlite3_value_text(db->pErr);
sqlite3DbFree(db, v->zErrMsg);
if( !db->mallocFailed ){
v->zErrMsg = sqlite3DbStrDup(db, zErr);
@@ -56567,9 +51077,9 @@ SQLITE_API void *sqlite3_get_auxdata(sqlite3_context *pCtx, int iArg){
** deleted by calling the delete function specified when it was set.
*/
SQLITE_API void sqlite3_set_auxdata(
- sqlite3_context *pCtx,
- int iArg,
- void *pAux,
+ sqlite3_context *pCtx,
+ int iArg,
+ void *pAux,
void (*xDelete)(void*)
){
struct AuxData *pAuxData;
@@ -56607,7 +51117,7 @@ failed:
#ifndef SQLITE_OMIT_DEPRECATED
/*
-** Return the number of times the Step function of a aggregate has been
+** Return the number of times the Step function of a aggregate has been
** called.
**
** This function is deprecated. Do not use it for new code. It is
@@ -56668,9 +51178,9 @@ static Mem *columnMem(sqlite3_stmt *pStmt, int i){
** this assert() from failing, when building with SQLITE_DEBUG defined
** using gcc, force nullMem to be 8-byte aligned using the magical
** __attribute__((aligned(8))) macro. */
- static const Mem nullMem
+ static const Mem nullMem
#if defined(SQLITE_DEBUG) && defined(__GNUC__)
- __attribute__((aligned(8)))
+ __attribute__((aligned(8)))
#endif
= {{0}, (double)0, 0, "", 0, MEM_Null, SQLITE_NULL, 0, 0, 0 };
@@ -56684,9 +51194,9 @@ static Mem *columnMem(sqlite3_stmt *pStmt, int i){
}
/*
-** This function is called after invoking an sqlite3_value_XXX function on a
+** This function is called after invoking an sqlite3_value_XXX function on a
** column value (i.e. a value returned by evaluating an SQL expression in the
-** select list of a SELECT statement) that may cause a malloc() failure. If
+** select list of a SELECT statement) that may cause a malloc() failure. If
** malloc() has failed, the threads mallocFailed flag is cleared and the result
** code of statement pStmt set to SQLITE_NOMEM.
**
@@ -56724,8 +51234,8 @@ SQLITE_API const void *sqlite3_column_blob(sqlite3_stmt *pStmt, int i){
const void *val;
val = sqlite3_value_blob( columnMem(pStmt,i) );
/* Even though there is no encoding conversion, value_blob() might
- ** need to call malloc() to expand the result of a zeroblob()
- ** expression.
+ ** need to call malloc() to expand the result of a zeroblob()
+ ** expression.
*/
columnMallocFailure(pStmt);
return val;
@@ -56815,7 +51325,7 @@ static const void *columnName(
Vdbe *p = (Vdbe *)pStmt;
int n;
sqlite3 *db = p->db;
-
+
assert( db!=0 );
n = sqlite3_column_count(pStmt);
if( N<n && N>=0 ){
@@ -56928,11 +51438,11 @@ SQLITE_API const void *sqlite3_column_origin_name16(sqlite3_stmt *pStmt, int N){
/******************************* sqlite3_bind_ ***************************
-**
+**
** Routines used to attach values to wildcards in a compiled SQL statement.
*/
/*
-** Unbind the value bound to variable i in virtual machine p. This is the
+** Unbind the value bound to variable i in virtual machine p. This is the
** the same as binding a NULL value to the column. If the "i" parameter is
** out of range, then SQLITE_RANGE is returned. Othewise SQLITE_OK.
**
@@ -56951,7 +51461,7 @@ static int vdbeUnbind(Vdbe *p, int i){
if( p->magic!=VDBE_MAGIC_RUN || p->pc>=0 ){
sqlite3Error(p->db, SQLITE_MISUSE, 0);
sqlite3_mutex_leave(p->db->mutex);
- sqlite3_log(SQLITE_MISUSE,
+ sqlite3_log(SQLITE_MISUSE,
"bind on a busy prepared statement: [%s]", p->zSql);
return SQLITE_MISUSE_BKPT;
}
@@ -56966,7 +51476,7 @@ static int vdbeUnbind(Vdbe *p, int i){
pVar->flags = MEM_Null;
sqlite3Error(p->db, SQLITE_OK, 0);
- /* If the bit corresponding to this variable in Vdbe.expmask is set, then
+ /* If the bit corresponding to this variable in Vdbe.expmask is set, then
** binding a new value to this variable invalidates the current query plan.
*/
if( p->isPrepareV2 &&
@@ -57013,10 +51523,10 @@ static int bindText(
** Bind a blob value to an SQL statement variable.
*/
SQLITE_API int sqlite3_bind_blob(
- sqlite3_stmt *pStmt,
- int i,
- const void *zData,
- int nData,
+ sqlite3_stmt *pStmt,
+ int i,
+ const void *zData,
+ int nData,
void (*xDel)(void*)
){
return bindText(pStmt, i, zData, nData, xDel, 0);
@@ -57053,21 +51563,21 @@ SQLITE_API int sqlite3_bind_null(sqlite3_stmt *pStmt, int i){
}
return rc;
}
-SQLITE_API int sqlite3_bind_text(
- sqlite3_stmt *pStmt,
- int i,
- const char *zData,
- int nData,
+SQLITE_API int sqlite3_bind_text(
+ sqlite3_stmt *pStmt,
+ int i,
+ const char *zData,
+ int nData,
void (*xDel)(void*)
){
return bindText(pStmt, i, zData, nData, xDel, SQLITE_UTF8);
}
#ifndef SQLITE_OMIT_UTF16
SQLITE_API int sqlite3_bind_text16(
- sqlite3_stmt *pStmt,
- int i,
- const void *zData,
- int nData,
+ sqlite3_stmt *pStmt,
+ int i,
+ const void *zData,
+ int nData,
void (*xDel)(void*)
){
return bindText(pStmt, i, zData, nData, xDel, SQLITE_UTF16NATIVE);
@@ -57117,7 +51627,7 @@ SQLITE_API int sqlite3_bind_zeroblob(sqlite3_stmt *pStmt, int i, int n){
/*
** Return the number of wildcards that can be potentially bound to.
-** This routine is added to support DBD::SQLite.
+** This routine is added to support DBD::SQLite.
*/
SQLITE_API int sqlite3_bind_parameter_count(sqlite3_stmt *pStmt){
Vdbe *p = (Vdbe*)pStmt;
@@ -57175,7 +51685,7 @@ SQLITE_PRIVATE int sqlite3VdbeParameterIndex(Vdbe *p, const char *zName, int nNa
if( p==0 ){
return 0;
}
- createVarMap(p);
+ createVarMap(p);
if( zName ){
for(i=0; i<p->nVar; i++){
const char *z = p->azVar[i];
@@ -57350,7 +51860,7 @@ SQLITE_PRIVATE char *sqlite3VdbeExpandSql(
char zBase[100]; /* Initial working space */
db = p->db;
- sqlite3StrAccumInit(&out, zBase, sizeof(zBase),
+ sqlite3StrAccumInit(&out, zBase, sizeof(zBase),
db->aLimit[SQLITE_LIMIT_LENGTH]);
out.db = db;
while( zRawSql[0] ){
@@ -57430,7 +51940,7 @@ SQLITE_PRIVATE char *sqlite3VdbeExpandSql(
** May you share freely, never taking more than you give.
**
*************************************************************************
-** The code in this file implements execution method of the
+** The code in this file implements execution method of the
** Virtual Database Engine (VDBE). A separate file ("vdbeaux.c")
** handles housekeeping details such as creating and deleting
** VDBE instances. This file is solely interested in executing
@@ -57440,10 +51950,10 @@ SQLITE_PRIVATE char *sqlite3VdbeExpandSql(
** to a VDBE.
**
** The SQL parser generates a program which is then executed by
-** the VDBE to do the work of the SQL statement. VDBE programs are
+** the VDBE to do the work of the SQL statement. VDBE programs are
** similar in form to assembly language. The program consists of
-** a linear sequence of operations. Each operation has an opcode
-** and 5 operands. Operands P1, P2, and P3 are integers. Operand P4
+** a linear sequence of operations. Each operation has an opcode
+** and 5 operands. Operands P1, P2, and P3 are integers. Operand P4
** is a null-terminated string. Operand P5 is an unsigned character.
** Few opcodes use all 5 operands.
**
@@ -57452,7 +51962,7 @@ SQLITE_PRIVATE char *sqlite3VdbeExpandSql(
** either an integer, a null-terminated string, a floating point
** number, or the SQL "NULL" value. An implicit conversion from one
** type to the other occurs as necessary.
-**
+**
** Most of the code in this file is taken up by the sqlite3VdbeExec()
** function which does the work of interpreting a VDBE program.
** But other routines are also provided to help in building up
@@ -57568,7 +52078,7 @@ SQLITE_API int sqlite3_found_count = 0;
/*
** Argument pMem points at a register that will be passed to a
** user-defined function or returned to the user as the result of a query.
-** This routine sets the pMem->type variable used by the sqlite3_value_*()
+** This routine sets the pMem->type variable used by the sqlite3_value_*()
** routines.
*/
SQLITE_PRIVATE void sqlite3VdbeMemStoreType(Mem *pMem){
@@ -57601,7 +52111,7 @@ static VdbeCursor *allocateCursor(
int isBtreeCursor /* True for B-Tree. False for pseudo-table or vtab */
){
/* Find the memory cell that will be used to store the blob of memory
- ** required for this VdbeCursor structure. It is convenient to use a
+ ** required for this VdbeCursor structure. It is convenient to use a
** vdbe memory cell to manage the memory allocation required for a
** VdbeCursor structure for the following reasons:
**
@@ -57622,9 +52132,9 @@ static VdbeCursor *allocateCursor(
int nByte;
VdbeCursor *pCx = 0;
- nByte =
- ROUND8(sizeof(VdbeCursor)) +
- (isBtreeCursor?sqlite3BtreeCursorSize():0) +
+ nByte =
+ ROUND8(sizeof(VdbeCursor)) +
+ (isBtreeCursor?sqlite3BtreeCursorSize():0) +
2*nField*sizeof(u32);
assert( iCur<p->nCursor );
@@ -57658,30 +52168,17 @@ static VdbeCursor *allocateCursor(
static void applyNumericAffinity(Mem *pRec){
if( (pRec->flags & (MEM_Real|MEM_Int))==0 ){
int realnum;
- u8 enc = pRec->enc;
sqlite3VdbeMemNulTerminate(pRec);
- if( (pRec->flags&MEM_Str) && sqlite3IsNumber(pRec->z, &realnum, enc) ){
+ if( (pRec->flags&MEM_Str)
+ && sqlite3IsNumber(pRec->z, &realnum, pRec->enc) ){
i64 value;
- char *zUtf8 = pRec->z;
-#ifndef SQLITE_OMIT_UTF16
- if( enc!=SQLITE_UTF8 ){
- assert( pRec->db );
- zUtf8 = sqlite3Utf16to8(pRec->db, pRec->z, pRec->n, enc);
- if( !zUtf8 ) return;
- }
-#endif
- if( !realnum && sqlite3Atoi64(zUtf8, &value) ){
+ sqlite3VdbeChangeEncoding(pRec, SQLITE_UTF8);
+ if( !realnum && sqlite3Atoi64(pRec->z, &value) ){
pRec->u.i = value;
MemSetTypeFlag(pRec, MEM_Int);
}else{
- sqlite3AtoF(zUtf8, &pRec->r);
- MemSetTypeFlag(pRec, MEM_Real);
- }
-#ifndef SQLITE_OMIT_UTF16
- if( enc!=SQLITE_UTF8 ){
- sqlite3DbFree(pRec->db, zUtf8);
+ sqlite3VdbeMemRealify(pRec);
}
-#endif
}
}
}
@@ -57692,7 +52189,7 @@ static void applyNumericAffinity(Mem *pRec){
** SQLITE_AFF_INTEGER:
** SQLITE_AFF_REAL:
** SQLITE_AFF_NUMERIC:
-** Try to convert pRec to an integer representation or a
+** Try to convert pRec to an integer representation or a
** floating-point representation if an integer representation
** is not possible. Note that the integer representation is
** always preferred, even if the affinity is REAL, because
@@ -57744,12 +52241,12 @@ SQLITE_API int sqlite3_value_numeric_type(sqlite3_value *pVal){
}
/*
-** Exported version of applyAffinity(). This one works on sqlite3_value*,
+** Exported version of applyAffinity(). This one works on sqlite3_value*,
** not the internal Mem* type.
*/
SQLITE_PRIVATE void sqlite3ValueApplyAffinity(
- sqlite3_value *pVal,
- u8 affinity,
+ sqlite3_value *pVal,
+ u8 affinity,
u8 enc
){
applyAffinity((Mem *)pVal, affinity, enc);
@@ -57878,8 +52375,8 @@ static void registerTrace(FILE *out, int iReg, Mem *p){
#ifdef VDBE_PROFILE
-/*
-** hwtime.h contains inline assembler code for implementing
+/*
+** hwtime.h contains inline assembler code for implementing
** high-performance timing routines.
*/
/************** Include hwtime.h in the middle of vdbe.c *********************/
@@ -57937,7 +52434,7 @@ static void registerTrace(FILE *out, int iReg, Mem *p){
__asm__ __volatile__ ("rdtsc" : "=A" (val));
return val;
}
-
+
#elif (defined(__GNUC__) && defined(__ppc__))
__inline__ sqlite_uint64 sqlite3Hwtime(void){
@@ -58009,9 +52506,9 @@ static int fileExists(sqlite3 *db, const char *zFile){
/*
** This function is only called from within an assert() expression. It
** checks that the sqlite3.nTransaction variable is correctly set to
-** the number of non-transaction savepoints currently in the
+** the number of non-transaction savepoints currently in the
** linked list starting at sqlite3.pSavepoint.
-**
+**
** Usage:
**
** assert( checkSavepointCount(db) );
@@ -58059,7 +52556,7 @@ static int checkSavepointCount(sqlite3 *db){
SQLITE_PRIVATE int sqlite3VdbeExec(
Vdbe *p /* The VDBE */
){
- int pc=0; /* The program counter */
+ int pc; /* The program counter */
Op *aOp = p->aOp; /* Copy of p->aOp */
Op *pOp; /* Current operation */
int rc = SQLITE_OK; /* Value to return */
@@ -58094,6 +52591,9 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
int pcDest;
} aa;
struct OP_Variable_stack_vars {
+ int p1; /* Variable to copy from */
+ int p2; /* Register to copy to */
+ int n; /* Number of values left to copy */
Mem *pVar; /* Value being transferred */
} ab;
struct OP_Move_stack_vars {
@@ -58130,8 +52630,6 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
struct OP_Ge_stack_vars {
int res; /* Result of the comparison of pIn1 against pIn3 */
char affinity; /* Affinity to use for comparison */
- u16 flags1; /* Copy of initial value of pIn1->flags */
- u16 flags3; /* Copy of initial value of pIn3->flags */
} ai;
struct OP_Compare_stack_vars {
int n;
@@ -58418,26 +52916,18 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
struct OP_AggFinal_stack_vars {
Mem *pMem;
} cc;
- struct OP_JournalMode_stack_vars {
- Btree *pBt; /* Btree to change journal mode of */
- Pager *pPager; /* Pager associated with pBt */
- int eNew; /* New journal mode */
- int eOld; /* The old journal mode */
- const sqlite3_vfs *pVfs; /* The VFS of pPager */
- const char *zFilename; /* Name of database file for pPager */
- } cd;
struct OP_IncrVacuum_stack_vars {
Btree *pBt;
- } ce;
+ } cd;
struct OP_VBegin_stack_vars {
VTable *pVTab;
- } cf;
+ } ce;
struct OP_VOpen_stack_vars {
VdbeCursor *pCur;
sqlite3_vtab_cursor *pVtabCursor;
sqlite3_vtab *pVtab;
sqlite3_module *pModule;
- } cg;
+ } cf;
struct OP_VFilter_stack_vars {
int nArg;
int iQuery;
@@ -58450,23 +52940,23 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
int res;
int i;
Mem **apArg;
- } ch;
+ } cg;
struct OP_VColumn_stack_vars {
sqlite3_vtab *pVtab;
const sqlite3_module *pModule;
Mem *pDest;
sqlite3_context sContext;
- } ci;
+ } ch;
struct OP_VNext_stack_vars {
sqlite3_vtab *pVtab;
const sqlite3_module *pModule;
int res;
VdbeCursor *pCur;
- } cj;
+ } ci;
struct OP_VRename_stack_vars {
sqlite3_vtab *pVtab;
Mem *pName;
- } ck;
+ } cj;
struct OP_VUpdate_stack_vars {
sqlite3_vtab *pVtab;
sqlite3_module *pModule;
@@ -58475,6 +52965,11 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
sqlite_int64 rowid;
Mem **apArg;
Mem *pX;
+ } ck;
+ struct OP_Pagecount_stack_vars {
+ int p1;
+ int nPage;
+ Pager *pPager;
} cl;
struct OP_Trace_stack_vars {
char *zTrace;
@@ -58502,7 +52997,7 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
#endif
#ifdef SQLITE_DEBUG
sqlite3BeginBenignMalloc();
- if( p->pc==0
+ if( p->pc==0
&& ((p->db->flags & SQLITE_VdbeListing) || fileExists(db, "vdbe_explain"))
){
int i;
@@ -58544,7 +53039,7 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
sqlite3EndBenignMalloc();
}
#endif
-
+
/* Check to see if we need to simulate an interrupt. This only happens
** if we have a special test build.
@@ -58619,7 +53114,7 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
assert( pOp->p3<=p->nMem );
}
#endif
-
+
switch( pOp->opcode ){
/*****************************************************************************
@@ -58660,7 +53155,7 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
/* Opcode: Goto * P2 * * *
**
** An unconditional jump to address P2.
-** The next instruction executed will be
+** The next instruction executed will be
** the one at index P2 from the beginning of
** the program.
*/
@@ -58737,7 +53232,7 @@ case OP_HaltIfNull: { /* in3 */
** whether or not to rollback the current transaction. Do not rollback
** if P2==OE_Fail. Do the rollback if P2==OE_Rollback. If P2==OE_Abort,
** then back out all changes that have occurred during this execution of the
-** VDBE, but do not rollback the transaction.
+** VDBE, but do not rollback the transaction.
**
** If P4 is not null then it is an error message string.
**
@@ -58754,7 +53249,7 @@ case OP_Halt: {
sqlite3VdbeSetChanges(db, p->nChange);
pc = sqlite3VdbeFrameRestore(pFrame);
if( pOp->p2==OE_Ignore ){
- /* Instruction pc is the OP_Program that invoked the sub-program
+ /* Instruction pc is the OP_Program that invoked the sub-program
** currently being halted. If the p2 instruction of this OP_Halt
** instruction is set to OE_Ignore, then the sub-program is throwing
** an IGNORE exception. In this case jump to the address specified
@@ -58810,7 +53305,6 @@ case OP_Int64: { /* out2-prerelease */
break;
}
-#ifndef SQLITE_OMIT_FLOATING_POINT
/* Opcode: Real * P2 * P4 *
**
** P4 is a pointer to a 64-bit floating point value.
@@ -58822,11 +53316,10 @@ case OP_Real: { /* same as TK_FLOAT, out2-prerelease */
pOut->r = *pOp->p4.pReal;
break;
}
-#endif
/* Opcode: String8 * P2 * P4 *
**
-** P4 points to a nul terminated UTF-8 string. This opcode is transformed
+** P4 points to a nul terminated UTF-8 string. This opcode is transformed
** into an OP_String before it is executed for the first time.
*/
case OP_String8: { /* same as TK_STRING, out2-prerelease */
@@ -58857,7 +53350,7 @@ case OP_String8: { /* same as TK_STRING, out2-prerelease */
}
/* Fall through to the next case, OP_String */
}
-
+
/* Opcode: String P1 P2 * P4 *
**
** The string value P4 of length P1 (bytes) is stored in register P2.
@@ -58899,25 +53392,40 @@ case OP_Blob: { /* out2-prerelease */
break;
}
-/* Opcode: Variable P1 P2 * P4 *
+/* Opcode: Variable P1 P2 P3 P4 *
**
-** Transfer the values of bound parameter P1 into register P2
+** Transfer the values of bound parameters P1..P1+P3-1 into registers
+** P2..P2+P3-1.
**
** If the parameter is named, then its name appears in P4 and P3==1.
** The P4 value is used by sqlite3_bind_parameter_name().
*/
-case OP_Variable: { /* out2-prerelease */
+case OP_Variable: {
#if 0 /* local variables moved into u.ab */
+ int p1; /* Variable to copy from */
+ int p2; /* Register to copy to */
+ int n; /* Number of values left to copy */
Mem *pVar; /* Value being transferred */
#endif /* local variables moved into u.ab */
- assert( pOp->p1>0 && pOp->p1<=p->nVar );
- u.ab.pVar = &p->aVar[pOp->p1 - 1];
- if( sqlite3VdbeMemTooBig(u.ab.pVar) ){
- goto too_big;
+ u.ab.p1 = pOp->p1 - 1;
+ u.ab.p2 = pOp->p2;
+ u.ab.n = pOp->p3;
+ assert( u.ab.p1>=0 && u.ab.p1+u.ab.n<=p->nVar );
+ assert( u.ab.p2>=1 && u.ab.p2+u.ab.n-1<=p->nMem );
+ assert( pOp->p4.z==0 || pOp->p3==1 || pOp->p3==0 );
+
+ while( u.ab.n-- > 0 ){
+ u.ab.pVar = &p->aVar[u.ab.p1++];
+ if( sqlite3VdbeMemTooBig(u.ab.pVar) ){
+ goto too_big;
+ }
+ pOut = &aMem[u.ab.p2++];
+ sqlite3VdbeMemReleaseExternal(pOut);
+ pOut->flags = MEM_Null;
+ sqlite3VdbeMemShallowCopy(pOut, u.ab.pVar, MEM_Static);
+ UPDATE_MAX_BLOBSIZE(pOut);
}
- sqlite3VdbeMemShallowCopy(pOut, u.ab.pVar, MEM_Static);
- UPDATE_MAX_BLOBSIZE(pOut);
break;
}
@@ -59136,14 +53644,14 @@ case OP_Concat: { /* same as TK_CONCAT, in1, in2, out3 */
/* Opcode: Divide P1 P2 P3 * *
**
** Divide the value in register P1 by the value in register P2
-** and store the result in register P3 (P3=P2/P1). If the value in
-** register P1 is zero, then the result is NULL. If either input is
+** and store the result in register P3 (P3=P2/P1). If the value in
+** register P1 is zero, then the result is NULL. If either input is
** NULL, the result is NULL.
*/
/* Opcode: Remainder P1 P2 P3 * *
**
** Compute the remainder after integer division of the value in
-** register P1 by the value in register P2 and store the result in P3.
+** register P1 by the value in register P2 and store the result in P3.
** If the value in register P2 is zero the result is NULL.
** If either operand is NULL, the result is NULL.
*/
@@ -59218,10 +53726,6 @@ case OP_Remainder: { /* same as TK_REM, in1, in2, out3 */
break;
}
}
-#ifdef SQLITE_OMIT_FLOATING_POINT
- pOut->u.i = u.af.rB;
- MemSetTypeFlag(pOut, MEM_Int);
-#else
if( sqlite3IsNaN(u.af.rB) ){
goto arithmetic_result_is_null;
}
@@ -59230,7 +53734,6 @@ case OP_Remainder: { /* same as TK_REM, in1, in2, out3 */
if( (u.af.flags & MEM_Real)==0 ){
sqlite3VdbeIntegerAffinity(pOut);
}
-#endif
}
break;
@@ -59262,7 +53765,7 @@ case OP_CollSeq: {
** successors. The result of the function is stored in register P3.
** Register P3 must not be one of the function inputs.
**
-** P1 is a 32-bit bitmask indicating whether or not each argument to the
+** P1 is a 32-bit bitmask indicating whether or not each argument to the
** function was determined to be constant at compile time. If the first
** argument was constant then bit 0 of P1 is set. This is used to determine
** whether meta data associated with a user function argument using the
@@ -59290,7 +53793,7 @@ case OP_Function: {
for(u.ag.i=0; u.ag.i<u.ag.n; u.ag.i++, u.ag.pArg++){
u.ag.apVal[u.ag.i] = u.ag.pArg;
sqlite3VdbeMemStoreType(u.ag.pArg);
- REGISTER_TRACE(pOp->p2+u.ag.i, u.ag.pArg);
+ REGISTER_TRACE(pOp->p2, u.ag.pArg);
}
assert( pOp->p4type==P4_FUNCDEF || pOp->p4type==P4_VDBEFUNC );
@@ -59417,7 +53920,7 @@ case OP_ShiftRight: { /* same as TK_RSHIFT, in1, in2, out3 */
}
/* Opcode: AddImm P1 P2 * * *
-**
+**
** Add the constant P2 to the value in register P1.
** The result is always an integer.
**
@@ -59431,7 +53934,7 @@ case OP_AddImm: { /* in1 */
}
/* Opcode: MustBeInt P1 P2 * * *
-**
+**
** Force the value in register P1 to be an integer. If the value
** in P1 is not an integer and cannot be converted into an integer
** without data loss, then jump immediately to P2, or if P2==0
@@ -59453,7 +53956,6 @@ case OP_MustBeInt: { /* jump, in1 */
break;
}
-#ifndef SQLITE_OMIT_FLOATING_POINT
/* Opcode: RealAffinity P1 * * * *
**
** If register P1 holds an integer convert it to a real value.
@@ -59470,7 +53972,6 @@ case OP_RealAffinity: { /* in1 */
}
break;
}
-#endif
#ifndef SQLITE_OMIT_CAST
/* Opcode: ToText P1 * * * *
@@ -59523,7 +54024,7 @@ case OP_ToBlob: { /* same as TK_TO_BLOB, in1 */
** Force the value in register P1 to be numeric (either an
** integer or a floating-point number.)
** If the value is text or blob, try to convert it to an using the
-** equivalent of atoi() or atof() and store 0 if no such conversion
+** equivalent of atoi() or atof() and store 0 if no such conversion
** is possible.
**
** A NULL value is not changed by this routine. It remains NULL.
@@ -59554,7 +54055,7 @@ case OP_ToInt: { /* same as TK_TO_INT, in1 */
break;
}
-#if !defined(SQLITE_OMIT_CAST) && !defined(SQLITE_OMIT_FLOATING_POINT)
+#ifndef SQLITE_OMIT_CAST
/* Opcode: ToReal P1 * * * *
**
** Force the value in register P1 to be a floating point number.
@@ -59571,26 +54072,26 @@ case OP_ToReal: { /* same as TK_TO_REAL, in1 */
}
break;
}
-#endif /* !defined(SQLITE_OMIT_CAST) && !defined(SQLITE_OMIT_FLOATING_POINT) */
+#endif /* SQLITE_OMIT_CAST */
/* Opcode: Lt P1 P2 P3 P4 P5
**
** Compare the values in register P1 and P3. If reg(P3)<reg(P1) then
-** jump to address P2.
+** jump to address P2.
**
** If the SQLITE_JUMPIFNULL bit of P5 is set and either reg(P1) or
-** reg(P3) is NULL then take the jump. If the SQLITE_JUMPIFNULL
+** reg(P3) is NULL then take the jump. If the SQLITE_JUMPIFNULL
** bit is clear then fall thru if either operand is NULL.
**
** The SQLITE_AFF_MASK portion of P5 must be an affinity character -
-** SQLITE_AFF_TEXT, SQLITE_AFF_INTEGER, and so forth. An attempt is made
+** SQLITE_AFF_TEXT, SQLITE_AFF_INTEGER, and so forth. An attempt is made
** to coerce both inputs according to this affinity before the
** comparison is made. If the SQLITE_AFF_MASK is 0x00, then numeric
** affinity is used. Note that the affinity conversions are stored
** back into the input registers P1 and P3. So this opcode can cause
** persistent changes to registers P1 and P3.
**
-** Once any conversions have taken place, and neither value is NULL,
+** Once any conversions have taken place, and neither value is NULL,
** the values are compared. If both values are blobs then memcmp() is
** used to determine the results of the comparison. If both values
** are text, then the appropriate collating function specified in
@@ -59654,14 +54155,10 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
#if 0 /* local variables moved into u.ai */
int res; /* Result of the comparison of pIn1 against pIn3 */
char affinity; /* Affinity to use for comparison */
- u16 flags1; /* Copy of initial value of pIn1->flags */
- u16 flags3; /* Copy of initial value of pIn3->flags */
#endif /* local variables moved into u.ai */
pIn1 = &aMem[pOp->p1];
pIn3 = &aMem[pOp->p3];
- u.ai.flags1 = pIn1->flags;
- u.ai.flags3 = pIn3->flags;
if( (pIn1->flags | pIn3->flags)&MEM_Null ){
/* One or both operands are NULL */
if( pOp->p5 & SQLITE_NULLEQ ){
@@ -59716,10 +54213,6 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
}else if( u.ai.res ){
pc = pOp->p2-1;
}
-
- /* Undo any changes made by applyAffinity() to the input registers. */
- pIn1->flags = (pIn1->flags&~MEM_TypeMask) | (u.ai.flags1&MEM_TypeMask);
- pIn3->flags = (pIn3->flags&~MEM_TypeMask) | (u.ai.flags3&MEM_TypeMask);
break;
}
@@ -59873,7 +54366,7 @@ case OP_Or: { /* same as TK_OR, in1, in2, out3 */
/* Opcode: Not P1 P2 * * *
**
** Interpret the value in register P1 as a boolean value. Store the
-** boolean complement in register P2. If the value in register P1 is
+** boolean complement in register P2. If the value in register P1 is
** NULL, then a NULL is stored in P2.
*/
case OP_Not: { /* same as TK_NOT, in1, out2 */
@@ -59952,7 +54445,7 @@ case OP_IsNull: { /* same as TK_ISNULL, jump, in1 */
/* Opcode: NotNull P1 P2 * * *
**
-** Jump to P2 if the value in register P1 is not NULL.
+** Jump to P2 if the value in register P1 is not NULL.
*/
case OP_NotNull: { /* same as TK_NOTNULL, jump, in1 */
pIn1 = &aMem[pOp->p1];
@@ -59967,7 +54460,7 @@ case OP_NotNull: { /* same as TK_NOTNULL, jump, in1 */
** Interpret the data that cursor P1 points to as a structure built using
** the MakeRecord instruction. (See the MakeRecord opcode for additional
** information about the format of the data.) Extract the P2-th column
-** from this record. If there are less that (P2+1)
+** from this record. If there are less that (P2+1)
** values in the record, extract a NULL.
**
** The value extracted is stored in register P3.
@@ -60429,7 +54922,7 @@ case OP_MakeRecord: {
/* Opcode: Count P1 P2 * * *
**
-** Store the number of entries (an integer value) in the table or index
+** Store the number of entries (an integer value) in the table or index
** opened by cursor P1 in register P2
*/
#ifndef SQLITE_OMIT_BTREECOUNT
@@ -60779,9 +55272,9 @@ case OP_ReadCookie: { /* out2-prerelease */
/* Opcode: SetCookie P1 P2 P3 * *
**
** Write the content of register P3 (interpreted as an integer)
-** into cookie number P2 of database P1. P2==1 is the schema version.
-** P2==2 is the database format. P2==3 is the recommended pager cache
-** size, and so forth. P1==0 is the main database file and P1==1 is the
+** into cookie number P2 of database P1. P2==1 is the schema version.
+** P2==2 is the database format. P2==3 is the recommended pager cache
+** size, and so forth. P1==0 is the main database file and P1==1 is the
** database file used to store temporary tables.
**
** A transaction must be started before executing this opcode.
@@ -60819,7 +55312,7 @@ case OP_SetCookie: { /* in3 */
/* Opcode: VerifyCookie P1 P2 *
**
** Check the value of global database parameter number 0 (the
-** schema version) and make sure it is equal to P2.
+** schema version) and make sure it is equal to P2.
** P1 is the database number which is 0 for the main database file
** and 1 for the file holding temporary tables and some higher number
** for auxiliary databases.
@@ -60874,8 +55367,8 @@ case OP_VerifyCookie: {
/* Opcode: OpenRead P1 P2 P3 P4 P5
**
** Open a read-only cursor for the database table whose root page is
-** P2 in a database file. The database file is determined by P3.
-** P3==0 means the main database, P3==1 means the database used for
+** P2 in a database file. The database file is determined by P3.
+** P3==0 means the main database, P3==1 means the database used for
** temporary tables, and P3>1 means used the corresponding attached
** database. Give the new cursor an identifier of P1. The P1
** values need not be contiguous but all P1 values should be small integers.
@@ -60894,9 +55387,9 @@ case OP_VerifyCookie: {
** SQLITE_BUSY error code.
**
** The P4 value may be either an integer (P4_INT32) or a pointer to
-** a KeyInfo structure (P4_KEYINFO). If it is a pointer to a KeyInfo
-** structure, then said structure defines the content and collating
-** sequence of the index being opened. Otherwise, if P4 is an integer
+** a KeyInfo structure (P4_KEYINFO). If it is a pointer to a KeyInfo
+** structure, then said structure defines the content and collating
+** sequence of the index being opened. Otherwise, if P4 is an integer
** value, it is set to the number of columns in the table.
**
** See also OpenWrite.
@@ -60908,9 +55401,9 @@ case OP_VerifyCookie: {
** root page.
**
** The P4 value may be either an integer (P4_INT32) or a pointer to
-** a KeyInfo structure (P4_KEYINFO). If it is a pointer to a KeyInfo
-** structure, then said structure defines the content and collating
-** sequence of the index being opened. Otherwise, if P4 is an integer
+** a KeyInfo structure (P4_KEYINFO). If it is a pointer to a KeyInfo
+** structure, then said structure defines the content and collating
+** sequence of the index being opened. Otherwise, if P4 is an integer
** value, it is set to the number of columns in the table, or to the
** largest index of any column of the table that is actually used.
**
@@ -61006,11 +55499,11 @@ case OP_OpenWrite: {
/* Opcode: OpenEphemeral P1 P2 * P4 *
**
** Open a new cursor P1 to a transient table.
-** The cursor is always opened read/write even if
-** the main database is read-only. The ephemeral
+** The cursor is always opened read/write even if
+** the main database is read-only. The transient or virtual
** table is deleted automatically when the cursor is closed.
**
-** P2 is the number of columns in the ephemeral table.
+** P2 is the number of columns in the virtual table.
** The cursor points to a BTree table if P4==0 and to a BTree index
** if P4 is not 0. If P4 is not NULL, it points to a KeyInfo structure
** that defines the format of keys in the index.
@@ -61021,14 +55514,6 @@ case OP_OpenWrite: {
** this opcode. Then this opcode was call OpenVirtual. But
** that created confusion with the whole virtual-table idea.
*/
-/* Opcode: OpenAutoindex P1 P2 * P4 *
-**
-** This opcode works the same as OP_OpenEphemeral. It has a
-** different name to distinguish its use. Tables created using
-** by this opcode will be used for automatically created transient
-** indices in joins.
-*/
-case OP_OpenAutoindex:
case OP_OpenEphemeral: {
#if 0 /* local variables moved into u.ax */
VdbeCursor *pCx;
@@ -61080,10 +55565,10 @@ case OP_OpenEphemeral: {
**
** Open a new cursor that points to a fake table that contains a single
** row of data. The content of that one row in the content of memory
-** register P2. In other words, cursor P1 becomes an alias for the
+** register P2. In other words, cursor P1 becomes an alias for the
** MEM_Blob content contained in register P2.
**
-** A pseudo-table created by this opcode is used to hold a single
+** A pseudo-table created by this opcode is used to hold the a single
** row output from the sorter so that the row can be decomposed into
** individual columns using the OP_Column opcode. The OP_Column opcode
** is the only cursor opcode that works with a pseudo-table.
@@ -61120,52 +55605,52 @@ case OP_Close: {
/* Opcode: SeekGe P1 P2 P3 P4 *
**
-** If cursor P1 refers to an SQL table (B-Tree that uses integer keys),
-** use the value in register P3 as the key. If cursor P1 refers
-** to an SQL index, then P3 is the first in an array of P4 registers
-** that are used as an unpacked index key.
+** If cursor P1 refers to an SQL table (B-Tree that uses integer keys),
+** use the value in register P3 as the key. If cursor P1 refers
+** to an SQL index, then P3 is the first in an array of P4 registers
+** that are used as an unpacked index key.
**
-** Reposition cursor P1 so that it points to the smallest entry that
-** is greater than or equal to the key value. If there are no records
+** Reposition cursor P1 so that it points to the smallest entry that
+** is greater than or equal to the key value. If there are no records
** greater than or equal to the key and P2 is not zero, then jump to P2.
**
** See also: Found, NotFound, Distinct, SeekLt, SeekGt, SeekLe
*/
/* Opcode: SeekGt P1 P2 P3 P4 *
**
-** If cursor P1 refers to an SQL table (B-Tree that uses integer keys),
-** use the value in register P3 as a key. If cursor P1 refers
-** to an SQL index, then P3 is the first in an array of P4 registers
-** that are used as an unpacked index key.
+** If cursor P1 refers to an SQL table (B-Tree that uses integer keys),
+** use the value in register P3 as a key. If cursor P1 refers
+** to an SQL index, then P3 is the first in an array of P4 registers
+** that are used as an unpacked index key.
**
-** Reposition cursor P1 so that it points to the smallest entry that
-** is greater than the key value. If there are no records greater than
+** Reposition cursor P1 so that it points to the smallest entry that
+** is greater than the key value. If there are no records greater than
** the key and P2 is not zero, then jump to P2.
**
** See also: Found, NotFound, Distinct, SeekLt, SeekGe, SeekLe
*/
-/* Opcode: SeekLt P1 P2 P3 P4 *
+/* Opcode: SeekLt P1 P2 P3 P4 *
**
-** If cursor P1 refers to an SQL table (B-Tree that uses integer keys),
-** use the value in register P3 as a key. If cursor P1 refers
-** to an SQL index, then P3 is the first in an array of P4 registers
-** that are used as an unpacked index key.
+** If cursor P1 refers to an SQL table (B-Tree that uses integer keys),
+** use the value in register P3 as a key. If cursor P1 refers
+** to an SQL index, then P3 is the first in an array of P4 registers
+** that are used as an unpacked index key.
**
-** Reposition cursor P1 so that it points to the largest entry that
-** is less than the key value. If there are no records less than
+** Reposition cursor P1 so that it points to the largest entry that
+** is less than the key value. If there are no records less than
** the key and P2 is not zero, then jump to P2.
**
** See also: Found, NotFound, Distinct, SeekGt, SeekGe, SeekLe
*/
/* Opcode: SeekLe P1 P2 P3 P4 *
**
-** If cursor P1 refers to an SQL table (B-Tree that uses integer keys),
-** use the value in register P3 as a key. If cursor P1 refers
-** to an SQL index, then P3 is the first in an array of P4 registers
-** that are used as an unpacked index key.
+** If cursor P1 refers to an SQL table (B-Tree that uses integer keys),
+** use the value in register P3 as a key. If cursor P1 refers
+** to an SQL index, then P3 is the first in an array of P4 registers
+** that are used as an unpacked index key.
**
-** Reposition cursor P1 so that it points to the largest entry that
-** is less than or equal to the key value. If there are no records
+** Reposition cursor P1 so that it points to the largest entry that
+** is less than or equal to the key value. If there are no records
** less than or equal to the key and P2 is not zero, then jump to P2.
**
** See also: Found, NotFound, Distinct, SeekGt, SeekGe, SeekLt
@@ -61347,7 +55832,7 @@ case OP_Seek: { /* in2 */
}
break;
}
-
+
/* Opcode: Found P1 P2 P3 P4 *
**
@@ -61364,9 +55849,9 @@ case OP_Seek: { /* in2 */
** If P4==0 then register P3 holds a blob constructed by MakeRecord. If
** P4>0 then register P3 is the first of P4 registers that form an unpacked
** record.
-**
+**
** Cursor P1 is on an index btree. If the record identified by P3 and P4
-** is not the prefix of any entry in P1 then a jump is made to P2. If P1
+** is not the prefix of any entry in P1 then a jump is made to P2. If P1
** does contain an entry whose prefix matches the P3/P4 record then control
** falls through to the next instruction and P1 is left pointing at the
** matching entry.
@@ -61439,7 +55924,7 @@ case OP_Found: { /* jump, in3 */
** the list field being the integer ROWID of the entry that the index
** entry refers to.
**
-** The P3 register contains an integer record number. Call this record
+** The P3 register contains an integer record number. Call this record
** number R. Register P4 is the first in a set of N contiguous registers
** that make up an unpacked index key that can be used with cursor P1.
** The value of N can be inferred from the cursor. N includes the rowid
@@ -61520,9 +56005,9 @@ case OP_IsUnique: { /* jump, in3 */
/* Opcode: NotExists P1 P2 P3 * *
**
-** Use the content of register P3 as a integer key. If a record
-** with that key does not exist in table of P1, then jump to P2.
-** If the record does exist, then fall thru. The cursor is left
+** Use the content of register P3 as a integer key. If a record
+** with that key does not exist in table of P1, then jump to P2.
+** If the record does exist, then fall thru. The cursor is left
** pointing to the record if it exists.
**
** The difference between this operation and NotFound is that this
@@ -61578,7 +56063,7 @@ case OP_NotExists: { /* jump, in3 */
** Find the next available sequence number for cursor P1.
** Write the sequence number into register P2.
** The sequence number on the cursor is incremented after this
-** instruction.
+** instruction.
*/
case OP_Sequence: { /* out2-prerelease */
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
@@ -61595,9 +56080,9 @@ case OP_Sequence: { /* out2-prerelease */
** table that cursor P1 points to. The new record number is written
** written to register P2.
**
-** If P3>0 then P3 is a register in the root frame of this VDBE that holds
+** If P3>0 then P3 is a register in the root frame of this VDBE that holds
** the largest previously generated record number. No new record numbers are
-** allowed to be less than this value. When this value reaches its maximum,
+** allowed to be less than this value. When this value reaches its maximum,
** a SQLITE_FULL error is generated. The P3 register is updated with the '
** generated record number. This P3 mechanism is used to help implement the
** AUTOINCREMENT feature.
@@ -61758,7 +56243,7 @@ case OP_NewRowid: { /* out2-prerelease */
** the update hook.
**
** Parameter P4 may point to a string containing the table-name, or
-** may be NULL. If it is not NULL, then the update-hook
+** may be NULL. If it is not NULL, then the update-hook
** (sqlite3.xUpdateCallback) is invoked following a successful insert.
**
** (WARNING/TODO: If P1 is a pseudo-cursor and P2 is dynamically
@@ -61775,7 +56260,7 @@ case OP_NewRowid: { /* out2-prerelease */
** This works exactly like OP_Insert except that the key is the
** integer value P3, not the value of the integer stored in register P3.
*/
-case OP_Insert:
+case OP_Insert:
case OP_InsertInt: {
#if 0 /* local variables moved into u.bf */
Mem *pData; /* MEM cell holding data for the record to be inserted */
@@ -61925,8 +56410,8 @@ case OP_ResetCount: {
/* Opcode: RowData P1 P2 * * *
**
** Write into register P2 the complete row data for cursor P1.
-** There is no interpretation of the data.
-** It is just copied onto the P2 register exactly as
+** There is no interpretation of the data.
+** It is just copied onto the P2 register exactly as
** it is found in the database file.
**
** If the P1 cursor must be pointing to a valid row (not a NULL row)
@@ -61935,8 +56420,8 @@ case OP_ResetCount: {
/* Opcode: RowKey P1 P2 * * *
**
** Write into register P2 the complete row key for cursor P1.
-** There is no interpretation of the data.
-** The key is copied onto the P3 register exactly as
+** There is no interpretation of the data.
+** The key is copied onto the P3 register exactly as
** it is found in the database file.
**
** If the P1 cursor must be pointing to a valid row (not a NULL row)
@@ -62079,7 +56564,7 @@ case OP_NullRow: {
/* Opcode: Last P1 P2 * * *
**
-** The next use of the Rowid or Column or Next instruction for P1
+** The next use of the Rowid or Column or Next instruction for P1
** will refer to the last entry in the database table or index.
** If the table or index is empty and P2>0, then jump immediately to P2.
** If P2 is 0 or if the table or index is not empty, fall through
@@ -62134,7 +56619,7 @@ case OP_Sort: { /* jump */
}
/* Opcode: Rewind P1 P2 * * *
**
-** The next use of the Rowid or Column or Next instruction for P1
+** The next use of the Rowid or Column or Next instruction for P1
** will refer to the first entry in the database table or index.
** If the table or index is empty and P2>0, then jump immediately to P2.
** If P2 is 0 or if the table or index is not empty, fall through
@@ -62167,7 +56652,7 @@ case OP_Rewind: { /* jump */
break;
}
-/* Opcode: Next P1 P2 * * P5
+/* Opcode: Next P1 P2 * * *
**
** Advance cursor P1 so that it points to the next key/data pair in its
** table or index. If there are no more key/value pairs then fall through
@@ -62176,12 +56661,9 @@ case OP_Rewind: { /* jump */
**
** The P1 cursor must be for a real table, not a pseudo-table.
**
-** If P5 is positive and the jump is taken, then event counter
-** number P5-1 in the prepared statement is incremented.
-**
** See also: Prev
*/
-/* Opcode: Prev P1 P2 * * P5
+/* Opcode: Prev P1 P2 * * *
**
** Back up cursor P1 so that it points to the previous key/data pair in its
** table or index. If there is no previous key/value pairs then fall through
@@ -62189,9 +56671,6 @@ case OP_Rewind: { /* jump */
** jump immediately to P2.
**
** The P1 cursor must be for a real table, not a pseudo-table.
-**
-** If P5 is positive and the jump is taken, then event counter
-** number P5-1 in the prepared statement is incremented.
*/
case OP_Prev: /* jump */
case OP_Next: { /* jump */
@@ -62203,7 +56682,6 @@ case OP_Next: { /* jump */
CHECK_FOR_INTERRUPT;
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
- assert( pOp->p5<=ArraySize(p->aCounter) );
u.bm.pC = p->apCsr[pOp->p1];
if( u.bm.pC==0 ){
break; /* See ticket #2273 */
@@ -62275,7 +56753,7 @@ case OP_IdxInsert: { /* in2 */
/* Opcode: IdxDelete P1 P2 P3 * *
**
** The content of P3 registers starting at register P2 form
-** an unpacked index key. This opcode removes that entry from the
+** an unpacked index key. This opcode removes that entry from the
** index opened by cursor P1.
*/
case OP_IdxDelete: {
@@ -62346,28 +56824,28 @@ case OP_IdxRowid: { /* out2-prerelease */
/* Opcode: IdxGE P1 P2 P3 P4 P5
**
-** The P4 register values beginning with P3 form an unpacked index
-** key that omits the ROWID. Compare this key value against the index
+** The P4 register values beginning with P3 form an unpacked index
+** key that omits the ROWID. Compare this key value against the index
** that P1 is currently pointing to, ignoring the ROWID on the P1 index.
**
** If the P1 index entry is greater than or equal to the key value
** then jump to P2. Otherwise fall through to the next instruction.
**
-** If P5 is non-zero then the key value is increased by an epsilon
+** If P5 is non-zero then the key value is increased by an epsilon
** prior to the comparison. This make the opcode work like IdxGT except
** that if the key from register P3 is a prefix of the key in the cursor,
** the result is false whereas it would be true with IdxGT.
*/
/* Opcode: IdxLT P1 P2 P3 * P5
**
-** The P4 register values beginning with P3 form an unpacked index
-** key that omits the ROWID. Compare this key value against the index
+** The P4 register values beginning with P3 form an unpacked index
+** key that omits the ROWID. Compare this key value against the index
** that P1 is currently pointing to, ignoring the ROWID on the P1 index.
**
** If the P1 index entry is less than the key value then jump to P2.
** Otherwise fall through to the next instruction.
**
-** If P5 is non-zero then the key value is increased by an epsilon prior
+** If P5 is non-zero then the key value is increased by an epsilon prior
** to the comparison. This makes the opcode work like IdxLE.
*/
case OP_IdxLT: /* jump */
@@ -62420,8 +56898,8 @@ case OP_IdxGE: { /* jump */
** might be moved into the newly deleted root page in order to keep all
** root pages contiguous at the beginning of the database. The former
** value of the root page that moved - its value before the move occurred -
-** is stored in register P2. If no page
-** movement was required (because the table being dropped was already
+** is stored in register P2. If no page
+** movement was required (because the table being dropped was already
** the last one in the database) then a zero is stored in register P2.
** If AUTOVACUUM is disabled then a zero is stored in register P2.
**
@@ -62476,8 +56954,8 @@ case OP_Destroy: { /* out2-prerelease */
** that is used to store tables create using CREATE TEMPORARY TABLE.
**
** If the P3 value is non-zero, then the table referred to must be an
-** intkey table (an SQL table, not an index). In this case the row change
-** count is incremented by the number of rows in the table being cleared.
+** intkey table (an SQL table, not an index). In this case the row change
+** count is incremented by the number of rows in the table being cleared.
** If P3 is greater than zero, then the value stored in register P3 is
** also incremented by the number of rows in the table being cleared.
**
@@ -62600,7 +57078,7 @@ case OP_ParseSchema: {
u.bu.initData.iDb = pOp->p1;
u.bu.initData.pzErrMsg = &p->zErrMsg;
u.bu.zSql = sqlite3MPrintf(db,
- "SELECT name, rootpage, sql FROM '%q'.%s WHERE %s ORDER BY rowid",
+ "SELECT name, rootpage, sql FROM '%q'.%s WHERE %s",
db->aDb[u.bu.iDb].zName, u.bu.zMaster, pOp->p4.z);
if( u.bu.zSql==0 ){
rc = SQLITE_NOMEM;
@@ -62632,7 +57110,7 @@ case OP_ParseSchema: {
case OP_LoadAnalysis: {
assert( pOp->p1>=0 && pOp->p1<db->nDb );
rc = sqlite3AnalysisLoad(db, pOp->p1);
- break;
+ break;
}
#endif /* !defined(SQLITE_OMIT_ANALYZE) */
@@ -62682,7 +57160,7 @@ case OP_DropTrigger: {
**
** The register P3 contains the maximum number of allowed errors.
** At most reg(P3) errors will be reported.
-** In other words, the analysis stops as soon as reg(P1) errors are
+** In other words, the analysis stops as soon as reg(P1) errors are
** seen. Reg(P1) is updated with the number of errors remaining.
**
** The root page numbers of all tables in the database are integer
@@ -62845,13 +57323,13 @@ case OP_RowSetTest: { /* jump, in1, in3 */
/* Opcode: Program P1 P2 P3 P4 *
**
-** Execute the trigger program passed as P4 (type P4_SUBPROGRAM).
+** Execute the trigger program passed as P4 (type P4_SUBPROGRAM).
**
-** P1 contains the address of the memory cell that contains the first memory
-** cell in an array of values used as arguments to the sub-program. P2
-** contains the address to jump to if the sub-program throws an IGNORE
-** exception using the RAISE() function. Register P3 contains the address
-** of a memory cell in this (the parent) VM that is used to allocate the
+** P1 contains the address of the memory cell that contains the first memory
+** cell in an array of values used as arguments to the sub-program. P2
+** contains the address to jump to if the sub-program throws an IGNORE
+** exception using the RAISE() function. Register P3 contains the address
+** of a memory cell in this (the parent) VM that is used to allocate the
** memory required by the sub-vdbe at runtime.
**
** P4 is a pointer to the VM containing the trigger program.
@@ -62960,10 +57438,10 @@ case OP_Program: { /* jump */
/* Opcode: Param P1 P2 * * *
**
-** This opcode is only ever present in sub-programs called via the
-** OP_Program instruction. Copy a value currently stored in a memory
-** cell of the calling (parent) frame to cell P2 in the current frames
-** address space. This is used by trigger programs to access the new.*
+** This opcode is only ever present in sub-programs called via the
+** OP_Program instruction. Copy a value currently stored in a memory
+** cell of the calling (parent) frame to cell P2 in the current frames
+** address space. This is used by trigger programs to access the new.*
** and old.* values.
**
** The address of the cell in the parent frame is determined by adding
@@ -62987,8 +57465,8 @@ case OP_Param: { /* out2-prerelease */
/* Opcode: FkCounter P1 P2 * * *
**
** Increment a "constraint counter" by P2 (P2 may be negative or positive).
-** If P1 is non-zero, the database constraint counter is incremented
-** (deferred foreign key constraints). Otherwise, if P1 is zero, the
+** If P1 is non-zero, the database constraint counter is incremented
+** (deferred foreign key constraints). Otherwise, if P1 is zero, the
** statement counter is incremented (immediate foreign key constraints).
*/
case OP_FkCounter: {
@@ -63003,7 +57481,7 @@ case OP_FkCounter: {
/* Opcode: FkIfZero P1 P2 * * *
**
** This opcode tests if a foreign key constraint-counter is currently zero.
-** If so, jump to instruction P2. Otherwise, fall through to the next
+** If so, jump to instruction P2. Otherwise, fall through to the next
** instruction.
**
** If P1 is non-zero, then the jump is taken if the database constraint-counter
@@ -63026,7 +57504,7 @@ case OP_FkIfZero: { /* jump */
**
** P1 is a register in the root frame of this VM (the root frame is
** different from the current frame if this instruction is being executed
-** within a sub-program). Set the value of register P1 to the maximum of
+** within a sub-program). Set the value of register P1 to the maximum of
** its current value and the value in register P2.
**
** This instruction throws an error if the memory cell is not initially
@@ -63071,7 +57549,7 @@ case OP_IfPos: { /* jump, in1 */
/* Opcode: IfNeg P1 P2 * * *
**
-** If the value of register P1 is less than zero, jump to P2.
+** If the value of register P1 is less than zero, jump to P2.
**
** It is illegal to use this instruction on a register that does
** not contain an integer. An assertion fault will result if you try.
@@ -63088,7 +57566,7 @@ case OP_IfNeg: { /* jump, in1 */
/* Opcode: IfZero P1 P2 P3 * *
**
** The register P1 must contain an integer. Add literal P3 to the
-** value in register P1. If the result is exactly 0, jump to P2.
+** value in register P1. If the result is exactly 0, jump to P2.
**
** It is illegal to use this instruction on a register that does
** not contain an integer. An assertion fault will result if you try.
@@ -63189,149 +57667,6 @@ case OP_AggFinal: {
break;
}
-#ifndef SQLITE_OMIT_WAL
-/* Opcode: Checkpoint P1 * * * *
-**
-** Checkpoint database P1. This is a no-op if P1 is not currently in
-** WAL mode.
-*/
-case OP_Checkpoint: {
- rc = sqlite3Checkpoint(db, pOp->p1);
- break;
-};
-#endif
-
-/* Opcode: JournalMode P1 P2 P3 * P5
-**
-** Change the journal mode of database P1 to P3. P3 must be one of the
-** PAGER_JOURNALMODE_XXX values. If changing between the various rollback
-** modes (delete, truncate, persist, off and memory), this is a simple
-** operation. No IO is required.
-**
-** If changing into or out of WAL mode the procedure is more complicated.
-**
-** Write a string containing the final journal-mode to register P2.
-**
-** If an attempt to change in to or out of WAL mode fails because another
-** connection also has the same database open, then an SQLITE_BUSY error
-** is raised if P5==0, or of P5!=0 the journal mode changed is skipped
-** without signaling the error.
-*/
-case OP_JournalMode: { /* out2-prerelease */
-#if 0 /* local variables moved into u.cd */
- Btree *pBt; /* Btree to change journal mode of */
- Pager *pPager; /* Pager associated with pBt */
- int eNew; /* New journal mode */
- int eOld; /* The old journal mode */
- const sqlite3_vfs *pVfs; /* The VFS of pPager */
- const char *zFilename; /* Name of database file for pPager */
-#endif /* local variables moved into u.cd */
-
- u.cd.eNew = pOp->p3;
- assert( u.cd.eNew==PAGER_JOURNALMODE_DELETE
- || u.cd.eNew==PAGER_JOURNALMODE_TRUNCATE
- || u.cd.eNew==PAGER_JOURNALMODE_PERSIST
- || u.cd.eNew==PAGER_JOURNALMODE_OFF
- || u.cd.eNew==PAGER_JOURNALMODE_MEMORY
- || u.cd.eNew==PAGER_JOURNALMODE_WAL
- || u.cd.eNew==PAGER_JOURNALMODE_QUERY
- );
- assert( pOp->p1>=0 && pOp->p1<db->nDb );
-
- /* This opcode is used in two places: PRAGMA journal_mode and ATTACH.
- ** In PRAGMA journal_mode, the sqlite3VdbeUsesBtree() routine is called
- ** when the statment is prepared and so p->aMutex.nMutex>0. All mutexes
- ** are already acquired. But when used in ATTACH, sqlite3VdbeUsesBtree()
- ** is not called when the statement is prepared because it requires the
- ** iDb index of the database as a parameter, and the database has not
- ** yet been attached so that index is unavailable. We have to wait
- ** until runtime (now) to get the mutex on the newly attached database.
- ** No other mutexes are required by the ATTACH command so this is safe
- ** to do.
- */
- assert( (p->btreeMask & (1<<pOp->p1))!=0 || p->aMutex.nMutex==0 );
- if( p->aMutex.nMutex==0 ){
- /* This occurs right after ATTACH. Get a mutex on the newly ATTACHed
- ** database. */
- sqlite3VdbeUsesBtree(p, pOp->p1);
- sqlite3VdbeMutexArrayEnter(p);
- }
-
- u.cd.pBt = db->aDb[pOp->p1].pBt;
- u.cd.pPager = sqlite3BtreePager(u.cd.pBt);
-
-#ifndef SQLITE_OMIT_WAL
- u.cd.zFilename = sqlite3PagerFilename(u.cd.pPager);
- u.cd.pVfs = sqlite3PagerVfs(u.cd.pPager);
-
- /* Do not allow a transition to journal_mode=WAL for a database
- ** in temporary storage or if the VFS does not support xShmOpen.
- */
- if( u.cd.eNew==PAGER_JOURNALMODE_WAL
- && (u.cd.zFilename[0]==0 /* Temp file */
- || !sqlite3PagerWalSupported(u.cd.pPager)) /* No xShmOpen support */
- ){
- u.cd.eNew = PAGER_JOURNALMODE_QUERY;
- }
-
- if( u.cd.eNew!=PAGER_JOURNALMODE_QUERY ){
- u.cd.eOld = sqlite3PagerJournalMode(u.cd.pPager, PAGER_JOURNALMODE_QUERY);
- if( (u.cd.eNew!=u.cd.eOld)
- && (u.cd.eOld==PAGER_JOURNALMODE_WAL || u.cd.eNew==PAGER_JOURNALMODE_WAL)
- ){
- if( !db->autoCommit || db->activeVdbeCnt>1 ){
- rc = SQLITE_ERROR;
- sqlite3SetString(&p->zErrMsg, db,
- "cannot change %s wal mode from within a transaction",
- (u.cd.eNew==PAGER_JOURNALMODE_WAL ? "into" : "out of")
- );
- break;
- }else{
-
- if( u.cd.eOld==PAGER_JOURNALMODE_WAL ){
- /* If leaving WAL mode, close the log file. If successful, the call
- ** to PagerCloseWal() checkpoints and deletes the write-ahead-log
- ** file. An EXCLUSIVE lock may still be held on the database file
- ** after a successful return.
- */
- rc = sqlite3PagerCloseWal(u.cd.pPager);
- if( rc==SQLITE_OK ){
- sqlite3PagerJournalMode(u.cd.pPager, u.cd.eNew);
- }else if( rc==SQLITE_BUSY && pOp->p5==0 ){
- goto abort_due_to_error;
- }
- }else{
- sqlite3PagerJournalMode(u.cd.pPager, PAGER_JOURNALMODE_DELETE);
- rc = SQLITE_OK;
- }
-
- /* Open a transaction on the database file. Regardless of the journal
- ** mode, this transaction always uses a rollback journal.
- */
- assert( sqlite3BtreeIsInTrans(u.cd.pBt)==0 );
- if( rc==SQLITE_OK ){
- rc = sqlite3BtreeSetVersion(u.cd.pBt,
- (u.cd.eNew==PAGER_JOURNALMODE_WAL ? 2 : 1));
- if( rc==SQLITE_BUSY && pOp->p5==0 ) goto abort_due_to_error;
- }
- if( rc==SQLITE_BUSY ){
- u.cd.eNew = PAGER_JOURNALMODE_QUERY;
- rc = SQLITE_OK;
- }
- }
- }
- }
-#endif /* ifndef SQLITE_OMIT_WAL */
-
- u.cd.eNew = sqlite3PagerJournalMode(u.cd.pPager, u.cd.eNew);
- pOut = &aMem[pOp->p2];
- pOut->flags = MEM_Str|MEM_Static|MEM_Term;
- pOut->z = (char *)sqlite3JournalModename(u.cd.eNew);
- pOut->n = sqlite3Strlen30(pOut->z);
- pOut->enc = SQLITE_UTF8;
- sqlite3VdbeChangeEncoding(pOut, encoding);
- break;
-};
#if !defined(SQLITE_OMIT_VACUUM) && !defined(SQLITE_OMIT_ATTACH)
/* Opcode: Vacuum * * * * *
@@ -63354,14 +57689,14 @@ case OP_Vacuum: {
** P2. Otherwise, fall through to the next instruction.
*/
case OP_IncrVacuum: { /* jump */
-#if 0 /* local variables moved into u.ce */
+#if 0 /* local variables moved into u.cd */
Btree *pBt;
-#endif /* local variables moved into u.ce */
+#endif /* local variables moved into u.cd */
assert( pOp->p1>=0 && pOp->p1<db->nDb );
assert( (p->btreeMask & (1<<pOp->p1))!=0 );
- u.ce.pBt = db->aDb[pOp->p1].pBt;
- rc = sqlite3BtreeIncrVacuum(u.ce.pBt);
+ u.cd.pBt = db->aDb[pOp->p1].pBt;
+ rc = sqlite3BtreeIncrVacuum(u.cd.pBt);
if( rc==SQLITE_DONE ){
pc = pOp->p2 - 1;
rc = SQLITE_OK;
@@ -63373,11 +57708,11 @@ case OP_IncrVacuum: { /* jump */
/* Opcode: Expire P1 * * * *
**
** Cause precompiled statements to become expired. An expired statement
-** fails with an error code of SQLITE_SCHEMA if it is ever executed
+** fails with an error code of SQLITE_SCHEMA if it is ever executed
** (via sqlite3_step()).
-**
+**
** If P1 is 0, then all SQL statements become expired. If P1 is non-zero,
-** then only the currently executing statement is affected.
+** then only the currently executing statement is affected.
*/
case OP_Expire: {
if( !pOp->p1 ){
@@ -63392,7 +57727,7 @@ case OP_Expire: {
/* Opcode: TableLock P1 P2 P3 P4 *
**
** Obtain a lock on a particular table. This instruction is only used when
-** the shared-cache feature is enabled.
+** the shared-cache feature is enabled.
**
** P1 is the index of the database in sqlite3.aDb[] of the database
** on which the lock is acquired. A readlock is obtained if P3==0 or
@@ -63406,7 +57741,7 @@ case OP_Expire: {
case OP_TableLock: {
u8 isWriteLock = (u8)pOp->p3;
if( isWriteLock || 0==(db->flags&SQLITE_ReadUncommitted) ){
- int p1 = pOp->p1;
+ int p1 = pOp->p1;
assert( p1>=0 && p1<db->nDb );
assert( (p->btreeMask & (1<<p1))!=0 );
assert( isWriteLock==0 || isWriteLock==1 );
@@ -63423,7 +57758,7 @@ case OP_TableLock: {
#ifndef SQLITE_OMIT_VIRTUALTABLE
/* Opcode: VBegin * * * P4 *
**
-** P4 may be a pointer to an sqlite3_vtab structure. If so, call the
+** P4 may be a pointer to an sqlite3_vtab structure. If so, call the
** xBegin method for that table.
**
** Also, whether or not P4 is set, check that this is not being called from
@@ -63431,15 +57766,15 @@ case OP_TableLock: {
** code will be set to SQLITE_LOCKED.
*/
case OP_VBegin: {
-#if 0 /* local variables moved into u.cf */
+#if 0 /* local variables moved into u.ce */
VTable *pVTab;
-#endif /* local variables moved into u.cf */
- u.cf.pVTab = pOp->p4.pVtab;
- rc = sqlite3VtabBegin(db, u.cf.pVTab);
- if( u.cf.pVTab ){
+#endif /* local variables moved into u.ce */
+ u.ce.pVTab = pOp->p4.pVtab;
+ rc = sqlite3VtabBegin(db, u.ce.pVTab);
+ if( u.ce.pVTab ){
sqlite3DbFree(db, p->zErrMsg);
- p->zErrMsg = u.cf.pVTab->pVtab->zErrMsg;
- u.cf.pVTab->pVtab->zErrMsg = 0;
+ p->zErrMsg = u.ce.pVTab->pVtab->zErrMsg;
+ u.ce.pVTab->pVtab->zErrMsg = 0;
}
break;
}
@@ -63479,34 +57814,34 @@ case OP_VDestroy: {
** table and stores that cursor in P1.
*/
case OP_VOpen: {
-#if 0 /* local variables moved into u.cg */
+#if 0 /* local variables moved into u.cf */
VdbeCursor *pCur;
sqlite3_vtab_cursor *pVtabCursor;
sqlite3_vtab *pVtab;
sqlite3_module *pModule;
-#endif /* local variables moved into u.cg */
+#endif /* local variables moved into u.cf */
- u.cg.pCur = 0;
- u.cg.pVtabCursor = 0;
- u.cg.pVtab = pOp->p4.pVtab->pVtab;
- u.cg.pModule = (sqlite3_module *)u.cg.pVtab->pModule;
- assert(u.cg.pVtab && u.cg.pModule);
- rc = u.cg.pModule->xOpen(u.cg.pVtab, &u.cg.pVtabCursor);
+ u.cf.pCur = 0;
+ u.cf.pVtabCursor = 0;
+ u.cf.pVtab = pOp->p4.pVtab->pVtab;
+ u.cf.pModule = (sqlite3_module *)u.cf.pVtab->pModule;
+ assert(u.cf.pVtab && u.cf.pModule);
+ rc = u.cf.pModule->xOpen(u.cf.pVtab, &u.cf.pVtabCursor);
sqlite3DbFree(db, p->zErrMsg);
- p->zErrMsg = u.cg.pVtab->zErrMsg;
- u.cg.pVtab->zErrMsg = 0;
+ p->zErrMsg = u.cf.pVtab->zErrMsg;
+ u.cf.pVtab->zErrMsg = 0;
if( SQLITE_OK==rc ){
/* Initialize sqlite3_vtab_cursor base class */
- u.cg.pVtabCursor->pVtab = u.cg.pVtab;
+ u.cf.pVtabCursor->pVtab = u.cf.pVtab;
/* Initialise vdbe cursor object */
- u.cg.pCur = allocateCursor(p, pOp->p1, 0, -1, 0);
- if( u.cg.pCur ){
- u.cg.pCur->pVtabCursor = u.cg.pVtabCursor;
- u.cg.pCur->pModule = u.cg.pVtabCursor->pVtab->pModule;
+ u.cf.pCur = allocateCursor(p, pOp->p1, 0, -1, 0);
+ if( u.cf.pCur ){
+ u.cf.pCur->pVtabCursor = u.cf.pVtabCursor;
+ u.cf.pCur->pModule = u.cf.pVtabCursor->pVtab->pModule;
}else{
db->mallocFailed = 1;
- u.cg.pModule->xClose(u.cg.pVtabCursor);
+ u.cf.pModule->xClose(u.cf.pVtabCursor);
}
}
break;
@@ -63533,7 +57868,7 @@ case OP_VOpen: {
** A jump is made to P2 if the result set after filtering would be empty.
*/
case OP_VFilter: { /* jump */
-#if 0 /* local variables moved into u.ch */
+#if 0 /* local variables moved into u.cg */
int nArg;
int iQuery;
const sqlite3_module *pModule;
@@ -63545,46 +57880,46 @@ case OP_VFilter: { /* jump */
int res;
int i;
Mem **apArg;
-#endif /* local variables moved into u.ch */
+#endif /* local variables moved into u.cg */
- u.ch.pQuery = &aMem[pOp->p3];
- u.ch.pArgc = &u.ch.pQuery[1];
- u.ch.pCur = p->apCsr[pOp->p1];
- REGISTER_TRACE(pOp->p3, u.ch.pQuery);
- assert( u.ch.pCur->pVtabCursor );
- u.ch.pVtabCursor = u.ch.pCur->pVtabCursor;
- u.ch.pVtab = u.ch.pVtabCursor->pVtab;
- u.ch.pModule = u.ch.pVtab->pModule;
+ u.cg.pQuery = &aMem[pOp->p3];
+ u.cg.pArgc = &u.cg.pQuery[1];
+ u.cg.pCur = p->apCsr[pOp->p1];
+ REGISTER_TRACE(pOp->p3, u.cg.pQuery);
+ assert( u.cg.pCur->pVtabCursor );
+ u.cg.pVtabCursor = u.cg.pCur->pVtabCursor;
+ u.cg.pVtab = u.cg.pVtabCursor->pVtab;
+ u.cg.pModule = u.cg.pVtab->pModule;
/* Grab the index number and argc parameters */
- assert( (u.ch.pQuery->flags&MEM_Int)!=0 && u.ch.pArgc->flags==MEM_Int );
- u.ch.nArg = (int)u.ch.pArgc->u.i;
- u.ch.iQuery = (int)u.ch.pQuery->u.i;
+ assert( (u.cg.pQuery->flags&MEM_Int)!=0 && u.cg.pArgc->flags==MEM_Int );
+ u.cg.nArg = (int)u.cg.pArgc->u.i;
+ u.cg.iQuery = (int)u.cg.pQuery->u.i;
/* Invoke the xFilter method */
{
- u.ch.res = 0;
- u.ch.apArg = p->apArg;
- for(u.ch.i = 0; u.ch.i<u.ch.nArg; u.ch.i++){
- u.ch.apArg[u.ch.i] = &u.ch.pArgc[u.ch.i+1];
- sqlite3VdbeMemStoreType(u.ch.apArg[u.ch.i]);
+ u.cg.res = 0;
+ u.cg.apArg = p->apArg;
+ for(u.cg.i = 0; u.cg.i<u.cg.nArg; u.cg.i++){
+ u.cg.apArg[u.cg.i] = &u.cg.pArgc[u.cg.i+1];
+ sqlite3VdbeMemStoreType(u.cg.apArg[u.cg.i]);
}
p->inVtabMethod = 1;
- rc = u.ch.pModule->xFilter(u.ch.pVtabCursor, u.ch.iQuery, pOp->p4.z, u.ch.nArg, u.ch.apArg);
+ rc = u.cg.pModule->xFilter(u.cg.pVtabCursor, u.cg.iQuery, pOp->p4.z, u.cg.nArg, u.cg.apArg);
p->inVtabMethod = 0;
sqlite3DbFree(db, p->zErrMsg);
- p->zErrMsg = u.ch.pVtab->zErrMsg;
- u.ch.pVtab->zErrMsg = 0;
+ p->zErrMsg = u.cg.pVtab->zErrMsg;
+ u.cg.pVtab->zErrMsg = 0;
if( rc==SQLITE_OK ){
- u.ch.res = u.ch.pModule->xEof(u.ch.pVtabCursor);
+ u.cg.res = u.cg.pModule->xEof(u.cg.pVtabCursor);
}
- if( u.ch.res ){
+ if( u.cg.res ){
pc = pOp->p2 - 1;
}
}
- u.ch.pCur->nullRow = 0;
+ u.cg.pCur->nullRow = 0;
break;
}
@@ -63594,56 +57929,56 @@ case OP_VFilter: { /* jump */
/* Opcode: VColumn P1 P2 P3 * *
**
** Store the value of the P2-th column of
-** the row of the virtual-table that the
+** the row of the virtual-table that the
** P1 cursor is pointing to into register P3.
*/
case OP_VColumn: {
-#if 0 /* local variables moved into u.ci */
+#if 0 /* local variables moved into u.ch */
sqlite3_vtab *pVtab;
const sqlite3_module *pModule;
Mem *pDest;
sqlite3_context sContext;
-#endif /* local variables moved into u.ci */
+#endif /* local variables moved into u.ch */
VdbeCursor *pCur = p->apCsr[pOp->p1];
assert( pCur->pVtabCursor );
assert( pOp->p3>0 && pOp->p3<=p->nMem );
- u.ci.pDest = &aMem[pOp->p3];
+ u.ch.pDest = &aMem[pOp->p3];
if( pCur->nullRow ){
- sqlite3VdbeMemSetNull(u.ci.pDest);
+ sqlite3VdbeMemSetNull(u.ch.pDest);
break;
}
- u.ci.pVtab = pCur->pVtabCursor->pVtab;
- u.ci.pModule = u.ci.pVtab->pModule;
- assert( u.ci.pModule->xColumn );
- memset(&u.ci.sContext, 0, sizeof(u.ci.sContext));
+ u.ch.pVtab = pCur->pVtabCursor->pVtab;
+ u.ch.pModule = u.ch.pVtab->pModule;
+ assert( u.ch.pModule->xColumn );
+ memset(&u.ch.sContext, 0, sizeof(u.ch.sContext));
/* The output cell may already have a buffer allocated. Move
- ** the current contents to u.ci.sContext.s so in case the user-function
+ ** the current contents to u.ch.sContext.s so in case the user-function
** can use the already allocated buffer instead of allocating a
** new one.
*/
- sqlite3VdbeMemMove(&u.ci.sContext.s, u.ci.pDest);
- MemSetTypeFlag(&u.ci.sContext.s, MEM_Null);
+ sqlite3VdbeMemMove(&u.ch.sContext.s, u.ch.pDest);
+ MemSetTypeFlag(&u.ch.sContext.s, MEM_Null);
- rc = u.ci.pModule->xColumn(pCur->pVtabCursor, &u.ci.sContext, pOp->p2);
+ rc = u.ch.pModule->xColumn(pCur->pVtabCursor, &u.ch.sContext, pOp->p2);
sqlite3DbFree(db, p->zErrMsg);
- p->zErrMsg = u.ci.pVtab->zErrMsg;
- u.ci.pVtab->zErrMsg = 0;
- if( u.ci.sContext.isError ){
- rc = u.ci.sContext.isError;
+ p->zErrMsg = u.ch.pVtab->zErrMsg;
+ u.ch.pVtab->zErrMsg = 0;
+ if( u.ch.sContext.isError ){
+ rc = u.ch.sContext.isError;
}
/* Copy the result of the function to the P3 register. We
** do this regardless of whether or not an error occurred to ensure any
- ** dynamic allocation in u.ci.sContext.s (a Mem struct) is released.
+ ** dynamic allocation in u.ch.sContext.s (a Mem struct) is released.
*/
- sqlite3VdbeChangeEncoding(&u.ci.sContext.s, encoding);
- sqlite3VdbeMemMove(u.ci.pDest, &u.ci.sContext.s);
- REGISTER_TRACE(pOp->p3, u.ci.pDest);
- UPDATE_MAX_BLOBSIZE(u.ci.pDest);
+ sqlite3VdbeChangeEncoding(&u.ch.sContext.s, encoding);
+ sqlite3VdbeMemMove(u.ch.pDest, &u.ch.sContext.s);
+ REGISTER_TRACE(pOp->p3, u.ch.pDest);
+ UPDATE_MAX_BLOBSIZE(u.ch.pDest);
- if( sqlite3VdbeMemTooBig(u.ci.pDest) ){
+ if( sqlite3VdbeMemTooBig(u.ch.pDest) ){
goto too_big;
}
break;
@@ -63658,22 +57993,22 @@ case OP_VColumn: {
** the end of its result set, then fall through to the next instruction.
*/
case OP_VNext: { /* jump */
-#if 0 /* local variables moved into u.cj */
+#if 0 /* local variables moved into u.ci */
sqlite3_vtab *pVtab;
const sqlite3_module *pModule;
int res;
VdbeCursor *pCur;
-#endif /* local variables moved into u.cj */
+#endif /* local variables moved into u.ci */
- u.cj.res = 0;
- u.cj.pCur = p->apCsr[pOp->p1];
- assert( u.cj.pCur->pVtabCursor );
- if( u.cj.pCur->nullRow ){
+ u.ci.res = 0;
+ u.ci.pCur = p->apCsr[pOp->p1];
+ assert( u.ci.pCur->pVtabCursor );
+ if( u.ci.pCur->nullRow ){
break;
}
- u.cj.pVtab = u.cj.pCur->pVtabCursor->pVtab;
- u.cj.pModule = u.cj.pVtab->pModule;
- assert( u.cj.pModule->xNext );
+ u.ci.pVtab = u.ci.pCur->pVtabCursor->pVtab;
+ u.ci.pModule = u.ci.pVtab->pModule;
+ assert( u.ci.pModule->xNext );
/* Invoke the xNext() method of the module. There is no way for the
** underlying implementation to return an error if one occurs during
@@ -63682,16 +58017,16 @@ case OP_VNext: { /* jump */
** some other method is next invoked on the save virtual table cursor.
*/
p->inVtabMethod = 1;
- rc = u.cj.pModule->xNext(u.cj.pCur->pVtabCursor);
+ rc = u.ci.pModule->xNext(u.ci.pCur->pVtabCursor);
p->inVtabMethod = 0;
sqlite3DbFree(db, p->zErrMsg);
- p->zErrMsg = u.cj.pVtab->zErrMsg;
- u.cj.pVtab->zErrMsg = 0;
+ p->zErrMsg = u.ci.pVtab->zErrMsg;
+ u.ci.pVtab->zErrMsg = 0;
if( rc==SQLITE_OK ){
- u.cj.res = u.cj.pModule->xEof(u.cj.pCur->pVtabCursor);
+ u.ci.res = u.ci.pModule->xEof(u.ci.pCur->pVtabCursor);
}
- if( !u.cj.res ){
+ if( !u.ci.res ){
/* If there is data, jump to P2 */
pc = pOp->p2 - 1;
}
@@ -63707,20 +58042,20 @@ case OP_VNext: { /* jump */
** in register P1 is passed as the zName argument to the xRename method.
*/
case OP_VRename: {
-#if 0 /* local variables moved into u.ck */
+#if 0 /* local variables moved into u.cj */
sqlite3_vtab *pVtab;
Mem *pName;
-#endif /* local variables moved into u.ck */
+#endif /* local variables moved into u.cj */
- u.ck.pVtab = pOp->p4.pVtab->pVtab;
- u.ck.pName = &aMem[pOp->p1];
- assert( u.ck.pVtab->pModule->xRename );
- REGISTER_TRACE(pOp->p1, u.ck.pName);
- assert( u.ck.pName->flags & MEM_Str );
- rc = u.ck.pVtab->pModule->xRename(u.ck.pVtab, u.ck.pName->z);
+ u.cj.pVtab = pOp->p4.pVtab->pVtab;
+ u.cj.pName = &aMem[pOp->p1];
+ assert( u.cj.pVtab->pModule->xRename );
+ REGISTER_TRACE(pOp->p1, u.cj.pName);
+ assert( u.cj.pName->flags & MEM_Str );
+ rc = u.cj.pVtab->pModule->xRename(u.cj.pVtab, u.cj.pName->z);
sqlite3DbFree(db, p->zErrMsg);
- p->zErrMsg = u.ck.pVtab->zErrMsg;
- u.ck.pVtab->zErrMsg = 0;
+ p->zErrMsg = u.cj.pVtab->zErrMsg;
+ u.cj.pVtab->zErrMsg = 0;
break;
}
@@ -63731,27 +58066,27 @@ case OP_VRename: {
**
** P4 is a pointer to a virtual table object, an sqlite3_vtab structure.
** This opcode invokes the corresponding xUpdate method. P2 values
-** are contiguous memory cells starting at P3 to pass to the xUpdate
-** invocation. The value in register (P3+P2-1) corresponds to the
+** are contiguous memory cells starting at P3 to pass to the xUpdate
+** invocation. The value in register (P3+P2-1) corresponds to the
** p2th element of the argv array passed to xUpdate.
**
** The xUpdate method will do a DELETE or an INSERT or both.
** The argv[0] element (which corresponds to memory cell P3)
-** is the rowid of a row to delete. If argv[0] is NULL then no
-** deletion occurs. The argv[1] element is the rowid of the new
-** row. This can be NULL to have the virtual table select the new
-** rowid for itself. The subsequent elements in the array are
+** is the rowid of a row to delete. If argv[0] is NULL then no
+** deletion occurs. The argv[1] element is the rowid of the new
+** row. This can be NULL to have the virtual table select the new
+** rowid for itself. The subsequent elements in the array are
** the values of columns in the new row.
**
** If P2==1 then no insert is performed. argv[0] is the rowid of
** a row to delete.
**
** P1 is a boolean flag. If it is set to true and the xUpdate call
-** is successful, then the value returned by sqlite3_last_insert_rowid()
+** is successful, then the value returned by sqlite3_last_insert_rowid()
** is set to the value of the rowid for the row just inserted.
*/
case OP_VUpdate: {
-#if 0 /* local variables moved into u.cl */
+#if 0 /* local variables moved into u.ck */
sqlite3_vtab *pVtab;
sqlite3_module *pModule;
int nArg;
@@ -63759,27 +58094,27 @@ case OP_VUpdate: {
sqlite_int64 rowid;
Mem **apArg;
Mem *pX;
-#endif /* local variables moved into u.cl */
+#endif /* local variables moved into u.ck */
- u.cl.pVtab = pOp->p4.pVtab->pVtab;
- u.cl.pModule = (sqlite3_module *)u.cl.pVtab->pModule;
- u.cl.nArg = pOp->p2;
+ u.ck.pVtab = pOp->p4.pVtab->pVtab;
+ u.ck.pModule = (sqlite3_module *)u.ck.pVtab->pModule;
+ u.ck.nArg = pOp->p2;
assert( pOp->p4type==P4_VTAB );
- if( ALWAYS(u.cl.pModule->xUpdate) ){
- u.cl.apArg = p->apArg;
- u.cl.pX = &aMem[pOp->p3];
- for(u.cl.i=0; u.cl.i<u.cl.nArg; u.cl.i++){
- sqlite3VdbeMemStoreType(u.cl.pX);
- u.cl.apArg[u.cl.i] = u.cl.pX;
- u.cl.pX++;
- }
- rc = u.cl.pModule->xUpdate(u.cl.pVtab, u.cl.nArg, u.cl.apArg, &u.cl.rowid);
+ if( ALWAYS(u.ck.pModule->xUpdate) ){
+ u.ck.apArg = p->apArg;
+ u.ck.pX = &aMem[pOp->p3];
+ for(u.ck.i=0; u.ck.i<u.ck.nArg; u.ck.i++){
+ sqlite3VdbeMemStoreType(u.ck.pX);
+ u.ck.apArg[u.ck.i] = u.ck.pX;
+ u.ck.pX++;
+ }
+ rc = u.ck.pModule->xUpdate(u.ck.pVtab, u.ck.nArg, u.ck.apArg, &u.ck.rowid);
sqlite3DbFree(db, p->zErrMsg);
- p->zErrMsg = u.cl.pVtab->zErrMsg;
- u.cl.pVtab->zErrMsg = 0;
+ p->zErrMsg = u.ck.pVtab->zErrMsg;
+ u.ck.pVtab->zErrMsg = 0;
if( rc==SQLITE_OK && pOp->p1 ){
- assert( u.cl.nArg>1 && u.cl.apArg[0] && (u.cl.apArg[0]->flags&MEM_Null) );
- db->lastRowid = u.cl.rowid;
+ assert( u.ck.nArg>1 && u.ck.apArg[0] && (u.ck.apArg[0]->flags&MEM_Null) );
+ db->lastRowid = u.ck.rowid;
}
p->nChange++;
}
@@ -63793,7 +58128,21 @@ case OP_VUpdate: {
** Write the current number of pages in database P1 to memory cell P2.
*/
case OP_Pagecount: { /* out2-prerelease */
- pOut->u.i = sqlite3BtreeLastPage(db->aDb[pOp->p1].pBt);
+#if 0 /* local variables moved into u.cl */
+ int p1;
+ int nPage;
+ Pager *pPager;
+#endif /* local variables moved into u.cl */
+
+ u.cl.p1 = pOp->p1;
+ u.cl.pPager = sqlite3BtreePager(db->aDb[u.cl.p1].pBt);
+ rc = sqlite3PagerPagecount(u.cl.pPager, &u.cl.nPage);
+ /* OP_Pagecount is always called from within a read transaction. The
+ ** page count has already been successfully read and cached. So the
+ ** sqlite3PagerPagecount() call above cannot fail. */
+ if( ALWAYS(rc==SQLITE_OK) ){
+ pOut->u.i = u.cl.nPage;
+ }
break;
}
#endif
@@ -63839,7 +58188,6 @@ case OP_Trace: {
** the same as a no-op. This opcodesnever appears in a real VM program.
*/
default: { /* This is really OP_Noop and OP_Explain */
- assert( pOp->opcode==OP_Noop || pOp->opcode==OP_Explain );
break;
}
@@ -63891,9 +58239,7 @@ default: { /* This is really OP_Noop and OP_Explain */
vdbe_error_halt:
assert( rc );
p->rc = rc;
- testcase( sqlite3GlobalConfig.xLog!=0 );
- sqlite3_log(rc, "statement aborts at %d: [%s] %s",
- pc, p->zSql, p->zErrMsg);
+ sqlite3_log(rc, "prepared statement aborts at %d: [%s]", pc, p->zSql);
sqlite3VdbeHalt(p);
if( rc==SQLITE_IOERR_NOMEM ) db->mallocFailed = 1;
rc = SQLITE_ERROR;
@@ -63992,7 +58338,7 @@ SQLITE_API int sqlite3_blob_open(
int nAttempt = 0;
int iCol; /* Index of zColumn in row-record */
- /* This VDBE program seeks a btree cursor to the identified
+ /* This VDBE program seeks a btree cursor to the identified
** db/table/row entry. The reason for using a vdbe program instead
** of writing code to use the b-tree layer directly is that the
** vdbe program will take advantage of the various transaction,
@@ -64000,11 +58346,11 @@ SQLITE_API int sqlite3_blob_open(
**
** After seeking the cursor, the vdbe executes an OP_ResultRow.
** Code external to the Vdbe then "borrows" the b-tree cursor and
- ** uses it to implement the blob_read(), blob_write() and
+ ** uses it to implement the blob_read(), blob_write() and
** blob_bytes() functions.
**
** The sqlite3_blob_close() function finalizes the vdbe program,
- ** which closes the b-tree cursor and (possibly) commits the
+ ** which closes the b-tree cursor and (possibly) commits the
** transaction.
*/
static const VdbeOpList openBlob[] = {
@@ -64079,7 +58425,7 @@ SQLITE_API int sqlite3_blob_open(
}
/* If the value is being opened for writing, check that the
- ** column is not indexed, and that it is not part of a foreign key.
+ ** column is not indexed, and that it is not part of a foreign key.
** It is against the rules to open a column to which either of these
** descriptions applies for writing. */
if( flags ){
@@ -64089,7 +58435,7 @@ SQLITE_API int sqlite3_blob_open(
if( db->flags&SQLITE_ForeignKeys ){
/* Check that the column is not part of an FK child key definition. It
** is not necessary to check if it is part of a parent key, as parent
- ** key columns must be indexed. The check below will pick up this
+ ** key columns must be indexed. The check below will pick up this
** case. */
FKey *pFKey;
for(pFKey=pTab->pFKey; pFKey; pFKey=pFKey->pNextFrom){
@@ -64134,7 +58480,7 @@ SQLITE_API int sqlite3_blob_open(
sqlite3VdbeChangeP2(v, 1, pTab->pSchema->schema_cookie);
/* Make sure a mutex is held on the table to be accessed */
- sqlite3VdbeUsesBtree(v, iDb);
+ sqlite3VdbeUsesBtree(v, iDb);
/* Configure the OP_TableLock instruction */
sqlite3VdbeChangeP1(v, 2, iDb);
@@ -64142,7 +58488,7 @@ SQLITE_API int sqlite3_blob_open(
sqlite3VdbeChangeP3(v, 2, flags);
sqlite3VdbeChangeP4(v, 2, pTab->zName, P4_TRANSIENT);
- /* Remove either the OP_OpenWrite or OpenRead. Set the P2
+ /* Remove either the OP_OpenWrite or OpenRead. Set the P2
** parameter of the other to pTab->tnum. */
sqlite3VdbeChangeToNoop(v, 4 - flags, 1);
sqlite3VdbeChangeP2(v, 3 + flags, pTab->tnum);
@@ -64152,7 +58498,7 @@ SQLITE_API int sqlite3_blob_open(
** think that the table has one more column than it really
** does. An OP_Column to retrieve this imaginary column will
** always return an SQL NULL. This is useful because it means
- ** we can invoke OP_Column to fill in the vdbe cursors type
+ ** we can invoke OP_Column to fill in the vdbe cursors type
** and offset cache without causing any IO.
*/
sqlite3VdbeChangeP4(v, 3+flags, SQLITE_INT_TO_PTR(pTab->nCol+1),P4_INT32);
@@ -64161,7 +58507,7 @@ SQLITE_API int sqlite3_blob_open(
sqlite3VdbeMakeReady(v, 1, 1, 1, 0, 0, 0);
}
}
-
+
sqlite3BtreeLeaveAll(db);
if( db->mallocFailed ){
goto blob_open_out;
@@ -64253,10 +58599,10 @@ SQLITE_API int sqlite3_blob_close(sqlite3_blob *pBlob){
** Perform a read or write operation on a blob
*/
static int blobReadWrite(
- sqlite3_blob *pBlob,
- void *z,
- int n,
- int iOffset,
+ sqlite3_blob *pBlob,
+ void *z,
+ int n,
+ int iOffset,
int (*xCall)(BtCursor*, u32, u32, void*)
){
int rc;
@@ -64350,7 +58696,7 @@ SQLITE_API int sqlite3_blob_bytes(sqlite3_blob *pBlob){
** be used to service read() and write() requests. The actual file
** on disk is not created or populated until either:
**
-** 1) The in-memory representation grows too large for the allocated
+** 1) The in-memory representation grows too large for the allocated
** buffer, or
** 2) The sqlite3JournalCreate() function is called.
*/
@@ -64374,7 +58720,7 @@ struct JournalFile {
typedef struct JournalFile JournalFile;
/*
-** If it does not already exists, create and populate the on-disk file
+** If it does not already exists, create and populate the on-disk file
** for JournalFile p.
*/
static int createFile(JournalFile *p){
@@ -64514,7 +58860,7 @@ static struct sqlite3_io_methods JournalFileMethods = {
0 /* xDeviceCharacteristics */
};
-/*
+/*
** Open a journal file.
*/
SQLITE_PRIVATE int sqlite3JournalOpen(
@@ -64553,7 +58899,7 @@ SQLITE_PRIVATE int sqlite3JournalCreate(sqlite3_file *p){
return createFile((JournalFile *)p);
}
-/*
+/*
** Return the number of bytes required to store a JournalFile that uses vfs
** pVfs to create the underlying on-disk files.
*/
@@ -64651,7 +58997,7 @@ static int memjrnlRead(
if( p->readpoint.iOffset!=iOfst || iOfst==0 ){
sqlite3_int64 iOff = 0;
- for(pChunk=p->pFirst;
+ for(pChunk=p->pFirst;
ALWAYS(pChunk) && (iOff+JOURNAL_CHUNKSIZE)<=iOfst;
pChunk=pChunk->pNext
){
@@ -64761,10 +59107,11 @@ static int memjrnlClose(sqlite3_file *pJfd){
** exists purely as a contingency, in case some malfunction in some other
** part of SQLite causes Sync to be called by mistake.
*/
-static int memjrnlSync(sqlite3_file *NotUsed, int NotUsed2){
- UNUSED_PARAMETER2(NotUsed, NotUsed2);
- return SQLITE_OK;
-}
+static int memjrnlSync(sqlite3_file *NotUsed, int NotUsed2){ /*NO_TEST*/
+ UNUSED_PARAMETER2(NotUsed, NotUsed2); /*NO_TEST*/
+ assert( 0 ); /*NO_TEST*/
+ return SQLITE_OK; /*NO_TEST*/
+} /*NO_TEST*/
/*
** Query the size of the file in bytes.
@@ -64794,7 +59141,7 @@ static struct sqlite3_io_methods MemJournalMethods = {
0 /* xDeviceCharacteristics */
};
-/*
+/*
** Open a journal file.
*/
SQLITE_PRIVATE void sqlite3MemJournalOpen(sqlite3_file *pJfd){
@@ -64805,14 +59152,14 @@ SQLITE_PRIVATE void sqlite3MemJournalOpen(sqlite3_file *pJfd){
}
/*
-** Return true if the file-handle passed as an argument is
-** an in-memory journal
+** Return true if the file-handle passed as an argument is
+** an in-memory journal
*/
SQLITE_PRIVATE int sqlite3IsMemJournal(sqlite3_file *pJfd){
return pJfd->pMethods==&MemJournalMethods;
}
-/*
+/*
** Return the number of bytes required to store a MemJournal that uses vfs
** pVfs to create the underlying on-disk files.
*/
@@ -64912,7 +59259,7 @@ SQLITE_PRIVATE int sqlite3WalkSelectExpr(Walker *pWalker, Select *p){
** Walk the parse trees associated with all subqueries in the
** FROM clause of SELECT statement p. Do not invoke the select
** callback on p, but do invoke it on each FROM clause subquery
-** and on any subqueries further down in the tree. Return
+** and on any subqueries further down in the tree. Return
** WRC_Abort or WRC_Continue;
*/
SQLITE_PRIVATE int sqlite3WalkSelectFrom(Walker *pWalker, Select *p){
@@ -64929,7 +59276,7 @@ SQLITE_PRIVATE int sqlite3WalkSelectFrom(Walker *pWalker, Select *p){
}
}
return WRC_Continue;
-}
+}
/*
** Call sqlite3WalkExpr() for every expression in Select statement p.
@@ -64987,7 +59334,7 @@ SQLITE_PRIVATE int sqlite3WalkSelect(Walker *pWalker, Select *p){
**
** The reason for suppressing the TK_AS term when the expression is a simple
** column reference is so that the column reference will be recognized as
-** usable by indices within the WHERE clause processing logic.
+** usable by indices within the WHERE clause processing logic.
**
** Hack: The TK_AS operator is inhibited if zType[0]=='G'. This means
** that in a GROUP BY clause, the expression is evaluated twice. Hence:
@@ -65045,7 +59392,7 @@ static void resolveAlias(
pDup->flags |= EP_ExpCollate;
}
- /* Before calling sqlite3ExprDelete(), set the EP_Static flag. This
+ /* Before calling sqlite3ExprDelete(), set the EP_Static flag. This
** prevents ExprDelete() from deleting the Expr structure itself,
** allowing it to be repopulated by the memcpy() on the following line.
*/
@@ -65057,7 +59404,7 @@ static void resolveAlias(
/*
** Given the name of a column of the form X.Y.Z or Y.Z or just Z, look up
-** that name in the set of source tables in pSrcList and make the pExpr
+** that name in the set of source tables in pSrcList and make the pExpr
** expression node refer back to that source column. The following changes
** are made to pExpr:
**
@@ -65119,7 +59466,7 @@ static int lookupName(
Table *pTab;
int iDb;
Column *pCol;
-
+
pTab = pItem->pTab;
assert( pTab!=0 && pTab->zName!=0 );
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
@@ -65181,7 +59528,7 @@ static int lookupName(
}
#ifndef SQLITE_OMIT_TRIGGER
- /* If we have not already resolved the name, then maybe
+ /* If we have not already resolved the name, then maybe
** it is a new.* or old.* trigger argument reference
*/
if( zDb==0 && zTab!=0 && cnt==0 && pParse->pTriggerTab!=0 ){
@@ -65196,7 +59543,7 @@ static int lookupName(
pTab = pParse->pTriggerTab;
}
- if( pTab ){
+ if( pTab ){
int iCol;
pSchema = pTab->pSchema;
cntTab++;
@@ -65273,7 +59620,7 @@ static int lookupName(
assert( zTab==0 && zDb==0 );
goto lookupname_end;
}
- }
+ }
}
/* Advance to the next name context. The loop will exit when either
@@ -65360,7 +59707,7 @@ lookupname_end:
/*
** Allocate and return a pointer to an expression to load the column iCol
-** from datasource iSrc in SrcList pSrc.
+** from datasource iSrc datasource in SrcList pSrc.
*/
SQLITE_PRIVATE Expr *sqlite3CreateColumnExpr(sqlite3 *db, SrcList *pSrc, int iSrc, int iCol){
Expr *p = sqlite3ExprAlloc(db, TK_COLUMN, 0, 0);
@@ -65372,8 +59719,6 @@ SQLITE_PRIVATE Expr *sqlite3CreateColumnExpr(sqlite3 *db, SrcList *pSrc, int iSr
p->iColumn = -1;
}else{
p->iColumn = (ynVar)iCol;
- testcase( iCol==BMS );
- testcase( iCol==BMS-1 );
pItem->colUsed |= ((Bitmask)1)<<(iCol>=BMS ? BMS-1 : iCol);
}
ExprSetProperty(p, EP_Resolved);
@@ -65423,7 +59768,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
SrcList *pSrcList = pNC->pSrcList;
struct SrcList_item *pItem;
assert( pSrcList && pSrcList->nSrc==1 );
- pItem = pSrcList->a;
+ pItem = pSrcList->a;
pExpr->op = TK_COLUMN;
pExpr->pTab = pItem->pTab;
pExpr->iTable = pItem->iCursor;
@@ -65438,7 +59783,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
case TK_ID: {
return lookupName(pParse, 0, 0, pExpr->u.zToken, pNC, pExpr);
}
-
+
/* A table name and column name: ID.ID
** Or a database, table and column: ID.ID.ID
*/
@@ -65527,7 +59872,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
sqlite3WalkExprList(pWalker, pList);
if( is_agg ) pNC->allowAgg = 1;
/* FIX ME: Compute pExpr->affinity based on the expected return
- ** type of the function
+ ** type of the function
*/
return WRC_Prune;
}
@@ -65650,7 +59995,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) ){
return i+1;
}
}
@@ -65668,7 +60013,7 @@ static void resolveOutOfRangeError(
int i, /* The index (1-based) of the term out of range */
int mx /* Largest permissible value of i */
){
- sqlite3ErrorMsg(pParse,
+ sqlite3ErrorMsg(pParse,
"%r %s BY term out of range - should be "
"between 1 and %d", i, zType, mx);
}
@@ -65889,7 +60234,7 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
ExprList *pGroupBy; /* The GROUP BY clause */
Select *pLeftmost; /* Left-most of SELECT of a compound */
sqlite3 *db; /* Database connection */
-
+
assert( p!=0 );
if( p->selFlags & SF_Resolved ){
@@ -65929,14 +60274,14 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
sqlite3ResolveExprNames(&sNC, p->pOffset) ){
return WRC_Abort;
}
-
+
/* Set up the local name-context to pass to sqlite3ResolveExprNames() to
** resolve the result-set expression list.
*/
sNC.allowAgg = 1;
sNC.pSrcList = p->pSrc;
sNC.pNext = pOuterNC;
-
+
/* Resolve names in the result set. */
pEList = p->pEList;
assert( pEList!=0 );
@@ -65946,7 +60291,7 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
return WRC_Abort;
}
}
-
+
/* Recursively resolve names in all subqueries
*/
for(i=0; i<p->pSrc->nSrc; i++){
@@ -65959,8 +60304,8 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
if( pParse->nErr || db->mallocFailed ) return WRC_Abort;
}
}
-
- /* If there are no aggregate functions in the result-set, and no GROUP BY
+
+ /* If there are no aggregate functions in the result-set, and no GROUP BY
** expression, do not allow aggregates in any of the other expressions.
*/
assert( (p->selFlags & SF_Aggregate)==0 );
@@ -65970,14 +60315,14 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
}else{
sNC.allowAgg = 0;
}
-
+
/* If a HAVING clause is present, then there must be a GROUP BY clause.
*/
if( p->pHaving && !pGroupBy ){
sqlite3ErrorMsg(pParse, "a GROUP BY clause is required before HAVING");
return WRC_Abort;
}
-
+
/* Add the expression 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
@@ -65994,7 +60339,7 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
}
/* The ORDER BY and GROUP BY clauses may not refer to terms in
- ** outer queries
+ ** outer queries
*/
sNC.pNext = 0;
sNC.allowAgg = 1;
@@ -66010,13 +60355,13 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
if( db->mallocFailed ){
return WRC_Abort;
}
-
- /* Resolve the GROUP BY clause. At the same time, make sure
+
+ /* Resolve the GROUP BY clause. At the same time, make sure
** the GROUP BY clause does not contain aggregate functions.
*/
if( pGroupBy ){
struct ExprList_item *pItem;
-
+
if( resolveOrderGroupBy(&sNC, p, pGroupBy, "GROUP") || db->mallocFailed ){
return WRC_Abort;
}
@@ -66051,7 +60396,7 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
** checking on function usage and set a flag if any aggregate functions
** are seen.
**
-** To resolve table columns references we look for nodes (or subtrees) of the
+** To resolve table columns references we look for nodes (or subtrees) of the
** form X.Y.Z or Y.Z or just Z where
**
** X: The name of a database. Ex: "main" or "temp" or
@@ -66083,7 +60428,7 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
**
** SELECT a+b AS x, c+d AS y FROM t1 ORDER BY a+b;
**
-** Function calls are checked to make sure that the function is
+** Function calls are checked to make sure that the function is
** defined and that the correct number of arguments are specified.
** If the function is an aggregate function, then the pNC->hasAgg is
** set and the opcode is changed from TK_FUNCTION to TK_AGG_FUNCTION.
@@ -66093,7 +60438,7 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
** An error message is left in pParse if anything is amiss. The number
** if errors is returned.
*/
-SQLITE_PRIVATE int sqlite3ResolveExprNames(
+SQLITE_PRIVATE int sqlite3ResolveExprNames(
NameContext *pNC, /* Namespace to resolve expressions in. */
Expr *pExpr /* The expression to be analyzed. */
){
@@ -66180,7 +60525,7 @@ SQLITE_PRIVATE void sqlite3ResolveSelectNames(
** Return the 'affinity' of the expression pExpr if any.
**
** If pExpr is a column, a reference to a column via an 'AS' alias,
-** or a sub-select with a column as the return value, then the
+** or a sub-select with a column as the return value, then the
** affinity of that column is returned. Otherwise, 0x00 is returned,
** indicating no affinity for the expression.
**
@@ -66204,7 +60549,7 @@ SQLITE_PRIVATE char sqlite3ExprAffinity(Expr *pExpr){
return sqlite3AffinityType(pExpr->u.zToken);
}
#endif
- if( (op==TK_AGG_COLUMN || op==TK_COLUMN || op==TK_REGISTER)
+ if( (op==TK_AGG_COLUMN || op==TK_COLUMN || op==TK_REGISTER)
&& pExpr->pTab!=0
){
/* op==TK_REGISTER && pExpr->pTab!=0 happens when pExpr was originally
@@ -66272,7 +60617,7 @@ SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){
}
p = p->pLeft;
}
- if( sqlite3CheckCollSeq(pParse, pColl) ){
+ if( sqlite3CheckCollSeq(pParse, pColl) ){
pColl = 0;
}
return pColl;
@@ -66368,8 +60713,8 @@ static u8 binaryCompareP5(Expr *pExpr1, Expr *pExpr2, int jumpIfNull){
** it is not considered.
*/
SQLITE_PRIVATE CollSeq *sqlite3BinaryCompareCollSeq(
- Parse *pParse,
- Expr *pLeft,
+ Parse *pParse,
+ Expr *pLeft,
Expr *pRight
){
CollSeq *pColl;
@@ -66410,6 +60755,10 @@ static int codeCompare(
addr = sqlite3VdbeAddOp4(pParse->pVdbe, opcode, in2, dest, in1,
(void*)p4, P4_COLLSEQ);
sqlite3VdbeChangeP5(pParse->pVdbe, (u8)p5);
+ if( (p5 & SQLITE_AFF_MASK)!=SQLITE_AFF_NONE ){
+ sqlite3ExprCacheAffinityChange(pParse, in1, 1);
+ sqlite3ExprCacheAffinityChange(pParse, in2, 1);
+ }
return addr;
}
@@ -66423,7 +60772,7 @@ SQLITE_PRIVATE int sqlite3ExprCheckHeight(Parse *pParse, int nHeight){
int rc = SQLITE_OK;
int mxHeight = pParse->db->aLimit[SQLITE_LIMIT_EXPR_DEPTH];
if( nHeight>mxHeight ){
- sqlite3ErrorMsg(pParse,
+ sqlite3ErrorMsg(pParse,
"Expression tree is too large (maximum depth %d)", mxHeight
);
rc = SQLITE_ERROR;
@@ -66469,10 +60818,10 @@ static void heightOfSelect(Select *p, int *pnHeight){
}
/*
-** Set the Expr.nHeight variable in the structure passed as an
-** argument. An expression with no children, Expr.pList or
+** Set the Expr.nHeight variable in the structure passed as an
+** argument. An expression with no children, Expr.pList or
** Expr.pSelect member has a height of 1. Any other expression
-** has a height equal to the maximum height of any other
+** has a height equal to the maximum height of any other
** referenced Expr plus one.
*/
static void exprSetHeight(Expr *p){
@@ -66559,7 +60908,7 @@ SQLITE_PRIVATE Expr *sqlite3ExprAlloc(
pNew->u.zToken = (char*)&pNew[1];
memcpy(pNew->u.zToken, pToken->z, pToken->n);
pNew->u.zToken[pToken->n] = 0;
- if( dequote && nExtra>=3
+ if( dequote && nExtra>=3
&& ((c = pToken->z[0])=='\'' || c=='"' || c=='[' || c=='`') ){
sqlite3Dequote(pNew->u.zToken);
if( c=='"' ) pNew->flags |= EP_DblQuoted;
@@ -66568,7 +60917,7 @@ SQLITE_PRIVATE Expr *sqlite3ExprAlloc(
}
#if SQLITE_MAX_EXPR_DEPTH>0
pNew->nHeight = 1;
-#endif
+#endif
}
return pNew;
}
@@ -66679,7 +61028,7 @@ SQLITE_PRIVATE Expr *sqlite3ExprFunction(Parse *pParse, ExprList *pList, Token *
/*
** Assign a variable number to an expression that encodes a wildcard
-** in the original SQL statement.
+** in the original SQL statement.
**
** Wildcards consisting of a single "?" are assigned the next sequential
** variable number.
@@ -66754,7 +61103,7 @@ SQLITE_PRIVATE void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr){
pParse->apVarExpr[pParse->nVarExpr++] = pExpr;
}
}
- }
+ }
if( !pParse->nErr && pParse->nVar>db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] ){
sqlite3ErrorMsg(pParse, "too many SQL variables");
}
@@ -66783,7 +61132,7 @@ SQLITE_PRIVATE void sqlite3ExprDelete(sqlite3 *db, Expr *p){
}
/*
-** Return the number of bytes allocated for the expression structure
+** Return the number of bytes allocated for the expression structure
** passed as the first argument. This is always one of EXPR_FULLSIZE,
** EXPR_REDUCEDSIZE or EXPR_TOKENONLYSIZE.
*/
@@ -66798,14 +61147,14 @@ static int exprStructSize(Expr *p){
** to store a copy of an expression or expression tree. They differ in
** how much of the tree is measured.
**
-** dupedExprStructSize() Size of only the Expr structure
+** dupedExprStructSize() Size of only the Expr structure
** dupedExprNodeSize() Size of Expr + space for token
** dupedExprSize() Expr + token + subtree components
**
***************************************************************************
**
-** The dupedExprStructSize() function returns two values OR-ed together:
-** (1) the space required for a copy of the Expr structure only and
+** The dupedExprStructSize() function returns two values OR-ed together:
+** (1) the space required for a copy of the Expr structure only and
** (2) the EP_xxx flags that indicate what the structure size should be.
** The return values is always one of:
**
@@ -66834,7 +61183,7 @@ static int dupedExprStructSize(Expr *p, int flags){
nSize = EXPR_FULLSIZE;
}else{
assert( !ExprHasAnyProperty(p, EP_TokenOnly|EP_Reduced) );
- assert( !ExprHasProperty(p, EP_FromJoin) );
+ assert( !ExprHasProperty(p, EP_FromJoin) );
assert( (p->flags2 & EP2_MallocedToken)==0 );
assert( (p->flags2 & EP2_Irreducible)==0 );
if( p->pLeft || p->pRight || p->pColl || p->x.pList ){
@@ -66847,7 +61196,7 @@ static int dupedExprStructSize(Expr *p, int flags){
}
/*
-** This function returns the space in bytes required to store the copy
+** This function returns the space in bytes required to store the copy
** of the Expr structure and a copy of the Expr.u.zToken string (if that
** string is defined.)
*/
@@ -66860,16 +61209,16 @@ static int dupedExprNodeSize(Expr *p, int flags){
}
/*
-** Return the number of bytes required to create a duplicate of the
+** Return the number of bytes required to create a duplicate of the
** expression passed as the first argument. The second argument is a
** mask containing EXPRDUP_XXX flags.
**
** The value returned includes space to create a copy of the Expr struct
** itself and the buffer referred to by Expr.u.zToken, if any.
**
-** If the EXPRDUP_REDUCE flag is set, then the return value includes
-** space to duplicate all Expr nodes in the tree formed by Expr.pLeft
-** and Expr.pRight variables (but not for any structures pointed to or
+** If the EXPRDUP_REDUCE flag is set, then the return value includes
+** space to duplicate all Expr nodes in the tree formed by Expr.pLeft
+** and Expr.pRight variables (but not for any structures pointed to or
** descended from the Expr.x.pList or Expr.x.pSelect variables).
*/
static int dupedExprSize(Expr *p, int flags){
@@ -66884,8 +61233,8 @@ static int dupedExprSize(Expr *p, int flags){
}
/*
-** This function is similar to sqlite3ExprDup(), except that if pzBuffer
-** is not NULL then *pzBuffer is assumed to point to a buffer large enough
+** This function is similar to sqlite3ExprDup(), except that if pzBuffer
+** is not NULL then *pzBuffer is assumed to point to a buffer large enough
** to store the copy of expression p, the copies of p->u.zToken
** (if applicable), and the copies of the p->pLeft and p->pRight expressions,
** if any. Before returning, *pzBuffer is set to the first byte passed the
@@ -66982,7 +61331,7 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int flags, u8 **pzBuffer){
** without effecting the originals.
**
** The expression list, ID, and source lists return by sqlite3ExprListDup(),
-** sqlite3IdListDup(), and sqlite3SrcListDup() can not be further expanded
+** sqlite3IdListDup(), and sqlite3SrcListDup() can not be further expanded
** by subsequent calls to sqlite*ListAppend() routines.
**
** Any tables that the SrcList might point to are not duplicated.
@@ -67008,7 +61357,7 @@ SQLITE_PRIVATE ExprList *sqlite3ExprListDup(sqlite3 *db, ExprList *p, int flags)
if( pItem==0 ){
sqlite3DbFree(db, pNew);
return 0;
- }
+ }
pOldItem = p->a;
for(i=0; i<p->nExpr; i++, pItem++, pOldItem++){
Expr *pOldExpr = pOldItem->pExpr;
@@ -67025,7 +61374,7 @@ SQLITE_PRIVATE ExprList *sqlite3ExprListDup(sqlite3 *db, ExprList *p, int flags)
/*
** If cursors, triggers, views and subqueries are all omitted from
-** the build, then none of the following routines, except for
+** the build, then none of the following routines, except for
** sqlite3SelectDup(), can be called. sqlite3SelectDup() is sometimes
** called with a NULL argument.
*/
@@ -67155,7 +61504,7 @@ SQLITE_PRIVATE ExprList *sqlite3ExprListAppend(
}
return pList;
-no_mem:
+no_mem:
/* Avoid leaking memory if malloc has failed. */
sqlite3ExprDelete(db, pExpr);
sqlite3ExprListDelete(db, pList);
@@ -67387,7 +61736,7 @@ SQLITE_PRIVATE int sqlite3ExprIsInteger(Expr *p, int *pValue){
** Return FALSE if there is no chance that the expression can be NULL.
**
** If the expression might be NULL or if the expression is too complex
-** to tell return TRUE.
+** to tell return TRUE.
**
** This routine is used as an optimization, to skip OP_IsNull opcodes
** when we know that a value cannot be NULL. Hence, a false positive
@@ -67415,7 +61764,7 @@ SQLITE_PRIVATE int sqlite3ExprCanBeNull(const Expr *p){
/*
** Generate an OP_IsNull instruction that tests register iReg and jumps
-** to location iDest if the value in iReg is NULL. The value in iReg
+** to location iDest if the value in iReg is NULL. The value in iReg
** was computed by pExpr. If we can look at pExpr at compile-time and
** determine that it can never generate a NULL, then the OP_IsNull operation
** can be omitted.
@@ -67530,7 +61879,7 @@ static int isCandidateForInOpt(Select *p){
** either to test for membership of the (...) set or to iterate through
** its members, skipping duplicates.
**
-** The index of the cursor opened on the b-tree (database table, database index
+** The index of the cursor opened on the b-tree (database table, database index
** or ephermal table) is stored in pX->iTable before this function returns.
** The returned value of this function indicates the b-tree type, as follows:
**
@@ -67550,13 +61899,13 @@ static int isCandidateForInOpt(Select *p){
** to be unique - either because it is an INTEGER PRIMARY KEY or it
** has a UNIQUE constraint or UNIQUE index.
**
-** If the prNotFound parameter is not 0, then the b-tree will be used
-** for fast set membership tests. In this case an epheremal table must
-** be used unless <column> is an INTEGER PRIMARY KEY or an index can
+** If the prNotFound parameter is not 0, then the b-tree will be used
+** for fast set membership tests. In this case an epheremal table must
+** be used unless <column> is an INTEGER PRIMARY KEY or an index can
** be found with <column> as its left-most column.
**
** When the b-tree is being used for membership tests, the calling function
-** needs to know whether or not the structure contains an SQL NULL
+** needs to know whether or not the structure contains an SQL NULL
** value in order to correctly evaluate expressions like "X IN (Y, Z)".
** If there is any chance that the (...) might contain a NULL value at
** runtime, then a register is allocated and the register number written
@@ -67588,7 +61937,7 @@ SQLITE_PRIVATE int sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound){
assert( pX->op==TK_IN );
/* Check to see if an existing table or index can be used to
- ** satisfy the query. This is preferable to generating a new
+ ** satisfy the query. This is preferable to generating a new
** ephemeral table.
*/
p = (ExprHasProperty(pX, EP_xIsSelect) ? pX->x.pSelect : 0);
@@ -67599,7 +61948,7 @@ SQLITE_PRIVATE int sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound){
Vdbe *v = sqlite3GetVdbe(pParse); /* Virtual machine being coded */
Table *pTab = p->pSrc->a[0].pTab; /* Table <table>. */
int iDb; /* Database idx for pTab */
-
+
/* Code an OP_VerifyCookie and OP_TableLock for <table>. */
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
sqlite3CodeVerifySchema(pParse, iDb);
@@ -67629,7 +61978,7 @@ SQLITE_PRIVATE int sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound){
** to this collation sequence. */
CollSeq *pReq = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft, pExpr);
- /* Check that the affinity that will be used to perform the
+ /* Check that the affinity that will be used to perform the
** comparison is the same as the affinity of the column. If
** it is not, it is not possible to use any index.
*/
@@ -67644,11 +61993,11 @@ SQLITE_PRIVATE int sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound){
int iMem = ++pParse->nMem;
int iAddr;
char *pKey;
-
+
pKey = (char *)sqlite3IndexKeyinfo(pParse, pIdx);
iAddr = sqlite3VdbeAddOp1(v, OP_If, iMem);
sqlite3VdbeAddOp2(v, OP_Integer, 1, iMem);
-
+
sqlite3VdbeAddOp4(v, OP_OpenRead, iTab, pIdx->tnum, iDb,
pKey,P4_KEYINFO_HANDOFF);
VdbeComment((v, "%s", pIdx->zName));
@@ -67759,7 +62108,7 @@ SQLITE_PRIVATE int sqlite3CodeSubselect(
affinity = sqlite3ExprAffinity(pLeft);
/* Whether this is an 'x IN(SELECT...)' or an 'x IN(<exprlist>)'
- ** expression it is handled the same way. An ephemeral table is
+ ** expression it is handled the same way. An ephemeral table is
** filled with single-field index keys representing the results
** from the SELECT or the <exprlist>.
**
@@ -67793,7 +62142,7 @@ SQLITE_PRIVATE int sqlite3CodeSubselect(
return 0;
}
pEList = pExpr->x.pSelect->pEList;
- if( ALWAYS(pEList!=0 && pEList->nExpr>0) ){
+ if( ALWAYS(pEList!=0 && pEList->nExpr>0) ){
keyInfo.aColl[0] = sqlite3BinaryCompareCollSeq(pParse, pExpr->pLeft,
pEList->a[0].pExpr);
}
@@ -67920,7 +62269,7 @@ SQLITE_PRIVATE int sqlite3CodeSubselect(
** if the LHS is NULL or if the LHS is not contained within the RHS and the
** RHS contains one or more NULL values.
**
-** This routine generates code will jump to destIfFalse if the LHS is not
+** This routine generates code will jump to destIfFalse if the LHS is not
** contained within the RHS. If due to NULLs we cannot determine if the LHS
** is contained in the RHS then jump to destIfNull. If the LHS is contained
** within the RHS then fall through.
@@ -67969,9 +62318,9 @@ static void sqlite3ExprCodeIN(
*/
sqlite3VdbeAddOp4(v, OP_Affinity, r1, 1, 0, &affinity, 1);
- /* If the set membership test fails, then the result of the
+ /* If the set membership test fails, then the result of the
** "x IN (...)" expression must be either 0 or NULL. If the set
- ** contains no NULL values, then the result is 0. If the set
+ ** contains no NULL values, then the result is 0. If the set
** contains one or more NULL values, then the result of the
** expression is also NULL.
*/
@@ -68017,7 +62366,7 @@ static void sqlite3ExprCodeIN(
sqlite3VdbeAddOp2(v, OP_If, rRhsHasNull, destIfNull);
sqlite3VdbeAddOp2(v, OP_Goto, 0, destIfFalse);
- /* The OP_Found at the top of this branch jumps here when true,
+ /* The OP_Found at the top of this branch jumps here when true,
** causing the overall IN expression evaluation to fall through.
*/
sqlite3VdbeJumpHere(v, j1);
@@ -68040,12 +62389,11 @@ static char *dup8bytes(Vdbe *v, const char *in){
return out;
}
-#ifndef SQLITE_OMIT_FLOATING_POINT
/*
** Generate an instruction that will put the floating point
** value described by z[0..n-1] into register iMem.
**
-** The z[] string will probably not be zero-terminated. But the
+** The z[] string will probably not be zero-terminated. But the
** z[n] character is guaranteed to be something that does not look
** like the continuation of the number.
*/
@@ -68060,19 +62408,17 @@ static void codeReal(Vdbe *v, const char *z, int negateFlag, int iMem){
sqlite3VdbeAddOp4(v, OP_Real, 0, iMem, 0, zV, P4_REAL);
}
}
-#endif
/*
** Generate an instruction that will put the integer describe by
** text z[0..n-1] into register iMem.
**
-** The z[] string will probably not be zero-terminated. But the
+** The z[] string will probably not be zero-terminated. But the
** z[n] character is guaranteed to be something that does not look
** like the continuation of the number.
*/
-static void codeInteger(Parse *pParse, Expr *pExpr, int negFlag, int iMem){
- Vdbe *v = pParse->pVdbe;
+static void codeInteger(Vdbe *v, Expr *pExpr, int negFlag, int iMem){
if( pExpr->flags & EP_IntValue ){
int i = pExpr->u.iValue;
if( negFlag ) i = -i;
@@ -68088,11 +62434,7 @@ static void codeInteger(Parse *pParse, Expr *pExpr, int negFlag, int iMem){
zV = dup8bytes(v, (char*)&value);
sqlite3VdbeAddOp4(v, OP_Int64, 0, iMem, 0, zV, P4_INT64);
}else{
-#ifdef SQLITE_OMIT_FLOATING_POINT
- sqlite3ErrorMsg(pParse, "oversized integer: %s%s", negFlag ? "-" : "", z);
-#else
codeReal(v, z, negFlag, iMem);
-#endif
}
}
}
@@ -68245,27 +62587,6 @@ static void sqlite3ExprCachePinRegister(Parse *pParse, int iReg){
}
/*
-** Generate code to extract the value of the iCol-th column of a table.
-*/
-SQLITE_PRIVATE void sqlite3ExprCodeGetColumnOfTable(
- Vdbe *v, /* The VDBE under construction */
- Table *pTab, /* The table containing the value */
- int iTabCur, /* The cursor for this table */
- int iCol, /* Index of the column to extract */
- int regOut /* Extract the valud into this register */
-){
- if( iCol<0 || iCol==pTab->iPKey ){
- sqlite3VdbeAddOp2(v, OP_Rowid, iTabCur, regOut);
- }else{
- int op = IsVirtual(pTab) ? OP_VColumn : OP_Column;
- sqlite3VdbeAddOp3(v, op, iTabCur, iCol, regOut);
- }
- if( iCol>=0 ){
- sqlite3ColumnDefault(v, pTab, iCol, regOut);
- }
-}
-
-/*
** Generate code that will extract the iColumn-th column from
** table pTab and store the column value in a register. An effort
** is made to store the column value in register iReg, but this is
@@ -68291,9 +62612,15 @@ SQLITE_PRIVATE int sqlite3ExprCodeGetColumn(
sqlite3ExprCachePinRegister(pParse, p->iReg);
return p->iReg;
}
- }
+ }
assert( v!=0 );
- sqlite3ExprCodeGetColumnOfTable(v, pTab, iTable, iColumn, iReg);
+ if( iColumn<0 ){
+ sqlite3VdbeAddOp2(v, OP_Rowid, iTable, iReg);
+ }else if( ALWAYS(pTab!=0) ){
+ int op = IsVirtual(pTab) ? OP_VColumn : OP_Column;
+ sqlite3VdbeAddOp3(v, op, iTable, iColumn, iReg);
+ sqlite3ColumnDefault(v, pTab, iColumn, iReg);
+ }
sqlite3ExprCacheStore(pParse, iTable, iColumn, iReg);
return iReg;
}
@@ -68399,7 +62726,7 @@ SQLITE_PRIVATE void sqlite3ExprHardCopy(Parse *pParse, int iReg, int nReg){
** same order that it is executed.
**
** Aliases are numbered starting with 1. So iAlias is in the range
-** of 1 to pParse->nAlias inclusive.
+** of 1 to pParse->nAlias inclusive.
**
** pParse->aAlias[iAlias-1] records the register number where the value
** of the iAlias-th alias is stored. If zero, that means that the
@@ -68494,16 +62821,14 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
break;
}
case TK_INTEGER: {
- codeInteger(pParse, pExpr, 0, target);
+ codeInteger(v, pExpr, 0, target);
break;
}
-#ifndef SQLITE_OMIT_FLOATING_POINT
case TK_FLOAT: {
assert( !ExprHasProperty(pExpr, EP_IntValue) );
codeReal(v, pExpr->u.zToken, 0, target);
break;
}
-#endif
case TK_STRING: {
assert( !ExprHasProperty(pExpr, EP_IntValue) );
sqlite3VdbeAddOp4(v, OP_String8, 0, target, 0, pExpr->u.zToken, 0);
@@ -68530,12 +62855,27 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
}
#endif
case TK_VARIABLE: {
+ VdbeOp *pOp;
assert( !ExprHasProperty(pExpr, EP_IntValue) );
assert( pExpr->u.zToken!=0 );
assert( pExpr->u.zToken[0]!=0 );
- sqlite3VdbeAddOp2(v, OP_Variable, pExpr->iColumn, target);
- if( pExpr->u.zToken[1]!=0 ){
- sqlite3VdbeChangeP4(v, -1, pExpr->u.zToken, 0);
+ if( pExpr->u.zToken[1]==0
+ && (pOp = sqlite3VdbeGetOp(v, -1))->opcode==OP_Variable
+ && pOp->p1+pOp->p3==pExpr->iColumn
+ && pOp->p2+pOp->p3==target
+ && pOp->p4.z==0
+ ){
+ /* If the previous instruction was a copy of the previous unnamed
+ ** parameter into the previous register, then simply increment the
+ ** repeat count on the prior instruction rather than making a new
+ ** instruction.
+ */
+ pOp->p3++;
+ }else{
+ sqlite3VdbeAddOp3(v, OP_Variable, pExpr->iColumn, target, 1);
+ if( pExpr->u.zToken[1]!=0 ){
+ sqlite3VdbeChangeP4(v, -1, pExpr->u.zToken, 0);
+ }
}
break;
}
@@ -68624,7 +62964,7 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
case TK_BITOR:
case TK_SLASH:
case TK_LSHIFT:
- case TK_RSHIFT:
+ case TK_RSHIFT:
case TK_CONCAT: {
assert( TK_AND==OP_And );
assert( TK_OR==OP_Or );
@@ -68658,13 +62998,11 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
case TK_UMINUS: {
Expr *pLeft = pExpr->pLeft;
assert( pLeft );
- if( pLeft->op==TK_INTEGER ){
- codeInteger(pParse, pLeft, 1, target);
-#ifndef SQLITE_OMIT_FLOATING_POINT
- }else if( pLeft->op==TK_FLOAT ){
+ if( pLeft->op==TK_FLOAT ){
assert( !ExprHasProperty(pExpr, EP_IntValue) );
codeReal(v, pLeft->u.zToken, 1, target);
-#endif
+ }else if( pLeft->op==TK_INTEGER ){
+ codeInteger(v, pLeft, 1, target);
}else{
regFree1 = r1 = sqlite3GetTempReg(pParse);
sqlite3VdbeAddOp2(v, OP_Integer, 0, r1);
@@ -68779,7 +63117,7 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
** see if it is a column in a virtual table. This is done because
** the left operand of infix functions (the operand we want to
** control overloading) ends up as the second argument to the
- ** function. The expression "A glob B" is equivalent to
+ ** function. The expression "A glob B" is equivalent to
** "glob(B,A). We want to use the A in "A glob B" to test
** for function overloading. But we use the B term in "glob(B,A)".
*/
@@ -68798,7 +63136,7 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
}
}
if( pDef->flags & SQLITE_FUNC_NEEDCOLL ){
- if( !pColl ) pColl = db->pDfltColl;
+ if( !pColl ) pColl = db->pDfltColl;
sqlite3VdbeAddOp4(v, OP_CollSeq, 0, 0, 0, (char *)pColl, P4_COLLSEQ);
}
sqlite3VdbeAddOp4(v, OP_Function, constMask, r1, target,
@@ -68881,7 +63219,7 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
**
** The expression is implemented using an OP_Param opcode. The p1
** parameter is set to 0 for an old.rowid reference, or to (i+1)
- ** to reference another column of the old.* pseudo-table, where
+ ** to reference another column of the old.* pseudo-table, where
** i is the index of the column. For a new.rowid reference, p1 is
** set to (n+1), where n is the number of columns in each pseudo-table.
** For a reference to any other column in the new.* pseudo-table, p1
@@ -68895,7 +63233,7 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
**
** p1==0 -> old.rowid p1==3 -> new.rowid
** p1==1 -> old.a p1==4 -> new.a
- ** p1==2 -> old.b p1==5 -> new.b
+ ** p1==2 -> old.b p1==5 -> new.b
*/
Table *pTab = pExpr->pTab;
int p1 = pExpr->iTable * (pTab->nCol+1) + 1 + pExpr->iColumn;
@@ -68912,15 +63250,13 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
target
));
-#ifndef SQLITE_OMIT_FLOATING_POINT
/* If the column has REAL affinity, it may currently be stored as an
** integer. Use OP_RealAffinity to make sure it is really real. */
- if( pExpr->iColumn>=0
+ if( pExpr->iColumn>=0
&& pTab->aCol[pExpr->iColumn].affinity==SQLITE_AFF_REAL
){
sqlite3VdbeAddOp1(v, OP_RealAffinity, target);
}
-#endif
break;
}
@@ -69002,14 +63338,14 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
}else{
sqlite3VdbeAddOp2(v, OP_Null, 0, target);
}
- assert( db->mallocFailed || pParse->nErr>0
+ assert( db->mallocFailed || pParse->nErr>0
|| pParse->iCacheLevel==iCacheLevel );
sqlite3VdbeResolveLabel(v, endLabel);
break;
}
#ifndef SQLITE_OMIT_TRIGGER
case TK_RAISE: {
- assert( pExpr->affinity==OE_Rollback
+ assert( pExpr->affinity==OE_Rollback
|| pExpr->affinity==OE_Abort
|| pExpr->affinity==OE_Fail
|| pExpr->affinity==OE_Ignore
@@ -69085,7 +63421,7 @@ SQLITE_PRIVATE int sqlite3ExprCode(Parse *pParse, Expr *pExpr, int target){
** and modify the expression so that the next time it is evaluated,
** the result is a copy of the cache register.
**
-** This routine is used for expressions that are used multiple
+** This routine is used for expressions that are used multiple
** times. They are evaluated once and the results of the expression
** are reused.
*/
@@ -69100,7 +63436,7 @@ SQLITE_PRIVATE int sqlite3ExprCodeAndCache(Parse *pParse, Expr *pExpr, int targe
** no way for a TK_REGISTER to exist here. But it seems prudent to
** keep the ALWAYS() in case the conditions above change with future
** modifications or enhancements. */
- if( ALWAYS(pExpr->op!=TK_REGISTER) ){
+ if( ALWAYS(pExpr->op!=TK_REGISTER) ){
int iMem;
iMem = ++pParse->nMem;
sqlite3VdbeAddOp2(v, OP_Copy, inReg, iMem);
@@ -69117,12 +63453,12 @@ SQLITE_PRIVATE int sqlite3ExprCodeAndCache(Parse *pParse, Expr *pExpr, int targe
**
** * Any expression that evaluates to two or more opcodes.
**
-** * Any OP_Integer, OP_Real, OP_String, OP_Blob, OP_Null,
-** or OP_Variable that does not need to be placed in a
+** * Any OP_Integer, OP_Real, OP_String, OP_Blob, OP_Null,
+** or OP_Variable that does not need to be placed in a
** specific register.
**
** There is no point in factoring out single-instruction constant
-** expressions that need to be placed in a particular register.
+** expressions that need to be placed in a particular register.
** We could factor them out, but then we would end up adding an
** OP_SCopy instruction to move the value into the correct register
** later. We might as well just use the original instruction and
@@ -69188,7 +63524,7 @@ static int evalConstExpr(Walker *pWalker, Expr *pExpr){
case TK_CONST_FUNC: {
/* The arguments to a function have a fixed destination.
** Mark them this way to avoid generated unneeded OP_SCopy
- ** instructions.
+ ** instructions.
*/
ExprList *pList = pExpr->x.pList;
assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
@@ -69268,7 +63604,7 @@ SQLITE_PRIVATE int sqlite3ExprCodeExprList(
**
** x BETWEEN y AND z
**
-** The above is equivalent to
+** The above is equivalent to
**
** x>=y AND x<=z
**
@@ -69439,7 +63775,7 @@ SQLITE_PRIVATE void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int
}
}
sqlite3ReleaseTempReg(pParse, regFree1);
- sqlite3ReleaseTempReg(pParse, regFree2);
+ sqlite3ReleaseTempReg(pParse, regFree2);
}
/*
@@ -69586,76 +63922,59 @@ SQLITE_PRIVATE void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int
}
/*
-** Do a deep comparison of two expression trees. Return 0 if the two
-** expressions are completely identical. Return 1 if they differ only
-** by a COLLATE operator at the top level. Return 2 if there are differences
-** other than the top-level COLLATE operator.
+** Do a deep comparison of two expression trees. Return TRUE (non-zero)
+** if they are identical and return FALSE if they differ in any way.
**
-** Sometimes this routine will return 2 even if the two expressions
+** Sometimes this routine will return FALSE 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
-** returns 2, then you do not really know for certain if the two
-** expressions are the same. But if you get a 0 or 1 return, then you
+** identical, we return FALSE just to be safe. So if this routine
+** returns false, then you do not really know for certain if the two
+** expressions are the same. But if you get a TRUE return, then you
** can be sure the expressions are the same. In the places where
-** this routine is used, it does not hurt to get an extra 2 - that
+** this routine is used, it does not hurt to get an extra FALSE - that
** just might result in some slightly slower code. But returning
-** an incorrect 0 or 1 could lead to a malfunction.
+** an incorrect TRUE could lead to a malfunction.
*/
SQLITE_PRIVATE int sqlite3ExprCompare(Expr *pA, Expr *pB){
+ int i;
if( pA==0||pB==0 ){
- return pB==pA ? 0 : 2;
+ return pB==pA;
}
assert( !ExprHasAnyProperty(pA, EP_TokenOnly|EP_Reduced) );
assert( !ExprHasAnyProperty(pB, EP_TokenOnly|EP_Reduced) );
if( ExprHasProperty(pA, EP_xIsSelect) || ExprHasProperty(pB, EP_xIsSelect) ){
- return 2;
+ return 0;
+ }
+ if( (pA->flags & EP_Distinct)!=(pB->flags & EP_Distinct) ) return 0;
+ if( pA->op!=pB->op ) return 0;
+ if( !sqlite3ExprCompare(pA->pLeft, pB->pLeft) ) return 0;
+ if( !sqlite3ExprCompare(pA->pRight, pB->pRight) ) return 0;
+
+ if( pA->x.pList && pB->x.pList ){
+ if( pA->x.pList->nExpr!=pB->x.pList->nExpr ) return 0;
+ for(i=0; i<pA->x.pList->nExpr; i++){
+ Expr *pExprA = pA->x.pList->a[i].pExpr;
+ Expr *pExprB = pB->x.pList->a[i].pExpr;
+ if( !sqlite3ExprCompare(pExprA, pExprB) ) return 0;
+ }
+ }else if( pA->x.pList || pB->x.pList ){
+ return 0;
}
- if( (pA->flags & EP_Distinct)!=(pB->flags & EP_Distinct) ) return 2;
- if( pA->op!=pB->op ) 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( pA->iTable!=pB->iTable || pA->iColumn!=pB->iColumn ) return 0;
if( ExprHasProperty(pA, EP_IntValue) ){
if( !ExprHasProperty(pB, EP_IntValue) || pA->u.iValue!=pB->u.iValue ){
- return 2;
+ return 0;
}
}else if( pA->op!=TK_COLUMN && pA->u.zToken ){
- if( ExprHasProperty(pB, EP_IntValue) || NEVER(pB->u.zToken==0) ) return 2;
+ if( ExprHasProperty(pB, EP_IntValue) || NEVER(pB->u.zToken==0) ) return 0;
if( sqlite3StrICmp(pA->u.zToken,pB->u.zToken)!=0 ){
- return 2;
+ return 0;
}
}
- if( (pA->flags & EP_ExpCollate)!=(pB->flags & EP_ExpCollate) ) return 1;
- if( (pA->flags & EP_ExpCollate)!=0 && pA->pColl!=pB->pColl ) return 2;
- return 0;
+ return 1;
}
-/*
-** Compare two ExprList objects. Return 0 if they are identical and
-** non-zero if they differ in any way.
-**
-** 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
-** a malfunction will result.
-**
-** 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){
- int i;
- if( pA==0 && pB==0 ) return 0;
- if( pA==0 || pB==0 ) return 1;
- if( pA->nExpr!=pB->nExpr ) return 1;
- for(i=0; i<pA->nExpr; i++){
- 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;
- }
- return 0;
-}
/*
** Add a new element to the pAggInfo->aCol[] array. Return the index of
@@ -69673,7 +63992,7 @@ static int addAggInfoColumn(sqlite3 *db, AggInfo *pInfo){
&i
);
return i;
-}
+}
/*
** Add a new element to the pAggInfo->aFunc[] array. Return the index of
@@ -69682,7 +64001,7 @@ static int addAggInfoColumn(sqlite3 *db, AggInfo *pInfo){
static int addAggInfoFunc(sqlite3 *db, AggInfo *pInfo){
int i;
pInfo->aFunc = sqlite3ArrayAllocate(
- db,
+ db,
pInfo->aFunc,
sizeof(pInfo->aFunc[0]),
3,
@@ -69691,7 +64010,7 @@ static int addAggInfoFunc(sqlite3 *db, AggInfo *pInfo){
&i
);
return i;
-}
+}
/*
** This is the xExprCallback for a tree walker. It is used to
@@ -69719,7 +64038,7 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){
assert( !ExprHasAnyProperty(pExpr, EP_TokenOnly|EP_Reduced) );
if( pExpr->iTable==pItem->iCursor ){
/* If we reach this point, it means that pExpr refers to a table
- ** that is in the FROM clause of the aggregate query.
+ ** that is in the FROM clause of the aggregate query.
**
** Make an entry for the column in pAggInfo->aCol[] if there
** is not an entry there already.
@@ -69733,7 +64052,7 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){
}
}
if( (k>=pAggInfo->nColumn)
- && (k = addAggInfoColumn(pParse->db, pAggInfo))>=0
+ && (k = addAggInfoColumn(pParse->db, pAggInfo))>=0
){
pCol = &pAggInfo->aCol[k];
pCol->pTab = pExpr->pTab;
@@ -69779,12 +64098,12 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){
/* The pNC->nDepth==0 test causes aggregate functions in subqueries
** to be ignored */
if( pNC->nDepth==0 ){
- /* Check to see if pExpr is a duplicate of another aggregate
+ /* Check to see if pExpr is a duplicate of another aggregate
** function that is already in the pAggInfo structure
*/
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) ){
break;
}
}
@@ -69948,9 +64267,9 @@ SQLITE_PRIVATE void sqlite3ReleaseTempRange(Parse *pParse, int iReg, int nReg){
/*
-** This function is used by SQL generated to implement the
+** This function is used by SQL generated to implement the
** ALTER TABLE command. The first argument is the text of a CREATE TABLE or
-** CREATE INDEX command. The second is a table name. The table name in
+** CREATE INDEX command. The second is a table name. The table name in
** the CREATE TABLE or CREATE INDEX statement is replaced with the third
** argument and the result returned. Examples:
**
@@ -69978,7 +64297,7 @@ static void renameTableFunc(
UNUSED_PARAMETER(NotUsed);
- /* The principle used to locate the table name in the CREATE TABLE
+ /* The principle used to locate the table name in the CREATE TABLE
** statement is that the table name is the first non-space token that
** is immediately followed by a TK_LP or TK_USING token.
*/
@@ -70003,7 +64322,7 @@ static void renameTableFunc(
assert( len>0 );
} while( token!=TK_LP && token!=TK_USING );
- zRet = sqlite3MPrintf(db, "%.*s\"%w\"%s", ((u8*)tname.z) - zSql, zSql,
+ zRet = sqlite3MPrintf(db, "%.*s\"%w\"%s", ((u8*)tname.z) - zSql, zSql,
zTableName, tname.z+tname.n);
sqlite3_result_text(context, zRet, -1, SQLITE_DYNAMIC);
}
@@ -70012,7 +64331,7 @@ static void renameTableFunc(
/*
** This C function implements an SQL user function that is used by SQL code
** generated by the ALTER TABLE ... RENAME command to modify the definition
-** of any foreign key constraints that use the table being renamed as the
+** of any foreign key constraints that use the table being renamed as the
** parent table. It is passed three arguments:
**
** 1) The complete text of the CREATE TABLE statement being modified,
@@ -70055,7 +64374,7 @@ static void renameParentFunc(
if( zParent==0 ) break;
sqlite3Dequote(zParent);
if( 0==sqlite3StrICmp((const char *)zOld, zParent) ){
- char *zOut = sqlite3MPrintf(db, "%s%.*s\"%w\"",
+ char *zOut = sqlite3MPrintf(db, "%s%.*s\"%w\"",
(zOutput?zOutput:""), z-zInput, zInput, (const char *)zNew
);
sqlite3DbFree(db, zOutput);
@@ -70066,7 +64385,7 @@ static void renameParentFunc(
}
}
- zResult = sqlite3MPrintf(db, "%s%s", (zOutput?zOutput:""), zInput),
+ zResult = sqlite3MPrintf(db, "%s%s", (zOutput?zOutput:""), zInput),
sqlite3_result_text(context, zResult, -1, SQLITE_DYNAMIC);
sqlite3DbFree(db, zOutput);
}
@@ -70074,9 +64393,9 @@ static void renameParentFunc(
#ifndef SQLITE_OMIT_TRIGGER
/* This function is used by SQL generated to implement the
-** ALTER TABLE command. The first argument is the text of a CREATE TRIGGER
-** statement. The second is a table name. The table name in the CREATE
-** TRIGGER statement is replaced with the third argument and the result
+** ALTER TABLE command. The first argument is the text of a CREATE TRIGGER
+** statement. The second is a table name. The table name in the CREATE
+** TRIGGER statement is replaced with the third argument and the result
** returned. This is analagous to renameTableFunc() above, except for CREATE
** TRIGGER, not CREATE INDEX and CREATE TABLE.
*/
@@ -70098,7 +64417,7 @@ static void renameTriggerFunc(
UNUSED_PARAMETER(NotUsed);
- /* The principle used to locate the table name in the CREATE TRIGGER
+ /* The principle used to locate the table name in the CREATE TRIGGER
** statement is that the table name is the first token that is immediatedly
** preceded by either TK_ON or TK_DOT and immediatedly followed by one
** of TK_WHEN, TK_BEGIN or TK_FOR.
@@ -70125,12 +64444,12 @@ static void renameTriggerFunc(
assert( len>0 );
/* Variable 'dist' stores the number of tokens read since the most
- ** recent TK_DOT or TK_ON. This means that when a WHEN, FOR or BEGIN
+ ** recent TK_DOT or TK_ON. This means that when a WHEN, FOR or BEGIN
** token is read and 'dist' equals 2, the condition stated above
** to be met.
**
** Note that ON cannot be a database, table or column name, so
- ** there is no need to worry about syntax like
+ ** there is no need to worry about syntax like
** "CREATE TRIGGER ... ON ON.ON BEGIN ..." etc.
*/
dist++;
@@ -70142,7 +64461,7 @@ static void renameTriggerFunc(
/* Variable tname now contains the token that is the old table-name
** in the CREATE TRIGGER statement.
*/
- zRet = sqlite3MPrintf(db, "%.*s\"%w\"%s", ((u8*)tname.z) - zSql, zSql,
+ zRet = sqlite3MPrintf(db, "%.*s\"%w\"%s", ((u8*)tname.z) - zSql, zSql,
zTableName, tname.z+tname.n);
sqlite3_result_text(context, zRet, -1, SQLITE_DYNAMIC);
}
@@ -70152,23 +64471,17 @@ static void renameTriggerFunc(
/*
** Register built-in functions used to help implement ALTER TABLE
*/
-SQLITE_PRIVATE void sqlite3AlterFunctions(void){
- static SQLITE_WSD FuncDef aAlterTableFuncs[] = {
- FUNCTION(sqlite_rename_table, 2, 0, 0, renameTableFunc),
+SQLITE_PRIVATE void sqlite3AlterFunctions(sqlite3 *db){
+ sqlite3CreateFunc(db, "sqlite_rename_table", 2, SQLITE_UTF8, 0,
+ renameTableFunc, 0, 0);
#ifndef SQLITE_OMIT_TRIGGER
- FUNCTION(sqlite_rename_trigger, 2, 0, 0, renameTriggerFunc),
+ sqlite3CreateFunc(db, "sqlite_rename_trigger", 2, SQLITE_UTF8, 0,
+ renameTriggerFunc, 0, 0);
#endif
#ifndef SQLITE_OMIT_FOREIGN_KEY
- FUNCTION(sqlite_rename_parent, 3, 0, 0, renameParentFunc),
+ sqlite3CreateFunc(db, "sqlite_rename_parent", 3, SQLITE_UTF8, 0,
+ renameParentFunc, 0, 0);
#endif
- };
- int i;
- FuncDefHash *pHash = &GLOBAL(FuncDefHash, sqlite3GlobalFunctions);
- FuncDef *aFunc = (FuncDef*)&GLOBAL(FuncDef, aAlterTableFuncs);
-
- for(i=0; i<ArraySize(aAlterTableFuncs); i++){
- sqlite3FuncDefInsert(pHash, &aFunc[i]);
- }
}
/*
@@ -70176,16 +64489,16 @@ SQLITE_PRIVATE void sqlite3AlterFunctions(void){
**
** name=<constant1> OR name=<constant2> OR ...
**
-** If argument zWhere is NULL, then a pointer string containing the text
+** If argument zWhere is NULL, then a pointer string containing the text
** "name=<constant>" is returned, where <constant> is the quoted version
** of the string passed as argument zConstant. The returned buffer is
** allocated using sqlite3DbMalloc(). It is the responsibility of the
** caller to ensure that it is eventually freed.
**
-** If argument zWhere is not NULL, then the string returned is
+** If argument zWhere is not NULL, then the string returned is
** "<where> OR name=<constant>", where <where> is the contents of zWhere.
** In this case zWhere is passed to sqlite3DbFree() before returning.
-**
+**
*/
static char *whereOrName(sqlite3 *db, char *zWhere, char *zConstant){
char *zNew;
@@ -70218,7 +64531,7 @@ static char *whereForeignKeys(Parse *pParse, Table *pTab){
/*
** Generate the text of a WHERE expression which can be used to select all
** temporary triggers on table pTab from the sqlite_temp_master table. If
-** table pTab has no temporary triggers, or is itself stored in the
+** table pTab has no temporary triggers, or is itself stored in the
** temporary database, NULL is returned.
*/
static char *whereTempTriggers(Parse *pParse, Table *pTab){
@@ -70226,9 +64539,9 @@ static char *whereTempTriggers(Parse *pParse, Table *pTab){
char *zWhere = 0;
const Schema *pTempSchema = pParse->db->aDb[1].pSchema; /* Temp db schema */
- /* If the table is not located in the temp-db (in which case NULL is
+ /* If the table is not located in the temp-db (in which case NULL is
** returned, loop through the tables list of triggers. For each trigger
- ** that is not part of the temp-db schema, add a clause to the WHERE
+ ** that is not part of the temp-db schema, add a clause to the WHERE
** expression being built up in zWhere.
*/
if( pTab->pSchema!=pTempSchema ){
@@ -70247,7 +64560,7 @@ static char *whereTempTriggers(Parse *pParse, Table *pTab){
** pTab from the database, including triggers and temporary triggers.
** Argument zName is the name of the table in the database schema at
** the time the generated code is executed. This can be different from
-** pTab->zName if this function is being called to code part of an
+** pTab->zName if this function is being called to code part of an
** "ALTER TABLE RENAME TO" statement.
*/
static void reloadTableSchema(Parse *pParse, Table *pTab, const char *zName){
@@ -70282,8 +64595,8 @@ static void reloadTableSchema(Parse *pParse, Table *pTab, const char *zName){
sqlite3VdbeAddOp4(v, OP_ParseSchema, iDb, 0, 0, zWhere, P4_DYNAMIC);
#ifndef SQLITE_OMIT_TRIGGER
- /* Now, if the table is not stored in the temp database, reload any temp
- ** triggers. Don't use IN(...) in case SQLITE_OMIT_SUBQUERY is defined.
+ /* Now, if the table is not stored in the temp database, reload any temp
+ ** triggers. Don't use IN(...) in case SQLITE_OMIT_SUBQUERY is defined.
*/
if( (zWhere=whereTempTriggers(pParse, pTab))!=0 ){
sqlite3VdbeAddOp4(v, OP_ParseSchema, 1, 0, 0, zWhere, P4_DYNAMIC);
@@ -70292,8 +64605,8 @@ static void reloadTableSchema(Parse *pParse, Table *pTab, const char *zName){
}
/*
-** Generate code to implement the "ALTER TABLE xxx RENAME TO yyy"
-** command.
+** Generate code to implement the "ALTER TABLE xxx RENAME TO yyy"
+** command.
*/
SQLITE_PRIVATE void sqlite3AlterRenameTable(
Parse *pParse, /* Parser context. */
@@ -70303,7 +64616,7 @@ SQLITE_PRIVATE void sqlite3AlterRenameTable(
int iDb; /* Database that contains the table */
char *zDb; /* Name of database iDb */
Table *pTab; /* Table being renamed */
- char *zName = 0; /* NULL-terminated version of pName */
+ char *zName = 0; /* NULL-terminated version of pName */
sqlite3 *db = pParse->db; /* Database connection */
int nTabName; /* Number of UTF-8 characters in zTabName */
const char *zTabName; /* Original name of the table */
@@ -70312,9 +64625,7 @@ SQLITE_PRIVATE void sqlite3AlterRenameTable(
char *zWhere = 0; /* Where clause to locate temp triggers */
#endif
VTable *pVTab = 0; /* Non-zero if this is a v-tab with an xRename() */
- int savedDbFlags; /* Saved value of db->flags */
-
- savedDbFlags = db->flags;
+
if( NEVER(db->mallocFailed) ) goto exit_rename_table;
assert( pSrc->nSrc==1 );
assert( sqlite3BtreeHoldsAllMutexes(pParse->db) );
@@ -70323,7 +64634,6 @@ SQLITE_PRIVATE void sqlite3AlterRenameTable(
if( !pTab ) goto exit_rename_table;
iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
zDb = db->aDb[iDb].zName;
- db->flags |= SQLITE_PreferBuiltin;
/* Get a NULL terminated version of the new table name. */
zName = sqlite3NameFromToken(db, pName);
@@ -70333,7 +64643,7 @@ SQLITE_PRIVATE void sqlite3AlterRenameTable(
** in database iDb. If so, this is an error.
*/
if( sqlite3FindTable(db, zName, zDb) || sqlite3FindIndex(db, zName, zDb) ){
- sqlite3ErrorMsg(pParse,
+ sqlite3ErrorMsg(pParse,
"there is already another table or index with this name: %s", zName);
goto exit_rename_table;
}
@@ -70341,7 +64651,7 @@ SQLITE_PRIVATE void sqlite3AlterRenameTable(
/* Make sure it is not a system table being altered, or a reserved name
** that the table is being renamed to.
*/
- if( sqlite3Strlen30(pTab->zName)>6
+ if( sqlite3Strlen30(pTab->zName)>6
&& 0==sqlite3StrNICmp(pTab->zName, "sqlite_", 7)
){
sqlite3ErrorMsg(pParse, "table %s may not be altered", pTab->zName);
@@ -70377,7 +64687,7 @@ SQLITE_PRIVATE void sqlite3AlterRenameTable(
}
#endif
- /* Begin a transaction and code the VerifyCookie for database iDb.
+ /* Begin a transaction and code the VerifyCookie for database iDb.
** Then modify the schema cookie (since the ALTER TABLE modifies the
** schema). Open a statement transaction if the table is a virtual
** table.
@@ -70409,14 +64719,14 @@ SQLITE_PRIVATE void sqlite3AlterRenameTable(
#if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER)
if( db->flags&SQLITE_ForeignKeys ){
- /* If foreign-key support is enabled, rewrite the CREATE TABLE
+ /* If foreign-key support is enabled, rewrite the CREATE TABLE
** statements corresponding to all child tables of foreign key constraints
** for which the renamed table is the parent table. */
if( (zWhere=whereForeignKeys(pParse, pTab))!=0 ){
- sqlite3NestedParse(pParse,
- "UPDATE \"%w\".%s SET "
+ sqlite3NestedParse(pParse,
+ "UPDATE sqlite_master SET "
"sql = sqlite_rename_parent(sql, %Q, %Q) "
- "WHERE %s;", zDb, SCHEMA_TABLE(iDb), zTabName, zName, zWhere);
+ "WHERE %s;", zTabName, zName, zWhere);
sqlite3DbFree(db, zWhere);
}
}
@@ -70439,8 +64749,8 @@ SQLITE_PRIVATE void sqlite3AlterRenameTable(
"'sqlite_autoindex_' || %Q || substr(name,%d+18) "
"ELSE name END "
"WHERE tbl_name=%Q AND "
- "(type='table' OR type='index' OR type='trigger');",
- zDb, SCHEMA_TABLE(iDb), zName, zName, zName,
+ "(type='table' OR type='index' OR type='trigger');",
+ zDb, SCHEMA_TABLE(iDb), zName, zName, zName,
#ifndef SQLITE_OMIT_TRIGGER
zName,
#endif
@@ -70448,7 +64758,7 @@ SQLITE_PRIVATE void sqlite3AlterRenameTable(
);
#ifndef SQLITE_OMIT_AUTOINCREMENT
- /* If the sqlite_sequence table exists in this database, then update
+ /* If the sqlite_sequence table exists in this database, then update
** it with the new table name.
*/
if( sqlite3FindTable(db, "sqlite_sequence", zDb) ){
@@ -70464,7 +64774,7 @@ SQLITE_PRIVATE void sqlite3AlterRenameTable(
** the temp database.
*/
if( (zWhere=whereTempTriggers(pParse, pTab))!=0 ){
- sqlite3NestedParse(pParse,
+ sqlite3NestedParse(pParse,
"UPDATE sqlite_temp_master SET "
"sql = sqlite_rename_trigger(sql, %Q), "
"tbl_name = %Q "
@@ -70491,7 +64801,6 @@ SQLITE_PRIVATE void sqlite3AlterRenameTable(
exit_rename_table:
sqlite3SrcListDelete(db, pSrc);
sqlite3DbFree(db, zName);
- db->flags = savedDbFlags;
}
@@ -70560,7 +64869,7 @@ SQLITE_PRIVATE void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){
}
#endif
- /* If the default value for the new column was specified with a
+ /* If the default value for the new column was specified with a
** literal NULL, then set pDflt to 0. This simplifies checking
** for an SQL NULL default below.
*/
@@ -70581,12 +64890,12 @@ SQLITE_PRIVATE void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){
return;
}
if( (db->flags&SQLITE_ForeignKeys) && pNew->pFKey && pDflt ){
- sqlite3ErrorMsg(pParse,
+ sqlite3ErrorMsg(pParse,
"Cannot add a REFERENCES column with non-NULL default value");
return;
}
if( pCol->notNull && !pDflt ){
- sqlite3ErrorMsg(pParse,
+ sqlite3ErrorMsg(pParse,
"Cannot add a NOT NULL column with default value NULL");
return;
}
@@ -70611,20 +64920,17 @@ SQLITE_PRIVATE void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){
zCol = sqlite3DbStrNDup(db, (char*)pColDef->z, pColDef->n);
if( zCol ){
char *zEnd = &zCol[pColDef->n-1];
- int savedDbFlags = db->flags;
while( zEnd>zCol && (*zEnd==';' || sqlite3Isspace(*zEnd)) ){
*zEnd-- = '\0';
}
- db->flags |= SQLITE_PreferBuiltin;
- sqlite3NestedParse(pParse,
+ sqlite3NestedParse(pParse,
"UPDATE \"%w\".%s SET "
"sql = substr(sql,1,%d) || ', ' || %Q || substr(sql,%d) "
- "WHERE type = 'table' AND name = %Q",
+ "WHERE type = 'table' AND name = %Q",
zDb, SCHEMA_TABLE(iDb), pNew->addColOffset, zCol, pNew->addColOffset+1,
zTab
);
sqlite3DbFree(db, zCol);
- db->flags = savedDbFlags;
}
/* If the default value of the new column is NULL, then set the file
@@ -70639,14 +64945,14 @@ SQLITE_PRIVATE void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){
/*
** This function is called by the parser after the table-name in
-** an "ALTER TABLE <table-name> ADD" statement is parsed. Argument
+** an "ALTER TABLE <table-name> ADD" statement is parsed. Argument
** pSrc is the full-name of the table being altered.
**
** This routine makes a (partial) copy of the Table structure
** for the table being altered and sets Parse.pNewTable to point
** to it. Routines called by the parser as the column definition
-** is parsed (i.e. sqlite3AddColumn()) add the new Column data to
-** the copy. The copy of the Table structure is deleted by tokenize.c
+** is parsed (i.e. sqlite3AddColumn()) add the new Column data to
+** the copy. The copy of the Table structure is deleted by tokenize.c
** after parsing is finished.
**
** Routine sqlite3AlterFinishAddColumn() will be called to complete
@@ -70756,7 +65062,7 @@ exit_begin_add_column:
**
** If the sqlite_stat1 tables does not previously exist, it is created.
** Similarly, if the sqlite_stat2 table does not exist and the library
-** is compiled with SQLITE_ENABLE_STAT2 defined, it is created.
+** is compiled with SQLITE_ENABLE_STAT2 defined, it is created.
**
** Argument zWhere may be a pointer to a buffer containing a table name,
** or it may be a NULL pointer. If it is not NULL, then all entries in
@@ -70796,9 +65102,9 @@ static void openStatTable(
const char *zTab = aTable[i].zName;
Table *pStat;
if( (pStat = sqlite3FindTable(db, zTab, pDb->zName))==0 ){
- /* The sqlite_stat[12] table does not exist. Create it. Note that a
- ** side-effect of the CREATE TABLE statement is to leave the rootpage
- ** of the new table in register pParse->regRoot. This is important
+ /* The sqlite_stat[12] table does not exist. Create it. Note that a
+ ** side-effect of the CREATE TABLE statement is to leave the rootpage
+ ** of the new table in register pParse->regRoot. This is important
** because the OpenWrite opcode below will be needing it. */
sqlite3NestedParse(pParse,
"CREATE TABLE %Q.%s(%s)", pDb->zName, zTab, aTable[i].zCols
@@ -70806,7 +65112,7 @@ static void openStatTable(
aRoot[i] = pParse->regRoot;
aCreateTbl[i] = 1;
}else{
- /* The table already exists. If zWhere is not NULL, delete all entries
+ /* The table already exists. If zWhere is not NULL, delete all entries
** associated with the table zWhere. If zWhere is NULL, delete the
** entire contents of the table. */
aRoot[i] = pStat->tnum;
@@ -70932,18 +65238,18 @@ static void analyzeOneTable(
/* The block of memory cells initialized here is used as follows.
**
- ** iMem:
+ ** iMem:
** The total number of rows in the table.
**
- ** iMem+1 .. iMem+nCol:
- ** Number of distinct entries in index considering the
- ** left-most N columns only, where N is between 1 and nCol,
+ ** iMem+1 .. iMem+nCol:
+ ** Number of distinct entries in index considering the
+ ** left-most N columns only, where N is between 1 and nCol,
** inclusive.
**
- ** iMem+nCol+1 .. Mem+2*nCol:
+ ** iMem+nCol+1 .. Mem+2*nCol:
** Previous value of indexed columns, from left to right.
**
- ** Cells iMem through iMem+nCol are initialized to 0. The others are
+ ** Cells iMem through iMem+nCol are initialized to 0. The others are
** initialized to contain an SQL NULL.
*/
for(i=0; i<=nCol; i++){
@@ -70968,7 +65274,7 @@ static void analyzeOneTable(
** value that should be stored in the sqlite_stat2 table. If so,
** store it. */
int ne = sqlite3VdbeAddOp3(v, OP_Ne, regRecno, 0, regSamplerecno);
- assert( regTabname+1==regIdxname
+ assert( regTabname+1==regIdxname
&& regTabname+2==regSampleno
&& regTabname+3==regCol
);
@@ -71000,8 +65306,8 @@ static void analyzeOneTable(
sqlite3VdbeChangeP5(v, SQLITE_JUMPIFNULL);
}
if( db->mallocFailed ){
- /* If a malloc failure has occurred, then the result of the expression
- ** passed as the second argument to the call to sqlite3VdbeJumpHere()
+ /* If a malloc failure has occurred, then the result of the expression
+ ** passed as the second argument to the call to sqlite3VdbeJumpHere()
** below may be negative. Which causes an assert() to fail (or an
** out-of-bounds write if SQLITE_DEBUG is not defined). */
return;
@@ -71032,7 +65338,7 @@ static void analyzeOneTable(
**
** I = (K+D-1)/D
**
- ** If K==0 then no entry is made into the sqlite_stat1 table.
+ ** If K==0 then no entry is made into the sqlite_stat1 table.
** If K>0 then it is always the case the D>0 so division by zero
** is never possible.
*/
@@ -71169,7 +65475,7 @@ SQLITE_PRIVATE void sqlite3Analyze(Parse *pParse, Token *pName1, Token *pName2){
analyzeTable(pParse, pTab);
}
}
- }
+ }
}
}
@@ -71185,7 +65491,7 @@ struct analysisInfo {
/*
** This callback is invoked once for each index when reading the
-** sqlite_stat1 table.
+** sqlite_stat1 table.
**
** argv[0] = name of the index
** argv[1] = results of analysis - on integer for each column
@@ -71250,11 +65556,11 @@ SQLITE_PRIVATE void sqlite3DeleteIndexSamples(Index *pIdx){
** Index.aSample[] arrays.
**
** If the sqlite_stat1 table is not present in the database, SQLITE_ERROR
-** is returned. In this case, even if SQLITE_ENABLE_STAT2 was defined
-** during compilation and the sqlite_stat2 table is present, no data is
+** is returned. In this case, even if SQLITE_ENABLE_STAT2 was defined
+** during compilation and the sqlite_stat2 table is present, no data is
** read from it.
**
-** If SQLITE_ENABLE_STAT2 was defined during compilation and the
+** If SQLITE_ENABLE_STAT2 was defined during compilation and the
** sqlite_stat2 table is not present in the database, SQLITE_ERROR is
** returned. However, in this case, data is read from the sqlite_stat1
** table (if it is present) before returning.
@@ -71288,7 +65594,7 @@ SQLITE_PRIVATE int sqlite3AnalysisLoad(sqlite3 *db, int iDb){
}
/* Load new statistics out of the sqlite_stat1 table */
- zSql = sqlite3MPrintf(db,
+ zSql = sqlite3MPrintf(db,
"SELECT idx, stat FROM %Q.sqlite_stat1", sInfo.zDatabase);
if( zSql==0 ){
rc = SQLITE_NOMEM;
@@ -71306,7 +65612,7 @@ SQLITE_PRIVATE int sqlite3AnalysisLoad(sqlite3 *db, int iDb){
if( rc==SQLITE_OK ){
sqlite3_stmt *pStmt = 0;
- zSql = sqlite3MPrintf(db,
+ zSql = sqlite3MPrintf(db,
"SELECT idx,sampleno,sample FROM %Q.sqlite_stat2", sInfo.zDatabase);
if( !zSql ){
rc = SQLITE_NOMEM;
@@ -71352,16 +65658,12 @@ SQLITE_PRIVATE int sqlite3AnalysisLoad(sqlite3 *db, int iDb){
n = 24;
}
pSample->nByte = (u8)n;
- if( n < 1){
- pSample->u.z = 0;
+ pSample->u.z = sqlite3DbMallocRaw(dbMem, n);
+ if( pSample->u.z ){
+ memcpy(pSample->u.z, z, n);
}else{
- pSample->u.z = sqlite3DbMallocRaw(dbMem, n);
- if( pSample->u.z ){
- memcpy(pSample->u.z, z, n);
- }else{
- db->mallocFailed = 1;
- break;
- }
+ db->mallocFailed = 1;
+ break;
}
}
}
@@ -71472,7 +65774,7 @@ static void attachFunc(
** * Specified database name already being used.
*/
if( db->nDb>=db->aLimit[SQLITE_LIMIT_ATTACHED]+2 ){
- zErrDyn = sqlite3MPrintf(db, "too many attached databases - max %d",
+ zErrDyn = sqlite3MPrintf(db, "too many attached databases - max %d",
db->aLimit[SQLITE_LIMIT_ATTACHED]
);
goto attach_error;
@@ -71522,16 +65824,13 @@ static void attachFunc(
if( !aNew->pSchema ){
rc = SQLITE_NOMEM;
}else if( aNew->pSchema->file_format && aNew->pSchema->enc!=ENC(db) ){
- zErrDyn = sqlite3MPrintf(db,
+ zErrDyn = sqlite3MPrintf(db,
"attached databases must use the same text encoding as main database");
rc = SQLITE_ERROR;
}
pPager = sqlite3BtreePager(aNew->pBt);
sqlite3PagerLockingMode(pPager, db->dfltLockMode);
- /* journal_mode set by the OP_JournalMode opcode that will following
- ** the OP_Function opcode that invoked this function. */
- sqlite3BtreeSecureDelete(aNew->pBt,
- sqlite3BtreeSecureDelete(db->aDb[0].pBt,-1) );
+ sqlite3PagerJournalMode(pPager, db->dfltJournalMode);
}
aNew->safety_level = 3;
aNew->zName = sqlite3DbStrDup(db, zName);
@@ -71540,7 +65839,7 @@ static void attachFunc(
}
-#ifdef SQLITE_HAS_CODEC
+#if SQLITE_HAS_CODEC
if( rc==SQLITE_OK ){
extern int sqlite3CodecAttach(sqlite3*, int, const void*, int);
extern void sqlite3CodecGetKey(sqlite3*, int, void**, int*);
@@ -71553,7 +65852,7 @@ static void attachFunc(
zErrDyn = sqlite3DbStrDup(db, "Invalid key value");
rc = SQLITE_ERROR;
break;
-
+
case SQLITE_TEXT:
case SQLITE_BLOB:
nKey = sqlite3_value_bytes(argv[2]);
@@ -71571,7 +65870,7 @@ static void attachFunc(
#endif
/* If the file was opened successfully, read the schema for the new database.
- ** If this fails, or if opening the file failed, then close the file and
+ ** If this fails, or if opening the file failed, then close the file and
** remove the entry from the db->aDb[] array. i.e. put everything back the way
** we found it.
*/
@@ -71599,7 +65898,7 @@ static void attachFunc(
}
goto attach_error;
}
-
+
return;
attach_error:
@@ -71689,7 +65988,7 @@ static void codeAttach(
memset(&sName, 0, sizeof(NameContext));
sName.pParse = pParse;
- if(
+ if(
SQLITE_OK!=(rc = resolveAttachExpr(&sName, pFilename)) ||
SQLITE_OK!=(rc = resolveAttachExpr(&sName, pDbname)) ||
SQLITE_OK!=(rc = resolveAttachExpr(&sName, pKey))
@@ -71725,24 +66024,13 @@ static void codeAttach(
sqlite3VdbeChangeP5(v, (u8)(pFunc->nArg));
sqlite3VdbeChangeP4(v, -1, (char *)pFunc, P4_FUNCDEF);
- if( type==SQLITE_ATTACH ){
- /* On an attach, also set the journal mode. Note that
- ** sqlite3VdbeUsesBtree() is not call here since the iDb index
- ** will be out of range prior to the new database being attached.
- ** The OP_JournalMode opcode will all sqlite3VdbeUsesBtree() for us.
- */
- sqlite3VdbeAddOp3(v, OP_JournalMode, db->nDb, regArgs+3,
- db->dfltJournalMode);
- sqlite3VdbeChangeP5(v, 1);
- }
-
/* Code an OP_Expire. For an ATTACH statement, set P1 to true (expire this
** statement only). For DETACH, set it to false (expire all existing
** statements).
*/
sqlite3VdbeAddOp1(v, OP_Expire, (type==SQLITE_ATTACH));
}
-
+
attach_end:
sqlite3ExprDelete(db, pFilename);
sqlite3ExprDelete(db, pDbname);
@@ -72062,10 +66350,10 @@ SQLITE_PRIVATE int sqlite3AuthReadCol(
/*
** The pExpr should be a TK_COLUMN expression. The table referred to
-** is in pTabList or else it is the NEW or OLD table of a trigger.
+** is in pTabList or else it is the NEW or OLD table of a trigger.
** Check to see if it is OK to read this particular column.
**
-** If the auth function returns SQLITE_IGNORE, change the TK_COLUMN
+** If the auth function returns SQLITE_IGNORE, change the TK_COLUMN
** instruction into a TK_NULL. If the auth function returns SQLITE_DENY,
** then generate an error.
*/
@@ -72164,7 +66452,7 @@ SQLITE_PRIVATE int sqlite3AuthCheck(
*/
SQLITE_PRIVATE void sqlite3AuthContextPush(
Parse *pParse,
- AuthContext *pContext,
+ AuthContext *pContext,
const char *zContext
){
assert( pParse );
@@ -72235,7 +66523,7 @@ struct TableLock {
};
/*
-** Record the fact that we want to lock a table at run-time.
+** Record the fact that we want to lock a table at run-time.
**
** The table to be locked has root page iTab and is found in database iDb.
** A read or a write lock can be taken depending on isWritelock.
@@ -72286,7 +66574,7 @@ SQLITE_PRIVATE void sqlite3TableLock(
*/
static void codeTableLocks(Parse *pParse){
int i;
- Vdbe *pVdbe;
+ Vdbe *pVdbe;
pVdbe = sqlite3GetVdbe(pParse);
assert( pVdbe!=0 ); /* sqlite3GetVdbe cannot fail: VDBE already allocated */
@@ -72325,7 +66613,7 @@ SQLITE_PRIVATE void sqlite3FinishCoding(Parse *pParse){
** vdbe program
*/
v = sqlite3GetVdbe(pParse);
- assert( !pParse->isMultiWrite
+ assert( !pParse->isMultiWrite
|| sqlite3VdbeAssertMayAbort(v, pParse->mayAbort));
if( v ){
sqlite3VdbeAddOp0(v, OP_Halt);
@@ -72359,8 +66647,8 @@ SQLITE_PRIVATE void sqlite3FinishCoding(Parse *pParse){
}
#endif
- /* Once all the cookies have been verified and transactions opened,
- ** obtain the required table-locks. This is a no-op unless the
+ /* Once all the cookies have been verified and transactions opened,
+ ** obtain the required table-locks. This is a no-op unless the
** shared-cache feature is enabled.
*/
codeTableLocks(pParse);
@@ -72391,7 +66679,7 @@ SQLITE_PRIVATE void sqlite3FinishCoding(Parse *pParse){
pParse->isMultiWrite && pParse->mayAbort);
pParse->rc = SQLITE_DONE;
pParse->colNamesSet = 0;
- }else{
+ }else if( pParse->rc==SQLITE_OK ){
pParse->rc = SQLITE_ERROR;
}
pParse->nTab = 0;
@@ -72505,7 +66793,7 @@ SQLITE_PRIVATE Table *sqlite3LocateTable(
}
/*
-** Locate the in-memory structure that describes
+** Locate the in-memory structure that describes
** a particular index given the name of that index
** and the name of the database that contains the index.
** Return NULL if not found.
@@ -72686,7 +66974,7 @@ static void sqliteResetColumnNames(Table *pTable){
**
** This routine just deletes the data structure. It does not unlink
** the table data structure from the hash table. But it does destroy
-** memory structures of the indices and foreign keys associated with
+** memory structures of the indices and foreign keys associated with
** the table.
*/
SQLITE_PRIVATE void sqlite3DeleteTable(Table *pTable){
@@ -72797,7 +67085,7 @@ SQLITE_PRIVATE int sqlite3FindDbName(sqlite3 *db, const char *zName){
Db *pDb;
int n = sqlite3Strlen30(zName);
for(i=(db->nDb-1), pDb=&db->aDb[i]; i>=0; i--, pDb--){
- if( (!OMIT_TEMPDB || i!=1 ) && n==sqlite3Strlen30(pDb->zName) &&
+ if( (!OMIT_TEMPDB || i!=1 ) && n==sqlite3Strlen30(pDb->zName) &&
0==sqlite3StrICmp(pDb->zName, zName) ){
break;
}
@@ -72809,7 +67097,7 @@ SQLITE_PRIVATE int sqlite3FindDbName(sqlite3 *db, const char *zName){
/*
** The token *pName contains the name of a database (either "main" or
** "temp" or the name of an attached db). This routine returns the
-** index of the named database in db->aDb[], or -1 if the named db
+** index of the named database in db->aDb[], or -1 if the named db
** does not exist.
*/
SQLITE_PRIVATE int sqlite3FindDb(sqlite3 *db, Token *pName){
@@ -72825,7 +67113,7 @@ SQLITE_PRIVATE int sqlite3FindDb(sqlite3 *db, Token *pName){
** pName1 and pName2. If the table name was fully qualified, for example:
**
** CREATE TABLE xxx.yyy (...);
-**
+**
** Then pName1 is set to "xxx" and pName2 "yyy". On the other hand if
** the table name is not fully qualified, i.e.:
**
@@ -72875,7 +67163,7 @@ SQLITE_PRIVATE int sqlite3TwoPartName(
** is reserved for internal use.
*/
SQLITE_PRIVATE int sqlite3CheckObjectName(Parse *pParse, const char *zName){
- if( !pParse->db->init.busy && pParse->nested==0
+ if( !pParse->db->init.busy && pParse->nested==0
&& (pParse->db->flags & SQLITE_WriteSchema)==0
&& 0==sqlite3StrNICmp(zName, "sqlite_", 7) ){
sqlite3ErrorMsg(pParse, "object name reserved for internal use: %s", zName);
@@ -72920,7 +67208,7 @@ SQLITE_PRIVATE void sqlite3StartTable(
** pName1 and pName2. If the table name was fully qualified, for example:
**
** CREATE TABLE xxx.yyy (...);
- **
+ **
** Then pName1 is set to "xxx" and pName2 "yyy". On the other hand if
** the table name is not fully qualified, i.e.:
**
@@ -73029,7 +67317,7 @@ SQLITE_PRIVATE void sqlite3StartTable(
** the SQLITE_MASTER table. Note in particular that we must go ahead
** and allocate the record number for the table entry now. Before any
** PRIMARY KEY or UNIQUE keywords are parsed. Those keywords will cause
- ** indices to be created and the table record must come before the
+ ** indices to be created and the table record must come before the
** indices. Hence, the record number for the table must be allocated
** now.
*/
@@ -73045,7 +67333,7 @@ SQLITE_PRIVATE void sqlite3StartTable(
}
#endif
- /* If the file format and encoding in the database have not been set,
+ /* If the file format and encoding in the database have not been set,
** set them now.
*/
reg1 = pParse->regRowid = ++pParse->nMem;
@@ -73151,7 +67439,7 @@ SQLITE_PRIVATE void sqlite3AddColumn(Parse *pParse, Token *pName){
pCol = &p->aCol[p->nCol];
memset(pCol, 0, sizeof(p->aCol[0]));
pCol->zName = z;
-
+
/* If there is no type specified, columns have the default affinity
** 'NONE'. If there is a type specified, then sqlite3AddColumnType() will
** be called next to set pCol->affinity correctly.
@@ -73177,11 +67465,11 @@ SQLITE_PRIVATE void sqlite3AddNotNull(Parse *pParse, int onError){
** Scan the column type name zType (length nType) and return the
** associated affinity type.
**
-** This routine does a case-independent search of zType for the
+** This routine does a case-independent search of zType for the
** substrings in the following table. If one of the substrings is
** found, the corresponding affinity is returned. If zType contains
-** more than one of the substrings, entries toward the top of
-** the table take priority. For example, if zType is 'BLOBINT',
+** more than one of the substrings, entries toward the top of
+** the table take priority. For example, if zType is 'BLOBINT',
** SQLITE_AFF_INTEGER is returned.
**
** Substring | Affinity
@@ -73206,7 +67494,7 @@ SQLITE_PRIVATE char sqlite3AffinityType(const char *zIn){
h = (h<<8) + sqlite3UpperToLower[(*zIn)&0xff];
zIn++;
if( h==(('c'<<24)+('h'<<16)+('a'<<8)+'r') ){ /* CHAR */
- aff = SQLITE_AFF_TEXT;
+ aff = SQLITE_AFF_TEXT;
}else if( h==(('c'<<24)+('l'<<16)+('o'<<8)+'b') ){ /* CLOB */
aff = SQLITE_AFF_TEXT;
}else if( h==(('t'<<24)+('e'<<16)+('x'<<8)+'t') ){ /* TEXT */
@@ -73242,7 +67530,7 @@ SQLITE_PRIVATE char sqlite3AffinityType(const char *zIn){
** in the sequence. Use this information to construct a string
** that contains the typename of the column and store that string
** in zType.
-*/
+*/
SQLITE_PRIVATE void sqlite3AddColumnType(Parse *pParse, Token *pType){
Table *p;
Column *pCol;
@@ -73291,7 +67579,7 @@ SQLITE_PRIVATE void sqlite3AddDefaultValue(Parse *pParse, ExprSpan *pSpan){
}
/*
-** Designate the PRIMARY KEY for the table. pList is a list of names
+** Designate the PRIMARY KEY for the table. pList is a list of names
** of columns that form the primary key. If pList is NULL, then the
** most recently added column of the table is the primary key.
**
@@ -73320,7 +67608,7 @@ SQLITE_PRIVATE void sqlite3AddPrimaryKey(
int iCol = -1, i;
if( pTab==0 || IN_DECLARE_VTAB ) goto primary_key_exit;
if( pTab->tabFlags & TF_HasPrimaryKey ){
- sqlite3ErrorMsg(pParse,
+ sqlite3ErrorMsg(pParse,
"table \"%s\" has more than one primary key", pTab->zName);
goto primary_key_exit;
}
@@ -73407,7 +67695,7 @@ SQLITE_PRIVATE void sqlite3AddCollateType(Parse *pParse, Token *pToken){
if( sqlite3LocateCollSeq(pParse, zColl) ){
Index *pIdx;
p->aCol[i].zColl = zColl;
-
+
/* If the column is declared as "<name> PRIMARY KEY COLLATE <type>",
** then an index may have been created on this column before the
** collation type was added. Correct this if it is the case.
@@ -73503,13 +67791,13 @@ static int identLength(const char *z){
}
/*
-** The first parameter is a pointer to an output buffer. The second
+** The first parameter is a pointer to an output buffer. The second
** parameter is a pointer to an integer that contains the offset at
** which to write into the output buffer. This function copies the
** nul-terminated string pointed to by the third parameter, zSignedIdent,
** to the specified offset in the buffer and updates *pIdx to refer
** to the first byte after the last byte written before returning.
-**
+**
** If the string zSignedIdent consists entirely of alpha-numeric
** characters, does not begin with a digit and is not an SQL keyword,
** then it is copied to the output buffer exactly as it is. Otherwise,
@@ -73553,7 +67841,7 @@ static char *createTableStmt(sqlite3 *db, Table *p){
n += identLength(pCol->zName) + 5;
}
n += identLength(p->zName);
- if( n<50 ){
+ if( n<50 ){
zSep = "";
zSep2 = ",";
zEnd = ")";
@@ -73594,10 +67882,10 @@ static char *createTableStmt(sqlite3 *db, Table *p){
testcase( pCol->affinity==SQLITE_AFF_NUMERIC );
testcase( pCol->affinity==SQLITE_AFF_INTEGER );
testcase( pCol->affinity==SQLITE_AFF_REAL );
-
+
zType = azType[pCol->affinity - SQLITE_AFF_TEXT];
len = sqlite3Strlen30(zType);
- assert( pCol->affinity==SQLITE_AFF_NONE
+ assert( pCol->affinity==SQLITE_AFF_NONE
|| pCol->affinity==sqlite3AffinityType(zType) );
memcpy(&zStmt[k], zType, len);
k += len;
@@ -73623,7 +67911,7 @@ static char *createTableStmt(sqlite3 *db, Table *p){
** the sqlite_master table. We do not want to create it again.
**
** If the pSelect argument is not NULL, it means that this routine
-** was called to create a table generated from a
+** was called to create a table generated from a
** "CREATE TABLE ... AS SELECT ..." statement. The column names of
** the new table will match the result set of the SELECT.
*/
@@ -73697,7 +67985,7 @@ SQLITE_PRIVATE void sqlite3EndTable(
sqlite3VdbeAddOp1(v, OP_Close, 0);
- /*
+ /*
** Initialize zType for the new view or table.
*/
if( p->pSelect==0 ){
@@ -73753,12 +68041,12 @@ SQLITE_PRIVATE void sqlite3EndTable(
zStmt = createTableStmt(db, p);
}else{
n = (int)(pEnd->z - pParse->sNameToken.z) + 1;
- zStmt = sqlite3MPrintf(db,
+ zStmt = sqlite3MPrintf(db,
"CREATE %s %.*s", zType2, n, pParse->sNameToken.z
);
}
- /* A slot for the record has already been allocated in the
+ /* A slot for the record has already been allocated in the
** SQLITE_MASTER table. We just need to update that slot with all
** the information we've collected.
*/
@@ -73946,7 +68234,7 @@ SQLITE_PRIVATE int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){
** Actually, the error above is now caught prior to reaching this point.
** But the following test is still important as it does come up
** in the following:
- **
+ **
** CREATE TABLE main.ex1(a);
** CREATE TEMP VIEW ex1 AS SELECT a FROM ex1;
** SELECT * FROM temp.ex1;
@@ -73999,7 +68287,7 @@ SQLITE_PRIVATE int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){
nErr++;
}
#endif /* SQLITE_OMIT_VIEW */
- return nErr;
+ return nErr;
}
#endif /* !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE) */
@@ -74032,7 +68320,7 @@ static void sqliteViewResetAll(sqlite3 *db, int idx){
** on tables and/or indices that are the process of being deleted.
** If you are unlucky, one of those deleted indices or tables might
** have the same rootpage number as the real table or index that is
-** being moved. So we cannot stop searching after the first match
+** being moved. So we cannot stop searching after the first match
** because the first match might be for one of the deleted indices
** or tables and not the table/index that is actually being moved.
** We must continue looping until all tables and indices with
@@ -74066,7 +68354,7 @@ SQLITE_PRIVATE void sqlite3RootPageMoved(Db *pDb, int iFrom, int iTo){
** Also write code to modify the sqlite_master table and internal schema
** if a root-page of another table is moved by the btree-layer whilst
** erasing iTable (this can happen with an auto-vacuum database).
-*/
+*/
static void destroyRootPage(Parse *pParse, int iTable, int iDb){
Vdbe *v = sqlite3GetVdbe(pParse);
int r1 = sqlite3GetTempReg(pParse);
@@ -74082,7 +68370,7 @@ static void destroyRootPage(Parse *pParse, int iTable, int iDb){
** is in register NNN. See grammar rules associated with the TK_REGISTER
** token for additional information.
*/
- sqlite3NestedParse(pParse,
+ sqlite3NestedParse(pParse,
"UPDATE %Q.%s SET rootpage=%d WHERE #%d AND rootpage=#%d",
pParse->db->aDb[iDb].zName, SCHEMA_TABLE(iDb), iTable, r1, r1);
#endif
@@ -74106,7 +68394,7 @@ static void destroyTable(Parse *pParse, Table *pTab){
#else
/* If the database may be auto-vacuum capable (if SQLITE_OMIT_AUTOVACUUM
** is not defined), then it is important to call OP_Destroy on the
- ** table and index root-pages in order, starting with the numerically
+ ** table and index root-pages in order, starting with the numerically
** largest root-page number. This guarantees that none of the root-pages
** to be destroyed is relocated by an earlier OP_Destroy. i.e. if the
** following were coded:
@@ -74116,7 +68404,7 @@ static void destroyTable(Parse *pParse, Table *pTab){
** OP_Destroy 5 0
**
** and root page 5 happened to be the largest root-page number in the
- ** database, then root page 5 would be moved to page 4 by the
+ ** database, then root page 5 would be moved to page 4 by the
** "OP_Destroy 4 0" opcode. The subsequent "OP_Destroy 5 0" would hit
** a free-list page.
*/
@@ -74164,7 +68452,7 @@ SQLITE_PRIVATE void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView,
assert( pParse->nErr==0 );
assert( pName->nSrc==1 );
if( noErr ) db->suppressErr++;
- pTab = sqlite3LocateTable(pParse, isView,
+ pTab = sqlite3LocateTable(pParse, isView,
pName->a[0].zName, pName->a[0].zDatabase);
if( noErr ) db->suppressErr--;
@@ -74256,7 +68544,7 @@ SQLITE_PRIVATE void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView,
*/
pTrigger = sqlite3TriggerList(pParse, pTab);
while( pTrigger ){
- assert( pTrigger->pSchema==pTab->pSchema ||
+ assert( pTrigger->pSchema==pTab->pSchema ||
pTrigger->pSchema==db->aDb[1].pSchema );
sqlite3DropTriggerPtr(pParse, pTrigger);
pTrigger = pTrigger->pNext;
@@ -74283,7 +68571,7 @@ SQLITE_PRIVATE void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView,
** created in the temp database that refers to a table in another
** database.
*/
- sqlite3NestedParse(pParse,
+ sqlite3NestedParse(pParse,
"DELETE FROM %Q.%s WHERE tbl_name=%Q and type!='trigger'",
pDb->zName, SCHEMA_TABLE(iDb), pTab->zName);
@@ -74397,8 +68685,8 @@ SQLITE_PRIVATE void sqlite3CreateForeignKey(
}
}
if( j>=p->nCol ){
- sqlite3ErrorMsg(pParse,
- "unknown column \"%s\" in foreign key definition",
+ sqlite3ErrorMsg(pParse,
+ "unknown column \"%s\" in foreign key definition",
pFromCol->a[i].zName);
goto fk_end;
}
@@ -74417,7 +68705,7 @@ SQLITE_PRIVATE void sqlite3CreateForeignKey(
pFKey->aAction[0] = (u8)(flags & 0xff); /* ON DELETE action */
pFKey->aAction[1] = (u8)((flags >> 8 ) & 0xff); /* ON UPDATE action */
- pNextTo = (FKey *)sqlite3HashInsert(&p->pSchema->fkeyHash,
+ pNextTo = (FKey *)sqlite3HashInsert(&p->pSchema->fkeyHash,
pFKey->zTo, sqlite3Strlen30(pFKey->zTo), (void *)pFKey
);
if( pNextTo==pFKey ){
@@ -74502,7 +68790,7 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
sqlite3VdbeAddOp2(v, OP_Clear, tnum, iDb);
}
pKey = sqlite3IndexKeyinfo(pParse, pIndex);
- sqlite3VdbeAddOp4(v, OP_OpenWrite, iIdx, tnum, iDb,
+ sqlite3VdbeAddOp4(v, OP_OpenWrite, iIdx, tnum, iDb,
(char *)pKey, P4_KEYINFO_HANDOFF);
if( memRootPage>=0 ){
sqlite3VdbeChangeP5(v, 1);
@@ -74519,7 +68807,7 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
/* The registers accessed by the OP_IsUnique opcode were allocated
** using sqlite3GetTempRange() inside of the sqlite3GenerateIndexKey()
** call above. Just before that function was freed they were released
- ** (made available to the compiler for reuse) using
+ ** (made available to the compiler for reuse) using
** sqlite3ReleaseTempRange(). So in some ways having the OP_IsUnique
** opcode use the values stored within seems dangerous. However, since
** we can be sure that no other temp registers have been allocated
@@ -74539,8 +68827,8 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
}
/*
-** Create a new index for an SQL table. pName1.pName2 is the name of the index
-** and pTblList is the name of the table that is to be indexed. Both will
+** Create a new index for an SQL table. pName1.pName2 is the name of the index
+** and pTblList is the name of the table that is to be indexed. Both will
** be NULL for a primary key or an index that is created to satisfy a
** UNIQUE constraint. If pTable and pIndex are NULL, use pParse->pNewTable
** as the table to be indexed. pParse->pNewTable is a table that is
@@ -74548,7 +68836,7 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
**
** pList is a list of columns to be indexed. pList will be NULL if this
** is a primary key or unique-constraint on the most recent column added
-** to the table currently under construction.
+** to the table currently under construction.
**
** If the index is created successfully, return a pointer to the new Index
** structure. This is used by sqlite3AddPrimaryKey() to mark the index
@@ -74598,7 +68886,7 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex(
*/
if( pTblName!=0 ){
- /* Use the two-part index name to determine the database
+ /* Use the two-part index name to determine the database
** to search for the table. 'Fix' the table name to this db
** before looking up the table.
*/
@@ -74626,7 +68914,7 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex(
** sqlite3FixSrcList can never fail. */
assert(0);
}
- pTab = sqlite3LocateTable(pParse, 0, pTblName->a[0].zName,
+ pTab = sqlite3LocateTable(pParse, 0, pTblName->a[0].zName,
pTblName->a[0].zDatabase);
if( !pTab || db->mallocFailed ) goto exit_create_index;
assert( db->aDb[iDb].pSchema==pTab->pSchema );
@@ -74640,7 +68928,7 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex(
assert( pTab!=0 );
assert( pParse->nErr==0 );
- if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0
+ if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0
&& memcmp(&pTab->zName[7],"altertab_",9)!=0 ){
sqlite3ErrorMsg(pParse, "table %s may not be indexed", pTab->zName);
goto exit_create_index;
@@ -74660,7 +68948,7 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex(
/*
** Find the name of the index. Make sure there is not already another
- ** index or table with the same name.
+ ** index or table with the same name.
**
** Exception: If we are reading the names of permanent indices from the
** sqlite_master table (because some other process changed the schema) and
@@ -74743,12 +69031,12 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex(
}
}
- /*
- ** Allocate the index structure.
+ /*
+ ** Allocate the index structure.
*/
nName = sqlite3Strlen30(zName);
nCol = pList->nExpr;
- pIndex = sqlite3DbMallocZero(db,
+ pIndex = sqlite3DbMallocZero(db,
sizeof(Index) + /* Index structure */
sizeof(int)*nCol + /* Index.aiColumn */
sizeof(int)*(nCol+1) + /* Index.aiRowEst */
@@ -74788,7 +69076,7 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex(
** TODO: Add a test to make sure that the same column is not named
** more than once within the same index. Only the first instance of
** the column will ever be used by the optimizer. Note that using the
- ** same column more than once cannot be an error because that would
+ ** same column more than once cannot be an error because that would
** break backwards compatibility - it needs to be a warning.
*/
for(i=0, pListItem=pList->a; i<pList->nExpr; i++, pListItem++){
@@ -74877,13 +69165,13 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex(
if( pIdx->onError!=pIndex->onError ){
/* This constraint creates the same index as a previous
** constraint specified somewhere in the CREATE TABLE statement.
- ** However the ON CONFLICT clauses are different. If both this
+ ** However the ON CONFLICT clauses are different. If both this
** constraint and the previous equivalent constraint have explicit
** ON CONFLICT clauses this is an error. Otherwise, use the
** explicitly specified behaviour for the index.
*/
if( !(pIdx->onError==OE_Default || pIndex->onError==OE_Default) ){
- sqlite3ErrorMsg(pParse,
+ sqlite3ErrorMsg(pParse,
"conflicting ON CONFLICT clauses specified", 0);
}
if( pIdx->onError==OE_Default ){
@@ -74896,11 +69184,11 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex(
}
/* Link the new Index structure to its table and to the other
- ** in-memory database structures.
+ ** in-memory database structures.
*/
if( db->init.busy ){
Index *p;
- p = sqlite3HashInsert(&pIndex->pSchema->idxHash,
+ p = sqlite3HashInsert(&pIndex->pSchema->idxHash,
pIndex->zName, sqlite3Strlen30(pIndex->zName),
pIndex);
if( p ){
@@ -74918,8 +69206,8 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex(
** involves writing the index into the master table and filling in the
** index with the current table contents.
**
- ** The db->init.busy is 0 when the user first enters a CREATE INDEX
- ** command. db->init.busy is 1 when a database is opened and
+ ** The db->init.busy is 0 when the user first enters a CREATE INDEX
+ ** command. db->init.busy is 1 when a database is opened and
** CREATE INDEX statements are read out of the master table. In
** the latter case the index already exists on disk, which is why
** we don't want to recreate it.
@@ -74961,7 +69249,7 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex(
/* Add an entry in sqlite_master for this index
*/
- sqlite3NestedParse(pParse,
+ sqlite3NestedParse(pParse,
"INSERT INTO %Q.%s VALUES('index',%Q,%Q,#%d,%Q);",
db->aDb[iDb].zName, SCHEMA_TABLE(iDb),
pIndex->zName,
@@ -74987,7 +69275,7 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex(
** sure all indices labeled OE_Replace come after all those labeled
** OE_Ignore. This is necessary for the correct constraint check
** processing (in sqlite3GenerateConstraintChecks()) as part of
- ** UPDATE and INSERT statements.
+ ** UPDATE and INSERT statements.
*/
if( db->init.busy || pTblName==0 ){
if( onError!=OE_Replace || pTab->pIndex==0
@@ -75305,7 +69593,7 @@ SQLITE_PRIVATE SrcList *sqlite3SrcListEnlarge(
** database name prefix. Like this: "database.table". The pDatabase
** points to the table name and the pTable points to the database name.
** The SrcList.a[].zName field is filled with the table name which might
-** come from pTable (if pDatabase is NULL) or from pDatabase.
+** come from pTable (if pDatabase is NULL) or from pDatabase.
** SrcList.a[].zDatabase is filled with the database name from pTable,
** or with NULL if no database is specified.
**
@@ -75425,7 +69713,7 @@ SQLITE_PRIVATE SrcList *sqlite3SrcListAppendFromTerm(
struct SrcList_item *pItem;
sqlite3 *db = pParse->db;
if( !p && (pOn || pUsing) ){
- sqlite3ErrorMsg(pParse, "a JOIN clause is required before %s",
+ sqlite3ErrorMsg(pParse, "a JOIN clause is required before %s",
(pOn ? "ON" : "USING")
);
goto append_from_error;
@@ -75453,7 +69741,7 @@ SQLITE_PRIVATE SrcList *sqlite3SrcListAppendFromTerm(
}
/*
-** Add an INDEXED BY or NOT INDEXED clause to the most recently added
+** Add an INDEXED BY or NOT INDEXED clause to the most recently added
** element of the source-list passed as the second argument.
*/
SQLITE_PRIVATE void sqlite3SrcListIndexedBy(Parse *pParse, SrcList *p, Token *pIndexedBy){
@@ -75462,7 +69750,7 @@ SQLITE_PRIVATE void sqlite3SrcListIndexedBy(Parse *pParse, SrcList *p, Token *pI
struct SrcList_item *pItem = &p->a[p->nSrc-1];
assert( pItem->notIndexed==0 && pItem->zIndex==0 );
if( pIndexedBy->n==1 && !pIndexedBy->z ){
- /* A "NOT INDEXED" clause was supplied. See parse.y
+ /* A "NOT INDEXED" clause was supplied. See parse.y
** construct "indexed_opt" for details. */
pItem->notIndexed = 1;
}else{
@@ -75564,7 +69852,7 @@ SQLITE_PRIVATE void sqlite3RollbackTransaction(Parse *pParse){
/*
** This function is called by the parser when it parses a command to create,
-** release or rollback an SQL savepoint.
+** release or rollback an SQL savepoint.
*/
SQLITE_PRIVATE void sqlite3Savepoint(Parse *pParse, int op, Token *pName){
char *zName = sqlite3NameFromToken(pParse->db, pName);
@@ -75590,28 +69878,24 @@ SQLITE_PRIVATE int sqlite3OpenTempDatabase(Parse *pParse){
sqlite3 *db = pParse->db;
if( db->aDb[1].pBt==0 && !pParse->explain ){
int rc;
- Btree *pBt;
- static const int flags =
+ static const int flags =
SQLITE_OPEN_READWRITE |
SQLITE_OPEN_CREATE |
SQLITE_OPEN_EXCLUSIVE |
SQLITE_OPEN_DELETEONCLOSE |
SQLITE_OPEN_TEMP_DB;
- rc = sqlite3BtreeFactory(db, 0, 0, SQLITE_DEFAULT_CACHE_SIZE, flags, &pBt);
+ rc = sqlite3BtreeFactory(db, 0, 0, SQLITE_DEFAULT_CACHE_SIZE, flags,
+ &db->aDb[1].pBt);
if( rc!=SQLITE_OK ){
sqlite3ErrorMsg(pParse, "unable to open a temporary database "
"file for storing temporary tables");
pParse->rc = rc;
return 1;
}
- db->aDb[1].pBt = pBt;
assert( db->aDb[1].pSchema );
- if( SQLITE_NOMEM==sqlite3BtreeSetPageSize(pBt, db->nextPagesize, -1, 0) ){
- db->mallocFailed = 1;
- return 1;
- }
- sqlite3PagerJournalMode(sqlite3BtreePager(pBt), db->dfltJournalMode);
+ sqlite3PagerJournalMode(sqlite3BtreePager(db->aDb[1].pBt),
+ db->dfltJournalMode);
}
return 0;
}
@@ -75696,9 +69980,9 @@ SQLITE_PRIVATE void sqlite3MultiWrite(Parse *pParse){
pToplevel->isMultiWrite = 1;
}
-/*
+/*
** The code generator calls this routine if is discovers that it is
-** possible to abort a statement prior to completion. In order to
+** possible to abort a statement prior to completion. In order to
** perform this abort without corrupting the database, we need to make
** sure that the statement is protected by a statement transaction.
**
@@ -75707,7 +69991,7 @@ SQLITE_PRIVATE void sqlite3MultiWrite(Parse *pParse){
** such that the abort must occur after the multiwrite. This makes
** some statements involving the REPLACE conflict resolution algorithm
** go a little faster. But taking advantage of this time dependency
-** makes it more difficult to prove that the code is correct (in
+** makes it more difficult to prove that the code is correct (in
** particular, it prevents us from writing an effective
** implementation of sqlite3AssertMayAbort()) and so we have chosen
** to take the safe route and skip the optimization.
@@ -75863,8 +70147,8 @@ SQLITE_PRIVATE void sqlite3Reindex(Parse *pParse, Token *pName1, Token *pName2){
** with OP_OpenRead or OP_OpenWrite to access database index pIdx.
**
** If successful, a pointer to the new structure is returned. In this case
-** the caller is responsible for calling sqlite3DbFree(db, ) on the returned
-** pointer. If an error occurs (out of memory or missing collation
+** the caller is responsible for calling sqlite3DbFree(db, ) on the returned
+** pointer. If an error occurs (out of memory or missing collation
** sequence), NULL is returned and the state of pParse updated to reflect
** the error.
*/
@@ -75898,7 +70182,7 @@ SQLITE_PRIVATE KeyInfo *sqlite3IndexKeyinfo(Parse *pParse, Index *pIdx){
/************** End of build.c ***********************************************/
/************** Begin file callback.c ****************************************/
/*
-** 2005 May 23
+** 2005 May 23
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
@@ -75967,8 +70251,8 @@ static int synthCollSeq(sqlite3 *db, CollSeq *pColl){
** This function is responsible for invoking the collation factory callback
** or substituting a collation sequence of a different encoding when the
** requested collation sequence is not available in the desired encoding.
-**
-** If it is not NULL, then pColl must point to the database native encoding
+**
+** If it is not NULL, then pColl must point to the database native encoding
** collation sequence with name zName, length nName.
**
** The return value is either the collation sequence to be used in database
@@ -76010,7 +70294,7 @@ SQLITE_PRIVATE CollSeq *sqlite3GetCollSeq(
** that have not been defined by sqlite3_create_collation() etc.
**
** If required, this routine calls the 'collation needed' callback to
-** request a definition of the collating sequence. If this doesn't work,
+** request a definition of the collating sequence. If this doesn't work,
** an equivalent collating sequence that uses a text encoding different
** from the main database is substituted, if one is available.
*/
@@ -76067,7 +70351,7 @@ static CollSeq *findCollSeqEntry(
pColl[0].zName[nName] = 0;
pDel = sqlite3HashInsert(&db->aCollSeq, pColl[0].zName, nName, pColl);
- /* If a malloc() failure occurred in sqlite3HashInsert(), it will
+ /* If a malloc() failure occurred in sqlite3HashInsert(), it will
** return the pColl pointer to be deleted (because it wasn't added
** to the hash table).
*/
@@ -76138,7 +70422,7 @@ SQLITE_PRIVATE CollSeq *sqlite3FindCollSeq(
*/
static int matchQuality(FuncDef *p, int nArg, u8 enc){
int match = 0;
- if( p->nArg==-1 || p->nArg==nArg
+ if( p->nArg==-1 || p->nArg==nArg
|| (nArg==-1 && (p->xFunc!=0 || p->xStep!=0))
){
match = 1;
@@ -76197,8 +70481,8 @@ SQLITE_PRIVATE void sqlite3FuncDefInsert(
pHash->a[h] = pDef;
}
}
-
-
+
+
/*
** Locate a user function given a name, a number of arguments and a flag
@@ -76251,19 +70535,14 @@ SQLITE_PRIVATE FuncDef *sqlite3FindFunction(
/* If no match is found, search the built-in functions.
**
- ** If the SQLITE_PreferBuiltin flag is set, then search the built-in
- ** functions even if a prior app-defined function was found. And give
- ** priority to built-in functions.
- **
** Except, if createFlag is true, that means that we are trying to
** install a new function. Whatever FuncDef structure is returned will
** have fields overwritten with new information appropriate for the
** new function. But the FuncDefs for built-in functions are read-only.
** So we must not search for built-ins when creating a new function.
- */
- if( !createFlag && (pBest==0 || (db->flags & SQLITE_PreferBuiltin)!=0) ){
+ */
+ if( !createFlag && !pBest ){
FuncDefHash *pHash = &GLOBAL(FuncDefHash, sqlite3GlobalFunctions);
- bestScore = 0;
p = functionSearch(pHash, h, zName, nName);
while( p ){
int score = matchQuality(p, nArg, enc);
@@ -76279,7 +70558,7 @@ SQLITE_PRIVATE FuncDef *sqlite3FindFunction(
** exact match for the name, number of arguments and encoding, then add a
** new entry to the hash table and return it.
*/
- if( createFlag && (bestScore<6 || pBest->nArg!=nArg) &&
+ if( createFlag && (bestScore<6 || pBest->nArg!=nArg) &&
(pBest = sqlite3DbMallocZero(db, sizeof(*pBest)+nName+1))!=0 ){
pBest->zName = (char *)&pBest[1];
pBest->nArg = (u16)nArg;
@@ -76297,7 +70576,7 @@ SQLITE_PRIVATE FuncDef *sqlite3FindFunction(
/*
** Free all resources held by the schema structure. The void* argument points
-** at a Schema struct. This function does not call sqlite3DbFree(db, ) on the
+** at a Schema struct. This function does not call sqlite3DbFree(db, ) on the
** pointer itself, it just cleans up subsiduary resources (i.e. the contents
** of the schema hash tables).
**
@@ -76401,12 +70680,12 @@ SQLITE_PRIVATE int sqlite3IsReadOnly(Parse *pParse, Table *pTab, int viewOk){
** 1) It is a virtual table and no implementation of the xUpdate method
** has been provided, or
** 2) It is a system table (i.e. sqlite_master), this call is not
- ** part of a nested parse and writable_schema pragma has not
+ ** part of a nested parse and writable_schema pragma has not
** been specified.
**
** In either case leave an error message in pParse and return non-zero.
*/
- if( ( IsVirtual(pTab)
+ if( ( IsVirtual(pTab)
&& sqlite3GetVTable(pParse->db, pTab)->pMod->pModule->xUpdate==0 )
|| ( (pTab->tabFlags & TF_Readonly)!=0
&& (pParse->db->flags & SQLITE_WriteSchema)==0
@@ -76445,7 +70724,7 @@ SQLITE_PRIVATE void sqlite3MaterializeView(
pDup = sqlite3SelectDup(db, pView->pSelect, 0);
if( pWhere ){
SrcList *pFrom;
-
+
pWhere = sqlite3ExprDup(db, pWhere, 0);
pFrom = sqlite3SrcListAppend(db, 0, 0, 0);
if( pFrom ){
@@ -76507,11 +70786,11 @@ SQLITE_PRIVATE Expr *sqlite3LimitWhere(
return pWhere;
}
- /* Generate a select expression tree to enforce the limit/offset
+ /* Generate a select expression tree to enforce the limit/offset
** term for the DELETE or UPDATE statement. For example:
** DELETE FROM table_a WHERE col1=1 ORDER BY col2 LIMIT 1 OFFSET 1
** becomes:
- ** DELETE FROM table_a WHERE rowid IN (
+ ** DELETE FROM table_a WHERE rowid IN (
** SELECT rowid FROM table_a WHERE col1=1 ORDER BY col2 LIMIT 1 OFFSET 1
** );
*/
@@ -76692,9 +70971,9 @@ SQLITE_PRIVATE void sqlite3DeleteFrom(
#ifndef SQLITE_OMIT_TRUNCATE_OPTIMIZATION
/* Special case: A DELETE without a WHERE clause deletes everything.
** It is easier just to erase the whole table. Prior to version 3.6.5,
- ** this optimization caused the row change count (the value returned by
+ ** this optimization caused the row change count (the value returned by
** API function sqlite3_count_changes) to be set incorrectly. */
- if( rcauth==SQLITE_OK && pWhere==0 && !pTrigger && !IsVirtual(pTab)
+ if( rcauth==SQLITE_OK && pWhere==0 && !pTrigger && !IsVirtual(pTab)
&& 0==sqlite3FkRequired(pParse, pTab, 0, 0)
){
assert( !isView );
@@ -76731,9 +71010,9 @@ SQLITE_PRIVATE void sqlite3DeleteFrom(
** because deleting an item can change the scan order. */
end = sqlite3VdbeMakeLabel(v);
- /* Unless this is a view, open cursors for the table we are
+ /* Unless this is a view, open cursors for the table we are
** deleting from and all its indices. If this is a view, then the
- ** only effect this statement has is to fire the INSTEAD OF
+ ** only effect this statement has is to fire the INSTEAD OF
** triggers. */
if( !isView ){
sqlite3OpenTableAndIndices(pParse, pTab, iCur, OP_OpenWrite);
@@ -76776,7 +71055,7 @@ SQLITE_PRIVATE void sqlite3DeleteFrom(
sqlite3AutoincrementEnd(pParse);
}
- /* Return the number of rows that were deleted. If this routine is
+ /* Return the number of rows that were deleted. If this routine is
** generating code because of a call to sqlite3NestedParse(), do not
** invoke the callback function.
*/
@@ -76818,7 +71097,7 @@ delete_from_cleanup:
** 3. The record number of the row to be deleted must be stored in
** memory cell iRowid.
**
-** This routine generates code to remove both the table record and all
+** This routine generates code to remove both the table record and all
** index entries that point to that record.
*/
SQLITE_PRIVATE void sqlite3GenerateRowDelete(
@@ -76837,12 +71116,12 @@ SQLITE_PRIVATE void sqlite3GenerateRowDelete(
/* Vdbe is guaranteed to have been allocated by this stage. */
assert( v );
- /* Seek cursor iCur to the row to delete. If this row no longer exists
+ /* Seek cursor iCur to the row to delete. If this row no longer exists
** (this can happen if a trigger program has already deleted it), do
** not attempt to delete it or fire any DELETE triggers. */
iLabel = sqlite3VdbeMakeLabel(v);
sqlite3VdbeAddOp3(v, OP_NotExists, iCur, iLabel, iRowid);
-
+
/* If there are any triggers to fire, allocate a range of registers to
** use for the old.* references in the triggers. */
if( sqlite3FkRequired(pParse, pTab, 0, 0) || pTrigger ){
@@ -76858,35 +71137,37 @@ SQLITE_PRIVATE void sqlite3GenerateRowDelete(
iOld = pParse->nMem+1;
pParse->nMem += (1 + pTab->nCol);
- /* Populate the OLD.* pseudo-table register array. These values will be
+ /* Populate the OLD.* pseudo-table register array. These values will be
** used by any BEFORE and AFTER triggers that exist. */
sqlite3VdbeAddOp2(v, OP_Copy, iRowid, iOld);
for(iCol=0; iCol<pTab->nCol; iCol++){
if( mask==0xffffffff || mask&(1<<iCol) ){
- sqlite3ExprCodeGetColumnOfTable(v, pTab, iCur, iCol, iOld+iCol+1);
+ int iTarget = iOld + iCol + 1;
+ sqlite3VdbeAddOp3(v, OP_Column, iCur, iCol, iTarget);
+ sqlite3ColumnDefault(v, pTab, iCol, iTarget);
}
}
/* Invoke BEFORE DELETE trigger programs. */
- sqlite3CodeRowTrigger(pParse, pTrigger,
+ sqlite3CodeRowTrigger(pParse, pTrigger,
TK_DELETE, 0, TRIGGER_BEFORE, pTab, iOld, onconf, iLabel
);
/* Seek the cursor to the row to be deleted again. It may be that
** the BEFORE triggers coded above have already removed the row
- ** being deleted. Do not attempt to delete the row a second time, and
+ ** being deleted. Do not attempt to delete the row a second time, and
** do not fire AFTER triggers. */
sqlite3VdbeAddOp3(v, OP_NotExists, iCur, iLabel, iRowid);
/* Do FK processing. This call checks that any FK constraints that
- ** refer to this table (i.e. constraints attached to other tables)
+ ** refer to this table (i.e. constraints attached to other tables)
** are not violated by deleting this row. */
sqlite3FkCheck(pParse, pTab, iOld, 0);
}
/* Delete the index and table entries. Skip this step if pTab is really
** a view (in which case the only effect of the DELETE statement is to
- ** fire the INSTEAD OF triggers). */
+ ** fire the INSTEAD OF triggers). */
if( pTab->pSelect==0 ){
sqlite3GenerateRowIndexDelete(pParse, pTab, iCur, 0);
sqlite3VdbeAddOp2(v, OP_Delete, iCur, (count?OPFLAG_NCHANGE:0));
@@ -76897,16 +71178,16 @@ SQLITE_PRIVATE void sqlite3GenerateRowDelete(
/* Do any ON CASCADE, SET NULL or SET DEFAULT operations required to
** handle rows (possibly in other tables) that refer via a foreign key
- ** to the row just deleted. */
+ ** to the row just deleted. */
sqlite3FkActions(pParse, pTab, 0, iOld);
/* Invoke AFTER DELETE trigger programs. */
- sqlite3CodeRowTrigger(pParse, pTrigger,
+ sqlite3CodeRowTrigger(pParse, pTrigger,
TK_DELETE, 0, TRIGGER_AFTER, pTab, iOld, onconf, iLabel
);
/* Jump here if the row had already been deleted before any BEFORE
- ** trigger programs were invoked. Or if a trigger program throws a
+ ** trigger programs were invoked. Or if a trigger program throws a
** RAISE(IGNORE) exception. */
sqlite3VdbeResolveLabel(v, iLabel);
}
@@ -77002,7 +71283,7 @@ SQLITE_PRIVATE int sqlite3GenerateIndexKey(
**
*************************************************************************
** This file contains the C functions that implement various SQL
-** functions of SQLite.
+** functions of SQLite.
**
** There is only one exported symbol in this file - the function
** sqliteRegisterBuildinFunctions() found at the bottom of the file.
@@ -77108,7 +71389,7 @@ static void lengthFunc(
** Implementation of the abs() function.
**
** IMP: R-23979-26855 The abs(X) function returns the absolute value of
-** the numeric argument X.
+** the numeric argument X.
*/
static void absFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
assert( argc==1 );
@@ -77125,7 +71406,7 @@ static void absFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
return;
}
iVal = -iVal;
- }
+ }
sqlite3_result_int64(context, iVal);
break;
}
@@ -77138,7 +71419,7 @@ static void absFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
/* Because sqlite3_value_double() returns 0.0 if the argument is not
** something that can be converted into a number, we have:
** IMP: R-57326-31541 Abs(X) return 0.0 if X is a string or blob that
- ** cannot be converted to a numeric value.
+ ** cannot be converted to a numeric value.
*/
double rVal = sqlite3_value_double(argv[0]);
if( rVal<0 ) rVal = -rVal;
@@ -77259,24 +71540,14 @@ static void roundFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
}
if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return;
r = sqlite3_value_double(argv[0]);
- /* If Y==0 and X will fit in a 64-bit int,
- ** handle the rounding directly,
- ** otherwise use printf.
- */
- if( n==0 && r>=0 && r<LARGEST_INT64-1 ){
- r = (double)((sqlite_int64)(r+0.5));
- }else if( n==0 && r<0 && (-r)<LARGEST_INT64-1 ){
- r = -(double)((sqlite_int64)((-r)+0.5));
+ zBuf = sqlite3_mprintf("%.*f",n,r);
+ if( zBuf==0 ){
+ sqlite3_result_error_nomem(context);
}else{
- zBuf = sqlite3_mprintf("%.*f",n,r);
- if( zBuf==0 ){
- sqlite3_result_error_nomem(context);
- return;
- }
sqlite3AtoF(zBuf, &r);
sqlite3_free(zBuf);
+ sqlite3_result_double(context, r);
}
- sqlite3_result_double(context, r);
}
#endif
@@ -77358,7 +71629,7 @@ static void lowerFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
** comment.
*/
/*
-** Implementation of the IFNULL(), NVL(), and COALESCE() functions.
+** Implementation of the IFNULL(), NVL(), and COALESCE() functions.
** All three do the same thing. They return the first non-NULL
** argument.
*/
@@ -77379,7 +71650,7 @@ static void ifnullFunc(
#define ifnullFunc versionFunc /* Substitute function - never called */
/*
-** Implementation of random(). Return a random integer.
+** Implementation of random(). Return a random integer.
*/
static void randomFunc(
sqlite3_context *context,
@@ -77390,11 +71661,11 @@ static void randomFunc(
UNUSED_PARAMETER2(NotUsed, NotUsed2);
sqlite3_randomness(sizeof(r), &r);
if( r<0 ){
- /* We need to prevent a random number of 0x8000000000000000
+ /* We need to prevent a random number of 0x8000000000000000
** (or -9223372036854775808) since when you do abs() of that
** number of you get the same value back again. To do this
** in a way that is testable, mask the sign bit off of negative
- ** values, resulting in a positive value. Then take the
+ ** values, resulting in a positive value. Then take the
** 2s complement of that positive value. The end result can
** therefore be no less than -9223372036854775807.
*/
@@ -77432,24 +71703,18 @@ static void randomBlob(
** value is the same as the sqlite3_last_insert_rowid() API function.
*/
static void last_insert_rowid(
- sqlite3_context *context,
- int NotUsed,
+ sqlite3_context *context,
+ int NotUsed,
sqlite3_value **NotUsed2
){
sqlite3 *db = sqlite3_context_db_handle(context);
UNUSED_PARAMETER2(NotUsed, NotUsed2);
- /* IMP: R-51513-12026 The last_insert_rowid() SQL function is a
- ** wrapper around the sqlite3_last_insert_rowid() C/C++ interface
- ** function. */
sqlite3_result_int64(context, sqlite3_last_insert_rowid(db));
}
/*
-** Implementation of the changes() SQL function.
-**
-** IMP: R-62073-11209 The changes() SQL function is a wrapper
-** around the sqlite3_changes() C/C++ function and hence follows the same
-** rules for counting changes.
+** Implementation of the changes() SQL function. The return value is the
+** same as the sqlite3_changes() API function.
*/
static void changes(
sqlite3_context *context,
@@ -77472,8 +71737,6 @@ static void total_changes(
){
sqlite3 *db = sqlite3_context_db_handle(context);
UNUSED_PARAMETER2(NotUsed, NotUsed2);
- /* IMP: R-52756-41993 This function is a wrapper around the
- ** sqlite3_total_changes() C/C++ interface. */
sqlite3_result_int(context, sqlite3_total_changes(db));
}
@@ -77548,7 +71811,7 @@ static int patternCompare(
u8 matchOne = pInfo->matchOne;
u8 matchAll = pInfo->matchAll;
u8 matchSet = pInfo->matchSet;
- u8 noCase = pInfo->noCase;
+ u8 noCase = pInfo->noCase;
int prevEscape = 0; /* True if the previous character was 'escape' */
while( (c = sqlite3Utf8Read(zPattern,&zPattern))!=0 ){
@@ -77667,8 +71930,8 @@ SQLITE_API int sqlite3_like_count = 0;
** the GLOB operator.
*/
static void likeFunc(
- sqlite3_context *context,
- int argc,
+ sqlite3_context *context,
+ int argc,
sqlite3_value **argv
){
const unsigned char *zA, *zB;
@@ -77698,7 +71961,7 @@ static void likeFunc(
const unsigned char *zEsc = sqlite3_value_text(argv[2]);
if( zEsc==0 ) return;
if( sqlite3Utf8CharLen((char*)zEsc, -1)!=1 ){
- sqlite3_result_error(context,
+ sqlite3_result_error(context,
"ESCAPE expression must be a single character", -1);
return;
}
@@ -77709,7 +71972,7 @@ static void likeFunc(
#ifdef SQLITE_TEST
sqlite3_like_count++;
#endif
-
+
sqlite3_result_int(context, patternCompare(zB, zA, pInfo, escape));
}
}
@@ -77741,9 +72004,7 @@ static void versionFunc(
sqlite3_value **NotUsed2
){
UNUSED_PARAMETER2(NotUsed, NotUsed2);
- /* IMP: R-48699-48617 This function is an SQL wrapper around the
- ** sqlite3_libversion() C-interface. */
- sqlite3_result_text(context, sqlite3_libversion(), -1, SQLITE_STATIC);
+ sqlite3_result_text(context, sqlite3_version, -1, SQLITE_STATIC);
}
/*
@@ -77757,59 +72018,14 @@ static void sourceidFunc(
sqlite3_value **NotUsed2
){
UNUSED_PARAMETER2(NotUsed, NotUsed2);
- /* IMP: R-24470-31136 This function is an SQL wrapper around the
- ** sqlite3_sourceid() C interface. */
- sqlite3_result_text(context, sqlite3_sourceid(), -1, SQLITE_STATIC);
-}
-
-/*
-** Implementation of the sqlite_compileoption_used() function.
-** The result is an integer that identifies if the compiler option
-** was used to build SQLite.
-*/
-#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
-static void compileoptionusedFunc(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- const char *zOptName;
- assert( argc==1 );
- UNUSED_PARAMETER(argc);
- /* IMP: R-xxxx This function is an SQL wrapper around the
- ** sqlite3_compileoption_used() C interface. */
- if( (zOptName = (const char*)sqlite3_value_text(argv[0]))!=0 ){
- sqlite3_result_int(context, sqlite3_compileoption_used(zOptName));
- }
-}
-#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */
-
-/*
-** Implementation of the sqlite_compileoption_get() function.
-** The result is a string that identifies the compiler options
-** used to build SQLite.
-*/
-#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
-static void compileoptiongetFunc(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- int n;
- assert( argc==1 );
- UNUSED_PARAMETER(argc);
- /* IMP: R-xxxx This function is an SQL wrapper around the
- ** sqlite3_compileoption_get() C interface. */
- n = sqlite3_value_int(argv[0]);
- sqlite3_result_text(context, sqlite3_compileoption_get(n), -1, SQLITE_STATIC);
+ sqlite3_result_text(context, SQLITE_SOURCE_ID, -1, SQLITE_STATIC);
}
-#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */
/* Array for converting from half-bytes (nybbles) into ASCII hex
** digits. */
static const char hexdigits[] = {
'0', '1', '2', '3', '4', '5', '6', '7',
- '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
+ '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
};
/*
@@ -77837,7 +72053,7 @@ static void quoteFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
char const *zBlob = sqlite3_value_blob(argv[0]);
int nBlob = sqlite3_value_bytes(argv[0]);
assert( zBlob==sqlite3_value_blob(argv[0]) ); /* No encoding change */
- zText = (char *)contextMalloc(context, (2*(i64)nBlob)+4);
+ zText = (char *)contextMalloc(context, (2*(i64)nBlob)+4);
if( zText ){
int i;
for(i=0; i<nBlob; i++){
@@ -77931,7 +72147,7 @@ static void zeroblobFunc(
if( n>db->aLimit[SQLITE_LIMIT_LENGTH] ){
sqlite3_result_error_toobig(context);
}else{
- sqlite3_result_zeroblob(context, (int)n); /* IMP: R-00293-64994 */
+ sqlite3_result_zeroblob(context, (int)n);
}
}
@@ -77986,7 +72202,7 @@ static void replaceFunc(
if( zOut==0 ){
return;
}
- loopLimit = nStr - nPattern;
+ loopLimit = nStr - nPattern;
for(i=j=0; i<=loopLimit; i++){
if( zStr[i]!=zPattern[0] || memcmp(&zStr[i], zPattern, nPattern) ){
zOut[j++] = zStr[i];
@@ -78115,7 +72331,7 @@ static void trimFunc(
** Compute the soundex encoding of a word.
**
** IMP: R-59782-00072 The soundex(X) function returns a string that is the
-** soundex encoding of the string X.
+** soundex encoding of the string X.
*/
static void soundexFunc(
sqlite3_context *context,
@@ -78196,7 +72412,7 @@ static void loadExt(sqlite3_context *context, int argc, sqlite3_value **argv){
typedef struct SumCtx SumCtx;
struct SumCtx {
double rSum; /* Floating point sum */
- i64 iSum; /* Integer sum */
+ i64 iSum; /* Integer sum */
i64 cnt; /* Number of elements summed */
u8 overflow; /* True if integer overflow seen */
u8 approx; /* True if non-integer value was input to the sum */
@@ -78286,13 +72502,13 @@ static void countStep(sqlite3_context *context, int argc, sqlite3_value **argv){
#ifndef SQLITE_OMIT_DEPRECATED
/* The sqlite3_aggregate_count() function is deprecated. But just to make
- ** sure it still operates correctly, verify that its count agrees with our
+ ** sure it still operates correctly, verify that its count agrees with our
** internal count when using count(*) and when the total count can be
** expressed as a 32-bit integer. */
assert( argc==1 || p==0 || p->n>0x7fffffff
|| p->n==sqlite3_aggregate_count(context) );
#endif
-}
+}
static void countFinalize(sqlite3_context *context){
CountCtx *p;
p = sqlite3_aggregate_context(context, 0);
@@ -78303,8 +72519,8 @@ static void countFinalize(sqlite3_context *context){
** Routines to implement min() and max() aggregate functions.
*/
static void minmaxStep(
- sqlite3_context *context,
- int NotUsed,
+ sqlite3_context *context,
+ int NotUsed,
sqlite3_value **argv
){
Mem *pArg = (Mem *)argv[0];
@@ -78391,23 +72607,28 @@ static void groupConcatFinalize(sqlite3_context *context){
sqlite3_result_error_toobig(context);
}else if( pAccum->mallocFailed ){
sqlite3_result_error_nomem(context);
- }else{
- sqlite3_result_text(context, sqlite3StrAccumFinish(pAccum), -1,
+ }else{
+ sqlite3_result_text(context, sqlite3StrAccumFinish(pAccum), -1,
sqlite3_free);
}
}
}
/*
-** This routine does per-connection function registration. Most
-** of the built-in functions above are part of the global function set.
-** This routine only deals with those that are not global.
+** 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 sqlite3RegisterBuiltinFunctions(sqlite3 *db){
- int rc = sqlite3_overload_function(db, "MATCH", 2);
- assert( rc==SQLITE_NOMEM || rc==SQLITE_OK );
- if( rc==SQLITE_NOMEM ){
- db->mallocFailed = 1;
+#ifndef SQLITE_OMIT_ALTERTABLE
+ sqlite3AlterFunctions(db);
+#endif
+ if( !db->mallocFailed ){
+ int rc = sqlite3_overload_function(db, "MATCH", 2);
+ assert( rc==SQLITE_NOMEM || rc==SQLITE_OK );
+ if( rc==SQLITE_NOMEM ){
+ db->mallocFailed = 1;
+ }
}
}
@@ -78437,10 +72658,10 @@ SQLITE_PRIVATE void sqlite3RegisterLikeFunctions(sqlite3 *db, int caseSensitive)
}
sqlite3CreateFunc(db, "like", 2, SQLITE_ANY, pInfo, likeFunc, 0, 0);
sqlite3CreateFunc(db, "like", 3, SQLITE_ANY, pInfo, likeFunc, 0, 0);
- sqlite3CreateFunc(db, "glob", 2, SQLITE_ANY,
+ sqlite3CreateFunc(db, "glob", 2, SQLITE_ANY,
(struct compareInfo*)&globInfo, likeFunc, 0,0);
setLikeOptFlag(db, "glob", SQLITE_FUNC_LIKE | SQLITE_FUNC_CASE);
- setLikeOptFlag(db, "like",
+ setLikeOptFlag(db, "like",
caseSensitive ? (SQLITE_FUNC_LIKE | SQLITE_FUNC_CASE) : SQLITE_FUNC_LIKE);
}
@@ -78453,14 +72674,14 @@ SQLITE_PRIVATE void sqlite3RegisterLikeFunctions(sqlite3 *db, int caseSensitive)
*/
SQLITE_PRIVATE int sqlite3IsLikeFunction(sqlite3 *db, Expr *pExpr, int *pIsNocase, char *aWc){
FuncDef *pDef;
- if( pExpr->op!=TK_FUNCTION
- || !pExpr->x.pList
+ if( pExpr->op!=TK_FUNCTION
+ || !pExpr->x.pList
|| pExpr->x.pList->nExpr!=2
){
return 0;
}
assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
- pDef = sqlite3FindFunction(db, pExpr->u.zToken,
+ pDef = sqlite3FindFunction(db, pExpr->u.zToken,
sqlite3Strlen30(pExpr->u.zToken),
2, SQLITE_UTF8, 0);
if( NEVER(pDef==0) || (pDef->flags & SQLITE_FUNC_LIKE)==0 ){
@@ -78531,10 +72752,6 @@ SQLITE_PRIVATE void sqlite3RegisterGlobalFunctions(void){
FUNCTION(nullif, 2, 0, 1, nullifFunc ),
FUNCTION(sqlite_version, 0, 0, 0, versionFunc ),
FUNCTION(sqlite_source_id, 0, 0, 0, sourceidFunc ),
-#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
- FUNCTION(sqlite_compileoption_used,1, 0, 0, compileoptionusedFunc ),
- FUNCTION(sqlite_compileoption_get, 1, 0, 0, compileoptiongetFunc ),
-#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */
FUNCTION(quote, 1, 0, 0, quoteFunc ),
FUNCTION(last_insert_rowid, 0, 0, 0, last_insert_rowid),
FUNCTION(changes, 0, 0, 0, changes ),
@@ -78556,7 +72773,7 @@ SQLITE_PRIVATE void sqlite3RegisterGlobalFunctions(void){
AGGREGATE(count, 1, 0, 0, countStep, countFinalize ),
AGGREGATE(group_concat, 1, 0, 0, groupConcatStep, groupConcatFinalize),
AGGREGATE(group_concat, 2, 0, 0, groupConcatStep, groupConcatFinalize),
-
+
LIKEFUNC(glob, 2, &globInfo, SQLITE_FUNC_LIKE|SQLITE_FUNC_CASE),
#ifdef SQLITE_CASE_SENSITIVE_LIKE
LIKEFUNC(like, 2, &likeInfoAlt, SQLITE_FUNC_LIKE|SQLITE_FUNC_CASE),
@@ -78575,9 +72792,6 @@ SQLITE_PRIVATE void sqlite3RegisterGlobalFunctions(void){
sqlite3FuncDefInsert(pHash, &aFunc[i]);
}
sqlite3RegisterDateTimeFunctions();
-#ifndef SQLITE_OMIT_ALTERTABLE
- sqlite3AlterFunctions();
-#endif
}
/************** End of func.c ************************************************/
@@ -78605,25 +72819,25 @@ SQLITE_PRIVATE void sqlite3RegisterGlobalFunctions(void){
**
** Foreign keys in SQLite come in two flavours: deferred and immediate.
** If an immediate foreign key constraint is violated, SQLITE_CONSTRAINT
-** is returned and the current statement transaction rolled back. If a
-** deferred foreign key constraint is violated, no action is taken
-** immediately. However if the application attempts to commit the
+** is returned and the current statement transaction rolled back. If a
+** deferred foreign key constraint is violated, no action is taken
+** immediately. However if the application attempts to commit the
** transaction before fixing the constraint violation, the attempt fails.
**
** Deferred constraints are implemented using a simple counter associated
-** with the database handle. The counter is set to zero each time a
-** database transaction is opened. Each time a statement is executed
+** with the database handle. The counter is set to zero each time a
+** database transaction is opened. Each time a statement is executed
** that causes a foreign key violation, the counter is incremented. Each
** time a statement is executed that removes an existing violation from
** the database, the counter is decremented. When the transaction is
** committed, the commit fails if the current value of the counter is
** greater than zero. This scheme has two big drawbacks:
**
-** * When a commit fails due to a deferred foreign key constraint,
+** * When a commit fails due to a deferred foreign key constraint,
** there is no way to tell which foreign constraint is not satisfied,
** or which row it is not satisfied for.
**
-** * If the database contains foreign key violations when the
+** * If the database contains foreign key violations when the
** transaction is opened, this may cause the mechanism to malfunction.
**
** Despite these problems, this approach is adopted as it seems simpler
@@ -78635,26 +72849,26 @@ SQLITE_PRIVATE void sqlite3RegisterGlobalFunctions(void){
** the parent table for a match. If none is found increment the
** constraint counter.
**
-** I.2) For each FK for which the table is the parent table,
+** I.2) For each FK for which the table is the parent table,
** search the child table for rows that correspond to the new
** row in the parent table. Decrement the counter for each row
** found (as the constraint is now satisfied).
**
** DELETE operations:
**
-** D.1) For each FK for which the table is the child table,
-** search the parent table for a row that corresponds to the
-** deleted row in the child table. If such a row is not found,
+** D.1) For each FK for which the table is the child table,
+** search the parent table for a row that corresponds to the
+** deleted row in the child table. If such a row is not found,
** decrement the counter.
**
-** D.2) For each FK for which the table is the parent table, search
-** the child table for rows that correspond to the deleted row
+** D.2) For each FK for which the table is the parent table, search
+** the child table for rows that correspond to the deleted row
** in the parent table. For each found increment the counter.
**
** UPDATE operations:
**
** An UPDATE command requires that all 4 steps above are taken, but only
-** for FK constraints for which the affected columns are actually
+** for FK constraints for which the affected columns are actually
** modified (values must be compared at runtime).
**
** Note that I.1 and D.1 are very similar operations, as are I.2 and D.2.
@@ -78663,10 +72877,10 @@ SQLITE_PRIVATE void sqlite3RegisterGlobalFunctions(void){
** For the purposes of immediate FK constraints, the OR REPLACE conflict
** resolution is considered to delete rows before the new row is inserted.
** If a delete caused by OR REPLACE violates an FK constraint, an exception
-** is thrown, even if the FK constraint would be satisfied after the new
+** is thrown, even if the FK constraint would be satisfied after the new
** row is inserted.
**
-** Immediate constraints are usually handled similarly. The only difference
+** Immediate constraints are usually handled similarly. The only difference
** is that the counter used is stored as part of each individual statement
** object (struct Vdbe). If, after the statement has run, its immediate
** constraint counter is greater than zero, it returns SQLITE_CONSTRAINT
@@ -78676,7 +72890,7 @@ SQLITE_PRIVATE void sqlite3RegisterGlobalFunctions(void){
** INSERT violates a foreign key constraint. This is necessary as such
** an INSERT does not open a statement transaction.
**
-** TODO: How should dropping a table be handled? How should renaming a
+** TODO: How should dropping a table be handled? How should renaming a
** table be handled?
**
**
@@ -78687,7 +72901,7 @@ SQLITE_PRIVATE void sqlite3RegisterGlobalFunctions(void){
** for those two operations needs to know whether or not the operation
** requires any FK processing and, if so, which columns of the original
** row are required by the FK processing VDBE code (i.e. if FKs were
-** implemented using triggers, which of the old.* columns would be
+** implemented using triggers, which of the old.* columns would be
** accessed). No information is required by the code-generator before
** coding an INSERT operation. The functions used by the UPDATE/DELETE
** generation code to query for this information are:
@@ -78724,13 +72938,13 @@ SQLITE_PRIVATE void sqlite3RegisterGlobalFunctions(void){
/*
** A foreign key constraint requires that the key columns in the parent
** table are collectively subject to a UNIQUE or PRIMARY KEY constraint.
-** Given that pParent is the parent table for foreign key constraint pFKey,
-** search the schema a unique index on the parent key columns.
-**
-** If successful, zero is returned. If the parent key is an INTEGER PRIMARY
-** KEY column, then output variable *ppIdx is set to NULL. Otherwise, *ppIdx
-** is set to point to the unique index.
+** Given that pParent is the parent table for foreign key constraint pFKey,
+** search the schema a unique index on the parent key columns.
**
+** If successful, zero is returned. If the parent key is an INTEGER PRIMARY
+** KEY column, then output variable *ppIdx is set to NULL. Otherwise, *ppIdx
+** is set to point to the unique index.
+**
** If the parent key consists of a single column (the foreign key constraint
** is not a composite foreign key), output variable *paiCol is set to NULL.
** Otherwise, it is set to point to an allocated array of size N, where
@@ -78753,8 +72967,8 @@ SQLITE_PRIVATE void sqlite3RegisterGlobalFunctions(void){
** PRIMARY KEY, or
**
** 4) No parent key columns were provided explicitly as part of the
-** foreign key definition, and the PRIMARY KEY of the parent table
-** consists of a a different number of columns to the child key in
+** foreign key definition, and the PRIMARY KEY of the parent table
+** consists of a a different number of columns to the child key in
** the child table.
**
** then non-zero is returned, and a "foreign key mismatch" error loaded
@@ -78778,9 +72992,9 @@ static int locateFkeyIndex(
assert( !paiCol || *paiCol==0 );
assert( pParse );
- /* If this is a non-composite (single column) foreign key, check if it
- ** maps to the INTEGER PRIMARY KEY of table pParent. If so, leave *ppIdx
- ** and *paiCol set to zero and return early.
+ /* If this is a non-composite (single column) foreign key, check if it
+ ** maps to the INTEGER PRIMARY KEY of table pParent. If so, leave *ppIdx
+ ** and *paiCol set to zero and return early.
**
** Otherwise, for a composite foreign key (more than one column), allocate
** space for the aiCol array (returned via output parameter *paiCol).
@@ -78789,7 +73003,7 @@ static int locateFkeyIndex(
if( nCol==1 ){
/* The FK maps to the IPK if any of the following are true:
**
- ** 1) There is an INTEGER PRIMARY KEY column and the FK is implicitly
+ ** 1) There is an INTEGER PRIMARY KEY column and the FK is implicitly
** mapped to the primary key of table pParent, or
** 2) The FK is explicitly mapped to a column declared as INTEGER
** PRIMARY KEY.
@@ -78806,14 +73020,14 @@ static int locateFkeyIndex(
}
for(pIdx=pParent->pIndex; pIdx; pIdx=pIdx->pNext){
- if( pIdx->nColumn==nCol && pIdx->onError!=OE_None ){
+ if( pIdx->nColumn==nCol && pIdx->onError!=OE_None ){
/* pIdx is a UNIQUE index (or a PRIMARY KEY) and has the right number
** of columns. If each indexed column corresponds to a foreign key
** column of pFKey, then this index is a winner. */
if( zKey==0 ){
- /* If zKey is NULL, then this foreign key is implicitly mapped to
- ** the PRIMARY KEY of table pParent. The PRIMARY KEY index may be
+ /* If zKey is NULL, then this foreign key is implicitly mapped to
+ ** the PRIMARY KEY of table pParent. The PRIMARY KEY index may be
** identified by the test (Index.autoIndex==2). */
if( pIdx->autoIndex==2 ){
if( aiCol ){
@@ -78869,15 +73083,15 @@ static int locateFkeyIndex(
}
/*
-** This function is called when a row is inserted into or deleted from the
-** child table of foreign key constraint pFKey. If an SQL UPDATE is executed
+** This function is called when a row is inserted into or deleted from the
+** child table of foreign key constraint pFKey. If an SQL UPDATE is executed
** on the child table of pFKey, this function is invoked twice for each row
** affected - once to "delete" the old row, and then again to "insert" the
** new row.
**
** Each time it is called, this function generates VDBE code to locate the
-** row in the parent table that corresponds to the row being inserted into
-** or deleted from the child table. If the parent row can be found, no
+** row in the parent table that corresponds to the row being inserted into
+** or deleted from the child table. If the parent row can be found, no
** special action is taken. Otherwise, if the parent row can *not* be
** found in the parent table:
**
@@ -78891,7 +73105,7 @@ static int locateFkeyIndex(
**
** DELETE deferred Decrement the "deferred constraint counter".
**
-** These operations are identified in the comment at the top of this file
+** These operations are identified in the comment at the top of this file
** (fkey.c) as "I.1" and "D.1".
*/
static void fkLookupParent(
@@ -78914,8 +73128,8 @@ static void fkLookupParent(
** outstanding constraints to resolve. If there are not, there is no need
** to check if deleting this row resolves any outstanding violations.
**
- ** Check if any of the key columns in the child table row are NULL. If
- ** any are, then the constraint is considered satisfied. No need to
+ ** Check if any of the key columns in the child table row are NULL. If
+ ** any are, then the constraint is considered satisfied. No need to
** search for a matching row in the parent table. */
if( nIncr<0 ){
sqlite3VdbeAddOp2(v, OP_FkIfZero, pFKey->isDeferred, iOk);
@@ -78931,15 +73145,15 @@ static void fkLookupParent(
** column of the parent table (table pTab). */
int iMustBeInt; /* Address of MustBeInt instruction */
int regTemp = sqlite3GetTempReg(pParse);
-
- /* Invoke MustBeInt to coerce the child key value to an integer (i.e.
+
+ /* Invoke MustBeInt to coerce the child key value to an integer (i.e.
** apply the affinity of the parent key). If this fails, then there
** is no matching parent key. Before using MustBeInt, make a copy of
** the value. Otherwise, the value inserted into the child key column
** will have INTEGER affinity applied to it, which may not be correct. */
sqlite3VdbeAddOp2(v, OP_SCopy, aiCol[0]+1+regData, regTemp);
iMustBeInt = sqlite3VdbeAddOp2(v, OP_MustBeInt, regTemp, 0);
-
+
/* If the parent table is the same as the child table, and we are about
** to increment the constraint-counter (i.e. this is an INSERT operation),
** then check if the row being inserted matches itself. If so, do not
@@ -78947,7 +73161,7 @@ static void fkLookupParent(
if( pTab==pFKey->pFrom && nIncr==1 ){
sqlite3VdbeAddOp3(v, OP_Eq, regData, iOk, regTemp);
}
-
+
sqlite3OpenTable(pParse, iCur, iDb, pTab, OP_OpenRead);
sqlite3VdbeAddOp3(v, OP_NotExists, iCur, 0, regTemp);
sqlite3VdbeAddOp2(v, OP_Goto, 0, iOk);
@@ -78959,13 +73173,13 @@ static void fkLookupParent(
int regTemp = sqlite3GetTempRange(pParse, nCol);
int regRec = sqlite3GetTempReg(pParse);
KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIdx);
-
+
sqlite3VdbeAddOp3(v, OP_OpenRead, iCur, pIdx->tnum, iDb);
sqlite3VdbeChangeP4(v, -1, (char*)pKey, P4_KEYINFO_HANDOFF);
for(i=0; i<nCol; i++){
sqlite3VdbeAddOp2(v, OP_SCopy, aiCol[i]+1+regData, regTemp+i);
}
-
+
/* If the parent table is the same as the child table, and we are about
** to increment the constraint-counter (i.e. this is an INSERT operation),
** then check if the row being inserted matches itself. If so, do not
@@ -78979,11 +73193,11 @@ static void fkLookupParent(
}
sqlite3VdbeAddOp2(v, OP_Goto, 0, iOk);
}
-
+
sqlite3VdbeAddOp3(v, OP_MakeRecord, regTemp, nCol, regRec);
sqlite3VdbeChangeP4(v, -1, sqlite3IndexAffinityStr(v, pIdx), 0);
sqlite3VdbeAddOp4Int(v, OP_Found, iCur, iOk, regRec, 0);
-
+
sqlite3ReleaseTempReg(pParse, regRec);
sqlite3ReleaseTempRange(pParse, regTemp, nCol);
}
@@ -79011,7 +73225,7 @@ static void fkLookupParent(
/*
** This function is called to generate code executed when a row is deleted
-** from the parent table of foreign key constraint pFKey and, if pFKey is
+** from the parent table of foreign key constraint pFKey and, if pFKey is
** deferred, when a row is inserted into the same table. When generating
** code for an SQL UPDATE operation, this function may be called twice -
** once to "delete" the old row and once to "insert" the new row.
@@ -79034,7 +73248,7 @@ static void fkLookupParent(
**
** INSERT deferred Decrement the "deferred constraint counter".
**
-** These operations are identified in the comment at the top of this file
+** These operations are identified in the comment at the top of this file
** (fkey.c) as "I.2" and "D.2".
*/
static void fkScanChildren(
@@ -79073,7 +73287,7 @@ static void fkScanChildren(
Expr *pLeft; /* Value from parent table row */
Expr *pRight; /* Column ref to child table */
Expr *pEq; /* Expression (pLeft = pRight) */
- int iCol; /* Index of column in child table */
+ int iCol; /* Index of column in child table */
const char *zCol; /* Name of column in child table */
pLeft = sqlite3Expr(db, TK_REGISTER, 0);
@@ -79102,7 +73316,7 @@ static void fkScanChildren(
/* If the child table is the same as the parent table, and this scan
** is taking place as part of a DELETE operation (operation D.2), omit the
- ** row being deleted from the scan by adding ($rowid != rowid) to the WHERE
+ ** row being deleted from the scan by adding ($rowid != rowid) to the WHERE
** clause, where $rowid is the rowid of the row being deleted. */
if( pTab==pFKey->pFrom && nIncr>0 ){
Expr *pEq; /* Expression (pLeft = pRight) */
@@ -79166,7 +73380,7 @@ SQLITE_PRIVATE FKey *sqlite3FkReferences(Table *pTab){
}
/*
-** The second argument is a Trigger structure allocated by the
+** The second argument is a Trigger structure allocated by the
** fkActionTrigger() routine. This function deletes the Trigger structure
** and all of its sub-components.
**
@@ -79194,7 +73408,7 @@ static void fkTriggerDelete(sqlite3 *dbMem, Trigger *p){
**
** (a) The table is the parent table of a FK constraint, or
** (b) The table is the child table of a deferred FK constraint and it is
-** determined at runtime that there are outstanding deferred FK
+** determined at runtime that there are outstanding deferred FK
** constraint violations in the database,
**
** then the equivalent of "DELETE FROM <tbl>" is executed before dropping
@@ -79210,7 +73424,7 @@ SQLITE_PRIVATE void sqlite3FkDropTable(Parse *pParse, SrcList *pName, Table *pTa
assert( v ); /* VDBE has already been allocated */
if( sqlite3FkReferences(pTab)==0 ){
/* Search for a deferred foreign key constraint for which this table
- ** is the child table. If one cannot be found, return without
+ ** is the child table. If one cannot be found, return without
** generating any VDBE code. If one can be found, then jump over
** the entire DELETE if there are no outstanding deferred constraints
** when this statement is run. */
@@ -79227,7 +73441,7 @@ SQLITE_PRIVATE void sqlite3FkDropTable(Parse *pParse, SrcList *pName, Table *pTa
sqlite3DeleteFrom(pParse, sqlite3SrcListDup(db, pName, 0), 0);
pParse->disableTriggers = 0;
- /* If the DELETE has generated immediate foreign key constraint
+ /* If the DELETE has generated immediate foreign key constraint
** violations, halt the VDBE and return an error at this point, before
** any modifications to the schema are made. This is because statement
** transactions are not able to rollback schema changes. */
@@ -79244,7 +73458,7 @@ SQLITE_PRIVATE void sqlite3FkDropTable(Parse *pParse, SrcList *pName, Table *pTa
/*
** This function is called when inserting, deleting or updating a row of
-** table pTab to generate VDBE code to perform foreign key constraint
+** table pTab to generate VDBE code to perform foreign key constraint
** processing for the operation.
**
** For a DELETE operation, parameter regOld is passed the index of the
@@ -79260,11 +73474,11 @@ SQLITE_PRIVATE void sqlite3FkDropTable(Parse *pParse, SrcList *pName, Table *pTa
** For an UPDATE operation, this function is called twice. Once before
** the original record is deleted from the table using the calling convention
** described for DELETE. Then again after the original record is deleted
-** but before the new record is inserted using the INSERT convention.
+** but before the new record is inserted using the INSERT convention.
*/
SQLITE_PRIVATE void sqlite3FkCheck(
Parse *pParse, /* Parse context */
- Table *pTab, /* Row is being deleted from this table */
+ Table *pTab, /* Row is being deleted from this table */
int regOld, /* Previous row data is stored here */
int regNew /* New row data is stored here */
){
@@ -79296,9 +73510,9 @@ SQLITE_PRIVATE void sqlite3FkCheck(
int i;
int isIgnore = 0;
- /* Find the parent table of this foreign key. Also find a unique index
- ** on the parent key columns in the parent table. If either of these
- ** schema items cannot be located, set an error in pParse and return
+ /* Find the parent table of this foreign key. Also find a unique index
+ ** on the parent key columns in the parent table. If either of these
+ ** schema items cannot be located, set an error in pParse and return
** early. */
if( pParse->disableTriggers ){
pTo = sqlite3FindTable(db, pFKey->zTo, zDb);
@@ -79322,7 +73536,7 @@ SQLITE_PRIVATE void sqlite3FkCheck(
aiCol[i] = -1;
}
#ifndef SQLITE_OMIT_AUTHORIZATION
- /* Request permission to read the parent key columns. If the
+ /* Request permission to read the parent key columns. If the
** authorization callback returns SQLITE_IGNORE, behave as if any
** values read from the parent table are NULL. */
if( db->xAuth ){
@@ -79334,21 +73548,21 @@ SQLITE_PRIVATE void sqlite3FkCheck(
#endif
}
- /* Take a shared-cache advisory read-lock on the parent table. Allocate
- ** a cursor to use to search the unique index on the parent key columns
+ /* Take a shared-cache advisory read-lock on the parent table. Allocate
+ ** a cursor to use to search the unique index on the parent key columns
** in the parent table. */
sqlite3TableLock(pParse, iDb, pTo->tnum, 0, pTo->zName);
pParse->nTab++;
if( regOld!=0 ){
/* A row is being removed from the child table. Search for the parent.
- ** If the parent does not exist, removing the child row resolves an
+ ** If the parent does not exist, removing the child row resolves an
** outstanding foreign key constraint violation. */
fkLookupParent(pParse, iDb, pTo, pIdx, pFKey, aiCol, regOld, -1,isIgnore);
}
if( regNew!=0 ){
/* A row is being added to the child table. If a parent row cannot
- ** be found, adding the child row has violated the FK constraint. */
+ ** be found, adding the child row has violated the FK constraint. */
fkLookupParent(pParse, iDb, pTo, pIdx, pFKey, aiCol, regNew, +1,isIgnore);
}
@@ -79374,7 +73588,7 @@ SQLITE_PRIVATE void sqlite3FkCheck(
}
assert( aiCol || pFKey->nCol==1 );
- /* Create a SrcList structure containing a single table (the table
+ /* Create a SrcList structure containing a single table (the table
** the foreign key that refers to this table is attached to). This
** is required for the sqlite3WhereXXX() interface. */
pSrc = sqlite3SrcListAppend(db, 0, 0, 0);
@@ -79384,13 +73598,13 @@ SQLITE_PRIVATE void sqlite3FkCheck(
pItem->zName = pFKey->pFrom->zName;
pItem->pTab->nRef++;
pItem->iCursor = pParse->nTab++;
-
+
if( regNew!=0 ){
fkScanChildren(pParse, pSrc, pTab, pIdx, pFKey, aiCol, regNew, -1);
}
if( regOld!=0 ){
/* If there is a RESTRICT action configured for the current operation
- ** on the parent table of this FK, then throw an exception
+ ** on the parent table of this FK, then throw an exception
** immediately if the FK constraint is violated, even if this is a
** deferred trigger. That's what RESTRICT means. To defer checking
** the constraint, the FK should specify NO ACTION (represented
@@ -79407,7 +73621,7 @@ SQLITE_PRIVATE void sqlite3FkCheck(
#define COLUMN_MASK(x) (((x)>31) ? 0xffffffff : ((u32)1<<(x)))
/*
-** This function is called before generating code to update or delete a
+** This function is called before generating code to update or delete a
** row contained in table pTab.
*/
SQLITE_PRIVATE u32 sqlite3FkOldmask(
@@ -79433,17 +73647,17 @@ SQLITE_PRIVATE u32 sqlite3FkOldmask(
}
/*
-** This function is called before generating code to update or delete a
+** This function is called before generating code to update or delete a
** row contained in table pTab. If the operation is a DELETE, then
** parameter aChange is passed a NULL value. For an UPDATE, aChange points
** to an array of size N, where N is the number of columns in table pTab.
-** If the i'th column is not modified by the UPDATE, then the corresponding
+** If the i'th column is not modified by the UPDATE, then the corresponding
** entry in the aChange[] array is set to -1. If the column is modified,
** the value is 0 or greater. Parameter chngRowid is set to true if the
** UPDATE statement modifies the rowid fields of the table.
**
** If any foreign key processing will be required, this function returns
-** true. If there is no foreign key related processing, this function
+** true. If there is no foreign key related processing, this function
** returns false.
*/
SQLITE_PRIVATE int sqlite3FkRequired(
@@ -79454,8 +73668,8 @@ SQLITE_PRIVATE int sqlite3FkRequired(
){
if( pParse->db->flags&SQLITE_ForeignKeys ){
if( !aChange ){
- /* A DELETE operation. Foreign key processing is required if the
- ** table in question is either the child or parent table for any
+ /* A DELETE operation. Foreign key processing is required if the
+ ** table in question is either the child or parent table for any
** foreign key constraint. */
return (sqlite3FkReferences(pTab) || pTab->pFKey);
}else{
@@ -79493,7 +73707,7 @@ SQLITE_PRIVATE int sqlite3FkRequired(
}
/*
-** This function is called when an UPDATE or DELETE operation is being
+** This function is called when an UPDATE or DELETE operation is being
** compiled on table pTab, which is the parent table of foreign-key pFKey.
** If the current operation is an UPDATE, then the pChanges parameter is
** passed a pointer to the list of columns being modified. If it is a
@@ -79505,7 +73719,7 @@ SQLITE_PRIVATE int sqlite3FkRequired(
** returned (these actions require no special handling by the triggers
** sub-system, code for them is created by fkScanChildren()).
**
-** For example, if pFKey is the foreign key and pTab is table "p" in
+** For example, if pFKey is the foreign key and pTab is table "p" in
** the following schema:
**
** CREATE TABLE p(pk PRIMARY KEY);
@@ -79518,7 +73732,7 @@ SQLITE_PRIVATE int sqlite3FkRequired(
** END;
**
** The returned pointer is cached as part of the foreign key object. It
-** is eventually freed along with the rest of the foreign key object by
+** is eventually freed along with the rest of the foreign key object by
** sqlite3FkDelete().
*/
static Trigger *fkActionTrigger(
@@ -79572,7 +73786,7 @@ static Trigger *fkActionTrigger(
** that the affinity and collation sequence associated with the
** parent table are used for the comparison. */
pEq = sqlite3PExpr(pParse, TK_EQ,
- sqlite3PExpr(pParse, TK_DOT,
+ sqlite3PExpr(pParse, TK_DOT,
sqlite3PExpr(pParse, TK_ID, 0, 0, &tOld),
sqlite3PExpr(pParse, TK_ID, 0, 0, &tToCol)
, 0),
@@ -79587,22 +73801,22 @@ static Trigger *fkActionTrigger(
*/
if( pChanges ){
pEq = sqlite3PExpr(pParse, TK_IS,
- sqlite3PExpr(pParse, TK_DOT,
+ sqlite3PExpr(pParse, TK_DOT,
sqlite3PExpr(pParse, TK_ID, 0, 0, &tOld),
sqlite3PExpr(pParse, TK_ID, 0, 0, &tToCol),
0),
- sqlite3PExpr(pParse, TK_DOT,
+ sqlite3PExpr(pParse, TK_DOT,
sqlite3PExpr(pParse, TK_ID, 0, 0, &tNew),
sqlite3PExpr(pParse, TK_ID, 0, 0, &tToCol),
0),
0);
pWhen = sqlite3ExprAnd(db, pWhen, pEq);
}
-
+
if( action!=OE_Restrict && (action!=OE_Cascade || pChanges) ){
Expr *pNew;
if( action==OE_Cascade ){
- pNew = sqlite3PExpr(pParse, TK_DOT,
+ pNew = sqlite3PExpr(pParse, TK_DOT,
sqlite3PExpr(pParse, TK_ID, 0, 0, &tNew),
sqlite3PExpr(pParse, TK_ID, 0, 0, &tToCol)
, 0);
@@ -79627,7 +73841,7 @@ static Trigger *fkActionTrigger(
if( action==OE_Restrict ){
Token tFrom;
- Expr *pRaise;
+ Expr *pRaise;
tFrom.z = zFrom;
tFrom.n = nFrom;
@@ -79635,7 +73849,7 @@ static Trigger *fkActionTrigger(
if( pRaise ){
pRaise->affinity = OE_Abort;
}
- pSelect = sqlite3SelectNew(pParse,
+ pSelect = sqlite3SelectNew(pParse,
sqlite3ExprListAppend(pParse, 0, pRaise),
sqlite3SrcListAppend(db, 0, &tFrom, 0),
pWhere,
@@ -79652,7 +73866,7 @@ static Trigger *fkActionTrigger(
enableLookaside = db->lookaside.bEnabled;
db->lookaside.bEnabled = 0;
- pTrigger = (Trigger *)sqlite3DbMallocZero(db,
+ pTrigger = (Trigger *)sqlite3DbMallocZero(db,
sizeof(Trigger) + /* struct Trigger */
sizeof(TriggerStep) + /* Single step in trigger program */
nFrom + 1 /* Space for pStep->target.z */
@@ -79662,7 +73876,7 @@ static Trigger *fkActionTrigger(
pStep->target.z = (char *)&pStep[1];
pStep->target.n = nFrom;
memcpy((char *)pStep->target.z, zFrom, nFrom);
-
+
pStep->pWhere = sqlite3ExprDup(db, pWhere, EXPRDUP_REDUCE);
pStep->pExprList = sqlite3ExprListDup(db, pList, EXPRDUP_REDUCE);
pStep->pSelect = sqlite3SelectDup(db, pSelect, EXPRDUP_REDUCE);
@@ -79686,12 +73900,12 @@ static Trigger *fkActionTrigger(
switch( action ){
case OE_Restrict:
- pStep->op = TK_SELECT;
+ pStep->op = TK_SELECT;
break;
- case OE_Cascade:
- if( !pChanges ){
- pStep->op = TK_DELETE;
- break;
+ case OE_Cascade:
+ if( !pChanges ){
+ pStep->op = TK_DELETE;
+ break;
}
default:
pStep->op = TK_UPDATE;
@@ -79716,9 +73930,9 @@ SQLITE_PRIVATE void sqlite3FkActions(
ExprList *pChanges, /* Change-list for UPDATE, NULL for DELETE */
int regOld /* Address of array containing old row */
){
- /* If foreign-key support is enabled, iterate through all FKs that
- ** refer to table pTab. If there is an action associated with the FK
- ** for this operation (either update or delete), invoke the associated
+ /* If foreign-key support is enabled, iterate through all FKs that
+ ** refer to table pTab. If there is an action associated with the FK
+ ** for this operation (either update or delete), invoke the associated
** trigger sub-program. */
if( pParse->db->flags&SQLITE_ForeignKeys ){
FKey *pFKey; /* Iterator variable */
@@ -79812,7 +74026,7 @@ SQLITE_PRIVATE void sqlite3OpenTable(
/*
** Return a pointer to the column affinity string associated with index
-** pIdx. A column affinity string has one character for each column in
+** pIdx. A column affinity string has one character for each column in
** the table, according to the affinity of the column:
**
** Character Column affinity
@@ -79854,7 +74068,7 @@ SQLITE_PRIVATE const char *sqlite3IndexAffinityStr(Vdbe *v, Index *pIdx){
pIdx->zColAff[n++] = SQLITE_AFF_NONE;
pIdx->zColAff[n] = 0;
}
-
+
return pIdx->zColAff;
}
@@ -79874,7 +74088,7 @@ SQLITE_PRIVATE const char *sqlite3IndexAffinityStr(Vdbe *v, Index *pIdx){
*/
SQLITE_PRIVATE void sqlite3TableAffinityStr(Vdbe *v, Table *pTab){
/* The first time a column affinity string for a particular table
- ** is required, it is allocated and populated here. It is then
+ ** is required, it is allocated and populated here. It is then
** stored as a member of the Table structure for subsequent use.
**
** The column affinity string will eventually be deleted by
@@ -79905,9 +74119,9 @@ SQLITE_PRIVATE void sqlite3TableAffinityStr(Vdbe *v, Table *pTab){
/*
** Return non-zero if the table pTab in database iDb or any of its indices
** have been opened at any point in the VDBE program beginning at location
-** iStartAddr throught the end of the program. This is used to see if
-** a statement of the form "INSERT INTO <iDb, pTab> SELECT ..." can
-** run without using temporary table for the results of the SELECT.
+** iStartAddr throught the end of the program. This is used to see if
+** a statement of the form "INSERT INTO <iDb, pTab> SELECT ..." can
+** run without using temporary table for the results of the SELECT.
*/
static int readsTable(Parse *p, int iStartAddr, int iDb, Table *pTab){
Vdbe *v = sqlite3GetVdbe(p);
@@ -79994,7 +74208,7 @@ static int autoIncBegin(
/*
** This routine generates code that will initialize all of the
-** register used by the autoincrement tracker.
+** register used by the autoincrement tracker.
*/
SQLITE_PRIVATE void sqlite3AutoincrementBegin(Parse *pParse){
AutoincInfo *p; /* Information about an AUTOINCREMENT */
@@ -80292,7 +74506,7 @@ SQLITE_PRIVATE void sqlite3Insert(
assert( (pTrigger && tmask) || (pTrigger==0 && tmask==0) );
/* If pTab is really a view, make sure it has been initialized.
- ** ViewGetColumnNames() is a no-op if pTab is not a view (or virtual
+ ** ViewGetColumnNames() is a no-op if pTab is not a view (or virtual
** module table).
*/
if( sqlite3ViewGetColumnNames(pParse, pTab) ){
@@ -80300,7 +74514,7 @@ SQLITE_PRIVATE void sqlite3Insert(
}
/* Ensure that:
- * (a) the table is not read-only,
+ * (a) the table is not read-only,
* (b) that if it is a view then ON INSERT triggers exist
*/
if( sqlite3IsReadOnly(pParse, pTab, tmask) ){
@@ -80398,7 +74612,7 @@ SQLITE_PRIVATE void sqlite3Insert(
** the destination table (template 3).
**
** A temp table must be used if the table being updated is also one
- ** of the tables being read by the SELECT statement. Also use a
+ ** of the tables being read by the SELECT statement. Also use a
** temp table in the case of row triggers.
*/
if( pTrigger || readsTable(pParse, addrSelect, iDb, pTab) ){
@@ -80462,7 +74676,7 @@ SQLITE_PRIVATE void sqlite3Insert(
}
}
if( pColumn==0 && nColumn && nColumn!=(pTab->nCol-nHidden) ){
- sqlite3ErrorMsg(pParse,
+ sqlite3ErrorMsg(pParse,
"table %S has %d columns but %d values were supplied",
pTabList, 0, pTab->nCol-nHidden, nColumn);
goto insert_cleanup;
@@ -80473,7 +74687,7 @@ SQLITE_PRIVATE void sqlite3Insert(
}
/* If the INSERT statement included an IDLIST term, then make sure
- ** all elements of the IDLIST really are columns of the table and
+ ** all elements of the IDLIST really are columns of the table and
** remember the column indices.
**
** If the table has an INTEGER PRIMARY KEY column and that column
@@ -80517,7 +74731,7 @@ SQLITE_PRIVATE void sqlite3Insert(
if( pColumn==0 && nColumn>0 ){
keyColumn = pTab->iPKey;
}
-
+
/* Initialize the count of rows to be inserted
*/
if( db->flags & SQLITE_CountRows ){
@@ -80622,10 +74836,10 @@ SQLITE_PRIVATE void sqlite3Insert(
if( pColumn->a[j].idx==i ) break;
}
}
- if( (!useTempTable && !pList) || (pColumn && j>=pColumn->nId) ){
+ if( pColumn && j>=pColumn->nId ){
sqlite3ExprCode(pParse, pTab->aCol[i].pDflt, regCols+i+1);
}else if( useTempTable ){
- sqlite3VdbeAddOp3(v, OP_Column, srcTab, j, regCols+i+1);
+ sqlite3VdbeAddOp3(v, OP_Column, srcTab, j, regCols+i+1);
}else{
assert( pSelect==0 ); /* Otherwise useTempTable is true */
sqlite3ExprCodeAndCache(pParse, pList->a[j].pExpr, regCols+i+1);
@@ -80643,7 +74857,7 @@ SQLITE_PRIVATE void sqlite3Insert(
}
/* Fire BEFORE or INSTEAD OF triggers */
- sqlite3CodeRowTrigger(pParse, pTrigger, TK_INSERT, 0, TRIGGER_BEFORE,
+ sqlite3CodeRowTrigger(pParse, pTrigger, TK_INSERT, 0, TRIGGER_BEFORE,
pTab, regCols-pTab->nCol-1, onError, endOfLoop);
sqlite3ReleaseTempRange(pParse, regCols, pTab->nCol+1);
@@ -80652,7 +74866,7 @@ SQLITE_PRIVATE void sqlite3Insert(
/* Push the record number for the new entry onto the stack. The
** record number is a randomly generate integer created by NewRowid
** except when the table has an INTEGER PRIMARY KEY column, in which
- ** case the record number is the same as that column.
+ ** case the record number is the same as that column.
*/
if( !isView ){
if( IsVirtual(pTab) ){
@@ -80729,7 +74943,7 @@ SQLITE_PRIVATE void sqlite3Insert(
if( j<0 || nColumn==0 || (pColumn && j>=pColumn->nId) ){
sqlite3ExprCode(pParse, pTab->aCol[i].pDflt, iRegStore);
}else if( useTempTable ){
- sqlite3VdbeAddOp3(v, OP_Column, srcTab, j, iRegStore);
+ sqlite3VdbeAddOp3(v, OP_Column, srcTab, j, iRegStore);
}else if( pSelect ){
sqlite3VdbeAddOp2(v, OP_SCopy, regFromSelect+j, iRegStore);
}else{
@@ -80768,7 +74982,7 @@ SQLITE_PRIVATE void sqlite3Insert(
if( pTrigger ){
/* Code AFTER triggers */
- sqlite3CodeRowTrigger(pParse, pTrigger, TK_INSERT, 0, TRIGGER_AFTER,
+ sqlite3CodeRowTrigger(pParse, pTrigger, TK_INSERT, 0, TRIGGER_AFTER,
pTab, regData-2-pTab->nCol, onError, endOfLoop);
}
@@ -80803,7 +75017,7 @@ insert_end:
}
/*
- ** Return the number of rows inserted. If this routine is
+ ** Return the number of rows inserted. If this routine is
** generating code because of a call to sqlite3NestedParse(), do not
** invoke the callback function.
*/
@@ -80853,10 +75067,10 @@ insert_cleanup:
** If isUpdate is true and rowidChng is non-zero, then rowidChng contains
** the address of a register containing the rowid before the update takes
** place. isUpdate is true for UPDATEs and false for INSERTs. If isUpdate
-** is false, indicating an INSERT statement, then a non-zero rowidChng
+** is false, indicating an INSERT statement, then a non-zero rowidChng
** indicates that the rowid was explicitly specified as part of the
** INSERT statement. If rowidChng is false, it means that the rowid is
-** computed automatically in an insert or that the rowid value is not
+** computed automatically in an insert or that the rowid value is not
** modified by an update.
**
** The code generated by this routine store new index entries into
@@ -81013,7 +75227,7 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
}else if( onError==OE_Default ){
onError = OE_Abort;
}
-
+
if( isUpdate ){
j2 = sqlite3VdbeAddOp3(v, OP_Eq, regRowid, 0, rowidChng);
}
@@ -81037,33 +75251,19 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
** the triggers and remove both the table and index b-tree entries.
**
** Otherwise, if there are no triggers or the recursive-triggers
- ** flag is not set, but the table has one or more indexes, call
- ** GenerateRowIndexDelete(). This removes the index b-tree entries
- ** only. The table b-tree entry will be replaced by the new entry
- ** when it is inserted.
- **
- ** If either GenerateRowDelete() or GenerateRowIndexDelete() is called,
- ** also invoke MultiWrite() to indicate that this VDBE may require
- ** statement rollback (if the statement is aborted after the delete
- ** takes place). Earlier versions called sqlite3MultiWrite() regardless,
- ** but being more selective here allows statements like:
- **
- ** REPLACE INTO t(rowid) VALUES($newrowid)
- **
- ** to run without a statement journal if there are no indexes on the
- ** table.
- */
+ ** flag is not set, call GenerateRowIndexDelete(). This removes
+ ** the index b-tree entries only. The table b-tree entry will be
+ ** replaced by the new entry when it is inserted. */
Trigger *pTrigger = 0;
if( pParse->db->flags&SQLITE_RecTriggers ){
pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0);
}
+ sqlite3MultiWrite(pParse);
if( pTrigger || sqlite3FkRequired(pParse, pTab, 0, 0) ){
- sqlite3MultiWrite(pParse);
sqlite3GenerateRowDelete(
pParse, pTab, baseCur, regRowid, 0, pTrigger, OE_Replace
);
- }else if( pTab->pIndex ){
- sqlite3MultiWrite(pParse);
+ }else{
sqlite3GenerateRowIndexDelete(pParse, pTab, baseCur, 0);
}
seenReplace = 1;
@@ -81108,7 +75308,7 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
/* Find out what action to take in case there is an indexing conflict */
onError = pIdx->onError;
- if( onError==OE_None ){
+ if( onError==OE_None ){
sqlite3ReleaseTempRange(pParse, regIdx, pIdx->nColumn+1);
continue; /* pIdx is not a UNIQUE index */
}
@@ -81121,7 +75321,7 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
if( onError==OE_Ignore ) onError = OE_Replace;
else if( onError==OE_Fail ) onError = OE_Abort;
}
-
+
/* Check to see if the new index entry will be unique */
regR = sqlite3GetTempReg(pParse);
sqlite3VdbeAddOp2(v, OP_SCopy, regOldRowid, regR);
@@ -81180,7 +75380,7 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
sqlite3VdbeJumpHere(v, j3);
sqlite3ReleaseTempReg(pParse, regR);
}
-
+
if( pbMayReplace ){
*pbMayReplace = seenReplace;
}
@@ -81505,7 +75705,7 @@ static int xferOptimization(
}
}
#ifndef SQLITE_OMIT_CHECK
- if( pDest->pCheck && sqlite3ExprCompare(pSrc->pCheck, pDest->pCheck) ){
+ if( pDest->pCheck && !sqlite3ExprCompare(pSrc->pCheck, pDest->pCheck) ){
return 0; /* Tables have different CHECK constraints. Ticket #2252 */
}
#endif
@@ -81648,7 +75848,6 @@ SQLITE_API int sqlite3_exec(
int nRetry = 0; /* Number of retry attempts */
int callbackIsInit; /* True if callback data is initialized */
- if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT;
if( zSql==0 ) zSql = "";
sqlite3_mutex_enter(db->mutex);
@@ -81677,7 +75876,7 @@ SQLITE_API int sqlite3_exec(
rc = sqlite3_step(pStmt);
/* Invoke the callback function if required */
- if( xCallback && (SQLITE_ROW==rc ||
+ if( xCallback && (SQLITE_ROW==rc ||
(SQLITE_DONE==rc && !callbackIsInit
&& db->flags&SQLITE_NullCallback)) ){
if( !callbackIsInit ){
@@ -81787,7 +75986,7 @@ exec_out:
** This header file defines the SQLite interface for use by
** shared libraries that want to be imported as extensions into
** an SQLite instance. Shared libraries that intend to be loaded
-** as extensions by SQLite should #include this file instead of
+** as extensions by SQLite should #include this file instead of
** sqlite3.h.
*/
#ifndef _SQLITE3EXT_H_
@@ -82421,8 +76620,8 @@ static const sqlite3_api_routines sqlite3Apis = {
sqlite3_memory_highwater,
sqlite3_memory_used,
#ifdef SQLITE_MUTEX_OMIT
- 0,
- 0,
+ 0,
+ 0,
0,
0,
0,
@@ -82471,7 +76670,7 @@ static const sqlite3_api_routines sqlite3Apis = {
**
** Return SQLITE_OK on success and SQLITE_ERROR if something goes wrong.
**
-** If an error occurs and pzErrMsg is not 0, then fill *pzErrMsg with
+** If an error occurs and pzErrMsg is not 0, then fill *pzErrMsg with
** error message text. The calling function should free this memory
** by calling sqlite3DbFree(db, ).
*/
@@ -82512,7 +76711,7 @@ static int sqlite3LoadExtension(
if( pzErrMsg ){
zErrmsg = sqlite3StackAllocZero(db, nMsg);
if( zErrmsg ){
- sqlite3_snprintf(nMsg, zErrmsg,
+ sqlite3_snprintf(nMsg, zErrmsg,
"unable to open shared library [%s]", zFile);
sqlite3OsDlError(pVfs, nMsg-1, zErrmsg);
*pzErrMsg = sqlite3DbStrDup(0, zErrmsg);
@@ -82623,7 +76822,7 @@ static const sqlite3_api_routines sqlite3Apis = { 0 };
*/
typedef struct sqlite3AutoExtList sqlite3AutoExtList;
static SQLITE_WSD struct sqlite3AutoExtList {
- int nExt; /* Number of entries in aExt[] */
+ int nExt; /* Number of entries in aExt[] */
void (**aExt)(void); /* Pointers to the extension init functions */
} sqlite3Autoext = { 0, 0 };
@@ -82764,7 +76963,7 @@ SQLITE_PRIVATE void sqlite3AutoLoadExtensions(sqlite3 *db){
/*
** Interpret the given string as a safety level. Return 0 for OFF,
-** 1 for ON or NORMAL and 2 for FULL. Return 1 for an empty or
+** 1 for ON or NORMAL and 2 for FULL. Return 1 for an empty or
** unrecognized string argument.
**
** Note that the values returned are one less that the values that
@@ -82813,7 +77012,7 @@ static int getLockingMode(const char *z){
/*
** Interpret the given string as an auto-vacuum mode value.
**
-** The following strings, "none", "full" and "incremental" are
+** The following strings, "none", "full" and "incremental" are
** acceptable, as are their numeric equivalents: 0, 1 and 2 respectively.
*/
static int getAutoVacuum(const char *z){
@@ -82918,9 +77117,6 @@ static int flagPragma(Parse *pParse, const char *zLeft, const char *zRight){
{ "legacy_file_format", SQLITE_LegacyFileFmt },
{ "fullfsync", SQLITE_FullFSync },
{ "reverse_unordered_selects", SQLITE_ReverseOrder },
-#ifndef SQLITE_OMIT_AUTOMATIC_INDEX
- { "automatic_index", SQLITE_AutoIndex },
-#endif
#ifdef SQLITE_DEBUG
{ "sql_trace", SQLITE_SqlTrace },
{ "vdbe_listing", SQLITE_VdbeListing },
@@ -82969,7 +77165,7 @@ static int flagPragma(Parse *pParse, const char *zLeft, const char *zRight){
db->flags &= ~mask;
}
- /* Many of the flag-pragmas modify the code generated by the SQL
+ /* Many of the flag-pragmas modify the code generated by the SQL
** compiler (eg. count_changes). So add an opcode to expire all
** compiled SQL statements after modifying a pragma value.
*/
@@ -82995,40 +77191,15 @@ static const char *actionName(u8 action){
case OE_SetDflt: zName = "SET DEFAULT"; break;
case OE_Cascade: zName = "CASCADE"; break;
case OE_Restrict: zName = "RESTRICT"; break;
- default: zName = "NO ACTION";
+ default: zName = "NO ACTION";
assert( action==OE_None ); break;
}
return zName;
}
#endif
-
/*
-** Parameter eMode must be one of the PAGER_JOURNALMODE_XXX constants
-** defined in pager.h. This function returns the associated lowercase
-** journal-mode name.
-*/
-SQLITE_PRIVATE const char *sqlite3JournalModename(int eMode){
- static char * const azModeName[] = {
- "delete", "persist", "off", "truncate", "memory"
-#ifndef SQLITE_OMIT_WAL
- , "wal"
-#endif
- };
- assert( PAGER_JOURNALMODE_DELETE==0 );
- assert( PAGER_JOURNALMODE_PERSIST==1 );
- assert( PAGER_JOURNALMODE_OFF==2 );
- assert( PAGER_JOURNALMODE_TRUNCATE==3 );
- assert( PAGER_JOURNALMODE_MEMORY==4 );
- assert( PAGER_JOURNALMODE_WAL==5 );
- assert( eMode>=0 && eMode<=ArraySize(azModeName) );
-
- if( eMode==ArraySize(azModeName) ) return 0;
- return azModeName[eMode];
-}
-
-/*
-** Process a pragma statement.
+** Process a pragma statement.
**
** Pragmas are of this form:
**
@@ -83043,7 +77214,7 @@ SQLITE_PRIVATE const char *sqlite3JournalModename(int eMode){
** id and pId2 is any empty string.
*/
SQLITE_PRIVATE void sqlite3Pragma(
- Parse *pParse,
+ Parse *pParse,
Token *pId1, /* First part of [database.]id field */
Token *pId2, /* Second part of [database.]id field, or NULL */
Token *pValue, /* Token for <value>, or NULL */
@@ -83067,8 +77238,8 @@ SQLITE_PRIVATE void sqlite3Pragma(
if( iDb<0 ) return;
pDb = &db->aDb[iDb];
- /* If the temp database has been explicitly named as part of the
- ** pragma, make sure it is open.
+ /* If the temp database has been explicitly named as part of the
+ ** pragma, make sure it is open.
*/
if( iDb==1 && sqlite3OpenTempDatabase(pParse) ){
return;
@@ -83087,7 +77258,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
if( sqlite3AuthCheck(pParse, SQLITE_PRAGMA, zLeft, zRight, zDb) ){
goto pragma_out;
}
-
+
#ifndef SQLITE_OMIT_PAGER_PRAGMAS
/*
** PRAGMA [database.]default_cache_size
@@ -83099,11 +77270,11 @@ SQLITE_PRIVATE void sqlite3Pragma(
** page cache size value and the persistent page cache size value
** stored in the database file.
**
- ** Older versions of SQLite would set the default cache size to a
- ** negative number to indicate synchronous=OFF. These days, synchronous
- ** is always on by default regardless of the sign of the default cache
- ** size. But continue to take the absolute value of the default cache
- ** size of historical compatibility.
+ ** The default cache size is stored in meta-value 2 of page 1 of the
+ ** database file. The cache size is actually the absolute value of
+ ** this memory location. The sign of meta-value 2 determines the
+ ** synchronous setting. A negative value means synchronous is off
+ ** and a positive value means synchronous is on.
*/
if( sqlite3StrICmp(zLeft,"default_cache_size")==0 ){
static const VdbeOpList getCacheSize[] = {
@@ -83132,6 +77303,10 @@ SQLITE_PRIVATE void sqlite3Pragma(
if( size<0 ) size = -size;
sqlite3BeginWriteOperation(pParse, 0, iDb);
sqlite3VdbeAddOp2(v, OP_Integer, size, 1);
+ sqlite3VdbeAddOp3(v, OP_ReadCookie, iDb, 2, BTREE_DEFAULT_CACHE_SIZE);
+ addr = sqlite3VdbeAddOp2(v, OP_IfPos, 2, 0);
+ sqlite3VdbeAddOp2(v, OP_Integer, -size, 1);
+ sqlite3VdbeJumpHere(v, addr);
sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_DEFAULT_CACHE_SIZE, 1);
pDb->pSchema->cache_size = size;
sqlite3BtreeSetCacheSize(pDb->pBt, pDb->pSchema->cache_size);
@@ -83169,7 +77344,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
** PRAGMA [database.]max_page_count=N
**
** The first form reports the current setting for the
- ** maximum number of pages in the database file. The
+ ** maximum number of pages in the database file. The
** second form attempts to change this setting. Both
** forms return the current setting.
*/
@@ -83187,31 +77362,6 @@ SQLITE_PRIVATE void sqlite3Pragma(
}else
/*
- ** PRAGMA [database.]secure_delete
- ** PRAGMA [database.]secure_delete=ON/OFF
- **
- ** The first form reports the current setting for the
- ** secure_delete flag. The second form changes the secure_delete
- ** flag setting and reports thenew value.
- */
- if( sqlite3StrICmp(zLeft,"secure_delete")==0 ){
- Btree *pBt = pDb->pBt;
- int b = -1;
- assert( pBt!=0 );
- if( zRight ){
- b = getBoolean(zRight);
- }
- if( pId2->n==0 && b>=0 ){
- int ii;
- for(ii=0; ii<db->nDb; ii++){
- sqlite3BtreeSecureDelete(db->aDb[ii].pBt, b);
- }
- }
- b = sqlite3BtreeSecureDelete(pBt, b);
- returnSingleInt(pParse, "secure_delete", b);
- }else
-
- /*
** PRAGMA [database.]page_count
**
** Return the number of pages in the specified database.
@@ -83276,25 +77426,21 @@ SQLITE_PRIVATE void sqlite3Pragma(
/*
** PRAGMA [database.]journal_mode
- ** PRAGMA [database.]journal_mode =
- ** (delete|persist|off|truncate|memory|wal|off)
+ ** PRAGMA [database.]journal_mode = (delete|persist|off|truncate|memory)
*/
if( sqlite3StrICmp(zLeft,"journal_mode")==0 ){
- int eMode; /* One of the PAGER_JOURNALMODE_XXX symbols */
-
- sqlite3VdbeSetNumCols(v, 1);
- sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "journal_mode", SQLITE_STATIC);
+ int eMode;
+ static char * const azModeName[] = {
+ "delete", "persist", "off", "truncate", "memory"
+ };
if( zRight==0 ){
eMode = PAGER_JOURNALMODE_QUERY;
}else{
- const char *zMode;
int n = sqlite3Strlen30(zRight);
- for(eMode=0; (zMode = sqlite3JournalModename(eMode)); eMode++){
- if( sqlite3StrNICmp(zRight, zMode, n)==0 ) break;
- }
- if( !zMode ){
- eMode = PAGER_JOURNALMODE_QUERY;
+ eMode = sizeof(azModeName)/sizeof(azModeName[0]) - 1;
+ while( eMode>=0 && sqlite3StrNICmp(zRight, azModeName[eMode], n)!=0 ){
+ eMode--;
}
}
if( pId2->n==0 && eMode==PAGER_JOURNALMODE_QUERY ){
@@ -83303,31 +77449,39 @@ SQLITE_PRIVATE void sqlite3Pragma(
** the journal-mode of the main database).
*/
eMode = db->dfltJournalMode;
- sqlite3VdbeAddOp2(v, OP_String8, 0, 1);
- sqlite3VdbeChangeP4(v, -1, sqlite3JournalModename(eMode), P4_STATIC);
}else{
- int ii;
-
+ Pager *pPager;
if( pId2->n==0 ){
- /* When there is no database name before the "journal_mode" keyword
- ** in the PRAGMA, then the journal-mode will be set on
- ** all attached databases, as well as the main db file.
+ /* This indicates that no database name was specified as part
+ ** of the PRAGMA command. In this case the journal-mode must be
+ ** set on all attached databases, as well as the main db file.
**
** Also, the sqlite3.dfltJournalMode variable is set so that
** any subsequently attached databases also use the specified
** journal mode.
*/
- db->dfltJournalMode = (u8)eMode;
- }
-
- for(ii=db->nDb-1; ii>=0; ii--){
- if( db->aDb[ii].pBt && (ii==iDb || pId2->n==0) ){
- sqlite3VdbeUsesBtree(v, ii);
- sqlite3VdbeAddOp3(v, OP_JournalMode, ii, 1, eMode);
+ int ii;
+ assert(pDb==&db->aDb[0]);
+ for(ii=1; ii<db->nDb; ii++){
+ if( db->aDb[ii].pBt ){
+ pPager = sqlite3BtreePager(db->aDb[ii].pBt);
+ sqlite3PagerJournalMode(pPager, eMode);
+ }
}
+ db->dfltJournalMode = (u8)eMode;
}
+ pPager = sqlite3BtreePager(pDb->pBt);
+ eMode = sqlite3PagerJournalMode(pPager, eMode);
}
-
+ assert( eMode==PAGER_JOURNALMODE_DELETE
+ || eMode==PAGER_JOURNALMODE_TRUNCATE
+ || eMode==PAGER_JOURNALMODE_PERSIST
+ || eMode==PAGER_JOURNALMODE_OFF
+ || eMode==PAGER_JOURNALMODE_MEMORY );
+ sqlite3VdbeSetNumCols(v, 1);
+ sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "journal_mode", SQLITE_STATIC);
+ sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0,
+ azModeName[eMode], P4_STATIC);
sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1);
}else
@@ -83384,7 +77538,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
*/
int rc = sqlite3BtreeSetAutoVacuum(pBt, eAuto);
if( rc==SQLITE_OK && (eAuto==1 || eAuto==2) ){
- /* When setting the auto_vacuum mode to either "full" or
+ /* When setting the auto_vacuum mode to either "full" or
** "incremental", write the value of meta[6] in the database
** file. Before writing to meta[6], check that meta[3] indicates
** that this really is an auto-vacuum capable database.
@@ -83495,7 +77649,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
if( !zRight ){
if( sqlite3_temp_directory ){
sqlite3VdbeSetNumCols(v, 1);
- sqlite3VdbeSetColName(v, 0, COLNAME_NAME,
+ sqlite3VdbeSetColName(v, 0, COLNAME_NAME,
"temp_store_directory", SQLITE_STATIC);
sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, sqlite3_temp_directory, 0);
sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1);
@@ -83548,12 +77702,12 @@ SQLITE_PRIVATE void sqlite3Pragma(
Pager *pPager = sqlite3BtreePager(pDb->pBt);
char *proxy_file_path = NULL;
sqlite3_file *pFile = sqlite3PagerFile(pPager);
- sqlite3OsFileControl(pFile, SQLITE_GET_LOCKPROXYFILE,
+ sqlite3OsFileControl(pFile, SQLITE_GET_LOCKPROXYFILE,
&proxy_file_path);
-
+
if( proxy_file_path ){
sqlite3VdbeSetNumCols(v, 1);
- sqlite3VdbeSetColName(v, 0, COLNAME_NAME,
+ sqlite3VdbeSetColName(v, 0, COLNAME_NAME,
"lock_proxy_file", SQLITE_STATIC);
sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, proxy_file_path, 0);
sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1);
@@ -83563,10 +77717,10 @@ SQLITE_PRIVATE void sqlite3Pragma(
sqlite3_file *pFile = sqlite3PagerFile(pPager);
int res;
if( zRight[0] ){
- res=sqlite3OsFileControl(pFile, SQLITE_SET_LOCKPROXYFILE,
+ res=sqlite3OsFileControl(pFile, SQLITE_SET_LOCKPROXYFILE,
zRight);
} else {
- res=sqlite3OsFileControl(pFile, SQLITE_SET_LOCKPROXYFILE,
+ res=sqlite3OsFileControl(pFile, SQLITE_SET_LOCKPROXYFILE,
NULL);
}
if( res!=SQLITE_OK ){
@@ -83575,8 +77729,8 @@ SQLITE_PRIVATE void sqlite3Pragma(
}
}
}else
-#endif /* SQLITE_ENABLE_LOCKING_STYLE */
-
+#endif /* SQLITE_ENABLE_LOCKING_STYLE */
+
/*
** PRAGMA [database.]synchronous
** PRAGMA [database.]synchronous=OFF|ON|NORMAL|FULL
@@ -83592,7 +77746,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
returnSingleInt(pParse, "synchronous", pDb->safety_level-1);
}else{
if( !db->autoCommit ){
- sqlite3ErrorMsg(pParse,
+ sqlite3ErrorMsg(pParse,
"Safety level may not be changed inside a transaction");
}else{
pDb->safety_level = getSafetyLevel(zRight)+1;
@@ -83692,7 +77846,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
v = sqlite3GetVdbe(pParse);
pIdx = pTab->pIndex;
if( pIdx ){
- int i = 0;
+ int i = 0;
sqlite3VdbeSetNumCols(v, 3);
pParse->nMem = 3;
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seq", SQLITE_STATIC);
@@ -83755,7 +77909,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
v = sqlite3GetVdbe(pParse);
pFK = pTab->pFKey;
if( pFK ){
- int i = 0;
+ int i = 0;
sqlite3VdbeSetNumCols(v, 8);
pParse->nMem = 8;
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "id", SQLITE_STATIC);
@@ -83817,12 +77971,12 @@ SQLITE_PRIVATE void sqlite3Pragma(
#endif
#ifndef SQLITE_OMIT_INTEGRITY_CHECK
- /* Pragma "quick_check" is an experimental reduced version of
+ /* Pragma "quick_check" is an experimental reduced version of
** integrity_check designed to detect most database corruption
** without most of the overhead of a full integrity-check.
*/
if( sqlite3StrICmp(zLeft, "integrity_check")==0
- || sqlite3StrICmp(zLeft, "quick_check")==0
+ || sqlite3StrICmp(zLeft, "quick_check")==0
){
int i, j, addr, mxErr;
@@ -83966,11 +78120,11 @@ SQLITE_PRIVATE void sqlite3Pragma(
sqlite3VdbeChangeP1(v, addr+3, j+2);
sqlite3VdbeChangeP2(v, addr+3, addr+2);
sqlite3VdbeJumpHere(v, addr+4);
- sqlite3VdbeChangeP4(v, addr+6,
+ sqlite3VdbeChangeP4(v, addr+6,
"wrong # of entries in index ", P4_STATIC);
sqlite3VdbeChangeP4(v, addr+7, pIdx->zName, P4_STATIC);
}
- }
+ }
}
addr = sqlite3VdbeAddOpList(v, ArraySize(endCode), endCode);
sqlite3VdbeChangeP2(v, addr, -mxErr);
@@ -83992,7 +78146,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
** encoding that will be used for the main database file if a new file
** is created. If an existing main database file is opened, then the
** default text encoding for the existing database is used.
- **
+ **
** In all cases new databases created using the ATTACH command are
** created to use the same default text encoding as the main database. If
** the main database has not been initialized and/or created when ATTACH
@@ -84034,9 +78188,9 @@ SQLITE_PRIVATE void sqlite3Pragma(
** will be overwritten when the schema is next loaded. If it does not
** already exists, it will be created to use the new encoding value.
*/
- if(
- !(DbHasProperty(db, 0, DB_SchemaLoaded)) ||
- DbHasProperty(db, 0, DB_Empty)
+ if(
+ !(DbHasProperty(db, 0, DB_SchemaLoaded)) ||
+ DbHasProperty(db, 0, DB_Empty)
){
for(pEnc=&encnames[0]; pEnc->zName; pEnc++){
if( 0==sqlite3StrICmp(zRight, pEnc->zName) ){
@@ -84078,9 +78232,9 @@ SQLITE_PRIVATE void sqlite3Pragma(
** The user-version is not used internally by SQLite. It may be used by
** applications for any purpose.
*/
- if( sqlite3StrICmp(zLeft, "schema_version")==0
- || sqlite3StrICmp(zLeft, "user_version")==0
- || sqlite3StrICmp(zLeft, "freelist_count")==0
+ if( sqlite3StrICmp(zLeft, "schema_version")==0
+ || sqlite3StrICmp(zLeft, "user_version")==0
+ || sqlite3StrICmp(zLeft, "freelist_count")==0
){
int iCookie; /* Cookie index. 1 for schema-cookie, 6 for user-cookie. */
sqlite3VdbeUsesBtree(v, iDb);
@@ -84125,56 +78279,6 @@ SQLITE_PRIVATE void sqlite3Pragma(
}else
#endif /* SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS */
-#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
- /*
- ** PRAGMA compile_options
- **
- ** Return the names of all compile-time options used in this build,
- ** one option per row.
- */
- if( sqlite3StrICmp(zLeft, "compile_options")==0 ){
- int i = 0;
- const char *zOpt;
- sqlite3VdbeSetNumCols(v, 1);
- pParse->nMem = 1;
- sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "compile_option", SQLITE_STATIC);
- while( (zOpt = sqlite3_compileoption_get(i++))!=0 ){
- sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, zOpt, 0);
- sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1);
- }
- }else
-#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */
-
-#ifndef SQLITE_OMIT_WAL
- /*
- ** PRAGMA [database.]wal_checkpoint
- **
- ** Checkpoint the database.
- */
- if( sqlite3StrICmp(zLeft, "wal_checkpoint")==0 ){
- if( sqlite3ReadSchema(pParse) ) goto pragma_out;
- sqlite3VdbeAddOp3(v, OP_Checkpoint, pId2->z?iDb:SQLITE_MAX_ATTACHED, 0, 0);
- }else
-
- /*
- ** PRAGMA wal_autocheckpoint
- ** PRAGMA wal_autocheckpoint = N
- **
- ** Configure a database connection to automatically checkpoint a database
- ** after accumulating N frames in the log. Or query for the current value
- ** of N.
- */
- if( sqlite3StrICmp(zLeft, "wal_autocheckpoint")==0 ){
- if( zRight ){
- int nAuto = atoi(zRight);
- sqlite3_wal_autocheckpoint(db, nAuto);
- }
- returnSingleInt(pParse, "wal_autocheckpoint",
- db->xWalCallback==sqlite3WalDefaultHook ?
- SQLITE_PTR_TO_INT(db->pWalArg) : 0);
- }else
-#endif
-
#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
/*
** Report the current state of file logs for all databases
@@ -84198,7 +78302,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
pBt = db->aDb[i].pBt;
if( pBt==0 || (pPager = sqlite3BtreePager(pBt))==0 ){
zState = "closed";
- }else if( sqlite3_file_control(db, i ? db->aDb[i].zName : 0,
+ }else if( sqlite3_file_control(db, i ? db->aDb[i].zName : 0,
SQLITE_FCNTL_LOCKSTATE, &j)==SQLITE_OK ){
zState = azLockName[j];
}
@@ -84209,7 +78313,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
}else
#endif
-#ifdef SQLITE_HAS_CODEC
+#if SQLITE_HAS_CODEC
if( sqlite3StrICmp(zLeft, "key")==0 && zRight ){
sqlite3_key(db, zRight, sqlite3Strlen30(zRight));
}else
@@ -84232,22 +78336,24 @@ SQLITE_PRIVATE void sqlite3Pragma(
}
}else
#endif
-#if defined(SQLITE_HAS_CODEC) || defined(SQLITE_ENABLE_CEROD)
+#if SQLITE_HAS_CODEC || defined(SQLITE_ENABLE_CEROD)
if( sqlite3StrICmp(zLeft, "activate_extensions")==0 ){
-#ifdef SQLITE_HAS_CODEC
+#if SQLITE_HAS_CODEC
if( sqlite3StrNICmp(zRight, "see-", 4)==0 ){
+ extern void sqlite3_activate_see(const char*);
sqlite3_activate_see(&zRight[4]);
}
#endif
#ifdef SQLITE_ENABLE_CEROD
if( sqlite3StrNICmp(zRight, "cerod-", 6)==0 ){
+ extern void sqlite3_activate_cerod(const char*);
sqlite3_activate_cerod(&zRight[6]);
}
#endif
}else
#endif
-
+
{/* Empty ELSE clause */}
/*
@@ -84300,7 +78406,7 @@ static void corruptSchema(
sqlite3SetString(pData->pzErrMsg, db,
"malformed database schema (%s)", zObj);
if( zExtra ){
- *pData->pzErrMsg = sqlite3MAppendf(db, *pData->pzErrMsg,
+ *pData->pzErrMsg = sqlite3MAppendf(db, *pData->pzErrMsg,
"%s - %s", *pData->pzErrMsg, zExtra);
}
}
@@ -84343,15 +78449,15 @@ SQLITE_PRIVATE int sqlite3InitCallback(void *pInit, int argc, char **argv, char
** or executed. All the parser does is build the internal data
** structures that describe the table, index, or view.
*/
+ char *zErr;
int rc;
- sqlite3_stmt *pStmt;
-
assert( db->init.busy );
db->init.iDb = iDb;
db->init.newTnum = atoi(argv[1]);
db->init.orphanTrigger = 0;
- rc = sqlite3_prepare(db, argv[2], -1, &pStmt, 0);
+ rc = sqlite3_exec(db, argv[2], 0, 0, &zErr);
db->init.iDb = 0;
+ assert( rc!=SQLITE_OK || zErr==0 );
if( SQLITE_OK!=rc ){
if( db->init.orphanTrigger ){
assert( iDb==1 );
@@ -84360,11 +78466,11 @@ SQLITE_PRIVATE int sqlite3InitCallback(void *pInit, int argc, char **argv, char
if( rc==SQLITE_NOMEM ){
db->mallocFailed = 1;
}else if( rc!=SQLITE_INTERRUPT && rc!=SQLITE_LOCKED ){
- corruptSchema(pData, argv[0], sqlite3_errmsg(db));
+ corruptSchema(pData, argv[0], zErr);
}
}
+ sqlite3DbFree(db, zErr);
}
- sqlite3_finalize(pStmt);
}else if( argv[0]==0 ){
corruptSchema(pData, 0, 0);
}else{
@@ -84414,7 +78520,7 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
/*
** The master database table has a structure like this
*/
- static const char master_schema[] =
+ static const char master_schema[] =
"CREATE TABLE sqlite_master(\n"
" type text,\n"
" name text,\n"
@@ -84424,7 +78530,7 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
")"
;
#ifndef SQLITE_OMIT_TEMPDB
- static const char temp_master_schema[] =
+ static const char temp_master_schema[] =
"CREATE TEMP TABLE sqlite_temp_master(\n"
" type text,\n"
" name text,\n"
@@ -84483,7 +78589,7 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
}
/* If there is not already a read-only (or read-write) transaction opened
- ** on the b-tree database, open one now. If a transaction is opened, it
+ ** on the b-tree database, open one now. If a transaction is opened, it
** will be closed before this function returns. */
sqlite3BtreeEnter(pDb->pBt);
if( !sqlite3BtreeIsInReadTrans(pDb->pBt) ){
@@ -84582,8 +78688,8 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
assert( db->init.busy );
{
char *zSql;
- zSql = sqlite3MPrintf(db,
- "SELECT name, rootpage, sql FROM '%q'.%s ORDER BY rowid",
+ zSql = sqlite3MPrintf(db,
+ "SELECT name, rootpage, sql FROM '%q'.%s",
db->aDb[iDb].zName, zMasterName);
#ifndef SQLITE_OMIT_AUTHORIZATION
{
@@ -84610,7 +78716,7 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
}
if( rc==SQLITE_OK || (db->flags&SQLITE_RecoveryMode)){
/* Black magic: If the SQLITE_RecoveryMode flag is set, then consider
- ** the schema loaded, even if errors occurred. In this situation the
+ ** the schema loaded, even if errors occurred. In this situation the
** current sqlite3_prepare() operation will fail, but the following one
** will attempt to compile the supplied statement against whatever subset
** of the schema was loaded before the error occurred. The primary
@@ -84651,7 +78757,7 @@ error_out:
SQLITE_PRIVATE int sqlite3Init(sqlite3 *db, char **pzErrMsg){
int i, rc;
int commit_internal = !(db->flags&SQLITE_InternChanges);
-
+
assert( sqlite3_mutex_held(db->mutex) );
rc = SQLITE_OK;
db->init.busy = 1;
@@ -84682,7 +78788,7 @@ SQLITE_PRIVATE int sqlite3Init(sqlite3 *db, char **pzErrMsg){
sqlite3CommitInternalChanges(db);
}
- return rc;
+ return rc;
}
/*
@@ -84723,7 +78829,7 @@ static void schemaIsValid(Parse *pParse){
if( pBt==0 ) continue;
/* If there is not already a read-only (or read-write) transaction opened
- ** on the b-tree database, open one now. If a transaction is opened, it
+ ** on the b-tree database, open one now. If a transaction is opened, it
** will be closed immediately after reading the meta-value. */
if( !sqlite3BtreeIsInReadTrans(pBt) ){
rc = sqlite3BtreeBeginTrans(pBt, 0);
@@ -84734,7 +78840,7 @@ static void schemaIsValid(Parse *pParse){
openedTransaction = 1;
}
- /* Read the schema cookie from the database. If it does not match the
+ /* Read the schema cookie from the database. If it does not match the
** value stored as part of the in-memory schema representation,
** set Parse.rc to SQLITE_SCHEMA. */
sqlite3BtreeGetMeta(pBt, BTREE_SCHEMA_VERSION, (u32 *)&cookie);
@@ -84759,13 +78865,13 @@ static void schemaIsValid(Parse *pParse){
SQLITE_PRIVATE int sqlite3SchemaToIndex(sqlite3 *db, Schema *pSchema){
int i = -1000000;
- /* If pSchema is NULL, then return -1000000. This happens when code in
+ /* If pSchema is NULL, then return -1000000. This happens when code in
** expr.c is trying to resolve a reference to a transient table (i.e. one
- ** created by a sub-select). In this case the return value of this
+ ** created by a sub-select). In this case the return value of this
** function should never be used.
**
** We return -1000000 instead of the more usual -1 simply because using
- ** -1000000 as the incorrect index into db->aDb[] is much
+ ** -1000000 as the incorrect index into db->aDb[] is much
** more likely to cause a segfault than -1 (of course there are assert()
** statements too, but it never hurts to play the odds).
*/
@@ -84824,8 +78930,8 @@ static int sqlite3Prepare(
** This thread is currently holding mutexes on all Btrees (because
** of the sqlite3BtreeEnterAll() in sqlite3LockAndPrepare()) so it
** is not possible for another thread to start a new schema change
- ** while this routine is running. Hence, we do not need to hold
- ** locks on the schema, we just need to make sure nobody else is
+ ** while this routine is running. Hence, we do not need to hold
+ ** locks on the schema, we just need to make sure nobody else is
** holding them.
**
** Note that setting READ_UNCOMMITTED overrides most lock detection,
@@ -84849,7 +78955,6 @@ static int sqlite3Prepare(
sqlite3VtabUnlockList(db);
pParse->db = db;
- pParse->nQueryLoop = (double)1;
if( nBytes>=0 && (nBytes==0 || zSql[nBytes-1]!=0) ){
char *zSqlCopy;
int mxLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH];
@@ -84871,7 +78976,6 @@ static int sqlite3Prepare(
}else{
sqlite3RunParser(pParse, zSql, &zErrMsg);
}
- assert( 1==(int)pParse->nQueryLoop );
if( db->mallocFailed ){
pParse->rc = SQLITE_NOMEM;
@@ -85051,7 +79155,7 @@ SQLITE_API int sqlite3_prepare_v2(
** Compile the UTF-16 encoded SQL statement zSql into a statement handle.
*/
static int sqlite3Prepare16(
- sqlite3 *db, /* Database handle. */
+ sqlite3 *db, /* Database handle. */
const void *zSql, /* UTF-8 encoded SQL statement. */
int nBytes, /* Length of zSql in bytes. */
int saveSqlFlag, /* True to save SQL text into the sqlite3_stmt */
@@ -85072,7 +79176,7 @@ static int sqlite3Prepare16(
return SQLITE_MISUSE_BKPT;
}
sqlite3_mutex_enter(db->mutex);
- zSql8 = sqlite3Utf16to8(db, zSql, nBytes, SQLITE_UTF16NATIVE);
+ zSql8 = sqlite3Utf16to8(db, zSql, nBytes);
if( zSql8 ){
rc = sqlite3LockAndPrepare(db, zSql8, -1, saveSqlFlag, 0, ppStmt, &zTail8);
}
@@ -85086,7 +79190,7 @@ static int sqlite3Prepare16(
int chars_parsed = sqlite3Utf8CharLen(zSql8, (int)(zTail8-zSql8));
*pzTail = (u8 *)zSql + sqlite3Utf16ByteLen(zSql, chars_parsed);
}
- sqlite3DbFree(db, zSql8);
+ sqlite3DbFree(db, zSql8);
rc = sqlite3ApiExit(db, rc);
sqlite3_mutex_leave(db->mutex);
return rc;
@@ -85101,7 +79205,7 @@ static int sqlite3Prepare16(
** occurs.
*/
SQLITE_API int sqlite3_prepare16(
- sqlite3 *db, /* Database handle. */
+ sqlite3 *db, /* Database handle. */
const void *zSql, /* UTF-8 encoded SQL statement. */
int nBytes, /* Length of zSql in bytes. */
sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */
@@ -85113,7 +79217,7 @@ SQLITE_API int sqlite3_prepare16(
return rc;
}
SQLITE_API int sqlite3_prepare16_v2(
- sqlite3 *db, /* Database handle. */
+ sqlite3 *db, /* Database handle. */
const void *zSql, /* UTF-8 encoded SQL statement. */
int nBytes, /* Length of zSql in bytes. */
sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */
@@ -85276,7 +79380,7 @@ SQLITE_PRIVATE int sqlite3JoinType(Parse *pParse, Token *pA, Token *pB, Token *p
for(i=0; i<3 && apAll[i]; i++){
p = apAll[i];
for(j=0; j<ArraySize(aKeyword); j++){
- if( p->n==aKeyword[j].nChar
+ if( p->n==aKeyword[j].nChar
&& sqlite3StrNICmp((char*)p->z, &zKeyText[aKeyword[j].i], p->n)==0 ){
jointype |= aKeyword[j].code;
break;
@@ -85298,9 +79402,9 @@ SQLITE_PRIVATE int sqlite3JoinType(Parse *pParse, Token *pA, Token *pB, Token *p
sqlite3ErrorMsg(pParse, "unknown or unsupported join type: "
"%T %T%s%T", pA, pB, zSp, pC);
jointype = JT_INNER;
- }else if( (jointype & JT_OUTER)!=0
+ }else if( (jointype & JT_OUTER)!=0
&& (jointype & (JT_LEFT|JT_RIGHT))!=JT_LEFT ){
- sqlite3ErrorMsg(pParse,
+ sqlite3ErrorMsg(pParse,
"RIGHT and FULL OUTER JOINs are not currently supported");
jointype = JT_INNER;
}
@@ -85321,7 +79425,7 @@ static int columnIndex(Table *pTab, const char *zCol){
/*
** Search the first N tables in pSrc, from left to right, looking for a
-** table that has a column named zCol.
+** table that has a column named zCol.
**
** When found, set *piTab and *piCol to the table index and column index
** of the matching column and return TRUE.
@@ -85359,7 +79463,7 @@ static int tableAndColumnIndex(
**
** (tab1.col1 = tab2.col2)
**
-** where tab1 is the iSrc'th table in SrcList pSrc and tab2 is the
+** where tab1 is the iSrc'th table in SrcList pSrc and tab2 is the
** (iSrc+1)'th. Column col1 is column iColLeft of tab1, and col2 is
** column iColRight of tab2.
*/
@@ -85430,7 +79534,7 @@ static void setJoinExpr(Expr *p, int iTable){
p->iRightJoinTable = (i16)iTable;
setJoinExpr(p->pLeft, iTable);
p = p->pRight;
- }
+ }
}
/*
@@ -85504,7 +79608,7 @@ static int sqliteProcessJoin(Parse *pParse, Select *p){
}
/* Create extra terms on the WHERE clause for each column named
- ** in the USING clause. Example: If the two tables to be joined are
+ ** in the USING clause. Example: If the two tables to be joined are
** A and B and the USING clause names X, Y, and Z, then add this
** to the WHERE clause: A.X=B.X AND A.Y=B.Y AND A.Z=B.Z
** Report an error if any column mentioned in the USING clause is
@@ -85690,7 +79794,7 @@ static void selectInnerLoop(
pDest->iMem = pParse->nMem+1;
pDest->nMem = nResultCol;
pParse->nMem += nResultCol;
- }else{
+ }else{
assert( pDest->nMem==nResultCol );
}
regResult = pDest->iMem;
@@ -85969,7 +80073,7 @@ static void generateSortTail(
#endif
default: {
int i;
- assert( eDest==SRT_Output || eDest==SRT_Coroutine );
+ assert( eDest==SRT_Output || eDest==SRT_Coroutine );
testcase( eDest==SRT_Output );
testcase( eDest==SRT_Coroutine );
for(i=0; i<nColumn; i++){
@@ -86013,18 +80117,18 @@ static void generateSortTail(
** original CREATE TABLE statement if the expression is a column. The
** declaration type for a ROWID field is INTEGER. Exactly when an expression
** is considered a column can be complex in the presence of subqueries. The
-** result-set expression in all of the following SELECT statements is
+** result-set expression in all of the following SELECT statements is
** considered a column by this function.
**
** SELECT col FROM tbl;
** SELECT (SELECT col FROM tbl;
** SELECT (SELECT col FROM tbl);
** SELECT abc FROM (SELECT col AS abc FROM tbl);
-**
+**
** The declaration type for any expression other than a column is NULL.
*/
static const char *columnType(
- NameContext *pNC,
+ NameContext *pNC,
Expr *pExpr,
const char **pzOriginDb,
const char **pzOriginTab,
@@ -86063,19 +80167,19 @@ static const char *columnType(
if( pTab==0 ){
/* At one time, code such as "SELECT new.x" within a trigger would
** cause this condition to run. Since then, we have restructured how
- ** trigger code is generated and so this condition is no longer
+ ** trigger code is generated and so this condition is no longer
** possible. However, it can still be true for statements like
** the following:
**
** CREATE TABLE t1(col INTEGER);
** SELECT (SELECT t1.col) FROM FROM t1;
**
- ** when columnType() is called on the expression "t1.col" in the
+ ** when columnType() is called on the expression "t1.col" in the
** sub-select. In this case, set the column type to NULL, even
** though it should really be "INTEGER".
**
** This is not a problem, as the column type of "t1.col" is never
- ** used. When columnType() is called on the expression
+ ** used. When columnType() is called on the expression
** "(SELECT t1.col)", the correct type is returned (see the TK_SELECT
** branch below. */
break;
@@ -86089,7 +80193,7 @@ static const char *columnType(
*/
if( iCol>=0 && ALWAYS(iCol<pS->pEList->nExpr) ){
/* If iCol is less than zero, then the expression requests the
- ** rowid of the sub-select or view. This expression is legal (see
+ ** rowid of the sub-select or view. This expression is legal (see
** test case misc2.2.2) - it always evaluates to NULL.
*/
NameContext sNC;
@@ -86097,7 +80201,7 @@ static const char *columnType(
sNC.pSrcList = pS->pSrc;
sNC.pNext = pNC;
sNC.pParse = pNC->pParse;
- zType = columnType(&sNC, p, &zOriginDb, &zOriginTab, &zOriginCol);
+ zType = columnType(&sNC, p, &zOriginDb, &zOriginTab, &zOriginCol);
}
}else if( ALWAYS(pTab->pSchema) ){
/* A real table */
@@ -86132,12 +80236,12 @@ static const char *columnType(
sNC.pSrcList = pS->pSrc;
sNC.pNext = pNC;
sNC.pParse = pNC->pParse;
- zType = columnType(&sNC, p, &zOriginDb, &zOriginTab, &zOriginCol);
+ zType = columnType(&sNC, p, &zOriginDb, &zOriginTab, &zOriginCol);
break;
}
#endif
}
-
+
if( pzOriginDb ){
assert( pzOriginTab && pzOriginCol );
*pzOriginDb = zOriginDb;
@@ -86171,7 +80275,7 @@ static void generateColumnTypes(
const char *zOrigCol = 0;
zType = columnType(&sNC, p, &zOrigDb, &zOrigTab, &zOrigCol);
- /* The vdbe must make its own copy of the column-type and other
+ /* The vdbe must make its own copy of the column-type and other
** column specific strings, in case the schema is reset before this
** virtual machine is deleted.
*/
@@ -86237,7 +80341,7 @@ static void generateColumnNames(
zCol = pTab->aCol[iCol].zName;
}
if( !shortNames && !fullNames ){
- sqlite3VdbeSetColName(v, i, COLNAME_NAME,
+ sqlite3VdbeSetColName(v, i, COLNAME_NAME,
sqlite3DbStrDup(db, pEList->a[i].zSpan), SQLITE_DYNAMIC);
}else if( fullNames ){
char *zName = 0;
@@ -86247,7 +80351,7 @@ static void generateColumnNames(
sqlite3VdbeSetColName(v, i, COLNAME_NAME, zCol, SQLITE_TRANSIENT);
}
}else{
- sqlite3VdbeSetColName(v, i, COLNAME_NAME,
+ sqlite3VdbeSetColName(v, i, COLNAME_NAME,
sqlite3DbStrDup(db, pEList->a[i].zSpan), SQLITE_DYNAMIC);
}
}
@@ -86366,7 +80470,7 @@ static int selectColumnsFromExprList(
/*
** Add type and collation information to a column list based on
** a SELECT statement.
-**
+**
** The column list presumably came from selectColumnNamesFromExprList().
** The column list has only names, not types or collations. This
** routine goes through and adds the types and collations.
@@ -86465,9 +80569,9 @@ SQLITE_PRIVATE Vdbe *sqlite3GetVdbe(Parse *pParse){
** Compute the iLimit and iOffset fields of the SELECT based on the
** pLimit and pOffset expressions. pLimit and pOffset hold the expressions
** that appear in the original SQL statement after the LIMIT and OFFSET
-** keywords. Or NULL if those keywords are omitted. iLimit and iOffset
-** are the integer memory register numbers for counters used to compute
-** the limit and offset. If there is no limit and/or offset, then
+** keywords. Or NULL if those keywords are omitted. iLimit and iOffset
+** are the integer memory register numbers for counters used to compute
+** the limit and offset. If there is no limit and/or offset, then
** iLimit and iOffset are negative.
**
** This routine changes the values of iLimit and iOffset only if
@@ -86486,7 +80590,7 @@ static void computeLimitRegisters(Parse *pParse, Select *p, int iBreak){
int addr1, n;
if( p->iLimit ) return;
- /*
+ /*
** "LIMIT -1" always shows all rows. There is some
** contraversy about what the correct behavior should be.
** The current implementation interprets "LIMIT 0" to mean
@@ -86568,7 +80672,7 @@ static int multiSelectOrderBy(
**
** "p" points to the right-most of the two queries. the query on the
** left is p->pPrior. The left query could also be a compound query
-** in which case this routine will be called recursively.
+** in which case this routine will be called recursively.
**
** The results of the total query are to be written into a destination
** of type eDest with parameter iParm.
@@ -86858,7 +80962,7 @@ static int multiSelect(
}
}
- /* Compute collating sequences used by
+ /* Compute collating sequences used by
** temporary tables needed to implement the compound select.
** Attach the KeyInfo structure to all temporary tables.
**
@@ -86956,7 +81060,7 @@ static int generateOutputSubroutine(
addr = sqlite3VdbeCurrentAddr(v);
iContinue = sqlite3VdbeMakeLabel(v);
- /* Suppress duplicates for UNION, EXCEPT, and INTERSECT
+ /* Suppress duplicates for UNION, EXCEPT, and INTERSECT
*/
if( regPrev ){
int j1, j2;
@@ -87000,7 +81104,7 @@ static int generateOutputSubroutine(
case SRT_Set: {
int r1;
assert( pIn->nMem==1 );
- p->affinity =
+ p->affinity =
sqlite3CompareAffinity(p->pEList->a[0].pExpr, pDest->affinity);
r1 = sqlite3GetTempReg(pParse);
sqlite3VdbeAddOp4(v, OP_MakeRecord, pIn->iMem, 1, r1, &p->affinity, 1);
@@ -87049,7 +81153,7 @@ static int generateOutputSubroutine(
** SRT_Output. This routine is never called with any other
** destination other than the ones handled above or SRT_Output.
**
- ** For SRT_Output, results are stored in a sequence of registers.
+ ** For SRT_Output, results are stored in a sequence of registers.
** Then the OP_ResultRow opcode is used to cause sqlite3_step() to
** return the next row of result.
*/
@@ -87107,7 +81211,7 @@ static int generateOutputSubroutine(
**
** EofB: Called when data is exhausted from selectB.
**
-** The implementation of the latter five subroutines depend on which
+** The implementation of the latter five subroutines depend on which
** <operator> is used:
**
**
@@ -87213,7 +81317,7 @@ static int multiSelectOrderBy(
/* Patch up the ORDER BY clause
*/
- op = p->op;
+ op = p->op;
pPrior = p->pPrior;
assert( pPrior->pOrderBy==0 );
pOrderBy = p->pOrderBy;
@@ -87308,7 +81412,7 @@ static int multiSelectOrderBy(
}
}
}
-
+
/* Separate the left and the right query from one another
*/
p->pPrior = 0;
@@ -87360,7 +81464,7 @@ static int multiSelectOrderBy(
sqlite3VdbeAddOp1(v, OP_Yield, regAddrA);
VdbeNoopComment((v, "End coroutine for left SELECT"));
- /* Generate a coroutine to evaluate the SELECT statement on
+ /* Generate a coroutine to evaluate the SELECT statement on
** the right - the "B" select
*/
addrSelectB = sqlite3VdbeCurrentAddr(v);
@@ -87368,7 +81472,7 @@ static int multiSelectOrderBy(
savedLimit = p->iLimit;
savedOffset = p->iOffset;
p->iLimit = regLimitB;
- p->iOffset = 0;
+ p->iOffset = 0;
sqlite3Select(pParse, p, &destB);
p->iLimit = savedLimit;
p->iOffset = savedOffset;
@@ -87383,7 +81487,7 @@ static int multiSelectOrderBy(
addrOutA = generateOutputSubroutine(pParse,
p, &destA, pDest, regOutA,
regPrev, pKeyDup, P4_KEYINFO_HANDOFF, labelEnd);
-
+
/* Generate a subroutine that outputs the current row of the B
** select as the next output row of the compound select.
*/
@@ -87400,7 +81504,7 @@ static int multiSelectOrderBy(
VdbeNoopComment((v, "eof-A subroutine"));
if( op==TK_EXCEPT || op==TK_INTERSECT ){
addrEofA = sqlite3VdbeAddOp2(v, OP_Goto, 0, labelEnd);
- }else{
+ }else{
addrEofA = sqlite3VdbeAddOp2(v, OP_If, regEofB, labelEnd);
sqlite3VdbeAddOp2(v, OP_Gosub, regOutB, addrOutB);
sqlite3VdbeAddOp1(v, OP_Yield, regAddrB);
@@ -87412,7 +81516,7 @@ static int multiSelectOrderBy(
*/
if( op==TK_INTERSECT ){
addrEofB = addrEofA;
- }else{
+ }else{
VdbeNoopComment((v, "eof-B subroutine"));
addrEofB = sqlite3VdbeAddOp2(v, OP_If, regEofA, labelEnd);
sqlite3VdbeAddOp2(v, OP_Gosub, regOutA, addrOutA);
@@ -87511,13 +81615,13 @@ static void substSelect(sqlite3*, Select *, int, ExprList *);
/*
** Scan through the expression pExpr. Replace every reference to
** a column in table number iTable with a copy of the iColumn-th
-** entry in pEList. (But leave references to the ROWID column
+** entry in pEList. (But leave references to the ROWID column
** unchanged.)
**
** This routine is part of the flattening procedure. A subquery
** whose result set is defined by pEList appears as entry in the
** FROM clause of a SELECT such that the VDBE cursor assigned to that
-** FORM clause entry is iTable. This routine make the necessary
+** FORM clause entry is iTable. This routine make the necessary
** changes to pExpr so that it refers directly to the source table
** of the subquery rather the result set of the subquery.
*/
@@ -87615,7 +81719,7 @@ static void substSelect(
** SELECT x+y AS a FROM t1 WHERE z<100 AND a>5
**
** The code generated for this simpification gives the same result
-** but only has to scan the data once. And because indices might
+** but only has to scan the data once. And because indices might
** exist on the table t1, a complete scan of the data might be
** avoided.
**
@@ -87656,15 +81760,15 @@ static void substSelect(
** (14) The subquery does not use OFFSET
**
** (15) The outer query is not part of a compound select or the
-** subquery does not have a LIMIT clause.
-** (See ticket #2339 and ticket [02a8e81d44]).
+** subquery does not have both an ORDER BY and a LIMIT clause.
+** (See ticket #2339)
**
** (16) The outer query is not an aggregate or the subquery does
** not contain ORDER BY. (Ticket #2942) This used to not matter
-** until we introduced the group_concat() function.
+** until we introduced the group_concat() function.
**
-** (17) The sub-query is not a compound select, or it is a UNION ALL
-** compound clause made up entirely of non-aggregate queries, and
+** (17) The sub-query is not a compound select, or it is a UNION ALL
+** compound clause made up entirely of non-aggregate queries, and
** the parent query:
**
** * is not itself part of a compound select,
@@ -87676,7 +81780,7 @@ static void substSelect(
** LIMIT and OFFSET clauses.
**
** (18) If the sub-query is a compound select, then all terms of the
-** ORDER by clause of the parent must be simple references to
+** ORDER by clause of the parent must be simple references to
** columns of the sub-query.
**
** (19) The subquery does not use LIMIT or the outer query does not
@@ -87740,13 +81844,13 @@ static int flattenSubquery(
** and (14). */
if( pSub->pLimit && p->pLimit ) return 0; /* Restriction (13) */
if( pSub->pOffset ) return 0; /* Restriction (14) */
- if( p->pRightmost && pSub->pLimit ){
+ if( p->pRightmost && pSub->pLimit && pSub->pOrderBy ){
return 0; /* Restriction (15) */
}
if( pSubSrc->nSrc==0 ) return 0; /* Restriction (7) */
- if( ((pSub->selFlags & SF_Distinct)!=0 || pSub->pLimit)
+ if( ((pSub->selFlags & SF_Distinct)!=0 || pSub->pLimit)
&& (pSrc->nSrc>1 || isAgg) ){ /* Restrictions (4)(5)(8)(9) */
- return 0;
+ return 0;
}
if( (p->selFlags & SF_Distinct)!=0 && subqueryIsAgg ){
return 0; /* Restriction (6) */
@@ -87758,7 +81862,7 @@ static int flattenSubquery(
if( pSub->pLimit && p->pWhere ) return 0; /* Restriction (19) */
/* OBSOLETE COMMENT 1:
- ** Restriction 3: If the subquery is a join, make sure the subquery is
+ ** Restriction 3: If the subquery is a join, make sure the subquery is
** not used as the right operand of an outer join. Examples of why this
** is not allowed:
**
@@ -87809,7 +81913,7 @@ static int flattenSubquery(
testcase( (pSub1->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct );
testcase( (pSub1->selFlags & (SF_Distinct|SF_Aggregate))==SF_Aggregate );
if( (pSub1->selFlags & (SF_Distinct|SF_Aggregate))!=0
- || (pSub1->pPrior && pSub1->op!=TK_ALL)
+ || (pSub1->pPrior && pSub1->op!=TK_ALL)
|| NEVER(pSub1->pSrc==0) || pSub1->pSrc->nSrc!=1
){
return 0;
@@ -87833,13 +81937,13 @@ static int flattenSubquery(
pParse->zAuthContext = zSavedAuthContext;
/* If the sub-query is a compound SELECT statement, then (by restrictions
- ** 17 and 18 above) it must be a UNION ALL and the parent query must
+ ** 17 and 18 above) it must be a UNION ALL and the parent query must
** be of the form:
**
- ** SELECT <expr-list> FROM (<sub-query>) <where-clause>
+ ** SELECT <expr-list> FROM (<sub-query>) <where-clause>
**
** followed by any ORDER BY, LIMIT and/or OFFSET clauses. This block
- ** creates N-1 copies of the parent query without any ORDER BY, LIMIT or
+ ** creates N-1 copies of the parent query without any ORDER BY, LIMIT or
** OFFSET clauses and joins them to the left-hand-side of the original
** using UNION ALL operators. In this case N is the number of simple
** select statements in the compound sub-query.
@@ -87890,7 +81994,7 @@ static int flattenSubquery(
if( db->mallocFailed ) return 1;
}
- /* Begin flattening the iFrom-th entry of the FROM clause
+ /* Begin flattening the iFrom-th entry of the FROM clause
** in the outer query.
*/
pSub = pSub1 = pSubitem->pSelect;
@@ -87988,10 +82092,10 @@ static int flattenSubquery(
memset(&pSubSrc->a[i], 0, sizeof(pSubSrc->a[i]));
}
pSrc->a[iFrom].jointype = jointype;
-
- /* Now begin substituting subquery result set expressions for
+
+ /* Now begin substituting subquery result set expressions for
** references to the iParent in the outer query.
- **
+ **
** Example:
**
** SELECT a+5, b*10 FROM (SELECT x*3 AS a, y+10 AS b FROM t1) WHERE a>b;
@@ -88032,7 +82136,7 @@ static int flattenSubquery(
pParent->pHaving = pParent->pWhere;
pParent->pWhere = pWhere;
pParent->pHaving = substExpr(db, pParent->pHaving, iParent, pSub->pEList);
- pParent->pHaving = sqlite3ExprAnd(db, pParent->pHaving,
+ pParent->pHaving = sqlite3ExprAnd(db, pParent->pHaving,
sqlite3ExprDup(db, pSub->pHaving, 0));
assert( pParent->pGroupBy==0 );
pParent->pGroupBy = sqlite3ExprListDup(db, pSub->pGroupBy, 0);
@@ -88040,12 +82144,12 @@ static int flattenSubquery(
pParent->pWhere = substExpr(db, pParent->pWhere, iParent, pSub->pEList);
pParent->pWhere = sqlite3ExprAnd(db, pParent->pWhere, pWhere);
}
-
+
/* The flattened query is distinct if either the inner or the
- ** outer query is distinct.
+ ** outer query is distinct.
*/
pParent->selFlags |= pSub->selFlags & SF_Distinct;
-
+
/*
** SELECT ... FROM (SELECT ... LIMIT a OFFSET b) LIMIT x OFFSET y;
**
@@ -88069,7 +82173,7 @@ static int flattenSubquery(
/*
** Analyze the SELECT statement passed as an argument to see if it
-** is a min() or max() query. Return WHERE_ORDERBY_MIN or WHERE_ORDERBY_MAX if
+** is a min() or max() query. Return WHERE_ORDERBY_MIN or WHERE_ORDERBY_MAX if
** it is, or 0 otherwise. At present, a query is considered to be
** a min()/max() query if:
**
@@ -88100,7 +82204,7 @@ static u8 minMaxQuery(Select *p){
/*
** The select statement passed as the first argument is an aggregate query.
-** The second argment is the associated aggregate-info object. This
+** The second argment is the associated aggregate-info object. This
** function tests if the SELECT is of the form:
**
** SELECT count(*) FROM <tbl>
@@ -88115,7 +82219,7 @@ static Table *isSimpleCount(Select *p, AggInfo *pAggInfo){
assert( !p->pGroupBy );
- if( p->pWhere || p->pEList->nExpr!=1
+ if( p->pWhere || p->pEList->nExpr!=1
|| p->pSrc->nSrc!=1 || p->pSrc->a[0].pSelect
){
return 0;
@@ -88135,8 +82239,8 @@ static Table *isSimpleCount(Select *p, AggInfo *pAggInfo){
/*
** If the source-list item passed as an argument was augmented with an
** INDEXED BY clause, then try to locate the specified index. If there
-** was such a clause and the named index cannot be found, return
-** SQLITE_ERROR and leave an error in pParse. Otherwise, populate
+** was such a clause and the named index cannot be found, return
+** SQLITE_ERROR and leave an error in pParse. Otherwise, populate
** pFrom->pIndex and return SQLITE_OK.
*/
SQLITE_PRIVATE int sqlite3IndexedByLookup(Parse *pParse, struct SrcList_item *pFrom){
@@ -88144,8 +82248,8 @@ SQLITE_PRIVATE int sqlite3IndexedByLookup(Parse *pParse, struct SrcList_item *pF
Table *pTab = pFrom->pTab;
char *zIndex = pFrom->zIndex;
Index *pIdx;
- for(pIdx=pTab->pIndex;
- pIdx && sqlite3StrICmp(pIdx->zName, zIndex);
+ for(pIdx=pTab->pIndex;
+ pIdx && sqlite3StrICmp(pIdx->zName, zIndex);
pIdx=pIdx->pNext
);
if( !pIdx ){
@@ -88164,7 +82268,7 @@ SQLITE_PRIVATE int sqlite3IndexedByLookup(Parse *pParse, struct SrcList_item *pF
** (1) Make sure VDBE cursor numbers have been assigned to every
** element of the FROM clause.
**
-** (2) Fill in the pTabList->a[].pTab fields in the SrcList that
+** (2) Fill in the pTabList->a[].pTab fields in the SrcList that
** defines FROM clause. When views appear in the FROM clause,
** fill pTabList->a[].pSelect with a copy of the SELECT statement
** that implements the view. A copy is made of the view's SELECT
@@ -88236,7 +82340,7 @@ static int selectExpander(Walker *pWalker, Select *p){
}else{
/* An ordinary table or view name in the FROM clause */
assert( pFrom->pTab==0 );
- pFrom->pTab = pTab =
+ pFrom->pTab = pTab =
sqlite3LocateTable(pParse,0,pFrom->zName,pFrom->zDatabase);
if( pTab==0 ) return WRC_Abort;
pTab->nRef++;
@@ -88349,7 +82453,7 @@ static int selectExpander(Walker *pWalker, Select *p){
if( (pFrom->jointype & JT_NATURAL)!=0
&& tableAndColumnIndex(pTabList, i, zName, 0, 0)
){
- /* In a NATURAL join, omit the join columns from the
+ /* In a NATURAL join, omit the join columns from the
** table to the right of the join */
continue;
}
@@ -88405,8 +82509,8 @@ static int selectExpander(Walker *pWalker, Select *p){
**
** When this routine is the Walker.xExprCallback then expression trees
** are walked without any actions being taken at each node. Presumably,
-** when this routine is used for Walker.xExprCallback then
-** Walker.xSelectCallback is set to do something useful for every
+** when this routine is used for Walker.xExprCallback then
+** Walker.xSelectCallback is set to do something useful for every
** subquery in the parser tree.
*/
static int exprWalkNoop(Walker *NotUsed, Expr *NotUsed2){
@@ -88457,19 +82561,18 @@ static int selectAddSubqueryTypeInfo(Walker *pWalker, Select *p){
struct SrcList_item *pFrom;
assert( p->selFlags & SF_Resolved );
- if( (p->selFlags & SF_HasTypeInfo)==0 ){
- p->selFlags |= SF_HasTypeInfo;
- pParse = pWalker->pParse;
- pTabList = p->pSrc;
- for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){
- Table *pTab = pFrom->pTab;
- if( ALWAYS(pTab!=0) && (pTab->tabFlags & TF_Ephemeral)!=0 ){
- /* A sub-query in the FROM clause of a SELECT */
- Select *pSel = pFrom->pSelect;
- assert( pSel );
- while( pSel->pPrior ) pSel = pSel->pPrior;
- selectAddColumnTypeAndCollation(pParse, pTab->nCol, pTab->aCol, pSel);
- }
+ assert( (p->selFlags & SF_HasTypeInfo)==0 );
+ p->selFlags |= SF_HasTypeInfo;
+ pParse = pWalker->pParse;
+ pTabList = p->pSrc;
+ for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){
+ Table *pTab = pFrom->pTab;
+ if( ALWAYS(pTab!=0) && (pTab->tabFlags & TF_Ephemeral)!=0 ){
+ /* A sub-query in the FROM clause of a SELECT */
+ Select *pSel = pFrom->pSelect;
+ assert( pSel );
+ while( pSel->pPrior ) pSel = pSel->pPrior;
+ selectAddColumnTypeAndCollation(pParse, pTab->nCol, pTab->aCol, pSel);
}
}
return WRC_Continue;
@@ -88628,18 +82731,6 @@ static void updateAccumulator(Parse *pParse, AggInfo *pAggInfo){
sqlite3ExprCacheClear(pParse);
}
}
-
- /* Before populating the accumulator registers, clear the column cache.
- ** Otherwise, if any of the required column values are already present
- ** in registers, sqlite3ExprCode() may use OP_SCopy to copy the value
- ** to pC->iMem. But by the time the value is used, the original register
- ** may have been used, invalidating the underlying buffer holding the
- ** text or blob value. See ticket [883034dcb5].
- **
- ** Another solution would be to change the OP_SCopy used to copy cached
- ** values to an OP_Copy.
- */
- sqlite3ExprCacheClear(pParse);
for(i=0, pC=pAggInfo->aCol; i<pAggInfo->nAccumulator; i++, pC++){
sqlite3ExprCode(pParse, pC->pExpr, pC->iMem);
}
@@ -88648,7 +82739,7 @@ static void updateAccumulator(Parse *pParse, AggInfo *pAggInfo){
}
/*
-** Generate code for the SELECT statement given in the p argument.
+** Generate code for the SELECT statement given in the p argument.
**
** The results are distributed in various ways depending on the
** contents of the SelectDest structure pointed to by argument pDest
@@ -88665,7 +82756,7 @@ static void updateAccumulator(Parse *pParse, AggInfo *pAggInfo){
** of the query. This destination implies "LIMIT 1".
**
** SRT_Set The result must be a single column. Store each
-** row of result as the key in table pDest->iParm.
+** row of result as the key in table pDest->iParm.
** Apply the affinity pDest->affinity before storing
** results. Used to implement "IN (SELECT ...)".
**
@@ -88732,7 +82823,7 @@ SQLITE_PRIVATE int sqlite3Select(
memset(&sAggInfo, 0, sizeof(sAggInfo));
if( IgnorableOrderby(pDest) ){
- assert(pDest->eDest==SRT_Exists || pDest->eDest==SRT_Union ||
+ assert(pDest->eDest==SRT_Exists || pDest->eDest==SRT_Union ||
pDest->eDest==SRT_Except || pDest->eDest==SRT_Discard);
/* If ORDER BY makes no difference in the output then neither does
** DISTINCT so it can be removed too. */
@@ -88848,20 +82939,8 @@ SQLITE_PRIVATE int sqlite3Select(
isDistinct = 0;
}
- /* If there is both a GROUP BY and an ORDER BY clause and they are
- ** identical, then disable the ORDER BY clause since the GROUP BY
- ** will cause elements to come out in the correct order. This is
- ** an optimization - the correct answer should result regardless.
- ** Use the SQLITE_GroupByOrder flag with SQLITE_TESTCTRL_OPTIMIZER
- ** to disable this optimization for testing purposes.
- */
- if( sqlite3ExprListCompare(p->pGroupBy, pOrderBy)==0
- && (db->flags & SQLITE_GroupByOrder)==0 ){
- pOrderBy = 0;
- }
-
/* If there is an ORDER BY clause, then this sorting
- ** index might end up being unused if the data can be
+ ** index might end up being unused if the data can be
** extracted in pre-sorted order. If that is the case, then the
** OP_OpenEphemeral instruction will be changed to an OP_Noop once
** we figure out that the sorting index is not needed. The addrSortIndex
@@ -88911,7 +82990,7 @@ SQLITE_PRIVATE int sqlite3Select(
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pOrderBy, 0);
if( pWInfo==0 ) goto select_end;
- /* If sorting index that was created by a prior OP_OpenEphemeral
+ /* If sorting index that was created by a prior OP_OpenEphemeral
** instruction ended up not being needed, then change the OP_OpenEphemeral
** into an OP_Noop.
*/
@@ -88956,7 +83035,7 @@ SQLITE_PRIVATE int sqlite3Select(
}
}
-
+
/* Create a label to jump to when we want to abort the query */
addrEnd = sqlite3VdbeMakeLabel(v);
@@ -88999,12 +83078,12 @@ SQLITE_PRIVATE int sqlite3Select(
/* If there is a GROUP BY clause we might need a sorting index to
** implement it. Allocate that sorting index now. If it turns out
** that we do not need it after all, the OpenEphemeral instruction
- ** will be converted into a Noop.
+ ** will be converted into a Noop.
*/
sAggInfo.sortingIdx = pParse->nTab++;
pKeyInfo = keyInfoFromExprList(pParse, pGroupBy);
- addrSortingIdx = sqlite3VdbeAddOp4(v, OP_OpenEphemeral,
- sAggInfo.sortingIdx, sAggInfo.nSortingColumn,
+ addrSortingIdx = sqlite3VdbeAddOp4(v, OP_OpenEphemeral,
+ sAggInfo.sortingIdx, sAggInfo.nSortingColumn,
0, (char*)pKeyInfo, P4_KEYINFO_HANDOFF);
/* Initialize memory locations used by GROUP BY aggregate processing
@@ -89071,7 +83150,7 @@ SQLITE_PRIVATE int sqlite3Select(
int r1 = j + regBase;
int r2;
- r2 = sqlite3ExprCodeGetColumn(pParse,
+ r2 = sqlite3ExprCodeGetColumn(pParse,
pCol->pTab, pCol->iColumn, pCol->iTable, r1);
if( r1!=r2 ){
sqlite3VdbeAddOp2(v, OP_SCopy, r2, r1);
@@ -89183,7 +83262,7 @@ SQLITE_PRIVATE int sqlite3Select(
sqlite3VdbeResolveLabel(v, addrReset);
resetAccumulator(pParse, &sAggInfo);
sqlite3VdbeAddOp1(v, OP_Return, regReset);
-
+
} /* endif pGroupBy. Begin aggregate queries without GROUP BY: */
else {
ExprList *pDel = 0;
@@ -89221,7 +83300,7 @@ SQLITE_PRIVATE int sqlite3Select(
** and pKeyInfo to the KeyInfo structure required to navigate the
** index.
**
- ** In practice the KeyInfo structure will not be used. It is only
+ ** In practice the KeyInfo structure will not be used. It is only
** passed to keep OP_OpenRead happy.
*/
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
@@ -89250,11 +83329,11 @@ SQLITE_PRIVATE int sqlite3Select(
** SELECT max(x) FROM ...
**
** If it is, then ask the code in where.c to attempt to sort results
- ** as if there was an "ORDER ON x" or "ORDER ON x DESC" clause.
+ ** as if there was an "ORDER ON x" or "ORDER ON x DESC" clause.
** If where.c is able to produce results sorted in this order, then
- ** add vdbe code to break out of the processing loop after the
- ** first iteration (since the first iteration of the loop is
- ** guaranteed to operate on the row with the minimum or maximum
+ ** add vdbe code to break out of the processing loop after the
+ ** first iteration (since the first iteration of the loop is
+ ** guaranteed to operate on the row with the minimum or maximum
** value of x, the only row required).
**
** A special flag must be passed to sqlite3WhereBegin() to slightly
@@ -89265,7 +83344,7 @@ SQLITE_PRIVATE int sqlite3Select(
** for x.
**
** + The optimizer code in where.c (the thing that decides which
- ** index or indices to use) should place a different priority on
+ ** index or indices to use) should place a different priority on
** satisfying the 'ORDER BY' clause than it does in other cases.
** Refer to code and comments in where.c for details.
*/
@@ -89280,7 +83359,7 @@ SQLITE_PRIVATE int sqlite3Select(
pMinMax->a[0].pExpr->op = TK_COLUMN;
}
}
-
+
/* This case runs if the aggregate has no GROUP BY clause. The
** processing is much simpler since there is only a single row
** of output.
@@ -89303,12 +83382,12 @@ SQLITE_PRIVATE int sqlite3Select(
pOrderBy = 0;
sqlite3ExprIfFalse(pParse, pHaving, addrEnd, SQLITE_JUMPIFNULL);
- selectInnerLoop(pParse, p, p->pEList, 0, 0, 0, -1,
+ selectInnerLoop(pParse, p, p->pEList, 0, 0, 0, -1,
pDest, addrEnd, addrEnd);
sqlite3ExprListDelete(db, pDel);
}
sqlite3VdbeResolveLabel(v, addrEnd);
-
+
} /* endif aggregate query */
/* If there is an ORDER BY clause, then we need to sort the results
@@ -89349,7 +83428,7 @@ select_end:
** The following code is used for testing and debugging only. The code
** that follows does not appear in normal builds.
**
-** These routines are used to print out the content of all or part of a
+** These routines are used to print out the content of all or part of a
** parse structures such as Select or Expr. Such printouts are useful
** for helping to understand what is happening inside the code generator
** during the execution of complex SELECT statements.
@@ -89551,7 +83630,7 @@ malloc_failed:
** at the conclusion of the call.
**
** The result that is written to ***pazResult is held in memory obtained
-** from malloc(). But the caller cannot free this memory directly.
+** from malloc(). But the caller cannot free this memory directly.
** Instead, the entire table should be passed to sqlite3_free_table() when
** the calling procedure is finished using it.
*/
@@ -89670,7 +83749,7 @@ SQLITE_PRIVATE void sqlite3DeleteTriggerStep(sqlite3 *db, TriggerStep *pTriggerS
}
/*
-** Given table pTab, return a list of all the triggers attached to
+** Given table pTab, return a list of all the triggers attached to
** the table. The list is connected by Trigger.pNext pointers.
**
** All of the triggers on pTab that are in the same database as pTab
@@ -89696,7 +83775,7 @@ SQLITE_PRIVATE Trigger *sqlite3TriggerList(Parse *pParse, Table *pTab){
for(p=sqliteHashFirst(&pTmpSchema->trigHash); p; p=sqliteHashNext(p)){
Trigger *pTrig = (Trigger *)sqliteHashData(p);
if( pTrig->pTabSchema==pTab->pSchema
- && 0==sqlite3StrICmp(pTrig->table, pTab->zName)
+ && 0==sqlite3StrICmp(pTrig->table, pTab->zName)
){
pTrig->pNext = (pList ? pList : pTab->pTrigger);
pList = pTrig;
@@ -89765,15 +83844,14 @@ SQLITE_PRIVATE void sqlite3BeginTrigger(
goto trigger_cleanup;
}
pTab = sqlite3SrcListLookup(pParse, pTableName);
- if( db->init.busy==0 && pName2->n==0 && pTab
- && pTab->pSchema==db->aDb[1].pSchema ){
+ if( pName2->n==0 && pTab && pTab->pSchema==db->aDb[1].pSchema ){
iDb = 1;
}
/* Ensure the table name matches database name and that the table exists */
if( db->mallocFailed ) goto trigger_cleanup;
assert( pTableName->nSrc==1 );
- if( sqlite3FixInit(&sFix, pParse, iDb, "trigger", pName) &&
+ if( sqlite3FixInit(&sFix, pParse, iDb, "trigger", pName) &&
sqlite3FixSrcList(&sFix, pTableName) ){
goto trigger_cleanup;
}
@@ -89823,7 +83901,7 @@ SQLITE_PRIVATE void sqlite3BeginTrigger(
** of triggers.
*/
if( pTab->pSelect && tr_tm!=TK_INSTEAD ){
- sqlite3ErrorMsg(pParse, "cannot create %s trigger on view: %S",
+ sqlite3ErrorMsg(pParse, "cannot create %s trigger on view: %S",
(tr_tm == TK_BEFORE)?"BEFORE":"AFTER", pTableName, 0);
goto trigger_cleanup;
}
@@ -89894,12 +83972,12 @@ SQLITE_PRIVATE void sqlite3FinishTrigger(
TriggerStep *pStepList, /* The triggered program */
Token *pAll /* Token that describes the complete CREATE TRIGGER */
){
- Trigger *pTrig = pParse->pNewTrigger; /* Trigger being finished */
- char *zName; /* Name of trigger */
- sqlite3 *db = pParse->db; /* The database */
- DbFixer sFix; /* Fixer object */
- int iDb; /* Database containing the trigger */
- Token nameToken; /* Trigger name for error reporting */
+ Trigger *pTrig = pParse->pNewTrigger; /* Trigger being finished */
+ char *zName; /* Name of trigger */
+ sqlite3 *db = pParse->db; /* The database */
+ DbFixer sFix;
+ int iDb; /* Database containing the trigger */
+ Token nameToken; /* Trigger name for error reporting */
pTrig = pParse->pNewTrigger;
pParse->pNewTrigger = 0;
@@ -89913,12 +83991,12 @@ SQLITE_PRIVATE void sqlite3FinishTrigger(
}
nameToken.z = pTrig->zName;
nameToken.n = sqlite3Strlen30(nameToken.z);
- if( sqlite3FixInit(&sFix, pParse, iDb, "trigger", &nameToken)
+ if( sqlite3FixInit(&sFix, pParse, iDb, "trigger", &nameToken)
&& sqlite3FixTriggerStep(&sFix, pTrig->step_list) ){
goto triggerfinish_cleanup;
}
- /* if we are not initializing,
+ /* if we are not initializing, and this trigger is not on a TEMP table,
** build the sqlite_master entry
*/
if( !db->init.busy ){
@@ -89968,7 +84046,7 @@ triggerfinish_cleanup:
** a trigger step. Return a pointer to a TriggerStep structure.
**
** The parser calls this routine when it finds a SELECT statement in
-** body of a TRIGGER.
+** body of a TRIGGER.
*/
SQLITE_PRIVATE TriggerStep *sqlite3TriggerSelectStep(sqlite3 *db, Select *pSelect){
TriggerStep *pTriggerStep = sqlite3DbMallocZero(db, sizeof(TriggerStep));
@@ -90087,7 +84165,7 @@ SQLITE_PRIVATE TriggerStep *sqlite3TriggerDeleteStep(
return pTriggerStep;
}
-/*
+/*
** Recursively delete a Trigger structure
*/
SQLITE_PRIVATE void sqlite3DeleteTrigger(sqlite3 *db, Trigger *pTrigger){
@@ -90101,7 +84179,7 @@ SQLITE_PRIVATE void sqlite3DeleteTrigger(sqlite3 *db, Trigger *pTrigger){
}
/*
-** This function is called to drop a trigger from the database schema.
+** This function is called to drop a trigger from the database schema.
**
** This may be called directly from the parser and therefore identifies
** the trigger by name. The sqlite3DropTriggerPtr() routine does the
@@ -90154,7 +84232,7 @@ static Table *tableOfTrigger(Trigger *pTrigger){
/*
-** Drop a trigger given a pointer to that trigger.
+** Drop a trigger given a pointer to that trigger.
*/
SQLITE_PRIVATE void sqlite3DropTriggerPtr(Parse *pParse, Trigger *pTrigger){
Table *pTable;
@@ -90245,12 +84323,12 @@ static int checkColumnOverlap(IdList *pIdList, ExprList *pEList){
for(e=0; e<pEList->nExpr; e++){
if( sqlite3IdListIndex(pIdList, pEList->a[e].zName)>=0 ) return 1;
}
- return 0;
+ return 0;
}
/*
** Return a list of all triggers on table pTab if there exists at least
-** one trigger that must be fired when an operation of type 'op' is
+** one trigger that must be fired when an operation of type 'op' is
** performed on the table, and, if that operation is an UPDATE, if at
** least one of the columns in pChanges is being modified.
*/
@@ -90308,13 +84386,13 @@ static SrcList *targetSrcList(
}
/*
-** Generate VDBE code for the statements inside the body of a single
+** Generate VDBE code for the statements inside the body of a single
** trigger.
*/
static int codeTriggerProgram(
Parse *pParse, /* The parser context */
TriggerStep *pStepList, /* List of statements inside the trigger body */
- int orconf /* Conflict algorithm. (OE_Abort, etc) */
+ int orconf /* Conflict algorithm. (OE_Abort, etc) */
){
TriggerStep *pStep;
Vdbe *v = pParse->pVdbe;
@@ -90341,26 +84419,26 @@ static int codeTriggerProgram(
switch( pStep->op ){
case TK_UPDATE: {
- sqlite3Update(pParse,
+ sqlite3Update(pParse,
targetSrcList(pParse, pStep),
- sqlite3ExprListDup(db, pStep->pExprList, 0),
- sqlite3ExprDup(db, pStep->pWhere, 0),
+ sqlite3ExprListDup(db, pStep->pExprList, 0),
+ sqlite3ExprDup(db, pStep->pWhere, 0),
pParse->eOrconf
);
break;
}
case TK_INSERT: {
- sqlite3Insert(pParse,
+ sqlite3Insert(pParse,
targetSrcList(pParse, pStep),
- sqlite3ExprListDup(db, pStep->pExprList, 0),
- sqlite3SelectDup(db, pStep->pSelect, 0),
- sqlite3IdListDup(db, pStep->pIdList),
+ sqlite3ExprListDup(db, pStep->pExprList, 0),
+ sqlite3SelectDup(db, pStep->pSelect, 0),
+ sqlite3IdListDup(db, pStep->pIdList),
pParse->eOrconf
);
break;
}
case TK_DELETE: {
- sqlite3DeleteFrom(pParse,
+ sqlite3DeleteFrom(pParse,
targetSrcList(pParse, pStep),
sqlite3ExprDup(db, pStep->pWhere, 0)
);
@@ -90374,7 +84452,7 @@ static int codeTriggerProgram(
sqlite3SelectDelete(db, pSelect);
break;
}
- }
+ }
if( pStep->op!=TK_SELECT ){
sqlite3VdbeAddOp0(v, OP_ResetCount);
}
@@ -90418,7 +84496,7 @@ static void transferParseError(Parse *pTo, Parse *pFrom){
}
/*
-** Create and populate a new TriggerPrg object with a sub-program
+** Create and populate a new TriggerPrg object with a sub-program
** implementing trigger pTrigger with ON CONFLICT policy orconf.
*/
static TriggerPrg *codeRowTrigger(
@@ -90440,7 +84518,7 @@ static TriggerPrg *codeRowTrigger(
assert( pTrigger->zName==0 || pTab==tableOfTrigger(pTrigger) );
/* Allocate the TriggerPrg and SubProgram objects. To ensure that they
- ** are freed if an error occurs, link them into the Parse.pTriggerPrg
+ ** are freed if an error occurs, link them into the Parse.pTriggerPrg
** list of the top-level Parse object sooner rather than later. */
pPrg = sqlite3DbMallocZero(db, sizeof(TriggerPrg));
if( !pPrg ) return 0;
@@ -90454,7 +84532,7 @@ static TriggerPrg *codeRowTrigger(
pPrg->aColmask[0] = 0xffffffff;
pPrg->aColmask[1] = 0xffffffff;
- /* Allocate and populate a new Parse context to use for coding the
+ /* Allocate and populate a new Parse context to use for coding the
** trigger sub-program. */
pSubParse = sqlite3StackAllocZero(db, sizeof(Parse));
if( !pSubParse ) return 0;
@@ -90465,11 +84543,10 @@ static TriggerPrg *codeRowTrigger(
pSubParse->pToplevel = pTop;
pSubParse->zAuthContext = pTrigger->zName;
pSubParse->eTriggerOp = pTrigger->op;
- pSubParse->nQueryLoop = pParse->nQueryLoop;
v = sqlite3GetVdbe(pSubParse);
if( v ){
- VdbeComment((v, "Start: %s.%s (%s %s%s%s ON %s)",
+ VdbeComment((v, "Start: %s.%s (%s %s%s%s ON %s)",
pTrigger->zName, onErrorText(orconf),
(pTrigger->tr_tm==TRIGGER_BEFORE ? "BEFORE" : "AFTER"),
(pTrigger->op==TK_UPDATE ? "UPDATE" : ""),
@@ -90478,18 +84555,18 @@ static TriggerPrg *codeRowTrigger(
pTab->zName
));
#ifndef SQLITE_OMIT_TRACE
- sqlite3VdbeChangeP4(v, -1,
+ sqlite3VdbeChangeP4(v, -1,
sqlite3MPrintf(db, "-- TRIGGER %s", pTrigger->zName), P4_DYNAMIC
);
#endif
/* If one was specified, code the WHEN clause. If it evaluates to false
- ** (or NULL) the sub-vdbe is immediately halted by jumping to the
+ ** (or NULL) the sub-vdbe is immediately halted by jumping to the
** OP_Halt inserted at the end of the program. */
if( pTrigger->pWhen ){
pWhen = sqlite3ExprDup(db, pTrigger->pWhen, 0);
- if( SQLITE_OK==sqlite3ResolveExprNames(&sNC, pWhen)
- && db->mallocFailed==0
+ if( SQLITE_OK==sqlite3ResolveExprNames(&sNC, pWhen)
+ && db->mallocFailed==0
){
iEndTrigger = sqlite3VdbeMakeLabel(v);
sqlite3ExprIfFalse(pSubParse, pWhen, iEndTrigger, SQLITE_JUMPIFNULL);
@@ -90525,7 +84602,7 @@ static TriggerPrg *codeRowTrigger(
return pPrg;
}
-
+
/*
** Return a pointer to a TriggerPrg object containing the sub-program for
** trigger pTrigger with default ON CONFLICT algorithm orconf. If no such
@@ -90547,8 +84624,8 @@ static TriggerPrg *getRowTrigger(
** process of being coded). If this is the case, then an entry with
** a matching TriggerPrg.pTrigger field will be present somewhere
** in the Parse.pTriggerPrg list. Search for such an entry. */
- for(pPrg=pRoot->pTriggerPrg;
- pPrg && (pPrg->pTrigger!=pTrigger || pPrg->orconf!=orconf);
+ for(pPrg=pRoot->pTriggerPrg;
+ pPrg && (pPrg->pTrigger!=pTrigger || pPrg->orconf!=orconf);
pPrg=pPrg->pNext
);
@@ -90561,7 +84638,7 @@ static TriggerPrg *getRowTrigger(
}
/*
-** Generate code for the trigger program associated with trigger p on
+** Generate code for the trigger program associated with trigger p on
** table pTab. The reg, orconf and ignoreJump parameters passed to this
** function are the same as those described in the header function for
** sqlite3CodeRowTrigger()
@@ -90579,7 +84656,7 @@ SQLITE_PRIVATE void sqlite3CodeRowTriggerDirect(
pPrg = getRowTrigger(pParse, p, pTab, orconf);
assert( pPrg || pParse->nErr || pParse->db->mallocFailed );
- /* Code the OP_Program opcode in the parent VDBE. P4 of the OP_Program
+ /* Code the OP_Program opcode in the parent VDBE. P4 of the OP_Program
** is a pointer to the sub-vdbe containing the trigger program. */
if( pPrg ){
sqlite3VdbeAddOp3(v, OP_Program, reg, ignoreJump, ++pParse->nMem);
@@ -90607,7 +84684,7 @@ SQLITE_PRIVATE void sqlite3CodeRowTriggerDirect(
** If there are no triggers that fire at the specified time for the specified
** operation on pTab, this function is a no-op.
**
-** The reg argument is the address of the first in an array of registers
+** The reg argument is the address of the first in an array of registers
** that contain the values substituted for the new.* and old.* references
** in the trigger program. If N is the number of columns in table pTab
** (a copy of pTab->nCol), then registers are populated as follows:
@@ -90624,12 +84701,12 @@ SQLITE_PRIVATE void sqlite3CodeRowTriggerDirect(
** reg+N+N+1 NEW.* value of right-most column of pTab
**
** For ON DELETE triggers, the registers containing the NEW.* values will
-** never be accessed by the trigger program, so they are not allocated or
-** populated by the caller (there is no data to populate them with anyway).
+** never be accessed by the trigger program, so they are not allocated or
+** populated by the caller (there is no data to populate them with anyway).
** Similarly, for ON INSERT triggers the values stored in the OLD.* registers
** are never accessed, and so are not allocated by the caller. So, for an
** ON INSERT trigger, the value passed to this function as parameter reg
-** is not a readable register, although registers (reg+N) through
+** is not a readable register, although registers (reg+N) through
** (reg+N+N+1) are.
**
** Parameter orconf is the default conflict resolution algorithm for the
@@ -90661,12 +84738,12 @@ SQLITE_PRIVATE void sqlite3CodeRowTrigger(
** or else it must be a TEMP trigger. */
assert( p->pSchema!=0 );
assert( p->pTabSchema!=0 );
- assert( p->pSchema==p->pTabSchema
+ assert( p->pSchema==p->pTabSchema
|| p->pSchema==pParse->db->aDb[1].pSchema );
/* Determine whether we should code this trigger */
- if( p->op==op
- && p->tr_tm==tr_tm
+ if( p->op==op
+ && p->tr_tm==tr_tm
&& checkColumnOverlap(p->pColumns, pChanges)
){
sqlite3CodeRowTriggerDirect(pParse, p, pTab, reg, orconf, ignoreJump);
@@ -90675,9 +84752,9 @@ SQLITE_PRIVATE void sqlite3CodeRowTrigger(
}
/*
-** Triggers may access values stored in the old.* or new.* pseudo-table.
-** This function returns a 32-bit bitmask indicating which columns of the
-** old.* or new.* tables actually are used by triggers. This information
+** Triggers may access values stored in the old.* or new.* pseudo-table.
+** This function returns a 32-bit bitmask indicating which columns of the
+** old.* or new.* tables actually are used by triggers. This information
** may be used by the caller, for example, to avoid having to load the entire
** old.* record into memory when executing an UPDATE or DELETE command.
**
@@ -90687,7 +84764,7 @@ SQLITE_PRIVATE void sqlite3CodeRowTrigger(
** are more than 32 columns in the table, and at least one of the columns
** with an index greater than 32 may be accessed, 0xffffffff is returned.
**
-** It is not possible to determine if the old.rowid or new.rowid column is
+** It is not possible to determine if the old.rowid or new.rowid column is
** accessed by triggers. The caller must always assume that it is.
**
** Parameter isNew must be either 1 or 0. If it is 0, then the mask returned
@@ -90742,7 +84819,7 @@ SQLITE_PRIVATE u32 sqlite3TriggerColmask(
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
-sqlite*************************************************************************
+*************************************************************************
** This file contains C code routines that are called by the parser
** to handle UPDATE statements.
*/
@@ -90762,10 +84839,10 @@ static void updateVirtualTable(
/*
** The most recently coded instruction was an OP_Column to retrieve the
-** i-th column of table pTab. This routine sets the P4 parameter of the
+** i-th column of table pTab. This routine sets the P4 parameter of the
** OP_Column to the default value, if any.
**
-** The default value of a column is specified by a DEFAULT clause in the
+** The default value of a column is specified by a DEFAULT clause in the
** column definition. This was either supplied by the user when the table
** was created, or added later to the table definition by an ALTER TABLE
** command. If the latter, then the row-records in the table btree on disk
@@ -90774,9 +84851,9 @@ static void updateVirtualTable(
** If the former, then all row-records are guaranteed to include a value
** for the column and the P4 value is not required.
**
-** Column definitions created by an ALTER TABLE command may only have
+** Column definitions created by an ALTER TABLE command may only have
** literal default values specified: a number, null or a string. (If a more
-** complicated default expression value was provided, it is evaluated
+** complicated default expression value was provided, it is evaluated
** when the ALTER TABLE is executed and one of the literal values written
** into the sqlite_master table.)
**
@@ -90786,8 +84863,8 @@ static void updateVirtualTable(
** sqlite3_value objects.
**
** If parameter iReg is not negative, code an OP_RealAffinity instruction
-** on register iReg. This is used when an equivalent integer value is
-** stored in place of an 8-byte floating point value in order to save
+** on register iReg. This is used when an equivalent integer value is
+** stored in place of an 8-byte floating point value in order to save
** space.
*/
SQLITE_PRIVATE void sqlite3ColumnDefault(Vdbe *v, Table *pTab, int i, int iReg){
@@ -90798,7 +84875,7 @@ SQLITE_PRIVATE void sqlite3ColumnDefault(Vdbe *v, Table *pTab, int i, int iReg){
Column *pCol = &pTab->aCol[i];
VdbeComment((v, "%s.%s", pTab->zName, pCol->zName));
assert( i<pTab->nCol );
- sqlite3ValueFromExpr(sqlite3VdbeDb(v), pCol->pDflt, enc,
+ sqlite3ValueFromExpr(sqlite3VdbeDb(v), pCol->pDflt, enc,
pCol->affinity, &pValue);
if( pValue ){
sqlite3VdbeChangeP4(v, -1, (const char *)pValue, P4_MEM);
@@ -90870,7 +84947,7 @@ SQLITE_PRIVATE void sqlite3Update(
}
assert( pTabList->nSrc==1 );
- /* Locate the table which we want to update.
+ /* Locate the table which we want to update.
*/
pTab = sqlite3SrcListLookup(pParse, pTabList);
if( pTab==0 ) goto update_cleanup;
@@ -91068,13 +85145,13 @@ SQLITE_PRIVATE void sqlite3Update(
}
if( !isView ){
- /*
+ /*
** Open every index that needs updating. Note that if any
- ** index could potentially invoke a REPLACE conflict resolution
+ ** index could potentially invoke a REPLACE conflict resolution
** action, then we need to open all indices because we might need
** to be deleting some records.
*/
- if( !okOnePass ) sqlite3OpenTable(pParse, iCur, iDb, pTab, OP_OpenWrite);
+ if( !okOnePass ) sqlite3OpenTable(pParse, iCur, iDb, pTab, OP_OpenWrite);
if( onError==OE_Replace ){
openAll = 1;
}else{
@@ -91120,16 +85197,17 @@ SQLITE_PRIVATE void sqlite3Update(
sqlite3VdbeAddOp1(v, OP_MustBeInt, regNewRowid);
}
- /* If there are triggers on this table, populate an array of registers
+ /* If there are triggers on this table, populate an array of registers
** with the required old.* column data. */
if( hasFK || pTrigger ){
u32 oldmask = (hasFK ? sqlite3FkOldmask(pParse, pTab) : 0);
- oldmask |= sqlite3TriggerColmask(pParse,
+ oldmask |= sqlite3TriggerColmask(pParse,
pTrigger, pChanges, 0, TRIGGER_BEFORE|TRIGGER_AFTER, pTab, onError
);
for(i=0; i<pTab->nCol; i++){
if( aXRef[i]<0 || oldmask==0xffffffff || (oldmask & (1<<i)) ){
- sqlite3ExprCodeGetColumnOfTable(v, pTab, iCur, i, regOld+i);
+ sqlite3VdbeAddOp3(v, OP_Column, iCur, i, regOld+i);
+ sqlite3ColumnDefault(v, pTab, i, regOld+i);
}else{
sqlite3VdbeAddOp2(v, OP_Null, 0, regOld+i);
}
@@ -91147,8 +85225,8 @@ SQLITE_PRIVATE void sqlite3Update(
** If there are one or more BEFORE triggers, then do not populate the
** registers associated with columns that are (a) not modified by
** this UPDATE statement and (b) not accessed by new.* references. The
- ** values for registers not modified by the UPDATE must be reloaded from
- ** the database after the BEFORE triggers are fired anyway (as the trigger
+ ** values for registers not modified by the UPDATE must be reloaded from
+ ** the database after the BEFORE triggers are fired anyway (as the trigger
** may have modified them). So not loading those that are not going to
** be used eliminates some redundant opcodes.
*/
@@ -91163,7 +85241,7 @@ SQLITE_PRIVATE void sqlite3Update(
if( j>=0 ){
sqlite3ExprCode(pParse, pChanges->a[j].pExpr, regNew+i);
}else if( 0==(tmask&TRIGGER_BEFORE) || i>31 || (newmask&(1<<i)) ){
- /* This branch loads the value of a column that will not be changed
+ /* This branch loads the value of a column that will not be changed
** into a register. This is done if there are no BEFORE triggers, or
** if there are one or more BEFORE triggers that use this value via
** a new.* reference in a trigger program.
@@ -91182,20 +85260,20 @@ SQLITE_PRIVATE void sqlite3Update(
if( tmask&TRIGGER_BEFORE ){
sqlite3VdbeAddOp2(v, OP_Affinity, regNew, pTab->nCol);
sqlite3TableAffinityStr(v, pTab);
- sqlite3CodeRowTrigger(pParse, pTrigger, TK_UPDATE, pChanges,
+ sqlite3CodeRowTrigger(pParse, pTrigger, TK_UPDATE, pChanges,
TRIGGER_BEFORE, pTab, regOldRowid, onError, addr);
/* The row-trigger may have deleted the row being updated. In this
- ** case, jump to the next row. No updates or AFTER triggers are
+ ** case, jump to the next row. No updates or AFTER triggers are
** required. This behaviour - what happens when the row being updated
** is deleted or renamed by a BEFORE trigger - is left undefined in the
** documentation.
*/
sqlite3VdbeAddOp3(v, OP_NotExists, iCur, addr, regOldRowid);
- /* If it did not delete it, the row-trigger may still have modified
- ** some of the columns of the row being updated. Load the values for
- ** all columns not modified by the update statement into their
+ /* If it did not delete it, the row-trigger may still have modified
+ ** some of the columns of the row being updated. Load the values for
+ ** all columns not modified by the update statement into their
** registers in case this has happened.
*/
for(i=0; i<pTab->nCol; i++){
@@ -91221,7 +85299,7 @@ SQLITE_PRIVATE void sqlite3Update(
/* Delete the index entries associated with the current record. */
j1 = sqlite3VdbeAddOp3(v, OP_NotExists, iCur, 0, regOldRowid);
sqlite3GenerateRowIndexDelete(pParse, pTab, iCur, aRegIdx);
-
+
/* If changing the record number, delete the old record. */
if( hasFK || chngRowid ){
sqlite3VdbeAddOp2(v, OP_Delete, iCur, 0);
@@ -91231,25 +85309,25 @@ SQLITE_PRIVATE void sqlite3Update(
if( hasFK ){
sqlite3FkCheck(pParse, pTab, 0, regNewRowid);
}
-
+
/* Insert the new index entries and the new record. */
sqlite3CompleteInsertion(pParse, pTab, iCur, regNewRowid, aRegIdx, 1, 0, 0);
/* Do any ON CASCADE, SET NULL or SET DEFAULT operations required to
** handle rows (possibly in other tables) that refer via a foreign key
- ** to the row just updated. */
+ ** to the row just updated. */
if( hasFK ){
sqlite3FkActions(pParse, pTab, pChanges, regOldRowid);
}
}
- /* Increment the row counter
+ /* Increment the row counter
*/
if( (db->flags & SQLITE_CountRows) && !pParse->pTriggerTab){
sqlite3VdbeAddOp2(v, OP_AddImm, regRowCount, 1);
}
- sqlite3CodeRowTrigger(pParse, pTrigger, TK_UPDATE, pChanges,
+ sqlite3CodeRowTrigger(pParse, pTrigger, TK_UPDATE, pChanges,
TRIGGER_AFTER, pTab, regOldRowid, onError, addr);
/* Repeat the above with the next record to be updated, until
@@ -91275,7 +85353,7 @@ SQLITE_PRIVATE void sqlite3Update(
}
/*
- ** Return the number of rows that were changed. If this routine is
+ ** Return the number of rows that were changed. If this routine is
** generating code because of a call to sqlite3NestedParse(), do not
** invoke the callback function.
*/
@@ -91346,7 +85424,7 @@ static void updateVirtualTable(
SelectDest dest;
/* Construct the SELECT statement that will find the new values for
- ** all updated rows.
+ ** all updated rows.
*/
pEList = sqlite3ExprListAppend(pParse, 0, sqlite3Expr(db, TK_ID, "_rowid_"));
if( pRowid ){
@@ -91363,7 +85441,7 @@ static void updateVirtualTable(
pEList = sqlite3ExprListAppend(pParse, pEList, pExpr);
}
pSelect = sqlite3SelectNew(pParse, pEList, pSrc, pWhere, 0, 0, 0, 0, 0, 0);
-
+
/* Create the ephemeral table into which the update results will
** be stored.
*/
@@ -91371,7 +85449,7 @@ static void updateVirtualTable(
ephemTab = pParse->nTab++;
sqlite3VdbeAddOp2(v, OP_OpenEphemeral, ephemTab, pTab->nCol+1+(pRowid!=0));
- /* fill the ephemeral table
+ /* fill the ephemeral table
*/
sqlite3SelectDestInit(&dest, SRT_Table, ephemTab);
sqlite3Select(pParse, pSelect, &dest);
@@ -91393,7 +85471,7 @@ static void updateVirtualTable(
sqlite3VdbeAddOp2(v, OP_Close, ephemTab, 0);
/* Cleanup */
- sqlite3SelectDelete(db, pSelect);
+ sqlite3SelectDelete(db, pSelect);
}
#endif /* SQLITE_OMIT_VIRTUALTABLE */
@@ -91502,23 +85580,22 @@ SQLITE_PRIVATE int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){
void (*saved_xTrace)(void*,const char*); /* Saved db->xTrace */
Db *pDb = 0; /* Database to detach at end of vacuum */
int isMemDb; /* True if vacuuming a :memory: database */
- int nRes; /* Bytes of reserved space at the end of each page */
- int nDb; /* Number of attached databases */
+ int nRes;
if( !db->autoCommit ){
sqlite3SetString(pzErrMsg, db, "cannot VACUUM from within a transaction");
return SQLITE_ERROR;
}
- /* Save the current value of the database flags so that it can be
+ /* 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->flags |= SQLITE_WriteSchema | SQLITE_IgnoreChecks;
+ db->flags &= ~SQLITE_ForeignKeys;
db->xTrace = 0;
pMain = db->aDb[0].pBt;
@@ -91538,18 +85615,15 @@ SQLITE_PRIVATE int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){
** time to parse and run the PRAGMA to turn journalling off than it does
** to write the journal header file.
*/
- nDb = db->nDb;
if( sqlite3TempInMemory(db) ){
zSql = "ATTACH ':memory:' AS vacuum_db;";
}else{
zSql = "ATTACH '' AS vacuum_db;";
}
rc = execSql(db, pzErrMsg, zSql);
- if( db->nDb>nDb ){
- pDb = &db->aDb[db->nDb-1];
- assert( strcmp(pDb->zName,"vacuum_db")==0 );
- }
if( rc!=SQLITE_OK ) goto end_of_vacuum;
+ pDb = &db->aDb[db->nDb-1];
+ assert( strcmp(db->aDb[db->nDb-1].zName,"vacuum_db")==0 );
pTemp = db->aDb[db->nDb-1].pBt;
/* The call to execSql() to attach the temp database has left the file
@@ -91571,12 +85645,6 @@ SQLITE_PRIVATE int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){
}
#endif
- /* Do not attempt to change the page size for a WAL database */
- if( sqlite3PagerJournalMode(sqlite3BtreePager(pMain),
- PAGER_JOURNALMODE_QUERY)==PAGER_JOURNALMODE_WAL ){
- db->nextPagesize = 0;
- }
-
if( sqlite3BtreeSetPageSize(pTemp, sqlite3BtreeGetPageSize(pMain), nRes, 0)
|| (!isMemDb && sqlite3BtreeSetPageSize(pTemp, db->nextPagesize, nRes, 0))
|| NEVER(db->mallocFailed)
@@ -91713,7 +85781,6 @@ end_of_vacuum:
db->nChange = saved_nChange;
db->nTotalChange = saved_nTotalChange;
db->xTrace = saved_xTrace;
- sqlite3BtreeSetPageSize(pMain, -1, -1, 1);
/* Currently there is an SQL level transaction open on the vacuum
** database. No locks are held on any other files (since the main file
@@ -91825,7 +85892,7 @@ SQLITE_API int sqlite3_create_module_v2(
/*
** Lock the virtual table so that it cannot be disconnected.
** Locks nest. Every lock should have a corresponding unlock.
-** If an unlock is omitted, resources leaks will occur.
+** If an unlock is omitted, resources leaks will occur.
**
** If a disconnect is attempted while a virtual table is locked,
** the disconnect is deferred until all locks have been removed.
@@ -91837,7 +85904,7 @@ SQLITE_PRIVATE void sqlite3VtabLock(VTable *pVTab){
/*
** pTab is a pointer to a Table structure representing a virtual-table.
-** Return a pointer to the VTable object used by connection db to access
+** Return a pointer to the VTable object used by connection db to access
** this virtual-table, if one has been created, or NULL otherwise.
*/
SQLITE_PRIVATE VTable *sqlite3GetVTable(sqlite3 *db, Table *pTab){
@@ -91871,7 +85938,7 @@ SQLITE_PRIVATE void sqlite3VtabUnlock(VTable *pVTab){
/*
** Table p is a virtual table. This function moves all elements in the
** p->pVTable list to the sqlite3.pDisconnect lists of their associated
-** database connections to be disconnected at the next opportunity.
+** database connections to be disconnected at the next opportunity.
** Except, if argument db is not NULL, then the entry associated with
** connection db is left in the p->pVTable list.
*/
@@ -91880,13 +85947,13 @@ static VTable *vtabDisconnectAll(sqlite3 *db, Table *p){
VTable *pVTable = p->pVTable;
p->pVTable = 0;
- /* Assert that the mutex (if any) associated with the BtShared database
- ** that contains table p is held by the caller. See header comments
+ /* Assert that the mutex (if any) associated with the BtShared database
+ ** that contains table p is held by the caller. See header comments
** above function sqlite3VtabUnlockList() for an explanation of why
** this makes it safe to access the sqlite3.pDisconnect list of any
** database connection that may have an entry in the p->pVTable list. */
assert( db==0 ||
- sqlite3BtreeHoldsMutex(db->aDb[sqlite3SchemaToIndex(db, p->pSchema)].pBt)
+ sqlite3BtreeHoldsMutex(db->aDb[sqlite3SchemaToIndex(db, p->pSchema)].pBt)
);
while( pVTable ){
@@ -91913,7 +85980,7 @@ static VTable *vtabDisconnectAll(sqlite3 *db, Table *p){
** Disconnect all the virtual table objects in the sqlite3.pDisconnect list.
**
** This function may only be called when the mutexes associated with all
-** shared b-tree databases opened using connection db are held by the
+** shared b-tree databases opened using connection db are held by the
** caller. This is done to protect the sqlite3.pDisconnect list. The
** sqlite3.pDisconnect list is accessed only as follows:
**
@@ -91926,7 +85993,7 @@ static VTable *vtabDisconnectAll(sqlite3 *db, Table *p){
** or, if the virtual table is stored in a non-sharable database, then
** the database handle mutex is held.
**
-** As a result, a sqlite3.pDisconnect cannot be accessed simultaneously
+** As a result, a sqlite3.pDisconnect cannot be accessed simultaneously
** by multiple threads. It is thread-safe.
*/
SQLITE_PRIVATE void sqlite3VtabUnlockList(sqlite3 *db){
@@ -91952,12 +86019,12 @@ SQLITE_PRIVATE void sqlite3VtabUnlockList(sqlite3 *db){
** record.
**
** Since it is a virtual-table, the Table structure contains a pointer
-** to the head of a linked list of VTable structures. Each VTable
+** to the head of a linked list of VTable structures. Each VTable
** structure is associated with a single sqlite3* user of the schema.
-** The reference count of the VTable structure associated with database
-** connection db is decremented immediately (which may lead to the
+** The reference count of the VTable structure associated with database
+** connection db is decremented immediately (which may lead to the
** structure being xDisconnected and free). Any other VTable structures
-** in the list are moved to the sqlite3.pDisconnect list of the associated
+** in the list are moved to the sqlite3.pDisconnect list of the associated
** database connection.
*/
SQLITE_PRIVATE void sqlite3VtabClear(Table *p){
@@ -92035,7 +86102,7 @@ SQLITE_PRIVATE void sqlite3VtabBeginParse(
** The second call, to obtain permission to create the table, is made now.
*/
if( pTable->azModuleArg ){
- sqlite3AuthCheck(pParse, SQLITE_CREATE_VTABLE, pTable->zName,
+ sqlite3AuthCheck(pParse, SQLITE_CREATE_VTABLE, pTable->zName,
pTable->azModuleArg[0], pParse->db->aDb[iDb].zName);
}
#endif
@@ -92067,7 +86134,7 @@ SQLITE_PRIVATE void sqlite3VtabFinishParse(Parse *pParse, Token *pEnd){
addArgumentToVtab(pParse);
pParse->sArg.z = 0;
if( pTab->nModuleArg<1 ) return;
-
+
/* If the CREATE VIRTUAL TABLE statement is being entered for the
** first time (in other words if the virtual table is actually being
** created now instead of just being read out of sqlite_master) then
@@ -92086,9 +86153,9 @@ SQLITE_PRIVATE void sqlite3VtabFinishParse(Parse *pParse, Token *pEnd){
}
zStmt = sqlite3MPrintf(db, "CREATE VIRTUAL TABLE %T", &pParse->sNameToken);
- /* A slot for the record has already been allocated in the
+ /* A slot for the record has already been allocated in the
** SQLITE_MASTER table. We just need to update that slot with all
- ** the information we've collected.
+ ** the information we've collected.
**
** The VM register number pParse->regRowid holds the rowid of an
** entry in the sqlite_master table tht was created for this vtab
@@ -92112,7 +86179,7 @@ SQLITE_PRIVATE void sqlite3VtabFinishParse(Parse *pParse, Token *pEnd){
sqlite3VdbeAddOp2(v, OP_Expire, 0, 0);
zWhere = sqlite3MPrintf(db, "name='%q'", pTab->zName);
sqlite3VdbeAddOp4(v, OP_ParseSchema, iDb, 1, 0, zWhere, P4_DYNAMIC);
- sqlite3VdbeAddOp4(v, OP_VCreate, iDb, 0, 0,
+ sqlite3VdbeAddOp4(v, OP_VCreate, iDb, 0, 0,
pTab->zName, sqlite3Strlen30(pTab->zName) + 1);
}
@@ -92168,7 +86235,7 @@ SQLITE_PRIVATE void sqlite3VtabArgExtend(Parse *pParse, Token *p){
** to this procedure.
*/
static int vtabCallConstructor(
- sqlite3 *db,
+ sqlite3 *db,
Table *pTab,
Module *pMod,
int (*xConstruct)(sqlite3*,void*,int,const char*const*,sqlite3_vtab**,char**),
@@ -92222,7 +86289,7 @@ static int vtabCallConstructor(
}else{
int iCol;
/* If everything went according to plan, link the new VTable structure
- ** into the linked list headed by pTab->pVTable. Then loop through the
+ ** into the linked list headed by pTab->pVTable. Then loop through the
** columns of the table to see if any of them contain the token "hidden".
** If so, set the Column.isHidden flag and remove the token from
** the type string. */
@@ -92268,7 +86335,7 @@ static int vtabCallConstructor(
/*
** This function is invoked by the parser to call the xConnect() method
-** of the virtual table pTab. If an error occurs, an error code is returned
+** of the virtual table pTab. If an error occurs, an error code is returned
** and an error left in pParse.
**
** This call is a no-op if table pTab is not a virtual table.
@@ -92330,7 +86397,7 @@ static int addToVTrans(sqlite3 *db, VTable *pVTab){
/*
** This function is invoked by the vdbe to call the xCreate method
-** of the virtual table named zTab in database iDb.
+** of the virtual table named zTab in database iDb.
**
** If an error occurs, *pzErr is set to point an an English language
** description of the error and an SQLITE_XXX error code is returned.
@@ -92349,8 +86416,8 @@ SQLITE_PRIVATE int sqlite3VtabCallCreate(sqlite3 *db, int iDb, const char *zTab,
zMod = pTab->azModuleArg[0];
pMod = (Module*)sqlite3HashFind(&db->aModule, zMod, sqlite3Strlen30(zMod));
- /* If the module has been registered and includes a Create method,
- ** invoke it now. If the module has not been registered, return an
+ /* If the module has been registered and includes a Create method,
+ ** invoke it now. If the module has not been registered, return an
** error. Otherwise, do nothing.
*/
if( !pMod ){
@@ -92396,9 +86463,8 @@ SQLITE_API int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){
}else{
pParse->declareVtab = 1;
pParse->db = db;
- pParse->nQueryLoop = 1;
-
- if( SQLITE_OK==sqlite3RunParser(pParse, zCreateTable, &zErr)
+
+ if( SQLITE_OK==sqlite3RunParser(pParse, zCreateTable, &zErr)
&& pParse->pNewTable
&& !db->mallocFailed
&& !pParse->pNewTable->pSelect
@@ -92417,7 +86483,7 @@ SQLITE_API int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){
rc = SQLITE_ERROR;
}
pParse->declareVtab = 0;
-
+
if( pParse->pVdbe ){
sqlite3VdbeFinalize(pParse->pVdbe);
}
@@ -92467,7 +86533,7 @@ SQLITE_PRIVATE int sqlite3VtabCallDestroy(sqlite3 *db, int iDb, const char *zTab
** called is identified by the second argument, "offset", which is
** the offset of the method to call in the sqlite3_module structure.
**
-** The array is cleared after invoking the callbacks.
+** The array is cleared after invoking the callbacks.
*/
static void callFinaliser(sqlite3 *db, int offset){
int i;
@@ -92493,7 +86559,7 @@ 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
+** Set *pzErrmsg to point to a buffer that should be released using
** sqlite3DbFree() containing an error message, if one is available.
*/
SQLITE_PRIVATE int sqlite3VtabSync(sqlite3 *db, char **pzErrmsg){
@@ -92517,7 +86583,7 @@ SQLITE_PRIVATE int sqlite3VtabSync(sqlite3 *db, char **pzErrmsg){
}
/*
-** Invoke the xRollback method of all virtual tables in the
+** Invoke the xRollback method of all virtual tables in the
** sqlite3.aVTrans array. Then clear the array itself.
*/
SQLITE_PRIVATE int sqlite3VtabRollback(sqlite3 *db){
@@ -92526,7 +86592,7 @@ SQLITE_PRIVATE int sqlite3VtabRollback(sqlite3 *db){
}
/*
-** Invoke the xCommit method of all virtual tables in the
+** Invoke the xCommit method of all virtual tables in the
** sqlite3.aVTrans array. Then clear the array itself.
*/
SQLITE_PRIVATE int sqlite3VtabCommit(sqlite3 *db){
@@ -92548,7 +86614,7 @@ SQLITE_PRIVATE int sqlite3VtabBegin(sqlite3 *db, VTable *pVTab){
/* Special case: If db->aVTrans is NULL and db->nVTrans is greater
** than zero, then this function is being called from within a
- ** virtual module xSync() callback. It is illegal to write to
+ ** virtual module xSync() callback. It is illegal to write to
** virtual module tables in this case, so return SQLITE_LOCKED.
*/
if( sqlite3VtabInSync(db) ){
@@ -92556,7 +86622,7 @@ SQLITE_PRIVATE int sqlite3VtabBegin(sqlite3 *db, VTable *pVTab){
}
if( !pVTab ){
return SQLITE_OK;
- }
+ }
pModule = pVTab->pVtab->pModule;
if( pModule->xBegin ){
@@ -92588,7 +86654,7 @@ SQLITE_PRIVATE int sqlite3VtabBegin(sqlite3 *db, VTable *pVTab){
** This routine is used to allow virtual table implementations to
** overload MATCH, LIKE, GLOB, and REGEXP operators.
**
-** Return either the pDef argument (indicating no change) or a
+** Return either the pDef argument (indicating no change) or a
** new FuncDef structure that is marked as ephemeral using the
** SQLITE_FUNC_EPHEM flag.
*/
@@ -92620,9 +86686,9 @@ SQLITE_PRIVATE FuncDef *sqlite3VtabOverloadFunction(
assert( pVtab->pModule!=0 );
pMod = (sqlite3_module *)pVtab->pModule;
if( pMod->xFindFunction==0 ) return pDef;
-
+
/* Call the xFindFunction method on the virtual table implementation
- ** to see if the implementation wants to overload this function
+ ** to see if the implementation wants to overload this function
*/
zLowerName = sqlite3DbStrDup(db, pDef->zName);
if( zLowerName ){
@@ -92726,7 +86792,7 @@ typedef struct WhereCost WhereCost;
** clause subexpression is separated from the others by AND operators,
** usually, or sometimes subexpressions separated by OR.
**
-** All WhereTerms are collected into a single WhereClause structure.
+** All WhereTerms are collected into a single WhereClause structure.
** The following identity holds:
**
** WhereTerm.pWC->a[WhereTerm.idx] == WhereTerm
@@ -92840,8 +86906,8 @@ struct WhereAndInfo {
** An instance of the following structure keeps track of a mapping
** between VDBE cursor numbers and bits of the bitmasks in WhereTerm.
**
-** The VDBE cursor numbers are small integers contained in
-** SrcList_item.iCursor and Expr.iTable fields. For any given WHERE
+** The VDBE cursor numbers are small integers contained in
+** SrcList_item.iCursor and Expr.iTable fields. For any given WHERE
** clause, the cursor numbers might not begin with 0 and they might
** contain gaps in the numbering sequence. But we want to make maximum
** use of the bits in our bitmasks. This structure provides a mapping
@@ -92917,7 +86983,6 @@ struct WhereCost {
#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 0x000f3000 /* Does not do a full table scan */
#define WHERE_IN_ABLE 0x000f1000 /* 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 */
@@ -92927,7 +86992,6 @@ struct WhereCost {
#define WHERE_UNIQUE 0x04000000 /* Selects no more than one 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 */
/*
** Initialize a preallocated WhereClause structure.
@@ -93174,9 +87238,9 @@ static int allowedOp(int op){
**
** If a collation sequence is associated with either the left or right
** side of the comparison, it remains associated with the same side after
-** the commutation. So "Y collate NOCASE op X" becomes
+** the commutation. So "Y collate NOCASE op X" becomes
** "X collate NOCASE op Y". This is because any collation sequence on
-** the left hand side of a comparison overrides any collation sequence
+** the left hand side of a comparison overrides any collation sequence
** attached to the right. For the same reason the EP_ExpCollate flag
** is not commuted.
*/
@@ -93281,7 +87345,7 @@ static WhereTerm *findTerm(
static void exprAnalyze(SrcList*, WhereClause*, int);
/*
-** Call exprAnalyze on all terms in a WHERE clause.
+** Call exprAnalyze on all terms in a WHERE clause.
**
**
*/
@@ -93302,7 +87366,7 @@ static void exprAnalyzeAll(
** so and false if not.
**
** In order for the operator to be optimizible, the RHS must be a string
-** literal that does not begin with a wildcard.
+** literal that does not begin with a wildcard.
*/
static int isLikeOrGlob(
Parse *pParse, /* Parsing and code generating context */
@@ -93337,7 +87401,7 @@ static int isLikeOrGlob(
}
assert( pLeft->iColumn!=(-1) ); /* Because IPK never has AFF_TEXT */
pColl = sqlite3ExprCollSeq(pParse, pLeft);
- if( pColl==0 ) return 0; /* Happens when LHS has an undefined collation */
+ assert( pColl!=0 ); /* Every non-IPK column has a collating sequence */
if( (pColl->type!=SQLITE_COLL_BINARY || *pnoCase) &&
(pColl->type!=SQLITE_COLL_NOCASE || !*pnoCase) ){
/* IMP: R-09003-32046 For the GLOB operator, the column must use the
@@ -93386,7 +87450,7 @@ static int isLikeOrGlob(
** function, then no OP_Variable will be added to the program.
** This causes problems for the sqlite3_bind_parameter_name()
** API. To workaround them, add a dummy OP_Variable here.
- */
+ */
int r1 = sqlite3GetTempReg(pParse);
sqlite3ExprCodeTarget(pParse, pRight, r1);
sqlite3VdbeChangeP3(v, sqlite3VdbeCurrentAddr(v)-1, 0);
@@ -93489,10 +87553,10 @@ static void transferJoinMarkings(Expr *pDerived, Expr *pBase){
** WhereTerm.u.pOrInfo->indexable |= the cursor number for table T
**
** A subterm is "indexable" if it is of the form
-** "T.C <op> <expr>" where C is any column of table T and
+** "T.C <op> <expr>" where C is any column of table T and
** <op> is one of "=", "<", "<=", ">", ">=", "IS NULL", or "IN".
** A subterm is also indexable if it is an AND of two or more
-** subsubterms at least one of which is indexable. Indexable AND
+** subsubterms at least one of which is indexable. Indexable AND
** subterms have their eOperator set to WO_AND and they have
** u.pAndInfo set to a dynamically allocated WhereAndTerm object.
**
@@ -93662,7 +87726,7 @@ static void exprAnalyzeOrTerm(
if( (chngToIN & getMask(pMaskSet, 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
+ ** or follwed by an inverted copy (t2.b==t1.a). Skip this term
** and use its inversion. */
testcase( pOrTerm->wtFlags & TERM_COPIED );
testcase( pOrTerm->wtFlags & TERM_VIRTUAL );
@@ -93710,7 +87774,7 @@ 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
+ ** case 1. In that case, construct a new virtual term that is
** pTerm converted into an IN operator.
*/
if( okToChngToIN ){
@@ -93780,7 +87844,7 @@ static void exprAnalyze(
Expr *pExpr; /* The expression to be analyzed */
Bitmask prereqLeft; /* Prerequesites of the pExpr->pLeft */
Bitmask prereqAll; /* Prerequesites of pExpr */
- Bitmask extraRight = 0; /* Extra dependencies on LEFT JOIN */
+ Bitmask extraRight = 0; /* */
Expr *pStr1 = 0; /* RHS of LIKE/GLOB operator */
int isComplete = 0; /* RHS of LIKE/GLOB ends with wildcard */
int noCase = 0; /* LIKE/GLOB distinguishes case */
@@ -93852,8 +87916,7 @@ static void exprAnalyze(
pLeft = pDup->pLeft;
pNew->leftCursor = pLeft->iTable;
pNew->u.leftColumn = pLeft->iColumn;
- testcase( (prereqLeft | extraRight) != prereqLeft );
- pNew->prereqRight = prereqLeft | extraRight;
+ pNew->prereqRight = prereqLeft;
pNew->prereqAll = prereqAll;
pNew->eOperator = operatorMask(pDup->op);
}
@@ -93884,7 +87947,7 @@ static void exprAnalyze(
for(i=0; i<2; i++){
Expr *pNewExpr;
int idxNew;
- pNewExpr = sqlite3PExpr(pParse, ops[i],
+ pNewExpr = sqlite3PExpr(pParse, ops[i],
sqlite3ExprDup(db, pExpr->pLeft, 0),
sqlite3ExprDup(db, pList->a[i].pExpr, 0), 0);
idxNew = whereClauseInsert(pWC, pNewExpr, TERM_VIRTUAL|TERM_DYNAMIC);
@@ -93919,7 +87982,7 @@ static void exprAnalyze(
** The last character of the prefix "abc" is incremented to form the
** termination condition "abd".
*/
- if( pWC->op==TK_AND
+ if( pWC->op==TK_AND
&& isLikeOrGlob(pParse, pExpr, &pStr1, &isComplete, &noCase)
){
Expr *pLeft; /* LHS of LIKE/GLOB operator */
@@ -93938,7 +88001,7 @@ static void exprAnalyze(
if( noCase ){
/* The point is to increment the last character before the first
** wildcard. But if we increment '@', that will push it into the
- ** alphabetic range where case conversions will mess up the
+ ** alphabetic range where case conversions will mess up the
** inequality. To avoid this, make sure to also run the full
** LIKE on all candidate expressions by clearing the isComplete flag
*/
@@ -93984,7 +88047,7 @@ static void exprAnalyze(
prereqColumn = exprTableUsage(pMaskSet, pLeft);
if( (prereqExpr & prereqColumn)==0 ){
Expr *pNewExpr;
- pNewExpr = sqlite3PExpr(pParse, TK_MATCH,
+ pNewExpr = sqlite3PExpr(pParse, TK_MATCH,
0, sqlite3ExprDup(db, pRight, 0), 0);
idxNew = whereClauseInsert(pWC, pNewExpr, TERM_VIRTUAL|TERM_DYNAMIC);
testcase( idxNew==0 );
@@ -94066,7 +88129,7 @@ static int isSortingIndex(
nTerm = pOrderBy->nExpr;
assert( nTerm>0 );
- /* Argument pIdx must either point to a 'real' named index structure,
+ /* 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) );
@@ -94144,7 +88207,7 @@ static int isSortingIndex(
if( iColumn<0 && !referencesOtherTables(pOrderBy, pMaskSet, j, base) ){
/* If the indexed column is the primary key and everything matches
** so far and none of the ORDER BY terms to the right reference other
- ** tables in the join, then we are assured that the index can be used
+ ** tables in the join, then we are assured that the index can be used
** to sort because the primary key is unique and so none of the other
** columns will make any difference
*/
@@ -94230,15 +88293,15 @@ static void TRACE_IDX_OUTPUTS(sqlite3_index_info *p){
#define TRACE_IDX_OUTPUTS(A)
#endif
-/*
-** Required because bestIndex() is called by bestOrClauseIndex()
+/*
+** Required because bestIndex() is called by bestOrClauseIndex()
*/
static void bestIndex(
Parse*, WhereClause*, struct SrcList_item*, Bitmask, ExprList*, WhereCost*);
/*
-** This routine attempts to find an scanning strategy that can be used
-** to optimize an 'OR' expression that is part of a WHERE clause.
+** 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.
@@ -94257,16 +88320,11 @@ static void bestOrClauseIndex(
WhereTerm * const pWCEnd = &pWC->a[pWC->nTerm]; /* End of pWC->a[] */
WhereTerm *pTerm; /* A single term of the WHERE clause */
- /* No OR-clause optimization allowed if the NOT INDEXED clause is used */
- if( pSrc->notIndexed ){
- return;
- }
-
/* Search the WHERE clause terms for a usable WO_OR term. */
for(pTerm=pWC->a; pTerm<pWCEnd; pTerm++){
- if( pTerm->eOperator==WO_OR
+ if( pTerm->eOperator==WO_OR
&& ((pTerm->prereqAll & ~maskSrc) & notReady)==0
- && (pTerm->u.pOrInfo->indexable & maskSrc)!=0
+ && (pTerm->u.pOrInfo->indexable & maskSrc)!=0
){
WhereClause * const pOrWC = &pTerm->u.pOrInfo->wc;
WhereTerm * const pOrWCEnd = &pOrWC->a[pOrWC->nTerm];
@@ -94278,7 +88336,7 @@ static void bestOrClauseIndex(
for(pOrTerm=pOrWC->a; pOrTerm<pOrWCEnd; pOrTerm++){
WhereCost sTermCost;
- WHERETRACE(("... Multi-index OR testing for term %d of %d....\n",
+ WHERETRACE(("... Multi-index OR testing for term %d of %d....\n",
(pOrTerm - pOrWC->a), (pTerm - pWC->a)
));
if( pOrTerm->eOperator==WO_AND ){
@@ -94301,12 +88359,11 @@ static void bestOrClauseIndex(
if( rTotal>=pCost->rCost ) break;
}
- /* If there is an ORDER BY clause, increase the scan cost to account
+ /* If there is an ORDER BY clause, increase the scan cost to account
** for the cost of the sort. */
if( pOrderBy!=0 ){
- WHERETRACE(("... sorting increases OR cost %.9g to %.9g\n",
- rTotal, rTotal+nRow*estLog(nRow)));
rTotal += nRow*estLog(nRow);
+ WHERETRACE(("... sorting increases OR cost to %.9g\n", rTotal));
}
/* If the cost of scanning using this OR term for optimization is
@@ -94325,255 +88382,14 @@ static void bestOrClauseIndex(
#endif /* SQLITE_OMIT_OR_OPTIMIZATION */
}
-#ifndef SQLITE_OMIT_AUTOMATIC_INDEX
-/*
-** Return TRUE if the WHERE clause term pTerm is of a form where it
-** could be used with an index to access pSrc, assuming an appropriate
-** index existed.
-*/
-static int termCanDriveIndex(
- WhereTerm *pTerm, /* WHERE clause term to check */
- struct SrcList_item *pSrc, /* Table we are trying to access */
- Bitmask notReady /* Tables in outer loops of the join */
-){
- char aff;
- if( pTerm->leftCursor!=pSrc->iCursor ) return 0;
- if( pTerm->eOperator!=WO_EQ ) return 0;
- if( (pTerm->prereqRight & notReady)!=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(
- Parse *pParse, /* The parsing context */
- WhereClause *pWC, /* The WHERE clause */
- struct SrcList_item *pSrc, /* The FROM clause term to search */
- Bitmask notReady, /* Mask of cursors that are not available */
- WhereCost *pCost /* Lowest cost query plan */
-){
- 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->db->flags & SQLITE_AutoIndex)==0 ){
- /* Automatic indices are disabled at run-time */
- return;
- }
- if( (pCost->plan.wsFlags & WHERE_NOT_FULLSCAN)!=0 ){
- /* We already have some kind of index in use for this query. */
- return;
- }
- if( pSrc->notIndexed ){
- /* The NOT INDEXED clause appears in the SQL. */
- return;
- }
-
- assert( pParse->nQueryLoop >= (double)1 );
- pTable = pSrc->pTab;
- nTableRow = pTable->pIndex ? pTable->pIndex->aiRowEst[0] : 1000000;
- logN = estLog(nTableRow);
- costTempIdx = 2*logN*(nTableRow/pParse->nQueryLoop + 1);
- if( costTempIdx>=pCost->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, notReady) ){
- WHERETRACE(("auto-index reduces cost from %.2f to %.2f\n",
- pCost->rCost, costTempIdx));
- pCost->rCost = costTempIdx;
- pCost->nRow = logN + 1;
- pCost->plan.wsFlags = WHERE_TEMP_INDEX;
- pCost->used = pTerm->prereqRight;
- break;
- }
- }
-}
-#else
-# define bestAutomaticIndex(A,B,C,D,E) /* no-op */
-#endif /* SQLITE_OMIT_AUTOMATIC_INDEX */
-
-
-#ifndef SQLITE_OMIT_AUTOMATIC_INDEX
-/*
-** Generate code to construct the Index object for an automatic index
-** and to set up the WhereLevel object pLevel so that the code generator
-** makes use of the automatic index.
-*/
-static void constructAutomaticIndex(
- Parse *pParse, /* The parsing context */
- WhereClause *pWC, /* The WHERE clause */
- struct SrcList_item *pSrc, /* The FROM clause term to get the next index */
- Bitmask notReady, /* Mask of cursors that are not available */
- WhereLevel *pLevel /* Write new index here */
-){
- int nColumn; /* Number of columns in the constructed index */
- WhereTerm *pTerm; /* A single term of the WHERE clause */
- WhereTerm *pWCEnd; /* End of pWC->a[] */
- int nByte; /* Byte of memory needed for pIdx */
- Index *pIdx; /* Object describing the transient index */
- Vdbe *v; /* Prepared statement under construction */
- int regIsInit; /* Register set by initialization */
- int addrInit; /* Address of the initialization bypass jump */
- Table *pTable; /* The table being indexed */
- KeyInfo *pKeyinfo; /* Key information for the index */
- int addrTop; /* Top of the index fill loop */
- int regRecord; /* Register holding an index record */
- int n; /* Column counter */
- int i; /* Loop counter */
- int mxBitCol; /* Maximum column in pSrc->colUsed */
- CollSeq *pColl; /* Collating sequence to on a column */
- Bitmask idxCols; /* Bitmap of columns used for indexing */
- Bitmask extraCols; /* Bitmap of additional columns */
-
- /* Generate code to skip over the creation and initialization of the
- ** transient index on 2nd and subsequent iterations of the loop. */
- v = pParse->pVdbe;
- assert( v!=0 );
- regIsInit = ++pParse->nMem;
- addrInit = sqlite3VdbeAddOp1(v, OP_If, regIsInit);
- sqlite3VdbeAddOp2(v, OP_Integer, 1, regIsInit);
-
- /* Count the number of columns that will be added to the index
- ** and used to match WHERE clause constraints */
- nColumn = 0;
- pTable = pSrc->pTab;
- pWCEnd = &pWC->a[pWC->nTerm];
- 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;
- testcase( iCol==BMS );
- testcase( iCol==BMS-1 );
- if( (idxCols & cMask)==0 ){
- nColumn++;
- idxCols |= cMask;
- }
- }
- }
- assert( nColumn>0 );
- pLevel->plan.nEq = nColumn;
-
- /* Count the number of additional columns needed to create a
- ** covering index. A "covering index" is an index that contains all
- ** columns that are needed by the query. With a covering index, the
- ** original table never needs to be accessed. Automatic indices must
- ** be a covering index because the index will not be updated if the
- ** 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)));
- 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( pSrc->colUsed & (((Bitmask)1)<<(BMS-1)) ){
- nColumn += pTable->nCol - BMS + 1;
- }
- pLevel->plan.wsFlags |= WHERE_COLUMN_EQ | WHERE_IDX_ONLY | WO_EQ;
-
- /* Construct the Index object to describe this index */
- nByte = sizeof(Index);
- nByte += nColumn*sizeof(int); /* Index.aiColumn */
- nByte += nColumn*sizeof(char*); /* Index.azColl */
- nByte += nColumn; /* Index.aSortOrder */
- pIdx = sqlite3DbMallocZero(pParse->db, nByte);
- if( pIdx==0 ) return;
- pLevel->plan.u.pIdx = pIdx;
- pIdx->azColl = (char**)&pIdx[1];
- pIdx->aiColumn = (int*)&pIdx->azColl[nColumn];
- pIdx->aSortOrder = (u8*)&pIdx->aiColumn[nColumn];
- pIdx->zName = "auto-index";
- pIdx->nColumn = nColumn;
- pIdx->pTable = pTable;
- n = 0;
- 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;
- if( (idxCols & cMask)==0 ){
- Expr *pX = pTerm->pExpr;
- idxCols |= cMask;
- pIdx->aiColumn[n] = pTerm->u.leftColumn;
- pColl = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft, pX->pRight);
- pIdx->azColl[n] = pColl->zName;
- n++;
- }
- }
- }
- assert( n==pLevel->plan.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) ){
- pIdx->aiColumn[n] = i;
- pIdx->azColl[n] = "BINARY";
- n++;
- }
- }
- if( pSrc->colUsed & (((Bitmask)1)<<(BMS-1)) ){
- for(i=BMS-1; i<pTable->nCol; i++){
- pIdx->aiColumn[n] = i;
- pIdx->azColl[n] = "BINARY";
- n++;
- }
- }
- assert( n==nColumn );
-
- /* Create the automatic index */
- pKeyinfo = sqlite3IndexKeyinfo(pParse, pIdx);
- assert( pLevel->iIdxCur>=0 );
- sqlite3VdbeAddOp4(v, OP_OpenAutoindex, pLevel->iIdxCur, nColumn+1, 0,
- (char*)pKeyinfo, P4_KEYINFO_HANDOFF);
- VdbeComment((v, "for %s", pTable->zName));
-
- /* Fill the automatic index with content */
- addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, pLevel->iTabCur);
- regRecord = sqlite3GetTempReg(pParse);
- sqlite3GenerateIndexKey(pParse, pIdx, pLevel->iTabCur, regRecord, 1);
- sqlite3VdbeAddOp2(v, OP_IdxInsert, pLevel->iIdxCur, regRecord);
- sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
- sqlite3VdbeAddOp2(v, OP_Next, pLevel->iTabCur, addrTop+1);
- sqlite3VdbeChangeP5(v, SQLITE_STMTSTATUS_AUTOINDEX);
- sqlite3VdbeJumpHere(v, addrTop);
- sqlite3ReleaseTempReg(pParse, regRecord);
-
- /* Jump here when skipping the initialization */
- sqlite3VdbeJumpHere(v, addrInit);
-}
-#endif /* SQLITE_OMIT_AUTOMATIC_INDEX */
-
#ifndef SQLITE_OMIT_VIRTUALTABLE
/*
-** Allocate and populate an sqlite3_index_info structure. It is the
+** Allocate and populate an sqlite3_index_info structure. It is the
** 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(
- Parse *pParse,
+ Parse *pParse,
WhereClause *pWC,
struct SrcList_item *pSrc,
ExprList *pOrderBy
@@ -94600,7 +88416,7 @@ static sqlite3_index_info *allocateIndexInfo(
nTerm++;
}
- /* If the ORDER BY clause contains only columns in the current
+ /* If the ORDER BY clause contains only columns in the current
** virtual table then allocate space for the aOrderBy part of
** the sqlite3_index_info structure.
*/
@@ -94709,7 +88525,7 @@ static int vtabBestIndex(Parse *pParse, Table *pTab, sqlite3_index_info *p){
for(i=0; i<p->nConstraint; i++){
if( !p->aConstraint[i].usable && p->aConstraintUsage[i].argvIndex>0 ){
- sqlite3ErrorMsg(pParse,
+ sqlite3ErrorMsg(pParse,
"table %s: xBestIndex returned an invalid plan", pTab->zName);
}
}
@@ -94730,7 +88546,7 @@ static int vtabBestIndex(Parse *pParse, Table *pTab, sqlite3_index_info *p){
** 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()
+** 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.
*/
@@ -94750,9 +88566,8 @@ static void bestVirtualIndex(
WhereTerm *pTerm;
int i, j;
int nOrderBy;
- double rCost;
- /* Make sure wsFlags is initialized to some sane value. Otherwise, if the
+ /* 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.
*/
@@ -94779,12 +88594,12 @@ static void bestVirtualIndex(
/* 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.
+ ** sqlite3ViewGetColumnNames() would have picked up the error.
*/
assert( pTab->azModuleArg && pTab->azModuleArg[0] );
assert( sqlite3GetVTable(pParse->db, pTab) );
- /* Set the aConstraint[].usable fields and initialize all
+ /* Set the aConstraint[].usable fields and initialize all
** output variables to zero.
**
** aConstraint[].usable is true for constraints where the right-hand
@@ -94793,7 +88608,7 @@ static void bestVirtualIndex(
**
** column = expr
**
- ** and we are evaluating a join, then the constraint on column is
+ ** 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.
**
@@ -94837,26 +88652,17 @@ static void bestVirtualIndex(
}
}
- /* 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( 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
+ **
+ ** Use "(double)2" instead of "2.0" in case OMIT_FLOATING_POINT
** is defined.
*/
- if( (SQLITE_BIG_DBL/((double)2))<rCost ){
+ if( (SQLITE_BIG_DBL/((double)2))<pIdxInfo->estimatedCost ){
pCost->rCost = (SQLITE_BIG_DBL/((double)2));
}else{
- pCost->rCost = rCost;
+ pCost->rCost = pIdxInfo->estimatedCost;
}
pCost->plan.u.pVtabIdx = pIdxInfo;
if( pIdxInfo->orderByConsumed ){
@@ -94866,7 +88672,7 @@ static void bestVirtualIndex(
pIdxInfo->nOrderBy = nOrderBy;
/* Try to find a more efficient access pattern by using multiple indexes
- ** to optimize an OR expression within the WHERE clause.
+ ** to optimize an OR expression within the WHERE clause.
*/
bestOrClauseIndex(pParse, pWC, pSrc, notReady, pOrderBy, pCost);
}
@@ -94881,7 +88687,7 @@ static void bestVirtualIndex(
** 1 contains values larger than or equal to the value of the first sample,
** but smaller than the value of the second. And so on.
**
-** If successful, this function determines which of the regions value
+** If successful, this function determines which of the regions value
** pVal lies in, sets *piRegion to the region index (a value between 0
** and SQLITE_INDEX_SAMPLES+1, inclusive) and returns SQLITE_OK.
** Or, if an OOM occurs while converting text values between encodings,
@@ -94905,7 +88711,7 @@ static int whereRangeRegion(
if( aSample[i].eType==SQLITE_NULL ) continue;
if( aSample[i].eType>=SQLITE_TEXT || aSample[i].u.r>r ) break;
}
- }else{
+ }else{
sqlite3 *db = pParse->db;
CollSeq *pColl;
const u8 *z;
@@ -94969,8 +88775,8 @@ static int whereRangeRegion(
/*
** If expression pExpr represents a literal value, set *pp to point to
** an sqlite3_value structure containing the same value, with affinity
-** aff applied to it, before returning. It is the responsibility of the
-** caller to eventually release this structure by passing it to
+** aff applied to it, before returning. It is the responsibility of the
+** caller to eventually release this structure by passing it to
** sqlite3ValueFree().
**
** If the current parse is a recompile (sqlite3Reprepare()) and pExpr
@@ -94984,9 +88790,9 @@ static int whereRangeRegion(
*/
#ifdef SQLITE_ENABLE_STAT2
static int valueFromExpr(
- Parse *pParse,
- Expr *pExpr,
- u8 aff,
+ Parse *pParse,
+ Expr *pExpr,
+ u8 aff,
sqlite3_value **pp
){
/* The evalConstExpr() function will have already converted any TK_VARIABLE
@@ -95135,13 +88941,13 @@ range_est_fallback:
** 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
+** 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,
+** 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 (pSrc->notIndexed!=0) was attached to the table
-** in the SELECT statement, then no indexes are considered. However, the
+** If a NOT INDEXED clause (pSrc->notIndexed!=0) was attached to the table
+** in the SELECT statement, then no indexes are considered. However, the
** selected plan may still take advantage of the tables built-in rowid
** index.
*/
@@ -95230,18 +89036,18 @@ static void bestBtreeIndex(
** scan being evaluated. They are then used to determine the expected
** cost and number of rows returned.
**
- ** nEq:
+ ** nEq:
** Number of equality terms that can be implemented using the index.
**
- ** 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
+ ** 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
+ ** 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
@@ -95249,35 +89055,35 @@ static void bestBtreeIndex(
**
** 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
+ ** 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
+ ** bInEst:
+ ** Set to true if there was at least one "x IN (SELECT ...)" term used
** in determining the value of nInMul.
**
- ** estBound:
+ ** nBound:
** An estimate on the amount of the table that must be searched. A
** value of 100 means the entire table is searched. Range constraints
** might reduce this to a value less than 100 to indicate that only
** a fraction of the table needs searching. In the absence of
** sqlite_stat2 ANALYZE data, a single inequality reduces the search
** space to 1/3rd its original size. So an x>? constraint reduces
- ** estBound to 33. Two constraints (x>? AND x<?) reduce estBound to 11.
+ ** nBound to 33. Two constraints (x>? AND x<?) reduce nBound to 11.
**
- ** 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
+ ** 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).
**
- ** bLookup:
- ** Boolean. True if for each index entry visited a lookup on the
- ** corresponding table b-tree is required. This is always false
- ** for the rowid index. For other indexes, it is true unless all the
- ** columns of the table used by the SELECT statement are present in
+ ** bLookup:
+ ** Boolean. True if for each index entry visited a lookup on the
+ ** corresponding table b-tree is required. This is always false
+ ** for the rowid index. 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
+ ** For example, given the index on (a, b), the second of the following
** two queries requires table b-tree lookups, but the first does not.
**
** SELECT a, b FROM tbl WHERE a = 1;
@@ -95286,14 +89092,13 @@ static void bestBtreeIndex(
int nEq;
int bInEst = 0;
int nInMul = 1;
- int estBound = 100;
- int nBound = 0; /* Number of range constraints seen */
+ int nBound = 100;
int bSort = 0;
int bLookup = 0;
- WhereTerm *pTerm; /* A single term of the WHERE clause */
/* Determine the values of nEq and nInMul */
for(nEq=0; nEq<pProbe->nColumn; nEq++){
+ WhereTerm *pTerm; /* A single term of the WHERE clause */
int j = pProbe->aiColumn[nEq];
pTerm = findTerm(pWC, iCur, j, notReady, eqTermMask, pIdx);
if( pTerm==0 ) break;
@@ -95313,20 +89118,18 @@ static void bestBtreeIndex(
used |= pTerm->prereqRight;
}
- /* Determine the value of estBound. */
+ /* Determine the value of nBound. */
if( nEq<pProbe->nColumn ){
int j = pProbe->aiColumn[nEq];
if( findTerm(pWC, iCur, j, notReady, WO_LT|WO_LE|WO_GT|WO_GE, pIdx) ){
WhereTerm *pTop = findTerm(pWC, iCur, j, notReady, WO_LT|WO_LE, pIdx);
WhereTerm *pBtm = findTerm(pWC, iCur, j, notReady, WO_GT|WO_GE, pIdx);
- whereRangeScanEst(pParse, pProbe, nEq, pBtm, pTop, &estBound);
+ whereRangeScanEst(pParse, pProbe, nEq, pBtm, pTop, &nBound);
if( pTop ){
- nBound = 1;
wsFlags |= WHERE_TOP_LIMIT;
used |= pTop->prereqRight;
}
if( pBtm ){
- nBound++;
wsFlags |= WHERE_BTM_LIMIT;
used |= pBtm->prereqRight;
}
@@ -95356,8 +89159,8 @@ static void bestBtreeIndex(
}
/* 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), determine if all required column data may be obtained without
+ ** seeking to entries in 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
** wsFlags. Otherwise, set the bLookup variable to true. */
if( pIdx && wsFlags ){
@@ -95376,7 +89179,8 @@ static void bestBtreeIndex(
}
}
- /*
+ /**** Begin adding up the cost of using this index (Needs improvements)
+ **
** Estimate the number of rows of output. For an IN operator,
** do not let the estimate exceed half the rows in the table.
*/
@@ -95395,8 +89199,8 @@ static void bestBtreeIndex(
/* Adjust the number of rows and the cost downward to reflect rows
** that are excluded by range constraints.
*/
- nRow = (nRow * (double)estBound) / (double)100;
- cost = (cost * (double)estBound) / (double)100;
+ nRow = (nRow * (double)nBound) / (double)100;
+ cost = (cost * (double)nBound) / (double)100;
/* Add in the estimated cost of sorting the result
*/
@@ -95413,75 +89217,17 @@ static void bestBtreeIndex(
}
/**** 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.
- **
- ** Do not reduce the output row count if pSrc is the only table that
- ** is notReady; if notReady is a power of two. This will be the case
- ** when the main sqlite3WhereBegin() loop is scanning for a table with
- ** and "optimal" index, and on such a scan the output row count
- ** reduction is not valid because it does not update the "pCost->used"
- ** bitmap. The notReady bitmap will also be a power of two when we
- ** are scanning for the last table in a 64-way join. We are willing
- ** to bypass this optimization in that corner case.
- */
- if( nRow>2 && cost<=pCost->rCost && (notReady & (notReady-1))!=0 ){
- int k; /* Loop counter */
- int nSkipEq = 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; nRow>2 && k; k--, pTerm++){
- if( pTerm->wtFlags & TERM_VIRTUAL ) continue;
- if( (pTerm->prereqAll & notReady)!=thisTab ) continue;
- if( pTerm->eOperator & (WO_EQ|WO_IN|WO_ISNULL) ){
- if( nSkipEq ){
- /* Ignore the first 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 */
- nRow /= 10;
- }
- }else if( pTerm->eOperator & (WO_LT|WO_LE|WO_GT|WO_GE) ){
- if( nSkipRange ){
- /* Ignore the first nBound 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 */
- nRow /= 3;
- }
- }else{
- /* Any other expression lowers the output row count by half */
- nRow /= 2;
- }
- }
- if( nRow<2 ) nRow = 2;
- }
-
-
WHERETRACE((
- "%s(%s): nEq=%d nInMul=%d estBound=%d bSort=%d bLookup=%d wsFlags=0x%x\n"
- " notReady=0x%llx nRow=%.2f cost=%.2f used=0x%llx\n",
- pSrc->pTab->zName, (pIdx ? pIdx->zName : "ipk"),
- nEq, nInMul, estBound, bSort, bLookup, wsFlags,
- notReady, nRow, cost, used
+ "tbl=%s idx=%s nEq=%d nInMul=%d nBound=%d bSort=%d bLookup=%d"
+ " wsFlags=%d (nRow=%.2f cost=%.2f)\n",
+ pSrc->pTab->zName, (pIdx ? pIdx->zName : "ipk"),
+ nEq, nInMul, nBound, bSort, bLookup, wsFlags, nRow, cost
));
/* If this index is the best we have seen so far, then record this
** index and its cost in the pCost structure.
*/
- if( (!pIdx || wsFlags)
- && (cost<pCost->rCost || (cost<=pCost->rCost && nRow<pCost->nRow))
- ){
+ if( (!pIdx || wsFlags) && cost<pCost->rCost ){
pCost->rCost = cost;
pCost->nRow = nRow;
pCost->used = used;
@@ -95510,24 +89256,22 @@ static void bestBtreeIndex(
assert( pOrderBy || (pCost->plan.wsFlags&WHERE_ORDERBY)==0 );
assert( pCost->plan.u.pIdx==0 || (pCost->plan.wsFlags&WHERE_ROWID_EQ)==0 );
- assert( pSrc->pIndex==0
- || pCost->plan.u.pIdx==0
- || pCost->plan.u.pIdx==pSrc->pIndex
+ assert( pSrc->pIndex==0
+ || pCost->plan.u.pIdx==0
+ || pCost->plan.u.pIdx==pSrc->pIndex
);
- WHERETRACE(("best index is: %s\n",
- ((pCost->plan.wsFlags & WHERE_NOT_FULLSCAN)==0 ? "none" :
- pCost->plan.u.pIdx ? pCost->plan.u.pIdx->zName : "ipk")
+ WHERETRACE(("best index is: %s\n",
+ (pCost->plan.u.pIdx ? pCost->plan.u.pIdx->zName : "ipk")
));
-
+
bestOrClauseIndex(pParse, pWC, pSrc, notReady, pOrderBy, pCost);
- bestAutomaticIndex(pParse, pWC, pSrc, notReady, pCost);
pCost->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
+** 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.
*/
@@ -95579,7 +89323,7 @@ static void bestIndex(
*/
static void disableTerm(WhereLevel *pLevel, WhereTerm *pTerm){
if( pTerm
- && (pTerm->wtFlags & TERM_CODED)==0
+ && ALWAYS((pTerm->wtFlags & TERM_CODED)==0)
&& (pLevel->iLeftJoin==0 || ExprHasProperty(pTerm->pExpr, EP_FromJoin))
){
pTerm->wtFlags |= TERM_CODED;
@@ -95594,7 +89338,7 @@ static void disableTerm(WhereLevel *pLevel, WhereTerm *pTerm){
/*
** Code an OP_Affinity opcode to apply the column affinity string zAff
-** to the n registers starting at base.
+** to the n registers starting at base.
**
** As an optimization, SQLITE_AFF_NONE entries (which are no-ops) at the
** beginning and end of zAff are ignored. If all entries in zAff are
@@ -95634,7 +89378,7 @@ static void codeApplyAffinity(Parse *pParse, int base, int n, char *zAff){
/*
** Generate code for a single equality term of the WHERE clause. An equality
-** term can be either X=expr or X IN (...). pTerm is the term to be
+** term can be either X=expr or X IN (...). pTerm is the term to be
** coded.
**
** The current value for the constraint is left in register iReg.
@@ -95704,7 +89448,7 @@ static int codeEqualityTerm(
** For example, consider table t1(a,b,c,d,e,f) with index i1(a,b,c).
** Suppose the WHERE clause is this: a==5 AND b IN (1,2,3) AND c>5 AND c<10
** The index has as many as three equality constraints, but in this
-** example, the third "c" value is an inequality. So only two
+** example, the third "c" value is an inequality. So only two
** constraints are coded. This routine will generate code to evaluate
** a==5 and b IN (1,2,3). The current values for a and b will be stored
** in consecutive registers and the index of the first register is returned.
@@ -95777,9 +89521,7 @@ static int codeAllEqualityTerms(
int k = pIdx->aiColumn[j];
pTerm = findTerm(pWC, iCur, k, notReady, pLevel->plan.wsFlags, pIdx);
if( NEVER(pTerm==0) ) break;
- /* 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 );
+ assert( (pTerm->wtFlags & TERM_CODED)==0 );
r1 = codeEqualityTerm(pParse, pTerm, pLevel, regBase+j);
if( r1!=regBase+j ){
if( nReg==1 ){
@@ -95841,7 +89583,7 @@ static Bitmask codeOneLoopStart(
pTabItem = &pWInfo->pTabList->a[pLevel->iFrom];
iCur = pTabItem->iCursor;
bRev = (pLevel->plan.wsFlags & WHERE_REVERSE)!=0;
- omitTable = (pLevel->plan.wsFlags & WHERE_IDX_ONLY)!=0
+ omitTable = (pLevel->plan.wsFlags & WHERE_IDX_ONLY)!=0
&& (wctrlFlags & WHERE_FORCE_TABLE)==0;
/* Create labels for the "break" and "continue" instructions
@@ -95950,7 +89692,7 @@ static Bitmask codeOneLoopStart(
Expr *pX; /* The expression that defines the start bound */
int r1, rTemp; /* Registers for holding the start boundary */
- /* The following constant maps TK_xx codes into corresponding
+ /* The following constant maps TK_xx codes into corresponding
** seek opcodes. It depends on a particular ordering of TK_xx
*/
const u8 aMoveOp[] = {
@@ -95993,11 +89735,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 );
- }
+ pLevel->p5 = (pStart==0 && pEnd==0) ?1:0;
if( testOp!=OP_Noop ){
iRowidReg = iReleaseReg = sqlite3GetTempReg(pParse);
sqlite3VdbeAddOp2(v, OP_Rowid, iCur, iRowidReg);
@@ -96008,14 +89746,14 @@ static Bitmask codeOneLoopStart(
}else if( pLevel->plan.wsFlags & (WHERE_COLUMN_RANGE|WHERE_COLUMN_EQ) ){
/* Case 3: A scan using an index.
**
- ** The WHERE clause may contain zero or more equality
+ ** The WHERE clause may contain zero or more equality
** terms ("==" or "IN" operators) that refer to the N
** left-most columns of the index. It may also contain
** inequality constraints (>, <, >= or <=) on the indexed
- ** column that immediately follows the N equalities. Only
+ ** column that immediately follows the N equalities. Only
** the right-most column can be an inequality - the rest must
- ** use the "==" and "IN" operators. For example, if the
- ** index is on (x,y,z), then the following clauses are all
+ ** use the "==" and "IN" operators. For example, if the
+ ** index is on (x,y,z), then the following clauses are all
** optimized:
**
** x=5
@@ -96036,7 +89774,7 @@ static Bitmask codeOneLoopStart(
** This case is also used when there are no WHERE clause
** constraints but an index is selected anyway, in order
** to force the output order to conform to an ORDER BY.
- */
+ */
int aStartOp[] = {
0,
0,
@@ -96072,8 +89810,8 @@ static Bitmask codeOneLoopStart(
iIdxCur = pLevel->iIdxCur;
k = pIdx->aiColumn[nEq]; /* Column for inequality constraints */
- /* If this loop satisfies a sort order (pOrderBy) request that
- ** was passed to this function to implement a "SELECT min(x) ..."
+ /* If this loop satisfies a sort order (pOrderBy) request that
+ ** was passed to this function to implement a "SELECT min(x) ..."
** query, then the caller will only allow the loop to run for
** a single iteration. This means that the first row returned
** should not have a NULL value stored in 'x'. If column 'x' is
@@ -96090,8 +89828,8 @@ static Bitmask codeOneLoopStart(
nExtraReg = 1;
}
- /* Find any inequality constraint terms for the start and end
- ** of the range.
+ /* 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);
@@ -96112,7 +89850,7 @@ static Bitmask codeOneLoopStart(
addrNxt = pLevel->addrNxt;
/* If we are doing a reverse order scan on an ascending index, or
- ** a forward order scan on a descending index, interchange the
+ ** a forward order scan on a descending index, interchange the
** start and end terms (pRangeStart and pRangeEnd).
*/
if( bRev==(pIdx->aSortOrder[nEq]==SQLITE_SO_ASC) ){
@@ -96136,14 +89874,14 @@ static Bitmask codeOneLoopStart(
if( zAff ){
if( sqlite3CompareAffinity(pRight, zAff[nConstraint])==SQLITE_AFF_NONE){
/* Since the comparison is to be performed with no conversions
- ** applied to the operands, set the affinity to apply to pRight to
+ ** applied to the operands, set the affinity to apply to pRight to
** SQLITE_AFF_NONE. */
zAff[nConstraint] = SQLITE_AFF_NONE;
}
if( sqlite3ExprNeedsNoAffinityChange(pRight, zAff[nConstraint]) ){
zAff[nConstraint] = SQLITE_AFF_NONE;
}
- }
+ }
nConstraint++;
}else if( isMinQuery ){
sqlite3VdbeAddOp2(v, OP_Null, 0, regBase+nEq);
@@ -96174,14 +89912,14 @@ static Bitmask codeOneLoopStart(
if( zAff ){
if( sqlite3CompareAffinity(pRight, zAff[nConstraint])==SQLITE_AFF_NONE){
/* Since the comparison is to be performed with no conversions
- ** applied to the operands, set the affinity to apply to pRight to
+ ** applied to the operands, set the affinity to apply to pRight to
** SQLITE_AFF_NONE. */
zAff[nConstraint] = SQLITE_AFF_NONE;
}
if( sqlite3ExprNeedsNoAffinityChange(pRight, zAff[nConstraint]) ){
zAff[nConstraint] = SQLITE_AFF_NONE;
}
- }
+ }
codeApplyAffinity(pParse, regBase, nEq+1, zAff);
nConstraint++;
}
@@ -96223,7 +89961,7 @@ static Bitmask codeOneLoopStart(
sqlite3VdbeAddOp2(v, OP_Seek, iCur, iRowidReg); /* Deferred seek */
}
- /* Record the instruction used to terminate the loop. Disable
+ /* Record the instruction used to terminate the loop. Disable
** WHERE clause terms made redundant by the index range scan.
*/
pLevel->op = bRev ? OP_Prev : OP_Next;
@@ -96282,7 +90020,7 @@ static Bitmask codeOneLoopStart(
int iRetInit; /* Address of regReturn init */
int untestedTerms = 0; /* Some terms not completely tested */
int ii;
-
+
pTerm = pLevel->plan.u.pTerm;
assert( pTerm!=0 );
assert( pTerm->eOperator==WO_OR );
@@ -96314,14 +90052,14 @@ static Bitmask codeOneLoopStart(
pOrTab = pWInfo->pTabList;
}
- /* Initialize the rowset register to contain NULL. An SQL NULL is
+ /* Initialize the rowset register to contain NULL. An SQL NULL is
** equivalent to an empty rowset.
**
- ** Also initialize regReturn to contain the address of the instruction
+ ** Also initialize regReturn to contain the address of the instruction
** immediately following the OP_Return at the bottom of the loop. This
** is required in a few obscure LEFT JOIN cases where control jumps
- ** over the top of the loop into the body of it. In this case the
- ** correct response for the end-of-loop code (the OP_Return) is to
+ ** over the top of the loop into the body of it. In this case the
+ ** correct response for the end-of-loop code (the OP_Return) is to
** fall through to the next instruction, just as an OP_Next does if
** called on an uninitialized cursor.
*/
@@ -96344,7 +90082,7 @@ static Bitmask codeOneLoopStart(
if( (wctrlFlags & WHERE_DUPLICATES_OK)==0 ){
int iSet = ((ii==pOrWc->nTerm-1)?-1:ii);
int r;
- r = sqlite3ExprCodeGetColumn(pParse, pTabItem->pTab, -1, iCur,
+ r = sqlite3ExprCodeGetColumn(pParse, pTabItem->pTab, -1, iCur,
regRowid);
sqlite3VdbeAddOp4Int(v, OP_RowSetTest, regRowset,
sqlite3VdbeCurrentAddr(v)+2, r, iSet);
@@ -96413,7 +90151,7 @@ static Bitmask codeOneLoopStart(
}
/* For a LEFT OUTER JOIN, generate code that will record the fact that
- ** at least one row of the right table has matched the left table.
+ ** at least one row of the right table has matched the left table.
*/
if( pLevel->iLeftJoin ){
pLevel->addrFirst = sqlite3VdbeCurrentAddr(v);
@@ -96455,7 +90193,7 @@ static int nQPlan = 0; /* Next free slow in _query_plan[] */
** Free a WhereInfo structure
*/
static void whereInfoFree(sqlite3 *db, WhereInfo *pWInfo){
- if( ALWAYS(pWInfo) ){
+ if( pWInfo ){
int i;
for(i=0; i<pWInfo->nLevel; i++){
sqlite3_index_info *pInfo = pWInfo->a[i].pIdxInfo;
@@ -96466,13 +90204,6 @@ static void whereInfoFree(sqlite3 *db, WhereInfo *pWInfo){
}
sqlite3DbFree(db, pInfo);
}
- 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);
- }
- }
}
whereClauseClear(pWInfo->pWC);
sqlite3DbFree(db, pWInfo);
@@ -96590,15 +90321,14 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
sqlite3 *db; /* Database connection */
/* The number of tables in the FROM clause is limited by the number of
- ** bits in a Bitmask
+ ** bits in a Bitmask
*/
- testcase( pTabList->nSrc==BMS );
if( pTabList->nSrc>BMS ){
sqlite3ErrorMsg(pParse, "at most %d tables in a join", BMS);
return 0;
}
- /* This function normally generates a nested loop for all tables in
+ /* This function normally generates a nested loop for all tables in
** pTabList. But if the WHERE_ONETABLE_ONLY flag is set, then we should
** only generate code for the first table in pTabList and assume that
** any cursors associated with subsequent tables are uninitialized.
@@ -96614,14 +90344,12 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
*/
db = pParse->db;
nByteWInfo = ROUND8(sizeof(WhereInfo)+(nTabList-1)*sizeof(WhereLevel));
- pWInfo = sqlite3DbMallocZero(db,
- nByteWInfo +
+ pWInfo = sqlite3DbMallocZero(db,
+ nByteWInfo +
sizeof(WhereClause) +
sizeof(WhereMaskSet)
);
if( db->mallocFailed ){
- sqlite3DbFree(db, pWInfo);
- pWInfo = 0;
goto whereBeginError;
}
pWInfo->nLevel = nTabList;
@@ -96630,7 +90358,6 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
pWInfo->iBreak = sqlite3VdbeMakeLabel(v);
pWInfo->pWC = pWC = (WhereClause *)&((u8 *)pWInfo)[nByteWInfo];
pWInfo->wctrlFlags = wctrlFlags;
- pWInfo->savedNQueryLoop = pParse->nQueryLoop;
pMaskSet = (WhereMaskSet*)&pWC[1];
/* Split the WHERE clause into separate subexpressions where each
@@ -96640,7 +90367,7 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
whereClauseInit(pWC, pParse, pMaskSet);
sqlite3ExprCodeConstants(pParse, pWhere);
whereSplit(pWC, pWhere, TK_AND);
-
+
/* Special case: a WHERE clause that is constant. Evaluate the
** expression and either jump over all of the code or fall thru.
*/
@@ -96661,8 +90388,8 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
** for all tables to the left of a left join is important. Ticket #3015.
**
** Configure the WhereClause.vmask variable so that bits that correspond
- ** to virtual table cursors are set. This is used to selectively disable
- ** the OR-to-IN transformation in exprAnalyzeOrTerm(). It is not helpful
+ ** to virtual table cursors are set. This is used to selectively disable
+ ** the OR-to-IN transformation in exprAnalyzeOrTerm(). It is not helpful
** with virtual tables.
**
** Note that bitmasks are created for all pTabList->nSrc tables in
@@ -96732,49 +90459,45 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
bestPlan.rCost = SQLITE_BIG_DBL;
/* 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.
+ ** next nested loop. The FROM clause entries may be iterated through
+ ** 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
+ ** The first iteration, which is always performed, searches for the
+ ** FROM clause entry that permits the lowest-cost, "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 notReady. If no notReady terms are
- ** used then the "optimal" query plan works.
+ ** by waiting for other tables to run first.
**
- ** The second loop iteration is only performed if no optimal scan
- ** strategies were found by the first loop. This 2nd iteration is used to
- ** search for the lowest cost scan overall.
+ ** The second iteration is only performed if no optimal scan strategies
+ ** were found by the first. This iteration is used to search for the
+ ** lowest cost scan overall.
**
** Previous versions of SQLite performed only the second iteration -
** the next outermost loop was always that with the lowest overall
** cost. However, this meant that SQLite could select the wrong plan
** for scripts such as the following:
- **
- ** CREATE TABLE t1(a, b);
+ **
+ ** 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.
- ** However, 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
+ ** However, 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.
*/
- for(isOptimal=(iFrom<nTabList-1); isOptimal>=0; isOptimal--){
- Bitmask mask; /* Mask of tables not yet ready */
+ for(isOptimal=1; isOptimal>=0 && bestJ<0; isOptimal--){
+ Bitmask mask = (isOptimal ? 0 : notReady);
+ assert( (nTabList-iFrom)>1 || isOptimal );
for(j=iFrom, pTabItem=&pTabList->a[j]; j<nTabList; j++, pTabItem++){
int doNotReorder; /* True if this table should not be reordered */
WhereCost sCost; /* Cost information from best[Virtual]Index() */
ExprList *pOrderBy; /* ORDER BY clause for index to optimize */
-
+
doNotReorder = (pTabItem->jointype & (JT_LEFT|JT_CROSS))!=0;
if( j!=iFrom && doNotReorder ) break;
m = getMask(pMaskSet, pTabItem->iCursor);
@@ -96782,15 +90505,14 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
if( j==iFrom ) iFrom++;
continue;
}
- mask = (isOptimal ? m : notReady);
pOrderBy = ((i==0 && ppOrderBy )?*ppOrderBy:0);
-
+
assert( pTabItem->pTab );
#ifndef SQLITE_OMIT_VIRTUALTABLE
if( IsVirtual(pTabItem->pTab) ){
sqlite3_index_info **pp = &pWInfo->a[j].pIdxInfo;
bestVirtualIndex(pParse, pWC, pTabItem, mask, pOrderBy, &sCost, pp);
- }else
+ }else
#endif
{
bestBtreeIndex(pParse, pWC, pTabItem, mask, pOrderBy, &sCost);
@@ -96798,11 +90520,8 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
assert( isOptimal || (sCost.used&notReady)==0 );
if( (sCost.used&notReady)==0
- && (bestJ<0 || sCost.rCost<bestPlan.rCost
- || (sCost.rCost<=bestPlan.rCost && sCost.nRow<bestPlan.nRow))
+ && (j==iFrom || sCost.rCost<bestPlan.rCost)
){
- WHERETRACE(("... best so far with cost=%g and nRow=%g\n",
- sCost.rCost, sCost.nRow));
bestPlan = sCost;
bestJ = j;
}
@@ -96818,16 +90537,13 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
}
andFlags &= bestPlan.plan.wsFlags;
pLevel->plan = bestPlan.plan;
- testcase( bestPlan.plan.wsFlags & WHERE_INDEXED );
- testcase( bestPlan.plan.wsFlags & WHERE_TEMP_INDEX );
- if( bestPlan.plan.wsFlags & (WHERE_INDEXED|WHERE_TEMP_INDEX) ){
+ if( bestPlan.plan.wsFlags & WHERE_INDEXED ){
pLevel->iIdxCur = pParse->nTab++;
}else{
pLevel->iIdxCur = -1;
}
notReady &= ~getMask(pMaskSet, pTabList->a[bestJ].iCursor);
pLevel->iFrom = (u8)bestJ;
- if( bestPlan.nRow>=(double)1 ) pParse->nQueryLoop *= bestPlan.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
@@ -96874,7 +90590,6 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
** searching those tables.
*/
sqlite3CodeVerifySchema(pParse, -1); /* Insert the cookie verifier Goto */
- notReady = ~(Bitmask)0;
for(i=0, pLevel=pWInfo->a; i<nTabList; i++, pLevel++){
Table *pTab; /* Table to open */
int iDb; /* Index of database containing table/index */
@@ -96887,9 +90602,7 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
if( pItem->zAlias ){
zMsg = sqlite3MAppendf(db, zMsg, "%s AS %s", zMsg, pItem->zAlias);
}
- if( (pLevel->plan.wsFlags & WHERE_TEMP_INDEX)!=0 ){
- zMsg = sqlite3MAppendf(db, zMsg, "%s WITH AUTOMATIC INDEX", zMsg);
- }else if( (pLevel->plan.wsFlags & WHERE_INDEXED)!=0 ){
+ if( (pLevel->plan.wsFlags & WHERE_INDEXED)!=0 ){
zMsg = sqlite3MAppendf(db, zMsg, "%s WITH INDEX %s",
zMsg, pLevel->plan.u.pIdx->zName);
}else if( pLevel->plan.wsFlags & WHERE_MULTI_OR ){
@@ -96912,11 +90625,8 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
#endif /* SQLITE_OMIT_EXPLAIN */
pTabItem = &pTabList->a[pLevel->iFrom];
pTab = pTabItem->pTab;
- pLevel->iTabCur = pTabItem->iCursor;
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
- if( (pTab->tabFlags & TF_Ephemeral)!=0 || pTab->pSelect ){
- /* Do nothing */
- }else
+ if( (pTab->tabFlags & TF_Ephemeral)!=0 || pTab->pSelect ) continue;
#ifndef SQLITE_OMIT_VIRTUALTABLE
if( (pLevel->plan.wsFlags & WHERE_VIRTUALTABLE)!=0 ){
const char *pVTab = (const char *)sqlite3GetVTable(db, pTab);
@@ -96928,24 +90638,18 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
&& (wctrlFlags & WHERE_OMIT_OPEN)==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 );
if( !pWInfo->okOnePass && pTab->nCol<BMS ){
Bitmask b = pTabItem->colUsed;
int n = 0;
for(; b; b=b>>1, n++){}
- sqlite3VdbeChangeP4(v, sqlite3VdbeCurrentAddr(v)-1,
+ sqlite3VdbeChangeP4(v, sqlite3VdbeCurrentAddr(v)-1,
SQLITE_INT_TO_PTR(n), P4_INT32);
assert( n<=pTab->nCol );
}
}else{
sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName);
}
-#ifndef SQLITE_OMIT_AUTOMATIC_INDEX
- if( (pLevel->plan.wsFlags & WHERE_TEMP_INDEX)!=0 ){
- constructAutomaticIndex(pParse, pWC, pTabItem, notReady, pLevel);
- }else
-#endif
+ pLevel->iTabCur = pTabItem->iCursor;
if( (pLevel->plan.wsFlags & WHERE_INDEXED)!=0 ){
Index *pIx = pLevel->plan.u.pIdx;
KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIx);
@@ -96957,10 +90661,8 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
VdbeComment((v, "%s", pIx->zName));
}
sqlite3CodeVerifySchema(pParse, iDb);
- notReady &= ~getMask(pWC->pMaskSet, pTabItem->iCursor);
}
pWInfo->iTop = sqlite3VdbeCurrentAddr(v);
- if( db->mallocFailed ) goto whereBeginError;
/* Generate the code to do the search. Each iteration of the for
** loop below generates code for a single nested loop of the VM
@@ -97028,15 +90730,12 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
/* Jump here if malloc fails */
whereBeginError:
- if( pWInfo ){
- pParse->nQueryLoop = pWInfo->savedNQueryLoop;
- whereInfoFree(db, pWInfo);
- }
+ whereInfoFree(db, pWInfo);
return 0;
}
/*
-** Generate the end of the WHERE loop. See comments on
+** Generate the end of the WHERE loop. See comments on
** sqlite3WhereBegin() for additional information.
*/
SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){
@@ -97101,15 +90800,12 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){
struct SrcList_item *pTabItem = &pTabList->a[pLevel->iFrom];
Table *pTab = pTabItem->pTab;
assert( pTab!=0 );
- if( (pTab->tabFlags & TF_Ephemeral)==0
- && pTab->pSelect==0
- && (pWInfo->wctrlFlags & WHERE_OMIT_CLOSE)==0
- ){
- int ws = pLevel->plan.wsFlags;
- if( !pWInfo->okOnePass && (ws & WHERE_IDX_ONLY)==0 ){
+ if( (pTab->tabFlags & TF_Ephemeral)!=0 || pTab->pSelect ) continue;
+ if( (pWInfo->wctrlFlags & WHERE_OMIT_CLOSE)==0 ){
+ if( !pWInfo->okOnePass && (pLevel->plan.wsFlags & WHERE_IDX_ONLY)==0 ){
sqlite3VdbeAddOp1(v, OP_Close, pTabItem->iCursor);
}
- if( (ws & WHERE_INDEXED)!=0 && (ws & WHERE_TEMP_INDEX)==0 ){
+ if( (pLevel->plan.wsFlags & WHERE_INDEXED)!=0 ){
sqlite3VdbeAddOp1(v, OP_Close, pLevel->iIdxCur);
}
}
@@ -97120,7 +90816,7 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){
** 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.
- **
+ **
** Calls to the code generator in between sqlite3WhereBegin and
** sqlite3WhereEnd will have created code that references the table
** directly. This loop scans all that code looking for opcodes
@@ -97157,7 +90853,6 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){
/* Final cleanup
*/
- pParse->nQueryLoop = pWInfo->savedNQueryLoop;
whereInfoFree(db, pWInfo);
return;
}
@@ -97269,7 +90964,7 @@ struct AttachKey { int type; Token key; };
pOut->pExpr = sqlite3PExpr(pParse, op, pOperand->pExpr, 0, 0);
pOut->zStart = pOperand->zStart;
pOut->zEnd = &pPostOp->z[pPostOp->n];
- }
+ }
/* A routine to convert a binary TK_IS or TK_ISNOT expression into a
** unary TK_ISNULL or TK_NOTNULL expression. */
@@ -97298,10 +90993,10 @@ struct AttachKey { int type; Token key; };
/* Next is all token values, in a form suitable for use by makeheaders.
** This section will be null unless lemon is run with the -m switch.
*/
-/*
+/*
** These constants (all generated automatically by the parser generator)
** specify the various kinds of tokens (terminals) that the parser
-** understands.
+** understands.
**
** Each symbol here is a terminal symbol in the grammar.
*/
@@ -97318,7 +91013,7 @@ struct AttachKey { int type; Token key; };
** and nonterminals. "int" is used otherwise.
** YYNOCODE is a number of type YYCODETYPE which corresponds
** to no legal terminal or nonterminal number. This
-** number is used to fill in empty slots of the hash
+** number is used to fill in empty slots of the hash
** table.
** YYFALLBACK If defined, this indicates that one or more tokens
** have fall-back values which should be used if the
@@ -97327,7 +91022,7 @@ struct AttachKey { int type; Token key; };
** and nonterminal numbers. "unsigned char" is
** used if there are fewer than 250 rules and
** states combined. "int" is used otherwise.
-** sqlite3ParserTOKENTYPE is the data type used for minor tokens given
+** sqlite3ParserTOKENTYPE is the data type used for minor tokens given
** directly to the parser from the tokenizer.
** YYMINORTYPE is the data type used for all minor tokens.
** This is typically a union of many types, one of
@@ -97400,7 +91095,7 @@ static const YYMINORTYPE yyzerominor = { 0 };
/* Next are the tables used to determine what action to take based on the
** current state and lookahead token. These tables are used to implement
** functions that take a state number and lookahead value and return an
-** action integer.
+** action integer.
**
** Suppose the action integer is N. Then the action is determined as
** follows
@@ -97425,7 +91120,7 @@ static const YYMINORTYPE yyzerominor = { 0 };
** If the index value yy_shift_ofst[S]+X is out of range or if the value
** yy_lookahead[yy_shift_ofst[S]+X] is not equal to X or if yy_shift_ofst[S]
** is equal to YY_SHIFT_USE_DFLT, it means that the action is not in the table
-** and that yy_default[S] should be used instead.
+** and that yy_default[S] should be used instead.
**
** The formula above is for computing the action when the lookahead is
** a terminal symbol. If the lookahead is a non-terminal (as occurs after
@@ -97444,7 +91139,7 @@ static const YYMINORTYPE yyzerominor = { 0 };
** shifting non-terminals after a reduce.
** yy_default[] Default action for each state.
*/
-#define YY_ACTTAB_COUNT (1550)
+#define YY_ACTTAB_COUNT (1543)
static const YYACTIONTYPE yy_action[] = {
/* 0 */ 313, 49, 556, 46, 147, 172, 628, 598, 55, 55,
/* 10 */ 55, 55, 302, 53, 53, 53, 53, 52, 52, 51,
@@ -97594,13 +91289,13 @@ static const YYACTIONTYPE yy_action[] = {
/* 1450 */ 249, 389, 487, 486, 314, 164, 602, 79, 310, 240,
/* 1460 */ 414, 373, 480, 163, 262, 371, 414, 162, 369, 602,
/* 1470 */ 78, 212, 478, 26, 477, 602, 9, 161, 467, 363,
- /* 1480 */ 141, 122, 339, 187, 119, 457, 348, 347, 117, 116,
- /* 1490 */ 115, 112, 114, 448, 182, 22, 320, 433, 432, 431,
- /* 1500 */ 19, 428, 610, 597, 574, 193, 572, 63, 298, 404,
- /* 1510 */ 555, 552, 290, 281, 510, 460, 498, 499, 495, 447,
- /* 1520 */ 356, 497, 256, 380, 306, 570, 5, 250, 345, 238,
- /* 1530 */ 299, 550, 527, 490, 508, 525, 502, 401, 501, 963,
- /* 1540 */ 211, 963, 483, 963, 963, 963, 963, 963, 963, 370,
+ /* 1480 */ 141, 122, 339, 187, 119, 457, 348, 117, 347, 116,
+ /* 1490 */ 115, 114, 448, 112, 182, 320, 22, 433, 19, 432,
+ /* 1500 */ 431, 63, 428, 610, 193, 298, 597, 574, 572, 404,
+ /* 1510 */ 555, 552, 290, 281, 510, 499, 498, 497, 495, 380,
+ /* 1520 */ 356, 460, 256, 250, 345, 447, 306, 5, 570, 550,
+ /* 1530 */ 299, 211, 370, 401, 550, 508, 502, 501, 490, 527,
+ /* 1540 */ 525, 483, 238,
};
static const YYCODETYPE yy_lookahead[] = {
/* 0 */ 19, 222, 223, 224, 225, 24, 1, 26, 77, 78,
@@ -97751,18 +91446,18 @@ static const YYCODETYPE yy_lookahead[] = {
/* 1450 */ 107, 150, 176, 176, 111, 156, 174, 175, 179, 116,
/* 1460 */ 165, 18, 157, 156, 238, 157, 165, 156, 45, 174,
/* 1470 */ 175, 157, 157, 135, 239, 174, 175, 156, 189, 157,
- /* 1480 */ 68, 189, 139, 219, 22, 199, 157, 18, 192, 192,
- /* 1490 */ 192, 189, 192, 199, 219, 243, 157, 40, 157, 157,
- /* 1500 */ 243, 38, 153, 166, 233, 196, 233, 246, 198, 228,
- /* 1510 */ 177, 177, 209, 177, 182, 199, 166, 177, 166, 199,
- /* 1520 */ 242, 177, 242, 178, 148, 166, 196, 209, 209, 92,
- /* 1530 */ 195, 208, 174, 186, 183, 174, 183, 191, 183, 253,
- /* 1540 */ 236, 253, 186, 253, 253, 253, 253, 253, 253, 237,
+ /* 1480 */ 68, 189, 139, 219, 22, 199, 157, 192, 18, 192,
+ /* 1490 */ 192, 192, 199, 189, 219, 157, 243, 40, 243, 157,
+ /* 1500 */ 157, 246, 38, 153, 196, 198, 166, 233, 233, 228,
+ /* 1510 */ 177, 177, 209, 177, 182, 177, 166, 177, 166, 178,
+ /* 1520 */ 242, 199, 242, 209, 209, 199, 148, 196, 166, 208,
+ /* 1530 */ 195, 236, 237, 191, 208, 183, 183, 183, 186, 174,
+ /* 1540 */ 174, 186, 92,
};
#define YY_SHIFT_USE_DFLT (-90)
#define YY_SHIFT_COUNT (418)
#define YY_SHIFT_MIN (-89)
-#define YY_SHIFT_MAX (1469)
+#define YY_SHIFT_MAX (1470)
static const short yy_shift_ofst[] = {
/* 0 */ 993, 1114, 1343, 1114, 1213, 1213, 90, 90, 0, -19,
/* 10 */ 1213, 1213, 1213, 1213, 1213, 352, 517, 721, 1091, 1213,
@@ -97777,7 +91472,7 @@ static const short yy_shift_ofst[] = {
/* 100 */ 1017, -69, -69, -69, -69, -1, -1, 58, 138, -44,
/* 110 */ 517, 517, 517, 517, 517, 517, 517, 517, 517, 517,
/* 120 */ 517, 517, 517, 517, 517, 517, 202, 579, 517, 517,
- /* 130 */ 517, 517, 517, 382, 885, 1437, -90, -90, -90, 1293,
+ /* 130 */ 517, 517, 517, 382, 885, 1450, -90, -90, -90, 1293,
/* 140 */ 73, 272, 272, 309, 311, 297, 282, 216, 602, 538,
/* 150 */ 517, 517, 517, 517, 517, 517, 517, 517, 517, 517,
/* 160 */ 517, 517, 517, 517, 517, 517, 517, 517, 517, 517,
@@ -97788,8 +91483,8 @@ static const short yy_shift_ofst[] = {
/* 210 */ 149, 604, 516, 149, 149, 508, 3, 299, 677, 871,
/* 220 */ 613, 613, 879, 871, 879, 144, 382, 226, 382, 226,
/* 230 */ 564, 226, 613, 226, 226, 404, 625, 625, 382, 426,
- /* 240 */ -89, 801, 1463, 1244, 1244, 1457, 1457, 1244, 1462, 1412,
- /* 250 */ 1188, 1469, 1469, 1469, 1469, 1244, 1188, 1462, 1412, 1412,
+ /* 240 */ -89, 801, 1464, 1244, 1244, 1457, 1457, 1244, 1462, 1412,
+ /* 250 */ 1188, 1470, 1470, 1470, 1470, 1244, 1188, 1462, 1412, 1412,
/* 260 */ 1244, 1443, 1338, 1423, 1244, 1244, 1443, 1244, 1443, 1244,
/* 270 */ 1443, 1414, 1306, 1306, 1306, 1365, 1348, 1348, 1414, 1306,
/* 280 */ 1317, 1306, 1365, 1306, 1306, 1267, 1268, 1267, 1268, 1267,
@@ -97810,7 +91505,7 @@ static const short yy_shift_ofst[] = {
#define YY_REDUCE_USE_DFLT (-222)
#define YY_REDUCE_COUNT (312)
#define YY_REDUCE_MIN (-221)
-#define YY_REDUCE_MAX (1376)
+#define YY_REDUCE_MAX (1378)
static const short yy_reduce_ofst[] = {
/* 0 */ 310, 994, 1134, 221, 169, 157, 89, 18, 83, 301,
/* 10 */ 377, 316, 312, 16, 295, 238, 249, 391, 1301, 1295,
@@ -97831,13 +91526,13 @@ static const short yy_reduce_ofst[] = {
/* 160 */ 1084, 1066, 1049, 1011, 1010, 1006, 1002, 999, 998, 973,
/* 170 */ 972, 970, 966, 964, 895, 894, 892, 833, 822, 762,
/* 180 */ 761, 229, 811, 804, 803, 389, 688, 808, 807, 737,
- /* 190 */ 460, 464, 572, 584, 1356, 1361, 1358, 1347, 1355, 1353,
- /* 200 */ 1351, 1323, 1335, 1346, 1335, 1335, 1335, 1335, 1335, 1335,
- /* 210 */ 1335, 1312, 1304, 1335, 1335, 1323, 1359, 1330, 1376, 1320,
- /* 220 */ 1319, 1318, 1280, 1316, 1278, 1345, 1352, 1344, 1350, 1340,
- /* 230 */ 1332, 1336, 1303, 1334, 1333, 1281, 1273, 1271, 1337, 1310,
- /* 240 */ 1309, 1349, 1261, 1342, 1341, 1257, 1252, 1339, 1275, 1302,
- /* 250 */ 1294, 1300, 1298, 1297, 1296, 1329, 1286, 1264, 1292, 1289,
+ /* 190 */ 460, 464, 572, 584, 1355, 1366, 1365, 1352, 1354, 1353,
+ /* 200 */ 1352, 1326, 1335, 1342, 1335, 1335, 1335, 1335, 1335, 1335,
+ /* 210 */ 1335, 1295, 1295, 1335, 1335, 1321, 1362, 1331, 1378, 1326,
+ /* 220 */ 1315, 1314, 1280, 1322, 1278, 1341, 1352, 1340, 1350, 1338,
+ /* 230 */ 1332, 1336, 1303, 1334, 1333, 1281, 1275, 1274, 1340, 1307,
+ /* 240 */ 1308, 1350, 1255, 1343, 1342, 1255, 1253, 1338, 1275, 1304,
+ /* 250 */ 1293, 1299, 1298, 1297, 1295, 1329, 1286, 1264, 1292, 1289,
/* 260 */ 1322, 1321, 1235, 1226, 1315, 1314, 1311, 1308, 1307, 1305,
/* 270 */ 1299, 1279, 1277, 1276, 1270, 1258, 1211, 1209, 1250, 1259,
/* 280 */ 1255, 1242, 1243, 1241, 1201, 1200, 1184, 1186, 1182, 1178,
@@ -97914,7 +91609,7 @@ static const YYACTIONTYPE yy_default[] = {
/* The next table maps tokens into fallback tokens. If a construct
** like the following:
-**
+**
** %fallback ID X Y Z.
**
** appears in the grammar, then ID becomes a fallback token for X, Y,
@@ -98039,10 +91734,10 @@ static char *yyTracePrompt = 0;
#endif /* NDEBUG */
#ifndef NDEBUG
-/*
+/*
** Turn parser tracing on by giving a stream to which to write the trace
** and a prompt to preface each trace message. Tracing is turned off
-** by making either argument NULL
+** by making either argument NULL
**
** Inputs:
** <ul>
@@ -98067,71 +91762,71 @@ SQLITE_PRIVATE void sqlite3ParserTrace(FILE *TraceFILE, char *zTracePrompt){
#ifndef NDEBUG
/* For tracing shifts, the names of all terminals and nonterminals
** are required. The following table supplies these names */
-static const char *const yyTokenName[] = {
- "$", "SEMI", "EXPLAIN", "QUERY",
- "PLAN", "BEGIN", "TRANSACTION", "DEFERRED",
- "IMMEDIATE", "EXCLUSIVE", "COMMIT", "END",
- "ROLLBACK", "SAVEPOINT", "RELEASE", "TO",
- "TABLE", "CREATE", "IF", "NOT",
- "EXISTS", "TEMP", "LP", "RP",
- "AS", "COMMA", "ID", "INDEXED",
- "ABORT", "ACTION", "AFTER", "ANALYZE",
- "ASC", "ATTACH", "BEFORE", "BY",
- "CASCADE", "CAST", "COLUMNKW", "CONFLICT",
- "DATABASE", "DESC", "DETACH", "EACH",
- "FAIL", "FOR", "IGNORE", "INITIALLY",
- "INSTEAD", "LIKE_KW", "MATCH", "NO",
- "KEY", "OF", "OFFSET", "PRAGMA",
- "RAISE", "REPLACE", "RESTRICT", "ROW",
- "TRIGGER", "VACUUM", "VIEW", "VIRTUAL",
- "REINDEX", "RENAME", "CTIME_KW", "ANY",
- "OR", "AND", "IS", "BETWEEN",
- "IN", "ISNULL", "NOTNULL", "NE",
- "EQ", "GT", "LE", "LT",
- "GE", "ESCAPE", "BITAND", "BITOR",
- "LSHIFT", "RSHIFT", "PLUS", "MINUS",
- "STAR", "SLASH", "REM", "CONCAT",
- "COLLATE", "BITNOT", "STRING", "JOIN_KW",
- "CONSTRAINT", "DEFAULT", "NULL", "PRIMARY",
- "UNIQUE", "CHECK", "REFERENCES", "AUTOINCR",
- "ON", "INSERT", "DELETE", "UPDATE",
- "SET", "DEFERRABLE", "FOREIGN", "DROP",
- "UNION", "ALL", "EXCEPT", "INTERSECT",
- "SELECT", "DISTINCT", "DOT", "FROM",
- "JOIN", "USING", "ORDER", "GROUP",
- "HAVING", "LIMIT", "WHERE", "INTO",
- "VALUES", "INTEGER", "FLOAT", "BLOB",
- "REGISTER", "VARIABLE", "CASE", "WHEN",
- "THEN", "ELSE", "INDEX", "ALTER",
- "ADD", "error", "input", "cmdlist",
- "ecmd", "explain", "cmdx", "cmd",
+static const char *const yyTokenName[] = {
+ "$", "SEMI", "EXPLAIN", "QUERY",
+ "PLAN", "BEGIN", "TRANSACTION", "DEFERRED",
+ "IMMEDIATE", "EXCLUSIVE", "COMMIT", "END",
+ "ROLLBACK", "SAVEPOINT", "RELEASE", "TO",
+ "TABLE", "CREATE", "IF", "NOT",
+ "EXISTS", "TEMP", "LP", "RP",
+ "AS", "COMMA", "ID", "INDEXED",
+ "ABORT", "ACTION", "AFTER", "ANALYZE",
+ "ASC", "ATTACH", "BEFORE", "BY",
+ "CASCADE", "CAST", "COLUMNKW", "CONFLICT",
+ "DATABASE", "DESC", "DETACH", "EACH",
+ "FAIL", "FOR", "IGNORE", "INITIALLY",
+ "INSTEAD", "LIKE_KW", "MATCH", "NO",
+ "KEY", "OF", "OFFSET", "PRAGMA",
+ "RAISE", "REPLACE", "RESTRICT", "ROW",
+ "TRIGGER", "VACUUM", "VIEW", "VIRTUAL",
+ "REINDEX", "RENAME", "CTIME_KW", "ANY",
+ "OR", "AND", "IS", "BETWEEN",
+ "IN", "ISNULL", "NOTNULL", "NE",
+ "EQ", "GT", "LE", "LT",
+ "GE", "ESCAPE", "BITAND", "BITOR",
+ "LSHIFT", "RSHIFT", "PLUS", "MINUS",
+ "STAR", "SLASH", "REM", "CONCAT",
+ "COLLATE", "BITNOT", "STRING", "JOIN_KW",
+ "CONSTRAINT", "DEFAULT", "NULL", "PRIMARY",
+ "UNIQUE", "CHECK", "REFERENCES", "AUTOINCR",
+ "ON", "INSERT", "DELETE", "UPDATE",
+ "SET", "DEFERRABLE", "FOREIGN", "DROP",
+ "UNION", "ALL", "EXCEPT", "INTERSECT",
+ "SELECT", "DISTINCT", "DOT", "FROM",
+ "JOIN", "USING", "ORDER", "GROUP",
+ "HAVING", "LIMIT", "WHERE", "INTO",
+ "VALUES", "INTEGER", "FLOAT", "BLOB",
+ "REGISTER", "VARIABLE", "CASE", "WHEN",
+ "THEN", "ELSE", "INDEX", "ALTER",
+ "ADD", "error", "input", "cmdlist",
+ "ecmd", "explain", "cmdx", "cmd",
"transtype", "trans_opt", "nm", "savepoint_opt",
- "create_table", "create_table_args", "createkw", "temp",
+ "create_table", "create_table_args", "createkw", "temp",
"ifnotexists", "dbnm", "columnlist", "conslist_opt",
- "select", "column", "columnid", "type",
- "carglist", "id", "ids", "typetoken",
- "typename", "signed", "plus_num", "minus_num",
- "carg", "ccons", "term", "expr",
- "onconf", "sortorder", "autoinc", "idxlist_opt",
- "refargs", "defer_subclause", "refarg", "refact",
- "init_deferred_pred_opt", "conslist", "tcons", "idxlist",
- "defer_subclause_opt", "orconf", "resolvetype", "raisetype",
+ "select", "column", "columnid", "type",
+ "carglist", "id", "ids", "typetoken",
+ "typename", "signed", "plus_num", "minus_num",
+ "carg", "ccons", "term", "expr",
+ "onconf", "sortorder", "autoinc", "idxlist_opt",
+ "refargs", "defer_subclause", "refarg", "refact",
+ "init_deferred_pred_opt", "conslist", "tcons", "idxlist",
+ "defer_subclause_opt", "orconf", "resolvetype", "raisetype",
"ifexists", "fullname", "oneselect", "multiselect_op",
- "distinct", "selcollist", "from", "where_opt",
- "groupby_opt", "having_opt", "orderby_opt", "limit_opt",
- "sclp", "as", "seltablist", "stl_prefix",
- "joinop", "indexed_opt", "on_opt", "using_opt",
- "joinop2", "inscollist", "sortlist", "sortitem",
+ "distinct", "selcollist", "from", "where_opt",
+ "groupby_opt", "having_opt", "orderby_opt", "limit_opt",
+ "sclp", "as", "seltablist", "stl_prefix",
+ "joinop", "indexed_opt", "on_opt", "using_opt",
+ "joinop2", "inscollist", "sortlist", "sortitem",
"nexprlist", "setlist", "insert_cmd", "inscollist_opt",
- "itemlist", "exprlist", "likeop", "escape",
+ "itemlist", "exprlist", "likeop", "escape",
"between_op", "in_op", "case_operand", "case_exprlist",
- "case_else", "uniqueflag", "collate", "nmnum",
+ "case_else", "uniqueflag", "collate", "nmnum",
"plus_opt", "number", "trigger_decl", "trigger_cmd_list",
- "trigger_time", "trigger_event", "foreach_clause", "when_clause",
+ "trigger_time", "trigger_event", "foreach_clause", "when_clause",
"trigger_cmd", "trnm", "tridxby", "database_kw_opt",
- "key_opt", "add_column_fullname", "kwcolumn_opt", "create_vtab",
- "vtabarglist", "vtabarg", "vtabargtoken", "lp",
- "anylist",
+ "key_opt", "add_column_fullname", "kwcolumn_opt", "create_vtab",
+ "vtabarglist", "vtabarg", "vtabargtoken", "lp",
+ "anylist",
};
#endif /* NDEBUG */
@@ -98496,7 +92191,7 @@ static void yyGrowStack(yyParser *p){
}
#endif
-/*
+/*
** This function allocates a new parser.
** The only argument is a pointer to a function which works like
** malloc.
@@ -98540,7 +92235,7 @@ static void yy_destructor(
/* Here is inserted the actions which take place when a
** terminal or non-terminal is destroyed. This can happen
** when the symbol is popped from the stack during a
- ** reduce or during error processing or when a parser is
+ ** reduce or during error processing or when a parser is
** being destroyed before it is finished parsing.
**
** Note: during a reduce, the only symbols destroyed are those
@@ -98646,7 +92341,7 @@ static int yy_pop_parser_stack(yyParser *pParser){
return yymajor;
}
-/*
+/*
** Deallocate and destroy a parser. Destructors are all called for
** all stack elements before shutting the parser down.
**
@@ -98697,7 +92392,7 @@ static int yy_find_shift_action(
){
int i;
int stateno = pParser->yystack[pParser->yyidx].stateno;
-
+
if( stateno>YY_SHIFT_COUNT
|| (i = yy_shift_ofst[stateno])==YY_SHIFT_USE_DFLT ){
return yy_default[stateno];
@@ -98722,7 +92417,7 @@ static int yy_find_shift_action(
#ifdef YYWILDCARD
{
int j = i - iLookAhead + YYWILDCARD;
- if(
+ if(
#if YY_SHIFT_MIN+YYWILDCARD<0
j>=0 &&
#endif
@@ -98820,7 +92515,7 @@ static void yy_shift(
yypParser->yyidxMax = yypParser->yyidx;
}
#endif
-#if YYSTACKDEPTH>0
+#if YYSTACKDEPTH>0
if( yypParser->yyidx>=YYSTACKDEPTH ){
yyStackOverflow(yypParser, yypMinor);
return;
@@ -99207,7 +92902,7 @@ static void yy_reduce(
sqlite3ParserARG_FETCH;
yymsp = &yypParser->yystack[yypParser->yyidx];
#ifndef NDEBUG
- if( yyTraceFILE && yyruleno>=0
+ if( yyTraceFILE && yyruleno>=0
&& yyruleno<(int)(sizeof(yyRuleName)/sizeof(yyRuleName[0])) ){
fprintf(yyTraceFILE, "%sReduce [%s].\n", yyTracePrompt,
yyRuleName[yyruleno]);
@@ -99220,7 +92915,7 @@ static void yy_reduce(
** not set the value of its left-hand side nonterminal. Leaving the
** value of the nonterminal uninitialized is utterly harmless as long
** as the value is never used. So really the only thing this code
- ** accomplishes is to quieten purify.
+ ** accomplishes is to quieten purify.
**
** 2007-01-16: The wireshark project (www.wireshark.org) reports that
** without this code, their parser segfaults. I'm not sure what there
@@ -99257,7 +92952,7 @@ static void yy_reduce(
{sqlite3BeginTransaction(pParse, yymsp[-1].minor.yy328);}
break;
case 13: /* transtype ::= */
-{yygotominor.yy328 = TK_DEFERRED;}
+{yygotominor.yy328 = (pParse->db->flags&SQLITE_BeginImmediate) ? TK_IMMEDIATE : TK_DEFERRED;}/* Android Change */
break;
case 14: /* transtype ::= DEFERRED */
case 15: /* transtype ::= IMMEDIATE */ yytestcase(yyruleno==15);
@@ -99715,7 +93410,7 @@ static void yy_reduce(
case 170: /* cmd ::= UPDATE orconf fullname indexed_opt SET setlist where_opt */
{
sqlite3SrcListIndexedBy(pParse, yymsp[-4].minor.yy65, &yymsp[-3].minor.yy0);
- sqlite3ExprListCheckLength(pParse,yymsp[-1].minor.yy14,"set list");
+ sqlite3ExprListCheckLength(pParse,yymsp[-1].minor.yy14,"set list");
sqlite3Update(pParse,yymsp[-4].minor.yy65,yymsp[-1].minor.yy14,yymsp[0].minor.yy132,yymsp[-5].minor.yy186);
}
break;
@@ -99853,7 +93548,7 @@ static void yy_reduce(
** treated as functions that return constants */
yygotominor.yy346.pExpr = sqlite3ExprFunction(pParse, 0,&yymsp[0].minor.yy0);
if( yygotominor.yy346.pExpr ){
- yygotominor.yy346.pExpr->op = TK_CONST_FUNC;
+ yygotominor.yy346.pExpr->op = TK_CONST_FUNC;
}
spanSet(&yygotominor.yy346, &yymsp[0].minor.yy0, &yymsp[0].minor.yy0);
}
@@ -99931,7 +93626,7 @@ static void yy_reduce(
yygotominor.yy346.pExpr->x.pList = pList;
}else{
sqlite3ExprListDelete(pParse->db, pList);
- }
+ }
if( yymsp[-3].minor.yy328 ) yygotominor.yy346.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy346.pExpr, 0, 0);
yygotominor.yy346.zStart = yymsp[-4].minor.yy346.zStart;
yygotominor.yy346.zEnd = yymsp[0].minor.yy346.zEnd;
@@ -100037,7 +93732,7 @@ static void yy_reduce(
break;
case 244: /* cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP idxlist RP */
{
- sqlite3CreateIndex(pParse, &yymsp[-6].minor.yy0, &yymsp[-5].minor.yy0,
+ sqlite3CreateIndex(pParse, &yymsp[-6].minor.yy0, &yymsp[-5].minor.yy0,
sqlite3SrcListAppend(pParse->db,0,&yymsp[-3].minor.yy0,0), yymsp[-1].minor.yy14, yymsp[-9].minor.yy328,
&yymsp[-10].minor.yy0, &yymsp[0].minor.yy0, SQLITE_SO_ASC, yymsp[-7].minor.yy328);
}
@@ -100148,7 +93843,7 @@ static void yy_reduce(
}
break;
case 285: /* trigger_cmd_list ::= trigger_cmd SEMI */
-{
+{
assert( yymsp[-1].minor.yy473!=0 );
yymsp[-1].minor.yy473->pLast = yymsp[-1].minor.yy473;
yygotominor.yy473 = yymsp[-1].minor.yy473;
@@ -100157,7 +93852,7 @@ static void yy_reduce(
case 287: /* trnm ::= nm DOT nm */
{
yygotominor.yy0 = yymsp[0].minor.yy0;
- sqlite3ErrorMsg(pParse,
+ sqlite3ErrorMsg(pParse,
"qualified table names are not allowed on INSERT, UPDATE, and DELETE "
"statements within triggers");
}
@@ -100193,7 +93888,7 @@ static void yy_reduce(
break;
case 296: /* expr ::= RAISE LP IGNORE RP */
{
- yygotominor.yy346.pExpr = sqlite3PExpr(pParse, TK_RAISE, 0, 0, 0);
+ yygotominor.yy346.pExpr = sqlite3PExpr(pParse, TK_RAISE, 0, 0, 0);
if( yygotominor.yy346.pExpr ){
yygotominor.yy346.pExpr->affinity = OE_Ignore;
}
@@ -100203,7 +93898,7 @@ static void yy_reduce(
break;
case 297: /* expr ::= RAISE LP raisetype COMMA nm RP */
{
- yygotominor.yy346.pExpr = sqlite3PExpr(pParse, TK_RAISE, 0, 0, &yymsp[-1].minor.yy0);
+ yygotominor.yy346.pExpr = sqlite3PExpr(pParse, TK_RAISE, 0, 0, &yymsp[-1].minor.yy0);
if( yygotominor.yy346.pExpr ) {
yygotominor.yy346.pExpr->affinity = (char)yymsp[-3].minor.yy328;
}
@@ -100486,7 +94181,7 @@ SQLITE_PRIVATE void sqlite3Parser(
#ifdef YYERRORSYMBOL
/* A syntax error has occurred.
** The response to an error depends upon whether or not the
- ** grammar defines an error token "ERROR".
+ ** grammar defines an error token "ERROR".
**
** This is what we do if the grammar does define ERROR:
**
@@ -100549,7 +94244,7 @@ SQLITE_PRIVATE void sqlite3Parser(
yy_syntax_error(yypParser,yymajor,yyminorunion);
yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion);
yymajor = YYNOCODE;
-
+
#else /* YYERRORSYMBOL is not defined */
/* This is what we do if the grammar does not define ERROR:
**
@@ -100630,7 +94325,7 @@ const unsigned char ebcdicToAscii[] = {
/*
** The sqlite3KeywordCode function looks up an identifier to determine if
-** it is a keyword. If it is a keyword, the token code of that keyword is
+** it is a keyword. If it is a keyword, the token code of that keyword is
** returned. If the input is not a keyword, TK_ID is returned.
**
** The implementation of this routine was generated by a program,
@@ -100748,31 +94443,31 @@ static int keywordCode(const char *z, int n){
521, 527, 531, 536,
};
static const unsigned char aCode[121] = {
- TK_REINDEX, TK_INDEXED, TK_INDEX, TK_DESC, TK_ESCAPE,
- TK_EACH, TK_CHECK, TK_KEY, TK_BEFORE, TK_FOREIGN,
- TK_FOR, TK_IGNORE, TK_LIKE_KW, TK_EXPLAIN, TK_INSTEAD,
- TK_ADD, TK_DATABASE, TK_AS, TK_SELECT, TK_TABLE,
- TK_JOIN_KW, TK_THEN, TK_END, TK_DEFERRABLE, TK_ELSE,
- TK_EXCEPT, TK_TRANSACTION,TK_ACTION, TK_ON, TK_JOIN_KW,
- TK_ALTER, TK_RAISE, TK_EXCLUSIVE, TK_EXISTS, TK_SAVEPOINT,
- TK_INTERSECT, TK_TRIGGER, TK_REFERENCES, TK_CONSTRAINT, TK_INTO,
- TK_OFFSET, TK_OF, TK_SET, TK_TEMP, TK_TEMP,
- TK_OR, TK_UNIQUE, TK_QUERY, TK_ATTACH, TK_HAVING,
- TK_GROUP, TK_UPDATE, TK_BEGIN, TK_JOIN_KW, TK_RELEASE,
- TK_BETWEEN, TK_NOTNULL, TK_NOT, TK_NO, TK_NULL,
- TK_LIKE_KW, TK_CASCADE, TK_ASC, TK_DELETE, TK_CASE,
- TK_COLLATE, TK_CREATE, TK_CTIME_KW, TK_DETACH, TK_IMMEDIATE,
- TK_JOIN, TK_INSERT, TK_MATCH, TK_PLAN, TK_ANALYZE,
- TK_PRAGMA, TK_ABORT, TK_VALUES, TK_VIRTUAL, TK_LIMIT,
- TK_WHEN, TK_WHERE, TK_RENAME, TK_AFTER, TK_REPLACE,
- TK_AND, TK_DEFAULT, TK_AUTOINCR, TK_TO, TK_IN,
- TK_CAST, TK_COLUMNKW, TK_COMMIT, TK_CONFLICT, TK_JOIN_KW,
- TK_CTIME_KW, TK_CTIME_KW, TK_PRIMARY, TK_DEFERRED, TK_DISTINCT,
- TK_IS, TK_DROP, TK_FAIL, TK_FROM, TK_JOIN_KW,
- TK_LIKE_KW, TK_BY, TK_IF, TK_ISNULL, TK_ORDER,
- TK_RESTRICT, TK_JOIN_KW, TK_JOIN_KW, TK_ROLLBACK, TK_ROW,
- TK_UNION, TK_USING, TK_VACUUM, TK_VIEW, TK_INITIALLY,
- TK_ALL,
+ TK_REINDEX, TK_INDEXED, TK_INDEX, TK_DESC, TK_ESCAPE,
+ TK_EACH, TK_CHECK, TK_KEY, TK_BEFORE, TK_FOREIGN,
+ TK_FOR, TK_IGNORE, TK_LIKE_KW, TK_EXPLAIN, TK_INSTEAD,
+ TK_ADD, TK_DATABASE, TK_AS, TK_SELECT, TK_TABLE,
+ TK_JOIN_KW, TK_THEN, TK_END, TK_DEFERRABLE, TK_ELSE,
+ TK_EXCEPT, TK_TRANSACTION,TK_ACTION, TK_ON, TK_JOIN_KW,
+ TK_ALTER, TK_RAISE, TK_EXCLUSIVE, TK_EXISTS, TK_SAVEPOINT,
+ TK_INTERSECT, TK_TRIGGER, TK_REFERENCES, TK_CONSTRAINT, TK_INTO,
+ TK_OFFSET, TK_OF, TK_SET, TK_TEMP, TK_TEMP,
+ TK_OR, TK_UNIQUE, TK_QUERY, TK_ATTACH, TK_HAVING,
+ TK_GROUP, TK_UPDATE, TK_BEGIN, TK_JOIN_KW, TK_RELEASE,
+ TK_BETWEEN, TK_NOTNULL, TK_NOT, TK_NO, TK_NULL,
+ TK_LIKE_KW, TK_CASCADE, TK_ASC, TK_DELETE, TK_CASE,
+ TK_COLLATE, TK_CREATE, TK_CTIME_KW, TK_DETACH, TK_IMMEDIATE,
+ TK_JOIN, TK_INSERT, TK_MATCH, TK_PLAN, TK_ANALYZE,
+ TK_PRAGMA, TK_ABORT, TK_VALUES, TK_VIRTUAL, TK_LIMIT,
+ TK_WHEN, TK_WHERE, TK_RENAME, TK_AFTER, TK_REPLACE,
+ TK_AND, TK_DEFAULT, TK_AUTOINCR, TK_TO, TK_IN,
+ TK_CAST, TK_COLUMNKW, TK_COMMIT, TK_CONFLICT, TK_JOIN_KW,
+ TK_CTIME_KW, TK_CTIME_KW, TK_PRIMARY, TK_DEFERRED, TK_DISTINCT,
+ TK_IS, TK_DROP, TK_FAIL, TK_FROM, TK_JOIN_KW,
+ TK_LIKE_KW, TK_BY, TK_IF, TK_ISNULL, TK_ORDER,
+ TK_RESTRICT, TK_JOIN_KW, TK_JOIN_KW, TK_ROLLBACK, TK_ROW,
+ TK_UNION, TK_USING, TK_VACUUM, TK_VIEW, TK_INITIALLY,
+ TK_ALL,
};
int h, i;
if( n<2 ) return TK_ID;
@@ -100921,14 +94616,14 @@ SQLITE_PRIVATE int sqlite3KeywordCode(const unsigned char *z, int n){
** IdChar(X) will be true. Otherwise it is false.
**
** For ASCII, any character with the high-order bit set is
-** allowed in an identifier. For 7-bit characters,
+** allowed in an identifier. For 7-bit characters,
** sqlite3IsIdChar[X] must be 1.
**
** For EBCDIC, the rules are more complex but have the same
** end result.
**
** Ticket #1066. the SQL standard does not allow '$' in the
-** middle of identfiers. But many SQL implementations do.
+** middle of identfiers. But many SQL implementations do.
** SQLite will allow '$' in identifiers for compatibility.
** But the feature is undocumented.
*/
@@ -100956,7 +94651,7 @@ SQLITE_PRIVATE const char sqlite3IsEbcdicIdChar[] = {
/*
-** Return the length of the token that begins at z[0].
+** Return the length of the token that begins at z[0].
** Store the token type in *tokenType before returning.
*/
SQLITE_PRIVATE int sqlite3GetToken(const unsigned char *z, int *tokenType){
@@ -101131,7 +94826,7 @@ SQLITE_PRIVATE int sqlite3GetToken(const unsigned char *z, int *tokenType){
*tokenType = TK_FLOAT;
}
if( (z[i]=='e' || z[i]=='E') &&
- ( sqlite3Isdigit(z[i+1])
+ ( sqlite3Isdigit(z[i+1])
|| ((z[i+1]=='+' || z[i+1]=='-') && sqlite3Isdigit(z[i+2]))
)
){
@@ -101232,7 +94927,7 @@ SQLITE_PRIVATE int sqlite3GetToken(const unsigned char *z, int *tokenType){
/*
** Run the parser on the given SQL string. The parser structure is
** passed in. An SQLITE_ status code is returned. If an error occurs
-** then an and attempt is made to write an error message into
+** then an and attempt is made to write an error message into
** memory obtained from sqlite3_malloc() and to make *pzErrMsg point to that
** error message.
*/
@@ -101351,7 +95046,7 @@ abort_parse:
#endif
if( !IN_DECLARE_VTAB ){
- /* If the pParse->declareVtab flag is set, do not delete any table
+ /* If the pParse->declareVtab flag is set, do not delete any table
** structure built up in pParse->pNewTable. The calling code (see vtab.c)
** will take responsibility for freeing the Table structure.
*/
@@ -101446,7 +95141,7 @@ SQLITE_PRIVATE const char sqlite3IsEbcdicIdChar[];
** (2) NORMAL We are in the middle of statement which ends with a single
** semicolon.
**
-** (3) EXPLAIN The keyword EXPLAIN has been seen at the beginning of
+** (3) EXPLAIN The keyword EXPLAIN has been seen at the beginning of
** a statement.
**
** (4) CREATE The keyword CREATE has been seen at the beginning of a
@@ -101704,7 +95399,9 @@ SQLITE_API int sqlite3_complete16(const void *zSql){
extern "C" {
#endif /* __cplusplus */
-SQLITE_PRIVATE int sqlite3Fts3Init(sqlite3 *db, const char* registerAs); // Android Change
+// Begin Android Change
+SQLITE_PRIVATE int sqlite3Fts3Init(sqlite3 *db, const char* registerAs);
+// End Android Change
#if 0
} /* extern "C" */
@@ -101810,13 +95507,13 @@ SQLITE_PRIVATE void (*sqlite3IoTrace)(const char*, ...) = 0;
SQLITE_API char *sqlite3_temp_directory = 0;
/*
-** Initialize SQLite.
+** Initialize SQLite.
**
** This routine must be called to initialize the memory allocation,
** VFS, and mutex subsystems prior to doing any serious work with
** SQLite. But as long as you do not compile with SQLITE_OMIT_AUTOINIT
** this routine will be called automatically by key routines such as
-** sqlite3_open().
+** sqlite3_open().
**
** This routine is a no-op except on its very first call for the process,
** or for the first call after a call to sqlite3_shutdown.
@@ -101858,7 +95555,7 @@ SQLITE_API int sqlite3_initialize(void){
*/
if( sqlite3GlobalConfig.isInit ) return SQLITE_OK;
- /* Make sure the mutex subsystem is initialized. If unable to
+ /* Make sure the mutex subsystem is initialized. If unable to
** initialize the mutex subsystem, return early with the error.
** If the system is so sick that we are unable to allocate a mutex,
** there is not much SQLite is going to be able to do.
@@ -101923,7 +95620,7 @@ SQLITE_API int sqlite3_initialize(void){
rc = sqlite3OsInit();
}
if( rc==SQLITE_OK ){
- sqlite3PCacheBufferSetup( sqlite3GlobalConfig.pPage,
+ sqlite3PCacheBufferSetup( sqlite3GlobalConfig.pPage,
sqlite3GlobalConfig.szPage, sqlite3GlobalConfig.nPage);
sqlite3GlobalConfig.isInit = 1;
}
@@ -102016,7 +95713,7 @@ SQLITE_API int sqlite3_config(int op, ...){
switch( op ){
/* Mutex configuration options are only available in a threadsafe
- ** compile.
+ ** compile.
*/
#if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE>0
case SQLITE_CONFIG_SINGLETHREAD: {
@@ -102131,18 +95828,13 @@ SQLITE_API int sqlite3_config(int op, ...){
sqlite3GlobalConfig.nLookaside = va_arg(ap, int);
break;
}
-
+
/* Record a pointer to the logger funcction and its first argument.
** The default is NULL. Logging is disabled if the function pointer is
** NULL.
*/
case SQLITE_CONFIG_LOG: {
- /* MSVC is picky about pulling func ptrs from va lists.
- ** http://support.microsoft.com/kb/47961
- ** sqlite3GlobalConfig.xLog = va_arg(ap, void(*)(void*,int,const char*));
- */
- typedef void(*LOGFUNC_t)(void*,int,const char*);
- sqlite3GlobalConfig.xLog = va_arg(ap, LOGFUNC_t);
+ sqlite3GlobalConfig.xLog = va_arg(ap, void(*)(void*,int,const char*));
sqlite3GlobalConfig.pLogArg = va_arg(ap, void*);
break;
}
@@ -102158,7 +95850,7 @@ SQLITE_API int sqlite3_config(int op, ...){
/*
** Set up the lookaside buffers for a database connection.
-** Return SQLITE_OK on success.
+** Return SQLITE_OK on success.
** If lookaside is already active, return SQLITE_BUSY.
**
** The sz parameter is the number of bytes in each lookaside slot.
@@ -102173,7 +95865,7 @@ static int setupLookaside(sqlite3 *db, void *pBuf, int sz, int cnt){
return SQLITE_BUSY;
}
/* Free any existing lookaside buffer for this handle before
- ** allocating a new one so we don't have to have space for
+ ** allocating a new one so we don't have to have space for
** both at the same time.
*/
if( db->lookaside.bMalloced ){
@@ -102289,7 +95981,7 @@ static int binCollFunc(
}
/*
-** Another built-in collating sequence: NOCASE.
+** Another built-in collating sequence: NOCASE.
**
** This collating sequence is intended to be used for "case independant
** comparison". SQLite's knowledge of upper and lower case equivalents
@@ -102376,7 +96068,7 @@ SQLITE_API int sqlite3_close(sqlite3 *db){
/* If there are any outstanding VMs, return SQLITE_BUSY. */
if( db->pVdbe ){
- sqlite3Error(db, SQLITE_BUSY,
+ sqlite3Error(db, SQLITE_BUSY,
"unable to close due to unfinalised statements");
sqlite3_mutex_leave(db->mutex);
return SQLITE_BUSY;
@@ -102386,7 +96078,7 @@ SQLITE_API int sqlite3_close(sqlite3 *db){
for(j=0; j<db->nDb; j++){
Btree *pBt = db->aDb[j].pBt;
if( pBt && sqlite3BtreeIsInBackup(pBt) ){
- sqlite3Error(db, SQLITE_BUSY,
+ sqlite3Error(db, SQLITE_BUSY,
"unable to close due to unfinished backup operation");
sqlite3_mutex_leave(db->mutex);
return SQLITE_BUSY;
@@ -102459,7 +96151,7 @@ SQLITE_API int sqlite3_close(sqlite3 *db){
/* The temp-database schema is allocated differently from the other schema
** objects (using sqliteMalloc() directly, instead of sqlite3BtreeSchema()).
** So it needs to be freed here. Todo: Why not roll the temp schema into
- ** the same sqliteMalloc() as the one that allocates the database
+ ** the same sqliteMalloc() as the one that allocates the database
** structure?
*/
sqlite3DbFree(db, db->aDb[1].pSchema);
@@ -102611,7 +96303,7 @@ SQLITE_PRIVATE int sqlite3InvokeBusyHandler(BusyHandler *p){
}else{
p->nBusy++;
}
- return rc;
+ return rc;
}
/*
@@ -102638,9 +96330,9 @@ SQLITE_API int sqlite3_busy_handler(
** be invoked every nOps opcodes.
*/
SQLITE_API void sqlite3_progress_handler(
- sqlite3 *db,
+ sqlite3 *db,
int nOps,
- int (*xProgress)(void*),
+ int (*xProgress)(void*),
void *pArg
){
sqlite3_mutex_enter(db->mutex);
@@ -102684,7 +96376,7 @@ SQLITE_API void sqlite3_interrupt(sqlite3 *db){
** This function is exactly the same as sqlite3_create_function(), except
** that it is designed to be called by internal code. The difference is
** that if a malloc() fails in sqlite3_create_function(), an error code
-** is returned and the mallocFailed flag cleared.
+** is returned and the mallocFailed flag cleared.
*/
SQLITE_PRIVATE int sqlite3CreateFunc(
sqlite3 *db,
@@ -102701,14 +96393,14 @@ SQLITE_PRIVATE int sqlite3CreateFunc(
assert( sqlite3_mutex_held(db->mutex) );
if( zFunctionName==0 ||
- (xFunc && (xFinal || xStep)) ||
+ (xFunc && (xFinal || xStep)) ||
(!xFunc && (xFinal && !xStep)) ||
(!xFunc && (!xFinal && xStep)) ||
(nArg<-1 || nArg>SQLITE_MAX_FUNCTION_ARG) ||
(255<(nName = sqlite3Strlen30( zFunctionName))) ){
return SQLITE_MISUSE_BKPT;
}
-
+
#ifndef SQLITE_OMIT_UTF16
/* If SQLITE_UTF16 is specified as the encoding type, transform this
** to one of SQLITE_UTF16LE or SQLITE_UTF16BE using the
@@ -102735,7 +96427,7 @@ SQLITE_PRIVATE int sqlite3CreateFunc(
#else
enc = SQLITE_UTF8;
#endif
-
+
/* Check if an existing function is being overridden or deleted. If so,
** and there are active VMs, then return SQLITE_BUSY. If a function
** is being overridden/deleted but there are no active VMs, allow the
@@ -102744,7 +96436,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 ){
- sqlite3Error(db, SQLITE_BUSY,
+ sqlite3Error(db, SQLITE_BUSY,
"unable to delete/modify user-function due to active statements");
assert( !db->mallocFailed );
return SQLITE_BUSY;
@@ -102803,7 +96495,7 @@ SQLITE_API int sqlite3_create_function16(
char *zFunc8;
sqlite3_mutex_enter(db->mutex);
assert( !db->mallocFailed );
- zFunc8 = sqlite3Utf16to8(db, zFunctionName, -1, SQLITE_UTF16NATIVE);
+ zFunc8 = sqlite3Utf16to8(db, zFunctionName, -1);
rc = sqlite3CreateFunc(db, zFunc8, nArg, eTextRep, p, xFunc, xStep, xFinal);
sqlite3DbFree(db, zFunc8);
rc = sqlite3ApiExit(db, rc);
@@ -102818,7 +96510,7 @@ SQLITE_API int sqlite3_create_function16(
**
** If the function already exists as a regular global function, then
** this routine is a no-op. If the function does not exist, then create
-** a new one that always throws a run-time error.
+** a new one that always throws a run-time error.
**
** When virtual tables intend to provide an overloaded function, they
** should call this routine to make sure the global function exists.
@@ -102845,7 +96537,7 @@ SQLITE_API int sqlite3_overload_function(
#ifndef SQLITE_OMIT_TRACE
/*
** Register a trace function. The pArg from the previously registered trace
-** is returned.
+** is returned.
**
** A NULL trace function means that no tracing is executes. A non-NULL
** trace is a pointer to a function that is invoked at the start of each
@@ -102861,8 +96553,8 @@ SQLITE_API void *sqlite3_trace(sqlite3 *db, void (*xTrace)(void*,const char*), v
return pOld;
}
/*
-** Register a profile function. The pArg from the previously registered
-** profile function is returned.
+** Register a profile function. The pArg from the previously registered
+** profile function is returned.
**
** A NULL profile function means that no profiling is executes. A non-NULL
** profile is a pointer to a function that is invoked at the conclusion of
@@ -102939,143 +96631,6 @@ SQLITE_API void *sqlite3_rollback_hook(
return pRet;
}
-#ifndef SQLITE_OMIT_WAL
-/*
-** The sqlite3_wal_hook() callback registered by sqlite3_wal_autocheckpoint().
-** Invoke sqlite3_wal_checkpoint if the number of frames in the log file
-** is greater than sqlite3.pWalArg cast to an integer (the value configured by
-** wal_autocheckpoint()).
-*/
-SQLITE_PRIVATE int sqlite3WalDefaultHook(
- void *pClientData, /* Argument */
- sqlite3 *db, /* Connection */
- const char *zDb, /* Database */
- int nFrame /* Size of WAL */
-){
- if( nFrame>=SQLITE_PTR_TO_INT(pClientData) ){
- sqlite3_wal_checkpoint(db, zDb);
- }
- return SQLITE_OK;
-}
-#endif /* SQLITE_OMIT_WAL */
-
-/*
-** Configure an sqlite3_wal_hook() callback to automatically checkpoint
-** a database after committing a transaction if there are nFrame or
-** more frames in the log file. Passing zero or a negative value as the
-** nFrame parameter disables automatic checkpoints entirely.
-**
-** The callback registered by this function replaces any existing callback
-** registered using sqlite3_wal_hook(). Likewise, registering a callback
-** using sqlite3_wal_hook() disables the automatic checkpoint mechanism
-** configured by this function.
-*/
-SQLITE_API int sqlite3_wal_autocheckpoint(sqlite3 *db, int nFrame){
-#ifndef SQLITE_OMIT_WAL
- if( nFrame>0 ){
- sqlite3_wal_hook(db, sqlite3WalDefaultHook, SQLITE_INT_TO_PTR(nFrame));
- }else{
- sqlite3_wal_hook(db, 0, 0);
- }
-#endif
- return SQLITE_OK;
-}
-
-/*
-** Register a callback to be invoked each time a transaction is written
-** into the write-ahead-log by this database connection.
-*/
-SQLITE_API void *sqlite3_wal_hook(
- sqlite3 *db, /* Attach the hook to this db handle */
- int(*xCallback)(void *, sqlite3*, const char*, int),
- void *pArg /* First argument passed to xCallback() */
-){
-#ifndef SQLITE_OMIT_WAL
- void *pRet;
- sqlite3_mutex_enter(db->mutex);
- pRet = db->pWalArg;
- db->xWalCallback = xCallback;
- db->pWalArg = pArg;
- sqlite3_mutex_leave(db->mutex);
- return pRet;
-#else
- return 0;
-#endif
-}
-
-
-/*
-** Checkpoint database zDb. If zDb is NULL, or if the buffer zDb points
-** to contains a zero-length string, all attached databases are
-** checkpointed.
-*/
-SQLITE_API int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb){
-#ifdef SQLITE_OMIT_WAL
- return SQLITE_OK;
-#else
- int rc; /* Return code */
- int iDb = SQLITE_MAX_ATTACHED; /* sqlite3.aDb[] index of db to checkpoint */
-
- sqlite3_mutex_enter(db->mutex);
- if( zDb && zDb[0] ){
- iDb = sqlite3FindDbName(db, zDb);
- }
- if( iDb<0 ){
- rc = SQLITE_ERROR;
- sqlite3Error(db, SQLITE_ERROR, "unknown database: %s", zDb);
- }else{
- rc = sqlite3Checkpoint(db, iDb);
- sqlite3Error(db, rc, 0);
- }
- rc = sqlite3ApiExit(db, rc);
- sqlite3_mutex_leave(db->mutex);
- return rc;
-#endif
-}
-
-#ifndef SQLITE_OMIT_WAL
-/*
-** Run a checkpoint on database iDb. This is a no-op if database iDb is
-** not currently open in WAL mode.
-**
-** If a transaction is open on the database being checkpointed, this
-** function returns SQLITE_LOCKED and a checkpoint is not attempted. If
-** an error occurs while running the checkpoint, an SQLite error code is
-** returned (i.e. SQLITE_IOERR). Otherwise, SQLITE_OK.
-**
-** The mutex on database handle db should be held by the caller. The mutex
-** associated with the specific b-tree being checkpointed is taken by
-** this function while the checkpoint is running.
-**
-** If iDb is passed SQLITE_MAX_ATTACHED, then all attached databases are
-** checkpointed. If an error is encountered it is returned immediately -
-** no attempt is made to checkpoint any remaining databases.
-*/
-SQLITE_PRIVATE int sqlite3Checkpoint(sqlite3 *db, int iDb){
- int rc = SQLITE_OK; /* Return code */
- int i; /* Used to iterate through attached dbs */
-
- assert( sqlite3_mutex_held(db->mutex) );
-
- for(i=0; i<db->nDb && rc==SQLITE_OK; i++){
- if( i==iDb || iDb==SQLITE_MAX_ATTACHED ){
- Btree *pBt = db->aDb[i].pBt;
- if( pBt ){
- if( sqlite3BtreeIsInReadTrans(pBt) ){
- rc = SQLITE_LOCKED;
- }else{
- sqlite3BtreeEnter(pBt);
- rc = sqlite3PagerCheckpoint(sqlite3BtreePager(pBt));
- sqlite3BtreeLeave(pBt);
- }
- }
- }
- }
-
- return rc;
-}
-#endif /* SQLITE_OMIT_WAL */
-
/*
** This function returns true if main-memory should be used instead of
** a temporary file for transient pager files and statement journals.
@@ -103133,7 +96688,7 @@ SQLITE_PRIVATE int sqlite3BtreeFactory(
){
int btFlags = 0;
int rc;
-
+
assert( sqlite3_mutex_held(db->mutex) );
assert( ppBtree != 0);
if( omitJournal ){
@@ -103155,7 +96710,7 @@ SQLITE_PRIVATE int sqlite3BtreeFactory(
/* If the B-Tree was successfully opened, set the pager-cache size to the
** default value. Except, if the call to BtreeOpen() returned a handle
- ** open on an existing shared pager-cache, do not change the pager-cache
+ ** open on an existing shared pager-cache, do not change the pager-cache
** size.
*/
if( rc==SQLITE_OK && 0==sqlite3BtreeSchema(*ppBtree, 0, 0) ){
@@ -103200,11 +96755,11 @@ SQLITE_API const void *sqlite3_errmsg16(sqlite3 *db){
'o', 'u', 't', ' ', 'o', 'f', ' ', 'm', 'e', 'm', 'o', 'r', 'y', 0
};
static const u16 misuse[] = {
- 'l', 'i', 'b', 'r', 'a', 'r', 'y', ' ',
- 'r', 'o', 'u', 't', 'i', 'n', 'e', ' ',
- 'c', 'a', 'l', 'l', 'e', 'd', ' ',
- 'o', 'u', 't', ' ',
- 'o', 'f', ' ',
+ 'l', 'i', 'b', 'r', 'a', 'r', 'y', ' ',
+ 'r', 'o', 'u', 't', 'i', 'n', 'e', ' ',
+ 'c', 'a', 'l', 'l', 'e', 'd', ' ',
+ 'o', 'u', 't', ' ',
+ 'o', 'f', ' ',
's', 'e', 'q', 'u', 'e', 'n', 'c', 'e', 0
};
@@ -103266,7 +96821,7 @@ SQLITE_API int sqlite3_extended_errcode(sqlite3 *db){
*/
static int createCollation(
sqlite3* db,
- const char *zName,
+ const char *zName,
u8 enc,
u8 collType,
void* pCtx,
@@ -103276,7 +96831,7 @@ static int createCollation(
CollSeq *pColl;
int enc2;
int nName = sqlite3Strlen30(zName);
-
+
assert( sqlite3_mutex_held(db->mutex) );
/* If SQLITE_UTF16 is specified as the encoding type, transform this
@@ -103293,14 +96848,14 @@ static int createCollation(
return SQLITE_MISUSE_BKPT;
}
- /* Check if this call is removing or replacing an existing collation
+ /* Check if this call is removing or replacing an existing collation
** sequence. If so, and there are active VMs, return busy. If there
** are no active VMs, invalidate any pre-compiled statements.
*/
pColl = sqlite3FindCollSeq(db, (u8)enc2, zName, 0);
if( pColl && pColl->xCmp ){
if( db->activeVdbeCnt ){
- sqlite3Error(db, SQLITE_BUSY,
+ sqlite3Error(db, SQLITE_BUSY,
"unable to delete/modify collation sequence due to active statements");
return SQLITE_BUSY;
}
@@ -103311,7 +96866,7 @@ static int createCollation(
** then any copies made by synthCollSeq() need to be invalidated.
** Also, collation destructor - CollSeq.xDel() - function may need
** to be called.
- */
+ */
if( (pColl->enc & ~SQLITE_UTF16_ALIGNED)==enc2 ){
CollSeq *aColl = sqlite3HashFind(&db->aCollSeq, zName, nName);
int j;
@@ -103421,7 +96976,7 @@ SQLITE_API int sqlite3_limit(sqlite3 *db, int limitId, int newLimit){
/*
** This routine does the work of opening a database on behalf of
-** sqlite3_open() and sqlite3_open16(). The database filename "zFilename"
+** sqlite3_open() and sqlite3_open16(). The database filename "zFilename"
** is UTF-8 encoded.
*/
static int openDatabase(
@@ -103466,11 +97021,11 @@ static int openDatabase(
flags &= ~( SQLITE_OPEN_DELETEONCLOSE |
SQLITE_OPEN_EXCLUSIVE |
SQLITE_OPEN_MAIN_DB |
- SQLITE_OPEN_TEMP_DB |
- SQLITE_OPEN_TRANSIENT_DB |
- SQLITE_OPEN_MAIN_JOURNAL |
- SQLITE_OPEN_TEMP_JOURNAL |
- SQLITE_OPEN_SUBJOURNAL |
+ SQLITE_OPEN_TEMP_DB |
+ SQLITE_OPEN_TRANSIENT_DB |
+ SQLITE_OPEN_MAIN_JOURNAL |
+ SQLITE_OPEN_TEMP_JOURNAL |
+ SQLITE_OPEN_SUBJOURNAL |
SQLITE_OPEN_MASTER_JOURNAL |
SQLITE_OPEN_NOMUTEX |
SQLITE_OPEN_FULLMUTEX
@@ -103498,7 +97053,7 @@ static int openDatabase(
db->autoCommit = 1;
db->nextAutovac = -1;
db->nextPagesize = 0;
- db->flags |= SQLITE_ShortColNames | SQLITE_AutoIndex
+ db->flags |= SQLITE_ShortColNames
#if SQLITE_DEFAULT_FILE_FORMAT<4
| SQLITE_LegacyFileFmt
#endif
@@ -103545,7 +97100,7 @@ static int openDatabase(
/* Open the backend database driver */
db->openFlags = flags;
- rc = sqlite3BtreeFactory(db, zFilename, 0, SQLITE_DEFAULT_CACHE_SIZE,
+ rc = sqlite3BtreeFactory(db, zFilename, 0, SQLITE_DEFAULT_CACHE_SIZE,
flags | SQLITE_OPEN_MAIN_DB,
&db->aDb[0].pBt);
if( rc!=SQLITE_OK ){
@@ -103560,7 +97115,7 @@ static int openDatabase(
/* The default safety_level for the main database is 'full'; for the temp
- ** database it is 'NONE'. This matches the pager layer defaults.
+ ** database it is 'NONE'. This matches the pager layer defaults.
*/
db->aDb[0].zName = "main";
db->aDb[0].safety_level = 3;
@@ -103657,8 +97212,6 @@ static int openDatabase(
setupLookaside(db, 0, sqlite3GlobalConfig.szLookaside,
sqlite3GlobalConfig.nLookaside);
- sqlite3_wal_autocheckpoint(db, SQLITE_DEFAULT_WAL_AUTOCHECKPOINT);
-
opendb_out:
if( db ){
assert( db->mutex!=0 || isThreadsafe==0 || sqlite3GlobalConfig.bFullMutex==0 );
@@ -103679,8 +97232,8 @@ opendb_out:
** Open a new database handle.
*/
SQLITE_API int sqlite3_open(
- const char *zFilename,
- sqlite3 **ppDb
+ const char *zFilename,
+ sqlite3 **ppDb
){
return openDatabase(zFilename, ppDb,
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, 0);
@@ -103699,7 +97252,7 @@ SQLITE_API int sqlite3_open_v2(
** Open a new database handle.
*/
SQLITE_API int sqlite3_open16(
- const void *zFilename,
+ const void *zFilename,
sqlite3 **ppDb
){
char const *zFilename8; /* zFilename encoded in UTF-8 instead of UTF-16 */
@@ -103736,9 +97289,9 @@ SQLITE_API int sqlite3_open16(
** Register a new collation sequence with the database handle db.
*/
SQLITE_API int sqlite3_create_collation(
- sqlite3* db,
- const char *zName,
- int enc,
+ sqlite3* db,
+ const char *zName,
+ int enc,
void* pCtx,
int(*xCompare)(void*,int,const void*,int,const void*)
){
@@ -103755,9 +97308,9 @@ SQLITE_API int sqlite3_create_collation(
** Register a new collation sequence with the database handle db.
*/
SQLITE_API int sqlite3_create_collation_v2(
- sqlite3* db,
- const char *zName,
- int enc,
+ sqlite3* db,
+ const char *zName,
+ int enc,
void* pCtx,
int(*xCompare)(void*,int,const void*,int,const void*),
void(*xDel)(void*)
@@ -103776,9 +97329,9 @@ SQLITE_API int sqlite3_create_collation_v2(
** Register a new collation sequence with the database handle db.
*/
SQLITE_API int sqlite3_create_collation16(
- sqlite3* db,
+ sqlite3* db,
const void *zName,
- int enc,
+ int enc,
void* pCtx,
int(*xCompare)(void*,int,const void*,int,const void*)
){
@@ -103786,7 +97339,7 @@ SQLITE_API int sqlite3_create_collation16(
char *zName8;
sqlite3_mutex_enter(db->mutex);
assert( !db->mallocFailed );
- zName8 = sqlite3Utf16to8(db, zName, -1, SQLITE_UTF16NATIVE);
+ zName8 = sqlite3Utf16to8(db, zName, -1);
if( zName8 ){
rc = createCollation(db, zName8, (u8)enc, SQLITE_COLL_USER, pCtx, xCompare, 0);
sqlite3DbFree(db, zName8);
@@ -103802,8 +97355,8 @@ SQLITE_API int sqlite3_create_collation16(
** db. Replace any previously installed collation sequence factory.
*/
SQLITE_API int sqlite3_collation_needed(
- sqlite3 *db,
- void *pCollNeededArg,
+ sqlite3 *db,
+ void *pCollNeededArg,
void(*xCollNeeded)(void*,sqlite3*,int eTextRep,const char*)
){
sqlite3_mutex_enter(db->mutex);
@@ -103820,8 +97373,8 @@ SQLITE_API int sqlite3_collation_needed(
** db. Replace any previously installed collation sequence factory.
*/
SQLITE_API int sqlite3_collation_needed16(
- sqlite3 *db,
- void *pCollNeededArg,
+ sqlite3 *db,
+ void *pCollNeededArg,
void(*xCollNeeded16)(void*,sqlite3*,int eTextRep,const void*)
){
sqlite3_mutex_enter(db->mutex);
@@ -103963,13 +97516,13 @@ SQLITE_API int sqlite3_table_column_metadata(
/* The following block stores the meta information that will be returned
** to the caller in local variables zDataType, zCollSeq, notnull, primarykey
** and autoinc. At this point there are two possibilities:
+ **
+ ** 1. The specified column name was rowid", "oid" or "_rowid_"
+ ** and there is no explicitly declared IPK column.
**
- ** 1. The specified column name was rowid", "oid" or "_rowid_"
- ** and there is no explicitly declared IPK column.
- **
- ** 2. The table is not a view and the column name identified an
+ ** 2. The table is not a view and the column name identified an
** explicitly declared column. Copy meta information from *pCol.
- */
+ */
if( pCol ){
zDataType = pCol->zType;
zCollSeq = pCol->zColl;
@@ -104020,7 +97573,7 @@ SQLITE_API int sqlite3_sleep(int ms){
pVfs = sqlite3_vfs_find(0);
if( pVfs==0 ) return 0;
- /* This function works in milliseconds, but the underlying OsSleep()
+ /* This function works in milliseconds, but the underlying OsSleep()
** API uses microseconds. Hence the 1000's.
*/
rc = (sqlite3OsSleep(pVfs, 1000*ms)/1000);
@@ -104068,7 +97621,7 @@ SQLITE_API int sqlite3_file_control(sqlite3 *db, const char *zDbName, int op, vo
}
}
sqlite3_mutex_leave(db->mutex);
- return rc;
+ return rc;
}
/*
@@ -104127,7 +97680,7 @@ SQLITE_API int sqlite3_test_control(int op, ...){
/*
** sqlite3_test_control(BENIGN_MALLOC_HOOKS, xBegin, xEnd)
**
- ** Register hooks to call to indicate which malloc() failures
+ ** Register hooks to call to indicate which malloc() failures
** are benign.
*/
case SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS: {
@@ -104184,7 +97737,7 @@ SQLITE_API int sqlite3_test_control(int op, ...){
** This action provides a run-time test to see how the ALWAYS and
** NEVER macros were defined at compile-time.
**
- ** The return value is ALWAYS(X).
+ ** The return value is ALWAYS(X).
**
** The recommended test is X==2. If the return value is 2, that means
** ALWAYS() and NEVER() are both no-op pass-through macros, which is the
@@ -104227,7 +97780,7 @@ SQLITE_API int sqlite3_test_control(int op, ...){
/* sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS, sqlite3 *db, int N)
**
- ** Enable or disable various optimizations for testing purposes. The
+ ** Enable or disable various optimizations for testing purposes. The
** argument N is a bitmask of optimizations to be disabled. For normal
** operation N should be 0. The idea is that a test program (like the
** SQL Logic Test or SLT test module) can run the same SQL multiple times
@@ -104246,7 +97799,7 @@ SQLITE_API int sqlite3_test_control(int op, ...){
**
** If zWord is a keyword recognized by the parser, then return the
** number of keywords. Or if zWord is not a keyword, return 0.
- **
+ **
** This test feature is only available in the amalgamation since
** the SQLITE_N_KEYWORD macro is not defined in this file if SQLite
** is built using separate source files.
@@ -104257,7 +97810,7 @@ SQLITE_API int sqlite3_test_control(int op, ...){
rc = (sqlite3KeywordCode((u8*)zWord, n)!=TK_ID) ? SQLITE_N_KEYWORD : 0;
break;
}
-#endif
+#endif
}
va_end(ap);
@@ -104308,13 +97861,13 @@ static sqlite3 *SQLITE_WSD sqlite3BlockedList = 0;
#ifndef NDEBUG
/*
-** This function is a complex assert() that verifies the following
+** This function is a complex assert() that verifies the following
** properties of the blocked connections list:
**
-** 1) Each entry in the list has a non-NULL value for either
+** 1) Each entry in the list has a non-NULL value for either
** pUnlockConnection or pBlockingConnection, or both.
**
-** 2) All entries in the list that share a common value for
+** 2) All entries in the list that share a common value for
** xUnlockNotify are grouped together.
**
** 3) If the argument db is not NULL, then none of the entries in the
@@ -104366,8 +97919,8 @@ static void addToBlockedList(sqlite3 *db){
sqlite3 **pp;
assertMutexHeld();
for(
- pp=&sqlite3BlockedList;
- *pp && (*pp)->xUnlockNotify!=db->xUnlockNotify;
+ pp=&sqlite3BlockedList;
+ *pp && (*pp)->xUnlockNotify!=db->xUnlockNotify;
pp=&(*pp)->pNextBlocked
);
db->pNextBlocked = *pp;
@@ -104424,14 +97977,13 @@ SQLITE_API int sqlite3_unlock_notify(
if( xNotify==0 ){
removeFromBlockedList(db);
- db->pBlockingConnection = 0;
db->pUnlockConnection = 0;
db->xUnlockNotify = 0;
db->pUnlockArg = 0;
}else if( 0==db->pBlockingConnection ){
- /* The blocking transaction has been concluded. Or there never was a
+ /* The blocking transaction has been concluded. Or there never was a
** blocking transaction. In either case, invoke the notify callback
- ** immediately.
+ ** immediately.
*/
xNotify(&pArg, 1);
}else{
@@ -104457,7 +98009,7 @@ SQLITE_API int sqlite3_unlock_notify(
}
/*
-** This function is called while stepping or preparing a statement
+** This function is called while stepping or preparing a statement
** associated with connection db. The operation will return SQLITE_LOCKED
** to the user because it requires a lock that will not be available
** until connection pBlocker concludes its current transaction.
@@ -104473,7 +98025,7 @@ SQLITE_PRIVATE void sqlite3ConnectionBlocked(sqlite3 *db, sqlite3 *pBlocker){
/*
** This function is called when
-** the transaction opened by database db has just finished. Locks held
+** the transaction opened by database db has just finished. Locks held
** by database connection db have been released.
**
** This function loops through each entry in the blocked connections
@@ -104533,7 +98085,7 @@ SQLITE_PRIVATE void sqlite3ConnectionUnlocked(sqlite3 *db){
}else{
/* This occurs when the array of context pointers that need to
** be passed to the unlock-notify callback is larger than the
- ** aStatic[] array allocated on the stack and the attempt to
+ ** aStatic[] array allocated on the stack and the attempt to
** allocate a larger array from the heap has failed.
**
** This is a difficult situation to handle. Returning an error
@@ -104541,17 +98093,17 @@ SQLITE_PRIVATE void sqlite3ConnectionUnlocked(sqlite3 *db){
** is returned the transaction on connection db will still be
** closed and the unlock-notify callbacks on blocked connections
** will go unissued. This might cause the application to wait
- ** indefinitely for an unlock-notify callback that will never
+ ** indefinitely for an unlock-notify callback that will never
** arrive.
**
** Instead, invoke the unlock-notify callback with the context
** array already accumulated. We can then clear the array and
- ** begin accumulating any further context pointers without
+ ** begin accumulating any further context pointers without
** requiring any dynamic allocation. This is sub-optimal because
** it means that instead of one callback with a large array of
** context pointers the application will receive two or more
** callbacks with smaller arrays of context pointers, which will
- ** reduce the applications ability to prioritize multiple
+ ** reduce the applications ability to prioritize multiple
** connections. But it is the best that can be done under the
** circumstances.
*/
@@ -104586,7 +98138,7 @@ SQLITE_PRIVATE void sqlite3ConnectionUnlocked(sqlite3 *db){
}
/*
-** This is called when the database connection passed as an argument is
+** This is called when the database connection passed as an argument is
** being closed. The connection is removed from the blocked list.
*/
SQLITE_PRIVATE void sqlite3ConnectionClosed(sqlite3 *db){
@@ -104625,6 +98177,9 @@ SQLITE_PRIVATE void sqlite3ConnectionClosed(sqlite3 *db){
** SQLite (in which case SQLITE_ENABLE_FTS3 is defined).
*/
+/* TODO(shess) Consider exporting this comment to an HTML file or the
+** wiki.
+*/
/* The full-text index is stored in a series of b+tree (-like)
** structures called segments which map terms to doclists. The
** structures are like b+trees in layout, but are constructed from the
@@ -104647,40 +98202,30 @@ SQLITE_PRIVATE void sqlite3ConnectionClosed(sqlite3 *db){
** 21 bits - BBA
** and so on.
**
-** This is similar in concept to how sqlite encodes "varints" but
-** the encoding is not the same. SQLite varints are big-endian
-** are are limited to 9 bytes in length whereas FTS3 varints are
-** little-endian and can be up to 10 bytes in length (in theory).
-**
-** Example encodings:
-**
-** 1: 0x01
-** 127: 0x7f
-** 128: 0x81 0x00
+** This is identical to how sqlite encodes varints (see util.c).
**
**
**** Document lists ****
** A doclist (document list) holds a docid-sorted list of hits for a
-** given term. Doclists hold docids and associated token positions.
-** A docid is the unique integer identifier for a single document.
-** A position is the index of a word within the document. The first
-** word of the document has a position of 0.
+** given term. Doclists hold docids, and can optionally associate
+** token positions and offsets with docids.
**
-** FTS3 used to optionally store character offsets using a compile-time
-** option. But that functionality is no longer supported.
-**
-** A doclist is stored like this:
+** A DL_POSITIONS_OFFSETS doclist is stored like this:
**
** array {
** varint docid;
** array { (position list for column 0)
-** varint position; (2 more than the delta from previous position)
+** varint position; (delta from previous position plus POS_BASE)
+** varint startOffset; (delta from previous startOffset)
+** varint endOffset; (delta from startOffset)
** }
** array {
** varint POS_COLUMN; (marks start of position list for new column)
** varint column; (index of new column)
** array {
-** varint position; (2 more than the delta from previous position)
+** varint position; (delta from previous position plus POS_BASE)
+** varint startOffset;(delta from previous startOffset)
+** varint endOffset; (delta from startOffset)
** }
** }
** varint POS_END; (marks end of positions for this document.
@@ -104688,32 +98233,19 @@ SQLITE_PRIVATE void sqlite3ConnectionClosed(sqlite3 *db){
**
** Here, array { X } means zero or more occurrences of X, adjacent in
** memory. A "position" is an index of a token in the token stream
-** generated by the tokenizer. Note that POS_END and POS_COLUMN occur
-** in the same logical place as the position element, and act as sentinals
-** ending a position list array. POS_END is 0. POS_COLUMN is 1.
-** The positions numbers are not stored literally but rather as two more
-** than the difference from the prior position, or the just the position plus
-** 2 for the first position. Example:
-**
-** label: A B C D E F G H I J K
-** value: 123 5 9 1 1 14 35 0 234 72 0
-**
-** The 123 value is the first docid. For column zero in this document
-** there are two matches at positions 3 and 10 (5-2 and 9-2+3). The 1
-** at D signals the start of a new column; the 1 at E indicates that the
-** new column is column number 1. There are two positions at 12 and 45
-** (14-2 and 35-2+12). The 0 at H indicate the end-of-document. The
-** 234 at I is the next docid. It has one position 72 (72-2) and then
-** terminates with the 0 at K.
-**
-** A "position-list" is the list of positions for multiple columns for
-** a single docid. A "column-list" is the set of positions for a single
-** column. Hence, a position-list consists of one or more column-lists,
-** a document record consists of a docid followed by a position-list and
-** a doclist consists of one or more document records.
-**
-** A bare doclist omits the position information, becoming an
-** array of varint-encoded docids.
+** generated by the tokenizer, while an "offset" is a byte offset,
+** both based at 0. Note that POS_END and POS_COLUMN occur in the
+** same logical place as the position element, and act as sentinals
+** ending a position list array.
+**
+** A DL_POSITIONS doclist omits the startOffset and endOffset
+** information. A DL_DOCIDS doclist omits both the position and
+** offset information, becoming an array of varint-encoded docids.
+**
+** On-disk data is stored as type DL_DEFAULT, so we don't serialize
+** the type. Due to how deletion is implemented in the segmentation
+** system, on-disk doclists MUST store at least positions.
+**
**
**** Segment leaf nodes ****
** Segment leaf nodes store terms and doclists, ordered by term. Leaf
@@ -104919,7 +98451,7 @@ SQLITE_PRIVATE void sqlite3ConnectionClosed(sqlite3 *db){
#ifndef _FTSINT_H
#define _FTSINT_H
-#if !defined(NDEBUG) && !defined(SQLITE_DEBUG)
+#if !defined(NDEBUG) && !defined(SQLITE_DEBUG)
# define NDEBUG 1
#endif
@@ -104961,7 +98493,7 @@ SQLITE_PRIVATE void sqlite3ConnectionClosed(sqlite3 *db){
** When an fts3 table is created, it passes any arguments passed to
** the tokenizer clause of the CREATE VIRTUAL TABLE statement to the
** sqlite3_tokenizer_module.xCreate() function of the requested tokenizer
-** implementation. The xCreate() function in turn returns an
+** implementation. The xCreate() function in turn returns an
** sqlite3_tokenizer structure representing the specific tokenizer to
** be used for the fts3 table (customized by the tokenizer clause arguments).
**
@@ -104993,7 +98525,7 @@ struct sqlite3_tokenizer_module {
** then argc is set to 2, and the argv[] array contains pointers
** to the strings "arg1" and "arg2".
**
- ** This method should return either SQLITE_OK (0), or an SQLite error
+ ** This method should return either SQLITE_OK (0), or an SQLite error
** code. If SQLITE_OK is returned, then *ppTokenizer should be set
** to point at the newly created tokenizer structure. The generic
** sqlite3_tokenizer.pModule variable should not be initialised by
@@ -105014,7 +98546,7 @@ struct sqlite3_tokenizer_module {
/*
** Create a tokenizer cursor to tokenize an input buffer. The caller
** is responsible for ensuring that the input buffer remains valid
- ** until the cursor is closed (using the xClose() method).
+ ** until the cursor is closed (using the xClose() method).
*/
int (*xOpen)(
sqlite3_tokenizer *pTokenizer, /* Tokenizer object */
@@ -105023,7 +98555,7 @@ struct sqlite3_tokenizer_module {
);
/*
- ** Destroy an existing tokenizer cursor. The fts3 module calls this
+ ** Destroy an existing tokenizer cursor. The fts3 module calls this
** method exactly once for each successful call to xOpen().
*/
int (*xClose)(sqlite3_tokenizer_cursor *pCursor);
@@ -105034,7 +98566,7 @@ struct sqlite3_tokenizer_module {
** "OUT" variables identified below, or SQLITE_DONE to indicate that
** the end of the buffer has been reached, or an SQLite error code.
**
- ** *ppToken should be set to point at a buffer containing the
+ ** *ppToken should be set to point at a buffer containing the
** normalized version of the token (i.e. after any case-folding and/or
** stemming has been performed). *pnBytes should be set to the length
** of this buffer in bytes. The input text that generated the token is
@@ -105046,7 +98578,7 @@ struct sqlite3_tokenizer_module {
**
** The buffer *ppToken is set to point at is managed by the tokenizer
** implementation. It is only required to be valid until the next call
- ** to xNext() or xClose().
+ ** to xNext() or xClose().
*/
/* TODO(shess) current implementation requires pInput to be
** nul-terminated. This should either be fixed, or pInput/nBytes
@@ -105124,7 +98656,7 @@ struct Fts3Hash {
} *ht;
};
-/* Each element in the hash table is an instance of the following
+/* Each element in the hash table is an instance of the following
** structure. All elements are stored on a single doubly-linked list.
**
** Again, this structure is intended to be opaque, but it can't really
@@ -105143,10 +98675,10 @@ struct Fts3HashElem {
** (including the null-terminator, if any). Case
** is respected in comparisons.
**
-** FTS3_HASH_BINARY pKey points to binary data nKey bytes long.
+** FTS3_HASH_BINARY pKey points to binary data nKey bytes long.
** memcmp() is used to compare keys.
**
-** A copy of the key is made if the copyKey parameter to fts3HashInit is 1.
+** A copy of the key is made if the copyKey parameter to fts3HashInit is 1.
*/
#define FTS3_HASH_STRING 1
#define FTS3_HASH_BINARY 2
@@ -105205,11 +98737,11 @@ SQLITE_PRIVATE Fts3HashElem *sqlite3Fts3HashFindElem(const Fts3Hash *, const voi
#define FTS3_MERGE_COUNT 16
/*
-** This is the maximum amount of data (in bytes) to store in the
+** This is the maximum amount of data (in bytes) to store in the
** Fts3Table.pendingTerms hash table. Normally, the hash table is
** populated as documents are inserted/updated/deleted in a transaction
** and used to create a new segment when the transaction is committed.
-** However if this limit is reached midway through a transaction, a new
+** However if this limit is reached midway through a transaction, a new
** segment is created and the hash table cleared immediately.
*/
#define FTS3_MAX_PENDING_DATA (1*1024*1024)
@@ -105228,22 +98760,8 @@ SQLITE_PRIVATE Fts3HashElem *sqlite3Fts3HashFindElem(const Fts3Hash *, const voi
#define FTS3_VARINT_MAX 10
/*
-** The testcase() macro is only used by the amalgamation. If undefined,
-** make it a no-op.
-*/
-#ifndef testcase
-# define testcase(X)
-#endif
-
-/*
-** Terminator values for position-lists and column-lists.
-*/
-#define POS_COLUMN (1) /* Column-list terminator */
-#define POS_END (0) /* Position-list terminator */
-
-/*
** This section provides definitions to allow the
-** FTS3 extension to be compiled outside of the
+** FTS3 extension to be compiled outside of the
** amalgamation.
*/
#ifndef SQLITE_AMALGAMATION
@@ -105289,14 +98807,14 @@ struct Fts3Table {
char **azColumn; /* column names. malloced */
sqlite3_tokenizer *pTokenizer; /* tokenizer for inserts and queries */
- /* Precompiled statements used by the implementation. Each of these
- ** statements is run and reset within a single virtual table API call.
+ /* Precompiled statements used by the implementation. Each of these
+ ** statements is run and reset within a single virtual table API call.
*/
- sqlite3_stmt *aStmt[25];
+ sqlite3_stmt *aStmt[18];
/* Pointer to string containing the SQL:
**
- ** "SELECT block FROM %_segments WHERE blockid BETWEEN ? AND ?
+ ** "SELECT block FROM %_segments WHERE blockid BETWEEN ? AND ?
** ORDER BY blockid"
*/
char *zSelectLeaves;
@@ -105306,13 +98824,11 @@ struct Fts3Table {
sqlite3_stmt **aLeavesStmt; /* Array of prepared zSelectLeaves stmts */
int nNodeSize; /* Soft limit for node size */
- u8 bHasContent; /* True if %_content table exists */
- u8 bHasDocsize; /* True if %_docsize table exists */
/* The following hash table is used to buffer pending index updates during
- ** transactions. Variable nPendingData estimates the memory size of the
- ** pending data, including hash table overhead, but not malloc overhead.
- ** When nPendingData exceeds nMaxPendingData, the buffer is flushed
+ ** transactions. Variable nPendingData estimates the memory size of the
+ ** pending data, including hash table overhead, but not malloc overhead.
+ ** When nPendingData exceeds nMaxPendingData, the buffer is flushed
** automatically. Variable iPrevDocid is the docid of the most recently
** inserted record.
*/
@@ -105338,8 +98854,8 @@ struct Fts3Cursor {
char *pNextId; /* Pointer into the body of aDoclist */
char *aDoclist; /* List of docids for full-text queries */
int nDoclist; /* Size of buffer at aDoclist */
- int isMatchinfoNeeded; /* True when aMatchinfo[] needs filling in */
- u32 *aMatchinfo; /* Information about most recent match */
+ int isMatchinfoOk; /* True when aMatchinfo[] matches iPrevId */
+ u32 *aMatchinfo;
};
/*
@@ -105350,10 +98866,10 @@ struct Fts3Cursor {
**
** CREATE VIRTUAL TABLE ex1 USING fts3(a,b,c,d);
** SELECT docid FROM ex1 WHERE b MATCH 'one two three';
-**
+**
** Because the LHS of the MATCH operator is 2nd column "b",
** Fts3Cursor.eSearch will be set to FTS3_FULLTEXT_SEARCH+1. (+0 for a,
-** +1 for b, +2 for c, +3 for d.) If the LHS of MATCH were "ex1"
+** +1 for b, +2 for c, +3 for d.) If the LHS of MATCH were "ex1"
** indicating that all columns should be searched,
** then eSearch would be set to FTS3_FULLTEXT_SEARCH+4.
*/
@@ -105382,7 +98898,7 @@ struct Fts3Phrase {
** A tree of these objects forms the RHS of a MATCH operator.
**
** If Fts3Expr.eType is either FTSQUERY_NEAR or FTSQUERY_PHRASE and isLoaded
-** is true, then aDoclist points to a malloced buffer, size nDoclist bytes,
+** is true, then aDoclist points to a malloced buffer, size nDoclist bytes,
** containing the results of the NEAR or phrase query in FTS3 doclist
** format. As usual, the initial "Length" field found in doclists stored
** on disk is omitted from this buffer.
@@ -105409,7 +98925,7 @@ struct Fts3Expr {
/*
** Candidate values for Fts3Query.eType. Note that the order of the first
-** four values is in order of precedence when parsing expressions. For
+** four values is in order of precedence when parsing expressions. For
** example, the following:
**
** "a OR b AND c NOT d NEAR e"
@@ -105427,7 +98943,7 @@ struct Fts3Expr {
/* fts3_init.c */
SQLITE_PRIVATE int sqlite3Fts3DeleteVtab(int, sqlite3_vtab *);
-SQLITE_PRIVATE int sqlite3Fts3InitVtab(int, sqlite3*, void*, int, const char*const*,
+SQLITE_PRIVATE int sqlite3Fts3InitVtab(int, sqlite3*, void*, int, const char*const*,
sqlite3_vtab **, char **);
/* fts3_write.c */
@@ -105445,8 +98961,6 @@ SQLITE_PRIVATE int sqlite3Fts3SegReaderIterate(
);
SQLITE_PRIVATE int sqlite3Fts3ReadBlock(Fts3Table*, sqlite3_int64, char const**, int*);
SQLITE_PRIVATE int sqlite3Fts3AllSegdirs(Fts3Table*, sqlite3_stmt **);
-SQLITE_PRIVATE int sqlite3Fts3MatchinfoDocsizeLocal(Fts3Cursor*, u32*);
-SQLITE_PRIVATE int sqlite3Fts3MatchinfoDocsizeGlobal(Fts3Cursor*, u32*);
/* Flags allowed as part of the 4th argument to SegmentReaderIterate() */
#define FTS3_SEGMENT_REQUIRE_POS 0x00000001
@@ -105471,24 +98985,26 @@ SQLITE_PRIVATE void sqlite3Fts3Dequote(char *);
SQLITE_PRIVATE char *sqlite3Fts3FindPositions(Fts3Expr *, sqlite3_int64, int);
SQLITE_PRIVATE int sqlite3Fts3ExprLoadDoclist(Fts3Table *, Fts3Expr *);
-SQLITE_PRIVATE int sqlite3Fts3ExprNearTrim(Fts3Expr *, Fts3Expr *, int);
/* fts3_tokenizer.c */
SQLITE_PRIVATE const char *sqlite3Fts3NextToken(const char *, int *);
SQLITE_PRIVATE int sqlite3Fts3InitHashTable(sqlite3 *, Fts3Hash *, const char *);
-SQLITE_PRIVATE int sqlite3Fts3InitTokenizer(Fts3Hash *pHash,
+SQLITE_PRIVATE int sqlite3Fts3InitTokenizer(Fts3Hash *pHash,
const char *, sqlite3_tokenizer **, const char **, char **
);
/* fts3_snippet.c */
SQLITE_PRIVATE void sqlite3Fts3Offsets(sqlite3_context*, Fts3Cursor*);
-SQLITE_PRIVATE void sqlite3Fts3Snippet(sqlite3_context *, Fts3Cursor *, const char *,
+SQLITE_PRIVATE void sqlite3Fts3Snippet(sqlite3_context*, Fts3Cursor*,
+ const char *, const char *, const char *
+);
+SQLITE_PRIVATE void sqlite3Fts3Snippet2(sqlite3_context *, Fts3Cursor *, const char *,
const char *, const char *, int, int
);
SQLITE_PRIVATE void sqlite3Fts3Matchinfo(sqlite3_context *, Fts3Cursor *);
/* fts3_expr.c */
-SQLITE_PRIVATE int sqlite3Fts3ExprParse(sqlite3_tokenizer *,
+SQLITE_PRIVATE int sqlite3Fts3ExprParse(sqlite3_tokenizer *,
char **, int, int, const char *, int, Fts3Expr **
);
SQLITE_PRIVATE void sqlite3Fts3ExprFree(Fts3Expr *);
@@ -105502,11 +99018,11 @@ SQLITE_PRIVATE int sqlite3Fts3ExprInitTestInterface(sqlite3 *db);
/************** Continuing where we left off in fts3.c ***********************/
-#ifndef SQLITE_CORE
+#ifndef SQLITE_CORE
SQLITE_EXTENSION_INIT1
#endif
-/*
+/*
** Write a 64-bit variable-length integer to memory starting at p[0].
** The length of data written will be between 1 and FTS3_VARINT_MAX bytes.
** The number of bytes written is returned.
@@ -105523,7 +99039,7 @@ SQLITE_PRIVATE int sqlite3Fts3PutVarint(char *p, sqlite_int64 v){
return (int) (q - (unsigned char *)p);
}
-/*
+/*
** Read a 64-bit variable-length integer from memory starting at p[0].
** Return the number of bytes read, or 0 on error.
** The value is stored in *v.
@@ -105552,7 +99068,8 @@ SQLITE_PRIVATE int sqlite3Fts3GetVarint32(const char *p, int *pi){
}
/*
-** Return the number of bytes required to encode v as a varint
+** Return the number of bytes required to store the value passed as the
+** first argument in varint form.
*/
SQLITE_PRIVATE int sqlite3Fts3VarintLen(sqlite3_uint64 v){
int i = 0;
@@ -105586,7 +99103,7 @@ SQLITE_PRIVATE void sqlite3Fts3Dequote(char *z){
int iOut = 0; /* Index of next byte to write to output */
/* If the first byte was a '[', then the close-quote character is a ']' */
- if( quote=='[' ) quote = ']';
+ if( quote=='[' ) quote = ']';
while( ALWAYS(z[iIn]) ){
if( z[iIn]==quote ){
@@ -105601,23 +99118,12 @@ SQLITE_PRIVATE void sqlite3Fts3Dequote(char *z){
}
}
-/*
-** Read a single varint from the doclist at *pp and advance *pp to point
-** to the first byte past the end of the varint. Add the value of the varint
-** to *pVal.
-*/
static void fts3GetDeltaVarint(char **pp, sqlite3_int64 *pVal){
sqlite3_int64 iVal;
*pp += sqlite3Fts3GetVarint(*pp, &iVal);
*pVal += iVal;
}
-/*
-** As long as *pp has not reached its end (pEnd), then do the same
-** as fts3GetDeltaVarint(): read a single varint and add it to *pVal.
-** But if we have reached the end of the varint, just set *pp=0 and
-** leave *pVal unchanged.
-*/
static void fts3GetDeltaVarint2(char **pp, char *pEnd, sqlite3_int64 *pVal){
if( *pp>=pEnd ){
*pp = 0;
@@ -105653,46 +99159,29 @@ static int fts3DisconnectMethod(sqlite3_vtab *pVtab){
}
/*
-** Construct one or more SQL statements from the format string given
-** and then evaluate those statements. The success code is writting
-** into *pRc.
-**
-** If *pRc is initially non-zero then this routine is a no-op.
-*/
-static void fts3DbExec(
- int *pRc, /* Success code */
- sqlite3 *db, /* Database in which to run SQL */
- const char *zFormat, /* Format string for SQL */
- ... /* Arguments to the format string */
-){
- va_list ap;
- char *zSql;
- if( *pRc ) return;
- va_start(ap, zFormat);
- zSql = sqlite3_vmprintf(zFormat, ap);
- va_end(ap);
- if( zSql==0 ){
- *pRc = SQLITE_NOMEM;
- }else{
- *pRc = sqlite3_exec(db, zSql, 0, 0, 0);
- sqlite3_free(zSql);
- }
-}
-
-/*
** The xDestroy() virtual table method.
*/
static int fts3DestroyMethod(sqlite3_vtab *pVtab){
- int rc = SQLITE_OK; /* Return code */
+ int rc; /* Return code */
Fts3Table *p = (Fts3Table *)pVtab;
- sqlite3 *db = p->db;
- /* Drop the shadow tables */
- fts3DbExec(&rc, db, "DROP TABLE IF EXISTS %Q.'%q_content'", p->zDb, p->zName);
- fts3DbExec(&rc, db, "DROP TABLE IF EXISTS %Q.'%q_segments'", p->zDb,p->zName);
- fts3DbExec(&rc, db, "DROP TABLE IF EXISTS %Q.'%q_segdir'", p->zDb, p->zName);
- fts3DbExec(&rc, db, "DROP TABLE IF EXISTS %Q.'%q_docsize'", p->zDb, p->zName);
- fts3DbExec(&rc, db, "DROP TABLE IF EXISTS %Q.'%q_stat'", p->zDb, p->zName);
+ /* Create a script to drop the underlying three storage tables. */
+ char *zSql = sqlite3_mprintf(
+ "DROP TABLE IF EXISTS %Q.'%q_content';"
+ "DROP TABLE IF EXISTS %Q.'%q_segments';"
+ "DROP TABLE IF EXISTS %Q.'%q_segdir';",
+ p->zDb, p->zName, p->zDb, p->zName, p->zDb, p->zName
+ );
+
+ /* If malloc has failed, set rc to SQLITE_NOMEM. Otherwise, try to
+ ** execute the SQL script created above.
+ */
+ if( zSql ){
+ rc = sqlite3_exec(p->db, zSql, 0, 0, 0);
+ sqlite3_free(zSql);
+ }else{
+ rc = SQLITE_NOMEM;
+ }
/* If everything has worked, invoke fts3DisconnectMethod() to free the
** memory associated with the Fts3Table structure and return SQLITE_OK.
@@ -105739,39 +99228,24 @@ static int fts3DeclareVtab(Fts3Table *p){
** Create the backing store tables (%_content, %_segments and %_segdir)
** required by the FTS3 table passed as the only argument. This is done
** as part of the vtab xCreate() method.
-**
-** If the p->bHasDocsize boolean is true (indicating that this is an
-** FTS4 table, not an FTS3 table) then also create the %_docsize and
-** %_stat tables required by FTS4.
*/
static int fts3CreateTables(Fts3Table *p){
- int rc = SQLITE_OK; /* Return code */
+ int rc; /* Return code */
int i; /* Iterator variable */
char *zContentCols; /* Columns of %_content table */
- sqlite3 *db = p->db; /* The database connection */
+ char *zSql; /* SQL script to create required tables */
/* Create a list of user columns for the content table */
- if( p->bHasContent ){
- zContentCols = sqlite3_mprintf("docid INTEGER PRIMARY KEY");
- for(i=0; zContentCols && i<p->nColumn; i++){
- char *z = p->azColumn[i];
- zContentCols = sqlite3_mprintf("%z, 'c%d%q'", zContentCols, i, z);
- }
- if( zContentCols==0 ) rc = SQLITE_NOMEM;
-
- /* Create the content table */
- fts3DbExec(&rc, db,
- "CREATE TABLE %Q.'%q_content'(%s)",
- p->zDb, p->zName, zContentCols
- );
- sqlite3_free(zContentCols);
+ zContentCols = sqlite3_mprintf("docid INTEGER PRIMARY KEY");
+ for(i=0; zContentCols && i<p->nColumn; i++){
+ char *z = p->azColumn[i];
+ zContentCols = sqlite3_mprintf("%z, 'c%d%q'", zContentCols, i, z);
}
- /* Create other tables */
- fts3DbExec(&rc, db,
- "CREATE TABLE %Q.'%q_segments'(blockid INTEGER PRIMARY KEY, block BLOB);",
- p->zDb, p->zName
- );
- fts3DbExec(&rc, db,
+
+ /* Create the whole SQL script */
+ zSql = sqlite3_mprintf(
+ "CREATE TABLE %Q.'%q_content'(%s);"
+ "CREATE TABLE %Q.'%q_segments'(blockid INTEGER PRIMARY KEY, block BLOB);"
"CREATE TABLE %Q.'%q_segdir'("
"level INTEGER,"
"idx INTEGER,"
@@ -105781,52 +99255,21 @@ static int fts3CreateTables(Fts3Table *p){
"root BLOB,"
"PRIMARY KEY(level, idx)"
");",
- p->zDb, p->zName
+ p->zDb, p->zName, zContentCols, p->zDb, p->zName, p->zDb, p->zName
);
- if( p->bHasDocsize ){
- fts3DbExec(&rc, db,
- "CREATE TABLE %Q.'%q_docsize'(docid INTEGER PRIMARY KEY, size BLOB);",
- p->zDb, p->zName
- );
- fts3DbExec(&rc, db,
- "CREATE TABLE %Q.'%q_stat'(id INTEGER PRIMARY KEY, value BLOB);",
- p->zDb, p->zName
- );
- }
- return rc;
-}
-/*
-** An sqlite3_exec() callback for fts3TableExists.
-*/
-static int fts3TableExistsCallback(void *pArg, int n, char **pp1, char **pp2){
- *(int*)pArg = 1;
- return 1;
-}
+ /* Unless a malloc() failure has occurred, execute the SQL script to
+ ** create the tables used to store data for this FTS3 virtual table.
+ */
+ if( zContentCols==0 || zSql==0 ){
+ rc = SQLITE_NOMEM;
+ }else{
+ rc = sqlite3_exec(p->db, zSql, 0, 0, 0);
+ }
-/*
-** Determine if a table currently exists in the database.
-*/
-static void fts3TableExists(
- int *pRc, /* Success code */
- sqlite3 *db, /* The database connection to test */
- const char *zDb, /* ATTACHed database within the connection */
- const char *zName, /* Name of the FTS3 table */
- const char *zSuffix, /* Shadow table extension */
- u8 *pResult /* Write results here */
-){
- int rc = SQLITE_OK;
- int res = 0;
- char *zSql;
- if( *pRc ) return;
- zSql = sqlite3_mprintf(
- "SELECT 1 FROM %Q.sqlite_master WHERE name='%q%s'",
- zDb, zName, zSuffix
- );
- rc = sqlite3_exec(db, zSql, fts3TableExistsCallback, &res, 0);
sqlite3_free(zSql);
- *pResult = res & 0xff;
- if( rc!=SQLITE_ABORT ) *pRc = rc;
+ sqlite3_free(zContentCols);
+ return rc;
}
/*
@@ -105835,7 +99278,7 @@ static void fts3TableExists(
**
** The argv[] array contains the following:
**
-** argv[0] -> module name ("fts3" or "fts4")
+** argv[0] -> module name
** argv[1] -> database name
** argv[2] -> table name
** argv[...] -> "column name" and other module argument fields.
@@ -105854,12 +99297,12 @@ static int fts3InitVtab(
int rc; /* Return code */
int i; /* Iterator variable */
int nByte; /* Size of allocation used for *p */
- int iCol; /* Column index */
- int nString = 0; /* Bytes required to hold all column names */
- int nCol = 0; /* Number of columns in the FTS table */
- char *zCsr; /* Space for holding column names */
- int nDb; /* Bytes required to hold database name */
- int nName; /* Bytes required to hold table name */
+ int iCol;
+ int nString = 0;
+ int nCol = 0;
+ char *zCsr;
+ int nDb;
+ int nName;
const char *zTokenizer = 0; /* Name of tokenizer to use */
sqlite3_tokenizer *pTokenizer = 0; /* Tokenizer for this table */
@@ -105925,7 +99368,7 @@ static int fts3InitVtab(
iCol = 0;
for(i=3; i<argc; i++){
if( argv[i]!=zTokenizer ){
- char *z;
+ char *z;
int n;
z = (char *)sqlite3Fts3NextToken(argv[i], &n);
memcpy(zCsr, z, n);
@@ -105941,19 +99384,13 @@ static int fts3InitVtab(
p->azColumn[0] = "content";
}
- /* If this is an xCreate call, create the underlying tables in the
+ /* If this is an xCreate call, create the underlying tables in the
** database. TODO: For xConnect(), it could verify that said tables exist.
*/
if( isCreate ){
- p->bHasContent = 1;
- p->bHasDocsize = argv[0][3]=='4';
rc = fts3CreateTables(p);
- }else{
- rc = SQLITE_OK;
- fts3TableExists(&rc, db, argv[1], argv[2], "_content", &p->bHasContent);
- fts3TableExists(&rc, db, argv[1], argv[2], "_docsize", &p->bHasDocsize);
+ if( rc!=SQLITE_OK ) goto fts3_init_out;
}
- if( rc!=SQLITE_OK ) goto fts3_init_out;
rc = fts3DeclareVtab(p);
if( rc!=SQLITE_OK ) goto fts3_init_out;
@@ -105997,11 +99434,11 @@ static int fts3CreateMethod(
return fts3InitVtab(1, db, pAux, argc, argv, ppVtab, pzErr);
}
-/*
+/*
** Implementation of the xBestIndex method for FTS3 tables. There
** are three possible strategies, in order of preference:
**
-** 1. Direct lookup by rowid or docid.
+** 1. Direct lookup by rowid or docid.
** 2. Full-text search using a MATCH operator on a non-docid column.
** 3. Linear scan of %_content table.
*/
@@ -106011,7 +99448,7 @@ static int fts3BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
int iCons = -1; /* Index of constraint to use */
/* By default use a full table scan. This is an expensive option,
- ** so search through the constraints to see if a more efficient
+ ** so search through the constraints to see if a more efficient
** strategy is possible.
*/
pInfo->idxNum = FTS3_FULLSCAN_SEARCH;
@@ -106021,7 +99458,7 @@ static int fts3BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
if( pCons->usable==0 ) continue;
/* A direct lookup on the rowid or docid column. Assign a cost of 1.0. */
- if( pCons->op==SQLITE_INDEX_CONSTRAINT_EQ
+ if( pCons->op==SQLITE_INDEX_CONSTRAINT_EQ
&& (pCons->iColumn<0 || pCons->iColumn==p->nColumn+1 )
){
pInfo->idxNum = FTS3_DOCID_SEARCH;
@@ -106033,12 +99470,12 @@ static int fts3BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
**
** If there is more than one MATCH constraint available, use the first
** one encountered. If there is both a MATCH constraint and a direct
- ** rowid/docid lookup, prefer the MATCH strategy. This is done even
+ ** rowid/docid lookup, prefer the MATCH strategy. This is done even
** though the rowid/docid lookup is faster than a MATCH query, selecting
- ** it would lead to an "unable to use function MATCH in the requested
+ ** it would lead to an "unable to use function MATCH in the requested
** context" error.
*/
- if( pCons->op==SQLITE_INDEX_CONSTRAINT_MATCH
+ if( pCons->op==SQLITE_INDEX_CONSTRAINT_MATCH
&& pCons->iColumn>=0 && pCons->iColumn<=p->nColumn
){
pInfo->idxNum = FTS3_FULLTEXT_SEARCH + pCons->iColumn;
@@ -106051,7 +99488,7 @@ static int fts3BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
if( iCons>=0 ){
pInfo->aConstraintUsage[iCons].argvIndex = 1;
pInfo->aConstraintUsage[iCons].omit = 1;
- }
+ }
return SQLITE_OK;
}
@@ -106064,7 +99501,7 @@ static int fts3OpenMethod(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCsr){
UNUSED_PARAMETER(pVTab);
/* Allocate a buffer large enough for an Fts3Cursor structure. If the
- ** allocation succeeds, zero it and return SQLITE_OK. Otherwise,
+ ** allocation succeeds, zero it and return SQLITE_OK. Otherwise,
** if the allocation fails, return SQLITE_NOMEM.
*/
*ppCsr = pCsr = (sqlite3_vtab_cursor *)sqlite3_malloc(sizeof(Fts3Cursor));
@@ -106075,6 +99512,12 @@ static int fts3OpenMethod(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCsr){
return SQLITE_OK;
}
+/****************************************************************/
+/****************************************************************/
+/****************************************************************/
+/****************************************************************/
+
+
/*
** Close the cursor. For additional information see the documentation
** on the xClose method of the virtual table interface.
@@ -106089,11 +99532,6 @@ static int fulltextClose(sqlite3_vtab_cursor *pCursor){
return SQLITE_OK;
}
-/*
-** Position the pCsr->pStmt statement so that it is on the row
-** of the %_content table that contains the last match. Return
-** SQLITE_OK on success.
-*/
static int fts3CursorSeek(sqlite3_context *pContext, Fts3Cursor *pCsr){
if( pCsr->isRequireSeek ){
pCsr->isRequireSeek = 0;
@@ -106120,17 +99558,6 @@ static int fts3CursorSeek(sqlite3_context *pContext, Fts3Cursor *pCsr){
}
}
-/*
-** Advance the cursor to the next row in the %_content table that
-** matches the search criteria. For a MATCH search, this will be
-** the next row that matches. For a full-table scan, this will be
-** simply the next row in the %_content table. For a docid lookup,
-** this routine simply sets the EOF flag.
-**
-** Return SQLITE_OK if nothing goes wrong. SQLITE_OK is returned
-** even if we reach end-of-file. The fts3EofMethod() will be called
-** subsequently to determine whether or not an EOF was hit.
-*/
static int fts3NextMethod(sqlite3_vtab_cursor *pCursor){
int rc = SQLITE_OK; /* Return code */
Fts3Cursor *pCsr = (Fts3Cursor *)pCursor;
@@ -106146,7 +99573,7 @@ static int fts3NextMethod(sqlite3_vtab_cursor *pCursor){
sqlite3_reset(pCsr->pStmt);
fts3GetDeltaVarint(&pCsr->pNextId, &pCsr->iPrevId);
pCsr->isRequireSeek = 1;
- pCsr->isMatchinfoNeeded = 1;
+ pCsr->isMatchinfoOk = 1;
}
return rc;
}
@@ -106156,8 +99583,8 @@ static int fts3NextMethod(sqlite3_vtab_cursor *pCursor){
** The buffer pointed to by argument zNode (size nNode bytes) contains the
** root node of a b-tree segment. The segment is guaranteed to be at least
** one level high (i.e. the root node is not also a leaf). If successful,
-** this function locates the leaf node of the segment that may contain the
-** term specified by arguments zTerm and nTerm and writes its block number
+** this function locates the leaf node of the segment that may contain the
+** term specified by arguments zTerm and nTerm and writes its block number
** to *piLeaf.
**
** It is possible that the returned leaf node does not contain the specified
@@ -106167,7 +99594,7 @@ static int fts3NextMethod(sqlite3_vtab_cursor *pCursor){
** to be sure.
**
** If an error occurs, an error code other than SQLITE_OK is returned.
-*/
+*/
static int fts3SelectLeaf(
Fts3Table *p, /* Virtual table handle */
const char *zTerm, /* Term to select leaves for */
@@ -106190,13 +99617,13 @@ static int fts3SelectLeaf(
zCsr += sqlite3Fts3GetVarint32(zCsr, &iHeight);
zCsr += sqlite3Fts3GetVarint(zCsr, &iChild);
-
+
while( zCsr<zEnd ){
int cmp; /* memcmp() result */
int nSuffix; /* Size of term suffix */
int nPrefix = 0; /* Size of term prefix */
int nBuffer; /* Total term size */
-
+
/* Load the next term on the node into zBuffer */
if( !isFirstTerm ){
zCsr += sqlite3Fts3GetVarint32(zCsr, &nPrefix);
@@ -106216,11 +99643,11 @@ static int fts3SelectLeaf(
memcpy(&zBuffer[nPrefix], zCsr, nSuffix);
nBuffer = nPrefix + nSuffix;
zCsr += nSuffix;
-
+
/* Compare the term we are searching for with the term just loaded from
** the interior node. If the specified term is greater than or equal
- ** to the term from the interior node, then all terms on the sub-tree
- ** headed by node iChild are smaller than zTerm. No need to search
+ ** to the term from the interior node, then all terms on the sub-tree
+ ** headed by node iChild are smaller than zTerm. No need to search
** iChild.
**
** If the interior node term is larger than the specified term, then
@@ -106249,7 +99676,7 @@ static int fts3SelectLeaf(
}
/*
-** This function is used to create delta-encoded serialized lists of FTS3
+** This function is used to create delta-encoded serialized lists of FTS3
** varints. Each call to this function appends a single varint to a list.
*/
static void fts3PutDeltaVarint(
@@ -106263,38 +99690,25 @@ static void fts3PutDeltaVarint(
}
/*
-** When this function is called, *ppPoslist is assumed to point to the
-** start of a position-list. After it returns, *ppPoslist points to the
-** first byte after the position-list.
-**
-** A position list is list of positions (delta encoded) and columns for
-** a single document record of a doclist. So, in other words, this
-** routine advances *ppPoslist so that it points to the next docid in
-** the doclist, or to the first byte past the end of the doclist.
-**
-** If pp is not NULL, then the contents of the position list are copied
-** to *pp. *pp is set to point to the first byte past the last byte copied
-** before this function returns.
+** When this function is called, *ppPoslist is assumed to point to the
+** start of a position-list.
*/
static void fts3PoslistCopy(char **pp, char **ppPoslist){
char *pEnd = *ppPoslist;
char c = 0;
- /* The end of a position list is marked by a zero encoded as an FTS3
- ** varint. A single POS_END (0) byte. Except, if the 0 byte is preceded by
+ /* The end of a position list is marked by a zero encoded as an FTS3
+ ** varint. A single 0x00 byte. Except, if the 0x00 byte is preceded by
** a byte with the 0x80 bit set, then it is not a varint 0, but the tail
** of some other, multi-byte, value.
**
- ** The following while-loop moves pEnd to point to the first byte that is not
+ ** The following block moves pEnd to point to the first byte that is not
** immediately preceded by a byte with the 0x80 bit set. Then increments
** pEnd once more so that it points to the byte immediately following the
** last byte in the position-list.
*/
- while( *pEnd | c ){
- c = *pEnd++ & 0x80;
- testcase( c!=0 && (*pEnd)==0 );
- }
- pEnd++; /* Advance past the POS_END terminator byte */
+ while( *pEnd | c ) c = *pEnd++ & 0x80;
+ pEnd++;
if( pp ){
int n = (int)(pEnd - *ppPoslist);
@@ -106306,34 +99720,12 @@ static void fts3PoslistCopy(char **pp, char **ppPoslist){
*ppPoslist = pEnd;
}
-/*
-** When this function is called, *ppPoslist is assumed to point to the
-** start of a column-list. After it returns, *ppPoslist points to the
-** to the terminator (POS_COLUMN or POS_END) byte of the column-list.
-**
-** A column-list is list of delta-encoded positions for a single column
-** within a single document within a doclist.
-**
-** The column-list is terminated either by a POS_COLUMN varint (1) or
-** a POS_END varint (0). This routine leaves *ppPoslist pointing to
-** the POS_COLUMN or POS_END that terminates the column-list.
-**
-** If pp is not NULL, then the contents of the column-list are copied
-** to *pp. *pp is set to point to the first byte past the last byte copied
-** before this function returns. The POS_COLUMN or POS_END terminator
-** is not copied into *pp.
-*/
static void fts3ColumnlistCopy(char **pp, char **ppPoslist){
char *pEnd = *ppPoslist;
char c = 0;
- /* A column-list is terminated by either a 0x01 or 0x00 byte that is
- ** not part of a multi-byte varint.
- */
- while( 0xFE & (*pEnd | c) ){
- c = *pEnd++ & 0x80;
- testcase( c!=0 && ((*pEnd)&0xfe)==0 );
- }
+ /* A column-list is terminated by either a 0x01 or 0x00. */
+ while( 0xFE & (*pEnd | c) ) c = *pEnd++ & 0x80;
if( pp ){
int n = (int)(pEnd - *ppPoslist);
char *p = *pp;
@@ -106345,47 +99737,39 @@ static void fts3ColumnlistCopy(char **pp, char **ppPoslist){
}
/*
-** Value used to signify the end of an position-list. This is safe because
+** Value used to signify the end of an offset-list. This is safe because
** it is not possible to have a document with 2^31 terms.
*/
-#define POSITION_LIST_END 0x7fffffff
+#define OFFSET_LIST_END 0x7fffffff
/*
-** This function is used to help parse position-lists. When this function is
-** called, *pp may point to the start of the next varint in the position-list
-** being parsed, or it may point to 1 byte past the end of the position-list
-** (in which case **pp will be a terminator bytes POS_END (0) or
-** (1)).
+** This function is used to help parse offset-lists. When this function is
+** called, *pp may point to the start of the next varint in the offset-list
+** being parsed, or it may point to 1 byte past the end of the offset-list
+** (in which case **pp will be 0x00 or 0x01).
**
-** If *pp points past the end of the current position-list, set *pi to
-** POSITION_LIST_END and return. Otherwise, read the next varint from *pp,
+** If *pp points past the end of the current offset list, set *pi to
+** OFFSET_LIST_END and return. Otherwise, read the next varint from *pp,
** increment the current value of *pi by the value read, and set *pp to
** point to the next value before returning.
-**
-** Before calling this routine *pi must be initialized to the value of
-** the previous position, or zero if we are reading the first position
-** in the position-list. Because positions are delta-encoded, the value
-** of the previous position is needed in order to compute the value of
-** the next position.
*/
static void fts3ReadNextPos(
- char **pp, /* IN/OUT: Pointer into position-list buffer */
- sqlite3_int64 *pi /* IN/OUT: Value read from position-list */
+ char **pp, /* IN/OUT: Pointer into offset-list buffer */
+ sqlite3_int64 *pi /* IN/OUT: Value read from offset-list */
){
- if( (**pp)&0xFE ){
+ if( **pp&0xFE ){
fts3GetDeltaVarint(pp, pi);
*pi -= 2;
}else{
- *pi = POSITION_LIST_END;
+ *pi = OFFSET_LIST_END;
}
}
/*
-** If parameter iCol is not 0, write an POS_COLUMN (1) byte followed by
-** the value of iCol encoded as a varint to *pp. This will start a new
-** column list.
+** If parameter iCol is not 0, write an 0x01 byte followed by the value of
+** iCol encoded as a varint to *pp.
**
-** Set *pp to point to the byte just after the last byte written before
+** Set *pp to point to the byte just after the last byte written before
** returning (do not modify it if iCol==0). Return the total number of bytes
** written (0 if iCol==0).
*/
@@ -106401,11 +99785,7 @@ static int fts3PutColNumber(char **pp, int iCol){
}
/*
-** Compute the union of two position lists. The output written
-** into *pp contains all positions of both *pp1 and *pp2 in sorted
-** order and with any duplicates removed. All pointers are
-** updated appropriately. The caller is responsible for insuring
-** that there is enough space in *pp to hold the complete output.
+**
*/
static void fts3PoslistMerge(
char **pp, /* Output buffer */
@@ -106417,38 +99797,37 @@ static void fts3PoslistMerge(
char *p2 = *pp2;
while( *p1 || *p2 ){
- int iCol1; /* The current column index in pp1 */
- int iCol2; /* The current column index in pp2 */
+ int iCol1;
+ int iCol2;
- if( *p1==POS_COLUMN ) sqlite3Fts3GetVarint32(&p1[1], &iCol1);
- else if( *p1==POS_END ) iCol1 = POSITION_LIST_END;
+ if( *p1==0x01 ) sqlite3Fts3GetVarint32(&p1[1], &iCol1);
+ else if( *p1==0x00 ) iCol1 = OFFSET_LIST_END;
else iCol1 = 0;
- if( *p2==POS_COLUMN ) sqlite3Fts3GetVarint32(&p2[1], &iCol2);
- else if( *p2==POS_END ) iCol2 = POSITION_LIST_END;
+ if( *p2==0x01 ) sqlite3Fts3GetVarint32(&p2[1], &iCol2);
+ else if( *p2==0x00 ) iCol2 = OFFSET_LIST_END;
else iCol2 = 0;
if( iCol1==iCol2 ){
- sqlite3_int64 i1 = 0; /* Last position from pp1 */
- sqlite3_int64 i2 = 0; /* Last position from pp2 */
+ sqlite3_int64 i1 = 0;
+ sqlite3_int64 i2 = 0;
sqlite3_int64 iPrev = 0;
int n = fts3PutColNumber(&p, iCol1);
p1 += n;
p2 += n;
- /* At this point, both p1 and p2 point to the start of column-lists
- ** for the same column (the column with index iCol1 and iCol2).
- ** A column-list is a list of non-negative delta-encoded varints, each
- ** incremented by 2 before being stored. Each list is terminated by a
- ** POS_END (0) or POS_COLUMN (1). The following block merges the two lists
+ /* At this point, both p1 and p2 point to the start of offset-lists.
+ ** An offset-list is a list of non-negative delta-encoded varints, each
+ ** incremented by 2 before being stored. Each list is terminated by a 0
+ ** or 1 value (0x00 or 0x01). The following block merges the two lists
** and writes the results to buffer p. p is left pointing to the byte
- ** after the list written. No terminator (POS_END or POS_COLUMN) is
- ** written to the output.
+ ** after the list written. No terminator (0x00 or 0x01) is written to
+ ** the output.
*/
fts3GetDeltaVarint(&p1, &i1);
fts3GetDeltaVarint(&p2, &i2);
do {
- fts3PutDeltaVarint(&p, &iPrev, (i1<i2) ? i1 : i2);
+ fts3PutDeltaVarint(&p, &iPrev, (i1<i2) ? i1 : i2);
iPrev -= 2;
if( i1==i2 ){
fts3ReadNextPos(&p1, &i1);
@@ -106458,7 +99837,7 @@ static void fts3PoslistMerge(
}else{
fts3ReadNextPos(&p2, &i2);
}
- }while( i1!=POSITION_LIST_END || i2!=POSITION_LIST_END );
+ }while( i1!=OFFSET_LIST_END || i2!=OFFSET_LIST_END );
}else if( iCol1<iCol2 ){
p1 += fts3PutColNumber(&p, iCol1);
fts3ColumnlistCopy(&p, &p1);
@@ -106468,7 +99847,7 @@ static void fts3PoslistMerge(
}
}
- *p++ = POS_END;
+ *p++ = '\0';
*pp = p;
*pp1 = p1 + 1;
*pp2 = p2 + 1;
@@ -106491,11 +99870,11 @@ static int fts3PoslistPhraseMerge(
int iCol1 = 0;
int iCol2 = 0;
assert( *p1!=0 && *p2!=0 );
- if( *p1==POS_COLUMN ){
+ if( *p1==0x01 ){
p1++;
p1 += sqlite3Fts3GetVarint32(p1, &iCol1);
}
- if( *p2==POS_COLUMN ){
+ if( *p2==0x01 ){
p2++;
p2 += sqlite3Fts3GetVarint32(p2, &iCol2);
}
@@ -106508,12 +99887,11 @@ static int fts3PoslistPhraseMerge(
sqlite3_int64 iPos2 = 0;
if( pp && iCol1 ){
- *p++ = POS_COLUMN;
+ *p++ = 0x01;
p += sqlite3Fts3PutVarint(p, iCol1);
}
- assert( *p1!=POS_END && *p1!=POS_COLUMN );
- assert( *p2!=POS_END && *p2!=POS_COLUMN );
+ assert( *p1!=0x00 && *p2!=0x00 && *p1!=0x01 && *p2!=0x01 );
fts3GetDeltaVarint(&p1, &iPos1); iPos1 -= 2;
fts3GetDeltaVarint(&p2, &iPos2); iPos2 -= 2;
@@ -106558,8 +99936,8 @@ static int fts3PoslistPhraseMerge(
/* Advance pointer p1 or p2 (whichever corresponds to the smaller of
** iCol1 and iCol2) so that it points to either the 0x00 that marks the
- ** end of the position list, or the 0x01 that precedes the next
- ** column-number in the position list.
+ ** end of the position list, or the 0x01 that precedes the next
+ ** column-number in the position list.
*/
else if( iCol1<iCol2 ){
fts3ColumnlistCopy(0, &p1);
@@ -106673,7 +100051,7 @@ static int fts3DoclistMerge(
char *pEnd1 = &a1[n1];
char *pEnd2 = &a2[n2];
- assert( mergetype==MERGE_OR || mergetype==MERGE_POS_OR
+ assert( mergetype==MERGE_OR || mergetype==MERGE_POS_OR
|| mergetype==MERGE_AND || mergetype==MERGE_NOT
|| mergetype==MERGE_PHRASE || mergetype==MERGE_POS_PHRASE
|| mergetype==MERGE_NEAR || mergetype==MERGE_POS_NEAR
@@ -106765,7 +100143,6 @@ static int fts3DoclistMerge(
default: assert( mergetype==MERGE_POS_NEAR || mergetype==MERGE_NEAR ); {
char *aTmp = 0;
char **ppPos = 0;
-
if( mergetype==MERGE_POS_NEAR ){
ppPos = &p;
aTmp = sqlite3_malloc(2*(n1+n2+1));
@@ -106804,8 +100181,8 @@ static int fts3DoclistMerge(
return SQLITE_OK;
}
-/*
-** A pointer to an instance of this structure is used as the context
+/*
+** A pointer to an instance of this structure is used as the context
** argument to sqlite3Fts3SegReaderIterate()
*/
typedef struct TermSelect TermSelect;
@@ -106866,13 +100243,13 @@ static int fts3TermSelectCb(
/*
** This function retreives the doclist for the specified term (or term
-** prefix) from the database.
+** prefix) from the database.
**
-** The returned doclist may be in one of two formats, depending on the
+** The returned doclist may be in one of two formats, depending on the
** value of parameter isReqPos. If isReqPos is zero, then the doclist is
-** a sorted list of delta-compressed docids (a bare doclist). If isReqPos
-** is non-zero, then the returned list is in the same format as is stored
-** in the database without the found length specifier at the start of on-disk
+** a sorted list of delta-compressed docids. If isReqPos is non-zero,
+** then the returned list is in the same format as is stored in the
+** database without the found length specifier at the start of on-disk
** doclists.
*/
static int fts3TermSelect(
@@ -106921,7 +100298,7 @@ static int fts3TermSelect(
if( sqlite3_column_int64(pStmt, 1)==0 ){
/* The entire segment is stored on the root node (which must be a
** leaf). Do not bother inspecting any data in this case, just
- ** create a Fts3SegReader to scan the single leaf.
+ ** create a Fts3SegReader to scan the single leaf.
*/
rc = sqlite3Fts3SegReaderNew(p, iAge, 0, 0, 0, zRoot, nRoot, &pNew);
}else{
@@ -106935,10 +100312,10 @@ static int fts3TermSelect(
/* The following call to ReadBlock() serves to reset the SQL statement
** used to retrieve blocks of data from the %_segments table. If it is
- ** not reset here, then it may remain classified as an active statement
- ** by SQLite, which may lead to "DROP TABLE" or "DETACH" commands
+ ** not reset here, then it may remain classified as an active statement
+ ** by SQLite, which may lead to "DROP TABLE" or "DETACH" commands
** failing.
- */
+ */
rc2 = sqlite3Fts3ReadBlock(p, 0, 0, 0);
if( rc==SQLITE_OK ){
rc = rc2;
@@ -106973,7 +100350,7 @@ static int fts3TermSelect(
memset(&tsc, 0, sizeof(TermSelect));
tsc.isReqPos = isReqPos;
- filter.flags = FTS3_SEGMENT_IGNORE_EMPTY
+ filter.flags = FTS3_SEGMENT_IGNORE_EMPTY
| (isPrefix ? FTS3_SEGMENT_PREFIX : 0)
| (isReqPos ? FTS3_SEGMENT_REQUIRE_POS : 0)
| (iColumn<p->nColumn ? FTS3_SEGMENT_COLUMN_FILTER : 0);
@@ -107002,7 +100379,7 @@ finished:
}
-/*
+/*
** Return a DocList corresponding to the phrase *pPhrase.
*/
static int fts3PhraseSelect(
@@ -107062,79 +100439,9 @@ static int fts3PhraseSelect(
return rc;
}
-static int fts3NearMerge(
- int mergetype, /* MERGE_POS_NEAR or MERGE_NEAR */
- int nNear, /* Parameter to NEAR operator */
- int nTokenLeft, /* Number of tokens in LHS phrase arg */
- char *aLeft, /* Doclist for LHS (incl. positions) */
- int nLeft, /* Size of LHS doclist in bytes */
- int nTokenRight, /* As nTokenLeft */
- char *aRight, /* As aLeft */
- int nRight, /* As nRight */
- char **paOut, /* OUT: Results of merge (malloced) */
- int *pnOut /* OUT: Sized of output buffer */
-){
- char *aOut;
- int rc;
-
- assert( mergetype==MERGE_POS_NEAR || MERGE_NEAR );
-
- aOut = sqlite3_malloc(nLeft+nRight+1);
- if( aOut==0 ){
- rc = SQLITE_NOMEM;
- }else{
- rc = fts3DoclistMerge(mergetype, nNear+nTokenRight, nNear+nTokenLeft,
- aOut, pnOut, aLeft, nLeft, aRight, nRight
- );
- if( rc!=SQLITE_OK ){
- sqlite3_free(aOut);
- aOut = 0;
- }
- }
-
- *paOut = aOut;
- return rc;
-}
-
-SQLITE_PRIVATE int sqlite3Fts3ExprNearTrim(Fts3Expr *pLeft, Fts3Expr *pRight, int nNear){
- int rc;
- if( pLeft->aDoclist==0 || pRight->aDoclist==0 ){
- sqlite3_free(pLeft->aDoclist);
- sqlite3_free(pRight->aDoclist);
- pRight->aDoclist = 0;
- pLeft->aDoclist = 0;
- rc = SQLITE_OK;
- }else{
- char *aOut;
- int nOut;
-
- rc = fts3NearMerge(MERGE_POS_NEAR, nNear,
- pLeft->pPhrase->nToken, pLeft->aDoclist, pLeft->nDoclist,
- pRight->pPhrase->nToken, pRight->aDoclist, pRight->nDoclist,
- &aOut, &nOut
- );
- if( rc!=SQLITE_OK ) return rc;
- sqlite3_free(pRight->aDoclist);
- pRight->aDoclist = aOut;
- pRight->nDoclist = nOut;
-
- rc = fts3NearMerge(MERGE_POS_NEAR, nNear,
- pRight->pPhrase->nToken, pRight->aDoclist, pRight->nDoclist,
- pLeft->pPhrase->nToken, pLeft->aDoclist, pLeft->nDoclist,
- &aOut, &nOut
- );
- sqlite3_free(pLeft->aDoclist);
- pLeft->aDoclist = aOut;
- pLeft->nDoclist = nOut;
- }
- return rc;
-}
-
/*
** Evaluate the full-text expression pExpr against fts3 table pTab. Store
-** the resulting doclist in *paOut and *pnOut. This routine mallocs for
-** the space needed to store the output. The caller is responsible for
-** freeing the space when it has finished.
+** the resulting doclist in *paOut and *pnOut.
*/
static int evalFts3Expr(
Fts3Table *p, /* Virtual table handle */
@@ -107150,12 +100457,12 @@ static int evalFts3Expr(
*pnOut = 0;
if( pExpr ){
- assert( pExpr->eType==FTSQUERY_PHRASE
- || pExpr->eType==FTSQUERY_NEAR
+ assert( pExpr->eType==FTSQUERY_PHRASE
+ || pExpr->eType==FTSQUERY_NEAR
|| isReqPos==0
);
if( pExpr->eType==FTSQUERY_PHRASE ){
- rc = fts3PhraseSelect(p, pExpr->pPhrase,
+ rc = fts3PhraseSelect(p, pExpr->pPhrase,
isReqPos || (pExpr->pParent && pExpr->pParent->eType==FTSQUERY_NEAR),
paOut, pnOut
);
@@ -107168,7 +100475,7 @@ static int evalFts3Expr(
if( 0==(rc = evalFts3Expr(p, pExpr->pRight, &aRight, &nRight, isReqPos))
&& 0==(rc = evalFts3Expr(p, pExpr->pLeft, &aLeft, &nLeft, isReqPos))
){
- assert( pExpr->eType==FTSQUERY_NEAR || pExpr->eType==FTSQUERY_OR
+ assert( pExpr->eType==FTSQUERY_NEAR || pExpr->eType==FTSQUERY_OR
|| pExpr->eType==FTSQUERY_AND || pExpr->eType==FTSQUERY_NOT
);
switch( pExpr->eType ){
@@ -107176,23 +100483,32 @@ static int evalFts3Expr(
Fts3Expr *pLeft;
Fts3Expr *pRight;
int mergetype = isReqPos ? MERGE_POS_NEAR : MERGE_NEAR;
-
+ int nParam1;
+ int nParam2;
+ char *aBuffer;
+
if( pExpr->pParent && pExpr->pParent->eType==FTSQUERY_NEAR ){
mergetype = MERGE_POS_NEAR;
}
pLeft = pExpr->pLeft;
- while( pLeft->eType==FTSQUERY_NEAR ){
+ while( pLeft->eType==FTSQUERY_NEAR ){
pLeft=pLeft->pRight;
}
pRight = pExpr->pRight;
assert( pRight->eType==FTSQUERY_PHRASE );
assert( pLeft->eType==FTSQUERY_PHRASE );
- rc = fts3NearMerge(mergetype, pExpr->nNear,
- pLeft->pPhrase->nToken, aLeft, nLeft,
- pRight->pPhrase->nToken, aRight, nRight,
- paOut, pnOut
+ nParam1 = pExpr->nNear+1;
+ nParam2 = nParam1+pLeft->pPhrase->nToken+pRight->pPhrase->nToken-2;
+ aBuffer = sqlite3_malloc(nLeft+nRight+1);
+ rc = fts3DoclistMerge(mergetype, nParam1, nParam2, aBuffer,
+ pnOut, aLeft, nLeft, aRight, nRight
);
+ if( rc!=SQLITE_OK ){
+ sqlite3_free(aBuffer);
+ }else{
+ *paOut = aBuffer;
+ }
sqlite3_free(aLeft);
break;
}
@@ -107304,16 +100620,10 @@ static int fts3FilterMethod(
return SQLITE_NOMEM;
}
- rc = sqlite3Fts3ExprParse(p->pTokenizer, p->azColumn, p->nColumn,
+ rc = sqlite3Fts3ExprParse(p->pTokenizer, p->azColumn, p->nColumn,
iCol, zQuery, -1, &pCsr->pExpr
);
- if( rc!=SQLITE_OK ){
- if( rc==SQLITE_ERROR ){
- p->base.zErrMsg = sqlite3_mprintf("malformed MATCH expression: [%s]",
- zQuery);
- }
- return rc;
- }
+ if( rc!=SQLITE_OK ) return rc;
rc = evalFts3Expr(p, pCsr->pExpr, &pCsr->aDoclist, &pCsr->nDoclist, 0);
pCsr->pNextId = pCsr->aDoclist;
@@ -107324,15 +100634,15 @@ static int fts3FilterMethod(
return fts3NextMethod(pCursor);
}
-/*
-** This is the xEof method of the virtual table. SQLite calls this
+/*
+** This is the xEof method of the virtual table. SQLite calls this
** routine to find out if it has reached the end of a result set.
*/
static int fts3EofMethod(sqlite3_vtab_cursor *pCursor){
return ((Fts3Cursor *)pCursor)->isEof;
}
-/*
+/*
** This is the xRowid method. The SQLite core calls this routine to
** retrieve the rowid for the current row of the result set. fts3
** exposes %_content.docid as the rowid for the virtual table. The
@@ -107348,7 +100658,7 @@ static int fts3RowidMethod(sqlite3_vtab_cursor *pCursor, sqlite_int64 *pRowid){
return SQLITE_OK;
}
-/*
+/*
** This is the xColumn method, called by SQLite to request a value from
** the row that the supplied cursor currently points to.
*/
@@ -107365,7 +100675,7 @@ static int fts3ColumnMethod(
assert( iCol>=0 && iCol<=p->nColumn+1 );
if( iCol==p->nColumn+1 ){
- /* This call is a request for the "docid" column. Since "docid" is an
+ /* This call is a request for the "docid" column. Since "docid" is an
** alias for "rowid", use the xRowid() method to obtain the value.
*/
sqlite3_int64 iRowid;
@@ -107386,8 +100696,8 @@ static int fts3ColumnMethod(
return rc;
}
-/*
-** This function is the implementation of the xUpdate callback used by
+/*
+** This function is the implementation of the xUpdate callback used by
** FTS3 virtual tables. It is invoked by SQLite each time a row is to be
** inserted, updated or deleted.
*/
@@ -107449,7 +100759,7 @@ SQLITE_PRIVATE int sqlite3Fts3ExprLoadDoclist(Fts3Table *pTab, Fts3Expr *pExpr){
/*
** After ExprLoadDoclist() (see above) has been called, this function is
-** used to iterate/search through the position lists that make up the doclist
+** used to iterate through the position lists that make up the doclist
** stored in pExpr->aDoclist.
*/
SQLITE_PRIVATE char *sqlite3Fts3FindPositions(
@@ -107466,9 +100776,7 @@ SQLITE_PRIVATE char *sqlite3Fts3FindPositions(
while( pCsr<pEnd ){
if( pExpr->iCurrent<iDocid ){
fts3PoslistCopy(0, &pCsr);
- if( pCsr<pEnd ){
- fts3GetDeltaVarint(&pCsr, &pExpr->iCurrent);
- }
+ fts3GetDeltaVarint(&pCsr, &pExpr->iCurrent);
pExpr->pCurrent = pCsr;
}else{
if( pExpr->iCurrent==iDocid ){
@@ -107486,7 +100794,7 @@ SQLITE_PRIVATE char *sqlite3Fts3FindPositions(
pCsr++;
pCsr += sqlite3Fts3GetVarint32(pCsr, &iThis);
}
- if( iCol==iThis && (*pCsr&0xFE) ) return pCsr;
+ if( iCol==iThis ) return pCsr;
}
return 0;
}
@@ -107501,7 +100809,7 @@ SQLITE_PRIVATE char *sqlite3Fts3FindPositions(
** offsets() and optimize() SQL functions.
**
** If the value passed as the third argument is a blob of size
-** sizeof(Fts3Cursor*), then the blob contents are copied to the
+** sizeof(Fts3Cursor*), then the blob contents are copied to the
** output variable *ppCsr and SQLITE_OK is returned. Otherwise, an error
** message is written to context pContext and SQLITE_ERROR returned. The
** string passed via zFunc is used as part of the error message.
@@ -107513,7 +100821,7 @@ static int fts3FunctionArg(
Fts3Cursor **ppCsr /* OUT: Store cursor handle here */
){
Fts3Cursor *pRet;
- if( sqlite3_value_type(pVal)!=SQLITE_BLOB
+ if( sqlite3_value_type(pVal)!=SQLITE_BLOB
|| sqlite3_value_bytes(pVal)!=sizeof(Fts3Cursor *)
){
char *zErr = sqlite3_mprintf("illegal first argument to %s", zFunc);
@@ -107538,8 +100846,45 @@ static void fts3SnippetFunc(
const char *zStart = "<b>";
const char *zEnd = "</b>";
const char *zEllipsis = "<b>...</b>";
+
+ /* There must be at least one argument passed to this function (otherwise
+ ** the non-overloaded version would have been called instead of this one).
+ */
+ assert( nVal>=1 );
+
+ if( nVal>4 ){
+ sqlite3_result_error(pContext,
+ "wrong number of arguments to function snippet()", -1);
+ return;
+ }
+ if( fts3FunctionArg(pContext, "snippet", apVal[0], &pCsr) ) return;
+
+ switch( nVal ){
+ case 4: zEllipsis = (const char*)sqlite3_value_text(apVal[3]);
+ case 3: zEnd = (const char*)sqlite3_value_text(apVal[2]);
+ case 2: zStart = (const char*)sqlite3_value_text(apVal[1]);
+ }
+ if( !zEllipsis || !zEnd || !zStart ){
+ sqlite3_result_error_nomem(pContext);
+ }else if( SQLITE_OK==fts3CursorSeek(pContext, pCsr) ){
+ sqlite3Fts3Snippet(pContext, pCsr, zStart, zEnd, zEllipsis);
+ }
+}
+
+/*
+** Implementation of the snippet2() function for FTS3
+*/
+static void fts3Snippet2Func(
+ sqlite3_context *pContext, /* SQLite function call context */
+ int nVal, /* Size of apVal[] array */
+ sqlite3_value **apVal /* Array of arguments */
+){
+ Fts3Cursor *pCsr; /* Cursor handle passed through apVal[0] */
+ const char *zStart = "<b>";
+ const char *zEnd = "</b>";
+ const char *zEllipsis = "<b>...</b>";
int iCol = -1;
- int nToken = 15; /* Default number of tokens in snippet */
+ int nToken = 10;
/* There must be at least one argument passed to this function (otherwise
** the non-overloaded version would have been called instead of this one).
@@ -107547,7 +100892,7 @@ static void fts3SnippetFunc(
assert( nVal>=1 );
if( nVal>6 ){
- sqlite3_result_error(pContext,
+ sqlite3_result_error(pContext,
"wrong number of arguments to function snippet()", -1);
return;
}
@@ -107563,7 +100908,7 @@ static void fts3SnippetFunc(
if( !zEllipsis || !zEnd || !zStart ){
sqlite3_result_error_nomem(pContext);
}else if( SQLITE_OK==fts3CursorSeek(pContext, pCsr) ){
- sqlite3Fts3Snippet(pContext, pCsr, zStart, zEnd, zEllipsis, iCol, nToken);
+ sqlite3Fts3Snippet2(pContext, pCsr, zStart, zEnd, zEllipsis, iCol, nToken);
}
}
@@ -107587,8 +100932,8 @@ static void fts3OffsetsFunc(
}
}
-/*
-** Implementation of the special optimize() function for FTS3. This
+/*
+** Implementation of the special optimize() function for FTS3. This
** function merges all segments in the database to a single segment.
** Example usage is:
**
@@ -107664,6 +101009,7 @@ static int fts3FindFunctionMethod(
void (*xFunc)(sqlite3_context*,int,sqlite3_value**);
} aOverload[] = {
{ "snippet", fts3SnippetFunc },
+ { "snippet2", fts3Snippet2Func },
{ "offsets", fts3OffsetsFunc },
{ "optimize", fts3OptimizeFunc },
{ "matchinfo", fts3MatchinfoFunc },
@@ -107692,35 +101038,22 @@ static int fts3RenameMethod(
sqlite3_vtab *pVtab, /* Virtual table handle */
const char *zName /* New name of table */
){
- Fts3Table *p = (Fts3Table *)pVtab;
- sqlite3 *db; /* Database connection */
- int rc; /* Return Code */
-
- db = p->db;
- rc = SQLITE_OK;
- fts3DbExec(&rc, db,
- "ALTER TABLE %Q.'%q_content' RENAME TO '%q_content';",
- p->zDb, p->zName, zName
+ Fts3Table *p = (Fts3Table *)pVtab;
+ int rc = SQLITE_NOMEM; /* Return Code */
+ char *zSql; /* SQL script to run to rename tables */
+
+ zSql = sqlite3_mprintf(
+ "ALTER TABLE %Q.'%q_content' RENAME TO '%q_content';"
+ "ALTER TABLE %Q.'%q_segments' RENAME TO '%q_segments';"
+ "ALTER TABLE %Q.'%q_segdir' RENAME TO '%q_segdir';"
+ , p->zDb, p->zName, zName
+ , p->zDb, p->zName, zName
+ , p->zDb, p->zName, zName
);
- if( rc==SQLITE_ERROR ) rc = SQLITE_OK;
- if( p->bHasDocsize ){
- fts3DbExec(&rc, db,
- "ALTER TABLE %Q.'%q_docsize' RENAME TO '%q_docsize';",
- p->zDb, p->zName, zName
- );
- fts3DbExec(&rc, db,
- "ALTER TABLE %Q.'%q_stat' RENAME TO '%q_stat';",
- p->zDb, p->zName, zName
- );
+ if( zSql ){
+ rc = sqlite3_exec(p->db, zSql, 0, 0, 0);
+ sqlite3_free(zSql);
}
- fts3DbExec(&rc, db,
- "ALTER TABLE %Q.'%q_segments' RENAME TO '%q_segments';",
- p->zDb, p->zName, zName
- );
- fts3DbExec(&rc, db,
- "ALTER TABLE %Q.'%q_segdir' RENAME TO '%q_segdir';",
- p->zDb, p->zName, zName
- );
return rc;
}
@@ -107779,7 +101112,10 @@ SQLITE_PRIVATE void sqlite3Fts3IcuTokenizerModule(sqlite3_tokenizer_module const
** SQLite. If fts3 is built as a dynamically loadable extension, this
** function is called by the sqlite3_extension_init() entry point.
*/
-SQLITE_PRIVATE int sqlite3Fts3Init(sqlite3 *db, const char* registerAs){ // Android Change
+// Begin Android change
+SQLITE_PRIVATE int sqlite3Fts3Init(sqlite3 *db, const char* registerAs){
+// End Android change
+
int rc = SQLITE_OK;
Fts3Hash *pHash = 0;
const sqlite3_tokenizer_module *pSimple = 0;
@@ -107804,7 +101140,7 @@ SQLITE_PRIVATE int sqlite3Fts3Init(sqlite3 *db, const char* registerAs){ // Andr
/* Load the built-in tokenizers into the hash table */
if( rc==SQLITE_OK ){
if( sqlite3Fts3HashInsert(pHash, "simple", 7, (void *)pSimple)
- || sqlite3Fts3HashInsert(pHash, "porter", 7, (void *)pPorter)
+ || sqlite3Fts3HashInsert(pHash, "porter", 7, (void *)pPorter)
#ifdef SQLITE_ENABLE_ICU
|| (pIcu && sqlite3Fts3HashInsert(pHash, "icu", 4, (void *)pIcu))
#endif
@@ -107819,13 +101155,14 @@ SQLITE_PRIVATE int sqlite3Fts3Init(sqlite3 *db, const char* registerAs){ // Andr
}
#endif
- /* Create the virtual table wrapper around the hash-table and overload
+ /* Create the virtual table wrapper around the hash-table and overload
** the two scalar functions. If this is successful, register the
** module with sqlite.
*/
- if( SQLITE_OK==rc
+ if( SQLITE_OK==rc
&& SQLITE_OK==(rc = sqlite3Fts3InitHashTable(db, pHash, "fts3_tokenizer"))
&& SQLITE_OK==(rc = sqlite3_overload_function(db, "snippet", -1))
+ && SQLITE_OK==(rc = sqlite3_overload_function(db, "snippet2", -1))
&& SQLITE_OK==(rc = sqlite3_overload_function(db, "offsets", 1))
&& SQLITE_OK==(rc = sqlite3_overload_function(db, "matchinfo", -1))
&& SQLITE_OK==(rc = sqlite3_overload_function(db, "optimize", 1))
@@ -107834,14 +101171,8 @@ SQLITE_PRIVATE int sqlite3Fts3Init(sqlite3 *db, const char* registerAs){ // Andr
/* Also register as fts1 and fts2 */
return sqlite3_create_module_v2(
db, registerAs, &fts3Module, (void *)pHash, hashDestroy
- );
// End Android change
- if( rc==SQLITE_OK ){
- rc = sqlite3_create_module_v2(
- db, "fts4", &fts3Module, (void *)pHash, 0
- );
- }
- return rc;
+ );
}
/* An error has occurred. Delete the hash table and return the error code. */
@@ -107855,7 +101186,7 @@ SQLITE_PRIVATE int sqlite3Fts3Init(sqlite3 *db, const char* registerAs){ // Andr
#if !SQLITE_CORE
SQLITE_API int sqlite3_extension_init(
- sqlite3 *db,
+ sqlite3 *db,
char **pzErrMsg,
const sqlite3_api_routines *pApi
){
@@ -107881,14 +101212,14 @@ SQLITE_API int sqlite3_extension_init(
******************************************************************************
**
** This module contains code that implements a parser for fts3 query strings
-** (the right-hand argument to the MATCH operator). Because the supported
+** (the right-hand argument to the MATCH operator). Because the supported
** syntax is relatively simple, the whole tokenizer/parser system is
-** hand-coded.
+** hand-coded.
*/
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
/*
-** By default, this module parses the legacy syntax that has been
+** By default, this module parses the legacy syntax that has been
** traditionally used by fts3. Or, if SQLITE_ENABLE_FTS3_PARENTHESIS
** is defined, then it uses the new syntax. The differences between
** the new and the old syntaxes are:
@@ -107897,7 +101228,7 @@ SQLITE_API int sqlite3_extension_init(
**
** b) The new syntax supports the AND and NOT operators. The old does not.
**
-** c) The old syntax supports the "-" token qualifier. This is not
+** c) The old syntax supports the "-" token qualifier. This is not
** supported by the new syntax (it is replaced by the NOT operator).
**
** d) When using the old syntax, the OR operator has a greater precedence
@@ -107906,7 +101237,7 @@ SQLITE_API int sqlite3_extension_init(
**
** If compiled with SQLITE_TEST defined, then this module exports the
** symbol "int sqlite3_fts3_enable_parentheses". Setting this variable
-** to zero causes the module to use the old syntax. If it is set to
+** to zero causes the module to use the old syntax. If it is set to
** non-zero the new syntax is activated. This is so both syntaxes can
** be tested using a single build of testfixture.
**
@@ -107935,7 +101266,7 @@ SQLITE_API int sqlite3_extension_init(
#ifdef SQLITE_TEST
SQLITE_API int sqlite3_fts3_enable_parentheses = 0;
#else
-# ifdef SQLITE_ENABLE_FTS3_PARENTHESIS
+# ifdef SQLITE_ENABLE_FTS3_PARENTHESIS
# define sqlite3_fts3_enable_parentheses 1
# else
# define sqlite3_fts3_enable_parentheses 0
@@ -107959,7 +101290,7 @@ struct ParseContext {
};
/*
-** This function is equivalent to the standard isspace() function.
+** This function is equivalent to the standard isspace() function.
**
** The standard isspace() can be awkward to use safely, because although it
** is defined to accept an argument of type int, its behaviour when passed
@@ -107979,7 +101310,7 @@ static int fts3isspace(char c){
** structure of type FTSQUERY_PHRASE containing a phrase consisting of this
** single token and set *ppExpr to point to it. If the end of the buffer is
** reached before a token is found, set *ppExpr to zero. It is the
-** responsibility of the caller to eventually deallocate the allocated
+** responsibility of the caller to eventually deallocate the allocated
** Fts3Expr structure (if any) by passing it to sqlite3_free().
**
** Return SQLITE_OK if successful, or SQLITE_NOMEM if a memory allocation
@@ -108036,7 +101367,7 @@ static int getNextToken(
pModule->xClose(pCursor);
}
-
+
*pnConsumed = nConsumed;
*ppExpr = pRet;
return rc;
@@ -108059,7 +101390,7 @@ static void *fts3ReallocOrFree(void *pOrig, int nNew){
** Buffer zInput, length nInput, contains the contents of a quoted string
** that appeared as part of an fts3 query expression. Neither quote character
** is included in the buffer. This function attempts to tokenize the entire
-** input buffer and create an Fts3Expr structure of type FTSQUERY_PHRASE
+** input buffer and create an Fts3Expr structure of type FTSQUERY_PHRASE
** containing the results.
**
** If successful, SQLITE_OK is returned and *ppExpr set to point at the
@@ -108163,7 +101494,7 @@ no_mem:
static int fts3ExprParse(ParseContext *, const char *, int, Fts3Expr **, int *);
/*
-** The output variable *ppExpr is populated with an allocated Fts3Expr
+** The output variable *ppExpr is populated with an allocated Fts3Expr
** structure, or set to 0 if the end of the input buffer is reached.
**
** Returns an SQLite error code. SQLITE_OK if everything works, SQLITE_NOMEM
@@ -108197,7 +101528,7 @@ static int getNextNode(
int nInput = n;
/* Skip over any whitespace before checking for a keyword, an open or
- ** close bracket, or a quoted string.
+ ** close bracket, or a quoted string.
*/
while( nInput>0 && fts3isspace(*zInput) ){
nInput--;
@@ -108233,10 +101564,10 @@ static int getNextNode(
/* At this point this is probably a keyword. But for that to be true,
** the next byte must contain either whitespace, an open or close
- ** parenthesis, a quote character, or EOF.
+ ** parenthesis, a quote character, or EOF.
*/
cNext = zInput[nKey];
- if( fts3isspace(cNext)
+ if( fts3isspace(cNext)
|| cNext=='"' || cNext=='(' || cNext==')' || cNext==0
){
pRet = (Fts3Expr *)sqlite3_malloc(sizeof(Fts3Expr));
@@ -108270,7 +101601,7 @@ static int getNextNode(
*pnConsumed = (int)((zInput - z) + 1 + nConsumed);
return rc;
}
-
+
/* Check for a close bracket. */
if( *zInput==')' ){
pParse->nNest--;
@@ -108294,15 +101625,15 @@ static int getNextNode(
}
- /* If control flows to this point, this must be a regular token, or
+ /* If control flows to this point, this must be a regular token, or
** the end of the input. Read a regular token using the sqlite3_tokenizer
** interface. Before doing so, figure out if there is an explicit
- ** column specifier for the token.
+ ** column specifier for the token.
**
** TODO: Strangely, it is not possible to associate a column specifier
** with a quoted phrase, only with a single token. Not sure if this was
** an implementation artifact or an intentional decision when fts3 was
- ** first implemented. Whichever it was, this module duplicates the
+ ** first implemented. Whichever it was, this module duplicates the
** limitation.
*/
iCol = pParse->iDefaultCol;
@@ -108310,8 +101641,8 @@ static int getNextNode(
for(ii=0; ii<pParse->nCol; ii++){
const char *zStr = pParse->azCol[ii];
int nStr = (int)strlen(zStr);
- if( nInput>nStr && zInput[nStr]==':'
- && sqlite3_strnicmp(zStr, zInput, nStr)==0
+ if( nInput>nStr && zInput[nStr]==':'
+ && sqlite3_strnicmp(zStr, zInput, nStr)==0
){
iCol = ii;
iColLen = (int)((zInput - z) + nStr + 1);
@@ -108356,7 +101687,7 @@ static int opPrecedence(Fts3Expr *p){
}
/*
-** Argument ppHead contains a pointer to the current head of a query
+** Argument ppHead contains a pointer to the current head of a query
** expression tree being parsed. pPrev is the expression node most recently
** inserted into the tree. This function adds pNew, which is always a binary
** operator node, into the expression tree based on the relative precedence
@@ -108386,7 +101717,7 @@ static void insertBinaryOperator(
/*
** Parse the fts3 query expression found in buffer z, length n. This function
-** returns either when the end of the buffer is reached or an unmatched
+** returns either when the end of the buffer is reached or an unmatched
** closing bracket - ')' - is encountered.
**
** If successful, SQLITE_OK is returned, *ppExpr is set to point to the
@@ -108415,8 +101746,8 @@ static int fts3ExprParse(
if( rc==SQLITE_OK ){
int isPhrase;
- if( !sqlite3_fts3_enable_parentheses
- && p->eType==FTSQUERY_PHRASE && p->pPhrase->isNot
+ if( !sqlite3_fts3_enable_parentheses
+ && p->eType==FTSQUERY_PHRASE && p->pPhrase->isNot
){
/* Create an implicit NOT operator. */
Fts3Expr *pNot = sqlite3_malloc(sizeof(Fts3Expr));
@@ -108448,7 +101779,7 @@ static int fts3ExprParse(
rc = SQLITE_ERROR;
goto exprparse_out;
}
-
+
if( isPhrase && !isRequirePhrase ){
/* Insert an implicit AND operator. */
Fts3Expr *pAnd;
@@ -108482,7 +101813,7 @@ static int fts3ExprParse(
rc = SQLITE_ERROR;
goto exprparse_out;
}
-
+
if( isPhrase ){
if( pRet ){
assert( pPrev && pPrev->pLeft && pPrev->pRight==0 );
@@ -108550,7 +101881,7 @@ exprparse_out:
** The first parameter, pTokenizer, is passed the fts3 tokenizer module to
** use to normalize query tokens while parsing the expression. The azCol[]
** array, which is assumed to contain nCol entries, should contain the names
-** of each column in the target fts3 table, in order from left to right.
+** of each column in the target fts3 table, in order from left to right.
** Column names must be nul-terminated strings.
**
** The iDefaultCol parameter should be passed the index of the table column
@@ -108618,8 +101949,8 @@ SQLITE_PRIVATE void sqlite3Fts3ExprFree(Fts3Expr *p){
** Function to query the hash-table of tokenizers (see README.tokenizers).
*/
static int queryTestTokenizer(
- sqlite3 *db,
- const char *zName,
+ sqlite3 *db,
+ const char *zName,
const sqlite3_tokenizer_module **pp
){
int rc;
@@ -108645,7 +101976,7 @@ static int queryTestTokenizer(
/*
** This function is part of the test interface for the query parser. It
** writes a text representation of the query expression pExpr into the
-** buffer pointed to by argument zBuf. It is assumed that zBuf is large
+** buffer pointed to by argument zBuf. It is assumed that zBuf is large
** enough to store the required text representation.
*/
static void exprToString(Fts3Expr *pExpr, char *zBuf){
@@ -108687,7 +102018,7 @@ static void exprToString(Fts3Expr *pExpr, char *zBuf){
}
/*
-** This is the implementation of a scalar SQL function used to test the
+** This is the implementation of a scalar SQL function used to test the
** expression parser. It should be called as follows:
**
** fts3_exprtest(<tokenizer>, <expr>, <column 1>, ...);
@@ -108717,7 +102048,7 @@ static void fts3ExprTest(
sqlite3 *db = sqlite3_context_db_handle(context);
if( argc<3 ){
- sqlite3_result_error(context,
+ sqlite3_result_error(context,
"Usage: fts3_exprtest(tokenizer, expr, col1, ...", -1
);
return;
@@ -108776,8 +102107,8 @@ exprtest_out:
}
/*
-** Register the query expression parser test function fts3_exprtest()
-** with database connection db.
+** Register the query expression parser test function fts3_exprtest()
+** with database connection db.
*/
SQLITE_PRIVATE int sqlite3Fts3ExprInitTestInterface(sqlite3* db){
return sqlite3_create_function(
@@ -108837,8 +102168,8 @@ static void fts3HashFree(void *p){
** fields of the Hash structure.
**
** "pNew" is a pointer to the hash table that is to be initialized.
-** keyClass is one of the constants
-** FTS3_HASH_BINARY or FTS3_HASH_STRING. The value of keyClass
+** keyClass is one of the constants
+** FTS3_HASH_BINARY or FTS3_HASH_STRING. The value of keyClass
** determines what kind of key the hash table will use. "copyKey" is
** true if the hash table should make its own private copy of keys and
** false if it should just use the supplied pointer.
@@ -108915,7 +102246,7 @@ static int fts3BinCompare(const void *pKey1, int n1, const void *pKey2, int n2){
/*
** Return a pointer to the appropriate hash function given the key class.
**
-** The C syntax in this function definition may be unfamilar to some
+** The C syntax in this function definition may be unfamilar to some
** programmers, so we provide the following additional explanation:
**
** The name of the function is "ftsHashFunction". The function takes a
@@ -108975,7 +102306,7 @@ static void fts3HashInsertElement(
/* Resize the hash table so that it cantains "new_size" buckets.
-** "new_size" must be a power of 2. The hash table might fail
+** "new_size" must be a power of 2. The hash table might fail
** to resize if sqliteMalloc() fails.
**
** Return non-zero if a memory allocation error occurs.
@@ -109020,7 +102351,7 @@ static Fts3HashElem *fts3FindElementByHash(
count = pEntry->count;
xCompare = ftsCompareFunction(pH->keyClass);
while( count-- && elem ){
- if( (*xCompare)(elem->pKey,elem->nKey,pKey,nKey)==0 ){
+ if( (*xCompare)(elem->pKey,elem->nKey,pKey,nKey)==0 ){
return elem;
}
elem = elem->next;
@@ -109039,7 +102370,7 @@ static void fts3RemoveElementByHash(
){
struct _fts3ht *pEntry;
if( elem->prev ){
- elem->prev->next = elem->next;
+ elem->prev->next = elem->next;
}else{
pH->first = elem->next;
}
@@ -109067,8 +102398,8 @@ static void fts3RemoveElementByHash(
}
SQLITE_PRIVATE Fts3HashElem *sqlite3Fts3HashFindElem(
- const Fts3Hash *pH,
- const void *pKey,
+ const Fts3Hash *pH,
+ const void *pKey,
int nKey
){
int h; /* A hash on key */
@@ -109082,7 +102413,7 @@ SQLITE_PRIVATE Fts3HashElem *sqlite3Fts3HashFindElem(
return fts3FindElementByHash(pH,pKey,nKey, h & (pH->htsize-1));
}
-/*
+/*
** 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.
@@ -109251,7 +102582,7 @@ static int porterDestroy(sqlite3_tokenizer *pTokenizer){
/*
** Prepare to begin tokenizing a particular string. The input
** string to be tokenized is zInput[0..nInput-1]. A cursor
-** used to incrementally tokenize this string is returned in
+** used to incrementally tokenize this string is returned in
** *ppCursor.
*/
static int porterOpen(
@@ -109304,7 +102635,7 @@ static const char cType[] = {
/*
** isConsonant() and isVowel() determine if their first character in
** the string they point to is a consonant or a vowel, according
-** to Porter ruls.
+** to Porter ruls.
**
** A consonate is any letter other than 'a', 'e', 'i', 'o', or 'u'.
** 'Y' is a consonant unless it follows another consonant,
@@ -109424,11 +102755,11 @@ static int star_oh(const char *z){
/*
** If the word ends with zFrom and xCond() is true for the stem
-** of the word that preceeds the zFrom ending, then change the
+** of the word that preceeds the zFrom ending, then change the
** ending to zTo.
**
** The input word *pz and zFrom are both in reverse order. zTo
-** is in normal order.
+** is in normal order.
**
** Return TRUE if zFrom matches. Return FALSE if zFrom does not
** match. Not that TRUE is returned even if xCond() fails and
@@ -109497,9 +102828,9 @@ static void copy_stemmer(const char *zIn, int nIn, char *zOut, int *pnOut){
** word contains digits, 3 bytes are taken from the beginning and
** 3 bytes from the end. For long words without digits, 10 bytes
** are taken from each end. US-ASCII case folding still applies.
-**
-** If the input word contains not digits but does characters not
-** in [a-zA-Z] then no stemming is attempted and this routine just
+**
+** If the input word contains not digits but does characters not
+** in [a-zA-Z] then no stemming is attempted and this routine just
** copies the input into the input into the output with US-ASCII
** case folding.
**
@@ -109544,11 +102875,11 @@ static void porter_stemmer(const char *zIn, int nIn, char *zOut, int *pnOut){
}
}
- /* Step 1b */
+ /* Step 1b */
z2 = z;
if( stem(&z, "dee", "ee", m_gt_0) ){
/* Do nothing. The work was all in the test */
- }else if(
+ }else if(
(stem(&z, "gni", "", hasVowel) || stem(&z, "de", "", hasVowel))
&& z!=z2
){
@@ -109771,11 +103102,9 @@ static int porterNext(
if( c->iOffset>iStartOffset ){
int n = c->iOffset-iStartOffset;
if( n>c->nAllocated ){
- char *pNew;
c->nAllocated = n+20;
- pNew = sqlite3_realloc(c->zToken, c->nAllocated);
- if( !pNew ) return SQLITE_NOMEM;
- c->zToken = pNew;
+ c->zToken = sqlite3_realloc(c->zToken, c->nAllocated);
+ if( c->zToken==NULL ) return SQLITE_NOMEM;
}
porter_stemmer(&z[iStartOffset], n, c->zToken, pnBytes);
*pzToken = c->zToken;
@@ -109847,7 +103176,7 @@ SQLITE_PRIVATE void sqlite3Fts3PorterTokenizerModule(
/*
-** Implementation of the SQL scalar function for accessing the underlying
+** Implementation of the SQL scalar function for accessing the underlying
** hash table. This function may be called as follows:
**
** SELECT <function-name>(<key-name>);
@@ -110020,7 +103349,7 @@ SQLITE_PRIVATE int sqlite3Fts3InitTokenizer(
if( rc!=SQLITE_OK ){
*pzErr = sqlite3_mprintf("unknown tokenizer");
}else{
- (*ppTok)->pModule = m;
+ (*ppTok)->pModule = m;
}
sqlite3_free((void *)aArg);
}
@@ -110034,7 +103363,7 @@ SQLITE_PRIVATE int sqlite3Fts3InitTokenizer(
/*
-** Implementation of a special SQL scalar function for testing tokenizers
+** Implementation of a special SQL scalar function for testing tokenizers
** designed to be used in concert with the Tcl testing framework. This
** function must be called with two arguments:
**
@@ -110047,9 +103376,9 @@ SQLITE_PRIVATE int sqlite3Fts3InitTokenizer(
**
** The return value is a string that may be interpreted as a Tcl
** list. For each token in the <input-string>, three elements are
-** added to the returned list. The first is the token position, the
+** added to the returned list. The first is the token position, the
** second is the token text (folded, stemmed, etc.) and the third is the
-** substring of <input-string> associated with the token. For example,
+** substring of <input-string> associated with the token. For example,
** using the built-in "simple" tokenizer:
**
** SELECT fts_tokenizer_test('simple', 'I don't see how');
@@ -110057,7 +103386,7 @@ SQLITE_PRIVATE int sqlite3Fts3InitTokenizer(
** will return the string:
**
** "{0 i I 1 dont don't 2 see see 3 how how}"
-**
+**
*/
static void testFunc(
sqlite3_context *context,
@@ -110149,8 +103478,8 @@ finish:
static
int registerTokenizer(
- sqlite3 *db,
- char *zName,
+ sqlite3 *db,
+ char *zName,
const sqlite3_tokenizer_module *p
){
int rc;
@@ -110171,8 +103500,8 @@ int registerTokenizer(
static
int queryTokenizer(
- sqlite3 *db,
- char *zName,
+ sqlite3 *db,
+ char *zName,
const sqlite3_tokenizer_module **pp
){
int rc;
@@ -110253,23 +103582,23 @@ static void intTestFunc(
/*
** Set up SQL objects in database db used to access the contents of
** the hash table pointed to by argument pHash. The hash table must
-** been initialised to use string keys, and to take a private copy
+** been initialised to use string keys, and to take a private copy
** of the key when a value is inserted. i.e. by a call similar to:
**
** sqlite3Fts3HashInit(pHash, FTS3_HASH_STRING, 1);
**
** This function adds a scalar function (see header comment above
** scalarFunc() in this file for details) and, if ENABLE_TABLE is
-** defined at compilation time, a temporary virtual table (see header
-** comment above struct HashTableVtab) to the database schema. Both
+** defined at compilation time, a temporary virtual table (see header
+** comment above struct HashTableVtab) to the database schema. Both
** provide read/write access to the contents of *pHash.
**
** The third argument to this function, zName, is used as the name
** of both the scalar and, if created, the virtual table.
*/
SQLITE_PRIVATE int sqlite3Fts3InitHashTable(
- sqlite3 *db,
- Fts3Hash *pHash,
+ sqlite3 *db,
+ Fts3Hash *pHash,
const char *zName
){
int rc = SQLITE_OK;
@@ -110410,7 +103739,7 @@ static int simpleDestroy(sqlite3_tokenizer *pTokenizer){
/*
** Prepare to begin tokenizing a particular string. The input
** string to be tokenized is pInput[0..nBytes-1]. A cursor
-** used to incrementally tokenize this string is returned in
+** used to incrementally tokenize this string is returned in
** *ppCursor.
*/
static int simpleOpen(
@@ -110486,11 +103815,9 @@ static int simpleNext(
if( c->iOffset>iStartOffset ){
int i, n = c->iOffset-iStartOffset;
if( n>c->nTokenAllocated ){
- char *pNew;
c->nTokenAllocated = n+20;
- pNew = sqlite3_realloc(c->pToken, c->nTokenAllocated);
- if( !pNew ) return SQLITE_NOMEM;
- c->pToken = pNew;
+ c->pToken = sqlite3_realloc(c->pToken, c->nTokenAllocated);
+ if( c->pToken==NULL ) return SQLITE_NOMEM;
}
for(i=0; i<n; i++){
/* TODO(shess) This needs expansion to handle UTF-8
@@ -110552,7 +103879,7 @@ SQLITE_PRIVATE void sqlite3Fts3SimpleTokenizerModule(
** This file is part of the SQLite FTS3 extension module. Specifically,
** this file contains code to insert, update and delete rows from FTS3
** tables. It also contains code to merge FTS3 b-tree segments. Some
-** of the sub-routines used to merge segments are also used by the query
+** of the sub-routines used to merge segments are also used by the query
** code in fts3.c.
*/
@@ -110671,29 +103998,22 @@ struct SegmentNode {
*/
#define SQL_DELETE_CONTENT 0
#define SQL_IS_EMPTY 1
-#define SQL_DELETE_ALL_CONTENT 2
+#define SQL_DELETE_ALL_CONTENT 2
#define SQL_DELETE_ALL_SEGMENTS 3
#define SQL_DELETE_ALL_SEGDIR 4
-#define SQL_DELETE_ALL_DOCSIZE 5
-#define SQL_DELETE_ALL_STAT 6
-#define SQL_SELECT_CONTENT_BY_ROWID 7
-#define SQL_NEXT_SEGMENT_INDEX 8
-#define SQL_INSERT_SEGMENTS 9
-#define SQL_NEXT_SEGMENTS_ID 10
-#define SQL_INSERT_SEGDIR 11
-#define SQL_SELECT_LEVEL 12
-#define SQL_SELECT_ALL_LEVEL 13
-#define SQL_SELECT_LEVEL_COUNT 14
-#define SQL_SELECT_SEGDIR_COUNT_MAX 15
-#define SQL_DELETE_SEGDIR_BY_LEVEL 16
-#define SQL_DELETE_SEGMENTS_RANGE 17
-#define SQL_CONTENT_INSERT 18
-#define SQL_GET_BLOCK 19
-#define SQL_DELETE_DOCSIZE 20
-#define SQL_REPLACE_DOCSIZE 21
-#define SQL_SELECT_DOCSIZE 22
-#define SQL_SELECT_DOCTOTAL 23
-#define SQL_REPLACE_DOCTOTAL 24
+#define SQL_SELECT_CONTENT_BY_ROWID 5
+#define SQL_NEXT_SEGMENT_INDEX 6
+#define SQL_INSERT_SEGMENTS 7
+#define SQL_NEXT_SEGMENTS_ID 8
+#define SQL_INSERT_SEGDIR 9
+#define SQL_SELECT_LEVEL 10
+#define SQL_SELECT_ALL_LEVEL 11
+#define SQL_SELECT_LEVEL_COUNT 12
+#define SQL_SELECT_SEGDIR_COUNT_MAX 13
+#define SQL_DELETE_SEGDIR_BY_LEVEL 14
+#define SQL_DELETE_SEGMENTS_RANGE 15
+#define SQL_CONTENT_INSERT 16
+#define SQL_GET_BLOCK 17
/*
** This function is used to obtain an SQLite prepared statement handle
@@ -110702,7 +104022,7 @@ struct SegmentNode {
** Otherwise, an SQLite error code is returned and *pp is set to 0.
**
** If argument apVal is not NULL, then it must point to an array with
-** at least as many entries as the requested statement has bound
+** at least as many entries as the requested statement has bound
** parameters. The values are bound to the statements parameters before
** returning.
*/
@@ -110718,44 +104038,37 @@ static int fts3SqlStmt(
/* 2 */ "DELETE FROM %Q.'%q_content'",
/* 3 */ "DELETE FROM %Q.'%q_segments'",
/* 4 */ "DELETE FROM %Q.'%q_segdir'",
-/* 5 */ "DELETE FROM %Q.'%q_docsize'",
-/* 6 */ "DELETE FROM %Q.'%q_stat'",
-/* 7 */ "SELECT * FROM %Q.'%q_content' WHERE rowid=?",
-/* 8 */ "SELECT (SELECT max(idx) FROM %Q.'%q_segdir' WHERE level = ?) + 1",
-/* 9 */ "INSERT INTO %Q.'%q_segments'(blockid, block) VALUES(?, ?)",
-/* 10 */ "SELECT coalesce((SELECT max(blockid) FROM %Q.'%q_segments') + 1, 1)",
-/* 11 */ "INSERT INTO %Q.'%q_segdir' VALUES(?,?,?,?,?,?)",
-
- /* Return segments in order from oldest to newest.*/
-/* 12 */ "SELECT idx, start_block, leaves_end_block, end_block, root "
+/* 5 */ "SELECT * FROM %Q.'%q_content' WHERE rowid=?",
+/* 6 */ "SELECT coalesce(max(idx)+1, 0) FROM %Q.'%q_segdir' WHERE level=?",
+/* 7 */ "INSERT INTO %Q.'%q_segments'(blockid, block) VALUES(?, ?)",
+/* 8 */ "SELECT coalesce(max(blockid)+1, 1) FROM %Q.'%q_segments'",
+/* 9 */ "INSERT INTO %Q.'%q_segdir' VALUES(?,?,?,?,?,?)",
+
+ /* Return segments in order from oldest to newest.*/
+/* 10 */ "SELECT idx, start_block, leaves_end_block, end_block, root "
"FROM %Q.'%q_segdir' WHERE level = ? ORDER BY idx ASC",
-/* 13 */ "SELECT idx, start_block, leaves_end_block, end_block, root "
+/* 11 */ "SELECT idx, start_block, leaves_end_block, end_block, root "
"FROM %Q.'%q_segdir' ORDER BY level DESC, idx ASC",
-/* 14 */ "SELECT count(*) FROM %Q.'%q_segdir' WHERE level = ?",
-/* 15 */ "SELECT count(*), max(level) FROM %Q.'%q_segdir'",
-
-/* 16 */ "DELETE FROM %Q.'%q_segdir' WHERE level = ?",
-/* 17 */ "DELETE FROM %Q.'%q_segments' WHERE blockid BETWEEN ? AND ?",
-/* 18 */ "INSERT INTO %Q.'%q_content' VALUES(%z)",
-/* 19 */ "SELECT block FROM %Q.'%q_segments' WHERE blockid = ?",
-/* 20 */ "DELETE FROM %Q.'%q_docsize' WHERE docid = ?",
-/* 21 */ "REPLACE INTO %Q.'%q_docsize' VALUES(?,?)",
-/* 22 */ "SELECT size FROM %Q.'%q_docsize' WHERE docid=?",
-/* 23 */ "SELECT value FROM %Q.'%q_stat' WHERE id=0",
-/* 24 */ "REPLACE INTO %Q.'%q_stat' VALUES(0,?)",
+/* 12 */ "SELECT count(*) FROM %Q.'%q_segdir' WHERE level = ?",
+/* 13 */ "SELECT count(*), max(level) FROM %Q.'%q_segdir'",
+
+/* 14 */ "DELETE FROM %Q.'%q_segdir' WHERE level = ?",
+/* 15 */ "DELETE FROM %Q.'%q_segments' WHERE blockid BETWEEN ? AND ?",
+/* 16 */ "INSERT INTO %Q.'%q_content' VALUES(%z)",
+/* 17 */ "SELECT block FROM %Q.'%q_segments' WHERE blockid = ?",
};
int rc = SQLITE_OK;
sqlite3_stmt *pStmt;
assert( SizeofArray(azSql)==SizeofArray(p->aStmt) );
assert( eStmt<SizeofArray(azSql) && eStmt>=0 );
-
+
pStmt = p->aStmt[eStmt];
if( !pStmt ){
char *zSql;
if( eStmt==SQL_CONTENT_INSERT ){
- int i; /* Iterator variable */
+ int i; /* Iterator variable */
char *zVarlist; /* The "?, ?, ..." string */
zVarlist = (char *)sqlite3_malloc(2*p->nColumn+2);
if( !zVarlist ){
@@ -110800,34 +104113,27 @@ static int fts3SqlStmt(
** Returns SQLITE_OK if the statement is successfully executed, or an
** SQLite error code otherwise.
*/
-static void fts3SqlExec(
- int *pRC, /* Result code */
- Fts3Table *p, /* The FTS3 table */
- int eStmt, /* Index of statement to evaluate */
- sqlite3_value **apVal /* Parameters to bind */
-){
+static int fts3SqlExec(Fts3Table *p, int eStmt, sqlite3_value **apVal){
sqlite3_stmt *pStmt;
- int rc;
- if( *pRC ) return;
- rc = fts3SqlStmt(p, eStmt, &pStmt, apVal);
+ int rc = fts3SqlStmt(p, eStmt, &pStmt, apVal);
if( rc==SQLITE_OK ){
sqlite3_step(pStmt);
rc = sqlite3_reset(pStmt);
}
- *pRC = rc;
+ return rc;
}
/*
** Read a single block from the %_segments table. If the specified block
-** does not exist, return SQLITE_CORRUPT. If some other error (malloc, IO
+** does not exist, return SQLITE_CORRUPT. If some other error (malloc, IO
** etc.) occurs, return the appropriate SQLite error code.
**
** Otherwise, if successful, set *pzBlock to point to a buffer containing
** the block read from the database, and *pnBlock to the size of the read
** block in bytes.
**
-** WARNING: The returned buffer is only valid until the next call to
+** WARNING: The returned buffer is only valid until the next call to
** sqlite3Fts3ReadBlock().
*/
SQLITE_PRIVATE int sqlite3Fts3ReadBlock(
@@ -110843,11 +104149,11 @@ SQLITE_PRIVATE int sqlite3Fts3ReadBlock(
if( pzBlock ){
sqlite3_bind_int64(pStmt, 1, iBlock);
- rc = sqlite3_step(pStmt);
+ rc = sqlite3_step(pStmt);
if( rc!=SQLITE_ROW ){
return (rc==SQLITE_DONE ? SQLITE_CORRUPT : rc);
}
-
+
*pnBlock = sqlite3_column_bytes(pStmt, 0);
*pzBlock = (char *)sqlite3_column_blob(pStmt, 0);
if( sqlite3_column_type(pStmt, 0)!=SQLITE_BLOB ){
@@ -110860,7 +104166,7 @@ SQLITE_PRIVATE int sqlite3Fts3ReadBlock(
/*
** Set *ppStmt to a statement handle that may be used to iterate through
** all rows in the %_segdir table, from oldest to newest. If successful,
-** return SQLITE_OK. If an error occurs while preparing the statement,
+** return SQLITE_OK. If an error occurs while preparing the statement,
** return an SQLite error code.
**
** There is only ever one instance of this SQL statement compiled for
@@ -110994,17 +104300,11 @@ static int fts3PendingListAppend(
**
** If successful, SQLITE_OK is returned. Otherwise, an SQLite error code.
*/
-static int fts3PendingTermsAdd(
- Fts3Table *p, /* FTS table into which text will be inserted */
- const char *zText, /* Text of document to be inseted */
- int iCol, /* Column number into which text is inserted */
- u32 *pnWord /* OUT: Number of tokens inserted */
-){
+static int fts3PendingTermsAdd(Fts3Table *p, const char *zText, int iCol){
int rc;
int iStart;
int iEnd;
int iPos;
- int nWord = 0;
char const *zToken;
int nToken;
@@ -111029,8 +104329,6 @@ static int fts3PendingTermsAdd(
){
PendingList *pList;
- if( iPos>=nWord ) nWord = iPos+1;
-
/* Positions cannot be negative; we use -1 as a terminator internally.
** Tokens must have a non-zero length.
*/
@@ -111045,7 +104343,7 @@ static int fts3PendingTermsAdd(
}
if( fts3PendingListAppend(&pList, p->iPrevDocid, iCol, iPos, &rc) ){
if( pList==fts3HashInsert(&p->pendingTerms, zToken, nToken, pList) ){
- /* Malloc failed while inserting the new entry. This can only
+ /* Malloc failed while inserting the new entry. This can only
** happen if there was no previous entry for this token.
*/
assert( 0==fts3HashFind(&p->pendingTerms, zToken, nToken) );
@@ -111059,12 +104357,11 @@ static int fts3PendingTermsAdd(
}
pModule->xClose(pCsr);
- *pnWord = nWord;
return (rc==SQLITE_DONE ? SQLITE_OK : rc);
}
-/*
-** Calling this function indicates that subsequent calls to
+/*
+** Calling this function indicates that subsequent calls to
** fts3PendingTermsAdd() are to add term/position-list pairs for the
** contents of the document with docid iDocid.
*/
@@ -111100,12 +104397,12 @@ SQLITE_PRIVATE void sqlite3Fts3PendingTermsClear(Fts3Table *p){
** Argument apVal is the same as the similarly named argument passed to
** fts3InsertData(). Parameter iDocid is the docid of the new row.
*/
-static int fts3InsertTerms(Fts3Table *p, sqlite3_value **apVal, u32 *aSz){
+static int fts3InsertTerms(Fts3Table *p, sqlite3_value **apVal){
int i; /* Iterator variable */
for(i=2; i<p->nColumn+2; i++){
const char *zText = (const char *)sqlite3_value_text(apVal[i]);
if( zText ){
- int rc = fts3PendingTermsAdd(p, zText, i-2, &aSz[i-2]);
+ int rc = fts3PendingTermsAdd(p, zText, i-2);
if( rc!=SQLITE_OK ){
return rc;
}
@@ -111169,8 +104466,8 @@ static int fts3InsertData(
if( rc!=SQLITE_OK ) return rc;
}
- /* Execute the statement to insert the record. Set *piDocid to the
- ** new docid value.
+ /* Execute the statement to insert the record. Set *piDocid to the
+ ** new docid value.
*/
sqlite3_step(pContentInsert);
rc = sqlite3_reset(pContentInsert);
@@ -111186,18 +104483,18 @@ static int fts3InsertData(
** pending terms.
*/
static int fts3DeleteAll(Fts3Table *p){
- int rc = SQLITE_OK; /* Return code */
+ int rc; /* Return code */
/* Discard the contents of the pending-terms hash table. */
sqlite3Fts3PendingTermsClear(p);
/* Delete everything from the %_content, %_segments and %_segdir tables. */
- fts3SqlExec(&rc, p, SQL_DELETE_ALL_CONTENT, 0);
- fts3SqlExec(&rc, p, SQL_DELETE_ALL_SEGMENTS, 0);
- fts3SqlExec(&rc, p, SQL_DELETE_ALL_SEGDIR, 0);
- if( p->bHasDocsize ){
- fts3SqlExec(&rc, p, SQL_DELETE_ALL_DOCSIZE, 0);
- fts3SqlExec(&rc, p, SQL_DELETE_ALL_STAT, 0);
+ rc = fts3SqlExec(p, SQL_DELETE_ALL_CONTENT, 0);
+ if( rc==SQLITE_OK ){
+ rc = fts3SqlExec(p, SQL_DELETE_ALL_SEGMENTS, 0);
+ }
+ if( rc==SQLITE_OK ){
+ rc = fts3SqlExec(p, SQL_DELETE_ALL_SEGDIR, 0);
}
return rc;
}
@@ -111207,27 +104504,20 @@ static int fts3DeleteAll(Fts3Table *p){
** (an integer) of a row about to be deleted. Remove all terms from the
** full-text index.
*/
-static void fts3DeleteTerms(
- int *pRC, /* Result code */
- Fts3Table *p, /* The FTS table to delete from */
- sqlite3_value **apVal, /* apVal[] contains the docid to be deleted */
- u32 *aSz /* Sizes of deleted document written here */
-){
+static int fts3DeleteTerms(Fts3Table *p, sqlite3_value **apVal){
int rc;
sqlite3_stmt *pSelect;
- if( *pRC ) return;
rc = fts3SqlStmt(p, SQL_SELECT_CONTENT_BY_ROWID, &pSelect, apVal);
if( rc==SQLITE_OK ){
if( SQLITE_ROW==sqlite3_step(pSelect) ){
int i;
for(i=1; i<=p->nColumn; i++){
const char *zText = (const char *)sqlite3_column_text(pSelect, i);
- rc = fts3PendingTermsAdd(p, zText, -1, &aSz[i-1]);
+ rc = fts3PendingTermsAdd(p, zText, -1);
if( rc!=SQLITE_OK ){
sqlite3_reset(pSelect);
- *pRC = rc;
- return;
+ return rc;
}
}
}
@@ -111235,7 +104525,7 @@ static void fts3DeleteTerms(
}else{
sqlite3_reset(pSelect);
}
- *pRC = rc;
+ return rc;
}
/*
@@ -111244,7 +104534,7 @@ static void fts3DeleteTerms(
*/
static int fts3SegmentMerge(Fts3Table *, int);
-/*
+/*
** This function allocates a new level iLevel index in the segdir table.
** Usually, indexes are allocated within a level sequentially starting
** with 0, so the allocated index is one greater than the value returned
@@ -111253,7 +104543,7 @@ static int fts3SegmentMerge(Fts3Table *, int);
** SELECT max(idx) FROM %_segdir WHERE level = :iLevel
**
** However, if there are already FTS3_MERGE_COUNT indexes at the requested
-** level, they are merged into a single level (iLevel+1) segment and the
+** level, they are merged into a single level (iLevel+1) segment and the
** allocated index is 0.
**
** If successful, *piIdx is set to the allocated index slot and SQLITE_OK
@@ -111337,7 +104627,7 @@ static int fts3SegReaderNext(Fts3SegReader *pReader){
pReader->aNode = (char *)sqlite3_column_blob(pReader->pStmt, 0);
pNext = pReader->aNode;
}
-
+
pNext += sqlite3Fts3GetVarint32(pNext, &nPrefix);
pNext += sqlite3Fts3GetVarint32(pNext, &nSuffix);
@@ -111375,8 +104665,8 @@ static void fts3SegReaderFirstDocid(Fts3SegReader *pReader){
/*
** Advance the SegReader to point to the next docid in the doclist
** associated with the current term.
-**
-** If arguments ppOffsetList and pnOffsetList are not NULL, then
+**
+** If arguments ppOffsetList and pnOffsetList are not NULL, then
** *ppOffsetList is set to point to the first column-offset list
** in the doclist entry (i.e. immediately past the docid varint).
** *pnOffsetList is set to the length of the set of column-offset
@@ -111420,7 +104710,7 @@ static void fts3SegReaderNextDocid(
}
/*
-** Free all allocations associated with the iterator passed as the
+** Free all allocations associated with the iterator passed as the
** second argument.
*/
SQLITE_PRIVATE void sqlite3Fts3SegReaderFree(Fts3Table *p, Fts3SegReader *pReader){
@@ -111634,7 +104924,7 @@ SQLITE_PRIVATE int sqlite3Fts3SegReaderPending(
** The second argument to this function is expected to be a statement of
** the form:
**
-** SELECT
+** SELECT
** idx, -- col 0
** start_block, -- col 1
** leaves_end_block, -- col 2
@@ -111644,7 +104934,7 @@ SQLITE_PRIVATE int sqlite3Fts3SegReaderPending(
**
** This function allocates and initializes a Fts3SegReader structure to
** iterate through the terms stored in the segment identified by the
-** current row that pStmt is pointing to.
+** current row that pStmt is pointing to.
**
** If successful, the Fts3SegReader is left pointing to the first term
** in the segment and SQLITE_OK is returned. Otherwise, an SQLite error
@@ -111656,7 +104946,7 @@ static int fts3SegReaderNew(
int iAge, /* Segment "age". */
Fts3SegReader **ppReader /* OUT: Allocated Fts3SegReader */
){
- return sqlite3Fts3SegReaderNew(p, iAge,
+ return sqlite3Fts3SegReaderNew(p, iAge,
sqlite3_column_int64(pStmt, 1),
sqlite3_column_int64(pStmt, 2),
sqlite3_column_int64(pStmt, 3),
@@ -111667,7 +104957,7 @@ static int fts3SegReaderNew(
}
/*
-** Compare the entries pointed to by two Fts3SegReader structures.
+** Compare the entries pointed to by two Fts3SegReader structures.
** Comparison is as follows:
**
** 1) EOF is greater than not EOF.
@@ -111726,7 +105016,7 @@ static int fts3SegReaderDoclistCmp(Fts3SegReader *pLhs, Fts3SegReader *pRhs){
/*
** Compare the term that the Fts3SegReader object passed as the first argument
-** points to with the term specified by arguments zTerm and nTerm.
+** points to with the term specified by arguments zTerm and nTerm.
**
** If the pSeg iterator is already at EOF, return 0. Otherwise, return
** -ve if the pSeg term is less than zTerm/nTerm, 0 if the two terms are
@@ -111787,7 +105077,7 @@ static void fts3SegReaderSort(
#endif
}
-/*
+/*
** Insert a record into the %_segments table.
*/
static int fts3WriteSegment(
@@ -111807,7 +105097,7 @@ static int fts3WriteSegment(
return rc;
}
-/*
+/*
** Insert a record into the %_segdir table.
*/
static int fts3WriteSegdir(
@@ -111837,7 +105127,7 @@ static int fts3WriteSegdir(
/*
** Return the size of the common prefix (if any) shared by zPrev and
-** zNext, in bytes. For example,
+** zNext, in bytes. For example,
**
** fts3PrefixCompress("abc", 3, "abcdef", 6) // returns 3
** fts3PrefixCompress("abX", 3, "abcdef", 6) // returns 2
@@ -111861,7 +105151,7 @@ static int fts3PrefixCompress(
*/
static int fts3NodeAddTerm(
Fts3Table *p, /* Virtual table handle */
- SegmentNode **ppTree, /* IN/OUT: SegmentNode handle */
+ SegmentNode **ppTree, /* IN/OUT: SegmentNode handle */
int isCopyTerm, /* True if zTerm/nTerm is transient */
const char *zTerm, /* Pointer to buffer containing term */
int nTerm /* Size of term in bytes */
@@ -111870,7 +105160,7 @@ static int fts3NodeAddTerm(
int rc;
SegmentNode *pNew;
- /* First try to append the term to the current node. Return early if
+ /* First try to append the term to the current node. Return early if
** this is possible.
*/
if( pTree ){
@@ -111890,8 +105180,8 @@ static int fts3NodeAddTerm(
** and the static node buffer (p->nNodeSize bytes) is not large
** enough. Use a separately malloced buffer instead This wastes
** p->nNodeSize bytes, but since this scenario only comes about when
- ** the database contain two terms that share a prefix of almost 2KB,
- ** this is not expected to be a serious problem.
+ ** the database contain two terms that share a prefix of almost 2KB,
+ ** this is not expected to be a serious problem.
*/
assert( pTree->aData==(char *)&pTree[1] );
pTree->aData = (char *)sqlite3_malloc(nReq);
@@ -111935,7 +105225,7 @@ static int fts3NodeAddTerm(
** If this is the first node in the tree, the term is added to it.
**
** Otherwise, the term is not added to the new node, it is left empty for
- ** now. Instead, the term is inserted into the parent of pTree. If pTree
+ ** now. Instead, the term is inserted into the parent of pTree. If pTree
** has no parent, one is created here.
*/
pNew = (SegmentNode *)sqlite3_malloc(sizeof(SegmentNode) + p->nNodeSize);
@@ -111960,7 +105250,7 @@ static int fts3NodeAddTerm(
pTree->zMalloc = 0;
}else{
pNew->pLeftmost = pNew;
- rc = fts3NodeAddTerm(p, &pNew, isCopyTerm, zTerm, nTerm);
+ rc = fts3NodeAddTerm(p, &pNew, isCopyTerm, zTerm, nTerm);
}
*ppTree = pNew;
@@ -111971,8 +105261,8 @@ static int fts3NodeAddTerm(
** Helper function for fts3NodeWrite().
*/
static int fts3TreeFinishNode(
- SegmentNode *pTree,
- int iHeight,
+ SegmentNode *pTree,
+ int iHeight,
sqlite3_int64 iLeftChild
){
int nStart;
@@ -111985,15 +105275,15 @@ static int fts3TreeFinishNode(
/*
** Write the buffer for the segment node pTree and all of its peers to the
-** database. Then call this function recursively to write the parent of
-** pTree and its peers to the database.
+** database. Then call this function recursively to write the parent of
+** pTree and its peers to the database.
**
** Except, if pTree is a root node, do not write it to the database. Instead,
** set output variables *paRoot and *pnRoot to contain the root node.
**
** If successful, SQLITE_OK is returned and output variable *piLast is
** set to the largest blockid written to the database (or zero if no
-** blocks were written to the db). Otherwise, an SQLite error code is
+** blocks were written to the db). Otherwise, an SQLite error code is
** returned.
*/
static int fts3NodeWrite(
@@ -112021,7 +105311,7 @@ static int fts3NodeWrite(
for(pIter=pTree->pLeftmost; pIter && rc==SQLITE_OK; pIter=pIter->pRight){
int nStart = fts3TreeFinishNode(pIter, iHeight, iNextLeaf);
int nWrite = pIter->nData - nStart;
-
+
rc = fts3WriteSegment(p, iNextFree, &pIter->aData[nStart], nWrite);
iNextFree++;
iNextLeaf += (pIter->nEntry+1);
@@ -112067,7 +105357,7 @@ static void fts3NodeFree(SegmentNode *pTree){
*/
static int fts3SegWriterAdd(
Fts3Table *p, /* Virtual table handle */
- SegmentWriter **ppWriter, /* IN/OUT: SegmentWriter handle */
+ SegmentWriter **ppWriter, /* IN/OUT: SegmentWriter handle */
int isCopyTerm, /* True if buffer zTerm must be copied */
const char *zTerm, /* Pointer to buffer containing term */
int nTerm, /* Size of term in bytes */
@@ -112235,7 +105525,7 @@ static int fts3SegWriterFlush(
}
/*
-** Release all memory held by the SegmentWriter object passed as the
+** Release all memory held by the SegmentWriter object passed as the
** first argument.
*/
static void fts3SegWriterFree(SegmentWriter *pWriter){
@@ -112313,9 +105603,9 @@ static int fts3SegmentCountMax(Fts3Table *p, int *pnSegment, int *pnMax){
** This function is used after merging multiple segments into a single large
** segment to delete the old, now redundant, segment b-trees. Specifically,
** it:
-**
-** 1) Deletes all %_segments entries for the segments associated with
-** each of the SegReader objects in the array passed as the third
+**
+** 1) Deletes all %_segments entries for the segments associated with
+** each of the SegReader objects in the array passed as the third
** argument, and
**
** 2) deletes all %_segdir entries with level iLevel, or all %_segdir
@@ -112355,14 +105645,14 @@ static int fts3DeleteSegdir(
rc = sqlite3_reset(pDelete);
}
}else{
- fts3SqlExec(&rc, p, SQL_DELETE_ALL_SEGDIR, 0);
+ rc = fts3SqlExec(p, SQL_DELETE_ALL_SEGDIR, 0);
}
return rc;
}
/*
-** When this function is called, buffer *ppList (size *pnList bytes) contains
+** When this function is called, buffer *ppList (size *pnList bytes) contains
** a position list that may (or may not) feature multiple columns. This
** function adjusts the pointer *ppList and the length *pnList so that they
** identify the subset of the position list that corresponds to column iCol.
@@ -112385,7 +105675,7 @@ static void fts3ColumnFilter(
while( 1 ){
char c = 0;
while( p<pEnd && (c | *p)&0xFE ) c = *p++ & 0x80;
-
+
if( iCol==iCurrent ){
nList = (int)(p - pList);
break;
@@ -112405,7 +105695,7 @@ static void fts3ColumnFilter(
}
/*
-** sqlite3Fts3SegReaderIterate() callback used when merging multiple
+** sqlite3Fts3SegReaderIterate() callback used when merging multiple
** segments to create a single, larger segment.
*/
static int fts3MergeCallback(
@@ -112437,12 +105727,12 @@ static int fts3FlushCallback(
}
/*
-** This function is used to iterate through a contiguous set of terms
-** stored in the full-text index. It merges data contained in one or
+** This function is used to iterate through a contiguous set of terms
+** stored in the full-text index. It merges data contained in one or
** more segments to support this.
**
** The second argument is passed an array of pointers to SegReader objects
-** allocated with sqlite3Fts3SegReaderNew(). This function merges the range
+** allocated with sqlite3Fts3SegReaderNew(). This function merges the range
** of terms selected by each SegReader. If a single term is present in
** more than one segment, the associated doclists are merged. For each
** term and (possibly merged) doclist in the merged range, the callback
@@ -112484,7 +105774,7 @@ SQLITE_PRIVATE int sqlite3Fts3SegReaderIterate(
*/
if( nSegment==0 ) goto finished;
- /* If the Fts3SegFilter defines a specific term (or term prefix) to search
+ /* If the Fts3SegFilter defines a specific term (or term prefix) to search
** for, then advance each segment iterator until it points to a term of
** equal or greater value than the specified term. This prevents many
** unnecessary merge/sort operations for the case where single segment
@@ -112508,24 +105798,24 @@ SQLITE_PRIVATE int sqlite3Fts3SegReaderIterate(
int nMerge = 1;
/* If this is a prefix-search, and if the term that apSegment[0] points
- ** to does not share a suffix with pFilter->zTerm/nTerm, then all
+ ** to does not share a suffix with pFilter->zTerm/nTerm, then all
** required callbacks have been made. In this case exit early.
**
** Similarly, if this is a search for an exact match, and the first term
** of segment apSegment[0] is not a match, exit early.
*/
if( pFilter->zTerm ){
- if( nTerm<pFilter->nTerm
+ if( nTerm<pFilter->nTerm
|| (!isPrefix && nTerm>pFilter->nTerm)
- || memcmp(zTerm, pFilter->zTerm, pFilter->nTerm)
+ || memcmp(zTerm, pFilter->zTerm, pFilter->nTerm)
){
goto finished;
}
}
- while( nMerge<nSegment
+ while( nMerge<nSegment
&& apSegment[nMerge]->aNode
- && apSegment[nMerge]->nTerm==nTerm
+ && apSegment[nMerge]->nTerm==nTerm
&& 0==memcmp(zTerm, apSegment[nMerge]->zTerm, nTerm)
){
nMerge++;
@@ -112619,14 +105909,14 @@ SQLITE_PRIVATE int sqlite3Fts3SegReaderIterate(
}
/*
-** Merge all level iLevel segments in the database into a single
+** Merge all level iLevel segments in the database into a single
** iLevel+1 segment. Or, if iLevel<0, merge all segments into a
-** single segment with a level equal to the numerically largest level
+** single segment with a level equal to the numerically largest level
** currently present in the database.
**
** If this function is called with iLevel<0, but there is only one
-** segment in the database, SQLITE_DONE is returned immediately.
-** Otherwise, if successful, SQLITE_OK is returned. If an error occurs,
+** segment in the database, SQLITE_DONE is returned immediately.
+** Otherwise, if successful, SQLITE_OK is returned. If an error occurs,
** an SQLite error code is returned.
*/
static int fts3SegmentMerge(Fts3Table *p, int iLevel){
@@ -112643,7 +105933,7 @@ static int fts3SegmentMerge(Fts3Table *p, int iLevel){
if( iLevel<0 ){
/* This call is to merge all segments in the database to a single
- ** segment. The level of the new segment is equal to the the numerically
+ ** segment. The level of the new segment is equal to the the numerically
** greatest segment level currently present in the database. The index
** of the new segment is always 0.
*/
@@ -112659,7 +105949,7 @@ static int fts3SegmentMerge(Fts3Table *p, int iLevel){
}else{
/* This call is to merge all segments at level iLevel. Find the next
** available segment index at level iLevel+1. The call to
- ** fts3AllocateSegdirIdx() will merge the segments at level iLevel+1 to
+ ** fts3AllocateSegdirIdx() will merge the segments at level iLevel+1 to
** a single iLevel+2 segment if necessary.
*/
iNewLevel = iLevel+1;
@@ -112679,9 +105969,9 @@ static int fts3SegmentMerge(Fts3Table *p, int iLevel){
}
memset(apSegment, 0, sizeof(Fts3SegReader *)*nSegment);
- /* Allocate a Fts3SegReader structure for each segment being merged. A
- ** Fts3SegReader stores the state data required to iterate through all
- ** entries on all leaves of a single segment.
+ /* Allocate a Fts3SegReader structure for each segment being merged. A
+ ** Fts3SegReader stores the state data required to iterate through all
+ ** entries on all leaves of a single segment.
*/
assert( SQL_SELECT_LEVEL+1==SQL_SELECT_ALL_LEVEL);
rc = fts3SqlStmt(p, SQL_SELECT_LEVEL+(iLevel<0), &pStmt, 0);
@@ -112728,7 +106018,7 @@ static int fts3SegmentMerge(Fts3Table *p, int iLevel){
}
-/*
+/*
** Flush the contents of pendingTerms to a level 0 segment.
*/
SQLITE_PRIVATE int sqlite3Fts3PendingTermsFlush(Fts3Table *p){
@@ -112752,7 +106042,7 @@ SQLITE_PRIVATE int sqlite3Fts3PendingTermsFlush(Fts3Table *p){
*/
rc = fts3AllocateSegdirIdx(p, 0, &idx);
- /* If no errors have occured, iterate through the contents of the
+ /* If no errors have occured, iterate through the contents of the
** pending-terms hash table using the Fts3SegReader iterator. The callback
** writes each term (along with its doclist) to the database via the
** SegmentWriter handle pWriter.
@@ -112784,216 +106074,11 @@ SQLITE_PRIVATE int sqlite3Fts3PendingTermsFlush(Fts3Table *p){
}
/*
-** Encode N integers as varints into a blob.
-*/
-static void fts3EncodeIntArray(
- int N, /* The number of integers to encode */
- u32 *a, /* The integer values */
- char *zBuf, /* Write the BLOB here */
- int *pNBuf /* Write number of bytes if zBuf[] used here */
-){
- int i, j;
- for(i=j=0; i<N; i++){
- j += sqlite3Fts3PutVarint(&zBuf[j], (sqlite3_int64)a[i]);
- }
- *pNBuf = j;
-}
-
-/*
-** Decode a blob of varints into N integers
-*/
-static void fts3DecodeIntArray(
- int N, /* The number of integers to decode */
- u32 *a, /* Write the integer values */
- const char *zBuf, /* The BLOB containing the varints */
- int nBuf /* size of the BLOB */
-){
- int i, j;
- UNUSED_PARAMETER(nBuf);
- for(i=j=0; i<N; i++){
- sqlite3_int64 x;
- j += sqlite3Fts3GetVarint(&zBuf[j], &x);
- assert(j<=nBuf);
- a[i] = (u32)(x & 0xffffffff);
- }
-}
-
-/*
-** Fill in the document size auxiliary information for the matchinfo
-** structure. The auxiliary information is:
-**
-** N Total number of documents in the full-text index
-** a0 Average length of column 0 over the whole index
-** n0 Length of column 0 on the matching row
-** ...
-** aM Average length of column M over the whole index
-** nM Length of column M on the matching row
-**
-** The fts3MatchinfoDocsizeLocal() routine fills in the nX values.
-** The fts3MatchinfoDocsizeGlobal() routine fills in N and the aX values.
-*/
-SQLITE_PRIVATE int sqlite3Fts3MatchinfoDocsizeLocal(Fts3Cursor *pCur, u32 *a){
- const char *pBlob; /* The BLOB holding %_docsize info */
- int nBlob; /* Size of the BLOB */
- sqlite3_stmt *pStmt; /* Statement for reading and writing */
- int i, j; /* Loop counters */
- sqlite3_int64 x; /* Varint value */
- int rc; /* Result code from subfunctions */
- Fts3Table *p; /* The FTS table */
-
- p = (Fts3Table*)pCur->base.pVtab;
- rc = fts3SqlStmt(p, SQL_SELECT_DOCSIZE, &pStmt, 0);
- if( rc ){
- return rc;
- }
- sqlite3_bind_int64(pStmt, 1, pCur->iPrevId);
- if( sqlite3_step(pStmt)==SQLITE_ROW ){
- nBlob = sqlite3_column_bytes(pStmt, 0);
- pBlob = (const char*)sqlite3_column_blob(pStmt, 0);
- for(i=j=0; i<p->nColumn && j<nBlob; i++){
- j = sqlite3Fts3GetVarint(&pBlob[j], &x);
- a[2+i*2] = (u32)(x & 0xffffffff);
- }
- }
- sqlite3_reset(pStmt);
- return SQLITE_OK;
-}
-SQLITE_PRIVATE int sqlite3Fts3MatchinfoDocsizeGlobal(Fts3Cursor *pCur, u32 *a){
- const char *pBlob; /* The BLOB holding %_stat info */
- int nBlob; /* Size of the BLOB */
- sqlite3_stmt *pStmt; /* Statement for reading and writing */
- int i, j; /* Loop counters */
- sqlite3_int64 x; /* Varint value */
- int nDoc; /* Number of documents */
- int rc; /* Result code from subfunctions */
- Fts3Table *p; /* The FTS table */
-
- p = (Fts3Table*)pCur->base.pVtab;
- rc = fts3SqlStmt(p, SQL_SELECT_DOCTOTAL, &pStmt, 0);
- if( rc ){
- return rc;
- }
- if( sqlite3_step(pStmt)==SQLITE_ROW ){
- nBlob = sqlite3_column_bytes(pStmt, 0);
- pBlob = (const char*)sqlite3_column_blob(pStmt, 0);
- j = sqlite3Fts3GetVarint(pBlob, &x);
- a[0] = nDoc = (u32)(x & 0xffffffff);
- for(i=0; i<p->nColumn && j<nBlob; i++){
- j = sqlite3Fts3GetVarint(&pBlob[j], &x);
- a[1+i*2] = ((u32)(x & 0xffffffff) + nDoc/2)/nDoc;
- }
- }
- sqlite3_reset(pStmt);
- return SQLITE_OK;
-}
-
-/*
-** Insert the sizes (in tokens) for each column of the document
-** with docid equal to p->iPrevDocid. The sizes are encoded as
-** a blob of varints.
-*/
-static void fts3InsertDocsize(
- int *pRC, /* Result code */
- Fts3Table *p, /* Table into which to insert */
- u32 *aSz /* Sizes of each column */
-){
- char *pBlob; /* The BLOB encoding of the document size */
- int nBlob; /* Number of bytes in the BLOB */
- sqlite3_stmt *pStmt; /* Statement used to insert the encoding */
- int rc; /* Result code from subfunctions */
-
- if( *pRC ) return;
- pBlob = sqlite3_malloc( 10*p->nColumn );
- if( pBlob==0 ){
- *pRC = SQLITE_NOMEM;
- return;
- }
- fts3EncodeIntArray(p->nColumn, aSz, pBlob, &nBlob);
- rc = fts3SqlStmt(p, SQL_REPLACE_DOCSIZE, &pStmt, 0);
- if( rc ){
- sqlite3_free(pBlob);
- *pRC = rc;
- return;
- }
- sqlite3_bind_int64(pStmt, 1, p->iPrevDocid);
- sqlite3_bind_blob(pStmt, 2, pBlob, nBlob, sqlite3_free);
- sqlite3_step(pStmt);
- *pRC = sqlite3_reset(pStmt);
-}
-
-/*
-** Update the 0 record of the %_stat table so that it holds a blob
-** which contains the document count followed by the cumulative
-** document sizes for all columns.
-*/
-static void fts3UpdateDocTotals(
- int *pRC, /* The result code */
- Fts3Table *p, /* Table being updated */
- u32 *aSzIns, /* Size increases */
- u32 *aSzDel, /* Size decreases */
- int nChng /* Change in the number of documents */
-){
- char *pBlob; /* Storage for BLOB written into %_stat */
- int nBlob; /* Size of BLOB written into %_stat */
- u32 *a; /* Array of integers that becomes the BLOB */
- sqlite3_stmt *pStmt; /* Statement for reading and writing */
- int i; /* Loop counter */
- int rc; /* Result code from subfunctions */
-
- if( *pRC ) return;
- a = sqlite3_malloc( (sizeof(u32)+10)*(p->nColumn+1) );
- if( a==0 ){
- *pRC = SQLITE_NOMEM;
- return;
- }
- pBlob = (char*)&a[p->nColumn+1];
- rc = fts3SqlStmt(p, SQL_SELECT_DOCTOTAL, &pStmt, 0);
- if( rc ){
- sqlite3_free(a);
- *pRC = rc;
- return;
- }
- if( sqlite3_step(pStmt)==SQLITE_ROW ){
- fts3DecodeIntArray(p->nColumn+1, a,
- sqlite3_column_blob(pStmt, 0),
- sqlite3_column_bytes(pStmt, 0));
- }else{
- memset(a, 0, sizeof(u32)*(p->nColumn+1) );
- }
- sqlite3_reset(pStmt);
- if( nChng<0 && a[0]<(u32)(-nChng) ){
- a[0] = 0;
- }else{
- a[0] += nChng;
- }
- for(i=0; i<p->nColumn; i++){
- u32 x = a[i+1];
- if( x+aSzIns[i] < aSzDel[i] ){
- x = 0;
- }else{
- x = x + aSzIns[i] - aSzDel[i];
- }
- a[i+1] = x;
- }
- fts3EncodeIntArray(p->nColumn+1, a, pBlob, &nBlob);
- rc = fts3SqlStmt(p, SQL_REPLACE_DOCTOTAL, &pStmt, 0);
- if( rc ){
- sqlite3_free(a);
- *pRC = rc;
- return;
- }
- sqlite3_bind_blob(pStmt, 1, pBlob, nBlob, SQLITE_STATIC);
- sqlite3_step(pStmt);
- *pRC = sqlite3_reset(pStmt);
- sqlite3_free(a);
-}
-
-/*
** Handle a 'special' INSERT of the form:
**
** "INSERT INTO tbl(tbl) VALUES(<expr>)"
**
-** Argument pVal contains the result of <expr>. Currently the only
+** Argument pVal contains the result of <expr>. Currently the only
** meaningful value to insert is the text 'optimize'.
*/
static int fts3SpecialInsert(Fts3Table *p, sqlite3_value *pVal){
@@ -113039,17 +106124,8 @@ SQLITE_PRIVATE int sqlite3Fts3UpdateMethod(
int rc = SQLITE_OK; /* Return Code */
int isRemove = 0; /* True for an UPDATE or DELETE */
sqlite3_int64 iRemove = 0; /* Rowid removed by UPDATE or DELETE */
- u32 *aSzIns; /* Sizes of inserted documents */
- u32 *aSzDel; /* Sizes of deleted documents */
- int nChng = 0; /* Net change in number of documents */
- /* Allocate space to hold the change in document sizes */
- aSzIns = sqlite3_malloc( sizeof(aSzIns[0])*p->nColumn*2 );
- if( aSzIns==0 ) return SQLITE_NOMEM;
- aSzDel = &aSzIns[p->nColumn];
- memset(aSzIns, 0, sizeof(aSzIns[0])*p->nColumn*2);
-
/* If this is a DELETE or UPDATE operation, remove the old record. */
if( sqlite3_value_type(apVal[0])!=SQLITE_NULL ){
int isEmpty;
@@ -113065,19 +106141,18 @@ SQLITE_PRIVATE int sqlite3Fts3UpdateMethod(
isRemove = 1;
iRemove = sqlite3_value_int64(apVal[0]);
rc = fts3PendingTermsDocid(p, iRemove);
- fts3DeleteTerms(&rc, p, apVal, aSzDel);
- fts3SqlExec(&rc, p, SQL_DELETE_CONTENT, apVal);
- if( p->bHasDocsize ){
- fts3SqlExec(&rc, p, SQL_DELETE_DOCSIZE, apVal);
- nChng--;
+ if( rc==SQLITE_OK ){
+ rc = fts3DeleteTerms(p, apVal);
+ if( rc==SQLITE_OK ){
+ rc = fts3SqlExec(p, SQL_DELETE_CONTENT, apVal);
+ }
}
}
}
}else if( sqlite3_value_type(apVal[p->nColumn+2])!=SQLITE_NULL ){
- sqlite3_free(aSzIns);
return fts3SpecialInsert(p, apVal[p->nColumn+2]);
}
-
+
/* If this is an INSERT or UPDATE operation, insert the new record. */
if( nArg>1 && rc==SQLITE_OK ){
rc = fts3InsertData(p, apVal, pRowid);
@@ -113085,26 +106160,17 @@ SQLITE_PRIVATE int sqlite3Fts3UpdateMethod(
rc = fts3PendingTermsDocid(p, *pRowid);
}
if( rc==SQLITE_OK ){
- rc = fts3InsertTerms(p, apVal, aSzIns);
+ rc = fts3InsertTerms(p, apVal);
}
- if( p->bHasDocsize ){
- nChng++;
- fts3InsertDocsize(&rc, p, aSzIns);
- }
- }
-
- if( p->bHasDocsize ){
- fts3UpdateDocTotals(&rc, p, aSzIns, aSzDel, nChng);
}
- sqlite3_free(aSzIns);
return rc;
}
-/*
+/*
** Flush any data in the pending-terms hash table to disk. If successful,
-** merge all segments in the database (including the new segment, if
-** there was any data to flush) into a single segment.
+** merge all segments in the database (including the new segment, if
+** there was any data to flush) into a single segment.
*/
SQLITE_PRIVATE int sqlite3Fts3Optimize(Fts3Table *p){
int rc;
@@ -113144,521 +106210,1024 @@ SQLITE_PRIVATE int sqlite3Fts3Optimize(Fts3Table *p){
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
+typedef struct Snippet Snippet;
/*
-** Used as an fts3ExprIterate() context when loading phrase doclists to
-** Fts3Expr.aDoclist[]/nDoclist.
+** An instance of the following structure keeps track of generated
+** matching-word offset information and snippets.
*/
-typedef struct LoadDoclistCtx LoadDoclistCtx;
-struct LoadDoclistCtx {
- Fts3Table *pTab; /* FTS3 Table */
- int nPhrase; /* Number of phrases seen so far */
- int nToken; /* Number of tokens seen so far */
+struct Snippet {
+ int nMatch; /* Total number of matches */
+ int nAlloc; /* Space allocated for aMatch[] */
+ struct snippetMatch { /* One entry for each matching term */
+ char snStatus; /* Status flag for use while constructing snippets */
+ short int nByte; /* Number of bytes in the term */
+ short int iCol; /* The column that contains the match */
+ short int iTerm; /* The index in Query.pTerms[] of the matching term */
+ int iToken; /* The index of the matching document token */
+ int iStart; /* The offset to the first character of the term */
+ } *aMatch; /* Points to space obtained from malloc */
+ char *zOffset; /* Text rendering of aMatch[] */
+ int nOffset; /* strlen(zOffset) */
+ char *zSnippet; /* Snippet text */
+ int nSnippet; /* strlen(zSnippet) */
};
-/*
-** The following types are used as part of the implementation of the
-** fts3BestSnippet() routine.
+
+/* It is not safe to call isspace(), tolower(), or isalnum() on
+** hi-bit-set characters. This is the same solution used in the
+** tokenizer.
*/
-typedef struct SnippetIter SnippetIter;
-typedef struct SnippetPhrase SnippetPhrase;
-typedef struct SnippetFragment SnippetFragment;
+static int fts3snippetIsspace(char c){
+ return (c&0x80)==0 ? isspace(c) : 0;
+}
-struct SnippetIter {
- Fts3Cursor *pCsr; /* Cursor snippet is being generated from */
- int iCol; /* Extract snippet from this column */
- int nSnippet; /* Requested snippet length (in tokens) */
- int nPhrase; /* Number of phrases in query */
- SnippetPhrase *aPhrase; /* Array of size nPhrase */
- int iCurrent; /* First token of current snippet */
-};
-struct SnippetPhrase {
- int nToken; /* Number of tokens in phrase */
- char *pList; /* Pointer to start of phrase position list */
- int iHead; /* Next value in position list */
- char *pHead; /* Position list data following iHead */
- int iTail; /* Next value in trailing position list */
- char *pTail; /* Position list data following iTail */
-};
+/*
+** A StringBuffer object holds a zero-terminated string that grows
+** arbitrarily by appending. Space to hold the string is obtained
+** from sqlite3_malloc(). After any memory allocation failure,
+** StringBuffer.z is set to NULL and no further allocation is attempted.
+*/
+typedef struct StringBuffer {
+ char *z; /* Text of the string. Space from malloc. */
+ int nUsed; /* Number bytes of z[] used, not counting \000 terminator */
+ int nAlloc; /* Bytes allocated for z[] */
+} StringBuffer;
-struct SnippetFragment {
- int iCol; /* Column snippet is extracted from */
- int iPos; /* Index of first token in snippet */
- u64 covered; /* Mask of query phrases covered */
- u64 hlmask; /* Mask of snippet terms to highlight */
-};
/*
-** This type is used as an fts3ExprIterate() context object while
-** accumulating the data returned by the matchinfo() function.
+** Initialize a new StringBuffer.
*/
-typedef struct MatchInfo MatchInfo;
-struct MatchInfo {
- Fts3Cursor *pCursor; /* FTS3 Cursor */
- int nCol; /* Number of columns in table */
- u32 *aMatchinfo; /* Pre-allocated buffer */
-};
+static void fts3SnippetSbInit(StringBuffer *p){
+ p->nAlloc = 100;
+ p->nUsed = 0;
+ p->z = sqlite3_malloc( p->nAlloc );
+}
+/*
+** Append text to the string buffer.
+*/
+static void fts3SnippetAppend(StringBuffer *p, const char *zNew, int nNew){
+ if( p->z==0 ) return;
+ if( nNew<0 ) nNew = (int)strlen(zNew);
+ if( p->nUsed + nNew >= p->nAlloc ){
+ int nAlloc;
+ char *zNew;
+ nAlloc = p->nUsed + nNew + p->nAlloc;
+ zNew = sqlite3_realloc(p->z, nAlloc);
+ if( zNew==0 ){
+ sqlite3_free(p->z);
+ p->z = 0;
+ return;
+ }
+ p->z = zNew;
+ p->nAlloc = nAlloc;
+ }
+ memcpy(&p->z[p->nUsed], zNew, nNew);
+ p->nUsed += nNew;
+ p->z[p->nUsed] = 0;
+}
-/*
-** The snippet() and offsets() functions both return text values. An instance
-** of the following structure is used to accumulate those values while the
-** functions are running. See fts3StringAppend() for details.
+/* If the StringBuffer ends in something other than white space, add a
+** single space character to the end.
*/
-typedef struct StrBuffer StrBuffer;
-struct StrBuffer {
- char *z; /* Pointer to buffer containing string */
- int n; /* Length of z in bytes (excl. nul-term) */
- int nAlloc; /* Allocated size of buffer z in bytes */
-};
+static void fts3SnippetAppendWhiteSpace(StringBuffer *p){
+ if( p->z && p->nUsed && !fts3snippetIsspace(p->z[p->nUsed-1]) ){
+ fts3SnippetAppend(p, " ", 1);
+ }
+}
+/* Remove white space from the end of the StringBuffer */
+static void fts3SnippetTrimWhiteSpace(StringBuffer *p){
+ if( p->z ){
+ while( p->nUsed && fts3snippetIsspace(p->z[p->nUsed-1]) ){
+ p->nUsed--;
+ }
+ p->z[p->nUsed] = 0;
+ }
+}
-/*
-** This function is used to help iterate through a position-list. A position
-** list is a list of unique integers, sorted from smallest to largest. Each
-** element of the list is represented by an FTS3 varint that takes the value
-** of the difference between the current element and the previous one plus
-** two. For example, to store the position-list:
-**
-** 4 9 113
-**
-** the three varints:
-**
-** 6 7 106
-**
-** are encoded.
-**
-** When this function is called, *pp points to the start of an element of
-** the list. *piPos contains the value of the previous entry in the list.
-** After it returns, *piPos contains the value of the next element of the
-** list and *pp is advanced to the following varint.
+/*
+** Release all memory associated with the Snippet structure passed as
+** an argument.
*/
-static void fts3GetDeltaPosition(char **pp, int *piPos){
- int iVal;
- *pp += sqlite3Fts3GetVarint32(*pp, &iVal);
- *piPos += (iVal-2);
+static void fts3SnippetFree(Snippet *p){
+ if( p ){
+ sqlite3_free(p->aMatch);
+ sqlite3_free(p->zOffset);
+ sqlite3_free(p->zSnippet);
+ sqlite3_free(p);
+ }
}
/*
-** Helper function for fts3ExprIterate() (see below).
+** Append a single entry to the p->aMatch[] log.
*/
-static int fts3ExprIterate2(
- Fts3Expr *pExpr, /* Expression to iterate phrases of */
- int *piPhrase, /* Pointer to phrase counter */
- int (*x)(Fts3Expr*,int,void*), /* Callback function to invoke for phrases */
- void *pCtx /* Second argument to pass to callback */
+static int snippetAppendMatch(
+ Snippet *p, /* Append the entry to this snippet */
+ int iCol, int iTerm, /* The column and query term */
+ int iToken, /* Matching token in document */
+ int iStart, int nByte /* Offset and size of the match */
){
- int rc; /* Return code */
- int eType = pExpr->eType; /* Type of expression node pExpr */
+ int i;
+ struct snippetMatch *pMatch;
+ if( p->nMatch+1>=p->nAlloc ){
+ struct snippetMatch *pNew;
+ p->nAlloc = p->nAlloc*2 + 10;
+ pNew = sqlite3_realloc(p->aMatch, p->nAlloc*sizeof(p->aMatch[0]) );
+ if( pNew==0 ){
+ p->aMatch = 0;
+ p->nMatch = 0;
+ p->nAlloc = 0;
+ return SQLITE_NOMEM;
+ }
+ p->aMatch = pNew;
+ }
+ i = p->nMatch++;
+ pMatch = &p->aMatch[i];
+ pMatch->iCol = (short)iCol;
+ pMatch->iTerm = (short)iTerm;
+ pMatch->iToken = iToken;
+ pMatch->iStart = iStart;
+ pMatch->nByte = (short)nByte;
+ return SQLITE_OK;
+}
- if( eType!=FTSQUERY_PHRASE ){
- assert( pExpr->pLeft && pExpr->pRight );
- rc = fts3ExprIterate2(pExpr->pLeft, piPhrase, x, pCtx);
- if( rc==SQLITE_OK && eType!=FTSQUERY_NOT ){
- rc = fts3ExprIterate2(pExpr->pRight, piPhrase, x, pCtx);
+/*
+** Sizing information for the circular buffer used in snippetOffsetsOfColumn()
+*/
+#define FTS3_ROTOR_SZ (32)
+#define FTS3_ROTOR_MASK (FTS3_ROTOR_SZ-1)
+
+/*
+** Function to iterate through the tokens of a compiled expression.
+**
+** Except, skip all tokens on the right-hand side of a NOT operator.
+** This function is used to find tokens as part of snippet and offset
+** generation and we do nt want snippets and offsets to report matches
+** for tokens on the RHS of a NOT.
+*/
+static int fts3NextExprToken(Fts3Expr **ppExpr, int *piToken){
+ Fts3Expr *p = *ppExpr;
+ int iToken = *piToken;
+ if( iToken<0 ){
+ /* In this case the expression p is the root of an expression tree.
+ ** Move to the first token in the expression tree.
+ */
+ while( p->pLeft ){
+ p = p->pLeft;
}
+ iToken = 0;
}else{
- rc = x(pExpr, *piPhrase, pCtx);
- (*piPhrase)++;
+ assert(p && p->eType==FTSQUERY_PHRASE );
+ if( iToken<(p->pPhrase->nToken-1) ){
+ iToken++;
+ }else{
+ iToken = 0;
+ while( p->pParent && p->pParent->pLeft!=p ){
+ assert( p->pParent->pRight==p );
+ p = p->pParent;
+ }
+ p = p->pParent;
+ if( p ){
+ assert( p->pRight!=0 );
+ p = p->pRight;
+ while( p->pLeft ){
+ p = p->pLeft;
+ }
+ }
+ }
}
- return rc;
+
+ *ppExpr = p;
+ *piToken = iToken;
+ return p?1:0;
}
/*
-** Iterate through all phrase nodes in an FTS3 query, except those that
-** are part of a sub-tree that is the right-hand-side of a NOT operator.
-** For each phrase node found, the supplied callback function is invoked.
-**
-** If the callback function returns anything other than SQLITE_OK,
-** the iteration is abandoned and the error code returned immediately.
-** Otherwise, SQLITE_OK is returned after a callback has been made for
-** all eligible phrase nodes.
+** Return TRUE if the expression node pExpr is located beneath the
+** RHS of a NOT operator.
*/
-static int fts3ExprIterate(
- Fts3Expr *pExpr, /* Expression to iterate phrases of */
- int (*x)(Fts3Expr*,int,void*), /* Callback function to invoke for phrases */
- void *pCtx /* Second argument to pass to callback */
+static int fts3ExprBeneathNot(Fts3Expr *p){
+ Fts3Expr *pParent;
+ while( p ){
+ pParent = p->pParent;
+ if( pParent && pParent->eType==FTSQUERY_NOT && pParent->pRight==p ){
+ return 1;
+ }
+ p = pParent;
+ }
+ return 0;
+}
+
+/*
+** Add entries to pSnippet->aMatch[] for every match that occurs against
+** document zDoc[0..nDoc-1] which is stored in column iColumn.
+*/
+static int snippetOffsetsOfColumn(
+ Fts3Cursor *pCur, /* The fulltest search cursor */
+ Snippet *pSnippet, /* The Snippet object to be filled in */
+ int iColumn, /* Index of fulltext table column */
+ const char *zDoc, /* Text of the fulltext table column */
+ int nDoc /* Length of zDoc in bytes */
){
- int iPhrase = 0; /* Variable used as the phrase counter */
- return fts3ExprIterate2(pExpr, &iPhrase, x, pCtx);
+ const sqlite3_tokenizer_module *pTModule; /* The tokenizer module */
+ sqlite3_tokenizer *pTokenizer; /* The specific tokenizer */
+ sqlite3_tokenizer_cursor *pTCursor; /* Tokenizer cursor */
+ Fts3Table *pVtab; /* The full text index */
+ int nColumn; /* Number of columns in the index */
+ int i, j; /* Loop counters */
+ int rc; /* Return code */
+ unsigned int match, prevMatch; /* Phrase search bitmasks */
+ const char *zToken; /* Next token from the tokenizer */
+ int nToken; /* Size of zToken */
+ int iBegin, iEnd, iPos; /* Offsets of beginning and end */
+
+ /* The following variables keep a circular buffer of the last
+ ** few tokens */
+ unsigned int iRotor = 0; /* Index of current token */
+ int iRotorBegin[FTS3_ROTOR_SZ]; /* Beginning offset of token */
+ int iRotorLen[FTS3_ROTOR_SZ]; /* Length of token */
+
+ pVtab = (Fts3Table *)pCur->base.pVtab;
+ nColumn = pVtab->nColumn;
+ pTokenizer = pVtab->pTokenizer;
+ pTModule = pTokenizer->pModule;
+ rc = pTModule->xOpen(pTokenizer, zDoc, nDoc, &pTCursor);
+ if( rc ) return rc;
+ pTCursor->pTokenizer = pTokenizer;
+
+ prevMatch = 0;
+ while( (rc = pTModule->xNext(pTCursor, &zToken, &nToken,
+ &iBegin, &iEnd, &iPos))==SQLITE_OK ){
+ Fts3Expr *pIter = pCur->pExpr;
+ int iIter = -1;
+ iRotorBegin[iRotor&FTS3_ROTOR_MASK] = iBegin;
+ iRotorLen[iRotor&FTS3_ROTOR_MASK] = iEnd-iBegin;
+ match = 0;
+ for(i=0; i<(FTS3_ROTOR_SZ-1) && fts3NextExprToken(&pIter, &iIter); i++){
+ int nPhrase; /* Number of tokens in current phrase */
+ struct PhraseToken *pToken; /* Current token */
+ int iCol; /* Column index */
+
+ if( fts3ExprBeneathNot(pIter) ) continue;
+ nPhrase = pIter->pPhrase->nToken;
+ pToken = &pIter->pPhrase->aToken[iIter];
+ iCol = pIter->pPhrase->iColumn;
+ if( iCol>=0 && iCol<nColumn && iCol!=iColumn ) continue;
+ if( pToken->n>nToken ) continue;
+ if( !pToken->isPrefix && pToken->n<nToken ) continue;
+ assert( pToken->n<=nToken );
+ if( memcmp(pToken->z, zToken, pToken->n) ) continue;
+ if( iIter>0 && (prevMatch & (1<<i))==0 ) continue;
+ match |= 1<<i;
+ if( i==(FTS3_ROTOR_SZ-2) || nPhrase==iIter+1 ){
+ for(j=nPhrase-1; j>=0; j--){
+ int k = (iRotor-j) & FTS3_ROTOR_MASK;
+ rc = snippetAppendMatch(pSnippet, iColumn, i-j, iPos-j,
+ iRotorBegin[k], iRotorLen[k]);
+ if( rc ) goto end_offsets_of_column;
+ }
+ }
+ }
+ prevMatch = match<<1;
+ iRotor++;
+ }
+end_offsets_of_column:
+ pTModule->xClose(pTCursor);
+ return rc==SQLITE_DONE ? SQLITE_OK : rc;
}
/*
-** The argument to this function is always a phrase node. Its doclist
-** (Fts3Expr.aDoclist[]) and the doclists associated with all phrase nodes
-** to the left of this one in the query tree have already been loaded.
+** Remove entries from the pSnippet structure to account for the NEAR
+** operator. When this is called, pSnippet contains the list of token
+** offsets produced by treating all NEAR operators as AND operators.
+** This function removes any entries that should not be present after
+** accounting for the NEAR restriction. For example, if the queried
+** document is:
**
-** If this phrase node is part of a series of phrase nodes joined by
-** NEAR operators (and is not the left-most of said series), then elements are
-** removed from the phrases doclist consistent with the NEAR restriction. If
-** required, elements may be removed from the doclists of phrases to the
-** left of this one that are part of the same series of NEAR operator
-** connected phrases.
+** "A B C D E A"
**
-** If an OOM error occurs, SQLITE_NOMEM is returned. Otherwise, SQLITE_OK.
+** and the query is:
+**
+** A NEAR/0 E
+**
+** then when this function is called the Snippet contains token offsets
+** 0, 4 and 5. This function removes the "0" entry (because the first A
+** is not near enough to an E).
+**
+** When this function is called, the value pointed to by parameter piLeft is
+** the integer id of the left-most token in the expression tree headed by
+** pExpr. This function increments *piLeft by the total number of tokens
+** in the expression tree headed by pExpr.
+**
+** Return 1 if any trimming occurs. Return 0 if no trimming is required.
*/
-static int fts3ExprNearTrim(Fts3Expr *pExpr){
- int rc = SQLITE_OK;
- Fts3Expr *pParent = pExpr->pParent;
-
- assert( pExpr->eType==FTSQUERY_PHRASE );
- while( rc==SQLITE_OK
- && pParent
- && pParent->eType==FTSQUERY_NEAR
- && pParent->pRight==pExpr
- ){
- /* This expression (pExpr) is the right-hand-side of a NEAR operator.
- ** Find the expression to the left of the same operator.
- */
- int nNear = pParent->nNear;
- Fts3Expr *pLeft = pParent->pLeft;
-
- if( pLeft->eType!=FTSQUERY_PHRASE ){
- assert( pLeft->eType==FTSQUERY_NEAR );
- assert( pLeft->pRight->eType==FTSQUERY_PHRASE );
- pLeft = pLeft->pRight;
+static int trimSnippetOffsets(
+ Fts3Expr *pExpr, /* The search expression */
+ Snippet *pSnippet, /* The set of snippet offsets to be trimmed */
+ int *piLeft /* Index of left-most token in pExpr */
+){
+ if( pExpr ){
+ if( trimSnippetOffsets(pExpr->pLeft, pSnippet, piLeft) ){
+ return 1;
}
- rc = sqlite3Fts3ExprNearTrim(pLeft, pExpr, nNear);
+ switch( pExpr->eType ){
+ case FTSQUERY_PHRASE:
+ *piLeft += pExpr->pPhrase->nToken;
+ break;
+ case FTSQUERY_NEAR: {
+ /* The right-hand-side of a NEAR operator is always a phrase. The
+ ** left-hand-side is either a phrase or an expression tree that is
+ ** itself headed by a NEAR operator. The following initializations
+ ** set local variable iLeft to the token number of the left-most
+ ** token in the right-hand phrase, and iRight to the right most
+ ** token in the same phrase. For example, if we had:
+ **
+ ** <col> MATCH '"abc def" NEAR/2 "ghi jkl"'
+ **
+ ** then iLeft will be set to 2 (token number of ghi) and nToken will
+ ** be set to 4.
+ */
+ Fts3Expr *pLeft = pExpr->pLeft;
+ Fts3Expr *pRight = pExpr->pRight;
+ int iLeft = *piLeft;
+ int nNear = pExpr->nNear;
+ int nToken = pRight->pPhrase->nToken;
+ int jj, ii;
+ if( pLeft->eType==FTSQUERY_NEAR ){
+ pLeft = pLeft->pRight;
+ }
+ assert( pRight->eType==FTSQUERY_PHRASE );
+ assert( pLeft->eType==FTSQUERY_PHRASE );
+ nToken += pLeft->pPhrase->nToken;
+
+ for(ii=0; ii<pSnippet->nMatch; ii++){
+ struct snippetMatch *p = &pSnippet->aMatch[ii];
+ if( p->iTerm==iLeft ){
+ int isOk = 0;
+ /* Snippet ii is an occurence of query term iLeft in the document.
+ ** It occurs at position (p->iToken) of the document. We now
+ ** search for an instance of token (iLeft-1) somewhere in the
+ ** range (p->iToken - nNear)...(p->iToken + nNear + nToken) within
+ ** the set of snippetMatch structures. If one is found, proceed.
+ ** If one cannot be found, then remove snippets ii..(ii+N-1)
+ ** from the matching snippets, where N is the number of tokens
+ ** in phrase pRight->pPhrase.
+ */
+ for(jj=0; isOk==0 && jj<pSnippet->nMatch; jj++){
+ struct snippetMatch *p2 = &pSnippet->aMatch[jj];
+ if( p2->iTerm==(iLeft-1) ){
+ if( p2->iToken>=(p->iToken-nNear-1)
+ && p2->iToken<(p->iToken+nNear+nToken)
+ ){
+ isOk = 1;
+ }
+ }
+ }
+ if( !isOk ){
+ int kk;
+ for(kk=0; kk<pRight->pPhrase->nToken; kk++){
+ pSnippet->aMatch[kk+ii].iTerm = -2;
+ }
+ return 1;
+ }
+ }
+ if( p->iTerm==(iLeft-1) ){
+ int isOk = 0;
+ for(jj=0; isOk==0 && jj<pSnippet->nMatch; jj++){
+ struct snippetMatch *p2 = &pSnippet->aMatch[jj];
+ if( p2->iTerm==iLeft ){
+ if( p2->iToken<=(p->iToken+nNear+1)
+ && p2->iToken>(p->iToken-nNear-nToken)
+ ){
+ isOk = 1;
+ }
+ }
+ }
+ if( !isOk ){
+ int kk;
+ for(kk=0; kk<pLeft->pPhrase->nToken; kk++){
+ pSnippet->aMatch[ii-kk].iTerm = -2;
+ }
+ return 1;
+ }
+ }
+ }
+ break;
+ }
+ }
- pExpr = pLeft;
- pParent = pExpr->pParent;
+ if( trimSnippetOffsets(pExpr->pRight, pSnippet, piLeft) ){
+ return 1;
+ }
}
-
- return rc;
+ return 0;
}
/*
-** This is an fts3ExprIterate() callback used while loading the doclists
-** for each phrase into Fts3Expr.aDoclist[]/nDoclist. See also
-** fts3ExprLoadDoclists().
+** Compute all offsets for the current row of the query.
+** If the offsets have already been computed, this routine is a no-op.
*/
-static int fts3ExprLoadDoclistsCb1(Fts3Expr *pExpr, int iPhrase, void *ctx){
+static int snippetAllOffsets(Fts3Cursor *pCsr, Snippet **ppSnippet){
+ Fts3Table *p = (Fts3Table *)pCsr->base.pVtab; /* The FTS3 virtual table */
+ int nColumn; /* Number of columns. Docid does count */
+ int iColumn; /* Index of of a column */
+ int i; /* Loop index */
+ int iFirst; /* First column to search */
+ int iLast; /* Last coumn to search */
+ int iTerm = 0;
+ Snippet *pSnippet;
int rc = SQLITE_OK;
- LoadDoclistCtx *p = (LoadDoclistCtx *)ctx;
- UNUSED_PARAMETER(iPhrase);
+ if( pCsr->pExpr==0 ){
+ return SQLITE_OK;
+ }
- p->nPhrase++;
- p->nToken += pExpr->pPhrase->nToken;
+ pSnippet = (Snippet *)sqlite3_malloc(sizeof(Snippet));
+ *ppSnippet = pSnippet;
+ if( !pSnippet ){
+ return SQLITE_NOMEM;
+ }
+ memset(pSnippet, 0, sizeof(Snippet));
- if( pExpr->isLoaded==0 ){
- rc = sqlite3Fts3ExprLoadDoclist(p->pTab, pExpr);
- pExpr->isLoaded = 1;
- if( rc==SQLITE_OK ){
- rc = fts3ExprNearTrim(pExpr);
+ nColumn = p->nColumn;
+ iColumn = (pCsr->eSearch - 2);
+ if( iColumn<0 || iColumn>=nColumn ){
+ /* Look for matches over all columns of the full-text index */
+ iFirst = 0;
+ iLast = nColumn-1;
+ }else{
+ /* Look for matches in the iColumn-th column of the index only */
+ iFirst = iColumn;
+ iLast = iColumn;
+ }
+ for(i=iFirst; rc==SQLITE_OK && i<=iLast; i++){
+ const char *zDoc;
+ int nDoc;
+ zDoc = (const char*)sqlite3_column_text(pCsr->pStmt, i+1);
+ nDoc = sqlite3_column_bytes(pCsr->pStmt, i+1);
+ if( zDoc==0 && sqlite3_column_type(pCsr->pStmt, i+1)!=SQLITE_NULL ){
+ rc = SQLITE_NOMEM;
+ }else{
+ rc = snippetOffsetsOfColumn(pCsr, pSnippet, i, zDoc, nDoc);
}
}
+ while( trimSnippetOffsets(pCsr->pExpr, pSnippet, &iTerm) ){
+ iTerm = 0;
+ }
+
return rc;
}
/*
-** This is an fts3ExprIterate() callback used while loading the doclists
-** for each phrase into Fts3Expr.aDoclist[]/nDoclist. See also
-** fts3ExprLoadDoclists().
+** Convert the information in the aMatch[] array of the snippet
+** into the string zOffset[0..nOffset-1]. This string is used as
+** the return of the SQL offsets() function.
*/
-static int fts3ExprLoadDoclistsCb2(Fts3Expr *pExpr, int iPhrase, void *ctx){
- UNUSED_PARAMETER(iPhrase);
- UNUSED_PARAMETER(ctx);
- if( pExpr->aDoclist ){
- pExpr->pCurrent = pExpr->aDoclist;
- pExpr->iCurrent = 0;
- pExpr->pCurrent += sqlite3Fts3GetVarint(pExpr->pCurrent, &pExpr->iCurrent);
+static void snippetOffsetText(Snippet *p){
+ int i;
+ int cnt = 0;
+ StringBuffer sb;
+ char zBuf[200];
+ if( p->zOffset ) return;
+ fts3SnippetSbInit(&sb);
+ for(i=0; i<p->nMatch; i++){
+ struct snippetMatch *pMatch = &p->aMatch[i];
+ if( pMatch->iTerm>=0 ){
+ /* If snippetMatch.iTerm is less than 0, then the match was
+ ** discarded as part of processing the NEAR operator (see the
+ ** trimSnippetOffsetsForNear() function for details). Ignore
+ ** it in this case
+ */
+ zBuf[0] = ' ';
+ sqlite3_snprintf(sizeof(zBuf)-1, &zBuf[cnt>0], "%d %d %d %d",
+ pMatch->iCol, pMatch->iTerm, pMatch->iStart, pMatch->nByte);
+ fts3SnippetAppend(&sb, zBuf, -1);
+ cnt++;
+ }
}
- return SQLITE_OK;
+ p->zOffset = sb.z;
+ p->nOffset = sb.z ? sb.nUsed : 0;
}
/*
-** Load the doclists for each phrase in the query associated with FTS3 cursor
-** pCsr.
+** zDoc[0..nDoc-1] is phrase of text. aMatch[0..nMatch-1] are a set
+** of matching words some of which might be in zDoc. zDoc is column
+** number iCol.
**
-** If pnPhrase is not NULL, then *pnPhrase is set to the number of matchable
-** phrases in the expression (all phrases except those directly or
-** indirectly descended from the right-hand-side of a NOT operator). If
-** pnToken is not NULL, then it is set to the number of tokens in all
-** matchable phrases of the expression.
+** iBreak is suggested spot in zDoc where we could begin or end an
+** excerpt. Return a value similar to iBreak but possibly adjusted
+** to be a little left or right so that the break point is better.
*/
-static int fts3ExprLoadDoclists(
- Fts3Cursor *pCsr, /* Fts3 cursor for current query */
- int *pnPhrase, /* OUT: Number of phrases in query */
- int *pnToken /* OUT: Number of tokens in query */
+static int wordBoundary(
+ int iBreak, /* The suggested break point */
+ const char *zDoc, /* Document text */
+ int nDoc, /* Number of bytes in zDoc[] */
+ struct snippetMatch *aMatch, /* Matching words */
+ int nMatch, /* Number of entries in aMatch[] */
+ int iCol /* The column number for zDoc[] */
){
- int rc; /* Return Code */
- LoadDoclistCtx sCtx = {0,0,0}; /* Context for fts3ExprIterate() */
- sCtx.pTab = (Fts3Table *)pCsr->base.pVtab;
- rc = fts3ExprIterate(pCsr->pExpr, fts3ExprLoadDoclistsCb1, (void *)&sCtx);
- if( rc==SQLITE_OK ){
- (void)fts3ExprIterate(pCsr->pExpr, fts3ExprLoadDoclistsCb2, 0);
+ int i;
+ if( iBreak<=10 ){
+ return 0;
}
- if( pnPhrase ) *pnPhrase = sCtx.nPhrase;
- if( pnToken ) *pnToken = sCtx.nToken;
- return rc;
+ if( iBreak>=nDoc-10 ){
+ return nDoc;
+ }
+ for(i=0; ALWAYS(i<nMatch) && aMatch[i].iCol<iCol; i++){}
+ while( i<nMatch && aMatch[i].iStart+aMatch[i].nByte<iBreak ){ i++; }
+ if( i<nMatch ){
+ if( aMatch[i].iStart<iBreak+10 ){
+ return aMatch[i].iStart;
+ }
+ if( i>0 && aMatch[i-1].iStart+aMatch[i-1].nByte>=iBreak ){
+ return aMatch[i-1].iStart;
+ }
+ }
+ for(i=1; i<=10; i++){
+ if( fts3snippetIsspace(zDoc[iBreak-i]) ){
+ return iBreak - i + 1;
+ }
+ if( fts3snippetIsspace(zDoc[iBreak+i]) ){
+ return iBreak + i + 1;
+ }
+ }
+ return iBreak;
}
+
+
/*
-** Advance the position list iterator specified by the first two
-** arguments so that it points to the first element with a value greater
-** than or equal to parameter iNext.
+** Allowed values for Snippet.aMatch[].snStatus
*/
-static void fts3SnippetAdvance(char **ppIter, int *piIter, int iNext){
- char *pIter = *ppIter;
- if( pIter ){
- int iIter = *piIter;
+#define SNIPPET_IGNORE 0 /* It is ok to omit this match from the snippet */
+#define SNIPPET_DESIRED 1 /* We want to include this match in the snippet */
- while( iIter<iNext ){
- if( 0==(*pIter & 0xFE) ){
- iIter = -1;
- pIter = 0;
+/*
+** Generate the text of a snippet.
+*/
+static void snippetText(
+ Fts3Cursor *pCursor, /* The cursor we need the snippet for */
+ Snippet *pSnippet,
+ const char *zStartMark, /* Markup to appear before each match */
+ const char *zEndMark, /* Markup to appear after each match */
+ const char *zEllipsis /* Ellipsis mark */
+){
+ int i, j;
+ struct snippetMatch *aMatch;
+ int nMatch;
+ int nDesired;
+ StringBuffer sb;
+ int tailCol;
+ int tailOffset;
+ int iCol;
+ int nDoc;
+ const char *zDoc;
+ int iStart, iEnd;
+ int tailEllipsis = 0;
+ int iMatch;
+
+
+ sqlite3_free(pSnippet->zSnippet);
+ pSnippet->zSnippet = 0;
+ aMatch = pSnippet->aMatch;
+ nMatch = pSnippet->nMatch;
+ fts3SnippetSbInit(&sb);
+
+ for(i=0; i<nMatch; i++){
+ aMatch[i].snStatus = SNIPPET_IGNORE;
+ }
+ nDesired = 0;
+ for(i=0; i<FTS3_ROTOR_SZ; i++){
+ for(j=0; j<nMatch; j++){
+ if( aMatch[j].iTerm==i ){
+ aMatch[j].snStatus = SNIPPET_DESIRED;
+ nDesired++;
break;
}
- fts3GetDeltaPosition(&pIter, &iIter);
}
+ }
- *piIter = iIter;
- *ppIter = pIter;
+ iMatch = 0;
+ tailCol = -1;
+ tailOffset = 0;
+ for(i=0; i<nMatch && nDesired>0; i++){
+ if( aMatch[i].snStatus!=SNIPPET_DESIRED ) continue;
+ nDesired--;
+ iCol = aMatch[i].iCol;
+ zDoc = (const char*)sqlite3_column_text(pCursor->pStmt, iCol+1);
+ nDoc = sqlite3_column_bytes(pCursor->pStmt, iCol+1);
+ iStart = aMatch[i].iStart - 40;
+ iStart = wordBoundary(iStart, zDoc, nDoc, aMatch, nMatch, iCol);
+ if( iStart<=10 ){
+ iStart = 0;
+ }
+ if( iCol==tailCol && iStart<=tailOffset+20 ){
+ iStart = tailOffset;
+ }
+ if( (iCol!=tailCol && tailCol>=0) || iStart!=tailOffset ){
+ fts3SnippetTrimWhiteSpace(&sb);
+ fts3SnippetAppendWhiteSpace(&sb);
+ fts3SnippetAppend(&sb, zEllipsis, -1);
+ fts3SnippetAppendWhiteSpace(&sb);
+ }
+ iEnd = aMatch[i].iStart + aMatch[i].nByte + 40;
+ iEnd = wordBoundary(iEnd, zDoc, nDoc, aMatch, nMatch, iCol);
+ if( iEnd>=nDoc-10 ){
+ iEnd = nDoc;
+ tailEllipsis = 0;
+ }else{
+ tailEllipsis = 1;
+ }
+ while( iMatch<nMatch && aMatch[iMatch].iCol<iCol ){ iMatch++; }
+ while( iStart<iEnd ){
+ while( iMatch<nMatch && aMatch[iMatch].iStart<iStart
+ && aMatch[iMatch].iCol<=iCol ){
+ iMatch++;
+ }
+ if( iMatch<nMatch && aMatch[iMatch].iStart<iEnd
+ && aMatch[iMatch].iCol==iCol ){
+ fts3SnippetAppend(&sb, &zDoc[iStart], aMatch[iMatch].iStart - iStart);
+ iStart = aMatch[iMatch].iStart;
+ fts3SnippetAppend(&sb, zStartMark, -1);
+ fts3SnippetAppend(&sb, &zDoc[iStart], aMatch[iMatch].nByte);
+ fts3SnippetAppend(&sb, zEndMark, -1);
+ iStart += aMatch[iMatch].nByte;
+ for(j=iMatch+1; j<nMatch; j++){
+ if( aMatch[j].iTerm==aMatch[iMatch].iTerm
+ && aMatch[j].snStatus==SNIPPET_DESIRED ){
+ nDesired--;
+ aMatch[j].snStatus = SNIPPET_IGNORE;
+ }
+ }
+ }else{
+ fts3SnippetAppend(&sb, &zDoc[iStart], iEnd - iStart);
+ iStart = iEnd;
+ }
+ }
+ tailCol = iCol;
+ tailOffset = iEnd;
+ }
+ fts3SnippetTrimWhiteSpace(&sb);
+ if( tailEllipsis ){
+ fts3SnippetAppendWhiteSpace(&sb);
+ fts3SnippetAppend(&sb, zEllipsis, -1);
}
+ pSnippet->zSnippet = sb.z;
+ pSnippet->nSnippet = sb.z ? sb.nUsed : 0;
}
-/*
-** Advance the snippet iterator to the next candidate snippet.
+SQLITE_PRIVATE void sqlite3Fts3Offsets(
+ sqlite3_context *pCtx, /* SQLite function call context */
+ Fts3Cursor *pCsr /* Cursor object */
+){
+ Snippet *p; /* Snippet structure */
+ int rc = snippetAllOffsets(pCsr, &p);
+ if( rc==SQLITE_OK ){
+ snippetOffsetText(p);
+ if( p->zOffset ){
+ sqlite3_result_text(pCtx, p->zOffset, p->nOffset, SQLITE_TRANSIENT);
+ }else{
+ sqlite3_result_error_nomem(pCtx);
+ }
+ }else{
+ sqlite3_result_error_nomem(pCtx);
+ }
+ fts3SnippetFree(p);
+}
+
+SQLITE_PRIVATE void sqlite3Fts3Snippet(
+ sqlite3_context *pCtx, /* SQLite function call context */
+ Fts3Cursor *pCsr, /* Cursor object */
+ const char *zStart, /* Snippet start text - "<b>" */
+ const char *zEnd, /* Snippet end text - "</b>" */
+ const char *zEllipsis /* Snippet ellipsis text - "<b>...</b>" */
+){
+ Snippet *p; /* Snippet structure */
+ int rc = snippetAllOffsets(pCsr, &p);
+ if( rc==SQLITE_OK ){
+ snippetText(pCsr, p, zStart, zEnd, zEllipsis);
+ if( p->zSnippet ){
+ sqlite3_result_text(pCtx, p->zSnippet, p->nSnippet, SQLITE_TRANSIENT);
+ }else{
+ sqlite3_result_error_nomem(pCtx);
+ }
+ }else{
+ sqlite3_result_error_nomem(pCtx);
+ }
+ fts3SnippetFree(p);
+}
+
+/*************************************************************************
+** Below this point is the alternative, experimental snippet() implementation.
*/
-static int fts3SnippetNextCandidate(SnippetIter *pIter){
- int i; /* Loop counter */
- if( pIter->iCurrent<0 ){
- /* The SnippetIter object has just been initialized. The first snippet
- ** candidate always starts at offset 0 (even if this candidate has a
- ** score of 0.0).
- */
- pIter->iCurrent = 0;
+#define SNIPPET_BUFFER_CHUNK 64
+#define SNIPPET_BUFFER_SIZE SNIPPET_BUFFER_CHUNK*4
+#define SNIPPET_BUFFER_MASK (SNIPPET_BUFFER_SIZE-1)
- /* Advance the 'head' iterator of each phrase to the first offset that
- ** is greater than or equal to (iNext+nSnippet).
- */
- for(i=0; i<pIter->nPhrase; i++){
- SnippetPhrase *pPhrase = &pIter->aPhrase[i];
- fts3SnippetAdvance(&pPhrase->pHead, &pPhrase->iHead, pIter->nSnippet);
+static void fts3GetDeltaPosition(char **pp, int *piPos){
+ int iVal;
+ *pp += sqlite3Fts3GetVarint32(*pp, &iVal);
+ *piPos += (iVal-2);
+}
+
+/*
+** Iterate through all phrase nodes in an FTS3 query, except those that
+** are part of a sub-tree that is the right-hand-side of a NOT operator.
+** For each phrase node found, the supplied callback function is invoked.
+**
+** If the callback function returns anything other than SQLITE_OK,
+** the iteration is abandoned and the error code returned immediately.
+** Otherwise, SQLITE_OK is returned after a callback has been made for
+** all eligible phrase nodes.
+*/
+static int fts3ExprIterate(
+ Fts3Expr *pExpr, /* Expression to iterate phrases of */
+ int (*x)(Fts3Expr *, void *), /* Callback function to invoke for phrases */
+ void *pCtx /* Second argument to pass to callback */
+){
+ int rc;
+ int eType = pExpr->eType;
+ if( eType==FTSQUERY_NOT ){
+ rc = SQLITE_OK;
+ }else if( eType!=FTSQUERY_PHRASE ){
+ assert( pExpr->pLeft && pExpr->pRight );
+ rc = fts3ExprIterate(pExpr->pLeft, x, pCtx);
+ if( rc==SQLITE_OK ){
+ rc = fts3ExprIterate(pExpr->pRight, x, pCtx);
}
}else{
- int iStart;
- int iEnd = 0x7FFFFFFF;
+ rc = x(pExpr, pCtx);
+ }
+ return rc;
+}
- for(i=0; i<pIter->nPhrase; i++){
- SnippetPhrase *pPhrase = &pIter->aPhrase[i];
- if( pPhrase->pHead && pPhrase->iHead<iEnd ){
- iEnd = pPhrase->iHead;
- }
- }
- if( iEnd==0x7FFFFFFF ){
- return 1;
- }
+typedef struct LoadDoclistCtx LoadDoclistCtx;
+struct LoadDoclistCtx {
+ Fts3Table *pTab; /* FTS3 Table */
+ int nPhrase; /* Number of phrases so far */
+};
- pIter->iCurrent = iStart = iEnd - pIter->nSnippet + 1;
- for(i=0; i<pIter->nPhrase; i++){
- SnippetPhrase *pPhrase = &pIter->aPhrase[i];
- fts3SnippetAdvance(&pPhrase->pHead, &pPhrase->iHead, iEnd+1);
- fts3SnippetAdvance(&pPhrase->pTail, &pPhrase->iTail, iStart);
+static int fts3ExprLoadDoclistsCb(Fts3Expr *pExpr, void *ctx){
+ int rc = SQLITE_OK;
+ LoadDoclistCtx *p = (LoadDoclistCtx *)ctx;
+ p->nPhrase++;
+ if( pExpr->isLoaded==0 ){
+ rc = sqlite3Fts3ExprLoadDoclist(p->pTab, pExpr);
+ pExpr->isLoaded = 1;
+ if( rc==SQLITE_OK && pExpr->aDoclist ){
+ pExpr->pCurrent = pExpr->aDoclist;
+ pExpr->pCurrent += sqlite3Fts3GetVarint(pExpr->pCurrent,&pExpr->iCurrent);
}
}
+ return rc;
+}
- return 0;
+static int fts3ExprLoadDoclists(Fts3Cursor *pCsr, int *pnPhrase){
+ int rc;
+ LoadDoclistCtx sCtx = {0, 0};
+ sCtx.pTab = (Fts3Table *)pCsr->base.pVtab;
+ rc = fts3ExprIterate(pCsr->pExpr, fts3ExprLoadDoclistsCb, (void *)&sCtx);
+ *pnPhrase = sCtx.nPhrase;
+ return rc;
}
/*
-** Retrieve information about the current candidate snippet of snippet
-** iterator pIter.
+** Each call to this function populates a chunk of a snippet-buffer
+** SNIPPET_BUFFER_CHUNK bytes in size.
+**
+** Return true if the end of the data has been reached (and all subsequent
+** calls to fts3LoadSnippetBuffer() with the same arguments will be no-ops),
+** or false otherwise.
*/
-static void fts3SnippetDetails(
- SnippetIter *pIter, /* Snippet iterator */
- u64 mCovered, /* Bitmask of phrases already covered */
- int *piToken, /* OUT: First token of proposed snippet */
- int *piScore, /* OUT: "Score" for this snippet */
- u64 *pmCover, /* OUT: Bitmask of phrases covered */
- u64 *pmHighlight /* OUT: Bitmask of terms to highlight */
+static int fts3LoadSnippetBuffer(
+ int iPos, /* Document token offset to load data for */
+ u8 *aBuffer, /* Circular snippet buffer to populate */
+ int nList, /* Number of position lists in appList */
+ char **apList, /* IN/OUT: nList position list pointers */
+ int *aiPrev /* IN/OUT: Previous positions read */
){
- int iStart = pIter->iCurrent; /* First token of snippet */
- int iScore = 0; /* Score of this snippet */
- int i; /* Loop counter */
- u64 mCover = 0; /* Mask of phrases covered by this snippet */
- u64 mHighlight = 0; /* Mask of tokens to highlight in snippet */
+ int i;
+ int nFin = 0;
- for(i=0; i<pIter->nPhrase; i++){
- SnippetPhrase *pPhrase = &pIter->aPhrase[i];
- if( pPhrase->pTail ){
- char *pCsr = pPhrase->pTail;
- int iCsr = pPhrase->iTail;
+ assert( (iPos&(SNIPPET_BUFFER_CHUNK-1))==0 );
- while( iCsr<(iStart+pIter->nSnippet) ){
- int j;
- u64 mPhrase = (u64)1 << i;
- u64 mPos = (u64)1 << (iCsr - iStart);
- assert( iCsr>=iStart );
- if( (mCover|mCovered)&mPhrase ){
- iScore++;
- }else{
- iScore += 1000;
- }
- mCover |= mPhrase;
+ memset(&aBuffer[iPos&SNIPPET_BUFFER_MASK], 0, SNIPPET_BUFFER_CHUNK);
- for(j=0; j<pPhrase->nToken; j++){
- mHighlight |= (mPos>>j);
- }
+ for(i=0; i<nList; i++){
+ int iPrev = aiPrev[i];
+ char *pList = apList[i];
- if( 0==(*pCsr & 0x0FE) ) break;
- fts3GetDeltaPosition(&pCsr, &iCsr);
+ if( !pList ){
+ nFin++;
+ continue;
+ }
+
+ while( iPrev<(iPos+SNIPPET_BUFFER_CHUNK) ){
+ if( iPrev>=iPos ){
+ aBuffer[iPrev&SNIPPET_BUFFER_MASK] = (u8)(i+1);
+ }
+ if( 0==((*pList)&0xFE) ){
+ nFin++;
+ break;
}
+ fts3GetDeltaPosition(&pList, &iPrev);
}
+
+ aiPrev[i] = iPrev;
+ apList[i] = pList;
}
- /* Set the output variables before returning. */
- *piToken = iStart;
- *piScore = iScore;
- *pmCover = mCover;
- *pmHighlight = mHighlight;
+ return (nFin==nList);
}
-/*
-** This function is an fts3ExprIterate() callback used by fts3BestSnippet().
-** Each invocation populates an element of the SnippetIter.aPhrase[] array.
-*/
-static int fts3SnippetFindPositions(Fts3Expr *pExpr, int iPhrase, void *ctx){
- SnippetIter *p = (SnippetIter *)ctx;
- SnippetPhrase *pPhrase = &p->aPhrase[iPhrase];
- char *pCsr;
+typedef struct SnippetCtx SnippetCtx;
+struct SnippetCtx {
+ Fts3Cursor *pCsr;
+ int iCol;
+ int iPhrase;
+ int *aiPrev;
+ int *anToken;
+ char **apList;
+};
- pPhrase->nToken = pExpr->pPhrase->nToken;
+static int fts3SnippetFindPositions(Fts3Expr *pExpr, void *ctx){
+ SnippetCtx *p = (SnippetCtx *)ctx;
+ int iPhrase = p->iPhrase++;
+ char *pCsr;
+ p->anToken[iPhrase] = pExpr->pPhrase->nToken;
pCsr = sqlite3Fts3FindPositions(pExpr, p->pCsr->iPrevId, p->iCol);
+
if( pCsr ){
- int iFirst = 0;
- pPhrase->pList = pCsr;
- fts3GetDeltaPosition(&pCsr, &iFirst);
- pPhrase->pHead = pCsr;
- pPhrase->pTail = pCsr;
- pPhrase->iHead = iFirst;
- pPhrase->iTail = iFirst;
- }else{
- assert( pPhrase->pList==0 && pPhrase->pHead==0 && pPhrase->pTail==0 );
+ int iVal;
+ pCsr += sqlite3Fts3GetVarint32(pCsr, &iVal);
+ p->apList[iPhrase] = pCsr;
+ p->aiPrev[iPhrase] = iVal-2;
}
-
return SQLITE_OK;
}
-/*
-** Select the fragment of text consisting of nFragment contiguous tokens
-** from column iCol that represent the "best" snippet. The best snippet
-** is the snippet with the highest score, where scores are calculated
-** by adding:
-**
-** (a) +1 point for each occurence of a matchable phrase in the snippet.
-**
-** (b) +1000 points for the first occurence of each matchable phrase in
-** the snippet for which the corresponding mCovered bit is not set.
-**
-** The selected snippet parameters are stored in structure *pFragment before
-** returning. The score of the selected snippet is stored in *piScore
-** before returning.
-*/
+static void fts3SnippetCnt(
+ int iIdx,
+ int nSnippet,
+ int *anCnt,
+ u8 *aBuffer,
+ int *anToken,
+ u64 *pHlmask
+){
+ int iSub = (iIdx-1)&SNIPPET_BUFFER_MASK;
+ int iAdd = (iIdx+nSnippet-1)&SNIPPET_BUFFER_MASK;
+ int iSub2 = (iIdx+(nSnippet/3)-1)&SNIPPET_BUFFER_MASK;
+ int iAdd2 = (iIdx+(nSnippet*2/3)-1)&SNIPPET_BUFFER_MASK;
+
+ u64 h = *pHlmask;
+
+ anCnt[ aBuffer[iSub] ]--;
+ anCnt[ aBuffer[iSub2] ]--;
+ anCnt[ aBuffer[iAdd] ]++;
+ anCnt[ aBuffer[iAdd2] ]++;
+
+ h = h >> 1;
+ if( aBuffer[iAdd] ){
+ int j;
+ for(j=anToken[aBuffer[iAdd]-1]; j>=1; j--){
+ h |= (u64)1 << (nSnippet-j);
+ }
+ }
+ *pHlmask = h;
+}
+
+static int fts3SnippetScore(int n, int *anCnt){
+ int j;
+ int iScore = 0;
+ for(j=1; j<=n; j++){
+ int nCnt = anCnt[j];
+ iScore += nCnt + (nCnt ? 1000 : 0);
+ }
+ return iScore;
+}
+
static int fts3BestSnippet(
int nSnippet, /* Desired snippet length */
Fts3Cursor *pCsr, /* Cursor to create snippet for */
int iCol, /* Index of column to create snippet from */
- u64 mCovered, /* Mask of phrases already covered */
- u64 *pmSeen, /* IN/OUT: Mask of phrases seen */
- SnippetFragment *pFragment, /* OUT: Best snippet found */
- int *piScore /* OUT: Score of snippet pFragment */
+ int *piPos, /* OUT: Starting token for best snippet */
+ u64 *pHlmask /* OUT: Highlight mask for best snippet */
){
int rc; /* Return Code */
- int nList; /* Number of phrases in expression */
- SnippetIter sIter; /* Iterates through snippet candidates */
- int nByte; /* Number of bytes of space to allocate */
- int iBestScore = -1; /* Best snippet score found so far */
- int i; /* Loop counter */
+ u8 aBuffer[SNIPPET_BUFFER_SIZE];/* Circular snippet buffer */
+ int *aiPrev; /* Used by fts3LoadSnippetBuffer() */
+ int *anToken; /* Number of tokens in each phrase */
+ char **apList; /* Array of position lists */
+ int *anCnt; /* Running totals of phrase occurences */
+ int nList;
- memset(&sIter, 0, sizeof(sIter));
+ int i;
+
+ u64 hlmask = 0; /* Current mask of highlighted terms */
+ u64 besthlmask = 0; /* Mask of highlighted terms for iBestPos */
+ int iBestPos = 0; /* Starting position of 'best' snippet */
+ int iBestScore = 0; /* Score of best snippet higher->better */
+ SnippetCtx sCtx;
/* Iterate through the phrases in the expression to count them. The same
** callback makes sure the doclists are loaded for each phrase.
*/
- rc = fts3ExprLoadDoclists(pCsr, &nList, 0);
+ rc = fts3ExprLoadDoclists(pCsr, &nList);
if( rc!=SQLITE_OK ){
return rc;
}
/* Now that it is known how many phrases there are, allocate and zero
- ** the required space using malloc().
+ ** the required arrays using malloc().
*/
- nByte = sizeof(SnippetPhrase) * nList;
- sIter.aPhrase = (SnippetPhrase *)sqlite3_malloc(nByte);
- if( !sIter.aPhrase ){
+ apList = sqlite3_malloc(
+ sizeof(u8*)*nList + /* apList */
+ sizeof(int)*(nList) + /* anToken */
+ sizeof(int)*nList + /* aiPrev */
+ sizeof(int)*(nList+1) /* anCnt */
+ );
+ if( !apList ){
return SQLITE_NOMEM;
}
- memset(sIter.aPhrase, 0, nByte);
-
- /* Initialize the contents of the SnippetIter object. Then iterate through
- ** the set of phrases in the expression to populate the aPhrase[] array.
- */
- sIter.pCsr = pCsr;
- sIter.iCol = iCol;
- sIter.nSnippet = nSnippet;
- sIter.nPhrase = nList;
- sIter.iCurrent = -1;
- (void)fts3ExprIterate(pCsr->pExpr, fts3SnippetFindPositions, (void *)&sIter);
+ memset(apList, 0, sizeof(u8*)*nList+sizeof(int)*nList+sizeof(int)*nList);
+ anToken = (int *)&apList[nList];
+ aiPrev = &anToken[nList];
+ anCnt = &aiPrev[nList];
+
+ /* Initialize the contents of the aiPrev and aiList arrays. */
+ sCtx.pCsr = pCsr;
+ sCtx.iCol = iCol;
+ sCtx.apList = apList;
+ sCtx.aiPrev = aiPrev;
+ sCtx.anToken = anToken;
+ sCtx.iPhrase = 0;
+ (void)fts3ExprIterate(pCsr->pExpr, fts3SnippetFindPositions, (void *)&sCtx);
+
+ /* Load the first two chunks of data into the buffer. */
+ memset(aBuffer, 0, SNIPPET_BUFFER_SIZE);
+ fts3LoadSnippetBuffer(0, aBuffer, nList, apList, aiPrev);
+ fts3LoadSnippetBuffer(SNIPPET_BUFFER_CHUNK, aBuffer, nList, apList, aiPrev);
+
+ /* Set the initial contents of the highlight-mask and anCnt[] array. */
+ for(i=1-nSnippet; i<=0; i++){
+ fts3SnippetCnt(i, nSnippet, anCnt, aBuffer, anToken, &hlmask);
+ }
+ iBestScore = fts3SnippetScore(nList, anCnt);
+ besthlmask = hlmask;
+ iBestPos = 0;
+
+ for(i=1; 1; i++){
+ int iScore;
- /* Set the *pmSeen output variable. */
- for(i=0; i<nList; i++){
- if( sIter.aPhrase[i].pHead ){
- *pmSeen |= (u64)1 << i;
+ if( 0==(i&(SNIPPET_BUFFER_CHUNK-1)) ){
+ int iLoad = i + SNIPPET_BUFFER_CHUNK;
+ if( fts3LoadSnippetBuffer(iLoad, aBuffer, nList, apList, aiPrev) ) break;
}
- }
- /* Loop through all candidate snippets. Store the best snippet in
- ** *pFragment. Store its associated 'score' in iBestScore.
- */
- pFragment->iCol = iCol;
- while( !fts3SnippetNextCandidate(&sIter) ){
- int iPos;
- int iScore;
- u64 mCover;
- u64 mHighlight;
- fts3SnippetDetails(&sIter, mCovered, &iPos, &iScore, &mCover, &mHighlight);
- assert( iScore>=0 );
+ /* Figure out how highly a snippet starting at token offset i scores
+ ** according to fts3SnippetScore(). If it is higher than any previously
+ ** considered position, save the current position, score and hlmask as
+ ** the best snippet candidate found so far.
+ */
+ fts3SnippetCnt(i, nSnippet, anCnt, aBuffer, anToken, &hlmask);
+ iScore = fts3SnippetScore(nList, anCnt);
if( iScore>iBestScore ){
- pFragment->iPos = iPos;
- pFragment->hlmask = mHighlight;
- pFragment->covered = mCover;
+ iBestPos = i;
iBestScore = iScore;
+ besthlmask = hlmask;
}
}
- sqlite3_free(sIter.aPhrase);
- *piScore = iBestScore;
+ sqlite3_free(apList);
+ *piPos = iBestPos;
+ *pHlmask = besthlmask;
return SQLITE_OK;
}
+typedef struct StrBuffer StrBuffer;
+struct StrBuffer {
+ char *z;
+ int n;
+ int nAlloc;
+};
-/*
-** Append a string to the string-buffer passed as the first argument.
-**
-** If nAppend is negative, then the length of the string zAppend is
-** determined using strlen().
-*/
static int fts3StringAppend(
- StrBuffer *pStr, /* Buffer to append to */
- const char *zAppend, /* Pointer to data to append to buffer */
- int nAppend /* Size of zAppend in bytes (or -1) */
+ StrBuffer *pStr,
+ const char *zAppend,
+ int nAppend
){
if( nAppend<0 ){
nAppend = (int)strlen(zAppend);
}
- /* If there is insufficient space allocated at StrBuffer.z, use realloc()
- ** to grow the buffer until so that it is big enough to accomadate the
- ** appended data.
- */
if( pStr->n+nAppend+1>=pStr->nAlloc ){
int nAlloc = pStr->nAlloc+nAppend+100;
char *zNew = sqlite3_realloc(pStr->z, nAlloc);
@@ -113669,7 +107238,6 @@ static int fts3StringAppend(
pStr->nAlloc = nAlloc;
}
- /* Append the data to the string buffer. */
memcpy(&pStr->z[pStr->n], zAppend, nAppend);
pStr->n += nAppend;
pStr->z[pStr->n] = '\0';
@@ -113677,201 +107245,126 @@ static int fts3StringAppend(
return SQLITE_OK;
}
-/*
-** The fts3BestSnippet() function often selects snippets that end with a
-** query term. That is, the final term of the snippet is always a term
-** that requires highlighting. For example, if 'X' is a highlighted term
-** and '.' is a non-highlighted term, BestSnippet() may select:
-**
-** ........X.....X
-**
-** This function "shifts" the beginning of the snippet forward in the
-** document so that there are approximately the same number of
-** non-highlighted terms to the right of the final highlighted term as there
-** are to the left of the first highlighted term. For example, to this:
-**
-** ....X.....X....
-**
-** This is done as part of extracting the snippet text, not when selecting
-** the snippet. Snippet selection is done based on doclists only, so there
-** is no way for fts3BestSnippet() to know whether or not the document
-** actually contains terms that follow the final highlighted term.
-*/
-static int fts3SnippetShift(
- Fts3Table *pTab, /* FTS3 table snippet comes from */
- int nSnippet, /* Number of tokens desired for snippet */
- const char *zDoc, /* Document text to extract snippet from */
- int nDoc, /* Size of buffer zDoc in bytes */
- int *piPos, /* IN/OUT: First token of snippet */
- u64 *pHlmask /* IN/OUT: Mask of tokens to highlight */
-){
- u64 hlmask = *pHlmask; /* Local copy of initial highlight-mask */
-
- if( hlmask ){
- int nLeft; /* Tokens to the left of first highlight */
- int nRight; /* Tokens to the right of last highlight */
- int nDesired; /* Ideal number of tokens to shift forward */
-
- for(nLeft=0; !(hlmask & ((u64)1 << nLeft)); nLeft++);
- for(nRight=0; !(hlmask & ((u64)1 << (nSnippet-1-nRight))); nRight++);
- nDesired = (nLeft-nRight)/2;
-
- /* Ideally, the start of the snippet should be pushed forward in the
- ** document nDesired tokens. This block checks if there are actually
- ** nDesired tokens to the right of the snippet. If so, *piPos and
- ** *pHlMask are updated to shift the snippet nDesired tokens to the
- ** right. Otherwise, the snippet is shifted by the number of tokens
- ** available.
- */
- if( nDesired>0 ){
- int nShift; /* Number of tokens to shift snippet by */
- int iCurrent = 0; /* Token counter */
- int rc; /* Return Code */
- sqlite3_tokenizer_module *pMod;
- sqlite3_tokenizer_cursor *pC;
- pMod = (sqlite3_tokenizer_module *)pTab->pTokenizer->pModule;
-
- /* Open a cursor on zDoc/nDoc. Check if there are (nSnippet+nDesired)
- ** or more tokens in zDoc/nDoc.
- */
- rc = pMod->xOpen(pTab->pTokenizer, zDoc, nDoc, &pC);
- if( rc!=SQLITE_OK ){
- return rc;
- }
- pC->pTokenizer = pTab->pTokenizer;
- while( rc==SQLITE_OK && iCurrent<(nSnippet+nDesired) ){
- const char *ZDUMMY; int DUMMY1, DUMMY2, DUMMY3;
- rc = pMod->xNext(pC, &ZDUMMY, &DUMMY1, &DUMMY2, &DUMMY3, &iCurrent);
- }
- pMod->xClose(pC);
- if( rc!=SQLITE_OK && rc!=SQLITE_DONE ){ return rc; }
-
- nShift = (rc==SQLITE_DONE)+iCurrent-nSnippet;
- assert( nShift<=nDesired );
- if( nShift>0 ){
- *piPos += nShift;
- *pHlmask = hlmask >> nShift;
- }
- }
- }
- return SQLITE_OK;
-}
-
-/*
-** Extract the snippet text for fragment pFragment from cursor pCsr and
-** append it to string buffer pOut.
-*/
static int fts3SnippetText(
Fts3Cursor *pCsr, /* FTS3 Cursor */
- SnippetFragment *pFragment, /* Snippet to extract */
- int iFragment, /* Fragment number */
- int isLast, /* True for final fragment in snippet */
+ const char *zDoc, /* Document to extract snippet from */
+ int nDoc, /* Size of zDoc in bytes */
int nSnippet, /* Number of tokens in extracted snippet */
+ int iPos, /* Index of first document token in snippet */
+ u64 hlmask, /* Bitmask of terms to highlight in snippet */
const char *zOpen, /* String inserted before highlighted term */
const char *zClose, /* String inserted after highlighted term */
- const char *zEllipsis, /* String inserted between snippets */
- StrBuffer *pOut /* Write output here */
+ const char *zEllipsis,
+ char **pzSnippet /* OUT: Snippet text */
){
Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
int rc; /* Return code */
- const char *zDoc; /* Document text to extract snippet from */
- int nDoc; /* Size of zDoc in bytes */
- int iCurrent = 0; /* Current token number of document */
- int iEnd = 0; /* Byte offset of end of current token */
- int isShiftDone = 0; /* True after snippet is shifted */
- int iPos = pFragment->iPos; /* First token of snippet */
- u64 hlmask = pFragment->hlmask; /* Highlight-mask for snippet */
- int iCol = pFragment->iCol+1; /* Query column to extract text from */
+ int iCurrent = 0;
+ int iStart = 0;
+ int iEnd;
+
sqlite3_tokenizer_module *pMod; /* Tokenizer module methods object */
sqlite3_tokenizer_cursor *pC; /* Tokenizer cursor open on zDoc/nDoc */
- const char *ZDUMMY; /* Dummy argument used with tokenizer */
- int DUMMY1; /* Dummy argument used with tokenizer */
+ const char *ZDUMMY; /* Dummy arguments used with tokenizer */
+ int DUMMY1, DUMMY2, DUMMY3; /* Dummy arguments used with tokenizer */
- zDoc = (const char *)sqlite3_column_text(pCsr->pStmt, iCol);
- if( zDoc==0 ){
- if( sqlite3_column_type(pCsr->pStmt, iCol)!=SQLITE_NULL ){
- return SQLITE_NOMEM;
- }
- return SQLITE_OK;
- }
- nDoc = sqlite3_column_bytes(pCsr->pStmt, iCol);
+ StrBuffer res = {0, 0, 0}; /* Result string */
- /* Open a token cursor on the document. */
+ /* Open a token cursor on the document. Read all tokens up to and
+ ** including token iPos (the first token of the snippet). Set variable
+ ** iStart to the byte offset in zDoc of the start of token iPos.
+ */
pMod = (sqlite3_tokenizer_module *)pTab->pTokenizer->pModule;
rc = pMod->xOpen(pTab->pTokenizer, zDoc, nDoc, &pC);
- if( rc!=SQLITE_OK ){
- return rc;
+ while( rc==SQLITE_OK && iCurrent<iPos ){
+ rc = pMod->xNext(pC, &ZDUMMY, &DUMMY1, &iStart, &DUMMY2, &iCurrent);
}
- pC->pTokenizer = pTab->pTokenizer;
+ iEnd = iStart;
- while( rc==SQLITE_OK ){
- int iBegin; /* Offset in zDoc of start of token */
- int iFin; /* Offset in zDoc of end of token */
- int isHighlight; /* True for highlighted terms */
+ if( rc==SQLITE_OK && iStart>0 ){
+ rc = fts3StringAppend(&res, zEllipsis, -1);
+ }
+ while( rc==SQLITE_OK ){
+ int iBegin;
+ int iFin;
rc = pMod->xNext(pC, &ZDUMMY, &DUMMY1, &iBegin, &iFin, &iCurrent);
- if( rc!=SQLITE_OK ){
- if( rc==SQLITE_DONE ){
- /* Special case - the last token of the snippet is also the last token
- ** of the column. Append any punctuation that occurred between the end
- ** of the previous token and the end of the document to the output.
- ** Then break out of the loop. */
- rc = fts3StringAppend(pOut, &zDoc[iEnd], -1);
- }
- break;
- }
- if( iCurrent<iPos ){ continue; }
- if( !isShiftDone ){
- int n = nDoc - iBegin;
- rc = fts3SnippetShift(pTab, nSnippet, &zDoc[iBegin], n, &iPos, &hlmask);
- isShiftDone = 1;
-
- /* Now that the shift has been done, check if the initial "..." are
- ** required. They are required if (a) this is not the first fragment,
- ** or (b) this fragment does not begin at position 0 of its column.
- */
- if( rc==SQLITE_OK && (iPos>0 || iFragment>0) ){
- rc = fts3StringAppend(pOut, zEllipsis, -1);
+ if( rc==SQLITE_OK ){
+ if( iCurrent>=(iPos+nSnippet) ){
+ rc = SQLITE_DONE;
+ }else{
+ iEnd = iFin;
+ if( hlmask & ((u64)1 << (iCurrent-iPos)) ){
+ if( fts3StringAppend(&res, &zDoc[iStart], iBegin-iStart)
+ || fts3StringAppend(&res, zOpen, -1)
+ || fts3StringAppend(&res, &zDoc[iBegin], iEnd-iBegin)
+ || fts3StringAppend(&res, zClose, -1)
+ ){
+ rc = SQLITE_NOMEM;
+ }
+ iStart = iEnd;
+ }
}
- if( rc!=SQLITE_OK || iCurrent<iPos ) continue;
}
-
- if( iCurrent>=(iPos+nSnippet) ){
- if( isLast ){
- rc = fts3StringAppend(pOut, zEllipsis, -1);
+ }
+ assert( rc!=SQLITE_OK );
+ if( rc==SQLITE_DONE ){
+ rc = fts3StringAppend(&res, &zDoc[iStart], iEnd-iStart);
+ if( rc==SQLITE_OK ){
+ rc = pMod->xNext(pC, &ZDUMMY, &DUMMY1, &DUMMY2, &DUMMY3, &iCurrent);
+ if( rc==SQLITE_OK ){
+ rc = fts3StringAppend(&res, zEllipsis, -1);
+ }else if( rc==SQLITE_DONE ){
+ rc = fts3StringAppend(&res, &zDoc[iEnd], -1);
}
- break;
}
-
- /* Set isHighlight to true if this term should be highlighted. */
- isHighlight = (hlmask & ((u64)1 << (iCurrent-iPos)))!=0;
-
- if( iCurrent>iPos ) rc = fts3StringAppend(pOut, &zDoc[iEnd], iBegin-iEnd);
- if( rc==SQLITE_OK && isHighlight ) rc = fts3StringAppend(pOut, zOpen, -1);
- if( rc==SQLITE_OK ) rc = fts3StringAppend(pOut, &zDoc[iBegin], iFin-iBegin);
- if( rc==SQLITE_OK && isHighlight ) rc = fts3StringAppend(pOut, zClose, -1);
-
- iEnd = iFin;
}
pMod->xClose(pC);
+ if( rc!=SQLITE_OK ){
+ sqlite3_free(res.z);
+ }else{
+ *pzSnippet = res.z;
+ }
return rc;
}
/*
-** This function is used to count the entries in a column-list (a
-** delta-encoded list of term offsets within a single column of a single
-** row). When this function is called, *ppCollist should point to the
-** beginning of the first varint in the column-list (the varint that
-** contains the position of the first matching term in the column data).
-** Before returning, *ppCollist is set to point to the first byte after
-** the last varint in the column-list (either the 0x00 signifying the end
-** of the position-list, or the 0x01 that precedes the column number of
-** the next column in the position-list).
+** An instance of this structure is used to collect the 'global' part of
+** the matchinfo statistics. The 'global' part consists of the following:
+**
+** 1. The number of phrases in the query (nPhrase).
+**
+** 2. The number of columns in the FTS3 table (nCol).
**
-** The number of elements in the column-list is returned.
+** 3. A matrix of (nPhrase*nCol) integers containing the sum of the
+** number of hits for each phrase in each column across all rows
+** of the table.
+**
+** The total size of the global matchinfo array, assuming the number of
+** columns is N and the number of phrases is P is:
+**
+** 2 + P*(N+1)
+**
+** The number of hits for the 3rd phrase in the second column is found
+** using the expression:
+**
+** aGlobal[2 + P*(1+2) + 1]
+*/
+typedef struct MatchInfo MatchInfo;
+struct MatchInfo {
+ Fts3Table *pTab; /* FTS3 Table */
+ Fts3Cursor *pCursor; /* FTS3 Cursor */
+ int iPhrase; /* Number of phrases so far */
+ int nCol; /* Number of columns in table */
+ u32 *aGlobal; /* Pre-allocated buffer */
+};
+
+/*
+** This function is used to count the entries in a column-list (delta-encoded
+** list of term offsets within a single column of a single row).
*/
static int fts3ColumnlistCount(char **ppCollist){
char *pEnd = *ppCollist;
@@ -113888,21 +107381,15 @@ static int fts3ColumnlistCount(char **ppCollist){
return nEntry;
}
-static void fts3LoadColumnlistCounts(char **pp, u32 *aOut, int isGlobal){
+static void fts3LoadColumnlistCounts(char **pp, u32 *aOut){
char *pCsr = *pp;
while( *pCsr ){
- int nHit;
sqlite3_int64 iCol = 0;
if( *pCsr==0x01 ){
pCsr++;
pCsr += sqlite3Fts3GetVarint(pCsr, &iCol);
}
- nHit = fts3ColumnlistCount(&pCsr);
- assert( nHit>0 );
- if( isGlobal ){
- aOut[iCol*3+1]++;
- }
- aOut[iCol*3] += nHit;
+ aOut[iCol] += fts3ColumnlistCount(&pCsr);
}
pCsr++;
*pp = pCsr;
@@ -113910,18 +107397,16 @@ static void fts3LoadColumnlistCounts(char **pp, u32 *aOut, int isGlobal){
/*
** fts3ExprIterate() callback used to collect the "global" matchinfo stats
-** for a single query. The "global" stats are those elements of the matchinfo
-** array that are constant for all rows returned by the current query.
+** for a single query.
*/
static int fts3ExprGlobalMatchinfoCb(
Fts3Expr *pExpr, /* Phrase expression node */
- int iPhrase, /* Phrase number (numbered from zero) */
void *pCtx /* Pointer to MatchInfo structure */
){
MatchInfo *p = (MatchInfo *)pCtx;
char *pCsr;
char *pEnd;
- const int iStart = 2 + (iPhrase * p->nCol * 3) + 1;
+ const int iStart = 2 + p->nCol*p->iPhrase;
assert( pExpr->isLoaded );
@@ -113929,108 +107414,84 @@ static int fts3ExprGlobalMatchinfoCb(
pCsr = pExpr->aDoclist;
pEnd = &pExpr->aDoclist[pExpr->nDoclist];
while( pCsr<pEnd ){
- while( *pCsr++ & 0x80 ); /* Skip past docid. */
- fts3LoadColumnlistCounts(&pCsr, &p->aMatchinfo[iStart], 1);
+ while( *pCsr++ & 0x80 );
+ fts3LoadColumnlistCounts(&pCsr, &p->aGlobal[iStart]);
}
+ p->iPhrase++;
return SQLITE_OK;
}
-/*
-** fts3ExprIterate() callback used to collect the "local" matchinfo stats
-** for a single query. The "local" stats are those elements of the matchinfo
-** array that are different for each row returned by the query.
-*/
static int fts3ExprLocalMatchinfoCb(
Fts3Expr *pExpr, /* Phrase expression node */
- int iPhrase, /* Phrase number */
void *pCtx /* Pointer to MatchInfo structure */
){
MatchInfo *p = (MatchInfo *)pCtx;
+ int iPhrase = p->iPhrase++;
if( pExpr->aDoclist ){
char *pCsr;
- int iStart = 2 + (iPhrase * p->nCol * 3);
- int i;
-
- for(i=0; i<p->nCol; i++) p->aMatchinfo[iStart+i*3] = 0;
+ int iOffset = 2 + p->nCol*(p->aGlobal[0]+iPhrase);
+ memset(&p->aGlobal[iOffset], 0, p->nCol*sizeof(u32));
pCsr = sqlite3Fts3FindPositions(pExpr, p->pCursor->iPrevId, -1);
- if( pCsr ){
- fts3LoadColumnlistCounts(&pCsr, &p->aMatchinfo[iStart], 0);
- }
+ if( pCsr ) fts3LoadColumnlistCounts(&pCsr, &p->aGlobal[iOffset]);
}
return SQLITE_OK;
}
/*
-** Populate pCsr->aMatchinfo[] with data for the current row. The
-** 'matchinfo' data is an array of 32-bit unsigned integers (C type u32).
+** Populate pCsr->aMatchinfo[] with data for the current row. The 'matchinfo'
+** data is an array of 32-bit unsigned integers (C type u32).
*/
static int fts3GetMatchinfo(Fts3Cursor *pCsr){
- MatchInfo sInfo;
+ MatchInfo g;
Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
- int rc = SQLITE_OK;
-
- sInfo.pCursor = pCsr;
- sInfo.nCol = pTab->nColumn;
-
if( pCsr->aMatchinfo==0 ){
- /* If Fts3Cursor.aMatchinfo[] is NULL, then this is the first time the
- ** matchinfo function has been called for this query. In this case
- ** allocate the array used to accumulate the matchinfo data and
- ** initialize those elements that are constant for every row.
- */
- int nPhrase; /* Number of phrases */
- int nMatchinfo; /* Number of u32 elements in match-info */
+ int rc;
+ int nPhrase;
+ int nMatchinfo;
- /* Load doclists for each phrase in the query. */
- rc = fts3ExprLoadDoclists(pCsr, &nPhrase, 0);
+ g.pTab = pTab;
+ g.nCol = pTab->nColumn;
+ g.iPhrase = 0;
+ rc = fts3ExprLoadDoclists(pCsr, &nPhrase);
if( rc!=SQLITE_OK ){
return rc;
}
- nMatchinfo = 2 + 3*sInfo.nCol*nPhrase;
- if( pTab->bHasDocsize ){
- nMatchinfo += 1 + 2*pTab->nColumn;
- }
- sInfo.aMatchinfo = (u32 *)sqlite3_malloc(sizeof(u32)*nMatchinfo);
- if( !sInfo.aMatchinfo ){
+ nMatchinfo = 2 + 2*g.nCol*nPhrase;
+
+ g.iPhrase = 0;
+ g.aGlobal = (u32 *)sqlite3_malloc(sizeof(u32)*nMatchinfo);
+ if( !g.aGlobal ){
return SQLITE_NOMEM;
}
- memset(sInfo.aMatchinfo, 0, sizeof(u32)*nMatchinfo);
+ memset(g.aGlobal, 0, sizeof(u32)*nMatchinfo);
+ g.aGlobal[0] = nPhrase;
+ g.aGlobal[1] = g.nCol;
+ (void)fts3ExprIterate(pCsr->pExpr, fts3ExprGlobalMatchinfoCb, (void *)&g);
- /* First element of match-info is the number of phrases in the query */
- sInfo.aMatchinfo[0] = nPhrase;
- sInfo.aMatchinfo[1] = sInfo.nCol;
- (void)fts3ExprIterate(pCsr->pExpr, fts3ExprGlobalMatchinfoCb,(void*)&sInfo);
- if( pTab->bHasDocsize ){
- int ofst = 2 + 3*sInfo.aMatchinfo[0]*sInfo.aMatchinfo[1];
- rc = sqlite3Fts3MatchinfoDocsizeGlobal(pCsr, &sInfo.aMatchinfo[ofst]);
- }
- pCsr->aMatchinfo = sInfo.aMatchinfo;
- pCsr->isMatchinfoNeeded = 1;
+ pCsr->aMatchinfo = g.aGlobal;
}
- sInfo.aMatchinfo = pCsr->aMatchinfo;
- if( rc==SQLITE_OK && pCsr->isMatchinfoNeeded ){
- (void)fts3ExprIterate(pCsr->pExpr, fts3ExprLocalMatchinfoCb, (void*)&sInfo);
- if( pTab->bHasDocsize ){
- int ofst = 2 + 3*sInfo.aMatchinfo[0]*sInfo.aMatchinfo[1];
- rc = sqlite3Fts3MatchinfoDocsizeLocal(pCsr, &sInfo.aMatchinfo[ofst]);
- }
- pCsr->isMatchinfoNeeded = 0;
+ g.pTab = pTab;
+ g.pCursor = pCsr;
+ g.nCol = pTab->nColumn;
+ g.iPhrase = 0;
+ g.aGlobal = pCsr->aMatchinfo;
+
+ if( pCsr->isMatchinfoOk ){
+ (void)fts3ExprIterate(pCsr->pExpr, fts3ExprLocalMatchinfoCb, (void *)&g);
+ pCsr->isMatchinfoOk = 0;
}
return SQLITE_OK;
}
-/*
-** Implementation of snippet() function.
-*/
-SQLITE_PRIVATE void sqlite3Fts3Snippet(
+SQLITE_PRIVATE void sqlite3Fts3Snippet2(
sqlite3_context *pCtx, /* SQLite function call context */
Fts3Cursor *pCsr, /* Cursor object */
const char *zStart, /* Snippet start text - "<b>" */
@@ -114039,292 +107500,35 @@ SQLITE_PRIVATE void sqlite3Fts3Snippet(
int iCol, /* Extract snippet from this column */
int nToken /* Approximate number of tokens in snippet */
){
- Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
- int rc = SQLITE_OK;
- int i;
- StrBuffer res = {0, 0, 0};
-
- /* The returned text includes up to four fragments of text extracted from
- ** the data in the current row. The first iteration of the for(...) loop
- ** below attempts to locate a single fragment of text nToken tokens in
- ** size that contains at least one instance of all phrases in the query
- ** expression that appear in the current row. If such a fragment of text
- ** cannot be found, the second iteration of the loop attempts to locate
- ** a pair of fragments, and so on.
- */
- int nSnippet = 0; /* Number of fragments in this snippet */
- SnippetFragment aSnippet[4]; /* Maximum of 4 fragments per snippet */
- int nFToken = -1; /* Number of tokens in each fragment */
-
- if( !pCsr->pExpr ){
- sqlite3_result_text(pCtx, "", 0, SQLITE_STATIC);
- return;
- }
-
- for(nSnippet=1; 1; nSnippet++){
-
- int iSnip; /* Loop counter 0..nSnippet-1 */
- u64 mCovered = 0; /* Bitmask of phrases covered by snippet */
- u64 mSeen = 0; /* Bitmask of phrases seen by BestSnippet() */
-
- if( nToken>=0 ){
- nFToken = (nToken+nSnippet-1) / nSnippet;
- }else{
- nFToken = -1 * nToken;
- }
-
- for(iSnip=0; iSnip<nSnippet; iSnip++){
- int iBestScore = -1; /* Best score of columns checked so far */
- int iRead; /* Used to iterate through columns */
- SnippetFragment *pFragment = &aSnippet[iSnip];
-
- memset(pFragment, 0, sizeof(*pFragment));
-
- /* Loop through all columns of the table being considered for snippets.
- ** If the iCol argument to this function was negative, this means all
- ** columns of the FTS3 table. Otherwise, only column iCol is considered.
- */
- for(iRead=0; iRead<pTab->nColumn; iRead++){
- SnippetFragment sF;
- int iS;
- if( iCol>=0 && iRead!=iCol ) continue;
-
- /* Find the best snippet of nFToken tokens in column iRead. */
- rc = fts3BestSnippet(nFToken, pCsr, iRead, mCovered, &mSeen, &sF, &iS);
- if( rc!=SQLITE_OK ){
- goto snippet_out;
- }
- if( iS>iBestScore ){
- *pFragment = sF;
- iBestScore = iS;
- }
- }
-
- mCovered |= pFragment->covered;
- }
+ int rc;
+ int iPos = 0;
+ u64 hlmask = 0;
+ char *z = 0;
+ int nDoc;
+ const char *zDoc;
- /* If all query phrases seen by fts3BestSnippet() are present in at least
- ** one of the nSnippet snippet fragments, break out of the loop.
- */
- assert( (mCovered&mSeen)==mCovered );
- if( mSeen==mCovered || nSnippet==SizeofArray(aSnippet) ) break;
- }
+ rc = fts3BestSnippet(nToken, pCsr, iCol, &iPos, &hlmask);
- assert( nFToken>0 );
+ nDoc = sqlite3_column_bytes(pCsr->pStmt, iCol+1);
+ zDoc = (const char *)sqlite3_column_text(pCsr->pStmt, iCol+1);
- for(i=0; i<nSnippet && rc==SQLITE_OK; i++){
- rc = fts3SnippetText(pCsr, &aSnippet[i],
- i, (i==nSnippet-1), nFToken, zStart, zEnd, zEllipsis, &res
- );
+ if( rc==SQLITE_OK ){
+ rc = fts3SnippetText(
+ pCsr, zDoc, nDoc, nToken, iPos, hlmask, zStart, zEnd, zEllipsis, &z);
}
-
- snippet_out:
if( rc!=SQLITE_OK ){
sqlite3_result_error_code(pCtx, rc);
- sqlite3_free(res.z);
}else{
- sqlite3_result_text(pCtx, res.z, -1, sqlite3_free);
+ sqlite3_result_text(pCtx, z, -1, sqlite3_free);
}
}
-
-typedef struct TermOffset TermOffset;
-typedef struct TermOffsetCtx TermOffsetCtx;
-
-struct TermOffset {
- char *pList; /* Position-list */
- int iPos; /* Position just read from pList */
- int iOff; /* Offset of this term from read positions */
-};
-
-struct TermOffsetCtx {
- int iCol; /* Column of table to populate aTerm for */
- int iTerm;
- sqlite3_int64 iDocid;
- TermOffset *aTerm;
-};
-
-/*
-** This function is an fts3ExprIterate() callback used by sqlite3Fts3Offsets().
-*/
-static int fts3ExprTermOffsetInit(Fts3Expr *pExpr, int iPhrase, void *ctx){
- TermOffsetCtx *p = (TermOffsetCtx *)ctx;
- int nTerm; /* Number of tokens in phrase */
- int iTerm; /* For looping through nTerm phrase terms */
- char *pList; /* Pointer to position list for phrase */
- int iPos = 0; /* First position in position-list */
-
- UNUSED_PARAMETER(iPhrase);
- pList = sqlite3Fts3FindPositions(pExpr, p->iDocid, p->iCol);
- nTerm = pExpr->pPhrase->nToken;
- if( pList ){
- fts3GetDeltaPosition(&pList, &iPos);
- assert( iPos>=0 );
- }
-
- for(iTerm=0; iTerm<nTerm; iTerm++){
- TermOffset *pT = &p->aTerm[p->iTerm++];
- pT->iOff = nTerm-iTerm-1;
- pT->pList = pList;
- pT->iPos = iPos;
- }
-
- return SQLITE_OK;
-}
-
-/*
-** Implementation of offsets() function.
-*/
-SQLITE_PRIVATE void sqlite3Fts3Offsets(
- sqlite3_context *pCtx, /* SQLite function call context */
- Fts3Cursor *pCsr /* Cursor object */
-){
- Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
- sqlite3_tokenizer_module const *pMod = pTab->pTokenizer->pModule;
- const char *ZDUMMY; /* Dummy argument used with xNext() */
- int NDUMMY; /* Dummy argument used with xNext() */
- int rc; /* Return Code */
- int nToken; /* Number of tokens in query */
- int iCol; /* Column currently being processed */
- StrBuffer res = {0, 0, 0}; /* Result string */
- TermOffsetCtx sCtx; /* Context for fts3ExprTermOffsetInit() */
-
- if( !pCsr->pExpr ){
- sqlite3_result_text(pCtx, "", 0, SQLITE_STATIC);
- return;
- }
-
- memset(&sCtx, 0, sizeof(sCtx));
- assert( pCsr->isRequireSeek==0 );
-
- /* Count the number of terms in the query */
- rc = fts3ExprLoadDoclists(pCsr, 0, &nToken);
- if( rc!=SQLITE_OK ) goto offsets_out;
-
- /* Allocate the array of TermOffset iterators. */
- sCtx.aTerm = (TermOffset *)sqlite3_malloc(sizeof(TermOffset)*nToken);
- if( 0==sCtx.aTerm ){
- rc = SQLITE_NOMEM;
- goto offsets_out;
- }
- sCtx.iDocid = pCsr->iPrevId;
-
- /* Loop through the table columns, appending offset information to
- ** string-buffer res for each column.
- */
- for(iCol=0; iCol<pTab->nColumn; iCol++){
- sqlite3_tokenizer_cursor *pC; /* Tokenizer cursor */
- int iStart;
- int iEnd;
- int iCurrent;
- const char *zDoc;
- int nDoc;
-
- /* Initialize the contents of sCtx.aTerm[] for column iCol. There is
- ** no way that this operation can fail, so the return code from
- ** fts3ExprIterate() can be discarded.
- */
- sCtx.iCol = iCol;
- sCtx.iTerm = 0;
- (void)fts3ExprIterate(pCsr->pExpr, fts3ExprTermOffsetInit, (void *)&sCtx);
-
- /* Retreive the text stored in column iCol. If an SQL NULL is stored
- ** in column iCol, jump immediately to the next iteration of the loop.
- ** If an OOM occurs while retrieving the data (this can happen if SQLite
- ** needs to transform the data from utf-16 to utf-8), return SQLITE_NOMEM
- ** to the caller.
- */
- zDoc = (const char *)sqlite3_column_text(pCsr->pStmt, iCol+1);
- nDoc = sqlite3_column_bytes(pCsr->pStmt, iCol+1);
- if( zDoc==0 ){
- if( sqlite3_column_type(pCsr->pStmt, iCol+1)==SQLITE_NULL ){
- continue;
- }
- rc = SQLITE_NOMEM;
- goto offsets_out;
- }
-
- /* Initialize a tokenizer iterator to iterate through column iCol. */
- rc = pMod->xOpen(pTab->pTokenizer, zDoc, nDoc, &pC);
- if( rc!=SQLITE_OK ) goto offsets_out;
- pC->pTokenizer = pTab->pTokenizer;
-
- rc = pMod->xNext(pC, &ZDUMMY, &NDUMMY, &iStart, &iEnd, &iCurrent);
- while( rc==SQLITE_OK ){
- int i; /* Used to loop through terms */
- int iMinPos = 0x7FFFFFFF; /* Position of next token */
- TermOffset *pTerm = 0; /* TermOffset associated with next token */
-
- for(i=0; i<nToken; i++){
- TermOffset *pT = &sCtx.aTerm[i];
- if( pT->pList && (pT->iPos-pT->iOff)<iMinPos ){
- iMinPos = pT->iPos-pT->iOff;
- pTerm = pT;
- }
- }
-
- if( !pTerm ){
- /* All offsets for this column have been gathered. */
- break;
- }else{
- assert( iCurrent<=iMinPos );
- if( 0==(0xFE&*pTerm->pList) ){
- pTerm->pList = 0;
- }else{
- fts3GetDeltaPosition(&pTerm->pList, &pTerm->iPos);
- }
- while( rc==SQLITE_OK && iCurrent<iMinPos ){
- rc = pMod->xNext(pC, &ZDUMMY, &NDUMMY, &iStart, &iEnd, &iCurrent);
- }
- if( rc==SQLITE_OK ){
- char aBuffer[64];
- sqlite3_snprintf(sizeof(aBuffer), aBuffer,
- "%d %d %d %d ", iCol, pTerm-sCtx.aTerm, iStart, iEnd-iStart
- );
- rc = fts3StringAppend(&res, aBuffer, -1);
- }else if( rc==SQLITE_DONE ){
- rc = SQLITE_CORRUPT;
- }
- }
- }
- if( rc==SQLITE_DONE ){
- rc = SQLITE_OK;
- }
-
- pMod->xClose(pC);
- if( rc!=SQLITE_OK ) goto offsets_out;
- }
-
- offsets_out:
- sqlite3_free(sCtx.aTerm);
- assert( rc!=SQLITE_DONE );
- if( rc!=SQLITE_OK ){
- sqlite3_result_error_code(pCtx, rc);
- sqlite3_free(res.z);
- }else{
- sqlite3_result_text(pCtx, res.z, res.n-1, sqlite3_free);
- }
- return;
-}
-
-/*
-** Implementation of matchinfo() function.
-*/
SQLITE_PRIVATE void sqlite3Fts3Matchinfo(sqlite3_context *pContext, Fts3Cursor *pCsr){
- int rc;
- if( !pCsr->pExpr ){
- sqlite3_result_blob(pContext, "", 0, SQLITE_STATIC);
- return;
- }
- rc = fts3GetMatchinfo(pCsr);
+ int rc = fts3GetMatchinfo(pCsr);
if( rc!=SQLITE_OK ){
sqlite3_result_error_code(pContext, rc);
}else{
- Fts3Table *pTab = (Fts3Table*)pCsr->base.pVtab;
- int n = sizeof(u32)*(2+pCsr->aMatchinfo[0]*pCsr->aMatchinfo[1]*3);
- if( pTab->bHasDocsize ){
- n += sizeof(u32)*(1 + 2*pTab->nColumn);
- }
+ int n = sizeof(u32)*(2+pCsr->aMatchinfo[0]*pCsr->aMatchinfo[1]*2);
sqlite3_result_blob(pContext, pCsr->aMatchinfo, n, SQLITE_TRANSIENT);
}
}
@@ -114352,19 +107556,19 @@ SQLITE_PRIVATE void sqlite3Fts3Matchinfo(sqlite3_context *pContext, Fts3Cursor *
/*
** This file contains an implementation of a couple of different variants
-** of the r-tree algorithm. See the README file for further details. The
+** of the r-tree algorithm. See the README file for further details. The
** same data-structure is used for all, but the algorithms for insert and
-** delete operations vary. The variants used are selected at compile time
+** delete operations vary. The variants used are selected at compile time
** by defining the following symbols:
*/
-/* Either, both or none of the following may be set to activate
+/* Either, both or none of the following may be set to activate
** r*tree variant algorithms.
*/
#define VARIANT_RSTARTREE_CHOOSESUBTREE 0
#define VARIANT_RSTARTREE_REINSERT 1
-/*
+/*
** Exactly one of the following must be set to 1.
*/
#define VARIANT_GUTTMAN_QUADRATIC_SPLIT 0
@@ -114412,12 +107616,12 @@ typedef union RtreeCoord RtreeCoord;
#define RTREE_MAX_DIMENSIONS 5
/* Size of hash table Rtree.aHash. This hash table is not expected to
-** ever contain very many entries, so a fixed number of buckets is
+** ever contain very many entries, so a fixed number of buckets is
** used.
*/
#define HASHSIZE 128
-/*
+/*
** An rtree virtual-table object.
*/
struct Rtree {
@@ -114428,13 +107632,13 @@ struct Rtree {
int nBytesPerCell; /* Bytes consumed per cell */
int iDepth; /* Current depth of the r-tree structure */
char *zDb; /* Name of database containing r-tree table */
- char *zName; /* Name of r-tree table */
- RtreeNode *aHash[HASHSIZE]; /* Hash table of in-memory nodes. */
+ char *zName; /* Name of r-tree table */
+ RtreeNode *aHash[HASHSIZE]; /* Hash table of in-memory nodes. */
int nBusy; /* Current number of users of this structure */
/* List of nodes removed during a CondenseTree operation. List is
** linked together via the pointer normally used for hash chains -
- ** RtreeNode.pNext. RtreeNode.iNode stores the depth of the sub-tree
+ ** RtreeNode.pNext. RtreeNode.iNode stores the depth of the sub-tree
** headed by the node (leaf nodes have RtreeNode.iNode==0).
*/
RtreeNode *pDeleted;
@@ -114463,7 +107667,7 @@ struct Rtree {
#define RTREE_COORD_INT32 1
/*
-** The minimum number of cells allowed for a node is a third of the
+** The minimum number of cells allowed for a node is a third of the
** maximum. In Gutman's notation:
**
** m = M/3
@@ -114475,7 +107679,7 @@ struct Rtree {
#define RTREE_REINSERT(p) RTREE_MINCELLS(p)
#define RTREE_MAXCELLS 51
-/*
+/*
** An rtree cursor object.
*/
struct RtreeCursor {
@@ -114519,7 +107723,7 @@ struct RtreeConstraint {
#define RTREE_GE 0x44
#define RTREE_GT 0x45
-/*
+/*
** An rtree structure node.
**
** Data format (RtreeNode.zData):
@@ -114528,7 +107732,7 @@ struct RtreeConstraint {
** of the node contain the tree depth as a big-endian integer.
** For non-root nodes, the first 2 bytes are left unused.
**
-** 2. The next 2 bytes contain the number of entries currently
+** 2. The next 2 bytes contain the number of entries currently
** stored in the node.
**
** 3. The remainder of the node contains the node entries. Each entry
@@ -114547,7 +107751,7 @@ struct RtreeNode {
};
#define NCELL(pNode) readInt16(&(pNode)->zData[2])
-/*
+/*
** Structure to store a deserialized rtree record.
*/
struct RtreeCell {
@@ -114571,22 +107775,22 @@ static int readInt16(u8 *p){
}
static void readCoord(u8 *p, RtreeCoord *pCoord){
u32 i = (
- (((u32)p[0]) << 24) +
- (((u32)p[1]) << 16) +
- (((u32)p[2]) << 8) +
+ (((u32)p[0]) << 24) +
+ (((u32)p[1]) << 16) +
+ (((u32)p[2]) << 8) +
(((u32)p[3]) << 0)
);
*(u32 *)pCoord = i;
}
static i64 readInt64(u8 *p){
return (
- (((i64)p[0]) << 56) +
- (((i64)p[1]) << 48) +
- (((i64)p[2]) << 40) +
- (((i64)p[3]) << 32) +
- (((i64)p[4]) << 24) +
- (((i64)p[5]) << 16) +
- (((i64)p[6]) << 8) +
+ (((i64)p[0]) << 56) +
+ (((i64)p[1]) << 48) +
+ (((i64)p[2]) << 40) +
+ (((i64)p[3]) << 32) +
+ (((i64)p[4]) << 24) +
+ (((i64)p[5]) << 16) +
+ (((i64)p[6]) << 8) +
(((i64)p[7]) << 0)
);
}
@@ -114649,7 +107853,7 @@ static void nodeZero(Rtree *pRtree, RtreeNode *p){
*/
static int nodeHash(i64 iNode){
return (
- (iNode>>56) ^ (iNode>>48) ^ (iNode>>40) ^ (iNode>>32) ^
+ (iNode>>56) ^ (iNode>>48) ^ (iNode>>40) ^ (iNode>>32) ^
(iNode>>24) ^ (iNode>>16) ^ (iNode>> 8) ^ (iNode>> 0)
) % HASHSIZE;
}
@@ -114754,7 +107958,6 @@ nodeAcquire(
rc = sqlite3_step(pRtree->pReadNode);
if( rc==SQLITE_ROW ){
const u8 *zBlob = sqlite3_column_blob(pRtree->pReadNode, 0);
- assert( sqlite3_column_bytes(pRtree->pReadNode, 0)==pRtree->iNodeSize );
memcpy(pNode->zData, zBlob, pRtree->iNodeSize);
nodeReference(pParent);
}else{
@@ -114779,9 +107982,9 @@ nodeAcquire(
** Overwrite cell iCell of node pNode with the contents of pCell.
*/
static void nodeOverwriteCell(
- Rtree *pRtree,
- RtreeNode *pNode,
- RtreeCell *pCell,
+ Rtree *pRtree,
+ RtreeNode *pNode,
+ RtreeCell *pCell,
int iCell
){
int ii;
@@ -114813,9 +108016,9 @@ static void nodeDeleteCell(Rtree *pRtree, RtreeNode *pNode, int iCell){
*/
static int
nodeInsertCell(
- Rtree *pRtree,
- RtreeNode *pNode,
- RtreeCell *pCell
+ Rtree *pRtree,
+ RtreeNode *pNode,
+ RtreeCell *pCell
){
int nCell; /* Current number of cells in pNode */
int nMaxCell; /* Maximum number of cells for pNode */
@@ -114892,8 +108095,8 @@ nodeRelease(Rtree *pRtree, RtreeNode *pNode){
** an internal node, then the 64-bit integer is a child page number.
*/
static i64 nodeGetRowid(
- Rtree *pRtree,
- RtreeNode *pNode,
+ Rtree *pRtree,
+ RtreeNode *pNode,
int iCell
){
assert( iCell<NCELL(pNode) );
@@ -114904,8 +108107,8 @@ static i64 nodeGetRowid(
** Return coordinate iCoord from cell iCell in node pNode.
*/
static void nodeGetCoord(
- Rtree *pRtree,
- RtreeNode *pNode,
+ Rtree *pRtree,
+ RtreeNode *pNode,
int iCell,
int iCoord,
RtreeCoord *pCoord /* Space to write result to */
@@ -114918,8 +108121,8 @@ static void nodeGetCoord(
** to by pCell with the results.
*/
static void nodeGetCell(
- Rtree *pRtree,
- RtreeNode *pNode,
+ Rtree *pRtree,
+ RtreeNode *pNode,
int iCell,
RtreeCell *pCell
){
@@ -114938,7 +108141,7 @@ static int rtreeInit(
sqlite3 *, void *, int, const char *const*, sqlite3_vtab **, char **, int
);
-/*
+/*
** Rtree virtual table module xCreate method.
*/
static int rtreeCreate(
@@ -114951,7 +108154,7 @@ static int rtreeCreate(
return rtreeInit(db, pAux, argc, argv, ppVtab, pzErr, 1);
}
-/*
+/*
** Rtree virtual table module xConnect method.
*/
static int rtreeConnect(
@@ -114991,7 +108194,7 @@ static void rtreeRelease(Rtree *pRtree){
}
}
-/*
+/*
** Rtree virtual table module xDisconnect method.
*/
static int rtreeDisconnect(sqlite3_vtab *pVtab){
@@ -114999,7 +108202,7 @@ static int rtreeDisconnect(sqlite3_vtab *pVtab){
return SQLITE_OK;
}
-/*
+/*
** Rtree virtual table module xDestroy method.
*/
static int rtreeDestroy(sqlite3_vtab *pVtab){
@@ -115009,7 +108212,7 @@ static int rtreeDestroy(sqlite3_vtab *pVtab){
"DROP TABLE '%q'.'%q_node';"
"DROP TABLE '%q'.'%q_rowid';"
"DROP TABLE '%q'.'%q_parent';",
- pRtree->zDb, pRtree->zName,
+ pRtree->zDb, pRtree->zName,
pRtree->zDb, pRtree->zName,
pRtree->zDb, pRtree->zName
);
@@ -115026,7 +108229,7 @@ static int rtreeDestroy(sqlite3_vtab *pVtab){
return rc;
}
-/*
+/*
** Rtree virtual table module xOpen method.
*/
static int rtreeOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
@@ -115044,7 +108247,7 @@ static int rtreeOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
return rc;
}
-/*
+/*
** Rtree virtual table module xClose method.
*/
static int rtreeClose(sqlite3_vtab_cursor *cur){
@@ -115060,7 +108263,7 @@ static int rtreeClose(sqlite3_vtab_cursor *cur){
/*
** Rtree virtual table module xEof method.
**
-** Return non-zero if the cursor does not currently point to a valid
+** Return non-zero if the cursor does not currently point to a valid
** record (i.e if the scan has finished), or zero otherwise.
*/
static int rtreeEof(sqlite3_vtab_cursor *cur){
@@ -115068,10 +108271,10 @@ static int rtreeEof(sqlite3_vtab_cursor *cur){
return (pCsr->pNode==0);
}
-/*
+/*
** Cursor pCursor currently points to a cell in a non-leaf page.
** Return true if the sub-tree headed by the cell is filtered
-** (excluded) by the constraints in the pCursor->aConstraint[]
+** (excluded) by the constraints in the pCursor->aConstraint[]
** array, or false otherwise.
*/
static int testRtreeCell(Rtree *pRtree, RtreeCursor *pCursor){
@@ -115085,14 +108288,14 @@ static int testRtreeCell(Rtree *pRtree, RtreeCursor *pCursor){
double cell_min = DCOORD(cell.aCoord[(p->iCoord>>1)*2]);
double cell_max = DCOORD(cell.aCoord[(p->iCoord>>1)*2+1]);
- assert(p->op==RTREE_LE || p->op==RTREE_LT || p->op==RTREE_GE
+ assert(p->op==RTREE_LE || p->op==RTREE_LT || p->op==RTREE_GE
|| p->op==RTREE_GT || p->op==RTREE_EQ
);
switch( p->op ){
case RTREE_LE: case RTREE_LT: bRes = p->rValue<cell_min; break;
case RTREE_GE: case RTREE_GT: bRes = p->rValue>cell_max; break;
- case RTREE_EQ:
+ case RTREE_EQ:
bRes = (p->rValue>cell_max || p->rValue<cell_min);
break;
}
@@ -115101,9 +108304,9 @@ static int testRtreeCell(Rtree *pRtree, RtreeCursor *pCursor){
return bRes;
}
-/*
+/*
** Return true if the cell that cursor pCursor currently points to
-** would be filtered (excluded) by the constraints in the
+** would be filtered (excluded) by the constraints in the
** pCursor->aConstraint[] array, or false otherwise.
**
** This function assumes that the cell is part of a leaf node.
@@ -115117,7 +108320,7 @@ static int testRtreeEntry(Rtree *pRtree, RtreeCursor *pCursor){
RtreeConstraint *p = &pCursor->aConstraint[ii];
double coord = DCOORD(cell.aCoord[p->iCoord]);
int res;
- assert(p->op==RTREE_LE || p->op==RTREE_LT || p->op==RTREE_GE
+ assert(p->op==RTREE_LE || p->op==RTREE_LT || p->op==RTREE_GE
|| p->op==RTREE_GT || p->op==RTREE_EQ
);
switch( p->op ){
@@ -115137,12 +108340,12 @@ static int testRtreeEntry(Rtree *pRtree, RtreeCursor *pCursor){
/*
** Cursor pCursor currently points at a node that heads a sub-tree of
** height iHeight (if iHeight==0, then the node is a leaf). Descend
-** to point to the left-most cell of the sub-tree that matches the
+** to point to the left-most cell of the sub-tree that matches the
** configured constraints.
*/
static int descendToCell(
- Rtree *pRtree,
- RtreeCursor *pCursor,
+ Rtree *pRtree,
+ RtreeCursor *pCursor,
int iHeight,
int *pEof /* OUT: Set to true if cannot descend */
){
@@ -115197,7 +108400,7 @@ static int descendToCell(
}
/*
-** One of the cells in node pNode is guaranteed to have a 64-bit
+** One of the cells in node pNode is guaranteed to have a 64-bit
** integer value equal to iRowid. Return the index of this cell.
*/
static int nodeRowidIndex(Rtree *pRtree, RtreeNode *pNode, i64 iRowid){
@@ -115220,7 +108423,7 @@ static int nodeParentIndex(Rtree *pRtree, RtreeNode *pNode){
return -1;
}
-/*
+/*
** Rtree virtual table module xNext method.
*/
static int rtreeNext(sqlite3_vtab_cursor *pVtabCursor){
@@ -115258,7 +108461,7 @@ static int rtreeNext(sqlite3_vtab_cursor *pVtabCursor){
return rc;
}
-/*
+/*
** Rtree virtual table module xRowid method.
*/
static int rtreeRowid(sqlite3_vtab_cursor *pVtabCursor, sqlite_int64 *pRowid){
@@ -115271,7 +108474,7 @@ static int rtreeRowid(sqlite3_vtab_cursor *pVtabCursor, sqlite_int64 *pRowid){
return SQLITE_OK;
}
-/*
+/*
** Rtree virtual table module xColumn method.
*/
static int rtreeColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){
@@ -115295,8 +108498,8 @@ static int rtreeColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){
return SQLITE_OK;
}
-/*
-** Use nodeAcquire() to obtain the leaf node containing the record with
+/*
+** Use nodeAcquire() to obtain the leaf node containing the record with
** rowid iRowid. If successful, set *ppLeaf to point to the node and
** return SQLITE_OK. If there is no such record in the table, set
** *ppLeaf to 0 and return SQLITE_OK. If an error occurs, set *ppLeaf
@@ -115317,11 +108520,11 @@ static int findLeafNode(Rtree *pRtree, i64 iRowid, RtreeNode **ppLeaf){
}
-/*
+/*
** Rtree virtual table module xFilter method.
*/
static int rtreeFilter(
- sqlite3_vtab_cursor *pVtabCursor,
+ sqlite3_vtab_cursor *pVtabCursor,
int idxNum, const char *idxStr,
int argc, sqlite3_value **argv
){
@@ -115343,13 +108546,13 @@ static int rtreeFilter(
RtreeNode *pLeaf; /* Leaf on which the required cell resides */
i64 iRowid = sqlite3_value_int64(argv[0]);
rc = findLeafNode(pRtree, iRowid, &pLeaf);
- pCsr->pNode = pLeaf;
+ pCsr->pNode = pLeaf;
if( pLeaf && rc==SQLITE_OK ){
pCsr->iCell = nodeRowidIndex(pRtree, pLeaf, iRowid);
}
}else{
- /* Normal case - r-tree scan. Set up the RtreeCursor.aConstraint array
- ** with the configured constraints.
+ /* Normal case - r-tree scan. Set up the RtreeCursor.aConstraint array
+ ** with the configured constraints.
*/
if( argc>0 ){
pCsr->aConstraint = sqlite3_malloc(sizeof(RtreeConstraint)*argc);
@@ -115366,7 +108569,7 @@ static int rtreeFilter(
}
}
}
-
+
if( rc==SQLITE_OK ){
pCsr->pNode = 0;
rc = nodeAcquire(pRtree, 1, 0, &pRoot);
@@ -115397,7 +108600,7 @@ static int rtreeFilter(
/*
** Rtree virtual table module xBestIndex method. There are three
-** table scan strategies to choose from (in order from most to
+** table scan strategies to choose from (in order from most to
** least desirable):
**
** idxNum idxStr Strategy
@@ -115408,8 +108611,8 @@ static int rtreeFilter(
** ------------------------------------------------
**
** If strategy 1 or 3 is used, then idxStr is not meaningful. If strategy
-** 2 is used, idxStr is formatted to contain 2 bytes for each
-** constraint used. The first two bytes of idxStr correspond to
+** 2 is used, idxStr is formatted to contain 2 bytes for each
+** constraint used. The first two bytes of idxStr correspond to
** the constraint in sqlite3_index_info.aConstraintUsage[] with
** (argvIndex==1) etc.
**
@@ -115453,10 +108656,10 @@ static int rtreeBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
pIdxInfo->aConstraintUsage[jj].omit = 1;
/* This strategy involves a two rowid lookups on an B-Tree structures
- ** and then a linear search of an R-Tree node. This should be
- ** considered almost as quick as a direct rowid lookup (for which
+ ** and then a linear search of an R-Tree node. This should be
+ ** considered almost as quick as a direct rowid lookup (for which
** sqlite uses an internal cost of 0.0).
- */
+ */
pIdxInfo->estimatedCost = 10.0;
return SQLITE_OK;
}
@@ -115569,8 +108772,8 @@ static int cellContains(Rtree *pRtree, RtreeCell *p1, RtreeCell *p2){
for(ii=0; ii<(pRtree->nDim*2); ii+=2){
RtreeCoord *a1 = &p1->aCoord[ii];
RtreeCoord *a2 = &p2->aCoord[ii];
- if( (!isInt && (a2[0].f<a1[0].f || a2[1].f>a1[1].f))
- || ( isInt && (a2[0].i<a1[0].i || a2[1].i>a1[1].i))
+ if( (!isInt && (a2[0].f<a1[0].f || a2[1].f>a1[1].f))
+ || ( isInt && (a2[0].i<a1[0].i || a2[1].i>a1[1].i))
){
return 0;
}
@@ -115592,10 +108795,10 @@ static float cellGrowth(Rtree *pRtree, RtreeCell *p, RtreeCell *pCell){
#if VARIANT_RSTARTREE_CHOOSESUBTREE || VARIANT_RSTARTREE_SPLIT
static float cellOverlap(
- Rtree *pRtree,
- RtreeCell *p,
- RtreeCell *aCell,
- int nCell,
+ Rtree *pRtree,
+ RtreeCell *p,
+ RtreeCell *aCell,
+ int nCell,
int iExclude
){
int ii;
@@ -115627,11 +108830,11 @@ static float cellOverlap(
#if VARIANT_RSTARTREE_CHOOSESUBTREE
static float cellOverlapEnlargement(
- Rtree *pRtree,
- RtreeCell *p,
- RtreeCell *pInsert,
- RtreeCell *aCell,
- int nCell,
+ Rtree *pRtree,
+ RtreeCell *p,
+ RtreeCell *pInsert,
+ RtreeCell *aCell,
+ int nCell,
int iExclude
){
float before;
@@ -115705,8 +108908,8 @@ static int ChooseLeaf(
overlap = cellOverlapEnlargement(pRtree,&cell,pCell,aCell,nCell,iCell);
}
#endif
- if( (iCell==0)
- || (overlap<fMinOverlap)
+ if( (iCell==0)
+ || (overlap<fMinOverlap)
|| (overlap==fMinOverlap && growth<fMinGrowth)
|| (overlap==fMinOverlap && growth==fMinGrowth && area<fMinArea)
){
@@ -115748,7 +108951,7 @@ static void AdjustTree(
cellUnion(pRtree, &cell, pCell);
nodeOverwriteCell(pRtree, pParent, &cell, iCell);
}
-
+
p = pParent;
}
}
@@ -115782,9 +108985,9 @@ static int rtreeInsertCell(Rtree *, RtreeNode *, RtreeCell *, int);
*/
static RtreeCell *LinearPickNext(
Rtree *pRtree,
- RtreeCell *aCell,
- int nCell,
- RtreeCell *pLeftBox,
+ RtreeCell *aCell,
+ int nCell,
+ RtreeCell *pLeftBox,
RtreeCell *pRightBox,
int *aiUsed
){
@@ -115800,9 +109003,9 @@ static RtreeCell *LinearPickNext(
*/
static void LinearPickSeeds(
Rtree *pRtree,
- RtreeCell *aCell,
- int nCell,
- int *piLeftSeed,
+ RtreeCell *aCell,
+ int nCell,
+ int *piLeftSeed,
int *piRightSeed
){
int i;
@@ -115811,7 +109014,7 @@ static void LinearPickSeeds(
float maxNormalInnerWidth = 0.0;
/* Pick two "seed" cells from the array of cells. The algorithm used
- ** here is the LinearPickSeeds algorithm from Gutman[1984]. The
+ ** here is the LinearPickSeeds algorithm from Gutman[1984]. The
** indices of the two seed cells in the array are stored in local
** variables iLeftSeek and iRightSeed.
*/
@@ -115862,9 +109065,9 @@ static void LinearPickSeeds(
*/
static RtreeCell *QuadraticPickNext(
Rtree *pRtree,
- RtreeCell *aCell,
- int nCell,
- RtreeCell *pLeftBox,
+ RtreeCell *aCell,
+ int nCell,
+ RtreeCell *pLeftBox,
RtreeCell *pRightBox,
int *aiUsed
){
@@ -115894,9 +109097,9 @@ static RtreeCell *QuadraticPickNext(
*/
static void QuadraticPickSeeds(
Rtree *pRtree,
- RtreeCell *aCell,
- int nCell,
- int *piLeftSeed,
+ RtreeCell *aCell,
+ int nCell,
+ int *piLeftSeed,
int *piRightSeed
){
int ii;
@@ -115927,7 +109130,7 @@ static void QuadraticPickSeeds(
/*
** Arguments aIdx, aDistance and aSpare all point to arrays of size
-** nIdx. The aIdx array contains the set of integers from 0 to
+** nIdx. The aIdx array contains the set of integers from 0 to
** (nIdx-1) in no particular order. This function sorts the values
** in aIdx according to the indexed values in aDistance. For
** example, assuming the inputs:
@@ -115943,9 +109146,9 @@ static void QuadraticPickSeeds(
** sorting algorithm.
*/
static void SortByDistance(
- int *aIdx,
- int nIdx,
- float *aDistance,
+ int *aIdx,
+ int nIdx,
+ float *aDistance,
int *aSpare
){
if( nIdx>1 ){
@@ -115999,7 +109202,7 @@ static void SortByDistance(
/*
** Arguments aIdx, aCell and aSpare all point to arrays of size
-** nIdx. The aIdx array contains the set of integers from 0 to
+** nIdx. The aIdx array contains the set of integers from 0 to
** (nIdx-1) in no particular order. This function sorts the values
** in aIdx according to dimension iDim of the cells in aCell. The
** minimum value of dimension iDim is considered first, the
@@ -116010,10 +109213,10 @@ static void SortByDistance(
*/
static void SortByDimension(
Rtree *pRtree,
- int *aIdx,
- int nIdx,
- int iDim,
- RtreeCell *aCell,
+ int *aIdx,
+ int nIdx,
+ int iDim,
+ RtreeCell *aCell,
int *aSpare
){
if( nIdx>1 ){
@@ -116111,8 +109314,8 @@ static int splitNodeStartree(
int nLeft;
for(
- nLeft=RTREE_MINCELLS(pRtree);
- nLeft<=(nCell-RTREE_MINCELLS(pRtree));
+ nLeft=RTREE_MINCELLS(pRtree);
+ nLeft<=(nCell-RTREE_MINCELLS(pRtree));
nLeft++
){
RtreeCell left;
@@ -116202,8 +109405,8 @@ static int splitNodeGuttman(
for(i=nCell-2; i>0; i--){
RtreeCell *pNext;
pNext = PickNext(pRtree, aCell, nCell, pBboxLeft, pBboxRight, aiUsed);
- float diff =
- cellGrowth(pRtree, pBboxLeft, pNext) -
+ float diff =
+ cellGrowth(pRtree, pBboxLeft, pNext) -
cellGrowth(pRtree, pBboxRight, pNext)
;
if( (RTREE_MINCELLS(pRtree)-NCELL(pRight)==i)
@@ -116223,9 +109426,9 @@ static int splitNodeGuttman(
#endif
static int updateMapping(
- Rtree *pRtree,
- i64 iRowid,
- RtreeNode *pNode,
+ Rtree *pRtree,
+ i64 iRowid,
+ RtreeNode *pNode,
int iHeight
){
int (*xSetMapping)(Rtree *, sqlite3_int64, sqlite3_int64);
@@ -116261,7 +109464,7 @@ static int SplitNode(
RtreeCell leftbbox;
RtreeCell rightbbox;
- /* Allocate an array and populate it with a copy of pCell and
+ /* Allocate an array and populate it with a copy of pCell and
** all cells from node pLeft. Then zero the original node.
*/
aCell = sqlite3_malloc((sizeof(RtreeCell)+sizeof(int))*(nCell+1));
@@ -116397,7 +109600,7 @@ static int removeNode(Rtree *pRtree, RtreeNode *pNode, int iHeight){
iCell = nodeParentIndex(pRtree, pNode);
pParent = pNode->pParent;
pNode->pParent = 0;
- if( SQLITE_OK!=(rc = deleteCell(pRtree, pParent, iCell, iHeight+1))
+ if( SQLITE_OK!=(rc = deleteCell(pRtree, pParent, iCell, iHeight+1))
|| SQLITE_OK!=(rc = nodeRelease(pRtree, pParent))
){
return rc;
@@ -116416,7 +109619,7 @@ static int removeNode(Rtree *pRtree, RtreeNode *pNode, int iHeight){
if( SQLITE_OK!=(rc = sqlite3_reset(pRtree->pDeleteParent)) ){
return rc;
}
-
+
/* Remove the node from the in-memory hash table and link it into
** the Rtree.pDeleted list. Its contents will be re-inserted later on.
*/
@@ -116432,7 +109635,7 @@ static int removeNode(Rtree *pRtree, RtreeNode *pNode, int iHeight){
static void fixBoundingBox(Rtree *pRtree, RtreeNode *pNode){
RtreeNode *pParent = pNode->pParent;
if( pParent ){
- int ii;
+ int ii;
int nCell = NCELL(pNode);
RtreeCell box; /* Bounding box for pNode */
nodeGetCell(pRtree, pNode, 0, &box);
@@ -116471,7 +109674,7 @@ static int deleteCell(Rtree *pRtree, RtreeNode *pNode, int iCell, int iHeight){
*/
if( pNode->iNode!=1 ){
RtreeNode *pParent = pNode->pParent;
- if( (pParent->iNode!=1 || NCELL(pParent)!=1)
+ if( (pParent->iNode!=1 || NCELL(pParent)!=1)
&& (NCELL(pNode)<RTREE_MINCELLS(pRtree))
){
rc = removeNode(pRtree, pNode, iHeight);
@@ -116484,9 +109687,9 @@ static int deleteCell(Rtree *pRtree, RtreeNode *pNode, int iCell, int iHeight){
}
static int Reinsert(
- Rtree *pRtree,
- RtreeNode *pNode,
- RtreeCell *pCell,
+ Rtree *pRtree,
+ RtreeNode *pNode,
+ RtreeCell *pCell,
int iHeight
){
int *aOrder;
@@ -116538,7 +109741,7 @@ static int Reinsert(
for(ii=0; ii<nCell; ii++){
aDistance[ii] = 0.0;
for(iDim=0; iDim<pRtree->nDim; iDim++){
- float coord = DCOORD(aCell[ii].aCoord[iDim*2+1]) -
+ float coord = DCOORD(aCell[ii].aCoord[iDim*2+1]) -
DCOORD(aCell[ii].aCoord[iDim*2]);
aDistance[ii] += (coord-aCenterCoord[iDim])*(coord-aCenterCoord[iDim]);
}
@@ -116583,7 +109786,7 @@ static int Reinsert(
}
/*
-** Insert cell pCell into node pNode. Node pNode is the head of a
+** Insert cell pCell into node pNode. Node pNode is the head of a
** subtree iHeight high (leaf nodes have iHeight==0).
*/
static int rtreeInsertCell(
@@ -116676,9 +109879,9 @@ static int hashIsEmpty(Rtree *pRtree){
** The xUpdate method for rtree module virtual tables.
*/
static int rtreeUpdate(
- sqlite3_vtab *pVtab,
- int nData,
- sqlite3_value **azData,
+ sqlite3_vtab *pVtab,
+ int nData,
+ sqlite3_value **azData,
sqlite_int64 *pRowid
){
Rtree *pRtree = (Rtree *)pVtab;
@@ -116702,8 +109905,8 @@ static int rtreeUpdate(
/* Obtain a reference to the root node to initialise Rtree.iDepth */
rc = nodeAcquire(pRtree, 1, 0, &pRoot);
- /* Obtain a reference to the leaf node that contains the entry
- ** about to be deleted.
+ /* Obtain a reference to the leaf node that contains the entry
+ ** about to be deleted.
*/
if( rc==SQLITE_OK ){
iDelete = sqlite3_value_int64(azData[0]);
@@ -116729,11 +109932,11 @@ static int rtreeUpdate(
}
/* Check if the root node now has exactly one child. If so, remove
- ** it, schedule the contents of the child for reinsertion and
+ ** it, schedule the contents of the child for reinsertion and
** reduce the tree height by one.
**
** This is equivalent to copying the contents of the child into
- ** the root node (the operation that Gutman's paper says to perform
+ ** the root node (the operation that Gutman's paper says to perform
** in this scenario).
*/
if( rc==SQLITE_OK && pRtree->iDepth>0 ){
@@ -116814,7 +110017,6 @@ static int rtreeUpdate(
}
rc = sqlite3_reset(pRtree->pReadRowid);
}
- *pRowid = cell.iRowid;
if( rc==SQLITE_OK ){
rc = ChooseLeaf(pRtree, &cell, 0, &pLeaf);
@@ -116845,8 +110047,8 @@ static int rtreeRename(sqlite3_vtab *pVtab, const char *zNewName){
"ALTER TABLE %Q.'%q_node' RENAME TO \"%w_node\";"
"ALTER TABLE %Q.'%q_parent' RENAME TO \"%w_parent\";"
"ALTER TABLE %Q.'%q_rowid' RENAME TO \"%w_rowid\";"
- , pRtree->zDb, pRtree->zName, zNewName
- , pRtree->zDb, pRtree->zName, zNewName
+ , pRtree->zDb, pRtree->zName, zNewName
+ , pRtree->zDb, pRtree->zName, zNewName
, pRtree->zDb, pRtree->zName, zNewName
);
if( zSql ){
@@ -116880,10 +110082,10 @@ static sqlite3_module rtreeModule = {
};
static int rtreeSqlInit(
- Rtree *pRtree,
- sqlite3 *db,
- const char *zDb,
- const char *zPrefix,
+ Rtree *pRtree,
+ sqlite3 *db,
+ const char *zDb,
+ const char *zPrefix,
int isCreate
){
int rc = SQLITE_OK;
@@ -116941,7 +110143,7 @@ static int rtreeSqlInit(
for(i=0; i<N_STATEMENT && rc==SQLITE_OK; i++){
char *zSql = sqlite3_mprintf(azSql[i], zDb, zPrefix);
if( zSql ){
- rc = sqlite3_prepare_v2(db, zSql, -1, appStmt[i], 0);
+ rc = sqlite3_prepare_v2(db, zSql, -1, appStmt[i], 0);
}else{
rc = SQLITE_NOMEM;
}
@@ -116952,72 +110154,34 @@ static int rtreeSqlInit(
}
/*
-** The second argument to this function contains the text of an SQL statement
-** that returns a single integer value. The statement is compiled and executed
-** using database connection db. If successful, the integer value returned
-** is written to *piVal and SQLITE_OK returned. Otherwise, an SQLite error
-** code is returned and the value of *piVal after returning is not defined.
+** This routine queries database handle db for the page-size used by
+** database zDb. If successful, the page-size in bytes is written to
+** *piPageSize and SQLITE_OK returned. Otherwise, and an SQLite error
+** code is returned.
*/
-static int getIntFromStmt(sqlite3 *db, const char *zSql, int *piVal){
+static int getPageSize(sqlite3 *db, const char *zDb, int *piPageSize){
int rc = SQLITE_NOMEM;
- if( zSql ){
- sqlite3_stmt *pStmt = 0;
- rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
- if( rc==SQLITE_OK ){
- if( SQLITE_ROW==sqlite3_step(pStmt) ){
- *piVal = sqlite3_column_int(pStmt, 0);
- }
- rc = sqlite3_finalize(pStmt);
- }
- }
- return rc;
-}
-
-/*
-** This function is called from within the xConnect() or xCreate() method to
-** determine the node-size used by the rtree table being created or connected
-** to. If successful, pRtree->iNodeSize is populated and SQLITE_OK returned.
-** Otherwise, an SQLite error code is returned.
-**
-** If this function is being called as part of an xConnect(), then the rtree
-** table already exists. In this case the node-size is determined by inspecting
-** the root node of the tree.
-**
-** Otherwise, for an xCreate(), use 64 bytes less than the database page-size.
-** This ensures that each node is stored on a single database page. If the
-** database page-size is so large that more than RTREE_MAXCELLS entries
-** would fit in a single node, use a smaller node-size.
-*/
-static int getNodeSize(
- sqlite3 *db, /* Database handle */
- Rtree *pRtree, /* Rtree handle */
- int isCreate /* True for xCreate, false for xConnect */
-){
- int rc;
char *zSql;
- if( isCreate ){
- int iPageSize;
- zSql = sqlite3_mprintf("PRAGMA %Q.page_size", pRtree->zDb);
- rc = getIntFromStmt(db, zSql, &iPageSize);
- if( rc==SQLITE_OK ){
- pRtree->iNodeSize = iPageSize-64;
- if( (4+pRtree->nBytesPerCell*RTREE_MAXCELLS)<pRtree->iNodeSize ){
- pRtree->iNodeSize = 4+pRtree->nBytesPerCell*RTREE_MAXCELLS;
- }
- }
- }else{
- zSql = sqlite3_mprintf(
- "SELECT length(data) FROM '%q'.'%q_node' WHERE nodeno = 1",
- pRtree->zDb, pRtree->zName
- );
- rc = getIntFromStmt(db, zSql, &pRtree->iNodeSize);
+ sqlite3_stmt *pStmt = 0;
+
+ zSql = sqlite3_mprintf("PRAGMA %Q.page_size", zDb);
+ if( !zSql ){
+ return SQLITE_NOMEM;
}
+ rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
sqlite3_free(zSql);
- return rc;
+ if( rc!=SQLITE_OK ){
+ return rc;
+ }
+
+ if( SQLITE_ROW==sqlite3_step(pStmt) ){
+ *piPageSize = sqlite3_column_int(pStmt, 0);
+ }
+ return sqlite3_finalize(pStmt);
}
-/*
+/*
** This function is the implementation of both the xConnect and xCreate
** methods of the r-tree virtual table.
**
@@ -117035,6 +110199,7 @@ static int rtreeInit(
int isCreate /* True for xCreate, false for xConnect */
){
int rc = SQLITE_OK;
+ int iPageSize = 0;
Rtree *pRtree;
int nDb; /* Length of string argv[1] */
int nName; /* Length of string argv[2] */
@@ -117053,6 +110218,11 @@ static int rtreeInit(
return SQLITE_ERROR;
}
+ rc = getPageSize(db, argv[1], &iPageSize);
+ if( rc!=SQLITE_OK ){
+ return rc;
+ }
+
/* Allocate the sqlite3_vtab structure */
nDb = strlen(argv[1]);
nName = strlen(argv[2]);
@@ -117071,37 +110241,44 @@ static int rtreeInit(
memcpy(pRtree->zDb, argv[1], nDb);
memcpy(pRtree->zName, argv[2], nName);
- /* Figure out the node size to use. */
- rc = getNodeSize(db, pRtree, isCreate);
+ /* Figure out the node size to use. By default, use 64 bytes less than
+ ** the database page-size. This ensures that each node is stored on
+ ** a single database page.
+ **
+ ** If the databasd page-size is so large that more than RTREE_MAXCELLS
+ ** entries would fit in a single node, use a smaller node-size.
+ */
+ pRtree->iNodeSize = iPageSize-64;
+ if( (4+pRtree->nBytesPerCell*RTREE_MAXCELLS)<pRtree->iNodeSize ){
+ pRtree->iNodeSize = 4+pRtree->nBytesPerCell*RTREE_MAXCELLS;
+ }
/* Create/Connect to the underlying relational database schema. If
** that is successful, call sqlite3_declare_vtab() to configure
** the r-tree table schema.
*/
- if( rc==SQLITE_OK ){
- if( (rc = rtreeSqlInit(pRtree, db, argv[1], argv[2], isCreate)) ){
+ if( (rc = rtreeSqlInit(pRtree, db, argv[1], argv[2], isCreate)) ){
+ *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db));
+ }else{
+ char *zSql = sqlite3_mprintf("CREATE TABLE x(%s", argv[3]);
+ char *zTmp;
+ int ii;
+ for(ii=4; zSql && ii<argc; ii++){
+ zTmp = zSql;
+ zSql = sqlite3_mprintf("%s, %s", zTmp, argv[ii]);
+ sqlite3_free(zTmp);
+ }
+ if( zSql ){
+ zTmp = zSql;
+ zSql = sqlite3_mprintf("%s);", zTmp);
+ sqlite3_free(zTmp);
+ }
+ if( !zSql ){
+ rc = SQLITE_NOMEM;
+ }else if( SQLITE_OK!=(rc = sqlite3_declare_vtab(db, zSql)) ){
*pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db));
- }else{
- char *zSql = sqlite3_mprintf("CREATE TABLE x(%s", argv[3]);
- char *zTmp;
- int ii;
- for(ii=4; zSql && ii<argc; ii++){
- zTmp = zSql;
- zSql = sqlite3_mprintf("%s, %s", zTmp, argv[ii]);
- sqlite3_free(zTmp);
- }
- if( zSql ){
- zTmp = zSql;
- zSql = sqlite3_mprintf("%s);", zTmp);
- sqlite3_free(zTmp);
- }
- if( !zSql ){
- rc = SQLITE_NOMEM;
- }else if( SQLITE_OK!=(rc = sqlite3_declare_vtab(db, zSql)) ){
- *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db));
- }
- sqlite3_free(zSql);
}
+ sqlite3_free(zSql);
}
if( rc==SQLITE_OK ){
@@ -117126,7 +110303,7 @@ static int rtreeInit(
**
** The human readable string takes the form of a Tcl list with one
** entry for each cell in the r-tree node. Each entry is itself a
-** list, containing the 8-byte rowid/pageno followed by the
+** list, containing the 8-byte rowid/pageno followed by the
** <num-dimension>*2 coordinates.
*/
static void rtreenode(sqlite3_context *ctx, int nArg, sqlite3_value **apArg){
@@ -117163,15 +110340,15 @@ static void rtreenode(sqlite3_context *ctx, int nArg, sqlite3_value **apArg){
zText = sqlite3_mprintf("{%s}", zCell);
}
}
-
+
sqlite3_result_text(ctx, zText, -1, sqlite3_free);
}
static void rtreedepth(sqlite3_context *ctx, int nArg, sqlite3_value **apArg){
- if( sqlite3_value_type(apArg[0])!=SQLITE_BLOB
+ if( sqlite3_value_type(apArg[0])!=SQLITE_BLOB
|| sqlite3_value_bytes(apArg[0])<2
){
- sqlite3_result_error(ctx, "Invalid argument to rtreedepth()", -1);
+ sqlite3_result_error(ctx, "Invalid argument to rtreedepth()", -1);
}else{
u8 *zBlob = (u8 *)sqlite3_value_blob(apArg[0]);
sqlite3_result_int(ctx, readInt16(zBlob));
@@ -117180,7 +110357,7 @@ static void rtreedepth(sqlite3_context *ctx, int nArg, sqlite3_value **apArg){
/*
** Register the r-tree module with database handle db. This creates the
-** virtual table module "rtree" and the debugging/analysis scalar
+** virtual table module "rtree" and the debugging/analysis scalar
** function "rtreenode".
*/
SQLITE_PRIVATE int sqlite3RtreeInit(sqlite3 *db){
@@ -117234,9 +110411,9 @@ SQLITE_API int sqlite3_extension_init(
*************************************************************************
** $Id: icu.c,v 1.7 2007/12/13 21:54:11 drh Exp $
**
-** This file implements an integration between the ICU library
-** ("International Components for Unicode", an open-source library
-** for handling unicode data) and SQLite. The integration uses
+** This file implements an integration between the ICU library
+** ("International Components for Unicode", an open-source library
+** for handling unicode data) and SQLite. The integration uses
** ICU to provide the following to SQLite:
**
** * An implementation of the SQL regexp() function (and hence REGEXP
@@ -117247,7 +110424,7 @@ SQLITE_API int sqlite3_extension_init(
**
** * Integration of ICU and SQLite collation seqences.
**
-** * An implementation of the LIKE operator that uses ICU to
+** * An implementation of the LIKE operator that uses ICU to
** provide case-independent matching.
*/
@@ -117282,7 +110459,7 @@ static void xFree(void *p){
/*
** Compare two UTF-8 strings for equality where the first string is
-** a "LIKE" expression. Return true (1) if they are the same and
+** a "LIKE" expression. Return true (1) if they are the same and
** false (0) if they are different.
*/
static int icuLikeCompare(
@@ -117317,7 +110494,7 @@ static int icuLikeCompare(
uint8_t c;
/* Skip any MATCH_ALL or MATCH_ONE characters that follow a
- ** MATCH_ALL. For each MATCH_ONE, skip one character in the
+ ** MATCH_ALL. For each MATCH_ONE, skip one character in the
** test string.
*/
while( (c=zPattern[iPattern]) == MATCH_ALL || c == MATCH_ONE ){
@@ -117370,15 +110547,15 @@ static int icuLikeCompare(
**
** A LIKE B
**
-** is implemented as like(B, A). If there is an escape character E,
+** is implemented as like(B, A). If there is an escape character E,
**
** A LIKE B ESCAPE E
**
** is mapped to like(B, A, E).
*/
static void icuLikeFunc(
- sqlite3_context *context,
- int argc,
+ sqlite3_context *context,
+ int argc,
sqlite3_value **argv
){
const unsigned char *zA = sqlite3_value_text(argv[0]);
@@ -117404,7 +110581,7 @@ static void icuLikeFunc(
if( zE==0 ) return;
U8_NEXT(zE, i, nE, uEsc);
if( i!=nE){
- sqlite3_result_error(context,
+ sqlite3_result_error(context,
"ESCAPE expression must be a single character", -1);
return;
}
@@ -117419,7 +110596,7 @@ static void icuLikeFunc(
** This function is called when an ICU function called from within
** the implementation of an SQL scalar function returns an error.
**
-** The scalar function context passed as the first argument is
+** The scalar function context passed as the first argument is
** loaded with an error message based on the following two args.
*/
static void icuFunctionError(
@@ -117445,7 +110622,7 @@ static void icuRegexpDelete(void *p){
/*
** Implementation of SQLite REGEXP operator. This scalar function takes
** two arguments. The first is a regular expression pattern to compile
-** the second is a string to match against that pattern. If either
+** the second is a string to match against that pattern. If either
** argument is an SQL NULL, then NULL Is returned. Otherwise, the result
** is 1 if the string matches the pattern, or 0 otherwise.
**
@@ -117467,8 +110644,8 @@ static void icuRegexpFunc(sqlite3_context *p, int nArg, sqlite3_value **apArg){
UBool res;
const UChar *zString = sqlite3_value_text16(apArg[1]);
- /* If the left hand side of the regexp operator is NULL,
- ** then the result is also NULL.
+ /* If the left hand side of the regexp operator is NULL,
+ ** then the result is also NULL.
*/
if( !zString ){
return;
@@ -117506,7 +110683,7 @@ static void icuRegexpFunc(sqlite3_context *p, int nArg, sqlite3_value **apArg){
}
/* Set the text that the regular expression operates on to a NULL
- ** pointer. This is not really necessary, but it is tidier than
+ ** pointer. This is not really necessary, but it is tidier than
** leaving the regular expression object configured with an invalid
** pointer after this function returns.
*/
@@ -117517,7 +110694,7 @@ static void icuRegexpFunc(sqlite3_context *p, int nArg, sqlite3_value **apArg){
}
/*
-** Implementations of scalar functions for case mapping - upper() and
+** Implementations of scalar functions for case mapping - upper() and
** lower(). Function upper() converts its input to upper-case (ABC).
** Function lower() converts to lower-case (abc).
**
@@ -117525,7 +110702,7 @@ static void icuRegexpFunc(sqlite3_context *p, int nArg, sqlite3_value **apArg){
** "language specific". Refer to ICU documentation for the differences
** between the two.
**
-** To utilise "general" case mapping, the upper() or lower() scalar
+** To utilise "general" case mapping, the upper() or lower() scalar
** functions are invoked with one argument:
**
** upper('ABC') -> 'abc'
@@ -117617,7 +110794,7 @@ static int icuCollationColl(
/*
** Implementation of the scalar function icu_load_collation().
**
-** This scalar function is used to add ICU collation based collation
+** This scalar function is used to add ICU collation based collation
** types to an SQLite database connection. It is intended to be called
** as follows:
**
@@ -117628,8 +110805,8 @@ static int icuCollationColl(
** collation sequence to create.
*/
static void icuLoadCollation(
- sqlite3_context *p,
- int nArg,
+ sqlite3_context *p,
+ int nArg,
sqlite3_value **apArg
){
sqlite3 *db = (sqlite3 *)sqlite3_user_data(p);
@@ -117654,7 +110831,7 @@ static void icuLoadCollation(
}
assert(p);
- rc = sqlite3_create_collation_v2(db, zName, SQLITE_UTF16, (void *)pUCollator,
+ rc = sqlite3_create_collation_v2(db, zName, SQLITE_UTF16, (void *)pUCollator,
icuCollationColl, icuCollationDel
);
if( rc!=SQLITE_OK ){
@@ -117707,7 +110884,7 @@ SQLITE_PRIVATE int sqlite3IcuInit(sqlite3 *db){
#if !SQLITE_CORE
SQLITE_API int sqlite3_extension_init(
- sqlite3 *db,
+ sqlite3 *db,
char **pzErrMsg,
const sqlite3_api_routines *pApi
){
@@ -117732,7 +110909,7 @@ SQLITE_API int sqlite3_extension_init(
**
*************************************************************************
** This file implements a tokenizer for fts3 based on the ICU library.
-**
+**
** $Id: fts3_icu.c,v 1.3 2008/09/01 18:34:20 danielk1977 Exp $
*/
@@ -117807,7 +110984,7 @@ static int icuDestroy(sqlite3_tokenizer *pTokenizer){
/*
** Prepare to begin tokenizing a particular string. The input
** string to be tokenized is pInput[0..nBytes-1]. A cursor
-** used to incrementally tokenize this string is returned in
+** used to incrementally tokenize this string is returned in
** *ppCursor.
*/
static int icuOpen(
@@ -117846,7 +111023,7 @@ static int icuOpen(
pCsr->aOffset = (int *)&pCsr->aChar[nChar];
pCsr->aOffset[iOut] = iInput;
- U8_NEXT(zInput, iInput, nInput, c);
+ U8_NEXT(zInput, iInput, nInput, c);
while( c>0 ){
int isError = 0;
c = u_foldCase(c, opt);
@@ -117977,3 +111154,18 @@ SQLITE_PRIVATE void sqlite3Fts3IcuTokenizerModule(
#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) */
/************** End of fts3_icu.c ********************************************/
+// Begin Android Add
+/*
+** Change the default behavior of BEGIN to IMMEDIATE instead of DEFERRED.
+*/
+SQLITE_API int sqlite3_set_transaction_default_immediate(sqlite3* db, int immediate){
+ sqlite3_mutex_enter(db->mutex);
+ if( immediate ){
+ db->flags|=SQLITE_BeginImmediate;
+ }else{
+ db->flags&=~SQLITE_BeginImmediate;
+ }
+ sqlite3_mutex_leave(db->mutex);
+ return SQLITE_OK;
+}
+// End Android Add