| sqlite3_value_frombind
+** | → | True if value originated from a [bound parameter]
**
**
** Details:
**
** These routines extract type, size, and content information from
** [protected sqlite3_value] objects. Protected sqlite3_value objects
-** are used to pass parameter information into implementation of
-** [application-defined SQL functions] and [virtual tables].
+** are used to pass parameter information into the functions that
+** implement [application-defined SQL functions] and [virtual tables].
**
** These routines work only with [protected sqlite3_value] objects.
** Any attempt to use these routines on an [unprotected sqlite3_value]
@@ -5941,11 +6478,11 @@ SQLITE_API SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int6
** sqlite3_value_text16be() and sqlite3_value_text16le() interfaces
** extract UTF-16 strings as big-endian and little-endian respectively.
**
-** ^If [sqlite3_value] object V was initialized
+** ^If [sqlite3_value] object V was initialized
** using [sqlite3_bind_pointer(S,I,P,X,D)] or [sqlite3_result_pointer(C,P,X,D)]
** and if X and Y are strings that compare equal according to strcmp(X,Y),
** then sqlite3_value_pointer(V,Y) will return the pointer P. ^Otherwise,
-** sqlite3_value_pointer(V,Y) returns a NULL. The sqlite3_bind_pointer()
+** sqlite3_value_pointer(V,Y) returns a NULL. The sqlite3_bind_pointer()
** routine is part of the [pointer passing interface] added for SQLite 3.20.0.
**
** ^(The sqlite3_value_type(V) interface returns the
@@ -5980,6 +6517,11 @@ SQLITE_API SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int6
** than within an [xUpdate] method call for an UPDATE statement, then
** the return value is arbitrary and meaningless.
**
+** ^The sqlite3_value_frombind(X) interface returns non-zero if the
+** value X originated from one of the [sqlite3_bind_int|sqlite3_bind()]
+** interfaces. ^If X comes from an SQL literal value, or a table column,
+** or an expression, then sqlite3_value_frombind(X) returns zero.
+**
** Please pay particular attention to the fact that the pointer returned
** from [sqlite3_value_blob()], [sqlite3_value_text()], or
** [sqlite3_value_text16()] can be invalidated by a subsequent call to
@@ -6025,6 +6567,7 @@ SQLITE_API int sqlite3_value_bytes16(sqlite3_value*);
SQLITE_API int sqlite3_value_type(sqlite3_value*);
SQLITE_API int sqlite3_value_numeric_type(sqlite3_value*);
SQLITE_API int sqlite3_value_nochange(sqlite3_value*);
+SQLITE_API int sqlite3_value_frombind(sqlite3_value*);
/*
** CAPI3REF: Finding The Subtype Of SQL Values
@@ -6062,9 +6605,9 @@ SQLITE_API void sqlite3_value_free(sqlite3_value*);
** Implementations 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
-** for a particular aggregate function, SQLite
-** allocates N of memory, zeroes out that memory, and returns a pointer
+** ^The first time the sqlite3_aggregate_context(C,N) routine is called
+** for a particular aggregate function, SQLite allocates
+** N bytes of memory, zeroes out that memory, and returns a pointer
** to the new memory. ^On second and subsequent calls to
** sqlite3_aggregate_context() for the same aggregate function instance,
** the same buffer is returned. Sqlite3_aggregate_context() is normally
@@ -6075,19 +6618,19 @@ SQLITE_API void sqlite3_value_free(sqlite3_value*);
** In those cases, sqlite3_aggregate_context() might be called for the
** first time from within xFinal().)^
**
-** ^The sqlite3_aggregate_context(C,N) routine returns a NULL pointer
+** ^The sqlite3_aggregate_context(C,N) routine returns a NULL pointer
** when first called if N is less than or equal to zero or if a memory
** allocate error occurs.
**
** ^(The amount of space allocated by sqlite3_aggregate_context(C,N) is
** determined by the N parameter on first successful call. Changing the
-** value of N in subsequent call to sqlite3_aggregate_context() within
+** value of N in any subsequent call to sqlite3_aggregate_context() within
** the same aggregate function instance will not resize the memory
** allocation.)^ Within the xFinal callback, it is customary to set
-** N=0 in calls to sqlite3_aggregate_context(C,N) so that no
+** N=0 in calls to sqlite3_aggregate_context(C,N) so that no
** pointless memory allocations occur.
**
-** ^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
@@ -6137,7 +6680,7 @@ SQLITE_API sqlite3 *sqlite3_context_db_handle(sqlite3_context*);
** some circumstances the associated metadata may be preserved. An example
** of where this might be useful is in a regular-expression matching
** function. The compiled version of the regular expression can be stored as
-** metadata associated with the pattern string.
+** metadata associated with the pattern string.
** Then as long as the pattern string remains the same,
** the compiled regular expression can be reused on multiple
** invocations of the same function.
@@ -6163,10 +6706,10 @@ SQLITE_API sqlite3 *sqlite3_context_db_handle(sqlite3_context*);
** SQL statement)^, or
** ^(when sqlite3_set_auxdata() is invoked again on the same
** parameter)^, or
-** ^(during the original sqlite3_set_auxdata() call when a memory
+** ^(during the original sqlite3_set_auxdata() call when a memory
** allocation error occurs.)^
**
-** Note the last bullet in particular. The destructor X in
+** Note the last bullet in particular. The destructor X in
** sqlite3_set_auxdata(C,N,P,X) might be called immediately, before the
** sqlite3_set_auxdata() interface even returns. Hence sqlite3_set_auxdata()
** should be called near the end of the function implementation and the
@@ -6238,8 +6781,9 @@ typedef void (*sqlite3_destructor_type)(void*);
** 2nd parameter of sqlite3_result_error() or sqlite3_result_error16()
** as the text of an error message. ^SQLite interprets the error
** message string from sqlite3_result_error() as UTF-8. ^SQLite
-** interprets the string from sqlite3_result_error16() as UTF-16 in native
-** byte order. ^If the third parameter to sqlite3_result_error()
+** interprets the string from sqlite3_result_error16() as UTF-16 using
+** the same [byte-order determination rules] as [sqlite3_bind_text16()].
+** ^If the third parameter to sqlite3_result_error()
** or sqlite3_result_error16() is negative then SQLite takes as the error
** message all text up through the first zero character.
** ^If the third parameter to sqlite3_result_error() or
@@ -6307,6 +6851,25 @@ typedef void (*sqlite3_destructor_type)(void*);
** then SQLite makes a copy of the result into space obtained
** from [sqlite3_malloc()] before it returns.
**
+** ^For the sqlite3_result_text16(), sqlite3_result_text16le(), and
+** sqlite3_result_text16be() routines, and for sqlite3_result_text64()
+** when the encoding is not UTF8, if the input UTF16 begins with a
+** byte-order mark (BOM, U+FEFF) then the BOM is removed from the
+** string and the rest of the string is interpreted according to the
+** byte-order specified by the BOM. ^The byte-order specified by
+** the BOM at the beginning of the text overrides the byte-order
+** specified by the interface procedure. ^So, for example, if
+** sqlite3_result_text16le() is invoked with text that begins
+** with bytes 0xfe, 0xff (a big-endian byte-order mark) then the
+** first two bytes of input are skipped and the remaining input
+** is interpreted as UTF16BE text.
+**
+** ^For UTF16 input text to the sqlite3_result_text16(),
+** sqlite3_result_text16be(), sqlite3_result_text16le(), and
+** sqlite3_result_text64() routines, if the text contains invalid
+** UTF16 characters, the invalid characters might be converted
+** into the unicode replacement character, U+FFFD.
+**
** ^The sqlite3_result_value() interface sets the result of
** the application-defined function to be a copy of the
** [unprotected sqlite3_value] object specified by the 2nd parameter. ^The
@@ -6319,7 +6882,7 @@ typedef void (*sqlite3_destructor_type)(void*);
**
** ^The sqlite3_result_pointer(C,P,T,D) interface sets the result to an
** SQL NULL value, just like [sqlite3_result_null(C)], except that it
-** also associates the host-language pointer P or type T with that
+** also associates the host-language pointer P or type T with that
** NULL value such that the pointer can be retrieved within an
** [application-defined SQL function] using [sqlite3_value_pointer()].
** ^If the D parameter is not NULL, then it is a pointer to a destructor
@@ -6361,8 +6924,8 @@ SQLITE_API int sqlite3_result_zeroblob64(sqlite3_context*, sqlite3_uint64 n);
** METHOD: sqlite3_context
**
** The sqlite3_result_subtype(C,T) function causes the subtype of
-** the result from the [application-defined SQL function] with
-** [sqlite3_context] C to be the value T. Only the lower 8 bits
+** the result from the [application-defined SQL function] with
+** [sqlite3_context] C to be the value T. Only the lower 8 bits
** of the subtype T are preserved in current versions of SQLite;
** higher order bits are discarded.
** The number of subtype bytes preserved by SQLite might increase
@@ -6392,7 +6955,7 @@ SQLITE_API void sqlite3_result_subtype(sqlite3_context*,unsigned int);
** [SQLITE_UTF16_ALIGNED].
** )^
** ^The eTextRep argument determines the encoding of strings passed
-** to the collating function callback, xCallback.
+** to the collating function callback, xCompare.
** ^The [SQLITE_UTF16] and [SQLITE_UTF16_ALIGNED] values for eTextRep
** force strings to be UTF16 with native byte order.
** ^The [SQLITE_UTF16_ALIGNED] value for eTextRep forces strings to begin
@@ -6401,18 +6964,19 @@ SQLITE_API void sqlite3_result_subtype(sqlite3_context*,unsigned int);
** ^The fourth argument, pArg, is an application data pointer that is passed
** through as the first argument to the collating function callback.
**
-** ^The fifth argument, xCallback, is a pointer to the collating function.
+** ^The fifth argument, xCompare, is a pointer to the collating function.
** ^Multiple collating functions can be registered using the same name but
** with different eTextRep parameters and SQLite will use whichever
** function requires the least amount of data transformation.
-** ^If the xCallback argument is NULL then the collating function is
+** ^If the xCompare argument is NULL then the collating function is
** deleted. ^When all collating functions having the same name are deleted,
** that collation is no longer usable.
**
-** ^The collating function callback is invoked with a copy of the pArg
+** ^The collating function callback is invoked with a copy of the pArg
** application data pointer and with two strings in the encoding specified
-** by the eTextRep argument. The collating function must return an
-** integer that is negative, zero, or positive
+** by the eTextRep argument. The two integer parameters to the collating
+** function callback are the length of the two strings, in bytes. The collating
+** function must return an integer that is negative, zero, or positive
** if the first string is less than, equal to, or greater than the second,
** respectively. A collating function must always return the same answer
** given the same inputs. If two or more collating functions are registered
@@ -6429,7 +6993,7 @@ SQLITE_API void sqlite3_result_subtype(sqlite3_context*,unsigned int);
**
**
** If a collating function fails any of the above constraints and that
-** collating function is registered and used, then the behavior of SQLite
+** collating function is registered and used, then the behavior of SQLite
** is undefined.
**
** ^The sqlite3_create_collation_v2() works like sqlite3_create_collation()
@@ -6439,36 +7003,36 @@ SQLITE_API void sqlite3_result_subtype(sqlite3_context*,unsigned int);
** calls to the collation creation functions or when the
** [database connection] is closed using [sqlite3_close()].
**
-** ^The xDestroy callback is not called if the
+** ^The xDestroy callback is not called if the
** sqlite3_create_collation_v2() function fails. Applications that invoke
-** sqlite3_create_collation_v2() with a non-NULL xDestroy argument should
+** sqlite3_create_collation_v2() with a non-NULL xDestroy argument should
** check the return code and dispose of the application data pointer
** themselves rather than expecting SQLite to deal with it for them.
-** This is different from every other SQLite interface. The inconsistency
-** is unfortunate but cannot be changed without breaking backwards
+** This is different from every other SQLite interface. The inconsistency
+** is unfortunate but cannot be changed without breaking backwards
** compatibility.
**
** 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 *pArg,
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 *pArg,
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 *pArg,
int(*xCompare)(void*,int,const void*,int,const void*)
);
@@ -6501,64 +7065,19 @@ 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().
-**
-** The code to implement this API is not available in the public release
-** of SQLite.
-*/
-SQLITE_API int sqlite3_key(
- sqlite3 *db, /* Database to be rekeyed */
- const void *pKey, int nKey /* The key */
-);
-SQLITE_API int sqlite3_key_v2(
- sqlite3 *db, /* Database to be rekeyed */
- const char *zDbName, /* Name of the database */
- const void *pKey, int nKey /* The key */
-);
-
-/*
-** Change the key on an open database. If the current database is not
-** encrypted, this routine will encrypt it. If pNew==0 or nNew==0, the
-** database is decrypted.
-**
-** The code to implement this API is not available in the public release
-** of SQLite.
-*/
-SQLITE_API int sqlite3_rekey(
- sqlite3 *db, /* Database to be rekeyed */
- const void *pKey, int nKey /* The new key */
-);
-SQLITE_API int sqlite3_rekey_v2(
- sqlite3 *db, /* Database to be rekeyed */
- const char *zDbName, /* Name of the database */
- const void *pKey, int nKey /* The new key */
-);
-
-/*
-** Specify the activation key for a SEE database. Unless
-** 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
+** Specify the activation key for a CEROD database. Unless
** activated, none of the CEROD routines will work.
*/
SQLITE_API void sqlite3_activate_cerod(
@@ -6614,7 +7133,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
@@ -6671,7 +7190,7 @@ SQLITE_API char *sqlite3_temp_directory;
** ^The [data_store_directory pragma] may modify this variable and cause
** it to point to memory obtained from [sqlite3_malloc]. ^Furthermore,
** the [data_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
@@ -6756,16 +7275,31 @@ SQLITE_API sqlite3 *sqlite3_db_handle(sqlite3_stmt*);
** CAPI3REF: Return The Filename For A Database Connection
** METHOD: sqlite3
**
-** ^The sqlite3_db_filename(D,N) interface returns a pointer to a filename
-** associated with database N of connection D. ^The main database file
-** has the name "main". If there is no attached database N on the database
+** ^The sqlite3_db_filename(D,N) interface returns a pointer to the filename
+** associated with database N of connection D.
+** ^If there is no attached database N on the database
** connection D, or if database N is a temporary or in-memory database, then
-** a NULL pointer is returned.
+** this function will return either a NULL pointer or an empty string.
+**
+** ^The string value returned by this routine is owned and managed by
+** the database connection. ^The value will be valid until the database N
+** is [DETACH]-ed or until the database connection closes.
**
** ^The filename returned by this function is the output of the
** xFullPathname method of the [VFS]. ^In other words, the filename
** will be an absolute pathname, even if the filename used
** to open the database originally was a URI or relative pathname.
+**
+** If the filename pointer returned by this routine is not NULL, then it
+** can be used as the filename input parameter to these routines:
+**
+** - [sqlite3_uri_parameter()]
+**
- [sqlite3_uri_boolean()]
+**
- [sqlite3_uri_int64()]
+**
- [sqlite3_filename_database()]
+**
- [sqlite3_filename_journal()]
+**
- [sqlite3_filename_wal()]
+**
*/
SQLITE_API const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName);
@@ -6779,6 +7313,57 @@ SQLITE_API const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName);
*/
SQLITE_API int sqlite3_db_readonly(sqlite3 *db, const char *zDbName);
+/*
+** CAPI3REF: Determine the transaction state of a database
+** METHOD: sqlite3
+**
+** ^The sqlite3_txn_state(D,S) interface returns the current
+** [transaction state] of schema S in database connection D. ^If S is NULL,
+** then the highest transaction state of any schema on database connection D
+** is returned. Transaction states are (in order of lowest to highest):
+**
+** - SQLITE_TXN_NONE
+**
- SQLITE_TXN_READ
+**
- SQLITE_TXN_WRITE
+**
+** ^If the S argument to sqlite3_txn_state(D,S) is not the name of
+** a valid schema, then -1 is returned.
+*/
+SQLITE_API int sqlite3_txn_state(sqlite3*,const char *zSchema);
+
+/*
+** CAPI3REF: Allowed return values from [sqlite3_txn_state()]
+** KEYWORDS: {transaction state}
+**
+** These constants define the current transaction state of a database file.
+** ^The [sqlite3_txn_state(D,S)] interface returns one of these
+** constants in order to describe the transaction state of schema S
+** in [database connection] D.
+**
+**
+** [[SQLITE_TXN_NONE]] - SQLITE_TXN_NONE
+** - The SQLITE_TXN_NONE state means that no transaction is currently
+** pending.
+**
+** [[SQLITE_TXN_READ]] - SQLITE_TXN_READ
+** - The SQLITE_TXN_READ state means that the database is currently
+** in a read transaction. Content has been read from the database file
+** but nothing in the database file has changed. The transaction state
+** will advanced to SQLITE_TXN_WRITE if any changes occur and there are
+** no other conflicting concurrent write transactions. The transaction
+** state will revert to SQLITE_TXN_NONE following a [ROLLBACK] or
+** [COMMIT].
+**
+** [[SQLITE_TXN_WRITE]] - SQLITE_TXN_WRITE
+** - The SQLITE_TXN_WRITE state means that the database is currently
+** in a write transaction. Content has been written to the database file
+** but has not yet committed. The transaction state will change to
+** to SQLITE_TXN_NONE at the next [ROLLBACK] or [COMMIT].
+*/
+#define SQLITE_TXN_NONE 0
+#define SQLITE_TXN_READ 1
+#define SQLITE_TXN_WRITE 2
+
/*
** CAPI3REF: Find the next prepared statement
** METHOD: sqlite3
@@ -6869,7 +7454,7 @@ SQLITE_API void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*);
** ^In the case of an update, this is the [rowid] after the update takes place.
**
** ^(The update hook is not invoked when internal system tables are
-** modified (i.e. sqlite_master and sqlite_sequence).)^
+** modified (i.e. sqlite_sequence).)^
** ^The update hook is not invoked when [WITHOUT ROWID] tables are modified.
**
** ^In the current implementation, the update hook
@@ -6895,7 +7480,7 @@ SQLITE_API void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*);
** and [sqlite3_preupdate_hook()] interfaces.
*/
SQLITE_API void *sqlite3_update_hook(
- sqlite3*,
+ sqlite3*,
void(*)(void *,int ,char const *,char const *,sqlite3_int64),
void*
);
@@ -6909,25 +7494,29 @@ SQLITE_API void *sqlite3_update_hook(
** and disabled if the argument is false.)^
**
** ^Cache sharing is enabled and disabled for an entire process.
-** This is a change as of SQLite [version 3.5.0] ([dateof:3.5.0]).
+** This is a change as of SQLite [version 3.5.0] ([dateof:3.5.0]).
** In prior versions of SQLite,
** sharing was enabled or disabled for each thread separately.
**
** ^(The cache sharing mode set by this interface effects all subsequent
** calls to [sqlite3_open()], [sqlite3_open_v2()], and [sqlite3_open16()].
-** Existing database connections continue use the sharing mode
+** Existing database connections continue to use the sharing mode
** that was in effect at the time they were opened.)^
**
** ^(This routine returns [SQLITE_OK] if shared cache was enabled or disabled
** successfully. An [error code] is returned otherwise.)^
**
-** ^Shared cache is disabled by default. But this might change in
-** future releases of SQLite. Applications that care about shared
-** cache setting should set it explicitly.
+** ^Shared cache is disabled by default. It is recommended that it stay
+** that way. In other words, do not use this routine. This interface
+** continues to be provided for historical compatibility, but its use is
+** discouraged. Any use of shared cache is discouraged. If shared cache
+** must be used, it is recommended that shared cache only be enabled for
+** individual database connections using the [sqlite3_open_v2()] interface
+** with the [SQLITE_OPEN_SHAREDCACHE] flag.
**
** Note: This method is disabled on MacOS X 10.7 and iOS version 5.0
-** and will always return SQLITE_MISUSE. On those systems,
-** shared cache mode should be enabled per-database connection via
+** and will always return SQLITE_MISUSE. On those systems,
+** shared cache mode should be enabled per-database connection via
** [sqlite3_open_v2()] with [SQLITE_OPEN_SHAREDCACHE].
**
** This interface is threadsafe on processors where writing a
@@ -6970,6 +7559,9 @@ SQLITE_API int sqlite3_db_release_memory(sqlite3*);
/*
** CAPI3REF: Impose A Limit On Heap Size
**
+** These interfaces impose limits on the amount of heap memory that will be
+** by all database connections within a single process.
+**
** ^The sqlite3_soft_heap_limit64() interface sets and/or queries the
** soft limit on the amount of heap memory that may be allocated by SQLite.
** ^SQLite strives to keep heap memory utilization below the soft heap
@@ -6977,23 +7569,44 @@ SQLITE_API int sqlite3_db_release_memory(sqlite3*);
** as heap memory usages approaches the limit.
** ^The soft heap limit is "soft" because even though SQLite strives to stay
** below the limit, it will exceed the limit rather than generate
-** an [SQLITE_NOMEM] error. In other words, the soft heap limit
+** an [SQLITE_NOMEM] error. In other words, the soft heap limit
** is advisory only.
**
-** ^The return value from sqlite3_soft_heap_limit64() is the size of
-** the soft heap limit prior to the call, or negative in the case of an
+** ^The sqlite3_hard_heap_limit64(N) interface sets a hard upper bound of
+** N bytes on the amount of memory that will be allocated. ^The
+** sqlite3_hard_heap_limit64(N) interface is similar to
+** sqlite3_soft_heap_limit64(N) except that memory allocations will fail
+** when the hard heap limit is reached.
+**
+** ^The return value from both sqlite3_soft_heap_limit64() and
+** sqlite3_hard_heap_limit64() is the size of
+** the heap limit prior to the call, or negative in the case of an
** error. ^If the argument N is negative
-** then no change is made to the soft heap limit. Hence, the current
-** size of the soft heap limit can be determined by invoking
-** sqlite3_soft_heap_limit64() with a negative argument.
+** then no change is made to the heap limit. Hence, the current
+** size of heap limits can be determined by invoking
+** sqlite3_soft_heap_limit64(-1) or sqlite3_hard_heap_limit(-1).
**
-** ^If the argument N is zero then the soft heap limit is disabled.
+** ^Setting the heap limits to zero disables the heap limiter mechanism.
**
-** ^(The soft heap limit is not enforced in the current implementation
+** ^The soft heap limit may not be greater than the hard heap limit.
+** ^If the hard heap limit is enabled and if sqlite3_soft_heap_limit(N)
+** is invoked with a value of N that is greater than the hard heap limit,
+** the the soft heap limit is set to the value of the hard heap limit.
+** ^The soft heap limit is automatically enabled whenever the hard heap
+** limit is enabled. ^When sqlite3_hard_heap_limit64(N) is invoked and
+** the soft heap limit is outside the range of 1..N, then the soft heap
+** limit is set to N. ^Invoking sqlite3_soft_heap_limit64(0) when the
+** hard heap limit is enabled makes the soft heap limit equal to the
+** hard heap limit.
+**
+** The memory allocation limits can also be adjusted using
+** [PRAGMA soft_heap_limit] and [PRAGMA hard_heap_limit].
+**
+** ^(The heap limits are not enforced in the current implementation
** if one or more of following conditions are true:
**
**
-** - The soft heap limit is set to zero.
+**
- The limit value is set to zero.
**
- Memory accounting is disabled using a combination of the
** [sqlite3_config]([SQLITE_CONFIG_MEMSTATUS],...) start-time option and
** the [SQLITE_DEFAULT_MEMSTATUS] compile-time option.
@@ -7004,21 +7617,11 @@ SQLITE_API int sqlite3_db_release_memory(sqlite3*);
** from the heap.
**
)^
**
-** Beginning with SQLite [version 3.7.3] ([dateof:3.7.3]),
-** the soft heap limit is enforced
-** regardless of whether or not the [SQLITE_ENABLE_MEMORY_MANAGEMENT]
-** compile-time option is invoked. With [SQLITE_ENABLE_MEMORY_MANAGEMENT],
-** the soft heap limit is enforced on every memory allocation. Without
-** [SQLITE_ENABLE_MEMORY_MANAGEMENT], the soft heap limit is only enforced
-** when memory is allocated by the page cache. Testing suggests that because
-** the page cache is the predominate memory user in SQLite, most
-** applications will achieve adequate soft heap limit enforcement without
-** the use of [SQLITE_ENABLE_MEMORY_MANAGEMENT].
-**
-** The circumstances under which SQLite will enforce the soft heap limit may
+** The circumstances under which SQLite will enforce the heap limits may
** changes in future releases of SQLite.
*/
SQLITE_API sqlite3_int64 sqlite3_soft_heap_limit64(sqlite3_int64 N);
+SQLITE_API sqlite3_int64 sqlite3_hard_heap_limit64(sqlite3_int64 N);
/*
** CAPI3REF: Deprecated Soft Heap Limit Interface
@@ -7042,7 +7645,7 @@ SQLITE_API SQLITE_DEPRECATED void sqlite3_soft_heap_limit(int N);
** interface returns SQLITE_OK and fills in the non-NULL pointers in
** the final five arguments with appropriate values if the specified
** column exists. ^The sqlite3_table_column_metadata() interface returns
-** SQLITE_ERROR and if the specified column does not exist.
+** SQLITE_ERROR if the specified column does not exist.
** ^If the column-name parameter to sqlite3_table_column_metadata() is a
** NULL pointer, then this routine simply checks for the existence of the
** table and returns SQLITE_OK if the table exists and SQLITE_ERROR if it
@@ -7082,7 +7685,7 @@ SQLITE_API SQLITE_DEPRECATED void sqlite3_soft_heap_limit(int N);
**
** ^If the specified table is actually a view, an [error code] is returned.
**
-** ^If the specified column is "rowid", "oid" or "_rowid_" and the table
+** ^If the specified column is "rowid", "oid" or "_rowid_" and the table
** is not a [WITHOUT ROWID] table and an
** [INTEGER PRIMARY KEY] column has been explicitly declared, then the output
** parameters are set for the explicitly declared column. ^(If there is no
@@ -7148,7 +7751,7 @@ SQLITE_API int sqlite3_table_column_metadata(
** prior to calling this API,
** otherwise an error will be returned.
**
-** Security warning: It is recommended that the
+** Security warning: It is recommended that the
** [SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION] method be used to enable only this
** interface. The use of the [sqlite3_enable_load_extension()] interface
** should be avoided. This will keep the SQL function [load_extension()]
@@ -7184,7 +7787,7 @@ SQLITE_API int sqlite3_load_extension(
** to enable or disable only the C-API.)^
**
** Security warning: It is recommended that extension loading
-** be disabled using the [SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION] method
+** be enabled using the [SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION] method
** rather than this interface, so the [load_extension()] SQL function
** remains disabled. This will prevent SQL injections from giving attackers
** access to extension loading capabilities.
@@ -7235,7 +7838,7 @@ SQLITE_API int sqlite3_auto_extension(void(*xEntryPoint)(void));
** ^The [sqlite3_cancel_auto_extension(X)] interface unregisters the
** initialization routine X that was registered using a prior call to
** [sqlite3_auto_extension(X)]. ^The [sqlite3_cancel_auto_extension(X)]
-** routine returns 1 if initialization routine X was successfully
+** routine returns 1 if initialization routine X was successfully
** unregistered and it returns 0 if X was not on the list of initialization
** routines.
*/
@@ -7270,8 +7873,8 @@ typedef struct sqlite3_module sqlite3_module;
** CAPI3REF: Virtual Table Object
** KEYWORDS: sqlite3_module {virtual table module}
**
-** This structure, sometimes called a "virtual table module",
-** defines the implementation of a [virtual tables].
+** This structure, sometimes called a "virtual table module",
+** defines the implementation of a [virtual table].
** This structure consists mostly of methods for the module.
**
** ^A virtual table module is created by filling in a persistent
@@ -7310,11 +7913,14 @@ struct sqlite3_module {
void (**pxFunc)(sqlite3_context*,int,sqlite3_value**),
void **ppArg);
int (*xRename)(sqlite3_vtab *pVtab, const char *zNew);
- /* The methods above are in version 1 of the sqlite_module object. Those
+ /* The methods above are in version 1 of the sqlite_module object. Those
** below are for version 2 and greater. */
int (*xSavepoint)(sqlite3_vtab *pVTab, int);
int (*xRelease)(sqlite3_vtab *pVTab, int);
int (*xRollbackTo)(sqlite3_vtab *pVTab, int);
+ /* The methods above are in versions 1 and 2 of the sqlite_module object.
+ ** Those below are for version 3 and greater. */
+ int (*xShadowName)(const char*);
};
/*
@@ -7357,7 +7963,7 @@ struct sqlite3_module {
** required by SQLite. If the table has at least 64 columns and any column
** to the right of the first 63 is required, then bit 63 of colUsed is also
** set. In other words, column iCol may be required if the expression
-** (colUsed & ((sqlite3_uint64)1 << (iCol>=63 ? 63 : iCol))) evaluates to
+** (colUsed & ((sqlite3_uint64)1 << (iCol>=63 ? 63 : iCol))) evaluates to
** non-zero.
**
** The [xBestIndex] method must fill aConstraintUsage[] with information
@@ -7365,7 +7971,13 @@ struct sqlite3_module {
** the right-hand side of the corresponding aConstraint[] is evaluated
** and becomes the argvIndex-th entry in argv. ^(If aConstraintUsage[].omit
** is true, then the constraint is assumed to be fully handled by the
-** virtual table and is not checked again by SQLite.)^
+** virtual table and might not be checked again by the byte code.)^ ^(The
+** aConstraintUsage[].omit flag is an optimization hint. When the omit flag
+** is left in its default setting of false, the constraint will always be
+** checked separately in byte code. If the omit flag is change to true, then
+** the constraint may or may not be checked in byte code. In other words,
+** when the omit flag is true there is no guarantee that the constraint will
+** not be checked again using byte code.)^
**
** ^The idxNum and idxPtr values are recorded and passed into the
** [xFilter] method.
@@ -7378,17 +7990,17 @@ struct sqlite3_module {
**
** ^The estimatedCost value is an estimate of the cost of a particular
** strategy. A cost of N indicates that the cost of the strategy is similar
-** to a linear scan of an SQLite table with N rows. A cost of log(N)
+** to a linear scan of an SQLite table with N rows. A cost of log(N)
** indicates that the expense of the operation is similar to that of a
** binary search on a unique indexed field of an SQLite table with N rows.
**
** ^The estimatedRows value is an estimate of the number of rows that
** will be returned by the strategy.
**
-** The xBestIndex method may optionally populate the idxFlags field with a
+** The xBestIndex method may optionally populate the idxFlags field with a
** mask of SQLITE_INDEX_SCAN_* flags. Currently there is only one such flag -
** SQLITE_INDEX_SCAN_UNIQUE. If the xBestIndex method sets this flag, SQLite
-** assumes that the strategy may visit at most one row.
+** assumes that the strategy may visit at most one row.
**
** Additionally, if xBestIndex sets the SQLITE_INDEX_SCAN_UNIQUE flag, then
** SQLite also assumes that if a call to the xUpdate() method is made as
@@ -7401,14 +8013,14 @@ struct sqlite3_module {
** the xUpdate method are automatically rolled back by SQLite.
**
** IMPORTANT: The estimatedRows field was added to the sqlite3_index_info
-** structure for SQLite [version 3.8.2] ([dateof:3.8.2]).
+** structure for SQLite [version 3.8.2] ([dateof:3.8.2]).
** If a virtual table extension is
-** used with an SQLite version earlier than 3.8.2, the results of attempting
-** to read or write the estimatedRows field are undefined (but are likely
-** to included crashing the application). The estimatedRows field should
+** used with an SQLite version earlier than 3.8.2, the results of attempting
+** to read or write the estimatedRows field are undefined (but are likely
+** to include crashing the application). The estimatedRows field should
** therefore only be used if [sqlite3_libversion_number()] returns a
** value greater than or equal to 3008002. Similarly, the idxFlags field
-** was added for [version 3.9.0] ([dateof:3.9.0]).
+** was added for [version 3.9.0] ([dateof:3.9.0]).
** It may therefore only be used if
** sqlite3_libversion_number() returns a value greater than or equal to
** 3009000.
@@ -7448,7 +8060,7 @@ struct sqlite3_index_info {
/*
** CAPI3REF: Virtual Table Scan Flags
**
-** Virtual table implementations are allowed to set the
+** Virtual table implementations are allowed to set the
** [sqlite3_index_info].idxFlags field to some combination of
** these bits.
*/
@@ -7457,7 +8069,7 @@ struct sqlite3_index_info {
/*
** CAPI3REF: Virtual Table Constraint Operator Codes
**
-** These macros defined the allowed values for the
+** These macros define the allowed values for the
** [sqlite3_index_info].aConstraint[].op field. Each value represents
** an operator that is part of a constraint term in the wHERE clause of
** a query that uses a [virtual table].
@@ -7488,7 +8100,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
@@ -7503,6 +8115,12 @@ struct sqlite3_index_info {
** ^The sqlite3_create_module()
** interface is equivalent to sqlite3_create_module_v2() with a NULL
** destructor.
+**
+** ^If the third parameter (the pointer to the sqlite3_module object) is
+** NULL then no new module is create and any existing modules with the
+** same name are dropped.
+**
+** See also: [sqlite3_drop_modules()]
*/
SQLITE_API int sqlite3_create_module(
sqlite3 *db, /* SQLite connection to register module with */
@@ -7518,6 +8136,23 @@ SQLITE_API int sqlite3_create_module_v2(
void(*xDestroy)(void*) /* Module destructor function */
);
+/*
+** CAPI3REF: Remove Unnecessary Virtual Table Implementations
+** METHOD: sqlite3
+**
+** ^The sqlite3_drop_modules(D,L) interface removes all virtual
+** table modules from database connection D except those named on list L.
+** The L parameter must be either NULL or a pointer to an array of pointers
+** to strings where the array is terminated by a single NULL pointer.
+** ^If the L parameter is NULL, then all virtual table modules are removed.
+**
+** See also: [sqlite3_create_module()]
+*/
+SQLITE_API int sqlite3_drop_modules(
+ sqlite3 *db, /* Remove modules from this connection */
+ const char **azKeep /* Except, do not remove the ones named here */
+);
+
/*
** CAPI3REF: Virtual Table Instance Object
** KEYWORDS: sqlite3_vtab
@@ -7580,7 +8215,7 @@ SQLITE_API int sqlite3_declare_vtab(sqlite3*, const char *zSQL);
** METHOD: sqlite3
**
** ^(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.)^
**
@@ -7631,7 +8266,7 @@ typedef struct sqlite3_blob sqlite3_blob;
** SELECT zColumn FROM zDb.zTable WHERE [rowid] = iRow;
** )^
**
-** ^(Parameter zDb is not the filename that contains the database, but
+** ^(Parameter zDb is not the filename that contains the database, but
** rather the symbolic name of the database. For attached databases, this is
** the name that appears after the AS keyword in the [ATTACH] statement.
** For the main database file, the database name is "main". For TEMP
@@ -7644,28 +8279,28 @@ typedef struct sqlite3_blob sqlite3_blob;
** ^(On success, [SQLITE_OK] is returned and the new [BLOB handle] is stored
** in *ppBlob. Otherwise an [error code] is returned and, unless the error
** code is SQLITE_MISUSE, *ppBlob is set to NULL.)^ ^This means that, provided
-** the API is not misused, it is always safe to call [sqlite3_blob_close()]
+** the API is not misused, it is always safe to call [sqlite3_blob_close()]
** on *ppBlob after this function it returns.
**
** This function fails with SQLITE_ERROR if any of the following are true:
**
-** - ^(Database zDb does not exist)^,
-**
- ^(Table zTable does not exist within database zDb)^,
-**
- ^(Table zTable is a WITHOUT ROWID table)^,
+**
- ^(Database zDb does not exist)^,
+**
- ^(Table zTable does not exist within database zDb)^,
+**
- ^(Table zTable is a WITHOUT ROWID table)^,
**
- ^(Column zColumn does not exist)^,
**
- ^(Row iRow is not present in the table)^,
**
- ^(The specified column of row iRow contains a value that is not
** a TEXT or BLOB value)^,
-**
- ^(Column zColumn is part of an index, PRIMARY KEY or UNIQUE
+**
- ^(Column zColumn is part of an index, PRIMARY KEY or UNIQUE
** constraint and the blob is being opened for read/write access)^,
-**
- ^([foreign key constraints | Foreign key constraints] are enabled,
+**
- ^([foreign key constraints | Foreign key constraints] are enabled,
** column zColumn is part of a [child key] definition and the blob is
** being opened for read/write access)^.
**
**
-** ^Unless it returns SQLITE_MISUSE, this function sets the
-** [database connection] error code and message accessible via
-** [sqlite3_errcode()] and [sqlite3_errmsg()] and related functions.
+** ^Unless it returns SQLITE_MISUSE, this function sets the
+** [database connection] error code and message accessible via
+** [sqlite3_errcode()] and [sqlite3_errmsg()] and related functions.
**
** A BLOB referenced by sqlite3_blob_open() may be read using the
** [sqlite3_blob_read()] interface and modified by using
@@ -7691,7 +8326,7 @@ typedef struct sqlite3_blob sqlite3_blob;
** blob.
**
** ^The [sqlite3_bind_zeroblob()] and [sqlite3_result_zeroblob()] interfaces
-** and the built-in [zeroblob] SQL function may be used to create a
+** and the built-in [zeroblob] SQL function may be used to create a
** zero-filled blob to read or write using the incremental-blob interface.
**
** To avoid a resource leak, every open [BLOB handle] should eventually
@@ -7741,7 +8376,7 @@ SQLITE_API int sqlite3_blob_reopen(sqlite3_blob *, sqlite3_int64);
** DESTRUCTOR: sqlite3_blob
**
** ^This function closes an open [BLOB handle]. ^(The BLOB handle is closed
-** unconditionally. Even if this routine returns an error code, the
+** unconditionally. Even if this routine returns an error code, the
** handle is still closed.)^
**
** ^If the blob handle being closed was opened for read-write access, and if
@@ -7751,10 +8386,10 @@ SQLITE_API int sqlite3_blob_reopen(sqlite3_blob *, sqlite3_int64);
** code is returned and the transaction rolled back.
**
** Calling this function with an argument that is not a NULL pointer or an
-** open blob handle results in undefined behaviour. ^Calling this routine
-** with a null pointer (such as would be returned by a failed call to
+** open blob handle results in undefined behaviour. ^Calling this routine
+** with a null pointer (such as would be returned by a failed call to
** [sqlite3_blob_open()]) is a harmless no-op. ^Otherwise, if this function
-** is passed a valid open blob handle, the values returned by the
+** is passed a valid open blob handle, the values returned by the
** sqlite3_errcode() and sqlite3_errmsg() functions are set before returning.
*/
SQLITE_API int sqlite3_blob_close(sqlite3_blob *);
@@ -7763,7 +8398,7 @@ SQLITE_API int sqlite3_blob_close(sqlite3_blob *);
** CAPI3REF: Return The Size Of An Open BLOB
** METHOD: sqlite3_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.
@@ -7814,9 +8449,9 @@ SQLITE_API int sqlite3_blob_read(sqlite3_blob *, void *Z, int N, int iOffset);
**
** ^(On success, sqlite3_blob_write() returns SQLITE_OK.
** Otherwise, an [error code] or an [extended error code] is returned.)^
-** ^Unless SQLITE_MISUSE is returned, this function sets the
-** [database connection] error code and message accessible via
-** [sqlite3_errcode()] and [sqlite3_errmsg()] and related functions.
+** ^Unless SQLITE_MISUSE is returned, this function sets the
+** [database connection] error code and message accessible via
+** [sqlite3_errcode()] and [sqlite3_errmsg()] and related functions.
**
** ^If the [BLOB handle] passed as the first argument was not opened for
** writing (the flags parameter to [sqlite3_blob_open()] was zero),
@@ -7825,9 +8460,9 @@ SQLITE_API int sqlite3_blob_read(sqlite3_blob *, void *Z, int N, int iOffset);
** This function may only modify the contents of the BLOB; it is
** not possible to increase the size of a BLOB using this API.
** ^If offset iOffset is less than N bytes from the end of the BLOB,
-** [SQLITE_ERROR] is returned and no data is written. The size of the
-** BLOB (and hence the maximum value of N+iOffset) can be determined
-** using the [sqlite3_blob_bytes()] interface. ^If N or iOffset are less
+** [SQLITE_ERROR] is returned and no data is written. The size of the
+** BLOB (and hence the maximum value of N+iOffset) can be determined
+** using the [sqlite3_blob_bytes()] interface. ^If N or iOffset are less
** than zero [SQLITE_ERROR] is returned and no data is written.
**
** ^An attempt to write to an expired [BLOB handle] fails with an
@@ -7921,7 +8556,7 @@ SQLITE_API int sqlite3_vfs_unregister(sqlite3_vfs*);
**
** - SQLITE_MUTEX_FAST
**
- SQLITE_MUTEX_RECURSIVE
-**
- SQLITE_MUTEX_STATIC_MASTER
+**
- SQLITE_MUTEX_STATIC_MAIN
**
- SQLITE_MUTEX_STATIC_MEM
**
- SQLITE_MUTEX_STATIC_OPEN
**
- SQLITE_MUTEX_STATIC_PRNG
@@ -7979,7 +8614,7 @@ SQLITE_API int sqlite3_vfs_unregister(sqlite3_vfs*);
** ^(Some systems (for example, Windows 95) do not support the operation
** implemented by sqlite3_mutex_try(). On those systems, sqlite3_mutex_try()
** will always return SQLITE_BUSY. The SQLite core only ever uses
-** sqlite3_mutex_try() as an optimization so this is acceptable
+** sqlite3_mutex_try() as an optimization so this is acceptable
** behavior.)^
**
** ^The sqlite3_mutex_leave() routine exits a mutex that was
@@ -8044,7 +8679,7 @@ SQLITE_API void sqlite3_mutex_leave(sqlite3_mutex*);
** The only difference is that the public sqlite3_XXX functions enumerated
** above silently ignore any invocations that pass a NULL pointer instead
** of a valid mutex handle. The implementations of the methods defined
-** by this structure are not required to handle this case, the results
+** by this structure are not required to handle this case. The results
** of passing a NULL pointer instead of a valid mutex handle are undefined
** (i.e. it is acceptable to provide an implementation that segfaults if
** it is passed a NULL pointer).
@@ -8123,7 +8758,7 @@ SQLITE_API int sqlite3_mutex_notheld(sqlite3_mutex*);
*/
#define SQLITE_MUTEX_FAST 0
#define SQLITE_MUTEX_RECURSIVE 1
-#define SQLITE_MUTEX_STATIC_MASTER 2
+#define SQLITE_MUTEX_STATIC_MAIN 2
#define SQLITE_MUTEX_STATIC_MEM 3 /* sqlite3_malloc() */
#define SQLITE_MUTEX_STATIC_MEM2 4 /* NOT USED */
#define SQLITE_MUTEX_STATIC_OPEN 4 /* sqlite3BtreeOpen() */
@@ -8138,11 +8773,15 @@ SQLITE_API int sqlite3_mutex_notheld(sqlite3_mutex*);
#define SQLITE_MUTEX_STATIC_VFS2 12 /* For use by extension VFS */
#define SQLITE_MUTEX_STATIC_VFS3 13 /* For use by application VFS */
+/* Legacy compatibility: */
+#define SQLITE_MUTEX_STATIC_MASTER 2
+
+
/*
** CAPI3REF: Retrieve the mutex for a database connection
** METHOD: sqlite3
**
-** ^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
@@ -8169,7 +8808,7 @@ SQLITE_API sqlite3_mutex *sqlite3_db_mutex(sqlite3*);
** method becomes the return value of this routine.
**
** A few opcodes for [sqlite3_file_control()] are handled directly
-** by the SQLite core and never invoke the
+** by the SQLite core and never invoke the
** sqlite3_io_methods.xFileControl method.
** ^The [SQLITE_FCNTL_FILE_POINTER] value for the op parameter causes
** a pointer to the underlying [sqlite3_file] object to be written into
@@ -8226,17 +8865,18 @@ SQLITE_API int sqlite3_test_control(int op, ...);
#define SQLITE_TESTCTRL_FIRST 5
#define SQLITE_TESTCTRL_PRNG_SAVE 5
#define SQLITE_TESTCTRL_PRNG_RESTORE 6
-#define SQLITE_TESTCTRL_PRNG_RESET 7
+#define SQLITE_TESTCTRL_PRNG_RESET 7 /* NOT USED */
#define SQLITE_TESTCTRL_BITVEC_TEST 8
#define SQLITE_TESTCTRL_FAULT_INSTALL 9
#define SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS 10
#define SQLITE_TESTCTRL_PENDING_BYTE 11
#define SQLITE_TESTCTRL_ASSERT 12
#define SQLITE_TESTCTRL_ALWAYS 13
-#define SQLITE_TESTCTRL_RESERVE 14
+#define SQLITE_TESTCTRL_RESERVE 14 /* NOT USED */
#define SQLITE_TESTCTRL_OPTIMIZATIONS 15
#define SQLITE_TESTCTRL_ISKEYWORD 16 /* NOT USED */
#define SQLITE_TESTCTRL_SCRATCHMALLOC 17 /* NOT USED */
+#define SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 17
#define SQLITE_TESTCTRL_LOCALTIME_FAULT 18
#define SQLITE_TESTCTRL_EXPLAIN_STMT 19 /* NOT USED */
#define SQLITE_TESTCTRL_ONCE_RESET_THRESHOLD 19
@@ -8247,12 +8887,18 @@ SQLITE_API int sqlite3_test_control(int op, ...);
#define SQLITE_TESTCTRL_SORTER_MMAP 24
#define SQLITE_TESTCTRL_IMPOSTER 25
#define SQLITE_TESTCTRL_PARSER_COVERAGE 26
-#define SQLITE_TESTCTRL_LAST 26 /* Largest TESTCTRL */
+#define SQLITE_TESTCTRL_RESULT_INTREAL 27
+#define SQLITE_TESTCTRL_PRNG_SEED 28
+#define SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS 29
+#define SQLITE_TESTCTRL_SEEK_COUNT 30
+#define SQLITE_TESTCTRL_TRACEFLAGS 31
+#define SQLITE_TESTCTRL_TUNE 32
+#define SQLITE_TESTCTRL_LAST 32 /* Largest TESTCTRL */
/*
** CAPI3REF: SQL Keyword Checking
**
-** These routines provide access to the set of SQL language keywords
+** These routines provide access to the set of SQL language keywords
** recognized by SQLite. Applications can uses these routines to determine
** whether or not a specific identifier needs to be escaped (for example,
** by enclosing in double-quotes) so as not to confuse the parser.
@@ -8324,14 +8970,14 @@ typedef struct sqlite3_str sqlite3_str;
**
** ^The [sqlite3_str_new(D)] interface allocates and initializes
** a new [sqlite3_str] object. To avoid memory leaks, the object returned by
-** [sqlite3_str_new()] must be freed by a subsequent call to
+** [sqlite3_str_new()] must be freed by a subsequent call to
** [sqlite3_str_finish(X)].
**
** ^The [sqlite3_str_new(D)] interface always returns a pointer to a
** valid [sqlite3_str] object, though in the event of an out-of-memory
** error the returned object might be a special singleton that will
-** silently reject new text, always return SQLITE_NOMEM from
-** [sqlite3_str_errcode()], always return 0 for
+** silently reject new text, always return SQLITE_NOMEM from
+** [sqlite3_str_errcode()], always return 0 for
** [sqlite3_str_length()], and always return NULL from
** [sqlite3_str_finish(X)]. It is always safe to use the value
** returned by [sqlite3_str_new(D)] as the sqlite3_str parameter
@@ -8367,9 +9013,9 @@ SQLITE_API char *sqlite3_str_finish(sqlite3_str*);
** These interfaces add content to an sqlite3_str object previously obtained
** from [sqlite3_str_new()].
**
-** ^The [sqlite3_str_appendf(X,F,...)] and
+** ^The [sqlite3_str_appendf(X,F,...)] and
** [sqlite3_str_vappendf(X,F,V)] interfaces uses the [built-in printf]
-** functionality of SQLite to append formatted text onto the end of
+** functionality of SQLite to append formatted text onto the end of
** [sqlite3_str] object X.
**
** ^The [sqlite3_str_append(X,S,N)] method appends exactly N bytes from string S
@@ -8386,7 +9032,7 @@ SQLITE_API char *sqlite3_str_finish(sqlite3_str*);
** ^This method can be used, for example, to add whitespace indentation.
**
** ^The [sqlite3_str_reset(X)] method resets the string under construction
-** inside [sqlite3_str] object X back to zero bytes in length.
+** inside [sqlite3_str] object X back to zero bytes in length.
**
** These methods do not return a result code. ^If an error occurs, that fact
** is recorded in the [sqlite3_str] object and can be recovered by a
@@ -8488,7 +9134,7 @@ SQLITE_API int sqlite3_status64(
**
- 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.
)^
**
** [[SQLITE_STATUS_MALLOC_COUNT]] ^(- SQLITE_STATUS_MALLOC_COUNT
@@ -8497,11 +9143,11 @@ SQLITE_API int sqlite3_status64(
**
** [[SQLITE_STATUS_PAGECACHE_USED]] ^(- SQLITE_STATUS_PAGECACHE_USED
** - 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.
)^
**
-** [[SQLITE_STATUS_PAGECACHE_OVERFLOW]]
+** [[SQLITE_STATUS_PAGECACHE_OVERFLOW]]
** ^(- SQLITE_STATUS_PAGECACHE_OVERFLOW
** - This parameter returns the number of bytes of page cache
** allocation which could not be satisfied by the [SQLITE_CONFIG_PAGECACHE]
@@ -8513,8 +9159,8 @@ SQLITE_API int sqlite3_status64(
**
** [[SQLITE_STATUS_PAGECACHE_SIZE]] ^(
- SQLITE_STATUS_PAGECACHE_SIZE
** - 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.
+** handed to the [pagecache memory allocator]. Only the value returned in the
+** *pHighwater parameter to [sqlite3_status()] is of interest.
** The value written into the *pCurrent parameter is undefined.
)^
**
** [[SQLITE_STATUS_SCRATCH_USED]] - SQLITE_STATUS_SCRATCH_USED
@@ -8527,7 +9173,7 @@ SQLITE_API int sqlite3_status64(
** - No longer used.
**
** [[SQLITE_STATUS_PARSER_STACK]] ^(- SQLITE_STATUS_PARSER_STACK
-** - The *pHighwater parameter records the deepest parser stack.
+**
- The *pHighwater parameter records the deepest parser stack.
** The *pCurrent value is undefined. The *pHighwater value is only
** meaningful if SQLite is compiled with [YYTRACKMAXSTACKDEPTH].
)^
**
@@ -8549,12 +9195,12 @@ SQLITE_API int sqlite3_status64(
** CAPI3REF: Database Connection Status
** METHOD: sqlite3
**
-** ^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 options], that
-** determines the parameter to interrogate. The set of
+** determines the parameter to interrogate. The set of
** [SQLITE_DBSTATUS options] is likely
** to grow in future releases of SQLite.
**
@@ -8589,7 +9235,7 @@ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int r
** checked out.)^
**
** [[SQLITE_DBSTATUS_LOOKASIDE_HIT]] ^(SQLITE_DBSTATUS_LOOKASIDE_HIT
-** This parameter returns the number malloc attempts that were
+** This parameter returns the number of malloc attempts that were
** satisfied using lookaside memory. Only the high-water value is meaningful;
** the current value is always zero.)^
**
@@ -8614,7 +9260,7 @@ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int r
** memory used by all pager caches associated with the database connection.)^
** ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_USED is always 0.
**
-** [[SQLITE_DBSTATUS_CACHE_USED_SHARED]]
+** [[SQLITE_DBSTATUS_CACHE_USED_SHARED]]
** ^(SQLITE_DBSTATUS_CACHE_USED_SHARED
** This parameter is similar to DBSTATUS_CACHE_USED, except that if a
** pager cache is shared between two or more connections the bytes of heap
@@ -8629,7 +9275,7 @@ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int r
** [[SQLITE_DBSTATUS_SCHEMA_USED]] ^(SQLITE_DBSTATUS_SCHEMA_USED
** This parameter returns the approximate number of bytes of heap
** memory used to store the schema for all databases associated
-** with the connection - main, temp, and any [ATTACH]-ed databases.)^
+** with the connection - main, temp, and any [ATTACH]-ed databases.)^
** ^The full amount of memory used by the schemas is reported, even if the
** schema memory is shared with other database connections due to
** [shared cache mode] being enabled.
@@ -8644,13 +9290,13 @@ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int r
**
** [[SQLITE_DBSTATUS_CACHE_HIT]] ^(SQLITE_DBSTATUS_CACHE_HIT
** This parameter returns the number of pager cache hits that have
-** occurred.)^ ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_HIT
+** occurred.)^ ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_HIT
** is always 0.
**
**
** [[SQLITE_DBSTATUS_CACHE_MISS]] ^(SQLITE_DBSTATUS_CACHE_MISS
** This parameter returns the number of pager cache misses that have
-** occurred.)^ ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_MISS
+** occurred.)^ ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_MISS
** is always 0.
**
**
@@ -8671,7 +9317,7 @@ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int r
** cache overflowing. Transactions are more efficient if they are written
** to disk all at once. When pages spill mid-transaction, that introduces
** additional overhead. This parameter can be used help identify
-** inefficiencies that can be resolve by increasing the cache size.
+** inefficiencies that can be resolved by increasing the cache size.
**
**
** [[SQLITE_DBSTATUS_DEFERRED_FKS]] ^(SQLITE_DBSTATUS_DEFERRED_FKS
@@ -8708,7 +9354,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
@@ -8735,7 +9381,7 @@ SQLITE_API int sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg);
** [[SQLITE_STMTSTATUS_FULLSCAN_STEP]] SQLITE_STMTSTATUS_FULLSCAN_STEP
** ^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.
**
** [[SQLITE_STMTSTATUS_SORT]] SQLITE_STMTSTATUS_SORT
@@ -8753,14 +9399,14 @@ SQLITE_API int sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg);
** [[SQLITE_STMTSTATUS_VM_STEP]] SQLITE_STMTSTATUS_VM_STEP
** ^This is the number of virtual machine operations executed
** by the prepared statement if that number is less than or equal
-** to 2147483647. The number of virtual machine operations can be
+** to 2147483647. The number of virtual machine operations can be
** used as a proxy for the total work done by the prepared statement.
** If the number of virtual machine operations exceeds 2147483647
** then the value returned by this statement status code is undefined.
**
** [[SQLITE_STMTSTATUS_REPREPARE]] SQLITE_STMTSTATUS_REPREPARE
** ^This is the number of times that the prepare statement has been
-** automatically regenerated due to schema changes or change to
+** automatically regenerated due to schema changes or changes to
** [bound parameters] that might affect the query plan.
**
** [[SQLITE_STMTSTATUS_RUN]] SQLITE_STMTSTATUS_RUN
@@ -8820,15 +9466,15 @@ struct sqlite3_pcache_page {
** KEYWORDS: {page cache}
**
** ^(The [sqlite3_config]([SQLITE_CONFIG_PCACHE2], ...) interface can
-** register an alternative page cache implementation by passing in an
+** register an alternative page cache implementation by passing in an
** instance of the sqlite3_pcache_methods2 structure.)^
-** In many applications, most of the heap memory allocated by
+** In many applications, most of the heap memory allocated by
** SQLite is used for the page cache.
-** By implementing a
+** By implementing a
** custom page cache using this API, an application can better control
-** 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
+** 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 alternative page cache mechanism is an
@@ -8841,19 +9487,19 @@ struct sqlite3_pcache_page {
** [sqlite3_config()] returns.)^
**
** [[the xInit() page cache method]]
-** ^(The xInit() method is called once for each effective
+** ^(The xInit() method is called once for each effective
** call to [sqlite3_initialize()])^
** (usually only once during the lifetime of the process). ^(The xInit()
** method is passed a copy of the sqlite3_pcache_methods2.pArg value.)^
-** The intent of the xInit() method is to set up global data structures
-** required by the custom page cache implementation.
-** ^(If the xInit() method is NULL, then the
+** The intent of the xInit() method is to set up global data structures
+** required by the custom page cache implementation.
+** ^(If the xInit() method is NULL, then the
** built-in default page cache is used instead of the application defined
** page cache.)^
**
** [[the xShutdown() page cache method]]
** ^The xShutdown() method is called by [sqlite3_shutdown()].
-** It can be used to clean up
+** It can be used to clean up
** any outstanding resources before process shutdown, if required.
** ^The xShutdown() method may be NULL.
**
@@ -8872,7 +9518,7 @@ struct sqlite3_pcache_page {
** though this is not guaranteed. ^The
** first parameter, szPage, is the size in bytes of the pages that must
** be allocated by the cache. ^szPage will always a power of two. ^The
-** second parameter szExtra is a number of bytes of extra storage
+** second parameter szExtra is a number of bytes of extra storage
** associated with each page cache entry. ^The szExtra parameter will
** a number less than 250. SQLite will use the
** extra szExtra bytes on each page to store metadata about the underlying
@@ -8885,7 +9531,7 @@ struct sqlite3_pcache_page {
** it is purely advisory. ^On a cache where bPurgeable is false, SQLite will
** never invoke xUnpin() except to deliberately delete a page.
** ^In other words, calls to xUnpin() on a cache with bPurgeable set to
-** false will always have the "discard" flag set to true.
+** false will always have the "discard" flag set to true.
** ^Hence, a cache created with bPurgeable false will
** never contain any unpinned pages.
**
@@ -8900,12 +9546,12 @@ struct sqlite3_pcache_page {
** [[the xPagecount() page cache methods]]
** The xPagecount() method must return the number of pages currently
** stored in the cache, both pinned and unpinned.
-**
+**
** [[the xFetch() page cache methods]]
-** The xFetch() method locates a page in the cache and returns a pointer to
+** The xFetch() method locates a page in the cache and returns a pointer to
** an sqlite3_pcache_page object associated with that page, or a NULL pointer.
** The pBuf element of the returned sqlite3_pcache_page object will be a
-** pointer to a buffer of szPage bytes used to store the content of a
+** pointer to a buffer of szPage bytes used to store the content of a
** single database page. The pExtra element of sqlite3_pcache_page will be
** a pointer to the szExtra bytes of extra storage that SQLite has requested
** for each entry in the page cache.
@@ -8931,7 +9577,7 @@ struct sqlite3_pcache_page {
**
** ^(SQLite will normally invoke xFetch() with a createFlag of 0 or 1. SQLite
** will only use a createFlag of 2 after a prior call with a createFlag of 1
-** failed.)^ In between the to xFetch() calls, SQLite may
+** failed.)^ In between the xFetch() calls, SQLite may
** attempt to unpin one or more cache pages by spilling the content of
** pinned pages to disk and synching the operating system disk cache.
**
@@ -8944,8 +9590,8 @@ struct sqlite3_pcache_page {
** page cache implementation. ^The page cache implementation
** may choose to evict unpinned pages at any time.
**
-** The cache must not perform any reference counting. A single
-** call to xUnpin() unpins the page regardless of the number of prior calls
+** The cache must not perform any reference counting. A single
+** call to xUnpin() unpins the page regardless of the number of prior calls
** to xFetch().
**
** [[the xRekey() page cache methods]]
@@ -8985,7 +9631,7 @@ struct sqlite3_pcache_methods2 {
int (*xPagecount)(sqlite3_pcache*);
sqlite3_pcache_page *(*xFetch)(sqlite3_pcache*, unsigned key, int createFlag);
void (*xUnpin)(sqlite3_pcache*, sqlite3_pcache_page*, int discard);
- void (*xRekey)(sqlite3_pcache*, sqlite3_pcache_page*,
+ void (*xRekey)(sqlite3_pcache*, sqlite3_pcache_page*,
unsigned oldKey, unsigned newKey);
void (*xTruncate)(sqlite3_pcache*, unsigned iLimit);
void (*xDestroy)(sqlite3_pcache*);
@@ -9030,7 +9676,7 @@ typedef struct sqlite3_backup sqlite3_backup;
**
** 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]
**
@@ -9041,36 +9687,36 @@ typedef struct sqlite3_backup sqlite3_backup;
** ^Thus, the backup may be performed on a live source database without
** preventing other database connections from
** reading or writing to the source database while the backup is underway.
-**
-** ^(To perform a backup operation:
+**
+** ^(To perform a backup operation:
**
** - sqlite3_backup_init() is called once to initialize the
-** backup,
-**
- sqlite3_backup_step() is called one or more times to transfer
+** backup,
+**
- sqlite3_backup_step() is called one or more times to transfer
** the data between the two databases, and finally
-**
- sqlite3_backup_finish() is called to release all resources
-** associated with the backup operation.
+**
- sqlite3_backup_finish() is called to release all resources
+** associated with the backup operation.
**
)^
** There should be exactly one call to sqlite3_backup_finish() for each
** successful call to sqlite3_backup_init().
**
** [[sqlite3_backup_init()]] sqlite3_backup_init()
**
-** ^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)
** must be different or else sqlite3_backup_init(D,N,S,M) will fail with
** an error.
**
-** ^A call to sqlite3_backup_init() will fail, returning NULL, if
-** there is already a read or read-write transaction open on the
+** ^A call to sqlite3_backup_init() will fail, returning NULL, if
+** there is already a read or read-write transaction open on the
** destination database.
**
** ^If an error occurs within sqlite3_backup_init(D,N,S,M), then NULL is
@@ -9082,14 +9728,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.
**
** [[sqlite3_backup_step()]] sqlite3_backup_step()
**
-** ^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 returns [SQLITE_OK].
** ^If sqlite3_backup_step(B,N) successfully finishes copying all pages
@@ -9111,8 +9757,8 @@ typedef struct sqlite3_backup sqlite3_backup;
**
** ^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]
@@ -9120,15 +9766,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.
@@ -9137,18 +9783,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.
**
** [[sqlite3_backup_finish()]] sqlite3_backup_finish()
**
-** 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
@@ -9188,8 +9834,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]
@@ -9200,11 +9846,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
@@ -9229,8 +9875,8 @@ SQLITE_API int sqlite3_backup_pagecount(sqlite3_backup *p);
** ^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.
@@ -9238,18 +9884,18 @@ 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]
-** call that concludes the blocking connections transaction.
+** call that concludes the blocking connection's transaction.
**
** ^(If sqlite3_unlock_notify() is called in a multi-threaded application,
** there is a chance that the blocking connection will have already
@@ -9259,15 +9905,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 canceled. ^The blocked connections
+** unlock-notify callback is canceled. ^The blocked connections
** unlock-notify callback may also be canceled by closing the blocked
** connection using [sqlite3_close()].
**
@@ -9280,25 +9926,25 @@ SQLITE_API int sqlite3_backup_pagecount(sqlite3_backup *p);
**
** Callback Invocation Details
**
-** 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
** an unlock-notify callback is a pointer to an array of void* pointers,
** and the second is the number of entries in the array.
**
-** When a blocking connections transaction is concluded, there may be
+** When a blocking connection's transaction is concluded, there may be
** more than one blocked connection that has registered for an unlock-notify
** callback. ^If two or more such blocked connections have specified the
** 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.
**
** Deadlock Detection
**
-** 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
@@ -9321,7 +9967,7 @@ SQLITE_API int sqlite3_backup_pagecount(sqlite3_backup *p);
**
** The "DROP TABLE" Exception
**
-** 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
@@ -9334,7 +9980,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(
@@ -9425,8 +10071,8 @@ SQLITE_API void sqlite3_log(int iErrCode, const char *zFormat, ...);
** ^The [sqlite3_wal_hook()] function is used to register a callback that
** is invoked each time data is committed to a database in 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
+** ^(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
@@ -9445,7 +10091,7 @@ SQLITE_API void sqlite3_log(int iErrCode, const char *zFormat, ...);
** 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
+** 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
@@ -9453,7 +10099,7 @@ SQLITE_API void sqlite3_log(int iErrCode, const char *zFormat, ...);
** overwrite any prior [sqlite3_wal_hook()] settings.
*/
SQLITE_API void *sqlite3_wal_hook(
- sqlite3*,
+ sqlite3*,
int(*)(void *,sqlite3*,const char*,int),
void*
);
@@ -9466,7 +10112,7 @@ SQLITE_API void *sqlite3_wal_hook(
** [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
+** more frames in the [write-ahead log] file. ^Passing zero or
** a negative value as the nFrame parameter disables automatic
** checkpoints entirely.
**
@@ -9496,7 +10142,7 @@ SQLITE_API int sqlite3_wal_autocheckpoint(sqlite3 *db, int N);
** ^(The sqlite3_wal_checkpoint(D,X) is equivalent to
** [sqlite3_wal_checkpoint_v2](D,X,[SQLITE_CHECKPOINT_PASSIVE],0,0).)^
**
-** In brief, sqlite3_wal_checkpoint(D,X) causes the content in the
+** In brief, sqlite3_wal_checkpoint(D,X) causes the content in the
** [write-ahead log] for database X on [database connection] D to be
** transferred into the database file and for the write-ahead log to
** be reset. See the [checkpointing] documentation for addition
@@ -9522,10 +10168,10 @@ SQLITE_API int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb);
**
**
** - SQLITE_CHECKPOINT_PASSIVE
-
-** ^Checkpoint as many frames as possible without waiting for any database
-** readers or writers to finish, then sync the database file if all frames
+** ^Checkpoint as many frames as possible without waiting for any database
+** readers or writers to finish, then sync the database file if all frames
** in the log were checkpointed. ^The [busy-handler callback]
-** is never invoked in the SQLITE_CHECKPOINT_PASSIVE mode.
+** is never invoked in the SQLITE_CHECKPOINT_PASSIVE mode.
** ^On the other hand, passive mode might leave the checkpoint unfinished
** if there are concurrent readers or writers.
**
@@ -9539,9 +10185,9 @@ SQLITE_API int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb);
**
**
- SQLITE_CHECKPOINT_RESTART
-
** ^This mode works the same way as SQLITE_CHECKPOINT_FULL with the addition
-** that after checkpointing the log file it blocks (calls the
+** that after checkpointing the log file it blocks (calls the
** [busy-handler callback])
-** until all readers are reading from the database file only. ^This ensures
+** until all readers are reading from the database file only. ^This ensures
** that the next writer will restart the log file from the beginning.
** ^Like SQLITE_CHECKPOINT_FULL, this mode blocks new
** database writer attempts while it is pending, but does not impede readers.
@@ -9563,31 +10209,31 @@ SQLITE_API int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb);
** truncated to zero bytes and so both *pnLog and *pnCkpt will be set to zero.
**
** ^All calls obtain an exclusive "checkpoint" lock on the database file. ^If
-** any other process is running a checkpoint operation at the same time, the
-** lock cannot be obtained and SQLITE_BUSY is returned. ^Even if there is a
+** any other process is running a checkpoint operation at the same time, the
+** lock cannot be obtained and SQLITE_BUSY is returned. ^Even if there is a
** busy-handler configured, it will not be invoked in this case.
**
-** ^The SQLITE_CHECKPOINT_FULL, RESTART and TRUNCATE modes also obtain the
+** ^The SQLITE_CHECKPOINT_FULL, RESTART and TRUNCATE modes also obtain the
** exclusive "writer" lock on the database file. ^If the writer lock cannot be
** obtained immediately, and a busy-handler is configured, it is invoked and
** the writer lock retried until either the busy-handler returns 0 or the lock
** is successfully obtained. ^The busy-handler is also invoked while waiting for
** database readers as described above. ^If the busy-handler returns 0 before
** the writer lock is obtained or while waiting for database readers, the
-** checkpoint operation proceeds from that point in the same way as
-** SQLITE_CHECKPOINT_PASSIVE - checkpointing as many frames as possible
+** checkpoint operation proceeds from that point in the same way as
+** SQLITE_CHECKPOINT_PASSIVE - checkpointing as many frames as possible
** without blocking any further. ^SQLITE_BUSY is returned in this case.
**
** ^If parameter zDb is NULL or points to a zero length string, then the
-** specified operation is attempted on all WAL databases [attached] to
+** specified operation is attempted on all WAL databases [attached] to
** [database connection] db. In this case the
-** values written to output parameters *pnLog and *pnCkpt are undefined. ^If
-** an SQLITE_BUSY error is encountered when processing one or more of the
-** attached WAL databases, the operation is still attempted on any remaining
-** attached databases and SQLITE_BUSY is returned at the end. ^If any other
-** error occurs while processing an attached database, processing is abandoned
-** and the error code is returned to the caller immediately. ^If no error
-** (SQLITE_BUSY or otherwise) is encountered while processing the attached
+** values written to output parameters *pnLog and *pnCkpt are undefined. ^If
+** an SQLITE_BUSY error is encountered when processing one or more of the
+** attached WAL databases, the operation is still attempted on any remaining
+** attached databases and SQLITE_BUSY is returned at the end. ^If any other
+** error occurs while processing an attached database, processing is abandoned
+** and the error code is returned to the caller immediately. ^If no error
+** (SQLITE_BUSY or otherwise) is encountered while processing the attached
** databases, SQLITE_OK is returned.
**
** ^If database zDb is the name of an attached database that is not in WAL
@@ -9635,21 +10281,28 @@ SQLITE_API int sqlite3_wal_checkpoint_v2(
** If this interface is invoked outside the context of an xConnect or
** xCreate virtual table method then the behavior is undefined.
**
-** At present, there is only one option that may be configured using
-** this function. (See [SQLITE_VTAB_CONSTRAINT_SUPPORT].) Further options
-** may be added in the future.
+** In the call sqlite3_vtab_config(D,C,...) the D parameter is the
+** [database connection] in which the virtual table is being created and
+** which is passed in as the first argument to the [xConnect] or [xCreate]
+** method that is invoking sqlite3_vtab_config(). The C parameter is one
+** of the [virtual table configuration options]. The presence and meaning
+** of parameters after C depend on which [virtual table configuration option]
+** is used.
*/
SQLITE_API int sqlite3_vtab_config(sqlite3*, int op, ...);
/*
** CAPI3REF: Virtual Table Configuration Options
+** KEYWORDS: {virtual table configuration options}
+** KEYWORDS: {virtual table configuration option}
**
** These macros define the various options to the
** [sqlite3_vtab_config()] interface that [virtual table] implementations
** can use to customize and optimize their behavior.
**
**
-** - SQLITE_VTAB_CONSTRAINT_SUPPORT
+** [[SQLITE_VTAB_CONSTRAINT_SUPPORT]]
+**
- SQLITE_VTAB_CONSTRAINT_SUPPORT
** - Calls of the form
** [sqlite3_vtab_config](db,SQLITE_VTAB_CONSTRAINT_SUPPORT,X) are supported,
** where X is an integer. If X is zero, then the [virtual table] whose
@@ -9663,24 +10316,46 @@ SQLITE_API int sqlite3_vtab_config(sqlite3*, int op, ...);
** If X is non-zero, then the virtual table implementation guarantees
** that if [xUpdate] returns [SQLITE_CONSTRAINT], it will do so before
** any modifications to internal or persistent data structures have been made.
-** If the [ON CONFLICT] mode is ABORT, FAIL, IGNORE or ROLLBACK, SQLite
+** If the [ON CONFLICT] mode is ABORT, FAIL, IGNORE or ROLLBACK, SQLite
** is able to roll back a statement or database transaction, and abandon
-** or continue processing the current SQL statement as appropriate.
+** or continue processing the current SQL statement as appropriate.
** If the ON CONFLICT mode is REPLACE and the [xUpdate] method returns
** [SQLITE_CONSTRAINT], SQLite handles this as if the ON CONFLICT mode
** had been ABORT.
**
** Virtual table implementations that are required to handle OR REPLACE
-** must do so within the [xUpdate] method. If a call to the
-** [sqlite3_vtab_on_conflict()] function indicates that the current ON
-** CONFLICT policy is REPLACE, the virtual table implementation should
+** must do so within the [xUpdate] method. If a call to the
+** [sqlite3_vtab_on_conflict()] function indicates that the current ON
+** CONFLICT policy is REPLACE, the virtual table implementation should
** silently replace the appropriate rows within the xUpdate callback and
** return SQLITE_OK. Or, if this is not possible, it may return
-** SQLITE_CONSTRAINT, in which case SQLite falls back to OR ABORT
+** SQLITE_CONSTRAINT, in which case SQLite falls back to OR ABORT
** constraint handling.
+**
+**
+** [[SQLITE_VTAB_DIRECTONLY]]- SQLITE_VTAB_DIRECTONLY
+** - Calls of the form
+** [sqlite3_vtab_config](db,SQLITE_VTAB_DIRECTONLY) from within the
+** the [xConnect] or [xCreate] methods of a [virtual table] implmentation
+** prohibits that virtual table from being used from within triggers and
+** views.
+**
+**
+** [[SQLITE_VTAB_INNOCUOUS]]- SQLITE_VTAB_INNOCUOUS
+** - Calls of the form
+** [sqlite3_vtab_config](db,SQLITE_VTAB_INNOCUOUS) from within the
+** the [xConnect] or [xCreate] methods of a [virtual table] implmentation
+** identify that virtual table as being safe to use from within triggers
+** and views. Conceptually, the SQLITE_VTAB_INNOCUOUS tag means that the
+** virtual table can do no serious harm even if it is controlled by a
+** malicious hacker. Developers should avoid setting the SQLITE_VTAB_INNOCUOUS
+** flag unless absolutely necessary.
+**
**
*/
#define SQLITE_VTAB_CONSTRAINT_SUPPORT 1
+#define SQLITE_VTAB_INNOCUOUS 2
+#define SQLITE_VTAB_DIRECTONLY 3
/*
** CAPI3REF: Determine The Virtual Table Conflict Policy
@@ -9698,10 +10373,11 @@ SQLITE_API int sqlite3_vtab_on_conflict(sqlite3 *);
** CAPI3REF: Determine If Virtual Table Column Access Is For UPDATE
**
** If the sqlite3_vtab_nochange(X) routine is called within the [xColumn]
-** method of a [virtual table], then it returns true if and only if the
+** method of a [virtual table], then it might return true if the
** column is being fetched as part of an UPDATE operation during which the
-** column value will not change. Applications might use this to substitute
-** a return value that is less expensive to compute and that the corresponding
+** column value will not change. The virtual table implementation can use
+** this hint as permission to substitute a return value that is less
+** expensive to compute and that the corresponding
** [xUpdate] method understands as a "no-change" value.
**
** If the [xColumn] method calls sqlite3_vtab_nochange() and finds that
@@ -9710,6 +10386,12 @@ SQLITE_API int sqlite3_vtab_on_conflict(sqlite3 *);
** any of the [sqlite3_result_int|sqlite3_result_xxxxx() interfaces].
** In that case, [sqlite3_value_nochange(X)] will return true for the
** same column in the [xUpdate] method.
+**
+** The sqlite3_vtab_nochange() routine is an optimization. Virtual table
+** implementations should continue to give a correct answer even if the
+** sqlite3_vtab_nochange() interface were to always return false. In the
+** current implementation, the sqlite3_vtab_nochange() interface does always
+** returns false for the enhanced [UPDATE FROM] statement.
*/
SQLITE_API int sqlite3_vtab_nochange(sqlite3_context*);
@@ -9717,12 +10399,12 @@ SQLITE_API int sqlite3_vtab_nochange(sqlite3_context*);
** CAPI3REF: Determine The Collation For a Virtual Table Constraint
**
** This function may only be called from within a call to the [xBestIndex]
-** method of a [virtual table].
+** method of a [virtual table].
**
** The first argument must be the sqlite3_index_info object that is the
** first parameter to the xBestIndex() method. The second argument must be
** an index into the aConstraint[] array belonging to the sqlite3_index_info
-** structure passed to xBestIndex. This function returns a pointer to a buffer
+** structure passed to xBestIndex. This function returns a pointer to a buffer
** containing the name of the collation sequence for the corresponding
** constraint.
*/
@@ -9760,15 +10442,15 @@ SQLITE_API SQLITE_EXPERIMENTAL const char *sqlite3_vtab_collation(sqlite3_index_
**
**
** [[SQLITE_SCANSTAT_NLOOP]] - SQLITE_SCANSTAT_NLOOP
-** - ^The [sqlite3_int64] variable pointed to by the T parameter will be
+**
- ^The [sqlite3_int64] variable pointed to by the V parameter will be
** set to the total number of times that the X-th loop has run.
**
** [[SQLITE_SCANSTAT_NVISIT]] - SQLITE_SCANSTAT_NVISIT
-** - ^The [sqlite3_int64] variable pointed to by the T parameter will be set
+**
- ^The [sqlite3_int64] variable pointed to by the V parameter will be set
** to the total number of rows examined by all iterations of the X-th loop.
**
** [[SQLITE_SCANSTAT_EST]] - SQLITE_SCANSTAT_EST
-** - ^The "double" variable pointed to by the T parameter will be set to the
+**
- ^The "double" variable pointed to by the V parameter will be set to the
** query planner's estimate for the average number of rows output from each
** iteration of the X-th loop. If the query planner's estimates was accurate,
** then this value will approximate the quotient NVISIT/NLOOP and the
@@ -9776,17 +10458,17 @@ SQLITE_API SQLITE_EXPERIMENTAL const char *sqlite3_vtab_collation(sqlite3_index_
** be the NLOOP value for the current loop.
**
** [[SQLITE_SCANSTAT_NAME]]
- SQLITE_SCANSTAT_NAME
-** - ^The "const char *" variable pointed to by the T parameter will be set
+**
- ^The "const char *" variable pointed to by the V parameter will be set
** to a zero-terminated UTF-8 string containing the name of the index or table
** used for the X-th loop.
**
** [[SQLITE_SCANSTAT_EXPLAIN]]
- SQLITE_SCANSTAT_EXPLAIN
-** - ^The "const char *" variable pointed to by the T parameter will be set
+**
- ^The "const char *" variable pointed to by the V parameter will be set
** to a zero-terminated UTF-8 string containing the [EXPLAIN QUERY PLAN]
** description for the X-th loop.
**
** [[SQLITE_SCANSTAT_SELECTID]]
- SQLITE_SCANSTAT_SELECT
-** - ^The "int" variable pointed to by the T parameter will be set to the
+**
- ^The "int" variable pointed to by the V parameter will be set to the
** "select-id" for the X-th loop. The select-id identifies which query or
** subquery the loop is part of. The main query has a select-id of zero.
** The select-id is the same value as is output in the first column
@@ -9836,7 +10518,7 @@ SQLITE_API int sqlite3_stmt_scanstatus(
int idx, /* Index of loop to report on */
int iScanStatusOp, /* Information desired. SQLITE_SCANSTAT_* */
void *pOut /* Result written here */
-);
+);
/*
** CAPI3REF: Zero Scan-Status Counters
@@ -9851,18 +10533,19 @@ SQLITE_API void sqlite3_stmt_scanstatus_reset(sqlite3_stmt*);
/*
** CAPI3REF: Flush caches to disk mid-transaction
+** METHOD: sqlite3
**
** ^If a write-transaction is open on [database connection] D when the
** [sqlite3_db_cacheflush(D)] interface invoked, any dirty
-** pages in the pager-cache that are not currently in use are written out
+** pages in the pager-cache that are not currently in use are written out
** to disk. A dirty page may be in use if a database cursor created by an
** active SQL statement is reading from it, or if it is page 1 of a database
** file (page 1 is always "in use"). ^The [sqlite3_db_cacheflush(D)]
** interface flushes caches for all schemas - "main", "temp", and
** any [attached] databases.
**
-** ^If this function needs to obtain extra database locks before dirty pages
-** can be flushed to disk, it does so. ^If those locks cannot be obtained
+** ^If this function needs to obtain extra database locks before dirty pages
+** can be flushed to disk, it does so. ^If those locks cannot be obtained
** immediately and there is a busy-handler callback configured, it is invoked
** in the usual manner. ^If the required lock still cannot be obtained, then
** the database is skipped and an attempt made to flush any dirty pages
@@ -9883,6 +10566,7 @@ SQLITE_API int sqlite3_db_cacheflush(sqlite3*);
/*
** CAPI3REF: The pre-update hook.
+** METHOD: sqlite3
**
** ^These interfaces are only available if SQLite is compiled using the
** [SQLITE_ENABLE_PREUPDATE_HOOK] compile-time option.
@@ -9900,7 +10584,7 @@ SQLITE_API int sqlite3_db_cacheflush(sqlite3*);
**
** ^The preupdate hook only fires for changes to real database tables; the
** preupdate hook is not invoked for changes to [virtual tables] or to
-** system tables like sqlite_master or sqlite_stat1.
+** system tables like sqlite_sequence or sqlite_stat1.
**
** ^The second parameter to the preupdate callback is a pointer to
** the [database connection] that registered the preupdate hook.
@@ -9909,21 +10593,21 @@ SQLITE_API int sqlite3_db_cacheflush(sqlite3*);
** kind of update operation that is about to occur.
** ^(The fourth parameter to the preupdate callback is the name of the
** database within the database connection that is being modified. This
-** will be "main" for the main database or "temp" for TEMP tables or
+** will be "main" for the main database or "temp" for TEMP tables or
** the name given after the AS keyword in the [ATTACH] statement for attached
** databases.)^
** ^The fifth parameter to the preupdate callback is the name of the
** table that is being modified.
**
** For an UPDATE or DELETE operation on a [rowid table], the sixth
-** parameter passed to the preupdate callback is the initial [rowid] of the
+** parameter passed to the preupdate callback is the initial [rowid] of the
** row being modified or deleted. For an INSERT operation on a rowid table,
-** or any operation on a WITHOUT ROWID table, the value of the sixth
+** or any operation on a WITHOUT ROWID table, the value of the sixth
** parameter is undefined. For an INSERT or UPDATE on a rowid table the
** seventh parameter is the final rowid value of the row being inserted
** or updated. The value of the seventh parameter passed to the callback
** function is not defined for operations on WITHOUT ROWID tables, or for
-** INSERT operations on rowid tables.
+** DELETE operations on rowid tables.
**
** The [sqlite3_preupdate_old()], [sqlite3_preupdate_new()],
** [sqlite3_preupdate_count()], and [sqlite3_preupdate_depth()] interfaces
@@ -9957,10 +10641,19 @@ SQLITE_API int sqlite3_db_cacheflush(sqlite3*);
**
** ^The [sqlite3_preupdate_depth(D)] interface returns 0 if the preupdate
** callback was invoked as a result of a direct insert, update, or delete
-** operation; or 1 for inserts, updates, or deletes invoked by top-level
+** operation; or 1 for inserts, updates, or deletes invoked by top-level
** triggers; or 2 for changes resulting from triggers called by top-level
** triggers; and so forth.
**
+** When the [sqlite3_blob_write()] API is used to update a blob column,
+** the pre-update hook is invoked with SQLITE_DELETE. This is because the
+** in this case the new values are not available. In this case, when a
+** callback made with op==SQLITE_DELETE is actuall a write using the
+** sqlite3_blob_write() API, the [sqlite3_preupdate_blobwrite()] returns
+** the index of the column being written. In other cases, where the
+** pre-update hook is being invoked for some other reason, including a
+** regular DELETE, sqlite3_preupdate_blobwrite() returns -1.
+**
** See also: [sqlite3_update_hook()]
*/
#if defined(SQLITE_ENABLE_PREUPDATE_HOOK)
@@ -9981,17 +10674,19 @@ SQLITE_API int sqlite3_preupdate_old(sqlite3 *, int, sqlite3_value **);
SQLITE_API int sqlite3_preupdate_count(sqlite3 *);
SQLITE_API int sqlite3_preupdate_depth(sqlite3 *);
SQLITE_API int sqlite3_preupdate_new(sqlite3 *, int, sqlite3_value **);
+SQLITE_API int sqlite3_preupdate_blobwrite(sqlite3 *);
#endif
/*
** CAPI3REF: Low-level system error code
+** METHOD: sqlite3
**
** ^Attempt to return the underlying operating system error code or error
** number that caused the most recent I/O error or failure to open a file.
** The return value is OS-dependent. For example, on unix systems, after
** [sqlite3_open_v2()] returns [SQLITE_CANTOPEN], this interface could be
** called to get back the underlying "errno" that caused the problem, such
-** as ENOSPC, EAUTH, EISDIR, and so forth.
+** as ENOSPC, EAUTH, EISDIR, and so forth.
*/
SQLITE_API int sqlite3_system_errno(sqlite3*);
@@ -10029,12 +10724,12 @@ typedef struct sqlite3_snapshot {
** [sqlite3_snapshot_get(D,S,P)] interface writes a pointer to the newly
** created [sqlite3_snapshot] object into *P and returns SQLITE_OK.
** If there is not already a read-transaction open on schema S when
-** this function is called, one is opened automatically.
+** this function is called, one is opened automatically.
**
** The following must be true for this function to succeed. If any of
** the following statements are false when sqlite3_snapshot_get() is
** called, SQLITE_ERROR is returned. The final value of *P is undefined
-** in this case.
+** in this case.
**
**
** - The database handle must not be in [autocommit mode].
@@ -10046,13 +10741,13 @@ typedef struct sqlite3_snapshot {
**
**
- One or more transactions must have been written to the current wal
** file since it was created on disk (by any connection). This means
-** that a snapshot cannot be taken on a wal mode database with no wal
+** that a snapshot cannot be taken on a wal mode database with no wal
** file immediately after it is first opened. At least one transaction
** must be written to it first.
**
**
** This function may also return SQLITE_NOMEM. If it is called with the
-** database handle in autocommit mode but fails for some other reason,
+** database handle in autocommit mode but fails for some other reason,
** whether or not a read transaction is opened on schema S is undefined.
**
** The [sqlite3_snapshot] object returned from a successful call to
@@ -10072,38 +10767,38 @@ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_get(
** CAPI3REF: Start a read transaction on an historical snapshot
** METHOD: sqlite3_snapshot
**
-** ^The [sqlite3_snapshot_open(D,S,P)] interface either starts a new read
-** transaction or upgrades an existing one for schema S of
-** [database connection] D such that the read transaction refers to
-** historical [snapshot] P, rather than the most recent change to the
-** database. ^The [sqlite3_snapshot_open()] interface returns SQLITE_OK
+** ^The [sqlite3_snapshot_open(D,S,P)] interface either starts a new read
+** transaction or upgrades an existing one for schema S of
+** [database connection] D such that the read transaction refers to
+** historical [snapshot] P, rather than the most recent change to the
+** database. ^The [sqlite3_snapshot_open()] interface returns SQLITE_OK
** on success or an appropriate [error code] if it fails.
**
-** ^In order to succeed, the database connection must not be in
+** ^In order to succeed, the database connection must not be in
** [autocommit mode] when [sqlite3_snapshot_open(D,S,P)] is called. If there
** is already a read transaction open on schema S, then the database handle
** must have no active statements (SELECT statements that have been passed
-** to sqlite3_step() but not sqlite3_reset() or sqlite3_finalize()).
+** to sqlite3_step() but not sqlite3_reset() or sqlite3_finalize()).
** SQLITE_ERROR is returned if either of these conditions is violated, or
** if schema S does not exist, or if the snapshot object is invalid.
**
** ^A call to sqlite3_snapshot_open() will fail to open if the specified
-** snapshot has been overwritten by a [checkpoint]. In this case
+** snapshot has been overwritten by a [checkpoint]. In this case
** SQLITE_ERROR_SNAPSHOT is returned.
**
-** If there is already a read transaction open when this function is
+** If there is already a read transaction open when this function is
** invoked, then the same read transaction remains open (on the same
** database snapshot) if SQLITE_ERROR, SQLITE_BUSY or SQLITE_ERROR_SNAPSHOT
** is returned. If another error code - for example SQLITE_PROTOCOL or an
** SQLITE_IOERR error code - is returned, then the final state of the
-** read transaction is undefined. If SQLITE_OK is returned, then the
+** read transaction is undefined. If SQLITE_OK is returned, then the
** read transaction is now open on database snapshot P.
**
** ^(A call to [sqlite3_snapshot_open(D,S,P)] will fail if the
** database connection D does not know that the database file for
** schema S is in [WAL mode]. A database connection might not know
** that the database file is in [WAL mode] if there has been no prior
-** I/O on that database connection, or if the database entered [WAL mode]
+** I/O on that database connection, or if the database entered [WAL mode]
** after the most recent I/O on the database connection.)^
** (Hint: Run "[PRAGMA application_id]" against a newly opened
** database connection in order to make it ready to use snapshots.)
@@ -10135,17 +10830,17 @@ SQLITE_API SQLITE_EXPERIMENTAL void sqlite3_snapshot_free(sqlite3_snapshot*);
** METHOD: sqlite3_snapshot
**
** The sqlite3_snapshot_cmp(P1, P2) interface is used to compare the ages
-** of two valid snapshot handles.
+** of two valid snapshot handles.
**
-** If the two snapshot handles are not associated with the same database
-** file, the result of the comparison is undefined.
+** If the two snapshot handles are not associated with the same database
+** file, the result of the comparison is undefined.
**
** Additionally, the result of the comparison is only valid if both of the
** snapshot handles were obtained by calling sqlite3_snapshot_get() since the
** last time the wal file was deleted. The wal file is deleted when the
** database is changed back to rollback mode or when the number of database
-** clients drops to zero. If either snapshot handle was obtained before the
-** wal file was last deleted, the value returned by this function
+** clients drops to zero. If either snapshot handle was obtained before the
+** wal file was last deleted, the value returned by this function
** is undefined.
**
** Otherwise, this API returns a negative value if P1 refers to an older
@@ -10210,7 +10905,7 @@ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_recover(sqlite3 *db, const c
** representation of the database will usually only exist if there has
** been a prior call to [sqlite3_deserialize(D,S,...)] with the same
** values of D and S.
-** The size of the database is written into *P even if the
+** The size of the database is written into *P even if the
** SQLITE_SERIALIZE_NOCOPY bit is set but no contiguous copy
** of the database exists.
**
@@ -10218,8 +10913,8 @@ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_recover(sqlite3 *db, const c
** SQLITE_SERIALIZE_NOCOPY bit is omitted from argument F if a memory
** allocation error occurs.
**
-** This interface is only available if SQLite is compiled with the
-** [SQLITE_ENABLE_DESERIALIZE] option.
+** This interface is omitted if SQLite is compiled with the
+** [SQLITE_OMIT_DESERIALIZE] option.
*/
SQLITE_API unsigned char *sqlite3_serialize(
sqlite3 *db, /* The database connection */
@@ -10247,7 +10942,7 @@ SQLITE_API unsigned char *sqlite3_serialize(
/*
** CAPI3REF: Deserialize a database
**
-** The sqlite3_deserialize(D,S,P,N,M,F) interface causes the
+** The sqlite3_deserialize(D,S,P,N,M,F) interface causes the
** [database connection] D to disconnect from database S and then
** reopen S as an in-memory database based on the serialization contained
** in P. The serialized database P is N bytes in size. M is the size of
@@ -10266,12 +10961,12 @@ SQLITE_API unsigned char *sqlite3_serialize(
** database is currently in a read transaction or is involved in a backup
** operation.
**
-** If sqlite3_deserialize(D,S,P,N,M,F) fails for any reason and if the
+** If sqlite3_deserialize(D,S,P,N,M,F) fails for any reason and if the
** SQLITE_DESERIALIZE_FREEONCLOSE bit is set in argument F, then
** [sqlite3_free()] is invoked on argument P prior to returning.
**
-** This interface is only available if SQLite is compiled with the
-** [SQLITE_ENABLE_DESERIALIZE] option.
+** This interface is omitted if SQLite is compiled with the
+** [SQLITE_OMIT_DESERIALIZE] option.
*/
SQLITE_API int sqlite3_deserialize(
sqlite3 *db, /* The database connection */
@@ -10381,7 +11076,7 @@ struct sqlite3_rtree_geometry {
};
/*
-** Register a 2nd-generation geometry callback named zScore that can be
+** Register a 2nd-generation geometry callback named zScore that can be
** used as part of an R-Tree geometry query as follows:
**
** SELECT ... FROM WHERE MATCH $zQueryFunc(... params ...)
@@ -10396,7 +11091,7 @@ SQLITE_API int sqlite3_rtree_query_callback(
/*
-** A pointer to a structure of the following type is passed as the
+** A pointer to a structure of the following type is passed as the
** argument to scored geometry callback registered using
** sqlite3_rtree_query_callback().
**
@@ -10418,7 +11113,7 @@ struct sqlite3_rtree_query_info {
sqlite3_int64 iRowid; /* Rowid for current entry */
sqlite3_rtree_dbl rParentScore; /* Score of parent node */
int eParentWithin; /* Visibility of parent node */
- int eWithin; /* OUT: Visiblity */
+ int eWithin; /* OUT: Visibility */
sqlite3_rtree_dbl rScore; /* OUT: Write the score here */
/* The following fields are only available in 3.8.11 and later */
sqlite3_value **apSqlParam; /* Original SQL values of parameters */
@@ -10491,7 +11186,7 @@ typedef struct sqlite3_changeset_iter sqlite3_changeset_iter;
** is not possible for an application to register a pre-update hook on a
** database handle that has one or more session objects attached. Nor is
** it possible to create a session object attached to a database handle for
-** which a pre-update hook is already defined. The results of attempting
+** which a pre-update hook is already defined. The results of attempting
** either of these things are undefined.
**
** The session object will be used to create changesets for tables in
@@ -10509,17 +11204,49 @@ SQLITE_API int sqlite3session_create(
** CAPI3REF: Delete A Session Object
** DESTRUCTOR: sqlite3_session
**
-** Delete a session object previously allocated using
+** Delete a session object previously allocated using
** [sqlite3session_create()]. Once a session object has been deleted, the
** results of attempting to use pSession with any other session module
** function are undefined.
**
** Session objects must be deleted before the database handle to which they
-** are attached is closed. Refer to the documentation for
+** are attached is closed. Refer to the documentation for
** [sqlite3session_create()] for details.
*/
SQLITE_API void sqlite3session_delete(sqlite3_session *pSession);
+/*
+** CAPIREF: Conigure a Session Object
+** METHOD: sqlite3_session
+**
+** This method is used to configure a session object after it has been
+** created. At present the only valid value for the second parameter is
+** [SQLITE_SESSION_OBJCONFIG_SIZE].
+**
+** Arguments for sqlite3session_object_config()
+**
+** The following values may passed as the the 4th parameter to
+** sqlite3session_object_config().
+**
+** - SQLITE_SESSION_OBJCONFIG_SIZE
-
+** This option is used to set, clear or query the flag that enables
+** the [sqlite3session_changeset_size()] API. Because it imposes some
+** computational overhead, this API is disabled by default. Argument
+** pArg must point to a value of type (int). If the value is initially
+** 0, then the sqlite3session_changeset_size() API is disabled. If it
+** is greater than 0, then the same API is enabled. Or, if the initial
+** value is less than zero, no change is made. In all cases the (int)
+** variable is set to 1 if the sqlite3session_changeset_size() API is
+** enabled following the current call, or 0 otherwise.
+**
+** It is an error (SQLITE_MISUSE) to attempt to modify this setting after
+** the first table has been attached to the session object.
+*/
+SQLITE_API int sqlite3session_object_config(sqlite3_session*, int op, void *pArg);
+
+/*
+*/
+#define SQLITE_SESSION_OBJCONFIG_SIZE 1
/*
** CAPI3REF: Enable Or Disable A Session Object
@@ -10533,10 +11260,10 @@ SQLITE_API void sqlite3session_delete(sqlite3_session *pSession);
** the eventual changesets.
**
** Passing zero to this function disables the session. Passing a value
-** greater than zero enables it. Passing a value less than zero is a
+** greater than zero enables it. Passing a value less than zero is a
** no-op, and may be used to query the current state of the session.
**
-** The return value indicates the final state of the session object: 0 if
+** The return value indicates the final state of the session object: 0 if
** the session is disabled, or 1 if it is enabled.
*/
SQLITE_API int sqlite3session_enable(sqlite3_session *pSession, int bEnable);
@@ -10551,7 +11278,7 @@ SQLITE_API int sqlite3session_enable(sqlite3_session *pSession, int bEnable);
**
** - The session object "indirect" flag is set when the change is
** made, or
-**
- The change is made by an SQL trigger or foreign key action
+**
- The change is made by an SQL trigger or foreign key action
** instead of directly as a result of a users SQL statement.
**
**
@@ -10563,10 +11290,10 @@ SQLITE_API int sqlite3session_enable(sqlite3_session *pSession, int bEnable);
** flag. If the second argument passed to this function is zero, then the
** indirect flag is cleared. If it is greater than zero, the indirect flag
** is set. Passing a value less than zero does not modify the current value
-** of the indirect flag, and may be used to query the current state of the
+** of the indirect flag, and may be used to query the current state of the
** indirect flag for the specified session object.
**
-** The return value indicates the final state of the indirect flag: 0 if
+** The return value indicates the final state of the indirect flag: 0 if
** it is clear, or 1 if it is set.
*/
SQLITE_API int sqlite3session_indirect(sqlite3_session *pSession, int bIndirect);
@@ -10576,20 +11303,20 @@ SQLITE_API int sqlite3session_indirect(sqlite3_session *pSession, int bIndirect)
** METHOD: sqlite3_session
**
** If argument zTab is not NULL, then it is the name of a table to attach
-** to the session object passed as the first argument. All subsequent changes
-** made to the table while the session object is enabled will be recorded. See
+** to the session object passed as the first argument. All subsequent changes
+** made to the table while the session object is enabled will be recorded. See
** documentation for [sqlite3session_changeset()] for further details.
**
** Or, if argument zTab is NULL, then changes are recorded for all tables
-** in the database. If additional tables are added to the database (by
-** executing "CREATE TABLE" statements) after this call is made, changes for
+** in the database. If additional tables are added to the database (by
+** executing "CREATE TABLE" statements) after this call is made, changes for
** the new tables are also recorded.
**
** Changes can only be recorded for tables that have a PRIMARY KEY explicitly
-** defined as part of their CREATE TABLE statement. It does not matter if the
+** defined as part of their CREATE TABLE statement. It does not matter if the
** PRIMARY KEY is an "INTEGER PRIMARY KEY" (rowid alias) or not. The PRIMARY
** KEY may consist of a single column, or may be a composite key.
-**
+**
** It is not an error if the named table does not exist in the database. Nor
** is it an error if the named table does not have a PRIMARY KEY. However,
** no changes will be recorded in either of these scenarios.
@@ -10597,29 +11324,29 @@ SQLITE_API int sqlite3session_indirect(sqlite3_session *pSession, int bIndirect)
** Changes are not recorded for individual rows that have NULL values stored
** in one or more of their PRIMARY KEY columns.
**
-** SQLITE_OK is returned if the call completes without error. Or, if an error
+** SQLITE_OK is returned if the call completes without error. Or, if an error
** occurs, an SQLite error code (e.g. SQLITE_NOMEM) is returned.
**
** Special sqlite_stat1 Handling
**
-** As of SQLite version 3.22.0, the "sqlite_stat1" table is an exception to
+** As of SQLite version 3.22.0, the "sqlite_stat1" table is an exception to
** some of the rules above. In SQLite, the schema of sqlite_stat1 is:
**
-** CREATE TABLE sqlite_stat1(tbl,idx,stat)
+** CREATE TABLE sqlite_stat1(tbl,idx,stat)
**
**
-** Even though sqlite_stat1 does not have a PRIMARY KEY, changes are
-** recorded for it as if the PRIMARY KEY is (tbl,idx). Additionally, changes
+** Even though sqlite_stat1 does not have a PRIMARY KEY, changes are
+** recorded for it as if the PRIMARY KEY is (tbl,idx). Additionally, changes
** are recorded for rows for which (idx IS NULL) is true. However, for such
** rows a zero-length blob (SQL value X'') is stored in the changeset or
** patchset instead of a NULL value. This allows such changesets to be
** manipulated by legacy implementations of sqlite3changeset_invert(),
** concat() and similar.
**
-** The sqlite3changeset_apply() function automatically converts the
+** The sqlite3changeset_apply() function automatically converts the
** zero-length blob back to a NULL value when updating the sqlite_stat1
** table. However, if the application calls sqlite3changeset_new(),
-** sqlite3changeset_old() or sqlite3changeset_conflict on a changeset
+** sqlite3changeset_old() or sqlite3changeset_conflict on a changeset
** iterator directly (including on a changeset iterator passed to a
** conflict-handler callback) then the X'' value is returned. The application
** must translate X'' to NULL itself if required.
@@ -10638,10 +11365,10 @@ SQLITE_API int sqlite3session_attach(
** CAPI3REF: Set a table filter on a Session Object.
** METHOD: sqlite3_session
**
-** The second argument (xFilter) is the "filter callback". For changes to rows
+** The second argument (xFilter) is the "filter callback". For changes to rows
** in tables that are not attached to the Session object, the filter is called
-** to determine whether changes to the table's rows should be tracked or not.
-** If xFilter returns 0, changes is not tracked. Note that once a table is
+** to determine whether changes to the table's rows should be tracked or not.
+** If xFilter returns 0, changes are not tracked. Note that once a table is
** attached, xFilter will not be called again.
*/
SQLITE_API void sqlite3session_table_filter(
@@ -10657,9 +11384,9 @@ SQLITE_API void sqlite3session_table_filter(
** CAPI3REF: Generate A Changeset From A Session Object
** METHOD: sqlite3_session
**
-** Obtain a changeset containing changes to the tables attached to the
-** session object passed as the first argument. If successful,
-** set *ppChangeset to point to a buffer containing the changeset
+** Obtain a changeset containing changes to the tables attached to the
+** session object passed as the first argument. If successful,
+** set *ppChangeset to point to a buffer containing the changeset
** and *pnChangeset to the size of the changeset in bytes before returning
** SQLITE_OK. If an error occurs, set both *ppChangeset and *pnChangeset to
** zero and return an SQLite error code.
@@ -10674,7 +11401,7 @@ SQLITE_API void sqlite3session_table_filter(
** modifies the values of primary key columns. If such a change is made, it
** is represented in a changeset as a DELETE followed by an INSERT.
**
-** Changes are not recorded for rows that have NULL values stored in one or
+** Changes are not recorded for rows that have NULL values stored in one or
** more of their PRIMARY KEY columns. If such a row is inserted or deleted,
** no corresponding change is present in the changesets returned by this
** function. If an existing row with one or more NULL values stored in
@@ -10727,14 +11454,14 @@ SQLITE_API void sqlite3session_table_filter(
**
** - For each record generated by an insert, the database is queried
** for a row with a matching primary key. If one is found, an INSERT
-** change is added to the changeset. If no such row is found, no change
+** change is added to the changeset. If no such row is found, no change
** is added to the changeset.
**
-**
- For each record generated by an update or delete, the database is
+**
- For each record generated by an update or delete, the database is
** queried for a row with a matching primary key. If such a row is
** found and one or more of the non-primary key fields have been
-** modified from their original values, an UPDATE change is added to
-** the changeset. Or, if no such row is found in the table, a DELETE
+** modified from their original values, an UPDATE change is added to
+** the changeset. Or, if no such row is found in the table, a DELETE
** change is added to the changeset. If there is a row with a matching
** primary key in the database, but all fields contain their original
** values, no change is added to the changeset.
@@ -10742,7 +11469,7 @@ SQLITE_API void sqlite3session_table_filter(
**
** This means, amongst other things, that if a row is inserted and then later
** deleted while a session object is active, neither the insert nor the delete
-** will be present in the changeset. Or if a row is deleted and then later a
+** will be present in the changeset. Or if a row is deleted and then later a
** row with the same primary key values inserted while a session object is
** active, the resulting changeset will contain an UPDATE change instead of
** a DELETE and an INSERT.
@@ -10751,10 +11478,10 @@ SQLITE_API void sqlite3session_table_filter(
** it does not accumulate records when rows are inserted, updated or deleted.
** This may appear to have some counter-intuitive effects if a single row
** is written to more than once during a session. For example, if a row
-** is inserted while a session object is enabled, then later deleted while
+** is inserted while a session object is enabled, then later deleted while
** the same session object is disabled, no INSERT record will appear in the
** changeset, even though the delete took place while the session was disabled.
-** Or, if one field of a row is updated while a session is disabled, and
+** Or, if one field of a row is updated while a session is disabled, and
** another field of the same row is updated while the session is enabled, the
** resulting changeset will contain an UPDATE change that updates both fields.
*/
@@ -10764,6 +11491,22 @@ SQLITE_API int sqlite3session_changeset(
void **ppChangeset /* OUT: Buffer containing changeset */
);
+/*
+** CAPI3REF: Return An Upper-limit For The Size Of The Changeset
+** METHOD: sqlite3_session
+**
+** By default, this function always returns 0. For it to return
+** a useful result, the sqlite3_session object must have been configured
+** to enable this API using sqlite3session_object_config() with the
+** SQLITE_SESSION_OBJCONFIG_SIZE verb.
+**
+** When enabled, this function returns an upper limit, in bytes, for the size
+** of the changeset that might be produced if sqlite3session_changeset() were
+** called. The final changeset size might be equal to or smaller than the
+** size in bytes returned by this function.
+*/
+SQLITE_API sqlite3_int64 sqlite3session_changeset_size(sqlite3_session *pSession);
+
/*
** CAPI3REF: Load The Difference Between Tables Into A Session
** METHOD: sqlite3_session
@@ -10775,7 +11518,7 @@ SQLITE_API int sqlite3session_changeset(
** an error).
**
** Argument zFromDb must be the name of a database ("main", "temp" etc.)
-** attached to the same database handle as the session object that contains
+** attached to the same database handle as the session object that contains
** a table compatible with the table attached to the session by this function.
** A table is considered compatible if it:
**
@@ -10791,33 +11534,33 @@ SQLITE_API int sqlite3session_changeset(
** APIs, tables without PRIMARY KEYs are simply ignored.
**
** This function adds a set of changes to the session object that could be
-** used to update the table in database zFrom (call this the "from-table")
-** so that its content is the same as the table attached to the session
+** used to update the table in database zFrom (call this the "from-table")
+** so that its content is the same as the table attached to the session
** object (call this the "to-table"). Specifically:
**
**
-** - For each row (primary key) that exists in the to-table but not in
+**
- For each row (primary key) that exists in the to-table but not in
** the from-table, an INSERT record is added to the session object.
**
-**
- For each row (primary key) that exists in the to-table but not in
+**
- For each row (primary key) that exists in the to-table but not in
** the from-table, a DELETE record is added to the session object.
**
-**
- For each row (primary key) that exists in both tables, but features
+**
- For each row (primary key) that exists in both tables, but features
** different non-PK values in each, an UPDATE record is added to the
-** session.
+** session.
**
**
** To clarify, if this function is called and then a changeset constructed
-** using [sqlite3session_changeset()], then after applying that changeset to
-** database zFrom the contents of the two compatible tables would be
+** using [sqlite3session_changeset()], then after applying that changeset to
+** database zFrom the contents of the two compatible tables would be
** identical.
**
** It an error if database zFrom does not exist or does not contain the
** required compatible table.
**
-** If the operation successful, SQLITE_OK is returned. Otherwise, an SQLite
+** If the operation is successful, SQLITE_OK is returned. Otherwise, an SQLite
** error code. In this case, if argument pzErrMsg is not NULL, *pzErrMsg
-** may be set to point to a buffer containing an English language error
+** may be set to point to a buffer containing an English language error
** message. It is the responsibility of the caller to free this buffer using
** sqlite3_free().
*/
@@ -10836,19 +11579,19 @@ SQLITE_API int sqlite3session_diff(
** The differences between a patchset and a changeset are that:
**
**
-** - DELETE records consist of the primary key fields only. The
+**
- DELETE records consist of the primary key fields only. The
** original values of other fields are omitted.
-**
- The original values of any modified fields are omitted from
+**
- The original values of any modified fields are omitted from
** UPDATE records.
**
**
-** A patchset blob may be used with up to date versions of all
-** sqlite3changeset_xxx API functions except for sqlite3changeset_invert(),
+** A patchset blob may be used with up to date versions of all
+** sqlite3changeset_xxx API functions except for sqlite3changeset_invert(),
** which returns SQLITE_CORRUPT if it is passed a patchset. Similarly,
** attempting to use a patchset blob with old versions of the
-** sqlite3changeset_xxx APIs also provokes an SQLITE_CORRUPT error.
+** sqlite3changeset_xxx APIs also provokes an SQLITE_CORRUPT error.
**
-** Because the non-primary key "old.*" fields are omitted, no
+** Because the non-primary key "old.*" fields are omitted, no
** SQLITE_CHANGESET_DATA conflicts can be detected or reported if a patchset
** is passed to the sqlite3changeset_apply() API. Other conflict types work
** in the same way as for changesets.
@@ -10867,22 +11610,30 @@ SQLITE_API int sqlite3session_patchset(
/*
** CAPI3REF: Test if a changeset has recorded any changes.
**
-** Return non-zero if no changes to attached tables have been recorded by
-** the session object passed as the first argument. Otherwise, if one or
+** Return non-zero if no changes to attached tables have been recorded by
+** the session object passed as the first argument. Otherwise, if one or
** more changes have been recorded, return zero.
**
** Even if this function returns zero, it is possible that calling
** [sqlite3session_changeset()] on the session handle may still return a
-** changeset that contains no changes. This can happen when a row in
-** an attached table is modified and then later on the original values
+** changeset that contains no changes. This can happen when a row in
+** an attached table is modified and then later on the original values
** are restored. However, if this function returns non-zero, then it is
-** guaranteed that a call to sqlite3session_changeset() will return a
+** guaranteed that a call to sqlite3session_changeset() will return a
** changeset containing zero changes.
*/
SQLITE_API int sqlite3session_isempty(sqlite3_session *pSession);
/*
-** CAPI3REF: Create An Iterator To Traverse A Changeset
+** CAPI3REF: Query for the amount of heap memory used by a session object.
+**
+** This API returns the total amount of heap memory in bytes currently
+** used by the session object passed as the only argument.
+*/
+SQLITE_API sqlite3_int64 sqlite3session_memory_used(sqlite3_session *pSession);
+
+/*
+** CAPI3REF: Create An Iterator To Traverse A Changeset
** CONSTRUCTOR: sqlite3_changeset_iter
**
** Create an iterator used to iterate through the contents of a changeset.
@@ -10890,7 +11641,7 @@ SQLITE_API int sqlite3session_isempty(sqlite3_session *pSession);
** is returned. Otherwise, if an error occurs, *pp is set to zero and an
** SQLite error code is returned.
**
-** The following functions can be used to advance and query a changeset
+** The following functions can be used to advance and query a changeset
** iterator created by this function:
**
**
@@ -10907,26 +11658,52 @@ SQLITE_API int sqlite3session_isempty(sqlite3_session *pSession);
**
** Assuming the changeset blob was created by one of the
** [sqlite3session_changeset()], [sqlite3changeset_concat()] or
-** [sqlite3changeset_invert()] functions, all changes within the changeset
-** that apply to a single table are grouped together. This means that when
-** an application iterates through a changeset using an iterator created by
-** this function, all changes that relate to a single table are visited
-** consecutively. There is no chance that the iterator will visit a change
-** the applies to table X, then one for table Y, and then later on visit
+** [sqlite3changeset_invert()] functions, all changes within the changeset
+** that apply to a single table are grouped together. This means that when
+** an application iterates through a changeset using an iterator created by
+** this function, all changes that relate to a single table are visited
+** consecutively. There is no chance that the iterator will visit a change
+** the applies to table X, then one for table Y, and then later on visit
** another change for table X.
+**
+** The behavior of sqlite3changeset_start_v2() and its streaming equivalent
+** may be modified by passing a combination of
+** [SQLITE_CHANGESETSTART_INVERT | supported flags] as the 4th parameter.
+**
+** Note that the sqlite3changeset_start_v2() API is still experimental
+** and therefore subject to change.
*/
SQLITE_API int sqlite3changeset_start(
sqlite3_changeset_iter **pp, /* OUT: New changeset iterator handle */
int nChangeset, /* Size of changeset blob in bytes */
void *pChangeset /* Pointer to blob containing changeset */
);
+SQLITE_API int sqlite3changeset_start_v2(
+ sqlite3_changeset_iter **pp, /* OUT: New changeset iterator handle */
+ int nChangeset, /* Size of changeset blob in bytes */
+ void *pChangeset, /* Pointer to blob containing changeset */
+ int flags /* SESSION_CHANGESETSTART_* flags */
+);
+
+/*
+** CAPI3REF: Flags for sqlite3changeset_start_v2
+**
+** The following flags may passed via the 4th parameter to
+** [sqlite3changeset_start_v2] and [sqlite3changeset_start_v2_strm]:
+**
+** - SQLITE_CHANGESETAPPLY_INVERT
-
+** Invert the changeset while iterating through it. This is equivalent to
+** inverting a changeset using sqlite3changeset_invert() before applying it.
+** It is an error to specify this flag with a patchset.
+*/
+#define SQLITE_CHANGESETSTART_INVERT 0x0002
/*
** CAPI3REF: Advance A Changeset Iterator
** METHOD: sqlite3_changeset_iter
**
-** This function may only be used with iterators created by function
+** This function may only be used with iterators created by the function
** [sqlite3changeset_start()]. If it is called on an iterator passed to
** a conflict-handler callback by [sqlite3changeset_apply()], SQLITE_MISUSE
** is returned and the call has no effect.
@@ -10937,12 +11714,12 @@ SQLITE_API int sqlite3changeset_start(
** point to the first change in the changeset. Each subsequent call advances
** the iterator to point to the next change in the changeset (if any). If
** no error occurs and the iterator points to a valid change after a call
-** to sqlite3changeset_next() has advanced it, SQLITE_ROW is returned.
+** to sqlite3changeset_next() has advanced it, SQLITE_ROW is returned.
** Otherwise, if all changes in the changeset have already been visited,
** SQLITE_DONE is returned.
**
-** If an error occurs, an SQLite error code is returned. Possible error
-** codes include SQLITE_CORRUPT (if the changeset buffer is corrupt) or
+** If an error occurs, an SQLite error code is returned. Possible error
+** codes include SQLITE_CORRUPT (if the changeset buffer is corrupt) or
** SQLITE_NOMEM.
*/
SQLITE_API int sqlite3changeset_next(sqlite3_changeset_iter *pIter);
@@ -10957,18 +11734,23 @@ SQLITE_API int sqlite3changeset_next(sqlite3_changeset_iter *pIter);
** call to [sqlite3changeset_next()] must have returned [SQLITE_ROW]. If this
** is not the case, this function returns [SQLITE_MISUSE].
**
-** If argument pzTab is not NULL, then *pzTab is set to point to a
-** nul-terminated utf-8 encoded string containing the name of the table
-** affected by the current change. The buffer remains valid until either
-** sqlite3changeset_next() is called on the iterator or until the
-** conflict-handler function returns. If pnCol is not NULL, then *pnCol is
-** set to the number of columns in the table affected by the change. If
-** pbIncorrect is not NULL, then *pbIndirect is set to true (1) if the change
+** Arguments pOp, pnCol and pzTab may not be NULL. Upon return, three
+** outputs are set through these pointers:
+**
+** *pOp is set to one of [SQLITE_INSERT], [SQLITE_DELETE] or [SQLITE_UPDATE],
+** depending on the type of change that the iterator currently points to;
+**
+** *pnCol is set to the number of columns in the table affected by the change; and
+**
+** *pzTab is set to point to a nul-terminated utf-8 encoded string containing
+** the name of the table affected by the current change. The buffer remains
+** valid until either sqlite3changeset_next() is called on the iterator
+** or until the conflict-handler function returns.
+**
+** If pbIndirect is not NULL, then *pbIndirect is set to true (1) if the change
** is an indirect change, or false (0) otherwise. See the documentation for
** [sqlite3session_indirect()] for a description of direct and indirect
-** changes. Finally, if pOp is not NULL, then *pOp is set to one of
-** [SQLITE_INSERT], [SQLITE_DELETE] or [SQLITE_UPDATE], depending on the
-** type of change that the iterator currently points to.
+** changes.
**
** If no error occurs, SQLITE_OK is returned. If an error does occur, an
** SQLite error code is returned. The values of the output variables may not
@@ -11021,7 +11803,7 @@ SQLITE_API int sqlite3changeset_pk(
** The pIter argument passed to this function may either be an iterator
** passed to a conflict-handler by [sqlite3changeset_apply()], or an iterator
** created by [sqlite3changeset_start()]. In the latter case, the most recent
-** call to [sqlite3changeset_next()] must have returned SQLITE_ROW.
+** call to [sqlite3changeset_next()] must have returned SQLITE_ROW.
** Furthermore, it may only be called if the type of change that the iterator
** currently points to is either [SQLITE_DELETE] or [SQLITE_UPDATE]. Otherwise,
** this function returns [SQLITE_MISUSE] and sets *ppValue to NULL.
@@ -11031,9 +11813,9 @@ SQLITE_API int sqlite3changeset_pk(
** [SQLITE_RANGE] is returned and *ppValue is set to NULL.
**
** If successful, this function sets *ppValue to point to a protected
-** sqlite3_value object containing the iVal'th value from the vector of
+** sqlite3_value object containing the iVal'th value from the vector of
** original row values stored as part of the UPDATE or DELETE change and
-** returns SQLITE_OK. The name of the function comes from the fact that this
+** returns SQLITE_OK. The name of the function comes from the fact that this
** is similar to the "old.*" columns available to update or delete triggers.
**
** If some other error occurs (e.g. an OOM condition), an SQLite error code
@@ -11052,7 +11834,7 @@ SQLITE_API int sqlite3changeset_old(
** The pIter argument passed to this function may either be an iterator
** passed to a conflict-handler by [sqlite3changeset_apply()], or an iterator
** created by [sqlite3changeset_start()]. In the latter case, the most recent
-** call to [sqlite3changeset_next()] must have returned SQLITE_ROW.
+** call to [sqlite3changeset_next()] must have returned SQLITE_ROW.
** Furthermore, it may only be called if the type of change that the iterator
** currently points to is either [SQLITE_UPDATE] or [SQLITE_INSERT]. Otherwise,
** this function returns [SQLITE_MISUSE] and sets *ppValue to NULL.
@@ -11062,12 +11844,12 @@ SQLITE_API int sqlite3changeset_old(
** [SQLITE_RANGE] is returned and *ppValue is set to NULL.
**
** If successful, this function sets *ppValue to point to a protected
-** sqlite3_value object containing the iVal'th value from the vector of
+** sqlite3_value object containing the iVal'th value from the vector of
** new row values stored as part of the UPDATE or INSERT change and
** returns SQLITE_OK. If the change is an UPDATE and does not include
-** a new value for the requested column, *ppValue is set to NULL and
-** SQLITE_OK returned. The name of the function comes from the fact that
-** this is similar to the "new.*" columns available to update or delete
+** a new value for the requested column, *ppValue is set to NULL and
+** SQLITE_OK returned. The name of the function comes from the fact that
+** this is similar to the "new.*" columns available to update or delete
** triggers.
**
** If some other error occurs (e.g. an OOM condition), an SQLite error code
@@ -11094,7 +11876,7 @@ SQLITE_API int sqlite3changeset_new(
** [SQLITE_RANGE] is returned and *ppValue is set to NULL.
**
** If successful, this function sets *ppValue to point to a protected
-** sqlite3_value object containing the iVal'th value from the
+** sqlite3_value object containing the iVal'th value from the
** "conflicting row" associated with the current conflict-handler callback
** and returns SQLITE_OK.
**
@@ -11138,7 +11920,7 @@ SQLITE_API int sqlite3changeset_fk_conflicts(
** call has no effect.
**
** If an error was encountered within a call to an sqlite3changeset_xxx()
-** function (for example an [SQLITE_CORRUPT] in [sqlite3changeset_next()] or an
+** function (for example an [SQLITE_CORRUPT] in [sqlite3changeset_next()] or an
** [SQLITE_NOMEM] in [sqlite3changeset_new()]) then an error code corresponding
** to that error is returned by this function. Otherwise, SQLITE_OK is
** returned. This is to allow the following pattern (pseudo-code):
@@ -11150,7 +11932,7 @@ SQLITE_API int sqlite3changeset_fk_conflicts(
** }
** rc = sqlite3changeset_finalize();
** if( rc!=SQLITE_OK ){
-** // An error has occurred
+** // An error has occurred
** }
**
*/
@@ -11178,7 +11960,7 @@ SQLITE_API int sqlite3changeset_finalize(sqlite3_changeset_iter *pIter);
** zeroed and an SQLite error code returned.
**
** It is the responsibility of the caller to eventually call sqlite3_free()
-** on the *ppOut pointer to free the buffer allocation following a successful
+** on the *ppOut pointer to free the buffer allocation following a successful
** call to this function.
**
** WARNING/TODO: This function currently assumes that the input is a valid
@@ -11192,11 +11974,11 @@ SQLITE_API int sqlite3changeset_invert(
/*
** CAPI3REF: Concatenate Two Changeset Objects
**
-** This function is used to concatenate two changesets, A and B, into a
+** This function is used to concatenate two changesets, A and B, into a
** single changeset. The result is a changeset equivalent to applying
-** changeset A followed by changeset B.
+** changeset A followed by changeset B.
**
-** This function combines the two input changesets using an
+** This function combines the two input changesets using an
** sqlite3_changegroup object. Calling it produces similar results as the
** following code fragment:
**
@@ -11228,7 +12010,7 @@ SQLITE_API int sqlite3changeset_concat(
/*
** CAPI3REF: Changegroup Handle
**
-** A changegroup is an object used to combine two or more
+** A changegroup is an object used to combine two or more
** [changesets] or [patchsets]
*/
typedef struct sqlite3_changegroup sqlite3_changegroup;
@@ -11244,7 +12026,7 @@ typedef struct sqlite3_changegroup sqlite3_changegroup;
**
** If successful, this function returns SQLITE_OK and populates (*pp) with
** a pointer to a new sqlite3_changegroup object before returning. The caller
-** should eventually free the returned object using a call to
+** should eventually free the returned object using a call to
** sqlite3changegroup_delete(). If an error occurs, an SQLite error code
** (i.e. SQLITE_NOMEM) is returned and *pp is set to NULL.
**
@@ -11256,7 +12038,7 @@ typedef struct sqlite3_changegroup sqlite3_changegroup;
**
- Zero or more changesets (or patchsets) are added to the object
** by calling sqlite3changegroup_add().
**
-**
- The result of combining all input changesets together is obtained
+**
- The result of combining all input changesets together is obtained
** by the application via a call to sqlite3changegroup_output().
**
**
- The object is deleted using a call to sqlite3changegroup_delete().
@@ -11265,7 +12047,7 @@ typedef struct sqlite3_changegroup sqlite3_changegroup;
** Any number of calls to add() and output() may be made between the calls to
** new() and delete(), and in any order.
**
-** As well as the regular sqlite3changegroup_add() and
+** As well as the regular sqlite3changegroup_add() and
** sqlite3changegroup_output() functions, also available are the streaming
** versions sqlite3changegroup_add_strm() and sqlite3changegroup_output_strm().
*/
@@ -11276,7 +12058,7 @@ SQLITE_API int sqlite3changegroup_new(sqlite3_changegroup **pp);
** METHOD: sqlite3_changegroup
**
** Add all changes within the changeset (or patchset) in buffer pData (size
-** nData bytes) to the changegroup.
+** nData bytes) to the changegroup.
**
** If the buffer contains a patchset, then all prior calls to this function
** on the same changegroup object must also have specified patchsets. Or, if
@@ -11303,7 +12085,7 @@ SQLITE_API int sqlite3changegroup_new(sqlite3_changegroup **pp);
** changeset was recorded immediately after the changesets already
** added to the changegroup.
**
| INSERT | UPDATE |
-** The INSERT change remains in the changegroup. The values in the
+** The INSERT change remains in the changegroup. The values in the
** INSERT change are modified as if the row was inserted by the
** existing change and then updated according to the new change.
** | | INSERT | DELETE |
@@ -11314,17 +12096,17 @@ SQLITE_API int sqlite3changegroup_new(sqlite3_changegroup **pp);
** changeset was recorded immediately after the changesets already
** added to the changegroup.
** | | UPDATE | UPDATE |
-** The existing UPDATE remains within the changegroup. It is amended
-** so that the accompanying values are as if the row was updated once
+** The existing UPDATE remains within the changegroup. It is amended
+** so that the accompanying values are as if the row was updated once
** by the existing change and then again by the new change.
** | | UPDATE | DELETE |
** The existing UPDATE is replaced by the new DELETE within the
** changegroup.
** | | DELETE | INSERT |
** If one or more of the column values in the row inserted by the
-** new change differ from those in the row deleted by the existing
+** new change differ from those in the row deleted by the existing
** change, the existing DELETE is replaced by an UPDATE within the
-** changegroup. Otherwise, if the inserted row is exactly the same
+** changegroup. Otherwise, if the inserted row is exactly the same
** as the deleted row, the existing DELETE is simply discarded.
** | | DELETE | UPDATE |
** The new change is ignored. This case does not occur if the new
@@ -11342,8 +12124,8 @@ SQLITE_API int sqlite3changegroup_new(sqlite3_changegroup **pp);
** case, this function fails with SQLITE_SCHEMA. If the input changeset
** appears to be corrupt and the corruption is detected, SQLITE_CORRUPT is
** returned. Or, if an out-of-memory condition occurs during processing, this
-** function returns SQLITE_NOMEM. In all cases, if an error occurs the
-** final contents of the changegroup is undefined.
+** function returns SQLITE_NOMEM. In all cases, if an error occurs the state
+** of the final contents of the changegroup is undefined.
**
** If no error occurs, SQLITE_OK is returned.
*/
@@ -11369,7 +12151,7 @@ SQLITE_API int sqlite3changegroup_add(sqlite3_changegroup*, int nData, void *pDa
**
** If an error occurs, an SQLite error code is returned and the output
** variables (*pnData) and (*ppData) are set to 0. Otherwise, SQLITE_OK
-** is returned and the output variables are set to the size of and a
+** is returned and the output variables are set to the size of and a
** pointer to the output buffer, respectively. In this case it is the
** responsibility of the caller to eventually free the buffer using a
** call to sqlite3_free().
@@ -11391,7 +12173,7 @@ SQLITE_API void sqlite3changegroup_delete(sqlite3_changegroup*);
**
** Apply a changeset or patchset to a database. These functions attempt to
** update the "main" database attached to handle db with the changes found in
-** the changeset passed via the second and third arguments.
+** the changeset passed via the second and third arguments.
**
** The fourth argument (xFilter) passed to these functions is the "filter
** callback". If it is not NULL, then for each table affected by at least one
@@ -11402,16 +12184,16 @@ SQLITE_API void sqlite3changegroup_delete(sqlite3_changegroup*);
** Otherwise, if the return value is non-zero or the xFilter argument to
** is NULL, all changes related to the table are attempted.
**
-** For each table that is not excluded by the filter callback, this function
-** tests that the target database contains a compatible table. A table is
+** For each table that is not excluded by the filter callback, this function
+** tests that the target database contains a compatible table. A table is
** considered compatible if all of the following are true:
**
**
-** - The table has the same name as the name recorded in the
+**
- The table has the same name as the name recorded in the
** changeset, and
-**
- The table has at least as many columns as recorded in the
+**
- The table has at least as many columns as recorded in the
** changeset, and
-**
- The table has primary key columns in the same position as
+**
- The table has primary key columns in the same position as
** recorded in the changeset.
**
**
@@ -11420,11 +12202,11 @@ SQLITE_API void sqlite3changegroup_delete(sqlite3_changegroup*);
** via the sqlite3_log() mechanism with the error code SQLITE_SCHEMA. At most
** one such warning is issued for each table in the changeset.
**
-** For each change for which there is a compatible table, an attempt is made
-** to modify the table contents according to the UPDATE, INSERT or DELETE
-** change. If a change cannot be applied cleanly, the conflict handler
-** function passed as the fifth argument to sqlite3changeset_apply() may be
-** invoked. A description of exactly when the conflict handler is invoked for
+** For each change for which there is a compatible table, an attempt is made
+** to modify the table contents according to the UPDATE, INSERT or DELETE
+** change. If a change cannot be applied cleanly, the conflict handler
+** function passed as the fifth argument to sqlite3changeset_apply() may be
+** invoked. A description of exactly when the conflict handler is invoked for
** each type of change is below.
**
** Unlike the xFilter argument, xConflict may not be passed NULL. The results
@@ -11432,23 +12214,23 @@ SQLITE_API void sqlite3changegroup_delete(sqlite3_changegroup*);
** argument are undefined.
**
** Each time the conflict handler function is invoked, it must return one
-** of [SQLITE_CHANGESET_OMIT], [SQLITE_CHANGESET_ABORT] or
+** of [SQLITE_CHANGESET_OMIT], [SQLITE_CHANGESET_ABORT] or
** [SQLITE_CHANGESET_REPLACE]. SQLITE_CHANGESET_REPLACE may only be returned
** if the second argument passed to the conflict handler is either
** SQLITE_CHANGESET_DATA or SQLITE_CHANGESET_CONFLICT. If the conflict-handler
** returns an illegal value, any changes already made are rolled back and
-** the call to sqlite3changeset_apply() returns SQLITE_MISUSE. Different
+** the call to sqlite3changeset_apply() returns SQLITE_MISUSE. Different
** actions are taken by sqlite3changeset_apply() depending on the value
** returned by each invocation of the conflict-handler function. Refer to
-** the documentation for the three
+** the documentation for the three
** [SQLITE_CHANGESET_OMIT|available return values] for details.
**
**
** - DELETE Changes
-
-** For each DELETE change, the function checks if the target database
-** contains a row with the same primary key value (or values) as the
-** original row values stored in the changeset. If it does, and the values
-** stored in all non-primary key columns also match the values stored in
+** For each DELETE change, the function checks if the target database
+** contains a row with the same primary key value (or values) as the
+** original row values stored in the changeset. If it does, and the values
+** stored in all non-primary key columns also match the values stored in
** the changeset the row is deleted from the target database.
**
** If a row with matching primary key values is found, but one or more of
@@ -11477,22 +12259,22 @@ SQLITE_API void sqlite3changegroup_delete(sqlite3_changegroup*);
** database table, the trailing fields are populated with their default
** values.
**
-** If the attempt to insert the row fails because the database already
+** If the attempt to insert the row fails because the database already
** contains a row with the same primary key values, the conflict handler
-** function is invoked with the second argument set to
+** function is invoked with the second argument set to
** [SQLITE_CHANGESET_CONFLICT].
**
** If the attempt to insert the row fails because of some other constraint
-** violation (e.g. NOT NULL or UNIQUE), the conflict handler function is
+** violation (e.g. NOT NULL or UNIQUE), the conflict handler function is
** invoked with the second argument set to [SQLITE_CHANGESET_CONSTRAINT].
-** This includes the case where the INSERT operation is re-attempted because
-** an earlier call to the conflict handler function returned
+** This includes the case where the INSERT operation is re-attempted because
+** an earlier call to the conflict handler function returned
** [SQLITE_CHANGESET_REPLACE].
**
**
- UPDATE Changes
-
-** For each UPDATE change, the function checks if the target database
-** contains a row with the same primary key value (or values) as the
-** original row values stored in the changeset. If it does, and the values
+** For each UPDATE change, the function checks if the target database
+** contains a row with the same primary key value (or values) as the
+** original row values stored in the changeset. If it does, and the values
** stored in all modified non-primary key columns also match the values
** stored in the changeset the row is updated within the target database.
**
@@ -11508,28 +12290,28 @@ SQLITE_API void sqlite3changegroup_delete(sqlite3_changegroup*);
** the conflict-handler function is invoked with [SQLITE_CHANGESET_NOTFOUND]
** passed as the second argument.
**
-** If the UPDATE operation is attempted, but SQLite returns
-** SQLITE_CONSTRAINT, the conflict-handler function is invoked with
+** If the UPDATE operation is attempted, but SQLite returns
+** SQLITE_CONSTRAINT, the conflict-handler function is invoked with
** [SQLITE_CHANGESET_CONSTRAINT] passed as the second argument.
-** This includes the case where the UPDATE operation is attempted after
+** This includes the case where the UPDATE operation is attempted after
** an earlier call to the conflict handler function returned
-** [SQLITE_CHANGESET_REPLACE].
+** [SQLITE_CHANGESET_REPLACE].
**
**
** It is safe to execute SQL statements, including those that write to the
** table that the callback related to, from within the xConflict callback.
-** This can be used to further customize the applications conflict
+** This can be used to further customize the application's conflict
** resolution strategy.
**
** All changes made by these functions are enclosed in a savepoint transaction.
** If any other error (aside from a constraint failure when attempting to
** write to the target database) occurs, then the savepoint transaction is
-** rolled back, restoring the target database to its original state, and an
+** rolled back, restoring the target database to its original state, and an
** SQLite error code returned.
**
** If the output parameters (ppRebase) and (pnRebase) are non-NULL and
** the input is a changeset (not a patchset), then sqlite3changeset_apply_v2()
-** may set (*ppRebase) to point to a "rebase" that may be used with the
+** may set (*ppRebase) to point to a "rebase" that may be used with the
** sqlite3_rebaser APIs buffer before returning. In this case (*pnRebase)
** is set to the size of the buffer in bytes. It is the responsibility of the
** caller to eventually free any such buffer using sqlite3_free(). The buffer
@@ -11574,7 +12356,7 @@ SQLITE_API int sqlite3changeset_apply_v2(
),
void *pCtx, /* First argument passed to xConflict */
void **ppRebase, int *pnRebase, /* OUT: Rebase data */
- int flags /* Combination of SESSION_APPLY_* flags */
+ int flags /* SESSION_CHANGESETAPPLY_* flags */
);
/*
@@ -11590,12 +12372,18 @@ SQLITE_API int sqlite3changeset_apply_v2(
** SAVEPOINT is committed if the changeset or patchset is successfully
** applied, or rolled back if an error occurs. Specifying this flag
** causes the sessions module to omit this savepoint. In this case, if the
-** caller has an open transaction or savepoint when apply_v2() is called,
+** caller has an open transaction or savepoint when apply_v2() is called,
** it may revert the partially applied changeset by rolling it back.
+**
+** - SQLITE_CHANGESETAPPLY_INVERT
-
+** Invert the changeset before applying it. This is equivalent to inverting
+** a changeset using sqlite3changeset_invert() before applying it. It is
+** an error to specify this flag with a patchset.
*/
#define SQLITE_CHANGESETAPPLY_NOSAVEPOINT 0x0001
+#define SQLITE_CHANGESETAPPLY_INVERT 0x0002
-/*
+/*
** CAPI3REF: Constants Passed To The Conflict Handler
**
** Values that may be passed as the second argument to a conflict-handler.
@@ -11604,32 +12392,32 @@ SQLITE_API int sqlite3changeset_apply_v2(
**
- SQLITE_CHANGESET_DATA
-
** The conflict handler is invoked with CHANGESET_DATA as the second argument
** when processing a DELETE or UPDATE change if a row with the required
-** PRIMARY KEY fields is present in the database, but one or more other
-** (non primary-key) fields modified by the update do not contain the
+** PRIMARY KEY fields is present in the database, but one or more other
+** (non primary-key) fields modified by the update do not contain the
** expected "before" values.
-**
+**
** The conflicting row, in this case, is the database row with the matching
** primary key.
-**
+**
**
- SQLITE_CHANGESET_NOTFOUND
-
** The conflict handler is invoked with CHANGESET_NOTFOUND as the second
** argument when processing a DELETE or UPDATE change if a row with the
** required PRIMARY KEY fields is not present in the database.
-**
+**
** There is no conflicting row in this case. The results of invoking the
** sqlite3changeset_conflict() API are undefined.
-**
+**
**
- SQLITE_CHANGESET_CONFLICT
-
** CHANGESET_CONFLICT is passed as the second argument to the conflict
-** handler while processing an INSERT change if the operation would result
+** handler while processing an INSERT change if the operation would result
** in duplicate primary key values.
-**
+**
** The conflicting row in this case is the database row with the matching
** primary key.
**
**
- SQLITE_CHANGESET_FOREIGN_KEY
-
** If foreign key handling is enabled, and applying a changeset leaves the
-** database in a state containing foreign key violations, the conflict
+** database in a state containing foreign key violations, the conflict
** handler is invoked with CHANGESET_FOREIGN_KEY as the second argument
** exactly once before the changeset is committed. If the conflict handler
** returns CHANGESET_OMIT, the changes, including those that caused the
@@ -11639,12 +12427,12 @@ SQLITE_API int sqlite3changeset_apply_v2(
** No current or conflicting row information is provided. The only function
** it is possible to call on the supplied sqlite3_changeset_iter handle
** is sqlite3changeset_fk_conflicts().
-**
+**
**
- SQLITE_CHANGESET_CONSTRAINT
-
-** If any other constraint violation occurs while applying a change (i.e.
-** a UNIQUE, CHECK or NOT NULL constraint), the conflict handler is
+** If any other constraint violation occurs while applying a change (i.e.
+** a UNIQUE, CHECK or NOT NULL constraint), the conflict handler is
** invoked with CHANGESET_CONSTRAINT as the second argument.
-**
+**
** There is no conflicting row in this case. The results of invoking the
** sqlite3changeset_conflict() API are undefined.
**
@@ -11656,7 +12444,7 @@ SQLITE_API int sqlite3changeset_apply_v2(
#define SQLITE_CHANGESET_CONSTRAINT 4
#define SQLITE_CHANGESET_FOREIGN_KEY 5
-/*
+/*
** CAPI3REF: Constants Returned By The Conflict Handler
**
** A conflict handler callback must return one of the following three values.
@@ -11664,13 +12452,13 @@ SQLITE_API int sqlite3changeset_apply_v2(
**
** - SQLITE_CHANGESET_OMIT
-
** If a conflict handler returns this value no special action is taken. The
-** change that caused the conflict is not applied. The session module
+** change that caused the conflict is not applied. The session module
** continues to the next change in the changeset.
**
**
- SQLITE_CHANGESET_REPLACE
-
** This value may only be returned if the second argument to the conflict
** handler was SQLITE_CHANGESET_DATA or SQLITE_CHANGESET_CONFLICT. If this
-** is not the case, any changes applied so far are rolled back and the
+** is not the case, any changes applied so far are rolled back and the
** call to sqlite3changeset_apply() returns SQLITE_MISUSE.
**
** If CHANGESET_REPLACE is returned by an SQLITE_CHANGESET_DATA conflict
@@ -11683,7 +12471,7 @@ SQLITE_API int sqlite3changeset_apply_v2(
** the original row is restored to the database before continuing.
**
**
- SQLITE_CHANGESET_ABORT
-
-** If this value is returned, any changes applied so far are rolled back
+** If this value is returned, any changes applied so far are rolled back
** and the call to sqlite3changeset_apply() returns SQLITE_ABORT.
**
*/
@@ -11691,20 +12479,20 @@ SQLITE_API int sqlite3changeset_apply_v2(
#define SQLITE_CHANGESET_REPLACE 1
#define SQLITE_CHANGESET_ABORT 2
-/*
+/*
** CAPI3REF: Rebasing changesets
** EXPERIMENTAL
**
** Suppose there is a site hosting a database in state S0. And that
** modifications are made that move that database to state S1 and a
** changeset recorded (the "local" changeset). Then, a changeset based
-** on S0 is received from another site (the "remote" changeset) and
-** applied to the database. The database is then in state
+** on S0 is received from another site (the "remote" changeset) and
+** applied to the database. The database is then in state
** (S1+"remote"), where the exact state depends on any conflict
** resolution decisions (OMIT or REPLACE) made while applying "remote".
-** Rebasing a changeset is to update it to take those conflict
+** Rebasing a changeset is to update it to take those conflict
** resolution decisions into account, so that the same conflicts
-** do not have to be resolved elsewhere in the network.
+** do not have to be resolved elsewhere in the network.
**
** For example, if both the local and remote changesets contain an
** INSERT of the same key on "CREATE TABLE t1(a PRIMARY KEY, b)":
@@ -11723,7 +12511,7 @@ SQLITE_API int sqlite3changeset_apply_v2(
**
**
** - Local INSERT
-
-** This may only conflict with a remote INSERT. If the conflict
+** This may only conflict with a remote INSERT. If the conflict
** resolution was OMIT, then add an UPDATE change to the rebased
** changeset. Or, if the conflict resolution was REPLACE, add
** nothing to the rebased changeset.
@@ -11747,12 +12535,12 @@ SQLITE_API int sqlite3changeset_apply_v2(
** the old.* values are rebased using the new.* values in the remote
** change. Or, if the resolution is REPLACE, then the change is copied
** into the rebased changeset with updates to columns also updated by
-** the conflicting remote UPDATE removed. If this means no columns would
+** the conflicting remote UPDATE removed. If this means no columns would
** be updated, the change is omitted.
**
**
-** A local change may be rebased against multiple remote changes
-** simultaneously. If a single key is modified by multiple remote
+** A local change may be rebased against multiple remote changes
+** simultaneously. If a single key is modified by multiple remote
** changesets, they are combined as follows before the local changeset
** is rebased:
**
@@ -11765,10 +12553,10 @@ SQLITE_API int sqlite3changeset_apply_v2(
** of the OMIT resolutions.
**
**
-** Note that conflict resolutions from multiple remote changesets are
-** combined on a per-field basis, not per-row. This means that in the
-** case of multiple remote UPDATE operations, some fields of a single
-** local change may be rebased for REPLACE while others are rebased for
+** Note that conflict resolutions from multiple remote changesets are
+** combined on a per-field basis, not per-row. This means that in the
+** case of multiple remote UPDATE operations, some fields of a single
+** local change may be rebased for REPLACE while others are rebased for
** OMIT.
**
** In order to rebase a local changeset, the remote changeset must first
@@ -11776,7 +12564,7 @@ SQLITE_API int sqlite3changeset_apply_v2(
** the buffer of rebase information captured. Then:
**
**
-** - An sqlite3_rebaser object is created by calling
+**
- An sqlite3_rebaser object is created by calling
** sqlite3rebaser_create().
**
- The new object is configured with the rebase buffer obtained from
** sqlite3changeset_apply_v2() by calling sqlite3rebaser_configure().
@@ -11797,8 +12585,8 @@ typedef struct sqlite3_rebaser sqlite3_rebaser;
**
** Allocate a new changeset rebaser object. If successful, set (*ppNew) to
** point to the new object and return SQLITE_OK. Otherwise, if an error
-** occurs, return an SQLite error code (e.g. SQLITE_NOMEM) and set (*ppNew)
-** to NULL.
+** occurs, return an SQLite error code (e.g. SQLITE_NOMEM) and set (*ppNew)
+** to NULL.
*/
SQLITE_API int sqlite3rebaser_create(sqlite3_rebaser **ppNew);
@@ -11812,9 +12600,9 @@ SQLITE_API int sqlite3rebaser_create(sqlite3_rebaser **ppNew);
** sqlite3changeset_apply_v2().
*/
SQLITE_API int sqlite3rebaser_configure(
- sqlite3_rebaser*,
+ sqlite3_rebaser*,
int nRebase, const void *pRebase
-);
+);
/*
** CAPI3REF: Rebase a changeset
@@ -11822,9 +12610,9 @@ SQLITE_API int sqlite3rebaser_configure(
**
** Argument pIn must point to a buffer containing a changeset nIn bytes
** in size. This function allocates and populates a buffer with a copy
-** of the changeset rebased rebased according to the configuration of the
+** of the changeset rebased according to the configuration of the
** rebaser object passed as the first argument. If successful, (*ppOut)
-** is set to point to the new buffer containing the rebased changset and
+** is set to point to the new buffer containing the rebased changeset and
** (*pnOut) to its size in bytes and SQLITE_OK returned. It is the
** responsibility of the caller to eventually free the new buffer using
** sqlite3_free(). Otherwise, if an error occurs, (*ppOut) and (*pnOut)
@@ -11832,8 +12620,8 @@ SQLITE_API int sqlite3rebaser_configure(
*/
SQLITE_API int sqlite3rebaser_rebase(
sqlite3_rebaser*,
- int nIn, const void *pIn,
- int *pnOut, void **ppOut
+ int nIn, const void *pIn,
+ int *pnOut, void **ppOut
);
/*
@@ -11844,30 +12632,30 @@ SQLITE_API int sqlite3rebaser_rebase(
** should be one call to this function for each successful invocation
** of sqlite3rebaser_create().
*/
-SQLITE_API void sqlite3rebaser_delete(sqlite3_rebaser *p);
+SQLITE_API void sqlite3rebaser_delete(sqlite3_rebaser *p);
/*
** CAPI3REF: Streaming Versions of API functions.
**
-** The six streaming API xxx_strm() functions serve similar purposes to the
+** The six streaming API xxx_strm() functions serve similar purposes to the
** corresponding non-streaming API functions:
**
**
** | Streaming function | Non-streaming equivalent |
-**
|---|
| sqlite3changeset_apply_strm | [sqlite3changeset_apply]
-** | | sqlite3changeset_apply_strm_v2 | [sqlite3changeset_apply_v2]
-** | | sqlite3changeset_concat_strm | [sqlite3changeset_concat]
-** | | sqlite3changeset_invert_strm | [sqlite3changeset_invert]
-** | | sqlite3changeset_start_strm | [sqlite3changeset_start]
-** | | sqlite3session_changeset_strm | [sqlite3session_changeset]
-** | | sqlite3session_patchset_strm | [sqlite3session_patchset]
+** | | sqlite3changeset_apply_strm | [sqlite3changeset_apply]
+** | | sqlite3changeset_apply_strm_v2 | [sqlite3changeset_apply_v2]
+** | | sqlite3changeset_concat_strm | [sqlite3changeset_concat]
+** | | sqlite3changeset_invert_strm | [sqlite3changeset_invert]
+** | | sqlite3changeset_start_strm | [sqlite3changeset_start]
+** | | sqlite3session_changeset_strm | [sqlite3session_changeset]
+** | | sqlite3session_patchset_strm | [sqlite3session_patchset]
** |
**
** Non-streaming functions that accept changesets (or patchsets) as input
-** require that the entire changeset be stored in a single buffer in memory.
-** Similarly, those that return a changeset or patchset do so by returning
-** a pointer to a single large buffer allocated using sqlite3_malloc().
-** Normally this is convenient. However, if an application running in a
+** require that the entire changeset be stored in a single buffer in memory.
+** Similarly, those that return a changeset or patchset do so by returning
+** a pointer to a single large buffer allocated using sqlite3_malloc().
+** Normally this is convenient. However, if an application running in a
** low-memory environment is required to handle very large changesets, the
** large contiguous memory allocations required can become onerous.
**
@@ -11889,12 +12677,12 @@ SQLITE_API void sqlite3rebaser_delete(sqlite3_rebaser *p);
**
**
** Each time the xInput callback is invoked by the sessions module, the first
-** argument passed is a copy of the supplied pIn context pointer. The second
-** argument, pData, points to a buffer (*pnData) bytes in size. Assuming no
-** error occurs the xInput method should copy up to (*pnData) bytes of data
-** into the buffer and set (*pnData) to the actual number of bytes copied
-** before returning SQLITE_OK. If the input is completely exhausted, (*pnData)
-** should be set to zero to indicate this. Or, if an error occurs, an SQLite
+** argument passed is a copy of the supplied pIn context pointer. The second
+** argument, pData, points to a buffer (*pnData) bytes in size. Assuming no
+** error occurs the xInput method should copy up to (*pnData) bytes of data
+** into the buffer and set (*pnData) to the actual number of bytes copied
+** before returning SQLITE_OK. If the input is completely exhausted, (*pnData)
+** should be set to zero to indicate this. Or, if an error occurs, an SQLite
** error code should be returned. In all cases, if an xInput callback returns
** an error, all processing is abandoned and the streaming API function
** returns a copy of the error code to the caller.
@@ -11902,7 +12690,7 @@ SQLITE_API void sqlite3rebaser_delete(sqlite3_rebaser *p);
** In the case of sqlite3changeset_start_strm(), the xInput callback may be
** invoked by the sessions module at any point during the lifetime of the
** iterator. If such an xInput callback returns an error, the iterator enters
-** an error state, whereby all subsequent calls to iterator functions
+** an error state, whereby all subsequent calls to iterator functions
** immediately fail with the same error code as returned by xInput.
**
** Similarly, streaming API functions that return changesets (or patchsets)
@@ -11932,7 +12720,7 @@ SQLITE_API void sqlite3rebaser_delete(sqlite3_rebaser *p);
** is immediately abandoned and the streaming API function returns a copy
** of the xOutput error code to the application.
**
-** The sessions module never invokes an xOutput callback with the third
+** The sessions module never invokes an xOutput callback with the third
** parameter set to a value less than or equal to zero. Other than this,
** no guarantees are made as to the size of the chunks of data returned.
*/
@@ -11987,6 +12775,12 @@ SQLITE_API int sqlite3changeset_start_strm(
int (*xInput)(void *pIn, void *pData, int *pnData),
void *pIn
);
+SQLITE_API int sqlite3changeset_start_v2_strm(
+ sqlite3_changeset_iter **pp,
+ int (*xInput)(void *pIn, void *pData, int *pnData),
+ void *pIn,
+ int flags
+);
SQLITE_API int sqlite3session_changeset_strm(
sqlite3_session *pSession,
int (*xOutput)(void *pOut, const void *pData, int nData),
@@ -11997,12 +12791,12 @@ SQLITE_API int sqlite3session_patchset_strm(
int (*xOutput)(void *pOut, const void *pData, int nData),
void *pOut
);
-SQLITE_API int sqlite3changegroup_add_strm(sqlite3_changegroup*,
+SQLITE_API int sqlite3changegroup_add_strm(sqlite3_changegroup*,
int (*xInput)(void *pIn, void *pData, int *pnData),
void *pIn
);
SQLITE_API int sqlite3changegroup_output_strm(sqlite3_changegroup*,
- int (*xOutput)(void *pOut, const void *pData, int nData),
+ int (*xOutput)(void *pOut, const void *pData, int nData),
void *pOut
);
SQLITE_API int sqlite3rebaser_rebase_strm(
@@ -12013,6 +12807,45 @@ SQLITE_API int sqlite3rebaser_rebase_strm(
void *pOut
);
+/*
+** CAPI3REF: Configure global parameters
+**
+** The sqlite3session_config() interface is used to make global configuration
+** changes to the sessions module in order to tune it to the specific needs
+** of the application.
+**
+** The sqlite3session_config() interface is not threadsafe. If it is invoked
+** while any other thread is inside any other sessions method then the
+** results are undefined. Furthermore, if it is invoked after any sessions
+** related objects have been created, the results are also undefined.
+**
+** The first argument to the sqlite3session_config() function must be one
+** of the SQLITE_SESSION_CONFIG_XXX constants defined below. The
+** interpretation of the (void*) value passed as the second parameter and
+** the effect of calling this function depends on the value of the first
+** parameter.
+**
+**
+** - SQLITE_SESSION_CONFIG_STRMSIZE
-
+** By default, the sessions module streaming interfaces attempt to input
+** and output data in approximately 1 KiB chunks. This operand may be used
+** to set and query the value of this configuration setting. The pointer
+** passed as the second argument must point to a value of type (int).
+** If this value is greater than 0, it is used as the new streaming data
+** chunk size for both input and output. Before returning, the (int) value
+** pointed to by pArg is set to the final value of the streaming interface
+** chunk size.
+**
+**
+** This function returns SQLITE_OK if successful, or an SQLite error code
+** otherwise.
+*/
+SQLITE_API int sqlite3session_config(int op, void *pArg);
+
+/*
+** CAPI3REF: Values for sqlite3session_config().
+*/
+#define SQLITE_SESSION_CONFIG_STRMSIZE 1
/*
** Make sure we can call this stuff from C++.
@@ -12037,7 +12870,7 @@ SQLITE_API int sqlite3rebaser_rebase_strm(
**
******************************************************************************
**
-** Interfaces to extend FTS5. Using the interfaces defined in this file,
+** Interfaces to extend FTS5. Using the interfaces defined in this file,
** FTS5 may be extended with:
**
** * custom tokenizers, and
@@ -12081,19 +12914,19 @@ struct Fts5PhraseIter {
** EXTENSION API FUNCTIONS
**
** xUserData(pFts):
-** Return a copy of the context pointer the extension function was
+** Return a copy of the context pointer the extension function was
** registered with.
**
** xColumnTotalSize(pFts, iCol, pnToken):
** If parameter iCol is less than zero, set output variable *pnToken
** to the total number of tokens in the FTS5 table. Or, if iCol is
** non-negative but less than the number of columns in the table, return
-** the total number of tokens in column iCol, considering all rows in
+** the total number of tokens in column iCol, considering all rows in
** the FTS5 table.
**
** If parameter iCol is greater than or equal to the number of columns
** in the table, SQLITE_RANGE is returned. Or, if an error occurs (e.g.
-** an OOM condition or IO error), an appropriate SQLite error code is
+** an OOM condition or IO error), an appropriate SQLite error code is
** returned.
**
** xColumnCount(pFts):
@@ -12107,7 +12940,7 @@ struct Fts5PhraseIter {
**
** If parameter iCol is greater than or equal to the number of columns
** in the table, SQLITE_RANGE is returned. Or, if an error occurs (e.g.
-** an OOM condition or IO error), an appropriate SQLite error code is
+** an OOM condition or IO error), an appropriate SQLite error code is
** returned.
**
** This function may be quite inefficient if used with an FTS5 table
@@ -12134,8 +12967,8 @@ struct Fts5PhraseIter {
** an error code (i.e. SQLITE_NOMEM) if an error occurs.
**
** This API can be quite slow if used with an FTS5 table created with the
-** "detail=none" or "detail=column" option. If the FTS5 table is created
-** with either "detail=none" or "detail=column" and "content=" option
+** "detail=none" or "detail=column" option. If the FTS5 table is created
+** with either "detail=none" or "detail=column" and "content=" option
** (i.e. if it is a contentless table), then this API always returns 0.
**
** xInst:
@@ -12146,15 +12979,11 @@ struct Fts5PhraseIter {
**
** Usually, output parameter *piPhrase is set to the phrase number, *piCol
** to the column in which it occurs and *piOff the token offset of the
-** first token of the phrase. The exception is if the table was created
-** with the offsets=0 option specified. In this case *piOff is always
-** set to -1.
-**
-** Returns SQLITE_OK if successful, or an error code (i.e. SQLITE_NOMEM)
-** if an error occurs.
+** first token of the phrase. Returns SQLITE_OK if successful, or an error
+** code (i.e. SQLITE_NOMEM) if an error occurs.
**
** This API can be quite slow if used with an FTS5 table created with the
-** "detail=none" or "detail=column" option.
+** "detail=none" or "detail=column" option.
**
** xRowid:
** Returns the rowid of the current row.
@@ -12170,11 +12999,11 @@ struct Fts5PhraseIter {
**
** with $p set to a phrase equivalent to the phrase iPhrase of the
** current query is executed. Any column filter that applies to
-** phrase iPhrase of the current query is included in $p. For each
-** row visited, the callback function passed as the fourth argument
-** is invoked. The context and API objects passed to the callback
+** phrase iPhrase of the current query is included in $p. For each
+** row visited, the callback function passed as the fourth argument
+** is invoked. The context and API objects passed to the callback
** function may be used to access the properties of each matched row.
-** Invoking Api.xUserData() returns a copy of the pointer passed as
+** Invoking Api.xUserData() returns a copy of the pointer passed as
** the third argument to pUserData.
**
** If the callback function returns any value other than SQLITE_OK, the
@@ -12189,14 +13018,14 @@ struct Fts5PhraseIter {
**
** xSetAuxdata(pFts5, pAux, xDelete)
**
-** Save the pointer passed as the second argument as the extension functions
+** Save the pointer passed as the second argument as the extension function's
** "auxiliary data". The pointer may then be retrieved by the current or any
** future invocation of the same fts5 extension function made as part of
-** of the same MATCH query using the xGetAuxdata() API.
+** the same MATCH query using the xGetAuxdata() API.
**
** Each extension function is allocated a single auxiliary data slot for
-** each FTS query (MATCH expression). If the extension function is invoked
-** more than once for a single FTS query, then all invocations share a
+** each FTS query (MATCH expression). If the extension function is invoked
+** more than once for a single FTS query, then all invocations share a
** single auxiliary data context.
**
** If there is already an auxiliary data pointer when this function is
@@ -12207,7 +13036,7 @@ struct Fts5PhraseIter {
** The xDelete callback, if one is specified, is also invoked on the
** auxiliary data pointer after the FTS5 query has finished.
**
-** If an error (e.g. an OOM condition) occurs within this function, an
+** If an error (e.g. an OOM condition) occurs within this function,
** the auxiliary data is set to NULL and an error code returned. If the
** xDelete parameter was not NULL, it is invoked on the auxiliary data
** pointer before returning.
@@ -12215,7 +13044,7 @@ struct Fts5PhraseIter {
**
** xGetAuxdata(pFts5, bClear)
**
-** Returns the current auxiliary data pointer for the fts5 extension
+** Returns the current auxiliary data pointer for the fts5 extension
** function. See the xSetAuxdata() method for details.
**
** If the bClear argument is non-zero, then the auxiliary data is cleared
@@ -12235,7 +13064,7 @@ struct Fts5PhraseIter {
** method, to iterate through all instances of a single query phrase within
** the current row. This is the same information as is accessible via the
** xInstCount/xInst APIs. While the xInstCount/xInst APIs are more convenient
-** to use, this API may be faster under some circumstances. To iterate
+** to use, this API may be faster under some circumstances. To iterate
** through instances of phrase iPhrase, use the following code:
**
** Fts5PhraseIter iter;
@@ -12253,8 +13082,8 @@ struct Fts5PhraseIter {
** xPhraseFirstColumn() and xPhraseNextColumn() as illustrated below).
**
** This API can be quite slow if used with an FTS5 table created with the
-** "detail=none" or "detail=column" option. If the FTS5 table is created
-** with either "detail=none" or "detail=column" and "content=" option
+** "detail=none" or "detail=column" option. If the FTS5 table is created
+** with either "detail=none" or "detail=column" and "content=" option
** (i.e. if it is a contentless table), then this API always iterates
** through an empty set (all calls to xPhraseFirst() set iCol to -1).
**
@@ -12278,16 +13107,16 @@ struct Fts5PhraseIter {
** }
**
** This API can be quite slow if used with an FTS5 table created with the
-** "detail=none" option. If the FTS5 table is created with either
-** "detail=none" "content=" option (i.e. if it is a contentless table),
-** then this API always iterates through an empty set (all calls to
+** "detail=none" option. If the FTS5 table is created with either
+** "detail=none" "content=" option (i.e. if it is a contentless table),
+** then this API always iterates through an empty set (all calls to
** xPhraseFirstColumn() set iCol to -1).
**
** The information accessed using this API and its companion
** xPhraseFirstColumn() may also be obtained using xPhraseFirst/xPhraseNext
** (or xInst/xInstCount). The chief advantage of this API is that it is
** significantly more efficient than those alternatives when used with
-** "detail=column" tables.
+** "detail=column" tables.
**
** xPhraseNextColumn()
** See xPhraseFirstColumn above.
@@ -12301,7 +13130,7 @@ struct Fts5ExtensionApi {
int (*xRowCount)(Fts5Context*, sqlite3_int64 *pnRow);
int (*xColumnTotalSize)(Fts5Context*, int iCol, sqlite3_int64 *pnToken);
- int (*xTokenize)(Fts5Context*,
+ int (*xTokenize)(Fts5Context*,
const char *pText, int nText, /* Text to tokenize */
void *pCtx, /* Context passed to xToken() */
int (*xToken)(void*, int, const char*, int, int, int) /* Callback */
@@ -12330,15 +13159,15 @@ struct Fts5ExtensionApi {
void (*xPhraseNextColumn)(Fts5Context*, Fts5PhraseIter*, int *piCol);
};
-/*
+/*
** CUSTOM AUXILIARY FUNCTIONS
*************************************************************************/
/*************************************************************************
** CUSTOM TOKENIZERS
**
-** Applications may also register custom tokenizer types. A tokenizer
-** is registered by providing fts5 with a populated instance of the
+** Applications may also register custom tokenizer types. A tokenizer
+** is registered by providing fts5 with a populated instance of the
** following structure. All structure methods must be defined, setting
** any member of the fts5_tokenizer struct to NULL leads to undefined
** behaviour. The structure methods are expected to function as follows:
@@ -12349,16 +13178,16 @@ struct Fts5ExtensionApi {
**
** The first argument passed to this function is a copy of the (void*)
** pointer provided by the application when the fts5_tokenizer object
-** was registered with FTS5 (the third argument to xCreateTokenizer()).
+** was registered with FTS5 (the third argument to xCreateTokenizer()).
** The second and third arguments are an array of nul-terminated strings
** containing the tokenizer arguments, if any, specified following the
** tokenizer name as part of the CREATE VIRTUAL TABLE statement used
** to create the FTS5 table.
**
-** The final argument is an output variable. If successful, (*ppOut)
+** The final argument is an output variable. If successful, (*ppOut)
** should be set to point to the new tokenizer handle and SQLITE_OK
** returned. If an error occurs, some value other than SQLITE_OK should
-** be returned. In this case, fts5 assumes that the final value of *ppOut
+** be returned. In this case, fts5 assumes that the final value of *ppOut
** is undefined.
**
** xDelete:
@@ -12367,7 +13196,7 @@ struct Fts5ExtensionApi {
** be invoked exactly once for each successful call to xCreate().
**
** xTokenize:
-** This function is expected to tokenize the nText byte string indicated
+** This function is expected to tokenize the nText byte string indicated
** by argument pText. pText may or may not be nul-terminated. The first
** argument passed to this function is a pointer to an Fts5Tokenizer object
** returned by an earlier call to xCreate().
@@ -12381,8 +13210,8 @@ struct Fts5ExtensionApi {
** determine the set of tokens to add to (or delete from) the
** FTS index.
**
-** - FTS5_TOKENIZE_QUERY - A MATCH query is being executed
-** against the FTS index. The tokenizer is being called to tokenize
+**
- FTS5_TOKENIZE_QUERY - A MATCH query is being executed
+** against the FTS index. The tokenizer is being called to tokenize
** a bareword or quoted string specified as part of the query.
**
**
- (FTS5_TOKENIZE_QUERY | FTS5_TOKENIZE_PREFIX) - Same as
@@ -12390,10 +13219,10 @@ struct Fts5ExtensionApi {
** followed by a "*" character, indicating that the last token
** returned by the tokenizer will be treated as a token prefix.
**
-**
- FTS5_TOKENIZE_AUX - The tokenizer is being invoked to
+**
- FTS5_TOKENIZE_AUX - The tokenizer is being invoked to
** satisfy an fts5_api.xTokenize() request made by an auxiliary
** function. Or an fts5_api.xColumnSize() request made by the same
-** on a columnsize=0 database.
+** on a columnsize=0 database.
**
**
** For each token in the input string, the supplied callback xToken() must
@@ -12405,10 +13234,10 @@ struct Fts5ExtensionApi {
** which the token is derived within the input.
**
** The second argument passed to the xToken() callback ("tflags") should
-** normally be set to 0. The exception is if the tokenizer supports
+** normally be set to 0. The exception is if the tokenizer supports
** synonyms. In this case see the discussion below for details.
**
-** FTS5 assumes the xToken() callback is invoked for each token in the
+** FTS5 assumes the xToken() callback is invoked for each token in the
** order that they occur within the input text.
**
** If an xToken() callback returns any value other than SQLITE_OK, then
@@ -12422,7 +13251,7 @@ struct Fts5ExtensionApi {
** SYNONYM SUPPORT
**
** Custom tokenizers may also support synonyms. Consider a case in which a
-** user wishes to query for a phrase such as "first place". Using the
+** user wishes to query for a phrase such as "first place". Using the
** built-in tokenizers, the FTS5 query 'first + place' will match instances
** of "first place" within the document set, but not alternative forms
** such as "1st place". In some applications, it would be better to match
@@ -12431,8 +13260,8 @@ struct Fts5ExtensionApi {
**
** There are several ways to approach this in FTS5:
**
-**
- By mapping all synonyms to a single token. In this case, the
-** In the above example, this means that the tokenizer returns the
+**
- By mapping all synonyms to a single token. In this case, using
+** the above example, this means that the tokenizer returns the
** same token for inputs "first" and "1st". Say that token is in
** fact "first", so that when the user inserts the document "I won
** 1st place" entries are added to the index for tokens "i", "won",
@@ -12440,36 +13269,36 @@ struct Fts5ExtensionApi {
** the tokenizer substitutes "first" for "1st" and the query works
** as expected.
**
-**
- By adding multiple synonyms for a single term to the FTS index.
-** In this case, when tokenizing query text, the tokenizer may
-** provide multiple synonyms for a single term within the document.
-** FTS5 then queries the index for each synonym individually. For
-** example, faced with the query:
+**
- By querying the index for all synonyms of each query term
+** separately. In this case, when tokenizing query text, the
+** tokenizer may provide multiple synonyms for a single term
+** within the document. FTS5 then queries the index for each
+** synonym individually. For example, faced with the query:
**
**
** ... MATCH 'first place'
**
** the tokenizer offers both "1st" and "first" as synonyms for the
-** first token in the MATCH query and FTS5 effectively runs a query
+** first token in the MATCH query and FTS5 effectively runs a query
** similar to:
**
**
** ... MATCH '(first OR 1st) place'
**
** except that, for the purposes of auxiliary functions, the query
-** still appears to contain just two phrases - "(first OR 1st)"
+** still appears to contain just two phrases - "(first OR 1st)"
** being treated as a single phrase.
**
**
- By adding multiple synonyms for a single term to the FTS index.
** Using this method, when tokenizing document text, the tokenizer
-** provides multiple synonyms for each token. So that when a
+** provides multiple synonyms for each token. So that when a
** document such as "I won first place" is tokenized, entries are
** added to the FTS index for "i", "won", "first", "1st" and
** "place".
**
** This way, even if the tokenizer does not provide synonyms
-** when tokenizing query text (it should not - to do would be
-** inefficient), it doesn't matter if the user queries for
+** when tokenizing query text (it should not - to do so would be
+** inefficient), it doesn't matter if the user queries for
** 'first + place' or '1st + place', as there are entries in the
** FTS index corresponding to both forms of the first token.
**
@@ -12490,11 +13319,11 @@ struct Fts5ExtensionApi {
**
** It is an error to specify the FTS5_TOKEN_COLOCATED flag the first time
** xToken() is called. Multiple synonyms may be specified for a single token
-** by making multiple calls to xToken(FTS5_TOKEN_COLOCATED) in sequence.
+** by making multiple calls to xToken(FTS5_TOKEN_COLOCATED) in sequence.
** There is no limit to the number of synonyms that may be provided for a
** single token.
**
-** In many cases, method (1) above is the best approach. It does not add
+** In many cases, method (1) above is the best approach. It does not add
** extra data to the FTS index or require FTS5 to query for multiple terms,
** so it is efficient in terms of disk space and query speed. However, it
** does not support prefix queries very well. If, as suggested above, the
@@ -12506,18 +13335,18 @@ struct Fts5ExtensionApi {
** will not match documents that contain the token "1st" (as the tokenizer
** will probably not map "1s" to any prefix of "first").
**
-** For full prefix support, method (3) may be preferred. In this case,
+** For full prefix support, method (3) may be preferred. In this case,
** because the index contains entries for both "first" and "1st", prefix
** queries such as 'fi*' or '1s*' will match correctly. However, because
** extra entries are added to the FTS index, this method uses more space
** within the database.
**
** Method (2) offers a midpoint between (1) and (3). Using this method,
-** a query such as '1s*' will match documents that contain the literal
+** a query such as '1s*' will match documents that contain the literal
** token "1st", but not "first" (assuming the tokenizer is not able to
** provide synonyms for prefixes). However, a non-prefix query like '1st'
** will match against "1st" and "first". This method does not require
-** extra disk space, as no extra entries are added to the FTS index.
+** extra disk space, as no extra entries are added to the FTS index.
** On the other hand, it may require more CPU cycles to run MATCH queries,
** as separate queries of the FTS index are required for each synonym.
**
@@ -12531,10 +13360,10 @@ typedef struct fts5_tokenizer fts5_tokenizer;
struct fts5_tokenizer {
int (*xCreate)(void*, const char **azArg, int nArg, Fts5Tokenizer **ppOut);
void (*xDelete)(Fts5Tokenizer*);
- int (*xTokenize)(Fts5Tokenizer*,
+ int (*xTokenize)(Fts5Tokenizer*,
void *pCtx,
int flags, /* Mask of FTS5_TOKENIZE_* flags */
- const char *pText, int nText,
+ const char *pText, int nText,
int (*xToken)(
void *pCtx, /* Copy of 2nd argument to xTokenize() */
int tflags, /* Mask of FTS5_TOKEN_* flags */
@@ -12631,7 +13460,7 @@ struct fts5_api {
** May you share freely, never taking more than you give.
**
*************************************************************************
-**
+**
** This file defines various limits of what SQLite can process.
*/
@@ -12679,14 +13508,10 @@ struct fts5_api {
#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
-** expression.
-**
-** A value of 0 used to mean that the limit was not enforced.
-** But that is no longer true. The limit is now strictly enforced
-** at all times.
+** 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 means that there is no limit.
*/
#ifndef SQLITE_MAX_EXPR_DEPTH
# define SQLITE_MAX_EXPR_DEPTH 1000
@@ -12753,9 +13578,12 @@ struct fts5_api {
/*
** The maximum value of a ?nnn wildcard that the parser will accept.
+** If the value exceeds 32767 then extra space is required for the Expr
+** structure. But otherwise, we believe that the number can be as large
+** as a signed 32-bit integer can hold.
*/
#ifndef SQLITE_MAX_VARIABLE_NUMBER
-# define SQLITE_MAX_VARIABLE_NUMBER 999
+# define SQLITE_MAX_VARIABLE_NUMBER 32766
#endif
/* Maximum page size. The upper bound on this value is 65536. This a limit
@@ -12763,10 +13591,10 @@ struct fts5_api {
**
** Earlier versions of SQLite allowed the user to change this value at
** compile time. This is no longer permitted, on the grounds that it creates
-** a library that 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 limit will not be able to rollback
+** a library that 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 limit will not be able to rollback
** the aborted transaction. This could lead to database corruption.
*/
#ifdef SQLITE_MAX_PAGE_SIZE
@@ -12825,7 +13653,7 @@ struct fts5_api {
** 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
@@ -12844,6 +13672,22 @@ struct fts5_api {
#pragma warn -spa /* Suspicious pointer arithmetic */
#endif
+/*
+** WAL mode depends on atomic aligned 32-bit loads and stores in a few
+** places. The following macros try to make this explicit.
+*/
+#ifndef __has_extension
+# define __has_extension(x) 0 /* compatibility with non-clang compilers */
+#endif
+#if GCC_VERSION>=4007000 || \
+ (__has_extension(c_atomic) && __has_extension(c_atomic_store_n))
+# define AtomicLoad(PTR) __atomic_load_n((PTR),__ATOMIC_RELAXED)
+# define AtomicStore(PTR,VAL) __atomic_store_n((PTR),(VAL),__ATOMIC_RELAXED)
+#else
+# define AtomicLoad(PTR) (*(PTR))
+# define AtomicStore(PTR,VAL) (*(PTR) = (VAL))
+#endif
+
/*
** Include standard header files as necessary
*/
@@ -12870,15 +13714,15 @@ struct fts5_api {
** So we have to define the macros in different ways depending on the
** compiler.
*/
-#if defined(__PTRDIFF_TYPE__) /* This case should work for GCC */
+#if 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))
+#elif 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))
@@ -13104,6 +13948,26 @@ SQLITE_PRIVATE void sqlite3Coverage(int);
# define NEVER(X) (X)
#endif
+/*
+** The harmless(X) macro indicates that expression X is usually false
+** but can be true without causing any problems, but we don't know of
+** any way to cause X to be true.
+**
+** In debugging and testing builds, this macro will abort if X is ever
+** true. In this way, developers are alerted to a possible test case
+** that causes X to be true. If a harmless macro ever fails, that is
+** an opportunity to change the macro into a testcase() and add a new
+** test case to the test suite.
+**
+** For normal production builds, harmless(X) is a no-op, since it does
+** not matter whether expression X is true or false.
+*/
+#ifdef SQLITE_DEBUG
+# define harmless(X) assert(!(X));
+#else
+# define harmless(X)
+#endif
+
/*
** Some conditionals are optimizations only. In other words, if the
** conditionals are replaced with a constant 1 (true) or 0 (false) then
@@ -13223,7 +14087,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.
@@ -13233,12 +14097,12 @@ struct Hash {
unsigned int count; /* Number of entries in this table */
HashElem *first; /* The first element of the array */
struct _ht { /* the hash table */
- int count; /* Number of entries with this hash */
+ unsigned int count; /* Number of entries with this hash */
HashElem *chain; /* Pointer to first entry with this 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
@@ -13368,105 +14232,108 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash*);
#define TK_VIEW 79
#define TK_VIRTUAL 80
#define TK_WITH 81
-#define TK_CURRENT 82
-#define TK_FOLLOWING 83
-#define TK_PARTITION 84
-#define TK_PRECEDING 85
-#define TK_RANGE 86
-#define TK_UNBOUNDED 87
-#define TK_REINDEX 88
-#define TK_RENAME 89
-#define TK_CTIME_KW 90
-#define TK_ANY 91
-#define TK_BITAND 92
-#define TK_BITOR 93
-#define TK_LSHIFT 94
-#define TK_RSHIFT 95
-#define TK_PLUS 96
-#define TK_MINUS 97
-#define TK_STAR 98
-#define TK_SLASH 99
-#define TK_REM 100
-#define TK_CONCAT 101
-#define TK_COLLATE 102
-#define TK_BITNOT 103
-#define TK_ON 104
-#define TK_INDEXED 105
-#define TK_STRING 106
-#define TK_JOIN_KW 107
-#define TK_CONSTRAINT 108
-#define TK_DEFAULT 109
-#define TK_NULL 110
-#define TK_PRIMARY 111
-#define TK_UNIQUE 112
-#define TK_CHECK 113
-#define TK_REFERENCES 114
-#define TK_AUTOINCR 115
-#define TK_INSERT 116
-#define TK_DELETE 117
-#define TK_UPDATE 118
-#define TK_SET 119
-#define TK_DEFERRABLE 120
-#define TK_FOREIGN 121
-#define TK_DROP 122
-#define TK_UNION 123
-#define TK_ALL 124
-#define TK_EXCEPT 125
-#define TK_INTERSECT 126
-#define TK_SELECT 127
-#define TK_VALUES 128
-#define TK_DISTINCT 129
-#define TK_DOT 130
-#define TK_FROM 131
-#define TK_JOIN 132
-#define TK_USING 133
-#define TK_ORDER 134
-#define TK_GROUP 135
-#define TK_HAVING 136
-#define TK_LIMIT 137
-#define TK_WHERE 138
-#define TK_INTO 139
-#define TK_NOTHING 140
-#define TK_FLOAT 141
-#define TK_BLOB 142
-#define TK_INTEGER 143
-#define TK_VARIABLE 144
-#define TK_CASE 145
-#define TK_WHEN 146
-#define TK_THEN 147
-#define TK_ELSE 148
-#define TK_INDEX 149
-#define TK_ALTER 150
-#define TK_ADD 151
-#define TK_WINDOW 152
-#define TK_OVER 153
-#define TK_FILTER 154
-#define TK_TRUEFALSE 155
-#define TK_ISNOT 156
-#define TK_FUNCTION 157
-#define TK_COLUMN 158
-#define TK_AGG_FUNCTION 159
-#define TK_AGG_COLUMN 160
-#define TK_UMINUS 161
-#define TK_UPLUS 162
-#define TK_TRUTH 163
-#define TK_REGISTER 164
-#define TK_VECTOR 165
-#define TK_SELECT_COLUMN 166
-#define TK_IF_NULL_ROW 167
-#define TK_ASTERISK 168
-#define TK_SPAN 169
-#define TK_END_OF_FILE 170
-#define TK_UNCLOSED_STRING 171
-#define TK_SPACE 172
-#define TK_ILLEGAL 173
-
-/* The token codes above must all fit in 8 bits */
-#define TKFLG_MASK 0xff
-
-/* Flags that can be added to a token code when it is not
-** being stored in a u8: */
-#define TKFLG_DONTFOLD 0x100 /* Omit constant folding optimizations */
+#define TK_NULLS 82
+#define TK_FIRST 83
+#define TK_LAST 84
+#define TK_CURRENT 85
+#define TK_FOLLOWING 86
+#define TK_PARTITION 87
+#define TK_PRECEDING 88
+#define TK_RANGE 89
+#define TK_UNBOUNDED 90
+#define TK_EXCLUDE 91
+#define TK_GROUPS 92
+#define TK_OTHERS 93
+#define TK_TIES 94
+#define TK_GENERATED 95
+#define TK_ALWAYS 96
+#define TK_MATERIALIZED 97
+#define TK_REINDEX 98
+#define TK_RENAME 99
+#define TK_CTIME_KW 100
+#define TK_ANY 101
+#define TK_BITAND 102
+#define TK_BITOR 103
+#define TK_LSHIFT 104
+#define TK_RSHIFT 105
+#define TK_PLUS 106
+#define TK_MINUS 107
+#define TK_STAR 108
+#define TK_SLASH 109
+#define TK_REM 110
+#define TK_CONCAT 111
+#define TK_COLLATE 112
+#define TK_BITNOT 113
+#define TK_ON 114
+#define TK_INDEXED 115
+#define TK_STRING 116
+#define TK_JOIN_KW 117
+#define TK_CONSTRAINT 118
+#define TK_DEFAULT 119
+#define TK_NULL 120
+#define TK_PRIMARY 121
+#define TK_UNIQUE 122
+#define TK_CHECK 123
+#define TK_REFERENCES 124
+#define TK_AUTOINCR 125
+#define TK_INSERT 126
+#define TK_DELETE 127
+#define TK_UPDATE 128
+#define TK_SET 129
+#define TK_DEFERRABLE 130
+#define TK_FOREIGN 131
+#define TK_DROP 132
+#define TK_UNION 133
+#define TK_ALL 134
+#define TK_EXCEPT 135
+#define TK_INTERSECT 136
+#define TK_SELECT 137
+#define TK_VALUES 138
+#define TK_DISTINCT 139
+#define TK_DOT 140
+#define TK_FROM 141
+#define TK_JOIN 142
+#define TK_USING 143
+#define TK_ORDER 144
+#define TK_GROUP 145
+#define TK_HAVING 146
+#define TK_LIMIT 147
+#define TK_WHERE 148
+#define TK_RETURNING 149
+#define TK_INTO 150
+#define TK_NOTHING 151
+#define TK_FLOAT 152
+#define TK_BLOB 153
+#define TK_INTEGER 154
+#define TK_VARIABLE 155
+#define TK_CASE 156
+#define TK_WHEN 157
+#define TK_THEN 158
+#define TK_ELSE 159
+#define TK_INDEX 160
+#define TK_ALTER 161
+#define TK_ADD 162
+#define TK_WINDOW 163
+#define TK_OVER 164
+#define TK_FILTER 165
+#define TK_COLUMN 166
+#define TK_AGG_FUNCTION 167
+#define TK_AGG_COLUMN 168
+#define TK_TRUEFALSE 169
+#define TK_ISNOT 170
+#define TK_FUNCTION 171
+#define TK_UMINUS 172
+#define TK_UPLUS 173
+#define TK_TRUTH 174
+#define TK_REGISTER 175
+#define TK_VECTOR 176
+#define TK_SELECT_COLUMN 177
+#define TK_IF_NULL_ROW 178
+#define TK_ASTERISK 179
+#define TK_SPAN 180
+#define TK_ERROR 181
+#define TK_SPACE 182
+#define TK_ILLEGAL 183
/************** End of parse.h ***********************************************/
/************** Continuing where we left off in sqliteInt.h ******************/
@@ -13587,7 +14454,7 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash*);
#endif
/*
-** The compile-time options SQLITE_MMAP_READWRITE and
+** The compile-time options SQLITE_MMAP_READWRITE and
** SQLITE_ENABLE_BATCH_ATOMIC_WRITE are not compatible with one another.
** You must choose one or the other (or neither) but not both.
*/
@@ -13772,12 +14639,13 @@ typedef INT16_TYPE LogEst;
** at run-time.
*/
#ifndef SQLITE_BYTEORDER
-# if defined(i386) || defined(__i386__) || defined(_M_IX86) || \
- defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || \
- defined(_M_AMD64) || defined(_M_ARM) || defined(__x86) || \
- defined(__arm__) || defined(_M_ARM64)
+# if defined(i386) || defined(__i386__) || defined(_M_IX86) || \
+ defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || \
+ defined(_M_AMD64) || defined(_M_ARM) || defined(__x86) || \
+ defined(__ARMEL__) || defined(__AARCH64EL__) || defined(_M_ARM64)
# define SQLITE_BYTEORDER 1234
-# elif defined(sparc) || defined(__ppc__)
+# elif defined(sparc) || defined(__ppc__) || \
+ defined(__ARMEB__) || defined(__AARCH64EB__)
# define SQLITE_BYTEORDER 4321
# else
# define SQLITE_BYTEORDER 0
@@ -13808,6 +14676,7 @@ typedef INT16_TYPE LogEst;
** compilers.
*/
#define LARGEST_INT64 (0xffffffff|(((i64)0x7fffffff)<<32))
+#define LARGEST_UINT64 (0xffffffff|(((u64)0xffffffff)<<32))
#define SMALLEST_INT64 (((i64)-1) - LARGEST_INT64)
/*
@@ -13876,30 +14745,38 @@ typedef INT16_TYPE LogEst;
# define SQLITE_DEFAULT_MMAP_SIZE SQLITE_MAX_MMAP_SIZE
#endif
-/*
-** Only one of SQLITE_ENABLE_STAT3 or SQLITE_ENABLE_STAT4 can be defined.
-** Priority is given to SQLITE_ENABLE_STAT4. If either are defined, also
-** define SQLITE_ENABLE_STAT3_OR_STAT4
-*/
-#ifdef SQLITE_ENABLE_STAT4
-# undef SQLITE_ENABLE_STAT3
-# define SQLITE_ENABLE_STAT3_OR_STAT4 1
-#elif SQLITE_ENABLE_STAT3
-# define SQLITE_ENABLE_STAT3_OR_STAT4 1
-#elif SQLITE_ENABLE_STAT3_OR_STAT4
-# undef SQLITE_ENABLE_STAT3_OR_STAT4
-#endif
-
/*
** SELECTTRACE_ENABLED will be either 1 or 0 depending on whether or not
** the Select query generator tracing logic is turned on.
*/
-#if defined(SQLITE_ENABLE_SELECTTRACE)
+#if !defined(SQLITE_AMALGAMATION)
+SQLITE_PRIVATE u32 sqlite3SelectTrace;
+#endif
+#if defined(SQLITE_DEBUG) \
+ && (defined(SQLITE_TEST) || defined(SQLITE_ENABLE_SELECTTRACE))
# define SELECTTRACE_ENABLED 1
+# define SELECTTRACE(K,P,S,X) \
+ if(sqlite3SelectTrace&(K)) \
+ sqlite3DebugPrintf("%u/%d/%p: ",(S)->selId,(P)->addrExplain,(S)),\
+ sqlite3DebugPrintf X
#else
+# define SELECTTRACE(K,P,S,X)
# define SELECTTRACE_ENABLED 0
#endif
+/*
+** Macros for "wheretrace"
+*/
+SQLITE_PRIVATE u32 sqlite3WhereTrace;
+#if defined(SQLITE_DEBUG) \
+ && (defined(SQLITE_TEST) || defined(SQLITE_ENABLE_WHERETRACE))
+# define WHERETRACE(K,X) if(sqlite3WhereTrace&(K)) sqlite3DebugPrintf X
+# define WHERETRACE_ENABLED 1
+#else
+# define WHERETRACE(K,X)
+#endif
+
+
/*
** An instance of the following structure is used to store the busy-handler
** callback for a given sqlite handle.
@@ -13914,26 +14791,27 @@ struct BusyHandler {
int (*xBusyHandler)(void *,int); /* The busy callback */
void *pBusyArg; /* First arg to busy callback */
int nBusy; /* Incremented with each busy call */
- u8 bExtraFileArg; /* Include sqlite3_file as callback arg */
};
/*
-** Name of the master database table. The master database table
-** is a special table that holds the names and attributes of all
-** user tables and indices.
+** Name of table that holds the database schema.
*/
-#define MASTER_NAME "sqlite_master"
-#define TEMP_MASTER_NAME "sqlite_temp_master"
+#define DFLT_SCHEMA_TABLE "sqlite_master"
+#define DFLT_TEMP_SCHEMA_TABLE "sqlite_temp_master"
+#define ALT_SCHEMA_TABLE "sqlite_schema"
+#define ALT_TEMP_SCHEMA_TABLE "sqlite_temp_schema"
+
/*
-** The root-page of the master database table.
+** The root-page of the schema table.
*/
-#define MASTER_ROOT 1
+#define SCHEMA_ROOT 1
/*
-** The name of the schema table.
+** The name of the schema table. The name is different for TEMP.
*/
-#define SCHEMA_TABLE(x) ((!OMIT_TEMPDB)&&(x==1)?TEMP_MASTER_NAME:MASTER_NAME)
+#define SCHEMA_TABLE(x) \
+ ((!OMIT_TEMPDB)&&(x==1)?DFLT_TEMP_SCHEMA_TABLE:DFLT_SCHEMA_TABLE)
/*
** A convenience macro that returns the number of elements in
@@ -13954,7 +14832,7 @@ struct BusyHandler {
** pointer will work here as long as it is distinct from SQLITE_STATIC
** and SQLITE_TRANSIENT.
*/
-#define SQLITE_DYNAMIC ((sqlite3_destructor_type)sqlite3MallocSize)
+#define SQLITE_DYNAMIC ((sqlite3_destructor_type)sqlite3OomFault)
/*
** When SQLITE_OMIT_WSD is defined, it means that the target platform does
@@ -14010,7 +14888,10 @@ typedef struct AutoincInfo AutoincInfo;
typedef struct Bitvec Bitvec;
typedef struct CollSeq CollSeq;
typedef struct Column Column;
+typedef struct Cte Cte;
+typedef struct CteUse CteUse;
typedef struct Db Db;
+typedef struct DbFixer DbFixer;
typedef struct Schema Schema;
typedef struct Expr Expr;
typedef struct ExprList ExprList;
@@ -14028,14 +14909,17 @@ typedef struct LookasideSlot LookasideSlot;
typedef struct Module Module;
typedef struct NameContext NameContext;
typedef struct Parse Parse;
+typedef struct ParseCleanup ParseCleanup;
typedef struct PreUpdate PreUpdate;
typedef struct PrintfArguments PrintfArguments;
typedef struct RenameToken RenameToken;
+typedef struct Returning Returning;
typedef struct RowSet RowSet;
typedef struct Savepoint Savepoint;
typedef struct Select Select;
typedef struct SQLiteThread SQLiteThread;
typedef struct SelectDest SelectDest;
+typedef struct SrcItem SrcItem;
typedef struct SrcList SrcList;
typedef struct sqlite3_str StrAccum; /* Internal alias for sqlite3_str */
typedef struct Table Table;
@@ -14077,6 +14961,7 @@ typedef struct With With;
** A bit in a Bitmask
*/
#define MASKBIT(n) (((Bitmask)1)<<(n))
+#define MASKBIT64(n) (((u64)1)<<(n))
#define MASKBIT32(n) (((unsigned int)1)<<(n))
#define ALLBITS ((Bitmask)-1)
@@ -14093,6 +14978,253 @@ typedef int VList;
** "BusyHandler" typedefs. vdbe.h also requires a few of the opaque
** pointer types (i.e. FuncDef) defined above.
*/
+/************** Include pager.h in the middle of sqliteInt.h *****************/
+/************** Begin file pager.h *******************************************/
+/*
+** 2001 September 15
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+** This header file defines the interface that the sqlite page cache
+** subsystem. The page cache subsystem reads and writes a file a page
+** at a time and provides a journal for rollback.
+*/
+
+#ifndef SQLITE_PAGER_H
+#define SQLITE_PAGER_H
+
+/*
+** 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
+ #define SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT -1
+#endif
+
+/*
+** The type used to represent a page number. The first page in a file
+** is called page 1. 0 is used to represent "not a page".
+*/
+typedef u32 Pgno;
+
+/*
+** Each open file is managed by a separate instance of the "Pager" structure.
+*/
+typedef struct Pager Pager;
+
+/*
+** Handle type for pages.
+*/
+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
+** is devoted to storing a super-journal name - there are no more pages to
+** roll back. See comments for function writeSuperJournal() in pager.c
+** for details.
+*/
+#define PAGER_MJ_PGNO(x) ((Pgno)((PENDING_BYTE/((x)->pageSize))+1))
+
+/*
+** Allowed values for the flags parameter to sqlite3PagerOpen().
+**
+** NOTE: These values must match the corresponding BTREE_ values in btree.h.
+*/
+#define PAGER_OMIT_JOURNAL 0x0001 /* Do not use a rollback journal */
+#define PAGER_MEMORY 0x0002 /* In-memory database */
+
+/*
+** Valid values for the second argument to sqlite3PagerLockingMode().
+*/
+#define PAGER_LOCKINGMODE_QUERY -1
+#define PAGER_LOCKINGMODE_NORMAL 0
+#define PAGER_LOCKINGMODE_EXCLUSIVE 1
+
+/*
+** Numeric constants that encode the journalmode.
+**
+** The numeric values encoded here (other than PAGER_JOURNALMODE_QUERY)
+** are exposed in the API via the "PRAGMA journal_mode" command and
+** therefore cannot be changed without a compatibility break.
+*/
+#define PAGER_JOURNALMODE_QUERY (-1) /* Query the value of journalmode */
+#define PAGER_JOURNALMODE_DELETE 0 /* Commit by deleting journal file */
+#define PAGER_JOURNALMODE_PERSIST 1 /* Commit by zeroing journal header */
+#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 */
+
+/*
+** Flags that make up the mask passed to sqlite3PagerGet().
+*/
+#define PAGER_GET_NOCONTENT 0x01 /* Do not load data from disk */
+#define PAGER_GET_READONLY 0x02 /* Read-only page is acceptable */
+
+/*
+** Flags for sqlite3PagerSetFlags()
+**
+** Value constraints (enforced via assert()):
+** PAGER_FULLFSYNC == SQLITE_FullFSync
+** PAGER_CKPT_FULLFSYNC == SQLITE_CkptFullFSync
+** PAGER_CACHE_SPILL == SQLITE_CacheSpill
+*/
+#define PAGER_SYNCHRONOUS_OFF 0x01 /* PRAGMA synchronous=OFF */
+#define PAGER_SYNCHRONOUS_NORMAL 0x02 /* PRAGMA synchronous=NORMAL */
+#define PAGER_SYNCHRONOUS_FULL 0x03 /* PRAGMA synchronous=FULL */
+#define PAGER_SYNCHRONOUS_EXTRA 0x04 /* PRAGMA synchronous=EXTRA */
+#define PAGER_SYNCHRONOUS_MASK 0x07 /* Mask for four values above */
+#define PAGER_FULLFSYNC 0x08 /* PRAGMA fullfsync=ON */
+#define PAGER_CKPT_FULLFSYNC 0x10 /* PRAGMA checkpoint_fullfsync=ON */
+#define PAGER_CACHESPILL 0x20 /* PRAGMA cache_spill=ON */
+#define PAGER_FLAGS_MASK 0x38 /* All above except SYNCHRONOUS */
+
+/*
+** The remainder of this file contains the declarations of the functions
+** 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. */
+SQLITE_PRIVATE int sqlite3PagerOpen(
+ sqlite3_vfs*,
+ Pager **ppPager,
+ const char*,
+ int,
+ int,
+ int,
+ void(*)(DbPage*)
+);
+SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager, sqlite3*);
+SQLITE_PRIVATE int sqlite3PagerReadFileheader(Pager*, int, unsigned char*);
+
+/* Functions used to configure a Pager object. */
+SQLITE_PRIVATE void sqlite3PagerSetBusyHandler(Pager*, int(*)(void *), void *);
+SQLITE_PRIVATE int sqlite3PagerSetPagesize(Pager*, u32*, int);
+SQLITE_PRIVATE Pgno sqlite3PagerMaxPageCount(Pager*, Pgno);
+SQLITE_PRIVATE void sqlite3PagerSetCachesize(Pager*, int);
+SQLITE_PRIVATE int sqlite3PagerSetSpillsize(Pager*, int);
+SQLITE_PRIVATE void sqlite3PagerSetMmapLimit(Pager *, sqlite3_int64);
+SQLITE_PRIVATE void sqlite3PagerShrink(Pager*);
+SQLITE_PRIVATE void sqlite3PagerSetFlags(Pager*,unsigned);
+SQLITE_PRIVATE int sqlite3PagerLockingMode(Pager *, int);
+SQLITE_PRIVATE int sqlite3PagerSetJournalMode(Pager *, int);
+SQLITE_PRIVATE int sqlite3PagerGetJournalMode(Pager*);
+SQLITE_PRIVATE int sqlite3PagerOkToChangeJournalMode(Pager*);
+SQLITE_PRIVATE i64 sqlite3PagerJournalSizeLimit(Pager *, i64);
+SQLITE_PRIVATE sqlite3_backup **sqlite3PagerBackupPtr(Pager*);
+SQLITE_PRIVATE int sqlite3PagerFlush(Pager*);
+
+/* Functions used to obtain and release page references. */
+SQLITE_PRIVATE int sqlite3PagerGet(Pager *pPager, Pgno pgno, DbPage **ppPage, int clrFlag);
+SQLITE_PRIVATE DbPage *sqlite3PagerLookup(Pager *pPager, Pgno pgno);
+SQLITE_PRIVATE void sqlite3PagerRef(DbPage*);
+SQLITE_PRIVATE void sqlite3PagerUnref(DbPage*);
+SQLITE_PRIVATE void sqlite3PagerUnrefNotNull(DbPage*);
+SQLITE_PRIVATE void sqlite3PagerUnrefPageOne(DbPage*);
+
+/* Operations on page references. */
+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 *);
+
+/* Functions used to manage pager transactions and savepoints. */
+SQLITE_PRIVATE void sqlite3PagerPagecount(Pager*, int*);
+SQLITE_PRIVATE int sqlite3PagerBegin(Pager*, int exFlag, int);
+SQLITE_PRIVATE int sqlite3PagerCommitPhaseOne(Pager*,const char *zSuper, int);
+SQLITE_PRIVATE int sqlite3PagerExclusiveLock(Pager*);
+SQLITE_PRIVATE int sqlite3PagerSync(Pager *pPager, const char *zSuper);
+SQLITE_PRIVATE int sqlite3PagerCommitPhaseTwo(Pager*);
+SQLITE_PRIVATE int sqlite3PagerRollback(Pager*);
+SQLITE_PRIVATE int sqlite3PagerOpenSavepoint(Pager *pPager, int n);
+SQLITE_PRIVATE int sqlite3PagerSavepoint(Pager *pPager, int op, int iSavepoint);
+SQLITE_PRIVATE int sqlite3PagerSharedLock(Pager *pPager);
+
+#ifndef SQLITE_OMIT_WAL
+SQLITE_PRIVATE int sqlite3PagerCheckpoint(Pager *pPager, sqlite3*, int, int*, int*);
+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, sqlite3*);
+# ifdef SQLITE_ENABLE_SNAPSHOT
+SQLITE_PRIVATE int sqlite3PagerSnapshotGet(Pager*, sqlite3_snapshot **ppSnapshot);
+SQLITE_PRIVATE int sqlite3PagerSnapshotOpen(Pager*, sqlite3_snapshot *pSnapshot);
+SQLITE_PRIVATE int sqlite3PagerSnapshotRecover(Pager *pPager);
+SQLITE_PRIVATE int sqlite3PagerSnapshotCheck(Pager *pPager, sqlite3_snapshot *pSnapshot);
+SQLITE_PRIVATE void sqlite3PagerSnapshotUnlock(Pager *pPager);
+# endif
+#endif
+
+#if !defined(SQLITE_OMIT_WAL) && defined(SQLITE_ENABLE_SETLK_TIMEOUT)
+SQLITE_PRIVATE int sqlite3PagerWalWriteLock(Pager*, int);
+SQLITE_PRIVATE void sqlite3PagerWalDb(Pager*, sqlite3*);
+#else
+# define sqlite3PagerWalWriteLock(y,z) SQLITE_OK
+# define sqlite3PagerWalDb(x,y)
+#endif
+
+#ifdef SQLITE_DIRECT_OVERFLOW_READ
+SQLITE_PRIVATE int sqlite3PagerDirectReadOk(Pager *pPager, Pgno pgno);
+#endif
+
+#ifdef SQLITE_ENABLE_ZIPVFS
+SQLITE_PRIVATE int sqlite3PagerWalFramesize(Pager *pPager);
+#endif
+
+/* Functions used to query pager state and configuration. */
+SQLITE_PRIVATE u8 sqlite3PagerIsreadonly(Pager*);
+SQLITE_PRIVATE u32 sqlite3PagerDataVersion(Pager*);
+#ifdef SQLITE_DEBUG
+SQLITE_PRIVATE int sqlite3PagerRefcount(Pager*);
+#endif
+SQLITE_PRIVATE int sqlite3PagerMemUsed(Pager*);
+SQLITE_PRIVATE const char *sqlite3PagerFilename(const Pager*, int);
+SQLITE_PRIVATE sqlite3_vfs *sqlite3PagerVfs(Pager*);
+SQLITE_PRIVATE sqlite3_file *sqlite3PagerFile(Pager*);
+SQLITE_PRIVATE sqlite3_file *sqlite3PagerJrnlFile(Pager*);
+SQLITE_PRIVATE const char *sqlite3PagerJournalname(Pager*);
+SQLITE_PRIVATE void *sqlite3PagerTempSpace(Pager*);
+SQLITE_PRIVATE int sqlite3PagerIsMemdb(Pager*);
+SQLITE_PRIVATE void sqlite3PagerCacheStat(Pager *, int, int, int *);
+SQLITE_PRIVATE void sqlite3PagerClearCache(Pager*);
+SQLITE_PRIVATE int sqlite3SectorSize(sqlite3_file *);
+
+/* Functions used to truncate the database file. */
+SQLITE_PRIVATE void sqlite3PagerTruncateImage(Pager*,Pgno);
+
+SQLITE_PRIVATE void sqlite3PagerRekey(DbPage*, Pgno, u16);
+
+/* Functions to support testing and debugging. */
+#if !defined(NDEBUG) || defined(SQLITE_TEST)
+SQLITE_PRIVATE Pgno sqlite3PagerPagenumber(DbPage*);
+SQLITE_PRIVATE int sqlite3PagerIswriteable(DbPage*);
+#endif
+#ifdef SQLITE_TEST
+SQLITE_PRIVATE int *sqlite3PagerStats(Pager*);
+SQLITE_PRIVATE void sqlite3PagerRefdump(Pager*);
+ void disable_simulated_io_errors(void);
+ void enable_simulated_io_errors(void);
+#else
+# define disable_simulated_io_errors()
+# define enable_simulated_io_errors()
+#endif
+
+#endif /* SQLITE_PAGER_H */
+
+/************** End of pager.h ***********************************************/
+/************** Continuing where we left off in sqliteInt.h ******************/
/************** Include btree.h in the middle of sqliteInt.h *****************/
/************** Begin file btree.h *******************************************/
/*
@@ -14168,30 +15300,38 @@ SQLITE_PRIVATE int sqlite3BtreeSetMmapLimit(Btree*,sqlite3_int64);
SQLITE_PRIVATE int sqlite3BtreeSetPagerFlags(Btree*,unsigned);
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 Pgno sqlite3BtreeMaxPageCount(Btree*,Pgno);
+SQLITE_PRIVATE Pgno sqlite3BtreeLastPage(Btree*);
SQLITE_PRIVATE int sqlite3BtreeSecureDelete(Btree*,int);
-SQLITE_PRIVATE int sqlite3BtreeGetOptimalReserve(Btree*);
+SQLITE_PRIVATE int sqlite3BtreeGetRequestedReserve(Btree*);
SQLITE_PRIVATE int sqlite3BtreeGetReserveNoMutex(Btree *p);
SQLITE_PRIVATE int sqlite3BtreeSetAutoVacuum(Btree *, int);
SQLITE_PRIVATE int sqlite3BtreeGetAutoVacuum(Btree *);
SQLITE_PRIVATE int sqlite3BtreeBeginTrans(Btree*,int,int*);
-SQLITE_PRIVATE int sqlite3BtreeCommitPhaseOne(Btree*, const char *zMaster);
+SQLITE_PRIVATE int sqlite3BtreeCommitPhaseOne(Btree*, const char*);
SQLITE_PRIVATE int sqlite3BtreeCommitPhaseTwo(Btree*, int);
SQLITE_PRIVATE int sqlite3BtreeCommit(Btree*);
SQLITE_PRIVATE int sqlite3BtreeRollback(Btree*,int,int);
SQLITE_PRIVATE int sqlite3BtreeBeginStmt(Btree*,int);
-SQLITE_PRIVATE int sqlite3BtreeCreateTable(Btree*, int*, int flags);
-SQLITE_PRIVATE int sqlite3BtreeIsInTrans(Btree*);
-SQLITE_PRIVATE int sqlite3BtreeIsInReadTrans(Btree*);
+SQLITE_PRIVATE int sqlite3BtreeCreateTable(Btree*, Pgno*, int flags);
+SQLITE_PRIVATE int sqlite3BtreeTxnState(Btree*);
SQLITE_PRIVATE int sqlite3BtreeIsInBackup(Btree*);
+
SQLITE_PRIVATE void *sqlite3BtreeSchema(Btree *, int, void(*)(void *));
SQLITE_PRIVATE int sqlite3BtreeSchemaLocked(Btree *pBtree);
#ifndef SQLITE_OMIT_SHARED_CACHE
SQLITE_PRIVATE int sqlite3BtreeLockTable(Btree *pBtree, int iTab, u8 isWriteLock);
#endif
+
+/* Savepoints are named, nestable SQL transactions mostly implemented */
+/* in vdbe.c and pager.c See https://sqlite.org/lang_savepoint.html */
SQLITE_PRIVATE int sqlite3BtreeSavepoint(Btree *, int, int);
+/* "Checkpoint" only refers to WAL. See https://sqlite.org/wal.html#ckpt */
+#ifndef SQLITE_OMIT_WAL
+SQLITE_PRIVATE int sqlite3BtreeCheckpoint(Btree*, int, int *, int *);
+#endif
+
SQLITE_PRIVATE const char *sqlite3BtreeGetFilename(Btree *);
SQLITE_PRIVATE const char *sqlite3BtreeGetJournalname(Btree *);
SQLITE_PRIVATE int sqlite3BtreeCopyFile(Btree *, Btree *);
@@ -14223,7 +15363,7 @@ SQLITE_PRIVATE int sqlite3BtreeNewDb(Btree *p);
/*
** 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:
**
@@ -14294,7 +15434,7 @@ SQLITE_PRIVATE int sqlite3BtreeNewDb(Btree *p);
#define BTREE_BULKLOAD 0x00000001 /* Used to full index in sorted order */
#define BTREE_SEEK_EQ 0x00000002 /* EQ seeks only - no range seeks */
-/*
+/*
** Flags passed as the third argument to sqlite3BtreeCursor().
**
** For read-only cursors the wrFlag argument is always zero. For read-write
@@ -14322,7 +15462,7 @@ SQLITE_PRIVATE int sqlite3BtreeNewDb(Btree *p);
SQLITE_PRIVATE int sqlite3BtreeCursor(
Btree*, /* BTree containing table to open */
- int iTable, /* Index of root page */
+ Pgno iTable, /* Index of root page */
int wrFlag, /* 1 for writing. 0 for read-only */
struct KeyInfo*, /* First argument to compare function */
BtCursor *pCursor /* Space to write cursor structure */
@@ -14351,6 +15491,7 @@ SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor*, u8 flags);
#define BTREE_SAVEPOSITION 0x02 /* Leave cursor pointing at NEXT or PREV */
#define BTREE_AUXDELETE 0x04 /* not the primary delete operation */
#define BTREE_APPEND 0x08 /* Insert is likely an append */
+#define BTREE_PREFORMAT 0x80 /* Inserted data is a preformated cell */
/* An instance of the BtreePayload object describes the content of a single
** entry in either an index or table btree.
@@ -14362,7 +15503,7 @@ SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor*, u8 flags);
** The nMem field might be zero, indicating that no decomposition is available.
**
** Table btrees (used for rowid tables) contain an integer rowid used as
-** the key and passed in the nKey field. The pKey field is zero.
+** the key and passed in the nKey field. The pKey field is zero.
** pData,nData hold the content of the new entry. nZero extra zero bytes
** are appended to the end of the content when constructing the entry.
** The aMem,nMem fields are uninitialized for table btrees.
@@ -14381,7 +15522,7 @@ SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor*, u8 flags);
**
** This object is used to pass information into sqlite3BtreeInsert(). The
** same information used to be passed as five separate parameters. But placing
-** the information into this object helps to keep the interface more
+** the information into this object helps to keep the interface more
** organized and understandable, and it also helps the resulting code to
** run a little faster by using fewer registers for parameter passing.
*/
@@ -14398,22 +15539,22 @@ struct BtreePayload {
SQLITE_PRIVATE int sqlite3BtreeInsert(BtCursor*, const BtreePayload *pPayload,
int flags, int seekResult);
SQLITE_PRIVATE int sqlite3BtreeFirst(BtCursor*, int *pRes);
-#ifndef SQLITE_OMIT_WINDOWFUNC
-SQLITE_PRIVATE void sqlite3BtreeSkipNext(BtCursor*);
-#endif
SQLITE_PRIVATE int sqlite3BtreeLast(BtCursor*, int *pRes);
SQLITE_PRIVATE int sqlite3BtreeNext(BtCursor*, int flags);
SQLITE_PRIVATE int sqlite3BtreeEof(BtCursor*);
SQLITE_PRIVATE int sqlite3BtreePrevious(BtCursor*, int flags);
SQLITE_PRIVATE i64 sqlite3BtreeIntegerKey(BtCursor*);
+SQLITE_PRIVATE void sqlite3BtreeCursorPin(BtCursor*);
+SQLITE_PRIVATE void sqlite3BtreeCursorUnpin(BtCursor*);
#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC
SQLITE_PRIVATE i64 sqlite3BtreeOffset(BtCursor*);
#endif
SQLITE_PRIVATE int sqlite3BtreePayload(BtCursor*, u32 offset, u32 amt, void*);
SQLITE_PRIVATE const void *sqlite3BtreePayloadFetch(BtCursor*, u32 *pAmt);
SQLITE_PRIVATE u32 sqlite3BtreePayloadSize(BtCursor*);
+SQLITE_PRIVATE sqlite3_int64 sqlite3BtreeMaxRecordSize(BtCursor*);
-SQLITE_PRIVATE char *sqlite3BtreeIntegrityCheck(Btree*, int *aRoot, int nRoot, int, int*);
+SQLITE_PRIVATE char *sqlite3BtreeIntegrityCheck(sqlite3*,Btree*,Pgno*aRoot,int nRoot,int,int*);
SQLITE_PRIVATE struct Pager *sqlite3BtreePager(Btree*);
SQLITE_PRIVATE i64 sqlite3BtreeRowCountEst(BtCursor*);
@@ -14428,14 +15569,18 @@ SQLITE_PRIVATE int sqlite3BtreeCursorHasHint(BtCursor*, unsigned int mask);
SQLITE_PRIVATE int sqlite3BtreeIsReadonly(Btree *pBt);
SQLITE_PRIVATE int sqlite3HeaderSizeBtree(void);
+#ifdef SQLITE_DEBUG
+SQLITE_PRIVATE sqlite3_uint64 sqlite3BtreeSeekCount(Btree*);
+#else
+# define sqlite3BtreeSeekCount(X) 0
+#endif
+
#ifndef NDEBUG
SQLITE_PRIVATE int sqlite3BtreeCursorIsValid(BtCursor*);
#endif
SQLITE_PRIVATE int sqlite3BtreeCursorIsValidNN(BtCursor*);
-#ifndef SQLITE_OMIT_BTREECOUNT
-SQLITE_PRIVATE int sqlite3BtreeCount(BtCursor *, i64 *);
-#endif
+SQLITE_PRIVATE int sqlite3BtreeCount(sqlite3*, BtCursor*, i64*);
#ifdef SQLITE_TEST
SQLITE_PRIVATE int sqlite3BtreeCursorInfo(BtCursor*, int*, int);
@@ -14446,6 +15591,8 @@ SQLITE_PRIVATE void sqlite3BtreeCursorList(Btree*);
SQLITE_PRIVATE int sqlite3BtreeCheckpoint(Btree*, int, int *, int *);
#endif
+SQLITE_PRIVATE int sqlite3BtreeTransferRow(BtCursor*, BtCursor*, i64);
+
/*
** If we are not using shared cache, then there is no need to
** use mutexes to access the BtShared structures. So make the
@@ -14458,7 +15605,7 @@ SQLITE_PRIVATE int sqlite3BtreeSharable(Btree*);
SQLITE_PRIVATE void sqlite3BtreeEnterCursor(BtCursor*);
SQLITE_PRIVATE int sqlite3BtreeConnectionCount(Btree*);
#else
-# define sqlite3BtreeEnter(X)
+# define sqlite3BtreeEnter(X)
# define sqlite3BtreeEnterAll(X)
# define sqlite3BtreeSharable(X) 0
# define sqlite3BtreeEnterCursor(X)
@@ -14552,7 +15699,7 @@ struct VdbeOp {
Mem *pMem; /* Used when p4type is P4_MEM */
VTable *pVtab; /* Used when p4type is P4_VTAB */
KeyInfo *pKeyInfo; /* Used when p4type is P4_KEYINFO */
- int *ai; /* Used when p4type is P4_INTARRAY */
+ u32 *ai; /* Used when p4type is P4_INTARRAY */
SubProgram *pProgram; /* Used when p4type is P4_SUBPROGRAM */
Table *pTab; /* Used when p4type is P4_TABLE */
#ifdef SQLITE_ENABLE_CURSOR_HINTS
@@ -14632,7 +15779,7 @@ typedef struct VdbeOpList VdbeOpList;
#define P5_ConstraintFK 4
/*
-** 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
@@ -14651,12 +15798,11 @@ typedef struct VdbeOpList VdbeOpList;
#endif
/*
-** The following macro converts a relative address in the p2 field
-** of a VdbeOp structure into a negative number so that
-** sqlite3VdbeAddOpList() knows that the address is relative. Calling
-** the macro again restores the address.
+** The following macro converts a label returned by sqlite3VdbeMakeLabel()
+** into an index into the Parse.aLabel[] array that contains the resolved
+** address of that label.
*/
-#define ADDR(X) (-1-(X))
+#define ADDR(X) (~(X))
/*
** The makefile scans the vdbe.c source file and creates the "opcodes.h"
@@ -14692,30 +15838,30 @@ typedef struct VdbeOpList VdbeOpList;
#define OP_SeekLE 23 /* jump, synopsis: key=r[P3@P4] */
#define OP_SeekGE 24 /* jump, synopsis: key=r[P3@P4] */
#define OP_SeekGT 25 /* jump, synopsis: key=r[P3@P4] */
-#define OP_IfNoHope 26 /* jump, synopsis: key=r[P3@P4] */
-#define OP_NoConflict 27 /* jump, synopsis: key=r[P3@P4] */
-#define OP_NotFound 28 /* jump, synopsis: key=r[P3@P4] */
-#define OP_Found 29 /* jump, synopsis: key=r[P3@P4] */
-#define OP_SeekRowid 30 /* jump, synopsis: intkey=r[P3] */
-#define OP_NotExists 31 /* jump, synopsis: intkey=r[P3] */
-#define OP_Last 32 /* jump */
-#define OP_IfSmaller 33 /* jump */
-#define OP_SorterSort 34 /* jump */
-#define OP_Sort 35 /* jump */
-#define OP_Rewind 36 /* jump */
-#define OP_IdxLE 37 /* jump, synopsis: key=r[P3@P4] */
-#define OP_IdxGT 38 /* jump, synopsis: key=r[P3@P4] */
-#define OP_IdxLT 39 /* jump, synopsis: key=r[P3@P4] */
-#define OP_IdxGE 40 /* jump, synopsis: key=r[P3@P4] */
-#define OP_RowSetRead 41 /* jump, synopsis: r[P3]=rowset(P1) */
-#define OP_RowSetTest 42 /* jump, synopsis: if r[P3] in rowset(P1) goto P2 */
+#define OP_IfNotOpen 26 /* jump, synopsis: if( !csr[P1] ) goto P2 */
+#define OP_IfNoHope 27 /* jump, synopsis: key=r[P3@P4] */
+#define OP_NoConflict 28 /* jump, synopsis: key=r[P3@P4] */
+#define OP_NotFound 29 /* jump, synopsis: key=r[P3@P4] */
+#define OP_Found 30 /* jump, synopsis: key=r[P3@P4] */
+#define OP_SeekRowid 31 /* jump, synopsis: intkey=r[P3] */
+#define OP_NotExists 32 /* jump, synopsis: intkey=r[P3] */
+#define OP_Last 33 /* jump */
+#define OP_IfSmaller 34 /* jump */
+#define OP_SorterSort 35 /* jump */
+#define OP_Sort 36 /* jump */
+#define OP_Rewind 37 /* jump */
+#define OP_IdxLE 38 /* jump, synopsis: key=r[P3@P4] */
+#define OP_IdxGT 39 /* jump, synopsis: key=r[P3@P4] */
+#define OP_IdxLT 40 /* jump, synopsis: key=r[P3@P4] */
+#define OP_IdxGE 41 /* jump, synopsis: key=r[P3@P4] */
+#define OP_RowSetRead 42 /* jump, synopsis: r[P3]=rowset(P1) */
#define OP_Or 43 /* same as TK_OR, synopsis: r[P3]=(r[P1] || r[P2]) */
#define OP_And 44 /* same as TK_AND, synopsis: r[P3]=(r[P1] && r[P2]) */
-#define OP_Program 45 /* jump */
-#define OP_FkIfZero 46 /* jump, synopsis: if fkctr[P1]==0 goto P2 */
-#define OP_IfPos 47 /* jump, synopsis: if r[P1]>0 then r[P1]-=P3, goto P2 */
-#define OP_IfNotZero 48 /* jump, synopsis: if r[P1]!=0 then r[P1]--, goto P2 */
-#define OP_DecrJumpZero 49 /* jump, synopsis: if (--r[P1])==0 goto P2 */
+#define OP_RowSetTest 45 /* jump, synopsis: if r[P3] in rowset(P1) goto P2 */
+#define OP_Program 46 /* jump */
+#define OP_FkIfZero 47 /* jump, synopsis: if fkctr[P1]==0 goto P2 */
+#define OP_IfPos 48 /* jump, synopsis: if r[P1]>0 then r[P1]-=P3, goto P2 */
+#define OP_IfNotZero 49 /* jump, synopsis: if r[P1]!=0 then r[P1]--, goto P2 */
#define OP_IsNull 50 /* jump, same as TK_ISNULL, synopsis: if r[P1]==NULL goto P2 */
#define OP_NotNull 51 /* jump, same as TK_NOTNULL, synopsis: if r[P1]!=NULL goto P2 */
#define OP_Ne 52 /* jump, same as TK_NE, synopsis: IF r[P3]!=r[P1] */
@@ -14724,29 +15870,29 @@ typedef struct VdbeOpList VdbeOpList;
#define OP_Le 55 /* jump, same as TK_LE, synopsis: IF r[P3]<=r[P1] */
#define OP_Lt 56 /* jump, same as TK_LT, synopsis: IF r[P3]=r[P1] */
-#define OP_ElseNotEq 58 /* jump, same as TK_ESCAPE */
-#define OP_IncrVacuum 59 /* jump */
-#define OP_VNext 60 /* jump */
-#define OP_Init 61 /* jump, synopsis: Start at P2 */
-#define OP_PureFunc0 62
-#define OP_Function0 63 /* synopsis: r[P3]=func(r[P2@P5]) */
-#define OP_PureFunc 64
-#define OP_Function 65 /* synopsis: r[P3]=func(r[P2@P5]) */
-#define OP_Return 66
-#define OP_EndCoroutine 67
-#define OP_HaltIfNull 68 /* synopsis: if r[P3]=null halt */
-#define OP_Halt 69
-#define OP_Integer 70 /* synopsis: r[P2]=P1 */
-#define OP_Int64 71 /* synopsis: r[P2]=P4 */
-#define OP_String 72 /* synopsis: r[P2]='P4' (len=P1) */
-#define OP_Null 73 /* synopsis: r[P2..P3]=NULL */
-#define OP_SoftNull 74 /* synopsis: r[P1]=NULL */
-#define OP_Blob 75 /* synopsis: r[P2]=P4 (len=P1) */
-#define OP_Variable 76 /* synopsis: r[P2]=parameter(P1,P4) */
-#define OP_Move 77 /* synopsis: r[P2@P3]=r[P1@P3] */
-#define OP_Copy 78 /* synopsis: r[P2@P3+1]=r[P1@P3+1] */
-#define OP_SCopy 79 /* synopsis: r[P2]=r[P1] */
-#define OP_IntCopy 80 /* synopsis: r[P2]=r[P1] */
+#define OP_ElseEq 58 /* jump, same as TK_ESCAPE */
+#define OP_DecrJumpZero 59 /* jump, synopsis: if (--r[P1])==0 goto P2 */
+#define OP_IncrVacuum 60 /* jump */
+#define OP_VNext 61 /* jump */
+#define OP_Init 62 /* jump, synopsis: Start at P2 */
+#define OP_PureFunc 63 /* synopsis: r[P3]=func(r[P2@NP]) */
+#define OP_Function 64 /* synopsis: r[P3]=func(r[P2@NP]) */
+#define OP_Return 65
+#define OP_EndCoroutine 66
+#define OP_HaltIfNull 67 /* synopsis: if r[P3]=null halt */
+#define OP_Halt 68
+#define OP_Integer 69 /* synopsis: r[P2]=P1 */
+#define OP_Int64 70 /* synopsis: r[P2]=P4 */
+#define OP_String 71 /* synopsis: r[P2]='P4' (len=P1) */
+#define OP_Null 72 /* synopsis: r[P2..P3]=NULL */
+#define OP_SoftNull 73 /* synopsis: r[P1]=NULL */
+#define OP_Blob 74 /* synopsis: r[P2]=P4 (len=P1) */
+#define OP_Variable 75 /* synopsis: r[P2]=parameter(P1,P4) */
+#define OP_Move 76 /* synopsis: r[P2@P3]=r[P1@P3] */
+#define OP_Copy 77 /* synopsis: r[P2@P3+1]=r[P1@P3+1] */
+#define OP_SCopy 78 /* synopsis: r[P2]=r[P1] */
+#define OP_IntCopy 79 /* synopsis: r[P2]=r[P1] */
+#define OP_ChngCntRow 80 /* synopsis: output=r[P1] */
#define OP_ResultRow 81 /* synopsis: output=r[P1@P2] */
#define OP_CollSeq 82
#define OP_AddImm 83 /* synopsis: r[P1]=r[P1]+P2 */
@@ -14755,91 +15901,97 @@ typedef struct VdbeOpList VdbeOpList;
#define OP_Permutation 86
#define OP_Compare 87 /* synopsis: r[P1@P3] <-> r[P2@P3] */
#define OP_IsTrue 88 /* synopsis: r[P2] = coalesce(r[P1]==TRUE,P3) ^ P4 */
-#define OP_Offset 89 /* synopsis: r[P3] = sqlite_offset(P1) */
-#define OP_Column 90 /* synopsis: r[P3]=PX */
-#define OP_Affinity 91 /* synopsis: affinity(r[P1@P2]) */
-#define OP_BitAnd 92 /* same as TK_BITAND, synopsis: r[P3]=r[P1]&r[P2] */
-#define OP_BitOr 93 /* same as TK_BITOR, synopsis: r[P3]=r[P1]|r[P2] */
-#define OP_ShiftLeft 94 /* same as TK_LSHIFT, synopsis: r[P3]=r[P2]<>r[P1] */
-#define OP_Add 96 /* same as TK_PLUS, synopsis: r[P3]=r[P1]+r[P2] */
-#define OP_Subtract 97 /* same as TK_MINUS, synopsis: r[P3]=r[P2]-r[P1] */
-#define OP_Multiply 98 /* same as TK_STAR, synopsis: r[P3]=r[P1]*r[P2] */
-#define OP_Divide 99 /* same as TK_SLASH, synopsis: r[P3]=r[P2]/r[P1] */
-#define OP_Remainder 100 /* same as TK_REM, synopsis: r[P3]=r[P2]%r[P1] */
-#define OP_Concat 101 /* same as TK_CONCAT, synopsis: r[P3]=r[P2]+r[P1] */
-#define OP_MakeRecord 102 /* synopsis: r[P3]=mkrec(r[P1@P2]) */
-#define OP_BitNot 103 /* same as TK_BITNOT, synopsis: r[P2]= ~r[P1] */
-#define OP_Count 104 /* synopsis: r[P2]=count() */
-#define OP_ReadCookie 105
-#define OP_String8 106 /* same as TK_STRING, synopsis: r[P2]='P4' */
-#define OP_SetCookie 107
-#define OP_ReopenIdx 108 /* synopsis: root=P2 iDb=P3 */
-#define OP_OpenRead 109 /* synopsis: root=P2 iDb=P3 */
-#define OP_OpenWrite 110 /* synopsis: root=P2 iDb=P3 */
-#define OP_OpenDup 111
-#define OP_OpenAutoindex 112 /* synopsis: nColumn=P2 */
-#define OP_OpenEphemeral 113 /* synopsis: nColumn=P2 */
+#define OP_ZeroOrNull 89 /* synopsis: r[P2] = 0 OR NULL */
+#define OP_Offset 90 /* synopsis: r[P3] = sqlite_offset(P1) */
+#define OP_Column 91 /* synopsis: r[P3]=PX */
+#define OP_Affinity 92 /* synopsis: affinity(r[P1@P2]) */
+#define OP_MakeRecord 93 /* synopsis: r[P3]=mkrec(r[P1@P2]) */
+#define OP_Count 94 /* synopsis: r[P2]=count() */
+#define OP_ReadCookie 95
+#define OP_SetCookie 96
+#define OP_ReopenIdx 97 /* synopsis: root=P2 iDb=P3 */
+#define OP_OpenRead 98 /* synopsis: root=P2 iDb=P3 */
+#define OP_OpenWrite 99 /* synopsis: root=P2 iDb=P3 */
+#define OP_OpenDup 100
+#define OP_OpenAutoindex 101 /* synopsis: nColumn=P2 */
+#define OP_BitAnd 102 /* same as TK_BITAND, synopsis: r[P3]=r[P1]&r[P2] */
+#define OP_BitOr 103 /* same as TK_BITOR, synopsis: r[P3]=r[P1]|r[P2] */
+#define OP_ShiftLeft 104 /* same as TK_LSHIFT, synopsis: r[P3]=r[P2]<>r[P1] */
+#define OP_Add 106 /* same as TK_PLUS, synopsis: r[P3]=r[P1]+r[P2] */
+#define OP_Subtract 107 /* same as TK_MINUS, synopsis: r[P3]=r[P2]-r[P1] */
+#define OP_Multiply 108 /* same as TK_STAR, synopsis: r[P3]=r[P1]*r[P2] */
+#define OP_Divide 109 /* same as TK_SLASH, synopsis: r[P3]=r[P2]/r[P1] */
+#define OP_Remainder 110 /* same as TK_REM, synopsis: r[P3]=r[P2]%r[P1] */
+#define OP_Concat 111 /* same as TK_CONCAT, synopsis: r[P3]=r[P2]+r[P1] */
+#define OP_OpenEphemeral 112 /* synopsis: nColumn=P2 */
+#define OP_BitNot 113 /* same as TK_BITNOT, synopsis: r[P2]= ~r[P1] */
#define OP_SorterOpen 114
#define OP_SequenceTest 115 /* synopsis: if( cursor[P1].ctr++ ) pc = P2 */
-#define OP_OpenPseudo 116 /* synopsis: P3 columns in r[P2] */
-#define OP_Close 117
-#define OP_ColumnsUsed 118
-#define OP_SeekHit 119 /* synopsis: seekHit=P2 */
-#define OP_Sequence 120 /* synopsis: r[P2]=cursor[P1].ctr++ */
-#define OP_NewRowid 121 /* synopsis: r[P2]=rowid */
-#define OP_Insert 122 /* synopsis: intkey=r[P3] data=r[P2] */
-#define OP_InsertInt 123 /* synopsis: intkey=P3 data=r[P2] */
-#define OP_Delete 124
-#define OP_ResetCount 125
-#define OP_SorterCompare 126 /* synopsis: if key(P1)!=trim(r[P3],P4) goto P2 */
-#define OP_SorterData 127 /* synopsis: r[P2]=data */
-#define OP_RowData 128 /* synopsis: r[P2]=data */
-#define OP_Rowid 129 /* synopsis: r[P2]=rowid */
-#define OP_NullRow 130
-#define OP_SeekEnd 131
-#define OP_SorterInsert 132 /* synopsis: key=r[P2] */
-#define OP_IdxInsert 133 /* synopsis: key=r[P2] */
-#define OP_IdxDelete 134 /* synopsis: key=r[P2@P3] */
-#define OP_DeferredSeek 135 /* synopsis: Move P3 to P1.rowid if needed */
-#define OP_IdxRowid 136 /* synopsis: r[P2]=rowid */
-#define OP_Destroy 137
-#define OP_Clear 138
-#define OP_ResetSorter 139
-#define OP_CreateBtree 140 /* synopsis: r[P2]=root iDb=P1 flags=P3 */
-#define OP_Real 141 /* same as TK_FLOAT, synopsis: r[P2]=P4 */
-#define OP_SqlExec 142
-#define OP_ParseSchema 143
-#define OP_LoadAnalysis 144
-#define OP_DropTable 145
-#define OP_DropIndex 146
-#define OP_DropTrigger 147
-#define OP_IntegrityCk 148
-#define OP_RowSetAdd 149 /* synopsis: rowset(P1)=r[P2] */
-#define OP_Param 150
-#define OP_FkCounter 151 /* synopsis: fkctr[P1]+=P2 */
-#define OP_MemMax 152 /* synopsis: r[P1]=max(r[P1],r[P2]) */
-#define OP_OffsetLimit 153 /* synopsis: if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1) */
-#define OP_AggInverse 154 /* synopsis: accum=r[P3] inverse(r[P2@P5]) */
-#define OP_AggStep 155 /* synopsis: accum=r[P3] step(r[P2@P5]) */
-#define OP_AggStep1 156 /* synopsis: accum=r[P3] step(r[P2@P5]) */
-#define OP_AggValue 157 /* synopsis: r[P3]=value N=P2 */
-#define OP_AggFinal 158 /* synopsis: accum=r[P1] N=P2 */
-#define OP_Expire 159
-#define OP_TableLock 160 /* synopsis: iDb=P1 root=P2 write=P3 */
-#define OP_VBegin 161
-#define OP_VCreate 162
-#define OP_VDestroy 163
-#define OP_VOpen 164
-#define OP_VColumn 165 /* synopsis: r[P3]=vcolumn(P2) */
-#define OP_VRename 166
-#define OP_Pagecount 167
-#define OP_MaxPgcnt 168
-#define OP_Trace 169
-#define OP_CursorHint 170
-#define OP_Noop 171
-#define OP_Explain 172
-#define OP_Abortable 173
+#define OP_String8 116 /* same as TK_STRING, synopsis: r[P2]='P4' */
+#define OP_OpenPseudo 117 /* synopsis: P3 columns in r[P2] */
+#define OP_Close 118
+#define OP_ColumnsUsed 119
+#define OP_SeekScan 120 /* synopsis: Scan-ahead up to P1 rows */
+#define OP_SeekHit 121 /* synopsis: set P2<=seekHit<=P3 */
+#define OP_Sequence 122 /* synopsis: r[P2]=cursor[P1].ctr++ */
+#define OP_NewRowid 123 /* synopsis: r[P2]=rowid */
+#define OP_Insert 124 /* synopsis: intkey=r[P3] data=r[P2] */
+#define OP_RowCell 125
+#define OP_Delete 126
+#define OP_ResetCount 127
+#define OP_SorterCompare 128 /* synopsis: if key(P1)!=trim(r[P3],P4) goto P2 */
+#define OP_SorterData 129 /* synopsis: r[P2]=data */
+#define OP_RowData 130 /* synopsis: r[P2]=data */
+#define OP_Rowid 131 /* synopsis: r[P2]=rowid */
+#define OP_NullRow 132
+#define OP_SeekEnd 133
+#define OP_IdxInsert 134 /* synopsis: key=r[P2] */
+#define OP_SorterInsert 135 /* synopsis: key=r[P2] */
+#define OP_IdxDelete 136 /* synopsis: key=r[P2@P3] */
+#define OP_DeferredSeek 137 /* synopsis: Move P3 to P1.rowid if needed */
+#define OP_IdxRowid 138 /* synopsis: r[P2]=rowid */
+#define OP_FinishSeek 139
+#define OP_Destroy 140
+#define OP_Clear 141
+#define OP_ResetSorter 142
+#define OP_CreateBtree 143 /* synopsis: r[P2]=root iDb=P1 flags=P3 */
+#define OP_SqlExec 144
+#define OP_ParseSchema 145
+#define OP_LoadAnalysis 146
+#define OP_DropTable 147
+#define OP_DropIndex 148
+#define OP_DropTrigger 149
+#define OP_IntegrityCk 150
+#define OP_RowSetAdd 151 /* synopsis: rowset(P1)=r[P2] */
+#define OP_Real 152 /* same as TK_FLOAT, synopsis: r[P2]=P4 */
+#define OP_Param 153
+#define OP_FkCounter 154 /* synopsis: fkctr[P1]+=P2 */
+#define OP_MemMax 155 /* synopsis: r[P1]=max(r[P1],r[P2]) */
+#define OP_OffsetLimit 156 /* synopsis: if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1) */
+#define OP_AggInverse 157 /* synopsis: accum=r[P3] inverse(r[P2@P5]) */
+#define OP_AggStep 158 /* synopsis: accum=r[P3] step(r[P2@P5]) */
+#define OP_AggStep1 159 /* synopsis: accum=r[P3] step(r[P2@P5]) */
+#define OP_AggValue 160 /* synopsis: r[P3]=value N=P2 */
+#define OP_AggFinal 161 /* synopsis: accum=r[P1] N=P2 */
+#define OP_Expire 162
+#define OP_CursorLock 163
+#define OP_CursorUnlock 164
+#define OP_TableLock 165 /* synopsis: iDb=P1 root=P2 write=P3 */
+#define OP_VBegin 166
+#define OP_VCreate 167
+#define OP_VDestroy 168
+#define OP_VOpen 169
+#define OP_VColumn 170 /* synopsis: r[P3]=vcolumn(P2) */
+#define OP_VRename 171
+#define OP_Pagecount 172
+#define OP_MaxPgcnt 173
+#define OP_Trace 174
+#define OP_CursorHint 175
+#define OP_ReleaseReg 176 /* synopsis: release r[P1@P2] mask P3 */
+#define OP_Noop 177
+#define OP_Explain 178
+#define OP_Abortable 179
/* Properties such as "out2" or "jump" that are specified in
** comments following the "case" for each opcode in the vdbe.c
@@ -14855,33 +16007,34 @@ typedef struct VdbeOpList VdbeOpList;
/* 0 */ 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x10,\
/* 8 */ 0x00, 0x01, 0x00, 0x01, 0x01, 0x01, 0x03, 0x03,\
/* 16 */ 0x01, 0x01, 0x03, 0x12, 0x03, 0x01, 0x09, 0x09,\
-/* 24 */ 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,\
-/* 32 */ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\
-/* 40 */ 0x01, 0x23, 0x0b, 0x26, 0x26, 0x01, 0x01, 0x03,\
+/* 24 */ 0x09, 0x09, 0x01, 0x09, 0x09, 0x09, 0x09, 0x09,\
+/* 32 */ 0x09, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\
+/* 40 */ 0x01, 0x01, 0x23, 0x26, 0x26, 0x0b, 0x01, 0x01,\
/* 48 */ 0x03, 0x03, 0x03, 0x03, 0x0b, 0x0b, 0x0b, 0x0b,\
-/* 56 */ 0x0b, 0x0b, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00,\
-/* 64 */ 0x00, 0x00, 0x02, 0x02, 0x08, 0x00, 0x10, 0x10,\
-/* 72 */ 0x10, 0x10, 0x00, 0x10, 0x10, 0x00, 0x00, 0x10,\
-/* 80 */ 0x10, 0x00, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00,\
-/* 88 */ 0x12, 0x20, 0x00, 0x00, 0x26, 0x26, 0x26, 0x26,\
-/* 96 */ 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x00, 0x12,\
-/* 104 */ 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,\
-/* 112 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
-/* 120 */ 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
-/* 128 */ 0x00, 0x10, 0x00, 0x00, 0x04, 0x04, 0x00, 0x00,\
-/* 136 */ 0x10, 0x10, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00,\
-/* 144 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x10, 0x00,\
-/* 152 */ 0x04, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
-/* 160 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,\
-/* 168 */ 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,}
+/* 56 */ 0x0b, 0x0b, 0x01, 0x03, 0x01, 0x01, 0x01, 0x00,\
+/* 64 */ 0x00, 0x02, 0x02, 0x08, 0x00, 0x10, 0x10, 0x10,\
+/* 72 */ 0x10, 0x00, 0x10, 0x10, 0x00, 0x00, 0x10, 0x10,\
+/* 80 */ 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00,\
+/* 88 */ 0x12, 0x1e, 0x20, 0x00, 0x00, 0x00, 0x10, 0x10,\
+/* 96 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x26,\
+/* 104 */ 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26,\
+/* 112 */ 0x00, 0x12, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,\
+/* 120 */ 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00,\
+/* 128 */ 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x04, 0x04,\
+/* 136 */ 0x00, 0x00, 0x10, 0x00, 0x10, 0x00, 0x00, 0x10,\
+/* 144 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06,\
+/* 152 */ 0x10, 0x10, 0x00, 0x04, 0x1a, 0x00, 0x00, 0x00,\
+/* 160 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
+/* 168 */ 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00,\
+/* 176 */ 0x00, 0x00, 0x00, 0x00,}
-/* The sqlite3P2Values() routine is able to run faster if it knows
+/* The resolve3P2Values() routine is able to run faster if it knows
** the value of the largest JUMP opcode. The smaller the maximum
** JUMP opcode the better, so the mkopcodeh.tcl script that
** generated this include file strives to group all JUMP opcodes
** together near the beginning of the list.
*/
-#define SQLITE_MX_JUMP_OPCODE 61 /* Maximum JUMP opcode */
+#define SQLITE_MX_JUMP_OPCODE 62 /* Maximum JUMP opcode */
/************** End of opcodes.h *********************************************/
/************** Continuing where we left off in vdbe.h ***********************/
@@ -14897,6 +16050,7 @@ typedef struct VdbeOpList VdbeOpList;
** for a description of what each of these routines does.
*/
SQLITE_PRIVATE Vdbe *sqlite3VdbeCreate(Parse*);
+SQLITE_PRIVATE Parse *sqlite3VdbeParser(Vdbe*);
SQLITE_PRIVATE int sqlite3VdbeAddOp0(Vdbe*,int);
SQLITE_PRIVATE int sqlite3VdbeAddOp1(Vdbe*,int,int);
SQLITE_PRIVATE int sqlite3VdbeAddOp2(Vdbe*,int,int,int);
@@ -14907,6 +16061,7 @@ SQLITE_PRIVATE int sqlite3VdbeAddOp3(Vdbe*,int,int,int,int);
SQLITE_PRIVATE int sqlite3VdbeAddOp4(Vdbe*,int,int,int,int,const char *zP4,int);
SQLITE_PRIVATE int sqlite3VdbeAddOp4Dup8(Vdbe*,int,int,int,int,const u8*,int);
SQLITE_PRIVATE int sqlite3VdbeAddOp4Int(Vdbe*,int,int,int,int,int);
+SQLITE_PRIVATE int sqlite3VdbeAddFunctionCall(Parse*,int,int,int,int,const FuncDef*,int);
SQLITE_PRIVATE void sqlite3VdbeEndCoroutine(Vdbe*,int);
#if defined(SQLITE_DEBUG) && !defined(SQLITE_TEST_REALLOC_STRESS)
SQLITE_PRIVATE void sqlite3VdbeVerifyNoMallocRequired(Vdbe *p, int N);
@@ -14932,22 +16087,34 @@ SQLITE_PRIVATE int sqlite3VdbeExplainParent(Parse*);
# define ExplainQueryPlan(P)
# define ExplainQueryPlanPop(P)
# define ExplainQueryPlanParent(P) 0
+# define sqlite3ExplainBreakpoint(A,B) /*no-op*/
#endif
-SQLITE_PRIVATE void sqlite3VdbeAddParseSchemaOp(Vdbe*,int,char*);
-SQLITE_PRIVATE void sqlite3VdbeChangeOpcode(Vdbe*, u32 addr, u8);
-SQLITE_PRIVATE void sqlite3VdbeChangeP1(Vdbe*, u32 addr, int P1);
-SQLITE_PRIVATE void sqlite3VdbeChangeP2(Vdbe*, u32 addr, int P2);
-SQLITE_PRIVATE void sqlite3VdbeChangeP3(Vdbe*, u32 addr, int P3);
+#if defined(SQLITE_DEBUG) && !defined(SQLITE_OMIT_EXPLAIN)
+SQLITE_PRIVATE void sqlite3ExplainBreakpoint(const char*,const char*);
+#else
+# define sqlite3ExplainBreakpoint(A,B) /*no-op*/
+#endif
+SQLITE_PRIVATE void sqlite3VdbeAddParseSchemaOp(Vdbe*, int, char*, u16);
+SQLITE_PRIVATE void sqlite3VdbeChangeOpcode(Vdbe*, int addr, u8);
+SQLITE_PRIVATE void sqlite3VdbeChangeP1(Vdbe*, int addr, int P1);
+SQLITE_PRIVATE void sqlite3VdbeChangeP2(Vdbe*, int addr, int P2);
+SQLITE_PRIVATE void sqlite3VdbeChangeP3(Vdbe*, int addr, int P3);
SQLITE_PRIVATE void sqlite3VdbeChangeP5(Vdbe*, u16 P5);
SQLITE_PRIVATE void sqlite3VdbeJumpHere(Vdbe*, int addr);
+SQLITE_PRIVATE void sqlite3VdbeJumpHereOrPopInst(Vdbe*, int addr);
SQLITE_PRIVATE int sqlite3VdbeChangeToNoop(Vdbe*, int addr);
SQLITE_PRIVATE int sqlite3VdbeDeletePriorOpcode(Vdbe*, u8 op);
+#ifdef SQLITE_DEBUG
+SQLITE_PRIVATE void sqlite3VdbeReleaseRegisters(Parse*,int addr, int n, u32 mask, int);
+#else
+# define sqlite3VdbeReleaseRegisters(P,A,N,M,F)
+#endif
SQLITE_PRIVATE void sqlite3VdbeChangeP4(Vdbe*, int addr, const char *zP4, int N);
SQLITE_PRIVATE void sqlite3VdbeAppendP4(Vdbe*, void *pP4, int p4type);
SQLITE_PRIVATE void sqlite3VdbeSetP4KeyInfo(Parse*, Index*);
SQLITE_PRIVATE void sqlite3VdbeUsesBtree(Vdbe*, int);
SQLITE_PRIVATE VdbeOp *sqlite3VdbeGetOp(Vdbe*, int);
-SQLITE_PRIVATE int sqlite3VdbeMakeLabel(Vdbe*);
+SQLITE_PRIVATE int sqlite3VdbeMakeLabel(Parse*);
SQLITE_PRIVATE void sqlite3VdbeRunOnlyOnce(Vdbe*);
SQLITE_PRIVATE void sqlite3VdbeReusable(Vdbe*);
SQLITE_PRIVATE void sqlite3VdbeDelete(Vdbe*);
@@ -14968,6 +16135,10 @@ SQLITE_PRIVATE void sqlite3VdbeCountChanges(Vdbe*);
SQLITE_PRIVATE sqlite3 *sqlite3VdbeDb(Vdbe*);
SQLITE_PRIVATE u8 sqlite3VdbePrepareFlags(Vdbe*);
SQLITE_PRIVATE void sqlite3VdbeSetSql(Vdbe*, const char *z, int n, u8);
+#ifdef SQLITE_ENABLE_NORMALIZE
+SQLITE_PRIVATE void sqlite3VdbeAddDblquoteStr(sqlite3*,Vdbe*,const char*);
+SQLITE_PRIVATE int sqlite3VdbeUsesDoubleQuotedString(Vdbe*,const char*);
+#endif
SQLITE_PRIVATE void sqlite3VdbeSwap(Vdbe*,Vdbe*);
SQLITE_PRIVATE VdbeOp *sqlite3VdbeTakeOpArray(Vdbe*, int*, int*);
SQLITE_PRIVATE sqlite3_value *sqlite3VdbeGetBoundValue(Vdbe*, int, u8);
@@ -14986,11 +16157,13 @@ SQLITE_PRIVATE UnpackedRecord *sqlite3VdbeAllocUnpackedRecord(KeyInfo*);
typedef int (*RecordCompare)(int,const void*,UnpackedRecord*);
SQLITE_PRIVATE RecordCompare sqlite3VdbeFindCompare(UnpackedRecord*);
-#ifndef SQLITE_OMIT_TRIGGER
SQLITE_PRIVATE void sqlite3VdbeLinkSubProgram(Vdbe *, SubProgram *);
-#endif
+SQLITE_PRIVATE int sqlite3VdbeHasSubProgram(Vdbe*);
SQLITE_PRIVATE int sqlite3NotPureFunc(sqlite3_context*);
+#ifdef SQLITE_ENABLE_BYTECODE_VTAB
+SQLITE_PRIVATE int sqlite3VdbeBytecodeVtabInit(sqlite3*);
+#endif
/* Use SQLITE_ENABLE_COMMENTS to enable generation of extra comments on
** each VDBE opcode.
@@ -15095,258 +16268,6 @@ SQLITE_PRIVATE void sqlite3VdbePrintOp(FILE*, int, VdbeOp*);
/************** End of vdbe.h ************************************************/
/************** Continuing where we left off in sqliteInt.h ******************/
-/************** Include pager.h in the middle of sqliteInt.h *****************/
-/************** Begin file pager.h *******************************************/
-/*
-** 2001 September 15
-**
-** The author disclaims copyright to this source code. In place of
-** a legal notice, here is a blessing:
-**
-** May you do good and not evil.
-** May you find forgiveness for yourself and forgive others.
-** May you share freely, never taking more than you give.
-**
-*************************************************************************
-** This header file defines the interface that the sqlite page cache
-** subsystem. The page cache subsystem reads and writes a file a page
-** at a time and provides a journal for rollback.
-*/
-
-#ifndef SQLITE_PAGER_H
-#define SQLITE_PAGER_H
-
-/*
-** 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
- #define SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT -1
-#endif
-
-/*
-** The type used to represent a page number. The first page in a file
-** is called page 1. 0 is used to represent "not a page".
-*/
-typedef u32 Pgno;
-
-/*
-** Each open file is managed by a separate instance of the "Pager" structure.
-*/
-typedef struct Pager Pager;
-
-/*
-** Handle type for pages.
-*/
-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
-** is devoted to storing a master journal name - there are no more pages to
-** roll back. See comments for function writeMasterJournal() in pager.c
-** for details.
-*/
-#define PAGER_MJ_PGNO(x) ((Pgno)((PENDING_BYTE/((x)->pageSize))+1))
-
-/*
-** Allowed values for the flags parameter to sqlite3PagerOpen().
-**
-** NOTE: These values must match the corresponding BTREE_ values in btree.h.
-*/
-#define PAGER_OMIT_JOURNAL 0x0001 /* Do not use a rollback journal */
-#define PAGER_MEMORY 0x0002 /* In-memory database */
-
-/*
-** Valid values for the second argument to sqlite3PagerLockingMode().
-*/
-#define PAGER_LOCKINGMODE_QUERY -1
-#define PAGER_LOCKINGMODE_NORMAL 0
-#define PAGER_LOCKINGMODE_EXCLUSIVE 1
-
-/*
-** Numeric constants that encode the journalmode.
-**
-** The numeric values encoded here (other than PAGER_JOURNALMODE_QUERY)
-** are exposed in the API via the "PRAGMA journal_mode" command and
-** therefore cannot be changed without a compatibility break.
-*/
-#define PAGER_JOURNALMODE_QUERY (-1) /* Query the value of journalmode */
-#define PAGER_JOURNALMODE_DELETE 0 /* Commit by deleting journal file */
-#define PAGER_JOURNALMODE_PERSIST 1 /* Commit by zeroing journal header */
-#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 */
-
-/*
-** Flags that make up the mask passed to sqlite3PagerGet().
-*/
-#define PAGER_GET_NOCONTENT 0x01 /* Do not load data from disk */
-#define PAGER_GET_READONLY 0x02 /* Read-only page is acceptable */
-
-/*
-** Flags for sqlite3PagerSetFlags()
-**
-** Value constraints (enforced via assert()):
-** PAGER_FULLFSYNC == SQLITE_FullFSync
-** PAGER_CKPT_FULLFSYNC == SQLITE_CkptFullFSync
-** PAGER_CACHE_SPILL == SQLITE_CacheSpill
-*/
-#define PAGER_SYNCHRONOUS_OFF 0x01 /* PRAGMA synchronous=OFF */
-#define PAGER_SYNCHRONOUS_NORMAL 0x02 /* PRAGMA synchronous=NORMAL */
-#define PAGER_SYNCHRONOUS_FULL 0x03 /* PRAGMA synchronous=FULL */
-#define PAGER_SYNCHRONOUS_EXTRA 0x04 /* PRAGMA synchronous=EXTRA */
-#define PAGER_SYNCHRONOUS_MASK 0x07 /* Mask for four values above */
-#define PAGER_FULLFSYNC 0x08 /* PRAGMA fullfsync=ON */
-#define PAGER_CKPT_FULLFSYNC 0x10 /* PRAGMA checkpoint_fullfsync=ON */
-#define PAGER_CACHESPILL 0x20 /* PRAGMA cache_spill=ON */
-#define PAGER_FLAGS_MASK 0x38 /* All above except SYNCHRONOUS */
-
-/*
-** The remainder of this file contains the declarations of the functions
-** 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. */
-SQLITE_PRIVATE int sqlite3PagerOpen(
- sqlite3_vfs*,
- Pager **ppPager,
- const char*,
- int,
- int,
- int,
- void(*)(DbPage*)
-);
-SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager, sqlite3*);
-SQLITE_PRIVATE int sqlite3PagerReadFileheader(Pager*, int, unsigned char*);
-
-/* Functions used to configure a Pager object. */
-SQLITE_PRIVATE void sqlite3PagerSetBusyHandler(Pager*, int(*)(void *), void *);
-SQLITE_PRIVATE int sqlite3PagerSetPagesize(Pager*, u32*, int);
-#ifdef SQLITE_HAS_CODEC
-SQLITE_PRIVATE void sqlite3PagerAlignReserve(Pager*,Pager*);
-#endif
-SQLITE_PRIVATE int sqlite3PagerMaxPageCount(Pager*, int);
-SQLITE_PRIVATE void sqlite3PagerSetCachesize(Pager*, int);
-SQLITE_PRIVATE int sqlite3PagerSetSpillsize(Pager*, int);
-SQLITE_PRIVATE void sqlite3PagerSetMmapLimit(Pager *, sqlite3_int64);
-SQLITE_PRIVATE void sqlite3PagerShrink(Pager*);
-SQLITE_PRIVATE void sqlite3PagerSetFlags(Pager*,unsigned);
-SQLITE_PRIVATE int sqlite3PagerLockingMode(Pager *, int);
-SQLITE_PRIVATE int sqlite3PagerSetJournalMode(Pager *, int);
-SQLITE_PRIVATE int sqlite3PagerGetJournalMode(Pager*);
-SQLITE_PRIVATE int sqlite3PagerOkToChangeJournalMode(Pager*);
-SQLITE_PRIVATE i64 sqlite3PagerJournalSizeLimit(Pager *, i64);
-SQLITE_PRIVATE sqlite3_backup **sqlite3PagerBackupPtr(Pager*);
-SQLITE_PRIVATE int sqlite3PagerFlush(Pager*);
-
-/* Functions used to obtain and release page references. */
-SQLITE_PRIVATE int sqlite3PagerGet(Pager *pPager, Pgno pgno, DbPage **ppPage, int clrFlag);
-SQLITE_PRIVATE DbPage *sqlite3PagerLookup(Pager *pPager, Pgno pgno);
-SQLITE_PRIVATE void sqlite3PagerRef(DbPage*);
-SQLITE_PRIVATE void sqlite3PagerUnref(DbPage*);
-SQLITE_PRIVATE void sqlite3PagerUnrefNotNull(DbPage*);
-SQLITE_PRIVATE void sqlite3PagerUnrefPageOne(DbPage*);
-
-/* Operations on page references. */
-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 *);
-
-/* Functions used to manage pager transactions and savepoints. */
-SQLITE_PRIVATE void sqlite3PagerPagecount(Pager*, int*);
-SQLITE_PRIVATE int sqlite3PagerBegin(Pager*, int exFlag, int);
-SQLITE_PRIVATE int sqlite3PagerCommitPhaseOne(Pager*,const char *zMaster, int);
-SQLITE_PRIVATE int sqlite3PagerExclusiveLock(Pager*);
-SQLITE_PRIVATE int sqlite3PagerSync(Pager *pPager, const char *zMaster);
-SQLITE_PRIVATE int sqlite3PagerCommitPhaseTwo(Pager*);
-SQLITE_PRIVATE int sqlite3PagerRollback(Pager*);
-SQLITE_PRIVATE int sqlite3PagerOpenSavepoint(Pager *pPager, int n);
-SQLITE_PRIVATE int sqlite3PagerSavepoint(Pager *pPager, int op, int iSavepoint);
-SQLITE_PRIVATE int sqlite3PagerSharedLock(Pager *pPager);
-
-#ifndef SQLITE_OMIT_WAL
-SQLITE_PRIVATE int sqlite3PagerCheckpoint(Pager *pPager, sqlite3*, int, int*, int*);
-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, sqlite3*);
-# ifdef SQLITE_DIRECT_OVERFLOW_READ
-SQLITE_PRIVATE int sqlite3PagerUseWal(Pager *pPager, Pgno);
-# endif
-# ifdef SQLITE_ENABLE_SNAPSHOT
-SQLITE_PRIVATE int sqlite3PagerSnapshotGet(Pager *pPager, sqlite3_snapshot **ppSnapshot);
-SQLITE_PRIVATE int sqlite3PagerSnapshotOpen(Pager *pPager, sqlite3_snapshot *pSnapshot);
-SQLITE_PRIVATE int sqlite3PagerSnapshotRecover(Pager *pPager);
-SQLITE_PRIVATE int sqlite3PagerSnapshotCheck(Pager *pPager, sqlite3_snapshot *pSnapshot);
-SQLITE_PRIVATE void sqlite3PagerSnapshotUnlock(Pager *pPager);
-# endif
-#else
-# define sqlite3PagerUseWal(x,y) 0
-#endif
-
-#ifdef SQLITE_ENABLE_ZIPVFS
-SQLITE_PRIVATE int sqlite3PagerWalFramesize(Pager *pPager);
-#endif
-
-/* Functions used to query pager state and configuration. */
-SQLITE_PRIVATE u8 sqlite3PagerIsreadonly(Pager*);
-SQLITE_PRIVATE u32 sqlite3PagerDataVersion(Pager*);
-#ifdef SQLITE_DEBUG
-SQLITE_PRIVATE int sqlite3PagerRefcount(Pager*);
-#endif
-SQLITE_PRIVATE int sqlite3PagerMemUsed(Pager*);
-SQLITE_PRIVATE const char *sqlite3PagerFilename(Pager*, int);
-SQLITE_PRIVATE sqlite3_vfs *sqlite3PagerVfs(Pager*);
-SQLITE_PRIVATE sqlite3_file *sqlite3PagerFile(Pager*);
-SQLITE_PRIVATE sqlite3_file *sqlite3PagerJrnlFile(Pager*);
-SQLITE_PRIVATE const char *sqlite3PagerJournalname(Pager*);
-SQLITE_PRIVATE void *sqlite3PagerTempSpace(Pager*);
-SQLITE_PRIVATE int sqlite3PagerIsMemdb(Pager*);
-SQLITE_PRIVATE void sqlite3PagerCacheStat(Pager *, int, int, int *);
-SQLITE_PRIVATE void sqlite3PagerClearCache(Pager*);
-SQLITE_PRIVATE int sqlite3SectorSize(sqlite3_file *);
-#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
-SQLITE_PRIVATE void sqlite3PagerResetLockTimeout(Pager *pPager);
-#else
-# define sqlite3PagerResetLockTimeout(X)
-#endif
-
-/* Functions used to truncate the database file. */
-SQLITE_PRIVATE void sqlite3PagerTruncateImage(Pager*,Pgno);
-
-SQLITE_PRIVATE void sqlite3PagerRekey(DbPage*, Pgno, u16);
-
-#if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_WAL)
-SQLITE_PRIVATE void *sqlite3PagerCodec(DbPage *);
-#endif
-
-/* Functions to support testing and debugging. */
-#if !defined(NDEBUG) || defined(SQLITE_TEST)
-SQLITE_PRIVATE Pgno sqlite3PagerPagenumber(DbPage*);
-SQLITE_PRIVATE int sqlite3PagerIswriteable(DbPage*);
-#endif
-#ifdef SQLITE_TEST
-SQLITE_PRIVATE int *sqlite3PagerStats(Pager*);
-SQLITE_PRIVATE void sqlite3PagerRefdump(Pager*);
- void disable_simulated_io_errors(void);
- void enable_simulated_io_errors(void);
-#else
-# define disable_simulated_io_errors()
-# define enable_simulated_io_errors()
-#endif
-
-#endif /* SQLITE_PAGER_H */
-
-/************** End of pager.h ***********************************************/
-/************** Continuing where we left off in sqliteInt.h ******************/
/************** Include pcache.h in the middle of sqliteInt.h ****************/
/************** Begin file pcache.h ******************************************/
/*
@@ -15361,7 +16282,7 @@ SQLITE_PRIVATE void sqlite3PagerRefdump(Pager*);
**
*************************************************************************
** This header file defines the interface that the sqlite page cache
-** subsystem.
+** subsystem.
*/
#ifndef _PCACHE_H_
@@ -15387,7 +16308,7 @@ struct PgHdr {
u16 flags; /* PGHDR flags defined below */
/**********************************************************************
- ** Elements above, except pCache, are public. All that follow are
+ ** Elements above, except pCache, are public. All that follow are
** private to pcache.c and should not be accessed by other modules.
** pCache is grouped with the public elements for efficiency.
*/
@@ -15440,7 +16361,7 @@ SQLITE_PRIVATE int sqlite3PcacheSetPageSize(PCache *, int);
SQLITE_PRIVATE int sqlite3PcacheSize(void);
/* One release per successful fetch. Page is pinned until released.
-** Reference counted.
+** Reference counted.
*/
SQLITE_PRIVATE sqlite3_pcache_page *sqlite3PcacheFetch(PCache*, Pgno, int createFlag);
SQLITE_PRIVATE int sqlite3PcacheFetchStress(PCache*, Pgno, sqlite3_pcache_page**);
@@ -15484,7 +16405,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 *));
@@ -15534,6 +16455,10 @@ SQLITE_PRIVATE int sqlite3HeaderSizePcache1(void);
/* Number of dirty pages as a percentage of the configured cache size */
SQLITE_PRIVATE int sqlite3PCachePercentDirty(PCache*);
+#ifdef SQLITE_DIRECT_OVERFLOW_READ
+SQLITE_PRIVATE int sqlite3PCacheIsDirty(PCache *pCache);
+#endif
+
#endif /* _PCACHE_H_ */
/************** End of pcache.h **********************************************/
@@ -15636,6 +16561,12 @@ SQLITE_PRIVATE int sqlite3PCachePercentDirty(PCache*);
# define SET_FULLSYNC(x,y)
#endif
+/* Maximum pathname length. Note: FILENAME_MAX defined by stdio.h
+*/
+#ifndef SQLITE_MAX_PATHLEN
+# define SQLITE_MAX_PATHLEN FILENAME_MAX
+#endif
+
/*
** The default size of a disk sector
*/
@@ -15655,10 +16586,10 @@ SQLITE_PRIVATE int sqlite3PCachePercentDirty(PCache*);
** 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
@@ -15699,9 +16630,9 @@ SQLITE_PRIVATE int sqlite3PCachePercentDirty(PCache*);
** 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
@@ -15720,7 +16651,7 @@ SQLITE_PRIVATE int sqlite3PCachePercentDirty(PCache*);
** 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 possibility of having
@@ -15736,7 +16667,7 @@ SQLITE_PRIVATE int sqlite3PCachePercentDirty(PCache*);
** 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
@@ -15760,8 +16691,8 @@ SQLITE_PRIVATE int sqlite3PCachePercentDirty(PCache*);
*/
SQLITE_PRIVATE int sqlite3OsInit(void);
-/*
-** Functions for accessing sqlite3_file methods
+/*
+** Functions for accessing sqlite3_file methods
*/
SQLITE_PRIVATE void sqlite3OsClose(sqlite3_file*);
SQLITE_PRIVATE int sqlite3OsRead(sqlite3_file*, void*, int amt, i64 offset);
@@ -15787,8 +16718,8 @@ SQLITE_PRIVATE int sqlite3OsFetch(sqlite3_file *id, i64, int, void **);
SQLITE_PRIVATE int sqlite3OsUnfetch(sqlite3_file *, i64, void *);
-/*
-** 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);
@@ -15806,7 +16737,7 @@ SQLITE_PRIVATE int sqlite3OsGetLastError(sqlite3_vfs*);
SQLITE_PRIVATE int sqlite3OsCurrentTimeInt64(sqlite3_vfs *, sqlite3_int64*);
/*
-** 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*);
@@ -15876,9 +16807,9 @@ SQLITE_PRIVATE void sqlite3OsCloseFree(sqlite3_file *);
*/
#define sqlite3_mutex_alloc(X) ((sqlite3_mutex*)8)
#define sqlite3_mutex_free(X)
-#define sqlite3_mutex_enter(X)
+#define sqlite3_mutex_enter(X)
#define sqlite3_mutex_try(X) SQLITE_OK
-#define sqlite3_mutex_leave(X)
+#define sqlite3_mutex_leave(X)
#define sqlite3_mutex_held(X) ((void)(X),1)
#define sqlite3_mutex_notheld(X) ((void)(X),1)
#define sqlite3MutexAlloc(X) ((sqlite3_mutex*)8)
@@ -15887,6 +16818,7 @@ SQLITE_PRIVATE void sqlite3OsCloseFree(sqlite3_file *);
#define MUTEX_LOGIC(X)
#else
#define MUTEX_LOGIC(X) X
+SQLITE_API int sqlite3_mutex_held(sqlite3_mutex*);
#endif /* defined(SQLITE_MUTEX_OMIT) */
/************** End of mutex.h ***********************************************/
@@ -15990,7 +16922,6 @@ struct Schema {
*/
#define DB_SchemaLoaded 0x0001 /* The schema has been loaded */
#define DB_UnresetViews 0x0002 /* Some views have defined column names */
-#define DB_Empty 0x0004 /* The file is empty (length 0 bytes) */
#define DB_ResetWanted 0x0008 /* Reset the schema when nSchemaLock==0 */
/*
@@ -16018,15 +16949,47 @@ struct Schema {
** is shared by multiple database connections. Therefore, while parsing
** schema information, the Lookaside.bEnabled flag is cleared so that
** lookaside allocations are not used to construct the schema objects.
+**
+** New lookaside allocations are only allowed if bDisable==0. When
+** bDisable is greater than zero, sz is set to zero which effectively
+** disables lookaside without adding a new test for the bDisable flag
+** in a performance-critical path. sz should be set by to szTrue whenever
+** bDisable changes back to zero.
+**
+** Lookaside buffers are initially held on the pInit list. As they are
+** used and freed, they are added back to the pFree list. New allocations
+** come off of pFree first, then pInit as a fallback. This dual-list
+** allows use to compute a high-water mark - the maximum number of allocations
+** outstanding at any point in the past - by subtracting the number of
+** allocations on the pInit list from the total number of allocations.
+**
+** Enhancement on 2019-12-12: Two-size-lookaside
+** The default lookaside configuration is 100 slots of 1200 bytes each.
+** The larger slot sizes are important for performance, but they waste
+** a lot of space, as most lookaside allocations are less than 128 bytes.
+** The two-size-lookaside enhancement breaks up the lookaside allocation
+** into two pools: One of 128-byte slots and the other of the default size
+** (1200-byte) slots. Allocations are filled from the small-pool first,
+** failing over to the full-size pool if that does not work. Thus more
+** lookaside slots are available while also using less memory.
+** This enhancement can be omitted by compiling with
+** SQLITE_OMIT_TWOSIZE_LOOKASIDE.
*/
struct Lookaside {
u32 bDisable; /* Only operate the lookaside when zero */
u16 sz; /* Size of each buffer in bytes */
+ u16 szTrue; /* True value of sz, even if disabled */
u8 bMalloced; /* True if pStart obtained from sqlite3_malloc() */
u32 nSlot; /* Number of lookaside slots allocated */
u32 anStat[3]; /* 0: hits. 1: size misses. 2: full misses */
LookasideSlot *pInit; /* List of buffers not previously used */
LookasideSlot *pFree; /* List of available buffers */
+#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE
+ LookasideSlot *pSmallInit; /* List of small buffers not prediously used */
+ LookasideSlot *pSmallFree; /* List of available small buffers */
+ void *pMiddle; /* First byte past end of full-size buffers and
+ ** the first byte of LOOKASIDE_SMALL buffers */
+#endif /* SQLITE_OMIT_TWOSIZE_LOOKASIDE */
void *pStart; /* First byte of available memory space */
void *pEnd; /* First byte past end of available space */
};
@@ -16034,17 +16997,30 @@ struct LookasideSlot {
LookasideSlot *pNext; /* Next buffer in the list of free buffers */
};
+#define DisableLookaside db->lookaside.bDisable++;db->lookaside.sz=0
+#define EnableLookaside db->lookaside.bDisable--;\
+ db->lookaside.sz=db->lookaside.bDisable?0:db->lookaside.szTrue
+
+/* Size of the smaller allocations in two-size lookside */
+#ifdef SQLITE_OMIT_TWOSIZE_LOOKASIDE
+# define LOOKASIDE_SMALL 0
+#else
+# define LOOKASIDE_SMALL 128
+#endif
+
/*
** A hash table for built-in function definitions. (Application-defined
** functions use a regular table table from hash.h.)
**
** Hash each FuncDef structure into one of the FuncDefHash.a[] slots.
-** Collisions are on the FuncDef.u.pHash chain.
+** Collisions are on the FuncDef.u.pHash chain. Use the SQLITE_FUNC_HASH()
+** macro to compute a hash on the function name.
*/
#define SQLITE_FUNC_HASH_SZ 23
struct FuncDefHash {
FuncDef *a[SQLITE_FUNC_HASH_SZ]; /* Hash table for functions */
};
+#define SQLITE_FUNC_HASH(C,L) (((C)+(L))%SQLITE_FUNC_HASH_SZ)
#ifdef SQLITE_USER_AUTHENTICATION
/*
@@ -16088,11 +17064,19 @@ SQLITE_PRIVATE void sqlite3CryptFunc(sqlite3_context*,int,sqlite3_value**);
/* This is an extra SQLITE_TRACE macro that indicates "legacy" tracing
** in the style of sqlite3_trace()
*/
-#define SQLITE_TRACE_LEGACY 0x80
+#define SQLITE_TRACE_LEGACY 0x40 /* Use the legacy xTrace */
+#define SQLITE_TRACE_XPROFILE 0x80 /* Use the legacy xProfile */
#else
-#define SQLITE_TRACE_LEGACY 0
+#define SQLITE_TRACE_LEGACY 0
+#define SQLITE_TRACE_XPROFILE 0
#endif /* SQLITE_OMIT_DEPRECATED */
+#define SQLITE_TRACE_NONLEGACY_MASK 0x0f /* Normal flags */
+/*
+** Maximum number of sqlite3.aDb[] entries. This is the number of attached
+** databases plus 2 for "main" and "temp".
+*/
+#define SQLITE_MAX_DB (SQLITE_MAX_ATTACHED+2)
/*
** Each database connection is an instance of the following structure.
@@ -16100,12 +17084,12 @@ SQLITE_PRIVATE void sqlite3CryptFunc(sqlite3_context*,int,sqlite3_value**);
struct sqlite3 {
sqlite3_vfs *pVfs; /* OS Interface */
struct Vdbe *pVdbe; /* List of active virtual machines */
- CollSeq *pDfltColl; /* The default collating sequence (BINARY) */
+ CollSeq *pDfltColl; /* BINARY collseq for the database encoding */
sqlite3_mutex *mutex; /* Connection mutex */
Db *aDb; /* All backends */
int nDb; /* Number of backends currently in use */
u32 mDbFlags; /* flags recording internal state */
- u32 flags; /* flags settable by pragmas. See below */
+ u64 flags; /* flags settable by pragmas. See below */
i64 lastRowid; /* ROWID of most recent insert (see above) */
i64 szMmap; /* Default mmap_size setting */
u32 nSchemaLock; /* Do not reset the schema when non-zero */
@@ -16113,7 +17097,7 @@ struct sqlite3 {
int errCode; /* Most recent error code (SQLITE_*) */
int errMask; /* & result codes with this before returning */
int iSysErrno; /* Errno value from last system error */
- u16 dbOptFlags; /* Flags to enable/disable optimizations */
+ u32 dbOptFlags; /* Flags to enable/disable optimizations */
u8 enc; /* Text encoding */
u8 autoCommit; /* The auto-commit flag. */
u8 temp_store; /* 1: file 2: memory 0: default */
@@ -16134,12 +17118,13 @@ struct sqlite3 {
int aLimit[SQLITE_N_LIMIT]; /* Limits */
int nMaxSorterMmap; /* Maximum size of regions mapped by sorter */
struct sqlite3InitInfo { /* Information used during initialization */
- int newTnum; /* Rootpage of table being initialized */
+ Pgno newTnum; /* Rootpage of table being initialized */
u8 iDb; /* Which db file is being initialized */
u8 busy; /* TRUE if currently initializing */
unsigned orphanTrigger : 1; /* Last statement is orphaned TEMP trigger */
unsigned imposterTable : 1; /* Building an imposter table */
unsigned reopenMemdb : 1; /* ATTACH is really a reopen using MemDB */
+ char **azInit; /* "type", "name", and "tbl_name" columns */
} init;
int nVdbeActive; /* Number of VDBEs currently running */
int nVdbeRead; /* Number of active VDBEs that read or write */
@@ -16148,16 +17133,22 @@ struct sqlite3 {
int nVDestroy; /* Number of active OP_VDestroy operations */
int nExtension; /* Number of loaded extensions */
void **aExtension; /* Array of shared library handles */
- int (*xTrace)(u32,void*,void*,void*); /* Trace function */
+ union {
+ void (*xLegacy)(void*,const char*); /* Legacy trace function */
+ int (*xV2)(u32,void*,void*,void*); /* V2 Trace function */
+ } trace;
void *pTraceArg; /* Argument to the trace function */
+#ifndef SQLITE_OMIT_DEPRECATED
void (*xProfile)(void*,const char*,u64); /* Profiling function */
void *pProfileArg; /* Argument to profile function */
+#endif
void *pCommitArg; /* Argument to xCommitCallback() */
int (*xCommitCallback)(void*); /* Invoked at every commit. */
void *pRollbackArg; /* Argument to xRollbackCallback() */
void (*xRollbackCallback)(void*); /* Invoked at every commit. */
void *pUpdateArg;
void (*xUpdateCallback)(void*,int, const char*,const char*,sqlite_int64);
+ Parse *pParse; /* Current parse */
#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
void *pPreUpdateArg; /* First argument to xPreUpdateCallback */
void (*xPreUpdateCallback)( /* Registered using sqlite3_preupdate_hook() */
@@ -16199,6 +17190,7 @@ struct sqlite3 {
BusyHandler busyHandler; /* Busy callback */
Db aDbStatic[2]; /* Static space for the 2 default backends */
Savepoint *pSavepoint; /* List of active savepoints */
+ int nAnalysisLimit; /* Number of index rows to ANALYZE */
int busyTimeout; /* Busy handler timeout, in msec */
int nSavepoint; /* Number of non-transaction savepoints */
int nStatement; /* Number of nested statement-transactions */
@@ -16206,7 +17198,7 @@ struct sqlite3 {
i64 nDeferredImmCons; /* Net deferred immediate constraints */
int *pnBytesFreed; /* If not NULL, increment this in DbFree() */
#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
- /* The following variables are all protected by the STATIC_MASTER
+ /* The following variables are all protected by the STATIC_MAIN
** 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
@@ -16233,6 +17225,13 @@ struct sqlite3 {
#define SCHEMA_ENC(db) ((db)->aDb[0].pSchema->enc)
#define ENC(db) ((db)->enc)
+/*
+** A u64 constant where the lower 32 bits are all zeros. Only the
+** upper 32 bits are included in the argument. Necessary because some
+** C-compilers still do not accept LL integer literals.
+*/
+#define HI(X) ((u64)(X)<<32)
+
/*
** Possible values for the sqlite3.flags.
**
@@ -16241,16 +17240,15 @@ struct sqlite3 {
** SQLITE_CkptFullFSync == PAGER_CKPT_FULLFSYNC
** SQLITE_CacheSpill == PAGER_CACHE_SPILL
*/
-#define SQLITE_WriteSchema 0x00000001 /* OK to update SQLITE_MASTER */
+#define SQLITE_WriteSchema 0x00000001 /* OK to update SQLITE_SCHEMA */
#define SQLITE_LegacyFileFmt 0x00000002 /* Create new databases in format 1 */
#define SQLITE_FullColNames 0x00000004 /* Show full column names on SELECT */
#define SQLITE_FullFSync 0x00000008 /* Use full fsync on the backend */
#define SQLITE_CkptFullFSync 0x00000010 /* Use full fsync for checkpoint */
#define SQLITE_CacheSpill 0x00000020 /* OK to spill pager cache */
#define SQLITE_ShortColNames 0x00000040 /* Show short columns names */
-#define SQLITE_CountRows 0x00000080 /* Count rows changed by INSERT, */
- /* DELETE, or UPDATE and return */
- /* the count using a callback. */
+#define SQLITE_TrustedSchema 0x00000080 /* Allow unsafe functions and
+ ** vtabs in the schema definition */
#define SQLITE_NullCallback 0x00000100 /* Invoke the callback once if the */
/* result set is empty */
#define SQLITE_IgnoreChecks 0x00000200 /* Do not enforce check constraints */
@@ -16271,14 +17269,23 @@ struct sqlite3 {
#define SQLITE_TriggerEQP 0x01000000 /* Show trigger EXPLAIN QUERY PLAN */
#define SQLITE_ResetDatabase 0x02000000 /* Reset the database */
#define SQLITE_LegacyAlter 0x04000000 /* Legacy ALTER TABLE behaviour */
+#define SQLITE_NoSchemaError 0x08000000 /* Do not report schema parse errors*/
+#define SQLITE_Defensive 0x10000000 /* Input SQL is likely hostile */
+#define SQLITE_DqsDDL 0x20000000 /* dbl-quoted strings allowed in DDL*/
+#define SQLITE_DqsDML 0x40000000 /* dbl-quoted strings allowed in DML*/
+#define SQLITE_EnableView 0x80000000 /* Enable the use of views */
+#define SQLITE_CountRows HI(0x00001) /* Count rows changed by INSERT, */
+ /* DELETE, or UPDATE and return */
+ /* the count using a callback. */
/* Flags used only if debugging */
#ifdef SQLITE_DEBUG
-#define SQLITE_SqlTrace 0x08000000 /* Debug print SQL as it executes */
-#define SQLITE_VdbeListing 0x10000000 /* Debug listings of VDBE programs */
-#define SQLITE_VdbeTrace 0x20000000 /* True to trace VDBE execution */
-#define SQLITE_VdbeAddopTrace 0x40000000 /* Trace sqlite3VdbeAddOp() calls */
-#define SQLITE_VdbeEQP 0x80000000 /* Debug EXPLAIN QUERY PLAN */
+#define SQLITE_SqlTrace HI(0x0100000) /* Debug print SQL as it executes */
+#define SQLITE_VdbeListing HI(0x0200000) /* Debug listings of VDBE progs */
+#define SQLITE_VdbeTrace HI(0x0400000) /* True to trace VDBE execution */
+#define SQLITE_VdbeAddopTrace HI(0x0800000) /* Trace sqlite3VdbeAddOp() calls */
+#define SQLITE_VdbeEQP HI(0x1000000) /* Debug EXPLAIN QUERY PLAN */
+#define SQLITE_ParserTrace HI(0x2000000) /* PRAGMA parser_trace=ON */
#endif
/*
@@ -16287,31 +17294,36 @@ struct sqlite3 {
#define DBFLAG_SchemaChange 0x0001 /* Uncommitted Hash table changes */
#define DBFLAG_PreferBuiltin 0x0002 /* Preference to built-in funcs */
#define DBFLAG_Vacuum 0x0004 /* Currently in a VACUUM */
-#define DBFLAG_SchemaKnownOk 0x0008 /* Schema is known to be valid */
+#define DBFLAG_VacuumInto 0x0008 /* Currently running VACUUM INTO */
+#define DBFLAG_SchemaKnownOk 0x0010 /* Schema is known to be valid */
+#define DBFLAG_InternalFunc 0x0020 /* Allow use of internal functions */
+#define DBFLAG_EncodingFixed 0x0040 /* No longer possible to change enc. */
/*
** Bits of the sqlite3.dbOptFlags field that are used by the
** sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS,...) interface to
** selectively disable various optimizations.
*/
-#define SQLITE_QueryFlattener 0x0001 /* Query flattening */
- /* 0x0002 available for reuse */
-#define SQLITE_GroupByOrder 0x0004 /* GROUPBY cover of ORDERBY */
-#define SQLITE_FactorOutConst 0x0008 /* Constant factoring */
-#define SQLITE_DistinctOpt 0x0010 /* DISTINCT using indexes */
-#define SQLITE_CoverIdxScan 0x0020 /* Covering index scans */
-#define SQLITE_OrderByIdxJoin 0x0040 /* ORDER BY of joins via index */
-#define SQLITE_Transitive 0x0080 /* Transitive constraints */
-#define SQLITE_OmitNoopJoin 0x0100 /* Omit unused tables in joins */
-#define SQLITE_CountOfView 0x0200 /* The count-of-view optimization */
-#define SQLITE_CursorHints 0x0400 /* Add OP_CursorHint opcodes */
-#define SQLITE_Stat34 0x0800 /* Use STAT3 or STAT4 data */
- /* TH3 expects the Stat34 ^^^^^^ value to be 0x0800. Don't change it */
-#define SQLITE_PushDown 0x1000 /* The push-down optimization */
-#define SQLITE_SimplifyJoin 0x2000 /* Convert LEFT JOIN to JOIN */
-#define SQLITE_SkipScan 0x4000 /* Skip-scans */
-#define SQLITE_PropagateConst 0x8000 /* The constant propagation opt */
-#define SQLITE_AllOpts 0xffff /* All optimizations */
+#define SQLITE_QueryFlattener 0x00000001 /* Query flattening */
+#define SQLITE_WindowFunc 0x00000002 /* Use xInverse for window functions */
+#define SQLITE_GroupByOrder 0x00000004 /* GROUPBY cover of ORDERBY */
+#define SQLITE_FactorOutConst 0x00000008 /* Constant factoring */
+#define SQLITE_DistinctOpt 0x00000010 /* DISTINCT using indexes */
+#define SQLITE_CoverIdxScan 0x00000020 /* Covering index scans */
+#define SQLITE_OrderByIdxJoin 0x00000040 /* ORDER BY of joins via index */
+#define SQLITE_Transitive 0x00000080 /* Transitive constraints */
+#define SQLITE_OmitNoopJoin 0x00000100 /* Omit unused tables in joins */
+#define SQLITE_CountOfView 0x00000200 /* The count-of-view optimization */
+#define SQLITE_CursorHints 0x00000400 /* Add OP_CursorHint opcodes */
+#define SQLITE_Stat4 0x00000800 /* Use STAT4 data */
+ /* TH3 expects this value ^^^^^^^^^^ to be 0x0000800. Don't change it */
+#define SQLITE_PushDown 0x00001000 /* The push-down optimization */
+#define SQLITE_SimplifyJoin 0x00002000 /* Convert LEFT JOIN to JOIN */
+#define SQLITE_SkipScan 0x00004000 /* Skip-scans */
+#define SQLITE_PropagateConst 0x00008000 /* The constant propagation opt */
+#define SQLITE_MinMaxOpt 0x00010000 /* The min/max optimization */
+#define SQLITE_SeekScan 0x00020000 /* The OP_SeekScan optimization */
+#define SQLITE_AllOpts 0xffffffff /* All optimizations */
/*
** Macros for testing whether or not optimizations are enabled or disabled.
@@ -16394,6 +17406,8 @@ struct FuncDestructor {
** SQLITE_FUNC_LENGTH == OPFLAG_LENGTHARG
** SQLITE_FUNC_TYPEOF == OPFLAG_TYPEOFARG
** SQLITE_FUNC_CONSTANT == SQLITE_DETERMINISTIC from the API
+** SQLITE_FUNC_DIRECT == SQLITE_DIRECTONLY from the API
+** SQLITE_FUNC_UNSAFE == SQLITE_INNOCUOUS
** SQLITE_FUNC_ENCMASK depends on SQLITE_UTF* macros in the API
*/
#define SQLITE_FUNC_ENCMASK 0x0003 /* SQLITE_UTF8, SQLITE_UTF16BE or UTF16LE */
@@ -16404,16 +17418,29 @@ struct FuncDestructor {
#define SQLITE_FUNC_LENGTH 0x0040 /* Built-in length() function */
#define SQLITE_FUNC_TYPEOF 0x0080 /* Built-in typeof() function */
#define SQLITE_FUNC_COUNT 0x0100 /* Built-in count(*) aggregate */
-#define SQLITE_FUNC_COALESCE 0x0200 /* Built-in coalesce() or ifnull() */
+/* 0x0200 -- available for reuse */
#define SQLITE_FUNC_UNLIKELY 0x0400 /* Built-in unlikely() function */
#define SQLITE_FUNC_CONSTANT 0x0800 /* Constant inputs give a constant output */
#define SQLITE_FUNC_MINMAX 0x1000 /* True for min() and max() aggregates */
#define SQLITE_FUNC_SLOCHNG 0x2000 /* "Slow Change". Value constant during a
** single query - might change over time */
-#define SQLITE_FUNC_AFFINITY 0x4000 /* Built-in affinity() function */
+#define SQLITE_FUNC_TEST 0x4000 /* Built-in testing functions */
#define SQLITE_FUNC_OFFSET 0x8000 /* Built-in sqlite_offset() function */
-#define SQLITE_FUNC_WINDOW 0x10000 /* Built-in window-only function */
-#define SQLITE_FUNC_WINDOW_SIZE 0x20000 /* Requires partition size as arg. */
+#define SQLITE_FUNC_WINDOW 0x00010000 /* Built-in window-only function */
+#define SQLITE_FUNC_INTERNAL 0x00040000 /* For use by NestedParse() only */
+#define SQLITE_FUNC_DIRECT 0x00080000 /* Not for use in TRIGGERs or VIEWs */
+#define SQLITE_FUNC_SUBTYPE 0x00100000 /* Result likely to have sub-type */
+#define SQLITE_FUNC_UNSAFE 0x00200000 /* Function has side effects */
+#define SQLITE_FUNC_INLINE 0x00400000 /* Functions implemented in-line */
+
+/* Identifier numbers for each in-line function */
+#define INLINEFUNC_coalesce 0
+#define INLINEFUNC_implies_nonnull_row 1
+#define INLINEFUNC_expr_implies_expr 2
+#define INLINEFUNC_expr_compare 3
+#define INLINEFUNC_affinity 4
+#define INLINEFUNC_iif 5
+#define INLINEFUNC_unlikely 99 /* Default case */
/*
** The following three macros, FUNCTION(), LIKEFUNC() and AGGREGATE() are
@@ -16429,6 +17456,22 @@ struct FuncDestructor {
** VFUNCTION(zName, nArg, iArg, bNC, xFunc)
** Like FUNCTION except it omits the SQLITE_FUNC_CONSTANT flag.
**
+** SFUNCTION(zName, nArg, iArg, bNC, xFunc)
+** Like FUNCTION except it omits the SQLITE_FUNC_CONSTANT flag and
+** adds the SQLITE_DIRECTONLY flag.
+**
+** INLINE_FUNC(zName, nArg, iFuncId, mFlags)
+** zName is the name of a function that is implemented by in-line
+** byte code rather than by the usual callbacks. The iFuncId
+** parameter determines the function id. The mFlags parameter is
+** optional SQLITE_FUNC_ flags for this function.
+**
+** TEST_FUNC(zName, nArg, iFuncId, mFlags)
+** zName is the name of a test-only function implemented by in-line
+** byte code rather than by the usual callbacks. The iFuncId
+** parameter determines the function id. The mFlags parameter is
+** optional SQLITE_FUNC_ flags for this function.
+**
** DFUNCTION(zName, nArg, iArg, bNC, xFunc)
** Like FUNCTION except it omits the SQLITE_FUNC_CONSTANT flag and
** adds the SQLITE_FUNC_SLOCHNG flag. Used for date & time functions
@@ -16436,10 +17479,13 @@ struct FuncDestructor {
** a single query. The iArg is ignored. The user-data is always set
** to a NULL pointer. The bNC parameter is not used.
**
+** MFUNCTION(zName, nArg, xPtr, xFunc)
+** For math-library functions. xPtr is an arbitrary pointer.
+**
** PURE_DATE(zName, nArg, iArg, bNC, xFunc)
** Used for "pure" date/time functions, this macro is like DFUNCTION
** except that it does set the SQLITE_FUNC_CONSTANT flags. iArg is
-** ignored and the user-data for these functions is set to an
+** ignored and the user-data for these functions is set to an
** arbitrary non-NULL pointer. The bNC parameter is not used.
**
** AGGREGATE(zName, nArg, iArg, bNC, xStep, xFinal)
@@ -16468,6 +17514,19 @@ struct FuncDestructor {
#define VFUNCTION(zName, nArg, iArg, bNC, xFunc) \
{nArg, SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \
SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, 0, #zName, {0} }
+#define SFUNCTION(zName, nArg, iArg, bNC, xFunc) \
+ {nArg, SQLITE_UTF8|SQLITE_DIRECTONLY|SQLITE_FUNC_UNSAFE, \
+ SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, 0, #zName, {0} }
+#define MFUNCTION(zName, nArg, xPtr, xFunc) \
+ {nArg, SQLITE_FUNC_CONSTANT|SQLITE_UTF8, \
+ xPtr, 0, xFunc, 0, 0, 0, #zName, {0} }
+#define INLINE_FUNC(zName, nArg, iArg, mFlags) \
+ {nArg, SQLITE_UTF8|SQLITE_FUNC_INLINE|SQLITE_FUNC_CONSTANT|(mFlags), \
+ SQLITE_INT_TO_PTR(iArg), 0, noopFunc, 0, 0, 0, #zName, {0} }
+#define TEST_FUNC(zName, nArg, iArg, mFlags) \
+ {nArg, SQLITE_UTF8|SQLITE_FUNC_INTERNAL|SQLITE_FUNC_TEST| \
+ SQLITE_FUNC_INLINE|SQLITE_FUNC_CONSTANT|(mFlags), \
+ SQLITE_INT_TO_PTR(iArg), 0, noopFunc, 0, 0, 0, #zName, {0} }
#define DFUNCTION(zName, nArg, iArg, bNC, xFunc) \
{nArg, SQLITE_FUNC_SLOCHNG|SQLITE_UTF8, \
0, 0, xFunc, 0, 0, 0, #zName, {0} }
@@ -16483,16 +17542,13 @@ struct FuncDestructor {
#define LIKEFUNC(zName, nArg, arg, flags) \
{nArg, SQLITE_FUNC_CONSTANT|SQLITE_UTF8|flags, \
(void *)arg, 0, likeFunc, 0, 0, 0, #zName, {0} }
-#define AGGREGATE(zName, nArg, arg, nc, xStep, xFinal, xValue) \
- {nArg, SQLITE_UTF8|(nc*SQLITE_FUNC_NEEDCOLL), \
- SQLITE_INT_TO_PTR(arg), 0, xStep,xFinal,xValue,0,#zName, {0}}
-#define AGGREGATE2(zName, nArg, arg, nc, xStep, xFinal, extraFlags) \
- {nArg, SQLITE_UTF8|(nc*SQLITE_FUNC_NEEDCOLL)|extraFlags, \
- SQLITE_INT_TO_PTR(arg), 0, xStep,xFinal,xFinal,0,#zName, {0}}
-
#define WAGGREGATE(zName, nArg, arg, nc, xStep, xFinal, xValue, xInverse, f) \
{nArg, SQLITE_UTF8|(nc*SQLITE_FUNC_NEEDCOLL)|f, \
SQLITE_INT_TO_PTR(arg), 0, xStep,xFinal,xValue,xInverse,#zName, {0}}
+#define INTERNAL_FUNCTION(zName, nArg, xFunc) \
+ {nArg, SQLITE_FUNC_INTERNAL|SQLITE_UTF8|SQLITE_FUNC_CONSTANT, \
+ 0, 0, xFunc, 0, 0, 0, #zName, {0} }
+
/*
** All current savepoints are stored in a linked list starting at
@@ -16524,32 +17580,58 @@ struct Savepoint {
struct Module {
const sqlite3_module *pModule; /* Callback pointers */
const char *zName; /* Name passed to create_module() */
+ int nRefModule; /* Number of pointers to this object */
void *pAux; /* pAux passed to create_module() */
void (*xDestroy)(void *); /* Module destructor function */
Table *pEpoTab; /* Eponymous table for this module */
};
/*
-** information about each column of an SQL table is held in an instance
-** of this structure.
+** Information about each column of an SQL table is held in an instance
+** of the Column structure, in the Table.aCol[] array.
+**
+** Definitions:
+**
+** "table column index" This is the index of the column in the
+** Table.aCol[] array, and also the index of
+** the column in the original CREATE TABLE stmt.
+**
+** "storage column index" This is the index of the column in the
+** record BLOB generated by the OP_MakeRecord
+** opcode. The storage column index is less than
+** or equal to the table column index. It is
+** equal if and only if there are no VIRTUAL
+** columns to the left.
*/
struct Column {
char *zName; /* Name of this column, \000, then the type */
- Expr *pDflt; /* Default value of this column */
+ Expr *pDflt; /* Default value or GENERATED ALWAYS AS value */
char *zColl; /* Collating sequence. If NULL, use the default */
u8 notNull; /* An OE_ code for handling a NOT NULL constraint */
char affinity; /* One of the SQLITE_AFF_... values */
u8 szEst; /* Estimated size of value in this column. sizeof(INT)==1 */
- u8 colFlags; /* Boolean properties. See COLFLAG_ defines below */
+ u8 hName; /* Column name hash for faster lookup */
+ u16 colFlags; /* Boolean properties. See COLFLAG_ defines below */
};
-/* Allowed values for Column.colFlags:
+/* Allowed values for Column.colFlags.
+**
+** Constraints:
+** TF_HasVirtual == COLFLAG_VIRTUAL
+** TF_HasStored == COLFLAG_STORED
+** TF_HasHidden == COLFLAG_HIDDEN
*/
-#define COLFLAG_PRIMKEY 0x0001 /* Column is part of the primary key */
-#define COLFLAG_HIDDEN 0x0002 /* A hidden column in a virtual table */
-#define COLFLAG_HASTYPE 0x0004 /* Type name follows column name */
-#define COLFLAG_UNIQUE 0x0008 /* Column def contains "UNIQUE" or "PK" */
+#define COLFLAG_PRIMKEY 0x0001 /* Column is part of the primary key */
+#define COLFLAG_HIDDEN 0x0002 /* A hidden column in a virtual table */
+#define COLFLAG_HASTYPE 0x0004 /* Type name follows column name */
+#define COLFLAG_UNIQUE 0x0008 /* Column def contains "UNIQUE" or "PK" */
#define COLFLAG_SORTERREF 0x0010 /* Use sorter-refs with this column */
+#define COLFLAG_VIRTUAL 0x0020 /* GENERATED ALWAYS AS ... VIRTUAL */
+#define COLFLAG_STORED 0x0040 /* GENERATED ALWAYS AS ... STORED */
+#define COLFLAG_NOTAVAIL 0x0080 /* STORED column not yet calculated */
+#define COLFLAG_BUSY 0x0100 /* Blocks recursion on GENERATED columns */
+#define COLFLAG_GENERATED 0x0060 /* Combo: _STORED, _VIRTUAL */
+#define COLFLAG_NOINSERT 0x0062 /* Combo: _HIDDEN, _STORED, _VIRTUAL */
/*
** A "Collating Sequence" is defined by an instance of the following
@@ -16589,11 +17671,12 @@ struct CollSeq {
** Note also that the numeric types are grouped together so that testing
** for a numeric type is a single comparison. And the BLOB type is first.
*/
-#define SQLITE_AFF_BLOB 'A'
-#define SQLITE_AFF_TEXT 'B'
-#define SQLITE_AFF_NUMERIC 'C'
-#define SQLITE_AFF_INTEGER 'D'
-#define SQLITE_AFF_REAL 'E'
+#define SQLITE_AFF_NONE 0x40 /* '@' */
+#define SQLITE_AFF_BLOB 0x41 /* 'A' */
+#define SQLITE_AFF_TEXT 0x42 /* 'B' */
+#define SQLITE_AFF_NUMERIC 0x43 /* 'C' */
+#define SQLITE_AFF_INTEGER 0x44 /* 'D' */
+#define SQLITE_AFF_REAL 0x45 /* 'E' */
#define sqlite3IsNumericAffinity(X) ((X)>=SQLITE_AFF_NUMERIC)
@@ -16612,9 +17695,7 @@ struct CollSeq {
** operator is NULL. It is added to certain comparison operators to
** prove that the operands are always NOT NULL.
*/
-#define SQLITE_KEEPNULL 0x08 /* Used by vector == or <> */
#define SQLITE_JUMPIFNULL 0x10 /* jumps if either operand is NULL */
-#define SQLITE_STOREP2 0x20 /* Store result in reg[P2] rather than jump */
#define SQLITE_NULLEQ 0x80 /* NULL=NULL */
#define SQLITE_NOTNULL 0x90 /* Assert that operands are never NULL */
@@ -16666,10 +17747,17 @@ struct VTable {
sqlite3_vtab *pVtab; /* Pointer to vtab instance */
int nRef; /* Number of pointers to this structure */
u8 bConstraint; /* True if constraints are supported */
+ u8 eVtabRisk; /* Riskiness of allowing hacker access */
int iSavepoint; /* Depth of the SAVEPOINT stack */
VTable *pNext; /* Next in linked list (see above) */
};
+/* Allowed values for VTable.eVtabRisk
+*/
+#define SQLITE_VTABRISK_Low 0
+#define SQLITE_VTABRISK_Normal 1
+#define SQLITE_VTABRISK_High 2
+
/*
** The schema for each SQL table and view is represented in memory
** by an instance of the following structure.
@@ -16683,11 +17771,12 @@ struct Table {
char *zColAff; /* String defining the affinity of each column */
ExprList *pCheck; /* All CHECK constraints */
/* ... also used as column name list in a VIEW */
- int tnum; /* Root BTree page for this table */
+ Pgno tnum; /* Root BTree page for this table */
u32 nTabRef; /* Number of pointers to this Table */
u32 tabFlags; /* Mask of TF_* values */
i16 iPKey; /* If not negative, use aCol[iPKey] as the rowid */
i16 nCol; /* Number of columns in this table */
+ i16 nNVCol; /* Number of columns that are not VIRTUAL */
LogEst nRowLogEst; /* Estimated rows in table - from sqlite_stat1 table */
LogEst szTabRow; /* Estimated size of each table row in bytes */
#ifdef SQLITE_ENABLE_COSTMULT
@@ -16704,7 +17793,6 @@ struct Table {
#endif
Trigger *pTrigger; /* List of triggers stored in pSchema */
Schema *pSchema; /* Schema that contains this table */
- Table *pNextZombie; /* Next on the Parse.pZombieTab list */
};
/*
@@ -16714,19 +17802,32 @@ struct Table {
** followed by non-hidden columns. Example: "CREATE VIRTUAL TABLE x USING
** vtab1(a HIDDEN, b);". Since "b" is a non-hidden column but "a" is hidden,
** the TF_OOOHidden attribute would apply in this case. Such tables require
-** special handling during INSERT processing.
+** special handling during INSERT processing. The "OOO" means "Out Of Order".
+**
+** Constraints:
+**
+** TF_HasVirtual == COLFLAG_VIRTUAL
+** TF_HasStored == COLFLAG_STORED
+** TF_HasHidden == COLFLAG_HIDDEN
*/
#define TF_Readonly 0x0001 /* Read-only system table */
-#define TF_Ephemeral 0x0002 /* An ephemeral table */
+#define TF_HasHidden 0x0002 /* Has one or more hidden columns */
#define TF_HasPrimaryKey 0x0004 /* Table has a primary key */
#define TF_Autoincrement 0x0008 /* Integer primary key is autoincrement */
#define TF_HasStat1 0x0010 /* nRowLogEst set from sqlite_stat1 */
-#define TF_WithoutRowid 0x0020 /* No rowid. PRIMARY KEY is the key */
-#define TF_NoVisibleRowid 0x0040 /* No user-visible "rowid" column */
-#define TF_OOOHidden 0x0080 /* Out-of-Order hidden columns */
+#define TF_HasVirtual 0x0020 /* Has one or more VIRTUAL columns */
+#define TF_HasStored 0x0040 /* Has one or more STORED columns */
+#define TF_HasGenerated 0x0060 /* Combo: HasVirtual + HasStored */
+#define TF_WithoutRowid 0x0080 /* No rowid. PRIMARY KEY is the key */
#define TF_StatsUsed 0x0100 /* Query planner decisions affected by
** Index.aiRowLogEst[] values */
-#define TF_HasNotNull 0x0200 /* Contains NOT NULL constraints */
+#define TF_NoVisibleRowid 0x0200 /* No user-visible "rowid" column */
+#define TF_OOOHidden 0x0400 /* Out-of-Order hidden columns */
+#define TF_HasNotNull 0x0800 /* Contains NOT NULL constraints */
+#define TF_Shadow 0x1000 /* True for a shadow table */
+#define TF_HasStat4 0x2000 /* STAT4 info available for this table */
+#define TF_Ephemeral 0x4000 /* An ephemeral table */
+#define TF_Eponymous 0x8000 /* An eponymous virtual table */
/*
** Test to see whether or not a table is a virtual table. This is
@@ -16735,8 +17836,11 @@ struct Table {
*/
#ifndef SQLITE_OMIT_VIRTUALTABLE
# define IsVirtual(X) ((X)->nModuleArg)
+# define ExprIsVtab(X) \
+ ((X)->op==TK_COLUMN && (X)->y.pTab!=0 && (X)->y.pTab->nModuleArg)
#else
# define IsVirtual(X) 0
+# define ExprIsVtab(X) 0
#endif
/*
@@ -16820,16 +17924,22 @@ struct FKey {
** is returned. REPLACE means that preexisting database rows that caused
** a UNIQUE constraint violation are removed so that the new insert or
** update can proceed. Processing continues and no error is reported.
+** UPDATE applies to insert operations only and means that the insert
+** is omitted and the DO UPDATE clause of an upsert is run instead.
**
-** RESTRICT, SETNULL, and CASCADE actions apply only to foreign keys.
+** RESTRICT, SETNULL, SETDFLT, and CASCADE actions apply only to foreign keys.
** RESTRICT is the same as ABORT for IMMEDIATE foreign keys and the
** same as ROLLBACK for DEFERRED keys. SETNULL means that the foreign
-** key is set to NULL. CASCADE means that a DELETE or UPDATE of the
+** key is set to NULL. SETDFLT means that the foreign key is set
+** to its default value. CASCADE means that a DELETE or UPDATE of the
** referenced table row is propagated into the row that holds the
** foreign key.
**
+** The OE_Default value is a place holder that means to use whatever
+** conflict resolution algorthm is required from context.
+**
** The following symbolic values are used to record which type
-** of action to take.
+** of conflict resolution action to take.
*/
#define OE_None 0 /* There is no constraint to check */
#define OE_Rollback 1 /* Fail the operation and rollback the transaction */
@@ -16860,10 +17970,16 @@ struct KeyInfo {
u16 nKeyField; /* Number of key columns in the index */
u16 nAllField; /* Total columns, including key plus others */
sqlite3 *db; /* The database connection */
- u8 *aSortOrder; /* Sort order for each column. */
+ u8 *aSortFlags; /* Sort order for each column. */
CollSeq *aColl[1]; /* Collating sequence for each term of the key */
};
+/*
+** Allowed bit values for entries in the KeyInfo.aSortFlags[] array.
+*/
+#define KEYINFO_ORDER_DESC 0x01 /* DESC sort order */
+#define KEYINFO_ORDER_BIGNULL 0x02 /* NULL is larger than any other value */
+
/*
** This object holds a record which has been parsed out into individual
** fields, for the purposes of doing a comparison.
@@ -16938,7 +18054,7 @@ struct UnpackedRecord {
** element.
**
** While parsing a CREATE TABLE or CREATE INDEX statement in order to
-** generate VDBE code (as opposed to parsing one read from an sqlite_master
+** generate VDBE code (as opposed to parsing one read from an sqlite_schema
** table as part of parsing an existing database schema), transient instances
** of this structure may be created. In this case the Index.tnum variable is
** used to store the address of a VDBE instruction, not a database page
@@ -16957,12 +18073,12 @@ struct Index {
const char **azColl; /* Array of collation sequence names for index */
Expr *pPartIdxWhere; /* WHERE clause for partial indices */
ExprList *aColExpr; /* Column expressions */
- int tnum; /* DB Page containing root of this index */
+ Pgno tnum; /* DB Page containing root of this index */
LogEst szIdxRow; /* Estimated average row size in bytes */
u16 nKeyCol; /* Number of columns forming the key */
u16 nColumn; /* Number of columns stored in the index */
u8 onError; /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */
- unsigned idxType:2; /* 1==UNIQUE, 2==PRIMARY KEY, 0==CREATE INDEX */
+ unsigned idxType:2; /* 0:Normal 1:UNIQUE, 2:PRIMARY KEY, 3:IPK */
unsigned bUnordered:1; /* Use this index for == or IN queries only */
unsigned uniqNotNull:1; /* True if UNIQUE and NOT NULL for all columns */
unsigned isResized:1; /* True if resizeIndexObject() has been called */
@@ -16970,7 +18086,9 @@ struct Index {
unsigned noSkipScan:1; /* Do not try to use skip-scan if true */
unsigned hasStat1:1; /* aiRowLogEst values come from sqlite_stat1 */
unsigned bNoQuery:1; /* Do not use this index to optimize queries */
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
+ unsigned bAscKeyBug:1; /* True if the bba7b69f9849b5bf bug applies */
+ unsigned bHasVCol:1; /* Index references one or more VIRTUAL columns */
+#ifdef SQLITE_ENABLE_STAT4
int nSample; /* Number of elements in aSample[] */
int nSampleCol; /* Size of IndexSample.anEq[] and so on */
tRowcnt *aAvgEq; /* Average nEq values for keys not in aSample */
@@ -16987,6 +18105,7 @@ struct Index {
#define SQLITE_IDXTYPE_APPDEF 0 /* Created using CREATE INDEX */
#define SQLITE_IDXTYPE_UNIQUE 1 /* Implements a UNIQUE constraint */
#define SQLITE_IDXTYPE_PRIMARYKEY 2 /* Is the PRIMARY KEY for the table */
+#define SQLITE_IDXTYPE_IPK 3 /* INTEGER PRIMARY KEY index */
/* Return true if index X is a PRIMARY KEY index */
#define IsPrimaryKeyIndex(X) ((X)->idxType==SQLITE_IDXTYPE_PRIMARYKEY)
@@ -17001,7 +18120,7 @@ struct Index {
#define XN_EXPR (-2) /* Indexed column is an expression */
/*
-** Each sample stored in the sqlite_stat3 table is represented in memory
+** Each sample stored in the sqlite_stat4 table is represented in memory
** using a structure of this type. See documentation at the top of the
** analyze.c source file for additional information.
*/
@@ -17013,6 +18132,12 @@ struct IndexSample {
tRowcnt *anDLt; /* Est. number of distinct keys less than this sample */
};
+/*
+** Possible values to use within the flags argument to sqlite3GetToken().
+*/
+#define SQLITE_TOKEN_QUOTED 0x1 /* Token is a quoted identifier. */
+#define SQLITE_TOKEN_KEYWORD 0x2 /* Token is a keyword. */
+
/*
** Each token coming out of the lexer is an instance of
** this structure. Tokens are also used as part of an expression.
@@ -17033,7 +18158,7 @@ struct Token {
** code for a SELECT that contains aggregate functions.
**
** If Expr.op==TK_AGG_COLUMN or TK_AGG_FUNCTION then Expr.pAggInfo is a
-** pointer to this structure. The Expr.iColumn field is the index in
+** pointer to this structure. The Expr.iAgg field is the index in
** AggInfo.aCol[] or AggInfo.aFunc[] of information needed to generate
** code for that node.
**
@@ -17053,23 +18178,25 @@ struct AggInfo {
ExprList *pGroupBy; /* The group by clause */
struct AggInfo_col { /* For each column used in source tables */
Table *pTab; /* Source table */
+ Expr *pCExpr; /* The original expression */
int iTable; /* Cursor number of the source table */
- int iColumn; /* Column number within the source table */
- int iSorterColumn; /* Column number in the sorting index */
int iMem; /* Memory location that acts as accumulator */
- Expr *pExpr; /* The original expression */
+ i16 iColumn; /* Column number within the source table */
+ i16 iSorterColumn; /* Column number in the sorting index */
} *aCol;
int nColumn; /* Number of used entries in aCol[] */
int nAccumulator; /* Number of columns that show through to the output.
** Additional columns are used only as parameters to
** aggregate functions */
struct AggInfo_func { /* For each aggregate function */
- Expr *pExpr; /* Expression encoding the function */
+ Expr *pFExpr; /* Expression encoding the function */
FuncDef *pFunc; /* The aggregate function implementation */
int iMem; /* Memory location that acts as accumulator */
int iDistinct; /* Ephemeral table used to enforce DISTINCT */
+ int iDistAddr; /* Address of OP_OpenEphemeral */
} *aFunc;
int nFunc; /* Number of entries in aFunc[] */
+ u32 selId; /* Select to which this AggInfo belongs */
};
/*
@@ -17079,10 +18206,10 @@ struct AggInfo {
** it uses less memory in the Expr object, which is a big memory user
** in systems with lots of prepared statements. And few applications
** need more than about 10 or 20 variables. But some extreme users want
-** to have prepared statements with over 32767 variables, and for them
+** to have prepared statements with over 32766 variables, and for them
** the option is available (at compile-time).
*/
-#if SQLITE_MAX_VARIABLE_NUMBER<=32767
+#if SQLITE_MAX_VARIABLE_NUMBER<32767
typedef i16 ynVar;
#else
typedef int ynVar;
@@ -17153,7 +18280,14 @@ typedef int ynVar;
*/
struct Expr {
u8 op; /* Operation performed by this node */
- char affinity; /* The affinity of the column or 0 if not a column */
+ char affExpr; /* affinity, or RAISE type */
+ u8 op2; /* TK_REGISTER/TK_TRUTH: original value of Expr.op
+ ** TK_COLUMN: the value of p5 for OP_Column
+ ** TK_AGG_FUNCTION: nesting depth
+ ** TK_FUNCTION: NC_SelfRef flag if needs OP_PureFunc */
+#ifdef SQLITE_DEBUG
+ u8 vvaFlags; /* Verification flags. */
+#endif
u32 flags; /* Various flags. EP_* See below */
union {
char *zToken; /* Token value. Zero terminated and dequoted */
@@ -17184,50 +18318,65 @@ struct Expr {
** TK_REGISTER: register number
** TK_TRIGGER: 1 -> new, 0 -> old
** EP_Unlikely: 134217728 times likelihood
+ ** TK_IN: ephemerial table holding RHS
+ ** TK_SELECT_COLUMN: Number of columns on the LHS
** TK_SELECT: 1st register of result vector */
ynVar iColumn; /* TK_COLUMN: column index. -1 for rowid.
** TK_VARIABLE: variable number (always >= 1).
** TK_SELECT_COLUMN: column of the result vector */
i16 iAgg; /* Which entry in pAggInfo->aCol[] or ->aFunc[] */
- i16 iRightJoinTable; /* If EP_FromJoin, the right table of the join */
- u8 op2; /* TK_REGISTER: original value of Expr.op
- ** TK_COLUMN: the value of p5 for OP_Column
- ** TK_AGG_FUNCTION: nesting depth */
+ int iRightJoinTable; /* If EP_FromJoin, the right table of the join */
AggInfo *pAggInfo; /* Used by TK_AGG_COLUMN and TK_AGG_FUNCTION */
- Table *pTab; /* Table for TK_COLUMN expressions. Can be NULL
- ** for a column of an index on an expression */
-#ifndef SQLITE_OMIT_WINDOWFUNC
- Window *pWin; /* Window definition for window functions */
-#endif
+ union {
+ Table *pTab; /* TK_COLUMN: Table containing column. Can be NULL
+ ** for a column of an index on an expression */
+ Window *pWin; /* EP_WinFunc: Window/Filter defn for a function */
+ struct { /* TK_IN, TK_SELECT, and TK_EXISTS */
+ int iAddr; /* Subroutine entry address */
+ int regReturn; /* Register used to hold return address */
+ } sub;
+ } y;
};
/*
** The following are the meanings of bits in the Expr.flags field.
+** Value restrictions:
+**
+** EP_Agg == NC_HasAgg == SF_HasAgg
+** EP_Win == NC_HasWin
*/
-#define EP_FromJoin 0x000001 /* Originates in ON/USING clause of outer join */
-#define EP_Agg 0x000002 /* Contains one or more aggregate functions */
-#define EP_HasFunc 0x000004 /* Contains one or more functions of any kind */
-#define EP_FixedCol 0x000008 /* TK_Column with a known fixed value */
-#define EP_Distinct 0x000010 /* Aggregate function with DISTINCT keyword */
-#define EP_VarSelect 0x000020 /* pSelect is correlated, not constant */
-#define EP_DblQuoted 0x000040 /* token.z was originally in "..." */
-#define EP_InfixFunc 0x000080 /* True for an infix function: LIKE, GLOB, etc */
-#define EP_Collate 0x000100 /* Tree contains a TK_COLLATE operator */
-#define EP_Generic 0x000200 /* Ignore COLLATE or affinity on this tree */
-#define EP_IntValue 0x000400 /* Integer value contained in u.iValue */
-#define EP_xIsSelect 0x000800 /* x.pSelect is valid (otherwise x.pList is) */
-#define EP_Skip 0x001000 /* COLLATE, AS, or UNLIKELY */
-#define EP_Reduced 0x002000 /* Expr struct EXPR_REDUCEDSIZE bytes only */
-#define EP_TokenOnly 0x004000 /* Expr struct EXPR_TOKENONLYSIZE bytes only */
-#define EP_Static 0x008000 /* Held in memory not obtained from malloc() */
-#define EP_MemToken 0x010000 /* Need to sqlite3DbFree() Expr.zToken */
-#define EP_NoReduce 0x020000 /* Cannot EXPRDUP_REDUCE this Expr */
-#define EP_Unlikely 0x040000 /* unlikely() or likelihood() function */
-#define EP_ConstFunc 0x080000 /* A SQLITE_FUNC_CONSTANT or _SLOCHNG function */
-#define EP_CanBeNull 0x100000 /* Can be null despite NOT NULL constraint */
-#define EP_Subquery 0x200000 /* Tree contains a TK_SELECT operator */
-#define EP_Alias 0x400000 /* Is an alias for a result set column */
-#define EP_Leaf 0x800000 /* Expr.pLeft, .pRight, .u.pSelect all NULL */
+#define EP_FromJoin 0x000001 /* Originates in ON/USING clause of outer join */
+#define EP_Distinct 0x000002 /* Aggregate function with DISTINCT keyword */
+#define EP_HasFunc 0x000004 /* Contains one or more functions of any kind */
+#define EP_FixedCol 0x000008 /* TK_Column with a known fixed value */
+#define EP_Agg 0x000010 /* Contains one or more aggregate functions */
+#define EP_VarSelect 0x000020 /* pSelect is correlated, not constant */
+#define EP_DblQuoted 0x000040 /* token.z was originally in "..." */
+#define EP_InfixFunc 0x000080 /* True for an infix function: LIKE, GLOB, etc */
+#define EP_Collate 0x000100 /* Tree contains a TK_COLLATE operator */
+#define EP_Commuted 0x000200 /* Comparison operator has been commuted */
+#define EP_IntValue 0x000400 /* Integer value contained in u.iValue */
+#define EP_xIsSelect 0x000800 /* x.pSelect is valid (otherwise x.pList is) */
+#define EP_Skip 0x001000 /* Operator does not contribute to affinity */
+#define EP_Reduced 0x002000 /* Expr struct EXPR_REDUCEDSIZE bytes only */
+#define EP_TokenOnly 0x004000 /* Expr struct EXPR_TOKENONLYSIZE bytes only */
+#define EP_Win 0x008000 /* Contains window functions */
+#define EP_MemToken 0x010000 /* Need to sqlite3DbFree() Expr.zToken */
+#define EP_IfNullRow 0x020000 /* The TK_IF_NULL_ROW opcode */
+#define EP_Unlikely 0x040000 /* unlikely() or likelihood() function */
+#define EP_ConstFunc 0x080000 /* A SQLITE_FUNC_CONSTANT or _SLOCHNG function */
+#define EP_CanBeNull 0x100000 /* Can be null despite NOT NULL constraint */
+#define EP_Subquery 0x200000 /* Tree contains a TK_SELECT operator */
+ /* 0x400000 // Available */
+#define EP_Leaf 0x800000 /* Expr.pLeft, .pRight, .u.pSelect all NULL */
+#define EP_WinFunc 0x1000000 /* TK_FUNCTION with Expr.y.pWin set */
+#define EP_Subrtn 0x2000000 /* Uses Expr.y.sub. TK_IN, _SELECT, or _EXISTS */
+#define EP_Quoted 0x4000000 /* TK_ID was originally quoted */
+#define EP_Static 0x8000000 /* Held in memory not obtained from malloc() */
+#define EP_IsTrue 0x10000000 /* Always has boolean value of TRUE */
+#define EP_IsFalse 0x20000000 /* Always has boolean value of FALSE */
+#define EP_FromDDL 0x40000000 /* Originates from sqlite_schema */
+ /* 0x80000000 // Available */
/*
** The EP_Propagate mask is a set of properties that automatically propagate
@@ -17243,15 +18392,27 @@ struct Expr {
#define ExprHasAllProperty(E,P) (((E)->flags&(P))==(P))
#define ExprSetProperty(E,P) (E)->flags|=(P)
#define ExprClearProperty(E,P) (E)->flags&=~(P)
+#define ExprAlwaysTrue(E) (((E)->flags&(EP_FromJoin|EP_IsTrue))==EP_IsTrue)
+#define ExprAlwaysFalse(E) (((E)->flags&(EP_FromJoin|EP_IsFalse))==EP_IsFalse)
+
+
+/* Flags for use with Expr.vvaFlags
+*/
+#define EP_NoReduce 0x01 /* Cannot EXPRDUP_REDUCE this Expr */
+#define EP_Immutable 0x02 /* Do not change this Expr node */
/* The ExprSetVVAProperty() macro is used for Verification, Validation,
** and Accreditation only. It works like ExprSetProperty() during VVA
** processes but is a no-op for delivery.
*/
#ifdef SQLITE_DEBUG
-# define ExprSetVVAProperty(E,P) (E)->flags|=(P)
+# define ExprSetVVAProperty(E,P) (E)->vvaFlags|=(P)
+# define ExprHasVVAProperty(E,P) (((E)->vvaFlags&(P))!=0)
+# define ExprClearVVAProperties(E) (E)->vvaFlags = 0
#else
# define ExprSetVVAProperty(E,P)
+# define ExprHasVVAProperty(E,P) 0
+# define ExprClearVVAProperties(E)
#endif
/*
@@ -17269,6 +18430,18 @@ struct Expr {
*/
#define EXPRDUP_REDUCE 0x0001 /* Used reduced-size Expr nodes */
+/*
+** True if the expression passed as an argument was a function with
+** an OVER() clause (a window function).
+*/
+#ifdef SQLITE_OMIT_WINDOWFUNC
+# define IsWindowFunc(p) 0
+#else
+# define IsWindowFunc(p) ( \
+ ExprHasProperty((p), EP_WinFunc) && p->y.pWin->eFrmType!=TK_FILTER \
+ )
+#endif
+
/*
** A list of expressions. Each expression may optionally have a
** name. An expr/name combination can be used in several ways, such
@@ -17277,25 +18450,32 @@ struct Expr {
** also be used as the argument to a function, in which case the a.zName
** field is not used.
**
-** By default the Expr.zSpan field holds a human-readable description of
-** the expression that is used in the generation of error messages and
-** column labels. In this case, Expr.zSpan is typically the text of a
-** column expression as it exists in a SELECT statement. However, if
-** the bSpanIsTab flag is set, then zSpan is overloaded to mean the name
-** of the result column in the form: DATABASE.TABLE.COLUMN. This later
-** form is used for name resolution with nested FROM clauses.
+** In order to try to keep memory usage down, the Expr.a.zEName field
+** is used for multiple purposes:
+**
+** eEName Usage
+** ---------- -------------------------
+** ENAME_NAME (1) the AS of result set column
+** (2) COLUMN= of an UPDATE
+**
+** ENAME_TAB DB.TABLE.NAME used to resolve names
+** of subqueries
+**
+** ENAME_SPAN Text of the original result set
+** expression.
*/
struct ExprList {
int nExpr; /* Number of expressions on the list */
+ int nAlloc; /* Number of a[] slots allocated */
struct ExprList_item { /* For each expression in the list */
Expr *pExpr; /* The parse tree for this expression */
- char *zName; /* Token associated with this expression */
- char *zSpan; /* Original text of the expression */
- u8 sortOrder; /* 1 for DESC or 0 for ASC */
+ char *zEName; /* Token associated with this expression */
+ u8 sortFlags; /* Mask of KEYINFO_ORDER_* flags */
+ unsigned eEName :2; /* Meaning of zEName */
unsigned done :1; /* A flag to indicate when processing is finished */
- unsigned bSpanIsTab :1; /* zSpan holds DB.TABLE.COLUMN */
unsigned reusable :1; /* Constant expression is reusable */
unsigned bSorterRef :1; /* Defer evaluation until after sorting */
+ unsigned bNulls: 1; /* True if explicit "NULLS FIRST/LAST" */
union {
struct {
u16 iOrderByCol; /* For ORDER BY, column number in result set */
@@ -17306,6 +18486,13 @@ struct ExprList {
} a[1]; /* One slot for each expression in the list */
};
+/*
+** Allowed values for Expr.a.eEName
+*/
+#define ENAME_NAME 0 /* The AS clause of a result set */
+#define ENAME_SPAN 1 /* Complete text of the result set expression */
+#define ENAME_TAB 2 /* "DB.TABLE.NAME" for the result set */
+
/*
** An instance of this structure can hold a simple list of identifiers,
** such as the list "a,b,c" in the following statements:
@@ -17329,6 +18516,46 @@ struct IdList {
int nId; /* Number of identifiers on the list */
};
+/*
+** The SrcItem object represents a single term in the FROM clause of a query.
+** The SrcList object is mostly an array of SrcItems.
+*/
+struct SrcItem {
+ Schema *pSchema; /* Schema to which this item is fixed */
+ char *zDatabase; /* Name of database holding this table */
+ char *zName; /* Name of the table */
+ char *zAlias; /* The "B" part of a "A AS B" phrase. zName is the "A" */
+ Table *pTab; /* An SQL table corresponding to zName */
+ Select *pSelect; /* A SELECT statement used in place of a table name */
+ int addrFillSub; /* Address of subroutine to manifest a subquery */
+ int regReturn; /* Register holding return address of addrFillSub */
+ int regResult; /* Registers holding results of a co-routine */
+ struct {
+ u8 jointype; /* Type of join between this table and the previous */
+ unsigned notIndexed :1; /* True if there is a NOT INDEXED clause */
+ unsigned isIndexedBy :1; /* True if there is an INDEXED BY clause */
+ unsigned isTabFunc :1; /* True if table-valued-function syntax */
+ unsigned isCorrelated :1; /* True if sub-query is correlated */
+ unsigned viaCoroutine :1; /* Implemented as a co-routine */
+ unsigned isRecursive :1; /* True for recursive reference in WITH */
+ unsigned fromDDL :1; /* Comes from sqlite_schema */
+ unsigned isCte :1; /* This is a CTE */
+ unsigned notCte :1; /* This item may not match a CTE */
+ } fg;
+ int iCursor; /* The VDBE cursor number used to access this table */
+ Expr *pOn; /* The ON clause of a join */
+ IdList *pUsing; /* The USING clause of a join */
+ Bitmask colUsed; /* Bit N (1<" clause */
+ ExprList *pFuncArg; /* Arguments to table-valued-function */
+ } u1;
+ union {
+ Index *pIBIndex; /* Index structure corresponding to u1.zIndexedBy */
+ CteUse *pCteUse; /* CTE Usage info info fg.isCte is true */
+ } u2;
+};
+
/*
** The following structure describes the FROM clause of a SELECT statement.
** Each table or subquery in the FROM clause is a separate element of
@@ -17351,35 +18578,7 @@ struct IdList {
struct SrcList {
int nSrc; /* Number of tables or subqueries in the FROM clause */
u32 nAlloc; /* Number of entries allocated in a[] below */
- struct SrcList_item {
- Schema *pSchema; /* Schema to which this item is fixed */
- char *zDatabase; /* Name of database holding this table */
- char *zName; /* Name of the table */
- char *zAlias; /* The "B" part of a "A AS B" phrase. zName is the "A" */
- Table *pTab; /* An SQL table corresponding to zName */
- Select *pSelect; /* A SELECT statement used in place of a table name */
- int addrFillSub; /* Address of subroutine to manifest a subquery */
- int regReturn; /* Register holding return address of addrFillSub */
- int regResult; /* Registers holding results of a co-routine */
- struct {
- u8 jointype; /* Type of join between this table and the previous */
- unsigned notIndexed :1; /* True if there is a NOT INDEXED clause */
- unsigned isIndexedBy :1; /* True if there is an INDEXED BY clause */
- unsigned isTabFunc :1; /* True if table-valued-function syntax */
- unsigned isCorrelated :1; /* True if sub-query is correlated */
- unsigned viaCoroutine :1; /* Implemented as a co-routine */
- unsigned isRecursive :1; /* True for recursive reference in WITH */
- } fg;
- int iCursor; /* The VDBE cursor number used to access this table */
- Expr *pOn; /* The ON clause of a join */
- IdList *pUsing; /* The USING clause of a join */
- Bitmask colUsed; /* Bit N (1<" clause */
- ExprList *pFuncArg; /* Arguments to table-valued-function */
- } u1;
- Index *pIBIndex; /* Index structure corresponding to u1.zIndexedBy */
- } a[1]; /* One entry for each identifier on the list */
+ SrcItem a[1]; /* One entry for each identifier on the list */
};
/*
@@ -17413,9 +18612,9 @@ struct SrcList {
#define WHERE_DISTINCTBY 0x0080 /* pOrderby is really a DISTINCT clause */
#define WHERE_WANT_DISTINCT 0x0100 /* All output needs to be distinct */
#define WHERE_SORTBYGROUP 0x0200 /* Support sqlite3WhereIsSorted() */
-#define WHERE_SEEK_TABLE 0x0400 /* Do not defer seeks on main table */
+#define WHERE_AGG_DISTINCT 0x0400 /* Query is "SELECT agg(DISTINCT ...)" */
#define WHERE_ORDERBY_LIMIT 0x0800 /* ORDERBY+LIMIT on the inner loop */
-#define WHERE_SEEK_UNIQ_TABLE 0x1000 /* Do not defer seeks if unique */
+ /* 0x1000 not currently used */
/* 0x2000 not currently used */
#define WHERE_USE_LIMIT 0x4000 /* Use the LIMIT in cost estimates */
/* 0x8000 not currently used */
@@ -17455,11 +18654,12 @@ struct NameContext {
ExprList *pEList; /* Optional list of result-set columns */
AggInfo *pAggInfo; /* Information about aggregates at this level */
Upsert *pUpsert; /* ON CONFLICT clause information from an upsert */
+ int iBaseReg; /* For TK_REGISTER when parsing RETURNING */
} uNC;
NameContext *pNext; /* Next outer name context. NULL for outermost */
int nRef; /* Number of names resolved by this context */
- int nErr; /* Number of errors encountered while resolving names */
- u16 ncFlags; /* Zero or more NC_* flags defined below */
+ int nNcErr; /* Number of errors encountered while resolving names */
+ int ncFlags; /* Zero or more NC_* flags defined below */
Select *pWinSelect; /* SELECT statement for any window functions */
};
@@ -17467,23 +18667,31 @@ struct NameContext {
** Allowed values for the NameContext, ncFlags field.
**
** Value constraints (all checked via assert()):
-** NC_HasAgg == SF_HasAgg
+** NC_HasAgg == SF_HasAgg == EP_Agg
** NC_MinMaxAgg == SF_MinMaxAgg == SQLITE_FUNC_MINMAX
+** NC_HasWin == EP_Win
**
*/
-#define NC_AllowAgg 0x0001 /* Aggregate functions are allowed here */
-#define NC_PartIdx 0x0002 /* True if resolving a partial index WHERE */
-#define NC_IsCheck 0x0004 /* True if resolving names in a CHECK constraint */
-#define NC_InAggFunc 0x0008 /* True if analyzing arguments to an agg func */
-#define NC_HasAgg 0x0010 /* One or more aggregate functions seen */
-#define NC_IdxExpr 0x0020 /* True if resolving columns of CREATE INDEX */
-#define NC_VarSelect 0x0040 /* A correlated subquery has been seen */
-#define NC_UEList 0x0080 /* True if uNC.pEList is used */
-#define NC_UAggInfo 0x0100 /* True if uNC.pAggInfo is used */
-#define NC_UUpsert 0x0200 /* True if uNC.pUpsert is used */
-#define NC_MinMaxAgg 0x1000 /* min/max aggregates seen. See note above */
-#define NC_Complex 0x2000 /* True if a function or subquery seen */
-#define NC_AllowWin 0x4000 /* Window functions are allowed here */
+#define NC_AllowAgg 0x00001 /* Aggregate functions are allowed here */
+#define NC_PartIdx 0x00002 /* True if resolving a partial index WHERE */
+#define NC_IsCheck 0x00004 /* True if resolving a CHECK constraint */
+#define NC_GenCol 0x00008 /* True for a GENERATED ALWAYS AS clause */
+#define NC_HasAgg 0x00010 /* One or more aggregate functions seen */
+#define NC_IdxExpr 0x00020 /* True if resolving columns of CREATE INDEX */
+#define NC_SelfRef 0x0002e /* Combo: PartIdx, isCheck, GenCol, and IdxExpr */
+#define NC_VarSelect 0x00040 /* A correlated subquery has been seen */
+#define NC_UEList 0x00080 /* True if uNC.pEList is used */
+#define NC_UAggInfo 0x00100 /* True if uNC.pAggInfo is used */
+#define NC_UUpsert 0x00200 /* True if uNC.pUpsert is used */
+#define NC_UBaseReg 0x00400 /* True if uNC.iBaseReg is used */
+#define NC_MinMaxAgg 0x01000 /* min/max aggregates seen. See note above */
+#define NC_Complex 0x02000 /* True if a function or subquery seen */
+#define NC_AllowWin 0x04000 /* Window functions are allowed here */
+#define NC_HasWin 0x08000 /* One or more window functions seen */
+#define NC_IsDDL 0x10000 /* Resolving names in a CREATE statement */
+#define NC_InAggFunc 0x20000 /* True if analyzing arguments to an agg func */
+#define NC_FromDDL 0x40000 /* SQL text comes from sqlite_schema */
+#define NC_NoSelect 0x80000 /* Do not descend into sub-selects */
/*
** An instance of the following object describes a single ON CONFLICT
@@ -17494,21 +18702,27 @@ struct NameContext {
** conflict-target clause.) The pUpsertTargetWhere is the optional
** WHERE clause used to identify partial unique indexes.
**
-** pUpsertSet is the list of column=expr terms of the UPDATE statement.
+** pUpsertSet is the list of column=expr terms of the UPDATE statement.
** The pUpsertSet field is NULL for a ON CONFLICT DO NOTHING. The
** pUpsertWhere is the WHERE clause for the UPDATE and is NULL if the
** WHERE clause is omitted.
*/
struct Upsert {
- ExprList *pUpsertTarget; /* Optional description of conflicting index */
+ ExprList *pUpsertTarget; /* Optional description of conflict target */
Expr *pUpsertTargetWhere; /* WHERE clause for partial index targets */
ExprList *pUpsertSet; /* The SET clause from an ON CONFLICT UPDATE */
Expr *pUpsertWhere; /* WHERE clause for the ON CONFLICT UPDATE */
- /* The fields above comprise the parse tree for the upsert clause.
- ** The fields below are used to transfer information from the INSERT
- ** processing down into the UPDATE processing while generating code.
- ** Upsert owns the memory allocated above, but not the memory below. */
- Index *pUpsertIdx; /* Constraint that pUpsertTarget identifies */
+ Upsert *pNextUpsert; /* Next ON CONFLICT clause in the list */
+ u8 isDoUpdate; /* True for DO UPDATE. False for DO NOTHING */
+ /* Above this point is the parse tree for the ON CONFLICT clauses.
+ ** The next group of fields stores intermediate data. */
+ void *pToFree; /* Free memory when deleting the Upsert object */
+ /* All fields above are owned by the Upsert object and must be freed
+ ** when the Upsert is destroyed. The fields below are used to transfer
+ ** information from the INSERT processing down into the UPDATE processing
+ ** while generating code. The fields below are owned by the INSERT
+ ** statement and will be freed by INSERT processing. */
+ Index *pUpsertIdx; /* UNIQUE constraint specified by pUpsertTarget */
SrcList *pUpsertSrc; /* Table to be updated */
int regData; /* First register holding array of VALUES */
int iDataCur; /* Index of the data cursor */
@@ -17533,13 +18747,13 @@ struct Upsert {
** sequences for the ORDER BY clause.
*/
struct Select {
- ExprList *pEList; /* The fields of the result */
u8 op; /* One of: TK_UNION TK_ALL TK_INTERSECT TK_EXCEPT */
LogEst nSelectRow; /* Estimated number of result rows */
u32 selFlags; /* Various SF_* values */
int iLimit, iOffset; /* Memory registers holding LIMIT & OFFSET counters */
u32 selId; /* Unique identifier number for this SELECT */
int addrOpenEphm[2]; /* OP_OpenEphem opcodes related to this select */
+ ExprList *pEList; /* The fields of the result */
SrcList *pSrc; /* The FROM clause */
Expr *pWhere; /* The WHERE clause */
ExprList *pGroupBy; /* The GROUP BY clause */
@@ -17564,25 +18778,33 @@ struct Select {
** SF_MinMaxAgg == NC_MinMaxAgg == SQLITE_FUNC_MINMAX
** SF_FixedLimit == WHERE_USE_LIMIT
*/
-#define SF_Distinct 0x00001 /* Output should be DISTINCT */
-#define SF_All 0x00002 /* Includes the ALL keyword */
-#define SF_Resolved 0x00004 /* Identifiers have been resolved */
-#define SF_Aggregate 0x00008 /* Contains agg functions or a GROUP BY */
-#define SF_HasAgg 0x00010 /* Contains aggregate functions */
-#define SF_UsesEphemeral 0x00020 /* Uses the OpenEphemeral opcode */
-#define SF_Expanded 0x00040 /* sqlite3SelectExpand() called on this */
-#define SF_HasTypeInfo 0x00080 /* FROM subqueries have Table metadata */
-#define SF_Compound 0x00100 /* Part of a compound query */
-#define SF_Values 0x00200 /* Synthesized from VALUES clause */
-#define SF_MultiValue 0x00400 /* Single VALUES term with multiple rows */
-#define SF_NestedFrom 0x00800 /* Part of a parenthesized FROM clause */
-#define SF_MinMaxAgg 0x01000 /* Aggregate containing min() or max() */
-#define SF_Recursive 0x02000 /* The recursive part of a recursive CTE */
-#define SF_FixedLimit 0x04000 /* nSelectRow set by a constant LIMIT */
-#define SF_MaybeConvert 0x08000 /* Need convertCompoundSelectToSubquery() */
-#define SF_Converted 0x10000 /* By convertCompoundSelectToSubquery() */
-#define SF_IncludeHidden 0x20000 /* Include hidden columns in output */
-#define SF_ComplexResult 0x40000 /* Result contains subquery or function */
+#define SF_Distinct 0x0000001 /* Output should be DISTINCT */
+#define SF_All 0x0000002 /* Includes the ALL keyword */
+#define SF_Resolved 0x0000004 /* Identifiers have been resolved */
+#define SF_Aggregate 0x0000008 /* Contains agg functions or a GROUP BY */
+#define SF_HasAgg 0x0000010 /* Contains aggregate functions */
+#define SF_UsesEphemeral 0x0000020 /* Uses the OpenEphemeral opcode */
+#define SF_Expanded 0x0000040 /* sqlite3SelectExpand() called on this */
+#define SF_HasTypeInfo 0x0000080 /* FROM subqueries have Table metadata */
+#define SF_Compound 0x0000100 /* Part of a compound query */
+#define SF_Values 0x0000200 /* Synthesized from VALUES clause */
+#define SF_MultiValue 0x0000400 /* Single VALUES term with multiple rows */
+#define SF_NestedFrom 0x0000800 /* Part of a parenthesized FROM clause */
+#define SF_MinMaxAgg 0x0001000 /* Aggregate containing min() or max() */
+#define SF_Recursive 0x0002000 /* The recursive part of a recursive CTE */
+#define SF_FixedLimit 0x0004000 /* nSelectRow set by a constant LIMIT */
+#define SF_MaybeConvert 0x0008000 /* Need convertCompoundSelectToSubquery() */
+#define SF_Converted 0x0010000 /* By convertCompoundSelectToSubquery() */
+#define SF_IncludeHidden 0x0020000 /* Include hidden columns in output */
+#define SF_ComplexResult 0x0040000 /* Result contains subquery or function */
+#define SF_WhereBegin 0x0080000 /* Really a WhereBegin() call. Debug Only */
+#define SF_WinRewrite 0x0100000 /* Window function rewrite accomplished */
+#define SF_View 0x0200000 /* SELECT statement is a view */
+#define SF_NoopOrderBy 0x0400000 /* ORDER BY is ignored for this query */
+#define SF_UpdateFrom 0x0800000 /* Statement is an UPDATE...FROM */
+#define SF_PushDown 0x1000000 /* SELECT has be modified by push-down opt */
+#define SF_MultiPart 0x2000000 /* Has multiple incompatible PARTITIONs */
+#define SF_CopyCte 0x4000000 /* SELECT statement is a copy of a CTE */
/*
** The results of a SELECT can be distributed in several ways, as defined
@@ -17601,9 +18823,6 @@ struct Select {
** statements within triggers whose only purpose is
** the side-effects of functions.
**
-** All of the above are free to ignore their ORDER BY clause. Those that
-** follow must honor the ORDER BY clause.
-**
** SRT_Output Generate a row of output (using the OP_ResultRow
** opcode) for each row in the result set.
**
@@ -17647,18 +18866,31 @@ struct Select {
** SRT_DistQueue Store results in priority queue pDest->iSDParm only if
** the same record has never been stored before. The
** index at pDest->iSDParm+1 hold all prior stores.
+**
+** SRT_Upfrom Store results in the temporary table already opened by
+** pDest->iSDParm. If (pDest->iSDParm<0), then the temp
+** table is an intkey table - in this case the first
+** column returned by the SELECT is used as the integer
+** key. If (pDest->iSDParm>0), then the table is an index
+** table. (pDest->iSDParm) is the number of key columns in
+** each index record in this case.
*/
#define SRT_Union 1 /* Store result as keys in an index */
#define SRT_Except 2 /* Remove result from a UNION index */
#define SRT_Exists 3 /* Store 1 if the result is not empty */
#define SRT_Discard 4 /* Do not save the results anywhere */
-#define SRT_Fifo 5 /* Store result as data with an automatic rowid */
-#define SRT_DistFifo 6 /* Like SRT_Fifo, but unique results only */
+#define SRT_DistFifo 5 /* Like SRT_Fifo, but unique results only */
+#define SRT_DistQueue 6 /* Like SRT_Queue, but unique results only */
+
+/* The DISTINCT clause is ignored for all of the above. Not that
+** IgnorableDistinct() implies IgnorableOrderby() */
+#define IgnorableDistinct(X) ((X->eDest)<=SRT_DistQueue)
+
#define SRT_Queue 7 /* Store result in an queue */
-#define SRT_DistQueue 8 /* Like SRT_Queue, but unique results only */
+#define SRT_Fifo 8 /* Store result as data with an automatic rowid */
/* The ORDER BY clause is ignored for all of the above */
-#define IgnorableOrderby(X) ((X->eDest)<=SRT_DistQueue)
+#define IgnorableOrderby(X) ((X->eDest)<=SRT_Fifo)
#define SRT_Output 9 /* Output each row of result */
#define SRT_Mem 10 /* Store result in a memory cell */
@@ -17666,14 +18898,16 @@ struct Select {
#define SRT_EphemTab 12 /* Create transient tab and store like SRT_Table */
#define SRT_Coroutine 13 /* Generate a single row of result */
#define SRT_Table 14 /* Store result as data with an automatic rowid */
+#define SRT_Upfrom 15 /* Store result as data with rowid */
/*
** An instance of this object describes where to put of the results of
** a SELECT statement.
*/
struct SelectDest {
- u8 eDest; /* How to dispose of the results. On of SRT_* above. */
+ u8 eDest; /* How to dispose of the results. One of SRT_* above. */
int iSDParm; /* A parameter used by the eDest disposal method */
+ int iSDParm2; /* A second parameter for the eDest disposal method */
int iSdst; /* Base register where results are written */
int nSdst; /* Number of registers allocated */
char *zAffSdst; /* Affinity used when eDest==SRT_Set */
@@ -17741,6 +18975,17 @@ struct TriggerPrg {
# define DbMaskNonZero(M) (M)!=0
#endif
+/*
+** An instance of the ParseCleanup object specifies an operation that
+** should be performed after parsing to deallocation resources obtained
+** during the parse and which are no longer needed.
+*/
+struct ParseCleanup {
+ ParseCleanup *pNext; /* Next cleanup task */
+ void *pPtr; /* Pointer to object to deallocate */
+ void (*xCleanup)(sqlite3*,void*); /* Deallocation routine */
+};
+
/*
** An SQL parser context. A copy of this structure is passed through
** the parser and down into all the parser action routine in order to
@@ -17771,16 +19016,20 @@ struct Parse {
u8 hasCompound; /* Need to invoke convertCompoundSelectToSubquery() */
u8 okConstFactor; /* OK to factor out constants */
u8 disableLookaside; /* Number of times lookaside has been disabled */
+ u8 disableVtab; /* Disable all virtual tables for this parse */
+#if defined(SQLITE_DEBUG) || defined(SQLITE_COVERAGE_TEST)
+ u8 earlyCleanup; /* OOM inside sqlite3ParserAddCleanup() */
+#endif
int nRangeReg; /* Size of the temporary register block */
int iRangeReg; /* First register in temporary register block */
int nErr; /* Number of errors seen */
int nTab; /* Number of previously allocated VDBE cursors */
int nMem; /* Number of memory cells used so far */
- int nOpAlloc; /* Number of slots allocated for Vdbe.aOp[] */
int szOpAlloc; /* Bytes of memory space allocated for Vdbe.aOp[] */
int iSelfTab; /* Table associated with an index on expr, or negative
** of the base register during check-constraint eval */
- int nLabel; /* Number of labels used */
+ int nLabel; /* The *negative* of the number of labels used */
+ int nLabelAlloc; /* Number of slots in aLabel */
int *aLabel; /* Space to hold the labels */
ExprList *pConstExpr;/* Constant expressions */
Token constraintName;/* Name of the constraint currently being parsed */
@@ -17797,11 +19046,16 @@ struct Parse {
AutoincInfo *pAinc; /* Information about AUTOINCREMENT counters */
Parse *pToplevel; /* Parse structure for main program (or NULL) */
Table *pTriggerTab; /* Table triggers are being coded for */
- int addrCrTab; /* Address of OP_CreateBtree opcode on CREATE TABLE */
+ Parse *pParentParse; /* Parent parser if this parser is nested */
+ union {
+ int addrCrTab; /* Address of OP_CreateBtree on CREATE TABLE */
+ Returning *pReturning; /* The RETURNING clause */
+ } u1;
u32 nQueryLoop; /* Est number of iterations of a query (10*log2(N)) */
u32 oldmask; /* Mask of old.* columns referenced */
u32 newmask; /* Mask of new.* columns referenced */
u8 eTriggerOp; /* TK_UPDATE, TK_INSERT or TK_DELETE */
+ u8 bReturning; /* Coding a RETURNING trigger */
u8 eOrconf; /* Default ON CONFLICT policy for trigger steps */
u8 disableTriggers; /* True to disable triggers */
@@ -17826,9 +19080,7 @@ struct Parse {
ynVar nVar; /* Number of '?' variables seen in the SQL so far */
u8 iPkSortOrder; /* ASC or DESC for INTEGER PRIMARY KEY */
u8 explain; /* True if the EXPLAIN flag is found on the query */
-#if !(defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_OMIT_ALTERTABLE))
u8 eParseMode; /* PARSE_MODE_XXX constant */
-#endif
#ifndef SQLITE_OMIT_VIRTUALTABLE
int nVtabLock; /* Number of virtual tables to lock */
#endif
@@ -17840,17 +19092,18 @@ struct Parse {
Vdbe *pReprepare; /* VM being reprepared (sqlite3Reprepare()) */
const char *zTail; /* All SQL text past the last semicolon parsed */
Table *pNewTable; /* A table being constructed by CREATE TABLE */
- Index *pNewIndex; /* An index being constructed by CREATE INDEX */
+ Index *pNewIndex; /* An index being constructed by CREATE INDEX.
+ ** Also used to hold redundant UNIQUE constraints
+ ** during a RENAME COLUMN */
Trigger *pNewTrigger; /* Trigger under construct by a CREATE TRIGGER */
const char *zAuthContext; /* The 6th parameter to db->xAuth callbacks */
#ifndef SQLITE_OMIT_VIRTUALTABLE
Token sArg; /* Complete text of a module argument */
Table **apVtabLock; /* Pointer to virtual tables needing locking */
#endif
- Table *pZombieTab; /* List of Table objects to delete after code gen */
TriggerPrg *pTriggerPrg; /* Linked list of coded triggers */
With *pWith; /* Current WITH clause, or NULL */
- With *pWithToFree; /* Free this WITH object at the end of the parse */
+ ParseCleanup *pCleanup; /* List of cleanup operations to run after parse */
#ifndef SQLITE_OMIT_ALTERTABLE
RenameToken *pRename; /* Tokens subject to renaming by ALTER TABLE */
#endif
@@ -17858,8 +19111,8 @@ struct Parse {
#define PARSE_MODE_NORMAL 0
#define PARSE_MODE_DECLARE_VTAB 1
-#define PARSE_MODE_RENAME_COLUMN 2
-#define PARSE_MODE_RENAME_TABLE 3
+#define PARSE_MODE_RENAME 2
+#define PARSE_MODE_UNMAP 3
/*
** Sizes and pointers of various parts of the Parse object.
@@ -17881,7 +19134,7 @@ struct Parse {
#if defined(SQLITE_OMIT_ALTERTABLE)
#define IN_RENAME_OBJECT 0
#else
- #define IN_RENAME_OBJECT (pParse->eParseMode>=PARSE_MODE_RENAME_COLUMN)
+ #define IN_RENAME_OBJECT (pParse->eParseMode>=PARSE_MODE_RENAME)
#endif
#if defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_OMIT_ALTERTABLE)
@@ -17913,6 +19166,7 @@ struct AuthContext {
*/
#define OPFLAG_NCHANGE 0x01 /* OP_Insert: Set to update db->nChange */
/* Also used in P2 (not P5) of OP_Delete */
+#define OPFLAG_NOCHNG 0x01 /* OP_VColumn nochange for UPDATE */
#define OPFLAG_EPHEM 0x01 /* OP_Column: Ephemeral output is ok */
#define OPFLAG_LASTROWID 0x20 /* Set to update db->lastRowid */
#define OPFLAG_ISUPDATE 0x04 /* This OP_Insert is an sql UPDATE */
@@ -17929,6 +19183,7 @@ struct AuthContext {
#define OPFLAG_SAVEPOSITION 0x02 /* OP_Delete/Insert: save cursor pos */
#define OPFLAG_AUXDELETE 0x04 /* OP_Delete: index in a DELETE op */
#define OPFLAG_NOCHNG_MAGIC 0x6d /* OP_MakeRecord: serialtype 10 is ok */
+#define OPFLAG_PREFORMAT 0x80 /* OP_Insert uses preformatted cell */
/*
* Each trigger present in the database schema is stored as an instance of
@@ -17950,6 +19205,7 @@ struct Trigger {
char *table; /* The table or view to which the trigger applies */
u8 op; /* One of TK_DELETE, TK_UPDATE, TK_INSERT */
u8 tr_tm; /* One of TRIGGER_BEFORE, TRIGGER_AFTER */
+ u8 bReturning; /* This trigger implements a RETURNING clause */
Expr *pWhen; /* The WHEN clause of the expression (may be NULL) */
IdList *pColumns; /* If this is an UPDATE OF trigger,
the is stored here */
@@ -18008,13 +19264,15 @@ struct Trigger {
*
*/
struct TriggerStep {
- u8 op; /* One of TK_DELETE, TK_UPDATE, TK_INSERT, TK_SELECT */
+ u8 op; /* One of TK_DELETE, TK_UPDATE, TK_INSERT, TK_SELECT,
+ ** or TK_RETURNING */
u8 orconf; /* OE_Rollback etc. */
Trigger *pTrig; /* The trigger that this step is a part of */
Select *pSelect; /* SELECT statement or RHS of INSERT INTO SELECT ... */
char *zTarget; /* Target table for DELETE, UPDATE, INSERT */
+ SrcList *pFrom; /* FROM clause for UPDATE statement (if any) */
Expr *pWhere; /* The WHERE clause for DELETE or UPDATE steps */
- ExprList *pExprList; /* SET clause for UPDATE */
+ ExprList *pExprList; /* SET clause for UPDATE, or RETURNING clause */
IdList *pIdList; /* Column names for INSERT */
Upsert *pUpsert; /* Upsert clauses on an INSERT */
char *zSpan; /* Original SQL text of this command */
@@ -18023,18 +19281,16 @@ struct TriggerStep {
};
/*
-** The following structure contains information used by the sqliteFix...
-** routines as they walk the parse tree to make database references
-** explicit.
+** Information about a RETURNING clause
*/
-typedef struct DbFixer DbFixer;
-struct DbFixer {
- Parse *pParse; /* The parsing context. Error messages written here */
- Schema *pSchema; /* Fix items to this schema */
- int bVarOnly; /* Check for variable references only */
- const char *zDb; /* Make sure all objects are contained in this database */
- const char *zType; /* Type of the container - used for error messages */
- const Token *pName; /* Name of the container - used for error messages */
+struct Returning {
+ Parse *pParse; /* The parse that includes the RETURNING clause */
+ ExprList *pReturnEL; /* List of expressions to return */
+ Trigger retTrig; /* The transient trigger that implements RETURNING */
+ TriggerStep retTStep; /* The trigger step */
+ int iRetCur; /* Transient table holding RETURNING results */
+ int nRetCol; /* Number of in pReturnEL after expansion */
+ int iRetReg; /* Register array for holding a row of RETURNING */
};
/*
@@ -18067,12 +19323,31 @@ typedef struct {
int iDb; /* 0 for main database. 1 for TEMP, 2.. for ATTACHed */
int rc; /* Result code stored here */
u32 mInitFlags; /* Flags controlling error messages */
+ u32 nInitRow; /* Number of rows processed */
+ Pgno mxPage; /* Maximum page number. 0 for no limit. */
} InitData;
/*
** Allowed values for mInitFlags
*/
-#define INITFLAG_AlterTable 0x0001 /* This is a reparse after ALTER TABLE */
+#define INITFLAG_AlterRename 0x0001 /* Reparse after a RENAME */
+#define INITFLAG_AlterDrop 0x0002 /* Reparse after a DROP COLUMN */
+
+/* Tuning parameters are set using SQLITE_TESTCTRL_TUNE and are controlled
+** on debug-builds of the CLI using ".testctrl tune ID VALUE". Tuning
+** parameters are for temporary use during development, to help find
+** optimial values for parameters in the query planner. The should not
+** be used on trunk check-ins. They are a temporary mechanism available
+** for transient development builds only.
+**
+** Tuning parameters are numbered starting with 1.
+*/
+#define SQLITE_NTUNE 6 /* Should be zero for all trunk check-ins */
+#ifdef SQLITE_DEBUG
+# define Tuning(X) (sqlite3Config.aTune[(X)-1])
+#else
+# define Tuning(X) 0
+#endif
/*
** Structure containing global configuration data for the SQLite library.
@@ -18081,11 +19356,12 @@ typedef struct {
*/
struct Sqlite3Config {
int bMemstat; /* True to enable memory status */
- int bCoreMutex; /* True to enable core mutexing */
- int bFullMutex; /* True to enable full mutexing */
- int bOpenUri; /* True to interpret filenames as URIs */
- int bUseCis; /* Use covering indices for full-scans */
- int bSmallMalloc; /* Avoid large memory allocations if true */
+ u8 bCoreMutex; /* True to enable core mutexing */
+ u8 bFullMutex; /* True to enable full mutexing */
+ u8 bOpenUri; /* True to interpret filenames as URIs */
+ u8 bUseCis; /* Use covering indices for full-scans */
+ u8 bSmallMalloc; /* Avoid large memory allocations if true */
+ u8 bExtraSchemaChecks; /* Verify type,name,tbl_name in schema */
int mxStrlen; /* Maximum string length */
int neverCorrupt; /* Database is always well-formed */
int szLookaside; /* Default lookaside buffer size */
@@ -18127,12 +19403,20 @@ struct Sqlite3Config {
void (*xVdbeBranch)(void*,unsigned iSrcLine,u8 eThis,u8 eMx); /* Callback */
void *pVdbeBranchArg; /* 1st argument */
#endif
+#ifndef SQLITE_OMIT_DESERIALIZE
+ sqlite3_int64 mxMemdbSize; /* Default max memdb size */
+#endif
#ifndef SQLITE_UNTESTABLE
int (*xTestCallback)(int); /* Invoked by sqlite3FaultSim() */
#endif
int bLocaltimeFault; /* True to fail localtime() calls */
int iOnceResetThreshold; /* When to reset OP_Once counters */
u32 szSorterRef; /* Min size in bytes to use sorter-refs */
+ unsigned int iPrngSeed; /* Alternative fixed seed for the PRNG */
+ /* vvvv--- must be last ---vvv */
+#ifdef SQLITE_DEBUG
+ sqlite3_int64 aTune[SQLITE_NTUNE]; /* Tuning parameters */
+#endif
};
/*
@@ -18162,7 +19446,7 @@ struct Walker {
int (*xSelectCallback)(Walker*,Select*); /* Callback for SELECTs */
void (*xSelectCallback2)(Walker*,Select*);/* Second callback for SELECTs */
int walkerDepth; /* Number of subqueries */
- u8 eCode; /* A small processing code */
+ u16 eCode; /* A small processing code */
union { /* Extra data for callback */
NameContext *pNC; /* Naming context */
int n; /* A counter */
@@ -18178,9 +19462,27 @@ struct Walker {
struct WindowRewrite *pRewrite; /* Window rewrite context */
struct WhereConst *pConst; /* WHERE clause constants */
struct RenameCtx *pRename; /* RENAME COLUMN context */
+ struct Table *pTab; /* Table of generated column */
+ SrcItem *pSrcItem; /* A single FROM clause item */
+ DbFixer *pFix;
} u;
};
+/*
+** The following structure contains information used by the sqliteFix...
+** routines as they walk the parse tree to make database references
+** explicit.
+*/
+struct DbFixer {
+ Parse *pParse; /* The parsing context. Error messages written here */
+ Walker w; /* Walker object */
+ Schema *pSchema; /* Fix items to this schema */
+ u8 bTemp; /* True for TEMP schema entries */
+ const char *zDb; /* Make sure all objects are contained in this database */
+ const char *zType; /* Type of the container - used for error messages */
+ const Token *pName; /* Name of the container - used for error messages */
+};
+
/* Forward declarations */
SQLITE_PRIVATE int sqlite3WalkExpr(Walker*, Expr*);
SQLITE_PRIVATE int sqlite3WalkExprList(Walker*, ExprList*);
@@ -18190,10 +19492,20 @@ SQLITE_PRIVATE int sqlite3WalkSelectFrom(Walker*, Select*);
SQLITE_PRIVATE int sqlite3ExprWalkNoop(Walker*, Expr*);
SQLITE_PRIVATE int sqlite3SelectWalkNoop(Walker*, Select*);
SQLITE_PRIVATE int sqlite3SelectWalkFail(Walker*, Select*);
+SQLITE_PRIVATE int sqlite3WalkerDepthIncrease(Walker*,Select*);
+SQLITE_PRIVATE void sqlite3WalkerDepthDecrease(Walker*,Select*);
+SQLITE_PRIVATE void sqlite3WalkWinDefnDummyCallback(Walker*,Select*);
+
#ifdef SQLITE_DEBUG
SQLITE_PRIVATE void sqlite3SelectWalkAssert2(Walker*, Select*);
#endif
+#ifndef SQLITE_OMIT_CTE
+SQLITE_PRIVATE void sqlite3SelectPopWith(Walker*, Select*);
+#else
+# define sqlite3SelectPopWith 0
+#endif
+
/*
** Return code from the parse-tree walking primitives and their
** callbacks.
@@ -18203,20 +19515,56 @@ SQLITE_PRIVATE void sqlite3SelectWalkAssert2(Walker*, Select*);
#define WRC_Abort 2 /* Abandon the tree walk */
/*
-** An instance of this structure represents a set of one or more CTEs
-** (common table expressions) created by a single WITH clause.
+** A single common table expression
+*/
+struct Cte {
+ char *zName; /* Name of this CTE */
+ ExprList *pCols; /* List of explicit column names, or NULL */
+ Select *pSelect; /* The definition of this CTE */
+ const char *zCteErr; /* Error message for circular references */
+ CteUse *pUse; /* Usage information for this CTE */
+ u8 eM10d; /* The MATERIALIZED flag */
+};
+
+/*
+** Allowed values for the materialized flag (eM10d):
+*/
+#define M10d_Yes 0 /* AS MATERIALIZED */
+#define M10d_Any 1 /* Not specified. Query planner's choice */
+#define M10d_No 2 /* AS NOT MATERIALIZED */
+
+/*
+** An instance of the With object represents a WITH clause containing
+** one or more CTEs (common table expressions).
*/
struct With {
- int nCte; /* Number of CTEs in the WITH clause */
- With *pOuter; /* Containing WITH clause, or NULL */
- struct Cte { /* For each CTE in the WITH clause.... */
- char *zName; /* Name of this CTE */
- ExprList *pCols; /* List of explicit column names, or NULL */
- Select *pSelect; /* The definition of this CTE */
- const char *zCteErr; /* Error message for circular references */
- } a[1];
+ int nCte; /* Number of CTEs in the WITH clause */
+ int bView; /* Belongs to the outermost Select of a view */
+ With *pOuter; /* Containing WITH clause, or NULL */
+ Cte a[1]; /* For each CTE in the WITH clause.... */
};
+/*
+** The Cte object is not guaranteed to persist for the entire duration
+** of code generation. (The query flattener or other parser tree
+** edits might delete it.) The following object records information
+** about each Common Table Expression that must be preserved for the
+** duration of the parse.
+**
+** The CteUse objects are freed using sqlite3ParserAddCleanup() rather
+** than sqlite3SelectDelete(), which is what enables them to persist
+** until the end of code generation.
+*/
+struct CteUse {
+ int nUse; /* Number of users of this CTE */
+ int addrM9e; /* Start of subroutine to compute materialization */
+ int regRtn; /* Return address register for addrM9e subroutine */
+ int iCur; /* Ephemeral table holding the materialization */
+ LogEst nRowEst; /* Estimated number of rows in the table */
+ u8 eM10d; /* The MATERIALIZED flag */
+};
+
+
#ifdef SQLITE_DEBUG
/*
** An instance of the TreeView object is used for printing the content of
@@ -18229,10 +19577,11 @@ struct TreeView {
#endif /* SQLITE_DEBUG */
/*
-** This object is used in varioius ways, all related to window functions
+** This object is used in various ways, most (but not all) related to window
+** functions.
**
** (1) A single instance of this structure is attached to the
-** the Expr.pWin field for each window function in an expression tree.
+** the Expr.y.pWin field for each window function in an expression tree.
** This object holds the information contained in the OVER clause,
** plus additional fields used during code generation.
**
@@ -18243,47 +19592,62 @@ struct TreeView {
** (3) The terms of the WINDOW clause of a SELECT are instances of this
** object on a linked list attached to Select.pWinDefn.
**
+** (4) For an aggregate function with a FILTER clause, an instance
+** of this object is stored in Expr.y.pWin with eFrmType set to
+** TK_FILTER. In this case the only field used is Window.pFilter.
+**
** The uses (1) and (2) are really the same Window object that just happens
-** to be accessible in two different ways. Use (3) is are separate objects.
+** to be accessible in two different ways. Use case (3) are separate objects.
*/
struct Window {
char *zName; /* Name of window (may be NULL) */
+ char *zBase; /* Name of base window for chaining (may be NULL) */
ExprList *pPartition; /* PARTITION BY clause */
ExprList *pOrderBy; /* ORDER BY clause */
- u8 eType; /* TK_RANGE or TK_ROWS */
+ u8 eFrmType; /* TK_RANGE, TK_GROUPS, TK_ROWS, or 0 */
u8 eStart; /* UNBOUNDED, CURRENT, PRECEDING or FOLLOWING */
u8 eEnd; /* UNBOUNDED, CURRENT, PRECEDING or FOLLOWING */
+ u8 bImplicitFrame; /* True if frame was implicitly specified */
+ u8 eExclude; /* TK_NO, TK_CURRENT, TK_TIES, TK_GROUP, or 0 */
Expr *pStart; /* Expression for " PRECEDING" */
Expr *pEnd; /* Expression for " FOLLOWING" */
+ Window **ppThis; /* Pointer to this object in Select.pWin list */
Window *pNextWin; /* Next window function belonging to this SELECT */
Expr *pFilter; /* The FILTER expression */
FuncDef *pFunc; /* The function */
int iEphCsr; /* Partition buffer or Peer buffer */
- int regAccum;
- int regResult;
+ int regAccum; /* Accumulator */
+ int regResult; /* Interim result */
int csrApp; /* Function cursor (used by min/max) */
int regApp; /* Function register (also used by min/max) */
- int regPart; /* First in a set of registers holding PARTITION BY
- ** and ORDER BY values for the window */
+ int regPart; /* Array of registers for PARTITION BY values */
Expr *pOwner; /* Expression object this window is attached to */
int nBufferCol; /* Number of columns in buffer table */
int iArgCol; /* Offset of first argument for this function */
+ int regOne; /* Register containing constant value 1 */
+ int regStartRowid;
+ int regEndRowid;
+ u8 bExprArgs; /* Defer evaluation of window function arguments
+ ** due to the SQLITE_SUBTYPE flag */
};
#ifndef SQLITE_OMIT_WINDOWFUNC
SQLITE_PRIVATE void sqlite3WindowDelete(sqlite3*, Window*);
+SQLITE_PRIVATE void sqlite3WindowUnlinkFromSelect(Window*);
SQLITE_PRIVATE void sqlite3WindowListDelete(sqlite3 *db, Window *p);
-SQLITE_PRIVATE Window *sqlite3WindowAlloc(Parse*, int, int, Expr*, int , Expr*);
+SQLITE_PRIVATE Window *sqlite3WindowAlloc(Parse*, int, int, Expr*, int , Expr*, u8);
SQLITE_PRIVATE void sqlite3WindowAttach(Parse*, Expr*, Window*);
-SQLITE_PRIVATE int sqlite3WindowCompare(Parse*, Window*, Window*);
-SQLITE_PRIVATE void sqlite3WindowCodeInit(Parse*, Window*);
+SQLITE_PRIVATE void sqlite3WindowLink(Select *pSel, Window *pWin);
+SQLITE_PRIVATE int sqlite3WindowCompare(Parse*, Window*, Window*, int);
+SQLITE_PRIVATE void sqlite3WindowCodeInit(Parse*, Select*);
SQLITE_PRIVATE void sqlite3WindowCodeStep(Parse*, Select*, WhereInfo*, int, int);
SQLITE_PRIVATE int sqlite3WindowRewrite(Parse*, Select*);
-SQLITE_PRIVATE int sqlite3ExpandSubquery(Parse*, struct SrcList_item*);
SQLITE_PRIVATE void sqlite3WindowUpdate(Parse*, Window*, Window*, FuncDef*);
SQLITE_PRIVATE Window *sqlite3WindowDup(sqlite3 *db, Expr *pOwner, Window *p);
SQLITE_PRIVATE Window *sqlite3WindowListDup(sqlite3 *db, Window *p);
SQLITE_PRIVATE void sqlite3WindowFunctions(void);
+SQLITE_PRIVATE void sqlite3WindowChain(Parse*, Window*, Window*);
+SQLITE_PRIVATE Window *sqlite3WindowAssemble(Parse*, Window*, ExprList*, ExprList*, Token*);
#else
# define sqlite3WindowDelete(a,b)
# define sqlite3WindowFunctions()
@@ -18317,13 +19681,16 @@ SQLITE_PRIVATE int sqlite3CantopenError(int);
#ifdef SQLITE_DEBUG
SQLITE_PRIVATE int sqlite3NomemError(int);
SQLITE_PRIVATE int sqlite3IoerrnomemError(int);
-SQLITE_PRIVATE int sqlite3CorruptPgnoError(int,Pgno);
# define SQLITE_NOMEM_BKPT sqlite3NomemError(__LINE__)
# define SQLITE_IOERR_NOMEM_BKPT sqlite3IoerrnomemError(__LINE__)
-# define SQLITE_CORRUPT_PGNO(P) sqlite3CorruptPgnoError(__LINE__,(P))
#else
# define SQLITE_NOMEM_BKPT SQLITE_NOMEM
# define SQLITE_IOERR_NOMEM_BKPT SQLITE_IOERR_NOMEM
+#endif
+#if defined(SQLITE_DEBUG) || defined(SQLITE_ENABLE_CORRUPT_PGNO)
+SQLITE_PRIVATE int sqlite3CorruptPgnoError(int,Pgno);
+# define SQLITE_CORRUPT_PGNO(P) sqlite3CorruptPgnoError(__LINE__,(P))
+#else
# define SQLITE_CORRUPT_PGNO(P) sqlite3CorruptError(__LINE__)
#endif
@@ -18384,6 +19751,7 @@ SQLITE_PRIVATE int sqlite3IsIdChar(u8);
*/
SQLITE_PRIVATE int sqlite3StrICmp(const char*,const char*);
SQLITE_PRIVATE int sqlite3Strlen30(const char*);
+#define sqlite3Strlen30NN(C) (strlen(C)&0x3fffffff)
SQLITE_PRIVATE char *sqlite3ColumnType(Column*,char*);
#define sqlite3StrNICmp sqlite3_strnicmp
@@ -18472,8 +19840,12 @@ SQLITE_PRIVATE void sqlite3MutexWarnOnContention(sqlite3_mutex*);
#endif
#ifndef SQLITE_OMIT_FLOATING_POINT
+# define EXP754 (((u64)0x7ff)<<52)
+# define MAN754 ((((u64)1)<<52)-1)
+# define IsNaN(X) (((X)&EXP754)==EXP754 && ((X)&MAN754)!=0)
SQLITE_PRIVATE int sqlite3IsNaN(double);
#else
+# define IsNaN(X) 0
# define sqlite3IsNaN(X) 0
#endif
@@ -18500,6 +19872,7 @@ SQLITE_PRIVATE void *sqlite3TestTextToPtr(const char*);
SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView*, const Expr*, u8);
SQLITE_PRIVATE void sqlite3TreeViewBareExprList(TreeView*, const ExprList*, const char*);
SQLITE_PRIVATE void sqlite3TreeViewExprList(TreeView*, const ExprList*, u8, const char*);
+SQLITE_PRIVATE void sqlite3TreeViewSrcList(TreeView*, const SrcList*);
SQLITE_PRIVATE void sqlite3TreeViewSelect(TreeView*, const Select*, u8);
SQLITE_PRIVATE void sqlite3TreeViewWith(TreeView*, const With*, u8);
#ifndef SQLITE_OMIT_WINDOWFUNC
@@ -18511,7 +19884,9 @@ SQLITE_PRIVATE void sqlite3TreeViewWinFunc(TreeView*, const Window*, u8);
SQLITE_PRIVATE void sqlite3SetString(char **, sqlite3*, const char*);
SQLITE_PRIVATE void sqlite3ErrorMsg(Parse*, const char*, ...);
+SQLITE_PRIVATE int sqlite3ErrorToParser(sqlite3*,int);
SQLITE_PRIVATE void sqlite3Dequote(char*);
+SQLITE_PRIVATE void sqlite3DequoteExpr(Expr*);
SQLITE_PRIVATE void sqlite3TokenInit(Token*,char*);
SQLITE_PRIVATE int sqlite3KeywordCode(const unsigned char*, int);
SQLITE_PRIVATE int sqlite3RunParser(Parse*, const char*, char **);
@@ -18529,17 +19904,22 @@ SQLITE_PRIVATE Expr *sqlite3Expr(sqlite3*,int,const char*);
SQLITE_PRIVATE void sqlite3ExprAttachSubtrees(sqlite3*,Expr*,Expr*,Expr*);
SQLITE_PRIVATE Expr *sqlite3PExpr(Parse*, int, Expr*, Expr*);
SQLITE_PRIVATE void sqlite3PExprAddSelect(Parse*, Expr*, Select*);
-SQLITE_PRIVATE Expr *sqlite3ExprAnd(sqlite3*,Expr*, Expr*);
+SQLITE_PRIVATE Expr *sqlite3ExprAnd(Parse*,Expr*, Expr*);
+SQLITE_PRIVATE Expr *sqlite3ExprSimplifiedAndOr(Expr*);
SQLITE_PRIVATE Expr *sqlite3ExprFunction(Parse*,ExprList*, Token*, int);
+SQLITE_PRIVATE void sqlite3ExprFunctionUsable(Parse*,Expr*,FuncDef*);
SQLITE_PRIVATE void sqlite3ExprAssignVarNumber(Parse*, Expr*, u32);
SQLITE_PRIVATE void sqlite3ExprDelete(sqlite3*, Expr*);
+SQLITE_PRIVATE void sqlite3ExprDeferredDelete(Parse*, Expr*);
+SQLITE_PRIVATE void sqlite3ExprUnmapAndDelete(Parse*, Expr*);
SQLITE_PRIVATE ExprList *sqlite3ExprListAppend(Parse*,ExprList*,Expr*);
SQLITE_PRIVATE ExprList *sqlite3ExprListAppendVector(Parse*,ExprList*,IdList*,Expr*);
-SQLITE_PRIVATE void sqlite3ExprListSetSortOrder(ExprList*,int);
+SQLITE_PRIVATE void sqlite3ExprListSetSortOrder(ExprList*,int,int);
SQLITE_PRIVATE void sqlite3ExprListSetName(Parse*,ExprList*,Token*,int);
SQLITE_PRIVATE void sqlite3ExprListSetSpan(Parse*,ExprList*,const char*,const char*);
SQLITE_PRIVATE void sqlite3ExprListDelete(sqlite3*, ExprList*);
SQLITE_PRIVATE u32 sqlite3ExprListFlags(const ExprList*);
+SQLITE_PRIVATE int sqlite3IndexHasDuplicateRootPage(Index*);
SQLITE_PRIVATE int sqlite3Init(sqlite3*, char**);
SQLITE_PRIVATE int sqlite3InitCallback(void*, int, char**, char**);
SQLITE_PRIVATE int sqlite3InitOne(sqlite3*, int, char**, u32);
@@ -18552,12 +19932,20 @@ SQLITE_PRIVATE void sqlite3ResetOneSchema(sqlite3*,int);
SQLITE_PRIVATE void sqlite3CollapseDatabaseArray(sqlite3*);
SQLITE_PRIVATE void sqlite3CommitInternalChanges(sqlite3*);
SQLITE_PRIVATE void sqlite3DeleteColumnNames(sqlite3*,Table*);
+SQLITE_PRIVATE void sqlite3GenerateColumnNames(Parse *pParse, Select *pSelect);
SQLITE_PRIVATE int sqlite3ColumnsFromExprList(Parse*,ExprList*,i16*,Column**);
-SQLITE_PRIVATE void sqlite3SelectAddColumnTypeAndCollation(Parse*,Table*,Select*);
-SQLITE_PRIVATE Table *sqlite3ResultSetOfSelect(Parse*,Select*);
-SQLITE_PRIVATE void sqlite3OpenMasterTable(Parse *, int);
+SQLITE_PRIVATE void sqlite3SelectAddColumnTypeAndCollation(Parse*,Table*,Select*,char);
+SQLITE_PRIVATE Table *sqlite3ResultSetOfSelect(Parse*,Select*,char);
+SQLITE_PRIVATE void sqlite3OpenSchemaTable(Parse *, int);
SQLITE_PRIVATE Index *sqlite3PrimaryKeyIndex(Table*);
-SQLITE_PRIVATE i16 sqlite3ColumnOfIndex(Index*, i16);
+SQLITE_PRIVATE i16 sqlite3TableColumnToIndex(Index*, i16);
+#ifdef SQLITE_OMIT_GENERATED_COLUMNS
+# define sqlite3TableColumnToStorage(T,X) (X) /* No-op pass-through */
+# define sqlite3StorageColumnToTable(T,X) (X) /* No-op pass-through */
+#else
+SQLITE_PRIVATE i16 sqlite3TableColumnToStorage(Table*, i16);
+SQLITE_PRIVATE i16 sqlite3StorageColumnToTable(Table*, i16);
+#endif
SQLITE_PRIVATE void sqlite3StartTable(Parse*,Token*,Token*,int,int,int,int);
#if SQLITE_ENABLE_HIDDEN_COLUMNS
SQLITE_PRIVATE void sqlite3ColumnPropertiesFromName(Table*, Column*);
@@ -18567,12 +19955,15 @@ SQLITE_PRIVATE void sqlite3ColumnPropertiesFromName(Table*, Column*);
SQLITE_PRIVATE void sqlite3AddColumn(Parse*,Token*,Token*);
SQLITE_PRIVATE void sqlite3AddNotNull(Parse*, int);
SQLITE_PRIVATE void sqlite3AddPrimaryKey(Parse*, ExprList*, int, int, int);
-SQLITE_PRIVATE void sqlite3AddCheckConstraint(Parse*, Expr*);
+SQLITE_PRIVATE void sqlite3AddCheckConstraint(Parse*, Expr*, const char*, const char*);
SQLITE_PRIVATE void sqlite3AddDefaultValue(Parse*,Expr*,const char*,const char*);
SQLITE_PRIVATE void sqlite3AddCollateType(Parse*, Token*);
+SQLITE_PRIVATE void sqlite3AddGenerated(Parse*,Expr*,Token*);
SQLITE_PRIVATE void sqlite3EndTable(Parse*,Token*,Token*,u8,Select*);
+SQLITE_PRIVATE void sqlite3AddReturning(Parse*,ExprList*);
SQLITE_PRIVATE int sqlite3ParseUri(const char*,const char*,unsigned int*,
sqlite3_vfs**,char**,char **);
+#define sqlite3CodecQueryParameters(A,B,C) 0
SQLITE_PRIVATE Btree *sqlite3DbNameToBtree(sqlite3*,const char*);
#ifdef SQLITE_UNTESTABLE
@@ -18622,16 +20013,20 @@ SQLITE_PRIVATE void sqlite3AutoincrementEnd(Parse *pParse);
# define sqlite3AutoincrementEnd(X)
#endif
SQLITE_PRIVATE void sqlite3Insert(Parse*, SrcList*, Select*, IdList*, int, Upsert*);
+#ifndef SQLITE_OMIT_GENERATED_COLUMNS
+SQLITE_PRIVATE void sqlite3ComputeGeneratedColumns(Parse*, int, Table*);
+#endif
SQLITE_PRIVATE void *sqlite3ArrayAllocate(sqlite3*,void*,int,int*,int*);
SQLITE_PRIVATE IdList *sqlite3IdListAppend(Parse*, IdList*, Token*);
SQLITE_PRIVATE int sqlite3IdListIndex(IdList*,const char*);
-SQLITE_PRIVATE SrcList *sqlite3SrcListEnlarge(sqlite3*, SrcList*, int, int);
-SQLITE_PRIVATE SrcList *sqlite3SrcListAppend(sqlite3*, SrcList*, Token*, Token*);
+SQLITE_PRIVATE SrcList *sqlite3SrcListEnlarge(Parse*, SrcList*, int, int);
+SQLITE_PRIVATE SrcList *sqlite3SrcListAppendList(Parse *pParse, SrcList *p1, SrcList *p2);
+SQLITE_PRIVATE SrcList *sqlite3SrcListAppend(Parse*, SrcList*, Token*, Token*);
SQLITE_PRIVATE SrcList *sqlite3SrcListAppendFromTerm(Parse*, SrcList*, Token*, Token*,
Token*, Select*, Expr*, IdList*);
SQLITE_PRIVATE void sqlite3SrcListIndexedBy(Parse *, SrcList *, Token *);
SQLITE_PRIVATE void sqlite3SrcListFuncArgs(Parse*, SrcList*, ExprList*);
-SQLITE_PRIVATE int sqlite3IndexedByLookup(Parse *, struct SrcList_item *);
+SQLITE_PRIVATE int sqlite3IndexedByLookup(Parse *, SrcItem *);
SQLITE_PRIVATE void sqlite3SrcListShiftJoinType(SrcList*);
SQLITE_PRIVATE void sqlite3SrcListAssignCursors(Parse*, SrcList*);
SQLITE_PRIVATE void sqlite3IdListDelete(sqlite3*, IdList*);
@@ -18659,6 +20054,7 @@ SQLITE_PRIVATE LogEst sqlite3WhereOutputRowCount(WhereInfo*);
SQLITE_PRIVATE int sqlite3WhereIsDistinct(WhereInfo*);
SQLITE_PRIVATE int sqlite3WhereIsOrdered(WhereInfo*);
SQLITE_PRIVATE int sqlite3WhereOrderByLimitOptLabel(WhereInfo*);
+SQLITE_PRIVATE void sqlite3WhereMinMaxOptEarlyOut(Vdbe*,WhereInfo*);
SQLITE_PRIVATE int sqlite3WhereIsSorted(WhereInfo*);
SQLITE_PRIVATE int sqlite3WhereContinueLabel(WhereInfo*);
SQLITE_PRIVATE int sqlite3WhereBreakLabel(WhereInfo*);
@@ -18666,17 +20062,20 @@ SQLITE_PRIVATE int sqlite3WhereOkOnePass(WhereInfo*, int*);
#define ONEPASS_OFF 0 /* Use of ONEPASS not allowed */
#define ONEPASS_SINGLE 1 /* ONEPASS valid for a single row update */
#define ONEPASS_MULTI 2 /* ONEPASS is valid for multiple rows */
+SQLITE_PRIVATE int sqlite3WhereUsesDeferredSeek(WhereInfo*);
SQLITE_PRIVATE void sqlite3ExprCodeLoadIndexColumn(Parse*, Index*, int, int, int);
SQLITE_PRIVATE int sqlite3ExprCodeGetColumn(Parse*, Table*, int, int, int, u8);
SQLITE_PRIVATE void sqlite3ExprCodeGetColumnOfTable(Vdbe*, Table*, int, int, int);
SQLITE_PRIVATE void sqlite3ExprCodeMove(Parse*, int, int, int);
SQLITE_PRIVATE void sqlite3ExprCode(Parse*, Expr*, int);
+#ifndef SQLITE_OMIT_GENERATED_COLUMNS
+SQLITE_PRIVATE void sqlite3ExprCodeGeneratedColumn(Parse*, Column*, int);
+#endif
SQLITE_PRIVATE void sqlite3ExprCodeCopy(Parse*, Expr*, int);
SQLITE_PRIVATE void sqlite3ExprCodeFactorable(Parse*, Expr*, int);
-SQLITE_PRIVATE int sqlite3ExprCodeAtInit(Parse*, Expr*, int);
+SQLITE_PRIVATE int sqlite3ExprCodeRunJustOnce(Parse*, Expr*, int);
SQLITE_PRIVATE int sqlite3ExprCodeTemp(Parse*, Expr*, int*);
SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse*, Expr*, int);
-SQLITE_PRIVATE void sqlite3ExprCodeAndCache(Parse*, Expr*, int);
SQLITE_PRIVATE int sqlite3ExprCodeExprList(Parse*, ExprList*, int, int, u8);
#define SQLITE_ECEL_DUP 0x01 /* Deep, not shallow copies */
#define SQLITE_ECEL_FACTOR 0x02 /* Factor out constant terms */
@@ -18689,18 +20088,19 @@ SQLITE_PRIVATE Table *sqlite3FindTable(sqlite3*,const char*, const char*);
#define LOCATE_VIEW 0x01
#define LOCATE_NOERR 0x02
SQLITE_PRIVATE Table *sqlite3LocateTable(Parse*,u32 flags,const char*, const char*);
-SQLITE_PRIVATE Table *sqlite3LocateTableItem(Parse*,u32 flags,struct SrcList_item *);
+SQLITE_PRIVATE Table *sqlite3LocateTableItem(Parse*,u32 flags,SrcItem *);
SQLITE_PRIVATE Index *sqlite3FindIndex(sqlite3*,const char*, const char*);
SQLITE_PRIVATE void sqlite3UnlinkAndDeleteTable(sqlite3*,int,const char*);
SQLITE_PRIVATE void sqlite3UnlinkAndDeleteIndex(sqlite3*,int,const char*);
-SQLITE_PRIVATE void sqlite3Vacuum(Parse*,Token*);
-SQLITE_PRIVATE int sqlite3RunVacuum(char**, sqlite3*, int);
+SQLITE_PRIVATE void sqlite3Vacuum(Parse*,Token*,Expr*);
+SQLITE_PRIVATE int sqlite3RunVacuum(char**, sqlite3*, int, sqlite3_value*);
SQLITE_PRIVATE char *sqlite3NameFromToken(sqlite3*, Token*);
SQLITE_PRIVATE int sqlite3ExprCompare(Parse*,Expr*, Expr*, int);
SQLITE_PRIVATE int sqlite3ExprCompareSkip(Expr*, Expr*, int);
SQLITE_PRIVATE int sqlite3ExprListCompare(ExprList*, ExprList*, int);
SQLITE_PRIVATE int sqlite3ExprImpliesExpr(Parse*,Expr*, Expr*, int);
SQLITE_PRIVATE int sqlite3ExprImpliesNonNullRow(Expr*,int);
+SQLITE_PRIVATE void sqlite3AggInfoPersistWalkerInit(Walker*,Parse*);
SQLITE_PRIVATE void sqlite3ExprAnalyzeAggregates(NameContext*, Expr*);
SQLITE_PRIVATE void sqlite3ExprAnalyzeAggList(NameContext*,ExprList*);
SQLITE_PRIVATE int sqlite3ExprCoveredByIndex(Expr*, int iCur, Index *pIdx);
@@ -18718,6 +20118,7 @@ SQLITE_PRIVATE void sqlite3EndTransaction(Parse*,int);
SQLITE_PRIVATE void sqlite3Savepoint(Parse*, int, Token*);
SQLITE_PRIVATE void sqlite3CloseSavepoints(sqlite3 *);
SQLITE_PRIVATE void sqlite3LeaveMutexAndCloseZombie(sqlite3*);
+SQLITE_PRIVATE u32 sqlite3IsTrueOrFalse(const char*);
SQLITE_PRIVATE int sqlite3ExprIdToTrueFalse(Expr*);
SQLITE_PRIVATE int sqlite3ExprTruthValue(const Expr*);
SQLITE_PRIVATE int sqlite3ExprIsConstant(Expr*);
@@ -18737,6 +20138,7 @@ SQLITE_PRIVATE void sqlite3GenerateRowDelete(
SQLITE_PRIVATE void sqlite3GenerateRowIndexDelete(Parse*, Table*, int, int, int*, int);
SQLITE_PRIVATE int sqlite3GenerateIndexKey(Parse*, Index*, int, int, int, int*,Index*,int);
SQLITE_PRIVATE void sqlite3ResolvePartIdxLabel(Parse*,int);
+SQLITE_PRIVATE int sqlite3ExprReferencesUpdatedColumn(Expr*,int*,int);
SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(Parse*,Table*,int*,int,int,int,int,
u8,u8,int,int*,int*,Upsert*);
#ifdef SQLITE_ENABLE_NULL_TRIM
@@ -18757,6 +20159,7 @@ SQLITE_PRIVATE ExprList *sqlite3ExprListDup(sqlite3*,ExprList*,int);
SQLITE_PRIVATE SrcList *sqlite3SrcListDup(sqlite3*,SrcList*,int);
SQLITE_PRIVATE IdList *sqlite3IdListDup(sqlite3*,IdList*);
SQLITE_PRIVATE Select *sqlite3SelectDup(sqlite3*,Select*,int);
+SQLITE_PRIVATE FuncDef *sqlite3FunctionSearch(int,const char*);
SQLITE_PRIVATE void sqlite3InsertBuiltinFuncs(FuncDef*,int);
SQLITE_PRIVATE FuncDef *sqlite3FindFunction(sqlite3*,const char*,int,u8,u8);
SQLITE_PRIVATE void sqlite3RegisterBuiltinFunctions(void);
@@ -18765,6 +20168,7 @@ SQLITE_PRIVATE void sqlite3RegisterPerConnectionBuiltinFunctions(sqlite3*);
SQLITE_PRIVATE int sqlite3SafetyCheckOk(sqlite3*);
SQLITE_PRIVATE int sqlite3SafetyCheckSickOrOk(sqlite3*);
SQLITE_PRIVATE void sqlite3ChangeCookie(Parse*, int);
+SQLITE_PRIVATE With *sqlite3WithDup(sqlite3 *db, With *p);
#if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER)
SQLITE_PRIVATE void sqlite3MaterializeView(Parse*, Table*, Expr*, ExprList*,Expr*,int);
@@ -18788,13 +20192,14 @@ SQLITE_PRIVATE TriggerStep *sqlite3TriggerSelectStep(sqlite3*,Select*,
SQLITE_PRIVATE TriggerStep *sqlite3TriggerInsertStep(Parse*,Token*, IdList*,
Select*,u8,Upsert*,
const char*,const char*);
-SQLITE_PRIVATE TriggerStep *sqlite3TriggerUpdateStep(Parse*,Token*,ExprList*, Expr*, u8,
- const char*,const char*);
+SQLITE_PRIVATE TriggerStep *sqlite3TriggerUpdateStep(Parse*,Token*,SrcList*,ExprList*,
+ Expr*, u8, const char*,const char*);
SQLITE_PRIVATE TriggerStep *sqlite3TriggerDeleteStep(Parse*,Token*, Expr*,
const char*,const char*);
SQLITE_PRIVATE void sqlite3DeleteTrigger(sqlite3*, Trigger*);
SQLITE_PRIVATE void sqlite3UnlinkAndDeleteTrigger(sqlite3*,int,const char*);
SQLITE_PRIVATE u32 sqlite3TriggerColmask(Parse*,Trigger*,ExprList*,int,int,Table*,int);
+SQLITE_PRIVATE SrcList *sqlite3TriggerStepSrc(Parse*, TriggerStep*);
# define sqlite3ParseToplevel(p) ((p)->pToplevel ? (p)->pToplevel : (p))
# define sqlite3IsToplevel(p) ((p)->pToplevel==0)
#else
@@ -18808,9 +20213,12 @@ SQLITE_PRIVATE u32 sqlite3TriggerColmask(Parse*,Trigger*,ExprList*,int,int,Tab
# define sqlite3ParseToplevel(p) p
# define sqlite3IsToplevel(p) 1
# define sqlite3TriggerColmask(A,B,C,D,E,F,G) 0
+# define sqlite3TriggerStepSrc(A,B) 0
#endif
SQLITE_PRIVATE int sqlite3JoinType(Parse*, Token*, Token*, Token*);
+SQLITE_PRIVATE int sqlite3ColumnIndex(Table *pTab, const char *zCol);
+SQLITE_PRIVATE void sqlite3SetJoinExpr(Expr*,int);
SQLITE_PRIVATE void sqlite3CreateForeignKey(Parse*, ExprList*, Token*, ExprList*, int);
SQLITE_PRIVATE void sqlite3DeferForeignKey(Parse*, int);
#ifndef SQLITE_OMIT_AUTHORIZATION
@@ -18825,16 +20233,19 @@ SQLITE_PRIVATE int sqlite3AuthReadCol(Parse*, const char *, const char *, int)
# define sqlite3AuthContextPush(a,b,c)
# define sqlite3AuthContextPop(a) ((void)(a))
#endif
+SQLITE_PRIVATE int sqlite3DbIsNamed(sqlite3 *db, int iDb, const char *zName);
SQLITE_PRIVATE void sqlite3Attach(Parse*, Expr*, Expr*, Expr*);
SQLITE_PRIVATE void sqlite3Detach(Parse*, Expr*);
SQLITE_PRIVATE void sqlite3FixInit(DbFixer*, Parse*, int, const char*, const Token*);
SQLITE_PRIVATE int sqlite3FixSrcList(DbFixer*, SrcList*);
SQLITE_PRIVATE int sqlite3FixSelect(DbFixer*, Select*);
SQLITE_PRIVATE int sqlite3FixExpr(DbFixer*, Expr*);
-SQLITE_PRIVATE int sqlite3FixExprList(DbFixer*, ExprList*);
SQLITE_PRIVATE int sqlite3FixTriggerStep(DbFixer*, TriggerStep*);
+SQLITE_PRIVATE int sqlite3RealSameAsInt(double,sqlite3_int64);
+SQLITE_PRIVATE void sqlite3Int64ToText(i64,char*);
SQLITE_PRIVATE int sqlite3AtoF(const char *z, double*, int, u8);
SQLITE_PRIVATE int sqlite3GetInt32(const char *, int*);
+SQLITE_PRIVATE int sqlite3GetUInt32(const char*, u32*);
SQLITE_PRIVATE int sqlite3Atoi(const char*);
#ifndef SQLITE_OMIT_UTF16
SQLITE_PRIVATE int sqlite3Utf16ByteLen(const void *pData, int nChar);
@@ -18847,7 +20258,7 @@ SQLITE_PRIVATE LogEst sqlite3LogEstAdd(LogEst,LogEst);
SQLITE_PRIVATE LogEst sqlite3LogEstFromDouble(double);
#endif
#if defined(SQLITE_ENABLE_STMT_SCANSTATUS) || \
- defined(SQLITE_ENABLE_STAT3_OR_STAT4) || \
+ defined(SQLITE_ENABLE_STAT4) || \
defined(SQLITE_EXPLAIN_ESTIMATED_ROWS)
SQLITE_PRIVATE u64 sqlite3LogEstToInt(LogEst);
#endif
@@ -18872,6 +20283,8 @@ SQLITE_PRIVATE int sqlite3VarintLen(u64 v);
*/
#define getVarint32(A,B) \
(u8)((*(A)<(u8)0x80)?((B)=(u32)*(A)),1:sqlite3GetVarint32((A),(u32 *)&(B)))
+#define getVarint32NR(A,B) \
+ B=(u32)*(A);if(B>=0x80)sqlite3GetVarint32((A),(u32*)&(B))
#define putVarint32(A,B) \
(u8)(((u32)(B)<(u32)0x80)?(*(A)=(unsigned char)(B)),1:\
sqlite3PutVarint((A),(B)))
@@ -18881,14 +20294,15 @@ SQLITE_PRIVATE int sqlite3VarintLen(u64 v);
SQLITE_PRIVATE const char *sqlite3IndexAffinityStr(sqlite3*, Index*);
SQLITE_PRIVATE void sqlite3TableAffinity(Vdbe*, Table*, int);
-SQLITE_PRIVATE char sqlite3CompareAffinity(Expr *pExpr, char aff2);
-SQLITE_PRIVATE int sqlite3IndexAffinityOk(Expr *pExpr, char idx_affinity);
+SQLITE_PRIVATE char sqlite3CompareAffinity(const Expr *pExpr, char aff2);
+SQLITE_PRIVATE int sqlite3IndexAffinityOk(const Expr *pExpr, char idx_affinity);
SQLITE_PRIVATE char sqlite3TableColumnAffinity(Table*,int);
-SQLITE_PRIVATE char sqlite3ExprAffinity(Expr *pExpr);
+SQLITE_PRIVATE char sqlite3ExprAffinity(const Expr *pExpr);
SQLITE_PRIVATE int sqlite3Atoi64(const char*, i64*, int, u8);
SQLITE_PRIVATE int sqlite3DecOrHexToI64(const char*, i64*);
SQLITE_PRIVATE void sqlite3ErrorWithMsg(sqlite3*, int, const char*,...);
SQLITE_PRIVATE void sqlite3Error(sqlite3*,int);
+SQLITE_PRIVATE void sqlite3ErrorClear(sqlite3*);
SQLITE_PRIVATE void sqlite3SystemError(sqlite3*,int);
SQLITE_PRIVATE void *sqlite3HexToBlob(sqlite3*, const char *z, int n);
SQLITE_PRIVATE u8 sqlite3HexToInt(int h);
@@ -18898,7 +20312,7 @@ SQLITE_PRIVATE int sqlite3TwoPartName(Parse *, Token *, Token *, Token **);
SQLITE_PRIVATE const char *sqlite3ErrName(int);
#endif
-#ifdef SQLITE_ENABLE_DESERIALIZE
+#ifndef SQLITE_OMIT_DESERIALIZE
SQLITE_PRIVATE int sqlite3MemdbInit(void);
#endif
@@ -18907,14 +20321,17 @@ SQLITE_PRIVATE int sqlite3ReadSchema(Parse *pParse);
SQLITE_PRIVATE CollSeq *sqlite3FindCollSeq(sqlite3*,u8 enc, const char*,int);
SQLITE_PRIVATE int sqlite3IsBinary(const CollSeq*);
SQLITE_PRIVATE CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char*zName);
-SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr);
-SQLITE_PRIVATE CollSeq *sqlite3ExprNNCollSeq(Parse *pParse, Expr *pExpr);
-SQLITE_PRIVATE int sqlite3ExprCollSeqMatch(Parse*,Expr*,Expr*);
+SQLITE_PRIVATE void sqlite3SetTextEncoding(sqlite3 *db, u8);
+SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, const Expr *pExpr);
+SQLITE_PRIVATE CollSeq *sqlite3ExprNNCollSeq(Parse *pParse, const Expr *pExpr);
+SQLITE_PRIVATE int sqlite3ExprCollSeqMatch(Parse*,const Expr*,const Expr*);
SQLITE_PRIVATE Expr *sqlite3ExprAddCollateToken(Parse *pParse, Expr*, const Token*, int);
SQLITE_PRIVATE Expr *sqlite3ExprAddCollateString(Parse*,Expr*,const char*);
SQLITE_PRIVATE Expr *sqlite3ExprSkipCollate(Expr*);
+SQLITE_PRIVATE Expr *sqlite3ExprSkipCollateAndLikely(Expr*);
SQLITE_PRIVATE int sqlite3CheckCollSeq(Parse *, CollSeq *);
-SQLITE_PRIVATE int sqlite3CheckObjectName(Parse *, const char *);
+SQLITE_PRIVATE int sqlite3WritableSchema(sqlite3*);
+SQLITE_PRIVATE int sqlite3CheckObjectName(Parse*, const char*,const char*,const char*);
SQLITE_PRIVATE void sqlite3VdbeSetChanges(sqlite3 *, int);
SQLITE_PRIVATE int sqlite3AddInt64(i64*,i64);
SQLITE_PRIVATE int sqlite3SubInt64(i64*,i64);
@@ -18933,6 +20350,9 @@ SQLITE_PRIVATE void sqlite3ValueSetStr(sqlite3_value*, int, const void *,u8,
void(*)(void*));
SQLITE_PRIVATE void sqlite3ValueSetNull(sqlite3_value*);
SQLITE_PRIVATE void sqlite3ValueFree(sqlite3_value*);
+#ifndef SQLITE_UNTESTABLE
+SQLITE_PRIVATE void sqlite3ResultIntReal(sqlite3_context*);
+#endif
SQLITE_PRIVATE sqlite3_value *sqlite3ValueNew(sqlite3 *);
#ifndef SQLITE_OMIT_UTF16
SQLITE_PRIVATE char *sqlite3Utf16to8(sqlite3 *, const void*, int, u8);
@@ -18943,18 +20363,20 @@ SQLITE_PRIVATE void sqlite3ValueApplyAffinity(sqlite3_value *, u8, u8);
SQLITE_PRIVATE const unsigned char sqlite3OpcodeProperty[];
SQLITE_PRIVATE const char sqlite3StrBINARY[];
SQLITE_PRIVATE const unsigned char sqlite3UpperToLower[];
+SQLITE_PRIVATE const unsigned char *sqlite3aLTb;
+SQLITE_PRIVATE const unsigned char *sqlite3aEQb;
+SQLITE_PRIVATE const unsigned char *sqlite3aGTb;
SQLITE_PRIVATE const unsigned char sqlite3CtypeMap[];
-SQLITE_PRIVATE const Token sqlite3IntTokens[];
SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlite3Config;
SQLITE_PRIVATE FuncDefHash sqlite3BuiltinFunctions;
#ifndef SQLITE_OMIT_WSD
SQLITE_PRIVATE int sqlite3PendingByte;
#endif
-#endif
+#endif /* SQLITE_AMALGAMATION */
#ifdef VDBE_PROFILE
SQLITE_PRIVATE sqlite3_uint64 sqlite3NProfileCnt;
#endif
-SQLITE_PRIVATE void sqlite3RootPageMoved(sqlite3*, int, int, int);
+SQLITE_PRIVATE void sqlite3RootPageMoved(sqlite3*, int, Pgno, Pgno);
SQLITE_PRIVATE void sqlite3Reindex(Parse*, Token*, Token*);
SQLITE_PRIVATE void sqlite3AlterFunctions(void);
SQLITE_PRIVATE void sqlite3AlterRenameTable(Parse*, SrcList*, Token*);
@@ -18962,18 +20384,28 @@ SQLITE_PRIVATE void sqlite3AlterRenameColumn(Parse*, SrcList*, Token*, Token*);
SQLITE_PRIVATE int sqlite3GetToken(const unsigned char *, int *);
SQLITE_PRIVATE void sqlite3NestedParse(Parse*, const char*, ...);
SQLITE_PRIVATE void sqlite3ExpirePreparedStatements(sqlite3*, int);
-SQLITE_PRIVATE int sqlite3CodeSubselect(Parse*, Expr *, int, int);
+SQLITE_PRIVATE void sqlite3CodeRhsOfIN(Parse*, Expr*, int);
+SQLITE_PRIVATE int sqlite3CodeSubselect(Parse*, Expr*);
SQLITE_PRIVATE void sqlite3SelectPrep(Parse*, Select*, NameContext*);
+SQLITE_PRIVATE int sqlite3ExpandSubquery(Parse*, SrcItem*);
SQLITE_PRIVATE void sqlite3SelectWrongNumTermsError(Parse *pParse, Select *p);
-SQLITE_PRIVATE int sqlite3MatchSpanName(const char*, const char*, const char*, const char*);
+SQLITE_PRIVATE int sqlite3MatchEName(
+ const struct ExprList_item*,
+ const char*,
+ const char*,
+ const char*
+);
+SQLITE_PRIVATE Bitmask sqlite3ExprColUsed(Expr*);
+SQLITE_PRIVATE u8 sqlite3StrIHash(const char*);
SQLITE_PRIVATE int sqlite3ResolveExprNames(NameContext*, Expr*);
SQLITE_PRIVATE int sqlite3ResolveExprListNames(NameContext*, ExprList*);
SQLITE_PRIVATE void sqlite3ResolveSelectNames(Parse*, Select*, NameContext*);
-SQLITE_PRIVATE void sqlite3ResolveSelfReference(Parse*,Table*,int,Expr*,ExprList*);
+SQLITE_PRIVATE int sqlite3ResolveSelfReference(Parse*,Table*,int,Expr*,ExprList*);
SQLITE_PRIVATE int sqlite3ResolveOrderGroupBy(Parse*, Select*, ExprList*, const char*);
SQLITE_PRIVATE void sqlite3ColumnDefault(Vdbe *, Table *, int, int);
SQLITE_PRIVATE void sqlite3AlterFinishAddColumn(Parse *, Token *);
SQLITE_PRIVATE void sqlite3AlterBeginAddColumn(Parse *, SrcList *);
+SQLITE_PRIVATE void sqlite3AlterDropColumn(Parse*, SrcList*, Token*);
SQLITE_PRIVATE void *sqlite3RenameTokenMap(Parse*, void*, Token*);
SQLITE_PRIVATE void sqlite3RenameTokenRemap(Parse*, void *pTo, void *pFrom);
SQLITE_PRIVATE void sqlite3RenameExprUnmap(Parse*, Expr*);
@@ -18981,7 +20413,7 @@ SQLITE_PRIVATE void sqlite3RenameExprlistUnmap(Parse*, ExprList*);
SQLITE_PRIVATE CollSeq *sqlite3GetCollSeq(Parse*, u8, CollSeq *, const char*);
SQLITE_PRIVATE char sqlite3AffinityType(const char*, Column*);
SQLITE_PRIVATE void sqlite3Analyze(Parse*, Token*, Token*);
-SQLITE_PRIVATE int sqlite3InvokeBusyHandler(BusyHandler*, sqlite3_file*);
+SQLITE_PRIVATE int sqlite3InvokeBusyHandler(BusyHandler*);
SQLITE_PRIVATE int sqlite3FindDb(sqlite3*, Token*);
SQLITE_PRIVATE int sqlite3FindDbName(sqlite3 *, const char *);
SQLITE_PRIVATE int sqlite3AnalysisLoad(sqlite3*,int iDB);
@@ -18997,16 +20429,18 @@ SQLITE_PRIVATE void sqlite3KeyInfoUnref(KeyInfo*);
SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoRef(KeyInfo*);
SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoOfIndex(Parse*, Index*);
SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoFromExprList(Parse*, ExprList*, int, int);
+SQLITE_PRIVATE const char *sqlite3SelectOpName(int);
+SQLITE_PRIVATE int sqlite3HasExplicitNulls(Parse*, ExprList*);
#ifdef SQLITE_DEBUG
SQLITE_PRIVATE int sqlite3KeyInfoIsWriteable(KeyInfo*);
#endif
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*,int,sqlite3_value **),
void (*)(sqlite3_context*),
void (*)(sqlite3_context*),
- void (*)(sqlite3_context*,int,sqlite3_value **),
+ void (*)(sqlite3_context*,int,sqlite3_value **),
FuncDestructor *pDestructor
);
SQLITE_PRIVATE void sqlite3NoopDestructor(void*);
@@ -19029,8 +20463,7 @@ SQLITE_PRIVATE int sqlite3ExprCheckIN(Parse*, Expr*);
# define sqlite3ExprCheckIN(x,y) SQLITE_OK
#endif
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
-SQLITE_PRIVATE void sqlite3AnalyzeFunctions(void);
+#ifdef SQLITE_ENABLE_STAT4
SQLITE_PRIVATE int sqlite3Stat4ProbeSetValue(
Parse*,Index*,UnpackedRecord**,Expr*,int,int,int*);
SQLITE_PRIVATE int sqlite3Stat4ValueFromExpr(Parse*, Expr*, u8, sqlite3_value**);
@@ -19060,7 +20493,7 @@ SQLITE_PRIVATE void sqlite3CloseExtensions(sqlite3*);
#endif
#ifndef SQLITE_OMIT_SHARED_CACHE
-SQLITE_PRIVATE void sqlite3TableLock(Parse *, int, int, u8, const char *);
+SQLITE_PRIVATE void sqlite3TableLock(Parse *, int, Pgno, u8, const char *);
#else
#define sqlite3TableLock(v,w,x,y,z)
#endif
@@ -19077,6 +20510,7 @@ SQLITE_PRIVATE int sqlite3Utf8To8(unsigned char*);
# define sqlite3VtabInSync(db) 0
# define sqlite3VtabLock(X)
# define sqlite3VtabUnlock(X)
+# define sqlite3VtabModuleUnref(D,X)
# define sqlite3VtabUnlockList(X)
# define sqlite3VtabSavepoint(X, Y, Z) SQLITE_OK
# define sqlite3GetVTable(X,Y) ((VTable*)0)
@@ -19088,6 +20522,7 @@ SQLITE_PRIVATE int sqlite3VtabRollback(sqlite3 *db);
SQLITE_PRIVATE int sqlite3VtabCommit(sqlite3 *db);
SQLITE_PRIVATE void sqlite3VtabLock(VTable *);
SQLITE_PRIVATE void sqlite3VtabUnlock(VTable *);
+SQLITE_PRIVATE void sqlite3VtabModuleUnref(sqlite3*,Module*);
SQLITE_PRIVATE void sqlite3VtabUnlockList(sqlite3*);
SQLITE_PRIVATE int sqlite3VtabSavepoint(sqlite3 *, int, int);
SQLITE_PRIVATE void sqlite3VtabImportErrmsg(Vdbe*, sqlite3_vtab*);
@@ -19101,6 +20536,14 @@ SQLITE_PRIVATE Module *sqlite3VtabCreateModule(
);
# define sqlite3VtabInSync(db) ((db)->nVTrans>0 && (db)->aVTrans==0)
#endif
+SQLITE_PRIVATE int sqlite3ReadOnlyShadowTables(sqlite3 *db);
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+SQLITE_PRIVATE int sqlite3ShadowTableName(sqlite3 *db, const char *zName);
+SQLITE_PRIVATE int sqlite3IsShadowTableOf(sqlite3*,Table*,const char*);
+#else
+# define sqlite3ShadowTableName(A,B) 0
+# define sqlite3IsShadowTableOf(A,B,C) 0
+#endif
SQLITE_PRIVATE int sqlite3VtabEponymousTableInit(Parse*,Module*);
SQLITE_PRIVATE void sqlite3VtabEponymousTableClear(sqlite3*,Module*);
SQLITE_PRIVATE void sqlite3VtabMakeWritable(Parse*,Table*);
@@ -19117,9 +20560,14 @@ SQLITE_PRIVATE sqlite3_int64 sqlite3StmtCurrentTime(sqlite3_context*);
SQLITE_PRIVATE int sqlite3VdbeParameterIndex(Vdbe*, const char*, int);
SQLITE_PRIVATE int sqlite3TransferBindings(sqlite3_stmt *, sqlite3_stmt *);
SQLITE_PRIVATE void sqlite3ParserReset(Parse*);
+SQLITE_PRIVATE void *sqlite3ParserAddCleanup(Parse*,void(*)(sqlite3*,void*),void*);
+#ifdef SQLITE_ENABLE_NORMALIZE
+SQLITE_PRIVATE char *sqlite3Normalize(Vdbe*, const char*);
+#endif
SQLITE_PRIVATE int sqlite3Reprepare(Vdbe*);
SQLITE_PRIVATE void sqlite3ExprListCheckLength(Parse*, ExprList*, const char*);
-SQLITE_PRIVATE CollSeq *sqlite3BinaryCompareCollSeq(Parse *, Expr *, Expr *);
+SQLITE_PRIVATE CollSeq *sqlite3ExprCompareCollSeq(Parse*,const Expr*);
+SQLITE_PRIVATE CollSeq *sqlite3BinaryCompareCollSeq(Parse *, const Expr*, const Expr*);
SQLITE_PRIVATE int sqlite3TempInMemory(const sqlite3*);
SQLITE_PRIVATE const char *sqlite3JournalModename(int);
#ifndef SQLITE_OMIT_WAL
@@ -19127,23 +20575,32 @@ SQLITE_PRIVATE int sqlite3Checkpoint(sqlite3*, int, int, int*, int*);
SQLITE_PRIVATE int sqlite3WalDefaultHook(void*,sqlite3*,const char*,int);
#endif
#ifndef SQLITE_OMIT_CTE
-SQLITE_PRIVATE With *sqlite3WithAdd(Parse*,With*,Token*,ExprList*,Select*);
+SQLITE_PRIVATE Cte *sqlite3CteNew(Parse*,Token*,ExprList*,Select*,u8);
+SQLITE_PRIVATE void sqlite3CteDelete(sqlite3*,Cte*);
+SQLITE_PRIVATE With *sqlite3WithAdd(Parse*,With*,Cte*);
SQLITE_PRIVATE void sqlite3WithDelete(sqlite3*,With*);
-SQLITE_PRIVATE void sqlite3WithPush(Parse*, With*, u8);
+SQLITE_PRIVATE With *sqlite3WithPush(Parse*, With*, u8);
#else
-#define sqlite3WithPush(x,y,z)
-#define sqlite3WithDelete(x,y)
+# define sqlite3CteNew(P,T,E,S) ((void*)0)
+# define sqlite3CteDelete(D,C)
+# define sqlite3CteWithAdd(P,W,C) ((void*)0)
+# define sqlite3WithDelete(x,y)
+# define sqlite3WithPush(x,y,z)
#endif
#ifndef SQLITE_OMIT_UPSERT
-SQLITE_PRIVATE Upsert *sqlite3UpsertNew(sqlite3*,ExprList*,Expr*,ExprList*,Expr*);
+SQLITE_PRIVATE Upsert *sqlite3UpsertNew(sqlite3*,ExprList*,Expr*,ExprList*,Expr*,Upsert*);
SQLITE_PRIVATE void sqlite3UpsertDelete(sqlite3*,Upsert*);
SQLITE_PRIVATE Upsert *sqlite3UpsertDup(sqlite3*,Upsert*);
SQLITE_PRIVATE int sqlite3UpsertAnalyzeTarget(Parse*,SrcList*,Upsert*);
SQLITE_PRIVATE void sqlite3UpsertDoUpdate(Parse*,Upsert*,Table*,Index*,int);
+SQLITE_PRIVATE Upsert *sqlite3UpsertOfIndex(Upsert*,Index*);
+SQLITE_PRIVATE int sqlite3UpsertNextIsIPK(Upsert*);
#else
-#define sqlite3UpsertNew(v,w,x,y,z) ((Upsert*)0)
+#define sqlite3UpsertNew(u,v,w,x,y,z) ((Upsert*)0)
#define sqlite3UpsertDelete(x,y)
-#define sqlite3UpsertDup(x,y) ((Upsert*)0)
+#define sqlite3UpsertDup(x,y) ((Upsert*)0)
+#define sqlite3UpsertOfIndex(x,y) ((Upsert*)0)
+#define sqlite3UpsertNextIsIPK(x) 0
#endif
@@ -19211,7 +20668,7 @@ SQLITE_PRIVATE void sqlite3EndBenignMalloc(void);
#define IN_INDEX_NOOP_OK 0x0001 /* OK to return IN_INDEX_NOOP */
#define IN_INDEX_MEMBERSHIP 0x0002 /* IN operator used for membership test */
#define IN_INDEX_LOOP 0x0004 /* IN operator used as a loop */
-SQLITE_PRIVATE int sqlite3FindInIndex(Parse *, Expr *, u32, int*, int*);
+SQLITE_PRIVATE int sqlite3FindInIndex(Parse *, Expr *, u32, int*, int*, int*);
SQLITE_PRIVATE int sqlite3JournalOpen(sqlite3_vfs *, const char *, sqlite3_file *, int, int);
SQLITE_PRIVATE int sqlite3JournalSize(sqlite3_vfs *);
@@ -19353,7 +20810,7 @@ SQLITE_PRIVATE const char **sqlite3CompileOptions(int *pnOpt);
/* #include "sqliteInt.h" */
/* 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
@@ -19375,7 +20832,7 @@ SQLITE_PRIVATE const unsigned char sqlite3UpperToLower[] = {
198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,
216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,
234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,
- 252,253,254,255
+ 252,253,254,255,
#endif
#ifdef SQLITE_EBCDIC
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, /* 0x */
@@ -19395,7 +20852,35 @@ SQLITE_PRIVATE const unsigned char sqlite3UpperToLower[] = {
224,225,162,163,164,165,166,167,168,169,234,235,236,237,238,239, /* Ex */
240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255, /* Fx */
#endif
+/* All of the upper-to-lower conversion data is above. The following
+** 18 integers are completely unrelated. They are appended to the
+** sqlite3UpperToLower[] array to avoid UBSAN warnings. Here's what is
+** going on:
+**
+** The SQL comparison operators (<>, =, >, <=, <, and >=) are implemented
+** by invoking sqlite3MemCompare(A,B) which compares values A and B and
+** returns negative, zero, or positive if A is less then, equal to, or
+** greater than B, respectively. Then the true false results is found by
+** consulting sqlite3aLTb[opcode], sqlite3aEQb[opcode], or
+** sqlite3aGTb[opcode] depending on whether the result of compare(A,B)
+** is negative, zero, or positive, where opcode is the specific opcode.
+** The only works because the comparison opcodes are consecutive and in
+** this order: NE EQ GT LE LT GE. Various assert()s throughout the code
+** ensure that is the case.
+**
+** These elements must be appended to another array. Otherwise the
+** index (here shown as [256-OP_Ne]) would be out-of-bounds and thus
+** be undefined behavior. That's goofy, but the C-standards people thought
+** it was a good idea, so here we are.
+*/
+/* NE EQ GT LE LT GE */
+ 1, 0, 0, 1, 1, 0, /* aLTb[]: Use when compare(A,B) less than zero */
+ 0, 1, 0, 1, 0, 1, /* aEQb[]: Use when compare(A,B) equals zero */
+ 1, 0, 1, 0, 0, 1 /* aGTb[]: Use when compare(A,B) greater than zero*/
};
+SQLITE_PRIVATE const unsigned char *sqlite3aLTb = &sqlite3UpperToLower[256-OP_Ne];
+SQLITE_PRIVATE const unsigned char *sqlite3aEQb = &sqlite3UpperToLower[256+6-OP_Ne];
+SQLITE_PRIVATE const unsigned char *sqlite3aGTb = &sqlite3UpperToLower[256+12-OP_Ne];
/*
** The following 256 byte lookup table is used to support SQLites built-in
@@ -19420,12 +20905,11 @@ SQLITE_PRIVATE const unsigned char sqlite3UpperToLower[] = {
** The equivalent of tolower() is implemented using the sqlite3UpperToLower[]
** array. tolower() is used more often than toupper() by SQLite.
**
-** Bit 0x40 is set if the character is non-alphanumeric and can be used in an
+** Bit 0x40 is set if the character is 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.
*/
-#ifdef SQLITE_ASCII
SQLITE_PRIVATE const unsigned char sqlite3CtypeMap[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 00..07 ........ */
0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, /* 08..0f ........ */
@@ -19463,7 +20947,6 @@ SQLITE_PRIVATE const unsigned char sqlite3CtypeMap[256] = {
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* f0..f7 ........ */
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40 /* f8..ff ........ */
};
-#endif
/* EVIDENCE-OF: R-02982-34736 In order to maintain full backwards
** compatibility for legacy applications, the URI filename capability is
@@ -19475,24 +20958,24 @@ SQLITE_PRIVATE const unsigned char sqlite3CtypeMap[256] = {
** EVIDENCE-OF: R-43642-56306 By default, URI handling is globally
** disabled. The default value may be changed by compiling with the
** SQLITE_USE_URI symbol defined.
-**
-** URI filenames are enabled by default if SQLITE_HAS_CODEC is
-** enabled.
*/
#ifndef SQLITE_USE_URI
-# ifdef SQLITE_HAS_CODEC
-# define SQLITE_USE_URI 1
-# else
-# define SQLITE_USE_URI 0
-# endif
+# define SQLITE_USE_URI 0
#endif
/* EVIDENCE-OF: R-38720-18127 The default setting is determined by the
** SQLITE_ALLOW_COVERING_INDEX_SCAN compile-time option, or is "on" if
** that compile-time option is omitted.
*/
-#ifndef SQLITE_ALLOW_COVERING_INDEX_SCAN
+#if !defined(SQLITE_ALLOW_COVERING_INDEX_SCAN)
# define SQLITE_ALLOW_COVERING_INDEX_SCAN 1
+#else
+# if !SQLITE_ALLOW_COVERING_INDEX_SCAN
+# error "Compile-time disabling of covering index scan using the\
+ -DSQLITE_ALLOW_COVERING_INDEX_SCAN=0 option is deprecated.\
+ Contact SQLite developers if this is a problem for you, and\
+ delete this #error macro to continue with your build."
+# endif
#endif
/* The minimum PMA size is set to this value multiplied by the database
@@ -19510,7 +20993,7 @@ SQLITE_PRIVATE const unsigned char sqlite3CtypeMap[256] = {
** if journal_mode=MEMORY or if temp_store=MEMORY, regardless of this
** setting.)
*/
-#ifndef SQLITE_STMTJRNL_SPILL
+#ifndef SQLITE_STMTJRNL_SPILL
# define SQLITE_STMTJRNL_SPILL (64*1024)
#endif
@@ -19521,12 +21004,28 @@ SQLITE_PRIVATE const unsigned char sqlite3CtypeMap[256] = {
** changed as start-time using sqlite3_config(SQLITE_CONFIG_LOOKASIDE)
** or at run-time for an individual database connection using
** sqlite3_db_config(db, SQLITE_DBCONFIG_LOOKASIDE);
+**
+** With the two-size-lookaside enhancement, less lookaside is required.
+** The default configuration of 1200,40 actually provides 30 1200-byte slots
+** and 93 128-byte slots, which is more lookaside than is available
+** using the older 1200,100 configuration without two-size-lookaside.
*/
#ifndef SQLITE_DEFAULT_LOOKASIDE
-# define SQLITE_DEFAULT_LOOKASIDE 1200,100
+# ifdef SQLITE_OMIT_TWOSIZE_LOOKASIDE
+# define SQLITE_DEFAULT_LOOKASIDE 1200,100 /* 120KB of memory */
+# else
+# define SQLITE_DEFAULT_LOOKASIDE 1200,40 /* 48KB of memory */
+# endif
#endif
+/* The default maximum size of an in-memory database created using
+** sqlite3_deserialize()
+*/
+#ifndef SQLITE_MEMDB_DEFAULT_MAXSIZE
+# define SQLITE_MEMDB_DEFAULT_MAXSIZE 1073741824
+#endif
+
/*
** The following singleton contains the global configuration for
** the SQLite library.
@@ -19538,6 +21037,7 @@ SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlite3Config = {
SQLITE_USE_URI, /* bOpenUri */
SQLITE_ALLOW_COVERING_INDEX_SCAN, /* bUseCis */
0, /* bSmallMalloc */
+ 1, /* bExtraSchemaChecks */
0x7ffffffe, /* mxStrlen */
0, /* neverCorrupt */
SQLITE_DEFAULT_LOOKASIDE, /* szLookaside, nLookaside */
@@ -19574,12 +21074,16 @@ SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlite3Config = {
0, /* xVdbeBranch */
0, /* pVbeBranchArg */
#endif
+#ifndef SQLITE_OMIT_DESERIALIZE
+ SQLITE_MEMDB_DEFAULT_MAXSIZE, /* mxMemdbSize */
+#endif
#ifndef SQLITE_UNTESTABLE
0, /* xTestCallback */
#endif
0, /* bLocaltimeFault */
0x7ffffffe, /* iOnceResetThreshold */
- SQLITE_DEFAULT_SORTERREF_SIZE /* szSorterRef */
+ SQLITE_DEFAULT_SORTERREF_SIZE, /* szSorterRef */
+ 0, /* iPrngSeed */
};
/*
@@ -19589,14 +21093,6 @@ SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlite3Config = {
*/
SQLITE_PRIVATE FuncDefHash sqlite3BuiltinFunctions;
-/*
-** Constant tokens for values 0 and 1.
-*/
-SQLITE_PRIVATE const Token sqlite3IntTokens[] = {
- { "0", 1 },
- { "1", 1 }
-};
-
#ifdef VDBE_PROFILE
/*
** The following performance counter can be used in place of
@@ -19627,12 +21123,18 @@ SQLITE_PRIVATE sqlite3_uint64 sqlite3NProfileCnt = 0;
SQLITE_PRIVATE int sqlite3PendingByte = 0x40000000;
#endif
+/*
+** Tracing flags set by SQLITE_TESTCTRL_TRACEFLAGS.
+*/
+SQLITE_PRIVATE u32 sqlite3SelectTrace = 0;
+SQLITE_PRIVATE u32 sqlite3WhereTrace = 0;
+
/* #include "opcodes.h" */
/*
** 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;
@@ -19694,7 +21196,8 @@ SQLITE_PRIVATE const char sqlite3StrBINARY[] = "BINARY";
** "explain" P4 display logic is enabled.
*/
#if !defined(SQLITE_OMIT_EXPLAIN) || !defined(NDEBUG) \
- || defined(VDBE_PROFILE) || defined(SQLITE_DEBUG)
+ || defined(VDBE_PROFILE) || defined(SQLITE_DEBUG) \
+ || defined(SQLITE_ENABLE_BYTECODE_VTAB)
# define VDBE_DISPLAY_P4 1
#else
# define VDBE_DISPLAY_P4 0
@@ -19748,10 +21251,11 @@ struct VdbeCursor {
Bool isEphemeral:1; /* True for an ephemeral table */
Bool useRandomRowid:1; /* Generate new record numbers semi-randomly */
Bool isOrdered:1; /* True if the table is not BTREE_UNORDERED */
- Bool seekHit:1; /* See the OP_SeekHit and OP_IfNoHope opcodes */
+ Bool hasBeenDuped:1; /* This cursor was source or target of OP_OpenDup */
+ u16 seekHit; /* See the OP_SeekHit and OP_IfNoHope opcodes */
Btree *pBtx; /* Separate file holding temporary table */
i64 seqCount; /* Sequence counter */
- int *aAltMap; /* Mapping from table to index column numbers */
+ u32 *aAltMap; /* Mapping from table to index column numbers */
/* Cached OP_Column parse information is only valid if cacheStatus matches
** Vdbe.cacheCtr. Vdbe.cacheCtr will never take on the value of
@@ -19803,7 +21307,7 @@ struct 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.
@@ -19900,7 +21404,7 @@ struct sqlite3_value {
** 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.
*/
#define MEM_Null 0x0001 /* Value is NULL (or a pointer) */
@@ -19908,12 +21412,12 @@ struct sqlite3_value {
#define MEM_Int 0x0004 /* Value is an integer */
#define MEM_Real 0x0008 /* Value is a real number */
#define MEM_Blob 0x0010 /* Value is a BLOB */
-#define MEM_AffMask 0x001f /* Mask of affinity bits */
-/* Available 0x0020 */
-/* Available 0x0040 */
+#define MEM_IntReal 0x0020 /* MEM_Int that stringifies like MEM_Real */
+#define MEM_AffMask 0x003f /* Mask of affinity bits */
+#define MEM_FromBind 0x0040 /* Value originates from sqlite3_bind() */
#define MEM_Undefined 0x0080 /* Value is undefined */
#define MEM_Cleared 0x0100 /* NULL set by OP_Null, not from data */
-#define MEM_TypeMask 0xc1ff /* Mask of type bits */
+#define MEM_TypeMask 0xc1bf /* Mask of type bits */
/* Whenever Mem contains a valid string or blob representation, one of
@@ -19945,6 +21449,13 @@ struct sqlite3_value {
#define MemSetTypeFlag(p, f) \
((p)->flags = ((p)->flags&~(MEM_TypeMask|MEM_Zero))|f)
+/*
+** True if Mem X is a NULL-nochng type.
+*/
+#define MemNullNochng(X) \
+ (((X)->flags&MEM_TypeMask)==(MEM_Null|MEM_Zero) \
+ && (X)->n==0 && (X)->u.nZero==0)
+
/*
** Return true if a memory cell is not marked as invalid. This macro
** is for use inside assert() statements only.
@@ -19954,7 +21465,7 @@ struct sqlite3_value {
#endif
/*
-** Each auxiliary data pointer stored by a user defined function
+** Each auxiliary data pointer stored by a user defined function
** implementation calling sqlite3_set_auxdata() is stored in an instance
** of this structure. All such structures associated with a single VM
** are stored in a linked list headed at Vdbe.pAuxData. All are destroyed
@@ -19998,6 +21509,9 @@ struct sqlite3_context {
*/
typedef unsigned bft; /* Bit Field Type */
+/* The ScanStatus object holds a single value for the
+** sqlite3_stmt_scanstatus() interface.
+*/
typedef struct ScanStatus ScanStatus;
struct ScanStatus {
int addrExplain; /* OP_Explain for loop */
@@ -20008,6 +21522,19 @@ struct ScanStatus {
char *zName; /* Name of table or index */
};
+/* The DblquoteStr object holds the text of a double-quoted
+** string for a prepared statement. A linked list of these objects
+** is constructed during statement parsing and is held on Vdbe.pDblStr.
+** When computing a normalized SQL statement for an SQL statement, that
+** list is consulted for each double-quoted identifier to see if the
+** identifier should really be a string literal.
+*/
+typedef struct DblquoteStr DblquoteStr;
+struct DblquoteStr {
+ DblquoteStr *pNextStr; /* Next string literal in the list */
+ char z[8]; /* Dequoted value for the string */
+};
+
/*
** An instance of the virtual machine. This structure contains the complete
** state of the virtual machine.
@@ -20020,35 +21547,36 @@ struct Vdbe {
Vdbe *pPrev,*pNext; /* Linked list of VDBEs with the same Vdbe.db */
Parse *pParse; /* Parsing context used to create this Vdbe */
ynVar nVar; /* Number of entries in aVar[] */
- u32 magic; /* Magic number for sanity checking */
+ u32 iVdbeMagic; /* Magic number defining state of the SQL statement */
int nMem; /* Number of memory locations currently allocated */
int nCursor; /* Number of slots in apCsr[] */
u32 cacheCtr; /* VdbeCursor row cache generation counter */
int pc; /* The program counter */
int rc; /* Value to return */
int nChange; /* Number of db changes made since last reset */
- int iStatement; /* Statement number (or 0 if has not opened stmt) */
+ int iStatement; /* Statement number (or 0 if has no opened stmt) */
i64 iCurrentTime; /* Value of julianday('now') for this statement */
i64 nFkConstraint; /* Number of imm. FK constraints this VM */
i64 nStmtDefCons; /* Number of def. constraints when stmt started */
i64 nStmtDefImmCons; /* Number of def. imm constraints when stmt started */
+ Mem *aMem; /* The memory locations */
+ Mem **apArg; /* Arguments to currently executing user function */
+ VdbeCursor **apCsr; /* One element of this array for each open cursor */
+ Mem *aVar; /* Values for the OP_Variable opcode. */
/* When allocating a new Vdbe object, all of the fields below should be
** initialized to zero or NULL */
Op *aOp; /* Space to hold the virtual machine's program */
- Mem *aMem; /* The memory locations */
- Mem **apArg; /* Arguments to currently executing user function */
+ int nOp; /* Number of instructions in the program */
+ int nOpAlloc; /* Slots allocated for aOp[] */
Mem *aColName; /* Column names to return */
Mem *pResultSet; /* Pointer to an array of results */
char *zErrMsg; /* Error message written here */
- VdbeCursor **apCsr; /* One element of this array for each open cursor */
- Mem *aVar; /* Values for the OP_Variable opcode. */
VList *pVList; /* Name of variables */
#ifndef SQLITE_OMIT_TRACE
i64 startTime; /* Time when query started - used for profiling */
#endif
- int nOp; /* Number of instructions in the program */
#ifdef SQLITE_DEBUG
int rcApp; /* errcode set by sqlite3_result_error_code() */
u32 nWrite; /* Number of write operations that have occurred */
@@ -20057,9 +21585,9 @@ struct Vdbe {
u8 errorAction; /* Recovery action to do in case of an error */
u8 minWriteFileFormat; /* Minimum file format for writable database files */
u8 prepFlags; /* SQLITE_PREPARE_* flags */
+ u8 doingRerun; /* True if rerunning after an auto-reprepare */
bft expired:2; /* 1: recompile VM immediately 2: when convenient */
bft explain:2; /* True if EXPLAIN present on SQL command */
- bft doingRerun:1; /* True if rerunning after an auto-reprepare */
bft changeCntOn:1; /* True to update the change-counter */
bft runOnlyOnce:1; /* Automatically expire on reset */
bft usesStmtJournal:1; /* True if uses a statement journal */
@@ -20069,6 +21597,10 @@ struct Vdbe {
yDbMask lockMask; /* Subset of btreeMask that requires a lock */
u32 aCounter[7]; /* Counters used by sqlite3_stmt_status() */
char *zSql; /* Text of the SQL statement that generated this */
+#ifdef SQLITE_ENABLE_NORMALIZE
+ char *zNormSql; /* Normalization of the associated SQL statement */
+ DblquoteStr *pDblStr; /* List of double-quoted string literals */
+#endif
void *pFree; /* Free this when deleting the vdbe */
VdbeFrame *pFrame; /* Parent frame */
VdbeFrame *pDelFrame; /* List of frame objects to free on VM reset */
@@ -20093,7 +21625,7 @@ struct Vdbe {
#define VDBE_MAGIC_DEAD 0x5606c3c8 /* The VDBE has been deallocated */
/*
-** Structure used to store the context required by the
+** Structure used to store the context required by the
** sqlite3_preupdate_*() API functions.
*/
struct PreUpdate {
@@ -20105,10 +21637,11 @@ struct PreUpdate {
UnpackedRecord *pUnpacked; /* Unpacked version of aRecord[] */
UnpackedRecord *pNewUnpacked; /* Unpacked version of new.* record */
int iNewReg; /* Register for new.* values */
+ int iBlobWrite; /* Value returned by preupdate_blobwrite() */
i64 iKey1; /* First key value passed to hook */
i64 iKey2; /* Second key value passed to hook */
Mem *aNew; /* Array of new.* values */
- Table *pTab; /* Schema object being upated */
+ Table *pTab; /* Schema object being upated */
Index *pPk; /* PK index if pTab is WITHOUT ROWID */
};
@@ -20118,11 +21651,11 @@ struct PreUpdate {
SQLITE_PRIVATE void sqlite3VdbeError(Vdbe*, const char *, ...);
SQLITE_PRIVATE void sqlite3VdbeFreeCursor(Vdbe *, VdbeCursor*);
void sqliteVdbePopStack(Vdbe*,int);
-SQLITE_PRIVATE int sqlite3VdbeCursorMoveto(VdbeCursor**, int*);
+SQLITE_PRIVATE int SQLITE_NOINLINE sqlite3VdbeFinishMoveto(VdbeCursor*);
+SQLITE_PRIVATE int sqlite3VdbeCursorMoveto(VdbeCursor**, u32*);
SQLITE_PRIVATE int sqlite3VdbeCursorRestore(VdbeCursor*);
SQLITE_PRIVATE u32 sqlite3VdbeSerialTypeLen(u32);
SQLITE_PRIVATE u8 sqlite3VdbeOneByteSerialTypeLen(u8);
-SQLITE_PRIVATE u32 sqlite3VdbeSerialType(Mem*, int, u32*);
SQLITE_PRIVATE u32 sqlite3VdbeSerialPut(unsigned char*, Mem*, u32);
SQLITE_PRIVATE u32 sqlite3VdbeSerialGet(const unsigned char*, u32, Mem*);
SQLITE_PRIVATE void sqlite3VdbeDeleteAuxData(sqlite3*, AuxData**, int, int);
@@ -20131,7 +21664,16 @@ int sqlite2BtreeKeyCompare(BtCursor *, const void *, int, int, int *);
SQLITE_PRIVATE int sqlite3VdbeIdxKeyCompare(sqlite3*,VdbeCursor*,UnpackedRecord*,int*);
SQLITE_PRIVATE int sqlite3VdbeIdxRowid(sqlite3*, BtCursor*, i64*);
SQLITE_PRIVATE int sqlite3VdbeExec(Vdbe*);
+#if !defined(SQLITE_OMIT_EXPLAIN) || defined(SQLITE_ENABLE_BYTECODE_VTAB)
+SQLITE_PRIVATE int sqlite3VdbeNextOpcode(Vdbe*,Mem*,int,int*,int*,Op**);
+SQLITE_PRIVATE char *sqlite3VdbeDisplayP4(sqlite3*,Op*);
+#endif
+#if defined(SQLITE_ENABLE_EXPLAIN_COMMENTS)
+SQLITE_PRIVATE char *sqlite3VdbeDisplayComment(sqlite3*,const Op*,const char*);
+#endif
+#if !defined(SQLITE_OMIT_EXPLAIN)
SQLITE_PRIVATE int sqlite3VdbeList(Vdbe*);
+#endif
SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe*);
SQLITE_PRIVATE int sqlite3VdbeChangeEncoding(Mem *, int);
SQLITE_PRIVATE int sqlite3VdbeMemTooBig(Mem*);
@@ -20139,7 +21681,7 @@ SQLITE_PRIVATE int sqlite3VdbeMemCopy(Mem*, const Mem*);
SQLITE_PRIVATE void sqlite3VdbeMemShallowCopy(Mem*, const Mem*, int);
SQLITE_PRIVATE void sqlite3VdbeMemMove(Mem*, Mem*);
SQLITE_PRIVATE int sqlite3VdbeMemNulTerminate(Mem*);
-SQLITE_PRIVATE int sqlite3VdbeMemSetStr(Mem*, const char*, int, u8, void(*)(void*));
+SQLITE_PRIVATE int sqlite3VdbeMemSetStr(Mem*, const char*, i64, u8, void(*)(void*));
SQLITE_PRIVATE void sqlite3VdbeMemSetInt64(Mem*, i64);
#ifdef SQLITE_OMIT_FLOATING_POINT
# define sqlite3VdbeMemSetDouble sqlite3VdbeMemSetInt64
@@ -20163,14 +21705,17 @@ SQLITE_PRIVATE int sqlite3VdbeBooleanValue(Mem*, int ifNull);
SQLITE_PRIVATE void sqlite3VdbeIntegerAffinity(Mem*);
SQLITE_PRIVATE int sqlite3VdbeMemRealify(Mem*);
SQLITE_PRIVATE int sqlite3VdbeMemNumerify(Mem*);
-SQLITE_PRIVATE void sqlite3VdbeMemCast(Mem*,u8,u8);
+SQLITE_PRIVATE int sqlite3VdbeMemCast(Mem*,u8,u8);
SQLITE_PRIVATE int sqlite3VdbeMemFromBtree(BtCursor*,u32,u32,Mem*);
+SQLITE_PRIVATE int sqlite3VdbeMemFromBtreeZeroOffset(BtCursor*,u32,Mem*);
SQLITE_PRIVATE void sqlite3VdbeMemRelease(Mem *p);
SQLITE_PRIVATE int sqlite3VdbeMemFinalize(Mem*, FuncDef*);
#ifndef SQLITE_OMIT_WINDOWFUNC
SQLITE_PRIVATE int sqlite3VdbeMemAggValue(Mem*, Mem*, FuncDef*);
#endif
+#if !defined(SQLITE_OMIT_EXPLAIN) || defined(SQLITE_ENABLE_BYTECODE_VTAB)
SQLITE_PRIVATE const char *sqlite3OpcodeName(int);
+#endif
SQLITE_PRIVATE int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve);
SQLITE_PRIVATE int sqlite3VdbeMemClearAndResize(Mem *pMem, int n);
SQLITE_PRIVATE int sqlite3VdbeCloseStatement(Vdbe *, int);
@@ -20181,7 +21726,8 @@ SQLITE_PRIVATE void sqlite3VdbeFrameMemDel(void*); /* Destructor on Mem */
SQLITE_PRIVATE void sqlite3VdbeFrameDelete(VdbeFrame*); /* Actually deletes the Frame */
SQLITE_PRIVATE int sqlite3VdbeFrameRestore(VdbeFrame *);
#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
-SQLITE_PRIVATE void sqlite3VdbePreUpdateHook(Vdbe*,VdbeCursor*,int,const char*,Table*,i64,int);
+SQLITE_PRIVATE void sqlite3VdbePreUpdateHook(
+ Vdbe*,VdbeCursor*,int,const char*,Table*,i64,int,int);
#endif
SQLITE_PRIVATE int sqlite3VdbeTransferError(Vdbe *p);
@@ -20202,7 +21748,7 @@ SQLITE_PRIVATE void sqlite3VdbeAssertAbortable(Vdbe*);
# define sqlite3VdbeAssertAbortable(V)
#endif
-#if !defined(SQLITE_OMIT_SHARED_CACHE)
+#if !defined(SQLITE_OMIT_SHARED_CACHE)
SQLITE_PRIVATE void sqlite3VdbeEnter(Vdbe*);
#else
# define sqlite3VdbeEnter(X)
@@ -20227,7 +21773,7 @@ SQLITE_PRIVATE int sqlite3VdbeCheckFk(Vdbe *, int);
#ifdef SQLITE_DEBUG
SQLITE_PRIVATE void sqlite3VdbePrintSql(Vdbe*);
-SQLITE_PRIVATE void sqlite3VdbeMemPrettyPrint(Mem *pMem, char *zBuf);
+SQLITE_PRIVATE void sqlite3VdbeMemPrettyPrint(Mem *pMem, StrAccum *pStr);
#endif
#ifndef SQLITE_OMIT_UTF16
SQLITE_PRIVATE int sqlite3VdbeMemTranslate(Mem*, u8);
@@ -20419,6 +21965,10 @@ static u32 countLookasideSlots(LookasideSlot *p){
SQLITE_PRIVATE int sqlite3LookasideUsed(sqlite3 *db, int *pHighwater){
u32 nInit = countLookasideSlots(db->lookaside.pInit);
u32 nFree = countLookasideSlots(db->lookaside.pFree);
+#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE
+ nInit += countLookasideSlots(db->lookaside.pSmallInit);
+ nFree += countLookasideSlots(db->lookaside.pSmallFree);
+#endif /* SQLITE_OMIT_TWOSIZE_LOOKASIDE */
if( pHighwater ) *pHighwater = db->lookaside.nSlot - nInit;
return db->lookaside.nSlot - (nInit+nFree);
}
@@ -20451,6 +22001,15 @@ SQLITE_API int sqlite3_db_status(
db->lookaside.pInit = db->lookaside.pFree;
db->lookaside.pFree = 0;
}
+#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE
+ p = db->lookaside.pSmallFree;
+ if( p ){
+ while( p->pNext ) p = p->pNext;
+ p->pNext = db->lookaside.pSmallInit;
+ db->lookaside.pSmallInit = db->lookaside.pSmallFree;
+ db->lookaside.pSmallFree = 0;
+ }
+#endif
}
break;
}
@@ -20471,7 +22030,7 @@ 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.
@@ -20515,7 +22074,7 @@ SQLITE_API int sqlite3_db_status(
HashElem *p;
nByte += sqlite3GlobalConfig.m.xRoundup(sizeof(HashElem)) * (
- pSchema->tblHash.count
+ pSchema->tblHash.count
+ pSchema->trigHash.count
+ pSchema->idxHash.count
+ pSchema->fkeyHash.count
@@ -20565,12 +22124,12 @@ SQLITE_API int sqlite3_db_status(
/*
** Set *pCurrent to the total cache hits or misses encountered by all
- ** pagers the database handle is connected to. *pHighwater is always set
+ ** pagers the database handle is connected to. *pHighwater is always set
** to zero.
*/
case SQLITE_DBSTATUS_CACHE_SPILL:
op = SQLITE_DBSTATUS_CACHE_WRITE+1;
- /* Fall through into the next case */
+ /* no break */ deliberate_fall_through
case SQLITE_DBSTATUS_CACHE_HIT:
case SQLITE_DBSTATUS_CACHE_MISS:
case SQLITE_DBSTATUS_CACHE_WRITE:{
@@ -20624,7 +22183,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.
@@ -20633,7 +22192,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
@@ -20981,7 +22540,7 @@ static void setRawDateNumber(DateTime *p, double r){
** 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
@@ -20991,8 +22550,8 @@ static void setRawDateNumber(DateTime *p, double r){
** as there is a year and date.
*/
static int parseDateOrTime(
- sqlite3_context *context,
- const char *zDate,
+ sqlite3_context *context,
+ const char *zDate,
DateTime *p
){
double r;
@@ -21002,7 +22561,7 @@ static int parseDateOrTime(
return 0;
}else if( sqlite3StrICmp(zDate,"now")==0 && sqlite3NotPureFunc(context) ){
return setDateTimeToCurrent(context, p);
- }else if( sqlite3AtoF(zDate, &r, sqlite3Strlen30(zDate), SQLITE_UTF8) ){
+ }else if( sqlite3AtoF(zDate, &r, sqlite3Strlen30(zDate), SQLITE_UTF8)>0 ){
setRawDateNumber(p, r);
return 0;
}
@@ -21013,7 +22572,7 @@ static int parseDateOrTime(
** Multiplying this by 86400000 gives 464269060799999 as the maximum value
** for DateTime.iJD.
**
-** But some older compilers (ex: gcc 4.2.1 on older Macs) cannot deal with
+** But some older compilers (ex: gcc 4.2.1 on older Macs) cannot deal with
** such a large integer literal, so we have to encode it.
*/
#define INT_464269060799999 ((((i64)0x1a640)<<32)|0x1072fdff)
@@ -21095,14 +22654,14 @@ static void clearYMD_HMS_TZ(DateTime *p){
#ifndef SQLITE_OMIT_LOCALTIME
/*
** 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 !HAVE_LOCALTIME_R && !HAVE_LOCALTIME_S \
@@ -21129,7 +22688,7 @@ static int osLocaltime(time_t *t, struct tm *pTm){
#if !HAVE_LOCALTIME_R && !HAVE_LOCALTIME_S
struct tm *pX;
#if SQLITE_THREADSAFE>0
- sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
+ sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN);
#endif
sqlite3_mutex_enter(mutex);
pX = localtime(t);
@@ -21158,7 +22717,7 @@ static int osLocaltime(time_t *t, struct tm *pTm){
/*
** Compute the difference (in milliseconds) between localtime and UTC
** (a.k.a. GMT) for the time value p where p is in UTC. If no error occurs,
-** return this value and set *pRc to SQLITE_OK.
+** return this value and set *pRc to SQLITE_OK.
**
** Or, if an error does occur, set *pRc to SQLITE_ERROR. The returned value
** is undefined in this case.
@@ -21235,12 +22794,12 @@ static const struct {
double rLimit; /* Maximum NNN value for this transform */
double rXform; /* Constant used for this transform */
} aXformType[] = {
- { 0, 6, "second", 464269060800.0, 86400000.0/(24.0*60.0*60.0) },
- { 0, 6, "minute", 7737817680.0, 86400000.0/(24.0*60.0) },
- { 0, 4, "hour", 128963628.0, 86400000.0/24.0 },
- { 0, 3, "day", 5373485.0, 86400000.0 },
- { 1, 5, "month", 176546.0, 30.0*86400000.0 },
- { 2, 4, "year", 14713.0, 365.0*86400000.0 },
+ { 0, 6, "second", 464269060800.0, 1000.0 },
+ { 0, 6, "minute", 7737817680.0, 60000.0 },
+ { 0, 4, "hour", 128963628.0, 3600000.0 },
+ { 0, 3, "day", 5373485.0, 86400000.0 },
+ { 1, 5, "month", 176546.0, 2592000000.0 },
+ { 2, 4, "year", 14713.0, 31536000000.0 },
};
/*
@@ -21302,7 +22861,7 @@ static int parseModifier(
r = p->s*1000.0 + 210866760000000.0;
if( r>=0.0 && r<464269060800000.0 ){
clearYMD_HMS_TZ(p);
- p->iJD = (sqlite3_int64)r;
+ p->iJD = (sqlite3_int64)(r + 0.5);
p->validJD = 1;
p->rawS = 0;
rc = 0;
@@ -21336,7 +22895,7 @@ static int parseModifier(
** date is already on the appropriate weekday, this is a no-op.
*/
if( sqlite3_strnicmp(z, "weekday ", 8)==0
- && sqlite3AtoF(&z[8], &r, sqlite3Strlen30(&z[8]), SQLITE_UTF8)
+ && sqlite3AtoF(&z[8], &r, sqlite3Strlen30(&z[8]), SQLITE_UTF8)>0
&& (n=(int)r)==r && n>=0 && r<7 ){
sqlite3_int64 Z;
computeYMD_HMS(p);
@@ -21395,7 +22954,7 @@ static int parseModifier(
double rRounder;
int i;
for(n=1; z[n] && z[n]!=':' && !sqlite3Isspace(z[n]); n++){}
- if( !sqlite3AtoF(z, &r, n, SQLITE_UTF8) ){
+ if( sqlite3AtoF(z, &r, n, SQLITE_UTF8)<=0 ){
rc = 1;
break;
}
@@ -21485,9 +23044,9 @@ static int parseModifier(
** 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, n;
@@ -21495,6 +23054,7 @@ static int isDate(
int eType;
memset(p, 0, sizeof(*p));
if( argc==0 ){
+ if( !sqlite3NotPureFunc(context) ) return 1;
return setDateTimeToCurrent(context, p);
}
if( (eType = sqlite3_value_type(argv[0]))==SQLITE_FLOAT
@@ -21726,8 +23286,8 @@ static void strftimeFunc(
case 'm': sqlite3_snprintf(3, &z[j],"%02d",x.M); j+=2; break;
case 'M': sqlite3_snprintf(3, &z[j],"%02d",x.m); j+=2; break;
case 's': {
- sqlite3_snprintf(30,&z[j],"%lld",
- (i64)(x.iJD/1000 - 21086676*(i64)10000));
+ i64 iS = (i64)(x.iJD/1000 - 21086676*(i64)10000);
+ sqlite3Int64ToText(iS, &z[j]);
j += sqlite3Strlen30(&z[j]);
break;
}
@@ -21825,10 +23385,10 @@ static void currentTimeFunc(
#if HAVE_GMTIME_R
pTm = gmtime_r(&t, &sNow);
#else
- sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
+ sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN));
pTm = gmtime(&t);
if( pTm ) memcpy(&sNow, pTm, sizeof(sNow));
- sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
+ sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN));
#endif
if( pTm ){
strftime(zBuf, 20, zFormat, &sNow);
@@ -21995,6 +23555,8 @@ SQLITE_PRIVATE int sqlite3OsFileControl(sqlite3_file *id, int op, void *pArg){
#ifdef SQLITE_TEST
if( op!=SQLITE_FCNTL_COMMIT_PHASETWO
&& op!=SQLITE_FCNTL_LOCK_TIMEOUT
+ && op!=SQLITE_FCNTL_CKPT_DONE
+ && op!=SQLITE_FCNTL_CKPT_START
){
/* Faults are not injected into COMMIT_PHASETWO because, assuming SQLite
** is using a regular VFS, it is called after the corresponding
@@ -22005,7 +23567,12 @@ SQLITE_PRIVATE int sqlite3OsFileControl(sqlite3_file *id, int op, void *pArg){
** The core must call OsFileControl() though, not OsFileControlHint(),
** as if a custom VFS (e.g. zipvfs) returns an error here, it probably
** means the commit really has failed and an error should be returned
- ** to the user. */
+ ** to the user.
+ **
+ ** The CKPT_DONE and CKPT_START file-controls are write-only signals
+ ** to the cksumvfs. Their return code is meaningless and is ignored
+ ** by the SQLite core, so there is no point in simulating OOMs for them.
+ */
DO_OS_MALLOC_TEST(id);
}
#endif
@@ -22081,14 +23648,14 @@ SQLITE_PRIVATE int sqlite3OsOpen(
** down into the VFS layer. Some SQLITE_OPEN_ flags (for example,
** SQLITE_OPEN_FULLMUTEX or SQLITE_OPEN_SHAREDCACHE) are blocked before
** reaching the VFS. */
- rc = pVfs->xOpen(pVfs, zPath, pFile, flags & 0x87f7f, pFlagsOut);
+ rc = pVfs->xOpen(pVfs, zPath, pFile, flags & 0x1087f7f, pFlagsOut);
assert( rc==SQLITE_OK || pFile->pMethods==0 );
return rc;
}
SQLITE_PRIVATE int sqlite3OsDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
DO_OS_MALLOC_TEST(0);
assert( dirSync==0 || dirSync==1 );
- return pVfs->xDelete(pVfs, zPath, dirSync);
+ return pVfs->xDelete!=0 ? pVfs->xDelete(pVfs, zPath, dirSync) : SQLITE_OK;
}
SQLITE_PRIVATE int sqlite3OsAccess(
sqlite3_vfs *pVfs,
@@ -22111,6 +23678,8 @@ SQLITE_PRIVATE int sqlite3OsFullPathname(
}
#ifndef SQLITE_OMIT_LOAD_EXTENSION
SQLITE_PRIVATE void *sqlite3OsDlOpen(sqlite3_vfs *pVfs, const char *zPath){
+ assert( zPath!=0 );
+ assert( strlen(zPath)<=SQLITE_MAX_PATHLEN ); /* tag-20210611-1 */
return pVfs->xDlOpen(pVfs, zPath);
}
SQLITE_PRIVATE void sqlite3OsDlError(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
@@ -22124,7 +23693,15 @@ SQLITE_PRIVATE void sqlite3OsDlClose(sqlite3_vfs *pVfs, void *pHandle){
}
#endif /* SQLITE_OMIT_LOAD_EXTENSION */
SQLITE_PRIVATE int sqlite3OsRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
- return pVfs->xRandomness(pVfs, nByte, zBufOut);
+ if( sqlite3Config.iPrngSeed ){
+ memset(zBufOut, 0, nByte);
+ if( ALWAYS(nByte>(signed)sizeof(unsigned)) ) nByte = sizeof(unsigned int);
+ memcpy(zBufOut, &sqlite3Config.iPrngSeed, nByte);
+ return SQLITE_OK;
+ }else{
+ return pVfs->xRandomness(pVfs, nByte, zBufOut);
+ }
+
}
SQLITE_PRIVATE int sqlite3OsSleep(sqlite3_vfs *pVfs, int nMicro){
return pVfs->xSleep(pVfs, nMicro);
@@ -22211,7 +23788,7 @@ SQLITE_API sqlite3_vfs *sqlite3_vfs_find(const char *zVfs){
if( rc ) return 0;
#endif
#if SQLITE_THREADSAFE
- mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
+ mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN);
#endif
sqlite3_mutex_enter(mutex);
for(pVfs = vfsList; pVfs; pVfs=pVfs->pNext){
@@ -22226,7 +23803,7 @@ SQLITE_API sqlite3_vfs *sqlite3_vfs_find(const char *zVfs){
** Unlink a VFS from the linked list
*/
static void vfsUnlink(sqlite3_vfs *pVfs){
- assert( sqlite3_mutex_held(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER)) );
+ assert( sqlite3_mutex_held(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN)) );
if( pVfs==0 ){
/* No-op */
}else if( vfsList==pVfs ){
@@ -22257,7 +23834,7 @@ SQLITE_API int sqlite3_vfs_register(sqlite3_vfs *pVfs, int makeDflt){
if( pVfs==0 ) return SQLITE_MISUSE_BKPT;
#endif
- MUTEX_LOGIC( mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); )
+ MUTEX_LOGIC( mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN); )
sqlite3_mutex_enter(mutex);
vfsUnlink(pVfs);
if( makeDflt || vfsList==0 ){
@@ -22281,7 +23858,7 @@ SQLITE_API int sqlite3_vfs_unregister(sqlite3_vfs *pVfs){
int rc = sqlite3_initialize();
if( rc ) return rc;
#endif
- MUTEX_LOGIC( mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); )
+ MUTEX_LOGIC( mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN); )
sqlite3_mutex_enter(mutex);
vfsUnlink(pVfs);
sqlite3_mutex_leave(mutex);
@@ -22302,17 +23879,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.
*/
@@ -22514,7 +24091,7 @@ static malloc_zone_t* _sqliteZone_;
#else /* if not __APPLE__ */
/*
-** Use standard C library malloc and free on non-Apple systems.
+** Use standard C library malloc and free on non-Apple systems.
** Also used by Apple systems if SQLITE_WITHOUT_ZONEMALLOC is defined.
*/
#define SQLITE_MALLOC(x) malloc(x)
@@ -22694,7 +24271,7 @@ static int sqlite3MemInit(void *NotUsed){
/* defer MT decisions to system malloc */
_sqliteZone_ = malloc_default_zone();
}else{
- /* only 1 core, use our own zone to contention over global locks,
+ /* only 1 core, use our own zone to contention over global locks,
** e.g. we have our own dedicated locks */
_sqliteZone_ = malloc_create_zone(4096, 0);
malloc_set_zone_name(_sqliteZone_, "Sqlite_Heap");
@@ -22818,7 +24395,7 @@ struct MemBlockHdr {
** when this module is combined with other in the amalgamation.
*/
static struct {
-
+
/*
** Mutex to control access to the memory allocation subsystem.
*/
@@ -22829,7 +24406,7 @@ static struct {
*/
struct MemBlockHdr *pFirst;
struct MemBlockHdr *pLast;
-
+
/*
** The number of levels of backtrace to save in new allocations.
*/
@@ -22842,7 +24419,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.
*/
@@ -22901,7 +24478,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 );
@@ -23030,7 +24607,7 @@ static void *sqlite3MemMalloc(int nByte){
p = (void*)pInt;
}
sqlite3_mutex_leave(mem.mutex);
- return p;
+ return p;
}
/*
@@ -23040,7 +24617,7 @@ static void sqlite3MemFree(void *pPrior){
struct MemBlockHdr *pHdr;
void **pBt;
char *z;
- assert( sqlite3GlobalConfig.bMemstat || sqlite3GlobalConfig.bCoreMutex==0
+ assert( sqlite3GlobalConfig.bMemstat || sqlite3GlobalConfig.bCoreMutex==0
|| mem.mutex!=0 );
pHdr = sqlite3MemsysGetHeader(pPrior);
pBt = (void**)pHdr;
@@ -23066,15 +24643,15 @@ static void sqlite3MemFree(void *pPrior){
randomFill(z, sizeof(void*)*pHdr->nBacktraceSlots + sizeof(*pHdr) +
(int)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.
*/
@@ -23117,7 +24694,7 @@ SQLITE_PRIVATE void sqlite3MemSetDefault(void){
** Set the "type" of an allocation.
*/
SQLITE_PRIVATE void sqlite3MemdebugSetType(void *p, u8 eType){
- if( p && sqlite3GlobalConfig.m.xMalloc==sqlite3MemMalloc ){
+ if( p && sqlite3GlobalConfig.m.xFree==sqlite3MemFree ){
struct MemBlockHdr *pHdr;
pHdr = sqlite3MemsysGetHeader(p);
assert( pHdr->iForeGuard==FOREGUARD );
@@ -23136,7 +24713,7 @@ SQLITE_PRIVATE void sqlite3MemdebugSetType(void *p, u8 eType){
*/
SQLITE_PRIVATE int sqlite3MemdebugHasType(void *p, u8 eType){
int rc = 1;
- if( p && sqlite3GlobalConfig.m.xMalloc==sqlite3MemMalloc ){
+ if( p && sqlite3GlobalConfig.m.xFree==sqlite3MemFree ){
struct MemBlockHdr *pHdr;
pHdr = sqlite3MemsysGetHeader(p);
assert( pHdr->iForeGuard==FOREGUARD ); /* Allocation is valid */
@@ -23158,7 +24735,7 @@ SQLITE_PRIVATE int sqlite3MemdebugHasType(void *p, u8 eType){
*/
SQLITE_PRIVATE int sqlite3MemdebugNoType(void *p, u8 eType){
int rc = 1;
- if( p && sqlite3GlobalConfig.m.xMalloc==sqlite3MemMalloc ){
+ if( p && sqlite3GlobalConfig.m.xFree==sqlite3MemFree ){
struct MemBlockHdr *pHdr;
pHdr = sqlite3MemsysGetHeader(p);
assert( pHdr->iForeGuard==FOREGUARD ); /* Allocation is valid */
@@ -23208,7 +24785,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){
@@ -23225,7 +24802,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);
@@ -23238,7 +24815,7 @@ SQLITE_PRIVATE void sqlite3MemdebugDump(const char *zFilename){
fprintf(out, "COUNTS:\n");
for(i=0; i=nBlock );
- if( nBlock>=mem3.szMaster-1 ){
- /* Use the entire master */
- void *p = memsys3Checkout(mem3.iMaster, mem3.szMaster);
- mem3.iMaster = 0;
- mem3.szMaster = 0;
- mem3.mnMaster = 0;
+ assert( mem3.szKeyBlk>=nBlock );
+ if( nBlock>=mem3.szKeyBlk-1 ){
+ /* Use the entire key chunk */
+ void *p = memsys3Checkout(mem3.iKeyBlk, mem3.szKeyBlk);
+ mem3.iKeyBlk = 0;
+ mem3.szKeyBlk = 0;
+ mem3.mnKeyBlk = 0;
return p;
}else{
- /* Split the master block. Return the tail. */
+ /* Split the key block. Return the tail. */
u32 newi, x;
- newi = mem3.iMaster + mem3.szMaster - nBlock;
- assert( newi > mem3.iMaster+1 );
- mem3.aPool[mem3.iMaster+mem3.szMaster-1].u.hdr.prevSize = nBlock;
- mem3.aPool[mem3.iMaster+mem3.szMaster-1].u.hdr.size4x |= 2;
+ newi = mem3.iKeyBlk + mem3.szKeyBlk - nBlock;
+ assert( newi > mem3.iKeyBlk+1 );
+ mem3.aPool[mem3.iKeyBlk+mem3.szKeyBlk-1].u.hdr.prevSize = nBlock;
+ mem3.aPool[mem3.iKeyBlk+mem3.szKeyBlk-1].u.hdr.size4x |= 2;
mem3.aPool[newi-1].u.hdr.size4x = nBlock*4 + 1;
- mem3.szMaster -= nBlock;
- mem3.aPool[newi-1].u.hdr.prevSize = mem3.szMaster;
- x = mem3.aPool[mem3.iMaster-1].u.hdr.size4x & 2;
- mem3.aPool[mem3.iMaster-1].u.hdr.size4x = mem3.szMaster*4 | x;
- if( mem3.szMaster < mem3.mnMaster ){
- mem3.mnMaster = mem3.szMaster;
+ mem3.szKeyBlk -= nBlock;
+ mem3.aPool[newi-1].u.hdr.prevSize = mem3.szKeyBlk;
+ x = mem3.aPool[mem3.iKeyBlk-1].u.hdr.size4x & 2;
+ mem3.aPool[mem3.iKeyBlk-1].u.hdr.size4x = mem3.szKeyBlk*4 | x;
+ if( mem3.szKeyBlk < mem3.mnKeyBlk ){
+ mem3.mnKeyBlk = mem3.szKeyBlk;
}
return (void*)&mem3.aPool[newi];
}
@@ -23568,18 +25145,18 @@ 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
-** the current mem3.iMaster with the new larger chunk. In order for
-** this mem3.iMaster replacement to work, the master chunk must be
+** If it sees a chunk that is larger than mem3.iKeyBlk, it replaces
+** the current mem3.iKeyBlk with the new larger chunk. In order for
+** this mem3.iKeyBlk replacement to work, the key chunk must be
** linked into the hash tables. That is not the normal state of
-** affairs, of course. The calling routine must link the master
+** affairs, of course. The calling routine must link the key
** chunk before invoking this routine, then must unlink the (possibly
-** changed) master chunk once this routine has finished.
+** changed) key chunk once this routine has finished.
*/
static void memsys3Merge(u32 *pRoot){
u32 iNext, prev, size, i, x;
@@ -23606,9 +25183,9 @@ static void memsys3Merge(u32 *pRoot){
}else{
size /= 4;
}
- if( size>mem3.szMaster ){
- mem3.iMaster = i;
- mem3.szMaster = size;
+ if( size>mem3.szKeyBlk ){
+ mem3.iKeyBlk = i;
+ mem3.szKeyBlk = size;
}
}
}
@@ -23657,26 +25234,26 @@ static void *memsys3MallocUnsafe(int nByte){
/* STEP 2:
** Try to satisfy the allocation by carving a piece off of the end
- ** of the master chunk. This step usually works if step 1 fails.
+ ** of the key chunk. This step usually works if step 1 fails.
*/
- if( mem3.szMaster>=nBlock ){
- return memsys3FromMaster(nBlock);
+ if( mem3.szKeyBlk>=nBlock ){
+ return memsys3FromKeyBlk(nBlock);
}
- /* STEP 3:
+ /* STEP 3:
** Loop through the entire memory pool. Coalesce adjacent free
- ** chunks. Recompute the master chunk as the largest free chunk.
+ ** chunks. Recompute the key chunk as the largest free chunk.
** Then try again to satisfy the allocation by carving a piece off
- ** of the end of the master chunk. This step happens very
+ ** of the end of the key chunk. This step happens very
** rarely (we hope!)
*/
for(toFree=nBlock*16; toFree<(mem3.nPool*16); toFree *= 2){
memsys3OutOfMemory(toFree);
- if( mem3.iMaster ){
- memsys3Link(mem3.iMaster);
- mem3.iMaster = 0;
- mem3.szMaster = 0;
+ if( mem3.iKeyBlk ){
+ memsys3Link(mem3.iKeyBlk);
+ mem3.iKeyBlk = 0;
+ mem3.szKeyBlk = 0;
}
for(i=0; i=nBlock ){
- return memsys3FromMaster(nBlock);
+ if( mem3.szKeyBlk ){
+ memsys3Unlink(mem3.iKeyBlk);
+ if( mem3.szKeyBlk>=nBlock ){
+ return memsys3FromKeyBlk(nBlock);
}
}
}
@@ -23717,23 +25294,23 @@ static void memsys3FreeUnsafe(void *pOld){
mem3.aPool[i+size-1].u.hdr.size4x &= ~2;
memsys3Link(i);
- /* Try to expand the master using the newly freed chunk */
- if( mem3.iMaster ){
- while( (mem3.aPool[mem3.iMaster-1].u.hdr.size4x&2)==0 ){
- size = mem3.aPool[mem3.iMaster-1].u.hdr.prevSize;
- mem3.iMaster -= size;
- mem3.szMaster += size;
- memsys3Unlink(mem3.iMaster);
- x = mem3.aPool[mem3.iMaster-1].u.hdr.size4x & 2;
- mem3.aPool[mem3.iMaster-1].u.hdr.size4x = mem3.szMaster*4 | x;
- mem3.aPool[mem3.iMaster+mem3.szMaster-1].u.hdr.prevSize = mem3.szMaster;
+ /* Try to expand the key using the newly freed chunk */
+ if( mem3.iKeyBlk ){
+ while( (mem3.aPool[mem3.iKeyBlk-1].u.hdr.size4x&2)==0 ){
+ size = mem3.aPool[mem3.iKeyBlk-1].u.hdr.prevSize;
+ mem3.iKeyBlk -= size;
+ mem3.szKeyBlk += size;
+ memsys3Unlink(mem3.iKeyBlk);
+ x = mem3.aPool[mem3.iKeyBlk-1].u.hdr.size4x & 2;
+ mem3.aPool[mem3.iKeyBlk-1].u.hdr.size4x = mem3.szKeyBlk*4 | x;
+ mem3.aPool[mem3.iKeyBlk+mem3.szKeyBlk-1].u.hdr.prevSize = mem3.szKeyBlk;
}
- x = mem3.aPool[mem3.iMaster-1].u.hdr.size4x & 2;
- while( (mem3.aPool[mem3.iMaster+mem3.szMaster-1].u.hdr.size4x&1)==0 ){
- memsys3Unlink(mem3.iMaster+mem3.szMaster);
- mem3.szMaster += mem3.aPool[mem3.iMaster+mem3.szMaster-1].u.hdr.size4x/4;
- mem3.aPool[mem3.iMaster-1].u.hdr.size4x = mem3.szMaster*4 | x;
- mem3.aPool[mem3.iMaster+mem3.szMaster-1].u.hdr.prevSize = mem3.szMaster;
+ x = mem3.aPool[mem3.iKeyBlk-1].u.hdr.size4x & 2;
+ while( (mem3.aPool[mem3.iKeyBlk+mem3.szKeyBlk-1].u.hdr.size4x&1)==0 ){
+ memsys3Unlink(mem3.iKeyBlk+mem3.szKeyBlk);
+ mem3.szKeyBlk += mem3.aPool[mem3.iKeyBlk+mem3.szKeyBlk-1].u.hdr.size4x/4;
+ mem3.aPool[mem3.iKeyBlk-1].u.hdr.size4x = mem3.szKeyBlk*4 | x;
+ mem3.aPool[mem3.iKeyBlk+mem3.szKeyBlk-1].u.hdr.prevSize = mem3.szKeyBlk;
}
}
}
@@ -23771,7 +25348,7 @@ static void *memsys3Malloc(int nBytes){
memsys3Enter();
p = memsys3MallocUnsafe(nBytes);
memsys3Leave();
- return (void*)p;
+ return (void*)p;
}
/*
@@ -23829,11 +25406,11 @@ static int memsys3Init(void *NotUsed){
mem3.aPool = (Mem3Block *)sqlite3GlobalConfig.pHeap;
mem3.nPool = (sqlite3GlobalConfig.nHeap / sizeof(Mem3Block)) - 2;
- /* Initialize the master block. */
- mem3.szMaster = mem3.nPool;
- mem3.mnMaster = mem3.szMaster;
- mem3.iMaster = 1;
- mem3.aPool[0].u.hdr.size4x = (mem3.szMaster<<2) + 2;
+ /* Initialize the key block. */
+ mem3.szKeyBlk = mem3.nPool;
+ mem3.mnKeyBlk = mem3.szKeyBlk;
+ mem3.iKeyBlk = 1;
+ mem3.aPool[0].u.hdr.size4x = (mem3.szKeyBlk<<2) + 2;
mem3.aPool[mem3.nPool].u.hdr.prevSize = mem3.nPool;
mem3.aPool[mem3.nPool].u.hdr.size4x = 1;
@@ -23852,7 +25429,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){
@@ -23893,7 +25470,7 @@ SQLITE_PRIVATE void sqlite3Memsys3Dump(const char *zFilename){
fprintf(out, "%p %6d bytes checked out\n", &mem3.aPool[i], (size/4)*8-8);
}else{
fprintf(out, "%p %6d bytes free%s\n", &mem3.aPool[i], (size/4)*8-8,
- i==mem3.iMaster ? " **master**" : "");
+ i==mem3.iKeyBlk ? " **key**" : "");
}
}
for(i=0; i= M*(1 + log2(n)/2) - n + 1
@@ -24010,7 +25587,7 @@ SQLITE_PRIVATE const sqlite3_mem_methods *sqlite3MemGetMemsys3(void){
/* #include "sqliteInt.h" */
/*
-** 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
@@ -24055,7 +25632,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.
*/
@@ -24074,7 +25651,7 @@ static SQLITE_WSD struct Mem5Global {
u32 maxCount; /* Maximum instantaneous currentCount */
u32 maxRequest; /* Largest allocation (exclusive of internal frag) */
#endif
-
+
/*
** Lists of free blocks. aiFreelist[0] is a list of free blocks of
** size mem5.szAtom. aiFreelist[1] holds blocks of size szAtom*2.
@@ -24250,7 +25827,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 = (int)(((u8 *)pOld-mem5.zPool)/mem5.szAtom);
@@ -24319,7 +25896,7 @@ static void *memsys5Malloc(int nBytes){
p = memsys5MallocUnsafe(nBytes);
memsys5Leave();
}
- return (void*)p;
+ return (void*)p;
}
/*
@@ -24332,14 +25909,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
@@ -24472,7 +26049,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){
@@ -24514,7 +26091,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.
*/
@@ -24569,7 +26146,7 @@ static SQLITE_WSD int mutexIsInit = 0;
/*
** This block (enclosed by SQLITE_ENABLE_MULTITHREADED_CHECKS) contains
** the implementation of a wrapper around the system default mutex
-** implementation (sqlite3DefaultMutex()).
+** implementation (sqlite3DefaultMutex()).
**
** Most calls are passed directly through to the underlying default
** mutex implementation. Except, if a mutex is configured by calling
@@ -24580,7 +26157,7 @@ static SQLITE_WSD int mutexIsInit = 0;
** apps that usually use SQLITE_CONFIG_MULTITHREAD mode.
*/
-/*
+/*
** Type for all mutexes used when SQLITE_ENABLE_MULTITHREADED_CHECKS
** is defined. Variable CheckMutex.mutex is a pointer to the real mutex
** allocated by the system mutex implementation. Variable iType is usually set
@@ -24597,9 +26174,9 @@ struct CheckMutex {
#define SQLITE_MUTEX_WARNONCONTENTION (-1)
-/*
+/*
** Pointer to real mutex methods object used by the CheckMutex
-** implementation. Set by checkMutexInit().
+** implementation. Set by checkMutexInit().
*/
static SQLITE_WSD const sqlite3_mutex_methods *pGlobalMutexMethods;
@@ -24615,13 +26192,13 @@ static int checkMutexNotheld(sqlite3_mutex *p){
/*
** Initialize and deinitialize the mutex subsystem.
*/
-static int checkMutexInit(void){
+static int checkMutexInit(void){
pGlobalMutexMethods = sqlite3DefaultMutex();
- return SQLITE_OK;
+ return SQLITE_OK;
}
-static int checkMutexEnd(void){
+static int checkMutexEnd(void){
pGlobalMutexMethods = 0;
- return SQLITE_OK;
+ return SQLITE_OK;
}
/*
@@ -24695,7 +26272,7 @@ static void checkMutexEnter(sqlite3_mutex *p){
if( SQLITE_OK==pGlobalMutexMethods->xMutexTry(pCheck->mutex) ){
return;
}
- sqlite3_log(SQLITE_MISUSE,
+ sqlite3_log(SQLITE_MISUSE,
"illegal multi-threaded access to database connection"
);
}
@@ -24754,11 +26331,11 @@ SQLITE_PRIVATE void sqlite3MutexWarnOnContention(sqlite3_mutex *p){
/*
** 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
+ ** 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.
*/
@@ -24792,6 +26369,7 @@ SQLITE_PRIVATE int sqlite3MutexInit(void){
GLOBAL(int, mutexIsInit) = 1;
#endif
+ sqlite3MemoryBarrier();
return rc;
}
@@ -24869,7 +26447,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.
*/
@@ -24938,9 +26516,9 @@ SQLITE_API int sqlite3_mutex_notheld(sqlite3_mutex *p){
*/
static int noopMutexInit(void){ return SQLITE_OK; }
static int noopMutexEnd(void){ return SQLITE_OK; }
-static sqlite3_mutex *noopMutexAlloc(int id){
+static sqlite3_mutex *noopMutexAlloc(int id){
UNUSED_PARAMETER(id);
- return (sqlite3_mutex*)8;
+ return (sqlite3_mutex*)8;
}
static void noopMutexFree(sqlite3_mutex *p){ UNUSED_PARAMETER(p); return; }
static void noopMutexEnter(sqlite3_mutex *p){ UNUSED_PARAMETER(p); return; }
@@ -25005,7 +26583,7 @@ 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[SQLITE_MUTEX_STATIC_VFS3 - 1];
@@ -25183,7 +26761,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.
@@ -25231,7 +26809,7 @@ static int pthreadMutexEnd(void){ return SQLITE_OK; }
**
** - SQLITE_MUTEX_FAST
**
- SQLITE_MUTEX_RECURSIVE
-**
- SQLITE_MUTEX_STATIC_MASTER
+**
- SQLITE_MUTEX_STATIC_MAIN
**
- SQLITE_MUTEX_STATIC_MEM
**
- SQLITE_MUTEX_STATIC_OPEN
**
- SQLITE_MUTEX_STATIC_PRNG
@@ -25265,7 +26843,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.
*/
@@ -25376,7 +26954,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.
@@ -25419,7 +26997,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.
@@ -25591,7 +27169,7 @@ SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3DefaultMutex(void){
******************************************************************************
**
** This file contains inline asm code for retrieving "high-performance"
-** counters for x86 class CPUs.
+** counters for x86 and x86_64 class CPUs.
*/
#ifndef SQLITE_HWTIME_H
#define SQLITE_HWTIME_H
@@ -25602,8 +27180,9 @@ SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3DefaultMutex(void){
** processor and returns that value. This can be used for high-res
** profiling.
*/
-#if (defined(__GNUC__) || defined(_MSC_VER)) && \
- (defined(i386) || defined(__i386__) || defined(_M_IX86))
+#if !defined(__STRICT_ANSI__) && \
+ (defined(__GNUC__) || defined(_MSC_VER)) && \
+ (defined(i386) || defined(__i386__) || defined(_M_IX86))
#if defined(__GNUC__)
@@ -25624,15 +27203,15 @@ SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3DefaultMutex(void){
#endif
-#elif (defined(__GNUC__) && defined(__x86_64__))
+#elif !defined(__STRICT_ANSI__) && (defined(__GNUC__) && defined(__x86_64__))
__inline__ sqlite_uint64 sqlite3Hwtime(void){
unsigned long val;
__asm__ __volatile__ ("rdtsc" : "=A" (val));
return val;
}
-
-#elif (defined(__GNUC__) && defined(__ppc__))
+
+#elif !defined(__STRICT_ANSI__) && (defined(__GNUC__) && defined(__ppc__))
__inline__ sqlite_uint64 sqlite3Hwtime(void){
unsigned long long retval;
@@ -25649,14 +27228,13 @@ SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3DefaultMutex(void){
#else
- #error Need implementation of sqlite3Hwtime() for your platform.
-
/*
- ** To compile without implementing sqlite3Hwtime() for your platform,
- ** you can remove the above #error and use the following
- ** stub function. You will lose timing support for many
- ** of the debugging and testing utilities, but it should at
- ** least compile and run.
+ ** asm() is needed for hardware timing support. Without asm(),
+ ** disable the sqlite3Hwtime() routine.
+ **
+ ** sqlite3Hwtime() is only used for some obscure debugging
+ ** and analysis configurations, not in any deliverable, so this
+ ** should not be a great loss.
*/
SQLITE_PRIVATE sqlite_uint64 sqlite3Hwtime(void){ return ((sqlite_uint64)0); }
@@ -25977,7 +27555,7 @@ static int winMutexEnd(void){
**
** - SQLITE_MUTEX_FAST
**
- SQLITE_MUTEX_RECURSIVE
-**
- SQLITE_MUTEX_STATIC_MASTER
+**
- SQLITE_MUTEX_STATIC_MAIN
**
- SQLITE_MUTEX_STATIC_MEM
**
- SQLITE_MUTEX_STATIC_OPEN
**
- SQLITE_MUTEX_STATIC_PRNG
@@ -26240,19 +27818,27 @@ SQLITE_API int sqlite3_release_memory(int n){
#endif
}
+/*
+** Default value of the hard heap limit. 0 means "no limit".
+*/
+#ifndef SQLITE_MAX_MEMORY
+# define SQLITE_MAX_MEMORY 0
+#endif
+
/*
** State information local to the memory allocation subsystem.
*/
static SQLITE_WSD struct Mem0Global {
sqlite3_mutex *mutex; /* Mutex to serialize access */
sqlite3_int64 alarmThreshold; /* The soft heap limit */
+ sqlite3_int64 hardLimit; /* The hard upper bound on memory */
/*
** True if heap is nearly "full" where "full" is defined by the
** sqlite3_soft_heap_limit() setting.
*/
int nearlyFull;
-} mem0 = { 0, 0, 0 };
+} mem0 = { 0, SQLITE_MAX_MEMORY, SQLITE_MAX_MEMORY, 0 };
#define mem0 GLOBAL(struct Mem0Global, mem0)
@@ -26282,8 +27868,15 @@ SQLITE_API int sqlite3_memory_alarm(
#endif
/*
-** Set the soft heap-size limit for the library. Passing a zero or
-** negative value indicates no limit.
+** Set the soft heap-size limit for the library. An argument of
+** zero disables the limit. A negative argument is a no-op used to
+** obtain the return value.
+**
+** The return value is the value of the heap limit just before this
+** interface was called.
+**
+** If the hard heap limit is enabled, then the soft heap limit cannot
+** be disabled nor raised above the hard heap limit.
*/
SQLITE_API sqlite3_int64 sqlite3_soft_heap_limit64(sqlite3_int64 n){
sqlite3_int64 priorLimit;
@@ -26299,9 +27892,12 @@ SQLITE_API sqlite3_int64 sqlite3_soft_heap_limit64(sqlite3_int64 n){
sqlite3_mutex_leave(mem0.mutex);
return priorLimit;
}
+ if( mem0.hardLimit>0 && (n>mem0.hardLimit || n==0) ){
+ n = mem0.hardLimit;
+ }
mem0.alarmThreshold = n;
nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED);
- mem0.nearlyFull = (n>0 && n<=nUsed);
+ AtomicStore(&mem0.nearlyFull, n>0 && n<=nUsed);
sqlite3_mutex_leave(mem0.mutex);
excess = sqlite3_memory_used() - n;
if( excess>0 ) sqlite3_release_memory((int)(excess & 0x7fffffff));
@@ -26312,6 +27908,37 @@ SQLITE_API void sqlite3_soft_heap_limit(int n){
sqlite3_soft_heap_limit64(n);
}
+/*
+** Set the hard heap-size limit for the library. An argument of zero
+** disables the hard heap limit. A negative argument is a no-op used
+** to obtain the return value without affecting the hard heap limit.
+**
+** The return value is the value of the hard heap limit just prior to
+** calling this interface.
+**
+** Setting the hard heap limit will also activate the soft heap limit
+** and constrain the soft heap limit to be no more than the hard heap
+** limit.
+*/
+SQLITE_API sqlite3_int64 sqlite3_hard_heap_limit64(sqlite3_int64 n){
+ sqlite3_int64 priorLimit;
+#ifndef SQLITE_OMIT_AUTOINIT
+ int rc = sqlite3_initialize();
+ if( rc ) return -1;
+#endif
+ sqlite3_mutex_enter(mem0.mutex);
+ priorLimit = mem0.hardLimit;
+ if( n>=0 ){
+ mem0.hardLimit = n;
+ if( nSQLITE_MAX_MEMORY ){
- *pp = 0;
- return;
- }
-#endif
-
sqlite3StatusHighwater(SQLITE_STATUS_MALLOC_SIZE, n);
if( mem0.alarmThreshold>0 ){
sqlite3_int64 nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED);
if( nUsed >= mem0.alarmThreshold - nFull ){
- mem0.nearlyFull = 1;
+ AtomicStore(&mem0.nearlyFull, 1);
sqlite3MallocAlarm(nFull);
+ if( mem0.hardLimit ){
+ nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED);
+ if( nUsed >= mem0.hardLimit - nFull ){
+ *pp = 0;
+ return;
+ }
+ }
}else{
- mem0.nearlyFull = 0;
+ AtomicStore(&mem0.nearlyFull, 0);
}
}
p = sqlite3GlobalConfig.m.xMalloc(nFull);
@@ -26491,10 +28117,17 @@ SQLITE_PRIVATE int sqlite3MallocSize(void *p){
assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) );
return sqlite3GlobalConfig.m.xSize(p);
}
+static int lookasideMallocSize(sqlite3 *db, void *p){
+#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE
+ return plookaside.pMiddle ? db->lookaside.szTrue : LOOKASIDE_SMALL;
+#else
+ return db->lookaside.szTrue;
+#endif
+}
SQLITE_PRIVATE int sqlite3DbMallocSize(sqlite3 *db, void *p){
assert( p!=0 );
- if( db==0 || !isLookaside(db,p) ){
#ifdef SQLITE_DEBUG
+ if( db==0 || !isLookaside(db,p) ){
if( db==0 ){
assert( sqlite3MemdebugNoType(p, (u8)~MEMTYPE_HEAP) );
assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) );
@@ -26502,12 +28135,23 @@ SQLITE_PRIVATE int sqlite3DbMallocSize(sqlite3 *db, void *p){
assert( sqlite3MemdebugHasType(p, (MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
assert( sqlite3MemdebugNoType(p, (u8)~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
}
-#endif
- return sqlite3GlobalConfig.m.xSize(p);
- }else{
- assert( sqlite3_mutex_held(db->mutex) );
- return db->lookaside.sz;
}
+#endif
+ if( db ){
+ if( ((uptr)p)<(uptr)(db->lookaside.pEnd) ){
+#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE
+ if( ((uptr)p)>=(uptr)(db->lookaside.pMiddle) ){
+ assert( sqlite3_mutex_held(db->mutex) );
+ return LOOKASIDE_SMALL;
+ }
+#endif
+ if( ((uptr)p)>=(uptr)(db->lookaside.pStart) ){
+ assert( sqlite3_mutex_held(db->mutex) );
+ return db->lookaside.szTrue;
+ }
+ }
+ }
+ return sqlite3GlobalConfig.m.xSize(p);
}
SQLITE_API sqlite3_uint64 sqlite3_msize(void *p){
assert( sqlite3MemdebugNoType(p, (u8)~MEMTYPE_HEAP) );
@@ -26554,15 +28198,27 @@ SQLITE_PRIVATE void sqlite3DbFreeNN(sqlite3 *db, void *p){
measureAllocationSize(db, p);
return;
}
- if( isLookaside(db, p) ){
- LookasideSlot *pBuf = (LookasideSlot*)p;
+ if( ((uptr)p)<(uptr)(db->lookaside.pEnd) ){
+#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE
+ if( ((uptr)p)>=(uptr)(db->lookaside.pMiddle) ){
+ LookasideSlot *pBuf = (LookasideSlot*)p;
#ifdef SQLITE_DEBUG
- /* Trash all content in the buffer being freed */
- memset(p, 0xaa, db->lookaside.sz);
+ memset(p, 0xaa, LOOKASIDE_SMALL); /* Trash freed content */
#endif
- pBuf->pNext = db->lookaside.pFree;
- db->lookaside.pFree = pBuf;
- return;
+ pBuf->pNext = db->lookaside.pSmallFree;
+ db->lookaside.pSmallFree = pBuf;
+ return;
+ }
+#endif /* SQLITE_OMIT_TWOSIZE_LOOKASIDE */
+ if( ((uptr)p)>=(uptr)(db->lookaside.pStart) ){
+ LookasideSlot *pBuf = (LookasideSlot*)p;
+#ifdef SQLITE_DEBUG
+ memset(p, 0xaa, db->lookaside.szTrue); /* Trash freed content */
+#endif
+ pBuf->pNext = db->lookaside.pFree;
+ db->lookaside.pFree = pBuf;
+ return;
+ }
}
}
assert( sqlite3MemdebugHasType(p, (MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
@@ -26603,18 +28259,25 @@ SQLITE_PRIVATE void *sqlite3Realloc(void *pOld, u64 nBytes){
if( nOld==nNew ){
pNew = pOld;
}else if( sqlite3GlobalConfig.bMemstat ){
+ sqlite3_int64 nUsed;
sqlite3_mutex_enter(mem0.mutex);
sqlite3StatusHighwater(SQLITE_STATUS_MALLOC_SIZE, (int)nBytes);
nDiff = nNew - nOld;
- if( nDiff>0 && sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED) >=
+ if( nDiff>0 && (nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED)) >=
mem0.alarmThreshold-nDiff ){
sqlite3MallocAlarm(nDiff);
+ if( mem0.hardLimit>0 && nUsed >= mem0.hardLimit - nDiff ){
+ sqlite3_mutex_leave(mem0.mutex);
+ return 0;
+ }
}
pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew);
+#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
if( pNew==0 && mem0.alarmThreshold>0 ){
sqlite3MallocAlarm((int)nBytes);
pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew);
}
+#endif
if( pNew ){
nNew = sqlite3MallocSize(pNew);
sqlite3StatusUp(SQLITE_STATUS_MEMORY_USED, nNew-nOld);
@@ -26648,7 +28311,7 @@ SQLITE_API void *sqlite3_realloc64(void *pOld, sqlite3_uint64 n){
/*
** Allocate and zero memory.
-*/
+*/
SQLITE_PRIVATE void *sqlite3MallocZero(u64 n){
void *p = sqlite3Malloc(n);
if( p ){
@@ -26678,13 +28341,13 @@ static SQLITE_NOINLINE void *dbMallocRawFinish(sqlite3 *db, u64 n){
assert( db!=0 );
p = sqlite3Malloc(n);
if( !p ) sqlite3OomFault(db);
- sqlite3MemdebugSetType(p,
+ sqlite3MemdebugSetType(p,
(db->lookaside.bDisable==0) ? MEMTYPE_LOOKASIDE : MEMTYPE_HEAP);
return p;
}
/*
-** Allocate memory, either lookaside (if possible) or heap.
+** Allocate memory, either lookaside (if possible) or heap.
** If the allocation fails, set the mallocFailed flag in
** the connection pointer.
**
@@ -26718,23 +28381,37 @@ SQLITE_PRIVATE void *sqlite3DbMallocRawNN(sqlite3 *db, u64 n){
assert( db!=0 );
assert( sqlite3_mutex_held(db->mutex) );
assert( db->pnBytesFreed==0 );
- if( db->lookaside.bDisable==0 ){
- assert( db->mallocFailed==0 );
- if( n>db->lookaside.sz ){
+ if( n>db->lookaside.sz ){
+ if( !db->lookaside.bDisable ){
db->lookaside.anStat[1]++;
- }else if( (pBuf = db->lookaside.pFree)!=0 ){
- db->lookaside.pFree = pBuf->pNext;
- db->lookaside.anStat[0]++;
- return (void*)pBuf;
- }else if( (pBuf = db->lookaside.pInit)!=0 ){
- db->lookaside.pInit = pBuf->pNext;
- db->lookaside.anStat[0]++;
- return (void*)pBuf;
- }else{
- db->lookaside.anStat[2]++;
+ }else if( db->mallocFailed ){
+ return 0;
}
- }else if( db->mallocFailed ){
- return 0;
+ return dbMallocRawFinish(db, n);
+ }
+#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE
+ if( n<=LOOKASIDE_SMALL ){
+ if( (pBuf = db->lookaside.pSmallFree)!=0 ){
+ db->lookaside.pSmallFree = pBuf->pNext;
+ db->lookaside.anStat[0]++;
+ return (void*)pBuf;
+ }else if( (pBuf = db->lookaside.pSmallInit)!=0 ){
+ db->lookaside.pSmallInit = pBuf->pNext;
+ db->lookaside.anStat[0]++;
+ return (void*)pBuf;
+ }
+ }
+#endif
+ if( (pBuf = db->lookaside.pFree)!=0 ){
+ db->lookaside.pFree = pBuf->pNext;
+ db->lookaside.anStat[0]++;
+ return (void*)pBuf;
+ }else if( (pBuf = db->lookaside.pInit)!=0 ){
+ db->lookaside.pInit = pBuf->pNext;
+ db->lookaside.anStat[0]++;
+ return (void*)pBuf;
+ }else{
+ db->lookaside.anStat[2]++;
}
#else
assert( db!=0 );
@@ -26758,7 +28435,16 @@ SQLITE_PRIVATE void *sqlite3DbRealloc(sqlite3 *db, void *p, u64 n){
assert( db!=0 );
if( p==0 ) return sqlite3DbMallocRawNN(db, n);
assert( sqlite3_mutex_held(db->mutex) );
- if( isLookaside(db,p) && n<=db->lookaside.sz ) return p;
+ if( ((uptr)p)<(uptr)db->lookaside.pEnd ){
+#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE
+ if( ((uptr)p)>=(uptr)db->lookaside.pMiddle ){
+ if( n<=LOOKASIDE_SMALL ) return p;
+ }else
+#endif
+ if( ((uptr)p)>=(uptr)db->lookaside.pStart ){
+ if( n<=db->lookaside.szTrue ) return p;
+ }
+ }
return dbReallocFinish(db, p, n);
}
static SQLITE_NOINLINE void *dbReallocFinish(sqlite3 *db, void *p, u64 n){
@@ -26769,14 +28455,14 @@ static SQLITE_NOINLINE void *dbReallocFinish(sqlite3 *db, void *p, u64 n){
if( isLookaside(db, p) ){
pNew = sqlite3DbMallocRawNN(db, n);
if( pNew ){
- memcpy(pNew, p, db->lookaside.sz);
+ memcpy(pNew, p, lookasideMallocSize(db, p));
sqlite3DbFree(db, p);
}
}else{
assert( sqlite3MemdebugHasType(p, (MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
assert( sqlite3MemdebugNoType(p, (u8)~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
- pNew = sqlite3_realloc64(p, n);
+ pNew = sqlite3Realloc(p, n);
if( !pNew ){
sqlite3OomFault(db);
}
@@ -26801,9 +28487,9 @@ SQLITE_PRIVATE void *sqlite3DbReallocOrFree(sqlite3 *db, void *p, u64 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.
*/
@@ -26823,11 +28509,9 @@ SQLITE_PRIVATE char *sqlite3DbStrDup(sqlite3 *db, const char *z){
SQLITE_PRIVATE char *sqlite3DbStrNDup(sqlite3 *db, const char *z, u64 n){
char *zNew;
assert( db!=0 );
- if( z==0 ){
- return 0;
- }
+ assert( z!=0 || n==0 );
assert( (n&0x7fffffff)==n );
- zNew = sqlite3DbMallocRawNN(db, n+1);
+ zNew = z ? sqlite3DbMallocRawNN(db, n+1) : 0;
if( zNew ){
memcpy(zNew, z, (size_t)n);
zNew[n] = 0;
@@ -26866,9 +28550,12 @@ SQLITE_PRIVATE void sqlite3OomFault(sqlite3 *db){
if( db->mallocFailed==0 && db->bBenignMalloc==0 ){
db->mallocFailed = 1;
if( db->nVdbeExec>0 ){
- db->u1.isInterrupted = 1;
+ AtomicStore(&db->u1.isInterrupted, 1);
+ }
+ DisableLookaside;
+ if( db->pParse ){
+ db->pParse->rc = SQLITE_NOMEM_BKPT;
}
- db->lookaside.bDisable++;
}
}
@@ -26882,42 +28569,45 @@ SQLITE_PRIVATE void sqlite3OomFault(sqlite3 *db){
SQLITE_PRIVATE void sqlite3OomClear(sqlite3 *db){
if( db->mallocFailed && db->nVdbeExec==0 ){
db->mallocFailed = 0;
- db->u1.isInterrupted = 0;
+ AtomicStore(&db->u1.isInterrupted, 0);
assert( db->lookaside.bDisable>0 );
- db->lookaside.bDisable--;
+ EnableLookaside;
}
}
/*
-** Take actions at the end of an API call to indicate an OOM error
+** Take actions at the end of an API call to deal with error codes.
*/
-static SQLITE_NOINLINE int apiOomError(sqlite3 *db){
- sqlite3OomClear(db);
- sqlite3Error(db, SQLITE_NOMEM);
- return SQLITE_NOMEM_BKPT;
+static SQLITE_NOINLINE int apiHandleError(sqlite3 *db, int rc){
+ if( db->mallocFailed || rc==SQLITE_IOERR_NOMEM ){
+ sqlite3OomClear(db);
+ sqlite3Error(db, SQLITE_NOMEM);
+ return SQLITE_NOMEM_BKPT;
+ }
+ return rc & db->errMask;
}
/*
-** 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 an OOM as occurred, then the connection error-code (the value
** returned by sqlite3_errcode()) is set to SQLITE_NOMEM.
*/
SQLITE_PRIVATE int sqlite3ApiExit(sqlite3* db, int rc){
/* If the db handle must hold the connection handle mutex here.
- ** Otherwise the read (and possible write) of db->mallocFailed
+ ** Otherwise the read (and possible write) of db->mallocFailed
** is unsafe, as is the call to sqlite3Error().
*/
assert( db!=0 );
assert( sqlite3_mutex_held(db->mutex) );
- if( db->mallocFailed || rc==SQLITE_IOERR_NOMEM ){
- return apiOomError(db);
+ if( db->mallocFailed || rc ){
+ return apiHandleError(db, rc);
}
return rc & db->errMask;
}
@@ -26926,7 +28616,7 @@ SQLITE_PRIVATE int sqlite3ApiExit(sqlite3* db, int rc){
/************** Begin file printf.c ******************************************/
/*
** The "printf" code that follows dates from the 1980's. It is in
-** the public domain.
+** the public domain.
**
**************************************************************************
**
@@ -26955,7 +28645,7 @@ SQLITE_PRIVATE int sqlite3ApiExit(sqlite3* db, int rc){
#define etSQLESCAPE2 10 /* Strings with '\'' doubled and enclosed in '',
NULL pointers replaced by SQL NULL. %Q */
#define etTOKEN 11 /* a pointer to a Token structure */
-#define etSRCLIST 12 /* a pointer to a SrcList */
+#define etSRCITEM 12 /* a pointer to a SrcItem */
#define etPOINTER 13 /* The %p conversion */
#define etSQLESCAPE3 14 /* %w -> Strings with '\"' doubled */
#define etORDINAL 15 /* %r -> 1st, 2nd, 3rd, 4th, etc. English only */
@@ -27021,10 +28711,22 @@ static const et_info fmtinfo[] = {
/* All the rest are undocumented and are for internal use only */
{ 'T', 0, 0, etTOKEN, 0, 0 },
- { 'S', 0, 0, etSRCLIST, 0, 0 },
+ { 'S', 0, 0, etSRCITEM, 0, 0 },
{ 'r', 10, 1, etORDINAL, 0, 0 },
};
+/* Notes:
+**
+** %S Takes a pointer to SrcItem. Shows name or database.name
+** %!S Like %S but prefer the zName over the zAlias
+*/
+
+/* Floating point constants used for rounding */
+static const double arRound[] = {
+ 5.0e-01, 5.0e-02, 5.0e-03, 5.0e-04, 5.0e-05,
+ 5.0e-06, 5.0e-07, 5.0e-08, 5.0e-09, 5.0e-10,
+};
+
/*
** If SQLITE_OMIT_FLOATING_POINT is defined, then none of the floating point
** conversions will work.
@@ -27062,7 +28764,8 @@ static char et_getdigit(LONGDOUBLE_TYPE *val, int *cnt){
static void setStrAccumError(StrAccum *p, u8 eError){
assert( eError==SQLITE_NOMEM || eError==SQLITE_TOOBIG );
p->accError = eError;
- p->nAlloc = 0;
+ if( p->mxAlloc ) sqlite3_str_reset(p);
+ if( eError==SQLITE_TOOBIG ) sqlite3ErrorToParser(p->db, eError);
}
/*
@@ -27081,6 +28784,28 @@ static char *getTextArg(PrintfArguments *p){
return (char*)sqlite3_value_text(p->apArg[p->nUsed++]);
}
+/*
+** Allocate memory for a temporary buffer needed for printf rendering.
+**
+** If the requested size of the temp buffer is larger than the size
+** of the output buffer in pAccum, then cause an SQLITE_TOOBIG error.
+** Do the size check before the memory allocation to prevent rogue
+** SQL from requesting large allocations using the precision or width
+** field of the printf() function.
+*/
+static char *printfTempBuf(sqlite3_str *pAccum, sqlite3_int64 n){
+ char *z;
+ if( pAccum->accError ) return 0;
+ if( n>pAccum->nAlloc && n>pAccum->mxAlloc ){
+ setStrAccumError(pAccum, SQLITE_TOOBIG);
+ return 0;
+ }
+ z = sqlite3DbMallocRaw(pAccum->db, n);
+ if( z==0 ){
+ setStrAccumError(pAccum, SQLITE_NOMEM);
+ }
+ return z;
+}
/*
** On machines with a small stack size, you can redefine the
@@ -27091,6 +28816,13 @@ static char *getTextArg(PrintfArguments *p){
#endif
#define etBUFSIZE SQLITE_PRINT_BUF_SIZE /* Size of the output buffer */
+/*
+** Hard limit on the precision of floating-point conversions.
+*/
+#ifndef SQLITE_PRINTF_PRECISION_LIMIT
+# define SQLITE_FP_PRECISION_LIMIT 100000000
+#endif
+
/*
** Render a string given by "fmt" into the StrAccum object.
*/
@@ -27132,7 +28864,7 @@ SQLITE_API void sqlite3_str_vappendf(
PrintfArguments *pArgList = 0; /* Arguments for SQLITE_PRINTF_SQLFUNC */
char buf[etBUFSIZE]; /* Conversion buffer */
- /* pAccum never starts out with an empty buffer that was obtained from
+ /* pAccum never starts out with an empty buffer that was obtained from
** malloc(). This precondition is required by the mprintf("%z...")
** optimization. */
assert( pAccum->nChar>0 || (pAccum->printfFlags&SQLITE_PRINTF_MALLOCED)==0 );
@@ -27163,6 +28895,9 @@ SQLITE_API void sqlite3_str_vappendf(
flag_leftjustify = flag_prefix = cThousand =
flag_alternateform = flag_altform2 = flag_zeropad = 0;
done = 0;
+ width = 0;
+ flag_long = 0;
+ precision = -1;
do{
switch( c ){
case '-': flag_leftjustify = 1; break;
@@ -27173,80 +28908,93 @@ SQLITE_API void sqlite3_str_vappendf(
case '0': flag_zeropad = 1; break;
case ',': cThousand = ','; break;
default: done = 1; break;
+ case 'l': {
+ flag_long = 1;
+ c = *++fmt;
+ if( c=='l' ){
+ c = *++fmt;
+ flag_long = 2;
+ }
+ done = 1;
+ break;
+ }
+ case '1': case '2': case '3': case '4': case '5':
+ case '6': case '7': case '8': case '9': {
+ unsigned wx = c - '0';
+ while( (c = *++fmt)>='0' && c<='9' ){
+ wx = wx*10 + c - '0';
+ }
+ testcase( wx>0x7fffffff );
+ width = wx & 0x7fffffff;
+#ifdef SQLITE_PRINTF_PRECISION_LIMIT
+ if( width>SQLITE_PRINTF_PRECISION_LIMIT ){
+ width = SQLITE_PRINTF_PRECISION_LIMIT;
+ }
+#endif
+ if( c!='.' && c!='l' ){
+ done = 1;
+ }else{
+ fmt--;
+ }
+ break;
+ }
+ case '*': {
+ if( bArgList ){
+ width = (int)getIntArg(pArgList);
+ }else{
+ width = va_arg(ap,int);
+ }
+ if( width<0 ){
+ flag_leftjustify = 1;
+ width = width >= -2147483647 ? -width : 0;
+ }
+#ifdef SQLITE_PRINTF_PRECISION_LIMIT
+ if( width>SQLITE_PRINTF_PRECISION_LIMIT ){
+ width = SQLITE_PRINTF_PRECISION_LIMIT;
+ }
+#endif
+ if( (c = fmt[1])!='.' && c!='l' ){
+ c = *++fmt;
+ done = 1;
+ }
+ break;
+ }
+ case '.': {
+ c = *++fmt;
+ if( c=='*' ){
+ if( bArgList ){
+ precision = (int)getIntArg(pArgList);
+ }else{
+ precision = va_arg(ap,int);
+ }
+ if( precision<0 ){
+ precision = precision >= -2147483647 ? -precision : -1;
+ }
+ c = *++fmt;
+ }else{
+ unsigned px = 0;
+ while( c>='0' && c<='9' ){
+ px = px*10 + c - '0';
+ c = *++fmt;
+ }
+ testcase( px>0x7fffffff );
+ precision = px & 0x7fffffff;
+ }
+#ifdef SQLITE_PRINTF_PRECISION_LIMIT
+ if( precision>SQLITE_PRINTF_PRECISION_LIMIT ){
+ precision = SQLITE_PRINTF_PRECISION_LIMIT;
+ }
+#endif
+ if( c=='l' ){
+ --fmt;
+ }else{
+ done = 1;
+ }
+ break;
+ }
}
}while( !done && (c=(*++fmt))!=0 );
- /* Get the field width */
- if( c=='*' ){
- if( bArgList ){
- width = (int)getIntArg(pArgList);
- }else{
- width = va_arg(ap,int);
- }
- if( width<0 ){
- flag_leftjustify = 1;
- width = width >= -2147483647 ? -width : 0;
- }
- c = *++fmt;
- }else{
- unsigned wx = 0;
- while( c>='0' && c<='9' ){
- wx = wx*10 + c - '0';
- c = *++fmt;
- }
- testcase( wx>0x7fffffff );
- width = wx & 0x7fffffff;
- }
- assert( width>=0 );
-#ifdef SQLITE_PRINTF_PRECISION_LIMIT
- if( width>SQLITE_PRINTF_PRECISION_LIMIT ){
- width = SQLITE_PRINTF_PRECISION_LIMIT;
- }
-#endif
- /* Get the precision */
- if( c=='.' ){
- c = *++fmt;
- if( c=='*' ){
- if( bArgList ){
- precision = (int)getIntArg(pArgList);
- }else{
- precision = va_arg(ap,int);
- }
- c = *++fmt;
- if( precision<0 ){
- precision = precision >= -2147483647 ? -precision : -1;
- }
- }else{
- unsigned px = 0;
- while( c>='0' && c<='9' ){
- px = px*10 + c - '0';
- c = *++fmt;
- }
- testcase( px>0x7fffffff );
- precision = px & 0x7fffffff;
- }
- }else{
- precision = -1;
- }
- assert( precision>=(-1) );
-#ifdef SQLITE_PRINTF_PRECISION_LIMIT
- if( precision>SQLITE_PRINTF_PRECISION_LIMIT ){
- precision = SQLITE_PRINTF_PRECISION_LIMIT;
- }
-#endif
-
-
- /* Get the conversion type modifier */
- if( c=='l' ){
- flag_long = 1;
- c = *++fmt;
- if( c=='l' ){
- flag_long = 2;
- c = *++fmt;
- }
- }else{
- flag_long = 0;
- }
/* Fetch the info entry for the field */
infop = &fmtinfo[0];
xtype = etINVALID;
@@ -27275,15 +29023,17 @@ SQLITE_API void sqlite3_str_vappendf(
** xtype The class of the conversion.
** infop Pointer to the appropriate info struct.
*/
+ assert( width>=0 );
+ assert( precision>=(-1) );
switch( xtype ){
case etPOINTER:
flag_long = sizeof(char*)==sizeof(i64) ? 2 :
sizeof(char*)==sizeof(long int) ? 1 : 0;
- /* Fall through into the next case */
+ /* no break */ deliberate_fall_through
case etORDINAL:
- case etRADIX:
+ case etRADIX:
cThousand = 0;
- /* Fall through into the next case */
+ /* no break */ deliberate_fall_through
case etDECIMAL:
if( infop->flags & FLAG_SIGNED ){
i64 v;
@@ -27299,11 +29049,10 @@ SQLITE_API void sqlite3_str_vappendf(
v = va_arg(ap,int);
}
if( v<0 ){
- if( v==SMALLEST_INT64 ){
- longvalue = ((u64)1)<<63;
- }else{
- longvalue = -v;
- }
+ testcase( v==SMALLEST_INT64 );
+ testcase( v==(-1) );
+ longvalue = ~v;
+ longvalue++;
prefix = '-';
}else{
longvalue = v;
@@ -27331,12 +29080,11 @@ SQLITE_API void sqlite3_str_vappendf(
nOut = etBUFSIZE;
zOut = buf;
}else{
- u64 n = (u64)precision + 10 + precision/3;
- zOut = zExtra = sqlite3Malloc( n );
- if( zOut==0 ){
- setStrAccumError(pAccum, SQLITE_NOMEM);
- return;
- }
+ u64 n;
+ n = (u64)precision + 10;
+ if( cThousand ) n += precision/3;
+ zOut = zExtra = printfTempBuf(pAccum, n);
+ if( zOut==0 ) return;
nOut = (int)n;
}
bufpt = &zOut[nOut-1];
@@ -27397,6 +29145,11 @@ SQLITE_API void sqlite3_str_vappendf(
length = 0;
#else
if( precision<0 ) precision = 6; /* Set default precision */
+#ifdef SQLITE_FP_PRECISION_LIMIT
+ if( precision>SQLITE_FP_PRECISION_LIMIT ){
+ precision = SQLITE_FP_PRECISION_LIMIT;
+ }
+#endif
if( realvalue<0.0 ){
realvalue = -realvalue;
prefix = '-';
@@ -27405,8 +29158,18 @@ SQLITE_API void sqlite3_str_vappendf(
}
if( xtype==etGENERIC && precision>0 ) precision--;
testcase( precision>0xfff );
- for(idx=precision&0xfff, rounder=0.5; idx>0; idx--, rounder*=0.1){}
- if( xtype==etFLOAT ) realvalue += rounder;
+ idx = precision & 0xfff;
+ rounder = arRound[idx%10];
+ while( idx>=10 ){ rounder *= 1.0e-10; idx -= 10; }
+ if( xtype==etFLOAT ){
+ double rx = (double)realvalue;
+ sqlite3_uint64 u;
+ int ex;
+ memcpy(&u, &rx, sizeof(u));
+ ex = -1023 + (int)((u>>52)&0x7ff);
+ if( precision+(ex/3) < 15 ) rounder += realvalue*3e-16;
+ realvalue += rounder;
+ }
/* Normalize realvalue to within 10.0 > realvalue >= 1.0 */
exp = 0;
if( sqlite3IsNaN((double)realvalue) ){
@@ -27455,12 +29218,12 @@ SQLITE_API void sqlite3_str_vappendf(
}else{
e2 = exp;
}
- if( MAX(e2,0)+(i64)precision+(i64)width > etBUFSIZE - 15 ){
- bufpt = zExtra
- = sqlite3Malloc( MAX(e2,0)+(i64)precision+(i64)width+15 );
- if( bufpt==0 ){
- setStrAccumError(pAccum, SQLITE_NOMEM);
- return;
+ {
+ i64 szBufNeeded; /* Size of a temporary buffer needed */
+ szBufNeeded = MAX(e2,0)+(i64)precision+(i64)width+15;
+ if( szBufNeeded > etBUFSIZE ){
+ bufpt = zExtra = printfTempBuf(pAccum, szBufNeeded);
+ if( bufpt==0 ) return;
}
}
zOut = bufpt;
@@ -27669,7 +29432,7 @@ SQLITE_API void sqlite3_str_vappendf(
}
isnull = escarg==0;
if( isnull ) escarg = (xtype==etSQLESCAPE2 ? "NULL" : "(NULL)");
- /* For %q, %Q, and %w, the precision is the number of byte (or
+ /* For %q, %Q, and %w, the precision is the number of bytes (or
** characters if the ! flags is present) to use from the input.
** Because of the extra quoting characters inserted, the number
** of output characters may be larger than the precision.
@@ -27684,11 +29447,8 @@ SQLITE_API void sqlite3_str_vappendf(
needQuote = !isnull && xtype==etSQLESCAPE2;
n += i + 3;
if( n>etBUFSIZE ){
- bufpt = zExtra = sqlite3Malloc( n );
- if( bufpt==0 ){
- setStrAccumError(pAccum, SQLITE_NOMEM);
- return;
- }
+ bufpt = zExtra = printfTempBuf(pAccum, n);
+ if( bufpt==0 ) return;
}else{
bufpt = buf;
}
@@ -27715,21 +29475,24 @@ SQLITE_API void sqlite3_str_vappendf(
length = width = 0;
break;
}
- case etSRCLIST: {
- SrcList *pSrc;
- int k;
- struct SrcList_item *pItem;
+ case etSRCITEM: {
+ SrcItem *pItem;
if( (pAccum->printfFlags & SQLITE_PRINTF_INTERNAL)==0 ) return;
- pSrc = va_arg(ap, SrcList*);
- k = va_arg(ap, int);
- pItem = &pSrc->a[k];
+ pItem = va_arg(ap, SrcItem*);
assert( bArgList==0 );
- assert( k>=0 && knSrc );
- if( pItem->zDatabase ){
- sqlite3_str_appendall(pAccum, pItem->zDatabase);
- sqlite3_str_append(pAccum, ".", 1);
+ if( pItem->zAlias && !flag_altform2 ){
+ sqlite3_str_appendall(pAccum, pItem->zAlias);
+ }else if( pItem->zName ){
+ if( pItem->zDatabase ){
+ sqlite3_str_appendall(pAccum, pItem->zDatabase);
+ sqlite3_str_append(pAccum, ".", 1);
+ }
+ sqlite3_str_appendall(pAccum, pItem->zName);
+ }else if( pItem->zAlias ){
+ sqlite3_str_appendall(pAccum, pItem->zAlias);
+ }else if( ALWAYS(pItem->pSelect) ){
+ sqlite3_str_appendf(pAccum, "SUBQUERY %u", pItem->pSelect->selId);
}
- sqlite3_str_appendall(pAccum, pItem->zName);
length = width = 0;
break;
}
@@ -27778,13 +29541,12 @@ static int sqlite3StrAccumEnlarge(StrAccum *p, int N){
return 0;
}
if( p->mxAlloc==0 ){
- N = p->nAlloc - p->nChar - 1;
setStrAccumError(p, SQLITE_TOOBIG);
- return N;
+ return p->nAlloc - p->nChar - 1;
}else{
char *zOld = isMalloced(p) ? p->zText : 0;
i64 szNew = p->nChar;
- szNew += N + 1;
+ szNew += (sqlite3_int64)N + 1;
if( szNew+p->nChar<=p->mxAlloc ){
/* Force exponential buffer size growth as long as it does not overflow,
** to avoid having to call this routine too often */
@@ -27800,7 +29562,7 @@ static int sqlite3StrAccumEnlarge(StrAccum *p, int N){
if( p->db ){
zNew = sqlite3DbRealloc(p->db, zOld, p->nAlloc);
}else{
- zNew = sqlite3_realloc64(zOld, p->nAlloc);
+ zNew = sqlite3Realloc(zOld, p->nAlloc);
}
if( zNew ){
assert( p->zText!=0 || p->nChar==0 );
@@ -27852,7 +29614,7 @@ SQLITE_API void sqlite3_str_append(sqlite3_str *p, const char *z, int N){
assert( z!=0 || N==0 );
assert( p->zText!=0 || p->nChar==0 || p->accError );
assert( N>=0 );
- assert( p->accError==0 || p->nAlloc==0 );
+ assert( p->accError==0 || p->nAlloc==0 || p->mxAlloc==0 );
if( p->nChar+N >= p->nAlloc ){
enlargeAndAppend(p,z,N);
}else if( N ){
@@ -28029,7 +29791,7 @@ SQLITE_API char *sqlite3_vmprintf(const char *zFormat, va_list ap){
char zBase[SQLITE_PRINT_BUF_SIZE];
StrAccum acc;
-#ifdef SQLITE_ENABLE_API_ARMOR
+#ifdef SQLITE_ENABLE_API_ARMOR
if( zFormat==0 ){
(void)SQLITE_MISUSE_BKPT;
return 0;
@@ -28142,7 +29904,7 @@ SQLITE_API void sqlite3_log(int iErrCode, const char *zFormat, ...){
SQLITE_PRIVATE void sqlite3DebugPrintf(const char *zFormat, ...){
va_list ap;
StrAccum acc;
- char zBuf[500];
+ char zBuf[SQLITE_PRINT_BUF_SIZE*10];
sqlite3StrAccumInit(&acc, 0, zBuf, sizeof(zBuf), 0);
va_start(ap,zFormat);
sqlite3_str_vappendf(&acc, zFormat, ap);
@@ -28188,7 +29950,7 @@ SQLITE_API void sqlite3_str_appendf(StrAccum *p, const char *zFormat, ...){
**
** This file contains C code to implement the TreeView debugging routines.
** These routines print a parse tree to standard output for debugging and
-** analysis.
+** analysis.
**
** The interfaces in this file is only available when compiling
** with SQLITE_DEBUG.
@@ -28242,7 +30004,7 @@ static void sqlite3TreeViewLine(TreeView *p, const char *zFormat, ...){
va_start(ap, zFormat);
sqlite3_str_vappendf(&acc, zFormat, ap);
va_end(ap);
- assert( acc.nChar>0 );
+ assert( acc.nChar>0 || acc.accError );
sqlite3_str_append(&acc, "\n", 1);
}
sqlite3StrAccumFinish(&acc);
@@ -28282,12 +30044,15 @@ SQLITE_PRIVATE void sqlite3TreeViewWith(TreeView *pView, const With *pWith, u8 m
char cSep = '(';
int j;
for(j=0; jpCols->nExpr; j++){
- sqlite3_str_appendf(&x, "%c%s", cSep, pCte->pCols->a[j].zName);
+ sqlite3_str_appendf(&x, "%c%s", cSep, pCte->pCols->a[j].zEName);
cSep = ',';
}
sqlite3_str_appendf(&x, ")");
}
- sqlite3_str_appendf(&x, " AS");
+ if( pCte->pUse ){
+ sqlite3_str_appendf(&x, " (pUse=0x%p, nUse=%d)", pCte->pUse,
+ pCte->pUse->nUse);
+ }
sqlite3StrAccumFinish(&x);
sqlite3TreeViewItem(pView, zLine, inCte-1);
sqlite3TreeViewSelect(pView, pCte->pSelect, 0);
@@ -28297,6 +30062,42 @@ SQLITE_PRIVATE void sqlite3TreeViewWith(TreeView *pView, const With *pWith, u8 m
}
}
+/*
+** Generate a human-readable description of a SrcList object.
+*/
+SQLITE_PRIVATE void sqlite3TreeViewSrcList(TreeView *pView, const SrcList *pSrc){
+ int i;
+ for(i=0; inSrc; i++){
+ const SrcItem *pItem = &pSrc->a[i];
+ StrAccum x;
+ char zLine[100];
+ sqlite3StrAccumInit(&x, 0, zLine, sizeof(zLine), 0);
+ x.printfFlags |= SQLITE_PRINTF_INTERNAL;
+ sqlite3_str_appendf(&x, "{%d:*} %!S", pItem->iCursor, pItem);
+ if( pItem->pTab ){
+ sqlite3_str_appendf(&x, " tab=%Q nCol=%d ptr=%p used=%llx",
+ pItem->pTab->zName, pItem->pTab->nCol, pItem->pTab, pItem->colUsed);
+ }
+ if( pItem->fg.jointype & JT_LEFT ){
+ sqlite3_str_appendf(&x, " LEFT-JOIN");
+ }
+ if( pItem->fg.fromDDL ){
+ sqlite3_str_appendf(&x, " DDL");
+ }
+ if( pItem->fg.isCte ){
+ sqlite3_str_appendf(&x, " CteUse=0x%p", pItem->u2.pCteUse);
+ }
+ sqlite3StrAccumFinish(&x);
+ sqlite3TreeViewItem(pView, zLine, inSrc-1);
+ if( pItem->pSelect ){
+ sqlite3TreeViewSelect(pView, pItem->pSelect, 0);
+ }
+ if( pItem->fg.isTabFunc ){
+ sqlite3TreeViewExprList(pView, pItem->u1.pFuncArg, 0, "func-args:");
+ }
+ sqlite3TreeViewPop(pView);
+ }
+}
/*
** Generate a human-readable description of a Select object.
@@ -28307,7 +30108,7 @@ SQLITE_PRIVATE void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 m
if( p==0 ){
sqlite3TreeViewLine(pView, "nil-SELECT");
return;
- }
+ }
pView = sqlite3TreeViewPush(pView, moreToFollow);
if( p->pWith ){
sqlite3TreeViewWith(pView, p->pWith, 1);
@@ -28315,13 +30116,17 @@ SQLITE_PRIVATE void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 m
sqlite3TreeViewPush(pView, 1);
}
do{
- sqlite3TreeViewLine(pView,
- "SELECT%s%s (%u/%p) selFlags=0x%x nSelectRow=%d",
- ((p->selFlags & SF_Distinct) ? " DISTINCT" : ""),
- ((p->selFlags & SF_Aggregate) ? " agg_flag" : ""),
- p->selId, p, p->selFlags,
- (int)p->nSelectRow
- );
+ if( p->selFlags & SF_WhereBegin ){
+ sqlite3TreeViewLine(pView, "sqlite3WhereBegin()");
+ }else{
+ sqlite3TreeViewLine(pView,
+ "SELECT%s%s (%u/%p) selFlags=0x%x nSelectRow=%d",
+ ((p->selFlags & SF_Distinct) ? " DISTINCT" : ""),
+ ((p->selFlags & SF_Aggregate) ? " agg_flag" : ""),
+ p->selId, p, p->selFlags,
+ (int)p->nSelectRow
+ );
+ }
if( cnt++ ) sqlite3TreeViewPop(pView);
if( p->pPrior ){
n = 1000;
@@ -28338,7 +30143,10 @@ SQLITE_PRIVATE void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 m
if( p->pWinDefn ) n++;
#endif
}
- sqlite3TreeViewExprList(pView, p->pEList, (n--)>0, "result-set");
+ if( p->pEList ){
+ sqlite3TreeViewExprList(pView, p->pEList, n>0, "result-set");
+ }
+ n--;
#ifndef SQLITE_OMIT_WINDOWFUNC
if( p->pWin ){
Window *pX;
@@ -28351,39 +30159,9 @@ SQLITE_PRIVATE void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 m
}
#endif
if( p->pSrc && p->pSrc->nSrc ){
- int i;
pView = sqlite3TreeViewPush(pView, (n--)>0);
sqlite3TreeViewLine(pView, "FROM");
- for(i=0; ipSrc->nSrc; i++){
- struct SrcList_item *pItem = &p->pSrc->a[i];
- StrAccum x;
- char zLine[100];
- sqlite3StrAccumInit(&x, 0, zLine, sizeof(zLine), 0);
- sqlite3_str_appendf(&x, "{%d,*}", pItem->iCursor);
- if( pItem->zDatabase ){
- sqlite3_str_appendf(&x, " %s.%s", pItem->zDatabase, pItem->zName);
- }else if( pItem->zName ){
- sqlite3_str_appendf(&x, " %s", pItem->zName);
- }
- if( pItem->pTab ){
- sqlite3_str_appendf(&x, " tabname=%Q", pItem->pTab->zName);
- }
- if( pItem->zAlias ){
- sqlite3_str_appendf(&x, " (AS %s)", pItem->zAlias);
- }
- if( pItem->fg.jointype & JT_LEFT ){
- sqlite3_str_appendf(&x, " LEFT-JOIN");
- }
- sqlite3StrAccumFinish(&x);
- sqlite3TreeViewItem(pView, zLine, ipSrc->nSrc-1);
- if( pItem->pSelect ){
- sqlite3TreeViewSelect(pView, pItem->pSelect, 0);
- }
- if( pItem->fg.isTabFunc ){
- sqlite3TreeViewExprList(pView, pItem->u1.pFuncArg, 0, "func-args:");
- }
- sqlite3TreeViewPop(pView);
- }
+ sqlite3TreeViewSrcList(pView, p->pSrc);
sqlite3TreeViewPop(pView);
}
if( p->pWhere ){
@@ -28478,24 +30256,62 @@ SQLITE_PRIVATE void sqlite3TreeViewBound(
** Generate a human-readable explanation for a Window object
*/
SQLITE_PRIVATE void sqlite3TreeViewWindow(TreeView *pView, const Window *pWin, u8 more){
+ int nElement = 0;
+ if( pWin->pFilter ){
+ sqlite3TreeViewItem(pView, "FILTER", 1);
+ sqlite3TreeViewExpr(pView, pWin->pFilter, 0);
+ sqlite3TreeViewPop(pView);
+ }
pView = sqlite3TreeViewPush(pView, more);
if( pWin->zName ){
- sqlite3TreeViewLine(pView, "OVER %s", pWin->zName);
+ sqlite3TreeViewLine(pView, "OVER %s (%p)", pWin->zName, pWin);
}else{
- sqlite3TreeViewLine(pView, "OVER");
+ sqlite3TreeViewLine(pView, "OVER (%p)", pWin);
+ }
+ if( pWin->zBase ) nElement++;
+ if( pWin->pOrderBy ) nElement++;
+ if( pWin->eFrmType ) nElement++;
+ if( pWin->eExclude ) nElement++;
+ if( pWin->zBase ){
+ sqlite3TreeViewPush(pView, (--nElement)>0);
+ sqlite3TreeViewLine(pView, "window: %s", pWin->zBase);
+ sqlite3TreeViewPop(pView);
}
if( pWin->pPartition ){
- sqlite3TreeViewExprList(pView, pWin->pPartition, 1, "PARTITION-BY");
+ sqlite3TreeViewExprList(pView, pWin->pPartition, nElement>0,"PARTITION-BY");
}
if( pWin->pOrderBy ){
- sqlite3TreeViewExprList(pView, pWin->pOrderBy, 1, "ORDER-BY");
+ sqlite3TreeViewExprList(pView, pWin->pOrderBy, (--nElement)>0, "ORDER-BY");
}
- if( pWin->eType ){
- sqlite3TreeViewItem(pView, pWin->eType==TK_RANGE ? "RANGE" : "ROWS", 0);
+ if( pWin->eFrmType ){
+ char zBuf[30];
+ const char *zFrmType = "ROWS";
+ if( pWin->eFrmType==TK_RANGE ) zFrmType = "RANGE";
+ if( pWin->eFrmType==TK_GROUPS ) zFrmType = "GROUPS";
+ sqlite3_snprintf(sizeof(zBuf),zBuf,"%s%s",zFrmType,
+ pWin->bImplicitFrame ? " (implied)" : "");
+ sqlite3TreeViewItem(pView, zBuf, (--nElement)>0);
sqlite3TreeViewBound(pView, pWin->eStart, pWin->pStart, 1);
sqlite3TreeViewBound(pView, pWin->eEnd, pWin->pEnd, 0);
sqlite3TreeViewPop(pView);
}
+ if( pWin->eExclude ){
+ char zBuf[30];
+ const char *zExclude;
+ switch( pWin->eExclude ){
+ case TK_NO: zExclude = "NO OTHERS"; break;
+ case TK_CURRENT: zExclude = "CURRENT ROW"; break;
+ case TK_GROUP: zExclude = "GROUP"; break;
+ case TK_TIES: zExclude = "TIES"; break;
+ default:
+ sqlite3_snprintf(sizeof(zBuf),zBuf,"invalid(%d)", pWin->eExclude);
+ zExclude = zBuf;
+ break;
+ }
+ sqlite3TreeViewPush(pView, 0);
+ sqlite3TreeViewLine(pView, "EXCLUDE %s", zExclude);
+ sqlite3TreeViewPop(pView);
+ }
sqlite3TreeViewPop(pView);
}
#endif /* SQLITE_OMIT_WINDOWFUNC */
@@ -28519,20 +30335,28 @@ SQLITE_PRIVATE void sqlite3TreeViewWinFunc(TreeView *pView, const Window *pWin,
SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 moreToFollow){
const char *zBinOp = 0; /* Binary operator */
const char *zUniOp = 0; /* Unary operator */
- char zFlgs[60];
+ char zFlgs[200];
pView = sqlite3TreeViewPush(pView, moreToFollow);
if( pExpr==0 ){
sqlite3TreeViewLine(pView, "nil");
sqlite3TreeViewPop(pView);
return;
}
- if( pExpr->flags ){
+ if( pExpr->flags || pExpr->affExpr || pExpr->vvaFlags ){
+ StrAccum x;
+ sqlite3StrAccumInit(&x, 0, zFlgs, sizeof(zFlgs), 0);
+ sqlite3_str_appendf(&x, " fg.af=%x.%c",
+ pExpr->flags, pExpr->affExpr ? pExpr->affExpr : 'n');
if( ExprHasProperty(pExpr, EP_FromJoin) ){
- sqlite3_snprintf(sizeof(zFlgs),zFlgs," flags=0x%x iRJT=%d",
- pExpr->flags, pExpr->iRightJoinTable);
- }else{
- sqlite3_snprintf(sizeof(zFlgs),zFlgs," flags=0x%x",pExpr->flags);
+ sqlite3_str_appendf(&x, " iRJT=%d", pExpr->iRightJoinTable);
}
+ if( ExprHasProperty(pExpr, EP_FromDDL) ){
+ sqlite3_str_appendf(&x, " DDL");
+ }
+ if( ExprHasVVAProperty(pExpr, EP_Immutable) ){
+ sqlite3_str_appendf(&x, " IMMUTABLE");
+ }
+ sqlite3StrAccumFinish(&x);
}else{
zFlgs[0] = 0;
}
@@ -28545,10 +30369,18 @@ SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 m
case TK_COLUMN: {
if( pExpr->iTable<0 ){
/* This only happens when coding check constraints */
- sqlite3TreeViewLine(pView, "COLUMN(%d)%s", pExpr->iColumn, zFlgs);
+ char zOp2[16];
+ if( pExpr->op2 ){
+ sqlite3_snprintf(sizeof(zOp2),zOp2," op2=0x%02x",pExpr->op2);
+ }else{
+ zOp2[0] = 0;
+ }
+ sqlite3TreeViewLine(pView, "COLUMN(%d)%s%s",
+ pExpr->iColumn, zFlgs, zOp2);
}else{
- sqlite3TreeViewLine(pView, "{%d:%d}%s",
- pExpr->iTable, pExpr->iColumn, zFlgs);
+ sqlite3TreeViewLine(pView, "{%d:%d} pTab=%p%s",
+ pExpr->iTable, pExpr->iColumn,
+ pExpr->y.pTab, zFlgs);
}
if( ExprHasProperty(pExpr, EP_FixedCol) ){
sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
@@ -28630,6 +30462,7 @@ SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 m
case TK_RSHIFT: zBinOp = "RSHIFT"; break;
case TK_CONCAT: zBinOp = "CONCAT"; break;
case TK_DOT: zBinOp = "DOT"; break;
+ case TK_LIMIT: zBinOp = "LIMIT"; break;
case TK_UMINUS: zUniOp = "UMINUS"; break;
case TK_UPLUS: zUniOp = "UPLUS"; break;
@@ -28645,7 +30478,7 @@ SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 m
};
assert( pExpr->op2==TK_IS || pExpr->op2==TK_ISNOT );
assert( pExpr->pRight );
- assert( pExpr->pRight->op==TK_TRUEFALSE );
+ assert( sqlite3ExprSkipCollate(pExpr->pRight)->op==TK_TRUEFALSE );
x = (pExpr->op2==TK_ISNOT)*2 + sqlite3ExprTruthValue(pExpr->pRight);
zUniOp = azOp[x];
break;
@@ -28658,7 +30491,14 @@ SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 m
}
case TK_COLLATE: {
- sqlite3TreeViewLine(pView, "COLLATE %Q", pExpr->u.zToken);
+ /* COLLATE operators without the EP_Collate flag are intended to
+ ** emulate collation associated with a table column. These show
+ ** up in the treeview output as "SOFT-COLLATE". Explicit COLLATE
+ ** operators that appear in the original SQL always have the
+ ** EP_Collate bit set and appear in treeview output as just "COLLATE" */
+ sqlite3TreeViewLine(pView, "%sCOLLATE %Q%s",
+ !ExprHasProperty(pExpr, EP_Collate) ? "SOFT-" : "",
+ pExpr->u.zToken, zFlgs);
sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
break;
}
@@ -28673,16 +30513,29 @@ SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 m
}else{
pFarg = pExpr->x.pList;
#ifndef SQLITE_OMIT_WINDOWFUNC
- pWin = pExpr->pWin;
+ pWin = ExprHasProperty(pExpr, EP_WinFunc) ? pExpr->y.pWin : 0;
#else
pWin = 0;
-#endif
+#endif
}
if( pExpr->op==TK_AGG_FUNCTION ){
- sqlite3TreeViewLine(pView, "AGG_FUNCTION%d %Q",
- pExpr->op2, pExpr->u.zToken);
+ sqlite3TreeViewLine(pView, "AGG_FUNCTION%d %Q%s agg=%d[%d]/%p",
+ pExpr->op2, pExpr->u.zToken, zFlgs,
+ pExpr->pAggInfo ? pExpr->pAggInfo->selId : 0,
+ pExpr->iAgg, pExpr->pAggInfo);
+ }else if( pExpr->op2!=0 ){
+ const char *zOp2;
+ char zBuf[8];
+ sqlite3_snprintf(sizeof(zBuf),zBuf,"0x%02x",pExpr->op2);
+ zOp2 = zBuf;
+ if( pExpr->op2==NC_IsCheck ) zOp2 = "NC_IsCheck";
+ if( pExpr->op2==NC_IdxExpr ) zOp2 = "NC_IdxExpr";
+ if( pExpr->op2==NC_PartIdx ) zOp2 = "NC_PartIdx";
+ if( pExpr->op2==NC_GenCol ) zOp2 = "NC_GenCol";
+ sqlite3TreeViewLine(pView, "FUNCTION %Q%s op2=%s",
+ pExpr->u.zToken, zFlgs, zOp2);
}else{
- sqlite3TreeViewLine(pView, "FUNCTION %Q", pExpr->u.zToken);
+ sqlite3TreeViewLine(pView, "FUNCTION %Q%s", pExpr->u.zToken, zFlgs);
}
if( pFarg ){
sqlite3TreeViewExprList(pView, pFarg, pWin!=0, 0);
@@ -28701,7 +30554,7 @@ SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 m
break;
}
case TK_SELECT: {
- sqlite3TreeViewLine(pView, "SELECT-expr flags=0x%x", pExpr->flags);
+ sqlite3TreeViewLine(pView, "subquery-expr flags=0x%x", pExpr->flags);
sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0);
break;
}
@@ -28746,7 +30599,7 @@ SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 m
** is set to the column of the pseudo-table to read, or to -1 to
** read the rowid field.
*/
- sqlite3TreeViewLine(pView, "%s(%d)",
+ sqlite3TreeViewLine(pView, "%s(%d)",
pExpr->iTable ? "NEW" : "OLD", pExpr->iColumn);
break;
}
@@ -28759,7 +30612,7 @@ SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 m
#ifndef SQLITE_OMIT_TRIGGER
case TK_RAISE: {
const char *zType = "unk";
- switch( pExpr->affinity ){
+ switch( pExpr->affExpr ){
case OE_Rollback: zType = "rollback"; break;
case OE_Abort: zType = "abort"; break;
case OE_Fail: zType = "fail"; break;
@@ -28776,7 +30629,9 @@ SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 m
break;
}
case TK_VECTOR: {
- sqlite3TreeViewBareExprList(pView, pExpr->x.pList, "VECTOR");
+ char *z = sqlite3_mprintf("VECTOR%s",zFlgs);
+ sqlite3TreeViewBareExprList(pView, pExpr->x.pList, z);
+ sqlite3_free(z);
break;
}
case TK_SELECT_COLUMN: {
@@ -28789,6 +30644,14 @@ SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 m
sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
break;
}
+ case TK_ERROR: {
+ Expr tmp;
+ sqlite3TreeViewLine(pView, "ERROR");
+ tmp = *pExpr;
+ tmp.op = pExpr->op2;
+ sqlite3TreeViewExpr(pView, &tmp, 0);
+ break;
+ }
default: {
sqlite3TreeViewLine(pView, "op=%d", pExpr->op);
break;
@@ -28800,7 +30663,7 @@ SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 m
sqlite3TreeViewExpr(pView, pExpr->pRight, 0);
}else if( zUniOp ){
sqlite3TreeViewLine(pView, "%s%s", zUniOp, zFlgs);
- sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
+ sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
}
sqlite3TreeViewPop(pView);
}
@@ -28822,8 +30685,9 @@ SQLITE_PRIVATE void sqlite3TreeViewBareExprList(
sqlite3TreeViewLine(pView, "%s", zLabel);
for(i=0; inExpr; i++){
int j = pList->a[i].u.x.iOrderByCol;
- char *zName = pList->a[i].zName;
+ char *zName = pList->a[i].zEName;
int moreToFollow = inExpr - 1;
+ if( pList->a[i].eEName!=ENAME_NAME ) zName = 0;
if( j || zName ){
sqlite3TreeViewPush(pView, moreToFollow);
moreToFollow = 0;
@@ -28937,11 +30801,16 @@ SQLITE_API void sqlite3_randomness(int N, void *pBuf){
** number generator) not as an encryption device.
*/
if( !wsdPrng.isInit ){
+ sqlite3_vfs *pVfs = sqlite3_vfs_find(0);
int i;
char k[256];
wsdPrng.j = 0;
wsdPrng.i = 0;
- sqlite3OsRandomness(sqlite3_vfs_find(0), 256, k);
+ if( NEVER(pVfs==0) ){
+ memset(k, 0, sizeof(k));
+ }else{
+ sqlite3OsRandomness(pVfs, 256, k);
+ }
for(i=0; i<256; i++){
wsdPrng.s[i] = (u8)i;
}
@@ -29065,13 +30934,13 @@ SQLITE_PRIVATE int sqlite3ThreadCreate(
memset(p, 0, sizeof(*p));
p->xTask = xTask;
p->pIn = pIn;
- /* If the SQLITE_TESTCTRL_FAULT_INSTALL callback is registered to a
+ /* If the SQLITE_TESTCTRL_FAULT_INSTALL callback is registered to a
** function that returns SQLITE_ERROR when passed the argument 200, that
- ** forces worker threads to run sequentially and deterministically
+ ** forces worker threads to run sequentially and deterministically
** for testing purposes. */
if( sqlite3FaultSim(200) ){
rc = 1;
- }else{
+ }else{
rc = pthread_create(&p->tid, 0, xTask, pIn);
}
if( rc ){
@@ -29153,9 +31022,9 @@ SQLITE_PRIVATE int sqlite3ThreadCreate(
*ppThread = 0;
p = sqlite3Malloc(sizeof(*p));
if( p==0 ) return SQLITE_NOMEM_BKPT;
- /* If the SQLITE_TESTCTRL_FAULT_INSTALL callback is registered to a
+ /* If the SQLITE_TESTCTRL_FAULT_INSTALL callback is registered to a
** function that returns SQLITE_ERROR when passed the argument 200, that
- ** forces worker threads to run sequentially and deterministically
+ ** forces worker threads to run sequentially and deterministically
** (via the sqlite3FaultSim() term of the conditional) for testing
** purposes. */
if( sqlite3GlobalConfig.bCoreMutex==0 || sqlite3FaultSim(200) ){
@@ -29284,7 +31153,7 @@ SQLITE_PRIVATE int sqlite3ThreadJoin(SQLiteThread *p, void **ppOut){
** 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:
@@ -29380,26 +31249,6 @@ static const unsigned char sqlite3Utf8Trans1[] = {
} \
}
-#define READ_UTF16LE(zIn, TERM, c){ \
- c = (*zIn++); \
- c += ((*zIn++)<<8); \
- if( c>=0xD800 && c<0xE000 && TERM ){ \
- int c2 = (*zIn++); \
- c2 += ((*zIn++)<<8); \
- c = (c2&0x03FF) + ((c&0x003F)<<10) + (((c&0x03C0)+0x0040)<<10); \
- } \
-}
-
-#define READ_UTF16BE(zIn, TERM, c){ \
- c = ((*zIn++)<<8); \
- c += (*zIn++); \
- if( c>=0xD800 && c<0xE000 && TERM ){ \
- int c2 = ((*zIn++)<<8); \
- c2 += (*zIn++); \
- c = (c2&0x03FF) + ((c&0x003F)<<10) + (((c&0x03C0)+0x0040)<<10); \
- } \
-}
-
/*
** Translate a single UTF-8 character. Return the unicode value.
**
@@ -29465,7 +31314,7 @@ SQLITE_PRIVATE u32 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
@@ -29475,11 +31324,11 @@ SQLITE_PRIVATE u32 sqlite3Utf8Read(
** encoding, or if *pMem does not contain a string value.
*/
SQLITE_PRIVATE SQLITE_NOINLINE int sqlite3VdbeMemTranslate(Mem *pMem, u8 desiredEnc){
- int len; /* Maximum length of output string in bytes */
- unsigned char *zOut; /* Output buffer */
- unsigned char *zIn; /* Input iterator */
- unsigned char *zTerm; /* End of input */
- unsigned char *z; /* Output iterator */
+ sqlite3_int64 len; /* Maximum length of output string in bytes */
+ unsigned char *zOut; /* Output buffer */
+ unsigned char *zIn; /* Input iterator */
+ unsigned char *zTerm; /* End of input */
+ unsigned char *z; /* Output iterator */
unsigned int c;
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
@@ -29490,13 +31339,15 @@ SQLITE_PRIVATE SQLITE_NOINLINE int sqlite3VdbeMemTranslate(Mem *pMem, u8 desired
#if defined(TRANSLATE_TRACE) && defined(SQLITE_DEBUG)
{
- char zBuf[100];
- sqlite3VdbeMemPrettyPrint(pMem, zBuf);
- fprintf(stderr, "INPUT: %s\n", zBuf);
+ StrAccum acc;
+ char zBuf[1000];
+ sqlite3StrAccumInit(&acc, 0, zBuf, sizeof(zBuf), 0);
+ sqlite3VdbeMemPrettyPrint(pMem, &acc);
+ fprintf(stderr, "INPUT: %s\n", sqlite3StrAccumFinish(&acc));
}
#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.
*/
@@ -29528,14 +31379,14 @@ SQLITE_PRIVATE SQLITE_NOINLINE int sqlite3VdbeMemTranslate(Mem *pMem, u8 desired
** nul-terminator.
*/
pMem->n &= ~1;
- len = pMem->n * 2 + 1;
+ len = 2 * (sqlite3_int64)pMem->n + 1;
}else{
/* When converting from UTF-8 to UTF-16 the maximum growth is caused
** when a 1-byte UTF-8 character is translated into a 2-byte UTF-16
** character. Two bytes are required in the output buffer for the
** nul-terminator.
*/
- len = pMem->n * 2 + 2;
+ len = 2 * (sqlite3_int64)pMem->n + 2;
}
/* Set zIn to point at the start of the input buffer and zTerm to point 1
@@ -29574,13 +31425,59 @@ SQLITE_PRIVATE SQLITE_NOINLINE int sqlite3VdbeMemTranslate(Mem *pMem, u8 desired
if( pMem->enc==SQLITE_UTF16LE ){
/* UTF-16 Little-endian -> UTF-8 */
while( zIn=0xd800 && c<0xe000 ){
+#ifdef SQLITE_REPLACE_INVALID_UTF
+ if( c>=0xdc00 || zIn>=zTerm ){
+ c = 0xfffd;
+ }else{
+ int c2 = *(zIn++);
+ c2 += (*(zIn++))<<8;
+ if( c2<0xdc00 || c2>=0xe000 ){
+ zIn -= 2;
+ c = 0xfffd;
+ }else{
+ c = ((c&0x3ff)<<10) + (c2&0x3ff) + 0x10000;
+ }
+ }
+#else
+ if( zIn UTF-8 */
while( zIn=0xd800 && c<0xe000 ){
+#ifdef SQLITE_REPLACE_INVALID_UTF
+ if( c>=0xdc00 || zIn>=zTerm ){
+ c = 0xfffd;
+ }else{
+ int c2 = (*(zIn++))<<8;
+ c2 += *(zIn++);
+ if( c2<0xdc00 || c2>=0xe000 ){
+ zIn -= 2;
+ c = 0xfffd;
+ }else{
+ c = ((c&0x3ff)<<10) + (c2&0x3ff) + 0x10000;
+ }
+ }
+#else
+ if( zInn+(desiredEnc==SQLITE_UTF8?1:2))<=len );
- c = pMem->flags;
+ c = MEM_Str|MEM_Term|(pMem->flags&(MEM_AffMask|MEM_Subtype));
sqlite3VdbeMemRelease(pMem);
- pMem->flags = MEM_Str|MEM_Term|(c&(MEM_AffMask|MEM_Subtype));
+ pMem->flags = c;
pMem->enc = desiredEnc;
pMem->z = (char*)zOut;
pMem->zMalloc = pMem->z;
@@ -29600,9 +31497,11 @@ SQLITE_PRIVATE SQLITE_NOINLINE int sqlite3VdbeMemTranslate(Mem *pMem, u8 desired
translate_out:
#if defined(TRANSLATE_TRACE) && defined(SQLITE_DEBUG)
{
- char zBuf[100];
- sqlite3VdbeMemPrettyPrint(pMem, zBuf);
- fprintf(stderr, "OUTPUT: %s\n", zBuf);
+ StrAccum acc;
+ char zBuf[1000];
+ sqlite3StrAccumInit(&acc, 0, zBuf, sizeof(zBuf), 0);
+ sqlite3VdbeMemPrettyPrint(pMem, &acc);
+ fprintf(stderr, "OUTPUT: %s\n", sqlite3StrAccumFinish(&acc));
}
#endif
return SQLITE_OK;
@@ -29611,7 +31510,7 @@ translate_out:
#ifndef SQLITE_OMIT_UTF16
/*
-** 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.
@@ -29634,7 +31533,7 @@ SQLITE_PRIVATE int sqlite3VdbeMemHandleBom(Mem *pMem){
bom = SQLITE_UTF16LE;
}
}
-
+
if( bom ){
rc = sqlite3VdbeMemMakeWriteable(pMem);
if( rc==SQLITE_OK ){
@@ -29654,7 +31553,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){
@@ -29674,7 +31573,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)
@@ -29736,19 +31635,16 @@ 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=0xd8 && c<0xdc && z[0]>=0xdc && z[0]<0xe0 ) z += 2;
+ n++;
}
- return (int)(z-(unsigned char const *)zIn);
+ return (int)(z-(unsigned char const *)zIn)
+ - (SQLITE_UTF16NATIVE==SQLITE_UTF16LE);
}
#if defined(SQLITE_TEST)
@@ -29778,30 +31674,6 @@ SQLITE_PRIVATE void sqlite3UtfSelfTest(void){
assert( c==t );
assert( (z-zBuf)==n );
}
- for(i=0; i<0x00110000; i++){
- if( i>=0xD800 && i<0xE000 ) continue;
- z = zBuf;
- WRITE_UTF16LE(z, i);
- n = (int)(z-zBuf);
- assert( n>0 && n<=4 );
- z[0] = 0;
- z = zBuf;
- READ_UTF16LE(z, 1, c);
- assert( c==i );
- assert( (z-zBuf)==n );
- }
- for(i=0; i<0x00110000; i++){
- if( i>=0xD800 && i<0xE000 ) continue;
- z = zBuf;
- WRITE_UTF16BE(z, i);
- n = (int)(z-zBuf);
- assert( n>0 && n<=4 );
- z[0] = 0;
- z = zBuf;
- READ_UTF16BE(z, 1, c);
- assert( c==i );
- assert( (z-zBuf)==n );
- }
}
#endif /* SQLITE_TEST */
#endif /* SQLITE_OMIT_UTF16 */
@@ -29827,8 +31699,8 @@ SQLITE_PRIVATE void sqlite3UtfSelfTest(void){
*/
/* #include "sqliteInt.h" */
/* #include */
-#if HAVE_ISNAN || SQLITE_HAVE_ISNAN
-# include
+#ifndef SQLITE_OMIT_FLOATING_POINT
+#include
#endif
/*
@@ -29842,15 +31714,23 @@ SQLITE_PRIVATE void sqlite3Coverage(int x){
#endif
/*
-** Give a callback to the test harness that can be used to simulate faults
-** in places where it is difficult or expensive to do so purely by means
-** of inputs.
+** Calls to sqlite3FaultSim() are used to simulate a failure during testing,
+** or to bypass normal error detection during testing in order to let
+** execute proceed futher downstream.
**
-** The intent of the integer argument is to let the fault simulator know
-** which of multiple sqlite3FaultSim() calls has been hit.
+** In deployment, sqlite3FaultSim() *always* return SQLITE_OK (0). The
+** sqlite3FaultSim() function only returns non-zero during testing.
**
-** Return whatever integer value the test callback returns, or return
-** SQLITE_OK if no test callback is installed.
+** During testing, if the test harness has set a fault-sim callback using
+** a call to sqlite3_test_control(SQLITE_TESTCTRL_FAULT_INSTALL), then
+** each call to sqlite3FaultSim() is relayed to that application-supplied
+** callback and the integer return value form the application-supplied
+** callback is returned by sqlite3FaultSim().
+**
+** The integer argument to sqlite3FaultSim() is a code to identify which
+** sqlite3FaultSim() instance is being invoked. Each call to sqlite3FaultSim()
+** should have a unique code. To prevent legacy testing applications from
+** breaking, the codes should not be changed or reused.
*/
#ifndef SQLITE_UNTESTABLE
SQLITE_PRIVATE int sqlite3FaultSim(int iTest){
@@ -29862,47 +31742,11 @@ SQLITE_PRIVATE int sqlite3FaultSim(int iTest){
#ifndef SQLITE_OMIT_FLOATING_POINT
/*
** Return true if the floating point value is Not a Number (NaN).
-**
-** Use the math library isnan() function if compiled with SQLITE_HAVE_ISNAN.
-** Otherwise, we have our own implementation that works on most systems.
*/
SQLITE_PRIVATE int sqlite3IsNaN(double x){
- int rc; /* The value return */
-#if !SQLITE_HAVE_ISNAN && !HAVE_ISNAN
- /*
- ** Systems that support the isnan() library function should probably
- ** make use of it by compiling with -DSQLITE_HAVE_ISNAN. But we have
- ** found that many systems do not have a working isnan() function so
- ** this implementation is provided as an alternative.
- **
- ** This NaN test sometimes fails if compiled on GCC with -ffast-math.
- ** On the other hand, the use of -ffast-math comes with the following
- ** warning:
- **
- ** This option [-ffast-math] should never be turned on by any
- ** -O option since it can result in incorrect output for programs
- ** which depend on an exact implementation of IEEE or ISO
- ** rules/specifications for math functions.
- **
- ** Under MSVC, this NaN test may fail if compiled with a floating-
- ** point precision mode other than /fp:precise. From the MSDN
- ** documentation:
- **
- ** The compiler [with /fp:precise] will properly handle comparisons
- ** involving NaN. For example, x != x evaluates to true if x is NaN
- ** ...
- */
-#ifdef __FAST_MATH__
-# error SQLite will not work correctly with the -ffast-math option of GCC.
-#endif
- volatile double y = x;
- volatile double z = y;
- rc = (y!=z);
-#else /* if HAVE_ISNAN */
- rc = isnan(x);
-#endif /* HAVE_ISNAN */
- testcase( rc );
- return rc;
+ u64 y;
+ memcpy(&y,&x,sizeof(y));
+ return IsNaN(y);
}
#endif /* SQLITE_OMIT_FLOATING_POINT */
@@ -29920,7 +31764,7 @@ SQLITE_PRIVATE int sqlite3Strlen30(const char *z){
}
/*
-** Return the declared type of a column. Or return zDflt if the column
+** Return the declared type of a column. Or return zDflt if the column
** has no declared type.
**
** The column type is an extra string stored after the zero-terminator on
@@ -29952,6 +31796,16 @@ SQLITE_PRIVATE void sqlite3Error(sqlite3 *db, int err_code){
if( err_code || db->pErr ) sqlite3ErrorFinish(db, err_code);
}
+/*
+** The equivalent of sqlite3Error(db, SQLITE_OK). Clear the error state
+** and error message.
+*/
+SQLITE_PRIVATE void sqlite3ErrorClear(sqlite3 *db){
+ assert( db!=0 );
+ db->errCode = SQLITE_OK;
+ if( db->pErr ) sqlite3ValueSetNull(db->pErr);
+}
+
/*
** Load the sqlite3.iSysErrno field if that is an appropriate thing
** to do based on the SQLite error code in rc.
@@ -30032,9 +31886,23 @@ SQLITE_PRIVATE void sqlite3ErrorMsg(Parse *pParse, const char *zFormat, ...){
sqlite3DbFree(db, pParse->zErrMsg);
pParse->zErrMsg = zMsg;
pParse->rc = SQLITE_ERROR;
+ pParse->pWith = 0;
}
}
+/*
+** If database connection db is currently parsing SQL, then transfer
+** error code errCode to that parser if the parser has not already
+** encountered some other kind of error.
+*/
+SQLITE_PRIVATE int sqlite3ErrorToParser(sqlite3 *db, int errCode){
+ Parse *pParse;
+ if( db==0 || (pParse = db->pParse)==0 ) return errCode;
+ pParse->rc = errCode;
+ pParse->nErr++;
+ return errCode;
+}
+
/*
** Convert an SQL-style quoted string into a normal string by removing
** the quote characters. The conversion is done in-place. If the
@@ -30048,7 +31916,7 @@ SQLITE_PRIVATE void sqlite3ErrorMsg(Parse *pParse, const char *zFormat, ...){
** dequoted string, exclusive of the zero terminator, if dequoting does
** occur.
**
-** 2002-Feb-14: This routine is extended to remove MS-Access style
+** 2002-02-14: This routine is extended to remove MS-Access style
** brackets from around identifiers. For example: "[a-b-c]" becomes
** "a-b-c".
*/
@@ -30074,6 +31942,11 @@ SQLITE_PRIVATE void sqlite3Dequote(char *z){
}
z[j] = 0;
}
+SQLITE_PRIVATE void sqlite3DequoteExpr(Expr *p){
+ assert( sqlite3Isquote(p->u.zToken[0]) );
+ p->flags |= p->u.zToken[0]=='"' ? EP_Quoted|EP_DblQuoted : EP_Quoted;
+ sqlite3Dequote(p->u.zToken);
+}
/*
** Generate a Token object from a string
@@ -30106,12 +31979,18 @@ SQLITE_API int sqlite3_stricmp(const char *zLeft, const char *zRight){
}
SQLITE_PRIVATE int sqlite3StrICmp(const char *zLeft, const char *zRight){
unsigned char *a, *b;
- int c;
+ int c, x;
a = (unsigned char *)zLeft;
b = (unsigned char *)zRight;
for(;;){
- c = (int)UpperToLower[*a] - (int)UpperToLower[*b];
- if( c || *a==0 ) break;
+ c = *a;
+ x = *b;
+ if( c==x ){
+ if( c==0 ) break;
+ }else{
+ c = (int)UpperToLower[c] - (int)UpperToLower[x];
+ if( c ) break;
+ }
a++;
b++;
}
@@ -30130,6 +32009,19 @@ SQLITE_API int sqlite3_strnicmp(const char *zLeft, const char *zRight, int N){
return N<0 ? 0 : UpperToLower[*a] - UpperToLower[*b];
}
+/*
+** Compute an 8-bit hash on a string that is insensitive to case differences
+*/
+SQLITE_PRIVATE u8 sqlite3StrIHash(const char *z){
+ u8 h = 0;
+ if( z==0 ) return 0;
+ while( z[0] ){
+ h += UpperToLower[(unsigned char)z[0]];
+ z++;
+ }
+ return h;
+}
+
/*
** Compute 10 to the E-th power. Examples: E==1 results in 10.
** E==2 results in 100. E==50 results in 1.0e50.
@@ -30139,15 +32031,15 @@ SQLITE_API int sqlite3_strnicmp(const char *zLeft, const char *zRight, int N){
static LONGDOUBLE_TYPE sqlite3Pow10(int E){
#if defined(_MSC_VER)
static const LONGDOUBLE_TYPE x[] = {
- 1.0e+001,
- 1.0e+002,
- 1.0e+004,
- 1.0e+008,
- 1.0e+016,
- 1.0e+032,
- 1.0e+064,
- 1.0e+128,
- 1.0e+256
+ 1.0e+001L,
+ 1.0e+002L,
+ 1.0e+004L,
+ 1.0e+008L,
+ 1.0e+016L,
+ 1.0e+032L,
+ 1.0e+064L,
+ 1.0e+128L,
+ 1.0e+256L
};
LONGDOUBLE_TYPE r = 1.0;
int i;
@@ -30165,7 +32057,7 @@ static LONGDOUBLE_TYPE sqlite3Pow10(int E){
if( E==0 ) break;
x *= x;
}
- return r;
+ return r;
#endif
}
@@ -30177,8 +32069,15 @@ static LONGDOUBLE_TYPE sqlite3Pow10(int E){
** uses the encoding enc. The string is not necessarily zero-terminated.
**
** Return TRUE if the result is a valid real number (or integer) and FALSE
-** if the string is empty or contains extraneous text. Valid numbers
-** are in one of these formats:
+** if the string is empty or contains extraneous text. More specifically
+** return
+** 1 => The input string is a pure integer
+** 2 or more => The input has a decimal point or eNNN clause
+** 0 or less => The input string is not a valid number
+** -1 => Not a valid number, but has a valid prefix which
+** includes a decimal point and/or an eNNN clause
+**
+** Valid numbers are in one of these formats:
**
** [+-]digits[E[+-]digits]
** [+-]digits.[digits][E[+-]digits]
@@ -30191,10 +32090,13 @@ static LONGDOUBLE_TYPE sqlite3Pow10(int E){
** returns FALSE but it still converts the prefix and writes the result
** into *pResult.
*/
+#if defined(_MSC_VER)
+#pragma warning(disable : 4756)
+#endif
SQLITE_PRIVATE int sqlite3AtoF(const char *z, double *pResult, int length, u8 enc){
#ifndef SQLITE_OMIT_FLOATING_POINT
int incr;
- const char *zEnd = z + length;
+ const char *zEnd;
/* sign * significand * (10 ^ (esign * exponent)) */
int sign = 1; /* sign of significand */
i64 s = 0; /* significand */
@@ -30203,20 +32105,25 @@ SQLITE_PRIVATE int sqlite3AtoF(const char *z, double *pResult, int length, u8 en
int e = 0; /* exponent */
int eValid = 1; /* True exponent is either not used or is well-formed */
double result;
- int nDigits = 0;
- int nonNum = 0; /* True if input contains UTF16 with high byte non-zero */
+ int nDigit = 0; /* Number of digits processed */
+ int eType = 1; /* 1: pure integer, 2+: fractional -1 or less: bad UTF16 */
assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE );
*pResult = 0.0; /* Default return value, in case of an error */
+ if( length==0 ) return 0;
if( enc==SQLITE_UTF8 ){
incr = 1;
+ zEnd = z + length;
}else{
int i;
incr = 2;
+ length &= ~1;
assert( SQLITE_UTF16LE==2 && SQLITE_UTF16BE==3 );
+ testcase( enc==SQLITE_UTF16LE );
+ testcase( enc==SQLITE_UTF16BE );
for(i=3-enc; i=((LARGEST_INT64-9)/10) ){
+ /* skip non-significant significand digits
+ ** (increase exponent by d to shift decimal left) */
+ while( z=zEnd ) goto do_atof_calc;
/* if decimal point is present */
if( *z=='.' ){
z+=incr;
+ eType++;
/* copy digits from after decimal to significand
** (decrease exponent by d to shift decimal right) */
while( z=zEnd ) goto do_atof_calc;
@@ -30263,8 +32173,9 @@ SQLITE_PRIVATE int sqlite3AtoF(const char *z, double *pResult, int length, u8 en
if( *z=='e' || *z=='E' ){
z+=incr;
eValid = 0;
+ eType++;
- /* This branch is needed to avoid a (harmless) buffer overread. The
+ /* This branch is needed to avoid a (harmless) buffer overread. The
** special comment alerts the mutation tester that the correct answer
** is obtained even if the branch is omitted */
if( z>=zEnd ) goto do_atof_calc; /*PREVENTS-HARMLESS-OVERREAD*/
@@ -30361,11 +32272,44 @@ do_atof_calc:
*pResult = result;
/* return true if number and no extra non-whitespace chracters after */
- return z==zEnd && nDigits>0 && eValid && nonNum==0;
+ if( z==zEnd && nDigit>0 && eValid && eType>0 ){
+ return eType;
+ }else if( eType>=2 && (eType==3 || eValid) && nDigit>0 ){
+ return -1;
+ }else{
+ return 0;
+ }
#else
return !sqlite3Atoi64(z, pResult, length, enc);
#endif /* SQLITE_OMIT_FLOATING_POINT */
}
+#if defined(_MSC_VER)
+#pragma warning(default : 4756)
+#endif
+
+/*
+** Render an signed 64-bit integer as text. Store the result in zOut[].
+**
+** The caller must ensure that zOut[] is at least 21 bytes in size.
+*/
+SQLITE_PRIVATE void sqlite3Int64ToText(i64 v, char *zOut){
+ int i;
+ u64 x;
+ char zTemp[22];
+ if( v<0 ){
+ x = (v==SMALLEST_INT64) ? ((u64)1)<<63 : (u64)-v;
+ }else{
+ x = v;
+ }
+ i = sizeof(zTemp)-2;
+ zTemp[sizeof(zTemp)-1] = 0;
+ do{
+ zTemp[i--] = (x%10) + '0';
+ x = x/10;
+ }while( x );
+ if( v<0 ) zTemp[i--] = '-';
+ memcpy(zOut, &zTemp[i+1], sizeof(zTemp)-1-i);
+}
/*
** Compare the 19-character string zNum against the text representation
@@ -30404,6 +32348,7 @@ static int compare2pow63(const char *zNum, int incr){
**
** Returns:
**
+** -1 Not even a prefix of the input text looks like an integer
** 0 Successful transformation. Fits in a 64-bit signed integer.
** 1 Excess non-space text after the integer value
** 2 Integer too large for a 64-bit signed integer or is malformed
@@ -30428,6 +32373,7 @@ SQLITE_PRIVATE int sqlite3Atoi64(const char *zNum, i64 *pNum, int length, u8 enc
incr = 1;
}else{
incr = 2;
+ length &= ~1;
assert( SQLITE_UTF16LE==2 && SQLITE_UTF16BE==3 );
for(i=3-enc; i4294967296LL ){ *pI = 0; return 0; }
+ }
+ if( i==0 || z[i]!=0 ){ *pI = 0; return 0; }
+ *pI = (u32)v;
+ return 1;
+}
+
/*
** The variable-length integer encoding is as follows:
**
@@ -30650,7 +32614,7 @@ static int SQLITE_NOINLINE putVarint64(unsigned char *p, u64 v){
v >>= 7;
}
return 9;
- }
+ }
n = 0;
do{
buf[n++] = (u8)((v & 0x7f) | 0x80);
@@ -30696,23 +32660,12 @@ SQLITE_PRIVATE int sqlite3PutVarint(unsigned char *p, u64 v){
SQLITE_PRIVATE u8 sqlite3GetVarint(const unsigned char *p, u64 *v){
u32 a,b,s;
- a = *p;
- /* a: p0 (unmasked) */
- if (!(a&0x80))
- {
- *v = a;
+ if( ((signed char*)p)[0]>=0 ){
+ *v = *p;
return 1;
}
-
- p++;
- b = *p;
- /* b: p1 (unmasked) */
- if (!(b&0x80))
- {
- a &= 0x7f;
- a = a<<7;
- a |= b;
- *v = a;
+ if( ((signed char*)p)[1]>=0 ){
+ *v = ((u32)(p[0]&0x7f)<<7) | p[1];
return 2;
}
@@ -30720,8 +32673,9 @@ SQLITE_PRIVATE u8 sqlite3GetVarint(const unsigned char *p, u64 *v){
assert( SLOT_2_0 == ((0x7f<<14) | (0x7f)) );
assert( SLOT_4_2_0 == ((0xfU<<28) | (0x7f<<14) | (0x7f)) );
- p++;
- a = a<<14;
+ a = ((u32)p[0])<<14;
+ b = p[1];
+ p += 2;
a |= *p;
/* a: p0<<14 | p2 (unmasked) */
if (!(a&0x80))
@@ -30860,8 +32814,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){
@@ -30922,8 +32876,7 @@ SQLITE_PRIVATE u8 sqlite3GetVarint32(const unsigned char *p, u32 *v){
u64 v64;
u8 n;
- p -= 2;
- n = sqlite3GetVarint(p, &v64);
+ n = sqlite3GetVarint(p-2, &v64);
assert( n>3 && n<=9 );
if( (v64 & SQLITE_MAX_U32)!=v64 ){
*v = 0xffffffff;
@@ -31050,7 +33003,7 @@ SQLITE_PRIVATE u8 sqlite3HexToInt(int h){
return (u8)(h & 0xf);
}
-#if !defined(SQLITE_OMIT_BLOB_LITERAL) || defined(SQLITE_HAS_CODEC)
+#if !defined(SQLITE_OMIT_BLOB_LITERAL)
/*
** Convert a BLOB literal of the form "x'hhhhhh'" into its binary
** value. Return a pointer to its binary value. Space to hold the
@@ -31071,7 +33024,7 @@ SQLITE_PRIVATE void *sqlite3HexToBlob(sqlite3 *db, const char *z, int n){
}
return zBlob;
}
-#endif /* !SQLITE_OMIT_BLOB_LITERAL || SQLITE_HAS_CODEC */
+#endif /* !SQLITE_OMIT_BLOB_LITERAL */
/*
** Log an error that is an API call on a connection pointer that should
@@ -31079,7 +33032,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
);
@@ -31153,7 +33106,7 @@ SQLITE_PRIVATE int sqlite3AddInt64(i64 *pA, i64 iB){
if( iA<0 && -(iA + LARGEST_INT64) > iB + 1 ) return 1;
}
*pA += iB;
- return 0;
+ return 0;
#endif
}
SQLITE_PRIVATE int sqlite3SubInt64(i64 *pA, i64 iB){
@@ -31194,7 +33147,7 @@ SQLITE_PRIVATE int sqlite3MulInt64(i64 *pA, i64 iB){
}
/*
-** Compute the absolute value of a 32-bit signed integer, of possible. Or
+** Compute the absolute value of a 32-bit signed integer, of possible. Or
** if the integer has a value of -2147483648, return +2147483647
*/
SQLITE_PRIVATE int sqlite3AbsInt32(int x){
@@ -31234,11 +33187,11 @@ SQLITE_PRIVATE void sqlite3FileSuffix3(const char *zBaseFilename, char *z){
}
#endif
-/*
+/*
** Find (an approximate) sum of two LogEst values. This computation is
** not a simple "+" operator because LogEst is stored as a logarithmic
** value.
-**
+**
*/
SQLITE_PRIVATE LogEst sqlite3LogEstAdd(LogEst a, LogEst b){
static const unsigned char x[] = {
@@ -31304,7 +33257,7 @@ SQLITE_PRIVATE LogEst sqlite3LogEstFromDouble(double x){
#endif /* SQLITE_OMIT_VIRTUALTABLE */
#if defined(SQLITE_ENABLE_STMT_SCANSTATUS) || \
- defined(SQLITE_ENABLE_STAT3_OR_STAT4) || \
+ defined(SQLITE_ENABLE_STAT4) || \
defined(SQLITE_EXPLAIN_ESTIMATED_ROWS)
/*
** Convert a LogEst into an integer.
@@ -31322,7 +33275,7 @@ SQLITE_PRIVATE u64 sqlite3LogEstToInt(LogEst x){
defined(SQLITE_EXPLAIN_ESTIMATED_ROWS)
if( x>60 ) return (u64)LARGEST_INT64;
#else
- /* If only SQLITE_ENABLE_STAT3_OR_STAT4 is on, then the largest input
+ /* If only SQLITE_ENABLE_STAT4 is on, then the largest input
** possible to this routine is 310, resulting in a maximum x of 31 */
assert( x<=60 );
#endif
@@ -31352,8 +33305,8 @@ SQLITE_PRIVATE u64 sqlite3LogEstToInt(LogEst x){
** Conceptually:
**
** struct VList {
-** int nAlloc; // Number of allocated slots
-** int nUsed; // Number of used slots
+** int nAlloc; // Number of allocated slots
+** int nUsed; // Number of used slots
** struct VListEntry {
** int iValue; // Value for this entry
** int nSlot; // Slots used by this entry
@@ -31362,7 +33315,7 @@ SQLITE_PRIVATE u64 sqlite3LogEstToInt(LogEst x){
** }
**
** During code generation, pointers to the variable names within the
-** VList are taken. When that happens, nAlloc is set to zero as an
+** VList are taken. When that happens, nAlloc is set to zero as an
** indication that the VList may never again be enlarged, since the
** accompanying realloc() would invalidate the pointers.
*/
@@ -31381,7 +33334,7 @@ SQLITE_PRIVATE VList *sqlite3VListAdd(
assert( pIn==0 || pIn[0]>=3 ); /* Verify ok to add new elements */
if( pIn==0 || pIn[1]+nInt > pIn[0] ){
/* Enlarge the allocation */
- int nAlloc = (pIn ? pIn[0]*2 : 10) + nInt;
+ sqlite3_int64 nAlloc = (pIn ? 2*(sqlite3_int64)pIn[0] : 10) + nInt;
VList *pOut = sqlite3DbRealloc(db, pIn, nAlloc*sizeof(int));
if( pOut==0 ) return pIn;
if( pIn==0 ) pOut[1] = 2;
@@ -31553,7 +33506,7 @@ static int rehash(Hash *pH, unsigned int new_size){
/* The inability to allocates space for a larger hash table is
** a performance hit but it is not a fatal error. So mark the
- ** allocation as a benign. Use sqlite3Malloc()/memset(0) instead of
+ ** allocation as a benign. Use sqlite3Malloc()/memset(0) instead of
** sqlite3MallocZero() to make the allocation, as sqlite3MallocZero()
** only zeroes the requested number of bytes whereas this module will
** use the actual amount of space allocated for the hash table (which
@@ -31587,7 +33540,7 @@ static HashElem *findElementWithHash(
unsigned int *pHash /* Write the hash value here */
){
HashElem *elem; /* Used to loop thru the element list */
- int count; /* Number of elements left to test */
+ unsigned int count; /* Number of elements left to test */
unsigned int h; /* The computed hash */
static HashElem nullElement = { 0, 0, 0, 0 };
@@ -31605,7 +33558,7 @@ static HashElem *findElementWithHash(
if( pHash ) *pHash = h;
while( count-- ){
assert( elem!=0 );
- if( sqlite3StrICmp(elem->pKey,pKey)==0 ){
+ if( sqlite3StrICmp(elem->pKey,pKey)==0 ){
return elem;
}
elem = elem->next;
@@ -31623,7 +33576,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;
}
@@ -31635,8 +33588,8 @@ static void removeElementGivenHash(
if( pEntry->chain==elem ){
pEntry->chain = elem->next;
}
+ assert( pEntry->count>0 );
pEntry->count--;
- assert( pEntry->count>=0 );
}
sqlite3_free( elem );
pH->count--;
@@ -31745,30 +33698,30 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
/* 23 */ "SeekLE" OpHelp("key=r[P3@P4]"),
/* 24 */ "SeekGE" OpHelp("key=r[P3@P4]"),
/* 25 */ "SeekGT" OpHelp("key=r[P3@P4]"),
- /* 26 */ "IfNoHope" OpHelp("key=r[P3@P4]"),
- /* 27 */ "NoConflict" OpHelp("key=r[P3@P4]"),
- /* 28 */ "NotFound" OpHelp("key=r[P3@P4]"),
- /* 29 */ "Found" OpHelp("key=r[P3@P4]"),
- /* 30 */ "SeekRowid" OpHelp("intkey=r[P3]"),
- /* 31 */ "NotExists" OpHelp("intkey=r[P3]"),
- /* 32 */ "Last" OpHelp(""),
- /* 33 */ "IfSmaller" OpHelp(""),
- /* 34 */ "SorterSort" OpHelp(""),
- /* 35 */ "Sort" OpHelp(""),
- /* 36 */ "Rewind" OpHelp(""),
- /* 37 */ "IdxLE" OpHelp("key=r[P3@P4]"),
- /* 38 */ "IdxGT" OpHelp("key=r[P3@P4]"),
- /* 39 */ "IdxLT" OpHelp("key=r[P3@P4]"),
- /* 40 */ "IdxGE" OpHelp("key=r[P3@P4]"),
- /* 41 */ "RowSetRead" OpHelp("r[P3]=rowset(P1)"),
- /* 42 */ "RowSetTest" OpHelp("if r[P3] in rowset(P1) goto P2"),
+ /* 26 */ "IfNotOpen" OpHelp("if( !csr[P1] ) goto P2"),
+ /* 27 */ "IfNoHope" OpHelp("key=r[P3@P4]"),
+ /* 28 */ "NoConflict" OpHelp("key=r[P3@P4]"),
+ /* 29 */ "NotFound" OpHelp("key=r[P3@P4]"),
+ /* 30 */ "Found" OpHelp("key=r[P3@P4]"),
+ /* 31 */ "SeekRowid" OpHelp("intkey=r[P3]"),
+ /* 32 */ "NotExists" OpHelp("intkey=r[P3]"),
+ /* 33 */ "Last" OpHelp(""),
+ /* 34 */ "IfSmaller" OpHelp(""),
+ /* 35 */ "SorterSort" OpHelp(""),
+ /* 36 */ "Sort" OpHelp(""),
+ /* 37 */ "Rewind" OpHelp(""),
+ /* 38 */ "IdxLE" OpHelp("key=r[P3@P4]"),
+ /* 39 */ "IdxGT" OpHelp("key=r[P3@P4]"),
+ /* 40 */ "IdxLT" OpHelp("key=r[P3@P4]"),
+ /* 41 */ "IdxGE" OpHelp("key=r[P3@P4]"),
+ /* 42 */ "RowSetRead" OpHelp("r[P3]=rowset(P1)"),
/* 43 */ "Or" OpHelp("r[P3]=(r[P1] || r[P2])"),
/* 44 */ "And" OpHelp("r[P3]=(r[P1] && r[P2])"),
- /* 45 */ "Program" OpHelp(""),
- /* 46 */ "FkIfZero" OpHelp("if fkctr[P1]==0 goto P2"),
- /* 47 */ "IfPos" OpHelp("if r[P1]>0 then r[P1]-=P3, goto P2"),
- /* 48 */ "IfNotZero" OpHelp("if r[P1]!=0 then r[P1]--, goto P2"),
- /* 49 */ "DecrJumpZero" OpHelp("if (--r[P1])==0 goto P2"),
+ /* 45 */ "RowSetTest" OpHelp("if r[P3] in rowset(P1) goto P2"),
+ /* 46 */ "Program" OpHelp(""),
+ /* 47 */ "FkIfZero" OpHelp("if fkctr[P1]==0 goto P2"),
+ /* 48 */ "IfPos" OpHelp("if r[P1]>0 then r[P1]-=P3, goto P2"),
+ /* 49 */ "IfNotZero" OpHelp("if r[P1]!=0 then r[P1]--, goto P2"),
/* 50 */ "IsNull" OpHelp("if r[P1]==NULL goto P2"),
/* 51 */ "NotNull" OpHelp("if r[P1]!=NULL goto P2"),
/* 52 */ "Ne" OpHelp("IF r[P3]!=r[P1]"),
@@ -31777,29 +33730,29 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
/* 55 */ "Le" OpHelp("IF r[P3]<=r[P1]"),
/* 56 */ "Lt" OpHelp("IF r[P3]=r[P1]"),
- /* 58 */ "ElseNotEq" OpHelp(""),
- /* 59 */ "IncrVacuum" OpHelp(""),
- /* 60 */ "VNext" OpHelp(""),
- /* 61 */ "Init" OpHelp("Start at P2"),
- /* 62 */ "PureFunc0" OpHelp(""),
- /* 63 */ "Function0" OpHelp("r[P3]=func(r[P2@P5])"),
- /* 64 */ "PureFunc" OpHelp(""),
- /* 65 */ "Function" OpHelp("r[P3]=func(r[P2@P5])"),
- /* 66 */ "Return" OpHelp(""),
- /* 67 */ "EndCoroutine" OpHelp(""),
- /* 68 */ "HaltIfNull" OpHelp("if r[P3]=null halt"),
- /* 69 */ "Halt" OpHelp(""),
- /* 70 */ "Integer" OpHelp("r[P2]=P1"),
- /* 71 */ "Int64" OpHelp("r[P2]=P4"),
- /* 72 */ "String" OpHelp("r[P2]='P4' (len=P1)"),
- /* 73 */ "Null" OpHelp("r[P2..P3]=NULL"),
- /* 74 */ "SoftNull" OpHelp("r[P1]=NULL"),
- /* 75 */ "Blob" OpHelp("r[P2]=P4 (len=P1)"),
- /* 76 */ "Variable" OpHelp("r[P2]=parameter(P1,P4)"),
- /* 77 */ "Move" OpHelp("r[P2@P3]=r[P1@P3]"),
- /* 78 */ "Copy" OpHelp("r[P2@P3+1]=r[P1@P3+1]"),
- /* 79 */ "SCopy" OpHelp("r[P2]=r[P1]"),
- /* 80 */ "IntCopy" OpHelp("r[P2]=r[P1]"),
+ /* 58 */ "ElseEq" OpHelp(""),
+ /* 59 */ "DecrJumpZero" OpHelp("if (--r[P1])==0 goto P2"),
+ /* 60 */ "IncrVacuum" OpHelp(""),
+ /* 61 */ "VNext" OpHelp(""),
+ /* 62 */ "Init" OpHelp("Start at P2"),
+ /* 63 */ "PureFunc" OpHelp("r[P3]=func(r[P2@NP])"),
+ /* 64 */ "Function" OpHelp("r[P3]=func(r[P2@NP])"),
+ /* 65 */ "Return" OpHelp(""),
+ /* 66 */ "EndCoroutine" OpHelp(""),
+ /* 67 */ "HaltIfNull" OpHelp("if r[P3]=null halt"),
+ /* 68 */ "Halt" OpHelp(""),
+ /* 69 */ "Integer" OpHelp("r[P2]=P1"),
+ /* 70 */ "Int64" OpHelp("r[P2]=P4"),
+ /* 71 */ "String" OpHelp("r[P2]='P4' (len=P1)"),
+ /* 72 */ "Null" OpHelp("r[P2..P3]=NULL"),
+ /* 73 */ "SoftNull" OpHelp("r[P1]=NULL"),
+ /* 74 */ "Blob" OpHelp("r[P2]=P4 (len=P1)"),
+ /* 75 */ "Variable" OpHelp("r[P2]=parameter(P1,P4)"),
+ /* 76 */ "Move" OpHelp("r[P2@P3]=r[P1@P3]"),
+ /* 77 */ "Copy" OpHelp("r[P2@P3+1]=r[P1@P3+1]"),
+ /* 78 */ "SCopy" OpHelp("r[P2]=r[P1]"),
+ /* 79 */ "IntCopy" OpHelp("r[P2]=r[P1]"),
+ /* 80 */ "ChngCntRow" OpHelp("output=r[P1]"),
/* 81 */ "ResultRow" OpHelp("output=r[P1@P2]"),
/* 82 */ "CollSeq" OpHelp(""),
/* 83 */ "AddImm" OpHelp("r[P1]=r[P1]+P2"),
@@ -31808,91 +33761,97 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
/* 86 */ "Permutation" OpHelp(""),
/* 87 */ "Compare" OpHelp("r[P1@P3] <-> r[P2@P3]"),
/* 88 */ "IsTrue" OpHelp("r[P2] = coalesce(r[P1]==TRUE,P3) ^ P4"),
- /* 89 */ "Offset" OpHelp("r[P3] = sqlite_offset(P1)"),
- /* 90 */ "Column" OpHelp("r[P3]=PX"),
- /* 91 */ "Affinity" OpHelp("affinity(r[P1@P2])"),
- /* 92 */ "BitAnd" OpHelp("r[P3]=r[P1]&r[P2]"),
- /* 93 */ "BitOr" OpHelp("r[P3]=r[P1]|r[P2]"),
- /* 94 */ "ShiftLeft" OpHelp("r[P3]=r[P2]<>r[P1]"),
- /* 96 */ "Add" OpHelp("r[P3]=r[P1]+r[P2]"),
- /* 97 */ "Subtract" OpHelp("r[P3]=r[P2]-r[P1]"),
- /* 98 */ "Multiply" OpHelp("r[P3]=r[P1]*r[P2]"),
- /* 99 */ "Divide" OpHelp("r[P3]=r[P2]/r[P1]"),
- /* 100 */ "Remainder" OpHelp("r[P3]=r[P2]%r[P1]"),
- /* 101 */ "Concat" OpHelp("r[P3]=r[P2]+r[P1]"),
- /* 102 */ "MakeRecord" OpHelp("r[P3]=mkrec(r[P1@P2])"),
- /* 103 */ "BitNot" OpHelp("r[P2]= ~r[P1]"),
- /* 104 */ "Count" OpHelp("r[P2]=count()"),
- /* 105 */ "ReadCookie" OpHelp(""),
- /* 106 */ "String8" OpHelp("r[P2]='P4'"),
- /* 107 */ "SetCookie" OpHelp(""),
- /* 108 */ "ReopenIdx" OpHelp("root=P2 iDb=P3"),
- /* 109 */ "OpenRead" OpHelp("root=P2 iDb=P3"),
- /* 110 */ "OpenWrite" OpHelp("root=P2 iDb=P3"),
- /* 111 */ "OpenDup" OpHelp(""),
- /* 112 */ "OpenAutoindex" OpHelp("nColumn=P2"),
- /* 113 */ "OpenEphemeral" OpHelp("nColumn=P2"),
+ /* 89 */ "ZeroOrNull" OpHelp("r[P2] = 0 OR NULL"),
+ /* 90 */ "Offset" OpHelp("r[P3] = sqlite_offset(P1)"),
+ /* 91 */ "Column" OpHelp("r[P3]=PX"),
+ /* 92 */ "Affinity" OpHelp("affinity(r[P1@P2])"),
+ /* 93 */ "MakeRecord" OpHelp("r[P3]=mkrec(r[P1@P2])"),
+ /* 94 */ "Count" OpHelp("r[P2]=count()"),
+ /* 95 */ "ReadCookie" OpHelp(""),
+ /* 96 */ "SetCookie" OpHelp(""),
+ /* 97 */ "ReopenIdx" OpHelp("root=P2 iDb=P3"),
+ /* 98 */ "OpenRead" OpHelp("root=P2 iDb=P3"),
+ /* 99 */ "OpenWrite" OpHelp("root=P2 iDb=P3"),
+ /* 100 */ "OpenDup" OpHelp(""),
+ /* 101 */ "OpenAutoindex" OpHelp("nColumn=P2"),
+ /* 102 */ "BitAnd" OpHelp("r[P3]=r[P1]&r[P2]"),
+ /* 103 */ "BitOr" OpHelp("r[P3]=r[P1]|r[P2]"),
+ /* 104 */ "ShiftLeft" OpHelp("r[P3]=r[P2]<>r[P1]"),
+ /* 106 */ "Add" OpHelp("r[P3]=r[P1]+r[P2]"),
+ /* 107 */ "Subtract" OpHelp("r[P3]=r[P2]-r[P1]"),
+ /* 108 */ "Multiply" OpHelp("r[P3]=r[P1]*r[P2]"),
+ /* 109 */ "Divide" OpHelp("r[P3]=r[P2]/r[P1]"),
+ /* 110 */ "Remainder" OpHelp("r[P3]=r[P2]%r[P1]"),
+ /* 111 */ "Concat" OpHelp("r[P3]=r[P2]+r[P1]"),
+ /* 112 */ "OpenEphemeral" OpHelp("nColumn=P2"),
+ /* 113 */ "BitNot" OpHelp("r[P2]= ~r[P1]"),
/* 114 */ "SorterOpen" OpHelp(""),
/* 115 */ "SequenceTest" OpHelp("if( cursor[P1].ctr++ ) pc = P2"),
- /* 116 */ "OpenPseudo" OpHelp("P3 columns in r[P2]"),
- /* 117 */ "Close" OpHelp(""),
- /* 118 */ "ColumnsUsed" OpHelp(""),
- /* 119 */ "SeekHit" OpHelp("seekHit=P2"),
- /* 120 */ "Sequence" OpHelp("r[P2]=cursor[P1].ctr++"),
- /* 121 */ "NewRowid" OpHelp("r[P2]=rowid"),
- /* 122 */ "Insert" OpHelp("intkey=r[P3] data=r[P2]"),
- /* 123 */ "InsertInt" OpHelp("intkey=P3 data=r[P2]"),
- /* 124 */ "Delete" OpHelp(""),
- /* 125 */ "ResetCount" OpHelp(""),
- /* 126 */ "SorterCompare" OpHelp("if key(P1)!=trim(r[P3],P4) goto P2"),
- /* 127 */ "SorterData" OpHelp("r[P2]=data"),
- /* 128 */ "RowData" OpHelp("r[P2]=data"),
- /* 129 */ "Rowid" OpHelp("r[P2]=rowid"),
- /* 130 */ "NullRow" OpHelp(""),
- /* 131 */ "SeekEnd" OpHelp(""),
- /* 132 */ "SorterInsert" OpHelp("key=r[P2]"),
- /* 133 */ "IdxInsert" OpHelp("key=r[P2]"),
- /* 134 */ "IdxDelete" OpHelp("key=r[P2@P3]"),
- /* 135 */ "DeferredSeek" OpHelp("Move P3 to P1.rowid if needed"),
- /* 136 */ "IdxRowid" OpHelp("r[P2]=rowid"),
- /* 137 */ "Destroy" OpHelp(""),
- /* 138 */ "Clear" OpHelp(""),
- /* 139 */ "ResetSorter" OpHelp(""),
- /* 140 */ "CreateBtree" OpHelp("r[P2]=root iDb=P1 flags=P3"),
- /* 141 */ "Real" OpHelp("r[P2]=P4"),
- /* 142 */ "SqlExec" OpHelp(""),
- /* 143 */ "ParseSchema" OpHelp(""),
- /* 144 */ "LoadAnalysis" OpHelp(""),
- /* 145 */ "DropTable" OpHelp(""),
- /* 146 */ "DropIndex" OpHelp(""),
- /* 147 */ "DropTrigger" OpHelp(""),
- /* 148 */ "IntegrityCk" OpHelp(""),
- /* 149 */ "RowSetAdd" OpHelp("rowset(P1)=r[P2]"),
- /* 150 */ "Param" OpHelp(""),
- /* 151 */ "FkCounter" OpHelp("fkctr[P1]+=P2"),
- /* 152 */ "MemMax" OpHelp("r[P1]=max(r[P1],r[P2])"),
- /* 153 */ "OffsetLimit" OpHelp("if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1)"),
- /* 154 */ "AggInverse" OpHelp("accum=r[P3] inverse(r[P2@P5])"),
- /* 155 */ "AggStep" OpHelp("accum=r[P3] step(r[P2@P5])"),
- /* 156 */ "AggStep1" OpHelp("accum=r[P3] step(r[P2@P5])"),
- /* 157 */ "AggValue" OpHelp("r[P3]=value N=P2"),
- /* 158 */ "AggFinal" OpHelp("accum=r[P1] N=P2"),
- /* 159 */ "Expire" OpHelp(""),
- /* 160 */ "TableLock" OpHelp("iDb=P1 root=P2 write=P3"),
- /* 161 */ "VBegin" OpHelp(""),
- /* 162 */ "VCreate" OpHelp(""),
- /* 163 */ "VDestroy" OpHelp(""),
- /* 164 */ "VOpen" OpHelp(""),
- /* 165 */ "VColumn" OpHelp("r[P3]=vcolumn(P2)"),
- /* 166 */ "VRename" OpHelp(""),
- /* 167 */ "Pagecount" OpHelp(""),
- /* 168 */ "MaxPgcnt" OpHelp(""),
- /* 169 */ "Trace" OpHelp(""),
- /* 170 */ "CursorHint" OpHelp(""),
- /* 171 */ "Noop" OpHelp(""),
- /* 172 */ "Explain" OpHelp(""),
- /* 173 */ "Abortable" OpHelp(""),
+ /* 116 */ "String8" OpHelp("r[P2]='P4'"),
+ /* 117 */ "OpenPseudo" OpHelp("P3 columns in r[P2]"),
+ /* 118 */ "Close" OpHelp(""),
+ /* 119 */ "ColumnsUsed" OpHelp(""),
+ /* 120 */ "SeekScan" OpHelp("Scan-ahead up to P1 rows"),
+ /* 121 */ "SeekHit" OpHelp("set P2<=seekHit<=P3"),
+ /* 122 */ "Sequence" OpHelp("r[P2]=cursor[P1].ctr++"),
+ /* 123 */ "NewRowid" OpHelp("r[P2]=rowid"),
+ /* 124 */ "Insert" OpHelp("intkey=r[P3] data=r[P2]"),
+ /* 125 */ "RowCell" OpHelp(""),
+ /* 126 */ "Delete" OpHelp(""),
+ /* 127 */ "ResetCount" OpHelp(""),
+ /* 128 */ "SorterCompare" OpHelp("if key(P1)!=trim(r[P3],P4) goto P2"),
+ /* 129 */ "SorterData" OpHelp("r[P2]=data"),
+ /* 130 */ "RowData" OpHelp("r[P2]=data"),
+ /* 131 */ "Rowid" OpHelp("r[P2]=rowid"),
+ /* 132 */ "NullRow" OpHelp(""),
+ /* 133 */ "SeekEnd" OpHelp(""),
+ /* 134 */ "IdxInsert" OpHelp("key=r[P2]"),
+ /* 135 */ "SorterInsert" OpHelp("key=r[P2]"),
+ /* 136 */ "IdxDelete" OpHelp("key=r[P2@P3]"),
+ /* 137 */ "DeferredSeek" OpHelp("Move P3 to P1.rowid if needed"),
+ /* 138 */ "IdxRowid" OpHelp("r[P2]=rowid"),
+ /* 139 */ "FinishSeek" OpHelp(""),
+ /* 140 */ "Destroy" OpHelp(""),
+ /* 141 */ "Clear" OpHelp(""),
+ /* 142 */ "ResetSorter" OpHelp(""),
+ /* 143 */ "CreateBtree" OpHelp("r[P2]=root iDb=P1 flags=P3"),
+ /* 144 */ "SqlExec" OpHelp(""),
+ /* 145 */ "ParseSchema" OpHelp(""),
+ /* 146 */ "LoadAnalysis" OpHelp(""),
+ /* 147 */ "DropTable" OpHelp(""),
+ /* 148 */ "DropIndex" OpHelp(""),
+ /* 149 */ "DropTrigger" OpHelp(""),
+ /* 150 */ "IntegrityCk" OpHelp(""),
+ /* 151 */ "RowSetAdd" OpHelp("rowset(P1)=r[P2]"),
+ /* 152 */ "Real" OpHelp("r[P2]=P4"),
+ /* 153 */ "Param" OpHelp(""),
+ /* 154 */ "FkCounter" OpHelp("fkctr[P1]+=P2"),
+ /* 155 */ "MemMax" OpHelp("r[P1]=max(r[P1],r[P2])"),
+ /* 156 */ "OffsetLimit" OpHelp("if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1)"),
+ /* 157 */ "AggInverse" OpHelp("accum=r[P3] inverse(r[P2@P5])"),
+ /* 158 */ "AggStep" OpHelp("accum=r[P3] step(r[P2@P5])"),
+ /* 159 */ "AggStep1" OpHelp("accum=r[P3] step(r[P2@P5])"),
+ /* 160 */ "AggValue" OpHelp("r[P3]=value N=P2"),
+ /* 161 */ "AggFinal" OpHelp("accum=r[P1] N=P2"),
+ /* 162 */ "Expire" OpHelp(""),
+ /* 163 */ "CursorLock" OpHelp(""),
+ /* 164 */ "CursorUnlock" OpHelp(""),
+ /* 165 */ "TableLock" OpHelp("iDb=P1 root=P2 write=P3"),
+ /* 166 */ "VBegin" OpHelp(""),
+ /* 167 */ "VCreate" OpHelp(""),
+ /* 168 */ "VDestroy" OpHelp(""),
+ /* 169 */ "VOpen" OpHelp(""),
+ /* 170 */ "VColumn" OpHelp("r[P3]=vcolumn(P2)"),
+ /* 171 */ "VRename" OpHelp(""),
+ /* 172 */ "Pagecount" OpHelp(""),
+ /* 173 */ "MaxPgcnt" OpHelp(""),
+ /* 174 */ "Trace" OpHelp(""),
+ /* 175 */ "CursorHint" OpHelp(""),
+ /* 176 */ "ReleaseReg" OpHelp("release r[P1@P2] mask P3"),
+ /* 177 */ "Noop" OpHelp(""),
+ /* 178 */ "Explain" OpHelp(""),
+ /* 179 */ "Abortable" OpHelp(""),
};
return azName[i];
}
@@ -31963,7 +33922,7 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
** 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__)
@@ -32007,13 +33966,30 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
# include
#endif /* SQLITE_ENABLE_LOCKING_STYLE */
-#if defined(__APPLE__) && ((__MAC_OS_X_VERSION_MIN_REQUIRED > 1050) || \
- (__IPHONE_OS_VERSION_MIN_REQUIRED > 2000))
-# if (!defined(TARGET_OS_EMBEDDED) || (TARGET_OS_EMBEDDED==0)) \
- && (!defined(TARGET_IPHONE_SIMULATOR) || (TARGET_IPHONE_SIMULATOR==0))
-# define HAVE_GETHOSTUUID 1
-# else
-# warning "gethostuuid() is disabled."
+/*
+** Try to determine if gethostuuid() is available based on standard
+** macros. This might sometimes compute the wrong value for some
+** obscure platforms. For those cases, simply compile with one of
+** the following:
+**
+** -DHAVE_GETHOSTUUID=0
+** -DHAVE_GETHOSTUUID=1
+**
+** None if this matters except when building on Apple products with
+** -DSQLITE_ENABLE_LOCKING_STYLE.
+*/
+#ifndef HAVE_GETHOSTUUID
+# define HAVE_GETHOSTUUID 0
+# if defined(__APPLE__) && ((__MAC_OS_X_VERSION_MIN_REQUIRED > 1050) || \
+ (__IPHONE_OS_VERSION_MIN_REQUIRED > 2000))
+# if (!defined(TARGET_OS_EMBEDDED) || (TARGET_OS_EMBEDDED==0)) \
+ && (!defined(TARGET_IPHONE_SIMULATOR) || (TARGET_IPHONE_SIMULATOR==0))\
+ && (!defined(TARGET_OS_MACCATALYST) || (TARGET_OS_MACCATALYST==0))
+# undef HAVE_GETHOSTUUID
+# define HAVE_GETHOSTUUID 1
+# else
+# warning "gethostuuid() is disabled."
+# endif
# endif
#endif
@@ -32038,12 +34014,10 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
#define SQLITE_FSFLAGS_IS_MSDOS 0x1
/*
-** If we are to be thread-safe, include the pthreads header and define
-** the SQLITE_UNIX_THREADS macro.
+** If we are to be thread-safe, include the pthreads header.
*/
#if SQLITE_THREADSAFE
/* # include */
-# define SQLITE_UNIX_THREADS 1
#endif
/*
@@ -32075,7 +34049,7 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
#define osGetpid(X) (pid_t)getpid()
/*
-** 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))
@@ -32143,7 +34117,7 @@ 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 */
@@ -32152,7 +34126,7 @@ struct unixFile {
#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];
@@ -32242,7 +34216,7 @@ static pid_t randomnessPid = 0;
******************************************************************************
**
** This file contains inline asm code for retrieving "high-performance"
-** counters for x86 class CPUs.
+** counters for x86 and x86_64 class CPUs.
*/
#ifndef SQLITE_HWTIME_H
#define SQLITE_HWTIME_H
@@ -32253,8 +34227,9 @@ static pid_t randomnessPid = 0;
** processor and returns that value. This can be used for high-res
** profiling.
*/
-#if (defined(__GNUC__) || defined(_MSC_VER)) && \
- (defined(i386) || defined(__i386__) || defined(_M_IX86))
+#if !defined(__STRICT_ANSI__) && \
+ (defined(__GNUC__) || defined(_MSC_VER)) && \
+ (defined(i386) || defined(__i386__) || defined(_M_IX86))
#if defined(__GNUC__)
@@ -32275,15 +34250,15 @@ static pid_t randomnessPid = 0;
#endif
-#elif (defined(__GNUC__) && defined(__x86_64__))
+#elif !defined(__STRICT_ANSI__) && (defined(__GNUC__) && defined(__x86_64__))
__inline__ sqlite_uint64 sqlite3Hwtime(void){
unsigned long val;
__asm__ __volatile__ ("rdtsc" : "=A" (val));
return val;
}
-
-#elif (defined(__GNUC__) && defined(__ppc__))
+
+#elif !defined(__STRICT_ANSI__) && (defined(__GNUC__) && defined(__ppc__))
__inline__ sqlite_uint64 sqlite3Hwtime(void){
unsigned long long retval;
@@ -32300,14 +34275,13 @@ static pid_t randomnessPid = 0;
#else
- #error Need implementation of sqlite3Hwtime() for your platform.
-
/*
- ** To compile without implementing sqlite3Hwtime() for your platform,
- ** you can remove the above #error and use the following
- ** stub function. You will lose timing support for many
- ** of the debugging and testing utilities, but it should at
- ** least compile and run.
+ ** asm() is needed for hardware timing support. Without asm(),
+ ** disable the sqlite3Hwtime() routine.
+ **
+ ** sqlite3Hwtime() is only used for some obscure debugging
+ ** and analysis configurations, not in any deliverable, so this
+ ** should not be a great loss.
*/
SQLITE_PRIVATE sqlite_uint64 sqlite3Hwtime(void){ return ((sqlite_uint64)0); }
@@ -32495,7 +34469,7 @@ static struct unix_syscall {
#ifdef __DJGPP__
{ "fstat", 0, 0 },
#define osFstat(a,b,c) 0
-#else
+#else
{ "fstat", (sqlite3_syscall_ptr)fstat, 0 },
#define osFstat ((int(*)(int,struct stat*))aSyscall[5].pCurrent)
#endif
@@ -32623,13 +34597,14 @@ static struct unix_syscall {
#if defined(__linux__) && defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE)
# ifdef __ANDROID__
{ "ioctl", (sqlite3_syscall_ptr)(int(*)(int, int, ...))ioctl, 0 },
+#define osIoctl ((int(*)(int,int,...))aSyscall[28].pCurrent)
# else
{ "ioctl", (sqlite3_syscall_ptr)ioctl, 0 },
+#define osIoctl ((int(*)(int,unsigned long,...))aSyscall[28].pCurrent)
# endif
#else
{ "ioctl", (sqlite3_syscall_ptr)0, 0 },
#endif
-#define osIoctl ((int(*)(int,int,...))aSyscall[28].pCurrent)
}; /* End of the overrideable system calls */
@@ -32732,7 +34707,7 @@ static const char *unixNextSystemCall(sqlite3_vfs *p, const char *zName){
/*
** Do not accept any file descriptor less than this value, in order to avoid
-** opening database file using file descriptors that are commonly used for
+** opening database file using file descriptors that are commonly used for
** standard input, output, and error.
*/
#ifndef SQLITE_MINIMUM_FILE_DESCRIPTOR
@@ -32771,17 +34746,17 @@ static int robust_open(const char *z, int f, mode_t m){
}
if( fd>=SQLITE_MINIMUM_FILE_DESCRIPTOR ) break;
osClose(fd);
- sqlite3_log(SQLITE_WARNING,
+ sqlite3_log(SQLITE_WARNING,
"attempt to open \"%s\" as file descriptor %d", z, fd);
fd = -1;
- if( osOpen("/dev/null", f, m)<0 ) break;
+ if( osOpen("/dev/null", O_RDONLY, m)<0 ) break;
}
if( fd>=0 ){
if( m!=0 ){
struct stat statbuf;
- if( osFstat(fd, &statbuf)==0
+ if( osFstat(fd, &statbuf)==0
&& statbuf.st_size==0
- && (statbuf.st_mode&0777)!=m
+ && (statbuf.st_mode&0777)!=m
){
osFchmod(fd, m);
}
@@ -32796,11 +34771,11 @@ static int robust_open(const char *z, int f, mode_t m){
/*
** 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
+** 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()
@@ -32922,7 +34897,7 @@ static int lockTrace(int fd, int op, struct flock *p){
static int robust_ftruncate(int h, sqlite3_int64 sz){
int rc;
#ifdef __ANDROID__
- /* On Android, ftruncate() always uses 32-bit offsets, even if
+ /* On Android, ftruncate() always uses 32-bit offsets, even if
** _FILE_OFFSET_BITS=64 is defined. This means it is unsafe to attempt to
** truncate a file to any size larger than 2GiB. Silently ignore any
** such attempts. */
@@ -32938,32 +34913,32 @@ static int robust_ftruncate(int h, sqlite3_int64 sz){
** 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) {
- assert( (sqliteIOErr == SQLITE_IOERR_LOCK) ||
- (sqliteIOErr == SQLITE_IOERR_UNLOCK) ||
+ assert( (sqliteIOErr == SQLITE_IOERR_LOCK) ||
+ (sqliteIOErr == SQLITE_IOERR_UNLOCK) ||
(sqliteIOErr == SQLITE_IOERR_RDLOCK) ||
(sqliteIOErr == SQLITE_IOERR_CHECKRESERVEDLOCK) );
switch (posixError) {
- case EACCES:
+ case EACCES:
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 EPERM:
+
+ case EPERM:
return SQLITE_PERM;
-
- default:
+
+ default:
return sqliteIOErr;
}
}
@@ -32978,7 +34953,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.
**
@@ -32994,7 +34969,7 @@ struct vxworksFileId {
};
#if OS_VXWORKS
-/*
+/*
** All unique filenames are held on a linked list headed by this
** variable:
*/
@@ -33066,7 +35041,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);
@@ -33159,7 +35134,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.
**
@@ -33192,7 +35167,7 @@ static void vxworksReleaseFileId(struct vxworksFileId *pId){
**
** 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
+** 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.
*/
@@ -33209,7 +35184,7 @@ struct unixFileId {
/* We are told that some versions of Android contain a bug that
** sizes ino_t at only 32-bits instead of 64-bits. (See
** https://android-review.googlesource.com/#/c/115351/3/dist/sqlite3.c)
- ** To work around this, always allocate 64-bits for the inode number.
+ ** To work around this, always allocate 64-bits for the inode number.
** On small machines that only have 32-bit inodes, this wastes 4 bytes,
** but that should not be a big deal. */
/* WAS: ino_t ino; */
@@ -33219,8 +35194,7 @@ struct unixFileId {
/*
** 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.
+** inode.
**
** A single inode can have multiple file descriptors, so each unixFile
** structure contains a pointer to an instance of this object and this
@@ -33266,13 +35240,16 @@ struct unixInodeInfo {
/*
** A lists of all unixInodeInfo objects.
+**
+** Must hold unixBigLock in order to read or write this variable.
*/
static unixInodeInfo *inodeList = 0; /* All unixInodeInfo objects */
#ifdef SQLITE_DEBUG
/*
-** True if the inode mutex is held, or not. Used only within assert()
-** to help verify correct mutex usage.
+** True if the inode mutex (on the unixFile.pFileMutex field) is held, or not.
+** This routine is used only within assert() to help verify correct mutex
+** usage.
*/
int unixFileMutexHeld(unixFile *pFile){
assert( pFile->pInode );
@@ -33295,7 +35272,7 @@ int unixFileMutexNotheld(unixFile *pFile){
** strerror_r().
**
** The first argument passed to the macro should be the error code that
-** will be returned to SQLite (e.g. SQLITE_IOERR_DELETE, SQLITE_CANTOPEN).
+** will be returned to SQLite (e.g. SQLITE_IOERR_DELETE, SQLITE_CANTOPEN).
** The two subsequent arguments should be the name of the OS function that
** failed (e.g. "unlink", "open") and the associated file-system path,
** if any.
@@ -33313,7 +35290,7 @@ static int unixLogErrorAtLine(
/* If this is not a threadsafe build (SQLITE_THREADSAFE==0), then use
** the strerror() function to obtain the human-readable error message
** equivalent to errno. Otherwise, use strerror_r().
- */
+ */
#if SQLITE_THREADSAFE && defined(HAVE_STRERROR_R)
char aErr[80];
memset(aErr, 0, sizeof(aErr));
@@ -33321,18 +35298,18 @@ static int unixLogErrorAtLine(
/* If STRERROR_R_CHAR_P (set by autoconf scripts) or __USE_GNU is defined,
** assume that the system provides the GNU version of strerror_r() that
- ** returns a pointer to a buffer containing the error message. That pointer
- ** may point to aErr[], or it may point to some static storage somewhere.
- ** Otherwise, assume that the system provides the POSIX version of
+ ** returns a pointer to a buffer containing the error message. That pointer
+ ** may point to aErr[], or it may point to some static storage somewhere.
+ ** Otherwise, assume that the system provides the POSIX version of
** strerror_r(), which always writes an error message into aErr[].
**
** If the code incorrectly assumes that it is the POSIX version that is
** available, the error message will often be an empty string. Not a
- ** huge problem. Incorrectly concluding that the GNU version is available
+ ** huge problem. Incorrectly concluding that the GNU version is available
** could lead to a segfault though.
*/
#if defined(STRERROR_R_CHAR_P) || defined(__USE_GNU)
- zErr =
+ zErr =
# endif
strerror_r(iErrno, aErr, sizeof(aErr)-1);
@@ -33383,7 +35360,7 @@ static void storeLastErrno(unixFile *pFile, int error){
/*
** Close all file descriptors accumuated in the unixInodeInfo->pUnused list.
-*/
+*/
static void closePendingFds(unixFile *pFile){
unixInodeInfo *pInode = pFile->pInode;
UnixUnusedFd *p;
@@ -33400,8 +35377,8 @@ static void closePendingFds(unixFile *pFile){
/*
** Release a unixInodeInfo structure previously allocated by findInodeInfo().
**
-** The mutex entered using the unixEnterMutex() function must be held
-** when this function is called.
+** The global mutex must be held when this routine is called, but the mutex
+** on the inode being deleted must NOT be held.
*/
static void releaseInodeInfo(unixFile *pFile){
unixInodeInfo *pInode = pFile->pInode;
@@ -33436,8 +35413,7 @@ static void releaseInodeInfo(unixFile *pFile){
** describes that file descriptor. Create a new one if necessary. The
** return value might be uninitialized if an error occurs.
**
-** The mutex entered using the unixEnterMutex() function must be held
-** when this function is called.
+** The global mutex must held when calling this routine.
**
** Return an appropriate error code.
*/
@@ -33498,6 +35474,7 @@ static int findInodeInfo(
#else
fileId.ino = (u64)statbuf.st_ino;
#endif
+ assert( unixMutexHeld() );
pInode = inodeList;
while( pInode && memcmp(&fileId, &pInode->fileId, sizeof(fileId)) ){
pInode = pInode->pNext;
@@ -33517,6 +35494,7 @@ static int findInodeInfo(
}
}
pInode->nRef = 1;
+ assert( unixMutexHeld() );
pInode->pNext = inodeList;
pInode->pPrev = 0;
if( inodeList ) inodeList->pPrev = pInode;
@@ -33537,7 +35515,7 @@ static int fileHasMoved(unixFile *pFile){
#else
struct stat buf;
return pFile->pInode!=0 &&
- (osStat(pFile->zPath, &buf)!=0
+ (osStat(pFile->zPath, &buf)!=0
|| (u64)buf.st_ino!=pFile->pInode->fileId.ino);
#endif
}
@@ -33618,7 +35596,7 @@ static int unixCheckReservedLock(sqlite3_file *id, int *pResOut){
}
}
#endif
-
+
sqlite3_mutex_leave(pFile->pInode->pLockMutex);
OSTRACE(("TEST WR-LOCK %d %d %d (unix)\n", pFile->h, rc, reserved));
@@ -33626,6 +35604,9 @@ static int unixCheckReservedLock(sqlite3_file *id, int *pResOut){
return rc;
}
+/* Forward declaration*/
+static int unixSleep(sqlite3_vfs*,int);
+
/*
** Set a posix-advisory-lock.
**
@@ -33647,16 +35628,17 @@ static int osSetPosixAdvisoryLock(
struct flock *pLock, /* The description of the lock */
unixFile *pFile /* Structure holding timeout value */
){
+ int tm = pFile->iBusyTimeout;
int rc = osFcntl(h,F_SETLK,pLock);
- while( rc<0 && pFile->iBusyTimeout>0 ){
+ while( rc<0 && tm>0 ){
/* On systems that support some kind of blocking file lock with a timeout,
** make appropriate changes here to invoke that blocking file lock. On
** generic posix, however, there is no such API. So we simply try the
** lock once every millisecond until either the timeout expires, or until
** the lock is obtained. */
- usleep(1000);
+ unixSleep(0,1000);
rc = osFcntl(h,F_SETLK,pLock);
- pFile->iBusyTimeout--;
+ tm--;
}
return rc;
}
@@ -33664,7 +35646,7 @@ static int osSetPosixAdvisoryLock(
/*
-** Attempt to set a system-lock on the file pFile. The lock is
+** Attempt to set a system-lock on the file pFile. The lock is
** described by pLock.
**
** If the pFile was opened read/write from unix-excl, then the only lock
@@ -33756,7 +35738,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
@@ -33770,7 +35752,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.
*/
int rc = SQLITE_OK;
unixFile *pFile = (unixFile*)id;
@@ -33811,7 +35793,7 @@ static int unixLock(sqlite3_file *id, int eFileLock){
/* 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 &&
+ if( (pFile->eFileLock!=pInode->eFileLock &&
(pInode->eFileLock>=PENDING_LOCK || eFileLock>SHARED_LOCK))
){
rc = SQLITE_BUSY;
@@ -33822,7 +35804,7 @@ 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 &&
+ if( eFileLock==SHARED_LOCK &&
(pInode->eFileLock==SHARED_LOCK || pInode->eFileLock==RESERVED_LOCK) ){
assert( eFileLock==SHARED_LOCK );
assert( pFile->eFileLock==0 );
@@ -33840,7 +35822,7 @@ static int unixLock(sqlite3_file *id, int eFileLock){
*/
lock.l_len = 1L;
lock.l_whence = SEEK_SET;
- if( eFileLock==SHARED_LOCK
+ if( eFileLock==SHARED_LOCK
|| (eFileLock==EXCLUSIVE_LOCK && pFile->eFileLockpLockMutex);
- OSTRACE(("LOCK %d %s %s (unix)\n", pFile->h, azFileLock(eFileLock),
+ OSTRACE(("LOCK %d %s %s (unix)\n", pFile->h, azFileLock(eFileLock),
rc==SQLITE_OK ? "ok" : "failed"));
return rc;
}
@@ -33975,11 +35957,11 @@ static void setPendingFd(unixFile *pFile){
**
** 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
+** 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){
@@ -34017,7 +35999,7 @@ static int posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){
/* 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
+ ** 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]
@@ -34033,7 +36015,7 @@ static int posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){
if( handleNFSUnlock ){
int tErrno; /* Error code from system call errors */
off_t divSize = SHARED_SIZE - 1;
-
+
lock.l_type = F_UNLCK;
lock.l_whence = SEEK_SET;
lock.l_start = SHARED_FIRST;
@@ -34075,11 +36057,11 @@ static int posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){
lock.l_len = SHARED_SIZE;
if( unixFileLock(pFile, &lock) ){
/* In theory, the call to unixFileLock() cannot fail because another
- ** process is holding an incompatible lock. If it does, this
+ ** process is holding an incompatible lock. If it does, this
** indicates that the other process is not following the locking
** protocol. If this happens, return SQLITE_IOERR_RDLOCK. Returning
- ** SQLITE_BUSY would confuse the upper layer (in practice it causes
- ** an assert to fail). */
+ ** SQLITE_BUSY would confuse the upper layer (in practice it causes
+ ** an assert to fail). */
rc = SQLITE_IOERR_RDLOCK;
storeLastErrno(pFile, errno);
goto end_unlock;
@@ -34155,7 +36137,7 @@ static void unixUnmapfile(unixFile *pFd);
#endif
/*
-** 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.
@@ -34218,13 +36200,14 @@ static int unixClose(sqlite3_file *id){
if( pInode->nLock ){
/* If there are outstanding locks, do not actually close the file just
** yet because that would clear those locks. Instead, add the file
- ** descriptor to pInode->pUnused list. It will be automatically closed
+ ** descriptor to pInode->pUnused list. It will be automatically closed
** when the last lock is cleared.
*/
setPendingFd(pFile);
}
sqlite3_mutex_leave(pInode->pLockMutex);
releaseInodeInfo(pFile);
+ assert( pFile->pShm==0 );
rc = closeUnixFile(id);
unixLeaveMutex();
return rc;
@@ -34318,7 +36301,7 @@ static int dotlockCheckReservedLock(sqlite3_file *id, int *pResOut) {
unixFile *pFile = (unixFile*)id;
SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
-
+
assert( pFile );
reserved = osAccess((const char*)pFile->lockingContext, 0)==0;
OSTRACE(("TEST WR-LOCK %d %d %d (dotlock)\n", pFile->h, rc, reserved));
@@ -34372,7 +36355,7 @@ static int dotlockLock(sqlite3_file *id, int eFileLock) {
#endif
return SQLITE_OK;
}
-
+
/* grab an exclusive lock */
rc = osMkdir(zLockFile, 0777);
if( rc<0 ){
@@ -34387,8 +36370,8 @@ static int dotlockLock(sqlite3_file *id, int eFileLock) {
}
}
return rc;
- }
-
+ }
+
/* got it, set the type and return ok */
pFile->eFileLock = eFileLock;
return rc;
@@ -34412,7 +36395,7 @@ static int dotlockUnlock(sqlite3_file *id, int eFileLock) {
OSTRACE(("UNLOCK %d %d was %d pid=%d (dotlock)\n", pFile->h, eFileLock,
pFile->eFileLock, osGetpid(0)));
assert( eFileLock<=SHARED_LOCK );
-
+
/* no-op if possible */
if( pFile->eFileLock==eFileLock ){
return SQLITE_OK;
@@ -34425,7 +36408,7 @@ static int dotlockUnlock(sqlite3_file *id, int eFileLock) {
pFile->eFileLock = SHARED_LOCK;
return SQLITE_OK;
}
-
+
/* To fully unlock the database, delete the lock file */
assert( eFileLock==NO_LOCK );
rc = osRmdir(zLockFile);
@@ -34437,7 +36420,7 @@ static int dotlockUnlock(sqlite3_file *id, int eFileLock) {
rc = SQLITE_IOERR_UNLOCK;
storeLastErrno(pFile, tErrno);
}
- return rc;
+ return rc;
}
pFile->eFileLock = NO_LOCK;
return SQLITE_OK;
@@ -34484,7 +36467,7 @@ static int robust_flock(int fd, int op){
#else
# define robust_flock(a,b) flock(a,b)
#endif
-
+
/*
** This routine checks if there is a RESERVED lock held on the specified
@@ -34496,16 +36479,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 ){
reserved = 1;
}
-
+
/* Otherwise see if some other process holds it. */
if( !reserved ){
/* attempt to get the lock */
@@ -34516,7 +36499,7 @@ static int flockCheckReservedLock(sqlite3_file *id, int *pResOut){
if ( lrc ) {
int tErrno = errno;
/* unlock failed with an error */
- lrc = SQLITE_IOERR_UNLOCK;
+ lrc = SQLITE_IOERR_UNLOCK;
storeLastErrno(pFile, tErrno);
rc = lrc;
}
@@ -34524,7 +36507,7 @@ 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) ){
storeLastErrno(pFile, tErrno);
rc = lrc;
@@ -34578,15 +36561,15 @@ static int flockLock(sqlite3_file *id, int eFileLock) {
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;
return SQLITE_OK;
}
-
+
/* grab an exclusive lock */
-
+
if (robust_flock(pFile->h, LOCK_EX | LOCK_NB)) {
int tErrno = errno;
/* didn't get, must be busy */
@@ -34598,7 +36581,7 @@ static int flockLock(sqlite3_file *id, int eFileLock) {
/* got it, set the type and return ok */
pFile->eFileLock = eFileLock;
}
- OSTRACE(("LOCK %d %s %s (flock)\n", pFile->h, azFileLock(eFileLock),
+ OSTRACE(("LOCK %d %s %s (flock)\n", pFile->h, azFileLock(eFileLock),
rc==SQLITE_OK ? "ok" : "failed"));
#ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS
if( (rc & 0xff) == SQLITE_IOERR ){
@@ -34618,23 +36601,23 @@ static int flockLock(sqlite3_file *id, int eFileLock) {
*/
static int flockUnlock(sqlite3_file *id, int eFileLock) {
unixFile *pFile = (unixFile*)id;
-
+
assert( pFile );
OSTRACE(("UNLOCK %d %d was %d pid=%d (flock)\n", pFile->h, eFileLock,
pFile->eFileLock, osGetpid(0)));
assert( eFileLock<=SHARED_LOCK );
-
+
/* no-op if possible */
if( pFile->eFileLock==eFileLock ){
return SQLITE_OK;
}
-
+
/* shared can just be set because we always have an exclusive */
if (eFileLock==SHARED_LOCK) {
pFile->eFileLock = eFileLock;
return SQLITE_OK;
}
-
+
/* no, really, unlock. */
if( robust_flock(pFile->h, LOCK_UN) ){
#ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS
@@ -34685,14 +36668,14 @@ static int semXCheckReservedLock(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 ){
reserved = 1;
}
-
+
/* Otherwise see if some other process holds it. */
if( !reserved ){
sem_t *pSem = pFile->pInode->pSem;
@@ -34751,14 +36734,14 @@ static int semXLock(sqlite3_file *id, int eFileLock) {
sem_t *pSem = pFile->pInode->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;
rc = SQLITE_OK;
goto sem_end_lock;
}
-
+
/* lock semaphore now but bail out when already locked. */
if( sem_trywait(pSem)==-1 ){
rc = SQLITE_BUSY;
@@ -34788,18 +36771,18 @@ static int semXUnlock(sqlite3_file *id, int eFileLock) {
OSTRACE(("UNLOCK %d %d was %d pid=%d (sem)\n", pFile->h, eFileLock,
pFile->eFileLock, osGetpid(0)));
assert( eFileLock<=SHARED_LOCK );
-
+
/* no-op if possible */
if( pFile->eFileLock==eFileLock ){
return SQLITE_OK;
}
-
+
/* shared can just be set because we always have an exclusive */
if (eFileLock==SHARED_LOCK) {
pFile->eFileLock = eFileLock;
return SQLITE_OK;
}
-
+
/* no, really unlock. */
if ( sem_post(pSem)==-1 ) {
int rc, tErrno = errno;
@@ -34807,7 +36790,7 @@ static int semXUnlock(sqlite3_file *id, int eFileLock) {
if( IS_LOCK_ERROR(rc) ){
storeLastErrno(pFile, tErrno);
}
- return rc;
+ return rc;
}
pFile->eFileLock = NO_LOCK;
return SQLITE_OK;
@@ -34873,7 +36856,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(
@@ -34885,14 +36868,14 @@ 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",
+
+ OSTRACE(("AFPSETLOCK [%s] for %d%s in range %llx:%llx\n",
(setLockFlag?"ON":"OFF"), pFile->h, (pb.fd==-1?"[testval-1]":""),
offset, length));
err = fsctl(path, afpfsByteRangeLock2FSCTL, &pb, 0);
@@ -34927,9 +36910,9 @@ static int afpCheckReservedLock(sqlite3_file *id, int *pResOut){
int reserved = 0;
unixFile *pFile = (unixFile*)id;
afpLockingContext *context;
-
+
SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
-
+
assert( pFile );
context = (afpLockingContext *) pFile->lockingContext;
if( context->reserved ){
@@ -34941,12 +36924,12 @@ static int afpCheckReservedLock(sqlite3_file *id, int *pResOut){
if( pFile->pInode->eFileLock>SHARED_LOCK ){
reserved = 1;
}
-
+
/* Otherwise see if some other process holds it.
*/
if( !reserved ){
/* lock the RESERVED byte */
- int lrc = afpSetLock(context->dbPath, pFile, RESERVED_BYTE, 1,1);
+ 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 */
@@ -34959,10 +36942,10 @@ static int afpCheckReservedLock(sqlite3_file *id, int *pResOut){
rc=lrc;
}
}
-
+
sqlite3_mutex_leave(pFile->pInode->pLockMutex);
OSTRACE(("TEST WR-LOCK %d %d %d (afp)\n", pFile->h, rc, reserved));
-
+
*pResOut = reserved;
return rc;
}
@@ -34996,7 +36979,7 @@ static int afpLock(sqlite3_file *id, int eFileLock){
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),
@@ -35020,7 +37003,7 @@ static int afpLock(sqlite3_file *id, int eFileLock){
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
*/
pInode = pFile->pInode;
@@ -35029,18 +37012,18 @@ static int afpLock(sqlite3_file *id, int eFileLock){
/* 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 &&
+ if( (pFile->eFileLock!=pInode->eFileLock &&
(pInode->eFileLock>=PENDING_LOCK || eFileLock>SHARED_LOCK))
){
rc = SQLITE_BUSY;
goto afp_end_lock;
}
-
+
/* If a SHARED lock is requested, and some thread using this PID already
** has a SHARED or RESERVED lock, then increment reference counts and
** return SQLITE_OK.
*/
- if( eFileLock==SHARED_LOCK &&
+ if( eFileLock==SHARED_LOCK &&
(pInode->eFileLock==SHARED_LOCK || pInode->eFileLock==RESERVED_LOCK) ){
assert( eFileLock==SHARED_LOCK );
assert( pFile->eFileLock==0 );
@@ -35050,12 +37033,12 @@ static int afpLock(sqlite3_file *id, int eFileLock){
pInode->nLock++;
goto afp_end_lock;
}
-
+
/* A PENDING lock is needed before acquiring a SHARED lock and before
** acquiring an EXCLUSIVE lock. For the SHARED lock, the PENDING will
** be released.
*/
- if( eFileLock==SHARED_LOCK
+ if( eFileLock==SHARED_LOCK
|| (eFileLock==EXCLUSIVE_LOCK && pFile->eFileLocknShared==0 );
assert( pInode->eFileLock==0 );
-
+
mask = (sizeof(long)==8) ? LARGEST_INT64 : 0x7fffffff;
/* Now get the read-lock SHARED_LOCK */
/* note that the quality of the randomness doesn't matter that much */
- lk = random();
+ lk = random();
pInode->sharedByte = (lk & mask)%(SHARED_SIZE - 1);
- lrc1 = afpSetLock(context->dbPath, pFile,
+ lrc1 = afpSetLock(context->dbPath, pFile,
SHARED_FIRST+pInode->sharedByte, 1, 1);
if( IS_LOCK_ERROR(lrc1) ){
lrc1Errno = pFile->lastErrno;
}
/* Drop the temporary PENDING lock */
lrc2 = afpSetLock(context->dbPath, pFile, PENDING_BYTE, 1, 0);
-
+
if( IS_LOCK_ERROR(lrc1) ) {
storeLastErrno(pFile, lrc1Errno);
rc = lrc1;
@@ -35123,34 +37106,34 @@ static int afpLock(sqlite3_file *id, int eFileLock){
}
if (!failed && eFileLock == 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)) ){
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,
+ if( failed && (failed2 = afpSetLock(context->dbPath, pFile,
SHARED_FIRST + pInode->sharedByte, 1, 1)) ){
/* Can't reestablish the shared lock. Sqlite can't deal, this is
** a critical I/O error
*/
- rc = ((failed & 0xff) == SQLITE_IOERR) ? failed2 :
+ rc = ((failed & 0xff) == 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;
@@ -35158,10 +37141,10 @@ static int afpLock(sqlite3_file *id, int eFileLock){
pFile->eFileLock = PENDING_LOCK;
pInode->eFileLock = PENDING_LOCK;
}
-
+
afp_end_lock:
sqlite3_mutex_leave(pInode->pLockMutex);
- OSTRACE(("LOCK %d %s %s (afp)\n", pFile->h, azFileLock(eFileLock),
+ OSTRACE(("LOCK %d %s %s (afp)\n", pFile->h, azFileLock(eFileLock),
rc==SQLITE_OK ? "ok" : "failed"));
return rc;
}
@@ -35200,7 +37183,7 @@ static int afpUnlock(sqlite3_file *id, int eFileLock) {
SimulateIOErrorBenign(1);
SimulateIOError( h=(-1) )
SimulateIOErrorBenign(0);
-
+
#ifdef SQLITE_DEBUG
/* When reducing a lock such that other processes can start
** reading the database file again, make sure that the
@@ -35215,7 +37198,7 @@ static int afpUnlock(sqlite3_file *id, int eFileLock) {
|| 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) ){
@@ -35228,11 +37211,11 @@ static int afpUnlock(sqlite3_file *id, int eFileLock) {
}
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 ){
+ context->reserved = 0;
}
}
if( rc==SQLITE_OK && (eFileLock==SHARED_LOCK || pInode->nShared>1)){
@@ -35265,7 +37248,7 @@ static int afpUnlock(sqlite3_file *id, int eFileLock) {
if( pInode->nLock==0 ) closePendingFds(pFile);
}
}
-
+
sqlite3_mutex_leave(pInode->pLockMutex);
if( rc==SQLITE_OK ){
pFile->eFileLock = eFileLock;
@@ -35274,7 +37257,7 @@ static int afpUnlock(sqlite3_file *id, int eFileLock) {
}
/*
-** 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;
@@ -35332,7 +37315,7 @@ static int nfsUnlock(sqlite3_file *id, int eFileLock){
/*
** 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.
+** is available.
**
********************* End of the NFS lock implementation **********************
******************************************************************************/
@@ -35340,7 +37323,7 @@ static int nfsUnlock(sqlite3_file *id, int eFileLock){
/******************************************************************************
**************** 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
@@ -35348,7 +37331,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
@@ -35410,8 +37393,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
){
@@ -35421,12 +37404,12 @@ static int unixRead(
assert( offset>=0 );
assert( amt>0 );
- /* If this is a database file (not a journal, master-journal or temp
+ /* If this is a database file (not a journal, super-journal or temp
** file), the bytes in the locking range should never be read or written. */
#if 0
assert( pFile->pPreallocatedUnused==0
|| offset>=PENDING_BYTE+512
- || offset+amt<=PENDING_BYTE
+ || offset+amt<=PENDING_BYTE
);
#endif
@@ -35451,7 +37434,24 @@ static int unixRead(
if( got==amt ){
return SQLITE_OK;
}else if( got<0 ){
- /* lastErrno set by seekAndRead */
+ /* pFile->lastErrno has been set by seekAndRead().
+ ** Usually we return SQLITE_IOERR_READ here, though for some
+ ** kinds of errors we return SQLITE_IOERR_CORRUPTFS. The
+ ** SQLITE_IOERR_CORRUPTFS will be converted into SQLITE_CORRUPT
+ ** prior to returning to the application by the sqlite3ApiExit()
+ ** routine.
+ */
+ switch( pFile->lastErrno ){
+ case ERANGE:
+ case EIO:
+#ifdef ENXIO
+ case ENXIO:
+#endif
+#ifdef EDEVERR
+ case EDEVERR:
+#endif
+ return SQLITE_IOERR_CORRUPTFS;
+ }
return SQLITE_IOERR_READ;
}else{
storeLastErrno(pFile, 0); /* not a system error */
@@ -35464,7 +37464,7 @@ static int unixRead(
/*
** Attempt to seek the file-descriptor passed as the first argument to
** absolute offset iOff, then attempt to write nBuf bytes of data from
-** pBuf to it. If an error occurs, return -1 and set *piErrno. Otherwise,
+** pBuf to it. If an error occurs, return -1 and set *piErrno. Otherwise,
** return the actual number of bytes written (which may be less than
** nBuf).
*/
@@ -35524,22 +37524,22 @@ 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;
assert( id );
assert( amt>0 );
- /* If this is a database file (not a journal, master-journal or temp
+ /* If this is a database file (not a journal, super-journal or temp
** file), the bytes in the locking range should never be read or written. */
#if 0
assert( pFile->pPreallocatedUnused==0
|| offset>=PENDING_BYTE+512
- || offset+amt<=PENDING_BYTE
+ || offset+amt<=PENDING_BYTE
);
#endif
@@ -35581,7 +37581,7 @@ static int unixWrite(
}
}
#endif
-
+
while( (wrote = seekAndWrite(pFile, offset, pBuf, amt))0 ){
amt -= wrote;
offset += wrote;
@@ -35647,8 +37647,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
@@ -35662,7 +37662,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
@@ -35676,7 +37676,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.
*/
@@ -35702,11 +37702,11 @@ 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);
@@ -35716,7 +37716,7 @@ static int full_fsync(int fd, int fullSync, int dataOnly){
** 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 ){
@@ -35877,7 +37877,7 @@ static int unixTruncate(sqlite3_file *id, i64 nByte){
#if SQLITE_MAX_MMAP_SIZE>0
/* If the file was just truncated to a size smaller than the currently
** mapped region, reduce the effective mapping size as well. SQLite will
- ** use read() and write() to access data beyond this point from now on.
+ ** use read() and write() to access data beyond this point from now on.
*/
if( nBytemmapSize ){
pFile->mmapSize = nByte;
@@ -35923,8 +37923,8 @@ static int unixFileSize(sqlite3_file *id, i64 *pSize){
static int proxyFileControl(sqlite3_file*,int,void*);
#endif
-/*
-** This function is called to handle the SQLITE_FCNTL_SIZE_HINT
+/*
+** This function is called to handle the SQLITE_FCNTL_SIZE_HINT
** file-control operation. Enlarge the database to nBytes in size
** (rounded up to the next chunk-size). If the database is already
** nBytes or larger, this routine is a no-op.
@@ -35933,7 +37933,7 @@ static int fcntlSizeHint(unixFile *pFile, i64 nByte){
if( pFile->szChunk>0 ){
i64 nSize; /* Required file size */
struct stat buf; /* Used to hold return values of fstat() */
-
+
if( osFstat(pFile->h, &buf) ){
return SQLITE_IOERR_FSTAT;
}
@@ -35942,8 +37942,8 @@ static int fcntlSizeHint(unixFile *pFile, i64 nByte){
if( nSize>(i64)buf.st_size ){
#if defined(HAVE_POSIX_FALLOCATE) && HAVE_POSIX_FALLOCATE
- /* The code below is handling the return value of osFallocate()
- ** correctly. posix_fallocate() is defined to "returns zero on success,
+ /* The code below is handling the return value of osFallocate()
+ ** correctly. posix_fallocate() is defined to "returns zero on success,
** or an error number on failure". See the manpage for details. */
int err;
do{
@@ -35951,7 +37951,7 @@ static int fcntlSizeHint(unixFile *pFile, i64 nByte){
}while( err==EINTR );
if( err && err!=EINVAL ) return SQLITE_IOERR_WRITE;
#else
- /* If the OS does not have posix_fallocate(), fake it. Write a
+ /* If the OS does not have posix_fallocate(), fake it. Write a
** single byte to the last byte in each block that falls entirely
** within the extended region. Then, if required, a single byte
** at offset (nSize-1), to set the size of the file correctly.
@@ -36010,6 +38010,7 @@ static void unixModeBit(unixFile *pFile, unsigned char mask, int *pArg){
/* Forward declaration */
static int unixGetTempname(int nBuf, char *zBuf);
+static int unixFcntlExternalReader(unixFile*, int*);
/*
** Information and control of an open file handle.
@@ -36077,7 +38078,9 @@ static int unixFileControl(sqlite3_file *id, int op, void *pArg){
}
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
case SQLITE_FCNTL_LOCK_TIMEOUT: {
+ int iOld = pFile->iBusyTimeout;
pFile->iBusyTimeout = *(int*)pArg;
+ *(int*)pArg = iOld;
return SQLITE_OK;
}
#endif
@@ -36124,15 +38127,19 @@ static int unixFileControl(sqlite3_file *id, int op, void *pArg){
return proxyFileControl(id,op,pArg);
}
#endif /* SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__) */
+
+ case SQLITE_FCNTL_EXTERNAL_READER: {
+ return unixFcntlExternalReader((unixFile*)id, (int*)pArg);
+ }
}
return SQLITE_NOTFOUND;
}
/*
** If pFd->sectorSize is non-zero when this function is called, it is a
-** no-op. Otherwise, the values of pFd->sectorSize and
-** pFd->deviceCharacteristics are set according to the file-system
-** characteristics.
+** no-op. Otherwise, the values of pFd->sectorSize and
+** pFd->deviceCharacteristics are set according to the file-system
+** characteristics.
**
** There are two versions of this function. One for QNX and one for all
** other systems.
@@ -36166,7 +38173,7 @@ static void setDeviceCharacteristics(unixFile *pFd){
static void setDeviceCharacteristics(unixFile *pFile){
if( pFile->sectorSize == 0 ){
struct statvfs fsInfo;
-
+
/* Set defaults for non-supported filesystems */
pFile->sectorSize = SQLITE_DEFAULT_SECTOR_SIZE;
pFile->deviceCharacteristics = 0;
@@ -36275,7 +38282,7 @@ static int unixDeviceCharacteristics(sqlite3_file *id){
/*
** Return the system page size.
**
-** This function should not be called directly by other code in this file.
+** This function should not be called directly by other code in this file.
** Instead, it should be called via macro osGetpagesize().
*/
static int unixGetpagesize(void){
@@ -36293,7 +38300,7 @@ static int unixGetpagesize(void){
#ifndef SQLITE_OMIT_WAL
/*
-** Object used to represent an shared memory buffer.
+** 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
@@ -36313,19 +38320,19 @@ static int unixGetpagesize(void){
** nRef
**
** The following fields are read-only after the object is created:
-**
-** fid
+**
+** hShm
** zFilename
**
-** Either unixShmNode.mutex must be held or unixShmNode.nRef==0 and
+** Either unixShmNode.pShmMutex must be held or unixShmNode.nRef==0 and
** unixMutexHeld() is true when reading or writing any other field
** in this structure.
*/
struct unixShmNode {
unixInodeInfo *pInode; /* unixInodeInfo that owns this SHM node */
- sqlite3_mutex *mutex; /* Mutex to access this object */
+ sqlite3_mutex *pShmMutex; /* Mutex to access this object */
char *zFilename; /* Name of the mmapped file */
- int h; /* Open file descriptor */
+ int hShm; /* Open file descriptor */
int szRegion; /* Size of shared-memory regions */
u16 nRegion; /* Size of array apRegion */
u8 isReadonly; /* True if read-only */
@@ -36333,6 +38340,7 @@ struct unixShmNode {
char **apRegion; /* Array of mapped shared-memory regions */
int nRef; /* Number of unixShm objects pointing to this */
unixShm *pFirst; /* All unixShm objects pointing to this */
+ int aLock[SQLITE_SHM_NLOCK]; /* # shared locks on slot, -1==excl lock */
#ifdef SQLITE_DEBUG
u8 exclMask; /* Mask of exclusive locks held */
u8 sharedMask; /* Mask of shared locks held */
@@ -36347,16 +38355,16 @@ struct unixShmNode {
** The following fields are initialized when this object is created and
** are read-only thereafter:
**
-** unixShm.pFile
+** unixShm.pShmNode
** unixShm.id
**
-** All other fields are read/write. The unixShm.pFile->mutex must be held
-** while accessing any read/write fields.
+** All other fields are read/write. The unixShm.pShmNode->pShmMutex must
+** be held while accessing any read/write fields.
*/
struct unixShm {
unixShmNode *pShmNode; /* The underlying unixShmNode object */
unixShm *pNext; /* Next unixShm with the same unixShmNode */
- u8 hasMutex; /* True if holding the unixShmNode mutex */
+ u8 hasMutex; /* True if holding the unixShmNode->pShmMutex */
u8 id; /* Id of this connection within its unixShmNode */
u16 sharedMask; /* Mask of shared locks held */
u16 exclMask; /* Mask of exclusive locks held */
@@ -36368,6 +38376,40 @@ struct unixShm {
#define UNIX_SHM_BASE ((22+SQLITE_SHM_NLOCK)*4) /* first lock byte */
#define UNIX_SHM_DMS (UNIX_SHM_BASE+SQLITE_SHM_NLOCK) /* deadman switch */
+/*
+** Use F_GETLK to check whether or not there are any readers with open
+** wal-mode transactions in other processes on database file pFile. If
+** no error occurs, return SQLITE_OK and set (*piOut) to 1 if there are
+** such transactions, or 0 otherwise. If an error occurs, return an
+** SQLite error code. The final value of *piOut is undefined in this
+** case.
+*/
+static int unixFcntlExternalReader(unixFile *pFile, int *piOut){
+ int rc = SQLITE_OK;
+ *piOut = 0;
+ if( pFile->pShm){
+ unixShmNode *pShmNode = pFile->pShm->pShmNode;
+ struct flock f;
+
+ memset(&f, 0, sizeof(f));
+ f.l_type = F_WRLCK;
+ f.l_whence = SEEK_SET;
+ f.l_start = UNIX_SHM_BASE + 3;
+ f.l_len = SQLITE_SHM_NLOCK - 3;
+
+ sqlite3_mutex_enter(pShmNode->pShmMutex);
+ if( osFcntl(pShmNode->hShm, F_GETLK, &f)<0 ){
+ rc = SQLITE_IOERR_LOCK;
+ }else{
+ *piOut = (f.l_type!=F_UNLCK);
+ }
+ sqlite3_mutex_leave(pShmNode->pShmMutex);
+ }
+
+ return rc;
+}
+
+
/*
** Apply posix advisory locks for all bytes from ofst through ofst+n-1.
**
@@ -36386,7 +38428,8 @@ static int unixShmSystemLock(
/* Access to the unixShmNode object is serialized by the caller */
pShmNode = pFile->pInode->pShmNode;
- assert( pShmNode->nRef==0 || sqlite3_mutex_held(pShmNode->mutex) );
+ assert( pShmNode->nRef==0 || sqlite3_mutex_held(pShmNode->pShmMutex) );
+ assert( pShmNode->nRef>0 || unixMutexHeld() );
/* Shared locks never span more than one byte */
assert( n==1 || lockType!=F_RDLCK );
@@ -36394,14 +38437,21 @@ static int unixShmSystemLock(
/* Locks are within range */
assert( n>=1 && n<=SQLITE_SHM_NLOCK );
- if( pShmNode->h>=0 ){
+ if( pShmNode->hShm>=0 ){
+ int res;
/* Initialize the locking parameters */
f.l_type = lockType;
f.l_whence = SEEK_SET;
f.l_start = ofst;
f.l_len = n;
- rc = osSetPosixAdvisoryLock(pShmNode->h, &f, pFile);
- rc = (rc!=(-1)) ? SQLITE_OK : SQLITE_BUSY;
+ res = osSetPosixAdvisoryLock(pShmNode->hShm, &f, pFile);
+ if( res==-1 ){
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+ rc = (pFile->iBusyTimeout ? SQLITE_BUSY_TIMEOUT : SQLITE_BUSY);
+#else
+ rc = SQLITE_BUSY;
+#endif
+ }
}
/* Update the global lock state and do debug tracing */
@@ -36439,7 +38489,7 @@ static int unixShmSystemLock(
}
#endif
- return rc;
+ return rc;
}
/*
@@ -36472,18 +38522,18 @@ static void unixShmPurge(unixFile *pFd){
int nShmPerMap = unixShmRegionPerMap();
int i;
assert( p->pInode==pFd->pInode );
- sqlite3_mutex_free(p->mutex);
+ sqlite3_mutex_free(p->pShmMutex);
for(i=0; inRegion; i+=nShmPerMap){
- if( p->h>=0 ){
+ if( p->hShm>=0 ){
osMunmap(p->apRegion[i], p->szRegion);
}else{
sqlite3_free(p->apRegion[i]);
}
}
sqlite3_free(p->apRegion);
- if( p->h>=0 ){
- robust_close(pFd, p->h, __LINE__);
- p->h = -1;
+ if( p->hShm>=0 ){
+ robust_close(pFd, p->hShm, __LINE__);
+ p->hShm = -1;
}
p->pInode->pShmNode = 0;
sqlite3_free(p);
@@ -36495,7 +38545,7 @@ static void unixShmPurge(unixFile *pFd){
** take it now. Return SQLITE_OK if successful, or an SQLite error
** code otherwise.
**
-** If the DMS cannot be locked because this is a readonly_shm=1
+** If the DMS cannot be locked because this is a readonly_shm=1
** connection and no other process already holds a lock, return
** SQLITE_READONLY_CANTINIT and set pShmNode->isUnlocked=1.
*/
@@ -36506,7 +38556,7 @@ static int unixLockSharedMemory(unixFile *pDbFd, unixShmNode *pShmNode){
/* Use F_GETLK to determine the locks other processes are holding
** on the DMS byte. If it indicates that another process is holding
** a SHARED lock, then this process may also take a SHARED lock
- ** and proceed with opening the *-shm file.
+ ** and proceed with opening the *-shm file.
**
** Or, if no other process is holding any lock, then this process
** is the first to open it. In this case take an EXCLUSIVE lock on the
@@ -36525,7 +38575,7 @@ static int unixLockSharedMemory(unixFile *pDbFd, unixShmNode *pShmNode){
lock.l_start = UNIX_SHM_DMS;
lock.l_len = 1;
lock.l_type = F_WRLCK;
- if( osFcntl(pShmNode->h, F_GETLK, &lock)!=0 ) {
+ if( osFcntl(pShmNode->hShm, F_GETLK, &lock)!=0 ) {
rc = SQLITE_IOERR_LOCK;
}else if( lock.l_type==F_UNLCK ){
if( pShmNode->isReadonly ){
@@ -36533,7 +38583,12 @@ static int unixLockSharedMemory(unixFile *pDbFd, unixShmNode *pShmNode){
rc = SQLITE_READONLY_CANTINIT;
}else{
rc = unixShmSystemLock(pDbFd, F_WRLCK, UNIX_SHM_DMS, 1);
- if( rc==SQLITE_OK && robust_ftruncate(pShmNode->h, 0) ){
+ /* The first connection to attach must truncate the -shm file. We
+ ** truncate to 3 bytes (an arbitrary small number, less than the
+ ** -shm header size) rather than 0 as a system debugging aid, to
+ ** help detect if a -shm file truncation is legitimate or is the work
+ ** or a rogue process. */
+ if( rc==SQLITE_OK && robust_ftruncate(pShmNode->hShm, 3) ){
rc = unixLogError(SQLITE_IOERR_SHMOPEN,"ftruncate",pShmNode->zFilename);
}
}
@@ -36549,20 +38604,20 @@ static int unixLockSharedMemory(unixFile *pDbFd, unixShmNode *pShmNode){
}
/*
-** Open a shared-memory area associated with open database file pDbFd.
+** Open a shared-memory area associated with open database file pDbFd.
** This particular implementation uses mmapped files.
**
** The file used to implement shared-memory is in the same directory
** as the open database file and has the same name as the open database
** file with the "-shm" suffix added. For example, if the database file
** is "/home/user1/config.db" then the file that is created and mmapped
-** for shared memory will be called "/home/user1/config.db-shm".
+** for shared memory will be called "/home/user1/config.db-shm".
**
** Another approach to is to use files in /dev/shm or /dev/tmp or an
** some other tmpfs mount. But if a file in a different directory
** from the database file is used, then differing access permissions
** or a chroot() might cause two different processes on the same
-** database to end up using different files for shared memory -
+** database to end up using different files for shared memory -
** meaning that their memory would not really be shared - resulting
** in database corruption. Nevertheless, this tmpfs file usage
** can be enabled at compile-time using -DSQLITE_SHM_DIRECTORY="/dev/shm"
@@ -36632,19 +38687,19 @@ static int unixOpenSharedMemory(unixFile *pDbFd){
memset(pShmNode, 0, sizeof(*pShmNode)+nShmFilename);
zShm = pShmNode->zFilename = (char*)&pShmNode[1];
#ifdef SQLITE_SHM_DIRECTORY
- sqlite3_snprintf(nShmFilename, zShm,
+ sqlite3_snprintf(nShmFilename, zShm,
SQLITE_SHM_DIRECTORY "/sqlite-shm-%x-%x",
(u32)sStat.st_ino, (u32)sStat.st_dev);
#else
sqlite3_snprintf(nShmFilename, zShm, "%s-shm", zBasePath);
sqlite3FileSuffix3(pDbFd->zPath, zShm);
#endif
- pShmNode->h = -1;
+ pShmNode->hShm = -1;
pDbFd->pInode->pShmNode = pShmNode;
pShmNode->pInode = pDbFd->pInode;
if( sqlite3GlobalConfig.bCoreMutex ){
- pShmNode->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
- if( pShmNode->mutex==0 ){
+ pShmNode->pShmMutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
+ if( pShmNode->pShmMutex==0 ){
rc = SQLITE_NOMEM_BKPT;
goto shm_open_err;
}
@@ -36652,11 +38707,13 @@ static int unixOpenSharedMemory(unixFile *pDbFd){
if( pInode->bProcessLock==0 ){
if( 0==sqlite3_uri_boolean(pDbFd->zPath, "readonly_shm", 0) ){
- pShmNode->h = robust_open(zShm, O_RDWR|O_CREAT, (sStat.st_mode&0777));
+ pShmNode->hShm = robust_open(zShm, O_RDWR|O_CREAT|O_NOFOLLOW,
+ (sStat.st_mode&0777));
}
- if( pShmNode->h<0 ){
- pShmNode->h = robust_open(zShm, O_RDONLY, (sStat.st_mode&0777));
- if( pShmNode->h<0 ){
+ if( pShmNode->hShm<0 ){
+ pShmNode->hShm = robust_open(zShm, O_RDONLY|O_NOFOLLOW,
+ (sStat.st_mode&0777));
+ if( pShmNode->hShm<0 ){
rc = unixLogError(SQLITE_CANTOPEN_BKPT, "open", zShm);
goto shm_open_err;
}
@@ -36667,7 +38724,7 @@ static int unixOpenSharedMemory(unixFile *pDbFd){
** is owned by the same user that owns the original database. Otherwise,
** the original owner will not be able to connect.
*/
- robustFchown(pShmNode->h, sStat.st_uid, sStat.st_gid);
+ robustFchown(pShmNode->hShm, sStat.st_uid, sStat.st_gid);
rc = unixLockSharedMemory(pDbFd, pShmNode);
if( rc!=SQLITE_OK && rc!=SQLITE_READONLY_CANTINIT ) goto shm_open_err;
@@ -36687,13 +38744,13 @@ static int unixOpenSharedMemory(unixFile *pDbFd){
** the cover of the unixEnterMutex() mutex and the pointer from the
** new (struct unixShm) object to the pShmNode has been set. All that is
** left to do is to link the new object into the linked list starting
- ** at pShmNode->pFirst. This must be done while holding the pShmNode->mutex
- ** mutex.
+ ** at pShmNode->pFirst. This must be done while holding the
+ ** pShmNode->pShmMutex.
*/
- sqlite3_mutex_enter(pShmNode->mutex);
+ sqlite3_mutex_enter(pShmNode->pShmMutex);
p->pNext = pShmNode->pFirst;
pShmNode->pFirst = p;
- sqlite3_mutex_leave(pShmNode->mutex);
+ sqlite3_mutex_leave(pShmNode->pShmMutex);
return rc;
/* Jump here on any error */
@@ -36705,22 +38762,22 @@ shm_open_err:
}
/*
-** This function is called to obtain a pointer to region iRegion of the
-** shared-memory associated with the database file fd. Shared-memory regions
-** are numbered starting from zero. Each shared-memory region is szRegion
+** This function is called to obtain a pointer to region iRegion of the
+** shared-memory associated with the database file fd. Shared-memory regions
+** are numbered starting from zero. Each shared-memory region is szRegion
** bytes in size.
**
** If an error occurs, an error code is returned and *pp is set to NULL.
**
** Otherwise, if the bExtend parameter is 0 and the requested shared-memory
** region has not been allocated (by any client, including one running in a
-** separate process), then *pp is set to NULL and SQLITE_OK returned. If
-** bExtend is non-zero and the requested shared-memory region has not yet
+** separate process), then *pp is set to NULL and SQLITE_OK returned. If
+** bExtend is non-zero and the requested shared-memory region has not yet
** been allocated, it is allocated by this function.
**
** If the shared-memory region has already been allocated or is allocated by
-** this call as described above, then it is mapped into this processes
-** address space (if it is not already), *pp is set to point to the mapped
+** this call as described above, then it is mapped into this processes
+** address space (if it is not already), *pp is set to point to the mapped
** memory and SQLITE_OK returned.
*/
static int unixShmMap(
@@ -36745,7 +38802,7 @@ static int unixShmMap(
p = pDbFd->pShm;
pShmNode = p->pShmNode;
- sqlite3_mutex_enter(pShmNode->mutex);
+ sqlite3_mutex_enter(pShmNode->pShmMutex);
if( pShmNode->isUnlocked ){
rc = unixLockSharedMemory(pDbFd, pShmNode);
if( rc!=SQLITE_OK ) goto shmpage_out;
@@ -36753,8 +38810,8 @@ static int unixShmMap(
}
assert( szRegion==pShmNode->szRegion || pShmNode->nRegion==0 );
assert( pShmNode->pInode==pDbFd->pInode );
- assert( pShmNode->h>=0 || pDbFd->pInode->bProcessLock==1 );
- assert( pShmNode->h<0 || pDbFd->pInode->bProcessLock==0 );
+ assert( pShmNode->hShm>=0 || pDbFd->pInode->bProcessLock==1 );
+ assert( pShmNode->hShm<0 || pDbFd->pInode->bProcessLock==0 );
/* Minimum number of regions required to be mapped. */
nReqRegion = ((iRegion+nShmPerMap) / nShmPerMap) * nShmPerMap;
@@ -36766,16 +38823,16 @@ static int unixShmMap(
pShmNode->szRegion = szRegion;
- if( pShmNode->h>=0 ){
+ if( pShmNode->hShm>=0 ){
/* The requested region is not mapped into this processes address space.
** Check to see if it has been allocated (i.e. if the wal-index file is
** large enough to contain the requested region).
*/
- if( osFstat(pShmNode->h, &sStat) ){
+ if( osFstat(pShmNode->hShm, &sStat) ){
rc = SQLITE_IOERR_SHMSIZE;
goto shmpage_out;
}
-
+
if( sStat.st_sizeh, iPg*pgsz + pgsz-1, "", 1, &x)!=1 ){
+ if( seekAndWriteFd(pShmNode->hShm, iPg*pgsz + pgsz-1,"",1,&x)!=1 ){
const char *zFile = pShmNode->zFilename;
rc = unixLogError(SQLITE_IOERR_SHMSIZE, "write", zFile);
goto shmpage_out;
@@ -36822,22 +38879,22 @@ static int unixShmMap(
int nMap = szRegion*nShmPerMap;
int i;
void *pMem;
- if( pShmNode->h>=0 ){
+ if( pShmNode->hShm>=0 ){
pMem = osMmap(0, nMap,
- pShmNode->isReadonly ? PROT_READ : PROT_READ|PROT_WRITE,
- MAP_SHARED, pShmNode->h, szRegion*(i64)pShmNode->nRegion
+ pShmNode->isReadonly ? PROT_READ : PROT_READ|PROT_WRITE,
+ MAP_SHARED, pShmNode->hShm, szRegion*(i64)pShmNode->nRegion
);
if( pMem==MAP_FAILED ){
rc = unixLogError(SQLITE_IOERR_SHMMAP, "mmap", pShmNode->zFilename);
goto shmpage_out;
}
}else{
- pMem = sqlite3_malloc64(szRegion);
+ pMem = sqlite3_malloc64(nMap);
if( pMem==0 ){
rc = SQLITE_NOMEM_BKPT;
goto shmpage_out;
}
- memset(pMem, 0, szRegion);
+ memset(pMem, 0, nMap);
}
for(i=0; iisReadonly && rc==SQLITE_OK ) rc = SQLITE_READONLY;
- sqlite3_mutex_leave(pShmNode->mutex);
+ sqlite3_mutex_leave(pShmNode->pShmMutex);
return rc;
}
+/*
+** Check that the pShmNode->aLock[] array comports with the locking bitmasks
+** held by each client. Return true if it does, or false otherwise. This
+** is to be used in an assert(). e.g.
+**
+** assert( assertLockingArrayOk(pShmNode) );
+*/
+#ifdef SQLITE_DEBUG
+static int assertLockingArrayOk(unixShmNode *pShmNode){
+ unixShm *pX;
+ int aLock[SQLITE_SHM_NLOCK];
+ assert( sqlite3_mutex_held(pShmNode->pShmMutex) );
+
+ memset(aLock, 0, sizeof(aLock));
+ for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
+ int i;
+ for(i=0; iexclMask & (1<sharedMask & (1<=0 );
+ aLock[i]++;
+ }
+ }
+ }
+
+ assert( 0==memcmp(pShmNode->aLock, aLock, sizeof(aLock)) );
+ return (memcmp(pShmNode->aLock, aLock, sizeof(aLock))==0);
+}
+#endif
+
/*
** Change the lock state for a shared-memory segment.
**
@@ -36874,10 +38963,10 @@ static int unixShmLock(
){
unixFile *pDbFd = (unixFile*)fd; /* Connection holding shared memory */
unixShm *p = pDbFd->pShm; /* The shared memory being locked */
- unixShm *pX; /* For looping over all siblings */
unixShmNode *pShmNode = p->pShmNode; /* The underlying file iNode */
int rc = SQLITE_OK; /* Result code */
u16 mask; /* Mask of locks to take or release */
+ int *aLock = pShmNode->aLock;
assert( pShmNode==pDbFd->pInode->pShmNode );
assert( pShmNode->pInode==pDbFd->pInode );
@@ -36888,92 +38977,112 @@ static int unixShmLock(
|| flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED)
|| flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE) );
assert( n==1 || (flags & SQLITE_SHM_EXCLUSIVE)!=0 );
- assert( pShmNode->h>=0 || pDbFd->pInode->bProcessLock==1 );
- assert( pShmNode->h<0 || pDbFd->pInode->bProcessLock==0 );
+ assert( pShmNode->hShm>=0 || pDbFd->pInode->bProcessLock==1 );
+ assert( pShmNode->hShm<0 || pDbFd->pInode->bProcessLock==0 );
+
+ /* Check that, if this to be a blocking lock, no locks that occur later
+ ** in the following list than the lock being obtained are already held:
+ **
+ ** 1. Checkpointer lock (ofst==1).
+ ** 2. Write lock (ofst==0).
+ ** 3. Read locks (ofst>=3 && ofstiBusyTimeout==0 || (
+ (ofst!=2) /* not RECOVER */
+ && (ofst!=1 || (p->exclMask|p->sharedMask)==0)
+ && (ofst!=0 || (p->exclMask|p->sharedMask)<3)
+ && (ofst<3 || (p->exclMask|p->sharedMask)<(1<1 || mask==(1<mutex);
+ sqlite3_mutex_enter(pShmNode->pShmMutex);
+ assert( assertLockingArrayOk(pShmNode) );
if( flags & SQLITE_SHM_UNLOCK ){
- u16 allMask = 0; /* Mask of locks held by siblings */
+ if( (p->exclMask|p->sharedMask) & mask ){
+ int ii;
+ int bUnlock = 1;
- /* See if any siblings hold this same lock */
- for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
- if( pX==p ) continue;
- assert( (pX->exclMask & (p->exclMask|p->sharedMask))==0 );
- allMask |= pX->sharedMask;
+ for(ii=ofst; ii((p->sharedMask & (1<sharedMask & (1<1 );
+ aLock[ofst]--;
+ }
+
+ /* Undo the local locks */
+ if( rc==SQLITE_OK ){
+ p->exclMask &= ~mask;
+ p->sharedMask &= ~mask;
+ }
}
-
- /* Unlock the system-level locks */
- if( (mask & allMask)==0 ){
- rc = unixShmSystemLock(pDbFd, F_UNLCK, ofst+UNIX_SHM_BASE, n);
- }else{
- rc = SQLITE_OK;
- }
-
- /* Undo the local locks */
- if( rc==SQLITE_OK ){
- p->exclMask &= ~mask;
- p->sharedMask &= ~mask;
- }
}else if( flags & SQLITE_SHM_SHARED ){
- u16 allShared = 0; /* Union of locks held by connections other than "p" */
-
- /* Find out which shared locks are already held by sibling connections.
- ** If any sibling already holds an exclusive lock, go ahead and return
- ** SQLITE_BUSY.
- */
- for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
- if( (pX->exclMask & mask)!=0 ){
+ assert( n==1 );
+ assert( (p->exclMask & (1<sharedMask & mask)==0 ){
+ if( aLock[ofst]<0 ){
rc = SQLITE_BUSY;
- break;
- }
- allShared |= pX->sharedMask;
- }
-
- /* Get shared locks at the system level, if necessary */
- if( rc==SQLITE_OK ){
- if( (allShared & mask)==0 ){
+ }else if( aLock[ofst]==0 ){
rc = unixShmSystemLock(pDbFd, F_RDLCK, ofst+UNIX_SHM_BASE, n);
- }else{
- rc = SQLITE_OK;
}
- }
- /* Get the local shared locks */
- if( rc==SQLITE_OK ){
- p->sharedMask |= mask;
+ /* Get the local shared locks */
+ if( rc==SQLITE_OK ){
+ p->sharedMask |= mask;
+ aLock[ofst]++;
+ }
}
}else{
/* Make sure no sibling connections hold locks that will block this
- ** lock. If any do, return SQLITE_BUSY right away.
- */
- for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
- if( (pX->exclMask & mask)!=0 || (pX->sharedMask & mask)!=0 ){
+ ** lock. If any do, return SQLITE_BUSY right away. */
+ int ii;
+ for(ii=ofst; iisharedMask & mask)==0 );
+ if( ALWAYS((p->exclMask & (1<sharedMask & mask)==0 );
p->exclMask |= mask;
+ for(ii=ofst; iimutex);
+ assert( assertLockingArrayOk(pShmNode) );
+ sqlite3_mutex_leave(pShmNode->pShmMutex);
OSTRACE(("SHM-LOCK shmid-%d, pid-%d got %03x,%03x\n",
p->id, osGetpid(0), p->sharedMask, p->exclMask));
return rc;
}
/*
-** Implement a memory barrier or memory fence on shared memory.
+** 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.
@@ -36983,15 +39092,15 @@ static void unixShmBarrier(
){
UNUSED_PARAMETER(fd);
sqlite3MemoryBarrier(); /* compiler-defined memory barrier */
- assert( fd->pMethods->xLock==nolockLock
- || unixFileMutexNotheld((unixFile*)fd)
+ assert( fd->pMethods->xLock==nolockLock
+ || unixFileMutexNotheld((unixFile*)fd)
);
unixEnterMutex(); /* Also mutex, for redundancy */
unixLeaveMutex();
}
/*
-** Close a connection to shared-memory. Delete the underlying
+** Close a connection to shared-memory. Delete the underlying
** storage if deleteFlag is true.
**
** If there is no shared memory associated with the connection then this
@@ -37016,14 +39125,14 @@ static int unixShmUnmap(
/* Remove connection p from the set of connections associated
** with pShmNode */
- sqlite3_mutex_enter(pShmNode->mutex);
+ sqlite3_mutex_enter(pShmNode->pShmMutex);
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);
+ sqlite3_mutex_leave(pShmNode->pShmMutex);
/* If pShmNode->nRef has reached 0, then close the underlying
** shared-memory file, too */
@@ -37032,7 +39141,7 @@ static int unixShmUnmap(
assert( pShmNode->nRef>0 );
pShmNode->nRef--;
if( pShmNode->nRef==0 ){
- if( deleteFlag && pShmNode->h>=0 ){
+ if( deleteFlag && pShmNode->hShm>=0 ){
osUnlink(pShmNode->zFilename);
}
unixShmPurge(pDbFd);
@@ -37065,7 +39174,7 @@ static void unixUnmapfile(unixFile *pFd){
}
/*
-** Attempt to set the size of the memory mapping maintained by file
+** Attempt to set the size of the memory mapping maintained by file
** descriptor pFd to nNew bytes. Any existing mapping is discarded.
**
** If successful, this function sets the following variables:
@@ -37157,14 +39266,14 @@ static void unixRemapfile(
/*
** Memory map or remap the file opened by file-descriptor pFd (if the file
-** is already mapped, the existing mapping is replaced by the new). Or, if
-** there already exists a mapping for this file, and there are still
+** is already mapped, the existing mapping is replaced by the new). Or, if
+** there already exists a mapping for this file, and there are still
** outstanding xFetch() references to it, this function is a no-op.
**
-** If parameter nByte is non-negative, then it is the requested size of
-** the mapping to create. Otherwise, if nByte is less than zero, then the
+** If parameter nByte is non-negative, then it is the requested size of
+** the mapping to create. Otherwise, if nByte is less than zero, then the
** requested size is the size of the file on disk. The actual size of the
-** created mapping is either the requested size or the value configured
+** created mapping is either the requested size or the value configured
** using SQLITE_FCNTL_MMAP_LIMIT, whichever is smaller.
**
** SQLITE_OK is returned if no error occurs (even if the mapping is not
@@ -37205,7 +39314,7 @@ static int unixMapfile(unixFile *pFd, i64 nMap){
** Finally, if an error does occur, return an SQLite error code. The final
** value of *pp is undefined in this case.
**
-** If this function does return a pointer, the caller must eventually
+** If this function does return a pointer, the caller must eventually
** release the reference by calling unixUnfetch().
*/
static int unixFetch(sqlite3_file *fd, i64 iOff, int nAmt, void **pp){
@@ -37230,13 +39339,13 @@ static int unixFetch(sqlite3_file *fd, i64 iOff, int nAmt, void **pp){
}
/*
-** If the third argument is non-NULL, then this function releases a
+** If the third argument is non-NULL, then this function releases a
** reference obtained by an earlier call to unixFetch(). The second
** argument passed to this function must be the same as the corresponding
-** argument that was passed to the unixFetch() invocation.
+** argument that was passed to the unixFetch() invocation.
**
-** Or, if the third argument is NULL, then this function is being called
-** to inform the VFS layer that, according to POSIX, any existing mapping
+** Or, if the third argument is NULL, then this function is being called
+** to inform the VFS layer that, according to POSIX, any existing mapping
** may now be invalid and should be unmapped.
*/
static int unixUnfetch(sqlite3_file *fd, i64 iOff, void *p){
@@ -37244,7 +39353,7 @@ static int unixUnfetch(sqlite3_file *fd, i64 iOff, void *p){
unixFile *pFd = (unixFile *)fd; /* The underlying database file */
UNUSED_PARAMETER(iOff);
- /* If p==0 (unmap the entire file) then there must be no outstanding
+ /* If p==0 (unmap the entire file) then there must be no outstanding
** xFetch references. Or, if p!=0 (meaning it is an xFetch reference),
** then there must be at least one outstanding. */
assert( (p==0)==(pFd->nFetchOut==0) );
@@ -37452,8 +39561,8 @@ IOMETHODS(
#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.
**
@@ -37495,8 +39604,8 @@ 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;
@@ -37512,7 +39621,7 @@ static const sqlite3_io_methods *autolockIoFinderImpl(
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 */
@@ -37548,7 +39657,7 @@ static const sqlite3_io_methods *vxworksIoFinderImpl(
return &semIoMethods;
}
}
-static const sqlite3_io_methods
+static const sqlite3_io_methods
*(*const vxworksIoFinder)(const char*,unixFile*) = vxworksIoFinderImpl;
#endif /* OS_VXWORKS */
@@ -37676,14 +39785,14 @@ static int fillInUnixFile(
robust_close(pNew, h, __LINE__);
h = -1;
}
- unixLeaveMutex();
+ 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;
@@ -37721,7 +39830,7 @@ static int fillInUnixFile(
unixLeaveMutex();
}
#endif
-
+
storeLastErrno(pNew, 0);
#if OS_VXWORKS
if( rc!=SQLITE_OK ){
@@ -37734,7 +39843,7 @@ static int fillInUnixFile(
if( rc!=SQLITE_OK ){
if( h>=0 ) robust_close(pNew, h, __LINE__);
}else{
- pNew->pMethod = pLockingStyle;
+ pId->pMethods = pLockingStyle;
OpenCounter(+1);
verifyDbFile(pNew);
}
@@ -37785,7 +39894,7 @@ static int unixGetTempname(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.
*/
zBuf[0] = 0;
SimulateIOError( return SQLITE_IOERR );
@@ -37814,8 +39923,8 @@ static int proxyTransformUnixFile(unixFile*, const char*);
#endif
/*
-** Search for an unused file descriptor that was opened on the database
-** file (not a journal or master-journal file) identified by pathname
+** Search for an unused file descriptor that was opened on the database
+** file (not a journal or super-journal file) identified by pathname
** zPath with SQLITE_OPEN_XXX flags matching those passed as the second
** argument to this function.
**
@@ -37823,7 +39932,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
@@ -37834,8 +39943,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 */
@@ -37862,6 +39971,7 @@ static UnixUnusedFd *findReusableFd(const char *zPath, int flags){
UnixUnusedFd **pp;
assert( sqlite3_mutex_notheld(pInode->pLockMutex) );
sqlite3_mutex_enter(pInode->pLockMutex);
+ flags &= (SQLITE_OPEN_READONLY|SQLITE_OPEN_READWRITE);
for(pp=&pInode->pUnused; *pp && (*pp)->flags!=flags; pp=&((*pp)->pNext));
pUnused = *pp;
if( pUnused ){
@@ -37876,7 +39986,7 @@ static UnixUnusedFd *findReusableFd(const char *zPath, int flags){
}
/*
-** Find the mode, uid and gid of file zFile.
+** Find the mode, uid and gid of file zFile.
*/
static int getFileMode(
const char *zFile, /* File name */
@@ -37900,22 +40010,22 @@ static int getFileMode(
** This function is called by unixOpen() to determine the unix permissions
** to create new files with. If no error occurs, then SQLITE_OK is returned
** and a value suitable for passing as the third argument to open(2) is
-** written to *pMode. If an IO error occurs, an SQLite error code is
+** written to *pMode. If an IO error occurs, an SQLite error code is
** returned and the value of *pMode is not modified.
**
** In most cases, this routine sets *pMode to 0, which will become
** an indication to robust_open() to create the file using
** SQLITE_DEFAULT_FILE_PERMISSIONS adjusted by the umask.
-** But if the file being opened is a WAL or regular journal file, then
-** this function queries the file-system for the permissions on the
-** corresponding database file and sets *pMode to this value. Whenever
-** possible, WAL and journal files are created using the same permissions
+** But if the file being opened is a WAL or regular journal file, then
+** this function queries the file-system for the permissions on the
+** corresponding database file and sets *pMode to this value. Whenever
+** possible, WAL and journal files are created using the same permissions
** as the associated database file.
**
** If the SQLITE_ENABLE_8_3_NAMES option is enabled, then the
** original filename is unavailable. But 8_3_NAMES is only used for
** FAT filesystems and permissions do not matter there, so just use
-** the default permissions.
+** the default permissions. In 8_3_NAMES mode, leave *pMode set to zero.
*/
static int findCreateFileMode(
const char *zPath, /* Path of file (possibly) being created */
@@ -37941,14 +40051,14 @@ static int findCreateFileMode(
** "-journalNN"
** "-walNN"
**
- ** where NN is a decimal number. The NN naming schemes are
+ ** where NN is a decimal number. The NN naming schemes are
** used by the test_multiplex.c module.
*/
- nDb = sqlite3Strlen30(zPath) - 1;
+ nDb = sqlite3Strlen30(zPath) - 1;
while( zPath[nDb]!='-' ){
/* In normal operation, the journal file name will always contain
** a '-' character. However in 8+3 filename mode, or if a corrupt
- ** rollback journal specifies a master journal with a goofy name, then
+ ** rollback journal specifies a super-journal with a goofy name, then
** the '-' might be missing. */
if( nDb==0 || zPath[nDb]=='.' ) return SQLITE_OK;
nDb--;
@@ -37974,7 +40084,7 @@ static int findCreateFileMode(
/*
** Open the file zPath.
-**
+**
** Previously, the SQLite OS layer used three functions in place of this
** one:
**
@@ -37985,13 +40095,13 @@ static int findCreateFileMode(
** 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(
@@ -38004,7 +40114,7 @@ static int unixOpen(
unixFile *p = (unixFile *)pFile;
int fd = -1; /* File descriptor returned by open() */
int openFlags = 0; /* Flags to pass to open() */
- int eType = flags&0xFFFFFF00; /* Type of file to open */
+ int eType = flags&0x0FFF00; /* Type of file to open */
int noLock; /* True to omit locking primitives */
int rc = SQLITE_OK; /* Function Return Code */
int ctrlFlags = 0; /* UNIXFILE_* flags */
@@ -38021,13 +40131,13 @@ static int unixOpen(
struct statfs fsInfo;
#endif
- /* If creating a master or main-file journal, this function will open
+ /* If creating a super- 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 isNewJrnl = (isCreate && (
- eType==SQLITE_OPEN_MASTER_JOURNAL
- || eType==SQLITE_OPEN_MAIN_JOURNAL
+ eType==SQLITE_OPEN_SUPER_JOURNAL
+ || eType==SQLITE_OPEN_MAIN_JOURNAL
|| eType==SQLITE_OPEN_WAL
));
@@ -38037,9 +40147,9 @@ static int unixOpen(
char zTmpname[MAX_PATHNAME+2];
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.
@@ -38049,17 +40159,17 @@ static int unixOpen(
assert(isExclusive==0 || isCreate);
assert(isDelete==0 || isCreate);
- /* The main DB, main journal, WAL file and master journal are never
+ /* The main DB, main journal, WAL file and super-journal are never
** automatically deleted. Nor are they ever temporary files. */
assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MAIN_DB );
assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MAIN_JOURNAL );
- assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MASTER_JOURNAL );
+ assert( (!isDelete && zName) || eType!=SQLITE_OPEN_SUPER_JOURNAL );
assert( (!isDelete && zName) || eType!=SQLITE_OPEN_WAL );
/* Assert that the upper layer has set one of the "file-type" flags. */
- assert( eType==SQLITE_OPEN_MAIN_DB || eType==SQLITE_OPEN_TEMP_DB
- || eType==SQLITE_OPEN_MAIN_JOURNAL || eType==SQLITE_OPEN_TEMP_JOURNAL
- || eType==SQLITE_OPEN_SUBJOURNAL || eType==SQLITE_OPEN_MASTER_JOURNAL
+ 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_SUPER_JOURNAL
|| eType==SQLITE_OPEN_TRANSIENT_DB || eType==SQLITE_OPEN_WAL
);
@@ -38108,13 +40218,13 @@ 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;
if( isCreate ) openFlags |= O_CREAT;
if( isExclusive ) openFlags |= (O_EXCL|O_NOFOLLOW);
- openFlags |= (O_LARGEFILE|O_BINARY);
+ openFlags |= (O_LARGEFILE|O_BINARY|O_NOFOLLOW);
if( fd<0 ){
mode_t openMode; /* Permissions to create file with */
@@ -38150,11 +40260,19 @@ static int unixOpen(
goto open_finished;
}
- /* If this process is running as root and if creating a new rollback
- ** journal or WAL file, set the ownership of the journal or WAL to be
- ** the same as the original database.
+ /* The owner of the rollback journal or WAL file should always be the
+ ** same as the owner of the database file. Try to ensure that this is
+ ** the case. The chown() system call will be a no-op if the current
+ ** process lacks root privileges, be we should at least try. Without
+ ** this step, if a root process opens a database file, it can leave
+ ** behinds a journal/WAL that is owned by root and hence make the
+ ** database inaccessible to unprivileged processes.
+ **
+ ** If openMode==0, then that means uid and gid are not set correctly
+ ** (probably because SQLite is configured to use 8+3 filename mode) and
+ ** in that case we do not want to attempt the chown().
*/
- if( flags & (SQLITE_OPEN_WAL|SQLITE_OPEN_MAIN_JOURNAL) ){
+ if( openMode && (flags & (SQLITE_OPEN_WAL|SQLITE_OPEN_MAIN_JOURNAL))!=0 ){
robustFchown(fd, uid, gid);
}
}
@@ -38165,7 +40283,8 @@ static int unixOpen(
if( p->pPreallocatedUnused ){
p->pPreallocatedUnused->fd = fd;
- p->pPreallocatedUnused->flags = flags;
+ p->pPreallocatedUnused->flags =
+ flags & (SQLITE_OPEN_READONLY|SQLITE_OPEN_READWRITE);
}
if( isDelete ){
@@ -38186,7 +40305,7 @@ static int unixOpen(
p->openFlags = openFlags;
}
#endif
-
+
#if defined(__APPLE__) || SQLITE_ENABLE_LOCKING_STYLE
if( fstatfs(fd, &fsInfo) == -1 ){
storeLastErrno(p, errno);
@@ -38217,7 +40336,7 @@ static int unixOpen(
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;
@@ -38229,9 +40348,9 @@ static int unixOpen(
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
+ /* 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;
@@ -38241,9 +40360,9 @@ static int unixOpen(
}
}
#endif
-
- assert( zPath==0 || zPath[0]=='/'
- || eType==SQLITE_OPEN_MASTER_JOURNAL || eType==SQLITE_OPEN_MAIN_JOURNAL
+
+ assert( zPath==0 || zPath[0]=='/'
+ || eType==SQLITE_OPEN_SUPER_JOURNAL || eType==SQLITE_OPEN_MAIN_JOURNAL
);
rc = fillInUnixFile(pVfs, fd, pFile, zPath, ctrlFlags);
@@ -38323,7 +40442,8 @@ static int unixAccess(
if( flags==SQLITE_ACCESS_EXISTS ){
struct stat buf;
- *pResOut = (0==osStat(zPath, &buf) && buf.st_size>0);
+ *pResOut = 0==osStat(zPath, &buf) &&
+ (!S_ISREG(buf.st_mode) || buf.st_size>0);
}else{
*pResOut = osAccess(zPath, W_OK|R_OK)==0;
}
@@ -38331,7 +40451,27 @@ static int unixAccess(
}
/*
+** If the last component of the pathname in z[0]..z[j-1] is something
+** other than ".." then back it out and return true. If the last
+** component is empty or if it is ".." then return false.
+*/
+static int unixBackupDir(const char *z, int *pJ){
+ int j = *pJ;
+ int i;
+ if( j<=0 ) return 0;
+ for(i=j-1; i>0 && z[i-1]!='/'; i--){}
+ if( i==0 ) return 0;
+ if( z[i]=='.' && i==j-2 && z[i+1]=='.' ) return 0;
+ *pJ = i-1;
+ return 1;
+}
+
+/*
+** Convert a relative pathname into a full pathname. Also
+** simplify the pathname as follows:
**
+** Remove all instances of /./
+** Remove all isntances of /X/../ for any X
*/
static int mkFullPathname(
const char *zPath, /* Input path */
@@ -38340,6 +40480,7 @@ static int mkFullPathname(
){
int nPath = sqlite3Strlen30(zPath);
int iOff = 0;
+ int i, j;
if( zPath[0]!='/' ){
if( osGetcwd(zOut, nOut-2)==0 ){
return unixLogError(SQLITE_CANTOPEN_BKPT, "getcwd", zPath);
@@ -38354,15 +40495,50 @@ static int mkFullPathname(
return SQLITE_CANTOPEN_BKPT;
}
sqlite3_snprintf(nOut-iOff, &zOut[iOff], "%s", zPath);
+
+ /* Remove duplicate '/' characters. Except, two // at the beginning
+ ** of a pathname is allowed since this is important on windows. */
+ for(i=j=1; zOut[i]; i++){
+ zOut[j++] = zOut[i];
+ while( zOut[i]=='/' && zOut[i+1]=='/' ) i++;
+ }
+ zOut[j] = 0;
+
+ assert( zOut[0]=='/' );
+ for(i=j=0; zOut[i]; i++){
+ if( zOut[i]=='/' ){
+ /* Skip over internal "/." directory components */
+ if( zOut[i+1]=='.' && zOut[i+2]=='/' ){
+ i += 1;
+ continue;
+ }
+
+ /* If this is a "/.." directory component then back out the
+ ** previous term of the directory if it is something other than "..".
+ */
+ if( zOut[i+1]=='.'
+ && zOut[i+2]=='.'
+ && zOut[i+3]=='/'
+ && unixBackupDir(zOut, &j)
+ ){
+ i += 2;
+ continue;
+ }
+ }
+ if( ALWAYS(j>=0) ) zOut[j] = zOut[i];
+ j++;
+ }
+ if( NEVER(j==0) ) zOut[j++] = '/';
+ zOut[j] = 0;
return SQLITE_OK;
}
/*
** 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.
*/
@@ -38377,7 +40553,7 @@ static int unixFullPathname(
#else
int rc = SQLITE_OK;
int nByte;
- int nLink = 1; /* Number of symbolic links followed so far */
+ int nLink = 0; /* Number of symbolic links followed so far */
const char *zIn = zPath; /* Input path for each iteration of loop */
char *zDel = 0;
@@ -38406,10 +40582,11 @@ static int unixFullPathname(
}
if( bLink ){
+ nLink++;
if( zDel==0 ){
zDel = sqlite3_malloc(nOut);
if( zDel==0 ) rc = SQLITE_NOMEM_BKPT;
- }else if( ++nLink>SQLITE_MAX_SYMLINKS ){
+ }else if( nLink>=SQLITE_MAX_SYMLINKS ){
rc = SQLITE_CANTOPEN_BKPT;
}
@@ -38445,6 +40622,7 @@ static int unixFullPathname(
}while( rc==SQLITE_OK );
sqlite3_free(zDel);
+ if( rc==SQLITE_OK && nLink ) rc = SQLITE_OK_SYMLINK;
return rc;
#endif /* HAVE_READLINK && HAVE_LSTAT */
}
@@ -38479,7 +40657,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
@@ -38489,7 +40667,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
@@ -38532,7 +40710,7 @@ static int unixRandomness(sqlite3_vfs *NotUsed, int nBuf, char *zBuf){
** tests repeatable.
*/
memset(zBuf, 0, nBuf);
- randomnessPid = osGetpid(0);
+ randomnessPid = osGetpid(0);
#if !defined(SQLITE_TEST) && !defined(SQLITE_OMIT_RANDOMNESS)
{
int fd, got;
@@ -38572,7 +40750,8 @@ static int unixSleep(sqlite3_vfs *NotUsed, int microseconds){
UNUSED_PARAMETER(NotUsed);
return microseconds;
#elif defined(HAVE_USLEEP) && HAVE_USLEEP
- usleep(microseconds);
+ if( microseconds>=1000000 ) sleep(microseconds/1000000);
+ if( microseconds%1000000 ) usleep(microseconds%1000000);
UNUSED_PARAMETER(NotUsed);
return microseconds;
#else
@@ -38599,7 +40778,7 @@ SQLITE_API int sqlite3_current_time = 0; /* Fake system time in seconds since 1
** epoch of noon in Greenwich on November 24, 4714 B.C according to the
** proleptic Gregorian calendar.
**
-** On success, return SQLITE_OK. Return SQLITE_ERROR if the time and date
+** On success, return SQLITE_OK. Return SQLITE_ERROR if the time and date
** cannot be found.
*/
static int unixCurrentTimeInt64(sqlite3_vfs *NotUsed, sqlite3_int64 *piNow){
@@ -38706,7 +40885,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
@@ -38732,19 +40911,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 "/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
@@ -38771,11 +40950,11 @@ static int unixGetLastError(sqlite3_vfs *NotUsed, int NotUsed2, char *NotUsed3){
** host (the conch ensures that they all use the same local lock file).
**
** Requesting the lock proxy does not immediately take the conch, it is
-** only taken when the first request to lock database file is made.
+** 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.
@@ -38789,7 +40968,7 @@ 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
@@ -38804,8 +40983,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
@@ -38815,12 +40994,12 @@ 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
/*
-** 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;
@@ -38836,10 +41015,10 @@ struct proxyLockingContext {
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,
+/*
+** 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.
+** file path.
*/
static int proxyGetLockPath(const char *dbPath, char *lPath, size_t maxLen){
int len;
@@ -38856,7 +41035,7 @@ static int proxyGetLockPath(const char *dbPath, char *lPath, size_t maxLen){
lPath, errno, osGetpid(0)));
return SQLITE_IOERR_LOCK;
}
- len = strlcat(lPath, "sqliteplocks", maxLen);
+ len = strlcat(lPath, "sqliteplocks", maxLen);
}
# else
len = strlcpy(lPath, "/tmp/", maxLen);
@@ -38866,7 +41045,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 0) ){
/* only mkdir if leaf dir != "." or "/" or ".." */
- if( i-start>2 || (i-start==1 && buf[start] != '.' && buf[start] != '/')
+ if( i-start>2 || (i-start==1 && buf[start] != '.' && buf[start] != '/')
|| (i-start==2 && buf[start] != '.' && buf[start+1] != '.') ){
buf[i]='\0';
if( osMkdir(buf, SQLITE_DEFAULT_PROXYDIR_PERMISSIONS) ){
@@ -38930,7 +41109,7 @@ static int proxyCreateUnixFile(
int fd = -1;
unixFile *pNew;
int rc = SQLITE_OK;
- int openFlags = O_RDWR | O_CREAT;
+ int openFlags = O_RDWR | O_CREAT | O_NOFOLLOW;
sqlite3_vfs dummyVfs;
int terrno = 0;
UnixUnusedFd *pUnused = NULL;
@@ -38960,7 +41139,7 @@ static int proxyCreateUnixFile(
}
}
if( fd<0 ){
- openFlags = O_RDONLY;
+ openFlags = O_RDONLY | O_NOFOLLOW;
fd = robust_open(path, openFlags, 0);
terrno = errno;
}
@@ -38971,13 +41150,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_malloc64(sizeof(*pNew));
if( pNew==NULL ){
rc = SQLITE_NOMEM_BKPT;
@@ -38991,13 +41170,13 @@ static int proxyCreateUnixFile(
pUnused->fd = fd;
pUnused->flags = openFlags;
pNew->pPreallocatedUnused = pUnused;
-
+
rc = fillInUnixFile(&dummyVfs, fd, (sqlite3_file*)pNew, path, 0);
if( rc==SQLITE_OK ){
*ppFile = pNew;
return SQLITE_OK;
}
-end_create_proxy:
+end_create_proxy:
robust_close(pNew, fd, __LINE__);
sqlite3_free(pNew);
sqlite3_free(pUnused);
@@ -39011,18 +41190,18 @@ SQLITE_API int sqlite3_hostid_num = 0;
#define PROXY_HOSTIDLEN 16 /* conch file host id length */
-#ifdef HAVE_GETHOSTUUID
+#if HAVE_GETHOSTUUID
/* Not always defined in the headers as it ought to be */
extern int gethostuuid(uuid_t id, const struct timespec *wait);
#endif
-/* get the host ID via gethostuuid(), pHostID must point to PROXY_HOSTIDLEN
+/* get the host ID via gethostuuid(), pHostID must point to PROXY_HOSTIDLEN
** bytes of writable memory.
*/
static int proxyGetHostID(unsigned char *pHostID, int *pError){
assert(PROXY_HOSTIDLEN == sizeof(uuid_t));
memset(pHostID, 0, PROXY_HOSTIDLEN);
-#ifdef HAVE_GETHOSTUUID
+#if HAVE_GETHOSTUUID
{
struct timespec timeout = {1, 0}; /* 1 sec timeout */
if( gethostuuid(pHostID, &timeout) ){
@@ -39042,7 +41221,7 @@ static int proxyGetHostID(unsigned char *pHostID, int *pError){
pHostID[0] = (char)(pHostID[0] + (char)(sqlite3_hostid_num & 0xFF));
}
#endif
-
+
return SQLITE_OK;
}
@@ -39053,14 +41232,14 @@ static int proxyGetHostID(unsigned char *pHostID, int *pError){
#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
+/*
+** 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
+** 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;
+ proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext;
unixFile *conchFile = pCtx->conchFile;
char tPath[MAXPATHLEN];
char buf[PROXY_MAXCONCHLEN];
@@ -39074,7 +41253,7 @@ static int proxyBreakConchLock(unixFile *pFile, uuid_t myHostID){
/* create a new path by replace the trailing '-conch' with '-break' */
pathLen = strlcpy(tPath, cPath, MAXPATHLEN);
- if( pathLen>MAXPATHLEN || pathLen<6 ||
+ if( pathLen>MAXPATHLEN || pathLen<6 ||
(strlcpy(&tPath[pathLen-5], "break", 6) != 5) ){
sqlite3_snprintf(sizeof(errmsg),errmsg,"path error (len %d)",(int)pathLen);
goto end_breaklock;
@@ -39086,7 +41265,7 @@ static int proxyBreakConchLock(unixFile *pFile, uuid_t myHostID){
goto end_breaklock;
}
/* write it out to the temporary break file */
- fd = robust_open(tPath, (O_RDWR|O_CREAT|O_EXCL), 0);
+ fd = robust_open(tPath, (O_RDWR|O_CREAT|O_EXCL|O_NOFOLLOW), 0);
if( fd<0 ){
sqlite3_snprintf(sizeof(errmsg), errmsg, "create failed (%d)", errno);
goto end_breaklock;
@@ -39116,24 +41295,24 @@ end_breaklock:
return rc;
}
-/* Take the requested lock on the conch file and break a stale lock if the
+/* 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;
+ proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext;
unixFile *conchFile = pCtx->conchFile;
int rc = SQLITE_OK;
int nTries = 0;
struct timespec conchModTime;
-
+
memset(&conchModTime, 0, sizeof(conchModTime));
do {
rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, lockType);
nTries ++;
if( rc==SQLITE_BUSY ){
/* If the lock failed (busy):
- * 1st try: get the mod time of the conch, wait 0.5s and try again.
- * 2nd try: fail if the mod time changed or host id is different, wait
+ * 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.
*/
@@ -39142,20 +41321,20 @@ static int proxyConchLock(unixFile *pFile, uuid_t myHostID, int lockType){
storeLastErrno(pFile, errno);
return SQLITE_IOERR_LOCK;
}
-
+
if( nTries==1 ){
conchModTime = buf.st_mtimespec;
- usleep(500000); /* wait 0.5 sec and try the lock again*/
- continue;
+ unixSleep(0,500000); /* wait 0.5 sec and try the lock again*/
+ continue;
}
assert( nTries>1 );
- if( conchModTime.tv_sec != buf.st_mtimespec.tv_sec ||
+ if( conchModTime.tv_sec != buf.st_mtimespec.tv_sec ||
conchModTime.tv_nsec != buf.st_mtimespec.tv_nsec ){
return SQLITE_BUSY;
}
-
- if( nTries==2 ){
+
+ if( nTries==2 ){
char tBuf[PROXY_MAXCONCHLEN];
int len = osPread(conchFile->h, tBuf, PROXY_MAXCONCHLEN, 0);
if( len<0 ){
@@ -39171,10 +41350,10 @@ static int proxyConchLock(unixFile *pFile, uuid_t myHostID, int lockType){
/* 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;
+ unixSleep(0,10000000); /* wait 10 sec and try the lock again */
+ continue;
}
-
+
assert( nTries==3 );
if( 0==proxyBreakConchLock(pFile, myHostID) ){
rc = SQLITE_OK;
@@ -39187,19 +41366,19 @@ static int proxyConchLock(unixFile *pFile, uuid_t myHostID, int lockType){
}
}
} while( rc==SQLITE_BUSY && nTries<3 );
-
+
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;
-
+ proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext;
+
if( pCtx->conchHeld!=0 ){
return SQLITE_OK;
}else{
@@ -39215,7 +41394,7 @@ static int proxyTakeConch(unixFile *pFile){
int readLen = 0;
int tryOldLockPath = 0;
int forceNewLockPath = 0;
-
+
OSTRACE(("TAKECONCH %d for %s pid=%d\n", conchFile->h,
(pCtx->lockProxyPath ? pCtx->lockProxyPath : ":auto:"),
osGetpid(0)));
@@ -39236,21 +41415,21 @@ static int proxyTakeConch(unixFile *pFile){
storeLastErrno(pFile, conchFile->lastErrno);
rc = SQLITE_IOERR_READ;
goto end_takeconch;
- }else if( readLen<=(PROXY_HEADERLEN+PROXY_HOSTIDLEN) ||
+ }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.
+ /* a short read or version format mismatch means we need to create a new
+ ** conch file.
*/
createConch = 1;
}
/* if the host id matches and the lock path already exists in the conch
- ** we'll try to use the path there, if we can't open that path, we'll
- ** retry with a new auto-generated path
+ ** 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,
+ hostIdMatch = !memcmp(&readBuf[PROXY_HEADERLEN], myHostID,
PROXY_HOSTIDLEN);
/* if the conch has data compare the contents */
if( !pCtx->lockProxyPath ){
@@ -39259,7 +41438,7 @@ static int proxyTakeConch(unixFile *pFile){
*/
if( hostIdMatch ){
size_t pathLen = (readLen - PROXY_PATHINDEX);
-
+
if( pathLen>=MAXPATHLEN ){
pathLen=MAXPATHLEN-1;
}
@@ -39275,23 +41454,23 @@ static int proxyTakeConch(unixFile *pFile){
readLen-PROXY_PATHINDEX)
){
/* conch host and lock path match */
- goto end_takeconch;
+ goto end_takeconch;
}
}
-
+
/* if the conch isn't writable and doesn't match, we can't take it */
if( (conchFile->openFlags&O_RDWR) == 0 ){
rc = SQLITE_BUSY;
goto end_takeconch;
}
-
+
/* either the conch didn't match or we need to create a new one */
if( !pCtx->lockProxyPath ){
proxyGetLockPath(pCtx->dbPath, lockPath, MAXPATHLEN);
tempLockPath = lockPath;
/* create a copy of the lock path _only_ if the conch is taken */
}
-
+
/* update conch with host and path (this will fail if other process
** has a shared lock already), if the host id matches, use the big
** stick.
@@ -39302,7 +41481,7 @@ static int proxyTakeConch(unixFile *pFile){
/* 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{
@@ -39311,7 +41490,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 ){
@@ -39324,8 +41503,8 @@ static int proxyTakeConch(unixFile *pFile){
robust_ftruncate(conchFile->h, writeSize);
rc = unixWrite((sqlite3_file *)conchFile, writeBuffer, writeSize, 0);
full_fsync(conchFile->h,0,0);
- /* 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;
@@ -39349,14 +41528,14 @@ 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));
if( rc==SQLITE_OK && pFile->openFlags ){
@@ -39379,7 +41558,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;
@@ -39399,7 +41578,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;
@@ -39411,7 +41590,7 @@ static int proxyTakeConch(unixFile *pFile){
OSTRACE(("TAKECONCH %d %s\n", conchFile->h,
rc==SQLITE_OK?"ok":"failed"));
return rc;
- } while (1); /* in case we need to retry the :auto: lock file -
+ } while (1); /* in case we need to retry the :auto: lock file -
** we should never get here except via the 'continue' call. */
}
}
@@ -39427,7 +41606,7 @@ static int proxyReleaseConch(unixFile *pFile){
pCtx = (proxyLockingContext *)pFile->lockingContext;
conchFile = pCtx->conchFile;
OSTRACE(("RELEASECONCH %d for %s pid=%d\n", conchFile->h,
- (pCtx->lockProxyPath ? pCtx->lockProxyPath : ":auto:"),
+ (pCtx->lockProxyPath ? pCtx->lockProxyPath : ":auto:"),
osGetpid(0)));
if( pCtx->conchHeld>0 ){
rc = conchFile->pMethod->xUnlock((sqlite3_file*)conchFile, NO_LOCK);
@@ -39455,13 +41634,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_malloc64(len + 8);
if( conchPath==0 ){
return SQLITE_NOMEM_BKPT;
}
memcpy(conchPath, dbPath, len+1);
-
+
/* now insert a "." before the last / character */
for( i=(len-1); i>=0; i-- ){
if( conchPath[i]=='/' ){
@@ -39484,7 +41663,7 @@ 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;
@@ -39493,7 +41672,7 @@ static int switchLockProxyPath(unixFile *pFile, const char *path) {
if( pFile->eFileLock!=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:") ||
@@ -39511,7 +41690,7 @@ static int switchLockProxyPath(unixFile *pFile, const char *path) {
sqlite3_free(oldPath);
pCtx->lockProxyPath = sqlite3DbStrDup(0, path);
}
-
+
return rc;
}
@@ -39525,7 +41704,7 @@ 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,
@@ -39546,9 +41725,9 @@ static int proxyGetDbPathForUnixFile(unixFile *pFile, char *dbPath){
}
/*
-** 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
@@ -39558,7 +41737,7 @@ 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 ){
return SQLITE_BUSY;
}
@@ -39568,7 +41747,7 @@ 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:"), osGetpid(0)));
@@ -39602,7 +41781,7 @@ static int proxyTransformUnixFile(unixFile *pFile, const char *path) {
rc = SQLITE_OK;
}
}
- }
+ }
if( rc==SQLITE_OK && lockPath ){
pCtx->lockProxyPath = sqlite3DbStrDup(0, lockPath);
}
@@ -39614,7 +41793,7 @@ static int proxyTransformUnixFile(unixFile *pFile, const char *path) {
}
}
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->oldLockingContext = pFile->lockingContext;
@@ -39622,12 +41801,12 @@ static int proxyTransformUnixFile(unixFile *pFile, const char *path) {
pCtx->pOldMethod = pFile->pMethod;
pFile->pMethod = &proxyIoMethods;
}else{
- if( pCtx->conchFile ){
+ if( pCtx->conchFile ){
pCtx->conchFile->pMethod->xClose((sqlite3_file *)pCtx->conchFile);
sqlite3_free(pCtx->conchFile);
}
sqlite3DbFree(0, pCtx->lockProxyPath);
- sqlite3_free(pCtx->conchFilePath);
+ sqlite3_free(pCtx->conchFilePath);
sqlite3_free(pCtx);
}
OSTRACE(("TRANSPROXY %d %s\n", pFile->h,
@@ -39665,7 +41844,7 @@ static int proxyFileControl(sqlite3_file *id, int op, void *pArg){
if( isProxyStyle ){
/* turn off proxy locking - not supported. If support is added for
** switching proxy locking mode off then it will need to fail if
- ** the journal mode is WAL mode.
+ ** the journal mode is WAL mode.
*/
rc = SQLITE_ERROR /*SQLITE_PROTOCOL? SQLITE_MISUSE?*/;
}else{
@@ -39675,9 +41854,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))
){
@@ -39696,7 +41875,7 @@ static int proxyFileControl(sqlite3_file *id, int op, void *pArg){
assert( 0 ); /* The call assures that only valid opcodes are sent */
}
}
- /*NOTREACHED*/
+ /*NOTREACHED*/ assert(0);
return SQLITE_ERROR;
}
@@ -39802,7 +41981,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;
@@ -39839,7 +42018,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 **********************
******************************************************************************/
@@ -39857,8 +42036,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
@@ -39874,7 +42053,7 @@ 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.
*/
@@ -39947,7 +42126,26 @@ SQLITE_API int sqlite3_os_init(void){
sqlite3_vfs_register(&aVfs[i], i==0);
}
unixBigLock = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1);
- return SQLITE_OK;
+
+#ifndef SQLITE_OMIT_WAL
+ /* Validate lock assumptions */
+ assert( SQLITE_SHM_NLOCK==8 ); /* Number of available locks */
+ assert( UNIX_SHM_BASE==120 ); /* Start of locking area */
+ /* Locks:
+ ** WRITE UNIX_SHM_BASE 120
+ ** CKPT UNIX_SHM_BASE+1 121
+ ** RECOVER UNIX_SHM_BASE+2 122
+ ** READ-0 UNIX_SHM_BASE+3 123
+ ** READ-1 UNIX_SHM_BASE+4 124
+ ** READ-2 UNIX_SHM_BASE+5 125
+ ** READ-3 UNIX_SHM_BASE+6 126
+ ** READ-4 UNIX_SHM_BASE+7 127
+ ** DMS UNIX_SHM_BASE+8 128
+ */
+ assert( UNIX_SHM_DMS==128 ); /* Byte offset of the deadman-switch */
+#endif
+
+ return SQLITE_OK;
}
/*
@@ -39957,11 +42155,11 @@ 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){
+SQLITE_API int sqlite3_os_end(void){
unixBigLock = 0;
- return SQLITE_OK;
+ return SQLITE_OK;
}
-
+
#endif /* SQLITE_OS_UNIX */
/************** End of os_unix.c *********************************************/
@@ -40044,7 +42242,7 @@ SQLITE_API int sqlite3_os_end(void){
******************************************************************************
**
** This file contains inline asm code for retrieving "high-performance"
-** counters for x86 class CPUs.
+** counters for x86 and x86_64 class CPUs.
*/
#ifndef SQLITE_HWTIME_H
#define SQLITE_HWTIME_H
@@ -40055,8 +42253,9 @@ SQLITE_API int sqlite3_os_end(void){
** processor and returns that value. This can be used for high-res
** profiling.
*/
-#if (defined(__GNUC__) || defined(_MSC_VER)) && \
- (defined(i386) || defined(__i386__) || defined(_M_IX86))
+#if !defined(__STRICT_ANSI__) && \
+ (defined(__GNUC__) || defined(_MSC_VER)) && \
+ (defined(i386) || defined(__i386__) || defined(_M_IX86))
#if defined(__GNUC__)
@@ -40077,15 +42276,15 @@ SQLITE_API int sqlite3_os_end(void){
#endif
-#elif (defined(__GNUC__) && defined(__x86_64__))
+#elif !defined(__STRICT_ANSI__) && (defined(__GNUC__) && defined(__x86_64__))
__inline__ sqlite_uint64 sqlite3Hwtime(void){
unsigned long val;
__asm__ __volatile__ ("rdtsc" : "=A" (val));
return val;
}
-
-#elif (defined(__GNUC__) && defined(__ppc__))
+
+#elif !defined(__STRICT_ANSI__) && (defined(__GNUC__) && defined(__ppc__))
__inline__ sqlite_uint64 sqlite3Hwtime(void){
unsigned long long retval;
@@ -40102,14 +42301,13 @@ SQLITE_API int sqlite3_os_end(void){
#else
- #error Need implementation of sqlite3Hwtime() for your platform.
-
/*
- ** To compile without implementing sqlite3Hwtime() for your platform,
- ** you can remove the above #error and use the following
- ** stub function. You will lose timing support for many
- ** of the debugging and testing utilities, but it should at
- ** least compile and run.
+ ** asm() is needed for hardware timing support. Without asm(),
+ ** disable the sqlite3Hwtime() routine.
+ **
+ ** sqlite3Hwtime() is only used for some obscure debugging
+ ** and analysis configurations, not in any deliverable, so this
+ ** should not be a great loss.
*/
SQLITE_PRIVATE sqlite_uint64 sqlite3Hwtime(void){ return ((sqlite_uint64)0); }
@@ -40450,8 +42648,7 @@ struct winFile {
int nFetchOut; /* Number of outstanding xFetch references */
HANDLE hMap; /* Handle for accessing memory mapping */
void *pMapRegion; /* Area memory mapped */
- sqlite3_int64 mmapSize; /* Usable size of mapped region */
- sqlite3_int64 mmapSizeActual; /* Actual size of mapped region */
+ sqlite3_int64 mmapSize; /* Size of mapped region */
sqlite3_int64 mmapSizeMax; /* Configured FCNTL_MMAP_SIZE value */
#endif
};
@@ -41457,17 +43654,17 @@ SQLITE_API int sqlite3_win32_compact_heap(LPUINT pnLargest){
*/
SQLITE_API int sqlite3_win32_reset_heap(){
int rc;
- MUTEX_LOGIC( sqlite3_mutex *pMaster; ) /* The main static mutex */
+ MUTEX_LOGIC( sqlite3_mutex *pMainMtx; ) /* The main static mutex */
MUTEX_LOGIC( sqlite3_mutex *pMem; ) /* The memsys static mutex */
- MUTEX_LOGIC( pMaster = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); )
+ MUTEX_LOGIC( pMainMtx = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN); )
MUTEX_LOGIC( pMem = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM); )
- sqlite3_mutex_enter(pMaster);
+ sqlite3_mutex_enter(pMainMtx);
sqlite3_mutex_enter(pMem);
winMemAssertMagic();
if( winMemGetHeap()!=NULL && winMemGetOwned() && sqlite3_memory_used()==0 ){
/*
** At this point, there should be no outstanding memory allocations on
- ** the heap. Also, since both the master and memsys locks are currently
+ ** the heap. Also, since both the main and memsys locks are currently
** being held by us, no other function (i.e. from another thread) should
** be able to even access the heap. Attempt to destroy and recreate our
** isolated Win32 native heap now.
@@ -41490,7 +43687,7 @@ SQLITE_API int sqlite3_win32_reset_heap(){
rc = SQLITE_BUSY;
}
sqlite3_mutex_leave(pMem);
- sqlite3_mutex_leave(pMaster);
+ sqlite3_mutex_leave(pMainMtx);
return rc;
}
#endif /* SQLITE_WIN32_MALLOC */
@@ -43072,6 +45269,26 @@ static int winTruncate(sqlite3_file *id, sqlite3_int64 nByte){
DWORD lastErrno;
#if SQLITE_MAX_MMAP_SIZE>0
sqlite3_int64 oldMmapSize;
+ if( pFile->nFetchOut>0 ){
+ /* File truncation is a no-op if there are outstanding memory mapped
+ ** pages. This is because truncating the file means temporarily unmapping
+ ** the file, and that might delete memory out from under existing cursors.
+ **
+ ** This can result in incremental vacuum not truncating the file,
+ ** if there is an active read cursor when the incremental vacuum occurs.
+ ** No real harm comes of this - the database file is not corrupted,
+ ** though some folks might complain that the file is bigger than it
+ ** needs to be.
+ **
+ ** The only feasible work-around is to defer the truncation until after
+ ** all references to memory-mapped content are closed. That is doable,
+ ** but involves adding a few branches in the common write code path which
+ ** could slow down normal operations slightly. Hence, we have decided for
+ ** now to simply make trancations a no-op if there are pending reads. We
+ ** can maybe revisit this decision in the future.
+ */
+ return SQLITE_OK;
+ }
#endif
assert( pFile );
@@ -43649,6 +45866,7 @@ static void winModeBit(winFile *pFile, unsigned char mask, int *pArg){
/* Forward references to VFS helper methods used for temporary files */
static int winGetTempname(sqlite3_vfs *, char **);
static int winIsDir(const void *);
+static BOOL winIsLongPathPrefix(const char *);
static BOOL winIsDriveLetterAndColon(const char *);
/*
@@ -44362,6 +46580,7 @@ static int winShmMap(
rc = winOpenSharedMemory(pDbFd);
if( rc!=SQLITE_OK ) return rc;
pShm = pDbFd->pShm;
+ assert( pShm!=0 );
}
pShmNode = pShm->pShmNode;
@@ -44500,9 +46719,9 @@ shmpage_out:
static int winUnmapfile(winFile *pFile){
assert( pFile!=0 );
OSTRACE(("UNMAP-FILE pid=%lu, pFile=%p, hMap=%p, pMapRegion=%p, "
- "mmapSize=%lld, mmapSizeActual=%lld, mmapSizeMax=%lld\n",
+ "mmapSize=%lld, mmapSizeMax=%lld\n",
osGetCurrentProcessId(), pFile, pFile->hMap, pFile->pMapRegion,
- pFile->mmapSize, pFile->mmapSizeActual, pFile->mmapSizeMax));
+ pFile->mmapSize, pFile->mmapSizeMax));
if( pFile->pMapRegion ){
if( !osUnmapViewOfFile(pFile->pMapRegion) ){
pFile->lastErrno = osGetLastError();
@@ -44514,7 +46733,6 @@ static int winUnmapfile(winFile *pFile){
}
pFile->pMapRegion = 0;
pFile->mmapSize = 0;
- pFile->mmapSizeActual = 0;
}
if( pFile->hMap!=NULL ){
if( !osCloseHandle(pFile->hMap) ){
@@ -44625,7 +46843,6 @@ static int winMapfile(winFile *pFd, sqlite3_int64 nByte){
}
pFd->pMapRegion = pNew;
pFd->mmapSize = nMap;
- pFd->mmapSizeActual = nMap;
}
OSTRACE(("MAP-FILE pid=%lu, pFile=%p, rc=SQLITE_OK\n",
@@ -44666,6 +46883,7 @@ static int winFetch(sqlite3_file *fd, i64 iOff, int nAmt, void **pp){
}
}
if( pFd->mmapSize >= iOff+nAmt ){
+ assert( pFd->pMapRegion!=0 );
*pp = &((u8 *)pFd->pMapRegion)[iOff];
pFd->nFetchOut++;
}
@@ -45169,7 +47387,7 @@ static int winOpen(
#ifndef NDEBUG
int isOpenJournal = (isCreate && (
- eType==SQLITE_OPEN_MASTER_JOURNAL
+ eType==SQLITE_OPEN_SUPER_JOURNAL
|| eType==SQLITE_OPEN_MAIN_JOURNAL
|| eType==SQLITE_OPEN_WAL
));
@@ -45190,17 +47408,17 @@ static int winOpen(
assert(isExclusive==0 || isCreate);
assert(isDelete==0 || isCreate);
- /* The main DB, main journal, WAL file and master journal are never
+ /* The main DB, main journal, WAL file and super-journal are never
** automatically deleted. Nor are they ever temporary files. */
assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MAIN_DB );
assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MAIN_JOURNAL );
- assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MASTER_JOURNAL );
+ assert( (!isDelete && zName) || eType!=SQLITE_OPEN_SUPER_JOURNAL );
assert( (!isDelete && zName) || eType!=SQLITE_OPEN_WAL );
/* Assert that the upper layer has set one of the "file-type" flags. */
assert( eType==SQLITE_OPEN_MAIN_DB || eType==SQLITE_OPEN_TEMP_DB
|| eType==SQLITE_OPEN_MAIN_JOURNAL || eType==SQLITE_OPEN_TEMP_JOURNAL
- || eType==SQLITE_OPEN_SUBJOURNAL || eType==SQLITE_OPEN_MASTER_JOURNAL
+ || eType==SQLITE_OPEN_SUBJOURNAL || eType==SQLITE_OPEN_SUPER_JOURNAL
|| eType==SQLITE_OPEN_TRANSIENT_DB || eType==SQLITE_OPEN_WAL
);
@@ -45272,7 +47490,11 @@ static int winOpen(
dwCreationDisposition = OPEN_EXISTING;
}
- dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
+ if( 0==sqlite3_uri_boolean(zName, "exclusive", 0) ){
+ dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
+ }else{
+ dwShareMode = 0;
+ }
if( isDelete ){
#if SQLITE_OS_WINCE
@@ -45412,13 +47634,15 @@ static int winOpen(
}
sqlite3_free(zTmpname);
- pFile->pMethod = pAppData ? pAppData->pMethod : &winIoMethod;
+ id->pMethods = pAppData ? pAppData->pMethod : &winIoMethod;
pFile->pVfs = pVfs;
pFile->h = h;
if( isReadonly ){
pFile->ctrlFlags |= WINFILE_RDONLY;
}
- if( sqlite3_uri_boolean(zName, "psow", SQLITE_POWERSAFE_OVERWRITE) ){
+ if( (flags & SQLITE_OPEN_MAIN_DB)
+ && sqlite3_uri_boolean(zName, "psow", SQLITE_POWERSAFE_OVERWRITE)
+ ){
pFile->ctrlFlags |= WINFILE_PSOW;
}
pFile->lastErrno = NO_ERROR;
@@ -45427,7 +47651,6 @@ static int winOpen(
pFile->hMap = NULL;
pFile->pMapRegion = 0;
pFile->mmapSize = 0;
- pFile->mmapSizeActual = 0;
pFile->mmapSizeMax = sqlite3GlobalConfig.szMmap;
#endif
@@ -45629,6 +47852,17 @@ static int winAccess(
return SQLITE_OK;
}
+/*
+** Returns non-zero if the specified path name starts with the "long path"
+** prefix.
+*/
+static BOOL winIsLongPathPrefix(
+ const char *zPathname
+){
+ return ( zPathname[0]=='\\' && zPathname[1]=='\\'
+ && zPathname[2]=='?' && zPathname[3]=='\\' );
+}
+
/*
** Returns non-zero if the specified path name starts with a drive letter
** followed by a colon character.
@@ -45693,10 +47927,11 @@ static int winFullPathname(
char *zOut;
#endif
- /* If this path name begins with "/X:", where "X" is any alphabetic
- ** character, discard the initial "/" from the pathname.
+ /* If this path name begins with "/X:" or "\\?\", where "X" is any
+ ** alphabetic character, discard the initial "/" from the pathname.
*/
- if( zRelative[0]=='/' && winIsDriveLetterAndColon(zRelative+1) ){
+ if( zRelative[0]=='/' && (winIsDriveLetterAndColon(zRelative+1)
+ || winIsLongPathPrefix(zRelative+1)) ){
zRelative++;
}
@@ -46303,30 +48538,88 @@ SQLITE_API int sqlite3_os_end(void){
** sqlite3_deserialize().
*/
/* #include "sqliteInt.h" */
-#ifdef SQLITE_ENABLE_DESERIALIZE
+#ifndef SQLITE_OMIT_DESERIALIZE
/*
** Forward declaration of objects used by this utility
*/
typedef struct sqlite3_vfs MemVfs;
typedef struct MemFile MemFile;
+typedef struct MemStore MemStore;
/* Access to a lower-level VFS that (might) implement dynamic loading,
** access to randomness, etc.
*/
#define ORIGVFS(p) ((sqlite3_vfs*)((p)->pAppData))
+/* Storage for a memdb file.
+**
+** An memdb object can be shared or separate. Shared memdb objects can be
+** used by more than one database connection. Mutexes are used by shared
+** memdb objects to coordinate access. Separate memdb objects are only
+** connected to a single database connection and do not require additional
+** mutexes.
+**
+** Shared memdb objects have .zFName!=0 and .pMutex!=0. They are created
+** using "file:/name?vfs=memdb". The first character of the name must be
+** "/" or else the object will be a separate memdb object. All shared
+** memdb objects are stored in memdb_g.apMemStore[] in an arbitrary order.
+**
+** Separate memdb objects are created using a name that does not begin
+** with "/" or using sqlite3_deserialize().
+**
+** Access rules for shared MemStore objects:
+**
+** * .zFName is initialized when the object is created and afterwards
+** is unchanged until the object is destroyed. So it can be accessed
+** at any time as long as we know the object is not being destroyed,
+** which means while either the SQLITE_MUTEX_STATIC_VFS1 or
+** .pMutex is held or the object is not part of memdb_g.apMemStore[].
+**
+** * Can .pMutex can only be changed while holding the
+** SQLITE_MUTEX_STATIC_VFS1 mutex or while the object is not part
+** of memdb_g.apMemStore[].
+**
+** * Other fields can only be changed while holding the .pMutex mutex
+** or when the .nRef is less than zero and the object is not part of
+** memdb_g.apMemStore[].
+**
+** * The .aData pointer has the added requirement that it can can only
+** be changed (for resizing) when nMmap is zero.
+**
+*/
+struct MemStore {
+ sqlite3_int64 sz; /* Size of the file */
+ sqlite3_int64 szAlloc; /* Space allocated to aData */
+ sqlite3_int64 szMax; /* Maximum allowed size of the file */
+ unsigned char *aData; /* content of the file */
+ sqlite3_mutex *pMutex; /* Used by shared stores only */
+ int nMmap; /* Number of memory mapped pages */
+ unsigned mFlags; /* Flags */
+ int nRdLock; /* Number of readers */
+ int nWrLock; /* Number of writers. (Always 0 or 1) */
+ int nRef; /* Number of users of this MemStore */
+ char *zFName; /* The filename for shared stores */
+};
+
/* An open file */
struct MemFile {
sqlite3_file base; /* IO methods */
- sqlite3_int64 sz; /* Size of the file */
- sqlite3_int64 szMax; /* Space allocated to aData */
- unsigned char *aData; /* content of the file */
- int nMmap; /* Number of memory mapped pages */
- unsigned mFlags; /* Flags */
+ MemStore *pStore; /* The storage */
int eLock; /* Most recent lock against this file */
};
+/*
+** File-scope variables for holding the memdb files that are accessible
+** to multiple database connections in separate threads.
+**
+** Must hold SQLITE_MUTEX_STATIC_VFS1 to access any part of this object.
+*/
+static struct MemFS {
+ int nMemStore; /* Number of shared MemStore objects */
+ MemStore **apMemStore; /* Array of all shared MemStore objects */
+} memdb_g;
+
/*
** Methods for MemFile
*/
@@ -46367,7 +48660,7 @@ static sqlite3_vfs memdb_vfs = {
1024, /* mxPathname */
0, /* pNext */
"memdb", /* zName */
- 0, /* pAppData (set when registered) */
+ 0, /* pAppData (set when registered) */
memdbOpen, /* xOpen */
0, /* memdbDelete, */ /* xDelete */
memdbAccess, /* xAccess */
@@ -46380,7 +48673,10 @@ static sqlite3_vfs memdb_vfs = {
memdbSleep, /* xSleep */
0, /* memdbCurrentTime, */ /* xCurrentTime */
memdbGetLastError, /* xGetLastError */
- memdbCurrentTimeInt64 /* xCurrentTimeInt64 */
+ memdbCurrentTimeInt64, /* xCurrentTimeInt64 */
+ 0, /* xSetSystemCall */
+ 0, /* xGetSystemCall */
+ 0, /* xNextSystemCall */
};
static const sqlite3_io_methods memdb_io_methods = {
@@ -46392,7 +48688,7 @@ static const sqlite3_io_methods memdb_io_methods = {
memdbSync, /* xSync */
memdbFileSize, /* xFileSize */
memdbLock, /* xLock */
- memdbLock, /* xUnlock - same as xLock in this case */
+ memdbLock, /* xUnlock - same as xLock in this case */
0, /* memdbCheckReservedLock, */ /* xCheckReservedLock */
memdbFileControl, /* xFileControl */
0, /* memdbSectorSize,*/ /* xSectorSize */
@@ -46405,17 +48701,68 @@ static const sqlite3_io_methods memdb_io_methods = {
memdbUnfetch /* xUnfetch */
};
+/*
+** Enter/leave the mutex on a MemStore
+*/
+#if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE==0
+static void memdbEnter(MemStore *p){
+ UNUSED_PARAMETER(p);
+}
+static void memdbLeave(MemStore *p){
+ UNUSED_PARAMETER(p);
+}
+#else
+static void memdbEnter(MemStore *p){
+ sqlite3_mutex_enter(p->pMutex);
+}
+static void memdbLeave(MemStore *p){
+ sqlite3_mutex_leave(p->pMutex);
+}
+#endif
+
/*
** Close an memdb-file.
-**
-** The pData pointer is owned by the application, so there is nothing
-** to free.
+** Free the underlying MemStore object when its refcount drops to zero
+** or less.
*/
static int memdbClose(sqlite3_file *pFile){
- MemFile *p = (MemFile *)pFile;
- if( p->mFlags & SQLITE_DESERIALIZE_FREEONCLOSE ) sqlite3_free(p->aData);
+ MemStore *p = ((MemFile*)pFile)->pStore;
+ if( p->zFName ){
+ int i;
+#ifndef SQLITE_MUTEX_OMIT
+ sqlite3_mutex *pVfsMutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1);
+#endif
+ sqlite3_mutex_enter(pVfsMutex);
+ for(i=0; ALWAYS(inRef==1 ){
+ memdb_g.apMemStore[i] = memdb_g.apMemStore[--memdb_g.nMemStore];
+ if( memdb_g.nMemStore==0 ){
+ sqlite3_free(memdb_g.apMemStore);
+ memdb_g.apMemStore = 0;
+ }
+ }
+ break;
+ }
+ }
+ sqlite3_mutex_leave(pVfsMutex);
+ }else{
+ memdbEnter(p);
+ }
+ p->nRef--;
+ if( p->nRef<=0 ){
+ if( p->mFlags & SQLITE_DESERIALIZE_FREEONCLOSE ){
+ sqlite3_free(p->aData);
+ }
+ memdbLeave(p);
+ sqlite3_mutex_free(p->pMutex);
+ sqlite3_free(p);
+ }else{
+ memdbLeave(p);
+ }
return SQLITE_OK;
}
@@ -46423,33 +48770,41 @@ static int memdbClose(sqlite3_file *pFile){
** Read data from an memdb-file.
*/
static int memdbRead(
- sqlite3_file *pFile,
- void *zBuf,
- int iAmt,
+ sqlite3_file *pFile,
+ void *zBuf,
+ int iAmt,
sqlite_int64 iOfst
){
- MemFile *p = (MemFile *)pFile;
+ MemStore *p = ((MemFile*)pFile)->pStore;
+ memdbEnter(p);
if( iOfst+iAmt>p->sz ){
memset(zBuf, 0, iAmt);
if( iOfstsz ) memcpy(zBuf, p->aData+iOfst, p->sz - iOfst);
+ memdbLeave(p);
return SQLITE_IOERR_SHORT_READ;
}
memcpy(zBuf, p->aData+iOfst, iAmt);
+ memdbLeave(p);
return SQLITE_OK;
}
/*
** Try to enlarge the memory allocation to hold at least sz bytes
*/
-static int memdbEnlarge(MemFile *p, sqlite3_int64 newSz){
+static int memdbEnlarge(MemStore *p, sqlite3_int64 newSz){
unsigned char *pNew;
if( (p->mFlags & SQLITE_DESERIALIZE_RESIZEABLE)==0 || p->nMmap>0 ){
return SQLITE_FULL;
}
- pNew = sqlite3_realloc64(p->aData, newSz);
- if( pNew==0 ) return SQLITE_NOMEM;
+ if( newSz>p->szMax ){
+ return SQLITE_FULL;
+ }
+ newSz *= 2;
+ if( newSz>p->szMax ) newSz = p->szMax;
+ pNew = sqlite3Realloc(p->aData, newSz);
+ if( pNew==0 ) return SQLITE_IOERR_NOMEM;
p->aData = pNew;
- p->szMax = newSz;
+ p->szAlloc = newSz;
return SQLITE_OK;
}
@@ -46462,18 +48817,27 @@ static int memdbWrite(
int iAmt,
sqlite_int64 iOfst
){
- MemFile *p = (MemFile *)pFile;
+ MemStore *p = ((MemFile*)pFile)->pStore;
+ memdbEnter(p);
+ if( NEVER(p->mFlags & SQLITE_DESERIALIZE_READONLY) ){
+ /* Can't happen: memdbLock() will return SQLITE_READONLY before
+ ** reaching this point */
+ memdbLeave(p);
+ return SQLITE_IOERR_WRITE;
+ }
if( iOfst+iAmt>p->sz ){
int rc;
- if( iOfst+iAmt>p->szMax
- && (rc = memdbEnlarge(p, (iOfst+iAmt)*2))!=SQLITE_OK
+ if( iOfst+iAmt>p->szAlloc
+ && (rc = memdbEnlarge(p, iOfst+iAmt))!=SQLITE_OK
){
+ memdbLeave(p);
return rc;
}
if( iOfst>p->sz ) memset(p->aData+p->sz, 0, iOfst-p->sz);
p->sz = iOfst+iAmt;
}
memcpy(p->aData+iOfst, z, iAmt);
+ memdbLeave(p);
return SQLITE_OK;
}
@@ -46485,16 +48849,24 @@ static int memdbWrite(
** the size of a file, never to increase the size.
*/
static int memdbTruncate(sqlite3_file *pFile, sqlite_int64 size){
- MemFile *p = (MemFile *)pFile;
- if( NEVER(size>p->sz) ) return SQLITE_FULL;
- p->sz = size;
- return SQLITE_OK;
+ MemStore *p = ((MemFile*)pFile)->pStore;
+ int rc = SQLITE_OK;
+ memdbEnter(p);
+ if( NEVER(size>p->sz) ){
+ rc = SQLITE_FULL;
+ }else{
+ p->sz = size;
+ }
+ memdbLeave(p);
+ return rc;
}
/*
** Sync an memdb-file.
*/
static int memdbSync(sqlite3_file *pFile, int flags){
+ UNUSED_PARAMETER(pFile);
+ UNUSED_PARAMETER(flags);
return SQLITE_OK;
}
@@ -46502,8 +48874,10 @@ static int memdbSync(sqlite3_file *pFile, int flags){
** Return the current file-size of an memdb-file.
*/
static int memdbFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
- MemFile *p = (MemFile *)pFile;
+ MemStore *p = ((MemFile*)pFile)->pStore;
+ memdbEnter(p);
*pSize = p->sz;
+ memdbLeave(p);
return SQLITE_OK;
}
@@ -46511,14 +48885,48 @@ static int memdbFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
** Lock an memdb-file.
*/
static int memdbLock(sqlite3_file *pFile, int eLock){
- MemFile *p = (MemFile *)pFile;
- p->eLock = eLock;
- return SQLITE_OK;
+ MemFile *pThis = (MemFile*)pFile;
+ MemStore *p = pThis->pStore;
+ int rc = SQLITE_OK;
+ if( eLock==pThis->eLock ) return SQLITE_OK;
+ memdbEnter(p);
+ if( eLock>SQLITE_LOCK_SHARED ){
+ if( p->mFlags & SQLITE_DESERIALIZE_READONLY ){
+ rc = SQLITE_READONLY;
+ }else if( pThis->eLock<=SQLITE_LOCK_SHARED ){
+ if( p->nWrLock ){
+ rc = SQLITE_BUSY;
+ }else{
+ p->nWrLock = 1;
+ }
+ }
+ }else if( eLock==SQLITE_LOCK_SHARED ){
+ if( pThis->eLock > SQLITE_LOCK_SHARED ){
+ assert( p->nWrLock==1 );
+ p->nWrLock = 0;
+ }else if( p->nWrLock ){
+ rc = SQLITE_BUSY;
+ }else{
+ p->nRdLock++;
+ }
+ }else{
+ assert( eLock==SQLITE_LOCK_NONE );
+ if( pThis->eLock>SQLITE_LOCK_SHARED ){
+ assert( p->nWrLock==1 );
+ p->nWrLock = 0;
+ }
+ assert( p->nRdLock>0 );
+ p->nRdLock--;
+ }
+ if( rc==SQLITE_OK ) pThis->eLock = eLock;
+ memdbLeave(p);
+ return rc;
}
-#if 0 /* Never used because memdbAccess() always returns false */
+#if 0
/*
-** Check if another file-handle holds a RESERVED lock on an memdb-file.
+** This interface is only used for crash recovery, which does not
+** occur on an in-memory database.
*/
static int memdbCheckReservedLock(sqlite3_file *pFile, int *pResOut){
*pResOut = 0;
@@ -46526,16 +48934,32 @@ static int memdbCheckReservedLock(sqlite3_file *pFile, int *pResOut){
}
#endif
+
/*
** File control method. For custom operations on an memdb-file.
*/
static int memdbFileControl(sqlite3_file *pFile, int op, void *pArg){
- MemFile *p = (MemFile *)pFile;
+ MemStore *p = ((MemFile*)pFile)->pStore;
int rc = SQLITE_NOTFOUND;
+ memdbEnter(p);
if( op==SQLITE_FCNTL_VFSNAME ){
*(char**)pArg = sqlite3_mprintf("memdb(%p,%lld)", p->aData, p->sz);
rc = SQLITE_OK;
}
+ if( op==SQLITE_FCNTL_SIZE_LIMIT ){
+ sqlite3_int64 iLimit = *(sqlite3_int64*)pArg;
+ if( iLimitsz ){
+ if( iLimit<0 ){
+ iLimit = p->szMax;
+ }else{
+ iLimit = p->sz;
+ }
+ }
+ p->szMax = iLimit;
+ *(sqlite3_int64*)pArg = iLimit;
+ rc = SQLITE_OK;
+ }
+ memdbLeave(p);
return rc;
}
@@ -46552,7 +48976,8 @@ static int memdbSectorSize(sqlite3_file *pFile){
** Return the device characteristic flags supported by an memdb-file.
*/
static int memdbDeviceCharacteristics(sqlite3_file *pFile){
- return SQLITE_IOCAP_ATOMIC |
+ UNUSED_PARAMETER(pFile);
+ return SQLITE_IOCAP_ATOMIC |
SQLITE_IOCAP_POWERSAFE_OVERWRITE |
SQLITE_IOCAP_SAFE_APPEND |
SQLITE_IOCAP_SEQUENTIAL;
@@ -46565,16 +48990,26 @@ static int memdbFetch(
int iAmt,
void **pp
){
- MemFile *p = (MemFile *)pFile;
- p->nMmap++;
- *pp = (void*)(p->aData + iOfst);
+ MemStore *p = ((MemFile*)pFile)->pStore;
+ memdbEnter(p);
+ if( iOfst+iAmt>p->sz ){
+ *pp = 0;
+ }else{
+ p->nMmap++;
+ *pp = (void*)(p->aData + iOfst);
+ }
+ memdbLeave(p);
return SQLITE_OK;
}
/* Release a memory-mapped page */
static int memdbUnfetch(sqlite3_file *pFile, sqlite3_int64 iOfst, void *pPage){
- MemFile *p = (MemFile *)pFile;
+ MemStore *p = ((MemFile*)pFile)->pStore;
+ UNUSED_PARAMETER(iOfst);
+ UNUSED_PARAMETER(pPage);
+ memdbEnter(p);
p->nMmap--;
+ memdbLeave(p);
return SQLITE_OK;
}
@@ -46584,23 +49019,83 @@ static int memdbUnfetch(sqlite3_file *pFile, sqlite3_int64 iOfst, void *pPage){
static int memdbOpen(
sqlite3_vfs *pVfs,
const char *zName,
- sqlite3_file *pFile,
+ sqlite3_file *pFd,
int flags,
int *pOutFlags
){
- MemFile *p = (MemFile*)pFile;
+ MemFile *pFile = (MemFile*)pFd;
+ MemStore *p = 0;
+ int szName;
if( (flags & SQLITE_OPEN_MAIN_DB)==0 ){
- return ORIGVFS(pVfs)->xOpen(ORIGVFS(pVfs), zName, pFile, flags, pOutFlags);
+ return ORIGVFS(pVfs)->xOpen(ORIGVFS(pVfs), zName, pFd, flags, pOutFlags);
}
- memset(p, 0, sizeof(*p));
- p->mFlags = SQLITE_DESERIALIZE_RESIZEABLE | SQLITE_DESERIALIZE_FREEONCLOSE;
+ memset(pFile, 0, sizeof(*p));
+ szName = sqlite3Strlen30(zName);
+ if( szName>1 && zName[0]=='/' ){
+ int i;
+#ifndef SQLITE_MUTEX_OMIT
+ sqlite3_mutex *pVfsMutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1);
+#endif
+ sqlite3_mutex_enter(pVfsMutex);
+ for(i=0; izFName,zName)==0 ){
+ p = memdb_g.apMemStore[i];
+ break;
+ }
+ }
+ if( p==0 ){
+ MemStore **apNew;
+ p = sqlite3Malloc( sizeof(*p) + szName + 3 );
+ if( p==0 ){
+ sqlite3_mutex_leave(pVfsMutex);
+ return SQLITE_NOMEM;
+ }
+ apNew = sqlite3Realloc(memdb_g.apMemStore,
+ sizeof(apNew[0])*(memdb_g.nMemStore+1) );
+ if( apNew==0 ){
+ sqlite3_free(p);
+ sqlite3_mutex_leave(pVfsMutex);
+ return SQLITE_NOMEM;
+ }
+ apNew[memdb_g.nMemStore++] = p;
+ memdb_g.apMemStore = apNew;
+ memset(p, 0, sizeof(*p));
+ p->mFlags = SQLITE_DESERIALIZE_RESIZEABLE|SQLITE_DESERIALIZE_FREEONCLOSE;
+ p->szMax = sqlite3GlobalConfig.mxMemdbSize;
+ p->zFName = (char*)&p[1];
+ memcpy(p->zFName, zName, szName+1);
+ p->pMutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
+ if( p->pMutex==0 ){
+ memdb_g.nMemStore--;
+ sqlite3_free(p);
+ sqlite3_mutex_leave(pVfsMutex);
+ return SQLITE_NOMEM;
+ }
+ p->nRef = 1;
+ memdbEnter(p);
+ }else{
+ memdbEnter(p);
+ p->nRef++;
+ }
+ sqlite3_mutex_leave(pVfsMutex);
+ }else{
+ p = sqlite3Malloc( sizeof(*p) );
+ if( p==0 ){
+ return SQLITE_NOMEM;
+ }
+ memset(p, 0, sizeof(*p));
+ p->mFlags = SQLITE_DESERIALIZE_RESIZEABLE | SQLITE_DESERIALIZE_FREEONCLOSE;
+ p->szMax = sqlite3GlobalConfig.mxMemdbSize;
+ }
+ pFile->pStore = p;
assert( pOutFlags!=0 ); /* True because flags==SQLITE_OPEN_MAIN_DB */
*pOutFlags = flags | SQLITE_OPEN_MEMORY;
- p->base.pMethods = &memdb_io_methods;
+ pFd->pMethods = &memdb_io_methods;
+ memdbLeave(p);
return SQLITE_OK;
}
-#if 0 /* Only used to delete rollback journals, master journals, and WAL
+#if 0 /* Only used to delete rollback journals, super-journals, and WAL
** files, none of which exist in memdb. So this routine is never used */
/*
** Delete the file located at zPath. If the dirSync argument is true,
@@ -46619,11 +49114,14 @@ static int memdbDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
** With memdb, no files ever exist on disk. So always return false.
*/
static int memdbAccess(
- sqlite3_vfs *pVfs,
- const char *zPath,
- int flags,
+ sqlite3_vfs *pVfs,
+ const char *zPath,
+ int flags,
int *pResOut
){
+ UNUSED_PARAMETER(pVfs);
+ UNUSED_PARAMETER(zPath);
+ UNUSED_PARAMETER(flags);
*pResOut = 0;
return SQLITE_OK;
}
@@ -46634,11 +49132,12 @@ static int memdbAccess(
** of at least (INST_MAX_PATHNAME+1) bytes.
*/
static int memdbFullPathname(
- sqlite3_vfs *pVfs,
- const char *zPath,
- int nOut,
+ sqlite3_vfs *pVfs,
+ const char *zPath,
+ int nOut,
char *zOut
){
+ UNUSED_PARAMETER(pVfs);
sqlite3_snprintf(nOut, zOut, "%s", zPath);
return SQLITE_OK;
}
@@ -46652,7 +49151,7 @@ static void *memdbDlOpen(sqlite3_vfs *pVfs, const char *zPath){
/*
** Populate the buffer zErrMsg (size nByte bytes) with a human readable
-** utf-8 string describing the most recent error encountered associated
+** utf-8 string describing the most recent error encountered associated
** with dynamic libraries.
*/
static void memdbDlError(sqlite3_vfs *pVfs, int nByte, char *zErrMsg){
@@ -46674,7 +49173,7 @@ static void memdbDlClose(sqlite3_vfs *pVfs, void *pHandle){
}
/*
-** Populate the buffer pointed to by zBufOut with nByte bytes of
+** Populate the buffer pointed to by zBufOut with nByte bytes of
** random data.
*/
static int memdbRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
@@ -46682,7 +49181,7 @@ static int memdbRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
}
/*
-** Sleep for nMicro microseconds. Return the number of microseconds
+** Sleep for nMicro microseconds. Return the number of microseconds
** actually slept.
*/
static int memdbSleep(sqlite3_vfs *pVfs, int nMicro){
@@ -46711,9 +49210,14 @@ static int memdbCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *p){
*/
static MemFile *memdbFromDbSchema(sqlite3 *db, const char *zSchema){
MemFile *p = 0;
+ MemStore *pStore;
int rc = sqlite3_file_control(db, zSchema, SQLITE_FCNTL_FILE_POINTER, &p);
if( rc ) return 0;
if( p->base.pMethods!=&memdb_io_methods ) return 0;
+ pStore = p->pStore;
+ memdbEnter(pStore);
+ if( pStore->zFName!=0 ) p = 0;
+ memdbLeave(pStore);
return p;
}
@@ -46749,12 +49253,14 @@ SQLITE_API unsigned char *sqlite3_serialize(
if( piSize ) *piSize = -1;
if( iDb<0 ) return 0;
if( p ){
- if( piSize ) *piSize = p->sz;
+ MemStore *pStore = p->pStore;
+ assert( pStore->pMutex==0 );
+ if( piSize ) *piSize = pStore->sz;
if( mFlags & SQLITE_SERIALIZE_NOCOPY ){
- pOut = p->aData;
+ pOut = pStore->aData;
}else{
- pOut = sqlite3_malloc64( p->sz );
- if( pOut ) memcpy(pOut, p->aData, p->sz);
+ pOut = sqlite3_malloc64( pStore->sz );
+ if( pOut ) memcpy(pOut, pStore->aData, pStore->sz);
}
return pOut;
}
@@ -46788,7 +49294,7 @@ SQLITE_API unsigned char *sqlite3_serialize(
}else{
memset(pTo, 0, szPage);
}
- sqlite3PagerUnref(pPage);
+ sqlite3PagerUnref(pPage);
}
}
}
@@ -46827,10 +49333,14 @@ SQLITE_API int sqlite3_deserialize(
if( iDb<0 ){
rc = SQLITE_ERROR;
goto end_deserialize;
- }
+ }
zSql = sqlite3_mprintf("ATTACH x AS %Q", zSchema);
- rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
- sqlite3_free(zSql);
+ if( zSql==0 ){
+ rc = SQLITE_NOMEM;
+ }else{
+ rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
+ sqlite3_free(zSql);
+ }
if( rc ) goto end_deserialize;
db->init.iDb = (u8)iDb;
db->init.reopenMemdb = 1;
@@ -46844,35 +49354,47 @@ SQLITE_API int sqlite3_deserialize(
if( p==0 ){
rc = SQLITE_ERROR;
}else{
- p->aData = pData;
- p->sz = szDb;
- p->szMax = szBuf;
- p->mFlags = mFlags;
+ MemStore *pStore = p->pStore;
+ pStore->aData = pData;
+ pData = 0;
+ pStore->sz = szDb;
+ pStore->szAlloc = szBuf;
+ pStore->szMax = szBuf;
+ if( pStore->szMaxszMax = sqlite3GlobalConfig.mxMemdbSize;
+ }
+ pStore->mFlags = mFlags;
rc = SQLITE_OK;
}
end_deserialize:
sqlite3_finalize(pStmt);
+ if( pData && (mFlags & SQLITE_DESERIALIZE_FREEONCLOSE)!=0 ){
+ sqlite3_free(pData);
+ }
sqlite3_mutex_leave(db->mutex);
return rc;
}
-/*
+/*
** This routine is called when the extension is loaded.
** Register the new VFS.
*/
SQLITE_PRIVATE int sqlite3MemdbInit(void){
sqlite3_vfs *pLower = sqlite3_vfs_find(0);
- int sz = pLower->szOsFile;
+ unsigned int sz;
+ if( NEVER(pLower==0) ) return SQLITE_ERROR;
+ sz = pLower->szOsFile;
memdb_vfs.pAppData = pLower;
- /* In all known configurations of SQLite, the size of a default
- ** sqlite3_file is greater than the size of a memdb sqlite3_file.
- ** Should that ever change, remove the following NEVER() */
- if( NEVER(szpCache==0 ) return;
N = sqlite3PcachePagecount(pCache);
@@ -47456,12 +49978,12 @@ static void pcacheManageDirtyList(PgHdr *pPage, u8 addRemove){
if( addRemove & PCACHE_DIRTYLIST_REMOVE ){
assert( pPage->pDirtyNext || pPage==p->pDirtyTail );
assert( pPage->pDirtyPrev || pPage==p->pDirty );
-
+
/* Update the PCache1.pSynced variable if necessary. */
if( p->pSynced==pPage ){
p->pSynced = pPage->pDirtyPrev;
}
-
+
if( pPage->pDirtyNext ){
pPage->pDirtyNext->pDirtyPrev = pPage->pDirtyPrev;
}else{
@@ -47471,7 +49993,7 @@ static void pcacheManageDirtyList(PgHdr *pPage, u8 addRemove){
if( pPage->pDirtyPrev ){
pPage->pDirtyPrev->pDirtyNext = pPage->pDirtyNext;
}else{
- /* If there are now no dirty pages in the cache, set eCreate to 2.
+ /* If there are now no dirty pages in the cache, set eCreate to 2.
** This is an optimization that allows sqlite3PcacheFetch() to skip
** searching for a dirty page to eject from the cache when it might
** otherwise have to. */
@@ -47500,11 +50022,11 @@ static void pcacheManageDirtyList(PgHdr *pPage, u8 addRemove){
p->pDirty = pPage;
/* If pSynced is NULL and this page has a clear NEED_SYNC flag, set
- ** pSynced to point to it. Checking the NEED_SYNC flag is an
+ ** pSynced to point to it. Checking the NEED_SYNC flag is an
** optimization, as if pSynced points to a page with the NEED_SYNC
- ** flag set sqlite3PcacheFetchStress() searches through all newer
+ ** flag set sqlite3PcacheFetchStress() searches through all newer
** entries of the dirty-list for a page with NEED_SYNC clear anyway. */
- if( !p->pSynced
+ if( !p->pSynced
&& 0==(pPage->flags&PGHDR_NEED_SYNC) /*OPTIMIZATION-IF-FALSE*/
){
p->pSynced = pPage;
@@ -47535,16 +50057,17 @@ static int numberOfCachePages(PCache *p){
** suggested cache size is set to N. */
return p->szCache;
}else{
- /* IMPLEMENTATION-OF: R-61436-13639 If the argument N is negative, then
- ** the number of cache pages is adjusted to use approximately abs(N*1024)
- ** bytes of memory. */
+ /* IMPLEMANTATION-OF: R-59858-46238 If the argument N is negative, then the
+ ** number of cache pages is adjusted to be a number of pages that would
+ ** use approximately abs(N*1024) bytes of memory based on the current
+ ** page size. */
return (int)((-1024*(i64)p->szCache)/(p->szPage+p->szExtra));
}
}
/*************************************************** 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){
@@ -47553,6 +50076,7 @@ SQLITE_PRIVATE int sqlite3PcacheInitialize(void){
** built-in default page cache is used instead of the application defined
** page cache. */
sqlite3PCacheSetDefault();
+ assert( sqlite3GlobalConfig.pcache2.xInit!=0 );
}
return sqlite3GlobalConfig.pcache2.xInit(sqlite3GlobalConfig.pcache2.pArg);
}
@@ -47570,8 +50094,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().
**
** szExtra is some extra space allocated for each page. The first
@@ -47683,7 +50207,7 @@ SQLITE_PRIVATE sqlite3_pcache_page *sqlite3PcacheFetch(
/*
** If the sqlite3PcacheFetch() routine is unable to allocate a new
** page because no clean pages are available for reuse and the cache
-** size limit has been reached, then this routine can be invoked to
+** size limit has been reached, then this routine can be invoked to
** try harder to allocate a page. This routine might invoke the stress
** callback to spill dirty pages to the journal. It will then try to
** allocate the new page and will only fail to allocate a new page on
@@ -47700,17 +50224,17 @@ SQLITE_PRIVATE int sqlite3PcacheFetchStress(
if( pCache->eCreate==2 ) return 0;
if( sqlite3PcachePagecount(pCache)>pCache->szSpill ){
- /* 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.
**
** If the LRU page in the dirty list that has a clear PGHDR_NEED_SYNC
** flag is currently referenced, then the following may leave pSynced
** set incorrectly (pointing to other than the LRU page with NEED_SYNC
** cleared). This is Ok, as pSynced is just an optimization. */
- 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;
@@ -47720,7 +50244,7 @@ SQLITE_PRIVATE int sqlite3PcacheFetchStress(
if( pPg ){
int rc;
#ifdef SQLITE_LOG_CACHE_SPILL
- sqlite3_log(SQLITE_FULL,
+ sqlite3_log(SQLITE_FULL,
"spill page %d making room for %d - cache used: %d/%d",
pPg->pgno, pgno,
sqlite3GlobalConfig.pcache2.xPagecount(pCache->pCache),
@@ -47905,7 +50429,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;
@@ -47968,7 +50492,7 @@ SQLITE_PRIVATE void sqlite3PcacheClose(PCache *pCache){
sqlite3GlobalConfig.pcache2.xDestroy(pCache->pCache);
}
-/*
+/*
** Discard the contents of the cache.
*/
SQLITE_PRIVATE void sqlite3PcacheClear(PCache *pCache){
@@ -48059,7 +50583,7 @@ SQLITE_PRIVATE PgHdr *sqlite3PcacheDirtyList(PCache *pCache){
return pcacheSortDirtyList(pCache->pDirty);
}
-/*
+/*
** Return the total number of references to all pages held by the cache.
**
** This is not the total number of pages referenced, but the sum of the
@@ -48076,7 +50600,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){
@@ -48118,7 +50642,7 @@ SQLITE_PRIVATE int sqlite3PcacheSetSpillsize(PCache *p, int mxPage){
p->szSpill = mxPage;
}
res = numberOfCachePages(p);
- if( resszSpill ) res = p->szSpill;
+ if( resszSpill ) res = p->szSpill;
return res;
}
@@ -48148,6 +50672,15 @@ SQLITE_PRIVATE int sqlite3PCachePercentDirty(PCache *pCache){
return nCache ? (int)(((i64)nDirty * 100) / nCache) : 0;
}
+#ifdef SQLITE_DIRECT_OVERFLOW_READ
+/*
+** Return true if there are one or more dirty pages in the cache. Else false.
+*/
+SQLITE_PRIVATE int sqlite3PCacheIsDirty(PCache *pCache){
+ return (pCache->pDirty!=0);
+}
+#endif
+
#if defined(SQLITE_CHECK_PAGES) || defined(SQLITE_DEBUG)
/*
** For all dirty pages currently in the cache, invoke the specified
@@ -48229,7 +50762,7 @@ SQLITE_PRIVATE void sqlite3PcacheIterateDirty(PCache *pCache, void (*xIter)(PgHd
**
** The third case is a chunk of heap memory (defaulting to 100 pages worth)
** that is allocated when the page cache is created. The size of the local
-** bulk allocation can be adjusted using
+** bulk allocation can be adjusted using
**
** sqlite3_config(SQLITE_CONFIG_PAGECACHE, (void*)0, 0, N).
**
@@ -48254,29 +50787,41 @@ typedef struct PgFreeslot PgFreeslot;
typedef struct PGroup PGroup;
/*
-** Each cache entry is represented by an instance of the following
+** Each cache entry is represented by an instance of the following
** structure. Unless SQLITE_PCACHE_SEPARATE_HEADER is defined, a buffer of
-** PgHdr1.pCache->szPage bytes is allocated directly before this structure
+** PgHdr1.pCache->szPage bytes is allocated directly before this structure
** in memory.
+**
+** Note: Variables isBulkLocal and isAnchor were once type "u8". That works,
+** but causes a 2-byte gap in the structure for most architectures (since
+** pointers must be either 4 or 8-byte aligned). As this structure is located
+** in memory directly after the associated page data, if the database is
+** corrupt, code at the b-tree layer may overread the page buffer and
+** read part of this structure before the corruption is detected. This
+** can cause a valgrind error if the unitialized gap is accessed. Using u16
+** ensures there is no such gap, and therefore no bytes of unitialized memory
+** in the structure.
*/
struct PgHdr1 {
sqlite3_pcache_page page; /* Base class. Must be first. pBuf & pExtra */
unsigned int iKey; /* Key value (page number) */
- u8 isBulkLocal; /* This page from bulk local storage */
- u8 isAnchor; /* This is the PGroup.lru element */
+ u16 isBulkLocal; /* This page from bulk local storage */
+ u16 isAnchor; /* This is the PGroup.lru element */
PgHdr1 *pNext; /* Next in hash table chain */
PCache1 *pCache; /* Cache that currently owns this page */
PgHdr1 *pLruNext; /* Next in LRU list of unpinned pages */
PgHdr1 *pLruPrev; /* Previous in LRU list of unpinned pages */
+ /* NB: pLruPrev is only valid if pLruNext!=0 */
};
/*
-** A page is pinned if it is no on the LRU list
+** A page is pinned if it is not on the LRU list. To be "pinned" means
+** that the page is in active use and must not be deallocated.
*/
#define PAGE_IS_PINNED(p) ((p)->pLruNext==0)
#define PAGE_IS_UNPINNED(p) ((p)->pLruNext!=0)
-/* Each page cache (or PCache) belongs to a PGroup. A PGroup is a set
+/* Each page cache (or PCache) belongs to a PGroup. A PGroup is a set
** of one or more PCaches that are able to recycle each other's unpinned
** pages when they are under memory pressure. A PGroup is an instance of
** the following object.
@@ -48312,13 +50857,13 @@ struct PGroup {
** temporary or transient database) has a single page cache which
** is an instance of this object.
**
-** 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) and the pnPurgeable pointer are all set when the
- ** cache is created and are never changed thereafter. nMax may be
+ ** cache is created and are never changed thereafter. nMax may be
** modified at any time by a call to the pcache1Cachesize() method.
** The PGroup mutex must be held when accessing nMax.
*/
@@ -48332,6 +50877,7 @@ struct PCache1 {
unsigned int nMax; /* Configured "cache_size" value */
unsigned int n90pct; /* nMax*9/10 */
unsigned int iMaxKey; /* Largest key seen since xTruncate() */
+ unsigned int nPurgeableDummy; /* pnPurgeable points here when not used*/
/* Hash table of all pages. The following variables may only be accessed
** when the accessor is holding the PGroup mutex.
@@ -48365,7 +50911,7 @@ static SQLITE_WSD struct PCacheGlobal {
*/
int isInit; /* True if initialized */
int separateCache; /* Use a new PGroup for each PCache */
- int nInitPage; /* Initial bulk allocation size */
+ int nInitPage; /* Initial bulk allocation size */
int szSlot; /* Size of each free slot */
int nSlot; /* The number of pcache slots */
int nReserve; /* Try to keep nFreeSlot above this */
@@ -48406,7 +50952,7 @@ static SQLITE_WSD struct PCacheGlobal {
/*
-** 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.
@@ -48466,6 +51012,7 @@ static int pcache1InitBulk(PCache1 *pCache){
pX->isBulkLocal = 1;
pX->isAnchor = 0;
pX->pNext = pCache->pFree;
+ pX->pLruPrev = 0; /* Initializing this saves a valgrind error */
pCache->pFree = pX;
zBulk += pCache->szAlloc;
}while( --nBulk );
@@ -48475,8 +51022,8 @@ static int pcache1InitBulk(PCache1 *pCache){
/*
** 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().
**
** Multiple threads can run this routine at the same time. Global variables
@@ -48576,13 +51123,14 @@ static PgHdr1 *pcache1AllocPage(PCache1 *pCache, int benignMalloc){
assert( sqlite3_mutex_held(pCache->pGroup->mutex) );
if( pCache->pFree || (pCache->nPage==0 && pcache1InitBulk(pCache)) ){
+ assert( pCache->pFree!=0 );
p = pCache->pFree;
pCache->pFree = p->pNext;
p->pNext = 0;
}else{
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
/* The group mutex must be released before pcache1Alloc() is called. This
- ** is because it might call sqlite3_release_memory(), which assumes that
+ ** is because it might call sqlite3_release_memory(), which assumes that
** this mutex is not held. */
assert( pcache1.separateCache==0 );
assert( pCache->pGroup==&pcache1.grp );
@@ -48599,17 +51147,20 @@ static PgHdr1 *pcache1AllocPage(PCache1 *pCache, int benignMalloc){
}
#else
pPg = pcache1Alloc(pCache->szAlloc);
- p = (PgHdr1 *)&((u8 *)pPg)[pCache->szPage];
#endif
if( benignMalloc ){ sqlite3EndBenignMalloc(); }
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
pcache1EnterMutex(pCache->pGroup);
#endif
if( pPg==0 ) return 0;
+#ifndef SQLITE_PCACHE_SEPARATE_HEADER
+ p = (PgHdr1 *)&((u8 *)pPg)[pCache->szPage];
+#endif
p->page.pBuf = pPg;
p->page.pExtra = &p[1];
p->isBulkLocal = 0;
p->isAnchor = 0;
+ p->pLruPrev = 0; /* Initializing this saves a valgrind error */
}
(*pCache->pnPurgeable)++;
return p;
@@ -48641,6 +51192,7 @@ static void pcache1FreePage(PgHdr1 *p){
** exists, this function falls back to sqlite3Malloc().
*/
SQLITE_PRIVATE void *sqlite3PageMalloc(int sz){
+ assert( sz<=65536+8 ); /* These allocations are never very large */
return pcache1Alloc(sz);
}
@@ -48720,7 +51272,7 @@ static void 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
** PGroup LRU list, if is part of it. If pPage is not part of the PGroup
** LRU list, then this function is a no-op.
**
@@ -48735,7 +51287,8 @@ static PgHdr1 *pcache1PinPage(PgHdr1 *pPage){
pPage->pLruPrev->pLruNext = pPage->pLruNext;
pPage->pLruNext->pLruPrev = pPage->pLruPrev;
pPage->pLruNext = 0;
- pPage->pLruPrev = 0;
+ /* pPage->pLruPrev = 0;
+ ** No need to clear pLruPrev as it is never accessed if pLruNext is 0 */
assert( pPage->isAnchor==0 );
assert( pPage->pCache->pGroup->lru.isAnchor==1 );
pPage->pCache->nRecyclable--;
@@ -48744,7 +51297,7 @@ static PgHdr1 *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.
** Also free the page if freePage is true.
**
@@ -48787,8 +51340,8 @@ static void pcache1EnforceMaxPage(PCache1 *pCache){
}
/*
-** 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 PCache mutex must be held when this function is called.
@@ -48820,7 +51373,7 @@ static void pcache1TruncateUnsafe(
PgHdr1 **pp;
PgHdr1 *pPage;
assert( hnHash );
- pp = &pCache->apHash[h];
+ pp = &pCache->apHash[h];
while( (pPage = *pp)!=0 ){
if( pPage->iKey>=iLimit ){
pCache->nPage--;
@@ -48859,7 +51412,7 @@ static int pcache1Init(void *NotUsed){
**
** * Use a unified cache in single-threaded applications that have
** configured a start-time buffer for use as page-cache memory using
- ** sqlite3_config(SQLITE_CONFIG_PAGECACHE, pBuf, sz, N) with non-NULL
+ ** sqlite3_config(SQLITE_CONFIG_PAGECACHE, pBuf, sz, N) with non-NULL
** pBuf argument.
**
** * Otherwise use separate caches (mode-1)
@@ -48894,7 +51447,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){
@@ -48928,6 +51481,7 @@ static sqlite3_pcache *pcache1Create(int szPage, int szExtra, int bPurgeable){
}else{
pGroup = &pcache1.grp;
}
+ pcache1EnterMutex(pGroup);
if( pGroup->lru.isAnchor==0 ){
pGroup->lru.isAnchor = 1;
pGroup->lru.pLruPrev = pGroup->lru.pLruNext = &pGroup->lru;
@@ -48937,7 +51491,6 @@ static sqlite3_pcache *pcache1Create(int szPage, int szExtra, int bPurgeable){
pCache->szExtra = szExtra;
pCache->szAlloc = szPage + szExtra + ROUND8(sizeof(PgHdr1));
pCache->bPurgeable = (bPurgeable ? 1 : 0);
- pcache1EnterMutex(pGroup);
pcache1ResizeHash(pCache);
if( bPurgeable ){
pCache->nMin = 10;
@@ -48945,8 +51498,7 @@ static sqlite3_pcache *pcache1Create(int szPage, int szExtra, int bPurgeable){
pGroup->mxPinned = pGroup->nMaxPage + 10 - pGroup->nMinPage;
pCache->pnPurgeable = &pGroup->nPurgeable;
}else{
- static unsigned int dummyCurrentPage;
- pCache->pnPurgeable = &dummyCurrentPage;
+ pCache->pnPurgeable = &pCache->nPurgeableDummy;
}
pcache1LeaveMutex(pGroup);
if( pCache->nHash==0 ){
@@ -48958,7 +51510,7 @@ static sqlite3_pcache *pcache1Create(int szPage, int szExtra, int bPurgeable){
}
/*
-** Implementation of the sqlite3_pcache.xCachesize method.
+** Implementation of the sqlite3_pcache.xCachesize method.
**
** Configure the cache_size limit for a cache.
*/
@@ -48977,7 +51529,7 @@ static void pcache1Cachesize(sqlite3_pcache *p, int nMax){
}
/*
-** Implementation of the sqlite3_pcache.xShrink method.
+** Implementation of the sqlite3_pcache.xShrink method.
**
** Free up as much memory as possible.
*/
@@ -48996,7 +51548,7 @@ static void pcache1Shrink(sqlite3_pcache *p){
}
/*
-** Implementation of the sqlite3_pcache.xPagecount method.
+** Implementation of the sqlite3_pcache.xPagecount method.
*/
static int pcache1Pagecount(sqlite3_pcache *p){
int n;
@@ -49017,8 +51569,8 @@ static int pcache1Pagecount(sqlite3_pcache *p){
** for these steps, the main pcache1Fetch() procedure can run faster.
*/
static SQLITE_NOINLINE PgHdr1 *pcache1FetchStage2(
- PCache1 *pCache,
- unsigned int iKey,
+ PCache1 *pCache,
+ unsigned int iKey,
int createFlag
){
unsigned int nPinned;
@@ -49060,8 +51612,8 @@ static SQLITE_NOINLINE PgHdr1 *pcache1FetchStage2(
}
}
- /* 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, createFlag==1);
@@ -49073,8 +51625,9 @@ static SQLITE_NOINLINE PgHdr1 *pcache1FetchStage2(
pPage->iKey = iKey;
pPage->pNext = pCache->apHash[h];
pPage->pCache = pCache;
- pPage->pLruPrev = 0;
pPage->pLruNext = 0;
+ /* pPage->pLruPrev = 0;
+ ** No need to clear pLruPrev since it is not accessed when pLruNext==0 */
*(void **)pPage->page.pExtra = 0;
pCache->apHash[h] = pPage;
if( iKey>pCache->iMaxKey ){
@@ -49085,13 +51638,13 @@ static SQLITE_NOINLINE PgHdr1 *pcache1FetchStage2(
}
/*
-** 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
@@ -49102,7 +51655,7 @@ static SQLITE_NOINLINE PgHdr1 *pcache1FetchStage2(
** 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
@@ -49116,13 +51669,13 @@ static SQLITE_NOINLINE PgHdr1 *pcache1FetchStage2(
** 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
+** the sum of nMax for all purgeable caches, less the sum of
** nMin for all other purgeable caches, or
**
** 4. If none of the first three conditions apply and the cache is marked
** as purgeable, and if one of the following is true:
**
-** (a) The number of pages allocated for the cache is already
+** (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
@@ -49134,7 +51687,7 @@ static SQLITE_NOINLINE PgHdr1 *pcache1FetchStage2(
**
** 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.
**
@@ -49144,8 +51697,8 @@ static SQLITE_NOINLINE PgHdr1 *pcache1FetchStage2(
** invokes the appropriate routine.
*/
static PgHdr1 *pcache1FetchNoMutex(
- sqlite3_pcache *p,
- unsigned int iKey,
+ sqlite3_pcache *p,
+ unsigned int iKey,
int createFlag
){
PCache1 *pCache = (PCache1 *)p;
@@ -49174,8 +51727,8 @@ static PgHdr1 *pcache1FetchNoMutex(
}
#if PCACHE1_MIGHT_USE_GROUP_MUTEX
static PgHdr1 *pcache1FetchWithMutex(
- sqlite3_pcache *p,
- unsigned int iKey,
+ sqlite3_pcache *p,
+ unsigned int iKey,
int createFlag
){
PCache1 *pCache = (PCache1 *)p;
@@ -49189,8 +51742,8 @@ static PgHdr1 *pcache1FetchWithMutex(
}
#endif
static sqlite3_pcache_page *pcache1Fetch(
- sqlite3_pcache *p,
- unsigned int iKey,
+ sqlite3_pcache *p,
+ unsigned int iKey,
int createFlag
){
#if PCACHE1_MIGHT_USE_GROUP_MUTEX || defined(SQLITE_DEBUG)
@@ -49220,21 +51773,21 @@ static sqlite3_pcache_page *pcache1Fetch(
** Mark a page as unpinned (eligible for asynchronous recycling).
*/
static void pcache1Unpin(
- sqlite3_pcache *p,
- sqlite3_pcache_page *pPg,
+ sqlite3_pcache *p,
+ sqlite3_pcache_page *pPg,
int reuseUnlikely
){
PCache1 *pCache = (PCache1 *)p;
PgHdr1 *pPage = (PgHdr1 *)pPg;
PGroup *pGroup = pCache->pGroup;
-
+
assert( pPage->pCache==pCache );
pcache1EnterMutex(pGroup);
- /* 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 PGroup LRU list.
*/
- assert( pPage->pLruPrev==0 && pPage->pLruNext==0 );
+ assert( pPage->pLruNext==0 );
assert( PAGE_IS_PINNED(pPage) );
if( reuseUnlikely || pGroup->nPurgeable>pGroup->nMaxPage ){
@@ -49252,7 +51805,7 @@ static void pcache1Unpin(
}
/*
-** Implementation of the sqlite3_pcache.xRekey method.
+** Implementation of the sqlite3_pcache.xRekey method.
*/
static void pcache1Rekey(
sqlite3_pcache *p,
@@ -49263,7 +51816,7 @@ static void pcache1Rekey(
PCache1 *pCache = (PCache1 *)p;
PgHdr1 *pPage = (PgHdr1 *)pPg;
PgHdr1 **pp;
- unsigned int h;
+ unsigned int h;
assert( pPage->iKey==iOld );
assert( pPage->pCache==pCache );
@@ -49288,7 +51841,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
@@ -49305,7 +51858,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().
*/
@@ -49371,7 +51924,7 @@ SQLITE_PRIVATE sqlite3_mutex *sqlite3Pcache1Mutex(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){
@@ -49462,7 +52015,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.
**
@@ -49510,7 +52063,7 @@ SQLITE_PRIVATE void sqlite3PcacheStats(
** in the list, pLeft points to the tree, and v is unused. The
** RowSet.pForest value points to the head of this forest list.
*/
-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) */
@@ -49604,7 +52157,7 @@ SQLITE_PRIVATE void sqlite3RowSetDelete(void *pArg){
/*
** Allocate a new RowSetEntry object that is associated with the
** given RowSet. Return a pointer to the new and completely uninitialized
-** objected.
+** object.
**
** In an OOM situation, the RowSet.db->mallocFailed flag is set and this
** routine returns NULL.
@@ -49662,7 +52215,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 *rowSetEntryMerge(
@@ -49699,7 +52252,7 @@ static struct RowSetEntry *rowSetEntryMerge(
/*
** Sort all elements on the list of RowSetEntry objects into order of
** increasing v.
-*/
+*/
static struct RowSetEntry *rowSetEntrySort(struct RowSetEntry *pIn){
unsigned int i;
struct RowSetEntry *pNext, *aBucket[40];
@@ -49772,7 +52325,7 @@ static struct RowSetEntry *rowSetNDeepTree(
struct RowSetEntry *pLeft; /* Left subtree */
if( *ppList==0 ){ /*OPTIMIZATION-IF-TRUE*/
/* Prevent unnecessary deep recursion when we run out of entries */
- return 0;
+ return 0;
}
if( iDepth>1 ){ /*OPTIMIZATION-IF-TRUE*/
/* This branch causes a *balanced* tree to be generated. A valid tree
@@ -49880,7 +52433,7 @@ SQLITE_PRIVATE int sqlite3RowSetTest(RowSet *pRowSet, int iBatch, sqlite3_int64
if( p ){
struct RowSetEntry **ppPrevTree = &pRowSet->pForest;
if( (pRowSet->rsFlags & ROWSET_SORTED)==0 ){ /*OPTIMIZATION-IF-FALSE*/
- /* Only sort the current set of entiries if they need it */
+ /* Only sort the current set of entries if they need it */
p = rowSetEntrySort(p);
}
for(pTree = pRowSet->pForest; pTree; pTree=pTree->pRight){
@@ -49942,7 +52495,7 @@ SQLITE_PRIVATE int sqlite3RowSetTest(RowSet *pRowSet, int iBatch, sqlite3_int64
**
*************************************************************************
** 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
@@ -49965,8 +52518,8 @@ SQLITE_PRIVATE int sqlite3RowSetTest(RowSet *pRowSet, int iBatch, sqlite3_int64
** 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
+** 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.
*/
@@ -50005,8 +52558,8 @@ SQLITE_PRIVATE int sqlite3RowSetTest(RowSet *pRowSet, int iBatch, sqlite3_int64
#define WAL_SAVEPOINT_NDATA 4
-/* Connection to a write-ahead log (WAL) file.
-** There is one object of this type for each pager.
+/* Connection to a write-ahead log (WAL) file.
+** There is one object of this type for each pager.
*/
typedef struct Wal Wal;
@@ -50017,7 +52570,7 @@ SQLITE_PRIVATE int sqlite3WalClose(Wal *pWal, sqlite3*, int sync_flags, int, u8
/* Set the limiting size of a WAL file. */
SQLITE_PRIVATE void sqlite3WalLimit(Wal*, i64);
-/* Used by readers to open (lock) and close (unlock) a snapshot. A
+/* 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
@@ -50052,7 +52605,7 @@ SQLITE_PRIVATE int sqlite3WalSavepointUndo(Wal *pWal, u32 *aWalData);
/* Write a frame or frames to the log. */
SQLITE_PRIVATE int sqlite3WalFrames(Wal *pWal, int, PgHdr *, Pgno, int, int);
-/* Copy pages from the log to the database file */
+/* Copy pages from the log to the database file */
SQLITE_PRIVATE int sqlite3WalCheckpoint(
Wal *pWal, /* Write-ahead log connection */
sqlite3 *db, /* Check this handle's interrupt flag */
@@ -50080,7 +52633,7 @@ SQLITE_PRIVATE int sqlite3WalExclusiveMode(Wal *pWal, int op);
/* Return true if the argument is non-NULL and the WAL module is using
** heap-memory for the wal-index. Otherwise, if the argument is NULL or the
-** WAL module is using shared-memory, return false.
+** WAL module is using shared-memory, return false.
*/
SQLITE_PRIVATE int sqlite3WalHeapMemory(Wal *pWal);
@@ -50102,6 +52655,11 @@ SQLITE_PRIVATE int sqlite3WalFramesize(Wal *pWal);
/* Return the sqlite3_file object for the WAL file */
SQLITE_PRIVATE sqlite3_file *sqlite3WalFile(Wal *pWal);
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+SQLITE_PRIVATE int sqlite3WalWriteLock(Wal *pWal, int bLock);
+SQLITE_PRIVATE void sqlite3WalDb(Wal *pWal, sqlite3 *db);
+#endif
+
#endif /* ifndef SQLITE_OMIT_WAL */
#endif /* SQLITE_WAL_H */
@@ -50122,60 +52680,60 @@ SQLITE_PRIVATE sqlite3_file *sqlite3WalFile(Wal *pWal);
**
** Definition: A page of the database file is said to be "overwriteable" if
** one or more of the following are true about the page:
-**
+**
** (a) The original content of the page as it was at the beginning of
** the transaction has been written into the rollback journal and
** synced.
-**
+**
** (b) The page was a freelist leaf page at the start of the transaction.
-**
+**
** (c) The page number is greater than the largest page that existed in
** the database file at the start of the transaction.
-**
+**
** (1) A page of the database file is never overwritten unless one of the
** following are true:
-**
+**
** (a) The page and all other pages on the same sector are overwriteable.
-**
+**
** (b) The atomic page write optimization is enabled, and the entire
** transaction other than the update of the transaction sequence
** number consists of a single page change.
-**
+**
** (2) The content of a page written into the rollback journal exactly matches
** both the content in the database when the rollback journal was written
** and the content in the database at the beginning of the current
** transaction.
-**
+**
** (3) Writes to the database file are an integer multiple of the page size
** in length and are aligned on a page boundary.
-**
+**
** (4) Reads from the database file are either aligned on a page boundary and
** an integer multiple of the page size in length or are taken from the
** first 100 bytes of the database file.
-**
+**
** (5) All writes to the database file are synced prior to the rollback journal
** being deleted, truncated, or zeroed.
-**
-** (6) If a master journal file is used, then all writes to the database file
-** are synced prior to the master journal being deleted.
-**
+**
+** (6) If a super-journal file is used, then all writes to the database file
+** are synced prior to the super-journal being deleted.
+**
** Definition: Two databases (or the same database at two points it time)
** are said to be "logically equivalent" if they give the same answer to
** all queries. Note in particular the content of freelist leaf
** pages can be changed arbitrarily without affecting 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
+** of the unsynced changes to a rollback journal are removed and the
** journal is rolled back, the resulting database file will be logically
** equivalent to the database file at the beginning of the transaction.
-**
+**
** (8) When a transaction is rolled back, the xTruncate method of the VFS
** is called to restore the database file to the same size it was at
** the beginning of the transaction. (In some VFSes, the xTruncate
** method is a no-op, but that does not change the fact the SQLite will
** invoke it.)
-**
+**
** (9) Whenever the database file is modified, at least one bit in the range
** of bytes from 24 through 39 inclusive will be changed prior to releasing
** the EXCLUSIVE lock, thus signaling other connections on the same
@@ -50208,7 +52766,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
@@ -50229,7 +52787,7 @@ int sqlite3PagerTrace=1; /* True to enable tracing */
** | | |
** | V |
** |<-------WRITER_LOCKED------> ERROR
-** | | ^
+** | | ^
** | V |
** |<------WRITER_CACHEMOD-------->|
** | | |
@@ -50241,7 +52799,7 @@ int sqlite3PagerTrace=1; /* True to enable tracing */
**
**
** List of state transitions and the C [function] that performs each:
-**
+**
** OPEN -> READER [sqlite3PagerSharedLock]
** READER -> OPEN [pager_unlock]
**
@@ -50253,7 +52811,7 @@ int sqlite3PagerTrace=1; /* True to enable tracing */
**
** WRITER_*** -> ERROR [pager_error]
** ERROR -> OPEN [pager_unlock]
-**
+**
**
** OPEN:
**
@@ -50267,9 +52825,9 @@ int sqlite3PagerTrace=1; /* True to enable tracing */
**
** READER:
**
-** In this state all the requirements for reading the database in
+** In this state all the requirements for reading the database in
** rollback (non-WAL) mode are met. Unless the pager is (or recently
-** was) in exclusive-locking mode, a user-level read transaction is
+** was) in exclusive-locking mode, a user-level read transaction is
** open. The database size is known in this state.
**
** A connection running with locking_mode=normal enters this state when
@@ -50279,28 +52837,28 @@ int sqlite3PagerTrace=1; /* True to enable tracing */
** this state even after the read-transaction is closed. The only way
** a locking_mode=exclusive connection can transition from READER to OPEN
** is via the ERROR state (see below).
-**
+**
** * A read transaction may be active (but a write-transaction cannot).
** * A SHARED or greater lock is held on the database file.
-** * The dbSize variable may be trusted (even if a user-level read
+** * The dbSize variable may be trusted (even if a user-level read
** transaction is not active). The dbOrigSize and dbFileSize variables
** may not be trusted at this point.
** * If the database is a WAL database, then the WAL connection is open.
-** * Even if a read-transaction is not open, it is guaranteed that
+** * Even if a read-transaction is not open, it is guaranteed that
** there is no hot-journal in the file-system.
**
** WRITER_LOCKED:
**
** The pager moves to this state from READER when a write-transaction
-** is first opened on the database. In WRITER_LOCKED state, all locks
-** required to start a write-transaction are held, but no actual
+** is first opened on the database. In WRITER_LOCKED state, all locks
+** required to start a write-transaction are held, but no actual
** modifications to the cache or database have taken place.
**
-** In rollback mode, a RESERVED or (if the transaction was opened with
+** In rollback mode, a RESERVED or (if the transaction was opened with
** BEGIN EXCLUSIVE) EXCLUSIVE lock is obtained on the database file when
-** moving to this state, but the journal file is not written to or opened
-** to in this state. If the transaction is committed or rolled back while
-** in WRITER_LOCKED state, all that is required is to unlock the database
+** moving to this state, but the journal file is not written to or opened
+** to in this state. If the transaction is committed or rolled back while
+** in WRITER_LOCKED state, all that is required is to unlock the database
** file.
**
** IN WAL mode, WalBeginWriteTransaction() is called to lock the log file.
@@ -50308,7 +52866,7 @@ int sqlite3PagerTrace=1; /* True to enable tracing */
** is made to obtain an EXCLUSIVE lock on the database file.
**
** * A write transaction is active.
-** * If the connection is open in rollback-mode, a RESERVED or greater
+** * If the connection is open in rollback-mode, a RESERVED or greater
** lock is held on the database file.
** * If the connection is open in WAL-mode, a WAL write transaction
** is open (i.e. sqlite3WalBeginWriteTransaction() has been successfully
@@ -50327,7 +52885,7 @@ int sqlite3PagerTrace=1; /* True to enable tracing */
**
** * A write transaction is active.
** * A RESERVED or greater lock is held on the database file.
-** * The journal file is open and the first header has been written
+** * The journal file is open and the first header has been written
** to it, but the header has not been synced to disk.
** * The contents of the page cache have been modified.
**
@@ -50340,7 +52898,7 @@ int sqlite3PagerTrace=1; /* True to enable tracing */
**
** * A write transaction is active.
** * An EXCLUSIVE or greater lock is held on the database file.
-** * The journal file is open and the first header has been written
+** * The journal file is open and the first header has been written
** and synced to disk.
** * The contents of the page cache have been modified (and possibly
** written to disk).
@@ -50352,8 +52910,8 @@ int sqlite3PagerTrace=1; /* True to enable tracing */
** A rollback-mode pager changes to WRITER_FINISHED state from WRITER_DBMOD
** state after the entire transaction has been successfully written into the
** database file. In this state the transaction may be committed simply
-** by finalizing the journal file. Once in WRITER_FINISHED state, it is
-** not possible to modify the database further. At this point, the upper
+** by finalizing the journal file. Once in WRITER_FINISHED state, it is
+** not possible to modify the database further. At this point, the upper
** layer must either commit or rollback the transaction.
**
** * A write transaction is active.
@@ -50361,19 +52919,19 @@ int sqlite3PagerTrace=1; /* True to enable tracing */
** * All writing and syncing of journal and database data has finished.
** If no error occurred, all that remains is to finalize the journal to
** commit the transaction. If an error did occur, the caller will need
-** to rollback the transaction.
+** to rollback the transaction.
**
** ERROR:
**
** The ERROR state is entered when an IO or disk-full error (including
-** SQLITE_IOERR_NOMEM) occurs at a point in the code that makes it
-** difficult to be sure that the in-memory pager state (cache contents,
+** SQLITE_IOERR_NOMEM) occurs at a point in the code that makes it
+** difficult to be sure that the in-memory pager state (cache contents,
** db size etc.) are consistent with the contents of the file-system.
**
** Temporary pager files may enter the ERROR state, but in-memory pagers
** cannot.
**
-** For example, if an IO error occurs while performing a rollback,
+** For example, if an IO error occurs while performing a rollback,
** the contents of the page-cache may be left in an inconsistent state.
** At this point it would be dangerous to change back to READER state
** (as usually happens after a rollback). Any subsequent readers might
@@ -50383,13 +52941,13 @@ int sqlite3PagerTrace=1; /* True to enable tracing */
** instead of READER following such an error.
**
** Once it has entered the ERROR state, any attempt to use the pager
-** to read or write data returns an error. Eventually, once all
+** to read or write data returns an error. Eventually, once all
** outstanding transactions have been abandoned, the pager is able to
-** transition back to OPEN state, discarding the contents of the
+** transition back to OPEN state, discarding the contents of the
** page-cache and any other in-memory state at the same time. Everything
** is reloaded from disk (and, if necessary, hot-journal rollback peformed)
** when a read-transaction is next opened on the pager (transitioning
-** the pager into READER state). At that point the system has recovered
+** the pager into READER state). At that point the system has recovered
** from the error.
**
** Specifically, the pager jumps into the ERROR state if:
@@ -50405,21 +52963,21 @@ int sqlite3PagerTrace=1; /* True to enable tracing */
** memory.
**
** In other cases, the error is returned to the b-tree layer. The b-tree
-** layer then attempts a rollback operation. If the error condition
+** layer then attempts a rollback operation. If the error condition
** persists, the pager enters the ERROR state via condition (1) above.
**
** Condition (3) is necessary because it can be triggered by a read-only
** statement executed within a transaction. In this case, if the error
** code were simply returned to the user, the b-tree layer would not
** automatically attempt a rollback, as it assumes that an error in a
-** read-only statement cannot leave the pager in an internally inconsistent
+** read-only statement cannot leave the pager in an internally inconsistent
** state.
**
** * The Pager.errCode variable is set to something other than SQLITE_OK.
** * There are one or more outstanding references to pages (after the
** last reference is dropped the pager should move back to OPEN state).
** * The pager is not an in-memory pager.
-**
+**
**
** Notes:
**
@@ -50429,7 +52987,7 @@ int sqlite3PagerTrace=1; /* True to enable tracing */
**
** * Normally, a connection open in exclusive mode is never in PAGER_OPEN
** state. There are two exceptions: immediately after exclusive-mode has
-** been turned on (and before any read or write transactions are
+** been turned on (and before any read or write transactions are
** executed), and when the pager is leaving the "error state".
**
** * See also: assert_pager_state().
@@ -50443,7 +53001,7 @@ int sqlite3PagerTrace=1; /* True to enable tracing */
#define PAGER_ERROR 6
/*
-** The Pager.eLock variable is almost always set to one of the
+** The Pager.eLock variable is almost always set to one of the
** following locking-states, according to the lock currently held on
** the database file: NO_LOCK, SHARED_LOCK, RESERVED_LOCK or EXCLUSIVE_LOCK.
** This variable is kept up to date as locks are taken and released by
@@ -50458,20 +53016,20 @@ int sqlite3PagerTrace=1; /* True to enable tracing */
** to a less exclusive (lower) value than the lock that is actually held
** at the system level, but it is never set to a more exclusive value.
**
-** This is usually safe. If an xUnlock fails or appears to fail, there may
+** This is usually safe. If an xUnlock fails or appears to fail, there may
** be a few redundant xLock() calls or a lock may be held for longer than
** required, but nothing really goes wrong.
**
** The exception is when the database file is unlocked as the pager moves
-** from ERROR to OPEN state. At this point there may be a hot-journal file
+** from ERROR to OPEN state. At this point there may be a hot-journal file
** in the file-system that needs to be rolled back (as part of an OPEN->SHARED
** transition, by the same pager or any other). If the call to xUnlock()
** fails at this point and the pager is left holding an EXCLUSIVE lock, this
** can confuse the call to xCheckReservedLock() call made later as part
** of hot-journal detection.
**
-** xCheckReservedLock() is defined as returning true "if there is a RESERVED
-** lock held by this process or any others". So xCheckReservedLock may
+** xCheckReservedLock() is defined as returning true "if there is a RESERVED
+** lock held by this process or any others". So xCheckReservedLock may
** return true because the caller itself is holding an EXCLUSIVE lock (but
** doesn't know it because of a previous error in xUnlock). If this happens
** a hot-journal may be mistaken for a journal being created by an active
@@ -50482,32 +53040,18 @@ int sqlite3PagerTrace=1; /* True to enable tracing */
** database in the ERROR state, Pager.eLock is set to UNKNOWN_LOCK. It
** is only changed back to a real locking state after a successful call
** to xLock(EXCLUSIVE). Also, the code to do the OPEN->SHARED state transition
-** omits the check for a hot-journal if Pager.eLock is set to UNKNOWN_LOCK
+** omits the check for a hot-journal if Pager.eLock is set to UNKNOWN_LOCK
** lock. Instead, it assumes a hot-journal exists and obtains an EXCLUSIVE
** lock on the database file before attempting to roll it back. See function
** PagerSharedLock() for more detail.
**
-** Pager.eLock may only be set to UNKNOWN_LOCK when the pager is in
+** Pager.eLock may only be set to UNKNOWN_LOCK when the pager is in
** PAGER_OPEN state.
*/
#define UNKNOWN_LOCK (EXCLUSIVE_LOCK+1)
/*
-** A macro used for invoking the codec if there is one
-*/
-#ifdef SQLITE_HAS_CODEC
-# define CODEC1(P,D,N,X,E) \
- if( P->xCodec && P->xCodec(P->pCodec,D,N,X)==0 ){ E; }
-# define CODEC2(P,D,N,X,E,O) \
- if( P->xCodec==0 ){ O=(char*)D; }else \
- if( (O=(char*)(P->xCodec(P->pCodec,D,N,X)))==0 ){ E; }
-#else
-# define CODEC1(P,D,N,X,E) /* NO-OP */
-# define CODEC2(P,D,N,X,E,O) O=(char*)D
-#endif
-
-/*
-** 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.
@@ -50523,7 +53067,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()).
@@ -50535,6 +53079,7 @@ 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 */
+ int bTruncateOnRelease; /* If stmt journal may be truncated on RELEASE */
#ifndef SQLITE_OMIT_WAL
u32 aWalData[WAL_SAVEPOINT_NDATA]; /* WAL savepoint context */
#endif
@@ -50573,44 +53118,44 @@ 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.
**
-** setMaster
+** setSuper
**
** When PagerCommitPhaseOne() is called to commit a transaction, it may
-** (or may not) specify a master-journal name to be written into the
+** (or may not) specify a super-journal name to be written into the
** journal file before it is synced to disk.
**
-** Whether or not a journal file contains a master-journal pointer affects
-** the way in which the journal file is finalized after the transaction is
+** Whether or not a journal file contains a super-journal pointer affects
+** the way in which the journal file is finalized after the transaction is
** committed or rolled back when running in "journal_mode=PERSIST" mode.
-** If a journal file does not contain a master-journal pointer, it is
+** If a journal file does not contain a super-journal pointer, it is
** finalized by overwriting the first journal header with zeroes. If
-** it does contain a master-journal pointer the journal file is finalized
-** by truncating it to zero bytes, just as if the connection were
+** it does contain a super-journal pointer the journal file is finalized
+** by truncating it to zero bytes, just as if the connection were
** running in "journal_mode=truncate" mode.
**
-** Journal files that contain master journal pointers cannot be finalized
+** Journal files that contain super-journal pointers cannot be finalized
** simply by overwriting the first journal-header with zeroes, as the
-** master journal pointer could interfere with hot-journal rollback of any
+** super-journal pointer could interfere with hot-journal rollback of any
** subsequently interrupted transaction that reuses the journal file.
**
** The flag is cleared as soon as the journal file is finalized (either
** by PagerCommitPhaseTwo or PagerRollback). If an IO error prevents the
-** journal file from being successfully finalized, the setMaster flag
+** journal file from being successfully finalized, the setSuper flag
** is cleared anyway (and the pager will move to ERROR state).
**
** doNotSpill
@@ -50626,12 +53171,12 @@ struct PagerSavepoint {
** to allocate a new page to prevent the journal file from being written
** while it is being traversed by code in pager_playback(). The SPILLFLAG_OFF
** case is a user preference.
-**
+**
** If the SPILLFLAG_NOSYNC bit is set, writing to the database from
** pagerStress() is permitted, but syncing the journal file is not.
** This flag is set by sqlite3PagerWrite() when the file-system sector-size
** is larger than the database page-size in order to prevent a journal sync
-** from happening in between the journalling of two pages on the same sector.
+** from happening in between the journalling of two pages on the same sector.
**
** subjInMemory
**
@@ -50639,16 +53184,16 @@ struct PagerSavepoint {
** is opened as an in-memory journal file. If false, then in-memory
** sub-journals are only used for in-memory pager files.
**
-** This variable is updated by the upper layer each time a new
+** This variable is updated by the upper layer each time a new
** write-transaction is opened.
**
** dbSize, dbOrigSize, dbFileSize
**
** Variable dbSize is set to the number of pages in the database file.
** It is valid in PAGER_READER and higher states (all states except for
-** OPEN and ERROR).
+** OPEN and ERROR).
**
-** dbSize is set based on the size of the database file, which may be
+** dbSize is set based on the size of the database file, which may be
** larger than the size of the database (the value stored at offset
** 28 of the database header by the btree). If the size of the file
** is not an integer multiple of the page-size, the value stored in
@@ -50659,10 +53204,10 @@ struct PagerSavepoint {
**
** During a write-transaction, if pages with page-numbers greater than
** dbSize are modified in the cache, dbSize is updated accordingly.
-** Similarly, if the database is truncated using PagerTruncateImage(),
+** Similarly, if the database is truncated using PagerTruncateImage(),
** dbSize is updated.
**
-** Variables dbOrigSize and dbFileSize are valid in states
+** Variables dbOrigSize and dbFileSize are valid in states
** PAGER_WRITER_LOCKED and higher. dbOrigSize is a copy of the dbSize
** variable at the start of the transaction. It is used during rollback,
** and to determine whether or not pages need to be journalled before
@@ -50671,12 +53216,12 @@ struct PagerSavepoint {
** Throughout a write-transaction, dbFileSize contains the size of
** the file on disk in pages. It is set to a copy of dbSize when the
** write-transaction is first opened, and updated when VFS calls are made
-** to write or truncate the database file on disk.
+** to write or truncate the database file on disk.
**
-** The only reason the dbFileSize variable is required is to suppress
-** unnecessary calls to xTruncate() after committing a transaction. If,
-** when a transaction is committed, the dbFileSize variable indicates
-** that the database file is larger than the database image (Pager.dbSize),
+** The only reason the dbFileSize variable is required is to suppress
+** unnecessary calls to xTruncate() after committing a transaction. If,
+** when a transaction is committed, the dbFileSize variable indicates
+** that the database file is larger than the database image (Pager.dbSize),
** pager_truncate() is called. The pager_truncate() call uses xFilesize()
** to measure the database file on disk, and then truncates it if required.
** dbFileSize is not used when rolling back a transaction. In this case
@@ -50687,20 +53232,20 @@ struct PagerSavepoint {
** dbHintSize
**
** The dbHintSize variable is used to limit the number of calls made to
-** the VFS xFileControl(FCNTL_SIZE_HINT) method.
+** the VFS xFileControl(FCNTL_SIZE_HINT) method.
**
** dbHintSize is set to a copy of the dbSize variable when a
** write-transaction is opened (at the same time as dbFileSize and
** dbOrigSize). If the xFileControl(FCNTL_SIZE_HINT) method is called,
** dbHintSize is increased to the number of pages that correspond to the
-** size-hint passed to the method call. See pager_write_pagelist() for
+** size-hint passed to the method call. See pager_write_pagelist() for
** details.
**
** errCode
**
** The Pager.errCode variable is only ever used in PAGER_ERROR state. It
-** is set to zero in all other states. In PAGER_ERROR state, Pager.errCode
-** is always set to SQLITE_FULL, SQLITE_IOERR or one of the SQLITE_IOERR_XXX
+** is set to zero in all other states. In PAGER_ERROR state, Pager.errCode
+** is always set to SQLITE_FULL, SQLITE_IOERR or one of the SQLITE_IOERR_XXX
** sub-codes.
**
** syncFlags, walSyncFlags
@@ -50742,7 +53287,7 @@ struct Pager {
u8 eState; /* Pager state (OPEN, READER, WRITER_LOCKED..) */
u8 eLock; /* Current lock held on database file */
u8 changeCountDone; /* Set after incrementing the change-counter */
- u8 setMaster; /* True if a m-j name has been written to jrnl */
+ u8 setSuper; /* Super-jrnl name is written into jrnl */
u8 doNotSpill; /* Do not spill the cache when non-zero */
u8 subjInMemory; /* True to use in-memory sub-journals */
u8 bUseFetch; /* True to use xFetch() */
@@ -50791,12 +53336,6 @@ struct Pager {
#endif
void (*xReiniter)(DbPage*); /* Call this routine when reloading pages */
int (*xGet)(Pager*,Pgno,DbPage**,int); /* Routine to fetch a patch */
-#ifdef SQLITE_HAS_CODEC
- void *(*xCodec)(void*,void*,Pgno,int); /* Routine for en/decoding data */
- void (*xCodecSizeChng)(void*,int,int); /* Notify of page size changes */
- void (*xCodecFree)(void*); /* Destructor for the codec */
- void *pCodec; /* First argument to xCodec... methods */
-#endif
char *pTmpSpace; /* Pager.pageSize bytes of space for tmp use */
PCache *pPCache; /* Pointer to page cache object */
#ifndef SQLITE_OMIT_WAL
@@ -50807,7 +53346,7 @@ struct Pager {
/*
** Indexes for use with Pager.aStat[]. The Pager.aStat[] array contains
-** the values accessed by passing SQLITE_DBSTATUS_CACHE_HIT, CACHE_MISS
+** the values accessed by passing SQLITE_DBSTATUS_CACHE_HIT, CACHE_MISS
** or CACHE_WRITE to sqlite3_db_status().
*/
#define PAGER_STAT_HIT 0
@@ -50865,7 +53404,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)
@@ -50892,11 +53431,6 @@ static const unsigned char aJournalMagic[] = {
# define USEFETCH(x) 0
#endif
-/*
-** The maximum legal page number is (2^31 - 1).
-*/
-#define PAGER_MAX_PGNO 2147483647
-
/*
** The argument to this macro is a file descriptor (type sqlite3_file*).
** Return 0 if it is not open, or non-zero (but not 1) if it is.
@@ -50911,19 +53445,30 @@ static const unsigned char aJournalMagic[] = {
*/
#define isOpen(pFd) ((pFd)->pMethods!=0)
+#ifdef SQLITE_DIRECT_OVERFLOW_READ
/*
-** Return true if this pager uses a write-ahead log to read page pgno.
-** Return false if the pager reads pgno directly from the database.
+** Return true if page pgno can be read directly from the database file
+** by the b-tree layer. This is the case if:
+**
+** * the database file is open,
+** * there are no dirty pages in the cache, and
+** * the desired page is not currently in the wal file.
*/
-#if !defined(SQLITE_OMIT_WAL) && defined(SQLITE_DIRECT_OVERFLOW_READ)
-SQLITE_PRIVATE int sqlite3PagerUseWal(Pager *pPager, Pgno pgno){
- u32 iRead = 0;
- int rc;
- if( pPager->pWal==0 ) return 0;
- rc = sqlite3WalFindFrame(pPager->pWal, pgno, &iRead);
- return rc || iRead;
+SQLITE_PRIVATE int sqlite3PagerDirectReadOk(Pager *pPager, Pgno pgno){
+ if( pPager->fd->pMethods==0 ) return 0;
+ if( sqlite3PCacheIsDirty(pPager->pPCache) ) return 0;
+#ifndef SQLITE_OMIT_WAL
+ if( pPager->pWal ){
+ u32 iRead = 0;
+ int rc;
+ rc = sqlite3WalFindFrame(pPager->pWal, pgno, &iRead);
+ return (rc==SQLITE_OK && iRead==0);
+ }
+#endif
+ return 1;
}
#endif
+
#ifndef SQLITE_OMIT_WAL
# define pagerUseWal(x) ((x)->pWal!=0)
#else
@@ -50934,7 +53479,7 @@ SQLITE_PRIVATE int sqlite3PagerUseWal(Pager *pPager, Pgno pgno){
# define pagerBeginReadTransaction(z) SQLITE_OK
#endif
-#ifndef NDEBUG
+#ifndef NDEBUG
/*
** Usage:
**
@@ -50963,25 +53508,25 @@ static int assert_pager_state(Pager *p){
assert( p->tempFile==0 || p->eLock==EXCLUSIVE_LOCK );
assert( p->tempFile==0 || pPager->changeCountDone );
- /* If the useJournal flag is clear, the journal-mode must be "OFF".
+ /* If the useJournal flag is clear, the journal-mode must be "OFF".
** And if the journal-mode is "OFF", the journal file must not be open.
*/
assert( p->journalMode==PAGER_JOURNALMODE_OFF || p->useJournal );
assert( p->journalMode!=PAGER_JOURNALMODE_OFF || !isOpen(p->jfd) );
- /* Check that MEMDB implies noSync. And an in-memory journal. Since
- ** this means an in-memory pager performs no IO at all, it cannot encounter
- ** either SQLITE_IOERR or SQLITE_FULL during rollback or while finalizing
- ** a journal file. (although the in-memory journal implementation may
- ** return SQLITE_IOERR_NOMEM while the journal file is being written). It
- ** is therefore not possible for an in-memory pager to enter the ERROR
+ /* Check that MEMDB implies noSync. And an in-memory journal. Since
+ ** this means an in-memory pager performs no IO at all, it cannot encounter
+ ** either SQLITE_IOERR or SQLITE_FULL during rollback or while finalizing
+ ** a journal file. (although the in-memory journal implementation may
+ ** return SQLITE_IOERR_NOMEM while the journal file is being written). It
+ ** is therefore not possible for an in-memory pager to enter the ERROR
** state.
*/
if( MEMDB ){
assert( !isOpen(p->fd) );
assert( p->noSync );
- assert( p->journalMode==PAGER_JOURNALMODE_OFF
- || p->journalMode==PAGER_JOURNALMODE_MEMORY
+ assert( p->journalMode==PAGER_JOURNALMODE_OFF
+ || p->journalMode==PAGER_JOURNALMODE_MEMORY
);
assert( p->eState!=PAGER_ERROR && p->eState!=PAGER_OPEN );
assert( pagerUseWal(p)==0 );
@@ -51015,7 +53560,7 @@ static int assert_pager_state(Pager *p){
assert( pPager->dbSize==pPager->dbOrigSize );
assert( pPager->dbOrigSize==pPager->dbFileSize );
assert( pPager->dbOrigSize==pPager->dbHintSize );
- assert( pPager->setMaster==0 );
+ assert( pPager->setSuper==0 );
break;
case PAGER_WRITER_CACHEMOD:
@@ -51028,9 +53573,9 @@ static int assert_pager_state(Pager *p){
** to journal_mode=wal.
*/
assert( p->eLock>=RESERVED_LOCK );
- assert( isOpen(p->jfd)
- || p->journalMode==PAGER_JOURNALMODE_OFF
- || p->journalMode==PAGER_JOURNALMODE_WAL
+ assert( isOpen(p->jfd)
+ || p->journalMode==PAGER_JOURNALMODE_OFF
+ || p->journalMode==PAGER_JOURNALMODE_WAL
);
}
assert( pPager->dbOrigSize==pPager->dbFileSize );
@@ -51042,9 +53587,9 @@ static int assert_pager_state(Pager *p){
assert( pPager->errCode==SQLITE_OK );
assert( !pagerUseWal(pPager) );
assert( p->eLock>=EXCLUSIVE_LOCK );
- assert( isOpen(p->jfd)
- || p->journalMode==PAGER_JOURNALMODE_OFF
- || p->journalMode==PAGER_JOURNALMODE_WAL
+ assert( isOpen(p->jfd)
+ || p->journalMode==PAGER_JOURNALMODE_OFF
+ || p->journalMode==PAGER_JOURNALMODE_WAL
|| (sqlite3OsDeviceCharacteristics(p->fd)&SQLITE_IOCAP_BATCH_ATOMIC)
);
assert( pPager->dbOrigSize<=pPager->dbHintSize );
@@ -51054,9 +53599,9 @@ static int assert_pager_state(Pager *p){
assert( p->eLock==EXCLUSIVE_LOCK );
assert( pPager->errCode==SQLITE_OK );
assert( !pagerUseWal(pPager) );
- assert( isOpen(p->jfd)
- || p->journalMode==PAGER_JOURNALMODE_OFF
- || p->journalMode==PAGER_JOURNALMODE_WAL
+ assert( isOpen(p->jfd)
+ || p->journalMode==PAGER_JOURNALMODE_OFF
+ || p->journalMode==PAGER_JOURNALMODE_WAL
|| (sqlite3OsDeviceCharacteristics(p->fd)&SQLITE_IOCAP_BATCH_ATOMIC)
);
break;
@@ -51075,7 +53620,7 @@ static int assert_pager_state(Pager *p){
}
#endif /* ifndef NDEBUG */
-#ifdef SQLITE_DEBUG
+#ifdef SQLITE_DEBUG
/*
** Return a pointer to a human readable string in a static buffer
** containing the state of the Pager object passed as an argument. This
@@ -51145,11 +53690,7 @@ static void setGetterMethod(Pager *pPager){
if( pPager->errCode ){
pPager->xGet = getPageError;
#if SQLITE_MAX_MMAP_SIZE>0
- }else if( USEFETCH(pPager)
-#ifdef SQLITE_HAS_CODEC
- && pPager->xCodec==0
-#endif
- ){
+ }else if( USEFETCH(pPager) ){
pPager->xGet = getPageMMap;
#endif /* SQLITE_MAX_MMAP_SIZE>0 */
}else{
@@ -51174,6 +53715,9 @@ static int subjRequiresPage(PgHdr *pPg){
for(i=0; inSavepoint; i++){
p = &pPager->aSavepoint[i];
if( p->nOrig>=pgno && 0==sqlite3BitvecTestNotNull(p->pInSavepoint, pgno) ){
+ for(i=i+1; inSavepoint; i++){
+ pPager->aSavepoint[i].bTruncateOnRelease = 0;
+ }
return 1;
}
}
@@ -51227,7 +53771,7 @@ static int write32bits(sqlite3_file *fd, i64 offset, u32 val){
** succeeds, set the Pager.eLock variable to match the (attempted) new lock.
**
** Except, if Pager.eLock is set to UNKNOWN_LOCK when this function is
-** called, do not modify it. See the comment above the #define of
+** called, do not modify it. See the comment above the #define of
** UNKNOWN_LOCK for an explanation of this.
*/
static int pagerUnlockDb(Pager *pPager, int eLock){
@@ -51244,17 +53788,18 @@ static int pagerUnlockDb(Pager *pPager, int eLock){
}
IOTRACE(("UNLOCK %p %d\n", pPager, eLock))
}
+ pPager->changeCountDone = pPager->tempFile; /* ticket fb3b3024ea238d5c */
return rc;
}
/*
** Lock the database file to level eLock, which must be either SHARED_LOCK,
** RESERVED_LOCK or EXCLUSIVE_LOCK. If the caller is successful, set the
-** Pager.eLock variable to the new locking state.
+** Pager.eLock variable to the new locking state.
**
-** Except, if Pager.eLock is set to UNKNOWN_LOCK when this function is
-** called, do not modify it unless the new locking state is EXCLUSIVE_LOCK.
-** See the comment above the #define of UNKNOWN_LOCK for an explanation
+** Except, if Pager.eLock is set to UNKNOWN_LOCK when this function is
+** called, do not modify it unless the new locking state is EXCLUSIVE_LOCK.
+** See the comment above the #define of UNKNOWN_LOCK for an explanation
** of this.
*/
static int pagerLockDb(Pager *pPager, int eLock){
@@ -51281,7 +53826,7 @@ static int pagerLockDb(Pager *pPager, int eLock){
** (b) the value returned by OsSectorSize() is less than or equal
** to the page size.
**
-** If it can be used, then the value returned is the size of the journal
+** If it can be used, then the value returned is the size of the journal
** file when it contains rollback data for exactly one page.
**
** The atomic-batch-write optimization can be used if OsDeviceCharacteristics()
@@ -51372,72 +53917,73 @@ 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
-** 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.
+** This function attempts to read a super-journal file name from the
+** end of the file and, if successful, copies it into memory supplied
+** by the caller. See comments above writeSuperJournal() for the format
+** used to store a super-journal file name at the end of a journal file.
**
-** zMaster must point to a buffer of at least nMaster bytes allocated by
+** zSuper must point to a buffer of at least nSuper bytes allocated by
** the caller. This should be sqlite3_vfs.mxPathname+1 (to ensure there is
-** enough space to write the master journal name). If the master journal
-** name in the journal is longer than nMaster bytes (including a
-** nul-terminator), then this is handled as if no master journal name
+** enough space to write the super-journal name). If the super-journal
+** name in the journal is longer than nSuper bytes (including a
+** nul-terminator), then this is handled as if no super-journal name
** were present in the journal.
**
-** If a master journal file name is present at the end of the journal
-** file, then it is copied into the buffer pointed to by zMaster. A
-** nul-terminator byte is appended to the buffer following the master
-** journal file name.
+** If a super-journal file name is present at the end of the journal
+** file, then it is copied into the buffer pointed to by zSuper. A
+** nul-terminator byte is appended to the buffer following the
+** super-journal file name.
**
-** If it is determined that no master journal file name is present
-** zMaster[0] is set to 0 and SQLITE_OK returned.
+** If it is determined that no super-journal file name is present
+** zSuper[0] is set to 0 and SQLITE_OK returned.
**
** If an error occurs while reading from the journal file, an SQLite
** error code is returned.
*/
-static int readMasterJournal(sqlite3_file *pJrnl, char *zMaster, u32 nMaster){
+static int readSuperJournal(sqlite3_file *pJrnl, char *zSuper, u32 nSuper){
int rc; /* Return code */
- u32 len; /* Length in bytes of master journal name */
+ u32 len; /* Length in bytes of super-journal name */
i64 szJ; /* Total size in bytes of journal file pJrnl */
u32 cksum; /* MJ checksum value read from journal */
u32 u; /* Unsigned loop counter */
unsigned char aMagic[8]; /* A buffer to hold the magic header */
- zMaster[0] = '\0';
+ zSuper[0] = '\0';
if( SQLITE_OK!=(rc = sqlite3OsFileSize(pJrnl, &szJ))
|| szJ<16
|| SQLITE_OK!=(rc = read32bits(pJrnl, szJ-16, &len))
- || len>=nMaster
+ || len>=nSuper
|| len>szJ-16
- || len==0
+ || len==0
|| SQLITE_OK!=(rc = read32bits(pJrnl, szJ-12, &cksum))
|| SQLITE_OK!=(rc = sqlite3OsRead(pJrnl, aMagic, 8, szJ-8))
|| memcmp(aMagic, aJournalMagic, 8)
- || SQLITE_OK!=(rc = sqlite3OsRead(pJrnl, zMaster, len, szJ-16-len))
+ || SQLITE_OK!=(rc = sqlite3OsRead(pJrnl, zSuper, len, szJ-16-len))
){
return rc;
}
- /* See if the checksum matches the master journal name */
+ /* See if the checksum matches the super-journal name */
for(u=0; ujournalOff, 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:
@@ -51448,7 +53994,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;
@@ -51470,12 +54016,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.
@@ -51501,8 +54047,8 @@ static int zeroJournalHdr(Pager *pPager, int doTruncate){
rc = sqlite3OsSync(pPager->jfd, SQLITE_SYNC_DATAONLY|pPager->syncFlags);
}
- /* At this point the transaction is committed but the write lock
- ** is still held on the file. If there is a size limit configured for
+ /* 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.
@@ -51530,7 +54076,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){
@@ -51546,8 +54092,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; iinSavepoint; ii++){
@@ -51558,10 +54104,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()).
**
@@ -51580,7 +54126,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);
@@ -51588,7 +54134,7 @@ static int writeJournalHdr(Pager *pPager){
memset(zHeader, 0, sizeof(aJournalMagic)+4);
}
- /* The random check-hash initializer */
+ /* The random check-hash initializer */
sqlite3_randomness(sizeof(pPager->cksumInit), &pPager->cksumInit);
put32bits(&zHeader[sizeof(aJournalMagic)+4], pPager->cksumInit);
/* The initial database size */
@@ -51607,23 +54153,23 @@ 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&&nWritejournalHdr, nHeader))
rc = sqlite3OsWrite(pPager->jfd, zHeader, nHeader, pPager->journalOff);
@@ -51721,29 +54267,29 @@ 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.
*/
rc = sqlite3PagerSetPagesize(pPager, &iPageSize, -1);
testcase( rc!=SQLITE_OK );
- /* 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
@@ -51758,50 +54304,50 @@ static int readJournalHdr(
/*
-** Write the supplied master journal name into the journal file for pager
-** pPager at the current location. The master journal name must be the last
+** Write the supplied super-journal name into the journal file for pager
+** pPager at the current location. The super-journal name must be the last
** thing written to a journal file. If the pager is in full-sync mode, the
** journal file descriptor is advanced to the next sector boundary before
** anything is written. The format is:
**
** + 4 bytes: PAGER_MJ_PGNO.
-** + N bytes: Master journal filename in utf-8.
-** + 4 bytes: N (length of master journal name in bytes, no nul-terminator).
-** + 4 bytes: Master journal name checksum.
+** + N bytes: super-journal filename in utf-8.
+** + 4 bytes: N (length of super-journal name in bytes, no nul-terminator).
+** + 4 bytes: super-journal name checksum.
** + 8 bytes: aJournalMagic[].
**
-** The master journal page checksum is the sum of the bytes in the master
-** journal name, where each byte is interpreted as a signed 8-bit integer.
+** The super-journal page checksum is the sum of the bytes in thesuper-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 zSuper is a NULL pointer (occurs for a single database transaction),
** this call is a no-op.
*/
-static int writeMasterJournal(Pager *pPager, const char *zMaster){
+static int writeSuperJournal(Pager *pPager, const char *zSuper){
int rc; /* Return code */
- int nMaster; /* Length of string zMaster */
+ int nSuper; /* Length of string zSuper */
i64 iHdrOff; /* Offset of header in journal file */
i64 jrnlSize; /* Size of journal file on disk */
- u32 cksum = 0; /* Checksum of string zMaster */
+ u32 cksum = 0; /* Checksum of string zSuper */
- assert( pPager->setMaster==0 );
+ assert( pPager->setSuper==0 );
assert( !pagerUseWal(pPager) );
- if( !zMaster
- || pPager->journalMode==PAGER_JOURNALMODE_MEMORY
+ if( !zSuper
+ || pPager->journalMode==PAGER_JOURNALMODE_MEMORY
|| !isOpen(pPager->jfd)
){
return SQLITE_OK;
}
- pPager->setMaster = 1;
+ pPager->setSuper = 1;
assert( pPager->journalHdr <= pPager->journalOff );
- /* Calculate the length in bytes and the checksum of zMaster */
- for(nMaster=0; zMaster[nMaster]; nMaster++){
- cksum += zMaster[nMaster];
+ /* Calculate the length in bytes and the checksum of zSuper */
+ for(nSuper=0; zSuper[nSuper]; nSuper++){
+ cksum += zSuper[nSuper];
}
/* If in full-sync mode, advance to the next disk sector before writing
- ** the master journal name. This is in case the previous page written to
+ ** the super-journal name. This is in case the previous page written to
** the journal has already been synced.
*/
if( pPager->fullSync ){
@@ -51809,30 +54355,30 @@ static int writeMasterJournal(Pager *pPager, const char *zMaster){
}
iHdrOff = pPager->journalOff;
- /* Write the master journal data to the end of the journal file. If
+ /* Write the super-journal data to the end of the journal file. If
** an error occurs, return the error code to the caller.
*/
if( (0 != (rc = write32bits(pPager->jfd, iHdrOff, PAGER_MJ_PGNO(pPager))))
- || (0 != (rc = sqlite3OsWrite(pPager->jfd, zMaster, nMaster, iHdrOff+4)))
- || (0 != (rc = write32bits(pPager->jfd, iHdrOff+4+nMaster, nMaster)))
- || (0 != (rc = write32bits(pPager->jfd, iHdrOff+4+nMaster+4, cksum)))
+ || (0 != (rc = sqlite3OsWrite(pPager->jfd, zSuper, nSuper, iHdrOff+4)))
+ || (0 != (rc = write32bits(pPager->jfd, iHdrOff+4+nSuper, nSuper)))
+ || (0 != (rc = write32bits(pPager->jfd, iHdrOff+4+nSuper+4, cksum)))
|| (0 != (rc = sqlite3OsWrite(pPager->jfd, aJournalMagic, 8,
- iHdrOff+4+nMaster+8)))
+ iHdrOff+4+nSuper+8)))
){
return rc;
}
- pPager->journalOff += (nMaster+20);
+ pPager->journalOff += (nSuper+20);
- /* If the pager is in peristent-journal mode, then the physical
- ** journal-file may extend past the end of the master-journal name
- ** and 8 bytes of magic data just written to the file. This is
+ /* If the pager is in peristent-journal mode, then the physical
+ ** journal-file may extend past the end of the super-journal name
+ ** and 8 bytes of magic data just written to the file. This is
** dangerous because the code to rollback a hot-journal file
- ** will not be able to find the master-journal name to determine
- ** whether or not the journal is hot.
+ ** will not be able to find the super-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
){
@@ -51877,7 +54423,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.
*/
@@ -51906,8 +54452,8 @@ static int addToSavepointBitvecs(Pager *pPager, Pgno pgno){
** not exhibit the UNDELETABLE_WHEN_OPEN property, the journal file is
** closed (if it is open).
**
-** If the pager is in ERROR state when this function is called, the
-** contents of the pager cache are discarded before switching back to
+** If the pager is in ERROR state when this function is called, the
+** contents of the pager cache are discarded before switching back to
** the OPEN state. Regardless of whether the pager is in exclusive-mode
** or not, any journal file left in the file-system will be treated
** as a hot-journal and rolled back the next time a read-transaction
@@ -51915,9 +54461,9 @@ static int addToSavepointBitvecs(Pager *pPager, Pgno pgno){
*/
static void pager_unlock(Pager *pPager){
- assert( pPager->eState==PAGER_READER
- || pPager->eState==PAGER_OPEN
- || pPager->eState==PAGER_ERROR
+ assert( pPager->eState==PAGER_READER
+ || pPager->eState==PAGER_OPEN
+ || pPager->eState==PAGER_ERROR
);
sqlite3BitvecDestroy(pPager->pInJournal);
@@ -51964,7 +54510,6 @@ static void pager_unlock(Pager *pPager){
** code is cleared and the cache reset in the block below.
*/
assert( pPager->errCode || pPager->eState!=PAGER_ERROR );
- pPager->changeCountDone = 0;
pPager->eState = PAGER_OPEN;
}
@@ -51989,23 +54534,23 @@ static void pager_unlock(Pager *pPager){
pPager->journalOff = 0;
pPager->journalHdr = 0;
- pPager->setMaster = 0;
+ pPager->setSuper = 0;
}
/*
** This function is called whenever an IOERR or FULL error that requires
** the pager to transition into the ERROR state may ahve occurred.
-** The first argument is a pointer to the pager structure, the second
-** the error-code about to be returned by a pager API function. The
-** value returned is a copy of the second argument to this function.
+** The first argument is a pointer to the pager structure, the second
+** the error-code about to be returned by a pager API function. The
+** value returned is a copy of the second argument to this function.
**
** If the second argument is SQLITE_FULL, SQLITE_IOERR or one of the
** IOERR sub-codes, the pager enters the ERROR state and the error code
** is stored in Pager.errCode. While the pager remains in the ERROR state,
** all major API calls on the Pager will immediately return Pager.errCode.
**
-** The ERROR state indicates that the contents of the pager-cache
-** cannot be trusted. This state can be cleared by completely discarding
+** The ERROR state indicates that the contents of the pager-cache
+** cannot be trusted. This state can be cleared by completely discarding
** the contents of the pager-cache. If a transaction was active when
** the persistent error occurred, then the rollback journal may need
** to be replayed to restore the contents of the database file (as if
@@ -52053,27 +54598,27 @@ static int pagerFlushOnCommit(Pager *pPager, int bCommit){
}
/*
-** 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.
-**
+**
** This routine is never called in PAGER_ERROR state. If it is called
** in PAGER_NONE or PAGER_SHARED state and the lock held is less
** exclusive than a RESERVED lock, it is a no-op.
**
** Otherwise, any active savepoints are released.
**
-** If the journal file is open, then it is "finalized". Once a journal
-** file has been finalized it is not possible to use it to roll back a
+** 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
@@ -52093,19 +54638,19 @@ static int pagerFlushOnCommit(Pager *pPager, int bCommit){
** journalMode==PERSIST is used instead.
**
** After the journal is finalized, the pager moves to PAGER_READER state.
-** If running in non-exclusive rollback mode, the lock on the file is
+** If running in non-exclusive rollback mode, the lock on the file is
** downgraded to a SHARED_LOCK.
**
** SQLITE_OK is returned if no error occurs. If an error occurs during
** any of the IO operations to finalize the journal file or unlock the
-** database then the IO error code is returned to the user. If the
+** database then the IO error code is returned to the user. If the
** operation to finalize the journal file fails, then the code still
** tries to unlock the database file if not in exclusive mode. If the
** unlock operation fails as well, then the first error code related
** to the first error encountered (the journal finalization one) is
** returned.
*/
-static int pager_end_transaction(Pager *pPager, int hasMaster, int bCommit){
+static int pager_end_transaction(Pager *pPager, int hasSuper, int bCommit){
int rc = SQLITE_OK; /* Error code from journal finalization operation */
int rc2 = SQLITE_OK; /* Error code from db file unlock operation */
@@ -52117,9 +54662,9 @@ static int pager_end_transaction(Pager *pPager, int hasMaster, int bCommit){
** 1. After a successful hot-journal rollback, it is called with
** eState==PAGER_NONE and eLock==EXCLUSIVE_LOCK.
**
- ** 2. If a connection with locking_mode=exclusive holding an EXCLUSIVE
+ ** 2. If a connection with locking_mode=exclusive holding an EXCLUSIVE
** lock switches back to locking_mode=normal and then executes a
- ** read-transaction, this function is called with eState==PAGER_READER
+ ** read-transaction, this function is called with eState==PAGER_READER
** and eLock==EXCLUSIVE_LOCK when the read-transaction is closed.
*/
assert( assert_pager_state(pPager) );
@@ -52129,7 +54674,7 @@ static int pager_end_transaction(Pager *pPager, int hasMaster, int bCommit){
}
releaseAllSavepoints(pPager);
- assert( isOpen(pPager->jfd) || pPager->pInJournal==0
+ assert( isOpen(pPager->jfd) || pPager->pInJournal==0
|| (sqlite3OsDeviceCharacteristics(pPager->fd)&SQLITE_IOCAP_BATCH_ATOMIC)
);
if( isOpen(pPager->jfd) ){
@@ -52157,7 +54702,7 @@ static int pager_end_transaction(Pager *pPager, int hasMaster, int bCommit){
}else if( pPager->journalMode==PAGER_JOURNALMODE_PERSIST
|| (pPager->exclusiveMode && pPager->journalMode!=PAGER_JOURNALMODE_WAL)
){
- rc = zeroJournalHdr(pPager, hasMaster||pPager->tempFile);
+ rc = zeroJournalHdr(pPager, hasSuper||pPager->tempFile);
pPager->journalOff = 0;
}else{
/* This branch may be executed with Pager.journalMode==MEMORY if
@@ -52167,9 +54712,9 @@ static int pager_end_transaction(Pager *pPager, int hasMaster, int bCommit){
*/
int bDelete = !pPager->tempFile;
assert( sqlite3JournalIsInMemory(pPager->jfd)==0 );
- assert( pPager->journalMode==PAGER_JOURNALMODE_DELETE
- || pPager->journalMode==PAGER_JOURNALMODE_MEMORY
- || pPager->journalMode==PAGER_JOURNALMODE_WAL
+ assert( pPager->journalMode==PAGER_JOURNALMODE_DELETE
+ || pPager->journalMode==PAGER_JOURNALMODE_MEMORY
+ || pPager->journalMode==PAGER_JOURNALMODE_WAL
);
sqlite3OsClose(pPager->jfd);
if( bDelete ){
@@ -52202,8 +54747,8 @@ static int pager_end_transaction(Pager *pPager, int hasMaster, int bCommit){
}
if( pagerUseWal(pPager) ){
- /* Drop the WAL write-lock, if any. Also, if the connection was in
- ** locking_mode=exclusive mode but is no longer, drop the EXCLUSIVE
+ /* Drop the WAL write-lock, if any. Also, if the connection was in
+ ** locking_mode=exclusive mode but is no longer, drop the EXCLUSIVE
** lock held on the database file.
*/
rc2 = sqlite3WalEndWriteTransaction(pPager->pWal);
@@ -52211,7 +54756,7 @@ static int pager_end_transaction(Pager *pPager, int hasMaster, int bCommit){
}else if( rc==SQLITE_OK && bCommit && pPager->dbFileSize>pPager->dbSize ){
/* This branch is taken when committing a transaction in rollback-journal
** mode if the database file on disk is larger than the database image.
- ** At this point the journal has been finalized and the transaction
+ ** At this point the journal has been finalized and the transaction
** successfully committed, but the EXCLUSIVE lock is still held on the
** file. So it is safe to truncate the database file to its minimum
** required size. */
@@ -52224,32 +54769,31 @@ static int pager_end_transaction(Pager *pPager, int hasMaster, int bCommit){
if( rc==SQLITE_NOTFOUND ) rc = SQLITE_OK;
}
- if( !pPager->exclusiveMode
+ if( !pPager->exclusiveMode
&& (!pagerUseWal(pPager) || sqlite3WalExclusiveMode(pPager->pWal, 0))
){
rc2 = pagerUnlockDb(pPager, SHARED_LOCK);
- pPager->changeCountDone = 0;
}
pPager->eState = PAGER_READER;
- pPager->setMaster = 0;
+ pPager->setSuper = 0;
return (rc==SQLITE_OK?rc2: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 move the pager back to OPEN state. If this
-** means that there is a hot-journal left in the file-system, the next
-** connection to obtain a shared lock on the pager (which may be this one)
+** the database file and move the pager back to OPEN state. If this
+** means that there is a hot-journal left in the file-system, the next
+** connection to obtain a shared lock on the pager (which may be this one)
** will roll it back.
**
** If the pager has not already entered the ERROR state, but an IO or
-** malloc error occurs during a rollback, then this will itself cause
+** 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.
*/
@@ -52270,10 +54814,10 @@ static void pagerUnlockAndRollback(Pager *pPager){
/*
** 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.
@@ -52281,8 +54825,8 @@ static void pagerUnlockAndRollback(Pager *pPager){
** 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.
@@ -52297,42 +54841,13 @@ static u32 pager_cksum(Pager *pPager, const u8 *aData){
return cksum;
}
-/*
-** Report the current page size and number of reserved bytes back
-** to the codec.
-*/
-#ifdef SQLITE_HAS_CODEC
-static void pagerReportSize(Pager *pPager){
- if( pPager->xCodecSizeChng ){
- pPager->xCodecSizeChng(pPager->pCodec, pPager->pageSize,
- (int)pPager->nReserve);
- }
-}
-#else
-# define pagerReportSize(X) /* No-op if we do not support a codec */
-#endif
-
-#ifdef SQLITE_HAS_CODEC
-/*
-** Make sure the number of reserved bits is the same in the destination
-** pager as it is in the source. This comes up when a VACUUM changes the
-** number of reserved bits to the "optimal" amount.
-*/
-SQLITE_PRIVATE void sqlite3PagerAlignReserve(Pager *pDest, Pager *pSrc){
- if( pDest->nReserve!=pSrc->nReserve ){
- pDest->nReserve = pSrc->nReserve;
- pagerReportSize(pDest);
- }
-}
-#endif
-
/*
** Read a single page from either the journal file (if isMainJrnl==1) or
** from the sub-journal (if isMainJrnl==0) and playback that page.
** The page begins at offset *pOffset into the file. The *pOffset
** value is increased to the start of the next page in the journal.
**
-** The main rollback journal uses checksums - the statement journal does
+** The main rollback journal uses checksums - the statement journal does
** not.
**
** If the page number of the page record read from the (sub-)journal file
@@ -52352,7 +54867,7 @@ SQLITE_PRIVATE void sqlite3PagerAlignReserve(Pager *pDest, Pager *pSrc){
** 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.
@@ -52377,11 +54892,6 @@ static int pager_playback_one_page(
char *aData; /* Temporary storage for the page */
sqlite3_file *jfd; /* The file descriptor for the journal file */
int isSynced; /* True if journal page is synced */
-#ifdef SQLITE_HAS_CODEC
- /* The jrnlEnc flag is true if Journal pages should be passed through
- ** the codec. It is false for pure in-memory journals. */
- const int jrnlEnc = (isMainJrnl || pPager->subjInMemory==0);
-#endif
assert( (isMainJrnl&~1)==0 ); /* isMainJrnl is 0 or 1 */
assert( (isSavepnt&~1)==0 ); /* isSavepnt is 0 or 1 */
@@ -52392,7 +54902,7 @@ static int pager_playback_one_page(
assert( aData ); /* Temp storage must have already been allocated */
assert( pagerUseWal(pPager)==0 || (!isMainJrnl && isSavepnt) );
- /* Either the state is greater than PAGER_WRITER_CACHEMOD (a transaction
+ /* Either the state is greater than PAGER_WRITER_CACHEMOD (a transaction
** or savepoint rollback done at the request of the caller) or this is
** a hot-journal rollback. If it is a hot-journal rollback, the pager
** is in state OPEN and holds an EXCLUSIVE lock. Hot-journal rollback
@@ -52444,7 +54954,6 @@ static int pager_playback_one_page(
*/
if( pgno==1 && pPager->nReserve!=((u8*)aData)[20] ){
pPager->nReserve = ((u8*)aData)[20];
- pagerReportSize(pPager);
}
/* If the pager is in CACHEMOD state, then there must be a copy of this
@@ -52459,7 +54968,7 @@ static int pager_playback_one_page(
** assert()able.
**
** If in WRITER_DBMOD, WRITER_FINISHED or OPEN state, then we update the
- ** pager cache if it exists and the main file. The page is then marked
+ ** pager cache if it exists and the main file. The page is then marked
** not dirty. Since this code is only executed in PAGER_OPEN state for
** a hot-journal rollback, it is guaranteed that the page-cache is empty
** if the pager is in OPEN state.
@@ -52512,43 +55021,29 @@ static int pager_playback_one_page(
** is if the data was just read from an in-memory sub-journal. In that
** case it must be encrypted here before it is copied into the database
** file. */
-#ifdef SQLITE_HAS_CODEC
- if( !jrnlEnc ){
- CODEC2(pPager, aData, pgno, 7, rc=SQLITE_NOMEM_BKPT, aData);
- rc = sqlite3OsWrite(pPager->fd, (u8 *)aData, pPager->pageSize, ofst);
- CODEC1(pPager, aData, pgno, 3, rc=SQLITE_NOMEM_BKPT);
- }else
-#endif
rc = sqlite3OsWrite(pPager->fd, (u8 *)aData, pPager->pageSize, ofst);
if( pgno>pPager->dbFileSize ){
pPager->dbFileSize = pgno;
}
if( pPager->pBackup ){
-#ifdef SQLITE_HAS_CODEC
- if( jrnlEnc ){
- CODEC1(pPager, aData, pgno, 3, rc=SQLITE_NOMEM_BKPT);
- sqlite3BackupUpdate(pPager->pBackup, pgno, (u8*)aData);
- CODEC2(pPager, aData, pgno, 7, rc=SQLITE_NOMEM_BKPT,aData);
- }else
-#endif
sqlite3BackupUpdate(pPager->pBackup, pgno, (u8*)aData);
}
}else if( !isMainJrnl && pPg==0 ){
/* If this is a rollback of a savepoint and data was not written to
** the database and the page is not in-memory, there is a potential
- ** problem. When the page is next fetched by the b-tree layer, it
- ** will be read from the database file, which may or may not be
- ** current.
+ ** 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 );
@@ -52582,164 +55077,167 @@ static int pager_playback_one_page(
if( pgno==1 ){
memcpy(&pPager->dbFileVers, &((u8*)pData)[24],sizeof(pPager->dbFileVers));
}
-
- /* Decode the page just read from disk */
-#if SQLITE_HAS_CODEC
- if( jrnlEnc ){ CODEC1(pPager, pData, pPg->pgno, 3, rc=SQLITE_NOMEM_BKPT); }
-#endif
sqlite3PcacheRelease(pPg);
}
return rc;
}
/*
-** Parameter zMaster is the name of a master journal file. A single journal
-** file that referred to the master journal file has just been rolled back.
-** This routine checks if it is possible to delete the master journal file,
+** Parameter zSuper is the name of a super-journal file. A single journal
+** file that referred to the super-journal file has just been rolled back.
+** This routine checks if it is possible to delete the super-journal file,
** and does so if it is.
**
-** Argument zMaster may point to Pager.pTmpSpace. So that buffer is not
+** Argument zSuper may point to Pager.pTmpSpace. So that buffer is not
** available for use within this function.
**
-** When a master journal file is created, it is populated with the names
-** of all of its child journals, one after another, formatted as utf-8
-** encoded text. The end of each child journal file is marked with a
-** nul-terminator byte (0x00). i.e. the entire contents of a master journal
+** When a super-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 super-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 super-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 super-journal file into
** memory and loops through each of the child journal names. For
** each child journal, it checks if:
**
** * if the child journal exists, and if so
-** * if the child journal contains a reference to master journal
-** file zMaster
+** * if the child journal contains a reference to super-journal
+** file zSuper
**
** If a child journal can be found that matches both of the criteria
** above, this function returns without doing anything. Otherwise, if
-** no such child journal can be found, file zMaster is deleted from
+** no such child journal can be found, file zSuper is deleted from
** the file-system using sqlite3OsDelete().
**
** 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
+** the entire contents of the super-journal file. This could be
+** a couple of kilobytes or so - potentially larger than the page
** size.
*/
-static int pager_delmaster(Pager *pPager, const char *zMaster){
+static int pager_delsuper(Pager *pPager, const char *zSuper){
sqlite3_vfs *pVfs = pPager->pVfs;
int rc; /* Return code */
- sqlite3_file *pMaster; /* Malloc'd master-journal file descriptor */
+ sqlite3_file *pSuper; /* Malloc'd super-journal file descriptor */
sqlite3_file *pJournal; /* Malloc'd child-journal file descriptor */
- char *zMasterJournal = 0; /* Contents of master journal file */
- i64 nMasterJournal; /* Size of master journal file */
+ char *zSuperJournal = 0; /* Contents of super-journal file */
+ i64 nSuperJournal; /* Size of super-journal file */
char *zJournal; /* Pointer to one journal within MJ file */
- char *zMasterPtr; /* Space to hold MJ filename from a journal file */
- int nMasterPtr; /* Amount of space allocated to zMasterPtr[] */
+ char *zSuperPtr; /* Space to hold super-journal filename */
+ char *zFree = 0; /* Free this buffer */
+ int nSuperPtr; /* Amount of space allocated to zSuperPtr[] */
- /* Allocate space for both the pJournal and pMaster file descriptors.
- ** If successful, open the master journal file for reading.
+ /* Allocate space for both the pJournal and pSuper file descriptors.
+ ** If successful, open the super-journal file for reading.
*/
- pMaster = (sqlite3_file *)sqlite3MallocZero(pVfs->szOsFile * 2);
- pJournal = (sqlite3_file *)(((u8 *)pMaster) + pVfs->szOsFile);
- if( !pMaster ){
+ pSuper = (sqlite3_file *)sqlite3MallocZero(pVfs->szOsFile * 2);
+ if( !pSuper ){
rc = SQLITE_NOMEM_BKPT;
+ pJournal = 0;
}else{
- const int flags = (SQLITE_OPEN_READONLY|SQLITE_OPEN_MASTER_JOURNAL);
- rc = sqlite3OsOpen(pVfs, zMaster, pMaster, flags, 0);
+ const int flags = (SQLITE_OPEN_READONLY|SQLITE_OPEN_SUPER_JOURNAL);
+ rc = sqlite3OsOpen(pVfs, zSuper, pSuper, flags, 0);
+ pJournal = (sqlite3_file *)(((u8 *)pSuper) + pVfs->szOsFile);
}
- if( rc!=SQLITE_OK ) goto delmaster_out;
+ if( rc!=SQLITE_OK ) goto delsuper_out;
- /* Load the entire master journal file into space obtained from
- ** sqlite3_malloc() and pointed to by zMasterJournal. Also obtain
- ** sufficient space (in zMasterPtr) to hold the names of master
- ** journal files extracted from regular rollback-journals.
+ /* Load the entire super-journal file into space obtained from
+ ** sqlite3_malloc() and pointed to by zSuperJournal. Also obtain
+ ** sufficient space (in zSuperPtr) to hold the names of super-journal
+ ** files extracted from regular rollback-journals.
*/
- rc = sqlite3OsFileSize(pMaster, &nMasterJournal);
- if( rc!=SQLITE_OK ) goto delmaster_out;
- nMasterPtr = pVfs->mxPathname+1;
- zMasterJournal = sqlite3Malloc(nMasterJournal + nMasterPtr + 1);
- if( !zMasterJournal ){
+ rc = sqlite3OsFileSize(pSuper, &nSuperJournal);
+ if( rc!=SQLITE_OK ) goto delsuper_out;
+ nSuperPtr = pVfs->mxPathname+1;
+ zFree = sqlite3Malloc(4 + nSuperJournal + nSuperPtr + 2);
+ if( !zFree ){
rc = SQLITE_NOMEM_BKPT;
- goto delmaster_out;
+ goto delsuper_out;
}
- zMasterPtr = &zMasterJournal[nMasterJournal+1];
- rc = sqlite3OsRead(pMaster, zMasterJournal, (int)nMasterJournal, 0);
- if( rc!=SQLITE_OK ) goto delmaster_out;
- zMasterJournal[nMasterJournal] = 0;
+ zFree[0] = zFree[1] = zFree[2] = zFree[3] = 0;
+ zSuperJournal = &zFree[4];
+ zSuperPtr = &zSuperJournal[nSuperJournal+2];
+ rc = sqlite3OsRead(pSuper, zSuperJournal, (int)nSuperJournal, 0);
+ if( rc!=SQLITE_OK ) goto delsuper_out;
+ zSuperJournal[nSuperJournal] = 0;
+ zSuperJournal[nSuperJournal+1] = 0;
- zJournal = zMasterJournal;
- while( (zJournal-zMasterJournal)pageSize bytes).
+** DBMOD or OPEN state, this function is a no-op. Otherwise, the size
+** of the file is changed to nPage pages (nPage*pPager->pageSize bytes).
** If the file on disk is currently larger than nPage pages, then use the VFS
** xTruncate() method to truncate it.
**
-** Or, it 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 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
@@ -52749,9 +55247,9 @@ static int pager_truncate(Pager *pPager, Pgno nPage){
int rc = SQLITE_OK;
assert( pPager->eState!=PAGER_ERROR );
assert( pPager->eState!=PAGER_READER );
-
- if( isOpen(pPager->fd)
- && (pPager->eState>=PAGER_WRITER_DBMOD || pPager->eState==PAGER_OPEN)
+
+ if( isOpen(pPager->fd)
+ && (pPager->eState>=PAGER_WRITER_DBMOD || pPager->eState==PAGER_OPEN)
){
i64 currentSize, newSize;
int szPage = pPager->pageSize;
@@ -52795,9 +55293,9 @@ SQLITE_PRIVATE int sqlite3SectorSize(sqlite3_file *pFile){
/*
** 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
-** to determine the size and alignment of journal header and
-** master journal pointers within created journal files.
+** of the open database file. The sector size will be used
+** to determine the size and alignment of journal header and
+** super-journal pointers within created journal files.
**
** For temporary files the effective sector size is always 512 bytes.
**
@@ -52819,7 +55317,7 @@ static void setSectorSize(Pager *pPager){
assert( isOpen(pPager->fd) || pPager->tempFile );
if( pPager->tempFile
- || (sqlite3OsDeviceCharacteristics(pPager->fd) &
+ || (sqlite3OsDeviceCharacteristics(pPager->fd) &
SQLITE_IOCAP_POWERSAFE_OVERWRITE)!=0
){
/* Sector size doesn't matter for temporary files. Also, the file
@@ -52833,15 +55331,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.
@@ -52870,7 +55368,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
@@ -52882,7 +55380,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
@@ -52896,7 +55394,7 @@ static int pager_playback(Pager *pPager, int isHot){
Pgno mxPg = 0; /* Size of the original file in pages */
int rc; /* Result code of a subroutine */
int res = 1; /* Value returned by sqlite3OsAccess() */
- char *zMaster = 0; /* Name of master journal file if any */
+ char *zSuper = 0; /* Name of super-journal file if any */
int needPagerReset; /* True to reset page prior to first page rollback */
int nPlayback = 0; /* Total number of pages restored from journal */
u32 savedPageSize = pPager->pageSize;
@@ -52910,8 +55408,8 @@ static int pager_playback(Pager *pPager, int isHot){
goto end_playback;
}
- /* Read the master journal name from the journal, if it is present.
- ** If a master journal file name is specified, but the file is not
+ /* Read the super-journal name from the journal, if it is present.
+ ** If a super-journal file name is specified, but the file is not
** present on disk, then the journal is not hot and does not need to be
** played back.
**
@@ -52921,21 +55419,21 @@ static int pager_playback(Pager *pPager, int isHot){
** mxPathname is 512, which is the same as the minimum allowable value
** for pageSize.
*/
- zMaster = pPager->pTmpSpace;
- rc = readMasterJournal(pPager->jfd, zMaster, pPager->pVfs->mxPathname+1);
- if( rc==SQLITE_OK && zMaster[0] ){
- rc = sqlite3OsAccess(pVfs, zMaster, SQLITE_ACCESS_EXISTS, &res);
+ zSuper = pPager->pTmpSpace;
+ rc = readSuperJournal(pPager->jfd, zSuper, pPager->pVfs->mxPathname+1);
+ if( rc==SQLITE_OK && zSuper[0] ){
+ rc = sqlite3OsAccess(pVfs, zSuper, SQLITE_ACCESS_EXISTS, &res);
}
- zMaster = 0;
+ zSuper = 0;
if( rc!=SQLITE_OK || !res ){
goto end_playback;
}
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 ){
/* Read the next journal header from the journal file. If there are
@@ -52944,7 +55442,7 @@ static int pager_playback(Pager *pPager, int isHot){
** 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;
}
@@ -52972,7 +55470,7 @@ 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 &&
@@ -52991,7 +55489,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; ufd,SQLITE_FCNTL_DB_UNCHANGED,0);
#endif
- /* If this playback is happening automatically as a result of an IO or
- ** malloc error that occurred after the change-counter was updated but
- ** before the transaction was committed, then the change-counter
- ** modification may just have been reverted. If this happens in exclusive
+ /* 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
@@ -53053,8 +55551,12 @@ end_playback:
pPager->changeCountDone = pPager->tempFile;
if( rc==SQLITE_OK ){
- zMaster = pPager->pTmpSpace;
- rc = readMasterJournal(pPager->jfd, zMaster, pPager->pVfs->mxPathname+1);
+ /* Leave 4 bytes of space before the super-journal filename in memory.
+ ** This is because it may end up being passed to sqlite3OsOpen(), in
+ ** which case it requires 4 0x00 bytes in memory immediately before
+ ** the filename. */
+ zSuper = &pPager->pTmpSpace[4];
+ rc = readSuperJournal(pPager->jfd, zSuper, pPager->pVfs->mxPathname+1);
testcase( rc!=SQLITE_OK );
}
if( rc==SQLITE_OK
@@ -53063,14 +55565,16 @@ end_playback:
rc = sqlite3PagerSync(pPager, 0);
}
if( rc==SQLITE_OK ){
- rc = pager_end_transaction(pPager, zMaster[0]!='\0', 0);
+ rc = pager_end_transaction(pPager, zSuper[0]!='\0', 0);
testcase( rc!=SQLITE_OK );
}
- if( rc==SQLITE_OK && zMaster[0] && res ){
- /* If there was a master journal and this routine will return success,
- ** see if it is possible to delete the master journal.
+ if( rc==SQLITE_OK && zSuper[0] && res ){
+ /* If there was a super-journal and this routine will return success,
+ ** see if it is possible to delete the super-journal.
*/
- rc = pager_delmaster(pPager, zMaster);
+ assert( zSuper==&pPager->pTmpSpace[4] );
+ memset(&zSuper[-4], 0, 4);
+ rc = pager_delsuper(pPager, zSuper);
testcase( rc!=SQLITE_OK );
}
if( isHot && nPlayback ){
@@ -53089,7 +55593,7 @@ end_playback:
/*
** Read the content for page pPg out of the database file (or out of
-** the WAL if that is where the most recent copy if found) into
+** the WAL if that is where the most recent copy if found) into
** pPg->pData. A shared lock or greater must be held on the database
** file before this function is called.
**
@@ -53145,8 +55649,6 @@ static int readDbPage(PgHdr *pPg){
memcpy(&pPager->dbFileVers, dbFileVers, sizeof(pPager->dbFileVers));
}
}
- CODEC1(pPager, pPg->pData, pPg->pgno, 3, rc = SQLITE_NOMEM_BKPT);
-
PAGER_INCR(sqlite3_pager_readdb_count);
PAGER_INCR(pPager->nRead);
IOTRACE(("PGIN %p %d\n", pPager, pPg->pgno));
@@ -53180,15 +55682,15 @@ static void pager_write_changecounter(PgHdr *pPg){
#ifndef SQLITE_OMIT_WAL
/*
-** This function is invoked once for each page that has already been
+** 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
+** 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,
+** 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){
@@ -53214,7 +55716,7 @@ static int pagerUndoCallback(void *pCtx, Pgno iPg){
** 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
+ ** 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.
*/
@@ -53231,7 +55733,7 @@ static int pagerRollbackWal(Pager *pPager){
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
+ ** been written (but not committed) to the log file, do one of the
** following:
**
** + Discard the cached page (if refcount==0), or
@@ -53253,11 +55755,11 @@ static int pagerRollbackWal(Pager *pPager){
** 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.
+** changed.
**
** The list of pages passed into this routine is always sorted by page number.
** Hence, if page 1 appears anywhere on the list, it will be the first page.
-*/
+*/
static int pagerWalFrames(
Pager *pPager, /* Pager object */
PgHdr *pList, /* List of frames to log */
@@ -53298,7 +55800,7 @@ static int pagerWalFrames(
pPager->aStat[PAGER_STAT_WRITE] += nList;
if( pList->pgno==1 ) pager_write_changecounter(pList);
- rc = sqlite3WalFrames(pPager->pWal,
+ rc = sqlite3WalFrames(pPager->pWal,
pPager->pageSize, pList, nTruncate, isCommit, pPager->walSyncFlags
);
if( rc==SQLITE_OK && pPager->pBackup ){
@@ -53413,9 +55915,9 @@ static int pagerPagecount(Pager *pPager, Pgno *pnPage){
** Return SQLITE_OK or an error code.
**
** The caller must hold a SHARED lock on the database file to call this
-** function. Because an EXCLUSIVE lock on the db file is required to delete
-** a WAL on a none-empty database, this ensures there is no race condition
-** between the xAccess() below and an xDelete() being executed by some
+** function. Because an EXCLUSIVE lock on the db file is required to delete
+** a WAL on a none-empty database, this ensures there is no race condition
+** between the xAccess() below and an xDelete() being executed by some
** other connection.
*/
static int pagerOpenWalIfPresent(Pager *pPager){
@@ -53451,21 +55953,21 @@ static int pagerOpenWalIfPresent(Pager *pPager){
/*
** 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 super-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
@@ -53481,7 +55983,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.
*/
@@ -53502,7 +56004,7 @@ 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;
@@ -53555,7 +56057,7 @@ 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));
@@ -53731,7 +56233,7 @@ SQLITE_PRIVATE void sqlite3PagerSetFlags(
/*
** 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;
@@ -53740,8 +56242,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
@@ -53773,9 +56275,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:
@@ -53787,7 +56289,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.
*/
@@ -53806,16 +56308,16 @@ SQLITE_PRIVATE void sqlite3PagerSetBusyHandler(
}
/*
-** 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, an SQLITE_IOERR_xxx sub-code 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
@@ -53825,14 +56327,14 @@ SQLITE_PRIVATE void sqlite3PagerSetBusyHandler(
**
** 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, u32 *pPageSize, int nReserve){
@@ -53842,7 +56344,7 @@ SQLITE_PRIVATE int sqlite3PagerSetPagesize(Pager *pPager, u32 *pPageSize, int nR
** function may be called from within PagerOpen(), before the state
** of the Pager object is internally consistent.
**
- ** At one point this function returned an error if the pager was in
+ ** At one point this function returned an error if the pager was in
** PAGER_ERROR state. But since PAGER_ERROR state guarantees that
** there is at least one outstanding page reference, this function
** is a no-op for that case anyhow.
@@ -53851,8 +56353,8 @@ SQLITE_PRIVATE int sqlite3PagerSetPagesize(Pager *pPager, u32 *pPageSize, int nR
u32 pageSize = *pPageSize;
assert( pageSize==0 || (pageSize>=512 && pageSize<=SQLITE_MAX_PAGE_SIZE) );
if( (pPager->memDb==0 || pPager->dbSize==0)
- && sqlite3PcacheRefCount(pPager->pPCache)==0
- && pageSize && pageSize!=(u32)pPager->pageSize
+ && sqlite3PcacheRefCount(pPager->pPCache)==0
+ && pageSize && pageSize!=(u32)pPager->pageSize
){
char *pNew = NULL; /* New temp space */
i64 nByte = 0;
@@ -53861,8 +56363,14 @@ SQLITE_PRIVATE int sqlite3PagerSetPagesize(Pager *pPager, u32 *pPageSize, int nR
rc = sqlite3OsFileSize(pPager->fd, &nByte);
}
if( rc==SQLITE_OK ){
- pNew = (char *)sqlite3PageMalloc(pageSize);
- if( !pNew ) rc = SQLITE_NOMEM_BKPT;
+ /* 8 bytes of zeroed overrun space is sufficient so that the b-tree
+ * cell header parser will never run off the end of the allocation */
+ pNew = (char *)sqlite3PageMalloc(pageSize+8);
+ if( !pNew ){
+ rc = SQLITE_NOMEM_BKPT;
+ }else{
+ memset(pNew+pageSize, 0, 8);
+ }
}
if( rc==SQLITE_OK ){
@@ -53884,7 +56392,6 @@ SQLITE_PRIVATE int sqlite3PagerSetPagesize(Pager *pPager, u32 *pPageSize, int nR
if( nReserve<0 ) nReserve = pPager->nReserve;
assert( nReserve>=0 && nReserve<1000 );
pPager->nReserve = (i16)nReserve;
- pagerReportSize(pPager);
pagerFixMaplimit(pPager);
}
return rc;
@@ -53903,18 +56410,21 @@ 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){
+SQLITE_PRIVATE Pgno sqlite3PagerMaxPageCount(Pager *pPager, Pgno mxPage){
if( mxPage>0 ){
pPager->mxPgno = mxPage;
}
assert( pPager->eState!=PAGER_OPEN ); /* Called only by OP_MaxPgcnt */
- assert( pPager->mxPgno>=pPager->dbSize ); /* OP_MaxPgcnt enforces this */
+ /* assert( pPager->mxPgno>=pPager->dbSize ); */
+ /* OP_MaxPgcnt ensures that the parameter passed to this function is not
+ ** less than the total number of valid pages in the database. But this
+ ** may be less than Pager.dbSize, and so the assert() above is not valid */
return pPager->mxPgno;
}
@@ -53944,11 +56454,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.
**
@@ -53981,7 +56491,7 @@ SQLITE_PRIVATE int sqlite3PagerReadFileheader(Pager *pPager, int N, unsigned cha
** This function may only be called when a read-transaction is open on
** the pager. It returns the total number of pages in the database.
**
-** However, if the file is between 1 and bytes in size, then
+** However, if the file is between 1 and bytes in size, then
** this is considered a 1 page file.
*/
SQLITE_PRIVATE void sqlite3PagerPagecount(Pager *pPager, int *pnPage){
@@ -53996,19 +56506,19 @@ SQLITE_PRIVATE void 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){
int rc; /* Return code */
- /* 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 transitions that the busy-handler
** may be invoked during, according to the comment above
** sqlite3PagerSetBusyhandler().
@@ -54025,10 +56535,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
@@ -54041,9 +56551,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 behavior would be to restore the current
** content of the page. However, since this content is not present in either
-** the database file or the portion of the rollback journal and
+** 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)
@@ -54059,9 +56569,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.
**
** This function is only called right before committing a transaction.
@@ -54070,17 +56580,18 @@ static void assertTruncateConstraint(Pager *pPager){
** then continue writing to the database.
*/
SQLITE_PRIVATE void sqlite3PagerTruncateImage(Pager *pPager, Pgno nPage){
- assert( pPager->dbSize>=nPage );
+ assert( pPager->dbSize>=nPage || CORRUPT_DB );
+ testcase( pPager->dbSizeeState>=PAGER_WRITER_CACHEMOD );
pPager->dbSize = nPage;
/* At one point the code here called assertTruncateConstraint() to
** ensure that all pages being truncated away by this operation are,
- ** if one or more savepoints are open, present in the savepoint
+ ** if one or more savepoints are open, present in the savepoint
** journal so that they can be restored if the savepoint is rolled
** back. This is no longer necessary as this function is now only
- ** called right before committing a transaction. So although the
- ** Pager object may still have open savepoints (Pager.nSavepoint!=0),
+ ** called right before committing a transaction. So although the
+ ** Pager object may still have open savepoints (Pager.nSavepoint!=0),
** they cannot be rolled back. So the assertTruncateConstraint() call
** is no longer correct. */
}
@@ -54092,12 +56603,12 @@ SQLITE_PRIVATE void sqlite3PagerTruncateImage(Pager *pPager, Pgno nPage){
** 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
+** 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,
+** If everything goes as planned, SQLITE_OK is returned. Otherwise,
** an SQLite error code.
*/
static int pagerSyncHotJournal(Pager *pPager){
@@ -54113,7 +56624,7 @@ static int pagerSyncHotJournal(Pager *pPager){
#if SQLITE_MAX_MMAP_SIZE>0
/*
-** Obtain a reference to a memory mapped page object for page number pgno.
+** Obtain a reference to a memory mapped page object for page number pgno.
** The new object will use the pointer pData, obtained from xFetch().
** If successful, set *ppPage to point to the new page reference
** and return SQLITE_OK. Otherwise, return an SQLite error code and set
@@ -54129,7 +56640,7 @@ static int pagerAcquireMapPage(
PgHdr **ppPage /* OUT: Acquired page object */
){
PgHdr *p; /* Memory mapped page to return */
-
+
if( pPager->pMmapFreelist ){
*ppPage = p = pPager->pMmapFreelist;
pPager->pMmapFreelist = p->pDirty;
@@ -54163,7 +56674,7 @@ static int pagerAcquireMapPage(
#endif
/*
-** Release a reference to page pPg. pPg must have been returned by an
+** Release a reference to page pPg. pPg must have been returned by an
** earlier call to pagerAcquireMapPage().
*/
static void pagerReleaseMapPage(PgHdr *pPg){
@@ -54223,7 +56734,7 @@ static int databaseIsUnmoved(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.
*/
@@ -54240,7 +56751,7 @@ SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager, sqlite3 *db){
{
u8 *a = 0;
assert( db || pPager->pWal==0 );
- if( db && 0==(db->flags & SQLITE_NoCkptOnClose)
+ if( db && 0==(db->flags & SQLITE_NoCkptOnClose)
&& SQLITE_OK==databaseIsUnmoved(pPager)
){
a = pTmp;
@@ -54254,8 +56765,8 @@ SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager, sqlite3 *db){
pager_unlock(pPager);
}else{
/* If it is open, sync the journal file before calling UnlockAndRollback.
- ** If this is not done, then an unsynced portion of the open journal
- ** file may be played back into the database. If a power failure occurs
+ ** If this is not done, then an unsynced portion of the open journal
+ ** file may be played back into the database. If a power failure occurs
** while this is happening, the database could become corrupt.
**
** If an error occurs while trying to sync the journal, shift the pager
@@ -54277,11 +56788,6 @@ SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager, sqlite3 *db){
sqlite3OsClose(pPager->fd);
sqlite3PageFree(pTmp);
sqlite3PcacheClose(pPager->pPCache);
-
-#ifdef SQLITE_HAS_CODEC
- if( pPager->xCodecFree ) pPager->xCodecFree(pPager->pCodec);
-#endif
-
assert( !pPager->aSavepoint && !pPager->pInJournal );
assert( !isOpen(pPager->jfd) && !isOpen(pPager->sjfd) );
@@ -54311,7 +56817,7 @@ SQLITE_PRIVATE void sqlite3PagerRef(DbPage *pPg){
** disk and can be restored in the event of a hot-journal rollback.
**
** If the Pager.noSync flag is set, then this function is a no-op.
-** Otherwise, the actions required depend on the journal-mode and the
+** Otherwise, the actions required depend on the journal-mode and the
** device characteristics of the file-system, as follows:
**
** * If the journal file is an in-memory journal file, no action need
@@ -54323,7 +56829,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:
@@ -54332,11 +56838,11 @@ SQLITE_PRIVATE void sqlite3PagerRef(DbPage *pPg){
** if( NOT SAFE_APPEND ){
** if( ) xSync();
**
-** }
+** }
** if( NOT SEQUENTIAL ) xSync();
** }
**
-** 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.
*/
@@ -54364,10 +56870,10 @@ static int syncJournal(Pager *pPager, int newHdr){
** 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 connection's transaction), and a crash or power-failure
+ ** occurs after nRec is updated but before this connection writes
+ ** anything else to the journal file (or commits/rolls back its
+ ** transaction), then SQLite may become confused when doing the
** hot-journal rollback following recovery. It may roll back all
** of this connections data, then proceed to rolling back the old,
** out-of-date data that follows it. Database corruption.
@@ -54377,7 +56883,7 @@ static int syncJournal(Pager *pPager, int newHdr){
** 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.
*/
@@ -54404,7 +56910,7 @@ static int syncJournal(Pager *pPager, int newHdr){
** 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.
@@ -54424,7 +56930,7 @@ static int syncJournal(Pager *pPager, int newHdr){
if( 0==(iDc&SQLITE_IOCAP_SEQUENTIAL) ){
PAGERTRACE(("SYNC journal of %d\n", PAGERID(pPager)));
IOTRACE(("JSYNC %p\n", pPager))
- rc = sqlite3OsSync(pPager->jfd, pPager->syncFlags|
+ rc = sqlite3OsSync(pPager->jfd, pPager->syncFlags|
(pPager->syncFlags==SQLITE_SYNC_FULL?SQLITE_SYNC_DATAONLY:0)
);
if( rc!=SQLITE_OK ) return rc;
@@ -54441,8 +56947,8 @@ static int syncJournal(Pager *pPager, int newHdr){
}
}
- /* Unless the pager is in noSync mode, the journal file was just
- ** successfully synced. Either way, clear the PGHDR_NEED_SYNC flag on
+ /* Unless the pager is in noSync mode, the journal file was just
+ ** successfully synced. Either way, clear the PGHDR_NEED_SYNC flag on
** all pages.
*/
sqlite3PcacheClearSyncFlags(pPager->pPCache);
@@ -54462,9 +56968,9 @@ static int syncJournal(Pager *pPager, int newHdr){
** 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,
@@ -54479,7 +56985,7 @@ static int syncJournal(Pager *pPager, int newHdr){
** 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.
*/
@@ -54505,7 +57011,7 @@ static int pager_write_pagelist(Pager *pPager, PgHdr *pList){
** file size will be.
*/
assert( rc!=SQLITE_OK || isOpen(pPager->fd) );
- if( rc==SQLITE_OK
+ if( rc==SQLITE_OK
&& pPager->dbHintSizedbSize
&& (pList->pDirty || pList->pgno>pPager->dbHintSize)
){
@@ -54527,20 +57033,19 @@ static int pager_write_pagelist(Pager *pPager, PgHdr *pList){
*/
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 */
assert( (pList->flags&PGHDR_NEED_SYNC)==0 );
if( pList->pgno==1 ) pager_write_changecounter(pList);
- /* Encode the database */
- CODEC2(pPager, pList->pData, pgno, 6, return SQLITE_NOMEM_BKPT, pData);
+ pData = pList->pData;
/* Write out the page data. */
rc = sqlite3OsWrite(pPager->fd, pData, pPager->pageSize, offset);
/* If page 1 was just written, update Pager.dbFileVers to match
- ** the value now stored in the database file. If writing this
- ** page caused the database file to grow, update dbFileSize.
+ ** 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));
@@ -54568,18 +57073,18 @@ static int pager_write_pagelist(Pager *pPager, PgHdr *pList){
}
/*
-** Ensure that the sub-journal file is open. If it is already open, this
+** Ensure that the sub-journal file is open. If it is already 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 sqlite3OsOpen()
+** 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( !isOpen(pPager->sjfd) ){
- const int flags = SQLITE_OPEN_SUBJOURNAL | SQLITE_OPEN_READWRITE
- | SQLITE_OPEN_CREATE | SQLITE_OPEN_EXCLUSIVE
+ const int flags = SQLITE_OPEN_SUBJOURNAL | SQLITE_OPEN_READWRITE
+ | SQLITE_OPEN_CREATE | SQLITE_OPEN_EXCLUSIVE
| SQLITE_OPEN_DELETEONCLOSE;
int nStmtSpill = sqlite3Config.nStmtSpill;
if( pPager->journalMode==PAGER_JOURNALMODE_MEMORY || pPager->subjInMemory ){
@@ -54591,13 +57096,13 @@ static int openSubJournal(Pager *pPager){
}
/*
-** Append a record of the current state of page pPg to the sub-journal.
+** Append a record of the current state of page pPg to the sub-journal.
**
** 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.
*/
@@ -54610,9 +57115,9 @@ static int subjournalPage(PgHdr *pPg){
assert( pPager->useJournal );
assert( isOpen(pPager->jfd) || pagerUseWal(pPager) );
assert( isOpen(pPager->sjfd) || pPager->nSubRec==0 );
- assert( pagerUseWal(pPager)
- || pageInJournal(pPager, pPg)
- || pPg->pgno>pPager->dbOrigSize
+ assert( pagerUseWal(pPager)
+ || pageInJournal(pPager, pPg)
+ || pPg->pgno>pPager->dbOrigSize
);
rc = openSubJournal(pPager);
@@ -54622,12 +57127,6 @@ static int subjournalPage(PgHdr *pPg){
void *pData = pPg->pData;
i64 offset = (i64)pPager->nSubRec*(4+pPager->pageSize);
char *pData2;
-
-#if SQLITE_HAS_CODEC
- if( !pPager->subjInMemory ){
- CODEC2(pPager, pData, pPg->pgno, 7, return SQLITE_NOMEM_BKPT, pData2);
- }else
-#endif
pData2 = pData;
PAGERTRACE(("STMT-JOURNAL %d page %d\n", PAGERID(pPager), pPg->pgno));
rc = write32bits(pPager->sjfd, offset, pPg->pgno);
@@ -54655,14 +57154,14 @@ static int subjournalPageIfRequired(PgHdr *pPg){
** 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
@@ -54687,7 +57186,7 @@ static int pagerStress(void *p, PgHdr *pPg){
** a rollback or by user request, respectively.
**
** Spilling is also prohibited when in an error state since that could
- ** lead to database corruption. In the current implementation it
+ ** lead to database corruption. In the current implementation it
** is impossible for sqlite3PcacheFetch() to be called with createFlag==3
** while in the error state, hence it is impossible for this routine to
** be called in the error state. Nevertheless, we include a NEVER()
@@ -54708,26 +57207,26 @@ static int pagerStress(void *p, PgHdr *pPg){
pPg->pDirty = 0;
if( pagerUseWal(pPager) ){
/* Write a single frame for this page to the log. */
- rc = subjournalPageIfRequired(pPg);
+ rc = subjournalPageIfRequired(pPg);
if( rc==SQLITE_OK ){
rc = pagerWalFrames(pPager, pPg, 0, 0);
}
}else{
-
+
#ifdef SQLITE_ENABLE_BATCH_ATOMIC_WRITE
if( pPager->tempFile==0 ){
rc = sqlite3JournalCreate(pPager->jfd);
if( rc!=SQLITE_OK ) return pager_error(pPager, rc);
}
#endif
-
+
/* Sync the journal file if required. */
- if( pPg->flags&PGHDR_NEED_SYNC
+ if( pPg->flags&PGHDR_NEED_SYNC
|| pPager->eState==PAGER_WRITER_CACHEMOD
){
rc = syncJournal(pPager, 1);
}
-
+
/* Write the contents of the page out to the database file. */
if( rc==SQLITE_OK ){
assert( (pPg->flags&PGHDR_NEED_SYNC)==0 );
@@ -54741,7 +57240,7 @@ static int pagerStress(void *p, PgHdr *pPg){
sqlite3PcacheMakeClean(pPg);
}
- return pager_error(pPager, rc);
+ return pager_error(pPager, rc);
}
/*
@@ -54772,8 +57271,8 @@ SQLITE_PRIVATE int sqlite3PagerFlush(Pager *pPager){
** 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
@@ -54787,13 +57286,13 @@ SQLITE_PRIVATE int sqlite3PagerFlush(Pager *pPager){
** of the PAGER_* flags.
**
** The vfsFlags parameter is a bitmask to pass to the flags parameter
-** of the xOpen() method of the supplied VFS when opening files.
+** 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(
@@ -54810,7 +57309,7 @@ SQLITE_PRIVATE int sqlite3PagerOpen(
int rc = SQLITE_OK; /* Return code */
int tempFile = 0; /* True for temp files (incl. in-memory files) */
int memDb = 0; /* True if this is an in-memory file */
-#ifdef SQLITE_ENABLE_DESERIALIZE
+#ifndef SQLITE_OMIT_DESERIALIZE
int memJM = 0; /* Memory journal mode */
#else
# define memJM 0
@@ -54823,7 +57322,8 @@ SQLITE_PRIVATE int sqlite3PagerOpen(
int pcacheSize = sqlite3PcacheSize(); /* Bytes to allocate for PCache */
u32 szPageDflt = SQLITE_DEFAULT_PAGE_SIZE; /* Default page size */
const char *zUri = 0; /* URI args to copy */
- int nUri = 0; /* Number of bytes of URI args at *zUri */
+ int nUriByte = 1; /* Number of bytes of URI args at *zUri */
+ int nUri = 0; /* Number of URI parameters */
/* Figure out how much space is required for each journal file-handle
** (there are two of them, the main journal and the sub-journal). */
@@ -54857,14 +57357,24 @@ SQLITE_PRIVATE int sqlite3PagerOpen(
}
zPathname[0] = 0; /* Make sure initialized even if FullPathname() fails */
rc = sqlite3OsFullPathname(pVfs, zFilename, nPathname, zPathname);
+ if( rc!=SQLITE_OK ){
+ if( rc==SQLITE_OK_SYMLINK ){
+ if( vfsFlags & SQLITE_OPEN_NOFOLLOW ){
+ rc = SQLITE_CANTOPEN_SYMLINK;
+ }else{
+ rc = SQLITE_OK;
+ }
+ }
+ }
nPathname = sqlite3Strlen30(zPathname);
z = zUri = &zFilename[sqlite3Strlen30(zFilename)+1];
while( *z ){
- z += sqlite3Strlen30(z)+1;
- z += sqlite3Strlen30(z)+1;
+ z += strlen(z)+1;
+ z += strlen(z)+1;
+ nUri++;
}
- nUri = (int)(&z[1] - zUri);
- assert( nUri>=0 );
+ nUriByte = (int)(&z[1] - zUri);
+ assert( nUriByte>=1 );
if( rc==SQLITE_OK && nPathname+8>pVfs->mxPathname ){
/* This branch is taken when the journal path required by
** the database being opened will be more than pVfs->mxPathname
@@ -54881,7 +57391,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)
@@ -54889,50 +57399,111 @@ SQLITE_PRIVATE int sqlite3PagerOpen(
** Database file handle (pVfs->szOsFile bytes)
** Sub-journal file handle (journalFileSize bytes)
** Main journal file handle (journalFileSize bytes)
+ ** Ptr back to the Pager (sizeof(Pager*) bytes)
+ ** \0\0\0\0 database prefix (4 bytes)
** Database file name (nPathname+1 bytes)
- ** Journal file name (nPathname+8+1 bytes)
+ ** URI query parameters (nUriByte bytes)
+ ** Journal filename (nPathname+8+1 bytes)
+ ** WAL filename (nPathname+4+1 bytes)
+ ** \0\0\0 terminator (3 bytes)
+ **
+ ** Some 3rd-party software, over which we have no control, depends on
+ ** the specific order of the filenames and the \0 separators between them
+ ** so that it can (for example) find the database filename given the WAL
+ ** filename without using the sqlite3_filename_database() API. This is a
+ ** misuse of SQLite and a bug in the 3rd-party software, but the 3rd-party
+ ** software is in widespread use, so we try to avoid changing the filename
+ ** order and formatting if possible. In particular, the details of the
+ ** filename format expected by 3rd-party software should be as follows:
+ **
+ ** - Main Database Path
+ ** - \0
+ ** - Multiple URI components consisting of:
+ ** - Key
+ ** - \0
+ ** - Value
+ ** - \0
+ ** - \0
+ ** - Journal Path
+ ** - \0
+ ** - WAL Path (zWALName)
+ ** - \0
+ **
+ ** The sqlite3_create_filename() interface and the databaseFilename() utility
+ ** that is used by sqlite3_filename_database() and kin also depend on the
+ ** specific formatting and order of the various filenames, so if the format
+ ** changes here, be sure to change it there as well.
*/
pPtr = (u8 *)sqlite3MallocZero(
- ROUND8(sizeof(*pPager)) + /* Pager structure */
- ROUND8(pcacheSize) + /* PCache object */
- ROUND8(pVfs->szOsFile) + /* The main db file */
- journalFileSize * 2 + /* The two journal files */
- nPathname + 1 + nUri + /* zFilename */
- nPathname + 8 + 2 /* zJournal */
+ ROUND8(sizeof(*pPager)) + /* Pager structure */
+ ROUND8(pcacheSize) + /* PCache object */
+ ROUND8(pVfs->szOsFile) + /* The main db file */
+ journalFileSize * 2 + /* The two journal files */
+ sizeof(pPager) + /* Space to hold a pointer */
+ 4 + /* Database prefix */
+ nPathname + 1 + /* database filename */
+ nUriByte + /* query parameters */
+ nPathname + 8 + 1 + /* Journal filename */
#ifndef SQLITE_OMIT_WAL
- + nPathname + 4 + 2 /* zWal */
+ nPathname + 4 + 1 + /* WAL filename */
#endif
+ 3 /* Terminator */
);
assert( EIGHT_BYTE_ALIGNMENT(SQLITE_INT_TO_PTR(journalFileSize)) );
if( !pPtr ){
sqlite3DbFree(0, zPathname);
return SQLITE_NOMEM_BKPT;
}
- pPager = (Pager*)(pPtr);
- pPager->pPCache = (PCache*)(pPtr += ROUND8(sizeof(*pPager)));
- pPager->fd = (sqlite3_file*)(pPtr += ROUND8(pcacheSize));
- pPager->sjfd = (sqlite3_file*)(pPtr += ROUND8(pVfs->szOsFile));
- pPager->jfd = (sqlite3_file*)(pPtr += journalFileSize);
- pPager->zFilename = (char*)(pPtr += journalFileSize);
+ pPager = (Pager*)pPtr; pPtr += ROUND8(sizeof(*pPager));
+ pPager->pPCache = (PCache*)pPtr; pPtr += ROUND8(pcacheSize);
+ pPager->fd = (sqlite3_file*)pPtr; pPtr += ROUND8(pVfs->szOsFile);
+ pPager->sjfd = (sqlite3_file*)pPtr; pPtr += journalFileSize;
+ pPager->jfd = (sqlite3_file*)pPtr; pPtr += journalFileSize;
assert( EIGHT_BYTE_ALIGNMENT(pPager->jfd) );
+ memcpy(pPtr, &pPager, sizeof(pPager)); pPtr += sizeof(pPager);
- /* Fill in the Pager.zFilename and Pager.zJournal buffers, if required. */
- if( zPathname ){
- assert( nPathname>0 );
- pPager->zJournal = (char*)(pPtr += nPathname + 1 + nUri);
- memcpy(pPager->zFilename, zPathname, nPathname);
- if( nUri ) memcpy(&pPager->zFilename[nPathname+1], zUri, nUri);
- memcpy(pPager->zJournal, zPathname, nPathname);
- memcpy(&pPager->zJournal[nPathname], "-journal\000", 8+2);
- sqlite3FileSuffix3(pPager->zFilename, pPager->zJournal);
-#ifndef SQLITE_OMIT_WAL
- pPager->zWal = &pPager->zJournal[nPathname+8+1];
- memcpy(pPager->zWal, zPathname, nPathname);
- memcpy(&pPager->zWal[nPathname], "-wal\000", 4+1);
- sqlite3FileSuffix3(pPager->zFilename, pPager->zWal);
-#endif
- sqlite3DbFree(0, zPathname);
+ /* Fill in the Pager.zFilename and pPager.zQueryParam fields */
+ pPtr += 4; /* Skip zero prefix */
+ pPager->zFilename = (char*)pPtr;
+ if( nPathname>0 ){
+ memcpy(pPtr, zPathname, nPathname); pPtr += nPathname + 1;
+ if( zUri ){
+ memcpy(pPtr, zUri, nUriByte); pPtr += nUriByte;
+ }else{
+ pPtr++;
+ }
}
+
+
+ /* Fill in Pager.zJournal */
+ if( nPathname>0 ){
+ pPager->zJournal = (char*)pPtr;
+ memcpy(pPtr, zPathname, nPathname); pPtr += nPathname;
+ memcpy(pPtr, "-journal",8); pPtr += 8 + 1;
+#ifdef SQLITE_ENABLE_8_3_NAMES
+ sqlite3FileSuffix3(zFilename,pPager->zJournal);
+ pPtr = (u8*)(pPager->zJournal + sqlite3Strlen30(pPager->zJournal)+1);
+#endif
+ }else{
+ pPager->zJournal = 0;
+ }
+
+#ifndef SQLITE_OMIT_WAL
+ /* Fill in Pager.zWal */
+ if( nPathname>0 ){
+ pPager->zWal = (char*)pPtr;
+ memcpy(pPtr, zPathname, nPathname); pPtr += nPathname;
+ memcpy(pPtr, "-wal", 4); pPtr += 4 + 1;
+#ifdef SQLITE_ENABLE_8_3_NAMES
+ sqlite3FileSuffix3(zFilename, pPager->zWal);
+ pPtr = (u8*)(pPager->zWal + sqlite3Strlen30(pPager->zWal)+1);
+#endif
+ }else{
+ pPager->zWal = 0;
+ }
+#endif
+
+ if( nPathname ) sqlite3DbFree(0, zPathname);
pPager->pVfs = pVfs;
pPager->vfsFlags = vfsFlags;
@@ -54942,7 +57513,7 @@ SQLITE_PRIVATE int sqlite3PagerOpen(
int fout = 0; /* VFS flags returned by xOpen() */
rc = sqlite3OsOpen(pVfs, pPager->zFilename, pPager->fd, vfsFlags, &fout);
assert( !memDb );
-#ifdef SQLITE_ENABLE_DESERIALIZE
+#ifndef SQLITE_OMIT_DESERIALIZE
memJM = (fout&SQLITE_OPEN_MEMORY)!=0;
#endif
readOnly = (fout&SQLITE_OPEN_READONLY)!=0;
@@ -54981,9 +57552,9 @@ SQLITE_PRIVATE int sqlite3PagerOpen(
}
#endif
}
- pPager->noLock = sqlite3_uri_boolean(zFilename, "nolock", 0);
+ pPager->noLock = sqlite3_uri_boolean(pPager->zFilename, "nolock", 0);
if( (iDc & SQLITE_IOCAP_IMMUTABLE)!=0
- || sqlite3_uri_boolean(zFilename, "immutable", 0) ){
+ || sqlite3_uri_boolean(pPager->zFilename, "immutable", 0) ){
vfsFlags |= SQLITE_OPEN_READONLY;
goto act_like_temp_file;
}
@@ -54998,7 +57569,7 @@ SQLITE_PRIVATE int sqlite3PagerOpen(
** disk and uses an in-memory rollback journal.
**
** This branch also runs for files marked as immutable.
- */
+ */
act_like_temp_file:
tempFile = 1;
pPager->eState = PAGER_READER; /* Pretend we already have a lock */
@@ -55007,7 +57578,7 @@ act_like_temp_file:
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 ){
@@ -55047,10 +57618,10 @@ act_like_temp_file:
/* pPager->state = 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;
@@ -55090,12 +57661,25 @@ act_like_temp_file:
return SQLITE_OK;
}
+/*
+** Return the sqlite3_file for the main database given the name
+** of the corresonding WAL or Journal name as passed into
+** xOpen.
+*/
+SQLITE_API sqlite3_file *sqlite3_database_file_object(const char *zName){
+ Pager *pPager;
+ while( zName[-1]!=0 || zName[-2]!=0 || zName[-3]!=0 || zName[-4]!=0 ){
+ zName--;
+ }
+ pPager = *(Pager**)(zName - 4 - sizeof(Pager*));
+ return pPager->fd;
+}
/*
** 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:
**
@@ -55110,14 +57694,14 @@ act_like_temp_file:
** just deleted using OsDelete, *pExists is set to 0 and SQLITE_OK
** is returned.
**
-** This routine does not check if there is a master journal filename
-** at the end of the file. If there is, and that master journal file
+** This routine does not check if there is a super-journal filename
+** at the end of the file. If there is, and that super-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
@@ -55145,7 +57729,7 @@ static int hasHotJournal(Pager *pPager, int *pExists){
int locked = 0; /* True if some process holds a RESERVED lock */
/* Race condition here: Another process might have been holding the
- ** the RESERVED lock and have a journal open at the sqlite3OsAccess()
+ ** 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
@@ -55178,7 +57762,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.
*/
if( !jrnlOpen ){
@@ -55228,7 +57812,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.
@@ -55239,8 +57823,8 @@ static int hasHotJournal(Pager *pPager, int *pExists){
** the contents of the page cache and rolling back any open journal
** file.
**
-** If everything is successful, SQLITE_OK is returned. If an IO error
-** occurs while locking the database, checking for a hot-journal file or
+** If everything is successful, SQLITE_OK is returned. If an IO error
+** occurs while locking the database, checking for a hot-journal file or
** rolling back a journal file, the IO error code is returned.
*/
SQLITE_PRIVATE int sqlite3PagerSharedLock(Pager *pPager){
@@ -55248,7 +57832,7 @@ SQLITE_PRIVATE int sqlite3PagerSharedLock(Pager *pPager){
/* This routine is only called from b-tree and only when there are no
** outstanding pages. This implies that the pager state should either
- ** be OPEN or READER. READER is only possible if the pager is or was in
+ ** be OPEN or READER. READER is only possible if the pager is or was in
** exclusive access mode. */
assert( sqlite3PcacheRefCount(pPager->pPCache)==0 );
assert( assert_pager_state(pPager) );
@@ -55286,12 +57870,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.
**
** Unless the pager is in locking_mode=exclusive mode, the lock is
@@ -55301,17 +57885,17 @@ SQLITE_PRIVATE int sqlite3PagerSharedLock(Pager *pPager){
if( rc!=SQLITE_OK ){
goto failed;
}
-
- /* If it is not already open and the file exists on disk, open the
- ** journal for read/write access. Write access is required because
- ** in exclusive-access mode the file descriptor will be kept open
- ** and possibly used for a transaction later on. Also, write-access
- ** is usually required to finalize the journal in journal_mode=persist
+
+ /* If it is not already open and the file exists on disk, open the
+ ** journal for read/write access. Write access is required because
+ ** in exclusive-access mode the file descriptor will be kept open
+ ** and possibly used for a transaction later on. Also, write-access
+ ** is usually required to finalize the journal in journal_mode=persist
** mode (and also for journal_mode=truncate on some systems).
**
- ** If the journal does not exist, it usually means that some
- ** other connection managed to get in and roll it back before
- ** this connection obtained the exclusive lock above. Or, it
+ ** 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.
*/
@@ -55332,7 +57916,7 @@ SQLITE_PRIVATE int sqlite3PagerSharedLock(Pager *pPager){
}
}
}
-
+
/* 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
@@ -55357,8 +57941,8 @@ SQLITE_PRIVATE int sqlite3PagerSharedLock(Pager *pPager){
** or roll back a hot-journal while holding an EXCLUSIVE lock. The
** pager_unlock() routine will be called before returning to unlock
** the file. If the unlock attempt fails, then Pager.eLock must be
- ** set to UNKNOWN_LOCK (see the comment above the #define for
- ** UNKNOWN_LOCK above for an explanation).
+ ** set to UNKNOWN_LOCK (see the comment above the #define for
+ ** UNKNOWN_LOCK above for an explanation).
**
** In order to get pager_unlock() to do this, set Pager.eState to
** PAGER_ERROR now. This is not actually counted as a transition
@@ -55366,7 +57950,7 @@ SQLITE_PRIVATE int sqlite3PagerSharedLock(Pager *pPager){
** since we know that the same call to pager_unlock() will very
** shortly transition the pager object to the OPEN state. Calling
** assert_pager_state() would fail now, as it should not be possible
- ** to be in ERROR state when there are zero outstanding page
+ ** to be in ERROR state when there are zero outstanding page
** references.
*/
pager_error(pPager, rc);
@@ -55391,8 +57975,8 @@ 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.
*/
@@ -55459,7 +58043,7 @@ 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 ){
assert( pPager->nMmapOut==0 ); /* because page1 is never memory mapped */
@@ -55469,7 +58053,7 @@ static void pagerUnlockIfUnused(Pager *pPager){
/*
** The page getter methods each try to acquire a reference to a
-** page with page number pgno. If the requested reference is
+** page with page number pgno. If the requested reference is
** successfully obtained, it is copied to *ppPage and SQLITE_OK returned.
**
** There are different implementations of the getter method depending
@@ -55479,22 +58063,22 @@ static void pagerUnlockIfUnused(Pager *pPager){
** getPageError() -- Used if the pager is in an error state
** getPageMmap() -- Used if memory-mapped I/O is enabled
**
-** 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
-** the flags parameter contains the PAGER_GET_NOCONTENT bit 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
+** the flags parameter contains the PAGER_GET_NOCONTENT bit 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 PAGER_GET_NOCONTENT is true, it means that we do not care about
** the contents of the page. This occurs in two scenarios:
@@ -55560,18 +58144,18 @@ static int getPageNormal(
if( pPg->pPager && !noContent ){
/* In this case the pcache already contains an initialized copy of
** the page. Return without further ado. */
- assert( pgno<=PAGER_MAX_PGNO && pgno!=PAGER_MJ_PGNO(pPager) );
+ assert( pgno!=PAGER_MJ_PGNO(pPager) );
pPager->aStat[PAGER_STAT_HIT]++;
return SQLITE_OK;
}else{
- /* The pager cache has created a new page. Its content needs to
+ /* The pager cache has created a new page. Its content needs to
** be initialized. But first some error checks:
**
- ** (1) The maximum page number is 2^31
+ ** (*) obsolete. Was: maximum page number is 2^31
** (2) Never try to fetch the locking page
*/
- if( pgno>PAGER_MAX_PGNO || pgno==PAGER_MJ_PGNO(pPager) ){
+ if( pgno==PAGER_MJ_PGNO(pPager) ){
rc = SQLITE_CORRUPT_BKPT;
goto pager_acquire_err;
}
@@ -55586,9 +58170,9 @@ static int getPageNormal(
}
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();
@@ -55638,16 +58222,13 @@ static int getPageMMap(
/* It is acceptable to use a read-only (mmap) page for any page except
** page 1 if there is no write-transaction open or the ACQUIRE_READONLY
- ** flag was specified by the caller. And so long as the db is not a
+ ** flag was specified by the caller. And so long as the db is not a
** temporary or in-memory database. */
const int bMmapOk = (pgno>1
&& (pPager->eState==PAGER_READER || (flags & PAGER_GET_READONLY))
);
assert( USEFETCH(pPager) );
-#ifdef SQLITE_HAS_CODEC
- assert( pPager->xCodec==0 );
-#endif
/* Optimization note: Adding the "pgno<=1" term before "pgno==0" here
** allows the compiler optimizer to reuse the results of the "pgno>1"
@@ -55670,7 +58251,7 @@ static int getPageMMap(
}
if( bMmapOk && iFrame==0 ){
void *pData = 0;
- rc = sqlite3OsFetch(pPager->fd,
+ rc = sqlite3OsFetch(pPager->fd,
(i64)(pgno-1) * pPager->pageSize, pPager->pageSize, &pData
);
if( rc==SQLITE_OK && pData ){
@@ -55726,12 +58307,12 @@ SQLITE_PRIVATE int sqlite3PagerGet(
/*
** 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.
+** or 0 if the page is not in cache.
**
** See also sqlite3PagerGet(). The difference between this routine
** and sqlite3PagerGet() is that _get() will go to the disk and read
** in the page if the page is not already in cache. This routine
-** returns NULL if the page is not in cache or if a disk I/O error
+** 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){
@@ -55778,31 +58359,30 @@ SQLITE_PRIVATE void sqlite3PagerUnrefPageOne(DbPage *pPg){
assert( pPg->pgno==1 );
assert( (pPg->flags & PGHDR_MMAP)==0 ); /* Page1 is never memory mapped */
pPager = pPg->pPager;
- sqlite3PagerResetLockTimeout(pPager);
sqlite3PcacheRelease(pPg);
pagerUnlockIfUnused(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){
@@ -55812,7 +58392,7 @@ static int pager_open_journal(Pager *pPager){
assert( pPager->eState==PAGER_WRITER_LOCKED );
assert( assert_pager_state(pPager) );
assert( pPager->pInJournal==0 );
-
+
/* If already in the error state, this function is a no-op. But on
** the other hand, this routine is never called if we are already in
** an error state. */
@@ -55823,7 +58403,7 @@ static int pager_open_journal(Pager *pPager){
if( pPager->pInJournal==0 ){
return SQLITE_NOMEM_BKPT;
}
-
+
/* Open the journal file if it is not already open. */
if( !isOpen(pPager->jfd) ){
if( pPager->journalMode==PAGER_JOURNALMODE_MEMORY ){
@@ -55839,7 +58419,7 @@ static int pager_open_journal(Pager *pPager){
flags |= SQLITE_OPEN_MAIN_JOURNAL;
nSpill = jrnlBufferSize(pPager);
}
-
+
/* Verify that the database still has the same name as it did when
** it was originally opened. */
rc = databaseIsUnmoved(pPager);
@@ -55851,16 +58431,16 @@ static int pager_open_journal(Pager *pPager){
}
assert( rc!=SQLITE_OK || isOpen(pPager->jfd) );
}
-
-
- /* 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 ){
/* TODO: Check if all of these are really required. */
pPager->nRec = 0;
pPager->journalOff = 0;
- pPager->setMaster = 0;
+ pPager->setSuper = 0;
pPager->journalHdr = 0;
rc = writeJournalHdr(pPager);
}
@@ -55878,12 +58458,12 @@ 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 the subjInMemory argument is non-zero, then any sub-journal opened
@@ -55891,7 +58471,7 @@ 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){
@@ -55901,7 +58481,7 @@ SQLITE_PRIVATE int sqlite3PagerBegin(Pager *pPager, int exFlag, int subjInMemory
assert( pPager->eState>=PAGER_READER && pPager->eStatesubjInMemory = (u8)subjInMemory;
- if( ALWAYS(pPager->eState==PAGER_READER) ){
+ if( pPager->eState==PAGER_READER ){
assert( pPager->pInJournal==0 );
if( pagerUseWal(pPager) ){
@@ -55939,9 +58519,9 @@ SQLITE_PRIVATE int sqlite3PagerBegin(Pager *pPager, int exFlag, int subjInMemory
**
** WAL mode sets Pager.eState to PAGER_WRITER_LOCKED or CACHEMOD
** when it has an open transaction, but never to DBMOD or FINISHED.
- ** This is because in those states the code to roll back savepoint
- ** transactions may copy data from the sub-journal into the database
- ** file as well as into the page cache. Which would be incorrect in
+ ** This is because in those states the code to roll back savepoint
+ ** transactions may copy data from the sub-journal into the database
+ ** file as well as into the page cache. Which would be incorrect in
** WAL mode.
*/
pPager->eState = PAGER_WRITER_LOCKED;
@@ -55976,7 +58556,7 @@ static SQLITE_NOINLINE int pagerAddPageToRollbackJournal(PgHdr *pPg){
assert( pPg->pgno!=PAGER_MJ_PGNO(pPager) );
assert( pPager->journalHdr<=pPager->journalOff );
- CODEC2(pPager, pPg->pData, pPg->pgno, 7, return SQLITE_NOMEM_BKPT, pData2);
+ pData2 = pPg->pData;
cksum = pager_cksum(pPager, (u8*)pData2);
/* Even if an IO or diskfull error occurs while journalling the
@@ -55995,11 +58575,11 @@ static SQLITE_NOINLINE int pagerAddPageToRollbackJournal(PgHdr *pPg){
rc = write32bits(pPager->jfd, iOff+pPager->pageSize+4, cksum);
if( rc!=SQLITE_OK ) return rc;
- 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)));
pPager->journalOff += 8 + pPager->pageSize;
@@ -56014,9 +58594,9 @@ static SQLITE_NOINLINE int pagerAddPageToRollbackJournal(PgHdr *pPg){
}
/*
-** 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.
*/
@@ -56024,7 +58604,7 @@ static int pager_write(PgHdr *pPg){
Pager *pPager = pPg->pPager;
int rc = SQLITE_OK;
- /* This routine is not called unless a write-transaction has already
+ /* This routine is not called unless a write-transaction has already
** been started. The journal file may or may not be open at this point.
** It is never called in the ERROR state.
*/
@@ -56041,7 +58621,7 @@ static int pager_write(PgHdr *pPg){
** obtained the necessary locks to begin the write-transaction, but the
** rollback journal might not yet be open. Open it now if this is the case.
**
- ** This is done before calling sqlite3PcacheMakeDirty() on the page.
+ ** This is done before calling sqlite3PcacheMakeDirty() on the page.
** Otherwise, if it were done after calling sqlite3PcacheMakeDirty(), then
** an error might occur and the pager would end up in WRITER_LOCKED state
** with pages marked as dirty in the cache.
@@ -56086,7 +58666,7 @@ static int pager_write(PgHdr *pPg){
** PGHDR_WRITEABLE bit that indicates that the page can be safely modified.
*/
pPg->flags |= PGHDR_WRITEABLE;
-
+
/* If the statement journal is open and the page is not in it,
** then write the page into the statement journal.
*/
@@ -56170,7 +58750,7 @@ static SQLITE_NOINLINE int pagerWriteLargeSector(PgHdr *pPg){
}
}
- /* 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
@@ -56193,9 +58773,9 @@ static SQLITE_NOINLINE int pagerWriteLargeSector(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
@@ -56246,13 +58826,13 @@ 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.
**
** This optimization cannot be used with a temp-file, as the page may
** have been dirty at the start of the transaction. In that case, if
-** memory pressure forces page pPg out of the cache, the data does need
-** to be written out to disk so that it may be read back in if the
+** memory pressure forces page pPg out of the cache, the data does need
+** to be written out to disk so that it may be read back in if the
** current transaction is rolled back.
*/
SQLITE_PRIVATE void sqlite3PagerDontWrite(PgHdr *pPg){
@@ -56268,17 +58848,17 @@ SQLITE_PRIVATE void sqlite3PagerDontWrite(PgHdr *pPg){
}
/*
-** This routine is called to increment the value of the database file
-** change-counter, stored as a 4-byte big-endian integer starting at
+** This routine is called to increment the value of the database file
+** change-counter, stored as a 4-byte big-endian integer starting at
** byte offset 24 of the pager file. The secondary change counter at
** 92 is also updated, as is the SQLite version number at offset 96.
**
** But this only happens if the pPager->changeCountDone flag is false.
** To avoid excess churning of page 1, the update only happens once.
-** See also the pager_write_changecounter() routine that does an
+** See also the pager_write_changecounter() routine that does an
** unconditional update of the change counters.
**
-** If the isDirectMode flag is zero, then this is done by calling
+** 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.
@@ -56286,7 +58866,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){
@@ -56325,7 +58905,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.
*/
@@ -56341,7 +58921,7 @@ static int pager_incr_changecounter(Pager *pPager, int isDirectMode){
if( DIRECT_MODE ){
const void *zBuf;
assert( pPager->dbFileSize>0 );
- CODEC2(pPager, pPgHdr->pData, 1, 6, rc=SQLITE_NOMEM_BKPT, zBuf);
+ zBuf = pPgHdr->pData;
if( rc==SQLITE_OK ){
rc = sqlite3OsWrite(pPager->fd, zBuf, pPager->pageSize, 0);
pPager->aStat[PAGER_STAT_WRITE]++;
@@ -56372,9 +58952,9 @@ static int pager_incr_changecounter(Pager *pPager, int isDirectMode){
** If successful, or if called on a pager for which it is a no-op, this
** function returns SQLITE_OK. Otherwise, an IO error code is returned.
*/
-SQLITE_PRIVATE int sqlite3PagerSync(Pager *pPager, const char *zMaster){
+SQLITE_PRIVATE int sqlite3PagerSync(Pager *pPager, const char *zSuper){
int rc = SQLITE_OK;
- void *pArg = (void*)zMaster;
+ void *pArg = (void*)zSuper;
rc = sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_SYNC, pArg);
if( rc==SQLITE_NOTFOUND ) rc = SQLITE_OK;
if( rc==SQLITE_OK && !pPager->noSync ){
@@ -56386,22 +58966,22 @@ SQLITE_PRIVATE int sqlite3PagerSync(Pager *pPager, const char *zMaster){
/*
** This function may only be called while a write-transaction is active in
-** rollback. If the connection is in WAL mode, this call is a no-op.
-** Otherwise, if the connection does not already have an EXCLUSIVE lock on
+** rollback. If the connection is in WAL mode, this call is a no-op.
+** Otherwise, if the connection does not already have an EXCLUSIVE lock on
** the database file, an attempt is made to obtain one.
**
** If the EXCLUSIVE lock is already held or the attempt to obtain it is
** successful, or the connection is in WAL mode, SQLITE_OK is returned.
-** Otherwise, either SQLITE_BUSY or an SQLITE_IOERR_XXX error code is
+** Otherwise, either SQLITE_BUSY or an SQLITE_IOERR_XXX error code is
** returned.
*/
SQLITE_PRIVATE int sqlite3PagerExclusiveLock(Pager *pPager){
int rc = pPager->errCode;
assert( assert_pager_state(pPager) );
if( rc==SQLITE_OK ){
- assert( pPager->eState==PAGER_WRITER_CACHEMOD
- || pPager->eState==PAGER_WRITER_DBMOD
- || pPager->eState==PAGER_WRITER_LOCKED
+ assert( pPager->eState==PAGER_WRITER_CACHEMOD
+ || pPager->eState==PAGER_WRITER_DBMOD
+ || pPager->eState==PAGER_WRITER_LOCKED
);
assert( assert_pager_state(pPager) );
if( 0==pagerUseWal(pPager) ){
@@ -56412,24 +58992,24 @@ SQLITE_PRIVATE int sqlite3PagerExclusiveLock(Pager *pPager){
}
/*
-** Sync the database file for the pager pPager. zMaster points to the name
-** of a master journal file that should be written into the individual
-** journal file. zMaster may be NULL, which is interpreted as no master
-** journal (a single database transaction).
+** Sync the database file for the pager pPager. zSuper points to the name
+** of a super-journal file that should be written into the individual
+** journal file. zSuper may be NULL, which is interpreted as no
+** super-journal (a single database transaction).
**
** This routine ensures that:
**
** * 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
-** delete the master journal file if specified).
+** 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 super-journal file if specified).
**
-** Note that if zMaster==NULL, this does not overwrite a previous value
+** Note that if zSuper==NULL, this does not overwrite a previous value
** passed to an sqlite3PagerCommitPhaseOne() call.
**
** If the final parameter - noSync - is true, then the database file itself
@@ -56439,7 +59019,7 @@ SQLITE_PRIVATE int sqlite3PagerExclusiveLock(Pager *pPager){
*/
SQLITE_PRIVATE int sqlite3PagerCommitPhaseOne(
Pager *pPager, /* Pager object */
- const char *zMaster, /* If not NULL, the master journal name */
+ const char *zSuper, /* If not NULL, the super-journal name */
int noSync /* True to omit the xSync on the db file */
){
int rc = SQLITE_OK; /* Return code */
@@ -56457,8 +59037,8 @@ SQLITE_PRIVATE int sqlite3PagerCommitPhaseOne(
/* Provide the ability to easily simulate an I/O error during testing */
if( sqlite3FaultSim(400) ) return SQLITE_IOERR;
- PAGERTRACE(("DATABASE SYNC: File=%s zMaster=%s nSize=%d\n",
- pPager->zFilename, zMaster, pPager->dbSize));
+ PAGERTRACE(("DATABASE SYNC: File=%s zSuper=%s nSize=%d\n",
+ pPager->zFilename, zSuper, pPager->dbSize));
/* If no database changes have been made, return early. */
if( pPager->eStatefd;
- int bBatch = zMaster==0 /* An SQLITE_IOCAP_BATCH_ATOMIC commit */
+ int bBatch = zSuper==0 /* An SQLITE_IOCAP_BATCH_ATOMIC commit */
&& (sqlite3OsDeviceCharacteristics(fd) & SQLITE_IOCAP_BATCH_ATOMIC)
&& !pPager->noSync
&& sqlite3JournalIsInMemory(pPager->jfd);
@@ -56508,11 +59088,11 @@ SQLITE_PRIVATE int sqlite3PagerCommitPhaseOne(
#ifdef SQLITE_ENABLE_ATOMIC_WRITE
/* 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:
+ ** 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
+ ** 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.
**
@@ -56522,7 +59102,7 @@ SQLITE_PRIVATE int sqlite3PagerCommitPhaseOne(
** 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.
+ ** mode.
**
** Otherwise, if the optimization is both enabled and applicable,
** then call pager_incr_changecounter() to update the change-counter
@@ -56531,19 +59111,19 @@ SQLITE_PRIVATE int sqlite3PagerCommitPhaseOne(
*/
if( bBatch==0 ){
PgHdr *pPg;
- assert( isOpen(pPager->jfd)
- || pPager->journalMode==PAGER_JOURNALMODE_OFF
- || pPager->journalMode==PAGER_JOURNALMODE_WAL
+ assert( isOpen(pPager->jfd)
+ || pPager->journalMode==PAGER_JOURNALMODE_OFF
+ || pPager->journalMode==PAGER_JOURNALMODE_WAL
);
- if( !zMaster && isOpen(pPager->jfd)
- && pPager->journalOff==jrnlBufferSize(pPager)
+ if( !zSuper && isOpen(pPager->jfd)
+ && pPager->journalOff==jrnlBufferSize(pPager)
&& pPager->dbSize>=pPager->dbOrigSize
&& (!(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
+ /* 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);
@@ -56556,7 +59136,7 @@ SQLITE_PRIVATE int sqlite3PagerCommitPhaseOne(
}
#else /* SQLITE_ENABLE_ATOMIC_WRITE */
#ifdef SQLITE_ENABLE_BATCH_ATOMIC_WRITE
- if( zMaster ){
+ if( zSuper ){
rc = sqlite3JournalCreate(pPager->jfd);
if( rc!=SQLITE_OK ) goto commit_phase_one_exit;
assert( bBatch==0 );
@@ -56565,24 +59145,24 @@ SQLITE_PRIVATE int sqlite3PagerCommitPhaseOne(
rc = pager_incr_changecounter(pPager, 0);
#endif /* !SQLITE_ENABLE_ATOMIC_WRITE */
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.
+
+ /* Write the super-journal name into the journal file. If a
+ ** super-journal file name has already been written to the journal file,
+ ** or if zSuper is NULL (no super-journal), then this call is a no-op.
*/
- rc = writeMasterJournal(pPager, zMaster);
+ rc = writeSuperJournal(pPager, zSuper);
if( rc!=SQLITE_OK ) goto commit_phase_one_exit;
-
+
/* Sync the journal file and write all dirty pages to the database.
- ** If the atomic-update optimization is being used, this sync will not
+ ** If the atomic-update optimization is being used, this sync will not
** create the journal file or perform any real IO.
**
** Because the change-counter page was just modified, unless the
** atomic-update optimization is used it is almost certain that the
** journal requires a sync here. However, in locking_mode=exclusive
- ** on a system under memory pressure it is just possible that this is
+ ** on a system under memory pressure it is just possible that this is
** not the case. In this case it is likely enough that the redundant
- ** xSync() call will be changed to a no-op by the OS anyhow.
+ ** xSync() call will be changed to a no-op by the OS anyhow.
*/
rc = syncJournal(pPager, 0);
if( rc!=SQLITE_OK ) goto commit_phase_one_exit;
@@ -56623,7 +59203,7 @@ SQLITE_PRIVATE int sqlite3PagerCommitPhaseOne(
}
sqlite3PcacheCleanAll(pPager->pPCache);
- /* If the file on disk is smaller than the database image, use
+ /* If the file on disk is smaller than the database image, use
** pager_truncate to grow the file here. This can happen if the database
** image was extended as part of the current transaction and then the
** last page in the db image moved to the free-list. In this case the
@@ -56635,10 +59215,10 @@ SQLITE_PRIVATE int sqlite3PagerCommitPhaseOne(
rc = pager_truncate(pPager, nNew);
if( rc!=SQLITE_OK ) goto commit_phase_one_exit;
}
-
+
/* Finally, sync the database file. */
if( !noSync ){
- rc = sqlite3PagerSync(pPager, zMaster);
+ rc = sqlite3PagerSync(pPager, zSuper);
}
IOTRACE(("DBSYNC %p\n", pPager))
}
@@ -56655,12 +59235,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.
**
@@ -56674,6 +59254,7 @@ SQLITE_PRIVATE int sqlite3PagerCommitPhaseTwo(Pager *pPager){
** But if (due to a coding error elsewhere in the system) it does get
** called, just return the same error code without doing anything. */
if( NEVER(pPager->errCode) ) return pPager->errCode;
+ pPager->iDataVersion++;
assert( pPager->eState==PAGER_WRITER_LOCKED
|| pPager->eState==PAGER_WRITER_FINISHED
@@ -56685,15 +59266,15 @@ 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->eState==PAGER_WRITER_LOCKED
- && pPager->exclusiveMode
+ if( pPager->eState==PAGER_WRITER_LOCKED
+ && pPager->exclusiveMode
&& pPager->journalMode==PAGER_JOURNALMODE_PERSIST
){
assert( pPager->journalOff==JOURNAL_HDR_SZ(pPager) || !pPager->journalOff );
@@ -56702,13 +59283,12 @@ SQLITE_PRIVATE int sqlite3PagerCommitPhaseTwo(Pager *pPager){
}
PAGERTRACE(("COMMIT %d\n", PAGERID(pPager)));
- pPager->iDataVersion++;
- rc = pager_end_transaction(pPager, pPager->setMaster, 1);
+ rc = pager_end_transaction(pPager, pPager->setSuper, 1);
return pager_error(pPager, rc);
}
/*
-** If a write transaction is open, then all changes made within the
+** If a write transaction is open, then all changes made within the
** transaction are reverted and the current write-transaction is closed.
** The pager falls back to PAGER_READER state if successful, or PAGER_ERROR
** state if an error occurs.
@@ -56718,14 +59298,14 @@ SQLITE_PRIVATE int sqlite3PagerCommitPhaseTwo(Pager *pPager){
**
** Otherwise, in rollback mode, this function performs two functions:
**
-** 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
** rollback at any point in the future.
**
-** Finalization of the journal file (task 2) is only performed if the
+** Finalization of the journal file (task 2) is only performed if the
** rollback is successful.
**
** In WAL mode, all cache-entries containing data modified within the
@@ -56738,7 +59318,7 @@ SQLITE_PRIVATE int sqlite3PagerRollback(Pager *pPager){
PAGERTRACE(("ROLLBACK %d\n", PAGERID(pPager)));
/* PagerRollback() is a no-op if called in READER or OPEN state. If
- ** the pager is already in the ERROR state, the rollback is not
+ ** the pager is already in the ERROR state, the rollback is not
** attempted here. Instead, the error code is returned to the caller.
*/
assert( assert_pager_state(pPager) );
@@ -56748,13 +59328,13 @@ SQLITE_PRIVATE int sqlite3PagerRollback(Pager *pPager){
if( pagerUseWal(pPager) ){
int rc2;
rc = sqlite3PagerSavepoint(pPager, SAVEPOINT_ROLLBACK, -1);
- rc2 = pager_end_transaction(pPager, pPager->setMaster, 0);
+ rc2 = pager_end_transaction(pPager, pPager->setSuper, 0);
if( rc==SQLITE_OK ) rc = rc2;
}else if( !isOpen(pPager->jfd) || pPager->eState==PAGER_WRITER_LOCKED ){
int eState = pPager->eState;
rc = pager_end_transaction(pPager, 0, 0);
if( !MEMDB && eState>PAGER_WRITER_LOCKED ){
- /* This can happen using journal_mode=off. Move the pager to the error
+ /* This can happen using journal_mode=off. Move the pager to the error
** state to indicate that the contents of the cache may not be trusted.
** Any active readers will get SQLITE_ABORT.
*/
@@ -56769,7 +59349,7 @@ SQLITE_PRIVATE int sqlite3PagerRollback(Pager *pPager){
assert( pPager->eState==PAGER_READER || rc!=SQLITE_OK );
assert( rc==SQLITE_OK || rc==SQLITE_FULL || rc==SQLITE_CORRUPT
- || rc==SQLITE_NOMEM || (rc&0xFF)==SQLITE_IOERR
+ || rc==SQLITE_NOMEM || (rc&0xFF)==SQLITE_IOERR
|| rc==SQLITE_CANTOPEN
);
@@ -56843,8 +59423,8 @@ SQLITE_PRIVATE int *sqlite3PagerStats(Pager *pPager){
** it was added later.
**
** Before returning, *pnVal is incremented by the
-** current cache hit or miss count, according to the value of eStat. If the
-** reset parameter is non-zero, the cache hit or miss count is zeroed before
+** current cache hit or miss count, according to the value of eStat. If the
+** reset parameter is non-zero, the cache hit or miss count is zeroed before
** returning.
*/
SQLITE_PRIVATE void sqlite3PagerCacheStat(Pager *pPager, int eStat, int reset, int *pnVal){
@@ -56880,7 +59460,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.
*/
@@ -56895,7 +59475,7 @@ static SQLITE_NOINLINE int pagerOpenSavepoint(Pager *pPager, int nSavepoint){
assert( nSavepoint>nCurrent && pPager->useJournal );
/* 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(
@@ -56917,6 +59497,7 @@ static SQLITE_NOINLINE int pagerOpenSavepoint(Pager *pPager, int nSavepoint){
}
aNew[ii].iSubRec = pPager->nSubRec;
aNew[ii].pInSavepoint = sqlite3BitvecCreate(pPager->dbSize);
+ aNew[ii].bTruncateOnRelease = 1;
if( !aNew[ii].pInSavepoint ){
return SQLITE_NOMEM_BKPT;
}
@@ -56943,7 +59524,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.
@@ -56951,29 +59532,29 @@ 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 = pPager->errCode;
-
+
#ifdef SQLITE_ENABLE_ZIPVFS
if( op==SAVEPOINT_RELEASE ) rc = SQLITE_OK;
#endif
@@ -56986,7 +59567,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);
@@ -56995,16 +59576,18 @@ 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) ){
+ PagerSavepoint *pRel = &pPager->aSavepoint[nNew];
+ if( pRel->bTruncateOnRelease && isOpen(pPager->sjfd) ){
/* Only truncate if it is an in-memory sub-journal. */
if( sqlite3JournalIsInMemory(pPager->sjfd) ){
- rc = sqlite3OsTruncate(pPager->sjfd, 0);
+ i64 sz = (pPager->pageSize+4)*pRel->iSubRec;
+ rc = sqlite3OsTruncate(pPager->sjfd, sz);
assert( rc==SQLITE_OK );
}
- pPager->nSubRec = 0;
+ pPager->nSubRec = pRel->iSubRec;
}
}
/* Else this is a rollback operation, playback the specified savepoint.
@@ -57017,14 +59600,14 @@ SQLITE_PRIVATE int sqlite3PagerSavepoint(Pager *pPager, int op, int iSavepoint){
rc = pagerPlaybackSavepoint(pPager, pSavepoint);
assert(rc!=SQLITE_DONE);
}
-
+
#ifdef SQLITE_ENABLE_ZIPVFS
- /* If the cache has been modified but the savepoint cannot be rolled
+ /* If the cache has been modified but the savepoint cannot be rolled
** back journal_mode=off, put the pager in the error state. This way,
** if the VFS used by this pager includes ZipVFS, the entire transaction
** can be rolled back at the ZipVFS level. */
- else if(
- pPager->journalMode==PAGER_JOURNALMODE_OFF
+ else if(
+ pPager->journalMode==PAGER_JOURNALMODE_OFF
&& pPager->eState>=PAGER_WRITER_CACHEMOD
){
pPager->errCode = SQLITE_ABORT;
@@ -57046,9 +59629,13 @@ SQLITE_PRIVATE int sqlite3PagerSavepoint(Pager *pPager, int op, int iSavepoint){
** behavior. But when the Btree needs to know the filename for matching to
** shared cache, it uses nullIfMemDb==0 so that in-memory databases can
** participate in shared-cache.
+**
+** The return value to this routine is always safe to use with
+** sqlite3_uri_parameter() and sqlite3_filename_database() and friends.
*/
-SQLITE_PRIVATE const char *sqlite3PagerFilename(Pager *pPager, int nullIfMemDb){
- return (nullIfMemDb && pPager->memDb) ? "" : pPager->zFilename;
+SQLITE_PRIVATE const char *sqlite3PagerFilename(const Pager *pPager, int nullIfMemDb){
+ static const char zFake[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
+ return (nullIfMemDb && pPager->memDb) ? &zFake[4] : pPager->zFilename;
}
/*
@@ -57067,16 +59654,6 @@ SQLITE_PRIVATE sqlite3_file *sqlite3PagerFile(Pager *pPager){
return pPager->fd;
}
-#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
-/*
-** Reset the lock timeout for pager.
-*/
-SQLITE_PRIVATE void sqlite3PagerResetLockTimeout(Pager *pPager){
- int x = 0;
- sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_LOCK_TIMEOUT, &x);
-}
-#endif
-
/*
** Return the file handle for the journal file (if it exists).
** This will be either the rollback journal or the WAL file.
@@ -57096,50 +59673,6 @@ SQLITE_PRIVATE const char *sqlite3PagerJournalname(Pager *pPager){
return pPager->zJournal;
}
-#ifdef SQLITE_HAS_CODEC
-/*
-** Set or retrieve the codec for this pager
-*/
-SQLITE_PRIVATE void sqlite3PagerSetCodec(
- Pager *pPager,
- void *(*xCodec)(void*,void*,Pgno,int),
- void (*xCodecSizeChng)(void*,int,int),
- void (*xCodecFree)(void*),
- void *pCodec
-){
- if( pPager->xCodecFree ) pPager->xCodecFree(pPager->pCodec);
- pPager->xCodec = pPager->memDb ? 0 : xCodec;
- pPager->xCodecSizeChng = xCodecSizeChng;
- pPager->xCodecFree = xCodecFree;
- pPager->pCodec = pCodec;
- setGetterMethod(pPager);
- pagerReportSize(pPager);
-}
-SQLITE_PRIVATE void *sqlite3PagerGetCodec(Pager *pPager){
- return pPager->pCodec;
-}
-
-/*
-** This function is called by the wal module when writing page content
-** into the log file.
-**
-** This function returns a pointer to a buffer containing the encrypted
-** page content. If a malloc fails, this function may return NULL.
-*/
-SQLITE_PRIVATE void *sqlite3PagerCodec(PgHdr *pPg){
- void *aData = 0;
- CODEC2(pPg->pPager, pPg->pData, pPg->pgno, 6, return 0, aData);
- return aData;
-}
-
-/*
-** Return the current pager state
-*/
-SQLITE_PRIVATE int sqlite3PagerState(Pager *pPager){
- return pPager->eState;
-}
-#endif /* SQLITE_HAS_CODEC */
-
#ifndef SQLITE_OMIT_AUTOVACUUM
/*
** Move the page pPg to location pgno in the file.
@@ -57159,8 +59692,8 @@ SQLITE_PRIVATE int sqlite3PagerState(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
@@ -57188,7 +59721,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;
@@ -57211,7 +59744,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))
@@ -57219,7 +59752,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 ){
@@ -57230,14 +59763,18 @@ 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_NEED_SYNC flag was set for
- ** page pgno before the 'move' operation, it needs to be retained
+ ** from its hash chain. Also, if the PGHDR_NEED_SYNC flag was set for
+ ** page pgno before the 'move' operation, it needs to be retained
** for the page moved there.
*/
pPg->flags &= ~PGHDR_NEED_SYNC;
pPgOld = sqlite3PagerLookup(pPager, pgno);
- assert( !pPgOld || pPgOld->nRef==1 );
+ assert( !pPgOld || pPgOld->nRef==1 || CORRUPT_DB );
if( pPgOld ){
+ if( pPgOld->nRef>1 ){
+ sqlite3PagerUnrefNotNull(pPgOld);
+ return SQLITE_CORRUPT_BKPT;
+ }
pPg->flags |= (pPgOld->flags&PGHDR_NEED_SYNC);
if( pPager->tempFile ){
/* Do not discard pages from an in-memory database since we might
@@ -57262,9 +59799,9 @@ SQLITE_PRIVATE int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno, i
}
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_NEED_SYNC
** flag.
@@ -57295,9 +59832,9 @@ SQLITE_PRIVATE int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno, i
#endif
/*
-** The page handle passed as the first argument refers to a dirty page
-** with a page number other than iNew. This function changes the page's
-** page number to iNew and sets the value of the PgHdr.flags field to
+** The page handle passed as the first argument refers to a dirty page
+** with a page number other than iNew. This function changes the page's
+** page number to iNew and sets the value of the PgHdr.flags field to
** the value passed as the third parameter.
*/
SQLITE_PRIVATE void sqlite3PagerRekey(DbPage *pPg, Pgno iNew, u16 flags){
@@ -57315,7 +59852,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){
@@ -57324,7 +59861,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.
**
@@ -57372,8 +59909,8 @@ SQLITE_PRIVATE int sqlite3PagerSetJournalMode(Pager *pPager, int eMode){
assert( 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_WAL
|| eMode==PAGER_JOURNALMODE_MEMORY );
/* This routine is only called from the OP_JournalMode opcode, and
@@ -57530,7 +60067,6 @@ SQLITE_PRIVATE int sqlite3PagerCheckpoint(
pPager->walSyncFlags, pPager->pageSize, (u8 *)pPager->pTmpSpace,
pnLog, pnCkpt
);
- sqlite3PagerResetLockTimeout(pPager);
}
return rc;
}
@@ -57559,7 +60095,7 @@ static int pagerExclusiveLock(Pager *pPager){
assert( pPager->eLock==SHARED_LOCK || pPager->eLock==EXCLUSIVE_LOCK );
rc = pagerLockDb(pPager, EXCLUSIVE_LOCK);
if( rc!=SQLITE_OK ){
- /* If the attempt to grab the exclusive lock failed, release the
+ /* If the attempt to grab the exclusive lock failed, release the
** pending lock that may have been obtained instead. */
pagerUnlockDb(pPager, SHARED_LOCK);
}
@@ -57568,7 +60104,7 @@ static int pagerExclusiveLock(Pager *pPager){
}
/*
-** Call sqlite3WalOpen() to open the WAL handle. If the pager is in
+** Call sqlite3WalOpen() to open the WAL handle. If the pager is in
** exclusive-locking mode when this function is called, take an EXCLUSIVE
** lock on the database file and use heap-memory to store the wal-index
** in. Otherwise, use the normal shared-memory.
@@ -57579,8 +60115,8 @@ static int pagerOpenWal(Pager *pPager){
assert( pPager->pWal==0 && pPager->tempFile==0 );
assert( pPager->eLock==SHARED_LOCK || pPager->eLock==EXCLUSIVE_LOCK );
- /* If the pager is already in exclusive-mode, the WAL module will use
- ** heap-memory for the wal-index instead of the VFS shared-memory
+ /* If the pager is already in exclusive-mode, the WAL module will use
+ ** heap-memory for the wal-index instead of the VFS shared-memory
** implementation. Take the exclusive lock now, before opening the WAL
** file, to make sure this is safe.
*/
@@ -57588,7 +60124,7 @@ static int pagerOpenWal(Pager *pPager){
rc = pagerExclusiveLock(pPager);
}
- /* Open the connection to the log file. If this operation fails,
+ /* Open the connection to the log file. If this operation fails,
** (e.g. due to malloc() failure), return an error code.
*/
if( rc==SQLITE_OK ){
@@ -57610,7 +60146,7 @@ static int pagerOpenWal(Pager *pPager){
** If the pager passed as the first argument is open on a real database
** file (not a temp file or an in-memory database), and the WAL file
** is not already open, make an attempt to open it now. If successful,
-** return SQLITE_OK. If an error occurs or the VFS used by the pager does
+** return SQLITE_OK. If an error occurs or the VFS used by the pager does
** not support the xShmXXX() methods, return an error code. *pbOpen is
** not modified in either case.
**
@@ -57652,7 +60188,7 @@ SQLITE_PRIVATE int sqlite3PagerOpenWal(
** 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
+** 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.
@@ -57678,7 +60214,7 @@ SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager, sqlite3 *db){
rc = pagerOpenWal(pPager);
}
}
-
+
/* Checkpoint and close the log. Because an EXCLUSIVE lock is held on
** the database file, the log and log-summary files will be deleted.
*/
@@ -57695,6 +60231,32 @@ SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager, sqlite3 *db){
return rc;
}
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+/*
+** If pager pPager is a wal-mode database not in exclusive locking mode,
+** invoke the sqlite3WalWriteLock() function on the associated Wal object
+** with the same db and bLock parameters as were passed to this function.
+** Return an SQLite error code if an error occurs, or SQLITE_OK otherwise.
+*/
+SQLITE_PRIVATE int sqlite3PagerWalWriteLock(Pager *pPager, int bLock){
+ int rc = SQLITE_OK;
+ if( pagerUseWal(pPager) && pPager->exclusiveMode==0 ){
+ rc = sqlite3WalWriteLock(pPager->pWal, bLock);
+ }
+ return rc;
+}
+
+/*
+** Set the database handle used by the wal layer to determine if
+** blocking locks are required.
+*/
+SQLITE_PRIVATE void sqlite3PagerWalDb(Pager *pPager, sqlite3 *db){
+ if( pagerUseWal(pPager) ){
+ sqlite3WalDb(pPager->pWal, db);
+ }
+}
+#endif
+
#ifdef SQLITE_ENABLE_SNAPSHOT
/*
** If this is a WAL database, obtain a snapshot handle for the snapshot
@@ -57710,10 +60272,13 @@ SQLITE_PRIVATE int sqlite3PagerSnapshotGet(Pager *pPager, sqlite3_snapshot **ppS
/*
** If this is a WAL database, store a pointer to pSnapshot. Next time a
-** read transaction is opened, attempt to read from the snapshot it
+** read transaction is opened, attempt to read from the snapshot it
** identifies. If this is not a WAL database, return an error.
*/
-SQLITE_PRIVATE int sqlite3PagerSnapshotOpen(Pager *pPager, sqlite3_snapshot *pSnapshot){
+SQLITE_PRIVATE int sqlite3PagerSnapshotOpen(
+ Pager *pPager,
+ sqlite3_snapshot *pSnapshot
+){
int rc = SQLITE_OK;
if( pPager->pWal ){
sqlite3WalSnapshotOpen(pPager->pWal, pSnapshot);
@@ -57724,7 +60289,7 @@ SQLITE_PRIVATE int sqlite3PagerSnapshotOpen(Pager *pPager, sqlite3_snapshot *pSn
}
/*
-** If this is a WAL database, call sqlite3WalSnapshotRecover(). If this
+** If this is a WAL database, call sqlite3WalSnapshotRecover(). If this
** is not a WAL database, return an error.
*/
SQLITE_PRIVATE int sqlite3PagerSnapshotRecover(Pager *pPager){
@@ -57741,7 +60306,7 @@ SQLITE_PRIVATE int sqlite3PagerSnapshotRecover(Pager *pPager){
** The caller currently has a read transaction open on the database.
** If this is not a WAL database, SQLITE_ERROR is returned. Otherwise,
** this function takes a SHARED lock on the CHECKPOINTER slot and then
-** checks if the snapshot passed as the second argument is still
+** checks if the snapshot passed as the second argument is still
** available. If so, SQLITE_OK is returned.
**
** If the snapshot is not available, SQLITE_ERROR is returned. Or, if
@@ -57765,7 +60330,7 @@ SQLITE_PRIVATE int sqlite3PagerSnapshotCheck(Pager *pPager, sqlite3_snapshot *pS
*/
SQLITE_PRIVATE void sqlite3PagerSnapshotUnlock(Pager *pPager){
assert( pPager->pWal );
- return sqlite3WalSnapshotUnlock(pPager->pWal);
+ sqlite3WalSnapshotUnlock(pPager->pWal);
}
#endif /* SQLITE_ENABLE_SNAPSHOT */
@@ -57801,7 +60366,7 @@ SQLITE_PRIVATE int sqlite3PagerWalFramesize(Pager *pPager){
**
*************************************************************************
**
-** This file contains the implementation of a write-ahead log (WAL) used in
+** This file contains the implementation of a write-ahead log (WAL) used in
** "journal_mode=WAL" mode.
**
** WRITE-AHEAD LOG (WAL) FILE FORMAT
@@ -57810,7 +60375,7 @@ SQLITE_PRIVATE int sqlite3PagerWalFramesize(Pager *pPager){
** 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
+** 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".
@@ -57836,11 +60401,11 @@ SQLITE_PRIVATE int sqlite3PagerWalFramesize(Pager *pPager){
**
** Immediately following the wal-header are zero or more frames. Each
** frame consists of a 24-byte frame-header followed by a bytes
-** of page data. The frame-header is six big-endian 32-bit unsigned
+** of page data. The frame-header is six big-endian 32-bit unsigned
** integer values, as follows:
**
** 0: Page number.
-** 4: For commit records, the size of the database image in pages
+** 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)
@@ -57866,7 +60431,7 @@ SQLITE_PRIVATE int sqlite3PagerWalFramesize(Pager *pPager){
** the checksum. The checksum is computed by interpreting the input as
** an even number of unsigned 32-bit integers: x[0] through x[N]. The
** algorithm used for the checksum is as follows:
-**
+**
** for i from 0 to n-1 step 2:
** s0 += x[i] + s1;
** s1 += x[i+1] + s0;
@@ -57874,7 +60439,7 @@ SQLITE_PRIVATE int sqlite3PagerWalFramesize(Pager *pPager){
**
** Note that s0 and s1 are both weighted checksums using fibonacci weights
** in reverse order (the largest fibonacci weight occurs on the first element
-** of the sequence being summed.) The s1 value spans all 32-bit
+** of the sequence being summed.) The s1 value spans all 32-bit
** terms of the sequence whereas s0 omits the final term.
**
** On a checkpoint, the WAL is first VFS.xSync-ed, then valid content of the
@@ -57907,19 +60472,19 @@ SQLITE_PRIVATE int sqlite3PagerWalFramesize(Pager *pPager){
** multiple concurrent readers to view different versions of the database
** content simultaneously.
**
-** The reader algorithm in the previous paragraphs works correctly, but
+** The reader algorithm in the previous paragraphs works correctly, but
** because frames for page P can appear anywhere within the WAL, the
** reader has to scan the entire WAL looking for page P frames. If the
** WAL is large (multiple megabytes is typical) that scan can be slow,
** and read performance suffers. To overcome this problem, a separate
** data structure called the wal-index is maintained to expedite the
** search for frames of a particular page.
-**
+**
** WAL-INDEX FORMAT
**
** Conceptually, the wal-index is shared memory, though VFS implementations
** might choose to implement the wal-index using a mmapped file. Because
-** the wal-index is shared memory, SQLite does not support journal_mode=WAL
+** 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.
**
@@ -57937,28 +60502,28 @@ SQLITE_PRIVATE int sqlite3PagerWalFramesize(Pager *pPager){
** byte order of the host computer.
**
** The purpose of the wal-index is to answer this question quickly: Given
-** a page number P and a maximum frame index M, return the index of the
+** a page number P and a maximum frame index M, return the index of the
** last frame in the wal before frame M for page P in the WAL, or return
** NULL if there are no frames for page P in the WAL prior to M.
**
** The wal-index consists of a header region, followed by an one or
-** more index blocks.
+** more index blocks.
**
** The wal-index header contains the total number of frames within the WAL
** in the mxFrame field.
**
-** Each index block except for the first contains information on
+** Each index block except for the first contains information on
** HASHTABLE_NPAGE frames. The first index block contains information on
-** HASHTABLE_NPAGE_ONE frames. The values of HASHTABLE_NPAGE_ONE and
+** HASHTABLE_NPAGE_ONE frames. The values of HASHTABLE_NPAGE_ONE and
** HASHTABLE_NPAGE are selected so that together the wal-index header and
** first index block are the same size as all other index blocks in the
** wal-index.
**
** Each index block contains two sections, a page-mapping that contains the
-** database page number associated with each wal frame, and a hash-table
+** database page number associated with each wal frame, and a hash-table
** that allows readers to query an index block for a specific page number.
** The page-mapping is an array of HASHTABLE_NPAGE (or HASHTABLE_NPAGE_ONE
-** for the first index block) 32-bit page numbers. The first entry in the
+** for the first index block) 32-bit page numbers. The first entry in the
** first index-block contains the database page number corresponding to the
** first frame in the WAL file. The first entry in the second index block
** in the WAL file corresponds to the (HASHTABLE_NPAGE_ONE+1)th frame in
@@ -57979,8 +60544,8 @@ SQLITE_PRIVATE int sqlite3PagerWalFramesize(Pager *pPager){
**
** 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
+** 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
@@ -57999,12 +60564,12 @@ SQLITE_PRIVATE int sqlite3PagerWalFramesize(Pager *pPager){
** 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
+** 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
+** 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
@@ -58029,7 +60594,7 @@ SQLITE_PRIVATE int sqlite3PagerWalFramesize(Pager *pPager){
** 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.
+** 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
@@ -58049,18 +60614,6 @@ SQLITE_PRIVATE int sqlite3WalTrace = 0;
# define WALTRACE(X)
#endif
-/*
-** WAL mode depends on atomic aligned 32-bit loads and stores in a few
-** places. The following macros try to make this explicit.
-*/
-#if GCC_VESRION>=5004000
-# define AtomicLoad(PTR) __atomic_load_n((PTR),__ATOMIC_RELAXED)
-# define AtomicStore(PTR,VAL) __atomic_store_n((PTR),(VAL),__ATOMIC_RELAXED)
-#else
-# define AtomicLoad(PTR) (*(PTR))
-# define AtomicStore(PTR,VAL) (*(PTR) = (VAL))
-#endif
-
/*
** The maximum (and only) versions of the wal and wal-index formats
** that may be interpreted by this version of SQLite.
@@ -58069,7 +60622,7 @@ SQLITE_PRIVATE int sqlite3WalTrace = 0;
** values in the wal-header are correct and (b) the version field is not
** WAL_MAX_VERSION, recovery fails and SQLite returns SQLITE_CANTOPEN.
**
-** Similarly, if a client successfully reads a wal-index header (i.e. the
+** Similarly, if a client successfully reads a wal-index header (i.e. the
** checksum test is successful) and finds that the version field is not
** WALINDEX_MAX_VERSION, then no read-transaction is opened and SQLite
** returns SQLITE_CANTOPEN.
@@ -58116,7 +60669,7 @@ typedef struct WalCkptInfo WalCkptInfo;
**
** The szPage value can be any power of 2 between 512 and 32768, inclusive.
** Or it can be 1 to represent a 65536-byte page. The latter case was
-** added in 3.7.1 when support for 64K pages was added.
+** added in 3.7.1 when support for 64K pages was added.
*/
struct WalIndexHdr {
u32 iVersion; /* Wal-index version */
@@ -58158,7 +60711,7 @@ struct WalIndexHdr {
** There is one entry in aReadMark[] for each reader lock. If a reader
** holds read-lock K, then the value in aReadMark[K] is no greater than
** the mxFrame for that reader. The value READMARK_NOT_USED (0xffffffff)
-** for any aReadMark[] means that entry is unused. aReadMark[0] is
+** for any aReadMark[] means that entry is unused. aReadMark[0] is
** a special case; its value is never used and it exists as a place-holder
** to avoid having to offset aReadMark[] indexs by one. Readers holding
** WAL_READ_LOCK(0) always ignore the entire WAL and read all content
@@ -58178,7 +60731,7 @@ struct WalIndexHdr {
** previous sentence is when nBackfill equals mxFrame (meaning that everything
** in the WAL has been backfilled into the database) then new readers
** will choose aReadMark[0] which has value 0 and hence such reader will
-** get all their all content directly from the database file and ignore
+** get all their all content directly from the database file and ignore
** the WAL.
**
** Writers normally append new frames to the end of the WAL. However,
@@ -58220,14 +60773,14 @@ struct WalCkptInfo {
** 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
+** 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,
+** 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.
*/
@@ -58270,13 +60823,16 @@ struct Wal {
#ifdef SQLITE_ENABLE_SNAPSHOT
WalIndexHdr *pSnapshot; /* Start transaction here if not NULL */
#endif
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+ sqlite3 *db;
+#endif
};
/*
** Candidate values for Wal.exclusiveMode.
*/
#define WAL_NORMAL_MODE 0
-#define WAL_EXCLUSIVE_MODE 1
+#define WAL_EXCLUSIVE_MODE 1
#define WAL_HEAPMEMORY_MODE 2
/*
@@ -58295,7 +60851,7 @@ typedef u16 ht_slot;
/*
** 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
+** 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).
**
@@ -58308,7 +60864,7 @@ typedef u16 ht_slot;
** This functionality is used by the checkpoint code (see walCheckpoint()).
*/
struct WalIterator {
- int iPrior; /* Last result returned from the iterator */
+ u32 iPrior; /* Last result returned from the iterator */
int nSegment; /* Number of entries in aSegment[] */
struct WalSegment {
int iNext; /* Next slot in aIndex[] not yet returned */
@@ -58331,7 +60887,7 @@ struct WalIterator {
#define HASHTABLE_HASH_1 383 /* Should be prime */
#define HASHTABLE_NSLOT (HASHTABLE_NPAGE*2) /* Must be a power of 2 */
-/*
+/*
** The block of page numbers associated with the first hash-table in a
** wal-index is smaller than usual. This is so that there is a complete
** hash-table on each aligned 32KB page of the wal-index.
@@ -58366,9 +60922,9 @@ static SQLITE_NOINLINE int walIndexPageRealloc(
/* Enlarge the pWal->apWiData[] array if required */
if( pWal->nWiData<=iPage ){
- int nByte = sizeof(u32*)*(iPage+1);
+ sqlite3_int64 nByte = sizeof(u32*)*(iPage+1);
volatile u32 **apNew;
- apNew = (volatile u32 **)sqlite3_realloc64((void *)pWal->apWiData, nByte);
+ apNew = (volatile u32 **)sqlite3Realloc((void *)pWal->apWiData, nByte);
if( !apNew ){
*ppPage = 0;
return SQLITE_NOMEM_BKPT;
@@ -58385,12 +60941,14 @@ static SQLITE_NOINLINE int walIndexPageRealloc(
pWal->apWiData[iPage] = (u32 volatile *)sqlite3MallocZero(WALINDEX_PGSZ);
if( !pWal->apWiData[iPage] ) rc = SQLITE_NOMEM_BKPT;
}else{
- rc = sqlite3OsShmMap(pWal->pDbFd, iPage, WALINDEX_PGSZ,
+ rc = sqlite3OsShmMap(pWal->pDbFd, iPage, WALINDEX_PGSZ,
pWal->writeLock, (void volatile **)&pWal->apWiData[iPage]
);
assert( pWal->apWiData[iPage]!=0 || rc!=SQLITE_OK || pWal->writeLock==0 );
testcase( pWal->apWiData[iPage]==0 && rc==SQLITE_OK );
- if( (rc&0xff)==SQLITE_READONLY ){
+ if( rc==SQLITE_OK ){
+ if( iPage>0 && sqlite3FaultSim(600) ) rc = SQLITE_NOMEM;
+ }else if( (rc&0xff)==SQLITE_READONLY ){
pWal->readOnly |= WAL_SHM_RDONLY;
if( rc==SQLITE_READONLY ){
rc = SQLITE_OK;
@@ -58442,7 +61000,7 @@ static volatile WalIndexHdr *walIndexHdr(Wal *pWal){
)
/*
-** Generate or extend an 8 byte checksum based on the data in
+** 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).
**
@@ -58470,6 +61028,7 @@ static void walChecksumBytes(
assert( nByte>=8 );
assert( (nByte&0x00000007)==0 );
+ assert( nByte<=65536 );
if( nativeCksum ){
do {
@@ -58488,18 +61047,35 @@ static void walChecksumBytes(
aOut[1] = s2;
}
+/*
+** If there is the possibility of concurrent access to the SHM file
+** from multiple threads and/or processes, then do a memory barrier.
+*/
static void walShmBarrier(Wal *pWal){
if( pWal->exclusiveMode!=WAL_HEAPMEMORY_MODE ){
sqlite3OsShmBarrier(pWal->pDbFd);
}
}
+/*
+** Add the SQLITE_NO_TSAN as part of the return-type of a function
+** definition as a hint that the function contains constructs that
+** might give false-positive TSAN warnings.
+**
+** See tag-20200519-1.
+*/
+#if defined(__clang__) && !defined(SQLITE_NO_TSAN)
+# define SQLITE_NO_TSAN __attribute__((no_sanitize_thread))
+#else
+# define SQLITE_NO_TSAN
+#endif
+
/*
** 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){
+static SQLITE_NO_TSAN void walIndexWriteHdr(Wal *pWal){
volatile WalIndexHdr *aHdr = walIndexHdr(pWal);
const int nCksum = offsetof(WalIndexHdr, aCksum);
@@ -58507,6 +61083,7 @@ static void walIndexWriteHdr(Wal *pWal){
pWal->hdr.isInit = 1;
pWal->hdr.iVersion = WALINDEX_MAX_VERSION;
walChecksumBytes(1, (u8*)&pWal->hdr, nCksum, 0, pWal->hdr.aCksum);
+ /* Possible TSAN false-positive. See tag-20200519-1 */
memcpy((void*)&aHdr[1], (const void*)&pWal->hdr, sizeof(WalIndexHdr));
walShmBarrier(pWal);
memcpy((void*)&aHdr[0], (const void*)&pWal->hdr, sizeof(WalIndexHdr));
@@ -58514,11 +61091,11 @@ static void walIndexWriteHdr(Wal *pWal){
/*
** 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
+** 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
+** 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)
@@ -58569,7 +61146,7 @@ static int walDecodeFrame(
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.
+ ** match the salt values in the wal-header.
*/
if( memcmp(&pWal->hdr.aSalt, &aFrame[8], 8)!=0 ){
return 0;
@@ -58583,15 +61160,15 @@ static int walDecodeFrame(
}
/* A frame is only valid if a checksum of the WAL header,
- ** all prior frams, the first 16 bytes of this frame-header,
- ** and the frame-data matches the checksum in the last 8
+ ** all prior frams, the first 16 bytes of this frame-header,
+ ** and the frame-data matches the checksum in the last 8
** bytes of this frame-header.
*/
nativeCksum = (pWal->hdr.bigEndCksum==SQLITE_BIGENDIAN);
walChecksumBytes(nativeCksum, aFrame, 8, aCksum, aCksum);
walChecksumBytes(nativeCksum, aData, pWal->szPage, aCksum, aCksum);
- if( aCksum[0]!=sqlite3Get4byte(&aFrame[16])
- || aCksum[1]!=sqlite3Get4byte(&aFrame[20])
+ if( aCksum[0]!=sqlite3Get4byte(&aFrame[16])
+ || aCksum[1]!=sqlite3Get4byte(&aFrame[20])
){
/* Checksum failed. */
return 0;
@@ -58626,7 +61203,7 @@ static const char *walLockName(int lockIdx){
}
}
#endif /*defined(SQLITE_TEST) || defined(SQLITE_DEBUG) */
-
+
/*
** Set or release locks on the WAL. Locks are either shared or exclusive.
@@ -58642,7 +61219,7 @@ static int walLockShared(Wal *pWal, int lockIdx){
SQLITE_SHM_LOCK | SQLITE_SHM_SHARED);
WALTRACE(("WAL%p: acquire SHARED-%s %s\n", pWal,
walLockName(lockIdx), rc ? "failed" : "ok"));
- VVA_ONLY( pWal->lockError = (u8)(rc!=SQLITE_OK && rc!=SQLITE_BUSY); )
+ VVA_ONLY( pWal->lockError = (u8)(rc!=SQLITE_OK && (rc&0xFF)!=SQLITE_BUSY); )
return rc;
}
static void walUnlockShared(Wal *pWal, int lockIdx){
@@ -58658,7 +61235,7 @@ static int walLockExclusive(Wal *pWal, int lockIdx, int n){
SQLITE_SHM_LOCK | SQLITE_SHM_EXCLUSIVE);
WALTRACE(("WAL%p: acquire EXCLUSIVE-%s cnt=%d %s\n", pWal,
walLockName(lockIdx), n, rc ? "failed" : "ok"));
- VVA_ONLY( pWal->lockError = (u8)(rc!=SQLITE_OK && rc!=SQLITE_BUSY); )
+ VVA_ONLY( pWal->lockError = (u8)(rc!=SQLITE_OK && (rc&0xFF)!=SQLITE_BUSY); )
return rc;
}
static void walUnlockExclusive(Wal *pWal, int lockIdx, int n){
@@ -58695,15 +61272,15 @@ struct WalHashLoc {
u32 iZero; /* One less than the frame number of first indexed*/
};
-/*
+/*
** Return pointers to the hash table and page number array stored on
** page iHash of the wal-index. The wal-index is broken into 32KB pages
** numbered starting from 0.
**
** Set output variable pLoc->aHash to point to the start of the hash table
-** in the wal-index file. Set pLoc->iZero to one less than the frame
+** in the wal-index file. Set pLoc->iZero 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
+** slot in the hash table is set to N, it refers to frame number
** (pLoc->iZero+N) in the log.
**
** Finally, set pLoc->aPgno so that pLoc->aPgno[1] is the page number of the
@@ -58735,7 +61312,7 @@ static int walHashGet(
/*
** Return the number of the wal-index page that contains the hash-table
** and page-number array that contain entries corresponding to WAL frame
-** iFrame. The wal-index is broken up into 32KB pages. Wal-index pages
+** iFrame. The wal-index is broken up into 32KB pages. Wal-index pages
** are numbered starting from 0.
*/
static int walFramePage(u32 iFrame){
@@ -58746,6 +61323,7 @@ static int walFramePage(u32 iFrame){
&& (iHash>=2 || iFrame<=HASHTABLE_NPAGE_ONE+HASHTABLE_NPAGE)
&& (iHash<=2 || iFrame>(HASHTABLE_NPAGE_ONE+2*HASHTABLE_NPAGE))
);
+ assert( iHash>=0 );
return iHash;
}
@@ -58785,13 +61363,14 @@ static void walCleanupHash(Wal *pWal){
if( pWal->hdr.mxFrame==0 ) return;
- /* Obtain pointers to the hash-table and page-number array containing
+ /* Obtain pointers to the hash-table and page-number array containing
** the entry that corresponds to frame pWal->hdr.mxFrame. It is guaranteed
- ** that the page said hash-table and array reside on is already mapped.
+ ** that the page said hash-table and array reside on is already mapped.(1)
*/
assert( pWal->nWiData>walFramePage(pWal->hdr.mxFrame) );
assert( pWal->apWiData[walFramePage(pWal->hdr.mxFrame)] );
- walHashGet(pWal, walFramePage(pWal->hdr.mxFrame), &sLoc);
+ i = walHashGet(pWal, walFramePage(pWal->hdr.mxFrame), &sLoc);
+ if( NEVER(i) ) return; /* Defense-in-depth, in case (1) above is wrong */
/* Zero all hash-table entries that correspond to frame numbers greater
** than pWal->hdr.mxFrame.
@@ -58803,9 +61382,9 @@ static void walCleanupHash(Wal *pWal){
sLoc.aHash[i] = 0;
}
}
-
+
/* Zero the entries in the aPgno array that correspond to frames with
- ** frame numbers greater than pWal->hdr.mxFrame.
+ ** frame numbers greater than pWal->hdr.mxFrame.
*/
nByte = (int)((char *)sLoc.aHash - (char *)&sLoc.aPgno[iLimit+1]);
memset((void *)&sLoc.aPgno[iLimit+1], 0, nByte);
@@ -58848,9 +61427,9 @@ static int walIndexAppend(Wal *pWal, u32 iFrame, u32 iPage){
idx = iFrame - sLoc.iZero;
assert( idx <= HASHTABLE_NSLOT/2 + 1 );
-
+
/* If this is the first entry to be added to this hash-table, zero the
- ** entire hash table and aPgno[] array before proceeding.
+ ** entire hash table and aPgno[] array before proceeding.
*/
if( idx==1 ){
int nByte = (int)((u8 *)&sLoc.aHash[HASHTABLE_NSLOT]
@@ -58860,8 +61439,8 @@ static int walIndexAppend(Wal *pWal, u32 iFrame, u32 iPage){
/* If the entry in aPgno[] is already set, then the previous writer
** must have exited unexpectedly in the middle of a transaction (after
- ** writing one or more dirty pages to the WAL to free up memory).
- ** Remove the remnants of that writers uncommitted transaction from
+ ** writing one or more dirty pages to the WAL to free up memory).
+ ** Remove the remnants of that writers uncommitted transaction from
** the hash-table before writing any new entries.
*/
if( sLoc.aPgno[idx] ){
@@ -58875,7 +61454,7 @@ static int walIndexAppend(Wal *pWal, u32 iFrame, u32 iPage){
if( (nCollide--)==0 ) return SQLITE_CORRUPT_BKPT;
}
sLoc.aPgno[idx] = iPage;
- sLoc.aHash[iKey] = (ht_slot)idx;
+ AtomicStore(&sLoc.aHash[iKey], (ht_slot)idx);
#ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT
/* Verify that the number of entries in the hash table exactly equals
@@ -58913,7 +61492,7 @@ static int walIndexAppend(Wal *pWal, u32 iFrame, u32 iPage){
/*
-** Recover the wal-index by reading the write-ahead log file.
+** Recover the wal-index by reading the write-ahead log file.
**
** This routine first tries to establish an exclusive lock on the
** wal-index to prevent other threads/processes from doing anything
@@ -58940,12 +61519,6 @@ static int walIndexRecover(Wal *pWal){
assert( pWal->writeLock );
iLock = WAL_ALL_BUT_WRITE + pWal->ckptLock;
rc = walLockExclusive(pWal, iLock, WAL_READ_LOCK(0)-iLock);
- if( rc==SQLITE_OK ){
- rc = walLockExclusive(pWal, WAL_READ_LOCK(1), WAL_NREADER-1);
- if( rc!=SQLITE_OK ){
- walUnlockExclusive(pWal, iLock, WAL_READ_LOCK(0)-iLock);
- }
- }
if( rc ){
return rc;
}
@@ -58961,15 +61534,16 @@ static int walIndexRecover(Wal *pWal){
if( nSize>WAL_HDRSIZE ){
u8 aBuf[WAL_HDRSIZE]; /* Buffer to load WAL header into */
+ u32 *aPrivate = 0; /* Heap copy of *-shm hash being populated */
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 */
u32 version; /* Magic value read from WAL header */
int isValid; /* True if this frame is valid */
+ u32 iPg; /* Current 32KB wal-index page */
+ u32 iLastFrame; /* Last frame in wal, based on nSize alone */
/* Read in the WAL header. */
rc = sqlite3OsRead(pWal->pWalFd, aBuf, WAL_HDRSIZE, 0);
@@ -58978,16 +61552,16 @@ static int walIndexRecover(Wal *pWal){
}
/* 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
+ ** 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
+ if( (magic&0xFFFFFFFE)!=WAL_MAGIC
+ || szPage&(szPage-1)
+ || szPage>SQLITE_MAX_PAGE_SIZE
+ || szPage<512
){
goto finished;
}
@@ -58997,7 +61571,7 @@ static int walIndexRecover(Wal *pWal){
memcpy(&pWal->hdr.aSalt, &aBuf[16], 8);
/* Verify that the WAL header checksum is correct */
- walChecksumBytes(pWal->hdr.bigEndCksum==SQLITE_BIGENDIAN,
+ walChecksumBytes(pWal->hdr.bigEndCksum==SQLITE_BIGENDIAN,
aBuf, WAL_HDRSIZE-2*4, 0, pWal->hdr.aFrameCksum
);
if( pWal->hdr.aFrameCksum[0]!=sqlite3Get4byte(&aBuf[24])
@@ -59016,38 +61590,82 @@ static int walIndexRecover(Wal *pWal){
/* Malloc a buffer to read frames into. */
szFrame = szPage + WAL_FRAME_HDRSIZE;
- aFrame = (u8 *)sqlite3_malloc64(szFrame);
+ aFrame = (u8 *)sqlite3_malloc64(szFrame + WALINDEX_PGSZ);
if( !aFrame ){
rc = SQLITE_NOMEM_BKPT;
goto recovery_error;
}
aData = &aFrame[WAL_FRAME_HDRSIZE];
+ aPrivate = (u32*)&aData[szPage];
/* 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 */
+ iLastFrame = (nSize - WAL_HDRSIZE) / szFrame;
+ for(iPg=0; iPg<=(u32)walFramePage(iLastFrame); iPg++){
+ u32 *aShare;
+ u32 iFrame; /* Index of last frame read */
+ u32 iLast = MIN(iLastFrame, HASHTABLE_NPAGE_ONE+iPg*HASHTABLE_NPAGE);
+ u32 iFirst = 1 + (iPg==0?0:HASHTABLE_NPAGE_ONE+(iPg-1)*HASHTABLE_NPAGE);
+ u32 nHdr, nHdr32;
+ rc = walIndexPage(pWal, iPg, (volatile u32**)&aShare);
+ if( rc ) break;
+ pWal->apWiData[iPg] = aPrivate;
- /* Read and decode the next log frame. */
- iFrame++;
- 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;
+ for(iFrame=iFirst; iFrame<=iLast; iFrame++){
+ i64 iOffset = walFrameOffset(iFrame, szPage);
+ u32 pgno; /* Database page number for frame */
+ u32 nTruncate; /* dbsize field from frame header */
- /* If nTruncate is non-zero, this is a commit record. */
- if( nTruncate ){
- pWal->hdr.mxFrame = iFrame;
- pWal->hdr.nPage = nTruncate;
- pWal->hdr.szPage = (u16)((szPage&0xff00) | (szPage>>16));
- testcase( szPage<=32768 );
- testcase( szPage>=65536 );
- aFrameCksum[0] = pWal->hdr.aFrameCksum[0];
- aFrameCksum[1] = pWal->hdr.aFrameCksum[1];
+ /* 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( NEVER(rc!=SQLITE_OK) ) break;
+
+ /* If nTruncate is non-zero, this is a commit record. */
+ if( nTruncate ){
+ pWal->hdr.mxFrame = iFrame;
+ pWal->hdr.nPage = nTruncate;
+ pWal->hdr.szPage = (u16)((szPage&0xff00) | (szPage>>16));
+ testcase( szPage<=32768 );
+ testcase( szPage>=65536 );
+ aFrameCksum[0] = pWal->hdr.aFrameCksum[0];
+ aFrameCksum[1] = pWal->hdr.aFrameCksum[1];
+ }
}
+ pWal->apWiData[iPg] = aShare;
+ nHdr = (iPg==0 ? WALINDEX_HDR_SIZE : 0);
+ nHdr32 = nHdr / sizeof(u32);
+#ifndef SQLITE_SAFER_WALINDEX_RECOVERY
+ /* Memcpy() should work fine here, on all reasonable implementations.
+ ** Technically, memcpy() might change the destination to some
+ ** intermediate value before setting to the final value, and that might
+ ** cause a concurrent reader to malfunction. Memcpy() is allowed to
+ ** do that, according to the spec, but no memcpy() implementation that
+ ** we know of actually does that, which is why we say that memcpy()
+ ** is safe for this. Memcpy() is certainly a lot faster.
+ */
+ memcpy(&aShare[nHdr32], &aPrivate[nHdr32], WALINDEX_PGSZ-nHdr);
+#else
+ /* In the event that some platform is found for which memcpy()
+ ** changes the destination to some intermediate value before
+ ** setting the final value, this alternative copy routine is
+ ** provided.
+ */
+ {
+ int i;
+ for(i=nHdr32; ihdr.aFrameCksum[1] = aFrameCksum[1];
walIndexWriteHdr(pWal);
- /* Reset the checkpoint-header. This is safe because this thread is
- ** currently holding locks that exclude all other readers, writers and
- ** checkpointers.
+ /* Reset the checkpoint-header. This is safe because this thread is
+ ** currently holding locks that exclude all other writers and
+ ** checkpointers. Then set the values of read-mark slots 1 through N.
*/
pInfo = walCkptInfo(pWal);
pInfo->nBackfill = 0;
pInfo->nBackfillAttempted = pWal->hdr.mxFrame;
pInfo->aReadMark[0] = 0;
- for(i=1; iaReadMark[i] = READMARK_NOT_USED;
- if( pWal->hdr.mxFrame ) pInfo->aReadMark[1] = pWal->hdr.mxFrame;
+ for(i=1; ihdr.mxFrame ){
+ pInfo->aReadMark[i] = pWal->hdr.mxFrame;
+ }else{
+ pInfo->aReadMark[i] = READMARK_NOT_USED;
+ }
+ walUnlockExclusive(pWal, WAL_READ_LOCK(i), 1);
+ }else if( rc!=SQLITE_BUSY ){
+ goto recovery_error;
+ }
+ }
/* If more than one frame was recovered from the log file, report an
** event via sqlite3_log(). This is to help with identifying performance
@@ -59088,7 +61717,6 @@ finished:
recovery_error:
WALTRACE(("WAL%p: recovery %s\n", pWal, rc ? "failed" : "ok"));
walUnlockExclusive(pWal, iLock, WAL_READ_LOCK(0)-iLock);
- walUnlockExclusive(pWal, WAL_READ_LOCK(1), WAL_NREADER-1);
return rc;
}
@@ -59108,8 +61736,8 @@ static void walIndexClose(Wal *pWal, int isDelete){
}
}
-/*
-** Open a connection to the WAL file zWalName. The database file must
+/*
+** Open a connection to the WAL file zWalName. The database file must
** already be opened on connection pDbFd. The buffer that zWalName points
** to must remain valid for the lifetime of the returned Wal* handle.
**
@@ -59119,7 +61747,7 @@ static void walIndexClose(Wal *pWal, int isDelete){
** 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
+** 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.
*/
@@ -59283,7 +61911,7 @@ static void walMerge(
ht_slot logpage;
Pgno dbpage;
- if( (iLeft=nRight || aContent[aLeft[iLeft]]aSegment[p->nSegment])[sLoc.iZero];
sLoc.iZero++;
-
+
for(j=0; jdb ){
+ int tmout = pWal->db->busyTimeout;
+ if( tmout ){
+ int rc;
+ rc = sqlite3OsFileControl(
+ pWal->pDbFd, SQLITE_FCNTL_LOCK_TIMEOUT, (void*)&tmout
+ );
+ res = (rc==SQLITE_OK);
+ }
+ }
+ return res;
+}
+
+/*
+** Disable blocking locks.
+*/
+static void walDisableBlocking(Wal *pWal){
+ int tmout = 0;
+ sqlite3OsFileControl(pWal->pDbFd, SQLITE_FCNTL_LOCK_TIMEOUT, (void*)&tmout);
+}
+
+/*
+** If parameter bLock is true, attempt to enable blocking locks, take
+** the WRITER lock, and then disable blocking locks. If blocking locks
+** cannot be enabled, no attempt to obtain the WRITER lock is made. Return
+** an SQLite error code if an error occurs, or SQLITE_OK otherwise. It is not
+** an error if blocking locks can not be enabled.
+**
+** If the bLock parameter is false and the WRITER lock is held, release it.
+*/
+SQLITE_PRIVATE int sqlite3WalWriteLock(Wal *pWal, int bLock){
+ int rc = SQLITE_OK;
+ assert( pWal->readLock<0 || bLock==0 );
+ if( bLock ){
+ assert( pWal->db );
+ if( walEnableBlocking(pWal) ){
+ rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1);
+ if( rc==SQLITE_OK ){
+ pWal->writeLock = 1;
+ }
+ walDisableBlocking(pWal);
+ }
+ }else if( pWal->writeLock ){
+ walUnlockExclusive(pWal, WAL_WRITE_LOCK, 1);
+ pWal->writeLock = 0;
+ }
+ return rc;
+}
+
+/*
+** Set the database handle used to determine if blocking locks are required.
+*/
+SQLITE_PRIVATE void sqlite3WalDb(Wal *pWal, sqlite3 *db){
+ pWal->db = db;
+}
+
+/*
+** Take an exclusive WRITE lock. Blocking if so configured.
+*/
+static int walLockWriter(Wal *pWal){
+ int rc;
+ walEnableBlocking(pWal);
+ rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1);
+ walDisableBlocking(pWal);
+ return rc;
+}
+#else
+# define walEnableBlocking(x) 0
+# define walDisableBlocking(x)
+# define walLockWriter(pWal) walLockExclusive((pWal), WAL_WRITE_LOCK, 1)
+# define sqlite3WalDb(pWal, db)
+#endif /* ifdef SQLITE_ENABLE_SETLK_TIMEOUT */
+
+
/*
** Attempt to obtain the exclusive WAL lock defined by parameters lockIdx and
** n. If the attempt fails and parameter xBusy is not NULL, then it is a
@@ -59493,6 +62204,12 @@ static int walBusyLock(
do {
rc = walLockExclusive(pWal, lockIdx, n);
}while( xBusy && rc==SQLITE_BUSY && xBusy(pBusyArg) );
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+ if( rc==SQLITE_BUSY_TIMEOUT ){
+ walDisableBlocking(pWal);
+ rc = SQLITE_BUSY;
+ }
+#endif
return rc;
}
@@ -59517,8 +62234,8 @@ static int walPagesize(Wal *pWal){
** client to write to the database (which may be this one) does so by
** writing frames into the start of the log file.
**
-** The value of parameter salt1 is used as the aSalt[1] value in the
-** new wal-index header. It should be passed a pseudo-random value (i.e.
+** The value of parameter salt1 is used as the aSalt[1] value in the
+** new wal-index header. It should be passed a pseudo-random value (i.e.
** one obtained from sqlite3_randomness()).
*/
static void walRestartHdr(Wal *pWal, u32 salt1){
@@ -59530,7 +62247,7 @@ static void walRestartHdr(Wal *pWal, u32 salt1){
sqlite3Put4byte((u8*)&aSalt[0], 1 + sqlite3Get4byte((u8*)&aSalt[0]));
memcpy(&pWal->hdr.aSalt[1], &salt1, 4);
walIndexWriteHdr(pWal);
- pInfo->nBackfill = 0;
+ AtomicStore(&pInfo->nBackfill, 0);
pInfo->nBackfillAttempted = 0;
pInfo->aReadMark[1] = 0;
for(i=2; iaReadMark[i] = READMARK_NOT_USED;
@@ -59546,8 +62263,8 @@ static void walRestartHdr(Wal *pWal, u32 salt1){
** that a concurrent reader might be using.
**
** All I/O barrier operations (a.k.a fsyncs) occur in this routine when
-** SQLite is in WAL-mode in synchronous=NORMAL. That means that if
-** checkpoints are always run by a background thread or background
+** SQLite is in WAL-mode in synchronous=NORMAL. That means that if
+** checkpoints are always run by a background thread or background
** process, foreground threads will never block on a lengthy fsync call.
**
** Fsync is called on the WAL before writing content out of the WAL and
@@ -59560,7 +62277,7 @@ static void walRestartHdr(Wal *pWal, u32 salt1){
** database file.
**
** This routine uses and updates the nBackfill field of the wal-index header.
-** This is the only routine that will increase the value of nBackfill.
+** This is the only routine that will increase the value of nBackfill.
** (A WAL reset or recovery will revert nBackfill to zero, but not increase
** its value.)
**
@@ -59605,20 +62322,13 @@ static int walCheckpoint(
mxSafeFrame = pWal->hdr.mxFrame;
mxPage = pWal->hdr.nPage;
for(i=1; iaReadMark[i];
+ u32 y = AtomicLoad(pInfo->aReadMark+i);
if( mxSafeFrame>y ){
assert( y<=pWal->hdr.mxFrame );
rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_READ_LOCK(i), 1);
if( rc==SQLITE_OK ){
- pInfo->aReadMark[i] = (i==1 ? mxSafeFrame : READMARK_NOT_USED);
+ u32 iMark = (i==1 ? mxSafeFrame : READMARK_NOT_USED);
+ AtomicStore(pInfo->aReadMark+i, iMark);
walUnlockExclusive(pWal, WAL_READ_LOCK(i), 1);
}else if( rc==SQLITE_BUSY ){
mxSafeFrame = y;
@@ -59636,7 +62346,7 @@ static int walCheckpoint(
}
if( pIter
- && (rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_READ_LOCK(0),1))==SQLITE_OK
+ && (rc = walBusyLock(pWal,xBusy,pBusyArg,WAL_READ_LOCK(0),1))==SQLITE_OK
){
u32 nBackfill = pInfo->nBackfill;
@@ -59651,18 +62361,27 @@ static int walCheckpoint(
if( rc==SQLITE_OK ){
i64 nReq = ((i64)mxPage * szPage);
i64 nSize; /* Current size of database file */
+ sqlite3OsFileControl(pWal->pDbFd, SQLITE_FCNTL_CKPT_START, 0);
rc = sqlite3OsFileSize(pWal->pDbFd, &nSize);
if( rc==SQLITE_OK && nSizepDbFd, SQLITE_FCNTL_SIZE_HINT, &nReq);
+ if( (nSize+65536+(i64)pWal->hdr.mxFrame*szPage)pDbFd, SQLITE_FCNTL_SIZE_HINT,&nReq);
+ }
}
- }
+ }
/* Iterate through the contents of the WAL, copying data to the db file */
while( rc==SQLITE_OK && 0==walIteratorNext(pIter, &iDbpage, &iFrame) ){
i64 iOffset;
assert( walFramePgno(pWal, iFrame)==iDbpage );
- if( db->u1.isInterrupted ){
+ if( AtomicLoad(&db->u1.isInterrupted) ){
rc = db->mallocFailed ? SQLITE_NOMEM_BKPT : SQLITE_INTERRUPT;
break;
}
@@ -59678,6 +62397,7 @@ static int walCheckpoint(
rc = sqlite3OsWrite(pWal->pDbFd, zBuf, szPage, iOffset);
if( rc!=SQLITE_OK ) break;
}
+ sqlite3OsFileControl(pWal->pDbFd, SQLITE_FCNTL_CKPT_DONE, 0);
/* If work was actually accomplished... */
if( rc==SQLITE_OK ){
@@ -59690,7 +62410,7 @@ static int walCheckpoint(
}
}
if( rc==SQLITE_OK ){
- pInfo->nBackfill = mxSafeFrame;
+ AtomicStore(&pInfo->nBackfill, mxSafeFrame);
}
}
@@ -59706,8 +62426,8 @@ static int walCheckpoint(
}
/* If this is an SQLITE_CHECKPOINT_RESTART or TRUNCATE operation, and the
- ** entire wal file has been copied into the database file, then block
- ** until all readers have finished using the wal file. This ensures that
+ ** entire wal file has been copied into the database file, then block
+ ** until all readers have finished using the wal file. This ensures that
** the next process to write to the database restarts the wal file.
*/
if( rc==SQLITE_OK && eMode!=SQLITE_CHECKPOINT_PASSIVE ){
@@ -59731,7 +62451,7 @@ static int walCheckpoint(
** writer clients should see that the entire log file has been
** checkpointed and behave accordingly. This seems unsafe though,
** as it would leave the system in a state where the contents of
- ** the wal-index header do not match the contents of the
+ ** the wal-index header do not match the contents of the
** file-system. To avoid this, update the wal-index header to
** indicate that the log file contains zero valid frames. */
walRestartHdr(pWal, salt1);
@@ -59793,7 +62513,7 @@ SQLITE_PRIVATE int sqlite3WalClose(
if( pWal->exclusiveMode==WAL_NORMAL_MODE ){
pWal->exclusiveMode = WAL_EXCLUSIVE_MODE;
}
- rc = sqlite3WalCheckpoint(pWal, db,
+ rc = sqlite3WalCheckpoint(pWal, db,
SQLITE_CHECKPOINT_PASSIVE, 0, 0, sync_flags, nBuf, zBuf, 0, 0
);
if( rc==SQLITE_OK ){
@@ -59849,7 +62569,7 @@ SQLITE_PRIVATE int sqlite3WalClose(
** If the checksum cannot be verified return non-zero. If the header
** is read successfully and the checksum verified, return zero.
*/
-static int walIndexTryHdr(Wal *pWal, int *pChanged){
+static SQLITE_NO_TSAN int walIndexTryHdr(Wal *pWal, int *pChanged){
u32 aCksum[2]; /* Checksum on the header content */
WalIndexHdr h1, h2; /* Two copies of the header content */
WalIndexHdr volatile *aHdr; /* Header in shared memory */
@@ -59862,19 +62582,25 @@ static int walIndexTryHdr(Wal *pWal, int *pChanged){
** meaning it is possible that an inconsistent snapshot is read
** from the file. If this happens, return non-zero.
**
+ ** tag-20200519-1:
** 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.
+ ** reordering the reads and writes. TSAN and similar tools can sometimes
+ ** give false-positive warnings about these accesses because the tools do not
+ ** account for the double-read and the memory barrier. The use of mutexes
+ ** here would be problematic as the memory being accessed is potentially
+ ** shared among multiple processes and not all mutex implementions work
+ ** reliably in that environment.
*/
aHdr = walIndexHdr(pWal);
- memcpy(&h1, (void *)&aHdr[0], sizeof(h1));
+ memcpy(&h1, (void *)&aHdr[0], sizeof(h1)); /* Possible TSAN false-positive */
walShmBarrier(pWal);
memcpy(&h2, (void *)&aHdr[1], sizeof(h2));
if( memcmp(&h1, &h2, sizeof(h1))!=0 ){
return 1; /* Dirty read */
- }
+ }
if( h1.isInit==0 ){
return 1; /* Malformed header - probably all zeros */
}
@@ -59910,7 +62636,7 @@ static int walIndexTryHdr(Wal *pWal, int *pChanged){
** changed by this operation. If pWal->hdr is unchanged, set *pChanged
** to 0.
**
-** If the wal-index header is successfully read, return SQLITE_OK.
+** If the wal-index header is successfully read, return SQLITE_OK.
** Otherwise an SQLite error code.
*/
static int walIndexReadHdr(Wal *pWal, int *pChanged){
@@ -59918,7 +62644,7 @@ static int walIndexReadHdr(Wal *pWal, int *pChanged){
int badHdr; /* True if a header read failed */
volatile u32 *page0; /* Chunk of wal-index containing header */
- /* Ensure that page 0 of the wal-index (the page that contains the
+ /* Ensure that page 0 of the wal-index (the page that contains the
** wal-index header) is mapped. Return early if an error occurs here.
*/
assert( pChanged );
@@ -59950,7 +62676,7 @@ static int walIndexReadHdr(Wal *pWal, int *pChanged){
/* If the first page of the wal-index has been mapped, try to read the
** wal-index header immediately, without holding any lock. This usually
- ** works, but may fail if the wal-index header is corrupt or currently
+ ** works, but may fail if the wal-index header is corrupt or currently
** being modified by another thread or process.
*/
badHdr = (page0 ? walIndexTryHdr(pWal, pChanged) : 1);
@@ -59958,28 +62684,32 @@ static int walIndexReadHdr(Wal *pWal, int *pChanged){
/* If the first attempt failed, it might have been due to a race
** with a writer. So get a WRITE lock and try again.
*/
- assert( badHdr==0 || pWal->writeLock==0 );
if( badHdr ){
if( pWal->bShmUnreliable==0 && (pWal->readOnly & WAL_SHM_RDONLY) ){
if( SQLITE_OK==(rc = walLockShared(pWal, WAL_WRITE_LOCK)) ){
walUnlockShared(pWal, WAL_WRITE_LOCK);
rc = SQLITE_READONLY_RECOVERY;
}
- }else if( SQLITE_OK==(rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1)) ){
- pWal->writeLock = 1;
- if( SQLITE_OK==(rc = walIndexPage(pWal, 0, &page0)) ){
- badHdr = walIndexTryHdr(pWal, pChanged);
- if( badHdr ){
- /* If the wal-index header is still malformed even while holding
- ** a WRITE lock, it can only mean that the header is corrupted and
- ** needs to be reconstructed. So run recovery to do exactly that.
- */
- rc = walIndexRecover(pWal);
- *pChanged = 1;
+ }else{
+ int bWriteLock = pWal->writeLock;
+ if( bWriteLock || SQLITE_OK==(rc = walLockWriter(pWal)) ){
+ pWal->writeLock = 1;
+ if( SQLITE_OK==(rc = walIndexPage(pWal, 0, &page0)) ){
+ badHdr = walIndexTryHdr(pWal, pChanged);
+ if( badHdr ){
+ /* If the wal-index header is still malformed even while holding
+ ** a WRITE lock, it can only mean that the header is corrupted and
+ ** needs to be reconstructed. So run recovery to do exactly that.
+ */
+ rc = walIndexRecover(pWal);
+ *pChanged = 1;
+ }
+ }
+ if( bWriteLock==0 ){
+ pWal->writeLock = 0;
+ walUnlockExclusive(pWal, WAL_WRITE_LOCK, 1);
}
}
- pWal->writeLock = 0;
- walUnlockExclusive(pWal, WAL_WRITE_LOCK, 1);
}
}
@@ -60021,15 +62751,15 @@ static int walIndexReadHdr(Wal *pWal, int *pChanged){
**
** The *-wal file has been read and an appropriate wal-index has been
** constructed in pWal->apWiData[] using heap memory instead of shared
-** memory.
+** memory.
**
** If this function returns SQLITE_OK, then the read transaction has
-** been successfully opened. In this case output variable (*pChanged)
+** been successfully opened. In this case output variable (*pChanged)
** is set to true before returning if the caller should discard the
-** contents of the page cache before proceeding. Or, if it returns
-** WAL_RETRY, then the heap memory wal-index has been discarded and
-** the caller should retry opening the read transaction from the
-** beginning (including attempting to map the *-shm file).
+** contents of the page cache before proceeding. Or, if it returns
+** WAL_RETRY, then the heap memory wal-index has been discarded and
+** the caller should retry opening the read transaction from the
+** beginning (including attempting to map the *-shm file).
**
** If an error occurs, an SQLite error code is returned.
*/
@@ -60140,8 +62870,8 @@ static int walBeginShmUnreliable(Wal *pWal, int *pChanged){
** the caller. */
aSaveCksum[0] = pWal->hdr.aFrameCksum[0];
aSaveCksum[1] = pWal->hdr.aFrameCksum[1];
- for(iOffset=walFrameOffset(pWal->hdr.mxFrame+1, pWal->hdr.szPage);
- iOffset+szFrame<=szWal;
+ for(iOffset=walFrameOffset(pWal->hdr.mxFrame+1, pWal->hdr.szPage);
+ iOffset+szFrame<=szWal;
iOffset+=szFrame
){
u32 pgno; /* Database page number for frame */
@@ -60189,10 +62919,10 @@ static int walBeginShmUnreliable(Wal *pWal, int *pChanged){
**
** The useWal parameter is true to force the use of the WAL and disable
** the case where the WAL is bypassed because it has been completely
-** checkpointed. If useWal==0 then this routine calls walIndexReadHdr()
-** to make a copy of the wal-index header into pWal->hdr. If the
-** wal-index header has changed, *pChanged is set to 1 (as an indication
-** to the caller that the local page cache is obsolete and needs to be
+** checkpointed. If useWal==0 then this routine calls walIndexReadHdr()
+** to make a copy of the wal-index header into pWal->hdr. If the
+** wal-index header has changed, *pChanged is set to 1 (as an indication
+** to the caller that the local page cache is obsolete and needs to be
** flushed.) When useWal==1, the wal-index header is assumed to already
** be loaded and the pChanged parameter is unused.
**
@@ -60207,7 +62937,7 @@ static int walBeginShmUnreliable(Wal *pWal, int *pChanged){
** bad luck when there is lots of contention for the wal-index, but that
** possibility is so small that it can be safely neglected, we believe.
**
-** On success, this routine obtains a read lock on
+** On success, this routine obtains a read lock on
** WAL_READ_LOCK(pWal->readLock). The pWal->readLock integer is
** in the range 0 <= pWal->readLock < WAL_NREADER. If pWal->readLock==(-1)
** that means the Wal does not hold any read lock. The reader must not
@@ -60245,16 +62975,16 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){
**
** Circumstances that cause a RETRY should only last for the briefest
** instances of time. No I/O or other system calls are done while the
- ** locks are held, so the locks should not be held for very long. But
+ ** locks are held, so the locks should not be held for very long. But
** if we are unlucky, another process that is holding a lock might get
- ** paged out or take a page-fault that is time-consuming to resolve,
+ ** paged out or take a page-fault that is time-consuming to resolve,
** during the few nanoseconds that it is holding the lock. In that case,
** it might take longer than normal for the lock to free.
**
** After 5 RETRYs, we begin calling sqlite3OsSleep(). The first few
** calls to sqlite3OsSleep() have a delay of 1 microsecond. Really this
** is more of a scheduler yield than an actual delay. But on the 10th
- ** an subsequent retries, the delays start becoming longer and longer,
+ ** an subsequent retries, the delays start becoming longer and longer,
** so that on the 100th (and last) RETRY we delay for 323 milliseconds.
** The total delay time before giving up is less than 10 seconds.
*/
@@ -60285,9 +63015,9 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){
if( pWal->apWiData[0]==0 ){
/* This branch is taken when the xShmMap() method returns SQLITE_BUSY.
** We assume this is a transient condition, so return WAL_RETRY. The
- ** xShmMap() implementation used by the default unix and win32 VFS
- ** modules may return SQLITE_BUSY due to a race condition in the
- ** code that determines whether or not the shared-memory region
+ ** xShmMap() implementation used by the default unix and win32 VFS
+ ** modules may return SQLITE_BUSY due to a race condition in the
+ ** code that determines whether or not the shared-memory region
** must be zeroed before the requested page is returned.
*/
rc = WAL_RETRY;
@@ -60309,7 +63039,7 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){
assert( pWal->nWiData>0 );
assert( pWal->apWiData[0]!=0 );
pInfo = walCkptInfo(pWal);
- if( !useWal && pInfo->nBackfill==pWal->hdr.mxFrame
+ if( !useWal && AtomicLoad(&pInfo->nBackfill)==pWal->hdr.mxFrame
#ifdef SQLITE_ENABLE_SNAPSHOT
&& (pWal->pSnapshot==0 || pWal->hdr.mxFrame==0)
#endif
@@ -60328,7 +63058,7 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){
** snapshot. Since holding READ_LOCK(0) prevents a checkpoint from
** happening, this is usually correct.
**
- ** However, if frames have been appended to the log (or if the log
+ ** However, if frames have been appended to the log (or if the log
** is wrapped and written for that matter) before the READ_LOCK(0)
** is obtained, that is not necessarily true. A checkpointer may
** have started to backfill the appended frames but crashed before
@@ -60371,7 +63101,8 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){
for(i=1; iaReadMark+i,mxFrame);
+ AtomicStore(pInfo->aReadMark+i,mxFrame);
+ mxReadMark = mxFrame;
mxI = i;
walUnlockExclusive(pWal, WAL_READ_LOCK(i), 1);
break;
@@ -60409,9 +63140,9 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){
** to read any frames earlier than minFrame from the wal file - they
** can be safely read directly from the database file.
**
- ** Because a ShmBarrier() call is made between taking the copy of
+ ** Because a ShmBarrier() call is made between taking the copy of
** nBackfill and checking that the wal-header in shared-memory still
- ** matches the one cached in pWal->hdr, it is guaranteed that the
+ ** matches the one cached in pWal->hdr, it is guaranteed that the
** checkpointer that set nBackfill was not working with a wal-index
** header newer than that cached in pWal->hdr. If it were, that could
** cause a problem. The checkpointer could omit to checkpoint
@@ -60439,15 +63170,15 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){
#ifdef SQLITE_ENABLE_SNAPSHOT
/*
-** Attempt to reduce the value of the WalCkptInfo.nBackfillAttempted
+** Attempt to reduce the value of the WalCkptInfo.nBackfillAttempted
** variable so that older snapshots can be accessed. To do this, loop
-** through all wal frames from nBackfillAttempted to (nBackfill+1),
+** through all wal frames from nBackfillAttempted to (nBackfill+1),
** comparing their content to the corresponding page with the database
** file, if any. Set nBackfillAttempted to the frame number of the
** first frame for which the wal file content matches the db file.
**
-** This is only really safe if the file-system is such that any page
-** writes made by earlier checkpointers were atomic operations, which
+** This is only really safe if the file-system is such that any page
+** writes made by earlier checkpointers were atomic operations, which
** is not always true. It is also possible that nBackfillAttempted
** may be left set to a value larger than expected, if a wal frame
** contains content that duplicate of an earlier version of the same
@@ -60475,7 +63206,7 @@ SQLITE_PRIVATE int sqlite3WalSnapshotRecover(Wal *pWal){
rc = SQLITE_NOMEM;
}else{
u32 i = pInfo->nBackfillAttempted;
- for(i=pInfo->nBackfillAttempted; i>pInfo->nBackfill; i--){
+ for(i=pInfo->nBackfillAttempted; i>AtomicLoad(&pInfo->nBackfill); i--){
WalHashLoc sLoc; /* Hash table location */
u32 pgno; /* Page number in db file */
i64 iDbOff; /* Offset of db file entry */
@@ -60530,12 +63261,35 @@ SQLITE_PRIVATE int sqlite3WalSnapshotRecover(Wal *pWal){
SQLITE_PRIVATE int sqlite3WalBeginReadTransaction(Wal *pWal, int *pChanged){
int rc; /* Return code */
int cnt = 0; /* Number of TryBeginRead attempts */
-
#ifdef SQLITE_ENABLE_SNAPSHOT
int bChanged = 0;
WalIndexHdr *pSnapshot = pWal->pSnapshot;
- if( pSnapshot && memcmp(pSnapshot, &pWal->hdr, sizeof(WalIndexHdr))!=0 ){
- bChanged = 1;
+#endif
+
+ assert( pWal->ckptLock==0 );
+
+#ifdef SQLITE_ENABLE_SNAPSHOT
+ if( pSnapshot ){
+ if( memcmp(pSnapshot, &pWal->hdr, sizeof(WalIndexHdr))!=0 ){
+ bChanged = 1;
+ }
+
+ /* It is possible that there is a checkpointer thread running
+ ** concurrent with this code. If this is the case, it may be that the
+ ** checkpointer has already determined that it will checkpoint
+ ** snapshot X, where X is later in the wal file than pSnapshot, but
+ ** has not yet set the pInfo->nBackfillAttempted variable to indicate
+ ** its intent. To avoid the race condition this leads to, ensure that
+ ** there is no checkpointer process by taking a shared CKPT lock
+ ** before checking pInfo->nBackfillAttempted. */
+ (void)walEnableBlocking(pWal);
+ rc = walLockShared(pWal, WAL_CKPT_LOCK);
+ walDisableBlocking(pWal);
+
+ if( rc!=SQLITE_OK ){
+ return rc;
+ }
+ pWal->ckptLock = 1;
}
#endif
@@ -60568,48 +63322,42 @@ SQLITE_PRIVATE int sqlite3WalBeginReadTransaction(Wal *pWal, int *pChanged){
assert( pWal->readLock>0 || pWal->hdr.mxFrame==0 );
assert( pInfo->aReadMark[pWal->readLock]<=pSnapshot->mxFrame );
- /* It is possible that there is a checkpointer thread running
- ** concurrent with this code. If this is the case, it may be that the
- ** checkpointer has already determined that it will checkpoint
- ** snapshot X, where X is later in the wal file than pSnapshot, but
- ** has not yet set the pInfo->nBackfillAttempted variable to indicate
- ** its intent. To avoid the race condition this leads to, ensure that
- ** there is no checkpointer process by taking a shared CKPT lock
- ** before checking pInfo->nBackfillAttempted.
- **
- ** TODO: Does the aReadMark[] lock prevent a checkpointer from doing
- ** this already?
- */
- rc = walLockShared(pWal, WAL_CKPT_LOCK);
-
- if( rc==SQLITE_OK ){
- /* Check that the wal file has not been wrapped. Assuming that it has
- ** not, also check that no checkpointer has attempted to checkpoint any
- ** frames beyond pSnapshot->mxFrame. If either of these conditions are
- ** true, return SQLITE_ERROR_SNAPSHOT. Otherwise, overwrite pWal->hdr
- ** with *pSnapshot and set *pChanged as appropriate for opening the
- ** snapshot. */
- if( !memcmp(pSnapshot->aSalt, pWal->hdr.aSalt, sizeof(pWal->hdr.aSalt))
- && pSnapshot->mxFrame>=pInfo->nBackfillAttempted
- ){
- assert( pWal->readLock>0 );
- memcpy(&pWal->hdr, pSnapshot, sizeof(WalIndexHdr));
- *pChanged = bChanged;
- }else{
- rc = SQLITE_ERROR_SNAPSHOT;
- }
-
- /* Release the shared CKPT lock obtained above. */
- walUnlockShared(pWal, WAL_CKPT_LOCK);
- pWal->minFrame = 1;
+ /* Check that the wal file has not been wrapped. Assuming that it has
+ ** not, also check that no checkpointer has attempted to checkpoint any
+ ** frames beyond pSnapshot->mxFrame. If either of these conditions are
+ ** true, return SQLITE_ERROR_SNAPSHOT. Otherwise, overwrite pWal->hdr
+ ** with *pSnapshot and set *pChanged as appropriate for opening the
+ ** snapshot. */
+ if( !memcmp(pSnapshot->aSalt, pWal->hdr.aSalt, sizeof(pWal->hdr.aSalt))
+ && pSnapshot->mxFrame>=pInfo->nBackfillAttempted
+ ){
+ assert( pWal->readLock>0 );
+ memcpy(&pWal->hdr, pSnapshot, sizeof(WalIndexHdr));
+ *pChanged = bChanged;
+ }else{
+ rc = SQLITE_ERROR_SNAPSHOT;
}
+ /* A client using a non-current snapshot may not ignore any frames
+ ** from the start of the wal file. This is because, for a system
+ ** where (minFrame < iSnapshot < maxFrame), a checkpointer may
+ ** have omitted to checkpoint a frame earlier than minFrame in
+ ** the file because there exists a frame after iSnapshot that
+ ** is the same database page. */
+ pWal->minFrame = 1;
if( rc!=SQLITE_OK ){
sqlite3WalEndReadTransaction(pWal);
}
}
}
+
+ /* Release the shared CKPT lock obtained above. */
+ if( pWal->ckptLock ){
+ assert( pSnapshot );
+ walUnlockShared(pWal, WAL_CKPT_LOCK);
+ pWal->ckptLock = 0;
+ }
#endif
return rc;
}
@@ -60649,8 +63397,8 @@ SQLITE_PRIVATE int sqlite3WalFindFrame(
/* 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 as an optimization. Likewise, if pWal->readLock==0,
- ** then the WAL is ignored by the reader so return early, as if the
+ ** in this case as an optimization. Likewise, if pWal->readLock==0,
+ ** then the WAL is ignored by the reader so return early, as if the
** WAL were empty.
*/
if( iLast==0 || (pWal->readLock==0 && pWal->bShmUnreliable==0) ){
@@ -60663,9 +63411,9 @@ SQLITE_PRIVATE int sqlite3WalFindFrame(
** hash table (each hash table indexes up to HASHTABLE_NPAGE frames).
**
** This code might 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
+ ** 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
@@ -60673,13 +63421,13 @@ SQLITE_PRIVATE int sqlite3WalFindFrame(
** 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
+ ** loop of the following block is more stringent that would be required
** if we had exclusive access to the hash-table:
**
- ** (aPgno[iFrame]==pgno):
+ ** (aPgno[iFrame]==pgno):
** This condition filters out normal hash-table collisions.
**
- ** (iFrame<=iLast):
+ ** (iFrame<=iLast):
** This condition filters out entries that were added to the hash
** table after the current read-transaction had started.
*/
@@ -60689,22 +63437,24 @@ SQLITE_PRIVATE int sqlite3WalFindFrame(
int iKey; /* Hash slot index */
int nCollide; /* Number of hash collisions remaining */
int rc; /* Error code */
+ u32 iH;
rc = walHashGet(pWal, iHash, &sLoc);
if( rc!=SQLITE_OK ){
return rc;
}
nCollide = HASHTABLE_NSLOT;
- for(iKey=walHash(pgno); sLoc.aHash[iKey]; iKey=walNextHash(iKey)){
- u32 iFrame = sLoc.aHash[iKey] + sLoc.iZero;
- if( iFrame<=iLast && iFrame>=pWal->minFrame
- && sLoc.aPgno[sLoc.aHash[iKey]]==pgno ){
+ iKey = walHash(pgno);
+ while( (iH = AtomicLoad(&sLoc.aHash[iKey]))!=0 ){
+ u32 iFrame = iH + sLoc.iZero;
+ if( iFrame<=iLast && iFrame>=pWal->minFrame && sLoc.aPgno[iH]==pgno ){
assert( iFrame>iRead || CORRUPT_DB );
iRead = iFrame;
}
if( (nCollide--)==0 ){
return SQLITE_CORRUPT_BKPT;
}
+ iKey = walNextHash(iKey);
}
if( iRead ) break;
}
@@ -60753,7 +63503,7 @@ SQLITE_PRIVATE int sqlite3WalReadFrame(
return sqlite3OsRead(pWal->pWalFd, pOut, (nOut>sz ? sz : nOut), iOffset);
}
-/*
+/*
** Return the size of the database in pages (or zero, if unknown).
*/
SQLITE_PRIVATE Pgno sqlite3WalDbsize(Wal *pWal){
@@ -60764,7 +63514,7 @@ SQLITE_PRIVATE Pgno sqlite3WalDbsize(Wal *pWal){
}
-/*
+/*
** This function starts a write transaction on the WAL.
**
** A read transaction must have already been started by a prior call
@@ -60780,6 +63530,16 @@ SQLITE_PRIVATE Pgno sqlite3WalDbsize(Wal *pWal){
SQLITE_PRIVATE int sqlite3WalBeginWriteTransaction(Wal *pWal){
int rc;
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+ /* If the write-lock is already held, then it was obtained before the
+ ** read-transaction was even opened, making this call a no-op.
+ ** Return early. */
+ if( pWal->writeLock ){
+ assert( !memcmp(&pWal->hdr,(void *)walIndexHdr(pWal),sizeof(WalIndexHdr)) );
+ return SQLITE_OK;
+ }
+#endif
+
/* Cannot start a write transaction without first holding a read
** transaction. */
assert( pWal->readLock>=0 );
@@ -60842,18 +63602,18 @@ SQLITE_PRIVATE int sqlite3WalUndo(Wal *pWal, int (*xUndo)(void *, Pgno), void *p
if( ALWAYS(pWal->writeLock) ){
Pgno iMax = pWal->hdr.mxFrame;
Pgno iFrame;
-
+
/* Restore the clients cache of the wal-index header to the state it
- ** was in before the client began writing to the database.
+ ** was in before the client began writing to the database.
*/
memcpy(&pWal->hdr, (void *)walIndexHdr(pWal), sizeof(WalIndexHdr));
- for(iFrame=pWal->hdr.mxFrame+1;
- ALWAYS(rc==SQLITE_OK) && iFrame<=iMax;
+ for(iFrame=pWal->hdr.mxFrame+1;
+ ALWAYS(rc==SQLITE_OK) && iFrame<=iMax;
iFrame++
){
/* This call cannot fail. Unless the page for which the page number
- ** is passed as the second argument is (a) in the cache and
+ ** is passed as the second argument is (a) in the cache and
** (b) has an outstanding reference, then xUndo is either a no-op
** (if (a) is false) or simply expels the page from the cache (if (b)
** is false).
@@ -60871,10 +63631,10 @@ SQLITE_PRIVATE int sqlite3WalUndo(Wal *pWal, int (*xUndo)(void *, Pgno), void *p
return rc;
}
-/*
-** Argument aWalData must point to an array of WAL_SAVEPOINT_NDATA u32
-** values. This function populates the array with values required to
-** "rollback" the write position of the WAL handle back to the current
+/*
+** Argument aWalData must point to an array of WAL_SAVEPOINT_NDATA u32
+** values. This function populates the array with values required to
+** "rollback" the write position of the WAL handle back to the current
** point in the event of a savepoint rollback (via WalSavepointUndo()).
*/
SQLITE_PRIVATE void sqlite3WalSavepoint(Wal *pWal, u32 *aWalData){
@@ -60885,7 +63645,7 @@ SQLITE_PRIVATE void sqlite3WalSavepoint(Wal *pWal, u32 *aWalData){
aWalData[3] = pWal->nCkpt;
}
-/*
+/*
** Move the write position of the WAL back to the point identified by
** the values in the aWalData[] array. aWalData must point to an array
** of WAL_SAVEPOINT_NDATA u32 values that has been previously populated
@@ -61025,11 +63785,7 @@ static int walWriteOneFrame(
int rc; /* Result code from subfunctions */
void *pData; /* Data actually written */
u8 aFrame[WAL_FRAME_HDRSIZE]; /* Buffer to assemble frame-header in */
-#if defined(SQLITE_HAS_CODEC)
- if( (pData = sqlite3PagerCodec(pPage))==0 ) return SQLITE_NOMEM_BKPT;
-#else
pData = pPage->pData;
-#endif
walEncodeFrame(p->pWal, pPage->pgno, nTruncate, pData, aFrame);
rc = walWriteToLog(p, aFrame, sizeof(aFrame), iOffset);
if( rc ) return rc;
@@ -61091,7 +63847,7 @@ static int walRewriteChecksums(Wal *pWal, u32 iLast){
return rc;
}
-/*
+/*
** Write a set of frames to the log. The caller must hold the write-lock
** on the log file (obtained using sqlite3WalBeginWriteTransaction()).
*/
@@ -61158,7 +63914,7 @@ SQLITE_PRIVATE int sqlite3WalFrames(
walChecksumBytes(1, aWalHdr, WAL_HDRSIZE-2*4, 0, aCksum);
sqlite3Put4byte(&aWalHdr[24], aCksum[0]);
sqlite3Put4byte(&aWalHdr[28], aCksum[1]);
-
+
pWal->szPage = szPage;
pWal->hdr.bigEndCksum = SQLITE_BIGENDIAN;
pWal->hdr.aFrameCksum[0] = aCksum[0];
@@ -61200,7 +63956,7 @@ SQLITE_PRIVATE int sqlite3WalFrames(
/* Check if this page has already been written into the wal file by
** the current transaction. If so, overwrite the existing frame and
- ** set Wal.writeLock to WAL_WRITELOCK_RECKSUM - indicating that
+ ** set Wal.writeLock to WAL_WRITELOCK_RECKSUM - indicating that
** checksums must be recomputed when the transaction is committed. */
if( iFirst && (p->pDirty || isCommit==0) ){
u32 iWrite = 0;
@@ -61212,11 +63968,7 @@ SQLITE_PRIVATE int sqlite3WalFrames(
if( pWal->iReCksum==0 || iWriteiReCksum ){
pWal->iReCksum = iWrite;
}
-#if defined(SQLITE_HAS_CODEC)
- if( (pData = sqlite3PagerCodec(p))==0 ) return SQLITE_NOMEM;
-#else
pData = p->pData;
-#endif
rc = sqlite3OsWrite(pWal->pWalFd, pData, szPage, iOff);
if( rc ) return rc;
p->flags &= ~PGHDR_WAL_APPEND;
@@ -61266,6 +64018,7 @@ SQLITE_PRIVATE int sqlite3WalFrames(
if( rc ) return rc;
iOffset += szFrame;
nExtra++;
+ assert( pLast!=0 );
}
}
if( bSync ){
@@ -61287,7 +64040,7 @@ SQLITE_PRIVATE int sqlite3WalFrames(
pWal->truncateOnCommit = 0;
}
- /* Append data to the wal-index. It is not necessary to lock the
+ /* 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.
@@ -61298,6 +64051,7 @@ SQLITE_PRIVATE int sqlite3WalFrames(
iFrame++;
rc = walIndexAppend(pWal, iFrame, p->pgno);
}
+ assert( pLast!=0 || nExtra==0 );
while( rc==SQLITE_OK && nExtra>0 ){
iFrame++;
nExtra--;
@@ -61325,7 +64079,7 @@ SQLITE_PRIVATE int sqlite3WalFrames(
return rc;
}
-/*
+/*
** This routine is called to implement sqlite3_wal_checkpoint() and
** related interfaces.
**
@@ -61362,45 +64116,52 @@ SQLITE_PRIVATE int sqlite3WalCheckpoint(
if( pWal->readOnly ) return SQLITE_READONLY;
WALTRACE(("WAL%p: checkpoint begins\n", pWal));
- /* IMPLEMENTATION-OF: R-62028-47212 All calls obtain an exclusive
- ** "checkpoint" lock on the database file. */
- rc = walLockExclusive(pWal, WAL_CKPT_LOCK, 1);
- if( rc ){
- /* EVIDENCE-OF: R-10421-19736 If any other process is running a
- ** checkpoint operation at the same time, the lock cannot be obtained and
- ** SQLITE_BUSY is returned.
- ** EVIDENCE-OF: R-53820-33897 Even if there is a busy-handler configured,
- ** it will not be invoked in this case.
- */
- testcase( rc==SQLITE_BUSY );
- testcase( xBusy!=0 );
- return rc;
- }
- pWal->ckptLock = 1;
+ /* Enable blocking locks, if possible. If blocking locks are successfully
+ ** enabled, set xBusy2=0 so that the busy-handler is never invoked. */
+ sqlite3WalDb(pWal, db);
+ (void)walEnableBlocking(pWal);
- /* IMPLEMENTATION-OF: R-59782-36818 The SQLITE_CHECKPOINT_FULL, RESTART and
- ** TRUNCATE modes also obtain the exclusive "writer" lock on the database
- ** file.
- **
- ** EVIDENCE-OF: R-60642-04082 If the writer lock cannot be obtained
- ** immediately, and a busy-handler is configured, it is invoked and the
- ** writer lock retried until either the busy-handler returns 0 or the
- ** lock is successfully obtained.
+ /* IMPLEMENTATION-OF: R-62028-47212 All calls obtain an exclusive
+ ** "checkpoint" lock on the database file.
+ ** EVIDENCE-OF: R-10421-19736 If any other process is running a
+ ** checkpoint operation at the same time, the lock cannot be obtained and
+ ** SQLITE_BUSY is returned.
+ ** EVIDENCE-OF: R-53820-33897 Even if there is a busy-handler configured,
+ ** it will not be invoked in this case.
*/
- if( eMode!=SQLITE_CHECKPOINT_PASSIVE ){
- rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_WRITE_LOCK, 1);
- if( rc==SQLITE_OK ){
- pWal->writeLock = 1;
- }else if( rc==SQLITE_BUSY ){
- eMode2 = SQLITE_CHECKPOINT_PASSIVE;
- xBusy2 = 0;
- rc = SQLITE_OK;
+ rc = walLockExclusive(pWal, WAL_CKPT_LOCK, 1);
+ testcase( rc==SQLITE_BUSY );
+ testcase( rc!=SQLITE_OK && xBusy2!=0 );
+ if( rc==SQLITE_OK ){
+ pWal->ckptLock = 1;
+
+ /* IMPLEMENTATION-OF: R-59782-36818 The SQLITE_CHECKPOINT_FULL, RESTART and
+ ** TRUNCATE modes also obtain the exclusive "writer" lock on the database
+ ** file.
+ **
+ ** EVIDENCE-OF: R-60642-04082 If the writer lock cannot be obtained
+ ** immediately, and a busy-handler is configured, it is invoked and the
+ ** writer lock retried until either the busy-handler returns 0 or the
+ ** lock is successfully obtained.
+ */
+ if( eMode!=SQLITE_CHECKPOINT_PASSIVE ){
+ rc = walBusyLock(pWal, xBusy2, pBusyArg, WAL_WRITE_LOCK, 1);
+ if( rc==SQLITE_OK ){
+ pWal->writeLock = 1;
+ }else if( rc==SQLITE_BUSY ){
+ eMode2 = SQLITE_CHECKPOINT_PASSIVE;
+ xBusy2 = 0;
+ rc = SQLITE_OK;
+ }
}
}
+
/* Read the wal-index header. */
if( rc==SQLITE_OK ){
+ walDisableBlocking(pWal);
rc = walIndexReadHdr(pWal, &isChanged);
+ (void)walEnableBlocking(pWal);
if( isChanged && pWal->pDbFd->pMethods->iVersion>=3 ){
sqlite3OsUnfetch(pWal->pDbFd, 0, 0);
}
@@ -61423,7 +64184,7 @@ SQLITE_PRIVATE int sqlite3WalCheckpoint(
}
if( isChanged ){
- /* If a new wal-index header was loaded before the checkpoint was
+ /* 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
@@ -61432,11 +64193,19 @@ SQLITE_PRIVATE int sqlite3WalCheckpoint(
memset(&pWal->hdr, 0, sizeof(WalIndexHdr));
}
+ walDisableBlocking(pWal);
+ sqlite3WalDb(pWal, 0);
+
/* Release the locks. */
sqlite3WalEndWriteTransaction(pWal);
- walUnlockExclusive(pWal, WAL_CKPT_LOCK, 1);
- pWal->ckptLock = 0;
+ if( pWal->ckptLock ){
+ walUnlockExclusive(pWal, WAL_CKPT_LOCK, 1);
+ pWal->ckptLock = 0;
+ }
WALTRACE(("WAL%p: checkpoint %s\n", pWal, rc ? "failed" : "ok"));
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+ if( rc==SQLITE_BUSY_TIMEOUT ) rc = SQLITE_BUSY;
+#endif
return (rc==SQLITE_OK && eMode!=eMode2 ? SQLITE_BUSY : rc);
}
@@ -61466,7 +64235,7 @@ SQLITE_PRIVATE int sqlite3WalCallback(Wal *pWal){
** operation must occur while the pager is still holding the exclusive
** lock on the main database file.
**
-** If op is one, then change from locking_mode=NORMAL into
+** If op is one, then change from locking_mode=NORMAL into
** locking_mode=EXCLUSIVE. This means that the pWal->readLock must
** be released. Return 1 if the transition is made and 0 if the
** WAL is already in exclusive-locking mode - meaning that this
@@ -61483,8 +64252,8 @@ SQLITE_PRIVATE int sqlite3WalExclusiveMode(Wal *pWal, int op){
assert( pWal->writeLock==0 );
assert( pWal->exclusiveMode!=WAL_HEAPMEMORY_MODE || op==-1 );
- /* pWal->readLock is usually set, but might be -1 if there was a
- ** prior error while attempting to acquire are read-lock. This cannot
+ /* pWal->readLock is usually set, but might be -1 if there was a
+ ** prior error while attempting to acquire are read-lock. This cannot
** happen if the connection is actually in exclusive mode (as no xShmLock
** locks are taken in this case). Nor should the pager attempt to
** upgrade to exclusive-mode following such an error.
@@ -61515,10 +64284,10 @@ SQLITE_PRIVATE int sqlite3WalExclusiveMode(Wal *pWal, int op){
return rc;
}
-/*
+/*
** Return true if the argument is non-NULL and the WAL module is using
** heap-memory for the wal-index. Otherwise, if the argument is NULL or the
-** WAL module is using shared-memory, return false.
+** WAL module is using shared-memory, return false.
*/
SQLITE_PRIVATE int sqlite3WalHeapMemory(Wal *pWal){
return (pWal && pWal->exclusiveMode==WAL_HEAPMEMORY_MODE );
@@ -61553,11 +64322,14 @@ SQLITE_PRIVATE int sqlite3WalSnapshotGet(Wal *pWal, sqlite3_snapshot **ppSnapsho
/* Try to open on pSnapshot when the next read-transaction starts
*/
-SQLITE_PRIVATE void sqlite3WalSnapshotOpen(Wal *pWal, sqlite3_snapshot *pSnapshot){
+SQLITE_PRIVATE void sqlite3WalSnapshotOpen(
+ Wal *pWal,
+ sqlite3_snapshot *pSnapshot
+){
pWal->pSnapshot = (WalIndexHdr*)pSnapshot;
}
-/*
+/*
** Return a +ve value if snapshot p1 is newer than p2. A -ve value if
** p1 is older than p2 and zero if p1 and p2 are the same snapshot.
*/
@@ -61577,7 +64349,7 @@ SQLITE_API int sqlite3_snapshot_cmp(sqlite3_snapshot *p1, sqlite3_snapshot *p2){
/*
** The caller currently has a read transaction open on the database.
** This function takes a SHARED lock on the CHECKPOINTER slot and then
-** checks if the snapshot passed as the second argument is still
+** checks if the snapshot passed as the second argument is still
** available. If so, SQLITE_OK is returned.
**
** If the snapshot is not available, SQLITE_ERROR is returned. Or, if
@@ -61684,16 +64456,16 @@ SQLITE_PRIVATE sqlite3_file *sqlite3WalFile(Wal *pWal){
** 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.
**
@@ -61823,7 +64595,7 @@ SQLITE_PRIVATE sqlite3_file *sqlite3WalFile(Wal *pWal){
** 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.
@@ -61896,7 +64668,7 @@ typedef struct CellInfo CellInfo;
** -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.
*/
@@ -61941,7 +64713,7 @@ struct MemPage {
u16 maxLocal; /* Copy of BtShared.maxLocal or BtShared.maxLeaf */
u16 minLocal; /* Copy of BtShared.minLocal or BtShared.minLeaf */
u16 cellOffset; /* Index in aData of first cell pointer */
- u16 nFree; /* Number of free bytes on the page */
+ int nFree; /* Number of free bytes on the page. -1 for unknown */
u16 nCell; /* Number of cells on this page, local and ovfl */
u16 maskPage; /* Mask for page offset */
u16 aiOvfl[4]; /* Insert the i-th overflow cell before the aiOvfl-th
@@ -61959,7 +64731,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.
@@ -61983,7 +64755,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
@@ -61991,7 +64763,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 go through this Btree to find their BtShared and
** they often do so without holding sqlite3.mutex.
@@ -62005,9 +64777,12 @@ struct Btree {
u8 hasIncrblobCur; /* True if there are one or more Incrblob cursors */
int wantToLock; /* Number of nested calls to sqlite3BtreeEnter() */
int nBackup; /* Number of backup operations reading this btree */
- u32 iDataVersion; /* Combines with pBt->pPager->iDataVersion */
+ u32 iBDataVersion; /* Combines with pBt->pPager->iDataVersion */
Btree *pNext; /* List of other sharable Btrees from the same db */
Btree *pPrev; /* Back pointer of the same list */
+#ifdef SQLITE_DEBUG
+ u64 nSeek; /* Calls to sqlite3BtreeMovetoUnpacked() */
+#endif
#ifndef SQLITE_OMIT_SHARED_CACHE
BtLock lock; /* Object used to lock page 1 */
#endif
@@ -62019,14 +64794,28 @@ struct Btree {
** If the shared-data extension is enabled, there may be multiple users
** of the Btree structure. At most one of these may open a write transaction,
** but any number may have active read transactions.
+**
+** These values must match SQLITE_TXN_NONE, SQLITE_TXN_READ, and
+** SQLITE_TXN_WRITE
*/
#define TRANS_NONE 0
#define TRANS_READ 1
#define TRANS_WRITE 2
+#if TRANS_NONE!=SQLITE_TXN_NONE
+# error wrong numeric code for no-transaction
+#endif
+#if TRANS_READ!=SQLITE_TXN_READ
+# error wrong numeric code for read-transaction
+#endif
+#if TRANS_WRITE!=SQLITE_TXN_WRITE
+# error wrong numeric code for write-transaction
+#endif
+
+
/*
** An instance of this object represents a single database file.
-**
+**
** A single database file can be in use at 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
@@ -62036,7 +64825,7 @@ struct Btree {
**
** Fields in this structure are accessed under the BtShared.mutex
** mutex, except for nRef and pNext which are accessed under the
-** global SQLITE_MUTEX_STATIC_MASTER mutex. The pPager field
+** global SQLITE_MUTEX_STATIC_MAIN mutex. The pPager field
** may not be modified once it is initially set as long as nRef>0.
** The pSchema field may be set once under BtShared.mutex and
** thereafter is unchanged as long as nRef>0.
@@ -62072,9 +64861,7 @@ struct BtShared {
#endif
u8 inTransaction; /* Transaction state */
u8 max1bytePayload; /* Maximum first byte of cell for a 1-byte payload */
-#ifdef SQLITE_HAS_CODEC
- u8 optimalReserve; /* Desired amount of reserved space per page */
-#endif
+ u8 nReserveWanted; /* Desired number of extra bytes per page */
u16 btsFlags; /* Boolean parameters. See BTS_* macros below */
u16 maxLocal; /* Maximum local payload in non-LEAFDATA tables */
u16 minLocal; /* Minimum local payload in non-LEAFDATA tables */
@@ -62095,6 +64882,7 @@ struct BtShared {
Btree *pWriter; /* Btree with currently open write transaction */
#endif
u8 *pTmpSpace; /* Temp space sufficient to hold a single cell */
+ int nPreformatSize; /* Size of last cell written by TransferRow() */
};
/*
@@ -62146,12 +64934,19 @@ 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.
**
** skipNext meaning:
-** eState==SKIPNEXT && skipNext>0: Next sqlite3BtreeNext() is no-op.
-** eState==SKIPNEXT && skipNext<0: Next sqlite3BtreePrevious() is no-op.
-** eState==FAULT: Cursor fault with skipNext as error code.
+** The meaning of skipNext depends on the value of eState:
+**
+** eState Meaning of skipNext
+** VALID skipNext is meaningless and is ignored
+** INVALID skipNext is meaningless and is ignored
+** SKIPNEXT sqlite3BtreeNext() is a no-op if skipNext>0 and
+** sqlite3BtreePrevious() is no-op if skipNext<0.
+** REQUIRESEEK restoreCursorPosition() restores the cursor to
+** eState=SKIPNEXT if skipNext!=0
+** FAULT skipNext holds the cursor fault error code.
*/
struct BtCursor {
u8 eState; /* One of the CURSOR_XXX constants (see below) */
@@ -62190,12 +64985,13 @@ struct BtCursor {
#define BTCF_AtLast 0x08 /* Cursor is pointing ot the last entry */
#define BTCF_Incrblob 0x10 /* True if an incremental I/O handle */
#define BTCF_Multiple 0x20 /* Maybe another cursor on the same btree */
+#define BTCF_Pinned 0x40 /* Cursor is busy and cannot be moved */
/*
** Potential values for BtCursor.eState.
**
** 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.
**
@@ -62208,9 +65004,9 @@ struct BtCursor {
** operation should be a no-op.
**
** 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.
**
@@ -62227,13 +65023,13 @@ struct BtCursor {
#define CURSOR_REQUIRESEEK 3
#define CURSOR_FAULT 4
-/*
+/*
** 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.
@@ -62268,10 +65064,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.
**
@@ -62293,13 +65089,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.
*/
@@ -62316,8 +65112,8 @@ struct BtCursor {
**
** The aRef[] array is allocated so that there is 1 bit for each page in
** the database. As the integrity-check proceeds, for each page used in
-** the database the corresponding bit is set. This allows integrity-check to
-** detect pages that are used twice and orphaned pages (both of which
+** the database the corresponding bit is set. This allows integrity-check to
+** detect pages that are used twice and orphaned pages (both of which
** indicate corruption).
*/
typedef struct IntegrityCk IntegrityCk;
@@ -62328,11 +65124,13 @@ struct IntegrityCk {
Pgno nPage; /* Number of pages in the database */
int mxErr; /* Stop accumulating errors when this reaches zero */
int nErr; /* Number of messages written to zErrMsg so far */
- int mallocFailed; /* A memory allocation error has occurred */
+ int bOomFault; /* A memory allocation error has occurred */
const char *zPfx; /* Error message prefix */
- int v1, v2; /* Values for up to two %d fields in zPfx */
+ Pgno v1; /* Value for first %u substitution in zPfx */
+ int v2; /* Value for second %d substitution in zPfx */
StrAccum errMsg; /* Accumulate the error message text here */
u32 *heap; /* Min-heap used for analyzing cell coverage */
+ sqlite3 *db; /* Database connection running the check */
};
/*
@@ -62633,10 +65431,10 @@ SQLITE_PRIVATE void sqlite3BtreeEnterAll(sqlite3 *db){
#ifndef SQLITE_OMIT_INCRBLOB
/*
-** Enter a mutex on a Btree given a cursor owned by that Btree.
+** Enter a mutex on a Btree given a cursor owned by that Btree.
**
-** These entry points are used by incremental I/O only. Enter() is required
-** any time OMIT_SHARED_CACHE is not defined, regardless of whether or not
+** These entry points are used by incremental I/O only. Enter() is required
+** any time OMIT_SHARED_CACHE is not defined, regardless of whether or not
** the build is threadsafe. Leave() is only required by threadsafe builds.
*/
SQLITE_PRIVATE void sqlite3BtreeEnterCursor(BtCursor *pCur){
@@ -62706,7 +65504,7 @@ int sqlite3BtreeTrace=1; /* True to enable tracing */
#define BTALLOC_LE 2 /* Allocate any page <= the parameter */
/*
-** Macro IfNotOmitAV(x) returns (x) if SQLITE_OMIT_AUTOVACUUM is not
+** Macro IfNotOmitAV(x) returns (x) if SQLITE_OMIT_AUTOVACUUM is not
** defined, or 0 if it is. For example:
**
** bIncrVacuum = IfNotOmitAV(pBtShared->incrVacuum);
@@ -62721,10 +65519,10 @@ 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.
+** Access to this variable is protected by SQLITE_MUTEX_STATIC_MAIN.
*/
#ifdef SQLITE_TEST
SQLITE_PRIVATE BtShared *SQLITE_WSD sqlite3SharedCacheList = 0;
@@ -62756,7 +65554,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
@@ -62767,6 +65565,17 @@ SQLITE_API int sqlite3_enable_shared_cache(int enable){
#define hasReadConflicts(a, b) 0
#endif
+#ifdef SQLITE_DEBUG
+/*
+** Return and reset the seek counter for a Btree object.
+*/
+SQLITE_PRIVATE sqlite3_uint64 sqlite3BtreeSeekCount(Btree *pBt){
+ u64 n = pBt->nSeek;
+ pBt->nSeek = 0;
+ return n;
+}
+#endif
+
/*
** Implementation of the SQLITE_CORRUPT_PAGE() macro. Takes a single
** (MemPage*) as an argument. The (MemPage*) must not be NULL.
@@ -62801,15 +65610,15 @@ int corruptPageError(int lineno, MemPage *p){
/*
**** 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
@@ -62831,7 +65640,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)
@@ -62855,29 +65664,31 @@ static int hasSharedCacheTableLock(
** table. */
if( isIndex ){
HashElem *p;
+ int bSeen = 0;
for(p=sqliteHashFirst(&pSchema->idxHash); p; p=sqliteHashNext(p)){
Index *pIdx = (Index *)sqliteHashData(p);
if( pIdx->tnum==(int)iRoot ){
- if( iTab ){
+ if( bSeen ){
/* Two or more indexes share the same root page. There must
** be imposter tables. So just return true. The assert is not
** useful in that case. */
return 1;
}
iTab = pIdx->pTable->tnum;
+ bSeen = 1;
}
}
}else{
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;
}
@@ -62910,7 +65721,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_ReadUncommit)
){
@@ -62922,7 +65733,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.
@@ -62935,14 +65746,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_ReadUncommit)||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;
@@ -62957,7 +65768,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)
@@ -62984,7 +65795,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:
@@ -62996,7 +65807,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){
@@ -63010,11 +65821,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_schema
** table, and that lock is obtained in BtreeBeginTrans(). */
assert( 0==(p->db->flags&SQLITE_ReadUncommit) || 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) );
@@ -63059,7 +65870,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 BTS_PENDING flag
** may be incorrectly cleared.
*/
@@ -63091,7 +65902,7 @@ static void clearAllSharedCacheTableLocks(Btree *p){
pBt->pWriter = 0;
pBt->btsFlags &= ~(BTS_EXCLUSIVE|BTS_PENDING);
}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
@@ -63137,7 +65948,7 @@ static int cursorHoldsMutex(BtCursor *p){
}
/* Verify that the cursor and the BtShared agree about what is the current
-** database connetion. This is important in shared-cache mode. If the database
+** database connetion. This is important in shared-cache mode. If the database
** connection pointers get out-of-sync, it is possible for routines like
** btreeInitPage() to reference an stale connection pointer that references a
** a connection that has already closed. This routine is used inside assert()
@@ -63189,7 +66000,7 @@ static void invalidateIncrblobCursors(
int isClearTable /* True if all rows are being deleted */
){
BtCursor *p;
- if( pBtree->hasIncrblobCur==0 ) return;
+ assert( pBtree->hasIncrblobCur );
assert( sqlite3BtreeHoldsMutex(pBtree) );
pBtree->hasIncrblobCur = 0;
for(p=pBtree->pBt->pCursor; p; p=p->pNext){
@@ -63208,8 +66019,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
@@ -63235,7 +66046,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
@@ -63266,7 +66077,7 @@ static int btreeSetHasContent(BtShared *pBt, Pgno pgno){
*/
static int btreeGetHasContent(BtShared *pBt, Pgno pgno){
Bitvec *p = pBt->pHasContent;
- return (p && (pgno>sqlite3BitvecSize(p) || sqlite3BitvecTest(p, pgno)));
+ return p && (pgno>sqlite3BitvecSize(p) || sqlite3BitvecTestNotNull(p, pgno));
}
/*
@@ -63296,13 +66107,13 @@ static void btreeReleaseAllCursorPages(BtCursor *pCur){
** The cursor passed as the only argument must point to a valid entry
** when this function is called (i.e. have eState==CURSOR_VALID). This
** function saves the current cursor key in variables pCur->nKey and
-** pCur->pKey. SQLITE_OK is returned if successful or an SQLite error
+** pCur->pKey. SQLITE_OK is returned if successful or an SQLite error
** code otherwise.
**
** If the cursor is open on an intkey table, then the integer key
** (the rowid) is stored in pCur->nKey and pCur->pKey is left set to
-** NULL. If the cursor is open on a non-intkey table, then pCur->pKey is
-** set to point to a malloced buffer pCur->nKey bytes in size containing
+** NULL. If the cursor is open on a non-intkey table, then pCur->pKey is
+** set to point to a malloced buffer pCur->nKey bytes in size containing
** the key.
*/
static int saveCursorKey(BtCursor *pCur){
@@ -63315,13 +66126,19 @@ static int saveCursorKey(BtCursor *pCur){
/* Only the rowid is required for a table btree */
pCur->nKey = sqlite3BtreeIntegerKey(pCur);
}else{
- /* For an index btree, save the complete key content */
+ /* For an index btree, save the complete key content. It is possible
+ ** that the current key is corrupt. In that case, it is possible that
+ ** the sqlite3VdbeRecordUnpack() function may overread the buffer by
+ ** up to the size of 1 varint plus 1 8-byte value when the cursor
+ ** position is restored. Hence the 17 bytes of padding allocated
+ ** below. */
void *pKey;
pCur->nKey = sqlite3BtreePayloadSize(pCur);
- pKey = sqlite3Malloc( pCur->nKey );
+ pKey = sqlite3Malloc( pCur->nKey + 9 + 8 );
if( pKey ){
rc = sqlite3BtreePayload(pCur, 0, (int)pCur->nKey, pKey);
if( rc==SQLITE_OK ){
+ memset(((u8*)pKey)+pCur->nKey, 0, 9+8);
pCur->pKey = pKey;
}else{
sqlite3_free(pKey);
@@ -63335,11 +66152,11 @@ static int saveCursorKey(BtCursor *pCur){
}
/*
-** 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;
@@ -63348,6 +66165,9 @@ static int saveCursorPosition(BtCursor *pCur){
assert( 0==pCur->pKey );
assert( cursorHoldsMutex(pCur) );
+ if( pCur->curFlags & BTCF_Pinned ){
+ return SQLITE_CONSTRAINT_PINNED;
+ }
if( pCur->eState==CURSOR_SKIPNEXT ){
pCur->eState = CURSOR_VALID;
}else{
@@ -63375,7 +66195,7 @@ static int SQLITE_NOINLINE saveCursorsOnList(BtCursor*,Pgno,BtCursor*);
** routine is called just before cursor pExcept is used to modify the
** table, for example in BtreeDelete() or BtreeInsert().
**
-** If there are two or more cursors on the same btree, then all such
+** If there are two or more cursors on the same btree, then all such
** cursors should have their BTCF_Multiple flag set. The btreeCursor()
** routine enforces that rule. This routine only needs to be called in
** the uncommon case when pExpect has the BTCF_Multiple flag set.
@@ -63453,11 +66273,12 @@ static int btreeMoveto(
UnpackedRecord *pIdxKey; /* Unpacked index key */
if( pKey ){
+ KeyInfo *pKeyInfo = pCur->pKeyInfo;
assert( nKey==(i64)(int)nKey );
- pIdxKey = sqlite3VdbeAllocUnpackedRecord(pCur->pKeyInfo);
+ pIdxKey = sqlite3VdbeAllocUnpackedRecord(pKeyInfo);
if( pIdxKey==0 ) return SQLITE_NOMEM_BKPT;
- sqlite3VdbeRecordUnpack(pCur->pKeyInfo, (int)nKey, pKey, pIdxKey);
- if( pIdxKey->nField==0 ){
+ sqlite3VdbeRecordUnpack(pKeyInfo, (int)nKey, pKey, pIdxKey);
+ if( pIdxKey->nField==0 || pIdxKey->nField>pKeyInfo->nAllField ){
rc = SQLITE_CORRUPT_BKPT;
goto moveto_done;
}
@@ -63474,26 +66295,30 @@ moveto_done:
/*
** 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){
int rc;
- int skipNext;
+ int skipNext = 0;
assert( cursorOwnsBtShared(pCur) );
assert( pCur->eState>=CURSOR_REQUIRESEEK );
if( pCur->eState==CURSOR_FAULT ){
return pCur->skipNext;
}
pCur->eState = CURSOR_INVALID;
- rc = btreeMoveto(pCur, pCur->pKey, pCur->nKey, 0, &skipNext);
+ if( sqlite3FaultSim(410) ){
+ rc = SQLITE_IOERR;
+ }else{
+ rc = btreeMoveto(pCur, pCur->pKey, pCur->nKey, 0, &skipNext);
+ }
if( rc==SQLITE_OK ){
sqlite3_free(pCur->pKey);
pCur->pKey = 0;
assert( pCur->eState==CURSOR_VALID || pCur->eState==CURSOR_INVALID );
- pCur->skipNext |= skipNext;
+ if( skipNext ) pCur->skipNext = skipNext;
if( pCur->skipNext && pCur->eState==CURSOR_VALID ){
pCur->eState = CURSOR_SKIPNEXT;
}
@@ -63540,7 +66365,7 @@ SQLITE_PRIVATE BtCursor *sqlite3BtreeFakeValidCursor(void){
/*
** This routine restores a cursor back to its original position after it
** has been moved by some outside activity (such as a btree rebalance or
-** a row having been deleted out from under the cursor).
+** a row having been deleted out from under the cursor).
**
** On success, the *pDifferentRow parameter is false if the cursor is left
** pointing at exactly the same row. *pDifferntRow is the row the cursor
@@ -63563,7 +66388,6 @@ SQLITE_PRIVATE int sqlite3BtreeCursorRestore(BtCursor *pCur, int *pDifferentRow)
if( pCur->eState!=CURSOR_VALID ){
*pDifferentRow = 1;
}else{
- assert( pCur->skipNext==0 );
*pDifferentRow = 0;
}
return SQLITE_OK;
@@ -63606,7 +66430,7 @@ static Pgno ptrmapPageno(BtShared *pBt, Pgno pgno){
if( pgno<2 ) return 0;
nPagesPerMapPage = (pBt->usableSize/5)+1;
iPtrMap = (pgno-2)/nPagesPerMapPage;
- ret = (iPtrMap*nPagesPerMapPage) + 2;
+ ret = (iPtrMap*nPagesPerMapPage) + 2;
if( ret==PENDING_BYTE_PAGE(pBt) ){
ret++;
}
@@ -63633,7 +66457,7 @@ static void ptrmapPut(BtShared *pBt, Pgno key, u8 eType, Pgno parent, int *pRC){
if( *pRC ) return;
assert( sqlite3_mutex_held(pBt->mutex) );
- /* The master-journal page number must never be used as a pointer map page */
+ /* The super-journal page number must never be used as a pointer map page */
assert( 0==PTRMAP_ISPAGE(pBt, PENDING_BYTE_PAGE(pBt)) );
assert( pBt->autoVacuum );
@@ -63647,6 +66471,13 @@ static void ptrmapPut(BtShared *pBt, Pgno key, u8 eType, Pgno parent, int *pRC){
*pRC = rc;
return;
}
+ if( ((char*)sqlite3PagerGetExtra(pDbPage))[0]!=0 ){
+ /* The first byte of the extra data is the MemPage.isInit byte.
+ ** If that byte is set, it means this page is also being used
+ ** as a btree page. */
+ *pRC = SQLITE_CORRUPT_BKPT;
+ goto ptrmap_exit;
+ }
offset = PTRMAP_PTROFFSET(iPtrmap, key);
if( offset<0 ){
*pRC = SQLITE_CORRUPT_BKPT;
@@ -63709,7 +66540,7 @@ static int ptrmapGet(BtShared *pBt, Pgno key, u8 *pEType, Pgno *pPgno){
#else /* if defined SQLITE_OMIT_AUTOVACUUM */
#define ptrmapPut(w,x,y,z,rc)
#define ptrmapGet(w,x,y,z) SQLITE_OK
- #define ptrmapPutOvflPtr(x, y, rc)
+ #define ptrmapPutOvflPtr(x, y, z, rc)
#endif
/*
@@ -63765,6 +66596,24 @@ static SQLITE_NOINLINE void btreeParseCellAdjustSizeForOverflow(
pInfo->nSize = (u16)(&pInfo->pPayload[pInfo->nLocal] - pCell) + 4;
}
+/*
+** Given a record with nPayload bytes of payload stored within btree
+** page pPage, return the number of bytes of payload stored locally.
+*/
+static int btreePayloadToLocal(MemPage *pPage, i64 nPayload){
+ int maxLocal; /* Maximum amount of payload held locally */
+ maxLocal = pPage->maxLocal;
+ if( nPayload<=maxLocal ){
+ return nPayload;
+ }else{
+ int minLocal; /* Minimum amount of payload held locally */
+ int surplus; /* Overflow payload available for local storage */
+ minLocal = pPage->minLocal;
+ surplus = minLocal + (nPayload - minLocal)%(pPage->pBt->usableSize-4);
+ return ( surplus <= maxLocal ) ? surplus : minLocal;
+ }
+}
+
/*
** The following routines are implementations of the MemPage.xParseCell()
** method.
@@ -63945,7 +66794,7 @@ static u16 cellSizePtr(MemPage *pPage, u8 *pCell){
}
pIter++;
if( pPage->intKey ){
- /* 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];
@@ -64002,17 +66851,24 @@ static u16 cellSize(MemPage *pPage, int iCell){
#ifndef SQLITE_OMIT_AUTOVACUUM
/*
-** If the cell pCell, part of page pPage contains a pointer
-** to an overflow page, insert an entry into the pointer-map
-** for the overflow page.
+** The cell pCell is currently part of page pSrc but will ultimately be part
+** of pPage. (pSrc and pPager are often the same.) If pCell contains a
+** pointer to an overflow page, insert an entry into the pointer-map for
+** the overflow page that will be valid after pCell has been moved to pPage.
*/
-static void ptrmapPutOvflPtr(MemPage *pPage, u8 *pCell, int *pRC){
+static void ptrmapPutOvflPtr(MemPage *pPage, MemPage *pSrc, u8 *pCell,int *pRC){
CellInfo info;
if( *pRC ) return;
assert( pCell!=0 );
pPage->xParseCell(pPage, pCell, &info);
if( info.nLocalaDataEnd, pCell, pCell+info.nLocal) ){
+ testcase( pSrc!=pPage );
+ *pRC = SQLITE_CORRUPT_BKPT;
+ return;
+ }
+ ovfl = get4byte(&pCell[info.nSize-4]);
ptrmapPut(pPage->pBt, ovfl, PTRMAP_OVERFLOW1, pPage->pgno, pRC);
}
}
@@ -64045,6 +66901,7 @@ static int defragmentPage(MemPage *pPage, int nMaxFrag){
unsigned char *src; /* Source of content */
int iCellFirst; /* First allowable cell index */
int iCellLast; /* Last possible cell index */
+ int iCellStart; /* First cell offset in input */
assert( sqlite3PagerIswriteable(pPage->pDbPage) );
assert( pPage->pBt!=0 );
@@ -64056,30 +66913,21 @@ static int defragmentPage(MemPage *pPage, int nMaxFrag){
hdr = pPage->hdrOffset;
cellOffset = pPage->cellOffset;
nCell = pPage->nCell;
- assert( nCell==get2byte(&data[hdr+3]) );
+ assert( nCell==get2byte(&data[hdr+3]) || CORRUPT_DB );
iCellFirst = cellOffset + 2*nCell;
usableSize = pPage->pBt->usableSize;
/* This block handles pages with two or fewer free blocks and nMaxFrag
** or fewer fragmented bytes. In this case it is faster to move the
** two (or one) blocks of cells using memmove() and add the required
- ** offsets to each pointer in the cell-pointer array than it is to
+ ** offsets to each pointer in the cell-pointer array than it is to
** reconstruct the entire page. */
if( (int)data[hdr+7]<=nMaxFrag ){
int iFree = get2byte(&data[hdr+1]);
+ if( iFree>usableSize-4 ) return SQLITE_CORRUPT_PAGE(pPage);
if( iFree ){
int iFree2 = get2byte(&data[iFree]);
-
- /* pageFindSlot() has already verified that free blocks are sorted
- ** in order of offset within the page, and that no block extends
- ** past the end of the page. Provided the two free slots do not
- ** overlap, this guarantees that the memmove() calls below will not
- ** overwrite the usableSize byte buffer, even if the database page
- ** is corrupt. */
- assert( iFree2==0 || iFree2>iFree );
- assert( iFree+get2byte(&data[iFree+2]) <= usableSize );
- assert( iFree2==0 || iFree2+get2byte(&data[iFree2+2]) <= usableSize );
-
+ if( iFree2>usableSize-4 ) return SQLITE_CORRUPT_PAGE(pPage);
if( 0==iFree2 || (data[iFree2]==0 && data[iFree2+1]==0) ){
u8 *pEnd = &data[cellOffset + nCell*2];
u8 *pAddr;
@@ -64090,12 +66938,15 @@ static int defragmentPage(MemPage *pPage, int nMaxFrag){
return SQLITE_CORRUPT_PAGE(pPage);
}
if( iFree2 ){
- assert( iFree+sz<=iFree2 ); /* Verified by pageFindSlot() */
+ if( iFree+sz>iFree2 ) return SQLITE_CORRUPT_PAGE(pPage);
sz2 = get2byte(&data[iFree2+2]);
- assert( iFree+sz+sz2+iFree2-(iFree+sz) <= usableSize );
+ if( iFree2+sz2 > usableSize ) return SQLITE_CORRUPT_PAGE(pPage);
memmove(&data[iFree+sz+sz2], &data[iFree+sz], iFree2-(iFree+sz));
sz += sz2;
+ }else if( iFree+sz>usableSize ){
+ return SQLITE_CORRUPT_PAGE(pPage);
}
+
cbrk = top+sz;
assert( cbrk+(iFree-top) <= usableSize );
memmove(&data[cbrk], &data[top], iFree-top);
@@ -64111,6 +66962,7 @@ static int defragmentPage(MemPage *pPage, int nMaxFrag){
cbrk = usableSize;
iCellLast = usableSize - 4;
+ iCellStart = get2byte(&data[hdr+5]);
for(i=0; iiCellLast ){
+ if( pciCellLast ){
return SQLITE_CORRUPT_PAGE(pPage);
}
- assert( pc>=iCellFirst && pc<=iCellLast );
+ assert( pc>=iCellStart && pc<=iCellLast );
size = pPage->xCellSize(pPage, &src[pc]);
cbrk -= size;
- if( cbrkusableSize ){
+ if( cbrkusableSize ){
return SQLITE_CORRUPT_PAGE(pPage);
}
- assert( cbrk+size<=usableSize && cbrk>=iCellFirst );
+ assert( cbrk+size<=usableSize && cbrk>=iCellStart );
testcase( cbrk+size==usableSize );
testcase( pc+size==usableSize );
put2byte(pAddr, cbrk);
if( temp==0 ){
- int x;
if( cbrk==pc ) continue;
temp = sqlite3PagerTempSpace(pPage->pBt->pPager);
- x = get2byte(&data[hdr+5]);
- memcpy(&temp[x], &data[x], (cbrk+size) - x);
+ memcpy(&temp[iCellStart], &data[iCellStart], usableSize - iCellStart);
src = temp;
}
memcpy(&data[cbrk], &src[pc], size);
@@ -64146,6 +66996,7 @@ static int defragmentPage(MemPage *pPage, int nMaxFrag){
data[hdr+7] = 0;
defragment_out:
+ assert( pPage->nFree>=0 );
if( data[hdr+7]+cbrk-iCellFirst!=pPage->nFree ){
return SQLITE_CORRUPT_PAGE(pPage);
}
@@ -64173,16 +67024,16 @@ static int defragmentPage(MemPage *pPage, int nMaxFrag){
** causes the fragmentation count to exceed 60.
*/
static u8 *pageFindSlot(MemPage *pPg, int nByte, int *pRc){
- const int hdr = pPg->hdrOffset;
- u8 * const aData = pPg->aData;
- int iAddr = hdr + 1;
- int pc = get2byte(&aData[iAddr]);
- int x;
- int usableSize = pPg->pBt->usableSize;
- int size; /* Size of the free slot */
+ const int hdr = pPg->hdrOffset; /* Offset to page header */
+ u8 * const aData = pPg->aData; /* Page data */
+ int iAddr = hdr + 1; /* Address of ptr to pc */
+ int pc = get2byte(&aData[iAddr]); /* Address of a free slot */
+ int x; /* Excess size of the slot */
+ int maxPC = pPg->pBt->usableSize - nByte; /* Max address for a usable slot */
+ int size; /* Size of the free slot */
assert( pc>0 );
- while( pc<=usableSize-4 ){
+ while( pc<=maxPC ){
/* EVIDENCE-OF: R-22710-53328 The third and fourth bytes of each
** freeblock form a big-endian integer which is the size of the freeblock
** in bytes, including the 4-byte header. */
@@ -64190,10 +67041,7 @@ static u8 *pageFindSlot(MemPage *pPg, int nByte, int *pRc){
if( (x = size - nByte)>=0 ){
testcase( x==4 );
testcase( x==3 );
- if( size+pc > usableSize ){
- *pRc = SQLITE_CORRUPT_PAGE(pPg);
- return 0;
- }else if( x<4 ){
+ if( x<4 ){
/* EVIDENCE-OF: R-11498-58022 In a well-formed b-tree page, the total
** number of bytes in fragments may not exceed 60. */
if( aData[hdr+7]>57 ) return 0;
@@ -64202,21 +67050,31 @@ static u8 *pageFindSlot(MemPage *pPg, int nByte, int *pRc){
** fragmented bytes within the page. */
memcpy(&aData[iAddr], &aData[pc], 2);
aData[hdr+7] += (u8)x;
+ }else if( x+pc > maxPC ){
+ /* This slot extends off the end of the usable part of the page */
+ *pRc = SQLITE_CORRUPT_PAGE(pPg);
+ return 0;
}else{
/* The slot remains on the free-list. Reduce its size to account
- ** for the portion used by the new allocation. */
+ ** for the portion used by the new allocation. */
put2byte(&aData[pc+2], x);
}
return &aData[pc + x];
}
iAddr = pc;
pc = get2byte(&aData[pc]);
- if( pcmaxPC+nByte-4 ){
+ /* The free slot chain extends off the end of the page */
*pRc = SQLITE_CORRUPT_PAGE(pPg);
}
-
return 0;
}
@@ -64239,7 +67097,7 @@ static int allocateSpace(MemPage *pPage, int nByte, int *pIdx){
int top; /* First byte of cell content area */
int rc = SQLITE_OK; /* Integer return code */
int gap; /* First byte of gap between cell pointers and cell content */
-
+
assert( sqlite3PagerIswriteable(pPage->pDbPage) );
assert( pPage->pBt );
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
@@ -64257,7 +67115,7 @@ static int allocateSpace(MemPage *pPage, int nByte, int *pIdx){
** However, that integer is too large to be stored in a 2-byte unsigned
** integer, so a value of 0 is used in its place. */
top = get2byte(&data[hdr+5]);
- assert( top<=(int)pPage->pBt->usableSize ); /* Prevent by getAndInitPage() */
+ assert( top<=(int)pPage->pBt->usableSize ); /* by btreeComputeFreeSpace() */
if( gap>top ){
if( top==0 && pPage->pBt->usableSize==65536 ){
top = 65536;
@@ -64266,9 +67124,9 @@ static int allocateSpace(MemPage *pPage, int nByte, int *pIdx){
}
}
- /* If there is enough space between gap and top for one more cell pointer
- ** array entry offset, and if the freelist is not empty, then search the
- ** freelist looking for a free slot big enough to satisfy the request.
+ /* If there is enough space between gap and top for one more cell pointer,
+ ** and if the freelist is not empty, then search the
+ ** freelist looking for a slot big enough to satisfy the request.
*/
testcase( gap+2==top );
testcase( gap+1==top );
@@ -64276,9 +67134,14 @@ static int allocateSpace(MemPage *pPage, int nByte, int *pIdx){
if( (data[hdr+2] || data[hdr+1]) && gap+2<=top ){
u8 *pSpace = pageFindSlot(pPage, nByte, &rc);
if( pSpace ){
- assert( pSpace>=data && (pSpace - data)<65536 );
- *pIdx = (int)(pSpace - data);
- return SQLITE_OK;
+ int g2;
+ assert( pSpace+nByte<=data+pPage->pBt->usableSize );
+ *pIdx = g2 = (int)(pSpace-data);
+ if( NEVER(g2<=gap) ){
+ return SQLITE_CORRUPT_PAGE(pPage);
+ }else{
+ return SQLITE_OK;
+ }
}else if( rc ){
return rc;
}
@@ -64290,6 +67153,7 @@ static int allocateSpace(MemPage *pPage, int nByte, int *pIdx){
testcase( gap+2+nByte==top );
if( gap+2+nByte>top ){
assert( pPage->nCell>0 || CORRUPT_DB );
+ assert( pPage->nFree>=0 );
rc = defragmentPage(pPage, MIN(4, pPage->nFree - (2+nByte)));
if( rc ) return rc;
top = get2byteNotZero(&data[hdr+5]);
@@ -64298,7 +67162,7 @@ static int allocateSpace(MemPage *pPage, int nByte, int *pIdx){
/* Allocate memory from the gap in between the cell pointer array
- ** and the cell content area. The btreeInitPage() call has already
+ ** and the cell content area. The btreeComputeFreeSpace() call has already
** validated the freelist. Given that the freelist is valid, there
** is no way that the allocation can extend off the end of the page.
** The assert() below verifies the previous sentence.
@@ -64317,7 +67181,7 @@ static int allocateSpace(MemPage *pPage, int nByte, int *pIdx){
**
** Adjacent freeblocks are coalesced.
**
-** Note that even though the freeblock list was checked by btreeInitPage(),
+** Even though the freeblock list was checked by btreeComputeFreeSpace(),
** that routine will not detect overlap between cells or freeblocks. Nor
** does it detect cells or freeblocks that encrouch into the reserved bytes
** at the end of the page. So do additional corruption checks inside this
@@ -64341,7 +67205,7 @@ static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){
assert( iSize>=4 ); /* Minimum cell size is 4 */
assert( iStart<=pPage->pBt->usableSize-4 );
- /* The list of freeblocks must be in ascending order. Find the
+ /* The list of freeblocks must be in ascending order. Find the
** spot on the list where iStart should be inserted.
*/
hdr = pPage->hdrOffset;
@@ -64351,16 +67215,16 @@ static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){
}else{
while( (iFreeBlk = get2byte(&data[iPtr]))pPage->pBt->usableSize-4 ){
+ if( iFreeBlk>pPage->pBt->usableSize-4 ){ /* TH3: corrupt081.100 */
return SQLITE_CORRUPT_PAGE(pPage);
}
assert( iFreeBlk>iPtr || iFreeBlk==0 );
-
+
/* At this point:
** iFreeBlk: First freeblock after iStart, or zero if none
** iPtr: The address of a pointer to iFreeBlk
@@ -64377,7 +67241,7 @@ static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){
iSize = iEnd - iStart;
iFreeBlk = get2byte(&data[iFreeBlk]);
}
-
+
/* If iPtr is another freeblock (that is, if iPtr is not the freelist
** pointer in the page header) then check to see if iStart should be
** coalesced onto the end of iPtr.
@@ -64399,7 +67263,8 @@ static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){
/* The new freeblock is at the beginning of the cell content area,
** so just extend the cell content area rather than create another
** freelist entry */
- if( iStartnFree field.
*/
-static int btreeInitPage(MemPage *pPage){
+static int btreeComputeFreeSpace(MemPage *pPage){
int pc; /* Address of a freeblock within pPage->aData[] */
u8 hdr; /* Offset to beginning of page header */
u8 *data; /* Equal to pPage->aData */
- BtShared *pBt; /* The main btree structure */
int usableSize; /* Amount of usable space on each page */
- u16 cellOffset; /* Offset from start of page to first cell pointer */
int nFree; /* Number of unused bytes on the page */
int top; /* First byte of the cell content area */
int iCellFirst; /* First allowable cell or freeblock offset */
@@ -64505,71 +67363,18 @@ static int btreeInitPage(MemPage *pPage){
assert( pPage->pgno==sqlite3PagerPagenumber(pPage->pDbPage) );
assert( pPage == sqlite3PagerGetExtra(pPage->pDbPage) );
assert( pPage->aData == sqlite3PagerGetData(pPage->pDbPage) );
- assert( pPage->isInit==0 );
+ assert( pPage->isInit==1 );
+ assert( pPage->nFree<0 );
- pBt = pPage->pBt;
+ usableSize = pPage->pBt->usableSize;
hdr = pPage->hdrOffset;
data = pPage->aData;
- /* EVIDENCE-OF: R-28594-02890 The one-byte flag at offset 0 indicating
- ** the b-tree page type. */
- if( decodeFlags(pPage, data[hdr]) ){
- return SQLITE_CORRUPT_PAGE(pPage);
- }
- assert( pBt->pageSize>=512 && pBt->pageSize<=65536 );
- pPage->maskPage = (u16)(pBt->pageSize - 1);
- pPage->nOverflow = 0;
- usableSize = pBt->usableSize;
- pPage->cellOffset = cellOffset = hdr + 8 + pPage->childPtrSize;
- pPage->aDataEnd = &data[usableSize];
- pPage->aCellIdx = &data[cellOffset];
- pPage->aDataOfst = &data[pPage->childPtrSize];
/* EVIDENCE-OF: R-58015-48175 The two-byte integer at offset 5 designates
** the start of the cell content area. A zero value for this integer is
** interpreted as 65536. */
top = get2byteNotZero(&data[hdr+5]);
- /* EVIDENCE-OF: R-37002-32774 The two-byte integer at offset 3 gives the
- ** number of cells on the page. */
- pPage->nCell = get2byte(&data[hdr+3]);
- if( pPage->nCell>MX_CELL(pBt) ){
- /* To many cells for a single page. The page must be corrupt */
- return SQLITE_CORRUPT_PAGE(pPage);
- }
- testcase( pPage->nCell==MX_CELL(pBt) );
- /* EVIDENCE-OF: R-24089-57979 If a page contains no cells (which is only
- ** possible for a root page of a table that contains no rows) then the
- ** offset to the cell content area will equal the page size minus the
- ** bytes of reserved space. */
- assert( pPage->nCell>0 || top==usableSize || CORRUPT_DB );
-
- /* A malformed database page might cause us to read past the end
- ** 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
- ** returned if it does.
- */
- iCellFirst = cellOffset + 2*pPage->nCell;
+ iCellFirst = hdr + 8 + pPage->childPtrSize + 2*pPage->nCell;
iCellLast = usableSize - 4;
- if( pBt->db->flags & SQLITE_CellSizeCk ){
- int i; /* Index into the cell pointer array */
- int sz; /* Size of a cell */
-
- if( !pPage->leaf ) iCellLast--;
- for(i=0; inCell; i++){
- pc = get2byteAligned(&data[cellOffset+i*2]);
- testcase( pc==iCellFirst );
- testcase( pc==iCellLast );
- if( pciCellLast ){
- return SQLITE_CORRUPT_PAGE(pPage);
- }
- sz = pPage->xCellSize(pPage, &data[pc]);
- testcase( pc+sz==usableSize );
- if( pc+sz>usableSize ){
- return SQLITE_CORRUPT_PAGE(pPage);
- }
- }
- if( !pPage->leaf ) iCellLast++;
- }
/* Compute the total free space on the page
** EVIDENCE-OF: R-23588-34450 The two-byte integer at offset 1 gives the
@@ -64579,11 +67384,11 @@ static int btreeInitPage(MemPage *pPage){
nFree = data[hdr+7] + top; /* Init nFree to non-freeblock free space */
if( pc>0 ){
u32 next, size;
- if( pciCellLast ){
@@ -64613,11 +67418,104 @@ static int btreeInitPage(MemPage *pPage){
** serves to verify that the offset to the start of the cell-content
** area, according to the page header, lies within the page.
*/
- if( nFree>usableSize ){
+ if( nFree>usableSize || nFreenFree = (u16)(nFree - iCellFirst);
+ return SQLITE_OK;
+}
+
+/*
+** Do additional sanity check after btreeInitPage() if
+** PRAGMA cell_size_check=ON
+*/
+static SQLITE_NOINLINE int btreeCellSizeCheck(MemPage *pPage){
+ int iCellFirst; /* First allowable cell or freeblock offset */
+ int iCellLast; /* Last possible cell or freeblock offset */
+ int i; /* Index into the cell pointer array */
+ int sz; /* Size of a cell */
+ int pc; /* Address of a freeblock within pPage->aData[] */
+ u8 *data; /* Equal to pPage->aData */
+ int usableSize; /* Maximum usable space on the page */
+ int cellOffset; /* Start of cell content area */
+
+ iCellFirst = pPage->cellOffset + 2*pPage->nCell;
+ usableSize = pPage->pBt->usableSize;
+ iCellLast = usableSize - 4;
+ data = pPage->aData;
+ cellOffset = pPage->cellOffset;
+ if( !pPage->leaf ) iCellLast--;
+ for(i=0; inCell; i++){
+ pc = get2byteAligned(&data[cellOffset+i*2]);
+ testcase( pc==iCellFirst );
+ testcase( pc==iCellLast );
+ if( pciCellLast ){
+ return SQLITE_CORRUPT_PAGE(pPage);
+ }
+ sz = pPage->xCellSize(pPage, &data[pc]);
+ testcase( pc+sz==usableSize );
+ if( pc+sz>usableSize ){
+ return SQLITE_CORRUPT_PAGE(pPage);
+ }
+ }
+ return SQLITE_OK;
+}
+
+/*
+** 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
+** 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.
+*/
+static int btreeInitPage(MemPage *pPage){
+ u8 *data; /* Equal to pPage->aData */
+ BtShared *pBt; /* The main btree structure */
+
+ assert( pPage->pBt!=0 );
+ assert( pPage->pBt->db!=0 );
+ assert( sqlite3_mutex_held(pPage->pBt->mutex) );
+ assert( pPage->pgno==sqlite3PagerPagenumber(pPage->pDbPage) );
+ assert( pPage == sqlite3PagerGetExtra(pPage->pDbPage) );
+ assert( pPage->aData == sqlite3PagerGetData(pPage->pDbPage) );
+ assert( pPage->isInit==0 );
+
+ pBt = pPage->pBt;
+ data = pPage->aData + pPage->hdrOffset;
+ /* EVIDENCE-OF: R-28594-02890 The one-byte flag at offset 0 indicating
+ ** the b-tree page type. */
+ if( decodeFlags(pPage, data[0]) ){
+ return SQLITE_CORRUPT_PAGE(pPage);
+ }
+ assert( pBt->pageSize>=512 && pBt->pageSize<=65536 );
+ pPage->maskPage = (u16)(pBt->pageSize - 1);
+ pPage->nOverflow = 0;
+ pPage->cellOffset = pPage->hdrOffset + 8 + pPage->childPtrSize;
+ pPage->aCellIdx = data + pPage->childPtrSize + 8;
+ pPage->aDataEnd = pPage->aData + pBt->usableSize;
+ pPage->aDataOfst = pPage->aData + pPage->childPtrSize;
+ /* EVIDENCE-OF: R-37002-32774 The two-byte integer at offset 3 gives the
+ ** number of cells on the page. */
+ pPage->nCell = get2byte(&data[3]);
+ if( pPage->nCell>MX_CELL(pBt) ){
+ /* To many cells for a single page. The page must be corrupt */
+ return SQLITE_CORRUPT_PAGE(pPage);
+ }
+ testcase( pPage->nCell==MX_CELL(pBt) );
+ /* EVIDENCE-OF: R-24089-57979 If a page contains no cells (which is only
+ ** possible for a root page of a table that contains no rows) then the
+ ** offset to the cell content area will equal the page size minus the
+ ** bytes of reserved space. */
+ assert( pPage->nCell>0
+ || get2byteNotZero(&data[5])==(int)pBt->usableSize
+ || CORRUPT_DB );
+ pPage->nFree = -1; /* Indicate that this value is yet uncomputed */
pPage->isInit = 1;
+ if( pBt->db->flags & SQLITE_CellSizeCk ){
+ return btreeCellSizeCheck(pPage);
+ }
return SQLITE_OK;
}
@@ -64672,7 +67570,7 @@ static MemPage *btreePageFromDbPage(DbPage *pDbPage, Pgno pgno, BtShared *pBt){
pPage->hdrOffset = pgno==1 ? 100 : 0;
}
assert( pPage->aData==sqlite3PagerGetData(pDbPage) );
- return pPage;
+ return pPage;
}
/*
@@ -64725,9 +67623,8 @@ static MemPage *btreePageLookup(BtShared *pBt, Pgno pgno){
static Pgno btreePagecount(BtShared *pBt){
return pBt->nPage;
}
-SQLITE_PRIVATE u32 sqlite3BtreeLastPage(Btree *p){
+SQLITE_PRIVATE Pgno sqlite3BtreeLastPage(Btree *p){
assert( sqlite3BtreeHoldsMutex(p) );
- assert( ((p->pBt->nPage)&0x80000000)==0 );
return btreePagecount(p->pBt);
}
@@ -64760,19 +67657,18 @@ static int getAndInitPage(
if( pgno>btreePagecount(pBt) ){
rc = SQLITE_CORRUPT_BKPT;
- goto getAndInitPage_error;
+ goto getAndInitPage_error1;
}
rc = sqlite3PagerGet(pBt->pPager, pgno, (DbPage**)&pDbPage, bReadOnly);
if( rc ){
- goto getAndInitPage_error;
+ goto getAndInitPage_error1;
}
*ppPage = (MemPage*)sqlite3PagerGetExtra(pDbPage);
if( (*ppPage)->isInit==0 ){
btreePageFromDbPage(pDbPage, pgno, pBt);
rc = btreeInitPage(*ppPage);
if( rc!=SQLITE_OK ){
- releasePage(*ppPage);
- goto getAndInitPage_error;
+ goto getAndInitPage_error2;
}
}
assert( (*ppPage)->pgno==pgno );
@@ -64782,12 +67678,13 @@ static int getAndInitPage(
** compatible with the root page. */
if( pCur && ((*ppPage)->nCell<1 || (*ppPage)->intKey!=pCur->curIntKey) ){
rc = SQLITE_CORRUPT_PGNO(pgno);
- releasePage(*ppPage);
- goto getAndInitPage_error;
+ goto getAndInitPage_error2;
}
return SQLITE_OK;
-getAndInitPage_error:
+getAndInitPage_error2:
+ releasePage(*ppPage);
+getAndInitPage_error1:
if( pCur ){
pCur->iPage--;
pCur->pPage = pCur->apPage[pCur->iPage];
@@ -64890,17 +67787,16 @@ static int btreeInvokeBusyHandler(void *pArg){
BtShared *pBt = (BtShared*)pArg;
assert( pBt->db );
assert( sqlite3_mutex_held(pBt->db->mutex) );
- return sqlite3InvokeBusyHandler(&pBt->db->busyHandler,
- sqlite3PagerFile(pBt->pPager));
+ return sqlite3InvokeBusyHandler(&pBt->db->busyHandler);
}
/*
** Open a database file.
-**
+**
** zFilename is the name of the database file. If zFilename is NULL
** then an ephemeral database is created. The ephemeral database might
** be exclusively in memory, or it might use a disk-based memory cache.
-** Either way, the ephemeral database will be automatically deleted
+** Either way, the ephemeral database will be automatically deleted
** when sqlite3BtreeClose() is called.
**
** If zFilename is ":memory:" then an in-memory database is created
@@ -64933,7 +67829,7 @@ SQLITE_PRIVATE int sqlite3BtreeOpen(
/* True if opening an ephemeral, temporary database */
const int isTempDb = zFilename==0 || zFilename[0]==0;
- /* 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.
*/
#ifdef SQLITE_OMIT_MEMORYDB
@@ -64995,15 +67891,19 @@ SQLITE_PRIVATE int sqlite3BtreeOpen(
rc = sqlite3OsFullPathname(pVfs, zFilename,
nFullPathname, zFullPathname);
if( rc ){
- sqlite3_free(zFullPathname);
- sqlite3_free(p);
- return rc;
+ if( rc==SQLITE_OK_SYMLINK ){
+ rc = SQLITE_OK;
+ }else{
+ sqlite3_free(zFullPathname);
+ sqlite3_free(p);
+ return rc;
+ }
}
}
#if SQLITE_THREADSAFE
mutexOpen = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_OPEN);
sqlite3_mutex_enter(mutexOpen);
- mutexShared = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
+ mutexShared = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN);
sqlite3_mutex_enter(mutexShared);
#endif
for(pBt=GLOBAL(BtShared*,sqlite3SharedCacheList); pBt; pBt=pBt->pNext){
@@ -65052,7 +67952,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_BKPT;
@@ -65071,7 +67971,7 @@ SQLITE_PRIVATE int sqlite3BtreeOpen(
pBt->db = db;
sqlite3PagerSetBusyHandler(pBt->pPager, btreeInvokeBusyHandler, pBt);
p->pBt = pBt;
-
+
pBt->pCursor = 0;
pBt->pPage1 = 0;
if( sqlite3PagerIsreadonly(pBt->pPager) ) pBt->btsFlags |= BTS_READ_ONLY;
@@ -65115,14 +68015,14 @@ 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.
*/
pBt->nRef = 1;
if( p->sharable ){
MUTEX_LOGIC( sqlite3_mutex *mutexShared; )
- MUTEX_LOGIC( mutexShared = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);)
+ MUTEX_LOGIC( mutexShared = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN);)
if( SQLITE_THREADSAFE && sqlite3GlobalConfig.bCoreMutex ){
pBt->mutex = sqlite3MutexAlloc(SQLITE_MUTEX_FAST);
if( pBt->mutex==0 ){
@@ -65187,7 +68087,7 @@ btree_open_out:
** do not change the pager-cache size.
*/
if( sqlite3BtreeSchema(p, 0, 0)==0 ){
- sqlite3PagerSetCachesize(p->pBt->pPager, SQLITE_DEFAULT_CACHE_SIZE);
+ sqlite3BtreeSetCacheSize(p, SQLITE_DEFAULT_CACHE_SIZE);
}
pFile = sqlite3PagerFile(pBt->pPager);
@@ -65211,13 +68111,13 @@ btree_open_out:
*/
static int removeFromSharingList(BtShared *pBt){
#ifndef SQLITE_OMIT_SHARED_CACHE
- MUTEX_LOGIC( sqlite3_mutex *pMaster; )
+ MUTEX_LOGIC( sqlite3_mutex *pMainMtx; )
BtShared *pList;
int removed = 0;
assert( sqlite3_mutex_notheld(pBt->mutex) );
- MUTEX_LOGIC( pMaster = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); )
- sqlite3_mutex_enter(pMaster);
+ MUTEX_LOGIC( pMainMtx = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN); )
+ sqlite3_mutex_enter(pMainMtx);
pBt->nRef--;
if( pBt->nRef<=0 ){
if( GLOBAL(BtShared*,sqlite3SharedCacheList)==pBt ){
@@ -65236,7 +68136,7 @@ static int removeFromSharingList(BtShared *pBt){
}
removed = 1;
}
- sqlite3_mutex_leave(pMaster);
+ sqlite3_mutex_leave(pMainMtx);
return removed;
#else
return 1;
@@ -65244,7 +68144,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 with a 4-byte prefix for a left-child
** pointer.
*/
@@ -65259,7 +68159,7 @@ static void allocateTempSpace(BtShared *pBt){
** can mean that fillInCell() only initializes the first 2 or 3
** bytes of pTmpSpace, but that the first 4 bytes are copied from
** it into a database page. This is not actually a problem, but it
- ** does cause a valgrind error when the 1 or 2 bytes of unitialized
+ ** does cause a valgrind error when the 1 or 2 bytes of unitialized
** data is passed to system call write(). So to avoid this error,
** zero the first 4 bytes of temp space here.
**
@@ -65290,19 +68190,23 @@ static void freeTempSpace(BtShared *pBt){
*/
SQLITE_PRIVATE int sqlite3BtreeClose(Btree *p){
BtShared *pBt = p->pBt;
- BtCursor *pCur;
/* Close all cursors opened via this handle. */
assert( sqlite3_mutex_held(p->db->mutex) );
sqlite3BtreeEnter(p);
- pCur = pBt->pCursor;
- while( pCur ){
- BtCursor *pTmp = pCur;
- pCur = pCur->pNext;
- if( pTmp->pBtree==p ){
- sqlite3BtreeCloseCursor(pTmp);
+
+ /* Verify that no other cursors have this Btree open */
+#ifdef SQLITE_DEBUG
+ {
+ BtCursor *pCur = pBt->pCursor;
+ while( pCur ){
+ BtCursor *pTmp = pCur;
+ pCur = pCur->pNext;
+ assert( pTmp->pBtree!=p );
+
}
}
+#endif
/* Rollback any active transaction and free the handle structure.
** The call to sqlite3BtreeRollback() drops any table-locks held by
@@ -65312,7 +68216,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 );
@@ -65418,7 +68322,7 @@ SQLITE_PRIVATE int sqlite3BtreeSetPagerFlags(
/*
** 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
@@ -65438,24 +68342,23 @@ SQLITE_PRIVATE int sqlite3BtreeSetPagerFlags(
*/
SQLITE_PRIVATE int sqlite3BtreeSetPageSize(Btree *p, int pageSize, int nReserve, int iFix){
int rc = SQLITE_OK;
+ int x;
BtShared *pBt = p->pBt;
- assert( nReserve>=-1 && nReserve<=255 );
+ assert( nReserve>=0 && nReserve<=255 );
sqlite3BtreeEnter(p);
-#if SQLITE_HAS_CODEC
- if( nReserve>pBt->optimalReserve ) pBt->optimalReserve = (u8)nReserve;
-#endif
+ pBt->nReserveWanted = nReserve;
+ x = pBt->pageSize - pBt->usableSize;
+ if( nReservebtsFlags & BTS_PAGESIZE_FIXED ){
sqlite3BtreeLeave(p);
return SQLITE_READONLY;
}
- if( nReserve<0 ){
- nReserve = pBt->pageSize - pBt->usableSize;
- }
assert( nReserve>=0 && nReserve<=255 );
if( pageSize>=512 && pageSize<=SQLITE_MAX_PAGE_SIZE &&
((pageSize-1)&pageSize)==0 ){
assert( (pageSize & 7)==0 );
assert( !pBt->pCursor );
+ if( nReserve>32 && pageSize==512 ) pageSize = 1024;
pBt->pageSize = (u32)pageSize;
freeTempSpace(pBt);
}
@@ -65479,7 +68382,7 @@ SQLITE_PRIVATE int sqlite3BtreeGetPageSize(Btree *p){
** held.
**
** This is useful in one special case in the backup API code where it is
-** known that the shared b-tree mutex is held, but the mutex on the
+** known that the shared b-tree mutex is held, but the mutex on the
** database handle that owns *p is not. In this case if sqlite3BtreeEnter()
** were to be called, it might collide with some other operation on the
** database handle that owns *p, causing undefined behavior.
@@ -65496,19 +68399,17 @@ SQLITE_PRIVATE int sqlite3BtreeGetReserveNoMutex(Btree *p){
** are intentually left unused. This is the "reserved" space that is
** sometimes used by extensions.
**
-** If SQLITE_HAS_MUTEX is defined then the number returned is the
-** greater of the current reserved space and the maximum requested
-** reserve space.
+** The value returned is the larger of the current reserve size and
+** the latest reserve size requested by SQLITE_FILECTRL_RESERVE_BYTES.
+** The amount of reserve can only grow - never shrink.
*/
-SQLITE_PRIVATE int sqlite3BtreeGetOptimalReserve(Btree *p){
- int n;
+SQLITE_PRIVATE int sqlite3BtreeGetRequestedReserve(Btree *p){
+ int n1, n2;
sqlite3BtreeEnter(p);
- n = sqlite3BtreeGetReserveNoMutex(p);
-#ifdef SQLITE_HAS_CODEC
- if( npBt->optimalReserve ) n = p->pBt->optimalReserve;
-#endif
+ n1 = (int)p->pBt->nReserveWanted;
+ n2 = sqlite3BtreeGetReserveNoMutex(p);
sqlite3BtreeLeave(p);
- return n;
+ return n1>n2 ? n1 : n2;
}
@@ -65517,8 +68418,8 @@ SQLITE_PRIVATE int sqlite3BtreeGetOptimalReserve(Btree *p){
** No changes are made if mxPage is 0 or negative.
** Regardless of the value of mxPage, return the maximum page count.
*/
-SQLITE_PRIVATE int sqlite3BtreeMaxPageCount(Btree *p, int mxPage){
- int n;
+SQLITE_PRIVATE Pgno sqlite3BtreeMaxPageCount(Btree *p, Pgno mxPage){
+ Pgno n;
sqlite3BtreeEnter(p);
n = sqlite3PagerMaxPageCount(p->pBt->pPager, mxPage);
sqlite3BtreeLeave(p);
@@ -65561,7 +68462,7 @@ SQLITE_PRIVATE int sqlite3BtreeSecureDelete(Btree *p, int newFlag){
/*
** 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){
@@ -65585,7 +68486,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){
@@ -65617,9 +68518,9 @@ static void setDefaultSyncFlag(BtShared *pBt, u8 safety_level){
Db *pDb;
if( (db=pBt->db)!=0 && (pDb=db->aDb)!=0 ){
while( pDb->pBt==0 || pDb->pBt->pBt!=pBt ){ pDb++; }
- if( pDb->bSyncSet==0
- && pDb->safety_level!=safety_level
- && pDb!=&db->aDb[1]
+ if( pDb->bSyncSet==0
+ && pDb->safety_level!=safety_level
+ && pDb!=&db->aDb[1]
){
pDb->safety_level = safety_level;
sqlite3PagerSetFlags(pBt->pPager,
@@ -65642,14 +68543,14 @@ static int newDatabase(BtShared*);
** 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 */
+ u32 nPage; /* Number of pages in the database */
+ u32 nPageFile = 0; /* Number of pages in the database file */
+ u32 nPageHeader; /* Number of pages in the database according to hdr */
assert( sqlite3_mutex_held(pBt->mutex) );
assert( pBt->pPage1==0 );
@@ -65659,10 +68560,10 @@ 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);
- sqlite3PagerPagecount(pBt->pPager, &nPageFile);
+ sqlite3PagerPagecount(pBt->pPager, (int*)&nPageFile);
if( nPage==0 || memcmp(24+(u8*)pPage1->aData, 92+(u8*)pPage1->aData,4)!=0 ){
nPage = nPageFile;
}
@@ -65697,7 +68598,7 @@ static int lockBtree(BtShared *pBt){
}
/* 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
+ ** 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
@@ -65738,15 +68639,16 @@ static int lockBtree(BtShared *pBt){
/* EVIDENCE-OF: R-25008-21688 The size of a page is a power of two
** between 512 and 65536 inclusive. */
if( ((pageSize-1)&pageSize)!=0
- || pageSize>SQLITE_MAX_PAGE_SIZE
- || pageSize<=256
+ || pageSize>SQLITE_MAX_PAGE_SIZE
+ || pageSize<=256
){
goto page1_init_failed;
}
+ pBt->btsFlags |= BTS_PAGESIZE_FIXED;
assert( (pageSize & 7)==0 );
/* EVIDENCE-OF: R-59310-51205 The "reserved space" size in the 1-byte
** integer at offset 20 is the number of bytes of space at the end of
- ** each page to reserve for extensions.
+ ** each page to reserve for extensions.
**
** EVIDENCE-OF: R-37497-42412 The size of the reserved region is
** determined by the one-byte unsigned integer found at an offset of 20
@@ -65767,7 +68669,7 @@ static int lockBtree(BtShared *pBt){
pageSize-usableSize);
return rc;
}
- if( (pBt->db->flags & SQLITE_WriteSchema)==0 && nPage>nPageFile ){
+ if( sqlite3WritableSchema(pBt->db)==0 && nPage>nPageFile ){
rc = SQLITE_CORRUPT_BKPT;
goto page1_init_failed;
}
@@ -65836,7 +68738,7 @@ static int countValidCursors(BtShared *pBt, int wrOnly){
int r = 0;
for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){
if( (wrOnly==0 || (pCur->curFlags & BTCF_WriteFlag)!=0)
- && pCur->eState!=CURSOR_FAULT ) r++;
+ && pCur->eState!=CURSOR_FAULT ) r++;
}
return r;
}
@@ -65845,7 +68747,7 @@ static int countValidCursors(BtShared *pBt, int wrOnly){
/*
** 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.
@@ -65929,8 +68831,8 @@ SQLITE_PRIVATE int sqlite3BtreeNewDb(Btree *p){
** 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()
@@ -65944,7 +68846,7 @@ SQLITE_PRIVATE int sqlite3BtreeNewDb(Btree *p){
** 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
@@ -65957,6 +68859,7 @@ SQLITE_PRIVATE int sqlite3BtreeNewDb(Btree *p){
*/
SQLITE_PRIVATE int sqlite3BtreeBeginTrans(Btree *p, int wrflag, int *pSchemaVersion){
BtShared *pBt = p->pBt;
+ Pager *pPager = pBt->pPager;
int rc = SQLITE_OK;
sqlite3BtreeEnter(p);
@@ -65971,8 +68874,8 @@ SQLITE_PRIVATE int sqlite3BtreeBeginTrans(Btree *p, int wrflag, int *pSchemaVers
}
assert( pBt->inTransaction==TRANS_WRITE || IfNotOmitAV(pBt->bDoTruncate)==0 );
- if( (p->db->flags & SQLITE_ResetDatabase)
- && sqlite3PagerIsreadonly(pBt->pPager)==0
+ if( (p->db->flags & SQLITE_ResetDatabase)
+ && sqlite3PagerIsreadonly(pPager)==0
){
pBt->btsFlags &= ~BTS_READ_ONLY;
}
@@ -65986,7 +68889,7 @@ SQLITE_PRIVATE int sqlite3BtreeBeginTrans(Btree *p, int wrflag, int *pSchemaVers
#ifndef SQLITE_OMIT_SHARED_CACHE
{
sqlite3 *pBlock = 0;
- /* 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.
*/
@@ -66011,19 +68914,31 @@ SQLITE_PRIVATE int sqlite3BtreeBeginTrans(Btree *p, int wrflag, int *pSchemaVers
}
#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);
+ rc = querySharedCacheTableLock(p, SCHEMA_ROOT, READ_LOCK);
if( SQLITE_OK!=rc ) goto trans_begun;
pBt->btsFlags &= ~BTS_INITIALLY_EMPTY;
if( pBt->nPage==0 ) pBt->btsFlags |= BTS_INITIALLY_EMPTY;
do {
+ sqlite3PagerWalDb(pPager, p->db);
+
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+ /* If transitioning from no transaction directly to a write transaction,
+ ** block for the WRITER lock first if possible. */
+ if( pBt->pPage1==0 && wrflag ){
+ assert( pBt->inTransaction==TRANS_NONE );
+ rc = sqlite3PagerWalWriteLock(pPager, 1);
+ if( rc!=SQLITE_BUSY && rc!=SQLITE_OK ) break;
+ }
+#endif
+
/* 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.
*/
@@ -66033,7 +68948,7 @@ SQLITE_PRIVATE int sqlite3BtreeBeginTrans(Btree *p, int wrflag, int *pSchemaVers
if( (pBt->btsFlags & BTS_READ_ONLY)!=0 ){
rc = SQLITE_READONLY;
}else{
- rc = sqlite3PagerBegin(pBt->pPager,wrflag>1,sqlite3TempInMemory(p->db));
+ rc = sqlite3PagerBegin(pPager, wrflag>1, sqlite3TempInMemory(p->db));
if( rc==SQLITE_OK ){
rc = newDatabase(pBt);
}else if( rc==SQLITE_BUSY_SNAPSHOT && pBt->inTransaction==TRANS_NONE ){
@@ -66044,13 +68959,17 @@ SQLITE_PRIVATE int sqlite3BtreeBeginTrans(Btree *p, int wrflag, int *pSchemaVers
}
}
}
-
+
if( rc!=SQLITE_OK ){
+ (void)sqlite3PagerWalWriteLock(pPager, 0);
unlockBtreeIfUnused(pBt);
}
}while( (rc&0xFF)==SQLITE_BUSY && pBt->inTransaction==TRANS_NONE &&
btreeInvokeBusyHandler(pBt) );
- sqlite3PagerResetLockTimeout(pBt->pPager);
+ sqlite3PagerWalDb(pPager, 0);
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+ if( rc==SQLITE_BUSY_TIMEOUT ) rc = SQLITE_BUSY;
+#endif
if( rc==SQLITE_OK ){
if( p->inTrans==TRANS_NONE ){
@@ -66079,7 +68998,7 @@ SQLITE_PRIVATE int sqlite3BtreeBeginTrans(Btree *p, int wrflag, int *pSchemaVers
/* If the db-size header field is incorrect (as it may be if an old
** client has been writing the database file), update it now. Doing
- ** this sooner rather than later means the database size can safely
+ ** this sooner rather than later means the database size can safely
** re-read the database size from page 1 if a savepoint or transaction
** rollback occurs within the transaction.
*/
@@ -66102,7 +69021,7 @@ trans_begun:
** open savepoints. If the second parameter is greater than 0 and
** the sub-journal is not already open, then it will be opened here.
*/
- rc = sqlite3PagerOpenSavepoint(pBt->pPager, p->db->nSavepoint);
+ rc = sqlite3PagerOpenSavepoint(pPager, p->db->nSavepoint);
}
}
@@ -66133,7 +69052,7 @@ static int setChildPtrmaps(MemPage *pPage){
for(i=0; ileaf ){
Pgno childPgno = get4byte(pCell);
@@ -66154,7 +69073,7 @@ static int setChildPtrmaps(MemPage *pPage){
** 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
@@ -66202,9 +69121,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_PAGE(pPage);
}
@@ -66216,11 +69135,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.
*/
@@ -66237,13 +69156,14 @@ 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 );
+ if( iDbPage<3 ) return SQLITE_CORRUPT_BKPT;
/* 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 ){
@@ -66302,19 +69222,19 @@ static int allocateBtreePage(BtShared *, MemPage **, Pgno *, Pgno, u8);
/*
** Perform a single step of an incremental-vacuum. If successful, return
-** SQLITE_OK. If there is no work to do (and therefore no point in
-** calling this function again), return SQLITE_DONE. Or, if an error
+** SQLITE_OK. If there is no work to do (and therefore no point in
+** calling this function again), return SQLITE_DONE. Or, if an error
** occurs, return some other error code.
**
-** More specifically, this function attempts to re-organize the database so
+** More specifically, this function attempts to re-organize the database so
** that the last page of the file currently in use is no longer in use.
**
** Parameter nFin is the number of pages that this database would contain
** were this function called until it returns SQLITE_DONE.
**
-** If the bCommit parameter is non-zero, this function assumes that the
-** caller will keep calling incrVacuumStep() until it returns SQLITE_DONE
-** or an error. bCommit is passed true for an auto-vacuum-on-commit
+** If the bCommit parameter is non-zero, this function assumes that the
+** caller will keep calling incrVacuumStep() until it returns SQLITE_DONE
+** or an error. bCommit is passed true for an auto-vacuum-on-commit
** operation, or false for an incremental vacuum.
*/
static int incrVacuumStep(BtShared *pBt, Pgno nFin, Pgno iLastPg, int bCommit){
@@ -66345,7 +69265,7 @@ static int incrVacuumStep(BtShared *pBt, Pgno nFin, Pgno iLastPg, int bCommit){
if( bCommit==0 ){
/* Remove the page from the files free-list. This is not required
** if bCommit 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;
@@ -66389,7 +69309,7 @@ static int incrVacuumStep(BtShared *pBt, Pgno nFin, Pgno iLastPg, int bCommit){
releasePage(pFreePg);
}while( bCommit && iFreePg>nFin );
assert( iFreePgpPage1->aData[36]);
Pgno nFin = finalDbSize(pBt, nOrig, nFree);
- if( nOrig=nOrig ){
rc = SQLITE_CORRUPT_BKPT;
}else if( nFree>0 ){
rc = saveAllCursors(pBt, 0, 0);
@@ -66477,7 +69397,7 @@ SQLITE_PRIVATE int sqlite3BtreeIncrVacuum(Btree *p){
** is committed for an auto-vacuum database.
**
** If SQLITE_OK is returned, then *pnTrunc is set to the number of pages
-** the database file should be truncated to during the commit process.
+** 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.
*/
@@ -66549,18 +69469,18 @@ static int autoVacuumCommit(BtShared *pBt){
**
** This call is a no-op if no write-transaction is currently active on 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
+** Otherwise, sync the database file for the btree pBt. zSuperJrnl points to
+** the name of a super-journal file that should be written into the
+** individual journal file, or is NULL, indicating no super-journal file
** (single database transaction).
**
-** When this is called, the master journal should already have been
+** When this is called, the super-journal should already have been
** created, populated with this journal pointer and synced to disk.
**
** Once this is routine has returned, the only thing required to commit
** the write-transaction for this database file is to delete the journal.
*/
-SQLITE_PRIVATE int sqlite3BtreeCommitPhaseOne(Btree *p, const char *zMaster){
+SQLITE_PRIVATE int sqlite3BtreeCommitPhaseOne(Btree *p, const char *zSuperJrnl){
int rc = SQLITE_OK;
if( p->inTrans==TRANS_WRITE ){
BtShared *pBt = p->pBt;
@@ -66577,7 +69497,7 @@ SQLITE_PRIVATE int sqlite3BtreeCommitPhaseOne(Btree *p, const char *zMaster){
sqlite3PagerTruncateImage(pBt->pPager, pBt->nPage);
}
#endif
- rc = sqlite3PagerCommitPhaseOne(pBt->pPager, zMaster, 0);
+ rc = sqlite3PagerCommitPhaseOne(pBt->pPager, zSuperJrnl, 0);
sqlite3BtreeLeave(p);
}
return rc;
@@ -66602,8 +69522,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 ){
@@ -66614,7 +69534,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);
@@ -66635,12 +69555,12 @@ static void btreeEndTransaction(Btree *p){
** the rollback journal (which causes the transaction to commit) and
** drop locks.
**
-** Normally, if an error occurs while the pager layer is attempting to
+** Normally, if an error occurs while the pager layer is attempting to
** finalize the underlying journal file, this function returns an error and
** the upper layer will attempt a rollback. However, if the second argument
-** is non-zero then this b-tree transaction is part of a multi-file
-** transaction. In this case, the transaction has already been committed
-** (by deleting a master journal file) and the caller will ignore this
+** is non-zero then this b-tree transaction is part of a multi-file
+** transaction. In this case, the transaction has already been committed
+** (by deleting a super-journal file) and the caller will ignore this
** functions return code. So, even if an error occurs in the pager layer,
** reset the b-tree objects internal state to indicate that the write
** transaction has been closed. This is quite safe, as the pager will have
@@ -66655,7 +69575,7 @@ SQLITE_PRIVATE int sqlite3BtreeCommitPhaseTwo(Btree *p, int bCleanup){
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 ){
@@ -66668,7 +69588,7 @@ SQLITE_PRIVATE int sqlite3BtreeCommitPhaseTwo(Btree *p, int bCleanup){
sqlite3BtreeLeave(p);
return rc;
}
- p->iDataVersion--; /* Compensate for pPager->iDataVersion++; */
+ p->iBDataVersion--; /* Compensate for pPager->iDataVersion++; */
pBt->inTransaction = TRANS_READ;
btreeClearHasContent(pBt);
}
@@ -66704,15 +69624,15 @@ SQLITE_PRIVATE int sqlite3BtreeCommit(Btree *p){
**
** This routine gets called when a rollback occurs. If the writeOnly
** flag is true, then only write-cursors need be tripped - read-only
-** cursors save their current positions so that they may continue
-** following the rollback. Or, if writeOnly is false, all cursors are
+** cursors save their current positions so that they may continue
+** following the rollback. Or, if writeOnly is false, all cursors are
** tripped. In general, writeOnly is false if the transaction being
** rolled back modified the database schema. In this case b-tree root
** pages may be moved or deleted from the database altogether, making
** it unsafe for read cursors to continue.
**
-** If the writeOnly flag is true and an error is encountered while
-** saving the current position of a read-only cursor, all cursors,
+** If the writeOnly flag is true and an error is encountered while
+** saving the current position of a read-only cursor, all cursors,
** including all read-cursors are tripped.
**
** SQLITE_OK is returned if successful, or if an error occurs while
@@ -66746,6 +69666,18 @@ SQLITE_PRIVATE int sqlite3BtreeTripAllCursors(Btree *pBtree, int errCode, int wr
return rc;
}
+/*
+** Set the pBt->nPage field correctly, according to the current
+** state of the database. Assume pBt->pPage1 is valid.
+*/
+static void btreeSetNPage(BtShared *pBt, MemPage *pPage1){
+ int nPage = get4byte(&pPage1->aData[28]);
+ testcase( nPage==0 );
+ if( nPage==0 ) sqlite3PagerPagecount(pBt->pPager, &nPage);
+ testcase( pBt->nPage!=nPage );
+ pBt->nPage = nPage;
+}
+
/*
** Rollback the transaction in progress.
**
@@ -66791,11 +69723,7 @@ SQLITE_PRIVATE int sqlite3BtreeRollback(Btree *p, int tripCode, int writeOnly){
** 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;
+ btreeSetNPage(pBt, pPage1);
releasePageOne(pPage1);
}
assert( countValidCursors(pBt, 1)==0 );
@@ -66810,8 +69738,8 @@ SQLITE_PRIVATE int sqlite3BtreeRollback(Btree *p, int tripCode, int writeOnly){
/*
** Start a statement subtransaction. The subtransaction 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
@@ -66848,11 +69776,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.
@@ -66875,12 +69803,11 @@ SQLITE_PRIVATE int sqlite3BtreeSavepoint(Btree *p, int op, int iSavepoint){
pBt->nPage = 0;
}
rc = newDatabase(pBt);
- pBt->nPage = get4byte(28 + pBt->pPage1->aData);
+ btreeSetNPage(pBt, pBt->pPage1);
- /* The database size was written into the offset 28 of the header
- ** when the transaction started, so we know that the value at offset
- ** 28 is nonzero. */
- assert( pBt->nPage>0 );
+ /* pBt->nPage might be zero if the database was corrupt when
+ ** the transaction was started. Otherwise, it must be at least 1. */
+ assert( CORRUPT_DB || pBt->nPage>0 );
}
sqlite3BtreeLeave(p);
}
@@ -66916,10 +69843,10 @@ SQLITE_PRIVATE int sqlite3BtreeSavepoint(Btree *p, int op, int iSavepoint){
** is set. If FORDELETE is set, that is a hint to the implementation that
** this cursor will only be used to seek to and delete entries of an index
** as part of a larger DELETE statement. The FORDELETE hint is not used by
-** this implementation. But in a hypothetical alternative storage engine
+** this implementation. But in a hypothetical alternative storage engine
** in which index entries are automatically deleted when corresponding table
** rows are deleted, the FORDELETE flag is a hint that all SEEK and DELETE
-** operations on this cursor can be no-ops and all READ operations can
+** operations on this cursor can be no-ops and all READ operations can
** return a null row (2-bytes: 0x01 0x00).
**
** No checking is done to make sure that page iTable really is the
@@ -66931,7 +69858,7 @@ SQLITE_PRIVATE int sqlite3BtreeSavepoint(Btree *p, int op, int iSavepoint){
*/
static int btreeCursor(
Btree *p, /* The btree */
- int iTable, /* Root page of table to open */
+ Pgno iTable, /* Root page of table to open */
int wrFlag, /* 1 to write. 0 read-only */
struct KeyInfo *pKeyInfo, /* First arg to comparison function */
BtCursor *pCur /* Space for new cursor */
@@ -66940,16 +69867,17 @@ static int btreeCursor(
BtCursor *pX; /* Looping over other all cursors */
assert( sqlite3BtreeHoldsMutex(p) );
- assert( wrFlag==0
- || wrFlag==BTREE_WRCSR
- || wrFlag==(BTREE_WRCSR|BTREE_FORDELETE)
+ assert( wrFlag==0
+ || wrFlag==BTREE_WRCSR
+ || wrFlag==(BTREE_WRCSR|BTREE_FORDELETE)
);
- /* 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?2: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
+ ** this lock. The iTable<1 term disables the check for corrupt schemas. */
+ assert( hasSharedCacheTableLock(p, iTable, pKeyInfo!=0, (wrFlag?2:1))
+ || iTable<1 );
assert( wrFlag==0 || !hasReadConflicts(p, iTable) );
/* Assert that the caller has opened the required transaction. */
@@ -66962,14 +69890,18 @@ static int btreeCursor(
allocateTempSpace(pBt);
if( pBt->pTmpSpace==0 ) return SQLITE_NOMEM_BKPT;
}
- if( iTable==1 && btreePagecount(pBt)==0 ){
- assert( wrFlag==0 );
- iTable = 0;
+ if( iTable<=1 ){
+ if( iTable<1 ){
+ return SQLITE_CORRUPT_BKPT;
+ }else if( btreePagecount(pBt)==0 ){
+ assert( wrFlag==0 );
+ iTable = 0;
+ }
}
/* Now that no other errors can occur, finish filling in the BtCursor
** variables and link the cursor into the BtShared list. */
- pCur->pgnoRoot = (Pgno)iTable;
+ pCur->pgnoRoot = iTable;
pCur->iPage = -1;
pCur->pKeyInfo = pKeyInfo;
pCur->pBtree = p;
@@ -66979,7 +69911,7 @@ static int btreeCursor(
/* If there are two or more cursors on the same btree, then all such
** cursors *must* have the BTCF_Multiple flag set. */
for(pX=pBt->pCursor; pX; pX=pX->pNext){
- if( pX->pgnoRoot==(Pgno)iTable ){
+ if( pX->pgnoRoot==iTable ){
pX->curFlags |= BTCF_Multiple;
pCur->curFlags |= BTCF_Multiple;
}
@@ -66989,22 +69921,31 @@ static int btreeCursor(
pCur->eState = CURSOR_INVALID;
return SQLITE_OK;
}
+static int btreeCursorWithLock(
+ Btree *p, /* The btree */
+ Pgno iTable, /* Root page of table to open */
+ int wrFlag, /* 1 to write. 0 read-only */
+ struct KeyInfo *pKeyInfo, /* First arg to comparison function */
+ BtCursor *pCur /* Space for new cursor */
+){
+ int rc;
+ sqlite3BtreeEnter(p);
+ rc = btreeCursor(p, iTable, wrFlag, pKeyInfo, pCur);
+ sqlite3BtreeLeave(p);
+ return rc;
+}
SQLITE_PRIVATE int sqlite3BtreeCursor(
Btree *p, /* The btree */
- int iTable, /* Root page of table to open */
+ Pgno iTable, /* Root page of table to open */
int wrFlag, /* 1 to write. 0 read-only */
struct KeyInfo *pKeyInfo, /* First arg to xCompare() */
BtCursor *pCur /* Write new cursor here */
){
- int rc;
- if( iTable<1 ){
- rc = SQLITE_CORRUPT_BKPT;
+ if( p->sharable ){
+ return btreeCursorWithLock(p, iTable, wrFlag, pKeyInfo, pCur);
}else{
- sqlite3BtreeEnter(p);
- rc = btreeCursor(p, iTable, wrFlag, pKeyInfo, pCur);
- sqlite3BtreeLeave(p);
+ return btreeCursor(p, iTable, wrFlag, pKeyInfo, pCur);
}
- return rc;
}
/*
@@ -67057,7 +69998,15 @@ SQLITE_PRIVATE int sqlite3BtreeCloseCursor(BtCursor *pCur){
unlockBtreeIfUnused(pBt);
sqlite3_free(pCur->aOverflow);
sqlite3_free(pCur->pKey);
- sqlite3BtreeLeave(pBtree);
+ if( (pBt->openFlags & BTREE_SINGLE) && pBt->pCursor==0 ){
+ /* Since the BtShared is not sharable, there is no need to
+ ** worry about the missing sqlite3BtreeLeave() call here. */
+ assert( pBtree->sharable==0 );
+ sqlite3BtreeClose(pBtree);
+ }else{
+ sqlite3BtreeLeave(pBtree);
+ }
+ pCur->pBtree = 0;
}
return SQLITE_OK;
}
@@ -67126,6 +70075,18 @@ SQLITE_PRIVATE i64 sqlite3BtreeIntegerKey(BtCursor *pCur){
return pCur->info.nKey;
}
+/*
+** Pin or unpin a cursor.
+*/
+SQLITE_PRIVATE void sqlite3BtreeCursorPin(BtCursor *pCur){
+ assert( (pCur->curFlags & BTCF_Pinned)==0 );
+ pCur->curFlags |= BTCF_Pinned;
+}
+SQLITE_PRIVATE void sqlite3BtreeCursorUnpin(BtCursor *pCur){
+ assert( (pCur->curFlags & BTCF_Pinned)!=0 );
+ pCur->curFlags &= ~BTCF_Pinned;
+}
+
#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC
/*
** Return the offset into the database file for the start of the
@@ -67156,17 +70117,36 @@ SQLITE_PRIVATE u32 sqlite3BtreePayloadSize(BtCursor *pCur){
return pCur->info.nPayload;
}
+/*
+** Return an upper bound on the size of any record for the table
+** that the cursor is pointing into.
+**
+** This is an optimization. Everything will still work if this
+** routine always returns 2147483647 (which is the largest record
+** that SQLite can handle) or more. But returning a smaller value might
+** prevent large memory allocations when trying to interpret a
+** corrupt datrabase.
+**
+** The current implementation merely returns the size of the underlying
+** database file.
+*/
+SQLITE_PRIVATE sqlite3_int64 sqlite3BtreeMaxRecordSize(BtCursor *pCur){
+ assert( cursorHoldsMutex(pCur) );
+ assert( pCur->eState==CURSOR_VALID );
+ return pCur->pBt->pageSize * (sqlite3_int64)pCur->pBt->nPage;
+}
+
/*
** 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
@@ -67190,9 +70170,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 ){
@@ -67280,8 +70260,8 @@ static int copyPayload(
**
** If the current cursor entry uses one or more overflow pages
** this function may allocate space for and lazily populate
-** the overflow page-list cache array (BtCursor.aOverflow).
-** Subsequent calls use this cache to make seeking to the supplied offset
+** the overflow page-list cache array (BtCursor.aOverflow).
+** Subsequent calls use this cache to make seeking to the supplied offset
** more efficient.
**
** Once an overflow page-list cache has been allocated, it must be
@@ -67297,7 +70277,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;
@@ -67388,6 +70368,7 @@ static int accessPayload(
assert( rc==SQLITE_OK && amt>0 );
while( nextPage ){
/* If required, populate the overflow page-list cache. */
+ if( nextPage > pBt->nPage ) return SQLITE_CORRUPT_BKPT;
assert( pCur->aOverflow[iIdx]==0
|| pCur->aOverflow[iIdx]==nextPage
|| CORRUPT_DB );
@@ -67412,9 +70393,6 @@ static int accessPayload(
/* Need to read this page properly. It contains some of the
** range of data that is being read (eOp==0) or written (eOp!=0).
*/
-#ifdef SQLITE_DIRECT_OVERFLOW_READ
- sqlite3_file *fd; /* File from which to do direct overflow read */
-#endif
int a = amt;
if( a + offset > ovflSize ){
a = ovflSize - offset;
@@ -67423,12 +70401,12 @@ static int accessPayload(
#ifdef SQLITE_DIRECT_OVERFLOW_READ
/* If all the following are true:
**
- ** 1) this is a read operation, and
+ ** 1) this is a read operation, and
** 2) data is required from the start of this overflow page, and
- ** 3) there is no open write-transaction, and
+ ** 3) there are no dirty pages in the page-cache
** 4) the database is file-backed, and
** 5) the page is not in the WAL file
- ** 6) at least 4 bytes have already been read into the output buffer
+ ** 6) at least 4 bytes have already been read into the output buffer
**
** then data can be read directly from the database file into the
** output buffer, bypassing the page-cache altogether. This speeds
@@ -67436,16 +70414,16 @@ static int accessPayload(
*/
if( eOp==0 /* (1) */
&& offset==0 /* (2) */
- && pBt->inTransaction==TRANS_READ /* (3) */
- && (fd = sqlite3PagerFile(pBt->pPager))->pMethods /* (4) */
- && 0==sqlite3PagerUseWal(pBt->pPager, nextPage) /* (5) */
+ && sqlite3PagerDirectReadOk(pBt->pPager, nextPage) /* (3,4,5) */
&& &pBuf[-4]>=pBufStart /* (6) */
){
+ sqlite3_file *fd = sqlite3PagerFile(pBt->pPager);
u8 aSave[4];
u8 *aWrite = &pBuf[-4];
assert( aWrite>=pBufStart ); /* due to (6) */
memcpy(aSave, aWrite, 4);
rc = sqlite3OsRead(fd, aWrite, a+4, (i64)pBt->pageSize*(nextPage-1));
+ if( rc && nextPage>pBt->nPage ) rc = SQLITE_CORRUPT_BKPT;
nextPage = get4byte(aWrite);
memcpy(aWrite, aSave, 4);
}else
@@ -67536,7 +70514,7 @@ SQLITE_PRIVATE int sqlite3BtreePayloadChecked(BtCursor *pCur, u32 offset, u32 am
#endif /* SQLITE_OMIT_INCRBLOB */
/*
-** 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 index btrees (pPage->intKey==0) and is the data for
** table btrees (pPage->intKey==1). The number of bytes of available
@@ -67628,7 +70606,7 @@ static int moveToChild(BtCursor *pCur, u32 newPgno){
#ifdef SQLITE_DEBUG
/*
-** 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
@@ -67645,7 +70623,7 @@ static void assertParentIndex(MemPage *pParent, int iIdx, Pgno iChild){
}
}
#else
-# define assertParentIndex(x,y,z)
+# define assertParentIndex(x,y,z)
#endif
/*
@@ -67663,8 +70641,8 @@ static void moveToParent(BtCursor *pCur){
assert( pCur->iPage>0 );
assert( pCur->pPage );
assertParentIndex(
- pCur->apPage[pCur->iPage-1],
- pCur->aiIdx[pCur->iPage-1],
+ pCur->apPage[pCur->iPage-1],
+ pCur->aiIdx[pCur->iPage-1],
pCur->pPage->pgno
);
testcase( pCur->aiIdx[pCur->iPage-1] > pCur->apPage[pCur->iPage-1]->nCell );
@@ -67681,19 +70659,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 and this routine returns SQLITE_EMPTY. 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).
*/
@@ -67744,19 +70722,19 @@ static int moveToRoot(BtCursor *pCur){
/* If pCur->pKeyInfo is not NULL, then the caller that opened this cursor
** expected to open it on an index b-tree. Otherwise, if pKeyInfo is
** NULL, the caller expects a table b-tree. If this is not the case,
- ** return an SQLITE_CORRUPT error.
+ ** return an SQLITE_CORRUPT error.
**
** Earlier versions of SQLite assumed that this test could not fail
** if the root page was already loaded when this function was called (i.e.
- ** if pCur->iPage>=0). But this is not so if the database is corrupted
- ** in such a way that page pRoot is linked into a second b-tree table
+ ** if pCur->iPage>=0). But this is not so if the database is corrupted
+ ** in such a way that page pRoot is linked into a second b-tree table
** (or the freelist). */
assert( pRoot->intKey==1 || pRoot->intKey==0 );
if( pRoot->isInit==0 || (pCur->pKeyInfo==0)!=pRoot->intKey ){
return SQLITE_CORRUPT_PAGE(pCur->pPage);
}
-skip_init:
+skip_init:
pCur->ix = 0;
pCur->info.nSize = 0;
pCur->curFlags &= ~(BTCF_AtLast|BTCF_ValidNKey|BTCF_ValidOvfl);
@@ -67850,45 +70828,31 @@ SQLITE_PRIVATE int sqlite3BtreeFirst(BtCursor *pCur, int *pRes){
return rc;
}
-/*
-** This function is a no-op if cursor pCur does not point to a valid row.
-** Otherwise, if pCur is valid, configure it so that the next call to
-** sqlite3BtreeNext() is a no-op.
-*/
-#ifndef SQLITE_OMIT_WINDOWFUNC
-SQLITE_PRIVATE void sqlite3BtreeSkipNext(BtCursor *pCur){
- /* We believe that the cursor must always be in the valid state when
- ** this routine is called, but the proof is difficult, so we add an
- ** ALWaYS() test just in case we are wrong. */
- if( ALWAYS(pCur->eState==CURSOR_VALID) ){
- pCur->eState = CURSOR_SKIPNEXT;
- pCur->skipNext = 1;
- }
-}
-#endif /* SQLITE_OMIT_WINDOWFUNC */
-
/* Move the cursor to the last entry in the table. Return SQLITE_OK
** on success. Set *pRes to 0 if the cursor actually points to something
** or set *pRes to 1 if the table is empty.
*/
SQLITE_PRIVATE int sqlite3BtreeLast(BtCursor *pCur, int *pRes){
int rc;
-
+
assert( cursorOwnsBtShared(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->curFlags & BTCF_AtLast)!=0 ){
#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; iiiPage; ii++){
assert( pCur->aiIdx[ii]==pCur->apPage[ii]->nCell );
}
- assert( pCur->ix==pCur->pPage->nCell-1 );
+ assert( pCur->ix==pCur->pPage->nCell-1 || CORRUPT_DB );
+ testcase( pCur->ix!=pCur->pPage->nCell-1 );
+ /* ^-- dbsqlfuzz b92b72e4de80b5140c30ab71372ca719b8feb618 */
assert( pCur->pPage->leaf );
#endif
+ *pRes = 0;
return SQLITE_OK;
}
@@ -67910,10 +70874,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.
**
@@ -67923,7 +70887,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:
**
@@ -67938,7 +70902,7 @@ SQLITE_PRIVATE int sqlite3BtreeLast(BtCursor *pCur, int *pRes){
** is larger than intKey/pIdxKey.
**
** For index tables, the pIdxKey->eqSeen field is set to 1 if there
-** exists an entry in the table that exactly matches pIdxKey.
+** exists an entry in the table that exactly matches pIdxKey.
*/
SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked(
BtCursor *pCur, /* The cursor to be moved */
@@ -67974,7 +70938,7 @@ SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked(
** try to get there using sqlite3BtreeNext() rather than a full
** binary search. This is an optimization only. The correct answer
** is still obtained without this case, only a little more slowely */
- if( pCur->info.nKey+1==intKey && !pCur->skipNext ){
+ if( pCur->info.nKey+1==intKey ){
*pRes = 0;
rc = sqlite3BtreeNext(pCur, 0);
if( rc==SQLITE_OK ){
@@ -67991,11 +70955,15 @@ SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked(
}
}
+#ifdef SQLITE_DEBUG
+ pCur->pBtree->nSeek++; /* Performance measurement during testing */
+#endif
+
if( pIdxKey ){
xRecordCompare = sqlite3VdbeFindCompare(pIdxKey);
pIdxKey->errCode = 0;
- assert( pIdxKey->default_rc==1
- || pIdxKey->default_rc==0
+ assert( pIdxKey->default_rc==1
+ || pIdxKey->default_rc==0
|| pIdxKey->default_rc==-1
);
}else{
@@ -68079,9 +71047,9 @@ SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked(
/* The maximum supported page-size is 65536 bytes. This means that
** the maximum number of record bytes stored on an index B-Tree
** page is less than 16384 bytes and 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.
*/
nCell = pCell[0];
@@ -68091,10 +71059,10 @@ SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked(
** b-tree page. */
testcase( pCell+nCell+1==pPage->aDataEnd );
c = xRecordCompare(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. */
testcase( pCell+nCell+2==pPage->aDataEnd );
c = xRecordCompare(nCell, (void*)&pCell[2], pIdxKey);
@@ -68102,40 +71070,42 @@ SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked(
/* The record flows over onto one or more overflow pages. In
** this case the whole cell needs to be parsed, a buffer allocated
** and accessPayload() used to retrieve the record into the
- ** buffer before VdbeRecordCompare() can be called.
+ ** buffer before VdbeRecordCompare() can be called.
**
** If the record is corrupt, the xRecordCompare routine may read
- ** up to two varints past the end of the buffer. An extra 18
+ ** up to two varints past the end of the buffer. An extra 18
** bytes of padding is allocated at the end of the buffer in
** case this happens. */
void *pCellKey;
u8 * const pCellBody = pCell - pPage->childPtrSize;
+ const int nOverrun = 18; /* Size of the overrun padding */
pPage->xParseCell(pPage, pCellBody, &pCur->info);
nCell = (int)pCur->info.nKey;
testcase( nCell<0 ); /* True if key size is 2^32 or more */
testcase( nCell==0 ); /* Invalid key size: 0x80 0x80 0x00 */
testcase( nCell==1 ); /* Invalid key size: 0x80 0x80 0x01 */
testcase( nCell==2 ); /* Minimum legal index key size */
- if( nCell<2 ){
+ if( nCell<2 || nCell/pCur->pBt->usableSize>pCur->pBt->nPage ){
rc = SQLITE_CORRUPT_PAGE(pPage);
goto moveto_finish;
}
- pCellKey = sqlite3Malloc( nCell+18 );
+ pCellKey = sqlite3Malloc( nCell+nOverrun );
if( pCellKey==0 ){
rc = SQLITE_NOMEM_BKPT;
goto moveto_finish;
}
pCur->ix = (u16)idx;
rc = accessPayload(pCur, 0, nCell, (unsigned char*)pCellKey, 0);
+ memset(((u8*)pCellKey)+nCell,0,nOverrun); /* Fix uninit warnings */
pCur->curFlags &= ~BTCF_ValidOvfl;
if( rc ){
sqlite3_free(pCellKey);
goto moveto_finish;
}
- c = xRecordCompare(nCell, pCellKey, pIdxKey);
+ c = sqlite3VdbeRecordCompare(nCell, pCellKey, pIdxKey);
sqlite3_free(pCellKey);
}
- assert(
+ assert(
(pIdxKey->errCode!=SQLITE_CORRUPT || c==0)
&& (pIdxKey->errCode!=SQLITE_NOMEM || pCur->pBtree->db->mallocFailed)
);
@@ -68199,7 +71169,7 @@ SQLITE_PRIVATE int sqlite3BtreeEof(BtCursor *pCur){
/*
** Return an estimate for the number of rows in the table that pCur is
-** pointing to. Return a negative number if no estimate is currently
+** pointing to. Return a negative number if no estimate is currently
** available.
*/
SQLITE_PRIVATE i64 sqlite3BtreeRowCountEst(BtCursor *pCur){
@@ -68223,7 +71193,7 @@ SQLITE_PRIVATE i64 sqlite3BtreeRowCountEst(BtCursor *pCur){
}
/*
-** Advance the cursor to the next entry in the database.
+** Advance the cursor to the next entry in the database.
** Return value:
**
** SQLITE_OK success
@@ -68248,7 +71218,6 @@ static SQLITE_NOINLINE int btreeNext(BtCursor *pCur){
MemPage *pPage;
assert( cursorOwnsBtShared(pCur) );
- assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID );
if( pCur->eState!=CURSOR_VALID ){
assert( (pCur->curFlags & BTCF_ValidOvfl)==0 );
rc = restoreCursorPosition(pCur);
@@ -68258,20 +71227,15 @@ static SQLITE_NOINLINE int btreeNext(BtCursor *pCur){
if( CURSOR_INVALID==pCur->eState ){
return SQLITE_DONE;
}
- if( pCur->skipNext ){
- assert( pCur->eState==CURSOR_VALID || pCur->eState==CURSOR_SKIPNEXT );
+ if( pCur->eState==CURSOR_SKIPNEXT ){
pCur->eState = CURSOR_VALID;
- if( pCur->skipNext>0 ){
- pCur->skipNext = 0;
- return SQLITE_OK;
- }
- pCur->skipNext = 0;
+ if( pCur->skipNext>0 ) return SQLITE_OK;
}
}
pPage = pCur->pPage;
idx = ++pCur->ix;
- if( !pPage->isInit ){
+ if( !pPage->isInit || sqlite3FaultSim(412) ){
/* The only known way for this to happen is for there to be a
** recursive SQL function that does a DELETE operation as part of a
** SELECT which deletes content out from under an active cursor
@@ -68282,12 +71246,15 @@ static SQLITE_NOINLINE int btreeNext(BtCursor *pCur){
return SQLITE_CORRUPT_BKPT;
}
- /* If the database file is corrupt, it is possible for the value of idx
+ /* If the database file is corrupt, it is possible for the value of idx
** to be invalid here. This can only occur if a second cursor modifies
** the page while cursor pCur is holding a reference to it. Which can
** only happen if the database is corrupt in such a way as to link the
- ** page into more than one b-tree structure. */
- testcase( idx>pPage->nCell );
+ ** page into more than one b-tree structure.
+ **
+ ** Update 2019-12-23: appears to long longer be possible after the
+ ** addition of anotherValidCursor() condition on balance_deeper(). */
+ harmless( idx>pPage->nCell );
if( idx>=pPage->nCell ){
if( !pPage->leaf ){
@@ -68320,7 +71287,6 @@ SQLITE_PRIVATE int sqlite3BtreeNext(BtCursor *pCur, int flags){
UNUSED_PARAMETER( flags ); /* Used in COMDB2 but not native SQLite */
assert( cursorOwnsBtShared(pCur) );
assert( flags==0 || flags==1 );
- assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID );
pCur->info.nSize = 0;
pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl);
if( pCur->eState!=CURSOR_VALID ) return btreeNext(pCur);
@@ -68361,7 +71327,6 @@ static SQLITE_NOINLINE int btreePrevious(BtCursor *pCur){
MemPage *pPage;
assert( cursorOwnsBtShared(pCur) );
- assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID );
assert( (pCur->curFlags & (BTCF_AtLast|BTCF_ValidOvfl|BTCF_ValidNKey))==0 );
assert( pCur->info.nSize==0 );
if( pCur->eState!=CURSOR_VALID ){
@@ -68372,14 +71337,9 @@ static SQLITE_NOINLINE int btreePrevious(BtCursor *pCur){
if( CURSOR_INVALID==pCur->eState ){
return SQLITE_DONE;
}
- if( pCur->skipNext ){
- assert( pCur->eState==CURSOR_VALID || pCur->eState==CURSOR_SKIPNEXT );
+ if( CURSOR_SKIPNEXT==pCur->eState ){
pCur->eState = CURSOR_VALID;
- if( pCur->skipNext<0 ){
- pCur->skipNext = 0;
- return SQLITE_OK;
- }
- pCur->skipNext = 0;
+ if( pCur->skipNext<0 ) return SQLITE_OK;
}
}
@@ -68414,7 +71374,6 @@ static SQLITE_NOINLINE int btreePrevious(BtCursor *pCur){
SQLITE_PRIVATE int sqlite3BtreePrevious(BtCursor *pCur, int flags){
assert( cursorOwnsBtShared(pCur) );
assert( flags==0 || flags==1 );
- assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID );
UNUSED_PARAMETER( flags ); /* Used in COMDB2 but not native SQLite */
pCur->curFlags &= ~(BTCF_AtLast|BTCF_ValidOvfl|BTCF_ValidNKey);
pCur->info.nSize = 0;
@@ -68439,7 +71398,7 @@ SQLITE_PRIVATE int sqlite3BtreePrevious(BtCursor *pCur, int flags){
** SQLITE_OK is returned on success. Any other return value indicates
** an error. *ppPage is set to NULL in the event of an error.
**
-** If the "nearby" parameter is not 0, then an effort is made to
+** If the "nearby" parameter is not 0, then an 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.
@@ -68481,7 +71440,7 @@ static int allocateBtreePage(
Pgno iTrunk;
u8 searchList = 0; /* If the free-list must be searched for 'nearby' */
u32 nSearch = 0; /* Count of the number of search attempts */
-
+
/* If eMode==BTALLOC_EXACT 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.
@@ -68544,8 +71503,8 @@ static int allocateBtreePage(
** is the number of leaf page pointers to follow. */
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);
@@ -68562,8 +71521,8 @@ static int allocateBtreePage(
rc = SQLITE_CORRUPT_PGNO(iTrunk);
goto end_allocate_page;
#ifndef SQLITE_OMIT_AUTOVACUUM
- }else if( searchList
- && (nearby==iTrunk || (iTrunkaData[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_PGNO(iTrunk);
goto end_allocate_page;
}
@@ -68657,13 +71616,13 @@ static int allocateBtreePage(
iPage = get4byte(&aData[8+closest*4]);
testcase( iPage==mxPage );
- if( iPage>mxPage ){
+ if( iPage>mxPage || iPage<2 ){
rc = SQLITE_CORRUPT_PGNO(iTrunk);
goto end_allocate_page;
}
testcase( iPage==mxPage );
- if( !searchList
- || (iPage==nearby || (iPagepPage1; /* Local reference to page 1 */
MemPage *pPage; /* Page being freed. May be NULL. */
int rc; /* Return Code */
- int nFree; /* Initial number of pages on free-list */
+ u32 nFree; /* Initial number of pages on free-list */
assert( sqlite3_mutex_held(pBt->mutex) );
assert( CORRUPT_DB || iPage>1 );
assert( !pMemPage || pMemPage->pgno==iPage );
- if( iPage<2 ) return SQLITE_CORRUPT_BKPT;
+ if( iPage<2 || iPage>pBt->nPage ){
+ return SQLITE_CORRUPT_BKPT;
+ }
if( pMemPage ){
pPage = pMemPage;
sqlite3PagerRef(pPage->pDbPage);
@@ -68829,6 +71790,10 @@ static int freePage2(BtShared *pBt, MemPage *pMemPage, Pgno iPage){
u32 nLeaf; /* Initial number of leaf cells on trunk page */
iTrunk = get4byte(&pPage1->aData[32]);
+ if( iTrunk>btreePagecount(pBt) ){
+ rc = SQLITE_CORRUPT_BKPT;
+ goto freepage_out;
+ }
rc = btreeGetPage(pBt, iTrunk, &pTrunk, 0);
if( rc!=SQLITE_OK ){
goto freepage_out;
@@ -68876,7 +71841,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.
*/
@@ -68907,10 +71872,9 @@ static void freePage(MemPage *pPage, int *pRC){
}
/*
-** Free any overflow pages associated with the given Cell. Store
-** size information about the cell in pInfo.
+** Free the overflow pages associated with the given Cell.
*/
-static int clearCell(
+static SQLITE_NOINLINE int clearCellOverflow(
MemPage *pPage, /* The page that contains the Cell */
unsigned char *pCell, /* First byte of the Cell */
CellInfo *pInfo /* Size information about the cell */
@@ -68922,10 +71886,7 @@ static int clearCell(
u32 ovflPageSize;
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
- pPage->xParseCell(pPage, pCell, pInfo);
- if( pInfo->nLocal==pInfo->nPayload ){
- return SQLITE_OK; /* No overflow pages. Return without doing anything */
- }
+ assert( pInfo->nLocal!=pInfo->nPayload );
testcase( pCell + pInfo->nSize == pPage->aDataEnd );
testcase( pCell + (pInfo->nSize-1) == pPage->aDataEnd );
if( pCell + pInfo->nSize > pPage->aDataEnd ){
@@ -68937,15 +71898,15 @@ static int clearCell(
assert( pBt->usableSize > 4 );
ovflPageSize = pBt->usableSize - 4;
nOvfl = (pInfo->nPayload - pInfo->nLocal + ovflPageSize - 1)/ovflPageSize;
- assert( nOvfl>0 ||
+ assert( nOvfl>0 ||
(CORRUPT_DB && (pInfo->nPayload + ovflPageSize)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
+ /* 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;
}
@@ -68957,11 +71918,11 @@ static int clearCell(
if( ( pOvfl || ((pOvfl = btreePageLookup(pBt, ovflPgno))!=0) )
&& sqlite3PagerPageRefcount(pOvfl->pDbPage)!=1
){
- /* There is no reason any cursor should have an outstanding reference
+ /* 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
+ ** 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
@@ -68981,6 +71942,21 @@ static int clearCell(
return SQLITE_OK;
}
+/* Call xParseCell to compute the size of a cell. If the cell contains
+** overflow, then invoke cellClearOverflow to clear out that overflow.
+** STore the result code (SQLITE_OK or some error code) in rc.
+**
+** Implemented as macro to force inlining for performance.
+*/
+#define BTREE_CLEAR_CELL(rc, pPage, pCell, sInfo) \
+ pPage->xParseCell(pPage, pCell, &sInfo); \
+ if( sInfo.nLocal!=sInfo.nPayload ){ \
+ rc = clearCellOverflow(pPage, pCell, &sInfo); \
+ }else{ \
+ rc = SQLITE_OK; \
+ }
+
+
/*
** Create the byte sequence used to represent a cell on page pPage
** and write that byte sequence into pCell[]. Overflow pages are
@@ -69032,7 +72008,7 @@ static int fillInCell(
pSrc = pX->pKey;
nHeader += putVarint32(&pCell[nHeader], nPayload);
}
-
+
/* Fill in the payload */
pPayload = &pCell[nHeader];
if( nPayload<=pPage->maxLocal ){
@@ -69123,8 +72099,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
@@ -69132,9 +72108,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 uninitialized values and delete the
@@ -69195,6 +72171,7 @@ static void dropCell(MemPage *pPage, int idx, int sz, int *pRC){
assert( CORRUPT_DB || sz==cellSize(pPage, idx) );
assert( sqlite3PagerIswriteable(pPage->pDbPage) );
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
+ assert( pPage->nFree>=0 );
data = pPage->aData;
ptr = &pPage->aCellIdx[2*idx];
pc = get2byte(ptr);
@@ -69232,8 +72209,8 @@ 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->apOvfl[] 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.
**
** *pRC must be SQLITE_OK when this routine is called.
@@ -69259,12 +72236,8 @@ static void insertCell(
assert( pPage->nOverflow<=ArraySize(pPage->apOvfl) );
assert( ArraySize(pPage->apOvfl)==ArraySize(pPage->aiOvfl) );
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
- /* The cell should normally be sized correctly. However, when moving a
- ** malformed cell from a leaf page to an interior page, if the cell size
- ** wanted to be less than 4 but got rounded up to 4 on the leaf, then size
- ** might be less than 8 (leaf-size + pointer) on the interior node. Hence
- ** the term after the || in the following assert(). */
- assert( sz==pPage->xCellSize(pPage, pCell) || (sz==8 && iChild>0) );
+ assert( sz==pPage->xCellSize(pPage, pCell) || CORRUPT_DB );
+ assert( pPage->nFree>=0 );
if( pPage->nOverflow || sz+2>pPage->nFree ){
if( pTemp ){
memcpy(pTemp, pCell, sz);
@@ -69305,9 +72278,16 @@ static void insertCell(
assert( idx >= pPage->cellOffset+2*pPage->nCell+2 || CORRUPT_DB );
assert( idx+sz <= (int)pPage->pBt->usableSize );
pPage->nFree -= (u16)(2 + sz);
- memcpy(&data[idx], pCell, sz);
if( iChild ){
+ /* In a corrupt database where an entry in the cell index section of
+ ** a btree page has a value of 3 or less, the pCell value might point
+ ** as many as 4 bytes in front of the start of the aData buffer for
+ ** the source page. Make sure this does not cause problems by not
+ ** reading the first 4 bytes */
+ memcpy(&data[idx+4], pCell+4, sz-4);
put4byte(&data[idx], iChild);
+ }else{
+ memcpy(&data[idx], pCell, sz);
}
pIns = pPage->aCellIdx + i*2;
memmove(pIns+2, pIns, 2*(pPage->nCell - i));
@@ -69315,21 +72295,100 @@ static void insertCell(
pPage->nCell++;
/* increment the cell count */
if( (++data[pPage->hdrOffset+4])==0 ) data[pPage->hdrOffset+3]++;
- assert( get2byte(&data[pPage->hdrOffset+3])==pPage->nCell );
+ assert( get2byte(&data[pPage->hdrOffset+3])==pPage->nCell || CORRUPT_DB );
#ifndef SQLITE_OMIT_AUTOVACUUM
if( pPage->pBt->autoVacuum ){
/* The cell may contain a pointer to an overflow page. If so, write
** the entry for the overflow page into the pointer map.
*/
- ptrmapPutOvflPtr(pPage, pCell, pRC);
+ ptrmapPutOvflPtr(pPage, pPage, pCell, pRC);
}
#endif
}
}
+/*
+** The following parameters determine how many adjacent pages get involved
+** in a balancing operation. NN is the number of neighbors on either side
+** of the page that participate in the balancing operation. NB is the
+** total number of pages that participate, including the target page and
+** NN neighbors on either side.
+**
+** The minimum value of NN is 1 (of course). Increasing NN above 1
+** (to 2 or 3) gives a modest improvement in SELECT and DELETE performance
+** in exchange for a larger degradation in INSERT and UPDATE performance.
+** The value of NN appears to give the best results overall.
+**
+** (Later:) The description above makes it seem as if these values are
+** tunable - as if you could change them and recompile and it would all work.
+** But that is unlikely. NB has been 3 since the inception of SQLite and
+** we have never tested any other value.
+*/
+#define NN 1 /* Number of neighbors on either side of pPage */
+#define NB 3 /* (NN*2+1): Total pages involved in the balance */
+
/*
** A CellArray object contains a cache of pointers and sizes for a
** consecutive sequence of cells that might be held on multiple pages.
+**
+** The cells in this array are the divider cell or cells from the pParent
+** page plus up to three child pages. There are a total of nCell cells.
+**
+** pRef is a pointer to one of the pages that contributes cells. This is
+** used to access information such as MemPage.intKey and MemPage.pBt->pageSize
+** which should be common to all pages that contribute cells to this array.
+**
+** apCell[] and szCell[] hold, respectively, pointers to the start of each
+** cell and the size of each cell. Some of the apCell[] pointers might refer
+** to overflow cells. In other words, some apCel[] pointers might not point
+** to content area of the pages.
+**
+** A szCell[] of zero means the size of that cell has not yet been computed.
+**
+** The cells come from as many as four different pages:
+**
+** -----------
+** | Parent |
+** -----------
+** / | \
+** / | \
+** --------- --------- ---------
+** |Child-1| |Child-2| |Child-3|
+** --------- --------- ---------
+**
+** The order of cells is in the array is for an index btree is:
+**
+** 1. All cells from Child-1 in order
+** 2. The first divider cell from Parent
+** 3. All cells from Child-2 in order
+** 4. The second divider cell from Parent
+** 5. All cells from Child-3 in order
+**
+** For a table-btree (with rowids) the items 2 and 4 are empty because
+** content exists only in leaves and there are no divider cells.
+**
+** For an index btree, the apEnd[] array holds pointer to the end of page
+** for Child-1, the Parent, Child-2, the Parent (again), and Child-3,
+** respectively. The ixNx[] array holds the number of cells contained in
+** each of these 5 stages, and all stages to the left. Hence:
+**
+** ixNx[0] = Number of cells in Child-1.
+** ixNx[1] = Number of cells in Child-1 plus 1 for first divider.
+** ixNx[2] = Number of cells in Child-1 and Child-2 + 1 for 1st divider.
+** ixNx[3] = Number of cells in Child-1 and Child-2 + both divider cells
+** ixNx[4] = Total number of cells.
+**
+** For a table-btree, the concept is similar, except only apEnd[0]..apEnd[2]
+** are used and they point to the leaf pages only, and the ixNx value are:
+**
+** ixNx[0] = Number of cells in Child-1.
+** ixNx[1] = Number of cells in Child-1 and Child-2.
+** ixNx[2] = Total number of cells.
+**
+** Sometimes when deleting, a child page can have zero cells. In those
+** cases, ixNx[] entries with higher indexes, and the corresponding apEnd[]
+** entries, shift down. The end result is that each ixNx[] entry should
+** be larger than the previous
*/
typedef struct CellArray CellArray;
struct CellArray {
@@ -69337,6 +72396,8 @@ struct CellArray {
MemPage *pRef; /* Reference page */
u8 **apCell; /* All cells begin balanced */
u16 *szCell; /* Local size of all cells in apCell[] */
+ u8 *apEnd[NB*2]; /* MemPage.aDataEnd values */
+ int ixNx[NB*2]; /* Index of at which we move to the next apEnd[] */
};
/*
@@ -69374,49 +72435,71 @@ static u16 cachedCellSize(CellArray *p, int N){
}
/*
-** Array apCell[] contains pointers to nCell b-tree page cells. The
+** Array apCell[] contains pointers to nCell b-tree page cells. The
** szCell[] array contains the size in bytes of each cell. This function
** replaces the current contents of page pPg with the contents of the cell
** array.
**
** Some of the cells in apCell[] may currently be stored in pPg. This
-** function works around problems caused by this by making a copy of any
+** function works around problems caused by this by making a copy of any
** such cells before overwriting the page data.
**
-** The MemPage.nFree field is invalidated by this function. It is the
+** The MemPage.nFree field is invalidated by this function. It is the
** responsibility of the caller to set it correctly.
*/
static int rebuildPage(
- MemPage *pPg, /* Edit this page */
+ CellArray *pCArray, /* Content to be added to page pPg */
+ int iFirst, /* First cell in pCArray to use */
int nCell, /* Final number of cells on page */
- u8 **apCell, /* Array of cells */
- u16 *szCell /* Array of cell sizes */
+ MemPage *pPg /* The page to be reconstructed */
){
const int hdr = pPg->hdrOffset; /* Offset of header on pPg */
u8 * const aData = pPg->aData; /* Pointer to data for pPg */
const int usableSize = pPg->pBt->usableSize;
u8 * const pEnd = &aData[usableSize];
- int i;
+ int i = iFirst; /* Which cell to copy from pCArray*/
+ u32 j; /* Start of cell content area */
+ int iEnd = i+nCell; /* Loop terminator */
u8 *pCellptr = pPg->aCellIdx;
u8 *pTmp = sqlite3PagerTempSpace(pPg->pBt->pPager);
u8 *pData;
+ int k; /* Current slot in pCArray->apEnd[] */
+ u8 *pSrcEnd; /* Current pCArray->apEnd[k] value */
- i = get2byte(&aData[hdr+5]);
- memcpy(&pTmp[i], &aData[i], usableSize - i);
+ assert( i(u32)usableSize) ){ j = 0; }
+ memcpy(&pTmp[j], &aData[j], usableSize - j);
+
+ for(k=0; pCArray->ixNx[k]<=i && ALWAYS(kapEnd[k];
pData = pEnd;
- for(i=0; iapCell[i];
+ u16 sz = pCArray->szCell[i];
+ assert( sz>0 );
+ if( SQLITE_WITHIN(pCell,aData+j,pEnd) ){
+ if( ((uptr)(pCell+sz))>(uptr)pEnd ) return SQLITE_CORRUPT_BKPT;
pCell = &pTmp[pCell - aData];
+ }else if( (uptr)(pCell+sz)>(uptr)pSrcEnd
+ && (uptr)(pCell)<(uptr)pSrcEnd
+ ){
+ return SQLITE_CORRUPT_BKPT;
}
- pData -= szCell[i];
+
+ pData -= sz;
put2byte(pCellptr, (pData - aData));
pCellptr += 2;
if( pData < pCellptr ) return SQLITE_CORRUPT_BKPT;
- memcpy(pData, pCell, szCell[i]);
- assert( szCell[i]==pPg->xCellSize(pPg, pCell) || CORRUPT_DB );
- testcase( szCell[i]!=pPg->xCellSize(pPg,pCell) );
+ memmove(pData, pCell, sz);
+ assert( sz==pPg->xCellSize(pPg, pCell) || CORRUPT_DB );
+ i++;
+ if( i>=iEnd ) break;
+ if( pCArray->ixNx[k]<=i ){
+ k++;
+ pSrcEnd = pCArray->apEnd[k];
+ }
}
/* The pPg->nFree field is now set incorrectly. The caller will fix it. */
@@ -69431,12 +72514,11 @@ static int rebuildPage(
}
/*
-** Array apCell[] contains nCell pointers to b-tree cells. Array szCell
-** contains the size in bytes of each such cell. This function attempts to
-** add the cells stored in the array to page pPg. If it cannot (because
-** the page needs to be defragmented before the cells will fit), non-zero
-** is returned. Otherwise, if the cells are added successfully, zero is
-** returned.
+** The pCArray objects contains pointers to b-tree cells and the cell sizes.
+** This function attempts to add the cells stored in the array to page pPg.
+** If it cannot (because the page needs to be defragmented before the cells
+** will fit), non-zero is returned. Otherwise, if the cells are added
+** successfully, zero is returned.
**
** Argument pCellptr points to the first entry in the cell-pointer array
** (part of page pPg) to populate. After cell apCell[0] is written to the
@@ -69444,7 +72526,7 @@ static int rebuildPage(
** cell in the array. It is the responsibility of the caller to ensure
** that it is safe to overwrite this part of the cell-pointer array.
**
-** When this function is called, *ppData points to the start of the
+** When this function is called, *ppData points to the start of the
** content area on page pPg. If the size of the content area is extended,
** *ppData is updated to point to the new start of the content area
** before returning.
@@ -69458,21 +72540,27 @@ static int rebuildPage(
static int pageInsertArray(
MemPage *pPg, /* Page to add cells to */
u8 *pBegin, /* End of cell-pointer array */
- u8 **ppData, /* IN/OUT: Page content -area pointer */
+ u8 **ppData, /* IN/OUT: Page content-area pointer */
u8 *pCellptr, /* Pointer to cell-pointer area */
int iFirst, /* Index of first cell to add */
int nCell, /* Number of cells to add to pPg */
CellArray *pCArray /* Array of cells */
){
- int i;
- u8 *aData = pPg->aData;
- u8 *pData = *ppData;
- int iEnd = iFirst + nCell;
+ int i = iFirst; /* Loop counter - cell index to insert */
+ u8 *aData = pPg->aData; /* Complete page */
+ u8 *pData = *ppData; /* Content area. A subset of aData[] */
+ int iEnd = iFirst + nCell; /* End of loop. One past last cell to ins */
+ int k; /* Current slot in pCArray->apEnd[] */
+ u8 *pEnd; /* Maximum extent of cell data */
assert( CORRUPT_DB || pPg->hdrOffset==0 ); /* Never called on page 1 */
- for(i=iFirst; iixNx[k]<=i && ALWAYS(kapEnd[k];
+ while( 1 /*Exit by break*/ ){
int sz, rc;
u8 *pSlot;
- sz = cachedCellSize(pCArray, i);
+ assert( pCArray->szCell[i]!=0 );
+ sz = pCArray->szCell[i];
if( (aData[1]==0 && aData[2]==0) || (pSlot = pageFindSlot(pPg,sz,&rc))==0 ){
if( (pData - pBegin)apCell[i]
|| pSlot>=(pCArray->apCell[i]+sz)
|| CORRUPT_DB );
+ if( (uptr)(pCArray->apCell[i]+sz)>(uptr)pEnd
+ && (uptr)(pCArray->apCell[i])<(uptr)pEnd
+ ){
+ assert( CORRUPT_DB );
+ (void)SQLITE_CORRUPT_BKPT;
+ return 1;
+ }
memmove(pSlot, pCArray->apCell[i], sz);
put2byte(pCellptr, (pSlot - aData));
pCellptr += 2;
+ i++;
+ if( i>=iEnd ) break;
+ if( pCArray->ixNx[k]<=i ){
+ k++;
+ pEnd = pCArray->apEnd[k];
+ }
}
*ppData = pData;
return 0;
}
/*
-** Array apCell[] contains nCell pointers to b-tree cells. Array szCell
-** contains the size in bytes of each such cell. This function adds the
-** space associated with each cell in the array that is currently stored
-** within the body of pPg to the pPg free-list. The cell-pointers and other
-** fields of the page are not updated.
+** The pCArray object contains pointers to b-tree cells and their sizes.
+**
+** This function adds the space associated with each cell in the array
+** that is currently stored within the body of pPg to the pPg free-list.
+** The cell-pointers and other fields of the page are not updated.
**
** This function returns the total number of cells added to the free-list.
*/
@@ -69531,7 +72632,9 @@ static int pageFreeArray(
}
pFree = pCell;
szFree = sz;
- if( pFree+sz>pEnd ) return 0;
+ if( pFree+sz>pEnd ){
+ return 0;
+ }
}else{
pFree = pCell;
szFree += sz;
@@ -69547,9 +72650,9 @@ static int pageFreeArray(
}
/*
-** apCell[] and szCell[] contains pointers to and sizes of all cells in the
-** pages being balanced. The current page, pPg, has pPg->nCell cells starting
-** with apCell[iOld]. After balancing, this page should hold nNew cells
+** pCArray contains pointers to and sizes of all cells in the page being
+** balanced. The current page, pPg, has pPg->nCell cells starting with
+** pCArray->apCell[iOld]. After balancing, this page should hold nNew cells
** starting at apCell[iNew].
**
** This routine makes the necessary adjustments to pPg so that it contains
@@ -69581,13 +72684,17 @@ static int editPage(
#endif
/* Remove cells from the start and end of the page */
+ assert( nCell>=0 );
if( iOldnCell) ) return SQLITE_CORRUPT_BKPT;
memmove(pPg->aCellIdx, &pPg->aCellIdx[nShift*2], nCell*2);
nCell -= nShift;
}
if( iNewEnd < iOldEnd ){
- nCell -= pageFreeArray(pPg, iNewEnd, iOldEnd - iNewEnd, pCArray);
+ int nTail = pageFreeArray(pPg, iNewEnd, iOldEnd - iNewEnd, pCArray);
+ assert( nCell>=nTail );
+ nCell -= nTail;
}
pData = &aData[get2byteNotZero(&aData[hdr+5])];
@@ -69597,6 +72704,7 @@ static int editPage(
if( iNew=0 );
pCellptr = pPg->aCellIdx;
memmove(&pCellptr[nAdd*2], pCellptr, nCell*2);
if( pageInsertArray(
@@ -69611,8 +72719,11 @@ static int editPage(
int iCell = (iOld + pPg->aiOvfl[i]) - iNew;
if( iCell>=0 && iCellaCellIdx[iCell * 2];
- memmove(&pCellptr[2], pCellptr, (nCell - iCell) * 2);
+ if( nCell>iCell ){
+ memmove(&pCellptr[2], pCellptr, (nCell - iCell) * 2);
+ }
nCell++;
+ cachedCellSize(pCArray, iCell+iNew);
if( pageInsertArray(
pPg, pBegin, &pData, pCellptr,
iCell+iNew, 1, pCArray
@@ -69621,6 +72732,7 @@ static int editPage(
}
/* Append cells to the end of the page */
+ assert( nCell>=0 );
pCellptr = &pPg->aCellIdx[nCell*2];
if( pageInsertArray(
pPg, pBegin, &pData, pCellptr,
@@ -69649,24 +72761,9 @@ static int editPage(
editpage_fail:
/* Unable to edit this page. Rebuild it from scratch instead. */
populateCellCache(pCArray, iNew, nNew);
- return rebuildPage(pPg, nNew, &pCArray->apCell[iNew], &pCArray->szCell[iNew]);
+ return rebuildPage(pCArray, iNew, nNew, pPg);
}
-/*
-** The following parameters determine how many adjacent pages get involved
-** in a balancing operation. NN is the number of neighbors on either side
-** of the page that participate in the balancing operation. NB is the
-** total number of pages that participate, including the target page and
-** NN neighbors on either side.
-**
-** The minimum value of NN is 1 (of course). Increasing NN above 1
-** (to 2 or 3) gives a modest improvement in SELECT and DELETE performance
-** in exchange for a larger degradation in INSERT and UPDATE performance.
-** The value of NN appears to give the best results overall.
-*/
-#define NN 1 /* Number of neighbors on either side of pPage */
-#define NB (NN*2+1) /* Total pages involved in the balance */
-
#ifndef SQLITE_OMIT_QUICKBALANCE
/*
@@ -69702,10 +72799,11 @@ static int balance_quick(MemPage *pParent, MemPage *pPage, u8 *pSpace){
assert( sqlite3PagerIswriteable(pParent->pDbPage) );
assert( pPage->nOverflow==1 );
- /* This error condition is now caught prior to reaching this function */
- if( NEVER(pPage->nCell==0) ) return SQLITE_CORRUPT_BKPT;
+ if( pPage->nCell==0 ) return SQLITE_CORRUPT_BKPT; /* dbfuzz001.test */
+ assert( pPage->nFree>=0 );
+ assert( pParent->nFree>=0 );
- /* 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.
*/
@@ -69717,16 +72815,26 @@ static int balance_quick(MemPage *pParent, MemPage *pPage, u8 *pSpace){
u8 *pCell = pPage->apOvfl[0];
u16 szCell = pPage->xCellSize(pPage, pCell);
u8 *pStop;
+ CellArray b;
assert( sqlite3PagerIswriteable(pNew->pDbPage) );
- assert( pPage->aData[0]==(PTF_INTKEY|PTF_LEAFDATA|PTF_LEAF) );
+ assert( CORRUPT_DB || pPage->aData[0]==(PTF_INTKEY|PTF_LEAFDATA|PTF_LEAF) );
zeroPage(pNew, PTF_INTKEY|PTF_LEAFDATA|PTF_LEAF);
- rc = rebuildPage(pNew, 1, &pCell, &szCell);
- if( NEVER(rc) ) return rc;
+ b.nCell = 1;
+ b.pRef = pPage;
+ b.apCell = &pCell;
+ b.szCell = &szCell;
+ b.apEnd[0] = pPage->aDataEnd;
+ b.ixNx[0] = 2;
+ rc = rebuildPage(&b, 0, 1, pNew);
+ if( NEVER(rc) ){
+ releasePage(pNew);
+ return rc;
+ }
pNew->nFree = pBt->usableSize - pNew->cellOffset - 2 - 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.
@@ -69737,17 +72845,17 @@ static int balance_quick(MemPage *pParent, MemPage *pPage, u8 *pSpace){
if( ISAUTOVACUUM ){
ptrmapPut(pBt, pgnoNew, PTRMAP_BTREE, pParent->pgno, &rc);
if( szCell>pNew->minLocal ){
- ptrmapPutOvflPtr(pNew, pCell, &rc);
+ ptrmapPutOvflPtr(pNew, 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
@@ -69768,7 +72876,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);
}
@@ -69780,7 +72888,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){
@@ -69795,7 +72903,7 @@ static int ptrmapCheckPages(MemPage **apPage, int nPage){
for(j=0; jnCell; j++){
CellInfo info;
u8 *z;
-
+
z = findCell(pPage, j);
pPage->xParseCell(pPage, z, &info);
if( info.nLocalpgno==1) ? 100 : 0);
int rc;
int iData;
-
-
+
+
assert( pFrom->isInit );
assert( pFrom->nFree>=iToHdr );
assert( get2byte(&aFrom[iFromHdr+5]) <= (int)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;
rc = btreeInitPage(pTo);
+ if( rc==SQLITE_OK ) rc = btreeComputeFreeSpace(pTo);
if( rc!=SQLITE_OK ){
*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.
*/
@@ -69882,13 +72991,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
@@ -69899,7 +73008,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
@@ -69914,7 +73023,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(
@@ -69960,12 +73069,8 @@ static int balance_nonroot(
assert( sqlite3_mutex_held(pBt->mutex) );
assert( sqlite3PagerIswriteable(pParent->pDbPage) );
-#if 0
- TRACE(("BALANCE: begin page %d child of %d\n", pPage->pgno, pParent->pgno));
-#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().
*/
@@ -69975,12 +73080,13 @@ static int balance_nonroot(
if( !aOvflSpace ){
return SQLITE_NOMEM_BKPT;
}
+ assert( pParent->nFree>=0 );
- /* 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
@@ -69992,7 +73098,7 @@ static int balance_nonroot(
nxDiv = 0;
}else{
assert( bBulk==0 || bBulk==1 );
- if( iParentIdx==0 ){
+ if( iParentIdx==0 ){
nxDiv = 0;
}else if( iParentIdx==i ){
nxDiv = i-2+bBulk;
@@ -70009,12 +73115,20 @@ static int balance_nonroot(
}
pgno = get4byte(pRight);
while( 1 ){
- rc = getAndInitPage(pBt, pgno, &apOld[i], 0, 0);
+ if( rc==SQLITE_OK ){
+ rc = getAndInitPage(pBt, pgno, &apOld[i], 0, 0);
+ }
if( rc ){
memset(apOld, 0, (i+1)*sizeof(MemPage*));
goto balance_cleanup;
}
- nMaxCells += 1+apOld[i]->nCell+apOld[i]->nOverflow;
+ if( apOld[i]->nFree<0 ){
+ rc = btreeComputeFreeSpace(apOld[i]);
+ if( rc ){
+ memset(apOld, 0, (i)*sizeof(MemPage*));
+ goto balance_cleanup;
+ }
+ }
if( (i--)==0 ) break;
if( pParent->nOverflow && i+nxDiv==pParent->aiOvfl[0] ){
@@ -70032,7 +73146,7 @@ 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.
**
** But not if we are in secure-delete mode. In secure-delete mode,
** the dropCell() routine will overwrite the entire cell with zeroes.
@@ -70042,12 +73156,10 @@ static int balance_nonroot(
if( pBt->btsFlags & BTS_FAST_SECURE ){
int iOff;
+ /* If the following if() condition is not true, the db is corrupted.
+ ** The call to dropCell() below will detect this. */
iOff = SQLITE_PTR_TO_INT(apDiv[i]) - SQLITE_PTR_TO_INT(pParent->aData);
- if( (iOff+szNew[i])>(int)pBt->usableSize ){
- rc = SQLITE_CORRUPT_BKPT;
- memset(apOld, 0, (i+1)*sizeof(MemPage*));
- goto balance_cleanup;
- }else{
+ if( (iOff+szNew[i])<=(int)pBt->usableSize ){
memcpy(&aOvflSpace[iOff], apDiv[i], szNew[i]);
apDiv[i] = &aOvflSpace[apDiv[i]-pParent->aData];
}
@@ -70058,6 +73170,7 @@ static int balance_nonroot(
/* Make nMaxCells a multiple of 4 in order to preserve 8-byte
** alignment */
+ nMaxCells = nOld*(MX_CELL(pBt) + ArraySize(pParent->apOvfl));
nMaxCells = (nMaxCells + 3)&~3;
/*
@@ -70068,7 +73181,7 @@ static int balance_nonroot(
+ nMaxCells*sizeof(u16) /* b.szCell */
+ pBt->pageSize; /* aSpace1 */
- assert( szScratch<=6*(int)pBt->pageSize );
+ assert( szScratch<=7*(int)pBt->pageSize );
b.apCell = sqlite3StackAllocRaw(0, szScratch );
if( b.apCell==0 ){
rc = SQLITE_NOMEM_BKPT;
@@ -70104,6 +73217,7 @@ static int balance_nonroot(
u16 maskPage = pOld->maskPage;
u8 *piCell = aData + pOld->cellOffset;
u8 *piEnd;
+ VVA_ONLY( int nCellAtStart = b.nCell; )
/* Verify that all sibling pages are of the same "type" (table-leaf,
** table-interior, index-leaf, or index-interior).
@@ -70132,6 +73246,10 @@ static int balance_nonroot(
*/
memset(&b.szCell[b.nCell], 0, sizeof(b.szCell[0])*(limit+pOld->nOverflow));
if( pOld->nOverflow>0 ){
+ if( NEVER(limitaiOvfl[0]) ){
+ rc = SQLITE_CORRUPT_BKPT;
+ goto balance_cleanup;
+ }
limit = pOld->aiOvfl[0];
for(j=0; jnCell+pOld->nOverflow) );
cntOld[i] = b.nCell;
if( ileaf ){
assert( leafCorrection==0 );
- assert( pOld->hdrOffset==0 );
+ assert( pOld->hdrOffset==0 || CORRUPT_DB );
/* The right pointer of the child page pOld becomes the left
** pointer of the divider cell */
memcpy(b.apCell[b.nCell], &pOld->aData[8], 4);
@@ -70191,7 +73310,7 @@ static int balance_nonroot(
** Figure out the number of pages needed to hold all b.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 b.apCell[] of the cell that divides page i from page i+1.
+ ** in b.apCell[] of the cell that divides page i from page i+1.
** cntNew[k] should equal b.nCell.
**
** Values computed by this block:
@@ -70201,11 +73320,22 @@ static int balance_nonroot(
** cntNew[i]: Index in b.apCell[] and b.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(i=0; iaDataEnd;
+ b.ixNx[k] = cntOld[i];
+ if( k && b.ixNx[k]==b.ixNx[k-1] ){
+ k--; /* Omit b.ixNx[] entry for child pages with no cells */
+ }
+ if( !leafData ){
+ k++;
+ b.apEnd[k] = pParent->aDataEnd;
+ b.ixNx[k] = cntOld[i]+1;
+ }
+ assert( p->nFree>=0 );
szNew[i] = usableSpace - p->nFree;
for(j=0; jnOverflow; j++){
szNew[i] += 2 + p->xCellSize(p, p->apOvfl[j]);
@@ -70323,6 +73453,9 @@ static int balance_nonroot(
apOld[i] = 0;
rc = sqlite3PagerWrite(pNew->pDbPage);
nNew++;
+ if( sqlite3PagerPageRefcount(pNew->pDbPage)!=1+(i==(iParentIdx-nxDiv)) ){
+ rc = SQLITE_CORRUPT_BKPT;
+ }
if( rc ) goto balance_cleanup;
}else{
assert( i>0 );
@@ -70344,24 +73477,24 @@ static int balance_nonroot(
}
/*
- ** Reassign page numbers so that the new pages are in ascending order.
+ ** Reassign page numbers so that the new pages are in ascending order.
** This helps to keep entries in the disk file in order so that a scan
- ** of the table is closer to a linear scan through the file. That in turn
+ ** of the table is closer to a linear scan through the file. That in turn
** helps the operating system to deliver pages from the disk more rapidly.
**
- ** An O(n^2) insertion sort algorithm is used, but since n is never more
+ ** An O(n^2) insertion sort algorithm is used, but since n is never more
** than (NB+2) (a small constant), that should not be a problem.
**
- ** When NB==3, this one optimization makes the database about 25% faster
+ ** When NB==3, this one optimization makes the database about 25% faster
** for large insertions and deletions.
*/
for(i=0; ipgno;
aPgFlags[i] = apNew[i]->pDbPage->flags;
for(j=0; jpDbPage) );
+ assert( nNew>=1 && nNew<=ArraySize(apNew) );
+ assert( apNew[nNew-1]!=0 );
put4byte(pRight, apNew[nNew-1]->pgno);
/* If the sibling pages are not leaves, ensure that the right-child pointer
- ** of the right-most new sibling page is set to the value that was
+ ** of the right-most new sibling page is set to the value that was
** originally in the same field of the right-most old sibling page. */
if( (pageFlags & PTF_LEAF)==0 && nOld!=nNew ){
MemPage *pOld = (nNew>nOld ? apNew : apOld)[nOld-1];
memcpy(&apNew[nNew-1]->aData[8], &pOld->aData[8], 4);
}
- /* Make any required updates to pointer map entries associated with
+ /* Make any required updates to pointer map entries associated with
** cells stored on sibling pages following the balance operation. Pointer
** map entries associated with divider cells are set by the insertCell()
** routine. The associated pointer map entries are:
@@ -70423,25 +73558,26 @@ static int balance_nonroot(
** b) if the sibling pages are not leaves, the child page associated
** with the cell.
**
- ** If the sibling pages are not leaves, then the pointer map entry
- ** associated with the right-child of each sibling may also need to be
- ** updated. This happens below, after the sibling pages have been
+ ** If the sibling pages are not leaves, then the pointer map entry
+ ** associated with the right-child of each sibling may also need to be
+ ** updated. This happens below, after the sibling pages have been
** populated, not here.
*/
if( ISAUTOVACUUM ){
- MemPage *pNew = apNew[0];
- u8 *aOld = pNew->aData;
+ MemPage *pOld;
+ MemPage *pNew = pOld = apNew[0];
int cntOldNext = pNew->nCell + pNew->nOverflow;
- int usableSize = pBt->usableSize;
int iNew = 0;
int iOld = 0;
for(i=0; i=0 && iOldnCell + pOld->nOverflow + !leafData;
- aOld = pOld->aData;
}
if( i==cntNew[iNew] ){
pNew = apNew[++iNew];
@@ -70449,20 +73585,20 @@ static int balance_nonroot(
}
/* Cell pCell is destined for new sibling page pNew. Originally, it
- ** was either part of sibling page iOld (possibly an overflow cell),
+ ** was either part of sibling page iOld (possibly an overflow cell),
** or else the divider cell to the left of sibling page iOld. So,
** if sibling page iOld had the same page number as pNew, and if
** pCell really was a part of sibling page iOld (not a divider or
** overflow cell), we can skip updating the pointer map entries. */
if( iOld>=nNew
|| pNew->pgno!=aPgno[iOld]
- || !SQLITE_WITHIN(pCell,aOld,&aOld[usableSize])
+ || !SQLITE_WITHIN(pCell,pOld->aData,pOld->aDataEnd)
){
if( !leafCorrection ){
ptrmapPut(pBt, get4byte(pCell), PTRMAP_BTREE, pNew->pgno, &rc);
}
if( cachedCellSize(&b,i)>pNew->minLocal ){
- ptrmapPutOvflPtr(pNew, pCell, &rc);
+ ptrmapPutOvflPtr(pNew, pOld, pCell, &rc);
}
if( rc ) goto balance_cleanup;
}
@@ -70474,6 +73610,7 @@ static int balance_nonroot(
u8 *pCell;
u8 *pTemp;
int sz;
+ u8 *pSrcEnd;
MemPage *pNew = apNew[i];
j = cntNew[i];
@@ -70485,9 +73622,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 b.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 b.apCell[]. Instead, the divider
+ ** cell consists of the integer key for the right-most cell of
** the sibling-page assembled above only.
*/
CellInfo info;
@@ -70500,9 +73637,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.
**
** This can only happen for b-trees used to evaluate "IN (SELECT ...)"
@@ -70517,6 +73654,12 @@ static int balance_nonroot(
iOvflSpace += sz;
assert( sz<=pBt->maxLocal+23 );
assert( iOvflSpace <= (int)pBt->pageSize );
+ for(k=0; b.ixNx[k]<=i && ALWAYS(kpgno, &rc);
if( rc!=SQLITE_OK ) goto balance_cleanup;
assert( sqlite3PagerIswriteable(pParent->pDbPage) );
@@ -70594,8 +73737,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.
**
** It is critical that the child page be defragmented before being
@@ -70606,8 +73749,9 @@ static int balance_nonroot(
assert( nNew==1 || CORRUPT_DB );
rc = defragmentPage(apNew[0], -1);
testcase( rc!=SQLITE_OK );
- assert( apNew[0]->nFree ==
- (get2byte(&apNew[0]->aData[5])-apNew[0]->cellOffset-apNew[0]->nCell*2)
+ assert( apNew[0]->nFree ==
+ (get2byteNotZero(&apNew[0]->aData[5]) - apNew[0]->cellOffset
+ - apNew[0]->nCell*2)
|| rc!=SQLITE_OK
);
copyNodeContent(apNew[0], pParent, &rc);
@@ -70635,7 +73779,7 @@ static int balance_nonroot(
#if 0
if( ISAUTOVACUUM && rc==SQLITE_OK && apNew[0]->isInit ){
/* 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);
@@ -70665,15 +73809,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.
@@ -70687,7 +73831,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.
*/
@@ -70706,7 +73850,7 @@ static int balance_deeper(MemPage *pRoot, MemPage **ppChild){
}
assert( sqlite3PagerIswriteable(pChild->pDbPage) );
assert( sqlite3PagerIswriteable(pRoot->pDbPage) );
- assert( pChild->nCell==pRoot->nCell );
+ assert( pChild->nCell==pRoot->nCell || CORRUPT_DB );
TRACE(("BALANCE: copy root %d into %d\n", pRoot->pgno, pChild->pgno));
@@ -70725,10 +73869,34 @@ static int balance_deeper(MemPage *pRoot, MemPage **ppChild){
return SQLITE_OK;
}
+/*
+** Return SQLITE_CORRUPT if any cursor other than pCur is currently valid
+** on the same B-tree as pCur.
+**
+** This can if a database is corrupt with two or more SQL tables
+** pointing to the same b-tree. If an insert occurs on one SQL table
+** and causes a BEFORE TRIGGER to do a secondary insert on the other SQL
+** table linked to the same b-tree. If the secondary insert causes a
+** rebalance, that can change content out from under the cursor on the
+** first SQL table, violating invariants on the first insert.
+*/
+static int anotherValidCursor(BtCursor *pCur){
+ BtCursor *pOther;
+ for(pOther=pCur->pBt->pCursor; pOther; pOther=pOther->pNext){
+ if( pOther!=pCur
+ && pOther->eState==CURSOR_VALID
+ && pOther->pPage==pCur->pPage
+ ){
+ return SQLITE_CORRUPT_BKPT;
+ }
+ }
+ return SQLITE_OK;
+}
+
/*
** 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()
@@ -70745,16 +73913,19 @@ static int balance(BtCursor *pCur){
VVA_ONLY( int balance_deeper_called = 0 );
do {
- int iPage = pCur->iPage;
+ int iPage;
MemPage *pPage = pCur->pPage;
- if( iPage==0 ){
- if( pPage->nOverflow ){
+ if( NEVER(pPage->nFree<0) && btreeComputeFreeSpace(pPage) ) break;
+ if( pPage->nOverflow==0 && pPage->nFree<=nMin ){
+ break;
+ }else if( (iPage = pCur->iPage)==0 ){
+ if( pPage->nOverflow && (rc = anotherValidCursor(pCur))==SQLITE_OK ){
/* The root page of the b-tree is overfull. In this case call the
** 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 );
VVA_ONLY( balance_deeper_called++ );
rc = balance_deeper(pPage, &pCur->apPage[1]);
@@ -70769,13 +73940,14 @@ static int balance(BtCursor *pCur){
}else{
break;
}
- }else if( pPage->nOverflow==0 && pPage->nFree<=nMin ){
- break;
}else{
MemPage * const pParent = pCur->apPage[iPage-1];
int const iIdx = pCur->aiIdx[iPage-1];
rc = sqlite3PagerWrite(pParent->pDbPage);
+ if( rc==SQLITE_OK && pParent->nFree<0 ){
+ rc = btreeComputeFreeSpace(pParent);
+ }
if( rc==SQLITE_OK ){
#ifndef SQLITE_OMIT_QUICKBALANCE
if( pPage->intKeyLeaf
@@ -70787,17 +73959,17 @@ 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 iteration of the do-loop will balance pParent
+ ** happens, the next iteration 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
** function. If this were not verified, a subtle bug involving reuse
** of the aBalanceQuickSpace[] might sneak in.
*/
- assert( balance_quick_called==0 );
+ assert( balance_quick_called==0 );
VVA_ONLY( balance_quick_called++ );
rc = balance_quick(pParent, pPage, aBalanceQuickSpace);
}else
@@ -70808,15 +73980,15 @@ 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().
*/
@@ -70824,9 +73996,9 @@ static int balance(BtCursor *pCur){
rc = balance_nonroot(pParent, iIdx, pSpace, iPage==1,
pCur->hints&BTREE_BULKLOAD);
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);
}
@@ -70886,7 +74058,11 @@ static int btreeOverwriteContent(
if( memcmp(pDest, ((u8*)pX->pData) + iOffset, iAmt)!=0 ){
int rc = sqlite3PagerWrite(pPage->pDbPage);
if( rc ) return rc;
- memcpy(pDest, ((u8*)pX->pData) + iOffset, iAmt);
+ /* In a corrupt database, it is possible for the source and destination
+ ** buffers to overlap. This is harmless since the database is already
+ ** corrupt but it does cause valgrind and ASAN warnings. So use
+ ** memmove(). */
+ memmove(pDest, ((u8*)pX->pData) + iOffset, iAmt);
}
}
return SQLITE_OK;
@@ -70905,7 +74081,9 @@ static int btreeOverwriteCell(BtCursor *pCur, const BtreePayload *pX){
Pgno ovflPgno; /* Next overflow page to write */
u32 ovflPageSize; /* Size to write on overflow page */
- if( pCur->info.pPayload + pCur->info.nLocal > pPage->aDataEnd ){
+ if( pCur->info.pPayload + pCur->info.nLocal > pPage->aDataEnd
+ || pCur->info.pPayload < pPage->aData + pPage->cellOffset
+ ){
return SQLITE_CORRUPT_BKPT;
}
/* Overwrite the local portion first */
@@ -70939,7 +74117,7 @@ static int btreeOverwriteCell(BtCursor *pCur, const BtreePayload *pX){
if( rc ) return rc;
iOffset += ovflPageSize;
}while( iOffsetpKeyInfo==0 );
if( pCur->eState==CURSOR_FAULT ){
assert( pCur->skipNext!=SQLITE_OK );
@@ -71007,14 +74186,14 @@ SQLITE_PRIVATE int sqlite3BtreeInsert(
** keys with no associated data. If the cursor was opened expecting an
** intkey table, the caller should be inserting integer keys with a
** blob of associated data. */
- assert( (pX->pKey==0)==(pCur->pKeyInfo==0) );
+ assert( (flags & BTREE_PREFORMAT) || (pX->pKey==0)==(pCur->pKeyInfo==0) );
/* Save the positions of any other cursors open on this table.
**
** 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
@@ -71023,22 +74202,31 @@ SQLITE_PRIVATE int sqlite3BtreeInsert(
if( pCur->curFlags & BTCF_Multiple ){
rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur);
if( rc ) return rc;
+ if( loc && pCur->iPage<0 ){
+ /* This can only happen if the schema is corrupt such that there is more
+ ** than one table or index with the same root page as used by the cursor.
+ ** Which can only happen if the SQLITE_NoSchemaError flag was set when
+ ** the schema was loaded. This cannot be asserted though, as a user might
+ ** set the flag, load the schema, and then unset the flag. */
+ return SQLITE_CORRUPT_BKPT;
+ }
}
if( pCur->pKeyInfo==0 ){
assert( pX->pKey==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 */
- invalidateIncrblobCursors(p, pCur->pgnoRoot, pX->nKey, 0);
+ if( p->hasIncrblobCur ){
+ invalidateIncrblobCursors(p, pCur->pgnoRoot, pX->nKey, 0);
+ }
- /* If BTREE_SAVEPOSITION is set, the cursor must already be pointing
+ /* If BTREE_SAVEPOSITION is set, the cursor must already be pointing
** to a row with the same key as the new entry being inserted.
*/
#ifdef SQLITE_DEBUG
if( flags & BTREE_SAVEPOSITION ){
assert( pCur->curFlags & BTCF_ValidNKey );
assert( pX->nKey==pCur->info.nKey );
- assert( pCur->info.nSize!=0 );
assert( loc==0 );
}
#endif
@@ -71069,7 +74257,7 @@ SQLITE_PRIVATE int sqlite3BtreeInsert(
}else{
/* This is an index or a WITHOUT ROWID table */
- /* If BTREE_SAVEPOSITION is set, the cursor must already be pointing
+ /* If BTREE_SAVEPOSITION is set, the cursor must already be pointing
** to a row with the same key as the new entry being inserted.
*/
assert( (flags & BTREE_SAVEPOSITION)==0 || loc==0 );
@@ -71111,13 +74299,22 @@ SQLITE_PRIVATE int sqlite3BtreeInsert(
return btreeOverwriteCell(pCur, &x2);
}
}
-
}
- assert( pCur->eState==CURSOR_VALID || (pCur->eState==CURSOR_INVALID && loc) );
+ assert( pCur->eState==CURSOR_VALID
+ || (pCur->eState==CURSOR_INVALID && loc)
+ || CORRUPT_DB );
pPage = pCur->pPage;
- assert( pPage->intKey || pX->nKey>=0 );
+ assert( pPage->intKey || pX->nKey>=0 || (flags & BTREE_PREFORMAT) );
assert( pPage->leaf || !pPage->intKey );
+ if( pPage->nFree<0 ){
+ if( NEVER(pCur->eState>CURSOR_INVALID) ){
+ rc = SQLITE_CORRUPT_BKPT;
+ }else{
+ rc = btreeComputeFreeSpace(pPage);
+ }
+ if( rc ) return rc;
+ }
TRACE(("INSERT: table=%d nkey=%lld ndata=%d page=%d %s\n",
pCur->pgnoRoot, pX->nKey, pX->nData, pPage->pgno,
@@ -71125,7 +74322,21 @@ SQLITE_PRIVATE int sqlite3BtreeInsert(
assert( pPage->isInit );
newCell = pBt->pTmpSpace;
assert( newCell!=0 );
- rc = fillInCell(pPage, newCell, pX, &szNew);
+ if( flags & BTREE_PREFORMAT ){
+ rc = SQLITE_OK;
+ szNew = pBt->nPreformatSize;
+ if( szNew<4 ) szNew = 4;
+ if( ISAUTOVACUUM && szNew>pPage->maxLocal ){
+ CellInfo info;
+ pPage->xParseCell(pPage, newCell, &info);
+ if( info.nPayload!=info.nLocal ){
+ Pgno ovfl = get4byte(&newCell[szNew-4]);
+ ptrmapPut(pBt, ovfl, PTRMAP_OVERFLOW1, pPage->pgno, &rc);
+ }
+ }
+ }else{
+ rc = fillInCell(pPage, newCell, pX, &szNew);
+ }
if( rc ) goto end_insert;
assert( szNew==pPage->xCellSize(pPage, newCell) );
assert( szNew <= MX_CELL_SIZE(pBt) );
@@ -71141,21 +74352,28 @@ SQLITE_PRIVATE int sqlite3BtreeInsert(
if( !pPage->leaf ){
memcpy(newCell, oldCell, 4);
}
- rc = clearCell(pPage, oldCell, &info);
- if( info.nSize==szNew && info.nLocal==info.nPayload
+ BTREE_CLEAR_CELL(rc, pPage, oldCell, info);
+ testcase( pCur->curFlags & BTCF_ValidOvfl );
+ invalidateOverflowCache(pCur);
+ if( info.nSize==szNew && info.nLocal==info.nPayload
&& (!ISAUTOVACUUM || szNewminLocal)
){
/* Overwrite the old cell with the new if they are the same size.
** We could also try to do this if the old cell is smaller, then add
** the leftover space to the free list. But experiments show that
** doing that is no faster then skipping this optimization and just
- ** calling dropCell() and insertCell().
+ ** calling dropCell() and insertCell().
**
** This optimization cannot be used on an autovacuum database if the
** new entry uses overflow pages, as the insertCell() call below is
** necessary to add the PTRMAP_OVERFLOW1 pointer-map entry. */
assert( rc==SQLITE_OK ); /* clearCell never fails when nLocal==nPayload */
- if( oldCell+szNew > pPage->aDataEnd ) return SQLITE_CORRUPT_BKPT;
+ if( oldCell < pPage->aData+pPage->hdrOffset+10 ){
+ return SQLITE_CORRUPT_BKPT;
+ }
+ if( oldCell+szNew > pPage->aDataEnd ){
+ return SQLITE_CORRUPT_BKPT;
+ }
memcpy(oldCell, newCell, szNew);
return SQLITE_OK;
}
@@ -71172,7 +74390,7 @@ SQLITE_PRIVATE int sqlite3BtreeInsert(
assert( pPage->nOverflow==0 || rc==SQLITE_OK );
assert( rc!=SQLITE_OK || pPage->nCell>0 || pPage->nOverflow>0 );
- /* If no error has occurred and pPage has an overflow cell, call balance()
+ /* If no error has occurred 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 BTCF_ValidNKey
** variables.
@@ -71199,7 +74417,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->pPage->nOverflow = 0;
@@ -71226,7 +74444,115 @@ end_insert:
}
/*
-** Delete the entry that the cursor is pointing to.
+** This function is used as part of copying the current row from cursor
+** pSrc into cursor pDest. If the cursors are open on intkey tables, then
+** parameter iKey is used as the rowid value when the record is copied
+** into pDest. Otherwise, the record is copied verbatim.
+**
+** This function does not actually write the new value to cursor pDest.
+** Instead, it creates and populates any required overflow pages and
+** writes the data for the new cell into the BtShared.pTmpSpace buffer
+** for the destination database. The size of the cell, in bytes, is left
+** in BtShared.nPreformatSize. The caller completes the insertion by
+** calling sqlite3BtreeInsert() with the BTREE_PREFORMAT flag specified.
+**
+** SQLITE_OK is returned if successful, or an SQLite error code otherwise.
+*/
+SQLITE_PRIVATE int sqlite3BtreeTransferRow(BtCursor *pDest, BtCursor *pSrc, i64 iKey){
+ int rc = SQLITE_OK;
+ BtShared *pBt = pDest->pBt;
+ u8 *aOut = pBt->pTmpSpace; /* Pointer to next output buffer */
+ const u8 *aIn; /* Pointer to next input buffer */
+ u32 nIn; /* Size of input buffer aIn[] */
+ u32 nRem; /* Bytes of data still to copy */
+
+ getCellInfo(pSrc);
+ aOut += putVarint32(aOut, pSrc->info.nPayload);
+ if( pDest->pKeyInfo==0 ) aOut += putVarint(aOut, iKey);
+ nIn = pSrc->info.nLocal;
+ aIn = pSrc->info.pPayload;
+ if( aIn+nIn>pSrc->pPage->aDataEnd ){
+ return SQLITE_CORRUPT_BKPT;
+ }
+ nRem = pSrc->info.nPayload;
+ if( nIn==nRem && nInpPage->maxLocal ){
+ memcpy(aOut, aIn, nIn);
+ pBt->nPreformatSize = nIn + (aOut - pBt->pTmpSpace);
+ }else{
+ Pager *pSrcPager = pSrc->pBt->pPager;
+ u8 *pPgnoOut = 0;
+ Pgno ovflIn = 0;
+ DbPage *pPageIn = 0;
+ MemPage *pPageOut = 0;
+ u32 nOut; /* Size of output buffer aOut[] */
+
+ nOut = btreePayloadToLocal(pDest->pPage, pSrc->info.nPayload);
+ pBt->nPreformatSize = nOut + (aOut - pBt->pTmpSpace);
+ if( nOutinfo.nPayload ){
+ pPgnoOut = &aOut[nOut];
+ pBt->nPreformatSize += 4;
+ }
+
+ if( nRem>nIn ){
+ if( aIn+nIn+4>pSrc->pPage->aDataEnd ){
+ return SQLITE_CORRUPT_BKPT;
+ }
+ ovflIn = get4byte(&pSrc->info.pPayload[nIn]);
+ }
+
+ do {
+ nRem -= nOut;
+ do{
+ assert( nOut>0 );
+ if( nIn>0 ){
+ int nCopy = MIN(nOut, nIn);
+ memcpy(aOut, aIn, nCopy);
+ nOut -= nCopy;
+ nIn -= nCopy;
+ aOut += nCopy;
+ aIn += nCopy;
+ }
+ if( nOut>0 ){
+ sqlite3PagerUnref(pPageIn);
+ pPageIn = 0;
+ rc = sqlite3PagerGet(pSrcPager, ovflIn, &pPageIn, PAGER_GET_READONLY);
+ if( rc==SQLITE_OK ){
+ aIn = (const u8*)sqlite3PagerGetData(pPageIn);
+ ovflIn = get4byte(aIn);
+ aIn += 4;
+ nIn = pSrc->pBt->usableSize - 4;
+ }
+ }
+ }while( rc==SQLITE_OK && nOut>0 );
+
+ if( rc==SQLITE_OK && nRem>0 ){
+ Pgno pgnoNew;
+ MemPage *pNew = 0;
+ rc = allocateBtreePage(pBt, &pNew, &pgnoNew, 0, 0);
+ put4byte(pPgnoOut, pgnoNew);
+ if( ISAUTOVACUUM && pPageOut ){
+ ptrmapPut(pBt, pgnoNew, PTRMAP_OVERFLOW2, pPageOut->pgno, &rc);
+ }
+ releasePage(pPageOut);
+ pPageOut = pNew;
+ if( pPageOut ){
+ pPgnoOut = pPageOut->aData;
+ put4byte(pPgnoOut, 0);
+ aOut = &pPgnoOut[4];
+ nOut = MIN(pBt->usableSize - 4, nRem);
+ }
+ }
+ }while( nRem>0 && rc==SQLITE_OK );
+
+ releasePage(pPageOut);
+ sqlite3PagerUnref(pPageIn);
+ }
+
+ return rc;
+}
+
+/*
+** Delete the entry that the cursor is pointing to.
**
** If the BTREE_SAVEPOSITION bit of the flags parameter is zero, then
** the cursor is left pointing at an arbitrary location after the delete.
@@ -71244,12 +74570,12 @@ end_insert:
*/
SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){
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 */
CellInfo info; /* Size of the cell being deleted */
int bSkipnext = 0; /* Leaf cursor in SKIPNEXT state */
u8 bPreserve = flags & BTREE_SAVEPOSITION; /* Keep cursor valid */
@@ -71260,27 +74586,33 @@ SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){
assert( pCur->curFlags & BTCF_WriteFlag );
assert( hasSharedCacheTableLock(p, pCur->pgnoRoot, pCur->pKeyInfo!=0, 2) );
assert( !hasReadConflicts(p, pCur->pgnoRoot) );
- assert( pCur->ixpPage->nCell );
- assert( pCur->eState==CURSOR_VALID );
assert( (flags & ~(BTREE_SAVEPOSITION | BTREE_AUXDELETE))==0 );
+ if( pCur->eState==CURSOR_REQUIRESEEK ){
+ rc = btreeRestoreCursorPosition(pCur);
+ assert( rc!=SQLITE_OK || CORRUPT_DB || pCur->eState==CURSOR_VALID );
+ if( rc || pCur->eState!=CURSOR_VALID ) return rc;
+ }
+ assert( CORRUPT_DB || pCur->eState==CURSOR_VALID );
iCellDepth = pCur->iPage;
iCellIdx = pCur->ix;
pPage = pCur->pPage;
pCell = findCell(pPage, iCellIdx);
+ if( pPage->nFree<0 && btreeComputeFreeSpace(pPage) ) return SQLITE_CORRUPT;
/* If the bPreserve flag is set to true, then the cursor position must
** be preserved following this delete operation. If the current delete
** will cause a b-tree rebalance, then this is done by saving the cursor
- ** key and leaving the cursor in CURSOR_REQUIRESEEK state before
- ** returning.
+ ** key and leaving the cursor in CURSOR_REQUIRESEEK state before
+ ** returning.
**
** Or, if the current delete will not cause a rebalance, then the cursor
** will be left in CURSOR_SKIPNEXT state pointing to the entry immediately
** before or after the deleted entry. In this case set bSkipnext to true. */
if( bPreserve ){
- if( !pPage->leaf
+ if( !pPage->leaf
|| (pPage->nFree+cellSizePtr(pPage,pCell)+2)>(int)(pBt->usableSize*2/3)
+ || pPage->nCell==1 /* See dbfuzz001.test for a test case */
){
/* A b-tree rebalance will be required after deleting this entry.
** Save the cursor key. */
@@ -71313,7 +74645,7 @@ SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){
/* If this is a delete operation to remove a row from a table b-tree,
** invalidate any incrblob cursors open on the row being deleted. */
- if( pCur->pKeyInfo==0 ){
+ if( pCur->pKeyInfo==0 && p->hasIncrblobCur ){
invalidateIncrblobCursors(p, pCur->pgnoRoot, pCur->info.nKey, 0);
}
@@ -71322,7 +74654,7 @@ SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){
** itself from within the page. */
rc = sqlite3PagerWrite(pPage->pDbPage);
if( rc ) return rc;
- rc = clearCell(pPage, pCell, &info);
+ BTREE_CLEAR_CELL(rc, pPage, pCell, info);
dropCell(pPage, iCellIdx, info.nSize, &rc);
if( rc ) return rc;
@@ -71337,6 +74669,10 @@ SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){
Pgno n;
unsigned char *pTmp;
+ if( pLeaf->nFree<0 ){
+ rc = btreeComputeFreeSpace(pLeaf);
+ if( rc ) return rc;
+ }
if( iCellDepthiPage-1 ){
n = pCur->apPage[iCellDepth+1]->pgno;
}else{
@@ -71369,7 +74705,7 @@ SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){
** 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 ){
@@ -71417,7 +74753,7 @@ SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){
** BTREE_INTKEY|BTREE_LEAFDATA Used for SQL tables with rowid keys
** BTREE_ZERODATA Used for SQL indices
*/
-static int btreeCreateTable(Btree *p, int *piTable, int createTabFlags){
+static int btreeCreateTable(Btree *p, Pgno *piTable, int createTabFlags){
BtShared *pBt = p->pBt;
MemPage *pRoot;
Pgno pgnoRoot;
@@ -71450,6 +74786,9 @@ static int btreeCreateTable(Btree *p, int *piTable, int createTabFlags){
** created so far, so the new root-page is (meta[3]+1).
*/
sqlite3BtreeGetMeta(p, BTREE_LARGEST_ROOT_PAGE, &pgnoRoot);
+ if( pgnoRoot>btreePagecount(pBt) ){
+ return SQLITE_CORRUPT_BKPT;
+ }
pgnoRoot++;
/* The new root-page may not be allocated on a pointer-map page, or the
@@ -71459,8 +74798,7 @@ static int btreeCreateTable(Btree *p, int *piTable, int createTabFlags){
pgnoRoot==PENDING_BYTE_PAGE(pBt) ){
pgnoRoot++;
}
- assert( pgnoRoot>=3 || CORRUPT_DB );
- testcase( pgnoRoot<3 );
+ assert( pgnoRoot>=3 );
/* Allocate a page. The page that currently resides at pgnoRoot will
** be moved to the allocated page (unless the allocated page happens
@@ -71523,7 +74861,7 @@ static int btreeCreateTable(Btree *p, int *piTable, int createTabFlags){
}
}else{
pRoot = pPageMove;
- }
+ }
/* Update the pointer-map and meta-data with the new root-page number. */
ptrmapPut(pBt, pgnoRoot, PTRMAP_ROOTPAGE, 0, &rc);
@@ -71557,10 +74895,10 @@ static int btreeCreateTable(Btree *p, int *piTable, int createTabFlags){
zeroPage(pRoot, ptfFlags);
sqlite3PagerUnref(pRoot->pDbPage);
assert( (pBt->openFlags & BTREE_SINGLE)==0 || pgnoRoot==2 );
- *piTable = (int)pgnoRoot;
+ *piTable = pgnoRoot;
return SQLITE_OK;
}
-SQLITE_PRIVATE int sqlite3BtreeCreateTable(Btree *p, int *piTable, int flags){
+SQLITE_PRIVATE int sqlite3BtreeCreateTable(Btree *p, Pgno *piTable, int flags){
int rc;
sqlite3BtreeEnter(p);
rc = btreeCreateTable(p, piTable, flags);
@@ -71603,14 +74941,14 @@ static int clearDatabasePage(
rc = clearDatabasePage(pBt, get4byte(pCell), 1, pnChange);
if( rc ) goto cleardatabasepage_out;
}
- rc = clearCell(pPage, pCell, &info);
+ BTREE_CLEAR_CELL(rc, pPage, pCell, info);
if( rc ) goto cleardatabasepage_out;
}
if( !pPage->leaf ){
rc = clearDatabasePage(pBt, get4byte(&pPage->aData[hdr+8]), 1, pnChange);
if( rc ) goto cleardatabasepage_out;
- }else if( pnChange ){
- assert( pPage->intKey || CORRUPT_DB );
+ }
+ if( pnChange ){
testcase( !pPage->intKey );
*pnChange += pPage->nCell;
}
@@ -71635,9 +74973,8 @@ cleardatabasepage_out:
** read cursors on the table. Open write cursors are moved to the
** root of the table.
**
-** If pnChange is not NULL, then table iTable must be an intkey table. The
-** integer value pointed to by pnChange is incremented by the number of
-** entries in the table.
+** If pnChange is not NULL, then the integer value pointed to by pnChange
+** is incremented by the number of entries in the table.
*/
SQLITE_PRIVATE int sqlite3BtreeClearTable(Btree *p, int iTable, int *pnChange){
int rc;
@@ -71651,7 +74988,9 @@ SQLITE_PRIVATE int sqlite3BtreeClearTable(Btree *p, int iTable, int *pnChange){
/* Invalidate all incrblob cursors open on table iTable (assuming iTable
** is the root of a table b-tree - if it is not, the following call is
** a no-op). */
- invalidateIncrblobCursors(p, (Pgno)iTable, 0, 1);
+ if( p->hasIncrblobCur ){
+ invalidateIncrblobCursors(p, (Pgno)iTable, 0, 1);
+ }
rc = clearDatabasePage(pBt, (Pgno)iTable, 0, pnChange);
}
sqlite3BtreeLeave(p);
@@ -71676,12 +75015,12 @@ SQLITE_PRIVATE int sqlite3BtreeClearTableOfCursor(BtCursor *pCur){
** 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
@@ -71695,6 +75034,9 @@ static int btreeDropTable(Btree *p, Pgno iTable, int *piMoved){
assert( sqlite3BtreeHoldsMutex(p) );
assert( p->inTrans==TRANS_WRITE );
assert( iTable>=2 );
+ if( iTable>btreePagecount(pBt) ){
+ return SQLITE_CORRUPT_BKPT;
+ }
rc = btreeGetPage(pBt, (Pgno)iTable, &pPage, 0);
if( rc ) return rc;
@@ -71716,7 +75058,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);
@@ -71725,7 +75067,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;
@@ -71767,7 +75109,7 @@ static int btreeDropTable(Btree *p, Pgno iTable, int *piMoved){
releasePage(pPage);
}
#endif
- return rc;
+ return rc;
}
SQLITE_PRIVATE int sqlite3BtreeDropTable(Btree *p, int iTable, int *piMoved){
int rc;
@@ -71786,7 +75128,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].
@@ -71803,12 +75145,12 @@ SQLITE_PRIVATE void sqlite3BtreeGetMeta(Btree *p, int idx, u32 *pMeta){
sqlite3BtreeEnter(p);
assert( p->inTrans>TRANS_NONE );
- assert( SQLITE_OK==querySharedCacheTableLock(p, MASTER_ROOT, READ_LOCK) );
+ assert( SQLITE_OK==querySharedCacheTableLock(p, SCHEMA_ROOT, READ_LOCK) );
assert( pBt->pPage1 );
assert( idx>=0 && idx<=15 );
if( idx==BTREE_DATA_VERSION ){
- *pMeta = sqlite3PagerDataVersion(pBt->pPager) + p->iDataVersion;
+ *pMeta = sqlite3PagerDataVersion(pBt->pPager) + p->iBDataVersion;
}else{
*pMeta = get4byte(&pBt->pPage1->aData[36 + idx*4]);
}
@@ -71852,16 +75194,15 @@ SQLITE_PRIVATE int sqlite3BtreeUpdateMeta(Btree *p, int idx, u32 iMeta){
return rc;
}
-#ifndef SQLITE_OMIT_BTREECOUNT
/*
** 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.
*/
-SQLITE_PRIVATE int sqlite3BtreeCount(BtCursor *pCur, i64 *pnEntry){
+SQLITE_PRIVATE int sqlite3BtreeCount(sqlite3 *db, BtCursor *pCur, i64 *pnEntry){
i64 nEntry = 0; /* Value to return in *pnEntry */
int rc; /* Return code */
@@ -71872,13 +75213,13 @@ SQLITE_PRIVATE int sqlite3BtreeCount(BtCursor *pCur, i64 *pnEntry){
}
/* 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 ){
+ while( rc==SQLITE_OK && !AtomicLoad(&db->u1.isInterrupted) ){
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.
*/
@@ -71887,7 +75228,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
@@ -71911,7 +75252,7 @@ SQLITE_PRIVATE int sqlite3BtreeCount(BtCursor *pCur, i64 *pnEntry){
pPage = pCur->pPage;
}
- /* 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->ix;
@@ -71925,7 +75266,6 @@ SQLITE_PRIVATE int sqlite3BtreeCount(BtCursor *pCur, i64 *pnEntry){
/* An error has occurred. Return an error code. */
return rc;
}
-#endif
/*
** Return the pager associated with a BTree. This routine is used for
@@ -71958,7 +75298,7 @@ static void checkAppendMsg(
sqlite3_str_vappendf(&pCheck->errMsg, zFormat, ap);
va_end(ap);
if( pCheck->errMsg.accError==SQLITE_NOMEM ){
- pCheck->mallocFailed = 1;
+ pCheck->bOomFault = 1;
}
}
#endif /* SQLITE_OMIT_INTEGRITY_CHECK */
@@ -72000,13 +75340,14 @@ static int checkRef(IntegrityCk *pCheck, Pgno iPage){
checkAppendMsg(pCheck, "2nd reference to page %d", iPage);
return 1;
}
+ if( AtomicLoad(&pCheck->db->u1.isInterrupted) ) return 1;
setPageReferenced(pCheck, iPage);
return 0;
}
#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.
*/
@@ -72022,14 +75363,14 @@ static void checkPtrmap(
rc = ptrmapGet(pCheck->pBt, iChild, &ePtrmapType, &iPtrmapParent);
if( rc!=SQLITE_OK ){
- if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ) pCheck->mallocFailed = 1;
+ if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ) pCheck->bOomFault = 1;
checkAppendMsg(pCheck, "Failed to read ptrmap key=%d", iChild);
return;
}
if( ePtrmapType!=eType || iPtrmapParent!=iParent ){
checkAppendMsg(pCheck,
- "Bad ptr map entry key=%d expected=(%d,%d) got=(%d,%d)",
+ "Bad ptr map entry key=%d expected=(%d,%d) got=(%d,%d)",
iChild, eType, iParent, ePtrmapType, iPtrmapParent);
}
}
@@ -72042,11 +75383,11 @@ static void checkPtrmap(
static void checkList(
IntegrityCk *pCheck, /* Integrity checking context */
int isFreeList, /* True for a freelist. False for overflow page list */
- int iPage, /* Page number for first page in the list */
- int N /* Expected number of pages in the list */
+ Pgno iPage, /* Page number for first page in the list */
+ u32 N /* Expected number of pages in the list */
){
int i;
- int expected = N;
+ u32 expected = N;
int nErrAtStart = pCheck->nErr;
while( iPage!=0 && pCheck->mxErr ){
DbPage *pOvflPage;
@@ -72059,18 +75400,18 @@ static void checkList(
}
pOvflData = (unsigned char *)sqlite3PagerGetData(pOvflPage);
if( isFreeList ){
- int n = get4byte(&pOvflData[4]);
+ u32 n = (u32)get4byte(&pOvflData[4]);
#ifndef SQLITE_OMIT_AUTOVACUUM
if( pCheck->pBt->autoVacuum ){
checkPtrmap(pCheck, iPage, PTRMAP_FREEPAGE, 0);
}
#endif
- if( n>(int)pCheck->pBt->usableSize/4-2 ){
+ if( n>pCheck->pBt->usableSize/4-2 ){
checkAppendMsg(pCheck,
"freelist leaf count too big on page %d", iPage);
N--;
}else{
- for(i=0; ipBt->autoVacuum ){
@@ -72124,7 +75465,7 @@ static void checkList(
** property.
**
** This heap is used for cell overlap and coverage testing. Each u32
-** entry represents the span of a cell or freeblock on a btree page.
+** entry represents the span of a cell or freeblock on a btree page.
** The upper 16 bits are the index of the first byte of a range and the
** lower 16 bits are the index of the last byte of that range.
*/
@@ -72154,7 +75495,7 @@ static int btreeHeapPull(u32 *aHeap, u32 *pOut){
aHeap[j] = x;
i = j;
}
- return 1;
+ return 1;
}
#ifndef SQLITE_OMIT_INTEGRITY_CHECK
@@ -72162,7 +75503,7 @@ static int btreeHeapPull(u32 *aHeap, u32 *pOut){
** 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
@@ -72174,7 +75515,7 @@ static int btreeHeapPull(u32 *aHeap, u32 *pOut){
*/
static int checkTreePage(
IntegrityCk *pCheck, /* Context for the sanity check */
- int iPage, /* Page number of the page to check */
+ Pgno iPage, /* Page number of the page to check */
i64 *piMinKey, /* Write minimum integer primary key here */
i64 maxKey /* Error if integer primary key greater than this */
){
@@ -72210,9 +75551,9 @@ static int checkTreePage(
usableSize = pBt->usableSize;
if( iPage==0 ) return 0;
if( checkRef(pCheck, iPage) ) return 0;
- pCheck->zPfx = "Page %d: ";
+ pCheck->zPfx = "Page %u: ";
pCheck->v1 = iPage;
- if( (rc = btreeGetPage(pBt, (Pgno)iPage, &pPage, 0))!=0 ){
+ if( (rc = btreeGetPage(pBt, iPage, &pPage, 0))!=0 ){
checkAppendMsg(pCheck,
"unable to get the page. error code=%d", rc);
goto end_of_check;
@@ -72228,11 +75569,16 @@ static int checkTreePage(
"btreeInitPage() returns error code %d", rc);
goto end_of_check;
}
+ if( (rc = btreeComputeFreeSpace(pPage))!=0 ){
+ assert( rc==SQLITE_CORRUPT );
+ checkAppendMsg(pCheck, "free space corruption", rc);
+ goto end_of_check;
+ }
data = pPage->aData;
hdr = pPage->hdrOffset;
/* Set up for cell analysis */
- pCheck->zPfx = "On tree page %d cell %d: ";
+ pCheck->zPfx = "On tree page %u cell %d: ";
contentOffset = get2byteNotZero(&data[hdr+5]);
assert( contentOffset<=usableSize ); /* Enforced by btreeInitPage() */
@@ -72252,7 +75598,7 @@ static int checkTreePage(
pgno = get4byte(&data[hdr+8]);
#ifndef SQLITE_OMIT_AUTOVACUUM
if( pBt->autoVacuum ){
- pCheck->zPfx = "On page %d at right child: ";
+ pCheck->zPfx = "On page %u at right child: ";
checkPtrmap(pCheck, pgno, PTRMAP_BTREE, iPage);
}
#endif
@@ -72300,7 +75646,7 @@ static int checkTreePage(
/* Check the content overflow list */
if( info.nPayload>info.nLocal ){
- int nPage; /* Number of pages on the overflow chain */
+ u32 nPage; /* Number of pages on the overflow chain */
Pgno pgnoOvfl; /* First page of the overflow chain */
assert( pc + info.nSize - 4 <= usableSize );
nPage = (info.nPayload - info.nLocal + usableSize - 5)/(usableSize - 4);
@@ -72355,14 +75701,14 @@ static int checkTreePage(
**
** EVIDENCE-OF: R-20690-50594 The second field of the b-tree page header
** is the offset of the first freeblock, or zero if there are no
- ** freeblocks on the page.
+ ** freeblocks on the page.
*/
i = get2byte(&data[hdr+1]);
while( i>0 ){
int size, j;
- assert( (u32)i<=usableSize-4 ); /* Enforced by btreeInitPage() */
+ assert( (u32)i<=usableSize-4 ); /* Enforced by btreeComputeFreeSpace() */
size = get2byte(&data[i+2]);
- assert( (u32)(i+size)<=usableSize ); /* Enforced by btreeInitPage() */
+ assert( (u32)(i+size)<=usableSize ); /* due to btreeComputeFreeSpace() */
btreeHeapInsert(heap, (((u32)i)<<16)|(i+size-1));
/* EVIDENCE-OF: R-58208-19414 The first 2 bytes of a freeblock are a
** big-endian integer which is the offset in the b-tree page of the next
@@ -72371,17 +75717,17 @@ static int checkTreePage(
j = get2byte(&data[i]);
/* EVIDENCE-OF: R-06866-39125 Freeblocks are always connected in order of
** increasing offset. */
- assert( j==0 || j>i+size ); /* Enforced by btreeInitPage() */
- assert( (u32)j<=usableSize-4 ); /* Enforced by btreeInitPage() */
+ assert( j==0 || j>i+size ); /* Enforced by btreeComputeFreeSpace() */
+ assert( (u32)j<=usableSize-4 ); /* Enforced by btreeComputeFreeSpace() */
i = j;
}
- /* Analyze the min-heap looking for overlap between cells and/or
+ /* Analyze the min-heap looking for overlap between cells and/or
** freeblocks, and counting the number of untracked bytes in nFrag.
- **
+ **
** Each min-heap entry is of the form: (start_address<<16)|end_address.
** There is an implied first entry the covers the page header, the cell
** pointer index, and the gap between the cell pointer index and the start
- ** of cell content.
+ ** of cell content.
**
** The loop below pulls entries from the min-heap in order and compares
** the start_address against the previous end_address. If there is an
@@ -72393,7 +75739,7 @@ static int checkTreePage(
while( btreeHeapPull(heap,&x) ){
if( (prev&0xffff)>=(x>>16) ){
checkAppendMsg(pCheck,
- "Multiple uses for byte %u of page %d", x>>16, iPage);
+ "Multiple uses for byte %u of page %u", x>>16, iPage);
break;
}else{
nFrag += (x>>16) - (prev&0xffff) - 1;
@@ -72408,7 +75754,7 @@ static int checkTreePage(
*/
if( heap[0]==0 && nFrag!=data[hdr+7] ){
checkAppendMsg(pCheck,
- "Fragmentation of %d bytes reported as %d on page %d",
+ "Fragmentation of %d bytes reported as %d on page %u",
nFrag, data[hdr+7], iPage);
}
}
@@ -72436,10 +75782,20 @@ end_of_check:
** allocation errors, an error message held in memory obtained from
** malloc is returned if *pnErr is non-zero. If *pnErr==0 then NULL is
** returned. If a memory allocation error occurs, NULL is returned.
+**
+** If the first entry in aRoot[] is 0, that indicates that the list of
+** root pages is incomplete. This is a "partial integrity-check". This
+** happens when performing an integrity check on a single table. The
+** zero is skipped, of course. But in addition, the freelist checks
+** and the checks to make sure every page is referenced are also skipped,
+** since obviously it is not possible to know which pages are covered by
+** the unverified btrees. Except, if aRoot[1] is 1, then the freelist
+** checks are still performed.
*/
SQLITE_PRIVATE char *sqlite3BtreeIntegrityCheck(
+ sqlite3 *db, /* Database connection that is running the check */
Btree *p, /* The btree to be checked */
- int *aRoot, /* An array of root pages numbers for individual trees */
+ Pgno *aRoot, /* An array of root pages numbers for individual trees */
int nRoot, /* Number of entries in aRoot[] */
int mxErr, /* Stop reporting errors after this many */
int *pnErr /* Write number of errors seen to this variable */
@@ -72447,20 +75803,31 @@ SQLITE_PRIVATE char *sqlite3BtreeIntegrityCheck(
Pgno i;
IntegrityCk sCheck;
BtShared *pBt = p->pBt;
- int savedDbFlags = pBt->db->flags;
+ u64 savedDbFlags = pBt->db->flags;
char zErr[100];
+ int bPartial = 0; /* True if not checking all btrees */
+ int bCkFreelist = 1; /* True to scan the freelist */
VVA_ONLY( int nRef );
+ assert( nRoot>0 );
+
+ /* aRoot[0]==0 means this is a partial check */
+ if( aRoot[0]==0 ){
+ assert( nRoot>1 );
+ bPartial = 1;
+ if( aRoot[1]!=1 ) bCkFreelist = 0;
+ }
sqlite3BtreeEnter(p);
assert( p->inTrans>TRANS_NONE && pBt->inTransaction>TRANS_NONE );
VVA_ONLY( nRef = sqlite3PagerRefcount(pBt->pPager) );
assert( nRef>=0 );
+ sCheck.db = db;
sCheck.pBt = pBt;
sCheck.pPager = pBt->pPager;
sCheck.nPage = btreePagecount(sCheck.pBt);
sCheck.mxErr = mxErr;
sCheck.nErr = 0;
- sCheck.mallocFailed = 0;
+ sCheck.bOomFault = 0;
sCheck.zPfx = 0;
sCheck.v1 = 0;
sCheck.v2 = 0;
@@ -72474,12 +75841,12 @@ SQLITE_PRIVATE char *sqlite3BtreeIntegrityCheck(
sCheck.aPgRef = sqlite3MallocZero((sCheck.nPage / 8)+ 1);
if( !sCheck.aPgRef ){
- sCheck.mallocFailed = 1;
+ sCheck.bOomFault = 1;
goto integrity_ck_cleanup;
}
sCheck.heap = (u32*)sqlite3PageMalloc( pBt->pageSize );
if( sCheck.heap==0 ){
- sCheck.mallocFailed = 1;
+ sCheck.bOomFault = 1;
goto integrity_ck_cleanup;
}
@@ -72488,38 +75855,42 @@ SQLITE_PRIVATE char *sqlite3BtreeIntegrityCheck(
/* Check the integrity of the freelist
*/
- sCheck.zPfx = "Main freelist: ";
- checkList(&sCheck, 1, get4byte(&pBt->pPage1->aData[32]),
- get4byte(&pBt->pPage1->aData[36]));
- sCheck.zPfx = 0;
+ if( bCkFreelist ){
+ sCheck.zPfx = "Main freelist: ";
+ checkList(&sCheck, 1, get4byte(&pBt->pPage1->aData[32]),
+ get4byte(&pBt->pPage1->aData[36]));
+ sCheck.zPfx = 0;
+ }
/* Check all the tables.
*/
#ifndef SQLITE_OMIT_AUTOVACUUM
- if( pBt->autoVacuum ){
- int mx = 0;
- int mxInHdr;
- for(i=0; (int)ipPage1->aData[52]);
- if( mx!=mxInHdr ){
+ if( !bPartial ){
+ if( pBt->autoVacuum ){
+ Pgno mx = 0;
+ Pgno mxInHdr;
+ for(i=0; (int)ipPage1->aData[52]);
+ if( mx!=mxInHdr ){
+ checkAppendMsg(&sCheck,
+ "max rootpage (%d) disagrees with header (%d)",
+ mx, mxInHdr
+ );
+ }
+ }else if( get4byte(&pBt->pPage1->aData[64])!=0 ){
checkAppendMsg(&sCheck,
- "max rootpage (%d) disagrees with header (%d)",
- mx, mxInHdr
+ "incremental_vacuum enabled with a max rootpage of zero"
);
}
- }else if( get4byte(&pBt->pPage1->aData[64])!=0 ){
- checkAppendMsg(&sCheck,
- "incremental_vacuum enabled with a max rootpage of zero"
- );
}
#endif
testcase( pBt->db->flags & SQLITE_CellSizeCk );
- pBt->db->flags &= ~SQLITE_CellSizeCk;
+ pBt->db->flags &= ~(u64)SQLITE_CellSizeCk;
for(i=0; (int)iautoVacuum && aRoot[i]>1 ){
+ if( pBt->autoVacuum && aRoot[i]>1 && !bPartial ){
checkPtrmap(&sCheck, aRoot[i], PTRMAP_ROOTPAGE, 0);
}
#endif
@@ -72529,24 +75900,26 @@ SQLITE_PRIVATE char *sqlite3BtreeIntegrityCheck(
/* Make sure every page in the file is referenced
*/
- for(i=1; i<=sCheck.nPage && sCheck.mxErr; i++){
+ if( !bPartial ){
+ for(i=1; i<=sCheck.nPage && sCheck.mxErr; i++){
#ifdef SQLITE_OMIT_AUTOVACUUM
- if( getPageReferenced(&sCheck, i)==0 ){
- checkAppendMsg(&sCheck, "Page %d is never used", i);
- }
+ if( getPageReferenced(&sCheck, i)==0 ){
+ checkAppendMsg(&sCheck, "Page %d is never used", i);
+ }
#else
- /* If the database supports auto-vacuum, make sure no tables contain
- ** references to pointer-map pages.
- */
- if( getPageReferenced(&sCheck, i)==0 &&
- (PTRMAP_PAGENO(pBt, i)!=i || !pBt->autoVacuum) ){
- checkAppendMsg(&sCheck, "Page %d is never used", i);
- }
- if( getPageReferenced(&sCheck, i)!=0 &&
- (PTRMAP_PAGENO(pBt, i)==i && pBt->autoVacuum) ){
- checkAppendMsg(&sCheck, "Pointer map page %d is referenced", i);
- }
+ /* If the database supports auto-vacuum, make sure no tables contain
+ ** references to pointer-map pages.
+ */
+ if( getPageReferenced(&sCheck, i)==0 &&
+ (PTRMAP_PAGENO(pBt, i)!=i || !pBt->autoVacuum) ){
+ checkAppendMsg(&sCheck, "Page %d is never used", i);
+ }
+ if( getPageReferenced(&sCheck, i)!=0 &&
+ (PTRMAP_PAGENO(pBt, i)==i && pBt->autoVacuum) ){
+ checkAppendMsg(&sCheck, "Pointer map page %d is referenced", i);
+ }
#endif
+ }
}
/* Clean up and report errors.
@@ -72554,7 +75927,7 @@ SQLITE_PRIVATE char *sqlite3BtreeIntegrityCheck(
integrity_ck_cleanup:
sqlite3PageFree(sCheck.heap);
sqlite3_free(sCheck.aPgRef);
- if( sCheck.mallocFailed ){
+ if( sCheck.bOomFault ){
sqlite3_str_reset(&sCheck.errMsg);
sCheck.nErr++;
}
@@ -72593,18 +75966,19 @@ SQLITE_PRIVATE const char *sqlite3BtreeGetJournalname(Btree *p){
}
/*
-** Return non-zero if a transaction is active.
+** Return one of SQLITE_TXN_NONE, SQLITE_TXN_READ, or SQLITE_TXN_WRITE
+** to describe the current transaction state of Btree p.
*/
-SQLITE_PRIVATE int sqlite3BtreeIsInTrans(Btree *p){
+SQLITE_PRIVATE int sqlite3BtreeTxnState(Btree *p){
assert( p==0 || sqlite3_mutex_held(p->db->mutex) );
- return (p && (p->inTrans==TRANS_WRITE));
+ return p ? p->inTrans : 0;
}
#ifndef SQLITE_OMIT_WAL
/*
** Run a checkpoint on the Btree passed as the first argument.
**
-** Return SQLITE_LOCKED if this or any other connection has an open
+** Return SQLITE_LOCKED if this or any other connection has an open
** transaction on the shared-cache the argument Btree is connected to.
**
** Parameter eMode is one of SQLITE_CHECKPOINT_PASSIVE, FULL or RESTART.
@@ -72626,14 +76000,8 @@ SQLITE_PRIVATE int sqlite3BtreeCheckpoint(Btree *p, int eMode, int *pnLog, int *
#endif
/*
-** Return non-zero if a read (or write) transaction is active.
+** Return true if there is currently a backup running on Btree p.
*/
-SQLITE_PRIVATE int sqlite3BtreeIsInReadTrans(Btree *p){
- assert( p );
- assert( sqlite3_mutex_held(p->db->mutex) );
- return p->inTrans!=TRANS_NONE;
-}
-
SQLITE_PRIVATE int sqlite3BtreeIsInBackup(Btree *p){
assert( p );
assert( sqlite3_mutex_held(p->db->mutex) );
@@ -72643,20 +76011,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. The xFree function should not call sqlite3_free()
** on the memory, the btree layer does that.
*/
@@ -72672,15 +76040,15 @@ 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
-** sqlite_master table. Otherwise SQLITE_OK.
+** Return SQLITE_LOCKED_SHAREDCACHE if another user of the same shared
+** btree as the argument handle holds an exclusive lock on the
+** sqlite_schema table. Otherwise SQLITE_OK.
*/
SQLITE_PRIVATE int sqlite3BtreeSchemaLocked(Btree *p){
int rc;
assert( sqlite3_mutex_held(p->db->mutex) );
sqlite3BtreeEnter(p);
- rc = querySharedCacheTableLock(p, MASTER_ROOT, READ_LOCK);
+ rc = querySharedCacheTableLock(p, SCHEMA_ROOT, READ_LOCK);
assert( rc==SQLITE_OK || rc==SQLITE_LOCKED_SHAREDCACHE );
sqlite3BtreeLeave(p);
return rc;
@@ -72714,11 +76082,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.
@@ -72749,7 +76117,7 @@ SQLITE_PRIVATE int sqlite3BtreePutData(BtCursor *pCsr, u32 offset, u32 amt, void
VVA_ONLY(rc =) saveAllCursors(pCsr->pBt, pCsr->pgnoRoot, pCsr);
assert( rc==SQLITE_OK );
- /* 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),
@@ -72768,7 +76136,7 @@ SQLITE_PRIVATE int sqlite3BtreePutData(BtCursor *pCsr, u32 offset, u32 amt, void
return accessPayload(pCsr, offset, amt, (unsigned char *)z, 1);
}
-/*
+/*
** Mark this cursor as an incremental blob cursor.
*/
SQLITE_PRIVATE void sqlite3BtreeIncrblobCursor(BtCursor *pCur){
@@ -72778,14 +76146,14 @@ SQLITE_PRIVATE void sqlite3BtreeIncrblobCursor(BtCursor *pCur){
#endif
/*
-** Set both the "read version" (single byte at byte offset 18) and
+** 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( iVersion==1 || iVersion==2 );
/* If setting the version fields to 1, do not automatically open the
@@ -72843,7 +76211,7 @@ SQLITE_PRIVATE int sqlite3BtreeSharable(Btree *p){
/*
** Return the number of connections to the BtShared object accessed by
-** the Btree handle passed as the only argument. For private caches
+** the Btree handle passed as the only argument. For private caches
** this is always 1. For shared caches it may be 1 or greater.
*/
SQLITE_PRIVATE int sqlite3BtreeConnectionCount(Btree *p){
@@ -72865,7 +76233,7 @@ SQLITE_PRIVATE int sqlite3BtreeConnectionCount(Btree *p){
** 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.
*/
/* #include "sqliteInt.h" */
@@ -72902,15 +76270,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
@@ -72931,8 +76299,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){
@@ -72968,18 +76336,18 @@ static Btree *findBtree(sqlite3 *pErrorDb, sqlite3 *pDb, const char *zDb){
*/
static int setDestPgsz(sqlite3_backup *p){
int rc;
- rc = sqlite3BtreeSetPageSize(p->pDest,sqlite3BtreeGetPageSize(p->pSrc),-1,0);
+ rc = sqlite3BtreeSetPageSize(p->pDest,sqlite3BtreeGetPageSize(p->pSrc),0,0);
return rc;
}
/*
** Check that there is no open read-transaction on the b-tree passed as the
** second argument. If there is not, return SQLITE_OK. Otherwise, if there
-** is an open read-transaction, return SQLITE_ERROR and leave an error
+** is an open read-transaction, return SQLITE_ERROR and leave an error
** message in database handle db.
*/
static int checkReadTransaction(sqlite3 *db, Btree *p){
- if( sqlite3BtreeIsInReadTrans(p) ){
+ if( sqlite3BtreeTxnState(p)!=SQLITE_TXN_NONE ){
sqlite3ErrorWithMsg(db, SQLITE_ERROR, "destination database is in use");
return SQLITE_ERROR;
}
@@ -73045,13 +76413,13 @@ SQLITE_API sqlite3_backup *sqlite3_backup_init(
p->iNext = 1;
p->isAttached = 0;
- if( 0==p->pSrc || 0==p->pDest
- || checkReadTransaction(pDestDb, p->pDest)!=SQLITE_OK
+ if( 0==p->pSrc || 0==p->pDest
+ || checkReadTransaction(pDestDb, p->pDest)!=SQLITE_OK
){
/* One (or both) of the named databases did not exist or an OOM
** error was hit. Or there is a transaction open on the destination
- ** database. The error has already been written into the pDestDb
- ** handle. All that is left to do here is free the sqlite3_backup
+ ** database. The error has already been written into the pDestDb
+ ** handle. All that is left to do here is free the sqlite3_backup
** structure. */
sqlite3_free(p);
p = 0;
@@ -73067,7 +76435,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.
*/
@@ -73076,8 +76444,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(
@@ -73091,13 +76459,6 @@ static int backupOnePage(
int nDestPgsz = sqlite3BtreeGetPageSize(p->pDest);
const int nCopy = MIN(nSrcPgsz, nDestPgsz);
const i64 iEnd = (i64)iSrcPg*(i64)nSrcPgsz;
-#ifdef SQLITE_HAS_CODEC
- /* Use BtreeGetReserveNoMutex() for the source b-tree, as although it is
- ** guaranteed that the shared-mutex is held by this thread, handle
- ** p->pSrc may not actually be the owner. */
- int nSrcReserve = sqlite3BtreeGetReserveNoMutex(p->pSrc);
- int nDestReserve = sqlite3BtreeGetOptimalReserve(p->pDest);
-#endif
int rc = SQLITE_OK;
i64 iOff;
@@ -73108,33 +76469,13 @@ static int backupOnePage(
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) ){
rc = SQLITE_READONLY;
}
-#ifdef SQLITE_HAS_CODEC
- /* Backup is not possible if the page size of the destination is changing
- ** and a codec is in use.
- */
- if( nSrcPgsz!=nDestPgsz && sqlite3PagerGetCodec(pDestPager)!=0 ){
- rc = SQLITE_READONLY;
- }
-
- /* Backup is not possible if the number of bytes of reserve space differ
- ** between source and destination. If there is a difference, try to
- ** fix the destination to agree with the source. If that is not possible,
- ** then the backup cannot proceed.
- */
- if( nSrcReserve!=nDestReserve ){
- u32 newPgsz = nSrcPgsz;
- rc = sqlite3PagerSetPagesize(pDestPager, &newPgsz, nSrcReserve);
- if( rc==SQLITE_OK && newPgsz!=nSrcPgsz ) rc = SQLITE_READONLY;
- }
-#endif
-
- /* 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.
*/
@@ -73153,7 +76494,7 @@ static int backupOnePage(
** 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);
@@ -73173,7 +76514,7 @@ static int backupOnePage(
** 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){
@@ -73237,7 +76578,7 @@ SQLITE_API int sqlite3_backup_step(sqlite3_backup *p, int nPage){
** one now. If a transaction is opened here, then it will be closed
** before this function exits.
*/
- if( rc==SQLITE_OK && 0==sqlite3BtreeIsInReadTrans(p->pSrc) ){
+ if( rc==SQLITE_OK && SQLITE_TXN_NONE==sqlite3BtreeTxnState(p->pSrc) ){
rc = sqlite3BtreeBeginTrans(p->pSrc, 0, 0);
bCloseTrans = 1;
}
@@ -73255,7 +76596,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,
- (int*)&p->iDestSchema))
+ (int*)&p->iDestSchema))
){
p->bDestLocked = 1;
}
@@ -73268,7 +76609,7 @@ SQLITE_API int sqlite3_backup_step(sqlite3_backup *p, int nPage){
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.
*/
@@ -73295,7 +76636,7 @@ 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
@@ -73321,12 +76662,12 @@ SQLITE_API int sqlite3_backup_step(sqlite3_backup *p, int nPage){
int nDestTruncate;
/* 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.
@@ -73350,7 +76691,7 @@ SQLITE_API int sqlite3_backup_step(sqlite3_backup *p, int nPage){
**
** * 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.
*/
@@ -73362,7 +76703,7 @@ SQLITE_API int sqlite3_backup_step(sqlite3_backup *p, int nPage){
i64 iEnd;
assert( pFile );
- assert( nDestTruncate==0
+ assert( nDestTruncate==0
|| (i64)nDestTruncate*(i64)pgszDest >= iSize || (
nDestTruncate==(int)(PENDING_BYTE_PAGE(p->pDest->pBt)-1)
&& iSize>=PENDING_BYTE && iSize<=PENDING_BYTE+pgszDest
@@ -73372,7 +76713,7 @@ SQLITE_API int sqlite3_backup_step(sqlite3_backup *p, int nPage){
** database has been stored in the journal for pDestPager and the
** journal synced to disk. So at this point we may safely modify
** the database file in any way, knowing that if a power failure
- ** occurs, the original database will be reconstructed from the
+ ** occurs, the original database will be reconstructed from the
** journal file. */
sqlite3PagerPagecount(pDestPager, &nDstPage);
for(iPg=nDestTruncate; rc==SQLITE_OK && iPg<=(Pgno)nDstPage; iPg++){
@@ -73392,8 +76733,8 @@ SQLITE_API int sqlite3_backup_step(sqlite3_backup *p, int nPage){
/* Write the extra pages and truncate the database file as required */
iEnd = MIN(PENDING_BYTE + pgszDest, iSize);
for(
- iOff=PENDING_BYTE+pgszSrc;
- rc==SQLITE_OK && iOffpDest, 0))
@@ -73426,7 +76767,7 @@ SQLITE_API int sqlite3_backup_step(sqlite3_backup *p, int nPage){
}
}
}
-
+
/* 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
@@ -73438,7 +76779,7 @@ SQLITE_API int sqlite3_backup_step(sqlite3_backup *p, int nPage){
TESTONLY( rc2 |= ) sqlite3BtreeCommitPhaseTwo(p->pSrc, 0);
assert( rc2==SQLITE_OK );
}
-
+
if( rc==SQLITE_IOERR_NOMEM ){
rc = SQLITE_NOMEM_BKPT;
}
@@ -73475,8 +76816,10 @@ SQLITE_API int sqlite3_backup_finish(sqlite3_backup *p){
}
if( p->isAttached ){
pp = sqlite3PagerBackupPtr(sqlite3BtreePager(p->pSrc));
+ assert( pp!=0 );
while( *pp!=p ){
pp = &(*pp)->pNext;
+ assert( pp!=0 );
}
*pp = p->pNext;
}
@@ -73518,7 +76861,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){
@@ -73533,7 +76876,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
@@ -73576,7 +76919,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
@@ -73596,8 +76939,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){
@@ -73607,7 +76950,7 @@ SQLITE_PRIVATE int sqlite3BtreeCopyFile(Btree *pTo, Btree *pFrom){
sqlite3BtreeEnter(pTo);
sqlite3BtreeEnter(pFrom);
- assert( sqlite3BtreeIsInTrans(pTo) );
+ assert( sqlite3BtreeTxnState(pTo)==SQLITE_TXN_WRITE );
pFd = sqlite3PagerFile(sqlite3BtreePager(pTo));
if( pFd->pMethods ){
i64 nByte = sqlite3BtreeGetPageSize(pFrom)*(i64)sqlite3BtreeLastPage(pFrom);
@@ -73627,15 +76970,11 @@ SQLITE_PRIVATE int sqlite3BtreeCopyFile(Btree *pTo, Btree *pFrom){
b.pDest = pTo;
b.iNext = 1;
-#ifdef SQLITE_HAS_CODEC
- sqlite3PagerAlignReserve(sqlite3BtreePager(pTo), sqlite3BtreePager(pFrom));
-#endif
-
/* 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);
assert( b.rc!=SQLITE_OK );
@@ -73647,7 +76986,7 @@ SQLITE_PRIVATE int sqlite3BtreeCopyFile(Btree *pTo, Btree *pFrom){
sqlite3PagerClearCache(sqlite3BtreePager(b.pDest));
}
- assert( sqlite3BtreeIsInTrans(pTo)==0 );
+ assert( sqlite3BtreeTxnState(pTo)!=SQLITE_TXN_WRITE );
copy_finished:
sqlite3BtreeLeave(pFrom);
sqlite3BtreeLeave(pTo);
@@ -73677,6 +77016,11 @@ copy_finished:
/* #include "sqliteInt.h" */
/* #include "vdbeInt.h" */
+/* True if X is a power of two. 0 is considered a power of two here.
+** In other words, return true if X has at most one bit set.
+*/
+#define ISPOWEROF2(X) (((X)&((X)-1))==0)
+
#ifdef SQLITE_DEBUG
/*
** Check invariants on a Mem object.
@@ -73685,7 +77029,7 @@ copy_finished:
** this: assert( sqlite3VdbeCheckMemInvariants(pMem) );
*/
SQLITE_PRIVATE int sqlite3VdbeCheckMemInvariants(Mem *p){
- /* If MEM_Dyn is set then Mem.xDel!=0.
+ /* If MEM_Dyn is set then Mem.xDel!=0.
** Mem.xDel might not be initialized if MEM_Dyn is clear.
*/
assert( (p->flags & MEM_Dyn)==0 || p->xDel!=0 );
@@ -73696,8 +77040,8 @@ SQLITE_PRIVATE int sqlite3VdbeCheckMemInvariants(Mem *p){
** That saves a few cycles in inner loops. */
assert( (p->flags & MEM_Dyn)==0 || p->szMalloc==0 );
- /* Cannot be both MEM_Int and MEM_Real at the same time */
- assert( (p->flags & (MEM_Int|MEM_Real))!=(MEM_Int|MEM_Real) );
+ /* Cannot have more than one of MEM_Int, MEM_Real, or MEM_IntReal */
+ assert( ISPOWEROF2(p->flags & (MEM_Int|MEM_Real|MEM_IntReal)) );
if( p->flags & MEM_Null ){
/* Cannot be both MEM_Null and some other type */
@@ -73716,7 +77060,7 @@ SQLITE_PRIVATE int sqlite3VdbeCheckMemInvariants(Mem *p){
((p->flags&MEM_Static)!=0 ? 1 : 0) <= 1 );
/* No other bits set */
- assert( (p->flags & ~(MEM_Null|MEM_Term|MEM_Subtype
+ assert( (p->flags & ~(MEM_Null|MEM_Term|MEM_Subtype|MEM_FromBind
|MEM_Dyn|MEM_Ephem|MEM_Static))==0 );
}else{
/* A pure NULL might have other flags, such as MEM_Static, MEM_Dyn,
@@ -73729,7 +77073,9 @@ SQLITE_PRIVATE int sqlite3VdbeCheckMemInvariants(Mem *p){
/* The szMalloc field holds the correct memory allocation size */
assert( p->szMalloc==0
- || p->szMalloc==sqlite3DbMallocSize(p->db,p->zMalloc) );
+ || (p->flags==MEM_Undefined
+ && p->szMalloc<=sqlite3DbMallocSize(p->db,p->zMalloc))
+ || p->szMalloc==sqlite3DbMallocSize(p->db,p->zMalloc));
/* If p holds a string or blob, the Mem.z must point to exactly
** one of the following:
@@ -73740,7 +77086,7 @@ SQLITE_PRIVATE int sqlite3VdbeCheckMemInvariants(Mem *p){
** (4) A static string or blob
*/
if( (p->flags & (MEM_Str|MEM_Blob)) && p->n>0 ){
- assert(
+ assert(
((p->szMalloc>0 && p->z==p->zMalloc)? 1 : 0) +
((p->flags&MEM_Dyn)!=0 ? 1 : 0) +
((p->flags&MEM_Ephem)!=0 ? 1 : 0) +
@@ -73751,9 +77097,40 @@ SQLITE_PRIVATE int sqlite3VdbeCheckMemInvariants(Mem *p){
}
#endif
+/*
+** Render a Mem object which is one of MEM_Int, MEM_Real, or MEM_IntReal
+** into a buffer.
+*/
+static void vdbeMemRenderNum(int sz, char *zBuf, Mem *p){
+ StrAccum acc;
+ assert( p->flags & (MEM_Int|MEM_Real|MEM_IntReal) );
+ assert( sz>22 );
+ if( p->flags & MEM_Int ){
+#if GCC_VERSION>=7000000
+ /* Work-around for GCC bug
+ ** https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96270 */
+ i64 x;
+ assert( (p->flags&MEM_Int)*2==sizeof(x) );
+ memcpy(&x, (char*)&p->u, (p->flags&MEM_Int)*2);
+ sqlite3Int64ToText(x, zBuf);
+#else
+ sqlite3Int64ToText(p->u.i, zBuf);
+#endif
+ }else{
+ sqlite3StrAccumInit(&acc, 0, zBuf, sz, 0);
+ sqlite3_str_appendf(&acc, "%!.15g",
+ (p->flags & MEM_IntReal)!=0 ? (double)p->u.i : p->u.r);
+ assert( acc.zText==zBuf && acc.mxAlloc<=0 );
+ zBuf[acc.nChar] = 0; /* Fast version of sqlite3StrAccumFinish(&acc) */
+ }
+}
+
#ifdef SQLITE_DEBUG
/*
-** Check that string value of pMem agrees with its integer or real value.
+** Validity checks on pMem. pMem holds a string.
+**
+** (1) Check that string value of pMem agrees with its integer or real value.
+** (2) Check that the string is correctly zero terminated
**
** A single int or real value always converts to the same strings. But
** many different strings can be converted into the same int or real.
@@ -73771,17 +77148,24 @@ SQLITE_PRIVATE int sqlite3VdbeCheckMemInvariants(Mem *p){
**
** This routine is for use inside of assert() statements only.
*/
-SQLITE_PRIVATE int sqlite3VdbeMemConsistentDualRep(Mem *p){
+SQLITE_PRIVATE int sqlite3VdbeMemValidStrRep(Mem *p){
char zBuf[100];
char *z;
int i, j, incr;
if( (p->flags & MEM_Str)==0 ) return 1;
- if( (p->flags & (MEM_Int|MEM_Real))==0 ) return 1;
- if( p->flags & MEM_Int ){
- sqlite3_snprintf(sizeof(zBuf),zBuf,"%lld",p->u.i);
- }else{
- sqlite3_snprintf(sizeof(zBuf),zBuf,"%!.15g",p->u.r);
+ if( p->flags & MEM_Term ){
+ /* Insure that the string is properly zero-terminated. Pay particular
+ ** attention to the case where p->n is odd */
+ if( p->szMalloc>0 && p->z==p->zMalloc ){
+ assert( p->enc==SQLITE_UTF8 || p->szMalloc >= ((p->n+1)&~1)+2 );
+ assert( p->enc!=SQLITE_UTF8 || p->szMalloc >= p->n+1 );
+ }
+ assert( p->z[p->n]==0 );
+ assert( p->enc==SQLITE_UTF8 || p->z[(p->n+1)&~1]==0 );
+ assert( p->enc==SQLITE_UTF8 || p->z[((p->n+1)&~1)+1]==0 );
}
+ if( (p->flags & (MEM_Int|MEM_Real|MEM_IntReal))==0 ) return 1;
+ vdbeMemRenderNum(sizeof(zBuf), zBuf, p);
z = p->z;
i = j = 0;
incr = 1;
@@ -73837,8 +77221,7 @@ SQLITE_PRIVATE int sqlite3VdbeChangeEncoding(Mem *pMem, int desiredEnc){
}
/*
-** Make sure pMem->z points to a writable allocation of at least
-** min(n,32) bytes.
+** Make sure pMem->z points to a writable allocation of at least n bytes.
**
** If the bPreserve argument is true, then copy of the content of
** pMem->z into the new allocation. pMem must be either a string or
@@ -73856,10 +77239,17 @@ SQLITE_PRIVATE SQLITE_NOINLINE int sqlite3VdbeMemGrow(Mem *pMem, int n, int bPre
testcase( bPreserve && pMem->z==0 );
assert( pMem->szMalloc==0
- || pMem->szMalloc==sqlite3DbMallocSize(pMem->db, pMem->zMalloc) );
- if( n<32 ) n = 32;
+ || (pMem->flags==MEM_Undefined
+ && pMem->szMalloc<=sqlite3DbMallocSize(pMem->db,pMem->zMalloc))
+ || pMem->szMalloc==sqlite3DbMallocSize(pMem->db,pMem->zMalloc));
if( pMem->szMalloc>0 && bPreserve && pMem->z==pMem->zMalloc ){
- pMem->z = pMem->zMalloc = sqlite3DbReallocOrFree(pMem->db, pMem->z, n);
+ if( pMem->db ){
+ pMem->z = pMem->zMalloc = sqlite3DbReallocOrFree(pMem->db, pMem->z, n);
+ }else{
+ pMem->zMalloc = sqlite3Realloc(pMem->z, n);
+ if( pMem->zMalloc==0 ) sqlite3_free(pMem->z);
+ pMem->z = pMem->zMalloc;
+ }
bPreserve = 0;
}else{
if( pMem->szMalloc>0 ) sqlite3DbFreeNN(pMem->db, pMem->zMalloc);
@@ -73895,34 +77285,40 @@ SQLITE_PRIVATE SQLITE_NOINLINE int sqlite3VdbeMemGrow(Mem *pMem, int n, int bPre
**
** Any prior string or blob content in the pMem object may be discarded.
** The pMem->xDel destructor is called, if it exists. Though MEM_Str
-** and MEM_Blob values may be discarded, MEM_Int, MEM_Real, and MEM_Null
-** values are preserved.
+** and MEM_Blob values may be discarded, MEM_Int, MEM_Real, MEM_IntReal,
+** and MEM_Null values are preserved.
**
** Return SQLITE_OK on success or an error code (probably SQLITE_NOMEM)
** if unable to complete the resizing.
*/
SQLITE_PRIVATE int sqlite3VdbeMemClearAndResize(Mem *pMem, int szNew){
- assert( szNew>0 );
+ assert( CORRUPT_DB || szNew>0 );
assert( (pMem->flags & MEM_Dyn)==0 || pMem->szMalloc==0 );
if( pMem->szMallocflags & MEM_Dyn)==0 );
pMem->z = pMem->zMalloc;
- pMem->flags &= (MEM_Null|MEM_Int|MEM_Real);
+ pMem->flags &= (MEM_Null|MEM_Int|MEM_Real|MEM_IntReal);
return SQLITE_OK;
}
/*
** It is already known that pMem contains an unterminated string.
** Add the zero terminator.
+**
+** Three bytes of zero are added. In this way, there is guaranteed
+** to be a double-zero byte at an even byte boundary in order to
+** terminate a UTF16 string, even if the initial size of the buffer
+** is an odd number of bytes.
*/
static SQLITE_NOINLINE int vdbeMemAddTerminator(Mem *pMem){
- if( sqlite3VdbeMemGrow(pMem, pMem->n+2, 1) ){
+ if( sqlite3VdbeMemGrow(pMem, pMem->n+3, 1) ){
return SQLITE_NOMEM_BKPT;
}
pMem->z[pMem->n] = 0;
pMem->z[pMem->n+1] = 0;
+ pMem->z[pMem->n+2] = 0;
pMem->flags |= MEM_Term;
return SQLITE_OK;
}
@@ -73959,13 +77355,15 @@ SQLITE_PRIVATE int sqlite3VdbeMemMakeWriteable(Mem *pMem){
SQLITE_PRIVATE int sqlite3VdbeMemExpandBlob(Mem *pMem){
int nByte;
assert( pMem->flags & MEM_Zero );
- assert( pMem->flags&MEM_Blob );
+ assert( (pMem->flags&MEM_Blob)!=0 || MemNullNochng(pMem) );
+ testcase( sqlite3_value_nochange(pMem) );
assert( !sqlite3VdbeMemIsRowSet(pMem) );
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
/* Set nByte to the number of bytes required to store the expanded blob. */
nByte = pMem->n + pMem->u.nZero;
if( nByte<=0 ){
+ if( (pMem->flags & MEM_Blob)==0 ) return SQLITE_OK;
nByte = 1;
}
if( sqlite3VdbeMemGrow(pMem, nByte, 1) ){
@@ -73994,12 +77392,12 @@ SQLITE_PRIVATE int sqlite3VdbeMemNulTerminate(Mem *pMem){
}
/*
-** Add MEM_Str to the set of representations for the given Mem. Numbers
-** are converted using sqlite3_snprintf(). Converting a BLOB to a string
-** is a no-op.
+** Add MEM_Str to the set of representations for the given Mem. This
+** routine is only called if pMem is a number of some kind, not a NULL
+** or a BLOB.
**
-** Existing representations MEM_Int and MEM_Real are invalidated if
-** bForce is true but are retained if bForce is false.
+** Existing representations MEM_Int, MEM_Real, or MEM_IntReal are invalidated
+** if bForce is true but are retained if bForce is false.
**
** A MEM_Null value will never be passed to this function. This function is
** used for converting values to text for returning to the user (i.e. via
@@ -74008,13 +77406,12 @@ SQLITE_PRIVATE int sqlite3VdbeMemNulTerminate(Mem *pMem){
** user and the latter is an internal programming error.
*/
SQLITE_PRIVATE int sqlite3VdbeMemStringify(Mem *pMem, u8 enc, u8 bForce){
- int fg = pMem->flags;
const int nByte = 32;
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
- assert( !(fg&MEM_Zero) );
- assert( !(fg&(MEM_Str|MEM_Blob)) );
- assert( fg&(MEM_Int|MEM_Real) );
+ assert( !(pMem->flags&MEM_Zero) );
+ assert( !(pMem->flags&(MEM_Str|MEM_Blob)) );
+ assert( pMem->flags&(MEM_Int|MEM_Real|MEM_IntReal) );
assert( !sqlite3VdbeMemIsRowSet(pMem) );
assert( EIGHT_BYTE_ALIGNMENT(pMem) );
@@ -74024,22 +77421,12 @@ SQLITE_PRIVATE int sqlite3VdbeMemStringify(Mem *pMem, u8 enc, u8 bForce){
return SQLITE_NOMEM_BKPT;
}
- /* For a Real or Integer, use sqlite3_snprintf() 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 ){
- sqlite3_snprintf(nByte, pMem->z, "%lld", pMem->u.i);
- }else{
- assert( fg & MEM_Real );
- sqlite3_snprintf(nByte, pMem->z, "%!.15g", pMem->u.r);
- }
- pMem->n = sqlite3Strlen30(pMem->z);
+ vdbeMemRenderNum(nByte, pMem->z, pMem);
+ assert( pMem->z!=0 );
+ pMem->n = sqlite3Strlen30NN(pMem->z);
pMem->enc = SQLITE_UTF8;
pMem->flags |= MEM_Str|MEM_Term;
- if( bForce ) pMem->flags &= ~(MEM_Int|MEM_Real);
+ if( bForce ) pMem->flags &= ~(MEM_Int|MEM_Real|MEM_IntReal);
sqlite3VdbeChangeEncoding(pMem, enc);
return SQLITE_OK;
}
@@ -74078,21 +77465,17 @@ SQLITE_PRIVATE int sqlite3VdbeMemFinalize(Mem *pMem, FuncDef *pFunc){
** This routine calls the xValue method for that function and stores
** the results in memory cell pMem.
**
-** SQLITE_ERROR is returned if xValue() reports an error. SQLITE_OK
+** SQLITE_ERROR is returned if xValue() reports an error. SQLITE_OK
** otherwise.
*/
#ifndef SQLITE_OMIT_WINDOWFUNC
SQLITE_PRIVATE int sqlite3VdbeMemAggValue(Mem *pAccum, Mem *pOut, FuncDef *pFunc){
sqlite3_context ctx;
- Mem t;
assert( pFunc!=0 );
assert( pFunc->xValue!=0 );
assert( (pAccum->flags & MEM_Null)!=0 || pFunc==pAccum->u.pDef );
assert( pAccum->db==0 || sqlite3_mutex_held(pAccum->db->mutex) );
memset(&ctx, 0, sizeof(ctx));
- memset(&t, 0, sizeof(t));
- t.flags = MEM_Null;
- t.db = pAccum->db;
sqlite3VdbeMemSetNull(pOut);
ctx.pOut = pOut;
ctx.pMem = pAccum;
@@ -74213,12 +77596,12 @@ SQLITE_PRIVATE i64 sqlite3VdbeIntValue(Mem *pMem){
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
assert( EIGHT_BYTE_ALIGNMENT(pMem) );
flags = pMem->flags;
- if( flags & MEM_Int ){
+ if( flags & (MEM_Int|MEM_IntReal) ){
+ testcase( flags & MEM_IntReal );
return pMem->u.i;
}else if( flags & MEM_Real ){
return doubleToInt64(pMem->u.r);
- }else if( flags & (MEM_Str|MEM_Blob) ){
- assert( pMem->z || pMem->n==0 );
+ }else if( (flags & (MEM_Str|MEM_Blob))!=0 && pMem->z!=0 ){
return memIntValue(pMem);
}else{
return 0;
@@ -74242,7 +77625,8 @@ SQLITE_PRIVATE double sqlite3VdbeRealValue(Mem *pMem){
assert( EIGHT_BYTE_ALIGNMENT(pMem) );
if( pMem->flags & MEM_Real ){
return pMem->u.r;
- }else if( pMem->flags & MEM_Int ){
+ }else if( pMem->flags & (MEM_Int|MEM_IntReal) ){
+ testcase( pMem->flags & MEM_IntReal );
return (double)pMem->u.i;
}else if( pMem->flags & (MEM_Str|MEM_Blob) ){
return memRealValue(pMem);
@@ -74254,10 +77638,11 @@ SQLITE_PRIVATE double sqlite3VdbeRealValue(Mem *pMem){
/*
** Return 1 if pMem represents true, and return 0 if pMem represents false.
-** Return the value ifNull if pMem is NULL.
+** Return the value ifNull if pMem is NULL.
*/
SQLITE_PRIVATE int sqlite3VdbeBooleanValue(Mem *pMem, int ifNull){
- if( pMem->flags & MEM_Int ) return pMem->u.i!=0;
+ testcase( pMem->flags & MEM_IntReal );
+ if( pMem->flags & (MEM_Int|MEM_IntReal) ) return pMem->u.i!=0;
if( pMem->flags & MEM_Null ) return ifNull;
return sqlite3VdbeRealValue(pMem)!=0.0;
}
@@ -74320,17 +77705,21 @@ SQLITE_PRIVATE int sqlite3VdbeMemRealify(Mem *pMem){
/* Compare a floating point value to an integer. Return true if the two
** values are the same within the precision of the floating point value.
**
+** This function assumes that i was obtained by assignment from r1.
+**
** For some versions of GCC on 32-bit machines, if you do the more obvious
** comparison of "r1==(double)i" you sometimes get an answer of false even
** though the r1 and (double)i values are bit-for-bit the same.
*/
-static int sqlite3RealSameAsInt(double r1, sqlite3_int64 i){
+SQLITE_PRIVATE int sqlite3RealSameAsInt(double r1, sqlite3_int64 i){
double r2 = (double)i;
- return memcmp(&r1, &r2, sizeof(r1))==0;
+ return r1==0.0
+ || (memcmp(&r1, &r2, sizeof(r1))==0
+ && i >= -2251799813685248LL && i < 2251799813685248LL);
}
/*
-** Convert pMem so that it has types MEM_Real or MEM_Int or both.
+** Convert pMem so that it has type MEM_Real or MEM_Int.
** Invalidate any prior representations.
**
** Every effort is made to force the conversion, even if the input
@@ -74338,25 +77727,26 @@ static int sqlite3RealSameAsInt(double r1, sqlite3_int64 i){
** as much of the string as we can and ignore the rest.
*/
SQLITE_PRIVATE int sqlite3VdbeMemNumerify(Mem *pMem){
- if( (pMem->flags & (MEM_Int|MEM_Real|MEM_Null))==0 ){
+ testcase( pMem->flags & MEM_Int );
+ testcase( pMem->flags & MEM_Real );
+ testcase( pMem->flags & MEM_IntReal );
+ testcase( pMem->flags & MEM_Null );
+ if( (pMem->flags & (MEM_Int|MEM_Real|MEM_IntReal|MEM_Null))==0 ){
int rc;
+ sqlite3_int64 ix;
assert( (pMem->flags & (MEM_Blob|MEM_Str))!=0 );
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
- rc = sqlite3Atoi64(pMem->z, &pMem->u.i, pMem->n, pMem->enc);
- if( rc==0 ){
+ rc = sqlite3AtoF(pMem->z, &pMem->u.r, pMem->n, pMem->enc);
+ if( ((rc==0 || rc==1) && sqlite3Atoi64(pMem->z, &ix, pMem->n, pMem->enc)<=1)
+ || sqlite3RealSameAsInt(pMem->u.r, (ix = (i64)pMem->u.r))
+ ){
+ pMem->u.i = ix;
MemSetTypeFlag(pMem, MEM_Int);
}else{
- i64 i = pMem->u.i;
- sqlite3AtoF(pMem->z, &pMem->u.r, pMem->n, pMem->enc);
- if( rc==1 && sqlite3RealSameAsInt(pMem->u.r, i) ){
- pMem->u.i = i;
- MemSetTypeFlag(pMem, MEM_Int);
- }else{
- MemSetTypeFlag(pMem, MEM_Real);
- }
+ MemSetTypeFlag(pMem, MEM_Real);
}
}
- assert( (pMem->flags & (MEM_Int|MEM_Real|MEM_Null))!=0 );
+ assert( (pMem->flags & (MEM_Int|MEM_Real|MEM_IntReal|MEM_Null))!=0 );
pMem->flags &= ~(MEM_Str|MEM_Blob|MEM_Zero);
return SQLITE_OK;
}
@@ -74368,8 +77758,8 @@ SQLITE_PRIVATE int sqlite3VdbeMemNumerify(Mem *pMem){
** affinity even if that results in loss of data. This routine is
** used (for example) to implement the SQL "cast()" operator.
*/
-SQLITE_PRIVATE void sqlite3VdbeMemCast(Mem *pMem, u8 aff, u8 encoding){
- if( pMem->flags & MEM_Null ) return;
+SQLITE_PRIVATE int sqlite3VdbeMemCast(Mem *pMem, u8 aff, u8 encoding){
+ if( pMem->flags & MEM_Null ) return SQLITE_OK;
switch( aff ){
case SQLITE_AFF_BLOB: { /* Really a cast to BLOB */
if( (pMem->flags & MEM_Blob)==0 ){
@@ -74399,10 +77789,11 @@ SQLITE_PRIVATE void sqlite3VdbeMemCast(Mem *pMem, u8 aff, u8 encoding){
pMem->flags |= (pMem->flags&MEM_Blob)>>3;
sqlite3ValueApplyAffinity(pMem, SQLITE_AFF_TEXT, encoding);
assert( pMem->flags & MEM_Str || pMem->db->mallocFailed );
- pMem->flags &= ~(MEM_Int|MEM_Real|MEM_Blob|MEM_Zero);
- break;
+ pMem->flags &= ~(MEM_Int|MEM_Real|MEM_IntReal|MEM_Blob|MEM_Zero);
+ return sqlite3VdbeChangeEncoding(pMem, encoding);
}
}
+ return SQLITE_OK;
}
/*
@@ -74438,7 +77829,7 @@ SQLITE_PRIVATE void sqlite3VdbeMemSetNull(Mem *pMem){
}
}
SQLITE_PRIVATE void sqlite3ValueSetNull(sqlite3_value *p){
- sqlite3VdbeMemSetNull((Mem*)p);
+ sqlite3VdbeMemSetNull((Mem*)p);
}
/*
@@ -74559,7 +77950,7 @@ SQLITE_PRIVATE int sqlite3VdbeMemTooBig(Mem *p){
}
return n>p->db->aLimit[SQLITE_LIMIT_LENGTH];
}
- return 0;
+ return 0;
}
#ifdef SQLITE_DEBUG
@@ -74568,26 +77959,28 @@ SQLITE_PRIVATE int sqlite3VdbeMemTooBig(Mem *p){
** its link to a shallow copy and by marking any current shallow
** copies of this cell as invalid.
**
-** This is used for testing and debugging only - to make sure shallow
-** copies are not misused.
+** This is used for testing and debugging only - to help ensure that shallow
+** copies (created by OP_SCopy) are not misused.
*/
SQLITE_PRIVATE void sqlite3VdbeMemAboutToChange(Vdbe *pVdbe, Mem *pMem){
int i;
Mem *pX;
- for(i=0, pX=pVdbe->aMem; inMem; i++, pX++){
+ for(i=1, pX=pVdbe->aMem+1; inMem; i++, pX++){
if( pX->pScopyFrom==pMem ){
- /* If pX is marked as a shallow copy of pMem, then verify that
+ u16 mFlags;
+ if( pVdbe->db->flags & SQLITE_VdbeTrace ){
+ sqlite3DebugPrintf("Invalidate R[%d] due to change in R[%d]\n",
+ (int)(pX - pVdbe->aMem), (int)(pMem - pVdbe->aMem));
+ }
+ /* If pX is marked as a shallow copy of pMem, then try to verify that
** no significant changes have been made to pX since the OP_SCopy.
** A significant change would indicated a missed call to this
** function for pX. Minor changes, such as adding or removing a
** dual type, are allowed, as long as the underlying value is the
** same. */
- u16 mFlags = pMem->flags & pX->flags & pX->mScopyFlags;
- assert( (mFlags&MEM_Int)==0 || pMem->u.i==pX->u.i );
- assert( (mFlags&MEM_Real)==0 || pMem->u.r==pX->u.r );
- assert( (mFlags&MEM_Str)==0 || (pMem->n==pX->n && pMem->z==pX->z) );
- assert( (mFlags&MEM_Blob)==0 || sqlite3BlobCompare(pMem,pX)==0 );
-
+ mFlags = pMem->flags & pX->flags & pX->mScopyFlags;
+ assert( (mFlags&(MEM_Int|MEM_IntReal))==0 || pMem->u.i==pX->u.i );
+
/* pMem is the register that is changing. But also mark pX as
** undefined so that we can quickly detect the shallow-copy error */
pX->flags = MEM_Undefined;
@@ -74598,7 +77991,6 @@ SQLITE_PRIVATE void sqlite3VdbeMemAboutToChange(Vdbe *pVdbe, Mem *pMem){
}
#endif /* SQLITE_DEBUG */
-
/*
** Make an shallow copy of pFrom into pTo. Prior contents of
** pTo are freed. The pFrom->z field is not duplicated. If
@@ -74664,8 +78056,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.
**
@@ -74678,11 +78070,11 @@ SQLITE_PRIVATE void sqlite3VdbeMemMove(Mem *pTo, Mem *pFrom){
SQLITE_PRIVATE int sqlite3VdbeMemSetStr(
Mem *pMem, /* Memory cell to set to string value */
const char *z, /* String pointer */
- int n, /* Bytes in string, or negative */
+ i64 n, /* Bytes in string, or negative */
u8 enc, /* Encoding of z. 0 for BLOBs */
void (*xDel)(void*) /* Destructor function */
){
- int nByte = n; /* New value for pMem->n */
+ i64 nByte = n; /* New value for pMem->n */
int iLimit; /* Maximum allowed string or blob size */
u16 flags = 0; /* New value for pMem->flags */
@@ -74704,8 +78096,7 @@ SQLITE_PRIVATE int sqlite3VdbeMemSetStr(
if( nByte<0 ){
assert( enc!=0 );
if( enc==SQLITE_UTF8 ){
- nByte = 0x7fffffff & (int)strlen(z);
- if( nByte>iLimit ) nByte = iLimit+1;
+ nByte = strlen(z);
}else{
for(nByte=0; nByte<=iLimit && (z[nByte] | z[nByte+1]); nByte+=2){}
}
@@ -74717,43 +78108,53 @@ SQLITE_PRIVATE int sqlite3VdbeMemSetStr(
** management (one of MEM_Dyn or MEM_Static).
*/
if( xDel==SQLITE_TRANSIENT ){
- int nAlloc = nByte;
+ i64 nAlloc = nByte;
if( flags&MEM_Term ){
nAlloc += (enc==SQLITE_UTF8?1:2);
}
if( nByte>iLimit ){
- return SQLITE_TOOBIG;
+ return sqlite3ErrorToParser(pMem->db, SQLITE_TOOBIG);
}
testcase( nAlloc==0 );
testcase( nAlloc==31 );
testcase( nAlloc==32 );
- if( sqlite3VdbeMemClearAndResize(pMem, MAX(nAlloc,32)) ){
+ if( sqlite3VdbeMemClearAndResize(pMem, (int)MAX(nAlloc,32)) ){
return SQLITE_NOMEM_BKPT;
}
memcpy(pMem->z, z, nAlloc);
- }else if( xDel==SQLITE_DYNAMIC ){
- sqlite3VdbeMemRelease(pMem);
- pMem->zMalloc = pMem->z = (char *)z;
- pMem->szMalloc = sqlite3DbMallocSize(pMem->db, pMem->zMalloc);
}else{
sqlite3VdbeMemRelease(pMem);
pMem->z = (char *)z;
- pMem->xDel = xDel;
- flags |= ((xDel==SQLITE_STATIC)?MEM_Static:MEM_Dyn);
+ if( xDel==SQLITE_DYNAMIC ){
+ pMem->zMalloc = pMem->z;
+ pMem->szMalloc = sqlite3DbMallocSize(pMem->db, pMem->zMalloc);
+ }else{
+ pMem->xDel = xDel;
+ flags |= ((xDel==SQLITE_STATIC)?MEM_Static:MEM_Dyn);
+ }
}
- pMem->n = nByte;
+ pMem->n = (int)(nByte & 0x7fffffff);
pMem->flags = flags;
- pMem->enc = (enc==0 ? SQLITE_UTF8 : enc);
+ if( enc ){
+ pMem->enc = enc;
+#ifdef SQLITE_ENABLE_SESSION
+ }else if( pMem->db==0 ){
+ pMem->enc = SQLITE_UTF8;
+#endif
+ }else{
+ assert( pMem->db!=0 );
+ pMem->enc = ENC(pMem->db);
+ }
#ifndef SQLITE_OMIT_UTF16
- if( pMem->enc!=SQLITE_UTF8 && sqlite3VdbeMemHandleBom(pMem) ){
+ if( enc>SQLITE_UTF8 && sqlite3VdbeMemHandleBom(pMem) ){
return SQLITE_NOMEM_BKPT;
}
#endif
if( nByte>iLimit ){
- return SQLITE_TOOBIG;
+ return sqlite3ErrorToParser(pMem->db, SQLITE_TOOBIG);
}
return SQLITE_OK;
@@ -74774,7 +78175,7 @@ SQLITE_PRIVATE int sqlite3VdbeMemSetStr(
** If this routine fails for any reason (malloc returns NULL or unable
** to read from the disk) then the pMem is left in an inconsistent state.
*/
-static SQLITE_NOINLINE int vdbeMemFromBtreeResize(
+SQLITE_PRIVATE int sqlite3VdbeMemFromBtree(
BtCursor *pCur, /* Cursor pointing at record to retrieve. */
u32 offset, /* Offset from the start of data to return bytes from. */
u32 amt, /* Number of bytes to return. */
@@ -74782,6 +78183,9 @@ static SQLITE_NOINLINE int vdbeMemFromBtreeResize(
){
int rc;
pMem->flags = MEM_Null;
+ if( sqlite3BtreeMaxRecordSize(pCur)z);
if( rc==SQLITE_OK ){
@@ -74794,31 +78198,28 @@ static SQLITE_NOINLINE int vdbeMemFromBtreeResize(
}
return rc;
}
-SQLITE_PRIVATE int sqlite3VdbeMemFromBtree(
+SQLITE_PRIVATE int sqlite3VdbeMemFromBtreeZeroOffset(
BtCursor *pCur, /* Cursor pointing at record to retrieve. */
- u32 offset, /* Offset from the start of data to return bytes from. */
u32 amt, /* Number of bytes to return. */
Mem *pMem /* OUT: Return data in this Mem structure. */
){
- char *zData; /* Data from the btree layer */
u32 available = 0; /* Number of bytes available on the local btree page */
int rc = SQLITE_OK; /* Return code */
assert( sqlite3BtreeCursorIsValid(pCur) );
assert( !VdbeMemDynamic(pMem) );
- /* 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( !sqlite3VdbeMemIsRowSet(pMem) );
- zData = (char *)sqlite3BtreePayloadFetch(pCur, &available);
- assert( zData!=0 );
+ pMem->z = (char *)sqlite3BtreePayloadFetch(pCur, &available);
+ assert( pMem->z!=0 );
- if( offset+amt<=available ){
- pMem->z = &zData[offset];
+ if( amt<=available ){
pMem->flags = MEM_Blob|MEM_Ephem;
pMem->n = (int)amt;
}else{
- rc = vdbeMemFromBtreeResize(pCur, offset, amt, pMem);
+ rc = sqlite3VdbeMemFromBtree(pCur, 0, amt, pMem);
}
return rc;
@@ -74855,7 +78256,7 @@ static SQLITE_NOINLINE const void *valueToText(sqlite3_value* pVal, u8 enc){
assert(pVal->enc==(enc & ~SQLITE_UTF16_ALIGNED) || pVal->db==0
|| pVal->db->mallocFailed );
if( pVal->enc==(enc & ~SQLITE_UTF16_ALIGNED) ){
- assert( sqlite3VdbeMemConsistentDualRep(pVal) );
+ assert( sqlite3VdbeMemValidStrRep(pVal) );
return pVal->z;
}else{
return 0;
@@ -74878,7 +78279,7 @@ SQLITE_PRIVATE const void *sqlite3ValueText(sqlite3_value* pVal, u8 enc){
assert( (enc&3)==(enc&~SQLITE_UTF16_ALIGNED) );
assert( !sqlite3VdbeMemIsRowSet(pVal) );
if( (pVal->flags&(MEM_Str|MEM_Term))==(MEM_Str|MEM_Term) && pVal->enc==enc ){
- assert( sqlite3VdbeMemConsistentDualRep(pVal) );
+ assert( sqlite3VdbeMemValidStrRep(pVal) );
return pVal->z;
}
if( pVal->flags&MEM_Null ){
@@ -74900,7 +78301,7 @@ SQLITE_PRIVATE sqlite3_value *sqlite3ValueNew(sqlite3 *db){
}
/*
-** Context object passed by sqlite3Stat4ProbeSetValue() through to
+** Context object passed by sqlite3Stat4ProbeSetValue() through to
** valueNew(). See comments above valueNew() for details.
*/
struct ValueNewStat4Ctx {
@@ -74915,14 +78316,14 @@ struct ValueNewStat4Ctx {
** the second argument to this function is NULL, the object is allocated
** by calling sqlite3ValueNew().
**
-** Otherwise, if the second argument is non-zero, then this function is
+** Otherwise, if the second argument is non-zero, then this function is
** being called indirectly by sqlite3Stat4ProbeSetValue(). If it has not
-** already been allocated, allocate the UnpackedRecord structure that
+** already been allocated, allocate the UnpackedRecord structure that
** that function will return to its caller here. Then return a pointer to
** an sqlite3_value within the UnpackedRecord.a[] array.
*/
static sqlite3_value *valueNew(sqlite3 *db, struct ValueNewStat4Ctx *p){
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
+#ifdef SQLITE_ENABLE_STAT4
if( p ){
UnpackedRecord *pRec = p->ppRec[0];
@@ -74931,7 +78332,7 @@ static sqlite3_value *valueNew(sqlite3 *db, struct ValueNewStat4Ctx *p){
int nByte; /* Bytes of space to allocate */
int i; /* Counter variable */
int nCol = pIdx->nColumn; /* Number of index columns including rowid */
-
+
nByte = sizeof(Mem) * nCol + ROUND8(sizeof(UnpackedRecord));
pRec = (UnpackedRecord*)sqlite3DbMallocZero(db, nByte);
if( pRec ){
@@ -74952,13 +78353,13 @@ static sqlite3_value *valueNew(sqlite3 *db, struct ValueNewStat4Ctx *p){
if( pRec==0 ) return 0;
p->ppRec[0] = pRec;
}
-
+
pRec->nField = p->iVal+1;
return &pRec->aMem[p->iVal];
}
#else
UNUSED_PARAMETER(p);
-#endif /* defined(SQLITE_ENABLE_STAT3_OR_STAT4) */
+#endif /* defined(SQLITE_ENABLE_STAT4) */
return sqlite3ValueNew(db);
}
@@ -74971,18 +78372,18 @@ static sqlite3_value *valueNew(sqlite3 *db, struct ValueNewStat4Ctx *p){
** * the SQLITE_FUNC_NEEDCOLL function flag is not set,
**
** then this routine attempts to invoke the SQL function. Assuming no
-** error occurs, output parameter (*ppVal) is set to point to a value
+** error occurs, output parameter (*ppVal) is set to point to a value
** object containing the result before returning SQLITE_OK.
**
** Affinity aff is applied to the result of the function before returning.
-** If the result is a text value, the sqlite3_value object uses encoding
+** If the result is a text value, the sqlite3_value object uses encoding
** enc.
**
** If the conditions above are not met, this function returns SQLITE_OK
** and sets (*ppVal) to NULL. Or, if an error occurs, (*ppVal) is set to
** NULL and an SQLite error code returned.
*/
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
+#ifdef SQLITE_ENABLE_STAT4
static int valueFromFunction(
sqlite3 *db, /* The database connection */
Expr *p, /* The expression to evaluate */
@@ -75006,7 +78407,7 @@ static int valueFromFunction(
if( pList ) nVal = pList->nExpr;
pFunc = sqlite3FindFunction(db, p->u.zToken, nVal, enc, 0);
assert( pFunc );
- if( (pFunc->funcFlags & (SQLITE_FUNC_CONSTANT|SQLITE_FUNC_SLOCHNG))==0
+ if( (pFunc->funcFlags & (SQLITE_FUNC_CONSTANT|SQLITE_FUNC_SLOCHNG))==0
|| (pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL)
){
return SQLITE_OK;
@@ -75065,7 +78466,7 @@ static int valueFromFunction(
}
#else
# define valueFromFunction(a,b,c,d,e,f) SQLITE_OK
-#endif /* defined(SQLITE_ENABLE_STAT3_OR_STAT4) */
+#endif /* defined(SQLITE_ENABLE_STAT4) */
/*
** Extract a value from the supplied expression in the manner described
@@ -75094,7 +78495,7 @@ static int valueFromExpr(
assert( pExpr!=0 );
while( (op = pExpr->op)==TK_UPLUS || op==TK_SPAN ) pExpr = pExpr->pLeft;
-#if defined(SQLITE_ENABLE_STAT3_OR_STAT4)
+#if defined(SQLITE_ENABLE_STAT4)
if( op==TK_REGISTER ) op = pExpr->op2;
#else
if( NEVER(op==TK_REGISTER) ) op = pExpr->op2;
@@ -75143,20 +78544,29 @@ static int valueFromExpr(
}else{
sqlite3ValueApplyAffinity(pVal, affinity, SQLITE_UTF8);
}
- if( pVal->flags & (MEM_Int|MEM_Real) ) pVal->flags &= ~MEM_Str;
+ assert( (pVal->flags & MEM_IntReal)==0 );
+ if( pVal->flags & (MEM_Int|MEM_IntReal|MEM_Real) ){
+ testcase( pVal->flags & MEM_Int );
+ testcase( pVal->flags & MEM_Real );
+ pVal->flags &= ~MEM_Str;
+ }
if( enc!=SQLITE_UTF8 ){
rc = sqlite3VdbeChangeEncoding(pVal, enc);
}
}else if( op==TK_UMINUS ) {
/* This branch happens for multiple negative signs. Ex: -(-5) */
- if( SQLITE_OK==valueFromExpr(db,pExpr->pLeft,enc,affinity,&pVal,pCtx)
+ if( SQLITE_OK==valueFromExpr(db,pExpr->pLeft,enc,affinity,&pVal,pCtx)
&& pVal!=0
){
sqlite3VdbeMemNumerify(pVal);
if( pVal->flags & MEM_Real ){
pVal->u.r = -pVal->u.r;
}else if( pVal->u.i==SMALLEST_INT64 ){
+#ifndef SQLITE_OMIT_FLOATING_POINT
pVal->u.r = -(double)SMALLEST_INT64;
+#else
+ pVal->u.r = LARGEST_INT64;
+#endif
MemSetTypeFlag(pVal, MEM_Real);
}else{
pVal->u.i = -pVal->u.i;
@@ -75166,7 +78576,7 @@ static int valueFromExpr(
}else if( op==TK_NULL ){
pVal = valueNew(db, pCtx);
if( pVal==0 ) goto no_mem;
- sqlite3VdbeMemNumerify(pVal);
+ sqlite3VdbeMemSetNull(pVal);
}
#ifndef SQLITE_OMIT_BLOB_LITERAL
else if( op==TK_BLOB ){
@@ -75182,28 +78592,30 @@ static int valueFromExpr(
0, SQLITE_DYNAMIC);
}
#endif
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
+#ifdef SQLITE_ENABLE_STAT4
else if( op==TK_FUNCTION && pCtx!=0 ){
rc = valueFromFunction(db, pExpr, enc, affinity, &pVal, pCtx);
}
#endif
else if( op==TK_TRUEFALSE ){
- pVal = valueNew(db, pCtx);
- pVal->flags = MEM_Int;
- pVal->u.i = pExpr->u.zToken[4]==0;
+ pVal = valueNew(db, pCtx);
+ if( pVal ){
+ pVal->flags = MEM_Int;
+ pVal->u.i = pExpr->u.zToken[4]==0;
+ }
}
*ppVal = pVal;
return rc;
no_mem:
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
+#ifdef SQLITE_ENABLE_STAT4
if( pCtx==0 || pCtx->pParse->nErr==0 )
#endif
sqlite3OomFault(db);
sqlite3DbFree(db, zVal);
assert( *ppVal==0 );
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
+#ifdef SQLITE_ENABLE_STAT4
if( pCtx==0 ) sqlite3ValueFree(pVal);
#else
assert( pCtx==0 ); sqlite3ValueFree(pVal);
@@ -75231,56 +78643,7 @@ SQLITE_PRIVATE int sqlite3ValueFromExpr(
return pExpr ? valueFromExpr(db, pExpr, enc, affinity, ppVal, 0) : 0;
}
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
-/*
-** The implementation of the sqlite_record() function. This function accepts
-** a single argument of any type. The return value is a formatted database
-** record (a blob) containing the argument value.
-**
-** This is used to convert the value stored in the 'sample' column of the
-** sqlite_stat3 table to the record format SQLite uses internally.
-*/
-static void recordFunc(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- const int file_format = 1;
- u32 iSerial; /* Serial type */
- int nSerial; /* Bytes of space for iSerial as varint */
- u32 nVal; /* Bytes of space required for argv[0] */
- int nRet;
- sqlite3 *db;
- u8 *aRet;
-
- UNUSED_PARAMETER( argc );
- iSerial = sqlite3VdbeSerialType(argv[0], file_format, &nVal);
- nSerial = sqlite3VarintLen(iSerial);
- db = sqlite3_context_db_handle(context);
-
- nRet = 1 + nSerial + nVal;
- aRet = sqlite3DbMallocRawNN(db, nRet);
- if( aRet==0 ){
- sqlite3_result_error_nomem(context);
- }else{
- aRet[0] = nSerial+1;
- putVarint32(&aRet[1], iSerial);
- sqlite3VdbeSerialPut(&aRet[1+nSerial], argv[0], iSerial);
- sqlite3_result_blob(context, aRet, nRet, SQLITE_TRANSIENT);
- sqlite3DbFreeNN(db, aRet);
- }
-}
-
-/*
-** Register built-in functions used to help read ANALYZE data.
-*/
-SQLITE_PRIVATE void sqlite3AnalyzeFunctions(void){
- static FuncDef aAnalyzeTableFuncs[] = {
- FUNCTION(sqlite_record, 1, 0, 0, recordFunc),
- };
- sqlite3InsertBuiltinFuncs(aAnalyzeTableFuncs, ArraySize(aAnalyzeTableFuncs));
-}
-
+#ifdef SQLITE_ENABLE_STAT4
/*
** Attempt to extract a value from pExpr and use it to construct *ppVal.
**
@@ -75341,8 +78704,8 @@ static int stat4ValueFromExpr(
}
/*
-** This function is used to allocate and populate UnpackedRecord
-** structures intended to be compared against sample index keys stored
+** This function is used to allocate and populate UnpackedRecord
+** structures intended to be compared against sample index keys stored
** in the sqlite_stat4 table.
**
** A single call to this function populates zero or more fields of the
@@ -75353,14 +78716,14 @@ static int stat4ValueFromExpr(
**
** * The expression is a bound variable, and this is a reprepare, or
**
-** * The sqlite3ValueFromExpr() function is able to extract a value
+** * The sqlite3ValueFromExpr() function is able to extract a value
** from the expression (i.e. the expression is a literal value).
**
** Or, if pExpr is a TK_VECTOR, one field is populated for each of the
** vector components that match either of the two latter criteria listed
** above.
**
-** Before any value is appended to the record, the affinity of the
+** Before any value is appended to the record, the affinity of the
** corresponding column within index pIdx is applied to it. Before
** this function returns, output parameter *pnExtract is set to the
** number of values appended to the record.
@@ -75411,9 +78774,9 @@ SQLITE_PRIVATE int sqlite3Stat4ProbeSetValue(
/*
** Attempt to extract a value from expression pExpr using the methods
-** as described for sqlite3Stat4ProbeSetValue() above.
+** as described for sqlite3Stat4ProbeSetValue() above.
**
-** If successful, set *ppVal to point to a new value object and return
+** If successful, set *ppVal to point to a new value object and return
** SQLITE_OK. If no value can be extracted, but no other error occurs
** (e.g. OOM), return SQLITE_OK and set *ppVal to NULL. Or, if an error
** does occur, return an SQLite error code. The final value of *ppVal
@@ -75433,7 +78796,7 @@ SQLITE_PRIVATE int sqlite3Stat4ValueFromExpr(
** the column value into *ppVal. If *ppVal is initially NULL then a new
** sqlite3_value object is allocated.
**
-** If *ppVal is initially NULL then the caller is responsible for
+** If *ppVal is initially NULL then the caller is responsible for
** ensuring that the value written into *ppVal is eventually freed.
*/
SQLITE_PRIVATE int sqlite3Stat4Column(
@@ -75557,11 +78920,15 @@ SQLITE_PRIVATE int sqlite3ValueBytes(sqlite3_value *pVal, u8 enc){
**
*************************************************************************
** This file contains code used for creating, destroying, and populating
-** a VDBE (or an "sqlite3_stmt" as it is known to the outside world.)
+** a VDBE (or an "sqlite3_stmt" as it is known to the outside world.)
*/
/* #include "sqliteInt.h" */
/* #include "vdbeInt.h" */
+/* Forward references */
+static void freeEphemeralFunction(sqlite3 *db, FuncDef *pDef);
+static void vdbeFreeOpArray(sqlite3 *, Op *, int);
+
/*
** Create a new virtual database engine.
*/
@@ -75578,17 +78945,24 @@ SQLITE_PRIVATE Vdbe *sqlite3VdbeCreate(Parse *pParse){
p->pNext = db->pVdbe;
p->pPrev = 0;
db->pVdbe = p;
- p->magic = VDBE_MAGIC_INIT;
+ p->iVdbeMagic = VDBE_MAGIC_INIT;
p->pParse = pParse;
pParse->pVdbe = p;
assert( pParse->aLabel==0 );
assert( pParse->nLabel==0 );
- assert( pParse->nOpAlloc==0 );
+ assert( p->nOpAlloc==0 );
assert( pParse->szOpAlloc==0 );
sqlite3VdbeAddOp2(p, OP_Init, 0, 1);
return p;
}
+/*
+** Return the Parse object that owns a Vdbe object.
+*/
+SQLITE_PRIVATE Parse *sqlite3VdbeParser(Vdbe *p){
+ return p->pParse;
+}
+
/*
** Change the error string stored in Vdbe.zErrMsg
*/
@@ -75613,6 +78987,43 @@ SQLITE_PRIVATE void sqlite3VdbeSetSql(Vdbe *p, const char *z, int n, u8 prepFlag
p->zSql = sqlite3DbStrNDup(p->db, z, n);
}
+#ifdef SQLITE_ENABLE_NORMALIZE
+/*
+** Add a new element to the Vdbe->pDblStr list.
+*/
+SQLITE_PRIVATE void sqlite3VdbeAddDblquoteStr(sqlite3 *db, Vdbe *p, const char *z){
+ if( p ){
+ int n = sqlite3Strlen30(z);
+ DblquoteStr *pStr = sqlite3DbMallocRawNN(db,
+ sizeof(*pStr)+n+1-sizeof(pStr->z));
+ if( pStr ){
+ pStr->pNextStr = p->pDblStr;
+ p->pDblStr = pStr;
+ memcpy(pStr->z, z, n+1);
+ }
+ }
+}
+#endif
+
+#ifdef SQLITE_ENABLE_NORMALIZE
+/*
+** zId of length nId is a double-quoted identifier. Check to see if
+** that identifier is really used as a string literal.
+*/
+SQLITE_PRIVATE int sqlite3VdbeUsesDoubleQuotedString(
+ Vdbe *pVdbe, /* The prepared statement */
+ const char *zId /* The double-quoted identifier, already dequoted */
+){
+ DblquoteStr *pStr;
+ assert( zId!=0 );
+ if( pVdbe->pDblStr==0 ) return 0;
+ for(pStr=pVdbe->pDblStr; pStr; pStr=pStr->pNextStr){
+ if( strcmp(zId, pStr->z)==0 ) return 1;
+ }
+ return 0;
+}
+#endif
+
/*
** Swap all content between two VDBE structures.
*/
@@ -75632,6 +79043,11 @@ SQLITE_PRIVATE void sqlite3VdbeSwap(Vdbe *pA, Vdbe *pB){
zTmp = pA->zSql;
pA->zSql = pB->zSql;
pB->zSql = zTmp;
+#ifdef SQLITE_ENABLE_NORMALIZE
+ zTmp = pA->zNormSql;
+ pA->zNormSql = pB->zNormSql;
+ pB->zNormSql = zTmp;
+#endif
pB->expmask = pA->expmask;
pB->prepFlags = pA->prepFlags;
memcpy(pB->aCounter, pA->aCounter, sizeof(pB->aCounter));
@@ -75639,13 +79055,13 @@ SQLITE_PRIVATE void sqlite3VdbeSwap(Vdbe *pA, Vdbe *pB){
}
/*
-** Resize the Vdbe.aOp array so that it is at least nOp elements larger
+** Resize the Vdbe.aOp array so that it is at least nOp elements larger
** than its current size. nOp is guaranteed to be less than or equal
** to 1024/sizeof(Op).
**
** If an out-of-memory error occurs while resizing the array, return
-** SQLITE_NOMEM. In this case Vdbe.aOp and Parse.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 *v, int nOp){
@@ -75653,16 +79069,18 @@ static int growOpArray(Vdbe *v, int nOp){
Parse *p = v->pParse;
/* The SQLITE_TEST_REALLOC_STRESS compile-time option is designed to force
- ** more frequent reallocs and hence provide more opportunities for
+ ** more frequent reallocs and hence provide more opportunities for
** simulated OOM faults. SQLITE_TEST_REALLOC_STRESS is generally used
** during testing only. With SQLITE_TEST_REALLOC_STRESS grow the op array
** by the minimum* amount required until the size reaches 512. Normal
** operation (without SQLITE_TEST_REALLOC_STRESS) is to double the current
** size of the op array or add 1KB of space, whichever is smaller. */
#ifdef SQLITE_TEST_REALLOC_STRESS
- int nNew = (p->nOpAlloc>=512 ? p->nOpAlloc*2 : p->nOpAlloc+nOp);
+ sqlite3_int64 nNew = (v->nOpAlloc>=512 ? 2*(sqlite3_int64)v->nOpAlloc
+ : (sqlite3_int64)v->nOpAlloc+nOp);
#else
- int nNew = (p->nOpAlloc ? p->nOpAlloc*2 : (int)(1024/sizeof(Op)));
+ sqlite3_int64 nNew = (v->nOpAlloc ? 2*(sqlite3_int64)v->nOpAlloc
+ : (sqlite3_int64)(1024/sizeof(Op)));
UNUSED_PARAMETER(nOp);
#endif
@@ -75673,11 +79091,11 @@ static int growOpArray(Vdbe *v, int nOp){
}
assert( nOp<=(1024/sizeof(Op)) );
- assert( nNew>=(p->nOpAlloc+nOp) );
+ assert( nNew>=(v->nOpAlloc+nOp) );
pNew = sqlite3DbRealloc(p->db, v->aOp, nNew*sizeof(Op));
if( pNew ){
p->szOpAlloc = sqlite3DbMallocSize(p->db, pNew);
- p->nOpAlloc = p->szOpAlloc/sizeof(Op);
+ v->nOpAlloc = p->szOpAlloc/sizeof(Op);
v->aOp = pNew;
}
return (pNew ? SQLITE_OK : SQLITE_NOMEM_BKPT);
@@ -75686,9 +79104,16 @@ static int growOpArray(Vdbe *v, int nOp){
#ifdef SQLITE_DEBUG
/* This routine is just a convenient place to set a breakpoint that will
** fire after each opcode is inserted and displayed using
-** "PRAGMA vdbe_addoptrace=on".
+** "PRAGMA vdbe_addoptrace=on". Parameters "pc" (program counter) and
+** pOp are available to make the breakpoint conditional.
+**
+** Other useful labels for breakpoints include:
+** test_trace_breakpoint(pc,pOp)
+** sqlite3CorruptError(lineno)
+** sqlite3MisuseError(lineno)
+** sqlite3CantopenError(lineno)
*/
-static void test_addop_breakpoint(void){
+static void test_addop_breakpoint(int pc, Op *pOp){
static int n = 0;
n++;
}
@@ -75711,9 +79136,9 @@ static void test_addop_breakpoint(void){
** operand.
*/
static SQLITE_NOINLINE int growOp3(Vdbe *p, int op, int p1, int p2, int p3){
- assert( p->pParse->nOpAlloc<=p->nOp );
+ assert( p->nOpAlloc<=p->nOp );
if( growOpArray(p, 1) ) return 1;
- assert( p->pParse->nOpAlloc>p->nOp );
+ assert( p->nOpAlloc>p->nOp );
return sqlite3VdbeAddOp3(p, op, p1, p2, p3);
}
SQLITE_PRIVATE int sqlite3VdbeAddOp3(Vdbe *p, int op, int p1, int p2, int p3){
@@ -75721,9 +79146,9 @@ SQLITE_PRIVATE int sqlite3VdbeAddOp3(Vdbe *p, int op, int p1, int p2, int p3){
VdbeOp *pOp;
i = p->nOp;
- assert( p->magic==VDBE_MAGIC_INIT );
+ assert( p->iVdbeMagic==VDBE_MAGIC_INIT );
assert( op>=0 && op<0xff );
- if( p->pParse->nOpAlloc<=i ){
+ if( p->nOpAlloc<=i ){
return growOp3(p, op, p1, p2, p3);
}
p->nOp++;
@@ -75741,7 +79166,7 @@ SQLITE_PRIVATE int sqlite3VdbeAddOp3(Vdbe *p, int op, int p1, int p2, int p3){
#ifdef SQLITE_DEBUG
if( p->db->flags & SQLITE_VdbeAddopTrace ){
sqlite3VdbePrintOp(0, i, &p->aOp[i]);
- test_addop_breakpoint();
+ test_addop_breakpoint(i, &p->aOp[i]);
}
#endif
#ifdef VDBE_PROFILE
@@ -75824,6 +79249,49 @@ SQLITE_PRIVATE int sqlite3VdbeAddOp4(
return addr;
}
+/*
+** Add an OP_Function or OP_PureFunc opcode.
+**
+** The eCallCtx argument is information (typically taken from Expr.op2)
+** that describes the calling context of the function. 0 means a general
+** function call. NC_IsCheck means called by a check constraint,
+** NC_IdxExpr means called as part of an index expression. NC_PartIdx
+** means in the WHERE clause of a partial index. NC_GenCol means called
+** while computing a generated column value. 0 is the usual case.
+*/
+SQLITE_PRIVATE int sqlite3VdbeAddFunctionCall(
+ Parse *pParse, /* Parsing context */
+ int p1, /* Constant argument mask */
+ int p2, /* First argument register */
+ int p3, /* Register into which results are written */
+ int nArg, /* Number of argument */
+ const FuncDef *pFunc, /* The function to be invoked */
+ int eCallCtx /* Calling context */
+){
+ Vdbe *v = pParse->pVdbe;
+ int nByte;
+ int addr;
+ sqlite3_context *pCtx;
+ assert( v );
+ nByte = sizeof(*pCtx) + (nArg-1)*sizeof(sqlite3_value*);
+ pCtx = sqlite3DbMallocRawNN(pParse->db, nByte);
+ if( pCtx==0 ){
+ assert( pParse->db->mallocFailed );
+ freeEphemeralFunction(pParse->db, (FuncDef*)pFunc);
+ return 0;
+ }
+ pCtx->pOut = 0;
+ pCtx->pFunc = (FuncDef*)pFunc;
+ pCtx->pVdbe = 0;
+ pCtx->isError = 0;
+ pCtx->argc = nArg;
+ pCtx->iOp = sqlite3VdbeCurrentAddr(v);
+ addr = sqlite3VdbeAddOp4(v, eCallCtx ? OP_PureFunc : OP_Function,
+ p1, p2, p3, (char*)pCtx, P4_FUNCCTX);
+ sqlite3VdbeChangeP5(v, eCallCtx & NC_SelfRef);
+ return addr;
+}
+
/*
** Add an opcode that includes the p4 value with a P4_INT64 or
** P4_REAL type.
@@ -75854,6 +79322,17 @@ SQLITE_PRIVATE int sqlite3VdbeExplainParent(Parse *pParse){
return pOp->p2;
}
+/*
+** Set a debugger breakpoint on the following routine in order to
+** monitor the EXPLAIN QUERY PLAN code generation.
+*/
+#if defined(SQLITE_DEBUG)
+SQLITE_PRIVATE void sqlite3ExplainBreakpoint(const char *z1, const char *z2){
+ (void)z1;
+ (void)z2;
+}
+#endif
+
/*
** Add a new OP_Explain opcode.
**
@@ -75861,7 +79340,12 @@ SQLITE_PRIVATE int sqlite3VdbeExplainParent(Parse *pParse){
** subsequent Explains until sqlite3VdbeExplainPop() is called.
*/
SQLITE_PRIVATE void sqlite3VdbeExplain(Parse *pParse, u8 bPush, const char *zFmt, ...){
- if( pParse->explain==2 ){
+#ifndef SQLITE_DEBUG
+ /* Always include the OP_Explain opcodes if SQLITE_DEBUG is defined.
+ ** But omit them (for performance) during production builds */
+ if( pParse->explain==2 )
+#endif
+ {
char *zMsg;
Vdbe *v;
va_list ap;
@@ -75873,7 +79357,10 @@ SQLITE_PRIVATE void sqlite3VdbeExplain(Parse *pParse, u8 bPush, const char *zFmt
iThis = v->nOp;
sqlite3VdbeAddOp4(v, OP_Explain, iThis, pParse->addrExplain, 0,
zMsg, P4_DYNAMIC);
- if( bPush) pParse->addrExplain = iThis;
+ sqlite3ExplainBreakpoint(bPush?"PUSH":"", sqlite3VdbeGetOp(v,-1)->p4.z);
+ if( bPush){
+ pParse->addrExplain = iThis;
+ }
}
}
@@ -75881,6 +79368,7 @@ SQLITE_PRIVATE void sqlite3VdbeExplain(Parse *pParse, u8 bPush, const char *zFmt
** Pop the EXPLAIN QUERY PLAN stack one level.
*/
SQLITE_PRIVATE void sqlite3VdbeExplainPop(Parse *pParse){
+ sqlite3ExplainBreakpoint("POP", 0);
pParse->addrExplain = sqlite3VdbeExplainParent(pParse);
}
#endif /* SQLITE_OMIT_EXPLAIN */
@@ -75893,10 +79381,12 @@ SQLITE_PRIVATE void sqlite3VdbeExplainPop(Parse *pParse){
** The zWhere string must have been obtained from sqlite3_malloc().
** This routine will take ownership of the allocated memory.
*/
-SQLITE_PRIVATE void sqlite3VdbeAddParseSchemaOp(Vdbe *p, int iDb, char *zWhere){
+SQLITE_PRIVATE void sqlite3VdbeAddParseSchemaOp(Vdbe *p, int iDb, char *zWhere, u16 p5){
int j;
sqlite3VdbeAddOp4(p, OP_ParseSchema, iDb, 0, 0, zWhere, P4_DYNAMIC);
+ sqlite3VdbeChangeP5(p, p5);
for(j=0; jdb->nDb; j++) sqlite3VdbeUsesBtree(p, j);
+ sqlite3MayAbort(p->pParse);
}
/*
@@ -75945,21 +79435,22 @@ SQLITE_PRIVATE void sqlite3VdbeEndCoroutine(Vdbe *v, int regYield){
** The VDBE knows that a P2 value is a label because labels are
** always negative and P2 values are suppose to be non-negative.
** Hence, a negative P2 value is a label that has yet to be resolved.
+** (Later:) This is only true for opcodes that have the OPFLG_JUMP
+** property.
**
-** Zero is returned if a malloc() fails.
+** Variable usage notes:
+**
+** Parse.aLabel[x] Stores the address that the x-th label resolves
+** into. For testing (SQLITE_DEBUG), unresolved
+** labels stores -1, but that is not required.
+** Parse.nLabelAlloc Number of slots allocated to Parse.aLabel[]
+** Parse.nLabel The *negative* of the number of labels that have
+** been issued. The negative is stored because
+** that gives a performance improvement over storing
+** the equivalent positive value.
*/
-SQLITE_PRIVATE int sqlite3VdbeMakeLabel(Vdbe *v){
- Parse *p = v->pParse;
- int i = p->nLabel++;
- assert( v->magic==VDBE_MAGIC_INIT );
- if( (i & (i-1))==0 ){
- p->aLabel = sqlite3DbReallocOrFree(p->db, p->aLabel,
- (i*2+1)*sizeof(p->aLabel[0]));
- }
- if( p->aLabel ){
- p->aLabel[i] = -1;
- }
- return ADDR(i);
+SQLITE_PRIVATE int sqlite3VdbeMakeLabel(Parse *pParse){
+ return --pParse->nLabel;
}
/*
@@ -75967,18 +79458,35 @@ SQLITE_PRIVATE int sqlite3VdbeMakeLabel(Vdbe *v){
** be inserted. The parameter "x" must have been obtained from
** a prior call to sqlite3VdbeMakeLabel().
*/
+static SQLITE_NOINLINE void resizeResolveLabel(Parse *p, Vdbe *v, int j){
+ int nNewSize = 10 - p->nLabel;
+ p->aLabel = sqlite3DbReallocOrFree(p->db, p->aLabel,
+ nNewSize*sizeof(p->aLabel[0]));
+ if( p->aLabel==0 ){
+ p->nLabelAlloc = 0;
+ }else{
+#ifdef SQLITE_DEBUG
+ int i;
+ for(i=p->nLabelAlloc; iaLabel[i] = -1;
+#endif
+ p->nLabelAlloc = nNewSize;
+ p->aLabel[j] = v->nOp;
+ }
+}
SQLITE_PRIVATE void sqlite3VdbeResolveLabel(Vdbe *v, int x){
Parse *p = v->pParse;
int j = ADDR(x);
- assert( v->magic==VDBE_MAGIC_INIT );
- assert( jnLabel );
+ assert( v->iVdbeMagic==VDBE_MAGIC_INIT );
+ assert( j<-p->nLabel );
assert( j>=0 );
- if( p->aLabel ){
#ifdef SQLITE_DEBUG
- if( p->db->flags & SQLITE_VdbeAddopTrace ){
- printf("RESOLVE LABEL %d to %d\n", x, v->nOp);
- }
+ if( p->db->flags & SQLITE_VdbeAddopTrace ){
+ printf("RESOLVE LABEL %d to %d\n", x, v->nOp);
+ }
#endif
+ if( p->nLabelAlloc + p->nLabel < 0 ){
+ resizeResolveLabel(p,v,j);
+ }else{
assert( p->aLabel[j]==(-1) ); /* Labels may only be resolved once */
p->aLabel[j] = v->nOp;
}
@@ -76002,19 +79510,19 @@ SQLITE_PRIVATE void sqlite3VdbeReusable(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 {
@@ -76047,7 +79555,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;
@@ -76078,9 +79586,10 @@ static Op *opIterNext(VdbeOpIter *p){
** * OP_HaltIfNull with P1=SQLITE_CONSTRAINT and P2=OE_Abort.
** * OP_Destroy
** * OP_VUpdate
+** * OP_VCreate
** * OP_VRename
** * OP_FkCounter with P2==0 (immediate foreign key constraint)
-** * OP_CreateBtree/BTREE_INTKEY and OP_InitCoroutine
+** * OP_CreateBtree/BTREE_INTKEY and OP_InitCoroutine
** (for CREATE TABLE AS SELECT ...)
**
** Then check that the value of Parse.mayAbort is true if an
@@ -76094,6 +79603,7 @@ SQLITE_PRIVATE int sqlite3VdbeAssertMayAbort(Vdbe *v, int mayAbort){
int hasAbort = 0;
int hasFkCounter = 0;
int hasCreateTable = 0;
+ int hasCreateIndex = 0;
int hasInitCoroutine = 0;
Op *pOp;
VdbeOpIter sIter;
@@ -76102,14 +79612,25 @@ 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
- || ((opcode==OP_Halt || opcode==OP_HaltIfNull)
- && ((pOp->p1&0xff)==SQLITE_CONSTRAINT && pOp->p2==OE_Abort))
+ if( opcode==OP_Destroy || opcode==OP_VUpdate || opcode==OP_VRename
+ || opcode==OP_VDestroy
+ || opcode==OP_VCreate
+ || opcode==OP_ParseSchema
+ || ((opcode==OP_Halt || opcode==OP_HaltIfNull)
+ && ((pOp->p1)!=SQLITE_OK && pOp->p2==OE_Abort))
){
hasAbort = 1;
break;
}
if( opcode==OP_CreateBtree && pOp->p3==BTREE_INTKEY ) hasCreateTable = 1;
+ if( mayAbort ){
+ /* hasCreateIndex may also be set for some DELETE statements that use
+ ** OP_Clear. So this routine may end up returning true in the case
+ ** where a "DELETE FROM tbl" has a statement-journal but does not
+ ** require one. This is not so bad - it is an inefficiency, not a bug. */
+ if( opcode==OP_CreateBtree && pOp->p3==BTREE_BLOBKEY ) hasCreateIndex = 1;
+ if( opcode==OP_Clear ) hasCreateIndex = 1;
+ }
if( opcode==OP_InitCoroutine ) hasInitCoroutine = 1;
#ifndef SQLITE_OMIT_FOREIGN_KEY
if( opcode==OP_FkCounter && pOp->p1==0 && pOp->p2==1 ){
@@ -76125,7 +79646,8 @@ SQLITE_PRIVATE int sqlite3VdbeAssertMayAbort(Vdbe *v, int mayAbort){
** true for this case to prevent the assert() in the callers frame
** from failing. */
return ( v->db->mallocFailed || hasAbort==mayAbort || hasFkCounter
- || (hasCreateTable && hasInitCoroutine) );
+ || (hasCreateTable && hasInitCoroutine) || hasCreateIndex
+ );
}
#endif /* SQLITE_DEBUG - the sqlite3AssertMayAbort() function */
@@ -76198,7 +79720,7 @@ static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){
switch( pOp->opcode ){
case OP_Transaction: {
if( pOp->p2!=0 ) p->readOnly = 0;
- /* fall thru */
+ /* no break */ deliberate_fall_through
}
case OP_AutoCommit:
case OP_Savepoint: {
@@ -76219,7 +79741,7 @@ static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){
pOp->p4.xAdvance = sqlite3BtreeNext;
pOp->p4type = P4_ADVANCE;
/* The code generator never codes any of these opcodes as a jump
- ** to a label. They are always coded as a jump backwards to a
+ ** to a label. They are always coded as a jump backwards to a
** known address */
assert( pOp->p2>=0 );
break;
@@ -76228,7 +79750,7 @@ static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){
pOp->p4.xAdvance = sqlite3BtreePrevious;
pOp->p4type = P4_ADVANCE;
/* The code generator never codes any of these opcodes as a jump
- ** to a label. They are always coded as a jump backwards to a
+ ** to a label. They are always coded as a jump backwards to a
** known address */
assert( pOp->p2>=0 );
break;
@@ -76245,6 +79767,7 @@ static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){
n = pOp[-1].p1;
if( n>nMaxArgs ) nMaxArgs = n;
/* Fall through into the default case */
+ /* no break */ deliberate_fall_through
}
#endif
default: {
@@ -76253,7 +79776,7 @@ static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){
** non-jump opcodes less than SQLITE_MX_JUMP_CODE are guaranteed to
** have non-negative values for P2. */
assert( (sqlite3OpcodeProperty[pOp->opcode] & OPFLG_JUMP)!=0 );
- assert( ADDR(pOp->p2)nLabel );
+ assert( ADDR(pOp->p2)<-pParse->nLabel );
pOp->p2 = aLabel[ADDR(pOp->p2)];
}
break;
@@ -76278,7 +79801,7 @@ static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){
** Return the address of the next instruction to be inserted.
*/
SQLITE_PRIVATE int sqlite3VdbeCurrentAddr(Vdbe *p){
- assert( p->magic==VDBE_MAGIC_INIT );
+ assert( p->iVdbeMagic==VDBE_MAGIC_INIT );
return p->nOp;
}
@@ -76292,7 +79815,7 @@ SQLITE_PRIVATE int sqlite3VdbeCurrentAddr(Vdbe *p){
*/
#if defined(SQLITE_DEBUG) && !defined(SQLITE_TEST_REALLOC_STRESS)
SQLITE_PRIVATE void sqlite3VdbeVerifyNoMallocRequired(Vdbe *p, int N){
- assert( p->nOp + N <= p->pParse->nOpAlloc );
+ assert( p->nOp + N <= p->nOpAlloc );
}
#endif
@@ -76326,12 +79849,12 @@ SQLITE_PRIVATE void sqlite3VdbeVerifyAbortable(Vdbe *p, int onError){
/*
** 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){
@@ -76363,8 +79886,8 @@ SQLITE_PRIVATE VdbeOp *sqlite3VdbeAddOpList(
int i;
VdbeOp *pOut, *pFirst;
assert( nOp>0 );
- assert( p->magic==VDBE_MAGIC_INIT );
- if( p->nOp + nOp > p->pParse->nOpAlloc && growOpArray(p, nOp) ){
+ assert( p->iVdbeMagic==VDBE_MAGIC_INIT );
+ if( p->nOp + nOp > p->nOpAlloc && growOpArray(p, nOp) ){
return 0;
}
pFirst = pOut = &p->aOp[p->nOp];
@@ -76405,12 +79928,12 @@ SQLITE_PRIVATE VdbeOp *sqlite3VdbeAddOpList(
SQLITE_PRIVATE void sqlite3VdbeScanStatus(
Vdbe *p, /* VM to add scanstatus() to */
int addrExplain, /* Address of OP_Explain (or 0) */
- int addrLoop, /* Address of loop counter */
+ int addrLoop, /* Address of loop counter */
int addrVisit, /* Address of rows visited counter */
LogEst nEst, /* Estimated number of output rows */
const char *zName /* Name of table or index being scanned */
){
- int nByte = (p->nScan+1) * sizeof(ScanStatus);
+ sqlite3_int64 nByte = (p->nScan+1) * sizeof(ScanStatus);
ScanStatus *aNew;
aNew = (ScanStatus*)sqlite3DbRealloc(p->db, p->aScan, nByte);
if( aNew ){
@@ -76430,16 +79953,16 @@ SQLITE_PRIVATE void sqlite3VdbeScanStatus(
** Change the value of the opcode, or P1, P2, P3, or P5 operands
** for a specific instruction.
*/
-SQLITE_PRIVATE void sqlite3VdbeChangeOpcode(Vdbe *p, u32 addr, u8 iNewOpcode){
+SQLITE_PRIVATE void sqlite3VdbeChangeOpcode(Vdbe *p, int addr, u8 iNewOpcode){
sqlite3VdbeGetOp(p,addr)->opcode = iNewOpcode;
}
-SQLITE_PRIVATE void sqlite3VdbeChangeP1(Vdbe *p, u32 addr, int val){
+SQLITE_PRIVATE void sqlite3VdbeChangeP1(Vdbe *p, int addr, int val){
sqlite3VdbeGetOp(p,addr)->p1 = val;
}
-SQLITE_PRIVATE void sqlite3VdbeChangeP2(Vdbe *p, u32 addr, int val){
+SQLITE_PRIVATE void sqlite3VdbeChangeP2(Vdbe *p, int addr, int val){
sqlite3VdbeGetOp(p,addr)->p2 = val;
}
-SQLITE_PRIVATE void sqlite3VdbeChangeP3(Vdbe *p, u32 addr, int val){
+SQLITE_PRIVATE void sqlite3VdbeChangeP3(Vdbe *p, int addr, int val){
sqlite3VdbeGetOp(p,addr)->p3 = val;
}
SQLITE_PRIVATE void sqlite3VdbeChangeP5(Vdbe *p, u16 p5){
@@ -76455,6 +79978,34 @@ SQLITE_PRIVATE void sqlite3VdbeJumpHere(Vdbe *p, int addr){
sqlite3VdbeChangeP2(p, addr, p->nOp);
}
+/*
+** Change the P2 operand of the jump instruction at addr so that
+** the jump lands on the next opcode. Or if the jump instruction was
+** the previous opcode (and is thus a no-op) then simply back up
+** the next instruction counter by one slot so that the jump is
+** overwritten by the next inserted opcode.
+**
+** This routine is an optimization of sqlite3VdbeJumpHere() that
+** strives to omit useless byte-code like this:
+**
+** 7 Once 0 8 0
+** 8 ...
+*/
+SQLITE_PRIVATE void sqlite3VdbeJumpHereOrPopInst(Vdbe *p, int addr){
+ if( addr==p->nOp-1 ){
+ assert( p->aOp[addr].opcode==OP_Once
+ || p->aOp[addr].opcode==OP_If
+ || p->aOp[addr].opcode==OP_FkIfZero );
+ assert( p->aOp[addr].p4type==0 );
+#ifdef SQLITE_VDBE_COVERAGE
+ sqlite3VdbeGetOp(p,-1)->iSrcLine = 0; /* Erase VdbeCoverage() macros */
+#endif
+ p->nOp--;
+ }else{
+ sqlite3VdbeChangeP2(p, addr, p->nOp);
+ }
+}
+
/*
** If the input FuncDef structure is ephemeral, then free it. If
@@ -76466,8 +80017,6 @@ static void freeEphemeralFunction(sqlite3 *db, FuncDef *pDef){
}
}
-static void vdbeFreeOpArray(sqlite3 *, Op *, int);
-
/*
** Delete a P4 value if necessary.
*/
@@ -76477,7 +80026,7 @@ static SQLITE_NOINLINE void freeP4Mem(sqlite3 *db, Mem *p){
}
static SQLITE_NOINLINE void freeP4FuncCtx(sqlite3 *db, sqlite3_context *p){
freeEphemeralFunction(db, p->pFunc);
- sqlite3DbFreeNN(db, p);
+ sqlite3DbFreeNN(db, p);
}
static void freeP4(sqlite3 *db, int p4type, void *p4){
assert( db );
@@ -76525,8 +80074,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 ){
@@ -76535,7 +80084,7 @@ static void vdbeFreeOpArray(sqlite3 *db, Op *aOp, int nOp){
if( pOp->p4type <= P4_FREE_IF_LE ) freeP4(db, pOp->p4type, pOp->p4.p);
#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
sqlite3DbFree(db, pOp->zComment);
-#endif
+#endif
}
sqlite3DbFreeNN(db, aOp);
}
@@ -76551,6 +80100,13 @@ SQLITE_PRIVATE void sqlite3VdbeLinkSubProgram(Vdbe *pVdbe, SubProgram *p){
pVdbe->pProgram = p;
}
+/*
+** Return true if the given Vdbe has any SubPrograms.
+*/
+SQLITE_PRIVATE int sqlite3VdbeHasSubProgram(Vdbe *pVdbe){
+ return pVdbe->pProgram!=0;
+}
+
/*
** Change the opcode at addr into OP_Noop
*/
@@ -76578,6 +80134,41 @@ SQLITE_PRIVATE int sqlite3VdbeDeletePriorOpcode(Vdbe *p, u8 op){
}
}
+#ifdef SQLITE_DEBUG
+/*
+** Generate an OP_ReleaseReg opcode to indicate that a range of
+** registers, except any identified by mask, are no longer in use.
+*/
+SQLITE_PRIVATE void sqlite3VdbeReleaseRegisters(
+ Parse *pParse, /* Parsing context */
+ int iFirst, /* Index of first register to be released */
+ int N, /* Number of registers to release */
+ u32 mask, /* Mask of registers to NOT release */
+ int bUndefine /* If true, mark registers as undefined */
+){
+ if( N==0 ) return;
+ assert( pParse->pVdbe );
+ assert( iFirst>=1 );
+ assert( iFirst+N-1<=pParse->nMem );
+ if( N<=31 && mask!=0 ){
+ while( N>0 && (mask&1)!=0 ){
+ mask >>= 1;
+ iFirst++;
+ N--;
+ }
+ while( N>0 && N<=32 && (mask & MASKBIT32(N-1))!=0 ){
+ mask &= ~MASKBIT32(N-1);
+ N--;
+ }
+ }
+ if( N>0 ){
+ sqlite3VdbeAddOp3(pParse->pVdbe, OP_ReleaseReg, iFirst, N, *(int*)&mask);
+ if( bUndefine ) sqlite3VdbeChangeP5(pParse->pVdbe, 1);
+ }
+}
+#endif /* SQLITE_DEBUG */
+
+
/*
** Change the value of the P4 operand for a specific instruction.
** This routine is useful when a large program is loaded from a
@@ -76588,7 +80179,7 @@ SQLITE_PRIVATE int sqlite3VdbeDeletePriorOpcode(Vdbe *p, u8 op){
** the string is made into memory obtained from sqlite3_malloc().
** A value of n==0 means copy bytes of zP4 up to and including the
** first null byte. If n>0 then copy n+1 bytes of zP4.
-**
+**
** 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.
@@ -76619,7 +80210,7 @@ SQLITE_PRIVATE void sqlite3VdbeChangeP4(Vdbe *p, int addr, const char *zP4, int
sqlite3 *db;
assert( p!=0 );
db = p->db;
- assert( p->magic==VDBE_MAGIC_INIT );
+ assert( p->iVdbeMagic==VDBE_MAGIC_INIT );
assert( p->aOp!=0 || db->mallocFailed );
if( db->mallocFailed ){
if( n!=P4_VTAB ) freeP4(db, n, (void*)*(char**)&zP4);
@@ -76649,7 +80240,7 @@ SQLITE_PRIVATE void sqlite3VdbeChangeP4(Vdbe *p, int addr, const char *zP4, int
}
/*
-** Change the P4 operand of the most recently coded instruction
+** Change the P4 operand of the most recently coded instruction
** to the value defined by the arguments. This is a high-speed
** version of sqlite3VdbeChangeP4().
**
@@ -76695,7 +80286,8 @@ SQLITE_PRIVATE void sqlite3VdbeSetP4KeyInfo(Parse *pParse, Index *pIdx){
*/
static void vdbeVComment(Vdbe *p, const char *zFormat, va_list ap){
assert( p->nOp>0 || p->aOp==0 );
- assert( p->aOp==0 || p->aOp[p->nOp-1].zComment==0 || p->db->mallocFailed );
+ assert( p->aOp==0 || p->aOp[p->nOp-1].zComment==0 || p->db->mallocFailed
+ || p->pParse->nErr>0 );
if( p->nOp ){
assert( p->aOp );
sqlite3DbFree(p->db, p->aOp[p->nOp-1].zComment);
@@ -76738,7 +80330,7 @@ SQLITE_PRIVATE void sqlite3VdbeSetLineNumber(Vdbe *v, int iLine){
** routine, then a pointer to a dummy VdbeOp will be returned. That opcode
** is readable but not writable, though it is cast to a writable value.
** The return of a dummy opcode allows the call to continue functioning
-** after an OOM fault without having to check to see if the return from
+** after an OOM fault without having to check to see if the return from
** this routine is a valid pointer. But because the dummy.opcode is 0,
** dummy will never be written to. This is verified by code inspection and
** by running with Valgrind.
@@ -76747,7 +80339,7 @@ SQLITE_PRIVATE VdbeOp *sqlite3VdbeGetOp(Vdbe *p, int addr){
/* C89 specifies that the constant "dummy" will be initialized to all
** zeros, which is correct. MSVC generates a warning, nevertheless. */
static VdbeOp dummy; /* Ignore the MSVC warning about no initializer */
- assert( p->magic==VDBE_MAGIC_INIT );
+ assert( p->iVdbeMagic==VDBE_MAGIC_INIT );
if( addr<0 ){
addr = p->nOp - 1;
}
@@ -76785,17 +80377,19 @@ static int translateP(char c, const Op *pOp){
** "PX@PY+1" -> "r[X..X+Y]" or "r[x]" if y is 0
** "PY..PY" -> "r[X..Y]" or "r[x]" if y<=x
*/
-static int displayComment(
+SQLITE_PRIVATE char *sqlite3VdbeDisplayComment(
+ sqlite3 *db, /* Optional - Oom error reporting only */
const Op *pOp, /* The opcode to be commented */
- const char *zP4, /* Previously obtained value for P4 */
- char *zTemp, /* Write result here */
- int nTemp /* Space available in zTemp[] */
+ const char *zP4 /* Previously obtained value for P4 */
){
const char *zOpName;
const char *zSynopsis;
int nOpName;
- int ii, jj;
+ int ii;
char zAlt[50];
+ StrAccum x;
+
+ sqlite3StrAccumInit(&x, 0, 0, 0, SQLITE_MAX_LENGTH);
zOpName = sqlite3OpcodeName(pOp->opcode);
nOpName = sqlite3Strlen30(zOpName);
if( zOpName[nOpName+1] ){
@@ -76803,60 +80397,67 @@ static int displayComment(
char c;
zSynopsis = zOpName += nOpName + 1;
if( strncmp(zSynopsis,"IF ",3)==0 ){
- if( pOp->p5 & SQLITE_STOREP2 ){
- sqlite3_snprintf(sizeof(zAlt), zAlt, "r[P2] = (%s)", zSynopsis+3);
- }else{
- sqlite3_snprintf(sizeof(zAlt), zAlt, "if %s goto P2", zSynopsis+3);
- }
+ sqlite3_snprintf(sizeof(zAlt), zAlt, "if %s goto P2", zSynopsis+3);
zSynopsis = zAlt;
}
- for(ii=jj=0; jjzComment);
+ sqlite3_str_appendall(&x, pOp->zComment);
seenCom = 1;
}else{
int v1 = translateP(c, pOp);
int v2;
- sqlite3_snprintf(nTemp-jj, zTemp+jj, "%d", v1);
if( strncmp(zSynopsis+ii+1, "@P", 2)==0 ){
ii += 3;
- jj += sqlite3Strlen30(zTemp+jj);
v2 = translateP(zSynopsis[ii], pOp);
if( strncmp(zSynopsis+ii+1,"+1",2)==0 ){
ii += 2;
v2++;
}
- if( v2>1 ){
- sqlite3_snprintf(nTemp-jj, zTemp+jj, "..%d", v1+v2-1);
+ if( v2<2 ){
+ sqlite3_str_appendf(&x, "%d", v1);
+ }else{
+ sqlite3_str_appendf(&x, "%d..%d", v1, v1+v2-1);
+ }
+ }else if( strncmp(zSynopsis+ii+1, "@NP", 3)==0 ){
+ sqlite3_context *pCtx = pOp->p4.pCtx;
+ if( pOp->p4type!=P4_FUNCCTX || pCtx->argc==1 ){
+ sqlite3_str_appendf(&x, "%d", v1);
+ }else if( pCtx->argc>1 ){
+ sqlite3_str_appendf(&x, "%d..%d", v1, v1+pCtx->argc-1);
+ }else if( x.accError==0 ){
+ assert( x.nChar>2 );
+ x.nChar -= 2;
+ ii++;
+ }
+ ii += 3;
+ }else{
+ sqlite3_str_appendf(&x, "%d", v1);
+ if( strncmp(zSynopsis+ii+1, "..P3", 4)==0 && pOp->p3==0 ){
+ ii += 4;
}
- }else if( strncmp(zSynopsis+ii+1, "..P3", 4)==0 && pOp->p3==0 ){
- ii += 4;
}
}
- jj += sqlite3Strlen30(zTemp+jj);
}else{
- zTemp[jj++] = c;
+ sqlite3_str_appendchar(&x, 1, c);
}
}
- if( !seenCom && jjzComment ){
- sqlite3_snprintf(nTemp-jj, zTemp+jj, "; %s", pOp->zComment);
- jj += sqlite3Strlen30(zTemp+jj);
+ if( !seenCom && pOp->zComment ){
+ sqlite3_str_appendf(&x, "; %s", pOp->zComment);
}
- if( jjzComment ){
- sqlite3_snprintf(nTemp, zTemp, "%s", pOp->zComment);
- jj = sqlite3Strlen30(zTemp);
- }else{
- zTemp[0] = 0;
- jj = 0;
+ sqlite3_str_appendall(&x, pOp->zComment);
}
- return jj;
+ if( (x.accError & SQLITE_NOMEM)!=0 && db!=0 ){
+ sqlite3OomFault(db);
+ }
+ return sqlite3StrAccumFinish(&x);
}
-#endif /* SQLITE_DEBUG */
+#endif /* SQLITE_ENABLE_EXPLAIN_COMMENTS */
#if VDBE_DISPLAY_P4 && defined(SQLITE_ENABLE_CURSOR_HINTS)
/*
@@ -76937,23 +80538,25 @@ static void displayP4Expr(StrAccum *p, Expr *pExpr){
** Compute a string that describes the P4 parameter for an opcode.
** Use zTemp for any required temporary buffer space.
*/
-static char *displayP4(Op *pOp, char *zTemp, int nTemp){
- char *zP4 = zTemp;
+SQLITE_PRIVATE char *sqlite3VdbeDisplayP4(sqlite3 *db, Op *pOp){
+ char *zP4 = 0;
StrAccum x;
- assert( nTemp>=20 );
- sqlite3StrAccumInit(&x, 0, zTemp, nTemp, 0);
+
+ sqlite3StrAccumInit(&x, 0, 0, 0, SQLITE_MAX_LENGTH);
switch( pOp->p4type ){
case P4_KEYINFO: {
int j;
KeyInfo *pKeyInfo = pOp->p4.pKeyInfo;
- assert( pKeyInfo->aSortOrder!=0 );
+ assert( pKeyInfo->aSortFlags!=0 );
sqlite3_str_appendf(&x, "k(%d", pKeyInfo->nKeyField);
for(j=0; jnKeyField; j++){
CollSeq *pColl = pKeyInfo->aColl[j];
const char *zColl = pColl ? pColl->zName : "";
if( strcmp(zColl, "BINARY")==0 ) zColl = "B";
- sqlite3_str_appendf(&x, ",%s%s",
- pKeyInfo->aSortOrder[j] ? "-" : "", zColl);
+ sqlite3_str_appendf(&x, ",%s%s%s",
+ (pKeyInfo->aSortFlags[j] & KEYINFO_ORDER_DESC) ? "-" : "",
+ (pKeyInfo->aSortFlags[j] & KEYINFO_ORDER_BIGNULL)? "N." : "",
+ zColl);
}
sqlite3_str_append(&x, ")", 1);
break;
@@ -76965,8 +80568,11 @@ static char *displayP4(Op *pOp, char *zTemp, int nTemp){
}
#endif
case P4_COLLSEQ: {
+ static const char *const encnames[] = {"?", "8", "16LE", "16BE"};
CollSeq *pColl = pOp->p4.pColl;
- sqlite3_str_appendf(&x, "(%.20s)", pColl->zName);
+ assert( pColl->enc>=0 && pColl->enc<4 );
+ sqlite3_str_appendf(&x, "%.18s-%s", pColl->zName,
+ encnames[pColl->enc]);
break;
}
case P4_FUNCDEF: {
@@ -76974,13 +80580,11 @@ static char *displayP4(Op *pOp, char *zTemp, int nTemp){
sqlite3_str_appendf(&x, "%s(%d)", pDef->zName, pDef->nArg);
break;
}
-#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE)
case P4_FUNCCTX: {
FuncDef *pDef = pOp->p4.pCtx->pFunc;
sqlite3_str_appendf(&x, "%s(%d)", pDef->zName, pDef->nArg);
break;
}
-#endif
case P4_INT64: {
sqlite3_str_appendf(&x, "%lld", *pOp->p4.pI64);
break;
@@ -76997,7 +80601,7 @@ static char *displayP4(Op *pOp, char *zTemp, int nTemp){
Mem *pMem = pOp->p4.pMem;
if( pMem->flags & MEM_Str ){
zP4 = pMem->z;
- }else if( pMem->flags & MEM_Int ){
+ }else if( pMem->flags & (MEM_Int|MEM_IntReal) ){
sqlite3_str_appendf(&x, "%lld", pMem->u.i);
}else if( pMem->flags & MEM_Real ){
sqlite3_str_appendf(&x, "%.16g", pMem->u.r);
@@ -77017,41 +80621,37 @@ static char *displayP4(Op *pOp, char *zTemp, int nTemp){
}
#endif
case P4_INTARRAY: {
- int i;
- int *ai = pOp->p4.ai;
- int n = ai[0]; /* The first element of an INTARRAY is always the
+ u32 i;
+ u32 *ai = pOp->p4.ai;
+ u32 n = ai[0]; /* The first element of an INTARRAY is always the
** count of the number of elements to follow */
for(i=1; i<=n; i++){
- sqlite3_str_appendf(&x, ",%d", ai[i]);
+ sqlite3_str_appendf(&x, "%c%u", (i==1 ? '[' : ','), ai[i]);
}
- zTemp[0] = '[';
sqlite3_str_append(&x, "]", 1);
break;
}
case P4_SUBPROGRAM: {
- sqlite3_str_appendf(&x, "program");
+ zP4 = "program";
break;
}
case P4_DYNBLOB:
case P4_ADVANCE: {
- zTemp[0] = 0;
break;
}
case P4_TABLE: {
- sqlite3_str_appendf(&x, "%s", pOp->p4.pTab->zName);
+ zP4 = pOp->p4.pTab->zName;
break;
}
default: {
zP4 = pOp->p4.z;
- if( zP4==0 ){
- zP4 = zTemp;
- zTemp[0] = 0;
- }
}
}
- sqlite3StrAccumFinish(&x);
- assert( zP4!=0 );
- return zP4;
+ if( zP4 ) sqlite3_str_appendall(&x, zP4);
+ if( (x.accError & SQLITE_NOMEM)!=0 ){
+ sqlite3OomFault(db);
+ }
+ return sqlite3StrAccumFinish(&x);
}
#endif /* VDBE_DISPLAY_P4 */
@@ -77082,13 +80682,13 @@ SQLITE_PRIVATE void sqlite3VdbeUsesBtree(Vdbe *p, int i){
**
** If SQLite is not threadsafe but does support shared-cache mode, then
** sqlite3BtreeEnter() 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.
**
** If SQLite is not threadsafe and does not support shared-cache mode, this
** function is a no-op.
**
-** The p->btreeMask field is a bitmask of all btrees that the prepared
+** The p->btreeMask field is a bitmask of all btrees that the prepared
** statement p will ever use. Let N be the number of bits in p->btreeMask
** corresponding to btrees that use shared cache. Then the runtime of
** this routine is N*N. But as N is rarely more than 1, this should not
@@ -77141,24 +80741,30 @@ SQLITE_PRIVATE void sqlite3VdbeLeave(Vdbe *p){
*/
SQLITE_PRIVATE void sqlite3VdbePrintOp(FILE *pOut, int pc, VdbeOp *pOp){
char *zP4;
- char zPtr[50];
- char zCom[100];
+ char *zCom;
+ sqlite3 dummyDb;
static const char *zFormat1 = "%4d %-13s %4d %4d %4d %-13s %.2X %s\n";
if( pOut==0 ) pOut = stdout;
- zP4 = displayP4(pOp, zPtr, sizeof(zPtr));
+ sqlite3BeginBenignMalloc();
+ dummyDb.mallocFailed = 1;
+ zP4 = sqlite3VdbeDisplayP4(&dummyDb, pOp);
#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
- displayComment(pOp, zP4, zCom, sizeof(zCom));
+ zCom = sqlite3VdbeDisplayComment(0, pOp, zP4);
#else
- zCom[0] = 0;
+ zCom = 0;
#endif
/* NB: The sqlite3OpcodeName() function is implemented by code created
** by the mkopcodeh.awk and mkopcodec.awk scripts which extract the
** information from the vdbe.c source text */
- fprintf(pOut, zFormat1, pc,
- sqlite3OpcodeName(pOp->opcode), pOp->p1, pOp->p2, pOp->p3, zP4, pOp->p5,
- zCom
+ fprintf(pOut, zFormat1, pc,
+ sqlite3OpcodeName(pOp->opcode), pOp->p1, pOp->p2, pOp->p3,
+ zP4 ? zP4 : "", pOp->p5,
+ zCom ? zCom : ""
);
fflush(pOut);
+ sqlite3_free(zP4);
+ sqlite3_free(zCom);
+ sqlite3EndBenignMalloc();
}
#endif
@@ -77195,15 +80801,15 @@ static void releaseMemArray(Mem *p, int N){
assert( sqlite3VdbeCheckMemInvariants(p) );
/* 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.
*/
testcase( p->flags & MEM_Agg );
@@ -77249,6 +80855,121 @@ SQLITE_PRIVATE void sqlite3VdbeFrameMemDel(void *pArg){
pFrame->v->pDelFrame = pFrame;
}
+#if defined(SQLITE_ENABLE_BYTECODE_VTAB) || !defined(SQLITE_OMIT_EXPLAIN)
+/*
+** Locate the next opcode to be displayed in EXPLAIN or EXPLAIN
+** QUERY PLAN output.
+**
+** Return SQLITE_ROW on success. Return SQLITE_DONE if there are no
+** more opcodes to be displayed.
+*/
+SQLITE_PRIVATE int sqlite3VdbeNextOpcode(
+ Vdbe *p, /* The statement being explained */
+ Mem *pSub, /* Storage for keeping track of subprogram nesting */
+ int eMode, /* 0: normal. 1: EQP. 2: TablesUsed */
+ int *piPc, /* IN/OUT: Current rowid. Overwritten with next rowid */
+ int *piAddr, /* OUT: Write index into (*paOp)[] here */
+ Op **paOp /* OUT: Write the opcode array here */
+){
+ int nRow; /* Stop when row count reaches this */
+ int nSub = 0; /* Number of sub-vdbes seen so far */
+ SubProgram **apSub = 0; /* Array of sub-vdbes */
+ int i; /* Next instruction address */
+ int rc = SQLITE_OK; /* Result code */
+ Op *aOp = 0; /* Opcode array */
+ int iPc; /* Rowid. Copy of value in *piPc */
+
+ /* When the number of output rows reaches nRow, that means the
+ ** listing has finished and sqlite3_step() should return SQLITE_DONE.
+ ** nRow is the sum of the number of rows in the main program, plus
+ ** the sum of the number of rows in all trigger subprograms encountered
+ ** so far. The nRow value will increase as new trigger subprograms are
+ ** encountered, but p->pc will eventually catch up to nRow.
+ */
+ nRow = p->nOp;
+ if( pSub!=0 ){
+ if( pSub->flags&MEM_Blob ){
+ /* pSub is initiallly NULL. It is initialized to a BLOB by
+ ** the P4_SUBPROGRAM processing logic below */
+ nSub = pSub->n/sizeof(Vdbe*);
+ apSub = (SubProgram **)pSub->z;
+ }
+ for(i=0; inOp;
+ }
+ }
+ iPc = *piPc;
+ while(1){ /* Loop exits via break */
+ i = iPc++;
+ if( i>=nRow ){
+ p->rc = SQLITE_OK;
+ rc = SQLITE_DONE;
+ break;
+ }
+ if( inOp ){
+ /* The rowid is small enough that we are still in the
+ ** main program. */
+ aOp = p->aOp;
+ }else{
+ /* We are currently listing subprograms. Figure out which one and
+ ** pick up the appropriate opcode. */
+ int j;
+ i -= p->nOp;
+ assert( apSub!=0 );
+ assert( nSub>0 );
+ for(j=0; i>=apSub[j]->nOp; j++){
+ i -= apSub[j]->nOp;
+ assert( inOp || j+1aOp;
+ }
+
+ /* When an OP_Program opcode is encounter (the only opcode that has
+ ** a P4_SUBPROGRAM argument), expand the size of the array of subprograms
+ ** kept in p->aMem[9].z to hold the new program - assuming this subprogram
+ ** has not already been seen.
+ */
+ if( pSub!=0 && aOp[i].p4type==P4_SUBPROGRAM ){
+ int nByte = (nSub+1)*sizeof(SubProgram*);
+ int j;
+ for(j=0; jrc = sqlite3VdbeMemGrow(pSub, nByte, nSub!=0);
+ if( p->rc!=SQLITE_OK ){
+ rc = SQLITE_ERROR;
+ break;
+ }
+ apSub = (SubProgram **)pSub->z;
+ apSub[nSub++] = aOp[i].p4.pProgram;
+ MemSetTypeFlag(pSub, MEM_Blob);
+ pSub->n = nSub*sizeof(SubProgram*);
+ nRow += aOp[i].p4.pProgram->nOp;
+ }
+ }
+ if( eMode==0 ) break;
+#ifdef SQLITE_ENABLE_BYTECODE_VTAB
+ if( eMode==2 ){
+ Op *pOp = aOp + i;
+ if( pOp->opcode==OP_OpenRead ) break;
+ if( pOp->opcode==OP_OpenWrite && (pOp->p5 & OPFLAG_P2ISREG)==0 ) break;
+ if( pOp->opcode==OP_ReopenIdx ) break;
+ }else
+#endif
+ {
+ assert( eMode==1 );
+ if( aOp[i].opcode==OP_Explain ) break;
+ if( aOp[i].opcode==OP_Init && iPc>1 ) break;
+ }
+ }
+ *piPc = iPc;
+ *piAddr = i;
+ *paOp = aOp;
+ return rc;
+}
+#endif /* SQLITE_ENABLE_BYTECODE_VTAB || !SQLITE_OMIT_EXPLAIN */
+
/*
** Delete a VdbeFrame object and its contents. VdbeFrame objects are
@@ -77289,19 +81010,17 @@ SQLITE_PRIVATE void sqlite3VdbeFrameDelete(VdbeFrame *p){
SQLITE_PRIVATE int sqlite3VdbeList(
Vdbe *p /* The VDBE */
){
- int nRow; /* Stop when row count reaches this */
- int nSub = 0; /* Number of sub-vdbes seen so far */
- SubProgram **apSub = 0; /* Array of sub-vdbes */
Mem *pSub = 0; /* Memory cell hold array of subprogs */
sqlite3 *db = p->db; /* The database connection */
int i; /* Loop counter */
int rc = SQLITE_OK; /* Return code */
Mem *pMem = &p->aMem[1]; /* First Mem of result set */
int bListSubprogs = (p->explain==1 || (db->flags & SQLITE_TriggerEQP)!=0);
- Op *pOp = 0;
+ Op *aOp; /* Array of opcodes */
+ Op *pOp; /* Current opcode */
assert( p->explain );
- assert( p->magic==VDBE_MAGIC_RUN );
+ assert( p->iVdbeMagic==VDBE_MAGIC_RUN );
assert( p->rc==SQLITE_OK || p->rc==SQLITE_BUSY || p->rc==SQLITE_NOMEM );
/* Even though this opcode does not use dynamic strings for
@@ -77318,14 +81037,6 @@ SQLITE_PRIVATE int sqlite3VdbeList(
return SQLITE_ERROR;
}
- /* When the number of output rows reaches nRow, that means the
- ** listing has finished and sqlite3_step() should return SQLITE_DONE.
- ** nRow is the sum of the number of rows in the main program, plus
- ** the sum of the number of rows in all trigger subprograms encountered
- ** so far. The nRow value will increase as new trigger subprograms are
- ** encountered, but p->pc will eventually catch up to nRow.
- */
- nRow = p->nOp;
if( bListSubprogs ){
/* The first 8 memory cells are used for the result set. So we will
** commandeer the 9th cell to use as storage for an array of pointers
@@ -77333,144 +81044,55 @@ SQLITE_PRIVATE int sqlite3VdbeList(
** cells. */
assert( p->nMem>9 );
pSub = &p->aMem[9];
- if( pSub->flags&MEM_Blob ){
- /* On the first call to sqlite3_step(), pSub will hold a NULL. It is
- ** initialized to a BLOB by the P4_SUBPROGRAM processing logic below */
- nSub = pSub->n/sizeof(Vdbe*);
- apSub = (SubProgram **)pSub->z;
- }
- for(i=0; inOp;
- }
+ }else{
+ pSub = 0;
}
- while(1){ /* Loop exits via break */
- i = p->pc++;
- if( i>=nRow ){
- p->rc = SQLITE_OK;
- rc = SQLITE_DONE;
- break;
- }
- if( inOp ){
- /* The output line number is small enough that we are still in the
- ** main program. */
- pOp = &p->aOp[i];
- }else{
- /* We are currently listing subprograms. Figure out which one and
- ** pick up the appropriate opcode. */
- int j;
- i -= p->nOp;
- for(j=0; i>=apSub[j]->nOp; j++){
- i -= apSub[j]->nOp;
- }
- pOp = &apSub[j]->aOp[i];
- }
-
- /* When an OP_Program opcode is encounter (the only opcode that has
- ** a P4_SUBPROGRAM argument), expand the size of the array of subprograms
- ** kept in p->aMem[9].z to hold the new program - assuming this subprogram
- ** has not already been seen.
- */
- if( bListSubprogs && pOp->p4type==P4_SUBPROGRAM ){
- int nByte = (nSub+1)*sizeof(SubProgram*);
- int j;
- for(j=0; jp4.pProgram ) break;
- }
- if( j==nSub ){
- p->rc = sqlite3VdbeMemGrow(pSub, nByte, nSub!=0);
- if( p->rc!=SQLITE_OK ){
- rc = SQLITE_ERROR;
- break;
- }
- apSub = (SubProgram **)pSub->z;
- apSub[nSub++] = pOp->p4.pProgram;
- pSub->flags |= MEM_Blob;
- pSub->n = nSub*sizeof(SubProgram*);
- nRow += pOp->p4.pProgram->nOp;
- }
- }
- if( p->explain<2 ) break;
- if( pOp->opcode==OP_Explain ) break;
- if( pOp->opcode==OP_Init && p->pc>1 ) break;
- }
+ /* Figure out which opcode is next to display */
+ rc = sqlite3VdbeNextOpcode(p, pSub, p->explain==2, &p->pc, &i, &aOp);
if( rc==SQLITE_OK ){
- if( db->u1.isInterrupted ){
+ pOp = aOp + i;
+ if( AtomicLoad(&db->u1.isInterrupted) ){
p->rc = SQLITE_INTERRUPT;
rc = SQLITE_ERROR;
sqlite3VdbeError(p, sqlite3ErrStr(p->rc));
}else{
- char *zP4;
- if( p->explain==1 ){
- pMem->flags = MEM_Int;
- 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 );
- pMem->n = sqlite3Strlen30(pMem->z);
- pMem->enc = SQLITE_UTF8;
- pMem++;
- }
-
- pMem->flags = MEM_Int;
- pMem->u.i = pOp->p1; /* P1 */
- pMem++;
-
- pMem->flags = MEM_Int;
- pMem->u.i = pOp->p2; /* P2 */
- pMem++;
-
- pMem->flags = MEM_Int;
- pMem->u.i = pOp->p3; /* P3 */
- pMem++;
-
- if( sqlite3VdbeMemClearAndResize(pMem, 100) ){ /* P4 */
- assert( p->db->mallocFailed );
- return SQLITE_ERROR;
- }
- pMem->flags = MEM_Str|MEM_Term;
- zP4 = displayP4(pOp, pMem->z, pMem->szMalloc);
- if( zP4!=pMem->z ){
- pMem->n = 0;
- sqlite3VdbeMemSetStr(pMem, zP4, -1, SQLITE_UTF8, 0);
+ char *zP4 = sqlite3VdbeDisplayP4(db, pOp);
+ if( p->explain==2 ){
+ sqlite3VdbeMemSetInt64(pMem, pOp->p1);
+ sqlite3VdbeMemSetInt64(pMem+1, pOp->p2);
+ sqlite3VdbeMemSetInt64(pMem+2, pOp->p3);
+ sqlite3VdbeMemSetStr(pMem+3, zP4, -1, SQLITE_UTF8, sqlite3_free);
+ p->nResColumn = 4;
}else{
- assert( pMem->z!=0 );
- pMem->n = sqlite3Strlen30(pMem->z);
- pMem->enc = SQLITE_UTF8;
- }
- pMem++;
-
- if( p->explain==1 ){
- if( sqlite3VdbeMemClearAndResize(pMem, 4) ){
- assert( p->db->mallocFailed );
- return SQLITE_ERROR;
- }
- pMem->flags = MEM_Str|MEM_Term;
- pMem->n = 2;
- sqlite3_snprintf(3, pMem->z, "%.2x", pOp->p5); /* P5 */
- pMem->enc = SQLITE_UTF8;
- pMem++;
-
+ sqlite3VdbeMemSetInt64(pMem+0, i);
+ sqlite3VdbeMemSetStr(pMem+1, (char*)sqlite3OpcodeName(pOp->opcode),
+ -1, SQLITE_UTF8, SQLITE_STATIC);
+ sqlite3VdbeMemSetInt64(pMem+2, pOp->p1);
+ sqlite3VdbeMemSetInt64(pMem+3, pOp->p2);
+ sqlite3VdbeMemSetInt64(pMem+4, pOp->p3);
+ /* pMem+5 for p4 is done last */
+ sqlite3VdbeMemSetInt64(pMem+6, pOp->p5);
#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
- if( sqlite3VdbeMemClearAndResize(pMem, 500) ){
- assert( p->db->mallocFailed );
- return SQLITE_ERROR;
+ {
+ char *zCom = sqlite3VdbeDisplayComment(db, pOp, zP4);
+ sqlite3VdbeMemSetStr(pMem+7, zCom, -1, SQLITE_UTF8, sqlite3_free);
}
- pMem->flags = MEM_Str|MEM_Term;
- pMem->n = displayComment(pOp, zP4, pMem->z, 500);
- pMem->enc = SQLITE_UTF8;
#else
- pMem->flags = MEM_Null; /* Comment */
+ sqlite3VdbeMemSetNull(pMem+7);
#endif
+ sqlite3VdbeMemSetStr(pMem+5, zP4, -1, SQLITE_UTF8, sqlite3_free);
+ p->nResColumn = 8;
+ }
+ p->pResultSet = pMem;
+ if( db->mallocFailed ){
+ p->rc = SQLITE_NOMEM;
+ rc = SQLITE_ERROR;
+ }else{
+ p->rc = SQLITE_OK;
+ rc = SQLITE_ROW;
}
-
- p->nResColumn = 8 - 4*(p->explain-1);
- p->pResultSet = &p->aMem[1];
- p->rc = SQLITE_OK;
- rc = SQLITE_ROW;
}
}
return rc;
@@ -77531,9 +81153,9 @@ SQLITE_PRIVATE void sqlite3VdbeIOTraceSql(Vdbe *p){
** of a ReusableSpace object by the allocSpace() routine below.
*/
struct ReusableSpace {
- u8 *pSpace; /* Available memory */
- int nFree; /* Bytes of available memory */
- int nNeeded; /* Total bytes that could not be allocated */
+ u8 *pSpace; /* Available memory */
+ sqlite3_int64 nFree; /* Bytes of available memory */
+ sqlite3_int64 nNeeded; /* Total bytes that could not be allocated */
};
/* Try to allocate nByte bytes of 8-byte aligned bulk memory for pBuf
@@ -77553,7 +81175,7 @@ struct ReusableSpace {
static void *allocSpace(
struct ReusableSpace *p, /* Bulk memory available for allocation */
void *pBuf, /* Pointer to a prior allocation */
- int nByte /* Bytes of memory needed */
+ sqlite3_int64 nByte /* Bytes of memory needed */
){
assert( EIGHT_BYTE_ALIGNMENT(p->pSpace) );
if( pBuf==0 ){
@@ -77578,14 +81200,14 @@ SQLITE_PRIVATE void sqlite3VdbeRewind(Vdbe *p){
int i;
#endif
assert( p!=0 );
- assert( p->magic==VDBE_MAGIC_INIT || p->magic==VDBE_MAGIC_RESET );
+ assert( p->iVdbeMagic==VDBE_MAGIC_INIT || p->iVdbeMagic==VDBE_MAGIC_RESET );
/* There should be at least one opcode.
*/
assert( p->nOp>0 );
/* Set the magic to VDBE_MAGIC_RUN sooner rather than later. */
- p->magic = VDBE_MAGIC_RUN;
+ p->iVdbeMagic = VDBE_MAGIC_RUN;
#ifdef SQLITE_DEBUG
for(i=0; inMem; i++){
@@ -77613,11 +81235,11 @@ SQLITE_PRIVATE void sqlite3VdbeRewind(Vdbe *p){
** creating the virtual machine. This involves things such
** as allocating registers 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 function may be called exactly once on each virtual machine.
** After this routine is called the VM has been "packaged" and is ready
-** to run. After this routine is called, further calls to
+** to run. After this routine is called, further calls to
** sqlite3VdbeAddOp() functions are prohibited. This routine disconnects
** the Vdbe from the Parse object that helped generate it so that the
** the Vdbe becomes an independent entity and the Parse object can be
@@ -77641,15 +81263,17 @@ SQLITE_PRIVATE void sqlite3VdbeMakeReady(
assert( p!=0 );
assert( p->nOp>0 );
assert( pParse!=0 );
- assert( p->magic==VDBE_MAGIC_INIT );
+ assert( p->iVdbeMagic==VDBE_MAGIC_INIT );
assert( pParse==p->pParse );
+ p->pVList = pParse->pVList;
+ pParse->pVList = 0;
db = p->db;
assert( db->mallocFailed==0 );
nVar = pParse->nVar;
nMem = pParse->nMem;
nCursor = pParse->nTab;
nArg = pParse->nMaxArg;
-
+
/* Each cursor uses a memory cell. The first cursor (cursor 0) can
** use aMem[0] which is not otherwise used by the VDBE program. Allocate
** space at the end of aMem[] for cursors 1 and greater.
@@ -77671,38 +81295,62 @@ SQLITE_PRIVATE void sqlite3VdbeMakeReady(
resolveP2Values(p, &nArg);
p->usesStmtJournal = (u8)(pParse->isMultiWrite && pParse->mayAbort);
- if( pParse->explain && nMem<10 ){
- nMem = 10;
+ if( pParse->explain ){
+ static const char * const azColName[] = {
+ "addr", "opcode", "p1", "p2", "p3", "p4", "p5", "comment",
+ "id", "parent", "notused", "detail"
+ };
+ int iFirst, mx, i;
+ if( nMem<10 ) nMem = 10;
+ p->explain = pParse->explain;
+ if( pParse->explain==2 ){
+ sqlite3VdbeSetNumCols(p, 4);
+ iFirst = 8;
+ mx = 12;
+ }else{
+ sqlite3VdbeSetNumCols(p, 8);
+ iFirst = 0;
+ mx = 8;
+ }
+ for(i=iFirst; iexpired = 0;
/* Memory for registers, parameters, cursor, etc, is allocated in one or two
- ** passes. On the first pass, we try to reuse unused memory at the
+ ** passes. On the first pass, we try to reuse unused memory 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 remainder using a fresh memory allocation.
+ ** pass will fill in the remainder using a fresh memory allocation.
**
** This two-pass approach that reuses as much memory as possible from
** the leftover memory at the end of the opcode array. This can significantly
** reduce the amount of memory held by a prepared statement.
*/
- do {
- x.nNeeded = 0;
- p->aMem = allocSpace(&x, p->aMem, nMem*sizeof(Mem));
- p->aVar = allocSpace(&x, p->aVar, nVar*sizeof(Mem));
- p->apArg = allocSpace(&x, p->apArg, nArg*sizeof(Mem*));
- p->apCsr = allocSpace(&x, p->apCsr, nCursor*sizeof(VdbeCursor*));
+ x.nNeeded = 0;
+ p->aMem = allocSpace(&x, 0, nMem*sizeof(Mem));
+ p->aVar = allocSpace(&x, 0, nVar*sizeof(Mem));
+ p->apArg = allocSpace(&x, 0, nArg*sizeof(Mem*));
+ p->apCsr = allocSpace(&x, 0, nCursor*sizeof(VdbeCursor*));
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
- p->anExec = allocSpace(&x, p->anExec, p->nOp*sizeof(i64));
+ p->anExec = allocSpace(&x, 0, p->nOp*sizeof(i64));
#endif
- if( x.nNeeded==0 ) break;
+ if( x.nNeeded ){
x.pSpace = p->pFree = sqlite3DbMallocRawNN(db, x.nNeeded);
x.nFree = x.nNeeded;
- }while( !db->mallocFailed );
+ if( !db->mallocFailed ){
+ p->aMem = allocSpace(&x, p->aMem, nMem*sizeof(Mem));
+ p->aVar = allocSpace(&x, p->aVar, nVar*sizeof(Mem));
+ p->apArg = allocSpace(&x, p->apArg, nArg*sizeof(Mem*));
+ p->apCsr = allocSpace(&x, p->apCsr, nCursor*sizeof(VdbeCursor*));
+#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
+ p->anExec = allocSpace(&x, p->anExec, p->nOp*sizeof(i64));
+#endif
+ }
+ }
- p->pVList = pParse->pVList;
- pParse->pVList = 0;
- p->explain = pParse->explain;
if( db->mallocFailed ){
p->nVar = 0;
p->nCursor = 0;
@@ -77722,7 +81370,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){
@@ -77730,20 +81378,15 @@ SQLITE_PRIVATE void sqlite3VdbeFreeCursor(Vdbe *p, VdbeCursor *pCx){
return;
}
assert( pCx->pBtx==0 || pCx->eCurType==CURTYPE_BTREE );
+ assert( pCx->pBtx==0 || pCx->isEphemeral );
switch( pCx->eCurType ){
case CURTYPE_SORTER: {
sqlite3VdbeSorterClose(p->db, pCx);
break;
}
case CURTYPE_BTREE: {
- if( pCx->isEphemeral ){
- if( pCx->pBtx ) sqlite3BtreeClose(pCx->pBtx);
- /* The pCx->pCursor will be close automatically, if it exists, by
- ** the call above. */
- }else{
- assert( pCx->uc.pCursor!=0 );
- sqlite3BtreeCloseCursor(pCx->uc.pCursor);
- }
+ assert( pCx->uc.pCursor!=0 );
+ sqlite3BtreeCloseCursor(pCx->uc.pCursor);
break;
}
#ifndef SQLITE_OMIT_VIRTUALTABLE
@@ -77804,7 +81447,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.
@@ -77890,43 +81533,43 @@ SQLITE_PRIVATE int sqlite3VdbeSetColName(
** A read or write transaction may or may not be active on database handle
** db. If a transaction is active, commit it. If there is a
** write-transaction spanning more than one database file, this routine
-** takes care of the master journal trickery.
+** takes care of the super-journal trickery.
*/
static int vdbeCommit(sqlite3 *db, Vdbe *p){
int i;
int nTrans = 0; /* Number of databases with an active write-transaction
** that are candidates for a two-phase commit using a
- ** master-journal */
+ ** super-journal */
int rc = SQLITE_OK;
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 super-journal file is
** required, as an xSync() callback may add an attached database
** to the transaction.
*/
rc = sqlite3VtabSync(db, p);
/* This loop determines (a) if the commit hook should be invoked and
- ** (b) how many database files have open write transactions, not
- ** including the temp database. (b) is important because if more than
- ** one database file has an open write transaction, a master journal
+ ** (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 super-journal
** file is required for an atomic commit.
- */
- for(i=0; rc==SQLITE_OK && inDb; i++){
+ */
+ for(i=0; rc==SQLITE_OK && inDb; i++){
Btree *pBt = db->aDb[i].pBt;
- if( sqlite3BtreeIsInTrans(pBt) ){
- /* Whether or not a database might need a master journal depends upon
+ if( sqlite3BtreeTxnState(pBt)==SQLITE_TXN_WRITE ){
+ /* Whether or not a database might need a super-journal depends upon
** its journal mode (among other things). This matrix determines which
- ** journal modes use a master journal and which do not */
+ ** journal modes use a super-journal and which do not */
static const u8 aMJNeeded[] = {
/* DELETE */ 1,
/* PERSIST */ 1,
@@ -77942,7 +81585,7 @@ static int vdbeCommit(sqlite3 *db, Vdbe *p){
if( db->aDb[i].safety_level!=PAGER_SYNCHRONOUS_OFF
&& aMJNeeded[sqlite3PagerGetJournalMode(pPager)]
&& sqlite3PagerIsMemdb(pPager)==0
- ){
+ ){
assert( i!=1 );
nTrans++;
}
@@ -77964,11 +81607,11 @@ static int vdbeCommit(sqlite3 *db, Vdbe *p){
/* The simple case - no more than one database file (not counting the
** TEMP database) has a transaction active. There is no need for the
- ** master-journal.
+ ** super-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))
@@ -77981,7 +81624,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.
@@ -77998,124 +81641,125 @@ static int vdbeCommit(sqlite3 *db, Vdbe *p){
}
/* The complex case - There is a multi-file write-transaction active.
- ** This requires a master journal file to ensure the transaction is
+ ** This requires a super-journal file to ensure the transaction is
** committed atomically.
*/
#ifndef SQLITE_OMIT_DISKIO
else{
sqlite3_vfs *pVfs = db->pVfs;
- char *zMaster = 0; /* File-name for the master journal */
+ char *zSuper = 0; /* File-name for the super-journal */
char const *zMainFile = sqlite3BtreeGetFilename(db->aDb[0].pBt);
- sqlite3_file *pMaster = 0;
+ sqlite3_file *pSuperJrnl = 0;
i64 offset = 0;
int res;
int retryCount = 0;
int nMainFile;
- /* Select a master journal file name */
+ /* Select a super-journal file name */
nMainFile = sqlite3Strlen30(zMainFile);
- zMaster = sqlite3MPrintf(db, "%s-mjXXXXXX9XXz", zMainFile);
- if( zMaster==0 ) return SQLITE_NOMEM_BKPT;
+ zSuper = sqlite3MPrintf(db, "%.4c%s%.16c", 0,zMainFile,0);
+ if( zSuper==0 ) return SQLITE_NOMEM_BKPT;
+ zSuper += 4;
do {
u32 iRandom;
if( retryCount ){
if( retryCount>100 ){
- sqlite3_log(SQLITE_FULL, "MJ delete: %s", zMaster);
- sqlite3OsDelete(pVfs, zMaster, 0);
+ sqlite3_log(SQLITE_FULL, "MJ delete: %s", zSuper);
+ sqlite3OsDelete(pVfs, zSuper, 0);
break;
}else if( retryCount==1 ){
- sqlite3_log(SQLITE_FULL, "MJ collide: %s", zMaster);
+ sqlite3_log(SQLITE_FULL, "MJ collide: %s", zSuper);
}
}
retryCount++;
sqlite3_randomness(sizeof(iRandom), &iRandom);
- sqlite3_snprintf(13, &zMaster[nMainFile], "-mj%06X9%02X",
+ sqlite3_snprintf(13, &zSuper[nMainFile], "-mj%06X9%02X",
(iRandom>>8)&0xffffff, iRandom&0xff);
- /* The antipenultimate character of the master journal name must
+ /* The antipenultimate character of the super-journal name must
** be "9" to avoid name collisions when using 8+3 filenames. */
- assert( zMaster[sqlite3Strlen30(zMaster)-3]=='9' );
- sqlite3FileSuffix3(zMainFile, zMaster);
- rc = sqlite3OsAccess(pVfs, zMaster, SQLITE_ACCESS_EXISTS, &res);
+ assert( zSuper[sqlite3Strlen30(zSuper)-3]=='9' );
+ sqlite3FileSuffix3(zMainFile, zSuper);
+ rc = sqlite3OsAccess(pVfs, zSuper, SQLITE_ACCESS_EXISTS, &res);
}while( rc==SQLITE_OK && res );
if( rc==SQLITE_OK ){
- /* Open the master journal. */
- rc = sqlite3OsOpenMalloc(pVfs, zMaster, &pMaster,
+ /* Open the super-journal. */
+ rc = sqlite3OsOpenMalloc(pVfs, zSuper, &pSuperJrnl,
SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|
- SQLITE_OPEN_EXCLUSIVE|SQLITE_OPEN_MASTER_JOURNAL, 0
+ SQLITE_OPEN_EXCLUSIVE|SQLITE_OPEN_SUPER_JOURNAL, 0
);
}
if( rc!=SQLITE_OK ){
- sqlite3DbFree(db, zMaster);
+ sqlite3DbFree(db, zSuper-4);
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
- ** still have 'null' as the master journal pointer, so they will roll
+ ** super-journal file. If an error occurs at this point close
+ ** and delete the super-journal file. All the individual journal files
+ ** still have 'null' as the super-journal pointer, so they will roll
** back independently if a failure occurs.
*/
for(i=0; inDb; i++){
Btree *pBt = db->aDb[i].pBt;
- if( sqlite3BtreeIsInTrans(pBt) ){
+ if( sqlite3BtreeTxnState(pBt)==SQLITE_TXN_WRITE ){
char const *zFile = sqlite3BtreeGetJournalname(pBt);
if( zFile==0 ){
continue; /* Ignore TEMP and :memory: databases */
}
assert( zFile[0]!=0 );
- rc = sqlite3OsWrite(pMaster, zFile, sqlite3Strlen30(zFile)+1, offset);
+ rc = sqlite3OsWrite(pSuperJrnl, zFile, sqlite3Strlen30(zFile)+1,offset);
offset += sqlite3Strlen30(zFile)+1;
if( rc!=SQLITE_OK ){
- sqlite3OsCloseFree(pMaster);
- sqlite3OsDelete(pVfs, zMaster, 0);
- sqlite3DbFree(db, zMaster);
+ sqlite3OsCloseFree(pSuperJrnl);
+ sqlite3OsDelete(pVfs, zSuper, 0);
+ sqlite3DbFree(db, zSuper-4);
return rc;
}
}
}
- /* Sync the master journal file. If the IOCAP_SEQUENTIAL device
+ /* Sync the super-journal file. If the IOCAP_SEQUENTIAL device
** flag is set this is not required.
*/
- if( 0==(sqlite3OsDeviceCharacteristics(pMaster)&SQLITE_IOCAP_SEQUENTIAL)
- && SQLITE_OK!=(rc = sqlite3OsSync(pMaster, SQLITE_SYNC_NORMAL))
+ if( 0==(sqlite3OsDeviceCharacteristics(pSuperJrnl)&SQLITE_IOCAP_SEQUENTIAL)
+ && SQLITE_OK!=(rc = sqlite3OsSync(pSuperJrnl, SQLITE_SYNC_NORMAL))
){
- sqlite3OsCloseFree(pMaster);
- sqlite3OsDelete(pVfs, zMaster, 0);
- sqlite3DbFree(db, zMaster);
+ sqlite3OsCloseFree(pSuperJrnl);
+ sqlite3OsDelete(pVfs, zSuper, 0);
+ sqlite3DbFree(db, zSuper-4);
return rc;
}
/* Sync all the db files involved in the transaction. The same call
- ** sets the master journal pointer in each individual journal. If
- ** an error occurs here, do not delete the master journal file.
+ ** sets the super-journal pointer in each individual journal. If
+ ** an error occurs here, do not delete the super-journal file.
**
** If the error occurs during the first call to
** sqlite3BtreeCommitPhaseOne(), then there is a chance that the
- ** master journal file will be orphaned. But we cannot delete it,
- ** in case the master journal file name was written into the journal
+ ** super-journal file will be orphaned. But we cannot delete it,
+ ** in case the super-journal file name was written into the journal
** file before the failure occurred.
*/
- for(i=0; rc==SQLITE_OK && inDb; i++){
+ for(i=0; rc==SQLITE_OK && inDb; i++){
Btree *pBt = db->aDb[i].pBt;
if( pBt ){
- rc = sqlite3BtreeCommitPhaseOne(pBt, zMaster);
+ rc = sqlite3BtreeCommitPhaseOne(pBt, zSuper);
}
}
- sqlite3OsCloseFree(pMaster);
+ sqlite3OsCloseFree(pSuperJrnl);
assert( rc!=SQLITE_BUSY );
if( rc!=SQLITE_OK ){
- sqlite3DbFree(db, zMaster);
+ sqlite3DbFree(db, zSuper-4);
return rc;
}
- /* Delete the master journal file. This commits the transaction. After
+ /* Delete the super-journal file. This commits the transaction. After
** doing this the directory is synced again before any individual
** transaction files are deleted.
*/
- rc = sqlite3OsDelete(pVfs, zMaster, 1);
- sqlite3DbFree(db, zMaster);
- zMaster = 0;
+ rc = sqlite3OsDelete(pVfs, zSuper, 1);
+ sqlite3DbFree(db, zSuper-4);
+ zSuper = 0;
if( rc ){
return rc;
}
@@ -78129,7 +81773,7 @@ static int vdbeCommit(sqlite3 *db, Vdbe *p){
*/
disable_simulated_io_errors();
sqlite3BeginBenignMalloc();
- for(i=0; inDb; i++){
+ for(i=0; inDb; i++){
Btree *pBt = db->aDb[i].pBt;
if( pBt ){
sqlite3BtreeCommitPhaseTwo(pBt, 1);
@@ -78145,7 +81789,7 @@ static int vdbeCommit(sqlite3 *db, Vdbe *p){
return rc;
}
-/*
+/*
** This routine checks that the sqlite3.nVdbeActive count variable
** matches the number of vdbe's in the list sqlite3.pVdbe that are
** currently active. An assertion fails if the two counts do not match.
@@ -78181,10 +81825,10 @@ static void checkActiveVdbeCnt(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 committed.
**
-** 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.
*/
static SQLITE_NOINLINE int vdbeCloseStatement(Vdbe *p, int eOp){
@@ -78197,7 +81841,7 @@ static SQLITE_NOINLINE int vdbeCloseStatement(Vdbe *p, int eOp){
assert( db->nStatement>0 );
assert( p->iStatement==(db->nStatement+db->nSavepoint) );
- for(i=0; inDb; i++){
+ for(i=0; inDb; i++){
int rc2 = SQLITE_OK;
Btree *pBt = db->aDb[i].pBt;
if( pBt ){
@@ -78224,8 +81868,8 @@ static SQLITE_NOINLINE int vdbeCloseStatement(Vdbe *p, int eOp){
}
}
- /* 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;
@@ -78242,20 +81886,20 @@ SQLITE_PRIVATE int sqlite3VdbeCloseStatement(Vdbe *p, int eOp){
/*
-** 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_FOREIGNKEY
** and write an error message to it. Then return SQLITE_ERROR.
*/
#ifndef SQLITE_OMIT_FOREIGN_KEY
SQLITE_PRIVATE int sqlite3VdbeCheckFk(Vdbe *p, int deferred){
sqlite3 *db = p->db;
- if( (deferred && (db->nDeferredCons+db->nDeferredImmCons)>0)
- || (!deferred && p->nFkConstraint>0)
+ if( (deferred && (db->nDeferredCons+db->nDeferredImmCons)>0)
+ || (!deferred && p->nFkConstraint>0)
){
p->rc = SQLITE_CONSTRAINT_FOREIGNKEY;
p->errorAction = OE_Abort;
@@ -78285,7 +81929,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:
**
@@ -78299,7 +81943,7 @@ SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe *p){
** one, or the complete transaction if there is no statement transaction.
*/
- if( p->magic!=VDBE_MAGIC_RUN ){
+ if( p->iVdbeMagic!=VDBE_MAGIC_RUN ){
return SQLITE_OK;
}
if( db->mallocFailed ){
@@ -78323,16 +81967,16 @@ SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe *p){
isSpecialError = mrc==SQLITE_NOMEM || mrc==SQLITE_IOERR
|| mrc==SQLITE_INTERRUPT || mrc==SQLITE_FULL;
if( isSpecialError ){
- /* If the query was read-only and the error code is SQLITE_INTERRUPT,
- ** no rollback is necessary. Otherwise, at least a savepoint
- ** transaction must be rolled back to restore the database to a
+ /* If the query was read-only and the error code is SQLITE_INTERRUPT,
+ ** no rollback is necessary. Otherwise, at least a savepoint
+ ** transaction must be rolled back to restore the database to a
** consistent state.
**
** Even if the statement is read-only, it is important to perform
- ** a statement or transaction rollback operation. If the error
+ ** a statement or transaction rollback operation. If the error
** occurred while writing to the journal, sub-journal or database
** file as part of an effort to free up cache space (see function
- ** pagerStress() in pager.c), the rollback is required to restore
+ ** pagerStress() in pager.c), the rollback is required to restore
** the pager to a consistent state.
*/
if( !p->readOnly || mrc!=SQLITE_INTERRUPT ){
@@ -78351,19 +81995,19 @@ SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe *p){
}
/* Check for immediate foreign key violations. */
- if( p->rc==SQLITE_OK ){
+ if( p->rc==SQLITE_OK || (p->errorAction==OE_Fail && !isSpecialError) ){
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->nVdbeWrite==(p->readOnly==0)
+ if( !sqlite3VtabInSync(db)
+ && db->autoCommit
+ && db->nVdbeWrite==(p->readOnly==0)
){
if( p->rc==SQLITE_OK || (p->errorAction==OE_Fail && !isSpecialError) ){
rc = sqlite3VdbeCheckFk(p, 1);
@@ -78373,10 +82017,10 @@ SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe *p){
return SQLITE_ERROR;
}
rc = SQLITE_CONSTRAINT_FOREIGNKEY;
- }else{
- /* The auto-commit flag is true, the vdbe program was successful
+ }else{
+ /* 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);
}
@@ -78390,7 +82034,7 @@ SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe *p){
}else{
db->nDeferredCons = 0;
db->nDeferredImmCons = 0;
- db->flags &= ~SQLITE_DeferFKs;
+ db->flags &= ~(u64)SQLITE_DeferFKs;
sqlite3CommitInternalChanges(db);
}
}else{
@@ -78410,7 +82054,7 @@ SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe *p){
p->nChange = 0;
}
}
-
+
/* 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
@@ -78431,9 +82075,9 @@ SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe *p){
p->nChange = 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 ){
@@ -78457,14 +82101,14 @@ SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe *p){
assert( db->nVdbeRead>=db->nVdbeWrite );
assert( db->nVdbeWrite>=0 );
}
- p->magic = VDBE_MAGIC_HALT;
+ p->iVdbeMagic = VDBE_MAGIC_HALT;
checkActiveVdbeCnt(db);
if( db->mallocFailed ){
p->rc = SQLITE_NOMEM_BKPT;
}
/* 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 ){
@@ -78486,7 +82130,7 @@ SQLITE_PRIVATE void sqlite3VdbeResetStepResult(Vdbe *p){
/*
** Copy the error code and error message belonging to the VDBE passed
-** as the first argument to its database handle (so that they will be
+** as the first argument to its database handle (so that they will be
** returned by calls to sqlite3_errcode() and sqlite3_errmsg()).
**
** This function does not clear the VDBE error code or message, just
@@ -78511,7 +82155,7 @@ SQLITE_PRIVATE int sqlite3VdbeTransferError(Vdbe *p){
#ifdef SQLITE_ENABLE_SQLLOG
/*
-** If an SQLITE_CONFIG_SQLLOG hook is registered and the VM has been run,
+** If an SQLITE_CONFIG_SQLLOG hook is registered and the VM has been run,
** invoke it.
*/
static void vdbeInvokeSqllog(Vdbe *v){
@@ -78562,7 +82206,11 @@ SQLITE_PRIVATE int sqlite3VdbeReset(Vdbe *p){
*/
if( p->pc>=0 ){
vdbeInvokeSqllog(p);
- sqlite3VdbeTransferError(p);
+ if( db->pErr || p->zErrMsg ){
+ sqlite3VdbeTransferError(p);
+ }else{
+ db->errCode = p->rc;
+ }
if( p->runOnlyOnce ) p->expired = 1;
}else if( p->rc && p->expired ){
/* The expired flag was set on the VDBE before the first call
@@ -78575,15 +82223,17 @@ SQLITE_PRIVATE int sqlite3VdbeReset(Vdbe *p){
/* Reset register contents and reclaim error message memory.
*/
#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. */
if( p->apCsr ) for(i=0; inCursor; i++) assert( p->apCsr[i]==0 );
if( p->aMem ){
for(i=0; inMem; i++) assert( p->aMem[i].flags==MEM_Undefined );
}
#endif
- sqlite3DbFree(db, p->zErrMsg);
- p->zErrMsg = 0;
+ if( p->zErrMsg ){
+ sqlite3DbFree(db, p->zErrMsg);
+ p->zErrMsg = 0;
+ }
p->pResultSet = 0;
#ifdef SQLITE_DEBUG
p->nWrite = 0;
@@ -78624,17 +82274,17 @@ SQLITE_PRIVATE int sqlite3VdbeReset(Vdbe *p){
}
}
#endif
- p->magic = VDBE_MAGIC_RESET;
+ p->iVdbeMagic = VDBE_MAGIC_RESET;
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.
*/
SQLITE_PRIVATE int sqlite3VdbeFinalize(Vdbe *p){
int rc = SQLITE_OK;
- if( p->magic==VDBE_MAGIC_RUN || p->magic==VDBE_MAGIC_HALT ){
+ if( p->iVdbeMagic==VDBE_MAGIC_RUN || p->iVdbeMagic==VDBE_MAGIC_HALT ){
rc = sqlite3VdbeReset(p);
assert( (rc & p->db->errMask)==rc );
}
@@ -78648,8 +82298,8 @@ SQLITE_PRIVATE int sqlite3VdbeFinalize(Vdbe *p){
** the first argument.
**
** Or, if iOp is greater than or equal to zero, then the destructor is
-** only invoked for those auxiliary data pointers created by the user
-** function invoked by the OP_Function opcode at instruction iOp of
+** only invoked for those auxiliary data pointers created by the user
+** function invoked by the OP_Function opcode at instruction iOp of
** VM pVdbe, and only then if:
**
** * the associated function parameter is the 32nd or later (counting
@@ -78695,7 +82345,7 @@ SQLITE_PRIVATE void sqlite3VdbeClearObject(sqlite3 *db, Vdbe *p){
vdbeFreeOpArray(db, pSub->aOp, pSub->nOp);
sqlite3DbFree(db, pSub);
}
- if( p->magic!=VDBE_MAGIC_INIT ){
+ if( p->iVdbeMagic!=VDBE_MAGIC_INIT ){
releaseMemArray(p->aVar, p->nVar);
sqlite3DbFree(db, p->pVList);
sqlite3DbFree(db, p->pFree);
@@ -78703,6 +82353,16 @@ SQLITE_PRIVATE void sqlite3VdbeClearObject(sqlite3 *db, Vdbe *p){
vdbeFreeOpArray(db, p->aOp, p->nOp);
sqlite3DbFree(db, p->aColName);
sqlite3DbFree(db, p->zSql);
+#ifdef SQLITE_ENABLE_NORMALIZE
+ sqlite3DbFree(db, p->zNormSql);
+ {
+ DblquoteStr *pThis, *pNext;
+ for(pThis=p->pDblStr; pThis; pThis=pNext){
+ pNext = pThis->pNextStr;
+ sqlite3DbFree(db, pThis);
+ }
+ }
+#endif
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
{
int i;
@@ -78733,7 +82393,7 @@ SQLITE_PRIVATE void sqlite3VdbeDelete(Vdbe *p){
if( p->pNext ){
p->pNext->pPrev = p->pPrev;
}
- p->magic = VDBE_MAGIC_DEAD;
+ p->iVdbeMagic = VDBE_MAGIC_DEAD;
p->db = 0;
sqlite3DbFreeNN(db, p);
}
@@ -78743,7 +82403,7 @@ SQLITE_PRIVATE void sqlite3VdbeDelete(Vdbe *p){
** carried out. Seek the cursor now. If an error occurs, return
** the appropriate error code.
*/
-static int SQLITE_NOINLINE handleDeferredMoveto(VdbeCursor *p){
+SQLITE_PRIVATE int SQLITE_NOINLINE sqlite3VdbeFinishMoveto(VdbeCursor *p){
int res, rc;
#ifdef SQLITE_TEST
extern int sqlite3_search_count;
@@ -78805,17 +82465,18 @@ SQLITE_PRIVATE int sqlite3VdbeCursorRestore(VdbeCursor *p){
** If the cursor is already pointing to the correct row and that row has
** not been deleted out from under the cursor, then this routine is a no-op.
*/
-SQLITE_PRIVATE int sqlite3VdbeCursorMoveto(VdbeCursor **pp, int *piCol){
+SQLITE_PRIVATE int sqlite3VdbeCursorMoveto(VdbeCursor **pp, u32 *piCol){
VdbeCursor *p = *pp;
assert( p->eCurType==CURTYPE_BTREE || p->eCurType==CURTYPE_PSEUDO );
if( p->deferredMoveto ){
- int iMap;
- if( p->aAltMap && (iMap = p->aAltMap[1+*piCol])>0 ){
+ u32 iMap;
+ assert( !p->isEphemeral );
+ if( p->aAltMap && (iMap = p->aAltMap[1+*piCol])>0 && !p->nullRow ){
*pp = p->pAltCursor;
*piCol = iMap - 1;
return SQLITE_OK;
}
- return handleDeferredMoveto(p);
+ return sqlite3VdbeFinishMoveto(p);
}
if( sqlite3BtreeCursorHasMoved(p->uc.pCursor) ){
return handleMovedCursor(p);
@@ -78865,8 +82526,17 @@ SQLITE_PRIVATE int sqlite3VdbeCursorMoveto(VdbeCursor **pp, int *piCol){
** of SQLite will not understand those serial types.
*/
+#if 0 /* Inlined into the OP_MakeRecord opcode */
/*
** Return the serial-type for the value stored in pMem.
+**
+** This routine might convert a large MEM_IntReal value into MEM_Real.
+**
+** 2019-07-11: The primary user of this subroutine was the OP_MakeRecord
+** opcode in the byte-code engine. But by moving this routine in-line, we
+** can omit some redundant tests and make that opcode a lot faster. So
+** this routine is now only used by the STAT3 logic and STAT3 support has
+** ended. The code is kept here for historical reference only.
*/
SQLITE_PRIVATE u32 sqlite3VdbeSerialType(Mem *pMem, int file_format, u32 *pLen){
int flags = pMem->flags;
@@ -78877,11 +82547,13 @@ SQLITE_PRIVATE u32 sqlite3VdbeSerialType(Mem *pMem, int file_format, u32 *pLen){
*pLen = 0;
return 0;
}
- if( flags&MEM_Int ){
+ if( flags&(MEM_Int|MEM_IntReal) ){
/* Figure out whether to use 1, 2, 4, 6 or 8 bytes. */
# define MAX_6BYTE ((((i64)0x00008000)<<32)-1)
i64 i = pMem->u.i;
u64 u;
+ testcase( flags & MEM_Int );
+ testcase( flags & MEM_IntReal );
if( i<0 ){
u = ~i;
}else{
@@ -78901,6 +82573,15 @@ SQLITE_PRIVATE u32 sqlite3VdbeSerialType(Mem *pMem, int file_format, u32 *pLen){
if( u<=2147483647 ){ *pLen = 4; return 4; }
if( u<=MAX_6BYTE ){ *pLen = 6; return 5; }
*pLen = 8;
+ if( flags&MEM_IntReal ){
+ /* If the value is IntReal and is going to take up 8 bytes to store
+ ** as an integer, then we might as well make it an 8-byte floating
+ ** point value */
+ pMem->u.r = (double)pMem->u.i;
+ pMem->flags &= ~MEM_IntReal;
+ pMem->flags |= MEM_Real;
+ return 7;
+ }
return 6;
}
if( flags&MEM_Real ){
@@ -78916,12 +82597,13 @@ SQLITE_PRIVATE u32 sqlite3VdbeSerialType(Mem *pMem, int file_format, u32 *pLen){
*pLen = n;
return ((n*2) + 12 + ((flags&MEM_Str)!=0));
}
+#endif /* inlined into OP_MakeRecord */
/*
** The sizes for serial types less than 128
*/
static const u8 sqlite3SmallTypeSizes[] = {
- /* 0 1 2 3 4 5 6 7 8 9 */
+ /* 0 1 2 3 4 5 6 7 8 9 */
/* 0 */ 0, 1, 2, 3, 4, 6, 8, 8, 0, 0,
/* 10 */ 0, 0, 0, 0, 1, 1, 2, 2, 3, 3,
/* 20 */ 4, 4, 5, 5, 6, 6, 7, 7, 8, 8,
@@ -78944,19 +82626,19 @@ SQLITE_PRIVATE u32 sqlite3VdbeSerialTypeLen(u32 serial_type){
if( serial_type>=128 ){
return (serial_type-12)/2;
}else{
- assert( serial_type<12
+ assert( serial_type<12
|| sqlite3SmallTypeSizes[serial_type]==(serial_type - 12)/2 );
return sqlite3SmallTypeSizes[serial_type];
}
}
SQLITE_PRIVATE u8 sqlite3VdbeOneByteSerialTypeLen(u8 serial_type){
assert( serial_type<128 );
- return sqlite3SmallTypeSizes[serial_type];
+ return sqlite3SmallTypeSizes[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.
@@ -78978,7 +82660,7 @@ SQLITE_PRIVATE u8 sqlite3VdbeOneByteSerialTypeLen(u8 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,
@@ -79008,7 +82690,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.
**
@@ -79019,7 +82701,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, Mem *pMem, u32 serial_type){
u32 len;
@@ -79073,8 +82755,8 @@ SQLITE_PRIVATE u32 sqlite3VdbeSerialPut(u8 *buf, Mem *pMem, u32 serial_type){
** The few cases that require local variables are broken out into a separate
** routine so that in most cases the overhead of moving the stack pointer
** is avoided.
-*/
-static u32 SQLITE_NOINLINE serialGet(
+*/
+static u32 serialGet(
const unsigned char *buf, /* Buffer to deserialize from */
u32 serial_type, /* Serial type to deserialize */
Mem *pMem /* Memory cell to write value into */
@@ -79106,7 +82788,7 @@ static u32 SQLITE_NOINLINE serialGet(
assert( sizeof(x)==8 && sizeof(pMem->u.r)==8 );
swapMixedEndianFloat(x);
memcpy(&pMem->u.r, &x, sizeof(x));
- pMem->flags = sqlite3IsNaN(pMem->u.r) ? MEM_Null : MEM_Real;
+ pMem->flags = IsNaN(x) ? MEM_Null : MEM_Real;
}
return 8;
}
@@ -79157,7 +82839,7 @@ SQLITE_PRIVATE u32 sqlite3VdbeSerialGet(
/* EVIDENCE-OF: R-01849-26079 Value is a big-endian 32-bit
** twos-complement integer. */
pMem->u.i = FOUR_BYTE_INT(buf);
-#ifdef __HP_cc
+#ifdef __HP_cc
/* Work around a sign-extension bug in the HP compiler for HP/UX */
if( buf[0]&0x80 ) pMem->u.i |= 0xffffffff80000000LL;
#endif
@@ -79209,7 +82891,7 @@ SQLITE_PRIVATE u32 sqlite3VdbeSerialGet(
** The space is either allocated using sqlite3DbMallocRaw() or from within
** the unaligned buffer passed via the second and third arguments (presumably
** stack space). If the former, then *ppFree is set to a pointer that should
-** be eventually freed by the caller using sqlite3DbFree(). Or, if the
+** be eventually freed by the caller using sqlite3DbFree(). Or, if the
** allocation comes from the pSpace/szSpace buffer, *ppFree is set to NULL
** before returning.
**
@@ -79224,17 +82906,17 @@ SQLITE_PRIVATE UnpackedRecord *sqlite3VdbeAllocUnpackedRecord(
p = (UnpackedRecord *)sqlite3DbMallocRaw(pKeyInfo->db, nByte);
if( !p ) return 0;
p->aMem = (Mem*)&((char*)p)[ROUND8(sizeof(UnpackedRecord))];
- assert( pKeyInfo->aSortOrder!=0 );
+ assert( pKeyInfo->aSortFlags!=0 );
p->pKeyInfo = pKeyInfo;
p->nField = pKeyInfo->nKeyField + 1;
return p;
}
/*
-** Given the nKey-byte encoding of a record in pKey[], populate the
+** Given the nKey-byte encoding of a record in pKey[], populate the
** UnpackedRecord structure indicated by the fourth argument with the
** contents of the decoded record.
-*/
+*/
SQLITE_PRIVATE void sqlite3VdbeRecordUnpack(
KeyInfo *pKeyInfo, /* Information about the record format */
int nKey, /* Size of the binary record */
@@ -79242,7 +82924,7 @@ SQLITE_PRIVATE void sqlite3VdbeRecordUnpack(
UnpackedRecord *p /* Populate this structure before returning. */
){
const unsigned char *aKey = (const unsigned char *)pKey;
- int d;
+ u32 d;
u32 idx; /* Offset in aKey[] to read from */
u16 u; /* Unsigned loop counter */
u32 szHdr;
@@ -79253,7 +82935,7 @@ SQLITE_PRIVATE void sqlite3VdbeRecordUnpack(
idx = getVarint32(aKey, szHdr);
d = szHdr;
u = 0;
- while( idx=p->nField ) break;
}
+ if( d>(u32)nKey && u ){
+ assert( CORRUPT_DB );
+ /* In a corrupt record entry, the last pMem might have been set up using
+ ** uninitialized memory. Overwrite its value with NULL, to prevent
+ ** warnings from MSAN. */
+ sqlite3VdbeMemSetNull(pMem-1);
+ }
assert( u<=pKeyInfo->nKeyField + 1 );
p->nField = u;
}
@@ -79305,18 +82994,18 @@ static int vdbeRecordCompareDebug(
/* 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 uninitialized, and doing
+ ** But in fact, mem1.u.i will never actually be used uninitialized, 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);
if( szHdr1>98307 ) return SQLITE_CORRUPT;
d1 = szHdr1;
assert( pKeyInfo->nAllField>=pPKey2->nField || CORRUPT_DB );
- assert( pKeyInfo->aSortOrder!=0 );
+ assert( pKeyInfo->aSortFlags!=0 );
assert( pKeyInfo->nKeyField>0 );
assert( idx1<=szHdr1 || CORRUPT_DB );
do{
@@ -79331,8 +83020,8 @@ static int vdbeRecordCompareDebug(
** Use that approximation to avoid the more expensive call to
** sqlite3VdbeSerialTypeLen() in the common case.
*/
- if( d1+serial_type1+2>(u32)nKey1
- && d1+sqlite3VdbeSerialTypeLen(serial_type1)>(u32)nKey1
+ if( d1+(u64)serial_type1+2>(u64)nKey1
+ && d1+(u64)sqlite3VdbeSerialTypeLen(serial_type1)>(u64)nKey1
){
break;
}
@@ -79343,10 +83032,16 @@ static int vdbeRecordCompareDebug(
/* Do the comparison
*/
- rc = sqlite3MemCompare(&mem1, &pPKey2->aMem[i], pKeyInfo->aColl[i]);
+ rc = sqlite3MemCompare(&mem1, &pPKey2->aMem[i],
+ pKeyInfo->nAllField>i ? pKeyInfo->aColl[i] : 0);
if( rc!=0 ){
assert( mem1.szMalloc==0 ); /* See comment below */
- if( pKeyInfo->aSortOrder[i] ){
+ if( (pKeyInfo->aSortFlags[i] & KEYINFO_ORDER_BIGNULL)
+ && ((mem1.flags & MEM_Null) || (pPKey2->aMem[i].flags & MEM_Null))
+ ){
+ rc = -rc;
+ }
+ if( pKeyInfo->aSortFlags[i] & KEYINFO_ORDER_DESC ){
rc = -rc; /* Invert the result for DESC sort order. */
}
goto debugCompareEnd;
@@ -79388,7 +83083,7 @@ debugCompareEnd:
** incorrectly.
*/
static void vdbeAssertFieldCountWithinLimits(
- int nKey, const void *pKey, /* The record to verify */
+ int nKey, const void *pKey, /* The record to verify */
const KeyInfo *pKeyInfo /* Compare size with this KeyInfo */
){
int nField = 0;
@@ -79414,7 +83109,7 @@ static void vdbeAssertFieldCountWithinLimits(
/*
** Both *pMem1 and *pMem2 contain string values. Compare the two values
** using the collation sequence pColl. As usual, return a negative , zero
-** or positive value if *pMem1 is less than, equal to or greater than
+** or positive value if *pMem1 is less than, equal to or greater than
** *pMem2, respectively. Similar in spirit to "rc = (*pMem1) - (*pMem2);".
*/
static int vdbeCompareMemString(
@@ -79503,9 +83198,12 @@ SQLITE_PRIVATE SQLITE_NOINLINE int sqlite3BlobCompare(const Mem *pB1, const Mem
static int sqlite3IntFloatCompare(i64 i, double r){
if( sizeof(LONGDOUBLE_TYPE)>8 ){
LONGDOUBLE_TYPE x = (LONGDOUBLE_TYPE)i;
+ testcase( xr );
+ testcase( x==r );
if( xr ) return +1;
- return 0;
+ if( x>r ) return +1; /*NO_TEST*/ /* work around bugs in gcov */
+ return 0; /*NO_TEST*/ /* work around bugs in gcov */
}else{
i64 y;
double s;
@@ -79538,7 +83236,7 @@ SQLITE_PRIVATE int sqlite3MemCompare(const Mem *pMem1, const Mem *pMem2, const C
f2 = pMem2->flags;
combined_flags = f1|f2;
assert( !sqlite3VdbeMemIsRowSet(pMem1) && !sqlite3VdbeMemIsRowSet(pMem2) );
-
+
/* If one value is NULL, it is less than the other. If both values
** are NULL, return 0.
*/
@@ -79548,8 +83246,13 @@ SQLITE_PRIVATE int sqlite3MemCompare(const Mem *pMem1, const Mem *pMem2, const C
/* At least one of the two values is a number
*/
- if( combined_flags&(MEM_Int|MEM_Real) ){
- if( (f1 & f2 & MEM_Int)!=0 ){
+ if( combined_flags&(MEM_Int|MEM_Real|MEM_IntReal) ){
+ testcase( combined_flags & MEM_Int );
+ testcase( combined_flags & MEM_Real );
+ testcase( combined_flags & MEM_IntReal );
+ if( (f1 & f2 & (MEM_Int|MEM_IntReal))!=0 ){
+ testcase( f1 & f2 & MEM_Int );
+ testcase( f1 & f2 & MEM_IntReal );
if( pMem1->u.i < pMem2->u.i ) return -1;
if( pMem1->u.i > pMem2->u.i ) return +1;
return 0;
@@ -79559,15 +83262,23 @@ SQLITE_PRIVATE int sqlite3MemCompare(const Mem *pMem1, const Mem *pMem2, const C
if( pMem1->u.r > pMem2->u.r ) return +1;
return 0;
}
- if( (f1&MEM_Int)!=0 ){
+ if( (f1&(MEM_Int|MEM_IntReal))!=0 ){
+ testcase( f1 & MEM_Int );
+ testcase( f1 & MEM_IntReal );
if( (f2&MEM_Real)!=0 ){
return sqlite3IntFloatCompare(pMem1->u.i, pMem2->u.r);
+ }else if( (f2&(MEM_Int|MEM_IntReal))!=0 ){
+ if( pMem1->u.i < pMem2->u.i ) return -1;
+ if( pMem1->u.i > pMem2->u.i ) return +1;
+ return 0;
}else{
return -1;
}
}
if( (f1&MEM_Real)!=0 ){
- if( (f2&MEM_Int)!=0 ){
+ if( (f2&(MEM_Int|MEM_IntReal))!=0 ){
+ testcase( f2 & MEM_Int );
+ testcase( f2 & MEM_IntReal );
return -sqlite3IntFloatCompare(pMem2->u.i, pMem1->u.r);
}else{
return -1;
@@ -79588,7 +83299,7 @@ SQLITE_PRIVATE int sqlite3MemCompare(const Mem *pMem1, const Mem *pMem2, const C
}
assert( pMem1->enc==pMem2->enc || pMem1->db->mallocFailed );
- 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
@@ -79603,7 +83314,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(). */
return sqlite3BlobCompare(pMem1, pMem2);
}
@@ -79611,7 +83322,7 @@ SQLITE_PRIVATE int sqlite3MemCompare(const Mem *pMem1, const Mem *pMem2, const C
/*
** The first argument passed to this function is a serial-type that
-** corresponds to an integer - all values between 1 and 9 inclusive
+** corresponds to an integer - all values between 1 and 9 inclusive
** except 7. The second points to a buffer containing an integer value
** serialized according to serial_type. This function deserializes
** and returns the value.
@@ -79653,7 +83364,7 @@ static i64 vdbeRecordDecodeInt(u32 serial_type, const u8 *aKey){
/*
** 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 the OP_MakeRecord opcode of the VDBE. The pPKey2
** key must be a parsed key such as obtained from
@@ -79662,12 +83373,12 @@ static i64 vdbeRecordDecodeInt(u32 serial_type, const u8 *aKey){
** If argument bSkip is non-zero, it is assumed that the caller has already
** determined that the first fields of the keys are equal.
**
-** Key1 and Key2 do not have to contain the same number of fields. If all
-** fields that appear in both keys are equal, then pPKey2->default_rc is
+** Key1 and Key2 do not have to contain the same number of fields. If all
+** fields that appear in both keys are equal, then pPKey2->default_rc is
** returned.
**
-** If database corruption is discovered, set pPKey2->errCode to
-** SQLITE_CORRUPT and return 0. If an OOM error is encountered,
+** If database corruption is discovered, set pPKey2->errCode to
+** SQLITE_CORRUPT and return 0. If an OOM error is encountered,
** pPKey2->errCode is set to SQLITE_NOMEM and, if it is not NULL, the
** malloc-failed flag set on database handle (pPKey2->pKeyInfo->db).
*/
@@ -79699,24 +83410,26 @@ SQLITE_PRIVATE int sqlite3VdbeRecordCompareWithSkip(
}else{
idx1 = getVarint32(aKey1, szHdr1);
d1 = szHdr1;
- if( d1>(unsigned)nKey1 ){
- pPKey2->errCode = (u8)SQLITE_CORRUPT_BKPT;
- return 0; /* Corruption */
- }
i = 0;
}
+ if( d1>(unsigned)nKey1 ){
+ pPKey2->errCode = (u8)SQLITE_CORRUPT_BKPT;
+ return 0; /* Corruption */
+ }
VVA_ONLY( mem1.szMalloc = 0; ) /* Only needed by assert() statements */
- assert( pPKey2->pKeyInfo->nAllField>=pPKey2->nField
+ assert( pPKey2->pKeyInfo->nAllField>=pPKey2->nField
|| CORRUPT_DB );
- assert( pPKey2->pKeyInfo->aSortOrder!=0 );
+ assert( pPKey2->pKeyInfo->aSortFlags!=0 );
assert( pPKey2->pKeyInfo->nKeyField>0 );
assert( idx1<=szHdr1 || CORRUPT_DB );
do{
u32 serial_type;
/* RHS is an integer */
- if( pRhs->flags & MEM_Int ){
+ if( pRhs->flags & (MEM_Int|MEM_IntReal) ){
+ testcase( pRhs->flags & MEM_Int );
+ testcase( pRhs->flags & MEM_IntReal );
serial_type = aKey1[idx1];
testcase( serial_type==12 );
if( serial_type>=10 ){
@@ -79742,7 +83455,7 @@ SQLITE_PRIVATE int sqlite3VdbeRecordCompareWithSkip(
serial_type = aKey1[idx1];
if( serial_type>=10 ){
/* Serial types 12 or greater are strings and blobs (greater than
- ** numbers). Types 10 and 11 are currently "reserved for future
+ ** numbers). Types 10 and 11 are currently "reserved for future
** use", so it doesn't really matter what the results of comparing
** them to numberic values are. */
rc = +1;
@@ -79764,7 +83477,7 @@ SQLITE_PRIVATE int sqlite3VdbeRecordCompareWithSkip(
/* RHS is a string */
else if( pRhs->flags & MEM_Str ){
- getVarint32(&aKey1[idx1], serial_type);
+ getVarint32NR(&aKey1[idx1], serial_type);
testcase( serial_type==12 );
if( serial_type<12 ){
rc = -1;
@@ -79774,10 +83487,12 @@ SQLITE_PRIVATE int sqlite3VdbeRecordCompareWithSkip(
mem1.n = (serial_type - 12) / 2;
testcase( (d1+mem1.n)==(unsigned)nKey1 );
testcase( (d1+mem1.n+1)==(unsigned)nKey1 );
- if( (d1+mem1.n) > (unsigned)nKey1 ){
+ if( (d1+mem1.n) > (unsigned)nKey1
+ || (pKeyInfo = pPKey2->pKeyInfo)->nAllField<=i
+ ){
pPKey2->errCode = (u8)SQLITE_CORRUPT_BKPT;
return 0; /* Corruption */
- }else if( (pKeyInfo = pPKey2->pKeyInfo)->aColl[i] ){
+ }else if( pKeyInfo->aColl[i] ){
mem1.enc = pKeyInfo->enc;
mem1.db = pKeyInfo->db;
mem1.flags = MEM_Str;
@@ -79788,7 +83503,7 @@ SQLITE_PRIVATE int sqlite3VdbeRecordCompareWithSkip(
}else{
int nCmp = MIN(mem1.n, pRhs->n);
rc = memcmp(&aKey1[d1], pRhs->z, nCmp);
- if( rc==0 ) rc = mem1.n - pRhs->n;
+ if( rc==0 ) rc = mem1.n - pRhs->n;
}
}
}
@@ -79796,7 +83511,7 @@ SQLITE_PRIVATE int sqlite3VdbeRecordCompareWithSkip(
/* RHS is a blob */
else if( pRhs->flags & MEM_Blob ){
assert( (pRhs->flags & MEM_Zero)==0 || pRhs->n==0 );
- getVarint32(&aKey1[idx1], serial_type);
+ getVarint32NR(&aKey1[idx1], serial_type);
testcase( serial_type==12 );
if( serial_type<12 || (serial_type & 0x01) ){
rc = -1;
@@ -79828,8 +83543,14 @@ SQLITE_PRIVATE int sqlite3VdbeRecordCompareWithSkip(
}
if( rc!=0 ){
- if( pPKey2->pKeyInfo->aSortOrder[i] ){
- rc = -rc;
+ int sortFlags = pPKey2->pKeyInfo->aSortFlags[i];
+ if( sortFlags ){
+ if( (sortFlags & KEYINFO_ORDER_BIGNULL)==0
+ || ((sortFlags & KEYINFO_ORDER_DESC)
+ !=(serial_type==0 || (pRhs->flags&MEM_Null)))
+ ){
+ rc = -rc;
+ }
}
assert( vdbeRecordCompareDebug(nKey1, pKey1, pPKey2, rc) );
assert( mem1.szMalloc==0 ); /* See comment below */
@@ -79851,8 +83572,8 @@ SQLITE_PRIVATE int sqlite3VdbeRecordCompareWithSkip(
/* rc==0 here means that one or both of the keys ran out of fields and
** all the fields up to that point were equal. Return the default_rc
** value. */
- assert( CORRUPT_DB
- || vdbeRecordCompareDebug(nKey1, pKey1, pPKey2, pPKey2->default_rc)
+ assert( CORRUPT_DB
+ || vdbeRecordCompareDebug(nKey1, pKey1, pPKey2, pPKey2->default_rc)
|| pPKey2->pKeyInfo->db->mallocFailed
);
pPKey2->eqSeen = 1;
@@ -79867,8 +83588,8 @@ SQLITE_PRIVATE int sqlite3VdbeRecordCompare(
/*
-** This function is an optimized version of sqlite3VdbeRecordCompare()
-** that (a) the first field of pPKey2 is an integer, and (b) the
+** This function is an optimized version of sqlite3VdbeRecordCompare()
+** that (a) the first field of pPKey2 is an integer, and (b) the
** size-of-header varint at the start of (pKey1/nKey1) fits in a single
** byte (i.e. is less than 128).
**
@@ -79923,7 +83644,7 @@ static int vdbeRecordCompareInt(
testcase( lhs<0 );
break;
}
- case 8:
+ case 8:
lhs = 0;
break;
case 9:
@@ -79931,11 +83652,11 @@ static int vdbeRecordCompareInt(
break;
/* This case could be removed without changing the results of running
- ** this code. Including it causes gcc to generate a faster switch
+ ** this code. Including it causes gcc to generate a faster switch
** statement (since the range of switch targets now starts at zero and
** is contiguous) but does not cause any duplicate code to be generated
- ** (as gcc is clever enough to combine the two like cases). Other
- ** compilers might be similar. */
+ ** (as gcc is clever enough to combine the two like cases). Other
+ ** compilers might be similar. */
case 0: case 7:
return sqlite3VdbeRecordCompare(nKey1, pKey1, pPKey2);
@@ -79949,7 +83670,7 @@ static int vdbeRecordCompareInt(
}else if( vr2;
}else if( pPKey2->nField>1 ){
- /* The first fields of the two keys are equal. Compare the trailing
+ /* The first fields of the two keys are equal. Compare the trailing
** fields. */
res = sqlite3VdbeRecordCompareWithSkip(nKey1, pKey1, pPKey2, 1);
}else{
@@ -79964,9 +83685,9 @@ static int vdbeRecordCompareInt(
}
/*
-** This function is an optimized version of sqlite3VdbeRecordCompare()
+** This function is an optimized version of sqlite3VdbeRecordCompare()
** that (a) the first field of pPKey2 is a string, that (b) the first field
-** uses the collation sequence BINARY and (c) that the size-of-header varint
+** uses the collation sequence BINARY and (c) that the size-of-header varint
** at the start of (pKey1/nKey1) fits in a single byte.
*/
static int vdbeRecordCompareString(
@@ -79979,10 +83700,13 @@ static int vdbeRecordCompareString(
assert( pPKey2->aMem[0].flags & MEM_Str );
vdbeAssertFieldCountWithinLimits(nKey1, pKey1, pPKey2->pKeyInfo);
- getVarint32(&aKey1[1], serial_type);
+ serial_type = (u8)(aKey1[1]);
+ if( serial_type >= 0x80 ){
+ sqlite3GetVarint32(&aKey1[1], (u32*)&serial_type);
+ }
if( serial_type<12 ){
res = pPKey2->r1; /* (pKey1/nKey1) is a number or a null */
- }else if( !(serial_type & 0x01) ){
+ }else if( !(serial_type & 0x01) ){
res = pPKey2->r2; /* (pKey1/nKey1) is a blob */
}else{
int nCmp;
@@ -79997,7 +83721,11 @@ static int vdbeRecordCompareString(
nCmp = MIN( pPKey2->aMem[0].n, nStr );
res = memcmp(&aKey1[szHdr], pPKey2->aMem[0].z, nCmp);
- if( res==0 ){
+ if( res>0 ){
+ res = pPKey2->r2;
+ }else if( res<0 ){
+ res = pPKey2->r1;
+ }else{
res = nStr - pPKey2->aMem[0].n;
if( res==0 ){
if( pPKey2->nField>1 ){
@@ -80011,10 +83739,6 @@ static int vdbeRecordCompareString(
}else{
res = pPKey2->r1;
}
- }else if( res>0 ){
- res = pPKey2->r2;
- }else{
- res = pPKey2->r1;
}
}
@@ -80034,7 +83758,7 @@ SQLITE_PRIVATE RecordCompare sqlite3VdbeFindCompare(UnpackedRecord *p){
/* varintRecordCompareInt() and varintRecordCompareString() both assume
** that the size-of-header varint that occurs at the start of each record
** fits in a single byte (i.e. is 127 or less). varintRecordCompareInt()
- ** also assumes that it is safe to overread a buffer by at least the
+ ** also assumes that it is safe to overread a buffer by at least the
** maximum possible legal header size plus 8 bytes. Because there is
** guaranteed to be at least 74 (but not 136) bytes of padding following each
** buffer passed to varintRecordCompareInt() this makes it convenient to
@@ -80046,7 +83770,10 @@ SQLITE_PRIVATE RecordCompare sqlite3VdbeFindCompare(UnpackedRecord *p){
** header size is (12*5 + 1 + 1) bytes. */
if( p->pKeyInfo->nAllField<=13 ){
int flags = p->aMem[0].flags;
- if( p->pKeyInfo->aSortOrder[0] ){
+ if( p->pKeyInfo->aSortFlags[0] ){
+ if( p->pKeyInfo->aSortFlags[0] & KEYINFO_ORDER_BIGNULL ){
+ return sqlite3VdbeRecordCompare;
+ }
p->r1 = 1;
p->r2 = -1;
}else{
@@ -80059,7 +83786,9 @@ SQLITE_PRIVATE RecordCompare sqlite3VdbeFindCompare(UnpackedRecord *p){
testcase( flags & MEM_Real );
testcase( flags & MEM_Null );
testcase( flags & MEM_Blob );
- if( (flags & (MEM_Real|MEM_Null|MEM_Blob))==0 && p->pKeyInfo->aColl[0]==0 ){
+ if( (flags & (MEM_Real|MEM_IntReal|MEM_Null|MEM_Blob))==0
+ && p->pKeyInfo->aColl[0]==0
+ ){
assert( flags & MEM_Str );
return vdbeRecordCompareString;
}
@@ -80087,7 +83816,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) );
nCellKey = sqlite3BtreePayloadSize(pCur);
@@ -80095,22 +83824,24 @@ SQLITE_PRIVATE int sqlite3VdbeIdxRowid(sqlite3 *db, BtCursor *pCur, i64 *rowid){
/* Read in the complete content of the index entry */
sqlite3VdbeMemInit(&m, db, 0);
- rc = sqlite3VdbeMemFromBtree(pCur, 0, (u32)nCellKey, &m);
+ rc = sqlite3VdbeMemFromBtreeZeroOffset(pCur, (u32)nCellKey, &m);
if( rc ){
return rc;
}
/* The index entry must begin with a header size */
- (void)getVarint32((u8*)m.z, szHdr);
+ getVarint32NR((u8*)m.z, szHdr);
testcase( szHdr==3 );
testcase( szHdr==m.n );
- if( unlikely(szHdr<3 || (int)szHdr>m.n) ){
+ testcase( szHdr>0x7fffffff );
+ assert( m.n>=0 );
+ if( unlikely(szHdr<3 || szHdr>(unsigned)m.n) ){
goto idx_rowid_corruption;
}
/* The last field of the index should be an integer - the ROWID.
** Verify that the last entry really is an integer. */
- (void)getVarint32((u8*)&m.z[szHdr-1], typeRowid);
+ getVarint32NR((u8*)&m.z[szHdr-1], typeRowid);
testcase( typeRowid==1 );
testcase( typeRowid==2 );
testcase( typeRowid==3 );
@@ -80150,7 +83881,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(
@@ -80175,7 +83906,7 @@ SQLITE_PRIVATE int sqlite3VdbeIdxKeyCompare(
return SQLITE_CORRUPT_BKPT;
}
sqlite3VdbeMemInit(&m, db, 0);
- rc = sqlite3VdbeMemFromBtree(pCur, 0, (u32)nCellKey, &m);
+ rc = sqlite3VdbeMemFromBtreeZeroOffset(pCur, (u32)nCellKey, &m);
if( rc ){
return rc;
}
@@ -80186,7 +83917,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) );
@@ -80243,7 +83974,7 @@ SQLITE_PRIVATE u8 sqlite3VdbePrepareFlags(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.
**
@@ -80291,13 +84022,25 @@ SQLITE_PRIVATE void sqlite3VdbeSetVarmask(Vdbe *v, int iVar){
** features such as 'now'.
*/
SQLITE_PRIVATE int sqlite3NotPureFunc(sqlite3_context *pCtx){
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
+ const VdbeOp *pOp;
+#ifdef SQLITE_ENABLE_STAT4
if( pCtx->pVdbe==0 ) return 1;
#endif
- if( pCtx->pVdbe->aOp[pCtx->iOp].opcode==OP_PureFunc ){
- sqlite3_result_error(pCtx,
- "non-deterministic function in index expression or CHECK constraint",
- -1);
+ pOp = pCtx->pVdbe->aOp + pCtx->iOp;
+ if( pOp->opcode==OP_PureFunc ){
+ const char *zContext;
+ char *zMsg;
+ if( pOp->p5 & NC_IsCheck ){
+ zContext = "a CHECK constraint";
+ }else if( pOp->p5 & NC_GenCol ){
+ zContext = "a generated column";
+ }else{
+ zContext = "an index";
+ }
+ zMsg = sqlite3_mprintf("non-deterministic use of %s() in %s",
+ pCtx->pFunc->zName, zContext);
+ sqlite3_result_error(pCtx, zMsg, -1);
+ sqlite3_free(zMsg);
return 0;
}
return 1;
@@ -80323,7 +84066,7 @@ SQLITE_PRIVATE void sqlite3VtabImportErrmsg(Vdbe *p, sqlite3_vtab *pVtab){
#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
/*
-** If the second argument is not NULL, release any allocations associated
+** If the second argument is not NULL, release any allocations associated
** with the memory cells in the p->aMem[] array. Also free the UnpackedRecord
** structure itself, using sqlite3DbFree().
**
@@ -80356,7 +84099,8 @@ SQLITE_PRIVATE void sqlite3VdbePreUpdateHook(
const char *zDb, /* Database name */
Table *pTab, /* Modified table */
i64 iKey1, /* Initial key value */
- int iReg /* Register for new.* record */
+ int iReg, /* Register for new.* record */
+ int iBlobWrite
){
sqlite3 *db = v->db;
i64 iKey2;
@@ -80377,7 +84121,7 @@ SQLITE_PRIVATE void sqlite3VdbePreUpdateHook(
}
}
- assert( pCsr->nField==pTab->nCol
+ assert( pCsr->nField==pTab->nCol
|| (pCsr->nField==pTab->nCol+1 && op==SQLITE_DELETE && iReg==-1)
);
@@ -80388,10 +84132,11 @@ SQLITE_PRIVATE void sqlite3VdbePreUpdateHook(
preupdate.keyinfo.db = db;
preupdate.keyinfo.enc = ENC(db);
preupdate.keyinfo.nKeyField = pTab->nCol;
- preupdate.keyinfo.aSortOrder = (u8*)&fakeSortOrder;
+ preupdate.keyinfo.aSortFlags = (u8*)&fakeSortOrder;
preupdate.iKey1 = iKey1;
preupdate.iKey2 = iKey2;
preupdate.pTab = pTab;
+ preupdate.iBlobWrite = iBlobWrite;
db->pPreUpdate = &preupdate;
db->xPreUpdateCallback(db->pPreUpdateArg, db, op, zDb, zTbl, iKey1, iKey2);
@@ -80475,16 +84220,18 @@ static SQLITE_NOINLINE void invokeProfileCallback(sqlite3 *db, Vdbe *p){
sqlite3_int64 iNow;
sqlite3_int64 iElapse;
assert( p->startTime>0 );
- assert( db->xProfile!=0 || (db->mTrace & SQLITE_TRACE_PROFILE)!=0 );
+ assert( (db->mTrace & (SQLITE_TRACE_PROFILE|SQLITE_TRACE_XPROFILE))!=0 );
assert( db->init.busy==0 );
assert( p->zSql!=0 );
sqlite3OsCurrentTimeInt64(db->pVfs, &iNow);
iElapse = (iNow - p->startTime)*1000000;
+#ifndef SQLITE_OMIT_DEPRECATED
if( db->xProfile ){
db->xProfile(db->pProfileArg, p->zSql, iElapse);
}
+#endif
if( db->mTrace & SQLITE_TRACE_PROFILE ){
- db->xTrace(SQLITE_TRACE_PROFILE, db->pTraceArg, p, (void*)&iElapse);
+ db->trace.xV2(SQLITE_TRACE_PROFILE, db->pTraceArg, p, (void*)&iElapse);
}
p->startTime = 0;
}
@@ -80645,39 +84392,86 @@ SQLITE_API const void *sqlite3_value_text16le(sqlite3_value *pVal){
*/
SQLITE_API int sqlite3_value_type(sqlite3_value* pVal){
static const u8 aType[] = {
- SQLITE_BLOB, /* 0x00 */
- SQLITE_NULL, /* 0x01 */
- SQLITE_TEXT, /* 0x02 */
- SQLITE_NULL, /* 0x03 */
- SQLITE_INTEGER, /* 0x04 */
- SQLITE_NULL, /* 0x05 */
- SQLITE_INTEGER, /* 0x06 */
- SQLITE_NULL, /* 0x07 */
- SQLITE_FLOAT, /* 0x08 */
- SQLITE_NULL, /* 0x09 */
- SQLITE_FLOAT, /* 0x0a */
- SQLITE_NULL, /* 0x0b */
- SQLITE_INTEGER, /* 0x0c */
- SQLITE_NULL, /* 0x0d */
- SQLITE_INTEGER, /* 0x0e */
- SQLITE_NULL, /* 0x0f */
- SQLITE_BLOB, /* 0x10 */
- SQLITE_NULL, /* 0x11 */
- SQLITE_TEXT, /* 0x12 */
- SQLITE_NULL, /* 0x13 */
- SQLITE_INTEGER, /* 0x14 */
- SQLITE_NULL, /* 0x15 */
- SQLITE_INTEGER, /* 0x16 */
- SQLITE_NULL, /* 0x17 */
- SQLITE_FLOAT, /* 0x18 */
- SQLITE_NULL, /* 0x19 */
- SQLITE_FLOAT, /* 0x1a */
- SQLITE_NULL, /* 0x1b */
- SQLITE_INTEGER, /* 0x1c */
- SQLITE_NULL, /* 0x1d */
- SQLITE_INTEGER, /* 0x1e */
- SQLITE_NULL, /* 0x1f */
+ SQLITE_BLOB, /* 0x00 (not possible) */
+ SQLITE_NULL, /* 0x01 NULL */
+ SQLITE_TEXT, /* 0x02 TEXT */
+ SQLITE_NULL, /* 0x03 (not possible) */
+ SQLITE_INTEGER, /* 0x04 INTEGER */
+ SQLITE_NULL, /* 0x05 (not possible) */
+ SQLITE_INTEGER, /* 0x06 INTEGER + TEXT */
+ SQLITE_NULL, /* 0x07 (not possible) */
+ SQLITE_FLOAT, /* 0x08 FLOAT */
+ SQLITE_NULL, /* 0x09 (not possible) */
+ SQLITE_FLOAT, /* 0x0a FLOAT + TEXT */
+ SQLITE_NULL, /* 0x0b (not possible) */
+ SQLITE_INTEGER, /* 0x0c (not possible) */
+ SQLITE_NULL, /* 0x0d (not possible) */
+ SQLITE_INTEGER, /* 0x0e (not possible) */
+ SQLITE_NULL, /* 0x0f (not possible) */
+ SQLITE_BLOB, /* 0x10 BLOB */
+ SQLITE_NULL, /* 0x11 (not possible) */
+ SQLITE_TEXT, /* 0x12 (not possible) */
+ SQLITE_NULL, /* 0x13 (not possible) */
+ SQLITE_INTEGER, /* 0x14 INTEGER + BLOB */
+ SQLITE_NULL, /* 0x15 (not possible) */
+ SQLITE_INTEGER, /* 0x16 (not possible) */
+ SQLITE_NULL, /* 0x17 (not possible) */
+ SQLITE_FLOAT, /* 0x18 FLOAT + BLOB */
+ SQLITE_NULL, /* 0x19 (not possible) */
+ SQLITE_FLOAT, /* 0x1a (not possible) */
+ SQLITE_NULL, /* 0x1b (not possible) */
+ SQLITE_INTEGER, /* 0x1c (not possible) */
+ SQLITE_NULL, /* 0x1d (not possible) */
+ SQLITE_INTEGER, /* 0x1e (not possible) */
+ SQLITE_NULL, /* 0x1f (not possible) */
+ SQLITE_FLOAT, /* 0x20 INTREAL */
+ SQLITE_NULL, /* 0x21 (not possible) */
+ SQLITE_TEXT, /* 0x22 INTREAL + TEXT */
+ SQLITE_NULL, /* 0x23 (not possible) */
+ SQLITE_FLOAT, /* 0x24 (not possible) */
+ SQLITE_NULL, /* 0x25 (not possible) */
+ SQLITE_FLOAT, /* 0x26 (not possible) */
+ SQLITE_NULL, /* 0x27 (not possible) */
+ SQLITE_FLOAT, /* 0x28 (not possible) */
+ SQLITE_NULL, /* 0x29 (not possible) */
+ SQLITE_FLOAT, /* 0x2a (not possible) */
+ SQLITE_NULL, /* 0x2b (not possible) */
+ SQLITE_FLOAT, /* 0x2c (not possible) */
+ SQLITE_NULL, /* 0x2d (not possible) */
+ SQLITE_FLOAT, /* 0x2e (not possible) */
+ SQLITE_NULL, /* 0x2f (not possible) */
+ SQLITE_BLOB, /* 0x30 (not possible) */
+ SQLITE_NULL, /* 0x31 (not possible) */
+ SQLITE_TEXT, /* 0x32 (not possible) */
+ SQLITE_NULL, /* 0x33 (not possible) */
+ SQLITE_FLOAT, /* 0x34 (not possible) */
+ SQLITE_NULL, /* 0x35 (not possible) */
+ SQLITE_FLOAT, /* 0x36 (not possible) */
+ SQLITE_NULL, /* 0x37 (not possible) */
+ SQLITE_FLOAT, /* 0x38 (not possible) */
+ SQLITE_NULL, /* 0x39 (not possible) */
+ SQLITE_FLOAT, /* 0x3a (not possible) */
+ SQLITE_NULL, /* 0x3b (not possible) */
+ SQLITE_FLOAT, /* 0x3c (not possible) */
+ SQLITE_NULL, /* 0x3d (not possible) */
+ SQLITE_FLOAT, /* 0x3e (not possible) */
+ SQLITE_NULL, /* 0x3f (not possible) */
};
+#ifdef SQLITE_DEBUG
+ {
+ int eType = SQLITE_BLOB;
+ if( pVal->flags & MEM_Null ){
+ eType = SQLITE_NULL;
+ }else if( pVal->flags & (MEM_Real|MEM_IntReal) ){
+ eType = SQLITE_FLOAT;
+ }else if( pVal->flags & MEM_Int ){
+ eType = SQLITE_INTEGER;
+ }else if( pVal->flags & MEM_Str ){
+ eType = SQLITE_TEXT;
+ }
+ assert( eType == aType[pVal->flags&MEM_AffMask] );
+ }
+#endif
return aType[pVal->flags&MEM_AffMask];
}
@@ -80686,6 +84480,11 @@ SQLITE_API int sqlite3_value_nochange(sqlite3_value *pVal){
return (pVal->flags&(MEM_Null|MEM_Zero))==(MEM_Null|MEM_Zero);
}
+/* Return true if a parameter value originated from an sqlite3_bind() */
+SQLITE_API int sqlite3_value_frombind(sqlite3_value *pVal){
+ return (pVal->flags&MEM_FromBind)!=0;
+}
+
/* Make a copy of an sqlite3_value object
*/
SQLITE_API sqlite3_value *sqlite3_value_dup(const sqlite3_value *pOrig){
@@ -80714,7 +84513,7 @@ SQLITE_API sqlite3_value *sqlite3_value_dup(const sqlite3_value *pOrig){
SQLITE_API void sqlite3_value_free(sqlite3_value *pOld){
sqlite3ValueFree(pOld);
}
-
+
/**************************** sqlite3_result_ *******************************
** The following routines are used by user-defined functions to specify
@@ -80751,13 +84550,13 @@ static int invokeValueDestructor(
}else{
xDel((void*)p);
}
- if( pCtx ) sqlite3_result_error_toobig(pCtx);
+ sqlite3_result_error_toobig(pCtx);
return SQLITE_TOOBIG;
}
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 );
@@ -80765,8 +84564,8 @@ SQLITE_API void sqlite3_result_blob(
setResultStrOrError(pCtx, z, n, 0, xDel);
}
SQLITE_API void sqlite3_result_blob64(
- sqlite3_context *pCtx,
- const void *z,
+ sqlite3_context *pCtx,
+ const void *z,
sqlite3_uint64 n,
void (*xDel)(void *)
){
@@ -80825,8 +84624,8 @@ SQLITE_API void sqlite3_result_subtype(sqlite3_context *pCtx, unsigned int eSubt
pOut->flags |= MEM_Subtype;
}
SQLITE_API void sqlite3_result_text(
- sqlite3_context *pCtx,
- const char *z,
+ sqlite3_context *pCtx,
+ const char *z,
int n,
void (*xDel)(void *)
){
@@ -80834,8 +84633,8 @@ SQLITE_API void sqlite3_result_text(
setResultStrOrError(pCtx, z, n, SQLITE_UTF8, xDel);
}
SQLITE_API void sqlite3_result_text64(
- sqlite3_context *pCtx,
- const char *z,
+ sqlite3_context *pCtx,
+ const char *z,
sqlite3_uint64 n,
void (*xDel)(void *),
unsigned char enc
@@ -80851,27 +84650,27 @@ SQLITE_API void sqlite3_result_text64(
}
#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->pOut->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->pOut->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->pOut->db->mutex) );
@@ -80901,7 +84700,7 @@ SQLITE_API void sqlite3_result_error_code(sqlite3_context *pCtx, int errCode){
if( pCtx->pVdbe ) pCtx->pVdbe->rcApp = errCode;
#endif
if( pCtx->pOut->flags & MEM_Null ){
- sqlite3VdbeMemSetStr(pCtx->pOut, sqlite3ErrStr(errCode), -1,
+ sqlite3VdbeMemSetStr(pCtx->pOut, sqlite3ErrStr(errCode), -1,
SQLITE_UTF8, SQLITE_STATIC);
}
}
@@ -80910,7 +84709,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->pOut->db->mutex) );
pCtx->isError = SQLITE_TOOBIG;
- sqlite3VdbeMemSetStr(pCtx->pOut, "string or blob too big", -1,
+ sqlite3VdbeMemSetStr(pCtx->pOut, "string or blob too big", -1,
SQLITE_UTF8, SQLITE_STATIC);
}
@@ -80922,8 +84721,23 @@ SQLITE_API void sqlite3_result_error_nomem(sqlite3_context *pCtx){
sqlite3OomFault(pCtx->pOut->db);
}
+#ifndef SQLITE_UNTESTABLE
+/* Force the INT64 value currently stored as the result to be
+** a MEM_IntReal value. See the SQLITE_TESTCTRL_RESULT_INTREAL
+** test-control.
+*/
+SQLITE_PRIVATE void sqlite3ResultIntReal(sqlite3_context *pCtx){
+ assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
+ if( pCtx->pOut->flags & MEM_Int ){
+ pCtx->pOut->flags &= ~MEM_Int;
+ pCtx->pOut->flags |= MEM_IntReal;
+ }
+}
+#endif
+
+
/*
-** This function is called after a transaction has been committed. It
+** 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){
@@ -80952,7 +84766,7 @@ static int doWalCallbacks(sqlite3 *db){
** 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.
*/
@@ -80961,20 +84775,20 @@ static int sqlite3Step(Vdbe *p){
int rc;
assert(p);
- if( p->magic!=VDBE_MAGIC_RUN ){
+ if( p->iVdbeMagic!=VDBE_MAGIC_RUN ){
/* We used to require that sqlite3_reset() be called before retrying
** sqlite3_step() after any error or after SQLITE_DONE. But beginning
** with version 3.7.0, we changed this so that sqlite3_reset() would
** be called automatically instead of throwing the SQLITE_MISUSE error.
- ** This "automatic-reset" change is not technically an incompatibility,
+ ** This "automatic-reset" change is not technically an incompatibility,
** since any application that receives an SQLITE_MISUSE is broken by
** definition.
**
** Nevertheless, some published applications that were originally written
- ** for version 3.6.23 or earlier do in fact depend on SQLITE_MISUSE
+ ** for version 3.6.23 or earlier do in fact depend on SQLITE_MISUSE
** returns, and those were broken by the automatic-reset change. As a
** a work-around, the SQLITE_OMIT_AUTORESET compile-time restores the
- ** legacy behavior of returning SQLITE_MISUSE for cases where the
+ ** legacy behavior of returning SQLITE_MISUSE for cases where the
** previous sqlite3_step() returned something other than a SQLITE_LOCKED
** or SQLITE_BUSY error.
*/
@@ -80996,9 +84810,16 @@ static int sqlite3Step(Vdbe *p){
return SQLITE_NOMEM_BKPT;
}
- if( p->pc<=0 && p->expired ){
+ if( p->pc<0 && p->expired ){
p->rc = SQLITE_SCHEMA;
rc = SQLITE_ERROR;
+ if( (p->prepFlags & SQLITE_PREPARE_SAVESQL)!=0 ){
+ /* If this statement was prepared using saved SQL and an
+ ** error has occurred, then return the error code in p->rc to the
+ ** caller. Set the error code in the database handle to the same value.
+ */
+ rc = sqlite3VdbeTransferError(p);
+ }
goto end_of_step;
}
if( p->pc<0 ){
@@ -81007,15 +84828,15 @@ static int sqlite3Step(Vdbe *p){
** from interrupting a statement that has not yet started.
*/
if( db->nVdbeActive==0 ){
- db->u1.isInterrupted = 0;
+ AtomicStore(&db->u1.isInterrupted, 0);
}
- assert( db->nVdbeWrite>0 || db->autoCommit==0
+ assert( db->nVdbeWrite>0 || db->autoCommit==0
|| (db->nDeferredCons==0 && db->nDeferredImmCons==0)
);
#ifndef SQLITE_OMIT_TRACE
- if( (db->xProfile || (db->mTrace & SQLITE_TRACE_PROFILE)!=0)
+ if( (db->mTrace & (SQLITE_TRACE_PROFILE|SQLITE_TRACE_XPROFILE))!=0
&& !db->init.busy && p->zSql ){
sqlite3OsCurrentTimeInt64(db->pVfs, &p->startTime);
}else{
@@ -81042,45 +84863,39 @@ static int sqlite3Step(Vdbe *p){
db->nVdbeExec--;
}
+ if( rc!=SQLITE_ROW ){
#ifndef SQLITE_OMIT_TRACE
- /* If the statement completed successfully, invoke the profile callback */
- if( rc!=SQLITE_ROW ) checkProfileCallback(db, p);
+ /* If the statement completed successfully, invoke the profile callback */
+ checkProfileCallback(db, p);
#endif
- if( rc==SQLITE_DONE && db->autoCommit ){
- assert( p->rc==SQLITE_OK );
- p->rc = doWalCallbacks(db);
- if( p->rc!=SQLITE_OK ){
- rc = SQLITE_ERROR;
+ if( rc==SQLITE_DONE && db->autoCommit ){
+ assert( p->rc==SQLITE_OK );
+ p->rc = doWalCallbacks(db);
+ if( p->rc!=SQLITE_OK ){
+ rc = SQLITE_ERROR;
+ }
+ }else if( rc!=SQLITE_DONE && (p->prepFlags & SQLITE_PREPARE_SAVESQL)!=0 ){
+ /* If this statement was prepared using saved SQL and an
+ ** error has occurred, then return the error code in p->rc to the
+ ** caller. Set the error code in the database handle to the same value.
+ */
+ rc = sqlite3VdbeTransferError(p);
}
}
db->errCode = rc;
if( SQLITE_NOMEM==sqlite3ApiExit(p->db, p->rc) ){
p->rc = SQLITE_NOMEM_BKPT;
+ if( (p->prepFlags & SQLITE_PREPARE_SAVESQL)!=0 ) rc = p->rc;
}
end_of_step:
- /* 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()
- ** were called on statement p.
- */
- assert( rc==SQLITE_ROW || rc==SQLITE_DONE || rc==SQLITE_ERROR
+ /* There are only a limited number of result codes allowed from the
+ ** statements prepared using the legacy sqlite3_prepare() interface */
+ assert( (p->prepFlags & SQLITE_PREPARE_SAVESQL)!=0
+ || rc==SQLITE_ROW || rc==SQLITE_DONE || rc==SQLITE_ERROR
|| (rc&0xff)==SQLITE_BUSY || rc==SQLITE_MISUSE
);
- assert( (p->rc!=SQLITE_ROW && p->rc!=SQLITE_DONE) || p->rc==p->rcApp );
- if( (p->prepFlags & SQLITE_PREPARE_SAVESQL)!=0
- && rc!=SQLITE_ROW
- && rc!=SQLITE_DONE
- ){
- /* If this statement was prepared using saved SQL and an
- ** error has occurred, then return the error code in p->rc to the
- ** caller. Set the error code in the database handle to the same value.
- */
- rc = sqlite3VdbeTransferError(p);
- }
return (rc&db->errMask);
}
@@ -81106,15 +84921,15 @@ SQLITE_API int sqlite3_step(sqlite3_stmt *pStmt){
int savedPc = v->pc;
rc = sqlite3Reprepare(v);
if( rc!=SQLITE_OK ){
- /* 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
+ /* 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);
@@ -81186,7 +85001,7 @@ SQLITE_API int sqlite3_vtab_nochange(sqlite3_context *p){
*/
SQLITE_PRIVATE sqlite3_int64 sqlite3StmtCurrentTime(sqlite3_context *p){
int rc;
-#ifndef SQLITE_ENABLE_STAT3_OR_STAT4
+#ifndef SQLITE_ENABLE_STAT4
sqlite3_int64 *piTime = &p->pVdbe->iCurrentTime;
assert( p->pVdbe!=0 );
#else
@@ -81251,7 +85066,7 @@ SQLITE_API void *sqlite3_get_auxdata(sqlite3_context *pCtx, int iArg){
AuxData *pAuxData;
assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
-#if SQLITE_ENABLE_STAT3_OR_STAT4
+#if SQLITE_ENABLE_STAT4
if( pCtx->pVdbe==0 ) return 0;
#else
assert( pCtx->pVdbe!=0 );
@@ -81276,16 +85091,16 @@ SQLITE_API void *sqlite3_get_auxdata(sqlite3_context *pCtx, int iArg){
** access code.
*/
SQLITE_API void sqlite3_set_auxdata(
- sqlite3_context *pCtx,
- int iArg,
- void *pAux,
+ sqlite3_context *pCtx,
+ int iArg,
+ void *pAux,
void (*xDelete)(void*)
){
AuxData *pAuxData;
Vdbe *pVdbe = pCtx->pVdbe;
assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
+#ifdef SQLITE_ENABLE_STAT4
if( pVdbe==0 ) goto failed;
#else
assert( pVdbe!=0 );
@@ -81320,7 +85135,7 @@ failed:
#ifndef SQLITE_OMIT_DEPRECATED
/*
-** Return the number of times the Step function of an aggregate has been
+** Return the number of times the Step function of an aggregate has been
** called.
**
** This function is deprecated. Do not use it for new code. It is
@@ -81365,9 +85180,9 @@ static const Mem *columnNullValue(void){
** these assert()s from failing, when building with SQLITE_DEBUG defined
** using gcc, we 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
= {
/* .u = */ {0},
@@ -81413,9 +85228,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.
**
@@ -81454,8 +85269,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;
@@ -81529,10 +85344,10 @@ SQLITE_API int sqlite3_column_type(sqlite3_stmt *pStmt, int i){
** or a constant) then useTypes 2, 3, and 4 return NULL.
*/
static const void *columnName(
- sqlite3_stmt *pStmt,
- int N,
- const void *(*xFunc)(Mem*),
- int useType
+ sqlite3_stmt *pStmt, /* The statement */
+ int N, /* Which column to get the name for */
+ int useUtf16, /* True to return the name as UTF16 */
+ int useType /* What type of name */
){
const void *ret;
Vdbe *p;
@@ -81553,8 +85368,15 @@ static const void *columnName(
N += useType*n;
sqlite3_mutex_enter(db->mutex);
assert( db->mallocFailed==0 );
- ret = xFunc(&p->aColName[N]);
- /* A malloc may have failed inside of the xFunc() call. If this
+#ifndef SQLITE_OMIT_UTF16
+ if( useUtf16 ){
+ ret = sqlite3_value_text16((sqlite3_value*)&p->aColName[N]);
+ }else
+#endif
+ {
+ ret = sqlite3_value_text((sqlite3_value*)&p->aColName[N]);
+ }
+ /* A malloc may have failed inside of the _text() call. If this
** is the case, clear the mallocFailed flag and return NULL.
*/
if( db->mallocFailed ){
@@ -81571,13 +85393,11 @@ static const void *columnName(
** statement pStmt.
*/
SQLITE_API const char *sqlite3_column_name(sqlite3_stmt *pStmt, int N){
- return columnName(
- pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, COLNAME_NAME);
+ return columnName(pStmt, N, 0, COLNAME_NAME);
}
#ifndef SQLITE_OMIT_UTF16
SQLITE_API const void *sqlite3_column_name16(sqlite3_stmt *pStmt, int N){
- return columnName(
- pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, COLNAME_NAME);
+ return columnName(pStmt, N, 1, COLNAME_NAME);
}
#endif
@@ -81596,13 +85416,11 @@ SQLITE_API const void *sqlite3_column_name16(sqlite3_stmt *pStmt, int N){
** of the result set of SQL statement pStmt.
*/
SQLITE_API const char *sqlite3_column_decltype(sqlite3_stmt *pStmt, int N){
- return columnName(
- pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, COLNAME_DECLTYPE);
+ return columnName(pStmt, N, 0, COLNAME_DECLTYPE);
}
#ifndef SQLITE_OMIT_UTF16
SQLITE_API const void *sqlite3_column_decltype16(sqlite3_stmt *pStmt, int N){
- return columnName(
- pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, COLNAME_DECLTYPE);
+ return columnName(pStmt, N, 1, COLNAME_DECLTYPE);
}
#endif /* SQLITE_OMIT_UTF16 */
#endif /* SQLITE_OMIT_DECLTYPE */
@@ -81614,13 +85432,11 @@ SQLITE_API const void *sqlite3_column_decltype16(sqlite3_stmt *pStmt, int N){
** anything else which is not an unambiguous reference to a database column.
*/
SQLITE_API const char *sqlite3_column_database_name(sqlite3_stmt *pStmt, int N){
- return columnName(
- pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, COLNAME_DATABASE);
+ return columnName(pStmt, N, 0, COLNAME_DATABASE);
}
#ifndef SQLITE_OMIT_UTF16
SQLITE_API const void *sqlite3_column_database_name16(sqlite3_stmt *pStmt, int N){
- return columnName(
- pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, COLNAME_DATABASE);
+ return columnName(pStmt, N, 1, COLNAME_DATABASE);
}
#endif /* SQLITE_OMIT_UTF16 */
@@ -81630,13 +85446,11 @@ SQLITE_API const void *sqlite3_column_database_name16(sqlite3_stmt *pStmt, int N
** anything else which is not an unambiguous reference to a database column.
*/
SQLITE_API const char *sqlite3_column_table_name(sqlite3_stmt *pStmt, int N){
- return columnName(
- pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, COLNAME_TABLE);
+ return columnName(pStmt, N, 0, COLNAME_TABLE);
}
#ifndef SQLITE_OMIT_UTF16
SQLITE_API const void *sqlite3_column_table_name16(sqlite3_stmt *pStmt, int N){
- return columnName(
- pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, COLNAME_TABLE);
+ return columnName(pStmt, N, 1, COLNAME_TABLE);
}
#endif /* SQLITE_OMIT_UTF16 */
@@ -81646,24 +85460,22 @@ SQLITE_API const void *sqlite3_column_table_name16(sqlite3_stmt *pStmt, int N){
** anything else which is not an unambiguous reference to a database column.
*/
SQLITE_API const char *sqlite3_column_origin_name(sqlite3_stmt *pStmt, int N){
- return columnName(
- pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, COLNAME_COLUMN);
+ return columnName(pStmt, N, 0, COLNAME_COLUMN);
}
#ifndef SQLITE_OMIT_UTF16
SQLITE_API const void *sqlite3_column_origin_name16(sqlite3_stmt *pStmt, int N){
- return columnName(
- pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, COLNAME_COLUMN);
+ return columnName(pStmt, N, 1, COLNAME_COLUMN);
}
#endif /* SQLITE_OMIT_UTF16 */
#endif /* SQLITE_ENABLE_COLUMN_METADATA */
/******************************* 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.
**
@@ -81679,10 +85491,10 @@ static int vdbeUnbind(Vdbe *p, int i){
return SQLITE_MISUSE_BKPT;
}
sqlite3_mutex_enter(p->db->mutex);
- if( p->magic!=VDBE_MAGIC_RUN || p->pc>=0 ){
+ if( p->iVdbeMagic!=VDBE_MAGIC_RUN || p->pc>=0 ){
sqlite3Error(p->db, SQLITE_MISUSE);
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;
}
@@ -81695,12 +85507,12 @@ static int vdbeUnbind(Vdbe *p, int i){
pVar = &p->aVar[i];
sqlite3VdbeMemRelease(pVar);
pVar->flags = MEM_Null;
- sqlite3Error(p->db, SQLITE_OK);
+ p->db->errCode = SQLITE_OK;
- /* 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.
**
- ** IMPLEMENTATION-OF: R-48440-37595 If the specific value bound to host
+ ** IMPLEMENTATION-OF: R-57496-20354 If the specific value bound to a host
** parameter in the WHERE clause might influence the choice of query plan
** for a statement, then the statement will be automatically recompiled,
** as if there had been a schema change, on the first sqlite3_step() call
@@ -81720,7 +85532,7 @@ static int bindText(
sqlite3_stmt *pStmt, /* The statement to bind against */
int i, /* Index of the parameter to bind */
const void *zData, /* Pointer to the data to be bound */
- int nData, /* Number of bytes of data to be bound */
+ i64 nData, /* Number of bytes of data to be bound */
void (*xDel)(void*), /* Destructor for the data */
u8 encoding /* Encoding for the data */
){
@@ -81753,10 +85565,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*)
){
#ifdef SQLITE_ENABLE_API_ARMOR
@@ -81765,18 +85577,14 @@ SQLITE_API int sqlite3_bind_blob(
return bindText(pStmt, i, zData, nData, xDel, 0);
}
SQLITE_API int sqlite3_bind_blob64(
- sqlite3_stmt *pStmt,
- int i,
- const void *zData,
- sqlite3_uint64 nData,
+ sqlite3_stmt *pStmt,
+ int i,
+ const void *zData,
+ sqlite3_uint64 nData,
void (*xDel)(void*)
){
assert( xDel!=SQLITE_DYNAMIC );
- if( nData>0x7fffffff ){
- return invokeValueDestructor(zData, xDel, 0);
- }else{
- return bindText(pStmt, i, zData, (int)nData, xDel, 0);
- }
+ return bindText(pStmt, i, zData, nData, xDel, 0);
}
SQLITE_API int sqlite3_bind_double(sqlite3_stmt *pStmt, int i, double rValue){
int rc;
@@ -81828,37 +85636,33 @@ SQLITE_API int sqlite3_bind_pointer(
}
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);
}
-SQLITE_API int sqlite3_bind_text64(
- sqlite3_stmt *pStmt,
- int i,
- const char *zData,
- sqlite3_uint64 nData,
+SQLITE_API int sqlite3_bind_text64(
+ sqlite3_stmt *pStmt,
+ int i,
+ const char *zData,
+ sqlite3_uint64 nData,
void (*xDel)(void*),
unsigned char enc
){
assert( xDel!=SQLITE_DYNAMIC );
- if( nData>0x7fffffff ){
- return invokeValueDestructor(zData, xDel, 0);
- }else{
- if( enc==SQLITE_UTF16 ) enc = SQLITE_UTF16NATIVE;
- return bindText(pStmt, i, zData, (int)nData, xDel, enc);
- }
+ if( enc==SQLITE_UTF16 ) enc = SQLITE_UTF16NATIVE;
+ return bindText(pStmt, i, zData, nData, xDel, enc);
}
#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);
@@ -81922,7 +85726,7 @@ SQLITE_API int sqlite3_bind_zeroblob64(sqlite3_stmt *pStmt, int i, sqlite3_uint6
/*
** 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;
@@ -82020,12 +85824,20 @@ SQLITE_API int sqlite3_stmt_readonly(sqlite3_stmt *pStmt){
return pStmt ? ((Vdbe*)pStmt)->readOnly : 1;
}
+/*
+** Return 1 if the statement is an EXPLAIN and return 2 if the
+** statement is an EXPLAIN QUERY PLAN
+*/
+SQLITE_API int sqlite3_stmt_isexplain(sqlite3_stmt *pStmt){
+ return pStmt ? ((Vdbe*)pStmt)->explain : 0;
+}
+
/*
** Return true if the prepared statement is in need of being reset.
*/
SQLITE_API int sqlite3_stmt_busy(sqlite3_stmt *pStmt){
Vdbe *v = (Vdbe*)pStmt;
- return v!=0 && v->magic==VDBE_MAGIC_RUN && v->pc>=0;
+ return v!=0 && v->iVdbeMagic==VDBE_MAGIC_RUN && v->pc>=0;
}
/*
@@ -82059,7 +85871,7 @@ SQLITE_API int sqlite3_stmt_status(sqlite3_stmt *pStmt, int op, int resetFlag){
Vdbe *pVdbe = (Vdbe*)pStmt;
u32 v;
#ifdef SQLITE_ENABLE_API_ARMOR
- if( !pStmt
+ if( !pStmt
|| (op!=SQLITE_STMTSTATUS_MEMUSED && (op<0||op>=ArraySize(pVdbe->aCounter)))
){
(void)SQLITE_MISUSE_BKPT;
@@ -82115,6 +85927,22 @@ SQLITE_API char *sqlite3_expanded_sql(sqlite3_stmt *pStmt){
#endif
}
+#ifdef SQLITE_ENABLE_NORMALIZE
+/*
+** Return the normalized SQL associated with a prepared statement.
+*/
+SQLITE_API const char *sqlite3_normalized_sql(sqlite3_stmt *pStmt){
+ Vdbe *p = (Vdbe *)pStmt;
+ if( p==0 ) return 0;
+ if( p->zNormSql==0 && ALWAYS(p->zSql!=0) ){
+ sqlite3_mutex_enter(p->db->mutex);
+ p->zNormSql = sqlite3Normalize(p, p->zSql);
+ sqlite3_mutex_leave(p->db->mutex);
+ }
+ return p->zNormSql;
+}
+#endif /* SQLITE_ENABLE_NORMALIZE */
+
#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
/*
** Allocate and populate an UnpackedRecord structure based on the serialized
@@ -82122,8 +85950,8 @@ SQLITE_API char *sqlite3_expanded_sql(sqlite3_stmt *pStmt){
** if successful, or a NULL pointer if an OOM error is encountered.
*/
static UnpackedRecord *vdbeUnpackRecord(
- KeyInfo *pKeyInfo,
- int nKey,
+ KeyInfo *pKeyInfo,
+ int nKey,
const void *pKey
){
UnpackedRecord *pRet; /* Return value */
@@ -82152,7 +85980,7 @@ SQLITE_API int sqlite3_preupdate_old(sqlite3 *db, int iIdx, sqlite3_value **ppVa
goto preupdate_old_out;
}
if( p->pPk ){
- iIdx = sqlite3ColumnOfIndex(p->pPk, iIdx);
+ iIdx = sqlite3TableColumnToIndex(p->pPk, iIdx);
}
if( iIdx>=p->pCsr->nField || iIdx<0 ){
rc = SQLITE_RANGE;
@@ -82185,7 +86013,9 @@ SQLITE_API int sqlite3_preupdate_old(sqlite3 *db, int iIdx, sqlite3_value **ppVa
}else if( iIdx>=p->pUnpacked->nField ){
*ppValue = (sqlite3_value *)columnNullValue();
}else if( p->pTab->aCol[iIdx].affinity==SQLITE_AFF_REAL ){
- if( pMem->flags & MEM_Int ){
+ if( pMem->flags & (MEM_Int|MEM_IntReal) ){
+ testcase( pMem->flags & MEM_Int );
+ testcase( pMem->flags & MEM_IntReal );
sqlite3VdbeMemRealify(pMem);
}
}
@@ -82213,7 +86043,7 @@ SQLITE_API int sqlite3_preupdate_count(sqlite3 *db){
** only. It returns zero if the change that caused the callback was made
** immediately by a user SQL statement. Or, if the change was made by a
** trigger program, it returns the number of trigger programs currently
-** on the stack (1 for a top-level trigger, 2 for a trigger fired by a
+** on the stack (1 for a top-level trigger, 2 for a trigger fired by a
** top-level trigger etc.).
**
** For the purposes of the previous paragraph, a foreign key CASCADE, SET NULL
@@ -82225,6 +86055,17 @@ SQLITE_API int sqlite3_preupdate_depth(sqlite3 *db){
}
#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */
+#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
+/*
+** This function is designed to be called from within a pre-update callback
+** only.
+*/
+SQLITE_API int sqlite3_preupdate_blobwrite(sqlite3 *db){
+ PreUpdate *p = db->pPreUpdate;
+ return (p ? p->iBlobWrite : -1);
+}
+#endif
+
#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
/*
** This function is called from within a pre-update callback to retrieve
@@ -82240,7 +86081,7 @@ SQLITE_API int sqlite3_preupdate_new(sqlite3 *db, int iIdx, sqlite3_value **ppVa
goto preupdate_new_out;
}
if( p->pPk && p->op!=SQLITE_UPDATE ){
- iIdx = sqlite3ColumnOfIndex(p->pPk, iIdx);
+ iIdx = sqlite3TableColumnToIndex(p->pPk, iIdx);
}
if( iIdx>=p->pCsr->nField || iIdx<0 ){
rc = SQLITE_RANGE;
@@ -82422,8 +86263,8 @@ static int findNextHostParameter(const char *zSql, int *pnToken){
/*
** This function returns a pointer to a nul-terminated string in memory
** obtained from sqlite3DbMalloc(). If sqlite3.nVdbeExec is 1, then the
-** string contains a copy of zRawSql but with host parameters expanded to
-** their current bindings. Or, if sqlite3.nVdbeExec is greater than 1,
+** string contains a copy of zRawSql but with host parameters expanded to
+** their current bindings. Or, if sqlite3.nVdbeExec is greater than 1,
** then the returned string holds a copy of zRawSql with "-- " prepended
** to each line of text.
**
@@ -82461,7 +86302,7 @@ SQLITE_PRIVATE char *sqlite3VdbeExpandSql(
char zBase[100]; /* Initial working space */
db = p->db;
- sqlite3StrAccumInit(&out, 0, zBase, sizeof(zBase),
+ sqlite3StrAccumInit(&out, 0, zBase, sizeof(zBase),
db->aLimit[SQLITE_LIMIT_LENGTH]);
if( db->nVdbeExec>1 ){
while( *zRawSql ){
@@ -82499,12 +86340,12 @@ SQLITE_PRIVATE char *sqlite3VdbeExpandSql(
assert( idx>0 );
}
zRawSql += nToken;
- nextIndex = idx + 1;
+ nextIndex = MAX(idx + 1, nextIndex);
assert( idx>0 && idx<=p->nVar );
pVar = &p->aVar[idx-1];
if( pVar->flags & MEM_Null ){
sqlite3_str_append(&out, "NULL", 4);
- }else if( pVar->flags & MEM_Int ){
+ }else if( pVar->flags & (MEM_Int|MEM_IntReal) ){
sqlite3_str_appendf(&out, "%lld", pVar->u.i);
}else if( pVar->flags & MEM_Real ){
sqlite3_str_appendf(&out, "%!.15g", pVar->u.r);
@@ -82529,7 +86370,7 @@ SQLITE_PRIVATE char *sqlite3VdbeExpandSql(
nOut = SQLITE_TRACE_SIZE_LIMIT;
while( nOutn && (pVar->z[nOut]&0xc0)==0x80 ){ nOut++; }
}
-#endif
+#endif
sqlite3_str_appendf(&out, "'%.*q'", nOut, pVar->z);
#ifdef SQLITE_TRACE_SIZE_LIMIT
if( nOutn ){
@@ -82688,17 +86529,45 @@ SQLITE_API int sqlite3_found_count = 0;
# define UPDATE_MAX_BLOBSIZE(P)
#endif
+#ifdef SQLITE_DEBUG
+/* This routine provides a convenient place to set a breakpoint during
+** tracing with PRAGMA vdbe_trace=on. The breakpoint fires right after
+** each opcode is printed. Variables "pc" (program counter) and pOp are
+** available to add conditionals to the breakpoint. GDB example:
+**
+** break test_trace_breakpoint if pc=22
+**
+** Other useful labels for breakpoints include:
+** test_addop_breakpoint(pc,pOp)
+** sqlite3CorruptError(lineno)
+** sqlite3MisuseError(lineno)
+** sqlite3CantopenError(lineno)
+*/
+static void test_trace_breakpoint(int pc, Op *pOp, Vdbe *v){
+ static int n = 0;
+ n++;
+}
+#endif
+
/*
** Invoke the VDBE coverage callback, if that callback is defined. This
** feature is used for test suite validation only and does not appear an
** production builds.
**
-** M is an integer between 2 and 4. 2 indicates a ordinary two-way
-** branch (I=0 means fall through and I=1 means taken). 3 indicates
-** a 3-way branch where the third way is when one of the operands is
-** NULL. 4 indicates the OP_Jump instruction which has three destinations
-** depending on whether the first operand is less than, equal to, or greater
-** than the second.
+** M is the type of branch. I is the direction taken for this instance of
+** the branch.
+**
+** M: 2 - two-way branch (I=0: fall-thru 1: jump )
+** 3 - two-way + NULL (I=0: fall-thru 1: jump 2: NULL )
+** 4 - OP_Jump (I=0: jump p1 1: jump p2 2: jump p3)
+**
+** In other words, if M is 2, then I is either 0 (for fall-through) or
+** 1 (for when the branch is taken). If M is 3, the I is 0 for an
+** ordinary fall-through, I is 1 if the branch was taken, and I is 2
+** if the result of comparison is NULL. For M=3, I=2 the jump may or
+** may not be taken, depending on the SQLITE_JUMPIFNULL flags in p5.
+** When M is 4, that means that an OP_Jump is being run. I is 0, 1, or 2
+** depending on if the operands are less than, equal, or greater than.
**
** iSrcLine is the source code line (from the __LINE__ macro) that
** generated the VDBE instruction combined with flag bits. The source
@@ -82709,9 +86578,9 @@ SQLITE_API int sqlite3_found_count = 0;
** alternate branch are never taken. If a branch is never taken then
** flags should be 0x06 since only the fall-through approach is allowed.
**
-** Bit 0x04 of the flags indicates an OP_Jump opcode that is only
+** Bit 0x08 of the flags indicates an OP_Jump opcode that is only
** interested in equal or not-equal. In other words, I==0 and I==2
-** should be treated the same.
+** should be treated as equivalent
**
** Since only a line number is retained, not the filename, this macro
** only works for amalgamation builds. But that is ok, since these macros
@@ -82735,6 +86604,18 @@ SQLITE_API int sqlite3_found_count = 0;
mNever = iSrcLine >> 24;
assert( (I & mNever)==0 );
if( sqlite3GlobalConfig.xVdbeBranch==0 ) return; /*NO_TEST*/
+ /* Invoke the branch coverage callback with three arguments:
+ ** iSrcLine - the line number of the VdbeCoverage() macro, with
+ ** flags removed.
+ ** I - Mask of bits 0x07 indicating which cases are are
+ ** fulfilled by this instance of the jump. 0x01 means
+ ** fall-thru, 0x02 means taken, 0x04 means NULL. Any
+ ** impossible cases (ex: if the comparison is never NULL)
+ ** are filled in automatically so that the coverage
+ ** measurement logic does not flag those impossible cases
+ ** as missed coverage.
+ ** M - Type of jump. Same as M argument above
+ */
I |= mNever;
if( M==2 ) I |= 0x04;
if( M==4 ){
@@ -82746,14 +86627,6 @@ SQLITE_API int sqlite3_found_count = 0;
}
#endif
-/*
-** Convert the given register into a string if it isn't one
-** already. Return non-zero if a malloc() fails.
-*/
-#define Stringify(P, enc) \
- if(((P)->flags&(MEM_Str|MEM_Blob))==0 && sqlite3VdbeMemStringify(P,enc,0)) \
- { goto no_mem; }
-
/*
** An ephemeral string value (signified by the MEM_Ephem flag) contains
** a pointer to a dynamically allocated string where some other entity
@@ -82784,7 +86657,7 @@ static VdbeCursor *allocateCursor(
u8 eCurType /* Type of the new cursor */
){
/* 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:
**
@@ -82805,8 +86678,8 @@ static VdbeCursor *allocateCursor(
int nByte;
VdbeCursor *pCx = 0;
- nByte =
- ROUND8(sizeof(VdbeCursor)) + 2*sizeof(u32)*nField +
+ nByte =
+ ROUND8(sizeof(VdbeCursor)) + 2*sizeof(u32)*nField +
(eCurType==CURTYPE_BTREE?sqlite3BtreeCursorSize():0);
assert( iCur>=0 && iCurnCursor );
@@ -82814,22 +86687,55 @@ static VdbeCursor *allocateCursor(
sqlite3VdbeFreeCursor(p, p->apCsr[iCur]);
p->apCsr[iCur] = 0;
}
- if( SQLITE_OK==sqlite3VdbeMemClearAndResize(pMem, nByte) ){
- p->apCsr[iCur] = pCx = (VdbeCursor*)pMem->z;
- memset(pCx, 0, offsetof(VdbeCursor,pAltCursor));
- pCx->eCurType = eCurType;
- pCx->iDb = iDb;
- pCx->nField = nField;
- pCx->aOffset = &pCx->aType[nField];
- if( eCurType==CURTYPE_BTREE ){
- pCx->uc.pCursor = (BtCursor*)
- &pMem->z[ROUND8(sizeof(VdbeCursor))+2*sizeof(u32)*nField];
- sqlite3BtreeCursorZero(pCx->uc.pCursor);
+
+ /* There used to be a call to sqlite3VdbeMemClearAndResize() to make sure
+ ** the pMem used to hold space for the cursor has enough storage available
+ ** in pMem->zMalloc. But for the special case of the aMem[] entries used
+ ** to hold cursors, it is faster to in-line the logic. */
+ assert( pMem->flags==MEM_Undefined );
+ assert( (pMem->flags & MEM_Dyn)==0 );
+ assert( pMem->szMalloc==0 || pMem->z==pMem->zMalloc );
+ if( pMem->szMallocszMalloc>0 ){
+ sqlite3DbFreeNN(pMem->db, pMem->zMalloc);
}
+ pMem->z = pMem->zMalloc = sqlite3DbMallocRaw(pMem->db, nByte);
+ if( pMem->zMalloc==0 ){
+ pMem->szMalloc = 0;
+ return 0;
+ }
+ pMem->szMalloc = nByte;
+ }
+
+ p->apCsr[iCur] = pCx = (VdbeCursor*)pMem->zMalloc;
+ memset(pCx, 0, offsetof(VdbeCursor,pAltCursor));
+ pCx->eCurType = eCurType;
+ pCx->iDb = iDb;
+ pCx->nField = nField;
+ pCx->aOffset = &pCx->aType[nField];
+ if( eCurType==CURTYPE_BTREE ){
+ pCx->uc.pCursor = (BtCursor*)
+ &pMem->z[ROUND8(sizeof(VdbeCursor))+2*sizeof(u32)*nField];
+ sqlite3BtreeCursorZero(pCx->uc.pCursor);
}
return pCx;
}
+/*
+** The string in pRec is known to look like an integer and to have a
+** floating point value of rValue. Return true and set *piValue to the
+** integer value if the string is in range to be an integer. Otherwise,
+** return false.
+*/
+static int alsoAnInt(Mem *pRec, double rValue, i64 *piValue){
+ i64 iValue = (double)rValue;
+ if( sqlite3RealSameAsInt(rValue,iValue) ){
+ *piValue = iValue;
+ return 1;
+ }
+ return 0==sqlite3Atoi64(pRec->z, piValue, pRec->n, pRec->enc);
+}
+
/*
** Try to convert a value into a numeric representation if we can
** do so without loss of information. In other words, if the string
@@ -82847,12 +86753,12 @@ static VdbeCursor *allocateCursor(
*/
static void applyNumericAffinity(Mem *pRec, int bTryForInt){
double rValue;
- i64 iValue;
u8 enc = pRec->enc;
- assert( (pRec->flags & (MEM_Str|MEM_Int|MEM_Real))==MEM_Str );
- if( sqlite3AtoF(pRec->z, &rValue, pRec->n, enc)==0 ) return;
- if( 0==sqlite3Atoi64(pRec->z, &iValue, pRec->n, enc) ){
- pRec->u.i = iValue;
+ int rc;
+ assert( (pRec->flags & (MEM_Str|MEM_Int|MEM_Real|MEM_IntReal))==MEM_Str );
+ rc = sqlite3AtoF(pRec->z, &rValue, pRec->n, enc);
+ if( rc<=0 ) return;
+ if( rc==1 && alsoAnInt(pRec, rValue, &pRec->u.i) ){
pRec->flags |= MEM_Int;
}else{
pRec->u.r = rValue;
@@ -82872,7 +86778,7 @@ static void applyNumericAffinity(Mem *pRec, int bTryForInt){
** 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
@@ -82882,6 +86788,7 @@ static void applyNumericAffinity(Mem *pRec, int bTryForInt){
** Convert pRec to a text representation.
**
** SQLITE_AFF_BLOB:
+** SQLITE_AFF_NONE:
** No-op. pRec is unchanged.
*/
static void applyAffinity(
@@ -82902,15 +86809,18 @@ static void applyAffinity(
}else if( affinity==SQLITE_AFF_TEXT ){
/* Only attempt the conversion to TEXT if there is an integer or real
** representation (blob and NULL do not get converted) but no string
- ** representation. It would be harmless to repeat the conversion if
+ ** representation. It would be harmless to repeat the conversion if
** there is already a string rep, but it is pointless to waste those
** CPU cycles. */
if( 0==(pRec->flags&MEM_Str) ){ /*OPTIMIZATION-IF-FALSE*/
- if( (pRec->flags&(MEM_Real|MEM_Int)) ){
+ if( (pRec->flags&(MEM_Real|MEM_Int|MEM_IntReal)) ){
+ testcase( pRec->flags & MEM_Int );
+ testcase( pRec->flags & MEM_Real );
+ testcase( pRec->flags & MEM_IntReal );
sqlite3VdbeMemStringify(pRec, enc, 1);
}
}
- pRec->flags &= ~(MEM_Real|MEM_Int);
+ pRec->flags &= ~(MEM_Real|MEM_Int|MEM_IntReal);
}
}
@@ -82931,12 +86841,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);
@@ -82949,12 +86859,24 @@ SQLITE_PRIVATE void sqlite3ValueApplyAffinity(
** accordingly.
*/
static u16 SQLITE_NOINLINE computeNumericType(Mem *pMem){
- assert( (pMem->flags & (MEM_Int|MEM_Real))==0 );
+ int rc;
+ sqlite3_int64 ix;
+ assert( (pMem->flags & (MEM_Int|MEM_Real|MEM_IntReal))==0 );
assert( (pMem->flags & (MEM_Str|MEM_Blob))!=0 );
- if( sqlite3AtoF(pMem->z, &pMem->u.r, pMem->n, pMem->enc)==0 ){
- return 0;
+ if( ExpandBlob(pMem) ){
+ pMem->u.i = 0;
+ return MEM_Int;
}
- if( sqlite3Atoi64(pMem->z, &pMem->u.i, pMem->n, pMem->enc)==0 ){
+ rc = sqlite3AtoF(pMem->z, &pMem->u.r, pMem->n, pMem->enc);
+ if( rc<=0 ){
+ if( rc==0 && sqlite3Atoi64(pMem->z, &ix, pMem->n, pMem->enc)<=1 ){
+ pMem->u.i = ix;
+ return MEM_Int;
+ }else{
+ return MEM_Real;
+ }
+ }else if( rc==1 && sqlite3Atoi64(pMem->z, &ix, pMem->n, pMem->enc)==0 ){
+ pMem->u.i = ix;
return MEM_Int;
}
return MEM_Real;
@@ -82962,16 +86884,21 @@ static u16 SQLITE_NOINLINE computeNumericType(Mem *pMem){
/*
** Return the numeric type for pMem, either MEM_Int or MEM_Real or both or
-** none.
+** none.
**
** Unlike applyNumericAffinity(), this routine does not modify pMem->flags.
** But it does set pMem->u.r and pMem->u.i appropriately.
*/
static u16 numericType(Mem *pMem){
- if( pMem->flags & (MEM_Int|MEM_Real) ){
- return pMem->flags & (MEM_Int|MEM_Real);
+ if( pMem->flags & (MEM_Int|MEM_Real|MEM_IntReal) ){
+ testcase( pMem->flags & MEM_Int );
+ testcase( pMem->flags & MEM_Real );
+ testcase( pMem->flags & MEM_IntReal );
+ return pMem->flags & (MEM_Int|MEM_Real|MEM_IntReal);
}
if( pMem->flags & (MEM_Str|MEM_Blob) ){
+ testcase( pMem->flags & MEM_Str );
+ testcase( pMem->flags & MEM_Blob );
return computeNumericType(pMem);
}
return 0;
@@ -82982,12 +86909,9 @@ static u16 numericType(Mem *pMem){
** Write a nice string representation of the contents of cell pMem
** into buffer zBuf, length nBuf.
*/
-SQLITE_PRIVATE void sqlite3VdbeMemPrettyPrint(Mem *pMem, char *zBuf){
- char *zCsr = zBuf;
+SQLITE_PRIVATE void sqlite3VdbeMemPrettyPrint(Mem *pMem, StrAccum *pStr){
int f = pMem->flags;
-
static const char *const encnames[] = {"(X)", "(8)", "(16LE)", "(16BE)"};
-
if( f&MEM_Blob ){
int i;
char c;
@@ -83003,55 +86927,40 @@ SQLITE_PRIVATE void sqlite3VdbeMemPrettyPrint(Mem *pMem, char *zBuf){
}else{
c = 's';
}
- *(zCsr++) = c;
- sqlite3_snprintf(100, zCsr, "%d[", pMem->n);
- zCsr += sqlite3Strlen30(zCsr);
- for(i=0; i<16 && in; i++){
- sqlite3_snprintf(100, zCsr, "%02X", ((int)pMem->z[i] & 0xFF));
- zCsr += sqlite3Strlen30(zCsr);
+ sqlite3_str_appendf(pStr, "%cx[", c);
+ for(i=0; i<25 && in; i++){
+ sqlite3_str_appendf(pStr, "%02X", ((int)pMem->z[i] & 0xFF));
}
- for(i=0; i<16 && in; i++){
+ sqlite3_str_appendf(pStr, "|");
+ for(i=0; i<25 && in; i++){
char z = pMem->z[i];
- if( z<32 || z>126 ) *zCsr++ = '.';
- else *zCsr++ = z;
+ sqlite3_str_appendchar(pStr, 1, (z<32||z>126)?'.':z);
}
- *(zCsr++) = ']';
+ sqlite3_str_appendf(pStr,"]");
if( f & MEM_Zero ){
- sqlite3_snprintf(100, zCsr,"+%dz",pMem->u.nZero);
- zCsr += sqlite3Strlen30(zCsr);
+ sqlite3_str_appendf(pStr, "+%dz",pMem->u.nZero);
}
- *zCsr = '\0';
}else if( f & MEM_Str ){
- int j, k;
- zBuf[0] = ' ';
+ int j;
+ u8 c;
if( f & MEM_Dyn ){
- zBuf[1] = 'z';
+ c = 'z';
assert( (f & (MEM_Static|MEM_Ephem))==0 );
}else if( f & MEM_Static ){
- zBuf[1] = 't';
+ c = 't';
assert( (f & (MEM_Dyn|MEM_Ephem))==0 );
}else if( f & MEM_Ephem ){
- zBuf[1] = 'e';
+ c = 'e';
assert( (f & (MEM_Static|MEM_Dyn))==0 );
}else{
- zBuf[1] = 's';
+ c = 's';
}
- k = 2;
- sqlite3_snprintf(100, &zBuf[k], "%d", pMem->n);
- k += sqlite3Strlen30(&zBuf[k]);
- zBuf[k++] = '[';
- for(j=0; j<15 && jn; j++){
- u8 c = pMem->z[j];
- if( c>=0x20 && c<0x7f ){
- zBuf[k++] = c;
- }else{
- zBuf[k++] = '.';
- }
+ sqlite3_str_appendf(pStr, " %c%d[", c, pMem->n);
+ for(j=0; j<25 && jn; j++){
+ c = pMem->z[j];
+ sqlite3_str_appendchar(pStr, 1, (c>=0x20&&c<=0x7f) ? c : '.');
}
- zBuf[k++] = ']';
- sqlite3_snprintf(100,&zBuf[k], encnames[pMem->enc]);
- k += sqlite3Strlen30(&zBuf[k]);
- zBuf[k++] = 0;
+ sqlite3_str_appendf(pStr, "]%s", encnames[pMem->enc]);
}
}
#endif
@@ -83067,29 +86976,53 @@ static void memTracePrint(Mem *p){
printf(p->flags & MEM_Zero ? " NULL-nochng" : " NULL");
}else if( (p->flags & (MEM_Int|MEM_Str))==(MEM_Int|MEM_Str) ){
printf(" si:%lld", p->u.i);
+ }else if( (p->flags & (MEM_IntReal))!=0 ){
+ printf(" ir:%lld", p->u.i);
}else if( p->flags & MEM_Int ){
printf(" i:%lld", p->u.i);
#ifndef SQLITE_OMIT_FLOATING_POINT
}else if( p->flags & MEM_Real ){
- printf(" r:%g", p->u.r);
+ printf(" r:%.17g", p->u.r);
#endif
}else if( sqlite3VdbeMemIsRowSet(p) ){
printf(" (rowset)");
}else{
- char zBuf[200];
- sqlite3VdbeMemPrettyPrint(p, zBuf);
- printf(" %s", zBuf);
+ StrAccum acc;
+ char zBuf[1000];
+ sqlite3StrAccumInit(&acc, 0, zBuf, sizeof(zBuf), 0);
+ sqlite3VdbeMemPrettyPrint(p, &acc);
+ printf(" %s", sqlite3StrAccumFinish(&acc));
}
if( p->flags & MEM_Subtype ) printf(" subtype=0x%02x", p->eSubtype);
}
static void registerTrace(int iReg, Mem *p){
- printf("REG[%d] = ", iReg);
+ printf("R[%d] = ", iReg);
memTracePrint(p);
+ if( p->pScopyFrom ){
+ printf(" <== R[%d]", (int)(p->pScopyFrom - &p[-iReg]));
+ }
printf("\n");
sqlite3VdbeCheckMemInvariants(p);
}
+/**/ void sqlite3PrintMem(Mem *pMem){
+ memTracePrint(pMem);
+ printf("\n");
+ fflush(stdout);
+}
#endif
+#ifdef SQLITE_DEBUG
+/*
+** Show the values of all registers in the virtual machine. Used for
+** interactive debugging.
+*/
+SQLITE_PRIVATE void sqlite3VdbeRegisterDump(Vdbe *v){
+ int i;
+ for(i=1; inMem; i++) registerTrace(i, v->aMem+i);
+}
+#endif /* SQLITE_DEBUG */
+
+
#ifdef SQLITE_DEBUG
# define REGISTER_TRACE(R,M) if(db->flags&SQLITE_VdbeTrace)registerTrace(R,M)
#else
@@ -83099,8 +87032,8 @@ static void registerTrace(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 *********************/
@@ -83118,7 +87051,7 @@ static void registerTrace(int iReg, Mem *p){
******************************************************************************
**
** This file contains inline asm code for retrieving "high-performance"
-** counters for x86 class CPUs.
+** counters for x86 and x86_64 class CPUs.
*/
#ifndef SQLITE_HWTIME_H
#define SQLITE_HWTIME_H
@@ -83129,8 +87062,9 @@ static void registerTrace(int iReg, Mem *p){
** processor and returns that value. This can be used for high-res
** profiling.
*/
-#if (defined(__GNUC__) || defined(_MSC_VER)) && \
- (defined(i386) || defined(__i386__) || defined(_M_IX86))
+#if !defined(__STRICT_ANSI__) && \
+ (defined(__GNUC__) || defined(_MSC_VER)) && \
+ (defined(i386) || defined(__i386__) || defined(_M_IX86))
#if defined(__GNUC__)
@@ -83151,15 +87085,15 @@ static void registerTrace(int iReg, Mem *p){
#endif
-#elif (defined(__GNUC__) && defined(__x86_64__))
+#elif !defined(__STRICT_ANSI__) && (defined(__GNUC__) && defined(__x86_64__))
__inline__ sqlite_uint64 sqlite3Hwtime(void){
unsigned long val;
__asm__ __volatile__ ("rdtsc" : "=A" (val));
return val;
}
-
-#elif (defined(__GNUC__) && defined(__ppc__))
+
+#elif !defined(__STRICT_ANSI__) && (defined(__GNUC__) && defined(__ppc__))
__inline__ sqlite_uint64 sqlite3Hwtime(void){
unsigned long long retval;
@@ -83176,14 +87110,13 @@ static void registerTrace(int iReg, Mem *p){
#else
- #error Need implementation of sqlite3Hwtime() for your platform.
-
/*
- ** To compile without implementing sqlite3Hwtime() for your platform,
- ** you can remove the above #error and use the following
- ** stub function. You will lose timing support for many
- ** of the debugging and testing utilities, but it should at
- ** least compile and run.
+ ** asm() is needed for hardware timing support. Without asm(),
+ ** disable the sqlite3Hwtime() routine.
+ **
+ ** sqlite3Hwtime() is only used for some obscure debugging
+ ** and analysis configurations, not in any deliverable, so this
+ ** should not be a great loss.
*/
SQLITE_PRIVATE sqlite_uint64 sqlite3Hwtime(void){ return ((sqlite_uint64)0); }
@@ -83200,9 +87133,9 @@ SQLITE_PRIVATE sqlite_uint64 sqlite3Hwtime(void){ return ((sqlite_uint64)0); }
/*
** 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) );
@@ -83242,7 +87175,7 @@ static Mem *out2Prerelease(Vdbe *p, VdbeOp *pOp){
/*
** Execute as much of a VDBE program as we can.
-** This is the core of sqlite3_step().
+** This is the core of sqlite3_step().
*/
SQLITE_PRIVATE int sqlite3VdbeExec(
Vdbe *p /* The VDBE */
@@ -83260,9 +87193,9 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
u8 resetSchemaOnFault = 0; /* Reset schema after an error if positive */
u8 encoding = ENC(db); /* The database encoding */
int iCompare = 0; /* Result of last comparison */
- unsigned nVmStep = 0; /* Number of virtual machine steps */
+ u64 nVmStep = 0; /* Number of virtual machine steps */
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
- unsigned nProgressLimit; /* Invoke xProgress() when nVmStep reaches this */
+ u64 nProgressLimit; /* Invoke xProgress() when nVmStep reaches this */
#endif
Mem *aMem = p->aMem; /* Copy of p->aMem */
Mem *pIn1 = 0; /* 1st input operand */
@@ -83274,30 +87207,32 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
#endif
/*** INSERT STACK UNION HERE ***/
- assert( p->magic==VDBE_MAGIC_RUN ); /* sqlite3_step() verifies this */
+ assert( p->iVdbeMagic==VDBE_MAGIC_RUN ); /* sqlite3_step() verifies this */
sqlite3VdbeEnter(p);
- if( p->rc==SQLITE_NOMEM ){
- /* This happens if a malloc() inside a call to sqlite3_column_text() or
- ** sqlite3_column_text16() failed. */
- goto no_mem;
- }
- assert( p->rc==SQLITE_OK || (p->rc&0xff)==SQLITE_BUSY );
- assert( p->bIsReader || p->readOnly!=0 );
- p->iCurrentTime = 0;
- assert( p->explain==0 );
- p->pResultSet = 0;
- db->busyHandler.nBusy = 0;
- if( db->u1.isInterrupted ) goto abort_due_to_interrupt;
- sqlite3VdbeIOTraceSql(p);
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
if( db->xProgress ){
u32 iPrior = p->aCounter[SQLITE_STMTSTATUS_VM_STEP];
assert( 0 < db->nProgressOps );
nProgressLimit = db->nProgressOps - (iPrior % db->nProgressOps);
}else{
- nProgressLimit = 0xffffffff;
+ nProgressLimit = LARGEST_UINT64;
}
#endif
+ if( p->rc==SQLITE_NOMEM ){
+ /* This happens if a malloc() inside a call to sqlite3_column_text() or
+ ** sqlite3_column_text16() failed. */
+ goto no_mem;
+ }
+ assert( p->rc==SQLITE_OK || (p->rc&0xff)==SQLITE_BUSY );
+ testcase( p->rc!=SQLITE_OK );
+ p->rc = SQLITE_OK;
+ assert( p->bIsReader || p->readOnly!=0 );
+ p->iCurrentTime = 0;
+ assert( p->explain==0 );
+ p->pResultSet = 0;
+ db->busyHandler.nBusy = 0;
+ if( AtomicLoad(&db->u1.isInterrupted) ) goto abort_due_to_interrupt;
+ sqlite3VdbeIOTraceSql(p);
#ifdef SQLITE_DEBUG
sqlite3BeginBenignMalloc();
if( p->pc==0
@@ -83344,9 +87279,10 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
#ifdef SQLITE_DEBUG
if( db->flags & SQLITE_VdbeTrace ){
sqlite3VdbePrintOp(stdout, (int)(pOp - aOp), pOp);
+ test_trace_breakpoint((int)(pOp - aOp),pOp,p);
}
#endif
-
+
/* Check to see if we need to simulate an interrupt. This only happens
** if we have a special test build.
@@ -83400,7 +87336,7 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE)
pOrigOp = pOp;
#endif
-
+
switch( pOp->opcode ){
/*****************************************************************************
@@ -83441,7 +87377,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.
**
@@ -83451,13 +87387,27 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
** to the current line should be indented for EXPLAIN output.
*/
case OP_Goto: { /* jump */
+
+#ifdef SQLITE_DEBUG
+ /* In debuggging mode, when the p5 flags is set on an OP_Goto, that
+ ** means we should really jump back to the preceeding OP_ReleaseReg
+ ** instruction. */
+ if( pOp->p5 ){
+ assert( pOp->p2 < (int)(pOp - aOp) );
+ assert( pOp->p2 > 1 );
+ pOp = &aOp[pOp->p2 - 2];
+ assert( pOp[1].opcode==OP_ReleaseReg );
+ goto check_for_interrupt;
+ }
+#endif
+
jump_to_p2_and_check_for_interrupt:
pOp = &aOp[pOp->p2 - 1];
/* Opcodes that are used as the bottom of a loop (OP_Next, OP_Prev,
** OP_VNext, or OP_SorterNext) all jump here upon
** completion. Check to see if sqlite3_interrupt() has been called
- ** or if the progress callback needs to be invoked.
+ ** or if the progress callback needs to be invoked.
**
** This code uses unstructured "goto" statements and does not look clean.
** But that is not due to sloppy coding habits. The code is written this
@@ -83465,7 +87415,7 @@ jump_to_p2_and_check_for_interrupt:
** checks on every opcode. This helps sqlite3_step() to run about 1.5%
** faster according to "valgrind --tool=cachegrind" */
check_for_interrupt:
- if( db->u1.isInterrupted ) goto abort_due_to_interrupt;
+ if( AtomicLoad(&db->u1.isInterrupted) ) goto abort_due_to_interrupt;
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
/* Call the progress callback if it is configured and the required number
** of VDBE ops have been executed (either since this invocation of
@@ -83473,16 +87423,17 @@ check_for_interrupt:
** If the progress callback returns non-zero, exit the virtual machine with
** a return code SQLITE_ABORT.
*/
- if( nVmStep>=nProgressLimit && db->xProgress!=0 ){
+ while( nVmStep>=nProgressLimit && db->xProgress!=0 ){
assert( db->nProgressOps!=0 );
- nProgressLimit = nVmStep + db->nProgressOps - (nVmStep%db->nProgressOps);
+ nProgressLimit += db->nProgressOps;
if( db->xProgress(db->pProgressArg) ){
+ nProgressLimit = LARGEST_UINT64;
rc = SQLITE_INTERRUPT;
goto abort_due_to_error;
}
}
#endif
-
+
break;
}
@@ -83604,6 +87555,7 @@ case OP_HaltIfNull: { /* in3 */
#endif
if( (pIn3->flags & MEM_Null)==0 ) break;
/* Fall through into OP_Halt */
+ /* no break */ deliberate_fall_through
}
/* Opcode: Halt P1 P2 * P4 P5
@@ -83617,7 +87569,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.
**
@@ -83652,7 +87604,7 @@ case OP_Halt: {
sqlite3VdbeSetChanges(db, p->nChange);
pcx = sqlite3VdbeFrameRestore(pFrame);
if( pOp->p2==OE_Ignore ){
- /* Instruction pcx is the OP_Program that invoked the sub-program
+ /* Instruction pcx 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
@@ -83740,7 +87692,7 @@ case OP_Real: { /* same as TK_FLOAT, out2 */
/* Opcode: String8 * P2 * P4 *
** Synopsis: r[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 a String opcode before it is executed for the first time. During
** this transformation, the length of string P4 is computed and stored
** as the P1 parameter.
@@ -83748,13 +87700,13 @@ case OP_Real: { /* same as TK_FLOAT, out2 */
case OP_String8: { /* same as TK_STRING, out2 */
assert( pOp->p4.z!=0 );
pOut = out2Prerelease(p, pOp);
- pOp->opcode = OP_String;
pOp->p1 = sqlite3Strlen30(pOp->p4.z);
#ifndef SQLITE_OMIT_UTF16
if( encoding!=SQLITE_UTF8 ){
rc = sqlite3VdbeMemSetStr(pOut, pOp->p4.z, -1, SQLITE_UTF8, SQLITE_STATIC);
assert( rc==SQLITE_OK || rc==SQLITE_TOOBIG );
+ if( rc ) goto too_big;
if( SQLITE_OK!=sqlite3VdbeChangeEncoding(pOut, encoding) ) goto no_mem;
assert( pOut->szMalloc>0 && pOut->zMalloc==pOut->z );
assert( VdbeMemDynamic(pOut)==0 );
@@ -83767,15 +87719,16 @@ case OP_String8: { /* same as TK_STRING, out2 */
pOp->p4.z = pOut->z;
pOp->p1 = pOut->n;
}
- testcase( rc==SQLITE_TOOBIG );
#endif
if( pOp->p1>db->aLimit[SQLITE_LIMIT_LENGTH] ){
goto too_big;
}
+ pOp->opcode = OP_String;
assert( rc==SQLITE_OK );
/* Fall through to the next case, OP_String */
+ /* no break */ deliberate_fall_through
}
-
+
/* Opcode: String P1 P2 P3 P4 P5
** Synopsis: r[P2]='P4' (len=P1)
**
@@ -83889,7 +87842,10 @@ case OP_Variable: { /* out2 */
goto too_big;
}
pOut = &aMem[pOp->p2];
- sqlite3VdbeMemShallowCopy(pOut, pVar, MEM_Static);
+ if( VdbeMemDynamic(pOut) ) sqlite3VdbeMemSetNull(pOut);
+ memcpy(pOut, pVar, MEMCELLSIZE);
+ pOut->flags &= ~(MEM_Dyn|MEM_Ephem);
+ pOut->flags |= MEM_Static|MEM_FromBind;
UPDATE_MAX_BLOBSIZE(pOut);
break;
}
@@ -83923,8 +87879,13 @@ case OP_Move: {
memAboutToChange(p, pOut);
sqlite3VdbeMemMove(pOut, pIn1);
#ifdef SQLITE_DEBUG
- if( pOut->pScopyFrom>=&aMem[p1] && pOut->pScopyFrompScopyFrom += pOp->p2 - p1;
+ pIn1->pScopyFrom = 0;
+ { int i;
+ for(i=1; inMem; i++){
+ if( aMem[i].pScopyFrom==pIn1 ){
+ aMem[i].pScopyFrom = pOut;
+ }
+ }
}
#endif
Deephemeralize(pOut);
@@ -84006,6 +87967,26 @@ case OP_IntCopy: { /* out2 */
break;
}
+/* Opcode: ChngCntRow P1 P2 * * *
+** Synopsis: output=r[P1]
+**
+** Output value in register P1 as the chance count for a DML statement,
+** due to the "PRAGMA count_changes=ON" setting. Or, if there was a
+** foreign key error in the statement, trigger the error now.
+**
+** This opcode is a variant of OP_ResultRow that checks the foreign key
+** immediate constraint count and throws an error if the count is
+** non-zero. The P2 opcode must be 1.
+*/
+case OP_ChngCntRow: {
+ assert( pOp->p2==1 );
+ if( (rc = sqlite3VdbeCheckFk(p,0))!=SQLITE_OK ){
+ goto abort_due_to_error;
+ }
+ /* Fall through to the next case, OP_ResultRow */
+ /* no break */ deliberate_fall_through
+}
+
/* Opcode: ResultRow P1 P2 * * *
** Synopsis: output=r[P1@P2]
**
@@ -84019,49 +88000,9 @@ case OP_ResultRow: {
Mem *pMem;
int i;
assert( p->nResColumn==pOp->p2 );
- assert( pOp->p1>0 );
+ assert( pOp->p1>0 || CORRUPT_DB );
assert( pOp->p1+pOp->p2<=(p->nMem+1 - p->nCursor)+1 );
-#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
- /* Run the progress counter just before returning.
- */
- if( db->xProgress!=0
- && nVmStep>=nProgressLimit
- && db->xProgress(db->pProgressArg)!=0
- ){
- rc = SQLITE_INTERRUPT;
- goto abort_due_to_error;
- }
-#endif
-
- /* If this statement has violated immediate foreign key constraints, do
- ** not return the number of rows modified. And do not RELEASE the statement
- ** transaction. It needs to be rolled back. */
- if( SQLITE_OK!=(rc = sqlite3VdbeCheckFk(p, 0)) ){
- assert( db->flags&SQLITE_CountRows );
- assert( p->usesStmtJournal );
- goto abort_due_to_error;
- }
-
- /* If the SQLITE_CountRows flag is set in sqlite3.flags mask, then
- ** DML statements invoke this opcode to return the number of rows
- ** modified to the user. This is the only way that a VM that
- ** opens a statement transaction may invoke this opcode.
- **
- ** In case this is such a statement, close any statement transaction
- ** opened by this VM before returning control to the user. This is to
- ** ensure that statement-transactions are always nested, not overlapping.
- ** If the open statement-transaction is not closed here, then the user
- ** may step another VM that opens its own statement transaction. This
- ** may lead to overlapping statement transactions.
- **
- ** The statement transaction is never a top-level transaction. Hence
- ** the RELEASE call below can never fail.
- */
- assert( p->iStatement==0 || db->flags&SQLITE_CountRows );
- rc = sqlite3VdbeCloseStatement(p, SAVEPOINT_RELEASE);
- assert( rc==SQLITE_OK );
-
/* Invalidate all ephemeral cursor row caches */
p->cacheCtr = (p->cacheCtr + 2)|1;
@@ -84077,13 +88018,22 @@ case OP_ResultRow: {
|| (pMem[i].flags & (MEM_Str|MEM_Blob))==0 );
sqlite3VdbeMemNulTerminate(&pMem[i]);
REGISTER_TRACE(pOp->p1+i, &pMem[i]);
+#ifdef SQLITE_DEBUG
+ /* The registers in the result will not be used again when the
+ ** prepared statement restarts. This is because sqlite3_column()
+ ** APIs might have caused type conversions of made other changes to
+ ** the register values. Therefore, we can go ahead and break any
+ ** OP_SCopy dependencies. */
+ pMem[i].pScopyFrom = 0;
+#endif
}
if( db->mallocFailed ) goto no_mem;
if( db->mTrace & SQLITE_TRACE_ROW ){
- db->xTrace(SQLITE_TRACE_ROW, db->pTraceArg, p, 0);
+ db->trace.xV2(SQLITE_TRACE_ROW, db->pTraceArg, p, 0);
}
+
/* Return SQLITE_ROW
*/
p->pc = (int)(pOp - aOp) + 1;
@@ -84105,33 +88055,56 @@ case OP_ResultRow: {
** to avoid a memcpy().
*/
case OP_Concat: { /* same as TK_CONCAT, in1, in2, out3 */
- i64 nByte;
+ i64 nByte; /* Total size of the output string or blob */
+ u16 flags1; /* Initial flags for P1 */
+ u16 flags2; /* Initial flags for P2 */
pIn1 = &aMem[pOp->p1];
pIn2 = &aMem[pOp->p2];
pOut = &aMem[pOp->p3];
+ testcase( pOut==pIn2 );
assert( pIn1!=pOut );
- if( (pIn1->flags | pIn2->flags) & MEM_Null ){
+ flags1 = pIn1->flags;
+ testcase( flags1 & MEM_Null );
+ testcase( pIn2->flags & MEM_Null );
+ if( (flags1 | pIn2->flags) & MEM_Null ){
sqlite3VdbeMemSetNull(pOut);
break;
}
- if( ExpandBlob(pIn1) || ExpandBlob(pIn2) ) goto no_mem;
- Stringify(pIn1, encoding);
- Stringify(pIn2, encoding);
+ if( (flags1 & (MEM_Str|MEM_Blob))==0 ){
+ if( sqlite3VdbeMemStringify(pIn1,encoding,0) ) goto no_mem;
+ flags1 = pIn1->flags & ~MEM_Str;
+ }else if( (flags1 & MEM_Zero)!=0 ){
+ if( sqlite3VdbeMemExpandBlob(pIn1) ) goto no_mem;
+ flags1 = pIn1->flags & ~MEM_Str;
+ }
+ flags2 = pIn2->flags;
+ if( (flags2 & (MEM_Str|MEM_Blob))==0 ){
+ if( sqlite3VdbeMemStringify(pIn2,encoding,0) ) goto no_mem;
+ flags2 = pIn2->flags & ~MEM_Str;
+ }else if( (flags2 & MEM_Zero)!=0 ){
+ if( sqlite3VdbeMemExpandBlob(pIn2) ) goto no_mem;
+ flags2 = pIn2->flags & ~MEM_Str;
+ }
nByte = pIn1->n + pIn2->n;
if( nByte>db->aLimit[SQLITE_LIMIT_LENGTH] ){
goto too_big;
}
- if( sqlite3VdbeMemGrow(pOut, (int)nByte+2, pOut==pIn2) ){
+ if( sqlite3VdbeMemGrow(pOut, (int)nByte+3, pOut==pIn2) ){
goto no_mem;
}
MemSetTypeFlag(pOut, MEM_Str);
if( pOut!=pIn2 ){
memcpy(pOut->z, pIn2->z, pIn2->n);
+ assert( (pIn2->flags & MEM_Dyn) == (flags2 & MEM_Dyn) );
+ pIn2->flags = flags2;
}
memcpy(&pOut->z[pIn2->n], pIn1->z, pIn1->n);
+ assert( (pIn1->flags & MEM_Dyn) == (flags1 & MEM_Dyn) );
+ pIn1->flags = flags1;
pOut->z[nByte]=0;
pOut->z[nByte+1] = 0;
+ pOut->z[nByte+2] = 0;
pOut->flags |= MEM_Term;
pOut->n = (int)nByte;
pOut->enc = encoding;
@@ -84165,15 +88138,15 @@ case OP_Concat: { /* same as TK_CONCAT, in1, in2, out3 */
** Synopsis: r[P3]=r[P2]/r[P1]
**
** 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 * *
** Synopsis: r[P3]=r[P2]%r[P1]
**
-** Compute the remainder after integer register P2 is divided by
-** register P1 and store the result in register P3.
+** Compute the remainder after integer register P2 is divided by
+** register P1 and store the result in register P3.
** If the value in register P1 is zero the result is NULL.
** If either operand is NULL, the result is NULL.
*/
@@ -84182,7 +88155,6 @@ case OP_Subtract: /* same as TK_MINUS, in1, in2, out3 */
case OP_Multiply: /* same as TK_STAR, in1, in2, out3 */
case OP_Divide: /* same as TK_SLASH, in1, in2, out3 */
case OP_Remainder: { /* same as TK_REM, in1, in2, out3 */
- char bIntint; /* Started out as two integer operands */
u16 flags; /* Combined MEM_* flags from both inputs */
u16 type1; /* Numeric type of left operand */
u16 type2; /* Numeric type of right operand */
@@ -84200,7 +88172,6 @@ case OP_Remainder: { /* same as TK_REM, in1, in2, out3 */
if( (type1 & type2 & MEM_Int)!=0 ){
iA = pIn1->u.i;
iB = pIn2->u.i;
- bIntint = 1;
switch( pOp->opcode ){
case OP_Add: if( sqlite3AddInt64(&iB,iA) ) goto fp_math; break;
case OP_Subtract: if( sqlite3SubInt64(&iB,iA) ) goto fp_math; break;
@@ -84223,7 +88194,6 @@ case OP_Remainder: { /* same as TK_REM, in1, in2, out3 */
}else if( (flags & MEM_Null)!=0 ){
goto arithmetic_result_is_null;
}else{
- bIntint = 0;
fp_math:
rA = sqlite3VdbeRealValue(pIn1);
rB = sqlite3VdbeRealValue(pIn2);
@@ -84238,8 +88208,8 @@ fp_math:
break;
}
default: {
- iA = (i64)rA;
- iB = (i64)rB;
+ iA = sqlite3VdbeIntValue(pIn1);
+ iB = sqlite3VdbeIntValue(pIn2);
if( iA==0 ) goto arithmetic_result_is_null;
if( iA==-1 ) iA = 1;
rB = (double)(iB % iA);
@@ -84255,9 +88225,6 @@ fp_math:
}
pOut->u.r = rB;
MemSetTypeFlag(pOut, MEM_Real);
- if( ((type1|type2)&MEM_Real)==0 && !bIntint ){
- sqlite3VdbeIntegerAffinity(pOut);
- }
#endif
}
break;
@@ -84374,7 +88341,7 @@ case OP_ShiftRight: { /* same as TK_RSHIFT, in1, in2, out3 */
/* Opcode: AddImm P1 P2 * * *
** Synopsis: r[P1]=r[P1]+P2
-**
+**
** Add the constant P2 to the value in register P1.
** The result is always an integer.
**
@@ -84389,7 +88356,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
@@ -84399,8 +88366,8 @@ case OP_MustBeInt: { /* jump, in1 */
pIn1 = &aMem[pOp->p1];
if( (pIn1->flags & MEM_Int)==0 ){
applyAffinity(pIn1, SQLITE_AFF_NUMERIC, encoding);
- VdbeBranchTaken((pIn1->flags&MEM_Int)==0, 2);
if( (pIn1->flags & MEM_Int)==0 ){
+ VdbeBranchTaken(1, 2);
if( pOp->p2==0 ){
rc = SQLITE_MISMATCH;
goto abort_due_to_error;
@@ -84409,6 +88376,7 @@ case OP_MustBeInt: { /* jump, in1 */
}
}
}
+ VdbeBranchTaken(0, 2);
MemSetTypeFlag(pIn1, MEM_Int);
break;
}
@@ -84425,8 +88393,11 @@ case OP_MustBeInt: { /* jump, in1 */
*/
case OP_RealAffinity: { /* in1 */
pIn1 = &aMem[pOp->p1];
- if( pIn1->flags & MEM_Int ){
+ if( pIn1->flags & (MEM_Int|MEM_IntReal) ){
+ testcase( pIn1->flags & MEM_Int );
+ testcase( pIn1->flags & MEM_IntReal );
sqlite3VdbeMemRealify(pIn1);
+ REGISTER_TRACE(pOp->p1, pIn1);
}
break;
}
@@ -84437,7 +88408,7 @@ case OP_RealAffinity: { /* in1 */
** Synopsis: affinity(r[P1])
**
** Force the value in register P1 to be the type defined by P2.
-**
+**
**
** - P2=='A' → BLOB
**
- P2=='B' → TEXT
@@ -84458,9 +88429,11 @@ case OP_Cast: { /* in1 */
pIn1 = &aMem[pOp->p1];
memAboutToChange(p, pIn1);
rc = ExpandBlob(pIn1);
- sqlite3VdbeMemCast(pIn1, pOp->p2, encoding);
- UPDATE_MAX_BLOBSIZE(pIn1);
if( rc ) goto abort_due_to_error;
+ rc = sqlite3VdbeMemCast(pIn1, pOp->p2, encoding);
+ if( rc ) goto abort_due_to_error;
+ UPDATE_MAX_BLOBSIZE(pIn1);
+ REGISTER_TRACE(pOp->p1, pIn1);
break;
}
#endif /* SQLITE_OMIT_CAST */
@@ -84469,18 +88442,17 @@ case OP_Cast: { /* in1 */
** Synopsis: IF r[P3]==r[P1]
**
** Compare the values in register P1 and P3. If reg(P3)==reg(P1) then
-** jump to address P2. Or if the SQLITE_STOREP2 flag is set in P5, then
-** store the result of comparison in register P2.
+** jump to address P2.
**
** 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
@@ -84496,9 +88468,8 @@ case OP_Cast: { /* in1 */
** If neither operand is NULL the result is the same as it would be if
** the SQLITE_NULLEQ flag were omitted from P5.
**
-** If both SQLITE_STOREP2 and SQLITE_KEEPNULL flags are set then the
-** content of r[P2] is only changed if the new value is NULL or 0 (false).
-** In other words, a prior r[P2] value will not be overwritten by 1 (true).
+** This opcode saves the result of comparison for use by the new
+** OP_Jump opcode.
*/
/* Opcode: Ne P1 P2 P3 P4 P5
** Synopsis: IF r[P3]!=r[P1]
@@ -84506,31 +88477,26 @@ case OP_Cast: { /* in1 */
** This works just like the Eq opcode except that the jump is taken if
** the operands in registers P1 and P3 are not equal. See the Eq opcode for
** additional information.
-**
-** If both SQLITE_STOREP2 and SQLITE_KEEPNULL flags are set then the
-** content of r[P2] is only changed if the new value is NULL or 1 (true).
-** In other words, a prior r[P2] value will not be overwritten by 0 (false).
*/
/* Opcode: Lt P1 P2 P3 P4 P5
** Synopsis: IF r[P3]p3];
flags1 = pIn1->flags;
flags3 = pIn3->flags;
+ if( (flags1 & flags3 & MEM_Int)!=0 ){
+ assert( (pOp->p5 & SQLITE_AFF_MASK)!=SQLITE_AFF_TEXT || CORRUPT_DB );
+ /* Common case of comparison of two integers */
+ if( pIn3->u.i > pIn1->u.i ){
+ iCompare = +1;
+ if( sqlite3aGTb[pOp->opcode] ){
+ VdbeBranchTaken(1, (pOp->p5 & SQLITE_NULLEQ)?2:3);
+ goto jump_to_p2;
+ }
+ }else if( pIn3->u.i < pIn1->u.i ){
+ iCompare = -1;
+ if( sqlite3aLTb[pOp->opcode] ){
+ VdbeBranchTaken(1, (pOp->p5 & SQLITE_NULLEQ)?2:3);
+ goto jump_to_p2;
+ }
+ }else{
+ iCompare = 0;
+ if( sqlite3aEQb[pOp->opcode] ){
+ VdbeBranchTaken(1, (pOp->p5 & SQLITE_NULLEQ)?2:3);
+ goto jump_to_p2;
+ }
+ }
+ VdbeBranchTaken(0, (pOp->p5 & SQLITE_NULLEQ)?2:3);
+ break;
+ }
if( (flags1 | flags3)&MEM_Null ){
/* One or both operands are NULL */
if( pOp->p5 & SQLITE_NULLEQ ){
@@ -84583,74 +88577,57 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
** OP_Eq or OP_Ne) then take the jump or not depending on whether
** or not both operands are null.
*/
- assert( pOp->opcode==OP_Eq || pOp->opcode==OP_Ne );
assert( (flags1 & MEM_Cleared)==0 );
- assert( (pOp->p5 & SQLITE_JUMPIFNULL)==0 );
+ assert( (pOp->p5 & SQLITE_JUMPIFNULL)==0 || CORRUPT_DB );
+ testcase( (pOp->p5 & SQLITE_JUMPIFNULL)!=0 );
if( (flags1&flags3&MEM_Null)!=0
&& (flags3&MEM_Cleared)==0
){
res = 0; /* Operands are equal */
}else{
- res = 1; /* Operands are not equal */
+ res = ((flags3 & MEM_Null) ? -1 : +1); /* Operands are not equal */
}
}else{
/* SQLITE_NULLEQ is clear and at least one operand is NULL,
** then the result is always NULL.
** The jump is taken if the SQLITE_JUMPIFNULL bit is set.
*/
- if( pOp->p5 & SQLITE_STOREP2 ){
- pOut = &aMem[pOp->p2];
- iCompare = 1; /* Operands are not equal */
- memAboutToChange(p, pOut);
- MemSetTypeFlag(pOut, MEM_Null);
- REGISTER_TRACE(pOp->p2, pOut);
- }else{
- VdbeBranchTaken(2,3);
- if( pOp->p5 & SQLITE_JUMPIFNULL ){
- goto jump_to_p2;
- }
+ iCompare = 1; /* Operands are not equal */
+ VdbeBranchTaken(2,3);
+ if( pOp->p5 & SQLITE_JUMPIFNULL ){
+ goto jump_to_p2;
}
break;
}
}else{
- /* Neither operand is NULL. Do a comparison. */
+ /* Neither operand is NULL and we couldn't do the special high-speed
+ ** integer comparison case. So do a general-case comparison. */
affinity = pOp->p5 & SQLITE_AFF_MASK;
if( affinity>=SQLITE_AFF_NUMERIC ){
if( (flags1 | flags3)&MEM_Str ){
- if( (flags1 & (MEM_Int|MEM_Real|MEM_Str))==MEM_Str ){
+ if( (flags1 & (MEM_Int|MEM_IntReal|MEM_Real|MEM_Str))==MEM_Str ){
applyNumericAffinity(pIn1,0);
- assert( flags3==pIn3->flags );
- /* testcase( flags3!=pIn3->flags );
- ** this used to be possible with pIn1==pIn3, but not since
- ** the column cache was removed. The following assignment
- ** is essentially a no-op. But, it provides defense-in-depth
- ** in case our analysis is incorrect, so it is left in. */
+ testcase( flags3==pIn3->flags );
flags3 = pIn3->flags;
}
- if( (flags3 & (MEM_Int|MEM_Real|MEM_Str))==MEM_Str ){
+ if( (flags3 & (MEM_Int|MEM_IntReal|MEM_Real|MEM_Str))==MEM_Str ){
applyNumericAffinity(pIn3,0);
}
}
- /* Handle the common case of integer comparison here, as an
- ** optimization, to avoid a call to sqlite3MemCompare() */
- if( (pIn1->flags & pIn3->flags & MEM_Int)!=0 ){
- if( pIn3->u.i > pIn1->u.i ){ res = +1; goto compare_op; }
- if( pIn3->u.i < pIn1->u.i ){ res = -1; goto compare_op; }
- res = 0;
- goto compare_op;
- }
}else if( affinity==SQLITE_AFF_TEXT ){
- if( (flags1 & MEM_Str)==0 && (flags1 & (MEM_Int|MEM_Real))!=0 ){
+ if( (flags1 & MEM_Str)==0 && (flags1&(MEM_Int|MEM_Real|MEM_IntReal))!=0 ){
testcase( pIn1->flags & MEM_Int );
testcase( pIn1->flags & MEM_Real );
+ testcase( pIn1->flags & MEM_IntReal );
sqlite3VdbeMemStringify(pIn1, encoding, 1);
testcase( (flags1&MEM_Dyn) != (pIn1->flags&MEM_Dyn) );
flags1 = (pIn1->flags & ~MEM_TypeMask) | (flags1 & MEM_TypeMask);
- assert( pIn1!=pIn3 );
+ if( NEVER(pIn1==pIn3) ) flags3 = flags1 | MEM_Str;
}
- if( (flags3 & MEM_Str)==0 && (flags3 & (MEM_Int|MEM_Real))!=0 ){
+ if( (flags3 & MEM_Str)==0 && (flags3&(MEM_Int|MEM_Real|MEM_IntReal))!=0 ){
testcase( pIn3->flags & MEM_Int );
testcase( pIn3->flags & MEM_Real );
+ testcase( pIn3->flags & MEM_IntReal );
sqlite3VdbeMemStringify(pIn3, encoding, 1);
testcase( (flags3&MEM_Dyn) != (pIn3->flags&MEM_Dyn) );
flags3 = (pIn3->flags & ~MEM_TypeMask) | (flags3 & MEM_TypeMask);
@@ -84659,7 +88636,7 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
assert( pOp->p4type==P4_COLLSEQ || pOp->p4.pColl==0 );
res = sqlite3MemCompare(pIn3, pIn1, pOp->p4.pColl);
}
-compare_op:
+
/* At this point, res is negative, zero, or positive if reg[P1] is
** less than, equal to, or greater than reg[P3], respectively. Compute
** the answer to this operator in res2, depending on what the comparison
@@ -84668,69 +88645,54 @@ compare_op:
** order: NE, EQ, GT, LE, LT, GE */
assert( OP_Eq==OP_Ne+1 ); assert( OP_Gt==OP_Ne+2 ); assert( OP_Le==OP_Ne+3 );
assert( OP_Lt==OP_Ne+4 ); assert( OP_Ge==OP_Ne+5 );
- if( res<0 ){ /* ne, eq, gt, le, lt, ge */
- static const unsigned char aLTb[] = { 1, 0, 0, 1, 1, 0 };
- res2 = aLTb[pOp->opcode - OP_Ne];
+ if( res<0 ){
+ res2 = sqlite3aLTb[pOp->opcode];
}else if( res==0 ){
- static const unsigned char aEQb[] = { 0, 1, 0, 1, 0, 1 };
- res2 = aEQb[pOp->opcode - OP_Ne];
+ res2 = sqlite3aEQb[pOp->opcode];
}else{
- static const unsigned char aGTb[] = { 1, 0, 1, 0, 0, 1 };
- res2 = aGTb[pOp->opcode - OP_Ne];
+ res2 = sqlite3aGTb[pOp->opcode];
}
+ iCompare = res;
/* Undo any changes made by applyAffinity() to the input registers. */
- assert( (pIn1->flags & MEM_Dyn) == (flags1 & MEM_Dyn) );
- pIn1->flags = flags1;
assert( (pIn3->flags & MEM_Dyn) == (flags3 & MEM_Dyn) );
pIn3->flags = flags3;
+ assert( (pIn1->flags & MEM_Dyn) == (flags1 & MEM_Dyn) );
+ pIn1->flags = flags1;
- if( pOp->p5 & SQLITE_STOREP2 ){
- pOut = &aMem[pOp->p2];
- iCompare = res;
- if( (pOp->p5 & SQLITE_KEEPNULL)!=0 ){
- /* The KEEPNULL flag prevents OP_Eq from overwriting a NULL with 1
- ** and prevents OP_Ne from overwriting NULL with 0. This flag
- ** is only used in contexts where either:
- ** (1) op==OP_Eq && (r[P2]==NULL || r[P2]==0)
- ** (2) op==OP_Ne && (r[P2]==NULL || r[P2]==1)
- ** Therefore it is not necessary to check the content of r[P2] for
- ** NULL. */
- assert( pOp->opcode==OP_Ne || pOp->opcode==OP_Eq );
- assert( res2==0 || res2==1 );
- testcase( res2==0 && pOp->opcode==OP_Eq );
- testcase( res2==1 && pOp->opcode==OP_Eq );
- testcase( res2==0 && pOp->opcode==OP_Ne );
- testcase( res2==1 && pOp->opcode==OP_Ne );
- if( (pOp->opcode==OP_Eq)==res2 ) break;
- }
- memAboutToChange(p, pOut);
- MemSetTypeFlag(pOut, MEM_Int);
- pOut->u.i = res2;
- REGISTER_TRACE(pOp->p2, pOut);
- }else{
- VdbeBranchTaken(res!=0, (pOp->p5 & SQLITE_NULLEQ)?2:3);
- if( res2 ){
- goto jump_to_p2;
- }
+ VdbeBranchTaken(res2!=0, (pOp->p5 & SQLITE_NULLEQ)?2:3);
+ if( res2 ){
+ goto jump_to_p2;
}
break;
}
-/* Opcode: ElseNotEq * P2 * * *
+/* Opcode: ElseEq * P2 * * *
**
-** This opcode must immediately follow an OP_Lt or OP_Gt comparison operator.
-** If result of an OP_Eq comparison on the same two operands
-** would have be NULL or false (0), then then jump to P2.
-** If the result of an OP_Eq comparison on the two previous operands
-** would have been true (1), then fall through.
+** This opcode must follow an OP_Lt or OP_Gt comparison operator. There
+** can be zero or more OP_ReleaseReg opcodes intervening, but no other
+** opcodes are allowed to occur between this instruction and the previous
+** OP_Lt or OP_Gt.
+**
+** If result of an OP_Eq comparison on the same two operands as the
+** prior OP_Lt or OP_Gt would have been true, then jump to P2.
+** If the result of an OP_Eq comparison on the two previous
+** operands would have been false or NULL, then fall through.
*/
-case OP_ElseNotEq: { /* same as TK_ESCAPE, jump */
- assert( pOp>aOp );
- assert( pOp[-1].opcode==OP_Lt || pOp[-1].opcode==OP_Gt );
- assert( pOp[-1].p5 & SQLITE_STOREP2 );
- VdbeBranchTaken(iCompare!=0, 2);
- if( iCompare!=0 ) goto jump_to_p2;
+case OP_ElseEq: { /* same as TK_ESCAPE, jump */
+
+#ifdef SQLITE_DEBUG
+ /* Verify the preconditions of this opcode - that it follows an OP_Lt or
+ ** OP_Gt with zero or more intervening OP_ReleaseReg opcodes */
+ int iAddr;
+ for(iAddr = (int)(pOp - aOp) - 1; ALWAYS(iAddr>=0); iAddr--){
+ if( aOp[iAddr].opcode==OP_ReleaseReg ) continue;
+ assert( aOp[iAddr].opcode==OP_Lt || aOp[iAddr].opcode==OP_Gt );
+ break;
+ }
+#endif /* SQLITE_DEBUG */
+ VdbeBranchTaken(iCompare==0, 2);
+ if( iCompare==0 ) goto jump_to_p2;
break;
}
@@ -84741,7 +88703,7 @@ case OP_ElseNotEq: { /* same as TK_ESCAPE, jump */
** instruction. The permutation is stored in the P4 operand.
**
** The permutation is only valid until the next OP_Compare that has
-** the OPFLAG_PERMUTE bit set in P5. Typically the OP_Permutation should
+** the OPFLAG_PERMUTE bit set in P5. Typically the OP_Permutation should
** occur immediately prior to the OP_Compare.
**
** The first integer in the P4 integer array is the length of the array
@@ -84781,10 +88743,10 @@ case OP_Compare: {
int p1;
int p2;
const KeyInfo *pKeyInfo;
- int idx;
+ u32 idx;
CollSeq *pColl; /* Collating sequence to use on this term */
int bRev; /* True for DESCENDING sort order */
- int *aPermute; /* The permutation */
+ u32 *aPermute; /* The permutation */
if( (pOp->p5 & OPFLAG_PERMUTE)==0 ){
aPermute = 0;
@@ -84804,7 +88766,7 @@ case OP_Compare: {
#ifdef SQLITE_DEBUG
if( aPermute ){
int k, mx = 0;
- for(k=0; kmx ) mx = aPermute[k];
+ for(k=0; k(u32)mx ) mx = aPermute[k];
assert( p1>0 && p1+mx<=(p->nMem+1 - p->nCursor)+1 );
assert( p2>0 && p2+mx<=(p->nMem+1 - p->nCursor)+1 );
}else{
@@ -84813,16 +88775,21 @@ case OP_Compare: {
}
#endif /* SQLITE_DEBUG */
for(i=0; inKeyField );
pColl = pKeyInfo->aColl[i];
- bRev = pKeyInfo->aSortOrder[i];
+ bRev = (pKeyInfo->aSortFlags[i] & KEYINFO_ORDER_DESC);
iCompare = sqlite3MemCompare(&aMem[p1+idx], &aMem[p2+idx], pColl);
if( iCompare ){
+ if( (pKeyInfo->aSortFlags[i] & KEYINFO_ORDER_BIGNULL)
+ && ((aMem[p1+idx].flags & MEM_Null) || (aMem[p2+idx].flags & MEM_Null))
+ ){
+ iCompare = -iCompare;
+ }
if( bRev ) iCompare = -iCompare;
break;
}
@@ -84898,13 +88865,13 @@ case OP_Or: { /* same as TK_OR, in1, in2, out3 */
** IS NOT FALSE operators.
**
** Interpret the value in register P1 as a boolean value. Store that
-** boolean (a 0 or 1) in register P2. Or if the value in register P1 is
+** boolean (a 0 or 1) in register P2. Or if the value in register P1 is
** NULL, then the P3 is stored in register P2. Invert the answer if P4
** is 1.
**
** The logic is summarized like this:
**
-**
+**
** - If P3==0 and P4==0 then r[P2] := r[P1] IS TRUE
**
- If P3==1 and P4==1 then r[P2] := r[P1] IS FALSE
**
- If P3==0 and P4==1 then r[P2] := r[P1] IS NOT TRUE
@@ -84924,7 +88891,7 @@ case OP_IsTrue: { /* in1, out2 */
** Synopsis: r[P2]= !r[P1]
**
** 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 */
@@ -85036,10 +89003,28 @@ case OP_IsNull: { /* same as TK_ISNULL, jump, in1 */
break;
}
+/* Opcode: ZeroOrNull P1 P2 P3 * *
+** Synopsis: r[P2] = 0 OR NULL
+**
+** If all both registers P1 and P3 are NOT NULL, then store a zero in
+** register P2. If either registers P1 or P3 are NULL then put
+** a NULL in register P2.
+*/
+case OP_ZeroOrNull: { /* in1, in2, out2, in3 */
+ if( (aMem[pOp->p1].flags & MEM_Null)!=0
+ || (aMem[pOp->p3].flags & MEM_Null)!=0
+ ){
+ sqlite3VdbeMemSetNull(aMem + pOp->p2);
+ }else{
+ sqlite3VdbeMemSetInt64(aMem + pOp->p2, 0);
+ }
+ break;
+}
+
/* Opcode: NotNull P1 P2 * * *
** Synopsis: if r[P1]!=NULL goto 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];
@@ -85104,7 +89089,7 @@ case OP_Offset: { /* out3 */
** 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.
@@ -85113,18 +89098,13 @@ case OP_Offset: { /* out3 */
** if the P4 argument is a P4_MEM use the value of the P4 argument as
** the result.
**
-** If the OPFLAG_CLEARCACHE bit is set on P5 and P1 is a pseudo-table cursor,
-** then the cache of the cursor is reset prior to extracting the column.
-** The first OP_Column against a pseudo-table after the value of the content
-** register has changed should have this bit set.
-**
** If the OPFLAG_LENGTHARG and OPFLAG_TYPEOFARG bits are set on P5 then
** the result is guaranteed to only be used as the argument of a length()
** or typeof() function, respectively. The loading of large blobs can be
** skipped for length() and all content loading can be skipped for typeof().
*/
case OP_Column: {
- int p2; /* column number to retrieve */
+ u32 p2; /* column number to retrieve */
VdbeCursor *pC; /* The VDBE cursor */
BtCursor *pCrsr; /* The BTree cursor */
u32 *aOffset; /* aOffset[i] is offset to start of data for i-th column */
@@ -85139,11 +89119,13 @@ case OP_Column: {
u32 t; /* A type code from the record header */
Mem *pReg; /* PseudoTable input register */
+ assert( pOp->p1>=0 && pOp->p1nCursor );
pC = p->apCsr[pOp->p1];
- p2 = pOp->p2;
+ assert( pC!=0 );
+ p2 = (u32)pOp->p2;
/* If the cursor cache is stale (meaning it is not currently point at
- ** the correct row) then bring it up-to-date by doing the necessary
+ ** the correct row) then bring it up-to-date by doing the necessary
** B-Tree seek. */
rc = sqlite3VdbeCursorMoveto(&pC, &p2);
if( rc ) goto abort_due_to_error;
@@ -85151,9 +89133,8 @@ case OP_Column: {
assert( pOp->p3>0 && pOp->p3<=(p->nMem+1 - p->nCursor) );
pDest = &aMem[pOp->p3];
memAboutToChange(p, pDest);
- assert( pOp->p1>=0 && pOp->p1nCursor );
assert( pC!=0 );
- assert( p2nField );
+ assert( p2<(u32)pC->nField );
aOffset = pC->aOffset;
assert( pC->eCurType!=CURTYPE_VTAB );
assert( pC->eCurType!=CURTYPE_PSEUDO || pC->nullRow );
@@ -85238,19 +89219,19 @@ case OP_Column: {
*/
if( pC->nHdrParsed<=p2 ){
/* If there is more header available for parsing in the record, try
- ** to extract additional fields up through the p2+1-th field
+ ** to extract additional fields up through the p2+1-th field
*/
if( pC->iHdrOffset
| |