| BLOB | TEXT | [CAST] to TEXT, ensure zero terminator
**
** )^
**
@@ -5743,7 +5915,7 @@ SQLITE_API int sqlite3_column_type(sqlite3_stmt*, int iCol);
**
** ^The sqlite3_finalize() function is called to delete a [prepared statement].
** ^If the most recent evaluation of the statement encountered no errors
-** or if the statement is never been evaluated, then sqlite3_finalize() returns
+** or if the statement has never been evaluated, then sqlite3_finalize() returns
** SQLITE_OK. ^If the most recent evaluation of statement S failed, then
** sqlite3_finalize(S) returns the appropriate [error code] or
** [extended error code].
@@ -5778,32 +5950,43 @@ SQLITE_API int sqlite3_finalize(sqlite3_stmt *pStmt);
** ^The [sqlite3_reset(S)] interface resets the [prepared statement] S
** back to the beginning of its program.
**
-** ^If the most recent call to [sqlite3_step(S)] for the
-** [prepared statement] S returned [SQLITE_ROW] or [SQLITE_DONE],
-** or if [sqlite3_step(S)] has never before been called on S,
-** then [sqlite3_reset(S)] returns [SQLITE_OK].
+** ^The return code from [sqlite3_reset(S)] indicates whether or not
+** the previous evaluation of prepared statement S completed successfully.
+** ^If [sqlite3_step(S)] has never before been called on S or if
+** [sqlite3_step(S)] has not been called since the previous call
+** to [sqlite3_reset(S)], then [sqlite3_reset(S)] will return
+** [SQLITE_OK].
**
** ^If the most recent call to [sqlite3_step(S)] for the
** [prepared statement] S indicated an error, then
** [sqlite3_reset(S)] returns an appropriate [error code].
+** ^The [sqlite3_reset(S)] interface might also return an [error code]
+** if there were no prior errors but the process of resetting
+** the prepared statement caused a new error. ^For example, if an
+** [INSERT] statement with a [RETURNING] clause is only stepped one time,
+** that one call to [sqlite3_step(S)] might return SQLITE_ROW but
+** the overall statement might still fail and the [sqlite3_reset(S)] call
+** might return SQLITE_BUSY if locking constraints prevent the
+** database change from committing. Therefore, it is important that
+** applications check the return code from [sqlite3_reset(S)] even if
+** no prior call to [sqlite3_step(S)] indicated a problem.
**
** ^The [sqlite3_reset(S)] interface does not change the values
** of any [sqlite3_bind_blob|bindings] on the [prepared statement] S.
*/
SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt);
+
/*
** CAPI3REF: Create Or Redefine SQL Functions
** KEYWORDS: {function creation routines}
-** KEYWORDS: {application-defined SQL function}
-** KEYWORDS: {application-defined SQL functions}
** METHOD: sqlite3
**
** ^These functions (collectively known as "function creation routines")
** are used to add SQL functions or aggregates or to redefine the behavior
** of existing SQL functions or aggregates. The only differences between
-** the three "sqlite3_create_function*" routines are the text encoding
-** expected for the second parameter (the name of the function being
+** the three "sqlite3_create_function*" routines are the text encoding
+** expected for the second parameter (the name of the function being
** created) and the presence or absence of a destructor callback for
** the application data pointer. Function sqlite3_create_window_function()
** is similar, but allows the user to supply the extra callback functions
@@ -5817,7 +6000,7 @@ SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt);
** ^The second parameter is the name of the SQL function to be created or
** redefined. ^The length of the name is limited to 255 bytes in a UTF-8
** representation, exclusive of the zero-terminator. ^Note that the name
-** length limit is in UTF-8 bytes, not characters nor UTF-16 bytes.
+** length limit is in UTF-8 bytes, not characters nor UTF-16 bytes.
** ^Any attempt to create a function with a longer name
** will result in [SQLITE_MISUSE] being returned.
**
@@ -5832,7 +6015,7 @@ SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt);
** ^The fourth parameter, eTextRep, specifies what
** [SQLITE_UTF8 | text encoding] this SQL function prefers for
** its parameters. The application should set this parameter to
-** [SQLITE_UTF16LE] if the function implementation invokes
+** [SQLITE_UTF16LE] if the function implementation invokes
** [sqlite3_value_text16le()] on an input, or [SQLITE_UTF16BE] if the
** implementation invokes [sqlite3_value_text16be()] on an input, or
** [SQLITE_UTF16] if [sqlite3_value_text16()] is used, or [SQLITE_UTF8]
@@ -5850,6 +6033,21 @@ SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt);
** perform additional optimizations on deterministic functions, so use
** of the [SQLITE_DETERMINISTIC] flag is recommended where possible.
**
+** ^The fourth parameter may also optionally include the [SQLITE_DIRECTONLY]
+** flag, which if present prevents the function from being invoked from
+** within VIEWs, TRIGGERs, CHECK constraints, generated column expressions,
+** index expressions, or the WHERE clause of partial indexes.
+**
+** For best security, the [SQLITE_DIRECTONLY] flag is recommended for
+** all application-defined SQL functions that do not need to be
+** used inside of triggers, views, CHECK constraints, or other elements of
+** the database schema. This flag is especially recommended for SQL
+** functions that have side effects or reveal internal application state.
+** Without this flag, an attacker might be able to modify the schema of
+** a database file to include invocations of the function with parameters
+** chosen by the attacker, which the application will then execute when
+** the database file is opened and read.
+**
** ^(The fifth parameter is an arbitrary pointer. The implementation of the
** function can gain access to this pointer using [sqlite3_user_data()].)^
**
@@ -5863,21 +6061,21 @@ SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt);
** SQL function or aggregate, pass NULL pointers for all three function
** callbacks.
**
-** ^The sixth, seventh, eighth and ninth parameters (xStep, xFinal, xValue
+** ^The sixth, seventh, eighth and ninth parameters (xStep, xFinal, xValue
** and xInverse) passed to sqlite3_create_window_function are pointers to
** C-language callbacks that implement the new function. xStep and xFinal
** must both be non-NULL. xValue and xInverse may either both be NULL, in
-** which case a regular aggregate function is created, or must both be
+** which case a regular aggregate function is created, or must both be
** non-NULL, in which case the new function may be used as either an aggregate
** or aggregate window function. More details regarding the implementation
-** of aggregate window functions are
+** of aggregate window functions are
** [user-defined window functions|available here].
**
** ^(If the final parameter to sqlite3_create_function_v2() or
-** sqlite3_create_window_function() is not NULL, then it is destructor for
-** the application data pointer. The destructor is invoked when the function
-** is deleted, either by being overloaded or when the database connection
-** closes.)^ ^The destructor is also invoked if the call to
+** sqlite3_create_window_function() is not NULL, then it is the destructor for
+** the application data pointer. The destructor is invoked when the function
+** is deleted, either by being overloaded or when the database connection
+** closes.)^ ^The destructor is also invoked if the call to
** sqlite3_create_function_v2() fails. ^When the destructor callback is
** invoked, it is passed a single argument which is a copy of the application
** data pointer which was the fifth parameter to sqlite3_create_function_v2().
@@ -5890,7 +6088,7 @@ SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt);
** nArg parameter is a better match than a function implementation with
** a negative nArg. ^A function where the preferred text encoding
** matches the database encoding is a better
-** match than a function where the encoding is different.
+** match than a function where the encoding is different.
** ^A function where the encoding difference is between UTF16le and UTF16be
** is a closer match than a function where the encoding difference is
** between UTF8 and UTF16.
@@ -5949,8 +6147,54 @@ SQLITE_API int sqlite3_create_window_function(
/*
** CAPI3REF: Text Encodings
**
-** These constant define integer codes that represent the various
+** These constants define integer codes that represent the various
** text encodings supported by SQLite.
+**
+**
+** [[SQLITE_UTF8]] - SQLITE_UTF8
- Text is encoding as UTF-8
+**
+** [[SQLITE_UTF16LE]] - SQLITE_UTF16LE
- Text is encoding as UTF-16
+** with each code point being expressed "little endian" - the least significant
+** byte first. This is the usual encoding, for example on Windows.
+**
+** [[SQLITE_UTF16BE]] - SQLITE_UTF16BE
- Text is encoding as UTF-16
+** with each code point being expressed "big endian" - the most significant
+** byte first. This encoding is less common, but is still sometimes seen,
+** specially on older systems.
+**
+** [[SQLITE_UTF16]]
- SQLITE_UTF16
- Text is encoding as UTF-16
+** with each code point being expressed either little endian or as big
+** endian, according to the native endianness of the host computer.
+**
+** [[SQLITE_ANY]]
- SQLITE_ANY
- This encoding value may only be used
+** to declare the preferred text for [application-defined SQL functions]
+** created using [sqlite3_create_function()] and similar. If the preferred
+** encoding (the 4th parameter to sqlite3_create_function() - the eTextRep
+** parameter) is SQLITE_ANY, that indicates that the function does not have
+** a preference regarding the text encoding of its parameters and can take
+** any text encoding that the SQLite core find convenient to supply. This
+** option is deprecated. Please do not use it in new applications.
+**
+** [[SQLITE_UTF16_ALIGNED]]
- SQLITE_UTF16_ALIGNED
- This encoding
+** value may be used as the 3rd parameter (the eTextRep parameter) to
+** [sqlite3_create_collation()] and similar. This encoding value means
+** that the application-defined collating sequence created expects its
+** input strings to be in UTF16 in native byte order, and that the start
+** of the strings must be aligned to a 2-byte boundary.
+**
+** [[SQLITE_UTF8_ZT]]
- SQLITE_UTF8_ZT
- This option can only be
+** used to specify the text encoding to strings input to
+** [sqlite3_result_text64()] and [sqlite3_bind_text64()].
+** The SQLITE_UTF8_ZT encoding means that the input string (call it "z")
+** is UTF-8 encoded and that it is zero-terminated. If the length parameter
+** (call it "n") is non-negative, this encoding option means that the caller
+** guarantees that z array contains at least n+1 bytes and that the z[n]
+** byte has a value of zero.
+** This option gives the same output as SQLITE_UTF8, but can be more efficient
+** by avoiding the need to make a copy of the input string, in some cases.
+** However, if z is allocated to hold fewer than n+1 bytes or if the
+** z[n] byte is not zero, undefined behavior may result.
+**
*/
#define SQLITE_UTF8 1 /* IMP: R-37514-35566 */
#define SQLITE_UTF16LE 2 /* IMP: R-03371-37637 */
@@ -5958,23 +6202,120 @@ SQLITE_API int sqlite3_create_window_function(
#define SQLITE_UTF16 4 /* Use native byte order */
#define SQLITE_ANY 5 /* Deprecated */
#define SQLITE_UTF16_ALIGNED 8 /* sqlite3_create_collation only */
+#define SQLITE_UTF8_ZT 16 /* Zero-terminated UTF8 */
/*
** CAPI3REF: Function Flags
**
-** These constants may be ORed together with the
+** These constants may be ORed together with the
** [SQLITE_UTF8 | preferred text encoding] as the fourth argument
** to [sqlite3_create_function()], [sqlite3_create_function16()], or
** [sqlite3_create_function_v2()].
+**
+**
+** [[SQLITE_DETERMINISTIC]] - SQLITE_DETERMINISTIC
-
+** The SQLITE_DETERMINISTIC flag means that the new function always gives
+** the same output when the input parameters are the same.
+** The [abs|abs() function] is deterministic, for example, but
+** [randomblob|randomblob()] is not. Functions must
+** be deterministic in order to be used in certain contexts such as
+** with the WHERE clause of [partial indexes] or in [generated columns].
+** SQLite might also optimize deterministic functions by factoring them
+** out of inner loops.
+**
+**
+** [[SQLITE_DIRECTONLY]] - SQLITE_DIRECTONLY
-
+** The SQLITE_DIRECTONLY flag means that the function may only be invoked
+** from top-level SQL, and cannot be used in VIEWs or TRIGGERs nor in
+** schema structures such as [CHECK constraints], [DEFAULT clauses],
+** [expression indexes], [partial indexes], or [generated columns].
+**
+** The SQLITE_DIRECTONLY flag is recommended for any
+** [application-defined SQL function]
+** that has side-effects or that could potentially leak sensitive information.
+** This will prevent attacks in which an application is tricked
+** into using a database file that has had its schema surreptitiously
+** modified to invoke the application-defined function in ways that are
+** harmful.
+**
+** Some people say it is good practice to set SQLITE_DIRECTONLY on all
+** [application-defined SQL functions], regardless of whether or not they
+** are security sensitive, as doing so prevents those functions from being used
+** inside of the database schema, and thus ensures that the database
+** can be inspected and modified using generic tools (such as the [CLI])
+** that do not have access to the application-defined functions.
+**
+**
+** [[SQLITE_INNOCUOUS]] - SQLITE_INNOCUOUS
-
+** The SQLITE_INNOCUOUS flag means that the function is unlikely
+** to cause problems even if misused. An innocuous function should have
+** no side effects and should not depend on any values other than its
+** input parameters. The [abs|abs() function] is an example of an
+** innocuous function.
+** The [load_extension() SQL function] is not innocuous because of its
+** side effects.
+**
SQLITE_INNOCUOUS is similar to SQLITE_DETERMINISTIC, but is not
+** exactly the same. The [random|random() function] is an example of a
+** function that is innocuous but not deterministic.
+** Some heightened security settings
+** ([SQLITE_DBCONFIG_TRUSTED_SCHEMA] and [PRAGMA trusted_schema=OFF])
+** disable the use of SQL functions inside views and triggers and in
+** schema structures such as [CHECK constraints], [DEFAULT clauses],
+** [expression indexes], [partial indexes], and [generated columns] unless
+** the function is tagged with SQLITE_INNOCUOUS. Most built-in functions
+** are innocuous. Developers are advised to avoid using the
+** SQLITE_INNOCUOUS flag for application-defined functions unless the
+** function has been carefully audited and found to be free of potentially
+** security-adverse side-effects and information-leaks.
+**
+**
+** [[SQLITE_SUBTYPE]] - SQLITE_SUBTYPE
-
+** The SQLITE_SUBTYPE flag indicates to SQLite that a function might call
+** [sqlite3_value_subtype()] to inspect the sub-types of its arguments.
+** This flag instructs SQLite to omit some corner-case optimizations that
+** might disrupt the operation of the [sqlite3_value_subtype()] function,
+** causing it to return zero rather than the correct subtype().
+** All SQL functions that invoke [sqlite3_value_subtype()] should have this
+** property. If the SQLITE_SUBTYPE property is omitted, then the return
+** value from [sqlite3_value_subtype()] might sometimes be zero even though
+** a non-zero subtype was specified by the function argument expression.
+**
+** [[SQLITE_RESULT_SUBTYPE]]
- SQLITE_RESULT_SUBTYPE
-
+** The SQLITE_RESULT_SUBTYPE flag indicates to SQLite that a function might call
+** [sqlite3_result_subtype()] to cause a sub-type to be associated with its
+** result.
+** Every function that invokes [sqlite3_result_subtype()] should have this
+** property. If it does not, then the call to [sqlite3_result_subtype()]
+** might become a no-op if the function is used as a term in an
+** [expression index]. On the other hand, SQL functions that never invoke
+** [sqlite3_result_subtype()] should avoid setting this property, as the
+** purpose of this property is to disable certain optimizations that are
+** incompatible with subtypes.
+**
+** [[SQLITE_SELFORDER1]]
- SQLITE_SELFORDER1
-
+** The SQLITE_SELFORDER1 flag indicates that the function is an aggregate
+** that internally orders the values provided to the first argument. The
+** ordered-set aggregate SQL notation with a single ORDER BY term can be
+** used to invoke this function. If the ordered-set aggregate notation is
+** used on a function that lacks this flag, then an error is raised. Note
+** that the ordered-set aggregate syntax is only available if SQLite is
+** built using the -DSQLITE_ENABLE_ORDERED_SET_AGGREGATES compile-time option.
+**
+**
*/
-#define SQLITE_DETERMINISTIC 0x800
+#define SQLITE_DETERMINISTIC 0x000000800
+#define SQLITE_DIRECTONLY 0x000080000
+#define SQLITE_SUBTYPE 0x000100000
+#define SQLITE_INNOCUOUS 0x000200000
+#define SQLITE_RESULT_SUBTYPE 0x001000000
+#define SQLITE_SELFORDER1 0x002000000
/*
** CAPI3REF: Deprecated Functions
** DEPRECATED
**
** These functions are [deprecated]. In order to maintain
-** backwards compatibility with older code, these functions continue
+** backwards compatibility with older code, these functions continue
** to be supported. However, new applications should avoid
** the use of these functions. To encourage programmers to avoid
** these functions, we will not explain what they do.
@@ -6026,8 +6367,8 @@ SQLITE_API SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int6
**
** 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]
@@ -6042,11 +6383,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
@@ -6072,7 +6413,7 @@ SQLITE_API SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int6
** sqlite3_value_nochange(X) interface returns true if and only if
** the column corresponding to X is unchanged by the UPDATE operation
** that the xUpdate method call was invoked to implement and if
-** and the prior [xColumn] method call that was invoked to extracted
+** the prior [xColumn] method call that was invoked to extract
** the value for that column returned without setting a result (probably
** because it queried [sqlite3_vtab_nochange()] and found that the column
** was unchanging). ^Within an [xUpdate] method, any value for which
@@ -6084,7 +6425,7 @@ SQLITE_API SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int6
** ^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,
-** and expression, then sqlite3_value_frombind(X) returns zero.
+** 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
@@ -6096,26 +6437,22 @@ SQLITE_API SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int6
** the SQL function that supplied the [sqlite3_value*] parameters.
**
** As long as the input parameter is correct, these routines can only
-** fail if an out-of-memory error occurs during a format conversion.
-** Only the following subset of interfaces are subject to out-of-memory
-** errors:
-**
-**
-** - sqlite3_value_blob()
-**
- sqlite3_value_text()
-**
- sqlite3_value_text16()
-**
- sqlite3_value_text16le()
-**
- sqlite3_value_text16be()
-**
- sqlite3_value_bytes()
-**
- sqlite3_value_bytes16()
-**
-**
+** fail if an out-of-memory error occurs while trying to do a
+** UTF8→UTF16 or UTF16→UTF8 conversion.
** If an out-of-memory error occurs, then the return value from these
** routines is the same as if the column had contained an SQL NULL value.
-** Valid SQL NULL returns can be distinguished from out-of-memory errors
-** by invoking the [sqlite3_errcode()] immediately after the suspect
+** If the input sqlite3_value was not obtained from [sqlite3_value_dup()],
+** then valid SQL NULL returns can also be distinguished from
+** out-of-memory errors after extracting the value
+** by invoking the [sqlite3_errcode()] immediately after the suspicious
** return value is obtained and before any
** other SQLite interface is called on the same [database connection].
+** If the input sqlite3_value was obtained from sqlite3_value_dup() then
+** it is disconnected from the database connection and so sqlite3_errcode()
+** will not work.
+** In that case, the only way to distinguish an out-of-memory
+** condition from a true SQL NULL is to invoke sqlite3_value_type() on the
+** input to see if it is NULL prior to trying to extract the value.
*/
SQLITE_API const void *sqlite3_value_blob(sqlite3_value*);
SQLITE_API double sqlite3_value_double(sqlite3_value*);
@@ -6133,6 +6470,29 @@ 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: Report the internal text encoding state of an sqlite3_value object
+** METHOD: sqlite3_value
+**
+** ^(The sqlite3_value_encoding(X) interface returns one of [SQLITE_UTF8],
+** [SQLITE_UTF16BE], or [SQLITE_UTF16LE] according to the current text encoding
+** of the value X, assuming that X has type TEXT.)^ If sqlite3_value_type(X)
+** returns something other than SQLITE_TEXT, then the return value from
+** sqlite3_value_encoding(X) is meaningless. ^Calls to
+** [sqlite3_value_text(X)], [sqlite3_value_text16(X)],
+** [sqlite3_value_text16be(X)],
+** [sqlite3_value_text16le(X)], [sqlite3_value_bytes(X)], or
+** [sqlite3_value_bytes16(X)] might change the encoding of the value X and
+** thus change the return from subsequent calls to sqlite3_value_encoding(X).
+**
+** This routine is intended for used by applications that test and validate
+** the SQLite implementation. This routine is inquiring about the opaque
+** internal state of an [sqlite3_value] object. Ordinary applications should
+** not need to know what the internal state of an sqlite3_value object is and
+** hence should not need to use this interface.
+*/
+SQLITE_API int sqlite3_value_encoding(sqlite3_value*);
+
/*
** CAPI3REF: Finding The Subtype Of SQL Values
** METHOD: sqlite3_value
@@ -6142,6 +6502,12 @@ SQLITE_API int sqlite3_value_frombind(sqlite3_value*);
** information can be used to pass a limited amount of context from
** one SQL function to another. Use the [sqlite3_result_subtype()]
** routine to set the subtype for the return value of an SQL function.
+**
+** Every [application-defined SQL function] that invokes this interface
+** should include the [SQLITE_SUBTYPE] property in the text
+** encoding argument when the function is [sqlite3_create_function|registered].
+** If the [SQLITE_SUBTYPE] property is omitted, then sqlite3_value_subtype()
+** might return zero instead of the upstream subtype in some corner cases.
*/
SQLITE_API unsigned int sqlite3_value_subtype(sqlite3_value*);
@@ -6150,10 +6516,11 @@ SQLITE_API unsigned int sqlite3_value_subtype(sqlite3_value*);
** METHOD: sqlite3_value
**
** ^The sqlite3_value_dup(V) interface makes a copy of the [sqlite3_value]
-** object D and returns a pointer to that copy. ^The [sqlite3_value] returned
+** object V and returns a pointer to that copy. ^The [sqlite3_value] returned
** is a [protected sqlite3_value] object even if the input is not.
** ^The sqlite3_value_dup(V) interface returns NULL if V is NULL or if a
-** memory allocation fails.
+** memory allocation fails. ^If V is a [pointer value], then the result
+** of sqlite3_value_dup(V) is a NULL value.
**
** ^The sqlite3_value_free(V) interface frees an [sqlite3_value] object
** previously obtained from [sqlite3_value_dup()]. ^If V is a NULL pointer
@@ -6169,9 +6536,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
@@ -6182,19 +6549,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.
+** allocation 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
+** determined by the N parameter on the first successful call. Changing the
+** 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
@@ -6239,48 +6606,56 @@ SQLITE_API sqlite3 *sqlite3_context_db_handle(sqlite3_context*);
** METHOD: sqlite3_context
**
** These functions may be used by (non-aggregate) SQL functions to
-** associate metadata with argument values. If the same value is passed to
-** multiple invocations of the same SQL function during query execution, under
-** some circumstances the associated metadata may be preserved. An example
-** of where this might be useful is in a regular-expression matching
-** function. The compiled version of the regular expression can be stored as
-** metadata associated with the pattern string.
-** Then as long as the pattern string remains the same,
+** associate auxiliary data with argument values. If the same argument
+** value is passed to multiple invocations of the same SQL function during
+** query execution, under some circumstances the associated auxiliary data
+** might 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 auxiliary data associated with the pattern
+** string. Then as long as the pattern string remains the same,
** the compiled regular expression can be reused on multiple
** invocations of the same function.
**
-** ^The sqlite3_get_auxdata(C,N) interface returns a pointer to the metadata
-** associated by the sqlite3_set_auxdata(C,N,P,X) function with the Nth argument
-** value to the application-defined function. ^N is zero for the left-most
-** function argument. ^If there is no metadata
-** associated with the function argument, the sqlite3_get_auxdata(C,N) interface
-** returns a NULL pointer.
+** ^The sqlite3_get_auxdata(C,N) interface returns a pointer to the auxiliary
+** data associated by the sqlite3_set_auxdata(C,N,P,X) function with the
+** Nth argument value to the application-defined function. ^N is zero
+** for the left-most function argument. ^If there is no auxiliary data
+** associated with the function argument, the sqlite3_get_auxdata(C,N)
+** interface returns a NULL pointer.
**
-** ^The sqlite3_set_auxdata(C,N,P,X) interface saves P as metadata for the N-th
-** argument of the application-defined function. ^Subsequent
+** ^The sqlite3_set_auxdata(C,N,P,X) interface saves P as auxiliary data for the
+** N-th argument of the application-defined function. ^Subsequent
** calls to sqlite3_get_auxdata(C,N) return P from the most recent
-** sqlite3_set_auxdata(C,N,P,X) call if the metadata is still valid or
-** NULL if the metadata has been discarded.
+** sqlite3_set_auxdata(C,N,P,X) call if the auxiliary data is still valid or
+** NULL if the auxiliary data has been discarded.
** ^After each call to sqlite3_set_auxdata(C,N,P,X) where X is not NULL,
** SQLite will invoke the destructor function X with parameter P exactly
-** once, when the metadata is discarded.
-** SQLite is free to discard the metadata at any time, including:
+** once, when the auxiliary data is discarded.
+** SQLite is free to discard the auxiliary data at any time, including:
** - ^(when the corresponding function parameter changes)^, or
**
- ^(when [sqlite3_reset()] or [sqlite3_finalize()] is called for the
** 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
-** allocation error occurs.)^
+** - ^(during the original sqlite3_set_auxdata() call when a memory
+** allocation error occurs.)^
+**
- ^(during the original sqlite3_set_auxdata() call if the function
+** is evaluated during query planning instead of during query execution,
+** as sometimes happens with [SQLITE_ENABLE_STAT4].)^
**
-** Note the last bullet in particular. The destructor X in
+** Note the last two bullets in particular. The destructor X in
** sqlite3_set_auxdata(C,N,P,X) might be called immediately, before the
** sqlite3_set_auxdata() interface even returns. Hence sqlite3_set_auxdata()
** should be called near the end of the function implementation and the
** function implementation should not make any use of P after
-** sqlite3_set_auxdata() has been called.
-**
-** ^(In practice, metadata is preserved between function calls for
+** sqlite3_set_auxdata() has been called. Furthermore, a call to
+** sqlite3_get_auxdata() that occurs immediately after a corresponding call
+** to sqlite3_set_auxdata() might still return NULL if an out-of-memory
+** condition occurred during the sqlite3_set_auxdata() call or if the
+** function is being evaluated during query planning rather than during
+** query execution.
+**
+** ^(In practice, auxiliary data is preserved between function calls for
** function parameters that are compile-time constants, including literal
** values and [parameters] and expressions composed from the same.)^
**
@@ -6290,10 +6665,72 @@ SQLITE_API sqlite3 *sqlite3_context_db_handle(sqlite3_context*);
**
** These routines must be called from the same thread in which
** the SQL function is running.
+**
+** See also: [sqlite3_get_clientdata()] and [sqlite3_set_clientdata()].
*/
SQLITE_API void *sqlite3_get_auxdata(sqlite3_context*, int N);
SQLITE_API void sqlite3_set_auxdata(sqlite3_context*, int N, void*, void (*)(void*));
+/*
+** CAPI3REF: Database Connection Client Data
+** METHOD: sqlite3
+**
+** These functions are used to associate one or more named pointers
+** with a [database connection].
+** A call to sqlite3_set_clientdata(D,N,P,X) causes the pointer P
+** to be attached to [database connection] D using name N. Subsequent
+** calls to sqlite3_get_clientdata(D,N) will return a copy of pointer P
+** or a NULL pointer if there were no prior calls to
+** sqlite3_set_clientdata() with the same values of D and N.
+** Names are compared using strcmp() and are thus case sensitive.
+** It returns 0 on success and SQLITE_NOMEM on allocation failure.
+**
+** If P and X are both non-NULL, then the destructor X is invoked with
+** argument P on the first of the following occurrences:
+**
+** - An out-of-memory error occurs during the call to
+** sqlite3_set_clientdata() which attempts to register pointer P.
+**
- A subsequent call to sqlite3_set_clientdata(D,N,P,X) is made
+** with the same D and N parameters.
+**
- The database connection closes. SQLite does not make any guarantees
+** about the order in which destructors are called, only that all
+** destructors will be called exactly once at some point during the
+** database connection closing process.
+**
+**
+** SQLite does not do anything with client data other than invoke
+** destructors on the client data at the appropriate time. The intended
+** use for client data is to provide a mechanism for wrapper libraries
+** to store additional information about an SQLite database connection.
+**
+** There is no limit (other than available memory) on the number of different
+** client data pointers (with different names) that can be attached to a
+** single database connection. However, the current implementation stores
+** the content on a linked list. Insert and retrieval performance will
+** be proportional to the number of entries. The design use case, and
+** the use case for which the implementation is optimized, is
+** that an application will store only small number of client data names,
+** typically just one or two. This interface is not intended to be a
+** generalized key/value store for thousands or millions of keys. It
+** will work for that, but performance might be disappointing.
+**
+** There is no way to enumerate the client data pointers
+** associated with a database connection. The N parameter can be thought
+** of as a secret key such that only code that knows the secret key is able
+** to access the associated data.
+**
+** Security Warning: These interfaces should not be exposed in scripting
+** languages or in other circumstances where it might be possible for an
+** attacker to invoke them. Any agent that can invoke these interfaces
+** can probably also take control of the process.
+**
+** Database connection client data is only available for SQLite
+** version 3.44.0 ([dateof:3.44.0]) and later.
+**
+** See also: [sqlite3_set_auxdata()] and [sqlite3_get_auxdata()].
+*/
+SQLITE_API void *sqlite3_get_clientdata(sqlite3*,const char*);
+SQLITE_API int sqlite3_set_clientdata(sqlite3*, const char*, void*, void(*)(void*));
/*
** CAPI3REF: Constants Defining Special Destructor Behavior
@@ -6345,8 +6782,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
@@ -6382,21 +6820,26 @@ typedef void (*sqlite3_destructor_type)(void*);
** set the return value of the application-defined function to be
** a text string which is represented as UTF-8, UTF-16 native byte order,
** UTF-16 little endian, or UTF-16 big endian, respectively.
-** ^The sqlite3_result_text64() interface sets the return value of an
+** ^The sqlite3_result_text64(C,Z,N,D,E) interface sets the return value of an
** application-defined function to be a text string in an encoding
-** specified by the fifth (and last) parameter, which must be one
-** of [SQLITE_UTF8], [SQLITE_UTF16], [SQLITE_UTF16BE], or [SQLITE_UTF16LE].
+** specified the E parameter, which must be one
+** of [SQLITE_UTF8], [SQLITE_UTF8_ZT], [SQLITE_UTF16], [SQLITE_UTF16BE],
+** or [SQLITE_UTF16LE]. ^The special value [SQLITE_UTF8_ZT] means that
+** the result text is both UTF-8 and zero-terminated. In other words,
+** SQLITE_UTF8_ZT means that the Z array holds at least N+1 bytes and that
+** the Z[N] is zero.
** ^SQLite takes the text result from the application from
** the 2nd parameter of the sqlite3_result_text* interfaces.
-** ^If the 3rd parameter to the sqlite3_result_text* interfaces
-** is negative, then SQLite takes result text from the 2nd parameter
-** through the first zero character.
+** ^If the 3rd parameter to any of the sqlite3_result_text* interfaces
+** other than sqlite3_result_text64() is negative, then SQLite computes
+** the string length itself by searching the 2nd parameter for the first
+** zero character.
** ^If the 3rd parameter to the sqlite3_result_text* interfaces
** is non-negative, then as many bytes (not characters) of the text
** pointed to by the 2nd parameter are taken as the application-defined
** function result. If the 3rd parameter is non-negative, then it
** must be the byte offset into the string where the NUL terminator would
-** appear if the string where NUL terminated. If any NUL characters occur
+** appear if the string were NUL terminated. If any NUL characters occur
** in the string at a byte offset that is less than the value of the 3rd
** parameter, then the resulting string will contain embedded NULs and the
** result of expressions operating on strings with embedded NULs is undefined.
@@ -6414,6 +6857,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
@@ -6426,7 +6888,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
@@ -6435,7 +6897,7 @@ typedef void (*sqlite3_destructor_type)(void*);
** string and preferably a string literal. The sqlite3_result_pointer()
** routine is part of the [pointer passing interface] added for SQLite 3.20.0.
**
-** If these routines are called from within the different thread
+** If these routines are called from within a different thread
** than the one containing the application-defined function that received
** the [sqlite3_context] pointer, the results are undefined.
*/
@@ -6452,7 +6914,7 @@ SQLITE_API void sqlite3_result_int(sqlite3_context*, int);
SQLITE_API void sqlite3_result_int64(sqlite3_context*, sqlite3_int64);
SQLITE_API void sqlite3_result_null(sqlite3_context*);
SQLITE_API void sqlite3_result_text(sqlite3_context*, const char*, int, void(*)(void*));
-SQLITE_API void sqlite3_result_text64(sqlite3_context*, const char*,sqlite3_uint64,
+SQLITE_API void sqlite3_result_text64(sqlite3_context*, const char *z, sqlite3_uint64 n,
void(*)(void*), unsigned char encoding);
SQLITE_API void sqlite3_result_text16(sqlite3_context*, const void*, int, void(*)(void*));
SQLITE_API void sqlite3_result_text16le(sqlite3_context*, const void*, int,void(*)(void*));
@@ -6468,12 +6930,26 @@ 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
** in future releases of SQLite.
+**
+** Every [application-defined SQL function] that invokes this interface
+** should include the [SQLITE_RESULT_SUBTYPE] property in its
+** text encoding argument when the SQL function is
+** [sqlite3_create_function|registered]. If the [SQLITE_RESULT_SUBTYPE]
+** property is omitted from the function that invokes sqlite3_result_subtype(),
+** then in some cases the sqlite3_result_subtype() might fail to set
+** the result subtype.
+**
+** If SQLite is compiled with -DSQLITE_STRICT_SUBTYPE=1, then any
+** SQL function that invokes the sqlite3_result_subtype() interface
+** and that does not have the SQLITE_RESULT_SUBTYPE property will raise
+** an error. Future versions of SQLite might enable -DSQLITE_STRICT_SUBTYPE=1
+** by default.
*/
SQLITE_API void sqlite3_result_subtype(sqlite3_context*,unsigned int);
@@ -6499,7 +6975,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
@@ -6508,18 +6984,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
@@ -6536,7 +7013,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()
@@ -6546,36 +7023,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*)
);
@@ -6608,64 +7085,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(
@@ -6689,6 +7121,13 @@ SQLITE_API void sqlite3_activate_cerod(
** of the default VFS is not implemented correctly, or not implemented at
** all, then the behavior of sqlite3_sleep() may deviate from the description
** in the previous paragraphs.
+**
+** If a negative argument is passed to sqlite3_sleep() the results vary by
+** VFS and operating system. Some system treat a negative argument as an
+** instruction to sleep forever. Others understand it to mean do not sleep
+** at all. ^In SQLite version 3.42.0 and later, a negative
+** argument passed into sqlite3_sleep() is changed to zero before it is relayed
+** down into the xSleep method of the VFS.
*/
SQLITE_API int sqlite3_sleep(int);
@@ -6721,7 +7160,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
@@ -6778,7 +7217,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
@@ -6859,22 +7298,59 @@ SQLITE_API int sqlite3_get_autocommit(sqlite3*);
*/
SQLITE_API sqlite3 *sqlite3_db_handle(sqlite3_stmt*);
+/*
+** CAPI3REF: Return The Schema Name For A Database Connection
+** METHOD: sqlite3
+**
+** ^The sqlite3_db_name(D,N) interface returns a pointer to the schema name
+** for the N-th database on database connection D, or a NULL pointer if N is
+** out of range. An N value of 0 means the main database file. An N of 1 is
+** the "temp" schema. Larger values of N correspond to various ATTACH-ed
+** databases.
+**
+** Space to hold the string that is returned by sqlite3_db_name() is managed
+** by SQLite itself. The string might be deallocated by any operation that
+** changes the schema, including [ATTACH] or [DETACH] or calls to
+** [sqlite3_serialize()] or [sqlite3_deserialize()], even operations that
+** occur on a different thread. Applications that need to
+** remember the string long-term should make their own copy. Applications that
+** are accessing the same database connection simultaneously on multiple
+** threads should mutex-protect calls to this API and should make their own
+** private copy of the result prior to releasing the mutex.
+*/
+SQLITE_API const char *sqlite3_db_name(sqlite3 *db, int N);
+
/*
** 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
** 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);
+SQLITE_API sqlite3_filename sqlite3_db_filename(sqlite3 *db, const char *zDbName);
/*
** CAPI3REF: Determine if a database is read-only
@@ -6886,6 +7362,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 be 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
+** 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
@@ -6952,6 +7479,72 @@ SQLITE_API sqlite3_stmt *sqlite3_next_stmt(sqlite3 *pDb, sqlite3_stmt *pStmt);
SQLITE_API void *sqlite3_commit_hook(sqlite3*, int(*)(void*), void*);
SQLITE_API void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*);
+/*
+** CAPI3REF: Autovacuum Compaction Amount Callback
+** METHOD: sqlite3
+**
+** ^The sqlite3_autovacuum_pages(D,C,P,X) interface registers a callback
+** function C that is invoked prior to each autovacuum of the database
+** file. ^The callback is passed a copy of the generic data pointer (P),
+** the schema-name of the attached database that is being autovacuumed,
+** the size of the database file in pages, the number of free pages,
+** and the number of bytes per page, respectively. The callback should
+** return the number of free pages that should be removed by the
+** autovacuum. ^If the callback returns zero, then no autovacuum happens.
+** ^If the value returned is greater than or equal to the number of
+** free pages, then a complete autovacuum happens.
+**
+** ^If there are multiple ATTACH-ed database files that are being
+** modified as part of a transaction commit, then the autovacuum pages
+** callback is invoked separately for each file.
+**
+** The callback is not reentrant. The callback function should
+** not attempt to invoke any other SQLite interface. If it does, bad
+** things may happen, including segmentation faults and corrupt database
+** files. The callback function should be a simple function that
+** does some arithmetic on its input parameters and returns a result.
+**
+** ^The X parameter to sqlite3_autovacuum_pages(D,C,P,X) is an optional
+** destructor for the P parameter. ^If X is not NULL, then X(P) is
+** invoked whenever the database connection closes or when the callback
+** is overwritten by another invocation of sqlite3_autovacuum_pages().
+**
+** ^There is only one autovacuum pages callback per database connection.
+** ^Each call to the sqlite3_autovacuum_pages() interface overrides all
+** previous invocations for that database connection. ^If the callback
+** argument (C) to sqlite3_autovacuum_pages(D,C,P,X) is a NULL pointer,
+** then the autovacuum steps callback is canceled. The return value
+** from sqlite3_autovacuum_pages() is normally SQLITE_OK, but might
+** be some other error code if something goes wrong. The current
+** implementation will only return SQLITE_OK or SQLITE_MISUSE, but other
+** return codes might be added in future releases.
+**
+** If no autovacuum pages callback is specified (the usual case) or
+** a NULL pointer is provided for the callback,
+** then the default behavior is to vacuum all free pages. So, in other
+** words, the default behavior is the same as if the callback function
+** were something like this:
+**
+**
+** unsigned int demonstration_autovac_pages_callback(
+** void *pClientData,
+** const char *zSchema,
+** unsigned int nDbPage,
+** unsigned int nFreePage,
+** unsigned int nBytePerPage
+** ){
+** return nFreePage;
+** }
+**
+*/
+SQLITE_API int sqlite3_autovacuum_pages(
+ sqlite3 *db,
+ unsigned int(*)(void*,const char*,unsigned int,unsigned int,unsigned int),
+ void*,
+ void(*)(void*)
+);
+
+
/*
** CAPI3REF: Data Change Notification Callbacks
** METHOD: sqlite3
@@ -6965,6 +7558,8 @@ SQLITE_API void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*);
**
** ^The second argument is a pointer to the function to invoke when a
** row is updated, inserted or deleted in a rowid table.
+** ^The update hook is disabled by invoking sqlite3_update_hook()
+** with a NULL pointer as the second parameter.
** ^The first argument to the callback is a copy of the third argument
** to sqlite3_update_hook().
** ^The second callback argument is one of [SQLITE_INSERT], [SQLITE_DELETE],
@@ -6976,7 +7571,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
@@ -6986,6 +7581,12 @@ SQLITE_API void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*);
** The exceptions defined in this paragraph might change in a future
** release of SQLite.
**
+** Whether the update hook is invoked before or after the
+** corresponding change is currently unspecified and may differ
+** depending on the type of change. Do not rely on the order of the
+** hook call with regards to the final result of the operation which
+** triggers the hook.
+**
** The update hook implementation must not do anything that will modify
** the database connection that invoked the update hook. Any actions
** to modify the database connection must be deferred until after the
@@ -7002,7 +7603,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*
);
@@ -7015,26 +7616,35 @@ SQLITE_API void *sqlite3_update_hook(
** to the same database. Sharing is enabled if the argument is true
** and disabled if the argument is false.)^
**
+** This interface is omitted if SQLite is compiled with
+** [-DSQLITE_OMIT_SHARED_CACHE]. The [-DSQLITE_OMIT_SHARED_CACHE]
+** compile-time option is recommended because the
+** [use of shared cache mode is discouraged].
+**
** ^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
@@ -7077,6 +7687,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
+** used 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
@@ -7084,23 +7697,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
-** 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.
-**
-** ^If the argument N is zero then the soft heap limit is disabled.
+** ^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 soft heap limit is not enforced in the current implementation
+** ^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 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).
+**
+** ^Setting the heap limits to zero disables the heap limiter mechanism.
+**
+** ^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 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.
@@ -7111,21 +7745,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
-** changes in future releases of SQLite.
+** The circumstances under which SQLite will enforce the heap limits may
+** change 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
@@ -7149,7 +7773,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
@@ -7189,7 +7813,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
@@ -7229,7 +7853,7 @@ SQLITE_API int sqlite3_table_column_metadata(
** ^The sqlite3_load_extension() interface attempts to load an
** [SQLite extension] library contained in the file zFile. If
** the file cannot be loaded directly, attempts are made to load
-** with various operating-system specific extensions added.
+** with various operating-system specific filename extensions added.
** So for example, if "samplelib" cannot be loaded, then names like
** "samplelib.so" or "samplelib.dylib" or "samplelib.dll" might
** be tried also.
@@ -7237,10 +7861,10 @@ SQLITE_API int sqlite3_table_column_metadata(
** ^The entry point is zProc.
** ^(zProc may be 0, in which case SQLite will try to come up with an
** entry point name on its own. It first tries "sqlite3_extension_init".
-** If that does not work, it constructs a name "sqlite3_X_init" where the
-** X is consists of the lower-case equivalent of all ASCII alphabetic
-** characters in the filename from the last "/" to the first following
-** "." and omitting any initial "lib".)^
+** If that does not work, it tries names of the form "sqlite3_X_init"
+** where X consists of the lower-case equivalent of all ASCII alphabetic
+** characters or all ASCII alphanumeric characters in the filename from
+** the last "/" to the first following "." and omitting any initial "lib".)^
** ^The sqlite3_load_extension() interface returns
** [SQLITE_OK] on success and [SQLITE_ERROR] if something goes wrong.
** ^If an error occurs and pzErrMsg is not 0, then the
@@ -7255,7 +7879,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()]
@@ -7291,7 +7915,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.
@@ -7309,12 +7933,12 @@ SQLITE_API int sqlite3_enable_load_extension(sqlite3 *db, int onoff);
** ^(Even though the function prototype shows that xEntryPoint() takes
** no arguments and returns void, SQLite invokes xEntryPoint() with three
** arguments and expects an integer result as if the signature of the
-** entry point where as follows:
+** entry point were as follows:
**
**
** int xEntryPoint(
** sqlite3 *db,
-** const char **pzErrMsg,
+** char **pzErrMsg,
** const struct sqlite3_api_routines *pThunk
** );
** )^
@@ -7342,7 +7966,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.
*/
@@ -7356,15 +7980,6 @@ SQLITE_API int sqlite3_cancel_auto_extension(void(*xEntryPoint)(void));
*/
SQLITE_API void sqlite3_reset_auto_extension(void);
-/*
-** The interface to the virtual-table mechanism is currently considered
-** to be experimental. The interface might change in incompatible ways.
-** If this is a problem for you, do not use the interface at this time.
-**
-** When the virtual-table mechanism stabilizes, we will declare the
-** interface fixed, support it indefinitely, and remove this comment.
-*/
-
/*
** Structures used by the virtual table interface
*/
@@ -7377,8 +7992,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
@@ -7417,7 +8032,7 @@ 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);
@@ -7425,6 +8040,10 @@ struct sqlite3_module {
/* 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*);
+ /* The methods above are in versions 1 through 3 of the sqlite_module object.
+ ** Those below are for version 4 and greater. */
+ int (*xIntegrity)(sqlite3_vtab *pVTab, const char *zSchema,
+ const char *zTabName, int mFlags, char **pzErr);
};
/*
@@ -7467,7 +8086,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
@@ -7475,12 +8094,18 @@ 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.)^
-**
-** ^The idxNum and idxPtr values are recorded and passed into the
+** 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 changed 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 idxStr values are recorded and passed into the
** [xFilter] method.
-** ^[sqlite3_free()] is used to free idxPtr if and only if
-** needToFreeIdxPtr is true.
+** ^[sqlite3_free()] is used to free idxStr if and only if
+** needToFreeIdxStr is true.
**
** ^The orderByConsumed means that output from [xFilter]/[xNext] will occur in
** the correct order to satisfy the ORDER BY clause so that no separate
@@ -7488,17 +8113,19 @@ 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
-** 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.
+** The xBestIndex method may optionally populate the idxFlags field with a
+** mask of SQLITE_INDEX_SCAN_* flags. One such flag is
+** [SQLITE_INDEX_SCAN_HEX], which if set causes the [EXPLAIN QUERY PLAN]
+** output to show the idxNum as hex instead of as decimal. Another flag is
+** SQLITE_INDEX_SCAN_UNIQUE, which if set indicates that the query plan will
+** return 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
@@ -7511,14 +8138,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.
@@ -7558,35 +8185,69 @@ 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.
*/
-#define SQLITE_INDEX_SCAN_UNIQUE 1 /* Scan visits at most 1 row */
+#define SQLITE_INDEX_SCAN_UNIQUE 0x00000001 /* Scan visits at most 1 row */
+#define SQLITE_INDEX_SCAN_HEX 0x00000002 /* Display idxNum as hex */
+ /* in EXPLAIN QUERY PLAN */
/*
** 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
+** an operator that is part of a constraint term in the WHERE clause of
** a query that uses a [virtual table].
-*/
-#define SQLITE_INDEX_CONSTRAINT_EQ 2
-#define SQLITE_INDEX_CONSTRAINT_GT 4
-#define SQLITE_INDEX_CONSTRAINT_LE 8
-#define SQLITE_INDEX_CONSTRAINT_LT 16
-#define SQLITE_INDEX_CONSTRAINT_GE 32
-#define SQLITE_INDEX_CONSTRAINT_MATCH 64
-#define SQLITE_INDEX_CONSTRAINT_LIKE 65
-#define SQLITE_INDEX_CONSTRAINT_GLOB 66
-#define SQLITE_INDEX_CONSTRAINT_REGEXP 67
-#define SQLITE_INDEX_CONSTRAINT_NE 68
-#define SQLITE_INDEX_CONSTRAINT_ISNOT 69
-#define SQLITE_INDEX_CONSTRAINT_ISNOTNULL 70
-#define SQLITE_INDEX_CONSTRAINT_ISNULL 71
-#define SQLITE_INDEX_CONSTRAINT_IS 72
-#define SQLITE_INDEX_CONSTRAINT_FUNCTION 150
+**
+** ^The left-hand operand of the operator is given by the corresponding
+** aConstraint[].iColumn field. ^An iColumn of -1 indicates the left-hand
+** operand is the rowid.
+** The SQLITE_INDEX_CONSTRAINT_LIMIT and SQLITE_INDEX_CONSTRAINT_OFFSET
+** operators have no left-hand operand, and so for those operators the
+** corresponding aConstraint[].iColumn is meaningless and should not be
+** used.
+**
+** All operator values from SQLITE_INDEX_CONSTRAINT_FUNCTION through
+** value 255 are reserved to represent functions that are overloaded
+** by the [xFindFunction|xFindFunction method] of the virtual table
+** implementation.
+**
+** The right-hand operands for each constraint might be accessible using
+** the [sqlite3_vtab_rhs_value()] interface. Usually the right-hand
+** operand is only available if it appears as a single constant literal
+** in the input SQL. If the right-hand operand is another column or an
+** expression (even a constant expression) or a parameter, then the
+** sqlite3_vtab_rhs_value() probably will not be able to extract it.
+** ^The SQLITE_INDEX_CONSTRAINT_ISNULL and
+** SQLITE_INDEX_CONSTRAINT_ISNOTNULL operators have no right-hand operand
+** and hence calls to sqlite3_vtab_rhs_value() for those operators will
+** always return SQLITE_NOTFOUND.
+**
+** The collating sequence to be used for comparison can be found using
+** the [sqlite3_vtab_collation()] interface. For most real-world virtual
+** tables, the collating sequence of constraints does not matter (for example
+** because the constraints are numeric) and so the sqlite3_vtab_collation()
+** interface is not commonly needed.
+*/
+#define SQLITE_INDEX_CONSTRAINT_EQ 2
+#define SQLITE_INDEX_CONSTRAINT_GT 4
+#define SQLITE_INDEX_CONSTRAINT_LE 8
+#define SQLITE_INDEX_CONSTRAINT_LT 16
+#define SQLITE_INDEX_CONSTRAINT_GE 32
+#define SQLITE_INDEX_CONSTRAINT_MATCH 64
+#define SQLITE_INDEX_CONSTRAINT_LIKE 65
+#define SQLITE_INDEX_CONSTRAINT_GLOB 66
+#define SQLITE_INDEX_CONSTRAINT_REGEXP 67
+#define SQLITE_INDEX_CONSTRAINT_NE 68
+#define SQLITE_INDEX_CONSTRAINT_ISNOT 69
+#define SQLITE_INDEX_CONSTRAINT_ISNOTNULL 70
+#define SQLITE_INDEX_CONSTRAINT_ISNULL 71
+#define SQLITE_INDEX_CONSTRAINT_IS 72
+#define SQLITE_INDEX_CONSTRAINT_LIMIT 73
+#define SQLITE_INDEX_CONSTRAINT_OFFSET 74
+#define SQLITE_INDEX_CONSTRAINT_FUNCTION 150
/*
** CAPI3REF: Register A Virtual Table Implementation
@@ -7598,12 +8259,12 @@ 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
** into the [xCreate] and [xConnect] methods of the virtual table module
-** when a new virtual table is be being created or reinitialized.
+** when a new virtual table is being created or reinitialized.
**
** ^The sqlite3_create_module_v2() interface has a fifth parameter which
** is a pointer to a destructor for the pClientData. ^SQLite will
@@ -7613,6 +8274,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 created 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 */
@@ -7628,6 +8295,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
@@ -7690,7 +8374,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.)^
**
@@ -7704,16 +8388,6 @@ SQLITE_API int sqlite3_declare_vtab(sqlite3*, const char *zSQL);
*/
SQLITE_API int sqlite3_overload_function(sqlite3*, const char *zFuncName, int nArg);
-/*
-** The interface to the virtual-table mechanism defined above (back up
-** to a comment remarkably similar to this one) is currently considered
-** to be experimental. The interface might change in incompatible ways.
-** If this is a problem for you, do not use the interface at this time.
-**
-** When the virtual-table mechanism stabilizes, we will declare the
-** interface fixed, support it indefinitely, and remove this comment.
-*/
-
/*
** CAPI3REF: A Handle To An Open BLOB
** KEYWORDS: {BLOB handle} {BLOB handles}
@@ -7741,7 +8415,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
@@ -7754,28 +8428,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()]
-** on *ppBlob after this function it returns.
+** the API is not misused, it is always safe to call [sqlite3_blob_close()]
+** on *ppBlob after this function 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
@@ -7801,7 +8475,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
@@ -7851,7 +8525,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
@@ -7861,10 +8535,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 behavior. ^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 *);
@@ -7873,9 +8547,9 @@ 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
+** incremental blob I/O routines can only read or overwrite existing
** blob content; they cannot change the size of a blob.
**
** This routine only works on a [BLOB handle] which has been created
@@ -7924,9 +8598,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),
@@ -7935,9 +8609,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
@@ -8014,24 +8688,17 @@ SQLITE_API int sqlite3_vfs_unregister(sqlite3_vfs*);
** SQLITE_MUTEX_W32 implementations are appropriate for use on Unix
** and Windows.
**
-** If SQLite is compiled with the SQLITE_MUTEX_APPDEF preprocessor
-** macro defined (with "-DSQLITE_MUTEX_APPDEF=1"), then no mutex
-** implementation is included with the library. In this case the
-** application must supply a custom mutex implementation using the
-** [SQLITE_CONFIG_MUTEX] option of the sqlite3_config() function
-** before calling sqlite3_initialize() or any other public sqlite3_
-** function that calls sqlite3_initialize().
**
** ^The sqlite3_mutex_alloc() routine allocates a new
** mutex and returns a pointer to it. ^The sqlite3_mutex_alloc()
** routine returns NULL if it is unable to allocate the requested
-** mutex. The argument to sqlite3_mutex_alloc() must one of these
+** mutex. The argument to sqlite3_mutex_alloc() must be one of these
** integer constants:
**
**
** - 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
@@ -8088,18 +8755,20 @@ 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
-** behavior.)^
+** will always return SQLITE_BUSY. In most cases the SQLite core only uses
+** sqlite3_mutex_try() as an optimization, so this is acceptable
+** behavior. The exceptions are unix builds that set the
+** SQLITE_ENABLE_SETLK_TIMEOUT build option. In that case a working
+** sqlite3_mutex_try() is required.)^
**
** ^The sqlite3_mutex_leave() routine exits a mutex that was
** previously entered by the same thread. The behavior
** is undefined if the mutex is not currently entered by the
** calling thread or is not currently allocated.
**
-** ^If the argument to sqlite3_mutex_enter(), sqlite3_mutex_try(), or
-** sqlite3_mutex_leave() is a NULL pointer, then all three routines
-** behave as no-ops.
+** ^If the argument to sqlite3_mutex_enter(), sqlite3_mutex_try(),
+** sqlite3_mutex_leave(), or sqlite3_mutex_free() is a NULL pointer,
+** then any of the four routines behaves as a no-op.
**
** See also: [sqlite3_mutex_held()] and [sqlite3_mutex_notheld()].
*/
@@ -8154,7 +8823,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).
@@ -8233,7 +8902,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() */
@@ -8248,11 +8917,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 to 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
@@ -8279,7 +8952,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
@@ -8336,16 +9009,19 @@ 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_FK_NO_ACTION 7
#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_JSON_SELFCHECK 14
#define SQLITE_TESTCTRL_OPTIMIZATIONS 15
#define SQLITE_TESTCTRL_ISKEYWORD 16 /* NOT USED */
+#define SQLITE_TESTCTRL_GETOPT 16
#define SQLITE_TESTCTRL_SCRATCHMALLOC 17 /* NOT USED */
#define SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 17
#define SQLITE_TESTCTRL_LOCALTIME_FAULT 18
@@ -8358,20 +9034,29 @@ 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_LOGEST 33
+#define SQLITE_TESTCTRL_USELONGDOUBLE 34 /* NOT USED */
+#define SQLITE_TESTCTRL_ATOF 34
+#define SQLITE_TESTCTRL_LAST 34 /* Largest TESTCTRL */
/*
** CAPI3REF: SQL Keyword Checking
**
-** These routines provide access to the set of SQL language keywords
-** recognized by SQLite. Applications can uses these routines to determine
+** These routines provide access to the set of SQL language keywords
+** recognized by SQLite. Applications can use 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.
**
** The sqlite3_keyword_count() interface returns the number of distinct
** keywords understood by SQLite.
**
-** The sqlite3_keyword_name(N,Z,L) interface finds the N-th keyword and
+** The sqlite3_keyword_name(N,Z,L) interface finds the 0-based N-th keyword and
** makes *Z point to that keyword expressed as UTF8 and writes the number
** of bytes in the keyword into *L. The string that *Z points to is not
** zero-terminated. The sqlite3_keyword_name(N,Z,L) routine returns
@@ -8435,14 +9120,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
@@ -8466,21 +9151,26 @@ SQLITE_API sqlite3_str *sqlite3_str_new(sqlite3*);
** pass the returned value to [sqlite3_free()] to avoid a memory leak.
** ^The [sqlite3_str_finish(X)] interface may return a NULL pointer if any
** errors were encountered during construction of the string. ^The
-** [sqlite3_str_finish(X)] interface will also return a NULL pointer if the
+** [sqlite3_str_finish(X)] interface might also return a NULL pointer if the
** string in [sqlite3_str] object X is zero bytes long.
+**
+** ^The [sqlite3_str_free(X)] interface destroys both the sqlite3_str object
+** X and the string content it contains. Calling sqlite3_str_free(X) is
+** the equivalent of calling [sqlite3_free](sqlite3_str_finish(X)).
*/
SQLITE_API char *sqlite3_str_finish(sqlite3_str*);
+SQLITE_API void sqlite3_str_free(sqlite3_str*);
/*
** CAPI3REF: Add Content To A Dynamic String
** METHOD: sqlite3_str
**
-** These interfaces add content to an sqlite3_str object previously obtained
-** from [sqlite3_str_new()].
+** These interfaces add or remove 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
@@ -8497,7 +9187,11 @@ 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.
+**
+** ^The [sqlite3_str_truncate(X,N)] method changes the length of the string
+** under construction to be N bytes or less. This routine is a no-op if
+** N is negative or if the string is already N bytes or smaller in size.
**
** 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
@@ -8509,6 +9203,7 @@ SQLITE_API void sqlite3_str_append(sqlite3_str*, const char *zIn, int N);
SQLITE_API void sqlite3_str_appendall(sqlite3_str*, const char *zIn);
SQLITE_API void sqlite3_str_appendchar(sqlite3_str*, int N, char C);
SQLITE_API void sqlite3_str_reset(sqlite3_str*);
+SQLITE_API void sqlite3_str_truncate(sqlite3_str*,int N);
/*
** CAPI3REF: Status Of A Dynamic String
@@ -8532,7 +9227,7 @@ SQLITE_API void sqlite3_str_reset(sqlite3_str*);
** content of the dynamic string under construction in X. The value
** returned by [sqlite3_str_value(X)] is managed by the sqlite3_str object X
** and might be freed or altered by any subsequent method on the same
-** [sqlite3_str] object. Applications must not used the pointer returned
+** [sqlite3_str] object. Applications must not use the pointer returned by
** [sqlite3_str_value(X)] after any subsequent method call on the same
** object. ^Applications may change the content of the string returned
** by [sqlite3_str_value(X)] as long as they do not write into any bytes
@@ -8599,7 +9294,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
@@ -8608,24 +9303,24 @@ 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]
** buffer and where forced to overflow to [sqlite3_malloc()]. The
** returned value includes allocations that overflowed because they
-** where too large (they were larger than the "sz" parameter to
+** were too large (they were larger than the "sz" parameter to
** [SQLITE_CONFIG_PAGECACHE]) and allocations that overflowed because
** no space was left in the page cache.
)^
**
** [[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
@@ -8638,7 +9333,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].
)^
**
@@ -8660,12 +9355,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.
**
@@ -8677,9 +9372,18 @@ SQLITE_API int sqlite3_status64(
** ^The sqlite3_db_status() routine returns SQLITE_OK on success and a
** non-zero [error code] on failure.
**
+** ^The sqlite3_db_status64(D,O,C,H,R) routine works exactly the same
+** way as sqlite3_db_status(D,O,C,H,R) routine except that the C and H
+** parameters are pointer to 64-bit integers (type: sqlite3_int64) instead
+** of pointers to 32-bit integers, which allows larger status values
+** to be returned. If a status value exceeds 2,147,483,647 then
+** sqlite3_db_status() will truncate the value whereas sqlite3_db_status64()
+** will return the full value.
+**
** See also: [sqlite3_status()] and [sqlite3_stmt_status()].
*/
SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg);
+SQLITE_API int sqlite3_db_status64(sqlite3*,int,sqlite3_int64*,sqlite3_int64*,int);
/*
** CAPI3REF: Status Parameters for database connections
@@ -8700,51 +9404,53 @@ 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.)^
+** the current value is always zero.)^
**
** [[SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE]]
** ^(SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE
-** This parameter returns the number malloc attempts that might have
+** This parameter returns the number of malloc attempts that might have
** been satisfied using lookaside memory but failed due to the amount of
** memory requested being larger than the lookaside slot size.
** Only the high-water value is meaningful;
-** the current value is always zero.)^
+** the current value is always zero.)^
**
** [[SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL]]
** ^(SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL
-** This parameter returns the number malloc attempts that might have
+** This parameter returns the number of malloc attempts that might have
** been satisfied using lookaside memory but failed due to all lookaside
** memory already being in use.
** Only the high-water value is meaningful;
-** the current value is always zero.)^
+** the current value is always zero.)^
**
** [[SQLITE_DBSTATUS_CACHE_USED]] ^(SQLITE_DBSTATUS_CACHE_USED
** This parameter returns the approximate number of bytes of heap
** memory used by all pager caches associated with the database connection.)^
** ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_USED is always 0.
+**
**
-** [[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
** memory used by that pager cache is divided evenly between the attached
** connections.)^ In other words, if none of the pager caches associated
** with the database connection are shared, this request returns the same
-** value as DBSTATUS_CACHE_USED. Or, if one or more or the pager caches are
+** value as DBSTATUS_CACHE_USED. Or, if one or more of the pager caches are
** shared, the value returned by this call will be smaller than that returned
** by DBSTATUS_CACHE_USED. ^The highwater mark associated with
-** SQLITE_DBSTATUS_CACHE_USED_SHARED is always 0.
+** SQLITE_DBSTATUS_CACHE_USED_SHARED is always 0.
**
** [[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.
** ^The highwater mark associated with SQLITE_DBSTATUS_SCHEMA_USED is always 0.
+**
**
** [[SQLITE_DBSTATUS_STMT_USED]] ^(SQLITE_DBSTATUS_STMT_USED
** This parameter returns the approximate number of bytes of heap
@@ -8755,13 +9461,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.
**
**
@@ -8774,6 +9480,10 @@ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int r
** If an IO or other error occurs while writing a page to disk, the effect
** on subsequent SQLITE_DBSTATUS_CACHE_WRITE requests is undefined.)^ ^The
** highwater mark associated with SQLITE_DBSTATUS_CACHE_WRITE is always 0.
+**
+** ^(There is overlap between the quantities measured by this parameter
+** (SQLITE_DBSTATUS_CACHE_WRITE) and SQLITE_DBSTATUS_TEMPBUF_SPILL.
+** Resetting one will reduce the other.)^
**
**
** [[SQLITE_DBSTATUS_CACHE_SPILL]] ^( SQLITE_DBSTATUS_CACHE_SPILL
@@ -8781,14 +9491,26 @@ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int r
** been written to disk in the middle of a transaction due to the page
** 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.
+** additional overhead. This parameter can be used to help identify
+** inefficiencies that can be resolved by increasing the cache size.
**
**
** [[SQLITE_DBSTATUS_DEFERRED_FKS]] ^(SQLITE_DBSTATUS_DEFERRED_FKS
** This parameter returns zero for the current value if and only if
** all foreign key constraints (deferred or immediate) have been
** resolved.)^ ^The highwater mark is always 0.
+**
+** [[SQLITE_DBSTATUS_TEMPBUF_SPILL] ^(SQLITE_DBSTATUS_TEMPBUF_SPILL
+** ^(This parameter returns the number of bytes written to temporary
+** files on disk that could have been kept in memory had sufficient memory
+** been available. This value includes writes to intermediate tables that
+** are part of complex queries, external sorts that spill to disk, and
+** writes to TEMP tables.)^
+** ^The highwater mark is always 0.
+**
+** ^(There is overlap between the quantities measured by this parameter
+** (SQLITE_DBSTATUS_TEMPBUF_SPILL) and SQLITE_DBSTATUS_CACHE_WRITE.
+** Resetting one will reduce the other.)^
**
**
*/
@@ -8805,7 +9527,8 @@ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int r
#define SQLITE_DBSTATUS_DEFERRED_FKS 10
#define SQLITE_DBSTATUS_CACHE_USED_SHARED 11
#define SQLITE_DBSTATUS_CACHE_SPILL 12
-#define SQLITE_DBSTATUS_MAX 12 /* Largest defined DBSTATUS */
+#define SQLITE_DBSTATUS_TEMPBUF_SPILL 13
+#define SQLITE_DBSTATUS_MAX 13 /* Largest defined DBSTATUS */
/*
@@ -8819,7 +9542,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
@@ -8846,40 +9569,50 @@ 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
** ^This is the number of sort operations that have occurred.
** A non-zero value in this counter may indicate an opportunity to
-** improvement performance through careful use of indices.
+** improve performance through careful use of indices.
**
** [[SQLITE_STMTSTATUS_AUTOINDEX]] SQLITE_STMTSTATUS_AUTOINDEX
** ^This is the number of rows inserted into transient indices that
** were created automatically in order to help joins run faster.
** A non-zero value in this counter may indicate an opportunity to
-** improvement performance by adding permanent indices that do not
+** improve performance by adding permanent indices that do not
** need to be reinitialized each time the statement is run.
**
** [[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.
+** 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
-** [bound parameters] that might affect the query plan.
+** automatically regenerated due to schema changes or changes to
+** [bound parameters] that might affect the query plan.
**
** [[SQLITE_STMTSTATUS_RUN]] SQLITE_STMTSTATUS_RUN
** ^This is the number of times that the prepared statement has
** been run. A single "run" for the purposes of this counter is one
** or more calls to [sqlite3_step()] followed by a call to [sqlite3_reset()].
** The counter is incremented on the first [sqlite3_step()] call of each
-** cycle.
+** cycle.
+**
+** [[SQLITE_STMTSTATUS_FILTER_MISS]]
+** [[SQLITE_STMTSTATUS_FILTER HIT]]
+** SQLITE_STMTSTATUS_FILTER_HIT
+** SQLITE_STMTSTATUS_FILTER_MISS
+** ^SQLITE_STMTSTATUS_FILTER_HIT is the number of times that a join
+** step was bypassed because a Bloom filter returned not-found. The
+** corresponding SQLITE_STMTSTATUS_FILTER_MISS value is the number of
+** times that the Bloom filter returned a find, and thus the join step
+** had to be processed as normal.
**
** [[SQLITE_STMTSTATUS_MEMUSED]] SQLITE_STMTSTATUS_MEMUSED
** ^This is the approximate number of bytes of heap memory
@@ -8895,6 +9628,8 @@ SQLITE_API int sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg);
#define SQLITE_STMTSTATUS_VM_STEP 4
#define SQLITE_STMTSTATUS_REPREPARE 5
#define SQLITE_STMTSTATUS_RUN 6
+#define SQLITE_STMTSTATUS_FILTER_MISS 7
+#define SQLITE_STMTSTATUS_FILTER_HIT 8
#define SQLITE_STMTSTATUS_MEMUSED 99
/*
@@ -8931,15 +9666,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
@@ -8952,19 +9687,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.
**
@@ -8982,9 +9717,9 @@ struct sqlite3_pcache_page {
** SQLite will typically create one cache instance for each open database file,
** 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
-** associated with each page cache entry. ^The szExtra parameter will
+** be allocated by the cache. ^szPage will always be a power of two. ^The
+** second parameter szExtra is a number of bytes of extra storage
+** associated with each page cache entry. ^The szExtra parameter will be
** a number less than 250. SQLite will use the
** extra szExtra bytes on each page to store metadata about the underlying
** database page on disk. The value passed into szExtra depends
@@ -8992,17 +9727,17 @@ struct sqlite3_pcache_page {
** ^The third argument to xCreate(), bPurgeable, is true if the cache being
** created will be used to cache database pages of a file stored on disk, or
** false if it is used for an in-memory database. The cache implementation
-** does not have to do anything special based with the value of bPurgeable;
+** does not have to do anything special based upon the value of bPurgeable;
** 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.
-** ^Hence, a cache created with bPurgeable false will
+** false will always have the "discard" flag set to true.
+** ^Hence, a cache created with bPurgeable set to false will
** never contain any unpinned pages.
**
** [[the xCachesize() page cache method]]
** ^(The xCachesize() method may be called at any time by SQLite to set the
-** suggested maximum cache-size (number of pages stored by) the cache
+** suggested maximum cache-size (number of pages stored) for the cache
** instance passed as the first argument. This is the value configured using
** the SQLite "[PRAGMA cache_size]" command.)^ As with the bPurgeable
** parameter, the implementation is not required to do anything with this
@@ -9011,12 +9746,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.
@@ -9029,12 +9764,12 @@ struct sqlite3_pcache_page {
** implementation must return a pointer to the page buffer with its content
** intact. If the requested page is not already in the cache, then the
** cache implementation should use the value of the createFlag
-** parameter to help it determined what action to take:
+** parameter to help it determine what action to take:
**
**
** | createFlag | Behavior when page is not already in cache
** |
|---|
| 0 | Do not allocate a new page. Return NULL.
-** | | 1 | Allocate a new page if it easy and convenient to do so.
+** | | 1 | Allocate a new page if it is easy and convenient to do so.
** Otherwise return NULL.
** | | 2 | Make every effort to allocate a new page. Only return
** NULL if allocating a new page is effectively impossible.
@@ -9042,7 +9777,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.
**
@@ -9051,12 +9786,12 @@ struct sqlite3_pcache_page {
** as its second argument. If the third parameter, discard, is non-zero,
** then the page must be evicted from the cache.
** ^If the discard parameter is
-** zero, then the page may be discarded or retained at the discretion of
+** zero, then the page may be discarded or retained at the discretion of the
** 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]]
@@ -9069,7 +9804,7 @@ struct sqlite3_pcache_page {
** When SQLite calls the xTruncate() method, the cache must discard all
** existing cache entries with page numbers (keys) greater than or equal
** to the value of the iLimit parameter passed to xTruncate(). If any
-** of these pages are pinned, they are implicitly unpinned, meaning that
+** of these pages are pinned, they become implicitly unpinned, meaning that
** they can be safely discarded.
**
** [[the xDestroy() page cache method]]
@@ -9096,7 +9831,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*);
@@ -9141,7 +9876,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]
**
@@ -9152,36 +9887,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
@@ -9193,14 +9928,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
@@ -9222,8 +9957,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]
@@ -9231,15 +9966,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.
@@ -9248,25 +9983,25 @@ 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
-** database is modified by the using the same database connection as is used
+** restarted by the next call to sqlite3_backup_step(). ^If the source
+** database is modified by 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
** and may not be used following a call to sqlite3_backup_finish().
**
** ^The value returned by sqlite3_backup_finish is [SQLITE_OK] if no
-** sqlite3_backup_step() errors occurred, regardless or whether or not
+** sqlite3_backup_step() errors occurred, regardless of whether or not
** sqlite3_backup_step() completed.
** ^If an out-of-memory condition or IO error occurred during any prior
** sqlite3_backup_step() call on the same [sqlite3_backup] object, then
@@ -9299,28 +10034,38 @@ 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]
** and so no error code is reported, but the operations may malfunction
** nevertheless. Use of the destination database connection while a
-** backup is in progress might also also cause a mutex deadlock.
+** backup is in progress might also cause a mutex deadlock.
**
** 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
** same time as another thread is invoking sqlite3_backup_step() it is
** possible that they return invalid values.
+**
+** Alternatives To Using The Backup API
+**
+** Other techniques for safely creating a consistent backup of an SQLite
+** database include:
+**
+**
+** - The [VACUUM INTO] command.
+**
- The [sqlite3_rsync] utility program.
+**
*/
SQLITE_API sqlite3_backup *sqlite3_backup_init(
sqlite3 *pDest, /* Destination database handle */
@@ -9340,8 +10085,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.
@@ -9349,18 +10094,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
+** when the blocking connection's 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
@@ -9370,15 +10115,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 connection's
** unlock-notify callback may also be canceled by closing the blocked
** connection using [sqlite3_close()].
**
@@ -9391,25 +10136,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
@@ -9432,7 +10177,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
@@ -9445,7 +10190,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(
@@ -9536,8 +10281,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
@@ -9548,7 +10293,7 @@ SQLITE_API void sqlite3_log(int iErrCode, const char *zFormat, ...);
** is the number of pages currently in the write-ahead log file,
** including those that were just committed.
**
-** The callback function should normally return [SQLITE_OK]. ^If an error
+** ^The callback function should normally return [SQLITE_OK]. ^If an error
** code is returned, that error will propagate back up through the
** SQLite code base to cause the statement that provoked the callback
** to report an error, though the commit will have still occurred. If the
@@ -9556,15 +10301,29 @@ 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
-** registered at one time. ^Calling [sqlite3_wal_hook()] replaces any
-** previously registered write-ahead log callback. ^Note that the
-** [sqlite3_wal_autocheckpoint()] interface and the
-** [wal_autocheckpoint pragma] both invoke [sqlite3_wal_hook()] and will
-** overwrite any prior [sqlite3_wal_hook()] settings.
+** ^A single database handle may have at most a single write-ahead log
+** callback registered at one time. ^Calling [sqlite3_wal_hook()]
+** replaces the default behavior or previously registered write-ahead
+** log callback.
+**
+** ^The return value is a copy of the third parameter from the
+** previous call, if any, or 0.
+**
+** ^The [sqlite3_wal_autocheckpoint()] interface and the
+** [wal_autocheckpoint pragma] both invoke [sqlite3_wal_hook()] and
+** will overwrite any prior [sqlite3_wal_hook()] settings.
+**
+** ^If a write-ahead log callback is set using this function then
+** [sqlite3_wal_checkpoint_v2()] or [PRAGMA wal_checkpoint]
+** should be invoked periodically to keep the write-ahead log file
+** from growing without bound.
+**
+** ^Passing a NULL pointer for the callback disables automatic
+** checkpointing entirely. To re-enable the default behavior, call
+** sqlite3_wal_autocheckpoint(db,1000) or use [PRAGMA wal_checkpoint].
*/
SQLITE_API void *sqlite3_wal_hook(
- sqlite3*,
+ sqlite3*,
int(*)(void *,sqlite3*,const char*,int),
void*
);
@@ -9577,8 +10336,8 @@ 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
-** a negative value as the nFrame parameter disables automatic
+** more frames in the [write-ahead log] file. ^Passing zero or
+** a negative value as the N parameter disables automatic
** checkpoints entirely.
**
** ^The callback registered by this function replaces any existing callback
@@ -9594,9 +10353,10 @@ SQLITE_API void *sqlite3_wal_hook(
**
** ^Every new [database connection] defaults to having the auto-checkpoint
** enabled with a threshold of 1000 or [SQLITE_DEFAULT_WAL_AUTOCHECKPOINT]
-** pages. The use of this interface
-** is only necessary if the default setting is found to be suboptimal
-** for a particular application.
+** pages.
+**
+** ^The use of this interface is only necessary if the default setting
+** is found to be suboptimal for a particular application.
*/
SQLITE_API int sqlite3_wal_autocheckpoint(sqlite3 *db, int N);
@@ -9607,7 +10367,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
@@ -9633,10 +10393,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.
**
@@ -9650,9 +10410,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.
@@ -9661,6 +10421,11 @@ SQLITE_API int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb);
** ^This mode works the same way as SQLITE_CHECKPOINT_RESTART with the
** addition that it also truncates the log file to zero bytes just prior
** to a successful return.
+**
+**
- SQLITE_CHECKPOINT_NOOP
-
+** ^This mode always checkpoints zero frames. The only reason to invoke
+** a NOOP checkpoint is to access the values returned by
+** sqlite3_wal_checkpoint_v2() via output parameters *pnLog and *pnCkpt.
**
**
** ^If pnLog is not NULL, then *pnLog is set to the total number of frames in
@@ -9674,31 +10439,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
@@ -9731,9 +10496,10 @@ SQLITE_API int sqlite3_wal_checkpoint_v2(
** See the [sqlite3_wal_checkpoint_v2()] documentation for details on the
** meaning of each of these checkpoint modes.
*/
+#define SQLITE_CHECKPOINT_NOOP -1 /* Do no work at all */
#define SQLITE_CHECKPOINT_PASSIVE 0 /* Do as much as possible w/o blocking */
#define SQLITE_CHECKPOINT_FULL 1 /* Wait for writers, then checkpoint */
-#define SQLITE_CHECKPOINT_RESTART 2 /* Like FULL but wait for for readers */
+#define SQLITE_CHECKPOINT_RESTART 2 /* Like FULL but wait for readers */
#define SQLITE_CHECKPOINT_TRUNCATE 3 /* Like RESTART but also truncate WAL */
/*
@@ -9746,14 +10512,20 @@ 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
@@ -9761,7 +10533,7 @@ SQLITE_API int sqlite3_vtab_config(sqlite3*, int op, ...);
**
**
** [[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
@@ -9769,30 +10541,62 @@ SQLITE_API int sqlite3_vtab_config(sqlite3*, int op, ...);
** support constraints. In this configuration (which is the default) if
** a call to the [xUpdate] method returns [SQLITE_CONSTRAINT], then the entire
** statement is rolled back as if [ON CONFLICT | OR ABORT] had been
-** specified as part of the users SQL statement, regardless of the actual
+** specified as part of the user's SQL statement, regardless of the actual
** ON CONFLICT mode specified.
**
** 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] implementation
+** 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
+** [xConnect] or [xCreate] methods of a [virtual table] implementation
+** 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.
+**
+**
+** [[SQLITE_VTAB_USES_ALL_SCHEMAS]]- SQLITE_VTAB_USES_ALL_SCHEMAS
+** - Calls of the form
+** [sqlite3_vtab_config](db,SQLITE_VTAB_USES_ALL_SCHEMA) from within the
+** the [xConnect] or [xCreate] methods of a [virtual table] implementation
+** instruct the query planner to begin at least a read transaction on
+** all schemas ("main", "temp", and any ATTACH-ed databases) whenever the
+** virtual table is used.
+**
**
*/
#define SQLITE_VTAB_CONSTRAINT_SUPPORT 1
+#define SQLITE_VTAB_INNOCUOUS 2
+#define SQLITE_VTAB_DIRECTONLY 3
+#define SQLITE_VTAB_USES_ALL_SCHEMAS 4
/*
** CAPI3REF: Determine The Virtual Table Conflict Policy
@@ -9810,10 +10614,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
@@ -9822,31 +10627,315 @@ 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*);
/*
** CAPI3REF: Determine The Collation For a Virtual Table Constraint
+** METHOD: sqlite3_index_info
**
** This function may only be called from within a call to the [xBestIndex]
-** method of a [virtual table].
+** method of a [virtual table]. This function returns a pointer to a string
+** that is the name of the appropriate collation sequence to use for text
+** comparisons on the constraint identified by its arguments.
+**
+** The first argument must be the pointer to 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.
+**
+** Important:
+** The first parameter must be the same pointer that is passed into the
+** xBestMethod() method. The first parameter may not be a pointer to a
+** different [sqlite3_index_info] object, even an exact copy.
+**
+** The return value is computed as follows:
+**
+**
+** If the constraint comes from a WHERE clause expression that contains
+** a [COLLATE operator], then the name of the collation specified by
+** that COLLATE operator is returned.
+** If there is no COLLATE operator, but the column that is the subject
+** of the constraint specifies an alternative collating sequence via
+** a [COLLATE clause] on the column definition within the CREATE TABLE
+** statement that was passed into [sqlite3_declare_vtab()], then the
+** name of that alternative collating sequence is returned.
+** Otherwise, "BINARY" is returned.
+**
+*/
+SQLITE_API const char *sqlite3_vtab_collation(sqlite3_index_info*,int);
+
+/*
+** CAPI3REF: Determine if a virtual table query is DISTINCT
+** METHOD: sqlite3_index_info
+**
+** This API may only be used from within an [xBestIndex|xBestIndex method]
+** of a [virtual table] implementation. The result of calling this
+** interface from outside of xBestIndex() is undefined and probably harmful.
+**
+** ^The sqlite3_vtab_distinct() interface returns an integer between 0 and
+** 3. The integer returned by sqlite3_vtab_distinct()
+** gives the virtual table additional information about how the query
+** planner wants the output to be ordered. As long as the virtual table
+** can meet the ordering requirements of the query planner, it may set
+** the "orderByConsumed" flag.
+**
+**
+** ^If the sqlite3_vtab_distinct() interface returns 0, that means
+** that the query planner needs the virtual table to return all rows in the
+** sort order defined by the "nOrderBy" and "aOrderBy" fields of the
+** [sqlite3_index_info] object. This is the default expectation. If the
+** virtual table outputs all rows in sorted order, then it is always safe for
+** the xBestIndex method to set the "orderByConsumed" flag, regardless of
+** the return value from sqlite3_vtab_distinct().
+**
+** ^(If the sqlite3_vtab_distinct() interface returns 1, that means
+** that the query planner does not need the rows to be returned in sorted order
+** as long as all rows with the same values in all columns identified by the
+** "aOrderBy" field are adjacent.)^ This mode is used when the query planner
+** is doing a GROUP BY.
+**
+** ^(If the sqlite3_vtab_distinct() interface returns 2, that means
+** that the query planner does not need the rows returned in any particular
+** order, as long as rows with the same values in all columns identified
+** by "aOrderBy" are adjacent.)^ ^(Furthermore, when two or more rows
+** contain the same values for all columns identified by "colUsed", all but
+** one such row may optionally be omitted from the result.)^
+** The virtual table is not required to omit rows that are duplicates
+** over the "colUsed" columns, but if the virtual table can do that without
+** too much extra effort, it could potentially help the query to run faster.
+** This mode is used for a DISTINCT query.
+**
+** ^(If the sqlite3_vtab_distinct() interface returns 3, that means the
+** virtual table must return rows in the order defined by "aOrderBy" as
+** if the sqlite3_vtab_distinct() interface had returned 0. However if
+** two or more rows in the result have the same values for all columns
+** identified by "colUsed", then all but one such row may optionally be
+** omitted.)^ Like when the return value is 2, the virtual table
+** is not required to omit rows that are duplicates over the "colUsed"
+** columns, but if the virtual table can do that without
+** too much extra effort, it could potentially help the query to run faster.
+** This mode is used for queries
+** that have both DISTINCT and ORDER BY clauses.
+**
+**
+** The following table summarizes the conditions under which the
+** virtual table is allowed to set the "orderByConsumed" flag based on
+** the value returned by sqlite3_vtab_distinct(). This table is a
+** restatement of the previous four paragraphs:
+**
+**
+**
+** | sqlite3_vtab_distinct() return value
+** | Rows are returned in aOrderBy order
+** | Rows with the same value in all aOrderBy columns are
+** adjacent
+** | Duplicates over all colUsed columns may be omitted
+** | | 0 | yes | yes | no
+** | | 1 | no | yes | no
+** | | 2 | no | yes | yes
+** | | 3 | yes | yes | yes
+** |
+**
+** ^For the purposes of comparing virtual table output values to see if the
+** values are the same value for sorting purposes, two NULL values are
+** considered to be the same. In other words, the comparison operator is "IS"
+** (or "IS NOT DISTINCT FROM") and not "==".
+**
+** If a virtual table implementation is unable to meet the requirements
+** specified above, then it must not set the "orderByConsumed" flag in the
+** [sqlite3_index_info] object or an incorrect answer may result.
+**
+** ^A virtual table implementation is always free to return rows in any order
+** it wants, as long as the "orderByConsumed" flag is not set. ^When the
+** "orderByConsumed" flag is unset, the query planner will add extra
+** [bytecode] to ensure that the final results returned by the SQL query are
+** ordered correctly. The use of the "orderByConsumed" flag and the
+** sqlite3_vtab_distinct() interface is merely an optimization. ^Careful
+** use of the sqlite3_vtab_distinct() interface and the "orderByConsumed"
+** flag might help queries against a virtual table to run faster. Being
+** overly aggressive and setting the "orderByConsumed" flag when it is not
+** valid to do so, on the other hand, might cause SQLite to return incorrect
+** results.
+*/
+SQLITE_API int sqlite3_vtab_distinct(sqlite3_index_info*);
+
+/*
+** CAPI3REF: Identify and handle IN constraints in xBestIndex
+**
+** This interface may only be used from within an
+** [xBestIndex|xBestIndex() method] of a [virtual table] implementation.
+** The result of invoking this interface from any other context is
+** undefined and probably harmful.
+**
+** ^(A constraint on a virtual table of the form
+** "[IN operator|column IN (...)]" is
+** communicated to the xBestIndex method as a
+** [SQLITE_INDEX_CONSTRAINT_EQ] constraint.)^ If xBestIndex wants to use
+** this constraint, it must set the corresponding
+** aConstraintUsage[].argvIndex to a positive integer. ^(Then, under
+** the usual mode of handling IN operators, SQLite generates [bytecode]
+** that invokes the [xFilter|xFilter() method] once for each value
+** on the right-hand side of the IN operator.)^ Thus the virtual table
+** only sees a single value from the right-hand side of the IN operator
+** at a time.
+**
+** In some cases, however, it would be advantageous for the virtual
+** table to see all values on the right-hand of the IN operator all at
+** once. The sqlite3_vtab_in() interfaces facilitates this in two ways:
+**
+**
+**
+** ^A call to sqlite3_vtab_in(P,N,-1) will return true (non-zero)
+** if and only if the [sqlite3_index_info|P->aConstraint][N] constraint
+** is an [IN operator] that can be processed all at once. ^In other words,
+** sqlite3_vtab_in() with -1 in the third argument is a mechanism
+** by which the virtual table can ask SQLite if all-at-once processing
+** of the IN operator is even possible.
+**
+**
+** ^A call to sqlite3_vtab_in(P,N,F) with F==1 or F==0 indicates
+** to SQLite that the virtual table does or does not want to process
+** the IN operator all-at-once, respectively. ^Thus when the third
+** parameter (F) is non-negative, this interface is the mechanism by
+** which the virtual table tells SQLite how it wants to process the
+** IN operator.
+**
+**
+** ^The sqlite3_vtab_in(P,N,F) interface can be invoked multiple times
+** within the same xBestIndex method call. ^For any given P,N pair,
+** the return value from sqlite3_vtab_in(P,N,F) will always be the same
+** within the same xBestIndex call. ^If the interface returns true
+** (non-zero), that means that the constraint is an IN operator
+** that can be processed all-at-once. ^If the constraint is not an IN
+** operator or cannot be processed all-at-once, then the interface returns
+** false.
+**
+** ^(All-at-once processing of the IN operator is selected if both of the
+** following conditions are met:
+**
+**
+** The P->aConstraintUsage[N].argvIndex value is set to a positive
+** integer. This is how the virtual table tells SQLite that it wants to
+** use the N-th constraint.
+**
+** The last call to sqlite3_vtab_in(P,N,F) for which F was
+** non-negative had F>=1.
+** )^
**
-** 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
-** containing the name of the collation sequence for the corresponding
-** constraint.
+** ^If either or both of the conditions above are false, then SQLite uses
+** the traditional one-at-a-time processing strategy for the IN constraint.
+** ^If both conditions are true, then the argvIndex-th parameter to the
+** xFilter method will be an [sqlite3_value] that appears to be NULL,
+** but which can be passed to [sqlite3_vtab_in_first()] and
+** [sqlite3_vtab_in_next()] to find all values on the right-hand side
+** of the IN constraint.
*/
-SQLITE_API SQLITE_EXPERIMENTAL const char *sqlite3_vtab_collation(sqlite3_index_info*,int);
+SQLITE_API int sqlite3_vtab_in(sqlite3_index_info*, int iCons, int bHandle);
+
+/*
+** CAPI3REF: Find all elements on the right-hand side of an IN constraint.
+**
+** These interfaces are only useful from within the
+** [xFilter|xFilter() method] of a [virtual table] implementation.
+** The result of invoking these interfaces from any other context
+** is undefined and probably harmful.
+**
+** The X parameter in a call to sqlite3_vtab_in_first(X,P) or
+** sqlite3_vtab_in_next(X,P) should be one of the parameters to the
+** xFilter method which invokes these routines, and specifically
+** a parameter that was previously selected for all-at-once IN constraint
+** processing using the [sqlite3_vtab_in()] interface in the
+** [xBestIndex|xBestIndex method]. ^(If the X parameter is not
+** an xFilter argument that was selected for all-at-once IN constraint
+** processing, then these routines return [SQLITE_ERROR].)^
+**
+** ^(Use these routines to access all values on the right-hand side
+** of the IN constraint using code like the following:
+**
+**
+** for(rc=sqlite3_vtab_in_first(pList, &pVal);
+** rc==SQLITE_OK && pVal;
+** rc=sqlite3_vtab_in_next(pList, &pVal)
+** ){
+** // do something with pVal
+** }
+** if( rc!=SQLITE_DONE ){
+** // an error has occurred
+** }
+** )^
+**
+** ^On success, the sqlite3_vtab_in_first(X,P) and sqlite3_vtab_in_next(X,P)
+** routines return SQLITE_OK and set *P to point to the first or next value
+** on the RHS of the IN constraint. ^If there are no more values on the
+** right hand side of the IN constraint, then *P is set to NULL and these
+** routines return [SQLITE_DONE]. ^The return value might be
+** some other value, such as SQLITE_NOMEM, in the event of a malfunction.
+**
+** The *ppOut values returned by these routines are only valid until the
+** next call to either of these routines or until the end of the xFilter
+** method from which these routines were called. If the virtual table
+** implementation needs to retain the *ppOut values for longer, it must make
+** copies. The *ppOut values are [protected sqlite3_value|protected].
+*/
+SQLITE_API int sqlite3_vtab_in_first(sqlite3_value *pVal, sqlite3_value **ppOut);
+SQLITE_API int sqlite3_vtab_in_next(sqlite3_value *pVal, sqlite3_value **ppOut);
+
+/*
+** CAPI3REF: Constraint values in xBestIndex()
+** METHOD: sqlite3_index_info
+**
+** This API may only be used from within the [xBestIndex|xBestIndex method]
+** of a [virtual table] implementation. The result of calling this interface
+** from outside of an xBestIndex method are undefined and probably harmful.
+**
+** ^When the sqlite3_vtab_rhs_value(P,J,V) interface is invoked from within
+** the [xBestIndex] method of a [virtual table] implementation, with P being
+** a copy of the [sqlite3_index_info] object pointer passed into xBestIndex and
+** J being a 0-based index into P->aConstraint[], then this routine
+** attempts to set *V to the value of the right-hand operand of
+** that constraint if the right-hand operand is known. ^If the
+** right-hand operand is not known, then *V is set to a NULL pointer.
+** ^The sqlite3_vtab_rhs_value(P,J,V) interface returns SQLITE_OK if
+** and only if *V is set to a value. ^The sqlite3_vtab_rhs_value(P,J,V)
+** inteface returns SQLITE_NOTFOUND if the right-hand side of the J-th
+** constraint is not available. ^The sqlite3_vtab_rhs_value() interface
+** can return a result code other than SQLITE_OK or SQLITE_NOTFOUND if
+** something goes wrong.
+**
+** The sqlite3_vtab_rhs_value() interface is usually only successful if
+** the right-hand operand of a constraint is a literal value in the original
+** SQL statement. If the right-hand operand is an expression or a reference
+** to some other column or a [host parameter], then sqlite3_vtab_rhs_value()
+** will probably return [SQLITE_NOTFOUND].
+**
+** ^(Some constraints, such as [SQLITE_INDEX_CONSTRAINT_ISNULL] and
+** [SQLITE_INDEX_CONSTRAINT_ISNOTNULL], have no right-hand operand. For such
+** constraints, sqlite3_vtab_rhs_value() always returns SQLITE_NOTFOUND.)^
+**
+** ^The [sqlite3_value] object returned in *V is a protected sqlite3_value
+** and remains valid for the duration of the xBestIndex method call.
+** ^When xBestIndex returns, the sqlite3_value object returned by
+** sqlite3_vtab_rhs_value() is automatically deallocated.
+**
+** The "_rhs_" in the name of this routine is an abbreviation for
+** "Right-Hand Side".
+*/
+SQLITE_API int sqlite3_vtab_rhs_value(sqlite3_index_info*, int, sqlite3_value **ppVal);
/*
** CAPI3REF: Conflict resolution modes
** KEYWORDS: {conflict resolution mode}
**
** These constants are returned by [sqlite3_vtab_on_conflict()] to
-** inform a [virtual table] implementation what the [ON CONFLICT] mode
-** is for the SQL statement being evaluated.
+** inform a [virtual table] implementation of the [ON CONFLICT] mode
+** for the SQL statement being evaluated.
**
** Note that the [SQLITE_IGNORE] constant is also used as a potential
** return value from the [sqlite3_set_authorizer()] callback and that
@@ -9870,39 +10959,55 @@ SQLITE_API SQLITE_EXPERIMENTAL const char *sqlite3_vtab_collation(sqlite3_index_
** managed by the prepared statement S and will be automatically freed when
** S is finalized.
**
+** Not all values are available for all query elements. When a value is
+** not available, the output variable is set to -1 if the value is numeric,
+** or to NULL if it is a string (SQLITE_SCANSTAT_NAME).
+**
**
** [[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,
+** iteration of the X-th loop. If the query planner's estimate was accurate,
** then this value will approximate the quotient NVISIT/NLOOP and the
** product of this value for all prior loops with the same SELECTID will
-** be the NLOOP value for the current loop.
+** 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.
+** 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
-** "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
-** of an [EXPLAIN QUERY PLAN] query.
+** description for the X-th loop.
+**
+** [[SQLITE_SCANSTAT_SELECTID]] - SQLITE_SCANSTAT_SELECTID
+** - ^The "int" variable pointed to by the V parameter will be set to the
+** id for the X-th query plan element. The id value is unique within the
+** statement. The select-id is the same value as is output in the first
+** column of an [EXPLAIN QUERY PLAN] query.
+**
+** [[SQLITE_SCANSTAT_PARENTID]] - SQLITE_SCANSTAT_PARENTID
+** - The "int" variable pointed to by the V parameter will be set to the
+** id of the parent of the current query element, if applicable, or
+** to zero if the query element has no parent. This is the same value as
+** returned in the second column of an [EXPLAIN QUERY PLAN] query.
+**
+** [[SQLITE_SCANSTAT_NCYCLE]] - SQLITE_SCANSTAT_NCYCLE
+** - The sqlite3_int64 output value is set to the number of cycles,
+** according to the processor time-stamp counter, that elapsed while the
+** query element was being processed. This value is not available for
+** all query elements - if it is unavailable the output variable is
+** set to -1.
**
*/
#define SQLITE_SCANSTAT_NLOOP 0
@@ -9911,12 +11016,14 @@ SQLITE_API SQLITE_EXPERIMENTAL const char *sqlite3_vtab_collation(sqlite3_index_
#define SQLITE_SCANSTAT_NAME 3
#define SQLITE_SCANSTAT_EXPLAIN 4
#define SQLITE_SCANSTAT_SELECTID 5
+#define SQLITE_SCANSTAT_PARENTID 6
+#define SQLITE_SCANSTAT_NCYCLE 7
/*
** CAPI3REF: Prepared Statement Scan Status
** METHOD: sqlite3_stmt
**
-** This interface returns information about the predicted and measured
+** These interfaces return information about the predicted and measured
** performance for pStmt. Advanced applications can use this
** interface to compare the predicted and the measured performance and
** issue warnings and/or rerun [ANALYZE] if discrepancies are found.
@@ -9927,28 +11034,48 @@ SQLITE_API SQLITE_EXPERIMENTAL const char *sqlite3_vtab_collation(sqlite3_index_
**
** The "iScanStatusOp" parameter determines which status information to return.
** The "iScanStatusOp" must be one of the [scanstatus options] or the behavior
-** of this interface is undefined.
-** ^The requested measurement is written into a variable pointed to by
-** the "pOut" parameter.
-** Parameter "idx" identifies the specific loop to retrieve statistics for.
-** Loops are numbered starting from zero. ^If idx is out of range - less than
-** zero or greater than or equal to the total number of loops used to implement
-** the statement - a non-zero value is returned and the variable that pOut
-** points to is unchanged.
-**
-** ^Statistics might not be available for all loops in all statements. ^In cases
-** where there exist loops with no available statistics, this function behaves
-** as if the loop did not exist - it returns non-zero and leave the variable
-** that pOut points to unchanged.
-**
-** See also: [sqlite3_stmt_scanstatus_reset()]
+** of this interface is undefined. ^The requested measurement is written into
+** a variable pointed to by the "pOut" parameter.
+**
+** The "flags" parameter must be passed a mask of flags. At present only
+** one flag is defined - [SQLITE_SCANSTAT_COMPLEX]. If SQLITE_SCANSTAT_COMPLEX
+** is specified, then status information is available for all elements
+** of a query plan that are reported by "[EXPLAIN QUERY PLAN]" output. If
+** SQLITE_SCANSTAT_COMPLEX is not specified, then only query plan elements
+** that correspond to query loops (the "SCAN..." and "SEARCH..." elements of
+** the EXPLAIN QUERY PLAN output) are available. Invoking API
+** sqlite3_stmt_scanstatus() is equivalent to calling
+** sqlite3_stmt_scanstatus_v2() with a zeroed flags parameter.
+**
+** Parameter "idx" identifies the specific query element to retrieve statistics
+** for. Query elements are numbered starting from zero. A value of -1 may
+** retrieve statistics for the entire query. ^If idx is out of range
+** - less than -1 or greater than or equal to the total number of query
+** elements used to implement the statement - a non-zero value is returned and
+** the variable that pOut points to is unchanged.
+**
+** See also: [sqlite3_stmt_scanstatus_reset()] and the
+** [nexec and ncycle] columns of the [bytecode virtual table].
*/
SQLITE_API int sqlite3_stmt_scanstatus(
sqlite3_stmt *pStmt, /* Prepared statement for which info desired */
int idx, /* Index of loop to report on */
int iScanStatusOp, /* Information desired. SQLITE_SCANSTAT_* */
void *pOut /* Result written here */
-);
+);
+SQLITE_API int sqlite3_stmt_scanstatus_v2(
+ sqlite3_stmt *pStmt, /* Prepared statement for which info desired */
+ int idx, /* Index of loop to report on */
+ int iScanStatusOp, /* Information desired. SQLITE_SCANSTAT_* */
+ int flags, /* Mask of flags defined below */
+ void *pOut /* Result written here */
+);
+
+/*
+** CAPI3REF: Prepared Statement Scan Status
+** KEYWORDS: {scan status flags}
+*/
+#define SQLITE_SCANSTAT_COMPLEX 0x0001
/*
** CAPI3REF: Zero Scan-Status Counters
@@ -9963,18 +11090,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
+** [sqlite3_db_cacheflush(D)] interface is invoked, any dirty
+** 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
@@ -9995,6 +11123,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.
@@ -10012,7 +11141,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.
@@ -10021,21 +11150,25 @@ 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_hook(D,C,P) function returns the P argument from
+** the previous call on the same [database connection] D, or NULL for
+** the first call on D.
**
** The [sqlite3_preupdate_old()], [sqlite3_preupdate_new()],
** [sqlite3_preupdate_count()], and [sqlite3_preupdate_depth()] interfaces
@@ -10069,10 +11202,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, because
+** the new values are not yet available. In this case, when a
+** callback made with op==SQLITE_DELETE is actually 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)
@@ -10093,17 +11235,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*);
@@ -10141,12 +11285,20 @@ 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.
+**
+** If a read-transaction is opened by this function, then it is guaranteed
+** that the returned snapshot object may not be invalidated by a database
+** writer or checkpointer until after the read-transaction is closed. This
+** is not guaranteed if a read-transaction is already open when this
+** function is called. In that case, any subsequent write or checkpoint
+** operation on the database may invalidate the returned snapshot handle,
+** even while the read-transaction remains open.
**
** 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].
@@ -10158,13 +11310,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
@@ -10174,7 +11326,7 @@ typedef struct sqlite3_snapshot {
** The [sqlite3_snapshot_get()] interface is only available when the
** [SQLITE_ENABLE_SNAPSHOT] compile-time option is used.
*/
-SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_get(
+SQLITE_API int sqlite3_snapshot_get(
sqlite3 *db,
const char *zSchema,
sqlite3_snapshot **ppSnapshot
@@ -10184,38 +11336,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.)
@@ -10223,7 +11375,7 @@ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_get(
** The [sqlite3_snapshot_open()] interface is only available when the
** [SQLITE_ENABLE_SNAPSHOT] compile-time option is used.
*/
-SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_open(
+SQLITE_API int sqlite3_snapshot_open(
sqlite3 *db,
const char *zSchema,
sqlite3_snapshot *pSnapshot
@@ -10240,24 +11392,24 @@ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_open(
** The [sqlite3_snapshot_free()] interface is only available when the
** [SQLITE_ENABLE_SNAPSHOT] compile-time option is used.
*/
-SQLITE_API SQLITE_EXPERIMENTAL void sqlite3_snapshot_free(sqlite3_snapshot*);
+SQLITE_API void sqlite3_snapshot_free(sqlite3_snapshot*);
/*
** CAPI3REF: Compare the ages of two snapshot handles.
** 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
@@ -10267,7 +11419,7 @@ SQLITE_API SQLITE_EXPERIMENTAL void sqlite3_snapshot_free(sqlite3_snapshot*);
** This interface is only available if SQLite is compiled with the
** [SQLITE_ENABLE_SNAPSHOT] option.
*/
-SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_cmp(
+SQLITE_API int sqlite3_snapshot_cmp(
sqlite3_snapshot *p1,
sqlite3_snapshot *p2
);
@@ -10295,20 +11447,21 @@ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_cmp(
** This interface is only available if SQLite is compiled with the
** [SQLITE_ENABLE_SNAPSHOT] option.
*/
-SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_recover(sqlite3 *db, const char *zDb);
+SQLITE_API int sqlite3_snapshot_recover(sqlite3 *db, const char *zDb);
/*
** CAPI3REF: Serialize a database
**
-** The sqlite3_serialize(D,S,P,F) interface returns a pointer to memory
-** that is a serialization of the S database on [database connection] D.
+** The sqlite3_serialize(D,S,P,F) interface returns a pointer to
+** memory that is a serialization of the S database on
+** [database connection] D. If S is a NULL pointer, the main database is used.
** If P is not a NULL pointer, then the size of the database in bytes
** is written into *P.
**
** For an ordinary on-disk database file, the serialization is just a
** copy of the disk file. For an in-memory database or a "TEMP" database,
** the serialization is the same sequence of bytes which would be written
-** to disk if that database where backed up to disk.
+** to disk if that database were backed up to disk.
**
** The usual case is that sqlite3_serialize() copies the serialization of
** the database into memory obtained from [sqlite3_malloc64()] and returns
@@ -10317,21 +11470,28 @@ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_recover(sqlite3 *db, const c
** contains the SQLITE_SERIALIZE_NOCOPY bit, then no memory allocations
** are made, and the sqlite3_serialize() function will return a pointer
** to the contiguous memory representation of the database that SQLite
-** is currently using for that database, or NULL if the no such contiguous
+** is currently using for that database, or NULL if no such contiguous
** memory representation of the database exists. A contiguous memory
** 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.
**
+** After the call, if the SQLITE_SERIALIZE_NOCOPY bit had been set,
+** the returned buffer content will remain accessible and unchanged
+** until either the next write operation on the connection or when
+** the connection is closed, and applications must not modify the
+** buffer. If the bit had been clear, the returned buffer will not
+** be accessed by SQLite after the call.
+**
** A call to sqlite3_serialize(D,S,P,F) might return NULL even if the
** 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 */
@@ -10359,14 +11519,15 @@ 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
-** the buffer P, which might be larger than N. If M is larger than N, and
-** the SQLITE_DESERIALIZE_READONLY bit is not set in F, then SQLite is
-** permitted to add content to the in-memory database as long as the total
-** size does not exceed M bytes.
+** reopen S as an in-memory database based on the serialization
+** contained in P. If S is a NULL pointer, the main database is
+** used. The serialized database P is N bytes in size. M is the size
+** of the buffer P, which might be larger than N. If M is larger than
+** N, and the SQLITE_DESERIALIZE_READONLY bit is not set in F, then
+** SQLite is permitted to add content to the in-memory database as
+** long as the total size does not exceed M bytes.
**
** If the SQLITE_DESERIALIZE_FREEONCLOSE bit is set in F, then SQLite will
** invoke sqlite3_free() on the serialization buffer when the database
@@ -10374,22 +11535,36 @@ SQLITE_API unsigned char *sqlite3_serialize(
** SQLite will try to increase the buffer size using sqlite3_realloc64()
** if writes on the database cause it to grow larger than M bytes.
**
+** Applications must not modify the buffer P or invalidate it before
+** the database connection D is closed.
+**
** The sqlite3_deserialize() interface will fail with SQLITE_BUSY if the
** 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
+** It is not possible to deserialize into the TEMP database. If the
+** S argument to sqlite3_deserialize(D,S,P,N,M,F) is "temp" then the
+** function returns SQLITE_ERROR.
+**
+** The deserialized database should not be in [WAL mode]. If the database
+** is in WAL mode, then any attempt to use the database file will result
+** in an [SQLITE_CANTOPEN] error. The application can set the
+** [file format version numbers] (bytes 18 and 19) of the input database P
+** to 0x01 prior to invoking sqlite3_deserialize(D,S,P,N,M,F) to force the
+** database file into rollback mode and work around this limitation.
+**
+** 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 */
const char *zSchema, /* Which DB to reopen with the deserialization */
unsigned char *pData, /* The serialized database content */
- sqlite3_int64 szDb, /* Number bytes in the deserialization */
+ sqlite3_int64 szDb, /* Number of bytes in the deserialization */
sqlite3_int64 szBuf, /* Total size of buffer pData[] */
unsigned mFlags /* Zero or more SQLITE_DESERIALIZE_* flags */
);
@@ -10397,7 +11572,7 @@ SQLITE_API int sqlite3_deserialize(
/*
** CAPI3REF: Flags for sqlite3_deserialize()
**
-** The following are allowed values for 6th argument (the F argument) to
+** The following are allowed values for the 6th argument (the F argument) to
** the [sqlite3_deserialize(D,S,P,N,M,F)] interface.
**
** The SQLITE_DESERIALIZE_FREEONCLOSE means that the database serialization
@@ -10419,6 +11594,77 @@ SQLITE_API int sqlite3_deserialize(
#define SQLITE_DESERIALIZE_RESIZEABLE 2 /* Resize using sqlite3_realloc64() */
#define SQLITE_DESERIALIZE_READONLY 4 /* Database is read-only */
+/*
+** CAPI3REF: Bind array values to the CARRAY table-valued function
+**
+** The sqlite3_carray_bind_v2(S,I,P,N,F,X,D) interface binds an array value to
+** parameter that is the first argument of the [carray() table-valued function].
+** The S parameter is a pointer to the [prepared statement] that uses the
+** carray() functions. I is the parameter index to be bound. I must be the
+** index of the parameter that is the first argument to the carray()
+** table-valued function. P is a pointer to the array to be bound, and N
+** is the number of elements in the array. The F argument is one of
+** constants [SQLITE_CARRAY_INT32], [SQLITE_CARRAY_INT64],
+** [SQLITE_CARRAY_DOUBLE], [SQLITE_CARRAY_TEXT],
+** or [SQLITE_CARRAY_BLOB] to indicate the datatype of the array P.
+**
+** If the X argument is not a NULL pointer or one of the special
+** values [SQLITE_STATIC] or [SQLITE_TRANSIENT], then SQLite will invoke
+** the function X with argument D when it is finished using the data in P.
+** The call to X(D) is a destructor for the array P. The destructor X(D)
+** is invoked even if the call to sqlite3_carray_bind_v2() fails. If the X
+** parameter is the special-case value [SQLITE_STATIC], then SQLite assumes
+** that the data static and the destructor is never invoked. If the X
+** parameter is the special-case value [SQLITE_TRANSIENT], then
+** sqlite3_carray_bind_v2() makes its own private copy of the data prior
+** to returning and never invokes the destructor X.
+**
+** The sqlite3_carray_bind() function works the same as sqlite3_carray_bind_v2()
+** with a D parameter set to P. In other words,
+** sqlite3_carray_bind(S,I,P,N,F,X) is same as
+** sqlite3_carray_bind_v2(S,I,P,N,F,X,P).
+*/
+SQLITE_API int sqlite3_carray_bind_v2(
+ sqlite3_stmt *pStmt, /* Statement to be bound */
+ int i, /* Parameter index */
+ void *aData, /* Pointer to array data */
+ int nData, /* Number of data elements */
+ int mFlags, /* CARRAY flags */
+ void (*xDel)(void*), /* Destructor for aData */
+ void *pDel /* Optional argument to xDel() */
+);
+SQLITE_API int sqlite3_carray_bind(
+ sqlite3_stmt *pStmt, /* Statement to be bound */
+ int i, /* Parameter index */
+ void *aData, /* Pointer to array data */
+ int nData, /* Number of data elements */
+ int mFlags, /* CARRAY flags */
+ void (*xDel)(void*) /* Destructor for aData */
+);
+
+/*
+** CAPI3REF: Datatypes for the CARRAY table-valued function
+**
+** The fifth argument to the [sqlite3_carray_bind()] interface musts be
+** one of the following constants, to specify the datatype of the array
+** that is being bound into the [carray table-valued function].
+*/
+#define SQLITE_CARRAY_INT32 0 /* Data is 32-bit signed integers */
+#define SQLITE_CARRAY_INT64 1 /* Data is 64-bit signed integers */
+#define SQLITE_CARRAY_DOUBLE 2 /* Data is doubles */
+#define SQLITE_CARRAY_TEXT 3 /* Data is char* */
+#define SQLITE_CARRAY_BLOB 4 /* Data is struct iovec */
+
+/*
+** Versions of the above #defines that omit the initial SQLITE_, for
+** legacy compatibility.
+*/
+#define CARRAY_INT32 0 /* Data is 32-bit signed integers */
+#define CARRAY_INT64 1 /* Data is 64-bit signed integers */
+#define CARRAY_DOUBLE 2 /* Data is doubles */
+#define CARRAY_TEXT 3 /* Data is char* */
+#define CARRAY_BLOB 4 /* Data is struct iovec */
+
/*
** Undo the hack that converts floating point types to integer for
** builds on processors without floating point support.
@@ -10427,10 +11673,21 @@ SQLITE_API int sqlite3_deserialize(
# undef double
#endif
+#if defined(__wasi__)
+# undef SQLITE_WASI
+# define SQLITE_WASI 1
+# ifndef SQLITE_OMIT_LOAD_EXTENSION
+# define SQLITE_OMIT_LOAD_EXTENSION
+# endif
+# ifndef SQLITE_THREADSAFE
+# define SQLITE_THREADSAFE 0
+# endif
+#endif
+
#if 0
} /* End of the 'extern "C"' block */
#endif
-#endif /* SQLITE3_H */
+/* #endif for SQLITE3_H will be added by mksqlite3.tcl */
/******** Begin file sqlite3rtree.h *********/
/*
@@ -10493,7 +11750,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 ...)
@@ -10508,7 +11765,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().
**
@@ -10603,7 +11860,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
@@ -10621,17 +11878,62 @@ 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);
+/*
+** CAPI3REF: Configure 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 values for the second parameter are
+** [SQLITE_SESSION_OBJCONFIG_SIZE] and [SQLITE_SESSION_OBJCONFIG_ROWID].
+**
+*/
+SQLITE_API int sqlite3session_object_config(sqlite3_session*, int op, void *pArg);
+
+/*
+** CAPI3REF: Options for sqlite3session_object_config
+**
+** The following values may passed as the the 2nd 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_SESSION_OBJCONFIG_ROWID
+** This option is used to set, clear or query the flag that enables
+** collection of data for tables with no explicit PRIMARY KEY.
+**
+** Normally, tables with no explicit PRIMARY KEY are simply ignored
+** by the sessions module. However, if this flag is set, it behaves
+** as if such tables have a column "_rowid_ INTEGER PRIMARY KEY" inserted
+** as their leftmost columns.
+**
+** It is an error (SQLITE_MISUSE) to attempt to modify this setting after
+** the first table has been attached to the session object.
+*/
+#define SQLITE_SESSION_OBJCONFIG_SIZE 1
+#define SQLITE_SESSION_OBJCONFIG_ROWID 2
/*
** CAPI3REF: Enable Or Disable A Session Object
@@ -10645,10 +11947,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);
@@ -10663,7 +11965,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.
**
**
@@ -10675,10 +11977,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);
@@ -10688,20 +11990,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.
@@ -10709,29 +12011,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.
@@ -10750,10 +12052,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(
@@ -10769,9 +12071,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.
@@ -10786,7 +12088,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
@@ -10839,14 +12141,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.
@@ -10854,7 +12156,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.
@@ -10863,12 +12165,13 @@ 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
-** 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.
+** Or, if one field of a row is updated while a session is enabled, and
+** then another field of the same row is updated while the session is disabled,
+** the resulting changeset will contain an UPDATE change that updates both
+** fields.
*/
SQLITE_API int sqlite3session_changeset(
sqlite3_session *pSession, /* Session object */
@@ -10876,6 +12179,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
@@ -10887,7 +12206,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:
**
@@ -10903,33 +12222,34 @@ 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.
+** Unless the call to this function is a no-op as described above, it is 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().
*/
@@ -10948,19 +12268,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.
@@ -10979,22 +12299,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.
@@ -11002,7 +12330,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:
**
**
@@ -11019,12 +12347,12 @@ 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
@@ -11052,7 +12380,7 @@ SQLITE_API int sqlite3changeset_start_v2(
** The following flags may passed via the 4th parameter to
** [sqlite3changeset_start_v2] and [sqlite3changeset_start_v2_strm]:
**
-** - SQLITE_CHANGESETAPPLY_INVERT
-
+**
- SQLITE_CHANGESETSTART_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.
@@ -11064,7 +12392,7 @@ SQLITE_API int sqlite3changeset_start_v2(
** 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.
@@ -11075,12 +12403,12 @@ SQLITE_API int sqlite3changeset_start_v2(
** 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);
@@ -11095,18 +12423,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
-** pbIndirect 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
@@ -11159,7 +12492,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.
@@ -11169,9 +12502,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
@@ -11190,7 +12523,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.
@@ -11200,12 +12533,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
@@ -11232,7 +12565,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.
**
@@ -11276,7 +12609,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):
@@ -11288,7 +12621,7 @@ SQLITE_API int sqlite3changeset_fk_conflicts(
** }
** rc = sqlite3changeset_finalize();
** if( rc!=SQLITE_OK ){
-** // An error has occurred
+** // An error has occurred
** }
**
*/
@@ -11316,7 +12649,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
@@ -11330,11 +12663,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:
**
@@ -11362,11 +12695,10 @@ SQLITE_API int sqlite3changeset_concat(
void **ppOut /* OUT: Buffer containing output changeset */
);
-
/*
** 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;
@@ -11382,7 +12714,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.
**
@@ -11394,7 +12726,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().
@@ -11403,18 +12735,50 @@ 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().
*/
SQLITE_API int sqlite3changegroup_new(sqlite3_changegroup **pp);
+/*
+** CAPI3REF: Add a Schema to a Changegroup
+** METHOD: sqlite3_changegroup_schema
+**
+** This method may be used to optionally enforce the rule that the changesets
+** added to the changegroup handle must match the schema of database zDb
+** ("main", "temp", or the name of an attached database). If
+** sqlite3changegroup_add() is called to add a changeset that is not compatible
+** with the configured schema, SQLITE_SCHEMA is returned and the changegroup
+** object is left in an undefined state.
+**
+** A changeset schema is considered compatible with the database schema in
+** the same way as for sqlite3changeset_apply(). Specifically, for each
+** table in the changeset, there exists a database table with:
+**
+**
+** - The name identified by the changeset, and
+**
- at least as many columns as recorded in the changeset, and
+**
- the primary key columns in the same position as recorded in
+** the changeset.
+**
+**
+** The output of the changegroup object always has the same schema as the
+** database nominated using this function. In cases where changesets passed
+** to sqlite3changegroup_add() have fewer columns than the corresponding table
+** in the database schema, these are filled in using the default column
+** values from the database schema. This makes it possible to combined
+** changesets that have different numbers of columns for a single table
+** within a changegroup, provided that they are otherwise compatible.
+*/
+SQLITE_API int sqlite3changegroup_schema(sqlite3_changegroup*, sqlite3*, const char *zDb);
+
/*
** CAPI3REF: Add A Changeset To A Changegroup
** 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
@@ -11441,7 +12805,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 |
@@ -11452,17 +12816,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
@@ -11477,16 +12841,45 @@ SQLITE_API int sqlite3changegroup_new(sqlite3_changegroup **pp);
** If the new changeset contains changes to a table that is already present
** in the changegroup, then the number of columns and the position of the
** primary key columns for the table must be consistent. If this is not the
-** 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.
+** case, this function fails with SQLITE_SCHEMA. Except, if the changegroup
+** object has been configured with a database schema using the
+** sqlite3changegroup_schema() API, then it is possible to combine changesets
+** with different numbers of columns for a single table, provided that
+** they are otherwise compatible.
+**
+** 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.
**
-** If no error occurs, SQLITE_OK is returned.
+** 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.
*/
SQLITE_API int sqlite3changegroup_add(sqlite3_changegroup*, int nData, void *pData);
+/*
+** CAPI3REF: Add A Single Change To A Changegroup
+** METHOD: sqlite3_changegroup
+**
+** This function adds the single change currently indicated by the iterator
+** passed as the second argument to the changegroup object. The rules for
+** adding the change are just as described for [sqlite3changegroup_add()].
+**
+** If the change is successfully added to the changegroup, SQLITE_OK is
+** returned. Otherwise, an SQLite error code is returned.
+**
+** The iterator must point to a valid entry when this function is called.
+** If it does not, SQLITE_ERROR is returned and no change is added to the
+** changegroup. Additionally, the iterator must not have been opened with
+** the SQLITE_CHANGESETAPPLY_INVERT flag. In this case SQLITE_ERROR is also
+** returned.
+*/
+SQLITE_API int sqlite3changegroup_add_change(
+ sqlite3_changegroup*,
+ sqlite3_changeset_iter*
+);
+
+
+
/*
** CAPI3REF: Obtain A Composite Changeset From A Changegroup
** METHOD: sqlite3_changegroup
@@ -11507,7 +12900,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().
@@ -11529,27 +12922,45 @@ 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.
+**
+** 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
+** SQLite error code returned. Additionally, starting with version 3.51.0,
+** an error code and error message that may be accessed using the
+** [sqlite3_errcode()] and [sqlite3_errmsg()] APIs are left in the database
+** handle.
**
** 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
-** change in the changeset, the filter callback is invoked with
-** the table name as the second argument, and a copy of the context pointer
-** passed as the sixth argument as the first. If the "filter callback"
-** returns zero, then no attempt is made to apply any changes to the table.
-** 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
+** callback". This may be passed NULL, in which case all changes in the
+** changeset are applied to the database. For sqlite3changeset_apply() and
+** sqlite3_changeset_apply_v2(), if it is not NULL, then it is invoked once
+** for each table affected by at least one change in the changeset. In this
+** case the table name is passed as the second argument, and a copy of
+** the context pointer passed as the sixth argument to apply() or apply_v2()
+** as the first. If the "filter callback" returns zero, then no attempt is
+** made to apply any changes to the table. Otherwise, if the return value is
+** non-zero, all changes related to the table are attempted.
+**
+** For sqlite3_changeset_apply_v3(), the xFilter callback is invoked once
+** per change. The second argument in this case is an sqlite3_changeset_iter
+** that may be queried using the usual APIs for the details of the current
+** change. If the "filter callback" returns zero in this case, then no attempt
+** is made to apply the current change. If it returns non-zero, the change
+** is applied.
+**
+** 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.
**
**
@@ -11558,35 +12969,35 @@ 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
-** each type of change is below.
+** For each change for which there is a compatible table, an attempt is made
+** to modify the table contents according to each UPDATE, INSERT or DELETE
+** change that is not excluded by a filter callback. 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
** of passing anything other than a valid function pointer as the xConflict
** 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
@@ -11615,22 +13026,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.
**
@@ -11646,28 +13057,22 @@ 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
-** 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
@@ -11714,6 +13119,23 @@ SQLITE_API int sqlite3changeset_apply_v2(
void **ppRebase, int *pnRebase, /* OUT: Rebase data */
int flags /* SESSION_CHANGESETAPPLY_* flags */
);
+SQLITE_API int sqlite3changeset_apply_v3(
+ sqlite3 *db, /* Apply change to "main" db of this handle */
+ int nChangeset, /* Size of changeset in bytes */
+ void *pChangeset, /* Changeset blob */
+ int(*xFilter)(
+ void *pCtx, /* Copy of sixth arg to _apply() */
+ sqlite3_changeset_iter *p /* Handle describing change */
+ ),
+ int(*xConflict)(
+ void *pCtx, /* Copy of sixth arg to _apply() */
+ int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */
+ sqlite3_changeset_iter *p /* Handle describing change and conflict */
+ ),
+ void *pCtx, /* First argument passed to xConflict */
+ void **ppRebase, int *pnRebase, /* OUT: Rebase data */
+ int flags /* SESSION_CHANGESETAPPLY_* flags */
+);
/*
** CAPI3REF: Flags for sqlite3changeset_apply_v2
@@ -11728,18 +13150,51 @@ 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.
+**
+**
- SQLITE_CHANGESETAPPLY_IGNORENOOP
-
+** Do not invoke the conflict handler callback for any changes that
+** would not actually modify the database even if they were applied.
+** Specifically, this means that the conflict handler is not invoked
+** for:
+**
+** - a delete change if the row being deleted cannot be found,
+**
- an update change if the modified fields are already set to
+** their new values in the conflicting row, or
+**
- an insert change if all fields of the conflicting row match
+** the row being inserted.
+**
+**
+** - SQLITE_CHANGESETAPPLY_FKNOACTION
-
+** If this flag it set, then all foreign key constraints in the target
+** database behave as if they were declared with "ON UPDATE NO ACTION ON
+** DELETE NO ACTION", even if they are actually CASCADE, RESTRICT, SET NULL
+** or SET DEFAULT.
+**
+**
- SQLITE_CHANGESETAPPLY_NOUPDATELOOP
-
+** Sometimes, a changeset contains two or more update statements such that
+** although after applying all updates the database will contain no
+** constraint violations, no single update can be applied before the others.
+** The simplest example of this is a pair of UPDATEs that have "swapped"
+** two column values with a UNIQUE constraint.
+**
+** Usually, sqlite3changeset_apply() and similar functions work hard to try
+** to find a way to apply such a changeset. However, if this flag is set,
+** then all such updates are considered CONSTRAINT conflicts.
*/
#define SQLITE_CHANGESETAPPLY_NOSAVEPOINT 0x0001
#define SQLITE_CHANGESETAPPLY_INVERT 0x0002
+#define SQLITE_CHANGESETAPPLY_IGNORENOOP 0x0004
+#define SQLITE_CHANGESETAPPLY_FKNOACTION 0x0008
+#define SQLITE_CHANGESETAPPLY_NOUPDATELOOP 0x0010
-/*
+/*
** CAPI3REF: Constants Passed To The Conflict Handler
**
** Values that may be passed as the second argument to a conflict-handler.
@@ -11748,32 +13203,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
@@ -11783,12 +13238,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.
**
@@ -11800,7 +13255,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.
@@ -11808,13 +13263,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
@@ -11827,7 +13282,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.
**
*/
@@ -11835,20 +13290,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)":
@@ -11867,7 +13322,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.
@@ -11891,12 +13346,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:
**
@@ -11909,10 +13364,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
@@ -11920,7 +13375,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().
@@ -11941,8 +13396,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);
@@ -11956,9 +13411,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
@@ -11966,9 +13421,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 changeset 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)
@@ -11976,8 +13431,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
);
/*
@@ -11988,30 +13443,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.
**
@@ -12033,12 +13488,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.
@@ -12046,7 +13501,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)
@@ -12076,7 +13531,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.
*/
@@ -12112,6 +13567,23 @@ SQLITE_API int sqlite3changeset_apply_v2_strm(
void **ppRebase, int *pnRebase,
int flags
);
+SQLITE_API int sqlite3changeset_apply_v3_strm(
+ sqlite3 *db, /* Apply change to "main" db of this handle */
+ int (*xInput)(void *pIn, void *pData, int *pnData), /* Input function */
+ void *pIn, /* First arg for xInput */
+ int(*xFilter)(
+ void *pCtx, /* Copy of sixth arg to _apply() */
+ sqlite3_changeset_iter *p
+ ),
+ int(*xConflict)(
+ void *pCtx, /* Copy of sixth arg to _apply() */
+ int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */
+ sqlite3_changeset_iter *p /* Handle describing change and conflict */
+ ),
+ void *pCtx, /* First argument passed to xConflict */
+ void **ppRebase, int *pnRebase,
+ int flags
+);
SQLITE_API int sqlite3changeset_concat_strm(
int (*xInputA)(void *pIn, void *pData, int *pnData),
void *pInA,
@@ -12147,12 +13619,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(
@@ -12167,16 +13639,16 @@ SQLITE_API int sqlite3rebaser_rebase_strm(
** 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
+** 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.
+** 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
+** 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.
@@ -12203,6 +13675,232 @@ SQLITE_API int sqlite3session_config(int op, void *pArg);
*/
#define SQLITE_SESSION_CONFIG_STRMSIZE 1
+/*
+** CAPI3REF: Configure a changegroup object
+**
+** Configure the changegroup object passed as the first argument.
+** At present the only valid value for the second parameter is
+** [SQLITE_CHANGEGROUP_CONFIG_PATCHSET].
+*/
+SQLITE_API int sqlite3changegroup_config(sqlite3_changegroup*, int, void *pArg);
+
+/*
+** CAPI3REF: Options for sqlite3changegroup_config().
+**
+** The following values may be passed as the 2nd parameter to
+** sqlite3changegroup_config().
+**
+** - SQLITE_CHANGEGROUP_CONFIG_PATCHSET
-
+** A changegroup object generates either a changeset or patchset. Usually,
+** this is determined by whether the first call to sqlite3changegroup_add()
+** is passed a changeset or a patchset. Or, if the first changes are added
+** to the changegroup object using the sqlite3changegroup_change_xxx()
+** APIs, then this option may be used to configure whether the changegroup
+** object generates a changeset or patchset.
+**
+** When this option is invoked, parameter pArg must point to a value of
+** type int. If the changegroup currently contains zero changes, and the
+** value of the int variable is zero or greater than zero, then the
+** changegroup is configured to generate a changeset or patchset,
+** respectively. It is a no-op, not an error, if the changegroup is not
+** configured because it has already started accumulating changes.
+**
+** Before returning, the int variable is set to 0 if the changegroup is
+** configured to generate a changeset, or 1 if it is configured to generate
+** a patchset.
+*/
+#define SQLITE_CHANGEGROUP_CONFIG_PATCHSET 1
+
+
+/*
+** CAPI3REF: Begin adding a change to a changegroup
+**
+** This API is used, in concert with other sqlite3changegroup_change_xxx()
+** APIs, to add changes to a changegroup object one at a time. To add a
+** single change, the caller must:
+**
+** 1. Invoke sqlite3changegroup_change_begin() to indicate the type of
+** change (INSERT, UPDATE or DELETE), the affected table and whether
+** or not the change should be marked as indirect.
+**
+** 2. Invoke sqlite3changegroup_change_int64() or one of the other four
+** value functions - _null(), _double(), _text() or _blob() - one or
+** more times to specify old.* and new.* values for the change being
+** constructed.
+**
+** 3. Invoke sqlite3changegroup_change_finish() to either finish adding
+** the change to the group, or to discard the change altogether.
+**
+** The first argument to this function must be a pointer to the existing
+** changegroup object that the change will be added to. The second argument
+** must be SQLITE_INSERT, SQLITE_UPDATE or SQLITE_DELETE. The third is the
+** name of the table that the change affects, and the fourth is a boolean
+** flag specifying whether the change should be marked as "indirect" (if
+** bIndirect is non-zero) or not indirect (if bIndirect is zero).
+**
+** Following a successful call to this function, this function may not be
+** called again on the same changegroup object until after
+** sqlite3changegroup_change_finish() has been called. Doing so is an
+** SQLITE_MISUSE error.
+**
+** The changegroup object passed as the first argument must be already
+** configured with schema data for the specified table. It may be configured
+** either by calling sqlite3changegroup_schema() with a database that contains
+** the table, or sqlite3changegroup_add() with a changeset that contains the
+** table. If the changegroup object has not been configured with a schema for
+** the specified table when this function is called, SQLITE_ERROR is returned.
+**
+** If successful, SQLITE_OK is returned. Otherwise, if an error occurs, an
+** SQLite error code is returned. In this case, if argument pzErr is non-NULL,
+** then (*pzErr) may be set to point to a buffer containing a utf-8 formated,
+** nul-terminated, English language error message. It is the responsibility
+** of the caller to eventually free this buffer using sqlite3_free().
+*/
+SQLITE_API int sqlite3changegroup_change_begin(
+ sqlite3_changegroup*,
+ int eOp,
+ const char *zTab,
+ int bIndirect,
+ char **pzErr
+);
+
+/*
+** CAPI3REF: Add a 64-bit integer to a changegroup
+**
+** This function may only be called between a successful call to
+** sqlite3changegroup_change_begin() and its matching
+** sqlite3changegroup_change_finish() call. If it is called at any
+** other time, it is an SQLITE_MISUSE error. Calling this function
+** specifies a 64-bit integer value to be used in the change currently being
+** added to the changegroup object passed as the first argument.
+**
+** The second parameter, bNew, specifies whether the value is to be part of
+** the new.* (if bNew is non-zero) or old.* (if bNew is zero) record of
+** the change under construction. If this does not match the type of change
+** specified by the preceding call to sqlite3changegroup_change_begin() (i.e.
+** an old.* value for an SQLITE_INSERT change, or a new.* value for an
+** SQLITE_DELETE), then SQLITE_ERROR is returned.
+**
+** The third parameter specifies the column of the old.* or new.* record that
+** the value will be a part of. If the specified table has an explicit primary
+** key, then this is the index of the table column, numbered from 0 in the order
+** specified within the CREATE TABLE statement. Or, if the table uses an
+** implicit rowid key, then the column 0 is the rowid and the explicit columns
+** are numbered starting from 1. If the iCol parameter is less than 0 or greater
+** than the index of the last column in the table, SQLITE_RANGE is returned.
+**
+** The fourth parameter is the integer value to use as part of the old.* or
+** new.* record.
+**
+** If this call is successful, SQLITE_OK is returned. Otherwise, if an
+** error occurs, an SQLite error code is returned.
+*/
+SQLITE_API int sqlite3changegroup_change_int64(
+ sqlite3_changegroup*,
+ int bNew,
+ int iCol,
+ sqlite3_int64 iVal
+);
+
+/*
+** CAPI3REF: Add a NULL to a changegroup
+**
+** This function is similar to sqlite3changegroup_change_int64(). Except that
+** it configures the change currently under construction with a NULL value
+** instead of a 64-bit integer.
+*/
+SQLITE_API int sqlite3changegroup_change_null(sqlite3_changegroup*, int, int);
+
+/*
+** CAPI3REF: Add an double to a changegroup
+**
+** This function is similar to sqlite3changegroup_change_int64(). Except that
+** it configures the change currently being constructed with a real value
+** instead of a 64-bit integer.
+*/
+SQLITE_API int sqlite3changegroup_change_double(sqlite3_changegroup*, int, int, double);
+
+/*
+** CAPI3REF: Add a text value to a changegroup
+**
+** This function is similar to sqlite3changegroup_change_int64(). It configures
+** the currently accumulated change with a text value instead of a 64-bit
+** integer. Parameter pVal points to a buffer containing the text encoded using
+** utf-8. Parameter nVal may either be the size of the text value in bytes, or
+** else a negative value, in which case the buffer pVal points to is assumed to
+** be nul-terminated.
+*/
+SQLITE_API int sqlite3changegroup_change_text(
+ sqlite3_changegroup*, int, int, const char *pVal, int nVal
+);
+
+/*
+** CAPI3REF: Add a blob to a changegroup
+**
+** This function is similar to sqlite3changegroup_change_int64(). It configures
+** the currently accumulated change with a blob value instead of a 64-bit
+** integer. Parameter pVal points to a buffer containing the blob. Parameter
+** nVal is the size of the blob in bytes.
+*/
+SQLITE_API int sqlite3changegroup_change_blob(
+ sqlite3_changegroup*, int, int, const void *pVal, int nVal
+);
+
+/*
+** CAPI3REF: Finish adding one-at-at-time changes to a changegroup
+**
+** This function may only be called following a successful call to
+** sqlite3changegroup_change_begin(). Otherwise, it is an SQLITE_MISUSE error.
+**
+** If parameter bDiscard is non-zero, then the current change is simply
+** discarded. In this case this function is always successful and SQLITE_OK
+** returned.
+**
+** If parameter bDiscard is zero, then an attempt is made to add the current
+** change to the changegroup. Assuming the changegroup is configured to
+** produce a changeset (not a patchset), this requires that:
+**
+** * If the change is an INSERT or DELETE, then a value must be specified
+** for all columns of the new.* or old.* record, respectively.
+**
+** * If the change is an UPDATE record, then values must be provided for
+** the PRIMARY KEY columns of the old.* record, but must not be provided
+** for PRIMARY KEY columns of the new.* record.
+**
+** * If the change is an UPDATE record, then for each non-PRIMARY KEY
+** column in the old.* record for which a value has been provided, a
+** value must also be provided for the same column in the new.* record.
+** Similarly, for each non-PK column in the old.* record for which
+** a value is not provided, a value must not be provided for the same
+** column in the new.* record.
+**
+** * All values specified for PRIMARY KEY columns must be non-NULL.
+**
+** Otherwise, it is an error.
+**
+** If the changegroup already contains a change for the same row (identified
+** by PRIMARY KEY columns), then the current change is combined with the
+** existing change in the same way as for sqlite3changegroup_add().
+**
+** For a patchset, all of the above rules apply except that it doesn't matter
+** whether or not values are provided for the non-PK old.* record columns
+** for an UPDATE or DELETE change. This means that code used to produce
+** a changeset using the sqlite3changegroup_change_xxx() APIs may also
+** be used to produce patchsets.
+**
+** If the call is successful, SQLITE_OK is returned. Otherwise, if an error
+** occurs, an SQLite error code is returned. If an error is returned and
+** parameter pzErr is not NULL, then (*pzErr) may be set to point to a buffer
+** containing a nul-terminated, utf-8 encoded, English language error message.
+** It is the responsibility of the caller to eventually free any such error
+** message buffer using sqlite3_free().
+*/
+SQLITE_API int sqlite3changegroup_change_finish(
+ sqlite3_changegroup*,
+ int bDiscard,
+ char **pzErr
+);
+
/*
** Make sure we can call this stuff from C++.
*/
@@ -12226,7 +13924,7 @@ SQLITE_API int sqlite3session_config(int op, void *pArg);
**
******************************************************************************
**
-** 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
@@ -12270,19 +13968,19 @@ struct Fts5PhraseIter {
** EXTENSION API FUNCTIONS
**
** xUserData(pFts):
-** Return a copy of the context pointer the extension function was
-** registered with.
+** Return a copy of the pUserData pointer passed to the xCreateFunction()
+** API when the extension function was registered.
**
** 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):
@@ -12296,15 +13994,18 @@ 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
** created with the "columnsize=0" option.
**
** xColumnText:
-** This function attempts to retrieve the text of column iCol of the
-** current document. If successful, (*pz) is set to point to a buffer
+** If parameter iCol is less than zero, or greater than or equal to the
+** number of columns in the table, SQLITE_RANGE is returned.
+**
+** Otherwise, this function attempts to retrieve the text of column iCol of
+** the current document. If successful, (*pz) is set to point to a buffer
** containing the text in utf-8 encoding, (*pn) is set to the size in bytes
** (not characters) of the buffer and SQLITE_OK is returned. Otherwise,
** if an error occurs, an SQLite error code is returned and the final values
@@ -12314,8 +14015,10 @@ struct Fts5PhraseIter {
** Returns the number of phrases in the current query expression.
**
** xPhraseSize:
-** Returns the number of tokens in phrase iPhrase of the query. Phrases
-** are numbered starting from zero.
+** If parameter iCol is less than zero, or greater than or equal to the
+** number of phrases in the current query, as returned by xPhraseCount,
+** 0 is returned. Otherwise, this function returns the number of tokens in
+** phrase iPhrase of the query. Phrases are numbered starting from zero.
**
** xInstCount:
** Set *pnInst to the total number of occurrences of all phrases within
@@ -12323,23 +14026,24 @@ 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:
** Query for the details of phrase match iIdx within the current row.
** Phrase matches are numbered starting from zero, so the iIdx argument
** should be greater than or equal to zero and smaller than the value
-** output by xInstCount().
+** output by xInstCount(). If iIdx is less than zero or greater than
+** or equal to the value returned by xInstCount(), SQLITE_RANGE is returned.
**
-** Usually, output parameter *piPhrase is set to the phrase number, *piCol
+** Otherwise, 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. Returns SQLITE_OK if successful, or an error
-** code (i.e. SQLITE_NOMEM) if an error occurs.
+** first token of the phrase. SQLITE_OK is returned 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.
@@ -12355,13 +14059,17 @@ 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 parameter iPhrase is less than zero, or greater than or equal to
+** the number of phrases in the query, as returned by xPhraseCount(),
+** this function returns SQLITE_RANGE.
+**
** If the callback function returns any value other than SQLITE_OK, the
** query is abandoned and the xQueryPhrase function returns immediately.
** If the returned value is SQLITE_DONE, xQueryPhrase returns SQLITE_OK.
@@ -12374,14 +14082,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
** 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
@@ -12400,7 +14108,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
@@ -12420,7 +14128,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;
@@ -12438,11 +14146,15 @@ 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).
**
+** In all cases, matches are visited in (column ASC, offset ASC) order.
+** i.e. all those in column 0, sorted by offset, followed by those in
+** column 1, etc.
+**
** xPhraseNext()
** See xPhraseFirst above.
**
@@ -12463,22 +14175,93 @@ 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.
+**
+** xQueryToken(pFts5, iPhrase, iToken, ppToken, pnToken)
+** This is used to access token iToken of phrase iPhrase of the current
+** query. Before returning, output parameter *ppToken is set to point
+** to a buffer containing the requested token, and *pnToken to the
+** size of this buffer in bytes.
+**
+** If iPhrase or iToken are less than zero, or if iPhrase is greater than
+** or equal to the number of phrases in the query as reported by
+** xPhraseCount(), or if iToken is equal to or greater than the number of
+** tokens in the phrase, SQLITE_RANGE is returned and *ppToken and *pnToken
+ are both zeroed.
+**
+** The output text is not a copy of the query text that specified the
+** token. It is the output of the tokenizer module. For tokendata=1
+** tables, this includes any embedded 0x00 and trailing data.
+**
+** xInstToken(pFts5, iIdx, iToken, ppToken, pnToken)
+** This is used to access token iToken of phrase hit iIdx within the
+** current row. If iIdx is less than zero or greater than or equal to the
+** value returned by xInstCount(), SQLITE_RANGE is returned. Otherwise,
+** output variable (*ppToken) is set to point to a buffer containing the
+** matching document token, and (*pnToken) to the size of that buffer in
+** bytes.
+**
+** The output text is not a copy of the document text that was tokenized.
+** It is the output of the tokenizer module. For tokendata=1 tables, this
+** includes any embedded 0x00 and trailing data.
+**
+** This API may be slow in some cases if the token identified by parameters
+** iIdx and iToken matched a prefix token in the query. In most cases, the
+** first call to this API for each prefix token in the query is forced
+** to scan the portion of the full-text index that matches the prefix
+** token to collect the extra data required by this API. If the prefix
+** token matches a large number of token instances in the document set,
+** this may be a performance problem.
+**
+** If the user knows in advance that a query may use this API for a
+** prefix token, FTS5 may be configured to collect all required data as part
+** of the initial querying of the full-text index, avoiding the second scan
+** entirely. This also causes prefix queries that do not use this API to
+** run more slowly and use more memory. FTS5 may be configured in this way
+** either on a per-table basis using the [FTS5 insttoken | 'insttoken']
+** option, or on a per-query basis using the
+** [fts5_insttoken | fts5_insttoken()] user function.
+**
+** This API can be quite slow if used with an FTS5 table created with the
+** "detail=none" or "detail=column" option.
+**
+** xColumnLocale(pFts5, iIdx, pzLocale, pnLocale)
+** If parameter iCol is less than zero, or greater than or equal to the
+** number of columns in the table, SQLITE_RANGE is returned.
+**
+** Otherwise, this function attempts to retrieve the locale associated
+** with column iCol of the current row. Usually, there is no associated
+** locale, and output parameters (*pzLocale) and (*pnLocale) are set
+** to NULL and 0, respectively. However, if the fts5_locale() function
+** was used to associate a locale with the value when it was inserted
+** into the fts5 table, then (*pzLocale) is set to point to a nul-terminated
+** buffer containing the name of the locale in utf-8 encoding. (*pnLocale)
+** is set to the size in bytes of the buffer, not including the
+** nul-terminator.
+**
+** If successful, SQLITE_OK is returned. Or, if an error occurs, an
+** SQLite error code is returned. The final value of the output parameters
+** is undefined in this case.
+**
+** xTokenize_v2:
+** Tokenize text using the tokenizer belonging to the FTS5 table. This
+** API is the same as the xTokenize() API, except that it allows a tokenizer
+** locale to be specified.
*/
struct Fts5ExtensionApi {
- int iVersion; /* Currently always set to 3 */
+ int iVersion; /* Currently always set to 4 */
void *(*xUserData)(Fts5Context*);
@@ -12486,7 +14269,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 */
@@ -12513,17 +14296,33 @@ struct Fts5ExtensionApi {
int (*xPhraseFirstColumn)(Fts5Context*, int iPhrase, Fts5PhraseIter*, int*);
void (*xPhraseNextColumn)(Fts5Context*, Fts5PhraseIter*, int *piCol);
+
+ /* Below this point are iVersion>=3 only */
+ int (*xQueryToken)(Fts5Context*,
+ int iPhrase, int iToken,
+ const char **ppToken, int *pnToken
+ );
+ int (*xInstToken)(Fts5Context*, int iIdx, int iToken, const char**, int*);
+
+ /* Below this point are iVersion>=4 only */
+ int (*xColumnLocale)(Fts5Context*, int iCol, const char **pz, int *pn);
+ int (*xTokenize_v2)(Fts5Context*,
+ const char *pText, int nText, /* Text to tokenize */
+ const char *pLocale, int nLocale, /* Locale to pass to tokenizer */
+ void *pCtx, /* Context passed to xToken() */
+ int (*xToken)(void*, int, const char*, int, int, int) /* Callback */
+ );
};
-/*
+/*
** 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:
@@ -12533,17 +14332,17 @@ struct Fts5ExtensionApi {
** A tokenizer instance is required to actually tokenize text.
**
** 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()).
+** pointer provided by the application when the fts5_tokenizer_v2 object
+** 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:
@@ -12552,12 +14351,12 @@ 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().
**
-** The second argument indicates the reason that FTS5 is requesting
+** The third argument indicates the reason that FTS5 is requesting
** tokenization of the supplied text. This is always one of the following
** four values:
**
@@ -12566,8 +14365,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
@@ -12575,12 +14374,19 @@ 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.
**
**
+** The sixth and seventh arguments passed to xTokenize() - pLocale and
+** nLocale - are a pointer to a buffer containing the locale to use for
+** tokenization (e.g. "en_US") and its size in bytes, respectively. The
+** pLocale buffer is not nul-terminated. pLocale may be passed NULL (in
+** which case nLocale is always 0) to indicate that the tokenizer should
+** use its default locale.
+**
** For each token in the input string, the supplied callback xToken() must
** be invoked. The first argument to it should be a copy of the pointer
** passed as the second argument to xTokenize(). The third and fourth
@@ -12590,10 +14396,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
@@ -12604,10 +14410,34 @@ struct Fts5ExtensionApi {
** may abandon the tokenization and return any error code other than
** SQLITE_OK or SQLITE_DONE.
**
+** If the tokenizer is registered using an fts5_tokenizer_v2 object,
+** then the xTokenize() method has two additional arguments - pLocale
+** and nLocale. These specify the locale that the tokenizer should use
+** for the current request. If pLocale and nLocale are both 0, then the
+** tokenizer should use its default locale. Otherwise, pLocale points to
+** an nLocale byte buffer containing the name of the locale to use as utf-8
+** text. pLocale is not nul-terminated.
+**
+** FTS5_TOKENIZER
+**
+** There is also an fts5_tokenizer object. This is an older, deprecated,
+** version of fts5_tokenizer_v2. It is similar except that:
+**
+**
+** - There is no "iVersion" field, and
+**
- The xTokenize() method does not take a locale argument.
+**
+**
+** Legacy fts5_tokenizer tokenizers must be registered using the
+** legacy xCreateTokenizer() function, instead of xCreateTokenizer_v2().
+**
+** Tokenizer implementations registered using either API may be retrieved
+** using both xFindTokenizer() and xFindTokenizer_v2().
+**
** 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
@@ -12616,8 +14446,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",
@@ -12627,34 +14457,34 @@ struct Fts5ExtensionApi {
**
**
- 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
+** 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 so would be
-** inefficient), it doesn't matter if the user queries for
+** 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.
**
@@ -12675,11 +14505,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
@@ -12691,35 +14521,62 @@ 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.
**
** When using methods (2) or (3), it is important that the tokenizer only
-** provide synonyms when tokenizing document text (method (2)) or query
-** text (method (3)), not both. Doing so will not cause any errors, but is
+** provide synonyms when tokenizing document text (method (3)) or query
+** text (method (2)), not both. Doing so will not cause any errors, but is
** inefficient.
*/
typedef struct Fts5Tokenizer Fts5Tokenizer;
+typedef struct fts5_tokenizer_v2 fts5_tokenizer_v2;
+struct fts5_tokenizer_v2 {
+ int iVersion; /* Currently always 2 */
+
+ int (*xCreate)(void*, const char **azArg, int nArg, Fts5Tokenizer **ppOut);
+ void (*xDelete)(Fts5Tokenizer*);
+ int (*xTokenize)(Fts5Tokenizer*,
+ void *pCtx,
+ int flags, /* Mask of FTS5_TOKENIZE_* flags */
+ const char *pText, int nText,
+ const char *pLocale, int nLocale,
+ int (*xToken)(
+ void *pCtx, /* Copy of 2nd argument to xTokenize() */
+ int tflags, /* Mask of FTS5_TOKEN_* flags */
+ const char *pToken, /* Pointer to buffer containing token */
+ int nToken, /* Size of token in bytes */
+ int iStart, /* Byte offset of token within input text */
+ int iEnd /* Byte offset of end of token within input text */
+ )
+ );
+};
+
+/*
+** New code should use the fts5_tokenizer_v2 type to define tokenizer
+** implementations. The following type is included for legacy applications
+** that still use it.
+*/
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 */
@@ -12731,6 +14588,7 @@ struct fts5_tokenizer {
);
};
+
/* Flags that may be passed as the third argument to xTokenize() */
#define FTS5_TOKENIZE_QUERY 0x0001
#define FTS5_TOKENIZE_PREFIX 0x0002
@@ -12750,13 +14608,13 @@ struct fts5_tokenizer {
*/
typedef struct fts5_api fts5_api;
struct fts5_api {
- int iVersion; /* Currently always set to 2 */
+ int iVersion; /* Currently always set to 3 */
/* Create a new tokenizer */
int (*xCreateTokenizer)(
fts5_api *pApi,
const char *zName,
- void *pContext,
+ void *pUserData,
fts5_tokenizer *pTokenizer,
void (*xDestroy)(void*)
);
@@ -12765,7 +14623,7 @@ struct fts5_api {
int (*xFindTokenizer)(
fts5_api *pApi,
const char *zName,
- void **ppContext,
+ void **ppUserData,
fts5_tokenizer *pTokenizer
);
@@ -12773,10 +14631,29 @@ struct fts5_api {
int (*xCreateFunction)(
fts5_api *pApi,
const char *zName,
- void *pContext,
+ void *pUserData,
fts5_extension_function xFunction,
void (*xDestroy)(void*)
);
+
+ /* APIs below this point are only available if iVersion>=3 */
+
+ /* Create a new tokenizer */
+ int (*xCreateTokenizer_v2)(
+ fts5_api *pApi,
+ const char *zName,
+ void *pUserData,
+ fts5_tokenizer_v2 *pTokenizer,
+ void (*xDestroy)(void*)
+ );
+
+ /* Find an existing tokenizer */
+ int (*xFindTokenizer_v2)(
+ fts5_api *pApi,
+ const char *zName,
+ void **ppUserData,
+ fts5_tokenizer_v2 **ppTokenizer
+ );
};
/*
@@ -12790,16 +14667,22 @@ struct fts5_api {
#endif /* _FTS5_H */
/******** End of fts5.h *********/
+#endif /* SQLITE3_H */
/************** End of sqlite3.h *********************************************/
/************** Continuing where we left off in sqliteInt.h ******************/
+/*
+** Reuse the STATIC_LRU for mutex access to sqlite3_temp_directory.
+*/
+#define SQLITE_MUTEX_STATIC_TEMPDIR SQLITE_MUTEX_STATIC_VFS1
+
/*
** Include the configuration header output by 'configure' if we're using the
** autoconf-based build
*/
#if defined(_HAVE_SQLITE_CONFIG_H) && !defined(SQLITECONFIG_H)
-/* #include "config.h" */
+#include "sqlite_cfg.h"
#define SQLITECONFIG_H 1
#endif
@@ -12816,7 +14699,7 @@ struct fts5_api {
** May you share freely, never taking more than you give.
**
*************************************************************************
-**
+**
** This file defines various limits of what SQLite can process.
*/
@@ -12830,6 +14713,28 @@ struct fts5_api {
#ifndef SQLITE_MAX_LENGTH
# define SQLITE_MAX_LENGTH 1000000000
#endif
+#define SQLITE_MIN_LENGTH 30 /* Minimum value for the length limit */
+
+/*
+** Maximum size of any single memory allocation.
+**
+** This is not a limit on the total amount of memory used. This is
+** a limit on the size parameter to sqlite3_malloc() and sqlite3_realloc().
+**
+** The upper bound is slightly less than 2GiB: 0x7ffffeff == 2,147,483,391
+** This provides a 256-byte safety margin for defense against 32-bit
+** signed integer overflow bugs when computing memory allocation sizes.
+** Paranoid applications might want to reduce the maximum allocation size
+** further for an even larger safety margin. 0x3fffffff or 0x0fffffff
+** or even smaller would be reasonable upper bounds on the size of a memory
+** allocations for most applications.
+*/
+#ifndef SQLITE_MAX_ALLOCATION_SIZE
+# define SQLITE_MAX_ALLOCATION_SIZE 2147483391
+#endif
+#if SQLITE_MAX_ALLOCATION_SIZE>2147483391
+# error Maximum size for SQLITE_MAX_ALLOCATION_SIZE is 2147483391
+#endif
/*
** This is the maximum number of
@@ -12842,14 +14747,22 @@ struct fts5_api {
** * Terms in the GROUP BY or ORDER BY clauses of a SELECT statement.
** * Terms in the VALUES clause of an INSERT statement
**
-** The hard upper limit here is 32676. Most database people will
+** The hard upper limit here is 32767. Most database people will
** tell you that in a well-normalized database, you usually should
** not have more than a dozen or so columns in any table. And if
** that is the case, there is no point in having more than a few
** dozen values in any of the other situations described above.
+**
+** An index can only have SQLITE_MAX_COLUMN columns from the user
+** point of view, but the underlying b-tree that implements the index
+** might have up to twice as many columns in a WITHOUT ROWID table,
+** since must also store the primary key at the end. Hence the
+** column count for Index is u16 instead of i16.
*/
-#ifndef SQLITE_MAX_COLUMN
+#if !defined(SQLITE_MAX_COLUMN)
# define SQLITE_MAX_COLUMN 2000
+#elif SQLITE_MAX_COLUMN>32767
+# error SQLITE_MAX_COLUMN may not exceed 32767
#endif
/*
@@ -12858,32 +14771,49 @@ struct fts5_api {
** It used to be the case that setting this value to zero would
** turn the limit off. That is no longer true. It is not possible
** to turn this limit off.
+**
+** The hard limit is the largest possible 32-bit signed integer less
+** 1024, or 2147482624.
*/
#ifndef SQLITE_MAX_SQL_LENGTH
# define SQLITE_MAX_SQL_LENGTH 1000000000
#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.
+** The maximum depth of an expression tree. The expression tree depth
+** is also limited indirectly by SQLITE_MAX_SQL_LENGTH and by
+** SQLITE_MAX_PARSER_DEPTH. Reducing the maximum complexity of
+** expressions can help prevent excess memory usage by hostile SQL.
**
-** 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.
+** A value of 0 for this compile-time option causes all expression
+** depth limiting code to be omitted.
*/
#ifndef SQLITE_MAX_EXPR_DEPTH
# define SQLITE_MAX_EXPR_DEPTH 1000
#endif
+/*
+** The maximum depth of the LALR(1) stack used in the parser that
+** interprets SQL inputs. The parser stack depth can also be limited
+** indirectly by SQLITE_MAX_SQL_LENGTH. Limiting the parser stack
+** depth can help prevent excess memory usage and excess CPU stack
+** usage when processing hostile SQL.
+**
+** Prior to version 3.45.0 (2024-01-15), the parser stack was
+** hard-coded to 100 entries, and that worked fine for almost all
+** applications. So the upper bound on this limit need not be large.
+*/
+#ifndef SQLITE_MAX_PARSER_DEPTH
+# define SQLITE_MAX_PARSER_DEPTH 2500
+#endif
+
/*
** The maximum number of terms in a compound SELECT statement.
** The code generator for compound SELECT statements does one
** level of recursion for each term. A stack overflow can result
** if the number of terms is too large. In practice, most SQL
** never has more than 3 or 4 terms. Use a value of 0 to disable
-** any limit on the number of terms in a compount SELECT.
+** any limit on the number of terms in a compound SELECT.
*/
#ifndef SQLITE_MAX_COMPOUND_SELECT
# define SQLITE_MAX_COMPOUND_SELECT 500
@@ -12899,9 +14829,13 @@ struct fts5_api {
/*
** The maximum number of arguments to an SQL function.
+**
+** This value has a hard upper limit of 32767 due to storage
+** constraints (it needs to fit inside a i16). We keep it
+** lower than that to prevent abuse.
*/
#ifndef SQLITE_MAX_FUNCTION_ARG
-# define SQLITE_MAX_FUNCTION_ARG 127
+# define SQLITE_MAX_FUNCTION_ARG 1000
#endif
/*
@@ -12938,9 +14872,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
@@ -12948,10 +14885,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
@@ -12985,17 +14922,21 @@ struct fts5_api {
# undef SQLITE_MAX_DEFAULT_PAGE_SIZE
# define SQLITE_MAX_DEFAULT_PAGE_SIZE SQLITE_MAX_PAGE_SIZE
#endif
+#if SQLITE_MAX_DEFAULT_PAGE_SIZE=4007000 || __has_extension(c_atomic)
+# define SQLITE_ATOMIC_INTRINSICS 1
+# define AtomicLoad(PTR) __atomic_load_n((PTR),__ATOMIC_RELAXED)
+# define AtomicStore(PTR,VAL) __atomic_store_n((PTR),(VAL),__ATOMIC_RELAXED)
+#else
+# define SQLITE_ATOMIC_INTRINSICS 0
+# define AtomicLoad(PTR) (*(PTR))
+# define AtomicStore(PTR,VAL) (*(PTR) = (VAL))
+#endif
+
/*
** Include standard header files as necessary
*/
-#ifdef HAVE_STDINT_H
#include
-#endif
#ifdef HAVE_INTTYPES_H
#include
#endif
@@ -13055,30 +15011,37 @@ 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))
#endif
/*
-** A macro to hint to the compiler that a function should not be
+** Macros to hint to the compiler that a function should or should not be
** inlined.
*/
#if defined(__GNUC__)
# define SQLITE_NOINLINE __attribute__((noinline))
+# define SQLITE_INLINE __attribute__((always_inline)) inline
#elif defined(_MSC_VER) && _MSC_VER>=1310
# define SQLITE_NOINLINE __declspec(noinline)
+# define SQLITE_INLINE __forceinline
#else
# define SQLITE_NOINLINE
+# define SQLITE_INLINE
+#endif
+#if defined(SQLITE_COVERAGE_TEST) || defined(__STRICT_ANSI__)
+# undef SQLITE_INLINE
+# define SQLITE_INLINE
#endif
/*
@@ -13100,6 +15063,29 @@ struct fts5_api {
# endif
#endif
+/*
+** Enable SQLITE_USE_SEH by default on MSVC builds. Only omit
+** SEH support if the -DSQLITE_OMIT_SEH option is given.
+*/
+#if defined(_MSC_VER) && !defined(SQLITE_OMIT_SEH)
+# define SQLITE_USE_SEH 1
+#else
+# undef SQLITE_USE_SEH
+#endif
+
+/*
+** Enable SQLITE_DIRECT_OVERFLOW_READ, unless the build explicitly
+** disables it using -DSQLITE_DIRECT_OVERFLOW_READ=0
+*/
+#if defined(SQLITE_DIRECT_OVERFLOW_READ) && SQLITE_DIRECT_OVERFLOW_READ+1==1
+ /* Disable if -DSQLITE_DIRECT_OVERFLOW_READ=0 */
+# undef SQLITE_DIRECT_OVERFLOW_READ
+#else
+ /* In all other cases, enable */
+# define SQLITE_DIRECT_OVERFLOW_READ 1
+#endif
+
+
/*
** The SQLITE_THREADSAFE macro must be defined as 0, 1, or 2.
** 0 means mutexes are permanently disable and the library is never
@@ -13229,11 +15215,12 @@ struct fts5_api {
** is significant and used at least once. On switch statements
** where multiple cases go to the same block of code, testcase()
** can insure that all cases are evaluated.
-**
*/
-#ifdef SQLITE_COVERAGE_TEST
-SQLITE_PRIVATE void sqlite3Coverage(int);
-# define testcase(X) if( X ){ sqlite3Coverage(__LINE__); }
+#if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_DEBUG)
+# ifndef SQLITE_AMALGAMATION
+ extern unsigned int sqlite3CoverageCounter;
+# endif
+# define testcase(X) if( X ){ sqlite3CoverageCounter += (unsigned)__LINE__; }
#else
# define testcase(X)
#endif
@@ -13263,6 +15250,14 @@ SQLITE_PRIVATE void sqlite3Coverage(int);
# define VVA_ONLY(X)
#endif
+/*
+** Disable ALWAYS() and NEVER() (make them pass-throughs) for coverage
+** and mutation testing
+*/
+#if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_MUTATION_TEST)
+# define SQLITE_OMIT_AUXILIARY_SAFETY_CHECKS 1
+#endif
+
/*
** The ALWAYS and NEVER macros surround boolean expressions which
** are intended to always be true or false, respectively. Such
@@ -13278,7 +15273,7 @@ SQLITE_PRIVATE void sqlite3Coverage(int);
** be true and false so that the unreachable code they specify will
** not be counted as untested code.
*/
-#if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_MUTATION_TEST)
+#if defined(SQLITE_OMIT_AUXILIARY_SAFETY_CHECKS)
# define ALWAYS(X) (1)
# define NEVER(X) (0)
#elif !defined(NDEBUG)
@@ -13352,6 +15347,15 @@ SQLITE_PRIVATE void sqlite3Coverage(int);
# undef SQLITE_ENABLE_EXPLAIN_COMMENTS
#endif
+/*
+** SQLITE_OMIT_VIRTUALTABLE implies SQLITE_OMIT_ALTERTABLE
+*/
+#if defined(SQLITE_OMIT_VIRTUALTABLE) && !defined(SQLITE_OMIT_ALTERTABLE)
+# define SQLITE_OMIT_ALTERTABLE
+#endif
+
+#define SQLITE_DIGIT_SEPARATOR '_'
+
/*
** Return true (non-zero) if the input is an integer that is too large
** to fit in 32-bits. This macro is used inside of various testcase()
@@ -13408,7 +15412,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.
@@ -13423,7 +15427,7 @@ struct Hash {
} *ht;
};
-/* Each element in the hash table is an instance of the following
+/* Each element in the hash table is an instance of the following
** structure. All elements are stored on a single doubly-linked list.
**
** Again, this structure is intended to be opaque, but it can't really
@@ -13433,6 +15437,7 @@ struct HashElem {
HashElem *next, *prev; /* Next and previous elements in the table */
void *data; /* Data associated with this element */
const char *pKey; /* Key associated with this element */
+ unsigned int h; /* hash for pKey */
};
/*
@@ -13464,7 +15469,7 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash*);
/*
** Number of entries in a hash table
*/
-/* #define sqliteHashCount(H) ((H)->count) // NOT USED */
+#define sqliteHashCount(H) ((H)->count)
#endif /* SQLITE_HASH_H */
@@ -13496,8 +15501,8 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash*);
#define TK_LP 22
#define TK_RP 23
#define TK_AS 24
-#define TK_WITHOUT 25
-#define TK_COMMA 26
+#define TK_COMMA 25
+#define TK_WITHOUT 26
#define TK_ABORT 27
#define TK_ACTION 28
#define TK_AFTER 29
@@ -13517,136 +15522,147 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash*);
#define TK_OR 43
#define TK_AND 44
#define TK_IS 45
-#define TK_MATCH 46
-#define TK_LIKE_KW 47
-#define TK_BETWEEN 48
-#define TK_IN 49
-#define TK_ISNULL 50
-#define TK_NOTNULL 51
-#define TK_NE 52
-#define TK_EQ 53
-#define TK_GT 54
-#define TK_LE 55
-#define TK_LT 56
-#define TK_GE 57
-#define TK_ESCAPE 58
-#define TK_ID 59
-#define TK_COLUMNKW 60
-#define TK_DO 61
-#define TK_FOR 62
-#define TK_IGNORE 63
-#define TK_INITIALLY 64
-#define TK_INSTEAD 65
-#define TK_NO 66
-#define TK_KEY 67
-#define TK_OF 68
-#define TK_OFFSET 69
-#define TK_PRAGMA 70
-#define TK_RAISE 71
-#define TK_RECURSIVE 72
-#define TK_REPLACE 73
-#define TK_RESTRICT 74
-#define TK_ROW 75
-#define TK_ROWS 76
-#define TK_TRIGGER 77
-#define TK_VACUUM 78
-#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_EXCLUDE 88
-#define TK_GROUPS 89
-#define TK_OTHERS 90
-#define TK_TIES 91
-#define TK_REINDEX 92
-#define TK_RENAME 93
-#define TK_CTIME_KW 94
-#define TK_ANY 95
-#define TK_BITAND 96
-#define TK_BITOR 97
-#define TK_LSHIFT 98
-#define TK_RSHIFT 99
-#define TK_PLUS 100
-#define TK_MINUS 101
-#define TK_STAR 102
-#define TK_SLASH 103
-#define TK_REM 104
-#define TK_CONCAT 105
-#define TK_COLLATE 106
-#define TK_BITNOT 107
-#define TK_ON 108
-#define TK_INDEXED 109
-#define TK_STRING 110
-#define TK_JOIN_KW 111
-#define TK_CONSTRAINT 112
-#define TK_DEFAULT 113
-#define TK_NULL 114
-#define TK_PRIMARY 115
-#define TK_UNIQUE 116
-#define TK_CHECK 117
-#define TK_REFERENCES 118
-#define TK_AUTOINCR 119
-#define TK_INSERT 120
-#define TK_DELETE 121
-#define TK_UPDATE 122
-#define TK_SET 123
-#define TK_DEFERRABLE 124
-#define TK_FOREIGN 125
-#define TK_DROP 126
-#define TK_UNION 127
-#define TK_ALL 128
-#define TK_EXCEPT 129
-#define TK_INTERSECT 130
-#define TK_SELECT 131
-#define TK_VALUES 132
-#define TK_DISTINCT 133
-#define TK_DOT 134
-#define TK_FROM 135
-#define TK_JOIN 136
-#define TK_USING 137
-#define TK_ORDER 138
-#define TK_GROUP 139
-#define TK_HAVING 140
-#define TK_LIMIT 141
-#define TK_WHERE 142
-#define TK_INTO 143
-#define TK_NOTHING 144
-#define TK_FLOAT 145
-#define TK_BLOB 146
-#define TK_INTEGER 147
-#define TK_VARIABLE 148
-#define TK_CASE 149
-#define TK_WHEN 150
-#define TK_THEN 151
-#define TK_ELSE 152
-#define TK_INDEX 153
-#define TK_ALTER 154
-#define TK_ADD 155
-#define TK_WINDOW 156
-#define TK_OVER 157
-#define TK_FILTER 158
-#define TK_TRUEFALSE 159
-#define TK_ISNOT 160
-#define TK_FUNCTION 161
-#define TK_COLUMN 162
-#define TK_AGG_FUNCTION 163
-#define TK_AGG_COLUMN 164
-#define TK_UMINUS 165
-#define TK_UPLUS 166
-#define TK_TRUTH 167
-#define TK_REGISTER 168
-#define TK_VECTOR 169
-#define TK_SELECT_COLUMN 170
-#define TK_IF_NULL_ROW 171
-#define TK_ASTERISK 172
-#define TK_SPAN 173
-#define TK_SPACE 174
-#define TK_ILLEGAL 175
+#define TK_ISNOT 46
+#define TK_MATCH 47
+#define TK_LIKE_KW 48
+#define TK_BETWEEN 49
+#define TK_IN 50
+#define TK_ISNULL 51
+#define TK_NOTNULL 52
+#define TK_NE 53
+#define TK_EQ 54
+#define TK_GT 55
+#define TK_LE 56
+#define TK_LT 57
+#define TK_GE 58
+#define TK_ESCAPE 59
+#define TK_ID 60
+#define TK_COLUMNKW 61
+#define TK_DO 62
+#define TK_FOR 63
+#define TK_IGNORE 64
+#define TK_INITIALLY 65
+#define TK_INSTEAD 66
+#define TK_NO 67
+#define TK_KEY 68
+#define TK_OF 69
+#define TK_OFFSET 70
+#define TK_PRAGMA 71
+#define TK_RAISE 72
+#define TK_RECURSIVE 73
+#define TK_REPLACE 74
+#define TK_RESTRICT 75
+#define TK_ROW 76
+#define TK_ROWS 77
+#define TK_TRIGGER 78
+#define TK_VACUUM 79
+#define TK_VIEW 80
+#define TK_VIRTUAL 81
+#define TK_WITH 82
+#define TK_NULLS 83
+#define TK_FIRST 84
+#define TK_LAST 85
+#define TK_CURRENT 86
+#define TK_FOLLOWING 87
+#define TK_PARTITION 88
+#define TK_PRECEDING 89
+#define TK_RANGE 90
+#define TK_UNBOUNDED 91
+#define TK_EXCLUDE 92
+#define TK_GROUPS 93
+#define TK_OTHERS 94
+#define TK_TIES 95
+#define TK_GENERATED 96
+#define TK_ALWAYS 97
+#define TK_MATERIALIZED 98
+#define TK_REINDEX 99
+#define TK_RENAME 100
+#define TK_CTIME_KW 101
+#define TK_ANY 102
+#define TK_BITAND 103
+#define TK_BITOR 104
+#define TK_LSHIFT 105
+#define TK_RSHIFT 106
+#define TK_PLUS 107
+#define TK_MINUS 108
+#define TK_STAR 109
+#define TK_SLASH 110
+#define TK_REM 111
+#define TK_CONCAT 112
+#define TK_PTR 113
+#define TK_COLLATE 114
+#define TK_BITNOT 115
+#define TK_ON 116
+#define TK_INDEXED 117
+#define TK_STRING 118
+#define TK_JOIN_KW 119
+#define TK_CONSTRAINT 120
+#define TK_DEFAULT 121
+#define TK_NULL 122
+#define TK_PRIMARY 123
+#define TK_UNIQUE 124
+#define TK_CHECK 125
+#define TK_REFERENCES 126
+#define TK_AUTOINCR 127
+#define TK_INSERT 128
+#define TK_DELETE 129
+#define TK_UPDATE 130
+#define TK_SET 131
+#define TK_DEFERRABLE 132
+#define TK_FOREIGN 133
+#define TK_DROP 134
+#define TK_UNION 135
+#define TK_ALL 136
+#define TK_EXCEPT 137
+#define TK_INTERSECT 138
+#define TK_SELECT 139
+#define TK_VALUES 140
+#define TK_DISTINCT 141
+#define TK_DOT 142
+#define TK_FROM 143
+#define TK_JOIN 144
+#define TK_USING 145
+#define TK_ORDER 146
+#define TK_GROUP 147
+#define TK_HAVING 148
+#define TK_LIMIT 149
+#define TK_WHERE 150
+#define TK_RETURNING 151
+#define TK_INTO 152
+#define TK_NOTHING 153
+#define TK_FLOAT 154
+#define TK_BLOB 155
+#define TK_INTEGER 156
+#define TK_VARIABLE 157
+#define TK_CASE 158
+#define TK_WHEN 159
+#define TK_THEN 160
+#define TK_ELSE 161
+#define TK_INDEX 162
+#define TK_ALTER 163
+#define TK_ADD 164
+#define TK_WINDOW 165
+#define TK_OVER 166
+#define TK_FILTER 167
+#define TK_COLUMN 168
+#define TK_AGG_FUNCTION 169
+#define TK_AGG_COLUMN 170
+#define TK_TRUEFALSE 171
+#define TK_FUNCTION 172
+#define TK_UPLUS 173
+#define TK_UMINUS 174
+#define TK_TRUTH 175
+#define TK_REGISTER 176
+#define TK_VECTOR 177
+#define TK_SELECT_COLUMN 178
+#define TK_IF_NULL_ROW 179
+#define TK_ASTERISK 180
+#define TK_SPAN 181
+#define TK_ERROR 182
+#define TK_QNUMBER 183
+#define TK_SPACE 184
+#define TK_COMMENT 185
+#define TK_ILLEGAL 186
/************** End of parse.h ***********************************************/
/************** Continuing where we left off in sqliteInt.h ******************/
@@ -13655,6 +15671,7 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash*);
#include
#include
#include
+#include
/*
** Use a macro to replace memcpy() if compiled with SQLITE_INLINE_MEMCPY.
@@ -13675,7 +15692,9 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash*);
#ifdef SQLITE_OMIT_FLOATING_POINT
# define double sqlite_int64
# define float sqlite_int64
-# define LONGDOUBLE_TYPE sqlite_int64
+# define fabs(X) ((X)<0?-(X):(X))
+# define sqlite3IsOverflow(X) 0
+# define INFINITY (9223372036854775807LL)
# ifndef SQLITE_BIG_DBL
# define SQLITE_BIG_DBL (((sqlite3_int64)1)<<50)
# endif
@@ -13752,7 +15771,7 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash*);
** number of pages. A negative number N translations means that a buffer
** of -1024*N bytes is allocated and used for as many pages as it will hold.
**
-** The default value of "20" was choosen to minimize the run-time of the
+** The default value of "20" was chosen to minimize the run-time of the
** speedtest1 test program with options: --shrink-memory --reprepare
*/
#ifndef SQLITE_DEFAULT_PCACHE_INITSZ
@@ -13767,7 +15786,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.
*/
@@ -13780,7 +15799,24 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash*);
** ourselves.
*/
#ifndef offsetof
-#define offsetof(STRUCTURE,FIELD) ((int)((char*)&((STRUCTURE*)0)->FIELD))
+# define offsetof(ST,M) ((size_t)((char*)&((ST*)0)->M - (char*)0))
+#endif
+
+/*
+** sizeof64() is like sizeof(), but always returns a 64-bit value, even
+** on 32-bit builds. This can help to avoid overflow by ensuring 64-bit
+** arithmetic is used consistently in both 32-bit and 64-bit builds.
+*/
+#define sizeof64(X) ((sqlite3_int64)sizeof(X))
+
+/*
+** Work around C99 "flex-array" syntax for pre-C99 compilers, so as
+** to avoid complaints from -fsanitize=strict-bounds.
+*/
+#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
+# define FLEXARRAY
+#else
+# define FLEXARRAY 1
#endif
/*
@@ -13850,9 +15886,6 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash*);
# define INT8_TYPE signed char
# endif
#endif
-#ifndef LONGDOUBLE_TYPE
-# define LONGDOUBLE_TYPE long double
-#endif
typedef sqlite_int64 i64; /* 8-byte signed integer */
typedef sqlite_uint64 u64; /* 8-byte unsigned integer */
typedef UINT32_TYPE u32; /* 4-byte unsigned integer */
@@ -13861,6 +15894,11 @@ typedef INT16_TYPE i16; /* 2-byte signed integer */
typedef UINT8_TYPE u8; /* 1-byte unsigned integer */
typedef INT8_TYPE i8; /* 1-byte signed integer */
+/* A bitfield type for use inside of structures. Always follow with :N where
+** N is the number of bits.
+*/
+typedef unsigned bft; /* Bit Field Type */
+
/*
** SQLITE_MAX_U32 is a u64 constant that is the maximum u64 value
** that can be stored in a u32 without loss of data. The value
@@ -13871,15 +15909,9 @@ typedef INT8_TYPE i8; /* 1-byte signed integer */
/*
** The datatype used to store estimates of the number of rows in a
-** table or index. This is an unsigned integer type. For 99.9% of
-** the world, a 32-bit integer is sufficient. But a 64-bit integer
-** can be used at compile-time if desired.
+** table or index.
*/
-#ifdef SQLITE_64BIT_STATS
- typedef u64 tRowcnt; /* 64-bit only if requested at compile-time */
-#else
- typedef u32 tRowcnt; /* 32-bit is the default */
-#endif
+typedef u64 tRowcnt;
/*
** Estimated quantities used for query planning are stored as 16-bit
@@ -13905,6 +15937,8 @@ typedef INT8_TYPE i8; /* 1-byte signed integer */
** 0.5 -> -10 0.1 -> -33 0.0625 -> -40
*/
typedef INT16_TYPE LogEst;
+#define LOGEST_MIN (-32768)
+#define LOGEST_MAX (32767)
/*
** Set the SQLITE_PTRSIZE macro to the number of bytes in a pointer
@@ -13914,6 +15948,7 @@ typedef INT16_TYPE LogEst;
# define SQLITE_PTRSIZE __SIZEOF_POINTER__
# elif defined(i386) || defined(__i386__) || defined(_M_IX86) || \
defined(_M_ARM) || defined(__arm__) || defined(__x86) || \
+ (defined(__APPLE__) && defined(__ppc__)) || \
(defined(__TOS_AIX__) && !defined(__64BIT__))
# define SQLITE_PTRSIZE 4
# else
@@ -13939,8 +15974,31 @@ typedef INT16_TYPE LogEst;
** the end of buffer S. This macro returns true if P points to something
** contained within the buffer S.
*/
-#define SQLITE_WITHIN(P,S,E) (((uptr)(P)>=(uptr)(S))&&((uptr)(P)<(uptr)(E)))
+#define SQLITE_WITHIN(P,S,E) (((uptr)(P)>=(uptr)(S))&&((uptr)(P)<(uptr)(E)))
+/*
+** P is one byte past the end of a large buffer. Return true if a span of bytes
+** between S..E crosses the end of that buffer. In other words, return true
+** if the sub-buffer S..E-1 overflows the buffer whose last byte is P-1.
+**
+** S is the start of the span. E is one byte past the end of end of span.
+**
+** P
+** |-----------------| FALSE
+** |-------|
+** S E
+**
+** P
+** |-----------------|
+** |-------| TRUE
+** S E
+**
+** P
+** |-----------------|
+** |-------| FALSE
+** S E
+*/
+#define SQLITE_OVERFLOW(P,S,E) (((uptr)(S)<(uptr)(P))&&((uptr)(E)>(uptr)(P)))
/*
** Macros to determine whether the machine is big or little endian,
@@ -13950,15 +16008,33 @@ typedef INT16_TYPE LogEst;
** using C-preprocessor macros. If that is unsuccessful, or if
** -DSQLITE_BYTEORDER=0 is set, then byte-order is determined
** at run-time.
+**
+** If you are building SQLite on some obscure platform for which the
+** following ifdef magic does not work, you can always include either:
+**
+** -DSQLITE_BYTEORDER=1234
+**
+** or
+**
+** -DSQLITE_BYTEORDER=4321
+**
+** to cause the build to work for little-endian or big-endian processors,
+** respectively.
*/
-#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)
-# define SQLITE_BYTEORDER 1234
-# elif defined(sparc) || defined(__ppc__)
-# define SQLITE_BYTEORDER 4321
+#ifndef SQLITE_BYTEORDER /* Replicate changes at tag-20230904a */
+# if defined(__BYTE_ORDER__) && __BYTE_ORDER__==__ORDER_BIG_ENDIAN__
+# define SQLITE_BYTEORDER 4321
+# elif defined(__BYTE_ORDER__) && __BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__
+# define SQLITE_BYTEORDER 1234
+# elif defined(__BIG_ENDIAN__) && __BIG_ENDIAN__==1
+# define SQLITE_BYTEORDER 4321
+# elif 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(__ARMEB__) || defined(__AARCH64EB__)
+# define SQLITE_BYTEORDER 4321
# else
# define SQLITE_BYTEORDER 0
# endif
@@ -13988,13 +16064,33 @@ 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)
+/*
+** Macro SMXV(n) return the maximum value that can be held in variable n,
+** assuming n is a signed integer type. UMXV(n) is similar for unsigned
+** integer types.
+*/
+#define SMXV(n) ((((i64)1)<<(sizeof(n)*8-1))-1)
+#define UMXV(n) ((((i64)1)<<(sizeof(n)*8))-1)
+
/*
** Round up a number to the next larger multiple of 8. This is used
** to force 8-byte alignment on 64-bit architectures.
+**
+** ROUND8() always does the rounding, for any argument.
+**
+** ROUND8P() assumes that the argument is already an integer number of
+** pointers in size, and so it is a no-op on systems where the pointer
+** size is 8.
*/
#define ROUND8(x) (((x)+7)&~7)
+#if SQLITE_PTRSIZE==8
+# define ROUND8P(x) (x)
+#else
+# define ROUND8P(x) (((x)+7)&~7)
+#endif
/*
** Round down to the nearest multiple of 8
@@ -14011,10 +16107,11 @@ typedef INT16_TYPE LogEst;
** pointers. In that case, only verify 4-byte alignment.
*/
#ifdef SQLITE_4_BYTE_ALIGNED_MALLOC
-# define EIGHT_BYTE_ALIGNMENT(X) ((((char*)(X) - (char*)0)&3)==0)
+# define EIGHT_BYTE_ALIGNMENT(X) ((((uptr)(X) - (uptr)0)&3)==0)
#else
-# define EIGHT_BYTE_ALIGNMENT(X) ((((char*)(X) - (char*)0)&7)==0)
+# define EIGHT_BYTE_ALIGNMENT(X) ((((uptr)(X) - (uptr)0)&7)==0)
#endif
+#define TWO_BYTE_ALIGNMENT(X) ((((uptr)(X) - (uptr)0)&1)==0)
/*
** Disable MMAP on platforms where it is known to not work
@@ -14057,28 +16154,96 @@ typedef INT16_TYPE LogEst;
#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
+** TREETRACE_ENABLED will be either 1 or 0 depending on whether or not
+** the Abstract Syntax Tree tracing logic is turned on.
*/
-#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
+#if !defined(SQLITE_AMALGAMATION)
+SQLITE_PRIVATE u32 sqlite3TreeTrace;
+#endif
+#if defined(SQLITE_DEBUG) \
+ && (defined(SQLITE_TEST) || defined(SQLITE_ENABLE_SELECTTRACE) \
+ || defined(SQLITE_ENABLE_TREETRACE))
+# define TREETRACE_ENABLED 1
+# define TREETRACE(K,P,S,X) \
+ if(sqlite3TreeTrace&(K)) \
+ sqlite3DebugPrintf("%u/%d/%p: ",(S)->selId,(P)->addrExplain,(S)),\
+ sqlite3DebugPrintf X
+#else
+# define TREETRACE(K,P,S,X)
+# define TREETRACE_ENABLED 0
+#endif
+
+/* TREETRACE flag meanings:
+**
+** 0x00000001 Beginning and end of SELECT processing
+** 0x00000002 WHERE clause processing
+** 0x00000004 Query flattener
+** 0x00000008 Result-set wildcard expansion
+** 0x00000010 Query name resolution
+** 0x00000020 Aggregate analysis
+** 0x00000040 Window functions
+** 0x00000080 Generated column names
+** 0x00000100 Move HAVING terms into WHERE
+** 0x00000200 Count-of-view optimization
+** 0x00000400 Compound SELECT processing
+** 0x00000800 Drop superfluous ORDER BY
+** 0x00001000 LEFT JOIN simplifies to JOIN
+** 0x00002000 Constant propagation
+** 0x00004000 Push-down optimization
+** 0x00008000 After all FROM-clause analysis
+** 0x00010000 Beginning of DELETE/INSERT/UPDATE processing
+** 0x00020000 Transform DISTINCT into GROUP BY
+** 0x00040000 SELECT tree dump after all code has been generated
+** 0x00080000 NOT NULL strength reduction
+** 0x00100000 Pointers are all shown as zero
+** 0x00200000 EXISTS-to-JOIN optimization
+*/
+
+/*
+** 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
/*
-** SELECTTRACE_ENABLED will be either 1 or 0 depending on whether or not
-** the Select query generator tracing logic is turned on.
+** Bits for the sqlite3WhereTrace mask:
+**
+** (---any--) Top-level block structure
+** 0x-------F High-level debug messages
+** 0x----FFF- More detail
+** 0xFFFF---- Low-level debug messages
+**
+** 0x00000001 Code generation
+** 0x00000002 Solver (Use 0x40000 for less detail)
+** 0x00000004 Solver costs
+** 0x00000008 WhereLoop inserts
+**
+** 0x00000010 Display sqlite3_index_info xBestIndex calls
+** 0x00000020 Range an equality scan metrics
+** 0x00000040 IN operator decisions
+** 0x00000080 WhereLoop cost adjustments
+** 0x00000100
+** 0x00000200 Covering index decisions
+** 0x00000400 OR optimization
+** 0x00000800 Index scanner
+** 0x00001000 More details associated with code generation
+** 0x00002000
+** 0x00004000 Show all WHERE terms at key points
+** 0x00008000 Show the full SELECT statement at key places
+**
+** 0x00010000 Show more detail when printing WHERE terms
+** 0x00020000 Show WHERE terms returned from whereScanNext()
+** 0x00040000 Solver overview messages
+** 0x00080000 Star-query heuristic
+** 0x00100000 Pointers are all shown as zero
*/
-#if defined(SQLITE_ENABLE_SELECTTRACE)
-# define SELECTTRACE_ENABLED 1
-#else
-# define SELECTTRACE_ENABLED 0
-#endif
+
/*
** An instance of the following structure is used to store the busy-handler
@@ -14094,26 +16259,41 @@ 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.
+**
+** The PREFERRED names are used wherever possible. But LEGACY is also
+** used for backwards compatibility.
+**
+** 1. Queries can use either the PREFERRED or the LEGACY names
+** 2. The sqlite3_set_authorizer() callback uses the LEGACY name
+** 3. The PRAGMA table_list statement uses the PREFERRED name
+**
+** The LEGACY names are stored in the internal symbol hash table
+** in support of (2). Names are translated using sqlite3PreferredTableName()
+** for (3). The sqlite3FindTable() function takes care of translating
+** names for (1).
+**
+** Note that "sqlite_temp_schema" can also be called "temp.sqlite_schema".
*/
-#define MASTER_NAME "sqlite_master"
-#define TEMP_MASTER_NAME "sqlite_temp_master"
+#define LEGACY_SCHEMA_TABLE "sqlite_master"
+#define LEGACY_TEMP_SCHEMA_TABLE "sqlite_temp_master"
+#define PREFERRED_SCHEMA_TABLE "sqlite_schema"
+#define PREFERRED_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)?LEGACY_TEMP_SCHEMA_TABLE:LEGACY_SCHEMA_TABLE)
/*
** A convenience macro that returns the number of elements in
@@ -14134,7 +16314,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)sqlite3RowSetClear)
/*
** When SQLITE_OMIT_WSD is defined, it means that the target platform does
@@ -14190,16 +16370,22 @@ 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 DbClientData DbClientData;
+typedef struct DbFixer DbFixer;
typedef struct Schema Schema;
typedef struct Expr Expr;
typedef struct ExprList ExprList;
typedef struct FKey FKey;
+typedef struct FpDecode FpDecode;
typedef struct FuncDestructor FuncDestructor;
typedef struct FuncDef FuncDef;
typedef struct FuncDefHash FuncDefHash;
typedef struct IdList IdList;
typedef struct Index Index;
+typedef struct IndexedExpr IndexedExpr;
typedef struct IndexSample IndexSample;
typedef struct KeyClass KeyClass;
typedef struct KeyInfo KeyInfo;
@@ -14207,15 +16393,21 @@ typedef struct Lookaside Lookaside;
typedef struct LookasideSlot LookasideSlot;
typedef struct Module Module;
typedef struct NameContext NameContext;
+typedef struct OnOrUsing OnOrUsing;
typedef struct Parse Parse;
+typedef struct ParseCleanup ParseCleanup;
typedef struct PreUpdate PreUpdate;
typedef struct PrintfArguments PrintfArguments;
+typedef struct RCStr RCStr;
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 Subquery Subquery;
+typedef struct SrcItem SrcItem;
typedef struct SrcList SrcList;
typedef struct sqlite3_str StrAccum; /* Internal alias for sqlite3_str */
typedef struct Table Table;
@@ -14256,9 +16448,12 @@ typedef struct With With;
/*
** A bit in a Bitmask
*/
-#define MASKBIT(n) (((Bitmask)1)<<(n))
-#define MASKBIT32(n) (((unsigned int)1)<<(n))
-#define ALLBITS ((Bitmask)-1)
+#define MASKBIT(n) (((Bitmask)1)<<(n))
+#define MASKBIT64(n) (((u64)1)<<(n))
+#define MASKBIT32(n) (((unsigned int)1)<<(n))
+#define SMASKBIT32(n) ((n)<=31?((unsigned int)1)<<(n):0)
+#define ALLBITS ((Bitmask)-1)
+#define TOPBIT (((Bitmask)1)<<(BMS-1))
/* A VList object records a mapping between parameters/variables/wildcards
** in the SQL statement (such as $abc, @pqr, or :xyz) and the integer
@@ -14273,6 +16468,599 @@ typedef int VList;
** "BusyHandler" typedefs. vdbe.h also requires a few of the opaque
** pointer types (i.e. FuncDef) defined above.
*/
+/************** Include os.h in the middle of sqliteInt.h ********************/
+/************** Begin file os.h **********************************************/
+/*
+** 2001 September 16
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+******************************************************************************
+**
+** This header file (together with is companion C source-code file
+** "os.c") attempt to abstract the underlying operating system so that
+** the SQLite library will work on both POSIX and windows systems.
+**
+** This header file is #include-ed by sqliteInt.h and thus ends up
+** being included by every source file.
+*/
+#ifndef _SQLITE_OS_H_
+#define _SQLITE_OS_H_
+
+/*
+** Attempt to automatically detect the operating system and setup the
+** necessary pre-processor macros for it.
+*/
+/************** Include os_setup.h in the middle of os.h *********************/
+/************** Begin file os_setup.h ****************************************/
+/*
+** 2013 November 25
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+******************************************************************************
+**
+** This file contains pre-processor directives related to operating system
+** detection and/or setup.
+*/
+#ifndef SQLITE_OS_SETUP_H
+#define SQLITE_OS_SETUP_H
+
+/*
+** Figure out if we are dealing with Unix, Windows, or some other operating
+** system.
+**
+** After the following block of preprocess macros, all of
+**
+** SQLITE_OS_KV
+** SQLITE_OS_OTHER
+** SQLITE_OS_UNIX
+** SQLITE_OS_WIN
+**
+** will defined to either 1 or 0. One of them will be 1. The others will be 0.
+** If none of the macros are initially defined, then select either
+** SQLITE_OS_UNIX or SQLITE_OS_WIN depending on the target platform.
+**
+** If SQLITE_OS_OTHER=1 is specified at compile-time, then the application
+** must provide its own VFS implementation together with sqlite3_os_init()
+** and sqlite3_os_end() routines.
+*/
+#if SQLITE_OS_KV+1<=1 && SQLITE_OS_OTHER+1<=1 && \
+ SQLITE_OS_WIN+1<=1 && SQLITE_OS_UNIX+1<=1
+# if defined(_WIN32) || defined(WIN32) || defined(__CYGWIN__) || \
+ defined(__MINGW32__) || defined(__BORLANDC__)
+# define SQLITE_OS_WIN 1
+# define SQLITE_OS_UNIX 0
+# else
+# define SQLITE_OS_WIN 0
+# define SQLITE_OS_UNIX 1
+# endif
+#endif
+#if SQLITE_OS_OTHER+1>1
+# undef SQLITE_OS_KV
+# define SQLITE_OS_KV 0
+# undef SQLITE_OS_UNIX
+# define SQLITE_OS_UNIX 0
+# undef SQLITE_OS_WIN
+# define SQLITE_OS_WIN 0
+#endif
+#if SQLITE_OS_KV+1>1
+# undef SQLITE_OS_OTHER
+# define SQLITE_OS_OTHER 0
+# undef SQLITE_OS_UNIX
+# define SQLITE_OS_UNIX 0
+# undef SQLITE_OS_WIN
+# define SQLITE_OS_WIN 0
+# define SQLITE_OMIT_LOAD_EXTENSION 1
+# define SQLITE_OMIT_WAL 1
+# define SQLITE_OMIT_DEPRECATED 1
+# undef SQLITE_TEMP_STORE
+# define SQLITE_TEMP_STORE 3 /* Always use memory for temporary storage */
+# define SQLITE_DQS 0
+# define SQLITE_OMIT_SHARED_CACHE 1
+# define SQLITE_OMIT_AUTOINIT 1
+#endif
+#if SQLITE_OS_UNIX+1>1
+# undef SQLITE_OS_KV
+# define SQLITE_OS_KV 0
+# undef SQLITE_OS_OTHER
+# define SQLITE_OS_OTHER 0
+# undef SQLITE_OS_WIN
+# define SQLITE_OS_WIN 0
+#endif
+#if SQLITE_OS_WIN+1>1
+# undef SQLITE_OS_KV
+# define SQLITE_OS_KV 0
+# undef SQLITE_OS_OTHER
+# define SQLITE_OS_OTHER 0
+# undef SQLITE_OS_UNIX
+# define SQLITE_OS_UNIX 0
+#endif
+
+
+#endif /* SQLITE_OS_SETUP_H */
+
+/************** End of os_setup.h ********************************************/
+/************** Continuing where we left off in os.h *************************/
+
+/* If the SET_FULLSYNC macro is not defined above, then make it
+** a no-op
+*/
+#ifndef SET_FULLSYNC
+# 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
+
+/* Maximum number of symlinks that will be resolved while trying to
+** expand a filename in xFullPathname() in the VFS.
+*/
+#ifndef SQLITE_MAX_SYMLINK
+# define SQLITE_MAX_SYMLINK 200
+#endif
+
+/*
+** The default size of a disk sector
+*/
+#ifndef SQLITE_DEFAULT_SECTOR_SIZE
+# define SQLITE_DEFAULT_SECTOR_SIZE 4096
+#endif
+
+/*
+** Temporary files are named starting with this prefix followed by 16 random
+** alphanumeric characters, and no file extension. They are stored in the
+** OS's standard temporary file directory, and are deleted prior to exit.
+** If sqlite is being embedded in another program, you may wish to change the
+** prefix to reflect your program's name, so that if your program exits
+** prematurely, old temporary files can be easily identified. This can be done
+** using -DSQLITE_TEMP_FILE_PREFIX=myprefix_ on the compiler command line.
+**
+** 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
+** 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"
+** 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
+** of the file.
+*/
+#ifndef SQLITE_TEMP_FILE_PREFIX
+# define SQLITE_TEMP_FILE_PREFIX "etilqs_"
+#endif
+
+/*
+** The following values may be passed as the second argument to
+** sqlite3OsLock(). The various locks exhibit the following semantics:
+**
+** SHARED: Any number of processes may hold a SHARED lock simultaneously.
+** RESERVED: A single process may hold a RESERVED lock on a file at
+** any time. Other processes may hold and obtain new SHARED locks.
+** PENDING: A single process may hold a PENDING lock on a file at
+** any one time. Existing SHARED locks may persist, but no new
+** SHARED locks may be obtained by other processes.
+** EXCLUSIVE: An EXCLUSIVE lock precludes all other locks.
+**
+** PENDING_LOCK may not be passed directly to sqlite3OsLock(). Instead, a
+** process that requests an EXCLUSIVE lock may actually obtain a PENDING
+** lock. This can be upgraded to an EXCLUSIVE lock by a subsequent call to
+** sqlite3OsLock().
+*/
+#define NO_LOCK 0
+#define SHARED_LOCK 1
+#define RESERVED_LOCK 2
+#define PENDING_LOCK 3
+#define EXCLUSIVE_LOCK 4
+
+/*
+** File Locking Notes: (Mostly about windows but also some info for Unix)
+**
+** We cannot use LockFileEx() or UnlockFileEx() on Win95/98/ME because
+** those functions are not available. So we use only LockFile() and
+** 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
+** 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
+** a single byte of the file that is designated as the reserved lock byte.
+** A PENDING_LOCK is obtained by locking a designated byte different from
+** the RESERVED_LOCK byte.
+**
+** On WinNT/2K/XP systems, LockFileEx() and UnlockFileEx() are available,
+** which means we can use reader/writer locks. When reader/writer locks
+** are used, the lock is placed on the same range of bytes that is used
+** for probabilistic locking in Win95/98/ME. Hence, the locking scheme
+** will support two or more Win95 readers or two or more WinNT readers.
+** But a single Win95 reader will lock out all WinNT readers and a single
+** WinNT reader will lock out all other Win95 readers.
+**
+** 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.
+**
+** The same locking strategy and
+** byte ranges are used for Unix. This leaves open the possibility of having
+** clients on win95, winNT, and unix all talking to the same shared file
+** and all locking correctly. To do so would require that samba (or whatever
+** tool is being used for file sharing) implements locks correctly between
+** windows and unix. I'm guessing that isn't likely to happen, but by
+** using the same locking range we are at least open to the possibility.
+**
+** Locking in windows is manditory. For this reason, we cannot store
+** actual data in the bytes used for locking. The pager never allocates
+** the pages involved in locking therefore. SHARED_SIZE is selected so
+** 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
+** by setting PENDING_BYTE low and running the entire regression suite.
+**
+** Changing the value of PENDING_BYTE results in a subtly incompatible
+** file format. Depending on how it is changed, you might not notice
+** the incompatibility right away, even running a full regression test.
+** The default location of PENDING_BYTE is the first byte past the
+** 1GB boundary.
+**
+*/
+#ifdef SQLITE_OMIT_WSD
+# define PENDING_BYTE (0x40000000)
+#else
+# define PENDING_BYTE sqlite3PendingByte
+#endif
+#define RESERVED_BYTE (PENDING_BYTE+1)
+#define SHARED_FIRST (PENDING_BYTE+2)
+#define SHARED_SIZE 510
+
+/*
+** Wrapper around OS specific sqlite3_os_init() function.
+*/
+SQLITE_PRIVATE int sqlite3OsInit(void);
+
+/*
+** Functions for accessing sqlite3_file methods
+*/
+SQLITE_PRIVATE void sqlite3OsClose(sqlite3_file*);
+SQLITE_PRIVATE int sqlite3OsRead(sqlite3_file*, void*, int amt, i64 offset);
+SQLITE_PRIVATE int sqlite3OsWrite(sqlite3_file*, const void*, int amt, i64 offset);
+SQLITE_PRIVATE int sqlite3OsTruncate(sqlite3_file*, i64 size);
+SQLITE_PRIVATE int sqlite3OsSync(sqlite3_file*, int);
+SQLITE_PRIVATE int sqlite3OsFileSize(sqlite3_file*, i64 *pSize);
+SQLITE_PRIVATE int sqlite3OsLock(sqlite3_file*, int);
+SQLITE_PRIVATE int sqlite3OsUnlock(sqlite3_file*, int);
+SQLITE_PRIVATE int sqlite3OsCheckReservedLock(sqlite3_file *id, int *pResOut);
+SQLITE_PRIVATE int sqlite3OsFileControl(sqlite3_file*,int,void*);
+SQLITE_PRIVATE void sqlite3OsFileControlHint(sqlite3_file*,int,void*);
+#define SQLITE_FCNTL_DB_UNCHANGED 0xca093fa0
+SQLITE_PRIVATE int sqlite3OsSectorSize(sqlite3_file *id);
+SQLITE_PRIVATE int sqlite3OsDeviceCharacteristics(sqlite3_file *id);
+#ifndef SQLITE_OMIT_WAL
+SQLITE_PRIVATE int sqlite3OsShmMap(sqlite3_file *,int,int,int,void volatile **);
+SQLITE_PRIVATE int sqlite3OsShmLock(sqlite3_file *id, int, int, int);
+SQLITE_PRIVATE void sqlite3OsShmBarrier(sqlite3_file *id);
+SQLITE_PRIVATE int sqlite3OsShmUnmap(sqlite3_file *id, int);
+#endif /* SQLITE_OMIT_WAL */
+SQLITE_PRIVATE int sqlite3OsFetch(sqlite3_file *id, i64, int, void **);
+SQLITE_PRIVATE int sqlite3OsUnfetch(sqlite3_file *, i64, void *);
+
+
+/*
+** 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);
+SQLITE_PRIVATE int sqlite3OsAccess(sqlite3_vfs *, const char *, int, int *pResOut);
+SQLITE_PRIVATE int sqlite3OsFullPathname(sqlite3_vfs *, const char *, int, char *);
+#ifndef SQLITE_OMIT_LOAD_EXTENSION
+SQLITE_PRIVATE void *sqlite3OsDlOpen(sqlite3_vfs *, const char *);
+SQLITE_PRIVATE void sqlite3OsDlError(sqlite3_vfs *, int, char *);
+SQLITE_PRIVATE void (*sqlite3OsDlSym(sqlite3_vfs *, void *, const char *))(void);
+SQLITE_PRIVATE void sqlite3OsDlClose(sqlite3_vfs *, void *);
+#endif /* SQLITE_OMIT_LOAD_EXTENSION */
+SQLITE_PRIVATE int sqlite3OsRandomness(sqlite3_vfs *, int, char *);
+SQLITE_PRIVATE int sqlite3OsSleep(sqlite3_vfs *, int);
+SQLITE_PRIVATE int sqlite3OsGetLastError(sqlite3_vfs*);
+SQLITE_PRIVATE int sqlite3OsCurrentTimeInt64(sqlite3_vfs *, sqlite3_int64*);
+
+/*
+** 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*);
+SQLITE_PRIVATE void sqlite3OsCloseFree(sqlite3_file *);
+
+#endif /* _SQLITE_OS_H_ */
+
+/************** End of os.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_SJ_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_SJ_PGNO_COMPUTED(x) ((Pgno)((PENDING_BYTE/((x)->pageSize))+1))
+#define PAGER_SJ_PGNO(x) ((x)->lckPgno)
+
+/*
+** 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 */
+
+#define isWalMode(x) ((x)==PAGER_JOURNALMODE_WAL)
+
+/*
+** The argument to this macro is a file descriptor (type sqlite3_file*).
+** Return 0 if it is not open, or non-zero (but not 1) if it is.
+**
+** This is so that expressions can be written as:
+**
+** if( isOpen(pPager->jfd) ){ ...
+**
+** instead of
+**
+** if( pPager->jfd->pMethods ){ ...
+*/
+#define isOpen(pFd) ((pFd)->pMethods!=0)
+
+/*
+** 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, u64*);
+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
+
+#if defined(SQLITE_USE_SEH) && !defined(SQLITE_OMIT_WAL)
+SQLITE_PRIVATE int sqlite3PagerWalSystemErrno(Pager*);
+#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 *******************************************/
/*
@@ -14348,33 +17136,41 @@ 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 *);
+SQLITE_PRIVATE int sqlite3BtreeCopyFile(Btree*, Btree*);
SQLITE_PRIVATE int sqlite3BtreeIncrVacuum(Btree *);
@@ -14392,7 +17188,7 @@ SQLITE_PRIVATE int sqlite3BtreeIncrVacuum(Btree *);
#define BTREE_BLOBKEY 2 /* Table has keys only - no data */
SQLITE_PRIVATE int sqlite3BtreeDropTable(Btree*, int, int*);
-SQLITE_PRIVATE int sqlite3BtreeClearTable(Btree*, int, int*);
+SQLITE_PRIVATE int sqlite3BtreeClearTable(Btree*, int, i64*);
SQLITE_PRIVATE int sqlite3BtreeClearTableOfCursor(BtCursor*);
SQLITE_PRIVATE int sqlite3BtreeTripAllCursors(Btree*, int, int);
@@ -14403,7 +17199,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:
**
@@ -14452,7 +17248,7 @@ SQLITE_PRIVATE int sqlite3BtreeNewDb(Btree *p);
** reduce network bandwidth.
**
** Note that BTREE_HINT_FLAGS with BTREE_BULKLOAD is the only hint used by
-** standard SQLite. The other hints are provided for extentions that use
+** standard SQLite. The other hints are provided for extensions that use
** the SQLite parser and code generator but substitute their own storage
** engine.
*/
@@ -14474,7 +17270,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
@@ -14502,13 +17298,16 @@ 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 */
);
SQLITE_PRIVATE BtCursor *sqlite3BtreeFakeValidCursor(void);
SQLITE_PRIVATE int sqlite3BtreeCursorSize(void);
+#ifdef SQLITE_DEBUG
+SQLITE_PRIVATE int sqlite3BtreeClosesWithCursor(Btree*,BtCursor*);
+#endif
SQLITE_PRIVATE void sqlite3BtreeCursorZero(BtCursor*);
SQLITE_PRIVATE void sqlite3BtreeCursorHintFlags(BtCursor*, unsigned);
#ifdef SQLITE_ENABLE_CURSOR_HINTS
@@ -14516,13 +17315,17 @@ SQLITE_PRIVATE void sqlite3BtreeCursorHint(BtCursor*, int, ...);
#endif
SQLITE_PRIVATE int sqlite3BtreeCloseCursor(BtCursor*);
-SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked(
+SQLITE_PRIVATE int sqlite3BtreeTableMoveto(
BtCursor*,
- UnpackedRecord *pUnKey,
i64 intKey,
int bias,
int *pRes
);
+SQLITE_PRIVATE int sqlite3BtreeIndexMoveto(
+ BtCursor*,
+ UnpackedRecord *pUnKey,
+ int *pRes
+);
SQLITE_PRIVATE int sqlite3BtreeCursorHasMoved(BtCursor*);
SQLITE_PRIVATE int sqlite3BtreeCursorRestore(BtCursor*, int*);
SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor*, u8 flags);
@@ -14531,6 +17334,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.
@@ -14542,7 +17346,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.
@@ -14561,7 +17365,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.
*/
@@ -14578,20 +17382,30 @@ struct BtreePayload {
SQLITE_PRIVATE int sqlite3BtreeInsert(BtCursor*, const BtreePayload *pPayload,
int flags, int seekResult);
SQLITE_PRIVATE int sqlite3BtreeFirst(BtCursor*, int *pRes);
+SQLITE_PRIVATE int sqlite3BtreeIsEmpty(BtCursor *pCur, int *pRes);
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*);
-#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC
+SQLITE_PRIVATE void sqlite3BtreeCursorPin(BtCursor*);
+SQLITE_PRIVATE void sqlite3BtreeCursorUnpin(BtCursor*);
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 int sqlite3BtreeIntegrityCheck(
+ sqlite3 *db, /* Database connection that is running the check */
+ Btree *p, /* The btree to be checked */
+ Pgno *aRoot, /* An array of root pages numbers for individual trees */
+ sqlite3_value *aCnt, /* OUT: entry counts for each btree in aRoot[] */
+ int nRoot, /* Number of entries in aRoot[] */
+ int mxErr, /* Stop reporting errors after this many */
+ int *pnErr, /* OUT: Write number of errors seen to this variable */
+ char **pzOut /* OUT: Write the error message string here */
+);
SQLITE_PRIVATE struct Pager *sqlite3BtreePager(Btree*);
SQLITE_PRIVATE i64 sqlite3BtreeRowCountEst(BtCursor*);
@@ -14606,14 +17420,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);
@@ -14624,6 +17442,10 @@ SQLITE_PRIVATE void sqlite3BtreeCursorList(Btree*);
SQLITE_PRIVATE int sqlite3BtreeCheckpoint(Btree*, int, int *, int *);
#endif
+SQLITE_PRIVATE int sqlite3BtreeTransferRow(BtCursor*, BtCursor*, i64);
+
+SQLITE_PRIVATE void sqlite3BtreeClearCache(Btree*);
+
/*
** If we are not using shared cache, then there is no need to
** use mutexes to access the BtShared structures. So make the
@@ -14636,7 +17458,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)
@@ -14705,6 +17527,20 @@ typedef struct Vdbe Vdbe;
*/
typedef struct sqlite3_value Mem;
typedef struct SubProgram SubProgram;
+typedef struct SubrtnSig SubrtnSig;
+
+/*
+** A signature for a reusable subroutine that materializes the RHS of
+** an IN operator.
+*/
+struct SubrtnSig {
+ int selId; /* SELECT-id for the SELECT statement on the RHS */
+ u8 bComplete; /* True if fully coded and available for reusable */
+ char *zAff; /* Affinity of the overall IN expression */
+ int iTable; /* Ephemeral table generated by the subroutine */
+ int iAddr; /* Subroutine entry address */
+ int regReturn; /* Register used to hold return address */
+};
/*
** A single instruction of the virtual machine has an opcode
@@ -14730,25 +17566,26 @@ 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 */
+ SubrtnSig *pSubrtnSig; /* Used when p4type is P4_SUBRTNSIG */
+ Index *pIdx; /* Used when p4type is P4_INDEX */
#ifdef SQLITE_ENABLE_CURSOR_HINTS
Expr *pExpr; /* Used when p4type is P4_EXPR */
#endif
- int (*xAdvance)(BtCursor *, int);
} p4;
#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
char *zComment; /* Comment to improve readability */
#endif
-#ifdef VDBE_PROFILE
- u32 cnt; /* Number of times this instruction was executed */
- u64 cycles; /* Total time spent executing this instruction */
-#endif
#ifdef SQLITE_VDBE_COVERAGE
u32 iSrcLine; /* Source-code line that generated this opcode
** with flags in the upper 8 bits */
#endif
+#if defined(SQLITE_ENABLE_STMT_SCANSTATUS) || defined(VDBE_PROFILE)
+ u64 nExec;
+ u64 nCycle;
+#endif
};
typedef struct VdbeOp VdbeOp;
@@ -14787,8 +17624,8 @@ typedef struct VdbeOpList VdbeOpList;
#define P4_COLLSEQ (-2) /* P4 is a pointer to a CollSeq structure */
#define P4_INT32 (-3) /* P4 is a 32-bit signed integer */
#define P4_SUBPROGRAM (-4) /* P4 is a pointer to a SubProgram structure */
-#define P4_ADVANCE (-5) /* P4 is a pointer to BtreeNext() or BtreePrev() */
-#define P4_TABLE (-6) /* P4 is a pointer to a Table structure */
+#define P4_TABLE (-5) /* P4 is a pointer to a Table structure */
+#define P4_INDEX (-6) /* P4 is a pointer to an Index structure */
/* Above do not own any resources. Must free those below */
#define P4_FREE_IF_LE (-7)
#define P4_DYNAMIC (-7) /* Pointer to memory from sqliteMalloc() */
@@ -14801,7 +17638,8 @@ typedef struct VdbeOpList VdbeOpList;
#define P4_INT64 (-14) /* P4 is a 64-bit signed integer */
#define P4_INTARRAY (-15) /* P4 is a vector of 32-bit integers */
#define P4_FUNCCTX (-16) /* P4 is a pointer to an sqlite3_context object */
-#define P4_DYNBLOB (-17) /* Pointer to memory from sqliteMalloc() */
+#define P4_TABLEREF (-17) /* Like P4_TABLE, but reference counted */
+#define P4_SUBRTNSIG (-18) /* P4 is a SubrtnSig pointer */
/* Error message codes for OP_Halt */
#define P5_ConstraintNotNull 1
@@ -14810,7 +17648,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
@@ -14846,176 +17684,195 @@ typedef struct VdbeOpList VdbeOpList;
#define OP_Savepoint 0
#define OP_AutoCommit 1
#define OP_Transaction 2
-#define OP_SorterNext 3 /* jump */
-#define OP_Prev 4 /* jump */
-#define OP_Next 5 /* jump */
-#define OP_Checkpoint 6
-#define OP_JournalMode 7
-#define OP_Vacuum 8
-#define OP_VFilter 9 /* jump, synopsis: iplan=r[P3] zplan='P4' */
-#define OP_VUpdate 10 /* synopsis: data=r[P3@P2] */
-#define OP_Goto 11 /* jump */
-#define OP_Gosub 12 /* jump */
-#define OP_InitCoroutine 13 /* jump */
-#define OP_Yield 14 /* jump */
-#define OP_MustBeInt 15 /* jump */
-#define OP_Jump 16 /* jump */
-#define OP_Once 17 /* jump */
-#define OP_If 18 /* jump */
+#define OP_Checkpoint 3
+#define OP_JournalMode 4
+#define OP_Vacuum 5
+#define OP_VFilter 6 /* jump, synopsis: iplan=r[P3] zplan='P4' */
+#define OP_VUpdate 7 /* synopsis: data=r[P3@P2] */
+#define OP_Init 8 /* jump0, synopsis: Start at P2 */
+#define OP_Goto 9 /* jump */
+#define OP_Gosub 10 /* jump */
+#define OP_InitCoroutine 11 /* jump0 */
+#define OP_Yield 12 /* jump0 */
+#define OP_MustBeInt 13 /* jump0 */
+#define OP_Jump 14 /* jump */
+#define OP_Once 15 /* jump */
+#define OP_If 16 /* jump */
+#define OP_IfNot 17 /* jump */
+#define OP_IsType 18 /* jump, synopsis: if typeof(P1.P3) in P5 goto P2 */
#define OP_Not 19 /* same as TK_NOT, synopsis: r[P2]= !r[P1] */
-#define OP_IfNot 20 /* jump */
-#define OP_IfNullRow 21 /* jump, synopsis: if P1.nullRow then r[P3]=NULL, goto P2 */
-#define OP_SeekLT 22 /* jump, synopsis: key=r[P3@P4] */
-#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_IfNullRow 20 /* jump, synopsis: if P1.nullRow then r[P3]=NULL, goto P2 */
+#define OP_SeekLT 21 /* jump0, synopsis: key=r[P3@P4] */
+#define OP_SeekLE 22 /* jump0, synopsis: key=r[P3@P4] */
+#define OP_SeekGE 23 /* jump0, synopsis: key=r[P3@P4] */
+#define OP_SeekGT 24 /* jump0, synopsis: key=r[P3@P4] */
+#define OP_IfNotOpen 25 /* jump, synopsis: if( !csr[P1] ) goto P2 */
#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_SeekRowid 30 /* jump0, 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_Last 32 /* jump0 */
+#define OP_IfSizeBetween 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_Rewind 36 /* jump0 */
+#define OP_IfEmpty 37 /* jump, synopsis: if( empty(P1) ) goto P2 */
+#define OP_SorterNext 38 /* jump */
+#define OP_Prev 39 /* jump */
+#define OP_Next 40 /* jump */
+#define OP_IdxLE 41 /* jump, synopsis: key=r[P3@P4] */
+#define OP_IdxGT 42 /* jump, synopsis: key=r[P3@P4] */
#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_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] */
-#define OP_Eq 53 /* jump, same as TK_EQ, synopsis: IF r[P3]==r[P1] */
-#define OP_Gt 54 /* jump, same as TK_GT, synopsis: IF r[P3]>r[P1] */
-#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_ResultRow 81 /* synopsis: output=r[P1@P2] */
-#define OP_CollSeq 82
-#define OP_AddImm 83 /* synopsis: r[P1]=r[P1]+P2 */
-#define OP_RealAffinity 84
-#define OP_Cast 85 /* synopsis: affinity(r[P1]) */
-#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_MakeRecord 92 /* synopsis: r[P3]=mkrec(r[P1@P2]) */
-#define OP_Count 93 /* synopsis: r[P2]=count() */
-#define OP_ReadCookie 94
-#define OP_SetCookie 95
-#define OP_BitAnd 96 /* same as TK_BITAND, synopsis: r[P3]=r[P1]&r[P2] */
-#define OP_BitOr 97 /* same as TK_BITOR, synopsis: r[P3]=r[P1]|r[P2] */
-#define OP_ShiftLeft 98 /* same as TK_LSHIFT, synopsis: r[P3]=r[P2]<>r[P1] */
-#define OP_Add 100 /* same as TK_PLUS, synopsis: r[P3]=r[P1]+r[P2] */
-#define OP_Subtract 101 /* same as TK_MINUS, synopsis: r[P3]=r[P2]-r[P1] */
-#define OP_Multiply 102 /* same as TK_STAR, synopsis: r[P3]=r[P1]*r[P2] */
-#define OP_Divide 103 /* same as TK_SLASH, synopsis: r[P3]=r[P2]/r[P1] */
-#define OP_Remainder 104 /* same as TK_REM, synopsis: r[P3]=r[P2]%r[P1] */
-#define OP_Concat 105 /* same as TK_CONCAT, synopsis: r[P3]=r[P2]+r[P1] */
-#define OP_ReopenIdx 106 /* synopsis: root=P2 iDb=P3 */
-#define OP_BitNot 107 /* same as TK_BITNOT, synopsis: r[P2]= ~r[P1] */
-#define OP_OpenRead 108 /* synopsis: root=P2 iDb=P3 */
-#define OP_OpenWrite 109 /* synopsis: root=P2 iDb=P3 */
-#define OP_String8 110 /* same as TK_STRING, synopsis: r[P2]='P4' */
-#define OP_OpenDup 111
-#define OP_OpenAutoindex 112 /* synopsis: nColumn=P2 */
-#define OP_OpenEphemeral 113 /* synopsis: nColumn=P2 */
-#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_Delete 123
-#define OP_ResetCount 124
-#define OP_SorterCompare 125 /* synopsis: if key(P1)!=trim(r[P3],P4) goto P2 */
-#define OP_SorterData 126 /* synopsis: r[P2]=data */
-#define OP_RowData 127 /* synopsis: r[P2]=data */
-#define OP_Rowid 128 /* synopsis: r[P2]=rowid */
-#define OP_NullRow 129
-#define OP_SeekEnd 130
-#define OP_SorterInsert 131 /* synopsis: key=r[P2] */
-#define OP_IdxInsert 132 /* synopsis: key=r[P2] */
-#define OP_IdxDelete 133 /* synopsis: key=r[P2@P3] */
-#define OP_DeferredSeek 134 /* synopsis: Move P3 to P1.rowid if needed */
-#define OP_IdxRowid 135 /* synopsis: r[P2]=rowid */
-#define OP_Destroy 136
-#define OP_Clear 137
-#define OP_ResetSorter 138
-#define OP_CreateBtree 139 /* synopsis: r[P2]=root iDb=P1 flags=P3 */
-#define OP_SqlExec 140
-#define OP_ParseSchema 141
-#define OP_LoadAnalysis 142
-#define OP_DropTable 143
-#define OP_DropIndex 144
-#define OP_Real 145 /* same as TK_FLOAT, synopsis: r[P2]=P4 */
-#define OP_DropTrigger 146
-#define OP_IntegrityCk 147
-#define OP_RowSetAdd 148 /* synopsis: rowset(P1)=r[P2] */
-#define OP_Param 149
-#define OP_FkCounter 150 /* synopsis: fkctr[P1]+=P2 */
-#define OP_MemMax 151 /* synopsis: r[P1]=max(r[P1],r[P2]) */
-#define OP_OffsetLimit 152 /* synopsis: if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1) */
-#define OP_AggInverse 153 /* synopsis: accum=r[P3] inverse(r[P2@P5]) */
-#define OP_AggStep 154 /* synopsis: accum=r[P3] step(r[P2@P5]) */
-#define OP_AggStep1 155 /* synopsis: accum=r[P3] step(r[P2@P5]) */
-#define OP_AggValue 156 /* synopsis: r[P3]=value N=P2 */
-#define OP_AggFinal 157 /* synopsis: accum=r[P1] N=P2 */
-#define OP_Expire 158
-#define OP_TableLock 159 /* synopsis: iDb=P1 root=P2 write=P3 */
-#define OP_VBegin 160
-#define OP_VCreate 161
-#define OP_VDestroy 162
-#define OP_VOpen 163
-#define OP_VColumn 164 /* synopsis: r[P3]=vcolumn(P2) */
-#define OP_VRename 165
-#define OP_Pagecount 166
-#define OP_MaxPgcnt 167
-#define OP_Trace 168
-#define OP_CursorHint 169
-#define OP_Noop 170
-#define OP_Explain 171
-#define OP_Abortable 172
+#define OP_IdxLT 45 /* jump, synopsis: key=r[P3@P4] */
+#define OP_IdxGE 46 /* jump, synopsis: key=r[P3@P4] */
+#define OP_IFindKey 47 /* jump */
+#define OP_RowSetRead 48 /* jump, synopsis: r[P3]=rowset(P1) */
+#define OP_RowSetTest 49 /* jump, synopsis: if r[P3] in rowset(P1) goto P2 */
+#define OP_Program 50 /* jump0 */
+#define OP_IsNull 51 /* jump, same as TK_ISNULL, synopsis: if r[P1]==NULL goto P2 */
+#define OP_NotNull 52 /* jump, same as TK_NOTNULL, synopsis: if r[P1]!=NULL goto P2 */
+#define OP_Ne 53 /* jump, same as TK_NE, synopsis: IF r[P3]!=r[P1] */
+#define OP_Eq 54 /* jump, same as TK_EQ, synopsis: IF r[P3]==r[P1] */
+#define OP_Gt 55 /* jump, same as TK_GT, synopsis: IF r[P3]>r[P1] */
+#define OP_Le 56 /* jump, same as TK_LE, synopsis: IF r[P3]<=r[P1] */
+#define OP_Lt 57 /* jump, same as TK_LT, synopsis: IF r[P3]=r[P1] */
+#define OP_ElseEq 59 /* jump, same as TK_ESCAPE */
+#define OP_FkIfZero 60 /* jump, synopsis: if fkctr[P1]==0 goto P2 */
+#define OP_IfPos 61 /* jump, synopsis: if r[P1]>0 then r[P1]-=P3, goto P2 */
+#define OP_IfNotZero 62 /* jump, synopsis: if r[P1]!=0 then r[P1]--, goto P2 */
+#define OP_DecrJumpZero 63 /* jump, synopsis: if (--r[P1])==0 goto P2 */
+#define OP_IncrVacuum 64 /* jump */
+#define OP_VNext 65 /* jump */
+#define OP_Filter 66 /* jump, synopsis: if key(P3@P4) not in filter(P1) goto P2 */
+#define OP_PureFunc 67 /* synopsis: r[P3]=func(r[P2@NP]) */
+#define OP_Function 68 /* synopsis: r[P3]=func(r[P2@NP]) */
+#define OP_Return 69
+#define OP_EndCoroutine 70
+#define OP_HaltIfNull 71 /* synopsis: if r[P3]=null halt */
+#define OP_Halt 72
+#define OP_Integer 73 /* synopsis: r[P2]=P1 */
+#define OP_Int64 74 /* synopsis: r[P2]=P4 */
+#define OP_String 75 /* synopsis: r[P2]='P4' (len=P1) */
+#define OP_BeginSubrtn 76 /* synopsis: r[P2]=NULL */
+#define OP_Null 77 /* synopsis: r[P2..P3]=NULL */
+#define OP_SoftNull 78 /* synopsis: r[P1]=NULL */
+#define OP_Blob 79 /* synopsis: r[P2]=P4 (len=P1) */
+#define OP_Variable 80 /* synopsis: r[P2]=parameter(P1) */
+#define OP_Move 81 /* synopsis: r[P2@P3]=r[P1@P3] */
+#define OP_Copy 82 /* synopsis: r[P2@P3+1]=r[P1@P3+1] */
+#define OP_SCopy 83 /* synopsis: r[P2]=r[P1] */
+#define OP_IntCopy 84 /* synopsis: r[P2]=r[P1] */
+#define OP_FkCheck 85
+#define OP_ResultRow 86 /* synopsis: output=r[P1@P2] */
+#define OP_CollSeq 87
+#define OP_AddImm 88 /* synopsis: r[P1]=r[P1]+P2 */
+#define OP_RealAffinity 89
+#define OP_Cast 90 /* synopsis: affinity(r[P1]) */
+#define OP_Permutation 91
+#define OP_Compare 92 /* synopsis: r[P1@P3] <-> r[P2@P3] */
+#define OP_IsTrue 93 /* synopsis: r[P2] = coalesce(r[P1]==TRUE,P3) ^ P4 */
+#define OP_ZeroOrNull 94 /* synopsis: r[P2] = 0 OR NULL */
+#define OP_Offset 95 /* synopsis: r[P3] = sqlite_offset(P1) */
+#define OP_Column 96 /* synopsis: r[P3]=PX cursor P1 column P2 */
+#define OP_TypeCheck 97 /* synopsis: typecheck(r[P1@P2]) */
+#define OP_Affinity 98 /* synopsis: affinity(r[P1@P2]) */
+#define OP_MakeRecord 99 /* synopsis: r[P3]=mkrec(r[P1@P2]) */
+#define OP_Count 100 /* synopsis: r[P2]=count() */
+#define OP_ReadCookie 101
+#define OP_SetCookie 102
+#define OP_BitAnd 103 /* same as TK_BITAND, synopsis: r[P3]=r[P1]&r[P2] */
+#define OP_BitOr 104 /* same as TK_BITOR, synopsis: r[P3]=r[P1]|r[P2] */
+#define OP_ShiftLeft 105 /* same as TK_LSHIFT, synopsis: r[P3]=r[P2]<>r[P1] */
+#define OP_Add 107 /* same as TK_PLUS, synopsis: r[P3]=r[P1]+r[P2] */
+#define OP_Subtract 108 /* same as TK_MINUS, synopsis: r[P3]=r[P2]-r[P1] */
+#define OP_Multiply 109 /* same as TK_STAR, synopsis: r[P3]=r[P1]*r[P2] */
+#define OP_Divide 110 /* same as TK_SLASH, synopsis: r[P3]=r[P2]/r[P1] */
+#define OP_Remainder 111 /* same as TK_REM, synopsis: r[P3]=r[P2]%r[P1] */
+#define OP_Concat 112 /* same as TK_CONCAT, synopsis: r[P3]=r[P2]+r[P1] */
+#define OP_ReopenIdx 113 /* synopsis: root=P2 iDb=P3 */
+#define OP_OpenRead 114 /* synopsis: root=P2 iDb=P3 */
+#define OP_BitNot 115 /* same as TK_BITNOT, synopsis: r[P2]= ~r[P1] */
+#define OP_OpenWrite 116 /* synopsis: root=P2 iDb=P3 */
+#define OP_OpenDup 117
+#define OP_String8 118 /* same as TK_STRING, synopsis: r[P2]='P4' */
+#define OP_OpenAutoindex 119 /* synopsis: nColumn=P2 */
+#define OP_OpenEphemeral 120 /* synopsis: nColumn=P2 */
+#define OP_SorterOpen 121
+#define OP_SequenceTest 122 /* synopsis: if( cursor[P1].ctr++ ) pc = P2 */
+#define OP_OpenPseudo 123 /* synopsis: P3 columns in r[P2] */
+#define OP_Close 124
+#define OP_ColumnsUsed 125
+#define OP_SeekScan 126 /* synopsis: Scan-ahead up to P1 rows */
+#define OP_SeekHit 127 /* synopsis: set P2<=seekHit<=P3 */
+#define OP_Sequence 128 /* synopsis: r[P2]=cursor[P1].ctr++ */
+#define OP_NewRowid 129 /* synopsis: r[P2]=rowid */
+#define OP_Insert 130 /* synopsis: intkey=r[P3] data=r[P2] */
+#define OP_RowCell 131
+#define OP_Delete 132
+#define OP_ResetCount 133
+#define OP_SorterCompare 134 /* synopsis: if key(P1)!=trim(r[P3],P4) goto P2 */
+#define OP_SorterData 135 /* synopsis: r[P2]=data */
+#define OP_RowData 136 /* synopsis: r[P2]=data */
+#define OP_Rowid 137 /* synopsis: r[P2]=PX rowid of P1 */
+#define OP_NullRow 138
+#define OP_SeekEnd 139
+#define OP_IdxInsert 140 /* synopsis: key=r[P2] */
+#define OP_SorterInsert 141 /* synopsis: key=r[P2] */
+#define OP_IdxDelete 142 /* synopsis: key=r[P2@P3] */
+#define OP_DeferredSeek 143 /* synopsis: Move P3 to P1.rowid if needed */
+#define OP_IdxRowid 144 /* synopsis: r[P2]=rowid */
+#define OP_FinishSeek 145
+#define OP_Destroy 146
+#define OP_Clear 147
+#define OP_ResetSorter 148
+#define OP_CreateBtree 149 /* synopsis: r[P2]=root iDb=P1 flags=P3 */
+#define OP_SqlExec 150
+#define OP_ParseSchema 151
+#define OP_LoadAnalysis 152
+#define OP_DropTable 153
+#define OP_Real 154 /* same as TK_FLOAT, synopsis: r[P2]=P4 */
+#define OP_DropIndex 155
+#define OP_DropTrigger 156
+#define OP_IntegrityCk 157
+#define OP_RowSetAdd 158 /* synopsis: rowset(P1)=r[P2] */
+#define OP_Param 159
+#define OP_FkCounter 160 /* synopsis: fkctr[P1]+=P2 */
+#define OP_MemMax 161 /* synopsis: r[P1]=max(r[P1],r[P2]) */
+#define OP_OffsetLimit 162 /* synopsis: if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1) */
+#define OP_AggInverse 163 /* synopsis: accum=r[P3] inverse(r[P2@P5]) */
+#define OP_AggStep 164 /* synopsis: accum=r[P3] step(r[P2@P5]) */
+#define OP_AggStep1 165 /* synopsis: accum=r[P3] step(r[P2@P5]) */
+#define OP_AggValue 166 /* synopsis: r[P3]=value N=P2 */
+#define OP_AggFinal 167 /* synopsis: accum=r[P1] N=P2 */
+#define OP_Expire 168
+#define OP_CursorLock 169
+#define OP_CursorUnlock 170
+#define OP_TableLock 171 /* synopsis: iDb=P1 root=P2 write=P3 */
+#define OP_VBegin 172
+#define OP_VCreate 173
+#define OP_VDestroy 174
+#define OP_VOpen 175
+#define OP_VCheck 176
+#define OP_VInitIn 177 /* synopsis: r[P2]=ValueList(P1,P3) */
+#define OP_VColumn 178 /* synopsis: r[P3]=vcolumn(P2) */
+#define OP_VRename 179
+#define OP_Pagecount 180
+#define OP_MaxPgcnt 181
+#define OP_ClrSubtype 182 /* synopsis: r[P1].subtype = 0 */
+#define OP_GetSubtype 183 /* synopsis: r[P2] = r[P1].subtype */
+#define OP_SetSubtype 184 /* synopsis: r[P2].subtype = r[P1] */
+#define OP_FilterAdd 185 /* synopsis: filter(P1) += key(P3@P4) */
+#define OP_Trace 186
+#define OP_CursorHint 187
+#define OP_ReleaseReg 188 /* synopsis: release r[P1@P2] mask P3 */
+#define OP_Noop 189
+#define OP_Explain 190
+#define OP_Abortable 191
/* Properties such as "out2" or "jump" that are specified in
** comments following the "case" for each opcode in the vdbe.c
@@ -15027,37 +17884,42 @@ typedef struct VdbeOpList VdbeOpList;
#define OPFLG_IN3 0x08 /* in3: P3 is an input */
#define OPFLG_OUT2 0x10 /* out2: P2 is an output */
#define OPFLG_OUT3 0x20 /* out3: P3 is an output */
+#define OPFLG_NCYCLE 0x40 /* ncycle:Cycles count against P1 */
+#define OPFLG_JUMP0 0x80 /* jump0: P2 might be zero */
#define OPFLG_INITIALIZER {\
-/* 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,\
-/* 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, 0x00, 0x10, 0x10, 0x00,\
-/* 96 */ 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26,\
-/* 104 */ 0x26, 0x26, 0x00, 0x12, 0x00, 0x00, 0x10, 0x00,\
-/* 112 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
-/* 120 */ 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
-/* 128 */ 0x10, 0x00, 0x00, 0x04, 0x04, 0x00, 0x00, 0x10,\
-/* 136 */ 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,\
-/* 144 */ 0x00, 0x10, 0x00, 0x00, 0x06, 0x10, 0x00, 0x04,\
-/* 152 */ 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
-/* 160 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10,\
-/* 168 */ 0x00, 0x00, 0x00, 0x00, 0x00,}
-
-/* The sqlite3P2Values() routine is able to run faster if it knows
+/* 0 */ 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x41, 0x00,\
+/* 8 */ 0x81, 0x01, 0x01, 0x81, 0x83, 0x83, 0x01, 0x01,\
+/* 16 */ 0x03, 0x03, 0x01, 0x12, 0x01, 0xc9, 0xc9, 0xc9,\
+/* 24 */ 0xc9, 0x01, 0x49, 0x49, 0x49, 0x49, 0xc9, 0x49,\
+/* 32 */ 0xc1, 0x01, 0x41, 0x41, 0xc1, 0x01, 0x01, 0x41,\
+/* 40 */ 0x41, 0x41, 0x41, 0x26, 0x26, 0x41, 0x41, 0x09,\
+/* 48 */ 0x23, 0x0b, 0x81, 0x03, 0x03, 0x0b, 0x0b, 0x0b,\
+/* 56 */ 0x0b, 0x0b, 0x0b, 0x01, 0x01, 0x03, 0x03, 0x03,\
+/* 64 */ 0x01, 0x41, 0x01, 0x00, 0x00, 0x02, 0x02, 0x08,\
+/* 72 */ 0x00, 0x10, 0x10, 0x10, 0x00, 0x10, 0x00, 0x10,\
+/* 80 */ 0x10, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00,\
+/* 88 */ 0x02, 0x02, 0x02, 0x00, 0x00, 0x12, 0x1e, 0x20,\
+/* 96 */ 0x40, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x26,\
+/* 104 */ 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26,\
+/* 112 */ 0x26, 0x40, 0x40, 0x12, 0x00, 0x40, 0x10, 0x40,\
+/* 120 */ 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x40, 0x40,\
+/* 128 */ 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,\
+/* 136 */ 0x00, 0x50, 0x00, 0x40, 0x04, 0x04, 0x00, 0x40,\
+/* 144 */ 0x50, 0x40, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00,\
+/* 152 */ 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x06, 0x10,\
+/* 160 */ 0x00, 0x04, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00,\
+/* 168 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,\
+/* 176 */ 0x10, 0x50, 0x40, 0x00, 0x10, 0x10, 0x02, 0x12,\
+/* 184 */ 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
+}
+
+/* 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 66 /* Maximum JUMP opcode */
/************** End of opcodes.h *********************************************/
/************** Continuing where we left off in vdbe.h ***********************/
@@ -15066,13 +17928,14 @@ typedef struct VdbeOpList VdbeOpList;
** Additional non-public SQLITE_PREPARE_* flags
*/
#define SQLITE_PREPARE_SAVESQL 0x80 /* Preserve SQL text */
-#define SQLITE_PREPARE_MASK 0x0f /* Mask of public flags */
+#define SQLITE_PREPARE_MASK 0x3f /* Mask of public flags */
/*
** Prototypes for the VDBE interface. See comments on the implementation
** 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);
@@ -15083,6 +17946,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);
@@ -15093,19 +17957,27 @@ SQLITE_PRIVATE void sqlite3VdbeVerifyNoResultRow(Vdbe *p);
#endif
#if defined(SQLITE_DEBUG)
SQLITE_PRIVATE void sqlite3VdbeVerifyAbortable(Vdbe *p, int);
+SQLITE_PRIVATE void sqlite3VdbeNoJumpsOutsideSubrtn(Vdbe*,int,int,int);
#else
# define sqlite3VdbeVerifyAbortable(A,B)
+# define sqlite3VdbeNoJumpsOutsideSubrtn(A,B,C,D)
#endif
SQLITE_PRIVATE VdbeOp *sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp,int iLineno);
#ifndef SQLITE_OMIT_EXPLAIN
-SQLITE_PRIVATE void sqlite3VdbeExplain(Parse*,u8,const char*,...);
+SQLITE_PRIVATE int sqlite3VdbeExplain(Parse*,u8,const char*,...);
SQLITE_PRIVATE void sqlite3VdbeExplainPop(Parse*);
SQLITE_PRIVATE int sqlite3VdbeExplainParent(Parse*);
# define ExplainQueryPlan(P) sqlite3VdbeExplain P
+# ifdef SQLITE_ENABLE_STMT_SCANSTATUS
+# define ExplainQueryPlan2(V,P) (V = sqlite3VdbeExplain P)
+# else
+# define ExplainQueryPlan2(V,P) ExplainQueryPlan(P)
+# endif
# define ExplainQueryPlanPop(P) sqlite3VdbeExplainPop(P)
# define ExplainQueryPlanParent(P) sqlite3VdbeExplainParent(P)
#else
# define ExplainQueryPlan(P)
+# define ExplainQueryPlan2(V,P)
# define ExplainQueryPlanPop(P)
# define ExplainQueryPlanParent(P) 0
# define sqlite3ExplainBreakpoint(A,B) /*no-op*/
@@ -15115,25 +17987,32 @@ SQLITE_PRIVATE void sqlite3ExplainBreakpoint(const char*,const char*);
#else
# 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);
+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 sqlite3VdbeTypeofColumn(Vdbe*, int);
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 VdbeOp *sqlite3VdbeGetLastOp(Vdbe*);
SQLITE_PRIVATE int sqlite3VdbeMakeLabel(Parse*);
SQLITE_PRIVATE void sqlite3VdbeRunOnlyOnce(Vdbe*);
SQLITE_PRIVATE void sqlite3VdbeReusable(Vdbe*);
SQLITE_PRIVATE void sqlite3VdbeDelete(Vdbe*);
-SQLITE_PRIVATE void sqlite3VdbeClearObject(sqlite3*,Vdbe*);
SQLITE_PRIVATE void sqlite3VdbeMakeReady(Vdbe*,Parse*);
SQLITE_PRIVATE int sqlite3VdbeFinalize(Vdbe*);
SQLITE_PRIVATE void sqlite3VdbeResolveLabel(Vdbe*, int);
@@ -15163,8 +18042,11 @@ SQLITE_PRIVATE char *sqlite3VdbeExpandSql(Vdbe*, const char*);
#endif
SQLITE_PRIVATE int sqlite3MemCompare(const Mem*, const Mem*, const CollSeq*);
SQLITE_PRIVATE int sqlite3BlobCompare(const Mem*, const Mem*);
+#ifdef SQLITE_ENABLE_PERCENTILE
+SQLITE_PRIVATE const char *sqlite3VdbeFuncName(const sqlite3_context*);
+#endif
-SQLITE_PRIVATE void sqlite3VdbeRecordUnpack(KeyInfo*,int,const void*,UnpackedRecord*);
+SQLITE_PRIVATE void sqlite3VdbeRecordUnpack(int,const void*,UnpackedRecord*);
SQLITE_PRIVATE int sqlite3VdbeRecordCompare(int,const void*,UnpackedRecord*);
SQLITE_PRIVATE int sqlite3VdbeRecordCompareWithSkip(int, const void *, UnpackedRecord *, int);
SQLITE_PRIVATE UnpackedRecord *sqlite3VdbeAllocUnpackedRecord(KeyInfo*);
@@ -15172,14 +18054,20 @@ 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 void sqlite3MemSetArrayInt64(sqlite3_value *aMem, int iIdx, i64 val);
+
+#ifndef SQLITE_OMIT_DATETIME_FUNCS
SQLITE_PRIVATE int sqlite3NotPureFunc(sqlite3_context*);
+#endif
+#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.
+/* Use SQLITE_ENABLE_EXPLAIN_COMMENTS to enable generation of extra
+** comments on each VDBE opcode.
**
** Use the SQLITE_ENABLE_MODULE_COMMENTS macro to see some extra no-op
** comments in VDBE programs that show key decision points in the code
@@ -15205,7 +18093,7 @@ SQLITE_PRIVATE void sqlite3VdbeNoopComment(Vdbe*, const char*, ...);
** The VdbeCoverage macros are used to set a coverage testing point
** for VDBE branch instructions. The coverage testing points are line
** numbers in the sqlite3.c source file. VDBE branch coverage testing
-** only works with an amalagmation build. That's ok since a VDBE branch
+** only works with an amalgamation build. That's ok since a VDBE branch
** coverage build designed for testing the test suite only. No application
** should ever ship with VDBE branch coverage measuring turned on.
**
@@ -15223,7 +18111,7 @@ SQLITE_PRIVATE void sqlite3VdbeNoopComment(Vdbe*, const char*, ...);
** // NULL option is not possible
**
** VdbeCoverageEqNe(v) // Previous OP_Jump is only interested
-** // in distingishing equal and not-equal.
+** // in distinguishing equal and not-equal.
**
** Every VDBE branch operation must be tagged with one of the macros above.
** If not, then when "make test" is run with -DSQLITE_VDBE_COVERAGE and
@@ -15233,7 +18121,7 @@ SQLITE_PRIVATE void sqlite3VdbeNoopComment(Vdbe*, const char*, ...);
** During testing, the test application will invoke
** sqlite3_test_control(SQLITE_TESTCTRL_VDBE_COVERAGE,...) to set a callback
** routine that is invoked as each bytecode branch is taken. The callback
-** contains the sqlite3.c source line number ov the VdbeCoverage macro and
+** contains the sqlite3.c source line number of the VdbeCoverage macro and
** flags to indicate whether or not the branch was taken. The test application
** is responsible for keeping track of this and reporting byte-code branches
** that are never taken.
@@ -15269,268 +18157,25 @@ SQLITE_PRIVATE void sqlite3VdbeSetLineNumber(Vdbe*,int);
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
SQLITE_PRIVATE void sqlite3VdbeScanStatus(Vdbe*, int, int, int, LogEst, const char*);
+SQLITE_PRIVATE void sqlite3VdbeScanStatusRange(Vdbe*, int, int, int);
+SQLITE_PRIVATE void sqlite3VdbeScanStatusCounters(Vdbe*, int, int, int);
#else
-# define sqlite3VdbeScanStatus(a,b,c,d,e)
+# define sqlite3VdbeScanStatus(a,b,c,d,e,f)
+# define sqlite3VdbeScanStatusRange(a,b,c,d)
+# define sqlite3VdbeScanStatusCounters(a,b,c,d)
#endif
#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE)
SQLITE_PRIVATE void sqlite3VdbePrintOp(FILE*, int, VdbeOp*);
#endif
-#endif /* SQLITE_VDBE_H */
-
-/************** 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_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
-#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(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()
+#if defined(SQLITE_ENABLE_CURSOR_HINTS) && defined(SQLITE_DEBUG)
+SQLITE_PRIVATE int sqlite3CursorRangeHintExprCheck(Walker *pWalker, Expr *pExpr);
#endif
-#endif /* SQLITE_PAGER_H */
+#endif /* SQLITE_VDBE_H */
-/************** End of pager.h ***********************************************/
+/************** End of vdbe.h ************************************************/
/************** Continuing where we left off in sqliteInt.h ******************/
/************** Include pcache.h in the middle of sqliteInt.h ****************/
/************** Begin file pcache.h ******************************************/
@@ -15546,7 +18191,7 @@ SQLITE_PRIVATE void sqlite3PagerRefdump(Pager*);
**
*************************************************************************
** This header file defines the interface that the sqlite page cache
-** subsystem.
+** subsystem.
*/
#ifndef _PCACHE_H_
@@ -15565,18 +18210,18 @@ struct PgHdr {
PCache *pCache; /* PRIVATE: Cache that owns this page */
PgHdr *pDirty; /* Transient list of dirty sorted by pgno */
Pager *pPager; /* The pager this page is part of */
- Pgno pgno; /* Page number for this page */
#ifdef SQLITE_CHECK_PAGES
- u32 pageHash; /* Hash of page content */
+ u64 pageHash; /* Hash of page content */
#endif
+ Pgno pgno; /* Page number for this page */
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.
*/
- i16 nRef; /* Number of users of this page */
+ i64 nRef; /* Number of users of this page */
PgHdr *pDirtyNext; /* Next element in list of dirty pages */
PgHdr *pDirtyPrev; /* Previous element in list of dirty pages */
/* NB: pDirtyNext and pDirtyPrev are undefined if the
@@ -15625,7 +18270,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**);
@@ -15657,19 +18302,19 @@ SQLITE_PRIVATE void sqlite3PcacheClearSyncFlags(PCache *);
SQLITE_PRIVATE void sqlite3PcacheClear(PCache*);
/* Return the total number of outstanding page references */
-SQLITE_PRIVATE int sqlite3PcacheRefCount(PCache*);
+SQLITE_PRIVATE i64 sqlite3PcacheRefCount(PCache*);
/* Increment the reference count of an existing page */
SQLITE_PRIVATE void sqlite3PcacheRef(PgHdr*);
-SQLITE_PRIVATE int sqlite3PcachePageRefcount(PgHdr*);
+SQLITE_PRIVATE i64 sqlite3PcachePageRefcount(PgHdr*);
/* Return the total number of pages stored in the cache */
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 *));
@@ -15727,284 +18372,6 @@ SQLITE_PRIVATE int sqlite3PCacheIsDirty(PCache *pCache);
/************** End of pcache.h **********************************************/
/************** Continuing where we left off in sqliteInt.h ******************/
-/************** Include os.h in the middle of sqliteInt.h ********************/
-/************** Begin file os.h **********************************************/
-/*
-** 2001 September 16
-**
-** The author disclaims copyright to this source code. In place of
-** a legal notice, here is a blessing:
-**
-** May you do good and not evil.
-** May you find forgiveness for yourself and forgive others.
-** May you share freely, never taking more than you give.
-**
-******************************************************************************
-**
-** This header file (together with is companion C source-code file
-** "os.c") attempt to abstract the underlying operating system so that
-** the SQLite library will work on both POSIX and windows systems.
-**
-** This header file is #include-ed by sqliteInt.h and thus ends up
-** being included by every source file.
-*/
-#ifndef _SQLITE_OS_H_
-#define _SQLITE_OS_H_
-
-/*
-** Attempt to automatically detect the operating system and setup the
-** necessary pre-processor macros for it.
-*/
-/************** Include os_setup.h in the middle of os.h *********************/
-/************** Begin file os_setup.h ****************************************/
-/*
-** 2013 November 25
-**
-** The author disclaims copyright to this source code. In place of
-** a legal notice, here is a blessing:
-**
-** May you do good and not evil.
-** May you find forgiveness for yourself and forgive others.
-** May you share freely, never taking more than you give.
-**
-******************************************************************************
-**
-** This file contains pre-processor directives related to operating system
-** detection and/or setup.
-*/
-#ifndef SQLITE_OS_SETUP_H
-#define SQLITE_OS_SETUP_H
-
-/*
-** Figure out if we are dealing with Unix, Windows, or some other operating
-** system.
-**
-** After the following block of preprocess macros, all of SQLITE_OS_UNIX,
-** SQLITE_OS_WIN, and SQLITE_OS_OTHER will defined to either 1 or 0. One of
-** the three will be 1. The other two will be 0.
-*/
-#if defined(SQLITE_OS_OTHER)
-# if SQLITE_OS_OTHER==1
-# undef SQLITE_OS_UNIX
-# define SQLITE_OS_UNIX 0
-# undef SQLITE_OS_WIN
-# define SQLITE_OS_WIN 0
-# else
-# undef SQLITE_OS_OTHER
-# endif
-#endif
-#if !defined(SQLITE_OS_UNIX) && !defined(SQLITE_OS_OTHER)
-# define SQLITE_OS_OTHER 0
-# ifndef SQLITE_OS_WIN
-# if defined(_WIN32) || defined(WIN32) || defined(__CYGWIN__) || \
- defined(__MINGW32__) || defined(__BORLANDC__)
-# define SQLITE_OS_WIN 1
-# define SQLITE_OS_UNIX 0
-# else
-# define SQLITE_OS_WIN 0
-# define SQLITE_OS_UNIX 1
-# endif
-# else
-# define SQLITE_OS_UNIX 0
-# endif
-#else
-# ifndef SQLITE_OS_WIN
-# define SQLITE_OS_WIN 0
-# endif
-#endif
-
-#endif /* SQLITE_OS_SETUP_H */
-
-/************** End of os_setup.h ********************************************/
-/************** Continuing where we left off in os.h *************************/
-
-/* If the SET_FULLSYNC macro is not defined above, then make it
-** a no-op
-*/
-#ifndef SET_FULLSYNC
-# define SET_FULLSYNC(x,y)
-#endif
-
-/*
-** The default size of a disk sector
-*/
-#ifndef SQLITE_DEFAULT_SECTOR_SIZE
-# define SQLITE_DEFAULT_SECTOR_SIZE 4096
-#endif
-
-/*
-** Temporary files are named starting with this prefix followed by 16 random
-** alphanumeric characters, and no file extension. They are stored in the
-** OS's standard temporary file directory, and are deleted prior to exit.
-** If sqlite is being embedded in another program, you may wish to change the
-** prefix to reflect your program's name, so that if your program exits
-** prematurely, old temporary files can be easily identified. This can be done
-** using -DSQLITE_TEMP_FILE_PREFIX=myprefix_ on the compiler command line.
-**
-** 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
-** 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"
-** 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
-** of the file.
-*/
-#ifndef SQLITE_TEMP_FILE_PREFIX
-# define SQLITE_TEMP_FILE_PREFIX "etilqs_"
-#endif
-
-/*
-** The following values may be passed as the second argument to
-** sqlite3OsLock(). The various locks exhibit the following semantics:
-**
-** SHARED: Any number of processes may hold a SHARED lock simultaneously.
-** RESERVED: A single process may hold a RESERVED lock on a file at
-** any time. Other processes may hold and obtain new SHARED locks.
-** PENDING: A single process may hold a PENDING lock on a file at
-** any one time. Existing SHARED locks may persist, but no new
-** SHARED locks may be obtained by other processes.
-** EXCLUSIVE: An EXCLUSIVE lock precludes all other locks.
-**
-** PENDING_LOCK may not be passed directly to sqlite3OsLock(). Instead, a
-** process that requests an EXCLUSIVE lock may actually obtain a PENDING
-** lock. This can be upgraded to an EXCLUSIVE lock by a subsequent call to
-** sqlite3OsLock().
-*/
-#define NO_LOCK 0
-#define SHARED_LOCK 1
-#define RESERVED_LOCK 2
-#define PENDING_LOCK 3
-#define EXCLUSIVE_LOCK 4
-
-/*
-** File Locking Notes: (Mostly about windows but also some info for Unix)
-**
-** We cannot use LockFileEx() or UnlockFileEx() on Win95/98/ME because
-** those functions are not available. So we use only LockFile() and
-** 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
-** 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
-** a single byte of the file that is designated as the reserved lock byte.
-** A PENDING_LOCK is obtained by locking a designated byte different from
-** the RESERVED_LOCK byte.
-**
-** On WinNT/2K/XP systems, LockFileEx() and UnlockFileEx() are available,
-** which means we can use reader/writer locks. When reader/writer locks
-** are used, the lock is placed on the same range of bytes that is used
-** for probabilistic locking in Win95/98/ME. Hence, the locking scheme
-** will support two or more Win95 readers or two or more WinNT readers.
-** But a single Win95 reader will lock out all WinNT readers and a single
-** WinNT reader will lock out all other Win95 readers.
-**
-** 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.
-**
-** The same locking strategy and
-** byte ranges are used for Unix. This leaves open the possibility of having
-** clients on win95, winNT, and unix all talking to the same shared file
-** and all locking correctly. To do so would require that samba (or whatever
-** tool is being used for file sharing) implements locks correctly between
-** windows and unix. I'm guessing that isn't likely to happen, but by
-** using the same locking range we are at least open to the possibility.
-**
-** Locking in windows is manditory. For this reason, we cannot store
-** actual data in the bytes used for locking. The pager never allocates
-** the pages involved in locking therefore. SHARED_SIZE is selected so
-** 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
-** by setting PENDING_BYTE low and running the entire regression suite.
-**
-** Changing the value of PENDING_BYTE results in a subtly incompatible
-** file format. Depending on how it is changed, you might not notice
-** the incompatibility right away, even running a full regression test.
-** The default location of PENDING_BYTE is the first byte past the
-** 1GB boundary.
-**
-*/
-#ifdef SQLITE_OMIT_WSD
-# define PENDING_BYTE (0x40000000)
-#else
-# define PENDING_BYTE sqlite3PendingByte
-#endif
-#define RESERVED_BYTE (PENDING_BYTE+1)
-#define SHARED_FIRST (PENDING_BYTE+2)
-#define SHARED_SIZE 510
-
-/*
-** Wrapper around OS specific sqlite3_os_init() function.
-*/
-SQLITE_PRIVATE int sqlite3OsInit(void);
-
-/*
-** Functions for accessing sqlite3_file methods
-*/
-SQLITE_PRIVATE void sqlite3OsClose(sqlite3_file*);
-SQLITE_PRIVATE int sqlite3OsRead(sqlite3_file*, void*, int amt, i64 offset);
-SQLITE_PRIVATE int sqlite3OsWrite(sqlite3_file*, const void*, int amt, i64 offset);
-SQLITE_PRIVATE int sqlite3OsTruncate(sqlite3_file*, i64 size);
-SQLITE_PRIVATE int sqlite3OsSync(sqlite3_file*, int);
-SQLITE_PRIVATE int sqlite3OsFileSize(sqlite3_file*, i64 *pSize);
-SQLITE_PRIVATE int sqlite3OsLock(sqlite3_file*, int);
-SQLITE_PRIVATE int sqlite3OsUnlock(sqlite3_file*, int);
-SQLITE_PRIVATE int sqlite3OsCheckReservedLock(sqlite3_file *id, int *pResOut);
-SQLITE_PRIVATE int sqlite3OsFileControl(sqlite3_file*,int,void*);
-SQLITE_PRIVATE void sqlite3OsFileControlHint(sqlite3_file*,int,void*);
-#define SQLITE_FCNTL_DB_UNCHANGED 0xca093fa0
-SQLITE_PRIVATE int sqlite3OsSectorSize(sqlite3_file *id);
-SQLITE_PRIVATE int sqlite3OsDeviceCharacteristics(sqlite3_file *id);
-#ifndef SQLITE_OMIT_WAL
-SQLITE_PRIVATE int sqlite3OsShmMap(sqlite3_file *,int,int,int,void volatile **);
-SQLITE_PRIVATE int sqlite3OsShmLock(sqlite3_file *id, int, int, int);
-SQLITE_PRIVATE void sqlite3OsShmBarrier(sqlite3_file *id);
-SQLITE_PRIVATE int sqlite3OsShmUnmap(sqlite3_file *id, int);
-#endif /* SQLITE_OMIT_WAL */
-SQLITE_PRIVATE int sqlite3OsFetch(sqlite3_file *id, i64, int, void **);
-SQLITE_PRIVATE int sqlite3OsUnfetch(sqlite3_file *, i64, void *);
-
-
-/*
-** 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);
-SQLITE_PRIVATE int sqlite3OsAccess(sqlite3_vfs *, const char *, int, int *pResOut);
-SQLITE_PRIVATE int sqlite3OsFullPathname(sqlite3_vfs *, const char *, int, char *);
-#ifndef SQLITE_OMIT_LOAD_EXTENSION
-SQLITE_PRIVATE void *sqlite3OsDlOpen(sqlite3_vfs *, const char *);
-SQLITE_PRIVATE void sqlite3OsDlError(sqlite3_vfs *, int, char *);
-SQLITE_PRIVATE void (*sqlite3OsDlSym(sqlite3_vfs *, void *, const char *))(void);
-SQLITE_PRIVATE void sqlite3OsDlClose(sqlite3_vfs *, void *);
-#endif /* SQLITE_OMIT_LOAD_EXTENSION */
-SQLITE_PRIVATE int sqlite3OsRandomness(sqlite3_vfs *, int, char *);
-SQLITE_PRIVATE int sqlite3OsSleep(sqlite3_vfs *, int);
-SQLITE_PRIVATE int sqlite3OsGetLastError(sqlite3_vfs*);
-SQLITE_PRIVATE int sqlite3OsCurrentTimeInt64(sqlite3_vfs *, sqlite3_int64*);
-
-/*
-** 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*);
-SQLITE_PRIVATE void sqlite3OsCloseFree(sqlite3_file *);
-
-#endif /* _SQLITE_OS_H_ */
-
-/************** End of os.h **************************************************/
-/************** Continuing where we left off in sqliteInt.h ******************/
/************** Include mutex.h in the middle of sqliteInt.h *****************/
/************** Begin file mutex.h *******************************************/
/*
@@ -16065,9 +18432,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)
@@ -16076,6 +18443,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 ***********************************************/
@@ -16092,7 +18460,7 @@ SQLITE_PRIVATE void sqlite3OsCloseFree(sqlite3_file *);
/*
** Default synchronous levels.
**
-** Note that (for historcal reasons) the PAGER_SYNCHRONOUS_* macros differ
+** Note that (for historical reasons) the PAGER_SYNCHRONOUS_* macros differ
** from the SQLITE_DEFAULT_SYNCHRONOUS value by 1.
**
** PAGER_SYNCHRONOUS DEFAULT_SYNCHRONOUS
@@ -16131,7 +18499,7 @@ struct Db {
** An instance of the following structure stores a database schema.
**
** Most Schema objects are associated with a Btree. The exception is
-** the Schema for the TEMP databaes (sqlite3.aDb[1]) which is free-standing.
+** the Schema for the TEMP database (sqlite3.aDb[1]) which is free-standing.
** In shared cache mode, a single Schema object can be shared by multiple
** Btrees that refer to the same underlying BtShared object.
**
@@ -16179,14 +18547,13 @@ 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 */
/*
** The number of different kinds of things that can be limited
** using the sqlite3_limit() interface.
*/
-#define SQLITE_N_LIMIT (SQLITE_LIMIT_WORKER_THREADS+1)
+#define SQLITE_N_LIMIT (SQLITE_LIMIT_PARSER_DEPTH+1)
/*
** Lookaside malloc is a set of fixed-size buffers that can be used
@@ -16207,22 +18574,66 @@ 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 previously 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 */
+ void *pTrueEnd; /* True value of pEnd, when db->pnBytesFreed!=0 */
};
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 lookaside */
+#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.)
@@ -16237,43 +18648,11 @@ struct FuncDefHash {
};
#define SQLITE_FUNC_HASH(C,L) (((C)+(L))%SQLITE_FUNC_HASH_SZ)
-#ifdef SQLITE_USER_AUTHENTICATION
-/*
-** Information held in the "sqlite3" database connection object and used
-** to manage user authentication.
-*/
-typedef struct sqlite3_userauth sqlite3_userauth;
-struct sqlite3_userauth {
- u8 authLevel; /* Current authentication level */
- int nAuthPW; /* Size of the zAuthPW in bytes */
- char *zAuthPW; /* Password used to authenticate */
- char *zAuthUser; /* User name used to authenticate */
-};
-
-/* Allowed values for sqlite3_userauth.authLevel */
-#define UAUTH_Unknown 0 /* Authentication not yet checked */
-#define UAUTH_Fail 1 /* User authentication failed */
-#define UAUTH_User 2 /* Authenticated as a normal user */
-#define UAUTH_Admin 3 /* Authenticated as an administrator */
-
-/* Functions used only by user authorization logic */
-SQLITE_PRIVATE int sqlite3UserAuthTable(const char*);
-SQLITE_PRIVATE int sqlite3UserAuthCheckLogin(sqlite3*,const char*,u8*);
-SQLITE_PRIVATE void sqlite3UserAuthInit(sqlite3*);
-SQLITE_PRIVATE void sqlite3CryptFunc(sqlite3_context*,int,sqlite3_value**);
-
-#endif /* SQLITE_USER_AUTHENTICATION */
-
/*
** typedef for the authorization callback function.
*/
-#ifdef SQLITE_USER_AUTHENTICATION
- typedef int (*sqlite3_xauth)(void*,int,const char*,const char*,const char*,
- const char*, const char*);
-#else
- typedef int (*sqlite3_xauth)(void*,int,const char*,const char*,const char*,
- const char*);
-#endif
+typedef int (*sqlite3_xauth)(void*,int,const char*,const char*,const char*,
+ const char*);
#ifndef SQLITE_OMIT_DEPRECATED
/* This is an extra SQLITE_TRACE macro that indicates "legacy" tracing
@@ -16287,6 +18666,11 @@ SQLITE_PRIVATE void sqlite3CryptFunc(sqlite3_context*,int,sqlite3_value**);
#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.
@@ -16294,7 +18678,7 @@ 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 */
@@ -16305,9 +18689,10 @@ struct sqlite3 {
u32 nSchemaLock; /* Do not reset the schema when non-zero */
unsigned int openFlags; /* Flags passed to sqlite3_vfs.xOpen() */
int errCode; /* Most recent error code (SQLITE_*) */
+ int errByteOffset; /* Byte offset of error in SQL statement */
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 */
@@ -16321,19 +18706,21 @@ struct sqlite3 {
u8 mTrace; /* zero or more SQLITE_TRACE flags */
u8 noSharedCache; /* True if no shared-cache backends */
u8 nSqlExec; /* Number of pending OP_SqlExec opcodes */
+ u8 eOpenState; /* Current condition of the connection */
+ u8 nFpDigit; /* Significant digits to keep on double->text */
int nextPagesize; /* Pagesize after VACUUM if >0 */
- u32 magic; /* Magic number for detect library misuse */
- int nChange; /* Value returned by sqlite3_changes() */
- int nTotalChange; /* Value returned by sqlite3_total_changes() */
+ i64 nChange; /* Value returned by sqlite3_changes() */
+ i64 nTotalChange; /* Value returned by sqlite3_total_changes() */
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 imposterTable : 2; /* Building an imposter table */
unsigned reopenMemdb : 1; /* ATTACH is really a reopen using MemDB */
+ const 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 */
@@ -16342,8 +18729,11 @@ 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 */
- void *pTraceArg; /* Argument to the trace function */
+ union {
+ void (*xLegacy)(void*,const char*); /* mTrace==SQLITE_TRACE_LEGACY */
+ int (*xV2)(u32,void*,void*,void*); /* All other mTrace values */
+ } 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 */
@@ -16354,6 +18744,9 @@ struct sqlite3 {
void (*xRollbackCallback)(void*); /* Invoked at every commit. */
void *pUpdateArg;
void (*xUpdateCallback)(void*,int, const char*,const char*,sqlite_int64);
+ void *pAutovacPagesArg; /* Client argument to autovac_pages */
+ void (*xAutovacDestr)(void*); /* Destructor for pAutovacPAgesArg */
+ unsigned int (*xAutovacPages)(void*,const char*,u32,u32,u32);
Parse *pParse; /* Current parse */
#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
void *pPreUpdateArg; /* First argument to xPreUpdateCallback */
@@ -16396,14 +18789,21 @@ 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 */
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+ int setlkTimeout; /* Blocking lock timeout, in msec. -1 -> inf. */
+ int setlkFlags; /* Flags passed to setlk_timeout() */
+#endif
int nSavepoint; /* Number of non-transaction savepoints */
int nStatement; /* Number of nested statement-transactions */
i64 nDeferredCons; /* Net deferred constraints this transaction. */
i64 nDeferredImmCons; /* Net deferred immediate constraints */
int *pnBytesFreed; /* If not NULL, increment this in DbFree() */
+ DbClientData *pDbData; /* sqlite3_set_clientdata() content */
+ u64 nSpill; /* TEMP content spilled to disk */
#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
@@ -16419,9 +18819,6 @@ struct sqlite3 {
void (*xUnlockNotify)(void **, int); /* Unlock notify callback */
sqlite3 *pNextBlocked; /* Next in list of all blocked connections */
#endif
-#ifdef SQLITE_USER_AUTHENTICATION
- sqlite3_userauth auth; /* User authentication information */
-#endif
};
/*
@@ -16430,6 +18827,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.
**
@@ -16438,20 +18842,19 @@ 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 */
-#define SQLITE_ReadUncommit 0x00000400 /* READ UNCOMMITTED in shared-cache */
+#define SQLITE_StmtScanStatus 0x00000400 /* Enable stmt_scanstats() counters */
#define SQLITE_NoCkptOnClose 0x00000800 /* No checkpoint on close()/DETACH */
#define SQLITE_ReverseOrder 0x00001000 /* Reverse unordered SELECTs */
#define SQLITE_RecTriggers 0x00002000 /* Enable recursive triggers */
@@ -16470,16 +18873,27 @@ struct sqlite3 {
#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. */
+#define SQLITE_CorruptRdOnly HI(0x00002) /* Prohibit writes due to error */
+#define SQLITE_ReadUncommit HI(0x00004) /* READ UNCOMMITTED in shared-cache */
+#define SQLITE_FkNoAction HI(0x00008) /* Treat all FK as NO ACTION */
+#define SQLITE_AttachCreate HI(0x00010) /* ATTACH allowed to create new dbs */
+#define SQLITE_AttachWrite HI(0x00020) /* ATTACH allowed to open for write */
+#define SQLITE_Comments HI(0x00040) /* Enable SQL comments */
/* Flags used only if debugging */
-#define HI(X) ((u64)(X)<<32)
#ifdef SQLITE_DEBUG
-#define SQLITE_SqlTrace HI(0x0001) /* Debug print SQL as it executes */
-#define SQLITE_VdbeListing HI(0x0002) /* Debug listings of VDBE progs */
-#define SQLITE_VdbeTrace HI(0x0004) /* True to trace VDBE execution */
-#define SQLITE_VdbeAddopTrace HI(0x0008) /* Trace sqlite3VdbeAddOp() calls */
-#define SQLITE_VdbeEQP HI(0x0010) /* Debug EXPLAIN QUERY PLAN */
-#define SQLITE_ParserTrace HI(0x0020) /* PRAGMA parser_trace=ON */
+#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
/*
@@ -16490,30 +18904,49 @@ struct sqlite3 {
#define DBFLAG_Vacuum 0x0004 /* Currently in a VACUUM */
#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 */
-#define SQLITE_WindowFunc 0x0002 /* Use xInverse for window functions */
-#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 /* WHERE-clause push-down opt */
+#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_OmitOrderBy 0x00040000 /* Omit pointless ORDER BY */
+ /* TH3 expects this value ^^^^^^^^^^ to be 0x40000. Coordinate any change */
+#define SQLITE_BloomFilter 0x00080000 /* Use a Bloom filter on searches */
+#define SQLITE_BloomPulldown 0x00100000 /* Run Bloom filters early */
+#define SQLITE_BalancedMerge 0x00200000 /* Balance multi-way merges */
+#define SQLITE_ReleaseReg 0x00400000 /* Use OP_ReleaseReg for testing */
+#define SQLITE_FlttnUnionAll 0x00800000 /* Disable the UNION ALL flattener */
+ /* TH3 expects this value ^^^^^^^^^^ See flatten04.test */
+#define SQLITE_IndexedExpr 0x01000000 /* Pull exprs from index when able */
+#define SQLITE_Coroutines 0x02000000 /* Co-routines for subqueries */
+#define SQLITE_NullUnusedCols 0x04000000 /* NULL unused columns in subqueries */
+#define SQLITE_OnePass 0x08000000 /* Single-pass DELETE and UPDATE */
+#define SQLITE_OrderBySubq 0x10000000 /* ORDER BY in subquery helps outer */
+#define SQLITE_StarQuery 0x20000000 /* Heurists for star queries */
+#define SQLITE_ExistsToJoin 0x40000000 /* The EXISTS-to-JOIN optimization */
+#define SQLITE_AllOpts 0xffffffff /* All optimizations */
/*
** Macros for testing whether or not optimizations are enabled or disabled.
@@ -16527,17 +18960,16 @@ struct sqlite3 {
*/
#define ConstFactorOk(P) ((P)->okConstFactor)
-/*
-** Possible values for the sqlite.magic field.
-** The numbers are obtained at random and have no special meaning, other
-** than being distinct from one another.
+/* Possible values for the sqlite3.eOpenState field.
+** The numbers are randomly selected such that a minimum of three bits must
+** change to convert any number to another or to zero
*/
-#define SQLITE_MAGIC_OPEN 0xa029a697 /* Database is open */
-#define SQLITE_MAGIC_CLOSED 0x9f3c2d33 /* Database is closed */
-#define SQLITE_MAGIC_SICK 0x4b771290 /* Error and awaiting close */
-#define SQLITE_MAGIC_BUSY 0xf03b7906 /* Database currently in use */
-#define SQLITE_MAGIC_ERROR 0xb5357930 /* An SQLITE_MISUSE error occurred */
-#define SQLITE_MAGIC_ZOMBIE 0x64cffc7f /* Close with last statement close */
+#define SQLITE_STATE_OPEN 0x76 /* Database is open */
+#define SQLITE_STATE_CLOSED 0xce /* Database is closed */
+#define SQLITE_STATE_SICK 0xba /* Error and awaiting close */
+#define SQLITE_STATE_BUSY 0x6d /* Database currently in use */
+#define SQLITE_STATE_ERROR 0xd5 /* An SQLITE_MISUSE error occurred */
+#define SQLITE_STATE_ZOMBIE 0xa7 /* Close with last statement close */
/*
** Each SQL function is defined by an instance of the following
@@ -16550,7 +18982,7 @@ struct sqlite3 {
** field is used by per-connection app-def functions.
*/
struct FuncDef {
- i8 nArg; /* Number of arguments. -1 means unlimited */
+ i16 nArg; /* Number of arguments. -1 means unlimited */
u32 funcFlags; /* Some combination of SQLITE_FUNC_* */
void *pUserData; /* User data parameter */
FuncDef *pNext; /* Next function with same name */
@@ -16562,7 +18994,7 @@ struct FuncDef {
union {
FuncDef *pHash; /* Next with a different name but the same hash */
FuncDestructor *pDestructor; /* Reference counted destructor function */
- } u;
+ } u; /* pHash if SQLITE_FUNC_BUILTIN, pDestructor otherwise */
};
/*
@@ -16592,11 +19024,21 @@ struct FuncDestructor {
** are assert() statements in the code to verify this.
**
** Value constraints (enforced via assert()):
-** SQLITE_FUNC_MINMAX == NC_MinMaxAgg == SF_MinMaxAgg
-** SQLITE_FUNC_LENGTH == OPFLAG_LENGTHARG
-** SQLITE_FUNC_TYPEOF == OPFLAG_TYPEOFARG
-** SQLITE_FUNC_CONSTANT == SQLITE_DETERMINISTIC from the API
+** SQLITE_FUNC_MINMAX == NC_MinMaxAgg == SF_MinMaxAgg
+** SQLITE_FUNC_ANYORDER == NC_OrderAgg == SF_OrderByReqd
+** SQLITE_FUNC_LENGTH == OPFLAG_LENGTHARG
+** SQLITE_FUNC_TYPEOF == OPFLAG_TYPEOFARG
+** SQLITE_FUNC_BYTELEN == OPFLAG_BYTELENARG
+** SQLITE_FUNC_CONSTANT == SQLITE_DETERMINISTIC from the API
+** SQLITE_FUNC_DIRECT == SQLITE_DIRECTONLY from the API
+** SQLITE_FUNC_UNSAFE == SQLITE_INNOCUOUS -- opposite meanings!!!
** SQLITE_FUNC_ENCMASK depends on SQLITE_UTF* macros in the API
+**
+** Note that even though SQLITE_FUNC_UNSAFE and SQLITE_INNOCUOUS have the
+** same bit value, their meanings are inverted. SQLITE_FUNC_UNSAFE is
+** used internally and if set means that the function has side effects.
+** SQLITE_INNOCUOUS is used by application code and means "not unsafe".
+** See multiple instances of tag-20230109-1.
*/
#define SQLITE_FUNC_ENCMASK 0x0003 /* SQLITE_UTF8, SQLITE_UTF16BE or UTF16LE */
#define SQLITE_FUNC_LIKE 0x0004 /* Candidate for the LIKE optimization */
@@ -16605,17 +19047,35 @@ struct FuncDestructor {
#define SQLITE_FUNC_NEEDCOLL 0x0020 /* sqlite3GetFuncCollSeq() might be called*/
#define SQLITE_FUNC_LENGTH 0x0040 /* Built-in length() function */
#define SQLITE_FUNC_TYPEOF 0x0080 /* Built-in typeof() function */
+#define SQLITE_FUNC_BYTELEN 0x00c0 /* Built-in octet_length() 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_OFFSET 0x8000 /* Built-in sqlite_offset() function */
+#define SQLITE_FUNC_TEST 0x4000 /* Built-in testing functions */
+#define SQLITE_FUNC_RUNONLY 0x8000 /* Cannot be used by valueFromFunction */
#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 */
+/* SQLITE_SUBTYPE 0x00100000 // Consumer of subtypes */
+#define SQLITE_FUNC_UNSAFE 0x00200000 /* Function has side effects */
+#define SQLITE_FUNC_INLINE 0x00400000 /* Functions implemented in-line */
+#define SQLITE_FUNC_BUILTIN 0x00800000 /* This is a built-in function */
+/* SQLITE_RESULT_SUBTYPE 0x01000000 // Generator of subtypes */
+#define SQLITE_FUNC_ANYORDER 0x08000000 /* count/min/max aggregate */
+
+/* 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_sqlite_offset 6
+#define INLINEFUNC_unlikely 99 /* Default case */
/*
** The following three macros, FUNCTION(), LIKEFUNC() and AGGREGATE() are
@@ -16631,6 +19091,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
@@ -16638,10 +19114,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)
@@ -16650,7 +19129,7 @@ struct FuncDestructor {
** are interpreted in the same way as the first 4 parameters to
** FUNCTION().
**
-** WFUNCTION(zName, nArg, iArg, xStep, xFinal, xValue, xInverse)
+** WAGGREGATE(zName, nArg, iArg, xStep, xFinal, xValue, xInverse)
** Used to create an aggregate function definition implemented by
** the C functions xStep and xFinal. The first four parameters
** are interpreted in the same way as the first 4 parameters to
@@ -16665,37 +19144,56 @@ struct FuncDestructor {
** parameter.
*/
#define FUNCTION(zName, nArg, iArg, bNC, xFunc) \
- {nArg, SQLITE_FUNC_CONSTANT|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \
+ {nArg, SQLITE_FUNC_BUILTIN|\
+ SQLITE_FUNC_CONSTANT|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \
SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, 0, #zName, {0} }
#define VFUNCTION(zName, nArg, iArg, bNC, xFunc) \
- {nArg, SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \
+ {nArg, SQLITE_FUNC_BUILTIN|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_FUNC_BUILTIN|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_BUILTIN|SQLITE_FUNC_CONSTANT|SQLITE_UTF8, \
+ xPtr, 0, xFunc, 0, 0, 0, #zName, {0} }
+#define JFUNCTION(zName, nArg, bUseCache, bWS, bRS, bJsonB, iArg, xFunc) \
+ {nArg, SQLITE_FUNC_BUILTIN|SQLITE_DETERMINISTIC|SQLITE_FUNC_CONSTANT|\
+ SQLITE_UTF8|((bUseCache)*SQLITE_FUNC_RUNONLY)|\
+ ((bRS)*SQLITE_SUBTYPE)|((bWS)*SQLITE_RESULT_SUBTYPE), \
+ SQLITE_INT_TO_PTR(iArg|((bJsonB)*JSON_BLOB)),0,xFunc,0, 0, 0, #zName, {0} }
+#define INLINE_FUNC(zName, nArg, iArg, mFlags) \
+ {nArg, SQLITE_FUNC_BUILTIN|\
+ 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_FUNC_BUILTIN|\
+ 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, \
+ {nArg, SQLITE_FUNC_BUILTIN|SQLITE_FUNC_SLOCHNG|SQLITE_UTF8, \
0, 0, xFunc, 0, 0, 0, #zName, {0} }
#define PURE_DATE(zName, nArg, iArg, bNC, xFunc) \
- {nArg, SQLITE_FUNC_SLOCHNG|SQLITE_UTF8|SQLITE_FUNC_CONSTANT, \
+ {nArg, SQLITE_FUNC_BUILTIN|\
+ SQLITE_FUNC_SLOCHNG|SQLITE_UTF8|SQLITE_FUNC_CONSTANT, \
(void*)&sqlite3Config, 0, xFunc, 0, 0, 0, #zName, {0} }
#define FUNCTION2(zName, nArg, iArg, bNC, xFunc, extraFlags) \
- {nArg,SQLITE_FUNC_CONSTANT|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL)|extraFlags,\
+ {nArg, SQLITE_FUNC_BUILTIN|\
+ SQLITE_FUNC_CONSTANT|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL)|extraFlags,\
SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, 0, #zName, {0} }
#define STR_FUNCTION(zName, nArg, pArg, bNC, xFunc) \
- {nArg, SQLITE_FUNC_SLOCHNG|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \
- pArg, 0, xFunc, 0, 0, 0, #zName, }
+ {nArg, SQLITE_FUNC_BUILTIN|\
+ SQLITE_FUNC_SLOCHNG|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \
+ pArg, 0, xFunc, 0, 0, 0, #zName, {0} }
#define LIKEFUNC(zName, nArg, arg, flags) \
- {nArg, SQLITE_FUNC_CONSTANT|SQLITE_UTF8|flags, \
+ {nArg, SQLITE_FUNC_BUILTIN|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, \
+ {nArg, SQLITE_FUNC_BUILTIN|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, \
+ {nArg, SQLITE_FUNC_BUILTIN|\
+ SQLITE_FUNC_INTERNAL|SQLITE_UTF8|SQLITE_FUNC_CONSTANT, \
0, 0, xFunc, 0, 0, 0, #zName, {0} }
@@ -16729,32 +19227,84 @@ 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.
+**
+** Notes on zCnName:
+** The zCnName field stores the name of the column, the datatype of the
+** column, and the collating sequence for the column, in that order, all in
+** a single allocation. Each string is 0x00 terminated. The datatype
+** is only included if the COLFLAG_HASTYPE bit of colFlags is set and the
+** collating sequence name is only included if the COLFLAG_HASCOLL bit is
+** set.
*/
struct Column {
- char *zName; /* Name of this column, \000, then the type */
- Expr *pDflt; /* Default value of this column */
- 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 */
+ char *zCnName; /* Name of this column */
+ unsigned notNull :4; /* An OE_ code for handling a NOT NULL constraint */
+ unsigned eCType :4; /* One of the standard types */
+ char affinity; /* One of the SQLITE_AFF_... values */
+ u8 szEst; /* Est size of value in this column. sizeof(INT)==1 */
+ u8 hName; /* Column name hash for faster lookup */
+ u16 iDflt; /* 1-based index of DEFAULT. 0 means "none" */
+ u16 colFlags; /* Boolean properties. See COLFLAG_ defines below */
};
-/* Allowed values for Column.colFlags:
-*/
-#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" */
+/* Allowed values for Column.eCType.
+**
+** Values must match entries in the global constant arrays
+** sqlite3StdTypeLen[] and sqlite3StdType[]. Each value is one more
+** than the offset into these arrays for the corresponding name.
+** Adjust the SQLITE_N_STDTYPE value if adding or removing entries.
+*/
+#define COLTYPE_CUSTOM 0 /* Type appended to zName */
+#define COLTYPE_ANY 1
+#define COLTYPE_BLOB 2
+#define COLTYPE_INT 3
+#define COLTYPE_INTEGER 4
+#define COLTYPE_REAL 5
+#define COLTYPE_TEXT 6
+#define SQLITE_N_STDTYPE 6 /* Number of standard types */
+
+/* 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_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_HASCOLL 0x0200 /* Has collating sequence name in zCnName */
+#define COLFLAG_NOEXPAND 0x0400 /* Omit this column when expanding "*" */
+#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
@@ -16794,11 +19344,14 @@ 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 SQLITE_AFF_FLEXNUM 0x46 /* 'F' */
+#define SQLITE_AFF_DEFER 0x58 /* 'X' - defer computation until later */
#define sqlite3IsNumericAffinity(X) ((X)>=SQLITE_AFF_NUMERIC)
@@ -16817,9 +19370,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 */
@@ -16871,45 +19422,61 @@ 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 bAllSchemas; /* True if might use any attached schema */
+ 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.
+** The schema for each SQL table, virtual table, and view is represented
+** in memory by an instance of the following structure.
*/
struct Table {
char *zName; /* Name of the table or view */
Column *aCol; /* Information about each column */
Index *pIndex; /* List of SQL indexes on this table. */
- Select *pSelect; /* NULL for tables. Points to definition if a view. */
- FKey *pFKey; /* Linked list of all foreign keys in this 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
LogEst costMult; /* Cost multiplier for using this table */
#endif
u8 keyConf; /* What to do in case of uniqueness conflict on iPKey */
-#ifndef SQLITE_OMIT_ALTERTABLE
- int addColOffset; /* Offset in CREATE TABLE stmt to add a new column */
-#endif
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- int nModuleArg; /* Number of arguments to the module */
- char **azModuleArg; /* 0: module 1: schema 2: vtab name 3...: args */
- VTable *pVTable; /* List of VTable objects. */
-#endif
- Trigger *pTrigger; /* List of triggers stored in pSchema */
+ u8 eTabType; /* 0: normal, 1: virtual, 2: view */
+ union {
+ struct { /* Used by ordinary tables: */
+ int addColOffset; /* Offset in CREATE TABLE stmt to add a new column */
+ FKey *pFKey; /* Linked list of all foreign keys in this table */
+ ExprList *pDfltList; /* DEFAULT clauses on various columns.
+ ** Or the AS clause for generated columns. */
+ } tab;
+ struct { /* Used by views: */
+ Select *pSelect; /* View definition */
+ } view;
+ struct { /* Used by virtual tables only: */
+ int nArg; /* Number of arguments to the module */
+ char **azArg; /* 0: module 1: schema 2: vtab name 3...: args */
+ VTable *p; /* List of VTable objects. */
+ } vtab;
+ } u;
+ Trigger *pTrigger; /* List of triggers on this object */
Schema *pSchema; /* Schema that contains this table */
- Table *pNextZombie; /* Next on the Parse.pZombieTab list */
+ u8 aHx[16]; /* Column aHt[K%sizeof(aHt)] might have hash K */
};
/*
@@ -16919,20 +19486,43 @@ 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.
-*/
-#define TF_Readonly 0x0001 /* Read-only system table */
-#define TF_Ephemeral 0x0002 /* An ephemeral table */
-#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_StatsUsed 0x0100 /* Query planner decisions affected by
- ** Index.aiRowLogEst[] values */
-#define TF_HasNotNull 0x0200 /* Contains NOT NULL constraints */
-#define TF_Shadow 0x0400 /* True for a shadow table */
+** 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 0x00000001 /* Read-only system table */
+#define TF_HasHidden 0x00000002 /* Has one or more hidden columns */
+#define TF_HasPrimaryKey 0x00000004 /* Table has a primary key */
+#define TF_Autoincrement 0x00000008 /* Integer primary key is autoincrement */
+#define TF_HasStat1 0x00000010 /* nRowLogEst set from sqlite_stat1 */
+#define TF_HasVirtual 0x00000020 /* Has one or more VIRTUAL columns */
+#define TF_HasStored 0x00000040 /* Has one or more STORED columns */
+#define TF_HasGenerated 0x00000060 /* Combo: HasVirtual + HasStored */
+#define TF_WithoutRowid 0x00000080 /* No rowid. PRIMARY KEY is the key */
+#define TF_MaybeReanalyze 0x00000100 /* Maybe run ANALYZE on this table */
+#define TF_NoVisibleRowid 0x00000200 /* No user-visible "rowid" column */
+#define TF_OOOHidden 0x00000400 /* Out-of-Order hidden columns */
+#define TF_HasNotNull 0x00000800 /* Contains NOT NULL constraints */
+#define TF_Shadow 0x00001000 /* True for a shadow table */
+#define TF_HasStat4 0x00002000 /* STAT4 info available for this table */
+#define TF_Ephemeral 0x00004000 /* An ephemeral table */
+#define TF_Eponymous 0x00008000 /* An eponymous virtual table */
+#define TF_Strict 0x00010000 /* STRICT mode */
+#define TF_Imposter 0x00020000 /* An imposter table */
+
+/*
+** Allowed values for Table.eTabType
+*/
+#define TABTYP_NORM 0 /* Ordinary table */
+#define TABTYP_VTAB 1 /* Virtual table */
+#define TABTYP_VIEW 2 /* A view */
+
+#define IsView(X) ((X)->eTabType==TABTYP_VIEW)
+#define IsOrdinaryTable(X) ((X)->eTabType==TABTYP_NORM)
/*
** Test to see whether or not a table is a virtual table. This is
@@ -16940,9 +19530,12 @@ struct Table {
** table support is omitted from the build.
*/
#ifndef SQLITE_OMIT_VIRTUALTABLE
-# define IsVirtual(X) ((X)->nModuleArg)
+# define IsVirtual(X) ((X)->eTabType==TABTYP_VTAB)
+# define ExprIsVtab(X) \
+ ((X)->op==TK_COLUMN && (X)->y.pTab->eTabType==TABTYP_VTAB)
#else
# define IsVirtual(X) 0
+# define ExprIsVtab(X) 0
#endif
/*
@@ -16967,6 +19560,15 @@ struct Table {
#define HasRowid(X) (((X)->tabFlags & TF_WithoutRowid)==0)
#define VisibleRowid(X) (((X)->tabFlags & TF_NoVisibleRowid)==0)
+/* Macro is true if the SQLITE_ALLOW_ROWID_IN_VIEW (mis-)feature is
+** available. By default, this macro is false
+*/
+#ifndef SQLITE_ALLOW_ROWID_IN_VIEW
+# define ViewCanHaveRowid 0
+#else
+# define ViewCanHaveRowid (sqlite3Config.mNoVisibleRowid==0)
+#endif
+
/*
** Each foreign key constraint is an instance of the following structure.
**
@@ -17009,9 +19611,13 @@ struct FKey {
struct sColMap { /* Mapping of columns in pFrom to columns in zTo */
int iFrom; /* Index of column in pFrom */
char *zCol; /* Name of column in zTo. If NULL use PRIMARY KEY */
- } aCol[1]; /* One entry for each of nCol columns */
+ } aCol[FLEXARRAY]; /* One entry for each of nCol columns */
};
+/* The size (in bytes) of an FKey object holding N columns. The answer
+** does NOT include space to hold the zTo name. */
+#define SZ_FKEY(N) (offsetof(FKey,aCol)+(N)*sizeof(struct sColMap))
+
/*
** SQLite supports many different ways to resolve a constraint
** error. ROLLBACK processing means that a constraint violation
@@ -17026,16 +19632,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 algorithm 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 */
@@ -17056,9 +19668,15 @@ struct FKey {
** argument to sqlite3VdbeKeyCompare and is used to control the
** comparison of the two index keys.
**
-** Note that aSortOrder[] and aColl[] have nField+1 slots. There
-** are nField slots for the columns of an index then one extra slot
-** for the rowid at the end.
+** The aSortOrder[] and aColl[] arrays have nAllField slots each. There
+** are nKeyField slots for the columns of an index then extra slots
+** for the rowid or key at the end. The aSortOrder array is located after
+** the aColl[] array.
+**
+** If SQLITE_ENABLE_PREUPDATE_HOOK is defined, then aSortFlags might be NULL
+** to indicate that this object is for use by a preupdate hook. When aSortFlags
+** is NULL, then nAllField is uninitialized and no space is allocated for
+** aColl[], so those fields may not be used.
*/
struct KeyInfo {
u32 nRef; /* Number of references to this KeyInfo object */
@@ -17066,10 +19684,28 @@ 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. */
- CollSeq *aColl[1]; /* Collating sequence for each term of the key */
+ u8 *aSortFlags; /* Sort order for each column. */
+ CollSeq *aColl[FLEXARRAY]; /* Collating sequence for each term of the key */
};
+/* The size (in bytes) of a KeyInfo object with up to N fields. This includes
+** the main body of the KeyInfo object and the aColl[] array of N elements,
+** but does not count the memory used to hold aSortFlags[]. */
+#define SZ_KEYINFO(N) (offsetof(KeyInfo,aColl) + (N)*sizeof(CollSeq*))
+
+/* The size of a bare KeyInfo with no aColl[] entries */
+#if FLEXARRAY+1 > 1
+# define SZ_KEYINFO_0 offsetof(KeyInfo,aColl)
+#else
+# define SZ_KEYINFO_0 sizeof(KeyInfo)
+#endif
+
+/*
+** 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.
@@ -17082,9 +19718,8 @@ struct KeyInfo {
**
** An instance of this object serves as a "key" for doing a search on
** an index b+tree. The goal of the search is to find the entry that
-** is closed to the key described by this object. This object might hold
-** just a prefix of the key. The number of fields is given by
-** pKeyInfo->nField.
+** is closest to the key described by this object. This object might hold
+** just a prefix of the key. The number of fields is given by nField.
**
** The r1 and r2 fields are the values to return if this key is less than
** or greater than a key in the btree, respectively. These are normally
@@ -17094,7 +19729,7 @@ struct KeyInfo {
** The key comparison functions actually return default_rc when they find
** an equals comparison. default_rc can be -1, 0, or +1. If there are
** multiple entries in the b-tree with the same key (when only looking
-** at the first pKeyInfo->nFields,) then default_rc can be set to -1 to
+** at the first nField elements) then default_rc can be set to -1 to
** cause the search to find the last match, or +1 to cause the search to
** find the first match.
**
@@ -17106,8 +19741,13 @@ struct KeyInfo {
** b-tree.
*/
struct UnpackedRecord {
- KeyInfo *pKeyInfo; /* Collation and sort-order information */
- Mem *aMem; /* Values */
+ KeyInfo *pKeyInfo; /* Comparison info for the index that is unpacked */
+ Mem *aMem; /* Values for columns of the index */
+ union {
+ char *z; /* Cache of aMem[0].z for vdbeRecordCompareString() */
+ i64 i; /* Cache of aMem[0].u.i for vdbeRecordCompareInt() */
+ } u;
+ int n; /* Cache of aMem[0].n used by vdbeRecordCompareString() */
u16 nField; /* Number of entries in apMem[] */
i8 default_rc; /* Comparison result if keys are equal */
u8 errCode; /* Error detected by xRecordCompare (CORRUPT or NOMEM) */
@@ -17139,12 +19779,24 @@ struct UnpackedRecord {
** The Index.onError field determines whether or not the indexed columns
** must be unique and what to do if they are not. When Index.onError=OE_None,
** it means this is not a unique index. Otherwise it is a unique index
-** and the value of Index.onError indicate the which conflict resolution
-** algorithm to employ whenever an attempt is made to insert a non-unique
+** and the value of Index.onError indicates which conflict resolution
+** algorithm to employ when an attempt is made to insert a non-unique
** element.
**
+** The colNotIdxed bitmask is used in combination with SrcItem.colUsed
+** for a fast test to see if an index can serve as a covering index.
+** colNotIdxed has a 1 bit for every column of the original table that
+** is *not* available in the index. Thus the expression
+** "colUsed & colNotIdxed" will be non-zero if the index is not a
+** covering index. The most significant bit of of colNotIdxed will always
+** be true (note-20221022-a). If a column beyond the 63rd column of the
+** table is used, the "colUsed & colNotIdxed" test will always be non-zero
+** and we have to assume either that the index is not covering, or use
+** an alternative (slower) algorithm to determine whether or not
+** the index is covering.
+**
** 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
@@ -17163,10 +19815,10 @@ 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 */
+ u16 nColumn; /* Nr columns in btree. Can be 2*Table.nCol */
u8 onError; /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */
unsigned idxType:2; /* 0:Normal 1:UNIQUE, 2:PRIMARY KEY, 3:IPK */
unsigned bUnordered:1; /* Use this index for == or IN queries only */
@@ -17176,15 +19828,20 @@ 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 */
+ unsigned bHasExpr:1; /* Index contains an expression, either a literal
+ ** expression, or a reference to a VIRTUAL column */
+#ifdef SQLITE_ENABLE_STAT4
int nSample; /* Number of elements in aSample[] */
+ int mxSample; /* Number of slots allocated to aSample[] */
int nSampleCol; /* Size of IndexSample.anEq[] and so on */
tRowcnt *aAvgEq; /* Average nEq values for keys not in aSample */
IndexSample *aSample; /* Samples of the left-most key */
tRowcnt *aiRowEst; /* Non-logarithmic stat1 data for this index */
tRowcnt nRowEst0; /* Non-logarithmic number of rows in the index */
#endif
- Bitmask colNotIdxed; /* 0 for unindexed columns in pTab */
+ Bitmask colNotIdxed; /* Unindexed columns in pTab */
};
/*
@@ -17208,7 +19865,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.
*/
@@ -17246,7 +19903,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.
**
@@ -17259,32 +19916,56 @@ struct AggInfo {
** from source tables rather than from accumulators */
u8 useSortingIdx; /* In direct mode, reference the sorting index rather
** than the source table */
+ u32 nSortingColumn; /* Number of columns in the sorting index */
int sortingIdx; /* Cursor number of the sorting index */
int sortingIdxPTab; /* Cursor number of pseudo-table */
- int nSortingColumn; /* Number of columns in the sorting index */
- int mnReg, mxReg; /* Range of registers allocated for aCol and aFunc */
+ int iFirstReg; /* First register in range for aCol[] and aFunc[] */
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 */
} *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 */
+ int iOBTab; /* Ephemeral table to implement ORDER BY */
+ u8 bOBPayload; /* iOBTab has payload columns separate from key */
+ u8 bOBUnique; /* Enforce uniqueness on iOBTab keys */
+ u8 bUseSubtype; /* Transfer subtype info through sorter */
} *aFunc;
int nFunc; /* Number of entries in aFunc[] */
+ u32 selId; /* Select to which this AggInfo belongs */
+#ifdef SQLITE_DEBUG
+ Select *pSelect; /* SELECT statement that this AggInfo supports */
+#endif
};
+/*
+** Macros to compute aCol[] and aFunc[] register numbers.
+**
+** These macros should not be used prior to the call to
+** assignAggregateRegisters() that computes the value of pAggInfo->iFirstReg.
+** The assert()s that are part of this macro verify that constraint.
+*/
+#ifndef NDEBUG
+#define AggInfoColumnReg(A,I) (assert((A)->iFirstReg),(A)->iFirstReg+(I))
+#define AggInfoFuncReg(A,I) \
+ (assert((A)->iFirstReg),(A)->iFirstReg+(A)->nColumn+(I))
+#else
+#define AggInfoColumnReg(A,I) ((A)->iFirstReg+(I))
+#define AggInfoFuncReg(A,I) \
+ ((A)->iFirstReg+(A)->nColumn+(I))
+#endif
+
/*
** The datatype ynVar is a signed integer, either 16-bit or 32-bit.
** Usually it is 16-bits. But if SQLITE_MAX_VARIABLE_NUMBER is greater
@@ -17292,10 +19973,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;
@@ -17312,10 +19993,10 @@ typedef int ynVar;
** tree.
**
** If the expression is an SQL literal (TK_INTEGER, TK_FLOAT, TK_BLOB,
-** or TK_STRING), then Expr.token contains the text of the SQL literal. If
-** the expression is a variable (TK_VARIABLE), then Expr.token contains the
+** or TK_STRING), then Expr.u.zToken contains the text of the SQL literal. If
+** the expression is a variable (TK_VARIABLE), then Expr.u.zToken contains the
** variable name. Finally, if the expression is an SQL function (TK_FUNCTION),
-** then Expr.token contains the name of the function.
+** then Expr.u.zToken contains the name of the function.
**
** Expr.pRight and Expr.pLeft are the left and right subexpressions of a
** binary operator. Either or both may be NULL.
@@ -17355,7 +20036,7 @@ typedef int ynVar;
** help reduce memory requirements, sometimes an Expr object will be
** truncated. And to reduce the number of memory allocations, sometimes
** two or more Expr objects will be stored in a single memory allocation,
-** together with Expr.zToken strings.
+** together with Expr.u.zToken strings.
**
** If the EP_Reduced and EP_TokenOnly flags are set when
** an Expr object is truncated. When EP_Reduced is set, then all
@@ -17366,7 +20047,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 */
@@ -17397,20 +20085,23 @@ struct Expr {
** TK_REGISTER: register number
** TK_TRIGGER: 1 -> new, 0 -> old
** EP_Unlikely: 134217728 times likelihood
+ ** TK_IN: ephemeral 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 */
+ union {
+ int iJoin; /* If EP_OuterON or EP_InnerON, the right table */
+ int iOfst; /* else: start of token from start of statement */
+ } w;
AggInfo *pAggInfo; /* Used by TK_AGG_COLUMN and TK_AGG_FUNCTION */
union {
Table *pTab; /* TK_COLUMN: Table containing column. Can be NULL
** for a column of an index on an expression */
- Window *pWin; /* TK_FUNCTION: Window definition for the func */
+ Window *pWin; /* EP_WinFunc: Window/Filter defn for a function */
+ int nReg; /* TK_NULLS: Number of registers to NULL out */
struct { /* TK_IN, TK_SELECT, and TK_EXISTS */
int iAddr; /* Subroutine entry address */
int regReturn; /* Register used to hold return address */
@@ -17418,65 +20109,91 @@ struct Expr {
} y;
};
-/*
-** The following are the meanings of bits in the Expr.flags field.
+/* 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_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_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_Win 0x008000 /* Contains window functions */
-#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_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() */
-
-/*
-** The EP_Propagate mask is a set of properties that automatically propagate
+#define EP_OuterON 0x000001 /* Originates in ON/USING clause of outer join */
+#define EP_InnerON 0x000002 /* Originates in ON/USING of an inner join */
+#define EP_Distinct 0x000004 /* Aggregate function with DISTINCT keyword */
+#define EP_HasFunc 0x000008 /* Contains one or more functions of any kind */
+#define EP_Agg 0x000010 /* Contains one or more aggregate functions */
+#define EP_FixedCol 0x000020 /* TK_Column with a known fixed value */
+#define EP_VarSelect 0x000040 /* pSelect is correlated, not constant */
+#define EP_DblQuoted 0x000080 /* token.z was originally in "..." */
+#define EP_InfixFunc 0x000100 /* True for an infix function: LIKE, GLOB, etc */
+#define EP_Collate 0x000200 /* Tree contains a TK_COLLATE operator */
+#define EP_Commuted 0x000400 /* Comparison operator has been commuted */
+#define EP_IntValue 0x000800 /* Integer value contained in u.iValue */
+#define EP_xIsSelect 0x001000 /* x.pSelect is valid (otherwise x.pList is) */
+#define EP_Skip 0x002000 /* Operator does not contribute to affinity */
+#define EP_Reduced 0x004000 /* Expr struct EXPR_REDUCEDSIZE bytes only */
+#define EP_Win 0x008000 /* Contains window functions */
+#define EP_TokenOnly 0x010000 /* Expr struct EXPR_TOKENONLYSIZE bytes only */
+#define EP_FullSize 0x020000 /* Expr structure must remain full sized */
+#define EP_IfNullRow 0x040000 /* The TK_IF_NULL_ROW opcode */
+#define EP_Unlikely 0x080000 /* unlikely() or likelihood() function */
+#define EP_ConstFunc 0x100000 /* A SQLITE_FUNC_CONSTANT or _SLOCHNG function */
+#define EP_CanBeNull 0x200000 /* Can be null despite NOT NULL constraint */
+#define EP_Subquery 0x400000 /* Tree contains a TK_SELECT operator */
+#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 */
+#define EP_SubtArg 0x80000000 /* Is argument to SQLITE_SUBTYPE function */
+
+/* The EP_Propagate mask is a set of properties that automatically propagate
** upwards into parent nodes.
*/
#define EP_Propagate (EP_Collate|EP_Subquery|EP_HasFunc)
-/*
-** These macros can be used to test, set, or clear bits in the
+/* Macros can be used to test, set, or clear bits in the
** Expr.flags field.
*/
-#define ExprHasProperty(E,P) (((E)->flags&(P))!=0)
-#define ExprHasAllProperty(E,P) (((E)->flags&(P))==(P))
-#define ExprSetProperty(E,P) (E)->flags|=(P)
-#define ExprClearProperty(E,P) (E)->flags&=~(P)
+#define ExprHasProperty(E,P) (((E)->flags&(u32)(P))!=0)
+#define ExprHasAllProperty(E,P) (((E)->flags&(u32)(P))==(u32)(P))
+#define ExprSetProperty(E,P) (E)->flags|=(u32)(P)
+#define ExprClearProperty(E,P) (E)->flags&=~(u32)(P)
+#define ExprAlwaysTrue(E) (((E)->flags&(EP_OuterON|EP_IsTrue))==EP_IsTrue)
+#define ExprAlwaysFalse(E) (((E)->flags&(EP_OuterON|EP_IsFalse))==EP_IsFalse)
+#define ExprIsFullSize(E) (((E)->flags&(EP_Reduced|EP_TokenOnly))==0)
+
+/* Macros used to ensure that the correct members of unions are accessed
+** in Expr.
+*/
+#define ExprUseUToken(E) (((E)->flags&EP_IntValue)==0)
+#define ExprUseUValue(E) (((E)->flags&EP_IntValue)!=0)
+#define ExprUseWOfst(E) (((E)->flags&(EP_InnerON|EP_OuterON))==0)
+#define ExprUseWJoin(E) (((E)->flags&(EP_InnerON|EP_OuterON))!=0)
+#define ExprUseXList(E) (((E)->flags&EP_xIsSelect)==0)
+#define ExprUseXSelect(E) (((E)->flags&EP_xIsSelect)!=0)
+#define ExprUseYTab(E) (((E)->flags&(EP_WinFunc|EP_Subrtn))==0)
+#define ExprUseYWin(E) (((E)->flags&EP_WinFunc)!=0)
+#define ExprUseYSub(E) (((E)->flags&EP_Subrtn)!=0)
+
+/* 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
/*
@@ -17494,6 +20211,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
@@ -17502,35 +20231,62 @@ 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 */
- 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 */
+ char *zEName; /* Token associated with this expression */
+ struct {
+ u8 sortFlags; /* Mask of KEYINFO_ORDER_* flags */
+ unsigned eEName :2; /* Meaning of zEName */
+ unsigned done :1; /* Indicates when processing is finished */
+ unsigned reusable :1; /* Constant expression is reusable */
+ unsigned bSorterRef :1; /* Defer evaluation until after sorting */
+ unsigned bNulls :1; /* True if explicit "NULLS FIRST/LAST" */
+ unsigned bUsed :1; /* This column used in a SF_NestedFrom subquery */
+ unsigned bUsingTerm:1; /* Term from the USING clause of a NestedFrom */
+ unsigned bNoExpand: 1; /* Term is an auxiliary in NestedFrom and should
+ ** not be expanded by "*" in parent queries */
+ } fg;
union {
- struct {
+ struct { /* Used by any ExprList other than Parse.pConsExpr */
u16 iOrderByCol; /* For ORDER BY, column number in result set */
u16 iAlias; /* Index into Parse.aAlias[] for zName */
} x;
- int iConstExprReg; /* Register in which Expr value is cached */
+ int iConstExprReg; /* Register in which Expr value is cached. Used only
+ ** by Parse.pConstExpr */
} u;
- } a[1]; /* One slot for each expression in the list */
+ } a[FLEXARRAY]; /* One slot for each expression in the list */
};
+/* The size (in bytes) of an ExprList object that is big enough to hold
+** as many as N expressions. */
+#define SZ_EXPRLIST(N) \
+ (offsetof(ExprList,a) + (N)*sizeof(struct ExprList_item))
+
+/*
+** 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 */
+#define ENAME_ROWID 3 /* "DB.TABLE._rowid_" for * expansion of rowid */
+
/*
** An instance of this structure can hold a simple list of identifiers,
** such as the list "a,b,c" in the following statements:
@@ -17547,23 +20303,36 @@ struct ExprList {
** If "a" is the k-th column of table "t", then IdList.a[0].idx==k.
*/
struct IdList {
+ int nId; /* Number of identifiers on the list */
struct IdList_item {
char *zName; /* Name of the identifier */
- int idx; /* Index in some Table.aCol[] of a column named zName */
- } *a;
- int nId; /* Number of identifiers on the list */
+ } a[FLEXARRAY];
};
+/* The size (in bytes) of an IdList object that can hold up to N IDs. */
+#define SZ_IDLIST(N) (offsetof(IdList,a)+(N)*sizeof(struct IdList_item))
+
/*
-** The following structure describes the FROM clause of a SELECT statement.
-** Each table or subquery in the FROM clause is a separate element of
-** the SrcList.a[] array.
-**
-** With the addition of multiple database support, the following structure
-** can also be used to describe a particular table such as the table that
-** is modified by an INSERT, DELETE, or UPDATE statement. In standard SQL,
-** such a table must be a simple name: ID. But in SQLite, the table can
-** now be identified by a database name, a dot, then the table name: ID.ID.
+** Allowed values for IdList.eType, which determines which value of the a.u4
+** is valid.
+*/
+#define EU4_NONE 0 /* Does not use IdList.a.u4 */
+#define EU4_IDX 1 /* Uses IdList.a.u4.idx */
+#define EU4_EXPR 2 /* Uses IdList.a.u4.pExpr -- NOT CURRENTLY USED */
+
+/*
+** Details of the implementation of a subquery.
+*/
+struct Subquery {
+ Select *pSelect; /* A SELECT statement used in place of a table name */
+ int addrFillSub; /* Address of subroutine to initialize a subquery */
+ int regReturn; /* Register holding return address of addrFillSub */
+ int regResult; /* Registers holding results of a co-routine */
+};
+
+/*
+** The SrcItem object represents a single term in the FROM clause of a query.
+** The SrcList object is mostly an array of SrcItems.
**
** The jointype starts out showing the join type between the current table
** and the next table on the list. The parser builds the list this way.
@@ -17572,52 +20341,122 @@ struct IdList {
**
** In the colUsed field, the high-order bit (bit 63) is set if the table
** contains more than 63 columns and the 64-th or later column is used.
-*/
-struct SrcList {
- int nSrc; /* Number of tables or subqueries in the FROM clause */
- u32 nAlloc; /* Number of entries allocated in a[] below */
- struct SrcList_item {
+**
+** Aggressive use of "union" helps keep the size of the object small. This
+** has been shown to boost performance, in addition to saving memory.
+** Access to union elements is gated by the following rules which should
+** always be checked, either by an if-statement or by an assert().
+**
+** Field Only access if this is true
+** --------------- -----------------------------------
+** u1.zIndexedBy fg.isIndexedBy
+** u1.pFuncArg fg.isTabFunc
+** u1.nRow !fg.isTabFunc && !fg.isIndexedBy
+**
+** u2.pIBIndex fg.isIndexedBy
+** u2.pCteUse fg.isCte
+**
+** u3.pOn !fg.isUsing
+** u3.pUsing fg.isUsing
+**
+** u4.zDatabase !fg.fixedSchema && !fg.isSubquery
+** u4.pSchema fg.fixedSchema
+** u4.pSubq fg.isSubquery
+**
+** See also the sqlite3SrcListDelete() routine for assert() statements that
+** check invariants on the fields of this object, especially the flags
+** inside the fg struct.
+*/
+struct SrcItem {
+ char *zName; /* Name of the table */
+ char *zAlias; /* The "B" part of a "A AS B" phrase. zName is the "A" */
+ Table *pSTab; /* Table object for zName. Mnemonic: Srcitem-TABle */
+ 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 isSubquery :1; /* True if this term is a subquery */
+ unsigned isTabFunc :1; /* True if table-valued-function syntax */
+ unsigned isCorrelated :1; /* True if sub-query is correlated */
+ unsigned isMaterialized:1; /* This is a materialized view */
+ 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 */
+ unsigned isUsing :1; /* u3.pUsing is valid */
+ unsigned isOn :1; /* u3.pOn was once valid and non-NULL */
+ unsigned isSynthUsing :1; /* u3.pUsing is synthesized from NATURAL */
+ unsigned isNestedFrom :1; /* pSelect is a SF_NestedFrom subquery */
+ unsigned rowidUsed :1; /* The ROWID of this table is referenced */
+ unsigned fixedSchema :1; /* Uses u4.pSchema, not u4.zDatabase */
+ unsigned hadSchema :1; /* Had u4.zDatabase before u4.pSchema */
+ unsigned fromExists :1; /* Comes from WHERE EXISTS(...) */
+ } fg;
+ int iCursor; /* The VDBE cursor number used to access this table */
+ Bitmask colUsed; /* Bit N set if column N used. Details above for N>62 */
+ union {
+ char *zIndexedBy; /* Identifier from "INDEXED BY " clause */
+ ExprList *pFuncArg; /* Arguments to table-valued-function */
+ u32 nRow; /* Number of rows in a VALUES clause */
+ } u1;
+ union {
+ Index *pIBIndex; /* Index structure corresponding to u1.zIndexedBy */
+ CteUse *pCteUse; /* CTE Usage info when fg.isCte is true */
+ } u2;
+ union {
+ Expr *pOn; /* fg.isUsing==0 => The ON clause of a join */
+ IdList *pUsing; /* fg.isUsing==1 => The USING clause of a join */
+ } u3;
+ union {
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 */
+ Subquery *pSubq; /* Description of a subquery */
+ } u4;
};
/*
-** Permitted values of the SrcList.a.jointype field
+** The OnOrUsing object represents either an ON clause or a USING clause.
+** It can never be both at the same time, but it can be neither.
+*/
+struct OnOrUsing {
+ Expr *pOn; /* The ON clause of a join */
+ IdList *pUsing; /* The USING clause of a join */
+};
+
+/*
+** This object represents one or more tables that are the source of
+** content for an SQL statement. For example, a single SrcList object
+** is used to hold the FROM clause of a SELECT statement. SrcList also
+** represents the target tables for DELETE, INSERT, and UPDATE statements.
+**
*/
-#define JT_INNER 0x0001 /* Any kind of inner or cross join */
-#define JT_CROSS 0x0002 /* Explicit use of the CROSS keyword */
-#define JT_NATURAL 0x0004 /* True for a "natural" join */
-#define JT_LEFT 0x0008 /* Left outer join */
-#define JT_RIGHT 0x0010 /* Right outer join */
-#define JT_OUTER 0x0020 /* The "OUTER" keyword is present */
-#define JT_ERROR 0x0040 /* unknown or unsupported join type */
+struct SrcList {
+ int nSrc; /* Number of tables or subqueries in the FROM clause */
+ u32 nAlloc; /* Number of entries allocated in a[] below */
+ SrcItem a[FLEXARRAY]; /* One entry for each identifier on the list */
+};
+
+/* Size (in bytes) of a SrcList object that can hold as many as N
+** SrcItem objects. */
+#define SZ_SRCLIST(N) (offsetof(SrcList,a)+(N)*sizeof(SrcItem))
+
+/* Size (in bytes( of a SrcList object that holds 1 SrcItem. This is a
+** special case of SZ_SRCITEM(1) that comes up often. */
+#define SZ_SRCLIST_1 (offsetof(SrcList,a)+sizeof(SrcItem))
+/*
+** Permitted values of the SrcList.a.jointype field
+*/
+#define JT_INNER 0x01 /* Any kind of inner or cross join */
+#define JT_CROSS 0x02 /* Explicit use of the CROSS keyword */
+#define JT_NATURAL 0x04 /* True for a "natural" join */
+#define JT_LEFT 0x08 /* Left outer join */
+#define JT_RIGHT 0x10 /* Right outer join */
+#define JT_OUTER 0x20 /* The "OUTER" keyword is present */
+#define JT_LTORJ 0x40 /* One of the LEFT operands of a RIGHT JOIN
+ ** Mnemonic: Left Table Of Right Join */
+#define JT_ERROR 0x80 /* unknown or unsupported join type */
/*
** Flags appropriate for the wctrlFlags parameter of sqlite3WhereBegin()
@@ -17638,10 +20477,10 @@ 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 */
- /* 0x2000 not currently used */
+#define WHERE_RIGHT_JOIN 0x1000 /* Processing a RIGHT JOIN */
+#define WHERE_KEEP_ALL_JOINS 0x2000 /* Do not do the omit-noop-join opt */
#define WHERE_USE_LIMIT 0x4000 /* Use the LIMIT in cost estimates */
/* 0x8000 not currently used */
@@ -17680,11 +20519,13 @@ 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 */
+ u32 nNestedSelect; /* Number of nested selects using this NC */
Select *pWinSelect; /* SELECT statement for any window functions */
};
@@ -17692,25 +20533,34 @@ struct NameContext {
** Allowed values for the NameContext, ncFlags field.
**
** Value constraints (all checked via assert()):
-** NC_HasAgg == SF_HasAgg == EP_Agg
-** NC_MinMaxAgg == SF_MinMaxAgg == SQLITE_FUNC_MINMAX
+** NC_HasAgg == SF_HasAgg == EP_Agg
+** NC_MinMaxAgg == SF_MinMaxAgg == SQLITE_FUNC_MINMAX
+** NC_OrderAgg == SF_OrderByReqd == SQLITE_FUNC_ANYORDER
** 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_HasWin 0x8000 /* One or more window functions seen */
+#define NC_AllowAgg 0x000001 /* Aggregate functions are allowed here */
+#define NC_PartIdx 0x000002 /* True if resolving a partial index WHERE */
+#define NC_IsCheck 0x000004 /* True if resolving a CHECK constraint */
+#define NC_GenCol 0x000008 /* True for a GENERATED ALWAYS AS clause */
+#define NC_HasAgg 0x000010 /* One or more aggregate functions seen */
+#define NC_IdxExpr 0x000020 /* True if resolving columns of CREATE INDEX */
+#define NC_SelfRef 0x00002e /* Combo: PartIdx, isCheck, GenCol, and IdxExpr */
+#define NC_Subquery 0x000040 /* A subquery has been seen */
+#define NC_UEList 0x000080 /* True if uNC.pEList is used */
+#define NC_UAggInfo 0x000100 /* True if uNC.pAggInfo is used */
+#define NC_UUpsert 0x000200 /* True if uNC.pUpsert is used */
+#define NC_UBaseReg 0x000400 /* True if uNC.iBaseReg is used */
+#define NC_MinMaxAgg 0x001000 /* min/max aggregates seen. See note above */
+/* 0x002000 // available for reuse */
+#define NC_AllowWin 0x004000 /* Window functions are allowed here */
+#define NC_HasWin 0x008000 /* One or more window functions seen */
+#define NC_IsDDL 0x010000 /* Resolving names in a CREATE statement */
+#define NC_InAggFunc 0x020000 /* True if analyzing arguments to an agg func */
+#define NC_FromDDL 0x040000 /* SQL text comes from sqlite_schema */
+#define NC_NoSelect 0x080000 /* Do not descend into sub-selects */
+#define NC_Where 0x100000 /* Processing WHERE clause of a SELECT */
+#define NC_OrderAgg 0x8000000 /* Has an aggregate other than count/min/max */
/*
** An instance of the following object describes a single ON CONFLICT
@@ -17721,21 +20571,28 @@ 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 */
+ u8 isDup; /* True if 2nd or later with same pUpsertIdx */
+ /* 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 */
@@ -17745,28 +20602,14 @@ struct Upsert {
/*
** An instance of the following structure contains all information
** needed to generate code for a single SELECT statement.
-**
-** See the header comment on the computeLimitRegisters() routine for a
-** detailed description of the meaning of the iLimit and iOffset fields.
-**
-** addrOpenEphm[] entries contain the address of OP_OpenEphemeral opcodes.
-** These addresses must be stored so that we can go back and fill in
-** the P4_KEYINFO and P2 parameters later. Neither the KeyInfo nor
-** the number of columns in P2 can be computed at the same time
-** as the OP_OpenEphm instruction is coded because not
-** enough information about the compound query is known at that point.
-** The KeyInfo for addrOpenTran[0] and [1] contains collating sequences
-** for the result set. The KeyInfo for addrOpenEphm[2] contains collating
-** 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 */
@@ -17787,40 +20630,53 @@ struct Select {
** "Select Flag".
**
** Value constraints (all checked via assert())
-** SF_HasAgg == NC_HasAgg
-** 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 */
+** SF_HasAgg == NC_HasAgg
+** SF_MinMaxAgg == NC_MinMaxAgg == SQLITE_FUNC_MINMAX
+** SF_OrderByReqd == NC_OrderAgg == SQLITE_FUNC_ANYORDER
+** SF_FixedLimit == WHERE_USE_LIMIT
+*/
+#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_ClonedRhsIn 0x0000020 /* Cloned RHS of an IN operator */
+#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 */
+/* 0x0008000 // available for reuse */
+#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 */
+/* 0x0400000 // available for reuse */
+#define SF_UFSrcCheck 0x0800000 /* Check pSrc as required by UPDATE...FROM */
+#define SF_PushDown 0x1000000 /* Modified by WHERE-clause push-down opt */
+#define SF_MultiPart 0x2000000 /* Has multiple incompatible PARTITIONs */
+#define SF_CopyCte 0x4000000 /* SELECT statement is a copy of a CTE */
+#define SF_OrderByReqd 0x8000000 /* The ORDER BY clause may not be omitted */
+#define SF_UpdateFrom 0x10000000 /* Query originates with UPDATE FROM */
+#define SF_Correlated 0x20000000 /* True if references the outer context */
+#define SF_OnToWhere 0x40000000 /* One or more ON clauses moved to WHERE */
+
+/* True if SrcItem X is a subquery that has SF_NestedFrom */
+#define IsNestedFrom(X) \
+ ((X)->fg.isSubquery && \
+ ((X)->u4.pSubq->pSelect->selFlags&SF_NestedFrom)!=0)
/*
** The results of a SELECT can be distributed in several ways, as defined
** by one of the following macros. The "SRT" prefix means "SELECT Result
** Type".
**
-** SRT_Union Store results as a key in a temporary index
-** identified by pDest->iSDParm.
-**
-** SRT_Except Remove results from the temporary index pDest->iSDParm.
-**
** SRT_Exists Store a 1 in memory cell pDest->iSDParm if the result
** set is not empty.
**
@@ -17828,9 +20684,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.
**
@@ -17842,7 +20695,11 @@ struct Select {
** SRT_Set The result must be a single column. Store each
** row of result as the key in table pDest->iSDParm.
** Apply the affinity pDest->affSdst before storing
-** results. Used to implement "IN (SELECT ...)".
+** results. if pDest->iSDParm2 is positive, then it is
+** a register holding a Bloom filter for the IN operator
+** that should be populated in addition to the
+** pDest->iSDParm table. This SRT is used to
+** implement "IN (SELECT ...)".
**
** SRT_EphemTab Create an temporary table pDest->iSDParm and store
** the result there. The cursor is left open after
@@ -17874,36 +20731,49 @@ 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_Queue 7 /* Store result in an queue */
-#define SRT_DistQueue 8 /* Like SRT_Queue, but unique results only */
+#define SRT_Exists 1 /* Store 1 if the result is not empty */
+#define SRT_Discard 2 /* Do not save the results anywhere */
+#define SRT_DistFifo 3 /* Like SRT_Fifo, but unique results only */
+#define SRT_DistQueue 4 /* 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 5 /* Store result in an queue */
+#define SRT_Fifo 6 /* 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 */
-#define SRT_Set 11 /* Store results as keys in an index */
-#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_Output 7 /* Output each row of result */
+#define SRT_Mem 8 /* Store result in a memory cell */
+#define SRT_Set 9 /* Store results as keys in an index */
+#define SRT_EphemTab 10 /* Create transient tab and store like SRT_Table */
+#define SRT_Coroutine 11 /* Generate a single row of result */
+#define SRT_Table 12 /* Store result as data with an automatic rowid */
+#define SRT_Upfrom 13 /* 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 */
+ char *zAffSdst; /* Affinity used for SRT_Set */
ExprList *pOrderBy; /* Key columns for SRT_Queue and SRT_DistQueue */
};
@@ -17962,11 +20832,45 @@ struct TriggerPrg {
#else
typedef unsigned int yDbMask;
# define DbMaskTest(M,I) (((M)&(((yDbMask)1)<<(I)))!=0)
-# define DbMaskZero(M) (M)=0
-# define DbMaskSet(M,I) (M)|=(((yDbMask)1)<<(I))
-# define DbMaskAllZero(M) (M)==0
-# define DbMaskNonZero(M) (M)!=0
+# define DbMaskZero(M) ((M)=0)
+# define DbMaskSet(M,I) ((M)|=(((yDbMask)1)<<(I)))
+# define DbMaskAllZero(M) ((M)==0)
+# define DbMaskNonZero(M) ((M)!=0)
+#endif
+
+/*
+** For each index X that has as one of its arguments either an expression
+** or the name of a virtual generated column, and if X is in scope such that
+** the value of the expression can simply be read from the index, then
+** there is an instance of this object on the Parse.pIdxExpr list.
+**
+** During code generation, while generating code to evaluate expressions,
+** this list is consulted and if a matching expression is found, the value
+** is read from the index rather than being recomputed.
+*/
+struct IndexedExpr {
+ Expr *pExpr; /* The expression contained in the index */
+ int iDataCur; /* The data cursor associated with the index */
+ int iIdxCur; /* The index cursor */
+ int iIdxCol; /* The index column that contains value of pExpr */
+ u8 bMaybeNullRow; /* True if we need an OP_IfNullRow check */
+ u8 aff; /* Affinity of the pExpr expression */
+ IndexedExpr *pIENext; /* Next in a list of all indexed expressions */
+#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
+ const char *zIdxName; /* Name of index, used only for bytecode comments */
#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
@@ -17989,16 +20893,33 @@ struct Parse {
char *zErrMsg; /* An error message */
Vdbe *pVdbe; /* An engine for executing database bytecode */
int rc; /* Return code from execution */
- u8 colNamesSet; /* TRUE after OP_ColumnName has been issued to pVdbe */
- u8 checkSchema; /* Causes schema cookie check after an error */
+ LogEst nQueryLoop; /* Est number of iterations of a query (10*log2(N)) */
u8 nested; /* Number of nested calls to the parser/code generator */
u8 nTempReg; /* Number of temporary registers in aTempReg[] */
u8 isMultiWrite; /* True if statement may modify/insert multiple rows */
- u8 mayAbort; /* True if statement may throw an ABORT exception */
- u8 hasCompound; /* Need to invoke convertCompoundSelectToSubquery() */
- 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 */
+ u8 prepFlags; /* SQLITE_PREPARE_* flags */
+ u8 withinRJSubrtn; /* Nesting level for RIGHT JOIN body subroutines */
+ u8 mSubrtnSig; /* mini Bloom filter on available SubrtnSig.selId */
+ u8 eTriggerOp; /* TK_UPDATE, TK_INSERT or TK_DELETE */
+ u8 eOrconf; /* Default ON CONFLICT policy for trigger steps */
+#if defined(SQLITE_DEBUG) || defined(SQLITE_COVERAGE_TEST)
+ u8 earlyCleanup; /* OOM inside sqlite3ParserAddCleanup() */
+#endif
+#ifdef SQLITE_DEBUG
+ u8 ifNotExists; /* Might be true if IF NOT EXISTS. Assert()s only */
+ u8 isCreate; /* CREATE TABLE, INDEX, or VIEW (but not TRIGGER)
+ ** and ALTER TABLE ADD COLUMN. */
+#endif
+ bft disableTriggers:1; /* True to disable triggers */
+ bft mayAbort :1; /* True if statement may throw an ABORT exception */
+ bft hasCompound :1; /* Need to invoke convertCompoundSelectToSubquery() */
+ bft bReturning :1; /* Coding a RETURNING trigger */
+ bft bHasExists :1; /* Has a correlated "EXISTS (SELECT ....)" expression */
+ bft colNamesSet :1; /* TRUE after OP_ColumnName has been issued to pVdbe */
+ bft bHasWith :1; /* True if statement contains WITH */
+ bft okConstFactor:1; /* OK to factor out constants */
+ bft checkSchema :1; /* Causes schema cookie check after an error */
int nRangeReg; /* Size of the temporary register block */
int iRangeReg; /* First register in temporary register block */
int nErr; /* Number of errors seen */
@@ -18007,17 +20928,20 @@ struct Parse {
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 nNestSel; /* Number of nested SELECT statements and/or VIEWs */
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 */
+ IndexedExpr *pIdxEpr;/* List of expressions used by active indexes */
+ IndexedExpr *pIdxPartExpr; /* Exprs constrained by index WHERE clauses */
yDbMask writeMask; /* Start a write transaction on these databases */
yDbMask cookieMask; /* Bitmask of schema verified databases */
- int regRowid; /* Register holding rowid of CREATE TABLE entry */
- int regRoot; /* Register holding root page number for new objects */
- int nMaxArg; /* Max args passed to user function by sub-program */
+ int nMaxArg; /* Max args to xUpdate and xFilter vtab methods */
int nSelect; /* Number of SELECT stmts. Counter for Select.selId */
+#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
+ u32 nProgressSteps; /* xProgress steps taken during sqlite3_prepare() */
+#endif
#ifndef SQLITE_OMIT_SHARED_CACHE
int nTableLock; /* Number of locks in aTableLock */
TableLock *aTableLock; /* Required table locks for shared-cache mode */
@@ -18025,14 +20949,8 @@ 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 */
- Parse *pParentParse; /* Parent parser if this parser is nested */
- int addrCrTab; /* Address of OP_CreateBtree opcode on CREATE TABLE */
- 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 eOrconf; /* Default ON CONFLICT policy for trigger steps */
- u8 disableTriggers; /* True to disable triggers */
+ TriggerPrg *pTriggerPrg; /* Linked list of coded triggers */
+ ParseCleanup *pCleanup; /* List of cleanup operations to run after parse */
/**************************************************************************
** Fields above must be initialized to zero. The fields that follow,
@@ -18042,7 +20960,21 @@ struct Parse {
**************************************************************************/
int aTempReg[8]; /* Holding area for temporary registers */
+ Parse *pOuterParse; /* Outer Parse object when nested */
Token sNameToken; /* Token with unqualified schema object name */
+ u32 oldmask; /* Mask of old.* columns referenced */
+ u32 newmask; /* Mask of new.* columns referenced */
+ union {
+ struct { /* These fields available when isCreate is true */
+ int addrCrTab; /* Address of OP_CreateBtree on CREATE TABLE */
+ int regRowid; /* Register holding rowid of CREATE TABLE entry */
+ int regRoot; /* Register holding root page for new objects */
+ Token constraintName; /* Name of the constraint currently being parsed */
+ } cr;
+ struct { /* These fields available to all other statements */
+ Returning *pReturning; /* The RETURNING clause */
+ } d;
+ } u1;
/************************************************************************
** Above is constant between recursions. Below is reset before and after
@@ -18055,16 +20987,12 @@ 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
int nHeight; /* Expression tree height of current sub-select */
-#ifndef SQLITE_OMIT_EXPLAIN
int addrExplain; /* Address of current OP_Explain opcode */
-#endif
VList *pVList; /* Mapping between variable names and numbers */
Vdbe *pReprepare; /* VM being reprepared (sqlite3Reprepare()) */
const char *zTail; /* All SQL text past the last semicolon parsed */
@@ -18078,24 +21006,24 @@ struct Parse {
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 */
#ifndef SQLITE_OMIT_ALTERTABLE
RenameToken *pRename; /* Tokens subject to renaming by ALTER TABLE */
#endif
};
+/* Allowed values for Parse.eParseMode
+*/
#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.
*/
-#define PARSE_HDR_SZ offsetof(Parse,aTempReg) /* Recursive part w/o aColCache*/
+#define PARSE_HDR(X) (((char*)(X))+offsetof(Parse,zErrMsg))
+#define PARSE_HDR_SZ (offsetof(Parse,aTempReg)-offsetof(Parse,zErrMsg)) /* Recursive part w/o aColCache*/
#define PARSE_RECURSE_SZ offsetof(Parse,sLastToken) /* Recursive part */
#define PARSE_TAIL_SZ (sizeof(Parse)-PARSE_RECURSE_SZ) /* Non-recursive part */
#define PARSE_TAIL(X) (((char*)(X))+PARSE_RECURSE_SZ) /* Pointer to tail */
@@ -18112,7 +21040,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)
@@ -18153,6 +21081,7 @@ struct AuthContext {
#define OPFLAG_ISNOOP 0x40 /* OP_Delete does pre-update-hook only */
#define OPFLAG_LENGTHARG 0x40 /* OP_Column only used for length() */
#define OPFLAG_TYPEOFARG 0x80 /* OP_Column only used for typeof() */
+#define OPFLAG_BYTELENARG 0xc0 /* OP_Column only for octet_length() */
#define OPFLAG_BULKCSR 0x01 /* OP_Open** used to open bulk cursor */
#define OPFLAG_SEEKEQ 0x02 /* OP_Open** cursor uses EQ seek only */
#define OPFLAG_FORDELETE 0x08 /* OP_Open should use BTREE_FORDELETE */
@@ -18161,27 +21090,29 @@ 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
- * struct Trigger.
- *
- * Pointers to instances of struct Trigger are stored in two ways.
- * 1. In the "trigHash" hash table (part of the sqlite3* that represents the
- * database). This allows Trigger structures to be retrieved by name.
- * 2. All triggers associated with a single table form a linked list, using the
- * pNext member of struct Trigger. A pointer to the first element of the
- * linked list is stored as the "pTrigger" member of the associated
- * struct Table.
- *
- * The "step_list" member points to the first element of a linked list
- * containing the SQL statements specified as the trigger program.
- */
+** Each trigger present in the database schema is stored as an instance of
+** struct Trigger.
+**
+** Pointers to instances of struct Trigger are stored in two ways.
+** 1. In the "trigHash" hash table (part of the sqlite3* that represents the
+** database). This allows Trigger structures to be retrieved by name.
+** 2. All triggers associated with a single table form a linked list, using the
+** pNext member of struct Trigger. A pointer to the first element of the
+** linked list is stored as the "pTrigger" member of the associated
+** struct Table.
+**
+** The "step_list" member points to the first element of a linked list
+** containing the SQL statements specified as the trigger program.
+*/
struct Trigger {
char *zName; /* The name of the 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 */
@@ -18202,51 +21133,57 @@ struct Trigger {
#define TRIGGER_AFTER 2
/*
- * An instance of struct TriggerStep is used to store a single SQL statement
- * that is a part of a trigger-program.
- *
- * Instances of struct TriggerStep are stored in a singly linked list (linked
- * using the "pNext" member) referenced by the "step_list" member of the
- * associated struct Trigger instance. The first element of the linked list is
- * the first step of the trigger-program.
- *
- * The "op" member indicates whether this is a "DELETE", "INSERT", "UPDATE" or
- * "SELECT" statement. The meanings of the other members is determined by the
- * value of "op" as follows:
- *
- * (op == TK_INSERT)
- * orconf -> stores the ON CONFLICT algorithm
- * pSelect -> If this is an INSERT INTO ... SELECT ... statement, then
- * this stores a pointer to the SELECT statement. Otherwise NULL.
- * zTarget -> Dequoted name of the table to insert into.
- * pExprList -> If this is an INSERT INTO ... VALUES ... statement, then
- * this stores values to be inserted. Otherwise NULL.
- * pIdList -> If this is an INSERT INTO ... () VALUES ...
- * statement, then this stores the column-names to be
- * inserted into.
- *
- * (op == TK_DELETE)
- * zTarget -> Dequoted name of the table to delete from.
- * pWhere -> The WHERE clause of the DELETE statement if one is specified.
- * Otherwise NULL.
- *
- * (op == TK_UPDATE)
- * zTarget -> Dequoted name of the table to update.
- * pWhere -> The WHERE clause of the UPDATE statement if one is specified.
- * Otherwise NULL.
- * pExprList -> A list of the columns to update and the expressions to update
- * them to. See sqlite3Update() documentation of "pChanges"
- * argument.
- *
- */
+** An instance of struct TriggerStep is used to store a single SQL statement
+** that is a part of a trigger-program.
+**
+** Instances of struct TriggerStep are stored in a singly linked list (linked
+** using the "pNext" member) referenced by the "step_list" member of the
+** associated struct Trigger instance. The first element of the linked list is
+** the first step of the trigger-program.
+**
+** The "op" member indicates whether this is a "DELETE", "INSERT", "UPDATE" or
+** "SELECT" statement. The meanings of the other members is determined by the
+** value of "op" as follows:
+**
+** (op == TK_INSERT)
+** orconf -> stores the ON CONFLICT algorithm
+** pSelect -> The content to be inserted - either a SELECT statement or
+** a VALUES clause.
+** pSrc -> Table to insert into.
+** pIdList -> If this is an INSERT INTO ... () VALUES ...
+** statement, then this stores the column-names to be
+** inserted into.
+** pUpsert -> The ON CONFLICT clauses for an Upsert
+**
+** (op == TK_DELETE)
+** pSrc -> Table to delete from
+** pWhere -> The WHERE clause of the DELETE statement if one is specified.
+** Otherwise NULL.
+**
+** (op == TK_UPDATE)
+** pSrc -> Table to update, followed by any FROM clause tables.
+** pWhere -> The WHERE clause of the UPDATE statement if one is specified.
+** Otherwise NULL.
+** pExprList -> A list of the columns to update and the expressions to update
+** them to. See sqlite3Update() documentation of "pChanges"
+** argument.
+**
+** (op == TK_SELECT)
+** pSelect -> The SELECT statement
+**
+** (op == TK_RETURNING)
+** pExprList -> The list of expressions that follow the RETURNING keyword.
+**
+*/
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 *pSrc; /* Table to insert/update/delete */
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 */
@@ -18255,22 +21192,21 @@ 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 */
+ char zName[40]; /* Name of trigger: "sqlite_returning_%p" */
};
/*
-** An objected used to accumulate the text of a string where we
+** An object used to accumulate the text of a string where we
** do not necessarily know how big the string will be in the end.
*/
struct sqlite3_str {
@@ -18284,10 +21220,32 @@ struct sqlite3_str {
};
#define SQLITE_PRINTF_INTERNAL 0x01 /* Internal-use-only converters allowed */
#define SQLITE_PRINTF_SQLFUNC 0x02 /* SQL function arguments to VXPrintf */
-#define SQLITE_PRINTF_MALLOCED 0x04 /* True if xText is allocated space */
+#define SQLITE_PRINTF_MALLOCED 0x04 /* True if zText is allocated space */
#define isMalloced(X) (((X)->printfFlags & SQLITE_PRINTF_MALLOCED)!=0)
+/*
+** The following object is the header for an "RCStr" or "reference-counted
+** string". An RCStr is passed around and used like any other char*
+** that has been dynamically allocated. The important interface
+** differences:
+**
+** 1. RCStr strings are reference counted. They are deallocated
+** when the reference count reaches zero.
+**
+** 2. Use sqlite3RCStrUnref() to free an RCStr string rather than
+** sqlite3_free()
+**
+** 3. Make a (read-only) copy of a read-only RCStr string using
+** sqlite3RCStrRef().
+**
+** "String" is in the name, but an RCStr object can also be used to hold
+** binary data.
+*/
+struct RCStr {
+ u64 nRCRef; /* Number of references */
+ /* Total structure size should be a multiple of 8 bytes for alignment */
+};
/*
** A pointer to this structure is used to communicate information
@@ -18300,12 +21258,33 @@ typedef struct {
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_AlterMask 0x0007 /* Types of ALTER */
+#define INITFLAG_AlterRename 0x0001 /* Reparse after a RENAME */
+#define INITFLAG_AlterDrop 0x0002 /* Reparse after a DROP COLUMN */
+#define INITFLAG_AlterAdd 0x0003 /* Reparse after an ADD COLUMN */
+#define INITFLAG_AlterDropCons 0x0004 /* Reparse after an ADD 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
+** optimal 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.
@@ -18314,11 +21293,15 @@ 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 */
+#ifdef SQLITE_DEBUG
+ u8 bJsonSelfcheck; /* Double-check JSON parsing */
+#endif
int mxStrlen; /* Maximum string length */
int neverCorrupt; /* Database is always well-formed */
int szLookaside; /* Default lookaside buffer size */
@@ -18360,16 +21343,26 @@ struct Sqlite3Config {
void (*xVdbeBranch)(void*,unsigned iSrcLine,u8 eThis,u8 eMx); /* Callback */
void *pVdbeBranchArg; /* 1st argument */
#endif
-#ifdef SQLITE_ENABLE_DESERIALIZE
+#ifndef SQLITE_OMIT_DESERIALIZE
sqlite3_int64 mxMemdbSize; /* Default max memdb size */
#endif
#ifndef SQLITE_UNTESTABLE
int (*xTestCallback)(int); /* Invoked by sqlite3FaultSim() */
+#endif
+#ifdef SQLITE_ALLOW_ROWID_IN_VIEW
+ u32 mNoVisibleRowid; /* TF_NoVisibleRowid if the ROWID_IN_VIEW
+ ** feature is disabled. 0 if rowids can
+ ** occur in views. */
#endif
int bLocaltimeFault; /* True to fail localtime() calls */
- int bInternalFunctions; /* Internal SQL functions are visible */
+ int (*xAltLocaltime)(const void*,void*); /* Alternative localtime() routine */
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
};
/*
@@ -18399,27 +21392,50 @@ 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 */
+ u16 mWFlags; /* Use-dependent flags */
union { /* Extra data for callback */
NameContext *pNC; /* Naming context */
int n; /* A counter */
int iCur; /* A cursor number */
+ int sz; /* String literal length */
SrcList *pSrcList; /* FROM clause */
- struct SrcCount *pSrcCount; /* Counting column references */
struct CCurHint *pCCurHint; /* Used by codeCursorHint() */
+ struct RefSrcList *pRefSrcList; /* sqlite3ReferencesSrcList() */
int *aiCol; /* array of column indexes */
struct IdxCover *pIdxCover; /* Check for index coverage */
- struct IdxExprTrans *pIdxTrans; /* Convert idxed expr to column */
ExprList *pGroupBy; /* GROUP BY clause */
Select *pSelect; /* HAVING to WHERE clause ctx */
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 */
+ struct CoveringIndexCheck *pCovIdxCk; /* Check for covering index */
+ SrcItem *pSrcItem; /* A single FROM clause item */
+ DbFixer *pFix; /* See sqlite3FixSelect() */
+ Mem *aMem; /* See sqlite3BtreeCursorHint() */
+ struct CheckOnCtx *pCheckOnCtx; /* See selectCheckOnClauses() */
} 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 sqlite3WalkExprNN(Walker*, Expr*);
SQLITE_PRIVATE int sqlite3WalkExprList(Walker*, ExprList*);
SQLITE_PRIVATE int sqlite3WalkSelect(Walker*, Select*);
SQLITE_PRIVATE int sqlite3WalkSelectExpr(Walker*, Select*);
@@ -18427,10 +21443,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.
@@ -18440,20 +21466,74 @@ 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[FLEXARRAY]; /* For each CTE in the WITH clause.... */
+};
+
+/* The size (in bytes) of a With object that can hold as many
+** as N different CTEs. */
+#define SZ_WITH(N) (offsetof(With,a) + (N)*sizeof(Cte))
+
+/*
+** 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 */
+};
+
+
+/* Client data associated with sqlite3_set_clientdata() and
+** sqlite3_get_clientdata().
+*/
+struct DbClientData {
+ DbClientData *pNext; /* Next in a linked list */
+ void *pData; /* The data */
+ void (*xDestructor)(void*); /* Destructor. Might be NULL */
+ char zName[FLEXARRAY]; /* Name of this client data. MUST BE LAST */
};
+/* The size (in bytes) of a DbClientData object that can has a name
+** that is N bytes long, including the zero-terminator. */
+#define SZ_DBCLIENTDATA(N) (offsetof(DbClientData,zName)+(N))
+
#ifdef SQLITE_DEBUG
/*
** An instance of the TreeView object is used for printing the content of
@@ -18466,10 +21546,11 @@ struct TreeView {
#endif /* SQLITE_DEBUG */
/*
-** This object is used in various 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.
**
@@ -18480,6 +21561,10 @@ 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 case (3) are separate objects.
*/
@@ -18495,12 +21580,13 @@ struct Window {
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 */
+ FuncDef *pWFunc; /* 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; /* Array of registers for PARTITION BY values */
@@ -18510,18 +21596,24 @@ struct Window {
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 */
};
+SQLITE_PRIVATE Select *sqlite3MultiValues(Parse *pParse, Select *pLeft, ExprList *pRow);
+SQLITE_PRIVATE void sqlite3MultiValuesEnd(Parse *pParse, Select *pVal);
+
#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*, 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(const Parse*, const Window*, const 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);
@@ -18561,13 +21653,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
@@ -18588,15 +21683,6 @@ SQLITE_PRIVATE int sqlite3CorruptPgnoError(int,Pgno);
# define SQLITE_ENABLE_FTS3 1
#endif
-/*
-** The ctype.h header is needed for non-ASCII systems. It is also
-** needed by FTS3 when FTS3 is included in the amalgamation.
-*/
-#if !defined(SQLITE_ASCII) || \
- (defined(SQLITE_ENABLE_FTS3) && defined(SQLITE_AMALGAMATION))
-# include
-#endif
-
/*
** The following macros mimic the standard library functions toupper(),
** isspace(), isalnum(), isdigit() and isxdigit(), respectively. The
@@ -18611,6 +21697,8 @@ SQLITE_PRIVATE int sqlite3CorruptPgnoError(int,Pgno);
# define sqlite3Isxdigit(x) (sqlite3CtypeMap[(unsigned char)(x)]&0x08)
# define sqlite3Tolower(x) (sqlite3UpperToLower[(unsigned char)(x)])
# define sqlite3Isquote(x) (sqlite3CtypeMap[(unsigned char)(x)]&0x80)
+# define sqlite3JsonId1(x) (sqlite3CtypeMap[(unsigned char)(x)]&0x42)
+# define sqlite3JsonId2(x) (sqlite3CtypeMap[(unsigned char)(x)]&0x46)
#else
# define sqlite3Toupper(x) toupper((unsigned char)(x))
# define sqlite3Isspace(x) isspace((unsigned char)(x))
@@ -18620,6 +21708,8 @@ SQLITE_PRIVATE int sqlite3CorruptPgnoError(int,Pgno);
# define sqlite3Isxdigit(x) isxdigit((unsigned char)(x))
# define sqlite3Tolower(x) tolower((unsigned char)(x))
# define sqlite3Isquote(x) ((x)=='"'||(x)=='\''||(x)=='['||(x)=='`')
+# define sqlite3JsonId1(x) (sqlite3IsIdChar(x)&&(x)<'0')
+# define sqlite3JsonId2(x) sqlite3IsIdChar(x)
#endif
SQLITE_PRIVATE int sqlite3IsIdChar(u8);
@@ -18647,8 +21737,9 @@ SQLITE_PRIVATE void *sqlite3DbReallocOrFree(sqlite3 *, void *, u64);
SQLITE_PRIVATE void *sqlite3DbRealloc(sqlite3 *, void *, u64);
SQLITE_PRIVATE void sqlite3DbFree(sqlite3*, void*);
SQLITE_PRIVATE void sqlite3DbFreeNN(sqlite3*, void*);
-SQLITE_PRIVATE int sqlite3MallocSize(void*);
-SQLITE_PRIVATE int sqlite3DbMallocSize(sqlite3*, void*);
+SQLITE_PRIVATE void sqlite3DbNNFreeNN(sqlite3*, void*);
+SQLITE_PRIVATE int sqlite3MallocSize(const void*);
+SQLITE_PRIVATE int sqlite3DbMallocSize(sqlite3*, const void*);
SQLITE_PRIVATE void *sqlite3PageMalloc(int);
SQLITE_PRIVATE void sqlite3PageFree(void*);
SQLITE_PRIVATE void sqlite3MemSetDefault(void);
@@ -18667,12 +21758,14 @@ SQLITE_PRIVATE int sqlite3HeapNearlyFull(void);
*/
#ifdef SQLITE_USE_ALLOCA
# define sqlite3StackAllocRaw(D,N) alloca(N)
-# define sqlite3StackAllocZero(D,N) memset(alloca(N), 0, N)
+# define sqlite3StackAllocRawNN(D,N) alloca(N)
# define sqlite3StackFree(D,P)
+# define sqlite3StackFreeNN(D,P)
#else
# define sqlite3StackAllocRaw(D,N) sqlite3DbMallocRaw(D,N)
-# define sqlite3StackAllocZero(D,N) sqlite3DbMallocZero(D,N)
+# define sqlite3StackAllocRawNN(D,N) sqlite3DbMallocRawNN(D,N)
# define sqlite3StackFree(D,P) sqlite3DbFree(D,P)
+# define sqlite3StackFreeNN(D,P) sqlite3DbFreeNN(D,P)
#endif
/* Do not allow both MEMSYS5 and MEMSYS3 to be defined together. If they
@@ -18710,16 +21803,36 @@ SQLITE_PRIVATE int sqlite3LookasideUsed(sqlite3*,int*);
SQLITE_PRIVATE sqlite3_mutex *sqlite3Pcache1Mutex(void);
SQLITE_PRIVATE sqlite3_mutex *sqlite3MallocMutex(void);
-#if defined(SQLITE_ENABLE_MULTITHREADED_CHECKS) && !defined(SQLITE_MUTEX_OMIT)
+
+/* The SQLITE_THREAD_MISUSE_WARNINGS compile-time option used to be called
+** SQLITE_ENABLE_MULTITHREADED_CHECKS. Keep that older macro for backwards
+** compatibility, at least for a while... */
+#ifdef SQLITE_ENABLE_MULTITHREADED_CHECKS
+# define SQLITE_THREAD_MISUSE_WARNINGS 1
+#endif
+
+/* SQLITE_THREAD_MISUSE_ABORT implies SQLITE_THREAD_MISUSE_WARNINGS */
+#ifdef SQLITE_THREAD_MISUSE_ABORT
+# define SQLITE_THREAD_MISUSE_WARNINGS 1
+#endif
+
+#if defined(SQLITE_THREAD_MISUSE_WARNINGS) && !defined(SQLITE_MUTEX_OMIT)
SQLITE_PRIVATE void sqlite3MutexWarnOnContention(sqlite3_mutex*);
#else
# define sqlite3MutexWarnOnContention(x)
#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)
+# define IsOvfl(X) (((X)&EXP754)==EXP754)
SQLITE_PRIVATE int sqlite3IsNaN(double);
+SQLITE_PRIVATE int sqlite3IsOverflow(double);
#else
-# define sqlite3IsNaN(X) 0
+# define IsNaN(X) 0
+# define sqlite3IsNaN(X) 0
+# define sqlite3IsOVerflow(X) 0
#endif
/*
@@ -18732,6 +21845,25 @@ struct PrintfArguments {
sqlite3_value **apArg; /* The argument values */
};
+/*
+** Maxium number of base-10 digits in an unsigned 64-bit integer
+*/
+#define SQLITE_U64_DIGITS 20
+
+/*
+** An instance of this object receives the decoding of a floating point
+** value into an approximate decimal representation.
+*/
+struct FpDecode {
+ int n; /* Significant digits in the decode */
+ int iDP; /* Location of the decimal point */
+ char *z; /* Start of significant digits */
+ char zBuf[SQLITE_U64_DIGITS+1]; /* Storage for significant digits */
+ char sign; /* '+' or '-' */
+ char isSpecial; /* 1: Infinity 2: NaN */
+};
+
+SQLITE_PRIVATE void sqlite3FpDecode(FpDecode*,double,int,int);
SQLITE_PRIVATE char *sqlite3MPrintf(sqlite3*,const char*, ...);
SQLITE_PRIVATE char *sqlite3VMPrintf(sqlite3*,const char*, va_list);
#if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE)
@@ -18742,51 +21874,104 @@ SQLITE_PRIVATE void *sqlite3TestTextToPtr(const char*);
#endif
#if defined(SQLITE_DEBUG)
+SQLITE_PRIVATE void sqlite3TreeViewLine(TreeView*, const char *zFormat, ...);
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 sqlite3TreeViewBareIdList(TreeView*, const IdList*, const char*);
+SQLITE_PRIVATE void sqlite3TreeViewIdList(TreeView*, const IdList*, u8, const char*);
+SQLITE_PRIVATE void sqlite3TreeViewColumnList(TreeView*, const Column*, int, u8);
SQLITE_PRIVATE void sqlite3TreeViewSrcList(TreeView*, const SrcList*);
SQLITE_PRIVATE void sqlite3TreeViewSelect(TreeView*, const Select*, u8);
SQLITE_PRIVATE void sqlite3TreeViewWith(TreeView*, const With*, u8);
+SQLITE_PRIVATE void sqlite3TreeViewUpsert(TreeView*, const Upsert*, u8);
+#if TREETRACE_ENABLED
+SQLITE_PRIVATE void sqlite3TreeViewDelete(const With*, const SrcList*, const Expr*,
+ const ExprList*,const Expr*, const Trigger*);
+SQLITE_PRIVATE void sqlite3TreeViewInsert(const With*, const SrcList*,
+ const IdList*, const Select*, const ExprList*,
+ int, const Upsert*, const Trigger*);
+SQLITE_PRIVATE void sqlite3TreeViewUpdate(const With*, const SrcList*, const ExprList*,
+ const Expr*, int, const ExprList*, const Expr*,
+ const Upsert*, const Trigger*);
+#endif
+#ifndef SQLITE_OMIT_TRIGGER
+SQLITE_PRIVATE void sqlite3TreeViewTriggerStep(TreeView*, const TriggerStep*, u8, u8);
+SQLITE_PRIVATE void sqlite3TreeViewTrigger(TreeView*, const Trigger*, u8, u8);
+#endif
#ifndef SQLITE_OMIT_WINDOWFUNC
SQLITE_PRIVATE void sqlite3TreeViewWindow(TreeView*, const Window*, u8);
SQLITE_PRIVATE void sqlite3TreeViewWinFunc(TreeView*, const Window*, u8);
#endif
+SQLITE_PRIVATE void sqlite3ShowExpr(const Expr*);
+SQLITE_PRIVATE void sqlite3ShowExprList(const ExprList*);
+SQLITE_PRIVATE void sqlite3ShowIdList(const IdList*);
+SQLITE_PRIVATE void sqlite3ShowSrcList(const SrcList*);
+SQLITE_PRIVATE void sqlite3ShowSelect(const Select*);
+SQLITE_PRIVATE void sqlite3ShowWith(const With*);
+SQLITE_PRIVATE void sqlite3ShowUpsert(const Upsert*);
+#ifndef SQLITE_OMIT_TRIGGER
+SQLITE_PRIVATE void sqlite3ShowTriggerStep(const TriggerStep*);
+SQLITE_PRIVATE void sqlite3ShowTriggerStepList(const TriggerStep*);
+SQLITE_PRIVATE void sqlite3ShowTrigger(const Trigger*);
+SQLITE_PRIVATE void sqlite3ShowTriggerList(const Trigger*);
+#endif
+#ifndef SQLITE_OMIT_WINDOWFUNC
+SQLITE_PRIVATE void sqlite3ShowWindow(const Window*);
+SQLITE_PRIVATE void sqlite3ShowWinFunc(const Window*);
+#endif
+SQLITE_PRIVATE void sqlite3ShowBitvec(Bitvec*);
#endif
-
SQLITE_PRIVATE void sqlite3SetString(char **, sqlite3*, const char*);
+SQLITE_PRIVATE void sqlite3ProgressCheck(Parse*);
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 sqlite3DequoteToken(Token*);
+SQLITE_PRIVATE void sqlite3DequoteNumber(Parse*, Expr*);
SQLITE_PRIVATE void sqlite3TokenInit(Token*,char*);
SQLITE_PRIVATE int sqlite3KeywordCode(const unsigned char*, int);
-SQLITE_PRIVATE int sqlite3RunParser(Parse*, const char*, char **);
+SQLITE_PRIVATE int sqlite3RunParser(Parse*, const char*);
SQLITE_PRIVATE void sqlite3FinishCoding(Parse*);
SQLITE_PRIVATE int sqlite3GetTempReg(Parse*);
SQLITE_PRIVATE void sqlite3ReleaseTempReg(Parse*,int);
SQLITE_PRIVATE int sqlite3GetTempRange(Parse*,int);
SQLITE_PRIVATE void sqlite3ReleaseTempRange(Parse*,int,int);
SQLITE_PRIVATE void sqlite3ClearTempRegCache(Parse*);
+SQLITE_PRIVATE void sqlite3TouchRegister(Parse*,int);
+#if defined(SQLITE_ENABLE_STAT4) || defined(SQLITE_DEBUG)
+SQLITE_PRIVATE int sqlite3FirstAvailableRegister(Parse*,int);
+#endif
#ifdef SQLITE_DEBUG
SQLITE_PRIVATE int sqlite3NoTempsInRange(Parse*,int,int);
#endif
SQLITE_PRIVATE Expr *sqlite3ExprAlloc(sqlite3*,int,const Token*,int);
SQLITE_PRIVATE Expr *sqlite3Expr(sqlite3*,int,const char*);
+SQLITE_PRIVATE Expr *sqlite3ExprInt32(sqlite3*,int);
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 *sqlite3ExprFunction(Parse*,ExprList*, Token*, int);
+SQLITE_PRIVATE Expr *sqlite3ExprAnd(Parse*,Expr*, Expr*);
+SQLITE_PRIVATE Expr *sqlite3ExprSimplifiedAndOr(Expr*);
+SQLITE_PRIVATE Expr *sqlite3ExprFunction(Parse*,ExprList*, const Token*, int);
+SQLITE_PRIVATE void sqlite3ExprAddFunctionOrderBy(Parse*,Expr*,ExprList*);
+SQLITE_PRIVATE void sqlite3ExprOrderByAggregateError(Parse*,Expr*);
+SQLITE_PRIVATE void sqlite3ExprFunctionUsable(Parse*,const Expr*,const FuncDef*);
SQLITE_PRIVATE void sqlite3ExprAssignVarNumber(Parse*, Expr*, u32);
SQLITE_PRIVATE void sqlite3ExprDelete(sqlite3*, Expr*);
+SQLITE_PRIVATE void sqlite3ExprDeleteGeneric(sqlite3*,void*);
+SQLITE_PRIVATE int 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 sqlite3ExprListSetName(Parse*,ExprList*,Token*,int);
+SQLITE_PRIVATE Select *sqlite3ExprListToValues(Parse*, int, ExprList*);
+SQLITE_PRIVATE void sqlite3ExprListSetSortOrder(ExprList*,int,int);
+SQLITE_PRIVATE void sqlite3ExprListSetName(Parse*,ExprList*,const Token*,int);
SQLITE_PRIVATE void sqlite3ExprListSetSpan(Parse*,ExprList*,const char*,const char*);
SQLITE_PRIVATE void sqlite3ExprListDelete(sqlite3*, ExprList*);
+SQLITE_PRIVATE void sqlite3ExprListDeleteGeneric(sqlite3*,void*);
SQLITE_PRIVATE u32 sqlite3ExprListFlags(const ExprList*);
SQLITE_PRIVATE int sqlite3IndexHasDuplicateRootPage(Index*);
SQLITE_PRIVATE int sqlite3Init(sqlite3*, char**);
@@ -18800,33 +21985,43 @@ SQLITE_PRIVATE void sqlite3ResetAllSchemasOfConnection(sqlite3*);
SQLITE_PRIVATE void sqlite3ResetOneSchema(sqlite3*,int);
SQLITE_PRIVATE void sqlite3CollapseDatabaseArray(sqlite3*);
SQLITE_PRIVATE void sqlite3CommitInternalChanges(sqlite3*);
+SQLITE_PRIVATE void sqlite3ColumnSetExpr(Parse*,Table*,Column*,Expr*);
+SQLITE_PRIVATE Expr *sqlite3ColumnExpr(Table*,Column*);
+SQLITE_PRIVATE void sqlite3ColumnSetColl(sqlite3*,Column*,const char*zColl);
+SQLITE_PRIVATE const char *sqlite3ColumnColl(Column*);
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 sqlite3SubqueryColumnTypes(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 int sqlite3TableColumnToIndex(Index*, int);
+#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*);
#else
# define sqlite3ColumnPropertiesFromName(T,C) /* no-op */
#endif
-SQLITE_PRIVATE void sqlite3AddColumn(Parse*,Token*,Token*);
+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 sqlite3EndTable(Parse*,Token*,Token*,u8,Select*);
+SQLITE_PRIVATE void sqlite3AddGenerated(Parse*,Expr*,Token*);
+SQLITE_PRIVATE void sqlite3EndTable(Parse*,Token*,Token*,u32,Select*);
+SQLITE_PRIVATE void sqlite3AddReturning(Parse*,ExprList*);
SQLITE_PRIVATE int sqlite3ParseUri(const char*,const char*,unsigned int*,
sqlite3_vfs**,char**,char **);
-#ifdef SQLITE_HAS_CODEC
-SQLITE_PRIVATE int sqlite3CodecQueryParameters(sqlite3*,const char*,const char*);
-#else
-# define sqlite3CodecQueryParameters(A,B,C) 0
-#endif
+#define sqlite3CodecQueryParameters(A,B,C) 0
SQLITE_PRIVATE Btree *sqlite3DbNameToBtree(sqlite3*,const char*);
#ifdef SQLITE_UNTESTABLE
@@ -18867,6 +22062,7 @@ SQLITE_PRIVATE int sqlite3DbMaskAllZero(yDbMask);
SQLITE_PRIVATE void sqlite3DropTable(Parse*, SrcList*, int, int);
SQLITE_PRIVATE void sqlite3CodeDropTable(Parse*, Table*, int, int);
SQLITE_PRIVATE void sqlite3DeleteTable(sqlite3*, Table*);
+SQLITE_PRIVATE void sqlite3DeleteTableGeneric(sqlite3*, void*);
SQLITE_PRIVATE void sqlite3FreeIndex(sqlite3*, Index*);
#ifndef SQLITE_OMIT_AUTOINCREMENT
SQLITE_PRIVATE void sqlite3AutoincrementBegin(Parse *pParse);
@@ -18876,21 +22072,29 @@ 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(Parse*, SrcList*, int, int);
+SQLITE_PRIVATE SrcList *sqlite3SrcListAppendList(Parse *pParse, SrcList *p1, SrcList *p2);
SQLITE_PRIVATE SrcList *sqlite3SrcListAppend(Parse*, SrcList*, Token*, Token*);
+SQLITE_PRIVATE void sqlite3SubqueryDelete(sqlite3*,Subquery*);
+SQLITE_PRIVATE Select *sqlite3SubqueryDetach(sqlite3*,SrcItem*);
+SQLITE_PRIVATE int sqlite3SrcItemAttachSubquery(Parse*, SrcItem*, Select*, int);
SQLITE_PRIVATE SrcList *sqlite3SrcListAppendFromTerm(Parse*, SrcList*, Token*, Token*,
- Token*, Select*, Expr*, IdList*);
+ Token*, Select*, OnOrUsing*);
SQLITE_PRIVATE void sqlite3SrcListIndexedBy(Parse *, SrcList *, Token *);
SQLITE_PRIVATE void sqlite3SrcListFuncArgs(Parse*, SrcList*, ExprList*);
-SQLITE_PRIVATE int sqlite3IndexedByLookup(Parse *, struct SrcList_item *);
-SQLITE_PRIVATE void sqlite3SrcListShiftJoinType(SrcList*);
+SQLITE_PRIVATE int sqlite3IndexedByLookup(Parse *, SrcItem *);
+SQLITE_PRIVATE void sqlite3SrcListShiftJoinType(Parse*,SrcList*);
SQLITE_PRIVATE void sqlite3SrcListAssignCursors(Parse*, SrcList*);
SQLITE_PRIVATE void sqlite3IdListDelete(sqlite3*, IdList*);
+SQLITE_PRIVATE void sqlite3ClearOnOrUsing(sqlite3*, OnOrUsing*);
SQLITE_PRIVATE void sqlite3SrcListDelete(sqlite3*, SrcList*);
-SQLITE_PRIVATE Index *sqlite3AllocateIndexObject(sqlite3*,i16,int,char**);
+SQLITE_PRIVATE Index *sqlite3AllocateIndexObject(sqlite3*,int,int,char**);
SQLITE_PRIVATE void sqlite3CreateIndex(Parse*,Token*,Token*,SrcList*,ExprList*,int,Token*,
Expr*, int, int, u8);
SQLITE_PRIVATE void sqlite3DropIndex(Parse*, SrcList*, int);
@@ -18898,21 +22102,26 @@ SQLITE_PRIVATE int sqlite3Select(Parse*, Select*, SelectDest*);
SQLITE_PRIVATE Select *sqlite3SelectNew(Parse*,ExprList*,SrcList*,Expr*,ExprList*,
Expr*,ExprList*,u32,Expr*);
SQLITE_PRIVATE void sqlite3SelectDelete(sqlite3*, Select*);
+SQLITE_PRIVATE void sqlite3SelectDeleteGeneric(sqlite3*,void*);
+SQLITE_PRIVATE void sqlite3SelectCheckOnClauses(Parse *pParse, Select *pSelect);
SQLITE_PRIVATE Table *sqlite3SrcListLookup(Parse*, SrcList*);
-SQLITE_PRIVATE int sqlite3IsReadOnly(Parse*, Table*, int);
+SQLITE_PRIVATE int sqlite3IsReadOnly(Parse*, Table*, Trigger*);
SQLITE_PRIVATE void sqlite3OpenTable(Parse*, int iCur, int iDb, Table*, int);
#if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY)
SQLITE_PRIVATE Expr *sqlite3LimitWhere(Parse*,SrcList*,Expr*,ExprList*,Expr*,char*);
#endif
+SQLITE_PRIVATE void sqlite3CodeChangeCount(Vdbe*,int,const char*);
SQLITE_PRIVATE void sqlite3DeleteFrom(Parse*, SrcList*, Expr*, ExprList*, Expr*);
SQLITE_PRIVATE void sqlite3Update(Parse*, SrcList*, ExprList*,Expr*,int,ExprList*,Expr*,
Upsert*);
-SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(Parse*,SrcList*,Expr*,ExprList*,ExprList*,u16,int);
+SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(Parse*,SrcList*,Expr*,ExprList*,
+ ExprList*,Select*,u16,int);
SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo*);
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*);
@@ -18920,17 +22129,22 @@ 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 sqlite3ExprToRegister(Expr *pExpr, int iReg);
SQLITE_PRIVATE void sqlite3ExprCode(Parse*, Expr*, int);
+#ifndef SQLITE_OMIT_GENERATED_COLUMNS
+SQLITE_PRIVATE void sqlite3ExprCodeGeneratedColumn(Parse*, Table*, 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 void sqlite3ExprNullRegisterRange(Parse*, int, 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 */
@@ -18943,22 +22157,24 @@ 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 const char *sqlite3PreferredTableName(const char*);
+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*,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 char *sqlite3NameFromToken(sqlite3*, const Token*);
+SQLITE_PRIVATE int sqlite3ExprCompare(const Parse*,const Expr*,const Expr*, int);
+SQLITE_PRIVATE int sqlite3ExprCompareSkip(Expr*,Expr*,int);
+SQLITE_PRIVATE int sqlite3ExprListCompare(const ExprList*,const ExprList*, int);
+SQLITE_PRIVATE int sqlite3ExprImpliesExpr(const Parse*,const Expr*,const Expr*, int);
+SQLITE_PRIVATE int sqlite3ExprImpliesNonNullRow(Expr*,int,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);
-SQLITE_PRIVATE int sqlite3FunctionUsesThisSrc(Expr*, SrcList*);
+SQLITE_PRIVATE int sqlite3ReferencesSrcList(Parse*, Expr*, SrcList*);
SQLITE_PRIVATE Vdbe *sqlite3GetVdbe(Parse*);
#ifndef SQLITE_UNTESTABLE
SQLITE_PRIVATE void sqlite3PrngSaveState(void);
@@ -18972,20 +22188,22 @@ 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*);
-SQLITE_PRIVATE int sqlite3ExprIsConstantNotJoin(Expr*);
+SQLITE_PRIVATE int sqlite3ExprIsConstant(Parse*,Expr*);
SQLITE_PRIVATE int sqlite3ExprIsConstantOrFunction(Expr*, u8);
SQLITE_PRIVATE int sqlite3ExprIsConstantOrGroupBy(Parse*, Expr*, ExprList*);
-SQLITE_PRIVATE int sqlite3ExprIsTableConstant(Expr*,int);
+SQLITE_PRIVATE int sqlite3ExprIsSingleTableConstraint(Expr*,const SrcList*,int,int);
#ifdef SQLITE_ENABLE_CURSOR_HINTS
SQLITE_PRIVATE int sqlite3ExprContainsSubquery(Expr*);
#endif
-SQLITE_PRIVATE int sqlite3ExprIsInteger(Expr*, int*);
+SQLITE_PRIVATE int sqlite3ExprIsInteger(const Expr*, int*, Parse*);
SQLITE_PRIVATE int sqlite3ExprCanBeNull(const Expr*);
SQLITE_PRIVATE int sqlite3ExprNeedsNoAffinityChange(const Expr*, char);
+SQLITE_PRIVATE int sqlite3ExprIsLikeOperator(const Expr*);
SQLITE_PRIVATE int sqlite3IsRowid(const char*);
+SQLITE_PRIVATE const char *sqlite3RowidAlias(Table *pTab);
SQLITE_PRIVATE void sqlite3GenerateRowDelete(
Parse*,Table*,Trigger*,int,int,int,i16,u8,u8,u8,int);
SQLITE_PRIVATE void sqlite3GenerateRowIndexDelete(Parse*, Table*, int, int, int*, int);
@@ -19007,20 +22225,31 @@ SQLITE_PRIVATE void sqlite3MayAbort(Parse*);
SQLITE_PRIVATE void sqlite3HaltConstraint(Parse*, int, int, char*, i8, u8);
SQLITE_PRIVATE void sqlite3UniqueConstraint(Parse*, int, Index*);
SQLITE_PRIVATE void sqlite3RowidConstraint(Parse*, int, Table*);
-SQLITE_PRIVATE Expr *sqlite3ExprDup(sqlite3*,Expr*,int);
-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 Expr *sqlite3ExprDup(sqlite3*,const Expr*,int);
+SQLITE_PRIVATE ExprList *sqlite3ExprListDup(sqlite3*,const ExprList*,int);
+SQLITE_PRIVATE SrcList *sqlite3SrcListDup(sqlite3*,const SrcList*,int);
+SQLITE_PRIVATE IdList *sqlite3IdListDup(sqlite3*,const IdList*);
+SQLITE_PRIVATE Select *sqlite3SelectDup(sqlite3*,const 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 sqlite3QuoteValue(StrAccum*,sqlite3_value*,int);
+SQLITE_PRIVATE int sqlite3AppendOneUtf8Character(char*, u32);
SQLITE_PRIVATE void sqlite3RegisterBuiltinFunctions(void);
SQLITE_PRIVATE void sqlite3RegisterDateTimeFunctions(void);
+SQLITE_PRIVATE void sqlite3RegisterJsonFunctions(void);
SQLITE_PRIVATE void sqlite3RegisterPerConnectionBuiltinFunctions(sqlite3*);
+#if !defined(SQLITE_OMIT_VIRTUALTABLE) && !defined(SQLITE_OMIT_JSON)
+SQLITE_PRIVATE Module *sqlite3JsonVtabRegister(sqlite3*,const char*);
+#endif
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_VIRTUALTABLE) && defined(SQLITE_ENABLE_CARRAY)
+SQLITE_PRIVATE Module *sqlite3CarrayRegister(sqlite3*);
+#endif
#if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER)
SQLITE_PRIVATE void sqlite3MaterializeView(Parse*, Table*, Expr*, ExprList*,Expr*,int);
@@ -19041,12 +22270,12 @@ SQLITE_PRIVATE void sqlite3CodeRowTriggerDirect(Parse *, Trigger *, Table *, i
SQLITE_PRIVATE void sqlite3DeleteTriggerStep(sqlite3*, TriggerStep*);
SQLITE_PRIVATE TriggerStep *sqlite3TriggerSelectStep(sqlite3*,Select*,
const char*,const char*);
-SQLITE_PRIVATE TriggerStep *sqlite3TriggerInsertStep(Parse*,Token*, IdList*,
+SQLITE_PRIVATE TriggerStep *sqlite3TriggerInsertStep(Parse*,SrcList*, IdList*,
Select*,u8,Upsert*,
const char*,const char*);
-SQLITE_PRIVATE TriggerStep *sqlite3TriggerUpdateStep(Parse*,Token*,ExprList*, Expr*, u8,
- const char*,const char*);
-SQLITE_PRIVATE TriggerStep *sqlite3TriggerDeleteStep(Parse*,Token*, Expr*,
+SQLITE_PRIVATE TriggerStep *sqlite3TriggerUpdateStep(Parse*,SrcList*,SrcList*,ExprList*,
+ Expr*, u8, const char*,const char*);
+SQLITE_PRIVATE TriggerStep *sqlite3TriggerDeleteStep(Parse*,SrcList*, Expr*,
const char*,const char*);
SQLITE_PRIVATE void sqlite3DeleteTrigger(sqlite3*, Trigger*);
SQLITE_PRIVATE void sqlite3UnlinkAndDeleteTrigger(sqlite3*,int,const char*);
@@ -19067,6 +22296,9 @@ SQLITE_PRIVATE u32 sqlite3TriggerColmask(Parse*,Trigger*,ExprList*,int,int,Tab
#endif
SQLITE_PRIVATE int sqlite3JoinType(Parse*, Token*, Token*, Token*);
+SQLITE_PRIVATE int sqlite3ColumnIndex(Table *pTab, const char *zCol);
+SQLITE_PRIVATE void sqlite3SrcItemColumnUsed(SrcItem*,int);
+SQLITE_PRIVATE void sqlite3SetJoinExpr(Expr*,int,u32);
SQLITE_PRIVATE void sqlite3CreateForeignKey(Parse*, ExprList*, Token*, ExprList*, int);
SQLITE_PRIVATE void sqlite3DeferForeignKey(Parse*, int);
#ifndef SQLITE_OMIT_AUTHORIZATION
@@ -19081,32 +22313,32 @@ 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 sqlite3AtoF(const char *z, double*, int, u8);
+
+SQLITE_PRIVATE int sqlite3RealSameAsInt(double,sqlite3_int64);
+SQLITE_PRIVATE i64 sqlite3RealToI64(double);
+SQLITE_PRIVATE int sqlite3Int64ToText(i64,char*);
+SQLITE_PRIVATE int sqlite3AtoF(const char *z, double*);
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);
+SQLITE_PRIVATE int sqlite3Utf16ByteLen(const void *pData, int nByte, int nChar);
#endif
SQLITE_PRIVATE int sqlite3Utf8CharLen(const char *pData, int nByte);
SQLITE_PRIVATE u32 sqlite3Utf8Read(const u8**);
+SQLITE_PRIVATE int sqlite3Utf8ReadLimited(const u8*, int, u32*);
SQLITE_PRIVATE LogEst sqlite3LogEst(u64);
SQLITE_PRIVATE LogEst sqlite3LogEstAdd(LogEst,LogEst);
-#ifndef SQLITE_OMIT_VIRTUALTABLE
SQLITE_PRIVATE LogEst sqlite3LogEstFromDouble(double);
-#endif
-#if defined(SQLITE_ENABLE_STMT_SCANSTATUS) || \
- defined(SQLITE_ENABLE_STAT3_OR_STAT4) || \
- defined(SQLITE_EXPLAIN_ESTIMATED_ROWS)
SQLITE_PRIVATE u64 sqlite3LogEstToInt(LogEst);
-#endif
SQLITE_PRIVATE VList *sqlite3VListAdd(sqlite3*,VList*,const char*,int,int);
SQLITE_PRIVATE const char *sqlite3VListNumToName(VList*,int);
SQLITE_PRIVATE int sqlite3VListNameToNum(VList*,const char*,int);
@@ -19128,6 +22360,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)))
@@ -19136,17 +22370,22 @@ SQLITE_PRIVATE int sqlite3VarintLen(u64 v);
SQLITE_PRIVATE const char *sqlite3IndexAffinityStr(sqlite3*, Index*);
+SQLITE_PRIVATE char *sqlite3TableAffinityStr(sqlite3*,const Table*);
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 sqlite3TableColumnAffinity(Table*,int);
-SQLITE_PRIVATE char sqlite3ExprAffinity(Expr *pExpr);
+SQLITE_PRIVATE char sqlite3CompareAffinity(const Expr *pExpr, char aff2);
+SQLITE_PRIVATE int sqlite3IndexAffinityOk(const Expr *pExpr, char idx_affinity);
+SQLITE_PRIVATE char sqlite3TableColumnAffinity(const Table*,int);
+SQLITE_PRIVATE char sqlite3ExprAffinity(const Expr *pExpr);
+SQLITE_PRIVATE int sqlite3ExprDataType(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);
+#if !defined(SQLITE_OMIT_BLOB_LITERAL)
SQLITE_PRIVATE void *sqlite3HexToBlob(sqlite3*, const char *z, int n);
+#endif
SQLITE_PRIVATE u8 sqlite3HexToInt(int h);
SQLITE_PRIVATE int sqlite3TwoPartName(Parse *, Token *, Token *, Token **);
@@ -19154,8 +22393,11 @@ 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);
+SQLITE_PRIVATE int sqlite3IsMemdb(const sqlite3_vfs*);
+#else
+# define sqlite3IsMemdb(X) 0
#endif
SQLITE_PRIVATE const char *sqlite3ErrStr(int);
@@ -19163,16 +22405,18 @@ 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 Expr *sqlite3ExprAddCollateToken(Parse *pParse, Expr*, const Token*, int);
-SQLITE_PRIVATE Expr *sqlite3ExprAddCollateString(Parse*,Expr*,const char*);
+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(const Parse *pParse, Expr*, const Token*, int);
+SQLITE_PRIVATE Expr *sqlite3ExprAddCollateString(const Parse*,Expr*,const char*);
SQLITE_PRIVATE Expr *sqlite3ExprSkipCollate(Expr*);
+SQLITE_PRIVATE Expr *sqlite3ExprSkipCollateAndLikely(Expr*);
SQLITE_PRIVATE int sqlite3CheckCollSeq(Parse *, CollSeq *);
SQLITE_PRIVATE int sqlite3WritableSchema(sqlite3*);
-SQLITE_PRIVATE int sqlite3CheckObjectName(Parse *, const char *);
-SQLITE_PRIVATE void sqlite3VdbeSetChanges(sqlite3 *, int);
+SQLITE_PRIVATE int sqlite3CheckObjectName(Parse*, const char*,const char*,const char*);
+SQLITE_PRIVATE void sqlite3VdbeSetChanges(sqlite3 *, i64);
SQLITE_PRIVATE int sqlite3AddInt64(i64*,i64);
SQLITE_PRIVATE int sqlite3SubInt64(i64*,i64);
SQLITE_PRIVATE int sqlite3MulInt64(i64*,i64);
@@ -19185,45 +22429,74 @@ SQLITE_PRIVATE void sqlite3FileSuffix3(const char*, char*);
SQLITE_PRIVATE u8 sqlite3GetBoolean(const char *z,u8);
SQLITE_PRIVATE const void *sqlite3ValueText(sqlite3_value*, u8);
+SQLITE_PRIVATE int sqlite3ValueIsOfClass(const sqlite3_value*, void(*)(void*));
SQLITE_PRIVATE int sqlite3ValueBytes(sqlite3_value*, u8);
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);
#endif
-SQLITE_PRIVATE int sqlite3ValueFromExpr(sqlite3 *, Expr *, u8, u8, sqlite3_value **);
+SQLITE_PRIVATE int sqlite3ValueFromExpr(sqlite3 *, const Expr *, u8, u8, sqlite3_value **);
SQLITE_PRIVATE void sqlite3ValueApplyAffinity(sqlite3_value *, u8, u8);
#ifndef SQLITE_AMALGAMATION
SQLITE_PRIVATE const unsigned char sqlite3OpcodeProperty[];
SQLITE_PRIVATE const char sqlite3StrBINARY[];
+SQLITE_PRIVATE const unsigned char sqlite3StdTypeLen[];
+SQLITE_PRIVATE const char sqlite3StdTypeAffinity[];
+SQLITE_PRIVATE const char *sqlite3StdType[];
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*);
SQLITE_PRIVATE void sqlite3AlterRenameColumn(Parse*, SrcList*, Token*, Token*);
-SQLITE_PRIVATE int sqlite3GetToken(const unsigned char *, int *);
+SQLITE_PRIVATE void sqlite3AlterDropConstraint(Parse*,SrcList*,Token*,Token*);
+SQLITE_PRIVATE void sqlite3AlterAddConstraint(
+ Parse *pParse, /* Parse context */
+ SrcList *pSrc, /* Table to add constraint to */
+ Token *pFirst, /* First token of new constraint */
+ Token *pName, /* Name of new constraint. NULL if name omitted. */
+ const char *zExpr, /* Text of CHECK expression */
+ int nExpr, /* Size of pExpr in bytes */
+ Expr *pExpr /* The parsed CHECK expression */
+);
+SQLITE_PRIVATE void sqlite3AlterSetNotNull(Parse*, SrcList*, Token*, Token*);
+SQLITE_PRIVATE i64 sqlite3GetToken(const unsigned char *, int *);
SQLITE_PRIVATE void sqlite3NestedParse(Parse*, const char*, ...);
SQLITE_PRIVATE void sqlite3ExpirePreparedStatements(sqlite3*, int);
-SQLITE_PRIVATE void sqlite3CodeRhsOfIN(Parse*, Expr*, int);
+SQLITE_PRIVATE void sqlite3CodeRhsOfIN(Parse*, Expr*, int, 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*,
+ int*
+);
+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*);
@@ -19232,14 +22505,15 @@ SQLITE_PRIVATE int sqlite3ResolveOrderGroupBy(Parse*, Select*, ExprList*, const
SQLITE_PRIVATE void sqlite3ColumnDefault(Vdbe *, Table *, int, int);
SQLITE_PRIVATE void sqlite3AlterFinishAddColumn(Parse *, Token *);
SQLITE_PRIVATE void sqlite3AlterBeginAddColumn(Parse *, SrcList *);
-SQLITE_PRIVATE void *sqlite3RenameTokenMap(Parse*, void*, Token*);
-SQLITE_PRIVATE void sqlite3RenameTokenRemap(Parse*, void *pTo, void *pFrom);
+SQLITE_PRIVATE void sqlite3AlterDropColumn(Parse*, SrcList*, const Token*);
+SQLITE_PRIVATE const void *sqlite3RenameTokenMap(Parse*, const void*, const Token*);
+SQLITE_PRIVATE void sqlite3RenameTokenRemap(Parse*, const void *pTo, const void *pFrom);
SQLITE_PRIVATE void sqlite3RenameExprUnmap(Parse*, Expr*);
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);
@@ -19255,28 +22529,41 @@ 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*);
-SQLITE_PRIVATE void sqlite3OomFault(sqlite3*);
+SQLITE_PRIVATE void *sqlite3OomFault(sqlite3*);
SQLITE_PRIVATE void sqlite3OomClear(sqlite3*);
SQLITE_PRIVATE int sqlite3ApiExit(sqlite3 *db, int);
SQLITE_PRIVATE int sqlite3OpenTempDatabase(Parse *);
+SQLITE_PRIVATE char *sqlite3RCStrRef(char*);
+SQLITE_PRIVATE void sqlite3RCStrUnref(void*);
+SQLITE_PRIVATE char *sqlite3RCStrNew(u64);
+SQLITE_PRIVATE char *sqlite3RCStrResize(char*,u64);
+
SQLITE_PRIVATE void sqlite3StrAccumInit(StrAccum*, sqlite3*, char*, int, int);
+SQLITE_PRIVATE int sqlite3StrAccumEnlarge(StrAccum*, i64);
+SQLITE_PRIVATE int sqlite3StrAccumEnlargeIfNeeded(StrAccum*, i64);
SQLITE_PRIVATE char *sqlite3StrAccumFinish(StrAccum*);
+SQLITE_PRIVATE void sqlite3StrAccumSetError(StrAccum*, u8);
+SQLITE_PRIVATE void sqlite3ResultStrAccum(sqlite3_context*,StrAccum*);
SQLITE_PRIVATE void sqlite3SelectDestInit(SelectDest*,int,int);
SQLITE_PRIVATE Expr *sqlite3CreateColumnExpr(sqlite3 *, SrcList *, int, int);
+SQLITE_PRIVATE void sqlite3RecordErrorByteOffset(sqlite3*,const char*);
+SQLITE_PRIVATE void sqlite3RecordErrorOffsetOfExpr(sqlite3*,const Expr*);
SQLITE_PRIVATE void sqlite3BackupRestart(sqlite3_backup *);
SQLITE_PRIVATE void sqlite3BackupUpdate(sqlite3_backup *, Pgno, const u8 *);
@@ -19287,8 +22574,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**);
@@ -19318,7 +22604,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
@@ -19328,13 +22614,14 @@ SQLITE_PRIVATE int sqlite3Utf8To8(unsigned char*);
#endif
#ifdef SQLITE_OMIT_VIRTUALTABLE
-# define sqlite3VtabClear(Y)
+# define sqlite3VtabClear(D,T)
# define sqlite3VtabSync(X,Y) SQLITE_OK
# define sqlite3VtabRollback(X)
# define sqlite3VtabCommit(X)
# 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)
@@ -19346,6 +22633,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*);
@@ -19359,6 +22647,16 @@ 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*);
+SQLITE_PRIVATE void sqlite3MarkAllShadowTablesOf(sqlite3*, Table*);
+#else
+# define sqlite3ShadowTableName(A,B) 0
+# define sqlite3IsShadowTableOf(A,B,C) 0
+# define sqlite3MarkAllShadowTablesOf(A,B)
+#endif
SQLITE_PRIVATE int sqlite3VtabEponymousTableInit(Parse*,Module*);
SQLITE_PRIVATE void sqlite3VtabEponymousTableClear(sqlite3*,Module*);
SQLITE_PRIVATE void sqlite3VtabMakeWritable(Parse*,Table*);
@@ -19370,17 +22668,22 @@ SQLITE_PRIVATE int sqlite3VtabCallCreate(sqlite3*, int, const char *, char **);
SQLITE_PRIVATE int sqlite3VtabCallConnect(Parse*, Table*);
SQLITE_PRIVATE int sqlite3VtabCallDestroy(sqlite3*, int, const char *);
SQLITE_PRIVATE int sqlite3VtabBegin(sqlite3 *, VTable *);
+
SQLITE_PRIVATE FuncDef *sqlite3VtabOverloadFunction(sqlite3 *,FuncDef*, int nArg, Expr*);
+SQLITE_PRIVATE void sqlite3VtabUsesAllSchemas(Parse*);
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 sqlite3ParseObjectInit(Parse*,sqlite3*);
+SQLITE_PRIVATE void sqlite3ParseObjectReset(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
@@ -19388,23 +22691,33 @@ 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 void sqlite3WithDeleteGeneric(sqlite3*,void*);
+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) ((void*)0)
#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 int sqlite3UpsertAnalyzeTarget(Parse*,SrcList*,Upsert*,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
@@ -19422,6 +22735,7 @@ SQLITE_PRIVATE void sqlite3FkActions(Parse*, Table*, ExprList*, int, int*, int
SQLITE_PRIVATE int sqlite3FkRequired(Parse*, Table*, int*, int);
SQLITE_PRIVATE u32 sqlite3FkOldmask(Parse*, Table*);
SQLITE_PRIVATE FKey *sqlite3FkReferences(Table *);
+SQLITE_PRIVATE void sqlite3FkClearTriggerCache(sqlite3*,int);
#else
#define sqlite3FkActions(a,b,c,d,e,f)
#define sqlite3FkCheck(a,b,c,d,e,f)
@@ -19429,6 +22743,7 @@ SQLITE_PRIVATE FKey *sqlite3FkReferences(Table *);
#define sqlite3FkOldmask(a,b) 0
#define sqlite3FkRequired(a,b,c,d) 0
#define sqlite3FkReferences(a) 0
+ #define sqlite3FkClearTriggerCache(a,b)
#endif
#ifndef SQLITE_OMIT_FOREIGN_KEY
SQLITE_PRIVATE void sqlite3FkDelete(sqlite3 *, Table*);
@@ -19486,12 +22801,13 @@ SQLITE_PRIVATE void sqlite3MemJournalOpen(sqlite3_file *);
SQLITE_PRIVATE void sqlite3ExprSetHeightAndFlags(Parse *pParse, Expr *p);
#if SQLITE_MAX_EXPR_DEPTH>0
-SQLITE_PRIVATE int sqlite3SelectExprHeight(Select *);
+SQLITE_PRIVATE int sqlite3SelectExprHeight(const Select *);
SQLITE_PRIVATE int sqlite3ExprCheckHeight(Parse*, int);
#else
#define sqlite3SelectExprHeight(x) 0
#define sqlite3ExprCheckHeight(x,y)
#endif
+SQLITE_PRIVATE void sqlite3ExprSetErrorOffset(Expr*,int);
SQLITE_PRIVATE u32 sqlite3Get4byte(const u8*);
SQLITE_PRIVATE void sqlite3Put4byte(u8*, u32);
@@ -19557,8 +22873,8 @@ SQLITE_API SQLITE_EXTERN void (SQLITE_CDECL *sqlite3IoTrace)(const char*,...);
*/
#ifdef SQLITE_MEMDEBUG
SQLITE_PRIVATE void sqlite3MemdebugSetType(void*,u8);
-SQLITE_PRIVATE int sqlite3MemdebugHasType(void*,u8);
-SQLITE_PRIVATE int sqlite3MemdebugNoType(void*,u8);
+SQLITE_PRIVATE int sqlite3MemdebugHasType(const void*,u8);
+SQLITE_PRIVATE int sqlite3MemdebugNoType(const void*,u8);
#else
# define sqlite3MemdebugSetType(X,Y) /* no-op */
# define sqlite3MemdebugHasType(X,Y) 1
@@ -19583,19 +22899,954 @@ SQLITE_PRIVATE int sqlite3DbpageRegister(sqlite3*);
SQLITE_PRIVATE int sqlite3DbstatRegister(sqlite3*);
#endif
-SQLITE_PRIVATE int sqlite3ExprVectorSize(Expr *pExpr);
-SQLITE_PRIVATE int sqlite3ExprIsVector(Expr *pExpr);
+SQLITE_PRIVATE int sqlite3ExprVectorSize(const Expr *pExpr);
+SQLITE_PRIVATE int sqlite3ExprIsVector(const Expr *pExpr);
SQLITE_PRIVATE Expr *sqlite3VectorFieldSubexpr(Expr*, int);
-SQLITE_PRIVATE Expr *sqlite3ExprForVectorField(Parse*,Expr*,int);
+SQLITE_PRIVATE Expr *sqlite3ExprForVectorField(Parse*,Expr*,int,int);
SQLITE_PRIVATE void sqlite3VectorErrorMsg(Parse*, Expr*);
#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
SQLITE_PRIVATE const char **sqlite3CompileOptions(int *pnOpt);
#endif
+#if SQLITE_OS_UNIX && defined(SQLITE_OS_KV_OPTIONAL)
+SQLITE_PRIVATE int sqlite3KvvfsInit(void);
+#endif
+
+#if defined(VDBE_PROFILE) \
+ || defined(SQLITE_PERFORMANCE_TRACE) \
+ || defined(SQLITE_ENABLE_STMT_SCANSTATUS)
+SQLITE_PRIVATE sqlite3_uint64 sqlite3Hwtime(void);
+#endif
+
+#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
+# define IS_STMT_SCANSTATUS(db) (db->flags & SQLITE_StmtScanStatus)
+#else
+# define IS_STMT_SCANSTATUS(db) 0
+#endif
+
#endif /* SQLITEINT_H */
/************** End of sqliteInt.h *******************************************/
+/************** Begin file os_common.h ***************************************/
+/*
+** 2004 May 22
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+******************************************************************************
+**
+** This file contains macros and a little bit of code that is common to
+** all of the platform-specific files (os_*.c) and is #included into those
+** files.
+**
+** This file should be #included by the os_*.c files only. It is not a
+** general purpose header file.
+*/
+#ifndef _OS_COMMON_H_
+#define _OS_COMMON_H_
+
+/*
+** At least two bugs have slipped in because we changed the MEMORY_DEBUG
+** macro to SQLITE_DEBUG and some older makefiles have not yet made the
+** switch. The following code should catch this problem at compile-time.
+*/
+#ifdef MEMORY_DEBUG
+# error "The MEMORY_DEBUG macro is obsolete. Use SQLITE_DEBUG instead."
+#endif
+
+/*
+** Macros for performance tracing. Normally turned off. Only works
+** on i486 hardware.
+*/
+#ifdef SQLITE_PERFORMANCE_TRACE
+
+static sqlite_uint64 g_start;
+static sqlite_uint64 g_elapsed;
+#define TIMER_START g_start=sqlite3Hwtime()
+#define TIMER_END g_elapsed=sqlite3Hwtime()-g_start
+#define TIMER_ELAPSED g_elapsed
+#else
+#define TIMER_START
+#define TIMER_END
+#define TIMER_ELAPSED ((sqlite_uint64)0)
+#endif
+
+/*
+** If we compile with the SQLITE_TEST macro set, then the following block
+** of code will give us the ability to simulate a disk I/O error. This
+** is used for testing the I/O recovery logic.
+*/
+#if defined(SQLITE_TEST)
+SQLITE_API extern int sqlite3_io_error_hit;
+SQLITE_API extern int sqlite3_io_error_hardhit;
+SQLITE_API extern int sqlite3_io_error_pending;
+SQLITE_API extern int sqlite3_io_error_persist;
+SQLITE_API extern int sqlite3_io_error_benign;
+SQLITE_API extern int sqlite3_diskfull_pending;
+SQLITE_API extern int sqlite3_diskfull;
+#define SimulateIOErrorBenign(X) sqlite3_io_error_benign=(X)
+#define SimulateIOError(CODE) \
+ if( (sqlite3_io_error_persist && sqlite3_io_error_hit) \
+ || sqlite3_io_error_pending-- == 1 ) \
+ { local_ioerr(); CODE; }
+static void local_ioerr(){
+ IOTRACE(("IOERR\n"));
+ sqlite3_io_error_hit++;
+ if( !sqlite3_io_error_benign ) sqlite3_io_error_hardhit++;
+}
+#define SimulateDiskfullError(CODE) \
+ if( sqlite3_diskfull_pending ){ \
+ if( sqlite3_diskfull_pending == 1 ){ \
+ local_ioerr(); \
+ sqlite3_diskfull = 1; \
+ sqlite3_io_error_hit = 1; \
+ CODE; \
+ }else{ \
+ sqlite3_diskfull_pending--; \
+ } \
+ }
+#else
+#define SimulateIOErrorBenign(X)
+#define SimulateIOError(A)
+#define SimulateDiskfullError(A)
+#endif /* defined(SQLITE_TEST) */
+
+/*
+** When testing, keep a count of the number of open files.
+*/
+#if defined(SQLITE_TEST)
+SQLITE_API extern int sqlite3_open_file_count;
+#define OpenCounter(X) sqlite3_open_file_count+=(X)
+#else
+#define OpenCounter(X)
+#endif /* defined(SQLITE_TEST) */
+
+#endif /* !defined(_OS_COMMON_H_) */
+
+/************** End of os_common.h *******************************************/
+/************** Begin file ctime.c *******************************************/
+/* DO NOT EDIT!
+** This file is automatically generated by the script in the canonical
+** SQLite source tree at tool/mkctimec.tcl.
+**
+** To modify this header, edit any of the various lists in that script
+** which specify categories of generated conditionals in this file.
+*/
+
+/*
+** 2010 February 23
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+**
+** This file implements routines used to report what compile-time options
+** SQLite was built with.
+*/
+#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS /* IMP: R-16824-07538 */
+
+/*
+** Include the configuration header output by 'configure' if we're using the
+** autoconf-based build
+*/
+#if defined(_HAVE_SQLITE_CONFIG_H) && !defined(SQLITECONFIG_H)
+/* #include "sqlite_cfg.h" */
+#define SQLITECONFIG_H 1
+#endif
+
+/* These macros are provided to "stringify" the value of the define
+** for those options in which the value is meaningful. */
+#define CTIMEOPT_VAL_(opt) #opt
+#define CTIMEOPT_VAL(opt) CTIMEOPT_VAL_(opt)
+
+/* Like CTIMEOPT_VAL, but especially for SQLITE_DEFAULT_LOOKASIDE. This
+** option requires a separate macro because legal values contain a single
+** comma. e.g. (-DSQLITE_DEFAULT_LOOKASIDE="100,100") */
+#define CTIMEOPT_VAL2_(opt1,opt2) #opt1 "," #opt2
+#define CTIMEOPT_VAL2(opt) CTIMEOPT_VAL2_(opt)
+/* #include "sqliteInt.h" */
+
+/*
+** An array of names of all compile-time options. This array should
+** be sorted A-Z.
+**
+** This array looks large, but in a typical installation actually uses
+** only a handful of compile-time options, so most times this array is usually
+** rather short and uses little memory space.
+*/
+static const char * const sqlite3azCompileOpt[] = {
+
+#ifdef SQLITE_32BIT_ROWID
+ "32BIT_ROWID",
+#endif
+#ifdef SQLITE_4_BYTE_ALIGNED_MALLOC
+ "4_BYTE_ALIGNED_MALLOC",
+#endif
+#ifdef SQLITE_ALLOW_COVERING_INDEX_SCAN
+# if SQLITE_ALLOW_COVERING_INDEX_SCAN != 1
+ "ALLOW_COVERING_INDEX_SCAN=" CTIMEOPT_VAL(SQLITE_ALLOW_COVERING_INDEX_SCAN),
+# endif
+#endif
+#ifdef SQLITE_ALLOW_ROWID_IN_VIEW
+ "ALLOW_ROWID_IN_VIEW",
+#endif
+#ifdef SQLITE_ALLOW_URI_AUTHORITY
+ "ALLOW_URI_AUTHORITY",
+#endif
+#ifdef SQLITE_ATOMIC_INTRINSICS
+ "ATOMIC_INTRINSICS=" CTIMEOPT_VAL(SQLITE_ATOMIC_INTRINSICS),
+#endif
+#ifdef SQLITE_BITMASK_TYPE
+ "BITMASK_TYPE=" CTIMEOPT_VAL(SQLITE_BITMASK_TYPE),
+#endif
+#ifdef SQLITE_BUG_COMPATIBLE_20160819
+ "BUG_COMPATIBLE_20160819",
+#endif
+#ifdef SQLITE_BUG_COMPATIBLE_20250510
+ "BUG_COMPATIBLE_20250510",
+#endif
+#ifdef SQLITE_CASE_SENSITIVE_LIKE
+ "CASE_SENSITIVE_LIKE",
+#endif
+#ifdef SQLITE_CHECK_PAGES
+ "CHECK_PAGES",
+#endif
+#if defined(__clang__) && defined(__clang_major__)
+ "COMPILER=clang-" CTIMEOPT_VAL(__clang_major__) "."
+ CTIMEOPT_VAL(__clang_minor__) "."
+ CTIMEOPT_VAL(__clang_patchlevel__),
+#elif defined(_MSC_VER)
+ "COMPILER=msvc-" CTIMEOPT_VAL(_MSC_VER),
+#elif defined(__GNUC__) && defined(__VERSION__)
+ "COMPILER=gcc-" __VERSION__,
+#endif
+#ifdef SQLITE_COVERAGE_TEST
+ "COVERAGE_TEST",
+#endif
+#ifdef SQLITE_DEBUG
+ "DEBUG",
+#endif
+#ifdef SQLITE_DEFAULT_AUTOMATIC_INDEX
+ "DEFAULT_AUTOMATIC_INDEX",
+#endif
+#ifdef SQLITE_DEFAULT_AUTOVACUUM
+ "DEFAULT_AUTOVACUUM",
+#endif
+#ifdef SQLITE_DEFAULT_CACHE_SIZE
+ "DEFAULT_CACHE_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_CACHE_SIZE),
+#endif
+#ifdef SQLITE_DEFAULT_CKPTFULLFSYNC
+ "DEFAULT_CKPTFULLFSYNC",
+#endif
+#ifdef SQLITE_DEFAULT_FILE_FORMAT
+ "DEFAULT_FILE_FORMAT=" CTIMEOPT_VAL(SQLITE_DEFAULT_FILE_FORMAT),
+#endif
+#ifdef SQLITE_DEFAULT_FILE_PERMISSIONS
+ "DEFAULT_FILE_PERMISSIONS=" CTIMEOPT_VAL(SQLITE_DEFAULT_FILE_PERMISSIONS),
+#endif
+#ifdef SQLITE_DEFAULT_FOREIGN_KEYS
+ "DEFAULT_FOREIGN_KEYS",
+#endif
+#ifdef SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT
+ "DEFAULT_JOURNAL_SIZE_LIMIT=" CTIMEOPT_VAL(SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT),
+#endif
+#ifdef SQLITE_DEFAULT_LOCKING_MODE
+ "DEFAULT_LOCKING_MODE=" CTIMEOPT_VAL(SQLITE_DEFAULT_LOCKING_MODE),
+#endif
+#ifdef SQLITE_DEFAULT_LOOKASIDE
+ "DEFAULT_LOOKASIDE=" CTIMEOPT_VAL2(SQLITE_DEFAULT_LOOKASIDE),
+#endif
+#ifdef SQLITE_DEFAULT_MEMSTATUS
+# if SQLITE_DEFAULT_MEMSTATUS != 1
+ "DEFAULT_MEMSTATUS=" CTIMEOPT_VAL(SQLITE_DEFAULT_MEMSTATUS),
+# endif
+#endif
+#ifdef SQLITE_DEFAULT_MMAP_SIZE
+ "DEFAULT_MMAP_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_MMAP_SIZE),
+#endif
+#ifdef SQLITE_DEFAULT_PAGE_SIZE
+ "DEFAULT_PAGE_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_PAGE_SIZE),
+#endif
+#ifdef SQLITE_DEFAULT_PCACHE_INITSZ
+ "DEFAULT_PCACHE_INITSZ=" CTIMEOPT_VAL(SQLITE_DEFAULT_PCACHE_INITSZ),
+#endif
+#ifdef SQLITE_DEFAULT_PROXYDIR_PERMISSIONS
+ "DEFAULT_PROXYDIR_PERMISSIONS=" CTIMEOPT_VAL(SQLITE_DEFAULT_PROXYDIR_PERMISSIONS),
+#endif
+#ifdef SQLITE_DEFAULT_RECURSIVE_TRIGGERS
+ "DEFAULT_RECURSIVE_TRIGGERS",
+#endif
+#ifdef SQLITE_DEFAULT_ROWEST
+ "DEFAULT_ROWEST=" CTIMEOPT_VAL(SQLITE_DEFAULT_ROWEST),
+#endif
+#ifdef SQLITE_DEFAULT_SECTOR_SIZE
+ "DEFAULT_SECTOR_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_SECTOR_SIZE),
+#endif
+#ifdef SQLITE_DEFAULT_SYNCHRONOUS
+ "DEFAULT_SYNCHRONOUS=" CTIMEOPT_VAL(SQLITE_DEFAULT_SYNCHRONOUS),
+#endif
+#ifdef SQLITE_DEFAULT_WAL_AUTOCHECKPOINT
+ "DEFAULT_WAL_AUTOCHECKPOINT=" CTIMEOPT_VAL(SQLITE_DEFAULT_WAL_AUTOCHECKPOINT),
+#endif
+#ifdef SQLITE_DEFAULT_WAL_SYNCHRONOUS
+ "DEFAULT_WAL_SYNCHRONOUS=" CTIMEOPT_VAL(SQLITE_DEFAULT_WAL_SYNCHRONOUS),
+#endif
+#ifdef SQLITE_DEFAULT_WORKER_THREADS
+ "DEFAULT_WORKER_THREADS=" CTIMEOPT_VAL(SQLITE_DEFAULT_WORKER_THREADS),
+#endif
+#ifdef SQLITE_DIRECT_OVERFLOW_READ
+ "DIRECT_OVERFLOW_READ",
+#endif
+#ifdef SQLITE_DISABLE_DIRSYNC
+ "DISABLE_DIRSYNC",
+#endif
+#ifdef SQLITE_DISABLE_FTS3_UNICODE
+ "DISABLE_FTS3_UNICODE",
+#endif
+#ifdef SQLITE_DISABLE_FTS4_DEFERRED
+ "DISABLE_FTS4_DEFERRED",
+#endif
+#ifdef SQLITE_DISABLE_INTRINSIC
+ "DISABLE_INTRINSIC",
+#endif
+#ifdef SQLITE_DISABLE_LFS
+ "DISABLE_LFS",
+#endif
+#ifdef SQLITE_DISABLE_PAGECACHE_OVERFLOW_STATS
+ "DISABLE_PAGECACHE_OVERFLOW_STATS",
+#endif
+#ifdef SQLITE_DISABLE_SKIPAHEAD_DISTINCT
+ "DISABLE_SKIPAHEAD_DISTINCT",
+#endif
+#ifdef SQLITE_DQS
+ "DQS=" CTIMEOPT_VAL(SQLITE_DQS),
+#endif
+#ifdef SQLITE_ENABLE_8_3_NAMES
+ "ENABLE_8_3_NAMES=" CTIMEOPT_VAL(SQLITE_ENABLE_8_3_NAMES),
+#endif
+#ifdef SQLITE_ENABLE_API_ARMOR
+ "ENABLE_API_ARMOR",
+#endif
+#ifdef SQLITE_ENABLE_ATOMIC_WRITE
+ "ENABLE_ATOMIC_WRITE",
+#endif
+#ifdef SQLITE_ENABLE_BATCH_ATOMIC_WRITE
+ "ENABLE_BATCH_ATOMIC_WRITE",
+#endif
+#ifdef SQLITE_ENABLE_BYTECODE_VTAB
+ "ENABLE_BYTECODE_VTAB",
+#endif
+#ifdef SQLITE_ENABLE_CARRAY
+ "ENABLE_CARRAY",
+#endif
+#ifdef SQLITE_ENABLE_CEROD
+ "ENABLE_CEROD=" CTIMEOPT_VAL(SQLITE_ENABLE_CEROD),
+#endif
+#ifdef SQLITE_ENABLE_COLUMN_METADATA
+ "ENABLE_COLUMN_METADATA",
+#endif
+#ifdef SQLITE_ENABLE_COLUMN_USED_MASK
+ "ENABLE_COLUMN_USED_MASK",
+#endif
+#ifdef SQLITE_ENABLE_COSTMULT
+ "ENABLE_COSTMULT",
+#endif
+#ifdef SQLITE_ENABLE_CURSOR_HINTS
+ "ENABLE_CURSOR_HINTS",
+#endif
+#ifdef SQLITE_ENABLE_DBPAGE_VTAB
+ "ENABLE_DBPAGE_VTAB",
+#endif
+#ifdef SQLITE_ENABLE_DBSTAT_VTAB
+ "ENABLE_DBSTAT_VTAB",
+#endif
+#ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT
+ "ENABLE_EXPENSIVE_ASSERT",
+#endif
+#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
+ "ENABLE_EXPLAIN_COMMENTS",
+#endif
+#ifdef SQLITE_ENABLE_FTS3
+ "ENABLE_FTS3",
+#endif
+#ifdef SQLITE_ENABLE_FTS3_PARENTHESIS
+ "ENABLE_FTS3_PARENTHESIS",
+#endif
+#ifdef SQLITE_ENABLE_FTS3_TOKENIZER
+ "ENABLE_FTS3_TOKENIZER",
+#endif
+#ifdef SQLITE_ENABLE_FTS4
+ "ENABLE_FTS4",
+#endif
+#ifdef SQLITE_ENABLE_FTS5
+ "ENABLE_FTS5",
+#endif
+#ifdef SQLITE_ENABLE_GEOPOLY
+ "ENABLE_GEOPOLY",
+#endif
+#ifdef SQLITE_ENABLE_HIDDEN_COLUMNS
+ "ENABLE_HIDDEN_COLUMNS",
+#endif
+#ifdef SQLITE_ENABLE_ICU
+ "ENABLE_ICU",
+#endif
+#ifdef SQLITE_ENABLE_IOTRACE
+ "ENABLE_IOTRACE",
+#endif
+#ifdef SQLITE_ENABLE_LOAD_EXTENSION
+ "ENABLE_LOAD_EXTENSION",
+#endif
+#ifdef SQLITE_ENABLE_LOCKING_STYLE
+ "ENABLE_LOCKING_STYLE=" CTIMEOPT_VAL(SQLITE_ENABLE_LOCKING_STYLE),
+#endif
+#ifdef SQLITE_ENABLE_MATH_FUNCTIONS
+ "ENABLE_MATH_FUNCTIONS",
+#endif
+#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
+ "ENABLE_MEMORY_MANAGEMENT",
+#endif
+#ifdef SQLITE_ENABLE_MEMSYS3
+ "ENABLE_MEMSYS3",
+#endif
+#ifdef SQLITE_ENABLE_MEMSYS5
+ "ENABLE_MEMSYS5",
+#endif
+#ifdef SQLITE_ENABLE_MULTIPLEX
+ "ENABLE_MULTIPLEX",
+#endif
+#ifdef SQLITE_ENABLE_NORMALIZE
+ "ENABLE_NORMALIZE",
+#endif
+#ifdef SQLITE_ENABLE_NULL_TRIM
+ "ENABLE_NULL_TRIM",
+#endif
+#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC
+ "ENABLE_OFFSET_SQL_FUNC",
+#endif
+#ifdef SQLITE_ENABLE_ORDERED_SET_AGGREGATES
+ "ENABLE_ORDERED_SET_AGGREGATES",
+#endif
+#ifdef SQLITE_ENABLE_OVERSIZE_CELL_CHECK
+ "ENABLE_OVERSIZE_CELL_CHECK",
+#endif
+#ifdef SQLITE_ENABLE_PERCENTILE
+ "ENABLE_PERCENTILE",
+#endif
+#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
+ "ENABLE_PREUPDATE_HOOK",
+#endif
+#ifdef SQLITE_ENABLE_QPSG
+ "ENABLE_QPSG",
+#endif
+#ifdef SQLITE_ENABLE_RBU
+ "ENABLE_RBU",
+#endif
+#ifdef SQLITE_ENABLE_RTREE
+ "ENABLE_RTREE",
+#endif
+#ifdef SQLITE_ENABLE_SESSION
+ "ENABLE_SESSION",
+#endif
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+ "ENABLE_SETLK_TIMEOUT",
+#endif
+#ifdef SQLITE_ENABLE_SNAPSHOT
+ "ENABLE_SNAPSHOT",
+#endif
+#ifdef SQLITE_ENABLE_SORTER_REFERENCES
+ "ENABLE_SORTER_REFERENCES",
+#endif
+#ifdef SQLITE_ENABLE_SQLLOG
+ "ENABLE_SQLLOG",
+#endif
+#ifdef SQLITE_ENABLE_STAT4
+ "ENABLE_STAT4",
+#endif
+#ifdef SQLITE_ENABLE_STMTVTAB
+ "ENABLE_STMTVTAB",
+#endif
+#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
+ "ENABLE_STMT_SCANSTATUS",
+#endif
+#ifdef SQLITE_ENABLE_TREETRACE
+ "ENABLE_TREETRACE",
+#endif
+#ifdef SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
+ "ENABLE_UNKNOWN_SQL_FUNCTION",
+#endif
+#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
+ "ENABLE_UNLOCK_NOTIFY",
+#endif
+#ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT
+ "ENABLE_UPDATE_DELETE_LIMIT",
+#endif
+#ifdef SQLITE_ENABLE_URI_00_ERROR
+ "ENABLE_URI_00_ERROR",
+#endif
+#ifdef SQLITE_ENABLE_VFSTRACE
+ "ENABLE_VFSTRACE",
+#endif
+#ifdef SQLITE_ENABLE_WHERETRACE
+ "ENABLE_WHERETRACE",
+#endif
+#ifdef SQLITE_ENABLE_ZIPVFS
+ "ENABLE_ZIPVFS",
+#endif
+#ifdef SQLITE_EXPLAIN_ESTIMATED_ROWS
+ "EXPLAIN_ESTIMATED_ROWS",
+#endif
+#ifdef SQLITE_EXTRA_AUTOEXT
+ "EXTRA_AUTOEXT=" CTIMEOPT_VAL(SQLITE_EXTRA_AUTOEXT),
+#endif
+#ifdef SQLITE_EXTRA_IFNULLROW
+ "EXTRA_IFNULLROW",
+#endif
+#ifdef SQLITE_EXTRA_INIT
+ "EXTRA_INIT=" CTIMEOPT_VAL(SQLITE_EXTRA_INIT),
+#endif
+#ifdef SQLITE_EXTRA_INIT_MUTEXED
+ "EXTRA_INIT_MUTEXED=" CTIMEOPT_VAL(SQLITE_EXTRA_INIT_MUTEXED),
+#endif
+#ifdef SQLITE_EXTRA_SHUTDOWN
+ "EXTRA_SHUTDOWN=" CTIMEOPT_VAL(SQLITE_EXTRA_SHUTDOWN),
+#endif
+#ifdef SQLITE_FTS3_MAX_EXPR_DEPTH
+ "FTS3_MAX_EXPR_DEPTH=" CTIMEOPT_VAL(SQLITE_FTS3_MAX_EXPR_DEPTH),
+#endif
+#ifdef SQLITE_FTS5_ENABLE_TEST_MI
+ "FTS5_ENABLE_TEST_MI",
+#endif
+#ifdef SQLITE_FTS5_NO_WITHOUT_ROWID
+ "FTS5_NO_WITHOUT_ROWID",
+#endif
+#if HAVE_ISNAN || SQLITE_HAVE_ISNAN
+ "HAVE_ISNAN",
+#endif
+#ifdef SQLITE_HOMEGROWN_RECURSIVE_MUTEX
+# if SQLITE_HOMEGROWN_RECURSIVE_MUTEX != 1
+ "HOMEGROWN_RECURSIVE_MUTEX=" CTIMEOPT_VAL(SQLITE_HOMEGROWN_RECURSIVE_MUTEX),
+# endif
+#endif
+#ifdef SQLITE_IGNORE_AFP_LOCK_ERRORS
+ "IGNORE_AFP_LOCK_ERRORS",
+#endif
+#ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS
+ "IGNORE_FLOCK_LOCK_ERRORS",
+#endif
+#ifdef SQLITE_INLINE_MEMCPY
+ "INLINE_MEMCPY",
+#endif
+#ifdef SQLITE_INT64_TYPE
+ "INT64_TYPE",
+#endif
+#ifdef SQLITE_INTEGRITY_CHECK_ERROR_MAX
+ "INTEGRITY_CHECK_ERROR_MAX=" CTIMEOPT_VAL(SQLITE_INTEGRITY_CHECK_ERROR_MAX),
+#endif
+#ifdef SQLITE_LEGACY_JSON_VALID
+ "LEGACY_JSON_VALID",
+#endif
+#ifdef SQLITE_LIKE_DOESNT_MATCH_BLOBS
+ "LIKE_DOESNT_MATCH_BLOBS",
+#endif
+#ifdef SQLITE_LOCK_TRACE
+ "LOCK_TRACE",
+#endif
+#ifdef SQLITE_LOG_CACHE_SPILL
+ "LOG_CACHE_SPILL",
+#endif
+#ifdef SQLITE_MALLOC_SOFT_LIMIT
+ "MALLOC_SOFT_LIMIT=" CTIMEOPT_VAL(SQLITE_MALLOC_SOFT_LIMIT),
+#endif
+#ifdef SQLITE_MAX_ATTACHED
+ "MAX_ATTACHED=" CTIMEOPT_VAL(SQLITE_MAX_ATTACHED),
+#endif
+#ifdef SQLITE_MAX_COLUMN
+ "MAX_COLUMN=" CTIMEOPT_VAL(SQLITE_MAX_COLUMN),
+#endif
+#ifdef SQLITE_MAX_COMPOUND_SELECT
+ "MAX_COMPOUND_SELECT=" CTIMEOPT_VAL(SQLITE_MAX_COMPOUND_SELECT),
+#endif
+#ifdef SQLITE_MAX_DEFAULT_PAGE_SIZE
+ "MAX_DEFAULT_PAGE_SIZE=" CTIMEOPT_VAL(SQLITE_MAX_DEFAULT_PAGE_SIZE),
+#endif
+#ifdef SQLITE_MAX_EXPR_DEPTH
+ "MAX_EXPR_DEPTH=" CTIMEOPT_VAL(SQLITE_MAX_EXPR_DEPTH),
+#endif
+#ifdef SQLITE_MAX_FUNCTION_ARG
+ "MAX_FUNCTION_ARG=" CTIMEOPT_VAL(SQLITE_MAX_FUNCTION_ARG),
+#endif
+#ifdef SQLITE_MAX_LENGTH
+ "MAX_LENGTH=" CTIMEOPT_VAL(SQLITE_MAX_LENGTH),
+#endif
+#ifdef SQLITE_MAX_LIKE_PATTERN_LENGTH
+ "MAX_LIKE_PATTERN_LENGTH=" CTIMEOPT_VAL(SQLITE_MAX_LIKE_PATTERN_LENGTH),
+#endif
+#ifdef SQLITE_MAX_MEMORY
+ "MAX_MEMORY=" CTIMEOPT_VAL(SQLITE_MAX_MEMORY),
+#endif
+#ifdef SQLITE_MAX_MMAP_SIZE
+ "MAX_MMAP_SIZE=" CTIMEOPT_VAL(SQLITE_MAX_MMAP_SIZE),
+#endif
+#ifdef SQLITE_MAX_MMAP_SIZE_
+ "MAX_MMAP_SIZE_=" CTIMEOPT_VAL(SQLITE_MAX_MMAP_SIZE_),
+#endif
+#ifdef SQLITE_MAX_PAGE_COUNT
+ "MAX_PAGE_COUNT=" CTIMEOPT_VAL(SQLITE_MAX_PAGE_COUNT),
+#endif
+#ifdef SQLITE_MAX_PAGE_SIZE
+ "MAX_PAGE_SIZE=" CTIMEOPT_VAL(SQLITE_MAX_PAGE_SIZE),
+#endif
+#ifdef SQLITE_MAX_SCHEMA_RETRY
+ "MAX_SCHEMA_RETRY=" CTIMEOPT_VAL(SQLITE_MAX_SCHEMA_RETRY),
+#endif
+#ifdef SQLITE_MAX_SQL_LENGTH
+ "MAX_SQL_LENGTH=" CTIMEOPT_VAL(SQLITE_MAX_SQL_LENGTH),
+#endif
+#ifdef SQLITE_MAX_TRIGGER_DEPTH
+ "MAX_TRIGGER_DEPTH=" CTIMEOPT_VAL(SQLITE_MAX_TRIGGER_DEPTH),
+#endif
+#ifdef SQLITE_MAX_VARIABLE_NUMBER
+ "MAX_VARIABLE_NUMBER=" CTIMEOPT_VAL(SQLITE_MAX_VARIABLE_NUMBER),
+#endif
+#ifdef SQLITE_MAX_VDBE_OP
+ "MAX_VDBE_OP=" CTIMEOPT_VAL(SQLITE_MAX_VDBE_OP),
+#endif
+#ifdef SQLITE_MAX_WORKER_THREADS
+ "MAX_WORKER_THREADS=" CTIMEOPT_VAL(SQLITE_MAX_WORKER_THREADS),
+#endif
+#ifdef SQLITE_MEMDEBUG
+ "MEMDEBUG",
+#endif
+#ifdef SQLITE_MIXED_ENDIAN_64BIT_FLOAT
+ "MIXED_ENDIAN_64BIT_FLOAT",
+#endif
+#ifdef SQLITE_MMAP_READWRITE
+ "MMAP_READWRITE",
+#endif
+#ifdef SQLITE_MUTEX_NOOP
+ "MUTEX_NOOP",
+#endif
+#ifdef SQLITE_MUTEX_OMIT
+ "MUTEX_OMIT",
+#endif
+#ifdef SQLITE_MUTEX_PTHREADS
+ "MUTEX_PTHREADS",
+#endif
+#ifdef SQLITE_MUTEX_W32
+ "MUTEX_W32",
+#endif
+#ifdef SQLITE_NEED_ERR_NAME
+ "NEED_ERR_NAME",
+#endif
+#ifdef SQLITE_NO_SYNC
+ "NO_SYNC",
+#endif
+#ifdef SQLITE_OMIT_ALTERTABLE
+ "OMIT_ALTERTABLE",
+#endif
+#ifdef SQLITE_OMIT_ANALYZE
+ "OMIT_ANALYZE",
+#endif
+#ifdef SQLITE_OMIT_ATTACH
+ "OMIT_ATTACH",
+#endif
+#ifdef SQLITE_OMIT_AUTHORIZATION
+ "OMIT_AUTHORIZATION",
+#endif
+#ifdef SQLITE_OMIT_AUTOINCREMENT
+ "OMIT_AUTOINCREMENT",
+#endif
+#ifdef SQLITE_OMIT_AUTOINIT
+ "OMIT_AUTOINIT",
+#endif
+#ifdef SQLITE_OMIT_AUTOMATIC_INDEX
+ "OMIT_AUTOMATIC_INDEX",
+#endif
+#ifdef SQLITE_OMIT_AUTORESET
+ "OMIT_AUTORESET",
+#endif
+#ifdef SQLITE_OMIT_AUTOVACUUM
+ "OMIT_AUTOVACUUM",
+#endif
+#ifdef SQLITE_OMIT_BETWEEN_OPTIMIZATION
+ "OMIT_BETWEEN_OPTIMIZATION",
+#endif
+#ifdef SQLITE_OMIT_BLOB_LITERAL
+ "OMIT_BLOB_LITERAL",
+#endif
+#ifdef SQLITE_OMIT_CAST
+ "OMIT_CAST",
+#endif
+#ifdef SQLITE_OMIT_CHECK
+ "OMIT_CHECK",
+#endif
+#ifdef SQLITE_OMIT_COMPLETE
+ "OMIT_COMPLETE",
+#endif
+#ifdef SQLITE_OMIT_COMPOUND_SELECT
+ "OMIT_COMPOUND_SELECT",
+#endif
+#ifdef SQLITE_OMIT_CONFLICT_CLAUSE
+ "OMIT_CONFLICT_CLAUSE",
+#endif
+#ifdef SQLITE_OMIT_CTE
+ "OMIT_CTE",
+#endif
+#if defined(SQLITE_OMIT_DATETIME_FUNCS) || defined(SQLITE_OMIT_FLOATING_POINT)
+ "OMIT_DATETIME_FUNCS",
+#endif
+#ifdef SQLITE_OMIT_DECLTYPE
+ "OMIT_DECLTYPE",
+#endif
+#ifdef SQLITE_OMIT_DEPRECATED
+ "OMIT_DEPRECATED",
+#endif
+#ifdef SQLITE_OMIT_DESERIALIZE
+ "OMIT_DESERIALIZE",
+#endif
+#ifdef SQLITE_OMIT_DISKIO
+ "OMIT_DISKIO",
+#endif
+#ifdef SQLITE_OMIT_EXPLAIN
+ "OMIT_EXPLAIN",
+#endif
+#ifdef SQLITE_OMIT_FLAG_PRAGMAS
+ "OMIT_FLAG_PRAGMAS",
+#endif
+#ifdef SQLITE_OMIT_FLOATING_POINT
+ "OMIT_FLOATING_POINT",
+#endif
+#ifdef SQLITE_OMIT_FOREIGN_KEY
+ "OMIT_FOREIGN_KEY",
+#endif
+#ifdef SQLITE_OMIT_GET_TABLE
+ "OMIT_GET_TABLE",
+#endif
+#ifdef SQLITE_OMIT_HEX_INTEGER
+ "OMIT_HEX_INTEGER",
+#endif
+#ifdef SQLITE_OMIT_INCRBLOB
+ "OMIT_INCRBLOB",
+#endif
+#ifdef SQLITE_OMIT_INTEGRITY_CHECK
+ "OMIT_INTEGRITY_CHECK",
+#endif
+#ifdef SQLITE_OMIT_INTROSPECTION_PRAGMAS
+ "OMIT_INTROSPECTION_PRAGMAS",
+#endif
+#ifdef SQLITE_OMIT_JSON
+ "OMIT_JSON",
+#endif
+#ifdef SQLITE_OMIT_LIKE_OPTIMIZATION
+ "OMIT_LIKE_OPTIMIZATION",
+#endif
+#ifdef SQLITE_OMIT_LOAD_EXTENSION
+ "OMIT_LOAD_EXTENSION",
+#endif
+#ifdef SQLITE_OMIT_LOCALTIME
+ "OMIT_LOCALTIME",
+#endif
+#ifdef SQLITE_OMIT_LOOKASIDE
+ "OMIT_LOOKASIDE",
+#endif
+#ifdef SQLITE_OMIT_MEMORYDB
+ "OMIT_MEMORYDB",
+#endif
+#ifdef SQLITE_OMIT_OR_OPTIMIZATION
+ "OMIT_OR_OPTIMIZATION",
+#endif
+#ifdef SQLITE_OMIT_PAGER_PRAGMAS
+ "OMIT_PAGER_PRAGMAS",
+#endif
+#ifdef SQLITE_OMIT_PARSER_TRACE
+ "OMIT_PARSER_TRACE",
+#endif
+#ifdef SQLITE_OMIT_POPEN
+ "OMIT_POPEN",
+#endif
+#ifdef SQLITE_OMIT_PRAGMA
+ "OMIT_PRAGMA",
+#endif
+#ifdef SQLITE_OMIT_PROGRESS_CALLBACK
+ "OMIT_PROGRESS_CALLBACK",
+#endif
+#ifdef SQLITE_OMIT_QUICKBALANCE
+ "OMIT_QUICKBALANCE",
+#endif
+#ifdef SQLITE_OMIT_REINDEX
+ "OMIT_REINDEX",
+#endif
+#ifdef SQLITE_OMIT_SCHEMA_PRAGMAS
+ "OMIT_SCHEMA_PRAGMAS",
+#endif
+#ifdef SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS
+ "OMIT_SCHEMA_VERSION_PRAGMAS",
+#endif
+#ifdef SQLITE_OMIT_SEH
+ "OMIT_SEH",
+#endif
+#ifdef SQLITE_OMIT_SHARED_CACHE
+ "OMIT_SHARED_CACHE",
+#endif
+#ifdef SQLITE_OMIT_SHUTDOWN_DIRECTORIES
+ "OMIT_SHUTDOWN_DIRECTORIES",
+#endif
+#ifdef SQLITE_OMIT_SUBQUERY
+ "OMIT_SUBQUERY",
+#endif
+#ifdef SQLITE_OMIT_TCL_VARIABLE
+ "OMIT_TCL_VARIABLE",
+#endif
+#ifdef SQLITE_OMIT_TEMPDB
+ "OMIT_TEMPDB",
+#endif
+#ifdef SQLITE_OMIT_TEST_CONTROL
+ "OMIT_TEST_CONTROL",
+#endif
+#ifdef SQLITE_OMIT_TRACE
+# if SQLITE_OMIT_TRACE != 1
+ "OMIT_TRACE=" CTIMEOPT_VAL(SQLITE_OMIT_TRACE),
+# endif
+#endif
+#ifdef SQLITE_OMIT_TRIGGER
+ "OMIT_TRIGGER",
+#endif
+#ifdef SQLITE_OMIT_TRUNCATE_OPTIMIZATION
+ "OMIT_TRUNCATE_OPTIMIZATION",
+#endif
+#ifdef SQLITE_OMIT_UTF16
+ "OMIT_UTF16",
+#endif
+#ifdef SQLITE_OMIT_VACUUM
+ "OMIT_VACUUM",
+#endif
+#ifdef SQLITE_OMIT_VIEW
+ "OMIT_VIEW",
+#endif
+#ifdef SQLITE_OMIT_VIRTUALTABLE
+ "OMIT_VIRTUALTABLE",
+#endif
+#ifdef SQLITE_OMIT_WAL
+ "OMIT_WAL",
+#endif
+#ifdef SQLITE_OMIT_WSD
+ "OMIT_WSD",
+#endif
+#ifdef SQLITE_OMIT_XFER_OPT
+ "OMIT_XFER_OPT",
+#endif
+#ifdef SQLITE_PERFORMANCE_TRACE
+ "PERFORMANCE_TRACE",
+#endif
+#ifdef SQLITE_POWERSAFE_OVERWRITE
+# if SQLITE_POWERSAFE_OVERWRITE != 1
+ "POWERSAFE_OVERWRITE=" CTIMEOPT_VAL(SQLITE_POWERSAFE_OVERWRITE),
+# endif
+#endif
+#ifdef SQLITE_PREFER_PROXY_LOCKING
+ "PREFER_PROXY_LOCKING",
+#endif
+#ifdef SQLITE_PROXY_DEBUG
+ "PROXY_DEBUG",
+#endif
+#ifdef SQLITE_REVERSE_UNORDERED_SELECTS
+ "REVERSE_UNORDERED_SELECTS",
+#endif
+#ifdef SQLITE_RTREE_INT_ONLY
+ "RTREE_INT_ONLY",
+#endif
+#ifdef SQLITE_SECURE_DELETE
+ "SECURE_DELETE",
+#endif
+#ifdef SQLITE_SMALL_STACK
+ "SMALL_STACK",
+#endif
+#ifdef SQLITE_SORTER_PMASZ
+ "SORTER_PMASZ=" CTIMEOPT_VAL(SQLITE_SORTER_PMASZ),
+#endif
+#ifdef SQLITE_SOUNDEX
+ "SOUNDEX",
+#endif
+#ifdef SQLITE_STAT4_SAMPLES
+ "STAT4_SAMPLES=" CTIMEOPT_VAL(SQLITE_STAT4_SAMPLES),
+#endif
+#ifdef SQLITE_STMTJRNL_SPILL
+ "STMTJRNL_SPILL=" CTIMEOPT_VAL(SQLITE_STMTJRNL_SPILL),
+#endif
+#ifdef SQLITE_STRICT_SUBTYPE
+ "STRICT_SUBTYPE",
+#endif
+#ifdef SQLITE_SUBSTR_COMPATIBILITY
+ "SUBSTR_COMPATIBILITY",
+#endif
+#if (!defined(SQLITE_WIN32_MALLOC) \
+ && !defined(SQLITE_ZERO_MALLOC) \
+ && !defined(SQLITE_MEMDEBUG) \
+ ) || defined(SQLITE_SYSTEM_MALLOC)
+ "SYSTEM_MALLOC",
+#endif
+#ifdef SQLITE_TCL
+ "TCL",
+#endif
+#ifdef SQLITE_TEMP_STORE
+ "TEMP_STORE=" CTIMEOPT_VAL(SQLITE_TEMP_STORE),
+#endif
+#ifdef SQLITE_TEST
+ "TEST",
+#endif
+#if defined(SQLITE_THREADSAFE)
+ "THREADSAFE=" CTIMEOPT_VAL(SQLITE_THREADSAFE),
+#elif defined(THREADSAFE)
+ "THREADSAFE=" CTIMEOPT_VAL(THREADSAFE),
+#else
+ "THREADSAFE=1",
+#endif
+#ifdef SQLITE_UNLINK_AFTER_CLOSE
+ "UNLINK_AFTER_CLOSE",
+#endif
+#ifdef SQLITE_UNTESTABLE
+ "UNTESTABLE",
+#endif
+#ifdef SQLITE_USE_ALLOCA
+ "USE_ALLOCA",
+#endif
+#ifdef SQLITE_USE_FCNTL_TRACE
+ "USE_FCNTL_TRACE",
+#endif
+#ifdef SQLITE_USE_URI
+ "USE_URI",
+#endif
+#ifdef SQLITE_VDBE_COVERAGE
+ "VDBE_COVERAGE",
+#endif
+#ifdef SQLITE_WIN32_MALLOC
+ "WIN32_MALLOC",
+#endif
+#ifdef SQLITE_ZERO_MALLOC
+ "ZERO_MALLOC",
+#endif
+
+} ;
+
+SQLITE_PRIVATE const char **sqlite3CompileOptions(int *pnOpt){
+ *pnOpt = sizeof(sqlite3azCompileOpt) / sizeof(sqlite3azCompileOpt[0]);
+ return (const char**)sqlite3azCompileOpt;
+}
+
+#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */
+
+/************** End of ctime.c ***********************************************/
/************** Begin file global.c ******************************************/
/*
** 2008 June 13
@@ -19614,7 +23865,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
@@ -19636,7 +23887,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 */
@@ -19656,7 +23907,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
@@ -19668,7 +23947,7 @@ SQLITE_PRIVATE const unsigned char sqlite3UpperToLower[] = {
** isalnum() 0x06
** isxdigit() 0x08
** toupper() 0x20
-** SQLite identifier character 0x40
+** SQLite identifier character 0x40 $, _, or non-ascii
** Quote character 0x80
**
** Bit 0x20 is set if the mapped character requires translation to upper
@@ -19681,12 +23960,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 ........ */
@@ -19724,7 +24002,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
@@ -19736,24 +24013,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
@@ -19771,7 +24048,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
@@ -19782,9 +24059,18 @@ 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
@@ -19806,6 +24092,10 @@ SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlite3Config = {
SQLITE_USE_URI, /* bOpenUri */
SQLITE_ALLOW_COVERING_INDEX_SCAN, /* bUseCis */
0, /* bSmallMalloc */
+ 1, /* bExtraSchemaChecks */
+#ifdef SQLITE_DEBUG
+ 0, /* bJsonSelfcheck */
+#endif
0x7ffffffe, /* mxStrlen */
0, /* neverCorrupt */
SQLITE_DEFAULT_LOOKASIDE, /* szLookaside, nLookaside */
@@ -19842,16 +24132,23 @@ SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlite3Config = {
0, /* xVdbeBranch */
0, /* pVbeBranchArg */
#endif
-#ifdef SQLITE_ENABLE_DESERIALIZE
+#ifndef SQLITE_OMIT_DESERIALIZE
SQLITE_MEMDB_DEFAULT_MAXSIZE, /* mxMemdbSize */
#endif
#ifndef SQLITE_UNTESTABLE
0, /* xTestCallback */
+#endif
+#ifdef SQLITE_ALLOW_ROWID_IN_VIEW
+ 0, /* mNoVisibleRowid. 0 == allow rowid-in-view */
#endif
0, /* bLocaltimeFault */
- 0, /* bInternalFunctions */
+ 0, /* xAltLocaltime */
0x7ffffffe, /* iOnceResetThreshold */
SQLITE_DEFAULT_SORTERREF_SIZE, /* szSorterRef */
+ 0, /* iPrngSeed */
+#ifdef SQLITE_DEBUG
+ {0,0,0,0,0,0}, /* aTune */
+#endif
};
/*
@@ -19861,13 +24158,17 @@ SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlite3Config = {
*/
SQLITE_PRIVATE FuncDefHash sqlite3BuiltinFunctions;
+#if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_DEBUG)
/*
-** Constant tokens for values 0 and 1.
+** Counter used for coverage testing. Does not come into play for
+** release builds.
+**
+** Access to this global variable is not mutex protected. This might
+** result in TSAN warnings. But as the variable does not exist in
+** release builds, that should not be a concern.
*/
-SQLITE_PRIVATE const Token sqlite3IntTokens[] = {
- { "0", 1 },
- { "1", 1 }
-};
+SQLITE_PRIVATE unsigned int sqlite3CoverageCounter;
+#endif /* SQLITE_COVERAGE_TEST || SQLITE_DEBUG */
#ifdef VDBE_PROFILE
/*
@@ -19899,12 +24200,18 @@ SQLITE_PRIVATE sqlite3_uint64 sqlite3NProfileCnt = 0;
SQLITE_PRIVATE int sqlite3PendingByte = 0x40000000;
#endif
+/*
+** Tracing flags set by SQLITE_TESTCTRL_TRACEFLAGS.
+*/
+SQLITE_PRIVATE u32 sqlite3TreeTrace = 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;
@@ -19913,6 +24220,36 @@ SQLITE_PRIVATE const unsigned char sqlite3OpcodeProperty[] = OPFLG_INITIALIZER;
*/
SQLITE_PRIVATE const char sqlite3StrBINARY[] = "BINARY";
+/*
+** Standard typenames. These names must match the COLTYPE_* definitions.
+** Adjust the SQLITE_N_STDTYPE value if adding or removing entries.
+**
+** sqlite3StdType[] The actual names of the datatypes.
+**
+** sqlite3StdTypeLen[] The length (in bytes) of each entry
+** in sqlite3StdType[].
+**
+** sqlite3StdTypeAffinity[] The affinity associated with each entry
+** in sqlite3StdType[].
+*/
+SQLITE_PRIVATE const unsigned char sqlite3StdTypeLen[] = { 3, 4, 3, 7, 4, 4 };
+SQLITE_PRIVATE const char sqlite3StdTypeAffinity[] = {
+ SQLITE_AFF_NUMERIC,
+ SQLITE_AFF_BLOB,
+ SQLITE_AFF_INTEGER,
+ SQLITE_AFF_INTEGER,
+ SQLITE_AFF_REAL,
+ SQLITE_AFF_TEXT
+};
+SQLITE_PRIVATE const char *sqlite3StdType[] = {
+ "ANY",
+ "BLOB",
+ "INT",
+ "INTEGER",
+ "REAL",
+ "TEXT"
+};
+
/************** End of global.c **********************************************/
/************** Begin file status.c ******************************************/
/*
@@ -19966,7 +24303,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
@@ -19990,6 +24328,9 @@ typedef struct VdbeSorter VdbeSorter;
/* Elements of the linked list at Vdbe.pAuxData */
typedef struct AuxData AuxData;
+/* A cache of large TEXT or BLOB values in a VdbeCursor */
+typedef struct VdbeTxtBlbCache VdbeTxtBlbCache;
+
/* Types of VDBE cursors */
#define CURTYPE_BTREE 0
#define CURTYPE_SORTER 1
@@ -20009,7 +24350,7 @@ typedef struct AuxData AuxData;
typedef struct VdbeCursor VdbeCursor;
struct VdbeCursor {
u8 eCurType; /* One of the CURTYPE_* values above */
- i8 iDb; /* Index of cursor database in db->aDb[] (or -1) */
+ i8 iDb; /* Index of cursor database in db->aDb[] */
u8 nullRow; /* True if pointing to a row with no data */
u8 deferredMoveto; /* A call to sqlite3BtreeMoveto() is needed */
u8 isTable; /* True for rowid tables. False for indexes */
@@ -20020,10 +24361,14 @@ 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 */
- Btree *pBtx; /* Separate file holding temporary table */
+ Bool noReuse:1; /* OpenEphemeral may not reuse this cursor */
+ Bool colCache:1; /* pCache pointer is initialized and non-NULL */
+ u16 seekHit; /* See the OP_SeekHit and OP_IfNoHope opcodes */
+ union { /* pBtx for isEphermeral. pAltMap otherwise */
+ Btree *pBtx; /* Separate file holding temporary table */
+ u32 *aAltMap; /* Mapping from table to index column numbers */
+ } ub;
i64 seqCount; /* Sequence counter */
- int *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
@@ -20058,24 +24403,50 @@ struct VdbeCursor {
#ifdef SQLITE_ENABLE_COLUMN_USED_MASK
u64 maskUsed; /* Mask of columns used by this cursor */
#endif
+ VdbeTxtBlbCache *pCache; /* Cache of large TEXT or BLOB values */
- /* 2*nField extra array elements allocated for aType[], beyond the one
- ** static element declared in the structure. nField total array slots for
- ** aType[] and nField+1 array slots for aOffset[] */
- u32 aType[1]; /* Type values record decode. MUST BE LAST */
+ /* Space is allocated for aType to hold at least 2*nField+1 entries:
+ ** nField slots for aType[] and nField+1 array slots for aOffset[] */
+ u32 aType[FLEXARRAY]; /* Type values record decode. MUST BE LAST */
};
+/*
+** The size (in bytes) of a VdbeCursor object that has an nField value of N
+** or less. The value of SZ_VDBECURSOR(n) is guaranteed to be a multiple
+** of 8.
+*/
+#define SZ_VDBECURSOR(N) \
+ (ROUND8(offsetof(VdbeCursor,aType)) + ((N)+1)*sizeof(u64))
+
+/* Return true if P is a null-only cursor
+*/
+#define IsNullCursor(P) \
+ ((P)->eCurType==CURTYPE_PSEUDO && (P)->nullRow && (P)->seekResult==0)
/*
** A value for VdbeCursor.cacheStatus that means the cache is always invalid.
*/
#define CACHE_STALE 0
+/*
+** Large TEXT or BLOB values can be slow to load, so we want to avoid
+** loading them more than once. For that reason, large TEXT and BLOB values
+** can be stored in a cache defined by this object, and attached to the
+** VdbeCursor using the pCache field.
+*/
+struct VdbeTxtBlbCache {
+ char *pCValue; /* A RCStr buffer to hold the value */
+ i64 iOffset; /* File offset of the row being cached */
+ int iCol; /* Column for which the cache is valid */
+ u32 cacheStatus; /* Vdbe.cacheCtr value */
+ u32 colCacheCtr; /* Column cache counter */
+};
+
/*
** 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.
@@ -20097,7 +24468,6 @@ struct VdbeFrame {
Vdbe *v; /* VM this frame belongs to */
VdbeFrame *pParent; /* Parent of this frame, or NULL if parent is main */
Op *aOp; /* Program instructions for parent frame */
- i64 *anExec; /* Event counters from parent frame */
Mem *aMem; /* Array of memory cells for parent frame */
VdbeCursor **apCsr; /* Array of Vdbe cursors for parent frame */
u8 *aOnce; /* Bitmask used by OP_Once */
@@ -20113,8 +24483,8 @@ struct VdbeFrame {
int nMem; /* Number of entries in aMem */
int nChildMem; /* Number of memory cells for child frame */
int nChildCsr; /* Number of cursors for child frame */
- int nChange; /* Statement changes (Vdbe.nChange) */
- int nDbChange; /* Value of db->nChange */
+ i64 nChange; /* Statement changes (Vdbe.nChange) */
+ i64 nDbChange; /* Value of db->nChange */
};
/* Magic number for sanity checking on VdbeFrame objects */
@@ -20139,20 +24509,21 @@ struct sqlite3_value {
const char *zPType; /* Pointer type when MEM_Term|MEM_Subtype|MEM_Null */
FuncDef *pDef; /* Used only when flags==MEM_Agg */
} u;
+ char *z; /* String or BLOB value */
+ int n; /* Number of characters in string value, excluding '\0' */
u16 flags; /* Some combination of MEM_Null, MEM_Str, MEM_Dyn, etc. */
u8 enc; /* SQLITE_UTF8, SQLITE_UTF16BE, SQLITE_UTF16LE */
u8 eSubtype; /* Subtype for this value */
- int n; /* Number of characters in string value, excluding '\0' */
- char *z; /* String or BLOB value */
/* ShallowCopy only needs to copy the information above */
- char *zMalloc; /* Space to hold MEM_Str or MEM_Blob if szMalloc>0 */
+ sqlite3 *db; /* The associated database connection */
int szMalloc; /* Size of the zMalloc allocation */
u32 uTemp; /* Transient storage for serial_type in OP_MakeRecord */
- sqlite3 *db; /* The associated database connection */
+ char *zMalloc; /* Space to hold MEM_Str or MEM_Blob if szMalloc>0 */
void (*xDel)(void*);/* Destructor for Mem.z - only valid if MEM_Dyn */
#ifdef SQLITE_DEBUG
Mem *pScopyFrom; /* This Mem is a shallow copy of pScopyFrom */
u16 mScopyFlags; /* flags value immediately after the shallow copy */
+ u8 bScopy; /* The pScopyFrom of some other Mem *might* point here */
#endif
};
@@ -20160,11 +24531,43 @@ struct sqlite3_value {
** Size of struct Mem not including the Mem.zMalloc member or anything that
** follows.
*/
-#define MEMCELLSIZE offsetof(Mem,zMalloc)
+#define MEMCELLSIZE offsetof(Mem,db)
-/* One or more of the following flags are set to indicate the validOK
+/* One or more of the following flags are set to indicate the
** representations of the value stored in the Mem struct.
**
+** * MEM_Null An SQL NULL value
+**
+** * MEM_Null|MEM_Zero An SQL NULL with the virtual table
+** UPDATE no-change flag set
+**
+** * MEM_Null|MEM_Term| An SQL NULL, but also contains a
+** MEM_Subtype pointer accessible using
+** sqlite3_value_pointer().
+**
+** * MEM_Null|MEM_Cleared Special SQL NULL that compares non-equal
+** to other NULLs even using the IS operator.
+**
+** * MEM_Str A string, stored in Mem.z with
+** length Mem.n. Zero-terminated if
+** MEM_Term is set. This flag is
+** incompatible with MEM_Blob and
+** MEM_Null, but can appear with MEM_Int,
+** MEM_Real, and MEM_IntReal.
+**
+** * MEM_Blob A blob, stored in Mem.z length Mem.n.
+** Incompatible with MEM_Str, MEM_Null,
+** MEM_Int, MEM_Real, and MEM_IntReal.
+**
+** * MEM_Blob|MEM_Zero A blob in Mem.z of length Mem.n plus
+** Mem.u.nZero extra 0x00 bytes at the end.
+**
+** * MEM_Int Integer stored in Mem.u.i.
+**
+** * MEM_Real Real stored in Mem.u.r.
+**
+** * MEM_IntReal Real stored as an integer in Mem.u.i.
+**
** If the MEM_Null flag is set, then the value is an SQL NULL value.
** For a pointer type created using sqlite3_bind_pointer() or
** sqlite3_result_pointer() the MEM_Term and MEM_Subtype flags are also set.
@@ -20172,38 +24575,35 @@ 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_Undefined 0x0000 /* Value is undefined */
#define MEM_Null 0x0001 /* Value is NULL (or a pointer) */
#define MEM_Str 0x0002 /* Value is a string */
#define MEM_Int 0x0004 /* Value is an integer */
#define MEM_Real 0x0008 /* Value is a real number */
#define MEM_Blob 0x0010 /* Value is a BLOB */
-#define MEM_AffMask 0x001f /* Mask of affinity bits */
-#define MEM_FromBind 0x0020 /* Value originates from sqlite3_bind() */
-/* Available 0x0040 */
-#define MEM_Undefined 0x0080 /* Value is undefined */
-#define MEM_Cleared 0x0100 /* NULL set by OP_Null, not from data */
-#define MEM_TypeMask 0xc1df /* Mask of type bits */
-
+#define MEM_IntReal 0x0020 /* MEM_Int that stringifies like MEM_Real */
+#define MEM_AffMask 0x003f /* Mask of affinity bits */
-/* Whenever Mem contains a valid string or blob representation, one of
-** the following flags must be set to determine the memory management
-** policy for Mem.z. The MEM_Term flag tells us whether or not the
-** string is \000 or \u0000 terminated
+/* Extra bits that modify the meanings of the core datatypes above
*/
+#define MEM_FromBind 0x0040 /* Value originates from sqlite3_bind() */
+ /* 0x0080 // Available */
+#define MEM_Cleared 0x0100 /* NULL set by OP_Null, not from data */
#define MEM_Term 0x0200 /* String in Mem.z is zero terminated */
-#define MEM_Dyn 0x0400 /* Need to call Mem.xDel() on Mem.z */
-#define MEM_Static 0x0800 /* Mem.z points to a static string */
-#define MEM_Ephem 0x1000 /* Mem.z points to an ephemeral string */
-#define MEM_Agg 0x2000 /* Mem.z points to an agg function context */
-#define MEM_Zero 0x4000 /* Mem.i contains count of 0s appended to blob */
-#define MEM_Subtype 0x8000 /* Mem.eSubtype is valid */
-#ifdef SQLITE_OMIT_INCRBLOB
- #undef MEM_Zero
- #define MEM_Zero 0x0000
-#endif
+#define MEM_Zero 0x0400 /* Mem.i contains count of 0s appended to blob */
+#define MEM_Subtype 0x0800 /* Mem.eSubtype is valid */
+#define MEM_TypeMask 0x0dbf /* Mask of type bits */
+
+/* Bits that determine the storage for Mem.z for a string or blob or
+** aggregate accumulator.
+*/
+#define MEM_Dyn 0x1000 /* Need to call Mem.xDel() on Mem.z */
+#define MEM_Static 0x2000 /* Mem.z points to a static string */
+#define MEM_Ephem 0x4000 /* Mem.z points to an ephemeral string */
+#define MEM_Agg 0x8000 /* Mem.z points to an agg function context */
/* Return TRUE if Mem X contains dynamically allocated content - anything
** that needs to be deallocated to avoid a leak.
@@ -20221,18 +24621,23 @@ struct sqlite3_value {
** True if Mem X is a NULL-nochng type.
*/
#define MemNullNochng(X) \
- ((X)->flags==(MEM_Null|MEM_Zero) && (X)->n==0 && (X)->u.nZero==0)
+ (((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
+** Return true if a memory cell has been initialized and is valid.
** is for use inside assert() statements only.
+**
+** A Memory cell is initialized if at least one of the
+** MEM_Null, MEM_Str, MEM_Int, MEM_Real, MEM_Blob, or MEM_IntReal bits
+** is set. It is "undefined" if all those bits are zero.
*/
#ifdef SQLITE_DEBUG
-#define memIsValid(M) ((M)->flags & MEM_Undefined)==0
+#define memIsValid(M) ((M)->flags & MEM_AffMask)!=0
#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
@@ -20266,22 +24671,35 @@ struct sqlite3_context {
Vdbe *pVdbe; /* The VM that owns this context */
int iOp; /* Instruction number of OP_Function */
int isError; /* Error code returned by the function. */
+ u8 enc; /* Encoding to use for results */
u8 skipFlag; /* Skip accumulator loading if true */
- u8 argc; /* Number of arguments */
- sqlite3_value *argv[1]; /* Argument set */
+ u16 argc; /* Number of arguments */
+ sqlite3_value *argv[FLEXARRAY]; /* Argument set */
};
-/* A bitfield type for use inside of structures. Always follow with :N where
-** N is the number of bits.
+/*
+** The size (in bytes) of an sqlite3_context object that holds N
+** argv[] arguments.
*/
-typedef unsigned bft; /* Bit Field Type */
+#define SZ_CONTEXT(N) \
+ (offsetof(sqlite3_context,argv)+(N)*sizeof(sqlite3_value*))
+
/* The ScanStatus object holds a single value for the
** sqlite3_stmt_scanstatus() interface.
+**
+** aAddrRange[]:
+** This array is used by ScanStatus elements associated with EQP
+** notes that make an SQLITE_SCANSTAT_NCYCLE value available. It is
+** an array of up to 3 ranges of VM addresses for which the Vdbe.anCycle[]
+** values should be summed to calculate the NCYCLE value. Each pair of
+** integer addresses is a start and end address (both inclusive) for a range
+** instructions. A start value of 0 indicates an empty range.
*/
typedef struct ScanStatus ScanStatus;
struct ScanStatus {
int addrExplain; /* OP_Explain for loop */
+ int aAddrRange[6];
int addrLoop; /* Address of "loops" counter */
int addrVisit; /* Address of "rows visited" counter */
int iSelectID; /* The "Select-ID" for this loop */
@@ -20311,23 +24729,22 @@ struct DblquoteStr {
*/
struct Vdbe {
sqlite3 *db; /* The database connection that owns this statement */
- Vdbe *pPrev,*pNext; /* Linked list of VDBEs with the same Vdbe.db */
+ Vdbe **ppVPrev,*pVNext; /* 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 */
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 */
+ i64 nChange; /* Number of db changes made since last reset */
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 */
+ Mem **apArg; /* Arguments xUpdate and xFilter vtab methods */
VdbeCursor **apCsr; /* One element of this array for each open cursor */
Mem *aVar; /* Values for the OP_Variable opcode. */
@@ -20338,7 +24755,7 @@ struct Vdbe {
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 */
+ Mem *pResultRow; /* Current output row */
char *zErrMsg; /* Error message written here */
VList *pVList; /* Name of variables */
#ifndef SQLITE_OMIT_TRACE
@@ -20347,22 +24764,24 @@ struct Vdbe {
#ifdef SQLITE_DEBUG
int rcApp; /* errcode set by sqlite3_result_error_code() */
u32 nWrite; /* Number of write operations that have occurred */
+ int napArg; /* Size of the apArg[] array */
#endif
u16 nResColumn; /* Number of columns in one row of the result set */
+ u16 nResAlloc; /* Column slots allocated to aColName[] */
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 eVdbeState; /* On of the VDBE_*_STATE values */
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 explain:2; /* 0: normal, 1: EXPLAIN, 2: EXPLAIN QUERY PLAN */
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 */
bft readOnly:1; /* True for statements that do not write */
bft bIsReader:1; /* True for statements that read */
+ bft haveEqpOps:1; /* Bytecode supports EXPLAIN QUERY PLAN */
yDbMask btreeMask; /* Bitmask of db->aDb[] entries referenced */
yDbMask lockMask; /* Subset of btreeMask that requires a lock */
- u32 aCounter[7]; /* Counters used by sqlite3_stmt_status() */
+ u32 aCounter[9]; /* 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 */
@@ -20376,23 +24795,21 @@ struct Vdbe {
SubProgram *pProgram; /* Linked list of all sub-programs used by VM */
AuxData *pAuxData; /* Linked list of auxdata allocations */
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
- i64 *anExec; /* Number of times each op has been executed */
int nScan; /* Entries in aScan[] */
ScanStatus *aScan; /* Scan definitions for sqlite3_stmt_scanstatus() */
#endif
};
/*
-** The following are allowed values for Vdbe.magic
+** The following are allowed values for Vdbe.eVdbeState
*/
-#define VDBE_MAGIC_INIT 0x16bceaa5 /* Building a VDBE program */
-#define VDBE_MAGIC_RUN 0x2df20da3 /* VDBE is ready to execute */
-#define VDBE_MAGIC_HALT 0x319c2973 /* VDBE has completed execution */
-#define VDBE_MAGIC_RESET 0x48fa9f76 /* Reset and ready to run again */
-#define VDBE_MAGIC_DEAD 0x5606c3c8 /* The VDBE has been deallocated */
+#define VDBE_INIT_STATE 0 /* Prepared statement under construction */
+#define VDBE_READY_STATE 1 /* Ready to run but not yet started */
+#define VDBE_RUN_STATE 2 /* Run in progress */
+#define VDBE_HALT_STATE 3 /* Finished. Need reset() or finalize() */
/*
-** Structure used to store the context required by the
+** Structure used to store the context required by the
** sqlite3_preupdate_*() API functions.
*/
struct PreUpdate {
@@ -20400,37 +24817,81 @@ struct PreUpdate {
VdbeCursor *pCsr; /* Cursor to read old values from */
int op; /* One of SQLITE_INSERT, UPDATE, DELETE */
u8 *aRecord; /* old.* database record */
- KeyInfo keyinfo;
+ KeyInfo *pKeyinfo; /* Key information */
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 oldipk; /* Memory cell holding "old" IPK value */
Mem *aNew; /* Array of new.* values */
- Table *pTab; /* Schema object being upated */
+ Table *pTab; /* Schema object being updated */
Index *pPk; /* PK index if pTab is WITHOUT ROWID */
+ sqlite3_value **apDflt; /* Array of default values, if required */
+ struct {
+ u8 keyinfoSpace[SZ_KEYINFO_0]; /* Space to hold pKeyinfo[0] content */
+ } uKey;
};
+/*
+** An instance of this object is used to pass an vector of values into
+** OP_VFilter, the xFilter method of a virtual table. The vector is the
+** set of values on the right-hand side of an IN constraint.
+**
+** The value as passed into xFilter is an sqlite3_value with a "pointer"
+** type, such as is generated by sqlite3_result_pointer() and read by
+** sqlite3_value_pointer. Such values have MEM_Term|MEM_Subtype|MEM_Null
+** and a subtype of 'p'. The sqlite3_vtab_in_first() and _next() interfaces
+** know how to use this object to step through all the values in the
+** right operand of the IN constraint.
+*/
+typedef struct ValueList ValueList;
+struct ValueList {
+ BtCursor *pCsr; /* An ephemeral table holding all values */
+ sqlite3_value *pOut; /* Register to hold each decoded output value */
+};
+
+/* Size of content associated with serial types that fit into a
+** single-byte varint.
+*/
+#ifndef SQLITE_AMALGAMATION
+SQLITE_PRIVATE const u8 sqlite3SmallTypeSizes[];
+#endif
+
/*
** Function prototypes
*/
SQLITE_PRIVATE void sqlite3VdbeError(Vdbe*, const char *, ...);
SQLITE_PRIVATE void sqlite3VdbeFreeCursor(Vdbe *, VdbeCursor*);
+SQLITE_PRIVATE void sqlite3VdbeFreeCursorNN(Vdbe*,VdbeCursor*);
void sqliteVdbePopStack(Vdbe*,int);
-SQLITE_PRIVATE int sqlite3VdbeCursorMoveto(VdbeCursor**, int*);
+SQLITE_PRIVATE int SQLITE_NOINLINE sqlite3VdbeHandleMovedCursor(VdbeCursor *p);
+SQLITE_PRIVATE int SQLITE_NOINLINE sqlite3VdbeFinishMoveto(VdbeCursor*);
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*);
+#ifdef SQLITE_MIXED_ENDIAN_64BIT_FLOAT
+SQLITE_PRIVATE u64 sqlite3FloatSwap(u64 in);
+# define swapMixedEndianFloat(X) X = sqlite3FloatSwap(X)
+#else
+# define swapMixedEndianFloat(X)
+#endif
+SQLITE_PRIVATE void sqlite3VdbeSerialGet(const unsigned char*, u32, Mem*);
SQLITE_PRIVATE void sqlite3VdbeDeleteAuxData(sqlite3*, AuxData**, int, int);
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*);
-#ifndef SQLITE_OMIT_EXPLAIN
+#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*);
@@ -20440,7 +24901,8 @@ 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 int sqlite3VdbeMemSetText(Mem*, const char*, i64, void(*)(void*));
SQLITE_PRIVATE void sqlite3VdbeMemSetInt64(Mem*, i64);
#ifdef SQLITE_OMIT_FLOATING_POINT
# define sqlite3VdbeMemSetDouble sqlite3VdbeMemSetInt64
@@ -20450,28 +24912,37 @@ SQLITE_PRIVATE void sqlite3VdbeMemSetDouble(Mem*, double);
SQLITE_PRIVATE void sqlite3VdbeMemSetPointer(Mem*, void*, const char*, void(*)(void*));
SQLITE_PRIVATE void sqlite3VdbeMemInit(Mem*,sqlite3*,u16);
SQLITE_PRIVATE void sqlite3VdbeMemSetNull(Mem*);
+#ifndef SQLITE_OMIT_INCRBLOB
SQLITE_PRIVATE void sqlite3VdbeMemSetZeroBlob(Mem*,int);
+#else
+SQLITE_PRIVATE int sqlite3VdbeMemSetZeroBlob(Mem*,int);
+#endif
#ifdef SQLITE_DEBUG
SQLITE_PRIVATE int sqlite3VdbeMemIsRowSet(const Mem*);
#endif
SQLITE_PRIVATE int sqlite3VdbeMemSetRowSet(Mem*);
+SQLITE_PRIVATE int sqlite3VdbeMemZeroTerminateIfAble(Mem*);
SQLITE_PRIVATE int sqlite3VdbeMemMakeWriteable(Mem*);
SQLITE_PRIVATE int sqlite3VdbeMemStringify(Mem*, u8, u8);
-SQLITE_PRIVATE i64 sqlite3VdbeIntValue(Mem*);
+SQLITE_PRIVATE int sqlite3IntFloatCompare(i64,double);
+SQLITE_PRIVATE i64 sqlite3VdbeIntValue(const Mem*);
SQLITE_PRIVATE int sqlite3VdbeMemIntegerify(Mem*);
SQLITE_PRIVATE double sqlite3VdbeRealValue(Mem*);
+SQLITE_PRIVATE int sqlite3MemRealValueRC(Mem*, double*);
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 void sqlite3VdbeMemReleaseMalloc(Mem*p);
SQLITE_PRIVATE int sqlite3VdbeMemFinalize(Mem*, FuncDef*);
#ifndef SQLITE_OMIT_WINDOWFUNC
SQLITE_PRIVATE int sqlite3VdbeMemAggValue(Mem*, Mem*, FuncDef*);
#endif
-#ifndef SQLITE_OMIT_EXPLAIN
+#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);
@@ -20484,9 +24955,11 @@ 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);
+SQLITE_PRIVATE int sqlite3VdbeFindIndexKey(BtCursor*, Index*, UnpackedRecord*, int*, int);
SQLITE_PRIVATE int sqlite3VdbeSorterInit(sqlite3 *, int, VdbeCursor *);
SQLITE_PRIVATE void sqlite3VdbeSorterReset(sqlite3 *, VdbeSorter *);
@@ -20497,6 +24970,8 @@ SQLITE_PRIVATE int sqlite3VdbeSorterRewind(const VdbeCursor *, int *);
SQLITE_PRIVATE int sqlite3VdbeSorterWrite(const VdbeCursor *, Mem *);
SQLITE_PRIVATE int sqlite3VdbeSorterCompare(const VdbeCursor *, Mem *, int, int *);
+SQLITE_PRIVATE void sqlite3VdbeValueListFree(void*);
+
#ifdef SQLITE_DEBUG
SQLITE_PRIVATE void sqlite3VdbeIncrWriteCounter(Vdbe*, VdbeCursor*);
SQLITE_PRIVATE void sqlite3VdbeAssertAbortable(Vdbe*);
@@ -20505,7 +24980,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)
@@ -20523,14 +24998,16 @@ SQLITE_PRIVATE int sqlite3VdbeCheckMemInvariants(Mem*);
#endif
#ifndef SQLITE_OMIT_FOREIGN_KEY
-SQLITE_PRIVATE int sqlite3VdbeCheckFk(Vdbe *, int);
+SQLITE_PRIVATE int sqlite3VdbeCheckFkImmediate(Vdbe*);
+SQLITE_PRIVATE int sqlite3VdbeCheckFkDeferred(Vdbe*);
#else
-# define sqlite3VdbeCheckFk(p,i) 0
+# define sqlite3VdbeCheckFkImmediate(p) 0
+# define sqlite3VdbeCheckFkDeferred(p) 0
#endif
#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);
@@ -20722,30 +25199,37 @@ 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);
- if( pHighwater ) *pHighwater = db->lookaside.nSlot - nInit;
- return db->lookaside.nSlot - (nInit+nFree);
+#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE
+ nInit += countLookasideSlots(db->lookaside.pSmallInit);
+ nFree += countLookasideSlots(db->lookaside.pSmallFree);
+#endif /* SQLITE_OMIT_TWOSIZE_LOOKASIDE */
+ assert( db->lookaside.nSlot >= nInit+nFree );
+ if( pHighwater ) *pHighwater = (int)(db->lookaside.nSlot - nInit);
+ return (int)(db->lookaside.nSlot - (nInit+nFree));
}
/*
** Query status information for a single database connection
*/
-SQLITE_API int sqlite3_db_status(
- sqlite3 *db, /* The database connection whose status is desired */
- int op, /* Status verb */
- int *pCurrent, /* Write current value here */
- int *pHighwater, /* Write high-water mark here */
- int resetFlag /* Reset high-water mark if true */
+SQLITE_API int sqlite3_db_status64(
+ sqlite3 *db, /* The database connection whose status is desired */
+ int op, /* Status verb */
+ sqlite3_int64 *pCurrent, /* Write current value here */
+ sqlite3_int64 *pHighwtr, /* Write high-water mark here */
+ int resetFlag /* Reset high-water mark if true */
){
int rc = SQLITE_OK; /* Return code */
#ifdef SQLITE_ENABLE_API_ARMOR
- if( !sqlite3SafetyCheckOk(db) || pCurrent==0|| pHighwater==0 ){
+ if( !sqlite3SafetyCheckOk(db) || pCurrent==0|| pHighwtr==0 ){
return SQLITE_MISUSE_BKPT;
}
#endif
sqlite3_mutex_enter(db->mutex);
switch( op ){
case SQLITE_DBSTATUS_LOOKASIDE_USED: {
- *pCurrent = sqlite3LookasideUsed(db, pHighwater);
+ int H = 0;
+ *pCurrent = sqlite3LookasideUsed(db, &H);
+ *pHighwtr = H;
if( resetFlag ){
LookasideSlot *p = db->lookaside.pFree;
if( p ){
@@ -20754,6 +25238,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;
}
@@ -20767,21 +25260,21 @@ SQLITE_API int sqlite3_db_status(
assert( (op-SQLITE_DBSTATUS_LOOKASIDE_HIT)>=0 );
assert( (op-SQLITE_DBSTATUS_LOOKASIDE_HIT)<3 );
*pCurrent = 0;
- *pHighwater = db->lookaside.anStat[op - SQLITE_DBSTATUS_LOOKASIDE_HIT];
+ *pHighwtr = db->lookaside.anStat[op-SQLITE_DBSTATUS_LOOKASIDE_HIT];
if( resetFlag ){
db->lookaside.anStat[op - SQLITE_DBSTATUS_LOOKASIDE_HIT] = 0;
}
break;
}
- /*
+ /*
** Return an approximation for the amount of memory currently used
** by all pagers associated with the given database connection. The
** highwater mark is meaningless and is returned as zero.
*/
case SQLITE_DBSTATUS_CACHE_USED_SHARED:
case SQLITE_DBSTATUS_CACHE_USED: {
- int totalUsed = 0;
+ sqlite3_int64 totalUsed = 0;
int i;
sqlite3BtreeEnterAll(db);
for(i=0; inDb; i++){
@@ -20797,28 +25290,30 @@ SQLITE_API int sqlite3_db_status(
}
sqlite3BtreeLeaveAll(db);
*pCurrent = totalUsed;
- *pHighwater = 0;
+ *pHighwtr = 0;
break;
}
/*
** *pCurrent gets an accurate estimate of the amount of memory used
** to store the schema for all databases (main, temp, and any ATTACHed
- ** databases. *pHighwater is set to zero.
+ ** databases. *pHighwtr is set to zero.
*/
case SQLITE_DBSTATUS_SCHEMA_USED: {
- int i; /* Used to iterate through schemas */
- int nByte = 0; /* Used to accumulate return value */
+ int i; /* Used to iterate through schemas */
+ int nByte = 0; /* Used to accumulate return value */
sqlite3BtreeEnterAll(db);
db->pnBytesFreed = &nByte;
+ assert( db->lookaside.pEnd==db->lookaside.pTrueEnd );
+ db->lookaside.pEnd = db->lookaside.pStart;
for(i=0; inDb; i++){
Schema *pSchema = db->aDb[i].pSchema;
if( ALWAYS(pSchema!=0) ){
HashElem *p;
nByte += sqlite3GlobalConfig.m.xRoundup(sizeof(HashElem)) * (
- pSchema->tblHash.count
+ pSchema->tblHash.count
+ pSchema->trigHash.count
+ pSchema->idxHash.count
+ pSchema->fkeyHash.count
@@ -20837,9 +25332,10 @@ SQLITE_API int sqlite3_db_status(
}
}
db->pnBytesFreed = 0;
+ db->lookaside.pEnd = db->lookaside.pTrueEnd;
sqlite3BtreeLeaveAll(db);
- *pHighwater = 0;
+ *pHighwtr = 0;
*pCurrent = nByte;
break;
}
@@ -20847,20 +25343,22 @@ SQLITE_API int sqlite3_db_status(
/*
** *pCurrent gets an accurate estimate of the amount of memory used
** to store all prepared statements.
- ** *pHighwater is set to zero.
+ ** *pHighwtr is set to zero.
*/
case SQLITE_DBSTATUS_STMT_USED: {
struct Vdbe *pVdbe; /* Used to iterate through VMs */
int nByte = 0; /* Used to accumulate return value */
db->pnBytesFreed = &nByte;
- for(pVdbe=db->pVdbe; pVdbe; pVdbe=pVdbe->pNext){
- sqlite3VdbeClearObject(db, pVdbe);
- sqlite3DbFree(db, pVdbe);
+ assert( db->lookaside.pEnd==db->lookaside.pTrueEnd );
+ db->lookaside.pEnd = db->lookaside.pStart;
+ for(pVdbe=db->pVdbe; pVdbe; pVdbe=pVdbe->pVNext){
+ sqlite3VdbeDelete(pVdbe);
}
+ db->lookaside.pEnd = db->lookaside.pTrueEnd;
db->pnBytesFreed = 0;
- *pHighwater = 0; /* IMP: R-64479-57858 */
+ *pHighwtr = 0; /* IMP: R-64479-57858 */
*pCurrent = nByte;
break;
@@ -20868,17 +25366,17 @@ 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. *pHighwtr 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:{
int i;
- int nRet = 0;
+ u64 nRet = 0;
assert( SQLITE_DBSTATUS_CACHE_MISS==SQLITE_DBSTATUS_CACHE_HIT+1 );
assert( SQLITE_DBSTATUS_CACHE_WRITE==SQLITE_DBSTATUS_CACHE_HIT+2 );
@@ -20888,19 +25386,39 @@ SQLITE_API int sqlite3_db_status(
sqlite3PagerCacheStat(pPager, op, resetFlag, &nRet);
}
}
- *pHighwater = 0; /* IMP: R-42420-56072 */
+ *pHighwtr = 0; /* IMP: R-42420-56072 */
/* IMP: R-54100-20147 */
/* IMP: R-29431-39229 */
*pCurrent = nRet;
break;
}
+ /* Set *pCurrent to the number of bytes that the db database connection
+ ** has spilled to the filesystem in temporary files that could have been
+ ** stored in memory, had sufficient memory been available.
+ ** The *pHighwater is always set to zero.
+ */
+ case SQLITE_DBSTATUS_TEMPBUF_SPILL: {
+ u64 nRet = 0;
+ if( db->aDb[1].pBt ){
+ Pager *pPager = sqlite3BtreePager(db->aDb[1].pBt);
+ sqlite3PagerCacheStat(pPager, SQLITE_DBSTATUS_CACHE_WRITE,
+ resetFlag, &nRet);
+ nRet *= sqlite3BtreeGetPageSize(db->aDb[1].pBt);
+ }
+ nRet += db->nSpill;
+ if( resetFlag ) db->nSpill = 0;
+ *pHighwtr = 0;
+ *pCurrent = nRet;
+ break;
+ }
+
/* Set *pCurrent to non-zero if there are unresolved deferred foreign
** key constraints. Set *pCurrent to zero if all foreign key constraints
- ** have been satisfied. The *pHighwater is always set to zero.
+ ** have been satisfied. The *pHighwtr is always set to zero.
*/
case SQLITE_DBSTATUS_DEFERRED_FKS: {
- *pHighwater = 0; /* IMP: R-11967-56545 */
+ *pHighwtr = 0; /* IMP: R-11967-56545 */
*pCurrent = db->nDeferredImmCons>0 || db->nDeferredCons>0;
break;
}
@@ -20913,6 +25431,31 @@ SQLITE_API int sqlite3_db_status(
return rc;
}
+/*
+** 32-bit variant of sqlite3_db_status64()
+*/
+SQLITE_API int sqlite3_db_status(
+ sqlite3 *db, /* The database connection whose status is desired */
+ int op, /* Status verb */
+ int *pCurrent, /* Write current value here */
+ int *pHighwtr, /* Write high-water mark here */
+ int resetFlag /* Reset high-water mark if true */
+){
+ sqlite3_int64 C = 0, H = 0;
+ int rc;
+#ifdef SQLITE_ENABLE_API_ARMOR
+ if( !sqlite3SafetyCheckOk(db) || pCurrent==0|| pHighwtr==0 ){
+ return SQLITE_MISUSE_BKPT;
+ }
+#endif
+ rc = sqlite3_db_status64(db, op, &C, &H, resetFlag);
+ if( rc==0 ){
+ *pCurrent = C & 0x7fffffff;
+ *pHighwtr = H & 0x7fffffff;
+ }
+ return rc;
+}
+
/************** End of status.c **********************************************/
/************** Begin file date.c ********************************************/
/*
@@ -20927,7 +25470,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.
@@ -20936,7 +25479,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
@@ -20988,12 +25531,14 @@ struct DateTime {
int tz; /* Timezone offset in minutes */
double s; /* Seconds */
char validJD; /* True (1) if iJD is valid */
- char rawS; /* Raw numeric value stored in s */
char validYMD; /* True (1) if Y,M,D are valid */
char validHMS; /* True (1) if h,m,s are valid */
- char validTZ; /* True (1) if tz is valid */
- char tzSet; /* Timezone was set explicitly */
- char isError; /* An overflow has occurred */
+ char nFloor; /* Days to implement "floor" */
+ unsigned rawS : 1; /* Raw numeric value stored in s */
+ unsigned isError : 1; /* An overflow has occurred */
+ unsigned useSubsec : 1; /* Display subsecond precision */
+ unsigned isUtc : 1; /* Time is known to be UTC */
+ unsigned isLocal : 1; /* Time is known to be localtime */
};
@@ -21026,8 +25571,8 @@ struct DateTime {
*/
static int getDigits(const char *zDate, const char *zFormat, ...){
/* The aMx[] array translates the 3rd character of each format
- ** spec into a max size: a b c d e f */
- static const u16 aMx[] = { 12, 14, 24, 31, 59, 9999 };
+ ** spec into a max size: a b c d e f */
+ static const u16 aMx[] = { 12, 14, 24, 31, 59, 14712 };
va_list ap;
int cnt = 0;
char nextC;
@@ -21091,6 +25636,8 @@ static int parseTimezone(const char *zDate, DateTime *p){
sgn = +1;
}else if( c=='Z' || c=='z' ){
zDate++;
+ p->isLocal = 0;
+ p->isUtc = 1;
goto zulu_time;
}else{
return c!=0;
@@ -21101,9 +25648,12 @@ static int parseTimezone(const char *zDate, DateTime *p){
}
zDate += 5;
p->tz = sgn*(nMn + nHr*60);
+ if( p->tz==0 ){ /* Forum post 2025-09-17T10:12:14z */
+ p->isLocal = 0;
+ p->isUtc = 1;
+ }
zulu_time:
while( sqlite3Isspace(*zDate) ){ zDate++; }
- p->tzSet = 1;
return *zDate!=0;
}
@@ -21136,6 +25686,9 @@ static int parseHhMmSs(const char *zDate, DateTime *p){
zDate++;
}
ms /= rScale;
+ /* Truncate to avoid problems with sub-milliseconds
+ ** rounding. https://sqlite.org/forum/forumpost/766a2c9231 */
+ if( ms>0.999 ) ms = 0.999;
}
}else{
s = 0;
@@ -21147,7 +25700,6 @@ static int parseHhMmSs(const char *zDate, DateTime *p){
p->m = m;
p->s = s + ms;
if( parseTimezone(zDate, p) ) return 1;
- p->validTZ = (p->tz!=0)?1:0;
return 0;
}
@@ -21186,23 +25738,48 @@ static void computeJD(DateTime *p){
Y--;
M += 12;
}
- A = Y/100;
- B = 2 - A + (A/4);
+ A = (Y+4800)/100;
+ B = 38 - A + (A/4);
X1 = 36525*(Y+4716)/100;
X2 = 306001*(M+1)/10000;
p->iJD = (sqlite3_int64)((X1 + X2 + D + B - 1524.5 ) * 86400000);
p->validJD = 1;
if( p->validHMS ){
- p->iJD += p->h*3600000 + p->m*60000 + (sqlite3_int64)(p->s*1000);
- if( p->validTZ ){
+ p->iJD += p->h*3600000 + p->m*60000 + (sqlite3_int64)(p->s*1000 + 0.5);
+ if( p->tz ){
p->iJD -= p->tz*60000;
p->validYMD = 0;
p->validHMS = 0;
- p->validTZ = 0;
+ p->tz = 0;
+ p->isUtc = 1;
+ p->isLocal = 0;
}
}
}
+/*
+** Given the YYYY-MM-DD information current in p, determine if there
+** is day-of-month overflow and set nFloor to the number of days that
+** would need to be subtracted from the date in order to bring the
+** date back to the end of the month.
+*/
+static void computeFloor(DateTime *p){
+ assert( p->validYMD || p->isError );
+ assert( p->D>=0 && p->D<=31 );
+ assert( p->M>=0 && p->M<=12 );
+ if( p->D<=28 ){
+ p->nFloor = 0;
+ }else if( (1<M) & 0x15aa ){
+ p->nFloor = 0;
+ }else if( p->M!=2 ){
+ p->nFloor = (p->D==31);
+ }else if( p->Y%4!=0 || (p->Y%100==0 && p->Y%400!=0) ){
+ p->nFloor = p->D - 28;
+ }else{
+ p->nFloor = p->D - 29;
+ }
+}
+
/*
** Parse dates of the form
**
@@ -21241,12 +25818,16 @@ static int parseYyyyMmDd(const char *zDate, DateTime *p){
p->Y = neg ? -Y : Y;
p->M = M;
p->D = D;
- if( p->validTZ ){
+ computeFloor(p);
+ if( p->tz ){
computeJD(p);
}
return 0;
}
+
+static void clearYMD_HMS_TZ(DateTime *p); /* Forward declaration */
+
/*
** Set the time to the current time reported by the VFS.
**
@@ -21256,6 +25837,9 @@ static int setDateTimeToCurrent(sqlite3_context *context, DateTime *p){
p->iJD = sqlite3StmtCurrentTime(context);
if( p->iJD>0 ){
p->validJD = 1;
+ p->isUtc = 1;
+ p->isLocal = 0;
+ clearYMD_HMS_TZ(p);
return 0;
}else{
return 1;
@@ -21284,7 +25868,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
@@ -21294,8 +25878,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;
@@ -21305,9 +25889,14 @@ 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)>0 ){
setRawDateNumber(p, r);
return 0;
+ }else if( (sqlite3StrICmp(zDate,"subsec")==0
+ || sqlite3StrICmp(zDate,"subsecond")==0)
+ && sqlite3NotPureFunc(context) ){
+ p->useSubsec = 1;
+ return setDateTimeToCurrent(context, p);
}
return 1;
}
@@ -21316,7 +25905,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)
@@ -21334,7 +25923,7 @@ static int validJulianDay(sqlite3_int64 iJD){
** Compute the Year, Month, and Day from the julian day number.
*/
static void computeYMD(DateTime *p){
- int Z, A, B, C, D, E, X1;
+ int Z, alpha, A, B, C, D, E, X1;
if( p->validYMD ) return;
if( !p->validJD ){
p->Y = 2000;
@@ -21345,8 +25934,8 @@ static void computeYMD(DateTime *p){
return;
}else{
Z = (int)((p->iJD + 43200000)/86400000);
- A = (int)((Z - 1867216.25)/36524.25);
- A = Z + 1 + A - (A/4);
+ alpha = (int)((Z + 32044.75)/36524.25) - 52;
+ A = Z + 1 + alpha - ((alpha+100)/4) + 25;
B = A + 1524;
C = (int)((B - 122.1)/365.25);
D = (36525*(C&32767))/100;
@@ -21363,17 +25952,14 @@ static void computeYMD(DateTime *p){
** Compute the Hour, Minute, and Seconds from the julian day number.
*/
static void computeHMS(DateTime *p){
- int s;
+ int day_ms, day_min; /* milliseconds, minutes into the day */
if( p->validHMS ) return;
computeJD(p);
- s = (int)((p->iJD + 43200000) % 86400000);
- p->s = s/1000.0;
- s = (int)p->s;
- p->s -= s;
- p->h = s/3600;
- s -= p->h*3600;
- p->m = s/60;
- p->s += s - p->m*60;
+ day_ms = (int)((p->iJD + 43200000) % 86400000);
+ p->s = (day_ms % 60000)/1000.0;
+ day_min = day_ms/60000;
+ p->m = day_min % 60;
+ p->h = day_min / 60;
p->rawS = 0;
p->validHMS = 1;
}
@@ -21392,20 +25978,20 @@ static void computeYMD_HMS(DateTime *p){
static void clearYMD_HMS_TZ(DateTime *p){
p->validYMD = 0;
p->validHMS = 0;
- p->validTZ = 0;
+ p->tz = 0;
}
#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 \
@@ -21420,8 +26006,10 @@ static void clearYMD_HMS_TZ(DateTime *p){
** is available. This routine returns 0 on success and
** non-zero on any kind of error.
**
-** If the sqlite3GlobalConfig.bLocaltimeFault variable is true then this
-** routine will always fail.
+** If the sqlite3GlobalConfig.bLocaltimeFault variable is non-zero then this
+** routine will always fail. If bLocaltimeFault is nonzero and
+** sqlite3GlobalConfig.xAltLocaltime is not NULL, then xAltLocaltime() is
+** invoked in place of the OS-defined localtime() function.
**
** EVIDENCE-OF: R-62172-00036 In this implementation, the standard C
** library function localtime_r() is used to assist in the calculation of
@@ -21432,19 +26020,35 @@ 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);
#ifndef SQLITE_UNTESTABLE
- if( sqlite3GlobalConfig.bLocaltimeFault ) pX = 0;
+ if( sqlite3GlobalConfig.bLocaltimeFault ){
+ if( sqlite3GlobalConfig.xAltLocaltime!=0
+ && 0==sqlite3GlobalConfig.xAltLocaltime((const void*)t,(void*)pTm)
+ ){
+ pX = pTm;
+ }else{
+ pX = 0;
+ }
+ }
#endif
if( pX ) *pTm = *pX;
+#if SQLITE_THREADSAFE>0
sqlite3_mutex_leave(mutex);
+#endif
rc = pX==0;
#else
#ifndef SQLITE_UNTESTABLE
- if( sqlite3GlobalConfig.bLocaltimeFault ) return 1;
+ if( sqlite3GlobalConfig.bLocaltimeFault ){
+ if( sqlite3GlobalConfig.xAltLocaltime!=0 ){
+ return sqlite3GlobalConfig.xAltLocaltime((const void*)t,(void*)pTm);
+ }else{
+ return 1;
+ }
+ }
#endif
#if HAVE_LOCALTIME_R
rc = localtime_r(t, pTm)==0;
@@ -21459,67 +26063,56 @@ static int osLocaltime(time_t *t, struct tm *pTm){
#ifndef SQLITE_OMIT_LOCALTIME
/*
-** Compute the difference (in milliseconds) between localtime and UTC
-** (a.k.a. GMT) for the time value p where p is in UTC. If no error occurs,
-** return this value and set *pRc to SQLITE_OK.
-**
-** Or, if an error does occur, set *pRc to SQLITE_ERROR. The returned value
-** is undefined in this case.
+** Assuming the input DateTime is UTC, move it to its localtime equivalent.
*/
-static sqlite3_int64 localtimeOffset(
- DateTime *p, /* Date at which to calculate offset */
- sqlite3_context *pCtx, /* Write error here if one occurs */
- int *pRc /* OUT: Error code. SQLITE_OK or ERROR */
+static int toLocaltime(
+ DateTime *p, /* Date at which to calculate offset */
+ sqlite3_context *pCtx /* Write error here if one occurs */
){
- DateTime x, y;
time_t t;
struct tm sLocal;
+ int iYearDiff;
/* Initialize the contents of sLocal to avoid a compiler warning. */
memset(&sLocal, 0, sizeof(sLocal));
- x = *p;
- computeYMD_HMS(&x);
- if( x.Y<1971 || x.Y>=2038 ){
+ computeJD(p);
+ if( p->iJD<2108667600*(i64)100000 /* 1970-01-01 */
+ || p->iJD>2130141456*(i64)100000 /* 2038-01-18 */
+ ){
/* EVIDENCE-OF: R-55269-29598 The localtime_r() C function normally only
** works for years between 1970 and 2037. For dates outside this range,
** SQLite attempts to map the year into an equivalent year within this
** range, do the calculation, then map the year back.
*/
- x.Y = 2000;
- x.M = 1;
- x.D = 1;
- x.h = 0;
- x.m = 0;
- x.s = 0.0;
- } else {
- int s = (int)(x.s + 0.5);
- x.s = s;
+ DateTime x = *p;
+ computeYMD_HMS(&x);
+ iYearDiff = (2000 + x.Y%4) - x.Y;
+ x.Y += iYearDiff;
+ x.validJD = 0;
+ computeJD(&x);
+ t = (time_t)(x.iJD/1000 - 21086676*(i64)10000);
+ }else{
+ iYearDiff = 0;
+ t = (time_t)(p->iJD/1000 - 21086676*(i64)10000);
}
- x.tz = 0;
- x.validJD = 0;
- computeJD(&x);
- t = (time_t)(x.iJD/1000 - 21086676*(i64)10000);
if( osLocaltime(&t, &sLocal) ){
sqlite3_result_error(pCtx, "local time unavailable", -1);
- *pRc = SQLITE_ERROR;
- return 0;
+ return SQLITE_ERROR;
}
- y.Y = sLocal.tm_year + 1900;
- y.M = sLocal.tm_mon + 1;
- y.D = sLocal.tm_mday;
- y.h = sLocal.tm_hour;
- y.m = sLocal.tm_min;
- y.s = sLocal.tm_sec;
- y.validYMD = 1;
- y.validHMS = 1;
- y.validJD = 0;
- y.rawS = 0;
- y.validTZ = 0;
- y.isError = 0;
- computeJD(&y);
- *pRc = SQLITE_OK;
- return y.iJD - x.iJD;
+ p->Y = sLocal.tm_year + 1900 - iYearDiff;
+ p->M = sLocal.tm_mon + 1;
+ p->D = sLocal.tm_mday;
+ p->h = sLocal.tm_hour;
+ p->m = sLocal.tm_min;
+ p->s = sLocal.tm_sec + (p->iJD%1000)*0.001;
+ p->validYMD = 1;
+ p->validHMS = 1;
+ p->validJD = 0;
+ p->rawS = 0;
+ p->tz = 0;
+ p->isError = 0;
+ return SQLITE_OK;
}
#endif /* SQLITE_OMIT_LOCALTIME */
@@ -21532,20 +26125,38 @@ static sqlite3_int64 localtimeOffset(
** of several units of time.
*/
static const struct {
- u8 eType; /* Transformation type code */
- u8 nName; /* Length of th name */
- char *zName; /* Name of the transformation */
- double rLimit; /* Maximum NNN value for this transform */
- double rXform; /* Constant used for this transform */
+ u8 nName; /* Length of the name */
+ char zName[7]; /* Name of the transformation */
+ float rLimit; /* Maximum NNN value for this transform */
+ float 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", 4.6427e+14, 1.0 },
+ /* 1 */ { 6, "minute", 7.7379e+12, 60.0 },
+ /* 2 */ { 4, "hour", 1.2897e+11, 3600.0 },
+ /* 3 */ { 3, "day", 5373485.0, 86400.0 },
+ /* 4 */ { 5, "month", 176546.0, 2592000.0 },
+ /* 5 */ { 4, "year", 14713.0, 31536000.0 },
};
+/*
+** If the DateTime p is raw number, try to figure out if it is
+** a julian day number of a unix timestamp. Set the p value
+** appropriately.
+*/
+static void autoAdjustDate(DateTime *p){
+ if( !p->rawS || p->validJD ){
+ p->rawS = 0;
+ }else if( p->s>=-21086676*(i64)10000 /* -4713-11-24 12:00:00 */
+ && p->s<=(25340230*(i64)10000)+799 /* 9999-12-31 23:59:59 */
+ ){
+ double r = p->s*1000.0 + 210866760000000.0;
+ clearYMD_HMS_TZ(p);
+ p->iJD = (sqlite3_int64)(r + 0.5);
+ p->validJD = 1;
+ p->rawS = 0;
+ }
+}
+
/*
** Process a modifier to a date-time stamp. The modifiers are
** as follows:
@@ -21556,14 +26167,20 @@ static const struct {
** NNN.NNNN seconds
** NNN months
** NNN years
+** +/-YYYY-MM-DD HH:MM:SS.SSS
+** ceiling
+** floor
** start of month
** start of year
** start of week
** start of day
** weekday N
** unixepoch
+** auto
** localtime
** utc
+** subsec
+** subsecond
**
** Return 0 on success and 1 if there is any kind of error. If the error
** is in a system call (i.e. localtime()), then an error message is written
@@ -21574,11 +26191,75 @@ static int parseModifier(
sqlite3_context *pCtx, /* Function context */
const char *z, /* The text of the modifier */
int n, /* Length of zMod in bytes */
- DateTime *p /* The date/time value to be modified */
+ DateTime *p, /* The date/time value to be modified */
+ int idx /* Parameter index of the modifier */
){
int rc = 1;
double r;
switch(sqlite3UpperToLower[(u8)z[0]] ){
+ case 'a': {
+ /*
+ ** auto
+ **
+ ** If rawS is available, then interpret as a julian day number, or
+ ** a unix timestamp, depending on its magnitude.
+ */
+ if( sqlite3_stricmp(z, "auto")==0 ){
+ if( idx>1 ) return 1; /* IMP: R-33611-57934 */
+ autoAdjustDate(p);
+ rc = 0;
+ }
+ break;
+ }
+ case 'c': {
+ /*
+ ** ceiling
+ **
+ ** Resolve day-of-month overflow by rolling forward into the next
+ ** month. As this is the default action, this modifier is really
+ ** a no-op that is only included for symmetry. See "floor".
+ */
+ if( sqlite3_stricmp(z, "ceiling")==0 ){
+ computeJD(p);
+ clearYMD_HMS_TZ(p);
+ rc = 0;
+ p->nFloor = 0;
+ }
+ break;
+ }
+ case 'f': {
+ /*
+ ** floor
+ **
+ ** Resolve day-of-month overflow by rolling back to the end of the
+ ** previous month.
+ */
+ if( sqlite3_stricmp(z, "floor")==0 ){
+ computeJD(p);
+ p->iJD -= p->nFloor*86400000;
+ clearYMD_HMS_TZ(p);
+ rc = 0;
+ }
+ break;
+ }
+ case 'j': {
+ /*
+ ** julianday
+ **
+ ** Always interpret the prior number as a julian-day value. If this
+ ** is not the first modifier, or if the prior argument is not a numeric
+ ** value in the allowed range of julian day numbers understood by
+ ** SQLite (0..5373484.5) then the result will be NULL.
+ */
+ if( sqlite3_stricmp(z, "julianday")==0 ){
+ if( idx>1 ) return 1; /* IMP: R-31176-64601 */
+ if( p->validJD && p->rawS ){
+ rc = 0;
+ p->rawS = 0;
+ }
+ }
+ break;
+ }
#ifndef SQLITE_OMIT_LOCALTIME
case 'l': {
/* localtime
@@ -21587,9 +26268,9 @@ static int parseModifier(
** show local time.
*/
if( sqlite3_stricmp(z, "localtime")==0 && sqlite3NotPureFunc(pCtx) ){
- computeJD(p);
- p->iJD += localtimeOffset(p, pCtx, &rc);
- clearYMD_HMS_TZ(p);
+ rc = p->isLocal ? SQLITE_OK : toLocaltime(p, pCtx);
+ p->isUtc = 0;
+ p->isLocal = 1;
}
break;
}
@@ -21602,10 +26283,11 @@ static int parseModifier(
** seconds since 1970. Convert to a real julian day number.
*/
if( sqlite3_stricmp(z, "unixepoch")==0 && p->rawS ){
+ if( idx>1 ) return 1; /* IMP: R-49255-55373 */
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;
@@ -21613,19 +26295,33 @@ static int parseModifier(
}
#ifndef SQLITE_OMIT_LOCALTIME
else if( sqlite3_stricmp(z, "utc")==0 && sqlite3NotPureFunc(pCtx) ){
- if( p->tzSet==0 ){
- sqlite3_int64 c1;
+ if( p->isUtc==0 ){
+ i64 iOrigJD; /* Original localtime */
+ i64 iGuess; /* Guess at the corresponding utc time */
+ int cnt = 0; /* Safety to prevent infinite loop */
+ i64 iErr; /* Guess is off by this much */
+
computeJD(p);
- c1 = localtimeOffset(p, pCtx, &rc);
- if( rc==SQLITE_OK ){
- p->iJD -= c1;
- clearYMD_HMS_TZ(p);
- p->iJD += c1 - localtimeOffset(p, pCtx, &rc);
- }
- p->tzSet = 1;
- }else{
- rc = SQLITE_OK;
+ iGuess = iOrigJD = p->iJD;
+ iErr = 0;
+ do{
+ DateTime new;
+ memset(&new, 0, sizeof(new));
+ iGuess -= iErr;
+ new.iJD = iGuess;
+ new.validJD = 1;
+ rc = toLocaltime(&new, pCtx);
+ if( rc ) return rc;
+ computeJD(&new);
+ iErr = new.iJD - iOrigJD;
+ }while( iErr && cnt++<3 );
+ memset(p, 0, sizeof(*p));
+ p->iJD = iGuess;
+ p->validJD = 1;
+ p->isUtc = 1;
+ p->isLocal = 0;
}
+ rc = SQLITE_OK;
}
#endif
break;
@@ -21639,11 +26335,11 @@ 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)
- && (n=(int)r)==r && n>=0 && r<7 ){
+ && sqlite3AtoF(&z[8], &r)>0
+ && r>=0.0 && r<7.0 && (n=(int)r)==r ){
sqlite3_int64 Z;
computeYMD_HMS(p);
- p->validTZ = 0;
+ p->tz = 0;
p->validJD = 0;
computeJD(p);
Z = ((p->iJD + 129600000)/86400000) % 7;
@@ -21660,8 +26356,22 @@ static int parseModifier(
**
** Move the date backwards to the beginning of the current day,
** or month or year.
+ **
+ ** subsecond
+ ** subsec
+ **
+ ** Show subsecond precision in the output of datetime() and
+ ** unixepoch() and strftime('%s').
*/
- if( sqlite3_strnicmp(z, "start of ", 9)!=0 ) break;
+ if( sqlite3_strnicmp(z, "start of ", 9)!=0 ){
+ if( sqlite3_stricmp(z, "subsec")==0
+ || sqlite3_stricmp(z, "subsecond")==0
+ ){
+ p->useSubsec = 1;
+ rc = 0;
+ }
+ break;
+ }
if( !p->validJD && !p->validYMD && !p->validHMS ) break;
z += 9;
computeYMD(p);
@@ -21669,7 +26379,7 @@ static int parseModifier(
p->h = p->m = 0;
p->s = 0.0;
p->rawS = 0;
- p->validTZ = 0;
+ p->tz = 0;
p->validJD = 0;
if( sqlite3_stricmp(z,"month")==0 ){
p->D = 1;
@@ -21696,19 +26406,81 @@ static int parseModifier(
case '8':
case '9': {
double rRounder;
- int i;
- for(n=1; z[n] && z[n]!=':' && !sqlite3Isspace(z[n]); n++){}
- if( !sqlite3AtoF(z, &r, n, SQLITE_UTF8) ){
- rc = 1;
+ int i, rx;
+ int Y,M,D,h,m,x;
+ const char *z2 = z;
+ char *zCopy;
+ sqlite3 *db = sqlite3_context_db_handle(pCtx);
+ char z0 = z[0];
+ for(n=1; z[n]; n++){
+ if( z[n]==':' ) break;
+ if( sqlite3Isspace(z[n]) ) break;
+ if( z[n]=='-' ){
+ if( n==5 && getDigits(&z[1], "40f", &Y)==1 ) break;
+ if( n==6 && getDigits(&z[1], "50f", &Y)==1 ) break;
+ }
+ }
+ zCopy = sqlite3DbStrNDup(db, z, n);
+ if( zCopy==0 ) break;
+ rx = sqlite3AtoF(zCopy, &r)<=0;
+ sqlite3DbFree(db, zCopy);
+ if( rx ){
+ assert( rc==1 );
break;
}
- if( z[n]==':' ){
+ if( z[n]=='-' ){
+ /* A modifier of the form (+|-)YYYY-MM-DD adds or subtracts the
+ ** specified number of years, months, and days. MM is limited to
+ ** the range 0-11 and DD is limited to 0-30.
+ */
+ if( z0!='+' && z0!='-' ) break; /* Must start with +/- */
+ if( n==5 ){
+ if( getDigits(&z[1], "40f-20a-20d", &Y, &M, &D)!=3 ) break;
+ }else{
+ assert( n==6 );
+ if( getDigits(&z[1], "50f-20a-20d", &Y, &M, &D)!=3 ) break;
+ z++;
+ }
+ if( M>=12 ) break; /* M range 0..11 */
+ if( D>=31 ) break; /* D range 0..30 */
+ computeYMD_HMS(p);
+ p->validJD = 0;
+ if( z0=='-' ){
+ p->Y -= Y;
+ p->M -= M;
+ D = -D;
+ }else{
+ p->Y += Y;
+ p->M += M;
+ }
+ x = p->M>0 ? (p->M-1)/12 : (p->M-12)/12;
+ p->Y += x;
+ p->M -= x*12;
+ computeFloor(p);
+ computeJD(p);
+ p->validHMS = 0;
+ p->validYMD = 0;
+ p->iJD += (i64)D*86400000;
+ if( z[11]==0 ){
+ rc = 0;
+ break;
+ }
+ if( sqlite3Isspace(z[11])
+ && getDigits(&z[12], "20c:20e", &h, &m)==2
+ ){
+ z2 = &z[12];
+ n = 2;
+ }else{
+ break;
+ }
+ }
+ if( z2[n]==':' ){
/* A modifier of the form (+|-)HH:MM:SS.FFF adds (or subtracts) the
** specified number of hours, minutes, seconds, and fractional seconds
** to the time. The ".FFF" may be omitted. The ":SS.FFF" may be
** omitted.
*/
- const char *z2 = z;
+
DateTime tx;
sqlite3_int64 day;
if( !sqlite3Isdigit(*z2) ) z2++;
@@ -21718,7 +26490,7 @@ static int parseModifier(
tx.iJD -= 43200000;
day = tx.iJD/86400000;
tx.iJD -= day*86400000;
- if( z[0]=='-' ) tx.iJD = -tx.iJD;
+ if( z0=='-' ) tx.iJD = -tx.iJD;
computeJD(p);
clearYMD_HMS_TZ(p);
p->iJD += tx.iJD;
@@ -21731,39 +26503,44 @@ static int parseModifier(
z += n;
while( sqlite3Isspace(*z) ) z++;
n = sqlite3Strlen30(z);
- if( n>10 || n<3 ) break;
+ if( n<3 || n>10 ) break;
if( sqlite3UpperToLower[(u8)z[n-1]]=='s' ) n--;
computeJD(p);
- rc = 1;
+ assert( rc==1 );
rRounder = r<0 ? -0.5 : +0.5;
+ p->nFloor = 0;
for(i=0; i-aXformType[i].rLimit && rM += (int)r;
x = p->M>0 ? (p->M-1)/12 : (p->M-12)/12;
p->Y += x;
p->M -= x*12;
+ computeFloor(p);
p->validJD = 0;
r -= (int)r;
break;
}
- case 2: { /* Special processing to add years */
+ case 5: { /* Special processing to add years */
int y = (int)r;
+ assert( strcmp(aXformType[5].zName,"year")==0 );
computeYMD_HMS(p);
+ assert( p->M>=0 && p->M<=12 );
p->Y += y;
+ computeFloor(p);
p->validJD = 0;
r -= (int)r;
break;
}
}
computeJD(p);
- p->iJD += (sqlite3_int64)(r*aXformType[i].rXform + rRounder);
+ p->iJD += (sqlite3_int64)(r*1000.0*aXformType[i].rXform + rRounder);
rc = 0;
break;
}
@@ -21788,9 +26565,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;
@@ -21798,6 +26575,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
@@ -21812,10 +26590,16 @@ static int isDate(
for(i=1; iisError || !validJulianDay(p->iJD) ) return 1;
+ if( argc==1 && p->validYMD && p->D>28 ){
+ /* Make sure a YYYY-MM-DD is normalized.
+ ** Example: 2023-02-31 -> 2023-03-03 */
+ assert( p->validJD );
+ p->validYMD = 0;
+ }
return 0;
}
@@ -21842,6 +26626,28 @@ static void juliandayFunc(
}
}
+/*
+** unixepoch( TIMESTRING, MOD, MOD, ...)
+**
+** Return the number of seconds (including fractional seconds) since
+** the unix epoch of 1970-01-01 00:00:00 GMT.
+*/
+static void unixepochFunc(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv
+){
+ DateTime x;
+ if( isDate(context, argc, argv, &x)==0 ){
+ computeJD(&x);
+ if( x.useSubsec ){
+ sqlite3_result_double(context, (x.iJD - 21086676*(i64)10000000)/1000.0);
+ }else{
+ sqlite3_result_int64(context, x.iJD/1000 - 21086676*(i64)10000);
+ }
+ }
+}
+
/*
** datetime( TIMESTRING, MOD, MOD, ...)
**
@@ -21854,11 +26660,51 @@ static void datetimeFunc(
){
DateTime x;
if( isDate(context, argc, argv, &x)==0 ){
- char zBuf[100];
+ int Y, s, n;
+ char zBuf[32];
computeYMD_HMS(&x);
- sqlite3_snprintf(sizeof(zBuf), zBuf, "%04d-%02d-%02d %02d:%02d:%02d",
- x.Y, x.M, x.D, x.h, x.m, (int)(x.s));
- sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
+ Y = x.Y;
+ if( Y<0 ) Y = -Y;
+ zBuf[1] = '0' + (Y/1000)%10;
+ zBuf[2] = '0' + (Y/100)%10;
+ zBuf[3] = '0' + (Y/10)%10;
+ zBuf[4] = '0' + (Y)%10;
+ zBuf[5] = '-';
+ zBuf[6] = '0' + (x.M/10)%10;
+ zBuf[7] = '0' + (x.M)%10;
+ zBuf[8] = '-';
+ zBuf[9] = '0' + (x.D/10)%10;
+ zBuf[10] = '0' + (x.D)%10;
+ zBuf[11] = ' ';
+ zBuf[12] = '0' + (x.h/10)%10;
+ zBuf[13] = '0' + (x.h)%10;
+ zBuf[14] = ':';
+ zBuf[15] = '0' + (x.m/10)%10;
+ zBuf[16] = '0' + (x.m)%10;
+ zBuf[17] = ':';
+ if( x.useSubsec ){
+ s = (int)(1000.0*x.s + 0.5);
+ zBuf[18] = '0' + (s/10000)%10;
+ zBuf[19] = '0' + (s/1000)%10;
+ zBuf[20] = '.';
+ zBuf[21] = '0' + (s/100)%10;
+ zBuf[22] = '0' + (s/10)%10;
+ zBuf[23] = '0' + (s)%10;
+ zBuf[24] = 0;
+ n = 24;
+ }else{
+ s = (int)x.s;
+ zBuf[18] = '0' + (s/10)%10;
+ zBuf[19] = '0' + (s)%10;
+ zBuf[20] = 0;
+ n = 20;
+ }
+ if( x.Y<0 ){
+ zBuf[0] = '-';
+ sqlite3_result_text(context, zBuf, n, SQLITE_TRANSIENT);
+ }else{
+ sqlite3_result_text(context, &zBuf[1], n-1, SQLITE_TRANSIENT);
+ }
}
}
@@ -21874,10 +26720,33 @@ static void timeFunc(
){
DateTime x;
if( isDate(context, argc, argv, &x)==0 ){
- char zBuf[100];
+ int s, n;
+ char zBuf[16];
computeHMS(&x);
- sqlite3_snprintf(sizeof(zBuf), zBuf, "%02d:%02d:%02d", x.h, x.m, (int)x.s);
- sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
+ zBuf[0] = '0' + (x.h/10)%10;
+ zBuf[1] = '0' + (x.h)%10;
+ zBuf[2] = ':';
+ zBuf[3] = '0' + (x.m/10)%10;
+ zBuf[4] = '0' + (x.m)%10;
+ zBuf[5] = ':';
+ if( x.useSubsec ){
+ s = (int)(1000.0*x.s + 0.5);
+ zBuf[6] = '0' + (s/10000)%10;
+ zBuf[7] = '0' + (s/1000)%10;
+ zBuf[8] = '.';
+ zBuf[9] = '0' + (s/100)%10;
+ zBuf[10] = '0' + (s/10)%10;
+ zBuf[11] = '0' + (s)%10;
+ zBuf[12] = 0;
+ n = 12;
+ }else{
+ s = (int)x.s;
+ zBuf[6] = '0' + (s/10)%10;
+ zBuf[7] = '0' + (s)%10;
+ zBuf[8] = 0;
+ n = 8;
+ }
+ sqlite3_result_text(context, zBuf, n, SQLITE_TRANSIENT);
}
}
@@ -21893,29 +26762,108 @@ static void dateFunc(
){
DateTime x;
if( isDate(context, argc, argv, &x)==0 ){
- char zBuf[100];
+ int Y;
+ char zBuf[16];
computeYMD(&x);
- sqlite3_snprintf(sizeof(zBuf), zBuf, "%04d-%02d-%02d", x.Y, x.M, x.D);
- sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
+ Y = x.Y;
+ if( Y<0 ) Y = -Y;
+ zBuf[1] = '0' + (Y/1000)%10;
+ zBuf[2] = '0' + (Y/100)%10;
+ zBuf[3] = '0' + (Y/10)%10;
+ zBuf[4] = '0' + (Y)%10;
+ zBuf[5] = '-';
+ zBuf[6] = '0' + (x.M/10)%10;
+ zBuf[7] = '0' + (x.M)%10;
+ zBuf[8] = '-';
+ zBuf[9] = '0' + (x.D/10)%10;
+ zBuf[10] = '0' + (x.D)%10;
+ zBuf[11] = 0;
+ if( x.Y<0 ){
+ zBuf[0] = '-';
+ sqlite3_result_text(context, zBuf, 11, SQLITE_TRANSIENT);
+ }else{
+ sqlite3_result_text(context, &zBuf[1], 10, SQLITE_TRANSIENT);
+ }
}
}
+/*
+** Compute the number of days after the most recent January 1.
+**
+** In other words, compute the zero-based day number for the
+** current year:
+**
+** Jan01 = 0, Jan02 = 1, ..., Jan31 = 30, Feb01 = 31, ...
+** Dec31 = 364 or 365.
+*/
+static int daysAfterJan01(DateTime *pDate){
+ DateTime jan01 = *pDate;
+ assert( jan01.validYMD );
+ assert( jan01.validHMS );
+ assert( pDate->validJD );
+ jan01.validJD = 0;
+ jan01.M = 1;
+ jan01.D = 1;
+ computeJD(&jan01);
+ return (int)((pDate->iJD-jan01.iJD+43200000)/86400000);
+}
+
+/*
+** Return the number of days after the most recent Monday.
+**
+** In other words, return the day of the week according
+** to this code:
+**
+** 0=Monday, 1=Tuesday, 2=Wednesday, ..., 6=Sunday.
+*/
+static int daysAfterMonday(DateTime *pDate){
+ assert( pDate->validJD );
+ return (int)((pDate->iJD+43200000)/86400000) % 7;
+}
+
+/*
+** Return the number of days after the most recent Sunday.
+**
+** In other words, return the day of the week according
+** to this code:
+**
+** 0=Sunday, 1=Monday, 2=Tuesday, ..., 6=Saturday
+*/
+static int daysAfterSunday(DateTime *pDate){
+ assert( pDate->validJD );
+ return (int)((pDate->iJD+129600000)/86400000) % 7;
+}
+
/*
** strftime( FORMAT, TIMESTRING, MOD, MOD, ...)
**
** Return a string described by FORMAT. Conversions as follows:
**
-** %d day of month
+** %d day of month 01-31
+** %e day of month 1-31
** %f ** fractional seconds SS.SSS
+** %F ISO date. YYYY-MM-DD
+** %G ISO year corresponding to %V 0000-9999.
+** %g 2-digit ISO year corresponding to %V 00-99
** %H hour 00-24
-** %j day of year 000-366
+** %k hour 0-24 (leading zero converted to space)
+** %I hour 01-12
+** %j day of year 001-366
** %J ** julian day number
+** %l hour 1-12 (leading zero converted to space)
** %m month 01-12
** %M minute 00-59
+** %p "AM" or "PM"
+** %P "am" or "pm"
+** %R time as HH:MM
** %s seconds since 1970-01-01
** %S seconds 00-59
-** %w day of week 0-6 sunday==0
-** %W week of year 00-53
+** %T time as HH:MM:SS
+** %u day of week 1-7 Monday==1, Sunday==7
+** %w day of week 0-6 Sunday==0, Monday==1
+** %U week of year 00-53 (First Sunday is start of week 01)
+** %V week of year 01-53 (First week containing Thursday is week 01)
+** %W week of year 00-53 (First Monday is start of week 01)
** %Y year 0000-9999
** %% %
*/
@@ -21925,131 +26873,161 @@ static void strftimeFunc(
sqlite3_value **argv
){
DateTime x;
- u64 n;
size_t i,j;
- char *z;
sqlite3 *db;
const char *zFmt;
- char zBuf[100];
+ sqlite3_str sRes;
+
+
if( argc==0 ) return;
zFmt = (const char*)sqlite3_value_text(argv[0]);
if( zFmt==0 || isDate(context, argc-1, argv+1, &x) ) return;
db = sqlite3_context_db_handle(context);
- for(i=0, n=1; zFmt[i]; i++, n++){
- if( zFmt[i]=='%' ){
- switch( zFmt[i+1] ){
- case 'd':
- case 'H':
- case 'm':
- case 'M':
- case 'S':
- case 'W':
- n++;
- /* fall thru */
- case 'w':
- case '%':
- break;
- case 'f':
- n += 8;
- break;
- case 'j':
- n += 3;
- break;
- case 'Y':
- n += 8;
- break;
- case 's':
- case 'J':
- n += 50;
- break;
- default:
- return; /* ERROR. return a NULL */
- }
- i++;
- }
- }
- testcase( n==sizeof(zBuf)-1 );
- testcase( n==sizeof(zBuf) );
- testcase( n==(u64)db->aLimit[SQLITE_LIMIT_LENGTH]+1 );
- testcase( n==(u64)db->aLimit[SQLITE_LIMIT_LENGTH] );
- if( n(u64)db->aLimit[SQLITE_LIMIT_LENGTH] ){
- sqlite3_result_error_toobig(context);
- return;
- }else{
- z = sqlite3DbMallocRawNN(db, (int)n);
- if( z==0 ){
- sqlite3_result_error_nomem(context);
- return;
- }
- }
+ sqlite3StrAccumInit(&sRes, 0, 0, 0, db->aLimit[SQLITE_LIMIT_LENGTH]);
+
computeJD(&x);
computeYMD_HMS(&x);
for(i=j=0; zFmt[i]; i++){
- if( zFmt[i]!='%' ){
- z[j++] = zFmt[i];
- }else{
- i++;
- switch( zFmt[i] ){
- case 'd': sqlite3_snprintf(3, &z[j],"%02d",x.D); j+=2; break;
- case 'f': {
- double s = x.s;
- if( s>59.999 ) s = 59.999;
- sqlite3_snprintf(7, &z[j],"%06.3f", s);
- j += sqlite3Strlen30(&z[j]);
- break;
- }
- case 'H': sqlite3_snprintf(3, &z[j],"%02d",x.h); j+=2; break;
- case 'W': /* Fall thru */
- case 'j': {
- int nDay; /* Number of days since 1st day of year */
- DateTime y = x;
- y.validJD = 0;
- y.M = 1;
- y.D = 1;
- computeJD(&y);
- nDay = (int)((x.iJD-y.iJD+43200000)/86400000);
- if( zFmt[i]=='W' ){
- int wd; /* 0=Monday, 1=Tuesday, ... 6=Sunday */
- wd = (int)(((x.iJD+43200000)/86400000)%7);
- sqlite3_snprintf(3, &z[j],"%02d",(nDay+7-wd)/7);
- j += 2;
- }else{
- sqlite3_snprintf(4, &z[j],"%03d",nDay+1);
- j += 3;
- }
- break;
- }
- case 'J': {
- sqlite3_snprintf(20, &z[j],"%.16g",x.iJD/86400000.0);
- j+=sqlite3Strlen30(&z[j]);
- break;
- }
- case 'm': sqlite3_snprintf(3, &z[j],"%02d",x.M); j+=2; break;
- case 'M': sqlite3_snprintf(3, &z[j],"%02d",x.m); j+=2; break;
- case 's': {
- sqlite3_snprintf(30,&z[j],"%lld",
- (i64)(x.iJD/1000 - 21086676*(i64)10000));
- j += sqlite3Strlen30(&z[j]);
- break;
+ char cf;
+ if( zFmt[i]!='%' ) continue;
+ if( j59.999) ) s = 59.999;
+ sqlite3_str_appendf(&sRes, "%06.3f", s);
+ break;
+ }
+ case 'F': {
+ sqlite3_str_appendf(&sRes, "%04d-%02d-%02d", x.Y, x.M, x.D);
+ break;
+ }
+ case 'G': /* Fall thru */
+ case 'g': {
+ DateTime y = x;
+ assert( y.validJD );
+ /* Move y so that it is the Thursday in the same week as x */
+ y.iJD += (3 - daysAfterMonday(&x))*86400000;
+ y.validYMD = 0;
+ computeYMD(&y);
+ if( cf=='g' ){
+ sqlite3_str_appendf(&sRes, "%02d", y.Y%100);
+ }else{
+ sqlite3_str_appendf(&sRes, "%04d", y.Y);
}
- case 'S': sqlite3_snprintf(3,&z[j],"%02d",(int)x.s); j+=2; break;
- case 'w': {
- z[j++] = (char)(((x.iJD+129600000)/86400000) % 7) + '0';
- break;
+ break;
+ }
+ case 'H':
+ case 'k': {
+ sqlite3_str_appendf(&sRes, cf=='H' ? "%02d" : "%2d", x.h);
+ break;
+ }
+ case 'I': /* Fall thru */
+ case 'l': {
+ int h = x.h;
+ if( h>12 ) h -= 12;
+ if( h==0 ) h = 12;
+ sqlite3_str_appendf(&sRes, cf=='I' ? "%02d" : "%2d", h);
+ break;
+ }
+ case 'j': { /* Day of year. Jan01==1, Jan02==2, and so forth */
+ sqlite3_str_appendf(&sRes,"%03d",daysAfterJan01(&x)+1);
+ break;
+ }
+ case 'J': { /* Julian day number. (Non-standard) */
+ sqlite3_str_appendf(&sRes,"%.16g",x.iJD/86400000.0);
+ break;
+ }
+ case 'm': {
+ sqlite3_str_appendf(&sRes,"%02d",x.M);
+ break;
+ }
+ case 'M': {
+ sqlite3_str_appendf(&sRes,"%02d",x.m);
+ break;
+ }
+ case 'p': /* Fall thru */
+ case 'P': {
+ if( x.h>=12 ){
+ sqlite3_str_append(&sRes, cf=='p' ? "PM" : "pm", 2);
+ }else{
+ sqlite3_str_append(&sRes, cf=='p' ? "AM" : "am", 2);
}
- case 'Y': {
- sqlite3_snprintf(5,&z[j],"%04d",x.Y); j+=sqlite3Strlen30(&z[j]);
- break;
+ break;
+ }
+ case 'R': {
+ sqlite3_str_appendf(&sRes, "%02d:%02d", x.h, x.m);
+ break;
+ }
+ case 's': {
+ if( x.useSubsec ){
+ sqlite3_str_appendf(&sRes,"%.3f",
+ (x.iJD - 21086676*(i64)10000000)/1000.0);
+ }else{
+ i64 iS = (i64)(x.iJD/1000 - 21086676*(i64)10000);
+ sqlite3_str_appendf(&sRes,"%lld",iS);
}
- default: z[j++] = '%'; break;
+ break;
+ }
+ case 'S': {
+ sqlite3_str_appendf(&sRes,"%02d",(int)x.s);
+ break;
+ }
+ case 'T': {
+ sqlite3_str_appendf(&sRes,"%02d:%02d:%02d", x.h, x.m, (int)x.s);
+ break;
+ }
+ case 'u': /* Day of week. 1 to 7. Monday==1, Sunday==7 */
+ case 'w': { /* Day of week. 0 to 6. Sunday==0, Monday==1 */
+ char c = (char)daysAfterSunday(&x) + '0';
+ if( c=='0' && cf=='u' ) c = '7';
+ sqlite3_str_appendchar(&sRes, 1, c);
+ break;
+ }
+ case 'U': { /* Week num. 00-53. First Sun of the year is week 01 */
+ sqlite3_str_appendf(&sRes,"%02d",
+ (daysAfterJan01(&x)-daysAfterSunday(&x)+7)/7);
+ break;
+ }
+ case 'V': { /* Week num. 01-53. First week with a Thur is week 01 */
+ DateTime y = x;
+ /* Adjust y so that is the Thursday in the same week as x */
+ assert( y.validJD );
+ y.iJD += (3 - daysAfterMonday(&x))*86400000;
+ y.validYMD = 0;
+ computeYMD(&y);
+ sqlite3_str_appendf(&sRes,"%02d", daysAfterJan01(&y)/7+1);
+ break;
+ }
+ case 'W': { /* Week num. 00-53. First Mon of the year is week 01 */
+ sqlite3_str_appendf(&sRes,"%02d",
+ (daysAfterJan01(&x)-daysAfterMonday(&x)+7)/7);
+ break;
+ }
+ case 'Y': {
+ sqlite3_str_appendf(&sRes,"%04d",x.Y);
+ break;
+ }
+ case '%': {
+ sqlite3_str_appendchar(&sRes, 1, '%');
+ break;
+ }
+ default: {
+ sqlite3_str_reset(&sRes);
+ return;
}
}
}
- z[j] = 0;
- sqlite3_result_text(context, z, -1,
- z==zBuf ? SQLITE_TRANSIENT : SQLITE_DYNAMIC);
+ if( j=d2.iJD ){
+ sign = '+';
+ Y = d1.Y - d2.Y;
+ if( Y ){
+ d2.Y = d1.Y;
+ d2.validJD = 0;
+ computeJD(&d2);
+ }
+ M = d1.M - d2.M;
+ if( M<0 ){
+ Y--;
+ M += 12;
+ }
+ if( M!=0 ){
+ d2.M = d1.M;
+ d2.validJD = 0;
+ computeJD(&d2);
+ }
+ while( d1.iJDd2.iJD ){
+ M--;
+ if( M<0 ){
+ M = 11;
+ Y--;
+ }
+ d2.M++;
+ if( d2.M>12 ){
+ d2.M = 1;
+ d2.Y++;
+ }
+ d2.validJD = 0;
+ computeJD(&d2);
+ }
+ d1.iJD = d2.iJD - d1.iJD;
+ d1.iJD += (u64)1486995408 * (u64)100000;
+ }
+ clearYMD_HMS_TZ(&d1);
+ computeYMD_HMS(&d1);
+ sqlite3StrAccumInit(&sRes, 0, 0, 0, 100);
+ sqlite3_str_appendf(&sRes, "%c%04d-%02d-%02d %02d:%02d:%06.3f",
+ sign, Y, M, d1.D-1, d1.h, d1.m, d1.s);
+ sqlite3ResultStrAccum(context, &sRes);
+}
+
+
/*
** current_timestamp()
**
@@ -22128,10 +27215,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);
@@ -22140,6 +27227,36 @@ static void currentTimeFunc(
}
#endif
+#if !defined(SQLITE_OMIT_DATETIME_FUNCS) && defined(SQLITE_DEBUG)
+/*
+** datedebug(...)
+**
+** This routine returns JSON that describes the internal DateTime object.
+** Used for debugging and testing only. Subject to change.
+*/
+static void datedebugFunc(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv
+){
+ DateTime x;
+ if( isDate(context, argc, argv, &x)==0 ){
+ char *zJson;
+ zJson = sqlite3_mprintf(
+ "{iJD:%lld,Y:%d,M:%d,D:%d,h:%d,m:%d,tz:%d,"
+ "s:%.3f,validJD:%d,validYMD:%d,validHMS:%d,"
+ "nFloor:%d,rawS:%d,isError:%d,useSubsec:%d,"
+ "isUtc:%d,isLocal:%d}",
+ x.iJD, x.Y, x.M, x.D, x.h, x.m, x.tz,
+ x.s, x.validJD, x.validYMD, x.validHMS,
+ x.nFloor, x.rawS, x.isError, x.useSubsec,
+ x.isUtc, x.isLocal);
+ sqlite3_result_text(context, zJson, -1, sqlite3_free);
+ }
+}
+#endif /* !SQLITE_OMIT_DATETIME_FUNCS && SQLITE_DEBUG */
+
+
/*
** This function registered all of the above C functions as SQL
** functions. This should be the only routine in this file with
@@ -22149,10 +27266,15 @@ SQLITE_PRIVATE void sqlite3RegisterDateTimeFunctions(void){
static FuncDef aDateTimeFuncs[] = {
#ifndef SQLITE_OMIT_DATETIME_FUNCS
PURE_DATE(julianday, -1, 0, 0, juliandayFunc ),
+ PURE_DATE(unixepoch, -1, 0, 0, unixepochFunc ),
PURE_DATE(date, -1, 0, 0, dateFunc ),
PURE_DATE(time, -1, 0, 0, timeFunc ),
PURE_DATE(datetime, -1, 0, 0, datetimeFunc ),
PURE_DATE(strftime, -1, 0, 0, strftimeFunc ),
+ PURE_DATE(timediff, 2, 0, 0, timediffFunc ),
+#ifdef SQLITE_DEBUG
+ PURE_DATE(datedebug, -1, 0, 0, datedebugFunc ),
+#endif
DFUNCTION(current_time, 0, 0, 0, ctimeFunc ),
DFUNCTION(current_timestamp, 0, 0, 0, ctimestampFunc),
DFUNCTION(current_date, 0, 0, 0, cdateFunc ),
@@ -22275,9 +27397,11 @@ SQLITE_PRIVATE int sqlite3OsFileSize(sqlite3_file *id, i64 *pSize){
}
SQLITE_PRIVATE int sqlite3OsLock(sqlite3_file *id, int lockType){
DO_OS_MALLOC_TEST(id);
+ assert( lockType>=SQLITE_LOCK_SHARED && lockType<=SQLITE_LOCK_EXCLUSIVE );
return id->pMethods->xLock(id, lockType);
}
SQLITE_PRIVATE int sqlite3OsUnlock(sqlite3_file *id, int lockType){
+ assert( lockType==SQLITE_LOCK_NONE || lockType==SQLITE_LOCK_SHARED );
return id->pMethods->xUnlock(id, lockType);
}
SQLITE_PRIVATE int sqlite3OsCheckReservedLock(sqlite3_file *id, int *pResOut){
@@ -22298,17 +27422,24 @@ 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
** transaction has been committed. Injecting a fault at this point
- ** confuses the test scripts - the COMMIT comand returns SQLITE_NOMEM
+ ** confuses the test scripts - the COMMIT command returns SQLITE_NOMEM
** but the transaction is committed anyway.
**
** 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
@@ -22323,6 +27454,7 @@ SQLITE_PRIVATE int sqlite3OsSectorSize(sqlite3_file *id){
return (xSectorSize ? xSectorSize(id) : SQLITE_DEFAULT_SECTOR_SIZE);
}
SQLITE_PRIVATE int sqlite3OsDeviceCharacteristics(sqlite3_file *id){
+ if( NEVER(id->pMethods==0) ) return 0;
return id->pMethods->xDeviceCharacteristics(id);
}
#ifndef SQLITE_OMIT_WAL
@@ -22384,14 +27516,15 @@ 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);
+ assert( zPath || (flags & SQLITE_OPEN_EXCLUSIVE) );
+ 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,
@@ -22414,6 +27547,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){
@@ -22427,7 +27562,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);
@@ -22448,7 +27591,7 @@ SQLITE_PRIVATE int sqlite3OsCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *p
}else{
double r;
rc = pVfs->xCurrentTime(pVfs, &r);
- *pTimeOut = (sqlite3_int64)(r*86400000.0);
+ *pTimeOut = sqlite3RealToI64(r*86400000.0);
}
return rc;
}
@@ -22467,12 +27610,15 @@ SQLITE_PRIVATE int sqlite3OsOpenMalloc(
rc = sqlite3OsOpen(pVfs, zFile, pFile, flags, pOutFlags);
if( rc!=SQLITE_OK ){
sqlite3_free(pFile);
+ *ppFile = 0;
}else{
*ppFile = pFile;
}
}else{
+ *ppFile = 0;
rc = SQLITE_NOMEM_BKPT;
}
+ assert( *ppFile!=0 || rc!=SQLITE_OK );
return rc;
}
SQLITE_PRIVATE void sqlite3OsCloseFree(sqlite3_file *pFile){
@@ -22514,7 +27660,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){
@@ -22529,7 +27675,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 ){
@@ -22560,7 +27706,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 ){
@@ -22584,7 +27730,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);
@@ -22605,17 +27751,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.
*/
@@ -22817,7 +27963,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)
@@ -22903,7 +28049,7 @@ static void *sqlite3MemMalloc(int nByte){
** or sqlite3MemRealloc().
**
** For this low-level routine, we already know that pPrior!=0 since
-** cases where pPrior==0 will have been intecepted and dealt with
+** cases where pPrior==0 will have been intercepted and dealt with
** by higher-level routines.
*/
static void sqlite3MemFree(void *pPrior){
@@ -22991,13 +28137,13 @@ static int sqlite3MemInit(void *NotUsed){
return SQLITE_OK;
}
len = sizeof(cpuCount);
- /* One usually wants to use hw.acctivecpu for MT decisions, but not here */
+ /* One usually wants to use hw.activecpu for MT decisions, but not here */
sysctlbyname("hw.ncpu", &cpuCount, &len, NULL, 0);
if( cpuCount>1 ){
/* defer MT decisions to system malloc */
_sqliteZone_ = malloc_default_zone();
}else{
- /* only 1 core, use our own zone to contention over global locks,
+ /* 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");
@@ -23121,7 +28267,7 @@ struct MemBlockHdr {
** when this module is combined with other in the amalgamation.
*/
static struct {
-
+
/*
** Mutex to control access to the memory allocation subsystem.
*/
@@ -23132,7 +28278,7 @@ static struct {
*/
struct MemBlockHdr *pFirst;
struct MemBlockHdr *pLast;
-
+
/*
** The number of levels of backtrace to save in new allocations.
*/
@@ -23145,7 +28291,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.
*/
@@ -23190,7 +28336,7 @@ static void adjustStats(int iSize, int increment){
** This routine checks the guards at either end of the allocation and
** if they are incorrect it asserts.
*/
-static struct MemBlockHdr *sqlite3MemsysGetHeader(void *pAllocation){
+static struct MemBlockHdr *sqlite3MemsysGetHeader(const void *pAllocation){
struct MemBlockHdr *p;
int *pInt;
u8 *pU8;
@@ -23204,7 +28350,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 );
@@ -23333,7 +28479,7 @@ static void *sqlite3MemMalloc(int nByte){
p = (void*)pInt;
}
sqlite3_mutex_leave(mem.mutex);
- return p;
+ return p;
}
/*
@@ -23343,7 +28489,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;
@@ -23369,15 +28515,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.
*/
@@ -23420,7 +28566,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 );
@@ -23437,9 +28583,9 @@ SQLITE_PRIVATE void sqlite3MemdebugSetType(void *p, u8 eType){
**
** assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) );
*/
-SQLITE_PRIVATE int sqlite3MemdebugHasType(void *p, u8 eType){
+SQLITE_PRIVATE int sqlite3MemdebugHasType(const 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 */
@@ -23459,9 +28605,9 @@ SQLITE_PRIVATE int sqlite3MemdebugHasType(void *p, u8 eType){
**
** assert( sqlite3MemdebugNoType(p, MEMTYPE_LOOKASIDE) );
*/
-SQLITE_PRIVATE int sqlite3MemdebugNoType(void *p, u8 eType){
+SQLITE_PRIVATE int sqlite3MemdebugNoType(const 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 */
@@ -23511,7 +28657,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){
@@ -23528,7 +28674,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);
@@ -23541,7 +28687,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];
}
@@ -23871,18 +29017,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;
@@ -23909,9 +29055,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;
}
}
}
@@ -23960,26 +29106,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);
}
}
}
@@ -24020,23 +29166,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;
}
}
}
@@ -24074,7 +29220,7 @@ static void *memsys3Malloc(int nBytes){
memsys3Enter();
p = memsys3MallocUnsafe(nBytes);
memsys3Leave();
- return (void*)p;
+ return (void*)p;
}
/*
@@ -24132,11 +29278,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;
@@ -24155,7 +29301,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){
@@ -24196,7 +29342,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
@@ -24313,7 +29459,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
@@ -24358,7 +29504,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.
*/
@@ -24377,7 +29523,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.
@@ -24553,7 +29699,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);
@@ -24622,7 +29768,7 @@ static void *memsys5Malloc(int nBytes){
p = memsys5MallocUnsafe(nBytes);
memsys5Leave();
}
- return (void*)p;
+ return (void*)p;
}
/*
@@ -24635,14 +29781,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
@@ -24682,8 +29828,17 @@ static void *memsys5Realloc(void *pPrior, int nBytes){
*/
static int memsys5Roundup(int n){
int iFullSz;
- if( n > 0x40000000 ) return 0;
- for(iFullSz=mem5.szAtom; iFullSz0x10000000 ){
+ if( n>0x40000000 ) return 0;
+ if( n>0x20000000 ) return 0x40000000;
+ return 0x20000000;
+ }
+ for(iFullSz=mem5.szAtom*8; iFullSz=(i64)n ) return iFullSz/2;
return iFullSz;
}
@@ -24775,7 +29930,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){
@@ -24817,7 +29972,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.
*/
@@ -24868,23 +30023,28 @@ static SQLITE_WSD int mutexIsInit = 0;
#ifndef SQLITE_MUTEX_OMIT
-#ifdef SQLITE_ENABLE_MULTITHREADED_CHECKS
+#ifdef SQLITE_THREAD_MISUSE_WARNINGS
/*
-** This block (enclosed by SQLITE_ENABLE_MULTITHREADED_CHECKS) contains
+** This block (enclosed by SQLITE_THREAD_MISUSE_WARNINGS) 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
** sqlite3MutexWarnOnContention() on it, then if contention is ever
-** encountered within xMutexEnter() a warning is emitted via sqlite3_log().
+** encountered within xMutexEnter() then a warning is emitted via
+** sqlite3_log(). Furthermore, if SQLITE_THREAD_MISUSE_ABORT is
+** defined then abort() is called after the sqlite3_log() warning.
**
-** This type of mutex is used as the database handle mutex when testing
-** apps that usually use SQLITE_CONFIG_MULTITHREAD mode.
+** This type of mutex is used on the database handle mutex when testing
+** apps that usually use SQLITE_CONFIG_MULTITHREAD mode. A failure
+** indicates that the app ought to be using SQLITE_OPEN_FULLMUTEX or
+** similar because it is trying to use the same database handle from
+** two different connections at the same time.
*/
-/*
-** Type for all mutexes used when SQLITE_ENABLE_MULTITHREADED_CHECKS
+/*
+** Type for all mutexes used when SQLITE_THREAD_MISUSE_WARNINGS
** is defined. Variable CheckMutex.mutex is a pointer to the real mutex
** allocated by the system mutex implementation. Variable iType is usually set
** to the type of mutex requested - SQLITE_MUTEX_RECURSIVE, SQLITE_MUTEX_FAST
@@ -24900,9 +30060,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;
@@ -24918,13 +30078,14 @@ 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 pGlobalMutexMethods->xMutexInit();
}
-static int checkMutexEnd(void){
+static int checkMutexEnd(void){
+ int rc = pGlobalMutexMethods->xMutexEnd();
pGlobalMutexMethods = 0;
- return SQLITE_OK;
+ return rc;
}
/*
@@ -24974,7 +30135,7 @@ static void checkMutexFree(sqlite3_mutex *p){
assert( SQLITE_MUTEX_FAST<2 );
assert( SQLITE_MUTEX_WARNONCONTENTION<2 );
-#if SQLITE_ENABLE_API_ARMOR
+#ifdef SQLITE_ENABLE_API_ARMOR
if( ((CheckMutex*)p)->iType<2 )
#endif
{
@@ -24998,9 +30159,12 @@ 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"
);
+#if SQLITE_THREAD_MISUSE_ABORT
+ abort();
+#endif
}
pGlobalMutexMethods->xMutexEnter(pCheck->mutex);
}
@@ -25052,16 +30216,16 @@ SQLITE_PRIVATE void sqlite3MutexWarnOnContention(sqlite3_mutex *p){
pCheck->iType = SQLITE_MUTEX_WARNONCONTENTION;
}
}
-#endif /* ifdef SQLITE_ENABLE_MULTITHREADED_CHECKS */
+#endif /* ifdef SQLITE_THREAD_MISUSE_WARNINGS */
/*
** 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.
*/
@@ -25069,7 +30233,7 @@ SQLITE_PRIVATE int sqlite3MutexInit(void){
sqlite3_mutex_methods *pTo = &sqlite3GlobalConfig.mutex;
if( sqlite3GlobalConfig.bCoreMutex ){
-#ifdef SQLITE_ENABLE_MULTITHREADED_CHECKS
+#ifdef SQLITE_THREAD_MISUSE_WARNINGS
pFrom = multiThreadedCheckMutex();
#else
pFrom = sqlite3DefaultMutex();
@@ -25095,6 +30259,7 @@ SQLITE_PRIVATE int sqlite3MutexInit(void){
GLOBAL(int, mutexIsInit) = 1;
#endif
+ sqlite3MemoryBarrier();
return rc;
}
@@ -25172,7 +30337,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.
*/
@@ -25187,16 +30352,29 @@ SQLITE_API void sqlite3_mutex_leave(sqlite3_mutex *p){
/*
** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are
** intended for use inside assert() statements.
+**
+** Because these routines raise false-positive alerts in TSAN, disable
+** them (make them always return 1) when compiling with TSAN.
*/
SQLITE_API int sqlite3_mutex_held(sqlite3_mutex *p){
+# if defined(__has_feature)
+# if __has_feature(thread_sanitizer)
+ p = 0;
+# endif
+# endif
assert( p==0 || sqlite3GlobalConfig.mutex.xMutexHeld );
return p==0 || sqlite3GlobalConfig.mutex.xMutexHeld(p);
}
SQLITE_API int sqlite3_mutex_notheld(sqlite3_mutex *p){
+# if defined(__has_feature)
+# if __has_feature(thread_sanitizer)
+ p = 0;
+# endif
+# endif
assert( p==0 || sqlite3GlobalConfig.mutex.xMutexNotheld );
return p==0 || sqlite3GlobalConfig.mutex.xMutexNotheld(p);
}
-#endif
+#endif /* NDEBUG */
#endif /* !defined(SQLITE_MUTEX_OMIT) */
@@ -25241,9 +30419,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; }
@@ -25308,7 +30486,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];
@@ -25448,7 +30626,7 @@ SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3DefaultMutex(void){
/*
** The sqlite3_mutex.id, sqlite3_mutex.nRef, and sqlite3_mutex.owner fields
-** are necessary under two condidtions: (1) Debug builds and (2) using
+** are necessary under two conditions: (1) Debug builds and (2) using
** home-grown mutexes. Encapsulate these conditions into a single #define.
*/
#if defined(SQLITE_DEBUG) || defined(SQLITE_HOMEGROWN_RECURSIVE_MUTEX)
@@ -25486,7 +30664,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.
@@ -25534,7 +30712,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
@@ -25568,7 +30746,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.
*/
@@ -25645,7 +30823,7 @@ static sqlite3_mutex *pthreadMutexAlloc(int iType){
*/
static void pthreadMutexFree(sqlite3_mutex *p){
assert( p->nRef==0 );
-#if SQLITE_ENABLE_API_ARMOR
+#ifdef SQLITE_ENABLE_API_ARMOR
if( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE )
#endif
{
@@ -25679,7 +30857,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.
@@ -25722,7 +30900,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.
@@ -25836,205 +31014,7 @@ SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3DefaultMutex(void){
/*
** Include code that is common to all os_*.c files
*/
-/************** Include os_common.h in the middle of mutex_w32.c *************/
-/************** Begin file os_common.h ***************************************/
-/*
-** 2004 May 22
-**
-** The author disclaims copyright to this source code. In place of
-** a legal notice, here is a blessing:
-**
-** May you do good and not evil.
-** May you find forgiveness for yourself and forgive others.
-** May you share freely, never taking more than you give.
-**
-******************************************************************************
-**
-** This file contains macros and a little bit of code that is common to
-** all of the platform-specific files (os_*.c) and is #included into those
-** files.
-**
-** This file should be #included by the os_*.c files only. It is not a
-** general purpose header file.
-*/
-#ifndef _OS_COMMON_H_
-#define _OS_COMMON_H_
-
-/*
-** At least two bugs have slipped in because we changed the MEMORY_DEBUG
-** macro to SQLITE_DEBUG and some older makefiles have not yet made the
-** switch. The following code should catch this problem at compile-time.
-*/
-#ifdef MEMORY_DEBUG
-# error "The MEMORY_DEBUG macro is obsolete. Use SQLITE_DEBUG instead."
-#endif
-
-/*
-** Macros for performance tracing. Normally turned off. Only works
-** on i486 hardware.
-*/
-#ifdef SQLITE_PERFORMANCE_TRACE
-
-/*
-** hwtime.h contains inline assembler code for implementing
-** high-performance timing routines.
-*/
-/************** Include hwtime.h in the middle of os_common.h ****************/
-/************** Begin file hwtime.h ******************************************/
-/*
-** 2008 May 27
-**
-** The author disclaims copyright to this source code. In place of
-** a legal notice, here is a blessing:
-**
-** May you do good and not evil.
-** May you find forgiveness for yourself and forgive others.
-** May you share freely, never taking more than you give.
-**
-******************************************************************************
-**
-** This file contains inline asm code for retrieving "high-performance"
-** counters for x86 class CPUs.
-*/
-#ifndef SQLITE_HWTIME_H
-#define SQLITE_HWTIME_H
-
-/*
-** The following routine only works on pentium-class (or newer) processors.
-** It uses the RDTSC opcode to read the cycle count value out of the
-** processor and returns that value. This can be used for high-res
-** profiling.
-*/
-#if (defined(__GNUC__) || defined(_MSC_VER)) && \
- (defined(i386) || defined(__i386__) || defined(_M_IX86))
-
- #if defined(__GNUC__)
-
- __inline__ sqlite_uint64 sqlite3Hwtime(void){
- unsigned int lo, hi;
- __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
- return (sqlite_uint64)hi << 32 | lo;
- }
-
- #elif defined(_MSC_VER)
-
- __declspec(naked) __inline sqlite_uint64 __cdecl sqlite3Hwtime(void){
- __asm {
- rdtsc
- ret ; return value at EDX:EAX
- }
- }
-
- #endif
-
-#elif (defined(__GNUC__) && defined(__x86_64__))
-
- __inline__ sqlite_uint64 sqlite3Hwtime(void){
- unsigned long val;
- __asm__ __volatile__ ("rdtsc" : "=A" (val));
- return val;
- }
-
-#elif (defined(__GNUC__) && defined(__ppc__))
-
- __inline__ sqlite_uint64 sqlite3Hwtime(void){
- unsigned long long retval;
- unsigned long junk;
- __asm__ __volatile__ ("\n\
- 1: mftbu %1\n\
- mftb %L0\n\
- mftbu %0\n\
- cmpw %0,%1\n\
- bne 1b"
- : "=r" (retval), "=r" (junk));
- return retval;
- }
-
-#else
-
- #error Need implementation of sqlite3Hwtime() for your platform.
-
- /*
- ** To compile without implementing sqlite3Hwtime() for your platform,
- ** you can remove the above #error and use the following
- ** stub function. You will lose timing support for many
- ** of the debugging and testing utilities, but it should at
- ** least compile and run.
- */
-SQLITE_PRIVATE sqlite_uint64 sqlite3Hwtime(void){ return ((sqlite_uint64)0); }
-
-#endif
-
-#endif /* !defined(SQLITE_HWTIME_H) */
-
-/************** End of hwtime.h **********************************************/
-/************** Continuing where we left off in os_common.h ******************/
-
-static sqlite_uint64 g_start;
-static sqlite_uint64 g_elapsed;
-#define TIMER_START g_start=sqlite3Hwtime()
-#define TIMER_END g_elapsed=sqlite3Hwtime()-g_start
-#define TIMER_ELAPSED g_elapsed
-#else
-#define TIMER_START
-#define TIMER_END
-#define TIMER_ELAPSED ((sqlite_uint64)0)
-#endif
-
-/*
-** If we compile with the SQLITE_TEST macro set, then the following block
-** of code will give us the ability to simulate a disk I/O error. This
-** is used for testing the I/O recovery logic.
-*/
-#if defined(SQLITE_TEST)
-SQLITE_API extern int sqlite3_io_error_hit;
-SQLITE_API extern int sqlite3_io_error_hardhit;
-SQLITE_API extern int sqlite3_io_error_pending;
-SQLITE_API extern int sqlite3_io_error_persist;
-SQLITE_API extern int sqlite3_io_error_benign;
-SQLITE_API extern int sqlite3_diskfull_pending;
-SQLITE_API extern int sqlite3_diskfull;
-#define SimulateIOErrorBenign(X) sqlite3_io_error_benign=(X)
-#define SimulateIOError(CODE) \
- if( (sqlite3_io_error_persist && sqlite3_io_error_hit) \
- || sqlite3_io_error_pending-- == 1 ) \
- { local_ioerr(); CODE; }
-static void local_ioerr(){
- IOTRACE(("IOERR\n"));
- sqlite3_io_error_hit++;
- if( !sqlite3_io_error_benign ) sqlite3_io_error_hardhit++;
-}
-#define SimulateDiskfullError(CODE) \
- if( sqlite3_diskfull_pending ){ \
- if( sqlite3_diskfull_pending == 1 ){ \
- local_ioerr(); \
- sqlite3_diskfull = 1; \
- sqlite3_io_error_hit = 1; \
- CODE; \
- }else{ \
- sqlite3_diskfull_pending--; \
- } \
- }
-#else
-#define SimulateIOErrorBenign(X)
-#define SimulateIOError(A)
-#define SimulateDiskfullError(A)
-#endif /* defined(SQLITE_TEST) */
-
-/*
-** When testing, keep a count of the number of open files.
-*/
-#if defined(SQLITE_TEST)
-SQLITE_API extern int sqlite3_open_file_count;
-#define OpenCounter(X) sqlite3_open_file_count+=(X)
-#else
-#define OpenCounter(X)
-#endif /* defined(SQLITE_TEST) */
-
-#endif /* !defined(_OS_COMMON_H_) */
-
-/************** End of os_common.h *******************************************/
-/************** Continuing where we left off in mutex_w32.c ******************/
+/* #include "os_common.h" */
/*
** Include the header file for the Windows VFS.
@@ -26065,6 +31045,8 @@ SQLITE_API extern int sqlite3_open_file_count;
#ifdef __CYGWIN__
# include
+# include /* amalgamator: dontcache */
+# include /* amalgamator: dontcache */
# include /* amalgamator: dontcache */
#endif
@@ -26099,14 +31081,6 @@ SQLITE_API extern int sqlite3_open_file_count;
# define SQLITE_OS_WINCE 0
#endif
-/*
-** Determine if we are dealing with WinRT, which provides only a subset of
-** the full Win32 API.
-*/
-#if !defined(SQLITE_OS_WINRT)
-# define SQLITE_OS_WINRT 0
-#endif
-
/*
** For WinCE, some API function parameters do not appear to be declared as
** volatile.
@@ -26121,7 +31095,7 @@ SQLITE_API extern int sqlite3_open_file_count;
** For some Windows sub-platforms, the _beginthreadex() / _endthreadex()
** functions are not available (e.g. those not using MSVC, Cygwin, etc).
*/
-#if SQLITE_OS_WIN && !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && \
+#if SQLITE_OS_WIN && !SQLITE_OS_WINCE && \
SQLITE_THREADSAFE>0 && !defined(__CYGWIN__)
# define SQLITE_OS_WIN_THREADS 1
#else
@@ -26147,7 +31121,7 @@ struct sqlite3_mutex {
CRITICAL_SECTION mutex; /* Mutex controlling the lock */
int id; /* Mutex type */
#ifdef SQLITE_DEBUG
- volatile int nRef; /* Number of enterances */
+ volatile int nRef; /* Number of entrances */
volatile DWORD owner; /* Thread holding this mutex */
volatile LONG trace; /* True to trace changes */
#endif
@@ -26196,7 +31170,7 @@ SQLITE_PRIVATE void sqlite3MemoryBarrier(void){
SQLITE_MEMORY_BARRIER;
#elif defined(__GNUC__)
__sync_synchronize();
-#elif MSVC_VERSION>=1300
+#elif MSVC_VERSION>=1400
_ReadWriteBarrier();
#elif defined(MemoryBarrier)
MemoryBarrier();
@@ -26238,11 +31212,7 @@ static int winMutexInit(void){
if( InterlockedCompareExchange(&winMutex_lock, 1, 0)==0 ){
int i;
for(i=0; i
**
- 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
@@ -26332,11 +31302,7 @@ static sqlite3_mutex *winMutexAlloc(int iType){
p->trace = 1;
#endif
#endif
-#if SQLITE_OS_WINRT
- InitializeCriticalSectionEx(&p->mutex, 0, 0);
-#else
InitializeCriticalSection(&p->mutex);
-#endif
}
break;
}
@@ -26543,19 +31509,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)
@@ -26585,8 +31559,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;
@@ -26602,9 +31583,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));
@@ -26615,6 +31599,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( n>32) < 0xffffffff );
+}
+#else
+# define test_oom_breakpoint(X) /* No-op for production builds */
+#endif
+
/*
** Do a memory allocation with statistics and alarms. Assume the
** lock is already held.
@@ -26701,21 +31733,22 @@ static void mallocWithAlarm(int n, void **pp){
** following xRoundup() call. */
nFull = sqlite3GlobalConfig.m.xRoundup(n);
-#ifdef SQLITE_MAX_MEMORY
- if( sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED)+nFull>SQLITE_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 ){
+ test_oom_breakpoint(1);
+ *pp = 0;
+ return;
+ }
+ }
}else{
- mem0.nearlyFull = 0;
+ AtomicStore(&mem0.nearlyFull, 0);
}
}
p = sqlite3GlobalConfig.m.xMalloc(nFull);
@@ -26739,12 +31772,7 @@ static void mallocWithAlarm(int n, void **pp){
*/
SQLITE_PRIVATE void *sqlite3Malloc(u64 n){
void *p;
- if( n==0 || n>=0x7fffff00 ){
- /* A memory allocation of a number of bytes which is near the maximum
- ** signed integer value might cause an integer overflow inside of the
- ** xMalloc(). Hence we limit the maximum size to 0x7fffff00, giving
- ** 255 bytes of overhead. SQLite itself will never use anything near
- ** this amount. The only way to reach the limit is with sqlite3_malloc() */
+ if( n==0 || n>SQLITE_MAX_ALLOCATION_SIZE ){
p = 0;
}else if( sqlite3GlobalConfig.bMemstat ){
sqlite3_mutex_enter(mem0.mutex);
@@ -26779,8 +31807,8 @@ SQLITE_API void *sqlite3_malloc64(sqlite3_uint64 n){
** TRUE if p is a lookaside memory allocation from db
*/
#ifndef SQLITE_OMIT_LOOKASIDE
-static int isLookaside(sqlite3 *db, void *p){
- return SQLITE_WITHIN(p, db->lookaside.pStart, db->lookaside.pEnd);
+static int isLookaside(sqlite3 *db, const void *p){
+ return SQLITE_WITHIN(p, db->lookaside.pStart, db->lookaside.pTrueEnd);
}
#else
#define isLookaside(A,B) 0
@@ -26790,27 +31818,43 @@ static int isLookaside(sqlite3 *db, void *p){
** Return the size of a memory allocation previously obtained from
** sqlite3Malloc() or sqlite3_malloc().
*/
-SQLITE_PRIVATE int sqlite3MallocSize(void *p){
+SQLITE_PRIVATE int sqlite3MallocSize(const void *p){
assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) );
- return sqlite3GlobalConfig.m.xSize(p);
+ return sqlite3GlobalConfig.m.xSize((void*)p);
}
-SQLITE_PRIVATE int sqlite3DbMallocSize(sqlite3 *db, void *p){
+static int lookasideMallocSize(sqlite3 *db, const 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, const void *p){
assert( p!=0 );
- if( db==0 || !isLookaside(db,p) ){
#ifdef SQLITE_DEBUG
- if( db==0 ){
- assert( sqlite3MemdebugNoType(p, (u8)~MEMTYPE_HEAP) );
- assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) );
- }else{
- assert( sqlite3MemdebugHasType(p, (MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
- assert( sqlite3MemdebugNoType(p, (u8)~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
- }
+ if( db==0 ){
+ assert( sqlite3MemdebugNoType(p, (u8)~MEMTYPE_HEAP) );
+ assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) );
+ }else if( !isLookaside(db,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;
+ if( db ){
+ if( ((uptr)p)<(uptr)(db->lookaside.pTrueEnd) ){
+#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((void*)p);
}
SQLITE_API sqlite3_uint64 sqlite3_msize(void *p){
assert( sqlite3MemdebugNoType(p, (u8)~MEMTYPE_HEAP) );
@@ -26853,24 +31897,75 @@ SQLITE_PRIVATE void sqlite3DbFreeNN(sqlite3 *db, void *p){
assert( db==0 || sqlite3_mutex_held(db->mutex) );
assert( p!=0 );
if( db ){
+ if( ((uptr)p)<(uptr)(db->lookaside.pEnd) ){
+#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE
+ if( ((uptr)p)>=(uptr)(db->lookaside.pMiddle) ){
+ LookasideSlot *pBuf = (LookasideSlot*)p;
+ assert( db->pnBytesFreed==0 );
+#ifdef SQLITE_DEBUG
+ memset(p, 0xaa, LOOKASIDE_SMALL); /* Trash freed content */
+#endif
+ 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;
+ assert( db->pnBytesFreed==0 );
+#ifdef SQLITE_DEBUG
+ memset(p, 0xaa, db->lookaside.szTrue); /* Trash freed content */
+#endif
+ pBuf->pNext = db->lookaside.pFree;
+ db->lookaside.pFree = pBuf;
+ return;
+ }
+ }
if( db->pnBytesFreed ){
measureAllocationSize(db, p);
return;
}
- if( isLookaside(db, p) ){
+ }
+ assert( sqlite3MemdebugHasType(p, (MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
+ assert( sqlite3MemdebugNoType(p, (u8)~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
+ assert( db!=0 || sqlite3MemdebugNoType(p, MEMTYPE_LOOKASIDE) );
+ sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
+ sqlite3_free(p);
+}
+SQLITE_PRIVATE void sqlite3DbNNFreeNN(sqlite3 *db, void *p){
+ assert( db!=0 );
+ assert( sqlite3_mutex_held(db->mutex) );
+ assert( p!=0 );
+ if( ((uptr)p)<(uptr)(db->lookaside.pEnd) ){
+#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE
+ if( ((uptr)p)>=(uptr)(db->lookaside.pMiddle) ){
+ LookasideSlot *pBuf = (LookasideSlot*)p;
+ assert( db->pnBytesFreed==0 );
+#ifdef SQLITE_DEBUG
+ memset(p, 0xaa, LOOKASIDE_SMALL); /* Trash freed content */
+#endif
+ 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;
+ assert( db->pnBytesFreed==0 );
#ifdef SQLITE_DEBUG
- /* Trash all content in the buffer being freed */
- memset(p, 0xaa, db->lookaside.sz);
+ memset(p, 0xaa, db->lookaside.szTrue); /* Trash freed content */
#endif
pBuf->pNext = db->lookaside.pFree;
db->lookaside.pFree = pBuf;
return;
}
}
+ if( db->pnBytesFreed ){
+ measureAllocationSize(db, p);
+ return;
+ }
assert( sqlite3MemdebugHasType(p, (MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
assert( sqlite3MemdebugNoType(p, (u8)~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
- assert( db!=0 || sqlite3MemdebugNoType(p, MEMTYPE_LOOKASIDE) );
sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
sqlite3_free(p);
}
@@ -26894,8 +31989,7 @@ SQLITE_PRIVATE void *sqlite3Realloc(void *pOld, u64 nBytes){
sqlite3_free(pOld); /* IMP: R-26507-47431 */
return 0;
}
- if( nBytes>=0x7fffff00 ){
- /* The 0x7ffff00 limit term is explained in comments on sqlite3Malloc() */
+ if( nBytes>SQLITE_MAX_ALLOCATION_SIZE ){
return 0;
}
nOld = sqlite3MallocSize(pOld);
@@ -26906,18 +32000,26 @@ 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);
+ test_oom_breakpoint(1);
+ 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);
@@ -26951,7 +32053,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 ){
@@ -26981,13 +32083,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.
**
@@ -27021,23 +32123,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;
+ }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.pInit)!=0 ){
- db->lookaside.pInit = pBuf->pNext;
+ }else if( (pBuf = db->lookaside.pSmallInit)!=0 ){
+ db->lookaside.pSmallInit = pBuf->pNext;
db->lookaside.anStat[0]++;
return (void*)pBuf;
- }else{
- db->lookaside.anStat[2]++;
}
- }else if( db->mallocFailed ){
- return 0;
+ }
+#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 );
@@ -27061,7 +32177,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){
@@ -27072,14 +32197,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);
}
@@ -27104,9 +32229,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.
*/
@@ -27126,11 +32251,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;
@@ -27145,9 +32268,14 @@ SQLITE_PRIVATE char *sqlite3DbStrNDup(sqlite3 *db, const char *z, u64 n){
*/
SQLITE_PRIVATE char *sqlite3DbSpanDup(sqlite3 *db, const char *zStart, const char *zEnd){
int n;
+#ifdef SQLITE_DEBUG
+ /* Because of the way the parser works, the span is guaranteed to contain
+ ** at least one non-space character */
+ for(n=0; sqlite3Isspace(zStart[n]); n++){ assert( &zStart[n]0) && sqlite3Isspace(zStart[n-1]) ) n--;
+ while( sqlite3Isspace(zStart[n-1]) ) n--;
return sqlite3DbStrNDup(db, zStart, n);
}
@@ -27155,8 +32283,9 @@ SQLITE_PRIVATE char *sqlite3DbSpanDup(sqlite3 *db, const char *zStart, const cha
** Free any prior content in *pz and replace it with a copy of zNew.
*/
SQLITE_PRIVATE void sqlite3SetString(char **pz, sqlite3 *db, const char *zNew){
+ char *z = sqlite3DbStrDup(db, zNew);
sqlite3DbFree(db, *pz);
- *pz = sqlite3DbStrDup(db, zNew);
+ *pz = z;
}
/*
@@ -27164,18 +32293,32 @@ SQLITE_PRIVATE void sqlite3SetString(char **pz, sqlite3 *db, const char *zNew){
** has happened. This routine will set db->mallocFailed, and also
** temporarily disable the lookaside memory allocator and interrupt
** any running VDBEs.
+**
+** Always return a NULL pointer so that this routine can be invoked using
+**
+** return sqlite3OomFault(db);
+**
+** and thereby avoid unnecessary stack frame allocations for the overwhelmingly
+** common case where no OOM occurs.
*/
-SQLITE_PRIVATE void sqlite3OomFault(sqlite3 *db){
+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);
}
- db->lookaside.bDisable++;
+ DisableLookaside;
if( db->pParse ){
+ Parse *pParse;
+ sqlite3ErrorMsg(db->pParse, "out of memory");
db->pParse->rc = SQLITE_NOMEM_BKPT;
+ for(pParse=db->pParse->pOuterParse; pParse; pParse = pParse->pOuterParse){
+ pParse->nErr++;
+ pParse->rc = SQLITE_NOMEM;
+ }
}
}
+ return 0;
}
/*
@@ -27188,51 +32331,54 @@ 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;
+ return 0;
}
/************** End of malloc.c **********************************************/
/************** Begin file printf.c ******************************************/
/*
** The "printf" code that follows dates from the 1980's. It is in
-** the public domain.
+** the public domain.
**
**************************************************************************
**
@@ -27257,17 +32403,17 @@ SQLITE_PRIVATE int sqlite3ApiExit(sqlite3* db, int rc){
#define etPERCENT 7 /* Percent symbol. %% */
#define etCHARX 8 /* Characters. %c */
/* The rest are extensions, not normally found in printf() */
-#define etSQLESCAPE 9 /* Strings with '\'' doubled. %q */
-#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 etPOINTER 13 /* The %p conversion */
-#define etSQLESCAPE3 14 /* %w -> Strings with '\"' doubled */
-#define etORDINAL 15 /* %r -> 1st, 2nd, 3rd, 4th, etc. English only */
-#define etDECIMAL 16 /* %d or %u, but not %x, %o */
+#define etESCAPE_q 9 /* Strings with '\'' doubled. %q */
+#define etESCAPE_Q 10 /* Strings with '\'' doubled and enclosed in '',
+ NULL pointers replaced by SQL NULL. %Q */
+#define etTOKEN 11 /* a pointer to a Token structure */
+#define etSRCITEM 12 /* a pointer to a SrcItem */
+#define etPOINTER 13 /* The %p conversion */
+#define etESCAPE_w 14 /* %w -> Strings with '\"' doubled */
+#define etORDINAL 15 /* %r -> 1st, 2nd, 3rd, 4th, etc. English only */
+#define etDECIMAL 16 /* %d or %u, but not %x, %o */
-#define etINVALID 17 /* Any unrecognized conversion type */
+#define etINVALID 17 /* Any unrecognized conversion type */
/*
@@ -27286,6 +32432,7 @@ typedef struct et_info { /* Information about each format field */
etByte type; /* Conversion paradigm */
etByte charset; /* Offset into aDigits[] of the digits string */
etByte prefix; /* Offset into aPrefix[] of the prefix string */
+ char iNxt; /* Next with same hash, or 0 for end of chain */
} et_info;
/*
@@ -27294,78 +32441,70 @@ typedef struct et_info { /* Information about each format field */
#define FLAG_SIGNED 1 /* True if the value to convert is signed */
#define FLAG_STRING 4 /* Allow infinite precision */
-
/*
-** The following table is searched linearly, so it is good to put the
-** most frequently used conversion types first.
+** The table is searched by hash. In the case of %C where C is the character
+** and that character has ASCII value j, then the hash is j%23.
+**
+** The order of the entries in fmtinfo[] and the hash chain was entered
+** manually, but based on the output of the following TCL script:
*/
+#if 0 /***** Beginning of script ******/
+foreach c {d s g z q Q w c o u x X f e E G i n % p T S r} {
+ scan $c %c x
+ set n($c) $x
+}
+set mx [llength [array names n]]
+puts "count: $mx"
+
+set mx 27
+puts "*********** mx=$mx ************"
+for {set r 0} {$r<$mx} {incr r} {
+ puts -nonewline [format %2d: $r]
+ foreach c [array names n] {
+ if {($n($c))%$mx==$r} {puts -nonewline " $c"}
+ }
+ puts ""
+}
+#endif /***** End of script ********/
+
static const char aDigits[] = "0123456789ABCDEF0123456789abcdef";
static const char aPrefix[] = "-x0\000X0";
-static const et_info fmtinfo[] = {
- { 'd', 10, 1, etDECIMAL, 0, 0 },
- { 's', 0, 4, etSTRING, 0, 0 },
- { 'g', 0, 1, etGENERIC, 30, 0 },
- { 'z', 0, 4, etDYNSTRING, 0, 0 },
- { 'q', 0, 4, etSQLESCAPE, 0, 0 },
- { 'Q', 0, 4, etSQLESCAPE2, 0, 0 },
- { 'w', 0, 4, etSQLESCAPE3, 0, 0 },
- { 'c', 0, 0, etCHARX, 0, 0 },
- { 'o', 8, 0, etRADIX, 0, 2 },
- { 'u', 10, 0, etDECIMAL, 0, 0 },
- { 'x', 16, 0, etRADIX, 16, 1 },
- { 'X', 16, 0, etRADIX, 0, 4 },
-#ifndef SQLITE_OMIT_FLOATING_POINT
- { 'f', 0, 1, etFLOAT, 0, 0 },
- { 'e', 0, 1, etEXP, 30, 0 },
- { 'E', 0, 1, etEXP, 14, 0 },
- { 'G', 0, 1, etGENERIC, 14, 0 },
-#endif
- { 'i', 10, 1, etDECIMAL, 0, 0 },
- { 'n', 0, 0, etSIZE, 0, 0 },
- { '%', 0, 0, etPERCENT, 0, 0 },
- { 'p', 16, 0, etPOINTER, 0, 1 },
-
- /* All the rest are undocumented and are for internal use only */
- { 'T', 0, 0, etTOKEN, 0, 0 },
- { 'S', 0, 0, etSRCLIST, 0, 0 },
- { 'r', 10, 1, etORDINAL, 0, 0 },
+static const et_info fmtinfo[23] = {
+ /* 0 */ { 's', 0, 4, etSTRING, 0, 0, 1 },
+ /* 1 */ { 'E', 0, 1, etEXP, 14, 0, 0 }, /* Hash: 0 */
+ /* 2 */ { 'u', 10, 0, etDECIMAL, 0, 0, 3 },
+ /* 3 */ { 'G', 0, 1, etGENERIC, 14, 0, 0 }, /* Hash: 2 */
+ /* 4 */ { 'w', 0, 4, etESCAPE_w, 0, 0, 0 },
+ /* 5 */ { 'x', 16, 0, etRADIX, 16, 1, 0 },
+ /* 6 */ { 'c', 0, 0, etCHARX, 0, 0, 0 }, /* Hash: 7 */
+ /* 7 */ { 'z', 0, 4, etDYNSTRING, 0, 0, 6 },
+ /* 8 */ { 'd', 10, 1, etDECIMAL, 0, 0, 0 },
+ /* 9 */ { 'e', 0, 1, etEXP, 30, 0, 0 },
+ /* 10 */ { 'f', 0, 1, etFLOAT, 0, 0, 0 },
+ /* 11 */ { 'g', 0, 1, etGENERIC, 30, 0, 0 },
+ /* 12 */ { 'Q', 0, 4, etESCAPE_Q, 0, 0, 0 },
+ /* 13 */ { 'i', 10, 1, etDECIMAL, 0, 0, 0 },
+ /* 14 */ { '%', 0, 0, etPERCENT, 0, 0, 16 },
+ /* 15 */ { 'T', 0, 0, etTOKEN, 0, 0, 0 },
+ /* 16 */ { 'S', 0, 0, etSRCITEM, 0, 0, 0 }, /* Hash: 14 */
+ /* 17 */ { 'X', 16, 0, etRADIX, 0, 4, 0 }, /* Hash: 19 */
+ /* 18 */ { 'n', 0, 0, etSIZE, 0, 0, 0 },
+ /* 19 */ { 'o', 8, 0, etRADIX, 0, 2, 17 },
+ /* 20 */ { 'p', 16, 0, etPOINTER, 0, 1, 0 },
+ /* 21 */ { 'q', 0, 4, etESCAPE_q, 0, 0, 0 },
+ /* 22 */ { 'r', 10, 1, etORDINAL, 0, 0, 0 }
};
-/*
-** If SQLITE_OMIT_FLOATING_POINT is defined, then none of the floating point
-** conversions will work.
-*/
-#ifndef SQLITE_OMIT_FLOATING_POINT
-/*
-** "*val" is a double such that 0.1 <= *val < 10.0
-** Return the ascii code for the leading digit of *val, then
-** multiply "*val" by 10.0 to renormalize.
+/* Additional Notes:
**
-** Example:
-** input: *val = 3.14159
-** output: *val = 1.4159 function return = '3'
-**
-** The counter *cnt is incremented each time. After counter exceeds
-** 16 (the number of significant digits in a 64-bit float) '0' is
-** always returned.
-*/
-static char et_getdigit(LONGDOUBLE_TYPE *val, int *cnt){
- int digit;
- LONGDOUBLE_TYPE d;
- if( (*cnt)<=0 ) return '0';
- (*cnt)--;
- digit = (int)*val;
- d = digit;
- digit += '0';
- *val = (*val - d)*10.0;
- return (char)digit;
-}
-#endif /* SQLITE_OMIT_FLOATING_POINT */
+** %S Takes a pointer to SrcItem. Shows name or database.name
+** %!S Like %S but prefer the zName over the zAlias
+*/
/*
** Set the StrAccum object to an error mode.
*/
-static void setStrAccumError(StrAccum *p, u8 eError){
+SQLITE_PRIVATE void sqlite3StrAccumSetError(StrAccum *p, u8 eError){
assert( eError==SQLITE_NOMEM || eError==SQLITE_TOOBIG );
p->accError = eError;
if( p->mxAlloc ) sqlite3_str_reset(p);
@@ -27401,12 +32540,12 @@ 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);
+ sqlite3StrAccumSetError(pAccum, SQLITE_TOOBIG);
return 0;
}
- z = sqlite3DbMallocRaw(pAccum->db, n);
+ z = sqlite3_malloc(n);
if( z==0 ){
- setStrAccumError(pAccum, SQLITE_NOMEM);
+ sqlite3StrAccumSetError(pAccum, SQLITE_NOMEM);
}
return z;
}
@@ -27420,6 +32559,13 @@ static char *printfTempBuf(sqlite3_str *pAccum, sqlite3_int64 n){
#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.
*/
@@ -27446,22 +32592,19 @@ SQLITE_API void sqlite3_str_vappendf(
u8 bArgList; /* True for SQLITE_PRINTF_SQLFUNC */
char prefix; /* Prefix character. "+" or "-" or " " or '\0'. */
sqlite_uint64 longvalue; /* Value for integer types */
- LONGDOUBLE_TYPE realvalue; /* Value for real types */
+ double realvalue; /* Value for real types */
const et_info *infop; /* Pointer to the appropriate info structure */
char *zOut; /* Rendering buffer */
int nOut; /* Size of the rendering buffer */
char *zExtra = 0; /* Malloced memory used by some conversion */
-#ifndef SQLITE_OMIT_FLOATING_POINT
- int exp, e2; /* exponent of real numbers */
- int nsd; /* Number of significant digits returned */
- double rounder; /* Used for rounding floating point values */
+ int exp, e2; /* exponent of real numbers */
etByte flag_dp; /* True if decimal point should be shown */
etByte flag_rtz; /* True if trailing zeros should be removed */
-#endif
+
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 );
@@ -27479,7 +32622,10 @@ SQLITE_API void sqlite3_str_vappendf(
#if HAVE_STRCHRNUL
fmt = strchrnul(fmt, '%');
#else
- do{ fmt++; }while( *fmt && *fmt != '%' );
+ fmt = strchr(fmt, '%');
+ if( fmt==0 ){
+ fmt = bufpt + strlen(bufpt);
+ }
#endif
sqlite3_str_append(pAccum, bufpt, (int)(fmt - bufpt));
if( *fmt==0 ) break;
@@ -27593,6 +32739,9 @@ SQLITE_API void sqlite3_str_vappendf(
}while( !done && (c=(*++fmt))!=0 );
/* Fetch the info entry for the field */
+#ifdef SQLITE_EBCDIC
+ /* The hash table only works for ASCII. For EBCDIC, we need to do
+ ** a linear search of the table */
infop = &fmtinfo[0];
xtype = etINVALID;
for(idx=0; idxtype;
+ }else{
+ infop = &fmtinfo[0];
+ xtype = etINVALID;
+ }
+#endif
/*
** At this point, variables are initialized as follows:
@@ -27620,15 +32783,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;
@@ -27644,11 +32809,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;
@@ -27668,6 +32832,14 @@ SQLITE_API void sqlite3_str_vappendf(
}
prefix = 0;
}
+
+#if WHERETRACE_ENABLED
+ if( xtype==etPOINTER && sqlite3WhereTrace & 0x100000 ) longvalue = 0;
+#endif
+#if TREETRACE_ENABLED
+ if( xtype==etPOINTER && sqlite3TreeTrace & 0x100000 ) longvalue = 0;
+#endif
+
if( longvalue==0 ) flag_alternateform = 0;
if( flag_zeropad && precision0 );
}
length = (int)(&zOut[nOut-1]-bufpt);
- while( precision>length ){
- *(--bufpt) = '0'; /* Zero pad */
- length++;
+ if( precision>length ){ /* zero pad */
+ int nn = precision-length;
+ bufpt -= nn;
+ memset(bufpt,'0',nn);
+ length = precision;
}
if( cThousand ){
int nn = (length - 1)/3; /* Number of "," to insert */
@@ -27731,59 +32905,84 @@ SQLITE_API void sqlite3_str_vappendf(
break;
case etFLOAT:
case etEXP:
- case etGENERIC:
+ case etGENERIC: {
+ FpDecode s;
+ int iRound;
+ int j;
+ i64 szBufNeeded; /* Size needed to hold the output */
+
if( bArgList ){
realvalue = getDoubleArg(pArgList);
}else{
realvalue = va_arg(ap,double);
}
-#ifdef SQLITE_OMIT_FLOATING_POINT
- length = 0;
-#else
if( precision<0 ) precision = 6; /* Set default precision */
- if( realvalue<0.0 ){
- realvalue = -realvalue;
- prefix = '-';
- }else{
- prefix = flag_prefix;
+#ifdef SQLITE_FP_PRECISION_LIMIT
+ if( precision>SQLITE_FP_PRECISION_LIMIT ){
+ precision = SQLITE_FP_PRECISION_LIMIT;
}
- 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;
- /* Normalize realvalue to within 10.0 > realvalue >= 1.0 */
- exp = 0;
- if( sqlite3IsNaN((double)realvalue) ){
- bufpt = "NaN";
- length = 3;
- break;
+#endif
+ if( xtype==etFLOAT ){
+ iRound = -precision;
+ }else if( xtype==etGENERIC ){
+ if( precision==0 ) precision = 1;
+ iRound = precision;
+ }else{
+ iRound = precision+1;
}
- if( realvalue>0.0 ){
- LONGDOUBLE_TYPE scale = 1.0;
- while( realvalue>=1e100*scale && exp<=350 ){ scale *= 1e100;exp+=100;}
- while( realvalue>=1e10*scale && exp<=350 ){ scale *= 1e10; exp+=10; }
- while( realvalue>=10.0*scale && exp<=350 ){ scale *= 10.0; exp++; }
- realvalue /= scale;
- while( realvalue<1e-8 ){ realvalue *= 1e8; exp-=8; }
- while( realvalue<1.0 ){ realvalue *= 10.0; exp--; }
- if( exp>350 ){
+ sqlite3FpDecode(&s, realvalue, iRound, flag_altform2 ? 20 : 16);
+ if( s.isSpecial ){
+ if( s.isSpecial==2 ){
+ bufpt = flag_zeropad ? "null" : "NaN";
+ length = sqlite3Strlen30(bufpt);
+ break;
+ }else if( flag_zeropad ){
+ s.z[0] = '9';
+ s.iDP = 1000;
+ s.n = 1;
+ }else{
+ memcpy(buf, "-Inf", 5);
bufpt = buf;
- buf[0] = prefix;
- memcpy(buf+(prefix!=0),"Inf",4);
- length = 3+(prefix!=0);
+ if( s.sign=='-' ){
+ /* no-op */
+ }else if( flag_prefix ){
+ buf[0] = flag_prefix;
+ }else{
+ bufpt++;
+ }
+ length = sqlite3Strlen30(bufpt);
break;
}
}
- bufpt = buf;
+ if( s.sign=='-' ){
+ if( flag_alternateform
+ && !flag_prefix
+ && xtype==etFLOAT
+ && s.iDP<=iRound
+ ){
+ /* Suppress the minus sign if all of the following are true:
+ ** * The value displayed is zero
+ ** * The '#' flag is used
+ ** * The '+' flag is not used, and
+ ** * The format is %f
+ */
+ prefix = 0;
+ }else{
+ prefix = '-';
+ }
+ }else{
+ prefix = flag_prefix;
+ }
+
+ exp = s.iDP-1;
+
/*
** If the field type is etGENERIC, then convert to either etEXP
** or etFLOAT, as appropriate.
*/
- if( xtype!=etFLOAT ){
- realvalue += rounder;
- if( realvalue>=10.0 ){ realvalue *= 0.1; exp++; }
- }
if( xtype==etGENERIC ){
+ assert( precision>0 );
+ precision--;
flag_rtz = !flag_alternateform;
if( exp<-4 || exp>precision ){
xtype = etEXP;
@@ -27797,29 +32996,58 @@ SQLITE_API void sqlite3_str_vappendf(
if( xtype==etEXP ){
e2 = 0;
}else{
- e2 = exp;
+ e2 = s.iDP - 1;
}
- {
- 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;
+
+ szBufNeeded = MAX(e2,0)+(i64)precision+(i64)width+10;
+ if( cThousand && e2>0 ) szBufNeeded += (e2+2)/3;
+ if( szBufNeeded + pAccum->nChar >= pAccum->nAlloc ){
+ if( pAccum->mxAlloc==0 && pAccum->accError==0 ){
+ /* Unable to allocate space in pAccum, perhaps because it
+ ** is coming from sqlite3_snprintf() or similar. We'll have
+ ** to render into temporary space and the memcpy() it over. */
+ bufpt = sqlite3_malloc(szBufNeeded);
+ if( bufpt==0 ){
+ sqlite3StrAccumSetError(pAccum, SQLITE_NOMEM);
+ return;
+ }
+ zExtra = bufpt;
+ }else if( sqlite3StrAccumEnlarge(pAccum, szBufNeeded)zText + pAccum->nChar;
}
+ }else{
+ bufpt = pAccum->zText + pAccum->nChar;
}
zOut = bufpt;
- nsd = 16 + flag_altform2*10;
+
flag_dp = (precision>0 ?1:0) | flag_alternateform | flag_altform2;
/* The sign in front of the number */
if( prefix ){
*(bufpt++) = prefix;
}
/* Digits prior to the decimal point */
+ j = 0;
+ assert( s.n>0 );
if( e2<0 ){
*(bufpt++) = '0';
- }else{
+ }else if( cThousand ){
for(; e2>=0; e2--){
- *(bufpt++) = et_getdigit(&realvalue,&nsd);
+ *(bufpt++) = j1 ) *(bufpt++) = ',';
+ }
+ }else{
+ j = e2+1;
+ if( j>s.n ) j = s.n;
+ memcpy(bufpt, s.z, j);
+ bufpt += j;
+ e2 -= j;
+ if( e2>=0 ){
+ memset(bufpt, '0', e2+1);
+ bufpt += e2+1;
+ e2 = -1;
}
}
/* The decimal point */
@@ -27828,13 +33056,26 @@ SQLITE_API void sqlite3_str_vappendf(
}
/* "0" digits after the decimal point but before the first
** significant digit of the number */
- for(e2++; e2<0; precision--, e2++){
- assert( precision>0 );
- *(bufpt++) = '0';
+ if( e2<(-1) && precision>0 ){
+ int nn = -1-e2;
+ if( nn>precision ) nn = precision;
+ memset(bufpt, '0', nn);
+ bufpt += nn;
+ precision -= nn;
}
/* Significant digits after the decimal point */
- while( (precision--)>0 ){
- *(bufpt++) = et_getdigit(&realvalue,&nsd);
+ if( precision>0 ){
+ int nn = s.n - j;
+ if( NEVER(nn>precision) ) nn = precision;
+ if( nn>0 ){
+ memcpy(bufpt, s.z+j, nn);
+ bufpt += nn;
+ precision -= nn;
+ }
+ if( precision>0 && !flag_rtz ){
+ memset(bufpt, '0', precision);
+ bufpt += precision;
+ }
}
/* Remove trailing zeros and the "." if no digits follow the "." */
if( flag_rtz && flag_dp ){
@@ -27850,6 +33091,7 @@ SQLITE_API void sqlite3_str_vappendf(
}
/* Add the "eNNN" suffix */
if( xtype==etEXP ){
+ exp = s.iDP - 1;
*(bufpt++) = aDigits[infop->charset];
if( exp<0 ){
*(bufpt++) = '-'; exp = -exp;
@@ -27863,28 +33105,40 @@ SQLITE_API void sqlite3_str_vappendf(
*(bufpt++) = (char)(exp/10+'0'); /* 10's digit */
*(bufpt++) = (char)(exp%10+'0'); /* 1's digit */
}
- *bufpt = 0;
- /* The converted number is in buf[] and zero terminated. Output it.
- ** Note that the number is in the usual order, not reversed as with
- ** integer conversions. */
length = (int)(bufpt-zOut);
- bufpt = zOut;
-
- /* Special case: Add leading zeros if the flag_zeropad flag is
- ** set and we are not left justified */
- if( flag_zeropad && !flag_leftjustify && length < width){
- int i;
- int nPad = width - length;
- for(i=width; i>=nPad; i--){
- bufpt[i] = bufpt[i-nPad];
+ assert( length <= szBufNeeded );
+ if( lengthnChar += length;
+ zOut[length] = 0;
+ continue;
+ }else{
+ /* We were unable to render directly into pAccum because we
+ ** couldn't allocate sufficient memory. We need to memcpy()
+ ** the rendering (or some prefix thereof) into the output
+ ** buffer. */
+ bufpt[0] = 0;
+ bufpt = zExtra;
+ break;
+ }
+ }
case etSIZE:
if( !bArgList ){
*(va_arg(ap,int*)) = pAccum->nChar;
@@ -27912,34 +33166,28 @@ SQLITE_API void sqlite3_str_vappendf(
}
}else{
unsigned int ch = va_arg(ap,unsigned int);
- if( ch<0x00080 ){
- buf[0] = ch & 0xff;
- length = 1;
- }else if( ch<0x00800 ){
- buf[0] = 0xc0 + (u8)((ch>>6)&0x1f);
- buf[1] = 0x80 + (u8)(ch & 0x3f);
- length = 2;
- }else if( ch<0x10000 ){
- buf[0] = 0xe0 + (u8)((ch>>12)&0x0f);
- buf[1] = 0x80 + (u8)((ch>>6) & 0x3f);
- buf[2] = 0x80 + (u8)(ch & 0x3f);
- length = 3;
- }else{
- buf[0] = 0xf0 + (u8)((ch>>18) & 0x07);
- buf[1] = 0x80 + (u8)((ch>>12) & 0x3f);
- buf[2] = 0x80 + (u8)((ch>>6) & 0x3f);
- buf[3] = 0x80 + (u8)(ch & 0x3f);
- length = 4;
- }
+ length = sqlite3AppendOneUtf8Character(buf, ch);
}
if( precision>1 ){
+ i64 nPrior = 1;
width -= precision-1;
if( width>1 && !flag_leftjustify ){
sqlite3_str_appendchar(pAccum, width-1, ' ');
width = 0;
}
- while( precision-- > 1 ){
- sqlite3_str_append(pAccum, buf, length);
+ sqlite3_str_append(pAccum, buf, length);
+ precision--;
+ while( precision > 1 ){
+ i64 nCopyBytes;
+ if( nPrior > precision-1 ) nPrior = precision - 1;
+ nCopyBytes = length*nPrior;
+ if( sqlite3StrAccumEnlargeIfNeeded(pAccum, nCopyBytes) ){
+ break;
+ }
+ sqlite3_str_append(pAccum,
+ &pAccum->zText[pAccum->nChar-nCopyBytes], nCopyBytes);
+ precision -= nPrior;
+ nPrior *= 2;
}
}
bufpt = buf;
@@ -27997,23 +33245,32 @@ SQLITE_API void sqlite3_str_vappendf(
while( ii>=0 ) if( (bufpt[ii--] & 0xc0)==0x80 ) width++;
}
break;
- case etSQLESCAPE: /* %q: Escape ' characters */
- case etSQLESCAPE2: /* %Q: Escape ' and enclose in '...' */
- case etSQLESCAPE3: { /* %w: Escape " characters */
- int i, j, k, n, isnull;
- int needQuote;
+ case etESCAPE_q: /* %q: Escape ' characters */
+ case etESCAPE_Q: /* %Q: Escape ' and enclose in '...' */
+ case etESCAPE_w: { /* %w: Escape " characters */
+ i64 i, j, k, n;
+ int needQuote = 0;
char ch;
- char q = ((xtype==etSQLESCAPE3)?'"':'\''); /* Quote character */
char *escarg;
+ char q;
if( bArgList ){
escarg = getTextArg(pArgList);
}else{
escarg = va_arg(ap,char*);
}
- isnull = escarg==0;
- if( isnull ) escarg = (xtype==etSQLESCAPE2 ? "NULL" : "(NULL)");
- /* For %q, %Q, and %w, the precision is the number of byte (or
+ if( escarg==0 ){
+ escarg = (xtype==etESCAPE_Q ? "NULL" : "(NULL)");
+ }else if( xtype==etESCAPE_Q ){
+ needQuote = 1;
+ }
+ if( xtype==etESCAPE_w ){
+ q = '"';
+ flag_alternateform = 0;
+ }else{
+ q = '\'';
+ }
+ /* 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.
@@ -28025,7 +33282,30 @@ SQLITE_API void sqlite3_str_vappendf(
while( (escarg[i+1]&0xc0)==0x80 ){ i++; }
}
}
- needQuote = !isnull && xtype==etSQLESCAPE2;
+ if( flag_alternateform ){
+ /* For %#q, do unistr()-style backslash escapes for
+ ** all control characters, and for backslash itself.
+ ** For %#Q, do the same but only if there is at least
+ ** one control character. */
+ i64 nBack = 0;
+ i64 nCtrl = 0;
+ for(k=0; ketBUFSIZE ){
bufpt = zExtra = printfTempBuf(pAccum, n);
@@ -28034,43 +33314,97 @@ SQLITE_API void sqlite3_str_vappendf(
bufpt = buf;
}
j = 0;
- if( needQuote ) bufpt[j++] = q;
+ if( needQuote ){
+ if( needQuote==2 ){
+ memcpy(&bufpt[j], "unistr('", 8);
+ j += 8;
+ }else{
+ bufpt[j++] = '\'';
+ }
+ }
k = i;
- for(i=0; i=0x10 ? '1' : '0';
+ bufpt[j++] = "0123456789abcdef"[ch&0xf];
+ }
+ }
+ }else{
+ for(i=0; iprintfFlags & SQLITE_PRINTF_INTERNAL)==0 ) return;
- pToken = va_arg(ap, Token*);
- assert( bArgList==0 );
- if( pToken && pToken->n ){
- sqlite3_str_append(pAccum, (const char*)pToken->z, pToken->n);
+ if( flag_alternateform ){
+ /* %#T means an Expr pointer that uses Expr.u.zToken */
+ Expr *pExpr = va_arg(ap,Expr*);
+ if( ALWAYS(pExpr) && ALWAYS(!ExprHasProperty(pExpr,EP_IntValue)) ){
+ sqlite3_str_appendall(pAccum, (const char*)pExpr->u.zToken);
+ sqlite3RecordErrorOffsetOfExpr(pAccum->db, pExpr);
+ }
+ }else{
+ /* %T means a Token pointer */
+ Token *pToken = va_arg(ap, Token*);
+ assert( bArgList==0 );
+ if( pToken && pToken->n ){
+ sqlite3_str_append(pAccum, (const char*)pToken->z, pToken->n);
+ sqlite3RecordErrorByteOffset(pAccum->db, pToken->z);
+ }
}
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->fg.fixedSchema==0
+ && pItem->fg.isSubquery==0
+ && pItem->u4.zDatabase!=0
+ ){
+ sqlite3_str_appendall(pAccum, pItem->u4.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->fg.isSubquery) ){/* Because of tag-20240424-1 */
+ Select *pSel = pItem->u4.pSubq->pSelect;
+ assert( pSel!=0 );
+ if( pSel->selFlags & SF_NestedFrom ){
+ sqlite3_str_appendf(pAccum, "(join-%u)", pSel->selId);
+ }else if( pSel->selFlags & SF_MultiValue ){
+ assert( !pItem->fg.isTabFunc && !pItem->fg.isIndexedBy );
+ sqlite3_str_appendf(pAccum, "%u-ROW VALUES CLAUSE",
+ pItem->u1.nRow);
+ }else{
+ sqlite3_str_appendf(pAccum, "(subquery-%u)", pSel->selId);
+ }
}
- sqlite3_str_appendall(pAccum, pItem->zName);
length = width = 0;
break;
}
@@ -28103,6 +33437,45 @@ SQLITE_API void sqlite3_str_vappendf(
}/* End for loop over the format string */
} /* End of function */
+
+/*
+** The z string points to the first character of a token that is
+** associated with an error. If db does not already have an error
+** byte offset recorded, try to compute the error byte offset for
+** z and set the error byte offset in db.
+*/
+SQLITE_PRIVATE void sqlite3RecordErrorByteOffset(sqlite3 *db, const char *z){
+ const Parse *pParse;
+ const char *zText;
+ const char *zEnd;
+ assert( z!=0 );
+ if( NEVER(db==0) ) return;
+ if( db->errByteOffset!=(-2) ) return;
+ pParse = db->pParse;
+ if( NEVER(pParse==0) ) return;
+ zText =pParse->zTail;
+ if( NEVER(zText==0) ) return;
+ zEnd = &zText[strlen(zText)];
+ if( SQLITE_WITHIN(z,zText,zEnd) ){
+ db->errByteOffset = (int)(z-zText);
+ }
+}
+
+/*
+** If pExpr has a byte offset for the start of a token, record that as
+** as the error offset.
+*/
+SQLITE_PRIVATE void sqlite3RecordErrorOffsetOfExpr(sqlite3 *db, const Expr *pExpr){
+ while( pExpr
+ && (ExprHasProperty(pExpr,EP_OuterON|EP_InnerON) || pExpr->w.iOfst<=0)
+ ){
+ pExpr = pExpr->pLeft;
+ }
+ if( pExpr==0 ) return;
+ if( ExprHasProperty(pExpr, EP_FromDDL) ) return;
+ db->errByteOffset = pExpr->w.iOfst;
+}
+
/*
** Enlarge the memory allocation on a StrAccum object so that it is
** able to accept at least N more bytes of text.
@@ -28110,21 +33483,20 @@ SQLITE_API void sqlite3_str_vappendf(
** Return the number of bytes of text that StrAccum is able to accept
** after the attempted enlargement. The value returned might be zero.
*/
-static int sqlite3StrAccumEnlarge(StrAccum *p, int N){
+SQLITE_PRIVATE int sqlite3StrAccumEnlarge(StrAccum *p, i64 N){
char *zNew;
- assert( p->nChar+(i64)N >= p->nAlloc ); /* Only called if really needed */
+ assert( p->nChar+N >= p->nAlloc ); /* Only called if really needed */
if( p->accError ){
testcase(p->accError==SQLITE_TOOBIG);
testcase(p->accError==SQLITE_NOMEM);
return 0;
}
if( p->mxAlloc==0 ){
- setStrAccumError(p, SQLITE_TOOBIG);
+ sqlite3StrAccumSetError(p, SQLITE_TOOBIG);
return p->nAlloc - p->nChar - 1;
}else{
char *zOld = isMalloced(p) ? p->zText : 0;
- i64 szNew = p->nChar;
- szNew += N + 1;
+ i64 szNew = p->nChar + 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 */
@@ -28132,7 +33504,7 @@ static int sqlite3StrAccumEnlarge(StrAccum *p, int N){
}
if( szNew > p->mxAlloc ){
sqlite3_str_reset(p);
- setStrAccumError(p, SQLITE_TOOBIG);
+ sqlite3StrAccumSetError(p, SQLITE_TOOBIG);
return 0;
}else{
p->nAlloc = (int)szNew;
@@ -28140,7 +33512,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 );
@@ -28150,11 +33522,19 @@ static int sqlite3StrAccumEnlarge(StrAccum *p, int N){
p->printfFlags |= SQLITE_PRINTF_MALLOCED;
}else{
sqlite3_str_reset(p);
- setStrAccumError(p, SQLITE_NOMEM);
+ sqlite3StrAccumSetError(p, SQLITE_NOMEM);
return 0;
}
}
- return N;
+ assert( N>=0 && N<=0x7fffffff );
+ return (int)N;
+}
+
+SQLITE_PRIVATE int sqlite3StrAccumEnlargeIfNeeded(StrAccum *p, i64 N){
+ if( N + p->nChar >= p->nAlloc ){
+ sqlite3StrAccumEnlarge(p, N);
+ }
+ return p->accError;
}
/*
@@ -28218,12 +33598,12 @@ SQLITE_API void sqlite3_str_appendall(sqlite3_str *p, const char *z){
static SQLITE_NOINLINE char *strAccumFinishRealloc(StrAccum *p){
char *zText;
assert( p->mxAlloc>0 && !isMalloced(p) );
- zText = sqlite3DbMallocRaw(p->db, p->nChar+1 );
+ zText = sqlite3DbMallocRaw(p->db, 1+(u64)p->nChar );
if( zText ){
memcpy(zText, p->zText, p->nChar+1);
p->printfFlags |= SQLITE_PRINTF_MALLOCED;
}else{
- setStrAccumError(p, SQLITE_NOMEM);
+ sqlite3StrAccumSetError(p, SQLITE_NOMEM);
}
p->zText = zText;
return zText;
@@ -28238,6 +33618,22 @@ SQLITE_PRIVATE char *sqlite3StrAccumFinish(StrAccum *p){
return p->zText;
}
+/*
+** Use the content of the StrAccum passed as the second argument
+** as the result of an SQL function.
+*/
+SQLITE_PRIVATE void sqlite3ResultStrAccum(sqlite3_context *pCtx, StrAccum *p){
+ if( p->accError ){
+ sqlite3_result_error_code(pCtx, p->accError);
+ sqlite3_str_reset(p);
+ }else if( isMalloced(p) ){
+ sqlite3_result_text(pCtx, p->zText, p->nChar, SQLITE_DYNAMIC);
+ }else{
+ sqlite3_result_text(pCtx, "", 0, SQLITE_STATIC);
+ sqlite3_str_reset(p);
+ }
+}
+
/*
** This singleton is an sqlite3_str object that is returned if
** sqlite3_malloc() fails to provide space for a real one. This
@@ -28271,6 +33667,14 @@ SQLITE_API int sqlite3_str_length(sqlite3_str *p){
return p ? p->nChar : 0;
}
+/* Truncate the text of the string to be no more than N bytes. */
+SQLITE_API void sqlite3_str_truncate(sqlite3_str *p, int N){
+ if( p!=0 && N>=0 && (u32)NnChar ){
+ p->nChar = N;
+ p->zText[p->nChar] = 0;
+ }
+}
+
/* Return the current value for p */
SQLITE_API char *sqlite3_str_value(sqlite3_str *p){
if( p==0 || p->nChar==0 ) return 0;
@@ -28291,6 +33695,17 @@ SQLITE_API void sqlite3_str_reset(StrAccum *p){
p->zText = 0;
}
+/*
+** Destroy a dynamically allocate sqlite3_str object and all
+** of its content, all in one call.
+*/
+SQLITE_API void sqlite3_str_free(sqlite3_str *p){
+ if( p!=0 && p!=&sqlite3OomStr ){
+ sqlite3_str_reset(p);
+ sqlite3_free(p);
+ }
+}
+
/*
** Initialize a string accumulator.
**
@@ -28369,7 +33784,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;
@@ -28429,14 +33844,33 @@ SQLITE_API char *sqlite3_vsnprintf(int n, char *zBuf, const char *zFormat, va_li
return zBuf;
}
SQLITE_API char *sqlite3_snprintf(int n, char *zBuf, const char *zFormat, ...){
- char *z;
+ StrAccum acc;
va_list ap;
+ if( n<=0 ) return zBuf;
+#ifdef SQLITE_ENABLE_API_ARMOR
+ if( zBuf==0 || zFormat==0 ) {
+ (void)SQLITE_MISUSE_BKPT;
+ if( zBuf ) zBuf[0] = 0;
+ return zBuf;
+ }
+#endif
+ sqlite3StrAccumInit(&acc, 0, zBuf, n, 0);
va_start(ap,zFormat);
- z = sqlite3_vsnprintf(n, zBuf, zFormat, ap);
+ sqlite3_str_vappendf(&acc, zFormat, ap);
va_end(ap);
- return z;
+ zBuf[acc.nChar] = 0;
+ return zBuf;
}
+/* Maximum size of an sqlite3_log() message. */
+#if defined(SQLITE_MAX_LOG_MESSAGE)
+ /* Leave the definition as supplied */
+#elif SQLITE_PRINT_BUF_SIZE*10>10000
+# define SQLITE_MAX_LOG_MESSAGE 10000
+#else
+# define SQLITE_MAX_LOG_MESSAGE (SQLITE_PRINT_BUF_SIZE*10)
+#endif
+
/*
** This is the routine that actually formats the sqlite3_log() message.
** We house it in a separate routine from sqlite3_log() to avoid using
@@ -28453,7 +33887,7 @@ SQLITE_API char *sqlite3_snprintf(int n, char *zBuf, const char *zFormat, ...){
*/
static void renderLogMsg(int iErrCode, const char *zFormat, va_list ap){
StrAccum acc; /* String accumulator */
- char zMsg[SQLITE_PRINT_BUF_SIZE*3]; /* Complete log message */
+ char zMsg[SQLITE_MAX_LOG_MESSAGE]; /* Complete log message */
sqlite3StrAccumInit(&acc, 0, zMsg, sizeof(zMsg), 0);
sqlite3_str_vappendf(&acc, zFormat, ap);
@@ -28482,7 +33916,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);
@@ -28512,6 +33946,75 @@ SQLITE_API void sqlite3_str_appendf(StrAccum *p, const char *zFormat, ...){
va_end(ap);
}
+
+/*****************************************************************************
+** Reference counted string/blob storage
+*****************************************************************************/
+
+/*
+** Increase the reference count of the string by one.
+**
+** The input parameter is returned.
+*/
+SQLITE_PRIVATE char *sqlite3RCStrRef(char *z){
+ RCStr *p = (RCStr*)z;
+ assert( p!=0 );
+ p--;
+ p->nRCRef++;
+ return z;
+}
+
+/*
+** Decrease the reference count by one. Free the string when the
+** reference count reaches zero.
+*/
+SQLITE_PRIVATE void sqlite3RCStrUnref(void *z){
+ RCStr *p = (RCStr*)z;
+ assert( p!=0 );
+ p--;
+ assert( p->nRCRef>0 );
+ if( p->nRCRef>=2 ){
+ p->nRCRef--;
+ }else{
+ sqlite3_free(p);
+ }
+}
+
+/*
+** Create a new string that is capable of holding N bytes of text, not counting
+** the zero byte at the end. The string is uninitialized.
+**
+** The reference count is initially 1. Call sqlite3RCStrUnref() to free the
+** newly allocated string.
+**
+** This routine returns 0 on an OOM.
+*/
+SQLITE_PRIVATE char *sqlite3RCStrNew(u64 N){
+ RCStr *p = sqlite3_malloc64( N + sizeof(*p) + 1 );
+ if( p==0 ) return 0;
+ p->nRCRef = 1;
+ return (char*)&p[1];
+}
+
+/*
+** Change the size of the string so that it is able to hold N bytes.
+** The string might be reallocated, so return the new allocation.
+*/
+SQLITE_PRIVATE char *sqlite3RCStrResize(char *z, u64 N){
+ RCStr *p = (RCStr*)z;
+ RCStr *pNew;
+ assert( p!=0 );
+ p--;
+ assert( p->nRCRef==1 );
+ pNew = sqlite3_realloc64(p, N+sizeof(RCStr)+1);
+ if( pNew==0 ){
+ sqlite3_free(p);
+ return 0;
+ }else{
+ return (char*)&pNew[1];
+ }
+}
+
/************** End of printf.c **********************************************/
/************** Begin file treeview.c ****************************************/
/*
@@ -28528,7 +34031,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.
@@ -28540,40 +34043,44 @@ SQLITE_API void sqlite3_str_appendf(StrAccum *p, const char *zFormat, ...){
** Add a new subitem to the tree. The moreToFollow flag indicates that this
** is not the last item in the tree.
*/
-static TreeView *sqlite3TreeViewPush(TreeView *p, u8 moreToFollow){
+static void sqlite3TreeViewPush(TreeView **pp, u8 moreToFollow){
+ TreeView *p = *pp;
if( p==0 ){
- p = sqlite3_malloc64( sizeof(*p) );
- if( p==0 ) return 0;
+ *pp = p = sqlite3_malloc64( sizeof(*p) );
+ if( p==0 ) return;
memset(p, 0, sizeof(*p));
}else{
p->iLevel++;
}
assert( moreToFollow==0 || moreToFollow==1 );
- if( p->iLevelbLine) ) p->bLine[p->iLevel] = moreToFollow;
- return p;
+ if( p->iLevel<(int)sizeof(p->bLine) ) p->bLine[p->iLevel] = moreToFollow;
}
/*
** Finished with one layer of the tree
*/
-static void sqlite3TreeViewPop(TreeView *p){
+static void sqlite3TreeViewPop(TreeView **pp){
+ TreeView *p = *pp;
if( p==0 ) return;
p->iLevel--;
- if( p->iLevel<0 ) sqlite3_free(p);
+ if( p->iLevel<0 ){
+ sqlite3_free(p);
+ *pp = 0;
+ }
}
/*
** Generate a single line of output for the tree, with a prefix that contains
** all the appropriate tree lines
*/
-static void sqlite3TreeViewLine(TreeView *p, const char *zFormat, ...){
+SQLITE_PRIVATE void sqlite3TreeViewLine(TreeView *p, const char *zFormat, ...){
va_list ap;
int i;
StrAccum acc;
- char zBuf[500];
+ char zBuf[1000];
sqlite3StrAccumInit(&acc, 0, zBuf, sizeof(zBuf), 0);
if( p ){
- for(i=0; iiLevel && ibLine)-1; i++){
+ for(i=0; iiLevel && i<(int)sizeof(p->bLine)-1; i++){
sqlite3_str_append(&acc, p->bLine[i] ? "| " : " ", 4);
}
sqlite3_str_append(&acc, p->bLine[i] ? "|-- " : "'-- ", 4);
@@ -28582,7 +34089,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);
@@ -28594,10 +34101,57 @@ static void sqlite3TreeViewLine(TreeView *p, const char *zFormat, ...){
** Shorthand for starting a new tree item that consists of a single label
*/
static void sqlite3TreeViewItem(TreeView *p, const char *zLabel,u8 moreFollows){
- p = sqlite3TreeViewPush(p, moreFollows);
+ sqlite3TreeViewPush(&p, moreFollows);
sqlite3TreeViewLine(p, "%s", zLabel);
}
+/*
+** Show a list of Column objects in tree format.
+*/
+SQLITE_PRIVATE void sqlite3TreeViewColumnList(
+ TreeView *pView,
+ const Column *aCol,
+ int nCol,
+ u8 moreToFollow
+){
+ int i;
+ sqlite3TreeViewPush(&pView, moreToFollow);
+ sqlite3TreeViewLine(pView, "COLUMNS");
+ for(i=0; inCte>0 ){
- pView = sqlite3TreeViewPush(pView, 1);
+ sqlite3TreeViewPush(&pView, moreToFollow);
for(i=0; inCte; i++){
StrAccum x;
char zLine[1000];
@@ -28622,18 +34176,25 @@ 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->eM10d!=M10d_Any ){
+ sqlite3_str_appendf(&x, " %sMATERIALIZED",
+ pCte->eM10d==M10d_No ? "NOT " : "");
+ }
+ 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);
- sqlite3TreeViewPop(pView);
+ sqlite3TreeViewPop(&pView);
}
- sqlite3TreeViewPop(pView);
+ sqlite3TreeViewPop(&pView);
}
}
@@ -28642,36 +34203,81 @@ SQLITE_PRIVATE void sqlite3TreeViewWith(TreeView *pView, const With *pWith, u8 m
*/
SQLITE_PRIVATE void sqlite3TreeViewSrcList(TreeView *pView, const SrcList *pSrc){
int i;
+ if( pSrc==0 ) return;
for(i=0; inSrc; i++){
- const struct SrcList_item *pItem = &pSrc->a[i];
+ const SrcItem *pItem = &pSrc->a[i];
StrAccum x;
- char zLine[100];
+ int n = 0;
+ char zLine[1000];
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, " tab=%Q nCol=%d ptr=%p",
- pItem->pTab->zName, pItem->pTab->nCol, pItem->pTab);
- }
- if( pItem->zAlias ){
- sqlite3_str_appendf(&x, " (AS %s)", pItem->zAlias);
- }
- if( pItem->fg.jointype & JT_LEFT ){
+ x.printfFlags |= SQLITE_PRINTF_INTERNAL;
+ sqlite3_str_appendf(&x, "{%d:*} %!S", pItem->iCursor, pItem);
+ if( pItem->pSTab ){
+ sqlite3_str_appendf(&x, " tab=%Q nCol=%d ptr=%p used=%llx%s",
+ pItem->pSTab->zName, pItem->pSTab->nCol, pItem->pSTab,
+ pItem->colUsed,
+ pItem->fg.rowidUsed ? "+rowid" : "");
+ }
+ if( (pItem->fg.jointype & (JT_LEFT|JT_RIGHT))==(JT_LEFT|JT_RIGHT) ){
+ sqlite3_str_appendf(&x, " FULL-OUTER-JOIN");
+ }else if( pItem->fg.jointype & JT_LEFT ){
sqlite3_str_appendf(&x, " LEFT-JOIN");
- }
+ }else if( pItem->fg.jointype & JT_RIGHT ){
+ sqlite3_str_appendf(&x, " RIGHT-JOIN");
+ }else if( pItem->fg.jointype & JT_CROSS ){
+ sqlite3_str_appendf(&x, " CROSS-JOIN");
+ }
+ if( pItem->fg.jointype & JT_LTORJ ){
+ sqlite3_str_appendf(&x, " LTORJ");
+ }
+ if( pItem->fg.fromDDL ){
+ sqlite3_str_appendf(&x, " DDL");
+ }
+ if( pItem->fg.isCte ){
+ static const char *aMat[] = {",MAT", "", ",NO-MAT"};
+ sqlite3_str_appendf(&x, " CteUse=%d%s",
+ pItem->u2.pCteUse->nUse,
+ aMat[pItem->u2.pCteUse->eM10d]);
+ }
+ if( pItem->fg.isOn || (pItem->fg.isUsing==0 && pItem->u3.pOn!=0) ){
+ sqlite3_str_appendf(&x, " isOn");
+ }
+ if( pItem->fg.isTabFunc ) sqlite3_str_appendf(&x, " isTabFunc");
+ if( pItem->fg.isCorrelated ) sqlite3_str_appendf(&x, " isCorrelated");
+ if( pItem->fg.isMaterialized ) sqlite3_str_appendf(&x, " isMaterialized");
+ if( pItem->fg.viaCoroutine ) sqlite3_str_appendf(&x, " viaCoroutine");
+ if( pItem->fg.notCte ) sqlite3_str_appendf(&x, " notCte");
+ if( pItem->fg.isNestedFrom ) sqlite3_str_appendf(&x, " isNestedFrom");
+ if( pItem->fg.fixedSchema ) sqlite3_str_appendf(&x, " fixedSchema");
+ if( pItem->fg.hadSchema ) sqlite3_str_appendf(&x, " hadSchema");
+ if( pItem->fg.isSubquery ) sqlite3_str_appendf(&x, " isSubquery");
+
sqlite3StrAccumFinish(&x);
- sqlite3TreeViewItem(pView, zLine, inSrc-1);
- if( pItem->pSelect ){
- sqlite3TreeViewSelect(pView, pItem->pSelect, 0);
+ sqlite3TreeViewItem(pView, zLine, inSrc-1);
+ n = 0;
+ if( pItem->fg.isSubquery ) n++;
+ if( pItem->fg.isTabFunc ) n++;
+ if( pItem->fg.isUsing || pItem->u3.pOn!=0 ) n++;
+ if( pItem->fg.isUsing ){
+ sqlite3TreeViewIdList(pView, pItem->u3.pUsing, (--n)>0, "USING");
+ }else if( pItem->u3.pOn!=0 ){
+ sqlite3TreeViewItem(pView, "ON", (--n)>0);
+ sqlite3TreeViewExpr(pView, pItem->u3.pOn, 0);
+ sqlite3TreeViewPop(&pView);
+ }
+ if( pItem->fg.isSubquery ){
+ assert( n==1 );
+ if( pItem->pSTab ){
+ Table *pTab = pItem->pSTab;
+ sqlite3TreeViewColumnList(pView, pTab->aCol, pTab->nCol, 1);
+ }
+ assert( (int)pItem->fg.isNestedFrom == IsNestedFrom(pItem) );
+ sqlite3TreeViewSelect(pView, pItem->u4.pSubq->pSelect, 0);
}
if( pItem->fg.isTabFunc ){
sqlite3TreeViewExprList(pView, pItem->u1.pFuncArg, 0, "func-args:");
}
- sqlite3TreeViewPop(pView);
+ sqlite3TreeViewPop(&pView);
}
}
@@ -28684,27 +34290,31 @@ SQLITE_PRIVATE void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 m
if( p==0 ){
sqlite3TreeViewLine(pView, "nil-SELECT");
return;
- }
- pView = sqlite3TreeViewPush(pView, moreToFollow);
+ }
+ sqlite3TreeViewPush(&pView, moreToFollow);
if( p->pWith ){
sqlite3TreeViewWith(pView, p->pWith, 1);
cnt = 1;
- sqlite3TreeViewPush(pView, 1);
+ 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( cnt++ ) sqlite3TreeViewPop(pView);
+ 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;
}else{
n = 0;
- if( p->pSrc && p->pSrc->nSrc ) n++;
+ if( p->pSrc && p->pSrc->nSrc && p->pSrc->nAlloc ) n++;
if( p->pWhere ) n++;
if( p->pGroupBy ) n++;
if( p->pHaving ) n++;
@@ -28715,28 +34325,31 @@ 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;
- pView = sqlite3TreeViewPush(pView, (n--)>0);
+ sqlite3TreeViewPush(&pView, (n--)>0);
sqlite3TreeViewLine(pView, "window-functions");
for(pX=p->pWin; pX; pX=pX->pNextWin){
sqlite3TreeViewWinFunc(pView, pX, pX->pNextWin!=0);
}
- sqlite3TreeViewPop(pView);
+ sqlite3TreeViewPop(&pView);
}
#endif
- if( p->pSrc && p->pSrc->nSrc ){
- pView = sqlite3TreeViewPush(pView, (n--)>0);
+ if( p->pSrc && p->pSrc->nSrc && p->pSrc->nAlloc ){
+ sqlite3TreeViewPush(&pView, (n--)>0);
sqlite3TreeViewLine(pView, "FROM");
sqlite3TreeViewSrcList(pView, p->pSrc);
- sqlite3TreeViewPop(pView);
+ sqlite3TreeViewPop(&pView);
}
if( p->pWhere ){
sqlite3TreeViewItem(pView, "WHERE", (n--)>0);
sqlite3TreeViewExpr(pView, p->pWhere, 0);
- sqlite3TreeViewPop(pView);
+ sqlite3TreeViewPop(&pView);
}
if( p->pGroupBy ){
sqlite3TreeViewExprList(pView, p->pGroupBy, (n--)>0, "GROUPBY");
@@ -28744,7 +34357,7 @@ SQLITE_PRIVATE void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 m
if( p->pHaving ){
sqlite3TreeViewItem(pView, "HAVING", (n--)>0);
sqlite3TreeViewExpr(pView, p->pHaving, 0);
- sqlite3TreeViewPop(pView);
+ sqlite3TreeViewPop(&pView);
}
#ifndef SQLITE_OMIT_WINDOWFUNC
if( p->pWinDefn ){
@@ -28753,7 +34366,7 @@ SQLITE_PRIVATE void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 m
for(pX=p->pWinDefn; pX; pX=pX->pNextWin){
sqlite3TreeViewWindow(pView, pX, pX->pNextWin!=0);
}
- sqlite3TreeViewPop(pView);
+ sqlite3TreeViewPop(&pView);
}
#endif
if( p->pOrderBy ){
@@ -28763,11 +34376,11 @@ SQLITE_PRIVATE void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 m
sqlite3TreeViewItem(pView, "LIMIT", (n--)>0);
sqlite3TreeViewExpr(pView, p->pLimit->pLeft, p->pLimit->pRight!=0);
if( p->pLimit->pRight ){
- sqlite3TreeViewItem(pView, "OFFSET", (n--)>0);
+ sqlite3TreeViewItem(pView, "OFFSET", 0);
sqlite3TreeViewExpr(pView, p->pLimit->pRight, 0);
- sqlite3TreeViewPop(pView);
+ sqlite3TreeViewPop(&pView);
}
- sqlite3TreeViewPop(pView);
+ sqlite3TreeViewPop(&pView);
}
if( p->pPrior ){
const char *zOp = "UNION";
@@ -28780,7 +34393,7 @@ SQLITE_PRIVATE void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 m
}
p = p->pPrior;
}while( p!=0 );
- sqlite3TreeViewPop(pView);
+ sqlite3TreeViewPop(&pView);
}
#ifndef SQLITE_OMIT_WINDOWFUNC
@@ -28796,24 +34409,24 @@ SQLITE_PRIVATE void sqlite3TreeViewBound(
switch( eBound ){
case TK_UNBOUNDED: {
sqlite3TreeViewItem(pView, "UNBOUNDED", moreToFollow);
- sqlite3TreeViewPop(pView);
+ sqlite3TreeViewPop(&pView);
break;
}
case TK_CURRENT: {
sqlite3TreeViewItem(pView, "CURRENT", moreToFollow);
- sqlite3TreeViewPop(pView);
+ sqlite3TreeViewPop(&pView);
break;
}
case TK_PRECEDING: {
sqlite3TreeViewItem(pView, "PRECEDING", moreToFollow);
sqlite3TreeViewExpr(pView, pExpr, 0);
- sqlite3TreeViewPop(pView);
+ sqlite3TreeViewPop(&pView);
break;
}
case TK_FOLLOWING: {
sqlite3TreeViewItem(pView, "FOLLOWING", moreToFollow);
sqlite3TreeViewExpr(pView, pExpr, 0);
- sqlite3TreeViewPop(pView);
+ sqlite3TreeViewPop(&pView);
break;
}
}
@@ -28826,12 +34439,14 @@ SQLITE_PRIVATE void sqlite3TreeViewBound(
*/
SQLITE_PRIVATE void sqlite3TreeViewWindow(TreeView *pView, const Window *pWin, u8 more){
int nElement = 0;
+ if( pWin==0 ) return;
if( pWin->pFilter ){
sqlite3TreeViewItem(pView, "FILTER", 1);
sqlite3TreeViewExpr(pView, pWin->pFilter, 0);
- sqlite3TreeViewPop(pView);
+ sqlite3TreeViewPop(&pView);
+ if( pWin->eFrmType==TK_FILTER ) return;
}
- pView = sqlite3TreeViewPush(pView, more);
+ sqlite3TreeViewPush(&pView, more);
if( pWin->zName ){
sqlite3TreeViewLine(pView, "OVER %s (%p)", pWin->zName, pWin);
}else{
@@ -28839,12 +34454,12 @@ SQLITE_PRIVATE void sqlite3TreeViewWindow(TreeView *pView, const Window *pWin, u
}
if( pWin->zBase ) nElement++;
if( pWin->pOrderBy ) nElement++;
- if( pWin->eFrmType ) nElement++;
+ if( pWin->eFrmType!=0 && pWin->eFrmType!=TK_FILTER ) nElement++;
if( pWin->eExclude ) nElement++;
if( pWin->zBase ){
- sqlite3TreeViewPush(pView, (--nElement)>0);
+ sqlite3TreeViewPush(&pView, (--nElement)>0);
sqlite3TreeViewLine(pView, "window: %s", pWin->zBase);
- sqlite3TreeViewPop(pView);
+ sqlite3TreeViewPop(&pView);
}
if( pWin->pPartition ){
sqlite3TreeViewExprList(pView, pWin->pPartition, nElement>0,"PARTITION-BY");
@@ -28852,7 +34467,7 @@ SQLITE_PRIVATE void sqlite3TreeViewWindow(TreeView *pView, const Window *pWin, u
if( pWin->pOrderBy ){
sqlite3TreeViewExprList(pView, pWin->pOrderBy, (--nElement)>0, "ORDER-BY");
}
- if( pWin->eFrmType ){
+ if( pWin->eFrmType!=0 && pWin->eFrmType!=TK_FILTER ){
char zBuf[30];
const char *zFrmType = "ROWS";
if( pWin->eFrmType==TK_RANGE ) zFrmType = "RANGE";
@@ -28862,7 +34477,7 @@ SQLITE_PRIVATE void sqlite3TreeViewWindow(TreeView *pView, const Window *pWin, u
sqlite3TreeViewItem(pView, zBuf, (--nElement)>0);
sqlite3TreeViewBound(pView, pWin->eStart, pWin->pStart, 1);
sqlite3TreeViewBound(pView, pWin->eEnd, pWin->pEnd, 0);
- sqlite3TreeViewPop(pView);
+ sqlite3TreeViewPop(&pView);
}
if( pWin->eExclude ){
char zBuf[30];
@@ -28877,11 +34492,11 @@ SQLITE_PRIVATE void sqlite3TreeViewWindow(TreeView *pView, const Window *pWin, u
zExclude = zBuf;
break;
}
- sqlite3TreeViewPush(pView, 0);
+ sqlite3TreeViewPush(&pView, 0);
sqlite3TreeViewLine(pView, "EXCLUDE %s", zExclude);
- sqlite3TreeViewPop(pView);
+ sqlite3TreeViewPop(&pView);
}
- sqlite3TreeViewPop(pView);
+ sqlite3TreeViewPop(&pView);
}
#endif /* SQLITE_OMIT_WINDOWFUNC */
@@ -28890,11 +34505,12 @@ SQLITE_PRIVATE void sqlite3TreeViewWindow(TreeView *pView, const Window *pWin, u
** Generate a human-readable explanation for a Window Function object
*/
SQLITE_PRIVATE void sqlite3TreeViewWinFunc(TreeView *pView, const Window *pWin, u8 more){
- pView = sqlite3TreeViewPush(pView, more);
+ if( pWin==0 ) return;
+ sqlite3TreeViewPush(&pView, more);
sqlite3TreeViewLine(pView, "WINFUNC %s(%d)",
- pWin->pFunc->zName, pWin->pFunc->nArg);
+ pWin->pWFunc->zName, pWin->pWFunc->nArg);
sqlite3TreeViewWindow(pView, pWin, 0);
- sqlite3TreeViewPop(pView);
+ sqlite3TreeViewPop(&pView);
}
#endif /* SQLITE_OMIT_WINDOWFUNC */
@@ -28904,20 +34520,34 @@ 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];
- pView = sqlite3TreeViewPush(pView, moreToFollow);
+ char zFlgs[200];
+ sqlite3TreeViewPush(&pView, moreToFollow);
if( pExpr==0 ){
sqlite3TreeViewLine(pView, "nil");
- sqlite3TreeViewPop(pView);
+ sqlite3TreeViewPop(&pView);
return;
}
- if( pExpr->flags ){
- 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);
+ if( pExpr->flags || pExpr->affExpr || pExpr->vvaFlags || pExpr->pAggInfo ){
+ 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_OuterON) ){
+ sqlite3_str_appendf(&x, " outer.iJoin=%d", pExpr->w.iJoin);
+ }
+ if( ExprHasProperty(pExpr, EP_InnerON) ){
+ sqlite3_str_appendf(&x, " inner.iJoin=%d", pExpr->w.iJoin);
+ }
+ if( ExprHasProperty(pExpr, EP_FromDDL) ){
+ sqlite3_str_appendf(&x, " DDL");
+ }
+ if( ExprHasVVAProperty(pExpr, EP_Immutable) ){
+ sqlite3_str_appendf(&x, " IMMUTABLE");
}
+ if( pExpr->pAggInfo!=0 ){
+ sqlite3_str_appendf(&x, " agg-column[%d]", pExpr->iAgg);
+ }
+ sqlite3StrAccumFinish(&x);
}else{
zFlgs[0] = 0;
}
@@ -28930,10 +34560,19 @@ 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);
+ assert( ExprUseYTab(pExpr) );
+ 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);
@@ -28950,11 +34589,13 @@ SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 m
}
#ifndef SQLITE_OMIT_FLOATING_POINT
case TK_FLOAT: {
+ assert( !ExprHasProperty(pExpr, EP_IntValue) );
sqlite3TreeViewLine(pView,"%s", pExpr->u.zToken);
break;
}
#endif
case TK_STRING: {
+ assert( !ExprHasProperty(pExpr, EP_IntValue) );
sqlite3TreeViewLine(pView,"%Q", pExpr->u.zToken);
break;
}
@@ -28963,17 +34604,19 @@ SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 m
break;
}
case TK_TRUEFALSE: {
- sqlite3TreeViewLine(pView,
- sqlite3ExprTruthValue(pExpr) ? "TRUE" : "FALSE");
+ sqlite3TreeViewLine(pView,"%s%s",
+ sqlite3ExprTruthValue(pExpr) ? "TRUE" : "FALSE", zFlgs);
break;
}
#ifndef SQLITE_OMIT_BLOB_LITERAL
case TK_BLOB: {
+ assert( !ExprHasProperty(pExpr, EP_IntValue) );
sqlite3TreeViewLine(pView,"%s", pExpr->u.zToken);
break;
}
#endif
case TK_VARIABLE: {
+ assert( !ExprHasProperty(pExpr, EP_IntValue) );
sqlite3TreeViewLine(pView,"VARIABLE(%s,%d)",
pExpr->u.zToken, pExpr->iColumn);
break;
@@ -28983,12 +34626,14 @@ SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 m
break;
}
case TK_ID: {
+ assert( !ExprHasProperty(pExpr, EP_IntValue) );
sqlite3TreeViewLine(pView,"ID \"%w\"", pExpr->u.zToken);
break;
}
#ifndef SQLITE_OMIT_CAST
case TK_CAST: {
/* Expressions of the form: CAST(pLeft AS token) */
+ assert( !ExprHasProperty(pExpr, EP_IntValue) );
sqlite3TreeViewLine(pView,"CAST %Q", pExpr->u.zToken);
sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
break;
@@ -29015,6 +34660,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;
@@ -29030,20 +34676,30 @@ 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( sqlite3ExprSkipCollateAndLikely(pExpr->pRight)->op
+ == TK_TRUEFALSE );
x = (pExpr->op2==TK_ISNOT)*2 + sqlite3ExprTruthValue(pExpr->pRight);
zUniOp = azOp[x];
break;
}
case TK_SPAN: {
+ assert( !ExprHasProperty(pExpr, EP_IntValue) );
sqlite3TreeViewLine(pView, "SPAN %Q", pExpr->u.zToken);
sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
break;
}
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" */
+ assert( !ExprHasProperty(pExpr, EP_IntValue) );
+ sqlite3TreeViewLine(pView, "%sCOLLATE %Q%s",
+ !ExprHasProperty(pExpr, EP_Collate) ? "SOFT-" : "",
+ pExpr->u.zToken, zFlgs);
sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
break;
}
@@ -29056,21 +34712,42 @@ SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 m
pFarg = 0;
pWin = 0;
}else{
+ assert( ExprUseXList(pExpr) );
pFarg = pExpr->x.pList;
#ifndef SQLITE_OMIT_WINDOWFUNC
- pWin = pExpr->y.pWin;
+ pWin = IsWindowFunc(pExpr) ? pExpr->y.pWin : 0;
#else
pWin = 0;
-#endif
+#endif
}
+ assert( !ExprHasProperty(pExpr, EP_IntValue) );
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);
+ sqlite3TreeViewExprList(pView, pFarg, pWin!=0 || pExpr->pLeft, 0);
+ if( pExpr->pLeft ){
+ Expr *pOB = pExpr->pLeft;
+ assert( pOB->op==TK_ORDER );
+ assert( ExprUseXList(pOB) );
+ sqlite3TreeViewExprList(pView, pOB->x.pList, pWin!=0, "ORDERBY");
+ }
}
#ifndef SQLITE_OMIT_WINDOWFUNC
if( pWin ){
@@ -29079,21 +34756,37 @@ SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 m
#endif
break;
}
+ case TK_ORDER: {
+ sqlite3TreeViewExprList(pView, pExpr->x.pList, 0, "ORDERBY");
+ break;
+ }
#ifndef SQLITE_OMIT_SUBQUERY
case TK_EXISTS: {
+ assert( ExprUseXSelect(pExpr) );
sqlite3TreeViewLine(pView, "EXISTS-expr flags=0x%x", pExpr->flags);
sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0);
break;
}
case TK_SELECT: {
- sqlite3TreeViewLine(pView, "SELECT-expr flags=0x%x", pExpr->flags);
+ assert( ExprUseXSelect(pExpr) );
+ sqlite3TreeViewLine(pView, "subquery-expr flags=0x%x", pExpr->flags);
sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0);
break;
}
case TK_IN: {
- sqlite3TreeViewLine(pView, "IN flags=0x%x", pExpr->flags);
+ sqlite3_str *pStr = sqlite3_str_new(0);
+ char *z;
+ sqlite3_str_appendf(pStr, "IN flags=0x%x", pExpr->flags);
+ if( pExpr->iTable ) sqlite3_str_appendf(pStr, " iTable=%d",pExpr->iTable);
+ if( ExprHasProperty(pExpr, EP_Subrtn) ){
+ sqlite3_str_appendf(pStr, " subrtn(%d,%d)",
+ pExpr->y.sub.regReturn, pExpr->y.sub.iAddr);
+ }
+ z = sqlite3_str_finish(pStr);
+ sqlite3TreeViewLine(pView, z);
+ sqlite3_free(z);
sqlite3TreeViewExpr(pView, pExpr->pLeft, 1);
- if( ExprHasProperty(pExpr, EP_xIsSelect) ){
+ if( ExprUseXSelect(pExpr) ){
sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0);
}else{
sqlite3TreeViewExprList(pView, pExpr->x.pList, 0, 0);
@@ -29114,10 +34807,13 @@ SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 m
** Z is stored in pExpr->pList->a[1].pExpr.
*/
case TK_BETWEEN: {
- Expr *pX = pExpr->pLeft;
- Expr *pY = pExpr->x.pList->a[0].pExpr;
- Expr *pZ = pExpr->x.pList->a[1].pExpr;
- sqlite3TreeViewLine(pView, "BETWEEN");
+ const Expr *pX, *pY, *pZ;
+ pX = pExpr->pLeft;
+ assert( ExprUseXList(pExpr) );
+ assert( pExpr->x.pList->nExpr==2 );
+ pY = pExpr->x.pList->a[0].pExpr;
+ pZ = pExpr->x.pList->a[1].pExpr;
+ sqlite3TreeViewLine(pView, "BETWEEN%s", zFlgs);
sqlite3TreeViewExpr(pView, pX, 1);
sqlite3TreeViewExpr(pView, pY, 1);
sqlite3TreeViewExpr(pView, pZ, 0);
@@ -29131,26 +34827,29 @@ 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;
}
case TK_CASE: {
sqlite3TreeViewLine(pView, "CASE");
sqlite3TreeViewExpr(pView, pExpr->pLeft, 1);
+ assert( ExprUseXList(pExpr) );
sqlite3TreeViewExprList(pView, pExpr->x.pList, 0, 0);
break;
}
#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;
case OE_Ignore: zType = "ignore"; break;
}
- sqlite3TreeViewLine(pView, "RAISE %s(%Q)", zType, pExpr->u.zToken);
+ assert( !ExprHasProperty(pExpr, EP_IntValue) );
+ sqlite3TreeViewLine(pView, "RAISE %s", zType);
+ sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
break;
}
#endif
@@ -29161,11 +34860,17 @@ 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);
+ assert( ExprUseXList(pExpr) );
+ sqlite3TreeViewBareExprList(pView, pExpr->x.pList, z);
+ sqlite3_free(z);
break;
}
case TK_SELECT_COLUMN: {
- sqlite3TreeViewLine(pView, "SELECT-COLUMN %d", pExpr->iColumn);
+ sqlite3TreeViewLine(pView, "SELECT-COLUMN %d of [0..%d]%s",
+ pExpr->iColumn, pExpr->iTable-1,
+ pExpr->pRight==pExpr->pLeft ? " (SELECT-owner)" : "");
+ assert( ExprUseXSelect(pExpr->pLeft) );
sqlite3TreeViewSelect(pView, pExpr->pLeft->x.pSelect, 0);
break;
}
@@ -29174,6 +34879,23 @@ 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;
+ }
+ case TK_ROW: {
+ if( pExpr->iColumn<=0 ){
+ sqlite3TreeViewLine(pView, "First FROM table rowid");
+ }else{
+ sqlite3TreeViewLine(pView, "First FROM table column %d",
+ pExpr->iColumn-1);
+ }
+ break;
+ }
default: {
sqlite3TreeViewLine(pView, "op=%d", pExpr->op);
break;
@@ -29185,9 +34907,9 @@ 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);
+ sqlite3TreeViewPop(&pView);
}
@@ -29207,24 +34929,43 @@ 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;
+ u8 sortFlags = pList->a[i].fg.sortFlags;
+ char *zName = pList->a[i].zEName;
int moreToFollow = inExpr - 1;
- if( j || zName ){
- sqlite3TreeViewPush(pView, moreToFollow);
+ if( j || zName || sortFlags ){
+ sqlite3TreeViewPush(&pView, moreToFollow);
moreToFollow = 0;
sqlite3TreeViewLine(pView, 0);
if( zName ){
- fprintf(stdout, "AS %s ", zName);
+ switch( pList->a[i].fg.eEName ){
+ default:
+ fprintf(stdout, "AS %s ", zName);
+ break;
+ case ENAME_TAB:
+ fprintf(stdout, "TABLE-ALIAS-NAME(\"%s\") ", zName);
+ if( pList->a[i].fg.bUsed ) fprintf(stdout, "(used) ");
+ if( pList->a[i].fg.bUsingTerm ) fprintf(stdout, "(USING-term) ");
+ if( pList->a[i].fg.bNoExpand ) fprintf(stdout, "(NoExpand) ");
+ break;
+ case ENAME_SPAN:
+ fprintf(stdout, "SPAN(\"%s\") ", zName);
+ break;
+ }
}
if( j ){
- fprintf(stdout, "iOrderByCol=%d", j);
+ fprintf(stdout, "iOrderByCol=%d ", j);
+ }
+ if( sortFlags & KEYINFO_ORDER_DESC ){
+ fprintf(stdout, "DESC ");
+ }else if( sortFlags & KEYINFO_ORDER_BIGNULL ){
+ fprintf(stdout, "NULLS-LAST");
}
fprintf(stdout, "\n");
fflush(stdout);
}
sqlite3TreeViewExpr(pView, pList->a[i].pExpr, moreToFollow);
- if( j || zName ){
- sqlite3TreeViewPop(pView);
+ if( j || zName || sortFlags ){
+ sqlite3TreeViewPop(&pView);
}
}
}
@@ -29235,11 +34976,374 @@ SQLITE_PRIVATE void sqlite3TreeViewExprList(
u8 moreToFollow,
const char *zLabel
){
- pView = sqlite3TreeViewPush(pView, moreToFollow);
+ sqlite3TreeViewPush(&pView, moreToFollow);
sqlite3TreeViewBareExprList(pView, pList, zLabel);
- sqlite3TreeViewPop(pView);
+ sqlite3TreeViewPop(&pView);
+}
+
+/*
+** Generate a human-readable explanation of an id-list.
+*/
+SQLITE_PRIVATE void sqlite3TreeViewBareIdList(
+ TreeView *pView,
+ const IdList *pList,
+ const char *zLabel
+){
+ if( zLabel==0 || zLabel[0]==0 ) zLabel = "LIST";
+ if( pList==0 ){
+ sqlite3TreeViewLine(pView, "%s (empty)", zLabel);
+ }else{
+ int i;
+ sqlite3TreeViewLine(pView, "%s", zLabel);
+ for(i=0; inId; i++){
+ char *zName = pList->a[i].zName;
+ int moreToFollow = inId - 1;
+ if( zName==0 ) zName = "(null)";
+ sqlite3TreeViewPush(&pView, moreToFollow);
+ sqlite3TreeViewLine(pView, 0);
+ fprintf(stdout, "%s\n", zName);
+ sqlite3TreeViewPop(&pView);
+ }
+ }
+}
+SQLITE_PRIVATE void sqlite3TreeViewIdList(
+ TreeView *pView,
+ const IdList *pList,
+ u8 moreToFollow,
+ const char *zLabel
+){
+ sqlite3TreeViewPush(&pView, moreToFollow);
+ sqlite3TreeViewBareIdList(pView, pList, zLabel);
+ sqlite3TreeViewPop(&pView);
}
+/*
+** Generate a human-readable explanation of a list of Upsert objects
+*/
+SQLITE_PRIVATE void sqlite3TreeViewUpsert(
+ TreeView *pView,
+ const Upsert *pUpsert,
+ u8 moreToFollow
+){
+ if( pUpsert==0 ) return;
+ sqlite3TreeViewPush(&pView, moreToFollow);
+ while( pUpsert ){
+ int n;
+ sqlite3TreeViewPush(&pView, pUpsert->pNextUpsert!=0 || moreToFollow);
+ sqlite3TreeViewLine(pView, "ON CONFLICT DO %s",
+ pUpsert->isDoUpdate ? "UPDATE" : "NOTHING");
+ n = (pUpsert->pUpsertSet!=0) + (pUpsert->pUpsertWhere!=0);
+ sqlite3TreeViewExprList(pView, pUpsert->pUpsertTarget, (n--)>0, "TARGET");
+ sqlite3TreeViewExprList(pView, pUpsert->pUpsertSet, (n--)>0, "SET");
+ if( pUpsert->pUpsertWhere ){
+ sqlite3TreeViewItem(pView, "WHERE", (n--)>0);
+ sqlite3TreeViewExpr(pView, pUpsert->pUpsertWhere, 0);
+ sqlite3TreeViewPop(&pView);
+ }
+ sqlite3TreeViewPop(&pView);
+ pUpsert = pUpsert->pNextUpsert;
+ }
+ sqlite3TreeViewPop(&pView);
+}
+
+#if TREETRACE_ENABLED
+/*
+** Generate a human-readable diagram of the data structure that go
+** into generating an DELETE statement.
+*/
+SQLITE_PRIVATE void sqlite3TreeViewDelete(
+ const With *pWith,
+ const SrcList *pTabList,
+ const Expr *pWhere,
+ const ExprList *pOrderBy,
+ const Expr *pLimit,
+ const Trigger *pTrigger
+){
+ int n = 0;
+ TreeView *pView = 0;
+ sqlite3TreeViewPush(&pView, 0);
+ sqlite3TreeViewLine(pView, "DELETE");
+ if( pWith ) n++;
+ if( pTabList ) n++;
+ if( pWhere ) n++;
+ if( pOrderBy ) n++;
+ if( pLimit ) n++;
+ if( pTrigger ) n++;
+ if( pWith ){
+ sqlite3TreeViewPush(&pView, (--n)>0);
+ sqlite3TreeViewWith(pView, pWith, 0);
+ sqlite3TreeViewPop(&pView);
+ }
+ if( pTabList ){
+ sqlite3TreeViewPush(&pView, (--n)>0);
+ sqlite3TreeViewLine(pView, "FROM");
+ sqlite3TreeViewSrcList(pView, pTabList);
+ sqlite3TreeViewPop(&pView);
+ }
+ if( pWhere ){
+ sqlite3TreeViewPush(&pView, (--n)>0);
+ sqlite3TreeViewLine(pView, "WHERE");
+ sqlite3TreeViewExpr(pView, pWhere, 0);
+ sqlite3TreeViewPop(&pView);
+ }
+ if( pOrderBy ){
+ sqlite3TreeViewExprList(pView, pOrderBy, (--n)>0, "ORDER-BY");
+ }
+ if( pLimit ){
+ sqlite3TreeViewPush(&pView, (--n)>0);
+ sqlite3TreeViewLine(pView, "LIMIT");
+ sqlite3TreeViewExpr(pView, pLimit, 0);
+ sqlite3TreeViewPop(&pView);
+ }
+ if( pTrigger ){
+ sqlite3TreeViewTrigger(pView, pTrigger, (--n)>0, 1);
+ }
+ sqlite3TreeViewPop(&pView);
+}
+#endif /* TREETRACE_ENABLED */
+
+#if TREETRACE_ENABLED
+/*
+** Generate a human-readable diagram of the data structure that go
+** into generating an INSERT statement.
+*/
+SQLITE_PRIVATE void sqlite3TreeViewInsert(
+ const With *pWith,
+ const SrcList *pTabList,
+ const IdList *pColumnList,
+ const Select *pSelect,
+ const ExprList *pExprList,
+ int onError,
+ const Upsert *pUpsert,
+ const Trigger *pTrigger
+){
+ TreeView *pView = 0;
+ int n = 0;
+ const char *zLabel = "INSERT";
+ switch( onError ){
+ case OE_Replace: zLabel = "REPLACE"; break;
+ case OE_Ignore: zLabel = "INSERT OR IGNORE"; break;
+ case OE_Rollback: zLabel = "INSERT OR ROLLBACK"; break;
+ case OE_Abort: zLabel = "INSERT OR ABORT"; break;
+ case OE_Fail: zLabel = "INSERT OR FAIL"; break;
+ }
+ sqlite3TreeViewPush(&pView, 0);
+ sqlite3TreeViewLine(pView, zLabel);
+ if( pWith ) n++;
+ if( pTabList ) n++;
+ if( pColumnList ) n++;
+ if( pSelect ) n++;
+ if( pExprList ) n++;
+ if( pUpsert ) n++;
+ if( pTrigger ) n++;
+ if( pWith ){
+ sqlite3TreeViewPush(&pView, (--n)>0);
+ sqlite3TreeViewWith(pView, pWith, 0);
+ sqlite3TreeViewPop(&pView);
+ }
+ if( pTabList ){
+ sqlite3TreeViewPush(&pView, (--n)>0);
+ sqlite3TreeViewLine(pView, "INTO");
+ sqlite3TreeViewSrcList(pView, pTabList);
+ sqlite3TreeViewPop(&pView);
+ }
+ if( pColumnList ){
+ sqlite3TreeViewIdList(pView, pColumnList, (--n)>0, "COLUMNS");
+ }
+ if( pSelect ){
+ sqlite3TreeViewPush(&pView, (--n)>0);
+ sqlite3TreeViewLine(pView, "DATA-SOURCE");
+ sqlite3TreeViewSelect(pView, pSelect, 0);
+ sqlite3TreeViewPop(&pView);
+ }
+ if( pExprList ){
+ sqlite3TreeViewExprList(pView, pExprList, (--n)>0, "VALUES");
+ }
+ if( pUpsert ){
+ sqlite3TreeViewPush(&pView, (--n)>0);
+ sqlite3TreeViewLine(pView, "UPSERT");
+ sqlite3TreeViewUpsert(pView, pUpsert, 0);
+ sqlite3TreeViewPop(&pView);
+ }
+ if( pTrigger ){
+ sqlite3TreeViewTrigger(pView, pTrigger, (--n)>0, 1);
+ }
+ sqlite3TreeViewPop(&pView);
+}
+#endif /* TREETRACE_ENABLED */
+
+#if TREETRACE_ENABLED
+/*
+** Generate a human-readable diagram of the data structure that go
+** into generating an UPDATE statement.
+*/
+SQLITE_PRIVATE void sqlite3TreeViewUpdate(
+ const With *pWith,
+ const SrcList *pTabList,
+ const ExprList *pChanges,
+ const Expr *pWhere,
+ int onError,
+ const ExprList *pOrderBy,
+ const Expr *pLimit,
+ const Upsert *pUpsert,
+ const Trigger *pTrigger
+){
+ int n = 0;
+ TreeView *pView = 0;
+ const char *zLabel = "UPDATE";
+ switch( onError ){
+ case OE_Replace: zLabel = "UPDATE OR REPLACE"; break;
+ case OE_Ignore: zLabel = "UPDATE OR IGNORE"; break;
+ case OE_Rollback: zLabel = "UPDATE OR ROLLBACK"; break;
+ case OE_Abort: zLabel = "UPDATE OR ABORT"; break;
+ case OE_Fail: zLabel = "UPDATE OR FAIL"; break;
+ }
+ sqlite3TreeViewPush(&pView, 0);
+ sqlite3TreeViewLine(pView, zLabel);
+ if( pWith ) n++;
+ if( pTabList ) n++;
+ if( pChanges ) n++;
+ if( pWhere ) n++;
+ if( pOrderBy ) n++;
+ if( pLimit ) n++;
+ if( pUpsert ) n++;
+ if( pTrigger ) n++;
+ if( pWith ){
+ sqlite3TreeViewPush(&pView, (--n)>0);
+ sqlite3TreeViewWith(pView, pWith, 0);
+ sqlite3TreeViewPop(&pView);
+ }
+ if( pTabList ){
+ sqlite3TreeViewPush(&pView, (--n)>0);
+ sqlite3TreeViewLine(pView, "FROM");
+ sqlite3TreeViewSrcList(pView, pTabList);
+ sqlite3TreeViewPop(&pView);
+ }
+ if( pChanges ){
+ sqlite3TreeViewExprList(pView, pChanges, (--n)>0, "SET");
+ }
+ if( pWhere ){
+ sqlite3TreeViewPush(&pView, (--n)>0);
+ sqlite3TreeViewLine(pView, "WHERE");
+ sqlite3TreeViewExpr(pView, pWhere, 0);
+ sqlite3TreeViewPop(&pView);
+ }
+ if( pOrderBy ){
+ sqlite3TreeViewExprList(pView, pOrderBy, (--n)>0, "ORDER-BY");
+ }
+ if( pLimit ){
+ sqlite3TreeViewPush(&pView, (--n)>0);
+ sqlite3TreeViewLine(pView, "LIMIT");
+ sqlite3TreeViewExpr(pView, pLimit, 0);
+ sqlite3TreeViewPop(&pView);
+ }
+ if( pUpsert ){
+ sqlite3TreeViewPush(&pView, (--n)>0);
+ sqlite3TreeViewLine(pView, "UPSERT");
+ sqlite3TreeViewUpsert(pView, pUpsert, 0);
+ sqlite3TreeViewPop(&pView);
+ }
+ if( pTrigger ){
+ sqlite3TreeViewTrigger(pView, pTrigger, (--n)>0, 1);
+ }
+ sqlite3TreeViewPop(&pView);
+}
+#endif /* TREETRACE_ENABLED */
+
+#ifndef SQLITE_OMIT_TRIGGER
+/*
+** Show a human-readable graph of a TriggerStep
+*/
+SQLITE_PRIVATE void sqlite3TreeViewTriggerStep(
+ TreeView *pView,
+ const TriggerStep *pStep,
+ u8 moreToFollow,
+ u8 showFullList
+){
+ int cnt = 0;
+ if( pStep==0 ) return;
+ sqlite3TreeViewPush(&pView,
+ moreToFollow || (showFullList && pStep->pNext!=0));
+ do{
+ if( cnt++ && pStep->pNext==0 ){
+ sqlite3TreeViewPop(&pView);
+ sqlite3TreeViewPush(&pView, 0);
+ }
+ sqlite3TreeViewLine(pView, "%s", pStep->zSpan ? pStep->zSpan : "RETURNING");
+ }while( showFullList && (pStep = pStep->pNext)!=0 );
+ sqlite3TreeViewPop(&pView);
+}
+
+/*
+** Show a human-readable graph of a Trigger
+*/
+SQLITE_PRIVATE void sqlite3TreeViewTrigger(
+ TreeView *pView,
+ const Trigger *pTrigger,
+ u8 moreToFollow,
+ u8 showFullList
+){
+ int cnt = 0;
+ if( pTrigger==0 ) return;
+ sqlite3TreeViewPush(&pView,
+ moreToFollow || (showFullList && pTrigger->pNext!=0));
+ do{
+ if( cnt++ && pTrigger->pNext==0 ){
+ sqlite3TreeViewPop(&pView);
+ sqlite3TreeViewPush(&pView, 0);
+ }
+ sqlite3TreeViewLine(pView, "TRIGGER %s", pTrigger->zName);
+ sqlite3TreeViewPush(&pView, 0);
+ sqlite3TreeViewTriggerStep(pView, pTrigger->step_list, 0, 1);
+ sqlite3TreeViewPop(&pView);
+ }while( showFullList && (pTrigger = pTrigger->pNext)!=0 );
+ sqlite3TreeViewPop(&pView);
+}
+#endif /* SQLITE_OMIT_TRIGGER */
+
+
+/*
+** These simplified versions of the tree-view routines omit unnecessary
+** parameters. These variants are intended to be used from a symbolic
+** debugger, such as "gdb", during interactive debugging sessions.
+**
+** This routines are given external linkage so that they will always be
+** accessible to the debugging, and to avoid warnings about unused
+** functions. But these routines only exist in debugging builds, so they
+** do not contaminate the interface.
+**
+** See Also:
+**
+** sqlite3ShowWhereTerm() in where.c
+*/
+SQLITE_PRIVATE void sqlite3ShowExpr(const Expr *p){ sqlite3TreeViewExpr(0,p,0); }
+SQLITE_PRIVATE void sqlite3ShowExprList(const ExprList *p){ sqlite3TreeViewExprList(0,p,0,0);}
+SQLITE_PRIVATE void sqlite3ShowIdList(const IdList *p){ sqlite3TreeViewIdList(0,p,0,0); }
+SQLITE_PRIVATE void sqlite3ShowSrcList(const SrcList *p){
+ TreeView *pView = 0;
+ sqlite3TreeViewPush(&pView, 0);
+ sqlite3TreeViewLine(pView, "SRCLIST");
+ sqlite3TreeViewSrcList(pView,p);
+ sqlite3TreeViewPop(&pView);
+}
+SQLITE_PRIVATE void sqlite3ShowSelect(const Select *p){ sqlite3TreeViewSelect(0,p,0); }
+SQLITE_PRIVATE void sqlite3ShowWith(const With *p){ sqlite3TreeViewWith(0,p,0); }
+SQLITE_PRIVATE void sqlite3ShowUpsert(const Upsert *p){ sqlite3TreeViewUpsert(0,p,0); }
+#ifndef SQLITE_OMIT_TRIGGER
+SQLITE_PRIVATE void sqlite3ShowTriggerStep(const TriggerStep *p){
+ sqlite3TreeViewTriggerStep(0,p,0,0);
+}
+SQLITE_PRIVATE void sqlite3ShowTriggerStepList(const TriggerStep *p){
+ sqlite3TreeViewTriggerStep(0,p,0,1);
+}
+SQLITE_PRIVATE void sqlite3ShowTrigger(const Trigger *p){ sqlite3TreeViewTrigger(0,p,0,0); }
+SQLITE_PRIVATE void sqlite3ShowTriggerList(const Trigger *p){ sqlite3TreeViewTrigger(0,p,0,1);}
+#endif
+#ifndef SQLITE_OMIT_WINDOWFUNC
+SQLITE_PRIVATE void sqlite3ShowWindow(const Window *p){ sqlite3TreeViewWindow(0,p,0); }
+SQLITE_PRIVATE void sqlite3ShowWinFunc(const Window *p){ sqlite3TreeViewWinFunc(0,p,0); }
+#endif
+
#endif /* SQLITE_DEBUG */
/************** End of treeview.c ********************************************/
@@ -29268,16 +35372,41 @@ SQLITE_PRIVATE void sqlite3TreeViewExprList(
** This structure is the current state of the generator.
*/
static SQLITE_WSD struct sqlite3PrngType {
- unsigned char isInit; /* True if initialized */
- unsigned char i, j; /* State variables */
- unsigned char s[256]; /* State variables */
+ u32 s[16]; /* 64 bytes of chacha20 state */
+ u8 out[64]; /* Output bytes */
+ u8 n; /* Output bytes remaining */
} sqlite3Prng;
+
+/* The RFC-7539 ChaCha20 block function
+*/
+#define ROTL(a,b) (((a) << (b)) | ((a) >> (32 - (b))))
+#define QR(a, b, c, d) ( \
+ a += b, d ^= a, d = ROTL(d,16), \
+ c += d, b ^= c, b = ROTL(b,12), \
+ a += b, d ^= a, d = ROTL(d, 8), \
+ c += d, b ^= c, b = ROTL(b, 7))
+static void chacha_block(u32 *out, const u32 *in){
+ int i;
+ u32 x[16];
+ memcpy(x, in, 64);
+ for(i=0; i<10; i++){
+ QR(x[0], x[4], x[ 8], x[12]);
+ QR(x[1], x[5], x[ 9], x[13]);
+ QR(x[2], x[6], x[10], x[14]);
+ QR(x[3], x[7], x[11], x[15]);
+ QR(x[0], x[5], x[10], x[15]);
+ QR(x[1], x[6], x[11], x[12]);
+ QR(x[2], x[7], x[ 8], x[13]);
+ QR(x[3], x[4], x[ 9], x[14]);
+ }
+ for(i=0; i<16; i++) out[i] = x[i]+in[i];
+}
+
/*
** Return N random bytes.
*/
SQLITE_API void sqlite3_randomness(int N, void *pBuf){
- unsigned char t;
unsigned char *zBuf = pBuf;
/* The "wsdPrng" macro will resolve to the pseudo-random number generator
@@ -29307,48 +35436,46 @@ SQLITE_API void sqlite3_randomness(int N, void *pBuf){
sqlite3_mutex_enter(mutex);
if( N<=0 || pBuf==0 ){
- wsdPrng.isInit = 0;
+ wsdPrng.s[0] = 0;
sqlite3_mutex_leave(mutex);
return;
}
/* Initialize the state of the random number generator once,
- ** the first time this routine is called. The seed value does
- ** not need to contain a lot of randomness since we are not
- ** trying to do secure encryption or anything like that...
- **
- ** Nothing in this file or anywhere else in SQLite does any kind of
- ** encryption. The RC4 algorithm is being used as a PRNG (pseudo-random
- ** number generator) not as an encryption device.
+ ** the first time this routine is called.
*/
- if( !wsdPrng.isInit ){
- int i;
- char k[256];
- wsdPrng.j = 0;
- wsdPrng.i = 0;
- sqlite3OsRandomness(sqlite3_vfs_find(0), 256, k);
- for(i=0; i<256; i++){
- wsdPrng.s[i] = (u8)i;
- }
- for(i=0; i<256; i++){
- wsdPrng.j += wsdPrng.s[i] + k[i];
- t = wsdPrng.s[wsdPrng.j];
- wsdPrng.s[wsdPrng.j] = wsdPrng.s[i];
- wsdPrng.s[i] = t;
+ if( wsdPrng.s[0]==0 ){
+ sqlite3_vfs *pVfs = sqlite3_vfs_find(0);
+ static const u32 chacha20_init[] = {
+ 0x61707865, 0x3320646e, 0x79622d32, 0x6b206574
+ };
+ memcpy(&wsdPrng.s[0], chacha20_init, 16);
+ if( NEVER(pVfs==0) ){
+ memset(&wsdPrng.s[4], 0, 44);
+ }else{
+ sqlite3OsRandomness(pVfs, 44, (char*)&wsdPrng.s[4]);
}
- wsdPrng.isInit = 1;
+ wsdPrng.s[15] = wsdPrng.s[12];
+ wsdPrng.s[12] = 0;
+ wsdPrng.n = 0;
}
assert( N>0 );
- do{
- wsdPrng.i++;
- t = wsdPrng.s[wsdPrng.i];
- wsdPrng.j += t;
- wsdPrng.s[wsdPrng.i] = wsdPrng.s[wsdPrng.j];
- wsdPrng.s[wsdPrng.j] = t;
- t += wsdPrng.s[wsdPrng.i];
- *(zBuf++) = wsdPrng.s[t];
- }while( --N );
+ while( 1 /* exit by break */ ){
+ if( N<=wsdPrng.n ){
+ memcpy(zBuf, &wsdPrng.out[wsdPrng.n-N], N);
+ wsdPrng.n -= N;
+ break;
+ }
+ if( wsdPrng.n>0 ){
+ memcpy(zBuf, wsdPrng.out, wsdPrng.n);
+ N -= wsdPrng.n;
+ zBuf += wsdPrng.n;
+ }
+ wsdPrng.s[12]++;
+ chacha_block((u32*)wsdPrng.out, wsdPrng.s);
+ wsdPrng.n = 64;
+ }
sqlite3_mutex_leave(mutex);
}
@@ -29450,13 +35577,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 ){
@@ -29538,9 +35665,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) ){
@@ -29579,6 +35706,7 @@ SQLITE_PRIVATE int sqlite3ThreadJoin(SQLiteThread *p, void **ppOut){
rc = sqlite3Win32Wait((HANDLE)p->tid);
assert( rc!=WAIT_IO_COMPLETION );
bRc = CloseHandle((HANDLE)p->tid);
+ (void)bRc; /* Prevent warning when assert() is a no-op */
assert( bRc );
}
if( rc==WAIT_OBJECT_0 ) *ppOut = p->pResult;
@@ -29669,7 +35797,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:
@@ -29765,24 +35893,33 @@ 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); \
- } \
+/*
+** Write a single UTF8 character whose value is v into the
+** buffer starting at zOut. zOut must be sized to hold at
+** least four bytes. Return the number of bytes needed
+** to encode the new character.
+*/
+SQLITE_PRIVATE int sqlite3AppendOneUtf8Character(char *zOut, u32 v){
+ if( v<0x00080 ){
+ zOut[0] = (u8)(v & 0xff);
+ return 1;
+ }
+ if( v<0x00800 ){
+ zOut[0] = 0xc0 + (u8)((v>>6) & 0x1f);
+ zOut[1] = 0x80 + (u8)(v & 0x3f);
+ return 2;
+ }
+ if( v<0x10000 ){
+ zOut[0] = 0xe0 + (u8)((v>>12) & 0x0f);
+ zOut[1] = 0x80 + (u8)((v>>6) & 0x3f);
+ zOut[2] = 0x80 + (u8)(v & 0x3f);
+ return 3;
+ }
+ zOut[0] = 0xf0 + (u8)((v>>18) & 0x07);
+ zOut[1] = 0x80 + (u8)((v>>12) & 0x3f);
+ zOut[2] = 0x80 + (u8)((v>>6) & 0x3f);
+ zOut[3] = 0x80 + (u8)(v & 0x3f);
+ return 4;
}
/*
@@ -29816,7 +35953,7 @@ static const unsigned char sqlite3Utf8Trans1[] = {
c = *(zIn++); \
if( c>=0xc0 ){ \
c = sqlite3Utf8Trans1[c-0xc0]; \
- while( zIn!=zTerm && (*zIn & 0xc0)==0x80 ){ \
+ while( zIn0 );
+ c = z[0];
+ if( c>=0xc0 ){
+ c = sqlite3Utf8Trans1[c-0xc0];
+ if( n>4 ) n = 4;
+ while( ienc==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;
@@ -29985,9 +36201,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;
@@ -29996,7 +36214,7 @@ SQLITE_PRIVATE SQLITE_NOINLINE int sqlite3VdbeMemTranslate(Mem *pMem, u8 desired
#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.
@@ -30019,7 +36237,7 @@ SQLITE_PRIVATE int sqlite3VdbeMemHandleBom(Mem *pMem){
bom = SQLITE_UTF16LE;
}
}
-
+
if( bom ){
rc = sqlite3VdbeMemMakeWriteable(pMem);
if( rc==SQLITE_OK ){
@@ -30039,7 +36257,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){
@@ -30059,7 +36277,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)
@@ -30113,27 +36331,26 @@ SQLITE_PRIVATE char *sqlite3Utf16to8(sqlite3 *db, const void *z, int nByte, u8 e
}
/*
-** zIn is a UTF-16 encoded unicode string at least nChar characters long.
+** zIn is a UTF-16 encoded unicode string at least nByte bytes long.
** Return the number of bytes in the first nChar unicode characters
-** in pZ. nChar must be non-negative.
+** in pZ. nChar must be non-negative. Surrogate pairs count as a single
+** character.
*/
-SQLITE_PRIVATE int sqlite3Utf16ByteLen(const void *zIn, int nChar){
+SQLITE_PRIVATE int sqlite3Utf16ByteLen(const void *zIn, int nByte, int nChar){
int c;
unsigned char const *z = zIn;
+ unsigned char const *zEnd = &z[nByte-1];
int n = 0;
-
- if( SQLITE_UTF16NATIVE==SQLITE_UTF16BE ){
- while( n=0xd8 && c<0xdc && z<=zEnd && 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)
@@ -30163,30 +36380,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 */
@@ -30212,24 +36405,14 @@ SQLITE_PRIVATE void sqlite3UtfSelfTest(void){
*/
/* #include "sqliteInt.h" */
/* #include */
-#if HAVE_ISNAN || SQLITE_HAVE_ISNAN
-# include
-#endif
-
-/*
-** Routine needed to support the testcase() macro.
-*/
-#ifdef SQLITE_COVERAGE_TEST
-SQLITE_PRIVATE void sqlite3Coverage(int x){
- static unsigned dummy = 0;
- dummy += (unsigned)x;
-}
+#ifndef SQLITE_OMIT_FLOATING_POINT
+#include
#endif
/*
** 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.
+** or to bypass normal error detection during testing in order to let
+** execute proceed further downstream.
**
** In deployment, sqlite3FaultSim() *always* return SQLITE_OK (0). The
** sqlite3FaultSim() function only returns non-zero during testing.
@@ -30262,36 +36445,10 @@ SQLITE_PRIVATE int sqlite3FaultSim(int iTest){
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 */
+ u64 y;
+ memcpy(&y,&x,sizeof(y));
+ rc = IsNaN(y);
+#else
rc = isnan(x);
#endif /* HAVE_ISNAN */
testcase( rc );
@@ -30299,6 +36456,19 @@ SQLITE_PRIVATE int sqlite3IsNaN(double x){
}
#endif /* SQLITE_OMIT_FLOATING_POINT */
+#ifndef SQLITE_OMIT_FLOATING_POINT
+/*
+** Return true if the floating point value is NaN or +Inf or -Inf.
+*/
+SQLITE_PRIVATE int sqlite3IsOverflow(double x){
+ int rc; /* The value return */
+ u64 y;
+ memcpy(&y,&x,sizeof(y));
+ rc = IsOvfl(y);
+ return rc;
+}
+#endif /* SQLITE_OMIT_FLOATING_POINT */
+
/*
** Compute a string length that is limited to what can be stored in
** lower 30 bits of a 32-bit signed integer.
@@ -30313,15 +36483,21 @@ 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
** the column name if and only if the COLFLAG_HASTYPE flag is set.
*/
SQLITE_PRIVATE char *sqlite3ColumnType(Column *pCol, char *zDflt){
- if( (pCol->colFlags & COLFLAG_HASTYPE)==0 ) return zDflt;
- return pCol->zName + strlen(pCol->zName) + 1;
+ if( pCol->colFlags & COLFLAG_HASTYPE ){
+ return pCol->zCnName + strlen(pCol->zCnName) + 1;
+ }else if( pCol->eCType ){
+ assert( pCol->eCType<=SQLITE_N_STDTYPE );
+ return (char*)sqlite3StdType[pCol->eCType-1];
+ }else{
+ return zDflt;
+ }
}
/*
@@ -30342,7 +36518,22 @@ static SQLITE_NOINLINE void sqlite3ErrorFinish(sqlite3 *db, int err_code){
SQLITE_PRIVATE void sqlite3Error(sqlite3 *db, int err_code){
assert( db!=0 );
db->errCode = err_code;
- if( err_code || db->pErr ) sqlite3ErrorFinish(db, err_code);
+ if( err_code || db->pErr ){
+ sqlite3ErrorFinish(db, err_code);
+ }else{
+ db->errByteOffset = -1;
+ }
+}
+
+/*
+** 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;
+ db->errByteOffset = -1;
+ if( db->pErr ) sqlite3ValueSetNull(db->pErr);
}
/*
@@ -30351,6 +36542,23 @@ SQLITE_PRIVATE void sqlite3Error(sqlite3 *db, int err_code){
*/
SQLITE_PRIVATE void sqlite3SystemError(sqlite3 *db, int rc){
if( rc==SQLITE_IOERR_NOMEM ) return;
+#if defined(SQLITE_USE_SEH) && !defined(SQLITE_OMIT_WAL)
+ if( rc==SQLITE_IOERR_IN_PAGE ){
+ int ii;
+ int iErr;
+ sqlite3BtreeEnterAll(db);
+ for(ii=0; iinDb; ii++){
+ if( db->aDb[ii].pBt ){
+ iErr = sqlite3PagerWalSystemErrno(sqlite3BtreePager(db->aDb[ii].pBt));
+ if( iErr ){
+ db->iSysErrno = iErr;
+ }
+ }
+ }
+ sqlite3BtreeLeaveAll(db);
+ return;
+ }
+#endif
rc &= 0xff;
if( rc==SQLITE_CANTOPEN || rc==SQLITE_IOERR ){
db->iSysErrno = sqlite3OsGetLastError(db->pVfs);
@@ -30362,17 +36570,8 @@ SQLITE_PRIVATE void sqlite3SystemError(sqlite3 *db, int rc){
** handle "db". The error code is set to "err_code".
**
** If it is not NULL, string zFormat specifies the format of the
-** error string in the style of the printf functions: The following
-** format characters are allowed:
-**
-** %s Insert a string
-** %z A string that should be freed after use
-** %d Insert an integer
-** %T Insert a token
-** %S Insert the first element of a SrcList
-**
-** zFormat and any string tokens that follow it are assumed to be
-** encoded in UTF-8.
+** error string. zFormat and any string tokens that follow it are
+** assumed to be encoded in UTF-8.
**
** To clear the most recent error for sqlite handle "db", sqlite3Error
** should be called with err_code set to SQLITE_OK and zFormat set
@@ -30394,15 +36593,32 @@ SQLITE_PRIVATE void sqlite3ErrorWithMsg(sqlite3 *db, int err_code, const char *z
}
}
+/*
+** Check for interrupts and invoke progress callback.
+*/
+SQLITE_PRIVATE void sqlite3ProgressCheck(Parse *p){
+ sqlite3 *db = p->db;
+ if( AtomicLoad(&db->u1.isInterrupted) ){
+ p->nErr++;
+ p->rc = SQLITE_INTERRUPT;
+ }
+#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
+ if( db->xProgress ){
+ if( p->rc==SQLITE_INTERRUPT ){
+ p->nProgressSteps = 0;
+ }else if( (++p->nProgressSteps)>=db->nProgressOps ){
+ if( db->xProgress(db->pProgressArg) ){
+ p->nErr++;
+ p->rc = SQLITE_INTERRUPT;
+ }
+ p->nProgressSteps = 0;
+ }
+ }
+#endif
+}
+
/*
** Add an error message to pParse->zErrMsg and increment pParse->nErr.
-** The following formatting characters are allowed:
-**
-** %s Insert a string
-** %z A string that should be freed after use
-** %d Insert an integer
-** %T Insert a token
-** %S Insert the first element of a SrcList
**
** This function should be used to report any error that occurs while
** compiling an SQL statement (i.e. within sqlite3_prepare()). The
@@ -30415,16 +36631,25 @@ SQLITE_PRIVATE void sqlite3ErrorMsg(Parse *pParse, const char *zFormat, ...){
char *zMsg;
va_list ap;
sqlite3 *db = pParse->db;
+ assert( db!=0 );
+ assert( db->pParse==pParse || db->pParse->pToplevel==pParse );
+ db->errByteOffset = -2;
va_start(ap, zFormat);
zMsg = sqlite3VMPrintf(db, zFormat, ap);
va_end(ap);
+ if( db->errByteOffset<-1 ) db->errByteOffset = -1;
if( db->suppressErr ){
sqlite3DbFree(db, zMsg);
+ if( db->mallocFailed ){
+ pParse->nErr++;
+ pParse->rc = SQLITE_NOMEM;
+ }
}else{
pParse->nErr++;
sqlite3DbFree(db, pParse->zErrMsg);
pParse->zErrMsg = zMsg;
pParse->rc = SQLITE_ERROR;
+ pParse->pWith = 0;
}
}
@@ -30481,11 +36706,72 @@ SQLITE_PRIVATE void sqlite3Dequote(char *z){
z[j] = 0;
}
SQLITE_PRIVATE void sqlite3DequoteExpr(Expr *p){
+ assert( !ExprHasProperty(p, EP_IntValue) );
assert( sqlite3Isquote(p->u.zToken[0]) );
p->flags |= p->u.zToken[0]=='"' ? EP_Quoted|EP_DblQuoted : EP_Quoted;
sqlite3Dequote(p->u.zToken);
}
+/*
+** Expression p is a QNUMBER (quoted number). Dequote the value in p->u.zToken
+** and set the type to INTEGER or FLOAT. "Quoted" integers or floats are those
+** that contain '_' characters that must be removed before further processing.
+*/
+SQLITE_PRIVATE void sqlite3DequoteNumber(Parse *pParse, Expr *p){
+ assert( p!=0 || pParse->db->mallocFailed );
+ if( p ){
+ const char *pIn = p->u.zToken;
+ char *pOut = p->u.zToken;
+ int bHex = (pIn[0]=='0' && (pIn[1]=='x' || pIn[1]=='X'));
+ int iValue;
+ assert( p->op==TK_QNUMBER );
+ p->op = TK_INTEGER;
+ do {
+ if( *pIn!=SQLITE_DIGIT_SEPARATOR ){
+ *pOut++ = *pIn;
+ if( *pIn=='e' || *pIn=='E' || *pIn=='.' ) p->op = TK_FLOAT;
+ }else{
+ if( (bHex==0 && (!sqlite3Isdigit(pIn[-1]) || !sqlite3Isdigit(pIn[1])))
+ || (bHex==1 && (!sqlite3Isxdigit(pIn[-1]) || !sqlite3Isxdigit(pIn[1])))
+ ){
+ sqlite3ErrorMsg(pParse, "unrecognized token: \"%s\"", p->u.zToken);
+ }
+ }
+ }while( *pIn++ );
+ if( bHex ) p->op = TK_INTEGER;
+
+ /* tag-20240227-a: If after dequoting, the number is an integer that
+ ** fits in 32 bits, then it must be converted into EP_IntValue. Other
+ ** parts of the code expect this. See also tag-20240227-b. */
+ if( p->op==TK_INTEGER && sqlite3GetInt32(p->u.zToken, &iValue) ){
+ p->u.iValue = iValue;
+ p->flags |= EP_IntValue;
+ }
+ }
+}
+
+/*
+** If the input token p is quoted, try to adjust the token to remove
+** the quotes. This is not always possible:
+**
+** "abc" -> abc
+** "ab""cd" -> (not possible because of the interior "")
+**
+** Remove the quotes if possible. This is a optimization. The overall
+** system should still return the correct answer even if this routine
+** is always a no-op.
+*/
+SQLITE_PRIVATE void sqlite3DequoteToken(Token *p){
+ unsigned int i;
+ if( p->n<2 ) return;
+ if( !sqlite3Isquote(p->z[0]) ) return;
+ for(i=1; in-1; i++){
+ if( sqlite3Isquote(p->z[i]) ) return;
+ }
+ p->n -= 2;
+ p->z++;
+}
+
/*
** Generate a Token object from a string
*/
@@ -30517,12 +36803,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++;
}
@@ -30542,240 +36834,674 @@ SQLITE_API int sqlite3_strnicmp(const char *zLeft, const char *zRight, int N){
}
/*
-** Compute 10 to the E-th power. Examples: E==1 results in 10.
-** E==2 results in 100. E==50 results in 1.0e50.
-**
-** This routine only works for values of E between 1 and 341.
+** Compute an 8-bit hash on a string that is insensitive to case differences
*/
-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
- };
- LONGDOUBLE_TYPE r = 1.0;
- int i;
- assert( E>=0 && E<=307 );
- for(i=0; E!=0; i++, E >>=1){
- if( E & 1 ) r *= x[i];
+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 r;
+ return h;
+}
+
+#if !defined(SQLITE_DISABLE_INTRINSIC) \
+ && (defined(__GNUC__) || defined(__clang__)) \
+ && (defined(__x86_64__) || defined(__aarch64__) || \
+ (defined(__riscv) && defined(__riscv_xlen) && (__riscv_xlen>32)))
+#define SQLITE_USE_UINT128
+#endif
+
+/*
+** Two inputs are multiplied to get a 128-bit result. Write the
+** lower 64-bits of the result into *pLo, and return the high-order
+** 64 bits.
+*/
+static u64 sqlite3Multiply128(u64 a, u64 b, u64 *pLo){
+#if defined(SQLITE_USE_UINT128)
+ __uint128_t r = (__uint128_t)a * b;
+ *pLo = (u64)r;
+ return (u64)(r>>64);
+#elif defined(_WIN64) && !defined(SQLITE_DISABLE_INTRINSIC)
+ *pLo = a*b;
+ return __umulh(a, b);
#else
- LONGDOUBLE_TYPE x = 10.0;
- LONGDOUBLE_TYPE r = 1.0;
- while(1){
- if( E & 1 ) r *= x;
- E >>= 1;
- if( E==0 ) break;
- x *= x;
- }
- return r;
+ u64 a0 = (u32)a;
+ u64 a1 = a >> 32;
+ u64 b0 = (u32)b;
+ u64 b1 = b >> 32;
+ u64 a0b0 = a0 * b0;
+ u64 a1b1 = a1 * b1;
+ u64 a0b1 = a0 * b1;
+ u64 a1b0 = a1 * b0;
+ u64 t = (a0b0 >> 32) + (u32)a0b1 + (u32)a1b0;
+ *pLo = (a0b0 & UINT64_C(0xffffffff)) | (t << 32);
+ return a1b1 + (a0b1>>32) + (a1b0>>32) + (t>>32);
+#endif
+}
+
+/*
+** A is an unsigned 96-bit integer formed by (a<<32)+aLo.
+** B is an unsigned 64-bit integer.
+**
+** Compute the upper 96 bits of 160-bit result of A*B.
+**
+** Write ((A*B)>>64 & 0xffffffff) (the middle 32 bits of A*B)
+** into *pLo. Return the upper 64 bits of A*B.
+**
+** The lower 64 bits of A*B are discarded.
+*/
+static u64 sqlite3Multiply160(u64 a, u32 aLo, u64 b, u32 *pLo){
+#if defined(SQLITE_USE_UINT128)
+ __uint128_t r = (__uint128_t)a * b;
+ r += ((__uint128_t)aLo * b) >> 32;
+ *pLo = (r>>32)&0xffffffff;
+ return r>>64;
+#elif defined(_WIN64) && !defined(SQLITE_DISABLE_INTRINSIC)
+ u64 r1_hi = __umulh(a,b);
+ u64 r1_lo = a*b;
+ u64 r2 = (__umulh((u64)aLo,b)<<32) + ((aLo*b)>>32);
+ u64 t = r1_lo + r2;
+ if( t>32;
+ return r1_hi;
+#else
+ u64 x2 = a>>32;
+ u64 x1 = a&0xffffffff;
+ u64 x0 = aLo;
+ u64 y1 = b>>32;
+ u64 y0 = b&0xffffffff;
+ u64 x2y1 = x2*y1;
+ u64 r4 = x2y1>>32;
+ u64 x2y0 = x2*y0;
+ u64 x1y1 = x1*y1;
+ u64 r3 = (x2y1 & 0xffffffff) + (x2y0 >>32) + (x1y1 >>32);
+ u64 x1y0 = x1*y0;
+ u64 x0y1 = x0*y1;
+ u64 r2 = (x2y0 & 0xffffffff) + (x1y1 & 0xffffffff) +
+ (x1y0 >>32) + (x0y1>>32);
+ u64 x0y0 = x0*y0;
+ u64 r1 = (x1y0 & 0xffffffff) + (x0y1 & 0xffffffff) +
+ (x0y0 >>32);
+ r2 += r1>>32;
+ r3 += r2>>32;
+ *pLo = r2&0xffffffff;
+ return (r4<<32) + r3;
#endif
}
+#undef SQLITE_USE_UINT128
+
/*
-** The string z[] is an text representation of a real number.
-** Convert this string to a double and write it into *pResult.
+** Return a u64 with the N-th bit set.
+*/
+#define U64_BIT(N) (((u64)1)<<(N))
+
+/*
+** Range of powers of 10 that we need to deal with when converting
+** IEEE754 doubles to and from decimal.
+*/
+#define POWERSOF10_FIRST (-348)
+#define POWERSOF10_LAST (+347)
+
+/*
+** For any p between -348 and +347, return the integer part of
**
-** The string z[] is length bytes in length (bytes, not characters) and
-** uses the encoding enc. The string is not necessarily zero-terminated.
+** pow(10,p) * pow(2,63-pow10to2(p))
**
-** 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:
+** Or, in other words, for any p in range, return the most significant
+** 64 bits of pow(10,p). The pow(10,p) value is shifted left or right,
+** as appropriate so the most significant 64 bits fit exactly into a
+** 64-bit unsigned integer.
**
-** [+-]digits[E[+-]digits]
-** [+-]digits.[digits][E[+-]digits]
-** [+-].digits[E[+-]digits]
+** Write into *pLo the next 32 significant bits of the answer after
+** the first 64.
**
-** Leading and trailing whitespace is ignored for the purpose of determining
-** validity.
+** Algorithm:
**
-** If some prefix of the input string is a valid number, this routine
-** returns FALSE but it still converts the prefix and writes the result
-** into *pResult.
+** (1) For p between 0 and 26, return the value directly from the aBase[]
+** lookup table.
+**
+** (2) For p outside the range 0 to 26, use aScale[] for the initial value
+** then refine that result (if necessary) by a single multiplication
+** against aBase[].
+**
+** The constant tables aBase[], aScale[], and aScaleLo[] are generated
+** by the C program at ../tool/mkfptab.c run with the --round option.
+*/
+static u64 powerOfTen(int p, u32 *pLo){
+ static const u64 aBase[] = {
+ UINT64_C(0x8000000000000000), /* 0: 1.0e+0 << 63 */
+ UINT64_C(0xa000000000000000), /* 1: 1.0e+1 << 60 */
+ UINT64_C(0xc800000000000000), /* 2: 1.0e+2 << 57 */
+ UINT64_C(0xfa00000000000000), /* 3: 1.0e+3 << 54 */
+ UINT64_C(0x9c40000000000000), /* 4: 1.0e+4 << 50 */
+ UINT64_C(0xc350000000000000), /* 5: 1.0e+5 << 47 */
+ UINT64_C(0xf424000000000000), /* 6: 1.0e+6 << 44 */
+ UINT64_C(0x9896800000000000), /* 7: 1.0e+7 << 40 */
+ UINT64_C(0xbebc200000000000), /* 8: 1.0e+8 << 37 */
+ UINT64_C(0xee6b280000000000), /* 9: 1.0e+9 << 34 */
+ UINT64_C(0x9502f90000000000), /* 10: 1.0e+10 << 30 */
+ UINT64_C(0xba43b74000000000), /* 11: 1.0e+11 << 27 */
+ UINT64_C(0xe8d4a51000000000), /* 12: 1.0e+12 << 24 */
+ UINT64_C(0x9184e72a00000000), /* 13: 1.0e+13 << 20 */
+ UINT64_C(0xb5e620f480000000), /* 14: 1.0e+14 << 17 */
+ UINT64_C(0xe35fa931a0000000), /* 15: 1.0e+15 << 14 */
+ UINT64_C(0x8e1bc9bf04000000), /* 16: 1.0e+16 << 10 */
+ UINT64_C(0xb1a2bc2ec5000000), /* 17: 1.0e+17 << 7 */
+ UINT64_C(0xde0b6b3a76400000), /* 18: 1.0e+18 << 4 */
+ UINT64_C(0x8ac7230489e80000), /* 19: 1.0e+19 >> 0 */
+ UINT64_C(0xad78ebc5ac620000), /* 20: 1.0e+20 >> 3 */
+ UINT64_C(0xd8d726b7177a8000), /* 21: 1.0e+21 >> 6 */
+ UINT64_C(0x878678326eac9000), /* 22: 1.0e+22 >> 10 */
+ UINT64_C(0xa968163f0a57b400), /* 23: 1.0e+23 >> 13 */
+ UINT64_C(0xd3c21bcecceda100), /* 24: 1.0e+24 >> 16 */
+ UINT64_C(0x84595161401484a0), /* 25: 1.0e+25 >> 20 */
+ UINT64_C(0xa56fa5b99019a5c8), /* 26: 1.0e+26 >> 23 */
+ };
+ static const u64 aScale[] = {
+ UINT64_C(0x8049a4ac0c5811ae), /* 0: 1.0e-351 << 1229 */
+ UINT64_C(0xcf42894a5dce35ea), /* 1: 1.0e-324 << 1140 */
+ UINT64_C(0xa76c582338ed2621), /* 2: 1.0e-297 << 1050 */
+ UINT64_C(0x873e4f75e2224e68), /* 3: 1.0e-270 << 960 */
+ UINT64_C(0xda7f5bf590966848), /* 4: 1.0e-243 << 871 */
+ UINT64_C(0xb080392cc4349dec), /* 5: 1.0e-216 << 781 */
+ UINT64_C(0x8e938662882af53e), /* 6: 1.0e-189 << 691 */
+ UINT64_C(0xe65829b3046b0afa), /* 7: 1.0e-162 << 602 */
+ UINT64_C(0xba121a4650e4ddeb), /* 8: 1.0e-135 << 512 */
+ UINT64_C(0x964e858c91ba2655), /* 9: 1.0e-108 << 422 */
+ UINT64_C(0xf2d56790ab41c2a2), /* 10: 1.0e-81 << 333 */
+ UINT64_C(0xc428d05aa4751e4c), /* 11: 1.0e-54 << 243 */
+ UINT64_C(0x9e74d1b791e07e48), /* 12: 1.0e-27 << 153 */
+ UINT64_C(0xcccccccccccccccc), /* 13: 1.0e-1 << 67 (special case) */
+ UINT64_C(0xcecb8f27f4200f3a), /* 14: 1.0e+27 >> 26 */
+ UINT64_C(0xa70c3c40a64e6c51), /* 15: 1.0e+54 >> 116 */
+ UINT64_C(0x86f0ac99b4e8dafd), /* 16: 1.0e+81 >> 206 */
+ UINT64_C(0xda01ee641a708de9), /* 17: 1.0e+108 >> 295 */
+ UINT64_C(0xb01ae745b101e9e4), /* 18: 1.0e+135 >> 385 */
+ UINT64_C(0x8e41ade9fbebc27d), /* 19: 1.0e+162 >> 475 */
+ UINT64_C(0xe5d3ef282a242e81), /* 20: 1.0e+189 >> 564 */
+ UINT64_C(0xb9a74a0637ce2ee1), /* 21: 1.0e+216 >> 654 */
+ UINT64_C(0x95f83d0a1fb69cd9), /* 22: 1.0e+243 >> 744 */
+ UINT64_C(0xf24a01a73cf2dccf), /* 23: 1.0e+270 >> 833 */
+ UINT64_C(0xc3b8358109e84f07), /* 24: 1.0e+297 >> 923 */
+ UINT64_C(0x9e19db92b4e31ba9), /* 25: 1.0e+324 >> 1013 */
+ };
+ static const unsigned int aScaleLo[] = {
+ 0x205b896d, /* 0: 1.0e-351 << 1229 */
+ 0x52064cad, /* 1: 1.0e-324 << 1140 */
+ 0xaf2af2b8, /* 2: 1.0e-297 << 1050 */
+ 0x5a7744a7, /* 3: 1.0e-270 << 960 */
+ 0xaf39a475, /* 4: 1.0e-243 << 871 */
+ 0xbd8d794e, /* 5: 1.0e-216 << 781 */
+ 0x547eb47b, /* 6: 1.0e-189 << 691 */
+ 0x0cb4a5a3, /* 7: 1.0e-162 << 602 */
+ 0x92f34d62, /* 8: 1.0e-135 << 512 */
+ 0x3a6a07f9, /* 9: 1.0e-108 << 422 */
+ 0xfae27299, /* 10: 1.0e-81 << 333 */
+ 0xaa97e14c, /* 11: 1.0e-54 << 243 */
+ 0x775ea265, /* 12: 1.0e-27 << 153 */
+ 0xcccccccc, /* 13: 1.0e-1 << 67 (special case) */
+ 0x00000000, /* 14: 1.0e+27 >> 26 */
+ 0x999090b6, /* 15: 1.0e+54 >> 116 */
+ 0x69a028bb, /* 16: 1.0e+81 >> 206 */
+ 0xe80e6f48, /* 17: 1.0e+108 >> 295 */
+ 0x5ec05dd0, /* 18: 1.0e+135 >> 385 */
+ 0x14588f14, /* 19: 1.0e+162 >> 475 */
+ 0x8f1668c9, /* 20: 1.0e+189 >> 564 */
+ 0x6d953e2c, /* 21: 1.0e+216 >> 654 */
+ 0x4abdaf10, /* 22: 1.0e+243 >> 744 */
+ 0xbc633b39, /* 23: 1.0e+270 >> 833 */
+ 0x0a862f81, /* 24: 1.0e+297 >> 923 */
+ 0x6c07a2c2, /* 25: 1.0e+324 >> 1013 */
+ };
+ int g, n;
+ u64 s, x;
+ u32 lo;
+
+ assert( p>=POWERSOF10_FIRST && p<=POWERSOF10_LAST );
+ if( p<0 ){
+ if( p==(-1) ){
+ *pLo = aScaleLo[13];
+ return aScale[13];
+ }
+ g = p/27;
+ n = p%27;
+ if( n ){
+ g--;
+ n += 27;
+ }
+ }else if( p<27 ){
+ *pLo = 0;
+ return aBase[p];
+ }else{
+ g = p/27;
+ n = p%27;
+ }
+ s = aScale[g+13];
+ if( n==0 ){
+ *pLo = aScaleLo[g+13];
+ return s;
+ }
+ x = sqlite3Multiply160(s,aScaleLo[g+13],aBase[n],&lo);
+ if( (U64_BIT(63) & x)==0 ){
+ x = x<<1 | ((lo>>31)&1);
+ lo = (lo<<1) | 1;
+ }
+ *pLo = lo;
+ return x;
+}
+
+/*
+** pow10to2(x) computes floor(log2(pow(10,x))).
+** pow2to10(y) computes floor(log10(pow(2,y))).
+**
+** Conceptually, pow10to2(p) converts a base-10 exponent p into
+** a corresponding base-2 exponent, and pow2to10(e) converts a base-2
+** exponent into a base-10 exponent.
+**
+** The conversions are based on the observation that:
+**
+** ln(10.0)/ln(2.0) == 108853/32768 (approximately)
+** ln(2.0)/ln(10.0) == 78913/262144 (approximately)
+**
+** These ratios are approximate, but they are accurate to 5 digits,
+** which is close enough for the usage here. Right-shift is used
+** for division so that rounding of negative numbers happens in the
+** right direction.
*/
-SQLITE_PRIVATE int sqlite3AtoF(const char *z, double *pResult, int length, u8 enc){
-#ifndef SQLITE_OMIT_FLOATING_POINT
- int incr;
- const char *zEnd = z + length;
- /* sign * significand * (10 ^ (esign * exponent)) */
- int sign = 1; /* sign of significand */
- i64 s = 0; /* significand */
- int d = 0; /* adjust exponent for shifting decimal point */
- int esign = 1; /* sign of exponent */
- int e = 0; /* exponent */
- int eValid = 1; /* True exponent is either not used or is well-formed */
- double result;
- int nDigits = 0;
- int nonNum = 0; /* True if input contains UTF16 with high byte non-zero */
+static int pwr10to2(int p){ return (p*108853) >> 15; }
+static int pwr2to10(int p){ return (p*78913) >> 18; }
- assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE );
- *pResult = 0.0; /* Default return value, in case of an error */
+/*
+** Count leading zeros for a 64-bit unsigned integer.
+*/
+static int countLeadingZeros(u64 m){
+#if (defined(__GNUC__) || defined(__clang__)) \
+ && !defined(SQLITE_DISABLE_INTRINSIC)
+ return __builtin_clzll(m);
+#else
+ int n = 0;
+ if( m <= 0x00000000ffffffffULL) { n += 32; m <<= 32; }
+ if( m <= 0x0000ffffffffffffULL) { n += 16; m <<= 16; }
+ if( m <= 0x00ffffffffffffffULL) { n += 8; m <<= 8; }
+ if( m <= 0x0fffffffffffffffULL) { n += 4; m <<= 4; }
+ if( m <= 0x3fffffffffffffffULL) { n += 2; m <<= 2; }
+ if( m <= 0x7fffffffffffffffULL) { n += 1; }
+ return n;
+#endif
+}
- if( enc==SQLITE_UTF8 ){
- incr = 1;
+/*
+** Given m and e, which represent a quantity r == m*pow(2,e),
+** return values *pD and *pP such that r == (*pD)*pow(10,*pP),
+** approximately. *pD should contain at least n significant digits.
+**
+** The input m is required to have its highest bit set. In other words,
+** m should be left-shifted, and e decremented, to maximize the value of m.
+*/
+static void sqlite3Fp2Convert10(u64 m, int e, int n, u64 *pD, int *pP){
+ int p;
+ u64 h, d1;
+ u32 d2;
+ assert( n>=1 && n<=18 );
+ p = n - 1 - pwr2to10(e+63);
+ h = sqlite3Multiply128(m, powerOfTen(p,&d2), &d1);
+ assert( -(e + pwr10to2(p) + 2) >= 0 );
+ assert( -(e + pwr10to2(p) + 1) <= 63 );
+ if( n==18 ){
+ h >>= -(e + pwr10to2(p) + 2);
+ *pD = (h + ((h<<1)&2))>>1;
}else{
- int i;
- incr = 2;
- assert( SQLITE_UTF16LE==2 && SQLITE_UTF16BE==3 );
- for(i=3-enc; i> -(e + pwr10to2(p) + 1);
}
+ *pP = -p;
+}
- /* skip leading spaces */
- while( z=zEnd ) return 0;
-
- /* get sign of significand */
- if( *z=='-' ){
- sign = -1;
- z+=incr;
- }else if( *z=='+' ){
- z+=incr;
- }
+/*
+** Return an IEEE754 floating point value that approximates d*pow(10,p).
+**
+** The (current) algorithm is adapted from the work of Ross Cox at
+** https://github.com/rsc/fpfmt
+*/
+static double sqlite3Fp10Convert2(u64 d, int p){
+ int b, lp, e, adj, s;
+ u32 pwr10l, mid1;
+ u64 pwr10h, x, hi, lo, sticky, u, m;
+ double r;
+ if( pPOWERSOF10_LAST ) return INFINITY;
+ b = 64 - countLeadingZeros(d);
+ lp = pwr10to2(p);
+ e = 53 - b - lp;
+ if( e > 1074 ){
+ if( e>=1130 ) return 0.0;
+ e = 1074;
+ }
+ s = -(e-(64-b) + lp + 3);
+ pwr10h = powerOfTen(p, &pwr10l);
+ if( pwr10l!=0 ){
+ pwr10h++;
+ pwr10l = ~pwr10l;
+ }
+ x = d<<(64-b);
+ hi = sqlite3Multiply128(x,pwr10h,&lo);
+ mid1 = lo>>32;
+ sticky = 1;
+ if( (hi & (U64_BIT(s)-1))==0 ) {
+ u32 mid2 = sqlite3Multiply128(x,((u64)pwr10l)<<32,&lo)>>32;
+ sticky = (mid1-mid2 > 1);
+ hi -= mid1 < mid2;
+ }
+ u = (hi>>s) | sticky;
+ adj = (u >= U64_BIT(55)-2);
+ if( adj ){
+ u = (u>>adj) | (u&1);
+ e -= adj;
+ }
+ m = (u + 1 + ((u>>2)&1)) >> 2;
+ if( e<=(-972) ) return INFINITY;
+ if((m & U64_BIT(52)) != 0){
+ m = (m & ~U64_BIT(52)) | ((u64)(1075-e)<<52);
+ }
+ memcpy(&r,&m,8);
+ return r;
+}
- /* copy max significant digits to significand */
- while( z Set if any prefix of the input is valid. Clear if
+** there is no prefix of the input that can be seen as
+** a valid floating point number.
+** bit 1 => Set if the input contains a decimal point or eNNN
+** clause. Zero if the input is an integer.
+** bit 2 => The input is exactly 0.0, not an underflow from
+** some value near zero.
+** bit 3 => Set if there are more than about 19 significant
+** digits in the input.
+**
+** If the input contains a syntax error but begins with text that might
+** be a valid number of some kind, then the result is negative. The
+** result is only zero if no prefix of the input could be interpreted as
+** a number.
+**
+** Leading and trailing whitespace is ignored. Valid numbers are in
+** one of the formats below:
+**
+** [+-]digits[E[+-]digits]
+** [+-]digits.[digits][E[+-]digits]
+** [+-].digits[E[+-]digits]
+**
+** Algorithm sketch: Compute an unsigned 64-bit integer s and a base-10
+** exponent d such that the value encoding by the input is s*pow(10,d).
+** Then invoke sqlite3Fp10Convert2() to calculated the closest possible
+** IEEE754 double. The sign is added back afterwards, if the input string
+** starts with a "-". The use of an unsigned 64-bit s mantissa means that
+** only about the first 19 significant digits of the input can contribute
+** to the result. This can result in suboptimal rounding decisions when
+** correct rounding requires more than 19 input digits. For example,
+** this routine renders "3500000000000000.2500001" as
+** 3500000000000000.0 instead of 3500000000000000.5 because the decision
+** to round up instead of using banker's rounding to round down is determined
+** by the 23rd significant digit, which this routine ignores. It is not
+** possible to do better without some kind of BigNum.
+*/
+SQLITE_PRIVATE int sqlite3AtoF(const char *zIn, double *pResult){
+#ifndef SQLITE_OMIT_FLOATING_POINT
+ const unsigned char *z = (const unsigned char*)zIn;
+ int neg = 0; /* True for a negative value */
+ u64 s = 0; /* mantissa */
+ int d = 0; /* Value is s * pow(10,d) */
+ int mState = 0; /* 1: digit seen 2: fp 4: hard-zero */
+ unsigned v; /* Value of a single digit */
+
+ start_of_text:
+ if( (v = (unsigned)z[0] - '0')<10 ){
+ parse_integer_part:
+ mState = 1;
+ s = v;
+ z++;
+ while( (v = (unsigned)z[0] - '0')<10 ){
+ s = s*10 + v;
+ z++;
+ if( s>=(LARGEST_UINT64-9)/10 ){
+ mState = 9;
+ while( sqlite3Isdigit(z[0]) ){ z++; d++; }
+ break;
+ }
+ }
+ }else if( z[0]=='-' ){
+ neg = 1;
+ z++;
+ if( (v = (unsigned)z[0] - '0')<10 ) goto parse_integer_part;
+ }else if( z[0]=='+' ){
+ z++;
+ if( (v = (unsigned)z[0] - '0')<10 ) goto parse_integer_part;
+ }else if( sqlite3Isspace(z[0]) ){
+ do{ z++; }while( sqlite3Isspace(z[0]) );
+ goto start_of_text;
+ }else{
+ s = 0;
}
- /* 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;
- /* copy digits from after decimal to significand
- ** (decrease exponent by d to shift decimal right) */
- while( z=zEnd ) goto do_atof_calc;
/* if exponent is present */
if( *z=='e' || *z=='E' ){
- z+=incr;
- eValid = 0;
-
- /* 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*/
+ int esign;
+ z++;
/* get sign of exponent */
if( *z=='-' ){
esign = -1;
- z+=incr;
- }else if( *z=='+' ){
- z+=incr;
+ z++;
+ }else{
+ esign = +1;
+ if( *z=='+' ){
+ z++;
+ }
}
/* copy digits to exponent */
- while( z0 ){ /*OPTIMIZATION-IF-TRUE*/
- if( esign>0 ){
- if( s>=(LARGEST_INT64/10) ) break; /*OPTIMIZATION-IF-FALSE*/
- s *= 10;
- }else{
- if( s%10!=0 ) break; /*OPTIMIZATION-IF-FALSE*/
- s /= 10;
- }
- e--;
+ /* return true if number and no extra non-whitespace characters after */
+ if( z[0]==0 ){
+ return mState;
+ }
+ if( sqlite3Isspace(z[0]) ){
+ do{ z++; }while( sqlite3Isspace(*z) );
+ if( z[0]==0 ){
+ return mState;
}
+ }
+ return 0xfffffff0 | mState;
+#else
+ return sqlite3Atoi64(z, pResult, strlen(z), SQLITE_UTF8)==0;
+#endif /* SQLITE_OMIT_FLOATING_POINT */
+}
- /* adjust the sign of significand */
- s = sign<0 ? -s : s;
+/*
+** Digit pairs used to convert a U64 or I64 into text, two digits
+** at a time.
+*/
+static const union {
+ char a[201];
+ short int forceAlignment;
+} sqlite3DigitPairs = {
+ "00010203040506070809"
+ "10111213141516171819"
+ "20212223242526272829"
+ "30313233343536373839"
+ "40414243444546474849"
+ "50515253545556575859"
+ "60616263646566676869"
+ "70717273747576777879"
+ "80818283848586878889"
+ "90919293949596979899"
+};
- if( e==0 ){ /*OPTIMIZATION-IF-TRUE*/
- result = (double)s;
- }else{
- /* attempt to handle extremely small/large numbers better */
- if( e>307 ){ /*OPTIMIZATION-IF-TRUE*/
- if( e<342 ){ /*OPTIMIZATION-IF-TRUE*/
- LONGDOUBLE_TYPE scale = sqlite3Pow10(e-308);
- if( esign<0 ){
- result = s / scale;
- result /= 1.0e+308;
- }else{
- result = s * scale;
- result *= 1.0e+308;
- }
- }else{ assert( e>=342 );
- if( esign<0 ){
- result = 0.0*s;
- }else{
-#ifdef INFINITY
- result = INFINITY*s;
-#else
- result = 1e308*1e308*s; /* Infinity */
+/*
+** ARMv6, ARMv7, PPC32 are known to not support hardware u64 division.
+*/
+#if (defined(__arm__) && !defined(__aarch64__)) || \
+ (defined(__ppc__) && !defined(__ppc64__))
+# define SQLITE_AVOID_U64_DIVIDE 1
#endif
- }
- }
- }else{
- LONGDOUBLE_TYPE scale = sqlite3Pow10(e);
- if( esign<0 ){
- result = s / scale;
- }else{
- result = s * scale;
- }
- }
- }
- }
- /* store the result */
- *pResult = result;
+#ifdef SQLITE_AVOID_U64_DIVIDE
+/*
+** Render an unsigned 64-bit integer as text onto the end of a 2-byte
+** aligned buffer that is SQLITE_U64_DIGIT+1 bytes long. The last byte
+** of the buffer will be filled with a \000 byte.
+**
+** Return the index into the buffer of the first byte.
+**
+** This routine is used on platforms where u64-division is slow because
+** it is not available in hardware and has to be emulated in software.
+** It seeks to minimize the number of u64 divisions and use u32 divisions
+** instead. It is slower on platforms that have hardware u64 division,
+** but much faster on platforms that do not.
+*/
+static int sqlite3UInt64ToText(u64 v, char *zOut){
+ u32 x32, kk;
+ int i;
+ zOut[SQLITE_U64_DIGITS] = 0;
+ i = SQLITE_U64_DIGITS;
+ assert( TWO_BYTE_ALIGNMENT(&sqlite3DigitPairs.a[0]) );
+ assert( TWO_BYTE_ALIGNMENT(zOut) );
+ while( (v>>32)!=0 ){
+ u32 y, x0, x1, y0, y1;
+ x32 = v % 100000000;
+ v = v / 100000000;
+ y = x32 % 10000;
+ x32 /= 10000;
+ x1 = x32 / 100;
+ x0 = x32 % 100;
+ y1 = y / 100;
+ y0 = y % 100;
+ assert( i>=8 );
+ i -= 8;
+ *(u16*)(&zOut[i]) = *(u16*)&sqlite3DigitPairs.a[x1*2];
+ *(u16*)(&zOut[i+2]) = *(u16*)&sqlite3DigitPairs.a[x0*2];
+ *(u16*)(&zOut[i+4]) = *(u16*)&sqlite3DigitPairs.a[y1*2];
+ *(u16*)(&zOut[i+6]) = *(u16*)&sqlite3DigitPairs.a[y0*2];
+ }
+ x32 = v;
+ while( x32>=10 ){
+ kk = x32 % 100;
+ x32 = x32 / 100;
+ assert( TWO_BYTE_ALIGNMENT(&sqlite3DigitPairs.a[kk*2]) );
+ assert( i>=2 );
+ i -= 2;
+ assert( TWO_BYTE_ALIGNMENT(&zOut[i]) );
+ *(u16*)(&zOut[i]) = *(u16*)&sqlite3DigitPairs.a[kk*2];
+ }
+ if( x32 ){
+ assert( i>0 );
+ zOut[--i] = x32 + '0';
+ }
+ return i;
+}
+#endif /* defined(SQLITE_AVOID_U64_DIVIDE) */
- /* return true if number and no extra non-whitespace chracters after */
- return z==zEnd && nDigits>0 && eValid && nonNum==0;
+/*
+** Render an signed 64-bit integer as text. Store the result in zOut[] and
+** return the length of the string that was stored, in bytes. The value
+** returned does not include the zero terminator at the end of the output
+** string.
+**
+** The caller must ensure that zOut[] is at least 21 bytes in size.
+*/
+SQLITE_PRIVATE int sqlite3Int64ToText(i64 v, char *zOut){
+ int i;
+ u64 x;
+ union {
+ char a[SQLITE_U64_DIGITS+1];
+ u16 forceAlignment;
+ } u;
+ if( v>0 ){
+ x = v;
+ }else if( v==0 ){
+ zOut[0] = '0';
+ zOut[1] = 0;
+ return 1;
+ }else{
+ x = (v==SMALLEST_INT64) ? ((u64)1)<<63 : (u64)-v;
+ }
+#ifdef SQLITE_AVOID_U64_DIVIDE
+ i = sqlite3UInt64ToText(x, u.a);
#else
- return !sqlite3Atoi64(z, pResult, length, enc);
-#endif /* SQLITE_OMIT_FLOATING_POINT */
+ i = sizeof(u.a)-1;
+ u.a[i] = 0;
+ while( x>=10 ){
+ int kk = (x%100)*2;
+ assert( TWO_BYTE_ALIGNMENT(&sqlite3DigitPairs.a[kk]) );
+ assert( TWO_BYTE_ALIGNMENT(&u.a[i-2]) );
+ *(u16*)(&u.a[i-2]) = *(u16*)&sqlite3DigitPairs.a[kk];
+ i -= 2;
+ x /= 100;
+ }
+ if( x ){
+ u.a[--i] = x + '0';
+ }
+#endif /* SQLITE_AVOID_U64_DIVIDE */
+ if( v<0 ) u.a[--i] = '-';
+ memcpy(zOut, &u.a[i], sizeof(u.a)-i);
+ return sizeof(u.a)-1-i;
}
/*
@@ -30815,6 +37541,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
@@ -30828,8 +37555,8 @@ SQLITE_PRIVATE int sqlite3Atoi64(const char *zNum, i64 *pNum, int length, u8 enc
int incr;
u64 u = 0;
int neg = 0; /* assume positive */
- int i;
- int c = 0;
+ int i, j;
+ unsigned int c = 0;
int nonNum = 0; /* True if input contains UTF16 with high byte non-zero */
int rc; /* Baseline return code */
const char *zStart;
@@ -30839,6 +37566,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; i='0' && c<='9'; i+=incr){
- u = u*10 + c - '0';
+ for(i=0; &zNum[i]19*incr ? 1 : compare2pow63(zNum, incr);
- if( c<0 ){
+ j = i>19*incr ? 1 : compare2pow63(zNum, incr);
+ if( j<0 ){
/* zNum is less than 9223372036854775808 so it fits */
assert( u<=LARGEST_INT64 );
return rc;
}else{
*pNum = neg ? SMALLEST_INT64 : LARGEST_INT64;
- if( c>0 ){
+ if( j>0 ){
/* zNum is greater than 9223372036854775808 so it overflows */
return 2;
}else{
@@ -30938,11 +37666,15 @@ SQLITE_PRIVATE int sqlite3DecOrHexToI64(const char *z, i64 *pOut){
u = u*16 + sqlite3HexToInt(z[k]);
}
memcpy(pOut, &u, 8);
- return (z[k]==0 && k-i<=16) ? 0 : 2;
+ if( k-i>16 ) return 2;
+ if( z[k]!=0 ) return 1;
+ return 0;
}else
#endif /* SQLITE_OMIT_HEX_INTEGER */
{
- return sqlite3Atoi64(z, pOut, sqlite3Strlen30(z), SQLITE_UTF8);
+ int n = (int)(0x3fffffff&strspn(z,"+- \n\t0123456789"));
+ if( z[n] ) n++;
+ return sqlite3Atoi64(z, pOut, n, SQLITE_UTF8);
}
}
@@ -30974,7 +37706,7 @@ SQLITE_PRIVATE int sqlite3GetInt32(const char *zNum, int *pValue){
u32 u = 0;
zNum += 2;
while( zNum[0]=='0' ) zNum++;
- for(i=0; sqlite3Isxdigit(zNum[i]) && i<8; i++){
+ for(i=0; i<8 && sqlite3Isxdigit(zNum[i]); i++){
u = u*16 + sqlite3HexToInt(zNum[i]);
}
if( (u&0x80000000)==0 && sqlite3Isxdigit(zNum[i])==0 ){
@@ -31017,10 +37749,192 @@ SQLITE_PRIVATE int sqlite3GetInt32(const char *zNum, int *pValue){
*/
SQLITE_PRIVATE int sqlite3Atoi(const char *z){
int x = 0;
- if( z ) sqlite3GetInt32(z, &x);
+ sqlite3GetInt32(z, &x);
return x;
}
+/*
+** Decode a floating-point value into an approximate decimal
+** representation.
+**
+** If iRound<=0 then round to -iRound significant digits to the
+** the right of the decimal point, or to a maximum of mxRound total
+** significant digits.
+**
+** If iRound>0 round to min(iRound,mxRound) significant digits total.
+**
+** mxRound must be positive.
+**
+** The significant digits of the decimal representation are
+** stored in p->z[] which is a often (but not always) a pointer
+** into the middle of p->zBuf[]. There are p->n significant digits.
+** The p->z[] array is *not* zero-terminated.
+*/
+SQLITE_PRIVATE void sqlite3FpDecode(FpDecode *p, double r, int iRound, int mxRound){
+ int i; /* Index into zBuf[] where to put next character */
+ int n; /* Number of digits */
+ u64 v; /* mantissa */
+ int e, exp = 0; /* Base-2 and base-10 exponent */
+ char *zBuf; /* Local alias for p->zBuf */
+ char *z; /* Local alias for p->z */
+
+ p->isSpecial = 0;
+ assert( mxRound>0 );
+
+ /* Convert negative numbers to positive. Deal with Infinity, 0.0, and
+ ** NaN. */
+ if( r<0.0 ){
+ p->sign = '-';
+ r = -r;
+ }else if( r==0.0 ){
+ p->sign = '+';
+ p->n = 1;
+ p->iDP = 1;
+ p->z = "0";
+ return;
+ }else{
+ p->sign = '+';
+ }
+ memcpy(&v,&r,8);
+ e = (v>>52)&0x7ff;
+ if( e==0x7ff ){
+ p->isSpecial = 1 + (v!=0x7ff0000000000000LL);
+ p->n = 0;
+ p->iDP = 0;
+ p->z = p->zBuf;
+ return;
+ }
+ v &= 0x000fffffffffffffULL;
+ if( e==0 ){
+ int nn = countLeadingZeros(v);
+ v <<= nn;
+ e = -1074 - nn;
+ }else{
+ v = (v<<11) | U64_BIT(63);
+ e -= 1086;
+ }
+ sqlite3Fp2Convert10(v, e, (iRound<=0||iRound>=18)?18:iRound+1, &v, &exp);
+
+ /* Extract significant digits, start at the right-most slot in p->zBuf
+ ** and working back to the right. "i" keeps track of the next slot in
+ ** which to store a digit. */
+ assert( sizeof(p->zBuf)==SQLITE_U64_DIGITS+1 );
+ assert( v>0 );
+ zBuf = p->zBuf;
+#ifdef SQLITE_AVOID_U64_DIVIDE
+ i = sqlite3UInt64ToText(v, zBuf);
+#else
+ i = SQLITE_U64_DIGITS;
+ while( v>=10 ){
+ int kk = (v%100)*2;
+ assert( TWO_BYTE_ALIGNMENT(&sqlite3DigitPairs.a[kk]) );
+ assert( TWO_BYTE_ALIGNMENT(&zBuf[i]) );
+ assert( i-2>=0 );
+ *(u16*)(&zBuf[i-2]) = *(u16*)&sqlite3DigitPairs.a[kk];
+ i -= 2;
+ v /= 100;
+ }
+ if( v ){
+ assert( v<10 );
+ assert( i>0 );
+ zBuf[--i] = v + '0';
+ }
+#endif /* SQLITE_AVOID_U64_DIVIDE */
+ assert( i>=0 && i0 );
+ assert( n<=SQLITE_U64_DIGITS );
+ p->iDP = n + exp;
+ if( iRound<=0 ){
+ iRound = p->iDP - iRound;
+ if( iRound==0 && zBuf[i]>='5' ){
+ iRound = 1;
+ zBuf[--i] = '0';
+ n++;
+ p->iDP++;
+ }
+ }
+ z = &zBuf[i]; /* z points to the first digit */
+ if( iRound>0 && (iRoundmxRound) ){
+ if( iRound>mxRound ) iRound = mxRound;
+ if( iRound==17 ){
+ /* If the precision is exactly 17, which only happens with the "!"
+ ** flag (ex: "%!.17g") then try to reduce the precision if that
+ ** yields text that will round-trip to the original floating-point.
+ ** value. Thus, for exaple, 49.47 will render as 49.47, rather than
+ ** as 49.469999999999999. */
+ if( z[15]=='9' && z[14]=='9' ){
+ int jj, kk;
+ u64 v2;
+ for(jj=14; jj>0 && z[jj-1]=='9'; jj--){}
+ if( jj==0 ){
+ v2 = 1;
+ }else{
+ v2 = z[0] - '0';
+ for(kk=1; kkiDP>=n || (z[15]=='0' && z[14]=='0' && z[13]=='0') ){
+ int jj, kk;
+ u64 v2;
+ assert( z[0]!='0' );
+ for(jj=13; z[jj-1]=='0'; jj--){}
+ v2 = z[0] - '0';
+ for(kk=1; kk='5' ){
+ int j = iRound-1;
+ while( 1 /*exit-by-break*/ ){
+ z[j]++;
+ if( z[j]<='9' ) break;
+ z[j] = '0';
+ if( j==0 ){
+ z--;
+ z[0] = '1';
+ n++;
+ p->iDP++;
+ break;
+ }else{
+ j--;
+ }
+ }
+ }
+ }
+ assert( n>0 );
+ while( z[n-1]=='0' ){
+ n--;
+ assert( n>0 );
+ }
+ p->n = n;
+ p->z = z;
+}
+
+/*
+** Try to convert z into an unsigned 32-bit integer. Return true on
+** success and false if there is an error.
+**
+** Only decimal notation is accepted.
+*/
+SQLITE_PRIVATE int sqlite3GetUInt32(const char *z, u32 *pI){
+ u64 v = 0;
+ int i;
+ for(i=0; sqlite3Isdigit(z[i]); i++){
+ v = v*10 + z[i] - '0';
+ if( v>4294967296LL ){ *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:
**
@@ -31061,7 +37975,7 @@ static int SQLITE_NOINLINE putVarint64(unsigned char *p, u64 v){
v >>= 7;
}
return 9;
- }
+ }
n = 0;
do{
buf[n++] = (u8)((v & 0x7f) | 0x80);
@@ -31107,23 +38021,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;
}
@@ -31131,8 +38034,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))
@@ -31271,127 +38175,37 @@ 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){
- u32 a,b;
+ u64 v64;
+ u8 n;
- /* The 1-byte case. Overwhelmingly the most common. Handled inline
- ** by the getVarin32() macro */
- a = *p;
- /* a: p0 (unmasked) */
-#ifndef getVarint32
- if (!(a&0x80))
- {
- /* Values between 0 and 127 */
- *v = a;
- return 1;
- }
-#endif
+ /* Assume that the single-byte case has already been handled by
+ ** the getVarint32() macro */
+ assert( (p[0] & 0x80)!=0 );
- /* The 2-byte case */
- p++;
- b = *p;
- /* b: p1 (unmasked) */
- if (!(b&0x80))
- {
- /* Values between 128 and 16383 */
- a &= 0x7f;
- a = a<<7;
- *v = a | b;
+ if( (p[1] & 0x80)==0 ){
+ /* This is the two-byte case */
+ *v = ((p[0]&0x7f)<<7) | p[1];
return 2;
}
-
- /* The 3-byte case */
- p++;
- a = a<<14;
- a |= *p;
- /* a: p0<<14 | p2 (unmasked) */
- if (!(a&0x80))
- {
- /* Values between 16384 and 2097151 */
- a &= (0x7f<<14)|(0x7f);
- b &= 0x7f;
- b = b<<7;
- *v = a | b;
+ if( (p[2] & 0x80)==0 ){
+ /* This is the three-byte case */
+ *v = ((p[0]&0x7f)<<14) | ((p[1]&0x7f)<<7) | p[2];
return 3;
}
-
- /* A 32-bit varint is used to store size information in btrees.
- ** Objects are rarely larger than 2MiB limit of a 3-byte varint.
- ** A 3-byte varint is sufficient, for example, to record the size
- ** of a 1048569-byte BLOB or string.
- **
- ** We only unroll the first 1-, 2-, and 3- byte cases. The very
- ** rare larger cases can be handled by the slower 64-bit varint
- ** routine.
- */
-#if 1
- {
- u64 v64;
- u8 n;
-
- p -= 2;
- n = sqlite3GetVarint(p, &v64);
- assert( n>3 && n<=9 );
- if( (v64 & SQLITE_MAX_U32)!=v64 ){
- *v = 0xffffffff;
- }else{
- *v = (u32)v64;
- }
- return n;
- }
-
-#else
- /* For following code (kept for historical record only) shows an
- ** unrolling for the 3- and 4-byte varint cases. This code is
- ** slightly faster, but it is also larger and much harder to test.
- */
- p++;
- b = b<<14;
- b |= *p;
- /* b: p1<<14 | p3 (unmasked) */
- if (!(b&0x80))
- {
- /* Values between 2097152 and 268435455 */
- b &= (0x7f<<14)|(0x7f);
- a &= (0x7f<<14)|(0x7f);
- a = a<<7;
- *v = a | b;
- return 4;
- }
-
- p++;
- a = a<<14;
- a |= *p;
- /* a: p0<<28 | p2<<14 | p4 (unmasked) */
- if (!(a&0x80))
- {
- /* Values between 268435456 and 34359738367 */
- a &= SLOT_4_2_0;
- b &= SLOT_4_2_0;
- b = b<<7;
- *v = a | b;
- return 5;
- }
-
- /* We can only reach this point when reading a corrupt database
- ** file. In that case we are not in any hurry. Use the (relatively
- ** slow) general-purpose sqlite3GetVarint() routine to extract the
- ** value. */
- {
- u64 v64;
- u8 n;
-
- p -= 4;
- n = sqlite3GetVarint(p, &v64);
- assert( n>5 && n<=9 );
+ /* four or more bytes */
+ n = sqlite3GetVarint(p, &v64);
+ assert( n>3 && n<=9 );
+ if( (v64 & SQLITE_MAX_U32)!=v64 ){
+ *v = 0xffffffff;
+ }else{
*v = (u32)v64;
- return n;
}
-#endif
+ return n;
}
/*
@@ -31461,7 +38275,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
@@ -31482,7 +38296,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
@@ -31490,7 +38304,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
);
@@ -31511,13 +38325,13 @@ static void logBadConnection(const char *zType){
** used as an argument to sqlite3_errmsg() or sqlite3_close().
*/
SQLITE_PRIVATE int sqlite3SafetyCheckOk(sqlite3 *db){
- u32 magic;
+ u8 eOpenState;
if( db==0 ){
logBadConnection("NULL");
return 0;
}
- magic = db->magic;
- if( magic!=SQLITE_MAGIC_OPEN ){
+ eOpenState = db->eOpenState;
+ if( eOpenState!=SQLITE_STATE_OPEN ){
if( sqlite3SafetyCheckSickOrOk(db) ){
testcase( sqlite3GlobalConfig.xLog!=0 );
logBadConnection("unopened");
@@ -31528,11 +38342,11 @@ SQLITE_PRIVATE int sqlite3SafetyCheckOk(sqlite3 *db){
}
}
SQLITE_PRIVATE int sqlite3SafetyCheckSickOrOk(sqlite3 *db){
- u32 magic;
- magic = db->magic;
- if( magic!=SQLITE_MAGIC_SICK &&
- magic!=SQLITE_MAGIC_OPEN &&
- magic!=SQLITE_MAGIC_BUSY ){
+ u8 eOpenState;
+ eOpenState = db->eOpenState;
+ if( eOpenState!=SQLITE_STATE_SICK &&
+ eOpenState!=SQLITE_STATE_OPEN &&
+ eOpenState!=SQLITE_STATE_BUSY ){
testcase( sqlite3GlobalConfig.xLog!=0 );
logBadConnection("invalid");
return 0;
@@ -31542,7 +38356,7 @@ SQLITE_PRIVATE int sqlite3SafetyCheckSickOrOk(sqlite3 *db){
}
/*
-** Attempt to add, substract, or multiply the 64-bit signed value iB against
+** Attempt to add, subtract, or multiply the 64-bit signed value iB against
** the other 64-bit signed integer at *pA and store the result in *pA.
** Return 0 on success. Or if the operation would have resulted in an
** overflow, leave *pA unchanged and return 1.
@@ -31564,7 +38378,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){
@@ -31605,7 +38419,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, if possible. Or
** if the integer has a value of -2147483648, return +2147483647
*/
SQLITE_PRIVATE int sqlite3AbsInt32(int x){
@@ -31645,11 +38459,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[] = {
@@ -31697,7 +38511,6 @@ SQLITE_PRIVATE LogEst sqlite3LogEst(u64 x){
return a[x&7] + y - 10;
}
-#ifndef SQLITE_OMIT_VIRTUALTABLE
/*
** Convert a double into a LogEst
** In other words, compute an approximation for 10*log2(x).
@@ -31712,16 +38525,9 @@ SQLITE_PRIVATE LogEst sqlite3LogEstFromDouble(double x){
e = (a>>52) - 1022;
return e*10;
}
-#endif /* SQLITE_OMIT_VIRTUALTABLE */
-#if defined(SQLITE_ENABLE_STMT_SCANSTATUS) || \
- defined(SQLITE_ENABLE_STAT3_OR_STAT4) || \
- defined(SQLITE_EXPLAIN_ESTIMATED_ROWS)
/*
** Convert a LogEst into an integer.
-**
-** Note that this routine is only used when one or more of various
-** non-standard compile-time options is enabled.
*/
SQLITE_PRIVATE u64 sqlite3LogEstToInt(LogEst x){
u64 n;
@@ -31729,17 +38535,9 @@ SQLITE_PRIVATE u64 sqlite3LogEstToInt(LogEst x){
x /= 10;
if( n>=5 ) n -= 2;
else if( n>=1 ) n -= 1;
-#if defined(SQLITE_ENABLE_STMT_SCANSTATUS) || \
- 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
- ** possible to this routine is 310, resulting in a maximum x of 31 */
- assert( x<=60 );
-#endif
return x>=3 ? (n+8)<<(x-3) : (n+8)>>(3-x);
}
-#endif /* defined SCANSTAT or STAT4 or ESTIMATED_ROWS */
/*
** Add a new name/number pair to a VList. This might require that the
@@ -31763,8 +38561,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
@@ -31773,7 +38571,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.
*/
@@ -31902,12 +38700,19 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash *pH){
*/
static unsigned int strHash(const char *z){
unsigned int h = 0;
- unsigned char c;
- while( (c = (unsigned char)*z++)!=0 ){ /*OPTIMIZATION-IF-TRUE*/
+ while( z[0] ){ /*OPTIMIZATION-IF-TRUE*/
/* Knuth multiplicative hashing. (Sorting & Searching, p. 510).
** 0x9e3779b1 is 2654435761 which is the closest prime number to
- ** (2**32)*golden_ratio, where golden_ratio = (sqrt(5) - 1)/2. */
- h += sqlite3UpperToLower[c];
+ ** (2**32)*golden_ratio, where golden_ratio = (sqrt(5) - 1)/2.
+ **
+ ** Only bits 0xdf for ASCII and bits 0xbf for EBCDIC each octet are
+ ** hashed since the omitted bits determine the upper/lower case difference.
+ */
+#ifdef SQLITE_EBCDIC
+ h += 0xbf & (unsigned char)*(z++);
+#else
+ h += 0xdf & (unsigned char)*(z++);
+#endif
h *= 0x9e3779b1;
}
return h;
@@ -31945,7 +38750,7 @@ static void insertElement(
}
-/* Resize the hash table so that it cantains "new_size" buckets.
+/* Resize the hash table so that it contains "new_size" buckets.
**
** The hash table might fail to resize if sqlite3_malloc() fails or
** if the new size is the same as the prior size.
@@ -31964,7 +38769,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
@@ -31980,9 +38785,8 @@ static int rehash(Hash *pH, unsigned int new_size){
pH->htsize = new_size = sqlite3MallocSize(new_ht)/sizeof(struct _ht);
memset(new_ht, 0, new_size*sizeof(struct _ht));
for(elem=pH->first, pH->first=0; elem; elem = next_elem){
- unsigned int h = strHash(elem->pKey) % new_size;
next_elem = elem->next;
- insertElement(pH, &new_ht[h], elem);
+ insertElement(pH, &new_ht[elem->h % new_size], elem);
}
return 1;
}
@@ -32000,26 +38804,26 @@ static HashElem *findElementWithHash(
HashElem *elem; /* Used to loop thru the element list */
unsigned int count; /* Number of elements left to test */
unsigned int h; /* The computed hash */
- static HashElem nullElement = { 0, 0, 0, 0 };
+ static HashElem nullElement = { 0, 0, 0, 0, 0 };
+ h = strHash(pKey);
if( pH->ht ){ /*OPTIMIZATION-IF-TRUE*/
struct _ht *pEntry;
- h = strHash(pKey) % pH->htsize;
- pEntry = &pH->ht[h];
+ pEntry = &pH->ht[h % pH->htsize];
elem = pEntry->chain;
count = pEntry->count;
}else{
- h = 0;
elem = pH->first;
count = pH->count;
}
if( pHash ) *pHash = h;
- while( count-- ){
+ while( count ){
assert( elem!=0 );
- if( sqlite3StrICmp(elem->pKey,pKey)==0 ){
+ if( h==elem->h && sqlite3StrICmp(elem->pKey,pKey)==0 ){
return elem;
}
elem = elem->next;
+ count--;
}
return &nullElement;
}
@@ -32027,14 +38831,13 @@ static HashElem *findElementWithHash(
/* Remove a single entry from the hash table given a pointer to that
** element and a hash on the element's key.
*/
-static void removeElementGivenHash(
+static void removeElement(
Hash *pH, /* The pH containing "elem" */
- HashElem* elem, /* The element to be removed from the pH */
- unsigned int h /* Hash value for the element */
+ HashElem *elem /* The element to be removed from the pH */
){
struct _ht *pEntry;
if( elem->prev ){
- elem->prev->next = elem->next;
+ elem->prev->next = elem->next;
}else{
pH->first = elem->next;
}
@@ -32042,7 +38845,7 @@ static void removeElementGivenHash(
elem->next->prev = elem->prev;
}
if( pH->ht ){
- pEntry = &pH->ht[h];
+ pEntry = &pH->ht[elem->h % pH->htsize];
if( pEntry->chain==elem ){
pEntry->chain = elem->next;
}
@@ -32093,7 +38896,7 @@ SQLITE_PRIVATE void *sqlite3HashInsert(Hash *pH, const char *pKey, void *data){
if( elem->data ){
void *old_data = elem->data;
if( data==0 ){
- removeElementGivenHash(pH,elem,h);
+ removeElement(pH,elem);
}else{
elem->data = data;
elem->pKey = pKey;
@@ -32104,18 +38907,17 @@ SQLITE_PRIVATE void *sqlite3HashInsert(Hash *pH, const char *pKey, void *data){
new_elem = (HashElem*)sqlite3Malloc( sizeof(HashElem) );
if( new_elem==0 ) return data;
new_elem->pKey = pKey;
+ new_elem->h = h;
new_elem->data = data;
pH->count++;
- if( pH->count>=10 && pH->count > 2*pH->htsize ){
- if( rehash(pH, pH->count*2) ){
- assert( pH->htsize>0 );
- h = strHash(pKey) % pH->htsize;
- }
+ if( pH->count>=5 && pH->count > 2*pH->htsize ){
+ rehash(pH, pH->count*3);
}
- insertElement(pH, pH->ht ? &pH->ht[h] : 0, new_elem);
+ insertElement(pH, pH->ht ? &pH->ht[new_elem->h % pH->htsize] : 0, new_elem);
return 0;
}
+
/************** End of hash.c ************************************************/
/************** Begin file opcodes.c *****************************************/
/* Automatically generated. Do not edit */
@@ -32133,29 +38935,29 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
/* 0 */ "Savepoint" OpHelp(""),
/* 1 */ "AutoCommit" OpHelp(""),
/* 2 */ "Transaction" OpHelp(""),
- /* 3 */ "SorterNext" OpHelp(""),
- /* 4 */ "Prev" OpHelp(""),
- /* 5 */ "Next" OpHelp(""),
- /* 6 */ "Checkpoint" OpHelp(""),
- /* 7 */ "JournalMode" OpHelp(""),
- /* 8 */ "Vacuum" OpHelp(""),
- /* 9 */ "VFilter" OpHelp("iplan=r[P3] zplan='P4'"),
- /* 10 */ "VUpdate" OpHelp("data=r[P3@P2]"),
- /* 11 */ "Goto" OpHelp(""),
- /* 12 */ "Gosub" OpHelp(""),
- /* 13 */ "InitCoroutine" OpHelp(""),
- /* 14 */ "Yield" OpHelp(""),
- /* 15 */ "MustBeInt" OpHelp(""),
- /* 16 */ "Jump" OpHelp(""),
- /* 17 */ "Once" OpHelp(""),
- /* 18 */ "If" OpHelp(""),
+ /* 3 */ "Checkpoint" OpHelp(""),
+ /* 4 */ "JournalMode" OpHelp(""),
+ /* 5 */ "Vacuum" OpHelp(""),
+ /* 6 */ "VFilter" OpHelp("iplan=r[P3] zplan='P4'"),
+ /* 7 */ "VUpdate" OpHelp("data=r[P3@P2]"),
+ /* 8 */ "Init" OpHelp("Start at P2"),
+ /* 9 */ "Goto" OpHelp(""),
+ /* 10 */ "Gosub" OpHelp(""),
+ /* 11 */ "InitCoroutine" OpHelp(""),
+ /* 12 */ "Yield" OpHelp(""),
+ /* 13 */ "MustBeInt" OpHelp(""),
+ /* 14 */ "Jump" OpHelp(""),
+ /* 15 */ "Once" OpHelp(""),
+ /* 16 */ "If" OpHelp(""),
+ /* 17 */ "IfNot" OpHelp(""),
+ /* 18 */ "IsType" OpHelp("if typeof(P1.P3) in P5 goto P2"),
/* 19 */ "Not" OpHelp("r[P2]= !r[P1]"),
- /* 20 */ "IfNot" OpHelp(""),
- /* 21 */ "IfNullRow" OpHelp("if P1.nullRow then r[P3]=NULL, goto P2"),
- /* 22 */ "SeekLT" OpHelp("key=r[P3@P4]"),
- /* 23 */ "SeekLE" OpHelp("key=r[P3@P4]"),
- /* 24 */ "SeekGE" OpHelp("key=r[P3@P4]"),
- /* 25 */ "SeekGT" OpHelp("key=r[P3@P4]"),
+ /* 20 */ "IfNullRow" OpHelp("if P1.nullRow then r[P3]=NULL, goto P2"),
+ /* 21 */ "SeekLT" OpHelp("key=r[P3@P4]"),
+ /* 22 */ "SeekLE" OpHelp("key=r[P3@P4]"),
+ /* 23 */ "SeekGE" OpHelp("key=r[P3@P4]"),
+ /* 24 */ "SeekGT" OpHelp("key=r[P3@P4]"),
+ /* 25 */ "IfNotOpen" OpHelp("if( !csr[P1] ) goto P2"),
/* 26 */ "IfNoHope" OpHelp("key=r[P3@P4]"),
/* 27 */ "NoConflict" OpHelp("key=r[P3@P4]"),
/* 28 */ "NotFound" OpHelp("key=r[P3@P4]"),
@@ -32163,152 +38965,1235 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
/* 30 */ "SeekRowid" OpHelp("intkey=r[P3]"),
/* 31 */ "NotExists" OpHelp("intkey=r[P3]"),
/* 32 */ "Last" OpHelp(""),
- /* 33 */ "IfSmaller" OpHelp(""),
+ /* 33 */ "IfSizeBetween" 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"),
+ /* 37 */ "IfEmpty" OpHelp("if( empty(P1) ) goto P2"),
+ /* 38 */ "SorterNext" OpHelp(""),
+ /* 39 */ "Prev" OpHelp(""),
+ /* 40 */ "Next" OpHelp(""),
+ /* 41 */ "IdxLE" OpHelp("key=r[P3@P4]"),
+ /* 42 */ "IdxGT" OpHelp("key=r[P3@P4]"),
/* 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"),
- /* 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]"),
- /* 53 */ "Eq" OpHelp("IF r[P3]==r[P1]"),
- /* 54 */ "Gt" OpHelp("IF r[P3]>r[P1]"),
- /* 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]"),
- /* 81 */ "ResultRow" OpHelp("output=r[P1@P2]"),
- /* 82 */ "CollSeq" OpHelp(""),
- /* 83 */ "AddImm" OpHelp("r[P1]=r[P1]+P2"),
- /* 84 */ "RealAffinity" OpHelp(""),
- /* 85 */ "Cast" OpHelp("affinity(r[P1])"),
- /* 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 */ "MakeRecord" OpHelp("r[P3]=mkrec(r[P1@P2])"),
- /* 93 */ "Count" OpHelp("r[P2]=count()"),
- /* 94 */ "ReadCookie" OpHelp(""),
- /* 95 */ "SetCookie" OpHelp(""),
- /* 96 */ "BitAnd" OpHelp("r[P3]=r[P1]&r[P2]"),
- /* 97 */ "BitOr" OpHelp("r[P3]=r[P1]|r[P2]"),
- /* 98 */ "ShiftLeft" OpHelp("r[P3]=r[P2]<>r[P1]"),
- /* 100 */ "Add" OpHelp("r[P3]=r[P1]+r[P2]"),
- /* 101 */ "Subtract" OpHelp("r[P3]=r[P2]-r[P1]"),
- /* 102 */ "Multiply" OpHelp("r[P3]=r[P1]*r[P2]"),
- /* 103 */ "Divide" OpHelp("r[P3]=r[P2]/r[P1]"),
- /* 104 */ "Remainder" OpHelp("r[P3]=r[P2]%r[P1]"),
- /* 105 */ "Concat" OpHelp("r[P3]=r[P2]+r[P1]"),
- /* 106 */ "ReopenIdx" OpHelp("root=P2 iDb=P3"),
- /* 107 */ "BitNot" OpHelp("r[P2]= ~r[P1]"),
- /* 108 */ "OpenRead" OpHelp("root=P2 iDb=P3"),
- /* 109 */ "OpenWrite" OpHelp("root=P2 iDb=P3"),
- /* 110 */ "String8" OpHelp("r[P2]='P4'"),
- /* 111 */ "OpenDup" OpHelp(""),
- /* 112 */ "OpenAutoindex" OpHelp("nColumn=P2"),
- /* 113 */ "OpenEphemeral" OpHelp("nColumn=P2"),
- /* 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 */ "Delete" OpHelp(""),
- /* 124 */ "ResetCount" OpHelp(""),
- /* 125 */ "SorterCompare" OpHelp("if key(P1)!=trim(r[P3],P4) goto P2"),
- /* 126 */ "SorterData" OpHelp("r[P2]=data"),
- /* 127 */ "RowData" OpHelp("r[P2]=data"),
- /* 128 */ "Rowid" OpHelp("r[P2]=rowid"),
- /* 129 */ "NullRow" OpHelp(""),
- /* 130 */ "SeekEnd" OpHelp(""),
- /* 131 */ "SorterInsert" OpHelp("key=r[P2]"),
- /* 132 */ "IdxInsert" OpHelp("key=r[P2]"),
- /* 133 */ "IdxDelete" OpHelp("key=r[P2@P3]"),
- /* 134 */ "DeferredSeek" OpHelp("Move P3 to P1.rowid if needed"),
- /* 135 */ "IdxRowid" OpHelp("r[P2]=rowid"),
- /* 136 */ "Destroy" OpHelp(""),
- /* 137 */ "Clear" OpHelp(""),
- /* 138 */ "ResetSorter" OpHelp(""),
- /* 139 */ "CreateBtree" OpHelp("r[P2]=root iDb=P1 flags=P3"),
- /* 140 */ "SqlExec" OpHelp(""),
- /* 141 */ "ParseSchema" OpHelp(""),
- /* 142 */ "LoadAnalysis" OpHelp(""),
- /* 143 */ "DropTable" OpHelp(""),
- /* 144 */ "DropIndex" OpHelp(""),
- /* 145 */ "Real" OpHelp("r[P2]=P4"),
- /* 146 */ "DropTrigger" OpHelp(""),
- /* 147 */ "IntegrityCk" OpHelp(""),
- /* 148 */ "RowSetAdd" OpHelp("rowset(P1)=r[P2]"),
- /* 149 */ "Param" OpHelp(""),
- /* 150 */ "FkCounter" OpHelp("fkctr[P1]+=P2"),
- /* 151 */ "MemMax" OpHelp("r[P1]=max(r[P1],r[P2])"),
- /* 152 */ "OffsetLimit" OpHelp("if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1)"),
- /* 153 */ "AggInverse" OpHelp("accum=r[P3] inverse(r[P2@P5])"),
- /* 154 */ "AggStep" OpHelp("accum=r[P3] step(r[P2@P5])"),
- /* 155 */ "AggStep1" OpHelp("accum=r[P3] step(r[P2@P5])"),
- /* 156 */ "AggValue" OpHelp("r[P3]=value N=P2"),
- /* 157 */ "AggFinal" OpHelp("accum=r[P1] N=P2"),
- /* 158 */ "Expire" OpHelp(""),
- /* 159 */ "TableLock" OpHelp("iDb=P1 root=P2 write=P3"),
- /* 160 */ "VBegin" OpHelp(""),
- /* 161 */ "VCreate" OpHelp(""),
- /* 162 */ "VDestroy" OpHelp(""),
- /* 163 */ "VOpen" OpHelp(""),
- /* 164 */ "VColumn" OpHelp("r[P3]=vcolumn(P2)"),
- /* 165 */ "VRename" OpHelp(""),
- /* 166 */ "Pagecount" OpHelp(""),
- /* 167 */ "MaxPgcnt" OpHelp(""),
- /* 168 */ "Trace" OpHelp(""),
- /* 169 */ "CursorHint" OpHelp(""),
- /* 170 */ "Noop" OpHelp(""),
- /* 171 */ "Explain" OpHelp(""),
- /* 172 */ "Abortable" OpHelp(""),
+ /* 45 */ "IdxLT" OpHelp("key=r[P3@P4]"),
+ /* 46 */ "IdxGE" OpHelp("key=r[P3@P4]"),
+ /* 47 */ "IFindKey" OpHelp(""),
+ /* 48 */ "RowSetRead" OpHelp("r[P3]=rowset(P1)"),
+ /* 49 */ "RowSetTest" OpHelp("if r[P3] in rowset(P1) goto P2"),
+ /* 50 */ "Program" OpHelp(""),
+ /* 51 */ "IsNull" OpHelp("if r[P1]==NULL goto P2"),
+ /* 52 */ "NotNull" OpHelp("if r[P1]!=NULL goto P2"),
+ /* 53 */ "Ne" OpHelp("IF r[P3]!=r[P1]"),
+ /* 54 */ "Eq" OpHelp("IF r[P3]==r[P1]"),
+ /* 55 */ "Gt" OpHelp("IF r[P3]>r[P1]"),
+ /* 56 */ "Le" OpHelp("IF r[P3]<=r[P1]"),
+ /* 57 */ "Lt" OpHelp("IF r[P3]=r[P1]"),
+ /* 59 */ "ElseEq" OpHelp(""),
+ /* 60 */ "FkIfZero" OpHelp("if fkctr[P1]==0 goto P2"),
+ /* 61 */ "IfPos" OpHelp("if r[P1]>0 then r[P1]-=P3, goto P2"),
+ /* 62 */ "IfNotZero" OpHelp("if r[P1]!=0 then r[P1]--, goto P2"),
+ /* 63 */ "DecrJumpZero" OpHelp("if (--r[P1])==0 goto P2"),
+ /* 64 */ "IncrVacuum" OpHelp(""),
+ /* 65 */ "VNext" OpHelp(""),
+ /* 66 */ "Filter" OpHelp("if key(P3@P4) not in filter(P1) goto P2"),
+ /* 67 */ "PureFunc" OpHelp("r[P3]=func(r[P2@NP])"),
+ /* 68 */ "Function" OpHelp("r[P3]=func(r[P2@NP])"),
+ /* 69 */ "Return" OpHelp(""),
+ /* 70 */ "EndCoroutine" OpHelp(""),
+ /* 71 */ "HaltIfNull" OpHelp("if r[P3]=null halt"),
+ /* 72 */ "Halt" OpHelp(""),
+ /* 73 */ "Integer" OpHelp("r[P2]=P1"),
+ /* 74 */ "Int64" OpHelp("r[P2]=P4"),
+ /* 75 */ "String" OpHelp("r[P2]='P4' (len=P1)"),
+ /* 76 */ "BeginSubrtn" OpHelp("r[P2]=NULL"),
+ /* 77 */ "Null" OpHelp("r[P2..P3]=NULL"),
+ /* 78 */ "SoftNull" OpHelp("r[P1]=NULL"),
+ /* 79 */ "Blob" OpHelp("r[P2]=P4 (len=P1)"),
+ /* 80 */ "Variable" OpHelp("r[P2]=parameter(P1)"),
+ /* 81 */ "Move" OpHelp("r[P2@P3]=r[P1@P3]"),
+ /* 82 */ "Copy" OpHelp("r[P2@P3+1]=r[P1@P3+1]"),
+ /* 83 */ "SCopy" OpHelp("r[P2]=r[P1]"),
+ /* 84 */ "IntCopy" OpHelp("r[P2]=r[P1]"),
+ /* 85 */ "FkCheck" OpHelp(""),
+ /* 86 */ "ResultRow" OpHelp("output=r[P1@P2]"),
+ /* 87 */ "CollSeq" OpHelp(""),
+ /* 88 */ "AddImm" OpHelp("r[P1]=r[P1]+P2"),
+ /* 89 */ "RealAffinity" OpHelp(""),
+ /* 90 */ "Cast" OpHelp("affinity(r[P1])"),
+ /* 91 */ "Permutation" OpHelp(""),
+ /* 92 */ "Compare" OpHelp("r[P1@P3] <-> r[P2@P3]"),
+ /* 93 */ "IsTrue" OpHelp("r[P2] = coalesce(r[P1]==TRUE,P3) ^ P4"),
+ /* 94 */ "ZeroOrNull" OpHelp("r[P2] = 0 OR NULL"),
+ /* 95 */ "Offset" OpHelp("r[P3] = sqlite_offset(P1)"),
+ /* 96 */ "Column" OpHelp("r[P3]=PX cursor P1 column P2"),
+ /* 97 */ "TypeCheck" OpHelp("typecheck(r[P1@P2])"),
+ /* 98 */ "Affinity" OpHelp("affinity(r[P1@P2])"),
+ /* 99 */ "MakeRecord" OpHelp("r[P3]=mkrec(r[P1@P2])"),
+ /* 100 */ "Count" OpHelp("r[P2]=count()"),
+ /* 101 */ "ReadCookie" OpHelp(""),
+ /* 102 */ "SetCookie" OpHelp(""),
+ /* 103 */ "BitAnd" OpHelp("r[P3]=r[P1]&r[P2]"),
+ /* 104 */ "BitOr" OpHelp("r[P3]=r[P1]|r[P2]"),
+ /* 105 */ "ShiftLeft" OpHelp("r[P3]=r[P2]<>r[P1]"),
+ /* 107 */ "Add" OpHelp("r[P3]=r[P1]+r[P2]"),
+ /* 108 */ "Subtract" OpHelp("r[P3]=r[P2]-r[P1]"),
+ /* 109 */ "Multiply" OpHelp("r[P3]=r[P1]*r[P2]"),
+ /* 110 */ "Divide" OpHelp("r[P3]=r[P2]/r[P1]"),
+ /* 111 */ "Remainder" OpHelp("r[P3]=r[P2]%r[P1]"),
+ /* 112 */ "Concat" OpHelp("r[P3]=r[P2]+r[P1]"),
+ /* 113 */ "ReopenIdx" OpHelp("root=P2 iDb=P3"),
+ /* 114 */ "OpenRead" OpHelp("root=P2 iDb=P3"),
+ /* 115 */ "BitNot" OpHelp("r[P2]= ~r[P1]"),
+ /* 116 */ "OpenWrite" OpHelp("root=P2 iDb=P3"),
+ /* 117 */ "OpenDup" OpHelp(""),
+ /* 118 */ "String8" OpHelp("r[P2]='P4'"),
+ /* 119 */ "OpenAutoindex" OpHelp("nColumn=P2"),
+ /* 120 */ "OpenEphemeral" OpHelp("nColumn=P2"),
+ /* 121 */ "SorterOpen" OpHelp(""),
+ /* 122 */ "SequenceTest" OpHelp("if( cursor[P1].ctr++ ) pc = P2"),
+ /* 123 */ "OpenPseudo" OpHelp("P3 columns in r[P2]"),
+ /* 124 */ "Close" OpHelp(""),
+ /* 125 */ "ColumnsUsed" OpHelp(""),
+ /* 126 */ "SeekScan" OpHelp("Scan-ahead up to P1 rows"),
+ /* 127 */ "SeekHit" OpHelp("set P2<=seekHit<=P3"),
+ /* 128 */ "Sequence" OpHelp("r[P2]=cursor[P1].ctr++"),
+ /* 129 */ "NewRowid" OpHelp("r[P2]=rowid"),
+ /* 130 */ "Insert" OpHelp("intkey=r[P3] data=r[P2]"),
+ /* 131 */ "RowCell" OpHelp(""),
+ /* 132 */ "Delete" OpHelp(""),
+ /* 133 */ "ResetCount" OpHelp(""),
+ /* 134 */ "SorterCompare" OpHelp("if key(P1)!=trim(r[P3],P4) goto P2"),
+ /* 135 */ "SorterData" OpHelp("r[P2]=data"),
+ /* 136 */ "RowData" OpHelp("r[P2]=data"),
+ /* 137 */ "Rowid" OpHelp("r[P2]=PX rowid of P1"),
+ /* 138 */ "NullRow" OpHelp(""),
+ /* 139 */ "SeekEnd" OpHelp(""),
+ /* 140 */ "IdxInsert" OpHelp("key=r[P2]"),
+ /* 141 */ "SorterInsert" OpHelp("key=r[P2]"),
+ /* 142 */ "IdxDelete" OpHelp("key=r[P2@P3]"),
+ /* 143 */ "DeferredSeek" OpHelp("Move P3 to P1.rowid if needed"),
+ /* 144 */ "IdxRowid" OpHelp("r[P2]=rowid"),
+ /* 145 */ "FinishSeek" OpHelp(""),
+ /* 146 */ "Destroy" OpHelp(""),
+ /* 147 */ "Clear" OpHelp(""),
+ /* 148 */ "ResetSorter" OpHelp(""),
+ /* 149 */ "CreateBtree" OpHelp("r[P2]=root iDb=P1 flags=P3"),
+ /* 150 */ "SqlExec" OpHelp(""),
+ /* 151 */ "ParseSchema" OpHelp(""),
+ /* 152 */ "LoadAnalysis" OpHelp(""),
+ /* 153 */ "DropTable" OpHelp(""),
+ /* 154 */ "Real" OpHelp("r[P2]=P4"),
+ /* 155 */ "DropIndex" OpHelp(""),
+ /* 156 */ "DropTrigger" OpHelp(""),
+ /* 157 */ "IntegrityCk" OpHelp(""),
+ /* 158 */ "RowSetAdd" OpHelp("rowset(P1)=r[P2]"),
+ /* 159 */ "Param" OpHelp(""),
+ /* 160 */ "FkCounter" OpHelp("fkctr[P1]+=P2"),
+ /* 161 */ "MemMax" OpHelp("r[P1]=max(r[P1],r[P2])"),
+ /* 162 */ "OffsetLimit" OpHelp("if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1)"),
+ /* 163 */ "AggInverse" OpHelp("accum=r[P3] inverse(r[P2@P5])"),
+ /* 164 */ "AggStep" OpHelp("accum=r[P3] step(r[P2@P5])"),
+ /* 165 */ "AggStep1" OpHelp("accum=r[P3] step(r[P2@P5])"),
+ /* 166 */ "AggValue" OpHelp("r[P3]=value N=P2"),
+ /* 167 */ "AggFinal" OpHelp("accum=r[P1] N=P2"),
+ /* 168 */ "Expire" OpHelp(""),
+ /* 169 */ "CursorLock" OpHelp(""),
+ /* 170 */ "CursorUnlock" OpHelp(""),
+ /* 171 */ "TableLock" OpHelp("iDb=P1 root=P2 write=P3"),
+ /* 172 */ "VBegin" OpHelp(""),
+ /* 173 */ "VCreate" OpHelp(""),
+ /* 174 */ "VDestroy" OpHelp(""),
+ /* 175 */ "VOpen" OpHelp(""),
+ /* 176 */ "VCheck" OpHelp(""),
+ /* 177 */ "VInitIn" OpHelp("r[P2]=ValueList(P1,P3)"),
+ /* 178 */ "VColumn" OpHelp("r[P3]=vcolumn(P2)"),
+ /* 179 */ "VRename" OpHelp(""),
+ /* 180 */ "Pagecount" OpHelp(""),
+ /* 181 */ "MaxPgcnt" OpHelp(""),
+ /* 182 */ "ClrSubtype" OpHelp("r[P1].subtype = 0"),
+ /* 183 */ "GetSubtype" OpHelp("r[P2] = r[P1].subtype"),
+ /* 184 */ "SetSubtype" OpHelp("r[P2].subtype = r[P1]"),
+ /* 185 */ "FilterAdd" OpHelp("filter(P1) += key(P3@P4)"),
+ /* 186 */ "Trace" OpHelp(""),
+ /* 187 */ "CursorHint" OpHelp(""),
+ /* 188 */ "ReleaseReg" OpHelp("release r[P1@P2] mask P3"),
+ /* 189 */ "Noop" OpHelp(""),
+ /* 190 */ "Explain" OpHelp(""),
+ /* 191 */ "Abortable" OpHelp(""),
};
return azName[i];
}
#endif
/************** End of opcodes.c *********************************************/
+/************** Begin file os_kv.c *******************************************/
+/*
+** 2022-09-06
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+******************************************************************************
+**
+** This file contains an experimental VFS layer that operates on a
+** Key/Value storage engine where both keys and values must be pure
+** text.
+*/
+/* #include */
+#if SQLITE_OS_KV || (SQLITE_OS_UNIX && defined(SQLITE_OS_KV_OPTIONAL))
+
+/*****************************************************************************
+** Debugging logic
+*/
+
+/* SQLITE_KV_TRACE() is used for tracing calls to kvrecord routines. */
+#if 0
+#define SQLITE_KV_TRACE(X) printf X
+#else
+#define SQLITE_KV_TRACE(X)
+#endif
+
+/* SQLITE_KV_LOG() is used for tracing calls to the VFS interface */
+#if 0
+#define SQLITE_KV_LOG(X) printf X
+#else
+#define SQLITE_KV_LOG(X)
+#endif
+
+/*
+** Forward declaration of objects used by this VFS implementation
+*/
+typedef struct KVVfsFile KVVfsFile;
+
+/* A single open file. There are only two files represented by this
+** VFS - the database and the rollback journal.
+**
+** Maintenance reminder: if this struct changes in any way, the JSON
+** rendering of its structure must be updated in
+** sqlite3-wasm.c:sqlite3__wasm_enum_json(). There are no binary
+** compatibility concerns, so it does not need an iVersion member.
+*/
+struct KVVfsFile {
+ sqlite3_file base; /* IO methods */
+ const char *zClass; /* Storage class */
+ int isJournal; /* True if this is a journal file */
+ unsigned int nJrnl; /* Space allocated for aJrnl[] */
+ char *aJrnl; /* Journal content */
+ int szPage; /* Last known page size */
+ sqlite3_int64 szDb; /* Database file size. -1 means unknown */
+ char *aData; /* Buffer to hold page data */
+};
+#define SQLITE_KVOS_SZ 133073
+
+/*
+** Methods for KVVfsFile
+*/
+static int kvvfsClose(sqlite3_file*);
+static int kvvfsReadDb(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);
+static int kvvfsReadJrnl(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);
+static int kvvfsWriteDb(sqlite3_file*,const void*,int iAmt, sqlite3_int64);
+static int kvvfsWriteJrnl(sqlite3_file*,const void*,int iAmt, sqlite3_int64);
+static int kvvfsTruncateDb(sqlite3_file*, sqlite3_int64 size);
+static int kvvfsTruncateJrnl(sqlite3_file*, sqlite3_int64 size);
+static int kvvfsSyncDb(sqlite3_file*, int flags);
+static int kvvfsSyncJrnl(sqlite3_file*, int flags);
+static int kvvfsFileSizeDb(sqlite3_file*, sqlite3_int64 *pSize);
+static int kvvfsFileSizeJrnl(sqlite3_file*, sqlite3_int64 *pSize);
+static int kvvfsLock(sqlite3_file*, int);
+static int kvvfsUnlock(sqlite3_file*, int);
+static int kvvfsCheckReservedLock(sqlite3_file*, int *pResOut);
+static int kvvfsFileControlDb(sqlite3_file*, int op, void *pArg);
+static int kvvfsFileControlJrnl(sqlite3_file*, int op, void *pArg);
+static int kvvfsSectorSize(sqlite3_file*);
+static int kvvfsDeviceCharacteristics(sqlite3_file*);
+
+/*
+** Methods for sqlite3_vfs
+*/
+static int kvvfsOpen(sqlite3_vfs*, const char *, sqlite3_file*, int , int *);
+static int kvvfsDelete(sqlite3_vfs*, const char *zName, int syncDir);
+static int kvvfsAccess(sqlite3_vfs*, const char *zName, int flags, int *);
+static int kvvfsFullPathname(sqlite3_vfs*, const char *zName, int, char *zOut);
+static void *kvvfsDlOpen(sqlite3_vfs*, const char *zFilename);
+static int kvvfsRandomness(sqlite3_vfs*, int nByte, char *zOut);
+static int kvvfsSleep(sqlite3_vfs*, int microseconds);
+static int kvvfsCurrentTime(sqlite3_vfs*, double*);
+static int kvvfsCurrentTimeInt64(sqlite3_vfs*, sqlite3_int64*);
+
+static sqlite3_vfs sqlite3OsKvvfsObject = {
+ 2, /* iVersion */
+ sizeof(KVVfsFile), /* szOsFile */
+ 1024, /* mxPathname */
+ 0, /* pNext */
+ "kvvfs", /* zName */
+ 0, /* pAppData */
+ kvvfsOpen, /* xOpen */
+ kvvfsDelete, /* xDelete */
+ kvvfsAccess, /* xAccess */
+ kvvfsFullPathname, /* xFullPathname */
+ kvvfsDlOpen, /* xDlOpen */
+ 0, /* xDlError */
+ 0, /* xDlSym */
+ 0, /* xDlClose */
+ kvvfsRandomness, /* xRandomness */
+ kvvfsSleep, /* xSleep */
+ kvvfsCurrentTime, /* xCurrentTime */
+ 0, /* xGetLastError */
+ kvvfsCurrentTimeInt64 /* xCurrentTimeInt64 */
+};
+
+/* Methods for sqlite3_file objects referencing a database file
+*/
+static sqlite3_io_methods kvvfs_db_io_methods = {
+ 1, /* iVersion */
+ kvvfsClose, /* xClose */
+ kvvfsReadDb, /* xRead */
+ kvvfsWriteDb, /* xWrite */
+ kvvfsTruncateDb, /* xTruncate */
+ kvvfsSyncDb, /* xSync */
+ kvvfsFileSizeDb, /* xFileSize */
+ kvvfsLock, /* xLock */
+ kvvfsUnlock, /* xUnlock */
+ kvvfsCheckReservedLock, /* xCheckReservedLock */
+ kvvfsFileControlDb, /* xFileControl */
+ kvvfsSectorSize, /* xSectorSize */
+ kvvfsDeviceCharacteristics, /* xDeviceCharacteristics */
+ 0, /* xShmMap */
+ 0, /* xShmLock */
+ 0, /* xShmBarrier */
+ 0, /* xShmUnmap */
+ 0, /* xFetch */
+ 0 /* xUnfetch */
+};
+
+/* Methods for sqlite3_file objects referencing a rollback journal
+*/
+static sqlite3_io_methods kvvfs_jrnl_io_methods = {
+ 1, /* iVersion */
+ kvvfsClose, /* xClose */
+ kvvfsReadJrnl, /* xRead */
+ kvvfsWriteJrnl, /* xWrite */
+ kvvfsTruncateJrnl, /* xTruncate */
+ kvvfsSyncJrnl, /* xSync */
+ kvvfsFileSizeJrnl, /* xFileSize */
+ kvvfsLock, /* xLock */
+ kvvfsUnlock, /* xUnlock */
+ kvvfsCheckReservedLock, /* xCheckReservedLock */
+ kvvfsFileControlJrnl, /* xFileControl */
+ kvvfsSectorSize, /* xSectorSize */
+ kvvfsDeviceCharacteristics, /* xDeviceCharacteristics */
+ 0, /* xShmMap */
+ 0, /* xShmLock */
+ 0, /* xShmBarrier */
+ 0, /* xShmUnmap */
+ 0, /* xFetch */
+ 0 /* xUnfetch */
+};
+
+/****** Storage subsystem **************************************************/
+#include
+#include
+#include
+
+/* Forward declarations for the low-level storage engine
+*/
+#ifndef SQLITE_WASM
+/* In WASM builds these are implemented in JS. */
+static int kvrecordWrite(const char*, const char *zKey, const char *zData);
+static int kvrecordDelete(const char*, const char *zKey);
+static int kvrecordRead(const char*, const char *zKey, char *zBuf, int nBuf);
+#endif
+#ifndef KVRECORD_KEY_SZ
+#define KVRECORD_KEY_SZ 32
+#endif
+
+/* Expand the key name with an appropriate prefix and put the result
+** in zKeyOut[]. The zKeyOut[] buffer is assumed to hold at least
+** KVRECORD_KEY_SZ bytes.
+*/
+static void kvrecordMakeKey(
+ const char *zClass,
+ const char *zKeyIn,
+ char *zKeyOut
+){
+ assert( zKeyIn );
+ assert( zKeyOut );
+ assert( zClass );
+ sqlite3_snprintf(KVRECORD_KEY_SZ, zKeyOut, "kvvfs-%s-%s",
+ zClass, zKeyIn);
+}
+
+#ifndef SQLITE_WASM
+/* In WASM builds do not define APIs which use fopen(), fwrite(),
+** and the like because those APIs are a portability issue for
+** WASM.
+*/
+/* Write content into a key. zClass is the particular namespace of the
+** underlying key/value store to use - either "local" or "session".
+**
+** Both zKey and zData are zero-terminated pure text strings.
+**
+** Return the number of errors.
+*/
+static int kvrecordWrite(
+ const char *zClass,
+ const char *zKey,
+ const char *zData
+){
+ FILE *fd;
+ char zXKey[KVRECORD_KEY_SZ];
+ kvrecordMakeKey(zClass, zKey, zXKey);
+ fd = fopen(zXKey, "wb");
+ if( fd ){
+ SQLITE_KV_TRACE(("KVVFS-WRITE %-15s (%d) %.50s%s\n", zXKey,
+ (int)strlen(zData), zData,
+ strlen(zData)>50 ? "..." : ""));
+ fputs(zData, fd);
+ fclose(fd);
+ return 0;
+ }else{
+ return 1;
+ }
+}
+
+/* Delete a key (with its corresponding data) from the key/value
+** namespace given by zClass. If the key does not previously exist,
+** this routine is a no-op.
+*/
+static int kvrecordDelete(const char *zClass, const char *zKey){
+ char zXKey[KVRECORD_KEY_SZ];
+ kvrecordMakeKey(zClass, zKey, zXKey);
+ unlink(zXKey);
+ SQLITE_KV_TRACE(("KVVFS-DELETE %-15s\n", zXKey));
+ return 0;
+}
+
+/* Read the value associated with a zKey from the key/value namespace given
+** by zClass and put the text data associated with that key in the first
+** nBuf bytes of zBuf[]. The value might be truncated if zBuf is not large
+** enough to hold it all. The value put into zBuf must always be zero
+** terminated, even if it gets truncated because nBuf is not large enough.
+**
+** Return the total number of bytes in the data, without truncation, and
+** not counting the final zero terminator. Return -1 if the key does
+** not exist or its key cannot be read.
+**
+** If nBuf<=0 then this routine simply returns the size of the data
+** without actually reading it. Similarly, if nBuf==1 then it
+** zero-terminates zBuf at zBuf[0] and returns the size of the data
+** without reading it.
+*/
+static int kvrecordRead(
+ const char *zClass,
+ const char *zKey,
+ char *zBuf,
+ int nBuf
+){
+ FILE *fd;
+ struct stat buf;
+ char zXKey[KVRECORD_KEY_SZ];
+ kvrecordMakeKey(zClass, zKey, zXKey);
+ if( access(zXKey, R_OK)!=0
+ || stat(zXKey, &buf)!=0
+ || !S_ISREG(buf.st_mode)
+ ){
+ SQLITE_KV_TRACE(("KVVFS-READ %-15s (-1)\n", zXKey));
+ return -1;
+ }
+ if( nBuf<=0 ){
+ return (int)buf.st_size;
+ }else if( nBuf==1 ){
+ zBuf[0] = 0;
+ SQLITE_KV_TRACE(("KVVFS-READ %-15s (%d)\n", zXKey,
+ (int)buf.st_size));
+ return (int)buf.st_size;
+ }
+ if( nBuf > buf.st_size + 1 ){
+ nBuf = buf.st_size + 1;
+ }
+ fd = fopen(zXKey, "rb");
+ if( fd==0 ){
+ SQLITE_KV_TRACE(("KVVFS-READ %-15s (-1)\n", zXKey));
+ return -1;
+ }else{
+ sqlite3_int64 n = fread(zBuf, 1, nBuf-1, fd);
+ fclose(fd);
+ zBuf[n] = 0;
+ SQLITE_KV_TRACE(("KVVFS-READ %-15s (%lld) %.50s%s\n", zXKey,
+ n, zBuf, n>50 ? "..." : ""));
+ return (int)n;
+ }
+}
+#endif /* #ifndef SQLITE_WASM */
+
+
+/*
+** An internal level of indirection which enables us to replace the
+** kvvfs i/o methods with JavaScript implementations in WASM builds.
+** Maintenance reminder: if this struct changes in any way, the JSON
+** rendering of its structure must be updated in
+** sqlite3-wasm.c:sqlite3__wasm_enum_json(). There are no binary
+** compatibility concerns, so it does not need an iVersion member.
+*/
+typedef struct sqlite3_kvvfs_methods sqlite3_kvvfs_methods;
+struct sqlite3_kvvfs_methods {
+ int (*xRcrdRead)(const char*, const char *zKey, char *zBuf, int nBuf);
+ int (*xRcrdWrite)(const char*, const char *zKey, const char *zData);
+ int (*xRcrdDelete)(const char*, const char *zKey);
+ const int nKeySize;
+ const int nBufferSize;
+#ifndef SQLITE_WASM
+# define MAYBE_CONST const
+#else
+# define MAYBE_CONST
+#endif
+ MAYBE_CONST sqlite3_vfs * pVfs;
+ MAYBE_CONST sqlite3_io_methods *pIoDb;
+ MAYBE_CONST sqlite3_io_methods *pIoJrnl;
+#undef MAYBE_CONST
+};
+
+
+/*
+** This object holds the kvvfs I/O methods which may be swapped out
+** for JavaScript-side implementations in WASM builds. In such builds
+** it cannot be const, but in native builds it should be so that
+** the compiler can hopefully optimize this level of indirection out.
+** That said, kvvfs is intended primarily for use in WASM builds.
+**
+** This is not explicitly flagged as static because the amalgamation
+** build will tag it with SQLITE_PRIVATE.
+*/
+#ifndef SQLITE_WASM
+const
+#endif
+SQLITE_PRIVATE sqlite3_kvvfs_methods sqlite3KvvfsMethods = {
+#ifndef SQLITE_WASM
+ .xRcrdRead = kvrecordRead,
+ .xRcrdWrite = kvrecordWrite,
+ .xRcrdDelete = kvrecordDelete,
+#else
+ .xRcrdRead = 0,
+ .xRcrdWrite = 0,
+ .xRcrdDelete = 0,
+#endif
+ .nKeySize = KVRECORD_KEY_SZ,
+ .nBufferSize = SQLITE_KVOS_SZ,
+ .pVfs = &sqlite3OsKvvfsObject,
+ .pIoDb = &kvvfs_db_io_methods,
+ .pIoJrnl = &kvvfs_jrnl_io_methods
+};
+
+/****** Utility subroutines ************************************************/
+
+/*
+** Encode binary into the text encoded used to persist on disk.
+** The output text is stored in aOut[], which must be at least
+** nData+1 bytes in length.
+**
+** Return the actual length of the encoded text, not counting the
+** zero terminator at the end.
+**
+** Encoding format
+** ---------------
+**
+** * Non-zero bytes are encoded as upper-case hexadecimal
+**
+** * A sequence of one or more zero-bytes that are not at the
+** beginning of the buffer are encoded as a little-endian
+** base-26 number using a..z. "a" means 0. "b" means 1,
+** "z" means 25. "ab" means 26. "ac" means 52. And so forth.
+**
+** * Because there is no overlap between the encoding characters
+** of hexadecimal and base-26 numbers, it is always clear where
+** one stops and the next begins.
+*/
+#ifndef SQLITE_WASM
+static
+#endif
+int kvvfsEncode(const char *aData, int nData, char *aOut){
+ int i, j;
+ const unsigned char *a = (const unsigned char*)aData;
+ for(i=j=0; i>4];
+ aOut[j++] = "0123456789ABCDEF"[c&0xf];
+ }else{
+ /* A sequence of 1 or more zeros is stored as a little-endian
+ ** base-26 number using a..z as the digits. So one zero is "b".
+ ** Two zeros is "c". 25 zeros is "z", 26 zeros is "ab", 27 is "bb",
+ ** and so forth.
+ */
+ int k;
+ for(k=1; i+k0 ){
+ aOut[j++] = 'a'+(k%26);
+ k /= 26;
+ }
+ }
+ }
+ aOut[j] = 0;
+ return j;
+}
+
+static const signed char kvvfsHexValue[256] = {
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1,
+ -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+};
+
+/*
+** Decode the text encoding back to binary. The binary content is
+** written into pOut, which must be at least nOut bytes in length.
+**
+** The return value is the number of bytes actually written into aOut[], or
+** -1 for malformed inputs.
+*/
+#ifndef SQLITE_WASM
+static
+#endif
+int kvvfsDecode(const char *a, char *aOut, int nOut){
+ int i, j;
+ int c;
+ const unsigned char *aIn = (const unsigned char*)a;
+ i = 0;
+ j = 0;
+ while( 1 ){
+ c = kvvfsHexValue[aIn[i]];
+ if( c<0 ){
+ sqlite3_int64 n = 0;
+ sqlite3_int64 mult = 1;
+ c = aIn[i];
+ if( c==0 ) break;
+ while( c>='a' && c<='z' ){
+ n += (c - 'a')*mult;
+ if( n>nOut ) return -1 /* oversized/malformed input */;
+ mult *= 26;
+ c = aIn[++i];
+ }
+ if( j+n>nOut ) return -1 /* oversized/malformed input */;
+ memset(&aOut[j], 0, n);
+ j += n;
+ if( c==0 || mult==1 ) break; /* progress stalled if mult==1 */
+ }else{
+ aOut[j] = c<<4;
+ c = kvvfsHexValue[aIn[++i]];
+ if( c<0 ) return -1 /* hex bytes are always in pairs */;
+ aOut[j++] += c;
+ i++;
+ }
+ }
+ return j;
+}
+
+/*
+** Decode a complete journal file. Allocate space in pFile->aJrnl
+** and store the decoding there. Or leave pFile->aJrnl set to NULL
+** if an error is encountered.
+**
+** The first few characters of the text encoding will be a little-endian
+** base-26 number (digits a..z) that is the total number of bytes
+** in the decoded journal file image. This base-26 number is followed
+** by a single space, then the encoding of the journal. The space
+** separator is required to act as a terminator for the base-26 number.
+*/
+static void kvvfsDecodeJournal(
+ KVVfsFile *pFile, /* Store decoding in pFile->aJrnl */
+ const char *zTxt, /* Text encoding. Zero-terminated */
+ int nTxt /* Bytes in zTxt, excluding zero terminator */
+){
+ unsigned int n = 0;
+ int c, i, mult;
+ i = 0;
+ mult = 1;
+ while( (c = zTxt[i++])>='a' && c<='z' ){
+ n += (c - 'a')*mult;
+ mult *= 26;
+ }
+ sqlite3_free(pFile->aJrnl);
+ pFile->aJrnl = sqlite3_malloc64( n );
+ if( pFile->aJrnl==0 ){
+ pFile->nJrnl = 0;
+ return;
+ }
+ pFile->nJrnl = n;
+ n = kvvfsDecode(zTxt+i, pFile->aJrnl, pFile->nJrnl);
+ if( nnJrnl ){
+ sqlite3_free(pFile->aJrnl);
+ pFile->aJrnl = 0;
+ pFile->nJrnl = 0;
+ }
+}
+
+/*
+** Read or write the "sz" element, containing the database file size.
+*/
+static sqlite3_int64 kvvfsReadFileSize(KVVfsFile *pFile){
+ char zData[50];
+ zData[0] = 0;
+ sqlite3KvvfsMethods.xRcrdRead(pFile->zClass, "sz", zData,
+ sizeof(zData)-1);
+ return strtoll(zData, 0, 0);
+}
+static int kvvfsWriteFileSize(KVVfsFile *pFile, sqlite3_int64 sz){
+ char zData[50];
+ sqlite3_snprintf(sizeof(zData), zData, "%lld", sz);
+ return sqlite3KvvfsMethods.xRcrdWrite(pFile->zClass, "sz", zData);
+}
+
+/****** sqlite3_io_methods methods ******************************************/
+
+/*
+** Close an kvvfs-file.
+*/
+static int kvvfsClose(sqlite3_file *pProtoFile){
+ KVVfsFile *pFile = (KVVfsFile *)pProtoFile;
+
+ SQLITE_KV_LOG(("xClose %s %s\n", pFile->zClass,
+ pFile->isJournal ? "journal" : "db"));
+ sqlite3_free(pFile->aJrnl);
+ sqlite3_free(pFile->aData);
+ memset(pFile, 0, sizeof(*pFile));
+ return SQLITE_OK;
+}
+
+/*
+** Read from the -journal file.
+*/
+static int kvvfsReadJrnl(
+ sqlite3_file *pProtoFile,
+ void *zBuf,
+ int iAmt,
+ sqlite_int64 iOfst
+){
+ KVVfsFile *pFile = (KVVfsFile*)pProtoFile;
+ assert( pFile->isJournal );
+ SQLITE_KV_LOG(("xRead('%s-journal',%d,%lld)\n", pFile->zClass, iAmt, iOfst));
+ if( pFile->aJrnl==0 ){
+ int rc;
+ int szTxt = sqlite3KvvfsMethods.xRcrdRead(pFile->zClass, "jrnl",
+ 0, 0);
+ char *aTxt;
+ if( szTxt<=4 ){
+ return SQLITE_IOERR;
+ }
+ aTxt = sqlite3_malloc64( szTxt+1 );
+ if( aTxt==0 ) return SQLITE_NOMEM;
+ rc = sqlite3KvvfsMethods.xRcrdRead(pFile->zClass, "jrnl",
+ aTxt, szTxt+1);
+ if( rc>=0 ){
+ kvvfsDecodeJournal(pFile, aTxt, szTxt);
+ rc = 0;
+ }
+ sqlite3_free(aTxt);
+ if( rc ) return rc;
+ if( pFile->aJrnl==0 ) return SQLITE_IOERR;
+ }
+ if( iOfst+iAmt>pFile->nJrnl ){
+ return SQLITE_IOERR_SHORT_READ;
+ }
+ memcpy(zBuf, pFile->aJrnl+iOfst, iAmt);
+ return SQLITE_OK;
+}
+
+/*
+** Read from the database file.
+*/
+static int kvvfsReadDb(
+ sqlite3_file *pProtoFile,
+ void *zBuf,
+ int iAmt,
+ sqlite_int64 iOfst
+){
+ KVVfsFile *pFile = (KVVfsFile*)pProtoFile;
+ unsigned int pgno;
+ int got, n;
+ char zKey[30];
+ char *aData = pFile->aData;
+ assert( iOfst>=0 );
+ assert( iAmt>=0 );
+ SQLITE_KV_LOG(("xRead('%s-db',%d,%lld)\n", pFile->zClass, iAmt, iOfst));
+ if( iOfst+iAmt>=512 ){
+ if( (iOfst % iAmt)!=0 ){
+ return SQLITE_IOERR_READ;
+ }
+ if( (iAmt & (iAmt-1))!=0 || iAmt<512 || iAmt>65536 ){
+ return SQLITE_IOERR_READ;
+ }
+ pFile->szPage = iAmt;
+ pgno = 1 + iOfst/iAmt;
+ }else{
+ pgno = 1;
+ }
+ sqlite3_snprintf(sizeof(zKey), zKey, "%u", pgno);
+ got = sqlite3KvvfsMethods.xRcrdRead(pFile->zClass, zKey,
+ aData, SQLITE_KVOS_SZ-1);
+ if( got<0 ){
+ n = 0;
+ }else{
+ aData[got] = 0;
+ if( iOfst+iAmt<512 ){
+ int k = iOfst+iAmt;
+ aData[k*2] = 0;
+ n = kvvfsDecode(aData, &aData[2000], SQLITE_KVOS_SZ-2000);
+ if( n>=iOfst+iAmt ){
+ memcpy(zBuf, &aData[2000+iOfst], iAmt);
+ n = iAmt;
+ }else{
+ n = 0;
+ }
+ }else{
+ n = kvvfsDecode(aData, zBuf, iAmt);
+ }
+ }
+ if( nzClass, iAmt, iOfst));
+ if( iEnd>=0x10000000 ) return SQLITE_FULL;
+ if( pFile->aJrnl==0 || pFile->nJrnlaJrnl, iEnd);
+ if( aNew==0 ){
+ return SQLITE_IOERR_NOMEM;
+ }
+ pFile->aJrnl = aNew;
+ if( pFile->nJrnlaJrnl+pFile->nJrnl, 0, iOfst-pFile->nJrnl);
+ }
+ pFile->nJrnl = iEnd;
+ }
+ memcpy(pFile->aJrnl+iOfst, zBuf, iAmt);
+ return SQLITE_OK;
+}
+
+/*
+** Write into the database file.
+*/
+static int kvvfsWriteDb(
+ sqlite3_file *pProtoFile,
+ const void *zBuf,
+ int iAmt,
+ sqlite_int64 iOfst
+){
+ KVVfsFile *pFile = (KVVfsFile*)pProtoFile;
+ unsigned int pgno;
+ char zKey[30];
+ char *aData = pFile->aData;
+ int rc;
+ SQLITE_KV_LOG(("xWrite('%s-db',%d,%lld)\n", pFile->zClass, iAmt, iOfst));
+ assert( iAmt>=512 && iAmt<=65536 );
+ assert( (iAmt & (iAmt-1))==0 );
+ assert( pFile->szPage<0 || pFile->szPage==iAmt );
+ pFile->szPage = iAmt;
+ pgno = 1 + iOfst/iAmt;
+ sqlite3_snprintf(sizeof(zKey), zKey, "%u", pgno);
+ kvvfsEncode(zBuf, iAmt, aData);
+ rc = sqlite3KvvfsMethods.xRcrdWrite(pFile->zClass, zKey, aData);
+ if( 0==rc ){
+ if( iOfst+iAmt > pFile->szDb ){
+ pFile->szDb = iOfst + iAmt;
+ }
+ }
+ return rc;
+}
+
+/*
+** Truncate an kvvfs-file.
+*/
+static int kvvfsTruncateJrnl(sqlite3_file *pProtoFile, sqlite_int64 size){
+ KVVfsFile *pFile = (KVVfsFile *)pProtoFile;
+ SQLITE_KV_LOG(("xTruncate('%s-journal',%lld)\n", pFile->zClass, size));
+ assert( size==0 );
+ sqlite3KvvfsMethods.xRcrdDelete(pFile->zClass, "jrnl");
+ sqlite3_free(pFile->aJrnl);
+ pFile->aJrnl = 0;
+ pFile->nJrnl = 0;
+ return SQLITE_OK;
+}
+static int kvvfsTruncateDb(sqlite3_file *pProtoFile, sqlite_int64 size){
+ KVVfsFile *pFile = (KVVfsFile *)pProtoFile;
+ if( pFile->szDb>size
+ && pFile->szPage>0
+ && (size % pFile->szPage)==0
+ ){
+ char zKey[50];
+ unsigned int pgno, pgnoMax;
+ SQLITE_KV_LOG(("xTruncate('%s-db',%lld)\n", pFile->zClass, size));
+ pgno = 1 + size/pFile->szPage;
+ pgnoMax = 2 + pFile->szDb/pFile->szPage;
+ while( pgno<=pgnoMax ){
+ sqlite3_snprintf(sizeof(zKey), zKey, "%u", pgno);
+ sqlite3KvvfsMethods.xRcrdDelete(pFile->zClass, zKey);
+ pgno++;
+ }
+ pFile->szDb = size;
+ return kvvfsWriteFileSize(pFile, size) ? SQLITE_IOERR : SQLITE_OK;
+ }
+ return SQLITE_IOERR;
+}
+
+/*
+** Sync an kvvfs-file.
+*/
+static int kvvfsSyncJrnl(sqlite3_file *pProtoFile, int flags){
+ int i, n;
+ KVVfsFile *pFile = (KVVfsFile *)pProtoFile;
+ char *zOut;
+ SQLITE_KV_LOG(("xSync('%s-journal')\n", pFile->zClass));
+ if( pFile->nJrnl<=0 ){
+ return kvvfsTruncateJrnl(pProtoFile, 0);
+ }
+ zOut = sqlite3_malloc64( pFile->nJrnl*2 + 50 );
+ if( zOut==0 ){
+ return SQLITE_IOERR_NOMEM;
+ }
+ n = pFile->nJrnl;
+ i = 0;
+ do{
+ zOut[i++] = 'a' + (n%26);
+ n /= 26;
+ }while( n>0 );
+ zOut[i++] = ' ';
+ kvvfsEncode(pFile->aJrnl, pFile->nJrnl, &zOut[i]);
+ i = sqlite3KvvfsMethods.xRcrdWrite(pFile->zClass, "jrnl", zOut);
+ sqlite3_free(zOut);
+ return i ? SQLITE_IOERR : SQLITE_OK;
+}
+static int kvvfsSyncDb(sqlite3_file *pProtoFile, int flags){
+ return SQLITE_OK;
+}
+
+/*
+** Return the current file-size of an kvvfs-file.
+*/
+static int kvvfsFileSizeJrnl(sqlite3_file *pProtoFile, sqlite_int64 *pSize){
+ KVVfsFile *pFile = (KVVfsFile *)pProtoFile;
+ SQLITE_KV_LOG(("xFileSize('%s-journal')\n", pFile->zClass));
+ *pSize = pFile->nJrnl;
+ return SQLITE_OK;
+}
+static int kvvfsFileSizeDb(sqlite3_file *pProtoFile, sqlite_int64 *pSize){
+ KVVfsFile *pFile = (KVVfsFile *)pProtoFile;
+ SQLITE_KV_LOG(("xFileSize('%s-db')\n", pFile->zClass));
+ if( pFile->szDb>=0 ){
+ *pSize = pFile->szDb;
+ }else{
+ *pSize = kvvfsReadFileSize(pFile);
+ }
+ return SQLITE_OK;
+}
+
+/*
+** Lock an kvvfs-file.
+*/
+static int kvvfsLock(sqlite3_file *pProtoFile, int eLock){
+ KVVfsFile *pFile = (KVVfsFile *)pProtoFile;
+ assert( !pFile->isJournal );
+ SQLITE_KV_LOG(("xLock(%s,%d)\n", pFile->zClass, eLock));
+
+ if( eLock!=SQLITE_LOCK_NONE ){
+ pFile->szDb = kvvfsReadFileSize(pFile);
+ }
+ return SQLITE_OK;
+}
+
+/*
+** Unlock an kvvfs-file.
+*/
+static int kvvfsUnlock(sqlite3_file *pProtoFile, int eLock){
+ KVVfsFile *pFile = (KVVfsFile *)pProtoFile;
+ assert( !pFile->isJournal );
+ SQLITE_KV_LOG(("xUnlock(%s,%d)\n", pFile->zClass, eLock));
+ if( eLock==SQLITE_LOCK_NONE ){
+ pFile->szDb = -1;
+ }
+ return SQLITE_OK;
+}
+
+/*
+** Check if another file-handle holds a RESERVED lock on an kvvfs-file.
+*/
+static int kvvfsCheckReservedLock(sqlite3_file *pProtoFile, int *pResOut){
+ SQLITE_KV_LOG(("xCheckReservedLock\n"));
+ *pResOut = 0;
+ return SQLITE_OK;
+}
+
+/*
+** File control method. For custom operations on an kvvfs-file.
+*/
+static int kvvfsFileControlJrnl(sqlite3_file *pProtoFile, int op, void *pArg){
+ SQLITE_KV_LOG(("xFileControl(%d) on journal\n", op));
+ return SQLITE_NOTFOUND;
+}
+static int kvvfsFileControlDb(sqlite3_file *pProtoFile, int op, void *pArg){
+ SQLITE_KV_LOG(("xFileControl(%d) on database\n", op));
+ if( op==SQLITE_FCNTL_SYNC ){
+ KVVfsFile *pFile = (KVVfsFile *)pProtoFile;
+ int rc = SQLITE_OK;
+ SQLITE_KV_LOG(("xSync('%s-db')\n", pFile->zClass));
+ if( pFile->szDb>0 && 0!=kvvfsWriteFileSize(pFile, pFile->szDb) ){
+ rc = SQLITE_IOERR;
+ }
+ return rc;
+ }
+ return SQLITE_NOTFOUND;
+}
+
+/*
+** Return the sector-size in bytes for an kvvfs-file.
+*/
+static int kvvfsSectorSize(sqlite3_file *pFile){
+ return 512;
+}
+
+/*
+** Return the device characteristic flags supported by an kvvfs-file.
+*/
+static int kvvfsDeviceCharacteristics(sqlite3_file *pProtoFile){
+ return 0;
+}
+
+/****** sqlite3_vfs methods *************************************************/
+
+/*
+** Open an kvvfs file handle.
+*/
+static int kvvfsOpen(
+ sqlite3_vfs *pProtoVfs,
+ const char *zName,
+ sqlite3_file *pProtoFile,
+ int flags,
+ int *pOutFlags
+){
+ KVVfsFile *pFile = (KVVfsFile*)pProtoFile;
+ if( zName==0 ) zName = "";
+ SQLITE_KV_LOG(("xOpen(\"%s\")\n", zName));
+ assert(!pFile->zClass);
+ assert(!pFile->aData);
+ assert(!pFile->aJrnl);
+ assert(!pFile->nJrnl);
+ assert(!pFile->base.pMethods);
+ pFile->szPage = -1;
+ pFile->szDb = -1;
+ if( 0==sqlite3_strglob("*-journal", zName) ){
+ pFile->isJournal = 1;
+ pFile->base.pMethods = &kvvfs_jrnl_io_methods;
+ if( 0==strcmp("session-journal",zName) ){
+ pFile->zClass = "session";
+ }else if( 0==strcmp("local-journal",zName) ){
+ pFile->zClass = "local";
+ }
+ }else{
+ pFile->isJournal = 0;
+ pFile->base.pMethods = &kvvfs_db_io_methods;
+ }
+ if( !pFile->zClass ){
+ pFile->zClass = zName;
+ }
+ pFile->aData = sqlite3_malloc64(SQLITE_KVOS_SZ);
+ if( pFile->aData==0 ){
+ return SQLITE_NOMEM;
+ }
+ return SQLITE_OK;
+}
+
+/*
+** Delete the file located at zPath. If the dirSync argument is true,
+** ensure the file-system modifications are synced to disk before
+** returning.
+*/
+static int kvvfsDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
+ int rc /* The JS impl can fail with OOM in argument conversion */;
+ if( strcmp(zPath, "local-journal")==0 ){
+ rc = sqlite3KvvfsMethods.xRcrdDelete("local", "jrnl");
+ }else
+ if( strcmp(zPath, "session-journal")==0 ){
+ rc = sqlite3KvvfsMethods.xRcrdDelete("session", "jrnl");
+ }
+ else{
+ rc = 0;
+ }
+ return rc;
+}
+
+/*
+** Test for access permissions. Return true if the requested permission
+** is available, or false otherwise.
+*/
+static int kvvfsAccess(
+ sqlite3_vfs *pProtoVfs,
+ const char *zPath,
+ int flags,
+ int *pResOut
+){
+ SQLITE_KV_LOG(("xAccess(\"%s\")\n", zPath));
+#if 0 && defined(SQLITE_WASM)
+ /*
+ ** This is not having the desired effect in the JS bindings.
+ ** It's ostensibly the same logic as the #else block, but
+ ** it's not behaving that way.
+ **
+ ** In JS we map all zPaths to Storage objects, and -journal files
+ ** are mapped to the storage for the main db (which is is exactly
+ ** what the mapping of "local-journal" -> "local" is doing).
+ */
+ const char *zKey = (0==sqlite3_strglob("*-journal", zPath))
+ ? "jrnl" : "sz";
+ *pResOut =
+ sqlite3KvvfsMethods.xRcrdRead(zPath, zKey, 0, 0)>0;
+#else
+ if( strcmp(zPath, "local-journal")==0 ){
+ *pResOut =
+ sqlite3KvvfsMethods.xRcrdRead("local", "jrnl", 0, 0)>0;
+ }else
+ if( strcmp(zPath, "session-journal")==0 ){
+ *pResOut =
+ sqlite3KvvfsMethods.xRcrdRead("session", "jrnl", 0, 0)>0;
+ }else
+ if( strcmp(zPath, "local")==0 ){
+ *pResOut =
+ sqlite3KvvfsMethods.xRcrdRead("local", "sz", 0, 0)>0;
+ }else
+ if( strcmp(zPath, "session")==0 ){
+ *pResOut =
+ sqlite3KvvfsMethods.xRcrdRead("session", "sz", 0, 0)>0;
+ }else
+ {
+ *pResOut = 0;
+ }
+ /*all current JS tests avoid triggering: assert( *pResOut == 0 ); */
+#endif
+ SQLITE_KV_LOG(("xAccess returns %d\n",*pResOut));
+ return SQLITE_OK;
+}
+
+/*
+** Populate buffer zOut with the full canonical pathname corresponding
+** to the pathname in zPath. zOut is guaranteed to point to a buffer
+** of at least (INST_MAX_PATHNAME+1) bytes.
+*/
+static int kvvfsFullPathname(
+ sqlite3_vfs *pVfs,
+ const char *zPath,
+ int nOut,
+ char *zOut
+){
+ size_t nPath;
+#ifdef SQLITE_OS_KV_ALWAYS_LOCAL
+ zPath = "local";
+#endif
+ nPath = strlen(zPath);
+ SQLITE_KV_LOG(("xFullPathname(\"%s\")\n", zPath));
+ if( nOut
+static int kvvfsCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *pTimeOut){
+ static const sqlite3_int64 unixEpoch = 24405875*(sqlite3_int64)8640000;
+ struct timeval sNow;
+ (void)gettimeofday(&sNow, 0); /* Cannot fail given valid arguments */
+ *pTimeOut = unixEpoch + 1000*(sqlite3_int64)sNow.tv_sec + sNow.tv_usec/1000;
+ return SQLITE_OK;
+}
+#endif /* SQLITE_OS_KV || SQLITE_OS_UNIX */
+
+#if SQLITE_OS_KV
+/*
+** This routine is called initialize the KV-vfs as the default VFS.
+*/
+SQLITE_API int sqlite3_os_init(void){
+ return sqlite3_vfs_register(&sqlite3OsKvvfsObject, 1);
+}
+SQLITE_API int sqlite3_os_end(void){
+ return SQLITE_OK;
+}
+#endif /* SQLITE_OS_KV */
+
+#if SQLITE_OS_UNIX && defined(SQLITE_OS_KV_OPTIONAL)
+SQLITE_PRIVATE int sqlite3KvvfsInit(void){
+ return sqlite3_vfs_register(&sqlite3OsKvvfsObject, 0);
+}
+#endif
+
+/************** End of os_kv.c ***********************************************/
/************** Begin file os_unix.c *****************************************/
/*
** 2004 May 22
@@ -32334,7 +40219,7 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
** This source file is organized into divisions where the logic for various
** subfunctions is contained within the appropriate division. PLEASE
** KEEP THE STRUCTURE OF THIS FILE INTACT. New code should be placed
-** in the correct division and should be clearly labeled.
+** in the correct division and should be clearly labelled.
**
** The layout of divisions is as follows:
**
@@ -32373,7 +40258,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__)
@@ -32384,7 +40269,7 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
#endif
/* Use pread() and pwrite() if they are available */
-#if defined(__APPLE__)
+#if defined(__APPLE__) || defined(__linux__)
# define HAVE_PREAD 1
# define HAVE_PWRITE 1
#endif
@@ -32399,15 +40284,16 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
/*
** standard include files.
*/
-#include
-#include
+#include /* amalgamator: keep */
+#include /* amalgamator: keep */
#include
#include
-#include
+#include /* amalgamator: keep */
/* #include */
-#include
+#include /* amalgamator: keep */
#include
-#if !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0
+#if (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0) \
+ && !defined(SQLITE_WASI)
# include
#endif
@@ -32417,13 +40303,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
@@ -32478,12 +40381,49 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
*/
#define SQLITE_MAX_SYMLINKS 100
+/*
+** Remove and stub certain info for WASI (WebAssembly System
+** Interface) builds.
+*/
+#ifdef SQLITE_WASI
+# undef HAVE_FCHMOD
+# undef HAVE_FCHOWN
+# undef HAVE_MREMAP
+# define HAVE_MREMAP 0
+# ifndef SQLITE_DEFAULT_UNIX_VFS
+# define SQLITE_DEFAULT_UNIX_VFS "unix-dotfile"
+ /* ^^^ should SQLITE_DEFAULT_UNIX_VFS be "unix-none"? */
+# endif
+# ifndef F_RDLCK
+# define F_RDLCK 0
+# define F_WRLCK 1
+# define F_UNLCK 2
+# if __LONG_MAX == 0x7fffffffL
+# define F_GETLK 12
+# define F_SETLK 13
+# define F_SETLKW 14
+# else
+# define F_GETLK 5
+# define F_SETLK 6
+# define F_SETLKW 7
+# endif
+# endif
+#else /* !SQLITE_WASI */
+# ifndef HAVE_FCHMOD
+# define HAVE_FCHMOD 1
+# endif
+#endif /* SQLITE_WASI */
+
+#ifdef SQLITE_WASI
+# define osGetpid(X) (pid_t)1
+#else
/* Always cast the getpid() return type for compatibility with
** kernel modules in VxWorks. */
-#define osGetpid(X) (pid_t)getpid()
+# define osGetpid(X) (pid_t)getpid()
+#endif
/*
-** 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))
@@ -32541,6 +40481,7 @@ struct unixFile {
#endif
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
unsigned iBusyTimeout; /* Wait this many millisec on locks */
+ int bBlockOnConnect; /* True to block for SHARED locks */
#endif
#if OS_VXWORKS
struct vxworksFileId *pId; /* Unique file ID */
@@ -32551,7 +40492,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 */
@@ -32560,7 +40501,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];
@@ -32579,7 +40520,7 @@ static pid_t randomnessPid = 0;
#define UNIXFILE_EXCL 0x01 /* Connections from one process only */
#define UNIXFILE_RDONLY 0x02 /* Connection is read only */
#define UNIXFILE_PERSIST_WAL 0x04 /* Persistent WAL mode */
-#ifndef SQLITE_DISABLE_DIRSYNC
+#if !defined(SQLITE_DISABLE_DIRSYNC) && !defined(_AIX)
# define UNIXFILE_DIRSYNC 0x08 /* Directory sync needed */
#else
# define UNIXFILE_DIRSYNC 0x00
@@ -32592,205 +40533,7 @@ static pid_t randomnessPid = 0;
/*
** Include code that is common to all os_*.c files
*/
-/************** Include os_common.h in the middle of os_unix.c ***************/
-/************** Begin file os_common.h ***************************************/
-/*
-** 2004 May 22
-**
-** The author disclaims copyright to this source code. In place of
-** a legal notice, here is a blessing:
-**
-** May you do good and not evil.
-** May you find forgiveness for yourself and forgive others.
-** May you share freely, never taking more than you give.
-**
-******************************************************************************
-**
-** This file contains macros and a little bit of code that is common to
-** all of the platform-specific files (os_*.c) and is #included into those
-** files.
-**
-** This file should be #included by the os_*.c files only. It is not a
-** general purpose header file.
-*/
-#ifndef _OS_COMMON_H_
-#define _OS_COMMON_H_
-
-/*
-** At least two bugs have slipped in because we changed the MEMORY_DEBUG
-** macro to SQLITE_DEBUG and some older makefiles have not yet made the
-** switch. The following code should catch this problem at compile-time.
-*/
-#ifdef MEMORY_DEBUG
-# error "The MEMORY_DEBUG macro is obsolete. Use SQLITE_DEBUG instead."
-#endif
-
-/*
-** Macros for performance tracing. Normally turned off. Only works
-** on i486 hardware.
-*/
-#ifdef SQLITE_PERFORMANCE_TRACE
-
-/*
-** hwtime.h contains inline assembler code for implementing
-** high-performance timing routines.
-*/
-/************** Include hwtime.h in the middle of os_common.h ****************/
-/************** Begin file hwtime.h ******************************************/
-/*
-** 2008 May 27
-**
-** The author disclaims copyright to this source code. In place of
-** a legal notice, here is a blessing:
-**
-** May you do good and not evil.
-** May you find forgiveness for yourself and forgive others.
-** May you share freely, never taking more than you give.
-**
-******************************************************************************
-**
-** This file contains inline asm code for retrieving "high-performance"
-** counters for x86 class CPUs.
-*/
-#ifndef SQLITE_HWTIME_H
-#define SQLITE_HWTIME_H
-
-/*
-** The following routine only works on pentium-class (or newer) processors.
-** It uses the RDTSC opcode to read the cycle count value out of the
-** processor and returns that value. This can be used for high-res
-** profiling.
-*/
-#if (defined(__GNUC__) || defined(_MSC_VER)) && \
- (defined(i386) || defined(__i386__) || defined(_M_IX86))
-
- #if defined(__GNUC__)
-
- __inline__ sqlite_uint64 sqlite3Hwtime(void){
- unsigned int lo, hi;
- __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
- return (sqlite_uint64)hi << 32 | lo;
- }
-
- #elif defined(_MSC_VER)
-
- __declspec(naked) __inline sqlite_uint64 __cdecl sqlite3Hwtime(void){
- __asm {
- rdtsc
- ret ; return value at EDX:EAX
- }
- }
-
- #endif
-
-#elif (defined(__GNUC__) && defined(__x86_64__))
-
- __inline__ sqlite_uint64 sqlite3Hwtime(void){
- unsigned long val;
- __asm__ __volatile__ ("rdtsc" : "=A" (val));
- return val;
- }
-
-#elif (defined(__GNUC__) && defined(__ppc__))
-
- __inline__ sqlite_uint64 sqlite3Hwtime(void){
- unsigned long long retval;
- unsigned long junk;
- __asm__ __volatile__ ("\n\
- 1: mftbu %1\n\
- mftb %L0\n\
- mftbu %0\n\
- cmpw %0,%1\n\
- bne 1b"
- : "=r" (retval), "=r" (junk));
- return retval;
- }
-
-#else
-
- #error Need implementation of sqlite3Hwtime() for your platform.
-
- /*
- ** To compile without implementing sqlite3Hwtime() for your platform,
- ** you can remove the above #error and use the following
- ** stub function. You will lose timing support for many
- ** of the debugging and testing utilities, but it should at
- ** least compile and run.
- */
-SQLITE_PRIVATE sqlite_uint64 sqlite3Hwtime(void){ return ((sqlite_uint64)0); }
-
-#endif
-
-#endif /* !defined(SQLITE_HWTIME_H) */
-
-/************** End of hwtime.h **********************************************/
-/************** Continuing where we left off in os_common.h ******************/
-
-static sqlite_uint64 g_start;
-static sqlite_uint64 g_elapsed;
-#define TIMER_START g_start=sqlite3Hwtime()
-#define TIMER_END g_elapsed=sqlite3Hwtime()-g_start
-#define TIMER_ELAPSED g_elapsed
-#else
-#define TIMER_START
-#define TIMER_END
-#define TIMER_ELAPSED ((sqlite_uint64)0)
-#endif
-
-/*
-** If we compile with the SQLITE_TEST macro set, then the following block
-** of code will give us the ability to simulate a disk I/O error. This
-** is used for testing the I/O recovery logic.
-*/
-#if defined(SQLITE_TEST)
-SQLITE_API extern int sqlite3_io_error_hit;
-SQLITE_API extern int sqlite3_io_error_hardhit;
-SQLITE_API extern int sqlite3_io_error_pending;
-SQLITE_API extern int sqlite3_io_error_persist;
-SQLITE_API extern int sqlite3_io_error_benign;
-SQLITE_API extern int sqlite3_diskfull_pending;
-SQLITE_API extern int sqlite3_diskfull;
-#define SimulateIOErrorBenign(X) sqlite3_io_error_benign=(X)
-#define SimulateIOError(CODE) \
- if( (sqlite3_io_error_persist && sqlite3_io_error_hit) \
- || sqlite3_io_error_pending-- == 1 ) \
- { local_ioerr(); CODE; }
-static void local_ioerr(){
- IOTRACE(("IOERR\n"));
- sqlite3_io_error_hit++;
- if( !sqlite3_io_error_benign ) sqlite3_io_error_hardhit++;
-}
-#define SimulateDiskfullError(CODE) \
- if( sqlite3_diskfull_pending ){ \
- if( sqlite3_diskfull_pending == 1 ){ \
- local_ioerr(); \
- sqlite3_diskfull = 1; \
- sqlite3_io_error_hit = 1; \
- CODE; \
- }else{ \
- sqlite3_diskfull_pending--; \
- } \
- }
-#else
-#define SimulateIOErrorBenign(X)
-#define SimulateIOError(A)
-#define SimulateDiskfullError(A)
-#endif /* defined(SQLITE_TEST) */
-
-/*
-** When testing, keep a count of the number of open files.
-*/
-#if defined(SQLITE_TEST)
-SQLITE_API extern int sqlite3_open_file_count;
-#define OpenCounter(X) sqlite3_open_file_count+=(X)
-#else
-#define OpenCounter(X)
-#endif /* defined(SQLITE_TEST) */
-
-#endif /* !defined(_OS_COMMON_H_) */
-
-/************** End of os_common.h *******************************************/
-/************** Continuing where we left off in os_unix.c ********************/
+/* #include "os_common.h" */
/*
** Define various macros that are missing from some systems.
@@ -32903,7 +40646,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
@@ -32950,8 +40693,13 @@ static struct unix_syscall {
#define osPwrite64 ((ssize_t(*)(int,const void*,size_t,off64_t))\
aSyscall[13].pCurrent)
+#if defined(HAVE_FCHMOD)
{ "fchmod", (sqlite3_syscall_ptr)fchmod, 0 },
#define osFchmod ((int(*)(int,mode_t))aSyscall[14].pCurrent)
+#else
+ { "fchmod", (sqlite3_syscall_ptr)0, 0 },
+#define osFchmod(FID,MODE) 0
+#endif
#if defined(HAVE_POSIX_FALLOCATE) && HAVE_POSIX_FALLOCATE
{ "fallocate", (sqlite3_syscall_ptr)posix_fallocate, 0 },
@@ -32986,14 +40734,16 @@ static struct unix_syscall {
#endif
#define osGeteuid ((uid_t(*)(void))aSyscall[21].pCurrent)
-#if !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0
+#if (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0) \
+ && !defined(SQLITE_WASI)
{ "mmap", (sqlite3_syscall_ptr)mmap, 0 },
#else
{ "mmap", (sqlite3_syscall_ptr)0, 0 },
#endif
#define osMmap ((void*(*)(void*,size_t,int,int,int,off_t))aSyscall[22].pCurrent)
-#if !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0
+#if (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0) \
+ && !defined(SQLITE_WASI)
{ "munmap", (sqlite3_syscall_ptr)munmap, 0 },
#else
{ "munmap", (sqlite3_syscall_ptr)0, 0 },
@@ -33031,17 +40781,131 @@ 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 */
+#if defined(SQLITE_DEBUG) || defined(SQLITE_ENABLE_FILESTAT)
+/*
+** Extract Posix Advisory Locking information about file description fd
+** from the /proc/PID/fdinfo/FD pseudo-file. Fill the string buffer a[16]
+** with characters to indicate which SQLite-relevant locks are held.
+** a[16] will be a 15-character zero-terminated string with the following
+** schema:
+**
+** AAA/B.DDD.DDDDD
+**
+** Each of character A-D will be "w" or "r" or "-" to indicate either a
+** write-lock, a read-lock, or no-lock, respectively. The "." and "/"
+** characters are delimiters intended to make the string more easily
+** readable by humans. Here are the meaning of the specific letters:
+**
+** AAA -> The main database locks. PENDING_BYTE, RESERVED_BYTE,
+** and SHARED_FIRST, respectively.
+**
+** B -> The deadman switch lock. Offset 128 of the -shm file.
+**
+** CCC -> WAL locks: WRITE, CKPT, RECOVER
+**
+** DDDDD -> WAL read-locks 0 through 5
+**
+** Note that elements before the "/" apply to the main database file and
+** elements after the "/" apply to the -shm file in WAL mode.
+**
+** Here is another way of thinking about the meaning of the result string:
+**
+** AAA/B.CCC.DDDDD
+** ||| | ||| \___/
+** PENDING--'|| | ||| `----- READ 0-5
+** RESERVED--'| | ||`---- RECOVER
+** SHARED ----' | |`----- CKPT
+** DMS ------' `------ WRITE
+**
+** Return SQLITE_OK on success and SQLITE_ERROR_UNABLE if the /proc
+** pseudo-filesystem is unavailable.
+*/
+static int unixPosixAdvisoryLocks(
+ int fd, /* The file descriptor to analyze */
+ char a[16] /* Write a text description of PALs here */
+){
+ int in;
+ ssize_t n;
+ char *p, *pNext, *x;
+ char z[2000];
+
+ /* 1 */
+ /* 012 4 678 01234 */
+ memcpy(a, "---/-.---.-----", 16);
+ sqlite3_snprintf(sizeof(z), z, "/proc/%d/fdinfo/%d", getpid(), fd);
+ in = osOpen(z, O_RDONLY, 0);
+ if( in<0 ){
+ return SQLITE_ERROR_UNABLE;
+ }
+ n = osRead(in, z, sizeof(z)-1);
+ osClose(in);
+ if( n<=0 ) return SQLITE_ERROR_UNABLE;
+ z[n] = 0;
+
+ /* We are looking for lines that begin with "lock:\t". Examples:
+ **
+ ** lock: 1: POSIX ADVISORY READ 494716 08:02:5277597 1073741826 1073742335
+ ** lock: 1: POSIX ADVISORY WRITE 494716 08:02:5282282 120 120
+ ** lock: 2: POSIX ADVISORY READ 494716 08:02:5282282 123 123
+ ** lock: 3: POSIX ADVISORY READ 494716 08:02:5282282 128 128
+ */
+ pNext = strstr(z, "lock:\t");
+ while( pNext ){
+ char cType = 0;
+ sqlite3_int64 iFirst, iLast;
+ p = pNext+6;
+ pNext = strstr(p, "lock:\t");
+ if( pNext ) pNext[-1] = 0;
+ if( (x = strstr(p, " READ "))!=0 ){
+ cType = 'r';
+ x += 6;
+ }else if( (x = strstr(p, " WRITE "))!=0 ){
+ cType = 'w';
+ x += 7;
+ }else{
+ continue;
+ }
+ x = strrchr(x, ' ');
+ if( x==0 ) continue;
+ iLast = strtoll(x+1, 0, 10);
+ *x = 0;
+ x = strrchr(p, ' ');
+ if( x==0 ) continue;
+ iFirst = strtoll(x+1, 0, 10);
+ if( iLast>=PENDING_BYTE ){
+ if( iFirst<=PENDING_BYTE && iLast>=PENDING_BYTE ) a[0] = cType;
+ if( iFirst<=PENDING_BYTE+1 && iLast>=PENDING_BYTE+1 ) a[1] = cType;
+ if( iFirst<=PENDING_BYTE+2 && iLast>=PENDING_BYTE+510 ) a[2] = cType;
+ }else if( iLast<=128 ){
+ if( iFirst<=128 && iLast>=128 ) a[4] = cType;
+ if( iFirst<=120 && iLast>=120 ) a[6] = cType;
+ if( iFirst<=121 && iLast>=121 ) a[7] = cType;
+ if( iFirst<=122 && iLast>=122 ) a[8] = cType;
+ if( iFirst<=123 && iLast>=123 ) a[10] = cType;
+ if( iFirst<=124 && iLast>=124 ) a[11] = cType;
+ if( iFirst<=125 && iLast>=125 ) a[12] = cType;
+ if( iFirst<=126 && iLast>=126 ) a[13] = cType;
+ if( iFirst<=127 && iLast>=127 ) a[14] = cType;
+ }
+ }
+ return SQLITE_OK;
+}
+#else
+# define unixPosixAdvisoryLocks(A,B) SQLITE_ERROR_UNABLE
+#endif /* SQLITE_DEBUG || SQLITE_ENABLE_FILESTAT */
+
/*
** On some systems, calls to fchown() will trigger a message in a security
** log if they come from non-root processes. So avoid calling fchown() if
@@ -33057,7 +40921,7 @@ static int robustFchown(int fd, uid_t uid, gid_t gid){
/*
** This is the xSetSystemCall() method of sqlite3_vfs for all of the
-** "unix" VFSes. Return SQLITE_OK opon successfully updating the
+** "unix" VFSes. Return SQLITE_OK upon successfully updating the
** system call pointer, or SQLITE_NOTFOUND if there is no configurable
** system call named zName.
*/
@@ -33140,7 +41004,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
@@ -33178,18 +41042,21 @@ static int robust_open(const char *z, int f, mode_t m){
break;
}
if( fd>=SQLITE_MINIMUM_FILE_DESCRIPTOR ) break;
+ if( (f & (O_EXCL|O_CREAT))==(O_EXCL|O_CREAT) ){
+ (void)osUnlink(z);
+ }
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);
}
@@ -33203,12 +41070,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
-** shared by multiple threads.
+** global mutex is used to protect the unixInodeInfo 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()
@@ -33330,7 +41196,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. */
@@ -33346,32 +41212,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;
}
}
@@ -33386,7 +41252,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.
**
@@ -33402,11 +41268,12 @@ struct vxworksFileId {
};
#if OS_VXWORKS
-/*
+/*
** All unique filenames are held on a linked list headed by this
** variable:
*/
static struct vxworksFileId *vxworksFileList = 0;
+static sqlite3_mutex *vxworksMutex = 0;
/*
** Simplify a filename into its canonical form
@@ -33472,14 +41339,14 @@ static struct vxworksFileId *vxworksFindFileId(const char *zAbsoluteName){
** If found, increment the reference count and return a pointer to
** the existing file ID.
*/
- unixEnterMutex();
+ sqlite3_mutex_enter(vxworksMutex);
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);
pCandidate->nRef++;
- unixLeaveMutex();
+ sqlite3_mutex_leave(vxworksMutex);
return pCandidate;
}
}
@@ -33489,7 +41356,7 @@ static struct vxworksFileId *vxworksFindFileId(const char *zAbsoluteName){
pNew->nName = n;
pNew->pNext = vxworksFileList;
vxworksFileList = pNew;
- unixLeaveMutex();
+ sqlite3_mutex_leave(vxworksMutex);
return pNew;
}
@@ -33498,7 +41365,7 @@ static struct vxworksFileId *vxworksFindFileId(const char *zAbsoluteName){
** the object when the reference count reaches zero.
*/
static void vxworksReleaseFileId(struct vxworksFileId *pId){
- unixEnterMutex();
+ sqlite3_mutex_enter(vxworksMutex);
assert( pId->nRef>0 );
pId->nRef--;
if( pId->nRef==0 ){
@@ -33508,7 +41375,7 @@ static void vxworksReleaseFileId(struct vxworksFileId *pId){
*pp = pId->pNext;
sqlite3_free(pId);
}
- unixLeaveMutex();
+ sqlite3_mutex_leave(vxworksMutex);
}
#endif /* OS_VXWORKS */
/*************** End of Unique File ID Utility Used By VxWorks ****************
@@ -33567,7 +41434,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.
**
@@ -33576,7 +41443,7 @@ static void vxworksReleaseFileId(struct vxworksFileId *pId){
** If you close a file descriptor that points to a file that has locks,
** all locks on that file that are owned by the current process are
** released. To work around this problem, each unixInodeInfo object
-** maintains a count of the number of pending locks on tha inode.
+** maintains a count of the number of pending locks on the inode.
** When an attempt is made to close an unixFile, if there are
** other unixFile open on the same inode that are holding locks, the call
** to close() the file descriptor is deferred until all of the locks clear.
@@ -33590,7 +41457,7 @@ static void vxworksReleaseFileId(struct vxworksFileId *pId){
** not posix compliant. Under LinuxThreads, a lock created by thread
** A cannot be modified or overridden by a different thread B.
** Only thread A can modify the lock. Locking behavior is correct
-** if the appliation uses the newer Native Posix Thread Library (NPTL)
+** if the application uses the newer Native Posix Thread Library (NPTL)
** on linux - with NPTL a lock created by thread A can override locks
** in thread B. But there is no way to know at compile-time which
** threading library is being used. So there is no way to know at
@@ -33600,7 +41467,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.
*/
@@ -33617,7 +41484,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; */
@@ -33705,7 +41572,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.
@@ -33723,7 +41590,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));
@@ -33731,18 +41598,22 @@ 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.
+ **
+ ** Forum post 3f13857fa4062301 reports that the Android SDK may use
+ ** int-type return, depending on its version.
*/
-#if defined(STRERROR_R_CHAR_P) || defined(__USE_GNU)
- zErr =
+#if (defined(STRERROR_R_CHAR_P) || defined(__USE_GNU)) \
+ && !defined(ANDROID) && !defined(__ANDROID__)
+ zErr =
# endif
strerror_r(iErrno, aErr, sizeof(aErr)-1);
@@ -33792,8 +41663,8 @@ static void storeLastErrno(unixFile *pFile, int error){
}
/*
-** Close all file descriptors accumuated in the unixInodeInfo->pUnused list.
-*/
+** Close all file descriptors accumulated in the unixInodeInfo->pUnused list.
+*/
static void closePendingFds(unixFile *pFile){
unixInodeInfo *pInode = pFile->pInode;
UnixUnusedFd *p;
@@ -33892,6 +41763,10 @@ static int findInodeInfo(
storeLastErrno(pFile, errno);
return SQLITE_IOERR;
}
+ if( fsync(fd) ){
+ storeLastErrno(pFile, errno);
+ return SQLITE_IOERR_FSYNC;
+ }
rc = osFstat(fd, &statbuf);
if( rc!=0 ){
storeLastErrno(pFile, errno);
@@ -33948,7 +41823,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
}
@@ -34029,7 +41904,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));
@@ -34037,6 +41912,9 @@ static int unixCheckReservedLock(sqlite3_file *id, int *pResOut){
return rc;
}
+/* Forward declaration*/
+static int unixSleep(sqlite3_vfs*,int);
+
/*
** Set a posix-advisory-lock.
**
@@ -34058,24 +41936,49 @@ static int osSetPosixAdvisoryLock(
struct flock *pLock, /* The description of the lock */
unixFile *pFile /* Structure holding timeout value */
){
- int rc = osFcntl(h,F_SETLK,pLock);
- while( rc<0 && pFile->iBusyTimeout>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);
+ int rc = 0;
+
+ if( pFile->iBusyTimeout==0 ){
+ /* unixFile->iBusyTimeout is set to 0. In this case, attempt a
+ ** non-blocking lock. */
rc = osFcntl(h,F_SETLK,pLock);
- pFile->iBusyTimeout--;
+ }else{
+ /* unixFile->iBusyTimeout is set to greater than zero. In this case,
+ ** attempt a blocking-lock with a unixFile->iBusyTimeout ms timeout.
+ **
+ ** On systems that support some kind of blocking file lock operation,
+ ** this block should be replaced by code to attempt a blocking lock
+ ** with a timeout of unixFile->iBusyTimeout ms. The code below is
+ ** placeholder code. If SQLITE_TEST is defined, the placeholder code
+ ** retries the lock once every 1ms until it succeeds or the timeout
+ ** is reached. Or, if SQLITE_TEST is not defined, the placeholder
+ ** code attempts a non-blocking lock and sets unixFile->iBusyTimeout
+ ** to 0. This causes the caller to return SQLITE_BUSY, instead of
+ ** SQLITE_BUSY_TIMEOUT to SQLite - as required by a VFS that does not
+ ** support blocking locks.
+ */
+#ifdef SQLITE_TEST
+ int tm = pFile->iBusyTimeout;
+ while( tm>0 ){
+ rc = osFcntl(h,F_SETLK,pLock);
+ if( rc==0 ) break;
+ unixSleep(0,1000);
+ tm--;
+ }
+#else
+ rc = osFcntl(h,F_SETLK,pLock);
+ pFile->iBusyTimeout = 0;
+#endif
+ /* End of code to replace with real blocking-locks code. */
}
+
return rc;
}
#endif /* SQLITE_ENABLE_SETLK_TIMEOUT */
/*
-** 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
@@ -34101,7 +42004,7 @@ static int unixFileLock(unixFile *pFile, struct flock *pLock){
if( (pFile->ctrlFlags & (UNIXFILE_EXCL|UNIXFILE_RDONLY))==UNIXFILE_EXCL ){
if( pInode->bProcessLock==0 ){
struct flock lock;
- assert( pInode->nLock==0 );
+ /* assert( pInode->nLock==0 ); <-- Not true if unix-excl READONLY used */
lock.l_whence = SEEK_SET;
lock.l_start = SHARED_FIRST;
lock.l_len = SHARED_SIZE;
@@ -34114,11 +42017,25 @@ static int unixFileLock(unixFile *pFile, struct flock *pLock){
rc = 0;
}
}else{
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+ if( pFile->bBlockOnConnect && pLock->l_type==F_RDLCK
+ && pLock->l_start==SHARED_FIRST && pLock->l_len==SHARED_SIZE
+ ){
+ rc = osFcntl(pFile->h, F_SETLKW, pLock);
+ }else
+#endif
rc = osSetPosixAdvisoryLock(pFile->h, pLock, pFile);
}
return rc;
}
+#if !defined(SQLITE_WASI) && !defined(SQLITE_OMIT_WAL)
+/* Forward reference */
+static int unixIsSharingShmNode(unixFile*);
+#else
+#define unixIsSharingShmNode(pFile) (0)
+#endif
+
/*
** Lock the file with the lock specified by parameter eFileLock - one
** of the following:
@@ -34136,7 +42053,7 @@ static int unixFileLock(unixFile *pFile, struct flock *pLock){
**
** UNLOCKED -> SHARED
** SHARED -> RESERVED
-** SHARED -> (PENDING) -> EXCLUSIVE
+** SHARED -> EXCLUSIVE
** RESERVED -> (PENDING) -> EXCLUSIVE
** PENDING -> EXCLUSIVE
**
@@ -34151,7 +42068,7 @@ static int unixLock(sqlite3_file *id, int eFileLock){
** slightly in order to be compatible with Windows95 systems simultaneously
** accessing the same database file, in case that is ever required.
**
- ** Symbols defined in os.h indentify the 'pending byte' and the 'reserved
+ ** Symbols defined in os.h identify the 'pending byte' and the 'reserved
** byte', each single bytes at well known offsets, and the 'shared byte
** range', a range of 510 bytes at a well known offset.
**
@@ -34159,7 +42076,7 @@ static int unixLock(sqlite3_file *id, int eFileLock){
** byte'. If this is successful, 'shared byte range' is read-locked
** and the lock on the 'pending byte' released. (Legacy note: When
** SQLite was first developed, Windows95 systems were still very common,
- ** and Widnows95 lacks a shared-lock capability. So on Windows95, a
+ ** and Windows95 lacks a shared-lock capability. So on Windows95, a
** single randomly selected by from the 'shared byte range' is locked.
** Windows95 is now pretty much extinct, but this work-around for the
** lack of shared-locks on Windows95 lives on, for backwards
@@ -34167,21 +42084,22 @@ 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
- ** on the 'pending byte'. This ensures that no new SHARED locks can be
- ** obtained, but existing SHARED locks are allowed to persist. A process
- ** does not have to obtain a RESERVED lock on the way to a PENDING lock.
- ** This property is used by the algorithm for rolling back a journal file
- ** after a crash.
+ ** An EXCLUSIVE lock may only be requested after either a SHARED or
+ ** RESERVED lock is held. An EXCLUSIVE lock is implemented by obtaining
+ ** a write-lock on the entire 'shared byte range'. Since all other locks
+ ** require a read-lock on one of the bytes within this range, this ensures
+ ** that no other locks are held on the database.
**
- ** An EXCLUSIVE lock, obtained after a PENDING lock is held, is
- ** implemented by obtaining a write-lock on the entire 'shared byte
- ** range'. Since all other locks require a read-lock on one of the bytes
- ** within this range, this ensures that no other locks are held on the
- ** database.
+ ** If a process that holds a RESERVED lock requests an EXCLUSIVE, then
+ ** a PENDING lock is obtained first. A PENDING lock is implemented by
+ ** obtaining a write-lock on the 'pending byte'. This ensures that no new
+ ** SHARED locks can be obtained, but existing SHARED locks are allowed to
+ ** persist. If the call to this function fails to obtain the EXCLUSIVE
+ ** lock in this case, it holds the PENDING lock instead. The client may
+ ** then re-attempt the EXCLUSIVE lock later on, after existing SHARED
+ ** locks have cleared.
*/
int rc = SQLITE_OK;
unixFile *pFile = (unixFile*)id;
@@ -34207,7 +42125,7 @@ static int unixLock(sqlite3_file *id, int eFileLock){
/* Make sure the locking sequence is correct.
** (1) We never move from unlocked to anything higher than shared lock.
- ** (2) SQLite never explicitly requests a pendig lock.
+ ** (2) SQLite never explicitly requests a pending lock.
** (3) A shared lock is always held when a reserve lock is requested.
*/
assert( pFile->eFileLock!=NO_LOCK || eFileLock==SHARED_LOCK );
@@ -34222,7 +42140,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;
@@ -34233,7 +42151,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 );
@@ -34251,8 +42169,8 @@ static int unixLock(sqlite3_file *id, int eFileLock){
*/
lock.l_len = 1L;
lock.l_whence = SEEK_SET;
- if( eFileLock==SHARED_LOCK
- || (eFileLock==EXCLUSIVE_LOCK && pFile->eFileLockeFileLock==RESERVED_LOCK)
){
lock.l_type = (eFileLock==SHARED_LOCK?F_RDLCK:F_WRLCK);
lock.l_start = PENDING_BYTE;
@@ -34263,6 +42181,9 @@ static int unixLock(sqlite3_file *id, int eFileLock){
storeLastErrno(pFile, tErrno);
}
goto end_lock;
+ }else if( eFileLock==EXCLUSIVE_LOCK ){
+ pFile->eFileLock = PENDING_LOCK;
+ pInode->eFileLock = PENDING_LOCK;
}
}
@@ -34290,7 +42211,7 @@ static int unixLock(sqlite3_file *id, int eFileLock){
if( unixFileLock(pFile, &lock) && rc==SQLITE_OK ){
/* This could happen with a network mount */
tErrno = errno;
- rc = SQLITE_IOERR_UNLOCK;
+ rc = SQLITE_IOERR_UNLOCK;
}
if( rc ){
@@ -34307,6 +42228,14 @@ static int unixLock(sqlite3_file *id, int eFileLock){
/* We are trying for an exclusive lock but another thread in this
** same process is still holding a shared lock. */
rc = SQLITE_BUSY;
+ }else if( unixIsSharingShmNode(pFile) ){
+ /* We are in WAL mode and attempting to delete the SHM and WAL
+ ** files due to closing the connection or changing out of WAL mode,
+ ** but another process still holds locks on the SHM file, thus
+ ** indicating that database locks have been broken, perhaps due
+ ** to a rogue close(open(dbFile)) or similar.
+ */
+ rc = SQLITE_BUSY;
}else{
/* The request was for a RESERVED or EXCLUSIVE lock. It is
** assumed that there is a SHARED or greater lock on the file
@@ -34332,7 +42261,7 @@ static int unixLock(sqlite3_file *id, int eFileLock){
}
}
}
-
+
#ifdef SQLITE_DEBUG
/* Set up the transaction-counter change checking flags when
@@ -34350,18 +42279,14 @@ static int unixLock(sqlite3_file *id, int eFileLock){
}
#endif
-
if( rc==SQLITE_OK ){
pFile->eFileLock = eFileLock;
pInode->eFileLock = eFileLock;
- }else if( eFileLock==EXCLUSIVE_LOCK ){
- pFile->eFileLock = PENDING_LOCK;
- pInode->eFileLock = PENDING_LOCK;
}
end_lock:
sqlite3_mutex_leave(pInode->pLockMutex);
- 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;
}
@@ -34386,11 +42311,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){
@@ -34428,7 +42353,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]
@@ -34444,7 +42369,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;
@@ -34486,11 +42411,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;
@@ -34566,7 +42491,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.
@@ -34629,13 +42554,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;
@@ -34715,26 +42641,22 @@ static int nolockClose(sqlite3_file *id) {
/*
** This routine checks if there is a RESERVED lock held on the specified
-** file by this or any other process. If such a lock is held, set *pResOut
-** to a non-zero value otherwise *pResOut is set to zero. The return value
-** is set to SQLITE_OK unless an I/O error occurs during lock checking.
-**
-** In dotfile locking, either a lock exists or it does not. So in this
-** variation of CheckReservedLock(), *pResOut is set to true if any lock
-** is held on the file and false if the file is unlocked.
+** file by this or any other process. If the caller holds a SHARED
+** or greater lock when it is called, then it is assumed that no other
+** client may hold RESERVED. Or, if the caller holds no lock, then it
+** is assumed another client holds RESERVED if the lock-file exists.
*/
static int dotlockCheckReservedLock(sqlite3_file *id, int *pResOut) {
- int rc = SQLITE_OK;
- int reserved = 0;
unixFile *pFile = (unixFile*)id;
-
SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
-
- assert( pFile );
- reserved = osAccess((const char*)pFile->lockingContext, 0)==0;
- OSTRACE(("TEST WR-LOCK %d %d %d (dotlock)\n", pFile->h, rc, reserved));
- *pResOut = reserved;
- return rc;
+
+ if( pFile->eFileLock>=SHARED_LOCK ){
+ *pResOut = 0;
+ }else{
+ *pResOut = osAccess((const char*)pFile->lockingContext, 0)==0;
+ }
+ OSTRACE(("TEST WR-LOCK %d %d %d (dotlock)\n", pFile->h, 0, *pResOut));
+ return SQLITE_OK;
}
/*
@@ -34783,7 +42705,7 @@ static int dotlockLock(sqlite3_file *id, int eFileLock) {
#endif
return SQLITE_OK;
}
-
+
/* grab an exclusive lock */
rc = osMkdir(zLockFile, 0777);
if( rc<0 ){
@@ -34798,8 +42720,8 @@ static int dotlockLock(sqlite3_file *id, int eFileLock) {
}
}
return rc;
- }
-
+ }
+
/* got it, set the type and return ok */
pFile->eFileLock = eFileLock;
return rc;
@@ -34823,7 +42745,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;
@@ -34836,7 +42758,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);
@@ -34848,7 +42770,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;
@@ -34895,7 +42817,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
@@ -34904,54 +42826,33 @@ static int robust_flock(int fd, int op){
** is set to SQLITE_OK unless an I/O error occurs during lock checking.
*/
static int flockCheckReservedLock(sqlite3_file *id, int *pResOut){
- int rc = SQLITE_OK;
- int reserved = 0;
+#ifdef SQLITE_DEBUG
unixFile *pFile = (unixFile*)id;
-
+#else
+ UNUSED_PARAMETER(id);
+#endif
+
SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
-
+
assert( pFile );
-
- /* Check if a thread in this process holds such a lock */
- if( pFile->eFileLock>SHARED_LOCK ){
- reserved = 1;
- }
-
- /* Otherwise see if some other process holds it. */
- if( !reserved ){
- /* attempt to get the lock */
- int lrc = robust_flock(pFile->h, LOCK_EX | LOCK_NB);
- if( !lrc ){
- /* got the lock, unlock it */
- lrc = robust_flock(pFile->h, LOCK_UN);
- if ( lrc ) {
- int tErrno = errno;
- /* unlock failed with an error */
- lrc = SQLITE_IOERR_UNLOCK;
- storeLastErrno(pFile, tErrno);
- rc = lrc;
- }
- } else {
- int tErrno = errno;
- reserved = 1;
- /* someone else might have it reserved */
- lrc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
- if( IS_LOCK_ERROR(lrc) ){
- storeLastErrno(pFile, tErrno);
- rc = lrc;
- }
- }
- }
- OSTRACE(("TEST WR-LOCK %d %d %d (flock)\n", pFile->h, rc, reserved));
+ assert( pFile->eFileLock<=SHARED_LOCK );
-#ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS
- if( (rc & 0xff) == SQLITE_IOERR ){
- rc = SQLITE_OK;
- reserved=1;
- }
-#endif /* SQLITE_IGNORE_FLOCK_LOCK_ERRORS */
- *pResOut = reserved;
- return rc;
+ /* The flock VFS only ever takes exclusive locks (see function flockLock).
+ ** Therefore, if this connection is holding any lock at all, no other
+ ** connection may be holding a RESERVED lock. So set *pResOut to 0
+ ** in this case.
+ **
+ ** Or, this connection may be holding no lock. In that case, set *pResOut to
+ ** 0 as well. The caller will then attempt to take an EXCLUSIVE lock on the
+ ** db in order to roll the hot journal back. If there is another connection
+ ** holding a lock, that attempt will fail and an SQLITE_BUSY returned to
+ ** the user. With other VFS, we try to avoid this, in order to allow a reader
+ ** to proceed while a writer is preparing its transaction. But that won't
+ ** work with the flock VFS - as it always takes EXCLUSIVE locks - so it is
+ ** not a problem in this case. */
+ *pResOut = 0;
+
+ return SQLITE_OK;
}
/*
@@ -34989,15 +42890,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 */
@@ -35009,7 +42910,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 ){
@@ -35029,23 +42930,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
@@ -35096,14 +42997,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;
@@ -35162,14 +43063,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;
@@ -35199,18 +43100,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;
@@ -35218,7 +43119,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;
@@ -35284,7 +43185,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(
@@ -35296,14 +43197,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);
@@ -35338,9 +43239,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 ){
@@ -35352,12 +43253,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 */
@@ -35370,10 +43271,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;
}
@@ -35407,7 +43308,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),
@@ -35425,13 +43326,13 @@ static int afpLock(sqlite3_file *id, int eFileLock){
/* Make sure the locking sequence is correct
** (1) We never move from unlocked to anything higher than shared lock.
- ** (2) SQLite never explicitly requests a pendig lock.
+ ** (2) SQLite never explicitly requests a pending lock.
** (3) A shared lock is always held when a reserve lock is requested.
*/
assert( pFile->eFileLock!=NO_LOCK || eFileLock==SHARED_LOCK );
assert( eFileLock!=PENDING_LOCK );
assert( eFileLock!=RESERVED_LOCK || pFile->eFileLock==SHARED_LOCK );
-
+
/* This mutex is needed because pFile->pInode is shared across threads
*/
pInode = pFile->pInode;
@@ -35440,18 +43341,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 );
@@ -35461,12 +43362,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;
@@ -35534,34 +43435,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,
+ /* now attempt to get the exclusive lock range */
+ 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;
@@ -35569,10 +43470,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;
}
@@ -35590,9 +43491,6 @@ static int afpUnlock(sqlite3_file *id, int eFileLock) {
unixInodeInfo *pInode;
afpLockingContext *context = (afpLockingContext *) pFile->lockingContext;
int skipShared = 0;
-#ifdef SQLITE_TEST
- int h = pFile->h;
-#endif
assert( pFile );
OSTRACE(("UNLOCK %d %d was %d(%d,%d) pid=%d (afp)\n", pFile->h, eFileLock,
@@ -35608,10 +43506,7 @@ static int afpUnlock(sqlite3_file *id, int eFileLock) {
assert( pInode->nShared!=0 );
if( pFile->eFileLock>SHARED_LOCK ){
assert( pInode->eFileLock==pFile->eFileLock );
- SimulateIOErrorBenign(1);
- SimulateIOError( h=(-1) )
- SimulateIOErrorBenign(0);
-
+
#ifdef SQLITE_DEBUG
/* When reducing a lock such that other processes can start
** reading the database file again, make sure that the
@@ -35626,7 +43521,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) ){
@@ -35639,11 +43534,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)){
@@ -35659,9 +43554,6 @@ static int afpUnlock(sqlite3_file *id, int eFileLock) {
unsigned long long sharedLockByte = SHARED_FIRST+pInode->sharedByte;
pInode->nShared--;
if( pInode->nShared==0 ){
- SimulateIOErrorBenign(1);
- SimulateIOError( h=(-1) )
- SimulateIOErrorBenign(0);
if( !skipShared ){
rc = afpSetLock(context->dbPath, pFile, sharedLockByte, 1, 0);
}
@@ -35676,7 +43568,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;
@@ -35685,7 +43577,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;
@@ -35743,7 +43635,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 **********************
******************************************************************************/
@@ -35751,7 +43643,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
@@ -35759,15 +43651,9 @@ 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
-** be necessary to define _XOPEN_SOURCE to be 500. This varies from
-** one system to another. Since SQLite does not define USE_PREAD
-** in any form by default, we will not attempt to define _XOPEN_SOURCE.
-** See tickets #2741 and #2681.
-**
** To avoid stomping the errno value on a failed read the lastErrno value
** is set before returning.
*/
@@ -35821,8 +43707,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
){
@@ -35832,17 +43718,17 @@ 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
#if SQLITE_MAX_MMAP_SIZE>0
- /* Deal with as much of this read request as possible by transfering
+ /* Deal with as much of this read request as possible by transferring
** data from the memory mapping using memcpy(). */
if( offsetmmapSize ){
if( offset+amt <= pFile->mmapSize ){
@@ -35862,7 +43748,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 */
@@ -35875,7 +43778,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).
*/
@@ -35935,22 +43838,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
@@ -35977,7 +43880,7 @@ static int unixWrite(
#endif
#if defined(SQLITE_MMAP_READWRITE) && SQLITE_MAX_MMAP_SIZE>0
- /* Deal with as much of this write request as possible by transfering
+ /* Deal with as much of this write request as possible by transferring
** data from the memory mapping using memcpy(). */
if( offsetmmapSize ){
if( offset+amt <= pFile->mmapSize ){
@@ -35992,7 +43895,7 @@ static int unixWrite(
}
}
#endif
-
+
while( (wrote = seekAndWrite(pFile, offset, pBuf, amt))0 ){
amt -= wrote;
offset += wrote;
@@ -36058,8 +43961,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
@@ -36073,7 +43976,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
@@ -36087,7 +43990,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.
*/
@@ -36099,7 +44002,7 @@ static int full_fsync(int fd, int fullSync, int dataOnly){
/* If we compiled with the SQLITE_NO_SYNC flag, then syncing is a
** no-op. But go ahead and call fstat() to validate the file
** descriptor as we need a method to provoke a failure during
- ** coverate testing.
+ ** coverage testing.
*/
#ifdef SQLITE_NO_SYNC
{
@@ -36113,11 +44016,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);
@@ -36127,7 +44030,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 ){
@@ -36288,7 +44191,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;
@@ -36334,8 +44237,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.
@@ -36344,7 +44247,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;
}
@@ -36353,8 +44256,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{
@@ -36362,7 +44265,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.
@@ -36421,6 +44324,13 @@ static void unixModeBit(unixFile *pFile, unsigned char mask, int *pArg){
/* Forward declaration */
static int unixGetTempname(int nBuf, char *zBuf);
+#if !defined(SQLITE_WASI) && !defined(SQLITE_OMIT_WAL)
+ static int unixFcntlExternalReader(unixFile*, int*);
+#endif
+#if defined(SQLITE_DEBUG) || defined(SQLITE_ENABLE_FILESTAT)
+ static void unixDescribeShm(sqlite3_str*,unixShm*);
+#endif
+
/*
** Information and control of an open file handle.
@@ -36443,6 +44353,11 @@ static int unixFileControl(sqlite3_file *id, int op, void *pArg){
}
#endif /* __linux__ && SQLITE_ENABLE_BATCH_ATOMIC_WRITE */
+ case SQLITE_FCNTL_NULL_IO: {
+ osClose(pFile->h);
+ pFile->h = -1;
+ return SQLITE_OK;
+ }
case SQLITE_FCNTL_LOCKSTATE: {
*(int*)pArg = pFile->eFileLock;
return SQLITE_OK;
@@ -36488,10 +44403,24 @@ static int unixFileControl(sqlite3_file *id, int op, void *pArg){
}
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
case SQLITE_FCNTL_LOCK_TIMEOUT: {
- pFile->iBusyTimeout = *(int*)pArg;
+ int iOld = pFile->iBusyTimeout;
+ int iNew = *(int*)pArg;
+#if SQLITE_ENABLE_SETLK_TIMEOUT==1
+ pFile->iBusyTimeout = iNew<0 ? 0x7FFFFFFF : (unsigned)iNew;
+#elif SQLITE_ENABLE_SETLK_TIMEOUT==2
+ pFile->iBusyTimeout = !!(*(int*)pArg);
+#else
+# error "SQLITE_ENABLE_SETLK_TIMEOUT must be set to 1 or 2"
+#endif
+ *(int*)pArg = iOld;
return SQLITE_OK;
}
-#endif
+ case SQLITE_FCNTL_BLOCK_ON_CONNECT: {
+ int iNew = *(int*)pArg;
+ pFile->bBlockOnConnect = iNew;
+ return SQLITE_OK;
+ }
+#endif /* SQLITE_ENABLE_SETLK_TIMEOUT */
#if SQLITE_MAX_MMAP_SIZE>0
case SQLITE_FCNTL_MMAP_SIZE: {
i64 newLimit = *(i64*)pArg;
@@ -36535,15 +44464,84 @@ 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: {
+#if !defined(SQLITE_WASI) && !defined(SQLITE_OMIT_WAL)
+ return unixFcntlExternalReader((unixFile*)id, (int*)pArg);
+#else
+ *(int*)pArg = 0;
+ return SQLITE_OK;
+#endif
+ }
+
+#if defined(SQLITE_DEBUG) || defined(SQLITE_ENABLE_FILESTAT)
+ case SQLITE_FCNTL_FILESTAT: {
+ sqlite3_str *pStr = (sqlite3_str*)pArg;
+ char aLck[16];
+ unixInodeInfo *pInode;
+ static const char *azLock[] = { "SHARED", "RESERVED",
+ "PENDING", "EXCLUSIVE" };
+ sqlite3_str_appendf(pStr, "{\"h\":%d", pFile->h);
+ sqlite3_str_appendf(pStr, ",\"vfs\":\"%s\"", pFile->pVfs->zName);
+ if( pFile->eFileLock ){
+ sqlite3_str_appendf(pStr, ",\"eFileLock\":\"%s\"",
+ azLock[pFile->eFileLock-1]);
+ if( unixPosixAdvisoryLocks(pFile->h, aLck)==SQLITE_OK ){
+ sqlite3_str_appendf(pStr, ",\"pal\":\"%s\"", aLck);
+ }
+ }
+ unixEnterMutex();
+ if( pFile->pShm ){
+ sqlite3_str_appendall(pStr, ",\"shm\":");
+ unixDescribeShm(pStr, pFile->pShm);
+ }
+#if SQLITE_MAX_MMAP_SIZE>0
+ if( pFile->mmapSize ){
+ sqlite3_str_appendf(pStr, ",\"mmapSize\":%lld", pFile->mmapSize);
+ sqlite3_str_appendf(pStr, ",\"nFetchOut\":%d", pFile->nFetchOut);
+ }
+#endif
+ if( (pInode = pFile->pInode)!=0 ){
+ sqlite3_str_appendf(pStr, ",\"inode\":{\"nRef\":%d",pInode->nRef);
+ sqlite3_mutex_enter(pInode->pLockMutex);
+ sqlite3_str_appendf(pStr, ",\"nShared\":%d", pInode->nShared);
+ if( pInode->eFileLock ){
+ sqlite3_str_appendf(pStr, ",\"eFileLock\":\"%s\"",
+ azLock[pInode->eFileLock-1]);
+ }
+ if( pInode->pUnused ){
+ char cSep = '[';
+ UnixUnusedFd *pUFd = pFile->pInode->pUnused;
+ sqlite3_str_appendall(pStr, ",\"unusedFd\":");
+ while( pUFd ){
+ sqlite3_str_appendf(pStr, "%c{\"fd\":%d,\"flags\":%d",
+ cSep, pUFd->fd, pUFd->flags);
+ cSep = ',';
+ if( unixPosixAdvisoryLocks(pUFd->fd, aLck)==SQLITE_OK ){
+ sqlite3_str_appendf(pStr, ",\"pal\":\"%s\"", aLck);
+ }
+ sqlite3_str_append(pStr, "}", 1);
+ pUFd = pUFd->pNext;
+ }
+ sqlite3_str_append(pStr, "]", 1);
+ }
+ sqlite3_mutex_leave(pInode->pLockMutex);
+ sqlite3_str_append(pStr, "}", 1);
+ }
+ unixLeaveMutex();
+ sqlite3_str_append(pStr, "}", 1);
+ return SQLITE_OK;
+ }
+#endif /* SQLITE_DEBUG || SQLITE_ENABLE_FILESTAT */
}
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.
@@ -36567,6 +44565,7 @@ static void setDeviceCharacteristics(unixFile *pFd){
if( pFd->ctrlFlags & UNIXFILE_PSOW ){
pFd->deviceCharacteristics |= SQLITE_IOCAP_POWERSAFE_OVERWRITE;
}
+ pFd->deviceCharacteristics |= SQLITE_IOCAP_SUBPAGE_READ;
pFd->sectorSize = SQLITE_DEFAULT_SECTOR_SIZE;
}
@@ -36577,7 +44576,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;
@@ -36617,7 +44616,7 @@ static void setDeviceCharacteristics(unixFile *pFile){
pFile->sectorSize = fsInfo.f_bsize;
pFile->deviceCharacteristics =
/* full bitset of atomics from max sector size and smaller */
- ((pFile->sectorSize / 512 * SQLITE_IOCAP_ATOMIC512) << 1) - 2 |
+ (((pFile->sectorSize / 512 * SQLITE_IOCAP_ATOMIC512) << 1) - 2) |
SQLITE_IOCAP_SEQUENTIAL | /* The ram filesystem has no write behind
** so it is ordered */
0;
@@ -36625,7 +44624,7 @@ static void setDeviceCharacteristics(unixFile *pFile){
pFile->sectorSize = fsInfo.f_bsize;
pFile->deviceCharacteristics =
/* full bitset of atomics from max sector size and smaller */
- ((pFile->sectorSize / 512 * SQLITE_IOCAP_ATOMIC512) << 1) - 2 |
+ (((pFile->sectorSize / 512 * SQLITE_IOCAP_ATOMIC512) << 1) - 2) |
SQLITE_IOCAP_SEQUENTIAL | /* The ram filesystem has no write behind
** so it is ordered */
0;
@@ -36686,7 +44685,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){
@@ -36701,10 +44700,10 @@ static int unixGetpagesize(void){
#endif /* !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0 */
-#ifndef SQLITE_OMIT_WAL
+#if !defined(SQLITE_WASI) && !defined(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
@@ -36724,13 +44723,32 @@ static int unixGetpagesize(void){
** nRef
**
** The following fields are read-only after the object is created:
-**
+**
** hShm
** zFilename
**
** Either unixShmNode.pShmMutex must be held or unixShmNode.nRef==0 and
** unixMutexHeld() is true when reading or writing any other field
** in this structure.
+**
+** aLock[SQLITE_SHM_NLOCK]:
+** This array records the various locks held by clients on each of the
+** SQLITE_SHM_NLOCK slots. If the aLock[] entry is set to 0, then no
+** locks are held by the process on this slot. If it is set to -1, then
+** some client holds an EXCLUSIVE lock on the locking slot. If the aLock[]
+** value is set to a positive value, then it is the number of shared
+** locks currently held on the slot.
+**
+** aMutex[SQLITE_SHM_NLOCK]:
+** Normally, when SQLITE_ENABLE_SETLK_TIMEOUT is not defined, mutex
+** pShmMutex is used to protect the aLock[] array and the right to
+** call fcntl() on unixShmNode.hShm to obtain or release locks.
+**
+** If SQLITE_ENABLE_SETLK_TIMEOUT is defined though, we use an array
+** of mutexes - one for each locking slot. To read or write locking
+** slot aLock[iSlot], the caller must hold the corresponding mutex
+** aMutex[iSlot]. Similarly, to call fcntl() to obtain or release a
+** lock corresponding to slot iSlot, mutex aMutex[iSlot] must be held.
*/
struct unixShmNode {
unixInodeInfo *pInode; /* unixInodeInfo that owns this SHM node */
@@ -36744,9 +44762,11 @@ 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 */
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+ sqlite3_mutex *aMutex[SQLITE_SHM_NLOCK];
+#endif
+ 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 */
u8 nextShmId; /* Next available unixShm.id value */
#endif
};
@@ -36779,6 +44799,98 @@ 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 */
+#if defined(SQLITE_DEBUG) || defined(SQLITE_ENABLE_FILESTAT)
+/*
+** Describe the pShm object using JSON. Used for diagnostics only.
+*/
+static void unixDescribeShm(sqlite3_str *pStr, unixShm *pShm){
+ unixShmNode *pNode = pShm->pShmNode;
+ char aLck[16];
+ sqlite3_str_appendf(pStr, "{\"h\":%d", pNode->hShm);
+ assert( unixMutexHeld() );
+ sqlite3_str_appendf(pStr, ",\"nRef\":%d", pNode->nRef);
+ sqlite3_str_appendf(pStr, ",\"id\":%d", pShm->id);
+ sqlite3_str_appendf(pStr, ",\"sharedMask\":%d", pShm->sharedMask);
+ sqlite3_str_appendf(pStr, ",\"exclMask\":%d", pShm->exclMask);
+ if( unixPosixAdvisoryLocks(pNode->hShm, aLck)==SQLITE_OK ){
+ sqlite3_str_appendf(pStr, ",\"pal\":\"%s\"", aLck);
+ }
+ sqlite3_str_append(pStr, "}", 1);
+}
+#endif /* SQLITE_DEBUG || SQLITE_ENABLE_FILESTAT */
+
+/*
+** 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;
+}
+
+/*
+** If pFile has a -shm file open and it is sharing that file with some
+** other connection, either in the same process or in a separate process,
+** then return true. Return false if either pFile does not have a -shm
+** file open or if it is the only connection to that -shm file across the
+** entire system.
+**
+** This routine is not required for correct operation. It can always return
+** false and SQLite will continue to operate according to spec. However,
+** when this routine does its job, it adds extra robustness in cases
+** where database file locks have been erroneously deleted in a WAL-mode
+** database by doing close(open(DATABASE_PATHNAME)) or similar.
+**
+** With false negatives, SQLite still operates to spec, though with less
+** robustness. With false positives, the last database connection on a
+** WAL-mode database will fail to unlink the -wal and -shm files, which
+** is annoying but harmless. False positives will also prevent a database
+** connection from running "PRAGMA journal_mode=DELETE" in order to take
+** the database out of WAL mode, which is perhaps more serious, but is
+** still not a disaster.
+*/
+static int unixIsSharingShmNode(unixFile *pFile){
+ unixShmNode *pShmNode;
+ struct flock lock;
+ if( pFile->pShm==0 ) return 0;
+ if( pFile->ctrlFlags & UNIXFILE_EXCL ) return 0;
+ pShmNode = pFile->pShm->pShmNode;
+#if SQLITE_ATOMIC_INTRINSICS
+ assert( AtomicLoad(&pShmNode->nRef)==1 );
+#endif
+ memset(&lock, 0, sizeof(lock));
+ lock.l_whence = SEEK_SET;
+ lock.l_start = UNIX_SHM_DMS;
+ lock.l_len = 1;
+ lock.l_type = F_WRLCK;
+ osFcntl(pShmNode->hShm, F_GETLK, &lock);
+ return (lock.l_type!=F_UNLCK);
+}
+
/*
** Apply posix advisory locks for all bytes from ofst through ofst+n-1.
**
@@ -36795,63 +44907,79 @@ static int unixShmSystemLock(
struct flock f; /* The posix advisory locking structure */
int rc = SQLITE_OK; /* Result code form fcntl() */
- /* Access to the unixShmNode object is serialized by the caller */
pShmNode = pFile->pInode->pShmNode;
- assert( pShmNode->nRef==0 || sqlite3_mutex_held(pShmNode->pShmMutex) );
- assert( pShmNode->nRef>0 || unixMutexHeld() );
+
+ /* Assert that the parameters are within expected range and that the
+ ** correct mutex or mutexes are held. */
+ assert( pShmNode->nRef>=0 );
+ assert( (ofst==UNIX_SHM_DMS && n==1)
+ || (ofst>=UNIX_SHM_BASE && ofst+n<=(UNIX_SHM_BASE+SQLITE_SHM_NLOCK))
+ );
+ if( ofst==UNIX_SHM_DMS ){
+ assert( pShmNode->nRef>0 || unixMutexHeld() );
+ assert( pShmNode->nRef==0 || sqlite3_mutex_held(pShmNode->pShmMutex) );
+ }else{
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+ int ii;
+ for(ii=ofst-UNIX_SHM_BASE; iiaMutex[ii]) );
+ }
+#else
+ assert( sqlite3_mutex_held(pShmNode->pShmMutex) );
+ assert( pShmNode->nRef>0 );
+#endif
+ }
/* Shared locks never span more than one byte */
assert( n==1 || lockType!=F_RDLCK );
/* Locks are within range */
assert( n>=1 && n<=SQLITE_SHM_NLOCK );
+ assert( ofst>=UNIX_SHM_BASE && ofst<=UNIX_SHM_DMS );
+ assert( ofst+n-1<=UNIX_SHM_DMS );
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->hShm, &f, pFile);
- rc = (rc!=(-1)) ? SQLITE_OK : SQLITE_BUSY;
+ res = osSetPosixAdvisoryLock(pShmNode->hShm, &f, pFile);
+ if( res==-1 ){
+#if defined(SQLITE_ENABLE_SETLK_TIMEOUT) && SQLITE_ENABLE_SETLK_TIMEOUT==1
+ rc = (pFile->iBusyTimeout ? SQLITE_BUSY_TIMEOUT : SQLITE_BUSY);
+#else
+ rc = SQLITE_BUSY;
+#endif
+ }
}
- /* Update the global lock state and do debug tracing */
+ /* Do debug tracing */
#ifdef SQLITE_DEBUG
- { u16 mask;
OSTRACE(("SHM-LOCK "));
- mask = ofst>31 ? 0xffff : (1<<(ofst+n)) - (1<exclMask &= ~mask;
- pShmNode->sharedMask &= ~mask;
+ OSTRACE(("unlock %d..%d ok\n", ofst, ofst+n-1));
}else if( lockType==F_RDLCK ){
- OSTRACE(("read-lock %d ok", ofst));
- pShmNode->exclMask &= ~mask;
- pShmNode->sharedMask |= mask;
+ OSTRACE(("read-lock %d..%d ok\n", ofst, ofst+n-1));
}else{
assert( lockType==F_WRLCK );
- OSTRACE(("write-lock %d ok", ofst));
- pShmNode->exclMask |= mask;
- pShmNode->sharedMask &= ~mask;
+ OSTRACE(("write-lock %d..%d ok\n", ofst, ofst+n-1));
}
}else{
if( lockType==F_UNLCK ){
- OSTRACE(("unlock %d failed", ofst));
+ OSTRACE(("unlock %d..%d failed\n", ofst, ofst+n-1));
}else if( lockType==F_RDLCK ){
- OSTRACE(("read-lock failed"));
+ OSTRACE(("read-lock %d..%d failed\n", ofst, ofst+n-1));
}else{
assert( lockType==F_WRLCK );
- OSTRACE(("write-lock %d failed", ofst));
+ OSTRACE(("write-lock %d..%d failed\n", ofst, ofst+n-1));
}
}
- OSTRACE((" - afterwards %03x,%03x\n",
- pShmNode->sharedMask, pShmNode->exclMask));
- }
#endif
- return rc;
+ return rc;
}
/*
@@ -36885,6 +45013,11 @@ static void unixShmPurge(unixFile *pFd){
int i;
assert( p->pInode==pFd->pInode );
sqlite3_mutex_free(p->pShmMutex);
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+ for(i=0; iaMutex[i]);
+ }
+#endif
for(i=0; inRegion; i+=nShmPerMap){
if( p->hShm>=0 ){
osMunmap(p->apRegion[i], p->szRegion);
@@ -36907,7 +45040,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.
*/
@@ -36918,7 +45051,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
@@ -36944,7 +45077,20 @@ static int unixLockSharedMemory(unixFile *pDbFd, unixShmNode *pShmNode){
pShmNode->isUnlocked = 1;
rc = SQLITE_READONLY_CANTINIT;
}else{
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+ /* Do not use a blocking lock here. If the lock cannot be obtained
+ ** immediately, it means some other connection is truncating the
+ ** *-shm file. And after it has done so, it will not release its
+ ** lock, but only downgrade it to a shared lock. So no point in
+ ** blocking here. The call below to obtain the shared DMS lock may
+ ** use a blocking lock. */
+ int iSaveTimeout = pDbFd->iBusyTimeout;
+ pDbFd->iBusyTimeout = 0;
+#endif
rc = unixShmSystemLock(pDbFd, F_WRLCK, UNIX_SHM_DMS, 1);
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+ pDbFd->iBusyTimeout = iSaveTimeout;
+#endif
/* 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
@@ -36966,20 +45112,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"
@@ -37049,7 +45195,7 @@ 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
@@ -37065,14 +45211,28 @@ static int unixOpenSharedMemory(unixFile *pDbFd){
rc = SQLITE_NOMEM_BKPT;
goto shm_open_err;
}
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+ {
+ int ii;
+ for(ii=0; iiaMutex[ii] = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
+ if( pShmNode->aMutex[ii]==0 ){
+ rc = SQLITE_NOMEM_BKPT;
+ goto shm_open_err;
+ }
+ }
+ }
+#endif
}
if( pInode->bProcessLock==0 ){
if( 0==sqlite3_uri_boolean(pDbFd->zPath, "readonly_shm", 0) ){
- pShmNode->hShm = 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->hShm<0 ){
- pShmNode->hShm = robust_open(zShm, O_RDONLY, (sStat.st_mode&0777));
+ 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;
@@ -37122,22 +45282,22 @@ static int unixOpenSharedMemory(unixFile *pDbFd){
}
/*
-** 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(
@@ -37177,9 +45337,9 @@ static int unixShmMap(
nReqRegion = ((iRegion+nShmPerMap) / nShmPerMap) * nShmPerMap;
if( pShmNode->nRegionszRegion = szRegion;
@@ -37192,7 +45352,7 @@ static int unixShmMap(
rc = SQLITE_IOERR_SHMSIZE;
goto shmpage_out;
}
-
+
if( sStat.st_sizeapRegion, nReqRegion*sizeof(char *)
);
if( !apNew ){
@@ -37236,12 +45396,12 @@ static int unixShmMap(
}
pShmNode->apRegion = apNew;
while( pShmNode->nRegionhShm>=0 ){
pMem = osMmap(0, nMap,
- pShmNode->isReadonly ? PROT_READ : PROT_READ|PROT_WRITE,
+ pShmNode->isReadonly ? PROT_READ : PROT_READ|PROT_WRITE,
MAP_SHARED, pShmNode->hShm, szRegion*(i64)pShmNode->nRegion
);
if( pMem==MAP_FAILED ){
@@ -37275,10 +45435,45 @@ static int unixShmMap(
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){
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+ return 1;
+#else
+ unixShm *pX;
+ int aLock[SQLITE_SHM_NLOCK];
+
+ 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
+}
+#endif /* !defined(SQLITE_WASI) && !defined(SQLITE_OMIT_WAL) */
+
/*
** Change the lock state for a shared-memory segment.
**
-** Note that the relationship between SHAREd and EXCLUSIVE locks is a little
+** Note that the relationship between SHARED and EXCLUSIVE locks is a little
** different here than in posix. In xShmLock(), one can go from unlocked
** to shared and back or from unlocked to exclusive and back. But one may
** not go from shared to exclusive or from exclusive to shared.
@@ -37290,11 +45485,17 @@ static int unixShmLock(
int flags /* What to do with the lock */
){
unixFile *pDbFd = (unixFile*)fd; /* Connection holding shared memory */
- unixShm *p = pDbFd->pShm; /* The shared memory being locked */
- unixShm *pX; /* For looping over all siblings */
- unixShmNode *pShmNode = p->pShmNode; /* The underlying file iNode */
+ unixShm *p; /* The shared memory being locked */
+ unixShmNode *pShmNode; /* The underlying file iNode */
int rc = SQLITE_OK; /* Result code */
- u16 mask; /* Mask of locks to take or release */
+ u16 mask = (1<<(ofst+n)) - (1<pShm;
+ if( p==0 ) return SQLITE_IOERR_SHMLOCK;
+ pShmNode = p->pShmNode;
+ if( NEVER(pShmNode==0) ) return SQLITE_IOERR_SHMLOCK;
+ aLock = pShmNode->aLock;
assert( pShmNode==pDbFd->pInode->pShmNode );
assert( pShmNode->pInode==pDbFd->pInode );
@@ -37308,89 +45509,171 @@ static int unixShmLock(
assert( pShmNode->hShm>=0 || pDbFd->pInode->bProcessLock==1 );
assert( pShmNode->hShm<0 || pDbFd->pInode->bProcessLock==0 );
- mask = (1<<(ofst+n)) - (1<1 || mask==(1<pShmMutex);
- if( flags & SQLITE_SHM_UNLOCK ){
- u16 allMask = 0; /* Mask of locks held by siblings */
-
- /* See if any siblings hold this same lock */
- for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
- if( pX==p ) continue;
- assert( (pX->exclMask & (p->exclMask|p->sharedMask))==0 );
- allMask |= pX->sharedMask;
- }
+ /* 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. Recovery lock (ofst==2).
+ ** 2. Checkpointer lock (ofst==1).
+ ** 3. Write lock (ofst==0).
+ ** 4. Read locks (ofst>=3 && ofstexclMask|p->sharedMask);
+ assert( (flags & SQLITE_SHM_UNLOCK) || pDbFd->iBusyTimeout==0 || (
+ (ofst!=2 || lockMask==0)
+ && (ofst!=1 || lockMask==0 || lockMask==2)
+ && (ofst!=0 || lockMask<3)
+ && (ofst<3 || lockMask<(1<exclMask & mask)
+ );
+ if( ((flags & SQLITE_SHM_UNLOCK) && ((p->exclMask|p->sharedMask) & mask))
+ || (flags==(SQLITE_SHM_SHARED|SQLITE_SHM_LOCK) && 0==(p->sharedMask & mask))
+ || (flags==(SQLITE_SHM_EXCLUSIVE|SQLITE_SHM_LOCK))
+ ){
- /* Undo the local locks */
- if( rc==SQLITE_OK ){
- p->exclMask &= ~mask;
- p->sharedMask &= ~mask;
- }
- }else if( flags & SQLITE_SHM_SHARED ){
- u16 allShared = 0; /* Union of locks held by connections other than "p" */
-
- /* Find out which shared locks are already held by sibling connections.
- ** If any sibling already holds an exclusive lock, go ahead and return
- ** SQLITE_BUSY.
- */
- for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
- if( (pX->exclMask & mask)!=0 ){
- rc = SQLITE_BUSY;
- break;
+ /* Take the required mutexes. In SETLK_TIMEOUT mode (blocking locks), if
+ ** this is an attempt on an exclusive lock use sqlite3_mutex_try(). If any
+ ** other thread is holding this mutex, then it is either holding or about
+ ** to hold a lock exclusive to the one being requested, and we may
+ ** therefore return SQLITE_BUSY to the caller.
+ **
+ ** Doing this prevents some deadlock scenarios. For example, thread 1 may
+ ** be a checkpointer blocked waiting on the WRITER lock. And thread 2
+ ** may be a normal SQL client upgrading to a write transaction. In this
+ ** case thread 2 does a non-blocking request for the WRITER lock. But -
+ ** if it were to use sqlite3_mutex_enter() then it would effectively
+ ** become a (doomed) blocking request, as thread 2 would block until thread
+ ** 1 obtained WRITER and released the mutex. Since thread 2 already holds
+ ** a lock on a read-locking slot at this point, this breaks the
+ ** anti-deadlock rules (see above). */
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+ int iMutex;
+ for(iMutex=ofst; iMutexaMutex[iMutex]);
+ if( rc!=SQLITE_OK ) goto leave_shmnode_mutexes;
+ }else{
+ sqlite3_mutex_enter(pShmNode->aMutex[iMutex]);
}
- allShared |= pX->sharedMask;
}
+#else
+ sqlite3_mutex_enter(pShmNode->pShmMutex);
+#endif
+
+ if( ALWAYS(rc==SQLITE_OK) ){
+ if( flags & SQLITE_SHM_UNLOCK ){
+ /* Case (a) - unlock. */
+ int bUnlock = 1;
+ assert( (p->exclMask & p->sharedMask)==0 );
+ assert( !(flags & SQLITE_SHM_EXCLUSIVE) || (p->exclMask & mask)==mask );
+ assert( !(flags & SQLITE_SHM_SHARED) || (p->sharedMask & mask)==mask );
+
+ /* If this is a SHARED lock being unlocked, it is possible that other
+ ** clients within this process are holding the same SHARED lock. In
+ ** this case, set bUnlock to 0 so that the posix lock is not removed
+ ** from the file-descriptor below. */
+ if( flags & SQLITE_SHM_SHARED ){
+ assert( n==1 );
+ assert( aLock[ofst]>=1 );
+ if( aLock[ofst]>1 ){
+ bUnlock = 0;
+ aLock[ofst]--;
+ p->sharedMask &= ~mask;
+ }
+ }
- /* Get shared locks at the system level, if necessary */
- if( rc==SQLITE_OK ){
- if( (allShared & mask)==0 ){
- rc = unixShmSystemLock(pDbFd, F_RDLCK, ofst+UNIX_SHM_BASE, n);
+ if( bUnlock ){
+ rc = unixShmSystemLock(pDbFd, F_UNLCK, ofst+UNIX_SHM_BASE, n);
+ if( rc==SQLITE_OK ){
+ memset(&aLock[ofst], 0, sizeof(int)*n);
+ p->sharedMask &= ~mask;
+ p->exclMask &= ~mask;
+ }
+ }
+ }else if( flags & SQLITE_SHM_SHARED ){
+ /* Case (b) - a shared lock. */
+
+ if( aLock[ofst]<0 ){
+ /* An exclusive lock is held by some other connection. BUSY. */
+ rc = SQLITE_BUSY;
+ }else if( aLock[ofst]==0 ){
+ rc = unixShmSystemLock(pDbFd, F_RDLCK, ofst+UNIX_SHM_BASE, n);
+ }
+
+ /* Get the local shared locks */
+ if( rc==SQLITE_OK ){
+ p->sharedMask |= mask;
+ aLock[ofst]++;
+ }
}else{
- rc = SQLITE_OK;
- }
- }
+ /* Case (c) - an exclusive lock. */
+ int ii;
- /* Get the local shared locks */
- if( rc==SQLITE_OK ){
- p->sharedMask |= mask;
- }
- }else{
- /* Make sure no sibling connections hold locks that will block this
- ** lock. If any do, return SQLITE_BUSY right away.
- */
- for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
- if( (pX->exclMask & mask)!=0 || (pX->sharedMask & mask)!=0 ){
- rc = SQLITE_BUSY;
- break;
- }
- }
-
- /* Get the exclusive locks at the system level. Then if successful
- ** also mark the local connection as being locked.
- */
- if( rc==SQLITE_OK ){
- rc = unixShmSystemLock(pDbFd, F_WRLCK, ofst+UNIX_SHM_BASE, n);
- if( rc==SQLITE_OK ){
+ assert( flags==(SQLITE_SHM_LOCK|SQLITE_SHM_EXCLUSIVE) );
assert( (p->sharedMask & mask)==0 );
- p->exclMask |= mask;
+ assert( (p->exclMask & mask)==0 );
+
+ /* Make sure no sibling connections hold locks that will block this
+ ** lock. If any do, return SQLITE_BUSY right away. */
+ for(ii=ofst; iiexclMask |= mask;
+ for(ii=ofst; ii=ofst; iMutex--){
+ sqlite3_mutex_leave(pShmNode->aMutex[iMutex]);
+ }
+#else
+ sqlite3_mutex_leave(pShmNode->pShmMutex);
+#endif
}
- 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.
@@ -37400,15 +45683,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
@@ -37482,7 +45765,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:
@@ -37574,14 +45857,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
@@ -37622,7 +45905,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){
@@ -37633,11 +45916,16 @@ static int unixFetch(sqlite3_file *fd, i64 iOff, int nAmt, void **pp){
#if SQLITE_MAX_MMAP_SIZE>0
if( pFd->mmapSizeMax>0 ){
+ /* Ensure that there is always at least a 256 byte buffer of addressable
+ ** memory following the returned page. If the database is corrupt,
+ ** SQLite may overread the page slightly (in practice only a few bytes,
+ ** but 256 is safe, round, number). */
+ const int nEofBuffer = 256;
if( pFd->pMapRegion==0 ){
int rc = unixMapfile(pFd, -1);
if( rc!=SQLITE_OK ) return rc;
}
- if( pFd->mmapSize >= iOff+nAmt ){
+ if( pFd->mmapSize >= (iOff+nAmt+nEofBuffer) ){
*pp = &((u8 *)pFd->pMapRegion)[iOff];
pFd->nFetchOut++;
}
@@ -37647,13 +45935,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){
@@ -37661,7 +45949,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) );
@@ -37869,8 +46157,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.
**
@@ -37912,8 +46200,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;
@@ -37929,7 +46217,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 */
@@ -37965,7 +46253,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 */
@@ -38093,14 +46381,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;
@@ -38138,55 +46426,75 @@ static int fillInUnixFile(
unixLeaveMutex();
}
#endif
-
+
storeLastErrno(pNew, 0);
#if OS_VXWORKS
if( rc!=SQLITE_OK ){
- if( h>=0 ) robust_close(pNew, h, __LINE__);
- h = -1;
- osUnlink(zFilename);
- pNew->ctrlFlags |= UNIXFILE_DELETE;
+ if( h>=0 ){
+ robust_close(pNew, h, __LINE__);
+ h = -1;
+ }
+ if( pNew->ctrlFlags & UNIXFILE_DELETE ){
+ osUnlink(zFilename);
+ }
+ if( pNew->pId ){
+ vxworksReleaseFileId(pNew->pId);
+ pNew->pId = 0;
+ }
}
#endif
if( rc!=SQLITE_OK ){
if( h>=0 ) robust_close(pNew, h, __LINE__);
}else{
- pNew->pMethod = pLockingStyle;
+ pId->pMethods = pLockingStyle;
OpenCounter(+1);
verifyDbFile(pNew);
}
return rc;
}
+/*
+** Directories to consider for temp files.
+*/
+static const char *azTempDirs[] = {
+ 0,
+ 0,
+ "/var/tmp",
+ "/usr/tmp",
+ "/tmp",
+ "."
+};
+
+/*
+** Initialize first two members of azTempDirs[] array.
+*/
+static void unixTempFileInit(void){
+ azTempDirs[0] = getenv("SQLITE_TMPDIR");
+ azTempDirs[1] = getenv("TMPDIR");
+}
+
/*
** Return the name of a directory in which to put temporary files.
** If no suitable temporary file directory can be found, return NULL.
*/
static const char *unixTempFileDir(void){
- static const char *azDirs[] = {
- 0,
- 0,
- "/var/tmp",
- "/usr/tmp",
- "/tmp",
- "."
- };
unsigned int i = 0;
struct stat buf;
const char *zDir = sqlite3_temp_directory;
- if( !azDirs[0] ) azDirs[0] = getenv("SQLITE_TMPDIR");
- if( !azDirs[1] ) azDirs[1] = getenv("TMPDIR");
while(1){
if( zDir!=0
+#if OS_VXWORKS
+ && zDir[0]=='/'
+#endif
&& osStat(zDir, &buf)==0
&& S_ISDIR(buf.st_mode)
&& osAccess(zDir, 03)==0
){
return zDir;
}
- if( i>=sizeof(azDirs)/sizeof(azDirs[0]) ) break;
- zDir = azDirs[i++];
+ if( i>=sizeof(azTempDirs)/sizeof(azTempDirs[0]) ) break;
+ zDir = azTempDirs[i++];
}
return 0;
}
@@ -38199,26 +46507,35 @@ static const char *unixTempFileDir(void){
static int unixGetTempname(int nBuf, char *zBuf){
const char *zDir;
int iLimit = 0;
+ int rc = SQLITE_OK;
/* 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 );
+ sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR));
zDir = unixTempFileDir();
- if( zDir==0 ) return SQLITE_IOERR_GETTEMPPATH;
- do{
- u64 r;
- sqlite3_randomness(sizeof(r), &r);
- assert( nBuf>2 );
- zBuf[nBuf-2] = 0;
- sqlite3_snprintf(nBuf, zBuf, "%s/"SQLITE_TEMP_FILE_PREFIX"%llx%c",
- zDir, r, 0);
- if( zBuf[nBuf-2]!=0 || (iLimit++)>10 ) return SQLITE_ERROR;
- }while( osAccess(zBuf,0)==0 );
- return SQLITE_OK;
+ if( zDir==0 ){
+ rc = SQLITE_IOERR_GETTEMPPATH;
+ }else{
+ do{
+ u64 r;
+ sqlite3_randomness(sizeof(r), &r);
+ assert( nBuf>2 );
+ zBuf[nBuf-2] = 0;
+ sqlite3_snprintf(nBuf, zBuf, "%s/"SQLITE_TEMP_FILE_PREFIX"%llx%c",
+ zDir, r, 0);
+ if( zBuf[nBuf-2]!=0 || (iLimit++)>10 ){
+ rc = SQLITE_ERROR;
+ break;
+ }
+ }while( osAccess(zBuf,0)==0 );
+ }
+ sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR));
+ return rc;
}
#if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__)
@@ -38231,8 +46548,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.
**
@@ -38240,7 +46557,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
@@ -38251,8 +46568,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 */
@@ -38279,6 +46596,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 ){
@@ -38293,7 +46611,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 */
@@ -38317,22 +46635,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 */
@@ -38358,22 +46676,25 @@ 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.
+ **
+ ** 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 super-journal with a goofy name, then
+ ** the '-' might be missing or the '-' might be the first character in
+ ** the filename. In that case, just return SQLITE_OK with *pMode==0.
*/
- 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
- ** the '-' might be missing. */
- if( nDb==0 || zPath[nDb]=='.' ) return SQLITE_OK;
+ nDb = sqlite3Strlen30(zPath) - 1;
+ while( nDb>0 && zPath[nDb]!='.' ){
+ if( zPath[nDb]=='-' ){
+ memcpy(zDb, zPath, nDb);
+ zDb[nDb] = '\0';
+ rc = getFileMode(zDb, pMode, pUid, pGid);
+ break;
+ }
nDb--;
}
- memcpy(zDb, zPath, nDb);
- zDb[nDb] = '\0';
-
- rc = getFileMode(zDb, pMode, pUid, pGid);
}else if( flags & SQLITE_OPEN_DELETEONCLOSE ){
*pMode = 0600;
}else if( flags & SQLITE_OPEN_URI ){
@@ -38391,7 +46712,7 @@ static int findCreateFileMode(
/*
** Open the file zPath.
-**
+**
** Previously, the SQLite OS layer used three functions in place of this
** one:
**
@@ -38402,13 +46723,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(
@@ -38421,7 +46742,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 */
@@ -38438,13 +46759,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
));
@@ -38454,9 +46775,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.
@@ -38466,20 +46787,26 @@ 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
);
+#if OS_VXWORKS
+ /* The file-ID mechanism used in Vxworks requires that all pathnames
+ ** provided to unixOpen must be absolute pathnames. */
+ if( zPath!=0 && zPath[0]!='/' ){ return SQLITE_CANTOPEN; }
+#endif
+
/* Detect a pid change and reset the PRNG. There is a race condition
** here such that two or more threads all trying to open databases at
** the same instant might all reset the PRNG. But multiple resets
@@ -38491,6 +46818,11 @@ static int unixOpen(
}
memset(p, 0, sizeof(unixFile));
+#ifdef SQLITE_ASSERT_NO_FILES
+ /* Applications that never read or write a persistent disk files */
+ assert( zName==0 );
+#endif
+
if( eType==SQLITE_OPEN_MAIN_DB ){
UnixUnusedFd *pUnused;
pUnused = findReusableFd(zName, flags);
@@ -38525,13 +46857,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 */
@@ -38553,12 +46885,19 @@ static int unixOpen(
rc = SQLITE_READONLY_DIRECTORY;
}else if( errno!=EISDIR && isReadWrite ){
/* Failed to open the file for read/write access. Try read-only. */
+ UnixUnusedFd *pReadonly = 0;
flags &= ~(SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE);
openFlags &= ~(O_RDWR|O_CREAT);
flags |= SQLITE_OPEN_READONLY;
openFlags |= O_RDONLY;
isReadonly = 1;
- fd = robust_open(zName, openFlags, openMode);
+ pReadonly = findReusableFd(zName, flags);
+ if( pReadonly ){
+ fd = pReadonly->fd;
+ sqlite3_free(pReadonly);
+ }else{
+ fd = robust_open(zName, openFlags, openMode);
+ }
}
}
if( fd<0 ){
@@ -38567,11 +46906,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);
}
}
@@ -38582,7 +46929,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 ){
@@ -38603,7 +46951,7 @@ static int unixOpen(
p->openFlags = openFlags;
}
#endif
-
+
#if defined(__APPLE__) || SQLITE_ENABLE_LOCKING_STYLE
if( fstatfs(fd, &fsInfo) == -1 ){
storeLastErrno(p, errno);
@@ -38634,7 +46982,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;
@@ -38646,9 +46994,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;
@@ -38658,9 +47006,12 @@ 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
+ || eType==SQLITE_OPEN_TEMP_JOURNAL
);
rc = fillInUnixFile(pVfs, fd, pFile, zPath, ctrlFlags);
@@ -38740,7 +47091,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;
}
@@ -38748,38 +47100,105 @@ static int unixAccess(
}
/*
-**
+** A pathname under construction
*/
-static int mkFullPathname(
- const char *zPath, /* Input path */
- char *zOut, /* Output buffer */
- int nOut /* Allocated size of buffer zOut */
+typedef struct DbPath DbPath;
+struct DbPath {
+ int rc; /* Non-zero following any error */
+ int nSymlink; /* Number of symlinks resolved */
+ char *zOut; /* Write the pathname here */
+ int nOut; /* Bytes of space available to zOut[] */
+ int nUsed; /* Bytes of zOut[] currently being used */
+};
+
+/* Forward reference */
+static void appendAllPathElements(DbPath*,const char*);
+
+/*
+** Append a single path element to the DbPath under construction
+*/
+static void appendOnePathElement(
+ DbPath *pPath, /* Path under construction, to which to append zName */
+ const char *zName, /* Name to append to pPath. Not zero-terminated */
+ int nName /* Number of significant bytes in zName */
){
- int nPath = sqlite3Strlen30(zPath);
- int iOff = 0;
- if( zPath[0]!='/' ){
- if( osGetcwd(zOut, nOut-2)==0 ){
- return unixLogError(SQLITE_CANTOPEN_BKPT, "getcwd", zPath);
+ assert( nName>0 );
+ assert( zName!=0 );
+ if( zName[0]=='.' ){
+ if( nName==1 ) return;
+ if( zName[1]=='.' && nName==2 ){
+ if( pPath->nUsed>1 ){
+ assert( pPath->zOut[0]=='/' );
+ while( pPath->zOut[--pPath->nUsed]!='/' ){}
+ }
+ return;
}
- iOff = sqlite3Strlen30(zOut);
- zOut[iOff++] = '/';
}
- if( (iOff+nPath+1)>nOut ){
- /* SQLite assumes that xFullPathname() nul-terminates the output buffer
- ** even if it returns an error. */
- zOut[iOff] = '\0';
- return SQLITE_CANTOPEN_BKPT;
+ if( pPath->nUsed + nName + 2 >= pPath->nOut ){
+ pPath->rc = SQLITE_ERROR;
+ return;
}
- sqlite3_snprintf(nOut-iOff, &zOut[iOff], "%s", zPath);
- return SQLITE_OK;
+ pPath->zOut[pPath->nUsed++] = '/';
+ memcpy(&pPath->zOut[pPath->nUsed], zName, nName);
+ pPath->nUsed += nName;
+#if defined(HAVE_READLINK) && defined(HAVE_LSTAT)
+ if( pPath->rc==SQLITE_OK ){
+ const char *zIn;
+ struct stat buf;
+ pPath->zOut[pPath->nUsed] = 0;
+ zIn = pPath->zOut;
+ if( osLstat(zIn, &buf)!=0 ){
+ if( errno!=ENOENT ){
+ pPath->rc = unixLogError(SQLITE_CANTOPEN_BKPT, "lstat", zIn);
+ }
+ }else if( S_ISLNK(buf.st_mode) ){
+ ssize_t got;
+ char zLnk[SQLITE_MAX_PATHLEN+2];
+ if( pPath->nSymlink++ > SQLITE_MAX_SYMLINK ){
+ pPath->rc = SQLITE_CANTOPEN_BKPT;
+ return;
+ }
+ got = osReadlink(zIn, zLnk, sizeof(zLnk)-2);
+ if( got<=0 || got>=(ssize_t)sizeof(zLnk)-2 ){
+ pPath->rc = unixLogError(SQLITE_CANTOPEN_BKPT, "readlink", zIn);
+ return;
+ }
+ zLnk[got] = 0;
+ if( zLnk[0]=='/' ){
+ pPath->nUsed = 0;
+ }else{
+ pPath->nUsed -= nName + 1;
+ }
+ appendAllPathElements(pPath, zLnk);
+ }
+ }
+#endif
+}
+
+/*
+** Append all path elements in zPath to the DbPath under construction.
+*/
+static void appendAllPathElements(
+ DbPath *pPath, /* Path under construction, to which to append zName */
+ const char *zPath /* Path to append to pPath. Is zero-terminated */
+){
+ int i = 0;
+ int j = 0;
+ do{
+ while( zPath[i] && zPath[i]!='/' ){ i++; }
+ if( i>j ){
+ appendOnePathElement(pPath, &zPath[j], i-j);
+ }
+ j = i+1;
+ }while( zPath[i++] );
}
/*
** 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.
*/
@@ -38789,84 +47208,27 @@ static int unixFullPathname(
int nOut, /* Size of output buffer in bytes */
char *zOut /* Output buffer */
){
-#if !defined(HAVE_READLINK) || !defined(HAVE_LSTAT)
- return mkFullPathname(zPath, zOut, nOut);
-#else
- int rc = SQLITE_OK;
- int nByte;
- int nLink = 1; /* Number of symbolic links followed so far */
- const char *zIn = zPath; /* Input path for each iteration of loop */
- char *zDel = 0;
-
- assert( pVfs->mxPathname==MAX_PATHNAME );
+ DbPath path;
UNUSED_PARAMETER(pVfs);
-
- /* It's odd to simulate an io-error here, but really this is just
- ** using the io-error infrastructure to test that SQLite handles this
- ** function failing. This function could fail if, for example, the
- ** current working directory has been unlinked.
- */
- SimulateIOError( return SQLITE_ERROR );
-
- do {
-
- /* Call stat() on path zIn. Set bLink to true if the path is a symbolic
- ** link, or false otherwise. */
- int bLink = 0;
- struct stat buf;
- if( osLstat(zIn, &buf)!=0 ){
- if( errno!=ENOENT ){
- rc = unixLogError(SQLITE_CANTOPEN_BKPT, "lstat", zIn);
- }
- }else{
- bLink = S_ISLNK(buf.st_mode);
- }
-
- if( bLink ){
- if( zDel==0 ){
- zDel = sqlite3_malloc(nOut);
- if( zDel==0 ) rc = SQLITE_NOMEM_BKPT;
- }else if( ++nLink>SQLITE_MAX_SYMLINKS ){
- rc = SQLITE_CANTOPEN_BKPT;
- }
-
- if( rc==SQLITE_OK ){
- nByte = osReadlink(zIn, zDel, nOut-1);
- if( nByte<0 ){
- rc = unixLogError(SQLITE_CANTOPEN_BKPT, "readlink", zIn);
- }else{
- if( zDel[0]!='/' ){
- int n;
- for(n = sqlite3Strlen30(zIn); n>0 && zIn[n-1]!='/'; n--);
- if( nByte+n+1>nOut ){
- rc = SQLITE_CANTOPEN_BKPT;
- }else{
- memmove(&zDel[n], zDel, nByte+1);
- memcpy(zDel, zIn, n);
- nByte += n;
- }
- }
- zDel[nByte] = '\0';
- }
- }
-
- zIn = zDel;
- }
-
- assert( rc!=SQLITE_OK || zIn!=zOut || zIn[0]=='/' );
- if( rc==SQLITE_OK && zIn!=zOut ){
- rc = mkFullPathname(zIn, zOut, nOut);
+ path.rc = 0;
+ path.nUsed = 0;
+ path.nSymlink = 0;
+ path.nOut = nOut;
+ path.zOut = zOut;
+ if( zPath[0]!='/' ){
+ char zPwd[SQLITE_MAX_PATHLEN+2];
+ if( osGetcwd(zPwd, sizeof(zPwd)-2)==0 ){
+ return unixLogError(SQLITE_CANTOPEN_BKPT, "getcwd", zPath);
}
- if( bLink==0 ) break;
- zIn = zOut;
- }while( rc==SQLITE_OK );
-
- sqlite3_free(zDel);
- return rc;
-#endif /* HAVE_READLINK && HAVE_LSTAT */
+ appendAllPathElements(&path, zPwd);
+ }
+ appendAllPathElements(&path, zPath);
+ zOut[path.nUsed] = 0;
+ if( path.rc || path.nUsed<2 ) return SQLITE_CANTOPEN_BKPT;
+ if( path.nSymlink ) return SQLITE_OK_SYMLINK;
+ return SQLITE_OK;
}
-
#ifndef SQLITE_OMIT_LOAD_EXTENSION
/*
** Interfaces for opening a shared library, finding entry points
@@ -38896,7 +47258,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
@@ -38906,7 +47268,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
@@ -38949,7 +47311,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;
@@ -38980,16 +47342,22 @@ static int unixRandomness(sqlite3_vfs *NotUsed, int nBuf, char *zBuf){
** than the argument.
*/
static int unixSleep(sqlite3_vfs *NotUsed, int microseconds){
-#if OS_VXWORKS
+#if !defined(HAVE_NANOSLEEP) || HAVE_NANOSLEEP+0
struct timespec sp;
-
sp.tv_sec = microseconds / 1000000;
sp.tv_nsec = (microseconds % 1000000) * 1000;
+
+ /* Almost all modern unix systems support nanosleep(). But if you are
+ ** compiling for one of the rare exceptions, you can use
+ ** -DHAVE_NANOSLEEP=0 (perhaps in conjunction with -DHAVE_USLEEP if
+ ** usleep() is available) in order to bypass the use of nanosleep() */
nanosleep(&sp, NULL);
+
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
@@ -39016,7 +47384,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){
@@ -39123,7 +47491,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
@@ -39149,19 +47517,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
@@ -39188,11 +47556,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.
@@ -39206,7 +47574,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
@@ -39221,8 +47589,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
@@ -39232,12 +47600,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;
@@ -39253,10 +47621,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;
@@ -39273,7 +47641,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);
@@ -39283,7 +47651,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) ){
@@ -39347,7 +47715,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;
@@ -39377,7 +47745,7 @@ static int proxyCreateUnixFile(
}
}
if( fd<0 ){
- openFlags = O_RDONLY;
+ openFlags = O_RDONLY | O_NOFOLLOW;
fd = robust_open(path, openFlags, 0);
terrno = errno;
}
@@ -39388,13 +47756,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;
@@ -39408,13 +47776,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);
@@ -39428,18 +47796,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) ){
@@ -39459,7 +47827,7 @@ static int proxyGetHostID(unsigned char *pHostID, int *pError){
pHostID[0] = (char)(pHostID[0] + (char)(sqlite3_hostid_num & 0xFF));
}
#endif
-
+
return SQLITE_OK;
}
@@ -39470,14 +47838,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];
@@ -39491,7 +47859,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;
@@ -39503,7 +47871,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;
@@ -39533,24 +47901,24 @@ static int proxyBreakConchLock(unixFile *pFile, uuid_t myHostID){
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.
*/
@@ -39559,20 +47927,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 ){
@@ -39588,10 +47956,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;
@@ -39604,19 +47972,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{
@@ -39632,7 +48000,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)));
@@ -39653,21 +48021,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 ){
@@ -39676,7 +48044,7 @@ static int proxyTakeConch(unixFile *pFile){
*/
if( hostIdMatch ){
size_t pathLen = (readLen - PROXY_PATHINDEX);
-
+
if( pathLen>=MAXPATHLEN ){
pathLen=MAXPATHLEN-1;
}
@@ -39692,23 +48060,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.
@@ -39719,7 +48087,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{
@@ -39728,7 +48096,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 ){
@@ -39741,8 +48109,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;
@@ -39766,14 +48134,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 ){
@@ -39796,7 +48164,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;
@@ -39816,7 +48184,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;
@@ -39828,7 +48196,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. */
}
}
@@ -39844,7 +48212,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);
@@ -39872,13 +48240,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]=='/' ){
@@ -39901,7 +48269,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;
@@ -39910,7 +48278,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:") ||
@@ -39928,7 +48296,7 @@ static int switchLockProxyPath(unixFile *pFile, const char *path) {
sqlite3_free(oldPath);
pCtx->lockProxyPath = sqlite3DbStrDup(0, path);
}
-
+
return rc;
}
@@ -39942,7 +48310,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,
@@ -39963,9 +48331,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
@@ -39975,7 +48343,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;
}
@@ -39985,7 +48353,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)));
@@ -40019,7 +48387,7 @@ static int proxyTransformUnixFile(unixFile *pFile, const char *path) {
rc = SQLITE_OK;
}
}
- }
+ }
if( rc==SQLITE_OK && lockPath ){
pCtx->lockProxyPath = sqlite3DbStrDup(0, lockPath);
}
@@ -40031,7 +48399,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;
@@ -40039,12 +48407,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,
@@ -40082,7 +48450,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{
@@ -40092,9 +48460,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))
){
@@ -40113,7 +48481,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;
}
@@ -40219,7 +48587,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;
@@ -40256,7 +48624,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 **********************
******************************************************************************/
@@ -40274,8 +48642,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
@@ -40291,7 +48659,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.
*/
@@ -40361,10 +48729,43 @@ SQLITE_API int sqlite3_os_init(void){
/* Register all VFSes defined in the aVfs[] array */
for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){
+#ifdef SQLITE_DEFAULT_UNIX_VFS
+ sqlite3_vfs_register(&aVfs[i],
+ 0==strcmp(aVfs[i].zName,SQLITE_DEFAULT_UNIX_VFS));
+#else
sqlite3_vfs_register(&aVfs[i], i==0);
+#endif
}
+#ifdef SQLITE_OS_KV_OPTIONAL
+ sqlite3KvvfsInit();
+#endif
unixBigLock = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1);
- return SQLITE_OK;
+#if OS_VXWORKS
+ vxworksMutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS2);
+#endif
+
+#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
+
+ /* Initialize temp file dir array. */
+ unixTempFileInit();
+
+ return SQLITE_OK;
}
/*
@@ -40374,11 +48775,14 @@ 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;
+#if OS_VXWORKS
+ vxworksMutex = 0;
+#endif
+ return SQLITE_OK;
}
-
+
#endif /* SQLITE_OS_UNIX */
/************** End of os_unix.c *********************************************/
@@ -40403,205 +48807,7 @@ SQLITE_API int sqlite3_os_end(void){
/*
** Include code that is common to all os_*.c files
*/
-/************** Include os_common.h in the middle of os_win.c ****************/
-/************** Begin file os_common.h ***************************************/
-/*
-** 2004 May 22
-**
-** The author disclaims copyright to this source code. In place of
-** a legal notice, here is a blessing:
-**
-** May you do good and not evil.
-** May you find forgiveness for yourself and forgive others.
-** May you share freely, never taking more than you give.
-**
-******************************************************************************
-**
-** This file contains macros and a little bit of code that is common to
-** all of the platform-specific files (os_*.c) and is #included into those
-** files.
-**
-** This file should be #included by the os_*.c files only. It is not a
-** general purpose header file.
-*/
-#ifndef _OS_COMMON_H_
-#define _OS_COMMON_H_
-
-/*
-** At least two bugs have slipped in because we changed the MEMORY_DEBUG
-** macro to SQLITE_DEBUG and some older makefiles have not yet made the
-** switch. The following code should catch this problem at compile-time.
-*/
-#ifdef MEMORY_DEBUG
-# error "The MEMORY_DEBUG macro is obsolete. Use SQLITE_DEBUG instead."
-#endif
-
-/*
-** Macros for performance tracing. Normally turned off. Only works
-** on i486 hardware.
-*/
-#ifdef SQLITE_PERFORMANCE_TRACE
-
-/*
-** hwtime.h contains inline assembler code for implementing
-** high-performance timing routines.
-*/
-/************** Include hwtime.h in the middle of os_common.h ****************/
-/************** Begin file hwtime.h ******************************************/
-/*
-** 2008 May 27
-**
-** The author disclaims copyright to this source code. In place of
-** a legal notice, here is a blessing:
-**
-** May you do good and not evil.
-** May you find forgiveness for yourself and forgive others.
-** May you share freely, never taking more than you give.
-**
-******************************************************************************
-**
-** This file contains inline asm code for retrieving "high-performance"
-** counters for x86 class CPUs.
-*/
-#ifndef SQLITE_HWTIME_H
-#define SQLITE_HWTIME_H
-
-/*
-** The following routine only works on pentium-class (or newer) processors.
-** It uses the RDTSC opcode to read the cycle count value out of the
-** processor and returns that value. This can be used for high-res
-** profiling.
-*/
-#if (defined(__GNUC__) || defined(_MSC_VER)) && \
- (defined(i386) || defined(__i386__) || defined(_M_IX86))
-
- #if defined(__GNUC__)
-
- __inline__ sqlite_uint64 sqlite3Hwtime(void){
- unsigned int lo, hi;
- __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
- return (sqlite_uint64)hi << 32 | lo;
- }
-
- #elif defined(_MSC_VER)
-
- __declspec(naked) __inline sqlite_uint64 __cdecl sqlite3Hwtime(void){
- __asm {
- rdtsc
- ret ; return value at EDX:EAX
- }
- }
-
- #endif
-
-#elif (defined(__GNUC__) && defined(__x86_64__))
-
- __inline__ sqlite_uint64 sqlite3Hwtime(void){
- unsigned long val;
- __asm__ __volatile__ ("rdtsc" : "=A" (val));
- return val;
- }
-
-#elif (defined(__GNUC__) && defined(__ppc__))
-
- __inline__ sqlite_uint64 sqlite3Hwtime(void){
- unsigned long long retval;
- unsigned long junk;
- __asm__ __volatile__ ("\n\
- 1: mftbu %1\n\
- mftb %L0\n\
- mftbu %0\n\
- cmpw %0,%1\n\
- bne 1b"
- : "=r" (retval), "=r" (junk));
- return retval;
- }
-
-#else
-
- #error Need implementation of sqlite3Hwtime() for your platform.
-
- /*
- ** To compile without implementing sqlite3Hwtime() for your platform,
- ** you can remove the above #error and use the following
- ** stub function. You will lose timing support for many
- ** of the debugging and testing utilities, but it should at
- ** least compile and run.
- */
-SQLITE_PRIVATE sqlite_uint64 sqlite3Hwtime(void){ return ((sqlite_uint64)0); }
-
-#endif
-
-#endif /* !defined(SQLITE_HWTIME_H) */
-
-/************** End of hwtime.h **********************************************/
-/************** Continuing where we left off in os_common.h ******************/
-
-static sqlite_uint64 g_start;
-static sqlite_uint64 g_elapsed;
-#define TIMER_START g_start=sqlite3Hwtime()
-#define TIMER_END g_elapsed=sqlite3Hwtime()-g_start
-#define TIMER_ELAPSED g_elapsed
-#else
-#define TIMER_START
-#define TIMER_END
-#define TIMER_ELAPSED ((sqlite_uint64)0)
-#endif
-
-/*
-** If we compile with the SQLITE_TEST macro set, then the following block
-** of code will give us the ability to simulate a disk I/O error. This
-** is used for testing the I/O recovery logic.
-*/
-#if defined(SQLITE_TEST)
-SQLITE_API extern int sqlite3_io_error_hit;
-SQLITE_API extern int sqlite3_io_error_hardhit;
-SQLITE_API extern int sqlite3_io_error_pending;
-SQLITE_API extern int sqlite3_io_error_persist;
-SQLITE_API extern int sqlite3_io_error_benign;
-SQLITE_API extern int sqlite3_diskfull_pending;
-SQLITE_API extern int sqlite3_diskfull;
-#define SimulateIOErrorBenign(X) sqlite3_io_error_benign=(X)
-#define SimulateIOError(CODE) \
- if( (sqlite3_io_error_persist && sqlite3_io_error_hit) \
- || sqlite3_io_error_pending-- == 1 ) \
- { local_ioerr(); CODE; }
-static void local_ioerr(){
- IOTRACE(("IOERR\n"));
- sqlite3_io_error_hit++;
- if( !sqlite3_io_error_benign ) sqlite3_io_error_hardhit++;
-}
-#define SimulateDiskfullError(CODE) \
- if( sqlite3_diskfull_pending ){ \
- if( sqlite3_diskfull_pending == 1 ){ \
- local_ioerr(); \
- sqlite3_diskfull = 1; \
- sqlite3_io_error_hit = 1; \
- CODE; \
- }else{ \
- sqlite3_diskfull_pending--; \
- } \
- }
-#else
-#define SimulateIOErrorBenign(X)
-#define SimulateIOError(A)
-#define SimulateDiskfullError(A)
-#endif /* defined(SQLITE_TEST) */
-
-/*
-** When testing, keep a count of the number of open files.
-*/
-#if defined(SQLITE_TEST)
-SQLITE_API extern int sqlite3_open_file_count;
-#define OpenCounter(X) sqlite3_open_file_count+=(X)
-#else
-#define OpenCounter(X)
-#endif /* defined(SQLITE_TEST) */
-
-#endif /* !defined(_OS_COMMON_H_) */
-
-/************** End of os_common.h *******************************************/
-/************** Continuing where we left off in os_win.c *********************/
+/* #include "os_common.h" */
/*
** Include the header file for the Windows VFS.
@@ -40626,7 +48832,7 @@ SQLITE_API extern int sqlite3_open_file_count;
** Are most of the Win32 ANSI APIs available (i.e. with certain exceptions
** based on the sub-platform)?
*/
-#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && !defined(SQLITE_WIN32_NO_ANSI)
+#if !SQLITE_OS_WINCE && !defined(SQLITE_WIN32_NO_ANSI)
# define SQLITE_WIN32_HAS_ANSI
#endif
@@ -40634,7 +48840,7 @@ SQLITE_API extern int sqlite3_open_file_count;
** Are most of the Win32 Unicode APIs available (i.e. with certain exceptions
** based on the sub-platform)?
*/
-#if (SQLITE_OS_WINCE || SQLITE_OS_WINNT || SQLITE_OS_WINRT) && \
+#if (SQLITE_OS_WINCE || SQLITE_OS_WINNT) && \
!defined(SQLITE_WIN32_NO_WIDE)
# define SQLITE_WIN32_HAS_WIDE
#endif
@@ -40773,16 +48979,7 @@ SQLITE_API extern int sqlite3_open_file_count;
*/
#if SQLITE_WIN32_FILEMAPPING_API && \
(!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0)
-/*
-** Two of the file mapping APIs are different under WinRT. Figure out which
-** set we need.
-*/
-#if SQLITE_OS_WINRT
-WINBASEAPI HANDLE WINAPI CreateFileMappingFromApp(HANDLE, \
- LPSECURITY_ATTRIBUTES, ULONG, ULONG64, LPCWSTR);
-WINBASEAPI LPVOID WINAPI MapViewOfFileFromApp(HANDLE, ULONG, ULONG64, SIZE_T);
-#else
#if defined(SQLITE_WIN32_HAS_ANSI)
WINBASEAPI HANDLE WINAPI CreateFileMappingA(HANDLE, LPSECURITY_ATTRIBUTES, \
DWORD, DWORD, DWORD, LPCSTR);
@@ -40794,7 +48991,6 @@ WINBASEAPI HANDLE WINAPI CreateFileMappingW(HANDLE, LPSECURITY_ATTRIBUTES, \
#endif /* defined(SQLITE_WIN32_HAS_WIDE) */
WINBASEAPI LPVOID WINAPI MapViewOfFile(HANDLE, DWORD, DWORD, DWORD, SIZE_T);
-#endif /* SQLITE_OS_WINRT */
/*
** These file mapping APIs are common to both Win32 and WinRT.
@@ -40870,8 +49066,18 @@ struct winFile {
sqlite3_int64 mmapSize; /* Size of mapped region */
sqlite3_int64 mmapSizeMax; /* Configured FCNTL_MMAP_SIZE value */
#endif
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+ DWORD iBusyTimeout; /* Wait this many millisec on locks */
+ int bBlockOnConnect;
+#endif
};
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+# define winFileBusyTimeout(pDbFd) pDbFd->iBusyTimeout
+#else
+# define winFileBusyTimeout(pDbFd) 0
+#endif
+
/*
** The winVfsAppData structure is used for the pAppData member for all of the
** Win32 VFS variants.
@@ -41075,7 +49281,7 @@ static LONG SQLITE_WIN32_VOLATILE sqlite3_os_type = 0;
** This function is not available on Windows CE or WinRT.
*/
-#if SQLITE_OS_WINCE || SQLITE_OS_WINRT
+#if SQLITE_OS_WINCE
# define osAreFileApisANSI() 1
#endif
@@ -41090,7 +49296,7 @@ static struct win_syscall {
sqlite3_syscall_ptr pCurrent; /* Current value of the system call */
sqlite3_syscall_ptr pDefault; /* Default value */
} aSyscall[] = {
-#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT
+#if !SQLITE_OS_WINCE
{ "AreFileApisANSI", (SYSCALL)AreFileApisANSI, 0 },
#else
{ "AreFileApisANSI", (SYSCALL)0, 0 },
@@ -41129,7 +49335,7 @@ static struct win_syscall {
#define osCreateFileA ((HANDLE(WINAPI*)(LPCSTR,DWORD,DWORD, \
LPSECURITY_ATTRIBUTES,DWORD,DWORD,HANDLE))aSyscall[4].pCurrent)
-#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE)
+#if defined(SQLITE_WIN32_HAS_WIDE)
{ "CreateFileW", (SYSCALL)CreateFileW, 0 },
#else
{ "CreateFileW", (SYSCALL)0, 0 },
@@ -41138,7 +49344,7 @@ static struct win_syscall {
#define osCreateFileW ((HANDLE(WINAPI*)(LPCWSTR,DWORD,DWORD, \
LPSECURITY_ATTRIBUTES,DWORD,DWORD,HANDLE))aSyscall[5].pCurrent)
-#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_ANSI) && \
+#if defined(SQLITE_WIN32_HAS_ANSI) && \
(!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0) && \
SQLITE_WIN32_CREATEFILEMAPPINGA
{ "CreateFileMappingA", (SYSCALL)CreateFileMappingA, 0 },
@@ -41149,8 +49355,8 @@ static struct win_syscall {
#define osCreateFileMappingA ((HANDLE(WINAPI*)(HANDLE,LPSECURITY_ATTRIBUTES, \
DWORD,DWORD,DWORD,LPCSTR))aSyscall[6].pCurrent)
-#if SQLITE_OS_WINCE || (!SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) && \
- (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0))
+#if (SQLITE_OS_WINCE || defined(SQLITE_WIN32_HAS_WIDE)) && \
+ (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0)
{ "CreateFileMappingW", (SYSCALL)CreateFileMappingW, 0 },
#else
{ "CreateFileMappingW", (SYSCALL)0, 0 },
@@ -41159,7 +49365,7 @@ static struct win_syscall {
#define osCreateFileMappingW ((HANDLE(WINAPI*)(HANDLE,LPSECURITY_ATTRIBUTES, \
DWORD,DWORD,DWORD,LPCWSTR))aSyscall[7].pCurrent)
-#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE)
+#if defined(SQLITE_WIN32_HAS_WIDE)
{ "CreateMutexW", (SYSCALL)CreateMutexW, 0 },
#else
{ "CreateMutexW", (SYSCALL)0, 0 },
@@ -41190,7 +49396,7 @@ static struct win_syscall {
{ "FileTimeToLocalFileTime", (SYSCALL)0, 0 },
#endif
-#define osFileTimeToLocalFileTime ((BOOL(WINAPI*)(CONST FILETIME*, \
+#define osFileTimeToLocalFileTime ((BOOL(WINAPI*)(const FILETIME*, \
LPFILETIME))aSyscall[11].pCurrent)
#if SQLITE_OS_WINCE
@@ -41199,7 +49405,7 @@ static struct win_syscall {
{ "FileTimeToSystemTime", (SYSCALL)0, 0 },
#endif
-#define osFileTimeToSystemTime ((BOOL(WINAPI*)(CONST FILETIME*, \
+#define osFileTimeToSystemTime ((BOOL(WINAPI*)(const FILETIME*, \
LPSYSTEMTIME))aSyscall[12].pCurrent)
{ "FlushFileBuffers", (SYSCALL)FlushFileBuffers, 0 },
@@ -41245,7 +49451,7 @@ static struct win_syscall {
#define osGetDiskFreeSpaceA ((BOOL(WINAPI*)(LPCSTR,LPDWORD,LPDWORD,LPDWORD, \
LPDWORD))aSyscall[18].pCurrent)
-#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE)
+#if !SQLITE_OS_WINCE && defined(SQLITE_WIN32_HAS_WIDE)
{ "GetDiskFreeSpaceW", (SYSCALL)GetDiskFreeSpaceW, 0 },
#else
{ "GetDiskFreeSpaceW", (SYSCALL)0, 0 },
@@ -41262,7 +49468,7 @@ static struct win_syscall {
#define osGetFileAttributesA ((DWORD(WINAPI*)(LPCSTR))aSyscall[20].pCurrent)
-#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE)
+#if defined(SQLITE_WIN32_HAS_WIDE)
{ "GetFileAttributesW", (SYSCALL)GetFileAttributesW, 0 },
#else
{ "GetFileAttributesW", (SYSCALL)0, 0 },
@@ -41279,11 +49485,7 @@ static struct win_syscall {
#define osGetFileAttributesExW ((BOOL(WINAPI*)(LPCWSTR,GET_FILEEX_INFO_LEVELS, \
LPVOID))aSyscall[22].pCurrent)
-#if !SQLITE_OS_WINRT
{ "GetFileSize", (SYSCALL)GetFileSize, 0 },
-#else
- { "GetFileSize", (SYSCALL)0, 0 },
-#endif
#define osGetFileSize ((DWORD(WINAPI*)(HANDLE,LPDWORD))aSyscall[23].pCurrent)
@@ -41296,7 +49498,7 @@ static struct win_syscall {
#define osGetFullPathNameA ((DWORD(WINAPI*)(LPCSTR,DWORD,LPSTR, \
LPSTR*))aSyscall[24].pCurrent)
-#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE)
+#if !SQLITE_OS_WINCE && defined(SQLITE_WIN32_HAS_WIDE)
{ "GetFullPathNameW", (SYSCALL)GetFullPathNameW, 0 },
#else
{ "GetFullPathNameW", (SYSCALL)0, 0 },
@@ -41305,6 +49507,12 @@ static struct win_syscall {
#define osGetFullPathNameW ((DWORD(WINAPI*)(LPCWSTR,DWORD,LPWSTR, \
LPWSTR*))aSyscall[25].pCurrent)
+/*
+** For GetLastError(), MSDN says:
+**
+** Minimum supported client: Windows XP [desktop apps | UWP apps]
+** Minimum supported server: Windows Server 2003 [desktop apps | UWP apps]
+*/
{ "GetLastError", (SYSCALL)GetLastError, 0 },
#define osGetLastError ((DWORD(WINAPI*)(VOID))aSyscall[26].pCurrent)
@@ -41325,16 +49533,10 @@ static struct win_syscall {
#define osGetProcAddressA ((FARPROC(WINAPI*)(HMODULE, \
LPCSTR))aSyscall[27].pCurrent)
-#if !SQLITE_OS_WINRT
{ "GetSystemInfo", (SYSCALL)GetSystemInfo, 0 },
-#else
- { "GetSystemInfo", (SYSCALL)0, 0 },
-#endif
-
#define osGetSystemInfo ((VOID(WINAPI*)(LPSYSTEM_INFO))aSyscall[28].pCurrent)
{ "GetSystemTime", (SYSCALL)GetSystemTime, 0 },
-
#define osGetSystemTime ((VOID(WINAPI*)(LPSYSTEMTIME))aSyscall[29].pCurrent)
#if !SQLITE_OS_WINCE
@@ -41354,7 +49556,7 @@ static struct win_syscall {
#define osGetTempPathA ((DWORD(WINAPI*)(DWORD,LPSTR))aSyscall[31].pCurrent)
-#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE)
+#if defined(SQLITE_WIN32_HAS_WIDE)
{ "GetTempPathW", (SYSCALL)GetTempPathW, 0 },
#else
{ "GetTempPathW", (SYSCALL)0, 0 },
@@ -41362,11 +49564,7 @@ static struct win_syscall {
#define osGetTempPathW ((DWORD(WINAPI*)(DWORD,LPWSTR))aSyscall[32].pCurrent)
-#if !SQLITE_OS_WINRT
{ "GetTickCount", (SYSCALL)GetTickCount, 0 },
-#else
- { "GetTickCount", (SYSCALL)0, 0 },
-#endif
#define osGetTickCount ((DWORD(WINAPI*)(VOID))aSyscall[33].pCurrent)
@@ -41379,7 +49577,7 @@ static struct win_syscall {
#define osGetVersionExA ((BOOL(WINAPI*)( \
LPOSVERSIONINFOA))aSyscall[34].pCurrent)
-#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) && \
+#if defined(SQLITE_WIN32_HAS_WIDE) && \
SQLITE_WIN32_GETVERSIONEX
{ "GetVersionExW", (SYSCALL)GetVersionExW, 0 },
#else
@@ -41394,20 +49592,12 @@ static struct win_syscall {
#define osHeapAlloc ((LPVOID(WINAPI*)(HANDLE,DWORD, \
SIZE_T))aSyscall[36].pCurrent)
-#if !SQLITE_OS_WINRT
{ "HeapCreate", (SYSCALL)HeapCreate, 0 },
-#else
- { "HeapCreate", (SYSCALL)0, 0 },
-#endif
#define osHeapCreate ((HANDLE(WINAPI*)(DWORD,SIZE_T, \
SIZE_T))aSyscall[37].pCurrent)
-#if !SQLITE_OS_WINRT
{ "HeapDestroy", (SYSCALL)HeapDestroy, 0 },
-#else
- { "HeapDestroy", (SYSCALL)0, 0 },
-#endif
#define osHeapDestroy ((BOOL(WINAPI*)(HANDLE))aSyscall[38].pCurrent)
@@ -41425,16 +49615,12 @@ static struct win_syscall {
#define osHeapSize ((SIZE_T(WINAPI*)(HANDLE,DWORD, \
LPCVOID))aSyscall[41].pCurrent)
-#if !SQLITE_OS_WINRT
{ "HeapValidate", (SYSCALL)HeapValidate, 0 },
-#else
- { "HeapValidate", (SYSCALL)0, 0 },
-#endif
#define osHeapValidate ((BOOL(WINAPI*)(HANDLE,DWORD, \
LPCVOID))aSyscall[42].pCurrent)
-#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT
+#if !SQLITE_OS_WINCE
{ "HeapCompact", (SYSCALL)HeapCompact, 0 },
#else
{ "HeapCompact", (SYSCALL)0, 0 },
@@ -41450,7 +49636,7 @@ static struct win_syscall {
#define osLoadLibraryA ((HMODULE(WINAPI*)(LPCSTR))aSyscall[44].pCurrent)
-#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) && \
+#if defined(SQLITE_WIN32_HAS_WIDE) && \
!defined(SQLITE_OMIT_LOAD_EXTENSION)
{ "LoadLibraryW", (SYSCALL)LoadLibraryW, 0 },
#else
@@ -41459,21 +49645,17 @@ static struct win_syscall {
#define osLoadLibraryW ((HMODULE(WINAPI*)(LPCWSTR))aSyscall[45].pCurrent)
-#if !SQLITE_OS_WINRT
{ "LocalFree", (SYSCALL)LocalFree, 0 },
-#else
- { "LocalFree", (SYSCALL)0, 0 },
-#endif
#define osLocalFree ((HLOCAL(WINAPI*)(HLOCAL))aSyscall[46].pCurrent)
-#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT
+#if !SQLITE_OS_WINCE
{ "LockFile", (SYSCALL)LockFile, 0 },
#else
{ "LockFile", (SYSCALL)0, 0 },
#endif
-#ifndef osLockFile
+#if !defined(osLockFile) && defined(SQLITE_WIN32_HAS_ANSI)
#define osLockFile ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \
DWORD))aSyscall[47].pCurrent)
#endif
@@ -41489,8 +49671,7 @@ static struct win_syscall {
LPOVERLAPPED))aSyscall[48].pCurrent)
#endif
-#if SQLITE_OS_WINCE || (!SQLITE_OS_WINRT && \
- (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0))
+#if SQLITE_OS_WINCE || !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0
{ "MapViewOfFile", (SYSCALL)MapViewOfFile, 0 },
#else
{ "MapViewOfFile", (SYSCALL)0, 0 },
@@ -41518,35 +49699,27 @@ static struct win_syscall {
#define osSetEndOfFile ((BOOL(WINAPI*)(HANDLE))aSyscall[53].pCurrent)
-#if !SQLITE_OS_WINRT
{ "SetFilePointer", (SYSCALL)SetFilePointer, 0 },
-#else
- { "SetFilePointer", (SYSCALL)0, 0 },
-#endif
#define osSetFilePointer ((DWORD(WINAPI*)(HANDLE,LONG,PLONG, \
DWORD))aSyscall[54].pCurrent)
-#if !SQLITE_OS_WINRT
{ "Sleep", (SYSCALL)Sleep, 0 },
-#else
- { "Sleep", (SYSCALL)0, 0 },
-#endif
#define osSleep ((VOID(WINAPI*)(DWORD))aSyscall[55].pCurrent)
{ "SystemTimeToFileTime", (SYSCALL)SystemTimeToFileTime, 0 },
-#define osSystemTimeToFileTime ((BOOL(WINAPI*)(CONST SYSTEMTIME*, \
+#define osSystemTimeToFileTime ((BOOL(WINAPI*)(const SYSTEMTIME*, \
LPFILETIME))aSyscall[56].pCurrent)
-#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT
+#if !SQLITE_OS_WINCE
{ "UnlockFile", (SYSCALL)UnlockFile, 0 },
#else
{ "UnlockFile", (SYSCALL)0, 0 },
#endif
-#ifndef osUnlockFile
+#if !defined(osUnlockFile) && defined(SQLITE_WIN32_HAS_ANSI)
#define osUnlockFile ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \
DWORD))aSyscall[57].pCurrent)
#endif
@@ -41578,23 +49751,16 @@ static struct win_syscall {
#define osWriteFile ((BOOL(WINAPI*)(HANDLE,LPCVOID,DWORD,LPDWORD, \
LPOVERLAPPED))aSyscall[61].pCurrent)
-#if SQLITE_OS_WINRT
- { "CreateEventExW", (SYSCALL)CreateEventExW, 0 },
-#else
- { "CreateEventExW", (SYSCALL)0, 0 },
-#endif
-
-#define osCreateEventExW ((HANDLE(WINAPI*)(LPSECURITY_ATTRIBUTES,LPCWSTR, \
- DWORD,DWORD))aSyscall[62].pCurrent)
-
-#if !SQLITE_OS_WINRT
+/*
+** For WaitForSingleObject(), MSDN says:
+**
+** Minimum supported client: Windows XP [desktop apps | UWP apps]
+** Minimum supported server: Windows Server 2003 [desktop apps | UWP apps]
+*/
{ "WaitForSingleObject", (SYSCALL)WaitForSingleObject, 0 },
-#else
- { "WaitForSingleObject", (SYSCALL)0, 0 },
-#endif
#define osWaitForSingleObject ((DWORD(WINAPI*)(HANDLE, \
- DWORD))aSyscall[63].pCurrent)
+ DWORD))aSyscall[62].pCurrent)
#if !SQLITE_OS_WINCE
{ "WaitForSingleObjectEx", (SYSCALL)WaitForSingleObjectEx, 0 },
@@ -41603,146 +49769,169 @@ static struct win_syscall {
#endif
#define osWaitForSingleObjectEx ((DWORD(WINAPI*)(HANDLE,DWORD, \
- BOOL))aSyscall[64].pCurrent)
+ BOOL))aSyscall[63].pCurrent)
+
+ { "GetNativeSystemInfo", (SYSCALL)0, 0 },
+ /* ^^^^^^^^^^^^^^^^^^^----------------^------- placeholder only */
-#if SQLITE_OS_WINRT
- { "SetFilePointerEx", (SYSCALL)SetFilePointerEx, 0 },
+#if defined(SQLITE_WIN32_HAS_ANSI)
+ { "OutputDebugStringA", (SYSCALL)OutputDebugStringA, 0 },
#else
- { "SetFilePointerEx", (SYSCALL)0, 0 },
+ { "OutputDebugStringA", (SYSCALL)0, 0 },
#endif
-#define osSetFilePointerEx ((BOOL(WINAPI*)(HANDLE,LARGE_INTEGER, \
- PLARGE_INTEGER,DWORD))aSyscall[65].pCurrent)
+#define osOutputDebugStringA ((VOID(WINAPI*)(LPCSTR))aSyscall[65].pCurrent)
-#if SQLITE_OS_WINRT
- { "GetFileInformationByHandleEx", (SYSCALL)GetFileInformationByHandleEx, 0 },
+#if defined(SQLITE_WIN32_HAS_WIDE)
+ { "OutputDebugStringW", (SYSCALL)OutputDebugStringW, 0 },
#else
- { "GetFileInformationByHandleEx", (SYSCALL)0, 0 },
+ { "OutputDebugStringW", (SYSCALL)0, 0 },
#endif
-#define osGetFileInformationByHandleEx ((BOOL(WINAPI*)(HANDLE, \
- FILE_INFO_BY_HANDLE_CLASS,LPVOID,DWORD))aSyscall[66].pCurrent)
+#define osOutputDebugStringW ((VOID(WINAPI*)(LPCWSTR))aSyscall[66].pCurrent)
+
+ { "GetProcessHeap", (SYSCALL)GetProcessHeap, 0 },
+
+#define osGetProcessHeap ((HANDLE(WINAPI*)(VOID))aSyscall[67].pCurrent)
+
+/*
+** NOTE: On some sub-platforms, the InterlockedCompareExchange "function"
+** is really just a macro that uses a compiler intrinsic (e.g. x64).
+** So do not try to make this is into a redefinable interface.
+*/
+#if defined(InterlockedCompareExchange)
+ { "InterlockedCompareExchange", (SYSCALL)0, 0 },
-#if SQLITE_OS_WINRT && (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0)
- { "MapViewOfFileFromApp", (SYSCALL)MapViewOfFileFromApp, 0 },
+#define osInterlockedCompareExchange InterlockedCompareExchange
#else
- { "MapViewOfFileFromApp", (SYSCALL)0, 0 },
-#endif
+ { "InterlockedCompareExchange", (SYSCALL)InterlockedCompareExchange, 0 },
-#define osMapViewOfFileFromApp ((LPVOID(WINAPI*)(HANDLE,ULONG,ULONG64, \
- SIZE_T))aSyscall[67].pCurrent)
+#define osInterlockedCompareExchange ((LONG(WINAPI*)(LONG \
+ SQLITE_WIN32_VOLATILE*, LONG,LONG))aSyscall[68].pCurrent)
+#endif /* defined(InterlockedCompareExchange) */
-#if SQLITE_OS_WINRT
- { "CreateFile2", (SYSCALL)CreateFile2, 0 },
+#if !SQLITE_OS_WINCE && SQLITE_WIN32_USE_UUID
+ { "UuidCreate", (SYSCALL)UuidCreate, 0 },
#else
- { "CreateFile2", (SYSCALL)0, 0 },
+ { "UuidCreate", (SYSCALL)0, 0 },
#endif
-#define osCreateFile2 ((HANDLE(WINAPI*)(LPCWSTR,DWORD,DWORD,DWORD, \
- LPCREATEFILE2_EXTENDED_PARAMETERS))aSyscall[68].pCurrent)
+#define osUuidCreate ((RPC_STATUS(RPC_ENTRY*)(UUID*))aSyscall[69].pCurrent)
-#if SQLITE_OS_WINRT && !defined(SQLITE_OMIT_LOAD_EXTENSION)
- { "LoadPackagedLibrary", (SYSCALL)LoadPackagedLibrary, 0 },
+#if !SQLITE_OS_WINCE && SQLITE_WIN32_USE_UUID
+ { "UuidCreateSequential", (SYSCALL)UuidCreateSequential, 0 },
#else
- { "LoadPackagedLibrary", (SYSCALL)0, 0 },
+ { "UuidCreateSequential", (SYSCALL)0, 0 },
#endif
-#define osLoadPackagedLibrary ((HMODULE(WINAPI*)(LPCWSTR, \
- DWORD))aSyscall[69].pCurrent)
+#define osUuidCreateSequential \
+ ((RPC_STATUS(RPC_ENTRY*)(UUID*))aSyscall[70].pCurrent)
-#if SQLITE_OS_WINRT
- { "GetTickCount64", (SYSCALL)GetTickCount64, 0 },
+#if !defined(SQLITE_NO_SYNC) && SQLITE_MAX_MMAP_SIZE>0
+ { "FlushViewOfFile", (SYSCALL)FlushViewOfFile, 0 },
#else
- { "GetTickCount64", (SYSCALL)0, 0 },
+ { "FlushViewOfFile", (SYSCALL)0, 0 },
#endif
-#define osGetTickCount64 ((ULONGLONG(WINAPI*)(VOID))aSyscall[70].pCurrent)
+#define osFlushViewOfFile \
+ ((BOOL(WINAPI*)(LPCVOID,SIZE_T))aSyscall[71].pCurrent)
-#if SQLITE_OS_WINRT
- { "GetNativeSystemInfo", (SYSCALL)GetNativeSystemInfo, 0 },
+/*
+** If SQLITE_ENABLE_SETLK_TIMEOUT is defined, we require CreateEvent()
+** to implement blocking locks with timeouts. MSDN says:
+**
+** Minimum supported client: Windows XP [desktop apps | UWP apps]
+** Minimum supported server: Windows Server 2003 [desktop apps | UWP apps]
+*/
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+ { "CreateEvent", (SYSCALL)CreateEvent, 0 },
#else
- { "GetNativeSystemInfo", (SYSCALL)0, 0 },
+ { "CreateEvent", (SYSCALL)0, 0 },
#endif
-#define osGetNativeSystemInfo ((VOID(WINAPI*)( \
- LPSYSTEM_INFO))aSyscall[71].pCurrent)
+#define osCreateEvent ( \
+ (HANDLE(WINAPI*) (LPSECURITY_ATTRIBUTES,BOOL,BOOL,LPCSTR)) \
+ aSyscall[72].pCurrent \
+)
-#if defined(SQLITE_WIN32_HAS_ANSI)
- { "OutputDebugStringA", (SYSCALL)OutputDebugStringA, 0 },
+/*
+** If SQLITE_ENABLE_SETLK_TIMEOUT is defined, we require CancelIo()
+** for the case where a timeout expires and a lock request must be
+** cancelled.
+**
+** Minimum supported client: Windows XP [desktop apps | UWP apps]
+** Minimum supported server: Windows Server 2003 [desktop apps | UWP apps]
+*/
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+ { "CancelIo", (SYSCALL)CancelIo, 0 },
#else
- { "OutputDebugStringA", (SYSCALL)0, 0 },
+ { "CancelIo", (SYSCALL)0, 0 },
#endif
-#define osOutputDebugStringA ((VOID(WINAPI*)(LPCSTR))aSyscall[72].pCurrent)
+#define osCancelIo ((BOOL(WINAPI*)(HANDLE))aSyscall[73].pCurrent)
-#if defined(SQLITE_WIN32_HAS_WIDE)
- { "OutputDebugStringW", (SYSCALL)OutputDebugStringW, 0 },
+#if defined(SQLITE_WIN32_HAS_WIDE) && defined(_WIN32)
+ { "GetModuleHandleW", (SYSCALL)GetModuleHandleW, 0 },
#else
- { "OutputDebugStringW", (SYSCALL)0, 0 },
+ { "GetModuleHandleW", (SYSCALL)0, 0 },
#endif
-#define osOutputDebugStringW ((VOID(WINAPI*)(LPCWSTR))aSyscall[73].pCurrent)
+#define osGetModuleHandleW ((HMODULE(WINAPI*)(LPCWSTR))aSyscall[74].pCurrent)
- { "GetProcessHeap", (SYSCALL)GetProcessHeap, 0 },
+#ifndef _WIN32
+ { "getenv", (SYSCALL)getenv, 0 },
+#else
+ { "getenv", (SYSCALL)0, 0 },
+#endif
-#define osGetProcessHeap ((HANDLE(WINAPI*)(VOID))aSyscall[74].pCurrent)
+#define osGetenv ((const char *(*)(const char *))aSyscall[75].pCurrent)
-#if SQLITE_OS_WINRT && (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0)
- { "CreateFileMappingFromApp", (SYSCALL)CreateFileMappingFromApp, 0 },
+#ifndef _WIN32
+ { "getcwd", (SYSCALL)getcwd, 0 },
#else
- { "CreateFileMappingFromApp", (SYSCALL)0, 0 },
+ { "getcwd", (SYSCALL)0, 0 },
#endif
-#define osCreateFileMappingFromApp ((HANDLE(WINAPI*)(HANDLE, \
- LPSECURITY_ATTRIBUTES,ULONG,ULONG64,LPCWSTR))aSyscall[75].pCurrent)
-
-/*
-** NOTE: On some sub-platforms, the InterlockedCompareExchange "function"
-** is really just a macro that uses a compiler intrinsic (e.g. x64).
-** So do not try to make this is into a redefinable interface.
-*/
-#if defined(InterlockedCompareExchange)
- { "InterlockedCompareExchange", (SYSCALL)0, 0 },
+#define osGetcwd ((char*(*)(char*,size_t))aSyscall[76].pCurrent)
-#define osInterlockedCompareExchange InterlockedCompareExchange
+#ifndef _WIN32
+ { "readlink", (SYSCALL)readlink, 0 },
#else
- { "InterlockedCompareExchange", (SYSCALL)InterlockedCompareExchange, 0 },
+ { "readlink", (SYSCALL)0, 0 },
+#endif
-#define osInterlockedCompareExchange ((LONG(WINAPI*)(LONG \
- SQLITE_WIN32_VOLATILE*, LONG,LONG))aSyscall[76].pCurrent)
-#endif /* defined(InterlockedCompareExchange) */
+#define osReadlink ((ssize_t(*)(const char*,char*,size_t))aSyscall[77].pCurrent)
-#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && SQLITE_WIN32_USE_UUID
- { "UuidCreate", (SYSCALL)UuidCreate, 0 },
+#ifndef _WIN32
+ { "lstat", (SYSCALL)lstat, 0 },
#else
- { "UuidCreate", (SYSCALL)0, 0 },
+ { "lstat", (SYSCALL)0, 0 },
#endif
-#define osUuidCreate ((RPC_STATUS(RPC_ENTRY*)(UUID*))aSyscall[77].pCurrent)
+#define osLstat ((int(*)(const char*,struct stat*))aSyscall[78].pCurrent)
-#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && SQLITE_WIN32_USE_UUID
- { "UuidCreateSequential", (SYSCALL)UuidCreateSequential, 0 },
+#ifndef _WIN32
+ { "__errno", (SYSCALL)__errno, 0 },
#else
- { "UuidCreateSequential", (SYSCALL)0, 0 },
+ { "__errno", (SYSCALL)0, 0 },
#endif
-#define osUuidCreateSequential \
- ((RPC_STATUS(RPC_ENTRY*)(UUID*))aSyscall[78].pCurrent)
+#define osErrno (*((int*(*)(void))aSyscall[79].pCurrent)())
-#if !defined(SQLITE_NO_SYNC) && SQLITE_MAX_MMAP_SIZE>0
- { "FlushViewOfFile", (SYSCALL)FlushViewOfFile, 0 },
+#ifndef _WIN32
+ { "cygwin_conv_path", (SYSCALL)cygwin_conv_path, 0 },
#else
- { "FlushViewOfFile", (SYSCALL)0, 0 },
+ { "cygwin_conv_path", (SYSCALL)0, 0 },
#endif
-#define osFlushViewOfFile \
- ((BOOL(WINAPI*)(LPCVOID,SIZE_T))aSyscall[79].pCurrent)
+#define osCygwin_conv_path ((size_t(*)(unsigned int, \
+ const void *, void *, size_t))aSyscall[80].pCurrent)
}; /* End of the overrideable system calls */
/*
** This is the xSetSystemCall() method of sqlite3_vfs for all of the
-** "win32" VFSes. Return SQLITE_OK opon successfully updating the
+** "win32" VFSes. Return SQLITE_OK upon successfully updating the
** system call pointer, or SQLITE_NOTFOUND if there is no configurable
** system call named zName.
*/
@@ -41840,10 +50029,10 @@ SQLITE_API int sqlite3_win32_compact_heap(LPUINT pnLargest){
hHeap = winMemGetHeap();
assert( hHeap!=0 );
assert( hHeap!=INVALID_HANDLE_VALUE );
-#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE)
+#if defined(SQLITE_WIN32_MALLOC_VALIDATE)
assert( osHeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) );
#endif
-#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT
+#if !SQLITE_OS_WINCE
if( (nLargest=osHeapCompact(hHeap, SQLITE_WIN32_HEAP_FLAGS))==0 ){
DWORD lastErrno = osGetLastError();
if( lastErrno==NO_ERROR ){
@@ -41873,17 +50062,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.
@@ -41906,11 +50095,12 @@ 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 */
+#ifdef _WIN32
/*
** This function outputs the specified (ANSI) string to the Win32 debugger
** (if available).
@@ -41953,29 +50143,13 @@ SQLITE_API void sqlite3_win32_write_debug(const char *zBuf, int nBuf){
}
#endif
}
-
-/*
-** The following routine suspends the current thread for at least ms
-** milliseconds. This is equivalent to the Win32 Sleep() interface.
-*/
-#if SQLITE_OS_WINRT
-static HANDLE sleepObj = NULL;
-#endif
+#endif /* _WIN32 */
SQLITE_API void sqlite3_win32_sleep(DWORD milliseconds){
-#if SQLITE_OS_WINRT
- if ( sleepObj==NULL ){
- sleepObj = osCreateEventExW(NULL, NULL, CREATE_EVENT_MANUAL_RESET,
- SYNCHRONIZE);
- }
- assert( sleepObj!=NULL );
- osWaitForSingleObjectEx(sleepObj, milliseconds, FALSE);
-#else
osSleep(milliseconds);
-#endif
}
-#if SQLITE_MAX_WORKER_THREADS>0 && !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && \
+#if SQLITE_MAX_WORKER_THREADS>0 && !SQLITE_OS_WINCE && \
SQLITE_THREADSAFE>0
SQLITE_PRIVATE DWORD sqlite3Win32Wait(HANDLE hObject){
DWORD rc;
@@ -41999,7 +50173,7 @@ SQLITE_PRIVATE DWORD sqlite3Win32Wait(HANDLE hObject){
#if !SQLITE_WIN32_GETVERSIONEX
# define osIsNT() (1)
-#elif SQLITE_OS_WINCE || SQLITE_OS_WINRT || !defined(SQLITE_WIN32_HAS_ANSI)
+#elif SQLITE_OS_WINCE || !defined(SQLITE_WIN32_HAS_ANSI)
# define osIsNT() (1)
#elif !defined(SQLITE_WIN32_HAS_WIDE)
# define osIsNT() (0)
@@ -42012,13 +50186,7 @@ SQLITE_PRIVATE DWORD sqlite3Win32Wait(HANDLE hObject){
** based on the NT kernel.
*/
SQLITE_API int sqlite3_win32_is_nt(void){
-#if SQLITE_OS_WINRT
- /*
- ** NOTE: The WinRT sub-platform is always assumed to be based on the NT
- ** kernel.
- */
- return 1;
-#elif SQLITE_WIN32_GETVERSIONEX
+#if SQLITE_WIN32_GETVERSIONEX
if( osInterlockedCompareExchange(&sqlite3_os_type, 0, 0)==0 ){
#if defined(SQLITE_WIN32_HAS_ANSI)
OSVERSIONINFOA sInfo;
@@ -42036,7 +50204,9 @@ SQLITE_API int sqlite3_win32_is_nt(void){
}
return osInterlockedCompareExchange(&sqlite3_os_type, 2, 2)==2;
#elif SQLITE_TEST
- return osInterlockedCompareExchange(&sqlite3_os_type, 2, 2)==2;
+ return osInterlockedCompareExchange(&sqlite3_os_type, 2, 2)==2
+ || osInterlockedCompareExchange(&sqlite3_os_type, 0, 0)==0
+ ;
#else
/*
** NOTE: All sub-platforms where the GetVersionEx[AW] functions are
@@ -42058,7 +50228,7 @@ static void *winMemMalloc(int nBytes){
hHeap = winMemGetHeap();
assert( hHeap!=0 );
assert( hHeap!=INVALID_HANDLE_VALUE );
-#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE)
+#if defined(SQLITE_WIN32_MALLOC_VALIDATE)
assert( osHeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) );
#endif
assert( nBytes>=0 );
@@ -42080,7 +50250,7 @@ static void winMemFree(void *pPrior){
hHeap = winMemGetHeap();
assert( hHeap!=0 );
assert( hHeap!=INVALID_HANDLE_VALUE );
-#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE)
+#if defined(SQLITE_WIN32_MALLOC_VALIDATE)
assert( osHeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior) );
#endif
if( !pPrior ) return; /* Passing NULL to HeapFree is undefined. */
@@ -42101,7 +50271,7 @@ static void *winMemRealloc(void *pPrior, int nBytes){
hHeap = winMemGetHeap();
assert( hHeap!=0 );
assert( hHeap!=INVALID_HANDLE_VALUE );
-#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE)
+#if defined(SQLITE_WIN32_MALLOC_VALIDATE)
assert( osHeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior) );
#endif
assert( nBytes>=0 );
@@ -42129,7 +50299,7 @@ static int winMemSize(void *p){
hHeap = winMemGetHeap();
assert( hHeap!=0 );
assert( hHeap!=INVALID_HANDLE_VALUE );
-#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE)
+#if defined(SQLITE_WIN32_MALLOC_VALIDATE)
assert( osHeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, p) );
#endif
if( !p ) return 0;
@@ -42159,7 +50329,7 @@ static int winMemInit(void *pAppData){
assert( pWinMemData->magic1==WINMEM_MAGIC1 );
assert( pWinMemData->magic2==WINMEM_MAGIC2 );
-#if !SQLITE_OS_WINRT && SQLITE_WIN32_HEAP_CREATE
+#if SQLITE_WIN32_HEAP_CREATE
if( !pWinMemData->hHeap ){
DWORD dwInitialSize = SQLITE_WIN32_HEAP_INIT_SIZE;
DWORD dwMaximumSize = (DWORD)sqlite3GlobalConfig.nHeap;
@@ -42192,7 +50362,7 @@ static int winMemInit(void *pAppData){
#endif
assert( pWinMemData->hHeap!=0 );
assert( pWinMemData->hHeap!=INVALID_HANDLE_VALUE );
-#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE)
+#if defined(SQLITE_WIN32_MALLOC_VALIDATE)
assert( osHeapValidate(pWinMemData->hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) );
#endif
return SQLITE_OK;
@@ -42210,7 +50380,7 @@ static void winMemShutdown(void *pAppData){
if( pWinMemData->hHeap ){
assert( pWinMemData->hHeap!=INVALID_HANDLE_VALUE );
-#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE)
+#if defined(SQLITE_WIN32_MALLOC_VALIDATE)
assert( osHeapValidate(pWinMemData->hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) );
#endif
if( pWinMemData->bOwned ){
@@ -42251,6 +50421,7 @@ SQLITE_PRIVATE void sqlite3MemSetDefault(void){
}
#endif /* SQLITE_WIN32_MALLOC */
+#ifdef _WIN32
/*
** Convert a UTF-8 string to Microsoft Unicode.
**
@@ -42276,6 +50447,7 @@ static LPWSTR winUtf8ToUnicode(const char *zText){
}
return zWideText;
}
+#endif /* _WIN32 */
/*
** Convert a Microsoft Unicode string to UTF-8.
@@ -42310,28 +50482,29 @@ static char *winUnicodeToUtf8(LPCWSTR zWideText){
** Space to hold the returned string is obtained from sqlite3_malloc().
*/
static LPWSTR winMbcsToUnicode(const char *zText, int useAnsi){
- int nByte;
+ int nWideChar;
LPWSTR zMbcsText;
int codepage = useAnsi ? CP_ACP : CP_OEMCP;
- nByte = osMultiByteToWideChar(codepage, 0, zText, -1, NULL,
- 0)*sizeof(WCHAR);
- if( nByte==0 ){
+ nWideChar = osMultiByteToWideChar(codepage, 0, zText, -1, NULL,
+ 0);
+ if( nWideChar==0 ){
return 0;
}
- zMbcsText = sqlite3MallocZero( nByte*sizeof(WCHAR) );
+ zMbcsText = sqlite3MallocZero( nWideChar*sizeof(WCHAR) );
if( zMbcsText==0 ){
return 0;
}
- nByte = osMultiByteToWideChar(codepage, 0, zText, -1, zMbcsText,
- nByte);
- if( nByte==0 ){
+ nWideChar = osMultiByteToWideChar(codepage, 0, zText, -1, zMbcsText,
+ nWideChar);
+ if( nWideChar==0 ){
sqlite3_free(zMbcsText);
zMbcsText = 0;
}
return zMbcsText;
}
+#ifdef _WIN32
/*
** Convert a Microsoft Unicode string to a multi-byte character string,
** using the ANSI or OEM code page.
@@ -42359,6 +50532,7 @@ static char *winUnicodeToMbcs(LPCWSTR zWideText, int useAnsi){
}
return zText;
}
+#endif /* _WIN32 */
/*
** Convert a multi-byte character string to UTF-8.
@@ -42378,6 +50552,7 @@ static char *winMbcsToUtf8(const char *zText, int useAnsi){
return zTextUtf8;
}
+#ifdef _WIN32
/*
** Convert a UTF-8 string to a multi-byte character string.
**
@@ -42427,6 +50602,7 @@ SQLITE_API char *sqlite3_win32_unicode_to_utf8(LPCWSTR zWideText){
#endif
return winUnicodeToUtf8(zWideText);
}
+#endif /* _WIN32 */
/*
** This is a public wrapper for the winMbcsToUtf8() function.
@@ -42444,6 +50620,7 @@ SQLITE_API char *sqlite3_win32_mbcs_to_utf8(const char *zText){
return winMbcsToUtf8(zText, osAreFileApisANSI());
}
+#ifdef _WIN32
/*
** This is a public wrapper for the winMbcsToUtf8() function.
*/
@@ -42501,10 +50678,12 @@ SQLITE_API int sqlite3_win32_set_directory8(
const char *zValue /* New value for directory being set or reset */
){
char **ppDirectory = 0;
+ int rc;
#ifndef SQLITE_OMIT_AUTOINIT
- int rc = sqlite3_initialize();
+ rc = sqlite3_initialize();
if( rc ) return rc;
#endif
+ sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR));
if( type==SQLITE_WIN32_DATA_DIRECTORY_TYPE ){
ppDirectory = &sqlite3_data_directory;
}else if( type==SQLITE_WIN32_TEMP_DIRECTORY_TYPE ){
@@ -42519,14 +50698,19 @@ SQLITE_API int sqlite3_win32_set_directory8(
if( zValue && zValue[0] ){
zCopy = sqlite3_mprintf("%s", zValue);
if ( zCopy==0 ){
- return SQLITE_NOMEM_BKPT;
+ rc = SQLITE_NOMEM_BKPT;
+ goto set_directory8_done;
}
}
sqlite3_free(*ppDirectory);
*ppDirectory = zCopy;
- return SQLITE_OK;
+ rc = SQLITE_OK;
+ }else{
+ rc = SQLITE_ERROR;
}
- return SQLITE_ERROR;
+set_directory8_done:
+ sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR));
+ return rc;
}
/*
@@ -42561,6 +50745,7 @@ SQLITE_API int sqlite3_win32_set_directory(
){
return sqlite3_win32_set_directory16(type, zValue);
}
+#endif /* _WIN32 */
/*
** The return value of winGetLastErrorMsg
@@ -42576,17 +50761,6 @@ static int winGetLastErrorMsg(DWORD lastErrno, int nBuf, char *zBuf){
char *zOut = 0;
if( osIsNT() ){
-#if SQLITE_OS_WINRT
- WCHAR zTempWide[SQLITE_WIN32_MAX_ERRMSG_CHARS+1];
- dwLen = osFormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM |
- FORMAT_MESSAGE_IGNORE_INSERTS,
- NULL,
- lastErrno,
- 0,
- zTempWide,
- SQLITE_WIN32_MAX_ERRMSG_CHARS,
- 0);
-#else
LPWSTR zTempWide = NULL;
dwLen = osFormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
@@ -42597,16 +50771,13 @@ static int winGetLastErrorMsg(DWORD lastErrno, int nBuf, char *zBuf){
(LPWSTR) &zTempWide,
0,
0);
-#endif
if( dwLen > 0 ){
/* allocate a buffer and convert to UTF8 */
sqlite3BeginBenignMalloc();
zOut = winUnicodeToUtf8(zTempWide);
sqlite3EndBenignMalloc();
-#if !SQLITE_OS_WINRT
/* free the system buffer allocated by FormatMessage */
osLocalFree(zTempWide);
-#endif
}
}
#ifdef SQLITE_WIN32_HAS_ANSI
@@ -43109,13 +51280,100 @@ static BOOL winLockFile(
ovlp.Offset = offsetLow;
ovlp.OffsetHigh = offsetHigh;
return osLockFileEx(*phFile, flags, 0, numBytesLow, numBytesHigh, &ovlp);
+#ifdef SQLITE_WIN32_HAS_ANSI
}else{
return osLockFile(*phFile, offsetLow, offsetHigh, numBytesLow,
numBytesHigh);
+#endif
}
#endif
}
+#ifndef SQLITE_OMIT_WAL
+/*
+** Lock a region of nByte bytes starting at offset offset of file hFile.
+** Take an EXCLUSIVE lock if parameter bExclusive is true, or a SHARED lock
+** otherwise. If nMs is greater than zero and the lock cannot be obtained
+** immediately, block for that many ms before giving up.
+**
+** This function returns SQLITE_OK if the lock is obtained successfully. If
+** some other process holds the lock, SQLITE_BUSY is returned if nMs==0, or
+** SQLITE_BUSY_TIMEOUT otherwise. Or, if an error occurs, SQLITE_IOERR.
+*/
+static int winHandleLockTimeout(
+ HANDLE hFile,
+ DWORD offset,
+ DWORD nByte,
+ int bExcl,
+ DWORD nMs
+){
+ DWORD flags = LOCKFILE_FAIL_IMMEDIATELY | (bExcl?LOCKFILE_EXCLUSIVE_LOCK:0);
+ int rc = SQLITE_OK;
+ BOOL ret;
+
+ if( !osIsNT() ){
+ ret = winLockFile(&hFile, flags, offset, 0, nByte, 0);
+ }else{
+ OVERLAPPED ovlp;
+ memset(&ovlp, 0, sizeof(OVERLAPPED));
+ ovlp.Offset = offset;
+
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+ if( nMs!=0 ){
+ flags &= ~LOCKFILE_FAIL_IMMEDIATELY;
+ }
+ ovlp.hEvent = osCreateEvent(NULL, TRUE, FALSE, NULL);
+ if( ovlp.hEvent==NULL ){
+ return SQLITE_IOERR_LOCK;
+ }
+#endif
+
+ ret = osLockFileEx(hFile, flags, 0, nByte, 0, &ovlp);
+
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+ /* If SQLITE_ENABLE_SETLK_TIMEOUT is defined, then the file-handle was
+ ** opened with FILE_FLAG_OVERHEAD specified. In this case, the call to
+ ** LockFileEx() may fail because the request is still pending. This can
+ ** happen even if LOCKFILE_FAIL_IMMEDIATELY was specified.
+ **
+ ** If nMs is 0, then LOCKFILE_FAIL_IMMEDIATELY was set in the flags
+ ** passed to LockFileEx(). In this case, if the operation is pending,
+ ** block indefinitely until it is finished.
+ **
+ ** Otherwise, wait for up to nMs ms for the operation to finish. nMs
+ ** may be set to INFINITE.
+ */
+ if( !ret && GetLastError()==ERROR_IO_PENDING ){
+ DWORD nDelay = (nMs==0 ? INFINITE : nMs);
+ DWORD res = osWaitForSingleObject(ovlp.hEvent, nDelay);
+ if( res==WAIT_OBJECT_0 ){
+ ret = TRUE;
+ }else if( res==WAIT_TIMEOUT ){
+#if SQLITE_ENABLE_SETLK_TIMEOUT==1
+ rc = SQLITE_BUSY_TIMEOUT;
+#else
+ rc = SQLITE_BUSY;
+#endif
+ }else{
+ /* Some other error has occurred */
+ rc = SQLITE_IOERR_LOCK;
+ }
+
+ /* If it is still pending, cancel the LockFileEx() call. */
+ osCancelIo(hFile);
+ }
+
+ osCloseHandle(ovlp.hEvent);
+#endif
+ }
+
+ if( rc==SQLITE_OK && !ret ){
+ rc = SQLITE_BUSY;
+ }
+ return rc;
+}
+#endif /* #ifndef SQLITE_OMIT_WAL */
+
/*
** Unlock a file region.
*/
@@ -43140,13 +51398,25 @@ static BOOL winUnlockFile(
ovlp.Offset = offsetLow;
ovlp.OffsetHigh = offsetHigh;
return osUnlockFileEx(*phFile, 0, numBytesLow, numBytesHigh, &ovlp);
+#ifdef SQLITE_WIN32_HAS_ANSI
}else{
return osUnlockFile(*phFile, offsetLow, offsetHigh, numBytesLow,
numBytesHigh);
+#endif
}
#endif
}
+#ifndef SQLITE_OMIT_WAL
+/*
+** Remove an nByte lock starting at offset iOff from HANDLE h.
+*/
+static int winHandleUnlock(HANDLE h, int iOff, int nByte){
+ BOOL ret = winUnlockFile(&h, iOff, 0, nByte, 0);
+ return (ret ? SQLITE_OK : SQLITE_IOERR_UNLOCK);
+}
+#endif
+
/*****************************************************************************
** The next group of routines implement the I/O methods specified
** by the sqlite3_io_methods object.
@@ -43160,66 +51430,56 @@ static BOOL winUnlockFile(
#endif
/*
-** Move the current position of the file handle passed as the first
-** argument to offset iOffset within the file. If successful, return 0.
-** Otherwise, set pFile->lastErrno and return non-zero.
+** Seek the file handle h to offset nByte of the file.
+**
+** If successful, return SQLITE_OK. Or, if an error occurs, return an SQLite
+** error code.
*/
-static int winSeekFile(winFile *pFile, sqlite3_int64 iOffset){
-#if !SQLITE_OS_WINRT
+static int winHandleSeek(HANDLE h, sqlite3_int64 iOffset){
+ int rc = SQLITE_OK; /* Return value */
+
LONG upperBits; /* Most sig. 32 bits of new offset */
LONG lowerBits; /* Least sig. 32 bits of new offset */
DWORD dwRet; /* Value returned by SetFilePointer() */
- DWORD lastErrno; /* Value returned by GetLastError() */
-
- OSTRACE(("SEEK file=%p, offset=%lld\n", pFile->h, iOffset));
upperBits = (LONG)((iOffset>>32) & 0x7fffffff);
lowerBits = (LONG)(iOffset & 0xffffffff);
+ dwRet = osSetFilePointer(h, lowerBits, &upperBits, FILE_BEGIN);
+
/* API oddity: If successful, SetFilePointer() returns a dword
** containing the lower 32-bits of the new file-offset. Or, if it fails,
** it returns INVALID_SET_FILE_POINTER. However according to MSDN,
** INVALID_SET_FILE_POINTER may also be a valid new offset. So to determine
** whether an error has actually occurred, it is also necessary to call
- ** GetLastError().
- */
- dwRet = osSetFilePointer(pFile->h, lowerBits, &upperBits, FILE_BEGIN);
-
- if( (dwRet==INVALID_SET_FILE_POINTER
- && ((lastErrno = osGetLastError())!=NO_ERROR)) ){
- pFile->lastErrno = lastErrno;
- winLogError(SQLITE_IOERR_SEEK, pFile->lastErrno,
- "winSeekFile", pFile->zPath);
- OSTRACE(("SEEK file=%p, rc=SQLITE_IOERR_SEEK\n", pFile->h));
- return 1;
+ ** GetLastError(). */
+ if( dwRet==INVALID_SET_FILE_POINTER ){
+ DWORD lastErrno = osGetLastError();
+ if( lastErrno!=NO_ERROR ){
+ rc = SQLITE_IOERR_SEEK;
+ }
}
+ OSTRACE(("SEEK file=%p, offset=%lld rc=%s\n", h, iOffset,sqlite3ErrName(rc)));
+ return rc;
+}
- OSTRACE(("SEEK file=%p, rc=SQLITE_OK\n", pFile->h));
- return 0;
-#else
- /*
- ** Same as above, except that this implementation works for WinRT.
- */
-
- LARGE_INTEGER x; /* The new offset */
- BOOL bRet; /* Value returned by SetFilePointerEx() */
-
- x.QuadPart = iOffset;
- bRet = osSetFilePointerEx(pFile->h, x, 0, FILE_BEGIN);
+/*
+** Move the current position of the file handle passed as the first
+** argument to offset iOffset within the file. If successful, return 0.
+** Otherwise, set pFile->lastErrno and return non-zero.
+*/
+static int winSeekFile(winFile *pFile, sqlite3_int64 iOffset){
+ int rc;
- if(!bRet){
+ rc = winHandleSeek(pFile->h, iOffset);
+ if( rc!=SQLITE_OK ){
pFile->lastErrno = osGetLastError();
- winLogError(SQLITE_IOERR_SEEK, pFile->lastErrno,
- "winSeekFile", pFile->zPath);
- OSTRACE(("SEEK file=%p, rc=SQLITE_IOERR_SEEK\n", pFile->h));
- return 1;
+ winLogError(rc, pFile->lastErrno, "winSeekFile", pFile->zPath);
}
-
- OSTRACE(("SEEK file=%p, rc=SQLITE_OK\n", pFile->h));
- return 0;
-#endif
+ return rc;
}
+
#if SQLITE_MAX_MMAP_SIZE>0
/* Forward references to VFS helper methods used for memory mapped files */
static int winMapfile(winFile*, sqlite3_int64);
@@ -43315,7 +51575,7 @@ static int winRead(
pFile->h, pBuf, amt, offset, pFile->locktype));
#if SQLITE_MAX_MMAP_SIZE>0
- /* Deal with as much of this read request as possible by transfering
+ /* Deal with as much of this read request as possible by transferring
** data from the memory mapping using memcpy(). */
if( offsetmmapSize ){
if( offset+amt <= pFile->mmapSize ){
@@ -43393,7 +51653,7 @@ static int winWrite(
pFile->h, pBuf, amt, offset, pFile->locktype));
#if defined(SQLITE_MMAP_READWRITE) && SQLITE_MAX_MMAP_SIZE>0
- /* Deal with as much of this write request as possible by transfering
+ /* Deal with as much of this write request as possible by transferring
** data from the memory mapping using memcpy(). */
if( offsetmmapSize ){
if( offset+amt <= pFile->mmapSize ){
@@ -43479,6 +51739,49 @@ static int winWrite(
return SQLITE_OK;
}
+#ifndef SQLITE_OMIT_WAL
+/*
+** Truncate the file opened by handle h to nByte bytes in size.
+*/
+static int winHandleTruncate(HANDLE h, sqlite3_int64 nByte){
+ int rc = SQLITE_OK; /* Return code */
+ rc = winHandleSeek(h, nByte);
+ if( rc==SQLITE_OK ){
+ if( 0==osSetEndOfFile(h) ){
+ rc = SQLITE_IOERR_TRUNCATE;
+ }
+ }
+ return rc;
+}
+
+/*
+** Determine the size in bytes of the file opened by the handle passed as
+** the first argument.
+*/
+static int winHandleSize(HANDLE h, sqlite3_int64 *pnByte){
+ int rc = SQLITE_OK;
+ DWORD upperBits = 0;
+ DWORD lowerBits = 0;
+
+ assert( pnByte );
+ lowerBits = osGetFileSize(h, &upperBits);
+ *pnByte = (((sqlite3_int64)upperBits)<<32) + lowerBits;
+ if( lowerBits==INVALID_FILE_SIZE && osGetLastError()!=NO_ERROR ){
+ rc = SQLITE_IOERR_FSTAT;
+ }
+ return rc;
+}
+
+/*
+** Close the handle passed as the only argument.
+*/
+static void winHandleClose(HANDLE h){
+ if( h!=INVALID_HANDLE_VALUE ){
+ osCloseHandle(h);
+ }
+}
+#endif /* #ifndef SQLITE_OMIT_WAL */
+
/*
** Truncate an open file to a specified size
*/
@@ -43503,7 +51806,7 @@ static int winTruncate(sqlite3_file *id, sqlite3_int64 nByte){
** 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
+ ** now to simply make transactions a no-op if there are pending reads. We
** can maybe revisit this decision in the future.
*/
return SQLITE_OK;
@@ -43562,7 +51865,7 @@ static int winTruncate(sqlite3_file *id, sqlite3_int64 nByte){
#ifdef SQLITE_TEST
/*
** Count the number of fullsyncs and normal syncs. This is used to test
-** that syncs and fullsyncs are occuring at the right times.
+** that syncs and fullsyncs are occurring at the right times.
*/
SQLITE_API int sqlite3_sync_count = 0;
SQLITE_API int sqlite3_fullsync_count = 0;
@@ -43664,20 +51967,6 @@ static int winFileSize(sqlite3_file *id, sqlite3_int64 *pSize){
assert( pSize!=0 );
SimulateIOError(return SQLITE_IOERR_FSTAT);
OSTRACE(("SIZE file=%p, pSize=%p\n", pFile->h, pSize));
-
-#if SQLITE_OS_WINRT
- {
- FILE_STANDARD_INFO info;
- if( osGetFileInformationByHandleEx(pFile->h, FileStandardInfo,
- &info, sizeof(info)) ){
- *pSize = info.EndOfFile.QuadPart;
- }else{
- pFile->lastErrno = osGetLastError();
- rc = winLogError(SQLITE_IOERR_FSTAT, pFile->lastErrno,
- "winFileSize", pFile->zPath);
- }
- }
-#else
{
DWORD upperBits;
DWORD lowerBits;
@@ -43692,7 +51981,6 @@ static int winFileSize(sqlite3_file *id, sqlite3_int64 *pSize){
"winFileSize", pFile->zPath);
}
}
-#endif
OSTRACE(("SIZE file=%p, pSize=%p, *pSize=%lld, rc=%s\n",
pFile->h, pSize, *pSize, sqlite3ErrName(rc)));
return rc;
@@ -43734,8 +52022,9 @@ static int winFileSize(sqlite3_file *id, sqlite3_int64 *pSize){
** Different API routines are called depending on whether or not this
** is Win9x or WinNT.
*/
-static int winGetReadLock(winFile *pFile){
+static int winGetReadLock(winFile *pFile, int bBlock){
int res;
+ DWORD mask = ~(bBlock ? LOCKFILE_FAIL_IMMEDIATELY : 0);
OSTRACE(("READ-LOCK file=%p, lock=%d\n", pFile->h, pFile->locktype));
if( osIsNT() ){
#if SQLITE_OS_WINCE
@@ -43745,7 +52034,7 @@ static int winGetReadLock(winFile *pFile){
*/
res = winceLockFile(&pFile->h, SHARED_FIRST, 0, 1, 0);
#else
- res = winLockFile(&pFile->h, SQLITE_LOCKFILEEX_FLAGS, SHARED_FIRST, 0,
+ res = winLockFile(&pFile->h, SQLITE_LOCKFILEEX_FLAGS&mask, SHARED_FIRST, 0,
SHARED_SIZE, 0);
#endif
}
@@ -43754,7 +52043,7 @@ static int winGetReadLock(winFile *pFile){
int lk;
sqlite3_randomness(sizeof(lk), &lk);
pFile->sharedLockByte = (short)((lk & 0x7fffffff)%(SHARED_SIZE - 1));
- res = winLockFile(&pFile->h, SQLITE_LOCKFILE_FLAGS,
+ res = winLockFile(&pFile->h, SQLITE_LOCKFILE_FLAGS&mask,
SHARED_FIRST+pFile->sharedLockByte, 0, 1, 0);
}
#endif
@@ -43849,46 +52138,62 @@ static int winLock(sqlite3_file *id, int locktype){
assert( locktype!=PENDING_LOCK );
assert( locktype!=RESERVED_LOCK || pFile->locktype==SHARED_LOCK );
- /* Lock the PENDING_LOCK byte if we need to acquire a PENDING lock or
+ /* Lock the PENDING_LOCK byte if we need to acquire an EXCLUSIVE lock or
** a SHARED lock. If we are acquiring a SHARED lock, the acquisition of
** the PENDING_LOCK byte is temporary.
*/
newLocktype = pFile->locktype;
- if( pFile->locktype==NO_LOCK
- || (locktype==EXCLUSIVE_LOCK && pFile->locktype<=RESERVED_LOCK)
+ if( locktype==SHARED_LOCK
+ || (locktype==EXCLUSIVE_LOCK && pFile->locktype==RESERVED_LOCK)
){
int cnt = 3;
- while( cnt-->0 && (res = winLockFile(&pFile->h, SQLITE_LOCKFILE_FLAGS,
- PENDING_BYTE, 0, 1, 0))==0 ){
+
+ /* Flags for the LockFileEx() call. This should be an exclusive lock if
+ ** this call is to obtain EXCLUSIVE, or a shared lock if this call is to
+ ** obtain SHARED. */
+ int flags = LOCKFILE_FAIL_IMMEDIATELY;
+ if( locktype==EXCLUSIVE_LOCK ){
+ flags |= LOCKFILE_EXCLUSIVE_LOCK;
+ }
+ while( cnt>0 ){
/* Try 3 times to get the pending lock. This is needed to work
** around problems caused by indexing and/or anti-virus software on
** Windows systems.
+ **
** If you are using this code as a model for alternative VFSes, do not
- ** copy this retry logic. It is a hack intended for Windows only.
- */
+ ** copy this retry logic. It is a hack intended for Windows only. */
+ res = winLockFile(&pFile->h, flags, PENDING_BYTE, 0, 1, 0);
+ if( res ) break;
+
lastErrno = osGetLastError();
OSTRACE(("LOCK-PENDING-FAIL file=%p, count=%d, result=%d\n",
- pFile->h, cnt, res));
+ pFile->h, cnt, res
+ ));
+
if( lastErrno==ERROR_INVALID_HANDLE ){
pFile->lastErrno = lastErrno;
rc = SQLITE_IOERR_LOCK;
OSTRACE(("LOCK-FAIL file=%p, count=%d, rc=%s\n",
- pFile->h, cnt, sqlite3ErrName(rc)));
+ pFile->h, cnt, sqlite3ErrName(rc)
+ ));
return rc;
}
- if( cnt ) sqlite3_win32_sleep(1);
+
+ cnt--;
+ if( cnt>0 ) sqlite3_win32_sleep(1);
}
gotPendingLock = res;
- if( !res ){
- lastErrno = osGetLastError();
- }
}
/* Acquire a shared lock
*/
if( locktype==SHARED_LOCK && res ){
assert( pFile->locktype==NO_LOCK );
- res = winGetReadLock(pFile);
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+ res = winGetReadLock(pFile, pFile->bBlockOnConnect);
+#else
+ res = winGetReadLock(pFile, 0);
+#endif
if( res ){
newLocktype = SHARED_LOCK;
}else{
@@ -43919,14 +52224,14 @@ static int winLock(sqlite3_file *id, int locktype){
*/
if( locktype==EXCLUSIVE_LOCK && res ){
assert( pFile->locktype>=SHARED_LOCK );
- res = winUnlockReadLock(pFile);
+ (void)winUnlockReadLock(pFile);
res = winLockFile(&pFile->h, SQLITE_LOCKFILE_FLAGS, SHARED_FIRST, 0,
SHARED_SIZE, 0);
if( res ){
newLocktype = EXCLUSIVE_LOCK;
}else{
lastErrno = osGetLastError();
- winGetReadLock(pFile);
+ winGetReadLock(pFile, 0);
}
}
@@ -44006,7 +52311,7 @@ static int winUnlock(sqlite3_file *id, int locktype){
type = pFile->locktype;
if( type>=EXCLUSIVE_LOCK ){
winUnlockFile(&pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0);
- if( locktype==SHARED_LOCK && !winGetReadLock(pFile) ){
+ if( locktype==SHARED_LOCK && !winGetReadLock(pFile, 0) ){
/* This should never happen. We should always be able to
** reacquire the read lock */
rc = winLogError(SQLITE_IOERR_UNLOCK, osGetLastError(),
@@ -44085,6 +52390,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 *);
/*
@@ -44174,6 +52480,11 @@ static int winFileControl(sqlite3_file *id, int op, void *pArg){
return SQLITE_OK;
}
#endif
+ case SQLITE_FCNTL_NULL_IO: {
+ (void)osCloseHandle(pFile->h);
+ pFile->h = NULL;
+ return SQLITE_OK;
+ }
case SQLITE_FCNTL_TEMPFILENAME: {
char *zTFile = 0;
int rc = winGetTempname(pFile->pVfs, &zTFile);
@@ -44210,6 +52521,50 @@ static int winFileControl(sqlite3_file *id, int op, void *pArg){
return rc;
}
#endif
+
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+ case SQLITE_FCNTL_LOCK_TIMEOUT: {
+ int iOld = pFile->iBusyTimeout;
+ int iNew = *(int*)pArg;
+#if SQLITE_ENABLE_SETLK_TIMEOUT==1
+ pFile->iBusyTimeout = (iNew < 0) ? INFINITE : (DWORD)iNew;
+#elif SQLITE_ENABLE_SETLK_TIMEOUT==2
+ pFile->iBusyTimeout = (DWORD)(!!iNew);
+#else
+# error "SQLITE_ENABLE_SETLK_TIMEOUT must be set to 1 or 2"
+#endif
+ *(int*)pArg = iOld;
+ return SQLITE_OK;
+ }
+ case SQLITE_FCNTL_BLOCK_ON_CONNECT: {
+ int iNew = *(int*)pArg;
+ pFile->bBlockOnConnect = iNew;
+ return SQLITE_OK;
+ }
+#endif /* SQLITE_ENABLE_SETLK_TIMEOUT */
+
+#if defined(SQLITE_DEBUG) || defined(SQLITE_ENABLE_FILESTAT)
+ case SQLITE_FCNTL_FILESTAT: {
+ sqlite3_str *pStr = (sqlite3_str*)pArg;
+ sqlite3_str_appendf(pStr, "{\"h\":%llu", (sqlite3_uint64)pFile->h);
+ sqlite3_str_appendf(pStr, ",\"vfs\":\"%s\"", pFile->pVfs->zName);
+ if( pFile->locktype ){
+ static const char *azLock[] = { "SHARED", "RESERVED",
+ "PENDING", "EXCLUSIVE" };
+ sqlite3_str_appendf(pStr, ",\"locktype\":\"%s\"",
+ azLock[pFile->locktype-1]);
+ }
+#if SQLITE_MAX_MMAP_SIZE>0
+ if( pFile->mmapSize ){
+ sqlite3_str_appendf(pStr, ",\"mmapSize\":%lld", pFile->mmapSize);
+ sqlite3_str_appendf(pStr, ",\"nFetchOut\":%d", pFile->nFetchOut);
+ }
+#endif
+ sqlite3_str_append(pStr, "}", 1);
+ return SQLITE_OK;
+ }
+#endif /* SQLITE_DEBUG || SQLITE_ENABLE_FILESTAT */
+
}
OSTRACE(("FCNTL file=%p, rc=SQLITE_NOTFOUND\n", pFile->h));
return SQLITE_NOTFOUND;
@@ -44235,7 +52590,7 @@ static int winSectorSize(sqlite3_file *id){
*/
static int winDeviceCharacteristics(sqlite3_file *id){
winFile *p = (winFile*)id;
- return SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN |
+ return SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN | SQLITE_IOCAP_SUBPAGE_READ |
((p->ctrlFlags & WINFILE_PSOW)?SQLITE_IOCAP_POWERSAFE_OVERWRITE:0);
}
@@ -44247,6 +52602,103 @@ static int winDeviceCharacteristics(sqlite3_file *id){
*/
static SYSTEM_INFO winSysInfo;
+/*
+** Convert a UTF-8 filename into whatever form the underlying
+** operating system wants filenames in. Space to hold the result
+** is obtained from malloc and must be freed by the calling
+** function
+**
+** On Cygwin, 3 possible input forms are accepted:
+** - If the filename starts with ":/" or ":\",
+** it is converted to UTF-16 as-is.
+** - If the filename contains '/', it is assumed to be a
+** Cygwin absolute path, it is converted to a win32
+** absolute path in UTF-16.
+** - Otherwise it must be a filename only, the win32 filename
+** is returned in UTF-16.
+** Note: If the function cygwin_conv_path() fails, only
+** UTF-8 -> UTF-16 conversion will be done. This can only
+** happen when the file path >32k, in which case winUtf8ToUnicode()
+** will fail too.
+*/
+static void *winConvertFromUtf8Filename(const char *zFilename){
+ void *zConverted = 0;
+ if( osIsNT() ){
+#ifdef __CYGWIN__
+ int nChar;
+ LPWSTR zWideFilename;
+
+ if( osCygwin_conv_path && !(winIsDriveLetterAndColon(zFilename)
+ && winIsDirSep(zFilename[2])) ){
+ i64 nByte;
+ int convertflag = CCP_POSIX_TO_WIN_W;
+ if( !strchr(zFilename, '/') ) convertflag |= CCP_RELATIVE;
+ nByte = (i64)osCygwin_conv_path(convertflag,
+ zFilename, 0, 0);
+ if( nByte>0 ){
+ zConverted = sqlite3MallocZero(12+(u64)nByte);
+ if ( zConverted==0 ){
+ return zConverted;
+ }
+ zWideFilename = zConverted;
+ /* Filenames should be prefixed, except when converted
+ * full path already starts with "\\?\". */
+ if( osCygwin_conv_path(convertflag, zFilename,
+ zWideFilename+4, nByte)==0 ){
+ if( (convertflag&CCP_RELATIVE) ){
+ memmove(zWideFilename, zWideFilename+4, nByte);
+ }else if( memcmp(zWideFilename+4, L"\\\\", 4) ){
+ memcpy(zWideFilename, L"\\\\?\\", 8);
+ }else if( zWideFilename[6]!='?' ){
+ memmove(zWideFilename+6, zWideFilename+4, nByte);
+ memcpy(zWideFilename, L"\\\\?\\UNC", 14);
+ }else{
+ memmove(zWideFilename, zWideFilename+4, nByte);
+ }
+ return zConverted;
+ }
+ sqlite3_free(zConverted);
+ }
+ }
+ nChar = osMultiByteToWideChar(CP_UTF8, 0, zFilename, -1, NULL, 0);
+ if( nChar==0 ){
+ return 0;
+ }
+ zWideFilename = sqlite3MallocZero( nChar*sizeof(WCHAR)+12 );
+ if( zWideFilename==0 ){
+ return 0;
+ }
+ nChar = osMultiByteToWideChar(CP_UTF8, 0, zFilename, -1,
+ zWideFilename, nChar);
+ if( nChar==0 ){
+ sqlite3_free(zWideFilename);
+ zWideFilename = 0;
+ }else if( nChar>MAX_PATH
+ && winIsDriveLetterAndColon(zFilename)
+ && winIsDirSep(zFilename[2]) ){
+ memmove(zWideFilename+4, zWideFilename, nChar*sizeof(WCHAR));
+ zWideFilename[2] = '\\';
+ memcpy(zWideFilename, L"\\\\?\\", 8);
+ }else if( nChar>MAX_PATH
+ && winIsDirSep(zFilename[0]) && winIsDirSep(zFilename[1])
+ && zFilename[2] != '?' ){
+ memmove(zWideFilename+6, zWideFilename, nChar*sizeof(WCHAR));
+ memcpy(zWideFilename, L"\\\\?\\UNC", 14);
+ }
+ zConverted = zWideFilename;
+#else
+ zConverted = winUtf8ToUnicode(zFilename);
+#endif /* __CYGWIN__ */
+ }
+#if defined(SQLITE_WIN32_HAS_ANSI) && defined(_WIN32)
+ else{
+ zConverted = winUtf8ToMbcs(zFilename, osAreFileApisANSI());
+ }
+#endif
+ /* caller will handle out of memory */
+ return zConverted;
+}
+
#ifndef SQLITE_OMIT_WAL
/*
@@ -44283,30 +52735,40 @@ static int winShmMutexHeld(void) {
** log-summary is opened only once per process.
**
** winShmMutexHeld() must be true when creating or destroying
-** this object or while reading or writing the following fields:
+** this object, or while editing the global linked list that starts
+** at winShmNodeList.
**
-** nRef
-** pNext
+** When reading or writing the linked list starting at winShmNode.pWinShmList,
+** pShmNode->mutex must be held.
**
-** The following fields are read-only after the object is created:
+** The following fields are constant after the object is created:
**
-** fid
** zFilename
+** hSharedShm
+** mutex
+** bUseSharedLockHandle
**
-** Either winShmNode.mutex must be held or winShmNode.nRef==0 and
+** Either winShmNode.mutex must be held or winShmNode.pWinShmList==0 and
** winShmMutexHeld() is true when reading or writing any other field
** in this structure.
**
+** File-handle hSharedShm is always used to (a) take the DMS lock, (b)
+** truncate the *-shm file if the DMS-locking protocol demands it, and
+** (c) map regions of the *-shm file into memory using MapViewOfFile()
+** or similar. If bUseSharedLockHandle is true, then other locks are also
+** taken on hSharedShm. Or, if bUseSharedLockHandle is false, then other
+** locks are taken using each connection's winShm.hShm handles.
*/
struct winShmNode {
sqlite3_mutex *mutex; /* Mutex to access this object */
char *zFilename; /* Name of the file */
- winFile hFile; /* File handle from winOpen */
+ HANDLE hSharedShm; /* File handle open on zFilename */
+ int bUseSharedLockHandle; /* True to use hSharedShm for everything */
+ int isUnlocked; /* DMS lock has not yet been obtained */
+ int isReadonly; /* True if read-only */
int szRegion; /* Size of shared-memory regions */
int nRegion; /* Size of array apRegion */
- u8 isReadonly; /* True if read-only */
- u8 isUnlocked; /* True if no DMS lock held */
struct ShmRegion {
HANDLE hMap; /* File handle from CreateFileMapping */
@@ -44314,8 +52776,8 @@ struct winShmNode {
} *aRegion;
DWORD lastErrno; /* The Windows errno from the last I/O error */
- int nRef; /* Number of winShm objects pointing to this */
- winShm *pFirst; /* All winShm objects pointing to this */
+ winShm *pWinShmList; /* List of winShm objects with ptrs to this */
+
winShmNode *pNext; /* Next in list of all winShmNode objects */
#if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE)
u8 nextShmId; /* Next available winShm.id value */
@@ -44331,26 +52793,19 @@ static winShmNode *winShmNodeList = 0;
/*
** Structure used internally by this VFS to record the state of an
-** open shared memory connection.
-**
-** The following fields are initialized when this object is created and
-** are read-only thereafter:
-**
-** winShm.pShmNode
-** winShm.id
-**
-** All other fields are read/write. The winShm.pShmNode->mutex must be held
-** while accessing any read/write fields.
+** open shared memory connection. There is one such structure for each
+** winFile open on a wal mode database.
*/
struct winShm {
winShmNode *pShmNode; /* The underlying winShmNode object */
- winShm *pNext; /* Next winShm with the same winShmNode */
- u8 hasMutex; /* True if holding the winShmNode mutex */
u16 sharedMask; /* Mask of shared locks held */
u16 exclMask; /* Mask of exclusive locks held */
+ HANDLE hShm; /* File-handle on *-shm file. For locking. */
+ int bReadonly; /* True if hShm is opened read-only */
#if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE)
u8 id; /* Id of this connection with its winShmNode */
#endif
+ winShm *pWinShmNext; /* Next winShm object on same winShmNode */
};
/*
@@ -44359,56 +52814,12 @@ struct winShm {
#define WIN_SHM_BASE ((22+SQLITE_SHM_NLOCK)*4) /* first lock byte */
#define WIN_SHM_DMS (WIN_SHM_BASE+SQLITE_SHM_NLOCK) /* deadman switch */
-/*
-** Apply advisory locks for all n bytes beginning at ofst.
-*/
-#define WINSHM_UNLCK 1
-#define WINSHM_RDLCK 2
-#define WINSHM_WRLCK 3
-static int winShmSystemLock(
- winShmNode *pFile, /* Apply locks to this open shared-memory segment */
- int lockType, /* WINSHM_UNLCK, WINSHM_RDLCK, or WINSHM_WRLCK */
- int ofst, /* Offset to first byte to be locked/unlocked */
- int nByte /* Number of bytes to lock or unlock */
-){
- int rc = 0; /* Result code form Lock/UnlockFileEx() */
-
- /* Access to the winShmNode object is serialized by the caller */
- assert( pFile->nRef==0 || sqlite3_mutex_held(pFile->mutex) );
-
- OSTRACE(("SHM-LOCK file=%p, lock=%d, offset=%d, size=%d\n",
- pFile->hFile.h, lockType, ofst, nByte));
-
- /* Release/Acquire the system-level lock */
- if( lockType==WINSHM_UNLCK ){
- rc = winUnlockFile(&pFile->hFile.h, ofst, 0, nByte, 0);
- }else{
- /* Initialize the locking parameters */
- DWORD dwFlags = LOCKFILE_FAIL_IMMEDIATELY;
- if( lockType == WINSHM_WRLCK ) dwFlags |= LOCKFILE_EXCLUSIVE_LOCK;
- rc = winLockFile(&pFile->hFile.h, dwFlags, ofst, 0, nByte, 0);
- }
-
- if( rc!= 0 ){
- rc = SQLITE_OK;
- }else{
- pFile->lastErrno = osGetLastError();
- rc = SQLITE_BUSY;
- }
-
- OSTRACE(("SHM-LOCK file=%p, func=%s, errno=%lu, rc=%s\n",
- pFile->hFile.h, (lockType == WINSHM_UNLCK) ? "winUnlockFile" :
- "winLockFile", pFile->lastErrno, sqlite3ErrName(rc)));
-
- return rc;
-}
-
/* Forward references to VFS methods */
static int winOpen(sqlite3_vfs*,const char*,sqlite3_file*,int,int*);
static int winDelete(sqlite3_vfs *,const char*,int);
/*
-** Purge the winShmNodeList list of all entries with winShmNode.nRef==0.
+** Purge the winShmNodeList list of all entries with winShmNode.pWinShmList==0.
**
** This is not a VFS shared-memory method; it is a utility function called
** by VFS shared-memory methods.
@@ -44421,7 +52832,7 @@ static void winShmPurge(sqlite3_vfs *pVfs, int deleteFlag){
osGetCurrentProcessId(), deleteFlag));
pp = &winShmNodeList;
while( (p = *pp)!=0 ){
- if( p->nRef==0 ){
+ if( p->pWinShmList==0 ){
int i;
if( p->mutex ){ sqlite3_mutex_free(p->mutex); }
for(i=0; inRegion; i++){
@@ -44434,11 +52845,7 @@ static void winShmPurge(sqlite3_vfs *pVfs, int deleteFlag){
osGetCurrentProcessId(), i, bRc ? "ok" : "failed"));
UNUSED_VARIABLE_VALUE(bRc);
}
- if( p->hFile.h!=NULL && p->hFile.h!=INVALID_HANDLE_VALUE ){
- SimulateIOErrorBenign(1);
- winClose((sqlite3_file *)&p->hFile);
- SimulateIOErrorBenign(0);
- }
+ winHandleClose(p->hSharedShm);
if( deleteFlag ){
SimulateIOErrorBenign(1);
sqlite3BeginBenignMalloc();
@@ -44456,42 +52863,199 @@ static void winShmPurge(sqlite3_vfs *pVfs, int deleteFlag){
}
/*
-** The DMS lock has not yet been taken on shm file pShmNode. Attempt to
-** 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
-** connection and no other process already holds a lock, return
-** SQLITE_READONLY_CANTINIT and set pShmNode->isUnlocked=1.
+** The DMS lock has not yet been taken on the shm file associated with
+** pShmNode. Take the lock. Truncate the *-shm file if required.
+** Return SQLITE_OK if successful, or an SQLite error code otherwise.
*/
-static int winLockSharedMemory(winShmNode *pShmNode){
- int rc = winShmSystemLock(pShmNode, WINSHM_WRLCK, WIN_SHM_DMS, 1);
+static int winLockSharedMemory(winShmNode *pShmNode, DWORD nMs){
+ HANDLE h = pShmNode->hSharedShm;
+ int rc = SQLITE_OK;
+ assert( sqlite3_mutex_held(pShmNode->mutex) );
+ rc = winHandleLockTimeout(h, WIN_SHM_DMS, 1, 1, 0);
if( rc==SQLITE_OK ){
+ /* We have an EXCLUSIVE lock on the DMS byte. This means that this
+ ** is the first process to open the file. Truncate it to zero bytes
+ ** in this case. */
if( pShmNode->isReadonly ){
- pShmNode->isUnlocked = 1;
- winShmSystemLock(pShmNode, WINSHM_UNLCK, WIN_SHM_DMS, 1);
- return SQLITE_READONLY_CANTINIT;
- }else if( winTruncate((sqlite3_file*)&pShmNode->hFile, 0) ){
- winShmSystemLock(pShmNode, WINSHM_UNLCK, WIN_SHM_DMS, 1);
- return winLogError(SQLITE_IOERR_SHMOPEN, osGetLastError(),
- "winLockSharedMemory", pShmNode->zFilename);
+ rc = SQLITE_READONLY_CANTINIT;
+ }else{
+ rc = winHandleTruncate(h, 0);
}
+
+ /* Release the EXCLUSIVE lock acquired above. */
+ winUnlockFile(&h, WIN_SHM_DMS, 0, 1, 0);
+ }else if( (rc & 0xFF)==SQLITE_BUSY ){
+ rc = SQLITE_OK;
}
if( rc==SQLITE_OK ){
- winShmSystemLock(pShmNode, WINSHM_UNLCK, WIN_SHM_DMS, 1);
+ /* Take a SHARED lock on the DMS byte. */
+ rc = winHandleLockTimeout(h, WIN_SHM_DMS, 1, 0, nMs);
+ if( rc==SQLITE_OK ){
+ pShmNode->isUnlocked = 0;
+ }
}
- return winShmSystemLock(pShmNode, WINSHM_RDLCK, WIN_SHM_DMS, 1);
+ return rc;
}
+
/*
-** Open the shared-memory area associated with database file pDbFd.
+** This function is used to open a handle on a *-shm file.
**
-** When opening a new shared-memory file, if no other instances of that
-** file are currently open, in this process or in other processes, then
-** the file must be truncated to zero length or have its header cleared.
+** If SQLITE_ENABLE_SETLK_TIMEOUT is defined at build time, then the file
+** is opened with FILE_FLAG_OVERLAPPED specified. If not, it is not.
+*/
+static int winHandleOpen(
+ const char *zUtf8, /* File to open */
+ int *pbReadonly, /* IN/OUT: True for readonly handle */
+ HANDLE *ph /* OUT: New HANDLE for file */
+){
+ int rc = SQLITE_OK;
+ void *zConverted = 0;
+ int bReadonly = *pbReadonly;
+ HANDLE h = INVALID_HANDLE_VALUE;
+
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+ const DWORD flag_overlapped = FILE_FLAG_OVERLAPPED;
+#else
+ const DWORD flag_overlapped = 0;
+#endif
+
+ /* Convert the filename to the system encoding. */
+ zConverted = winConvertFromUtf8Filename(zUtf8);
+ if( zConverted==0 ){
+ OSTRACE(("OPEN name=%s, rc=SQLITE_IOERR_NOMEM", zUtf8));
+ rc = SQLITE_IOERR_NOMEM_BKPT;
+ goto winopenfile_out;
+ }
+
+ /* Ensure the file we are trying to open is not actually a directory. */
+ if( winIsDir(zConverted) ){
+ OSTRACE(("OPEN name=%s, rc=SQLITE_CANTOPEN_ISDIR", zUtf8));
+ rc = SQLITE_CANTOPEN_ISDIR;
+ goto winopenfile_out;
+ }
+
+ /* TODO: platforms.
+ ** TODO: retry-on-ioerr.
+ */
+ if( osIsNT() ){
+ h = osCreateFileW((LPCWSTR)zConverted, /* lpFileName */
+ (GENERIC_READ | (bReadonly ? 0 : GENERIC_WRITE)), /* dwDesiredAccess */
+ FILE_SHARE_READ | FILE_SHARE_WRITE, /* dwShareMode */
+ NULL, /* lpSecurityAttributes */
+ OPEN_ALWAYS, /* dwCreationDisposition */
+ FILE_ATTRIBUTE_NORMAL|flag_overlapped,
+ NULL
+ );
+ }else{
+ /* Due to pre-processor directives earlier in this file,
+ ** SQLITE_WIN32_HAS_ANSI is always defined if osIsNT() is false. */
+#ifdef SQLITE_WIN32_HAS_ANSI
+ h = osCreateFileA((LPCSTR)zConverted,
+ (GENERIC_READ | (bReadonly ? 0 : GENERIC_WRITE)), /* dwDesiredAccess */
+ FILE_SHARE_READ | FILE_SHARE_WRITE, /* dwShareMode */
+ NULL, /* lpSecurityAttributes */
+ OPEN_ALWAYS, /* dwCreationDisposition */
+ FILE_ATTRIBUTE_NORMAL|flag_overlapped,
+ NULL
+ );
+#endif
+ }
+
+ if( h==INVALID_HANDLE_VALUE ){
+ if( bReadonly==0 ){
+ bReadonly = 1;
+ rc = winHandleOpen(zUtf8, &bReadonly, &h);
+ }else{
+ rc = SQLITE_CANTOPEN_BKPT;
+ }
+ }
+
+ winopenfile_out:
+ sqlite3_free(zConverted);
+ *pbReadonly = bReadonly;
+ *ph = h;
+ return rc;
+}
+
+/*
+** Close pDbFd's connection to shared-memory. Delete the underlying
+** *-shm file if deleteFlag is true.
+*/
+static int winCloseSharedMemory(winFile *pDbFd, int deleteFlag){
+ winShm *p; /* The connection to be closed */
+ winShm **pp; /* Iterator for pShmNode->pWinShmList */
+ winShmNode *pShmNode; /* The underlying shared-memory file */
+
+ p = pDbFd->pShm;
+ if( p==0 ) return SQLITE_OK;
+ if( p->hShm!=INVALID_HANDLE_VALUE ){
+ osCloseHandle(p->hShm);
+ }
+
+ winShmEnterMutex();
+ pShmNode = p->pShmNode;
+
+ /* Remove this connection from the winShmNode.pWinShmList list */
+ sqlite3_mutex_enter(pShmNode->mutex);
+ for(pp=&pShmNode->pWinShmList; *pp!=p; pp=&(*pp)->pWinShmNext){}
+ *pp = p->pWinShmNext;
+ sqlite3_mutex_leave(pShmNode->mutex);
+
+ winShmPurge(pDbFd->pVfs, deleteFlag);
+ winShmLeaveMutex();
+
+ /* Free the connection p */
+ sqlite3_free(p);
+ pDbFd->pShm = 0;
+ return SQLITE_OK;
+}
+
+/*
+** testfixture builds may set this global variable to true via a
+** Tcl interface. This forces the VFS to use the locking normally
+** only used for UNC paths for all files.
+*/
+#ifdef SQLITE_TEST
+SQLITE_API int sqlite3_win_test_unc_locking = 0;
+#else
+# define sqlite3_win_test_unc_locking 0
+#endif
+
+/*
+** Return true if the string passed as the only argument is likely
+** to be a UNC path. Return false if note.
+**
+** Return true if:
+**
+** (1) The name begins with "\\"
+** (2) But does not begin with "\\?\C:\" where C can be any alphabetic
+** character.
+**
+** For testing, also return true in all cases if the global variable
+** sqlite3_win_test_unc_locking is true.
+*/
+static int winIsUNCPath(const char *zFile){
+ if( zFile[0]=='\\' && zFile[1]=='\\' ){
+ if( zFile[2]=='?'
+ && zFile[3]=='\\'
+ && sqlite3Isalpha(zFile[4])
+ && zFile[5]==':'
+ && winIsDirSep(zFile[6])
+ ){
+ return sqlite3_win_test_unc_locking;
+ }else{
+ return 1;
+ }
+ }
+ return sqlite3_win_test_unc_locking;
+}
+
+/*
+** Open the shared-memory area associated with database file pDbFd.
*/
static int winOpenSharedMemory(winFile *pDbFd){
struct winShm *p; /* The connection to be opened */
@@ -44503,98 +53067,93 @@ static int winOpenSharedMemory(winFile *pDbFd){
assert( pDbFd->pShm==0 ); /* Not previously opened */
/* Allocate space for the new sqlite3_shm object. Also speculatively
- ** allocate space for a new winShmNode and filename.
- */
+ ** allocate space for a new winShmNode and filename. */
p = sqlite3MallocZero( sizeof(*p) );
if( p==0 ) return SQLITE_IOERR_NOMEM_BKPT;
nName = sqlite3Strlen30(pDbFd->zPath);
- pNew = sqlite3MallocZero( sizeof(*pShmNode) + nName + 17 );
+ pNew = sqlite3MallocZero( sizeof(*pShmNode) + (i64)nName + 17 );
if( pNew==0 ){
sqlite3_free(p);
return SQLITE_IOERR_NOMEM_BKPT;
}
pNew->zFilename = (char*)&pNew[1];
+ pNew->hSharedShm = INVALID_HANDLE_VALUE;
+ pNew->isUnlocked = 1;
+ pNew->bUseSharedLockHandle = winIsUNCPath(pDbFd->zPath);
sqlite3_snprintf(nName+15, pNew->zFilename, "%s-shm", pDbFd->zPath);
sqlite3FileSuffix3(pDbFd->zPath, pNew->zFilename);
/* Look to see if there is an existing winShmNode that can be used.
- ** If no matching winShmNode currently exists, create a new one.
- */
+ ** If no matching winShmNode currently exists, then create a new one. */
winShmEnterMutex();
for(pShmNode = winShmNodeList; pShmNode; pShmNode=pShmNode->pNext){
/* TBD need to come up with better match here. Perhaps
- ** use FILE_ID_BOTH_DIR_INFO Structure.
- */
+ ** use FILE_ID_BOTH_DIR_INFO Structure. */
if( sqlite3StrICmp(pShmNode->zFilename, pNew->zFilename)==0 ) break;
}
- if( pShmNode ){
- sqlite3_free(pNew);
- }else{
- int inFlags = SQLITE_OPEN_WAL;
- int outFlags = 0;
-
+ if( pShmNode==0 ){
pShmNode = pNew;
- pNew = 0;
- ((winFile*)(&pShmNode->hFile))->h = INVALID_HANDLE_VALUE;
- pShmNode->pNext = winShmNodeList;
- winShmNodeList = pShmNode;
+ /* Allocate a mutex for this winShmNode object, if one is required. */
if( sqlite3GlobalConfig.bCoreMutex ){
pShmNode->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
- if( pShmNode->mutex==0 ){
- rc = SQLITE_IOERR_NOMEM_BKPT;
- goto shm_open_err;
- }
+ if( pShmNode->mutex==0 ) rc = SQLITE_IOERR_NOMEM_BKPT;
}
- if( 0==sqlite3_uri_boolean(pDbFd->zPath, "readonly_shm", 0) ){
- inFlags |= SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
- }else{
- inFlags |= SQLITE_OPEN_READONLY;
- }
- rc = winOpen(pDbFd->pVfs, pShmNode->zFilename,
- (sqlite3_file*)&pShmNode->hFile,
- inFlags, &outFlags);
- if( rc!=SQLITE_OK ){
- rc = winLogError(rc, osGetLastError(), "winOpenShm",
- pShmNode->zFilename);
- goto shm_open_err;
+ /* Open a file-handle to use for mappings, and for the DMS lock. */
+ if( rc==SQLITE_OK ){
+ HANDLE h = INVALID_HANDLE_VALUE;
+ pShmNode->isReadonly = sqlite3_uri_boolean(pDbFd->zPath,"readonly_shm",0);
+ rc = winHandleOpen(pNew->zFilename, &pShmNode->isReadonly, &h);
+ pShmNode->hSharedShm = h;
}
- if( outFlags==SQLITE_OPEN_READONLY ) pShmNode->isReadonly = 1;
- rc = winLockSharedMemory(pShmNode);
- if( rc!=SQLITE_OK && rc!=SQLITE_READONLY_CANTINIT ) goto shm_open_err;
+ /* If successful, link the new winShmNode into the global list. If an
+ ** error occurred, free the object. */
+ if( rc==SQLITE_OK ){
+ pShmNode->pNext = winShmNodeList;
+ winShmNodeList = pShmNode;
+ pNew = 0;
+ }else{
+ sqlite3_mutex_free(pShmNode->mutex);
+ if( pShmNode->hSharedShm!=INVALID_HANDLE_VALUE ){
+ osCloseHandle(pShmNode->hSharedShm);
+ }
+ }
}
- /* Make the new connection a child of the winShmNode */
- p->pShmNode = pShmNode;
+ /* If no error has occurred, link the winShm object to the winShmNode and
+ ** the winShm to pDbFd. */
+ if( rc==SQLITE_OK ){
+ sqlite3_mutex_enter(pShmNode->mutex);
+ p->pShmNode = pShmNode;
+ p->pWinShmNext = pShmNode->pWinShmList;
+ pShmNode->pWinShmList = p;
#if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE)
- p->id = pShmNode->nextShmId++;
+ p->id = pShmNode->nextShmId++;
#endif
- pShmNode->nRef++;
- pDbFd->pShm = p;
+ pDbFd->pShm = p;
+ sqlite3_mutex_leave(pShmNode->mutex);
+ }else if( p ){
+ sqlite3_free(p);
+ }
+
+ assert( rc!=SQLITE_OK || pShmNode->isUnlocked==0 || pShmNode->nRegion==0 );
winShmLeaveMutex();
+ sqlite3_free(pNew);
- /* The reference count on pShmNode has already been incremented under
- ** the cover of the winShmEnterMutex() mutex and the pointer from the
- ** new (struct winShm) object to the pShmNode has been set. All that is
- ** left to do is to link the new object into the linked list starting
- ** at pShmNode->pFirst. This must be done while holding the pShmNode->mutex
- ** mutex.
- */
- sqlite3_mutex_enter(pShmNode->mutex);
- p->pNext = pShmNode->pFirst;
- pShmNode->pFirst = p;
- sqlite3_mutex_leave(pShmNode->mutex);
- return rc;
+ /* Open a file-handle on the *-shm file for this connection. This file-handle
+ ** is only used for locking. The mapping of the *-shm file is created using
+ ** the shared file handle in winShmNode.hSharedShm. */
+ if( rc==SQLITE_OK && pShmNode->bUseSharedLockHandle==0 ){
+ p->bReadonly = sqlite3_uri_boolean(pDbFd->zPath, "readonly_shm", 0);
+ rc = winHandleOpen(pShmNode->zFilename, &p->bReadonly, &p->hShm);
+ if( rc!=SQLITE_OK ){
+ assert( p->hShm==INVALID_HANDLE_VALUE );
+ winCloseSharedMemory(pDbFd, 0);
+ }
+ }
- /* Jump here on any error */
-shm_open_err:
- winShmSystemLock(pShmNode, WINSHM_UNLCK, WIN_SHM_DMS, 1);
- winShmPurge(pDbFd->pVfs, 0); /* This call frees pShmNode if required */
- sqlite3_free(p);
- sqlite3_free(pNew);
- winShmLeaveMutex();
return rc;
}
@@ -44606,38 +53165,7 @@ static int winShmUnmap(
sqlite3_file *fd, /* Database holding shared memory */
int deleteFlag /* Delete after closing if true */
){
- winFile *pDbFd; /* Database holding shared-memory */
- winShm *p; /* The connection to be closed */
- winShmNode *pShmNode; /* The underlying shared-memory file */
- winShm **pp; /* For looping over sibling connections */
-
- pDbFd = (winFile*)fd;
- p = pDbFd->pShm;
- if( p==0 ) return SQLITE_OK;
- pShmNode = p->pShmNode;
-
- /* Remove connection p from the set of connections associated
- ** with pShmNode */
- sqlite3_mutex_enter(pShmNode->mutex);
- for(pp=&pShmNode->pFirst; (*pp)!=p; pp = &(*pp)->pNext){}
- *pp = p->pNext;
-
- /* Free the connection p */
- sqlite3_free(p);
- pDbFd->pShm = 0;
- sqlite3_mutex_leave(pShmNode->mutex);
-
- /* If pShmNode->nRef has reached 0, then close the underlying
- ** shared-memory file, too */
- winShmEnterMutex();
- assert( pShmNode->nRef>0 );
- pShmNode->nRef--;
- if( pShmNode->nRef==0 ){
- winShmPurge(pDbFd->pVfs, deleteFlag);
- }
- winShmLeaveMutex();
-
- return SQLITE_OK;
+ return winCloseSharedMemory((winFile*)fd, deleteFlag);
}
/*
@@ -44651,10 +53179,13 @@ static int winShmLock(
){
winFile *pDbFd = (winFile*)fd; /* Connection holding shared memory */
winShm *p = pDbFd->pShm; /* The shared memory being locked */
- winShm *pX; /* For looping over all siblings */
- winShmNode *pShmNode = p->pShmNode;
+ winShmNode *pShmNode;
int rc = SQLITE_OK; /* Result code */
- u16 mask; /* Mask of locks to take or release */
+ u16 mask = (u16)((1U<<(ofst+n)) - (1U<pShmNode;
+ if( NEVER(pShmNode==0) ) return SQLITE_IOERR_SHMLOCK;
assert( ofst>=0 && ofst+n<=SQLITE_SHM_NLOCK );
assert( n>=1 );
@@ -44664,85 +53195,127 @@ static int winShmLock(
|| flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE) );
assert( n==1 || (flags & SQLITE_SHM_EXCLUSIVE)!=0 );
- mask = (u16)((1U<<(ofst+n)) - (1U<1 || mask==(1<mutex);
- if( flags & SQLITE_SHM_UNLOCK ){
- u16 allMask = 0; /* Mask of locks held by siblings */
-
- /* See if any siblings hold this same lock */
- for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
- if( pX==p ) continue;
- assert( (pX->exclMask & (p->exclMask|p->sharedMask))==0 );
- allMask |= pX->sharedMask;
- }
-
- /* Unlock the system-level locks */
- if( (mask & allMask)==0 ){
- rc = winShmSystemLock(pShmNode, WINSHM_UNLCK, ofst+WIN_SHM_BASE, n);
- }else{
- rc = SQLITE_OK;
- }
-
- /* Undo the local locks */
- if( rc==SQLITE_OK ){
- p->exclMask &= ~mask;
- p->sharedMask &= ~mask;
- }
- }else if( flags & SQLITE_SHM_SHARED ){
- u16 allShared = 0; /* Union of locks held by connections other than "p" */
+ /* 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. Recovery lock (ofst==2).
+ ** 2. Checkpointer lock (ofst==1).
+ ** 3. Write lock (ofst==0).
+ ** 4. Read locks (ofst>=3 && ofstexclMask|p->sharedMask);
+ assert( (flags & SQLITE_SHM_UNLOCK) || pDbFd->iBusyTimeout==0 || (
+ (ofst!=2 || lockMask==0)
+ && (ofst!=1 || lockMask==0 || lockMask==2)
+ && (ofst!=0 || lockMask<3)
+ && (ofst<3 || lockMask<(1<pFirst; pX; pX=pX->pNext){
- if( (pX->exclMask & mask)!=0 ){
- rc = SQLITE_BUSY;
- break;
+ /* Check if there is any work to do. There are three cases:
+ **
+ ** a) An unlock operation where there are locks to unlock,
+ ** b) An shared lock where the requested lock is not already held
+ ** c) An exclusive lock where the requested lock is not already held
+ **
+ ** The SQLite core never requests an exclusive lock that it already holds.
+ ** This is assert()ed immediately below. */
+ assert( flags!=(SQLITE_SHM_EXCLUSIVE|SQLITE_SHM_LOCK)
+ || 0==(p->exclMask & mask)
+ );
+ if( ((flags & SQLITE_SHM_UNLOCK) && ((p->exclMask|p->sharedMask) & mask))
+ || (flags==(SQLITE_SHM_SHARED|SQLITE_SHM_LOCK) && 0==(p->sharedMask & mask))
+ || (flags==(SQLITE_SHM_EXCLUSIVE|SQLITE_SHM_LOCK))
+ ){
+ HANDLE h = p->hShm;
+
+ if( flags & SQLITE_SHM_UNLOCK ){
+ /* Case (a) - unlock. */
+
+ assert( (p->exclMask & p->sharedMask)==0 );
+ assert( !(flags & SQLITE_SHM_EXCLUSIVE) || (p->exclMask & mask)==mask );
+ assert( !(flags & SQLITE_SHM_SHARED) || (p->sharedMask & mask)==mask );
+
+ assert( !(flags & SQLITE_SHM_SHARED) || n==1 );
+ if( pShmNode->bUseSharedLockHandle ){
+ h = pShmNode->hSharedShm;
+ if( flags & SQLITE_SHM_SHARED ){
+ winShm *pShm;
+ sqlite3_mutex_enter(pShmNode->mutex);
+ for(pShm=pShmNode->pWinShmList; pShm; pShm=pShm->pWinShmNext){
+ if( pShm!=p && (pShm->sharedMask & mask) ){
+ /* Another connection within this process is also holding this
+ ** SHARED lock. So do not actually release the OS lock. */
+ h = INVALID_HANDLE_VALUE;
+ break;
+ }
+ }
+ sqlite3_mutex_leave(pShmNode->mutex);
+ }
}
- allShared |= pX->sharedMask;
- }
- /* Get shared locks at the system level, if necessary */
- if( rc==SQLITE_OK ){
- if( (allShared & mask)==0 ){
- rc = winShmSystemLock(pShmNode, WINSHM_RDLCK, ofst+WIN_SHM_BASE, n);
- }else{
- rc = SQLITE_OK;
+ if( h!=INVALID_HANDLE_VALUE ){
+ rc = winHandleUnlock(h, ofst+WIN_SHM_BASE, n);
}
- }
- /* Get the local shared locks */
- if( rc==SQLITE_OK ){
- p->sharedMask |= mask;
- }
- }else{
- /* Make sure no sibling connections hold locks that will block this
- ** lock. If any do, return SQLITE_BUSY right away.
- */
- for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
- if( (pX->exclMask & mask)!=0 || (pX->sharedMask & mask)!=0 ){
- rc = SQLITE_BUSY;
- break;
+ /* If successful, also clear the bits in sharedMask/exclMask */
+ if( rc==SQLITE_OK ){
+ p->exclMask = (p->exclMask & ~mask);
+ p->sharedMask = (p->sharedMask & ~mask);
+ }
+ }else{
+ int bExcl = ((flags & SQLITE_SHM_EXCLUSIVE) ? 1 : 0);
+ DWORD nMs = winFileBusyTimeout(pDbFd);
+
+ if( pShmNode->bUseSharedLockHandle ){
+ winShm *pShm;
+ h = pShmNode->hSharedShm;
+ sqlite3_mutex_enter(pShmNode->mutex);
+ for(pShm=pShmNode->pWinShmList; pShm; pShm=pShm->pWinShmNext){
+ if( bExcl ){
+ if( (pShm->sharedMask|pShm->exclMask) & mask ){
+ rc = SQLITE_BUSY;
+ h = INVALID_HANDLE_VALUE;
+ }
+ }else{
+ if( pShm->sharedMask & mask ){
+ h = INVALID_HANDLE_VALUE;
+ }else if( pShm->exclMask & mask ){
+ rc = SQLITE_BUSY;
+ h = INVALID_HANDLE_VALUE;
+ }
+ }
+ }
+ sqlite3_mutex_leave(pShmNode->mutex);
}
- }
- /* Get the exclusive locks at the system level. Then if successful
- ** also mark the local connection as being locked.
- */
- if( rc==SQLITE_OK ){
- rc = winShmSystemLock(pShmNode, WINSHM_WRLCK, ofst+WIN_SHM_BASE, n);
+ if( h!=INVALID_HANDLE_VALUE ){
+ rc = winHandleLockTimeout(h, ofst+WIN_SHM_BASE, n, bExcl, nMs);
+ }
if( rc==SQLITE_OK ){
- assert( (p->sharedMask & mask)==0 );
- p->exclMask |= mask;
+ if( bExcl ){
+ p->exclMask = (p->exclMask | mask);
+ }else{
+ p->sharedMask = (p->sharedMask | mask);
+ }
}
}
}
- sqlite3_mutex_leave(pShmNode->mutex);
- OSTRACE(("SHM-LOCK pid=%lu, id=%d, sharedMask=%03x, exclMask=%03x, rc=%s\n",
- osGetCurrentProcessId(), p->id, p->sharedMask, p->exclMask,
- sqlite3ErrName(rc)));
+
+ OSTRACE((
+ "SHM-LOCK(%d,%d,%d) pid=%lu, id=%d, sharedMask=%03x, exclMask=%03x,"
+ " rc=%s\n",
+ ofst, n, flags,
+ osGetCurrentProcessId(), p->id, p->sharedMask, p->exclMask,
+ sqlite3ErrName(rc))
+ );
return rc;
}
@@ -44798,20 +53371,23 @@ static int winShmMap(
rc = winOpenSharedMemory(pDbFd);
if( rc!=SQLITE_OK ) return rc;
pShm = pDbFd->pShm;
+ assert( pShm!=0 );
}
pShmNode = pShm->pShmNode;
sqlite3_mutex_enter(pShmNode->mutex);
if( pShmNode->isUnlocked ){
- rc = winLockSharedMemory(pShmNode);
+ /* Take the DMS lock. */
+ assert( pShmNode->nRegion==0 );
+ rc = winLockSharedMemory(pShmNode, winFileBusyTimeout(pDbFd));
if( rc!=SQLITE_OK ) goto shmpage_out;
- pShmNode->isUnlocked = 0;
}
- assert( szRegion==pShmNode->szRegion || pShmNode->nRegion==0 );
+ assert( szRegion==pShmNode->szRegion || pShmNode->nRegion==0 );
if( pShmNode->nRegion<=iRegion ){
+ HANDLE hShared = pShmNode->hSharedShm;
struct ShmRegion *apNew; /* New aRegion[] array */
- int nByte = (iRegion+1)*szRegion; /* Minimum required file size */
+ i64 nByte = ((i64)iRegion+1)*(i64)szRegion; /* Minimum file size */
sqlite3_int64 sz; /* Current size of wal-index file */
pShmNode->szRegion = szRegion;
@@ -44820,10 +53396,9 @@ static int winShmMap(
** Check to see if it has been allocated (i.e. if the wal-index file is
** large enough to contain the requested region).
*/
- rc = winFileSize((sqlite3_file *)&pShmNode->hFile, &sz);
+ rc = winHandleSize(hShared, &sz);
if( rc!=SQLITE_OK ){
- rc = winLogError(SQLITE_IOERR_SHMSIZE, osGetLastError(),
- "winShmMap1", pDbFd->zPath);
+ rc = winLogError(rc, osGetLastError(), "winShmMap1", pDbFd->zPath);
goto shmpage_out;
}
@@ -44832,20 +53407,18 @@ static int winShmMap(
** zero, exit early. *pp will be set to NULL and SQLITE_OK returned.
**
** Alternatively, if isWrite is non-zero, use ftruncate() to allocate
- ** the requested memory region.
- */
+ ** the requested memory region. */
if( !isWrite ) goto shmpage_out;
- rc = winTruncate((sqlite3_file *)&pShmNode->hFile, nByte);
+ rc = winHandleTruncate(hShared, nByte);
if( rc!=SQLITE_OK ){
- rc = winLogError(SQLITE_IOERR_SHMSIZE, osGetLastError(),
- "winShmMap2", pDbFd->zPath);
+ rc = winLogError(rc, osGetLastError(), "winShmMap2", pDbFd->zPath);
goto shmpage_out;
}
}
/* Map the requested memory region into this processes address space. */
- apNew = (struct ShmRegion *)sqlite3_realloc64(
- pShmNode->aRegion, (iRegion+1)*sizeof(apNew[0])
+ apNew = (struct ShmRegion*)sqlite3_realloc64(
+ pShmNode->aRegion, ((i64)iRegion+1)*sizeof(apNew[0])
);
if( !apNew ){
rc = SQLITE_IOERR_NOMEM_BKPT;
@@ -44862,34 +53435,20 @@ static int winShmMap(
HANDLE hMap = NULL; /* file-mapping handle */
void *pMap = 0; /* Mapped memory region */
-#if SQLITE_OS_WINRT
- hMap = osCreateFileMappingFromApp(pShmNode->hFile.h,
- NULL, protect, nByte, NULL
- );
-#elif defined(SQLITE_WIN32_HAS_WIDE)
- hMap = osCreateFileMappingW(pShmNode->hFile.h,
- NULL, protect, 0, nByte, NULL
- );
+#if defined(SQLITE_WIN32_HAS_WIDE)
+ hMap = osCreateFileMappingW(hShared, NULL, protect, 0, nByte, NULL);
#elif defined(SQLITE_WIN32_HAS_ANSI) && SQLITE_WIN32_CREATEFILEMAPPINGA
- hMap = osCreateFileMappingA(pShmNode->hFile.h,
- NULL, protect, 0, nByte, NULL
- );
+ hMap = osCreateFileMappingA(hShared, NULL, protect, 0, nByte, NULL);
#endif
- OSTRACE(("SHM-MAP-CREATE pid=%lu, region=%d, size=%d, rc=%s\n",
+ OSTRACE(("SHM-MAP-CREATE pid=%lu, region=%d, size=%lld, rc=%s\n",
osGetCurrentProcessId(), pShmNode->nRegion, nByte,
hMap ? "ok" : "failed"));
if( hMap ){
- int iOffset = pShmNode->nRegion*szRegion;
+ i64 iOffset = pShmNode->nRegion*szRegion;
int iOffsetShift = iOffset % winSysInfo.dwAllocationGranularity;
-#if SQLITE_OS_WINRT
- pMap = osMapViewOfFileFromApp(hMap, flags,
- iOffset - iOffsetShift, szRegion + iOffsetShift
- );
-#else
pMap = osMapViewOfFile(hMap, flags,
- 0, iOffset - iOffsetShift, szRegion + iOffsetShift
+ 0, iOffset - iOffsetShift, (i64)szRegion + iOffsetShift
);
-#endif
OSTRACE(("SHM-MAP-MAP pid=%lu, region=%d, offset=%d, size=%d, rc=%s\n",
osGetCurrentProcessId(), pShmNode->nRegion, iOffset,
szRegion, pMap ? "ok" : "failed"));
@@ -44910,14 +53469,16 @@ static int winShmMap(
shmpage_out:
if( pShmNode->nRegion>iRegion ){
- int iOffset = iRegion*szRegion;
+ i64 iOffset = (i64)iRegion*(i64)szRegion;
int iOffsetShift = iOffset % winSysInfo.dwAllocationGranularity;
char *p = (char *)pShmNode->aRegion[iRegion].pMap;
*pp = (void *)&p[iOffsetShift];
}else{
*pp = 0;
}
- if( pShmNode->isReadonly && rc==SQLITE_OK ) rc = SQLITE_READONLY;
+ if( pShmNode->isReadonly && rc==SQLITE_OK ){
+ rc = SQLITE_READONLY;
+ }
sqlite3_mutex_leave(pShmNode->mutex);
return rc;
}
@@ -45020,9 +53581,7 @@ static int winMapfile(winFile *pFd, sqlite3_int64 nByte){
flags |= FILE_MAP_WRITE;
}
#endif
-#if SQLITE_OS_WINRT
- pFd->hMap = osCreateFileMappingFromApp(pFd->h, NULL, protect, nMap, NULL);
-#elif defined(SQLITE_WIN32_HAS_WIDE)
+#if defined(SQLITE_WIN32_HAS_WIDE)
pFd->hMap = osCreateFileMappingW(pFd->h, NULL, protect,
(DWORD)((nMap>>32) & 0xffffffff),
(DWORD)(nMap & 0xffffffff), NULL);
@@ -45042,11 +53601,7 @@ static int winMapfile(winFile *pFd, sqlite3_int64 nByte){
}
assert( (nMap % winSysInfo.dwPageSize)==0 );
assert( sizeof(SIZE_T)==sizeof(sqlite3_int64) || nMap<=0xffffffff );
-#if SQLITE_OS_WINRT
- pNew = osMapViewOfFileFromApp(pFd->hMap, flags, 0, (SIZE_T)nMap);
-#else
pNew = osMapViewOfFile(pFd->hMap, flags, 0, 0, (SIZE_T)nMap);
-#endif
if( pNew==NULL ){
osCloseHandle(pFd->hMap);
pFd->hMap = NULL;
@@ -45091,6 +53646,11 @@ static int winFetch(sqlite3_file *fd, i64 iOff, int nAmt, void **pp){
#if SQLITE_MAX_MMAP_SIZE>0
if( pFd->mmapSizeMax>0 ){
+ /* Ensure that there is always at least a 256 byte buffer of addressable
+ ** memory following the returned page. If the database is corrupt,
+ ** SQLite may overread the page slightly (in practice only a few bytes,
+ ** but 256 is safe, round, number). */
+ const int nEofBuffer = 256;
if( pFd->pMapRegion==0 ){
int rc = winMapfile(pFd, -1);
if( rc!=SQLITE_OK ){
@@ -45099,7 +53659,8 @@ static int winFetch(sqlite3_file *fd, i64 iOff, int nAmt, void **pp){
return rc;
}
}
- if( pFd->mmapSize >= iOff+nAmt ){
+ if( pFd->mmapSize >= (iOff+nAmt+nEofBuffer) ){
+ assert( pFd->pMapRegion!=0 );
*pp = &((u8 *)pFd->pMapRegion)[iOff];
pFd->nFetchOut++;
}
@@ -45231,47 +53792,6 @@ static winVfsAppData winNolockAppData = {
** sqlite3_vfs object.
*/
-#if defined(__CYGWIN__)
-/*
-** Convert a filename from whatever the underlying operating system
-** supports for filenames into UTF-8. Space to hold the result is
-** obtained from malloc and must be freed by the calling function.
-*/
-static char *winConvertToUtf8Filename(const void *zFilename){
- char *zConverted = 0;
- if( osIsNT() ){
- zConverted = winUnicodeToUtf8(zFilename);
- }
-#ifdef SQLITE_WIN32_HAS_ANSI
- else{
- zConverted = winMbcsToUtf8(zFilename, osAreFileApisANSI());
- }
-#endif
- /* caller will handle out of memory */
- return zConverted;
-}
-#endif
-
-/*
-** Convert a UTF-8 filename into whatever form the underlying
-** operating system wants filenames in. Space to hold the result
-** is obtained from malloc and must be freed by the calling
-** function.
-*/
-static void *winConvertFromUtf8Filename(const char *zFilename){
- void *zConverted = 0;
- if( osIsNT() ){
- zConverted = winUtf8ToUnicode(zFilename);
- }
-#ifdef SQLITE_WIN32_HAS_ANSI
- else{
- zConverted = winUtf8ToMbcs(zFilename, osAreFileApisANSI());
- }
-#endif
- /* caller will handle out of memory */
- return zConverted;
-}
-
/*
** This function returns non-zero if the specified UTF-8 string buffer
** ends with a directory separator character or one was successfully
@@ -45284,7 +53804,14 @@ static int winMakeEndInDirSep(int nBuf, char *zBuf){
if( winIsDirSep(zBuf[nLen-1]) ){
return 1;
}else if( nLen+1mxPathname; nBuf = nMax + 2;
+ nMax = pVfs->mxPathname;
+ nBuf = 2 + (i64)nMax;
zBuf = sqlite3MallocZero( nBuf );
if( !zBuf ){
OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n"));
@@ -45329,22 +53871,25 @@ static int winGetTempname(sqlite3_vfs *pVfs, char **pzBuf){
*/
nDir = nMax - (nPre + 15);
assert( nDir>0 );
- if( sqlite3_temp_directory ){
+ if( winTempDirDefined() ){
int nDirLen = sqlite3Strlen30(sqlite3_temp_directory);
if( nDirLen>0 ){
if( !winIsDirSep(sqlite3_temp_directory[nDirLen-1]) ){
nDirLen++;
}
if( nDirLen>nDir ){
+ sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR));
sqlite3_free(zBuf);
OSTRACE(("TEMP-FILENAME rc=SQLITE_ERROR\n"));
return winLogError(SQLITE_ERROR, 0, "winGetTempname1", 0);
}
sqlite3_snprintf(nMax, zBuf, "%s", sqlite3_temp_directory);
}
+ sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR));
}
+
#if defined(__CYGWIN__)
- else{
+ else if( osGetenv!=NULL ){
static const char *azDirs[] = {
0, /* getenv("SQLITE_TMPDIR") */
0, /* getenv("TMPDIR") */
@@ -45360,11 +53905,11 @@ static int winGetTempname(sqlite3_vfs *pVfs, char **pzBuf){
unsigned int i;
const char *zDir = 0;
- if( !azDirs[0] ) azDirs[0] = getenv("SQLITE_TMPDIR");
- if( !azDirs[1] ) azDirs[1] = getenv("TMPDIR");
- if( !azDirs[2] ) azDirs[2] = getenv("TMP");
- if( !azDirs[3] ) azDirs[3] = getenv("TEMP");
- if( !azDirs[4] ) azDirs[4] = getenv("USERPROFILE");
+ if( !azDirs[0] ) azDirs[0] = osGetenv("SQLITE_TMPDIR");
+ if( !azDirs[1] ) azDirs[1] = osGetenv("TMPDIR");
+ if( !azDirs[2] ) azDirs[2] = osGetenv("TMP");
+ if( !azDirs[3] ) azDirs[3] = osGetenv("TEMP");
+ if( !azDirs[4] ) azDirs[4] = osGetenv("USERPROFILE");
for(i=0; i>= 8;
zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ];
}
zBuf[j] = 0;
@@ -45544,7 +54058,7 @@ static int winIsDir(const void *zConverted){
return 0; /* Invalid name? */
}
attr = sAttrData.dwFileAttributes;
-#if SQLITE_OS_WINCE==0
+#if SQLITE_OS_WINCE==0 && defined(SQLITE_WIN32_HAS_ANSI)
}else{
attr = osGetFileAttributesA((char*)zConverted);
#endif
@@ -45560,6 +54074,12 @@ static int winAccess(
int *pResOut /* OUT: Result */
);
+/*
+** The Windows version of xAccess() accepts an extra bit in the flags
+** parameter that prevents an anti-virus retry loop.
+*/
+#define NORETRY 0x4000
+
/*
** Open a file.
*/
@@ -45584,6 +54104,7 @@ static int winOpen(
void *zConverted; /* Filename in OS encoding */
const char *zUtf8Name = zName; /* Filename in UTF-8 encoding */
int cnt = 0;
+ int isRO = 0; /* file is known to be accessible readonly */
/* If argument zPath is a NULL pointer, this function is required to open
** a temporary file. Use this buffer to store the file name in.
@@ -45592,7 +54113,7 @@ static int winOpen(
int rc = SQLITE_OK; /* Function Return Code */
#if !defined(NDEBUG) || SQLITE_OS_WINCE
- int eType = flags&0xFFFFFF00; /* Type of file to open */
+ int eType = flags&0x0FFF00; /* Type of file to open */
#endif
int isExclusive = (flags & SQLITE_OPEN_EXCLUSIVE);
@@ -45603,7 +54124,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
));
@@ -45624,17 +54145,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
);
@@ -45642,13 +54163,6 @@ static int winOpen(
memset(pFile, 0, sizeof(winFile));
pFile->h = INVALID_HANDLE_VALUE;
-#if SQLITE_OS_WINRT
- if( !zUtf8Name && !sqlite3_temp_directory ){
- sqlite3_log(SQLITE_ERROR,
- "sqlite3_temp_directory variable should be set for WinRT");
- }
-#endif
-
/* If the second argument to this function is NULL, generate a
** temporary file name to use
*/
@@ -45706,7 +54220,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
@@ -45727,31 +54245,6 @@ static int winOpen(
#endif
if( osIsNT() ){
-#if SQLITE_OS_WINRT
- CREATEFILE2_EXTENDED_PARAMETERS extendedParameters;
- extendedParameters.dwSize = sizeof(CREATEFILE2_EXTENDED_PARAMETERS);
- extendedParameters.dwFileAttributes =
- dwFlagsAndAttributes & FILE_ATTRIBUTE_MASK;
- extendedParameters.dwFileFlags = dwFlagsAndAttributes & FILE_FLAG_MASK;
- extendedParameters.dwSecurityQosFlags = SECURITY_ANONYMOUS;
- extendedParameters.lpSecurityAttributes = NULL;
- extendedParameters.hTemplateFile = NULL;
- do{
- h = osCreateFile2((LPCWSTR)zConverted,
- dwDesiredAccess,
- dwShareMode,
- dwCreationDisposition,
- &extendedParameters);
- if( h!=INVALID_HANDLE_VALUE ) break;
- if( isReadWrite ){
- int rc2, isRO = 0;
- sqlite3BeginBenignMalloc();
- rc2 = winAccess(pVfs, zName, SQLITE_ACCESS_READ, &isRO);
- sqlite3EndBenignMalloc();
- if( rc2==SQLITE_OK && isRO ) break;
- }
- }while( winRetryIoerr(&cnt, &lastErrno) );
-#else
do{
h = osCreateFileW((LPCWSTR)zConverted,
dwDesiredAccess,
@@ -45761,14 +54254,13 @@ static int winOpen(
NULL);
if( h!=INVALID_HANDLE_VALUE ) break;
if( isReadWrite ){
- int rc2, isRO = 0;
+ int rc2;
sqlite3BeginBenignMalloc();
- rc2 = winAccess(pVfs, zName, SQLITE_ACCESS_READ, &isRO);
+ rc2 = winAccess(pVfs, zUtf8Name, SQLITE_ACCESS_READ|NORETRY, &isRO);
sqlite3EndBenignMalloc();
if( rc2==SQLITE_OK && isRO ) break;
}
}while( winRetryIoerr(&cnt, &lastErrno) );
-#endif
}
#ifdef SQLITE_WIN32_HAS_ANSI
else{
@@ -45781,9 +54273,9 @@ static int winOpen(
NULL);
if( h!=INVALID_HANDLE_VALUE ) break;
if( isReadWrite ){
- int rc2, isRO = 0;
+ int rc2;
sqlite3BeginBenignMalloc();
- rc2 = winAccess(pVfs, zName, SQLITE_ACCESS_READ, &isRO);
+ rc2 = winAccess(pVfs, zUtf8Name, SQLITE_ACCESS_READ|NORETRY, &isRO);
sqlite3EndBenignMalloc();
if( rc2==SQLITE_OK && isRO ) break;
}
@@ -45798,7 +54290,7 @@ static int winOpen(
if( h==INVALID_HANDLE_VALUE ){
sqlite3_free(zConverted);
sqlite3_free(zTmpname);
- if( isReadWrite && !isExclusive ){
+ if( isReadWrite && isRO && !isExclusive ){
return winOpen(pVfs, zName, id,
((flags|SQLITE_OPEN_READONLY) &
~(SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE)),
@@ -45846,13 +54338,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;
@@ -45903,25 +54397,7 @@ static int winDelete(
}
if( osIsNT() ){
do {
-#if SQLITE_OS_WINRT
- WIN32_FILE_ATTRIBUTE_DATA sAttrData;
- memset(&sAttrData, 0, sizeof(sAttrData));
- if ( osGetFileAttributesExW(zConverted, GetFileExInfoStandard,
- &sAttrData) ){
- attr = sAttrData.dwFileAttributes;
- }else{
- lastErrno = osGetLastError();
- if( lastErrno==ERROR_FILE_NOT_FOUND
- || lastErrno==ERROR_PATH_NOT_FOUND ){
- rc = SQLITE_IOERR_DELETE_NOENT; /* Already gone? */
- }else{
- rc = SQLITE_ERROR;
- }
- break;
- }
-#else
attr = osGetFileAttributesW(zConverted);
-#endif
if ( attr==INVALID_FILE_ATTRIBUTES ){
lastErrno = osGetLastError();
if( lastErrno==ERROR_FILE_NOT_FOUND
@@ -45998,12 +54474,25 @@ static int winAccess(
int rc = 0;
DWORD lastErrno = 0;
void *zConverted;
+ int noRetry = 0; /* Do not use winRetryIoerr() */
UNUSED_PARAMETER(pVfs);
+ if( (flags & NORETRY)!=0 ){
+ noRetry = 1;
+ flags &= ~NORETRY;
+ }
+
SimulateIOError( return SQLITE_IOERR_ACCESS; );
OSTRACE(("ACCESS name=%s, flags=%x, pResOut=%p\n",
zFilename, flags, pResOut));
+ if( zFilename==0 ){
+ *pResOut = 0;
+ OSTRACE(("ACCESS name=%s, pResOut=%p, *pResOut=%d, rc=SQLITE_OK\n",
+ zFilename, pResOut, *pResOut));
+ return SQLITE_OK;
+ }
+
zConverted = winConvertFromUtf8Filename(zFilename);
if( zConverted==0 ){
OSTRACE(("ACCESS name=%s, rc=SQLITE_IOERR_NOMEM\n", zFilename));
@@ -46015,7 +54504,10 @@ static int winAccess(
memset(&sAttrData, 0, sizeof(sAttrData));
while( !(rc = osGetFileAttributesExW((LPCWSTR)zConverted,
GetFileExInfoStandard,
- &sAttrData)) && winRetryIoerr(&cnt, &lastErrno) ){}
+ &sAttrData))
+ && !noRetry
+ && winRetryIoerr(&cnt, &lastErrno)
+ ){ /* Loop until true */}
if( rc ){
/* For an SQLITE_ACCESS_EXISTS query, treat a zero-length file
** as if it does not exist.
@@ -46028,6 +54520,7 @@ static int winAccess(
attr = sAttrData.dwFileAttributes;
}
}else{
+ if( noRetry ) lastErrno = osGetLastError();
winLogIoerr(cnt, __LINE__);
if( lastErrno!=ERROR_FILE_NOT_FOUND && lastErrno!=ERROR_PATH_NOT_FOUND ){
sqlite3_free(zConverted);
@@ -46062,6 +54555,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.
@@ -46072,6 +54576,7 @@ static BOOL winIsDriveLetterAndColon(
return ( sqlite3Isalpha(zPathname[0]) && zPathname[1]==':' );
}
+#ifdef _WIN32
/*
** Returns non-zero if the specified path name should be used verbatim. If
** non-zero is returned from this function, the calling function must simply
@@ -46108,89 +54613,172 @@ static BOOL winIsVerbatimPathname(
*/
return FALSE;
}
+#endif /* _WIN32 */
+
+#ifdef __CYGWIN__
+/*
+** Simplify a filename into its canonical form
+** by making the following changes:
+**
+** * convert any '/' to '\' (win32) or reverse (Cygwin)
+** * removing any trailing and duplicate / (except for UNC paths)
+** * convert /./ into just /
+**
+** Changes are made in-place. Return the new name length.
+**
+** The original filename is in z[0..]. If the path is shortened,
+** no-longer used bytes will be written by '\0'.
+*/
+static void winSimplifyName(char *z){
+ int i, j;
+ for(i=j=0; z[i]; ++i){
+ if( winIsDirSep(z[i]) ){
+#if !defined(SQLITE_TEST)
+ /* Some test-cases assume that "./foo" and "foo" are different */
+ if( z[i+1]=='.' && winIsDirSep(z[i+2]) ){
+ ++i;
+ continue;
+ }
+#endif
+ if( !z[i+1] || (winIsDirSep(z[i+1]) && (i!=0)) ){
+ continue;
+ }
+ z[j++] = osGetenv?'/':'\\';
+ }else{
+ z[j++] = z[i];
+ }
+ }
+ while(jnOut ){
+ /* SQLite assumes that xFullPathname() nul-terminates the output buffer
+ ** even if it returns an error. */
+ zOut[iOff] = '\0';
+ return SQLITE_CANTOPEN_BKPT;
+ }
+ sqlite3_snprintf(nOut-iOff, &zOut[iOff], "%s", zPath);
+ return SQLITE_OK;
+}
+#endif /* __CYGWIN__ */
/*
** Turn a relative pathname into a full pathname. Write the full
** pathname into zOut[]. zOut[] will be at least pVfs->mxPathname
** bytes in size.
*/
-static int winFullPathname(
+static int winFullPathnameNoMutex(
sqlite3_vfs *pVfs, /* Pointer to vfs object */
const char *zRelative, /* Possibly relative input path */
int nFull, /* Size of output buffer in bytes */
char *zFull /* Output buffer */
){
-#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && !defined(__CYGWIN__)
- DWORD nByte;
+#if !SQLITE_OS_WINCE
+ int nByte;
void *zConverted;
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++;
}
-#if defined(__CYGWIN__)
SimulateIOError( return SQLITE_ERROR );
- UNUSED_PARAMETER(nFull);
- assert( nFull>=pVfs->mxPathname );
- if ( sqlite3_data_directory && !winIsVerbatimPathname(zRelative) ){
- /*
- ** NOTE: We are dealing with a relative path name and the data
- ** directory has been set. Therefore, use it as the basis
- ** for converting the relative path name to an absolute
- ** one by prepending the data directory and a slash.
- */
- char *zOut = sqlite3MallocZero( pVfs->mxPathname+1 );
- if( !zOut ){
- return SQLITE_IOERR_NOMEM_BKPT;
- }
- if( cygwin_conv_path(
- (osIsNT() ? CCP_POSIX_TO_WIN_W : CCP_POSIX_TO_WIN_A) |
- CCP_RELATIVE, zRelative, zOut, pVfs->mxPathname+1)<0 ){
- sqlite3_free(zOut);
- return winLogError(SQLITE_CANTOPEN_CONVPATH, (DWORD)errno,
- "winFullPathname1", zRelative);
- }else{
- char *zUtf8 = winConvertToUtf8Filename(zOut);
- if( !zUtf8 ){
- sqlite3_free(zOut);
- return SQLITE_IOERR_NOMEM_BKPT;
- }
- sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s%c%s",
- sqlite3_data_directory, winGetDirSep(), zUtf8);
- sqlite3_free(zUtf8);
- sqlite3_free(zOut);
- }
- }else{
- char *zOut = sqlite3MallocZero( pVfs->mxPathname+1 );
- if( !zOut ){
- return SQLITE_IOERR_NOMEM_BKPT;
- }
- if( cygwin_conv_path(
- (osIsNT() ? CCP_POSIX_TO_WIN_W : CCP_POSIX_TO_WIN_A),
- zRelative, zOut, pVfs->mxPathname+1)<0 ){
- sqlite3_free(zOut);
- return winLogError(SQLITE_CANTOPEN_CONVPATH, (DWORD)errno,
- "winFullPathname2", zRelative);
- }else{
- char *zUtf8 = winConvertToUtf8Filename(zOut);
- if( !zUtf8 ){
- sqlite3_free(zOut);
- return SQLITE_IOERR_NOMEM_BKPT;
- }
- sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s", zUtf8);
- sqlite3_free(zUtf8);
- sqlite3_free(zOut);
+
+#ifdef __CYGWIN__
+ if( osGetcwd ){
+ zFull[nFull-1] = '\0';
+ if( !winIsDriveLetterAndColon(zRelative) || !winIsDirSep(zRelative[2]) ){
+ int rc = SQLITE_OK;
+ int nLink = 1; /* Number of symbolic links followed so far */
+ const char *zIn = zRelative; /* Input path for each iteration of loop */
+ char *zDel = 0;
+ struct stat buf;
+
+ UNUSED_PARAMETER(pVfs);
+
+ do {
+ /* Call lstat() on path zIn. Set bLink to true if the path is a symbolic
+ ** link, or false otherwise. */
+ int bLink = 0;
+ if( osLstat && osReadlink ) {
+ if( osLstat(zIn, &buf)!=0 ){
+ int myErrno = osErrno;
+ if( myErrno!=ENOENT ){
+ rc = winLogError(SQLITE_CANTOPEN_BKPT, (DWORD)myErrno, "lstat", zIn);
+ }
+ }else{
+ bLink = ((buf.st_mode & 0170000) == 0120000);
+ }
+
+ if( bLink ){
+ if( zDel==0 ){
+ zDel = sqlite3MallocZero(nFull);
+ if( zDel==0 ) rc = SQLITE_NOMEM;
+ }else if( ++nLink>SQLITE_MAX_SYMLINKS ){
+ rc = SQLITE_CANTOPEN_BKPT;
+ }
+
+ if( rc==SQLITE_OK ){
+ nByte = osReadlink(zIn, zDel, nFull-1);
+ if( nByte ==(DWORD)-1 ){
+ rc = winLogError(SQLITE_CANTOPEN_BKPT, (DWORD)osErrno, "readlink", zIn);
+ }else{
+ if( zDel[0]!='/' ){
+ int n;
+ for(n = sqlite3Strlen30(zIn); n>0 && zIn[n-1]!='/'; n--);
+ if( nByte+n+1>nFull ){
+ rc = SQLITE_CANTOPEN_BKPT;
+ }else{
+ memmove(&zDel[n], zDel, nByte+1);
+ memcpy(zDel, zIn, n);
+ nByte += n;
+ }
+ }
+ zDel[nByte] = '\0';
+ }
+ }
+
+ zIn = zDel;
+ }
+ }
+
+ assert( rc!=SQLITE_OK || zIn!=zFull || zIn[0]=='/' );
+ if( rc==SQLITE_OK && zIn!=zFull ){
+ rc = mkFullPathname(zIn, zFull, nFull);
+ }
+ if( bLink==0 ) break;
+ zIn = zFull;
+ }while( rc==SQLITE_OK );
+
+ sqlite3_free(zDel);
+ winSimplifyName(zFull);
+ return rc;
}
}
- return SQLITE_OK;
-#endif
+#endif /* __CYGWIN__ */
-#if (SQLITE_OS_WINCE || SQLITE_OS_WINRT) && !defined(__CYGWIN__)
+#if SQLITE_OS_WINCE && defined(_WIN32)
SimulateIOError( return SQLITE_ERROR );
/* WinCE has no concept of a relative pathname, or so I am told. */
/* WinRT has no way to convert a relative path to an absolute one. */
@@ -46209,7 +54797,8 @@ static int winFullPathname(
return SQLITE_OK;
#endif
-#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && !defined(__CYGWIN__)
+#if !SQLITE_OS_WINCE
+#if defined(_WIN32)
/* It's odd to simulate an io-error here, but really this is just
** using the io-error infrastructure to test that SQLite handles this
** function failing. This function could fail if, for example, the
@@ -46227,6 +54816,7 @@ static int winFullPathname(
sqlite3_data_directory, winGetDirSep(), zRelative);
return SQLITE_OK;
}
+#endif
zConverted = winConvertFromUtf8Filename(zRelative);
if( zConverted==0 ){
return SQLITE_IOERR_NOMEM_BKPT;
@@ -46265,13 +54855,12 @@ static int winFullPathname(
return winLogError(SQLITE_CANTOPEN_FULLPATH, osGetLastError(),
"winFullPathname3", zRelative);
}
- nByte += 3;
- zTemp = sqlite3MallocZero( nByte*sizeof(zTemp[0]) );
+ zTemp = sqlite3MallocZero( nByte*sizeof(zTemp[0]) + 3*sizeof(zTemp[0]) );
if( zTemp==0 ){
sqlite3_free(zConverted);
return SQLITE_IOERR_NOMEM_BKPT;
}
- nByte = osGetFullPathNameA((char*)zConverted, nByte, zTemp, 0);
+ nByte = osGetFullPathNameA((char*)zConverted, nByte+3, zTemp, 0);
if( nByte==0 ){
sqlite3_free(zConverted);
sqlite3_free(zTemp);
@@ -46284,7 +54873,26 @@ static int winFullPathname(
}
#endif
if( zOut ){
+#ifdef __CYGWIN__
+ if( memcmp(zOut, "\\\\?\\", 4) ){
+ sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s", zOut);
+ }else if( memcmp(zOut+4, "UNC\\", 4) ){
+ sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s", zOut+4);
+ }else{
+ char *p = zOut+6;
+ *p = '\\';
+ if( osGetcwd ){
+ /* On Cygwin, UNC paths use forward slashes */
+ while( *p ){
+ if( *p=='\\' ) *p = '/';
+ ++p;
+ }
+ }
+ sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s", zOut+6);
+ }
+#else
sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s", zOut);
+#endif /* __CYGWIN__ */
sqlite3_free(zOut);
return SQLITE_OK;
}else{
@@ -46292,6 +54900,20 @@ static int winFullPathname(
}
#endif
}
+static int winFullPathname(
+ sqlite3_vfs *pVfs, /* Pointer to vfs object */
+ const char *zRelative, /* Possibly relative input path */
+ int nFull, /* Size of output buffer in bytes */
+ char *zFull /* Output buffer */
+){
+ int rc;
+ MUTEX_LOGIC( sqlite3_mutex *pMutex; )
+ MUTEX_LOGIC( pMutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR); )
+ sqlite3_mutex_enter(pMutex);
+ rc = winFullPathnameNoMutex(pVfs, zRelative, nFull, zFull);
+ sqlite3_mutex_leave(pMutex);
+ return rc;
+}
#ifndef SQLITE_OMIT_LOAD_EXTENSION
/*
@@ -46300,35 +54922,14 @@ static int winFullPathname(
*/
static void *winDlOpen(sqlite3_vfs *pVfs, const char *zFilename){
HANDLE h;
-#if defined(__CYGWIN__)
- int nFull = pVfs->mxPathname+1;
- char *zFull = sqlite3MallocZero( nFull );
- void *zConverted = 0;
- if( zFull==0 ){
- OSTRACE(("DLOPEN name=%s, handle=%p\n", zFilename, (void*)0));
- return 0;
- }
- if( winFullPathname(pVfs, zFilename, nFull, zFull)!=SQLITE_OK ){
- sqlite3_free(zFull);
- OSTRACE(("DLOPEN name=%s, handle=%p\n", zFilename, (void*)0));
- return 0;
- }
- zConverted = winConvertFromUtf8Filename(zFull);
- sqlite3_free(zFull);
-#else
void *zConverted = winConvertFromUtf8Filename(zFilename);
UNUSED_PARAMETER(pVfs);
-#endif
if( zConverted==0 ){
OSTRACE(("DLOPEN name=%s, handle=%p\n", zFilename, (void*)0));
return 0;
}
if( osIsNT() ){
-#if SQLITE_OS_WINRT
- h = osLoadPackagedLibrary((LPCWSTR)zConverted, 0);
-#else
h = osLoadLibraryW((LPCWSTR)zConverted);
-#endif
}
#ifdef SQLITE_WIN32_HAS_ANSI
else{
@@ -46410,23 +55011,16 @@ static int winRandomness(sqlite3_vfs *pVfs, int nBuf, char *zBuf){
DWORD pid = osGetCurrentProcessId();
xorMemory(&e, (unsigned char*)&pid, sizeof(DWORD));
}
-#if SQLITE_OS_WINRT
- {
- ULONGLONG cnt = osGetTickCount64();
- xorMemory(&e, (unsigned char*)&cnt, sizeof(ULONGLONG));
- }
-#else
{
DWORD cnt = osGetTickCount();
xorMemory(&e, (unsigned char*)&cnt, sizeof(DWORD));
}
-#endif /* SQLITE_OS_WINRT */
{
LARGE_INTEGER i;
osQueryPerformanceCounter(&i);
xorMemory(&e, (unsigned char*)&i, sizeof(LARGE_INTEGER));
}
-#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && SQLITE_WIN32_USE_UUID
+#if !SQLITE_OS_WINCE && SQLITE_WIN32_USE_UUID
{
UUID id;
memset(&id, 0, sizeof(UUID));
@@ -46436,7 +55030,7 @@ static int winRandomness(sqlite3_vfs *pVfs, int nBuf, char *zBuf){
osUuidCreateSequential(&id);
xorMemory(&e, (unsigned char*)&id, sizeof(UUID));
}
-#endif /* !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && SQLITE_WIN32_USE_UUID */
+#endif /* !SQLITE_OS_WINCE && SQLITE_WIN32_USE_UUID */
return e.nXor>nBuf ? nBuf : e.nXor;
#endif /* defined(SQLITE_TEST) || defined(SQLITE_OMIT_RANDOMNESS) */
}
@@ -46667,15 +55261,16 @@ SQLITE_API int sqlite3_os_init(void){
/* Double-check that the aSyscall[] array has been constructed
** correctly. See ticket [bb3a86e890c8e96ab] */
- assert( ArraySize(aSyscall)==80 );
+ assert( ArraySize(aSyscall)==81 );
+ assert( strcmp(aSyscall[0].zName,"AreFileApisANSI")==0 );
+ assert( strcmp(aSyscall[20].zName,"GetFileAttributesA")==0 );
+ assert( strcmp(aSyscall[40].zName,"HeapReAlloc")==0 );
+ assert( strcmp(aSyscall[60].zName,"WideCharToMultiByte")==0 );
+ assert( strcmp(aSyscall[80].zName,"cygwin_conv_path")==0 );
/* get memory map allocation granularity */
memset(&winSysInfo, 0, sizeof(SYSTEM_INFO));
-#if SQLITE_OS_WINRT
- osGetNativeSystemInfo(&winSysInfo);
-#else
osGetSystemInfo(&winSysInfo);
-#endif
assert( winSysInfo.dwAllocationGranularity>0 );
assert( winSysInfo.dwPageSize>0 );
@@ -46699,17 +55294,9 @@ SQLITE_API int sqlite3_os_init(void){
}
SQLITE_API int sqlite3_os_end(void){
-#if SQLITE_OS_WINRT
- if( sleepObj!=NULL ){
- osCloseHandle(sleepObj);
- sleepObj = NULL;
- }
-#endif
-
#ifndef SQLITE_OMIT_WAL
winBigLock = 0;
#endif
-
return SQLITE_OK;
}
@@ -46736,31 +55323,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))
-/* An open file */
-struct MemFile {
- sqlite3_file base; /* IO methods */
+/* 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 */
+ 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
*/
@@ -46771,6 +55415,7 @@ static int memdbTruncate(sqlite3_file*, sqlite3_int64 size);
static int memdbSync(sqlite3_file*, int flags);
static int memdbFileSize(sqlite3_file*, sqlite3_int64 *pSize);
static int memdbLock(sqlite3_file*, int);
+static int memdbUnlock(sqlite3_file*, int);
/* static int memdbCheckReservedLock(sqlite3_file*, int *pResOut);// not used */
static int memdbFileControl(sqlite3_file*, int op, void *pArg);
/* static int memdbSectorSize(sqlite3_file*); // not used */
@@ -46801,7 +55446,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 */
@@ -46814,7 +55459,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 = {
@@ -46826,7 +55474,7 @@ static const sqlite3_io_methods memdb_io_methods = {
memdbSync, /* xSync */
memdbFileSize, /* xFileSize */
memdbLock, /* xLock */
- memdbLock, /* xUnlock - same as xLock in this case */
+ memdbUnlock, /* xUnlock */
0, /* memdbCheckReservedLock, */ /* xCheckReservedLock */
memdbFileControl, /* xFileControl */
0, /* memdbSectorSize,*/ /* xSectorSize */
@@ -46839,17 +55487,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;
}
@@ -46857,27 +55556,30 @@ 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 ){
+ if( (p->mFlags & SQLITE_DESERIALIZE_RESIZEABLE)==0 || NEVER(p->nMmap>0) ){
return SQLITE_FULL;
}
if( newSz>p->szMax ){
@@ -46885,8 +55587,8 @@ static int memdbEnlarge(MemFile *p, sqlite3_int64 newSz){
}
newSz *= 2;
if( newSz>p->szMax ) newSz = p->szMax;
- pNew = sqlite3_realloc64(p->aData, newSz);
- if( pNew==0 ) return SQLITE_NOMEM;
+ pNew = sqlite3Realloc(p->aData, newSz);
+ if( pNew==0 ) return SQLITE_IOERR_NOMEM;
p->aData = pNew;
p->szAlloc = newSz;
return SQLITE_OK;
@@ -46901,19 +55603,27 @@ static int memdbWrite(
int iAmt,
sqlite_int64 iOfst
){
- MemFile *p = (MemFile *)pFile;
- if( NEVER(p->mFlags & SQLITE_DESERIALIZE_READONLY) ) return SQLITE_READONLY;
+ 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->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;
}
@@ -46925,16 +55635,25 @@ 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( size>p->sz ){
+ /* This can only happen with a corrupt wal mode db */
+ rc = SQLITE_CORRUPT;
+ }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;
}
@@ -46942,8 +55661,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;
}
@@ -46951,19 +55672,90 @@ 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;
- if( eLock>SQLITE_LOCK_SHARED
- && (p->mFlags & SQLITE_DESERIALIZE_READONLY)!=0
- ){
- return SQLITE_READONLY;
+ MemFile *pThis = (MemFile*)pFile;
+ MemStore *p = pThis->pStore;
+ int rc = SQLITE_OK;
+ if( eLock<=pThis->eLock ) return SQLITE_OK;
+ memdbEnter(p);
+
+ assert( p->nWrLock==0 || p->nWrLock==1 );
+ assert( pThis->eLock<=SQLITE_LOCK_SHARED || p->nWrLock==1 );
+ assert( pThis->eLock==SQLITE_LOCK_NONE || p->nRdLock>=1 );
+
+ if( eLock>SQLITE_LOCK_SHARED && (p->mFlags & SQLITE_DESERIALIZE_READONLY) ){
+ rc = SQLITE_READONLY;
+ }else{
+ switch( eLock ){
+ case SQLITE_LOCK_SHARED: {
+ assert( pThis->eLock==SQLITE_LOCK_NONE );
+ if( p->nWrLock>0 ){
+ rc = SQLITE_BUSY;
+ }else{
+ p->nRdLock++;
+ }
+ break;
+ };
+
+ case SQLITE_LOCK_RESERVED:
+ case SQLITE_LOCK_PENDING: {
+ assert( pThis->eLock>=SQLITE_LOCK_SHARED );
+ if( ALWAYS(pThis->eLock==SQLITE_LOCK_SHARED) ){
+ if( p->nWrLock>0 ){
+ rc = SQLITE_BUSY;
+ }else{
+ p->nWrLock = 1;
+ }
+ }
+ break;
+ }
+
+ default: {
+ assert( eLock==SQLITE_LOCK_EXCLUSIVE );
+ assert( pThis->eLock>=SQLITE_LOCK_SHARED );
+ if( p->nRdLock>1 ){
+ rc = SQLITE_BUSY;
+ }else if( pThis->eLock==SQLITE_LOCK_SHARED ){
+ p->nWrLock = 1;
+ }
+ break;
+ }
+ }
+ }
+ if( rc==SQLITE_OK ) pThis->eLock = eLock;
+ memdbLeave(p);
+ return rc;
+}
+
+/*
+** Unlock an memdb-file.
+*/
+static int memdbUnlock(sqlite3_file *pFile, int eLock){
+ MemFile *pThis = (MemFile*)pFile;
+ MemStore *p = pThis->pStore;
+ if( eLock>=pThis->eLock ) return SQLITE_OK;
+ memdbEnter(p);
+
+ assert( eLock==SQLITE_LOCK_SHARED || eLock==SQLITE_LOCK_NONE );
+ if( eLock==SQLITE_LOCK_SHARED ){
+ if( ALWAYS(pThis->eLock>SQLITE_LOCK_SHARED) ){
+ p->nWrLock--;
+ }
+ }else{
+ if( pThis->eLock>SQLITE_LOCK_SHARED ){
+ p->nWrLock--;
+ }
+ p->nRdLock--;
}
- p->eLock = eLock;
+
+ pThis->eLock = eLock;
+ memdbLeave(p);
return SQLITE_OK;
}
-#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;
@@ -46971,12 +55763,14 @@ 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;
@@ -46994,6 +55788,7 @@ static int memdbFileControl(sqlite3_file *pFile, int op, void *pArg){
*(sqlite3_int64*)pArg = iLimit;
rc = SQLITE_OK;
}
+ memdbLeave(p);
return rc;
}
@@ -47010,7 +55805,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;
@@ -47023,20 +55819,26 @@ static int memdbFetch(
int iAmt,
void **pp
){
- MemFile *p = (MemFile *)pFile;
- if( iOfst+iAmt>p->sz ){
+ MemStore *p = ((MemFile*)pFile)->pStore;
+ memdbEnter(p);
+ if( iOfst+iAmt>p->sz || (p->mFlags & SQLITE_DESERIALIZE_RESIZEABLE)!=0 ){
*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;
}
@@ -47046,24 +55848,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;
- if( (flags & SQLITE_OPEN_MAIN_DB)==0 ){
- return ORIGVFS(pVfs)->xOpen(ORIGVFS(pVfs), zName, pFile, flags, pOutFlags);
+ MemFile *pFile = (MemFile*)pFd;
+ MemStore *p = 0;
+ int szName;
+ UNUSED_PARAMETER(pVfs);
+
+ memset(pFile, 0, sizeof(*pFile));
+ szName = sqlite3Strlen30(zName);
+ if( szName>1 && (zName[0]=='/' || 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) + (i64)szName + 3 );
+ if( p==0 ){
+ sqlite3_mutex_leave(pVfsMutex);
+ return SQLITE_NOMEM;
+ }
+ apNew = sqlite3Realloc(memdb_g.apMemStore,
+ sizeof(apNew[0])*(1+(i64)memdb_g.nMemStore) );
+ 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;
}
- memset(p, 0, sizeof(*p));
- p->mFlags = SQLITE_DESERIALIZE_RESIZEABLE | SQLITE_DESERIALIZE_FREEONCLOSE;
- assert( pOutFlags!=0 ); /* True because flags==SQLITE_OPEN_MAIN_DB */
- *pOutFlags = flags | SQLITE_OPEN_MEMORY;
- p->base.pMethods = &memdb_io_methods;
- p->szMax = sqlite3GlobalConfig.mxMemdbSize;
+ pFile->pStore = p;
+ if( pOutFlags!=0 ){
+ *pOutFlags = flags | SQLITE_OPEN_MEMORY;
+ }
+ 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,
@@ -47082,11 +55943,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;
}
@@ -47097,11 +55961,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;
}
@@ -47115,7 +55980,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){
@@ -47137,7 +56002,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){
@@ -47145,7 +56010,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){
@@ -47174,9 +56039,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;
}
@@ -47195,7 +56065,7 @@ SQLITE_API unsigned char *sqlite3_serialize(
sqlite3_int64 sz;
int szPage = 0;
sqlite3_stmt *pStmt = 0;
- unsigned char *pOut;
+ unsigned char *pOut = 0;
char *zSql;
int rc;
@@ -47205,34 +56075,43 @@ SQLITE_API unsigned char *sqlite3_serialize(
return 0;
}
#endif
+ sqlite3_mutex_enter(db->mutex);
if( zSchema==0 ) zSchema = db->aDb[0].zDbSName;
p = memdbFromDbSchema(db, zSchema);
iDb = sqlite3FindDbName(db, zSchema);
if( piSize ) *piSize = -1;
- if( iDb<0 ) return 0;
+ if( iDb<0 ) goto serialize_out;
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;
+ goto serialize_out;
}
pBt = db->aDb[iDb].pBt;
- if( pBt==0 ) return 0;
+ if( pBt==0 ) goto serialize_out;
szPage = sqlite3BtreeGetPageSize(pBt);
zSql = sqlite3_mprintf("PRAGMA \"%w\".page_count", zSchema);
rc = zSql ? sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0) : SQLITE_NOMEM;
sqlite3_free(zSql);
- if( rc ) return 0;
+ if( rc ) goto serialize_out;
rc = sqlite3_step(pStmt);
- if( rc!=SQLITE_ROW ){
- pOut = 0;
- }else{
+ if( rc==SQLITE_ROW ){
sz = sqlite3_column_int64(pStmt, 0)*szPage;
+ if( sz==0 ){
+ sqlite3_reset(pStmt);
+ sqlite3_exec(db, "BEGIN IMMEDIATE; COMMIT;", 0, 0, 0);
+ rc = sqlite3_step(pStmt);
+ if( rc==SQLITE_ROW ){
+ sz = sqlite3_column_int64(pStmt, 0)*szPage;
+ }
+ }
if( piSize ) *piSize = sz;
if( mFlags & SQLITE_SERIALIZE_NOCOPY ){
pOut = 0;
@@ -47251,12 +56130,15 @@ SQLITE_API unsigned char *sqlite3_serialize(
}else{
memset(pTo, 0, szPage);
}
- sqlite3PagerUnref(pPage);
+ sqlite3PagerUnref(pPage);
}
}
}
}
sqlite3_finalize(pStmt);
+
+ serialize_out:
+ sqlite3_mutex_leave(db->mutex);
return pOut;
}
@@ -47287,59 +56169,78 @@ SQLITE_API int sqlite3_deserialize(
sqlite3_mutex_enter(db->mutex);
if( zSchema==0 ) zSchema = db->aDb[0].zDbSName;
iDb = sqlite3FindDbName(db, zSchema);
- if( iDb<0 ){
+ testcase( iDb==1 );
+ if( iDb<2 && 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;
- rc = sqlite3_step(pStmt);
+ sqlite3_step(pStmt);
db->init.reopenMemdb = 0;
- if( rc!=SQLITE_DONE ){
- rc = SQLITE_ERROR;
+ rc = sqlite3_finalize(pStmt);
+ if( rc!=SQLITE_OK ){
goto end_deserialize;
}
p = memdbFromDbSchema(db, zSchema);
if( p==0 ){
rc = SQLITE_ERROR;
}else{
- p->aData = pData;
- p->sz = szDb;
- p->szAlloc = szBuf;
- p->szMax = szBuf;
- if( p->szMaxszMax = sqlite3GlobalConfig.mxMemdbSize;
- }
- 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;
}
-/*
+/*
+** Return true if the VFS is the memvfs.
+*/
+SQLITE_PRIVATE int sqlite3IsMemdb(const sqlite3_vfs *pVfs){
+ return pVfs==&memdb_vfs;
+}
+
+/*
** 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(szu.aHash[h] ){
if (p->nSet<(BITVEC_NINT-1)) {
goto bitvec_set_end;
@@ -47561,7 +56463,9 @@ SQLITE_PRIVATE int sqlite3BitvecSet(Bitvec *p, u32 i){
}else{
memcpy(aiValues, p->u.aHash, sizeof(p->u.aHash));
memset(p->u.apSub, 0, sizeof(p->u.apSub));
- p->iDivisor = (p->iSize + BITVEC_NPTR - 1)/BITVEC_NPTR;
+ p->iDivisor = p->iSize/BITVEC_NPTR;
+ if( (p->iSize%BITVEC_NPTR)!=0 ) p->iDivisor++;
+ if( p->iDivisoriDivisor = BITVEC_NBIT;
rc = sqlite3BitvecSet(p, i);
for(j=0; jiSize<=BITVEC_NBIT ){
- p->u.aBitmap[i/BITVEC_SZELEM] &= ~(1 << (i&(BITVEC_SZELEM-1)));
+ p->u.aBitmap[i/BITVEC_SZELEM] &= ~(BITVEC_TELEM)(1<<(i&(BITVEC_SZELEM-1)));
}else{
unsigned int j;
u32 *aiValues = pBuf;
@@ -47638,6 +56542,52 @@ SQLITE_PRIVATE u32 sqlite3BitvecSize(Bitvec *p){
return p->iSize;
}
+#ifdef SQLITE_DEBUG
+/*
+** Show the content of a Bitvec option and its children. Indent
+** everything by n spaces. Add x to each bitvec value.
+**
+** From a debugger such as gdb, one can type:
+**
+** call sqlite3ShowBitvec(p)
+**
+** For some Bitvec p and see a recursive view of the Bitvec's content.
+*/
+static void showBitvec(Bitvec *p, int n, unsigned x){
+ int i;
+ if( p==0 ){
+ printf("NULL\n");
+ return;
+ }
+ printf("Bitvec 0x%p iSize=%u", p, p->iSize);
+ if( p->iSize<=BITVEC_NBIT ){
+ printf(" bitmap\n");
+ printf("%*s bits:", n, "");
+ for(i=1; i<=BITVEC_NBIT; i++){
+ if( sqlite3BitvecTest(p,i) ) printf(" %u", x+(unsigned)i);
+ }
+ printf("\n");
+ }else if( p->iDivisor==0 ){
+ printf(" hash with %u entries\n", p->nSet);
+ printf("%*s bits:", n, "");
+ for(i=0; iu.aHash[i] ) printf(" %u", x+(unsigned)p->u.aHash[i]);
+ }
+ printf("\n");
+ }else{
+ printf(" sub-bitvec with iDivisor=%u\n", p->iDivisor);
+ for(i=0; iu.apSub[i]==0 ) continue;
+ printf("%*s apSub[%d]=", n, "", i);
+ showBitvec(p->u.apSub[i], n+4, i*p->iDivisor);
+ }
+ }
+}
+SQLITE_PRIVATE void sqlite3ShowBitvec(Bitvec *p){
+ showBitvec(p, 0, 0);
+}
+#endif
+
#ifndef SQLITE_UNTESTABLE
/*
** Let V[] be an array of unsigned characters sufficient to hold
@@ -47646,9 +56596,10 @@ SQLITE_PRIVATE u32 sqlite3BitvecSize(Bitvec *p){
** individual bits within V.
*/
#define SETBIT(V,I) V[I>>3] |= (1<<(I&7))
-#define CLEARBIT(V,I) V[I>>3] &= ~(1<<(I&7))
+#define CLEARBIT(V,I) V[I>>3] &= ~(BITVEC_TELEM)(1<<(I&7))
#define TESTBIT(V,I) (V[I>>3]&(1<<(I&7)))!=0
+
/*
** This routine runs an extensive test of the Bitvec code.
**
@@ -47657,7 +56608,7 @@ SQLITE_PRIVATE u32 sqlite3BitvecSize(Bitvec *p){
** by 0, 1, or 3 operands, depending on the opcode. Another
** opcode follows immediately after the last operand.
**
-** There are 6 opcodes numbered from 0 through 5. 0 is the
+** There are opcodes numbered starting with 0. 0 is the
** "halt" opcode and causes the test to end.
**
** 0 Halt and return the number of errors
@@ -47666,18 +56617,25 @@ SQLITE_PRIVATE u32 sqlite3BitvecSize(Bitvec *p){
** 3 N Set N randomly chosen bits
** 4 N Clear N randomly chosen bits
** 5 N S X Set N bits from S increment X in array only, not in bitvec
+** 6 Invoice sqlite3ShowBitvec() on the Bitvec object so far
+** 7 X Show compile-time parameters and the hash of X
**
** The opcodes 1 through 4 perform set and clear operations are performed
** on both a Bitvec object and on a linear array of bits obtained from malloc.
** Opcode 5 works on the linear array only, not on the Bitvec.
** Opcode 5 is used to deliberately induce a fault in order to
-** confirm that error detection works.
+** confirm that error detection works. Opcodes 6 and greater are
+** state output opcodes. Opcodes 6 and greater are no-ops unless
+** SQLite has been compiled with SQLITE_DEBUG.
**
** At the conclusion of the test the linear array is compared
** against the Bitvec object. If there are any differences,
** an error is returned. If they are the same, zero is returned.
**
** If a memory allocation error occurs, return -1.
+**
+** sz is the size of the Bitvec. Or if sz is negative, make the size
+** 2*(unsigned)(-sz) and disabled the linear vector check.
*/
SQLITE_PRIVATE int sqlite3BitvecBuiltinTest(int sz, int *aOp){
Bitvec *pBitvec = 0;
@@ -47688,18 +56646,41 @@ SQLITE_PRIVATE int sqlite3BitvecBuiltinTest(int sz, int *aOp){
/* Allocate the Bitvec to be tested and a linear array of
** bits to act as the reference */
- pBitvec = sqlite3BitvecCreate( sz );
- pV = sqlite3MallocZero( (sz+7)/8 + 1 );
+ if( sz<=0 ){
+ pBitvec = sqlite3BitvecCreate( 2*(unsigned)(-sz) );
+ pV = 0;
+ }else{
+ pBitvec = sqlite3BitvecCreate( sz );
+ pV = sqlite3MallocZero( (7+(i64)sz)/8 + 1 );
+ }
pTmpSpace = sqlite3_malloc64(BITVEC_SZ);
- if( pBitvec==0 || pV==0 || pTmpSpace==0 ) goto bitvec_end;
+ if( pBitvec==0 || pTmpSpace==0 || (pV==0 && sz>0) ) goto bitvec_end;
/* NULL pBitvec tests */
sqlite3BitvecSet(0, 1);
sqlite3BitvecClear(0, 1, pTmpSpace);
/* Run the program */
- pc = 0;
+ pc = i = 0;
while( (op = aOp[pc])!=0 ){
+ if( op>=6 ){
+#ifdef SQLITE_DEBUG
+ if( op==6 ){
+ sqlite3ShowBitvec(pBitvec);
+ }else if( op==7 ){
+ printf("BITVEC_SZ = %d (%d by sizeof)\n",
+ BITVEC_SZ, (int)sizeof(Bitvec));
+ printf("BITVEC_USIZE = %d\n", (int)BITVEC_USIZE);
+ printf("BITVEC_NELEM = %d\n", (int)BITVEC_NELEM);
+ printf("BITVEC_NBIT = %d\n", (int)BITVEC_NBIT);
+ printf("BITVEC_NINT = %d\n", (int)BITVEC_NINT);
+ printf("BITVEC_MXHASH = %d\n", (int)BITVEC_MXHASH);
+ printf("BITVEC_NPTR = %d\n", (int)BITVEC_NPTR);
+ }
+#endif
+ pc++;
+ continue;
+ }
switch( op ){
case 1:
case 2:
@@ -47710,7 +56691,7 @@ SQLITE_PRIVATE int sqlite3BitvecBuiltinTest(int sz, int *aOp){
break;
}
case 3:
- case 4:
+ case 4:
default: {
nx = 2;
sqlite3_randomness(sizeof(i), &i);
@@ -47721,12 +56702,12 @@ SQLITE_PRIVATE int sqlite3BitvecBuiltinTest(int sz, int *aOp){
pc += nx;
i = (i & 0x7fffffff)%sz;
if( (op & 1)!=0 ){
- SETBIT(pV, (i+1));
+ if( pV ) SETBIT(pV, (i+1));
if( op!=5 ){
if( sqlite3BitvecSet(pBitvec, i+1) ) goto bitvec_end;
}
}else{
- CLEARBIT(pV, (i+1));
+ if( pV ) CLEARBIT(pV, (i+1));
sqlite3BitvecClear(pBitvec, i+1, pTmpSpace);
}
}
@@ -47736,14 +56717,18 @@ SQLITE_PRIVATE int sqlite3BitvecBuiltinTest(int sz, int *aOp){
** match (rc==0). Change rc to non-zero if a discrepancy
** is found.
*/
- rc = sqlite3BitvecTest(0,0) + sqlite3BitvecTest(pBitvec, sz+1)
- + sqlite3BitvecTest(pBitvec, 0)
- + (sqlite3BitvecSize(pBitvec) - sz);
- for(i=1; i<=sz; i++){
- if( (TESTBIT(pV,i))!=sqlite3BitvecTest(pBitvec,i) ){
- rc = i;
- break;
+ if( pV ){
+ rc = sqlite3BitvecTest(0,0) + sqlite3BitvecTest(pBitvec, sz+1)
+ + sqlite3BitvecTest(pBitvec, 0)
+ + (sqlite3BitvecSize(pBitvec) - sz);
+ for(i=1; i<=sz; i++){
+ if( (TESTBIT(pV,i))!=sqlite3BitvecTest(pBitvec,i) ){
+ rc = i;
+ break;
+ }
}
+ }else{
+ rc = 0;
}
/* Free allocated structure */
@@ -47790,7 +56775,7 @@ SQLITE_PRIVATE int sqlite3BitvecBuiltinTest(int sz, int *aOp){
**
** The PCache.pSynced variable is used to optimize searching for a dirty
** page to eject from the cache mid-transaction. It is better to eject
-** a page that does not require a journal sync than one that does.
+** a page that does not require a journal sync than one that does.
** Therefore, pSynced is maintained so that it *almost* always points
** to either the oldest page in the pDirty/pDirtyTail list that has a
** clear PGHDR_NEED_SYNC flag or to a page that is older than this one
@@ -47800,7 +56785,7 @@ SQLITE_PRIVATE int sqlite3BitvecBuiltinTest(int sz, int *aOp){
struct PCache {
PgHdr *pDirty, *pDirtyTail; /* List of dirty pages in LRU order */
PgHdr *pSynced; /* Last synced page in dirty page list */
- int nRefSum; /* Sum of ref counts over all pages */
+ i64 nRefSum; /* Sum of ref counts over all pages */
int szCache; /* Configured cache size */
int szSpill; /* Size before spilling occurs */
int szPage; /* Size of every page in this cache */
@@ -47825,35 +56810,67 @@ struct PCache {
int sqlite3PcacheTrace = 2; /* 0: off 1: simple 2: cache dumps */
int sqlite3PcacheMxDump = 9999; /* Max cache entries for pcacheDump() */
# define pcacheTrace(X) if(sqlite3PcacheTrace){sqlite3DebugPrintf X;}
- void pcacheDump(PCache *pCache){
- int N;
- int i, j;
- sqlite3_pcache_page *pLower;
+ static void pcachePageTrace(int i, sqlite3_pcache_page *pLower){
PgHdr *pPg;
unsigned char *a;
-
+ int j;
+ if( pLower==0 ){
+ printf("%3d: NULL\n", i);
+ }else{
+ pPg = (PgHdr*)pLower->pExtra;
+ printf("%3d: nRef %2lld flgs %02x data ", i, pPg->nRef, pPg->flags);
+ a = (unsigned char *)pLower->pBuf;
+ for(j=0; j<12; j++) printf("%02x", a[j]);
+ printf(" ptr %p\n", pPg);
+ }
+ }
+ static void pcacheDump(PCache *pCache){
+ int N;
+ int i;
+ sqlite3_pcache_page *pLower;
+
if( sqlite3PcacheTrace<2 ) return;
if( pCache->pCache==0 ) return;
N = sqlite3PcachePagecount(pCache);
if( N>sqlite3PcacheMxDump ) N = sqlite3PcacheMxDump;
for(i=1; i<=N; i++){
pLower = sqlite3GlobalConfig.pcache2.xFetch(pCache->pCache, i, 0);
- if( pLower==0 ) continue;
- pPg = (PgHdr*)pLower->pExtra;
- printf("%3d: nRef %2d flgs %02x data ", i, pPg->nRef, pPg->flags);
- a = (unsigned char *)pLower->pBuf;
- for(j=0; j<12; j++) printf("%02x", a[j]);
- printf("\n");
- if( pPg->pPage==0 ){
+ pcachePageTrace(i, pLower);
+ if( pLower && ((PgHdr*)pLower)->pPage==0 ){
sqlite3GlobalConfig.pcache2.xUnpin(pCache->pCache, pLower, 0);
}
}
}
- #else
+#else
# define pcacheTrace(X)
+# define pcachePageTrace(PGNO, X)
# define pcacheDump(X)
#endif
+/*
+** Return 1 if pPg is on the dirty list for pCache. Return 0 if not.
+** This routine runs inside of assert() statements only.
+*/
+#if defined(SQLITE_ENABLE_EXPENSIVE_ASSERT)
+static int pageOnDirtyList(PCache *pCache, PgHdr *pPg){
+ PgHdr *p;
+ for(p=pCache->pDirty; p; p=p->pDirtyNext){
+ if( p==pPg ) return 1;
+ }
+ return 0;
+}
+static int pageNotOnDirtyList(PCache *pCache, PgHdr *pPg){
+ PgHdr *p;
+ for(p=pCache->pDirty; p; p=p->pDirtyNext){
+ if( p==pPg ) return 0;
+ }
+ return 1;
+}
+#else
+# define pageOnDirtyList(A,B) 1
+# define pageNotOnDirtyList(A,B) 1
+#endif
+
/*
** Check invariants on a PgHdr entry. Return true if everything is OK.
** Return false if any invariant is violated.
@@ -47872,8 +56889,13 @@ SQLITE_PRIVATE int sqlite3PcachePageSanity(PgHdr *pPg){
assert( pCache!=0 ); /* Every page has an associated PCache */
if( pPg->flags & PGHDR_CLEAN ){
assert( (pPg->flags & PGHDR_DIRTY)==0 );/* Cannot be both CLEAN and DIRTY */
- assert( pCache->pDirty!=pPg ); /* CLEAN pages not on dirty list */
- assert( pCache->pDirtyTail!=pPg );
+ assert( pageNotOnDirtyList(pCache, pPg) );/* CLEAN pages not on dirtylist */
+ }else{
+ assert( (pPg->flags & PGHDR_DIRTY)!=0 );/* If not CLEAN must be DIRTY */
+ assert( pPg->pDirtyNext==0 || pPg->pDirtyNext->pDirtyPrev==pPg );
+ assert( pPg->pDirtyPrev==0 || pPg->pDirtyPrev->pDirtyNext==pPg );
+ assert( pPg->pDirtyPrev!=0 || pCache->pDirty==pPg );
+ assert( pageOnDirtyList(pCache, pPg) );
}
/* WRITEABLE pages must also be DIRTY */
if( pPg->flags & PGHDR_WRITEABLE ){
@@ -47923,12 +56945,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{
@@ -47938,7 +56960,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. */
@@ -47967,11 +56989,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;
@@ -48002,16 +57024,20 @@ 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. */
- return (int)((-1024*(i64)p->szCache)/(p->szPage+p->szExtra));
+ i64 n;
+ /* IMPLEMENTATION-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. */
+ n = ((-1024*(i64)p->szCache)/(p->szPage+p->szExtra));
+ if( n>1000000000 ) n = 1000000000;
+ return (int)n;
}
}
/*************************************************** 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){
@@ -48020,6 +57046,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);
}
@@ -48037,8 +57064,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
@@ -48142,15 +57169,16 @@ SQLITE_PRIVATE sqlite3_pcache_page *sqlite3PcacheFetch(
assert( createFlag==0 || pCache->eCreate==eCreate );
assert( createFlag==0 || eCreate==1+(!pCache->bPurgeable||!pCache->pDirty) );
pRes = sqlite3GlobalConfig.pcache2.xFetch(pCache->pCache, pgno, eCreate);
- pcacheTrace(("%p.FETCH %d%s (result: %p)\n",pCache,pgno,
+ pcacheTrace(("%p.FETCH %d%s (result: %p) ",pCache,pgno,
createFlag?" create":"",pRes));
+ pcachePageTrace(pgno, pRes);
return pRes;
}
/*
** 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
@@ -48167,17 +57195,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;
@@ -48187,7 +57215,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),
@@ -48228,6 +57256,7 @@ static SQLITE_NOINLINE PgHdr *pcacheFetchFinishWithInit(
pPgHdr->pData = pPage->pBuf;
pPgHdr->pExtra = (void *)&pPgHdr[1];
memset(pPgHdr->pExtra, 0, 8);
+ assert( EIGHT_BYTE_ALIGNMENT( pPgHdr->pExtra ) );
pPgHdr->pCache = pCache;
pPgHdr->pgno = pgno;
pPgHdr->flags = PGHDR_CLEAN;
@@ -48271,6 +57300,7 @@ SQLITE_PRIVATE void SQLITE_NOINLINE sqlite3PcacheRelease(PgHdr *p){
pcacheUnpin(p);
}else{
pcacheManageDirtyList(p, PCACHE_DIRTYLIST_FRONT);
+ assert( sqlite3PcachePageSanity(p) );
}
}
}
@@ -48314,6 +57344,7 @@ SQLITE_PRIVATE void sqlite3PcacheMakeDirty(PgHdr *p){
pcacheTrace(("%p.DIRTY %d\n",p->pCache,p->pgno));
assert( (p->flags & (PGHDR_DIRTY|PGHDR_CLEAN))==PGHDR_DIRTY );
pcacheManageDirtyList(p, PCACHE_DIRTYLIST_ADD);
+ assert( sqlite3PcachePageSanity(p) );
}
assert( sqlite3PcachePageSanity(p) );
}
@@ -48372,18 +57403,28 @@ 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;
+ sqlite3_pcache_page *pOther;
assert( p->nRef>0 );
assert( newPgno>0 );
assert( sqlite3PcachePageSanity(p) );
pcacheTrace(("%p.MOVE %d -> %d\n",pCache,p->pgno,newPgno));
+ pOther = sqlite3GlobalConfig.pcache2.xFetch(pCache->pCache, newPgno, 0);
+ if( pOther ){
+ PgHdr *pXPage = (PgHdr*)pOther->pExtra;
+ assert( pXPage->nRef==0 );
+ pXPage->nRef++;
+ pCache->nRefSum++;
+ sqlite3PcacheDrop(pXPage);
+ }
sqlite3GlobalConfig.pcache2.xRekey(pCache->pCache, p->pPage, p->pgno,newPgno);
p->pgno = newPgno;
if( (p->flags&PGHDR_DIRTY) && (p->flags&PGHDR_NEED_SYNC) ){
pcacheManageDirtyList(p, PCACHE_DIRTYLIST_FRONT);
+ assert( sqlite3PcachePageSanity(p) );
}
}
@@ -48435,7 +57476,7 @@ SQLITE_PRIVATE void sqlite3PcacheClose(PCache *pCache){
sqlite3GlobalConfig.pcache2.xDestroy(pCache->pCache);
}
-/*
+/*
** Discard the contents of the cache.
*/
SQLITE_PRIVATE void sqlite3PcacheClear(PCache *pCache){
@@ -48473,7 +57514,7 @@ static PgHdr *pcacheMergeDirtyList(PgHdr *pA, PgHdr *pB){
}
/*
-** Sort the list of pages in accending order by pgno. Pages are
+** Sort the list of pages in ascending order by pgno. Pages are
** connected by pDirty pointers. The pDirtyPrev pointers are
** corrupted by this sort.
**
@@ -48526,24 +57567,24 @@ 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
** reference count for all pages.
*/
-SQLITE_PRIVATE int sqlite3PcacheRefCount(PCache *pCache){
+SQLITE_PRIVATE i64 sqlite3PcacheRefCount(PCache *pCache){
return pCache->nRefSum;
}
/*
** Return the number of references to the page supplied as an argument.
*/
-SQLITE_PRIVATE int sqlite3PcachePageRefcount(PgHdr *p){
+SQLITE_PRIVATE i64 sqlite3PcachePageRefcount(PgHdr *p){
return p->nRef;
}
-/*
+/*
** Return the total number of pages in the cache.
*/
SQLITE_PRIVATE int sqlite3PcachePagecount(PCache *pCache){
@@ -48585,7 +57626,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;
}
@@ -48616,7 +57657,7 @@ SQLITE_PRIVATE int sqlite3PCachePercentDirty(PCache *pCache){
}
#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){
@@ -48681,12 +57722,13 @@ SQLITE_PRIVATE void sqlite3PcacheIterateDirty(PCache *pCache, void (*xIter)(PgHd
** size can vary according to architecture, compile-time options, and
** SQLite library version number.
**
-** If SQLITE_PCACHE_SEPARATE_HEADER is defined, then the extension is obtained
-** using a separate memory allocation from the database page content. This
-** seeks to overcome the "clownshoe" problem (also called "internal
-** fragmentation" in academic literature) of allocating a few bytes more
-** than a power of two with the memory allocator rounding up to the next
-** power of two, and leaving the rounded-up space unused.
+** Historical note: It used to be that if the SQLITE_PCACHE_SEPARATE_HEADER
+** was defined, then the page content would be held in a separate memory
+** allocation from the PgHdr1. This was intended to avoid clownshoe memory
+** allocations. However, the btree layer needs a small (16-byte) overrun
+** area after the page content buffer. The header serves as that overrun
+** area. Therefore SQLITE_PCACHE_SEPARATE_HEADER was discontinued to avoid
+** any possibility of a memory error.
**
** This module tracks pointers to PgHdr1 objects. Only pcache.c communicates
** with this module. Information is passed back and forth as PgHdr1 pointers.
@@ -48705,14 +57747,14 @@ 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).
**
** If N is positive, then N pages worth of memory are allocated using a single
** sqlite3Malloc() call and that memory is used for the first N pages allocated.
** Or if N is negative, then -1024*N bytes of memory are allocated and used
-** for as many pages as can be accomodated.
+** for as many pages as can be accommodated.
**
** Only one of (2) or (3) can be used. Once the memory available to (2) or
** (3) is exhausted, subsequent allocations fail over to the general-purpose
@@ -48730,31 +57772,41 @@ typedef struct PgFreeslot PgFreeslot;
typedef struct PGroup PGroup;
/*
-** Each cache entry is represented by an instance of the following
-** structure. Unless SQLITE_PCACHE_SEPARATE_HEADER is defined, a buffer of
-** PgHdr1.pCache->szPage bytes is allocated directly before this structure
-** in memory.
+** Each cache entry is represented by an instance of the following
+** structure. A buffer of PgHdr1.pCache->szPage bytes is allocated
+** directly before this structure and is used to cache the page content.
+**
+** When reading a corrupt database file, it is possible that SQLite might
+** read a few bytes (no more than 16 bytes) past the end of the page buffer.
+** It will only read past the end of the page buffer, never write. This
+** object is positioned immediately after the page buffer to serve as an
+** overrun area, so that overreads are harmless.
**
-** Note: Variables isBulkLocal and isAnchor were once type "u8". That works,
-** but causes a 2-byte gap in the structure for most architectures (since
+** 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
+** 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.
+** can cause a valgrind error if the uninitialized gap is accessed. Using u16
+** ensures there is no such gap, and therefore no bytes of uninitialized
+** memory in the structure.
+**
+** The pLruNext and pLruPrev pointers form a double-linked circular list
+** of all pages that are unpinned. The PGroup.lru element (which should be
+** the only element on the list with PgHdr1.isAnchor set to 1) forms the
+** beginning and the end of the list.
*/
struct PgHdr1 {
- sqlite3_pcache_page page; /* Base class. Must be first. pBuf & pExtra */
- unsigned int iKey; /* Key value (page number) */
- 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 */
+ sqlite3_pcache_page page; /* Base class. Must be first. pBuf & pExtra */
+ unsigned int iKey; /* Key value (page number) */
+ 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 circular LRU list of unpinned pages */
+ PgHdr1 *pLruPrev; /* Previous in LRU list of unpinned pages */
+ /* NB: pLruPrev is only valid if pLruNext!=0 */
};
/*
@@ -48764,7 +57816,7 @@ struct PgHdr1 {
#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.
@@ -48800,13 +57852,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.
*/
@@ -48854,7 +57906,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 */
@@ -48863,10 +57915,6 @@ static SQLITE_WSD struct PCacheGlobal {
sqlite3_mutex *mutex; /* Mutex for accessing the following: */
PgFreeslot *pFree; /* Free page blocks */
int nFreeSlot; /* Number of unused pcache slots */
- /* The following value requires a mutex to change. We skip the mutex on
- ** reading because (1) most platforms read a 32-bit integer atomically and
- ** (2) even if an incorrect value is read, no great harm is done since this
- ** is really just an optimization. */
int bUnderPressure; /* True if low on PAGECACHE memory */
} pcache1_g;
@@ -48895,7 +57943,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.
@@ -48914,7 +57962,7 @@ SQLITE_PRIVATE void sqlite3PCacheBufferSetup(void *pBuf, int sz, int n){
pcache1.nReserve = n>90 ? 10 : (n/10 + 1);
pcache1.pStart = pBuf;
pcache1.pFree = 0;
- pcache1.bUnderPressure = 0;
+ AtomicStore(&pcache1.bUnderPressure,0);
while( n-- ){
p = (PgFreeslot*)pBuf;
p->pNext = pcache1.pFree;
@@ -48944,29 +57992,32 @@ static int pcache1InitBulk(PCache1 *pCache){
if( szBulk > pCache->szAlloc*(i64)pCache->nMax ){
szBulk = pCache->szAlloc*(i64)pCache->nMax;
}
- zBulk = pCache->pBulk = sqlite3Malloc( szBulk );
- sqlite3EndBenignMalloc();
- if( zBulk ){
- int nBulk = sqlite3MallocSize(zBulk)/pCache->szAlloc;
- do{
- PgHdr1 *pX = (PgHdr1*)&zBulk[pCache->szPage];
- pX->page.pBuf = zBulk;
- pX->page.pExtra = &pX[1];
- 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 );
+ if( szBulk>=pCache->szAlloc ){
+ zBulk = pCache->pBulk = sqlite3Malloc( szBulk );
+ sqlite3EndBenignMalloc();
+ if( zBulk ){
+ int nBulk = sqlite3MallocSize(zBulk)/pCache->szAlloc;
+ do{
+ PgHdr1 *pX = (PgHdr1*)&zBulk[pCache->szPage];
+ pX->page.pBuf = zBulk;
+ pX->page.pExtra = (u8*)pX + ROUND8(sizeof(*pX));
+ assert( EIGHT_BYTE_ALIGNMENT( pX->page.pExtra ) );
+ 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 );
+ }
}
return pCache->pFree!=0;
}
/*
** 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
@@ -48981,7 +58032,7 @@ static void *pcache1Alloc(int nByte){
if( p ){
pcache1.pFree = pcache1.pFree->pNext;
pcache1.nFreeSlot--;
- pcache1.bUnderPressure = pcache1.nFreeSlot=0 );
sqlite3StatusHighwater(SQLITE_STATUS_PAGECACHE_SIZE, nByte);
sqlite3StatusUp(SQLITE_STATUS_PAGECACHE_USED, 1);
@@ -49020,7 +58071,7 @@ static void pcache1Free(void *p){
pSlot->pNext = pcache1.pFree;
pcache1.pFree = pSlot;
pcache1.nFreeSlot++;
- pcache1.bUnderPressure = pcache1.nFreeSlotpGroup->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 );
pcache1LeaveMutex(pCache->pGroup);
#endif
if( benignMalloc ){ sqlite3BeginBenignMalloc(); }
-#ifdef SQLITE_PCACHE_SEPARATE_HEADER
- pPg = pcache1Alloc(pCache->szPage);
- p = sqlite3Malloc(sizeof(PgHdr1) + pCache->szExtra);
- if( !pPg || !p ){
- pcache1Free(pPg);
- sqlite3_free(p);
- pPg = 0;
- }
-#else
pPg = pcache1Alloc(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;
+ p = (PgHdr1 *)&((u8 *)pPg)[pCache->szPage];
p->page.pBuf = pPg;
- p->page.pExtra = &p[1];
+ p->page.pExtra = (u8*)p + ROUND8(sizeof(*p));
+ assert( EIGHT_BYTE_ALIGNMENT( p->page.pExtra ) );
p->isBulkLocal = 0;
p->isAnchor = 0;
+ p->pLruPrev = 0; /* Initializing this saves a valgrind error */
}
(*pCache->pnPurgeable)++;
return p;
@@ -49118,9 +58162,6 @@ static void pcache1FreePage(PgHdr1 *p){
pCache->pFree = p;
}else{
pcache1Free(p->page.pBuf);
-#ifdef SQLITE_PCACHE_SEPARATE_HEADER
- sqlite3_free(p);
-#endif
}
(*pCache->pnPurgeable)--;
}
@@ -49161,7 +58202,7 @@ SQLITE_PRIVATE void sqlite3PageFree(void *p){
*/
static int pcache1UnderMemoryPressure(PCache1 *pCache){
if( pcache1.nSlot && (pCache->szPage+pCache->szExtra)<=pcache1.szSlot ){
- return pcache1.bUnderPressure;
+ return AtomicLoad(&pcache1.bUnderPressure);
}else{
return sqlite3HeapNearlyFull();
}
@@ -49178,12 +58219,12 @@ static int pcache1UnderMemoryPressure(PCache1 *pCache){
*/
static void pcache1ResizeHash(PCache1 *p){
PgHdr1 **apNew;
- unsigned int nNew;
- unsigned int i;
+ u64 nNew;
+ u32 i;
assert( sqlite3_mutex_held(p->pGroup->mutex) );
- nNew = p->nHash*2;
+ nNew = 2*(u64)p->nHash;
if( nNew<256 ){
nNew = 256;
}
@@ -49211,7 +58252,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.
**
@@ -49236,7 +58277,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.
**
@@ -49279,8 +58320,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.
@@ -49312,7 +58353,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--;
@@ -49351,7 +58392,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)
@@ -49386,7 +58427,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){
@@ -49406,7 +58447,7 @@ static void pcache1Destroy(sqlite3_pcache *p);
static sqlite3_pcache *pcache1Create(int szPage, int szExtra, int bPurgeable){
PCache1 *pCache; /* The newly created page cache */
PGroup *pGroup; /* The group the new page cache will belong to */
- int sz; /* Bytes of memory required to allocate the new cache */
+ i64 sz; /* Bytes of memory required to allocate the new cache */
assert( (szPage & (szPage-1))==0 && szPage>=512 && szPage<=65536 );
assert( szExtra < 300 );
@@ -49420,6 +58461,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;
@@ -49429,7 +58471,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;
@@ -49449,18 +58490,24 @@ 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.
*/
static void pcache1Cachesize(sqlite3_pcache *p, int nMax){
PCache1 *pCache = (PCache1 *)p;
+ u32 n;
+ assert( nMax>=0 );
if( pCache->bPurgeable ){
PGroup *pGroup = pCache->pGroup;
pcache1EnterMutex(pGroup);
- pGroup->nMaxPage += (nMax - pCache->nMax);
+ n = (u32)nMax;
+ if( n > 0x7fff0000 - pGroup->nMaxPage + pCache->nMax ){
+ n = 0x7fff0000 - pGroup->nMaxPage + pCache->nMax;
+ }
+ pGroup->nMaxPage += (n - pCache->nMax);
pGroup->mxPinned = pGroup->nMaxPage + 10 - pGroup->nMinPage;
- pCache->nMax = nMax;
+ pCache->nMax = n;
pCache->n90pct = pCache->nMax*9/10;
pcache1EnforceMaxPage(pCache);
pcache1LeaveMutex(pGroup);
@@ -49468,7 +58515,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.
*/
@@ -49476,7 +58523,7 @@ static void pcache1Shrink(sqlite3_pcache *p){
PCache1 *pCache = (PCache1*)p;
if( pCache->bPurgeable ){
PGroup *pGroup = pCache->pGroup;
- int savedMaxPage;
+ unsigned int savedMaxPage;
pcache1EnterMutex(pGroup);
savedMaxPage = pGroup->nMaxPage;
pGroup->nMaxPage = 0;
@@ -49487,7 +58534,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;
@@ -49508,8 +58555,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;
@@ -49551,8 +58598,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);
@@ -49577,13 +58624,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
@@ -49594,7 +58641,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
@@ -49608,13 +58655,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
@@ -49626,7 +58673,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.
**
@@ -49636,8 +58683,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;
@@ -49666,8 +58713,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;
@@ -49681,8 +58728,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)
@@ -49712,18 +58759,18 @@ 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->pLruNext==0 );
@@ -49744,7 +58791,7 @@ static void pcache1Unpin(
}
/*
-** Implementation of the sqlite3_pcache.xRekey method.
+** Implementation of the sqlite3_pcache.xRekey method.
*/
static void pcache1Rekey(
sqlite3_pcache *p,
@@ -49755,23 +58802,26 @@ static void pcache1Rekey(
PCache1 *pCache = (PCache1 *)p;
PgHdr1 *pPage = (PgHdr1 *)pPg;
PgHdr1 **pp;
- unsigned int h;
+ unsigned int hOld, hNew;
assert( pPage->iKey==iOld );
assert( pPage->pCache==pCache );
+ assert( iOld!=iNew ); /* The page number really is changing */
pcache1EnterMutex(pCache->pGroup);
- h = iOld%pCache->nHash;
- pp = &pCache->apHash[h];
+ assert( pcache1FetchNoMutex(p, iOld, 0)==pPage ); /* pPg really is iOld */
+ hOld = iOld%pCache->nHash;
+ pp = &pCache->apHash[hOld];
while( (*pp)!=pPage ){
pp = &(*pp)->pNext;
}
*pp = pPage->pNext;
- h = iNew%pCache->nHash;
+ assert( pcache1FetchNoMutex(p, iNew, 0)==0 ); /* iNew not in cache */
+ hNew = iNew%pCache->nHash;
pPage->iKey = iNew;
- pPage->pNext = pCache->apHash[h];
- pCache->apHash[h] = pPage;
+ pPage->pNext = pCache->apHash[hNew];
+ pCache->apHash[hNew] = pPage;
if( iNew>pCache->iMaxKey ){
pCache->iMaxKey = iNew;
}
@@ -49780,7 +58830,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
@@ -49797,7 +58847,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().
*/
@@ -49863,7 +58913,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){
@@ -49878,9 +58928,6 @@ SQLITE_PRIVATE int sqlite3PcacheReleaseMemory(int nReq){
&& p->isAnchor==0
){
nFree += pcache1MemSize(p->page.pBuf);
-#ifdef SQLITE_PCACHE_SEPARATE_HEADER
- nFree += sqlite3MemSize(p);
-#endif
assert( PAGE_IS_UNPINNED(p) );
pcache1PinPage(p);
pcache1RemoveFromHash(p, 1);
@@ -49954,14 +59001,14 @@ 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.
**
** The TEST primitive includes a "batch" number. The TEST primitive
** will only see elements that were inserted before the last change
** in the batch number. In other words, if an INSERT occurs between
-** two TESTs where the TESTs have the same batch nubmer, then the
+** two TESTs where the TESTs have the same batch number, then the
** value added by the INSERT will not be visible to the second TEST.
** The initial batch number is zero, so if the very first TEST contains
** a non-zero batch number, it will see all prior INSERTs.
@@ -50002,7 +59049,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) */
@@ -50096,7 +59143,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.
@@ -50154,7 +59201,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(
@@ -50191,7 +59238,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];
@@ -50264,7 +59311,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
@@ -50372,7 +59419,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){
@@ -50434,7 +59481,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
@@ -50457,8 +59504,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.
*/
@@ -50493,12 +59540,13 @@ SQLITE_PRIVATE int sqlite3RowSetTest(RowSet *pRowSet, int iBatch, sqlite3_int64
# define sqlite3WalFramesize(z) 0
# define sqlite3WalFindFrame(x,y,z) 0
# define sqlite3WalFile(x) 0
+# undef SQLITE_USE_SEH
#else
#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;
@@ -50509,7 +59557,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
@@ -50544,7 +59592,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 */
@@ -50572,7 +59620,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);
@@ -50594,6 +59642,15 @@ 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
+
+#ifdef SQLITE_USE_SEH
+SQLITE_PRIVATE int sqlite3WalSystemErrno(Wal*);
+#endif
+
#endif /* ifndef SQLITE_OMIT_WAL */
#endif /* SQLITE_WAL_H */
@@ -50614,60 +59671,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
@@ -50700,7 +59757,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
@@ -50721,7 +59778,7 @@ int sqlite3PagerTrace=1; /* True to enable tracing */
** | | |
** | V |
** |<-------WRITER_LOCKED------> ERROR
-** | | ^
+** | | ^
** | V |
** |<------WRITER_CACHEMOD-------->|
** | | |
@@ -50733,7 +59790,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]
**
@@ -50745,7 +59802,7 @@ int sqlite3PagerTrace=1; /* True to enable tracing */
**
** WRITER_*** -> ERROR [pager_error]
** ERROR -> OPEN [pager_unlock]
-**
+**
**
** OPEN:
**
@@ -50759,9 +59816,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
@@ -50771,28 +59828,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.
@@ -50800,7 +59857,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
@@ -50819,7 +59876,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.
**
@@ -50832,7 +59889,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).
@@ -50844,8 +59901,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.
@@ -50853,19 +59910,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
@@ -50875,13 +59932,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)
+** is reloaded from disk (and, if necessary, hot-journal rollback performed)
** 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:
@@ -50897,21 +59954,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:
**
@@ -50921,7 +59978,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().
@@ -50935,7 +59992,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
@@ -50950,20 +60007,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
@@ -50974,32 +60031,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.
@@ -51015,7 +60058,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()).
@@ -51027,6 +60070,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
@@ -51065,44 +60109,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
@@ -51118,12 +60162,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
**
@@ -51131,16 +60175,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
@@ -51151,10 +60195,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
@@ -51163,12 +60207,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
@@ -51179,20 +60223,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
@@ -51221,6 +60265,7 @@ struct Pager {
u8 noLock; /* Do not lock (except in WAL mode) */
u8 readOnly; /* True for a read-only database */
u8 memDb; /* True to inhibit all file I/O */
+ u8 memVfs; /* VFS-implemented memory database */
/**************************************************************************
** The following block contains those class members that change during
@@ -51234,7 +60279,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() */
@@ -51270,36 +60315,34 @@ struct Pager {
i16 nReserve; /* Number of unused bytes at end of each page */
u32 vfsFlags; /* Flags for sqlite3_vfs.xOpen() */
u32 sectorSize; /* Assumed sector size during rollback */
- int pageSize; /* Number of bytes in a page */
Pgno mxPgno; /* Maximum allowed size of the database */
+ Pgno lckPgno; /* Page number for the locking page */
+ i64 pageSize; /* Number of bytes in a page */
i64 journalSizeLimit; /* Size limit for persistent journal files */
char *zFilename; /* Name of the database file */
char *zJournal; /* Name of the journal file */
int (*xBusyHandler)(void*); /* Function to call when busy */
void *pBusyHandlerArg; /* Context argument for xBusyHandler */
- int aStat[4]; /* Total cache hits, misses, writes, spills */
+ u32 aStat[4]; /* Total cache hits, misses, writes, spills */
#ifdef SQLITE_TEST
int nRead; /* Database pages read */
#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
Wal *pWal; /* Write-ahead log used by "journal_mode=wal" */
char *zWal; /* File name for write-ahead log */
#endif
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+ sqlite3 *dbWal;
+#endif
};
/*
** 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
@@ -51357,7 +60400,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)
@@ -51384,48 +60427,35 @@ 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.
-**
-** This is so that expressions can be written as:
-**
-** if( isOpen(pPager->jfd) ){ ...
-**
-** instead of
-**
-** if( pPager->jfd->pMethods ){ ...
-*/
-#define isOpen(pFd) ((pFd)->pMethods!=0)
-
#ifdef SQLITE_DIRECT_OVERFLOW_READ
/*
** 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.
+** (1) the database file is open
+** (2) the VFS for the database is able to do unaligned sub-page reads
+** (3) there are no dirty pages in the cache, and
+** (4) the desired page is not currently in the wal file.
*/
SQLITE_PRIVATE int sqlite3PagerDirectReadOk(Pager *pPager, Pgno pgno){
- if( pPager->fd->pMethods==0 ) return 0;
- if( sqlite3PCacheIsDirty(pPager->pPCache) ) return 0;
-#ifdef SQLITE_HAS_CODEC
- if( pPager->xCodec!=0 ) return 0;
-#endif
+ assert( pPager!=0 );
+ assert( pPager->fd!=0 );
+ if( pPager->fd->pMethods==0 ) return 0; /* Case (1) */
+ if( sqlite3PCacheIsDirty(pPager->pPCache) ) return 0; /* Failed (3) */
#ifndef SQLITE_OMIT_WAL
if( pPager->pWal ){
u32 iRead = 0;
- int rc;
- rc = sqlite3WalFindFrame(pPager->pWal, pgno, &iRead);
- return (rc==SQLITE_OK && iRead==0);
+ (void)sqlite3WalFindFrame(pPager->pWal, pgno, &iRead);
+ if( iRead ) return 0; /* Case (4) */
}
+#else
+ UNUSED_PARAMETER(pgno);
#endif
+ assert( pPager->fd->pMethods->xDeviceCharacteristics!=0 );
+ if( (pPager->fd->pMethods->xDeviceCharacteristics(pPager->fd)
+ & SQLITE_IOCAP_SUBPAGE_READ)==0 ){
+ return 0; /* Case (2) */
+ }
return 1;
}
#endif
@@ -51440,7 +60470,7 @@ SQLITE_PRIVATE int sqlite3PagerDirectReadOk(Pager *pPager, Pgno pgno){
# define pagerBeginReadTransaction(z) SQLITE_OK
#endif
-#ifndef NDEBUG
+#ifndef NDEBUG
/*
** Usage:
**
@@ -51469,25 +60499,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 );
@@ -51521,7 +60551,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:
@@ -51534,9 +60564,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 );
@@ -51548,9 +60578,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 );
@@ -51560,9 +60590,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;
@@ -51581,7 +60611,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
@@ -51651,11 +60681,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{
@@ -51680,6 +60706,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;
}
}
@@ -51733,7 +60762,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){
@@ -51750,17 +60779,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){
@@ -51787,7 +60817,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()
@@ -51840,17 +60870,17 @@ static int jrnlBufferSize(Pager *pPager){
*/
#ifdef SQLITE_CHECK_PAGES
/*
-** Return a 32-bit hash of the page data for pPage.
+** Return a 64-bit hash of the page data for pPage.
*/
-static u32 pager_datahash(int nByte, unsigned char *pData){
- u32 hash = 0;
+static u64 pager_datahash(int nByte, unsigned char *pData){
+ u64 hash = 0;
int i;
for(i=0; ipPager->pageSize, (unsigned char *)pPage->pData);
}
static void pager_set_pagehash(PgHdr *pPage){
@@ -51877,73 +60907,85 @@ static void checkPage(PgHdr *pPg){
#endif /* SQLITE_CHECK_PAGES */
/*
-** 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.
-**
-** zMaster must point to a buffer of at least nMaster bytes allocated by
-** the caller. This should be sqlite3_vfs.mxPathname+1 (to ensure there is
-** enough space to write the master journal name). If the master journal
-** name in the journal is longer than nMaster bytes (including a
-** nul-terminator), then this is handled as if no master journal name
-** were present in the journal.
+** Free a buffer allocated by the readSuperJournal() function.
+*/
+static void freeSuperJournal(char *zSuper){
+ if( zSuper ){
+ sqlite3_free(&zSuper[-4]);
+ }
+}
+
+/*
+** Parameter pJrnl is a file-handle open on a journal file. This function
+** attempts to read a super-journal file name from the end of the journal
+** file. If successful, it sets output parameter (*pzSuper) to point to a
+** buffer containing the super-journal name as a nul-terminated string.
+** The caller is responsible for freeing the buffer using freeSuperJournal().
**
-** 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.
+** Refer to comments above writeSuperJournal() for the format used to store
+** a super-journal file name at the end of a journal file.
**
-** If it is determined that no master journal file name is present
-** zMaster[0] is set to 0 and SQLITE_OK returned.
+** Parameter nSuper is passed the maximum allowable size of the super journal
+** name in bytes. 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 an error occurs while reading from the journal file, an SQLite
-** error code is returned.
+** If there is no super-journal name at the end of pJrnl, (*pzSuper) is
+** set to 0 and SQLITE_OK is returned. Or, if an error occurs while reading
+** the super-journal name, an SQLite error code is returned and (*pzSuper)
+** is set to 0.
*/
-static int readMasterJournal(sqlite3_file *pJrnl, char *zMaster, u32 nMaster){
+static int readSuperJournal(sqlite3_file *pJrnl, u64 nSuper, char **pzSuper){
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';
+ char *zOut = 0;
+ *pzSuper = 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))
){
return rc;
}
- /* See if the checksum matches the master 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:
@@ -51954,7 +60996,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;
@@ -51976,12 +61018,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.
@@ -52007,8 +61049,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.
@@ -52036,7 +61078,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){
@@ -52052,8 +61094,8 @@ static int writeJournalHdr(Pager *pPager){
nHeader = JOURNAL_HDR_SZ(pPager);
}
- /* If there are active savepoints and any of them were created
- ** since the most recent journal header was written, update the
+ /* If there are active savepoints and any of them were created
+ ** since the most recent journal header was written, update the
** PagerSavepoint.iHdrOffset fields now.
*/
for(ii=0; ii
| | |