@@ -1,7 +1,7 @@
/******************************************************************************
** This file is an amalgamation of many separate C source files from SQLite
-** version 3.5.5. By combining all the individual C code files into this
+** version 3.5.9. By combining all the individual C code files into this
** single large file, the entire code can be compiled as a one translation
** unit. This allows many compilers to do optimizations that would not be
** possible if the files were compiled separately. Performance improvements
** of 5% are more are commonly seen when SQLite is compiled as a single
@@ -10,15 +10,15 @@
** This file is all you need to compile SQLite. To use SQLite in other
** programs, you need this file and the "sqlite3.h" header file that defines
** the programming interface to the SQLite library. (If you do not have
** the "sqlite3.h" header file at hand, you will find a copy in the first
-** 4800 lines past this header comment.) Additional code files may be
+** 5638 lines past this header comment.) Additional code files may be
** needed if you want a wrapper to interface SQLite with your choice of
** programming language. The code for the "sqlite3" command-line shell
** is also in a separate file. This file contains only code for the core
** SQLite library.
**
-** This amalgamation was generated on 2008-02-01 15:34:25 UTC.
+** This amalgamation was generated on 2008-05-14 16:30:52 UTC.
*/
#define SQLITE_CORE 1
#define SQLITE_AMALGAMATION 1
#ifndef SQLITE_PRIVATE
@@ -40,55 +40,20 @@
**
*************************************************************************
** Internal interface definitions for SQLite.
**
-** @(#) $Id: sqliteInt.h,v 1.658 2008/01/30 16:14:23 drh Exp $
+** @(#) $Id: sqliteInt.h,v 1.704 2008/05/13 13:27:34 drh Exp $
*/
#ifndef _SQLITEINT_H_
#define _SQLITEINT_H_
/*
-** The macro unlikely() is a hint that surrounds a boolean
-** expression that is usually false. Macro likely() surrounds
-** a boolean expression that is usually true. GCC is able to
-** use these hints to generate better code, sometimes.
-*/
-#if defined(__GNUC__) && 0
-# define likely(X) __builtin_expect((X),1)
-# define unlikely(X) __builtin_expect((X),0)
-#else
-# define likely(X) !!(X)
-# define unlikely(X) !!(X)
-#endif
-
-
-/*
-** These #defines should enable >2GB file support on Posix if the
-** underlying operating system supports it. If the OS lacks
-** large file support, or if the OS is windows, these should be no-ops.
-**
-** Ticket #2739: The _LARGEFILE_SOURCE macro must appear before any
-** system #includes. Hence, this block of code must be the very first
-** code in all source files.
-**
-** Large file support can be disabled using the -DSQLITE_DISABLE_LFS switch
-** on the compiler command line. This is necessary if you are compiling
-** on a recent machine (ex: RedHat 7.2) but you want your code to work
-** on an older machine (ex: RedHat 6.0). If you compile on RedHat 7.2
-** without this option, LFS is enable. But LFS does not exist in the kernel
-** in RedHat 6.0, so the code won't work. Hence, for maximum binary
-** portability you should omit LFS.
-**
-** Similar is true for MacOS. LFS is only supported on MacOS 9 and later.
-*/
-#ifndef SQLITE_DISABLE_LFS
-# define _LARGE_FILE 1
-# ifndef _FILE_OFFSET_BITS
-# define _FILE_OFFSET_BITS 64
-# endif
-# define _LARGEFILE_SOURCE 1
-#endif
-
+** Include the configuration header output by 'configure' if we're using the
+** autoconf-based build
+*/
+#ifdef _HAVE_SQLITE_CONFIG_H
+#include "config.h"
+#endif
/************** Include sqliteLimit.h in the middle of sqliteInt.h ***********/
/************** Begin file sqliteLimit.h *************************************/
/*
@@ -104,9 +69,9 @@
*************************************************************************
**
** This file defines various limits of what SQLite can process.
**
-** @(#) $Id: sqliteLimit.h,v 1.6 2007/12/17 16:20:07 drh Exp $
+** @(#) $Id: sqliteLimit.h,v 1.8 2008/03/26 15:56:22 drh Exp $
*/
/*
** The maximum length of a TEXT or BLOB in bytes. This also
@@ -141,20 +106,26 @@
#endif
/*
** The maximum length of a single SQL statement in bytes.
-** A value of zero means there is no limit.
+**
+** 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.
*/
#ifndef SQLITE_MAX_SQL_LENGTH
-# define SQLITE_MAX_SQL_LENGTH 0
+# 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. A value of 0 (the default) means do not enforce
-** any limitation on expression tree depth.
+** expression.
+**
+** A value of 0 used to mean that the limit was not enforced.
+** But that is no longer true. The limit is now strictly enforced
+** at all times.
*/
#ifndef SQLITE_MAX_EXPR_DEPTH
# define SQLITE_MAX_EXPR_DEPTH 1000
#endif
@@ -197,13 +168,11 @@
# define SQLITE_DEFAULT_TEMP_CACHE_SIZE 500
#endif
/*
-** The maximum number of attached databases. This must be at least 2
-** in order to support the main database file (0) and the file used to
-** hold temporary tables (1). And it must be less than 32 because
-** we use a bitmask of databases with a u32 in places (for example
-** the Parse.cookieMask field).
+** The maximum number of attached databases. This must be between 0
+** and 30. The upper bound on 30 is because a 32-bit integer bitmap
+** is used internally to track attached databases.
*/
#ifndef SQLITE_MAX_ATTACHED
# define SQLITE_MAX_ATTACHED 10
#endif
@@ -273,48 +242,85 @@
/************** End of sqliteLimit.h *****************************************/
/************** Continuing where we left off in sqliteInt.h ******************/
-/*
-** For testing purposes, the various size limit constants are really
-** variables that we can modify in the testfixture.
-*/
-#ifdef SQLITE_TEST
- #undef SQLITE_MAX_LENGTH
- #undef SQLITE_MAX_COLUMN
- #undef SQLITE_MAX_SQL_LENGTH
- #undef SQLITE_MAX_EXPR_DEPTH
- #undef SQLITE_MAX_COMPOUND_SELECT
- #undef SQLITE_MAX_VDBE_OP
- #undef SQLITE_MAX_FUNCTION_ARG
- #undef SQLITE_MAX_VARIABLE_NUMBER
- #undef SQLITE_MAX_PAGE_SIZE
- #undef SQLITE_MAX_PAGE_COUNT
- #undef SQLITE_MAX_LIKE_PATTERN_LENGTH
-
- #define SQLITE_MAX_LENGTH sqlite3MAX_LENGTH
- #define SQLITE_MAX_COLUMN sqlite3MAX_COLUMN
- #define SQLITE_MAX_SQL_LENGTH sqlite3MAX_SQL_LENGTH
- #define SQLITE_MAX_EXPR_DEPTH sqlite3MAX_EXPR_DEPTH
- #define SQLITE_MAX_COMPOUND_SELECT sqlite3MAX_COMPOUND_SELECT
- #define SQLITE_MAX_VDBE_OP sqlite3MAX_VDBE_OP
- #define SQLITE_MAX_FUNCTION_ARG sqlite3MAX_FUNCTION_ARG
- #define SQLITE_MAX_VARIABLE_NUMBER sqlite3MAX_VARIABLE_NUMBER
- #define SQLITE_MAX_PAGE_SIZE sqlite3MAX_PAGE_SIZE
- #define SQLITE_MAX_PAGE_COUNT sqlite3MAX_PAGE_COUNT
- #define SQLITE_MAX_LIKE_PATTERN_LENGTH sqlite3MAX_LIKE_PATTERN_LENGTH
-
- extern int sqlite3MAX_LENGTH;
- extern int sqlite3MAX_COLUMN;
- extern int sqlite3MAX_SQL_LENGTH;
- extern int sqlite3MAX_EXPR_DEPTH;
- extern int sqlite3MAX_COMPOUND_SELECT;
- extern int sqlite3MAX_VDBE_OP;
- extern int sqlite3MAX_FUNCTION_ARG;
- extern int sqlite3MAX_VARIABLE_NUMBER;
- extern int sqlite3MAX_PAGE_SIZE;
- extern int sqlite3MAX_PAGE_COUNT;
- extern int sqlite3MAX_LIKE_PATTERN_LENGTH;
+/* Disable nuisance warnings on Borland compilers */
+#if defined(__BORLANDC__)
+#pragma warn -rch /* unreachable code */
+#pragma warn -ccc /* Condition is always true or false */
+#pragma warn -aus /* Assigned value is never used */
+#pragma warn -csu /* Comparing signed and unsigned */
+#pragma warn -spa /* Suspicous pointer arithmetic */
+#endif
+
+/* Needed for various definitions... */
+#define _GNU_SOURCE
+
+/*
+** Include standard header files as necessary
+*/
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+#ifdef HAVE_INTTYPES_H
+#include <inttypes.h>
+#endif
+
+/*
+** A macro used to aid in coverage testing. When doing coverage
+** testing, the condition inside the argument must be evaluated
+** both true and false in order to get full branch coverage.
+** This macro can be inserted to ensure adequate test coverage
+** in places where simple condition/decision coverage is inadequate.
+*/
+#ifdef SQLITE_COVERAGE_TEST
+SQLITE_PRIVATE void sqlite3Coverage(int);
+# define testcase(X) if( X ){ sqlite3Coverage(__LINE__); }
+#else
+# define testcase(X)
+#endif
+
+
+/*
+** The macro unlikely() is a hint that surrounds a boolean
+** expression that is usually false. Macro likely() surrounds
+** a boolean expression that is usually true. GCC is able to
+** use these hints to generate better code, sometimes.
+*/
+#if defined(__GNUC__) && 0
+# define likely(X) __builtin_expect((X),1)
+# define unlikely(X) __builtin_expect((X),0)
+#else
+# define likely(X) !!(X)
+# define unlikely(X) !!(X)
+#endif
+
+
+/*
+** These #defines should enable >2GB file support on Posix if the
+** underlying operating system supports it. If the OS lacks
+** large file support, or if the OS is windows, these should be no-ops.
+**
+** Ticket #2739: The _LARGEFILE_SOURCE macro must appear before any
+** system #includes. Hence, this block of code must be the very first
+** code in all source files.
+**
+** Large file support can be disabled using the -DSQLITE_DISABLE_LFS switch
+** on the compiler command line. This is necessary if you are compiling
+** on a recent machine (ex: RedHat 7.2) but you want your code to work
+** on an older machine (ex: RedHat 6.0). If you compile on RedHat 7.2
+** without this option, LFS is enable. But LFS does not exist in the kernel
+** in RedHat 6.0, so the code won't work. Hence, for maximum binary
+** portability you should omit LFS.
+**
+** Similar is true for MacOS. LFS is only supported on MacOS 9 and later.
+*/
+#ifndef SQLITE_DISABLE_LFS
+# define _LARGE_FILE 1
+# ifndef _FILE_OFFSET_BITS
+# define _FILE_OFFSET_BITS 64
+# endif
+# define _LARGEFILE_SOURCE 1
#endif
/*
@@ -327,8 +333,42 @@
# define SQLITE_THREADSAFE THREADSAFE
#else
# define SQLITE_THREADSAFE 1
#endif
+#endif
+
+/*
+** Exactly one of the following macros must be defined in order to
+** specify which memory allocation subsystem to use.
+**
+** SQLITE_SYSTEM_MALLOC // Use normal system malloc()
+** SQLITE_MEMDEBUG // Debugging version of system malloc()
+** SQLITE_MEMORY_SIZE // internal allocator #1
+** SQLITE_MMAP_HEAP_SIZE // internal mmap() allocator
+** SQLITE_POW2_MEMORY_SIZE // internal power-of-two allocator
+**
+** If none of the above are defined, then set SQLITE_SYSTEM_MALLOC as
+** the default.
+*/
+#if defined(SQLITE_SYSTEM_MALLOC)+defined(SQLITE_MEMDEBUG)+\
+ defined(SQLITE_MEMORY_SIZE)+defined(SQLITE_MMAP_HEAP_SIZE)+\
+ defined(SQLITE_POW2_MEMORY_SIZE)>1
+# error "At most one of the following compile-time configuration options\
+ is allows: SQLITE_SYSTEM_MALLOC, SQLITE_MEMDEBUG, SQLITE_MEMORY_SIZE,\
+ SQLITE_MMAP_HEAP_SIZE, SQLITE_POW2_MEMORY_SIZE"
+#endif
+#if defined(SQLITE_SYSTEM_MALLOC)+defined(SQLITE_MEMDEBUG)+\
+ defined(SQLITE_MEMORY_SIZE)+defined(SQLITE_MMAP_HEAP_SIZE)+\
+ defined(SQLITE_POW2_MEMORY_SIZE)==0
+# define SQLITE_SYSTEM_MALLOC 1
+#endif
+
+/*
+** If SQLITE_MALLOC_SOFT_LIMIT is defined, then try to keep the
+** sizes of memory allocations below this value where possible.
+*/
+#if defined(SQLITE_POW2_MEMORY_SIZE) && !defined(SQLITE_MALLOC_SOFT_LIMIT)
+# define SQLITE_MALLOC_SOFT_LIMIT 1024
#endif
/*
** We need to define _XOPEN_SOURCE as follows in order to enable
@@ -395,9 +435,9 @@
** The makefile makes some minor changes to this file (such as inserting
** the version number) and changes its name to "sqlite3.h" as
** part of the build process.
**
-** @(#) $Id: sqlite.h.in,v 1.283 2008/01/31 17:21:22 drh Exp $
+** @(#) $Id: sqlite.h.in,v 1.312 2008/05/12 12:39:56 drh Exp $
*/
#ifndef _SQLITE3_H_
#define _SQLITE3_H_
#include <stdarg.h> /* Needed for the definition of va_list */
@@ -434,9 +474,9 @@
** The SQLITE_VERSION and SQLITE_VERSION_NUMBER #defines in
** the sqlite3.h file specify the version of SQLite with which
** that header file is associated.
**
-** The "version" of SQLite is a strong of the form "X.Y.Z".
+** The "version" of SQLite is a string of the form "X.Y.Z".
** The phrase "alpha" or "beta" might be appended after the Z.
** The X value is major version number always 3 in SQLite3.
** The X value only changes when backwards compatibility is
** broken and we intend to never break
@@ -458,10 +498,10 @@
** {F10014} The SQLITE_VERSION_NUMBER #define resolves to an integer
** with the value (X*1000000 + Y*1000 + Z) where X, Y, and
** Z are the major version, minor version, and release number.
*/
-#define SQLITE_VERSION "3.5.5"
-#define SQLITE_VERSION_NUMBER 3005005
+#define SQLITE_VERSION "3.5.9"
+#define SQLITE_VERSION_NUMBER 3005009
/*
** CAPI3REF: Run-Time Library Version Numbers {F10020}
** KEYWORDS: sqlite3_version
@@ -488,9 +528,9 @@
**
** {F10023} The [sqlite3_libversion()] function returns
** a pointer to the [sqlite3_version] string constant.
*/
-SQLITE_EXTERN const char sqlite3_version[];
+SQLITE_API const char sqlite3_version[];
SQLITE_API const char *sqlite3_libversion(void);
SQLITE_API int sqlite3_libversion_number(void);
/*
@@ -497,9 +537,9 @@
** CAPI3REF: Test To See If The Library Is Threadsafe {F10100}
**
** SQLite can be compiled with or without mutexes. When
** the SQLITE_THREADSAFE C preprocessor macro is true, mutexes
-** are enabled and SQLite is threadsafe. When that macro os false,
+** are enabled and SQLite is threadsafe. When that macro is false,
** the mutexes are omitted. Without the mutexes, it is not safe
** to use SQLite from more than one thread.
**
** There is a measurable performance penalty for enabling mutexes.
@@ -520,9 +560,9 @@
SQLITE_API int sqlite3_threadsafe(void);
/*
** CAPI3REF: Database Connection Handle {F12000}
-** KEYWORDS: {database connection}
+** KEYWORDS: {database connection} {database connections}
**
** Each open SQLite database is represented by pointer to an instance of the
** opaque structure named "sqlite3". It is useful to think of an sqlite3
** pointer as an object. The [sqlite3_open()], [sqlite3_open16()], and
@@ -699,9 +739,10 @@
** {F12134} The [sqlite3_exec()] routine does not change the value of
** *errmsg if errmsg is NULL or if there are no errors.
**
** {F12137} The [sqlite3_exec()] function sets the error code and message
-** accessible via [sqlite3_errcode()] and [sqlite3_errmsg()].
+** accessible via [sqlite3_errcode()], [sqlite3_errmsg()], and
+** [sqlite3_errmsg16()].
**
** LIMITATIONS:
**
** {U12141} The first parameter to [sqlite3_exec()] must be an valid and open
@@ -798,9 +839,9 @@
**
** {F10225} Extended result code names contain two or more "_" characters.
**
** {F10226} The numeric value of an extended result code contains the
-** numeric value of its corresponding primary result code it
+** numeric value of its corresponding primary result code in
** its least significant 8 bits.
*/
#define SQLITE_IOERR_READ (SQLITE_IOERR | (1<<8))
#define SQLITE_IOERR_SHORT_READ (SQLITE_IOERR | (2<<8))
@@ -817,9 +858,9 @@
/*
** CAPI3REF: Flags For File Open Operations {F10230}
**
-** These bit values are intended for use in then
+** These bit values are intended for use in the
** 3rd parameter to the [sqlite3_open_v2()] interface and
** in the 4th parameter to the xOpen method of the
** [sqlite3_vfs] object.
*/
@@ -884,14 +925,14 @@
/*
** CAPI3REF: Synchronization Type Flags {F10260}
**
** When SQLite invokes the xSync() method of an
-** [sqlite3_io_methods] object it uses a combination of the
+** [sqlite3_io_methods] object it uses a combination of
** these integer values as the second argument.
**
** When the SQLITE_SYNC_DATAONLY flag is used, it means that the
** sync operation only needs to flush data to mass storage. Inode
-** information need not be flushed. The SQLITE_SYNC_NORMAL means
+** information need not be flushed. The SQLITE_SYNC_NORMAL flag means
** to use normal fsync() semantics. The SQLITE_SYNC_FULL flag means
** to use Mac OS-X style fullsync instead of fsync().
*/
#define SQLITE_SYNC_NORMAL 0x00002
@@ -917,9 +958,9 @@
/*
** CAPI3REF: OS Interface File Virtual Methods Object {F11120}
**
** Every file opened by the [sqlite3_vfs] xOpen method contains a pointer to
-** an instance of the this object. This object defines the
+** an instance of this object. This object defines the
** methods used to perform various operations against the open file.
**
** The flags argument to xSync may be one of [SQLITE_SYNC_NORMAL] or
** [SQLITE_SYNC_FULL]. The first choice is the normal fsync().
@@ -1015,9 +1056,9 @@
** of the [sqlite3_io_methods] object and to the [sqlite3_file_control()]
** interface.
**
** The [SQLITE_FCNTL_LOCKSTATE] opcode is used for debugging. This
-** opcode cases the xFileControl method to write the current state of
+** opcode causes the xFileControl method to write the current state of
** the lock (one of [SQLITE_LOCK_NONE], [SQLITE_LOCK_SHARED],
** [SQLITE_LOCK_RESERVED], [SQLITE_LOCK_PENDING], or [SQLITE_LOCK_EXCLUSIVE])
** into an integer that the pArg argument points to. This capability
** is used during testing and only needs to be supported when SQLITE_TEST
@@ -1051,15 +1092,15 @@
** The szOsFile field is the size of the subclassed [sqlite3_file]
** structure used by this VFS. mxPathname is the maximum length of
** a pathname in this VFS.
**
-** Registered vfs modules are kept on a linked list formed by
+** Registered sqlite3_vfs objects are kept on a linked list formed by
** the pNext pointer. The [sqlite3_vfs_register()]
** and [sqlite3_vfs_unregister()] interfaces manage this list
** in a thread-safe way. The [sqlite3_vfs_find()] interface
** searches the list.
**
-** The pNext field is the only fields in the sqlite3_vfs
+** The pNext field is the only field in the sqlite3_vfs
** structure that SQLite will ever modify. SQLite will only access
** or modify this field while holding a particular static mutex.
** The application should never modify anything within the sqlite3_vfs
** object once the object has been registered.
@@ -1095,14 +1136,14 @@
** </ul> {END}
**
** The file I/O implementation can use the object type flags to
** changes the way it deals with files. For example, an application
-** that does not care about crash recovery or rollback, might make
-** the open of a journal file a no-op. Writes to this journal are
-** also a no-op. Any attempt to read the journal return SQLITE_IOERR.
-** Or the implementation might recognize the a database file will
-** be doing page-aligned sector reads and writes in a random order
-** and set up its I/O subsystem accordingly.
+** that does not care about crash recovery or rollback might make
+** the open of a journal file a no-op. Writes to this journal would
+** also be no-ops, and any attempt to read the journal would return
+** SQLITE_IOERR. Or the implementation might recognize that a database
+** file will be doing page-aligned sector reads and writes in a random
+** order and set up its I/O subsystem accordingly.
**
** SQLite might also add one of the following flags to the xOpen
** method:
**
@@ -1117,9 +1158,9 @@
** {F11147} The [SQLITE_OPEN_EXCLUSIVE] flag means the file should be opened
** for exclusive access. This flag is set for all files except
** for the main database file. {END}
**
-** {F11148} At least szOsFile bytes of memory is allocated by SQLite
+** {F11148} At least szOsFile bytes of memory are allocated by SQLite
** to hold the [sqlite3_file] structure passed as the third
** argument to xOpen. {END} The xOpen method does not have to
** allocate the structure; it should just fill it in.
**
@@ -1129,9 +1170,9 @@
** if a file is readable and writable, or [SQLITE_ACCESS_READ]
** to test to see if a file is at least readable. {END} The file can be a
** directory.
**
-** {F11150} SQLite will always allocate at least mxPathname+1 byte for
+** {F11150} SQLite will always allocate at least mxPathname+1 bytes for
** the output buffers for xGetTempname and xFullPathname. {F11151} The exact
** size of the output buffer is also passed as a parameter to both
** methods. {END} If the output buffer is not large enough, SQLITE_CANTOPEN
** should be returned. As this is handled as a fatal error by SQLite,
@@ -1143,9 +1184,9 @@
** included in the VFS structure for completeness.
** The xRandomness() function attempts to return nBytes bytes
** of good-quality randomness into zOut. The return value is
** the actual number of bytes of randomness obtained. The
-** xSleep() method cause the calling thread to sleep for at
+** xSleep() method causes the calling thread to sleep for at
** least the number of microseconds given. The xCurrentTime()
** method returns a Julian Day Number for the current date and
** time.
*/
@@ -1178,9 +1219,9 @@
** CAPI3REF: Flags for the xAccess VFS method {F11190}
**
** {F11191} These integer constants can be used as the third parameter to
** the xAccess method of an [sqlite3_vfs] object. {END} They determine
-** the kind of what kind of permissions the xAccess method is
+** what kind of permissions the xAccess method is
** looking for. {F11192} With SQLITE_ACCESS_EXISTS, the xAccess method
** simply checks to see if the file exists. {F11193} With
** SQLITE_ACCESS_READWRITE, the xAccess method checks to see
** if the file is both readable and writable. {F11194} With
@@ -1219,9 +1260,9 @@
** integer key called the "rowid". The rowid is always available
** as an undeclared column named ROWID, OID, or _ROWID_ as long as those
** names are not also used by explicitly declared columns. If
** the table has a column of type INTEGER PRIMARY KEY then that column
-** is another an alias for the rowid.
+** is another alias for the rowid.
**
** This routine returns the rowid of the most recent
** successful INSERT into the database from the database connection
** shown in the first argument. If no successful inserts
@@ -1259,9 +1300,9 @@
** immediately before and after a ROLLBACK.
**
** LIMITATIONS:
**
-** {U12232} If separate thread does a new insert on the same
+** {U12232} If a separate thread does a new insert on the same
** database connection while the [sqlite3_last_insert_rowid()]
** function is running and thus changes the last insert rowid,
** then the value returned by [sqlite3_last_insert_rowid()] is
** unpredictable and might not equal either the old or the new
@@ -1279,9 +1320,9 @@
** DELETE statement are counted. Auxiliary changes caused by
** triggers are not counted. Use the [sqlite3_total_changes()] function
** to find the total number of changes including changes caused by triggers.
**
-** A "row changes" is a change to a single row of a single table
+** A "row change" is a change to a single row of a single table
** caused by an INSERT, DELETE, or UPDATE statement. Rows that
** are changed as side effects of REPLACE constraint resolution,
** rollback, ABORT processing, DROP TABLE, or by any other
** mechanisms do not count as direct row changes.
@@ -1351,9 +1392,9 @@
**
** SQLite implements the command "DELETE FROM table" without
** a WHERE clause by dropping and recreating the table. (This is much
** faster than going
-** through and deleting individual elements form the table.) Because of
+** through and deleting individual elements from the table.) Because of
** this optimization, the change count for "DELETE FROM table" will be
** zero regardless of the number of elements that were originally in the
** table. To get an accurate count of the number of rows deleted, use
** "DELETE FROM table WHERE 1" instead.
@@ -1955,19 +1996,44 @@
SQLITE_API sqlite3_int64 sqlite3_memory_used(void);
SQLITE_API sqlite3_int64 sqlite3_memory_highwater(int resetFlag);
/*
+** CAPI3REF: Pseudo-Random Number Generator {F17390}
+**
+** SQLite contains a high-quality pseudo-random number generator (PRNG) used to
+** select random ROWIDs when inserting new records into a table that
+** already uses the largest possible ROWID. The PRNG is also used for
+** the build-in random() and randomblob() SQL functions. This interface allows
+** appliations to access the same PRNG for other purposes.
+**
+** A call to this routine stores N bytes of randomness into buffer P.
+**
+** The first time this routine is invoked (either internally or by
+** the application) the PRNG is seeded using randomness obtained
+** from the xRandomness method of the default [sqlite3_vfs] object.
+** On all subsequent invocations, the pseudo-randomness is generated
+** internally and without recourse to the [sqlite3_vfs] xRandomness
+** method.
+**
+** INVARIANTS:
+**
+** {F17392} The [sqlite3_randomness(N,P)] interface writes N bytes of
+** high-quality pseudo-randomness into buffer P.
+*/
+SQLITE_API void sqlite3_randomness(int N, void *P);
+
+/*
** CAPI3REF: Compile-Time Authorization Callbacks {F12500}
**
** This routine registers a authorizer callback with a particular
-** database connection, supplied in the first argument.
+** [database connection], supplied in the first argument.
** The authorizer callback is invoked as SQL statements are being compiled
** by [sqlite3_prepare()] or its variants [sqlite3_prepare_v2()],
** [sqlite3_prepare16()] and [sqlite3_prepare16_v2()]. At various
** points during the compilation process, as logic is being created
** to perform various actions, the authorizer callback is invoked to
** see if those actions are allowed. The authorizer callback should
-** return SQLITE_OK to allow the action, [SQLITE_IGNORE] to disallow the
+** return [SQLITE_OK] to allow the action, [SQLITE_IGNORE] to disallow the
** specific action but allow the SQL statement to continue to be
** compiled, or [SQLITE_DENY] to cause the entire SQL statement to be
** rejected with an error. If the authorizer callback returns
** any value other than [SQLITE_IGNORE], [SQLITE_OK], or [SQLITE_DENY]
@@ -1978,11 +2044,11 @@
** requested is ok. When the callback returns [SQLITE_DENY], the
** [sqlite3_prepare_v2()] or equivalent call that triggered the
** authorizer will fail with an error message explaining that
** access is denied. If the authorizer code is [SQLITE_READ]
-** and the callback returns [SQLITE_IGNORE] then the prepared
-** statement is constructed to insert a NULL value in place of
-** the table column that would have
+** and the callback returns [SQLITE_IGNORE] then the
+** [prepared statement] statement is constructed to substitute
+** a NULL value in place of the table column that would have
** been read if [SQLITE_OK] had been returned. The [SQLITE_IGNORE]
** return can be used to deny an untrusted user access to individual
** columns of a table.
**
@@ -1993,18 +2059,24 @@
** to be authorized. The third through sixth
** parameters to the callback are zero-terminated strings that contain
** additional details about the action to be authorized.
**
-** An authorizer is used when preparing SQL statements from an untrusted
+** An authorizer is used when [sqlite3_prepare | preparing]
+** SQL statements from an untrusted
** source, to ensure that the SQL statements do not try to access data
** that they are not allowed to see, or that they do not try to
** execute malicious statements that damage the database. For
** example, an application may allow a user to enter arbitrary
** SQL queries for evaluation by a database. But the application does
** not want the user to be able to make arbitrary changes to the
** database. An authorizer could then be put in place while the
-** user-entered SQL is being prepared that disallows everything
-** except SELECT statements.
+** user-entered SQL is being [sqlite3_prepare | prepared] that
+** disallows everything except [SELECT] statements.
+**
+** Applications that need to process SQL from untrusted sources
+** might also consider lowering resource limits using [sqlite3_limit()]
+** and limiting database size using the [max_page_count] [PRAGMA]
+** in addition to using an authorizer.
**
** Only a single authorizer can be in place on a database connection
** at a time. Each call to sqlite3_set_authorizer overrides the
** previous call. Disable the authorizer by installing a NULL callback.
@@ -2317,8 +2389,11 @@
** not already exist.
** The third options is behavior that is always used for [sqlite3_open()]
** and [sqlite3_open16()].
**
+** If the 3rd parameter to [sqlite3_open_v2()] is not one of the
+** combinations shown above then the behavior is undefined.
+**
** If the filename is ":memory:", then an private
** in-memory database is created for the connection. This in-memory
** database will vanish when the database connection is closed. Future
** version of SQLite might make use of additional special filenames
@@ -2395,10 +2470,10 @@
** ephemeral, in-memory database is created for the connection.
** <todo>Is SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE required
** in sqlite3_open_v2()?</todo>
**
-** {F12719} If the filename is an empty string, then a private, ephermeral
-** on-disk database will be created.
+** {F12719} If the filename is NULL or an empty string, then a private,
+** ephermeral on-disk database will be created.
** <todo>Is SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE required
** in sqlite3_open_v2()?</todo>
**
** {F12721} The [database connection] created by
@@ -2434,34 +2509,26 @@
** The sqlite3_errmsg() and sqlite3_errmsg16() return English-language
** text that describes the error, as either UTF8 or UTF16 respectively.
** Memory to hold the error message string is managed internally.
** The application does not need to worry with freeing the result.
-** However, the error string might be overwritten or deallocated b
+** However, the error string might be overwritten or deallocated by
** subsequent calls to other SQLite interface functions.
**
** INVARIANTS:
**
** {F12801} The [sqlite3_errcode(D)] interface returns the numeric
** [SQLITE_OK | result code] or
** [SQLITE_IOERR_READ | extended result code]
-** for the most recent failed interface call associated
-** with [sqlite3] handle D.
-**
-** {U12802} If a prior API call failed but the most recent API call
-** succeeded, the return value from [sqlite3_errcode()],
-** [sqlite3_errmsg()], and [sqlite3_errmsg16()] are undefined.
+** for the most recently failed interface call associated
+** with [database connection] D.
**
** {F12803} The [sqlite3_errmsg(D)] and [sqlite3_errmsg16(D)]
** interfaces return English-language text that describes
** the error in the mostly recently failed interface call,
** encoded as either UTF8 or UTF16 respectively.
**
-** {U12804} The strings returned by [sqlite3_errmsg()] and [sqlite3_errmsg16()]
-** are only valid until the next SQLite interface call.
-**
-** {F12807} Calls to [sqlite3_errcode()], [sqlite3_errmsg()], and
-** [sqlite3_errmsg16()] themselves do not affect the
-** results of future invocations of these routines.
+** {F12807} The strings returned by [sqlite3_errmsg()] and [sqlite3_errmsg16()]
+** are valid until the next SQLite interface call.
**
** {F12808} Calls to API routines that do not return an error code
** (example: [sqlite3_data_count()]) do not
** change the error code or message returned by
@@ -2503,8 +2570,115 @@
*/
typedef struct sqlite3_stmt sqlite3_stmt;
/*
+** CAPI3REF: Run-time Limits {F12760}
+**
+** This interface allows the size of various constructs to be limited
+** on a connection by connection basis. The first parameter is the
+** [database connection] whose limit is to be set or queried. The
+** second parameter is one of the [limit categories] that define a
+** class of constructs to be size limited. The third parameter is the
+** new limit for that construct. The function returns the old limit.
+**
+** If the new limit is a negative number, the limit is unchanged.
+** For the limit category of SQLITE_LIMIT_XYZ there is a hard upper
+** bound set by a compile-time C-preprocess macro named SQLITE_MAX_XYZ.
+** (The "_LIMIT_" in the name is changed to "_MAX_".)
+** Attempts to increase a limit above its hard upper bound are
+** silently truncated to the hard upper limit.
+**
+** Run time limits are intended for use in applications that manage
+** both their own internal database and also databases that are controlled
+** by untrusted external sources. An example application might be a
+** webbrowser that has its own databases for storing history and
+** separate databases controlled by javascript applications downloaded
+** off the internet. The internal databases can be given the
+** large, default limits. Databases managed by external sources can
+** be given much smaller limits designed to prevent a denial of service
+** attach. Developers might also want to use the [sqlite3_set_authorizer()]
+** interface to further control untrusted SQL. The size of the database
+** created by an untrusted script can be contained using the
+** [max_page_count] [PRAGMA].
+**
+** This interface is currently considered experimental and is subject
+** to change or removal without prior notice.
+**
+** INVARIANTS:
+**
+** {F12762} A successful call to [sqlite3_limit(D,C,V)] where V is
+** positive changes the
+** limit on the size of construct C in [database connection] D
+** to the lessor of V and the hard upper bound on the size
+** of C that is set at compile-time.
+**
+** {F12766} A successful call to [sqlite3_limit(D,C,V)] where V is negative
+** leaves the state of [database connection] D unchanged.
+**
+** {F12769} A successful call to [sqlite3_limit(D,C,V)] returns the
+** value of the limit on the size of construct C in
+** in [database connection] D as it was prior to the call.
+*/
+SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal);
+
+/*
+** CAPI3REF: Run-Time Limit Categories {F12790}
+** KEYWORDS: {limit category} {limit categories}
+**
+** These constants define various aspects of a [database connection]
+** that can be limited in size by calls to [sqlite3_limit()].
+** The meanings of the various limits are as follows:
+**
+** <dl>
+** <dt>SQLITE_LIMIT_LENGTH</dt>
+** <dd>The maximum size of any
+** string or blob or table row.<dd>
+**
+** <dt>SQLITE_LIMIT_SQL_LENGTH</dt>
+** <dd>The maximum length of an SQL statement.</dd>
+**
+** <dt>SQLITE_LIMIT_COLUMN</dt>
+** <dd>The maximum number of columns in a table definition or in the
+** result set of a SELECT or the maximum number of columns in an index
+** or in an ORDER BY or GROUP BY clause.</dd>
+**
+** <dt>SQLITE_LIMIT_EXPR_DEPTH</dt>
+** <dd>The maximum depth of the parse tree on any expression.</dd>
+**
+** <dt>SQLITE_LIMIT_COMPOUND_SELECT</dt>
+** <dd>The maximum number of terms in a compound SELECT statement.</dd>
+**
+** <dt>SQLITE_LIMIT_VDBE_OP</dt>
+** <dd>The maximum number of instructions in a virtual machine program
+** used to implement an SQL statement.</dd>
+**
+** <dt>SQLITE_LIMIT_FUNCTION_ARG</dt>
+** <dd>The maximum number of arguments on a function.</dd>
+**
+** <dt>SQLITE_LIMIT_ATTACHED</dt>
+** <dd>The maximum number of attached databases.</dd>
+**
+** <dt>SQLITE_LIMIT_LIKE_PATTERN_LENGTH</dt>
+** <dd>The maximum length of the pattern argument to the LIKE or
+** GLOB operators.</dd>
+**
+** <dt>SQLITE_LIMIT_VARIABLE_NUMBER</dt>
+** <dd>The maximum number of variables in an SQL statement that can
+** be bound.</dd>
+** </dl>
+*/
+#define SQLITE_LIMIT_LENGTH 0
+#define SQLITE_LIMIT_SQL_LENGTH 1
+#define SQLITE_LIMIT_COLUMN 2
+#define SQLITE_LIMIT_EXPR_DEPTH 3
+#define SQLITE_LIMIT_COMPOUND_SELECT 4
+#define SQLITE_LIMIT_VDBE_OP 5
+#define SQLITE_LIMIT_FUNCTION_ARG 6
+#define SQLITE_LIMIT_ATTACHED 7
+#define SQLITE_LIMIT_LIKE_PATTERN_LENGTH 8
+#define SQLITE_LIMIT_VARIABLE_NUMBER 9
+
+/*
** CAPI3REF: Compiling An SQL Statement {F13010}
**
** To execute an SQL query, it must first be compiled into a byte-code
** program using one of these routines.
@@ -2521,17 +2695,21 @@
** than zero, then zSql is read up to the first zero terminator.
** If nByte is non-negative, then it is the maximum number of
** bytes read from zSql. When nByte is non-negative, the
** zSql string ends at either the first '\000' or '\u0000' character or
-** until the nByte-th byte, whichever comes first. {END}
+** the nByte-th byte, whichever comes first. If the caller knows
+** that the supplied string is nul-terminated, then there is a small
+** performance advantage to be had by passing an nByte parameter that
+** is equal to the number of bytes in the input string <i>including</i>
+** the nul-terminator bytes.{END}
**
** *pzTail is made to point to the first byte past the end of the
** first SQL statement in zSql. These routines only compiles the first
** statement in zSql, so *pzTail is left pointing to what remains
** uncompiled.
**
** *ppStmt is left pointing to a compiled [prepared statement] that can be
-** executed using [sqlite3_step()]. Or if there is an error, *ppStmt may be
+** executed using [sqlite3_step()]. Or if there is an error, *ppStmt is
** set to NULL. If the input text contains no SQL (if the input
** is and empty string or a comment) then *ppStmt is set to NULL.
** {U13018} The calling procedure is responsible for deleting the
** compiled SQL statement
@@ -2587,9 +2765,9 @@
** and its variants is less than zero, then SQL text is
** read from zSql is read up to the first zero terminator.
**
** {F13014} If the nByte argument to [sqlite3_prepare_v2(db,zSql,nByte,...)]
-** and its variants is non-negative, then nBytes bytes
+** and its variants is non-negative, then at most nBytes bytes
** SQL text is read from zSql.
**
** {F13015} In [sqlite3_prepare_v2(db,zSql,N,P,pzTail)] and its variants
** if the zSql input text contains more than one SQL statement
@@ -2603,8 +2781,12 @@
** if zSql contains nothing other than whitespace or comments.
**
** {F13019} The [sqlite3_prepare_v2()] interface and its variants return
** [SQLITE_OK] or an appropriate [error code] upon failure.
+**
+** {F13021} Before [sqlite3_prepare(db,zSql,nByte,ppStmt,pzTail)] or its
+** variants returns an error (any value other than [SQLITE_OK])
+** it first sets *ppStmt to NULL.
*/
SQLITE_API int sqlite3_prepare(
sqlite3 *db, /* Database handle */
const char *zSql, /* SQL statement, UTF-8 encoded */
@@ -2662,14 +2844,41 @@
SQLITE_API const char *sqlite3_sql(sqlite3_stmt *pStmt);
/*
** CAPI3REF: Dynamically Typed Value Object {F15000}
+** KEYWORDS: {protected sqlite3_value} {unprotected sqlite3_value}
**
** SQLite uses the sqlite3_value object to represent all values
-** that are or can be stored in a database table.
+** that can be stored in a database table.
** SQLite uses dynamic typing for the values it stores.
** Values stored in sqlite3_value objects can be
** be integers, floating point values, strings, BLOBs, or NULL.
+**
+** An sqlite3_value object may be either "protected" or "unprotected".
+** Some interfaces require a protected sqlite3_value. Other interfaces
+** will accept either a protected or an unprotected sqlite3_value.
+** Every interface that accepts sqlite3_value arguments specifies
+** whether or not it requires a protected sqlite3_value.
+**
+** The terms "protected" and "unprotected" refer to whether or not
+** a mutex is held. A internal mutex is held for a protected
+** sqlite3_value object but no mutex is held for an unprotected
+** sqlite3_value object. If SQLite is compiled to be single-threaded
+** (with SQLITE_THREADSAFE=0 and with [sqlite3_threadsafe()] returning 0)
+** then there is no distinction between
+** protected and unprotected sqlite3_value objects and they can be
+** used interchangable. However, for maximum code portability it
+** is recommended that applications make the distinction between
+** between protected and unprotected sqlite3_value objects even if
+** they are single threaded.
+**
+** The sqlite3_value objects that are passed as parameters into the
+** implementation of application-defined SQL functions are protected.
+** The sqlite3_value object returned by
+** [sqlite3_column_value()] is unprotected.
+** Unprotected sqlite3_value objects may only be used with
+** [sqlite3_result_value()] and [sqlite3_bind_value()]. All other
+** interfaces that use sqlite3_value require protected sqlite3_value objects.
*/
typedef struct Mem sqlite3_value;
/*
@@ -2719,10 +2928,9 @@
**
** In those
** routines that have a fourth argument, its value is the number of bytes
** in the parameter. To be clear: the value is the number of <u>bytes</u>
-** in the value, not the number of characters. The number
-** of bytes does not include the zero-terminator at the end of strings.
+** in the value, not the number of characters.
** If the fourth parameter is negative, the length of the string is
** number of bytes up to the first zero terminator.
**
** The fifth argument to sqlite3_bind_blob(), sqlite3_bind_text(), and
@@ -2829,8 +3037,12 @@
** V value after it has finished using the V value.
**
** {F13548} In calls to [sqlite3_bind_zeroblob(S,N,V,L)] the value bound
** is a blob of L bytes, or a zero-length blob if L is negative.
+**
+** {F13551} In calls to [sqlite3_bind_value(S,N,V)] the V argument may
+** be either a [protected sqlite3_value] object or an
+** [unprotected sqlite3_value] object.
*/
SQLITE_API int sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*));
SQLITE_API int sqlite3_bind_double(sqlite3_stmt*, int, double);
SQLITE_API int sqlite3_bind_int(sqlite3_stmt*, int, int);
@@ -2872,13 +3084,14 @@
** CAPI3REF: Name Of A Host Parameter {F13620}
**
** This routine returns a pointer to the name of the n-th
** SQL parameter in a [prepared statement].
-** SQL parameters of the form ":AAA" or "@AAA" or "$AAA" have a name
-** which is the string ":AAA" or "@AAA" or "$VVV".
-** In other words, the initial ":" or "$" or "@"
+** SQL parameters of the form "?NNN" or ":AAA" or "@AAA" or "$AAA"
+** have a name which is the string "?NNN" or ":AAA" or "@AAA" or "$AAA"
+** respectively.
+** In other words, the initial ":" or "$" or "@" or "?"
** is included as part of the name.
-** Parameters of the form "?" or "?NNN" have no name.
+** Parameters of the form "?" without a following integer have no name.
**
** The first host parameter has an index of 1, not 0.
**
** If the value n is out of range or if the n-th parameter is
@@ -2896,10 +3109,9 @@
** {F13621} The [sqlite3_bind_parameter_name(S,N)] interface returns
** a UTF-8 rendering of the name of the SQL parameter in
** [prepared statement] S having index N, or
** NULL if there is no SQL parameter with index N or if the
-** parameter with index N is an anonymous parameter "?" or
-** a numbered parameter "?NNN".
+** parameter with index N is an anonymous parameter "?".
*/
SQLITE_API const char *sqlite3_bind_parameter_name(sqlite3_stmt*, int);
/*
@@ -3194,9 +3406,9 @@
** interface [sqlite3_prepare()] and [sqlite3_prepare16()]. The use of the
** new "v2" interface is recommended for new applications but the legacy
** interface will continue to be supported.
**
-** In the lagacy interface, the return value will be either [SQLITE_BUSY],
+** In the legacy interface, the return value will be either [SQLITE_BUSY],
** [SQLITE_DONE], [SQLITE_ROW], [SQLITE_ERROR], or [SQLITE_MISUSE].
** With the "v2" interface, any of the other [SQLITE_OK | result code]
** or [SQLITE_IOERR_READ | extended result code] might be returned as
** well.
@@ -3387,8 +3599,17 @@
** The sqlite3_column_bytes16() routine is similar to sqlite3_column_bytes()
** but leaves the result in UTF-16 in native byte order instead of UTF-8.
** The zero terminator is not included in this count.
**
+** The object returned by [sqlite3_column_value()] is an
+** [unprotected sqlite3_value] object. An unprotected sqlite3_value object
+** may only be used with [sqlite3_bind_value()] and [sqlite3_result_value()].
+** If the [unprotected sqlite3_value] object returned by
+** [sqlite3_column_value()] is used in any other way, including calls
+** to routines like
+** [sqlite3_value_int()], [sqlite3_value_text()], or [sqlite3_value_bytes()],
+** then the behavior is undefined.
+**
** These routines attempt to convert the value where appropriate. For
** example, if the internal representation is FLOAT and a text result
** is requested, [sqlite3_snprintf()] is used internally to do the conversion
** automatically. The following table details the conversions that
@@ -3502,10 +3723,10 @@
** returns a copy of that value.
**
** {F13815} The [sqlite3_column_int(S,N)] interface converts the
** Nth column in the current row of the result set for
-** [prepared statement] S into a 32-bit signed integer and
-** returns a copy of that integer.
+** [prepared statement] S into a 64-bit signed integer and
+** returns the lower 32 bits of that integer.
**
** {F13818} The [sqlite3_column_int64(S,N)] interface converts the
** Nth column in the current row of the result set for
** [prepared statement] S into a 64-bit signed integer and
@@ -3528,9 +3749,9 @@
** the Nth column in the current row of the result set for
** [prepared statement] S.
**
** {F13830} The [sqlite3_column_value(S,N)] interface returns a
-** pointer to the [sqlite3_value] object that for the
+** pointer to an [unprotected sqlite3_value] object for the
** Nth column in the current row of the result set for
** [prepared statement] S.
*/
SQLITE_API const void *sqlite3_column_blob(sqlite3_stmt*, int iCol);
@@ -3611,13 +3832,12 @@
** difference only between the two is that the second parameter, the
** name of the (scalar) function or aggregate, is encoded in UTF-8 for
** sqlite3_create_function() and UTF-16 for sqlite3_create_function16().
**
-** The first argument is the [database connection] that holds the
-** SQL function or aggregate is to be added or redefined. If a single
-** program uses more than one database handle internally, then SQL
-** functions or aggregates must be added individually to each database
-** handle with which they will be used.
+** The first parameter is the [database connection] to which the SQL
+** function is to be added. If a single
+** program uses more than one [database connection] internally, then SQL
+** functions must be added individually to each [database connection].
**
** 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, exclusive of the
@@ -3668,9 +3888,65 @@
** interprets the zFunctionName argument as
** zero-terminated UTF-16 native byte order instead of as a
** zero-terminated UTF-8.
**
-** {F16106}
+** {F16106} A successful invocation of
+** the [sqlite3_create_function(D,X,N,E,...)] interface registers
+** or replaces callback functions in [database connection] D
+** used to implement the SQL function named X with N parameters
+** and having a perferred text encoding of E.
+**
+** {F16109} A successful call to [sqlite3_create_function(D,X,N,E,P,F,S,L)]
+** replaces the P, F, S, and L values from any prior calls with
+** the same D, X, N, and E values.
+**
+** {F16112} The [sqlite3_create_function(D,X,...)] interface fails with
+** a return code of [SQLITE_ERROR] if the SQL function name X is
+** longer than 255 bytes exclusive of the zero terminator.
+**
+** {F16118} Either F must be NULL and S and L are non-NULL or else F
+** is non-NULL and S and L are NULL, otherwise
+** [sqlite3_create_function(D,X,N,E,P,F,S,L)] returns [SQLITE_ERROR].
+**
+** {F16121} The [sqlite3_create_function(D,...)] interface fails with an
+** error code of [SQLITE_BUSY] if there exist [prepared statements]
+** associated with the [database connection] D.
+**
+** {F16124} The [sqlite3_create_function(D,X,N,...)] interface fails with an
+** error code of [SQLITE_ERROR] if parameter N (specifying the number
+** of arguments to the SQL function being registered) is less
+** than -1 or greater than 127.
+**
+** {F16127} When N is non-negative, the [sqlite3_create_function(D,X,N,...)]
+** interface causes callbacks to be invoked for the SQL function
+** named X when the number of arguments to the SQL function is
+** exactly N.
+**
+** {F16130} When N is -1, the [sqlite3_create_function(D,X,N,...)]
+** interface causes callbacks to be invoked for the SQL function
+** named X with any number of arguments.
+**
+** {F16133} When calls to [sqlite3_create_function(D,X,N,...)]
+** specify multiple implementations of the same function X
+** and when one implementation has N>=0 and the other has N=(-1)
+** the implementation with a non-zero N is preferred.
+**
+** {F16136} When calls to [sqlite3_create_function(D,X,N,E,...)]
+** specify multiple implementations of the same function X with
+** the same number of arguments N but with different
+** encodings E, then the implementation where E matches the
+** database encoding is preferred.
+**
+** {F16139} For an aggregate SQL function created using
+** [sqlite3_create_function(D,X,N,E,P,0,S,L)] the finializer
+** function L will always be invoked exactly once if the
+** step function S is called one or more times.
+**
+** {F16142} When SQLite invokes either the xFunc or xStep function of
+** an application-defined SQL function or aggregate created
+** by [sqlite3_create_function()] or [sqlite3_create_function16()],
+** then the array of [sqlite3_value] objects passed as the
+** third parameter are always [protected sqlite3_value] objects.
*/
SQLITE_API int sqlite3_create_function(
sqlite3 *db,
const char *zFunctionName,
@@ -3731,16 +4007,20 @@
** The xFunc (for scalar functions) or xStep (for aggregates) parameters
** to [sqlite3_create_function()] and [sqlite3_create_function16()]
** define callbacks that implement the SQL functions and aggregates.
** The 4th parameter to these callbacks is an array of pointers to
-** [sqlite3_value] objects. There is one [sqlite3_value] object for
+** [protected sqlite3_value] objects. There is one [sqlite3_value] object for
** each parameter to the SQL function. These routines are used to
** extract values from the [sqlite3_value] objects.
**
+** These routines work only with [protected sqlite3_value] objects.
+** Any attempt to use these routines on an [unprotected sqlite3_value]
+** object results in undefined behavior.
+**
** These routines work just like the corresponding
** [sqlite3_column_blob | sqlite3_column_* routines] except that
-** these routines take a single [sqlite3_value*] pointer instead
-** of an [sqlite3_stmt*] pointer and an integer column number.
+** these routines take a single [protected sqlite3_value] object pointer
+** instead of an [sqlite3_stmt*] pointer and an integer column number.
**
** The sqlite3_value_text16() interface extracts a UTF16 string
** in the native byte-order of the host machine. The
** sqlite3_value_text16be() and sqlite3_value_text16le() interfaces
@@ -3760,13 +4040,72 @@
** [sqlite3_value_bytes()], [sqlite3_value_bytes16()], [sqlite3_value_text()],
** or [sqlite3_value_text16()].
**
** These routines must be called from the same thread as
-** the SQL function that supplied the sqlite3_value* parameters.
-** Or, if the sqlite3_value* argument comes from the [sqlite3_column_value()]
-** interface, then these routines should be called from the same thread
-** that ran [sqlite3_column_value()].
-**
+** the SQL function that supplied the [sqlite3_value*] parameters.
+**
+**
+** INVARIANTS:
+**
+** {F15103} The [sqlite3_value_blob(V)] interface converts the
+** [protected sqlite3_value] object V into a blob and then returns a
+** pointer to the converted value.
+**
+** {F15106} The [sqlite3_value_bytes(V)] interface returns the
+** number of bytes in the blob or string (exclusive of the
+** zero terminator on the string) that was returned by the
+** most recent call to [sqlite3_value_blob(V)] or
+** [sqlite3_value_text(V)].
+**
+** {F15109} The [sqlite3_value_bytes16(V)] interface returns the
+** number of bytes in the string (exclusive of the
+** zero terminator on the string) that was returned by the
+** most recent call to [sqlite3_value_text16(V)],
+** [sqlite3_value_text16be(V)], or [sqlite3_value_text16le(V)].
+**
+** {F15112} The [sqlite3_value_double(V)] interface converts the
+** [protected sqlite3_value] object V into a floating point value and
+** returns a copy of that value.
+**
+** {F15115} The [sqlite3_value_int(V)] interface converts the
+** [protected sqlite3_value] object V into a 64-bit signed integer and
+** returns the lower 32 bits of that integer.
+**
+** {F15118} The [sqlite3_value_int64(V)] interface converts the
+** [protected sqlite3_value] object V into a 64-bit signed integer and
+** returns a copy of that integer.
+**
+** {F15121} The [sqlite3_value_text(V)] interface converts the
+** [protected sqlite3_value] object V into a zero-terminated UTF-8
+** string and returns a pointer to that string.
+**
+** {F15124} The [sqlite3_value_text16(V)] interface converts the
+** [protected sqlite3_value] object V into a zero-terminated 2-byte
+** aligned UTF-16 native byte order
+** string and returns a pointer to that string.
+**
+** {F15127} The [sqlite3_value_text16be(V)] interface converts the
+** [protected sqlite3_value] object V into a zero-terminated 2-byte
+** aligned UTF-16 big-endian
+** string and returns a pointer to that string.
+**
+** {F15130} The [sqlite3_value_text16le(V)] interface converts the
+** [protected sqlite3_value] object V into a zero-terminated 2-byte
+** aligned UTF-16 little-endian
+** string and returns a pointer to that string.
+**
+** {F15133} The [sqlite3_value_type(V)] interface returns
+** one of [SQLITE_NULL], [SQLITE_INTEGER], [SQLITE_FLOAT],
+** [SQLITE_TEXT], or [SQLITE_BLOB] as appropriate for
+** the [sqlite3_value] object V.
+**
+** {F15136} The [sqlite3_value_numeric_type(V)] interface converts
+** the [protected sqlite3_value] object V into either an integer or
+** a floating point value if it can do so without loss of
+** information, and returns one of [SQLITE_NULL],
+** [SQLITE_INTEGER], [SQLITE_FLOAT], [SQLITE_TEXT], or
+** [SQLITE_BLOB] as appropriate for
+** the [protected sqlite3_value] object V after the conversion attempt.
*/
SQLITE_API const void *sqlite3_value_blob(sqlite3_value*);
SQLITE_API int sqlite3_value_bytes(sqlite3_value*);
SQLITE_API int sqlite3_value_bytes16(sqlite3_value*);
@@ -3784,18 +4123,18 @@
** CAPI3REF: Obtain Aggregate Function Context {F16210}
**
** The implementation of aggregate SQL functions use this routine to allocate
** a structure for storing their state.
-** {F16211} The first time the sqlite3_aggregate_context() routine is
+** The first time the sqlite3_aggregate_context() routine is
** is called for a particular aggregate, SQLite allocates nBytes of memory
** zeros that memory, and returns a pointer to it.
-** {F16212} On second and subsequent calls to sqlite3_aggregate_context()
-** for the same aggregate function index, the same buffer is returned. {END}
+** On second and subsequent calls to sqlite3_aggregate_context()
+** for the same aggregate function index, the same buffer is returned.
** The implementation
** of the aggregate can use the returned buffer to accumulate data.
**
-** {F16213} SQLite automatically frees the allocated buffer when the aggregate
-** query concludes. {END}
+** SQLite automatically frees the allocated buffer when the aggregate
+** query concludes.
**
** The first parameter should be a copy of the
** [sqlite3_context | SQL function context] that is the first
** parameter to the callback routine that implements the aggregate
@@ -3802,24 +4141,72 @@
** function.
**
** This routine must be called from the same thread in which
** the aggregate SQL function is running.
+**
+** INVARIANTS:
+**
+** {F16211} The first invocation of [sqlite3_aggregate_context(C,N)] for
+** a particular instance of an aggregate function (for a particular
+** context C) causes SQLite to allocation N bytes of memory,
+** zero that memory, and return a pointer to the allocationed
+** memory.
+**
+** {F16213} If a memory allocation error occurs during
+** [sqlite3_aggregate_context(C,N)] then the function returns 0.
+**
+** {F16215} Second and subsequent invocations of
+** [sqlite3_aggregate_context(C,N)] for the same context pointer C
+** ignore the N parameter and return a pointer to the same
+** block of memory returned by the first invocation.
+**
+** {F16217} The memory allocated by [sqlite3_aggregate_context(C,N)] is
+** automatically freed on the next call to [sqlite3_reset()]
+** or [sqlite3_finalize()] for the [prepared statement] containing
+** the aggregate function associated with context C.
*/
SQLITE_API void *sqlite3_aggregate_context(sqlite3_context*, int nBytes);
/*
** CAPI3REF: User Data For Functions {F16240}
**
-** {F16241} The sqlite3_user_data() interface returns a copy of
+** The sqlite3_user_data() interface returns a copy of
** the pointer that was the pUserData parameter (the 5th parameter)
** of the the [sqlite3_create_function()]
** and [sqlite3_create_function16()] routines that originally
** registered the application defined function. {END}
**
-** {U16243} This routine must be called from the same thread in which
+** This routine must be called from the same thread in which
** the application-defined function is running.
+**
+** INVARIANTS:
+**
+** {F16243} The [sqlite3_user_data(C)] interface returns a copy of the
+** P pointer from the [sqlite3_create_function(D,X,N,E,P,F,S,L)]
+** or [sqlite3_create_function16(D,X,N,E,P,F,S,L)] call that
+** registered the SQL function associated with
+** [sqlite3_context] C.
*/
SQLITE_API void *sqlite3_user_data(sqlite3_context*);
+
+/*
+** CAPI3REF: Database Connection For Functions {F16250}
+**
+** The sqlite3_context_db_handle() interface returns a copy of
+** the pointer to the [database connection] (the 1st parameter)
+** of the the [sqlite3_create_function()]
+** and [sqlite3_create_function16()] routines that originally
+** registered the application defined function.
+**
+** INVARIANTS:
+**
+** {F16253} The [sqlite3_context_db_handle(C)] interface returns a copy of the
+** D pointer from the [sqlite3_create_function(D,X,N,E,P,F,S,L)]
+** or [sqlite3_create_function16(D,X,N,E,P,F,S,L)] call that
+** registered the SQL function associated with
+** [sqlite3_context] C.
+*/
+SQLITE_API sqlite3 *sqlite3_context_db_handle(sqlite3_context*);
/*
** CAPI3REF: Function Auxiliary Data {F16270}
**
@@ -3833,33 +4220,64 @@
** pattern. The compiled regular expression can be reused on multiple
** invocations of the same function so that the original pattern string
** does not need to be recompiled on each invocation.
**
-** {F16271}
** The sqlite3_get_auxdata() interface returns a pointer to the meta-data
** associated by the sqlite3_set_auxdata() function with the Nth argument
** value to the application-defined function.
-** {F16272} If no meta-data has been ever been set for the Nth
+** If no meta-data has been ever been set for the Nth
** argument of the function, or if the cooresponding function parameter
** has changed since the meta-data was set, then sqlite3_get_auxdata()
** returns a NULL pointer.
**
-** {F16275} The sqlite3_set_auxdata() interface saves the meta-data
+** The sqlite3_set_auxdata() interface saves the meta-data
** pointed to by its 3rd parameter as the meta-data for the N-th
-** argument of the application-defined function. {END} Subsequent
+** argument of the application-defined function. Subsequent
** calls to sqlite3_get_auxdata() might return this data, if it has
** not been destroyed.
-** {F16277} If it is not NULL, SQLite will invoke the destructor
+** If it is not NULL, SQLite will invoke the destructor
** function given by the 4th parameter to sqlite3_set_auxdata() on
** the meta-data when the corresponding function parameter changes
-** or when the SQL statement completes, whichever comes first. {END}
+** or when the SQL statement completes, whichever comes first.
+**
+** SQLite is free to call the destructor and drop meta-data on
+** any parameter of any function at any time. The only guarantee
+** is that the destructor will be called before the metadata is
+** dropped.
**
** In practice, meta-data is preserved between function calls for
** expressions that are constant at compile time. This includes literal
** values and SQL variables.
**
** These routines must be called from the same thread in which
** the SQL function is running.
+**
+** INVARIANTS:
+**
+** {F16272} The [sqlite3_get_auxdata(C,N)] interface returns a pointer
+** to metadata associated with the Nth parameter of the SQL function
+** whose context is C, or NULL if there is no metadata associated
+** with that parameter.
+**
+** {F16274} The [sqlite3_set_auxdata(C,N,P,D)] interface assigns a metadata
+** pointer P to the Nth parameter of the SQL function with context
+** C.
+**
+** {F16276} SQLite will invoke the destructor D with a single argument
+** which is the metadata pointer P following a call to
+** [sqlite3_set_auxdata(C,N,P,D)] when SQLite ceases to hold
+** the metadata.
+**
+** {F16277} SQLite ceases to hold metadata for an SQL function parameter
+** when the value of that parameter changes.
+**
+** {F16278} When [sqlite3_set_auxdata(C,N,P,D)] is invoked, the destructor
+** is called for any prior metadata associated with the same function
+** context C and parameter N.
+**
+** {F16279} SQLite will call destructors for any metadata it is holding
+** in a particular [prepared statement] S when either
+** [sqlite3_reset(S)] or [sqlite3_finalize(S)] is called.
*/
SQLITE_API void *sqlite3_get_auxdata(sqlite3_context*, int N);
SQLITE_API void sqlite3_set_auxdata(sqlite3_context*, int N, void*, void (*)(void*));
@@ -3896,99 +4314,203 @@
** Refer to the
** [sqlite3_bind_blob | sqlite3_bind_* documentation] for
** additional information.
**
-** {F16402} The sqlite3_result_blob() interface sets the result from
+** The sqlite3_result_blob() interface sets the result from
** an application defined function to be the BLOB whose content is pointed
** to by the second parameter and which is N bytes long where N is the
** third parameter.
-** {F16403} The sqlite3_result_zeroblob() inerfaces set the result of
+** The sqlite3_result_zeroblob() inerfaces set the result of
** the application defined function to be a BLOB containing all zero
** bytes and N bytes in size, where N is the value of the 2nd parameter.
**
-** {F16407} The sqlite3_result_double() interface sets the result from
+** The sqlite3_result_double() interface sets the result from
** an application defined function to be a floating point value specified
** by its 2nd argument.
**
-** {F16409} The sqlite3_result_error() and sqlite3_result_error16() functions
+** The sqlite3_result_error() and sqlite3_result_error16() functions
** cause the implemented SQL function to throw an exception.
-** {F16411} SQLite uses the string pointed to by the
+** SQLite uses the string pointed to by the
** 2nd parameter of sqlite3_result_error() or sqlite3_result_error16()
-** as the text of an error message. {F16412} SQLite interprets the error
-** message string from sqlite3_result_error() as UTF8. {F16413} SQLite
+** as the text of an error message. SQLite interprets the error
+** message string from sqlite3_result_error() as UTF8. SQLite
** interprets the string from sqlite3_result_error16() as UTF16 in native
-** byte order. {F16414} If the third parameter to sqlite3_result_error()
+** byte order. 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.
-** {F16415} If the third parameter to sqlite3_result_error() or
+** If the third parameter to sqlite3_result_error() or
** sqlite3_result_error16() is non-negative then SQLite takes that many
** bytes (not characters) from the 2nd parameter as the error message.
-** {F16417} The sqlite3_result_error() and sqlite3_result_error16()
+** The sqlite3_result_error() and sqlite3_result_error16()
** routines make a copy private copy of the error message text before
-** they return. {END} Hence, the calling function can deallocate or
+** they return. Hence, the calling function can deallocate or
** modify the text after they return without harm.
-**
-** {F16421} The sqlite3_result_toobig() interface causes SQLite
+** The sqlite3_result_error_code() function changes the error code
+** returned by SQLite as a result of an error in a function. By default,
+** the error code is SQLITE_ERROR. A subsequent call to sqlite3_result_error()
+** or sqlite3_result_error16() resets the error code to SQLITE_ERROR.
+**
+** The sqlite3_result_toobig() interface causes SQLite
** to throw an error indicating that a string or BLOB is to long
-** to represent. {F16422} The sqlite3_result_nomem() interface
+** to represent. The sqlite3_result_nomem() interface
** causes SQLite to throw an exception indicating that the a
** memory allocation failed.
**
-** {F16431} The sqlite3_result_int() interface sets the return value
+** The sqlite3_result_int() interface sets the return value
** of the application-defined function to be the 32-bit signed integer
** value given in the 2nd argument.
-** {F16432} The sqlite3_result_int64() interface sets the return value
+** The sqlite3_result_int64() interface sets the return value
** of the application-defined function to be the 64-bit signed integer
** value given in the 2nd argument.
**
-** {F16437} The sqlite3_result_null() interface sets the return value
+** The sqlite3_result_null() interface sets the return value
** of the application-defined function to be NULL.
**
-** {F16441} The sqlite3_result_text(), sqlite3_result_text16(),
+** The sqlite3_result_text(), sqlite3_result_text16(),
** sqlite3_result_text16le(), and sqlite3_result_text16be() interfaces
** 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.
-** {F16442} SQLite takes the text result from the application from
+** SQLite takes the text result from the application from
** the 2nd parameter of the sqlite3_result_text* interfaces.
-** {F16444} If the 3rd parameter to 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.
-** {F16447} If the 3rd parameter to the sqlite3_result_text* interfaces
+** 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.
-** {F16451} If the 4th parameter to the sqlite3_result_text* interfaces
+** If the 4th parameter to the sqlite3_result_text* interfaces
** or sqlite3_result_blob is a non-NULL pointer, then SQLite calls that
** function as the destructor on the text or blob result when it has
** finished using that result.
-** {F16453} If the 4th parameter to the sqlite3_result_text* interfaces
+** If the 4th parameter to the sqlite3_result_text* interfaces
** or sqlite3_result_blob is the special constant SQLITE_STATIC, then
** SQLite assumes that the text or blob result is constant space and
** does not copy the space or call a destructor when it has
** finished using that result.
-** {F16454} If the 4th parameter to the sqlite3_result_text* interfaces
+** If the 4th parameter to the sqlite3_result_text* interfaces
** or sqlite3_result_blob is the special constant SQLITE_TRANSIENT
** then SQLite makes a copy of the result into space obtained from
** from [sqlite3_malloc()] before it returns.
**
-** {F16461} The sqlite3_result_value() interface sets the result of
-** the application-defined function to be a copy the [sqlite3_value]
-** object specified by the 2nd parameter. {F16463} The
+** The sqlite3_result_value() interface sets the result of
+** the application-defined function to be a copy the
+** [unprotected sqlite3_value] object specified by the 2nd parameter. The
** sqlite3_result_value() interface makes a copy of the [sqlite3_value]
** so that [sqlite3_value] specified in the parameter may change or
** be deallocated after sqlite3_result_value() returns without harm.
-**
-** {U16491} These routines are called from within the different thread
+** A [protected sqlite3_value] object may always be used where an
+** [unprotected sqlite3_value] object is required, so either
+** kind of [sqlite3_value] object can be used with this interface.
+**
+** If these routines are called from within the different thread
** than the one containing the application-defined function that recieved
** the [sqlite3_context] pointer, the results are undefined.
+**
+** INVARIANTS:
+**
+** {F16403} The default return value from any SQL function is NULL.
+**
+** {F16406} The [sqlite3_result_blob(C,V,N,D)] interface changes the
+** return value of function C to be a blob that is N bytes
+** in length and with content pointed to by V.
+**
+** {F16409} The [sqlite3_result_double(C,V)] interface changes the
+** return value of function C to be the floating point value V.
+**
+** {F16412} The [sqlite3_result_error(C,V,N)] interface changes the return
+** value of function C to be an exception with error code
+** [SQLITE_ERROR] and a UTF8 error message copied from V up to the
+** first zero byte or until N bytes are read if N is positive.
+**
+** {F16415} The [sqlite3_result_error16(C,V,N)] interface changes the return
+** value of function C to be an exception with error code
+** [SQLITE_ERROR] and a UTF16 native byte order error message
+** copied from V up to the first zero terminator or until N bytes
+** are read if N is positive.
+**
+** {F16418} The [sqlite3_result_error_toobig(C)] interface changes the return
+** value of the function C to be an exception with error code
+** [SQLITE_TOOBIG] and an appropriate error message.
+**
+** {F16421} The [sqlite3_result_error_nomem(C)] interface changes the return
+** value of the function C to be an exception with error code
+** [SQLITE_NOMEM] and an appropriate error message.
+**
+** {F16424} The [sqlite3_result_error_code(C,E)] interface changes the return
+** value of the function C to be an exception with error code E.
+** The error message text is unchanged.
+**
+** {F16427} The [sqlite3_result_int(C,V)] interface changes the
+** return value of function C to be the 32-bit integer value V.
+**
+** {F16430} The [sqlite3_result_int64(C,V)] interface changes the
+** return value of function C to be the 64-bit integer value V.
+**
+** {F16433} The [sqlite3_result_null(C)] interface changes the
+** return value of function C to be NULL.
+**
+** {F16436} The [sqlite3_result_text(C,V,N,D)] interface changes the
+** return value of function C to be the UTF8 string
+** V up to the first zero if N is negative
+** or the first N bytes of V if N is non-negative.
+**
+** {F16439} The [sqlite3_result_text16(C,V,N,D)] interface changes the
+** return value of function C to be the UTF16 native byte order
+** string V up to the first zero if N is
+** negative or the first N bytes of V if N is non-negative.
+**
+** {F16442} The [sqlite3_result_text16be(C,V,N,D)] interface changes the
+** return value of function C to be the UTF16 big-endian
+** string V up to the first zero if N is
+** is negative or the first N bytes or V if N is non-negative.
+**
+** {F16445} The [sqlite3_result_text16le(C,V,N,D)] interface changes the
+** return value of function C to be the UTF16 little-endian
+** string V up to the first zero if N is
+** negative or the first N bytes of V if N is non-negative.
+**
+** {F16448} The [sqlite3_result_value(C,V)] interface changes the
+** return value of function C to be [unprotected sqlite3_value]
+** object V.
+**
+** {F16451} The [sqlite3_result_zeroblob(C,N)] interface changes the
+** return value of function C to be an N-byte blob of all zeros.
+**
+** {F16454} The [sqlite3_result_error()] and [sqlite3_result_error16()]
+** interfaces make a copy of their error message strings before
+** returning.
+**
+** {F16457} If the D destructor parameter to [sqlite3_result_blob(C,V,N,D)],
+** [sqlite3_result_text(C,V,N,D)], [sqlite3_result_text16(C,V,N,D)],
+** [sqlite3_result_text16be(C,V,N,D)], or
+** [sqlite3_result_text16le(C,V,N,D)] is the constant [SQLITE_STATIC]
+** then no destructor is ever called on the pointer V and SQLite
+** assumes that V is immutable.
+**
+** {F16460} If the D destructor parameter to [sqlite3_result_blob(C,V,N,D)],
+** [sqlite3_result_text(C,V,N,D)], [sqlite3_result_text16(C,V,N,D)],
+** [sqlite3_result_text16be(C,V,N,D)], or
+** [sqlite3_result_text16le(C,V,N,D)] is the constant
+** [SQLITE_TRANSIENT] then the interfaces makes a copy of the
+** content of V and retains the copy.
+**
+** {F16463} If the D destructor parameter to [sqlite3_result_blob(C,V,N,D)],
+** [sqlite3_result_text(C,V,N,D)], [sqlite3_result_text16(C,V,N,D)],
+** [sqlite3_result_text16be(C,V,N,D)], or
+** [sqlite3_result_text16le(C,V,N,D)] is some value other than
+** the constants [SQLITE_STATIC] and [SQLITE_TRANSIENT] then
+** SQLite will invoke the destructor D with V as its only argument
+** when it has finished with the V value.
*/
SQLITE_API void sqlite3_result_blob(sqlite3_context*, const void*, int, void(*)(void*));
SQLITE_API void sqlite3_result_double(sqlite3_context*, double);
SQLITE_API void sqlite3_result_error(sqlite3_context*, const char*, int);
SQLITE_API void sqlite3_result_error16(sqlite3_context*, const void*, int);
SQLITE_API void sqlite3_result_error_toobig(sqlite3_context*);
SQLITE_API void sqlite3_result_error_nomem(sqlite3_context*);
+SQLITE_API void sqlite3_result_error_code(sqlite3_context*, int);
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*));
@@ -4000,37 +4522,32 @@
/*
** CAPI3REF: Define New Collating Sequences {F16600}
**
-** {F16601}
** These functions are used to add new collation sequences to the
** [sqlite3*] handle specified as the first argument.
**
-** {F16602}
** The name of the new collation sequence is specified as a UTF-8 string
** for sqlite3_create_collation() and sqlite3_create_collation_v2()
-** and a UTF-16 string for sqlite3_create_collation16(). {F16603} In all cases
+** and a UTF-16 string for sqlite3_create_collation16(). In all cases
** the name is passed as the second function argument.
**
-** {F16604}
** The third argument may be one of the constants [SQLITE_UTF8],
** [SQLITE_UTF16LE] or [SQLITE_UTF16BE], indicating that the user-supplied
** routine expects to be passed pointers to strings encoded using UTF-8,
-** UTF-16 little-endian or UTF-16 big-endian respectively. {F16605} The
+** UTF-16 little-endian or UTF-16 big-endian respectively. The
** third argument might also be [SQLITE_UTF16_ALIGNED] to indicate that
** the routine expects pointers to 16-bit word aligned strings
** of UTF16 in the native byte order of the host computer.
**
-** {F16607}
** A pointer to the user supplied routine must be passed as the fifth
-** argument. {F16609} If it is NULL, this is the same as deleting the collation
+** argument. If it is NULL, this is the same as deleting the collation
** sequence (so that SQLite cannot call it anymore).
-** {F16611} Each time the application
+** Each time the application
** supplied function is invoked, it is passed a copy of the void* passed as
** the fourth argument to sqlite3_create_collation() or
** sqlite3_create_collation16() as its first parameter.
**
-** {F16612}
** The remaining arguments to the application-supplied routine are two strings,
** each represented by a (length, data) pair and encoded in the encoding
** that was passed as the third argument when the collation sequence was
** registered. {END} The application defined collation routine should
@@ -4037,17 +4554,65 @@
** return negative, zero or positive if
** the first string is less than, equal to, or greater than the second
** string. i.e. (STRING1 - STRING2).
**
-** {F16615}
** The sqlite3_create_collation_v2() works like sqlite3_create_collation()
** excapt that it takes an extra argument which is a destructor for
-** the collation. {F16617} The destructor is called when the collation is
+** the collation. The destructor is called when the collation is
** destroyed and is passed a copy of the fourth parameter void* pointer
** of the sqlite3_create_collation_v2().
-** {F16618} Collations are destroyed when
+** Collations are destroyed when
** they are overridden by later calls to the collation creation functions
** or when the [sqlite3*] database handle is closed using [sqlite3_close()].
+**
+** INVARIANTS:
+**
+** {F16603} A successful call to the
+** [sqlite3_create_collation_v2(B,X,E,P,F,D)] interface
+** registers function F as the comparison function used to
+** implement collation X on [database connection] B for
+** databases having encoding E.
+**
+** {F16604} SQLite understands the X parameter to
+** [sqlite3_create_collation_v2(B,X,E,P,F,D)] as a zero-terminated
+** UTF-8 string in which case is ignored for ASCII characters and
+** is significant for non-ASCII characters.
+**
+** {F16606} Successive calls to [sqlite3_create_collation_v2(B,X,E,P,F,D)]
+** with the same values for B, X, and E, override prior values
+** of P, F, and D.
+**
+** {F16609} The destructor D in [sqlite3_create_collation_v2(B,X,E,P,F,D)]
+** is not NULL then it is called with argument P when the
+** collating function is dropped by SQLite.
+**
+** {F16612} A collating function is dropped when it is overloaded.
+**
+** {F16615} A collating function is dropped when the database connection
+** is closed using [sqlite3_close()].
+**
+** {F16618} The pointer P in [sqlite3_create_collation_v2(B,X,E,P,F,D)]
+** is passed through as the first parameter to the comparison
+** function F for all subsequent invocations of F.
+**
+** {F16621} A call to [sqlite3_create_collation(B,X,E,P,F)] is exactly
+** the same as a call to [sqlite3_create_collation_v2()] with
+** the same parameters and a NULL destructor.
+**
+** {F16624} Following a [sqlite3_create_collation_v2(B,X,E,P,F,D)],
+** SQLite uses the comparison function F for all text comparison
+** operations on [database connection] B on text values that
+** use the collating sequence name X.
+**
+** {F16627} The [sqlite3_create_collation16(B,X,E,P,F)] works the same
+** as [sqlite3_create_collation(B,X,E,P,F)] except that the
+** collation name X is understood as UTF-16 in native byte order
+** instead of UTF-8.
+**
+** {F16630} When multiple comparison functions are available for the same
+** collating sequence, SQLite chooses the one whose text encoding
+** requires the least amount of conversion from the default
+** text encoding of the database.
*/
SQLITE_API int sqlite3_create_collation(
sqlite3*,
const char *zName,
@@ -4073,33 +4638,52 @@
/*
** CAPI3REF: Collation Needed Callbacks {F16700}
**
-** {F16701}
** To avoid having to register all collation sequences before a database
** can be used, a single callback function may be registered with the
** database handle to be called whenever an undefined collation sequence is
** required.
**
-** {F16702}
** If the function is registered using the sqlite3_collation_needed() API,
** then it is passed the names of undefined collation sequences as strings
** encoded in UTF-8. {F16703} If sqlite3_collation_needed16() is used, the names
-** are passed as UTF-16 in machine native byte order. {F16704} A call to either
+** are passed as UTF-16 in machine native byte order. A call to either
** function replaces any existing callback.
**
-** {F16705} When the callback is invoked, the first argument passed is a copy
+** When the callback is invoked, the first argument passed is a copy
** of the second argument to sqlite3_collation_needed() or
-** sqlite3_collation_needed16(). {F16706} The second argument is the database
-** handle. {F16707} The third argument is one of [SQLITE_UTF8],
+** sqlite3_collation_needed16(). The second argument is the database
+** handle. The third argument is one of [SQLITE_UTF8],
** [SQLITE_UTF16BE], or [SQLITE_UTF16LE], indicating the most
** desirable form of the collation sequence function required.
-** {F16708} The fourth parameter is the name of the
-** required collation sequence. {END}
+** The fourth parameter is the name of the
+** required collation sequence.
**
** The callback function should register the desired collation using
** [sqlite3_create_collation()], [sqlite3_create_collation16()], or
** [sqlite3_create_collation_v2()].
+**
+** INVARIANTS:
+**
+** {F16702} A successful call to [sqlite3_collation_needed(D,P,F)]
+** or [sqlite3_collation_needed16(D,P,F)] causes
+** the [database connection] D to invoke callback F with first
+** parameter P whenever it needs a comparison function for a
+** collating sequence that it does not know about.
+**
+** {F16704} Each successful call to [sqlite3_collation_needed()] or
+** [sqlite3_collation_needed16()] overrides the callback registered
+** on the same [database connection] by prior calls to either
+** interface.
+**
+** {F16706} The name of the requested collating function passed in the
+** 4th parameter to the callback is in UTF-8 if the callback
+** was registered using [sqlite3_collation_needed()] and
+** is in UTF-16 native byte order if the callback was
+** registered using [sqlite3_collation_needed16()].
+**
+**
*/
SQLITE_API int sqlite3_collation_needed(
sqlite3*,
void*,
@@ -4138,19 +4722,30 @@
/*
** CAPI3REF: Suspend Execution For A Short Time {F10530}
**
-** {F10531} The sqlite3_sleep() function
+** The sqlite3_sleep() function
** causes the current thread to suspend execution
** for at least a number of milliseconds specified in its parameter.
**
-** {F10532} If the operating system does not support sleep requests with
+** If the operating system does not support sleep requests with
** millisecond time resolution, then the time will be rounded up to
-** the nearest second. {F10533} The number of milliseconds of sleep actually
+** the nearest second. The number of milliseconds of sleep actually
** requested from the operating system is returned.
**
-** {F10534} SQLite implements this interface by calling the xSleep()
-** method of the default [sqlite3_vfs] object. {END}
+** SQLite implements this interface by calling the xSleep()
+** method of the default [sqlite3_vfs] object.
+**
+** INVARIANTS:
+**
+** {F10533} The [sqlite3_sleep(M)] interface invokes the xSleep
+** method of the default [sqlite3_vfs|VFS] in order to
+** suspend execution of the current thread for at least
+** M milliseconds.
+**
+** {F10536} The [sqlite3_sleep(M)] interface returns the number of
+** milliseconds of sleep actually requested of the operating
+** system, which might be larger than the parameter M.
*/
SQLITE_API int sqlite3_sleep(int);
/*
@@ -4166,9 +4761,9 @@
** has been opened. It is intended that this variable be set once
** as part of process initialization and before any SQLite interface
** routines have been call and remain unchanged thereafter.
*/
-SQLITE_EXTERN char *sqlite3_temp_directory;
+SQLITE_API char *sqlite3_temp_directory;
/*
** CAPI3REF: Test To See If The Database Is In Auto-Commit Mode {F12930}
**
@@ -4186,10 +4781,10 @@
** an error is to use this function.
**
** INVARIANTS:
**
-** {F12931} The [sqlite3_get_autocommit()] interface returns non-zero or
-** zero if the given database connection is or is not in autocommit
+** {F12931} The [sqlite3_get_autocommit(D)] interface returns non-zero or
+** zero if the [database connection] D is or is not in autocommit
** mode, respectively.
**
** {F12932} Autocommit mode is on by default.
**
@@ -4209,82 +4804,156 @@
/*
** CAPI3REF: Find The Database Handle Of A Prepared Statement {F13120}
**
-** {F13121} The sqlite3_db_handle interface
+** The sqlite3_db_handle interface
** returns the [sqlite3*] database handle to which a
** [prepared statement] belongs.
-** {F13122} the database handle returned by sqlite3_db_handle
+** The database handle returned by sqlite3_db_handle
** is the same database handle that was
** the first argument to the [sqlite3_prepare_v2()] or its variants
** that was used to create the statement in the first place.
+**
+** INVARIANTS:
+**
+** {F13123} The [sqlite3_db_handle(S)] interface returns a pointer
+** to the [database connection] associated with
+** [prepared statement] S.
*/
SQLITE_API sqlite3 *sqlite3_db_handle(sqlite3_stmt*);
/*
** CAPI3REF: Commit And Rollback Notification Callbacks {F12950}
**
-** {F12951} The sqlite3_commit_hook() interface registers a callback
+** The sqlite3_commit_hook() interface registers a callback
** function to be invoked whenever a transaction is committed.
-** {F12952} Any callback set by a previous call to sqlite3_commit_hook()
+** Any callback set by a previous call to sqlite3_commit_hook()
** for the same database connection is overridden.
-** {F12953} The sqlite3_rollback_hook() interface registers a callback
+** The sqlite3_rollback_hook() interface registers a callback
** function to be invoked whenever a transaction is committed.
-** {F12954} Any callback set by a previous call to sqlite3_commit_hook()
+** Any callback set by a previous call to sqlite3_commit_hook()
** for the same database connection is overridden.
-** {F12956} The pArg argument is passed through
-** to the callback. {F12957} If the callback on a commit hook function
+** The pArg argument is passed through
+** to the callback. If the callback on a commit hook function
** returns non-zero, then the commit is converted into a rollback.
**
-** {F12958} If another function was previously registered, its
+** If another function was previously registered, its
** pArg value is returned. Otherwise NULL is returned.
**
-** {F12959} Registering a NULL function disables the callback.
-**
-** {F12961} For the purposes of this API, a transaction is said to have been
+** Registering a NULL function disables the callback.
+**
+** For the purposes of this API, a transaction is said to have been
** rolled back if an explicit "ROLLBACK" statement is executed, or
** an error or constraint causes an implicit rollback to occur.
-** {F12962} The rollback callback is not invoked if a transaction is
+** The rollback callback is not invoked if a transaction is
** automatically rolled back because the database connection is closed.
-** {F12964} The rollback callback is not invoked if a transaction is
+** The rollback callback is not invoked if a transaction is
** rolled back because a commit callback returned non-zero.
-** <todo> Check on this </todo> {END}
+** <todo> Check on this </todo>
**
** These are experimental interfaces and are subject to change.
+**
+** INVARIANTS:
+**
+** {F12951} The [sqlite3_commit_hook(D,F,P)] interface registers the
+** callback function F to be invoked with argument P whenever
+** a transaction commits on [database connection] D.
+**
+** {F12952} The [sqlite3_commit_hook(D,F,P)] interface returns the P
+** argument from the previous call with the same
+** [database connection ] D , or NULL on the first call
+** for a particular [database connection] D.
+**
+** {F12953} Each call to [sqlite3_commit_hook()] overwrites the callback
+** registered by prior calls.
+**
+** {F12954} If the F argument to [sqlite3_commit_hook(D,F,P)] is NULL
+** then the commit hook callback is cancelled and no callback
+** is invoked when a transaction commits.
+**
+** {F12955} If the commit callback returns non-zero then the commit is
+** converted into a rollback.
+**
+** {F12961} The [sqlite3_rollback_hook(D,F,P)] interface registers the
+** callback function F to be invoked with argument P whenever
+** a transaction rolls back on [database connection] D.
+**
+** {F12962} The [sqlite3_rollback_hook(D,F,P)] interface returns the P
+** argument from the previous call with the same
+** [database connection ] D , or NULL on the first call
+** for a particular [database connection] D.
+**
+** {F12963} Each call to [sqlite3_rollback_hook()] overwrites the callback
+** registered by prior calls.
+**
+** {F12964} If the F argument to [sqlite3_rollback_hook(D,F,P)] is NULL
+** then the rollback hook callback is cancelled and no callback
+** is invoked when a transaction rolls back.
*/
SQLITE_API void *sqlite3_commit_hook(sqlite3*, int(*)(void*), void*);
SQLITE_API void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*);
/*
** CAPI3REF: Data Change Notification Callbacks {F12970}
**
-** {F12971} The sqlite3_update_hook() interface
+** The sqlite3_update_hook() interface
** registers a callback function with the database connection identified by the
** first argument to be invoked whenever a row is updated, inserted or deleted.
-** {F12972} Any callback set by a previous call to this function for the same
+** Any callback set by a previous call to this function for the same
** database connection is overridden.
**
-** {F12974} The second argument is a pointer to the function to invoke when a
+** The second argument is a pointer to the function to invoke when a
** row is updated, inserted or deleted.
-** {F12976} The first argument to the callback is
+** The first argument to the callback is
** a copy of the third argument to sqlite3_update_hook().
-** {F12977} The second callback
+** The second callback
** argument is one of [SQLITE_INSERT], [SQLITE_DELETE] or [SQLITE_UPDATE],
** depending on the operation that caused the callback to be invoked.
-** {F12978} The third and
+** The third and
** fourth arguments to the callback contain pointers to the database and
** table name containing the affected row.
-** {F12979} The final callback parameter is
+** The final callback parameter is
** the rowid of the row.
-** {F12981} In the case of an update, this is the rowid after
+** In the case of an update, this is the rowid after
** the update takes place.
**
-** {F12983} The update hook is not invoked when internal system tables are
+** The update hook is not invoked when internal system tables are
** modified (i.e. sqlite_master and sqlite_sequence).
**
-** {F12984} If another function was previously registered, its pArg value
-** is returned. {F12985} Otherwise NULL is returned.
+** If another function was previously registered, its pArg value
+** is returned. Otherwise NULL is returned.
+**
+** INVARIANTS:
+**
+** {F12971} The [sqlite3_update_hook(D,F,P)] interface causes callback
+** function F to be invoked with first parameter P whenever
+** a table row is modified, inserted, or deleted on
+** [database connection] D.
+**
+** {F12973} The [sqlite3_update_hook(D,F,P)] interface returns the value
+** of P for the previous call on the same [database connection] D,
+** or NULL for the first call.
+**
+** {F12975} If the update hook callback F in [sqlite3_update_hook(D,F,P)]
+** is NULL then the no update callbacks are made.
+**
+** {F12977} Each call to [sqlite3_update_hook(D,F,P)] overrides prior calls
+** to the same interface on the same [database connection] D.
+**
+** {F12979} The update hook callback is not invoked when internal system
+** tables such as sqlite_master and sqlite_sequence are modified.
+**
+** {F12981} The second parameter to the update callback
+** is one of [SQLITE_INSERT], [SQLITE_DELETE] or [SQLITE_UPDATE],
+** depending on the operation that caused the callback to be invoked.
+**
+** {F12983} The third and fourth arguments to the callback contain pointers
+** to zero-terminated UTF-8 strings which are the names of the
+** database and table that is being updated.
+
+** {F12985} The final callback parameter is the rowid of the row after
+** the change occurs.
*/
SQLITE_API void *sqlite3_update_hook(
sqlite3*,
void(*)(void *,int ,char const *,char const *,sqlite3_int64),
@@ -4293,85 +4962,133 @@
/*
** CAPI3REF: Enable Or Disable Shared Pager Cache {F10330}
**
-** {F10331}
** This routine enables or disables the sharing of the database cache
** and schema data structures between connections to the same database.
-** {F10332}
** Sharing is enabled if the argument is true and disabled if the argument
** is false.
**
-** {F10333} Cache sharing is enabled and disabled
+** Cache sharing is enabled and disabled
** for an entire process. {END} This is a change as of SQLite version 3.5.0.
** In prior versions of SQLite, sharing was
** enabled or disabled for each thread separately.
**
-** {F10334}
** The cache sharing mode set by this interface effects all subsequent
** calls to [sqlite3_open()], [sqlite3_open_v2()], and [sqlite3_open16()].
-** {F10335} Existing database connections continue use the sharing mode
-** that was in effect at the time they were opened. {END}
-**
-** Virtual tables cannot be used with a shared cache. {F10336} When shared
+** Existing database connections continue use the sharing mode
+** that was in effect at the time they were opened.
+**
+** Virtual tables cannot be used with a shared cache. When shared
** cache is enabled, the [sqlite3_create_module()] API used to register
-** virtual tables will always return an error. {END}
-**
-** {F10337} This routine returns [SQLITE_OK] if shared cache was
-** enabled or disabled successfully. {F10338} An [error code]
-** is returned otherwise. {END}
-**
-** {F10339} Shared cache is disabled by default. {END} But this might change in
+** virtual tables will always return an error.
+**
+** 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.
+**
+** INVARIANTS:
+**
+** {F10331} A successful invocation of [sqlite3_enable_shared_cache(B)]
+** will enable or disable shared cache mode for any subsequently
+** created [database connection] in the same process.
+**
+** {F10336} When shared cache is enabled, the [sqlite3_create_module()]
+** interface will always return an error.
+**
+** {F10337} The [sqlite3_enable_shared_cache(B)] interface returns
+** [SQLITE_OK] if shared cache was enabled or disabled successfully.
+**
+** {F10339} Shared cache is disabled by default.
*/
SQLITE_API int sqlite3_enable_shared_cache(int);
/*
** CAPI3REF: Attempt To Free Heap Memory {F17340}
**
-** {F17341} The sqlite3_release_memory() interface attempts to
+** The sqlite3_release_memory() interface attempts to
** free N bytes of heap memory by deallocating non-essential memory
** allocations held by the database labrary. {END} Memory used
** to cache database pages to improve performance is an example of
-** non-essential memory. {F16342} sqlite3_release_memory() returns
+** non-essential memory. Sqlite3_release_memory() returns
** the number of bytes actually freed, which might be more or less
** than the amount requested.
+**
+** INVARIANTS:
+**
+** {F17341} The [sqlite3_release_memory(N)] interface attempts to
+** free N bytes of heap memory by deallocating non-essential
+** memory allocations held by the database labrary.
+**
+** {F16342} The [sqlite3_release_memory(N)] returns the number
+** of bytes actually freed, which might be more or less
+** than the amount requested.
*/
SQLITE_API int sqlite3_release_memory(int);
/*
** CAPI3REF: Impose A Limit On Heap Size {F17350}
**
-** {F16351} The sqlite3_soft_heap_limit() interface
+** The sqlite3_soft_heap_limit() interface
** places a "soft" limit on the amount of heap memory that may be allocated
-** by SQLite. {F16352} If an internal allocation is requested
+** by SQLite. If an internal allocation is requested
** that would exceed the soft heap limit, [sqlite3_release_memory()] is
** invoked one or more times to free up some space before the allocation
-** is made. {END}
-**
-** {F16353} The limit is called "soft", because if
+** is made.
+**
+** The limit is called "soft", because if
** [sqlite3_release_memory()] cannot
** free sufficient memory to prevent the limit from being exceeded,
** the memory is allocated anyway and the current operation proceeds.
**
-** {F16354}
** A negative or zero value for N means that there is no soft heap limit and
** [sqlite3_release_memory()] will only be called when memory is exhausted.
-** {F16355} The default value for the soft heap limit is zero.
+** The default value for the soft heap limit is zero.
**
** SQLite makes a best effort to honor the soft heap limit.
-** {F16356} But if the soft heap limit cannot honored, execution will
-** continue without error or notification. {END} This is why the limit is
+** But if the soft heap limit cannot honored, execution will
+** continue without error or notification. This is why the limit is
** called a "soft" limit. It is advisory only.
**
** Prior to SQLite version 3.5.0, this routine only constrained the memory
** allocated by a single thread - the same thread in which this routine
** runs. Beginning with SQLite version 3.5.0, the soft heap limit is
-** applied to all threads. {F16357} The value specified for the soft heap limit
-** is an upper bound on the total memory allocation for all threads. {END} In
+** applied to all threads. The value specified for the soft heap limit
+** is an upper bound on the total memory allocation for all threads. In
** version 3.5.0 there is no mechanism for limiting the heap usage for
** individual threads.
+**
+** INVARIANTS:
+**
+** {F16351} The [sqlite3_soft_heap_limit(N)] interface places a soft limit
+** of N bytes on the amount of heap memory that may be allocated
+** using [sqlite3_malloc()] or [sqlite3_realloc()] at any point
+** in time.
+**
+** {F16352} If a call to [sqlite3_malloc()] or [sqlite3_realloc()] would
+** cause the total amount of allocated memory to exceed the
+** soft heap limit, then [sqlite3_release_memory()] is invoked
+** in an attempt to reduce the memory usage prior to proceeding
+** with the memory allocation attempt.
+**
+** {F16353} Calls to [sqlite3_malloc()] or [sqlite3_realloc()] that trigger
+** attempts to reduce memory usage through the soft heap limit
+** mechanism continue even if the attempt to reduce memory
+** usage is unsuccessful.
+**
+** {F16354} A negative or zero value for N in a call to
+** [sqlite3_soft_heap_limit(N)] means that there is no soft
+** heap limit and [sqlite3_release_memory()] will only be
+** called when memory is completely exhausted.
+**
+** {F16355} The default value for the soft heap limit is zero.
+**
+** {F16358} Each call to [sqlite3_soft_heap_limit(N)] overrides the
+** values set by all prior calls.
*/
SQLITE_API void sqlite3_soft_heap_limit(int);
/*
@@ -4559,8 +5276,11 @@
typedef struct sqlite3_vtab_cursor sqlite3_vtab_cursor;
typedef struct sqlite3_module sqlite3_module;
/*
+** CAPI3REF: Virtual Table Object {F18000}
+** KEYWORDS: sqlite3_module
+**
** A module is a class of virtual tables. Each module is defined
** by an instance of the following structure. This structure consists
** mostly of methods for the module.
*/
@@ -4595,8 +5315,11 @@
int (*xRename)(sqlite3_vtab *pVtab, const char *zNew);
};
/*
+** CAPI3REF: Virtual Table Indexing Information {F18100}
+** KEYWORDS: sqlite3_index_info
+**
** The sqlite3_index_info structure and its substructures is used to
** pass information into and receive the reply from the xBestIndex
** method of an sqlite3_module. The fields under **Inputs** are the
** inputs to xBestIndex and are read-only. xBestIndex inserts its
@@ -4675,8 +5398,10 @@
#define SQLITE_INDEX_CONSTRAINT_GE 32
#define SQLITE_INDEX_CONSTRAINT_MATCH 64
/*
+** CAPI3REF: Register A Virtual Table Implementation {F18200}
+**
** This routine is used to register a new module name with an SQLite
** connection. Module names must be registered before creating new
** virtual tables on the module, or before using preexisting virtual
** tables of the module.
@@ -4688,8 +5413,10 @@
void * /* Client data for xCreate/xConnect */
);
/*
+** CAPI3REF: Register A Virtual Table Implementation {F18210}
+**
** This routine is identical to the sqlite3_create_module() method above,
** except that it allows a destructor function to be specified. It is
** even more experimental than the rest of the virtual tables API.
*/
@@ -4701,8 +5428,11 @@
void(*xDestroy)(void*) /* Module destructor function */
);
/*
+** CAPI3REF: Virtual Table Instance Object {F18010}
+** KEYWORDS: sqlite3_vtab
+**
** Every module implementation uses a subclass of the following structure
** to describe a particular instance of the module. Each subclass will
** be tailored to the specific needs of the module implementation. The
** purpose of this superclass is to define certain fields that are common
@@ -4724,9 +5454,13 @@
char *zErrMsg; /* Error message from sqlite3_mprintf() */
/* Virtual table implementations will typically add additional fields */
};
-/* Every module implementation uses a subclass of the following structure
+/*
+** CAPI3REF: Virtual Table Cursor Object {F18020}
+** KEYWORDS: sqlite3_vtab_cursor
+**
+** Every module implementation uses a subclass of the following structure
** to describe cursors that point into the virtual table and are used
** to loop through the virtual table. Cursors are created using the
** xOpen method of the module. Each module implementation will define
** the content of a cursor structure to suit its own needs.
@@ -4739,15 +5473,19 @@
/* Virtual table implementations will typically add additional fields */
};
/*
+** CAPI3REF: Declare The Schema Of A Virtual Table {F18280}
+**
** The xCreate and xConnect methods of a module use the following API
** to declare the format (the names and datatypes of the columns) of
** the virtual tables they implement.
*/
SQLITE_API int sqlite3_declare_vtab(sqlite3*, const char *zCreateTable);
/*
+** CAPI3REF: Overload A Function For A Virtual Table {F18300}
+**
** Virtual tables can provide alternative implementations of functions
** using the xFindFunction method. But global versions of those functions
** must exist in order to be overloaded.
**
@@ -4778,10 +5516,11 @@
/*
** CAPI3REF: A Handle To An Open BLOB {F17800}
**
-** An instance of the following opaque structure is used to
-** represent an blob-handle. A blob-handle is created by
+** An instance of this object represents an open BLOB on which
+** incremental I/O can be preformed.
+** Objects of this type are created by
** [sqlite3_blob_open()] and destroyed by [sqlite3_blob_close()].
** The [sqlite3_blob_read()] and [sqlite3_blob_write()] interfaces
** can be used to read or write small subsections of the blob.
** The [sqlite3_blob_bytes()] interface returns the size of the
@@ -4791,28 +5530,54 @@
/*
** CAPI3REF: Open A BLOB For Incremental I/O {F17810}
**
-** {F17811} This interfaces opens a handle to the blob located
-** in row iRow,, column zColumn, table zTable in database zDb;
+** This interfaces opens a handle to the blob located
+** in row iRow, column zColumn, table zTable in database zDb;
** in other words, the same blob that would be selected by:
**
** <pre>
** SELECT zColumn FROM zDb.zTable WHERE rowid = iRow;
** </pre> {END}
**
-** {F17812} If the flags parameter is non-zero, the blob is opened for
+** If the flags parameter is non-zero, the blob is opened for
** read and write access. If it is zero, the blob is opened for read
-** access. {END}
-**
-** {F17813} On success, [SQLITE_OK] is returned and the new
+** access.
+**
+** Note that the database name is not the filename that contains
+** the database but rather the symbolic name of the database that
+** is assigned when the database is connected using [ATTACH].
+** For the main database file, the database name is "main". For
+** TEMP tables, the database name is "temp".
+**
+** On success, [SQLITE_OK] is returned and the new
** [sqlite3_blob | blob handle] is written to *ppBlob.
-** {F17814} Otherwise an error code is returned and
+** Otherwise an error code is returned and
** any value written to *ppBlob should not be used by the caller.
-** {F17815} This function sets the database-handle error code and message
+** This function sets the database-handle error code and message
** accessible via [sqlite3_errcode()] and [sqlite3_errmsg()].
-** <todo>We should go through and mark all interfaces that behave this
-** way with a similar statement</todo>
+**
+** INVARIANTS:
+**
+** {F17813} A successful invocation of the [sqlite3_blob_open(D,B,T,C,R,F,P)]
+** interface opens an [sqlite3_blob] object P on the blob
+** in column C of table T in database B on [database connection] D.
+**
+** {F17814} A successful invocation of [sqlite3_blob_open(D,...)] starts
+** a new transaction on [database connection] D if that connection
+** is not already in a transaction.
+**
+** {F17816} The [sqlite3_blob_open(D,B,T,C,R,F,P)] interface opens the blob
+** for read and write access if and only if the F parameter
+** is non-zero.
+**
+** {F17819} The [sqlite3_blob_open()] interface returns [SQLITE_OK] on
+** success and an appropriate [error code] on failure.
+**
+** {F17821} If an error occurs during evaluation of [sqlite3_blob_open(D,...)]
+** then subsequent calls to [sqlite3_errcode(D)],
+** [sqlite3_errmsg(D)], and [sqlite3_errmsg16(D)] will return
+** information approprate for that error.
*/
SQLITE_API int sqlite3_blob_open(
sqlite3*,
const char *zDb,
@@ -4827,28 +5592,52 @@
** CAPI3REF: Close A BLOB Handle {F17830}
**
** Close an open [sqlite3_blob | blob handle].
**
-** {F17831} Closing a BLOB shall cause the current transaction to commit
+** Closing a BLOB shall cause the current transaction to commit
** if there are no other BLOBs, no pending prepared statements, and the
** database connection is in autocommit mode.
-** {F17832} If any writes were made to the BLOB, they might be held in cache
+** If any writes were made to the BLOB, they might be held in cache
** until the close operation if they will fit. {END}
** Closing the BLOB often forces the changes
** out to disk and so if any I/O errors occur, they will likely occur
** at the time when the BLOB is closed. {F17833} Any errors that occur during
** closing are reported as a non-zero return value.
**
-** {F17839} The BLOB is closed unconditionally. Even if this routine returns
+** The BLOB is closed unconditionally. Even if this routine returns
** an error code, the BLOB is still closed.
+**
+** INVARIANTS:
+**
+** {F17833} The [sqlite3_blob_close(P)] interface closes an
+** [sqlite3_blob] object P previously opened using
+** [sqlite3_blob_open()].
+**
+** {F17836} Closing an [sqlite3_blob] object using
+** [sqlite3_blob_close()] shall cause the current transaction to
+** commit if there are no other open [sqlite3_blob] objects
+** or [prepared statements] on the same [database connection] and
+** the [database connection] is in
+** [sqlite3_get_autocommit | autocommit mode].
+**
+** {F17839} The [sqlite3_blob_close(P)] interfaces closes the
+** [sqlite3_blob] object P unconditionally, even if
+** [sqlite3_blob_close(P)] returns something other than [SQLITE_OK].
+**
*/
SQLITE_API int sqlite3_blob_close(sqlite3_blob *);
/*
-** CAPI3REF: Return The Size Of An Open BLOB {F17805}
-**
-** {F16806} Return the size in bytes of the blob accessible via the open
-** [sqlite3_blob | blob-handle] passed as an argument.
+** CAPI3REF: Return The Size Of An Open BLOB {F17840}
+**
+** Return the size in bytes of the blob accessible via the open
+** [sqlite3_blob] object in its only argument.
+**
+** INVARIANTS:
+**
+** {F17843} The [sqlite3_blob_bytes(P)] interface returns the size
+** in bytes of the BLOB that the [sqlite3_blob] object P
+** refers to.
*/
SQLITE_API int sqlite3_blob_bytes(sqlite3_blob *);
/*
@@ -4855,40 +5644,99 @@
** CAPI3REF: Read Data From A BLOB Incrementally {F17850}
**
** This function is used to read data from an open
** [sqlite3_blob | blob-handle] into a caller supplied buffer.
-** {F17851} n bytes of data are copied into buffer
-** z from the open blob, starting at offset iOffset.
-**
-** {F17852} If offset iOffset is less than n bytes from the end of the blob,
-** [SQLITE_ERROR] is returned and no data is read. {F17853} If n is
+** N bytes of data are copied into buffer
+** Z from the open blob, starting at offset iOffset.
+**
+** If offset iOffset is less than N bytes from the end of the blob,
+** [SQLITE_ERROR] is returned and no data is read. If N or iOffset is
** less than zero [SQLITE_ERROR] is returned and no data is read.
**
-** {F17854} On success, SQLITE_OK is returned. Otherwise, an
+** On success, SQLITE_OK is returned. Otherwise, an
** [error code] or an [extended error code] is returned.
-*/
-SQLITE_API int sqlite3_blob_read(sqlite3_blob *, void *z, int n, int iOffset);
+**
+** INVARIANTS:
+**
+** {F17853} The [sqlite3_blob_read(P,Z,N,X)] interface reads N bytes
+** beginning at offset X from
+** the blob that [sqlite3_blob] object P refers to
+** and writes those N bytes into buffer Z.
+**
+** {F17856} In [sqlite3_blob_read(P,Z,N,X)] if the size of the blob
+** is less than N+X bytes, then the function returns [SQLITE_ERROR]
+** and nothing is read from the blob.
+**
+** {F17859} In [sqlite3_blob_read(P,Z,N,X)] if X or N is less than zero
+** then the function returns [SQLITE_ERROR]
+** and nothing is read from the blob.
+**
+** {F17862} The [sqlite3_blob_read(P,Z,N,X)] interface returns [SQLITE_OK]
+** if N bytes where successfully read into buffer Z.
+**
+** {F17865} If the requested read could not be completed,
+** the [sqlite3_blob_read(P,Z,N,X)] interface returns an
+** appropriate [error code] or [extended error code].
+**
+** {F17868} If an error occurs during evaluation of [sqlite3_blob_read(P,...)]
+** then subsequent calls to [sqlite3_errcode(D)],
+** [sqlite3_errmsg(D)], and [sqlite3_errmsg16(D)] will return
+** information approprate for that error, where D is the
+** database handle that was used to open blob handle P.
+*/
+SQLITE_API int sqlite3_blob_read(sqlite3_blob *, void *Z, int N, int iOffset);
/*
** CAPI3REF: Write Data Into A BLOB Incrementally {F17870}
**
** This function is used to write data into an open
** [sqlite3_blob | blob-handle] from a user supplied buffer.
-** {F17871} n bytes of data are copied from the buffer
+** n bytes of data are copied from the buffer
** pointed to by z into the open blob, starting at offset iOffset.
**
-** {F17872} If the [sqlite3_blob | blob-handle] passed as the first argument
+** If the [sqlite3_blob | blob-handle] passed as the first argument
** was not opened for writing (the flags parameter to [sqlite3_blob_open()]
*** was zero), this function returns [SQLITE_READONLY].
**
-** {F17873} This function may only modify the contents of the blob; it is
+** This function may only modify the contents of the blob; it is
** not possible to increase the size of a blob using this API.
-** {F17874} If offset iOffset is less than n bytes from the end of the blob,
-** [SQLITE_ERROR] is returned and no data is written. {F17875} If n is
+** If offset iOffset is less than n bytes from the end of the blob,
+** [SQLITE_ERROR] is returned and no data is written. If n is
** less than zero [SQLITE_ERROR] is returned and no data is written.
**
-** {F17876} On success, SQLITE_OK is returned. Otherwise, an
+** On success, SQLITE_OK is returned. Otherwise, an
** [error code] or an [extended error code] is returned.
+**
+** INVARIANTS:
+**
+** {F17873} The [sqlite3_blob_write(P,Z,N,X)] interface writes N bytes
+** from buffer Z into
+** the blob that [sqlite3_blob] object P refers to
+** beginning at an offset of X into the blob.
+**
+** {F17875} The [sqlite3_blob_write(P,Z,N,X)] interface returns
+** [SQLITE_READONLY] if the [sqlite3_blob] object P was
+** [sqlite3_blob_open | opened] for reading only.
+**
+** {F17876} In [sqlite3_blob_write(P,Z,N,X)] if the size of the blob
+** is less than N+X bytes, then the function returns [SQLITE_ERROR]
+** and nothing is written into the blob.
+**
+** {F17879} In [sqlite3_blob_write(P,Z,N,X)] if X or N is less than zero
+** then the function returns [SQLITE_ERROR]
+** and nothing is written into the blob.
+**
+** {F17882} The [sqlite3_blob_write(P,Z,N,X)] interface returns [SQLITE_OK]
+** if N bytes where successfully written into blob.
+**
+** {F17885} If the requested write could not be completed,
+** the [sqlite3_blob_write(P,Z,N,X)] interface returns an
+** appropriate [error code] or [extended error code].
+**
+** {F17888} If an error occurs during evaluation of [sqlite3_blob_write(D,...)]
+** then subsequent calls to [sqlite3_errcode(D)],
+** [sqlite3_errmsg(D)], and [sqlite3_errmsg16(D)] will return
+** information approprate for that error.
*/
SQLITE_API int sqlite3_blob_write(sqlite3_blob *, const void *z, int n, int iOffset);
/*
@@ -4895,32 +5743,59 @@
** CAPI3REF: Virtual File System Objects {F11200}
**
** A virtual filesystem (VFS) is an [sqlite3_vfs] object
** that SQLite uses to interact
-** with the underlying operating system. Most builds come with a
+** with the underlying operating system. Most SQLite builds come with a
** single default VFS that is appropriate for the host computer.
** New VFSes can be registered and existing VFSes can be unregistered.
** The following interfaces are provided.
**
-** {F11201} The sqlite3_vfs_find() interface returns a pointer to
-** a VFS given its name. {F11202} Names are case sensitive.
-** {F11203} Names are zero-terminated UTF-8 strings.
-** {F11204} If there is no match, a NULL
-** pointer is returned. {F11205} If zVfsName is NULL then the default
-** VFS is returned. {END}
-**
-** {F11210} New VFSes are registered with sqlite3_vfs_register().
-** {F11211} Each new VFS becomes the default VFS if the makeDflt flag is set.
-** {F11212} The same VFS can be registered multiple times without injury.
-** {F11213} To make an existing VFS into the default VFS, register it again
-** with the makeDflt flag set. {U11214} If two different VFSes with the
-** same name are registered, the behavior is undefined. {U11215} If a
+** The sqlite3_vfs_find() interface returns a pointer to
+** a VFS given its name. Names are case sensitive.
+** Names are zero-terminated UTF-8 strings.
+** If there is no match, a NULL
+** pointer is returned. If zVfsName is NULL then the default
+** VFS is returned.
+**
+** New VFSes are registered with sqlite3_vfs_register().
+** Each new VFS becomes the default VFS if the makeDflt flag is set.
+** The same VFS can be registered multiple times without injury.
+** To make an existing VFS into the default VFS, register it again
+** with the makeDflt flag set. If two different VFSes with the
+** same name are registered, the behavior is undefined. If a
** VFS is registered with a name that is NULL or an empty string,
** then the behavior is undefined.
**
-** {F11220} Unregister a VFS with the sqlite3_vfs_unregister() interface.
-** {F11221} If the default VFS is unregistered, another VFS is chosen as
+** Unregister a VFS with the sqlite3_vfs_unregister() interface.
+** If the default VFS is unregistered, another VFS is chosen as
** the default. The choice for the new VFS is arbitrary.
+**
+** INVARIANTS:
+**
+** {F11203} The [sqlite3_vfs_find(N)] interface returns a pointer to the
+** registered [sqlite3_vfs] object whose name exactly matches
+** the zero-terminated UTF-8 string N, or it returns NULL if
+** there is no match.
+**
+** {F11206} If the N parameter to [sqlite3_vfs_find(N)] is NULL then
+** the function returns a pointer to the default [sqlite3_vfs]
+** object if there is one, or NULL if there is no default
+** [sqlite3_vfs] object.
+**
+** {F11209} The [sqlite3_vfs_register(P,F)] interface registers the
+** well-formed [sqlite3_vfs] object P using the name given
+** by the zName field of the object.
+**
+** {F11212} Using the [sqlite3_vfs_register(P,F)] interface to register
+** the same [sqlite3_vfs] object multiple times is a harmless no-op.
+**
+** {F11215} The [sqlite3_vfs_register(P,F)] interface makes the
+** the [sqlite3_vfs] object P the default [sqlite3_vfs] object
+** if F is non-zero.
+**
+** {F11218} The [sqlite3_vfs_unregister(P)] interface unregisters the
+** [sqlite3_vfs] object P so that it is no longer returned by
+** subsequent calls to [sqlite3_vfs_find()].
*/
SQLITE_API sqlite3_vfs *sqlite3_vfs_find(const char *zVfsName);
SQLITE_API int sqlite3_vfs_register(sqlite3_vfs*, int makeDflt);
SQLITE_API int sqlite3_vfs_unregister(sqlite3_vfs*);
@@ -4973,8 +5848,9 @@
** <li> SQLITE_MUTEX_STATIC_MEM
** <li> SQLITE_MUTEX_STATIC_MEM2
** <li> SQLITE_MUTEX_STATIC_PRNG
** <li> SQLITE_MUTEX_STATIC_LRU
+** <li> SQLITE_MUTEX_STATIC_LRU2
** </ul> {END}
**
** {F17015} The first two constants cause sqlite3_mutex_alloc() to create
** a new mutex. The new mutex is recursive when SQLITE_MUTEX_RECURSIVE
@@ -5085,8 +5961,9 @@
#define SQLITE_MUTEX_STATIC_MEM 3 /* sqlite3_malloc() */
#define SQLITE_MUTEX_STATIC_MEM2 4 /* sqlite3_release_memory() */
#define SQLITE_MUTEX_STATIC_PRNG 5 /* sqlite3_random() */
#define SQLITE_MUTEX_STATIC_LRU 6 /* lru page list */
+#define SQLITE_MUTEX_STATIC_LRU2 7 /* lru page list */
/*
** CAPI3REF: Low-Level Control Of Database Files {F11300}
**
@@ -5146,11 +6023,12 @@
#define SQLITE_TESTCTRL_FAULT_CONFIG 1
#define SQLITE_TESTCTRL_FAULT_FAILURES 2
#define SQLITE_TESTCTRL_FAULT_BENIGN_FAILURES 3
#define SQLITE_TESTCTRL_FAULT_PENDING 4
-
-
-
+#define SQLITE_TESTCTRL_PRNG_SAVE 5
+#define SQLITE_TESTCTRL_PRNG_RESTORE 6
+#define SQLITE_TESTCTRL_PRNG_RESET 7
+#define SQLITE_TESTCTRL_BITVEC_TEST 8
/*
** Undo the hack that converts floating point types to integer for
@@ -5444,10 +6322,8 @@
#include <string.h>
#include <assert.h>
#include <stddef.h>
-#define sqlite3_isnan(X) ((X)!=(X))
-
/*
** If compiling for a processor that lacks floating point support,
** substitute integer for floating-point
*/
@@ -5534,21 +6410,41 @@
**
** cc '-DUINTPTR_TYPE=long long int' ...
*/
#ifndef UINT32_TYPE
-# define UINT32_TYPE unsigned int
+# ifdef HAVE_UINT32_T
+# define UINT32_TYPE uint32_t
+# else
+# define UINT32_TYPE unsigned int
+# endif
#endif
#ifndef UINT16_TYPE
-# define UINT16_TYPE unsigned short int
+# ifdef HAVE_UINT16_T
+# define UINT16_TYPE uint16_t
+# else
+# define UINT16_TYPE unsigned short int
+# endif
#endif
#ifndef INT16_TYPE
-# define INT16_TYPE short int
+# ifdef HAVE_INT16_T
+# define INT16_TYPE int16_t
+# else
+# define INT16_TYPE short int
+# endif
#endif
#ifndef UINT8_TYPE
-# define UINT8_TYPE unsigned char
+# ifdef HAVE_UINT8_T
+# define UINT8_TYPE uint8_t
+# else
+# define UINT8_TYPE unsigned char
+# endif
#endif
#ifndef INT8_TYPE
-# define INT8_TYPE signed char
+# ifdef HAVE_INT8_T
+# define INT8_TYPE int8_t
+# else
+# define INT8_TYPE signed char
+# endif
#endif
#ifndef LONGDOUBLE_TYPE
# define LONGDOUBLE_TYPE long double
#endif
@@ -5564,9 +6460,9 @@
** Macros to determine whether the machine is big or little endian,
** evaluated at runtime.
*/
#ifdef SQLITE_AMALGAMATION
-SQLITE_PRIVATE const int sqlite3One;
+SQLITE_PRIVATE const int sqlite3one;
#else
SQLITE_PRIVATE const int sqlite3one;
#endif
#if defined(i386) || defined(__i386__) || defined(_M_IX86)
@@ -5577,8 +6473,16 @@
# define SQLITE_BIGENDIAN (*(char *)(&sqlite3one)==0)
# define SQLITE_LITTLEENDIAN (*(char *)(&sqlite3one)==1)
# define SQLITE_UTF16NATIVE (SQLITE_BIGENDIAN?SQLITE_UTF16BE:SQLITE_UTF16LE)
#endif
+
+/*
+** Constants for the largest and smallest possible 64-bit signed integers.
+** These macros are designed to work correctly on both 32-bit and 64-bit
+** compilers.
+*/
+#define LARGEST_INT64 (0xffffffff|(((i64)0x7fffffff)<<32))
+#define SMALLEST_INT64 (((i64)-1) - LARGEST_INT64)
/*
** An instance of the following structure is used to store the busy-handler
** callback for a given sqlite handle.
@@ -5623,8 +6527,9 @@
** Forward references to structures
*/
typedef struct AggInfo AggInfo;
typedef struct AuthContext AuthContext;
+typedef struct Bitvec Bitvec;
typedef struct CollSeq CollSeq;
typedef struct Column Column;
typedef struct Db Db;
typedef struct Schema Schema;
@@ -5672,9 +6577,9 @@
** This header file defines the interface that the sqlite B-Tree file
** subsystem. See comments in the source code for a detailed description
** of what each interface routine does.
**
-** @(#) $Id: btree.h,v 1.94 2007/12/07 18:55:28 drh Exp $
+** @(#) $Id: btree.h,v 1.98 2008/04/26 13:39:47 drh Exp $
*/
#ifndef _BTREE_H_
#define _BTREE_H_
@@ -5786,19 +6691,28 @@
SQLITE_PRIVATE int sqlite3BtreeGetMeta(Btree*, int idx, u32 *pValue);
SQLITE_PRIVATE int sqlite3BtreeUpdateMeta(Btree*, int idx, u32 value);
SQLITE_PRIVATE void sqlite3BtreeTripAllCursors(Btree*, int);
+struct UnpackedRecord; /* Forward declaration. Definition in vdbeaux.c. */
+
SQLITE_PRIVATE int sqlite3BtreeCursor(
Btree*, /* BTree containing table to open */
int iTable, /* Index of root page */
int wrFlag, /* 1 for writing. 0 for read-only */
- int(*)(void*,int,const void*,int,const void*), /* Key comparison function */
- void*, /* First argument to compare function */
- BtCursor **ppCursor /* Returned cursor */
+ struct KeyInfo*, /* First argument to compare function */
+ BtCursor *pCursor /* Space to write cursor structure */
);
+SQLITE_PRIVATE int sqlite3BtreeCursorSize(void);
SQLITE_PRIVATE int sqlite3BtreeCloseCursor(BtCursor*);
-SQLITE_PRIVATE int sqlite3BtreeMoveto(BtCursor*,const void *pKey,i64 nKey,int bias,int *pRes);
+SQLITE_PRIVATE int sqlite3BtreeMoveto(
+ BtCursor*,
+ const void *pKey,
+ struct UnpackedRecord *pUnKey,
+ i64 nKey,
+ int bias,
+ int *pRes
+);
SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor*);
SQLITE_PRIVATE int sqlite3BtreeInsert(BtCursor*, const void *pKey, i64 nKey,
const void *pData, int nData,
int nZero, int bias);
@@ -5882,9 +6796,9 @@
** This header defines the interface to the virtual database engine
** or VDBE. The VDBE implements an abstract machine that runs a
** simple program to access and modify the underlying database.
**
-** $Id: vdbe.h,v 1.125 2008/01/17 17:27:31 drh Exp $
+** $Id: vdbe.h,v 1.131 2008/05/01 17:03:49 drh Exp $
*/
#ifndef _SQLITE_VDBE_H_
#define _SQLITE_VDBE_H_
@@ -5900,8 +6814,9 @@
** for the VdbeOp definition.
*/
typedef struct VdbeFunc VdbeFunc;
typedef struct Mem Mem;
+typedef struct UnpackedRecord UnpackedRecord;
/*
** A single instruction of the virtual machine has an opcode
** and as many as three operands. The instruction is recorded
@@ -5909,9 +6824,9 @@
*/
struct VdbeOp {
u8 opcode; /* What operation to perform */
signed char p4type; /* One of the P4_xxx constants for p4 */
- u8 flags; /* Flags for internal use */
+ u8 opflags; /* Not currently used */
u8 p5; /* Fifth parameter is an unsigned character */
int p1; /* First operand */
int p2; /* Second parameter (often the jump destination) */
int p3; /* The third parameter */
@@ -5985,9 +6900,17 @@
#define COLNAME_DECLTYPE 1
#define COLNAME_DATABASE 2
#define COLNAME_TABLE 3
#define COLNAME_COLUMN 4
-#define COLNAME_N 5 /* Number of COLNAME_xxx symbols */
+#ifdef SQLITE_ENABLE_COLUMN_METADATA
+# define COLNAME_N 5 /* Number of COLNAME_xxx symbols */
+#else
+# ifdef SQLITE_OMIT_DECLTYPE
+# define COLNAME_N 1 /* Store only the name */
+# else
+# define COLNAME_N 2 /* Store the name and decltype */
+# endif
+#endif
/*
** The following macro converts a relative address in the p2 field
** of a VdbeOp structure into a negative number so that
@@ -6004,139 +6927,139 @@
/************** Begin file opcodes.h *****************************************/
/* Automatically generated. Do not edit */
/* See the mkopcodeh.awk script for details */
#define OP_VNext 1
-#define OP_Column 2
-#define OP_SetCookie 3
+#define OP_Affinity 2
+#define OP_Column 3
+#define OP_SetCookie 4
#define OP_Real 125 /* same as TK_FLOAT */
-#define OP_Sequence 4
-#define OP_MoveGt 5
+#define OP_Sequence 5
+#define OP_MoveGt 6
#define OP_Ge 72 /* same as TK_GE */
-#define OP_RowKey 6
-#define OP_SCopy 7
+#define OP_RowKey 7
+#define OP_SCopy 8
#define OP_Eq 68 /* same as TK_EQ */
-#define OP_OpenWrite 8
+#define OP_OpenWrite 9
#define OP_NotNull 66 /* same as TK_NOTNULL */
-#define OP_If 9
+#define OP_If 10
#define OP_ToInt 141 /* same as TK_TO_INT */
#define OP_String8 88 /* same as TK_STRING */
-#define OP_VRowid 10
-#define OP_CollSeq 11
-#define OP_OpenRead 12
-#define OP_Expire 13
-#define OP_AutoCommit 14
+#define OP_VRowid 11
+#define OP_CollSeq 12
+#define OP_OpenRead 13
+#define OP_Expire 14
+#define OP_AutoCommit 15
#define OP_Gt 69 /* same as TK_GT */
-#define OP_IntegrityCk 15
-#define OP_Sort 17
-#define OP_Copy 18
-#define OP_Trace 19
-#define OP_Function 20
-#define OP_IfNeg 21
+#define OP_IntegrityCk 17
+#define OP_Sort 18
+#define OP_Copy 19
+#define OP_Trace 20
+#define OP_Function 21
+#define OP_IfNeg 22
#define OP_And 61 /* same as TK_AND */
#define OP_Subtract 79 /* same as TK_MINUS */
-#define OP_Noop 22
-#define OP_Return 23
+#define OP_Noop 23
+#define OP_Return 24
#define OP_Remainder 82 /* same as TK_REM */
-#define OP_NewRowid 24
+#define OP_NewRowid 25
#define OP_Multiply 80 /* same as TK_STAR */
-#define OP_Variable 25
-#define OP_String 26
-#define OP_RealAffinity 27
-#define OP_VRename 28
-#define OP_ParseSchema 29
-#define OP_VOpen 30
-#define OP_Close 31
-#define OP_CreateIndex 32
-#define OP_IsUnique 33
-#define OP_NotFound 34
-#define OP_Int64 35
-#define OP_MustBeInt 36
-#define OP_Halt 37
-#define OP_Rowid 38
-#define OP_IdxLT 39
-#define OP_AddImm 40
-#define OP_Statement 41
-#define OP_RowData 42
-#define OP_MemMax 43
+#define OP_Variable 26
+#define OP_String 27
+#define OP_RealAffinity 28
+#define OP_VRename 29
+#define OP_ParseSchema 30
+#define OP_VOpen 31
+#define OP_Close 32
+#define OP_CreateIndex 33
+#define OP_IsUnique 34
+#define OP_NotFound 35
+#define OP_Int64 36
+#define OP_MustBeInt 37
+#define OP_Halt 38
+#define OP_Rowid 39
+#define OP_IdxLT 40
+#define OP_AddImm 41
+#define OP_Statement 42
+#define OP_RowData 43
+#define OP_MemMax 44
#define OP_Or 60 /* same as TK_OR */
-#define OP_NotExists 44
-#define OP_Gosub 45
+#define OP_NotExists 45
+#define OP_Gosub 46
#define OP_Divide 81 /* same as TK_SLASH */
-#define OP_Integer 46
+#define OP_Integer 47
#define OP_ToNumeric 140 /* same as TK_TO_NUMERIC*/
-#define OP_Prev 47
+#define OP_Prev 48
#define OP_Concat 83 /* same as TK_CONCAT */
#define OP_BitAnd 74 /* same as TK_BITAND */
-#define OP_VColumn 48
-#define OP_CreateTable 49
-#define OP_Last 50
+#define OP_VColumn 49
+#define OP_CreateTable 50
+#define OP_Last 51
#define OP_IsNull 65 /* same as TK_ISNULL */
-#define OP_IncrVacuum 51
-#define OP_IdxRowid 52
+#define OP_IncrVacuum 52
+#define OP_IdxRowid 53
#define OP_ShiftRight 77 /* same as TK_RSHIFT */
-#define OP_ResetCount 53
-#define OP_FifoWrite 54
-#define OP_ContextPush 55
-#define OP_DropTrigger 56
-#define OP_DropIndex 57
-#define OP_IdxGE 58
-#define OP_IdxDelete 59
-#define OP_Vacuum 62
-#define OP_MoveLe 63
-#define OP_IfNot 64
-#define OP_DropTable 73
-#define OP_MakeRecord 84
+#define OP_ResetCount 54
+#define OP_FifoWrite 55
+#define OP_ContextPush 56
+#define OP_DropTrigger 57
+#define OP_DropIndex 58
+#define OP_IdxGE 59
+#define OP_IdxDelete 62
+#define OP_Vacuum 63
+#define OP_MoveLe 64
+#define OP_IfNot 73
+#define OP_DropTable 84
+#define OP_MakeRecord 85
#define OP_ToBlob 139 /* same as TK_TO_BLOB */
-#define OP_ResultRow 85
-#define OP_Delete 86
-#define OP_AggFinal 89
+#define OP_ResultRow 86
+#define OP_Delete 89
+#define OP_AggFinal 90
#define OP_ShiftLeft 76 /* same as TK_LSHIFT */
-#define OP_Goto 90
-#define OP_TableLock 91
-#define OP_FifoRead 92
-#define OP_Clear 93
-#define OP_MoveLt 94
+#define OP_Goto 91
+#define OP_TableLock 92
+#define OP_FifoRead 93
+#define OP_Clear 94
+#define OP_MoveLt 95
#define OP_Le 70 /* same as TK_LE */
-#define OP_VerifyCookie 95
-#define OP_AggStep 96
+#define OP_VerifyCookie 96
+#define OP_AggStep 97
#define OP_ToText 138 /* same as TK_TO_TEXT */
#define OP_Not 16 /* same as TK_NOT */
#define OP_ToReal 142 /* same as TK_TO_REAL */
-#define OP_SetNumColumns 97
-#define OP_Transaction 98
-#define OP_VFilter 99
+#define OP_SetNumColumns 98
+#define OP_Transaction 99
+#define OP_VFilter 100
#define OP_Ne 67 /* same as TK_NE */
-#define OP_VDestroy 100
-#define OP_ContextPop 101
+#define OP_VDestroy 101
+#define OP_ContextPop 102
#define OP_BitOr 75 /* same as TK_BITOR */
-#define OP_Next 102
-#define OP_IdxInsert 103
+#define OP_Next 103
+#define OP_IdxInsert 104
#define OP_Lt 71 /* same as TK_LT */
-#define OP_Insert 104
-#define OP_Destroy 105
-#define OP_ReadCookie 106
-#define OP_ForceInt 107
-#define OP_LoadAnalysis 108
-#define OP_Explain 109
-#define OP_OpenPseudo 110
-#define OP_OpenEphemeral 111
-#define OP_Null 112
-#define OP_Move 113
-#define OP_Blob 114
+#define OP_Insert 105
+#define OP_Destroy 106
+#define OP_ReadCookie 107
+#define OP_ForceInt 108
+#define OP_LoadAnalysis 109
+#define OP_Explain 110
+#define OP_OpenPseudo 111
+#define OP_OpenEphemeral 112
+#define OP_Null 113
+#define OP_Move 114
+#define OP_Blob 115
#define OP_Add 78 /* same as TK_PLUS */
-#define OP_Rewind 115
-#define OP_MoveGe 116
-#define OP_VBegin 117
-#define OP_VUpdate 118
-#define OP_IfZero 119
+#define OP_Rewind 116
+#define OP_MoveGe 117
+#define OP_VBegin 118
+#define OP_VUpdate 119
+#define OP_IfZero 120
#define OP_BitNot 87 /* same as TK_BITNOT */
-#define OP_VCreate 120
-#define OP_Found 121
-#define OP_IfPos 122
-#define OP_NullRow 123
-
-/* The following opcode values are never used */
-#define OP_NotUsed_124 124
+#define OP_VCreate 121
+#define OP_Found 122
+#define OP_IfPos 123
+#define OP_NullRow 124
+
+/* The following opcode values are never used */
#define OP_NotUsed_126 126
#define OP_NotUsed_127 127
#define OP_NotUsed_128 128
#define OP_NotUsed_129 129
@@ -6160,24 +7083,24 @@
#define OPFLG_IN2 0x0008 /* in2: P2 is an input */
#define OPFLG_IN3 0x0010 /* in3: P3 is an input */
#define OPFLG_OUT3 0x0020 /* out3: P3 is an output */
#define OPFLG_INITIALIZER {\
-/* 0 */ 0x00, 0x01, 0x00, 0x10, 0x02, 0x11, 0x02, 0x00,\
-/* 8 */ 0x00, 0x05, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,\
-/* 16 */ 0x04, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,\
-/* 24 */ 0x02, 0x02, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00,\
-/* 32 */ 0x02, 0x11, 0x11, 0x02, 0x05, 0x00, 0x02, 0x11,\
-/* 40 */ 0x04, 0x00, 0x02, 0x0c, 0x11, 0x01, 0x02, 0x01,\
-/* 48 */ 0x00, 0x02, 0x01, 0x01, 0x02, 0x00, 0x04, 0x00,\
-/* 56 */ 0x00, 0x00, 0x11, 0x08, 0x2c, 0x2c, 0x00, 0x11,\
-/* 64 */ 0x05, 0x05, 0x05, 0x15, 0x15, 0x15, 0x15, 0x15,\
-/* 72 */ 0x15, 0x00, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c,\
+/* 0 */ 0x00, 0x01, 0x00, 0x00, 0x10, 0x02, 0x11, 0x00,\
+/* 8 */ 0x00, 0x00, 0x05, 0x02, 0x00, 0x00, 0x00, 0x00,\
+/* 16 */ 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00,\
+/* 24 */ 0x00, 0x02, 0x02, 0x02, 0x04, 0x00, 0x00, 0x00,\
+/* 32 */ 0x00, 0x02, 0x11, 0x11, 0x02, 0x05, 0x00, 0x02,\
+/* 40 */ 0x11, 0x04, 0x00, 0x00, 0x0c, 0x11, 0x01, 0x02,\
+/* 48 */ 0x01, 0x00, 0x02, 0x01, 0x01, 0x02, 0x00, 0x04,\
+/* 56 */ 0x00, 0x00, 0x00, 0x11, 0x2c, 0x2c, 0x00, 0x00,\
+/* 64 */ 0x11, 0x05, 0x05, 0x15, 0x15, 0x15, 0x15, 0x15,\
+/* 72 */ 0x15, 0x05, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c,\
/* 80 */ 0x2c, 0x2c, 0x2c, 0x2c, 0x00, 0x00, 0x00, 0x04,\
-/* 88 */ 0x02, 0x00, 0x01, 0x00, 0x01, 0x00, 0x11, 0x00,\
-/* 96 */ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x08,\
-/* 104 */ 0x00, 0x02, 0x02, 0x05, 0x00, 0x00, 0x00, 0x00,\
-/* 112 */ 0x02, 0x00, 0x02, 0x01, 0x11, 0x00, 0x00, 0x05,\
-/* 120 */ 0x00, 0x11, 0x05, 0x00, 0x00, 0x02, 0x00, 0x00,\
+/* 88 */ 0x02, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x11,\
+/* 96 */ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01,\
+/* 104 */ 0x08, 0x00, 0x02, 0x02, 0x05, 0x00, 0x00, 0x00,\
+/* 112 */ 0x00, 0x02, 0x00, 0x02, 0x01, 0x11, 0x00, 0x00,\
+/* 120 */ 0x05, 0x00, 0x11, 0x05, 0x00, 0x02, 0x00, 0x00,\
/* 128 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
/* 136 */ 0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04,}
/************** End of opcodes.h *********************************************/
@@ -6212,15 +7135,23 @@
#ifdef SQLITE_DEBUG
SQLITE_PRIVATE void sqlite3VdbeTrace(Vdbe*,FILE*);
#endif
SQLITE_PRIVATE void sqlite3VdbeResetStepResult(Vdbe*);
-SQLITE_PRIVATE int sqlite3VdbeReset(Vdbe*);
+SQLITE_PRIVATE int sqlite3VdbeReset(Vdbe*, int);
SQLITE_PRIVATE void sqlite3VdbeSetNumCols(Vdbe*,int);
SQLITE_PRIVATE int sqlite3VdbeSetColName(Vdbe*, int, int, const char *, int);
SQLITE_PRIVATE void sqlite3VdbeCountChanges(Vdbe*);
SQLITE_PRIVATE sqlite3 *sqlite3VdbeDb(Vdbe*);
SQLITE_PRIVATE void sqlite3VdbeSetSql(Vdbe*, const char *z, int n);
SQLITE_PRIVATE void sqlite3VdbeSwap(Vdbe*,Vdbe*);
+
+#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
+SQLITE_PRIVATE int sqlite3VdbeReleaseMemory(int);
+#endif
+SQLITE_PRIVATE UnpackedRecord *sqlite3VdbeRecordUnpack(KeyInfo*,int,const void*,void*,int);
+SQLITE_PRIVATE void sqlite3VdbeDeleteUnpackedRecord(UnpackedRecord*);
+SQLITE_PRIVATE int sqlite3VdbeRecordCompare(int,const void*,UnpackedRecord*);
+
#ifndef NDEBUG
SQLITE_PRIVATE void sqlite3VdbeComment(Vdbe*, const char*, ...);
# define VdbeComment(X) sqlite3VdbeComment X
@@ -6248,9 +7179,9 @@
** 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.
**
-** @(#) $Id: pager.h,v 1.68 2007/11/28 16:19:56 drh Exp $
+** @(#) $Id: pager.h,v 1.72 2008/05/01 17:03:49 drh Exp $
*/
#ifndef _PAGER_H_
#define _PAGER_H_
@@ -6286,8 +7217,16 @@
#define PAGER_LOCKINGMODE_NORMAL 0
#define PAGER_LOCKINGMODE_EXCLUSIVE 1
/*
+** Valid values for the second argument to sqlite3PagerJournalMode().
+*/
+#define PAGER_JOURNALMODE_QUERY -1
+#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. */
+
+/*
** See source code comments for a detailed description of the following
** routines:
*/
SQLITE_PRIVATE int sqlite3PagerOpen(sqlite3_vfs *, Pager **ppPager, const char*, int,int,int);
@@ -6304,13 +7243,12 @@
SQLITE_PRIVATE DbPage *sqlite3PagerLookup(Pager *pPager, Pgno pgno);
SQLITE_PRIVATE int sqlite3PagerRef(DbPage*);
SQLITE_PRIVATE int sqlite3PagerUnref(DbPage*);
SQLITE_PRIVATE int sqlite3PagerWrite(DbPage*);
-SQLITE_PRIVATE int sqlite3PagerOverwrite(Pager *pPager, Pgno pgno, void*);
SQLITE_PRIVATE int sqlite3PagerPagecount(Pager*);
SQLITE_PRIVATE int sqlite3PagerTruncate(Pager*,Pgno);
SQLITE_PRIVATE int sqlite3PagerBegin(DbPage*, int exFlag);
-SQLITE_PRIVATE int sqlite3PagerCommitPhaseOne(Pager*,const char *zMaster, Pgno);
+SQLITE_PRIVATE int sqlite3PagerCommitPhaseOne(Pager*,const char *zMaster, Pgno, int);
SQLITE_PRIVATE int sqlite3PagerCommitPhaseTwo(Pager*);
SQLITE_PRIVATE int sqlite3PagerRollback(Pager*);
SQLITE_PRIVATE int sqlite3PagerIsreadonly(Pager*);
SQLITE_PRIVATE int sqlite3PagerStmtBegin(Pager*);
@@ -6329,9 +7267,11 @@
SQLITE_PRIVATE int sqlite3PagerMovepage(Pager*,DbPage*,Pgno);
SQLITE_PRIVATE void *sqlite3PagerGetData(DbPage *);
SQLITE_PRIVATE void *sqlite3PagerGetExtra(DbPage *);
SQLITE_PRIVATE int sqlite3PagerLockingMode(Pager *, int);
+SQLITE_PRIVATE int sqlite3PagerJournalMode(Pager *, int);
SQLITE_PRIVATE void *sqlite3PagerTempSpace(Pager*);
+SQLITE_PRIVATE int sqlite3PagerSync(Pager *pPager);
#if defined(SQLITE_ENABLE_MEMORY_MANAGEMENT) && !defined(SQLITE_OMIT_DISKIO)
SQLITE_PRIVATE int sqlite3PagerReleaseMemory(int);
#endif
@@ -6347,9 +7287,8 @@
#ifdef SQLITE_TEST
SQLITE_PRIVATE int *sqlite3PagerStats(Pager*);
SQLITE_PRIVATE void sqlite3PagerRefdump(Pager*);
- int pager3_refinfo_enable;
#endif
#ifdef SQLITE_TEST
void disable_simulated_io_errors(void);
@@ -6451,8 +7390,9 @@
# define INCL_DOSPROCESS
# define INCL_DOSMODULEMGR
# define INCL_DOSSEMAPHORES
# include <os2.h>
+# include <uconv.h>
# define SQLITE_TEMPNAME_SIZE (CCHMAXPATHCOMP)
#else
# define SQLITE_TEMPNAME_SIZE 200
#endif
@@ -6633,13 +7573,9 @@
** is used) then there is no default VFS. The application must
** register one or more VFS structures using sqlite3_vfs_register()
** before attempting to use SQLite.
*/
-#if OS_UNIX || OS_WIN || OS_OS2
-SQLITE_PRIVATE sqlite3_vfs *sqlite3OsDefaultVfs(void);
-#else
-# define sqlite3OsDefaultVfs(X) 0
-#endif
+SQLITE_PRIVATE sqlite3_vfs *sqlite3OsDefaultVfs(void);
#endif /* _SQLITE_OS_H_ */
/************** End of os.h **************************************************/
@@ -6731,8 +7667,9 @@
/************** End of mutex.h ***********************************************/
/************** Continuing where we left off in sqliteInt.h ******************/
+
/*
** Each database file to be accessed by the system is an instance
** of the following structure. There are normally two of these structures
** in the sqlite.aDb[] array. aDb[0] is the main database file and
@@ -6798,8 +7735,13 @@
#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) */
+/*
+** The number of different kinds of things that can be limited
+** using the sqlite3_limit() interface.
+*/
+#define SQLITE_N_LIMIT (SQLITE_LIMIT_VARIABLE_NUMBER+1)
/*
** Each database is an instance of the following structure.
**
@@ -6836,9 +7778,12 @@
int errMask; /* & result codes with this before returning */
u8 autoCommit; /* The auto-commit flag. */
u8 temp_store; /* 1: file 2: memory 0: default */
u8 mallocFailed; /* True if we have seen a malloc failure */
+ u8 dfltLockMode; /* Default locking-mode for attached dbs */
+ u8 dfltJournalMode; /* Default journal mode for attached dbs */
signed char nextAutovac; /* Autovac setting after VACUUM if >=0 */
+ int nextPagesize; /* Pagesize after VACUUM if >0 */
int nTable; /* Number of tables in the database */
CollSeq *pDfltColl; /* The default collating sequence (BINARY) */
i64 lastRowid; /* ROWID of most recent insert (see above) */
i64 priorNewRowid; /* Last randomly generated ROWID */
@@ -6845,8 +7790,9 @@
int magic; /* Magic number for detect library misuse */
int nChange; /* Value returned by sqlite3_changes() */
int nTotalChange; /* Value returned by sqlite3_total_changes() */
sqlite3_mutex *mutex; /* Connection mutex */
+ int aLimit[SQLITE_N_LIMIT]; /* Limits */
struct sqlite3InitInfo { /* Information used during initialization */
int iDb; /* When back is being initialized */
int newTnum; /* Rootpage of table being initialized */
u8 busy; /* TRUE if currently initializing */
@@ -6898,9 +7844,8 @@
Db aDbStatic[2]; /* Static space for the 2 default backends */
#ifdef SQLITE_SSE
sqlite3_stmt *pFetch; /* Used by SSE to fetch stored statements */
#endif
- u8 dfltLockMode; /* Default locking-mode for attached dbs */
};
/*
** A macro to discover the encoding of a database.
@@ -7434,17 +8379,19 @@
/*
** The following are the meanings of bits in the Expr.flags field.
*/
-#define EP_FromJoin 0x01 /* Originated in ON or USING clause of a join */
-#define EP_Agg 0x02 /* Contains one or more aggregate functions */
-#define EP_Resolved 0x04 /* IDs have been resolved to COLUMNs */
-#define EP_Error 0x08 /* Expression contains one or more errors */
-#define EP_Distinct 0x10 /* Aggregate function with DISTINCT keyword */
-#define EP_VarSelect 0x20 /* pSelect is correlated, not constant */
-#define EP_Dequoted 0x40 /* True if the string has been dequoted */
-#define EP_InfixFunc 0x80 /* True for an infix function: LIKE, GLOB, etc */
-#define EP_ExpCollate 0x100 /* Collating sequence specified explicitly */
+#define EP_FromJoin 0x0001 /* Originated in ON or USING clause of a join */
+#define EP_Agg 0x0002 /* Contains one or more aggregate functions */
+#define EP_Resolved 0x0004 /* IDs have been resolved to COLUMNs */
+#define EP_Error 0x0008 /* Expression contains one or more errors */
+#define EP_Distinct 0x0010 /* Aggregate function with DISTINCT keyword */
+#define EP_VarSelect 0x0020 /* pSelect is correlated, not constant */
+#define EP_Dequoted 0x0040 /* True if the string has been dequoted */
+#define EP_InfixFunc 0x0080 /* True for an infix function: LIKE, GLOB, etc */
+#define EP_ExpCollate 0x0100 /* Collating sequence specified explicitly */
+#define EP_AnyAff 0x0200 /* Can take a cached column of any affinity */
+#define EP_FixedDest 0x0400 /* Result needed in a specific register */
/*
** These macros can be used to test, set, or clear bits in the
** Expr.flags field.
@@ -7599,11 +8546,15 @@
*/
sqlite3_index_info *pIdxInfo; /* Index info for n-th source table */
};
-#define ORDERBY_NORMAL 0
-#define ORDERBY_MIN 1
-#define ORDERBY_MAX 2
+/*
+** Flags appropriate for the wflags parameter of sqlite3WhereBegin().
+*/
+#define WHERE_ORDERBY_NORMAL 0 /* No-op */
+#define WHERE_ORDERBY_MIN 1 /* ORDER BY processing for min() func */
+#define WHERE_ORDERBY_MAX 2 /* ORDER BY processing for max() func */
+#define WHERE_ONEPASS_DESIRED 4 /* Want to do one-pass UPDATE/DELETE */
/*
** The WHERE clause processing routine has two halves. The
** first part does the start of the WHERE loop and the second
@@ -7611,9 +8562,10 @@
** this structure is returned by the first half and passed
** into the second half to give some continuity.
*/
struct WhereInfo {
- Parse *pParse;
+ Parse *pParse; /* Parsing and code generating context */
+ u8 okOnePass; /* Ok to use one-pass algorithm for UPDATE or DELETE */
SrcList *pTabList; /* List of tables in the join */
int iTop; /* The very beginning of the WHERE loop */
int iContinue; /* Jump here to continue with next record */
int iBreak; /* Jump here to break out of the loop */
@@ -7727,8 +8679,9 @@
u8 eDest; /* How to dispose of the results */
u8 affinity; /* Affinity used when eDest==SRT_Set */
int iParm; /* A parameter used by the eDest disposal method */
int iMem; /* Base register where results are written */
+ int nMem; /* Number of registers allocated */
};
/*
** An SQL parser context. A copy of this structure is passed through
@@ -7765,8 +8718,17 @@
int nTab; /* Number of previously allocated VDBE cursors */
int nMem; /* Number of memory cells used so far */
int nSet; /* Number of sets used so far */
int ckBase; /* Base register of data during check constraints */
+ int disableColCache; /* True to disable adding to column cache */
+ int nColCache; /* Number of entries in the column cache */
+ int iColCache; /* Next entry of the cache to replace */
+ struct yColCache {
+ int iTable; /* Table cursor number */
+ int iColumn; /* Table column number */
+ char affChange; /* True if this register has had an affinity change */
+ int iReg; /* Register holding value of this column */
+ } aColCache[10]; /* One for each valid column cache entry */
u32 writeMask; /* Start a write transaction on these databases */
u32 cookieMask; /* Bitmask of schema verified databases */
int cookieGoto; /* Address of OP_Goto to cookie verifier subroutine */
int cookieValue[SQLITE_MAX_ATTACHED+2]; /* Values of cookies to verify */
@@ -7773,14 +8735,14 @@
#ifndef SQLITE_OMIT_SHARED_CACHE
int nTableLock; /* Number of locks in aTableLock */
TableLock *aTableLock; /* Required table locks for shared-cache mode */
#endif
+ int regRowid; /* Register holding rowid of CREATE TABLE entry */
+ int regRoot; /* Register holding root page number for new objects */
/* Above is constant between recursions. Below is reset before and after
** each recursion */
- int regRowid; /* Register holding rowid of CREATE TABLE entry */
- int regRoot; /* Register holding root page number for new objects */
int nVar; /* Number of '?' variables seen in the SQL so far */
int nVarExpr; /* Number of used slots in apVarExpr[] */
int nVarExprAlloc; /* Number of allocated slots in apVarExpr[] */
Expr **apVarExpr; /* Pointers to :aaa and $aaaa wildcard expressions */
@@ -7796,9 +8758,10 @@
const char *zAuthContext; /* The 6th parameter to db->xAuth callbacks */
#ifndef SQLITE_OMIT_VIRTUALTABLE
Token sArg; /* Complete text of a module argument */
u8 declareVtab; /* True if inside sqlite3_declare_vtab() */
- Table *pVirtualLock; /* Require virtual table lock on this table */
+ int nVtabLock; /* Number of virtual tables to lock */
+ Table **apVtabLock; /* Pointer to virtual tables needing locking */
#endif
#if defined(SQLITE_TEST) || SQLITE_MAX_EXPR_DEPTH>0
int nHeight; /* Expression tree height of current sub-select */
#endif
@@ -7981,8 +8944,9 @@
char *zBase; /* A base allocation. Not from malloc. */
char *zText; /* The string collected so far */
int nChar; /* Length of the string so far */
int nAlloc; /* Amount of space allocated in zText */
+ int mxAlloc; /* Maximum allowed string length */
u8 mallocFailed; /* Becomes true if any memory allocation fails */
u8 useMalloc; /* True if zText is enlargable using realloc */
u8 tooBig; /* Becomes true if string size exceeds limits */
};
@@ -8038,8 +9002,11 @@
SQLITE_PRIVATE char *sqlite3DbStrDup(sqlite3*,const char*);
SQLITE_PRIVATE char *sqlite3DbStrNDup(sqlite3*,const char*, int);
SQLITE_PRIVATE void *sqlite3DbReallocOrFree(sqlite3 *, void *, int);
SQLITE_PRIVATE void *sqlite3DbRealloc(sqlite3 *, void *, int);
+SQLITE_PRIVATE int sqlite3MallocSize(void *);
+
+SQLITE_PRIVATE int sqlite3IsNaN(double);
SQLITE_PRIVATE char *sqlite3MPrintf(sqlite3*,const char*, ...);
SQLITE_PRIVATE char *sqlite3VMPrintf(sqlite3*,const char*, va_list);
#if defined(SQLITE_TEST) || defined(SQLITE_DEBUG)
@@ -8087,8 +9054,15 @@
SQLITE_PRIVATE void sqlite3AddDefaultValue(Parse*,Expr*);
SQLITE_PRIVATE void sqlite3AddCollateType(Parse*, Token*);
SQLITE_PRIVATE void sqlite3EndTable(Parse*,Token*,Token*,Select*);
+SQLITE_PRIVATE Bitvec *sqlite3BitvecCreate(u32);
+SQLITE_PRIVATE int sqlite3BitvecTest(Bitvec*, u32);
+SQLITE_PRIVATE int sqlite3BitvecSet(Bitvec*, u32);
+SQLITE_PRIVATE void sqlite3BitvecClear(Bitvec*, u32);
+SQLITE_PRIVATE void sqlite3BitvecDestroy(Bitvec*);
+SQLITE_PRIVATE int sqlite3BitvecBuiltinTest(int,int*);
+
SQLITE_PRIVATE void sqlite3CreateView(Parse*,Token*,Token*,Token*,Select*,int,int);
#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE)
SQLITE_PRIVATE int sqlite3ViewGetColumnNames(Parse*,Table*);
@@ -8115,21 +9089,27 @@
SQLITE_PRIVATE int sqlite3Select(Parse*, Select*, SelectDest*, Select*, int, int*, char *aff);
SQLITE_PRIVATE Select *sqlite3SelectNew(Parse*,ExprList*,SrcList*,Expr*,ExprList*,
Expr*,ExprList*,int,Expr*,Expr*);
SQLITE_PRIVATE void sqlite3SelectDelete(Select*);
-SQLITE_PRIVATE void sqlite3SelectMask(Parse *, Select *, u32);
SQLITE_PRIVATE Table *sqlite3SrcListLookup(Parse*, SrcList*);
SQLITE_PRIVATE int sqlite3IsReadOnly(Parse*, Table*, int);
SQLITE_PRIVATE void sqlite3OpenTable(Parse*, int iCur, int iDb, Table*, int);
SQLITE_PRIVATE void sqlite3DeleteFrom(Parse*, SrcList*, Expr*);
SQLITE_PRIVATE void sqlite3Update(Parse*, SrcList*, ExprList*, Expr*, int);
SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(Parse*, SrcList*, Expr*, ExprList**, u8);
SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo*);
-SQLITE_PRIVATE void sqlite3ExprCodeGetColumn(Vdbe*, Table*, int, int, int);
+SQLITE_PRIVATE int sqlite3ExprCodeGetColumn(Parse*, Table*, int, int, int, int);
+SQLITE_PRIVATE void sqlite3ExprCodeMove(Parse*, int, int);
+SQLITE_PRIVATE void sqlite3ExprClearColumnCache(Parse*, int);
+SQLITE_PRIVATE void sqlite3ExprCacheAffinityChange(Parse*, int, int);
+SQLITE_PRIVATE int sqlite3ExprWritableRegister(Parse*,int,int);
+SQLITE_PRIVATE void sqlite3ExprHardCopy(Parse*,int,int);
SQLITE_PRIVATE int sqlite3ExprCode(Parse*, Expr*, int);
SQLITE_PRIVATE int sqlite3ExprCodeTemp(Parse*, Expr*, int*);
+SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse*, Expr*, int);
SQLITE_PRIVATE int sqlite3ExprCodeAndCache(Parse*, Expr*, int);
-SQLITE_PRIVATE int sqlite3ExprCodeExprList(Parse*, ExprList*, int);
+SQLITE_PRIVATE void sqlite3ExprCodeConstants(Parse*, Expr*);
+SQLITE_PRIVATE int sqlite3ExprCodeExprList(Parse*, ExprList*, int, int);
SQLITE_PRIVATE void sqlite3ExprIfTrue(Parse*, Expr*, int, int);
SQLITE_PRIVATE void sqlite3ExprIfFalse(Parse*, Expr*, int, int);
SQLITE_PRIVATE Table *sqlite3FindTable(sqlite3*,const char*, const char*);
SQLITE_PRIVATE Table *sqlite3LocateTable(Parse*,int isView,const char*, const char*);
@@ -8144,9 +9124,11 @@
SQLITE_PRIVATE void sqlite3ExprAnalyzeAggregates(NameContext*, Expr*);
SQLITE_PRIVATE void sqlite3ExprAnalyzeAggList(NameContext*,ExprList*);
SQLITE_PRIVATE Vdbe *sqlite3GetVdbe(Parse*);
SQLITE_PRIVATE Expr *sqlite3CreateIdExpr(Parse *, const char*);
-SQLITE_PRIVATE void sqlite3Randomness(int, void*);
+SQLITE_PRIVATE void sqlite3PrngSaveState(void);
+SQLITE_PRIVATE void sqlite3PrngRestoreState(void);
+SQLITE_PRIVATE void sqlite3PrngResetState(void);
SQLITE_PRIVATE void sqlite3RollbackAll(sqlite3*);
SQLITE_PRIVATE void sqlite3CodeVerifySchema(Parse*, int);
SQLITE_PRIVATE void sqlite3BeginTransaction(Parse*, int);
SQLITE_PRIVATE void sqlite3CommitTransaction(Parse*);
@@ -8157,9 +9139,9 @@
SQLITE_PRIVATE int sqlite3ExprIsInteger(Expr*, int*);
SQLITE_PRIVATE int sqlite3IsRowid(const char*);
SQLITE_PRIVATE void sqlite3GenerateRowDelete(Parse*, Table*, int, int, int);
SQLITE_PRIVATE void sqlite3GenerateRowIndexDelete(Parse*, Table*, int, int*);
-SQLITE_PRIVATE int sqlite3GenerateIndexKey(Parse*, Index*, int, int);
+SQLITE_PRIVATE int sqlite3GenerateIndexKey(Parse*, Index*, int, int, int);
SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(Parse*,Table*,int,int,
int*,int,int,int,int);
SQLITE_PRIVATE void sqlite3CompleteInsertion(Parse*, Table*, int, int, int*,int,int,int,int);
SQLITE_PRIVATE int sqlite3OpenTableAndIndices(Parse*, Table*, int, int);
@@ -8182,8 +9164,9 @@
#endif
SQLITE_PRIVATE int sqlite3SafetyCheckOk(sqlite3*);
SQLITE_PRIVATE int sqlite3SafetyCheckSickOrOk(sqlite3*);
SQLITE_PRIVATE void sqlite3ChangeCookie(Parse*, int);
+SQLITE_PRIVATE void sqlite3MaterializeView(Parse*, Select*, Expr*, int);
#ifndef SQLITE_OMIT_TRIGGER
SQLITE_PRIVATE void sqlite3BeginTrigger(Parse*, Token*,Token*,int,int,IdList*,SrcList*,
Expr*,int, int);
@@ -8240,12 +9223,45 @@
SQLITE_PRIVATE int sqlite3FitsIn64Bits(const char *, int);
SQLITE_PRIVATE int sqlite3Utf16ByteLen(const void *pData, int nChar);
SQLITE_PRIVATE int sqlite3Utf8CharLen(const char *pData, int nByte);
SQLITE_PRIVATE int sqlite3Utf8Read(const u8*, const u8*, const u8**);
-SQLITE_PRIVATE int sqlite3PutVarint(unsigned char *, u64);
+
+/*
+** Routines to read and write variable-length integers. These used to
+** be defined locally, but now we use the varint routines in the util.c
+** file. Code should use the MACRO forms below, as the Varint32 versions
+** are coded to assume the single byte case is already handled (which
+** the MACRO form does).
+*/
+SQLITE_PRIVATE int sqlite3PutVarint(unsigned char*, u64);
+SQLITE_PRIVATE int sqlite3PutVarint32(unsigned char*, u32);
SQLITE_PRIVATE int sqlite3GetVarint(const unsigned char *, u64 *);
SQLITE_PRIVATE int sqlite3GetVarint32(const unsigned char *, u32 *);
SQLITE_PRIVATE int sqlite3VarintLen(u64 v);
+
+/*
+** The header of a record consists of a sequence variable-length integers.
+** These integers are almost always small and are encoded as a single byte.
+** The following macros take advantage this fact to provide a fast encode
+** and decode of the integers in a record header. It is faster for the common
+** case where the integer is a single byte. It is a little slower when the
+** integer is two or more bytes. But overall it is faster.
+**
+** The following expressions are equivalent:
+**
+** x = sqlite3GetVarint32( A, &B );
+** x = sqlite3PutVarint32( A, B );
+**
+** x = getVarint32( A, B );
+** x = putVarint32( A, B );
+**
+*/
+#define getVarint32(A,B) ((*(A)<(unsigned char)0x80) ? ((B) = (u32)*(A)),1 : sqlite3GetVarint32((A), &(B)))
+#define putVarint32(A,B) (((B)<(u32)0x80) ? (*(A) = (unsigned char)(B)),1 : sqlite3PutVarint32((A), (B)))
+#define getVarint sqlite3GetVarint
+#define putVarint sqlite3PutVarint
+
+
SQLITE_PRIVATE void sqlite3IndexAffinityStr(Vdbe *, Index *);
SQLITE_PRIVATE void sqlite3TableAffinityStr(Vdbe *, Table *);
SQLITE_PRIVATE char sqlite3CompareAffinity(Expr *pExpr, char aff2);
SQLITE_PRIVATE int sqlite3IndexAffinityOk(Expr *pExpr, char idx_affinity);
@@ -8320,14 +9336,13 @@
SQLITE_PRIVATE void *sqlite3ParserAlloc(void*(*)(size_t));
SQLITE_PRIVATE void sqlite3ParserFree(void*, void(*)(void*));
SQLITE_PRIVATE void sqlite3Parser(void*, int, Token, Parse*);
+SQLITE_PRIVATE int sqlite3AutoLoadExtensions(sqlite3*);
#ifndef SQLITE_OMIT_LOAD_EXTENSION
SQLITE_PRIVATE void sqlite3CloseExtensions(sqlite3*);
-SQLITE_PRIVATE int sqlite3AutoLoadExtensions(sqlite3*);
-#else
-# define sqlite3CloseExtensions(X)
-# define sqlite3AutoLoadExtensions(X) SQLITE_OK
+#else
+# define sqlite3CloseExtensions(X)
#endif
#ifndef SQLITE_OMIT_SHARED_CACHE
SQLITE_PRIVATE void sqlite3TableLock(Parse *, int, int, u8, const char *);
@@ -8349,8 +9364,9 @@
SQLITE_PRIVATE int sqlite3VtabSync(sqlite3 *db, int rc);
SQLITE_PRIVATE int sqlite3VtabRollback(sqlite3 *db);
SQLITE_PRIVATE int sqlite3VtabCommit(sqlite3 *db);
#endif
+SQLITE_PRIVATE void sqlite3VtabMakeWritable(Parse*,Table*);
SQLITE_PRIVATE void sqlite3VtabLock(sqlite3_vtab*);
SQLITE_PRIVATE void sqlite3VtabUnlock(sqlite3*, sqlite3_vtab*);
SQLITE_PRIVATE void sqlite3VtabBeginParse(Parse*, Token*, Token*, Token*);
SQLITE_PRIVATE void sqlite3VtabFinishParse(Parse*, Token*);
@@ -8362,9 +9378,9 @@
SQLITE_PRIVATE int sqlite3VtabBegin(sqlite3 *, sqlite3_vtab *);
SQLITE_PRIVATE FuncDef *sqlite3VtabOverloadFunction(sqlite3 *,FuncDef*, int nArg, Expr*);
SQLITE_PRIVATE void sqlite3InvalidFunction(sqlite3_context*,int,sqlite3_value**);
SQLITE_PRIVATE int sqlite3Reprepare(Vdbe*);
-SQLITE_PRIVATE void sqlite3ExprListCheckLength(Parse*, ExprList*, int, const char*);
+SQLITE_PRIVATE void sqlite3ExprListCheckLength(Parse*, ExprList*, const char*);
SQLITE_PRIVATE CollSeq *sqlite3BinaryCompareCollSeq(Parse *, Expr *, Expr *);
/*
@@ -8377,21 +9393,23 @@
** The interface to the fault injector subsystem. If the fault injector
** mechanism is disabled at compile-time then set up macros so that no
** unnecessary code is generated.
*/
-#ifndef SQLITE_OMIT_FAULTINJECTOR
+#ifndef SQLITE_OMIT_BUILTIN_TEST
SQLITE_PRIVATE void sqlite3FaultConfig(int,int,int);
SQLITE_PRIVATE int sqlite3FaultFailures(int);
SQLITE_PRIVATE int sqlite3FaultBenignFailures(int);
SQLITE_PRIVATE int sqlite3FaultPending(int);
-SQLITE_PRIVATE void sqlite3FaultBenign(int,int);
+SQLITE_PRIVATE void sqlite3FaultBeginBenign(int);
+SQLITE_PRIVATE void sqlite3FaultEndBenign(int);
SQLITE_PRIVATE int sqlite3FaultStep(int);
#else
# define sqlite3FaultConfig(A,B,C)
# define sqlite3FaultFailures(A) 0
# define sqlite3FaultBenignFailures(A) 0
# define sqlite3FaultPending(A) (-1)
-# define sqlite3FaultBenign(A,B)
+# define sqlite3FaultBeginBenign(A)
+# define sqlite3FaultEndBenign(A)
# define sqlite3FaultStep(A) 0
#endif
@@ -8428,19 +9446,19 @@
#endif
/*
** If the SQLITE_ENABLE IOTRACE exists then the global variable
-** sqlite3_io_trace is a pointer to a printf-like routine used to
+** sqlite3IoTrace is a pointer to a printf-like routine used to
** print I/O tracing messages.
*/
#ifdef SQLITE_ENABLE_IOTRACE
-# define IOTRACE(A) if( sqlite3_io_trace ){ sqlite3_io_trace A; }
+# define IOTRACE(A) if( sqlite3IoTrace ){ sqlite3IoTrace A; }
SQLITE_PRIVATE void sqlite3VdbeIOTraceSql(Vdbe*);
+SQLITE_PRIVATE void (*sqlite3IoTrace)(const char*,...);
#else
# define IOTRACE(A)
# define sqlite3VdbeIOTraceSql(X)
#endif
-SQLITE_EXTERN void (*sqlite3_io_trace)(const char*,...);
#endif
/************** End of sqliteInt.h *******************************************/
@@ -8462,9 +9480,9 @@
** There is only one exported symbol in this file - the function
** sqlite3RegisterDateTimeFunctions() found at the bottom of the file.
** All other code has file scope.
**
-** $Id: date.c,v 1.75 2008/01/17 22:27:54 drh Exp $
+** $Id: date.c,v 1.79 2008/03/20 14:03:29 drh Exp $
**
** 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
@@ -8574,32 +9592,42 @@
** The extension is of the form:
**
** (+/-)HH:MM
**
+** Or the "zulu" notation:
+**
+** Z
+**
** If the parse is successful, write the number of minutes
-** of change in *pnMin and return 0. If a parser error occurs,
-** return 0.
+** of change in p->tz and return 0. If a parser error occurs,
+** return non-zero.
**
** A missing specifier is not considered an error.
*/
static int parseTimezone(const char *zDate, DateTime *p){
int sgn = 0;
int nHr, nMn;
+ int c;
while( isspace(*(u8*)zDate) ){ zDate++; }
p->tz = 0;
- if( *zDate=='-' ){
+ c = *zDate;
+ if( c=='-' ){
sgn = -1;
- }else if( *zDate=='+' ){
+ }else if( c=='+' ){
sgn = +1;
- }else{
- return *zDate!=0;
+ }else if( c=='Z' || c=='z' ){
+ zDate++;
+ goto zulu_time;
+ }else{
+ return c!=0;
}
zDate++;
if( getDigits(zDate, 2, 0, 14, ':', &nHr, 2, 0, 59, 0, &nMn)!=2 ){
return 1;
}
zDate += 5;
p->tz = sgn*(nMn + nHr*60);
+zulu_time:
while( isspace(*(u8*)zDate) ){ zDate++; }
return *zDate!=0;
}
@@ -8757,9 +9785,10 @@
}else if( parseHhMmSs(zDate, p)==0 ){
return 0;
}else if( sqlite3StrICmp(zDate,"now")==0){
double r;
- sqlite3OsCurrentTime((sqlite3_vfs *)sqlite3_user_data(context), &r);
+ sqlite3 *db = sqlite3_context_db_handle(context);
+ sqlite3OsCurrentTime(db->pVfs, &r);
p->rJD = r;
p->validJD = 1;
return 0;
}else if( sqlite3IsNumber(zDate, 0, SQLITE_UTF8) ){
@@ -9272,9 +10301,9 @@
}
}
if( n<sizeof(zBuf) ){
z = zBuf;
- }else if( n>SQLITE_MAX_LENGTH ){
+ }else if( n>sqlite3_context_db_handle(context)->aLimit[SQLITE_LIMIT_LENGTH] ){
sqlite3_result_error_toobig(context);
return;
}else{
z = sqlite3_malloc( n );
@@ -9403,20 +10432,15 @@
sqlite3_value **argv
){
time_t t;
char *zFormat = (char *)sqlite3_user_data(context);
+ sqlite3 *db;
+ double rT;
char zBuf[20];
- time(&t);
-#ifdef SQLITE_TEST
- {
- extern int sqlite3_current_time; /* See os_XXX.c */
- if( sqlite3_current_time ){
- t = sqlite3_current_time;
- }
- }
-#endif
-
+ db = sqlite3_context_db_handle(context);
+ sqlite3OsCurrentTime(db->pVfs, &rT);
+ t = 86400.0*(rT - 2440587.5) + 0.5;
#ifdef HAVE_GMTIME_R
{
struct tm sNow;
gmtime_r(&t, &sNow);
@@ -9460,9 +10484,9 @@
int i;
for(i=0; i<sizeof(aFuncs)/sizeof(aFuncs[0]); i++){
sqlite3CreateFunc(db, aFuncs[i].zName, aFuncs[i].nArg,
- SQLITE_UTF8, (void *)(db->pVfs), aFuncs[i].xFunc, 0, 0);
+ SQLITE_UTF8, 0, aFuncs[i].xFunc, 0, 0);
}
#else
static const struct {
char *zName;
@@ -9482,9 +10506,9 @@
}
/************** End of date.c ************************************************/
/************** Begin file os.c **********************************************/
- /*
+/*
** 2005 November 29
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
@@ -9517,9 +10541,9 @@
** sqlite3OsSync()
** sqlite3OsLock()
**
*/
-#ifdef SQLITE_TEST
+#if defined(SQLITE_TEST) && (OS_WIN==0)
#define DO_OS_MALLOC_TEST if (1) { \
void *pTstAlloc = sqlite3_malloc(10); \
if (!pTstAlloc) return SQLITE_IOERR_NOMEM; \
sqlite3_free(pTstAlloc); \
@@ -9598,9 +10622,16 @@
SQLITE_PRIVATE int sqlite3OsDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
return pVfs->xDelete(pVfs, zPath, dirSync);
}
SQLITE_PRIVATE int sqlite3OsAccess(sqlite3_vfs *pVfs, const char *zPath, int flags){
- return pVfs->xAccess(pVfs, zPath, flags);
+ int rc;
+#ifdef SQLITE_TEST
+ void *pTstAlloc = sqlite3_malloc(10);
+ if (!pTstAlloc) return -1;
+ sqlite3_free(pTstAlloc);
+#endif
+ rc = pVfs->xAccess(pVfs, zPath, flags);
+ return rc;
}
SQLITE_PRIVATE int sqlite3OsGetTempname(sqlite3_vfs *pVfs, int nBufOut, char *zBufOut){
return pVfs->xGetTempname(pVfs, nBufOut, zBufOut);
}
@@ -9655,12 +10686,11 @@
return rc;
}
SQLITE_PRIVATE int sqlite3OsCloseFree(sqlite3_file *pFile){
int rc = SQLITE_OK;
- if( pFile ){
- rc = sqlite3OsClose(pFile);
- sqlite3_free(pFile);
- }
+ assert( pFile );
+ rc = sqlite3OsClose(pFile);
+ sqlite3_free(pFile);
return rc;
}
/*
@@ -9749,8 +10779,16 @@
sqlite3_mutex_leave(mutex);
return SQLITE_OK;
}
+/*
+** Provide a default sqlite3OsDefaultVfs() implementation in the
+** cases where none of the standard backends are used.
+*/
+#if !OS_UNIX && !OS_WIN && !OS_OS2
+SQLITE_PRIVATE sqlite3_vfs *sqlite3OsDefaultVfs(void){ return 0; }
+#endif
+
/************** End of os.c **************************************************/
/************** Begin file fault.c *******************************************/
/*
** 2008 Jan 22
@@ -9772,17 +10810,17 @@
** Fault injectors can be used, for example, to simulate memory
** allocation failures or I/O errors.
**
** The fault injector is omitted from the code if SQLite is
-** compiled with -DSQLITE_OMIT_FAULTINJECTOR=1. There is a very
+** compiled with -DSQLITE_OMIT_BUILTIN_TEST=1. There is a very
** small performance hit for leaving the fault injector in the code.
** Commerical products will probably want to omit the fault injector
** from production builds. But safety-critical systems who work
** under the motto "fly what you test and test what you fly" may
** choose to leave the fault injector enabled even in production.
*/
-#ifndef SQLITE_OMIT_FAULTINJECTOR
+#ifndef SQLITE_OMIT_BUILTIN_TEST
/*
** There can be various kinds of faults. For example, there can be
** a memory allocation failure. Or an I/O failure. For each different
@@ -9794,9 +10832,9 @@
int nRepeat; /* Number of times to repeat the failure */
int nBenign; /* Number of benign failures seen since last config */
int nFail; /* Number of failures seen since last config */
u8 enable; /* True if enabled */
- u8 benign; /* Ture if next failure will be benign */
+ i16 benign; /* Positive if next failure will be benign */
} aFault[SQLITE_FAULTINJECTOR_COUNT];
/*
** This routine configures and enables a fault injector. After
@@ -9856,11 +10894,29 @@
** 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.
*/
-SQLITE_PRIVATE void sqlite3FaultBenign(int id, int enable){
- assert( id>=0 && id<SQLITE_FAULTINJECTOR_COUNT );
- aFault[id].benign = enable;
+SQLITE_PRIVATE void sqlite3FaultBeginBenign(int id){
+ if( id<0 ){
+ for(id=0; id<SQLITE_FAULTINJECTOR_COUNT; id++){
+ aFault[id].benign++;
+ }
+ }else{
+ assert( id>=0 && id<SQLITE_FAULTINJECTOR_COUNT );
+ aFault[id].benign++;
+ }
+}
+SQLITE_PRIVATE void sqlite3FaultEndBenign(int id){
+ if( id<0 ){
+ for(id=0; id<SQLITE_FAULTINJECTOR_COUNT; id++){
+ assert( aFault[id].benign>0 );
+ aFault[id].benign--;
+ }
+ }else{
+ assert( id>=0 && id<SQLITE_FAULTINJECTOR_COUNT );
+ assert( aFault[id].benign>0 );
+ aFault[id].benign--;
+ }
}
/*
** This routine exists as a place to set a breakpoint that will
@@ -9886,9 +10942,9 @@
return 0;
}
sqlite3Fault();
aFault[id].nFail++;
- if( aFault[id].benign ){
+ if( aFault[id].benign>0 ){
aFault[id].nBenign++;
}
aFault[id].nRepeat--;
if( aFault[id].nRepeat<=0 ){
@@ -9896,9 +10952,9 @@
}
return 1;
}
-#endif /* SQLITE_OMIT_FAULTINJECTOR */
+#endif /* SQLITE_OMIT_BUILTIN_TEST */
/************** End of fault.c ***********************************************/
/************** Begin file mem1.c ********************************************/
/*
@@ -9914,32 +10970,17 @@
*************************************************************************
** This file contains the C functions that implement a memory
** allocation subsystem for use by SQLite.
**
-** $Id: mem1.c,v 1.14 2007/11/29 18:36:49 drh Exp $
+** $Id: mem1.c,v 1.17 2008/03/18 00:07:11 drh Exp $
*/
/*
** This version of the memory allocator is the default. It is
** used when no other memory allocator is specified using compile-time
** macros.
*/
-#if !defined(SQLITE_MEMDEBUG) && !defined(SQLITE_MEMORY_SIZE) \
- && !defined(SQLITE_MMAP_HEAP_SIZE)
-
-/*
-** We will eventually construct multiple memory allocation subsystems
-** suitable for use in various contexts:
-**
-** * Normal multi-threaded builds
-** * Normal single-threaded builds
-** * Debugging builds
-**
-** This initial version is suitable for use in normal multi-threaded
-** builds. We envision that alternative versions will be stored in
-** separate source files. #ifdefs will be used to select the code from
-** one of the various memN.c source files for use in any given build.
-*/
+#ifdef SQLITE_SYSTEM_MALLOC
/*
** All of the static variables used by this module are collected
** into a single structure named "mem". This is to keep the
@@ -10053,12 +11094,16 @@
enterMem();
if( mem.alarmCallback!=0 && mem.nowUsed+nBytes>=mem.alarmThreshold ){
sqlite3MemsysAlarm(nBytes);
}
- p = malloc(nBytes+8);
- if( p==0 ){
- sqlite3MemsysAlarm(nBytes);
+ if( sqlite3FaultStep(SQLITE_FAULTINJECTOR_MALLOC) ){
+ p = 0;
+ }else{
p = malloc(nBytes+8);
+ if( p==0 ){
+ sqlite3MemsysAlarm(nBytes);
+ p = malloc(nBytes+8);
+ }
}
if( p ){
p[0] = nBytes;
p++;
@@ -10091,8 +11136,18 @@
sqlite3_mutex_leave(mem.mutex);
}
/*
+** Return the number of bytes allocated at p.
+*/
+SQLITE_PRIVATE int sqlite3MallocSize(void *p){
+ sqlite3_int64 *pInt;
+ if( !p ) return 0;
+ pInt = p;
+ return pInt[-1];
+}
+
+/*
** Change the size of an existing memory allocation
*/
SQLITE_API void *sqlite3_realloc(void *pPrior, int nBytes){
int nOld;
@@ -10111,14 +11166,18 @@
sqlite3_mutex_enter(mem.mutex);
if( mem.nowUsed+nBytes-nOld>=mem.alarmThreshold ){
sqlite3MemsysAlarm(nBytes-nOld);
}
- p = realloc(p, nBytes+8);
- if( p==0 ){
- sqlite3MemsysAlarm(nBytes);
- p = pPrior;
- p--;
+ if( sqlite3FaultStep(SQLITE_FAULTINJECTOR_MALLOC) ){
+ p = 0;
+ }else{
p = realloc(p, nBytes+8);
+ if( p==0 ){
+ sqlite3MemsysAlarm(nBytes);
+ p = pPrior;
+ p--;
+ p = realloc(p, nBytes+8);
+ }
}
if( p ){
p[0] = nBytes;
p++;
@@ -10130,9 +11189,9 @@
sqlite3_mutex_leave(mem.mutex);
return (void*)p;
}
-#endif /* !SQLITE_MEMDEBUG && !SQLITE_OMIT_MEMORY_ALLOCATION */
+#endif /* SQLITE_SYSTEM_MALLOC */
/************** End of mem1.c ************************************************/
/************** Begin file mem2.c ********************************************/
/*
@@ -10148,38 +11207,16 @@
*************************************************************************
** This file contains the C functions that implement a memory
** allocation subsystem for use by SQLite.
**
-** $Id: mem2.c,v 1.19 2008/01/22 21:30:53 drh Exp $
+** $Id: mem2.c,v 1.26 2008/04/10 14:57:25 drh Exp $
*/
/*
** This version of the memory allocator is used only if the
-** SQLITE_MEMDEBUG macro is defined and SQLITE_OMIT_MEMORY_ALLOCATION
-** is not defined.
-*/
-#if defined(SQLITE_MEMDEBUG)
-
-/*
-** We will eventually construct multiple memory allocation subsystems
-** suitable for use in various contexts:
-**
-** * Normal multi-threaded builds
-** * Normal single-threaded builds
-** * Debugging builds
-**
-** This version is suitable for use in debugging builds.
-**
-** Features:
-**
-** * Every allocate has guards at both ends.
-** * New allocations are initialized with randomness
-** * Allocations are overwritten with randomness when freed
-** * Optional logs of malloc activity generated
-** * Summary of outstanding allocations with backtraces to the
-** point of allocation.
-** * The ability to simulate memory allocation failure
-*/
+** SQLITE_MEMDEBUG macro is defined
+*/
+#ifdef SQLITE_MEMDEBUG
/*
** The backtrace functionality is only available with GLIBC
*/
@@ -10204,10 +11241,10 @@
** backtrace pointers. There is also a guard word at the end of the
** MemBlockHdr.
*/
struct MemBlockHdr {
- struct MemBlockHdr *pNext, *pPrev; /* Linked list of all unfreed memory */
- int iSize; /* Size of this allocation */
+ i64 iSize; /* Size of this allocation */
+ struct MemBlockHdr *pNext, *pPrev; /* Linked list of all unfreed memory */
char nBacktrace; /* Number of backtraces on this alloc */
char nBacktraceSlots; /* Available backtrace slots */
short nTitle; /* Bytes of title; includes '\0' */
int iForeGuard; /* Guard word for sanity */
@@ -10263,8 +11300,9 @@
/*
** The number of levels of backtrace to save in new allocations.
*/
int nBacktrace;
+ void (*xBacktrace)(int, int, void **);
/*
** Title text to insert in front of each block
*/
@@ -10367,16 +11405,34 @@
*/
static struct MemBlockHdr *sqlite3MemsysGetHeader(void *pAllocation){
struct MemBlockHdr *p;
int *pInt;
+ u8 *pU8;
+ int nReserve;
p = (struct MemBlockHdr*)pAllocation;
p--;
assert( p->iForeGuard==FOREGUARD );
- assert( (p->iSize & 3)==0 );
+ nReserve = (p->iSize+7)&~7;
pInt = (int*)pAllocation;
- assert( pInt[p->iSize/sizeof(int)]==REARGUARD );
- return p;
+ pU8 = (u8*)pAllocation;
+ assert( pInt[nReserve/sizeof(int)]==REARGUARD );
+ assert( (nReserve-0)<=p->iSize || pU8[nReserve-1]==0x65 );
+ assert( (nReserve-1)<=p->iSize || pU8[nReserve-2]==0x65 );
+ assert( (nReserve-2)<=p->iSize || pU8[nReserve-3]==0x65 );
+ return p;
+}
+
+/*
+** Return the number of bytes currently allocated at address p.
+*/
+SQLITE_PRIVATE int sqlite3MallocSize(void *p){
+ struct MemBlockHdr *pHdr;
+ if( !p ){
+ return 0;
+ }
+ pHdr = sqlite3MemsysGetHeader(p);
+ return pHdr->iSize;
}
/*
** Allocate nByte bytes of memory.
@@ -10389,20 +11445,21 @@
void *p = 0;
int totalSize;
if( nByte>0 ){
+ int nReserve;
enterMem();
assert( mem.disallow==0 );
if( mem.alarmCallback!=0 && mem.nowUsed+nByte>=mem.alarmThreshold ){
sqlite3MemsysAlarm(nByte);
}
- nByte = (nByte+3)&~3;
- if( nByte/8>NCSIZE-1 ){
+ nReserve = (nByte+7)&~7;
+ if( nReserve/8>NCSIZE-1 ){
mem.sizeCnt[NCSIZE-1]++;
}else{
- mem.sizeCnt[nByte/8]++;
- }
- totalSize = nByte + sizeof(*pHdr) + sizeof(int) +
+ mem.sizeCnt[nReserve/8]++;
+ }
+ totalSize = nReserve + sizeof(*pHdr) + sizeof(int) +
mem.nBacktrace*sizeof(void*) + mem.nTitle;
if( sqlite3FaultStep(SQLITE_FAULTINJECTOR_MALLOC) ){
p = 0;
}else{
@@ -10430,8 +11487,11 @@
if( mem.nBacktrace ){
void *aAddr[40];
pHdr->nBacktrace = backtrace(aAddr, mem.nBacktrace+1)-1;
memcpy(pBt, &aAddr[1], pHdr->nBacktrace*sizeof(void*));
+ if( mem.xBacktrace ){
+ mem.xBacktrace(nByte, pHdr->nBacktrace-1, &aAddr[1]);
+ }
}else{
pHdr->nBacktrace = 0;
}
if( mem.nTitle ){
@@ -10438,10 +11498,10 @@
memcpy(z, mem.zTitle, mem.nTitle);
}
pHdr->iSize = nByte;
pInt = (int*)&pHdr[1];
- pInt[nByte/sizeof(int)] = REARGUARD;
- memset(pInt, 0x65, nByte);
+ pInt[nReserve/sizeof(int)] = REARGUARD;
+ memset(pInt, 0x65, nReserve);
mem.nowUsed += nByte;
if( mem.nowUsed>mem.mxUsed ){
mem.mxUsed = mem.nowUsed;
}
@@ -10526,33 +11586,46 @@
** Set the number of backtrace levels kept for each allocation.
** A value of zero turns of backtracing. The number is always rounded
** up to a multiple of 2.
*/
-SQLITE_API void sqlite3_memdebug_backtrace(int depth){
+SQLITE_PRIVATE void sqlite3MemdebugBacktrace(int depth){
if( depth<0 ){ depth = 0; }
if( depth>20 ){ depth = 20; }
depth = (depth+1)&0xfe;
mem.nBacktrace = depth;
}
+SQLITE_PRIVATE void sqlite3MemdebugBacktraceCallback(void (*xBacktrace)(int, int, void **)){
+ mem.xBacktrace = xBacktrace;
+}
+
/*
** Set the title string for subsequent allocations.
*/
-SQLITE_API void sqlite3_memdebug_settitle(const char *zTitle){
+SQLITE_PRIVATE void sqlite3MemdebugSettitle(const char *zTitle){
int n = strlen(zTitle) + 1;
enterMem();
if( n>=sizeof(mem.zTitle) ) n = sizeof(mem.zTitle)-1;
memcpy(mem.zTitle, zTitle, n);
mem.zTitle[n] = 0;
- mem.nTitle = (n+3)&~3;
+ mem.nTitle = (n+7)&~7;
sqlite3_mutex_leave(mem.mutex);
+}
+
+SQLITE_PRIVATE void sqlite3MemdebugSync(){
+ struct MemBlockHdr *pHdr;
+ for(pHdr=mem.pFirst; pHdr; pHdr=pHdr->pNext){
+ void **pBt = (void**)pHdr;
+ pBt -= pHdr->nBacktraceSlots;
+ mem.xBacktrace(pHdr->iSize, pHdr->nBacktrace-1, &pBt[1]);
+ }
}
/*
** Open the file indicated and write a log of all unfreed memory
** allocations into that log.
*/
-SQLITE_API void sqlite3_memdebug_dump(const char *zFilename){
+SQLITE_PRIVATE void sqlite3MemdebugDump(const char *zFilename){
FILE *out;
struct MemBlockHdr *pHdr;
void **pBt;
int i;
@@ -10564,9 +11637,9 @@
}
for(pHdr=mem.pFirst; pHdr; pHdr=pHdr->pNext){
char *z = (char*)pHdr;
z -= pHdr->nBacktraceSlots*sizeof(void*) + pHdr->nTitle;
- fprintf(out, "**** %d 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);
pBt = (void**)pHdr;
@@ -10586,10 +11659,22 @@
}
fclose(out);
}
-
-#endif /* SQLITE_MEMDEBUG && !SQLITE_OMIT_MEMORY_ALLOCATION */
+/*
+** Return the number of times sqlite3_malloc() has been called.
+*/
+SQLITE_PRIVATE int sqlite3MemdebugMallocCount(){
+ int i;
+ int nTotal = 0;
+ for(i=0; i<NCSIZE; i++){
+ nTotal += mem.sizeCnt[i];
+ }
+ return nTotal;
+}
+
+
+#endif /* SQLITE_MEMDEBUG */
/************** End of mem2.c ************************************************/
/************** Begin file mem3.c ********************************************/
/*
@@ -10613,20 +11698,16 @@
**
** This version of the memory allocation subsystem is used if
** and only if SQLITE_MEMORY_SIZE is defined.
**
-** $Id: mem3.c,v 1.8 2007/12/29 13:18:22 drh Exp $
+** $Id: mem3.c,v 1.12 2008/02/19 15:15:16 drh Exp $
*/
/*
** This version of the memory allocator is used only when
** SQLITE_MEMORY_SIZE is defined.
*/
-#if defined(SQLITE_MEMORY_SIZE)
-
-#ifdef SQLITE_MEMDEBUG
-# error cannot define both SQLITE_MEMDEBUG and SQLITE_MEMORY_SIZE
-#endif
+#ifdef SQLITE_MEMORY_SIZE
/*
** Maximum size (in Mem3Blocks) of a "small" chunk.
*/
@@ -10883,12 +11964,16 @@
** Return the size of an outstanding allocation, in bytes. The
** size returned omits the 8-byte header overhead. This only
** works for chunks that are currently checked out.
*/
-static int memsys3Size(void *p){
- Mem3Block *pBlock = (Mem3Block*)p;
- assert( (pBlock[-1].u.hdr.size4x&1)!=0 );
- return (pBlock[-1].u.hdr.size4x&~3)*2 - 4;
+SQLITE_PRIVATE int sqlite3MallocSize(void *p){
+ int iSize = 0;
+ if( p ){
+ Mem3Block *pBlock = (Mem3Block*)p;
+ assert( (pBlock[-1].u.hdr.size4x&1)!=0 );
+ iSize = (pBlock[-1].u.hdr.size4x&~3)*2 - 4;
+ }
+ return iSize;
}
/*
** Chunk i is a free chunk that has been unlinked. Adjust its
@@ -11148,9 +12233,9 @@
sqlite3_free(pPrior);
return 0;
}
assert( mem.mutex!=0 );
- nOld = memsys3Size(pPrior);
+ nOld = sqlite3MallocSize(pPrior);
if( nBytes<=nOld && nBytes>=nOld-128 ){
return pPrior;
}
sqlite3_mutex_enter(mem.mutex);
@@ -11170,9 +12255,9 @@
/*
** Open the file indicated and write a log of all unfreed memory
** allocations into that log.
*/
-SQLITE_API void sqlite3_memdebug_dump(const char *zFilename){
+SQLITE_PRIVATE void sqlite3MemdebugDump(const char *zFilename){
#ifdef SQLITE_DEBUG
FILE *out;
int i, j;
u32 size;
@@ -11245,8 +12330,521 @@
#endif /* !SQLITE_MEMORY_SIZE */
/************** End of mem3.c ************************************************/
+/************** Begin file mem5.c ********************************************/
+/*
+** 2007 October 14
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+** This file contains the C functions that implement a memory
+** allocation subsystem for use by SQLite.
+**
+** This version of the memory allocation subsystem omits all
+** use of malloc(). All dynamically allocatable memory is
+** contained in a static array, mem.aPool[]. The size of this
+** fixed memory pool is SQLITE_POW2_MEMORY_SIZE bytes.
+**
+** This version of the memory allocation subsystem is used if
+** and only if SQLITE_POW2_MEMORY_SIZE is defined.
+**
+** $Id: mem5.c,v 1.4 2008/02/19 15:15:16 drh Exp $
+*/
+
+/*
+** This version of the memory allocator is used only when
+** SQLITE_POW2_MEMORY_SIZE is defined.
+*/
+#ifdef SQLITE_POW2_MEMORY_SIZE
+
+/*
+** Log2 of the minimum size of an allocation. For example, if
+** 4 then all allocations will be rounded up to at least 16 bytes.
+** If 5 then all allocations will be rounded up to at least 32 bytes.
+*/
+#ifndef SQLITE_POW2_LOGMIN
+# define SQLITE_POW2_LOGMIN 6
+#endif
+#define POW2_MIN (1<<SQLITE_POW2_LOGMIN)
+
+/*
+** Log2 of the maximum size of an allocation.
+*/
+#ifndef SQLITE_POW2_LOGMAX
+# define SQLITE_POW2_LOGMAX 18
+#endif
+#define POW2_MAX (((unsigned int)1)<<SQLITE_POW2_LOGMAX)
+
+/*
+** Number of distinct allocation sizes.
+*/
+#define NSIZE (SQLITE_POW2_LOGMAX - SQLITE_POW2_LOGMIN + 1)
+
+/*
+** A minimum allocation is an instance of the following structure.
+** Larger allocations are an array of these structures where the
+** size of the array is a power of 2.
+*/
+typedef struct Mem5Block Mem5Block;
+struct Mem5Block {
+ union {
+ char aData[POW2_MIN];
+ struct {
+ int next; /* Index in mem.aPool[] of next free chunk */
+ int prev; /* Index in mem.aPool[] of previous free chunk */
+ } list;
+ } u;
+};
+
+/*
+** Number of blocks of memory available for allocation.
+*/
+#define NBLOCK (SQLITE_POW2_MEMORY_SIZE/POW2_MIN)
+
+/*
+** The size in blocks of an POW2_MAX allocation
+*/
+#define SZ_MAX (1<<(NSIZE-1))
+
+/*
+** Masks used for mem.aCtrl[] elements.
+*/
+#define CTRL_LOGSIZE 0x1f /* Log2 Size of this block relative to POW2_MIN */
+#define CTRL_FREE 0x20 /* True if not checked out */
+
+/*
+** All of the static variables used by this module are collected
+** into a single structure named "mem". This is to keep the
+** static variables organized and to reduce namespace pollution
+** when this module is combined with other in the amalgamation.
+*/
+static struct {
+ /*
+ ** The alarm callback and its arguments. The mem.mutex lock will
+ ** be held while the callback is running. Recursive calls into
+ ** the memory subsystem are allowed, but no new callbacks will be
+ ** issued. The alarmBusy variable is set to prevent recursive
+ ** callbacks.
+ */
+ sqlite3_int64 alarmThreshold;
+ void (*alarmCallback)(void*, sqlite3_int64,int);
+ void *alarmArg;
+ int alarmBusy;
+
+ /*
+ ** Mutex to control access to the memory allocation subsystem.
+ */
+ sqlite3_mutex *mutex;
+
+ /*
+ ** Performance statistics
+ */
+ u64 nAlloc; /* Total number of calls to malloc */
+ u64 totalAlloc; /* Total of all malloc calls - includes internal frag */
+ u64 totalExcess; /* Total internal fragmentation */
+ u32 currentOut; /* Current checkout, including internal fragmentation */
+ u32 currentCount; /* Current number of distinct checkouts */
+ u32 maxOut; /* Maximum instantaneous currentOut */
+ u32 maxCount; /* Maximum instantaneous currentCount */
+ u32 maxRequest; /* Largest allocation (exclusive of internal frag) */
+
+ /*
+ ** Lists of free blocks of various sizes.
+ */
+ int aiFreelist[NSIZE];
+
+ /*
+ ** Space for tracking which blocks are checked out and the size
+ ** of each block. One byte per block.
+ */
+ u8 aCtrl[NBLOCK];
+
+ /*
+ ** Memory available for allocation
+ */
+ Mem5Block aPool[NBLOCK];
+} mem;
+
+/*
+** Unlink the chunk at mem.aPool[i] from list it is currently
+** on. It should be found on mem.aiFreelist[iLogsize].
+*/
+static void memsys5Unlink(int i, int iLogsize){
+ int next, prev;
+ assert( i>=0 && i<NBLOCK );
+ assert( iLogsize>=0 && iLogsize<NSIZE );
+ assert( (mem.aCtrl[i] & CTRL_LOGSIZE)==iLogsize );
+ assert( sqlite3_mutex_held(mem.mutex) );
+
+ next = mem.aPool[i].u.list.next;
+ prev = mem.aPool[i].u.list.prev;
+ if( prev<0 ){
+ mem.aiFreelist[iLogsize] = next;
+ }else{
+ mem.aPool[prev].u.list.next = next;
+ }
+ if( next>=0 ){
+ mem.aPool[next].u.list.prev = prev;
+ }
+}
+
+/*
+** Link the chunk at mem.aPool[i] so that is on the iLogsize
+** free list.
+*/
+static void memsys5Link(int i, int iLogsize){
+ int x;
+ assert( sqlite3_mutex_held(mem.mutex) );
+ assert( i>=0 && i<NBLOCK );
+ assert( iLogsize>=0 && iLogsize<NSIZE );
+ assert( (mem.aCtrl[i] & CTRL_LOGSIZE)==iLogsize );
+
+ mem.aPool[i].u.list.next = x = mem.aiFreelist[iLogsize];
+ mem.aPool[i].u.list.prev = -1;
+ if( x>=0 ){
+ assert( x<NBLOCK );
+ mem.aPool[x].u.list.prev = i;
+ }
+ mem.aiFreelist[iLogsize] = i;
+}
+
+/*
+** Enter the mutex mem.mutex. Allocate it if it is not already allocated.
+**
+** Also: Initialize the memory allocation subsystem the first time
+** this routine is called.
+*/
+static void memsys5Enter(void){
+ if( mem.mutex==0 ){
+ int i;
+ assert( sizeof(Mem5Block)==POW2_MIN );
+ assert( (SQLITE_POW2_MEMORY_SIZE % POW2_MAX)==0 );
+ assert( SQLITE_POW2_MEMORY_SIZE>=POW2_MAX );
+ mem.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MEM);
+ sqlite3_mutex_enter(mem.mutex);
+ for(i=0; i<NSIZE; i++) mem.aiFreelist[i] = -1;
+ for(i=0; i<=NBLOCK-SZ_MAX; i += SZ_MAX){
+ mem.aCtrl[i] = (NSIZE-1) | CTRL_FREE;
+ memsys5Link(i, NSIZE-1);
+ }
+ }else{
+ sqlite3_mutex_enter(mem.mutex);
+ }
+}
+
+/*
+** Return the amount of memory currently checked out.
+*/
+SQLITE_API sqlite3_int64 sqlite3_memory_used(void){
+ return mem.currentOut;
+}
+
+/*
+** Return the maximum amount of memory that has ever been
+** checked out since either the beginning of this process
+** or since the most recent reset.
+*/
+SQLITE_API sqlite3_int64 sqlite3_memory_highwater(int resetFlag){
+ sqlite3_int64 n;
+ memsys5Enter();
+ n = mem.maxOut;
+ if( resetFlag ){
+ mem.maxOut = mem.currentOut;
+ }
+ sqlite3_mutex_leave(mem.mutex);
+ return n;
+}
+
+
+/*
+** Trigger the alarm
+*/
+static void memsys5Alarm(int nByte){
+ void (*xCallback)(void*,sqlite3_int64,int);
+ sqlite3_int64 nowUsed;
+ void *pArg;
+ if( mem.alarmCallback==0 || mem.alarmBusy ) return;
+ mem.alarmBusy = 1;
+ xCallback = mem.alarmCallback;
+ nowUsed = mem.currentOut;
+ pArg = mem.alarmArg;
+ sqlite3_mutex_leave(mem.mutex);
+ xCallback(pArg, nowUsed, nByte);
+ sqlite3_mutex_enter(mem.mutex);
+ mem.alarmBusy = 0;
+}
+
+/*
+** Change the alarm callback.
+**
+** This is a no-op for the static memory allocator. The purpose
+** of the memory alarm is to support sqlite3_soft_heap_limit().
+** But with this memory allocator, the soft_heap_limit is really
+** a hard limit that is fixed at SQLITE_POW2_MEMORY_SIZE.
+*/
+SQLITE_API int sqlite3_memory_alarm(
+ void(*xCallback)(void *pArg, sqlite3_int64 used,int N),
+ void *pArg,
+ sqlite3_int64 iThreshold
+){
+ memsys5Enter();
+ mem.alarmCallback = xCallback;
+ mem.alarmArg = pArg;
+ mem.alarmThreshold = iThreshold;
+ sqlite3_mutex_leave(mem.mutex);
+ return SQLITE_OK;
+}
+
+/*
+** Return the size of an outstanding allocation, in bytes. The
+** size returned omits the 8-byte header overhead. This only
+** works for chunks that are currently checked out.
+*/
+SQLITE_PRIVATE int sqlite3MallocSize(void *p){
+ int iSize = 0;
+ if( p ){
+ int i = ((Mem5Block*)p) - mem.aPool;
+ assert( i>=0 && i<NBLOCK );
+ iSize = 1 << ((mem.aCtrl[i]&CTRL_LOGSIZE) + SQLITE_POW2_LOGMIN);
+ }
+ return iSize;
+}
+
+/*
+** Find the first entry on the freelist iLogsize. Unlink that
+** entry and return its index.
+*/
+static int memsys5UnlinkFirst(int iLogsize){
+ int i;
+ int iFirst;
+
+ assert( iLogsize>=0 && iLogsize<NSIZE );
+ i = iFirst = mem.aiFreelist[iLogsize];
+ assert( iFirst>=0 );
+ while( i>0 ){
+ if( i<iFirst ) iFirst = i;
+ i = mem.aPool[i].u.list.next;
+ }
+ memsys5Unlink(iFirst, iLogsize);
+ return iFirst;
+}
+
+/*
+** Return a block of memory of at least nBytes in size.
+** Return NULL if unable.
+*/
+static void *memsys5Malloc(int nByte){
+ int i; /* Index of a mem.aPool[] slot */
+ int iBin; /* Index into mem.aiFreelist[] */
+ int iFullSz; /* Size of allocation rounded up to power of 2 */
+ int iLogsize; /* Log2 of iFullSz/POW2_MIN */
+
+ assert( sqlite3_mutex_held(mem.mutex) );
+
+ /* Keep track of the maximum allocation request. Even unfulfilled
+ ** requests are counted */
+ if( nByte>mem.maxRequest ){
+ mem.maxRequest = nByte;
+ }
+
+ /* Simulate a memory allocation fault */
+ if( sqlite3FaultStep(SQLITE_FAULTINJECTOR_MALLOC) ) return 0;
+
+ /* Round nByte up to the next valid power of two */
+ if( nByte>POW2_MAX ) return 0;
+ for(iFullSz=POW2_MIN, iLogsize=0; iFullSz<nByte; iFullSz *= 2, iLogsize++){}
+
+ /* If we will be over the memory alarm threshold after this allocation,
+ ** then trigger the memory overflow alarm */
+ if( mem.alarmCallback!=0 && mem.currentOut+iFullSz>=mem.alarmThreshold ){
+ memsys5Alarm(iFullSz);
+ }
+
+ /* Make sure mem.aiFreelist[iLogsize] contains at least one free
+ ** block. If not, then split a block of the next larger power of
+ ** two in order to create a new free block of size iLogsize.
+ */
+ for(iBin=iLogsize; mem.aiFreelist[iBin]<0 && iBin<NSIZE; iBin++){}
+ if( iBin>=NSIZE ) return 0;
+ i = memsys5UnlinkFirst(iBin);
+ while( iBin>iLogsize ){
+ int newSize;
+
+ iBin--;
+ newSize = 1 << iBin;
+ mem.aCtrl[i+newSize] = CTRL_FREE | iBin;
+ memsys5Link(i+newSize, iBin);
+ }
+ mem.aCtrl[i] = iLogsize;
+
+ /* Update allocator performance statistics. */
+ mem.nAlloc++;
+ mem.totalAlloc += iFullSz;
+ mem.totalExcess += iFullSz - nByte;
+ mem.currentCount++;
+ mem.currentOut += iFullSz;
+ if( mem.maxCount<mem.currentCount ) mem.maxCount = mem.currentCount;
+ if( mem.maxOut<mem.currentOut ) mem.maxOut = mem.currentOut;
+
+ /* Return a pointer to the allocated memory. */
+ return (void*)&mem.aPool[i];
+}
+
+/*
+** Free an outstanding memory allocation.
+*/
+void memsys5Free(void *pOld){
+ u32 size, iLogsize;
+ int i;
+
+ i = ((Mem5Block*)pOld) - mem.aPool;
+ assert( sqlite3_mutex_held(mem.mutex) );
+ assert( i>=0 && i<NBLOCK );
+ assert( (mem.aCtrl[i] & CTRL_FREE)==0 );
+ iLogsize = mem.aCtrl[i] & CTRL_LOGSIZE;
+ size = 1<<iLogsize;
+ assert( i+size-1<NBLOCK );
+ mem.aCtrl[i] |= CTRL_FREE;
+ mem.aCtrl[i+size-1] |= CTRL_FREE;
+ assert( mem.currentCount>0 );
+ assert( mem.currentOut>=0 );
+ mem.currentCount--;
+ mem.currentOut -= size*POW2_MIN;
+ assert( mem.currentOut>0 || mem.currentCount==0 );
+ assert( mem.currentCount>0 || mem.currentOut==0 );
+
+ mem.aCtrl[i] = CTRL_FREE | iLogsize;
+ while( iLogsize<NSIZE-1 ){
+ int iBuddy;
+
+ if( (i>>iLogsize) & 1 ){
+ iBuddy = i - size;
+ }else{
+ iBuddy = i + size;
+ }
+ assert( iBuddy>=0 && iBuddy<NBLOCK );
+ if( mem.aCtrl[iBuddy]!=(CTRL_FREE | iLogsize) ) break;
+ memsys5Unlink(iBuddy, iLogsize);
+ iLogsize++;
+ if( iBuddy<i ){
+ mem.aCtrl[iBuddy] = CTRL_FREE | iLogsize;
+ mem.aCtrl[i] = 0;
+ i = iBuddy;
+ }else{
+ mem.aCtrl[i] = CTRL_FREE | iLogsize;
+ mem.aCtrl[iBuddy] = 0;
+ }
+ size *= 2;
+ }
+ memsys5Link(i, iLogsize);
+}
+
+/*
+** Allocate nBytes of memory
+*/
+SQLITE_API void *sqlite3_malloc(int nBytes){
+ sqlite3_int64 *p = 0;
+ if( nBytes>0 ){
+ memsys5Enter();
+ p = memsys5Malloc(nBytes);
+ sqlite3_mutex_leave(mem.mutex);
+ }
+ return (void*)p;
+}
+
+/*
+** Free memory.
+*/
+SQLITE_API void sqlite3_free(void *pPrior){
+ if( pPrior==0 ){
+ return;
+ }
+ assert( mem.mutex!=0 );
+ sqlite3_mutex_enter(mem.mutex);
+ memsys5Free(pPrior);
+ sqlite3_mutex_leave(mem.mutex);
+}
+
+/*
+** Change the size of an existing memory allocation
+*/
+SQLITE_API void *sqlite3_realloc(void *pPrior, int nBytes){
+ int nOld;
+ void *p;
+ if( pPrior==0 ){
+ return sqlite3_malloc(nBytes);
+ }
+ if( nBytes<=0 ){
+ sqlite3_free(pPrior);
+ return 0;
+ }
+ assert( mem.mutex!=0 );
+ nOld = sqlite3MallocSize(pPrior);
+ if( nBytes<=nOld ){
+ return pPrior;
+ }
+ sqlite3_mutex_enter(mem.mutex);
+ p = memsys5Malloc(nBytes);
+ if( p ){
+ memcpy(p, pPrior, nOld);
+ memsys5Free(pPrior);
+ }
+ sqlite3_mutex_leave(mem.mutex);
+ return p;
+}
+
+/*
+** Open the file indicated and write a log of all unfreed memory
+** allocations into that log.
+*/
+SQLITE_PRIVATE void sqlite3MemdebugDump(const char *zFilename){
+#ifdef SQLITE_DEBUG
+ FILE *out;
+ int i, j, n;
+
+ if( zFilename==0 || zFilename[0]==0 ){
+ out = stdout;
+ }else{
+ out = fopen(zFilename, "w");
+ if( out==0 ){
+ fprintf(stderr, "** Unable to output memory debug output log: %s **\n",
+ zFilename);
+ return;
+ }
+ }
+ memsys5Enter();
+ for(i=0; i<NSIZE; i++){
+ for(n=0, j=mem.aiFreelist[i]; j>=0; j = mem.aPool[j].u.list.next, n++){}
+ fprintf(out, "freelist items of size %d: %d\n", POW2_MIN << i, n);
+ }
+ fprintf(out, "mem.nAlloc = %llu\n", mem.nAlloc);
+ fprintf(out, "mem.totalAlloc = %llu\n", mem.totalAlloc);
+ fprintf(out, "mem.totalExcess = %llu\n", mem.totalExcess);
+ fprintf(out, "mem.currentOut = %u\n", mem.currentOut);
+ fprintf(out, "mem.currentCount = %u\n", mem.currentCount);
+ fprintf(out, "mem.maxOut = %u\n", mem.maxOut);
+ fprintf(out, "mem.maxCount = %u\n", mem.maxCount);
+ fprintf(out, "mem.maxRequest = %u\n", mem.maxRequest);
+ sqlite3_mutex_leave(mem.mutex);
+ if( out==stdout ){
+ fflush(stdout);
+ }else{
+ fclose(out);
+ }
+#endif
+}
+
+
+#endif /* !SQLITE_POW2_MEMORY_SIZE */
+
+/************** End of mem5.c ************************************************/
/************** Begin file mutex.c *******************************************/
/*
** 2007 August 14
**
@@ -11267,9 +12865,9 @@
** are called correctly and at appropriate times. Hence, this
** implementation is suitable for testing.
** debugging purposes
**
-** $Id: mutex.c,v 1.16 2007/09/10 16:13:00 danielk1977 Exp $
+** $Id: mutex.c,v 1.17 2008/03/26 18:34:43 danielk1977 Exp $
*/
#ifdef SQLITE_MUTEX_NOOP_DEBUG
/*
@@ -11291,9 +12889,9 @@
** mutex and returns a pointer to it. If it returns NULL
** that means that a mutex could not be allocated.
*/
SQLITE_API sqlite3_mutex *sqlite3_mutex_alloc(int id){
- static sqlite3_mutex aStatic[5];
+ static sqlite3_mutex aStatic[6];
sqlite3_mutex *pNew = 0;
switch( id ){
case SQLITE_MUTEX_FAST:
case SQLITE_MUTEX_RECURSIVE: {
@@ -11387,9 +12985,9 @@
**
*************************************************************************
** This file contains the C functions that implement mutexes for OS/2
**
-** $Id: mutex_os2.c,v 1.4 2007/12/30 23:29:07 pweilbacher Exp $
+** $Id: mutex_os2.c,v 1.6 2008/03/26 18:34:43 danielk1977 Exp $
*/
/*
** The code in this file is only used if SQLITE_MUTEX_OS2 is defined.
@@ -11406,14 +13004,15 @@
** The mutex object
** Each recursive mutex is an instance of the following structure.
*/
struct sqlite3_mutex {
- PSZ mutexName; /* Mutex name controlling the lock */
HMTX mutex; /* Mutex controlling the lock */
int id; /* Mutex type */
int nRef; /* Number of references */
TID owner; /* Thread holding this mutex */
};
+
+#define OS2_MUTEX_INITIALIZER 0,0,0,0
/*
** The sqlite3_mutex_alloc() routine allocates a new
** mutex and returns a pointer to it. If it returns NULL
@@ -11453,48 +13052,58 @@
** mutex types, the same mutex is returned on every call that has
** the same type number.
*/
SQLITE_API sqlite3_mutex *sqlite3_mutex_alloc(int iType){
- PSZ mutex_name = "\\SEM32\\SQLITE\\MUTEX";
- int mutex_name_len = strlen(mutex_name) + 1; /* name length + null byte */
- sqlite3_mutex *p;
-
+ sqlite3_mutex *p = NULL;
switch( iType ){
case SQLITE_MUTEX_FAST:
case SQLITE_MUTEX_RECURSIVE: {
p = sqlite3MallocZero( sizeof(*p) );
if( p ){
- p->mutexName = (PSZ)malloc(mutex_name_len);
- sqlite3_snprintf(mutex_name_len, p->mutexName, "%s", mutex_name);
p->id = iType;
- DosCreateMutexSem(p->mutexName, &p->mutex, 0, FALSE);
- DosOpenMutexSem(p->mutexName, &p->mutex);
- }
- break;
- }
- default: {
- static sqlite3_mutex staticMutexes[5];
- static int isInit = 0;
- while( !isInit ) {
- static long lock = 0;
- DosEnterCritSec();
- lock++;
- if( lock == 1 ) {
- int i;
- DosExitCritSec();
- for(i = 0; i < sizeof(staticMutexes)/sizeof(staticMutexes[0]); i++) {
- staticMutexes[i].mutexName = (PSZ)malloc(mutex_name_len + 1);
- sqlite3_snprintf(mutex_name_len + 1, /* one more for the number */
- staticMutexes[i].mutexName, "%s%1d", mutex_name, i);
- DosCreateMutexSem(staticMutexes[i].mutexName,
- &staticMutexes[i].mutex, 0, FALSE);
- DosOpenMutexSem(staticMutexes[i].mutexName,
- &staticMutexes[i].mutex);
- }
- isInit = 1;
- } else {
- DosExitCritSec();
- DosSleep(1);
+ if( DosCreateMutexSem( 0, &p->mutex, 0, FALSE ) != NO_ERROR ){
+ sqlite3_free( p );
+ p = NULL;
+ }
+ }
+ break;
+ }
+ default: {
+ static volatile int isInit = 0;
+ static sqlite3_mutex staticMutexes[] = {
+ { OS2_MUTEX_INITIALIZER, },
+ { OS2_MUTEX_INITIALIZER, },
+ { OS2_MUTEX_INITIALIZER, },
+ { OS2_MUTEX_INITIALIZER, },
+ { OS2_MUTEX_INITIALIZER, },
+ { OS2_MUTEX_INITIALIZER, },
+ };
+ if ( !isInit ){
+ APIRET rc;
+ PTIB ptib;
+ PPIB ppib;
+ HMTX mutex;
+ char name[32];
+ DosGetInfoBlocks( &ptib, &ppib );
+ sqlite3_snprintf( sizeof(name), name, "\\SEM32\\SQLITE%04x",
+ ppib->pib_ulpid );
+ while( !isInit ){
+ mutex = 0;
+ rc = DosCreateMutexSem( name, &mutex, 0, FALSE);
+ if( rc == NO_ERROR ){
+ int i;
+ if( !isInit ){
+ for( i = 0; i < sizeof(staticMutexes)/sizeof(staticMutexes[0]); i++ ){
+ DosCreateMutexSem( 0, &staticMutexes[i].mutex, 0, FALSE );
+ }
+ isInit = 1;
+ }
+ DosCloseMutexSem( mutex );
+ }else if( rc == ERROR_DUPLICATE_NAME ){
+ DosSleep( 1 );
+ }else{
+ return p;
+ }
}
}
assert( iType-2 >= 0 );
assert( iType-2 < sizeof(staticMutexes)/sizeof(staticMutexes[0]) );
@@ -11514,11 +13123,10 @@
SQLITE_API void sqlite3_mutex_free(sqlite3_mutex *p){
assert( p );
assert( p->nRef==0 );
assert( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE );
- DosCloseMutexSem(p->mutex);
- free(p->mutexName);
- sqlite3_free(p);
+ DosCloseMutexSem( p->mutex );
+ sqlite3_free( p );
}
/*
** The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt
@@ -11625,9 +13233,9 @@
**
*************************************************************************
** This file contains the C functions that implement mutexes for pthreads
**
-** $Id: mutex_unix.c,v 1.5 2007/11/28 14:04:57 drh Exp $
+** $Id: mutex_unix.c,v 1.7 2008/03/29 12:47:27 rse Exp $
*/
/*
** The code in this file is only used if we are compiling threadsafe
@@ -11652,8 +13260,13 @@
#ifdef SQLITE_DEBUG
int trace; /* True to trace changes */
#endif
};
+#ifdef SQLITE_DEBUG
+#define SQLITE3_MUTEX_INITIALIZER { PTHREAD_MUTEX_INITIALIZER, 0, 0, (pthread_t)0, 0 }
+#else
+#define SQLITE3_MUTEX_INITIALIZER { PTHREAD_MUTEX_INITIALIZER, 0, 0, (pthread_t)0 }
+#endif
/*
** The sqlite3_mutex_alloc() routine allocates a new
** mutex and returns a pointer to it. If it returns NULL
@@ -11696,13 +13309,14 @@
** the same type number.
*/
SQLITE_API sqlite3_mutex *sqlite3_mutex_alloc(int iType){
static sqlite3_mutex staticMutexes[] = {
- { PTHREAD_MUTEX_INITIALIZER, },
- { PTHREAD_MUTEX_INITIALIZER, },
- { PTHREAD_MUTEX_INITIALIZER, },
- { PTHREAD_MUTEX_INITIALIZER, },
- { PTHREAD_MUTEX_INITIALIZER, },
+ SQLITE3_MUTEX_INITIALIZER,
+ SQLITE3_MUTEX_INITIALIZER,
+ SQLITE3_MUTEX_INITIALIZER,
+ SQLITE3_MUTEX_INITIALIZER,
+ SQLITE3_MUTEX_INITIALIZER,
+ SQLITE3_MUTEX_INITIALIZER
};
sqlite3_mutex *p;
switch( iType ){
case SQLITE_MUTEX_RECURSIVE: {
@@ -11925,9 +13539,9 @@
**
*************************************************************************
** This file contains the C functions that implement mutexes for win32
**
-** $Id: mutex_w32.c,v 1.5 2007/10/05 15:08:01 drh Exp $
+** $Id: mutex_w32.c,v 1.6 2008/03/26 18:34:43 danielk1977 Exp $
*/
/*
** The code in this file is only used if we are compiling multithreaded
@@ -12024,9 +13638,9 @@
}
break;
}
default: {
- static sqlite3_mutex staticMutexes[5];
+ static sqlite3_mutex staticMutexes[6];
static int isInit = 0;
while( !isInit ){
static long lock = 0;
if( InterlockedIncrement(&lock)==1 ){
@@ -12147,9 +13761,9 @@
*************************************************************************
** Memory allocation functions used throughout sqlite.
**
**
-** $Id: malloc.c,v 1.14 2007/10/20 16:36:31 drh Exp $
+** $Id: malloc.c,v 1.15 2008/03/26 18:34:43 danielk1977 Exp $
*/
/*
** This routine runs when the memory allocator sees that the
@@ -12191,9 +13805,11 @@
** Release memory held by SQLite instances created by the current thread.
*/
SQLITE_API int sqlite3_release_memory(int n){
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
- return sqlite3PagerReleaseMemory(n);
+ int nRet = sqlite3VdbeReleaseMemory(n);
+ nRet += sqlite3PagerReleaseMemory(n-nRet);
+ return nRet;
#else
return SQLITE_OK;
#endif
}
@@ -12847,9 +14463,9 @@
#endif
if( xtype==etFLOAT ) realvalue += rounder;
/* Normalize realvalue to within 10.0 > realvalue >= 1.0 */
exp = 0;
- if( sqlite3_isnan(realvalue) ){
+ if( sqlite3IsNaN(realvalue) ){
bufpt = "NaN";
length = 3;
break;
}
@@ -13000,10 +14616,13 @@
bufpt = "";
}else if( xtype==etDYNSTRING ){
zExtra = bufpt;
}
- length = strlen(bufpt);
- if( precision>=0 && precision<length ) length = precision;
+ if( precision>=0 ){
+ for(length=0; length<precision && bufpt[length]; length++){}
+ }else{
+ length = strlen(bufpt);
+ }
break;
case etSQLESCAPE:
case etSQLESCAPE2:
case etSQLESCAPE3: {
@@ -13108,16 +14727,19 @@
if( N<=0 ){
return;
}
}else{
- p->nAlloc += p->nAlloc + N + 1;
- if( p->nAlloc > SQLITE_MAX_LENGTH ){
- p->nAlloc = SQLITE_MAX_LENGTH;
- if( p->nChar+N >= p->nAlloc ){
+ i64 szNew = p->nAlloc;
+ szNew += N + 1;
+ if( szNew > p->mxAlloc ){
+ p->nAlloc = p->mxAlloc;
+ if( ((i64)p->nChar)+((i64)N) >= p->nAlloc ){
sqlite3StrAccumReset(p);
p->tooBig = 1;
return;
}
+ }else{
+ p->nAlloc = szNew;
}
zNew = sqlite3_malloc( p->nAlloc );
if( zNew ){
memcpy(zNew, p->zText, p->nChar);
@@ -13166,12 +14788,13 @@
/*
** Initialize a string accumulator
*/
-static void sqlite3StrAccumInit(StrAccum *p, char *zBase, int n){
+static void sqlite3StrAccumInit(StrAccum *p, char *zBase, int n, int mx){
p->zText = p->zBase = zBase;
p->nChar = 0;
p->nAlloc = n;
+ p->mxAlloc = mx;
p->useMalloc = 1;
p->tooBig = 0;
p->mallocFailed = 0;
}
@@ -13183,9 +14806,10 @@
SQLITE_PRIVATE char *sqlite3VMPrintf(sqlite3 *db, const char *zFormat, va_list ap){
char *z;
char zBase[SQLITE_PRINT_BUF_SIZE];
StrAccum acc;
- sqlite3StrAccumInit(&acc, zBase, sizeof(zBase));
+ sqlite3StrAccumInit(&acc, zBase, sizeof(zBase),
+ db ? db->aLimit[SQLITE_LIMIT_LENGTH] : SQLITE_MAX_LENGTH);
vxprintf(&acc, 1, zFormat, ap);
z = sqlite3StrAccumFinish(&acc);
if( acc.mallocFailed && db ){
db->mallocFailed = 1;
@@ -13213,9 +14837,9 @@
SQLITE_API char *sqlite3_vmprintf(const char *zFormat, va_list ap){
char *z;
char zBase[SQLITE_PRINT_BUF_SIZE];
StrAccum acc;
- sqlite3StrAccumInit(&acc, zBase, sizeof(zBase));
+ sqlite3StrAccumInit(&acc, zBase, sizeof(zBase), SQLITE_MAX_LENGTH);
vxprintf(&acc, 0, zFormat, ap);
z = sqlite3StrAccumFinish(&acc);
return z;
}
@@ -13246,9 +14870,9 @@
if( n<=0 ){
return zBuf;
}
- sqlite3StrAccumInit(&acc, zBuf, n);
+ sqlite3StrAccumInit(&acc, zBuf, n, 0);
acc.useMalloc = 0;
va_start(ap,zFormat);
vxprintf(&acc, 0, zFormat, ap);
va_end(ap);
@@ -13265,9 +14889,9 @@
SQLITE_PRIVATE void sqlite3DebugPrintf(const char *zFormat, ...){
va_list ap;
StrAccum acc;
char zBuf[500];
- sqlite3StrAccumInit(&acc, zBuf, sizeof(zBuf));
+ sqlite3StrAccumInit(&acc, zBuf, sizeof(zBuf), 0);
acc.useMalloc = 0;
va_start(ap,zFormat);
vxprintf(&acc, 0, zFormat, ap);
va_end(ap);
@@ -13295,9 +14919,9 @@
**
** Random numbers are used by some of the database backends in order
** to generate random integer keys for tables or random filenames.
**
-** $Id: random.c,v 1.21 2008/01/16 17:46:38 drh Exp $
+** $Id: random.c,v 1.23 2008/03/21 16:45:47 drh Exp $
*/
/* All threads share a single random number generator.
@@ -13369,9 +14993,9 @@
/*
** Return N random bytes.
*/
-SQLITE_PRIVATE void sqlite3Randomness(int N, void *pBuf){
+SQLITE_API void sqlite3_randomness(int N, void *pBuf){
unsigned char *zBuf = pBuf;
static sqlite3_mutex *mutex = 0;
if( mutex==0 ){
mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_PRNG);
@@ -13382,24 +15006,26 @@
}
sqlite3_mutex_leave(mutex);
}
-#ifdef SQLITE_TEST
+#ifndef SQLITE_OMIT_BUILTIN_TEST
/*
** For testing purposes, we sometimes want to preserve the state of
** PRNG and restore the PRNG to its saved state at a later time.
+** The sqlite3_test_control() interface calls these routines to
+** control the PRNG.
*/
static struct sqlite3PrngType sqlite3SavedPrng;
-SQLITE_PRIVATE void sqlite3SavePrngState(void){
+SQLITE_PRIVATE void sqlite3PrngSaveState(void){
memcpy(&sqlite3SavedPrng, &sqlite3Prng, sizeof(sqlite3Prng));
}
-SQLITE_PRIVATE void sqlite3RestorePrngState(void){
+SQLITE_PRIVATE void sqlite3PrngRestoreState(void){
memcpy(&sqlite3Prng, &sqlite3SavedPrng, sizeof(sqlite3Prng));
}
-SQLITE_PRIVATE void sqlite3ResetPrngState(void){
+SQLITE_PRIVATE void sqlite3PrngResetState(void){
sqlite3Prng.isInit = 0;
}
-#endif /* SQLITE_TEST */
+#endif /* SQLITE_OMIT_BUILTIN_TEST */
/************** End of random.c **********************************************/
/************** Begin file utf.c *********************************************/
/*
@@ -13415,9 +15041,9 @@
*************************************************************************
** This file contains routines used to translate between UTF-8,
** UTF-16, UTF-16BE, and UTF-16LE.
**
-** $Id: utf.c,v 1.59 2007/10/03 08:46:45 danielk1977 Exp $
+** $Id: utf.c,v 1.61 2008/03/28 15:44:10 danielk1977 Exp $
**
** Notes on UTF-8:
**
** Byte-0 Byte-1 Byte-2 Byte-3 Value
@@ -13507,8 +15133,9 @@
Bool useRandomRowid; /* Generate new record numbers semi-randomly */
Bool nullRow; /* True if pointing to a row with no data */
Bool nextRowidValid; /* True if the nextRowid field is valid */
Bool pseudoTable; /* This is a NEW or OLD pseudo-tables of a trigger */
+ Bool ephemPseudoTable;
Bool deferredMoveto; /* A call to sqlite3BtreeMoveto() is needed */
Bool isTable; /* True if a table requiring integer keys */
Bool isIndex; /* True if an index containing keys only - no data */
u8 bogusIncrKey; /* Something for pIncrKey to point to if pKeyInfo==0 */
@@ -13535,15 +15162,8 @@
u32 *aOffset; /* Cached offsets to the start of each columns data */
u8 *aRow; /* Data for the current row, if all on one page */
};
typedef struct Cursor Cursor;
-
-/*
-** Number of bytes of string storage space available to each stack
-** layer without having to malloc. NBFS is short for Number of Bytes
-** For Strings.
-*/
-#define NBFS 32
/*
** A value for Cursor.cacheValid that means the cache is always invalid.
*/
@@ -13572,9 +15192,9 @@
u16 flags; /* Some combination of MEM_Null, MEM_Str, MEM_Dyn, etc. */
u8 type; /* One of SQLITE_NULL, SQLITE_TEXT, SQLITE_INTEGER, etc */
u8 enc; /* SQLITE_UTF8, SQLITE_UTF16BE, SQLITE_UTF16LE */
void (*xDel)(void *); /* If not null, call this function to delete Mem.z */
- char zShort[NBFS]; /* Space for short strings */
+ char *zMalloc; /* Dynamic buffer allocated by sqlite3_malloc() */
};
/* One or more of the following flags are set to indicate the validOK
** representations of the value stored in the Mem struct.
@@ -13596,8 +15216,11 @@
#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 MemSetTypeFlag(p, f) \
+ ((p)->flags = ((p)->flags&~(MEM_Int|MEM_Real|MEM_Null|MEM_Blob|MEM_Str))|f)
+
/* 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
@@ -13605,9 +15228,8 @@
#define MEM_Term 0x0020 /* String rep is nul terminated */
#define MEM_Dyn 0x0040 /* Need to call sqliteFree() on Mem.z */
#define MEM_Static 0x0080 /* Mem.z points to a static string */
#define MEM_Ephem 0x0100 /* Mem.z points to an ephemeral string */
-#define MEM_Short 0x0200 /* Mem.z points to Mem.zShort */
#define MEM_Agg 0x0400 /* Mem.z points to an agg function context */
#define MEM_Zero 0x0800 /* Mem.i contains count of 0s appended to blob */
#ifdef SQLITE_OMIT_INCRBLOB
@@ -13651,9 +15273,9 @@
FuncDef *pFunc; /* Pointer to function information. MUST BE FIRST */
VdbeFunc *pVdbeFunc; /* Auxilary data, if created. */
Mem s; /* The return value is stored here */
Mem *pMem; /* Memory cell used to store aggregate context */
- u8 isError; /* Set to true for an error */
+ int isError; /* Error code returned by the function. */
CollSeq *pColl; /* Collating sequence */
};
/*
@@ -13781,8 +15403,34 @@
#ifdef SQLITE_SSE
int fetchId; /* Statement number used by sqlite3_fetch_statement */
int lru; /* Counter used for LRU cache replacement */
#endif
+#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
+ Vdbe *pLruPrev;
+ Vdbe *pLruNext;
+#endif
+};
+
+/*
+** An instance of the following structure holds information about a
+** single index record that has already been parsed out into individual
+** values.
+**
+** A record is an object that contains one or more fields of data.
+** Records are used to store the content of a table row and to store
+** the key of an index. A blob encoding of a record is created by
+** the OP_MakeRecord opcode of the VDBE and is disassemblied by the
+** OP_Column opcode.
+**
+** This structure holds a record that has already been disassembled
+** into its constitutent fields.
+*/
+struct UnpackedRecord {
+ KeyInfo *pKeyInfo; /* Collation and sort-order information */
+ u16 nField; /* Number of entries in apMem[] */
+ u8 needFree; /* True if memory obtained from sqlite3_malloc() */
+ u8 needDestroy; /* True if apMem[]s should be destroyed on close */
+ Mem *aMem; /* Values */
};
/*
** The following are allowed values for Vdbe.magic
@@ -13807,12 +15455,11 @@
SQLITE_PRIVATE int sqlite3VdbeSerialGet(const unsigned char*, u32, Mem*);
SQLITE_PRIVATE void sqlite3VdbeDeleteAuxData(VdbeFunc*, int);
int sqlite2BtreeKeyCompare(BtCursor *, const void *, int, int, int *);
-SQLITE_PRIVATE int sqlite3VdbeIdxKeyCompare(Cursor*,int,const unsigned char*,int*);
+SQLITE_PRIVATE int sqlite3VdbeIdxKeyCompare(Cursor*,UnpackedRecord *,int,const unsigned char*,int*);
SQLITE_PRIVATE int sqlite3VdbeIdxRowid(BtCursor *, i64 *);
SQLITE_PRIVATE int sqlite3MemCompare(const Mem*, const Mem*, const CollSeq*);
-SQLITE_PRIVATE int sqlite3VdbeRecordCompare(void*,int,const void*,int, const void*);
SQLITE_PRIVATE int sqlite3VdbeIdxRowidLen(const u8*);
SQLITE_PRIVATE int sqlite3VdbeExec(Vdbe*);
SQLITE_PRIVATE int sqlite3VdbeList(Vdbe*);
SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe*);
@@ -13837,11 +15484,16 @@
SQLITE_PRIVATE int sqlite3VdbeMemRealify(Mem*);
SQLITE_PRIVATE int sqlite3VdbeMemNumerify(Mem*);
SQLITE_PRIVATE int sqlite3VdbeMemFromBtree(BtCursor*,int,int,int,Mem*);
SQLITE_PRIVATE void sqlite3VdbeMemRelease(Mem *p);
+SQLITE_PRIVATE void sqlite3VdbeMemReleaseExternal(Mem *p);
SQLITE_PRIVATE int sqlite3VdbeMemFinalize(Mem*, FuncDef*);
SQLITE_PRIVATE const char *sqlite3OpcodeName(int);
SQLITE_PRIVATE int sqlite3VdbeOpcodeHasProperty(int, int);
+SQLITE_PRIVATE int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve);
+#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
+SQLITE_PRIVATE int sqlite3VdbeReleaseBuffers(Vdbe *p);
+#endif
#ifndef NDEBUG
SQLITE_PRIVATE void sqlite3VdbeMemSanity(Mem*);
#endif
@@ -14015,9 +15667,8 @@
** desiredEnc. It is an error if the string is already of the desired
** encoding, or if *pMem does not contain a string value.
*/
SQLITE_PRIVATE int sqlite3VdbeMemTranslate(Mem *pMem, u8 desiredEnc){
- unsigned char zShort[NBFS]; /* Temporary short output buffer */
int len; /* Maximum length of output string in bytes */
unsigned char *zOut; /* Output buffer */
unsigned char *zIn; /* Input iterator */
unsigned char *zTerm; /* End of input */
@@ -14081,21 +15732,16 @@
/* Set zIn to point at the start of the input buffer and zTerm to point 1
** byte past the end.
**
- ** Variable zOut is set to point at the output buffer. This may be space
- ** obtained from sqlite3_malloc(), or Mem.zShort, if it large enough and
- ** not in use, or the zShort array on the stack (see above).
+ ** Variable zOut is set to point at the output buffer, space obtained
+ ** from sqlite3_malloc().
*/
zIn = (u8*)pMem->z;
zTerm = &zIn[pMem->n];
- if( len>NBFS ){
- zOut = sqlite3DbMallocRaw(pMem->db, len);
- if( !zOut ){
- return SQLITE_NOMEM;
- }
- }else{
- zOut = zShort;
+ zOut = sqlite3DbMallocRaw(pMem->db, len);
+ if( !zOut ){
+ return SQLITE_NOMEM;
}
z = zOut;
if( pMem->enc==SQLITE_UTF8 ){
@@ -14135,18 +15781,13 @@
*z = 0;
assert( (pMem->n+(desiredEnc==SQLITE_UTF8?1:2))<=len );
sqlite3VdbeMemRelease(pMem);
- pMem->flags &= ~(MEM_Static|MEM_Dyn|MEM_Ephem|MEM_Short);
+ pMem->flags &= ~(MEM_Static|MEM_Dyn|MEM_Ephem);
pMem->enc = desiredEnc;
- if( zOut==zShort ){
- memcpy(pMem->zShort, zOut, len);
- zOut = (u8*)pMem->zShort;
- pMem->flags |= (MEM_Term|MEM_Short);
- }else{
- pMem->flags |= (MEM_Term|MEM_Dyn);
- }
+ pMem->flags |= (MEM_Term|MEM_Dyn);
pMem->z = (char*)zOut;
+ pMem->zMalloc = pMem->z;
translate_out:
#if defined(TRANSLATE_TRACE) && defined(SQLITE_DEBUG)
{
@@ -14182,26 +15823,16 @@
}
}
if( bom ){
- /* This function is called as soon as a string is stored in a Mem*,
- ** from within sqlite3VdbeMemSetStr(). At that point it is not possible
- ** for the string to be stored in Mem.zShort, or for it to be stored
- ** in dynamic memory with no destructor.
- */
- assert( !(pMem->flags&MEM_Short) );
- assert( !(pMem->flags&MEM_Dyn) || pMem->xDel );
- if( pMem->flags & MEM_Dyn ){
- void (*xDel)(void*) = pMem->xDel;
- char *z = pMem->z;
- pMem->z = 0;
- pMem->xDel = 0;
- rc = sqlite3VdbeMemSetStr(pMem, &z[2], pMem->n-2, bom,
- SQLITE_TRANSIENT);
- xDel(z);
- }else{
- rc = sqlite3VdbeMemSetStr(pMem, &pMem->z[2], pMem->n-2, bom,
- SQLITE_TRANSIENT);
+ rc = sqlite3VdbeMemMakeWriteable(pMem);
+ if( rc==SQLITE_OK ){
+ pMem->n -= 2;
+ memmove(pMem->z, &pMem->z[2], pMem->n);
+ pMem->z[pMem->n] = '\0';
+ pMem->z[pMem->n+1] = '\0';
+ pMem->flags |= MEM_Term;
+ pMem->enc = bom;
}
}
return rc;
}
@@ -14389,11 +16020,28 @@
**
** This file contains functions for allocating memory, comparing
** strings, and stuff like that.
**
-** $Id: util.c,v 1.216 2008/01/23 03:03:05 drh Exp $
-*/
-
+** $Id: util.c,v 1.229 2008/05/13 16:41:50 drh Exp $
+*/
+
+
+/*
+** Return true if the floating point value is Not a Number.
+*/
+SQLITE_PRIVATE int sqlite3IsNaN(double x){
+ /* 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.
+ */
+ volatile double y = x;
+ return x!=y;
+}
/*
** Set the most recent error code and error string for the sqlite
** handle "db". The error code is set to "err_code".
@@ -14617,25 +16265,39 @@
#ifndef SQLITE_OMIT_FLOATING_POINT
int sign = 1;
const char *zBegin = z;
LONGDOUBLE_TYPE v1 = 0.0;
+ int nSignificant = 0;
while( isspace(*(u8*)z) ) z++;
if( *z=='-' ){
sign = -1;
z++;
}else if( *z=='+' ){
z++;
}
+ while( z[0]=='0' ){
+ z++;
+ }
while( isdigit(*(u8*)z) ){
v1 = v1*10.0 + (*z - '0');
z++;
+ nSignificant++;
}
if( *z=='.' ){
LONGDOUBLE_TYPE divisor = 1.0;
z++;
+ if( nSignificant==0 ){
+ while( z[0]=='0' ){
+ divisor *= 10.0;
+ z++;
+ }
+ }
while( isdigit(*(u8*)z) ){
- v1 = v1*10.0 + (*z - '0');
- divisor *= 10.0;
+ if( nSignificant<18 ){
+ v1 = v1*10.0 + (*z - '0');
+ divisor *= 10.0;
+ nSignificant++;
+ }
z++;
}
v1 /= divisor;
}
@@ -14870,73 +16532,273 @@
return n;
}
/*
+** This routine is a faster version of sqlite3PutVarint() that only
+** works for 32-bit positive integers and which is optimized for
+** the common case of small integers. A MACRO version, putVarint32,
+** is provided which inlines the single-byte case. All code should use
+** the MACRO version as this function assumes the single-byte case has
+** already been handled.
+*/
+SQLITE_PRIVATE int sqlite3PutVarint32(unsigned char *p, u32 v){
+#ifndef putVarint32
+ if( (v & ~0x7f)==0 ){
+ p[0] = v;
+ return 1;
+ }
+#endif
+ if( (v & ~0x3fff)==0 ){
+ p[0] = (v>>7) | 0x80;
+ p[1] = v & 0x7f;
+ return 2;
+ }
+ return sqlite3PutVarint(p, v);
+}
+
+/*
** Read a 64-bit variable-length integer from memory starting at p[0].
** Return the number of bytes read. The value is stored in *v.
*/
SQLITE_PRIVATE int sqlite3GetVarint(const unsigned char *p, u64 *v){
- u32 x;
- u64 x64;
- int n;
- unsigned char c;
- if( ((c = p[0]) & 0x80)==0 ){
- *v = c;
- return 1;
- }
- x = c & 0x7f;
- if( ((c = p[1]) & 0x80)==0 ){
- *v = (x<<7) | c;
+ u32 a,b,s;
+
+ a = *p;
+ // a: p0 (unmasked)
+ if (!(a&0x80))
+ {
+ *v = a;
+ return 1;
+ }
+
+ p++;
+ b = *p;
+ // b: p1 (unmasked)
+ if (!(b&0x80))
+ {
+ a &= 0x7f;
+ a = a<<7;
+ a |= b;
+ *v = a;
return 2;
}
- x = (x<<7) | (c&0x7f);
- if( ((c = p[2]) & 0x80)==0 ){
- *v = (x<<7) | c;
+
+ p++;
+ a = a<<14;
+ a |= *p;
+ // a: p0<<14 | p2 (unmasked)
+ if (!(a&0x80))
+ {
+ a &= (0x7f<<14)|(0x7f);
+ b &= 0x7f;
+ b = b<<7;
+ a |= b;
+ *v = a;
return 3;
}
- x = (x<<7) | (c&0x7f);
- if( ((c = p[3]) & 0x80)==0 ){
- *v = (x<<7) | c;
+
+ // CSE1 from below
+ a &= (0x7f<<14)|(0x7f);
+ p++;
+ b = b<<14;
+ b |= *p;
+ // b: p1<<14 | p3 (unmasked)
+ if (!(b&0x80))
+ {
+ b &= (0x7f<<14)|(0x7f);
+ // moved CSE1 up
+ // a &= (0x7f<<14)|(0x7f);
+ a = a<<7;
+ a |= b;
+ *v = a;
return 4;
}
- x64 = (x<<7) | (c&0x7f);
- n = 4;
- do{
- c = p[n++];
- if( n==9 ){
- x64 = (x64<<8) | c;
- break;
- }
- x64 = (x64<<7) | (c&0x7f);
- }while( (c & 0x80)!=0 );
- *v = x64;
- return n;
+
+ // a: p0<<14 | p2 (masked)
+ // b: p1<<14 | p3 (unmasked)
+ // 1:save off p0<<21 | p1<<14 | p2<<7 | p3 (masked)
+ // moved CSE1 up
+ // a &= (0x7f<<14)|(0x7f);
+ b &= (0x7f<<14)|(0x7f);
+ s = a;
+ // s: p0<<14 | p2 (masked)
+
+ p++;
+ a = a<<14;
+ a |= *p;
+ // a: p0<<28 | p2<<14 | p4 (unmasked)
+ if (!(a&0x80))
+ {
+ // we can skip these cause they were (effectively) done above in calc'ing s
+ // a &= (0x7f<<28)|(0x7f<<14)|(0x7f);
+ // b &= (0x7f<<14)|(0x7f);
+ b = b<<7;
+ a |= b;
+ s = s>>18;
+ *v = ((u64)s)<<32 | a;
+ return 5;
+ }
+
+ // 2:save off p0<<21 | p1<<14 | p2<<7 | p3 (masked)
+ s = s<<7;
+ s |= b;
+ // s: p0<<21 | p1<<14 | p2<<7 | p3 (masked)
+
+ p++;
+ b = b<<14;
+ b |= *p;
+ // b: p1<<28 | p3<<14 | p5 (unmasked)
+ if (!(b&0x80))
+ {
+ // we can skip this cause it was (effectively) done above in calc'ing s
+ // b &= (0x7f<<28)|(0x7f<<14)|(0x7f);
+ a &= (0x7f<<14)|(0x7f);
+ a = a<<7;
+ a |= b;
+ s = s>>18;
+ *v = ((u64)s)<<32 | a;
+ return 6;
+ }
+
+ p++;
+ a = a<<14;
+ a |= *p;
+ // a: p2<<28 | p4<<14 | p6 (unmasked)
+ if (!(a&0x80))
+ {
+ a &= (0x7f<<28)|(0x7f<<14)|(0x7f);
+ b &= (0x7f<<14)|(0x7f);
+ b = b<<7;
+ a |= b;
+ s = s>>11;
+ *v = ((u64)s)<<32 | a;
+ return 7;
+ }
+
+ // CSE2 from below
+ a &= (0x7f<<14)|(0x7f);
+ p++;
+ b = b<<14;
+ b |= *p;
+ // b: p3<<28 | p5<<14 | p7 (unmasked)
+ if (!(b&0x80))
+ {
+ b &= (0x7f<<28)|(0x7f<<14)|(0x7f);
+ // moved CSE2 up
+ // a &= (0x7f<<14)|(0x7f);
+ a = a<<7;
+ a |= b;
+ s = s>>4;
+ *v = ((u64)s)<<32 | a;
+ return 8;
+ }
+
+ p++;
+ a = a<<15;
+ a |= *p;
+ // a: p4<<29 | p6<<15 | p8 (unmasked)
+
+ // moved CSE2 up
+ // a &= (0x7f<<29)|(0x7f<<15)|(0xff);
+ b &= (0x7f<<14)|(0x7f);
+ b = b<<8;
+ a |= b;
+
+ s = s<<4;
+ b = p[-4];
+ b &= 0x7f;
+ b = b>>3;
+ s |= b;
+
+ *v = ((u64)s)<<32 | a;
+
+ return 9;
}
/*
** Read a 32-bit variable-length integer from memory starting at p[0].
** Return the number of bytes read. The value is stored in *v.
+** 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 int sqlite3GetVarint32(const unsigned char *p, u32 *v){
- u32 x;
- int n;
- unsigned char c;
- if( ((signed char*)p)[0]>=0 ){
- *v = p[0];
- return 1;
- }
- x = p[0] & 0x7f;
- if( ((signed char*)p)[1]>=0 ){
- *v = (x<<7) | p[1];
+ u32 a,b;
+
+ a = *p;
+ // a: p0 (unmasked)
+#ifndef getVarint32
+ if (!(a&0x80))
+ {
+ *v = a;
+ return 1;
+ }
+#endif
+
+ p++;
+ b = *p;
+ // b: p1 (unmasked)
+ if (!(b&0x80))
+ {
+ a &= 0x7f;
+ a = a<<7;
+ *v = a | b;
return 2;
}
- x = (x<<7) | (p[1] & 0x7f);
- n = 2;
- do{
- x = (x<<7) | ((c = p[n++])&0x7f);
- }while( (c & 0x80)!=0 && n<9 );
- *v = x;
- return n;
+
+ p++;
+ a = a<<14;
+ a |= *p;
+ // a: p0<<14 | p2 (unmasked)
+ if (!(a&0x80))
+ {
+ a &= (0x7f<<14)|(0x7f);
+ b &= 0x7f;
+ b = b<<7;
+ *v = a | b;
+ return 3;
+ }
+
+ p++;
+ b = b<<14;
+ b |= *p;
+ // b: p1<<14 | p3 (unmasked)
+ if (!(b&0x80))
+ {
+ 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))
+ {
+ a &= (0x7f<<28)|(0x7f<<14)|(0x7f);
+ b &= (0x7f<<28)|(0x7f<<14)|(0x7f);
+ 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;
+ int n;
+
+ p -= 4;
+ n = sqlite3GetVarint(p, &v64);
+ assert( n>5 && n<=9 );
+ *v = (u32)v64;
+ return n;
+ }
}
/*
** Return the number of bytes that will be needed to store the given
@@ -14966,24 +16828,25 @@
}
-#if !defined(SQLITE_OMIT_BLOB_LITERAL) || defined(SQLITE_HAS_CODEC) \
- || defined(SQLITE_TEST)
+#if !defined(SQLITE_OMIT_BLOB_LITERAL) || defined(SQLITE_HAS_CODEC)
/*
** Translate a single byte of Hex into an integer.
+** This routinen only works if h really is a valid hexadecimal
+** character: 0..9a..fA..F
*/
static int hexToInt(int h){
- if( h>='0' && h<='9' ){
- return h - '0';
- }else if( h>='a' && h<='f' ){
- return h - 'a' + 10;
- }else{
- assert( h>='A' && h<='F' );
- return h - 'A' + 10;
- }
-}
-#endif /* !SQLITE_OMIT_BLOB_LITERAL || SQLITE_HAS_CODEC || SQLITE_TEST */
+ assert( (h>='0' && h<='9') || (h>='a' && h<='f') || (h>='A' && h<='F') );
+#ifdef SQLITE_ASCII
+ h += 9*(1&(h>>6));
+#endif
+#ifdef SQLITE_EBCDIC
+ h += 9*(1&~(h>>4));
+#endif
+ return h & 0xf;
+}
+#endif /* !SQLITE_OMIT_BLOB_LITERAL || SQLITE_HAS_CODEC */
#if !defined(SQLITE_OMIT_BLOB_LITERAL) || defined(SQLITE_HAS_CODEC)
/*
** Convert a BLOB literal of the form "x'hhhhhh'" into its binary
@@ -15036,8 +16899,9 @@
#ifdef SQLITE_DEBUG
SQLITE_PRIVATE int sqlite3SafetyOn(sqlite3 *db){
if( db->magic==SQLITE_MAGIC_OPEN ){
db->magic = SQLITE_MAGIC_BUSY;
+ assert( sqlite3_mutex_held(db->mutex) );
return 0;
}else if( db->magic==SQLITE_MAGIC_BUSY ){
db->magic = SQLITE_MAGIC_ERROR;
db->u1.isInterrupted = 1;
@@ -15054,8 +16918,9 @@
#ifdef SQLITE_DEBUG
SQLITE_PRIVATE int sqlite3SafetyOff(sqlite3 *db){
if( db->magic==SQLITE_MAGIC_BUSY ){
db->magic = SQLITE_MAGIC_OPEN;
+ assert( sqlite3_mutex_held(db->mutex) );
return 0;
}else{
db->magic = SQLITE_MAGIC_ERROR;
db->u1.isInterrupted = 1;
@@ -15111,9 +16976,9 @@
*************************************************************************
** This is the implementation of generic hash-tables
** used in SQLite.
**
-** $Id: hash.c,v 1.25 2008/01/22 21:30:53 drh Exp $
+** $Id: hash.c,v 1.28 2008/05/13 13:27:34 drh Exp $
*/
/* Turn bulk memory into a hash table object by initializing the
** fields of the Hash structure.
@@ -15150,9 +17015,9 @@
assert( pH!=0 );
elem = pH->first;
pH->first = 0;
- if( pH->ht ) sqlite3_free(pH->ht);
+ sqlite3_free(pH->ht);
pH->ht = 0;
pH->htsize = 0;
while( elem ){
HashElem *next_elem = elem->next;
@@ -15318,21 +17183,26 @@
struct _ht *new_ht; /* The new hash table */
HashElem *elem, *next_elem; /* For looping over existing elements */
int (*xHash)(const void*,int); /* The hash function */
- assert( (new_size & (new_size-1))==0 );
+#ifdef SQLITE_MALLOC_SOFT_LIMIT
+ if( new_size*sizeof(struct _ht)>SQLITE_MALLOC_SOFT_LIMIT ){
+ new_size = SQLITE_MALLOC_SOFT_LIMIT/sizeof(struct _ht);
+ }
+ if( new_size==pH->htsize ) return;
+#endif
/* There is a call to sqlite3_malloc() inside rehash(). If there is
** already an allocation at pH->ht, then if this malloc() fails it
** is benign (since failing to resize a hash table is a performance
** hit only, not a fatal error).
*/
- sqlite3FaultBenign(SQLITE_FAULTINJECTOR_MALLOC, pH->htsize>0);
+ if( pH->htsize>0 ) sqlite3FaultBeginBenign(SQLITE_FAULTINJECTOR_MALLOC);
new_ht = (struct _ht *)sqlite3MallocZero( new_size*sizeof(struct _ht) );
- sqlite3FaultBenign(SQLITE_FAULTINJECTOR_MALLOC, 0);
+ if( pH->htsize>0 ) sqlite3FaultEndBenign(SQLITE_FAULTINJECTOR_MALLOC);
if( new_ht==0 ) return;
- if( pH->ht ) sqlite3_free(pH->ht);
+ sqlite3_free(pH->ht);
pH->ht = new_ht;
pH->htsize = new_size;
xHash = hashFunction(pH->keyClass);
for(elem=pH->first, pH->first=0; elem; elem = next_elem){
@@ -15421,10 +17291,9 @@
if( pH==0 || pH->ht==0 ) return 0;
xHash = hashFunction(pH->keyClass);
assert( xHash!=0 );
h = (*xHash)(pKey,nKey);
- assert( (pH->htsize & (pH->htsize-1))==0 );
- elem = findElementGivenHash(pH,pKey,nKey, h & (pH->htsize-1));
+ elem = findElementGivenHash(pH,pKey,nKey, h % pH->htsize);
return elem;
}
/* Attempt to locate an element of the hash table pH with a key
@@ -15462,23 +17331,24 @@
assert( pH!=0 );
xHash = hashFunction(pH->keyClass);
assert( xHash!=0 );
hraw = (*xHash)(pKey, nKey);
- assert( (pH->htsize & (pH->htsize-1))==0 );
- h = hraw & (pH->htsize-1);
- elem = findElementGivenHash(pH,pKey,nKey,h);
- if( elem ){
- void *old_data = elem->data;
- if( data==0 ){
- removeElementGivenHash(pH,elem,h);
- }else{
- elem->data = data;
- if( !pH->copyKey ){
- elem->pKey = (void *)pKey;
- }
- assert(nKey==elem->nKey);
- }
- return old_data;
+ if( pH->htsize ){
+ h = hraw % pH->htsize;
+ elem = findElementGivenHash(pH,pKey,nKey,h);
+ if( elem ){
+ void *old_data = elem->data;
+ if( data==0 ){
+ removeElementGivenHash(pH,elem,h);
+ }else{
+ elem->data = data;
+ if( !pH->copyKey ){
+ elem->pKey = (void *)pKey;
+ }
+ assert(nKey==elem->nKey);
+ }
+ return old_data;
+ }
}
if( data==0 ) return 0;
new_elem = (HashElem*)sqlite3_malloc( sizeof(HashElem) );
if( new_elem==0 ) return data;
@@ -15494,9 +17364,9 @@
}
new_elem->nKey = nKey;
pH->count++;
if( pH->htsize==0 ){
- rehash(pH,8);
+ rehash(pH, 128/sizeof(pH->ht[0]));
if( pH->htsize==0 ){
pH->count = 0;
if( pH->copyKey ){
sqlite3_free(new_elem->pKey);
@@ -15508,10 +17378,9 @@
if( pH->count > pH->htsize ){
rehash(pH,pH->htsize*2);
}
assert( pH->htsize>0 );
- assert( (pH->htsize & (pH->htsize-1))==0 );
- h = hraw & (pH->htsize-1);
+ h = hraw % pH->htsize;
insertElement(pH, &pH->ht[h], new_elem);
new_elem->data = data;
return 0;
}
@@ -15523,71 +17392,71 @@
#if !defined(SQLITE_OMIT_EXPLAIN) || !defined(NDEBUG) || defined(VDBE_PROFILE) || defined(SQLITE_DEBUG)
SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
static const char *const azName[] = { "?",
/* 1 */ "VNext",
- /* 2 */ "Column",
- /* 3 */ "SetCookie",
- /* 4 */ "Sequence",
- /* 5 */ "MoveGt",
- /* 6 */ "RowKey",
- /* 7 */ "SCopy",
- /* 8 */ "OpenWrite",
- /* 9 */ "If",
- /* 10 */ "VRowid",
- /* 11 */ "CollSeq",
- /* 12 */ "OpenRead",
- /* 13 */ "Expire",
- /* 14 */ "AutoCommit",
- /* 15 */ "IntegrityCk",
+ /* 2 */ "Affinity",
+ /* 3 */ "Column",
+ /* 4 */ "SetCookie",
+ /* 5 */ "Sequence",
+ /* 6 */ "MoveGt",
+ /* 7 */ "RowKey",
+ /* 8 */ "SCopy",
+ /* 9 */ "OpenWrite",
+ /* 10 */ "If",
+ /* 11 */ "VRowid",
+ /* 12 */ "CollSeq",
+ /* 13 */ "OpenRead",
+ /* 14 */ "Expire",
+ /* 15 */ "AutoCommit",
/* 16 */ "Not",
- /* 17 */ "Sort",
- /* 18 */ "Copy",
- /* 19 */ "Trace",
- /* 20 */ "Function",
- /* 21 */ "IfNeg",
- /* 22 */ "Noop",
- /* 23 */ "Return",
- /* 24 */ "NewRowid",
- /* 25 */ "Variable",
- /* 26 */ "String",
- /* 27 */ "RealAffinity",
- /* 28 */ "VRename",
- /* 29 */ "ParseSchema",
- /* 30 */ "VOpen",
- /* 31 */ "Close",
- /* 32 */ "CreateIndex",
- /* 33 */ "IsUnique",
- /* 34 */ "NotFound",
- /* 35 */ "Int64",
- /* 36 */ "MustBeInt",
- /* 37 */ "Halt",
- /* 38 */ "Rowid",
- /* 39 */ "IdxLT",
- /* 40 */ "AddImm",
- /* 41 */ "Statement",
- /* 42 */ "RowData",
- /* 43 */ "MemMax",
- /* 44 */ "NotExists",
- /* 45 */ "Gosub",
- /* 46 */ "Integer",
- /* 47 */ "Prev",
- /* 48 */ "VColumn",
- /* 49 */ "CreateTable",
- /* 50 */ "Last",
- /* 51 */ "IncrVacuum",
- /* 52 */ "IdxRowid",
- /* 53 */ "ResetCount",
- /* 54 */ "FifoWrite",
- /* 55 */ "ContextPush",
- /* 56 */ "DropTrigger",
- /* 57 */ "DropIndex",
- /* 58 */ "IdxGE",
- /* 59 */ "IdxDelete",
+ /* 17 */ "IntegrityCk",
+ /* 18 */ "Sort",
+ /* 19 */ "Copy",
+ /* 20 */ "Trace",
+ /* 21 */ "Function",
+ /* 22 */ "IfNeg",
+ /* 23 */ "Noop",
+ /* 24 */ "Return",
+ /* 25 */ "NewRowid",
+ /* 26 */ "Variable",
+ /* 27 */ "String",
+ /* 28 */ "RealAffinity",
+ /* 29 */ "VRename",
+ /* 30 */ "ParseSchema",
+ /* 31 */ "VOpen",
+ /* 32 */ "Close",
+ /* 33 */ "CreateIndex",
+ /* 34 */ "IsUnique",
+ /* 35 */ "NotFound",
+ /* 36 */ "Int64",
+ /* 37 */ "MustBeInt",
+ /* 38 */ "Halt",
+ /* 39 */ "Rowid",
+ /* 40 */ "IdxLT",
+ /* 41 */ "AddImm",
+ /* 42 */ "Statement",
+ /* 43 */ "RowData",
+ /* 44 */ "MemMax",
+ /* 45 */ "NotExists",
+ /* 46 */ "Gosub",
+ /* 47 */ "Integer",
+ /* 48 */ "Prev",
+ /* 49 */ "VColumn",
+ /* 50 */ "CreateTable",
+ /* 51 */ "Last",
+ /* 52 */ "IncrVacuum",
+ /* 53 */ "IdxRowid",
+ /* 54 */ "ResetCount",
+ /* 55 */ "FifoWrite",
+ /* 56 */ "ContextPush",
+ /* 57 */ "DropTrigger",
+ /* 58 */ "DropIndex",
+ /* 59 */ "IdxGE",
/* 60 */ "Or",
/* 61 */ "And",
- /* 62 */ "Vacuum",
- /* 63 */ "MoveLe",
- /* 64 */ "IfNot",
+ /* 62 */ "IdxDelete",
+ /* 63 */ "Vacuum",
+ /* 64 */ "MoveLe",
/* 65 */ "IsNull",
/* 66 */ "NotNull",
/* 67 */ "Ne",
/* 68 */ "Eq",
@@ -15594,9 +17463,9 @@
/* 69 */ "Gt",
/* 70 */ "Le",
/* 71 */ "Lt",
/* 72 */ "Ge",
- /* 73 */ "DropTable",
+ /* 73 */ "IfNot",
/* 74 */ "BitAnd",
/* 75 */ "BitOr",
/* 76 */ "ShiftLeft",
/* 77 */ "ShiftRight",
@@ -15605,49 +17474,49 @@
/* 80 */ "Multiply",
/* 81 */ "Divide",
/* 82 */ "Remainder",
/* 83 */ "Concat",
- /* 84 */ "MakeRecord",
- /* 85 */ "ResultRow",
- /* 86 */ "Delete",
+ /* 84 */ "DropTable",
+ /* 85 */ "MakeRecord",
+ /* 86 */ "ResultRow",
/* 87 */ "BitNot",
/* 88 */ "String8",
- /* 89 */ "AggFinal",
- /* 90 */ "Goto",
- /* 91 */ "TableLock",
- /* 92 */ "FifoRead",
- /* 93 */ "Clear",
- /* 94 */ "MoveLt",
- /* 95 */ "VerifyCookie",
- /* 96 */ "AggStep",
- /* 97 */ "SetNumColumns",
- /* 98 */ "Transaction",
- /* 99 */ "VFilter",
- /* 100 */ "VDestroy",
- /* 101 */ "ContextPop",
- /* 102 */ "Next",
- /* 103 */ "IdxInsert",
- /* 104 */ "Insert",
- /* 105 */ "Destroy",
- /* 106 */ "ReadCookie",
- /* 107 */ "ForceInt",
- /* 108 */ "LoadAnalysis",
- /* 109 */ "Explain",
- /* 110 */ "OpenPseudo",
- /* 111 */ "OpenEphemeral",
- /* 112 */ "Null",
- /* 113 */ "Move",
- /* 114 */ "Blob",
- /* 115 */ "Rewind",
- /* 116 */ "MoveGe",
- /* 117 */ "VBegin",
- /* 118 */ "VUpdate",
- /* 119 */ "IfZero",
- /* 120 */ "VCreate",
- /* 121 */ "Found",
- /* 122 */ "IfPos",
- /* 123 */ "NullRow",
- /* 124 */ "NotUsed_124",
+ /* 89 */ "Delete",
+ /* 90 */ "AggFinal",
+ /* 91 */ "Goto",
+ /* 92 */ "TableLock",
+ /* 93 */ "FifoRead",
+ /* 94 */ "Clear",
+ /* 95 */ "MoveLt",
+ /* 96 */ "VerifyCookie",
+ /* 97 */ "AggStep",
+ /* 98 */ "SetNumColumns",
+ /* 99 */ "Transaction",
+ /* 100 */ "VFilter",
+ /* 101 */ "VDestroy",
+ /* 102 */ "ContextPop",
+ /* 103 */ "Next",
+ /* 104 */ "IdxInsert",
+ /* 105 */ "Insert",
+ /* 106 */ "Destroy",
+ /* 107 */ "ReadCookie",
+ /* 108 */ "ForceInt",
+ /* 109 */ "LoadAnalysis",
+ /* 110 */ "Explain",
+ /* 111 */ "OpenPseudo",
+ /* 112 */ "OpenEphemeral",
+ /* 113 */ "Null",
+ /* 114 */ "Move",
+ /* 115 */ "Blob",
+ /* 116 */ "Rewind",
+ /* 117 */ "MoveGe",
+ /* 118 */ "VBegin",
+ /* 119 */ "VUpdate",
+ /* 120 */ "IfZero",
+ /* 121 */ "VCreate",
+ /* 122 */ "Found",
+ /* 123 */ "IfPos",
+ /* 124 */ "NullRow",
/* 125 */ "Real",
/* 126 */ "NotUsed_126",
/* 127 */ "NotUsed_127",
/* 128 */ "NotUsed_128",
@@ -15766,18 +17635,18 @@
SQLITE_API unsigned int sqlite3_pending_byte = 0x40000000;
#endif
#ifdef SQLITE_DEBUG
-SQLITE_API int sqlite3_os_trace = 0;
-#define OSTRACE1(X) if( sqlite3_os_trace ) sqlite3DebugPrintf(X)
-#define OSTRACE2(X,Y) if( sqlite3_os_trace ) sqlite3DebugPrintf(X,Y)
-#define OSTRACE3(X,Y,Z) if( sqlite3_os_trace ) sqlite3DebugPrintf(X,Y,Z)
-#define OSTRACE4(X,Y,Z,A) if( sqlite3_os_trace ) sqlite3DebugPrintf(X,Y,Z,A)
-#define OSTRACE5(X,Y,Z,A,B) if( sqlite3_os_trace ) sqlite3DebugPrintf(X,Y,Z,A,B)
+SQLITE_PRIVATE int sqlite3OSTrace = 0;
+#define OSTRACE1(X) if( sqlite3OSTrace ) sqlite3DebugPrintf(X)
+#define OSTRACE2(X,Y) if( sqlite3OSTrace ) sqlite3DebugPrintf(X,Y)
+#define OSTRACE3(X,Y,Z) if( sqlite3OSTrace ) sqlite3DebugPrintf(X,Y,Z)
+#define OSTRACE4(X,Y,Z,A) if( sqlite3OSTrace ) sqlite3DebugPrintf(X,Y,Z,A)
+#define OSTRACE5(X,Y,Z,A,B) if( sqlite3OSTrace ) sqlite3DebugPrintf(X,Y,Z,A,B)
#define OSTRACE6(X,Y,Z,A,B,C) \
- if(sqlite3_os_trace) sqlite3DebugPrintf(X,Y,Z,A,B,C)
+ if(sqlite3OSTrace) sqlite3DebugPrintf(X,Y,Z,A,B,C)
#define OSTRACE7(X,Y,Z,A,B,C,D) \
- if(sqlite3_os_trace) sqlite3DebugPrintf(X,Y,Z,A,B,C,D)
+ if(sqlite3OSTrace) sqlite3DebugPrintf(X,Y,Z,A,B,C,D)
#else
#define OSTRACE1(X)
#define OSTRACE2(X,Y)
#define OSTRACE3(X,Y,Z)
@@ -15815,21 +17684,24 @@
** of code will give us the ability to simulate a disk I/O error. This
** is used for testing the I/O recovery logic.
*/
#ifdef SQLITE_TEST
-SQLITE_API int sqlite3_io_error_hit = 0;
-SQLITE_API int sqlite3_io_error_pending = 0;
-SQLITE_API int sqlite3_io_error_persist = 0;
+SQLITE_API int sqlite3_io_error_hit = 0; /* Total number of I/O Errors */
+SQLITE_API int sqlite3_io_error_hardhit = 0; /* Number of non-benign errors */
+SQLITE_API int sqlite3_io_error_pending = 0; /* Count down to first I/O error */
+SQLITE_API int sqlite3_io_error_persist = 0; /* True if I/O errors persist */
+SQLITE_API int sqlite3_io_error_benign = 0; /* True if errors are benign */
SQLITE_API int sqlite3_diskfull_pending = 0;
SQLITE_API int sqlite3_diskfull = 0;
+#define SimulateIOErrorBenign(X) sqlite3_io_error_benign=(X)
#define SimulateIOError(CODE) \
- if( sqlite3_io_error_pending || sqlite3_io_error_hit ) \
- if( sqlite3_io_error_pending-- == 1 \
- || (sqlite3_io_error_persist && sqlite3_io_error_hit) ) \
- { local_ioerr(); 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 = 1;
+ 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 ){ \
@@ -15841,8 +17713,9 @@
sqlite3_diskfull_pending--; \
} \
}
#else
+#define SimulateIOErrorBenign(X)
#define SimulateIOError(A)
#define SimulateDiskfullError(A)
#endif
@@ -15866,12 +17739,13 @@
typedef struct os2File os2File;
struct os2File {
const sqlite3_io_methods *pMethod; /* Always the first entry */
HFILE h; /* Handle for accessing the file */
- int delOnClose; /* True if file is to be deleted on close */
- char* pathToDel; /* Name of file to delete on close */
+ char* pathToDel; /* Name of file to delete on close, NULL if not */
unsigned char locktype; /* Type of lock currently held on this file */
};
+
+#define LOCK_TIMEOUT 10L /* the default locking timeout */
/*****************************************************************************
** The next group of routines implement the I/O methods specified
** by the sqlite3_io_methods object.
@@ -15886,13 +17760,12 @@
if( id && (pFile = (os2File*)id) != 0 ){
OSTRACE2( "CLOSE %d\n", pFile->h );
rc = DosClose( pFile->h );
pFile->locktype = NO_LOCK;
- if( pFile->delOnClose != 0 ){
+ if( pFile->pathToDel != NULL ){
rc = DosForceDelete( (PSZ)pFile->pathToDel );
- }
- if( pFile->pathToDel ){
free( pFile->pathToDel );
+ pFile->pathToDel = NULL;
}
id = 0;
OpenCounter( -1 );
}
@@ -15953,9 +17826,9 @@
return SQLITE_IOERR;
}
assert( amt>0 );
while( amt > 0 &&
- (rc = DosWrite( pFile->h, (PVOID)pBuf, amt, &wrote )) &&
+ ( rc = DosWrite( pFile->h, (PVOID)pBuf, amt, &wrote ) ) == NO_ERROR &&
wrote > 0
){
amt -= wrote;
pBuf = &((char*)pBuf)[wrote];
@@ -16030,9 +17903,9 @@
LockArea.lOffset = SHARED_FIRST;
LockArea.lRange = SHARED_SIZE;
UnlockArea.lOffset = 0L;
UnlockArea.lRange = 0L;
- res = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, 2000L, 1L );
+ res = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, LOCK_TIMEOUT, 1L );
OSTRACE3( "GETREADLOCK %d res=%d\n", pFile->h, res );
return res;
}
@@ -16048,9 +17921,9 @@
LockArea.lOffset = 0L;
LockArea.lRange = 0L;
UnlockArea.lOffset = SHARED_FIRST;
UnlockArea.lRange = SHARED_SIZE;
- res = DosSetFileLocks( id->h, &UnlockArea, &LockArea, 2000L, 1L );
+ res = DosSetFileLocks( id->h, &UnlockArea, &LockArea, LOCK_TIMEOUT, 1L );
OSTRACE3( "UNLOCK-READLOCK file handle=%d res=%d?\n", id->h, res );
return res;
}
@@ -16094,9 +17967,9 @@
OSTRACE4( "LOCK %d %d was %d\n", pFile->h, locktype, pFile->locktype );
/* If there is already a lock of this type or more restrictive on the
** os2File, do nothing. Don't use the end_lock: exit path, as
- ** sqlite3OsEnterMutex() hasn't been called yet.
+ ** sqlite3_mutex_enter() hasn't been called yet.
*/
if( pFile->locktype>=locktype ){
OSTRACE3( "LOCK %d %d ok (already held)\n", pFile->h, locktype );
return SQLITE_OK;
@@ -16115,25 +17988,16 @@
newLocktype = pFile->locktype;
if( pFile->locktype==NO_LOCK
|| (locktype==EXCLUSIVE_LOCK && pFile->locktype==RESERVED_LOCK)
){
- int cnt = 3;
-
LockArea.lOffset = PENDING_BYTE;
LockArea.lRange = 1L;
UnlockArea.lOffset = 0L;
UnlockArea.lRange = 0L;
- while( cnt-->0 && ( res = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, 2000L, 1L) )
- != NO_ERROR
- ){
- /* Try 3 times to get the pending lock. The pending lock might be
- ** held by another reader process who will release it momentarily.
- */
- OSTRACE2( "LOCK could not get a PENDING lock. cnt=%d\n", cnt );
- DosSleep(1);
- }
- if( res == NO_ERROR){
+ /* wait longer than LOCK_TIMEOUT here not to have to try multiple times */
+ res = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, 100L, 0L );
+ if( res == NO_ERROR ){
gotPendingLock = 1;
OSTRACE3( "LOCK %d pending lock boolean set. res=%d\n", pFile->h, res );
}
}
@@ -16156,9 +18020,9 @@
LockArea.lOffset = RESERVED_BYTE;
LockArea.lRange = 1L;
UnlockArea.lOffset = 0L;
UnlockArea.lRange = 0L;
- res = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, 2000L, 1L );
+ res = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, LOCK_TIMEOUT, 0L );
if( res == NO_ERROR ){
newLocktype = RESERVED_LOCK;
}
OSTRACE3( "LOCK %d acquire reserved lock. res=%d\n", pFile->h, res );
@@ -16181,9 +18045,9 @@
LockArea.lOffset = SHARED_FIRST;
LockArea.lRange = SHARED_SIZE;
UnlockArea.lOffset = 0L;
UnlockArea.lRange = 0L;
- res = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, 2000L, 1L );
+ res = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, LOCK_TIMEOUT, 0L );
if( res == NO_ERROR ){
newLocktype = EXCLUSIVE_LOCK;
}else{
OSTRACE2( "OS/2 error-code = %d\n", res );
@@ -16200,9 +18064,9 @@
LockArea.lOffset = 0L;
LockArea.lRange = 0L;
UnlockArea.lOffset = PENDING_BYTE;
UnlockArea.lRange = 1L;
- r = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, 2000L, 1L );
+ r = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, LOCK_TIMEOUT, 0L );
OSTRACE3( "LOCK %d unlocking pending/is shared. r=%d\n", pFile->h, r );
}
/* Update the state of the lock has held in the file descriptor then
@@ -16225,37 +18089,39 @@
** file by this or any other process. If such a lock is held, return
** non-zero, otherwise zero.
*/
int os2CheckReservedLock( sqlite3_file *id ){
- APIRET rc = NO_ERROR;
+ int r = 0;
os2File *pFile = (os2File*)id;
assert( pFile!=0 );
if( pFile->locktype>=RESERVED_LOCK ){
- rc = 1;
- OSTRACE3( "TEST WR-LOCK %d %d (local)\n", pFile->h, rc );
+ r = 1;
+ OSTRACE3( "TEST WR-LOCK %d %d (local)\n", pFile->h, r );
}else{
FILELOCK LockArea,
UnlockArea;
+ APIRET rc = NO_ERROR;
memset(&LockArea, 0, sizeof(LockArea));
memset(&UnlockArea, 0, sizeof(UnlockArea));
LockArea.lOffset = RESERVED_BYTE;
LockArea.lRange = 1L;
UnlockArea.lOffset = 0L;
UnlockArea.lRange = 0L;
- rc = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, 2000L, 1L );
+ rc = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, LOCK_TIMEOUT, 0L );
OSTRACE3( "TEST WR-LOCK %d lock reserved byte rc=%d\n", pFile->h, rc );
if( rc == NO_ERROR ){
- int r;
+ APIRET rcu = NO_ERROR; /* return code for unlocking */
LockArea.lOffset = 0L;
LockArea.lRange = 0L;
UnlockArea.lOffset = RESERVED_BYTE;
UnlockArea.lRange = 1L;
- r = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, 2000L, 1L );
- OSTRACE3( "TEST WR-LOCK %d unlock reserved byte r=%d\n", pFile->h, r );
- }
- OSTRACE3( "TEST WR-LOCK %d %d (remote)\n", pFile->h, rc );
- }
- return rc;
+ rcu = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, LOCK_TIMEOUT, 0L );
+ OSTRACE3( "TEST WR-LOCK %d unlock reserved byte r=%d\n", pFile->h, rcu );
+ }
+ r = !(rc == NO_ERROR);
+ OSTRACE3( "TEST WR-LOCK %d %d (remote)\n", pFile->h, r );
+ }
+ return r;
}
/*
** Lower the locking level on file descriptor id to locktype. locktype
@@ -16285,9 +18151,9 @@
LockArea.lOffset = 0L;
LockArea.lRange = 0L;
UnlockArea.lOffset = SHARED_FIRST;
UnlockArea.lRange = SHARED_SIZE;
- res = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, 2000L, 1L );
+ res = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, LOCK_TIMEOUT, 0L );
OSTRACE3( "UNLOCK %d exclusive lock res=%d\n", pFile->h, res );
if( locktype==SHARED_LOCK && getReadLock(pFile) != NO_ERROR ){
/* This should never happen. We should always be able to
** reacquire the read lock */
@@ -16299,9 +18165,9 @@
LockArea.lOffset = 0L;
LockArea.lRange = 0L;
UnlockArea.lOffset = RESERVED_BYTE;
UnlockArea.lRange = 1L;
- res = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, 2000L, 1L );
+ res = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, LOCK_TIMEOUT, 0L );
OSTRACE3( "UNLOCK %d reserved res=%d\n", pFile->h, res );
}
if( locktype==NO_LOCK && type>=SHARED_LOCK ){
res = unlockReadLock(pFile);
@@ -16311,9 +18177,9 @@
LockArea.lOffset = 0L;
LockArea.lRange = 0L;
UnlockArea.lOffset = PENDING_BYTE;
UnlockArea.lRange = 1L;
- res = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, 2000L, 1L );
+ res = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, LOCK_TIMEOUT, 0L );
OSTRACE3( "UNLOCK %d pending res=%d\n", pFile->h, res );
}
pFile->locktype = locktype;
OSTRACE3( "UNLOCK %d now %d\n", pFile->h, pFile->locktype );
@@ -16355,8 +18221,68 @@
return 0;
}
/*
+** Helper function to convert UTF-8 filenames to local OS/2 codepage.
+** The two-step process: first convert the incoming UTF-8 string
+** into UCS-2 and then from UCS-2 to the current codepage.
+** The returned char pointer has to be freed.
+*/
+char *convertUtf8PathToCp(const char *in)
+{
+ UconvObject uconv;
+ UniChar ucsUtf8Cp[12],
+ tempPath[CCHMAXPATH];
+ char *out;
+ int rc = 0;
+
+ out = (char *)calloc(CCHMAXPATH, 1);
+
+ /* determine string for the conversion of UTF-8 which is CP1208 */
+ rc = UniMapCpToUcsCp(1208, ucsUtf8Cp, 12);
+ rc = UniCreateUconvObject(ucsUtf8Cp, &uconv);
+ rc = UniStrToUcs(uconv, tempPath, (char *)in, CCHMAXPATH);
+ rc = UniFreeUconvObject(uconv);
+
+ /* conversion for current codepage which can be used for paths */
+ rc = UniCreateUconvObject((UniChar *)L"@path=yes", &uconv);
+ rc = UniStrFromUcs(uconv, out, tempPath, CCHMAXPATH);
+ rc = UniFreeUconvObject(uconv);
+
+ return out;
+}
+
+/*
+** Helper function to convert filenames from local codepage to UTF-8.
+** The two-step process: first convert the incoming codepage-specific
+** string into UCS-2 and then from UCS-2 to the codepage of UTF-8.
+** The returned char pointer has to be freed.
+*/
+char *convertCpPathToUtf8(const char *in)
+{
+ UconvObject uconv;
+ UniChar ucsUtf8Cp[12],
+ tempPath[CCHMAXPATH];
+ char *out;
+ int rc = 0;
+
+ out = (char *)calloc(CCHMAXPATH, 1);
+
+ /* conversion for current codepage which can be used for paths */
+ rc = UniCreateUconvObject((UniChar *)L"@path=yes", &uconv);
+ rc = UniStrToUcs(uconv, tempPath, (char *)in, CCHMAXPATH);
+ rc = UniFreeUconvObject(uconv);
+
+ /* determine string for the conversion of UTF-8 which is CP1208 */
+ rc = UniMapCpToUcsCp(1208, ucsUtf8Cp, 12);
+ rc = UniCreateUconvObject(ucsUtf8Cp, &uconv);
+ rc = UniStrFromUcs(uconv, out, tempPath, CCHMAXPATH);
+ rc = UniFreeUconvObject(uconv);
+
+ return out;
+}
+
+/*
** This vector defines all the methods that can operate on an
** sqlite3_file for os2.
*/
static const sqlite3_io_methods os2IoMethod = {
@@ -16398,9 +18324,9 @@
os2File *pFile = (os2File*)id;
APIRET rc = NO_ERROR;
ULONG ulAction;
- memset(pFile, 0, sizeof(*pFile));
+ memset( pFile, 0, sizeof(*pFile) );
OSTRACE2( "OPEN want %d\n", flags );
//ulOpenMode = flags & SQLITE_OPEN_READWRITE ? OPEN_ACCESS_READWRITE : OPEN_ACCESS_READONLY;
@@ -16431,43 +18357,40 @@
}
if( flags & (SQLITE_OPEN_TEMP_DB | SQLITE_OPEN_TEMP_JOURNAL
| SQLITE_OPEN_SUBJOURNAL) ){
+ char pathUtf8[CCHMAXPATH];
//ulFileAttribute = FILE_HIDDEN; //for debugging, we want to make sure it is deleted
ulFileAttribute = FILE_NORMAL;
- pFile->delOnClose = 1;
- pFile->pathToDel = (char*)malloc(sizeof(char) * pVfs->mxPathname);
- sqlite3OsFullPathname(pVfs, zName, pVfs->mxPathname, pFile->pathToDel);
+ sqlite3OsFullPathname( pVfs, zName, CCHMAXPATH, pathUtf8 );
+ pFile->pathToDel = convertUtf8PathToCp( pathUtf8 );
OSTRACE1( "OPEN hidden/delete on close file attributes\n" );
}else{
ulFileAttribute = FILE_ARCHIVED | FILE_NORMAL;
- pFile->delOnClose = 0;
pFile->pathToDel = NULL;
OSTRACE1( "OPEN normal file attribute\n" );
}
- //ulOpenMode |= flags & (SQLITE_OPEN_MAIN_DB | SQLITE_OPEN_TEMP_DB) ?
- // OPEN_FLAGS_RANDOM : OPEN_FLAGS_SEQUENTIAL;
- if( flags & (SQLITE_OPEN_MAIN_DB | SQLITE_OPEN_TEMP_DB) ){
- ulOpenMode |= OPEN_FLAGS_RANDOM;
- OSTRACE1( "OPEN random access\n" );
- }else{
- ulOpenMode |= OPEN_FLAGS_SEQUENTIAL;
- OSTRACE1( "OPEN sequential access\n" );
- }
+ /* always open in random access mode for possibly better speed */
+ ulOpenMode |= OPEN_FLAGS_RANDOM;
ulOpenMode |= OPEN_FLAGS_FAIL_ON_ERROR;
-
- rc = DosOpen( (PSZ)zName,
+ ulOpenMode |= OPEN_FLAGS_NOINHERIT;
+
+ char *zNameCp = convertUtf8PathToCp( zName );
+ rc = DosOpen( (PSZ)zNameCp,
&h,
&ulAction,
0L,
ulFileAttribute,
ulOpenFlags,
ulOpenMode,
(PEAOP2)NULL );
+ free( zNameCp );
if( rc != NO_ERROR ){
OSTRACE7( "OPEN Invalid handle rc=%d: zName=%s, ulAction=%#lx, ulAttr=%#lx, ulFlags=%#lx, ulMode=%#lx\n",
rc, zName, ulAction, ulFileAttribute, ulOpenFlags, ulOpenMode );
+ free( pFile->pathToDel );
+ pFile->pathToDel = NULL;
if( flags & SQLITE_OPEN_READWRITE ){
OSTRACE2( "OPEN %d Invalid handle\n", ((flags | SQLITE_OPEN_READONLY) & ~SQLITE_OPEN_READWRITE) );
return os2Open( 0, zName, id,
((flags | SQLITE_OPEN_READONLY) & ~SQLITE_OPEN_READWRITE),
@@ -16497,9 +18420,11 @@
int syncDir /* Not used on os2 */
){
APIRET rc = NO_ERROR;
SimulateIOError(return SQLITE_IOERR_DELETE);
- rc = DosDelete( (PSZ)zFilename );
+ char *zFilenameCp = convertUtf8PathToCp( zFilename );
+ rc = DosDelete( (PSZ)zFilenameCp );
+ free( zFilenameCp );
OSTRACE2( "DELETE \"%s\"\n", zFilename );
return rc == NO_ERROR ? SQLITE_OK : SQLITE_IOERR;
}
@@ -16513,11 +18438,13 @@
){
FILESTATUS3 fsts3ConfigInfo;
APIRET rc = NO_ERROR;
- memset(&fsts3ConfigInfo, 0, sizeof(fsts3ConfigInfo));
- rc = DosQueryPathInfo( (PSZ)zFilename, FIL_STANDARD,
+ memset( &fsts3ConfigInfo, 0, sizeof(fsts3ConfigInfo) );
+ char *zFilenameCp = convertUtf8PathToCp( zFilename );
+ rc = DosQueryPathInfo( (PSZ)zFilenameCp, FIL_STANDARD,
&fsts3ConfigInfo, sizeof(FILESTATUS3) );
+ free( zFilenameCp );
OSTRACE4( "ACCESS fsts3ConfigInfo.attrFile=%d flags=%d rc=%d\n",
fsts3ConfigInfo.attrFile, flags, rc );
switch( flags ){
case SQLITE_ACCESS_READ:
@@ -16547,8 +18474,9 @@
"0123456789";
int i, j;
char zTempPathBuf[3];
PSZ zTempPath = (PSZ)&zTempPathBuf;
+ char *zTempPathUTF;
if( DosScanEnv( (PSZ)"TEMP", &zTempPath ) ){
if( DosScanEnv( (PSZ)"TMP", &zTempPath ) ){
if( DosScanEnv( (PSZ)"TMPDIR", &zTempPath ) ){
ULONG ulDriveNum = 0, ulDriveMap = 0;
@@ -16563,13 +18491,14 @@
while( j > 0 && ( zTempPath[j-1] == '\\' || zTempPath[j-1] == '/' ) ){
j--;
}
zTempPath[j] = '\0';
- assert( nBuf>=pVfs->mxPathname );
- sqlite3_snprintf( pVfs->mxPathname-30, zBuf,
- "%s\\"SQLITE_TEMP_FILE_PREFIX, zTempPath );
+ zTempPathUTF = convertCpPathToUtf8( zTempPath );
+ sqlite3_snprintf( nBuf-30, zBuf,
+ "%s\\"SQLITE_TEMP_FILE_PREFIX, zTempPathUTF );
+ free( zTempPathUTF );
j = strlen( zBuf );
- sqlite3Randomness( 20, &zBuf[j] );
+ sqlite3_randomness( 20, &zBuf[j] );
for( i = 0; i < 20; i++, j++ ){
zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ];
}
zBuf[j] = 0;
@@ -16588,9 +18517,17 @@
const char *zRelative, /* Possibly relative input path */
int nFull, /* Size of output buffer in bytes */
char *zFull /* Output buffer */
){
- APIRET rc = DosQueryPathInfo( zRelative, FIL_QUERYFULLNAME, zFull, nFull );
+ char *zRelativeCp = convertUtf8PathToCp( zRelative );
+ char zFullCp[CCHMAXPATH];
+ char *zFullUTF;
+ APIRET rc = DosQueryPathInfo( zRelativeCp, FIL_QUERYFULLNAME, zFullCp,
+ CCHMAXPATH );
+ free( zRelativeCp );
+ zFullUTF = convertCpPathToUtf8( zFullCp );
+ sqlite3_snprintf( nFull, zFull, zFullUTF );
+ free( zFullUTF );
return rc == NO_ERROR ? SQLITE_OK : SQLITE_IOERR;
}
#ifndef SQLITE_OMIT_LOAD_EXTENSION
@@ -16605,9 +18542,11 @@
static void *os2DlOpen(sqlite3_vfs *pVfs, const char *zFilename){
UCHAR loadErr[256];
HMODULE hmod;
APIRET rc;
- rc = DosLoadModule((PSZ)loadErr, sizeof(loadErr), zFilename, &hmod);
+ char *zFilenameCp = convertUtf8PathToCp(zFilename);
+ rc = DosLoadModule((PSZ)loadErr, sizeof(loadErr), zFilenameCp, &hmod);
+ free(zFilenameCp);
return rc != NO_ERROR ? 0 : (void*)hmod;
}
/*
** A no-op since the error code is returned on the DosLoadModule call.
@@ -16939,18 +18878,18 @@
SQLITE_API unsigned int sqlite3_pending_byte = 0x40000000;
#endif
#ifdef SQLITE_DEBUG
-SQLITE_API int sqlite3_os_trace = 0;
-#define OSTRACE1(X) if( sqlite3_os_trace ) sqlite3DebugPrintf(X)
-#define OSTRACE2(X,Y) if( sqlite3_os_trace ) sqlite3DebugPrintf(X,Y)
-#define OSTRACE3(X,Y,Z) if( sqlite3_os_trace ) sqlite3DebugPrintf(X,Y,Z)
-#define OSTRACE4(X,Y,Z,A) if( sqlite3_os_trace ) sqlite3DebugPrintf(X,Y,Z,A)
-#define OSTRACE5(X,Y,Z,A,B) if( sqlite3_os_trace ) sqlite3DebugPrintf(X,Y,Z,A,B)
+SQLITE_PRIVATE int sqlite3OSTrace = 0;
+#define OSTRACE1(X) if( sqlite3OSTrace ) sqlite3DebugPrintf(X)
+#define OSTRACE2(X,Y) if( sqlite3OSTrace ) sqlite3DebugPrintf(X,Y)
+#define OSTRACE3(X,Y,Z) if( sqlite3OSTrace ) sqlite3DebugPrintf(X,Y,Z)
+#define OSTRACE4(X,Y,Z,A) if( sqlite3OSTrace ) sqlite3DebugPrintf(X,Y,Z,A)
+#define OSTRACE5(X,Y,Z,A,B) if( sqlite3OSTrace ) sqlite3DebugPrintf(X,Y,Z,A,B)
#define OSTRACE6(X,Y,Z,A,B,C) \
- if(sqlite3_os_trace) sqlite3DebugPrintf(X,Y,Z,A,B,C)
+ if(sqlite3OSTrace) sqlite3DebugPrintf(X,Y,Z,A,B,C)
#define OSTRACE7(X,Y,Z,A,B,C,D) \
- if(sqlite3_os_trace) sqlite3DebugPrintf(X,Y,Z,A,B,C,D)
+ if(sqlite3OSTrace) sqlite3DebugPrintf(X,Y,Z,A,B,C,D)
#else
#define OSTRACE1(X)
#define OSTRACE2(X,Y)
#define OSTRACE3(X,Y,Z)
@@ -16988,21 +18927,24 @@
** of code will give us the ability to simulate a disk I/O error. This
** is used for testing the I/O recovery logic.
*/
#ifdef SQLITE_TEST
-SQLITE_API int sqlite3_io_error_hit = 0;
-SQLITE_API int sqlite3_io_error_pending = 0;
-SQLITE_API int sqlite3_io_error_persist = 0;
+SQLITE_API int sqlite3_io_error_hit = 0; /* Total number of I/O Errors */
+SQLITE_API int sqlite3_io_error_hardhit = 0; /* Number of non-benign errors */
+SQLITE_API int sqlite3_io_error_pending = 0; /* Count down to first I/O error */
+SQLITE_API int sqlite3_io_error_persist = 0; /* True if I/O errors persist */
+SQLITE_API int sqlite3_io_error_benign = 0; /* True if errors are benign */
SQLITE_API int sqlite3_diskfull_pending = 0;
SQLITE_API int sqlite3_diskfull = 0;
+#define SimulateIOErrorBenign(X) sqlite3_io_error_benign=(X)
#define SimulateIOError(CODE) \
- if( sqlite3_io_error_pending || sqlite3_io_error_hit ) \
- if( sqlite3_io_error_pending-- == 1 \
- || (sqlite3_io_error_persist && sqlite3_io_error_hit) ) \
- { local_ioerr(); 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 = 1;
+ 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 ){ \
@@ -17014,8 +18956,9 @@
sqlite3_diskfull_pending--; \
} \
}
#else
+#define SimulateIOErrorBenign(X)
#define SimulateIOError(A)
#define SimulateDiskfullError(A)
#endif
@@ -17276,14 +19219,14 @@
** UNSUPPORTED means that no locking will be attempted, this is only used for
** file systems that are known to be unsupported
*/
typedef enum {
- posixLockingStyle = 0, /* standard posix-advisory locks */
- afpLockingStyle, /* use afp locks */
- flockLockingStyle, /* use flock() */
- dotlockLockingStyle, /* use <file>.lock files */
- noLockingStyle, /* useful for read-only file system */
- unsupportedLockingStyle /* indicates unsupported file system */
+ posixLockingStyle = 0, /* standard posix-advisory locks */
+ afpLockingStyle, /* use afp locks */
+ flockLockingStyle, /* use flock() */
+ dotlockLockingStyle, /* use <file>.lock files */
+ noLockingStyle, /* useful for read-only file system */
+ unsupportedLockingStyle /* indicates unsupported file system */
} sqlite3LockingStyle;
#endif /* SQLITE_ENABLE_LOCKING_STYLE */
/*
@@ -17505,33 +19448,33 @@
return (sqlite3LockingStyle)SQLITE_FIXED_LOCKING_STYLE;
#else
struct statfs fsInfo;
- if (statfs(filePath, &fsInfo) == -1)
+ if( statfs(filePath, &fsInfo) == -1 ){
return sqlite3TestLockingStyle(filePath, fd);
-
- if (fsInfo.f_flags & MNT_RDONLY)
+ }
+ if( fsInfo.f_flags & MNT_RDONLY ){
return noLockingStyle;
-
- if( (!strcmp(fsInfo.f_fstypename, "hfs")) ||
- (!strcmp(fsInfo.f_fstypename, "ufs")) )
- return posixLockingStyle;
-
- if(!strcmp(fsInfo.f_fstypename, "afpfs"))
+ }
+ if( strcmp(fsInfo.f_fstypename, "hfs")==0 ||
+ strcmp(fsInfo.f_fstypename, "ufs")==0 ){
+ return posixLockingStyle;
+ }
+ if( strcmp(fsInfo.f_fstypename, "afpfs")==0 ){
return afpLockingStyle;
-
- if(!strcmp(fsInfo.f_fstypename, "nfs"))
+ }
+ if( strcmp(fsInfo.f_fstypename, "nfs")==0 ){
return sqlite3TestLockingStyle(filePath, fd);
-
- if(!strcmp(fsInfo.f_fstypename, "smbfs"))
+ }
+ if( strcmp(fsInfo.f_fstypename, "smbfs")==0 ){
return flockLockingStyle;
-
- if(!strcmp(fsInfo.f_fstypename, "msdos"))
+ }
+ if( strcmp(fsInfo.f_fstypename, "msdos")==0 ){
return dotlockLockingStyle;
-
- if(!strcmp(fsInfo.f_fstypename, "webdav"))
+ }
+ if( strcmp(fsInfo.f_fstypename, "webdav")==0 ){
return unsupportedLockingStyle;
-
+ }
return sqlite3TestLockingStyle(filePath, fd);
#endif /* SQLITE_FIXED_LOCKING_STYLE */
}
@@ -17541,9 +19484,9 @@
** Given a file descriptor, locate lockInfo and openCnt structures that
** describes that file descriptor. Create new ones if necessary. The
** return values might be uninitialized if an error occurs.
**
-** Return the number of errors.
+** Return an appropriate error code.
*/
static int findLockInfo(
int fd, /* The file descriptor used in the key */
struct lockInfo **ppLock, /* Return the lockInfo structure here */
@@ -17555,9 +19498,14 @@
struct stat statbuf;
struct lockInfo *pLock;
struct openCnt *pOpen;
rc = fstat(fd, &statbuf);
- if( rc!=0 ) return 1;
+ if( rc!=0 ){
+#ifdef EOVERFLOW
+ if( errno==EOVERFLOW ) return SQLITE_NOLFS;
+#endif
+ return SQLITE_IOERR;
+ }
memset(&key1, 0, sizeof(key1));
key1.dev = statbuf.st_dev;
key1.ino = statbuf.st_ino;
@@ -17574,9 +19522,9 @@
if( pLock==0 ){
struct lockInfo *pOld;
pLock = sqlite3_malloc( sizeof(*pLock) );
if( pLock==0 ){
- rc = 1;
+ rc = SQLITE_NOMEM;
goto exit_findlockinfo;
}
pLock->key = key1;
pLock->nRef = 1;
@@ -17585,9 +19533,9 @@
pOld = sqlite3HashInsert(&lockHash, &pLock->key, sizeof(key1), pLock);
if( pOld!=0 ){
assert( pOld==pLock );
sqlite3_free(pLock);
- rc = 1;
+ rc = SQLITE_NOMEM;
goto exit_findlockinfo;
}
}else{
pLock->nRef++;
@@ -17599,9 +19547,9 @@
struct openCnt *pOld;
pOpen = sqlite3_malloc( sizeof(*pOpen) );
if( pOpen==0 ){
releaseLockInfo(pLock);
- rc = 1;
+ rc = SQLITE_NOMEM;
goto exit_findlockinfo;
}
pOpen->key = key2;
pOpen->nRef = 1;
@@ -17612,9 +19560,9 @@
if( pOld!=0 ){
assert( pOld==pOpen );
sqlite3_free(pOpen);
releaseLockInfo(pLock);
- rc = 1;
+ rc = SQLITE_NOMEM;
goto exit_findlockinfo;
}
}else{
pOpen->nRef++;
@@ -18250,8 +20198,9 @@
struct lockInfo *pLock;
struct flock lock;
int rc = SQLITE_OK;
unixFile *pFile = (unixFile*)id;
+ int h;
assert( pFile );
OSTRACE7("UNLOCK %d %d was %d(%d,%d) pid=%d\n", pFile->h, locktype,
pFile->locktype, pFile->pLock->locktype, pFile->pLock->cnt, getpid());
@@ -18263,30 +20212,33 @@
if( CHECK_THREADID(pFile) ){
return SQLITE_MISUSE;
}
enterMutex();
+ h = pFile->h;
pLock = pFile->pLock;
assert( pLock->cnt!=0 );
if( pFile->locktype>SHARED_LOCK ){
assert( pLock->locktype==pFile->locktype );
+ SimulateIOErrorBenign(1);
+ SimulateIOError( h=(-1) )
+ SimulateIOErrorBenign(0);
if( locktype==SHARED_LOCK ){
lock.l_type = F_RDLCK;
lock.l_whence = SEEK_SET;
lock.l_start = SHARED_FIRST;
lock.l_len = SHARED_SIZE;
- if( fcntl(pFile->h, F_SETLK, &lock)==(-1) ){
- /* This should never happen */
+ if( fcntl(h, F_SETLK, &lock)==(-1) ){
rc = SQLITE_IOERR_RDLOCK;
}
}
lock.l_type = F_UNLCK;
lock.l_whence = SEEK_SET;
lock.l_start = PENDING_BYTE;
lock.l_len = 2L; assert( PENDING_BYTE+1==RESERVED_BYTE );
- if( fcntl(pFile->h, F_SETLK, &lock)!=(-1) ){
+ if( fcntl(h, F_SETLK, &lock)!=(-1) ){
pLock->locktype = SHARED_LOCK;
}else{
- rc = SQLITE_IOERR_UNLOCK; /* This should never happen */
+ rc = SQLITE_IOERR_UNLOCK;
}
}
if( locktype==NO_LOCK ){
struct openCnt *pOpen;
@@ -18299,34 +20251,40 @@
if( pLock->cnt==0 ){
lock.l_type = F_UNLCK;
lock.l_whence = SEEK_SET;
lock.l_start = lock.l_len = 0L;
- if( fcntl(pFile->h, F_SETLK, &lock)!=(-1) ){
+ SimulateIOErrorBenign(1);
+ SimulateIOError( h=(-1) )
+ SimulateIOErrorBenign(0);
+ if( fcntl(h, F_SETLK, &lock)!=(-1) ){
pLock->locktype = NO_LOCK;
}else{
- rc = SQLITE_IOERR_UNLOCK; /* This should never happen */
+ rc = SQLITE_IOERR_UNLOCK;
+ pLock->cnt = 1;
}
}
/* Decrement the count of locks against this same file. When the
** count reaches zero, close any other file descriptors whose close
** was deferred because of outstanding locks.
*/
- pOpen = pFile->pOpen;
- pOpen->nLock--;
- assert( pOpen->nLock>=0 );
- if( pOpen->nLock==0 && pOpen->nPending>0 ){
- int i;
- for(i=0; i<pOpen->nPending; i++){
- close(pOpen->aPending[i]);
- }
- free(pOpen->aPending);
- pOpen->nPending = 0;
- pOpen->aPending = 0;
+ if( rc==SQLITE_OK ){
+ pOpen = pFile->pOpen;
+ pOpen->nLock--;
+ assert( pOpen->nLock>=0 );
+ if( pOpen->nLock==0 && pOpen->nPending>0 ){
+ int i;
+ for(i=0; i<pOpen->nPending; i++){
+ close(pOpen->aPending[i]);
+ }
+ free(pOpen->aPending);
+ pOpen->nPending = 0;
+ pOpen->aPending = 0;
+ }
}
}
leaveMutex();
- pFile->locktype = locktype;
+ if( rc==SQLITE_OK ) pFile->locktype = locktype;
return rc;
}
/*
@@ -18379,9 +20337,9 @@
*/
typedef struct afpLockingContext afpLockingContext;
struct afpLockingContext {
unsigned long long sharedLockByte;
- char *filePath;
+ const char *filePath;
};
struct ByteRangeLockPB2
{
@@ -18466,10 +20424,9 @@
}
/* AFP-style locking following the behavior of unixLock, see the unixLock
** function comments for details of lock management. */
-static int afpUnixLock(sqlite3_file *id, int locktype)
-{
+static int afpUnixLock(sqlite3_file *id, int locktype){
int rc = SQLITE_OK;
unixFile *pFile = (unixFile*)id;
afpLockingContext *context = (afpLockingContext *) pFile->lockingContext;
int gotPendingLock = 0;
@@ -18476,54 +20433,55 @@
assert( pFile );
OSTRACE5("LOCK %d %s was %s pid=%d\n", pFile->h,
locktypeName(locktype), locktypeName(pFile->locktype), getpid());
+
/* If there is already a lock of this type or more restrictive on the
- ** unixFile, do nothing. Don't use the afp_end_lock: exit path, as
- ** enterMutex() hasn't been called yet.
- */
+ ** unixFile, do nothing. Don't use the afp_end_lock: exit path, as
+ ** enterMutex() hasn't been called yet.
+ */
if( pFile->locktype>=locktype ){
OSTRACE3("LOCK %d %s ok (already held)\n", pFile->h,
locktypeName(locktype));
return SQLITE_OK;
}
/* Make sure the locking sequence is correct
- */
+ */
assert( pFile->locktype!=NO_LOCK || locktype==SHARED_LOCK );
assert( locktype!=PENDING_LOCK );
assert( locktype!=RESERVED_LOCK || pFile->locktype==SHARED_LOCK );
/* This mutex is needed because pFile->pLock is shared across threads
- */
+ */
enterMutex();
/* Make sure the current thread owns the pFile.
- */
+ */
rc = transferOwnership(pFile);
if( rc!=SQLITE_OK ){
leaveMutex();
return rc;
}
/* A PENDING lock is needed before acquiring a SHARED lock and before
- ** acquiring an EXCLUSIVE lock. For the SHARED lock, the PENDING will
- ** be released.
- */
+ ** acquiring an EXCLUSIVE lock. For the SHARED lock, the PENDING will
+ ** be released.
+ */
if( locktype==SHARED_LOCK
|| (locktype==EXCLUSIVE_LOCK && pFile->locktype<PENDING_LOCK)
- ){
- int failed = _AFPFSSetLock(context->filePath, pFile->h,
- PENDING_BYTE, 1, 1);
+ ){
+ int failed;
+ failed = _AFPFSSetLock(context->filePath, pFile->h, PENDING_BYTE, 1, 1);
if (failed) {
rc = SQLITE_BUSY;
goto afp_end_lock;
}
}
/* If control gets to this point, then actually go ahead and make
- ** operating system calls for the specified lock.
- */
+ ** operating system calls for the specified lock.
+ */
if( locktype==SHARED_LOCK ){
int lk, failed;
int tries = 0;
@@ -18587,21 +20545,21 @@
pFile->locktype = PENDING_LOCK;
}
afp_end_lock:
- leaveMutex();
+ leaveMutex();
OSTRACE4("LOCK %d %s %s\n", pFile->h, locktypeName(locktype),
rc==SQLITE_OK ? "ok" : "failed");
return rc;
}
/*
- ** Lower the locking level on file descriptor pFile to locktype. locktype
- ** must be either NO_LOCK or SHARED_LOCK.
- **
- ** If the locking level of the file descriptor is already at or below
- ** the requested locking level, this routine is a no-op.
- */
+** Lower the locking level on file descriptor pFile to locktype. locktype
+** must be either NO_LOCK or SHARED_LOCK.
+**
+** If the locking level of the file descriptor is already at or below
+** the requested locking level, this routine is a no-op.
+*/
static int afpUnixUnlock(sqlite3_file *id, int locktype) {
struct flock lock;
int rc = SQLITE_OK;
unixFile *pFile = (unixFile*)id;
@@ -18666,39 +20624,36 @@
return rc;
}
/*
- ** Close a file & cleanup AFP specific locking context
- */
-static int afpUnixClose(sqlite3_file *id) {
- unixFile *pFile = (unixFile*)pId;
+** Close a file & cleanup AFP specific locking context
+*/
+static int afpUnixClose(sqlite3_file *id) {
+ unixFile *pFile = (unixFile*)id;
if( !pFile ) return SQLITE_OK;
- afpUnixUnlock(*pId, NO_LOCK);
- /* free the AFP locking structure */
- if (pFile->lockingContext != NULL) {
- if (((afpLockingContext *)pFile->lockingContext)->filePath != NULL)
- sqlite3_free(((afpLockingContext*)pFile->lockingContext)->filePath);
- sqlite3_free(pFile->lockingContext);
- }
-
+ afpUnixUnlock(id, NO_LOCK);
+ sqlite3_free(pFile->lockingContext);
if( pFile->dirfd>=0 ) close(pFile->dirfd);
pFile->dirfd = -1;
+ enterMutex();
close(pFile->h);
+ leaveMutex();
OSTRACE2("CLOSE %-3d\n", pFile->h);
OpenCounter(-1);
+ memset(pFile, 0, sizeof(unixFile));
return SQLITE_OK;
}
#pragma mark flock() style locking
/*
- ** The flockLockingContext is not used
- */
+** The flockLockingContext is not used
+*/
typedef void flockLockingContext;
-static int flockUnixCheckReservedLock(sqlite3_file *id) {
+static int flockUnixCheckReservedLock(sqlite3_file *id){
unixFile *pFile = (unixFile*)id;
if (pFile->locktype == RESERVED_LOCK) {
return 1; /* already have a reserved lock */
@@ -18762,33 +20717,34 @@
}
}
/*
- ** Close a file.
- */
-static int flockUnixClose(sqlite3_file *pId) {
- unixFile *pFile = (unixFile*)*pId;
+** Close a file.
+*/
+static int flockUnixClose(sqlite3_file *id) {
+ unixFile *pFile = (unixFile*)id;
if( !pFile ) return SQLITE_OK;
- flockUnixUnlock(*pId, NO_LOCK);
+ flockUnixUnlock(id, NO_LOCK);
if( pFile->dirfd>=0 ) close(pFile->dirfd);
pFile->dirfd = -1;
- enterMutex();
-
+
+ enterMutex();
close(pFile->h);
leaveMutex();
OSTRACE2("CLOSE %-3d\n", pFile->h);
OpenCounter(-1);
+ memset(pFile, 0, sizeof(unixFile));
return SQLITE_OK;
}
#pragma mark Old-School .lock file based locking
/*
- ** The dotlockLockingContext structure contains all dotlock (.lock) lock
- ** specific state
- */
+** The dotlockLockingContext structure contains all dotlock (.lock) lock
+** specific state
+*/
typedef struct dotlockLockingContext dotlockLockingContext;
struct dotlockLockingContext {
char *lockPath;
};
@@ -18795,28 +20751,31 @@
static int dotlockUnixCheckReservedLock(sqlite3_file *id) {
unixFile *pFile = (unixFile*)id;
- dotlockLockingContext *context =
- (dotlockLockingContext *) pFile->lockingContext;
-
+ dotlockLockingContext *context;
+
+ context = (dotlockLockingContext*)pFile->lockingContext;
if (pFile->locktype == RESERVED_LOCK) {
return 1; /* already have a reserved lock */
} else {
struct stat statBuf;
- if (lstat(context->lockPath,&statBuf) == 0)
+ if (lstat(context->lockPath,&statBuf) == 0){
/* file exists, someone else has the lock */
return 1;
- else
+ }else{
/* file does not exist, we could have it if we want it */
return 0;
+ }
}
}
static int dotlockUnixLock(sqlite3_file *id, int locktype) {
unixFile *pFile = (unixFile*)id;
- dotlockLockingContext *context =
- (dotlockLockingContext *) pFile->lockingContext;
+ dotlockLockingContext *context;
+ int fd;
+
+ context = (dotlockLockingContext*)pFile->lockingContext;
/* if we already have a lock, it is exclusive.
** Just adjust level and punt on outta here. */
if (pFile->locktype > NO_LOCK) {
@@ -18833,10 +20792,10 @@
return SQLITE_BUSY; /* it does, busy */
}
/* grab an exclusive lock */
- int fd = open(context->lockPath,O_RDONLY|O_CREAT|O_EXCL,0600);
- if (fd < 0) {
+ fd = open(context->lockPath,O_RDONLY|O_CREAT|O_EXCL,0600);
+ if( fd<0 ){
/* failed to open/create the file, someone else may have stolen the lock */
return SQLITE_BUSY;
}
close(fd);
@@ -18847,10 +20806,11 @@
}
static int dotlockUnixUnlock(sqlite3_file *id, int locktype) {
unixFile *pFile = (unixFile*)id;
- dotlockLockingContext *context =
- (dotlockLockingContext *) pFile->lockingContext;
+ dotlockLockingContext *context;
+
+ context = (dotlockLockingContext*)pFile->lockingContext;
assert( locktype<=SHARED_LOCK );
/* no-op if possible */
@@ -18876,35 +20836,27 @@
static int dotlockUnixClose(sqlite3_file *id) {
unixFile *pFile = (unixFile*)id;
if( !pFile ) return SQLITE_OK;
- dotlockUnixUnlock(*pId, NO_LOCK);
- /* free the dotlock locking structure */
- if (pFile->lockingContext != NULL) {
- if (((dotlockLockingContext *)pFile->lockingContext)->lockPath != NULL)
- sqlite3_free( ( (dotlockLockingContext *)
- pFile->lockingContext)->lockPath);
- sqlite3_free(pFile->lockingContext);
- }
-
+ dotlockUnixUnlock(id, NO_LOCK);
+ sqlite3_free(pFile->lockingContext);
if( pFile->dirfd>=0 ) close(pFile->dirfd);
pFile->dirfd = -1;
enterMutex();
-
- close(pFile->h);
-
+ close(pFile->h);
leaveMutex();
OSTRACE2("CLOSE %-3d\n", pFile->h);
OpenCounter(-1);
+ memset(pFile, 0, sizeof(unixFile));
return SQLITE_OK;
}
#pragma mark No locking
/*
- ** The nolockLockingContext is void
- */
+** The nolockLockingContext is void
+*/
typedef void nolockLockingContext;
static int nolockUnixCheckReservedLock(sqlite3_file *id) {
return 0;
@@ -18918,23 +20870,22 @@
return SQLITE_OK;
}
/*
- ** Close a file.
- */
+** Close a file.
+*/
static int nolockUnixClose(sqlite3_file *id) {
unixFile *pFile = (unixFile*)id;
if( !pFile ) return SQLITE_OK;
if( pFile->dirfd>=0 ) close(pFile->dirfd);
pFile->dirfd = -1;
enterMutex();
-
- close(pFile->h);
-
+ close(pFile->h);
leaveMutex();
OSTRACE2("CLOSE %-3d\n", pFile->h);
OpenCounter(-1);
+ memset(pFile, 0, sizeof(unixFile));
return SQLITE_OK;
}
#endif /* SQLITE_ENABLE_LOCKING_STYLE */
@@ -19000,9 +20951,9 @@
** for unix with AFP style file locking.
*/
static const sqlite3_io_methods sqlite3AFPLockingUnixIoMethod = {
1, /* iVersion */
- unixClose,
+ afpUnixClose,
unixRead,
unixWrite,
unixTruncate,
unixSync,
@@ -19056,9 +21007,9 @@
};
/*
** This vector defines all the methods that can operate on an sqlite3_file
-** for unix with dotlock style file locking.
+** for unix with nolock style file locking.
*/
static const sqlite3_io_methods sqlite3NolockLockingUnixIoMethod = {
1, /* iVersion */
nolockUnixClose,
@@ -19091,90 +21042,95 @@
*/
static int fillInUnixFile(
int h, /* Open file descriptor of file being opened */
int dirfd, /* Directory file descriptor */
- sqlite3_file *pId, /* Write completed initialization here */
- const char *zFilename, /* Name of the file being opened */
+ sqlite3_file *pId, /* Write to the unixFile structure here */
+ const char *zFilename /* Name of the file being opened */
){
sqlite3LockingStyle lockingStyle;
unixFile *pNew = (unixFile *)pId;
int rc;
- memset(pNew, 0, sizeof(unixFile));
+#ifdef FD_CLOEXEC
+ fcntl(h, F_SETFD, fcntl(h, F_GETFD, 0) | FD_CLOEXEC);
+#endif
+
lockingStyle = sqlite3DetectLockingStyle(zFilename, h);
- if ( lockingStyle == posixLockingStyle ) {
+ if ( lockingStyle==posixLockingStyle ){
enterMutex();
rc = findLockInfo(h, &pNew->pLock, &pNew->pOpen);
leaveMutex();
if( rc ){
+ if( dirfd>=0 ) close(dirfd);
close(h);
- unlink(zFilename);
- return SQLITE_NOMEM;
+ return rc;
}
} else {
/* pLock and pOpen are only used for posix advisory locking */
pNew->pLock = NULL;
pNew->pOpen = NULL;
}
+
+ OSTRACE3("OPEN %-3d %s\n", h, zFilename);
pNew->dirfd = -1;
pNew->h = h;
+ pNew->dirfd = dirfd;
SET_THREADID(pNew);
- pNew = sqlite3_malloc( sizeof(unixFile) );
- if( pNew==0 ){
- close(h);
- enterMutex();
- releaseLockInfo(pNew->pLock);
- releaseOpenCnt(pNew->pOpen);
- leaveMutex();
- return SQLITE_NOMEM;
- }else{
- switch(lockingStyle) {
- case afpLockingStyle: {
- /* afp locking uses the file path so it needs to be included in
- ** the afpLockingContext */
- int nFilename;
- pNew->pMethod = &sqlite3AFPLockingUnixIoMethod;
- pNew->lockingContext =
- sqlite3_malloc(sizeof(afpLockingContext));
- nFilename = strlen(zFilename)+1;
- ((afpLockingContext *)pNew->lockingContext)->filePath =
- sqlite3_malloc(nFilename);
- memcpy(((afpLockingContext *)pNew->lockingContext)->filePath,
- zFilename, nFilename);
- srandomdev();
- break;
- }
- case flockLockingStyle:
- /* flock locking doesn't need additional lockingContext information */
- pNew->pMethod = &sqlite3FlockLockingUnixIoMethod;
- break;
- case dotlockLockingStyle: {
- /* dotlock locking uses the file path so it needs to be included in
- ** the dotlockLockingContext */
- int nFilename;
- pNew->pMethod = &sqlite3DotlockLockingUnixIoMethod;
- pNew->lockingContext = sqlite3_malloc(
- sizeof(dotlockLockingContext));
- nFilename = strlen(zFilename) + 6;
- ((dotlockLockingContext *)pNew->lockingContext)->lockPath =
- sqlite3_malloc( nFilename );
- sqlite3_snprintf(nFilename,
- ((dotlockLockingContext *)pNew->lockingContext)->lockPath,
- "%s.lock", zFilename);
- break;
- }
- case posixLockingStyle:
- /* posix locking doesn't need additional lockingContext information */
- pNew->pMethod = &sqlite3UnixIoMethod;
- break;
- case noLockingStyle:
- case unsupportedLockingStyle:
- default:
- pNew->pMethod = &sqlite3NolockLockingUnixIoMethod;
- }
- OpenCounter(+1);
- return SQLITE_OK;
- }
+
+ switch(lockingStyle) {
+ case afpLockingStyle: {
+ /* afp locking uses the file path so it needs to be included in
+ ** the afpLockingContext */
+ afpLockingContext *context;
+ pNew->pMethod = &sqlite3AFPLockingUnixIoMethod;
+ pNew->lockingContext = context = sqlite3_malloc( sizeof(*context) );
+ if( context==0 ){
+ close(h);
+ if( dirfd>=0 ) close(dirfd);
+ return SQLITE_NOMEM;
+ }
+
+ /* NB: zFilename exists and remains valid until the file is closed
+ ** according to requirement F11141. So we do not need to make a
+ ** copy of the filename. */
+ context->filePath = zFilename;
+ srandomdev();
+ break;
+ }
+ case flockLockingStyle:
+ /* flock locking doesn't need additional lockingContext information */
+ pNew->pMethod = &sqlite3FlockLockingUnixIoMethod;
+ break;
+ case dotlockLockingStyle: {
+ /* dotlock locking uses the file path so it needs to be included in
+ ** the dotlockLockingContext */
+ dotlockLockingContext *context;
+ int nFilename;
+ nFilename = strlen(zFilename);
+ pNew->pMethod = &sqlite3DotlockLockingUnixIoMethod;
+ pNew->lockingContext = context =
+ sqlite3_malloc( sizeof(*context) + nFilename + 6 );
+ if( context==0 ){
+ close(h);
+ if( dirfd>=0 ) close(dirfd);
+ return SQLITE_NOMEM;
+ }
+ context->lockPath = (char*)&context[1];
+ sqlite3_snprintf(nFilename, context->lockPath,
+ "%s.lock", zFilename);
+ break;
+ }
+ case posixLockingStyle:
+ /* posix locking doesn't need additional lockingContext information */
+ pNew->pMethod = &sqlite3UnixIoMethod;
+ break;
+ case noLockingStyle:
+ case unsupportedLockingStyle:
+ default:
+ pNew->pMethod = &sqlite3NolockLockingUnixIoMethod;
+ }
+ OpenCounter(+1);
+ return SQLITE_OK;
}
#else /* SQLITE_ENABLE_LOCKING_STYLE */
static int fillInUnixFile(
int h, /* Open file descriptor on file being opened */
@@ -19194,9 +21150,9 @@
leaveMutex();
if( rc ){
if( dirfd>=0 ) close(dirfd);
close(h);
- return SQLITE_NOMEM;
+ return rc;
}
OSTRACE3("OPEN %-3d %s\n", h, zFilename);
pNew->dirfd = -1;
@@ -19436,16 +21392,21 @@
if( access(azDirs[i], 07) ) continue;
zDir = azDirs[i];
break;
}
- if( strlen(zDir) - sizeof(SQLITE_TEMP_FILE_PREFIX) - 17 <=0 ){
- return SQLITE_ERROR;
- }
+
+ /* Check that the output buffer is large enough for the temporary file
+ ** name. If it is not, return SQLITE_ERROR.
+ */
+ if( (strlen(zDir) + strlen(SQLITE_TEMP_FILE_PREFIX) + 17) >= nBuf ){
+ return SQLITE_ERROR;
+ }
+
do{
assert( pVfs->mxPathname==MAX_PATHNAME );
sqlite3_snprintf(nBuf-17, zBuf, "%s/"SQLITE_TEMP_FILE_PREFIX, zDir);
j = strlen(zBuf);
- sqlite3Randomness(15, &zBuf[j]);
+ sqlite3_randomness(15, &zBuf[j]);
for(i=0; i<15; i++, j++){
zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ];
}
zBuf[j] = 0;
@@ -19783,18 +21744,18 @@
SQLITE_API unsigned int sqlite3_pending_byte = 0x40000000;
#endif
#ifdef SQLITE_DEBUG
-SQLITE_API int sqlite3_os_trace = 0;
-#define OSTRACE1(X) if( sqlite3_os_trace ) sqlite3DebugPrintf(X)
-#define OSTRACE2(X,Y) if( sqlite3_os_trace ) sqlite3DebugPrintf(X,Y)
-#define OSTRACE3(X,Y,Z) if( sqlite3_os_trace ) sqlite3DebugPrintf(X,Y,Z)
-#define OSTRACE4(X,Y,Z,A) if( sqlite3_os_trace ) sqlite3DebugPrintf(X,Y,Z,A)
-#define OSTRACE5(X,Y,Z,A,B) if( sqlite3_os_trace ) sqlite3DebugPrintf(X,Y,Z,A,B)
+SQLITE_PRIVATE int sqlite3OSTrace = 0;
+#define OSTRACE1(X) if( sqlite3OSTrace ) sqlite3DebugPrintf(X)
+#define OSTRACE2(X,Y) if( sqlite3OSTrace ) sqlite3DebugPrintf(X,Y)
+#define OSTRACE3(X,Y,Z) if( sqlite3OSTrace ) sqlite3DebugPrintf(X,Y,Z)
+#define OSTRACE4(X,Y,Z,A) if( sqlite3OSTrace ) sqlite3DebugPrintf(X,Y,Z,A)
+#define OSTRACE5(X,Y,Z,A,B) if( sqlite3OSTrace ) sqlite3DebugPrintf(X,Y,Z,A,B)
#define OSTRACE6(X,Y,Z,A,B,C) \
- if(sqlite3_os_trace) sqlite3DebugPrintf(X,Y,Z,A,B,C)
+ if(sqlite3OSTrace) sqlite3DebugPrintf(X,Y,Z,A,B,C)
#define OSTRACE7(X,Y,Z,A,B,C,D) \
- if(sqlite3_os_trace) sqlite3DebugPrintf(X,Y,Z,A,B,C,D)
+ if(sqlite3OSTrace) sqlite3DebugPrintf(X,Y,Z,A,B,C,D)
#else
#define OSTRACE1(X)
#define OSTRACE2(X,Y)
#define OSTRACE3(X,Y,Z)
@@ -19832,21 +21793,24 @@
** of code will give us the ability to simulate a disk I/O error. This
** is used for testing the I/O recovery logic.
*/
#ifdef SQLITE_TEST
-SQLITE_API int sqlite3_io_error_hit = 0;
-SQLITE_API int sqlite3_io_error_pending = 0;
-SQLITE_API int sqlite3_io_error_persist = 0;
+SQLITE_API int sqlite3_io_error_hit = 0; /* Total number of I/O Errors */
+SQLITE_API int sqlite3_io_error_hardhit = 0; /* Number of non-benign errors */
+SQLITE_API int sqlite3_io_error_pending = 0; /* Count down to first I/O error */
+SQLITE_API int sqlite3_io_error_persist = 0; /* True if I/O errors persist */
+SQLITE_API int sqlite3_io_error_benign = 0; /* True if errors are benign */
SQLITE_API int sqlite3_diskfull_pending = 0;
SQLITE_API int sqlite3_diskfull = 0;
+#define SimulateIOErrorBenign(X) sqlite3_io_error_benign=(X)
#define SimulateIOError(CODE) \
- if( sqlite3_io_error_pending || sqlite3_io_error_hit ) \
- if( sqlite3_io_error_pending-- == 1 \
- || (sqlite3_io_error_persist && sqlite3_io_error_hit) ) \
- { local_ioerr(); 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 = 1;
+ 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 ){ \
@@ -19858,8 +21822,9 @@
sqlite3_diskfull_pending--; \
} \
}
#else
+#define SimulateIOErrorBenign(X)
#define SimulateIOError(A)
#define SimulateDiskfullError(A)
#endif
@@ -20420,11 +22385,19 @@
do{
rc = CloseHandle(pFile->h);
}while( rc==0 && cnt++ < MX_CLOSE_ATTEMPT && (Sleep(100), 1) );
#if OS_WINCE
+#define WINCE_DELETION_ATTEMPTS 3
winceDestroyLock(pFile);
if( pFile->zDeleteOnClose ){
- DeleteFileW(pFile->zDeleteOnClose);
+ int cnt = 0;
+ while(
+ DeleteFileW(pFile->zDeleteOnClose)==0
+ && GetFileAttributesW(pFile->zDeleteOnClose)!=0xffffffff
+ && cnt++ < WINCE_DELETION_ATTEMPTS
+ ){
+ Sleep(100); /* Wait a little before trying again */
+ }
free(pFile->zDeleteOnClose);
}
#endif
OpenCounter(-1);
@@ -20586,9 +22559,9 @@
res = LockFileEx(pFile->h, LOCKFILE_FAIL_IMMEDIATELY,
0, SHARED_SIZE, 0, &ovlp);
}else{
int lk;
- sqlite3Randomness(sizeof(lk), &lk);
+ sqlite3_randomness(sizeof(lk), &lk);
pFile->sharedLockByte = (lk & 0x7fffffff)%(SHARED_SIZE - 1);
res = LockFile(pFile->h, SHARED_FIRST+pFile->sharedLockByte, 0, 1, 0);
}
return res;
@@ -21120,9 +23093,9 @@
zTempPath[i] = 0;
sqlite3_snprintf(nBuf-30, zBuf,
"%s\\"SQLITE_TEMP_FILE_PREFIX, zTempPath);
j = strlen(zBuf);
- sqlite3Randomness(20, &zBuf[j]);
+ sqlite3_randomness(20, &zBuf[j]);
for(i=0; i<20; i++, j++){
zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ];
}
zBuf[j] = 0;
@@ -21371,8 +23344,335 @@
#endif /* OS_WIN */
/************** End of os_win.c **********************************************/
+/************** Begin file bitvec.c ******************************************/
+/*
+** 2008 February 16
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+** This file implements an object that represents a fixed-length
+** bitmap. Bits are numbered starting with 1.
+**
+** A bitmap is used to record what pages a database file have been
+** journalled during a transaction. Usually only a few pages are
+** journalled. So the bitmap is usually sparse and has low cardinality.
+** But sometimes (for example when during a DROP of a large table) most
+** or all of the pages get journalled. In those cases, the bitmap becomes
+** dense. The algorithm needs to handle both cases well.
+**
+** The size of the bitmap is fixed when the object is created.
+**
+** All bits are clear when the bitmap is created. Individual bits
+** may be set or cleared one at a time.
+**
+** Test operations are about 100 times more common that set operations.
+** Clear operations are exceedingly rare. There are usually between
+** 5 and 500 set operations per Bitvec object, though the number of sets can
+** sometimes grow into tens of thousands or larger. The size of the
+** Bitvec object is the number of pages in the database file at the
+** start of a transaction, and is thus usually less than a few thousand,
+** but can be as large as 2 billion for a really big database.
+**
+** @(#) $Id: bitvec.c,v 1.5 2008/05/13 13:27:34 drh Exp $
+*/
+
+#define BITVEC_SZ 512
+/* Round the union size down to the nearest pointer boundary, since that's how
+** it will be aligned within the Bitvec struct. */
+#define BITVEC_USIZE (((BITVEC_SZ-12)/sizeof(Bitvec*))*sizeof(Bitvec*))
+#define BITVEC_NCHAR BITVEC_USIZE
+#define BITVEC_NBIT (BITVEC_NCHAR*8)
+#define BITVEC_NINT (BITVEC_USIZE/4)
+#define BITVEC_MXHASH (BITVEC_NINT/2)
+#define BITVEC_NPTR (BITVEC_USIZE/sizeof(Bitvec *))
+
+#define BITVEC_HASH(X) (((X)*37)%BITVEC_NINT)
+
+/*
+** A bitmap is an instance of the following structure.
+**
+** This bitmap records the existance of zero or more bits
+** with values between 1 and iSize, inclusive.
+**
+** There are three possible representations of the bitmap.
+** If iSize<=BITVEC_NBIT, then Bitvec.u.aBitmap[] is a straight
+** bitmap. The least significant bit is bit 1.
+**
+** If iSize>BITVEC_NBIT and iDivisor==0 then Bitvec.u.aHash[] is
+** a hash table that will hold up to BITVEC_MXHASH distinct values.
+**
+** Otherwise, the value i is redirected into one of BITVEC_NPTR
+** sub-bitmaps pointed to by Bitvec.u.apSub[]. Each subbitmap
+** handles up to iDivisor separate values of i. apSub[0] holds
+** values between 1 and iDivisor. apSub[1] holds values between
+** iDivisor+1 and 2*iDivisor. apSub[N] holds values between
+** N*iDivisor+1 and (N+1)*iDivisor. Each subbitmap is normalized
+** to hold deal with values between 1 and iDivisor.
+*/
+struct Bitvec {
+ u32 iSize; /* Maximum bit index */
+ u32 nSet; /* Number of bits that are set */
+ u32 iDivisor; /* Number of bits handled by each apSub[] entry */
+ union {
+ u8 aBitmap[BITVEC_NCHAR]; /* Bitmap representation */
+ u32 aHash[BITVEC_NINT]; /* Hash table representation */
+ Bitvec *apSub[BITVEC_NPTR]; /* Recursive representation */
+ } u;
+};
+
+/*
+** Create a new bitmap object able to handle bits between 0 and iSize,
+** inclusive. Return a pointer to the new object. Return NULL if
+** malloc fails.
+*/
+SQLITE_PRIVATE Bitvec *sqlite3BitvecCreate(u32 iSize){
+ Bitvec *p;
+ assert( sizeof(*p)==BITVEC_SZ );
+ p = sqlite3MallocZero( sizeof(*p) );
+ if( p ){
+ p->iSize = iSize;
+ }
+ return p;
+}
+
+/*
+** Check to see if the i-th bit is set. Return true or false.
+** If p is NULL (if the bitmap has not been created) or if
+** i is out of range, then return false.
+*/
+SQLITE_PRIVATE int sqlite3BitvecTest(Bitvec *p, u32 i){
+ if( p==0 ) return 0;
+ if( i>p->iSize || i==0 ) return 0;
+ if( p->iSize<=BITVEC_NBIT ){
+ i--;
+ return (p->u.aBitmap[i/8] & (1<<(i&7)))!=0;
+ }
+ if( p->iDivisor>0 ){
+ u32 bin = (i-1)/p->iDivisor;
+ i = (i-1)%p->iDivisor + 1;
+ return sqlite3BitvecTest(p->u.apSub[bin], i);
+ }else{
+ u32 h = BITVEC_HASH(i);
+ while( p->u.aHash[h] ){
+ if( p->u.aHash[h]==i ) return 1;
+ h++;
+ if( h>=BITVEC_NINT ) h = 0;
+ }
+ return 0;
+ }
+}
+
+/*
+** Set the i-th bit. Return 0 on success and an error code if
+** anything goes wrong.
+*/
+SQLITE_PRIVATE int sqlite3BitvecSet(Bitvec *p, u32 i){
+ u32 h;
+ assert( p!=0 );
+ assert( i>0 );
+ assert( i<=p->iSize );
+ if( p->iSize<=BITVEC_NBIT ){
+ i--;
+ p->u.aBitmap[i/8] |= 1 << (i&7);
+ return SQLITE_OK;
+ }
+ if( p->iDivisor ){
+ u32 bin = (i-1)/p->iDivisor;
+ i = (i-1)%p->iDivisor + 1;
+ if( p->u.apSub[bin]==0 ){
+ sqlite3FaultBeginBenign(SQLITE_FAULTINJECTOR_MALLOC);
+ p->u.apSub[bin] = sqlite3BitvecCreate( p->iDivisor );
+ sqlite3FaultEndBenign(SQLITE_FAULTINJECTOR_MALLOC);
+ if( p->u.apSub[bin]==0 ) return SQLITE_NOMEM;
+ }
+ return sqlite3BitvecSet(p->u.apSub[bin], i);
+ }
+ h = BITVEC_HASH(i);
+ while( p->u.aHash[h] ){
+ if( p->u.aHash[h]==i ) return SQLITE_OK;
+ h++;
+ if( h==BITVEC_NINT ) h = 0;
+ }
+ p->nSet++;
+ if( p->nSet>=BITVEC_MXHASH ){
+ int j, rc;
+ u32 aiValues[BITVEC_NINT];
+ memcpy(aiValues, p->u.aHash, sizeof(aiValues));
+ memset(p->u.apSub, 0, sizeof(p->u.apSub[0])*BITVEC_NPTR);
+ p->iDivisor = (p->iSize + BITVEC_NPTR - 1)/BITVEC_NPTR;
+ rc = sqlite3BitvecSet(p, i);
+ for(j=0; j<BITVEC_NINT; j++){
+ if( aiValues[j] ) rc |= sqlite3BitvecSet(p, aiValues[j]);
+ }
+ return rc;
+ }
+ p->u.aHash[h] = i;
+ return SQLITE_OK;
+}
+
+/*
+** Clear the i-th bit. Return 0 on success and an error code if
+** anything goes wrong.
+*/
+SQLITE_PRIVATE void sqlite3BitvecClear(Bitvec *p, u32 i){
+ assert( p!=0 );
+ assert( i>0 );
+ if( p->iSize<=BITVEC_NBIT ){
+ i--;
+ p->u.aBitmap[i/8] &= ~(1 << (i&7));
+ }else if( p->iDivisor ){
+ u32 bin = (i-1)/p->iDivisor;
+ i = (i-1)%p->iDivisor + 1;
+ if( p->u.apSub[bin] ){
+ sqlite3BitvecClear(p->u.apSub[bin], i);
+ }
+ }else{
+ int j;
+ u32 aiValues[BITVEC_NINT];
+ memcpy(aiValues, p->u.aHash, sizeof(aiValues));
+ memset(p->u.aHash, 0, sizeof(p->u.aHash[0])*BITVEC_NINT);
+ p->nSet = 0;
+ for(j=0; j<BITVEC_NINT; j++){
+ if( aiValues[j] && aiValues[j]!=i ){
+ sqlite3BitvecSet(p, aiValues[j]);
+ }
+ }
+ }
+}
+
+/*
+** Destroy a bitmap object. Reclaim all memory used.
+*/
+SQLITE_PRIVATE void sqlite3BitvecDestroy(Bitvec *p){
+ if( p==0 ) return;
+ if( p->iDivisor ){
+ int i;
+ for(i=0; i<BITVEC_NPTR; i++){
+ sqlite3BitvecDestroy(p->u.apSub[i]);
+ }
+ }
+ sqlite3_free(p);
+}
+
+#ifndef SQLITE_OMIT_BUILTIN_TEST
+/*
+** Let V[] be an array of unsigned characters sufficient to hold
+** up to N bits. Let I be an integer between 0 and N. 0<=I<N.
+** Then the following macros can be used to set, clear, or test
+** individual bits within V.
+*/
+#define SETBIT(V,I) V[I>>3] |= (1<<(I&7))
+#define CLEARBIT(V,I) V[I>>3] &= ~(1<<(I&7))
+#define TESTBIT(V,I) (V[I>>3]&(1<<(I&7)))!=0
+
+/*
+** This routine runs an extensive test of the Bitvec code.
+**
+** The input is an array of integers that acts as a program
+** to test the Bitvec. The integers are opcodes followed
+** by 0, 1, or 3 operands, depending on the opcode. Another
+** opcode follows immediately after the last operand.
+**
+** There are 6 opcodes numbered from 0 through 5. 0 is the
+** "halt" opcode and causes the test to end.
+**
+** 0 Halt and return the number of errors
+** 1 N S X Set N bits beginning with S and incrementing by X
+** 2 N S X Clear N bits beginning with S and incrementing by X
+** 3 N Set N randomly chosen bits
+** 4 N Clear N randomly chosen bits
+** 5 N S X Set N bits from S increment X in array only, not in bitvec
+**
+** The opcodes 1 through 4 perform set and clear operations are performed
+** on both a Bitvec object and on a linear array of bits obtained from malloc.
+** Opcode 5 works on the linear array only, not on the Bitvec.
+** Opcode 5 is used to deliberately induce a fault in order to
+** confirm that error detection works.
+**
+** At the conclusion of the test the linear array is compared
+** against the Bitvec object. If there are any differences,
+** an error is returned. If they are the same, zero is returned.
+**
+** If a memory allocation error occurs, return -1.
+*/
+SQLITE_PRIVATE int sqlite3BitvecBuiltinTest(int sz, int *aOp){
+ Bitvec *pBitvec = 0;
+ unsigned char *pV = 0;
+ int rc = -1;
+ int i, nx, pc, op;
+
+ /* Allocate the Bitvec to be tested and a linear array of
+ ** bits to act as the reference */
+ pBitvec = sqlite3BitvecCreate( sz );
+ pV = sqlite3_malloc( (sz+7)/8 + 1 );
+ if( pBitvec==0 || pV==0 ) goto bitvec_end;
+ memset(pV, 0, (sz+7)/8 + 1);
+
+ /* Run the program */
+ pc = 0;
+ while( (op = aOp[pc])!=0 ){
+ switch( op ){
+ case 1:
+ case 2:
+ case 5: {
+ nx = 4;
+ i = aOp[pc+2] - 1;
+ aOp[pc+2] += aOp[pc+3];
+ break;
+ }
+ case 3:
+ case 4:
+ default: {
+ nx = 2;
+ sqlite3_randomness(sizeof(i), &i);
+ break;
+ }
+ }
+ if( (--aOp[pc+1]) > 0 ) nx = 0;
+ pc += nx;
+ i = (i & 0x7fffffff)%sz;
+ if( (op & 1)!=0 ){
+ SETBIT(pV, (i+1));
+ if( op!=5 ){
+ if( sqlite3BitvecSet(pBitvec, i+1) ) goto bitvec_end;
+ }
+ }else{
+ CLEARBIT(pV, (i+1));
+ sqlite3BitvecClear(pBitvec, i+1);
+ }
+ }
+
+ /* Test to make sure the linear array exactly matches the
+ ** Bitvec object. Start with the assumption that they do
+ ** match (rc==0). Change rc to non-zero if a discrepancy
+ ** is found.
+ */
+ rc = sqlite3BitvecTest(0,0) + sqlite3BitvecTest(pBitvec, sz+1)
+ + sqlite3BitvecTest(pBitvec, 0);
+ for(i=1; i<=sz; i++){
+ if( (TESTBIT(pV,i))!=sqlite3BitvecTest(pBitvec,i) ){
+ rc = i;
+ break;
+ }
+ }
+
+ /* Free allocated structure */
+bitvec_end:
+ sqlite3_free(pV);
+ sqlite3BitvecDestroy(pBitvec);
+ return rc;
+}
+#endif /* SQLITE_OMIT_BUILTIN_TEST */
+
+/************** End of bitvec.c **********************************************/
/************** Begin file pager.c *******************************************/
/*
** 2001 September 15
**
@@ -21392,9 +23692,9 @@
** locking to prevent two processes from writing the same database
** file simultaneously, or one process from reading the database while
** another is writing.
**
-** @(#) $Id: pager.c,v 1.404 2008/01/22 21:30:53 drh Exp $
+** @(#) $Id: pager.c,v 1.446 2008/05/13 13:27:34 drh Exp $
*/
#ifndef SQLITE_OMIT_DISKIO
/*
@@ -21584,11 +23884,11 @@
** And this flag says nothing about whether or not the journal
** has been synced to disk. For pages that are in the original
** database file, the following expression should always be true:
**
-** inJournal = (pPager->aInJournal[(pgno-1)/8] & (1<<((pgno-1)%8))!=0
-**
-** The pPager->aInJournal[] array is only valid for the original
+** inJournal = sqlite3BitvecTest(pPager->pInJournal, pgno)
+**
+** The pPager->pInJournal object is only valid for the original
** pages of the database, not new pages that are added to the end
** of the database, so obviously the above expression cannot be
** valid for new pages. For new pages inJournal is always 0.
**
@@ -21721,8 +24021,10 @@
u8 memDb; /* True to inhibit all file I/O */
u8 setMaster; /* True if a m-j name has been written to jrnl */
u8 doNotSync; /* Boolean. While true, do not spill the cache */
u8 exclusiveMode; /* Boolean. True if locking_mode==EXCLUSIVE */
+ u8 journalMode; /* On of the PAGER_JOURNALMODE_* values */
+ u8 dbModified; /* True if there are any changes to the Db */
u8 changeCountDone; /* Set after incrementing the change-counter */
u32 vfsFlags; /* Flags for sqlite3_vfs.xOpen() */
int errCode; /* One of several kinds of errors */
int dbSize; /* Number of pages in the file */
@@ -21736,10 +24038,10 @@
int nPage; /* Total number of in-memory pages */
int nRef; /* Number of in-memory pages with PgHdr.nRef>0 */
int mxPage; /* Maximum number of pages to hold in cache */
Pgno mxPgno; /* Maximum allowed size of the database */
- u8 *aInJournal; /* One bit for each page in the database file */
- u8 *aInStmt; /* One bit for each page in the database */
+ Bitvec *pInJournal; /* One bit for each page in the database file */
+ Bitvec *pInStmt; /* One bit for each page in the database */
char *zFilename; /* Name of the database file */
char *zJournal; /* Name of the journal file */
char *zDirectory; /* Directory hold database and journal files */
char *zStmtJrnl; /* Name of the statement journal file */
@@ -21885,10 +24187,12 @@
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
static void pagerEnter(Pager *p){
p->iInUseDB++;
if( p->iInUseMM && p->iInUseDB==1 ){
+#ifndef SQLITE_MUTEX_NOOP
sqlite3_mutex *mutex;
mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MEM2);
+#endif
p->iInUseDB = 0;
sqlite3_mutex_enter(mutex);
p->iInUseDB = 1;
sqlite3_mutex_leave(mutex);
@@ -21901,27 +24205,8 @@
}
#else
# define pagerEnter(X)
# define pagerLeave(X)
-#endif
-
-/*
-** Enable reference count tracking (for debugging) here:
-*/
-#ifdef SQLITE_DEBUG
- int pager3_refinfo_enable = 0;
- static void pager_refinfo(PgHdr *p){
- static int cnt = 0;
- if( !pager3_refinfo_enable ) return;
- sqlite3DebugPrintf(
- "REFCNT: %4d addr=%p nRef=%-3d total=%d\n",
- p->pgno, PGHDR_TO_DATA(p), p->nRef, p->pPager->nRef
- );
- cnt++; /* Something to set a breakpoint on */
- }
-# define REFINFO(X) pager_refinfo(X)
-#else
-# define REFINFO(X)
#endif
/*
** Add page pPg to the end of the linked list managed by structure
@@ -22056,11 +24341,9 @@
Pager *pPager = pPg->pPager;
if( MEMDB ){
return PGHDR_TO_HIST(pPg, pPager)->inStmt;
}else{
- Pgno pgno = pPg->pgno;
- u8 *a = pPager->aInStmt;
- return (a && (int)pgno<=pPager->stmtSize && (a[pgno/8] & (1<<(pgno&7))));
+ return sqlite3BitvecTest(pPager->pInStmt, pPg->pgno);
}
}
/*
@@ -22069,12 +24352,18 @@
*/
static void pager_resize_hash_table(Pager *pPager, int N){
PgHdr **aHash, *pPg;
assert( N>0 && (N&(N-1))==0 );
- pagerLeave(pPager);
- sqlite3FaultBenign(SQLITE_FAULTINJECTOR_MALLOC, pPager->aHash!=0);
+#ifdef SQLITE_MALLOC_SOFT_LIMIT
+ if( N*sizeof(aHash[0])>SQLITE_MALLOC_SOFT_LIMIT ){
+ N = SQLITE_MALLOC_SOFT_LIMIT/sizeof(aHash[0]);
+ }
+ if( N==pPager->nHash ) return;
+#endif
+ pagerLeave(pPager);
+ if( pPager->aHash!=0 ) sqlite3FaultBeginBenign(SQLITE_FAULTINJECTOR_MALLOC);
aHash = sqlite3MallocZero( sizeof(aHash[0])*N );
- sqlite3FaultBenign(SQLITE_FAULTINJECTOR_MALLOC, 0);
+ if( pPager->aHash!=0 ) sqlite3FaultEndBenign(SQLITE_FAULTINJECTOR_MALLOC);
pagerEnter(pPager);
if( aHash==0 ){
/* Failure to rehash is not an error. It is only a performance hit. */
return;
@@ -22347,8 +24636,31 @@
pPager->journalOff = offset;
}
/*
+** Write zeros over the header of the journal file. This has the
+** effect of invalidating the journal file and committing the
+** transaction.
+*/
+static int zeroJournalHdr(Pager *pPager, int doTruncate){
+ int rc = SQLITE_OK;
+ static const char zeroHdr[28];
+
+ if( pPager->journalOff ){
+ IOTRACE(("JZEROHDR %p\n", pPager))
+ if( doTruncate ){
+ rc = sqlite3OsTruncate(pPager->jfd, 0);
+ }else{
+ rc = sqlite3OsWrite(pPager->jfd, zeroHdr, sizeof(zeroHdr), 0);
+ }
+ if( rc==SQLITE_OK ){
+ rc = sqlite3OsSync(pPager->jfd, SQLITE_SYNC_DATAONLY|pPager->sync_flags);
+ }
+ }
+ return rc;
+}
+
+/*
** The journal file must be open when this routine is called. A journal
** header (JOURNAL_HDR_SZ bytes) is written into the journal file at the
** current location.
**
@@ -22357,14 +24669,21 @@
** - 4 bytes: Number of records in journal, or -1 no-sync mode is on.
** - 4 bytes: Random number used for page hash.
** - 4 bytes: Initial database page count.
** - 4 bytes: Sector size used by the process that wrote this journal.
-**
-** Followed by (JOURNAL_HDR_SZ - 24) bytes of unused space.
+** - 4 bytes: Database page size.
+**
+** Followed by (JOURNAL_HDR_SZ - 28) bytes of unused space.
*/
static int writeJournalHdr(Pager *pPager){
- char zHeader[sizeof(aJournalMagic)+16];
- int rc;
+ int rc = SQLITE_OK;
+ char *zHeader = pPager->pTmpSpace;
+ int nHeader = pPager->pageSize;
+ int nWrite;
+
+ if( nHeader>JOURNAL_HDR_SZ(pPager) ){
+ nHeader = JOURNAL_HDR_SZ(pPager);
+ }
if( pPager->stmtHdrOff==0 ){
pPager->stmtHdrOff = pPager->journalOff;
}
@@ -22403,25 +24722,25 @@
put32bits(&zHeader[sizeof(aJournalMagic)], 0);
}
/* The random check-hash initialiser */
- sqlite3Randomness(sizeof(pPager->cksumInit), &pPager->cksumInit);
+ sqlite3_randomness(sizeof(pPager->cksumInit), &pPager->cksumInit);
put32bits(&zHeader[sizeof(aJournalMagic)+4], pPager->cksumInit);
/* The initial database size */
put32bits(&zHeader[sizeof(aJournalMagic)+8], pPager->dbSize);
/* The assumed sector size for this process */
put32bits(&zHeader[sizeof(aJournalMagic)+12], pPager->sectorSize);
- IOTRACE(("JHDR %p %lld %d\n", pPager, pPager->journalHdr, sizeof(zHeader)))
- rc = sqlite3OsWrite(pPager->jfd, zHeader, sizeof(zHeader),pPager->journalOff);
- pPager->journalOff += JOURNAL_HDR_SZ(pPager);
-
- /* The journal header has been written successfully. Seek the journal
- ** file descriptor to the end of the journal header sector.
- */
- if( rc==SQLITE_OK ){
- IOTRACE(("JTAIL %p %lld\n", pPager, pPager->journalOff-1))
- rc = sqlite3OsWrite(pPager->jfd, "\000", 1, pPager->journalOff-1);
- }
+ if( pPager->journalHdr==0 ){
+ /* The page size */
+ put32bits(&zHeader[sizeof(aJournalMagic)+16], pPager->pageSize);
+ }
+
+ for(nWrite=0; rc==SQLITE_OK&&nWrite<JOURNAL_HDR_SZ(pPager); nWrite+=nHeader){
+ IOTRACE(("JHDR %p %lld %d\n", pPager, pPager->journalHdr, nHeader))
+ rc = sqlite3OsWrite(pPager->jfd, zHeader, nHeader, pPager->journalOff);
+ pPager->journalOff += nHeader;
+ }
+
return rc;
}
/*
@@ -22448,8 +24767,9 @@
){
int rc;
unsigned char aMagic[8]; /* A buffer to hold the magic header */
i64 jrnlOff;
+ int iPageSize;
seekJournalHdr(pPager);
if( pPager->journalOff+JOURNAL_HDR_SZ(pPager) > journalSize ){
return SQLITE_DONE;
@@ -22470,8 +24790,19 @@
rc = read32bits(pPager->jfd, jrnlOff+4, &pPager->cksumInit);
if( rc ) return rc;
rc = read32bits(pPager->jfd, jrnlOff+8, pDbSize);
+ if( rc ) return rc;
+
+ rc = read32bits(pPager->jfd, jrnlOff+16, (u32 *)&iPageSize);
+ if( rc==SQLITE_OK
+ && iPageSize>=512
+ && iPageSize<=SQLITE_MAX_PAGE_SIZE
+ && ((iPageSize-1)&iPageSize)==0
+ ){
+ u16 pagesize = iPageSize;
+ rc = sqlite3PagerSetPagesize(pPager, &pagesize);
+ }
if( rc ) return rc;
/* Update the assumed sector-size to match the value used by
** the process that created this journal. If this journal was
@@ -22510,8 +24841,9 @@
int rc;
int len;
int i;
i64 jrnlOff;
+ i64 jrnlSize;
u32 cksum = 0;
char zBuf[sizeof(aJournalMagic)+2*4];
if( !zMaster || pPager->setMaster) return SQLITE_OK;
@@ -22543,9 +24875,27 @@
put32bits(zBuf, len);
put32bits(&zBuf[4], cksum);
memcpy(&zBuf[8], aJournalMagic, sizeof(aJournalMagic));
rc = sqlite3OsWrite(pPager->jfd, zBuf, 8+sizeof(aJournalMagic), jrnlOff);
+ jrnlOff += 8+sizeof(aJournalMagic);
pPager->needSync = !pPager->noSync;
+
+ /* If the pager is in peristent-journal mode, then the physical
+ ** journal-file may extend past the end of the master-journal name
+ ** and 8 bytes of magic data just written to the file. This is
+ ** dangerous because the code to rollback a hot-journal file
+ ** will not be able to find the master-journal name to determine
+ ** whether or not the journal is hot.
+ **
+ ** Easiest thing to do in this scenario is to truncate the journal
+ ** file to the required size.
+ */
+ if( (rc==SQLITE_OK)
+ && (rc = sqlite3OsFileSize(pPager->jfd, &jrnlSize))==SQLITE_OK
+ && jrnlSize>jrnlOff
+ ){
+ rc = sqlite3OsTruncate(pPager->jfd, jrnlOff);
+ }
return rc;
}
/*
@@ -22599,8 +24949,9 @@
IOTRACE(("PGFREE %p %d\n", pPager, pPg->pgno));
PAGER_INCR(sqlite3_pager_pgfree_count);
pNext = pPg->pNextAll;
lruListRemove(pPg);
+ sqlite3_free(pPg->pData);
sqlite3_free(pPg);
}
assert(pPager->lru.pFirst==0);
assert(pPager->lru.pFirstSynced==0);
@@ -22626,31 +24977,35 @@
*/
static void pager_unlock(Pager *pPager){
if( !pPager->exclusiveMode ){
if( !MEMDB ){
- if( pPager->fd->pMethods ){
- osUnlock(pPager->fd, NO_LOCK);
- }
+ int rc = osUnlock(pPager->fd, NO_LOCK);
+ if( rc ) pPager->errCode = rc;
pPager->dbSize = -1;
IOTRACE(("UNLOCK %p\n", pPager))
+
+ /* Always close the journal file when dropping the database lock.
+ ** Otherwise, another connection with journal_mode=delete might
+ ** delete the file out from under us.
+ */
+ if( pPager->journalOpen ){
+ sqlite3OsClose(pPager->jfd);
+ pPager->journalOpen = 0;
+ sqlite3BitvecDestroy(pPager->pInJournal);
+ pPager->pInJournal = 0;
+ }
/* If Pager.errCode is set, the contents of the pager cache cannot be
** trusted. Now that the pager file is unlocked, the contents of the
** cache can be discarded and the error code safely cleared.
*/
if( pPager->errCode ){
- pPager->errCode = SQLITE_OK;
+ if( rc==SQLITE_OK ) pPager->errCode = SQLITE_OK;
pager_reset(pPager);
if( pPager->stmtOpen ){
sqlite3OsClose(pPager->stfd);
- sqlite3_free(pPager->aInStmt);
- pPager->aInStmt = 0;
- }
- if( pPager->journalOpen ){
- sqlite3OsClose(pPager->jfd);
- pPager->journalOpen = 0;
- sqlite3_free(pPager->aInJournal);
- pPager->aInJournal = 0;
+ sqlite3BitvecDestroy(pPager->pInStmt);
+ pPager->pInStmt = 0;
}
pPager->stmtOpen = 0;
pPager->stmtInUse = 0;
pPager->journalOff = 0;
@@ -22672,15 +25027,19 @@
** database file. If the pager has already entered the error state,
** do not attempt the rollback.
*/
static void pagerUnlockAndRollback(Pager *p){
- assert( p->state>=PAGER_RESERVED || p->journalOpen==0 );
+ /* assert( p->state>=PAGER_RESERVED || p->journalOpen==0 ); */
if( p->errCode==SQLITE_OK && p->state>=PAGER_RESERVED ){
+ sqlite3FaultBeginBenign(-1);
sqlite3PagerRollback(p);
+ sqlite3FaultEndBenign(-1);
}
pager_unlock(p);
+#if 0
assert( p->errCode || !p->journalOpen || (p->exclusiveMode&&!p->journalOff) );
assert( p->errCode || !p->stmtOpen || p->exclusiveMode );
+#endif
}
/*
** This routine ends a transaction. A transaction is ended by either
@@ -22698,9 +25057,9 @@
** TODO: Consider keeping the journal file open for temporary databases.
** This might give a performance improvement on windows where opening
** a file is an expensive operation.
*/
-static int pager_end_transaction(Pager *pPager){
+static int pager_end_transaction(Pager *pPager, int hasMaster){
PgHdr *pPg;
int rc = SQLITE_OK;
int rc2 = SQLITE_OK;
assert( !MEMDB );
@@ -22713,9 +25072,12 @@
pPager->stmtOpen = 0;
}
if( pPager->journalOpen ){
if( pPager->exclusiveMode
- && (rc = sqlite3OsTruncate(pPager->jfd, 0))==SQLITE_OK ){;
+ || pPager->journalMode==PAGER_JOURNALMODE_PERSIST
+ ){
+ rc = zeroJournalHdr(pPager, hasMaster);
+ pager_error(pPager, rc);
pPager->journalOff = 0;
pPager->journalStarted = 0;
}else{
sqlite3OsClose(pPager->jfd);
@@ -22723,10 +25085,10 @@
if( rc==SQLITE_OK ){
rc = sqlite3OsDelete(pPager->pVfs, pPager->zJournal, 0);
}
}
- sqlite3_free( pPager->aInJournal );
- pPager->aInJournal = 0;
+ sqlite3BitvecDestroy(pPager->pInJournal);
+ pPager->pInJournal = 0;
for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){
pPg->inJournal = 0;
pPg->dirty = 0;
pPg->needSync = 0;
@@ -22738,10 +25100,9 @@
pPager->pDirty = 0;
pPager->dirtyCache = 0;
pPager->nRec = 0;
}else{
- assert( pPager->aInJournal==0 );
- assert( pPager->dirtyCache==0 || pPager->useJournal==0 );
+ assert( pPager->pInJournal==0 );
}
if( !pPager->exclusiveMode ){
rc2 = osUnlock(pPager->fd, SHARED_LOCK);
@@ -22753,8 +25114,9 @@
pPager->setMaster = 0;
pPager->needSync = 0;
lruListSetFirstSynced(pPager);
pPager->dbSize = -1;
+ pPager->dbModified = 0;
return (rc==SQLITE_OK?rc2:rc);
}
@@ -22871,13 +25233,18 @@
** met before writing to the database files. (1) the database must be
** locked. (2) we know that the original page content is fully synced
** in the main journal either because the page is not in cache or else
** the page is marked as needSync==0.
+ **
+ ** 2008-04-14: When attempting to vacuum a corrupt database file, it
+ ** is possible to fail a statement on a database that does not yet exist.
+ ** Do not attempt to write if database file has never been opened.
*/
pPg = pager_lookup(pPager, pgno);
PAGERTRACE4("PLAYBACK %d page %d hash(%08x)\n",
PAGERID(pPager), pgno, pager_datahash(pPager->pageSize, aData));
- if( pPager->state>=PAGER_EXCLUSIVE && (pPg==0 || pPg->needSync==0) ){
+ if( pPager->state>=PAGER_EXCLUSIVE && (pPg==0 || pPg->needSync==0)
+ && pPager->fd->pMethods ){
i64 offset = (pgno-1)*(i64)pPager->pageSize;
rc = sqlite3OsWrite(pPager->fd, aData, pPager->pageSize, offset);
if( pPg ){
makeClean(pPg);
@@ -22971,9 +25338,14 @@
if( rc!=SQLITE_OK ) goto delmaster_out;
zJournal = zMasterJournal;
while( (zJournal-zMasterJournal)<nMasterJournal ){
- if( sqlite3OsAccess(pVfs, zJournal, SQLITE_ACCESS_EXISTS) ){
+ rc = sqlite3OsAccess(pVfs, zJournal, SQLITE_ACCESS_EXISTS);
+ if( rc!=0 && rc!=1 ){
+ rc = SQLITE_IOERR_NOMEM;
+ goto delmaster_out;
+ }
+ if( rc==1 ){
/* One of the journals pointed to by the master journal exists.
** Open it and check if it points at the master journal. If
** so, return without deleting the master journal file.
*/
@@ -23025,18 +25397,23 @@
** which has extended the file size and the new pages are still all held
** in cache, then an INSERT or UPDATE does a statement rollback. Some
** operating system implementations can get confused if you try to
** truncate a file to some size that is larger than it currently is,
-** so detect this case and do not do the truncation.
+** so detect this case and write a single zero byte to the end of the new
+** file instead.
*/
static int pager_truncate(Pager *pPager, int nPage){
int rc = SQLITE_OK;
if( pPager->state>=PAGER_EXCLUSIVE && pPager->fd->pMethods ){
i64 currentSize, newSize;
rc = sqlite3OsFileSize(pPager->fd, ¤tSize);
newSize = pPager->pageSize*(i64)nPage;
- if( rc==SQLITE_OK && currentSize>newSize ){
- rc = sqlite3OsTruncate(pPager->fd, newSize);
+ if( rc==SQLITE_OK && currentSize!=newSize ){
+ if( currentSize>newSize ){
+ rc = sqlite3OsTruncate(pPager->fd, newSize);
+ }else{
+ rc = sqlite3OsWrite(pPager->fd, "", 1, newSize-1);
+ }
}
}
if( rc==SQLITE_OK ){
pPager->dbSize = nPage;
@@ -23047,10 +25424,10 @@
/*
** Set the sectorSize for the given pager.
**
-** The sector size is the larger of the sector size reported
-** by sqlite3OsSectorSize() and the pageSize.
+** The sector size is at least as big as the sector size reported
+** by sqlite3OsSectorSize(). The minimum sector size is 512.
*/
static void setSectorSize(Pager *pPager){
assert(pPager->fd->pMethods||pPager->tempFile);
if( !pPager->tempFile ){
@@ -23059,10 +25436,10 @@
** call will segfault.
*/
pPager->sectorSize = sqlite3OsSectorSize(pPager->fd);
}
- if( pPager->sectorSize<pPager->pageSize ){
- pPager->sectorSize = pPager->pageSize;
+ if( pPager->sectorSize<512 ){
+ pPager->sectorSize = 512;
}
}
/*
@@ -23078,22 +25455,25 @@
** (3) 4 byte big-endian integer which is the initial value for the
** sanity checksum.
** (4) 4 byte integer which is the number of pages to truncate the
** database to during a rollback.
-** (5) 4 byte integer which is the number of bytes in the master journal
+** (5) 4 byte big-endian integer which is the sector size. The header
+** is this many bytes in size.
+** (6) 4 byte big-endian integer which is the page case.
+** (7) 4 byte integer which is the number of bytes in the master journal
** name. The value may be zero (indicate that there is no master
** journal.)
-** (6) N bytes of the master journal name. The name will be nul-terminated
+** (8) N bytes of the master journal name. The name will be nul-terminated
** and might be shorter than the value read from (5). If the first byte
** of the name is \000 then there is no master journal. The master
** journal name is stored in UTF-8.
-** (7) Zero or more pages instances, each as follows:
+** (9) Zero or more pages instances, each as follows:
** + 4 byte page number.
** + pPager->pageSize bytes of data.
** + 4 byte checksum
**
-** When we speak of the journal header, we mean the first 6 items above.
-** Each entry in the journal is an instance of the 7th item.
+** When we speak of the journal header, we mean the first 8 items above.
+** Each entry in the journal is an instance of the 9th item.
**
** Call the value from the second bullet "nRec". nRec is the number of
** valid page entries in the journal. In most cases, you can compute the
** value of nRec from the size of the journal file. But if a power
@@ -23124,8 +25504,9 @@
u32 nRec; /* Number of Records in the journal */
int i; /* Loop counter */
Pgno mxPg = 0; /* Size of the original file in pages */
int rc; /* Result code of a subroutine */
+ int res = 0; /* Value returned by sqlite3OsAccess() */
char *zMaster = 0; /* Name of master journal file if any */
/* Figure out how many records are in the journal. Abort early if
** the journal is empty.
@@ -23142,18 +25523,20 @@
** played back.
*/
zMaster = pPager->pTmpSpace;
rc = readMasterJournal(pPager->jfd, zMaster, pPager->pVfs->mxPathname+1);
- assert( rc!=SQLITE_DONE );
- if( rc!=SQLITE_OK
- || (zMaster[0] && !sqlite3OsAccess(pVfs, zMaster, SQLITE_ACCESS_EXISTS))
+ if( rc!=SQLITE_OK || (zMaster[0]
+ && (res=sqlite3OsAccess(pVfs, zMaster, SQLITE_ACCESS_EXISTS))==0 )
){
zMaster = 0;
- if( rc==SQLITE_DONE ) rc = SQLITE_OK;
+ goto end_playback;
+ }
+ zMaster = 0;
+ if( res<0 ){
+ rc = SQLITE_IOERR_NOMEM;
goto end_playback;
}
pPager->journalOff = 0;
- zMaster = 0;
/* This loop terminates either when the readJournalHdr() call returns
** SQLITE_DONE or an IO error occurs. */
while( 1 ){
@@ -23227,9 +25610,9 @@
zMaster = pPager->pTmpSpace;
rc = readMasterJournal(pPager->jfd, zMaster, pPager->pVfs->mxPathname+1);
}
if( rc==SQLITE_OK ){
- rc = pager_end_transaction(pPager);
+ rc = pager_end_transaction(pPager, zMaster[0]!='\0');
}
if( rc==SQLITE_OK && zMaster[0] ){
/* If there was a master journal and this routine will return success,
** see if it is possible to delete the master journal.
@@ -23266,16 +25649,8 @@
int i; /* Loop counter */
int rc;
szJ = pPager->journalOff;
-#ifndef NDEBUG
- {
- i64 os_szJ;
- rc = sqlite3OsFileSize(pPager->jfd, &os_szJ);
- if( rc!=SQLITE_OK ) return rc;
- assert( szJ==os_szJ );
- }
-#endif
/* Set hdrOff to be the offset just after the end of the last journal
** page written before the first journal-header for this statement
** transaction was written, or the end of the file if no journal
@@ -23469,15 +25844,17 @@
int journalFileSize = sqlite3JournalSize(pVfs);
int nDefaultPage = SQLITE_DEFAULT_PAGE_SIZE;
char *zPathname;
int nPathname;
+ char *zStmtJrnl;
+ int nStmtJrnl;
/* The default return is a NULL pointer */
*ppPager = 0;
/* Compute the full pathname */
nPathname = pVfs->mxPathname+1;
- zPathname = sqlite3_malloc(nPathname);
+ zPathname = sqlite3_malloc(nPathname*2);
if( zPathname==0 ){
return SQLITE_NOMEM;
}
if( zFilename && zFilename[0] ){
@@ -23498,14 +25875,28 @@
return rc;
}
nPathname = strlen(zPathname);
+ /* Put the statement journal in temporary disk space since this is
+ ** sometimes RAM disk or other optimized storage. Unlikely the main
+ ** main journal file, the statement journal does not need to be
+ ** colocated with the database nor does it need to be persistent.
+ */
+ zStmtJrnl = &zPathname[nPathname+1];
+ rc = sqlite3OsGetTempname(pVfs, pVfs->mxPathname+1, zStmtJrnl);
+ if( rc!=SQLITE_OK ){
+ sqlite3_free(zPathname);
+ return rc;
+ }
+ nStmtJrnl = strlen(zStmtJrnl);
+
/* Allocate memory for the pager structure */
pPager = sqlite3MallocZero(
sizeof(*pPager) + /* Pager structure */
journalFileSize + /* The journal file structure */
- pVfs->szOsFile * 2 + /* The db and stmt journal files */
- 4*nPathname + 40 /* zFilename, zDirectory, zJournal, zStmtJrnl */
+ pVfs->szOsFile * 3 + /* The main db and two journal files */
+ 3*nPathname + 40 + /* zFilename, zDirectory, zJournal */
+ nStmtJrnl /* zStmtJrnl */
);
if( !pPager ){
sqlite3_free(zPathname);
return SQLITE_NOMEM;
@@ -23520,8 +25911,9 @@
pPager->zJournal = &pPager->zDirectory[nPathname+1];
pPager->zStmtJrnl = &pPager->zJournal[nPathname+10];
pPager->pVfs = pVfs;
memcpy(pPager->zFilename, zPathname, nPathname+1);
+ memcpy(pPager->zStmtJrnl, zStmtJrnl, nStmtJrnl+1);
sqlite3_free(zPathname);
/* Open the pager file.
*/
@@ -23573,9 +25965,9 @@
pPager->state = PAGER_EXCLUSIVE;
}
if( pPager && rc==SQLITE_OK ){
- pPager->pTmpSpace = (char *)sqlite3_malloc(nDefaultPage);
+ pPager->pTmpSpace = sqlite3MallocZero(nDefaultPage);
}
/* If an error occured in either of the blocks above.
** Free the Pager structure and close the file.
@@ -23595,13 +25987,11 @@
memcpy(pPager->zDirectory, pPager->zFilename, nPathname+1);
for(i=strlen(pPager->zDirectory); i>0 && pPager->zDirectory[i-1]!='/'; i--){}
if( i>0 ) pPager->zDirectory[i-1] = 0;
- /* Fill in Pager.zJournal[] and Pager.zStmtJrnl[] */
+ /* Fill in Pager.zJournal[] */
memcpy(pPager->zJournal, pPager->zFilename, nPathname);
memcpy(&pPager->zJournal[nPathname], "-journal", 9);
- memcpy(pPager->zStmtJrnl, pPager->zFilename, nPathname);
- memcpy(&pPager->zStmtJrnl[nPathname], "-stmtjrnl", 10);
/* pPager->journalOpen = 0; */
pPager->useJournal = useJournal && !memDb;
pPager->noReadlock = noReadlock && readOnly;
@@ -23643,9 +26033,11 @@
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
pPager->iInUseMM = 0;
pPager->iInUseDB = 0;
if( !memDb ){
+#ifndef SQLITE_MUTEX_NOOP
sqlite3_mutex *mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MEM2);
+#endif
sqlite3_mutex_enter(mutex);
pPager->pNext = sqlite3PagerList;
if( sqlite3PagerList ){
assert( sqlite3PagerList->pPrev==0 );
@@ -23806,9 +26198,9 @@
i64 n = 0;
int rc;
assert( pPager!=0 );
if( pPager->errCode ){
- return 0;
+ return -1;
}
if( pPager->dbSize>=0 ){
n = pPager->dbSize;
} else {
@@ -23817,9 +26209,9 @@
&& (rc = sqlite3OsFileSize(pPager->fd, &n))!=SQLITE_OK ){
pPager->nRef++;
pager_error(pPager, rc);
pPager->nRef--;
- return 0;
+ return -1;
}
if( n>0 && n<pPager->pageSize ){
n = 1;
}else{
@@ -23929,8 +26321,9 @@
IOTRACE(("PGFREE %p %d\n", pPager, pPg->pgno));
PAGER_INCR(sqlite3_pager_pgfree_count);
unlinkPage(pPg);
makeClean(pPg);
+ sqlite3_free(pPg->pData);
sqlite3_free(pPg);
pPager->nPage--;
}
}
@@ -23957,8 +26350,9 @@
if( pPager->state>=locktype ){
rc = SQLITE_OK;
}else{
+ if( pPager->pBusyHandler ) pPager->pBusyHandler->nBusy = 0;
do {
rc = sqlite3OsLock(pPager->fd, locktype);
}while( rc==SQLITE_BUSY && sqlite3InvokeBusyHandler(pPager->pBusyHandler) );
if( rc==SQLITE_OK ){
@@ -24023,9 +26417,11 @@
*/
SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager){
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
if( !MEMDB ){
+#ifndef SQLITE_MUTEX_NOOP
sqlite3_mutex *mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MEM2);
+#endif
sqlite3_mutex_enter(mutex);
if( pPager->pPrev ){
pPager->pPrev->pNext = pPager->pNext;
}else{
@@ -24038,20 +26434,21 @@
}
#endif
disable_simulated_io_errors();
+ sqlite3FaultBeginBenign(-1);
pPager->errCode = 0;
pPager->exclusiveMode = 0;
pager_reset(pPager);
pagerUnlockAndRollback(pPager);
enable_simulated_io_errors();
+ sqlite3FaultEndBenign(-1);
PAGERTRACE2("CLOSE %d\n", PAGERID(pPager));
IOTRACE(("CLOSE %p\n", pPager))
- assert( pPager->errCode || (pPager->journalOpen==0 && pPager->stmtOpen==0) );
if( pPager->journalOpen ){
sqlite3OsClose(pPager->jfd);
}
- sqlite3_free(pPager->aInJournal);
+ sqlite3BitvecDestroy(pPager->pInJournal);
if( pPager->stmtOpen ){
sqlite3OsClose(pPager->stfd);
}
sqlite3OsClose(pPager->fd);
@@ -24091,17 +26488,15 @@
lruListRemove(pPg);
pPg->pPager->nRef++;
}
pPg->nRef++;
- REFINFO(pPg);
}
#ifdef SQLITE_DEBUG
static void page_ref(PgHdr *pPg){
if( pPg->nRef==0 ){
_page_ref(pPg);
}else{
pPg->nRef++;
- REFINFO(pPg);
}
}
#else
# define page_ref(P) ((P)->nRef==0?_page_ref(P):(void)(P)->nRef++)
@@ -24155,21 +26550,8 @@
if( !pPager->tempFile ){
int iDc = sqlite3OsDeviceCharacteristics(pPager->fd);
assert( pPager->journalOpen );
- /* assert( !pPager->noSync ); // noSync might be set if synchronous
- ** was turned off after the transaction was started. Ticket #615 */
-#ifndef NDEBUG
- {
- /* Make sure the pPager->nRec counter we are keeping agrees
- ** with the nRec computed from the size of the journal file.
- */
- i64 jSz;
- rc = sqlite3OsFileSize(pPager->jfd, &jSz);
- if( rc!=0 ) return rc;
- assert( pPager->journalOff==jSz );
- }
-#endif
if( 0==(iDc&SQLITE_IOCAP_SAFE_APPEND) ){
/* Write the nRec value into the journal file header. If in
** full-synchronous mode, sync the journal first. This ensures that
** all data has really hit the disk before nRec is updated to mark
@@ -24390,25 +26772,51 @@
** return a pointer to the head of that list. All pages are
** collected even if they are still in use.
*/
static PgHdr *pager_get_all_dirty_pages(Pager *pPager){
+
+#ifndef NDEBUG
+ /* Verify the sanity of the dirty list when we are running
+ ** in debugging mode. This is expensive, so do not
+ ** do this on a normal build. */
+ int n1 = 0;
+ int n2 = 0;
+ PgHdr *p;
+ for(p=pPager->pAll; p; p=p->pNextAll){ if( p->dirty ) n1++; }
+ for(p=pPager->pDirty; p; p=p->pDirty){ n2++; }
+ assert( n1==n2 );
+#endif
+
return pPager->pDirty;
}
/*
-** Return TRUE if there is a hot journal on the given pager.
+** Return 1 if there is a hot journal on the given pager.
** A hot journal is one that needs to be played back.
**
** If the current size of the database file is 0 but a journal file
** exists, that is probably an old journal left over from a prior
** database with the same name. Just delete the journal.
+**
+** Return negative if unable to determine the status of the journal.
+**
+** This routine does not open the journal file to examine its
+** content. Hence, the journal might contain the name of a master
+** journal file that has been deleted, and hence not be hot. Or
+** the header of the journal might be zeroed out. This routine
+** does not discover these cases of a non-hot journal - if the
+** journal file exists and is not empty this routine assumes it
+** is hot. The pager_playback() routine will discover that the
+** journal file is not really hot and will no-op.
*/
static int hasHotJournal(Pager *pPager){
sqlite3_vfs *pVfs = pPager->pVfs;
+ int rc;
if( !pPager->useJournal ) return 0;
if( !pPager->fd->pMethods ) return 0;
- if( !sqlite3OsAccess(pVfs, pPager->zJournal, SQLITE_ACCESS_EXISTS) ){
- return 0;
+ rc = sqlite3OsAccess(pVfs, pPager->zJournal, SQLITE_ACCESS_EXISTS);
+ if( rc<=0 ){
+ return rc;
}
if( sqlite3OsCheckReservedLock(pPager->fd) ){
return 0;
}
@@ -24521,16 +26929,18 @@
** of bytes of memory released.
*/
SQLITE_PRIVATE int sqlite3PagerReleaseMemory(int nReq){
int nReleased = 0; /* Bytes of memory released so far */
- sqlite3_mutex *mutex; /* The MEM2 mutex */
Pager *pPager; /* For looping over pagers */
BusyHandler *savedBusy; /* Saved copy of the busy handler */
int rc = SQLITE_OK;
/* Acquire the memory-management mutex
*/
+#ifndef SQLITE_MUTEX_NOOP
+ sqlite3_mutex *mutex; /* The MEM2 mutex */
mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MEM2);
+#endif
sqlite3_mutex_enter(mutex);
/* Signal all database connections that memory management wants
** to have access to the pagers.
@@ -24597,8 +27007,9 @@
+ MEMDB*sizeof(PgHistory)
);
IOTRACE(("PGFREE %p %d *\n", pPager, pPg->pgno));
PAGER_INCR(sqlite3_pager_pgfree_count);
+ sqlite3_free(pPg->pData);
sqlite3_free(pPg);
pPager->nPage--;
}else{
/* An error occured whilst writing to the database file or
@@ -24678,10 +27089,10 @@
if( !MEMDB && pPager->exclusiveMode && pPager->nRef==0 && pPager->errCode ){
if( pPager->journalOpen ){
isHot = 1;
}
- pager_reset(pPager);
pPager->errCode = SQLITE_OK;
+ pager_reset(pPager);
}
/* If the pager is still in an error state, do not proceed. The error
** state will be cleared at some point in the future when all page
@@ -24697,8 +27108,9 @@
assert( pPager->nRef==0 );
if( !pPager->noReadlock ){
rc = pager_wait_on_lock(pPager, SHARED_LOCK);
if( rc!=SQLITE_OK ){
+ assert( pPager->state==PAGER_UNLOCK );
return pager_error(pPager, rc);
}
assert( pPager->state>=SHARED_LOCK );
}
@@ -24705,9 +27117,14 @@
/* If a journal file exists, and there is no RESERVED lock on the
** database file, then it either needs to be played back or deleted.
*/
- if( hasHotJournal(pPager) || isHot ){
+ rc = hasHotJournal(pPager);
+ if( rc<0 ){
+ rc = SQLITE_IOERR_NOMEM;
+ goto failed;
+ }
+ if( rc==1 || isHot ){
/* Get an EXCLUSIVE lock on the database file. At this point it is
** important that a RESERVED lock is not obtained on the way to the
** EXCLUSIVE lock. If it were, another process might open the
** database file, detect the RESERVED lock, and conclude that the
@@ -24720,31 +27137,23 @@
*/
if( pPager->state<EXCLUSIVE_LOCK ){
rc = sqlite3OsLock(pPager->fd, EXCLUSIVE_LOCK);
if( rc!=SQLITE_OK ){
- pager_unlock(pPager);
- return pager_error(pPager, rc);
+ rc = pager_error(pPager, rc);
+ goto failed;
}
pPager->state = PAGER_EXCLUSIVE;
}
- /* Open the journal for reading only. Return SQLITE_BUSY if
- ** we are unable to open the journal file.
- **
- ** The journal file does not need to be locked itself. The
- ** journal file is never open unless the main database file holds
- ** a write lock, so there is never any chance of two or more
- ** processes opening the journal at the same time.
- **
- ** Open the journal for read/write access. This is because in
+ /* Open the journal for read/write access. This is because in
** exclusive-access mode the file descriptor will be kept open and
** possibly used for a transaction later on. On some systems, the
** OsTruncate() call used in exclusive-access mode also requires
** a read/write file handle.
*/
- if( !isHot ){
- rc = SQLITE_BUSY;
- if( sqlite3OsAccess(pVfs, pPager->zJournal, SQLITE_ACCESS_EXISTS) ){
+ if( !isHot && pPager->journalOpen==0 ){
+ int res = sqlite3OsAccess(pVfs,pPager->zJournal,SQLITE_ACCESS_EXISTS);
+ if( res==1 ){
int fout = 0;
int f = SQLITE_OPEN_READWRITE|SQLITE_OPEN_MAIN_JOURNAL;
assert( !pPager->tempFile );
rc = sqlite3OsOpen(pVfs, pPager->zJournal, pPager->jfd, f, &fout);
@@ -24752,13 +27161,25 @@
if( fout&SQLITE_OPEN_READONLY ){
rc = SQLITE_BUSY;
sqlite3OsClose(pPager->jfd);
}
- }
- }
- if( rc!=SQLITE_OK ){
- pager_unlock(pPager);
- return ((rc==SQLITE_NOMEM||rc==SQLITE_IOERR_NOMEM)?rc:SQLITE_BUSY);
+ }else if( res==0 ){
+ /* If the journal does not exist, that means some other process
+ ** has already rolled it back */
+ rc = SQLITE_BUSY;
+ }else{
+ /* If sqlite3OsAccess() returns a negative value, that means it
+ ** failed a memory allocation */
+ rc = SQLITE_IOERR_NOMEM;
+ }
+ }
+ if( rc!=SQLITE_OK ){
+ if( rc!=SQLITE_NOMEM && rc!=SQLITE_IOERR_UNLOCK
+ && rc!=SQLITE_IOERR_NOMEM
+ ){
+ rc = SQLITE_BUSY;
+ }
+ goto failed;
}
pPager->journalOpen = 1;
pPager->journalStarted = 0;
pPager->journalOff = 0;
@@ -24769,9 +27190,10 @@
** lock and reacquire the read lock.
*/
rc = pager_playback(pPager, 1);
if( rc!=SQLITE_OK ){
- return pager_error(pPager, rc);
+ rc = pager_error(pPager, rc);
+ goto failed;
}
assert(pPager->state==PAGER_SHARED ||
(pPager->exclusiveMode && pPager->state>PAGER_SHARED)
);
@@ -24797,16 +27219,17 @@
char dbFileVers[sizeof(pPager->dbFileVers)];
sqlite3PagerPagecount(pPager);
if( pPager->errCode ){
- return pPager->errCode;
+ rc = pPager->errCode;
+ goto failed;
}
if( pPager->dbSize>0 ){
IOTRACE(("CKVERS %p %d\n", pPager, sizeof(dbFileVers)));
rc = sqlite3OsRead(pPager->fd, &dbFileVers, sizeof(dbFileVers), 24);
if( rc!=SQLITE_OK ){
- return rc;
+ goto failed;
}
}else{
memset(dbFileVers, 0, sizeof(dbFileVers));
}
@@ -24821,8 +27244,13 @@
pPager->state = PAGER_SHARED;
}
}
+ failed:
+ if( rc!=SQLITE_OK ){
+ /* pager_unlock() is a no-op for exclusive mode and in-memory databases. */
+ pager_unlock(pPager);
+ }
return rc;
}
/*
@@ -24868,8 +27296,9 @@
|| pPager->lru.pFirst==0
|| MEMDB
|| (pPager->lru.pFirstSynced==0 && pPager->doNotSync)
){
+ void *pData;
if( pPager->nPage>=pPager->nHash ){
pager_resize_hash_table(pPager,
pPager->nHash<256 ? 256 : pPager->nHash*2);
if( pPager->nHash==0 ){
@@ -24879,16 +27308,23 @@
}
pagerLeave(pPager);
nByteHdr = sizeof(*pPg) + sizeof(u32) + pPager->nExtra
+ MEMDB*sizeof(PgHistory);
- pPg = sqlite3_malloc( nByteHdr + pPager->pageSize );
+ pPg = sqlite3_malloc( nByteHdr );
+ if( pPg ){
+ pData = sqlite3_malloc( pPager->pageSize );
+ if( pData==0 ){
+ sqlite3_free(pPg);
+ pPg = 0;
+ }
+ }
pagerEnter(pPager);
if( pPg==0 ){
rc = SQLITE_NOMEM;
goto pager_allocate_out;
}
memset(pPg, 0, nByteHdr);
- pPg->pData = (void*)(nByteHdr + (char*)pPg);
+ pPg->pData = pData;
pPg->pPager = pPager;
pPg->pNextAll = pPager->pAll;
pPager->pAll = pPg;
pPager->nPage++;
@@ -25006,23 +27442,13 @@
}
pPg->pgno = pgno;
assert( !MEMDB || pgno>pPager->stmtSize );
- if( pPager->aInJournal && (int)pgno<=pPager->origDbSize ){
-#if 0
- sqlite3CheckMemory(pPager->aInJournal, pgno/8);
-#endif
- assert( pPager->journalOpen );
- pPg->inJournal = (pPager->aInJournal[pgno/8] & (1<<(pgno&7)))!=0;
- pPg->needSync = 0;
- }else{
- pPg->inJournal = 0;
- pPg->needSync = 0;
- }
+ pPg->inJournal = sqlite3BitvecTest(pPager->pInJournal, pgno);
+ pPg->needSync = 0;
makeClean(pPg);
pPg->nRef = 1;
- REFINFO(pPg);
pPager->nRef++;
if( pPager->nExtra>0 ){
memset(PGHDR_TO_EXTRA(pPg, pPager), 0, pPager->nExtra);
@@ -25134,16 +27560,18 @@
** are released, a rollback occurs and the lock on the database is
** removed.
*/
SQLITE_PRIVATE int sqlite3PagerUnref(DbPage *pPg){
- Pager *pPager = pPg->pPager;
+ Pager *pPager;
+
+ if( pPg==0 ) return SQLITE_OK;
+ pPager = pPg->pPager;
/* Decrement the reference count for this page
*/
assert( pPg->nRef>0 );
pagerEnter(pPg->pPager);
pPg->nRef--;
- REFINFO(pPg);
CHECK_PAGE(pPg);
/* When the number of references to a page reach 0, call the
@@ -25182,41 +27610,42 @@
int rc;
assert( !MEMDB );
assert( pPager->state>=PAGER_RESERVED );
- assert( pPager->journalOpen==0 );
assert( pPager->useJournal );
- assert( pPager->aInJournal==0 );
+ assert( pPager->pInJournal==0 );
sqlite3PagerPagecount(pPager);
pagerLeave(pPager);
- pPager->aInJournal = sqlite3MallocZero( pPager->dbSize/8 + 1 );
- pagerEnter(pPager);
- if( pPager->aInJournal==0 ){
+ pPager->pInJournal = sqlite3BitvecCreate(pPager->dbSize);
+ pagerEnter(pPager);
+ if( pPager->pInJournal==0 ){
rc = SQLITE_NOMEM;
goto failed_to_open_journal;
}
- if( pPager->tempFile ){
- flags |= (SQLITE_OPEN_DELETEONCLOSE|SQLITE_OPEN_TEMP_JOURNAL);
- }else{
- flags |= (SQLITE_OPEN_MAIN_JOURNAL);
- }
+ if( pPager->journalOpen==0 ){
+ if( pPager->tempFile ){
+ flags |= (SQLITE_OPEN_DELETEONCLOSE|SQLITE_OPEN_TEMP_JOURNAL);
+ }else{
+ flags |= (SQLITE_OPEN_MAIN_JOURNAL);
+ }
#ifdef SQLITE_ENABLE_ATOMIC_WRITE
- rc = sqlite3JournalOpen(
- pVfs, pPager->zJournal, pPager->jfd, flags, jrnlBufferSize(pPager)
- );
-#else
- rc = sqlite3OsOpen(pVfs, pPager->zJournal, pPager->jfd, flags, 0);
-#endif
- assert( rc!=SQLITE_OK || pPager->jfd->pMethods );
- pPager->journalOff = 0;
- pPager->setMaster = 0;
- pPager->journalHdr = 0;
- if( rc!=SQLITE_OK ){
- if( rc==SQLITE_NOMEM ){
- sqlite3OsDelete(pVfs, pPager->zJournal, 0);
- }
- goto failed_to_open_journal;
+ rc = sqlite3JournalOpen(
+ pVfs, pPager->zJournal, pPager->jfd, flags, jrnlBufferSize(pPager)
+ );
+#else
+ rc = sqlite3OsOpen(pVfs, pPager->zJournal, pPager->jfd, flags, 0);
+#endif
+ assert( rc!=SQLITE_OK || pPager->jfd->pMethods );
+ pPager->journalOff = 0;
+ pPager->setMaster = 0;
+ pPager->journalHdr = 0;
+ if( rc!=SQLITE_OK ){
+ if( rc==SQLITE_NOMEM ){
+ sqlite3OsDelete(pVfs, pPager->zJournal, 0);
+ }
+ goto failed_to_open_journal;
+ }
}
pPager->journalOpen = 1;
pPager->journalStarted = 0;
pPager->needSync = 0;
@@ -25233,18 +27662,18 @@
if( pPager->stmtAutoopen && rc==SQLITE_OK ){
rc = sqlite3PagerStmtBegin(pPager);
}
if( rc!=SQLITE_OK && rc!=SQLITE_NOMEM && rc!=SQLITE_IOERR_NOMEM ){
- rc = pager_end_transaction(pPager);
+ rc = pager_end_transaction(pPager, 0);
if( rc==SQLITE_OK ){
rc = SQLITE_FULL;
}
}
return rc;
failed_to_open_journal:
- sqlite3_free(pPager->aInJournal);
- pPager->aInJournal = 0;
+ sqlite3BitvecDestroy(pPager->pInJournal);
+ pPager->pInJournal = 0;
return rc;
}
/*
@@ -25280,9 +27709,9 @@
pagerEnter(pPager);
assert( pPg->nRef>0 );
assert( pPager->state!=PAGER_UNLOCK );
if( pPager->state==PAGER_SHARED ){
- assert( pPager->aInJournal==0 );
+ assert( pPager->pInJournal==0 );
if( MEMDB ){
pPager->state = PAGER_EXCLUSIVE;
pPager->origDbSize = pPager->dbSize;
}else{
@@ -25298,26 +27727,28 @@
return rc;
}
pPager->dirtyCache = 0;
PAGERTRACE2("TRANSACTION %d\n", PAGERID(pPager));
- if( pPager->useJournal && !pPager->tempFile ){
+ if( pPager->useJournal && !pPager->tempFile
+ && pPager->journalMode!=PAGER_JOURNALMODE_OFF ){
rc = pager_open_journal(pPager);
}
}
}else if( pPager->journalOpen && pPager->journalOff==0 ){
- /* This happens when the pager was in exclusive-access mode last
+ /* This happens when the pager was in exclusive-access mode the last
** time a (read or write) transaction was successfully concluded
** by this connection. Instead of deleting the journal file it was
- ** kept open and truncated to 0 bytes.
+ ** kept open and either was truncated to 0 bytes or its header was
+ ** overwritten with zeros.
*/
assert( pPager->nRec==0 );
assert( pPager->origDbSize==0 );
- assert( pPager->aInJournal==0 );
+ assert( pPager->pInJournal==0 );
sqlite3PagerPagecount(pPager);
pagerLeave(pPager);
- pPager->aInJournal = sqlite3MallocZero( pPager->dbSize/8 + 1 );
+ pPager->pInJournal = sqlite3BitvecCreate( pPager->dbSize );
pagerEnter(pPager);
- if( !pPager->aInJournal ){
+ if( !pPager->pInJournal ){
rc = SQLITE_NOMEM;
}else{
pPager->origDbSize = pPager->dbSize;
rc = writeJournalHdr(pPager);
@@ -25420,8 +27851,9 @@
*/
makeDirty(pPg);
if( pPg->inJournal && (pageInStatement(pPg) || pPager->stmtInUse==0) ){
pPager->dirtyCache = 1;
+ pPager->dbModified = 1;
}else{
/* If we get this far, it means that the page needs to be
** written to the transaction journal or the ckeckpoint journal
@@ -25435,20 +27867,21 @@
if( rc!=SQLITE_OK ){
return rc;
}
assert( pPager->state>=PAGER_RESERVED );
- if( !pPager->journalOpen && pPager->useJournal ){
+ if( !pPager->journalOpen && pPager->useJournal
+ && pPager->journalMode!=PAGER_JOURNALMODE_OFF ){
rc = pager_open_journal(pPager);
if( rc!=SQLITE_OK ) return rc;
}
- assert( pPager->journalOpen || !pPager->useJournal );
pPager->dirtyCache = 1;
+ pPager->dbModified = 1;
/* The transaction journal now exists and we have a RESERVED or an
** EXCLUSIVE lock on the main database file. Write the current page to
** the transaction journal if it is not there already.
*/
- if( !pPg->inJournal && (pPager->useJournal || MEMDB) ){
+ if( !pPg->inJournal && (pPager->journalOpen || MEMDB) ){
if( (int)pPg->pgno <= pPager->origDbSize ){
if( MEMDB ){
PgHistory *pHist = PGHDR_TO_HIST(pPg, pPager);
PAGERTRACE3("JOURNAL %d page %d\n", PAGERID(pPager), pPg->pgno);
@@ -25491,13 +27924,13 @@
return rc;
}
pPager->nRec++;
- assert( pPager->aInJournal!=0 );
- pPager->aInJournal[pPg->pgno/8] |= 1<<(pPg->pgno&7);
+ assert( pPager->pInJournal!=0 );
+ sqlite3BitvecSet(pPager->pInJournal, pPg->pgno);
pPg->needSync = !pPager->noSync;
if( pPager->stmtInUse ){
- pPager->aInStmt[pPg->pgno/8] |= 1<<(pPg->pgno&7);
+ sqlite3BitvecSet(pPager->pInStmt, pPg->pgno);
}
}
}else{
pPg->needSync = !pPager->journalStarted && !pPager->noSync;
@@ -25540,10 +27973,10 @@
if( rc!=SQLITE_OK ){
return rc;
}
pPager->stmtNRec++;
- assert( pPager->aInStmt!=0 );
- pPager->aInStmt[pPg->pgno/8] |= 1<<(pPg->pgno&7);
+ assert( pPager->pInStmt!=0 );
+ sqlite3BitvecSet(pPager->pInStmt, pPg->pgno);
}
}
}
@@ -25610,11 +28043,9 @@
for(ii=0; ii<nPage && rc==SQLITE_OK; ii++){
Pgno pg = pg1+ii;
PgHdr *pPage;
- if( !pPager->aInJournal || pg==pPg->pgno ||
- pg>pPager->origDbSize || !(pPager->aInJournal[pg/8]&(1<<(pg&7)))
- ) {
+ if( pg==pPg->pgno || !sqlite3BitvecTest(pPager->pInJournal, pg) ){
if( pg!=PAGER_MJ_PGNO(pPager) ){
rc = sqlite3PagerGet(pPager, pg, &pPage);
if( rc==SQLITE_OK ){
rc = pager_write(pPage);
@@ -25623,9 +28054,9 @@
}
sqlite3PagerUnref(pPage);
}
}
- }else if( (pPage = pager_lookup(pPager, pg)) ){
+ }else if( (pPage = pager_lookup(pPager, pg))!=0 ){
if( pPage->needSync ){
needSync = 1;
}
}
@@ -25661,31 +28092,8 @@
*/
#ifndef NDEBUG
SQLITE_PRIVATE int sqlite3PagerIswriteable(DbPage *pPg){
return pPg->dirty;
-}
-#endif
-
-#ifndef SQLITE_OMIT_VACUUM
-/*
-** Replace the content of a single page with the information in the third
-** argument.
-*/
-SQLITE_PRIVATE int sqlite3PagerOverwrite(Pager *pPager, Pgno pgno, void *pData){
- PgHdr *pPg;
- int rc;
-
- pagerEnter(pPager);
- rc = sqlite3PagerGet(pPager, pgno, &pPg);
- if( rc==SQLITE_OK ){
- rc = sqlite3PagerWrite(pPg);
- if( rc==SQLITE_OK ){
- memcpy(sqlite3PagerGetData(pPg), pData, pPager->pageSize);
- }
- sqlite3PagerUnref(pPg);
- }
- pagerLeave(pPager);
- return rc;
}
#endif
/*
@@ -25751,21 +28159,8 @@
** If we have not yet actually read the content of this page (if
** the PgHdr.needRead flag is set) then this routine acts as a promise
** that we will never need to read the page content in the future.
** so the needRead flag can be cleared at this point.
-**
-** This routine is only called from a single place in the sqlite btree
-** code (when a leaf is removed from the free-list). This allows the
-** following assumptions to be made about pPg:
-**
-** 1. PagerDontWrite() has been called on the page, OR
-** PagerWrite() has not yet been called on the page.
-**
-** 2. The page existed when the transaction was started.
-**
-** Details: DontRollback() (this routine) is only called when a leaf is
-** removed from the free list. DontWrite() is called whenever a page
-** becomes a free-list leaf.
*/
SQLITE_PRIVATE void sqlite3PagerDontRollback(DbPage *pPg){
Pager *pPager = pPg->pPager;
@@ -25781,20 +28176,29 @@
return;
}
assert( !MEMDB ); /* For a memdb, pPager->journalOpen is always 0 */
- /* Check that PagerWrite() has not yet been called on this page, and
- ** that the page existed when the transaction started.
+#ifdef SQLITE_SECURE_DELETE
+ if( pPg->inJournal || (int)pPg->pgno > pPager->origDbSize ){
+ return;
+ }
+#endif
+
+ /* If SECURE_DELETE is disabled, then there is no way that this
+ ** routine can be called on a page for which sqlite3PagerDontWrite()
+ ** has not been previously called during the same transaction.
+ ** And if DontWrite() has previously been called, the following
+ ** conditions must be met.
*/
assert( !pPg->inJournal && (int)pPg->pgno <= pPager->origDbSize );
- assert( pPager->aInJournal!=0 );
- pPager->aInJournal[pPg->pgno/8] |= 1<<(pPg->pgno&7);
+ assert( pPager->pInJournal!=0 );
+ sqlite3BitvecSet(pPager->pInJournal, pPg->pgno);
pPg->inJournal = 1;
pPg->needRead = 0;
if( pPager->stmtInUse ){
- assert( pPager->stmtSize <= pPager->origDbSize );
- pPager->aInStmt[pPg->pgno/8] |= 1<<(pPg->pgno&7);
+ assert( pPager->stmtSize >= pPager->origDbSize );
+ sqlite3BitvecSet(pPager->pInStmt, pPg->pgno);
}
PAGERTRACE3("DONT_ROLLBACK page %d of %d\n", pPg->pgno, PAGERID(pPager));
IOTRACE(("GARBAGE %p %d\n", pPager, pPg->pgno))
pagerLeave(pPager);
@@ -25840,8 +28244,19 @@
return rc;
}
/*
+** Sync the pager file to disk.
+*/
+SQLITE_PRIVATE int sqlite3PagerSync(Pager *pPager){
+ int rc;
+ pagerEnter(pPager);
+ rc = sqlite3OsSync(pPager->fd, pPager->sync_flags);
+ pagerLeave(pPager);
+ return rc;
+}
+
+/*
** Sync the database file for the pager pPager. zMaster points to the name
** of a master journal file that should be written into the individual
** journal file. zMaster may be NULL, which is interpreted as no master
** journal (a single database transaction).
@@ -25855,11 +28270,30 @@
** passed to an sqlite3PagerCommitPhaseOne() call.
**
** If parameter nTrunc is non-zero, then the pager file is truncated to
** nTrunc pages (this is used by auto-vacuum databases).
-*/
-SQLITE_PRIVATE int sqlite3PagerCommitPhaseOne(Pager *pPager, const char *zMaster, Pgno nTrunc){
- int rc = SQLITE_OK;
+**
+** If the final parameter - noSync - is true, then the database file itself
+** is not synced. The caller must call sqlite3PagerSync() directly to
+** sync the database file before calling CommitPhaseTwo() to delete the
+** journal file in this case.
+*/
+SQLITE_PRIVATE int sqlite3PagerCommitPhaseOne(
+ Pager *pPager,
+ const char *zMaster,
+ Pgno nTrunc,
+ int noSync
+){
+ int rc = SQLITE_OK;
+
+ /* If no changes have been made, we can leave the transaction early.
+ */
+ if( pPager->dbModified==0 &&
+ (pPager->journalMode!=PAGER_JOURNALMODE_DELETE ||
+ pPager->exclusiveMode!=0) ){
+ assert( pPager->dirtyCache==0 || pPager->journalOpen==0 );
+ return SQLITE_OK;
+ }
PAGERTRACE4("DATABASE SYNC: File=%s zMaster=%s nTrunc=%d\n",
pPager->zFilename, zMaster, nTrunc);
pagerEnter(pPager);
@@ -25883,12 +28317,14 @@
** be created for this transaction.
*/
int useAtomicWrite = (
!zMaster &&
+ pPager->journalOpen &&
pPager->journalOff==jrnlBufferSize(pPager) &&
nTrunc==0 &&
(0==pPager->pDirty || 0==pPager->pDirty->pDirty)
);
+ assert( pPager->journalOpen || pPager->journalMode==PAGER_JOURNALMODE_OFF );
if( useAtomicWrite ){
/* Update the nRec field in the journal file. */
int offset = pPager->journalHdr + sizeof(aJournalMagic);
assert(pPager->nRec==1);
@@ -25916,9 +28352,8 @@
** EXCLUSIVE lock. The next time the process tries to commit the
** transaction the m-j name will have already been written.
*/
if( !pPager->setMaster ){
- assert( pPager->journalOpen );
rc = pager_incr_changecounter(pPager, 0);
if( rc!=SQLITE_OK ) goto sync_exit;
#ifndef SQLITE_OMIT_AUTOVACUUM
if( nTrunc!=0 ){
@@ -25928,9 +28363,9 @@
*/
Pgno i;
int iSkip = PAGER_MJ_PGNO(pPager);
for( i=nTrunc+1; i<=pPager->origDbSize; i++ ){
- if( !(pPager->aInJournal[i/8] & (1<<(i&7))) && i!=iSkip ){
+ if( !sqlite3BitvecTest(pPager->pInJournal, i) && i!=iSkip ){
rc = sqlite3PagerGet(pPager, i, &pPg);
if( rc!=SQLITE_OK ) goto sync_exit;
rc = sqlite3PagerWrite(pPg);
sqlite3PagerUnref(pPg);
@@ -25955,16 +28390,22 @@
/* Write all dirty pages to the database file */
pPg = pager_get_all_dirty_pages(pPager);
rc = pager_write_pagelist(pPg);
if( rc!=SQLITE_OK ){
- while( pPg && !pPg->dirty ){ pPg = pPg->pDirty; }
- pPager->pDirty = pPg;
+ assert( rc!=SQLITE_IOERR_BLOCKED );
+ /* The error might have left the dirty list all fouled up here,
+ ** but that does not matter because if the if the dirty list did
+ ** get corrupted, then the transaction will roll back and
+ ** discard the dirty list. There is an assert in
+ ** pager_get_all_dirty_pages() that verifies that no attempt
+ ** is made to use an invalid dirty list.
+ */
goto sync_exit;
}
pPager->pDirty = 0;
/* Sync the database file. */
- if( !pPager->noSync ){
+ if( !pPager->noSync && !noSync ){
rc = sqlite3OsSync(pPager->fd, pPager->sync_flags);
}
IOTRACE(("DBSYNC %p\n", pPager))
@@ -26003,8 +28444,14 @@
}
if( pPager->state<PAGER_RESERVED ){
return SQLITE_ERROR;
}
+ if( pPager->dbModified==0 &&
+ (pPager->journalMode!=PAGER_JOURNALMODE_DELETE ||
+ pPager->exclusiveMode!=0) ){
+ assert( pPager->dirtyCache==0 || pPager->journalOpen==0 );
+ return SQLITE_OK;
+ }
pagerEnter(pPager);
PAGERTRACE2("COMMIT %d\n", PAGERID(pPager));
if( MEMDB ){
pPg = pager_get_all_dirty_pages(pPager);
@@ -26031,11 +28478,10 @@
pPager->state = PAGER_SHARED;
pagerLeave(pPager);
return SQLITE_OK;
}
- assert( pPager->journalOpen || !pPager->dirtyCache );
assert( pPager->state==PAGER_SYNCED || !pPager->dirtyCache );
- rc = pager_end_transaction(pPager);
+ rc = pager_end_transaction(pPager, pPager->setMaster);
rc = pager_error(pPager, rc);
pagerLeave(pPager);
return rc;
}
@@ -26092,9 +28538,9 @@
}
pagerEnter(pPager);
if( !pPager->dirtyCache || !pPager->journalOpen ){
- rc = pager_end_transaction(pPager);
+ rc = pager_end_transaction(pPager, pPager->setMaster);
pagerLeave(pPager);
return rc;
}
@@ -26107,9 +28553,9 @@
}
if( pPager->state==PAGER_RESERVED ){
int rc2;
rc = pager_playback(pPager, 0);
- rc2 = pager_end_transaction(pPager);
+ rc2 = pager_end_transaction(pPager, pPager->setMaster);
if( rc==SQLITE_OK ){
rc = rc2;
}
}else{
@@ -26186,20 +28632,15 @@
return SQLITE_OK;
}
assert( pPager->journalOpen );
pagerLeave(pPager);
- assert( pPager->aInStmt==0 );
- pPager->aInStmt = sqlite3MallocZero( pPager->dbSize/8 + 1 );
+ assert( pPager->pInStmt==0 );
+ pPager->pInStmt = sqlite3BitvecCreate(pPager->dbSize);
pagerEnter(pPager);
- if( pPager->aInStmt==0 ){
+ if( pPager->pInStmt==0 ){
/* sqlite3OsLock(pPager->fd, SHARED_LOCK); */
return SQLITE_NOMEM;
}
-#ifndef NDEBUG
- rc = sqlite3OsFileSize(pPager->jfd, &pPager->stmtJSize);
- if( rc ) goto stmt_begin_failed;
- assert( pPager->stmtJSize == pPager->journalOff );
-#endif
pPager->stmtJSize = pPager->journalOff;
pPager->stmtSize = pPager->dbSize;
pPager->stmtHdrOff = 0;
pPager->stmtCksum = pPager->cksumInit;
@@ -26215,11 +28656,11 @@
pPager->stmtInUse = 1;
return SQLITE_OK;
stmt_begin_failed:
- if( pPager->aInStmt ){
- sqlite3_free(pPager->aInStmt);
- pPager->aInStmt = 0;
+ if( pPager->pInStmt ){
+ sqlite3BitvecDestroy(pPager->pInStmt);
+ pPager->pInStmt = 0;
}
return rc;
}
SQLITE_PRIVATE int sqlite3PagerStmtBegin(Pager *pPager){
@@ -26239,10 +28680,10 @@
PgHdr *pPg, *pNext;
PAGERTRACE2("STMT-COMMIT %d\n", PAGERID(pPager));
if( !MEMDB ){
/* sqlite3OsTruncate(pPager->stfd, 0); */
- sqlite3_free( pPager->aInStmt );
- pPager->aInStmt = 0;
+ sqlite3BitvecDestroy(pPager->pInStmt);
+ pPager->pInStmt = 0;
}else{
for(pPg=pPager->pStmt; pPg; pPg=pNext){
PgHistory *pHist = PGHDR_TO_HIST(pPg, pPager);
pNext = pHist->pNextStmt;
@@ -26410,14 +28851,9 @@
pPg->needSync = pPgOld->needSync;
}else{
pPg->needSync = 0;
}
- if( pPager->aInJournal && (int)pgno<=pPager->origDbSize ){
- pPg->inJournal = (pPager->aInJournal[pgno/8] & (1<<(pgno&7)))!=0;
- }else{
- pPg->inJournal = 0;
- assert( pPg->needSync==0 || (int)pgno>pPager->origDbSize );
- }
+ pPg->inJournal = sqlite3BitvecTest(pPager->pInJournal, pgno);
/* Change the page number for pPg and insert it into the new hash-chain. */
assert( pgno!=0 );
pPg->pgno = pgno;
@@ -26431,18 +28867,19 @@
pPg->pPrevHash = 0;
makeDirty(pPg);
pPager->dirtyCache = 1;
+ pPager->dbModified = 1;
if( needSyncPgno ){
/* If needSyncPgno is non-zero, then the journal file needs to be
** sync()ed before any data is written to database file page needSyncPgno.
** Currently, no such page exists in the page-cache and the
- ** Pager.aInJournal bit has been set. This needs to be remedied by loading
+ ** Pager.pInJournal bit has been set. This needs to be remedied by loading
** the page into the pager-cache and setting the PgHdr.needSync flag.
**
** If the attempt to load the page into the page-cache fails, (due
- ** to a malloc() or IO failure), clear the bit in the aInJournal[]
+ ** to a malloc() or IO failure), clear the bit in the pInJournal[]
** array. Otherwise, if the page is loaded and written again in
** this transaction, it may be written to the database file before
** it is synced into the journal file. This way, it may end up in
** the journal file twice, but that is not a problem.
@@ -26454,10 +28891,10 @@
PgHdr *pPgHdr;
assert( pPager->needSync );
rc = sqlite3PagerGet(pPager, needSyncPgno, &pPgHdr);
if( rc!=SQLITE_OK ){
- if( pPager->aInJournal && (int)needSyncPgno<=pPager->origDbSize ){
- pPager->aInJournal[needSyncPgno/8] &= ~(1<<(needSyncPgno&7));
+ if( pPager->pInJournal && (int)needSyncPgno<=pPager->origDbSize ){
+ sqlite3BitvecClear(pPager->pInJournal, needSyncPgno);
}
pagerLeave(pPager);
return rc;
}
@@ -26510,8 +28947,31 @@
}
return (int)pPager->exclusiveMode;
}
+/*
+** Get/set the journal-mode for this pager. Parameter eMode must be one
+** of PAGER_JOURNALMODE_QUERY, PAGER_JOURNALMODE_DELETE or
+** PAGER_JOURNALMODE_PERSIST. If the parameter is not _QUERY, then
+** the journal-mode is set to the value specified.
+**
+** The returned value is either PAGER_JOURNALMODE_DELETE or
+** PAGER_JOURNALMODE_PERSIST, indicating the current (possibly updated)
+** journal-mode.
+*/
+SQLITE_PRIVATE int sqlite3PagerJournalMode(Pager *pPager, int eMode){
+ assert( eMode==PAGER_JOURNALMODE_QUERY
+ || eMode==PAGER_JOURNALMODE_DELETE
+ || eMode==PAGER_JOURNALMODE_PERSIST
+ || eMode==PAGER_JOURNALMODE_OFF );
+ assert( PAGER_JOURNALMODE_QUERY<0 );
+ assert( PAGER_JOURNALMODE_DELETE>=0 && PAGER_JOURNALMODE_PERSIST>=0 );
+ if( eMode>=0 ){
+ pPager->journalMode = eMode;
+ }
+ return (int)pPager->journalMode;
+}
+
#ifdef SQLITE_TEST
/*
** Print a listing of all referenced pages and their ref count.
*/
@@ -26560,9 +29020,9 @@
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
-** $Id: btreeInt.h,v 1.15 2007/12/21 04:47:26 danielk1977 Exp $
+** $Id: btreeInt.h,v 1.21 2008/04/24 19:15:10 shane Exp $
**
** This file implements a external (disk-based) database using BTrees.
** For a detailed discussion of BTrees, refer to
**
@@ -26767,12 +29227,13 @@
*/
#define MX_CELL_SIZE(pBt) (pBt->pageSize-8)
/* The maximum number of cells on a single page of the database. This
-** assumes a minimum cell size of 3 bytes. Such small cells will be
-** exceedingly rare, but they are possible.
-*/
-#define MX_CELL(pBt) ((pBt->pageSize-8)/3)
+** assumes a minimum cell size of 6 bytes (4 bytes for the cell itself
+** plus 2 bytes for the index to the cell in the page header). Such
+** small cells will be rare, but they are possible.
+*/
+#define MX_CELL(pBt) ((pBt->pageSize-8)/6)
/* Forward declarations */
typedef struct MemPage MemPage;
typedef struct BtLock BtLock;
@@ -26943,8 +29404,9 @@
BtShared *pNext; /* Next on a list of sharable BtShared structs */
BtLock *pLock; /* List of locks held on this shared-btree struct */
Btree *pExclusive; /* Btree with an EXCLUSIVE lock on the whole db */
#endif
+ u8 *pTmpSpace; /* BtShared.pageSize bytes of space for tmp use */
};
/*
** An instance of the following structure is used to hold information
@@ -26980,15 +29442,16 @@
struct BtCursor {
Btree *pBtree; /* The Btree to which this cursor belongs */
BtShared *pBt; /* The BtShared this cursor points to */
BtCursor *pNext, *pPrev; /* Forms a linked list of all cursors */
- int (*xCompare)(void*,int,const void*,int,const void*); /* Key comp func */
- void *pArg; /* First arg to xCompare() */
+ struct KeyInfo *pKeyInfo; /* Argument passed to comparison function */
Pgno pgnoRoot; /* The root page of this tree */
MemPage *pPage; /* Page that contains the entry */
int idx; /* Index of the entry in pPage->aCell[] */
CellInfo info; /* A parse of the cell we are pointing at */
u8 wrFlag; /* True if writable */
+ u8 atLast; /* Cursor pointing to the last entry */
+ u8 validNKey; /* True if info.nKey is valid */
u8 eState; /* One of the CURSOR_XXX constants (see below) */
void *pKey; /* Saved key that was cursor's last known position */
i64 nKey; /* Size of pKey, or last integer key */
int skip; /* (skip<0) -> Prev() is a no-op. (skip>0) -> Next() is */
@@ -27029,25 +29492,16 @@
#define CURSOR_FAULT 3
/*
** The TRACE macro will print high-level status information about the
-** btree operation when the global variable sqlite3_btree_trace is
+** btree operation when the global variable sqlite3BtreeTrace is
** enabled.
*/
#if SQLITE_TEST
-# define TRACE(X) if( sqlite3_btree_trace ){ printf X; fflush(stdout); }
+# define TRACE(X) if( sqlite3BtreeTrace ){ printf X; fflush(stdout); }
#else
# define TRACE(X)
#endif
-
-/*
-** Routines to read and write variable-length integers. These used to
-** be defined locally, but now we use the varint routines in the util.c
-** file.
-*/
-#define getVarint sqlite3GetVarint
-#define getVarint32(A,B) ((*B=*(A))<=0x7f?1:sqlite3GetVarint32(A,B))
-#define putVarint sqlite3PutVarint
/* The database page the PENDING_BYTE occupies. This page is never used.
** TODO: This macro is very similary to PAGER_MJ_PGNO() in pager.c. They
** should possibly be consolidated (presumably in pager.h).
@@ -27508,9 +29962,9 @@
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
-** $Id: btree.c,v 1.438 2008/01/31 14:54:44 drh Exp $
+** $Id: btree.c,v 1.458 2008/05/09 16:57:51 danielk1977 Exp $
**
** This file implements a external (disk-based) database using BTrees.
** See the header comment on "btreeInt.h" for additional information.
** Including a description of file format and an overview of operation.
@@ -27526,9 +29980,9 @@
** Set this global variable to 1 to enable tracing using the TRACE
** macro.
*/
#if SQLITE_TEST
-int sqlite3_btree_trace=0; /* True to enable tracing */
+int sqlite3BtreeTrace=0; /* True to enable tracing */
#endif
@@ -27877,9 +30331,9 @@
return SQLITE_ABORT;
}
#endif
pCur->eState = CURSOR_INVALID;
- rc = sqlite3BtreeMoveto(pCur, pCur->pKey, pCur->nKey, 0, &pCur->skip);
+ rc = sqlite3BtreeMoveto(pCur, pCur->pKey, 0, pCur->nKey, 0, &pCur->skip);
if( rc==SQLITE_OK ){
sqlite3_free(pCur->pKey);
pCur->pKey = 0;
assert( pCur->eState==CURSOR_VALID || pCur->eState==CURSOR_INVALID );
@@ -28050,9 +30504,9 @@
assert( pPage->leaf==0 || pPage->leaf==1 );
n = pPage->childPtrSize;
assert( n==4-4*pPage->leaf );
if( pPage->hasData ){
- n += getVarint32(&pCell[n], &nPayload);
+ n += getVarint32(&pCell[n], nPayload);
}else{
nPayload = 0;
}
pInfo->nData = nPayload;
@@ -28059,9 +30513,9 @@
if( pPage->intKey ){
n += getVarint(&pCell[n], (u64 *)&pInfo->nKey);
}else{
u32 x;
- n += getVarint32(&pCell[n], &x);
+ n += getVarint32(&pCell[n], x);
pInfo->nKey = x;
nPayload += x;
}
pInfo->nPayload = nPayload;
@@ -28120,15 +30574,15 @@
** data header and the local payload, but not any overflow page or
** the space used by the cell pointer.
*/
#ifndef NDEBUG
-static int cellSize(MemPage *pPage, int iCell){
+static u16 cellSize(MemPage *pPage, int iCell){
CellInfo info;
sqlite3BtreeParseCell(pPage, iCell, &info);
return info.nSize;
}
#endif
-static int cellSizePtr(MemPage *pPage, u8 *pCell){
+static u16 cellSizePtr(MemPage *pPage, u8 *pCell){
CellInfo info;
sqlite3BtreeParseCellPtr(pPage, pCell, &info);
return info.nSize;
}
@@ -28552,8 +31006,12 @@
}
rc = sqlite3BtreeGetPage(pBt, pgno, ppPage, 0);
if( rc==SQLITE_OK && (*ppPage)->isInit==0 ){
rc = sqlite3BtreeInitPage(*ppPage, pParent);
+ if( rc!=SQLITE_OK ){
+ releasePage(*ppPage);
+ *ppPage = 0;
+ }
}
return rc;
}
@@ -28938,8 +31396,9 @@
if( pBt->xFreeSchema && pBt->pSchema ){
pBt->xFreeSchema(pBt->pSchema);
}
sqlite3_free(pBt->pSchema);
+ sqlite3_free(pBt->pTmpSpace);
sqlite3_free(pBt);
}
#ifndef SQLITE_OMIT_SHARED_CACHE
@@ -29042,8 +31501,10 @@
((pageSize-1)&pageSize)==0 ){
assert( (pageSize & 7)==0 );
assert( !pBt->pPage1 && !pBt->pCursor );
pBt->pageSize = pageSize;
+ sqlite3_free(pBt->pTmpSpace);
+ pBt->pTmpSpace = 0;
rc = sqlite3PagerSetPagesize(pBt->pPager, &pBt->pageSize);
}
pBt->usableSize = pBt->pageSize - nReserve;
sqlite3BtreeLeave(p);
@@ -29133,22 +31594,28 @@
** SQLITE_BUSY is returned if the database is locked. SQLITE_NOMEM
** is returned if we run out of memory.
*/
static int lockBtree(BtShared *pBt){
- int rc, pageSize;
+ int rc;
MemPage *pPage1;
+ int nPage;
assert( sqlite3_mutex_held(pBt->mutex) );
if( pBt->pPage1 ) return SQLITE_OK;
rc = sqlite3BtreeGetPage(pBt, 1, &pPage1, 0);
if( rc!=SQLITE_OK ) return rc;
-
/* Do some checking to help insure the file we opened really is
** a valid database file.
*/
rc = SQLITE_NOTADB;
- if( sqlite3PagerPagecount(pBt->pPager)>0 ){
+ nPage = sqlite3PagerPagecount(pBt->pPager);
+ if( nPage<0 ){
+ rc = SQLITE_IOERR;
+ goto page1_init_failed;
+ }else if( nPage>0 ){
+ int pageSize;
+ int usableSize;
u8 *page1 = pPage1->aData;
if( memcmp(page1, zMagicHeader, 16)!=0 ){
goto page1_init_failed;
}
@@ -29164,13 +31631,29 @@
){
goto page1_init_failed;
}
assert( (pageSize & 7)==0 );
- pBt->pageSize = pageSize;
- pBt->usableSize = pageSize - page1[20];
- if( pBt->usableSize<500 ){
+ usableSize = pageSize - page1[20];
+ if( pageSize!=pBt->pageSize ){
+ /* After reading the first page of the database assuming a page size
+ ** of BtShared.pageSize, we have discovered that the page-size is
+ ** actually pageSize. Unlock the database, leave pBt->pPage1 at
+ ** zero and return SQLITE_OK. The caller will call this function
+ ** again with the correct page-size.
+ */
+ releasePage(pPage1);
+ pBt->usableSize = usableSize;
+ pBt->pageSize = pageSize;
+ sqlite3_free(pBt->pTmpSpace);
+ pBt->pTmpSpace = 0;
+ sqlite3PagerSetPagesize(pBt->pPager, &pBt->pageSize);
+ return SQLITE_OK;
+ }
+ if( usableSize<500 ){
goto page1_init_failed;
}
+ pBt->pageSize = pageSize;
+ pBt->usableSize = usableSize;
pBt->maxEmbedFrac = page1[21];
pBt->minEmbedFrac = page1[22];
pBt->minLeafFrac = page1[23];
#ifndef SQLITE_OMIT_AUTOVACUUM
@@ -29378,9 +31861,11 @@
#endif
do {
if( pBt->pPage1==0 ){
- rc = lockBtree(pBt);
+ do{
+ rc = lockBtree(pBt);
+ }while( pBt->pPage1==0 && rc==SQLITE_OK );
}
if( rc==SQLITE_OK && wrflag ){
if( pBt->readOnly ){
@@ -29793,9 +32278,9 @@
}
if( rc==SQLITE_DONE ){
assert(nFin==0 || pBt->nTrunc==0 || nFin<=pBt->nTrunc);
rc = SQLITE_OK;
- if( pBt->nTrunc ){
+ if( pBt->nTrunc && nFin ){
rc = sqlite3PagerWrite(pBt->pPage1->pDbPage);
put4byte(&pBt->pPage1->aData[32], 0);
put4byte(&pBt->pPage1->aData[36], 0);
pBt->nTrunc = nFin;
@@ -29857,9 +32342,9 @@
return rc;
}
}
#endif
- rc = sqlite3PagerCommitPhaseOne(pBt->pPager, zMaster, nTrunc);
+ rc = sqlite3PagerCommitPhaseOne(pBt->pPager, zMaster, nTrunc, 0);
sqlite3BtreeLeave(p);
}
return rc;
}
@@ -30133,25 +32618,8 @@
return rc;
}
/*
-** Default key comparison function to be used if no comparison function
-** is specified on the sqlite3BtreeCursor() call.
-*/
-static int dfltCompare(
- void *NotUsed, /* User data is not used */
- int n1, const void *p1, /* First key to compare */
- int n2, const void *p2 /* Second key to compare */
-){
- int c;
- c = memcmp(p1, p2, n1<n2 ? n1 : n2);
- if( c==0 ){
- c = n1 - n2;
- }
- return c;
-}
-
-/*
** Create a new cursor for the BTree whose root is on the page
** iTable. The act of acquiring a cursor gets a read lock on
** the database file.
**
@@ -30175,29 +32643,20 @@
**
** No checking is done to make sure that page iTable really is the
** root page of a b-tree. If it is not, then the cursor acquired
** will not work correctly.
-**
-** The comparison function must be logically the same for every cursor
-** on a particular table. Changing the comparison function will result
-** in incorrect operations. If the comparison function is NULL, a
-** default comparison function is used. The comparison function is
-** always ignored for INTKEY tables.
*/
static int btreeCursor(
- Btree *p, /* The btree */
- int iTable, /* Root page of table to open */
- int wrFlag, /* 1 to write. 0 read-only */
- int (*xCmp)(void*,int,const void*,int,const void*), /* Key Comparison func */
- void *pArg, /* First arg to xCompare() */
- BtCursor **ppCur /* Write new cursor here */
-){
- int rc;
- BtCursor *pCur;
+ Btree *p, /* The btree */
+ int iTable, /* Root page of table to open */
+ int wrFlag, /* 1 to write. 0 read-only */
+ struct KeyInfo *pKeyInfo, /* First arg to comparison function */
+ BtCursor *pCur /* Space for new cursor */
+){
+ int rc;
BtShared *pBt = p->pBt;
assert( sqlite3BtreeHoldsMutex(p) );
- *ppCur = 0;
if( wrFlag ){
if( pBt->readOnly ){
return SQLITE_READONLY;
}
@@ -30214,13 +32673,8 @@
if( pBt->readOnly && wrFlag ){
return SQLITE_READONLY;
}
}
- pCur = sqlite3MallocZero( sizeof(*pCur) );
- if( pCur==0 ){
- rc = SQLITE_NOMEM;
- goto create_cursor_exception;
- }
pCur->pgnoRoot = (Pgno)iTable;
if( iTable==1 && sqlite3PagerPagecount(pBt->pPager)==0 ){
rc = SQLITE_EMPTY;
goto create_cursor_exception;
@@ -30233,10 +32687,9 @@
/* Now that no other errors can occur, finish filling in the BtCursor
** variables, link the cursor into the BtShared list and set *ppCur (the
** output argument to this function).
*/
- pCur->xCompare = xCmp ? xCmp : dfltCompare;
- pCur->pArg = pArg;
+ pCur->pKeyInfo = pKeyInfo;
pCur->pBtree = p;
pCur->pBt = pBt;
pCur->wrFlag = wrFlag;
pCur->pNext = pBt->pCursor;
@@ -30244,16 +32697,14 @@
pCur->pNext->pPrev = pCur;
}
pBt->pCursor = pCur;
pCur->eState = CURSOR_INVALID;
- *ppCur = pCur;
return SQLITE_OK;
create_cursor_exception:
if( pCur ){
releasePage(pCur->pPage);
- sqlite3_free(pCur);
}
unlockBtreeIfUnused(pBt);
return rc;
}
@@ -30260,45 +32711,49 @@
SQLITE_PRIVATE int sqlite3BtreeCursor(
Btree *p, /* The btree */
int iTable, /* Root page of table to open */
int wrFlag, /* 1 to write. 0 read-only */
- int (*xCmp)(void*,int,const void*,int,const void*), /* Key Comparison func */
- void *pArg, /* First arg to xCompare() */
- BtCursor **ppCur /* Write new cursor here */
+ struct KeyInfo *pKeyInfo, /* First arg to xCompare() */
+ BtCursor *pCur /* Write new cursor here */
){
int rc;
sqlite3BtreeEnter(p);
p->pBt->db = p->db;
- rc = btreeCursor(p, iTable, wrFlag, xCmp, pArg, ppCur);
+ rc = btreeCursor(p, iTable, wrFlag, pKeyInfo, pCur);
sqlite3BtreeLeave(p);
return rc;
}
+SQLITE_PRIVATE int sqlite3BtreeCursorSize(){
+ return sizeof(BtCursor);
+}
+
/*
** Close a cursor. The read lock on the database file is released
** when the last cursor is closed.
*/
SQLITE_PRIVATE int sqlite3BtreeCloseCursor(BtCursor *pCur){
- BtShared *pBt = pCur->pBt;
Btree *pBtree = pCur->pBtree;
-
- sqlite3BtreeEnter(pBtree);
- pBt->db = pBtree->db;
- clearCursorPosition(pCur);
- if( pCur->pPrev ){
- pCur->pPrev->pNext = pCur->pNext;
- }else{
- pBt->pCursor = pCur->pNext;
- }
- if( pCur->pNext ){
- pCur->pNext->pPrev = pCur->pPrev;
- }
- releasePage(pCur->pPage);
- unlockBtreeIfUnused(pBt);
- invalidateOverflowCache(pCur);
- sqlite3_free(pCur);
- sqlite3BtreeLeave(pBtree);
+ if( pBtree ){
+ BtShared *pBt = pCur->pBt;
+ sqlite3BtreeEnter(pBtree);
+ pBt->db = pBtree->db;
+ clearCursorPosition(pCur);
+ if( pCur->pPrev ){
+ pCur->pPrev->pNext = pCur->pNext;
+ }else{
+ pBt->pCursor = pCur->pNext;
+ }
+ if( pCur->pNext ){
+ pCur->pNext->pPrev = pCur->pPrev;
+ }
+ releasePage(pCur->pPage);
+ unlockBtreeIfUnused(pBt);
+ invalidateOverflowCache(pCur);
+ /* sqlite3_free(pCur); */
+ sqlite3BtreeLeave(pBtree);
+ }
return SQLITE_OK;
}
/*
@@ -30355,8 +32810,9 @@
/* Use a real function in MSVC to work around bugs in that compiler. */
static void getCellInfo(BtCursor *pCur){
if( pCur->info.nSize==0 ){
sqlite3BtreeParseCell(pCur->pPage, pCur->idx, &pCur->info);
+ pCur->validNKey = 1;
}else{
assertCellInfo(pCur);
}
}
@@ -30364,8 +32820,9 @@
/* Use a macro in all other compilers so that the function is inlined */
#define getCellInfo(pCur) \
if( pCur->info.nSize==0 ){ \
sqlite3BtreeParseCell(pCur->pPage, pCur->idx, &pCur->info); \
+ pCur->validNKey = 1; \
}else{ \
assertCellInfo(pCur); \
}
#endif /* _MSC_VER */
@@ -30857,8 +33314,9 @@
releasePage(pOldPage);
pCur->pPage = pNewPage;
pCur->idx = 0;
pCur->info.nSize = 0;
+ pCur->validNKey = 0;
if( pNewPage->nCell<1 ){
return SQLITE_CORRUPT_BKPT;
}
return SQLITE_OK;
@@ -30908,8 +33366,9 @@
sqlite3PagerRef(pParent->pDbPage);
releasePage(pPage);
pCur->pPage = pParent;
pCur->info.nSize = 0;
+ pCur->validNKey = 0;
assert( pParent->idxShift==0 );
pCur->idx = idxParent;
}
@@ -30946,8 +33405,10 @@
pCur->pPage = pRoot;
}
pCur->idx = 0;
pCur->info.nSize = 0;
+ pCur->atLast = 0;
+ pCur->validNKey = 0;
if( pRoot->nCell==0 && !pRoot->leaf ){
Pgno subpage;
assert( pRoot->pgno==1 );
subpage = get4byte(&pRoot->aData[pRoot->hdrOffset+8]);
@@ -31005,8 +33466,9 @@
}
if( rc==SQLITE_OK ){
pCur->idx = pPage->nCell - 1;
pCur->info.nSize = 0;
+ pCur->validNKey = 0;
}
return SQLITE_OK;
}
@@ -31051,20 +33513,22 @@
}else{
assert( pCur->eState==CURSOR_VALID );
*pRes = 0;
rc = moveToRightmost(pCur);
- }
- }
- return rc;
-}
-
-/* Move the cursor so that it points to an entry near pKey/nKey.
-** Return a success code.
-**
-** For INTKEY tables, only the nKey parameter is used. pKey is
-** ignored. For other tables, nKey is the number of bytes of data
-** in pKey. The comparison function specified when the cursor was
-** created is used to compare keys.
+ getCellInfo(pCur);
+ pCur->atLast = rc==SQLITE_OK;
+ }
+ }
+ return rc;
+}
+
+/* Move the cursor so that it points to an entry near the key
+** specified by pKey/nKey/pUnKey. Return a success code.
+**
+** For INTKEY tables, only the nKey parameter is used. pKey
+** and pUnKey must be NULL. For index tables, either pUnKey
+** must point to a key that has already been unpacked, or else
+** pKey/nKey describes a blob containing the key.
**
** If an exact match is not found, then the cursor is always
** left pointing at a leaf page which would hold the entry if it
** were present. The cursor might point to an entry that comes
@@ -31087,16 +33551,33 @@
*/
SQLITE_PRIVATE int sqlite3BtreeMoveto(
BtCursor *pCur, /* The cursor to be moved */
const void *pKey, /* The key content for indices. Not used by tables */
+ UnpackedRecord *pUnKey,/* Unpacked version of pKey */
i64 nKey, /* Size of pKey. Or the key for tables */
int biasRight, /* If true, bias the search to the high end */
int *pRes /* Search result flag */
){
int rc;
+ char aSpace[200];
assert( cursorHoldsMutex(pCur) );
assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
+
+ /* If the cursor is already positioned at the point we are trying
+ ** to move to, then just return without doing any work */
+ if( pCur->eState==CURSOR_VALID && pCur->validNKey && pCur->pPage->intKey ){
+ if( pCur->info.nKey==nKey ){
+ *pRes = 0;
+ return SQLITE_OK;
+ }
+ if( pCur->atLast && pCur->info.nKey<nKey ){
+ *pRes = -1;
+ return SQLITE_OK;
+ }
+ }
+
+
rc = moveToRoot(pCur);
if( rc ){
return rc;
}
@@ -31106,17 +33587,36 @@
*pRes = -1;
assert( pCur->pPage->nCell==0 );
return SQLITE_OK;
}
+ if( pCur->pPage->intKey ){
+ /* We are given an SQL table to search. The key is the integer
+ ** rowid contained in nKey. pKey and pUnKey should both be NULL */
+ assert( pUnKey==0 );
+ assert( pKey==0 );
+ }else if( pUnKey==0 ){
+ /* We are to search an SQL index using a key encoded as a blob.
+ ** The blob is found at pKey and is nKey bytes in length. Unpack
+ ** this key so that we can use it. */
+ assert( pKey!=0 );
+ pUnKey = sqlite3VdbeRecordUnpack(pCur->pKeyInfo, nKey, pKey,
+ aSpace, sizeof(aSpace));
+ if( pUnKey==0 ) return SQLITE_NOMEM;
+ }else{
+ /* We are to search an SQL index using a key that is already unpacked
+ ** and handed to us in pUnKey. */
+ assert( pKey==0 );
+ }
for(;;){
int lwr, upr;
Pgno chldPg;
MemPage *pPage = pCur->pPage;
int c = -1; /* pRes return if table is empty must be -1 */
lwr = 0;
upr = pPage->nCell-1;
- if( !pPage->intKey && pKey==0 ){
- return SQLITE_CORRUPT_BKPT;
+ if( !pPage->intKey && pUnKey==0 ){
+ rc = SQLITE_CORRUPT_BKPT;
+ goto moveto_finish;
}
if( biasRight ){
pCur->idx = upr;
}else{
@@ -31125,48 +33625,53 @@
if( lwr<=upr ) for(;;){
void *pCellKey;
i64 nCellKey;
pCur->info.nSize = 0;
+ pCur->validNKey = 1;
if( pPage->intKey ){
u8 *pCell;
pCell = findCell(pPage, pCur->idx) + pPage->childPtrSize;
if( pPage->hasData ){
u32 dummy;
- pCell += getVarint32(pCell, &dummy);
- }
- getVarint(pCell, (u64 *)&nCellKey);
- if( nCellKey<nKey ){
+ pCell += getVarint32(pCell, dummy);
+ }
+ getVarint(pCell, (u64*)&nCellKey);
+ if( nCellKey==nKey ){
+ c = 0;
+ }else if( nCellKey<nKey ){
c = -1;
- }else if( nCellKey>nKey ){
- c = +1;
- }else{
- c = 0;
+ }else{
+ assert( nCellKey>nKey );
+ c = +1;
}
}else{
int available;
pCellKey = (void *)fetchPayload(pCur, &available, 0);
nCellKey = pCur->info.nKey;
if( available>=nCellKey ){
- c = pCur->xCompare(pCur->pArg, nCellKey, pCellKey, nKey, pKey);
+ c = sqlite3VdbeRecordCompare(nCellKey, pCellKey, pUnKey);
}else{
pCellKey = sqlite3_malloc( nCellKey );
- if( pCellKey==0 ) return SQLITE_NOMEM;
+ if( pCellKey==0 ){
+ rc = SQLITE_NOMEM;
+ goto moveto_finish;
+ }
rc = sqlite3BtreeKey(pCur, 0, nCellKey, (void *)pCellKey);
- c = pCur->xCompare(pCur->pArg, nCellKey, pCellKey, nKey, pKey);
+ c = sqlite3VdbeRecordCompare(nCellKey, pCellKey, pUnKey);
sqlite3_free(pCellKey);
- if( rc ){
- return rc;
- }
+ if( rc ) goto moveto_finish;
}
}
if( c==0 ){
+ pCur->info.nKey = nCellKey;
if( pPage->leafData && !pPage->leaf ){
lwr = pCur->idx;
upr = lwr - 1;
break;
}else{
if( pRes ) *pRes = 0;
- return SQLITE_OK;
+ rc = SQLITE_OK;
+ goto moveto_finish;
}
}
if( c<0 ){
lwr = pCur->idx+1;
@@ -31173,8 +33678,9 @@
}else{
upr = pCur->idx-1;
}
if( lwr>upr ){
+ pCur->info.nKey = nCellKey;
break;
}
pCur->idx = (lwr+upr)/2;
}
@@ -31189,18 +33695,24 @@
}
if( chldPg==0 ){
assert( pCur->idx>=0 && pCur->idx<pCur->pPage->nCell );
if( pRes ) *pRes = c;
- return SQLITE_OK;
+ rc = SQLITE_OK;
+ goto moveto_finish;
}
pCur->idx = lwr;
pCur->info.nSize = 0;
+ pCur->validNKey = 0;
rc = moveToChild(pCur, chldPg);
- if( rc ){
- return rc;
- }
- }
- /* NOT REACHED */
+ if( rc ) goto moveto_finish;
+ }
+moveto_finish:
+ if( pKey ){
+ /* If we created our own unpacked key at the top of this
+ ** procedure, then destroy that key before returning. */
+ sqlite3VdbeDeleteUnpackedRecord(pUnKey);
+ }
+ return rc;
}
/*
@@ -31231,9 +33743,9 @@
** successful then set *pRes=0. If the cursor
** was already pointing to the last entry in the database before
** this routine was called, then set *pRes=1.
*/
-static int btreeNext(BtCursor *pCur, int *pRes){
+SQLITE_PRIVATE int sqlite3BtreeNext(BtCursor *pCur, int *pRes){
int rc;
MemPage *pPage;
assert( cursorHoldsMutex(pCur) );
@@ -31258,8 +33770,9 @@
assert( pCur->idx<pPage->nCell );
pCur->idx++;
pCur->info.nSize = 0;
+ pCur->validNKey = 0;
if( pCur->idx>=pPage->nCell ){
if( !pPage->leaf ){
rc = moveToChild(pCur, get4byte(&pPage->aData[pPage->hdrOffset+8]));
if( rc ) return rc;
@@ -31290,14 +33803,8 @@
}
rc = moveToLeftmost(pCur);
return rc;
}
-SQLITE_PRIVATE int sqlite3BtreeNext(BtCursor *pCur, int *pRes){
- int rc;
- assert( cursorHoldsMutex(pCur) );
- rc = btreeNext(pCur, pRes);
- return rc;
-}
/*
** Step the cursor to the back to the previous entry in the database. If
@@ -31304,9 +33811,9 @@
** successful then set *pRes=0. If the cursor
** was already pointing to the first entry in the database before
** this routine was called, then set *pRes=1.
*/
-static int btreePrevious(BtCursor *pCur, int *pRes){
+SQLITE_PRIVATE int sqlite3BtreePrevious(BtCursor *pCur, int *pRes){
int rc;
Pgno pgno;
MemPage *pPage;
@@ -31314,8 +33821,9 @@
rc = restoreOrClearCursorPosition(pCur);
if( rc!=SQLITE_OK ){
return rc;
}
+ pCur->atLast = 0;
if( CURSOR_INVALID==pCur->eState ){
*pRes = 1;
return SQLITE_OK;
}
@@ -31347,21 +33855,16 @@
pPage = pCur->pPage;
}
pCur->idx--;
pCur->info.nSize = 0;
+ pCur->validNKey = 0;
if( pPage->leafData && !pPage->leaf ){
rc = sqlite3BtreePrevious(pCur, pRes);
}else{
rc = SQLITE_OK;
}
}
*pRes = 0;
- return rc;
-}
-SQLITE_PRIVATE int sqlite3BtreePrevious(BtCursor *pCur, int *pRes){
- int rc;
- assert( cursorHoldsMutex(pCur) );
- rc = btreePrevious(pCur, pRes);
return rc;
}
/*
@@ -31549,9 +34052,10 @@
if( !searchList || iPage==nearby ){
*pPgno = iPage;
if( *pPgno>sqlite3PagerPagecount(pBt->pPager) ){
/* Free page off the end of the file */
- return SQLITE_CORRUPT_BKPT;
+ rc = SQLITE_CORRUPT_BKPT;
+ goto end_allocate_page;
}
TRACE(("ALLOCATE: %d was leaf %d of %d on trunk %d"
": %d more free pages\n",
*pPgno, closest+1, k, pTrunk->pgno, n-1));
@@ -31938,18 +34442,14 @@
if( pPage->leaf ) return SQLITE_OK;
for(i=0; i<pPage->nCell; i++){
u8 *pCell = findCell(pPage, i);
- if( !pPage->leaf ){
- rc = reparentPage(pBt, get4byte(pCell), pPage, i);
- if( rc!=SQLITE_OK ) return rc;
- }
- }
- if( !pPage->leaf ){
- rc = reparentPage(pBt, get4byte(&pPage->aData[pPage->hdrOffset+8]),
- pPage, i);
- pPage->idxShift = 0;
- }
+ rc = reparentPage(pBt, get4byte(pCell), pPage, i);
+ if( rc!=SQLITE_OK ) return rc;
+ }
+ rc = reparentPage(pBt, get4byte(&pPage->aData[pPage->hdrOffset+8]),
+ pPage, i);
+ pPage->idxShift = 0;
return rc;
}
/*
@@ -32091,9 +34591,9 @@
static void assemblePage(
MemPage *pPage, /* The page to be assemblied */
int nCell, /* The number of cells to add to this page */
u8 **apCell, /* Pointers to cell bodies */
- int *aSize /* Sizes of the cells */
+ u16 *aSize /* Sizes of the cells */
){
int i; /* Loop counter */
int totalSize; /* Total size of all cells */
int hdr; /* Index of page header */
@@ -32169,9 +34669,9 @@
int rc;
MemPage *pNew;
Pgno pgnoNew;
u8 *pCell;
- int szCell;
+ u16 szCell;
CellInfo info;
BtShared *pBt = pPage->pBt;
int parentIdx = pParent->nCell; /* pParent new divider cell index */
int parentSize; /* Size of new divider cell */
@@ -32295,9 +34795,9 @@
u8 *apDiv[NB]; /* Divider cells in pParent */
int cntNew[NB+2]; /* Index in aCell[] of cell after i-th page */
int szNew[NB+2]; /* Combined size of cells place on i-th page */
u8 **apCell = 0; /* All cells begin balanced */
- int *szCell; /* Local size of all cells in apCell[] */
+ u16 *szCell; /* Local size of all cells in apCell[] */
u8 *aCopy[NB]; /* Space for holding data of apCopy[] */
u8 *aSpace; /* Space to hold copies of dividers cells */
#ifndef SQLITE_OMIT_AUTOVACUUM
u8 *aFrom = 0;
@@ -32408,27 +34908,27 @@
nOld++;
nMaxCells += 1+apOld[i]->nCell+apOld[i]->nOverflow;
}
- /* Make nMaxCells a multiple of 2 in order to preserve 8-byte
+ /* Make nMaxCells a multiple of 4 in order to preserve 8-byte
** alignment */
- nMaxCells = (nMaxCells + 1)&~1;
+ nMaxCells = (nMaxCells + 3)&~3;
/*
** Allocate space for memory structures
*/
apCell = sqlite3_malloc(
- nMaxCells*sizeof(u8*) /* apCell */
- + nMaxCells*sizeof(int) /* szCell */
- + ROUND8(sizeof(MemPage))*NB /* aCopy */
- + pBt->pageSize*(5+NB) /* aSpace */
- + (ISAUTOVACUUM ? nMaxCells : 0) /* aFrom */
+ nMaxCells*sizeof(u8*) /* apCell */
+ + nMaxCells*sizeof(u16) /* szCell */
+ + (ROUND8(sizeof(MemPage))+pBt->pageSize)*NB /* aCopy */
+ + pBt->pageSize*5 /* aSpace */
+ + (ISAUTOVACUUM ? nMaxCells : 0) /* aFrom */
);
if( apCell==0 ){
rc = SQLITE_NOMEM;
goto balance_cleanup;
}
- szCell = (int*)&apCell[nMaxCells];
+ szCell = (u16*)&apCell[nMaxCells];
aCopy[0] = (u8*)&szCell[nMaxCells];
assert( ((aCopy[0] - (u8*)apCell) & 7)==0 ); /* 8-byte alignment required */
for(i=1; i<NB; i++){
aCopy[i] = &aCopy[i-1][pBt->pageSize+ROUND8(sizeof(MemPage))];
@@ -32495,9 +34995,9 @@
#endif
nCell++;
}
if( i<nOld-1 ){
- int sz = cellSizePtr(pParent, apDiv[i]);
+ u16 sz = cellSizePtr(pParent, apDiv[i]);
if( leafData ){
/* With the LEAFDATA flag, pParent cells hold only INTKEYs that
** are duplicates of keys on the child pages. We need to remove
** the divider cells from pParent, but the dividers cells are not
@@ -32849,18 +35349,18 @@
int rc = SQLITE_OK; /* Return code from subprocedures */
BtShared *pBt; /* The main BTree structure */
int mxCellPerPage; /* Maximum number of cells per page */
u8 **apCell; /* All cells from pages being balanced */
- int *szCell; /* Local size of all cells */
+ u16 *szCell; /* Local size of all cells */
assert( pPage->pParent==0 );
assert( pPage->nCell==0 );
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
pBt = pPage->pBt;
mxCellPerPage = MX_CELL(pBt);
- apCell = sqlite3_malloc( mxCellPerPage*(sizeof(u8*)+sizeof(int)) );
+ apCell = sqlite3_malloc( mxCellPerPage*(sizeof(u8*)+sizeof(u16)) );
if( apCell==0 ) return SQLITE_NOMEM;
- szCell = (int*)&apCell[mxCellPerPage];
+ szCell = (u16*)&apCell[mxCellPerPage];
if( pPage->leaf ){
/* The table is completely empty */
TRACE(("BALANCE: empty table %d\n", pPage->pgno));
}else{
@@ -33064,8 +35564,18 @@
return SQLITE_OK;
}
/*
+** Make sure pBt->pTmpSpace points to an allocation of
+** MX_CELL_SIZE(pBt) bytes.
+*/
+static void allocateTempSpace(BtShared *pBt){
+ if( !pBt->pTmpSpace ){
+ pBt->pTmpSpace = sqlite3_malloc(MX_CELL_SIZE(pBt));
+ }
+}
+
+/*
** Insert a new record into the BTree. The key is given by (pKey,nKey)
** and the data is given by (pData,nData). The cursor is used only to
** define what table the record should be inserted into. The cursor
** is left pointing at a random location.
@@ -33109,9 +35619,9 @@
/* Save the positions of any other cursors open on this table */
clearCursorPosition(pCur);
if(
SQLITE_OK!=(rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur)) ||
- SQLITE_OK!=(rc = sqlite3BtreeMoveto(pCur, pKey, nKey, appendBias, &loc))
+ SQLITE_OK!=(rc = sqlite3BtreeMoveto(pCur, pKey, 0, nKey, appendBias, &loc))
){
return rc;
}
@@ -33121,16 +35631,17 @@
TRACE(("INSERT: table=%d nkey=%lld ndata=%d page=%d %s\n",
pCur->pgnoRoot, nKey, nData, pPage->pgno,
loc==0 ? "overwrite" : "new entry"));
assert( pPage->isInit );
- newCell = sqlite3_malloc( MX_CELL_SIZE(pBt) );
+ allocateTempSpace(pBt);
+ newCell = pBt->pTmpSpace;
if( newCell==0 ) return SQLITE_NOMEM;
rc = fillInCell(pPage, newCell, pKey, nKey, pData, nData, nZero, &szNew);
if( rc ) goto end_insert;
assert( szNew==cellSizePtr(pPage, newCell) );
assert( szNew<=MX_CELL_SIZE(pBt) );
if( loc==0 && CURSOR_VALID==pCur->eState ){
- int szOld;
+ u16 szOld;
assert( pCur->idx>=0 && pCur->idx<pPage->nCell );
rc = sqlite3PagerWrite(pPage->pDbPage);
if( rc ){
goto end_insert;
@@ -33146,8 +35657,9 @@
}else if( loc<0 && pPage->nCell>0 ){
assert( pPage->leaf );
pCur->idx++;
pCur->info.nSize = 0;
+ pCur->validNKey = 0;
}else{
assert( pPage->leaf );
}
rc = insertCell(pPage, pCur->idx, newCell, szNew, 0, 0);
@@ -33158,9 +35670,8 @@
if( rc==SQLITE_OK ){
moveToRoot(pCur);
}
end_insert:
- sqlite3_free(newCell);
return rc;
}
/*
@@ -33240,16 +35751,17 @@
if( rc==SQLITE_OK ){
rc = sqlite3PagerWrite(leafCur.pPage->pDbPage);
}
if( rc==SQLITE_OK ){
- int szNext;
+ u16 szNext;
TRACE(("DELETE: table=%d delete internal from %d replace from leaf %d\n",
pCur->pgnoRoot, pPage->pgno, leafCur.pPage->pgno));
dropCell(pPage, pCur->idx, cellSizePtr(pPage, pCell));
pNext = findCell(leafCur.pPage, leafCur.idx);
szNext = cellSizePtr(leafCur.pPage, pNext);
assert( MX_CELL_SIZE(pBt)>=szNext+4 );
- tempCell = sqlite3_malloc( MX_CELL_SIZE(pBt) );
+ allocateTempSpace(pBt);
+ tempCell = pBt->pTmpSpace;
if( tempCell==0 ){
rc = SQLITE_NOMEM;
}
if( rc==SQLITE_OK ){
@@ -33263,9 +35775,8 @@
dropCell(leafCur.pPage, leafCur.idx, szNext);
rc = balance(leafCur.pPage, 0);
}
}
- sqlite3_free(tempCell);
sqlite3BtreeReleaseTempCursor(&leafCur);
}else{
TRACE(("DELETE: table=%d delete from leaf %d\n",
pCur->pgnoRoot, pPage->pgno));
@@ -34025,9 +36536,9 @@
nCell = get2byte(&data[hdr+3]);
cellStart = hdr + 12 - 4*pPage->leaf;
for(i=0; i<nCell; i++){
int pc = get2byte(&data[cellStart+i*2]);
- int size = cellSizePtr(pPage, &data[pc]);
+ u16 size = cellSizePtr(pPage, &data[pc]);
int j;
if( (pc+size-1)>=usableSize || pc<0 ){
checkAppendMsg(pCheck, 0,
"Corruption detected in cell %d on page %d",i,iPage,0);
@@ -34227,64 +36738,207 @@
/*
** Copy the complete content of pBtFrom into pBtTo. A transaction
** must be active for both files.
**
-** The size of file pBtFrom may be reduced by this operation.
-** If anything goes wrong, the transaction on pBtFrom is rolled back.
+** The size of file pTo may be reduced by this operation.
+** If anything goes wrong, the transaction on pTo is rolled back.
+**
+** If successful, CommitPhaseOne() may be called on pTo before returning.
+** The caller should finish committing the transaction on pTo by calling
+** sqlite3BtreeCommit().
*/
static int btreeCopyFile(Btree *pTo, Btree *pFrom){
int rc = SQLITE_OK;
- Pgno i, nPage, nToPage, iSkip;
+ Pgno i;
+
+ Pgno nFromPage; /* Number of pages in pFrom */
+ Pgno nToPage; /* Number of pages in pTo */
+ Pgno nNewPage; /* Number of pages in pTo after the copy */
+
+ Pgno iSkip; /* Pending byte page in pTo */
+ int nToPageSize; /* Page size of pTo in bytes */
+ int nFromPageSize; /* Page size of pFrom in bytes */
BtShared *pBtTo = pTo->pBt;
BtShared *pBtFrom = pFrom->pBt;
pBtTo->db = pTo->db;
pBtFrom->db = pFrom->db;
+ nToPageSize = pBtTo->pageSize;
+ nFromPageSize = pBtFrom->pageSize;
if( pTo->inTrans!=TRANS_WRITE || pFrom->inTrans!=TRANS_WRITE ){
return SQLITE_ERROR;
}
- if( pBtTo->pCursor ) return SQLITE_BUSY;
+ if( pBtTo->pCursor ){
+ return SQLITE_BUSY;
+ }
+
nToPage = sqlite3PagerPagecount(pBtTo->pPager);
- nPage = sqlite3PagerPagecount(pBtFrom->pPager);
+ nFromPage = sqlite3PagerPagecount(pBtFrom->pPager);
iSkip = PENDING_BYTE_PAGE(pBtTo);
- for(i=1; rc==SQLITE_OK && i<=nPage; i++){
- DbPage *pDbPage;
- if( i==iSkip ) continue;
- rc = sqlite3PagerGet(pBtFrom->pPager, i, &pDbPage);
- if( rc ) break;
- rc = sqlite3PagerOverwrite(pBtTo->pPager, i, sqlite3PagerGetData(pDbPage));
- sqlite3PagerUnref(pDbPage);
- }
-
- /* If the file is shrinking, journal the pages that are being truncated
- ** so that they can be rolled back if the commit fails.
- */
- for(i=nPage+1; rc==SQLITE_OK && i<=nToPage; i++){
- DbPage *pDbPage;
- if( i==iSkip ) continue;
- rc = sqlite3PagerGet(pBtTo->pPager, i, &pDbPage);
- if( rc ) break;
- rc = sqlite3PagerWrite(pDbPage);
- sqlite3PagerDontWrite(pDbPage);
- /* Yeah. It seems wierd to call DontWrite() right after Write(). But
- ** that is because the names of those procedures do not exactly
- ** represent what they do. Write() really means "put this page in the
- ** rollback journal and mark it as dirty so that it will be written
- ** to the database file later." DontWrite() undoes the second part of
- ** that and prevents the page from being written to the database. The
- ** page is still on the rollback journal, though. And that is the whole
- ** point of this loop: to put pages on the rollback journal. */
- sqlite3PagerUnref(pDbPage);
- }
- if( !rc && nPage<nToPage ){
- rc = sqlite3PagerTruncate(pBtTo->pPager, nPage);
+
+ /* Variable nNewPage is the number of pages required to store the
+ ** contents of pFrom using the current page-size of pTo.
+ */
+ nNewPage = ((i64)nFromPage * (i64)nFromPageSize + (i64)nToPageSize - 1) /
+ (i64)nToPageSize;
+
+ for(i=1; rc==SQLITE_OK && (i<=nToPage || i<=nNewPage); i++){
+
+ /* Journal the original page.
+ **
+ ** iSkip is the page number of the locking page (PENDING_BYTE_PAGE)
+ ** in database *pTo (before the copy). This page is never written
+ ** into the journal file. Unless i==iSkip or the page was not
+ ** present in pTo before the copy operation, journal page i from pTo.
+ */
+ if( i!=iSkip && i<=nToPage ){
+ DbPage *pDbPage = 0;
+ rc = sqlite3PagerGet(pBtTo->pPager, i, &pDbPage);
+ if( rc==SQLITE_OK ){
+ rc = sqlite3PagerWrite(pDbPage);
+ if( rc==SQLITE_OK && i>nFromPage ){
+ /* Yeah. It seems wierd to call DontWrite() right after Write(). But
+ ** that is because the names of those procedures do not exactly
+ ** represent what they do. Write() really means "put this page in the
+ ** rollback journal and mark it as dirty so that it will be written
+ ** to the database file later." DontWrite() undoes the second part of
+ ** that and prevents the page from being written to the database. The
+ ** page is still on the rollback journal, though. And that is the
+ ** whole point of this block: to put pages on the rollback journal.
+ */
+ sqlite3PagerDontWrite(pDbPage);
+ }
+ sqlite3PagerUnref(pDbPage);
+ }
+ }
+
+ /* Overwrite the data in page i of the target database */
+ if( rc==SQLITE_OK && i!=iSkip && i<=nNewPage ){
+
+ DbPage *pToPage = 0;
+ sqlite3_int64 iOff;
+
+ rc = sqlite3PagerGet(pBtTo->pPager, i, &pToPage);
+ if( rc==SQLITE_OK ){
+ rc = sqlite3PagerWrite(pToPage);
+ }
+
+ for(
+ iOff=(i-1)*nToPageSize;
+ rc==SQLITE_OK && iOff<i*nToPageSize;
+ iOff += nFromPageSize
+ ){
+ DbPage *pFromPage = 0;
+ Pgno iFrom = (iOff/nFromPageSize)+1;
+
+ if( iFrom==PENDING_BYTE_PAGE(pBtFrom) ){
+ continue;
+ }
+
+ rc = sqlite3PagerGet(pBtFrom->pPager, iFrom, &pFromPage);
+ if( rc==SQLITE_OK ){
+ char *zTo = sqlite3PagerGetData(pToPage);
+ char *zFrom = sqlite3PagerGetData(pFromPage);
+ int nCopy;
+
+ if( nFromPageSize>=nToPageSize ){
+ zFrom += ((i-1)*nToPageSize - ((iFrom-1)*nFromPageSize));
+ nCopy = nToPageSize;
+ }else{
+ zTo += (((iFrom-1)*nFromPageSize) - (i-1)*nToPageSize);
+ nCopy = nFromPageSize;
+ }
+
+ memcpy(zTo, zFrom, nCopy);
+ sqlite3PagerUnref(pFromPage);
+ }
+ }
+
+ if( pToPage ) sqlite3PagerUnref(pToPage);
+ }
+ }
+
+ /* If things have worked so far, the database file may need to be
+ ** truncated. The complex part is that it may need to be truncated to
+ ** a size that is not an integer multiple of nToPageSize - the current
+ ** page size used by the pager associated with B-Tree pTo.
+ **
+ ** For example, say the page-size of pTo is 2048 bytes and the original
+ ** number of pages is 5 (10 KB file). If pFrom has a page size of 1024
+ ** bytes and 9 pages, then the file needs to be truncated to 9KB.
+ */
+ if( rc==SQLITE_OK ){
+ if( nFromPageSize!=nToPageSize ){
+ sqlite3_file *pFile = sqlite3PagerFile(pBtTo->pPager);
+ i64 iSize = (i64)nFromPageSize * (i64)nFromPage;
+ i64 iNow = (i64)((nToPage>nNewPage)?nToPage:nNewPage) * (i64)nToPageSize;
+ i64 iPending = ((i64)PENDING_BYTE_PAGE(pBtTo)-1) *(i64)nToPageSize;
+
+ assert( iSize<=iNow );
+
+ /* Commit phase one syncs the journal file associated with pTo
+ ** containing the original data. It does not sync the database file
+ ** itself. After doing this it is safe to use OsTruncate() and other
+ ** file APIs on the database file directly.
+ */
+ pBtTo->db = pTo->db;
+ rc = sqlite3PagerCommitPhaseOne(pBtTo->pPager, 0, 0, 1);
+ if( iSize<iNow && rc==SQLITE_OK ){
+ rc = sqlite3OsTruncate(pFile, iSize);
+ }
+
+ /* The loop that copied data from database pFrom to pTo did not
+ ** populate the locking page of database pTo. If the page-size of
+ ** pFrom is smaller than that of pTo, this means some data will
+ ** not have been copied.
+ **
+ ** This block copies the missing data from database pFrom to pTo
+ ** using file APIs. This is safe because at this point we know that
+ ** all of the original data from pTo has been synced into the
+ ** journal file. At this point it would be safe to do anything at
+ ** all to the database file except truncate it to zero bytes.
+ */
+ if( rc==SQLITE_OK && nFromPageSize<nToPageSize && iSize>iPending){
+ i64 iOff;
+ for(
+ iOff=iPending;
+ rc==SQLITE_OK && iOff<(iPending+nToPageSize);
+ iOff += nFromPageSize
+ ){
+ DbPage *pFromPage = 0;
+ Pgno iFrom = (iOff/nFromPageSize)+1;
+
+ if( iFrom==PENDING_BYTE_PAGE(pBtFrom) || iFrom>nFromPage ){
+ continue;
+ }
+
+ rc = sqlite3PagerGet(pBtFrom->pPager, iFrom, &pFromPage);
+ if( rc==SQLITE_OK ){
+ char *zFrom = sqlite3PagerGetData(pFromPage);
+ rc = sqlite3OsWrite(pFile, zFrom, nFromPageSize, iOff);
+ sqlite3PagerUnref(pFromPage);
+ }
+ }
+ }
+
+ /* Sync the database file */
+ if( rc==SQLITE_OK ){
+ rc = sqlite3PagerSync(pBtTo->pPager);
+ }
+ }else{
+ rc = sqlite3PagerTruncate(pBtTo->pPager, nNewPage);
+ }
+ if( rc==SQLITE_OK ){
+ pBtTo->pageSizeFixed = 0;
+ }
}
if( rc ){
sqlite3BtreeRollback(pTo);
}
+
return rc;
}
SQLITE_PRIVATE int sqlite3BtreeCopyFile(Btree *pTo, Btree *pFrom){
int rc;
@@ -34370,15 +37024,19 @@
** if it is false.
*/
SQLITE_PRIVATE int sqlite3BtreeLockTable(Btree *p, int iTab, u8 isWriteLock){
int rc = SQLITE_OK;
- u8 lockType = (isWriteLock?WRITE_LOCK:READ_LOCK);
- sqlite3BtreeEnter(p);
- rc = queryTableLock(p, iTab, lockType);
- if( rc==SQLITE_OK ){
- rc = lockTable(p, iTab, lockType);
- }
- sqlite3BtreeLeave(p);
+ if( p->sharable ){
+ u8 lockType = READ_LOCK + isWriteLock;
+ assert( READ_LOCK+1==WRITE_LOCK );
+ assert( isWriteLock==0 || isWriteLock==1 );
+ sqlite3BtreeEnter(p);
+ rc = queryTableLock(p, iTab, lockType);
+ if( rc==SQLITE_OK ){
+ rc = lockTable(p, iTab, lockType);
+ }
+ sqlite3BtreeLeave(p);
+ }
return rc;
}
#endif
@@ -34458,15 +37116,27 @@
** UPDATE and DELETE statements.
*/
/*
+** Constants FIFOSIZE_FIRST and FIFOSIZE_MAX are the initial
+** number of entries in a fifo page and the maximum number of
+** entries in a fifo page.
+*/
+#define FIFOSIZE_FIRST (((128-sizeof(FifoPage))/8)+1)
+#ifdef SQLITE_MALLOC_SOFT_LIMIT
+# define FIFOSIZE_MAX (((SQLITE_MALLOC_SOFT_LIMIT-sizeof(FifoPage))/8)+1)
+#else
+# define FIFOSIZE_MAX (((262144-sizeof(FifoPage))/8)+1)
+#endif
+
+/*
** Allocate a new FifoPage and return a pointer to it. Return NULL if
** we run out of memory. Leave space on the page for nEntry entries.
*/
static FifoPage *allocateFifoPage(int nEntry){
FifoPage *pPage;
- if( nEntry>32767 ){
- nEntry = 32767;
+ if( nEntry>FIFOSIZE_MAX ){
+ nEntry = FIFOSIZE_MAX;
}
pPage = sqlite3_malloc( sizeof(FifoPage) + sizeof(i64)*(nEntry-1) );
if( pPage ){
pPage->nSlot = nEntry;
@@ -34492,9 +37162,9 @@
SQLITE_PRIVATE int sqlite3VdbeFifoPush(Fifo *pFifo, i64 val){
FifoPage *pPage;
pPage = pFifo->pLast;
if( pPage==0 ){
- pPage = pFifo->pLast = pFifo->pFirst = allocateFifoPage(20);
+ pPage = pFifo->pLast = pFifo->pFirst = allocateFifoPage(FIFOSIZE_FIRST);
if( pPage==0 ){
return SQLITE_NOMEM;
}
}else if( pPage->iWrite>=pPage->nSlot ){
@@ -34616,34 +37286,74 @@
#endif
}
/*
+** Make sure pMem->z points to a writable allocation of at least
+** n bytes.
+**
+** If the memory cell currently contains string or blob data
+** and the third argument passed to this function is true, the
+** current content of the cell is preserved. Otherwise, it may
+** be discarded.
+**
+** This function sets the MEM_Dyn flag and clears any xDel callback.
+** It also clears MEM_Ephem and MEM_Static. If the preserve flag is
+** not set, Mem.n is zeroed.
+*/
+SQLITE_PRIVATE int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve){
+ assert( 1 >=
+ ((pMem->zMalloc && pMem->zMalloc==pMem->z) ? 1 : 0) +
+ (((pMem->flags&MEM_Dyn)&&pMem->xDel) ? 1 : 0) +
+ ((pMem->flags&MEM_Ephem) ? 1 : 0) +
+ ((pMem->flags&MEM_Static) ? 1 : 0)
+ );
+
+ if( !pMem->zMalloc || sqlite3MallocSize(pMem->zMalloc)<n ){
+ n = (n>32?n:32);
+ if( preserve && pMem->z==pMem->zMalloc ){
+ pMem->z = pMem->zMalloc = sqlite3DbReallocOrFree(pMem->db, pMem->z, n);
+ if( !pMem->z ){
+ pMem->flags = MEM_Null;
+ }
+ preserve = 0;
+ }else{
+ sqlite3_free(pMem->zMalloc);
+ pMem->zMalloc = sqlite3DbMallocRaw(pMem->db, n);
+ }
+ }
+
+ if( preserve && pMem->z && pMem->zMalloc && pMem->z!=pMem->zMalloc ){
+ memcpy(pMem->zMalloc, pMem->z, pMem->n);
+ }
+ if( pMem->flags&MEM_Dyn && pMem->xDel ){
+ pMem->xDel((void *)(pMem->z));
+ }
+
+ pMem->z = pMem->zMalloc;
+ pMem->flags &= ~(MEM_Ephem|MEM_Static);
+ pMem->xDel = 0;
+ return (pMem->z ? SQLITE_OK : SQLITE_NOMEM);
+}
+
+/*
** Make the given Mem object MEM_Dyn.
**
** Return SQLITE_OK on success or SQLITE_NOMEM if malloc fails.
*/
SQLITE_PRIVATE int sqlite3VdbeMemDynamicify(Mem *pMem){
- int n;
- u8 *z;
+ int f;
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
expandBlob(pMem);
- if( (pMem->flags & (MEM_Ephem|MEM_Static|MEM_Short))==0 ){
- return SQLITE_OK;
- }
- assert( (pMem->flags & MEM_Dyn)==0 );
- n = pMem->n;
- assert( pMem->flags & (MEM_Str|MEM_Blob) );
- z = sqlite3DbMallocRaw(pMem->db, n+2 );
- if( z==0 ){
- return SQLITE_NOMEM;
- }
- pMem->flags |= MEM_Dyn|MEM_Term;
- pMem->xDel = 0;
- memcpy(z, pMem->z, n );
- z[n] = 0;
- z[n+1] = 0;
- pMem->z = (char*)z;
- pMem->flags &= ~(MEM_Ephem|MEM_Static|MEM_Short);
+ f = pMem->flags;
+ if( (f&(MEM_Str|MEM_Blob)) && pMem->z!=pMem->zMalloc ){
+ if( sqlite3VdbeMemGrow(pMem, pMem->n + 2, 1) ){
+ return SQLITE_NOMEM;
+ }
+ pMem->z[pMem->n] = 0;
+ pMem->z[pMem->n+1] = 0;
+ pMem->flags |= MEM_Term;
+ }
+
return SQLITE_OK;
}
/*
@@ -34652,26 +37362,24 @@
*/
#ifndef SQLITE_OMIT_INCRBLOB
SQLITE_PRIVATE int sqlite3VdbeMemExpandBlob(Mem *pMem){
if( pMem->flags & MEM_Zero ){
- char *pNew;
int nByte;
- assert( (pMem->flags & MEM_Blob)!=0 );
+ assert( pMem->flags&MEM_Blob );
+ assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
+
+ /* Set nByte to the number of bytes required to store the expanded blob. */
nByte = pMem->n + pMem->u.i;
- if( nByte<=0 ) nByte = 1;
- assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
- pNew = sqlite3DbMallocRaw(pMem->db, nByte);
- if( pNew==0 ){
+ if( nByte<=0 ){
+ nByte = 1;
+ }
+ if( sqlite3VdbeMemGrow(pMem, nByte, 1) ){
return SQLITE_NOMEM;
}
- memcpy(pNew, pMem->z, pMem->n);
- memset(&pNew[pMem->n], 0, pMem->u.i);
- sqlite3VdbeMemRelease(pMem);
- pMem->z = pNew;
+
+ memset(&pMem->z[pMem->n], 0, pMem->u.i);
pMem->n += pMem->u.i;
- pMem->u.i = 0;
- pMem->flags &= ~(MEM_Zero|MEM_Static|MEM_Ephem|MEM_Short|MEM_Term);
- pMem->flags |= MEM_Dyn;
+ pMem->flags &= ~(MEM_Zero|MEM_Term);
}
return SQLITE_OK;
}
#endif
@@ -34683,35 +37391,9 @@
**
** Return SQLITE_OK on success or SQLITE_NOMEM if malloc fails.
*/
SQLITE_PRIVATE int sqlite3VdbeMemMakeWriteable(Mem *pMem){
- int n;
- u8 *z;
- assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
- expandBlob(pMem);
- if( (pMem->flags & (MEM_Ephem|MEM_Static))==0 ){
- return SQLITE_OK;
- }
- assert( (pMem->flags & MEM_Dyn)==0 );
- assert( pMem->flags & (MEM_Str|MEM_Blob) );
- if( (n = pMem->n)+2<sizeof(pMem->zShort) ){
- z = (u8*)pMem->zShort;
- pMem->flags |= MEM_Short|MEM_Term;
- }else{
- z = sqlite3DbMallocRaw(pMem->db, n+2 );
- if( z==0 ){
- return SQLITE_NOMEM;
- }
- pMem->flags |= MEM_Dyn|MEM_Term;
- pMem->xDel = 0;
- }
- memcpy(z, pMem->z, n );
- z[n] = 0;
- z[n+1] = 0;
- pMem->z = (char*)z;
- pMem->flags &= ~(MEM_Ephem|MEM_Static);
- assert(0==(1&(int)pMem->z));
- return SQLITE_OK;
+ return sqlite3VdbeMemDynamicify(pMem);
}
/*
** Make sure the given Mem is \u0000 terminated.
@@ -34720,29 +37402,14 @@
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
if( (pMem->flags & MEM_Term)!=0 || (pMem->flags & MEM_Str)==0 ){
return SQLITE_OK; /* Nothing to do */
}
- if( pMem->flags & (MEM_Static|MEM_Ephem) ){
- return sqlite3VdbeMemMakeWriteable(pMem);
- }else{
- char *z;
- sqlite3VdbeMemExpandBlob(pMem);
- z = sqlite3DbMallocRaw(pMem->db, pMem->n+2);
- if( !z ){
- return SQLITE_NOMEM;
- }
- memcpy(z, pMem->z, pMem->n);
- z[pMem->n] = 0;
- z[pMem->n+1] = 0;
- if( pMem->xDel ){
- pMem->xDel(pMem->z);
- }else{
- sqlite3_free(pMem->z);
- }
- pMem->xDel = 0;
- pMem->z = z;
- pMem->flags |= MEM_Term;
- }
+ if( sqlite3VdbeMemGrow(pMem, pMem->n+2, 1) ){
+ return SQLITE_NOMEM;
+ }
+ pMem->z[pMem->n] = 0;
+ pMem->z[pMem->n+1] = 0;
+ pMem->flags |= MEM_Term;
return SQLITE_OK;
}
/*
@@ -34760,31 +37427,34 @@
*/
SQLITE_PRIVATE int sqlite3VdbeMemStringify(Mem *pMem, int enc){
int rc = SQLITE_OK;
int fg = pMem->flags;
- char *z = pMem->zShort;
+ const int nByte = 32;
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
assert( !(fg&MEM_Zero) );
assert( !(fg&(MEM_Str|MEM_Blob)) );
assert( fg&(MEM_Int|MEM_Real) );
- /* For a Real or Integer, use sqlite3_snprintf() to produce the UTF-8
+ if( sqlite3VdbeMemGrow(pMem, nByte, 0) ){
+ return SQLITE_NOMEM;
+ }
+
+ /* For a Real or Integer, use sqlite3_mprintf() to produce the UTF-8
** string representation of the value. Then, if the required encoding
** is UTF-16le or UTF-16be do a translation.
**
** FIX ME: It would be better if sqlite3_snprintf() could do UTF-16.
*/
if( fg & MEM_Int ){
- sqlite3_snprintf(NBFS, z, "%lld", pMem->u.i);
+ sqlite3_snprintf(nByte, pMem->z, "%lld", pMem->u.i);
}else{
assert( fg & MEM_Real );
- sqlite3_snprintf(NBFS, z, "%!.15g", pMem->r);
- }
- pMem->n = strlen(z);
- pMem->z = z;
+ sqlite3_snprintf(nByte, pMem->z, "%!.15g", pMem->r);
+ }
+ pMem->n = strlen(pMem->z);
pMem->enc = SQLITE_UTF8;
- pMem->flags |= MEM_Str | MEM_Short | MEM_Term;
+ pMem->flags |= MEM_Str|MEM_Term;
sqlite3VdbeChangeEncoding(pMem, enc);
return rc;
}
@@ -34802,24 +37472,37 @@
sqlite3_context ctx;
assert( (pMem->flags & MEM_Null)!=0 || pFunc==pMem->u.pDef );
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
ctx.s.flags = MEM_Null;
- ctx.s.z = pMem->zShort;
ctx.s.db = pMem->db;
+ ctx.s.zMalloc = 0;
ctx.pMem = pMem;
ctx.pFunc = pFunc;
ctx.isError = 0;
pFunc->xFinalize(&ctx);
- if( pMem->z && pMem->z!=pMem->zShort ){
- sqlite3_free( pMem->z );
- }
- *pMem = ctx.s;
- if( pMem->flags & MEM_Short ){
- pMem->z = pMem->zShort;
- }
+ assert( 0==(pMem->flags&MEM_Dyn) && !pMem->xDel );
+ sqlite3_free(pMem->zMalloc);
+ *pMem = ctx.s;
rc = (ctx.isError?SQLITE_ERROR:SQLITE_OK);
}
return rc;
+}
+
+/*
+** If the memory cell contains a string value that must be freed by
+** invoking an external callback, free it now. Calling this function
+** does not free any Mem.zMalloc buffer.
+*/
+SQLITE_PRIVATE void sqlite3VdbeMemReleaseExternal(Mem *p){
+ assert( p->db==0 || sqlite3_mutex_held(p->db->mutex) );
+ if( p->flags&MEM_Agg ){
+ sqlite3VdbeMemFinalize(p, p->u.pDef);
+ assert( (p->flags & MEM_Agg)==0 );
+ sqlite3VdbeMemRelease(p);
+ }else if( p->flags&MEM_Dyn && p->xDel ){
+ p->xDel((void *)p->z);
+ p->xDel = 0;
+ }
}
/*
** Release any memory held by the Mem. This may leave the Mem in an
@@ -34826,24 +37509,13 @@
** inconsistent state, for example with (Mem.z==0) and
** (Mem.type==SQLITE_TEXT).
*/
SQLITE_PRIVATE void sqlite3VdbeMemRelease(Mem *p){
- assert( p->db==0 || sqlite3_mutex_held(p->db->mutex) );
- if( p->flags & (MEM_Dyn|MEM_Agg) ){
- if( p->xDel ){
- if( p->flags & MEM_Agg ){
- sqlite3VdbeMemFinalize(p, p->u.pDef);
- assert( (p->flags & MEM_Agg)==0 );
- sqlite3VdbeMemRelease(p);
- }else{
- p->xDel((void *)p->z);
- }
- }else{
- sqlite3_free(p->z);
- }
- p->z = 0;
- p->xDel = 0;
- }
+ sqlite3VdbeMemReleaseExternal(p);
+ sqlite3_free(p->zMalloc);
+ p->z = 0;
+ p->zMalloc = 0;
+ p->xDel = 0;
}
/*
** Convert a 64-bit IEEE double into a 64-bit signed integer.
@@ -34864,10 +37536,10 @@
** inconsistently. And many do not understand the "LL" notation.
** So we define our own static constants here using nothing
** larger than a 32-bit integer constant.
*/
- static const i64 maxInt = (((i64)0x7fffffff)<<32)|0xffffffff;
- static const i64 minInt = ((i64)0x80000000)<<32;
+ static const i64 maxInt = LARGEST_INT64;
+ static const i64 minInt = SMALLEST_INT64;
if( r<(double)minInt ){
return minInt;
}else if( r>(double)maxInt ){
@@ -34950,16 +37622,19 @@
pMem->flags |= MEM_Int;
}
}
+static void setTypeFlag(Mem *pMem, int f){
+ MemSetTypeFlag(pMem, f);
+}
+
/*
** Convert pMem to type integer. Invalidate any prior representations.
*/
SQLITE_PRIVATE int sqlite3VdbeMemIntegerify(Mem *pMem){
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
pMem->u.i = sqlite3VdbeIntValue(pMem);
- sqlite3VdbeMemRelease(pMem);
- pMem->flags = MEM_Int;
+ setTypeFlag(pMem, MEM_Int);
return SQLITE_OK;
}
/*
@@ -34968,10 +37643,9 @@
*/
SQLITE_PRIVATE int sqlite3VdbeMemRealify(Mem *pMem){
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
pMem->r = sqlite3VdbeRealValue(pMem);
- sqlite3VdbeMemRelease(pMem);
- pMem->flags = MEM_Real;
+ setTypeFlag(pMem, MEM_Real);
return SQLITE_OK;
}
/*
@@ -34990,10 +37664,9 @@
if( r1==r2 ){
sqlite3VdbeMemIntegerify(pMem);
}else{
pMem->r = r1;
- pMem->flags = MEM_Real;
- sqlite3VdbeMemRelease(pMem);
+ setTypeFlag(pMem, MEM_Real);
}
return SQLITE_OK;
}
@@ -35000,12 +37673,10 @@
/*
** Delete any previous value and set the value stored in *pMem to NULL.
*/
SQLITE_PRIVATE void sqlite3VdbeMemSetNull(Mem *pMem){
- sqlite3VdbeMemRelease(pMem);
- pMem->flags = MEM_Null;
- pMem->type = SQLITE_NULL;
- pMem->n = 0;
+ setTypeFlag(pMem, MEM_Null);
+ pMem->type = SQLITE_NULL;
}
/*
** Delete any previous value and set the value to be a BLOB of length
@@ -35012,14 +37683,14 @@
** n containing all zeros.
*/
SQLITE_PRIVATE void sqlite3VdbeMemSetZeroBlob(Mem *pMem, int n){
sqlite3VdbeMemRelease(pMem);
- pMem->flags = MEM_Blob|MEM_Zero|MEM_Short;
+ setTypeFlag(pMem, MEM_Blob);
+ pMem->flags = MEM_Blob|MEM_Zero;
pMem->type = SQLITE_BLOB;
pMem->n = 0;
if( n<0 ) n = 0;
pMem->u.i = n;
- pMem->z = pMem->zShort;
pMem->enc = SQLITE_UTF8;
}
/*
@@ -35037,9 +37708,9 @@
** Delete any previous value and set the value stored in *pMem to val,
** manifest type REAL.
*/
SQLITE_PRIVATE void sqlite3VdbeMemSetDouble(Mem *pMem, double val){
- if( sqlite3_isnan(val) ){
+ if( sqlite3IsNaN(val) ){
sqlite3VdbeMemSetNull(pMem);
}else{
sqlite3VdbeMemRelease(pMem);
pMem->r = val;
@@ -35052,17 +37723,23 @@
** Return true if the Mem object contains a TEXT or BLOB that is
** too large - whose size exceeds SQLITE_MAX_LENGTH.
*/
SQLITE_PRIVATE int sqlite3VdbeMemTooBig(Mem *p){
+ assert( p->db!=0 );
if( p->flags & (MEM_Str|MEM_Blob) ){
int n = p->n;
if( p->flags & MEM_Zero ){
n += p->u.i;
}
- return n>SQLITE_MAX_LENGTH;
- }
- return 0;
-}
+ return n>p->db->aLimit[SQLITE_LIMIT_LENGTH];
+ }
+ return 0;
+}
+
+/*
+** Size of struct Mem not including the Mem.zMalloc member.
+*/
+#define MEMCELLSIZE (size_t)(&(((Mem *)0)->zMalloc))
/*
** Make an shallow copy of pFrom into pTo. Prior contents of
** pTo are freed. The pFrom->z field is not duplicated. If
@@ -35069,13 +37746,13 @@
** pFrom->z is used, then pTo->z points to the same thing as pFrom->z
** and flags gets srcType (either MEM_Ephem or MEM_Static).
*/
SQLITE_PRIVATE void sqlite3VdbeMemShallowCopy(Mem *pTo, const Mem *pFrom, int srcType){
- sqlite3VdbeMemRelease(pTo);
- memcpy(pTo, pFrom, sizeof(*pFrom)-sizeof(pFrom->zShort));
+ sqlite3VdbeMemReleaseExternal(pTo);
+ memcpy(pTo, pFrom, MEMCELLSIZE);
pTo->xDel = 0;
- if( pTo->flags & (MEM_Str|MEM_Blob) ){
- pTo->flags &= ~(MEM_Dyn|MEM_Static|MEM_Short|MEM_Ephem);
+ if( (pFrom->flags&MEM_Dyn)!=0 || pFrom->z==pFrom->zMalloc ){
+ pTo->flags &= ~(MEM_Dyn|MEM_Static|MEM_Ephem);
assert( srcType==MEM_Ephem || srcType==MEM_Static );
pTo->flags |= srcType;
}
}
@@ -35084,15 +37761,21 @@
** Make a full copy of pFrom into pTo. Prior contents of pTo are
** freed before the copy is made.
*/
SQLITE_PRIVATE int sqlite3VdbeMemCopy(Mem *pTo, const Mem *pFrom){
- int rc;
- sqlite3VdbeMemShallowCopy(pTo, pFrom, MEM_Ephem);
- if( pTo->flags & MEM_Ephem ){
- rc = sqlite3VdbeMemMakeWriteable(pTo);
- }else{
- rc = SQLITE_OK;
- }
+ int rc = SQLITE_OK;
+
+ sqlite3VdbeMemReleaseExternal(pTo);
+ memcpy(pTo, pFrom, MEMCELLSIZE);
+ pTo->flags &= ~MEM_Dyn;
+
+ if( pTo->flags&(MEM_Str|MEM_Blob) ){
+ if( 0==(pFrom->flags&MEM_Static) ){
+ pTo->flags |= MEM_Ephem;
+ rc = sqlite3VdbeMemMakeWriteable(pTo);
+ }
+ }
+
return rc;
}
/*
@@ -35104,21 +37787,24 @@
SQLITE_PRIVATE void sqlite3VdbeMemMove(Mem *pTo, Mem *pFrom){
assert( pFrom->db==0 || sqlite3_mutex_held(pFrom->db->mutex) );
assert( pTo->db==0 || sqlite3_mutex_held(pTo->db->mutex) );
assert( pFrom->db==0 || pTo->db==0 || pFrom->db==pTo->db );
- if( pTo->flags & MEM_Dyn ){
- sqlite3VdbeMemRelease(pTo);
- }
- memcpy(pTo, pFrom, sizeof(Mem));
- if( pFrom->flags & MEM_Short ){
- pTo->z = pTo->zShort;
- }
+
+ sqlite3VdbeMemRelease(pTo);
+ memcpy(pTo, pFrom, sizeof(Mem));
pFrom->flags = MEM_Null;
pFrom->xDel = 0;
+ pFrom->zMalloc = 0;
}
/*
** Change the value of a Mem to be a string or a BLOB.
+**
+** The memory management strategy depends on the value of the xDel
+** parameter. If the value passed is SQLITE_TRANSIENT, then the
+** string is copied into a (possibly existing) buffer managed by the
+** Mem structure. Otherwise, any existing buffer is freed and the
+** pointer copied.
*/
SQLITE_PRIVATE int sqlite3VdbeMemSetStr(
Mem *pMem, /* Memory cell to set to string value */
const char *z, /* String pointer */
@@ -35125,61 +37811,61 @@
int n, /* Bytes in string, or negative */
u8 enc, /* Encoding of z. 0 for BLOBs */
void (*xDel)(void*) /* Destructor function */
){
+ int nByte = n; /* New value for pMem->n */
+ int flags = 0; /* New value for pMem->flags */
+
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
- sqlite3VdbeMemRelease(pMem);
+
+ /* If z is a NULL pointer, set pMem to contain an SQL NULL. */
if( !z ){
- pMem->flags = MEM_Null;
- pMem->type = SQLITE_NULL;
- return SQLITE_OK;
- }
- pMem->z = (char *)z;
- if( xDel==SQLITE_STATIC ){
- pMem->flags = MEM_Static;
- }else if( xDel==SQLITE_TRANSIENT ){
- pMem->flags = MEM_Ephem;
- }else{
- pMem->flags = MEM_Dyn;
+ sqlite3VdbeMemSetNull(pMem);
+ return SQLITE_OK;
+ }
+
+ flags = (enc==0?MEM_Blob:MEM_Str);
+ if( nByte<0 ){
+ assert( enc!=0 );
+ if( enc==SQLITE_UTF8 ){
+ for(nByte=0; z[nByte]; nByte++){}
+ }else{
+ for(nByte=0; z[nByte] | z[nByte+1]; nByte+=2){}
+ }
+ flags |= MEM_Term;
+ }
+
+ /* The following block sets the new values of Mem.z and Mem.xDel. It
+ ** also sets a flag in local variable "flags" to indicate the memory
+ ** management (one of MEM_Dyn or MEM_Static).
+ */
+ if( xDel==SQLITE_TRANSIENT ){
+ int nAlloc = nByte;
+ if( flags&MEM_Term ){
+ nAlloc += (enc==SQLITE_UTF8?1:2);
+ }
+ if( sqlite3VdbeMemGrow(pMem, nAlloc, 0) ){
+ return SQLITE_NOMEM;
+ }
+ memcpy(pMem->z, z, nAlloc);
+ }else{
+ sqlite3VdbeMemRelease(pMem);
+ pMem->z = (char *)z;
pMem->xDel = xDel;
- }
-
- pMem->enc = enc;
- pMem->type = enc==0 ? SQLITE_BLOB : SQLITE_TEXT;
- pMem->n = n;
-
- assert( enc==0 || enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE
- || enc==SQLITE_UTF16BE );
- switch( enc ){
- case 0:
- pMem->flags |= MEM_Blob;
- pMem->enc = SQLITE_UTF8;
- break;
-
- case SQLITE_UTF8:
- pMem->flags |= MEM_Str;
- if( n<0 ){
- pMem->n = strlen(z);
- pMem->flags |= MEM_Term;
- }
- break;
-
-#ifndef SQLITE_OMIT_UTF16
- case SQLITE_UTF16LE:
- case SQLITE_UTF16BE:
- pMem->flags |= MEM_Str;
- if( pMem->n<0 ){
- pMem->n = sqlite3Utf16ByteLen(pMem->z,-1);
- pMem->flags |= MEM_Term;
- }
- if( sqlite3VdbeMemHandleBom(pMem) ){
- return SQLITE_NOMEM;
- }
-#endif /* SQLITE_OMIT_UTF16 */
- }
- if( pMem->flags&MEM_Ephem ){
- return sqlite3VdbeMemMakeWriteable(pMem);
- }
+ flags |= ((xDel==SQLITE_STATIC)?MEM_Static:MEM_Dyn);
+ }
+
+ pMem->n = nByte;
+ pMem->flags = flags;
+ pMem->enc = (enc==0 ? SQLITE_UTF8 : enc);
+ pMem->type = (enc==0 ? SQLITE_BLOB : SQLITE_TEXT);
+
+#ifndef SQLITE_OMIT_UTF16
+ if( pMem->enc!=SQLITE_UTF8 && sqlite3VdbeMemHandleBom(pMem) ){
+ return SQLITE_NOMEM;
+ }
+#endif
+
return SQLITE_OK;
}
/*
@@ -35325,8 +38011,9 @@
){
char *zData; /* Data from the btree layer */
int available = 0; /* Number of bytes available on the local btree page */
sqlite3 *db; /* Database connection */
+ int rc = SQLITE_OK;
db = sqlite3BtreeCursorDb(pCur);
assert( sqlite3_mutex_held(db->mutex) );
if( key ){
@@ -35335,51 +38022,30 @@
zData = (char *)sqlite3BtreeDataFetch(pCur, &available);
}
assert( zData!=0 );
- pMem->db = db;
- pMem->n = amt;
- if( offset+amt<=available ){
+ if( offset+amt<=available && ((pMem->flags&MEM_Dyn)==0 || pMem->xDel) ){
+ sqlite3VdbeMemRelease(pMem);
pMem->z = &zData[offset];
pMem->flags = MEM_Blob|MEM_Ephem;
- }else{
- int rc;
- if( amt>NBFS-2 ){
- zData = (char *)sqlite3DbMallocRaw(db, amt+2);
- if( !zData ){
- return SQLITE_NOMEM;
- }
- pMem->flags = MEM_Blob|MEM_Dyn|MEM_Term;
- pMem->xDel = 0;
- }else{
- zData = &(pMem->zShort[0]);
- pMem->flags = MEM_Blob|MEM_Short|MEM_Term;
- }
- pMem->z = zData;
+ }else if( SQLITE_OK==(rc = sqlite3VdbeMemGrow(pMem, amt+2, 0)) ){
+ pMem->flags = MEM_Blob|MEM_Dyn|MEM_Term;
pMem->enc = 0;
pMem->type = SQLITE_BLOB;
-
if( key ){
- rc = sqlite3BtreeKey(pCur, offset, amt, zData);
- }else{
- rc = sqlite3BtreeData(pCur, offset, amt, zData);
- }
- zData[amt] = 0;
- zData[amt+1] = 0;
- if( rc!=SQLITE_OK ){
- if( amt>NBFS-2 ){
- assert( zData!=pMem->zShort );
- assert( pMem->flags & MEM_Dyn );
- sqlite3_free(zData);
- } else {
- assert( zData==pMem->zShort );
- assert( pMem->flags & MEM_Short );
- }
- return rc;
- }
- }
-
- return SQLITE_OK;
+ rc = sqlite3BtreeKey(pCur, offset, amt, pMem->z);
+ }else{
+ rc = sqlite3BtreeData(pCur, offset, amt, pMem->z);
+ }
+ pMem->z[amt] = 0;
+ pMem->z[amt+1] = 0;
+ if( rc!=SQLITE_OK ){
+ sqlite3VdbeMemRelease(pMem);
+ }
+ }
+ pMem->n = amt;
+
+ return rc;
}
#if 0
/*
@@ -35575,9 +38241,9 @@
** Free an sqlite3_value object
*/
SQLITE_PRIVATE void sqlite3ValueFree(sqlite3_value *v){
if( !v ) return;
- sqlite3ValueSetStr(v, 0, 0, SQLITE_UTF8, SQLITE_STATIC);
+ sqlite3VdbeMemRelease((Mem *)v);
sqlite3_free(v);
}
/*
@@ -35612,19 +38278,21 @@
** This file contains code used for creating, destroying, and populating
** a VDBE (or an "sqlite3_stmt" as it is known to the outside world.) Prior
** to version 2.8.7, all this code was combined into the vdbe.c source file.
** But that file was getting too big so this subroutines were split out.
+**
+** $Id: vdbeaux.c,v 1.383 2008/05/13 13:27:34 drh Exp $
*/
/*
** When debugging the code generator in a symbolic debugger, one can
-** set the sqlite3_vdbe_addop_trace to 1 and all opcodes will be printed
+** set the sqlite3VdbeAddopTrace to 1 and all opcodes will be printed
** as they are added to the instruction stream.
*/
#ifdef SQLITE_DEBUG
-SQLITE_API int sqlite3_vdbe_addop_trace = 0;
+SQLITE_PRIVATE int sqlite3VdbeAddopTrace = 0;
#endif
/*
@@ -35704,16 +38372,12 @@
** along with the rest of the Vdbe).
*/
static void resizeOpArray(Vdbe *p, int N){
VdbeOp *pNew;
- int oldSize = p->nOpAlloc;
pNew = sqlite3DbRealloc(p->db, p->aOp, N*sizeof(Op));
if( pNew ){
p->nOpAlloc = N;
p->aOp = pNew;
- if( N>oldSize ){
- memset(&p->aOp[oldSize], 0, (N-oldSize)*sizeof(Op));
- }
}
}
/*
@@ -35738,24 +38402,30 @@
i = p->nOp;
assert( p->magic==VDBE_MAGIC_INIT );
if( p->nOpAlloc<=i ){
- resizeOpArray(p, p->nOpAlloc*2 + 100);
+ resizeOpArray(p, p->nOpAlloc ? p->nOpAlloc*2 : 1024/sizeof(Op));
if( p->db->mallocFailed ){
return 0;
}
}
p->nOp++;
pOp = &p->aOp[i];
pOp->opcode = op;
+ pOp->p5 = 0;
pOp->p1 = p1;
pOp->p2 = p2;
pOp->p3 = p3;
pOp->p4.p = 0;
pOp->p4type = P4_NOTUSED;
p->expired = 0;
#ifdef SQLITE_DEBUG
- if( sqlite3_vdbe_addop_trace ) sqlite3VdbePrintOp(0, i, &p->aOp[i]);
+ pOp->zComment = 0;
+ if( sqlite3VdbeAddopTrace ) sqlite3VdbePrintOp(0, i, &p->aOp[i]);
+#endif
+#ifdef VDBE_PROFILE
+ pOp->cycles = 0;
+ pOp->cnt = 0;
#endif
return i;
}
SQLITE_PRIVATE int sqlite3VdbeAddOp0(Vdbe *p, int op){
@@ -35931,9 +38601,10 @@
SQLITE_PRIVATE int sqlite3VdbeAddOpList(Vdbe *p, int nOp, VdbeOpList const *aOp){
int addr;
assert( p->magic==VDBE_MAGIC_INIT );
if( p->nOp + nOp > p->nOpAlloc ){
- resizeOpArray(p, p->nOp*2 + nOp);
+ resizeOpArray(p, p->nOpAlloc ? p->nOpAlloc*2 : 1024/sizeof(Op));
+ assert( p->nOp+nOp<=p->nOpAlloc || p->db->mallocFailed );
}
if( p->db->mallocFailed ){
return 0;
}
@@ -35955,9 +38626,10 @@
pOut->p4type = P4_NOTUSED;
pOut->p4.p = 0;
pOut->p5 = 0;
#ifdef SQLITE_DEBUG
- if( sqlite3_vdbe_addop_trace ){
+ pOut->zComment = 0;
+ if( sqlite3VdbeAddopTrace ){
sqlite3VdbePrintOp(0, i+addr, &p->aOp[i+addr]);
}
#endif
}
@@ -36124,8 +38796,10 @@
pOp = &p->aOp[addr];
freeP4(pOp->p4type, pOp->p4.p);
pOp->p4.p = 0;
if( n==P4_INT32 ){
+ /* Note: this cast is safe, because the origin data point was an int
+ ** that was cast to a (const char *). */
pOp->p4.i = (int)zP4;
pOp->p4type = n;
}else if( zP4==0 ){
pOp->p4.p = 0;
@@ -36330,16 +39004,42 @@
/*
** Release an array of N Mem elements
*/
-static void releaseMemArray(Mem *p, int N){
- if( p ){
+static void releaseMemArray(Mem *p, int N, int freebuffers){
+ if( p && N ){
+ sqlite3 *db = p->db;
+ int malloc_failed = db->mallocFailed;
while( N-->0 ){
assert( N<2 || p[0].db==p[1].db );
- sqlite3VdbeMemSetNull(p++);
- }
- }
-}
+ if( freebuffers ){
+ sqlite3VdbeMemRelease(p);
+ }else{
+ sqlite3VdbeMemReleaseExternal(p);
+ }
+ p->flags = MEM_Null;
+ p++;
+ }
+ db->mallocFailed = malloc_failed;
+ }
+}
+
+#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
+SQLITE_PRIVATE int sqlite3VdbeReleaseBuffers(Vdbe *p){
+ int ii;
+ int nFree = 0;
+ assert( sqlite3_mutex_held(p->db->mutex) );
+ for(ii=1; ii<=p->nMem; ii++){
+ Mem *pMem = &p->aMem[ii];
+ if( pMem->z && pMem->flags&MEM_Dyn ){
+ assert( !pMem->xDel );
+ nFree += sqlite3MallocSize(pMem->z);
+ sqlite3VdbeMemRelease(pMem);
+ }
+ }
+ return nFree;
+}
+#endif
#ifndef SQLITE_OMIT_EXPLAIN
/*
** Give a listing of the program in the virtual machine.
@@ -36369,9 +39069,9 @@
/* Even though this opcode does not use dynamic strings for
** the result, result columns may become dynamic if the user calls
** sqlite3_column_text16(), causing a translation to UTF-16 encoding.
*/
- releaseMemArray(pMem, p->nMem);
+ releaseMemArray(pMem, p->nMem, 1);
do{
i = p->pc++;
}while( i<p->nOp && p->explain==2 && p->aOp[i].opcode!=OP_Explain );
@@ -36382,8 +39082,9 @@
p->rc = SQLITE_INTERRUPT;
rc = SQLITE_ERROR;
sqlite3SetString(&p->zErrMsg, sqlite3ErrStr(p->rc), (char*)0);
}else{
+ char *z;
Op *pOp = &p->aOp[i];
if( p->explain==1 ){
pMem->flags = MEM_Int;
pMem->type = SQLITE_INTEGER;
@@ -36415,33 +39116,48 @@
pMem->type = SQLITE_INTEGER;
pMem++;
}
- pMem->flags = MEM_Ephem|MEM_Str|MEM_Term; /* P4 */
- pMem->z = displayP4(pOp, pMem->zShort, sizeof(pMem->zShort));
- assert( pMem->z!=0 );
- pMem->n = strlen(pMem->z);
- pMem->type = SQLITE_TEXT;
- pMem->enc = SQLITE_UTF8;
+ if( sqlite3VdbeMemGrow(pMem, 32, 0) ){ /* P4 */
+ p->db->mallocFailed = 1;
+ return SQLITE_NOMEM;
+ }
+ pMem->flags = MEM_Dyn|MEM_Str|MEM_Term;
+ z = displayP4(pOp, pMem->z, 32);
+ if( z!=pMem->z ){
+ sqlite3VdbeMemSetStr(pMem, z, -1, SQLITE_UTF8, 0);
+ }else{
+ assert( pMem->z!=0 );
+ pMem->n = strlen(pMem->z);
+ pMem->enc = SQLITE_UTF8;
+ }
+ pMem->type = SQLITE_TEXT;
pMem++;
if( p->explain==1 ){
- pMem->flags = MEM_Str|MEM_Term|MEM_Short;
- pMem->n = sprintf(pMem->zShort, "%.2x", pOp->p5); /* P5 */
- pMem->z = pMem->zShort;
+ if( sqlite3VdbeMemGrow(pMem, 4, 0) ){
+ p->db->mallocFailed = 1;
+ return SQLITE_NOMEM;
+ }
+ pMem->flags = MEM_Dyn|MEM_Str|MEM_Term;
+ pMem->n = 2;
+ sqlite3_snprintf(3, pMem->z, "%.2x", pOp->p5); /* P5 */
pMem->type = SQLITE_TEXT;
pMem->enc = SQLITE_UTF8;
pMem++;
- pMem->flags = MEM_Null; /* Comment */
#ifdef SQLITE_DEBUG
if( pOp->zComment ){
pMem->flags = MEM_Str|MEM_Term;
pMem->z = pOp->zComment;
pMem->n = strlen(pMem->z);
pMem->enc = SQLITE_UTF8;
- }
-#endif
+ }else
+#endif
+ {
+ pMem->flags = MEM_Null; /* Comment */
+ pMem->type = SQLITE_NULL;
+ }
}
p->nResColumn = 8 - 5*(p->explain-1);
p->rc = SQLITE_OK;
@@ -36474,9 +39190,9 @@
*/
SQLITE_PRIVATE void sqlite3VdbeIOTraceSql(Vdbe *p){
int nOp = p->nOp;
VdbeOp *pOp;
- if( sqlite3_io_trace==0 ) return;
+ if( sqlite3IoTrace==0 ) return;
if( nOp<1 ) return;
pOp = &p->aOp[0];
if( pOp->opcode==OP_Trace && pOp->p4.z!=0 ){
int i, j;
@@ -36492,9 +39208,9 @@
z[j++] = z[i];
}
}
z[j] = 0;
- sqlite3_io_trace("SQL %s\n", z);
+ sqlite3IoTrace("SQL %s\n", z);
}
}
#endif /* !SQLITE_OMIT_TRACE && SQLITE_ENABLE_IOTRACE */
@@ -36531,15 +39247,26 @@
* state.
*/
p->magic = VDBE_MAGIC_RUN;
+ /* For each cursor required, also allocate a memory cell. Memory
+ ** cells (nMem+1-nCursor)..nMem, inclusive, will never be used by
+ ** the vdbe program. Instead they are used to allocate space for
+ ** Cursor/BtCursor structures. The blob of memory associated with
+ ** cursor 0 is stored in memory cell nMem. Memory cell (nMem-1)
+ ** stores the blob of memory associated with cursor 1, etc.
+ **
+ ** See also: allocateCursor().
+ */
+ nMem += nCursor;
+
/*
** Allocation space for registers.
*/
if( p->aMem==0 ){
int nArg; /* Maximum number of args passed to a user function. */
resolveP2Values(p, &nArg);
- resizeOpArray(p, p->nOp);
+ /*resizeOpArray(p, p->nOp);*/
assert( nVar>=0 );
if( isExplain && nMem<10 ){
p->nMem = nMem = 10;
}
@@ -36572,9 +39299,8 @@
}
#ifdef SQLITE_DEBUG
for(n=1; n<p->nMem; n++){
assert( p->aMem[n].db==db );
- assert( p->aMem[n].flags==MEM_Null );
}
#endif
p->pc = -1;
@@ -36599,10 +39325,10 @@
#endif
}
/*
-** Close a VDBE cursor and release all the resources that cursor happens
-** to hold.
+** Close a VDBE cursor and release all the resources that cursor
+** happens to hold.
*/
SQLITE_PRIVATE void sqlite3VdbeFreeCursor(Vdbe *p, Cursor *pCx){
if( pCx==0 ){
return;
@@ -36623,11 +39349,14 @@
(void)sqlite3SafetyOn(p->db);
p->inVtabMethod = 0;
}
#endif
- sqlite3_free(pCx->pData);
- sqlite3_free(pCx->aType);
- sqlite3_free(pCx);
+ if( !pCx->ephemPseudoTable ){
+ sqlite3_free(pCx->pData);
+ }
+ /* memset(pCx, 0, sizeof(Cursor)); */
+ /* sqlite3_free(pCx->aType); */
+ /* sqlite3_free(pCx); */
}
/*
** Close all cursors except for VTab cursors that are currently
@@ -36651,12 +39380,15 @@
** This routine will automatically close any cursors, lists, and/or
** sorters that were left open. It also deletes the values of
** variables in the aVar[] array.
*/
-static void Cleanup(Vdbe *p){
+static void Cleanup(Vdbe *p, int freebuffers){
int i;
closeAllCursorsExceptActiveVtabs(p);
- releaseMemArray(&p->aMem[1], p->nMem);
+ for(i=1; i<=p->nMem; i++){
+ MemSetTypeFlag(&p->aMem[i], MEM_Null);
+ }
+ releaseMemArray(&p->aMem[1], p->nMem, freebuffers);
sqlite3VdbeFifoClear(&p->sFifo);
if( p->contextStack ){
for(i=0; i<p->contextStackTop; i++){
sqlite3VdbeFifoClear(&p->contextStack[i].sFifo);
@@ -36680,9 +39412,9 @@
SQLITE_PRIVATE void sqlite3VdbeSetNumCols(Vdbe *p, int nResColumn){
Mem *pColName;
int n;
- releaseMemArray(p->aColName, p->nResColumn*COLNAME_N);
+ releaseMemArray(p->aColName, p->nResColumn*COLNAME_N, 1);
sqlite3_free(p->aColName);
n = nResColumn*COLNAME_N;
p->nResColumn = nResColumn;
p->aColName = pColName = (Mem*)sqlite3DbMallocZero(p->db, sizeof(Mem)*n );
@@ -36718,10 +39450,10 @@
}else{
rc = sqlite3VdbeMemSetStr(pColName, zName, N, SQLITE_UTF8,SQLITE_TRANSIENT);
}
if( rc==SQLITE_OK && N==P4_DYNAMIC ){
- pColName->flags = (pColName->flags&(~MEM_Static))|MEM_Dyn;
- pColName->xDel = 0;
+ pColName->flags &= (~MEM_Static);
+ pColName->zMalloc = pColName->z;
}
return rc;
}
@@ -36821,20 +39553,24 @@
/* Select a master journal file name */
do {
u32 random;
sqlite3_free(zMaster);
- sqlite3Randomness(sizeof(random), &random);
+ sqlite3_randomness(sizeof(random), &random);
zMaster = sqlite3MPrintf(db, "%s-mj%08X", zMainFile, random&0x7fffffff);
if( !zMaster ){
return SQLITE_NOMEM;
}
- }while( sqlite3OsAccess(pVfs, zMaster, SQLITE_ACCESS_EXISTS) );
-
- /* Open the master journal. */
- rc = sqlite3OsOpenMalloc(pVfs, zMaster, &pMaster,
- SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|
- SQLITE_OPEN_EXCLUSIVE|SQLITE_OPEN_MASTER_JOURNAL, 0
- );
+ rc = sqlite3OsAccess(pVfs, zMaster, SQLITE_ACCESS_EXISTS);
+ }while( rc==1 );
+ if( rc!=0 ){
+ rc = SQLITE_IOERR_NOMEM;
+ }else{
+ /* Open the master journal. */
+ rc = sqlite3OsOpenMalloc(pVfs, zMaster, &pMaster,
+ SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|
+ SQLITE_OPEN_EXCLUSIVE|SQLITE_OPEN_MASTER_JOURNAL, 0
+ );
+ }
if( rc!=SQLITE_OK ){
sqlite3_free(zMaster);
return rc;
}
@@ -36918,14 +39654,16 @@
** transaction is already guaranteed, but some stray 'cold' journals
** may be lying around. Returning an error code won't help matters.
*/
disable_simulated_io_errors();
+ sqlite3FaultBeginBenign(SQLITE_FAULTINJECTOR_MALLOC);
for(i=0; i<db->nDb; i++){
Btree *pBt = db->aDb[i].pBt;
if( pBt ){
sqlite3BtreeCommitPhaseTwo(pBt);
}
}
+ sqlite3FaultEndBenign(SQLITE_FAULTINJECTOR_MALLOC);
enable_simulated_io_errors();
sqlite3VtabCommit(db);
}
@@ -37180,9 +39918,8 @@
checkActiveVdbeCnt(db);
if( p->db->mallocFailed ){
p->rc = SQLITE_NOMEM;
}
- checkActiveVdbeCnt(db);
return SQLITE_OK;
}
@@ -37205,9 +39942,9 @@
** To look at it another way, this routine resets the state of the
** virtual machine from VDBE_MAGIC_RUN or VDBE_MAGIC_HALT back to
** VDBE_MAGIC_INIT.
*/
-SQLITE_PRIVATE int sqlite3VdbeReset(Vdbe *p){
+SQLITE_PRIVATE int sqlite3VdbeReset(Vdbe *p, int freebuffers){
sqlite3 *db;
db = p->db;
/* If the VM did not run to completion or if it encountered an
@@ -37244,9 +39981,9 @@
}
/* Reclaim all memory used by the VDBE
*/
- Cleanup(p);
+ Cleanup(p, freebuffers);
/* Save profiling information from this VDBE run.
*/
#ifdef VDBE_PROFILE
@@ -37282,13 +40019,14 @@
*/
SQLITE_PRIVATE int sqlite3VdbeFinalize(Vdbe *p){
int rc = SQLITE_OK;
if( p->magic==VDBE_MAGIC_RUN || p->magic==VDBE_MAGIC_HALT ){
- rc = sqlite3VdbeReset(p);
+ rc = sqlite3VdbeReset(p, 1);
assert( (rc & p->db->errMask)==rc );
}else if( p->magic!=VDBE_MAGIC_INIT ){
return SQLITE_MISUSE;
}
+ releaseMemArray(&p->aMem[1], p->nMem, 1);
sqlite3VdbeDelete(p);
return rc;
}
@@ -37316,9 +40054,9 @@
*/
SQLITE_PRIVATE void sqlite3VdbeDelete(Vdbe *p){
int i;
if( p==0 ) return;
- Cleanup(p);
+ Cleanup(p, 1);
if( p->pPrev ){
p->pPrev->pNext = p->pNext;
}else{
assert( p->db->pVdbe==p );
@@ -37336,14 +40074,14 @@
#endif
}
sqlite3_free(p->aOp);
}
- releaseMemArray(p->aVar, p->nVar);
+ releaseMemArray(p->aVar, p->nVar, 1);
sqlite3_free(p->aLabel);
if( p->aMem ){
sqlite3_free(&p->aMem[1]);
}
- releaseMemArray(p->aColName, p->nResColumn*COLNAME_N);
+ releaseMemArray(p->aColName, p->nResColumn*COLNAME_N, 1);
sqlite3_free(p->aColName);
sqlite3_free(p->zSql);
p->magic = VDBE_MAGIC_DEAD;
sqlite3_free(p);
@@ -37360,9 +40098,9 @@
#ifdef SQLITE_TEST
extern int sqlite3_search_count;
#endif
assert( p->isTable );
- rc = sqlite3BtreeMoveto(p->pCursor, 0, p->movetoTarget, 0, &res);
+ rc = sqlite3BtreeMoveto(p->pCursor, 0, 0, p->movetoTarget, 0, &res);
if( rc ) return rc;
*p->pIncrKey = 0;
p->lastRowid = keyToInt(p->movetoTarget);
p->rowidIsValid = res==0;
@@ -37432,9 +40170,9 @@
return 0;
}
if( flags&MEM_Int ){
/* Figure out whether to use 1, 2, 4, 6 or 8 bytes. */
-# define MAX_6BYTE ((((i64)0x00001000)<<32)-1)
+# define MAX_6BYTE ((((i64)0x00008000)<<32)-1)
i64 i = pMem->u.i;
u64 u;
if( file_format>=4 && (i&1)==i ){
return 8+i;
@@ -37657,9 +40395,9 @@
}else{
assert( sizeof(x)==8 && sizeof(pMem->r)==8 );
swapMixedEndianFloat(x);
memcpy(&pMem->r, &x, sizeof(x));
- pMem->flags = MEM_Real;
+ pMem->flags = sqlite3IsNaN(pMem->r) ? MEM_Null : MEM_Real;
}
return 8;
}
case 8: /* Integer 0 */
@@ -37683,87 +40421,153 @@
}
return 0;
}
-/*
-** The header of a record consists of a sequence variable-length integers.
-** These integers are almost always small and are encoded as a single byte.
-** The following macro takes advantage this fact to provide a fast decode
-** of the integers in a record header. It is faster for the common case
-** where the integer is a single byte. It is a little slower when the
-** integer is two or more bytes. But overall it is faster.
-**
-** The following expressions are equivalent:
-**
-** x = sqlite3GetVarint32( A, &B );
-**
-** x = GetVarint( A, B );
-**
-*/
-#define GetVarint(A,B) ((B = *(A))<=0x7f ? 1 : sqlite3GetVarint32(A, &B))
-
-/*
-** This function compares the two table rows or index records specified by
-** {nKey1, pKey1} and {nKey2, pKey2}, returning a negative, zero
+
+/*
+** Given the nKey-byte encoding of a record in pKey[], parse the
+** record into a UnpackedRecord structure. Return a pointer to
+** that structure.
+**
+** The calling function might provide szSpace bytes of memory
+** space at pSpace. This space can be used to hold the returned
+** VDbeParsedRecord structure if it is large enough. If it is
+** not big enough, space is obtained from sqlite3_malloc().
+**
+** The returned structure should be closed by a call to
+** sqlite3VdbeDeleteUnpackedRecord().
+*/
+SQLITE_PRIVATE UnpackedRecord *sqlite3VdbeRecordUnpack(
+ KeyInfo *pKeyInfo, /* Information about the record format */
+ int nKey, /* Size of the binary record */
+ const void *pKey, /* The binary record */
+ void *pSpace, /* Space available to hold resulting object */
+ int szSpace /* Size of pSpace[] in bytes */
+){
+ const unsigned char *aKey = (const unsigned char *)pKey;
+ UnpackedRecord *p;
+ int nByte;
+ int i, idx, d;
+ u32 szHdr;
+ Mem *pMem;
+
+ assert( sizeof(Mem)>sizeof(*p) );
+ nByte = sizeof(Mem)*(pKeyInfo->nField+2);
+ if( nByte>szSpace ){
+ p = sqlite3DbMallocRaw(pKeyInfo->db, nByte);
+ if( p==0 ) return 0;
+ p->needFree = 1;
+ }else{
+ p = pSpace;
+ p->needFree = 0;
+ }
+ p->pKeyInfo = pKeyInfo;
+ p->nField = pKeyInfo->nField + 1;
+ p->needDestroy = 1;
+ p->aMem = pMem = &((Mem*)p)[1];
+ idx = getVarint32(aKey, szHdr);
+ d = szHdr;
+ i = 0;
+ while( idx<szHdr && i<p->nField ){
+ u32 serial_type;
+
+ idx += getVarint32( aKey+idx, serial_type);
+ if( d>=nKey && sqlite3VdbeSerialTypeLen(serial_type)>0 ) break;
+ pMem->enc = pKeyInfo->enc;
+ pMem->db = pKeyInfo->db;
+ pMem->flags = 0;
+ pMem->zMalloc = 0;
+ d += sqlite3VdbeSerialGet(&aKey[d], serial_type, pMem);
+ pMem++;
+ i++;
+ }
+ p->nField = i;
+ return (void*)p;
+}
+
+/*
+** This routine destroys a UnpackedRecord object
+*/
+SQLITE_PRIVATE void sqlite3VdbeDeleteUnpackedRecord(UnpackedRecord *p){
+ if( p ){
+ if( p->needDestroy ){
+ int i;
+ Mem *pMem;
+ for(i=0, pMem=p->aMem; i<p->nField; i++, pMem++){
+ if( pMem->zMalloc ){
+ sqlite3VdbeMemRelease(pMem);
+ }
+ }
+ }
+ if( p->needFree ){
+ sqlite3_free(p);
+ }
+ }
+}
+
+/*
+** This function compares the two table rows or index records
+** specified by {nKey1, pKey1} and pPKey2. It returns a negative, zero
** or positive integer if {nKey1, pKey1} is less than, equal to or
-** greater than {nKey2, pKey2}. Both Key1 and Key2 must be byte strings
-** composed by the OP_MakeRecord opcode of the VDBE.
+** greater than pPKey2. The {nKey1, pKey1} key must be a blob
+** created by th OP_MakeRecord opcode of the VDBE. The pPKey2
+** key must be a parsed key such as obtained from
+** sqlite3VdbeParseRecord.
**
** Key1 and Key2 do not have to contain the same number of fields.
** But if the lengths differ, Key2 must be the shorter of the two.
+**
+** Historical note: In earlier versions of this routine both Key1
+** and Key2 were blobs obtained from OP_MakeRecord. But we found
+** that in typical use the same Key2 would be submitted multiple times
+** in a row. So an optimization was added to parse the Key2 key
+** separately and submit the parsed version. In this way, we avoid
+** parsing the same Key2 multiple times in a row.
*/
SQLITE_PRIVATE int sqlite3VdbeRecordCompare(
- void *userData,
int nKey1, const void *pKey1,
- int nKey2, const void *pKey2
-){
- KeyInfo *pKeyInfo = (KeyInfo*)userData;
- u32 d1, d2; /* Offset into aKey[] of next data element */
- u32 idx1, idx2; /* Offset into aKey[] of next header element */
- u32 szHdr1, szHdr2; /* Number of bytes in header */
+ UnpackedRecord *pPKey2
+){
+ u32 d1; /* Offset into aKey[] of next data element */
+ u32 idx1; /* Offset into aKey[] of next header element */
+ u32 szHdr1; /* Number of bytes in header */
int i = 0;
int nField;
int rc = 0;
const unsigned char *aKey1 = (const unsigned char *)pKey1;
- const unsigned char *aKey2 = (const unsigned char *)pKey2;
-
+ KeyInfo *pKeyInfo;
Mem mem1;
- Mem mem2;
+
+ pKeyInfo = pPKey2->pKeyInfo;
mem1.enc = pKeyInfo->enc;
mem1.db = pKeyInfo->db;
- mem2.enc = pKeyInfo->enc;
- mem2.db = pKeyInfo->db;
-
- idx1 = GetVarint(aKey1, szHdr1);
+ mem1.flags = 0;
+ mem1.zMalloc = 0;
+
+ idx1 = getVarint32(aKey1, szHdr1);
d1 = szHdr1;
- idx2 = GetVarint(aKey2, szHdr2);
- d2 = szHdr2;
nField = pKeyInfo->nField;
- while( idx1<szHdr1 && idx2<szHdr2 ){
- u32 serial_type1;
- u32 serial_type2;
+ while( idx1<szHdr1 && i<pPKey2->nField ){
+ u32 serial_type1;
/* Read the serial types for the next element in each key. */
- idx1 += GetVarint( aKey1+idx1, serial_type1 );
- if( d1>=nKey1 && sqlite3VdbeSerialTypeLen(serial_type1)>0 ) break;
- idx2 += GetVarint( aKey2+idx2, serial_type2 );
- if( d2>=nKey2 && sqlite3VdbeSerialTypeLen(serial_type2)>0 ) break;
+ idx1 += getVarint32( aKey1+idx1, serial_type1 );
+ if( d1>=nKey1 && sqlite3VdbeSerialTypeLen(serial_type1)>0 ) break;
/* Extract the values to be compared.
*/
d1 += sqlite3VdbeSerialGet(&aKey1[d1], serial_type1, &mem1);
- d2 += sqlite3VdbeSerialGet(&aKey2[d2], serial_type2, &mem2);
/* Do the comparison
*/
- rc = sqlite3MemCompare(&mem1, &mem2, i<nField ? pKeyInfo->aColl[i] : 0);
- if( mem1.flags & MEM_Dyn ) sqlite3VdbeMemRelease(&mem1);
- if( mem2.flags & MEM_Dyn ) sqlite3VdbeMemRelease(&mem2);
+ rc = sqlite3MemCompare(&mem1, &pPKey2->aMem[i],
+ i<nField ? pKeyInfo->aColl[i] : 0);
if( rc!=0 ){
break;
}
i++;
}
+ if( mem1.zMalloc ) sqlite3VdbeMemRelease(&mem1);
/* One of the keys ran out of fields, but all the fields up to that point
** were equal. If the incrKey flag is true, then the second key is
** treated as larger.
@@ -37773,10 +40577,8 @@
rc = -1;
}else if( !pKeyInfo->prefixIsEqual ){
if( d1<nKey1 ){
rc = 1;
- }else if( d2<nKey2 ){
- rc = -1; /* Only occurs on a corrupt database file */
}
}
}else if( pKeyInfo->aSortOrder && i<pKeyInfo->nField
&& pKeyInfo->aSortOrder[i] ){
@@ -37795,10 +40597,10 @@
SQLITE_PRIVATE int sqlite3VdbeIdxRowidLen(const u8 *aKey){
u32 szHdr; /* Size of the header */
u32 typeRowid; /* Serial type of the rowid */
- sqlite3GetVarint32(aKey, &szHdr);
- sqlite3GetVarint32(&aKey[szHdr-1], &typeRowid);
+ (void)getVarint32(aKey, szHdr);
+ (void)getVarint32(&aKey[szHdr-1], typeRowid);
return sqlite3VdbeSerialTypeLen(typeRowid);
}
@@ -37818,14 +40620,17 @@
sqlite3BtreeKeySize(pCur, &nCellKey);
if( nCellKey<=0 ){
return SQLITE_CORRUPT_BKPT;
}
+ m.flags = 0;
+ m.db = 0;
+ m.zMalloc = 0;
rc = sqlite3VdbeMemFromBtree(pCur, 0, nCellKey, 1, &m);
if( rc ){
return rc;
}
- sqlite3GetVarint32((u8*)m.z, &szHdr);
- sqlite3GetVarint32((u8*)&m.z[szHdr-1], &typeRowid);
+ (void)getVarint32((u8*)m.z, szHdr);
+ (void)getVarint32((u8*)&m.z[szHdr-1], typeRowid);
lenRowid = sqlite3VdbeSerialTypeLen(typeRowid);
sqlite3VdbeSerialGet((u8*)&m.z[m.n-lenRowid], typeRowid, &v);
*rowid = v.u.i;
sqlite3VdbeMemRelease(&m);
@@ -37843,8 +40648,9 @@
** is ignored as well.
*/
SQLITE_PRIVATE int sqlite3VdbeIdxKeyCompare(
Cursor *pC, /* The cursor to compare against */
+ UnpackedRecord *pUnpacked,
int nKey, const u8 *pKey, /* The key to compare */
int *res /* Write the comparison result here */
){
i64 nCellKey = 0;
@@ -37851,20 +40657,37 @@
int rc;
BtCursor *pCur = pC->pCursor;
int lenRowid;
Mem m;
+ UnpackedRecord *pRec;
+ char zSpace[200];
sqlite3BtreeKeySize(pCur, &nCellKey);
if( nCellKey<=0 ){
*res = 0;
return SQLITE_OK;
}
+ m.db = 0;
+ m.flags = 0;
+ m.zMalloc = 0;
rc = sqlite3VdbeMemFromBtree(pC->pCursor, 0, nCellKey, 1, &m);
if( rc ){
return rc;
}
lenRowid = sqlite3VdbeIdxRowidLen((u8*)m.z);
- *res = sqlite3VdbeRecordCompare(pC->pKeyInfo, m.n-lenRowid, m.z, nKey, pKey);
+ if( !pUnpacked ){
+ pRec = sqlite3VdbeRecordUnpack(pC->pKeyInfo, nKey, pKey,
+ zSpace, sizeof(zSpace));
+ }else{
+ pRec = pUnpacked;
+ }
+ if( pRec==0 ){
+ return SQLITE_NOMEM;
+ }
+ *res = sqlite3VdbeRecordCompare(m.n-lenRowid, m.z, pRec);
+ if( !pUnpacked ){
+ sqlite3VdbeDeleteUnpackedRecord(pRec);
+ }
sqlite3VdbeMemRelease(&m);
return SQLITE_OK;
}
@@ -37927,8 +40750,164 @@
** This file contains code use to implement APIs that are part of the
** VDBE.
*/
+#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
+/*
+** The following structure contains pointers to the end points of a
+** doubly-linked list of all compiled SQL statements that may be holding
+** buffers eligible for release when the sqlite3_release_memory() interface is
+** invoked. Access to this list is protected by the SQLITE_MUTEX_STATIC_LRU2
+** mutex.
+**
+** Statements are added to the end of this list when sqlite3_reset() is
+** called. They are removed either when sqlite3_step() or sqlite3_finalize()
+** is called. When statements are added to this list, the associated
+** register array (p->aMem[1..p->nMem]) may contain dynamic buffers that
+** can be freed using sqlite3VdbeReleaseMemory().
+**
+** When statements are added or removed from this list, the mutex
+** associated with the Vdbe being added or removed (Vdbe.db->mutex) is
+** already held. The LRU2 mutex is then obtained, blocking if necessary,
+** the linked-list pointers manipulated and the LRU2 mutex relinquished.
+*/
+struct StatementLruList {
+ Vdbe *pFirst;
+ Vdbe *pLast;
+};
+static struct StatementLruList sqlite3LruStatements;
+
+/*
+** Check that the list looks to be internally consistent. This is used
+** as part of an assert() statement as follows:
+**
+** assert( stmtLruCheck() );
+*/
+#ifndef NDEBUG
+static int stmtLruCheck(){
+ Vdbe *p;
+ for(p=sqlite3LruStatements.pFirst; p; p=p->pLruNext){
+ assert(p->pLruNext || p==sqlite3LruStatements.pLast);
+ assert(!p->pLruNext || p->pLruNext->pLruPrev==p);
+ assert(p->pLruPrev || p==sqlite3LruStatements.pFirst);
+ assert(!p->pLruPrev || p->pLruPrev->pLruNext==p);
+ }
+ return 1;
+}
+#endif
+
+/*
+** Add vdbe p to the end of the statement lru list. It is assumed that
+** p is not already part of the list when this is called. The lru list
+** is protected by the SQLITE_MUTEX_STATIC_LRU mutex.
+*/
+static void stmtLruAdd(Vdbe *p){
+ sqlite3_mutex_enter(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_LRU2));
+
+ if( p->pLruPrev || p->pLruNext || sqlite3LruStatements.pFirst==p ){
+ sqlite3_mutex_leave(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_LRU2));
+ return;
+ }
+
+ assert( stmtLruCheck() );
+
+ if( !sqlite3LruStatements.pFirst ){
+ assert( !sqlite3LruStatements.pLast );
+ sqlite3LruStatements.pFirst = p;
+ sqlite3LruStatements.pLast = p;
+ }else{
+ assert( !sqlite3LruStatements.pLast->pLruNext );
+ p->pLruPrev = sqlite3LruStatements.pLast;
+ sqlite3LruStatements.pLast->pLruNext = p;
+ sqlite3LruStatements.pLast = p;
+ }
+
+ assert( stmtLruCheck() );
+
+ sqlite3_mutex_leave(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_LRU2));
+}
+
+/*
+** Assuming the SQLITE_MUTEX_STATIC_LRU2 mutext is already held, remove
+** statement p from the least-recently-used statement list. If the
+** statement is not currently part of the list, this call is a no-op.
+*/
+static void stmtLruRemoveNomutex(Vdbe *p){
+ if( p->pLruPrev || p->pLruNext || p==sqlite3LruStatements.pFirst ){
+ assert( stmtLruCheck() );
+ if( p->pLruNext ){
+ p->pLruNext->pLruPrev = p->pLruPrev;
+ }else{
+ sqlite3LruStatements.pLast = p->pLruPrev;
+ }
+ if( p->pLruPrev ){
+ p->pLruPrev->pLruNext = p->pLruNext;
+ }else{
+ sqlite3LruStatements.pFirst = p->pLruNext;
+ }
+ p->pLruNext = 0;
+ p->pLruPrev = 0;
+ assert( stmtLruCheck() );
+ }
+}
+
+/*
+** Assuming the SQLITE_MUTEX_STATIC_LRU2 mutext is not held, remove
+** statement p from the least-recently-used statement list. If the
+** statement is not currently part of the list, this call is a no-op.
+*/
+static void stmtLruRemove(Vdbe *p){
+ sqlite3_mutex_enter(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_LRU2));
+ stmtLruRemoveNomutex(p);
+ sqlite3_mutex_leave(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_LRU2));
+}
+
+/*
+** Try to release n bytes of memory by freeing buffers associated
+** with the memory registers of currently unused vdbes.
+*/
+SQLITE_PRIVATE int sqlite3VdbeReleaseMemory(int n){
+ Vdbe *p;
+ Vdbe *pNext;
+ int nFree = 0;
+
+ sqlite3_mutex_enter(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_LRU2));
+ for(p=sqlite3LruStatements.pFirst; p && nFree<n; p=pNext){
+ pNext = p->pLruNext;
+
+ /* For each statement handle in the lru list, attempt to obtain the
+ ** associated database mutex. If it cannot be obtained, continue
+ ** to the next statement handle. It is not possible to block on
+ ** the database mutex - that could cause deadlock.
+ */
+ if( SQLITE_OK==sqlite3_mutex_try(p->db->mutex) ){
+ nFree += sqlite3VdbeReleaseBuffers(p);
+ stmtLruRemoveNomutex(p);
+ sqlite3_mutex_leave(p->db->mutex);
+ }
+ }
+ sqlite3_mutex_leave(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_LRU2));
+
+ return nFree;
+}
+
+/*
+** Call sqlite3Reprepare() on the statement. Remove it from the
+** lru list before doing so, as Reprepare() will free all the
+** memory register buffers anyway.
+*/
+int vdbeReprepare(Vdbe *p){
+ stmtLruRemove(p);
+ return sqlite3Reprepare(p);
+}
+
+#else /* !SQLITE_ENABLE_MEMORY_MANAGEMENT */
+ #define stmtLruRemove(x)
+ #define stmtLruAdd(x)
+ #define vdbeReprepare(x) sqlite3Reprepare(x)
+#endif
+
+
/*
** Return TRUE (non-zero) of the statement supplied as an argument needs
** to be recompiled. A statement needs to be recompiled whenever the
** execution environment changes in a way that would alter the program
@@ -37959,8 +40938,9 @@
#ifndef SQLITE_MUTEX_NOOP
sqlite3_mutex *mutex = v->db->mutex;
#endif
sqlite3_mutex_enter(mutex);
+ stmtLruRemove(v);
rc = sqlite3VdbeFinalize(v);
sqlite3_mutex_leave(mutex);
}
return rc;
@@ -37980,9 +40960,10 @@
rc = SQLITE_OK;
}else{
Vdbe *v = (Vdbe*)pStmt;
sqlite3_mutex_enter(v->db->mutex);
- rc = sqlite3VdbeReset(v);
+ rc = sqlite3VdbeReset(v, 1);
+ stmtLruAdd(v);
sqlite3VdbeMakeReady(v, -1, 0, 0, 0);
assert( (rc & (v->db->errMask))==rc );
sqlite3_mutex_leave(v->db->mutex);
}
@@ -37994,14 +40975,16 @@
*/
SQLITE_API int sqlite3_clear_bindings(sqlite3_stmt *pStmt){
int i;
int rc = SQLITE_OK;
+ Vdbe *p = (Vdbe*)pStmt;
#ifndef SQLITE_MUTEX_NOOP
sqlite3_mutex *mutex = ((Vdbe*)pStmt)->db->mutex;
#endif
sqlite3_mutex_enter(mutex);
- for(i=1; rc==SQLITE_OK && i<=sqlite3_bind_parameter_count(pStmt); i++){
- rc = sqlite3_bind_null(pStmt, i);
+ for(i=0; i<p->nVar; i++){
+ sqlite3VdbeMemRelease(&p->aVar[i]);
+ p->aVar[i].flags = MEM_Null;
}
sqlite3_mutex_leave(mutex);
return rc;
}
@@ -38074,15 +41057,15 @@
sqlite3VdbeMemSetDouble(&pCtx->s, rVal);
}
SQLITE_API void sqlite3_result_error(sqlite3_context *pCtx, const char *z, int n){
assert( sqlite3_mutex_held(pCtx->s.db->mutex) );
- pCtx->isError = 1;
+ pCtx->isError = SQLITE_ERROR;
sqlite3VdbeMemSetStr(&pCtx->s, z, n, SQLITE_UTF8, SQLITE_TRANSIENT);
}
#ifndef SQLITE_OMIT_UTF16
SQLITE_API void sqlite3_result_error16(sqlite3_context *pCtx, const void *z, int n){
assert( sqlite3_mutex_held(pCtx->s.db->mutex) );
- pCtx->isError = 1;
+ pCtx->isError = SQLITE_ERROR;
sqlite3VdbeMemSetStr(&pCtx->s, z, n, SQLITE_UTF16NATIVE, SQLITE_TRANSIENT);
}
#endif
SQLITE_API void sqlite3_result_int(sqlite3_context *pCtx, int iVal){
@@ -38142,20 +41125,25 @@
SQLITE_API void sqlite3_result_zeroblob(sqlite3_context *pCtx, int n){
assert( sqlite3_mutex_held(pCtx->s.db->mutex) );
sqlite3VdbeMemSetZeroBlob(&pCtx->s, n);
}
+SQLITE_API void sqlite3_result_error_code(sqlite3_context *pCtx, int errCode){
+ pCtx->isError = errCode;
+}
/* Force an SQLITE_TOOBIG error. */
SQLITE_API void sqlite3_result_error_toobig(sqlite3_context *pCtx){
assert( sqlite3_mutex_held(pCtx->s.db->mutex) );
- sqlite3VdbeMemSetZeroBlob(&pCtx->s, SQLITE_MAX_LENGTH+1);
+ pCtx->isError = SQLITE_TOOBIG;
+ sqlite3VdbeMemSetStr(&pCtx->s, "string or blob too big", -1,
+ SQLITE_UTF8, SQLITE_STATIC);
}
/* An SQLITE_NOMEM error. */
SQLITE_API void sqlite3_result_error_nomem(sqlite3_context *pCtx){
assert( sqlite3_mutex_held(pCtx->s.db->mutex) );
sqlite3VdbeMemSetNull(&pCtx->s);
- pCtx->isError = 1;
+ pCtx->isError = SQLITE_NOMEM;
pCtx->s.db->mallocFailed = 1;
}
/*
@@ -38212,8 +41200,9 @@
#endif
db->activeVdbeCnt++;
p->pc = 0;
+ stmtLruRemove(p);
}
#ifndef SQLITE_OMIT_EXPLAIN
if( p->explain ){
rc = sqlite3VdbeList(p);
@@ -38283,9 +41272,9 @@
sqlite3 *db = v->db;
sqlite3_mutex_enter(db->mutex);
while( (rc = sqlite3Step(v))==SQLITE_SCHEMA
&& cnt++ < 5
- && sqlite3Reprepare(v) ){
+ && vdbeReprepare(v) ){
sqlite3_reset(pStmt);
v->expired = 0;
}
if( rc==SQLITE_SCHEMA && v->zSql && db->pErr ){
@@ -38322,8 +41311,17 @@
return p->pFunc->pUserData;
}
/*
+** Extract the user data from a sqlite3_context structure and return a
+** pointer to it.
+*/
+SQLITE_API sqlite3 *sqlite3_context_db_handle(sqlite3_context *p){
+ assert( p && p->pFunc );
+ return p->s.db;
+}
+
+/*
** The following is the implementation of an SQL function that always
** fails with an error message stating that the function is used in the
** wrong context. The sqlite3_overload_function() API might construct
** SQL function that use this routine so that the functions will exist
@@ -38354,15 +41352,18 @@
assert( sqlite3_mutex_held(p->s.db->mutex) );
pMem = p->pMem;
if( (pMem->flags & MEM_Agg)==0 ){
if( nByte==0 ){
- assert( pMem->flags==MEM_Null );
+ sqlite3VdbeMemReleaseExternal(pMem);
+ pMem->flags = MEM_Null;
pMem->z = 0;
}else{
- pMem->flags = MEM_Agg;
- pMem->xDel = sqlite3_free;
+ sqlite3VdbeMemGrow(pMem, nByte, 0);
+ pMem->flags = MEM_Agg;
pMem->u.pDef = p->pFunc;
- pMem->z = sqlite3DbMallocZero(p->s.db, nByte);
+ if( pMem->z ){
+ memset(pMem->z, 0, nByte);
+ }
}
}
return (void*)pMem->z;
}
@@ -38475,9 +41476,9 @@
sqlite3_mutex_enter(pVm->db->mutex);
vals = sqlite3_data_count(pStmt);
pOut = &pVm->pResultSet[i];
}else{
- static const Mem nullMem = {{0}, 0.0, 0, "", 0, MEM_Null, SQLITE_NULL };
+ static const Mem nullMem = {{0}, 0.0, 0, "", 0, MEM_Null, SQLITE_NULL, 0, 0, 0 };
if( pVm->db ){
sqlite3_mutex_enter(pVm->db->mutex);
sqlite3Error(pVm->db, SQLITE_RANGE, 0);
}
@@ -38650,8 +41651,18 @@
}
#endif
/*
+** Constraint: If you have ENABLE_COLUMN_METADATA then you must
+** not define OMIT_DECLTYPE.
+*/
+#if defined(SQLITE_OMIT_DECLTYPE) && defined(SQLITE_ENABLE_COLUMN_METADATA)
+# error "Must not define both SQLITE_OMIT_DECLTYPE \
+ and SQLITE_ENABLE_COLUMN_METADATA"
+#endif
+
+#ifndef SQLITE_OMIT_DECLTYPE
+/*
** Return the column declaration type (if applicable) of the 'i'th column
** of the result set of SQL statement pStmt.
*/
SQLITE_API const char *sqlite3_column_decltype(sqlite3_stmt *pStmt, int N){
@@ -38663,8 +41674,9 @@
return columnName(
pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, COLNAME_DECLTYPE);
}
#endif /* SQLITE_OMIT_UTF16 */
+#endif /* SQLITE_OMIT_DECLTYPE */
#ifdef SQLITE_ENABLE_COLUMN_METADATA
/*
** Return the name of the database from which a result column derives.
@@ -38852,8 +41864,9 @@
rc = vdbeUnbind(p, i);
if( rc==SQLITE_OK ){
rc = sqlite3VdbeMemCopy(&p->aVar[i-1], pValue);
}
+ rc = sqlite3ApiExit(p->db, rc);
sqlite3_mutex_leave(p->db->mutex);
return rc;
}
SQLITE_API int sqlite3_bind_zeroblob(sqlite3_stmt *pStmt, int i, int n){
@@ -39020,9 +42033,9 @@
** of the code in this file is, therefore, important. See other comments
** in this file for details. If in doubt, do not deviate from existing
** commenting and indentation practices when changing or adding code.
**
-** $Id: vdbe.c,v 1.707 2008/01/31 19:34:52 drh Exp $
+** $Id: vdbe.c,v 1.740 2008/05/13 13:27:34 drh Exp $
*/
/*
** The following global variable is incremented every time a cursor
@@ -39077,9 +42090,9 @@
/*
** Test a register to see if it exceeds the current maximum blob size.
** If it does, record the new maximum blob size.
*/
-#ifdef SQLITE_TEST
+#if defined(SQLITE_TEST) && !defined(SQLITE_OMIT_BUILTIN_TEST)
# define UPDATE_MAX_BLOBSIZE(P) updateMaxBlobsize(P)
#else
# define UPDATE_MAX_BLOBSIZE(P)
#endif
@@ -39096,25 +42109,8 @@
*/
#define Stringify(P, enc) \
if(((P)->flags&(MEM_Str|MEM_Blob))==0 && sqlite3VdbeMemStringify(P,enc)) \
{ goto no_mem; }
-
-/*
-** The header of a record consists of a sequence variable-length integers.
-** These integers are almost always small and are encoded as a single byte.
-** The following macro takes advantage this fact to provide a fast decode
-** of the integers in a record header. It is faster for the common case
-** where the integer is a single byte. It is a little slower when the
-** integer is two or more bytes. But overall it is faster.
-**
-** The following expressions are equivalent:
-**
-** x = sqlite3GetVarint32( A, &B );
-**
-** x = GetVarint( A, B );
-**
-*/
-#define GetVarint(A,B) ((B = *(A))<=0x7f ? 1 : sqlite3GetVarint32(A, &B))
/*
** An ephemeral string value (signified by the MEM_Ephem flag) contains
** a pointer to a dynamically allocated string where some other entity
@@ -39182,17 +42178,67 @@
/*
** Allocate cursor number iCur. Return a pointer to it. Return NULL
** if we run out of memory.
*/
-static Cursor *allocateCursor(Vdbe *p, int iCur, int iDb){
- Cursor *pCx;
+static Cursor *allocateCursor(
+ Vdbe *p,
+ int iCur,
+ Op *pOp,
+ int iDb,
+ int isBtreeCursor
+){
+ /* Find the memory cell that will be used to store the blob of memory
+ ** required for this Cursor structure. It is convenient to use a
+ ** vdbe memory cell to manage the memory allocation required for a
+ ** Cursor structure for the following reasons:
+ **
+ ** * Sometimes cursor numbers are used for a couple of different
+ ** purposes in a vdbe program. The different uses might require
+ ** different sized allocations. Memory cells provide growable
+ ** allocations.
+ **
+ ** * When using ENABLE_MEMORY_MANAGEMENT, memory cell buffers can
+ ** be freed lazily via the sqlite3_release_memory() API. This
+ ** minimizes the number of malloc calls made by the system.
+ **
+ ** Memory cells for cursors are allocated at the top of the address
+ ** space. Memory cell (p->nMem) corresponds to cursor 0. Space for
+ ** cursor 1 is managed by memory cell (p->nMem-1), etc.
+ */
+ Mem *pMem = &p->aMem[p->nMem-iCur];
+
+ int nByte;
+ Cursor *pCx = 0;
+ /* If the opcode of pOp is OP_SetNumColumns, then pOp->p2 contains
+ ** the number of fields in the records contained in the table or
+ ** index being opened. Use this to reserve space for the
+ ** Cursor.aType[] array.
+ */
+ int nField = 0;
+ if( pOp->opcode==OP_SetNumColumns || pOp->opcode==OP_OpenEphemeral ){
+ nField = pOp->p2;
+ }
+ nByte =
+ sizeof(Cursor) +
+ (isBtreeCursor?sqlite3BtreeCursorSize():0) +
+ 2*nField*sizeof(u32);
+
assert( iCur<p->nCursor );
if( p->apCsr[iCur] ){
sqlite3VdbeFreeCursor(p, p->apCsr[iCur]);
- }
- p->apCsr[iCur] = pCx = sqlite3MallocZero( sizeof(Cursor) );
- if( pCx ){
+ p->apCsr[iCur] = 0;
+ }
+ if( SQLITE_OK==sqlite3VdbeMemGrow(pMem, nByte, 0) ){
+ p->apCsr[iCur] = pCx = (Cursor *)pMem->z;
+ memset(pMem->z, 0, nByte);
pCx->iDb = iDb;
+ pCx->nField = nField;
+ if( nField ){
+ pCx->aType = (u32 *)&pMem->z[sizeof(Cursor)];
+ }
+ if( isBtreeCursor ){
+ pCx->pCursor = (BtCursor *)&pMem->z[sizeof(Cursor)+2*nField*sizeof(u32)];
+ }
}
return pCx;
}
@@ -39210,11 +42256,10 @@
&& sqlite3IsNumber(pRec->z, &realnum, pRec->enc) ){
i64 value;
sqlite3VdbeChangeEncoding(pRec, SQLITE_UTF8);
if( !realnum && sqlite3Atoi64(pRec->z, &value) ){
- sqlite3VdbeMemRelease(pRec);
pRec->u.i = value;
- pRec->flags = MEM_Int;
+ MemSetTypeFlag(pRec, MEM_Int);
}else{
sqlite3VdbeMemRealify(pRec);
}
}
@@ -39414,13 +42459,12 @@
** processor and returns that value. This can be used for high-res
** profiling.
*/
__inline__ unsigned long long int hwtime(void){
- unsigned long long int x;
- __asm__("rdtsc\n\t"
- "mov %%edx, %%ecx\n\t"
- :"=A" (x));
- return x;
+ unsigned int lo, hi;
+ /* We cannot use "=A", since this would use %rax on x86_64 */
+ __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
+ return (unsigned long long int)hi << 32 | lo;
}
#endif
/*
@@ -39502,10 +42546,11 @@
db->busyHandler.nBusy = 0;
CHECK_FOR_INTERRUPT;
sqlite3VdbeIOTraceSql(p);
#ifdef SQLITE_DEBUG
+ sqlite3FaultBeginBenign(-1);
if( p->pc==0 && ((p->db->flags & SQLITE_VdbeListing)!=0
- || sqlite3OsAccess(db->pVfs, "vdbe_explain", SQLITE_ACCESS_EXISTS))
+ || sqlite3OsAccess(db->pVfs, "vdbe_explain", SQLITE_ACCESS_EXISTS)==1 )
){
int i;
printf("VDBE Program Listing:\n");
sqlite3VdbePrintSql(p);
@@ -39512,11 +42557,12 @@
for(i=0; i<p->nOp; i++){
sqlite3VdbePrintOp(stdout, i, &p->aOp[i]);
}
}
- if( sqlite3OsAccess(db->pVfs, "vdbe_trace", SQLITE_ACCESS_EXISTS) ){
+ if( sqlite3OsAccess(db->pVfs, "vdbe_trace", SQLITE_ACCESS_EXISTS)==1 ){
p->trace = stdout;
}
+ sqlite3FaultEndBenign(-1);
#endif
for(pc=p->pc; rc==SQLITE_OK; pc++){
assert( pc>=0 && pc<p->nOp );
if( db->mallocFailed ) goto no_mem;
@@ -39535,11 +42581,14 @@
sqlite3VdbePrintSql(p);
}
sqlite3VdbePrintOp(p->trace, pc, pOp);
}
- if( p->trace==0 && pc==0
- && sqlite3OsAccess(db->pVfs, "vdbe_sqltrace", SQLITE_ACCESS_EXISTS) ){
- sqlite3VdbePrintSql(p);
+ if( p->trace==0 && pc==0 ){
+ sqlite3FaultBeginBenign(-1);
+ if( sqlite3OsAccess(db->pVfs, "vdbe_sqltrace", SQLITE_ACCESS_EXISTS)==1 ){
+ sqlite3VdbePrintSql(p);
+ }
+ sqlite3FaultEndBenign(-1);
}
#endif
@@ -39587,9 +42636,9 @@
if( (opProperty & OPFLG_OUT2_PRERELEASE)!=0 ){
assert( pOp->p2>0 );
assert( pOp->p2<=p->nMem );
pOut = &p->aMem[pOp->p2];
- sqlite3VdbeMemRelease(pOut);
+ sqlite3VdbeMemReleaseExternal(pOut);
pOut->flags = MEM_Null;
}else
/* Do common setup for opcodes marked with one of the following
@@ -39780,8 +42829,9 @@
** Write that value into register P2.
*/
case OP_Real: { /* same as TK_FLOAT, out2-prerelease */
pOut->flags = MEM_Real;
+ assert( !sqlite3IsNaN(*pOp->p4.pReal) );
pOut->r = *pOp->p4.pReal;
break;
}
@@ -39799,24 +42849,25 @@
if( encoding!=SQLITE_UTF8 ){
sqlite3VdbeMemSetStr(pOut, pOp->p4.z, -1, SQLITE_UTF8, SQLITE_STATIC);
if( SQLITE_OK!=sqlite3VdbeChangeEncoding(pOut, encoding) ) goto no_mem;
if( SQLITE_OK!=sqlite3VdbeMemDynamicify(pOut) ) goto no_mem;
- pOut->flags &= ~(MEM_Dyn);
+ pOut->zMalloc = 0;
pOut->flags |= MEM_Static;
+ pOut->flags &= ~MEM_Dyn;
if( pOp->p4type==P4_DYNAMIC ){
sqlite3_free(pOp->p4.z);
}
pOp->p4type = P4_DYNAMIC;
pOp->p4.z = pOut->z;
pOp->p1 = pOut->n;
- if( pOp->p1>SQLITE_MAX_LENGTH ){
+ if( pOp->p1>db->aLimit[SQLITE_LIMIT_LENGTH] ){
goto too_big;
}
UPDATE_MAX_BLOBSIZE(pOut);
break;
}
#endif
- if( pOp->p1>SQLITE_MAX_LENGTH ){
+ if( pOp->p1>db->aLimit[SQLITE_LIMIT_LENGTH] ){
goto too_big;
}
/* Fall through to the next case, OP_String */
}
@@ -39891,15 +42942,48 @@
** Move the value in register P1 over into register P2. Register P1
** is left holding a NULL. It is an error for P1 and P2 to be the
** same register.
*/
+case OP_Move: {
+ char *zMalloc;
+ assert( pOp->p1>0 );
+ assert( pOp->p1<=p->nMem );
+ pIn1 = &p->aMem[pOp->p1];
+ REGISTER_TRACE(pOp->p1, pIn1);
+ assert( pOp->p2>0 );
+ assert( pOp->p2<=p->nMem );
+ pOut = &p->aMem[pOp->p2];
+ assert( pOut!=pIn1 );
+ zMalloc = pOut->zMalloc;
+ pOut->zMalloc = 0;
+ sqlite3VdbeMemMove(pOut, pIn1);
+ pIn1->zMalloc = zMalloc;
+ REGISTER_TRACE(pOp->p2, pOut);
+ break;
+}
+
/* Opcode: Copy P1 P2 * * *
**
** Make a copy of register P1 into register P2.
**
** This instruction makes a deep copy of the value. A duplicate
** is made of any string or blob constant. See also OP_SCopy.
*/
+case OP_Copy: {
+ assert( pOp->p1>0 );
+ assert( pOp->p1<=p->nMem );
+ pIn1 = &p->aMem[pOp->p1];
+ REGISTER_TRACE(pOp->p1, pIn1);
+ assert( pOp->p2>0 );
+ assert( pOp->p2<=p->nMem );
+ pOut = &p->aMem[pOp->p2];
+ assert( pOut!=pIn1 );
+ sqlite3VdbeMemShallowCopy(pOut, pIn1, MEM_Ephem);
+ Deephemeralize(pOut);
+ REGISTER_TRACE(pOp->p2, pOut);
+ break;
+}
+
/* Opcode: SCopy P1 P2 * * *
**
** Make a shallow copy of register P1 into register P2.
**
@@ -39910,10 +42994,8 @@
** Thus the program must guarantee that the original will not change
** during the lifetime of the copy. Use OP_Copy to make a complete
** copy.
*/
-case OP_Move:
-case OP_Copy:
case OP_SCopy: {
assert( pOp->p1>0 );
assert( pOp->p1<=p->nMem );
pIn1 = &p->aMem[pOp->p1];
@@ -39921,16 +43003,9 @@
assert( pOp->p2>0 );
assert( pOp->p2<=p->nMem );
pOut = &p->aMem[pOp->p2];
assert( pOut!=pIn1 );
- if( pOp->opcode==OP_Move ){
- sqlite3VdbeMemMove(pOut, pIn1);
- }else{
- sqlite3VdbeMemShallowCopy(pOut, pIn1, MEM_Ephem);
- if( pOp->opcode==OP_Copy ){
- Deephemeralize(pOut);
- }
- }
+ sqlite3VdbeMemShallowCopy(pOut, pIn1, MEM_Ephem);
REGISTER_TRACE(pOp->p2, pOut);
break;
}
@@ -39960,8 +43035,9 @@
for(i=0; i<pOp->p2; i++){
sqlite3VdbeMemNulTerminate(&pMem[i]);
storeTypeInfo(&pMem[i], encoding);
}
+ if( db->mallocFailed ) goto no_mem;
/* Return SQLITE_ROW
*/
p->nCallback++;
@@ -39974,40 +43050,44 @@
**
** Add the text in register P1 onto the end of the text in
** register P2 and store the result in register P3.
** If either the P1 or P2 text are NULL then store NULL in P3.
-*/
-case OP_Concat: { /* same as TK_CONCAT, in1, in2, out3 */
- char *zNew;
+**
+** P3 = P2 || P1
+**
+** It is illegal for P1 and P3 to be the same register. Sometimes,
+** if P3 is the same register as P2, the implementation is able
+** to avoid a memcpy().
+*/
+case OP_Concat: { /* same as TK_CONCAT, in1, in2, out3 */
i64 nByte;
+ assert( pIn1!=pOut );
if( (pIn1->flags | pIn2->flags) & MEM_Null ){
- Release(pOut);
- pOut->flags = MEM_Null;
+ sqlite3VdbeMemSetNull(pOut);
break;
}
ExpandBlob(pIn1);
Stringify(pIn1, encoding);
ExpandBlob(pIn2);
Stringify(pIn2, encoding);
nByte = pIn1->n + pIn2->n;
- if( nByte>SQLITE_MAX_LENGTH ){
+ if( nByte>db->aLimit[SQLITE_LIMIT_LENGTH] ){
goto too_big;
}
- zNew = sqlite3DbMallocRaw(db, nByte+2);
- if( zNew==0 ){
+ MemSetTypeFlag(pOut, MEM_Str);
+ if( sqlite3VdbeMemGrow(pOut, nByte+2, pOut==pIn2) ){
goto no_mem;
}
- memcpy(zNew, pIn2->z, pIn2->n);
- memcpy(&zNew[pIn2->n], pIn1->z, pIn1->n);
- zNew[nByte] = 0;
- zNew[nByte+1] = 0;
- Release(pOut);
+ if( pOut!=pIn2 ){
+ memcpy(pOut->z, pIn2->z, pIn2->n);
+ }
+ memcpy(&pOut->z[pIn2->n], pIn1->z, pIn1->n);
+ pOut->z[nByte] = 0;
+ pOut->z[nByte+1] = 0;
+ pOut->flags |= MEM_Term;
pOut->n = nByte;
- pOut->flags = MEM_Str|MEM_Dyn|MEM_Term;
- pOut->xDel = 0;
- pOut->enc = encoding;
- pOut->z = zNew;
+ pOut->enc = encoding;
UPDATE_MAX_BLOBSIZE(pOut);
break;
}
@@ -40062,15 +43142,15 @@
case OP_Multiply: b *= a; break;
case OP_Divide: {
if( a==0 ) goto arithmetic_result_is_null;
/* Dividing the largest possible negative 64-bit integer (1<<63) by
- ** -1 returns an integer to large to store in a 64-bit data-type. On
+ ** -1 returns an integer too large to store in a 64-bit data-type. On
** some architectures, the value overflows to (1<<63). On others,
** a SIGFPE is issued. The following statement normalizes this
** behaviour so that all architectures behave as if integer
** overflow occured.
*/
- if( a==-1 && b==(((i64)1)<<63) ) a = 1;
+ if( a==-1 && b==SMALLEST_INT64 ) a = 1;
b /= a;
break;
}
default: {
@@ -40079,11 +43159,10 @@
b %= a;
break;
}
}
- Release(pOut);
pOut->u.i = b;
- pOut->flags = MEM_Int;
+ MemSetTypeFlag(pOut, MEM_Int);
}else{
double a, b;
a = sqlite3VdbeRealValue(pIn1);
b = sqlite3VdbeRealValue(pIn2);
@@ -40104,14 +43183,13 @@
b = ib % ia;
break;
}
}
- if( sqlite3_isnan(b) ){
+ if( sqlite3IsNaN(b) ){
goto arithmetic_result_is_null;
}
- Release(pOut);
pOut->r = b;
- pOut->flags = MEM_Real;
+ MemSetTypeFlag(pOut, MEM_Real);
if( (flags & MEM_Real)==0 ){
sqlite3VdbeIntegerAffinity(pOut);
}
}
@@ -40142,8 +43220,9 @@
**
** Invoke a user function (P4 is a pointer to a Function structure that
** defines the function) with P5 arguments taken from register P2 and
** successors. The result of the function is stored in register P3.
+** Register P3 must not be one of the function inputs.
**
** P1 is a 32-bit bitmask indicating whether or not each argument to the
** function was determined to be constant at compile time. If the first
** argument was constant then bit 0 of P1 is set. This is used to determine
@@ -40163,8 +43242,9 @@
apVal = p->apArg;
assert( apVal || n==0 );
assert( n==0 || (pOp->p2>0 && pOp->p2+n<=p->nMem) );
+ assert( pOp->p3<pOp->p2 || pOp->p3>=pOp->p2+n );
pArg = &p->aMem[pOp->p2];
for(i=0; i<n; i++, pArg++){
apVal[i] = pArg;
storeTypeInfo(pArg, encoding);
@@ -40179,12 +43259,22 @@
ctx.pVdbeFunc = (VdbeFunc*)pOp->p4.pVdbeFunc;
ctx.pFunc = ctx.pVdbeFunc->pFunc;
}
- ctx.s.flags = MEM_Null;
- ctx.s.z = 0;
- ctx.s.xDel = 0;
+ assert( pOp->p3>0 && pOp->p3<=p->nMem );
+ pOut = &p->aMem[pOp->p3];
+ ctx.s.flags = MEM_Null;
ctx.s.db = db;
+ ctx.s.xDel = 0;
+ ctx.s.zMalloc = 0;
+
+ /* The output cell may already have a buffer allocated. Move
+ ** the pointer to ctx.s so in case the user-function can use
+ ** the already allocated buffer instead of allocating a new one.
+ */
+ sqlite3VdbeMemMove(&ctx.s, pOut);
+ MemSetTypeFlag(&ctx.s, MEM_Null);
+
ctx.isError = 0;
if( ctx.pFunc->needCollSeq ){
assert( pOp>p->aOp );
assert( pOp[-1].p4type==P4_COLLSEQ );
@@ -40192,9 +43282,12 @@
ctx.pColl = pOp[-1].p4.pColl;
}
if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
(*ctx.pFunc->xFunc)(&ctx, n, apVal);
- if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
+ if( sqlite3SafetyOn(db) ){
+ sqlite3VdbeMemRelease(&ctx.s);
+ goto abort_due_to_misuse;
+ }
if( db->mallocFailed ){
/* Even though a malloc() has failed, the implementation of the
** user function may have called an sqlite3_result_XXX() function
** to return a value. The following call releases any resources
@@ -40219,15 +43312,13 @@
/* If the function returned an error, throw an exception */
if( ctx.isError ){
sqlite3SetString(&p->zErrMsg, sqlite3_value_text(&ctx.s), (char*)0);
- rc = SQLITE_ERROR;
+ rc = ctx.isError;
}
/* Copy the result of the function into register P3 */
sqlite3VdbeChangeEncoding(&ctx.s, encoding);
- assert( pOp->p3>0 && pOp->p3<=p->nMem );
- pOut = &p->aMem[pOp->p3];
sqlite3VdbeMemMove(pOut, &ctx.s);
if( sqlite3VdbeMemTooBig(pOut) ){
goto too_big;
}
@@ -40280,11 +43371,10 @@
case OP_ShiftLeft: a <<= b; break;
default: assert( pOp->opcode==OP_ShiftRight );
a >>= b; break;
}
- Release(pOut);
pOut->u.i = a;
- pOut->flags = MEM_Int;
+ MemSetTypeFlag(pOut, MEM_Int);
break;
}
/* Opcode: AddImm P1 P2 * * *
@@ -40324,11 +43414,10 @@
v = (sqlite3_int64)pIn1->r;
if( pIn1->r>(double)v ) v++;
if( pOp->p3 && pIn1->r==(double)v ) v++;
}
- Release(pIn1);
pIn1->u.i = v;
- pIn1->flags = MEM_Int;
+ MemSetTypeFlag(pIn1, MEM_Int);
break;
}
/* Opcode: MustBeInt P1 P2 * * *
@@ -40347,10 +43436,9 @@
}else{
pc = pOp->p2 - 1;
}
}else{
- Release(pIn1);
- pIn1->flags = MEM_Int;
+ MemSetTypeFlag(pIn1, MEM_Int);
}
break;
}
@@ -40385,9 +43473,9 @@
assert( MEM_Str==(MEM_Blob>>3) );
pIn1->flags |= (pIn1->flags&MEM_Blob)>>3;
applyAffinity(pIn1, SQLITE_AFF_TEXT, encoding);
rc = ExpandBlob(pIn1);
- assert( pIn1->flags & MEM_Str );
+ assert( pIn1->flags & MEM_Str || db->mallocFailed );
pIn1->flags &= ~(MEM_Int|MEM_Real|MEM_Blob);
UPDATE_MAX_BLOBSIZE(pIn1);
break;
}
@@ -40404,12 +43492,11 @@
case OP_ToBlob: { /* same as TK_TO_BLOB, in1 */
if( pIn1->flags & MEM_Null ) break;
if( (pIn1->flags & MEM_Blob)==0 ){
applyAffinity(pIn1, SQLITE_AFF_TEXT, encoding);
- assert( pIn1->flags & MEM_Str );
- pIn1->flags |= MEM_Blob;
- }
- pIn1->flags &= ~(MEM_Int|MEM_Real|MEM_Str);
+ assert( pIn1->flags & MEM_Str || db->mallocFailed );
+ }
+ MemSetTypeFlag(pIn1, MEM_Blob);
UPDATE_MAX_BLOBSIZE(pIn1);
break;
}
@@ -40565,10 +43652,9 @@
** SQLITE_JUMPIFNULL bit is set.
*/
if( pOp->p5 & SQLITE_STOREP2 ){
pOut = &p->aMem[pOp->p2];
- Release(pOut);
- pOut->flags = MEM_Null;
+ MemSetTypeFlag(pOut, MEM_Null);
REGISTER_TRACE(pOp->p2, pOut);
}else if( pOp->p5 & SQLITE_JUMPIFNULL ){
pc = pOp->p2-1;
}
@@ -40596,10 +43682,9 @@
}
if( pOp->p5 & SQLITE_STOREP2 ){
pOut = &p->aMem[pOp->p2];
- Release(pOut);
- pOut->flags = MEM_Int;
+ MemSetTypeFlag(pOut, MEM_Int);
pOut->u.i = res;
REGISTER_TRACE(pOp->p2, pOut);
}else if( res ){
pc = pOp->p2-1;
@@ -40645,14 +43730,13 @@
}else{
static const unsigned char or_logic[] = { 0, 1, 2, 1, 1, 1, 2, 1, 2 };
v1 = or_logic[v1*3+v2];
}
- Release(pOut);
if( v1==2 ){
- pOut->flags = MEM_Null;
+ MemSetTypeFlag(pOut, MEM_Null);
}else{
pOut->u.i = v1;
- pOut->flags = MEM_Int;
+ MemSetTypeFlag(pOut, MEM_Int);
}
break;
}
@@ -40665,9 +43749,9 @@
case OP_Not: { /* same as TK_NOT, in1 */
if( pIn1->flags & MEM_Null ) break; /* Do nothing to NULLs */
sqlite3VdbeMemIntegerify(pIn1);
pIn1->u.i = !pIn1->u.i;
- assert( pIn1->flags==MEM_Int );
+ assert( pIn1->flags&MEM_Int );
break;
}
/* Opcode: BitNot P1 * * * *
@@ -40679,9 +43763,9 @@
case OP_BitNot: { /* same as TK_BITNOT, in1 */
if( pIn1->flags & MEM_Null ) break; /* Do nothing to NULLs */
sqlite3VdbeMemIntegerify(pIn1);
pIn1->u.i = ~pIn1->u.i;
- assert( pIn1->flags==MEM_Int );
+ assert( pIn1->flags&MEM_Int );
break;
}
/* Opcode: If P1 P2 P3 * *
@@ -40744,24 +43828,25 @@
}
break;
}
-/* Opcode: SetNumColumns P1 P2 * * *
-**
-** Before the OP_Column opcode can be executed on a cursor, this
-** opcode must be called to set the number of fields in the table.
-**
-** This opcode sets the number of columns for cursor P1 to P2.
-**
-** If OP_KeyAsData is to be applied to cursor P1, it must be executed
-** before this op-code.
-*/
-case OP_SetNumColumns: {
- Cursor *pC;
- assert( (pOp->p1)<p->nCursor );
- assert( p->apCsr[pOp->p1]!=0 );
- pC = p->apCsr[pOp->p1];
- pC->nField = pOp->p2;
+/* Opcode: SetNumColumns * P2 * * *
+**
+** This opcode sets the number of columns for the cursor opened by the
+** following instruction to P2.
+**
+** An OP_SetNumColumns is only useful if it occurs immediately before
+** one of the following opcodes:
+**
+** OpenRead
+** OpenWrite
+** OpenPseudo
+**
+** If the OP_Column opcode is to be executed on a cursor, then
+** this opcode must be present immediately before the opcode that
+** opens the cursor.
+*/
+case OP_SetNumColumns: {
break;
}
/* Opcode: Column P1 P2 P3 P4 *
@@ -40797,12 +43882,14 @@
Mem *pDest; /* Where to write the extracted value */
Mem sMem; /* For storing the record being decoded */
sMem.flags = 0;
+ sMem.db = 0;
+ sMem.zMalloc = 0;
assert( p1<p->nCursor );
assert( pOp->p3>0 && pOp->p3<=p->nMem );
pDest = &p->aMem[pOp->p3];
- sqlite3VdbeMemSetNull(pDest);
+ MemSetTypeFlag(pDest, MEM_Null);
/* This block sets the variable payloadSize to be the total number of
** bytes in the record.
**
@@ -40851,12 +43938,12 @@
}
/* If payloadSize is 0, then just store a NULL */
if( payloadSize==0 ){
- assert( pDest->flags==MEM_Null );
+ assert( pDest->flags&MEM_Null );
goto op_column_out;
}
- if( payloadSize>SQLITE_MAX_LENGTH ){
+ if( payloadSize>db->aLimit[SQLITE_LIMIT_LENGTH] ){
goto too_big;
}
assert( p2<nField );
@@ -40863,10 +43950,10 @@
/* Read and parse the table header. Store the results of the parse
** into the record header cache fields of the cursor.
*/
- if( pC->cacheStatus==p->cacheCtr ){
- aType = pC->aType;
+ aType = pC->aType;
+ if( pC->cacheStatus==p->cacheCtr ){
aOffset = pC->aOffset;
}else{
u8 *zIdx; /* Index into header */
u8 *zEndHdr; /* Pointer to first byte after the header */
@@ -40873,15 +43960,9 @@
u32 offset; /* Offset into the data */
int szHdrSz; /* Size of the header size field at start of record */
int avail; /* Number of bytes of available data */
- aType = pC->aType;
- if( aType==0 ){
- pC->aType = aType = sqlite3DbMallocRaw(db, 2*nField*sizeof(aType) );
- }
- if( aType==0 ){
- goto no_mem;
- }
+ assert(aType);
pC->aOffset = aOffset = &aType[nField];
pC->payloadSize = payloadSize;
pC->cacheStatus = p->cacheCtr;
@@ -40908,9 +43989,9 @@
}
/* The following assert is true in all cases accept when
** the database file has been corrupted externally.
** assert( zRec!=0 || avail>=payloadSize || avail>=9 ); */
- szHdrSz = GetVarint((u8*)zData, offset);
+ szHdrSz = getVarint32((u8*)zData, offset);
/* The KeyFetch() or DataFetch() above are fast and will get the entire
** record header in most cases. But they will fail to get the complete
** record header if the record header does not fit on a single page
@@ -40917,8 +43998,10 @@
** in the B-Tree. When that happens, use sqlite3VdbeMemFromBtree() to
** acquire the complete header text.
*/
if( !zRec && avail<offset ){
+ sMem.flags = 0;
+ sMem.db = 0;
rc = sqlite3VdbeMemFromBtree(pCrsr, 0, offset, pC->isIndex, &sMem);
if( rc!=SQLITE_OK ){
goto op_column_out;
}
@@ -40934,9 +44017,9 @@
*/
for(i=0; i<nField; i++){
if( zIdx<zEndHdr ){
aOffset[i] = offset;
- zIdx += GetVarint(zIdx, aType[i]);
+ zIdx += getVarint32(zIdx, aType[i]);
offset += sqlite3VdbeSerialTypeLen(aType[i]);
}else{
/* If i is less that nField, then there are less fields in this
** record than SetNumColumns indicated there are columns in the
@@ -40946,16 +44029,18 @@
*/
aOffset[i] = 0;
}
}
- Release(&sMem);
+ sqlite3VdbeMemRelease(&sMem);
sMem.flags = MEM_Null;
/* If we have read more header data than was contained in the header,
** or if the end of the last field appears to be past the end of the
- ** record, then we must be dealing with a corrupt database.
- */
- if( zIdx>zEndHdr || offset>payloadSize ){
+ ** record, or if the end of the last field appears to be before the end
+ ** of the record (when all fields present), then we must be dealing
+ ** with a corrupt database.
+ */
+ if( zIdx>zEndHdr || offset>payloadSize || (zIdx==zEndHdr && offset!=payloadSize) ){
rc = SQLITE_CORRUPT_BKPT;
goto op_column_out;
}
}
@@ -40968,24 +44053,35 @@
*/
if( aOffset[p2] ){
assert( rc==SQLITE_OK );
if( zRec ){
- zData = &zRec[aOffset[p2]];
+ if( pDest->flags&MEM_Dyn ){
+ sqlite3VdbeSerialGet((u8 *)&zRec[aOffset[p2]], aType[p2], &sMem);
+ sMem.db = db;
+ rc = sqlite3VdbeMemCopy(pDest, &sMem);
+ assert( !(sMem.flags&MEM_Dyn) );
+ if( rc!=SQLITE_OK ){
+ goto op_column_out;
+ }
+ }else{
+ sqlite3VdbeSerialGet((u8 *)&zRec[aOffset[p2]], aType[p2], pDest);
+ }
}else{
len = sqlite3VdbeSerialTypeLen(aType[p2]);
+ sqlite3VdbeMemMove(&sMem, pDest);
rc = sqlite3VdbeMemFromBtree(pCrsr, aOffset[p2], len, pC->isIndex, &sMem);
if( rc!=SQLITE_OK ){
goto op_column_out;
}
zData = sMem.z;
- }
- sqlite3VdbeSerialGet((u8*)zData, aType[p2], pDest);
+ sqlite3VdbeSerialGet((u8*)zData, aType[p2], pDest);
+ }
pDest->enc = encoding;
}else{
if( pOp->p4type==P4_MEM ){
sqlite3VdbeMemShallowCopy(pDest, pOp->p4.pMem, MEM_Static);
}else{
- assert( pDest->flags==MEM_Null );
+ assert( pDest->flags&MEM_Null );
}
}
/* If we dynamically allocated space to hold the data (in the
@@ -40992,19 +44088,18 @@
** sqlite3VdbeMemFromBtree() call above) then transfer control of that
** dynamically allocated space over to the pDest structure.
** This prevents a memory copy.
*/
- if( (sMem.flags & MEM_Dyn)!=0 ){
- assert( pDest->flags & MEM_Ephem );
- assert( pDest->flags & (MEM_Str|MEM_Blob) );
- assert( pDest->z==sMem.z );
- assert( sMem.flags & MEM_Term );
- pDest->flags &= ~MEM_Ephem;
- pDest->flags |= MEM_Dyn|MEM_Term;
- }
-
- /* pDest->z might be pointing to sMem.zShort[]. Fix that so that we
- ** can abandon sMem */
+ if( sMem.zMalloc ){
+ assert( sMem.z==sMem.zMalloc );
+ assert( !(pDest->flags & MEM_Dyn) );
+ assert( !(pDest->flags & (MEM_Blob|MEM_Str)) || pDest->z==sMem.z );
+ pDest->flags &= ~(MEM_Ephem|MEM_Static);
+ pDest->flags |= MEM_Term;
+ pDest->z = sMem.z;
+ pDest->zMalloc = sMem.zMalloc;
+ }
+
rc = sqlite3VdbeMemMakeWriteable(pDest);
op_column_out:
UPDATE_MAX_BLOBSIZE(pDest);
@@ -41011,19 +44106,39 @@
REGISTER_TRACE(pOp->p3, pDest);
break;
}
+/* Opcode: Affinity P1 P2 * P4 *
+**
+** Apply affinities to a range of P2 registers starting with P1.
+**
+** P4 is a string that is P2 characters long. The nth character of the
+** string indicates the column affinity that should be used for the nth
+** memory cell in the range.
+*/
+case OP_Affinity: {
+ char *zAffinity = pOp->p4.z;
+ Mem *pData0 = &p->aMem[pOp->p1];
+ Mem *pLast = &pData0[pOp->p2-1];
+ Mem *pRec;
+
+ for(pRec=pData0; pRec<=pLast; pRec++){
+ ExpandBlob(pRec);
+ applyAffinity(pRec, zAffinity[pRec-pData0], encoding);
+ }
+ break;
+}
+
/* Opcode: MakeRecord P1 P2 P3 P4 *
**
** Convert P2 registers beginning with P1 into a single entry
** suitable for use as a data record in a database table or as a key
** in an index. The details of the format are irrelavant as long as
-** the OP_Column opcode can decode the record later and as long as the
-** sqlite3VdbeRecordCompare function will correctly compare two encoded
-** records. Refer to source code comments for the details of the record
+** the OP_Column opcode can decode the record later.
+** Refer to source code comments for the details of the record
** format.
**
-** P4 may be a string that is P1 characters long. The nth character of the
+** P4 may be a string that is P2 characters long. The nth character of the
** string indicates the column affinity that should be used for the nth
** field of the index key.
**
** The mapping from character to affinity is given by the SQLITE_AFF_
@@ -41060,9 +44175,8 @@
int nField; /* Number of fields in the record */
char *zAffinity; /* The affinity string for the record */
int file_format; /* File format to use for encoding */
int i; /* Space used in zNewRecord[] */
- char zTemp[NBFS]; /* Space to hold small records */
nField = pOp->p1;
zAffinity = pOp->p4.z;
assert( nField>0 && pOp->p2>0 && pOp->p2+nField<=p->nMem );
@@ -41100,48 +44214,39 @@
if( nVarint<sqlite3VarintLen(nHdr) ){
nHdr++;
}
nByte = nHdr+nData-nZero;
- if( nByte>SQLITE_MAX_LENGTH ){
+ if( nByte>db->aLimit[SQLITE_LIMIT_LENGTH] ){
goto too_big;
}
- /* Allocate space for the new record. */
- if( nByte>sizeof(zTemp) ){
- zNewRecord = sqlite3DbMallocRaw(db, nByte);
- if( !zNewRecord ){
- goto no_mem;
- }
- }else{
- zNewRecord = (u8*)zTemp;
- }
+ /* Make sure the output register has a buffer large enough to store
+ ** the new record. The output register (pOp->p3) is not allowed to
+ ** be one of the input registers (because the following call to
+ ** sqlite3VdbeMemGrow() could clobber the value before it is used).
+ */
+ assert( pOp->p3<pOp->p1 || pOp->p3>=pOp->p1+pOp->p2 );
+ pOut = &p->aMem[pOp->p3];
+ if( sqlite3VdbeMemGrow(pOut, nByte, 0) ){
+ goto no_mem;
+ }
+ zNewRecord = (u8 *)pOut->z;
/* Write the record */
- i = sqlite3PutVarint(zNewRecord, nHdr);
+ i = putVarint32(zNewRecord, nHdr);
for(pRec=pData0; pRec<=pLast; pRec++){
serial_type = sqlite3VdbeSerialType(pRec, file_format);
- i += sqlite3PutVarint(&zNewRecord[i], serial_type); /* serial type */
+ i += putVarint32(&zNewRecord[i], serial_type); /* serial type */
}
for(pRec=pData0; pRec<=pLast; pRec++){ /* serial data */
i += sqlite3VdbeSerialPut(&zNewRecord[i], nByte-i, pRec, file_format);
}
assert( i==nByte );
assert( pOp->p3>0 && pOp->p3<=p->nMem );
- pOut = &p->aMem[pOp->p3];
- Release(pOut);
pOut->n = nByte;
- if( nByte<=sizeof(zTemp) ){
- assert( zNewRecord==(unsigned char *)zTemp );
- pOut->z = pOut->zShort;
- memcpy(pOut->zShort, zTemp, nByte);
- pOut->flags = MEM_Blob | MEM_Short;
- }else{
- assert( zNewRecord!=(unsigned char *)zTemp );
- pOut->z = (char*)zNewRecord;
- pOut->flags = MEM_Blob | MEM_Dyn;
- pOut->xDel = 0;
- }
+ pOut->flags = MEM_Blob | MEM_Dyn;
+ pOut->xDel = 0;
if( nZero ){
pOut->u.i = nZero;
pOut->flags |= MEM_Zero;
}
@@ -41153,12 +44258,22 @@
/* Opcode: Statement P1 * * * *
**
** Begin an individual statement transaction which is part of a larger
-** BEGIN..COMMIT transaction. This is needed so that the statement
+** transaction. This is needed so that the statement
** can be rolled back after an error without having to roll back the
** entire transaction. The statement transaction will automatically
** commit when the VDBE halts.
+**
+** If the database connection is currently in autocommit mode (that
+** is to say, if it is in between BEGIN and COMMIT)
+** and if there are no other active statements on the same database
+** connection, then this operation is a no-op. No statement transaction
+** is needed since any error can use the normal ROLLBACK process to
+** undo changes.
+**
+** If a statement transaction is started, then a statement journal file
+** will be allocated and initialized.
**
** The statement is begun on the database file with index P1. The main
** database file has an index of 0 and the file used for temporary tables
** has an index of 1.
@@ -41317,9 +44432,9 @@
** by one in the following statement.
*/
rc = sqlite3BtreeGetMeta(db->aDb[iDb].pBt, 1 + iCookie, (u32 *)&iMeta);
pOut->u.i = iMeta;
- pOut->flags = MEM_Int;
+ MemSetTypeFlag(pOut, MEM_Int);
break;
}
/* Opcode: SetCookie P1 P2 P3 * *
@@ -41488,16 +44603,12 @@
p2 = pIn2->u.i;
assert( p2>=2 );
}
assert( i>=0 );
- pCur = allocateCursor(p, i, iDb);
+ pCur = allocateCursor(p, i, &pOp[-1], iDb, 1);
if( pCur==0 ) goto no_mem;
pCur->nullRow = 1;
- /* We always provide a key comparison function. If the table being
- ** opened is of type INTKEY, the comparision function will be ignored. */
- rc = sqlite3BtreeCursor(pX, p2, wrFlag,
- sqlite3VdbeRecordCompare, pOp->p4.p,
- &pCur->pCursor);
+ rc = sqlite3BtreeCursor(pX, p2, wrFlag, pOp->p4.p, pCur->pCursor);
if( pOp->p4type==P4_KEYINFO ){
pCur->pKeyInfo = pOp->p4.pKeyInfo;
pCur->pIncrKey = &pCur->pKeyInfo->incrKey;
pCur->pKeyInfo->enc = ENC(p->db);
@@ -41538,8 +44649,9 @@
}
case SQLITE_EMPTY: {
pCur->isTable = pOp->p4type!=P4_KEYINFO;
pCur->isIndex = !pCur->isTable;
+ pCur->pCursor = 0;
rc = SQLITE_OK;
break;
}
default: {
@@ -41577,9 +44689,9 @@
SQLITE_OPEN_DELETEONCLOSE |
SQLITE_OPEN_TRANSIENT_DB;
assert( i>=0 );
- pCx = allocateCursor(p, i, -1);
+ pCx = allocateCursor(p, i, pOp, -1, 1);
if( pCx==0 ) goto no_mem;
pCx->nullRow = 1;
rc = sqlite3BtreeFactory(db, 0, 1, SQLITE_DEFAULT_TEMP_CACHE_SIZE, openFlags,
&pCx->pBt);
@@ -41597,27 +44709,26 @@
assert( pOp->p4type==P4_KEYINFO );
rc = sqlite3BtreeCreateTable(pCx->pBt, &pgno, BTREE_ZERODATA);
if( rc==SQLITE_OK ){
assert( pgno==MASTER_ROOT+1 );
- rc = sqlite3BtreeCursor(pCx->pBt, pgno, 1, sqlite3VdbeRecordCompare,
- pOp->p4.z, &pCx->pCursor);
+ rc = sqlite3BtreeCursor(pCx->pBt, pgno, 1,
+ (KeyInfo*)pOp->p4.z, pCx->pCursor);
pCx->pKeyInfo = pOp->p4.pKeyInfo;
pCx->pKeyInfo->enc = ENC(p->db);
pCx->pIncrKey = &pCx->pKeyInfo->incrKey;
}
pCx->isTable = 0;
}else{
- rc = sqlite3BtreeCursor(pCx->pBt, MASTER_ROOT, 1, 0, 0, &pCx->pCursor);
+ rc = sqlite3BtreeCursor(pCx->pBt, MASTER_ROOT, 1, 0, pCx->pCursor);
pCx->isTable = 1;
pCx->pIncrKey = &pCx->bogusIncrKey;
}
}
- pCx->nField = pOp->p2;
pCx->isIndex = !pCx->isTable;
break;
}
-/* Opcode: OpenPseudo P1 * * * *
+/* Opcode: OpenPseudo P1 P2 * * *
**
** Open a new cursor that points to a fake table that contains a single
** row of data. Any attempt to write a second row of data causes the
** first row to be deleted. All data is deleted when the cursor is
@@ -41626,17 +44737,26 @@
** A pseudo-table created by this opcode is useful for holding the
** NEW or OLD tables in a trigger. Also used to hold the a single
** row output from the sorter so that the row can be decomposed into
** individual columns using the OP_Column opcode.
+**
+** When OP_Insert is executed to insert a row in to the pseudo table,
+** the pseudo-table cursor may or may not make it's own copy of the
+** original row data. If P2 is 0, then the pseudo-table will copy the
+** original row data. Otherwise, a pointer to the original memory cell
+** is stored. In this case, the vdbe program must ensure that the
+** memory cell containing the row data is not overwritten until the
+** pseudo table is closed (or a new row is inserted into it).
*/
case OP_OpenPseudo: {
int i = pOp->p1;
Cursor *pCx;
assert( i>=0 );
- pCx = allocateCursor(p, i, -1);
+ pCx = allocateCursor(p, i, &pOp[-1], -1, 0);
if( pCx==0 ) goto no_mem;
pCx->nullRow = 1;
pCx->pseudoTable = 1;
+ pCx->ephemPseudoTable = pOp->p2;
pCx->pIncrKey = &pCx->bogusIncrKey;
pCx->isTable = 1;
pCx->isIndex = 0;
break;
@@ -41654,15 +44774,18 @@
p->apCsr[i] = 0;
break;
}
-/* Opcode: MoveGe P1 P2 P3 * *
-**
-** Use the value in register P3 as a key. Reposition
-** cursor P1 so that it points to the smallest entry that is greater
-** than or equal to the key in register P3.
-** If there are no records greater than or equal to the key and P2
-** is not zero, then jump to P2.
+/* Opcode: MoveGe P1 P2 P3 P4 *
+**
+** If cursor P1 refers to an SQL table (B-Tree that uses integer keys),
+** use the integer value in register P3 as a key. If cursor P1 refers
+** to an SQL index, then P3 is the first in an array of P4 registers
+** that are used as an unpacked index key.
+**
+** Reposition cursor P1 so that it points to the smallest entry that
+** is greater than or equal to the key value. If there are no records
+** greater than or equal to the key and P2 is not zero, then jump to P2.
**
** A special feature of this opcode (and different from the
** related OP_MoveGt, OP_MoveLt, and OP_MoveLe) is that if P2 is
** zero and P1 is an SQL table (a b-tree with integer keys) then
@@ -41671,35 +44794,44 @@
** seek, we avoid unnecessary seeks.
**
** See also: Found, NotFound, Distinct, MoveLt, MoveGt, MoveLe
*/
-/* Opcode: MoveGt P1 P2 P3 * *
-**
-** Use the value in register P3 as a key. Reposition
-** cursor P1 so that it points to the smallest entry that is greater
-** than the key in register P3.
-** If there are no records greater than the key
-** then jump to P2.
+/* Opcode: MoveGt P1 P2 P3 P4 *
+**
+** If cursor P1 refers to an SQL table (B-Tree that uses integer keys),
+** use the integer value in register P3 as a key. If cursor P1 refers
+** to an SQL index, then P3 is the first in an array of P4 registers
+** that are used as an unpacked index key.
+**
+** Reposition cursor P1 so that it points to the smallest entry that
+** is greater than the key value. If there are no records greater than
+** the key and P2 is not zero, then jump to P2.
**
** See also: Found, NotFound, Distinct, MoveLt, MoveGe, MoveLe
*/
-/* Opcode: MoveLt P1 P2 P3 * *
-**
-** Use the value in register P3 as a key. Reposition
-** cursor P1 so that it points to the largest entry that is less
-** than the key in register P3.
-** If there are no records less than the key
-** then jump to P2.
+/* Opcode: MoveLt P1 P2 P3 P4 *
+**
+** If cursor P1 refers to an SQL table (B-Tree that uses integer keys),
+** use the integer value in register P3 as a key. If cursor P1 refers
+** to an SQL index, then P3 is the first in an array of P4 registers
+** that are used as an unpacked index key.
+**
+** Reposition cursor P1 so that it points to the largest entry that
+** is less than the key value. If there are no records less than
+** the key and P2 is not zero, then jump to P2.
**
** See also: Found, NotFound, Distinct, MoveGt, MoveGe, MoveLe
*/
-/* Opcode: MoveLe P1 P2 P3 * *
-**
-** Use the value in register P3 as a key. Reposition
-** cursor P1 so that it points to the largest entry that is less than
-** or equal to the key.
-** If there are no records less than or eqal to the key
-** then jump to P2.
+/* Opcode: MoveLe P1 P2 P3 P4 *
+**
+** If cursor P1 refers to an SQL table (B-Tree that uses integer keys),
+** use the integer value in register P3 as a key. If cursor P1 refers
+** to an SQL index, then P3 is the first in an array of P4 registers
+** that are used as an unpacked index key.
+**
+** Reposition cursor P1 so that it points to the largest entry that
+** is less than or equal to the key value. If there are no records
+** less than or equal to the key and P2 is not zero, then jump to P2.
**
** See also: Found, NotFound, Distinct, MoveGt, MoveGe, MoveLt
*/
case OP_MoveLt: /* jump, in3 */
@@ -41725,18 +44857,25 @@
pC->rowidIsValid = 0;
pC->deferredMoveto = 1;
break;
}
- rc = sqlite3BtreeMoveto(pC->pCursor, 0, (u64)iKey, 0, &res);
+ rc = sqlite3BtreeMoveto(pC->pCursor, 0, 0, (u64)iKey, 0, &res);
if( rc!=SQLITE_OK ){
goto abort_due_to_error;
}
pC->lastRowid = iKey;
pC->rowidIsValid = res==0;
}else{
- assert( pIn3->flags & MEM_Blob );
- ExpandBlob(pIn3);
- rc = sqlite3BtreeMoveto(pC->pCursor, pIn3->z, pIn3->n, 0, &res);
+ UnpackedRecord r;
+ int nField = pOp->p4.i;
+ assert( pOp->p4type==P4_INT32 );
+ assert( nField>0 );
+ r.pKeyInfo = pC->pKeyInfo;
+ r.nField = nField;
+ r.needFree = 0;
+ r.needDestroy = 0;
+ r.aMem = &p->aMem[pOp->p3];
+ rc = sqlite3BtreeMoveto(pC->pCursor, 0, &r, 0, 0, &res);
if( rc!=SQLITE_OK ){
goto abort_due_to_error;
}
pC->rowidIsValid = 0;
@@ -41819,9 +44958,9 @@
assert( pIn3->flags & MEM_Blob );
if( pOp->opcode==OP_Found ){
pC->pKeyInfo->prefixIsEqual = 1;
}
- rc = sqlite3BtreeMoveto(pC->pCursor, pIn3->z, pIn3->n, 0, &res);
+ rc = sqlite3BtreeMoveto(pC->pCursor, pIn3->z, 0, pIn3->n, 0, &res);
pC->pKeyInfo->prefixIsEqual = 0;
if( rc!=SQLITE_OK ){
break;
}
@@ -41870,9 +45009,8 @@
assert( pOp->p4.i>0 && pOp->p4.i<=p->nMem );
pK = &p->aMem[pOp->p4.i];
sqlite3VdbeMemIntegerify(pIn3);
R = pIn3->u.i;
- assert( (pIn3->flags & MEM_Dyn)==0 );
assert( i>=0 && i<p->nCursor );
pCx = p->apCsr[i];
assert( pCx!=0 );
pCrsr = pCx->pCursor;
@@ -41897,9 +45035,9 @@
** If there is no such entry, jump immediately to P2.
*/
assert( pCx->deferredMoveto==0 );
pCx->cacheStatus = CACHE_STALE;
- rc = sqlite3BtreeMoveto(pCrsr, zKey, len, 0, &res);
+ rc = sqlite3BtreeMoveto(pCrsr, zKey, 0, len, 0, &res);
if( rc!=SQLITE_OK ){
goto abort_due_to_error;
}
if( res<0 ){
@@ -41908,9 +45046,9 @@
pc = pOp->p2 - 1;
break;
}
}
- rc = sqlite3VdbeIdxKeyCompare(pCx, len, (u8*)zKey, &res);
+ rc = sqlite3VdbeIdxKeyCompare(pCx, 0, len, (u8*)zKey, &res);
if( rc!=SQLITE_OK ) goto abort_due_to_error;
if( res>0 ){
pc = pOp->p2 - 1;
break;
@@ -41934,9 +45072,9 @@
** into register R3. (The record number of an entry that violates
** a UNIQUE constraint.)
*/
pIn3->u.i = v;
- assert( pIn3->flags==MEM_Int );
+ assert( pIn3->flags&MEM_Int );
}
break;
}
@@ -41965,9 +45103,9 @@
u64 iKey;
assert( pIn3->flags & MEM_Int );
assert( p->apCsr[i]->isTable );
iKey = intToKey(pIn3->u.i);
- rc = sqlite3BtreeMoveto(pCrsr, 0, iKey, 0,&res);
+ rc = sqlite3BtreeMoveto(pCrsr, 0, 0, iKey, 0,&res);
pC->lastRowid = pIn3->u.i;
pC->rowidIsValid = res==0;
pC->nullRow = 0;
pC->cacheStatus = CACHE_STALE;
@@ -41995,9 +45133,9 @@
int i = pOp->p1;
assert( i>=0 && i<p->nCursor );
assert( p->apCsr[i]!=0 );
pOut->u.i = p->apCsr[i]->seqCount++;
- pOut->flags = MEM_Int;
+ MemSetTypeFlag(pOut, MEM_Int);
break;
}
@@ -42130,14 +45268,14 @@
do{
if( cnt==0 && (v&0xffffff)==v ){
v++;
}else{
- sqlite3Randomness(sizeof(v), &v);
+ sqlite3_randomness(sizeof(v), &v);
if( cnt<5 ) v &= 0xffffff;
}
if( v==0 ) continue;
x = intToKey(v);
- rx = sqlite3BtreeMoveto(pC->pCursor, 0, (u64)x, 0, &res);
+ rx = sqlite3BtreeMoveto(pC->pCursor, 0, 0, (u64)x, 0, &res);
cnt++;
}while( cnt<100 && rx==SQLITE_OK && res==0 );
db->priorNewRowid = v;
if( rx==SQLITE_OK && res==0 ){
@@ -42148,9 +45286,9 @@
pC->rowidIsValid = 0;
pC->deferredMoveto = 0;
pC->cacheStatus = CACHE_STALE;
}
- pOut->flags = MEM_Int;
+ MemSetTypeFlag(pOut, MEM_Int);
pOut->u.i = v;
break;
}
@@ -42208,15 +45346,20 @@
}else{
assert( pData->flags & (MEM_Blob|MEM_Str) );
}
if( pC->pseudoTable ){
- sqlite3_free(pC->pData);
+ if( !pC->ephemPseudoTable ){
+ sqlite3_free(pC->pData);
+ }
pC->iKey = iKey;
pC->nData = pData->n;
- if( pData->flags & MEM_Dyn ){
+ if( pData->z==pData->zMalloc || pC->ephemPseudoTable ){
pC->pData = pData->z;
- pData->flags &= ~MEM_Dyn;
- pData->flags |= MEM_Ephem;
+ if( !pC->ephemPseudoTable ){
+ pData->flags &= ~MEM_Dyn;
+ pData->flags |= MEM_Ephem;
+ pData->zMalloc = 0;
+ }
}else{
pC->pData = sqlite3_malloc( pC->nData+2 );
if( !pC->pData ) goto no_mem;
memcpy(pC->pData, pData->z, pC->nData);
@@ -42342,14 +45485,16 @@
**
** If the P1 cursor must be pointing to a valid row (not a NULL row)
** of a real table, not a pseudo-table.
*/
-case OP_RowKey: /* out2-prerelease */
-case OP_RowData: { /* out2-prerelease */
+case OP_RowKey:
+case OP_RowData: {
int i = pOp->p1;
Cursor *pC;
BtCursor *pCrsr;
u32 n;
+
+ pOut = &p->aMem[pOp->p2];
/* Note that RowKey and RowData are really exactly the same instruction */
assert( i>=0 && i<p->nCursor );
pC = p->apCsr[i];
@@ -42365,29 +45510,23 @@
if( pC->isIndex ){
i64 n64;
assert( !pC->isTable );
sqlite3BtreeKeySize(pCrsr, &n64);
- if( n64>SQLITE_MAX_LENGTH ){
+ if( n64>db->aLimit[SQLITE_LIMIT_LENGTH] ){
goto too_big;
}
n = n64;
}else{
sqlite3BtreeDataSize(pCrsr, &n);
- if( n>SQLITE_MAX_LENGTH ){
+ if( n>db->aLimit[SQLITE_LIMIT_LENGTH] ){
goto too_big;
}
}
+ if( sqlite3VdbeMemGrow(pOut, n, 0) ){
+ goto no_mem;
+ }
pOut->n = n;
- if( n<=NBFS ){
- pOut->flags = MEM_Blob | MEM_Short;
- pOut->z = pOut->zShort;
- }else{
- char *z = sqlite3_malloc( n );
- if( z==0 ) goto no_mem;
- pOut->flags = MEM_Blob | MEM_Dyn;
- pOut->xDel = 0;
- pOut->z = z;
- }
+ MemSetTypeFlag(pOut, MEM_Blob);
if( pC->isIndex ){
rc = sqlite3BtreeKey(pCrsr, 0, n, pOut->z);
}else{
rc = sqlite3BtreeData(pCrsr, 0, n, pOut->z);
@@ -42424,9 +45563,9 @@
sqlite3BtreeKeySize(pC->pCursor, &v);
v = keyToInt(v);
}
pOut->u.i = v;
- pOut->flags = MEM_Int;
+ MemSetTypeFlag(pOut, MEM_Int);
break;
}
/* Opcode: NullRow P1 * * * *
@@ -42552,9 +45691,8 @@
case OP_Prev: /* jump */
case OP_Next: { /* jump */
Cursor *pC;
BtCursor *pCrsr;
- int res;
CHECK_FOR_INTERRUPT;
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
pC = p->apCsr[pOp->p1];
@@ -42562,11 +45700,10 @@
break; /* See ticket #2273 */
}
pCrsr = pC->pCursor;
assert( pCrsr );
- if( pC->nullRow ){
- res = 1;
- }else{
+ if( pC->nullRow==0 ){
+ int res = 1;
assert( pC->deferredMoveto==0 );
rc = pOp->opcode==OP_Next ? sqlite3BtreeNext(pCrsr, &res) :
sqlite3BtreePrevious(pCrsr, &res);
pC->nullRow = res;
@@ -42614,23 +45751,31 @@
}
break;
}
-/* Opcode: IdxDelete P1 P2 * * *
-**
-** The content of register P2 is an index key built using the either the
-** MakeIdxRec opcode. Removes that entry from the index.
-*/
-case OP_IdxDelete: { /* in2 */
+/* Opcode: IdxDeleteM P1 P2 P3 * *
+**
+** The content of P3 registers starting at register P2 form
+** an unpacked index key. This opcode removes that entry from the
+** index opened by cursor P1.
+*/
+case OP_IdxDelete: {
int i = pOp->p1;
Cursor *pC;
BtCursor *pCrsr;
- assert( pIn2->flags & MEM_Blob );
+ assert( pOp->p3>0 );
+ assert( pOp->p2>0 && pOp->p2+pOp->p3<=p->nMem );
assert( i>=0 && i<p->nCursor );
assert( p->apCsr[i]!=0 );
if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){
int res;
- rc = sqlite3BtreeMoveto(pCrsr, pIn2->z, pIn2->n, 0, &res);
+ UnpackedRecord r;
+ r.pKeyInfo = pC->pKeyInfo;
+ r.nField = pOp->p3;
+ r.needFree = 0;
+ r.needDestroy = 0;
+ r.aMem = &p->aMem[pOp->p2];
+ rc = sqlite3BtreeMoveto(pCrsr, 0, &r, 0, 0, &res);
if( rc==SQLITE_OK && res==0 ){
rc = sqlite3BtreeDelete(pCrsr);
}
assert( pC->deferredMoveto==0 );
@@ -42663,44 +45808,40 @@
rc = sqlite3VdbeIdxRowid(pCrsr, &rowid);
if( rc!=SQLITE_OK ){
goto abort_due_to_error;
}
- pOut->flags = MEM_Int;
+ MemSetTypeFlag(pOut, MEM_Int);
pOut->u.i = rowid;
}
}
break;
}
-/* Opcode: IdxGE P1 P2 P3 * P5
-**
-** The value in register P3 is an index entry that omits the ROWID. Compare
-** this value against the index that P1 is currently pointing to.
-** Ignore the ROWID on the P1 index.
-**
-** If the P1 index entry is greater than or equal to the value in
-** register P3 then jump to P2. Otherwise fall through to the next
-** instruction.
-**
-** If P5 is non-zero then the value in register P3 is temporarily
-** increased by an epsilon prior to the comparison. This make the opcode work
-** like IdxGT except that if the key from register P3 is a prefix of
-** the key in the cursor, the result is false whereas it would be
-** true with IdxGT.
+/* Opcode: IdxGE P1 P2 P3 P4 P5
+**
+** The P4 register values beginning with P3 form an unpacked index
+** key that omits the ROWID. Compare this key value against the index
+** that P1 is currently pointing to, ignoring the ROWID on the P1 index.
+**
+** If the P1 index entry is greater than or equal to the key value
+** then jump to P2. Otherwise fall through to the next instruction.
+**
+** If P5 is non-zero then the key value is increased by an epsilon
+** prior to the comparison. This make the opcode work like IdxGT except
+** that if the key from register P3 is a prefix of the key in the cursor,
+** the result is false whereas it would be true with IdxGT.
*/
/* Opcode: IdxLT P1 P2 P3 * P5
**
-** The value in register P3 is an index entry that omits the ROWID. Compare
-** the this value against the index that P1 is currently pointing to.
-** Ignore the ROWID on the P1 index.
-**
-** If the P1 index entry is less than the register P3 value
-** then jump to P2. Otherwise fall through to the next instruction.
-**
-** If P5 is non-zero then the
-** index taken from register P3 is temporarily increased by
-** an epsilon prior to the comparison. This makes the opcode work
-** like IdxLE.
+** The P4 register values beginning with P3 form an unpacked index
+** key that omits the ROWID. Compare this key value against the index
+** that P1 is currently pointing to, ignoring the ROWID on the P1 index.
+**
+** If the P1 index entry is less than the key value then jump to P2.
+** Otherwise fall through to the next instruction.
+**
+** If P5 is non-zero then the key value is increased by an epsilon prior
+** to the comparison. This makes the opcode work like IdxLE.
*/
case OP_IdxLT: /* jump, in3 */
case OP_IdxGE: { /* jump, in3 */
int i= pOp->p1;
@@ -42709,19 +45850,20 @@
assert( i>=0 && i<p->nCursor );
assert( p->apCsr[i]!=0 );
if( (pC = p->apCsr[i])->pCursor!=0 ){
int res;
-
- assert( pIn3->flags & MEM_Blob ); /* Created using OP_MakeRecord */
- assert( pC->deferredMoveto==0 );
- ExpandBlob(pIn3);
+ UnpackedRecord r;
+ assert( pC->deferredMoveto==0 );
assert( pOp->p5==0 || pOp->p5==1 );
+ assert( pOp->p4type==P4_INT32 );
+ r.pKeyInfo = pC->pKeyInfo;
+ r.nField = pOp->p4.i;
+ r.needFree = 0;
+ r.needDestroy = 0;
+ r.aMem = &p->aMem[pOp->p3];
*pC->pIncrKey = pOp->p5;
- rc = sqlite3VdbeIdxKeyCompare(pC, pIn3->n, (u8*)pIn3->z, &res);
- *pC->pIncrKey = 0;
- if( rc!=SQLITE_OK ){
- break;
- }
+ rc = sqlite3VdbeIdxKeyCompare(pC, &r, 0, 0, &res);
+ *pC->pIncrKey = 0;
if( pOp->opcode==OP_IdxLT ){
res = -res;
}else{
assert( pOp->opcode==OP_IdxGE );
@@ -42775,9 +45917,9 @@
int iDb = pOp->p3;
assert( iCnt==1 );
assert( (p->btreeMask & (1<<iDb))!=0 );
rc = sqlite3BtreeDropTable(db->aDb[iDb].pBt, pOp->p1, &iMoved);
- pOut->flags = MEM_Int;
+ MemSetTypeFlag(pOut, MEM_Int);
pOut->u.i = iMoved;
#ifndef SQLITE_OMIT_AUTOVACUUM
if( rc==SQLITE_OK && iMoved!=0 ){
sqlite3RootPageMoved(&db->aDb[iDb], iMoved, pOp->p1);
@@ -42844,9 +45986,9 @@
}
rc = sqlite3BtreeCreateTable(pDb->pBt, &pgno, flags);
if( rc==SQLITE_OK ){
pOut->u.i = pgno;
- pOut->flags = MEM_Int;
+ MemSetTypeFlag(pOut, MEM_Int);
}
break;
}
@@ -42997,14 +46139,10 @@
sqlite3VdbeMemSetNull(pIn1);
if( nErr==0 ){
assert( z==0 );
}else{
- pIn1->z = z;
- pIn1->n = strlen(z);
- pIn1->flags = MEM_Str | MEM_Dyn | MEM_Term;
- pIn1->xDel = 0;
- }
- pIn1->enc = SQLITE_UTF8;
+ sqlite3VdbeMemSetStr(pIn1, z, -1, SQLITE_UTF8, sqlite3_free);
+ }
UPDATE_MAX_BLOBSIZE(pIn1);
sqlite3VdbeChangeEncoding(pIn1, encoding);
sqlite3_free(aRoot);
break;
@@ -43032,10 +46170,9 @@
case OP_FifoRead: { /* jump */
CHECK_FOR_INTERRUPT;
assert( pOp->p1>0 && pOp->p1<=p->nMem );
pOut = &p->aMem[pOp->p1];
- Release(pOut);
- pOut->flags = MEM_Int;
+ MemSetTypeFlag(pOut, MEM_Int);
if( sqlite3VdbeFifoPop(&p->sFifo, &pOut->u.i)==SQLITE_DONE ){
pc = pOp->p2 - 1;
}
break;
@@ -43111,9 +46248,9 @@
** It is illegal to use this instruction on a register that does
** not contain an integer. An assertion fault will result if you try.
*/
case OP_IfPos: { /* jump, in1 */
- assert( pIn1->flags==MEM_Int );
+ assert( pIn1->flags&MEM_Int );
if( pIn1->u.i>0 ){
pc = pOp->p2 - 1;
}
break;
@@ -43126,9 +46263,9 @@
** It is illegal to use this instruction on a register that does
** not contain an integer. An assertion fault will result if you try.
*/
case OP_IfNeg: { /* jump, in1 */
- assert( pIn1->flags==MEM_Int );
+ assert( pIn1->flags&MEM_Int );
if( pIn1->u.i<0 ){
pc = pOp->p2 - 1;
}
break;
@@ -43141,9 +46278,9 @@
** It is illegal to use this instruction on a register that does
** not contain an integer. An assertion fault will result if you try.
*/
case OP_IfZero: { /* jump, in1 */
- assert( pIn1->flags==MEM_Int );
+ assert( pIn1->flags&MEM_Int );
if( pIn1->u.i==0 ){
pc = pOp->p2 - 1;
}
break;
@@ -43179,8 +46316,9 @@
ctx.pMem = pMem = &p->aMem[pOp->p3];
pMem->n++;
ctx.s.flags = MEM_Null;
ctx.s.z = 0;
+ ctx.s.zMalloc = 0;
ctx.s.xDel = 0;
ctx.s.db = db;
ctx.isError = 0;
ctx.pColl = 0;
@@ -43192,9 +46330,9 @@
}
(ctx.pFunc->xStep)(&ctx, n, apVal);
if( ctx.isError ){
sqlite3SetString(&p->zErrMsg, sqlite3_value_text(&ctx.s), (char*)0);
- rc = SQLITE_ERROR;
+ rc = ctx.isError;
}
sqlite3VdbeMemRelease(&ctx.s);
break;
}
@@ -43219,8 +46357,9 @@
rc = sqlite3VdbeMemFinalize(pMem, pOp->p4.pFunc);
if( rc==SQLITE_ERROR ){
sqlite3SetString(&p->zErrMsg, sqlite3_value_text(pMem), (char*)0);
}
+ sqlite3VdbeChangeEncoding(pMem, encoding);
UPDATE_MAX_BLOBSIZE(pMem);
if( sqlite3VdbeMemTooBig(pMem) ){
goto too_big;
}
@@ -43283,18 +46422,16 @@
break;
}
#ifndef SQLITE_OMIT_SHARED_CACHE
-/* Opcode: TableLock P1 P2 * P4 *
+/* Opcode: TableLock P1 P2 P3 P4 *
**
** Obtain a lock on a particular table. This instruction is only used when
** the shared-cache feature is enabled.
**
-** If P1 is not negative, then it is the index of the database
-** in sqlite3.aDb[] and a read-lock is required. If P1 is negative, a
-** write-lock is required. In this case the index of the database is the
-** absolute value of P1 minus one (iDb = abs(P1) - 1;) and a write-lock is
-** required.
+** If P1 is the index of the database in sqlite3.aDb[] of the database
+** on which the lock is acquired. A readlock is obtained if P3==0 or
+** a write lock if P3==1.
**
** P2 contains the root-page of the table to lock.
**
** P4 contains a pointer to the name of the table being locked. This is only
@@ -43301,14 +46438,12 @@
** used to generate an error message if the lock cannot be obtained.
*/
case OP_TableLock: {
int p1 = pOp->p1;
- u8 isWriteLock = (p1<0);
- if( isWriteLock ){
- p1 = (-1*p1)-1;
- }
+ u8 isWriteLock = pOp->p3;
assert( p1>=0 && p1<db->nDb );
assert( (p->btreeMask & (1<<p1))!=0 );
+ assert( isWriteLock==0 || isWriteLock==1 );
rc = sqlite3BtreeLockTable(db->aDb[p1].pBt, pOp->p2, isWriteLock);
if( rc==SQLITE_LOCKED ){
const char *z = pOp->p4.z;
sqlite3SetString(&p->zErrMsg, "database table is locked: ", z, (char*)0);
@@ -43377,9 +46512,9 @@
/* Initialise sqlite3_vtab_cursor base class */
pVtabCursor->pVtab = pVtab;
/* Initialise vdbe cursor object */
- pCur = allocateCursor(p, pOp->p1, -1);
+ pCur = allocateCursor(p, pOp->p1, &pOp[-1], -1, 0);
if( pCur ){
pCur->pVtabCursor = pVtabCursor;
pCur->pModule = pVtabCursor->pVtab->pModule;
}else{
@@ -43476,9 +46611,9 @@
assert( pModule->xRowid );
if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
rc = pModule->xRowid(pCur->pVtabCursor, &iRow);
if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
- pOut->flags = MEM_Int;
+ MemSetTypeFlag(pOut, MEM_Int);
pOut->u.i = iRow;
break;
}
#endif /* SQLITE_OMIT_VIRTUALTABLE */
@@ -43505,10 +46640,17 @@
}
pModule = pCur->pVtabCursor->pVtab->pModule;
assert( pModule->xColumn );
memset(&sContext, 0, sizeof(sContext));
- sContext.s.flags = MEM_Null;
- sContext.s.db = db;
+
+ /* The output cell may already have a buffer allocated. Move
+ ** the current contents to sContext.s so in case the user-function
+ ** can use the already allocated buffer instead of allocating a
+ ** new one.
+ */
+ sqlite3VdbeMemMove(&sContext.s, pDest);
+ MemSetTypeFlag(&sContext.s, MEM_Null);
+
if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
rc = pModule->xColumn(pCur->pVtabCursor, &sContext, pOp->p2);
/* Copy the result of the function to the P3 register. We
@@ -43647,8 +46789,9 @@
if( pOp->p1 && rc==SQLITE_OK ){
assert( nArg>1 && apArg[0] && (apArg[0]->flags&MEM_Null) );
db->lastRowid = rowid;
}
+ p->nChange++;
}
break;
}
#endif /* SQLITE_OMIT_VIRTUALTABLE */
@@ -43805,9 +46948,9 @@
*************************************************************************
**
** This file contains code used to implement incremental BLOB I/O.
**
-** $Id: vdbeblob.c,v 1.20 2008/01/25 15:04:50 drh Exp $
+** $Id: vdbeblob.c,v 1.22 2008/04/24 09:49:55 danielk1977 Exp $
*/
#ifndef SQLITE_OMIT_INCRBLOB
@@ -43861,18 +47004,19 @@
/* One of the following two instructions is replaced by an
** OP_Noop before exection.
*/
- {OP_OpenRead, 0, 0, 0}, /* 2: Open cursor 0 for reading */
- {OP_OpenWrite, 0, 0, 0}, /* 3: Open cursor 0 for read/write */
+ {OP_SetNumColumns, 0, 0, 0}, /* 2: Num cols for cursor */
+ {OP_OpenRead, 0, 0, 0}, /* 3: Open cursor 0 for reading */
{OP_SetNumColumns, 0, 0, 0}, /* 4: Num cols for cursor */
-
- {OP_Variable, 1, 1, 0}, /* 5: Push the rowid to the stack */
- {OP_NotExists, 0, 10, 1}, /* 6: Seek the cursor */
- {OP_Column, 0, 0, 1}, /* 7 */
- {OP_ResultRow, 1, 0, 0}, /* 8 */
- {OP_Close, 0, 0, 0}, /* 9 */
- {OP_Halt, 0, 0, 0}, /* 10 */
+ {OP_OpenWrite, 0, 0, 0}, /* 5: Open cursor 0 for read/write */
+
+ {OP_Variable, 1, 1, 0}, /* 6: Push the rowid to the stack */
+ {OP_NotExists, 0, 10, 1}, /* 7: Seek the cursor */
+ {OP_Column, 0, 0, 1}, /* 8 */
+ {OP_ResultRow, 1, 0, 0}, /* 9 */
+ {OP_Close, 0, 0, 0}, /* 10 */
+ {OP_Halt, 0, 0, 0}, /* 11 */
};
Vdbe *v = 0;
int rc = SQLITE_OK;
@@ -43894,8 +47038,18 @@
}
sqlite3BtreeEnterAll(db);
pTab = sqlite3LocateTable(&sParse, 0, zTable, zDb);
+ if( pTab && IsVirtual(pTab) ){
+ pTab = 0;
+ sqlite3ErrorMsg(&sParse, "cannot open virtual table: %s", zTable);
+ }
+#ifndef SQLITE_OMIT_VIEW
+ if( pTab && pTab->pSelect ){
+ pTab = 0;
+ sqlite3ErrorMsg(&sParse, "cannot open view: %s", zTable);
+ }
+#endif
if( !pTab ){
if( sParse.zErrMsg ){
sqlite3_snprintf(sizeof(zErr), zErr, "%s", sParse.zErrMsg);
}
@@ -43959,11 +47113,11 @@
/* Remove either the OP_OpenWrite or OpenRead. Set the P2
** parameter of the other to pTab->tnum.
*/
- sqlite3VdbeChangeToNoop(v, (flags ? 2 : 3), 1);
- sqlite3VdbeChangeP2(v, (flags ? 3 : 2), pTab->tnum);
- sqlite3VdbeChangeP3(v, (flags ? 3 : 2), iDb);
+ sqlite3VdbeChangeToNoop(v, (flags ? 3 : 5), 1);
+ sqlite3VdbeChangeP2(v, (flags ? 5 : 3), pTab->tnum);
+ sqlite3VdbeChangeP3(v, (flags ? 5 : 3), iDb);
/* Configure the OP_SetNumColumns. Configure the cursor to
** think that the table has one more column than it really
** does. An OP_Column to retrieve this imaginary column will
@@ -43970,9 +47124,9 @@
** always return an SQL NULL. This is useful because it means
** we can invoke OP_Column to fill in the vdbe cursors type
** and offset cache without causing any IO.
*/
- sqlite3VdbeChangeP2(v, 4, pTab->nCol+1);
+ sqlite3VdbeChangeP2(v, flags ? 4 : 2, pTab->nCol+1);
if( !db->mallocFailed ){
sqlite3VdbeMakeReady(v, 1, 1, 1, 0);
}
}
@@ -44141,9 +47295,9 @@
** May you share freely, never taking more than you give.
**
*************************************************************************
**
-** @(#) $Id: journal.c,v 1.7 2007/09/06 13:49:37 drh Exp $
+** @(#) $Id: journal.c,v 1.8 2008/05/01 18:01:47 drh Exp $
*/
#ifdef SQLITE_ENABLE_ATOMIC_WRITE
@@ -44279,11 +47433,12 @@
*/
static int jrnlSync(sqlite3_file *pJfd, int flags){
int rc;
JournalFile *p = (JournalFile *)pJfd;
- rc = createFile(p);
- if( rc==SQLITE_OK ){
+ if( p->pReal ){
rc = sqlite3OsSync(p->pReal, flags);
+ }else{
+ rc = SQLITE_OK;
}
return rc;
}
@@ -44383,9 +47538,9 @@
*************************************************************************
** This file contains routines used for analyzing expressions and
** for generating VDBE code that evaluates expressions in SQLite.
**
-** $Id: expr.c,v 1.352 2008/01/23 14:51:49 drh Exp $
+** $Id: expr.c,v 1.371 2008/05/01 17:16:53 drh Exp $
*/
/*
** Return the 'affinity' of the expression pExpr if any.
@@ -44571,8 +47726,32 @@
return pColl;
}
/*
+** Generate the operands for a comparison operation. Before
+** generating the code for each operand, set the EP_AnyAff
+** flag on the expression so that it will be able to used a
+** cached column value that has previously undergone an
+** affinity change.
+*/
+static void codeCompareOperands(
+ Parse *pParse, /* Parsing and code generating context */
+ Expr *pLeft, /* The left operand */
+ int *pRegLeft, /* Register where left operand is stored */
+ int *pFreeLeft, /* Free this register when done */
+ Expr *pRight, /* The right operand */
+ int *pRegRight, /* Register where right operand is stored */
+ int *pFreeRight /* Write temp register for right operand there */
+){
+ while( pLeft->op==TK_UPLUS ) pLeft = pLeft->pLeft;
+ pLeft->flags |= EP_AnyAff;
+ *pRegLeft = sqlite3ExprCodeTemp(pParse, pLeft, pFreeLeft);
+ while( pRight->op==TK_UPLUS ) pRight = pRight->pLeft;
+ pRight->flags |= EP_AnyAff;
+ *pRegRight = sqlite3ExprCodeTemp(pParse, pRight, pFreeRight);
+}
+
+/*
** Generate code for a comparison operator.
*/
static int codeCompare(
Parse *pParse, /* The parsing (and code generating) context */
@@ -44591,8 +47770,12 @@
p5 = binaryCompareP5(pLeft, pRight, jumpIfNull);
addr = sqlite3VdbeAddOp4(pParse->pVdbe, opcode, in2, dest, in1,
(void*)p4, P4_COLLSEQ);
sqlite3VdbeChangeP5(pParse->pVdbe, p5);
+ if( p5 & SQLITE_AFF_MASK ){
+ sqlite3ExprCacheAffinityChange(pParse, in1, 1);
+ sqlite3ExprCacheAffinityChange(pParse, in2, 1);
+ }
return addr;
}
/*
@@ -44769,11 +47952,15 @@
/* Wildcard of the form "?nnn". Convert "nnn" to an integer and
** use it as the variable number */
int i;
pExpr->iTable = i = atoi((char*)&pToken->z[1]);
- if( i<1 || i>SQLITE_MAX_VARIABLE_NUMBER ){
+ testcase( i==0 );
+ testcase( i==1 );
+ testcase( i==db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER]-1 );
+ testcase( i==db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] );
+ if( i<1 || i>db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] ){
sqlite3ErrorMsg(pParse, "variable number must be between ?1 and ?%d",
- SQLITE_MAX_VARIABLE_NUMBER);
+ db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER]);
}
if( i>pParse->nVar ){
pParse->nVar = i;
}
@@ -44809,9 +47996,9 @@
pParse->apVarExpr[pParse->nVarExpr++] = pExpr;
}
}
}
- if( !pParse->nErr && pParse->nVar>SQLITE_MAX_VARIABLE_NUMBER ){
+ if( !pParse->nErr && pParse->nVar>db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] ){
sqlite3ErrorMsg(pParse, "too many SQL variables");
}
}
@@ -45065,18 +48252,19 @@
*/
SQLITE_PRIVATE void sqlite3ExprListCheckLength(
Parse *pParse,
ExprList *pEList,
- int iLimit,
const char *zObject
){
- if( pEList && pEList->nExpr>iLimit ){
+ int mx = pParse->db->aLimit[SQLITE_LIMIT_COLUMN];
+ testcase( pEList && pEList->nExpr==mx );
+ testcase( pEList && pEList->nExpr==mx+1 );
+ if( pEList && pEList->nExpr>mx ){
sqlite3ErrorMsg(pParse, "too many columns in %s", zObject);
}
}
-#if defined(SQLITE_TEST) || SQLITE_MAX_EXPR_DEPTH>0
/* The following three functions, heightOfExpr(), heightOfExprList()
** and heightOfSelect(), are used to determine the maximum height
** of any expression tree referenced by the structure passed as the
** first argument.
@@ -45137,9 +48325,8 @@
int nHeight = 0;
heightOfSelect(p, &nHeight);
return nHeight;
}
-#endif
/*
** Delete an entire expression list.
*/
@@ -45157,9 +48344,10 @@
sqlite3_free(pList);
}
/*
-** Walk an expression tree. Call xFunc for each node visited.
+** Walk an expression tree. Call xFunc for each node visited. xFunc
+** is called on the node before xFunc is called on the nodes children.
**
** The return value from xFunc determines whether the tree walk continues.
** 0 means continue walking the tree. 1 means do not walk children
** of the current node but continue with siblings. 2 means abandon
@@ -45251,9 +48439,16 @@
case TK_AGG_COLUMN:
#ifndef SQLITE_OMIT_SUBQUERY
case TK_SELECT:
case TK_EXISTS:
-#endif
+ testcase( pExpr->op==TK_SELECT );
+ testcase( pExpr->op==TK_EXISTS );
+#endif
+ testcase( pExpr->op==TK_ID );
+ testcase( pExpr->op==TK_COLUMN );
+ testcase( pExpr->op==TK_DOT );
+ testcase( pExpr->op==TK_AGG_FUNCTION );
+ testcase( pExpr->op==TK_AGG_COLUMN );
*pN = 0;
return 2;
case TK_IN:
if( pExpr->pSelect ){
@@ -45507,8 +48702,10 @@
pExpr->pColl = sqlite3FindCollSeq(db, ENC(db), zColl,-1, 0);
}
pExpr->pTab = pTab;
if( iCol>=0 ){
+ testcase( iCol==31 );
+ testcase( iCol==32 );
*piColMask |= ((u32)1<<iCol) | (iCol>=32?0xffffffff:0);
}
break;
}
@@ -45616,8 +48813,9 @@
** then set the high-order bit of the bitmask.
*/
if( pExpr->iColumn>=0 && pMatch!=0 ){
int n = pExpr->iColumn;
+ testcase( n==sizeof(Bitmask)*8-1 );
if( n>=sizeof(Bitmask)*8 ){
n = sizeof(Bitmask)*8-1;
}
assert( pMatch->iCursor==pExpr->iTable );
@@ -45853,23 +49051,26 @@
NameContext *pNC, /* Namespace to resolve expressions in. */
Expr *pExpr /* The expression to be analyzed. */
){
int savedHasAgg;
+
if( pExpr==0 ) return 0;
-#if defined(SQLITE_TEST) || SQLITE_MAX_EXPR_DEPTH>0
- if( (pExpr->nHeight+pNC->pParse->nHeight)>SQLITE_MAX_EXPR_DEPTH ){
- sqlite3ErrorMsg(pNC->pParse,
- "Expression tree is too large (maximum depth %d)",
- SQLITE_MAX_EXPR_DEPTH
- );
- return 1;
- }
- pNC->pParse->nHeight += pExpr->nHeight;
+#if SQLITE_MAX_EXPR_DEPTH>0
+ {
+ int mxDepth = pNC->pParse->db->aLimit[SQLITE_LIMIT_EXPR_DEPTH];
+ if( (pExpr->nHeight+pNC->pParse->nHeight)>mxDepth ){
+ sqlite3ErrorMsg(pNC->pParse,
+ "Expression tree is too large (maximum depth %d)", mxDepth
+ );
+ return 1;
+ }
+ pNC->pParse->nHeight += pExpr->nHeight;
+ }
#endif
savedHasAgg = pNC->hasAgg;
pNC->hasAgg = 0;
walkExprTree(pExpr, nameResolverStep, pNC);
-#if defined(SQLITE_TEST) || SQLITE_MAX_EXPR_DEPTH>0
+#if SQLITE_MAX_EXPR_DEPTH>0
pNC->pParse->nHeight -= pExpr->nHeight;
#endif
if( pNC->nErr>0 ){
ExprSetProperty(pExpr, EP_Error);
@@ -45896,8 +49097,47 @@
int sqlite3_enable_in_opt = 1;
#else
#define sqlite3_enable_in_opt 1
#endif
+
+/*
+** Return true if the IN operator optimization is enabled and
+** the SELECT statement p exists and is of the
+** simple form:
+**
+** SELECT <column> FROM <table>
+**
+** If this is the case, it may be possible to use an existing table
+** or index instead of generating an epheremal table.
+*/
+#ifndef SQLITE_OMIT_SUBQUERY
+static int isCandidateForInOpt(Select *p){
+ SrcList *pSrc;
+ ExprList *pEList;
+ Table *pTab;
+ if( !sqlite3_enable_in_opt ) return 0; /* IN optimization must be enabled */
+ if( p==0 ) return 0; /* right-hand side of IN is SELECT */
+ if( p->pPrior ) return 0; /* Not a compound SELECT */
+ if( p->isDistinct ) return 0; /* No DISTINCT keyword */
+ if( p->isAgg ) return 0; /* Contains no aggregate functions */
+ if( p->pGroupBy ) return 0; /* Has no GROUP BY clause */
+ if( p->pLimit ) return 0; /* Has no LIMIT clause */
+ if( p->pOffset ) return 0;
+ if( p->pWhere ) return 0; /* Has no WHERE clause */
+ pSrc = p->pSrc;
+ if( pSrc==0 ) return 0; /* A single table in the FROM clause */
+ if( pSrc->nSrc!=1 ) return 0;
+ if( pSrc->a[0].pSelect ) return 0; /* FROM clause is not a subquery */
+ pTab = pSrc->a[0].pTab;
+ if( pTab==0 ) return 0;
+ if( pTab->pSelect ) return 0; /* FROM clause is not a view */
+ if( IsVirtual(pTab) ) return 0; /* FROM clause not a virtual table */
+ pEList = p->pEList;
+ if( pEList->nExpr!=1 ) return 0; /* One column in the result set */
+ if( pEList->a[0].pExpr->op!=TK_COLUMN ) return 0; /* Result is a column */
+ return 1;
+}
+#endif /* SQLITE_OMIT_SUBQUERY */
/*
** This function is used by the implementation of the IN (...) operator.
** It's job is to find or create a b-tree structure that may be used
@@ -45942,16 +49182,10 @@
**
** If this is the case, it may be possible to use an existing table
** or index instead of generating an epheremal table.
*/
- if( sqlite3_enable_in_opt
- && (p=pX->pSelect) && !p->pPrior
- && !p->isDistinct && !p->isAgg && !p->pGroupBy
- && p->pSrc && p->pSrc->nSrc==1 && !p->pSrc->a[0].pSelect
- && !p->pSrc->a[0].pTab->pSelect
- && p->pEList->nExpr==1 && p->pEList->a[0].pExpr->op==TK_COLUMN
- && !p->pLimit && !p->pOffset && !p->pWhere
- ){
+ p = pX->pSelect;
+ if( isCandidateForInOpt(p) ){
sqlite3 *db = pParse->db;
Index *pIdx;
Expr *pExpr = p->pEList->a[0].pExpr;
int iCol = pExpr->iColumn;
@@ -46007,13 +49241,13 @@
iAddr = sqlite3VdbeAddOp1(v, OP_If, iMem);
sqlite3VdbeAddOp2(v, OP_Integer, 1, iMem);
+ sqlite3VdbeAddOp2(v, OP_SetNumColumns, 0, pIdx->nColumn);
sqlite3VdbeAddOp4(v, OP_OpenRead, iTab, pIdx->tnum, iDb,
pKey,P4_KEYINFO_HANDOFF);
VdbeComment((v, "%s", pIdx->zName));
eType = IN_INDEX_INDEX;
- sqlite3VdbeAddOp2(v, OP_SetNumColumns, iTab, pIdx->nColumn);
sqlite3VdbeJumpHere(v, iAddr);
}
}
@@ -46087,12 +49321,11 @@
** 'x' nor the SELECT... statement are columns, then numeric affinity
** is used.
*/
pExpr->iTable = pParse->nTab++;
- addr = sqlite3VdbeAddOp1(v, OP_OpenEphemeral, pExpr->iTable);
+ addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pExpr->iTable, 1);
memset(&keyInfo, 0, sizeof(keyInfo));
keyInfo.nField = 1;
- sqlite3VdbeAddOp2(v, OP_SetNumColumns, pExpr->iTable, 1);
if( pExpr->pSelect ){
/* Case 1: expr IN (SELECT ...)
**
@@ -46147,10 +49380,14 @@
testAddr = 0;
}
/* Evaluate the expression and insert it into the temp table */
+ pParse->disableColCache++;
sqlite3ExprCode(pParse, pE2, r1);
+ assert( pParse->disableColCache>0 );
+ pParse->disableColCache--;
sqlite3VdbeAddOp4(v, OP_MakeRecord, r1, 1, r2, &affinity, 1);
+ sqlite3ExprCacheAffinityChange(pParse, r1, 1);
sqlite3VdbeAddOp2(v, OP_IdxInsert, pExpr->iTable, r2);
}
sqlite3ReleaseTempReg(pParse, r1);
sqlite3ReleaseTempReg(pParse, r2);
@@ -46223,11 +49460,15 @@
double value;
char *zV;
assert( !isdigit(z[n]) );
sqlite3AtoF(z, &value);
- if( negateFlag ) value = -value;
- zV = dup8bytes(v, (char*)&value);
- sqlite3VdbeAddOp4(v, OP_Real, 0, iMem, 0, zV, P4_REAL);
+ if( sqlite3IsNaN(value) ){
+ sqlite3VdbeAddOp2(v, OP_Null, 0, iMem);
+ }else{
+ if( negateFlag ) value = -value;
+ zV = dup8bytes(v, (char*)&value);
+ sqlite3VdbeAddOp4(v, OP_Real, 0, iMem, 0, zV, P4_REAL);
+ }
}
}
@@ -46262,19 +49503,44 @@
/*
** Generate code that will extract the iColumn-th column from
-** table pTab and store the column value in register iReg.
-** There is an open cursor to pTab in
-** iTable. If iColumn<0 then code is generated that extracts the rowid.
-*/
-SQLITE_PRIVATE void sqlite3ExprCodeGetColumn(
- Vdbe *v, /* The VM being created */
+** table pTab and store the column value in a register. An effort
+** is made to store the column value in register iReg, but this is
+** not guaranteed. The location of the column value is returned.
+**
+** There must be an open cursor to pTab in iTable when this routine
+** is called. If iColumn<0 then code is generated that extracts the rowid.
+**
+** This routine might attempt to reuse the value of the column that
+** has already been loaded into a register. The value will always
+** be used if it has not undergone any affinity changes. But if
+** an affinity change has occurred, then the cached value will only be
+** used if allowAffChng is true.
+*/
+SQLITE_PRIVATE int sqlite3ExprCodeGetColumn(
+ Parse *pParse, /* Parsing and code generating context */
Table *pTab, /* Description of the table we are reading from */
int iColumn, /* Index of the table column */
int iTable, /* The cursor pointing to the table */
- int iReg /* Store results here */
-){
+ int iReg, /* Store results here */
+ int allowAffChng /* True if prior affinity changes are OK */
+){
+ Vdbe *v = pParse->pVdbe;
+ int i;
+ struct yColCache *p;
+
+ for(i=0, p=pParse->aColCache; i<pParse->nColCache; i++, p++){
+ if( p->iTable==iTable && p->iColumn==iColumn
+ && (!p->affChange || allowAffChng) ){
+#if 0
+ sqlite3VdbeAddOp0(v, OP_Noop);
+ VdbeComment((v, "OPT: tab%d.col%d -> r%d", iTable, iColumn, p->iReg));
+#endif
+ return p->iReg;
+ }
+ }
+ assert( v!=0 );
if( iColumn<0 ){
int op = (pTab && IsVirtual(pTab)) ? OP_VRowid : OP_Rowid;
sqlite3VdbeAddOp2(v, op, iTable, iReg);
}else if( pTab==0 ){
@@ -46288,8 +49554,133 @@
sqlite3VdbeAddOp1(v, OP_RealAffinity, iReg);
}
#endif
}
+ if( pParse->disableColCache==0 ){
+ i = pParse->iColCache;
+ p = &pParse->aColCache[i];
+ p->iTable = iTable;
+ p->iColumn = iColumn;
+ p->iReg = iReg;
+ p->affChange = 0;
+ i++;
+ if( i>=ArraySize(pParse->aColCache) ) i = 0;
+ if( i>pParse->nColCache ) pParse->nColCache = i;
+ pParse->iColCache = i;
+ }
+ return iReg;
+}
+
+/*
+** Clear all column cache entries associated with the vdbe
+** cursor with cursor number iTable.
+*/
+SQLITE_PRIVATE void sqlite3ExprClearColumnCache(Parse *pParse, int iTable){
+ if( iTable<0 ){
+ pParse->nColCache = 0;
+ pParse->iColCache = 0;
+ }else{
+ int i;
+ for(i=0; i<pParse->nColCache; i++){
+ if( pParse->aColCache[i].iTable==iTable ){
+ testcase( i==pParse->nColCache-1 );
+ pParse->aColCache[i] = pParse->aColCache[--pParse->nColCache];
+ pParse->iColCache = pParse->nColCache;
+ }
+ }
+ }
+}
+
+/*
+** Record the fact that an affinity change has occurred on iCount
+** registers starting with iStart.
+*/
+SQLITE_PRIVATE void sqlite3ExprCacheAffinityChange(Parse *pParse, int iStart, int iCount){
+ int iEnd = iStart + iCount - 1;
+ int i;
+ for(i=0; i<pParse->nColCache; i++){
+ int r = pParse->aColCache[i].iReg;
+ if( r>=iStart && r<=iEnd ){
+ pParse->aColCache[i].affChange = 1;
+ }
+ }
+}
+
+/*
+** Generate code to moves content from one register to another.
+** Keep the column cache up-to-date.
+*/
+SQLITE_PRIVATE void sqlite3ExprCodeMove(Parse *pParse, int iFrom, int iTo){
+ int i;
+ if( iFrom==iTo ) return;
+ sqlite3VdbeAddOp2(pParse->pVdbe, OP_Move, iFrom, iTo);
+ for(i=0; i<pParse->nColCache; i++){
+ if( pParse->aColCache[i].iReg==iFrom ){
+ pParse->aColCache[i].iReg = iTo;
+ }
+ }
+}
+
+/*
+** Return true if any register in the range iFrom..iTo (inclusive)
+** is used as part of the column cache.
+*/
+static int usedAsColumnCache(Parse *pParse, int iFrom, int iTo){
+ int i;
+ for(i=0; i<pParse->nColCache; i++){
+ int r = pParse->aColCache[i].iReg;
+ if( r>=iFrom && r<=iTo ) return 1;
+ }
+ return 0;
+}
+
+/*
+** Theres is a value in register iCurrent. We ultimately want
+** the value to be in register iTarget. It might be that
+** iCurrent and iTarget are the same register.
+**
+** We are going to modify the value, so we need to make sure it
+** is not a cached register. If iCurrent is a cached register,
+** then try to move the value over to iTarget. If iTarget is a
+** cached register, then clear the corresponding cache line.
+**
+** Return the register that the value ends up in.
+*/
+SQLITE_PRIVATE int sqlite3ExprWritableRegister(Parse *pParse, int iCurrent, int iTarget){
+ int i;
+ assert( pParse->pVdbe!=0 );
+ if( !usedAsColumnCache(pParse, iCurrent, iCurrent) ){
+ return iCurrent;
+ }
+ if( iCurrent!=iTarget ){
+ sqlite3VdbeAddOp2(pParse->pVdbe, OP_SCopy, iCurrent, iTarget);
+ }
+ for(i=0; i<pParse->nColCache; i++){
+ if( pParse->aColCache[i].iReg==iTarget ){
+ pParse->aColCache[i] = pParse->aColCache[--pParse->nColCache];
+ pParse->iColCache = pParse->nColCache;
+ }
+ }
+ return iTarget;
+}
+
+/*
+** If the last instruction coded is an ephemeral copy of any of
+** the registers in the nReg registers beginning with iReg, then
+** convert the last instruction from OP_SCopy to OP_Copy.
+*/
+SQLITE_PRIVATE void sqlite3ExprHardCopy(Parse *pParse, int iReg, int nReg){
+ int addr;
+ VdbeOp *pOp;
+ Vdbe *v;
+
+ v = pParse->pVdbe;
+ addr = sqlite3VdbeCurrentAddr(v);
+ pOp = sqlite3VdbeGetOp(v, addr-1);
+ assert( pOp || pParse->db->mallocFailed );
+ if( pOp && pOp->opcode==OP_SCopy && pOp->p1>=iReg && pOp->p1<iReg+nReg ){
+ pOp->opcode = OP_Copy;
+ }
}
/*
** Generate code into the current Vdbe to evaluate the given
@@ -46301,15 +49692,15 @@
** register if it is convenient to do so. The calling function
** must check the return code and move the results to the desired
** register.
*/
-static int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
+SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
Vdbe *v = pParse->pVdbe; /* The VM under construction */
int op; /* The opcode being coded */
int inReg = target; /* Results stored in register inReg */
int regFree1 = 0; /* If non-zero free this temporary register */
int regFree2 = 0; /* If non-zero free this temporary register */
- int r1, r2, r3; /* Various register numbers */
+ int r1, r2, r3, r4; /* Various register numbers */
assert( v!=0 || pParse->db->mallocFailed );
assert( target>0 && target<=pParse->nMem );
if( v==0 ) return 0;
@@ -46339,10 +49730,12 @@
/* This only happens when coding check constraints */
assert( pParse->ckBase>0 );
inReg = pExpr->iColumn + pParse->ckBase;
}else{
- sqlite3ExprCodeGetColumn(v, pExpr->pTab,
- pExpr->iColumn, pExpr->iTable, target);
+ testcase( (pExpr->flags & EP_AnyAff)!=0 );
+ inReg = sqlite3ExprCodeGetColumn(pParse, pExpr->pTab,
+ pExpr->iColumn, pExpr->iTable, target,
+ pExpr->flags & EP_AnyAff);
}
break;
}
case TK_INTEGER: {
@@ -46401,9 +49794,16 @@
assert( to_op==OP_ToBlob || aff!=SQLITE_AFF_NONE );
assert( to_op==OP_ToNumeric || aff!=SQLITE_AFF_NUMERIC );
assert( to_op==OP_ToInt || aff!=SQLITE_AFF_INTEGER );
assert( to_op==OP_ToReal || aff!=SQLITE_AFF_REAL );
+ testcase( to_op==OP_ToText );
+ testcase( to_op==OP_ToBlob );
+ testcase( to_op==OP_ToNumeric );
+ testcase( to_op==OP_ToInt );
+ testcase( to_op==OP_ToReal );
sqlite3VdbeAddOp1(v, to_op, inReg);
+ testcase( usedAsColumnCache(pParse, inReg, inReg) );
+ sqlite3ExprCacheAffinityChange(pParse, inReg, 1);
break;
}
#endif /* SQLITE_OMIT_CAST */
case TK_LT:
@@ -46417,12 +49817,20 @@
assert( TK_GT==OP_Gt );
assert( TK_GE==OP_Ge );
assert( TK_EQ==OP_Eq );
assert( TK_NE==OP_Ne );
- r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1);
- r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2);
+ testcase( op==TK_LT );
+ testcase( op==TK_LE );
+ testcase( op==TK_GT );
+ testcase( op==TK_GE );
+ testcase( op==TK_EQ );
+ testcase( op==TK_NE );
+ codeCompareOperands(pParse, pExpr->pLeft, &r1, ®Free1,
+ pExpr->pRight, &r2, ®Free2);
codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
r1, r2, inReg, SQLITE_STOREP2);
+ testcase( regFree1==0 );
+ testcase( regFree2==0 );
break;
}
case TK_AND:
case TK_OR:
@@ -46446,11 +49854,24 @@
assert( TK_SLASH==OP_Divide );
assert( TK_LSHIFT==OP_ShiftLeft );
assert( TK_RSHIFT==OP_ShiftRight );
assert( TK_CONCAT==OP_Concat );
+ testcase( op==TK_AND );
+ testcase( op==TK_OR );
+ testcase( op==TK_PLUS );
+ testcase( op==TK_MINUS );
+ testcase( op==TK_REM );
+ testcase( op==TK_BITAND );
+ testcase( op==TK_BITOR );
+ testcase( op==TK_SLASH );
+ testcase( op==TK_LSHIFT );
+ testcase( op==TK_RSHIFT );
+ testcase( op==TK_CONCAT );
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1);
r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2);
sqlite3VdbeAddOp3(v, op, r2, r1, target);
+ testcase( regFree1==0 );
+ testcase( regFree2==0 );
break;
}
case TK_UMINUS: {
Expr *pLeft = pExpr->pLeft;
@@ -46464,10 +49885,11 @@
}
}else{
regFree1 = r1 = sqlite3GetTempReg(pParse);
sqlite3VdbeAddOp2(v, OP_Integer, 0, r1);
- r2 = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target);
+ r2 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free2);
sqlite3VdbeAddOp3(v, OP_Subtract, r2, r1, target);
+ testcase( regFree2==0 );
}
inReg = target;
break;
}
@@ -46474,9 +49896,14 @@
case TK_BITNOT:
case TK_NOT: {
assert( TK_BITNOT==OP_BitNot );
assert( TK_NOT==OP_Not );
+ testcase( op==TK_BITNOT );
+ testcase( op==TK_NOT );
inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target);
+ testcase( inReg==target );
+ testcase( usedAsColumnCache(pParse, inReg, inReg) );
+ inReg = sqlite3ExprWritableRegister(pParse, inReg, target);
sqlite3VdbeAddOp1(v, op, inReg);
break;
}
case TK_ISNULL:
@@ -46483,10 +49910,13 @@
case TK_NOTNULL: {
int addr;
assert( TK_ISNULL==OP_IsNull );
assert( TK_NOTNULL==OP_NotNull );
+ testcase( op==TK_ISNULL );
+ testcase( op==TK_NOTNULL );
sqlite3VdbeAddOp2(v, OP_Integer, 1, target);
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1);
+ testcase( regFree1==0 );
addr = sqlite3VdbeAddOp1(v, op, r1);
sqlite3VdbeAddOp2(v, OP_AddImm, target, -1);
sqlite3VdbeJumpHere(v, addr);
break;
@@ -46513,16 +49943,18 @@
sqlite3 *db = pParse->db;
u8 enc = ENC(db);
CollSeq *pColl = 0;
+ testcase( op==TK_CONST_FUNC );
+ testcase( op==TK_FUNCTION );
zId = (char*)pExpr->token.z;
nId = pExpr->token.n;
pDef = sqlite3FindFunction(pParse->db, zId, nId, nExpr, enc, 0);
assert( pDef!=0 );
if( pList ){
nExpr = pList->nExpr;
r1 = sqlite3GetTempRange(pParse, nExpr);
- sqlite3ExprCodeExprList(pParse, pList, r1);
+ sqlite3ExprCodeExprList(pParse, pList, r1, 1);
}else{
nExpr = r1 = 0;
}
#ifndef SQLITE_OMIT_VIRTUALTABLE
@@ -46561,13 +49993,16 @@
sqlite3VdbeChangeP5(v, nExpr);
if( nExpr ){
sqlite3ReleaseTempRange(pParse, r1, nExpr);
}
+ sqlite3ExprCacheAffinityChange(pParse, r1, nExpr);
break;
}
#ifndef SQLITE_OMIT_SUBQUERY
case TK_EXISTS:
case TK_SELECT: {
+ testcase( op==TK_EXISTS );
+ testcase( op==TK_SELECT );
if( pExpr->iColumn==0 ){
sqlite3CodeSubselect(pParse, pExpr);
}
inReg = pExpr->iColumn;
@@ -46591,21 +50026,23 @@
/* Code the <expr> from "<expr> IN (...)". The temporary table
** pExpr->iTable contains the values that make up the (...) set.
*/
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1);
+ testcase( regFree1==0 );
j1 = sqlite3VdbeAddOp1(v, OP_NotNull, r1);
sqlite3VdbeAddOp2(v, OP_Null, 0, target);
j2 = sqlite3VdbeAddOp0(v, OP_Goto);
sqlite3VdbeJumpHere(v, j1);
if( eType==IN_INDEX_ROWID ){
- j3 = sqlite3VdbeAddOp3(v, OP_MustBeInt, r1, 0, 1);
+ j3 = sqlite3VdbeAddOp1(v, OP_MustBeInt, r1);
j4 = sqlite3VdbeAddOp3(v, OP_NotExists, pExpr->iTable, 0, r1);
j5 = sqlite3VdbeAddOp0(v, OP_Goto);
sqlite3VdbeJumpHere(v, j3);
sqlite3VdbeJumpHere(v, j4);
}else{
r2 = regFree2 = sqlite3GetTempReg(pParse);
sqlite3VdbeAddOp4(v, OP_MakeRecord, r1, 1, r2, &affinity, 1);
+ sqlite3ExprCacheAffinityChange(pParse, r1, 1);
j5 = sqlite3VdbeAddOp3(v, OP_Found, pExpr->iTable, 0, r2);
}
sqlite3VdbeAddOp2(v, OP_AddImm, target, -1);
sqlite3VdbeJumpHere(v, j2);
@@ -46628,20 +50065,25 @@
Expr *pLeft = pExpr->pLeft;
struct ExprList_item *pLItem = pExpr->pList->a;
Expr *pRight = pLItem->pExpr;
- r1 = sqlite3ExprCodeTemp(pParse, pLeft, ®Free1);
- r2 = sqlite3ExprCodeTemp(pParse, pRight, ®Free2);
+ codeCompareOperands(pParse, pLeft, &r1, ®Free1,
+ pRight, &r2, ®Free2);
+ testcase( regFree1==0 );
+ testcase( regFree2==0 );
r3 = sqlite3GetTempReg(pParse);
+ r4 = sqlite3GetTempReg(pParse);
codeCompare(pParse, pLeft, pRight, OP_Ge,
r1, r2, r3, SQLITE_STOREP2);
pLItem++;
pRight = pLItem->pExpr;
sqlite3ReleaseTempReg(pParse, regFree2);
r2 = sqlite3ExprCodeTemp(pParse, pRight, ®Free2);
- codeCompare(pParse, pLeft, pRight, OP_Le, r1, r2, r2, SQLITE_STOREP2);
- sqlite3VdbeAddOp3(v, OP_And, r3, r2, target);
+ testcase( regFree2==0 );
+ codeCompare(pParse, pLeft, pRight, OP_Le, r1, r2, r4, SQLITE_STOREP2);
+ sqlite3VdbeAddOp3(v, OP_And, r3, r4, target);
sqlite3ReleaseTempReg(pParse, r3);
+ sqlite3ReleaseTempReg(pParse, r4);
break;
}
case TK_UPLUS: {
inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target);
@@ -46689,22 +50131,29 @@
nExpr = pEList->nExpr;
endLabel = sqlite3VdbeMakeLabel(v);
if( (pX = pExpr->pLeft)!=0 ){
cacheX = *pX;
+ testcase( pX->op==TK_COLUMN || pX->op==TK_REGISTER );
cacheX.iTable = sqlite3ExprCodeTemp(pParse, pX, ®Free1);
+ testcase( regFree1==0 );
cacheX.op = TK_REGISTER;
+ cacheX.iColumn = 0;
opCompare.op = TK_EQ;
opCompare.pLeft = &cacheX;
pTest = &opCompare;
}
+ pParse->disableColCache++;
for(i=0; i<nExpr; i=i+2){
if( pX ){
opCompare.pRight = aListelem[i].pExpr;
}else{
pTest = aListelem[i].pExpr;
}
nextCase = sqlite3VdbeMakeLabel(v);
+ testcase( pTest->op==TK_COLUMN || pTest->op==TK_REGISTER );
sqlite3ExprIfFalse(pParse, pTest, nextCase, SQLITE_JUMPIFNULL);
+ testcase( aListelem[i+1].pExpr->op==TK_COLUMN );
+ testcase( aListelem[i+1].pExpr->op==TK_REGISTER );
sqlite3ExprCode(pParse, aListelem[i+1].pExpr, target);
sqlite3VdbeAddOp2(v, OP_Goto, 0, endLabel);
sqlite3VdbeResolveLabel(v, nextCase);
}
@@ -46713,8 +50162,10 @@
}else{
sqlite3VdbeAddOp2(v, OP_Null, 0, target);
}
sqlite3VdbeResolveLabel(v, endLabel);
+ assert( pParse->disableColCache>0 );
+ pParse->disableColCache--;
break;
}
#ifndef SQLITE_OMIT_TRIGGER
case TK_RAISE: {
@@ -46750,9 +50201,9 @@
** into a register. Return the register number where the results
** are stored.
**
** If the register is a temporary register that can be deallocated,
-** then write its number into *pReg. If the result register is no
+** then write its number into *pReg. If the result register is not
** a temporary, then set *pReg to zero.
*/
SQLITE_PRIVATE int sqlite3ExprCodeTemp(Parse *pParse, Expr *pExpr, int *pReg){
int r1 = sqlite3GetTempReg(pParse);
@@ -46804,11 +50255,123 @@
int iMem;
iMem = ++pParse->nMem;
sqlite3VdbeAddOp2(v, OP_Copy, inReg, iMem);
pExpr->iTable = iMem;
+ pExpr->iColumn = pExpr->op;
pExpr->op = TK_REGISTER;
}
return inReg;
+}
+
+/*
+** Return TRUE if pExpr is an constant expression that is appropriate
+** for factoring out of a loop. Appropriate expressions are:
+**
+** * Any expression that evaluates to two or more opcodes.
+**
+** * Any OP_Integer, OP_Real, OP_String, OP_Blob, OP_Null,
+** or OP_Variable that does not need to be placed in a
+** specific register.
+**
+** There is no point in factoring out single-instruction constant
+** expressions that need to be placed in a particular register.
+** We could factor them out, but then we would end up adding an
+** OP_SCopy instruction to move the value into the correct register
+** later. We might as well just use the original instruction and
+** avoid the OP_SCopy.
+*/
+static int isAppropriateForFactoring(Expr *p){
+ if( !sqlite3ExprIsConstantNotJoin(p) ){
+ return 0; /* Only constant expressions are appropriate for factoring */
+ }
+ if( (p->flags & EP_FixedDest)==0 ){
+ return 1; /* Any constant without a fixed destination is appropriate */
+ }
+ while( p->op==TK_UPLUS ) p = p->pLeft;
+ switch( p->op ){
+#ifndef SQLITE_OMIT_BLOB_LITERAL
+ case TK_BLOB:
+#endif
+ case TK_VARIABLE:
+ case TK_INTEGER:
+ case TK_FLOAT:
+ case TK_NULL:
+ case TK_STRING: {
+ testcase( p->op==TK_BLOB );
+ testcase( p->op==TK_VARIABLE );
+ testcase( p->op==TK_INTEGER );
+ testcase( p->op==TK_FLOAT );
+ testcase( p->op==TK_NULL );
+ testcase( p->op==TK_STRING );
+ /* Single-instruction constants with a fixed destination are
+ ** better done in-line. If we factor them, they will just end
+ ** up generating an OP_SCopy to move the value to the destination
+ ** register. */
+ return 0;
+ }
+ case TK_UMINUS: {
+ if( p->pLeft->op==TK_FLOAT || p->pLeft->op==TK_INTEGER ){
+ return 0;
+ }
+ break;
+ }
+ default: {
+ break;
+ }
+ }
+ return 1;
+}
+
+/*
+** If pExpr is a constant expression that is appropriate for
+** factoring out of a loop, then evaluate the expression
+** into a register and convert the expression into a TK_REGISTER
+** expression.
+*/
+static int evalConstExpr(void *pArg, Expr *pExpr){
+ Parse *pParse = (Parse*)pArg;
+ switch( pExpr->op ){
+ case TK_REGISTER: {
+ return 1;
+ }
+ case TK_FUNCTION:
+ case TK_AGG_FUNCTION:
+ case TK_CONST_FUNC: {
+ /* The arguments to a function have a fixed destination.
+ ** Mark them this way to avoid generated unneeded OP_SCopy
+ ** instructions.
+ */
+ ExprList *pList = pExpr->pList;
+ if( pList ){
+ int i = pList->nExpr;
+ struct ExprList_item *pItem = pList->a;
+ for(; i>0; i--, pItem++){
+ if( pItem->pExpr ) pItem->pExpr->flags |= EP_FixedDest;
+ }
+ }
+ break;
+ }
+ }
+ if( isAppropriateForFactoring(pExpr) ){
+ int r1 = ++pParse->nMem;
+ int r2;
+ r2 = sqlite3ExprCodeTarget(pParse, pExpr, r1);
+ if( r1!=r2 ) sqlite3ReleaseTempReg(pParse, r1);
+ pExpr->iColumn = pExpr->op;
+ pExpr->op = TK_REGISTER;
+ pExpr->iTable = r2;
+ return 1;
+ }
+ return 0;
+}
+
+/*
+** Preevaluate constant subexpressions within pExpr and store the
+** results in registers. Modify pExpr so that the constant subexpresions
+** are TK_REGISTER opcodes that refer to the precomputed values.
+*/
+SQLITE_PRIVATE void sqlite3ExprCodeConstants(Parse *pParse, Expr *pExpr){
+ walkExprTree(pExpr, evalConstExpr, pParse);
}
/*
@@ -46819,9 +50382,10 @@
*/
SQLITE_PRIVATE int sqlite3ExprCodeExprList(
Parse *pParse, /* Parsing context */
ExprList *pList, /* The expression list to be coded */
- int target /* Where to write results */
+ int target, /* Where to write results */
+ int doHardCopy /* Call sqlite3ExprHardCopy on each element if true */
){
struct ExprList_item *pItem;
int i, n;
assert( pList!=0 || pParse->db->mallocFailed );
@@ -46829,11 +50393,11 @@
return 0;
}
assert( target>0 );
n = pList->nExpr;
- for(pItem=pList->a, i=n; i>0; i--, pItem++){
- sqlite3ExprCode(pParse, pItem->pExpr, target);
- target++;
+ for(pItem=pList->a, i=0; i<n; i++, pItem++){
+ sqlite3ExprCode(pParse, pItem->pExpr, target+i);
+ if( doHardCopy ) sqlite3ExprHardCopy(pParse, target, n);
}
return n;
}
@@ -46863,19 +50427,30 @@
op = pExpr->op;
switch( op ){
case TK_AND: {
int d2 = sqlite3VdbeMakeLabel(v);
+ testcase( jumpIfNull==0 );
+ testcase( pParse->disableColCache==0 );
sqlite3ExprIfFalse(pParse, pExpr->pLeft, d2,jumpIfNull^SQLITE_JUMPIFNULL);
+ pParse->disableColCache++;
sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull);
+ assert( pParse->disableColCache>0 );
+ pParse->disableColCache--;
sqlite3VdbeResolveLabel(v, d2);
break;
}
case TK_OR: {
+ testcase( jumpIfNull==0 );
+ testcase( pParse->disableColCache==0 );
sqlite3ExprIfTrue(pParse, pExpr->pLeft, dest, jumpIfNull);
+ pParse->disableColCache++;
sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull);
+ assert( pParse->disableColCache>0 );
+ pParse->disableColCache--;
break;
}
case TK_NOT: {
+ testcase( jumpIfNull==0 );
sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull);
break;
}
case TK_LT:
@@ -46889,20 +50464,32 @@
assert( TK_GT==OP_Gt );
assert( TK_GE==OP_Ge );
assert( TK_EQ==OP_Eq );
assert( TK_NE==OP_Ne );
- r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1);
- r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2);
+ testcase( op==TK_LT );
+ testcase( op==TK_LE );
+ testcase( op==TK_GT );
+ testcase( op==TK_GE );
+ testcase( op==TK_EQ );
+ testcase( op==TK_NE );
+ testcase( jumpIfNull==0 );
+ codeCompareOperands(pParse, pExpr->pLeft, &r1, ®Free1,
+ pExpr->pRight, &r2, ®Free2);
codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
r1, r2, dest, jumpIfNull);
+ testcase( regFree1==0 );
+ testcase( regFree2==0 );
break;
}
case TK_ISNULL:
case TK_NOTNULL: {
assert( TK_ISNULL==OP_IsNull );
assert( TK_NOTNULL==OP_NotNull );
+ testcase( op==TK_ISNULL );
+ testcase( op==TK_NOTNULL );
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1);
sqlite3VdbeAddOp2(v, op, r1, dest);
+ testcase( regFree1==0 );
break;
}
case TK_BETWEEN: {
/* x BETWEEN y AND z
@@ -46929,15 +50516,19 @@
compRight.op = TK_LE;
compRight.pLeft = &exprX;
compRight.pRight = pExpr->pList->a[1].pExpr;
exprX.iTable = sqlite3ExprCodeTemp(pParse, &exprX, ®Free1);
+ testcase( regFree1==0 );
exprX.op = TK_REGISTER;
+ testcase( jumpIfNull==0 );
sqlite3ExprIfTrue(pParse, &exprAnd, dest, jumpIfNull);
break;
}
default: {
r1 = sqlite3ExprCodeTemp(pParse, pExpr, ®Free1);
sqlite3VdbeAddOp3(v, OP_If, r1, dest, jumpIfNull!=0);
+ testcase( regFree1==0 );
+ testcase( jumpIfNull==0 );
break;
}
}
sqlite3ReleaseTempReg(pParse, regFree1);
@@ -46995,16 +50586,26 @@
assert( pExpr->op!=TK_GE || op==OP_Lt );
switch( pExpr->op ){
case TK_AND: {
+ testcase( jumpIfNull==0 );
+ testcase( pParse->disableColCache==0 );
sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull);
+ pParse->disableColCache++;
sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull);
+ assert( pParse->disableColCache>0 );
+ pParse->disableColCache--;
break;
}
case TK_OR: {
int d2 = sqlite3VdbeMakeLabel(v);
+ testcase( jumpIfNull==0 );
+ testcase( pParse->disableColCache==0 );
sqlite3ExprIfTrue(pParse, pExpr->pLeft, d2, jumpIfNull^SQLITE_JUMPIFNULL);
+ pParse->disableColCache++;
sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull);
+ assert( pParse->disableColCache>0 );
+ pParse->disableColCache--;
sqlite3VdbeResolveLabel(v, d2);
break;
}
case TK_NOT: {
@@ -47016,18 +50617,30 @@
case TK_GT:
case TK_GE:
case TK_NE:
case TK_EQ: {
- r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1);
- r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2);
+ testcase( op==TK_LT );
+ testcase( op==TK_LE );
+ testcase( op==TK_GT );
+ testcase( op==TK_GE );
+ testcase( op==TK_EQ );
+ testcase( op==TK_NE );
+ testcase( jumpIfNull==0 );
+ codeCompareOperands(pParse, pExpr->pLeft, &r1, ®Free1,
+ pExpr->pRight, &r2, ®Free2);
codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
r1, r2, dest, jumpIfNull);
+ testcase( regFree1==0 );
+ testcase( regFree2==0 );
break;
}
case TK_ISNULL:
case TK_NOTNULL: {
+ testcase( op==TK_ISNULL );
+ testcase( op==TK_NOTNULL );
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1);
sqlite3VdbeAddOp2(v, op, r1, dest);
+ testcase( regFree1==0 );
break;
}
case TK_BETWEEN: {
/* x BETWEEN y AND z
@@ -47054,15 +50667,19 @@
compRight.op = TK_LE;
compRight.pLeft = &exprX;
compRight.pRight = pExpr->pList->a[1].pExpr;
exprX.iTable = sqlite3ExprCodeTemp(pParse, &exprX, ®Free1);
+ testcase( regFree1==0 );
exprX.op = TK_REGISTER;
+ testcase( jumpIfNull==0 );
sqlite3ExprIfFalse(pParse, &exprAnd, dest, jumpIfNull);
break;
}
default: {
r1 = sqlite3ExprCodeTemp(pParse, pExpr, ®Free1);
sqlite3VdbeAddOp3(v, OP_IfNot, r1, dest, jumpIfNull!=0);
+ testcase( regFree1==0 );
+ testcase( jumpIfNull==0 );
break;
}
}
sqlite3ReleaseTempReg(pParse, regFree1);
@@ -47316,17 +50933,27 @@
/*
** Allocate or deallocate temporary use registers during code generation.
*/
SQLITE_PRIVATE int sqlite3GetTempReg(Parse *pParse){
- if( pParse->nTempReg ){
- return pParse->aTempReg[--pParse->nTempReg];
- }else{
+ int i, r;
+ if( pParse->nTempReg==0 ){
+ return ++pParse->nMem;
+ }
+ for(i=0; i<pParse->nTempReg; i++){
+ r = pParse->aTempReg[i];
+ if( usedAsColumnCache(pParse, r, r) ) continue;
+ }
+ if( i>=pParse->nTempReg ){
return ++pParse->nMem;
}
+ while( i<pParse->nTempReg-1 ){
+ pParse->aTempReg[i] = pParse->aTempReg[i+1];
+ }
+ pParse->nTempReg--;
+ return r;
}
SQLITE_PRIVATE void sqlite3ReleaseTempReg(Parse *pParse, int iReg){
if( iReg && pParse->nTempReg<ArraySize(pParse->aTempReg) ){
- assert( iReg>0 );
pParse->aTempReg[pParse->nTempReg++] = iReg;
}
}
@@ -47333,11 +50960,12 @@
/*
** Allocate or deallocate a block of nReg consecutive registers
*/
SQLITE_PRIVATE int sqlite3GetTempRange(Parse *pParse, int nReg){
- int i;
- if( nReg<=pParse->nRangeReg ){
- i = pParse->iRangeReg;
+ int i, n;
+ i = pParse->iRangeReg;
+ n = pParse->nRangeReg;
+ if( nReg<=n && !usedAsColumnCache(pParse, i, i+n-1) ){
pParse->iRangeReg += nReg;
pParse->nRangeReg -= nReg;
}else{
i = pParse->nMem+1;
@@ -47367,9 +50995,9 @@
*************************************************************************
** This file contains C code routines that used to generate VDBE code
** that implements the ALTER TABLE command.
**
-** $Id: alter.c,v 1.41 2008/01/25 15:04:48 drh Exp $
+** $Id: alter.c,v 1.44 2008/05/09 14:17:52 drh Exp $
*/
/*
** The code in this file only exists if we are not omitting the
@@ -47404,13 +51032,13 @@
unsigned char const *zCsr = zSql;
int len = 0;
char *zRet;
- sqlite3 *db = sqlite3_user_data(context);
+ sqlite3 *db = sqlite3_context_db_handle(context);
/* The principle used to locate the table name in the CREATE TABLE
- ** statement is that the table name is the first token that is immediatedly
- ** followed by a left parenthesis - TK_LP - or "USING" TK_USING.
+ ** statement is that the table name is the first non-space token that
+ ** is immediately followed by a left parenthesis - TK_LP - or "USING" TK_USING.
*/
if( zSql ){
do {
if( !*zCsr ){
@@ -47427,13 +51055,13 @@
*/
do {
zCsr += len;
len = sqlite3GetToken(zCsr, &token);
- } while( token==TK_SPACE );
+ } while( token==TK_SPACE || token==TK_COMMENT );
assert( len>0 );
} while( token!=TK_LP && token!=TK_USING );
- zRet = sqlite3MPrintf(db, "%.*s%Q%s", tname.z - zSql, zSql,
+ zRet = sqlite3MPrintf(db, "%.*s\"%w\"%s", tname.z - zSql, zSql,
zTableName, tname.z+tname.n);
sqlite3_result_text(context, zRet, -1, sqlite3_free);
}
}
@@ -47460,9 +51088,9 @@
unsigned char const *zCsr = zSql;
int len = 0;
char *zRet;
- sqlite3 *db = sqlite3_user_data(context);
+ sqlite3 *db = sqlite3_context_db_handle(context);
/* The principle used to locate the table name in the CREATE TRIGGER
** statement is that the table name is the first token that is immediatedly
** preceded by either TK_ON or TK_DOT and immediatedly followed by one
@@ -47506,9 +51134,9 @@
/* Variable tname now contains the token that is the old table-name
** in the CREATE TRIGGER statement.
*/
- zRet = sqlite3MPrintf(db, "%.*s%Q%s", tname.z - zSql, zSql,
+ zRet = sqlite3MPrintf(db, "%.*s\"%w\"%s", tname.z - zSql, zSql,
zTableName, tname.z+tname.n);
sqlite3_result_text(context, zRet, -1, sqlite3_free);
}
}
@@ -47531,9 +51159,9 @@
int i;
for(i=0; i<sizeof(aFuncs)/sizeof(aFuncs[0]); i++){
sqlite3CreateFunc(db, aFuncs[i].zName, aFuncs[i].nArg,
- SQLITE_UTF8, (void *)db, aFuncs[i].xFunc, 0, 0);
+ SQLITE_UTF8, 0, aFuncs[i].xFunc, 0, 0);
}
}
/*
@@ -47756,9 +51384,9 @@
** it with the new table name.
*/
if( sqlite3FindTable(db, "sqlite_sequence", zDb) ){
sqlite3NestedParse(pParse,
- "UPDATE %Q.sqlite_sequence set name = %Q WHERE name = %Q",
+ "UPDATE \"%w\".sqlite_sequence set name = %Q WHERE name = %Q",
zDb, zName, pTab->zName);
}
#endif
@@ -47875,9 +51503,9 @@
while( (zEnd>zCol && *zEnd==';') || isspace(*(unsigned char *)zEnd) ){
*zEnd-- = '\0';
}
sqlite3NestedParse(pParse,
- "UPDATE %Q.%s SET "
+ "UPDATE \"%w\".%s SET "
"sql = substr(sql,1,%d) || ', ' || %Q || substr(sql,%d) "
"WHERE type = 'table' AND name = %Q",
zDb, SCHEMA_TABLE(iDb), pNew->addColOffset, zCol, pNew->addColOffset+1,
zTab
@@ -47997,9 +51625,9 @@
**
*************************************************************************
** This file contains code associated with the ANALYZE command.
**
-** @(#) $Id: analyze.c,v 1.41 2008/01/25 15:04:49 drh Exp $
+** @(#) $Id: analyze.c,v 1.42 2008/03/25 09:47:35 danielk1977 Exp $
*/
#ifndef SQLITE_OMIT_ANALYZE
/*
@@ -48059,11 +51687,11 @@
*/
if( !createStat1 ){
sqlite3TableLock(pParse, iDb, iRootPage, 1, "sqlite_stat1");
}
+ sqlite3VdbeAddOp2(v, OP_SetNumColumns, 0, 3);
sqlite3VdbeAddOp3(v, OP_OpenWrite, iStatCur, iRootPage, iDb);
sqlite3VdbeChangeP5(v, createStat1);
- sqlite3VdbeAddOp2(v, OP_SetNumColumns, iStatCur, 3);
}
/*
** Generate code to do an analysis of all indices associated with
@@ -48115,19 +51743,19 @@
/* Open a cursor to the index to be analyzed
*/
assert( iDb==sqlite3SchemaToIndex(pParse->db, pIdx->pSchema) );
+ nCol = pIdx->nColumn;
+ sqlite3VdbeAddOp2(v, OP_SetNumColumns, 0, nCol+1);
sqlite3VdbeAddOp4(v, OP_OpenRead, iIdxCur, pIdx->tnum, iDb,
(char *)pKey, P4_KEYINFO_HANDOFF);
VdbeComment((v, "%s", pIdx->zName));
- nCol = pIdx->nColumn;
regFields = iMem+nCol*2;
regTemp = regRowid = regCol = regFields+3;
regRec = regCol+1;
if( regRec>pParse->nMem ){
pParse->nMem = regRec;
}
- sqlite3VdbeAddOp2(v, OP_SetNumColumns, iIdxCur, nCol+1);
/* Memory cells are used as follows:
**
** mem[iMem]: The total number of rows in the table.
@@ -48424,9 +52052,9 @@
**
*************************************************************************
** This file contains code used to implement the ATTACH and DETACH commands.
**
-** $Id: attach.c,v 1.70 2008/01/23 03:03:05 drh Exp $
+** $Id: attach.c,v 1.75 2008/04/17 17:02:01 drh Exp $
*/
#ifndef SQLITE_OMIT_ATTACH
/*
@@ -48481,9 +52109,9 @@
sqlite3_value **argv
){
int i;
int rc = 0;
- sqlite3 *db = sqlite3_user_data(context);
+ sqlite3 *db = sqlite3_context_db_handle(context);
const char *zName;
const char *zFile;
Db *aNew;
char *zErrDyn = 0;
@@ -48499,12 +52127,12 @@
** * Too many attached databases,
** * Transaction currently open
** * Specified database name already being used.
*/
- if( db->nDb>=SQLITE_MAX_ATTACHED+2 ){
+ if( db->nDb>=db->aLimit[SQLITE_LIMIT_ATTACHED]+2 ){
sqlite3_snprintf(
sizeof(zErr), zErr, "too many attached databases - max %d",
- SQLITE_MAX_ATTACHED
+ db->aLimit[SQLITE_LIMIT_ATTACHED]
);
goto attach_error;
}
if( !db->autoCommit ){
@@ -48549,8 +52177,9 @@
rc = sqlite3BtreeFactory(db, zFile, 0, SQLITE_DEFAULT_CACHE_SIZE,
db->openFlags | SQLITE_OPEN_MAIN_DB,
&aNew->pBt);
if( rc==SQLITE_OK ){
+ Pager *pPager;
aNew->pSchema = sqlite3SchemaGet(db, aNew->pBt);
if( !aNew->pSchema ){
rc = SQLITE_NOMEM;
}else if( aNew->pSchema->file_format && aNew->pSchema->enc!=ENC(db) ){
@@ -48557,9 +52186,11 @@
sqlite3_snprintf(sizeof(zErr), zErr,
"attached databases must use the same text encoding as main database");
goto attach_error;
}
- sqlite3PagerLockingMode(sqlite3BtreePager(aNew->pBt), db->dfltLockMode);
+ pPager = sqlite3BtreePager(aNew->pBt);
+ sqlite3PagerLockingMode(pPager, db->dfltLockMode);
+ sqlite3PagerJournalMode(pPager, db->dfltJournalMode);
}
aNew->zName = sqlite3DbStrDup(db, zName);
aNew->safety_level = 3;
@@ -48634,8 +52265,9 @@
}else{
zErr[sizeof(zErr)-1] = 0;
sqlite3_result_error(context, zErr, -1);
}
+ if( rc ) sqlite3_result_error_code(context, rc);
}
/*
** An SQL user-function registered to do the work of an DETACH statement. The
@@ -48650,9 +52282,9 @@
int argc,
sqlite3_value **argv
){
const char *zName = (const char *)sqlite3_value_text(argv[0]);
- sqlite3 *db = sqlite3_user_data(context);
+ sqlite3 *db = sqlite3_context_db_handle(context);
int i;
Db *pDb = 0;
char zErr[128];
@@ -48739,16 +52371,16 @@
goto attach_end;
}
v = sqlite3GetVdbe(pParse);
- regArgs = sqlite3GetTempRange(pParse, 3);
+ regArgs = sqlite3GetTempRange(pParse, 4);
sqlite3ExprCode(pParse, pFilename, regArgs);
sqlite3ExprCode(pParse, pDbname, regArgs+1);
sqlite3ExprCode(pParse, pKey, regArgs+2);
assert( v || db->mallocFailed );
if( v ){
- sqlite3VdbeAddOp3(v, OP_Function, 0, regArgs+3-nFunc, regArgs);
+ sqlite3VdbeAddOp3(v, OP_Function, 0, regArgs+3-nFunc, regArgs+3);
sqlite3VdbeChangeP5(v, nFunc);
pFunc = sqlite3FindFunction(db, zFunc, strlen(zFunc), nFunc, SQLITE_UTF8,0);
sqlite3VdbeChangeP4(v, -1, (char *)pFunc, P4_FUNCDEF);
@@ -48789,10 +52421,10 @@
*/
SQLITE_PRIVATE void sqlite3AttachFunctions(sqlite3 *db){
#ifndef SQLITE_OMIT_ATTACH
static const int enc = SQLITE_UTF8;
- sqlite3CreateFunc(db, "sqlite_attach", 3, enc, db, attachFunc, 0, 0);
- sqlite3CreateFunc(db, "sqlite_detach", 1, enc, db, detachFunc, 0, 0);
+ sqlite3CreateFunc(db, "sqlite_attach", 3, enc, 0, attachFunc, 0, 0);
+ sqlite3CreateFunc(db, "sqlite_detach", 1, enc, 0, detachFunc, 0, 0);
#endif
}
/*
@@ -49199,9 +52831,9 @@
** BEGIN TRANSACTION
** COMMIT
** ROLLBACK
**
-** $Id: build.c,v 1.472 2008/01/31 13:35:49 drh Exp $
+** $Id: build.c,v 1.484 2008/05/01 17:16:53 drh Exp $
*/
/*
** This routine is called when a new SQL statement is beginning to
@@ -49286,12 +52918,10 @@
for(i=0; i<pParse->nTableLock; i++){
TableLock *p = &pParse->aTableLock[i];
int p1 = p->iDb;
- if( p->isWriteLock ){
- p1 = -1*(p1+1);
- }
- sqlite3VdbeAddOp4(pVdbe, OP_TableLock, p1, p->iTab, 0, p->zName, P4_STATIC);
+ sqlite3VdbeAddOp4(pVdbe, OP_TableLock, p1, p->iTab, p->isWriteLock,
+ p->zName, P4_STATIC);
}
}
#else
#define codeTableLocks(x)
@@ -49345,11 +52975,15 @@
sqlite3VdbeAddOp2(v,OP_Transaction, iDb, (mask & pParse->writeMask)!=0);
sqlite3VdbeAddOp2(v,OP_VerifyCookie, iDb, pParse->cookieValue[iDb]);
}
#ifndef SQLITE_OMIT_VIRTUALTABLE
- if( pParse->pVirtualLock ){
- char *vtab = (char *)pParse->pVirtualLock->pVtab;
- sqlite3VdbeAddOp4(v, OP_VBegin, 0, 0, 0, vtab, P4_VTAB);
+ {
+ int i;
+ for(i=0; i<pParse->nVtabLock; i++){
+ char *vtab = (char *)pParse->apVtabLock[i]->pVtab;
+ sqlite3VdbeAddOp4(v, OP_VBegin, 0, 0, 0, vtab, P4_VTAB);
+ }
+ pParse->nVtabLock = 0;
}
#endif
/* Once all the cookies have been verified and transactions opened,
@@ -49380,8 +53014,9 @@
#ifdef SQLITE_DEBUG
FILE *trace = (db->flags & SQLITE_VdbeTrace)!=0 ? stdout : 0;
sqlite3VdbeTrace(v, trace);
#endif
+ assert( pParse->disableColCache==0 ); /* Disables and re-enables match */
sqlite3VdbeMakeReady(v, pParse->nVar, pParse->nMem+3,
pParse->nTab+3, pParse->explain);
pParse->rc = SQLITE_DONE;
pParse->colNamesSet = 0;
@@ -49783,10 +53418,10 @@
*/
SQLITE_PRIVATE void sqlite3OpenMasterTable(Parse *p, int iDb){
Vdbe *v = sqlite3GetVdbe(p);
sqlite3TableLock(p, iDb, MASTER_ROOT, 1, SCHEMA_TABLE(iDb));
- sqlite3VdbeAddOp3(v, OP_OpenWrite, 0, MASTER_ROOT, iDb);
- sqlite3VdbeAddOp2(v, OP_SetNumColumns, 0, 5); /* sqlite_master has 5 columns */
+ sqlite3VdbeAddOp2(v, OP_SetNumColumns, 0, 5);/* sqlite_master has 5 columns */
+ sqlite3VdbeAddOp3(v, OP_OpenWrite, 0, MASTER_ROOT, iDb);
}
/*
** The token *pName contains the name of a database (either "main" or
@@ -50108,13 +53743,16 @@
Table *p;
int i;
char *z;
Column *pCol;
+ sqlite3 *db = pParse->db;
if( (p = pParse->pNewTable)==0 ) return;
- if( p->nCol+1>SQLITE_MAX_COLUMN ){
+#if SQLITE_MAX_COLUMN
+ if( p->nCol+1>db->aLimit[SQLITE_LIMIT_COLUMN] ){
sqlite3ErrorMsg(pParse, "too many columns on %s", p->zName);
return;
}
+#endif
z = sqlite3NameFromToken(pParse->db, pName);
if( z==0 ) return;
for(i=0; i<p->nCol; i++){
if( STRICMP(z, p->aCol[i].zName) ){
@@ -51245,8 +54883,16 @@
*/
sqlite3NestedParse(pParse,
"DELETE FROM %Q.%s WHERE tbl_name=%Q and type!='trigger'",
pDb->zName, SCHEMA_TABLE(iDb), pTab->zName);
+
+ /* Drop any statistics from the sqlite_stat1 table, if it exists */
+ if( sqlite3FindTable(db, "sqlite_stat1", db->aDb[iDb].zName) ){
+ sqlite3NestedParse(pParse,
+ "DELETE FROM %Q.sqlite_stat1 WHERE tbl=%Q", pDb->zName, pTab->zName
+ );
+ }
+
if( !isView && !IsVirtual(pTab) ){
destroyTable(pParse, pTab);
}
@@ -51450,9 +55096,9 @@
}
sqlite3OpenTable(pParse, iTab, iDb, pTab, OP_OpenRead);
addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iTab, 0);
regRecord = sqlite3GetTempReg(pParse);
- regIdxKey = sqlite3GenerateIndexKey(pParse, pIndex, iTab, regRecord);
+ regIdxKey = sqlite3GenerateIndexKey(pParse, pIndex, iTab, regRecord, 1);
if( pIndex->onError!=OE_None ){
int j1, j2;
int regRowid;
@@ -52030,8 +55676,14 @@
"DELETE FROM %Q.%s WHERE name=%Q",
db->aDb[iDb].zName, SCHEMA_TABLE(iDb),
pIndex->zName
);
+ if( sqlite3FindTable(db, "sqlite_stat1", db->aDb[iDb].zName) ){
+ sqlite3NestedParse(pParse,
+ "DELETE FROM %Q.sqlite_stat1 WHERE idx=%Q",
+ db->aDb[iDb].zName, pIndex->zName
+ );
+ }
sqlite3ChangeCookie(pParse, iDb);
destroyRootPage(pParse, pIndex->tnum, iDb);
sqlite3VdbeAddOp4(v, OP_DropIndex, iDb, 0, 0, pIndex->zName, 0);
}
@@ -52394,8 +56046,10 @@
return 1;
}
assert( (db->flags & SQLITE_InTrans)==0 || db->autoCommit );
assert( db->aDb[1].pSchema );
+ sqlite3PagerJournalMode(sqlite3BtreePager(db->aDb[1].pBt),
+ db->dfltJournalMode);
}
return 0;
}
@@ -53037,9 +56691,9 @@
*************************************************************************
** This file contains C code routines that are called by the parser
** in order to generate code for DELETE FROM statements.
**
-** $Id: delete.c,v 1.160 2008/01/25 15:04:50 drh Exp $
+** $Id: delete.c,v 1.169 2008/04/28 18:46:43 drh Exp $
*/
/*
** Look up every table that is named in pSrc. If any table is not found,
@@ -53099,12 +56753,43 @@
if( IsVirtual(pTab) ) return;
v = sqlite3GetVdbe(p);
assert( opcode==OP_OpenWrite || opcode==OP_OpenRead );
sqlite3TableLock(p, iDb, pTab->tnum, (opcode==OP_OpenWrite), pTab->zName);
+ sqlite3VdbeAddOp2(v, OP_SetNumColumns, 0, pTab->nCol);
sqlite3VdbeAddOp3(v, opcode, iCur, pTab->tnum, iDb);
VdbeComment((v, "%s", pTab->zName));
- sqlite3VdbeAddOp2(v, OP_SetNumColumns, iCur, pTab->nCol);
-}
+}
+
+
+#if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER)
+/*
+** Evaluate a view and store its result in an ephemeral table. The
+** pWhere argument is an optional WHERE clause that restricts the
+** set of rows in the view that are to be added to the ephemeral table.
+*/
+SQLITE_PRIVATE void sqlite3MaterializeView(
+ Parse *pParse, /* Parsing context */
+ Select *pView, /* View definition */
+ Expr *pWhere, /* Optional WHERE clause to be added */
+ int iCur /* Cursor number for ephemerial table */
+){
+ SelectDest dest;
+ Select *pDup;
+ sqlite3 *db = pParse->db;
+
+ pDup = sqlite3SelectDup(db, pView);
+ if( pWhere ){
+ SrcList *pFrom;
+
+ pWhere = sqlite3ExprDup(db, pWhere);
+ pFrom = sqlite3SrcListAppendFromTerm(pParse, 0, 0, 0, 0, pDup, 0, 0);
+ pDup = sqlite3SelectNew(pParse, 0, pFrom, pWhere, 0, 0, 0, 0, 0, 0);
+ }
+ sqlite3SelectDestInit(&dest, SRT_EphemTab, iCur);
+ sqlite3Select(pParse, pDup, &dest, 0, 0, 0, 0);
+ sqlite3SelectDelete(pDup);
+}
+#endif /* !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER) */
/*
** Generate code for a DELETE FROM statement.
@@ -53194,20 +56879,14 @@
if( triggers_exist ){
oldIdx = pParse->nTab++;
}
- /* Resolve the column names in the WHERE clause.
+ /* Assign cursor number to the table and all its indices.
*/
assert( pTabList->nSrc==1 );
iCur = pTabList->a[0].iCursor = pParse->nTab++;
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
pParse->nTab++;
- }
- memset(&sNC, 0, sizeof(sNC));
- sNC.pParse = pParse;
- sNC.pSrcList = pTabList;
- if( sqlite3ExprResolveNames(&sNC, pWhere) ){
- goto delete_from_cleanup;
}
/* Start the view context
*/
@@ -53245,16 +56924,18 @@
/* If we are trying to delete from a view, realize that view into
** a ephemeral table.
*/
if( isView ){
- SelectDest dest;
- Select *pView;
-
- pView = sqlite3SelectDup(db, pTab->pSelect);
- sqlite3SelectMask(pParse, pView, old_col_mask);
- sqlite3SelectDestInit(&dest, SRT_EphemTab, iCur);
- sqlite3Select(pParse, pView, &dest, 0, 0, 0, 0);
- sqlite3SelectDelete(pView);
+ sqlite3MaterializeView(pParse, pTab->pSelect, pWhere, iCur);
+ }
+
+ /* Resolve the column names in the WHERE clause.
+ */
+ memset(&sNC, 0, sizeof(sNC));
+ sNC.pParse = pParse;
+ sNC.pSrcList = pTabList;
+ if( sqlite3ExprResolveNames(&sNC, pWhere) ){
+ goto delete_from_cleanup;
}
/* Initialize the counter of the number of rows deleted, if
** we are counting rows.
@@ -53317,10 +56998,10 @@
/* Open the pseudo-table used to store OLD if there are triggers.
*/
if( triggers_exist ){
- sqlite3VdbeAddOp1(v, OP_OpenPseudo, oldIdx);
- sqlite3VdbeAddOp2(v, OP_SetNumColumns, oldIdx, pTab->nCol);
+ sqlite3VdbeAddOp2(v, OP_SetNumColumns, 0, pTab->nCol);
+ sqlite3VdbeAddOp1(v, OP_OpenPseudo, oldIdx);
}
/* Delete every item whose key was written to the list during the
** database scan. We have to delete items after the scan is complete
@@ -53368,9 +57049,9 @@
/* Delete the row */
#ifndef SQLITE_OMIT_VIRTUALTABLE
if( IsVirtual(pTab) ){
const char *pVtab = (const char *)pTab->pVtab;
- pParse->pVirtualLock = pTab;
+ sqlite3VtabMakeWritable(pParse, pTab);
sqlite3VdbeAddOp4(v, OP_VUpdate, 0, 1, iRowid, pVtab, P4_VTAB);
}else
#endif
{
@@ -53483,20 +57164,18 @@
int i;
Index *pIdx;
int r1;
- r1 = sqlite3GetTempReg(pParse);
for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
if( aRegIdx!=0 && aRegIdx[i-1]==0 ) continue;
- sqlite3GenerateIndexKey(pParse, pIdx, iCur, r1);
- sqlite3VdbeAddOp2(pParse->pVdbe, OP_IdxDelete, iCur+i, r1);
- }
- sqlite3ReleaseTempReg(pParse, r1);
-}
-
-/*
-** Generate code that will assemble an index key and put it on the top
-** of the tack. The key with be for index pIdx which is an index on pTab.
+ r1 = sqlite3GenerateIndexKey(pParse, pIdx, iCur, 0, 0);
+ sqlite3VdbeAddOp3(pParse->pVdbe, OP_IdxDelete, iCur+i, r1,pIdx->nColumn+1);
+ }
+}
+
+/*
+** Generate code that will assemble an index key and put it in register
+** regOut. The key with be for index pIdx which is an index on pTab.
** iCur is the index of a cursor open on the pTab table and pointing to
** the entry that needs indexing.
**
** Return a register number which is the first in a block of
@@ -53507,9 +57186,10 @@
SQLITE_PRIVATE int sqlite3GenerateIndexKey(
Parse *pParse, /* Parsing context */
Index *pIdx, /* The index for which to generate a key */
int iCur, /* Cursor number for the pIdx->pTable table */
- int regOut /* Write the new index key to this register */
+ int regOut, /* Write the new index key to this register */
+ int doMakeRec /* Run the OP_MakeRecord instruction if true */
){
Vdbe *v = pParse->pVdbe;
int j;
Table *pTab = pIdx->pTable;
@@ -53527,13 +57207,21 @@
sqlite3VdbeAddOp3(v, OP_Column, iCur, idx, regBase+j);
sqlite3ColumnDefault(v, pTab, idx);
}
}
- sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol+1, regOut);
- sqlite3IndexAffinityStr(v, pIdx);
+ if( doMakeRec ){
+ sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol+1, regOut);
+ sqlite3IndexAffinityStr(v, pIdx);
+ sqlite3ExprCacheAffinityChange(pParse, regBase, nCol+1);
+ }
sqlite3ReleaseTempRange(pParse, regBase, nCol+1);
return regBase;
}
+
+/* Make sure "isView" gets undefined in case this file becomes part of
+** the amalgamation - so that subsequent files do not see isView as a
+** macro. */
+#undef isView
/************** End of delete.c **********************************************/
/************** Begin file func.c ********************************************/
/*
@@ -53553,9 +57241,9 @@
** There is only one exported symbol in this file - the function
** sqliteRegisterBuildinFunctions() found at the bottom of the file.
** All other code has file scope.
**
-** $Id: func.c,v 1.183 2008/01/21 16:22:46 drh Exp $
+** $Id: func.c,v 1.192 2008/04/27 18:40:12 drh Exp $
*/
/*
@@ -53720,9 +57408,9 @@
p1 = sqlite3_value_int(argv[1]);
if( argc==3 ){
p2 = sqlite3_value_int(argv[2]);
}else{
- p2 = SQLITE_MAX_LENGTH;
+ p2 = sqlite3_context_db_handle(context)->aLimit[SQLITE_LIMIT_LENGTH];
}
if( p1<0 ){
p1 += len;
if( p1<0 ){
@@ -53775,12 +57463,18 @@
** Allocate nByte bytes of space using sqlite3_malloc(). If the
** allocation fails, call sqlite3_result_error_nomem() to notify
** the database handle that malloc() has failed.
*/
-static void *contextMalloc(sqlite3_context *context, int nByte){
- char *z = sqlite3_malloc(nByte);
- if( !z && nByte>0 ){
- sqlite3_result_error_nomem(context);
+static void *contextMalloc(sqlite3_context *context, i64 nByte){
+ char *z;
+ if( nByte>sqlite3_context_db_handle(context)->aLimit[SQLITE_LIMIT_LENGTH] ){
+ sqlite3_result_error_toobig(context);
+ z = 0;
+ }else{
+ z = sqlite3_malloc(nByte);
+ if( !z && nByte>0 ){
+ sqlite3_result_error_nomem(context);
+ }
}
return z;
}
@@ -53796,9 +57490,9 @@
n = sqlite3_value_bytes(argv[0]);
/* Verify that the call to _bytes() does not invalidate the _text() pointer */
assert( z2==(char*)sqlite3_value_text(argv[0]) );
if( z2 ){
- z1 = contextMalloc(context, n+1);
+ z1 = contextMalloc(context, ((i64)n)+1);
if( z1 ){
memcpy(z1, z2, n+1);
for(i=0; z1[i]; i++){
z1[i] = toupper(z1[i]);
@@ -53816,9 +57510,9 @@
n = sqlite3_value_bytes(argv[0]);
/* Verify that the call to _bytes() does not invalidate the _text() pointer */
assert( z2==(char*)sqlite3_value_text(argv[0]) );
if( z2 ){
- z1 = contextMalloc(context, n+1);
+ z1 = contextMalloc(context, ((i64)n)+1);
if( z1 ){
memcpy(z1, z2, n+1);
for(i=0; z1[i]; i++){
z1[i] = tolower(z1[i]);
@@ -53855,9 +57549,9 @@
int argc,
sqlite3_value **argv
){
sqlite_int64 r;
- sqlite3Randomness(sizeof(r), &r);
+ sqlite3_randomness(sizeof(r), &r);
if( (r<<1)==0 ) r = 0; /* Prevent 0x8000.... as the result so that we */
/* can always do abs() of the result */
sqlite3_result_int64(context, r);
}
@@ -53877,15 +57571,11 @@
n = sqlite3_value_int(argv[0]);
if( n<1 ){
n = 1;
}
- if( n>SQLITE_MAX_LENGTH ){
- sqlite3_result_error_toobig(context);
- return;
- }
p = contextMalloc(context, n);
if( p ){
- sqlite3Randomness(n, p);
+ sqlite3_randomness(n, p);
sqlite3_result_blob(context, (char*)p, n, sqlite3_free);
}
}
@@ -53897,9 +57587,9 @@
sqlite3_context *context,
int arg,
sqlite3_value **argv
){
- sqlite3 *db = sqlite3_user_data(context);
+ sqlite3 *db = sqlite3_context_db_handle(context);
sqlite3_result_int64(context, sqlite3_last_insert_rowid(db));
}
/*
@@ -53910,9 +57600,9 @@
sqlite3_context *context,
int arg,
sqlite3_value **argv
){
- sqlite3 *db = sqlite3_user_data(context);
+ sqlite3 *db = sqlite3_context_db_handle(context);
sqlite3_result_int(context, sqlite3_changes(db));
}
/*
@@ -53923,9 +57613,9 @@
sqlite3_context *context,
int arg,
sqlite3_value **argv
){
- sqlite3 *db = sqlite3_user_data(context);
+ sqlite3 *db = sqlite3_context_db_handle(context);
sqlite3_result_int(context, sqlite3_total_changes(db));
}
/*
@@ -54123,16 +57813,18 @@
sqlite3_value **argv
){
const unsigned char *zA, *zB;
int escape = 0;
+ sqlite3 *db = sqlite3_context_db_handle(context);
zB = sqlite3_value_text(argv[0]);
zA = sqlite3_value_text(argv[1]);
/* Limit the length of the LIKE or GLOB pattern to avoid problems
** of deep recursion and N*N behavior in patternCompare().
*/
- if( sqlite3_value_bytes(argv[0])>SQLITE_MAX_LIKE_PATTERN_LENGTH ){
+ if( sqlite3_value_bytes(argv[0]) >
+ db->aLimit[SQLITE_LIMIT_LIKE_PATTERN_LENGTH] ){
sqlite3_result_error(context, "LIKE or GLOB pattern too complex", -1);
return;
}
assert( zB==sqlite3_value_text(argv[0]) ); /* Encoding did not change */
@@ -54222,14 +57914,9 @@
char *zText = 0;
char const *zBlob = sqlite3_value_blob(argv[0]);
int nBlob = sqlite3_value_bytes(argv[0]);
assert( zBlob==sqlite3_value_blob(argv[0]) ); /* No encoding change */
-
- if( 2*nBlob+4>SQLITE_MAX_LENGTH ){
- sqlite3_result_error_toobig(context);
- return;
- }
- zText = (char *)contextMalloc(context, (2*nBlob)+4);
+ zText = (char *)contextMalloc(context, (2*(i64)nBlob)+4);
if( zText ){
int i;
for(i=0; i<nBlob; i++){
zText[(i*2)+2] = hexdigits[(zBlob[i]>>4)&0x0F];
@@ -54251,13 +57938,9 @@
char *z;
if( zArg==0 ) return;
for(i=0, n=0; zArg[i]; i++){ if( zArg[i]=='\'' ) n++; }
- if( i+n+3>SQLITE_MAX_LENGTH ){
- sqlite3_result_error_toobig(context);
- return;
- }
- z = contextMalloc(context, i+n+3);
+ z = contextMalloc(context, ((i64)i)+((i64)n)+3);
if( z ){
z[0] = '\'';
for(i=0, j=1; zArg[i]; i++){
z[j++] = zArg[i];
@@ -54287,14 +57970,10 @@
char *zHex, *z;
assert( argc==1 );
pBlob = sqlite3_value_blob(argv[0]);
n = sqlite3_value_bytes(argv[0]);
- if( n*2+1>SQLITE_MAX_LENGTH ){
- sqlite3_result_error_toobig(context);
- return;
- }
assert( pBlob==sqlite3_value_blob(argv[0]) ); /* No encoding change */
- z = zHex = contextMalloc(context, n*2 + 1);
+ z = zHex = contextMalloc(context, ((i64)n)*2 + 1);
if( zHex ){
for(i=0; i<n; i++, pBlob++){
unsigned char c = *pBlob;
*(z++) = hexdigits[(c>>4)&0xf];
@@ -54359,9 +58038,9 @@
nRep = sqlite3_value_bytes(argv[2]);
assert( zRep==sqlite3_value_text(argv[2]) );
nOut = nStr + 1;
assert( nOut<SQLITE_MAX_LENGTH );
- zOut = contextMalloc(context, (int)nOut);
+ zOut = contextMalloc(context, (i64)nOut);
if( zOut==0 ){
return;
}
loopLimit = nStr - nPattern;
@@ -54369,10 +58048,11 @@
if( zStr[i]!=zPattern[0] || memcmp(&zStr[i], zPattern, nPattern) ){
zOut[j++] = zStr[i];
}else{
u8 *zOld;
+ sqlite3 *db = sqlite3_context_db_handle(context);
nOut += nRep - nPattern;
- if( nOut>=SQLITE_MAX_LENGTH ){
+ if( nOut>=db->aLimit[SQLITE_LIMIT_LENGTH] ){
sqlite3_result_error_toobig(context);
sqlite3_free(zOut);
return;
}
@@ -54435,9 +58115,9 @@
for(z=zCharSet, nChar=0; *z; nChar++){
SQLITE_SKIP_UTF8(z);
}
if( nChar>0 ){
- azChar = contextMalloc(context, nChar*(sizeof(char*)+1));
+ azChar = contextMalloc(context, ((i64)nChar)*(sizeof(char*)+1));
if( azChar==0 ){
return;
}
aLen = (unsigned char*)&azChar[nChar];
@@ -54537,9 +58217,9 @@
*/
static void loadExt(sqlite3_context *context, int argc, sqlite3_value **argv){
const char *zFile = (const char *)sqlite3_value_text(argv[0]);
const char *zProc;
- sqlite3 *db = sqlite3_user_data(context);
+ sqlite3 *db = sqlite3_context_db_handle(context);
char *zErrMsg = 0;
if( argc==2 ){
zProc = (const char *)sqlite3_value_text(argv[1]);
@@ -54552,167 +58232,8 @@
}
}
#endif
-#ifdef SQLITE_TEST
-/*
-** This function generates a string of random characters. Used for
-** generating test data.
-*/
-static void randStr(sqlite3_context *context, int argc, sqlite3_value **argv){
- static const unsigned char zSrc[] =
- "abcdefghijklmnopqrstuvwxyz"
- "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
- "0123456789"
- ".-!,:*^+=_|?/<> ";
- int iMin, iMax, n, r, i;
- unsigned char zBuf[1000];
-
- /* It used to be possible to call randstr() with any number of arguments,
- ** but now it is registered with SQLite as requiring exactly 2.
- */
- assert(argc==2);
-
- iMin = sqlite3_value_int(argv[0]);
- if( iMin<0 ) iMin = 0;
- if( iMin>=sizeof(zBuf) ) iMin = sizeof(zBuf)-1;
- iMax = sqlite3_value_int(argv[1]);
- if( iMax<iMin ) iMax = iMin;
- if( iMax>=sizeof(zBuf) ) iMax = sizeof(zBuf)-1;
- n = iMin;
- if( iMax>iMin ){
- sqlite3Randomness(sizeof(r), &r);
- r &= 0x7fffffff;
- n += r%(iMax + 1 - iMin);
- }
- assert( n<sizeof(zBuf) );
- sqlite3Randomness(n, zBuf);
- for(i=0; i<n; i++){
- zBuf[i] = zSrc[zBuf[i]%(sizeof(zSrc)-1)];
- }
- zBuf[n] = 0;
- sqlite3_result_text(context, (char*)zBuf, n, SQLITE_TRANSIENT);
-}
-#endif /* SQLITE_TEST */
-
-#ifdef SQLITE_TEST
-/*
-** The following two SQL functions are used to test returning a text
-** result with a destructor. Function 'test_destructor' takes one argument
-** and returns the same argument interpreted as TEXT. A destructor is
-** passed with the sqlite3_result_text() call.
-**
-** SQL function 'test_destructor_count' returns the number of outstanding
-** allocations made by 'test_destructor';
-**
-** WARNING: Not threadsafe.
-*/
-static int test_destructor_count_var = 0;
-static void destructor(void *p){
- char *zVal = (char *)p;
- assert(zVal);
- zVal--;
- sqlite3_free(zVal);
- test_destructor_count_var--;
-}
-static void test_destructor(
- sqlite3_context *pCtx,
- int nArg,
- sqlite3_value **argv
-){
- char *zVal;
- int len;
- sqlite3 *db = sqlite3_user_data(pCtx);
-
- test_destructor_count_var++;
- assert( nArg==1 );
- if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return;
- len = sqlite3ValueBytes(argv[0], ENC(db));
- zVal = contextMalloc(pCtx, len+3);
- if( !zVal ){
- return;
- }
- zVal[len+1] = 0;
- zVal[len+2] = 0;
- zVal++;
- memcpy(zVal, sqlite3ValueText(argv[0], ENC(db)), len);
- if( ENC(db)==SQLITE_UTF8 ){
- sqlite3_result_text(pCtx, zVal, -1, destructor);
-#ifndef SQLITE_OMIT_UTF16
- }else if( ENC(db)==SQLITE_UTF16LE ){
- sqlite3_result_text16le(pCtx, zVal, -1, destructor);
- }else{
- sqlite3_result_text16be(pCtx, zVal, -1, destructor);
-#endif /* SQLITE_OMIT_UTF16 */
- }
-}
-static void test_destructor_count(
- sqlite3_context *pCtx,
- int nArg,
- sqlite3_value **argv
-){
- sqlite3_result_int(pCtx, test_destructor_count_var);
-}
-#endif /* SQLITE_TEST */
-
-#ifdef SQLITE_TEST
-/*
-** Routines for testing the sqlite3_get_auxdata() and sqlite3_set_auxdata()
-** interface.
-**
-** The test_auxdata() SQL function attempts to register each of its arguments
-** as auxiliary data. If there are no prior registrations of aux data for
-** that argument (meaning the argument is not a constant or this is its first
-** call) then the result for that argument is 0. If there is a prior
-** registration, the result for that argument is 1. The overall result
-** is the individual argument results separated by spaces.
-*/
-static void free_test_auxdata(void *p) {sqlite3_free(p);}
-static void test_auxdata(
- sqlite3_context *pCtx,
- int nArg,
- sqlite3_value **argv
-){
- int i;
- char *zRet = contextMalloc(pCtx, nArg*2);
- if( !zRet ) return;
- memset(zRet, 0, nArg*2);
- for(i=0; i<nArg; i++){
- char const *z = (char*)sqlite3_value_text(argv[i]);
- if( z ){
- char *zAux = sqlite3_get_auxdata(pCtx, i);
- if( zAux ){
- zRet[i*2] = '1';
- assert( strcmp(zAux,z)==0 );
- }else {
- zRet[i*2] = '0';
- }
-
- zAux = contextMalloc(pCtx, strlen(z)+1);
- if( zAux ){
- strcpy(zAux, z);
- sqlite3_set_auxdata(pCtx, i, zAux, free_test_auxdata);
- }
- zRet[i*2+1] = ' ';
- }
- }
- sqlite3_result_text(pCtx, zRet, 2*nArg-1, free_test_auxdata);
-}
-#endif /* SQLITE_TEST */
-
-#ifdef SQLITE_TEST
-/*
-** A function to test error reporting from user functions. This function
-** returns a copy of its first argument as an error.
-*/
-static void test_error(
- sqlite3_context *pCtx,
- int nArg,
- sqlite3_value **argv
-){
- sqlite3_result_error(pCtx, (char*)sqlite3_value_text(argv[0]), 0);
-}
-#endif /* SQLITE_TEST */
/*
** An instance of the following structure holds the context of a
** sum() or avg() aggregate computation.
@@ -54870,9 +58391,11 @@
if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return;
pAccum = (StrAccum*)sqlite3_aggregate_context(context, sizeof(*pAccum));
if( pAccum ){
+ sqlite3 *db = sqlite3_context_db_handle(context);
pAccum->useMalloc = 1;
+ pAccum->mxAlloc = db->aLimit[SQLITE_LIMIT_LENGTH];
if( pAccum->nChar ){
if( argc==2 ){
zSep = (char*)sqlite3_value_text(argv[1]);
nSep = sqlite3_value_bytes(argv[1]);
@@ -54910,9 +58433,9 @@
SQLITE_PRIVATE void sqlite3RegisterBuiltinFunctions(sqlite3 *db){
static const struct {
char *zName;
signed char nArg;
- u8 argType; /* ff: db 1: 0, 2: 1, 3: 2,... N: N-1. */
+ u8 argType; /* 1: 0, 2: 1, 3: 2,... N: N-1. */
u8 eTextRep; /* 1: UTF-16. 0: UTF-8 */
u8 needCollSeq;
void (*xFunc)(sqlite3_context*,int,sqlite3_value **);
} aFuncs[] = {
@@ -54938,11 +58461,11 @@
{ "randomblob", 1, 0, SQLITE_UTF8, 0, randomBlob },
{ "nullif", 2, 0, SQLITE_UTF8, 1, nullifFunc },
{ "sqlite_version", 0, 0, SQLITE_UTF8, 0, versionFunc},
{ "quote", 1, 0, SQLITE_UTF8, 0, quoteFunc },
- { "last_insert_rowid", 0, 0xff, SQLITE_UTF8, 0, last_insert_rowid },
- { "changes", 0, 0xff, SQLITE_UTF8, 0, changes },
- { "total_changes", 0, 0xff, SQLITE_UTF8, 0, total_changes },
+ { "last_insert_rowid", 0, 0, SQLITE_UTF8, 0, last_insert_rowid },
+ { "changes", 0, 0, SQLITE_UTF8, 0, changes },
+ { "total_changes", 0, 0, SQLITE_UTF8, 0, total_changes },
{ "replace", 3, 0, SQLITE_UTF8, 0, replaceFunc },
{ "ltrim", 1, 1, SQLITE_UTF8, 0, trimFunc },
{ "ltrim", 2, 1, SQLITE_UTF8, 0, trimFunc },
{ "rtrim", 1, 2, SQLITE_UTF8, 0, trimFunc },
@@ -54953,17 +58476,10 @@
#ifdef SQLITE_SOUNDEX
{ "soundex", 1, 0, SQLITE_UTF8, 0, soundexFunc},
#endif
#ifndef SQLITE_OMIT_LOAD_EXTENSION
- { "load_extension", 1, 0xff, SQLITE_UTF8, 0, loadExt },
- { "load_extension", 2, 0xff, SQLITE_UTF8, 0, loadExt },
-#endif
-#ifdef SQLITE_TEST
- { "randstr", 2, 0, SQLITE_UTF8, 0, randStr },
- { "test_destructor", 1, 0xff, SQLITE_UTF8, 0, test_destructor},
- { "test_destructor_count", 0, 0, SQLITE_UTF8, 0, test_destructor_count},
- { "test_auxdata", -1, 0, SQLITE_UTF8, 0, test_auxdata},
- { "test_error", 1, 0, SQLITE_UTF8, 0, test_error},
+ { "load_extension", 1, 0, SQLITE_UTF8, 0, loadExt },
+ { "load_extension", 2, 0, SQLITE_UTF8, 0, loadExt },
#endif
};
static const struct {
char *zName;
@@ -54987,13 +58503,9 @@
for(i=0; i<sizeof(aFuncs)/sizeof(aFuncs[0]); i++){
void *pArg;
u8 argType = aFuncs[i].argType;
- if( argType==0xff ){
- pArg = db;
- }else{
- pArg = (void*)(int)argType;
- }
+ pArg = (void*)(int)argType;
sqlite3CreateFunc(db, aFuncs[i].zName, aFuncs[i].nArg,
aFuncs[i].eTextRep, pArg, aFuncs[i].xFunc, 0, 0);
if( aFuncs[i].needCollSeq ){
FuncDef *pFunc = sqlite3FindFunction(db, aFuncs[i].zName,
@@ -55119,9 +58631,9 @@
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle INSERT statements in SQLite.
**
-** $Id: insert.c,v 1.228 2008/01/25 15:04:50 drh Exp $
+** $Id: insert.c,v 1.238 2008/04/28 18:46:43 drh Exp $
*/
/*
** Set P4 of the most recently inserted opcode to a column affinity
@@ -55151,9 +58663,9 @@
*/
int n;
Table *pTab = pIdx->pTable;
sqlite3 *db = sqlite3VdbeDb(v);
- pIdx->zColAff = (char *)sqlite3DbMallocZero(db, pIdx->nColumn+2);
+ pIdx->zColAff = (char *)sqlite3DbMallocRaw(db, pIdx->nColumn+2);
if( !pIdx->zColAff ){
return;
}
for(n=0; n<pIdx->nColumn; n++){
@@ -55192,9 +58704,9 @@
char *zColAff;
int i;
sqlite3 *db = sqlite3VdbeDb(v);
- zColAff = (char *)sqlite3DbMallocZero(db, pTab->nCol+1);
+ zColAff = (char *)sqlite3DbMallocRaw(db, pTab->nCol+1);
if( !zColAff ){
return;
}
@@ -55324,16 +58836,17 @@
int iCur = pParse->nTab;
Vdbe *v = pParse->pVdbe;
Db *pDb = &pParse->db->aDb[iDb];
int j1;
+ int iRec = ++pParse->nMem; /* Memory cell used for record */
assert( v );
sqlite3OpenTable(pParse, iCur, iDb, pDb->pSchema->pSeqTab, OP_OpenWrite);
j1 = sqlite3VdbeAddOp1(v, OP_NotNull, memId+1);
sqlite3VdbeAddOp2(v, OP_NewRowid, iCur, memId+1);
sqlite3VdbeJumpHere(v, j1);
- sqlite3VdbeAddOp3(v, OP_MakeRecord, memId-1, 2, memId-1);
- sqlite3VdbeAddOp3(v, OP_Insert, iCur, memId-1, memId+1);
+ sqlite3VdbeAddOp3(v, OP_MakeRecord, memId-1, 2, iRec);
+ sqlite3VdbeAddOp3(v, OP_Insert, iCur, iRec, memId+1);
sqlite3VdbeChangeP5(v, OPFLAG_APPEND);
sqlite3VdbeAddOp1(v, OP_Close, iCur);
}
}
@@ -55642,10 +59155,9 @@
** of the program jumps to it. Create the temporary table, then jump
** back up and execute the SELECT code above.
*/
sqlite3VdbeJumpHere(v, iInitCode);
- sqlite3VdbeAddOp2(v, OP_OpenEphemeral, srcTab, 0);
- sqlite3VdbeAddOp2(v, OP_SetNumColumns, srcTab, nColumn);
+ sqlite3VdbeAddOp2(v, OP_OpenEphemeral, srcTab, nColumn);
sqlite3VdbeAddOp2(v, OP_Goto, 0, iSelectLoop);
sqlite3VdbeResolveLabel(v, iCleanup);
}else{
sqlite3VdbeJumpHere(v, iInitCode);
@@ -55734,10 +59246,10 @@
/* Open the temp table for FOR EACH ROW triggers
*/
if( triggers_exist ){
- sqlite3VdbeAddOp2(v, OP_OpenPseudo, newIdx, 0);
- sqlite3VdbeAddOp2(v, OP_SetNumColumns, newIdx, pTab->nCol);
+ sqlite3VdbeAddOp2(v, OP_SetNumColumns, 0, pTab->nCol);
+ sqlite3VdbeAddOp2(v, OP_OpenPseudo, newIdx, 0);
}
/* Initialize the count of rows to be inserted
*/
@@ -55752,9 +59264,9 @@
int i;
baseCur = pParse->nTab;
nIdx = sqlite3OpenTableAndIndices(pParse, pTab, baseCur, OP_OpenWrite);
- aRegIdx = sqlite3DbMallocZero(db, sizeof(int)*(nIdx+1));
+ aRegIdx = sqlite3DbMallocRaw(db, sizeof(int)*(nIdx+1));
if( aRegIdx==0 ){
goto insert_cleanup;
}
for(i=0; i<nIdx; i++){
@@ -55952,9 +59464,9 @@
** do the insertion.
*/
#ifndef SQLITE_OMIT_VIRTUALTABLE
if( IsVirtual(pTab) ){
- pParse->pVirtualLock = pTab;
+ sqlite3VtabMakeWritable(pParse, pTab);
sqlite3VdbeAddOp4(v, OP_VUpdate, 1, pTab->nCol+2, regIns,
(const char*)pTab->pVtab, P4_VTAB);
}else
#endif
@@ -56277,8 +59789,9 @@
}
sqlite3VdbeAddOp2(v, OP_SCopy, regRowid, regIdx+i);
sqlite3VdbeAddOp3(v, OP_MakeRecord, regIdx, pIdx->nColumn+1, aRegIdx[iCur]);
sqlite3IndexAffinityStr(v, pIdx);
+ sqlite3ExprCacheAffinityChange(pParse, regIdx, pIdx->nColumn+1);
sqlite3ReleaseTempRange(pParse, regIdx, pIdx->nColumn+1);
/* Find out what action to take in case there is an indexing conflict */
onError = pIdx->onError;
@@ -56298,9 +59811,10 @@
j2 = sqlite3VdbeAddOp3(v, OP_IsNull, regIdx, 0, pIdx->nColumn);
regR = sqlite3GetTempReg(pParse);
sqlite3VdbeAddOp2(v, OP_SCopy, regRowid-hasTwoRowids, regR);
j3 = sqlite3VdbeAddOp4(v, OP_IsUnique, baseCur+iCur+1, 0,
- regR, (char*)aRegIdx[iCur], P4_INT32);
+ regR, (char*)aRegIdx[iCur],
+ P4_INT32);
/* Generate code that executes if the new index entry is not unique */
assert( onError==OE_Rollback || onError==OE_Abort || onError==OE_Fail
|| onError==OE_Ignore || onError==OE_Replace );
@@ -56390,8 +59904,9 @@
regData = regRowid + 1;
regRec = sqlite3GetTempReg(pParse);
sqlite3VdbeAddOp3(v, OP_MakeRecord, regData, pTab->nCol, regRec);
sqlite3TableAffinityStr(v, pTab);
+ sqlite3ExprCacheAffinityChange(pParse, regData, pTab->nCol);
#ifndef SQLITE_OMIT_TRIGGER
if( newIdx>=0 ){
sqlite3VdbeAddOp3(v, OP_Insert, newIdx, regRec, regRowid);
}
@@ -56768,8 +60283,13 @@
}
}
#endif /* SQLITE_OMIT_XFER_OPT */
+/* Make sure "isView" gets undefined in case this file becomes part of
+** the amalgamation - so that subsequent files do not see isView as a
+** macro. */
+#undef isView
+
/************** End of insert.c **********************************************/
/************** Begin file legacy.c ******************************************/
/*
** 2001 September 15
@@ -56786,9 +60306,9 @@
** implement the programmer interface to the library. Routines in
** other files are for internal use by SQLite and should not be
** accessed by users of the library.
**
-** $Id: legacy.c,v 1.22 2007/08/29 12:31:26 danielk1977 Exp $
+** $Id: legacy.c,v 1.24 2008/03/21 18:01:14 drh Exp $
*/
/*
@@ -56835,14 +60355,9 @@
continue;
}
nCallback = 0;
-
- nCol = sqlite3_column_count(pStmt);
- azCols = sqlite3DbMallocZero(db, 2*nCol*sizeof(const char *) + 1);
- if( azCols==0 ){
- goto exec_out;
- }
+ nCol = sqlite3_column_count(pStmt);
while( 1 ){
int i;
rc = sqlite3_step(pStmt);
@@ -56850,17 +60365,31 @@
/* Invoke the callback function if required */
if( xCallback && (SQLITE_ROW==rc ||
(SQLITE_DONE==rc && !nCallback && db->flags&SQLITE_NullCallback)) ){
if( 0==nCallback ){
+ if( azCols==0 ){
+ azCols = sqlite3DbMallocZero(db, 2*nCol*sizeof(const char*) + 1);
+ if( azCols==0 ){
+ goto exec_out;
+ }
+ }
for(i=0; i<nCol; i++){
azCols[i] = (char *)sqlite3_column_name(pStmt, i);
+ if( !azCols[i] ){
+ db->mallocFailed = 1;
+ goto exec_out;
+ }
}
nCallback++;
}
if( rc==SQLITE_ROW ){
azVals = &azCols[nCol];
for(i=0; i<nCol; i++){
azVals[i] = (char *)sqlite3_column_text(pStmt, i);
+ if( !azVals[i] && sqlite3_column_type(pStmt, i)!=SQLITE_NULL ){
+ db->mallocFailed = 1;
+ goto exec_out;
+ }
}
}
if( xCallback(pArg, nCol, azVals, azCols) ){
rc = SQLITE_ABORT;
@@ -56919,9 +60448,8 @@
*************************************************************************
** This file contains code used to dynamically load extensions into
** the SQLite library.
*/
-#ifndef SQLITE_OMIT_LOAD_EXTENSION
#ifndef SQLITE_CORE
#define SQLITE_CORE 1 /* Disable the API redefinition in sqlite3ext.h */
#endif
@@ -56943,23 +60471,23 @@
** an SQLite instance. Shared libraries that intend to be loaded
** as extensions by SQLite should #include this file instead of
** sqlite3.h.
**
-** @(#) $Id: sqlite3ext.h,v 1.17 2007/08/31 16:11:36 drh Exp $
+** @(#) $Id: sqlite3ext.h,v 1.21 2008/03/19 21:45:51 drh Exp $
*/
#ifndef _SQLITE3EXT_H_
#define _SQLITE3EXT_H_
typedef struct sqlite3_api_routines sqlite3_api_routines;
/*
-** The following structure hold pointers to all of the SQLite API
+** The following structure holds pointers to all of the SQLite API
** routines.
**
** WARNING: In order to maintain backwards compatibility, add new
** interfaces to the end of this structure only. If you insert new
** interfaces in the middle of this structure, then older different
-** versions of SQLite will not be able to load each others shared
+** versions of SQLite will not be able to load each others' shared
** libraries!
*/
struct sqlite3_api_routines {
void * (*aggregate_context)(sqlite3_context*,int nBytes);
@@ -57109,8 +60637,14 @@
void (*soft_heap_limit)(int);
sqlite3_vfs *(*vfs_find)(const char*);
int (*vfs_register)(sqlite3_vfs*,int);
int (*vfs_unregister)(sqlite3_vfs*);
+ int (*xthreadsafe)(void);
+ void (*result_zeroblob)(sqlite3_context*,int);
+ void (*result_error_code)(sqlite3_context*,int);
+ int (*test_control)(int, ...);
+ void (*randomness)(int,void*);
+ sqlite3 *(*context_db_handle)(sqlite3_context*);
};
/*
** The following macros redefine the API routines so that they are
@@ -57269,8 +60803,14 @@
#define sqlite3_soft_heap_limit sqlite3_api->soft_heap_limit
#define sqlite3_vfs_find sqlite3_api->vfs_find
#define sqlite3_vfs_register sqlite3_api->vfs_register
#define sqlite3_vfs_unregister sqlite3_api->vfs_unregister
+#define sqlite3_threadsafe sqlite3_api->xthreadsafe
+#define sqlite3_result_zeroblob sqlite3_api->result_zeroblob
+#define sqlite3_result_error_code sqlite3_api->result_error_code
+#define sqlite3_test_control sqlite3_api->test_control
+#define sqlite3_randomness sqlite3_api->randomness
+#define sqlite3_context_db_handle sqlite3_api->context_db_handle
#endif /* SQLITE_CORE */
#define SQLITE_EXTENSION_INIT1 const sqlite3_api_routines *sqlite3_api;
#define SQLITE_EXTENSION_INIT2(v) sqlite3_api = v;
@@ -57278,8 +60818,10 @@
#endif /* _SQLITE3EXT_H_ */
/************** End of sqlite3ext.h ******************************************/
/************** Continuing where we left off in loadext.c ********************/
+
+#ifndef SQLITE_OMIT_LOAD_EXTENSION
/*
** Some API routines are omitted when various features are
** excluded from a build of SQLite. Substitute a NULL pointer
@@ -57376,9 +60918,9 @@
** intend to use is supported by the library. Extensions should
** also check to make sure that the pointer to the function is
** not NULL before calling it.
*/
-SQLITE_API const sqlite3_api_routines sqlite3_apis = {
+static const sqlite3_api_routines sqlite3Apis = {
sqlite3_aggregate_context,
sqlite3_aggregate_count,
sqlite3_bind_blob,
sqlite3_bind_double,
@@ -57549,8 +61091,18 @@
sqlite3_soft_heap_limit,
sqlite3_vfs_find,
sqlite3_vfs_register,
sqlite3_vfs_unregister,
+
+ /*
+ ** Added for 3.5.8
+ */
+ sqlite3_threadsafe,
+ sqlite3_result_zeroblob,
+ sqlite3_result_error_code,
+ sqlite3_test_control,
+ sqlite3_randomness,
+ sqlite3_context_db_handle,
};
/*
** Attempt to load an SQLite extension library contained in the file
@@ -57617,9 +61169,9 @@
*pzErrMsg = sqlite3DbStrDup(db, zErr);
sqlite3OsDlClose(pVfs, handle);
}
return SQLITE_ERROR;
- }else if( xInit(db, &zErrmsg, &sqlite3_apis) ){
+ }else if( xInit(db, &zErrmsg, &sqlite3Apis) ){
if( pzErrMsg ){
*pzErrMsg = sqlite3_mprintf("error during initialization: %s", zErrmsg);
}
sqlite3_free(zErrmsg);
@@ -57682,8 +61234,21 @@
sqlite3_mutex_leave(db->mutex);
return SQLITE_OK;
}
+#endif /* SQLITE_OMIT_LOAD_EXTENSION */
+
+/*
+** The auto-extension code added regardless of whether or not extension
+** loading is supported. We need a dummy sqlite3Apis pointer for that
+** code if regular extension loading is not available. This is that
+** dummy pointer.
+*/
+#ifdef SQLITE_OMIT_LOAD_EXTENSION
+static const sqlite3_api_routines sqlite3Apis = { 0 };
+#endif
+
+
/*
** The following object holds the list of automatically loaded
** extensions.
**
@@ -57702,9 +61267,11 @@
*/
SQLITE_API int sqlite3_auto_extension(void *xInit){
int i;
int rc = SQLITE_OK;
+#ifndef SQLITE_MUTEX_NOOP
sqlite3_mutex *mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER);
+#endif
sqlite3_mutex_enter(mutex);
for(i=0; i<autoext.nExt; i++){
if( autoext.aExt[i]==xInit ) break;
}
@@ -57728,9 +61295,11 @@
/*
** Reset the automatic extension loading mechanism.
*/
SQLITE_API void sqlite3_reset_auto_extension(void){
+#ifndef SQLITE_MUTEX_NOOP
sqlite3_mutex *mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER);
+#endif
sqlite3_mutex_enter(mutex);
sqlite3_free(autoext.aExt);
autoext.aExt = 0;
autoext.nExt = 0;
@@ -57751,9 +61320,11 @@
return SQLITE_OK;
}
for(i=0; go; i++){
char *zErrmsg = 0;
+#ifndef SQLITE_MUTEX_NOOP
sqlite3_mutex *mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER);
+#endif
sqlite3_mutex_enter(mutex);
if( i>=autoext.nExt ){
xInit = 0;
go = 0;
@@ -57761,9 +61332,9 @@
xInit = (int(*)(sqlite3*,char**,const sqlite3_api_routines*))
autoext.aExt[i];
}
sqlite3_mutex_leave(mutex);
- if( xInit && xInit(db, &zErrmsg, &sqlite3_apis) ){
+ if( xInit && xInit(db, &zErrmsg, &sqlite3Apis) ){
sqlite3Error(db, SQLITE_ERROR,
"automatic extension loading failed: %s", zErrmsg);
go = 0;
rc = SQLITE_ERROR;
@@ -57771,10 +61342,8 @@
}
}
return rc;
}
-
-#endif /* SQLITE_OMIT_LOAD_EXTENSION */
/************** End of loadext.c *********************************************/
/************** Begin file pragma.c ******************************************/
/*
@@ -57789,9 +61358,9 @@
**
*************************************************************************
** This file contains code used to implement the PRAGMA command.
**
-** $Id: pragma.c,v 1.169 2008/01/22 01:48:09 drh Exp $
+** $Id: pragma.c,v 1.176 2008/04/17 20:59:38 drh Exp $
*/
/* Ignore this whole file if pragmas are disabled
*/
@@ -58126,9 +61695,10 @@
}else{
/* Malloc may fail when setting the page-size, as there is an internal
** buffer that the pager module resizes using sqlite3_realloc().
*/
- if( SQLITE_NOMEM==sqlite3BtreeSetPageSize(pBt, atoi(zRight), -1) ){
+ db->nextPagesize = atoi(zRight);
+ if( SQLITE_NOMEM==sqlite3BtreeSetPageSize(pBt, db->nextPagesize, -1) ){
db->mallocFailed = 1;
}
}
}else
@@ -58197,8 +61767,65 @@
}
sqlite3VdbeSetNumCols(v, 1);
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "locking_mode", P4_STATIC);
sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, zRet, 0);
+ sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1);
+ }else
+
+ /*
+ ** PRAGMA [database.]journal_mode
+ ** PRAGMA [database.]journal_mode = (delete|persist|off)
+ */
+ if( sqlite3StrICmp(zLeft,"journal_mode")==0 ){
+ int eMode;
+ static const char *azModeName[] = {"delete", "persist", "off"};
+
+ if( zRight==0 ){
+ eMode = PAGER_JOURNALMODE_QUERY;
+ }else{
+ int n = strlen(zRight);
+ eMode = 2;
+ while( eMode>=0 && sqlite3StrNICmp(zRight, azModeName[eMode], n)!=0 ){
+ eMode--;
+ }
+ }
+ if( pId2->n==0 && eMode==PAGER_JOURNALMODE_QUERY ){
+ /* Simple "PRAGMA persistent_journal;" statement. This is a query for
+ ** the current default journal mode (which may be different to
+ ** the journal-mode of the main database).
+ */
+ eMode = db->dfltJournalMode;
+ }else{
+ Pager *pPager;
+ if( pId2->n==0 ){
+ /* This indicates that no database name was specified as part
+ ** of the PRAGMA command. In this case the journal-mode must be
+ ** set on all attached databases, as well as the main db file.
+ **
+ ** Also, the sqlite3.dfltJournalMode variable is set so that
+ ** any subsequently attached databases also use the specified
+ ** journal mode.
+ */
+ int ii;
+ assert(pDb==&db->aDb[0]);
+ for(ii=1; ii<db->nDb; ii++){
+ if( db->aDb[ii].pBt ){
+ pPager = sqlite3BtreePager(db->aDb[ii].pBt);
+ sqlite3PagerJournalMode(pPager, eMode);
+ }
+ }
+ db->dfltJournalMode = eMode;
+ }
+ pPager = sqlite3BtreePager(pDb->pBt);
+ eMode = sqlite3PagerJournalMode(pPager, eMode);
+ }
+ assert( eMode==PAGER_JOURNALMODE_DELETE
+ || eMode==PAGER_JOURNALMODE_PERSIST
+ || eMode==PAGER_JOURNALMODE_OFF );
+ sqlite3VdbeSetNumCols(v, 1);
+ sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "journal_mode", P4_STATIC);
+ sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0,
+ azModeName[eMode], P4_STATIC);
sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1);
}else
#endif /* SQLITE_OMIT_PAGER_PRAGMAS */
@@ -58346,9 +61973,9 @@
sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1);
}
}else{
if( zRight[0]
- && !sqlite3OsAccess(db->pVfs, zRight, SQLITE_ACCESS_READWRITE)
+ && sqlite3OsAccess(db->pVfs, zRight, SQLITE_ACCESS_READWRITE)==0
){
sqlite3ErrorMsg(pParse, "not a writable directory");
goto pragma_out;
}
@@ -58670,10 +62297,10 @@
}
if( cnt==0 ) continue;
/* Make sure sufficient number of registers have been allocated */
- if( pParse->nMem < cnt+3 ){
- pParse->nMem = cnt+3;
+ if( pParse->nMem < cnt+4 ){
+ pParse->nMem = cnt+4;
}
/* Do the b-tree integrity checks */
sqlite3VdbeAddOp3(v, OP_IntegrityCk, 2, cnt, 1);
@@ -58681,9 +62308,10 @@
addr = sqlite3VdbeAddOp1(v, OP_IsNull, 2);
sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0,
sqlite3MPrintf(db, "*** in database %s ***\n", db->aDb[i].zName),
P4_DYNAMIC);
- sqlite3VdbeAddOp3(v, OP_Concat, 2, 3, 2);
+ sqlite3VdbeAddOp2(v, OP_Move, 2, 4);
+ sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 2);
sqlite3VdbeAddOp2(v, OP_ResultRow, 2, 1);
sqlite3VdbeJumpHere(v, addr);
/* Make sure all the indices are constructed correctly.
@@ -58712,15 +62340,18 @@
{ OP_Concat, 4, 3, 3},
{ OP_Concat, 5, 3, 3},
{ OP_Concat, 6, 3, 3},
{ OP_ResultRow, 3, 1, 0},
+ { OP_IfPos, 1, 0, 0}, /* 9 */
+ { OP_Halt, 0, 0, 0},
};
- sqlite3GenerateIndexKey(pParse, pIdx, 1, 3);
+ sqlite3GenerateIndexKey(pParse, pIdx, 1, 3, 1);
jmp2 = sqlite3VdbeAddOp3(v, OP_Found, j+2, 0, 3);
addr = sqlite3VdbeAddOpList(v, ArraySize(idxErr), idxErr);
sqlite3VdbeChangeP4(v, addr+1, "rowid ", P4_STATIC);
sqlite3VdbeChangeP4(v, addr+3, " missing from index ", P4_STATIC);
sqlite3VdbeChangeP4(v, addr+4, pIdx->zName, P4_STATIC);
+ sqlite3VdbeJumpHere(v, addr+9);
sqlite3VdbeJumpHere(v, jmp2);
}
sqlite3VdbeAddOp2(v, OP_Next, 1, loopTop+1);
sqlite3VdbeJumpHere(v, loopTop);
@@ -59019,18 +62650,23 @@
** This file contains the implementation of the sqlite3_prepare()
** interface, and routines that contribute to loading the database schema
** from disk.
**
-** $Id: prepare.c,v 1.75 2008/01/23 03:03:05 drh Exp $
+** $Id: prepare.c,v 1.83 2008/04/03 14:36:26 danielk1977 Exp $
*/
/*
** Fill the InitData structure with an error message that indicates
** that the database is corrupt.
*/
-static void corruptSchema(InitData *pData, const char *zExtra){
+static void corruptSchema(
+ InitData *pData, /* Initialization context */
+ const char *zObj, /* Object being parsed at the point of error */
+ const char *zExtra /* Error information */
+){
if( !pData->db->mallocFailed ){
- sqlite3SetString(pData->pzErrMsg, "malformed database schema",
+ if( zObj==0 ) zObj = "?";
+ sqlite3SetString(pData->pzErrMsg, "malformed database schema (", zObj, ")",
zExtra!=0 && zExtra[0]!=0 ? " - " : (char*)0, zExtra, (char*)0);
}
pData->rc = SQLITE_CORRUPT;
}
@@ -59055,16 +62691,16 @@
assert( sqlite3_mutex_held(db->mutex) );
pData->rc = SQLITE_OK;
DbClearProperty(db, iDb, DB_Empty);
if( db->mallocFailed ){
- corruptSchema(pData, 0);
+ corruptSchema(pData, argv[0], 0);
return SQLITE_NOMEM;
}
assert( argc==3 );
if( argv==0 ) return 0; /* Might happen if EMPTY_RESULT_CALLBACKS are on */
if( argv[1]==0 ){
- corruptSchema(pData, 0);
+ corruptSchema(pData, argv[0], 0);
return 1;
}
assert( iDb>=0 && iDb<db->nDb );
if( argv[2] && argv[2][0] ){
@@ -59085,15 +62721,15 @@
pData->rc = rc;
if( rc==SQLITE_NOMEM ){
db->mallocFailed = 1;
}else if( rc!=SQLITE_INTERRUPT ){
- corruptSchema(pData, zErr);
+ corruptSchema(pData, argv[0], zErr);
}
sqlite3_free(zErr);
return 1;
}
}else if( argv[0]==0 ){
- corruptSchema(pData, 0);
+ corruptSchema(pData, 0, 0);
}else{
/* If the SQL column is blank it means this is an index that
** was created to be the PRIMARY KEY or to fulfill a UNIQUE
** constraint for a CREATE TABLE. The index should have already
@@ -59206,14 +62842,18 @@
DbSetProperty(db, 1, DB_SchemaLoaded);
}
return SQLITE_OK;
}
+ curMain = sqlite3MallocZero(sqlite3BtreeCursorSize());
+ if( !curMain ){
+ rc = SQLITE_NOMEM;
+ goto error_out;
+ }
sqlite3BtreeEnter(pDb->pBt);
- rc = sqlite3BtreeCursor(pDb->pBt, MASTER_ROOT, 0, 0, 0, &curMain);
+ rc = sqlite3BtreeCursor(pDb->pBt, MASTER_ROOT, 0, 0, curMain);
if( rc!=SQLITE_OK && rc!=SQLITE_EMPTY ){
sqlite3SetString(pzErrMsg, sqlite3ErrStr(rc), (char*)0);
- sqlite3BtreeLeave(pDb->pBt);
- goto error_out;
+ goto leave_error_out;
}
/* Get the database meta information.
**
@@ -59238,11 +62878,9 @@
rc = sqlite3BtreeGetMeta(pDb->pBt, i+1, (u32 *)&meta[i]);
}
if( rc ){
sqlite3SetString(pzErrMsg, sqlite3ErrStr(rc), (char*)0);
- sqlite3BtreeCloseCursor(curMain);
- sqlite3BtreeLeave(pDb->pBt);
- goto error_out;
+ goto leave_error_out;
}
}else{
memset(meta, 0, sizeof(meta));
}
@@ -59260,13 +62898,12 @@
db->pDfltColl = sqlite3FindCollSeq(db, SQLITE_UTF8, "BINARY", 6, 0);
}else{
/* If opening an attached database, the encoding much match ENC(db) */
if( meta[4]!=ENC(db) ){
- sqlite3BtreeCloseCursor(curMain);
sqlite3SetString(pzErrMsg, "attached databases must use the same"
" text encoding as main database", (char*)0);
- sqlite3BtreeLeave(pDb->pBt);
- return SQLITE_ERROR;
+ rc = SQLITE_ERROR;
+ goto leave_error_out;
}
}
}else{
DbSetProperty(db, iDb, DB_Empty);
@@ -59289,12 +62926,11 @@
if( pDb->pSchema->file_format==0 ){
pDb->pSchema->file_format = 1;
}
if( pDb->pSchema->file_format>SQLITE_MAX_FILE_FORMAT ){
- sqlite3BtreeCloseCursor(curMain);
sqlite3SetString(pzErrMsg, "unsupported file format", (char*)0);
- sqlite3BtreeLeave(pDb->pBt);
- return SQLITE_ERROR;
+ rc = SQLITE_ERROR;
+ goto leave_error_out;
}
/* Ticket #2804: When we open a database in the newer file format,
** clear the legacy_file_format pragma flag so that a VACUUM will
@@ -59335,9 +62971,8 @@
if( rc==SQLITE_OK ){
sqlite3AnalysisLoad(db, iDb);
}
#endif
- sqlite3BtreeCloseCursor(curMain);
}
if( db->mallocFailed ){
/* sqlite3SetString(pzErrMsg, "out of memory", (char*)0); */
rc = SQLITE_NOMEM;
@@ -59354,8 +62989,16 @@
*/
DbSetProperty(db, iDb, DB_SchemaLoaded);
rc = SQLITE_OK;
}
+
+ /* Jump here for an error that occurs after successfully allocating
+ ** curMain and calling sqlite3BtreeEnter(). For an error that occurs
+ ** before that point, jump to error_out.
+ */
+leave_error_out:
+ sqlite3BtreeCloseCursor(curMain);
+ sqlite3_free(curMain);
sqlite3BtreeLeave(pDb->pBt);
error_out:
if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){
@@ -59440,25 +63083,34 @@
BtCursor *curTemp;
int cookie;
int allOk = 1;
- assert( sqlite3_mutex_held(db->mutex) );
- for(iDb=0; allOk && iDb<db->nDb; iDb++){
- Btree *pBt;
- pBt = db->aDb[iDb].pBt;
- if( pBt==0 ) continue;
- rc = sqlite3BtreeCursor(pBt, MASTER_ROOT, 0, 0, 0, &curTemp);
- if( rc==SQLITE_OK ){
- rc = sqlite3BtreeGetMeta(pBt, 1, (u32 *)&cookie);
- if( rc==SQLITE_OK && cookie!=db->aDb[iDb].pSchema->schema_cookie ){
- allOk = 0;
- }
- sqlite3BtreeCloseCursor(curTemp);
- }
- if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){
- db->mallocFailed = 1;
- }
- }
+ curTemp = (BtCursor *)sqlite3_malloc(sqlite3BtreeCursorSize());
+ if( curTemp ){
+ assert( sqlite3_mutex_held(db->mutex) );
+ for(iDb=0; allOk && iDb<db->nDb; iDb++){
+ Btree *pBt;
+ pBt = db->aDb[iDb].pBt;
+ if( pBt==0 ) continue;
+ memset(curTemp, 0, sqlite3BtreeCursorSize());
+ rc = sqlite3BtreeCursor(pBt, MASTER_ROOT, 0, 0, curTemp);
+ if( rc==SQLITE_OK ){
+ rc = sqlite3BtreeGetMeta(pBt, 1, (u32 *)&cookie);
+ if( rc==SQLITE_OK && cookie!=db->aDb[iDb].pSchema->schema_cookie ){
+ allOk = 0;
+ }
+ sqlite3BtreeCloseCursor(curTemp);
+ }
+ if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){
+ db->mallocFailed = 1;
+ }
+ }
+ sqlite3_free(curTemp);
+ }else{
+ allOk = 0;
+ db->mallocFailed = 1;
+ }
+
return allOk;
}
/*
@@ -59495,9 +63147,9 @@
/*
** Compile the UTF-8 encoded SQL statement zSql into a statement handle.
*/
-SQLITE_PRIVATE int sqlite3Prepare(
+static int sqlite3Prepare(
sqlite3 *db, /* Database handle. */
const char *zSql, /* UTF-8 encoded SQL statement. */
int nBytes, /* Length of zSql in bytes. */
int saveSqlFlag, /* True to copy SQL text into the sqlite3_stmt */
@@ -59535,11 +63187,12 @@
}
memset(&sParse, 0, sizeof(sParse));
sParse.db = db;
- if( nBytes>=0 && zSql[nBytes]!=0 ){
+ if( nBytes>=0 && zSql[nBytes-1]!=0 ){
char *zSqlCopy;
- if( SQLITE_MAX_SQL_LENGTH>0 && nBytes>SQLITE_MAX_SQL_LENGTH ){
+ int mxLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH];
+ if( nBytes>mxLen ){
sqlite3Error(db, SQLITE_TOOBIG, "statement too long");
(void)sqlite3SafetyOff(db);
return SQLITE_TOOBIG;
}
@@ -59546,10 +63199,12 @@
zSqlCopy = sqlite3DbStrNDup(db, zSql, nBytes);
if( zSqlCopy ){
sqlite3RunParser(&sParse, zSqlCopy, &zErrMsg);
sqlite3_free(zSqlCopy);
- }
- sParse.zTail = &zSql[nBytes];
+ sParse.zTail = &zSql[sParse.zTail-zSqlCopy];
+ }else{
+ sParse.zTail = &zSql[nBytes];
+ }
}else{
sqlite3RunParser(&sParse, zSql, &zErrMsg);
}
@@ -59685,9 +63340,12 @@
int nBytes, /* Length of zSql in bytes. */
sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */
const char **pzTail /* OUT: End of parsed string */
){
- return sqlite3LockAndPrepare(db,zSql,nBytes,0,ppStmt,pzTail);
+ int rc;
+ rc = sqlite3LockAndPrepare(db,zSql,nBytes,0,ppStmt,pzTail);
+ assert( rc==SQLITE_OK || ppStmt==0 || *ppStmt==0 ); /* VERIFY: F13021 */
+ return rc;
}
SQLITE_API int sqlite3_prepare_v2(
sqlite3 *db, /* Database handle. */
const char *zSql, /* UTF-8 encoded SQL statement. */
@@ -59694,9 +63352,12 @@
int nBytes, /* Length of zSql in bytes. */
sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */
const char **pzTail /* OUT: End of parsed string */
){
- return sqlite3LockAndPrepare(db,zSql,nBytes,1,ppStmt,pzTail);
+ int rc;
+ rc = sqlite3LockAndPrepare(db,zSql,nBytes,1,ppStmt,pzTail);
+ assert( rc==SQLITE_OK || ppStmt==0 || *ppStmt==0 ); /* VERIFY: F13021 */
+ return rc;
}
#ifndef SQLITE_OMIT_UTF16
@@ -59757,9 +63418,12 @@
int nBytes, /* Length of zSql in bytes. */
sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */
const void **pzTail /* OUT: End of parsed string */
){
- return sqlite3Prepare16(db,zSql,nBytes,0,ppStmt,pzTail);
+ int rc;
+ rc = sqlite3Prepare16(db,zSql,nBytes,0,ppStmt,pzTail);
+ assert( rc==SQLITE_OK || ppStmt==0 || *ppStmt==0 ); /* VERIFY: F13021 */
+ return rc;
}
SQLITE_API int sqlite3_prepare16_v2(
sqlite3 *db, /* Database handle. */
const void *zSql, /* UTF-8 encoded SQL statement. */
@@ -59766,9 +63430,12 @@
int nBytes, /* Length of zSql in bytes. */
sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */
const void **pzTail /* OUT: End of parsed string */
){
- return sqlite3Prepare16(db,zSql,nBytes,1,ppStmt,pzTail);
+ int rc;
+ rc = sqlite3Prepare16(db,zSql,nBytes,1,ppStmt,pzTail);
+ assert( rc==SQLITE_OK || ppStmt==0 || *ppStmt==0 ); /* VERIFY: F13021 */
+ return rc;
}
#endif /* SQLITE_OMIT_UTF16 */
@@ -59787,9 +63454,9 @@
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle SELECT statements in SQLite.
**
-** $Id: select.c,v 1.411 2008/01/25 15:04:50 drh Exp $
+** $Id: select.c,v 1.429 2008/05/01 17:03:49 drh Exp $
*/
/*
@@ -59815,8 +63482,9 @@
pDest->eDest = eDest;
pDest->iParm = iParm;
pDest->affinity = 0;
pDest->iMem = 0;
+ pDest->nMem = 0;
}
/*
@@ -59978,14 +63646,32 @@
**
** {a"bc} -> {"a""bc"}
*/
static void setQuotedToken(Parse *pParse, Token *p, const char *z){
- p->z = (u8 *)sqlite3MPrintf(0, "\"%w\"", z);
- p->dyn = 1;
- if( p->z ){
- p->n = strlen((char *)p->z);
- }else{
- pParse->db->mallocFailed = 1;
+
+ /* Check if the string contains any " characters. If it does, then
+ ** this function will malloc space to create a quoted version of
+ ** the string in. Otherwise, save a call to sqlite3MPrintf() by
+ ** just copying the pointer to the string.
+ */
+ const char *z2 = z;
+ while( *z2 ){
+ if( *z2=='"' ) break;
+ z2++;
+ }
+
+ if( *z2 ){
+ /* String contains " characters - copy and quote the string. */
+ p->z = (u8 *)sqlite3MPrintf(pParse->db, "\"%w\"", z);
+ if( p->z ){
+ p->n = strlen((char *)p->z);
+ p->dyn = 1;
+ }
+ }else{
+ /* String contains no " characters - copy the pointer. */
+ p->z = (u8*)z;
+ p->n = (z2 - z);
+ p->dyn = 0;
}
}
/*
@@ -59995,9 +63681,8 @@
Token dummy;
setToken(&dummy, zName);
return sqlite3PExpr(pParse, TK_ID, 0, 0, &dummy);
}
-
/*
** Add a term to the WHERE expression in *ppExpr that requires the
** zCol column to be equal in the two tables pTab1 and pTab2.
@@ -60009,9 +63694,10 @@
const char *zAlias1, /* Alias for first table. May be NULL */
const Table *pTab2, /* Second table */
const char *zAlias2, /* Alias for second table. May be NULL */
int iRightJoinTable, /* VDBE cursor for the right table */
- Expr **ppExpr /* Add the equality term to this expression */
+ Expr **ppExpr, /* Add the equality term to this expression */
+ int isOuterJoin /* True if dealing with an OUTER join */
){
Expr *pE1a, *pE1b, *pE1c;
Expr *pE2a, *pE2b, *pE2c;
Expr *pE;
@@ -60028,9 +63714,9 @@
pE2b = sqlite3CreateIdExpr(pParse, zAlias2);
pE1c = sqlite3PExpr(pParse, TK_DOT, pE1b, pE1a, 0);
pE2c = sqlite3PExpr(pParse, TK_DOT, pE2b, pE2a, 0);
pE = sqlite3PExpr(pParse, TK_EQ, pE1c, pE2c, 0);
- if( pE ){
+ if( pE && isOuterJoin ){
ExprSetProperty(pE, EP_FromJoin);
pE->iRightJoinTable = iRightJoinTable;
}
*ppExpr = sqlite3ExprAnd(pParse->db,*ppExpr, pE);
@@ -60096,10 +63782,12 @@
pRight = &pLeft[1];
for(i=0; i<pSrc->nSrc-1; i++, pRight++, pLeft++){
Table *pLeftTab = pLeft->pTab;
Table *pRightTab = pRight->pTab;
+ int isOuter;
if( pLeftTab==0 || pRightTab==0 ) continue;
+ isOuter = (pRight->jointype & JT_OUTER)!=0;
/* When the NATURAL keyword is present, add WHERE clause terms for
** every column that the two tables have in common.
*/
@@ -60113,9 +63801,9 @@
char *zName = pLeftTab->aCol[j].zName;
if( columnIndex(pRightTab, zName)>=0 ){
addWhereTerm(pParse, zName, pLeftTab, pLeft->zAlias,
pRightTab, pRight->zAlias,
- pRight->iCursor, &p->pWhere);
+ pRight->iCursor, &p->pWhere, isOuter);
}
}
}
@@ -60131,9 +63819,9 @@
/* Add the ON clause to the end of the WHERE clause, connected by
** an AND operator.
*/
if( pRight->pOn ){
- setJoinExpr(pRight->pOn, pRight->iCursor);
+ if( isOuter ) setJoinExpr(pRight->pOn, pRight->iCursor);
p->pWhere = sqlite3ExprAnd(pParse->db, p->pWhere, pRight->pOn);
pRight->pOn = 0;
}
@@ -60154,9 +63842,9 @@
return 1;
}
addWhereTerm(pParse, zName, pLeftTab, pLeft->zAlias,
pRightTab, pRight->zAlias,
- pRight->iCursor, &p->pWhere);
+ pRight->iCursor, &p->pWhere, isOuter);
}
}
}
return 0;
@@ -60175,11 +63863,11 @@
Vdbe *v = pParse->pVdbe;
int nExpr = pOrderBy->nExpr;
int regBase = sqlite3GetTempRange(pParse, nExpr+2);
int regRecord = sqlite3GetTempReg(pParse);
- sqlite3ExprCodeExprList(pParse, pOrderBy, regBase);
+ sqlite3ExprCodeExprList(pParse, pOrderBy, regBase, 0);
sqlite3VdbeAddOp2(v, OP_Sequence, pOrderBy->iECursor, regBase+nExpr);
- sqlite3VdbeAddOp2(v, OP_Move, regData, regBase+nExpr+1);
+ sqlite3ExprCodeMove(pParse, regData, regBase+nExpr+1);
sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nExpr + 2, regRecord);
sqlite3VdbeAddOp2(v, OP_IdxInsert, pOrderBy->iECursor, regRecord);
sqlite3ReleaseTempReg(pParse, regRecord);
sqlite3ReleaseTempRange(pParse, regBase, nExpr+2);
@@ -60296,9 +63984,8 @@
int regResult; /* Start of memory holding result set */
int eDest = pDest->eDest; /* How to dispose of results */
int iParm = pDest->iParm; /* First argument to disposal method */
int nResultCol; /* Number of result columns */
- int nToFree; /* Number of result columns to release */
if( v==0 ) return;
assert( pEList!=0 );
@@ -60316,15 +64003,18 @@
nResultCol = nColumn;
}else{
nResultCol = pEList->nExpr;
}
- if( pDest->iMem>0 ){
- regResult = pDest->iMem;
- nToFree = 0;
- }else{
- pDest->iMem = regResult = sqlite3GetTempRange(pParse, nResultCol);
- nToFree = nResultCol;
- }
+ if( pDest->iMem==0 ){
+ pDest->iMem = sqlite3GetTempRange(pParse, nResultCol);
+ pDest->nMem = nResultCol;
+ }else if( pDest->nMem!=nResultCol ){
+ /* This happens when two SELECTs of a compound SELECT have differing
+ ** numbers of result columns. The error message will be generated by
+ ** a higher-level routine. */
+ return;
+ }
+ regResult = pDest->iMem;
if( nColumn>0 ){
for(i=0; i<nColumn; i++){
sqlite3VdbeAddOp3(v, OP_Column, srcTab, i, regResult+i);
}
@@ -60331,11 +64021,9 @@
}else if( eDest!=SRT_Exists ){
/* If the destination is an EXISTS(...) expression, the actual
** values returned by the SELECT are not required.
*/
- for(i=0; i<nResultCol; i++){
- sqlite3ExprCode(pParse, pEList->a[i].pExpr, regResult+i);
- }
+ sqlite3ExprCodeExprList(pParse, pEList, regResult, eDest==SRT_Callback);
}
nColumn = nResultCol;
/* If the DISTINCT keyword was present on the SELECT statement
@@ -60376,14 +64064,9 @@
** saving that record, use it as a key to delete elements from
** the temporary table iParm.
*/
case SRT_Except: {
- int r1;
- r1 = sqlite3GetTempReg(pParse);
- sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nColumn, r1);
- sqlite3VdbeChangeP4(v, -1, aff, P4_STATIC);
- sqlite3VdbeAddOp2(v, OP_IdxDelete, iParm, r1);
- sqlite3ReleaseTempReg(pParse, r1);
+ sqlite3VdbeAddOp3(v, OP_IdxDelete, iParm, regResult, nColumn);
break;
}
#endif
@@ -60425,8 +64108,9 @@
pushOntoSorter(pParse, pOrderBy, p, regResult);
}else{
int r1 = sqlite3GetTempReg(pParse);
sqlite3VdbeAddOp4(v, OP_MakeRecord, regResult, 1, r1, &p->affinity, 1);
+ sqlite3ExprCacheAffinityChange(pParse, regResult, 1);
sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, r1);
sqlite3ReleaseTempReg(pParse, r1);
}
sqlite3VdbeJumpHere(v, addr2);
@@ -60449,9 +64133,9 @@
assert( nColumn==1 );
if( pOrderBy ){
pushOntoSorter(pParse, pOrderBy, p, regResult);
}else{
- sqlite3VdbeAddOp2(v, OP_Move, regResult, iParm);
+ sqlite3ExprCodeMove(pParse, regResult, iParm);
/* The LIMIT clause will jump out of the loop for us */
}
break;
}
@@ -60468,12 +64152,12 @@
sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nColumn, r1);
pushOntoSorter(pParse, pOrderBy, p, r1);
sqlite3ReleaseTempReg(pParse, r1);
}else if( eDest==SRT_Subroutine ){
- nToFree = 0; /* Preserve registers. Subroutine will need them. */
sqlite3VdbeAddOp2(v, OP_Gosub, 0, iParm);
}else{
sqlite3VdbeAddOp2(v, OP_ResultRow, regResult, nColumn);
+ sqlite3ExprCacheAffinityChange(pParse, regResult, nColumn);
}
break;
}
@@ -60495,9 +64179,8 @@
if( p->iLimit>=0 && pOrderBy==0 ){
sqlite3VdbeAddOp2(v, OP_AddImm, p->iLimit, -1);
sqlite3VdbeAddOp2(v, OP_IfZero, p->iLimit, iBreak);
}
- sqlite3ReleaseTempRange(pParse, regResult, nToFree);
}
/*
** Given an expression list, generate a KeyInfo structure that records
@@ -60569,10 +64252,10 @@
iTab = pOrderBy->iECursor;
if( eDest==SRT_Callback || eDest==SRT_Subroutine ){
pseudoTab = pParse->nTab++;
- sqlite3VdbeAddOp2(v, OP_OpenPseudo, pseudoTab, 0);
- sqlite3VdbeAddOp2(v, OP_SetNumColumns, pseudoTab, nColumn);
+ sqlite3VdbeAddOp2(v, OP_SetNumColumns, 0, nColumn);
+ sqlite3VdbeAddOp2(v, OP_OpenPseudo, pseudoTab, eDest==SRT_Callback);
}
addr = 1 + sqlite3VdbeAddOp2(v, OP_Sort, iTab, brk);
codeOffset(v, p, cont);
regRow = sqlite3GetTempReg(pParse);
@@ -60590,16 +64273,17 @@
case SRT_Set: {
int j1;
assert( nColumn==1 );
j1 = sqlite3VdbeAddOp1(v, OP_IsNull, regRow);
- sqlite3VdbeAddOp4(v, OP_MakeRecord, regRow, 1, regRow, &p->affinity, 1);
- sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, regRow);
+ sqlite3VdbeAddOp4(v, OP_MakeRecord, regRow, 1, regRowid, &p->affinity, 1);
+ sqlite3ExprCacheAffinityChange(pParse, regRow, 1);
+ sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, regRowid);
sqlite3VdbeJumpHere(v, j1);
break;
}
case SRT_Mem: {
assert( nColumn==1 );
- sqlite3VdbeAddOp2(v, OP_Move, regRow, iParm);
+ sqlite3ExprCodeMove(pParse, regRow, iParm);
/* The LIMIT clause will terminate the loop for us */
break;
}
#endif
@@ -60608,12 +64292,14 @@
int i;
sqlite3VdbeAddOp2(v, OP_Integer, 1, regRowid);
sqlite3VdbeAddOp3(v, OP_Insert, pseudoTab, regRow, regRowid);
for(i=0; i<nColumn; i++){
+ assert( regRow!=pDest->iMem+i );
sqlite3VdbeAddOp3(v, OP_Column, pseudoTab, i, pDest->iMem+i);
}
if( eDest==SRT_Callback ){
sqlite3VdbeAddOp2(v, OP_ResultRow, pDest->iMem, nColumn);
+ sqlite3ExprCacheAffinityChange(pParse, pDest->iMem, nColumn);
}else{
sqlite3VdbeAddOp2(v, OP_Gosub, 0, iParm);
}
break;
@@ -60785,29 +64471,36 @@
Parse *pParse, /* Parser context */
SrcList *pTabList, /* List of tables */
ExprList *pEList /* Expressions defining the result set */
){
+#ifndef SQLITE_OMIT_DECLTYPE
Vdbe *v = pParse->pVdbe;
int i;
NameContext sNC;
sNC.pSrcList = pTabList;
sNC.pParse = pParse;
for(i=0; i<pEList->nExpr; i++){
Expr *p = pEList->a[i].pExpr;
+ const char *zType;
+#ifdef SQLITE_ENABLE_COLUMN_METADATA
const char *zOrigDb = 0;
const char *zOrigTab = 0;
const char *zOrigCol = 0;
- const char *zType = columnType(&sNC, p, &zOrigDb, &zOrigTab, &zOrigCol);
+ zType = columnType(&sNC, p, &zOrigDb, &zOrigTab, &zOrigCol);
/* The vdbe must make its own copy of the column-type and other
** column specific strings, in case the schema is reset before this
** virtual machine is deleted.
*/
- sqlite3VdbeSetColName(v, i, COLNAME_DECLTYPE, zType, P4_TRANSIENT);
sqlite3VdbeSetColName(v, i, COLNAME_DATABASE, zOrigDb, P4_TRANSIENT);
sqlite3VdbeSetColName(v, i, COLNAME_TABLE, zOrigTab, P4_TRANSIENT);
sqlite3VdbeSetColName(v, i, COLNAME_COLUMN, zOrigCol, P4_TRANSIENT);
- }
+#else
+ zType = columnType(&sNC, p, 0, 0, 0);
+#endif
+ sqlite3VdbeSetColName(v, i, COLNAME_DECLTYPE, zType, P4_TRANSIENT);
+ }
+#endif /* SQLITE_OMIT_DECLTYPE */
}
/*
** Generate code that will tell the VDBE the names of columns
@@ -61239,12 +64932,14 @@
}
sqlite3ExprListDelete(pEList);
p->pEList = pNew;
}
- if( p->pEList && p->pEList->nExpr>SQLITE_MAX_COLUMN ){
+#if SQLITE_MAX_COLUMN
+ if( p->pEList && p->pEList->nExpr>db->aLimit[SQLITE_LIMIT_COLUMN] ){
sqlite3ErrorMsg(pParse, "too many columns in result set");
rc = SQLITE_ERROR;
}
+#endif
if( db->mallocFailed ){
rc = SQLITE_NOMEM;
}
return rc;
@@ -61369,13 +65064,15 @@
sqlite3 *db = pParse->db;
ExprList *pEList;
if( pOrderBy==0 || pParse->db->mallocFailed ) return 0;
- if( pOrderBy->nExpr>SQLITE_MAX_COLUMN ){
+#if SQLITE_MAX_COLUMN
+ if( pOrderBy->nExpr>db->aLimit[SQLITE_LIMIT_COLUMN] ){
const char *zType = isOrder ? "ORDER" : "GROUP";
sqlite3ErrorMsg(pParse, "too many terms in %s BY clause", zType);
return 1;
}
+#endif
pEList = pSelect->pEList;
if( pEList==0 ){
return 0;
}
@@ -61436,13 +65133,15 @@
int moreToDo = 1;
pOrderBy = pSelect->pOrderBy;
if( pOrderBy==0 ) return 0;
- if( pOrderBy->nExpr>SQLITE_MAX_COLUMN ){
+ db = pParse->db;
+#if SQLITE_MAX_COLUMN
+ if( pOrderBy->nExpr>db->aLimit[SQLITE_LIMIT_COLUMN] ){
sqlite3ErrorMsg(pParse, "too many terms in ORDER BY clause");
return 1;
}
- db = pParse->db;
+#endif
for(i=0; i<pOrderBy->nExpr; i++){
pOrderBy->a[i].done = 0;
}
while( pSelect->pPrior ){
@@ -62040,8 +65739,9 @@
}
multi_select_end:
pDest->iMem = dest.iMem;
+ pDest->nMem = dest.nMem;
return rc;
}
#endif /* SQLITE_OMIT_COMPOUND_SELECT */
@@ -62197,8 +65897,12 @@
** (15) The outer query is not part of a compound select or the
** subquery does not have both an ORDER BY and a LIMIT clause.
** (See ticket #2339)
**
+** (16) The outer query is not an aggregate or the subquery does
+** not contain ORDER BY. (Ticket #2942) This used to not matter
+** until we introduced the group_concat() function.
+**
** In this routine, the "p" parameter is a pointer to the outer query.
** The subquery is p->pSrc->a[iFrom]. isAgg is true if the outer query
** uses aggregates and subqueryIsAgg is true if the subquery uses aggregates.
**
@@ -62254,8 +65958,9 @@
if( p->isDistinct && subqueryIsAgg ) return 0; /* Restriction (6) */
if( (p->disallowOrderBy || p->pOrderBy) && pSub->pOrderBy ){
return 0; /* Restriction (11) */
}
+ if( isAgg && pSub->pOrderBy ) return 0; /* Restriction (16) */
/* Restriction 3: If the subquery is a join, make sure the subquery is
** not used as the right operand of an outer join. Examples of why this
** is not allowed:
@@ -62411,9 +66116,9 @@
#endif /* SQLITE_OMIT_VIEW */
/*
** Analyze the SELECT statement passed as an argument to see if it
-** is a min() or max() query. Return ORDERBY_MIN or ORDERBY_MAX if
+** is a min() or max() query. Return WHERE_ORDERBY_MIN or WHERE_ORDERBY_MAX if
** it is, or 0 otherwise. At present, a query is considered to be
** a min()/max() query if:
**
** 1. There is a single object in the FROM clause.
@@ -62424,20 +66129,20 @@
static int minMaxQuery(Parse *pParse, Select *p){
Expr *pExpr;
ExprList *pEList = p->pEList;
- if( pEList->nExpr!=1 ) return ORDERBY_NORMAL;
+ if( pEList->nExpr!=1 ) return WHERE_ORDERBY_NORMAL;
pExpr = pEList->a[0].pExpr;
pEList = pExpr->pList;
if( pExpr->op!=TK_AGG_FUNCTION || pEList==0 || pEList->nExpr!=1 ) return 0;
- if( pEList->a[0].pExpr->op!=TK_AGG_COLUMN ) return ORDERBY_NORMAL;
- if( pExpr->token.n!=3 ) return ORDERBY_NORMAL;
+ if( pEList->a[0].pExpr->op!=TK_AGG_COLUMN ) return WHERE_ORDERBY_NORMAL;
+ if( pExpr->token.n!=3 ) return WHERE_ORDERBY_NORMAL;
if( sqlite3StrNICmp((char*)pExpr->token.z,"min",3)==0 ){
- return ORDERBY_MIN;
+ return WHERE_ORDERBY_MIN;
}else if( sqlite3StrNICmp((char*)pExpr->token.z,"max",3)==0 ){
- return ORDERBY_MAX;
- }
- return ORDERBY_NORMAL;
+ return WHERE_ORDERBY_MAX;
+ }
+ return WHERE_ORDERBY_NORMAL;
}
/*
** This routine resolves any names used in the result set of the
@@ -62636,9 +66341,9 @@
ExprList *pList = pF->pExpr->pList;
if( pList ){
nArg = pList->nExpr;
regAgg = sqlite3GetTempRange(pParse, nArg);
- sqlite3ExprCodeExprList(pParse, pList, regAgg);
+ sqlite3ExprCodeExprList(pParse, pList, regAgg, 0);
}else{
nArg = 0;
regAgg = 0;
}
@@ -62663,8 +66368,9 @@
sqlite3VdbeAddOp4(v, OP_AggStep, 0, regAgg, pF->iMem,
(void*)pF->pFunc, P4_FUNCDEF);
sqlite3VdbeChangeP5(v, nArg);
sqlite3ReleaseTempRange(pParse, regAgg, nArg);
+ sqlite3ExprCacheAffinityChange(pParse, regAgg, nArg);
if( addrNext ){
sqlite3VdbeResolveLabel(v, addrNext);
}
}
@@ -62673,9 +66379,9 @@
}
pAggInfo->directMode = 0;
}
-#ifndef SQLITE_OMIT_TRIGGER
+#if 0
/*
** This function is used when a SELECT statement is used to create a
** temporary table for iterating through when running an INSTEAD OF
** UPDATE or INSTEAD OF DELETE trigger.
@@ -62823,14 +66529,16 @@
if( p->pPrior ){
if( p->pRightmost==0 ){
Select *pLoop, *pRight = 0;
int cnt = 0;
+ int mxSelect;
for(pLoop=p; pLoop; pLoop=pLoop->pPrior, cnt++){
pLoop->pRightmost = p;
pLoop->pNext = pRight;
pRight = pLoop;
}
- if( SQLITE_MAX_COMPOUND_SELECT>0 && cnt>SQLITE_MAX_COMPOUND_SELECT ){
+ mxSelect = db->aLimit[SQLITE_LIMIT_COMPOUND_SELECT];
+ if( mxSelect && cnt>mxSelect ){
sqlite3ErrorMsg(pParse, "too many terms in compound SELECT");
return 1;
}
}
@@ -62891,9 +66599,8 @@
needRestoreContext = 1;
}else{
needRestoreContext = 0;
}
-#if defined(SQLITE_TEST) || SQLITE_MAX_EXPR_DEPTH>0
/* Increment Parse.nHeight by the height of the largest expression
** tree refered to by this, the parent select. The child select
** may contain expression trees of at most
** (SQLITE_MAX_EXPR_DEPTH-Parse.nHeight) height. This is a bit
@@ -62900,17 +66607,14 @@
** more conservative than necessary, but much easier than enforcing
** an exact limit.
*/
pParse->nHeight += sqlite3SelectExprHeight(p);
-#endif
sqlite3SelectDestInit(&dest, SRT_EphemTab, pItem->iCursor);
sqlite3Select(pParse, pItem->pSelect, &dest, p, i, &isAgg, 0);
if( db->mallocFailed ){
goto select_end;
}
-#if defined(SQLITE_TEST) || SQLITE_MAX_EXPR_DEPTH>0
- pParse->nHeight -= sqlite3SelectExprHeight(p);
-#endif
+ pParse->nHeight -= sqlite3SelectExprHeight(p);
if( needRestoreContext ){
pParse->zAuthContext = zSavedAuthContext;
}
pTabList = p->pSrc;
@@ -62920,18 +66624,8 @@
}
pGroupBy = p->pGroupBy;
pHaving = p->pHaving;
isDistinct = p->isDistinct;
- }
-#endif
-
- /* Check for the special case of a min() or max() function by itself
- ** in the result set.
- */
-#if 0
- if( simpleMinMaxQuery(pParse, p, pDest) ){
- rc = 0;
- goto select_end;
}
#endif
/* Check to see if this is a subquery that can be "flattened" into its parent.
@@ -63090,12 +66784,11 @@
** will be converted into a Noop.
*/
sAggInfo.sortingIdx = pParse->nTab++;
pKeyInfo = keyInfoFromExprList(pParse, pGroupBy);
- addrSortingIdx =
- sqlite3VdbeAddOp4(v, OP_OpenEphemeral, sAggInfo.sortingIdx,
- sAggInfo.nSortingColumn, 0,
- (char*)pKeyInfo, P4_KEYINFO_HANDOFF);
+ addrSortingIdx = sqlite3VdbeAddOp4(v, OP_OpenEphemeral,
+ sAggInfo.sortingIdx, sAggInfo.nSortingColumn,
+ 0, (char*)pKeyInfo, P4_KEYINFO_HANDOFF);
/* Initialize memory locations used by GROUP BY aggregate processing
*/
iUseFlag = ++pParse->nMem;
@@ -63178,16 +66871,20 @@
j++;
}
}
regBase = sqlite3GetTempRange(pParse, nCol);
- sqlite3ExprCodeExprList(pParse, pGroupBy, regBase);
+ sqlite3ExprCodeExprList(pParse, pGroupBy, regBase, 0);
sqlite3VdbeAddOp2(v, OP_Sequence, sAggInfo.sortingIdx,regBase+nGroupBy);
j = nGroupBy+1;
for(i=0; i<sAggInfo.nColumn; i++){
struct AggInfo_col *pCol = &sAggInfo.aCol[i];
if( pCol->iSorterColumn>=j ){
- sqlite3ExprCodeGetColumn(v, pCol->pTab, pCol->iColumn, pCol->iTable,
- j + regBase);
+ int r1 = j + regBase;
+ int r2 = sqlite3ExprCodeGetColumn(pParse,
+ pCol->pTab, pCol->iColumn, pCol->iTable, r1, 0);
+ if( r1!=r2 ){
+ sqlite3VdbeAddOp2(v, OP_SCopy, r2, r1);
+ }
j++;
}
}
regRecord = sqlite3GetTempReg(pParse);
@@ -63235,9 +66932,9 @@
** for the next GROUP BY batch.
*/
sqlite3VdbeResolveLabel(v, addrGroupByChange);
for(j=0; j<pGroupBy->nExpr; j++){
- sqlite3VdbeAddOp2(v, OP_Move, iBMem+j, iAMem+j);
+ sqlite3ExprCodeMove(pParse, iBMem+j, iAMem+j);
}
sqlite3VdbeAddOp2(v, OP_Gosub, 0, addrOutputRow);
VdbeComment((v, "output one row"));
sqlite3VdbeAddOp2(v, OP_IfPos, iAbortFlag, addrEnd);
@@ -63301,9 +66998,9 @@
flag = minMaxQuery(pParse, p);
if( flag ){
pDel = pMinMax = sqlite3ExprListDup(db, p->pEList->a[0].pExpr->pList);
if( pMinMax && !db->mallocFailed ){
- pMinMax->a[0].sortOrder = ((flag==ORDERBY_MIN)?0:1);
+ pMinMax->a[0].sortOrder = ((flag==WHERE_ORDERBY_MIN)?0:1);
pMinMax->a[0].pExpr->op = TK_COLUMN;
}
}
@@ -63319,9 +67016,9 @@
}
updateAccumulator(pParse, &sAggInfo);
if( !pMinMax && flag ){
sqlite3VdbeAddOp2(v, OP_Goto, 0, pWInfo->iBreak);
- VdbeComment((v, "%s() by index", (flag==ORDERBY_MIN?"min":"max")));
+ VdbeComment((v, "%s() by index", (flag==WHERE_ORDERBY_MIN?"min":"max")));
}
sqlite3WhereEnd(pWInfo);
finalizeAggFunctions(pParse, &sAggInfo);
pOrderBy = 0;
@@ -64546,9 +68243,9 @@
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle UPDATE statements.
**
-** $Id: update.c,v 1.170 2008/01/19 03:35:59 drh Exp $
+** $Id: update.c,v 1.178 2008/04/28 18:46:43 drh Exp $
*/
#ifndef SQLITE_OMIT_VIRTUALTABLE
/* Forward declaration */
@@ -64636,8 +68333,9 @@
AuthContext sContext; /* The authorization context */
NameContext sNC; /* The name-context to resolve expressions in */
int iDb; /* Database containing the table being updated */
int j1; /* Addresses of jump instructions */
+ int okOnePass; /* True for one-pass algorithm without the FIFO */
#ifndef SQLITE_OMIT_TRIGGER
int isView; /* Trying to update a view */
int triggers_exist = 0; /* True if any row triggers exist */
@@ -64822,15 +68520,8 @@
goto update_cleanup;
}
#endif
- /* Resolve the column names in all the expressions in the
- ** WHERE clause.
- */
- if( sqlite3ExprResolveNames(&sNC, pWhere) ){
- goto update_cleanup;
- }
-
/* Start the view context
*/
if( isView ){
sqlite3AuthContextPush(pParse, &sContext, pTab->zName);
@@ -64842,12 +68533,12 @@
int iGoto;
/* Create pseudo-tables for NEW and OLD
*/
+ sqlite3VdbeAddOp2(v, OP_SetNumColumns, 0, pTab->nCol);
sqlite3VdbeAddOp2(v, OP_OpenPseudo, oldIdx, 0);
- sqlite3VdbeAddOp2(v, OP_SetNumColumns, oldIdx, pTab->nCol);
- sqlite3VdbeAddOp2(v, OP_OpenPseudo, newIdx, 0);
- sqlite3VdbeAddOp2(v, OP_SetNumColumns, newIdx, pTab->nCol);
+ sqlite3VdbeAddOp2(v, OP_SetNumColumns, 0, pTab->nCol);
+ sqlite3VdbeAddOp2(v, OP_OpenPseudo, newIdx, 0);
iGoto = sqlite3VdbeAddOp2(v, OP_Goto, 0, 0);
addr = sqlite3VdbeMakeLabel(v);
iBeginBeforeTrigger = sqlite3VdbeCurrentAddr(v);
@@ -64868,27 +68559,30 @@
/* If we are trying to update a view, realize that view into
** a ephemeral table.
*/
if( isView ){
- Select *pView;
- SelectDest dest;
-
- pView = sqlite3SelectDup(db, pTab->pSelect);
- sqlite3SelectMask(pParse, pView, old_col_mask|new_col_mask);
- sqlite3SelectDestInit(&dest, SRT_EphemTab, iCur);
- sqlite3Select(pParse, pView, &dest, 0, 0, 0, 0);
- sqlite3SelectDelete(pView);
+ sqlite3MaterializeView(pParse, pTab->pSelect, pWhere, iCur);
+ }
+
+ /* Resolve the column names in all the expressions in the
+ ** WHERE clause.
+ */
+ if( sqlite3ExprResolveNames(&sNC, pWhere) ){
+ goto update_cleanup;
}
/* Begin the database scan
*/
- pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0);
+ sqlite3VdbeAddOp2(v, OP_Null, 0, regOldRowid);
+ pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0,
+ WHERE_ONEPASS_DESIRED);
if( pWInfo==0 ) goto update_cleanup;
+ okOnePass = pWInfo->okOnePass;
/* Remember the rowid of every item to be updated.
*/
- sqlite3VdbeAddOp2(v, IsVirtual(pTab) ? OP_VRowid : OP_Rowid,iCur,regOldRowid);
- sqlite3VdbeAddOp2(v, OP_FifoWrite, regOldRowid, 0);
+ sqlite3VdbeAddOp2(v, IsVirtual(pTab)?OP_VRowid:OP_Rowid, iCur, regOldRowid);
+ if( !okOnePass ) sqlite3VdbeAddOp2(v, OP_FifoWrite, regOldRowid, 0);
/* End the database scan loop.
*/
sqlite3WhereEnd(pWInfo);
@@ -64906,9 +68600,9 @@
** index could potentially invoke a REPLACE conflict resolution
** action, then we need to open all indices because we might need
** to be deleting some records.
*/
- sqlite3OpenTable(pParse, iCur, iDb, pTab, OP_OpenWrite);
+ if( !okOnePass ) sqlite3OpenTable(pParse, iCur, iDb, pTab, OP_OpenWrite);
if( onError==OE_Replace ){
openAll = 1;
}else{
openAll = 0;
@@ -64934,9 +68628,15 @@
sqlite3VdbeResolveLabel(v, addr);
}
/* Top of the update loop */
- addr = sqlite3VdbeAddOp2(v, OP_FifoRead, regOldRowid, 0);
+ if( okOnePass ){
+ int a1 = sqlite3VdbeAddOp1(v, OP_NotNull, regOldRowid);
+ addr = sqlite3VdbeAddOp0(v, OP_Goto);
+ sqlite3VdbeJumpHere(v, a1);
+ }else{
+ addr = sqlite3VdbeAddOp2(v, OP_FifoRead, regOldRowid, 0);
+ }
if( triggers_exist ){
int regRowid;
int regRow;
@@ -64985,8 +68685,9 @@
}
sqlite3VdbeAddOp3(v, OP_MakeRecord, regCols, pTab->nCol, regRow);
if( !isView ){
sqlite3TableAffinityStr(v, pTab);
+ sqlite3ExprCacheAffinityChange(pParse, regCols, pTab->nCol);
}
sqlite3ReleaseTempRange(pParse, regCols, pTab->nCol);
if( pParse->nErr ) goto update_cleanup;
sqlite3VdbeAddOp3(v, OP_Insert, newIdx, regRow, regRowid);
@@ -65190,9 +68891,9 @@
sqlite3VdbeAddOp3(v, OP_Column, ephemTab, (pRowid?1:0), iReg+1);
for(i=0; i<pTab->nCol; i++){
sqlite3VdbeAddOp3(v, OP_Column, ephemTab, i+1+(pRowid!=0), iReg+2+i);
}
- pParse->pVirtualLock = pTab;
+ sqlite3VtabMakeWritable(pParse, pTab);
sqlite3VdbeAddOp4(v, OP_VUpdate, 0, pTab->nCol+2, iReg, pVtab, P4_VTAB);
sqlite3VdbeAddOp2(v, OP_Next, ephemTab, addr);
sqlite3VdbeJumpHere(v, addr-1);
sqlite3VdbeAddOp2(v, OP_Close, ephemTab, 0);
@@ -65200,8 +68901,13 @@
/* Cleanup */
sqlite3SelectDelete(pSelect);
}
#endif /* SQLITE_OMIT_VIRTUALTABLE */
+
+/* Make sure "isView" gets undefined in case this file becomes part of
+** the amalgamation - so that subsequent files do not see isView as a
+** macro. */
+#undef isView
/************** End of update.c **********************************************/
/************** Begin file vacuum.c ******************************************/
/*
@@ -65219,9 +68925,9 @@
**
** Most of the code in this file may be omitted by defining the
** SQLITE_OMIT_VACUUM macro.
**
-** $Id: vacuum.c,v 1.76 2008/01/03 00:01:25 drh Exp $
+** $Id: vacuum.c,v 1.78 2008/04/30 16:38:23 drh Exp $
*/
#if !defined(SQLITE_OMIT_VACUUM) && !defined(SQLITE_OMIT_ATTACH)
/*
@@ -65288,8 +68994,9 @@
Btree *pTemp; /* The temporary database we vacuum into */
char *zSql = 0; /* SQL statements */
int saved_flags; /* Saved value of the db->flags */
Db *pDb = 0; /* Database to detach at end of vacuum */
+ int nRes;
/* Save the current value of the write-schema flag before setting it. */
saved_flags = db->flags;
db->flags |= SQLITE_WriteSchema | SQLITE_IgnoreChecks;
@@ -65308,22 +69015,30 @@
** (possibly synchronous) transaction opened on the main database before
** sqlite3BtreeCopyFile() is called.
**
** An optimisation would be to use a non-journaled pager.
+ ** (Later:) I tried setting "PRAGMA vacuum_db.journal_mode=OFF" but
+ ** that actually made the VACUUM run slower. Very little journalling
+ ** actually occurs when doing a vacuum since the vacuum_db is initially
+ ** empty. Only the journal header is written. Apparently it takes more
+ ** time to parse and run the PRAGMA to turn journalling off than it does
+ ** to write the journal header file.
*/
zSql = "ATTACH '' AS vacuum_db;";
rc = execSql(db, zSql);
if( rc!=SQLITE_OK ) goto end_of_vacuum;
pDb = &db->aDb[db->nDb-1];
assert( strcmp(db->aDb[db->nDb-1].zName,"vacuum_db")==0 );
pTemp = db->aDb[db->nDb-1].pBt;
- sqlite3BtreeSetPageSize(pTemp, sqlite3BtreeGetPageSize(pMain),
- sqlite3BtreeGetReserve(pMain));
- if( db->mallocFailed ){
+
+ nRes = sqlite3BtreeGetReserve(pMain);
+ if( sqlite3BtreeSetPageSize(pTemp, sqlite3BtreeGetPageSize(pMain), nRes)
+ || sqlite3BtreeSetPageSize(pTemp, db->nextPagesize, nRes)
+ || db->mallocFailed
+ ){
rc = SQLITE_NOMEM;
goto end_of_vacuum;
}
- assert( sqlite3BtreeGetPageSize(pTemp)==sqlite3BtreeGetPageSize(pMain) );
rc = execSql(db, "PRAGMA vacuum_db.synchronous=OFF");
if( rc!=SQLITE_OK ){
goto end_of_vacuum;
}
@@ -65440,8 +69155,12 @@
if( rc!=SQLITE_OK ) goto end_of_vacuum;
rc = sqlite3BtreeCommit(pMain);
}
+ if( rc==SQLITE_OK ){
+ rc = sqlite3BtreeSetPageSize(pMain, sqlite3BtreeGetPageSize(pTemp), nRes);
+ }
+
end_of_vacuum:
/* Restore the original value of db->flags */
db->flags = saved_flags;
@@ -65480,9 +69199,9 @@
**
*************************************************************************
** This file contains code used to help implement virtual tables.
**
-** $Id: vtab.c,v 1.63 2008/01/23 03:03:05 drh Exp $
+** $Id: vtab.c,v 1.69 2008/05/05 13:23:04 drh Exp $
*/
#ifndef SQLITE_OMIT_VIRTUALTABLE
static int createModule(
@@ -66064,8 +69783,15 @@
rc = xDestroy(pTab->pVtab);
}
(void)sqlite3SafetyOn(db);
if( rc==SQLITE_OK ){
+ int i;
+ for(i=0; i<db->nVTrans; i++){
+ if( db->aVTrans[i]==pTab->pVtab ){
+ db->aVTrans[i] = db->aVTrans[--db->nVTrans];
+ break;
+ }
+ }
pTab->pVtab = 0;
}
}
@@ -66132,9 +69858,9 @@
** Invoke the xRollback method of all virtual tables in the
** sqlite3.aVTrans array. Then clear the array itself.
*/
SQLITE_PRIVATE int sqlite3VtabRollback(sqlite3 *db){
- callFinaliser(db, (int)(&((sqlite3_module *)0)->xRollback));
+ callFinaliser(db, offsetof(sqlite3_module,xRollback));
return SQLITE_OK;
}
/*
@@ -66141,9 +69867,9 @@
** Invoke the xCommit method of all virtual tables in the
** sqlite3.aVTrans array. Then clear the array itself.
*/
SQLITE_PRIVATE int sqlite3VtabCommit(sqlite3 *db){
- callFinaliser(db, (int)(&((sqlite3_module *)0)->xCommit));
+ callFinaliser(db, offsetof(sqlite3_module,xCommit));
return SQLITE_OK;
}
/*
@@ -66263,8 +69989,29 @@
pNew->flags |= SQLITE_FUNC_EPHEM;
return pNew;
}
+/*
+** Make sure virtual table pTab is contained in the pParse->apVirtualLock[]
+** array so that an OP_VBegin will get generated for it. Add pTab to the
+** array if it is missing. If pTab is already in the array, this routine
+** is a no-op.
+*/
+SQLITE_PRIVATE void sqlite3VtabMakeWritable(Parse *pParse, Table *pTab){
+ int i, n;
+ assert( IsVirtual(pTab) );
+ for(i=0; i<pParse->nVtabLock; i++){
+ if( pTab==pParse->apVtabLock[i] ) return;
+ }
+ n = (pParse->nVtabLock+1)*sizeof(pParse->apVtabLock[0]);
+ pParse->apVtabLock = sqlite3_realloc(pParse->apVtabLock, n);
+ if( pParse->apVtabLock ){
+ pParse->apVtabLock[pParse->nVtabLock++] = pTab;
+ }else{
+ pParse->db->mallocFailed = 1;
+ }
+}
+
#endif /* SQLITE_OMIT_VIRTUALTABLE */
/************** End of vtab.c ************************************************/
/************** Begin file where.c *******************************************/
@@ -66285,9 +70032,9 @@
** rows. Indices are selected and used to speed the search when doing
** so is applicable. Because this module is responsible for selecting
** indices, you might also think of this module as the "query optimizer".
**
-** $Id: where.c,v 1.286 2008/01/23 12:52:41 drh Exp $
+** $Id: where.c,v 1.302 2008/04/19 14:40:44 drh Exp $
*/
/*
** The number of bits in a Bitmask. "BMS" means "BitMask Size".
@@ -66297,10 +70044,10 @@
/*
** Trace output macros
*/
#if defined(SQLITE_TEST) || defined(SQLITE_DEBUG)
-SQLITE_API int sqlite3_where_trace = 0;
-# define WHERETRACE(X) if(sqlite3_where_trace) sqlite3DebugPrintf X
+SQLITE_PRIVATE int sqlite3WhereTrace = 0;
+# define WHERETRACE(X) if(sqlite3WhereTrace) sqlite3DebugPrintf X
#else
# define WHERETRACE(X)
#endif
@@ -66785,24 +70532,28 @@
static int isLikeOrGlob(
sqlite3 *db, /* The database */
Expr *pExpr, /* Test this expression */
int *pnPattern, /* Number of non-wildcard prefix characters */
- int *pisComplete /* True if the only wildcard is % in the last character */
+ int *pisComplete, /* True if the only wildcard is % in the last character */
+ int *pnoCase /* True if uppercase is equivalent to lowercase */
){
const char *z;
Expr *pRight, *pLeft;
ExprList *pList;
int c, cnt;
- int noCase;
char wc[3];
CollSeq *pColl;
- if( !sqlite3IsLikeFunction(db, pExpr, &noCase, wc) ){
- return 0;
- }
+ if( !sqlite3IsLikeFunction(db, pExpr, pnoCase, wc) ){
+ return 0;
+ }
+#ifdef SQLITE_EBCDIC
+ if( *pnoCase ) return 0;
+#endif
pList = pExpr->pList;
pRight = pList->a[0].pExpr;
- if( pRight->op!=TK_STRING ){
+ if( pRight->op!=TK_STRING
+ && (pRight->op!=TK_REGISTER || pRight->iColumn!=TK_STRING) ){
return 0;
}
pLeft = pList->a[1].pExpr;
if( pLeft->op!=TK_COLUMN ){
@@ -66813,10 +70564,10 @@
if( pColl==0 ){
/* No collation is defined for the ROWID. Use the default. */
pColl = db->pDfltColl;
}
- if( (pColl->type!=SQLITE_COLL_BINARY || noCase) &&
- (pColl->type!=SQLITE_COLL_NOCASE || !noCase) ){
+ if( (pColl->type!=SQLITE_COLL_BINARY || *pnoCase) &&
+ (pColl->type!=SQLITE_COLL_NOCASE || !*pnoCase) ){
return 0;
}
sqlite3DequoteExpr(db, pRight);
z = (char *)pRight->token.z;
@@ -66982,10 +70733,12 @@
ExprMaskSet *pMaskSet;
Expr *pExpr;
Bitmask prereqLeft;
Bitmask prereqAll;
+ Bitmask extraRight = 0;
int nPattern;
int isComplete;
+ int noCase;
int op;
Parse *pParse = pWC->pParse;
sqlite3 *db = pParse->db;
@@ -67007,9 +70760,12 @@
pTerm->prereqRight = exprTableUsage(pMaskSet, pExpr->pRight);
}
prereqAll = exprTableUsage(pMaskSet, pExpr);
if( ExprHasProperty(pExpr, EP_FromJoin) ){
- prereqAll |= getMask(pMaskSet, pExpr->iRightJoinTable);
+ Bitmask x = getMask(pMaskSet, pExpr->iRightJoinTable);
+ prereqAll |= x;
+ extraRight = x-1; /* ON clause terms may not be used with an index
+ ** on left table of a LEFT JOIN. Ticket #3015 */
}
pTerm->prereqAll = prereqAll;
pTerm->leftCursor = -1;
pTerm->iParent = -1;
@@ -67102,8 +70858,9 @@
whereSplit(&sOr, pExpr, TK_OR);
exprAnalyzeAll(pSrc, &sOr);
assert( sOr.nTerm>=2 );
j = 0;
+ if( db->mallocFailed ) goto or_not_possible;
do{
assert( j<sOr.nTerm );
iColumn = sOr.a[j].leftColumn;
iCursor = sOr.a[j].leftCursor;
@@ -67154,10 +70911,18 @@
#ifndef SQLITE_OMIT_LIKE_OPTIMIZATION
/* Add constraints to reduce the search space on a LIKE or GLOB
** operator.
- */
- if( isLikeOrGlob(db, pExpr, &nPattern, &isComplete) ){
+ **
+ ** A like pattern of the form "x LIKE 'abc%'" is changed into constraints
+ **
+ ** x>='abc' AND x<'abd' AND x LIKE 'abc%'
+ **
+ ** The last character of the prefix "abc" is incremented to form the
+ ** termination condidtion "abd". This trick of incrementing the last
+ ** is not 255 and if the character set is not EBCDIC.
+ */
+ if( isLikeOrGlob(db, pExpr, &nPattern, &isComplete, &noCase) ){
Expr *pLeft, *pRight;
Expr *pStr1, *pStr2;
Expr *pNewExpr1, *pNewExpr2;
int idxNew1, idxNew2;
@@ -67171,10 +70936,14 @@
pStr1->flags = EP_Dequoted;
}
pStr2 = sqlite3ExprDup(db, pStr1);
if( !db->mallocFailed ){
+ u8 c, *pC;
assert( pStr2->token.dyn );
- ++*(u8*)&pStr2->token.z[nPattern-1];
+ pC = (u8*)&pStr2->token.z[nPattern-1];
+ c = *pC;
+ if( noCase ) c = sqlite3UpperToLower[c];
+ *pC = c + 1;
}
pNewExpr1 = sqlite3PExpr(pParse, TK_GE, sqlite3ExprDup(db,pLeft), pStr1, 0);
idxNew1 = whereClauseInsert(pWC, pNewExpr1, TERM_VIRTUAL|TERM_DYNAMIC);
exprAnalyze(pSrc, pWC, idxNew1);
@@ -67223,8 +70992,13 @@
pNewTerm->prereqAll = pTerm->prereqAll;
}
}
#endif /* SQLITE_OMIT_VIRTUALTABLE */
+
+ /* Prevent ON clause terms of a LEFT JOIN from being used to drive
+ ** an index for tables to the left of the join.
+ */
+ pTerm->prereqRight |= extraRight;
}
/*
** Return TRUE if any of the expressions in pList->a[iFirst...] contain
@@ -67428,9 +71202,9 @@
*/
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_DEBUG)
static void TRACE_IDX_INPUTS(sqlite3_index_info *p){
int i;
- if( !sqlite3_where_trace ) return;
+ if( !sqlite3WhereTrace ) return;
for(i=0; i<p->nConstraint; i++){
sqlite3DebugPrintf(" constraint[%d]: col=%d termid=%d op=%d usabled=%d\n",
i,
p->aConstraint[i].iColumn,
@@ -67446,9 +71220,9 @@
}
}
static void TRACE_IDX_OUTPUTS(sqlite3_index_info *p){
int i;
- if( !sqlite3_where_trace ) return;
+ if( !sqlite3WhereTrace ) return;
for(i=0; i<p->nConstraint; i++){
sqlite3DebugPrintf(" usage[%d]: argvIdx=%d omit=%d\n",
i,
p->aConstraintUsage[i].argvIndex,
@@ -67513,10 +71287,12 @@
/* Count the number of possible WHERE clause constraints referring
** to this virtual table */
for(i=nTerm=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){
if( pTerm->leftCursor != pSrc->iCursor ) continue;
- if( pTerm->eOperator==WO_IN ) continue;
- if( pTerm->eOperator==WO_ISNULL ) continue;
+ if( (pTerm->eOperator&(pTerm->eOperator-1))==0 );
+ testcase( pTerm->eOperator==WO_IN );
+ testcase( pTerm->eOperator==WO_ISNULL );
+ if( pTerm->eOperator & (WO_IN|WO_ISNULL) ) continue;
nTerm++;
}
/* If the ORDER BY clause contains only columns in the current
@@ -67561,10 +71337,12 @@
pUsage;
for(i=j=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){
if( pTerm->leftCursor != pSrc->iCursor ) continue;
- if( pTerm->eOperator==WO_IN ) continue;
- if( pTerm->eOperator==WO_ISNULL ) continue;
+ if( (pTerm->eOperator&(pTerm->eOperator-1))==0 );
+ testcase( pTerm->eOperator==WO_IN );
+ testcase( pTerm->eOperator==WO_ISNULL );
+ if( pTerm->eOperator & (WO_IN|WO_ISNULL) ) continue;
pIdxCons[j].iColumn = pTerm->leftColumn;
pIdxCons[j].iTermOffset = i;
pIdxCons[j].op = pTerm->eOperator;
/* The direct assignment in the previous line is possible only because
@@ -67652,16 +71430,25 @@
WHERETRACE(("xBestIndex for %s\n", pTab->zName));
TRACE_IDX_INPUTS(pIdxInfo);
rc = pTab->pVtab->pModule->xBestIndex(pTab->pVtab, pIdxInfo);
TRACE_IDX_OUTPUTS(pIdxInfo);
+ (void)sqlite3SafetyOn(pParse->db);
+
+ for(i=0; i<pIdxInfo->nConstraint; i++){
+ if( !pIdxInfo->aConstraint[i].usable && pUsage[i].argvIndex>0 ){
+ sqlite3ErrorMsg(pParse,
+ "table %s: xBestIndex returned an invalid plan", pTab->zName);
+ return 0.0;
+ }
+ }
+
if( rc!=SQLITE_OK ){
if( rc==SQLITE_NOMEM ){
pParse->db->mallocFailed = 1;
}else {
sqlite3ErrorMsg(pParse, "%s", sqlite3ErrStr(rc));
}
}
- (void)sqlite3SafetyOn(pParse->db);
*(int*)&pIdxInfo->nOrderBy = nOrderBy;
return pIdxInfo->estimatedCost;
}
@@ -67959,26 +71746,19 @@
}
}
/*
-** Generate code that builds a probe for an index.
-**
-** There should be nColumn values on the stack. The index
-** to be probed is pIdx. Pop the values from the stack and
-** replace them all with a single record that is the index
-** problem.
-*/
-static void buildIndexProbe(
- Vdbe *v, /* Generate code into this VM */
- int nColumn, /* The number of columns to check for NULL */
- Index *pIdx, /* Index that we will be searching */
- int regSrc, /* Take values from this register */
- int regDest /* Write the result into this register */
-){
- assert( regSrc>0 );
- assert( regDest>0 );
- sqlite3VdbeAddOp3(v, OP_MakeRecord, regSrc, nColumn, regDest);
- sqlite3IndexAffinityStr(v, pIdx);
+** Apply the affinities associated with the first n columns of index
+** pIdx to the values in the n registers starting at base.
+*/
+static void codeApplyAffinity(Parse *pParse, int base, int n, Index *pIdx){
+ if( n>0 ){
+ Vdbe *v = pParse->pVdbe;
+ assert( v!=0 );
+ sqlite3VdbeAddOp2(v, OP_Affinity, base, n);
+ sqlite3IndexAffinityStr(v, pIdx);
+ sqlite3ExprCacheAffinityChange(pParse, base, n);
+ }
}
/*
@@ -67991,21 +71771,25 @@
** For a constraint of the form X=expr, the expression is evaluated and its
** result is left on the stack. For constraints of the form X IN (...)
** this routine sets up a loop that will iterate over all values of X.
*/
-static void codeEqualityTerm(
+static int codeEqualityTerm(
Parse *pParse, /* The parsing context */
WhereTerm *pTerm, /* The term of the WHERE clause to be coded */
WhereLevel *pLevel, /* When level of the FROM clause we are working on */
- int iReg /* Leave results in this register */
+ int iTarget /* Attempt to leave results in this register */
){
Expr *pX = pTerm->pExpr;
Vdbe *v = pParse->pVdbe;
-
- assert( iReg>0 && iReg<=pParse->nMem );
+ int iReg; /* Register holding results */
+
+ if( iTarget<=0 ){
+ iReg = iTarget = sqlite3GetTempReg(pParse);
+ }
if( pX->op==TK_EQ ){
- sqlite3ExprCode(pParse, pX->pRight, iReg);
+ iReg = sqlite3ExprCodeTarget(pParse, pX->pRight, iTarget);
}else if( pX->op==TK_ISNULL ){
+ iReg = iTarget;
sqlite3VdbeAddOp2(v, OP_Null, 0, iReg);
#ifndef SQLITE_OMIT_SUBQUERY
}else{
int eType;
@@ -68012,8 +71796,9 @@
int iTab;
struct InLoop *pIn;
assert( pX->op==TK_IN );
+ iReg = iTarget;
eType = sqlite3FindInIndex(pParse, pX, 1);
iTab = pX->iTable;
sqlite3VdbeAddOp2(v, OP_Rewind, iTab, 0);
VdbeComment((v, "%.*s", pX->span.n, pX->span.z));
@@ -68038,8 +71823,9 @@
}
#endif
}
disableTerm(pLevel, pTerm);
+ return iReg;
}
/*
** Generate code that will evaluate all == and IN constraints for an
@@ -68091,13 +71877,19 @@
/* Evaluate the equality constraints
*/
assert( pIdx->nColumn>=nEq );
for(j=0; j<nEq; j++){
+ int r1;
int k = pIdx->aiColumn[j];
pTerm = findTerm(pWC, iCur, k, notReady, pLevel->flags, pIdx);
if( pTerm==0 ) break;
assert( (pTerm->flags & TERM_CODED)==0 );
- codeEqualityTerm(pParse, pTerm, pLevel, regBase+j);
+ r1 = codeEqualityTerm(pParse, pTerm, pLevel, regBase+j);
+ if( r1!=regBase+j ){
+ sqlite3VdbeAddOp2(v, OP_SCopy, r1, regBase+j);
+ }
+ testcase( pTerm->eOperator & WO_ISNULL );
+ testcase( pTerm->eOperator & WO_IN );
if( (pTerm->eOperator & (WO_ISNULL|WO_IN))==0 ){
sqlite3VdbeAddOp2(v, OP_IsNull, regBase+j, pLevel->brk);
}
}
@@ -68227,9 +72019,9 @@
Parse *pParse, /* The parser context */
SrcList *pTabList, /* A list of all tables to be scanned */
Expr *pWhere, /* The WHERE clause */
ExprList **ppOrderBy, /* An ORDER BY clause, or NULL */
- u8 obflag /* One of ORDERBY_MIN, ORDERBY_MAX or ORDERBY_NORMAL */
+ u8 wflags /* One of the WHERE_* flags defined in sqliteInt.h */
){
int i; /* Loop counter */
WhereInfo *pWInfo; /* Will become the return value of this function */
Vdbe *v = pParse->pVdbe; /* The virtual database engine */
@@ -68261,8 +72053,9 @@
** subexpression is separated by an AND operator.
*/
initMaskSet(&maskSet);
whereClauseInit(&wc, pParse, &maskSet);
+ sqlite3ExprCodeConstants(pParse, pWhere);
whereSplit(&wc, pWhere, TK_AND);
/* Allocate and initialize the WhereInfo structure that will become the
** return value.
@@ -68285,16 +72078,38 @@
sqlite3ExprIfFalse(pParse, pWhere, pWInfo->iBreak, SQLITE_JUMPIFNULL);
pWhere = 0;
}
+ /* Assign a bit from the bitmask to every term in the FROM clause.
+ **
+ ** When assigning bitmask values to FROM clause cursors, it must be
+ ** the case that if X is the bitmask for the N-th FROM clause term then
+ ** the bitmask for all FROM clause terms to the left of the N-th term
+ ** is (X-1). An expression from the ON clause of a LEFT JOIN can use
+ ** its Expr.iRightJoinTable value to find the bitmask of the right table
+ ** of the join. Subtracting one from the right table bitmask gives a
+ ** bitmask for all tables to the left of the join. Knowing the bitmask
+ ** for all tables to the left of a left join is important. Ticket #3015.
+ */
+ for(i=0; i<pTabList->nSrc; i++){
+ createMask(&maskSet, pTabList->a[i].iCursor);
+ }
+#ifndef NDEBUG
+ {
+ Bitmask toTheLeft = 0;
+ for(i=0; i<pTabList->nSrc; i++){
+ Bitmask m = getMask(&maskSet, pTabList->a[i].iCursor);
+ assert( (m-1)==toTheLeft );
+ toTheLeft |= m;
+ }
+ }
+#endif
+
/* Analyze all of the subexpressions. Note that exprAnalyze() might
** add new virtual terms onto the end of the WHERE clause. We do not
** want to analyze these virtual terms, so start analyzing at the end
** and work forward so that the added virtual terms are never processed.
*/
- for(i=0; i<pTabList->nSrc; i++){
- createMask(&maskSet, pTabList->a[i].iCursor);
- }
exprAnalyzeAll(pTabList, &wc);
if( db->mallocFailed ){
goto whereBeginNoMem;
}
@@ -68412,8 +72227,19 @@
if( (andFlags & WHERE_UNIQUE)!=0 && ppOrderBy ){
*ppOrderBy = 0;
}
+ /* If the caller is an UPDATE or DELETE statement that is requesting
+ ** to use a one-pass algorithm, determine if this is appropriate.
+ ** The one-pass algorithm only works if the WHERE clause constraints
+ ** the statement to update a single row.
+ */
+ assert( (wflags & WHERE_ONEPASS_DESIRED)==0 || pWInfo->nLevel==1 );
+ if( (wflags & WHERE_ONEPASS_DESIRED)!=0 && (andFlags & WHERE_UNIQUE)!=0 ){
+ pWInfo->okOnePass = 1;
+ pWInfo->a[0].flags &= ~WHERE_IDX_ONLY;
+ }
+
/* Open all tables in the pTabList and any indices selected for
** searching those tables.
*/
sqlite3CodeVerifySchema(pParse, -1); /* Insert the cookie verifier Goto */
@@ -68460,14 +72286,15 @@
(const char*)pTab->pVtab, P4_VTAB);
}else
#endif
if( (pLevel->flags & WHERE_IDX_ONLY)==0 ){
- sqlite3OpenTable(pParse, pTabItem->iCursor, iDb, pTab, OP_OpenRead);
- if( pTab->nCol<(sizeof(Bitmask)*8) ){
+ int op = pWInfo->okOnePass ? OP_OpenWrite : OP_OpenRead;
+ sqlite3OpenTable(pParse, pTabItem->iCursor, iDb, pTab, op);
+ if( !pWInfo->okOnePass && pTab->nCol<(sizeof(Bitmask)*8) ){
Bitmask b = pTabItem->colUsed;
int n = 0;
for(; b; b=b>>1, n++){}
- sqlite3VdbeChangeP2(v, sqlite3VdbeCurrentAddr(v)-1, n);
+ sqlite3VdbeChangeP2(v, sqlite3VdbeCurrentAddr(v)-2, n);
assert( n<=pTab->nCol );
}
}else{
sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName);
@@ -68475,12 +72302,12 @@
pLevel->iTabCur = pTabItem->iCursor;
if( (pIx = pLevel->pIdx)!=0 ){
KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIx);
assert( pIx->pSchema==pTab->pSchema );
+ sqlite3VdbeAddOp2(v, OP_SetNumColumns, 0, pIx->nColumn+1);
sqlite3VdbeAddOp4(v, OP_OpenRead, iIdxCur, pIx->tnum, iDb,
(char*)pKey, P4_KEYINFO_HANDOFF);
VdbeComment((v, "%s", pIx->zName));
- sqlite3VdbeAddOp2(v, OP_SetNumColumns, iIdxCur, pIx->nColumn+1);
}
sqlite3CodeVerifySchema(pParse, iDb);
}
pWInfo->iTop = sqlite3VdbeCurrentAddr(v);
@@ -68584,15 +72411,13 @@
assert( pTerm!=0 );
assert( pTerm->pExpr!=0 );
assert( pTerm->leftCursor==iCur );
assert( omitTable==0 );
- r1 = sqlite3GetTempReg(pParse);
- codeEqualityTerm(pParse, pTerm, pLevel, r1);
+ r1 = codeEqualityTerm(pParse, pTerm, pLevel, 0);
nxt = pLevel->nxt;
- sqlite3VdbeAddOp3(v, OP_MustBeInt, r1, nxt, 1);
+ sqlite3VdbeAddOp2(v, OP_MustBeInt, r1, nxt);
sqlite3VdbeAddOp3(v, OP_NotExists, iCur, nxt, r1);
VdbeComment((v, "pk"));
- sqlite3ReleaseTempReg(pParse, r1);
pLevel->op = OP_Noop;
}else if( pLevel->flags & WHERE_ROWID_RANGE ){
/* Case 2: We have an inequality comparison against the ROWID field.
*/
@@ -68649,50 +72474,74 @@
sqlite3VdbeAddOp3(v, testOp, pLevel->iMem, brk, r1);
sqlite3VdbeChangeP5(v, SQLITE_AFF_NUMERIC | SQLITE_JUMPIFNULL);
sqlite3ReleaseTempReg(pParse, r1);
}
- }else if( pLevel->flags & WHERE_COLUMN_RANGE ){
- /* Case 3: The WHERE clause term that refers to the right-most
- ** column of the index is an inequality. For example, if
- ** the index is on (x,y,z) and the WHERE clause is of the
- ** form "x=5 AND y<10" then this case is used. Only the
- ** right-most column can be an inequality - the rest must
- ** use the "==" and "IN" operators.
+ }else if( pLevel->flags & (WHERE_COLUMN_RANGE|WHERE_COLUMN_EQ) ){
+ /* Case 3: A scan using an index.
+ **
+ ** The WHERE clause may contain zero or more equality
+ ** terms ("==" or "IN" operators) that refer to the N
+ ** left-most columns of the index. It may also contain
+ ** inequality constraints (>, <, >= or <=) on the indexed
+ ** column that immediately follows the N equalities. Only
+ ** the right-most column can be an inequality - the rest must
+ ** use the "==" and "IN" operators. For example, if the
+ ** index is on (x,y,z), then the following clauses are all
+ ** optimized:
+ **
+ ** x=5
+ ** x=5 AND y=10
+ ** x=5 AND y<10
+ ** x=5 AND y>5 AND y<10
+ ** x=5 AND y=5 AND z<=10
+ **
+ ** The z<10 term of the following cannot be used, only
+ ** the x=5 term:
+ **
+ ** x=5 AND z<10
+ **
+ ** N may be zero if there are inequality constraints.
+ ** If there are no inequality constraints, then N is at
+ ** least one.
**
** This case is also used when there are no WHERE clause
** constraints but an index is selected anyway, in order
** to force the output order to conform to an ORDER BY.
*/
- int start;
+ int aStartOp[] = {
+ 0,
+ 0,
+ OP_Rewind, /* 2: (!start_constraints && startEq && !bRev) */
+ OP_Last, /* 3: (!start_constraints && startEq && bRev) */
+ OP_MoveGt, /* 4: (start_constraints && !startEq && !bRev) */
+ OP_MoveLt, /* 5: (start_constraints && !startEq && bRev) */
+ OP_MoveGe, /* 6: (start_constraints && startEq && !bRev) */
+ OP_MoveLe /* 7: (start_constraints && startEq && bRev) */
+ };
+ int aEndOp[] = {
+ OP_Noop, /* 0: (!end_constraints) */
+ OP_IdxGE, /* 1: (end_constraints && !bRev) */
+ OP_IdxLT /* 2: (end_constraints && bRev) */
+ };
int nEq = pLevel->nEq;
- int topEq=0; /* True if top limit uses ==. False is strictly < */
- int btmEq=0; /* True if btm limit uses ==. False if strictly > */
- int topOp, btmOp; /* Operators for the top and bottom search bounds */
- int testOp;
- int topLimit = (pLevel->flags & WHERE_TOP_LIMIT)!=0;
- int btmLimit = (pLevel->flags & WHERE_BTM_LIMIT)!=0;
- int isMinQuery = 0; /* If this is an optimized SELECT min(x) ... */
- int regBase; /* Base register holding constraint values */
- int r1; /* Temp register */
+ int isMinQuery = 0; /* If this is an optimized SELECT min(x).. */
+ int regBase; /* Base register holding constraint values */
+ int r1; /* Temp register */
+ WhereTerm *pRangeStart = 0; /* Inequality constraint at range start */
+ WhereTerm *pRangeEnd = 0; /* Inequality constraint at range end */
+ int startEq; /* True if range start uses ==, >= or <= */
+ int endEq; /* True if range end uses ==, >= or <= */
+ int start_constraints; /* Start of range is constrained */
+ int k = pIdx->aiColumn[nEq]; /* Column for inequality constraints */
+ int nConstraint; /* Number of constraint terms */
+ int op;
/* Generate code to evaluate all constraint terms using == or IN
- ** and level the values of those terms on the stack.
+ ** and store the values of those terms in an array of registers
+ ** starting at regBase.
*/
regBase = codeAllEqualityTerms(pParse, pLevel, &wc, notReady, 2);
-
- /* Figure out what comparison operators to use for top and bottom
- ** search bounds. For an ascending index, the bottom bound is a > or >=
- ** operator and the top bound is a < or <= operator. For a descending
- ** index the operators are reversed.
- */
- if( pIdx->aSortOrder[nEq]==SQLITE_SO_ASC ){
- topOp = WO_LT|WO_LE;
- btmOp = WO_GT|WO_GE;
- }else{
- topOp = WO_GT|WO_GE;
- btmOp = WO_LT|WO_LE;
- SWAP(int, topLimit, btmLimit);
- }
+ nxt = pLevel->nxt;
/* If this loop satisfies a sort order (pOrderBy) request that
** was passed to this function to implement a "SELECT min(x) ..."
** query, then the caller will only allow the loop to run for
@@ -68700,204 +72549,122 @@
** should not have a NULL value stored in 'x'. If column 'x' is
** the first one after the nEq equality constraints in the index,
** this requires some special handling.
*/
- if( (obflag==ORDERBY_MIN)
+ if( (wflags&WHERE_ORDERBY_MIN)!=0
&& (pLevel->flags&WHERE_ORDERBY)
&& (pIdx->nColumn>nEq)
&& (pOrderBy->a[0].pExpr->iColumn==pIdx->aiColumn[nEq])
){
isMinQuery = 1;
}
- /* Generate the termination key. This is the key value that
- ** will end the search. There is no termination key if there
- ** are no equality terms and no "X<..." term.
- **
- ** 2002-Dec-04: On a reverse-order scan, the so-called "termination"
- ** key computed here really ends up being the start key.
+ /* Find any inequality constraint terms for the start and end
+ ** of the range.
+ */
+ if( pLevel->flags & WHERE_TOP_LIMIT ){
+ pRangeEnd = findTerm(&wc, iCur, k, notReady, (WO_LT|WO_LE), pIdx);
+ }
+ if( pLevel->flags & WHERE_BTM_LIMIT ){
+ pRangeStart = findTerm(&wc, iCur, k, notReady, (WO_GT|WO_GE), pIdx);
+ }
+
+ /* If we are doing a reverse order scan on an ascending index, or
+ ** a forward order scan on a descending index, interchange the
+ ** start and end terms (pRangeStart and pRangeEnd).
*/
- nxt = pLevel->nxt;
- if( topLimit ){
- Expr *pX;
- int k = pIdx->aiColumn[nEq];
- pTerm = findTerm(&wc, iCur, k, notReady, topOp, pIdx);
- assert( pTerm!=0 );
- pX = pTerm->pExpr;
- assert( (pTerm->flags & TERM_CODED)==0 );
- sqlite3ExprCode(pParse, pX->pRight, regBase+nEq);
+ if( bRev==(pIdx->aSortOrder[nEq]==SQLITE_SO_ASC) ){
+ SWAP(WhereTerm *, pRangeEnd, pRangeStart);
+ }
+
+ testcase( pRangeStart && pRangeStart->eOperator & WO_LE );
+ testcase( pRangeStart && pRangeStart->eOperator & WO_GE );
+ testcase( pRangeEnd && pRangeEnd->eOperator & WO_LE );
+ testcase( pRangeEnd && pRangeEnd->eOperator & WO_GE );
+ startEq = !pRangeStart || pRangeStart->eOperator & (WO_LE|WO_GE);
+ endEq = !pRangeEnd || pRangeEnd->eOperator & (WO_LE|WO_GE);
+ start_constraints = pRangeStart || nEq>0;
+
+ /* Seek the index cursor to the start of the range. */
+ nConstraint = nEq;
+ if( pRangeStart ){
+ int dcc = pParse->disableColCache;
+ if( pRangeEnd ){
+ pParse->disableColCache = 1;
+ }
+ sqlite3ExprCode(pParse, pRangeStart->pExpr->pRight, regBase+nEq);
+ pParse->disableColCache = dcc;
sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, nxt);
- topEq = pTerm->eOperator & (WO_LE|WO_GE);
- disableTerm(pLevel, pTerm);
- testOp = OP_IdxGE;
- }else{
- testOp = nEq>0 ? OP_IdxGE : OP_Noop;
- topEq = 1;
- }
- if( testOp!=OP_Noop || (isMinQuery&&bRev) ){
- int nCol = nEq + topLimit;
- if( isMinQuery && !topLimit ){
- sqlite3VdbeAddOp2(v, OP_Null, 0, regBase+nCol);
- nCol++;
- topEq = 0;
- }
- buildIndexProbe(v, nCol, pIdx, regBase, pLevel->iMem);
- if( bRev ){
- int op = topEq ? OP_MoveLe : OP_MoveLt;
- sqlite3VdbeAddOp3(v, op, iIdxCur, nxt, pLevel->iMem);
- }
- }else if( bRev ){
- sqlite3VdbeAddOp2(v, OP_Last, iIdxCur, brk);
- }
-
- /* Generate the start key. This is the key that defines the lower
- ** bound on the search. There is no start key if there are no
- ** equality terms and if there is no "X>..." term. In
- ** that case, generate a "Rewind" instruction in place of the
- ** start key search.
- **
- ** 2002-Dec-04: In the case of a reverse-order search, the so-called
- ** "start" key really ends up being used as the termination key.
+ nConstraint++;
+ }else if( isMinQuery ){
+ sqlite3VdbeAddOp2(v, OP_Null, 0, regBase+nEq);
+ nConstraint++;
+ startEq = 0;
+ start_constraints = 1;
+ }
+ codeApplyAffinity(pParse, regBase, nConstraint, pIdx);
+ op = aStartOp[(start_constraints<<2) + (startEq<<1) + bRev];
+ assert( op!=0 );
+ testcase( op==OP_Rewind );
+ testcase( op==OP_Last );
+ testcase( op==OP_MoveGt );
+ testcase( op==OP_MoveGe );
+ testcase( op==OP_MoveLe );
+ testcase( op==OP_MoveLt );
+ sqlite3VdbeAddOp4(v, op, iIdxCur, nxt, regBase,
+ (char*)nConstraint, P4_INT32);
+
+ /* Load the value for the inequality constraint at the end of the
+ ** range (if any).
*/
- if( btmLimit ){
- Expr *pX;
- int k = pIdx->aiColumn[nEq];
- pTerm = findTerm(&wc, iCur, k, notReady, btmOp, pIdx);
- assert( pTerm!=0 );
- pX = pTerm->pExpr;
- assert( (pTerm->flags & TERM_CODED)==0 );
- sqlite3ExprCode(pParse, pX->pRight, regBase+nEq);
+ nConstraint = nEq;
+ if( pRangeEnd ){
+ sqlite3ExprCode(pParse, pRangeEnd->pExpr->pRight, regBase+nEq);
sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, nxt);
- btmEq = pTerm->eOperator & (WO_LE|WO_GE);
- disableTerm(pLevel, pTerm);
- }else{
- btmEq = 1;
- }
- if( nEq>0 || btmLimit || (isMinQuery&&!bRev) ){
- int nCol = nEq + btmLimit;
- if( isMinQuery && !btmLimit ){
- sqlite3VdbeAddOp2(v, OP_Null, 0, regBase+nCol);
- nCol++;
- btmEq = 0;
- }
- if( bRev ){
- r1 = pLevel->iMem;
- testOp = OP_IdxLT;
- }else{
- r1 = sqlite3GetTempReg(pParse);
- }
- buildIndexProbe(v, nCol, pIdx, regBase, r1);
- if( !bRev ){
- int op = btmEq ? OP_MoveGe : OP_MoveGt;
- sqlite3VdbeAddOp3(v, op, iIdxCur, nxt, r1);
- sqlite3ReleaseTempReg(pParse, r1);
- }
- }else if( bRev ){
- testOp = OP_Noop;
- }else{
- sqlite3VdbeAddOp2(v, OP_Rewind, iIdxCur, brk);
- }
-
- /* Generate the the top of the loop. If there is a termination
- ** key we have to test for that key and abort at the top of the
- ** loop.
+ codeApplyAffinity(pParse, regBase, nEq+1, pIdx);
+ nConstraint++;
+ }
+
+ /* Top of the loop body */
+ pLevel->p2 = sqlite3VdbeCurrentAddr(v);
+
+ /* Check if the index cursor is past the end of the range. */
+ op = aEndOp[(pRangeEnd || nEq) * (1 + bRev)];
+ testcase( op==OP_Noop );
+ testcase( op==OP_IdxGE );
+ testcase( op==OP_IdxLT );
+ sqlite3VdbeAddOp4(v, op, iIdxCur, nxt, regBase,
+ (char*)nConstraint, P4_INT32);
+ sqlite3VdbeChangeP5(v, endEq!=bRev);
+
+ /* If there are inequality constraints, check that the value
+ ** of the table column that the inequality contrains is not NULL.
+ ** If it is, jump to the next iteration of the loop.
*/
- start = sqlite3VdbeCurrentAddr(v);
- if( testOp!=OP_Noop ){
- sqlite3VdbeAddOp3(v, testOp, iIdxCur, nxt, pLevel->iMem);
- if( (topEq && !bRev) || (!btmEq && bRev) ){
- sqlite3VdbeChangeP5(v, 1);
- }
- }
r1 = sqlite3GetTempReg(pParse);
- if( topLimit | btmLimit ){
+ testcase( pLevel->flags & WHERE_BTM_LIMIT );
+ testcase( pLevel->flags & WHERE_TOP_LIMIT );
+ if( pLevel->flags & (WHERE_BTM_LIMIT|WHERE_TOP_LIMIT) ){
sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, nEq, r1);
sqlite3VdbeAddOp2(v, OP_IsNull, r1, cont);
}
+
+ /* Seek the table cursor, if required */
if( !omitTable ){
sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, r1);
sqlite3VdbeAddOp3(v, OP_MoveGe, iCur, 0, r1); /* Deferred seek */
}
sqlite3ReleaseTempReg(pParse, r1);
- /* Record the instruction used to terminate the loop.
+ /* Record the instruction used to terminate the loop. Disable
+ ** WHERE clause terms made redundant by the index range scan.
*/
pLevel->op = bRev ? OP_Prev : OP_Next;
pLevel->p1 = iIdxCur;
- pLevel->p2 = start;
- }else if( pLevel->flags & WHERE_COLUMN_EQ ){
- /* Case 4: There is an index and all terms of the WHERE clause that
- ** refer to the index using the "==" or "IN" operators.
- */
- int start;
- int nEq = pLevel->nEq;
- int isMinQuery = 0; /* If this is an optimized SELECT min(x) ... */
- int regBase; /* Base register of array holding constraints */
- int r1;
-
- /* Generate code to evaluate all constraint terms using == or IN
- ** and leave the values of those terms on the stack.
- */
- regBase = codeAllEqualityTerms(pParse, pLevel, &wc, notReady, 1);
- nxt = pLevel->nxt;
-
- if( (obflag==ORDERBY_MIN)
- && (pLevel->flags&WHERE_ORDERBY)
- && (pIdx->nColumn>nEq)
- && (pOrderBy->a[0].pExpr->iColumn==pIdx->aiColumn[nEq])
- ){
- isMinQuery = 1;
- buildIndexProbe(v, nEq, pIdx, regBase, pLevel->iMem);
- sqlite3VdbeAddOp2(v, OP_Null, 0, regBase+nEq);
- r1 = ++pParse->nMem;
- buildIndexProbe(v, nEq+1, pIdx, regBase, r1);
- }else{
- /* Generate a single key that will be used to both start and
- ** terminate the search
- */
- r1 = pLevel->iMem;
- buildIndexProbe(v, nEq, pIdx, regBase, r1);
- }
-
- /* Generate code (1) to move to the first matching element of the table.
- ** Then generate code (2) that jumps to "nxt" after the cursor is past
- ** the last matching element of the table. The code (1) is executed
- ** once to initialize the search, the code (2) is executed before each
- ** iteration of the scan to see if the scan has finished. */
- if( bRev ){
- /* Scan in reverse order */
- int op;
- if( isMinQuery ){
- op = OP_MoveLt;
- }else{
- op = OP_MoveLe;
- }
- sqlite3VdbeAddOp3(v, op, iIdxCur, nxt, r1);
- start = sqlite3VdbeAddOp3(v, OP_IdxLT, iIdxCur, nxt, pLevel->iMem);
- pLevel->op = OP_Prev;
- }else{
- /* Scan in the forward order */
- int op;
- if( isMinQuery ){
- op = OP_MoveGt;
- }else{
- op = OP_MoveGe;
- }
- sqlite3VdbeAddOp3(v, op, iIdxCur, nxt, r1);
- start = sqlite3VdbeAddOp3(v, OP_IdxGE, iIdxCur, nxt, pLevel->iMem);
- sqlite3VdbeChangeP5(v, 1);
- pLevel->op = OP_Next;
- }
- if( !omitTable ){
- r1 = sqlite3GetTempReg(pParse);
- sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, r1);
- sqlite3VdbeAddOp3(v, OP_MoveGe, iCur, 0, r1); /* Deferred seek */
- sqlite3ReleaseTempReg(pParse, r1);
- }
- pLevel->p1 = iIdxCur;
- pLevel->p2 = start;
- }else{
- /* Case 5: There is no usable index. We must do a complete
+ disableTerm(pLevel, pRangeStart);
+ disableTerm(pLevel, pRangeEnd);
+ }else{
+ /* Case 4: There is no usable index. We must do a complete
** scan of the entire table.
*/
assert( omitTable==0 );
assert( bRev==0 );
@@ -68911,8 +72678,10 @@
** computed using the current set of tables.
*/
for(pTerm=wc.a, j=wc.nTerm; j>0; j--, pTerm++){
Expr *pE;
+ testcase( pTerm->flags & TERM_VIRTUAL );
+ testcase( pTerm->flags & TERM_CODED );
if( pTerm->flags & (TERM_VIRTUAL|TERM_CODED) ) continue;
if( (pTerm->prereqAll & notReady)!=0 ) continue;
pE = pTerm->pExpr;
assert( pE!=0 );
@@ -68929,9 +72698,13 @@
if( pLevel->iLeftJoin ){
pLevel->top = sqlite3VdbeCurrentAddr(v);
sqlite3VdbeAddOp2(v, OP_Integer, 1, pLevel->iLeftJoin);
VdbeComment((v, "record LEFT JOIN hit"));
+ sqlite3ExprClearColumnCache(pParse, pLevel->iTabCur);
+ sqlite3ExprClearColumnCache(pParse, pLevel->iIdxCur);
for(pTerm=wc.a, j=0; j<wc.nTerm; j++, pTerm++){
+ testcase( pTerm->flags & TERM_VIRTUAL );
+ testcase( pTerm->flags & TERM_CODED );
if( pTerm->flags & (TERM_VIRTUAL|TERM_CODED) ) continue;
if( (pTerm->prereqAll & notReady)!=0 ) continue;
assert( pTerm->pExpr );
sqlite3ExprIfFalse(pParse, pTerm->pExpr, cont, SQLITE_JUMPIFNULL);
@@ -68964,8 +72737,10 @@
nQPlan += n;
}
sqlite3_query_plan[nQPlan++] = ' ';
}
+ testcase( pLevel->flags & WHERE_ROWID_EQ );
+ testcase( pLevel->flags & WHERE_ROWID_RANGE );
if( pLevel->flags & (WHERE_ROWID_EQ|WHERE_ROWID_RANGE) ){
memcpy(&sqlite3_query_plan[nQPlan], "* ", 2);
nQPlan += 2;
}else if( pLevel->pIdx==0 ){
@@ -69012,8 +72787,9 @@
SrcList *pTabList = pWInfo->pTabList;
/* Generate loop termination code.
*/
+ sqlite3ExprClearColumnCache(pWInfo->pParse, -1);
for(i=pTabList->nSrc-1; i>=0; i--){
pLevel = &pWInfo->a[i];
sqlite3VdbeResolveLabel(v, pLevel->cont);
if( pLevel->op!=OP_Noop ){
@@ -69054,9 +72830,9 @@
struct SrcList_item *pTabItem = &pTabList->a[pLevel->iFrom];
Table *pTab = pTabItem->pTab;
assert( pTab!=0 );
if( pTab->isEphem || pTab->pSelect ) continue;
- if( (pLevel->flags & WHERE_IDX_ONLY)==0 ){
+ if( !pWInfo->okOnePass && (pLevel->flags & WHERE_IDX_ONLY)==0 ){
sqlite3VdbeAddOp1(v, OP_Close, pTabItem->iCursor);
}
if( pLevel->pIdx!=0 ){
sqlite3VdbeAddOp1(v, OP_Close, pLevel->iIdxCur);
@@ -69229,14 +73005,18 @@
#define sqlite3ParserARG_SDECL Parse *pParse;
#define sqlite3ParserARG_PDECL ,Parse *pParse
#define sqlite3ParserARG_FETCH Parse *pParse = yypParser->pParse
#define sqlite3ParserARG_STORE yypParser->pParse = pParse
-#define YYNSTATE 588
-#define YYNRULE 312
+#define YYNSTATE 589
+#define YYNRULE 313
#define YYFALLBACK 1
#define YY_NO_ACTION (YYNSTATE+YYNRULE+2)
#define YY_ACCEPT_ACTION (YYNSTATE+YYNRULE+1)
#define YY_ERROR_ACTION (YYNSTATE+YYNRULE)
+
+/* The yyzerominor constant is used to initialize instances of
+** YYMINORTYPE objects to zero. */
+static const YYMINORTYPE yyzerominor;
/* Next are that tables used to determine what action to take based on the
** current state and lookahead token. These tables are used to implement
** functions that take a state number and lookahead value and return an
@@ -69284,9 +73064,9 @@
** shifting non-terminals after a reduce.
** yy_default[] Default action for each state.
*/
static const YYACTIONTYPE yy_action[] = {
- /* 0 */ 292, 901, 124, 587, 409, 172, 2, 418, 61, 61,
+ /* 0 */ 292, 903, 124, 588, 409, 172, 2, 418, 61, 61,
/* 10 */ 61, 61, 519, 63, 63, 63, 63, 64, 64, 65,
/* 20 */ 65, 65, 66, 210, 447, 212, 425, 431, 68, 63,
/* 30 */ 63, 63, 63, 64, 64, 65, 65, 65, 66, 210,
/* 40 */ 391, 388, 396, 451, 60, 59, 297, 435, 436, 432,
@@ -69293,25 +73073,25 @@
/* 50 */ 432, 62, 62, 61, 61, 61, 61, 263, 63, 63,
/* 60 */ 63, 63, 64, 64, 65, 65, 65, 66, 210, 292,
/* 70 */ 493, 494, 418, 489, 208, 82, 67, 420, 69, 154,
/* 80 */ 63, 63, 63, 63, 64, 64, 65, 65, 65, 66,
- /* 90 */ 210, 67, 462, 69, 154, 425, 431, 573, 264, 58,
+ /* 90 */ 210, 67, 462, 69, 154, 425, 431, 574, 264, 58,
/* 100 */ 64, 64, 65, 65, 65, 66, 210, 397, 398, 422,
/* 110 */ 422, 422, 292, 60, 59, 297, 435, 436, 432, 432,
/* 120 */ 62, 62, 61, 61, 61, 61, 317, 63, 63, 63,
/* 130 */ 63, 64, 64, 65, 65, 65, 66, 210, 425, 431,
/* 140 */ 94, 65, 65, 65, 66, 210, 396, 210, 414, 34,
- /* 150 */ 56, 298, 442, 443, 410, 488, 60, 59, 297, 435,
- /* 160 */ 436, 432, 432, 62, 62, 61, 61, 61, 61, 490,
+ /* 150 */ 56, 298, 442, 443, 410, 418, 60, 59, 297, 435,
+ /* 160 */ 436, 432, 432, 62, 62, 61, 61, 61, 61, 208,
/* 170 */ 63, 63, 63, 63, 64, 64, 65, 65, 65, 66,
- /* 180 */ 210, 292, 257, 524, 295, 571, 113, 408, 522, 451,
- /* 190 */ 331, 317, 407, 20, 418, 340, 519, 396, 532, 531,
- /* 200 */ 505, 447, 212, 570, 569, 208, 530, 425, 431, 149,
- /* 210 */ 150, 397, 398, 414, 41, 211, 151, 533, 372, 489,
- /* 220 */ 261, 568, 259, 420, 292, 60, 59, 297, 435, 436,
+ /* 180 */ 210, 292, 372, 524, 295, 572, 113, 408, 522, 451,
+ /* 190 */ 331, 317, 407, 20, 244, 340, 519, 396, 478, 531,
+ /* 200 */ 505, 447, 212, 571, 570, 245, 530, 425, 431, 149,
+ /* 210 */ 150, 397, 398, 414, 41, 211, 151, 533, 488, 489,
+ /* 220 */ 418, 568, 569, 420, 292, 60, 59, 297, 435, 436,
/* 230 */ 432, 432, 62, 62, 61, 61, 61, 61, 317, 63,
/* 240 */ 63, 63, 63, 64, 64, 65, 65, 65, 66, 210,
- /* 250 */ 425, 431, 447, 333, 215, 422, 422, 422, 363, 418,
+ /* 250 */ 425, 431, 447, 333, 215, 422, 422, 422, 363, 299,
/* 260 */ 414, 41, 397, 398, 366, 567, 211, 292, 60, 59,
/* 270 */ 297, 435, 436, 432, 432, 62, 62, 61, 61, 61,
/* 280 */ 61, 396, 63, 63, 63, 63, 64, 64, 65, 65,
/* 290 */ 65, 66, 210, 425, 431, 491, 300, 524, 474, 66,
@@ -69318,48 +73098,48 @@
/* 300 */ 210, 214, 474, 229, 411, 286, 534, 20, 449, 523,
/* 310 */ 168, 60, 59, 297, 435, 436, 432, 432, 62, 62,
/* 320 */ 61, 61, 61, 61, 474, 63, 63, 63, 63, 64,
/* 330 */ 64, 65, 65, 65, 66, 210, 209, 480, 317, 77,
- /* 340 */ 292, 239, 300, 55, 484, 230, 397, 398, 181, 547,
+ /* 340 */ 292, 239, 300, 55, 484, 490, 397, 398, 181, 547,
/* 350 */ 494, 345, 348, 349, 67, 152, 69, 154, 339, 524,
- /* 360 */ 414, 35, 350, 241, 221, 370, 425, 431, 578, 20,
+ /* 360 */ 414, 35, 350, 241, 221, 370, 425, 431, 579, 20,
/* 370 */ 164, 118, 243, 343, 248, 344, 176, 322, 442, 443,
/* 380 */ 414, 3, 80, 252, 60, 59, 297, 435, 436, 432,
/* 390 */ 432, 62, 62, 61, 61, 61, 61, 174, 63, 63,
/* 400 */ 63, 63, 64, 64, 65, 65, 65, 66, 210, 292,
/* 410 */ 221, 550, 236, 487, 510, 353, 317, 118, 243, 343,
- /* 420 */ 248, 344, 176, 181, 317, 525, 345, 348, 349, 252,
+ /* 420 */ 248, 344, 176, 181, 317, 532, 345, 348, 349, 252,
/* 430 */ 223, 415, 155, 464, 511, 425, 431, 350, 414, 34,
- /* 440 */ 465, 211, 177, 175, 160, 237, 414, 34, 338, 549,
+ /* 440 */ 465, 211, 177, 175, 160, 525, 414, 34, 338, 549,
/* 450 */ 449, 323, 168, 60, 59, 297, 435, 436, 432, 432,
/* 460 */ 62, 62, 61, 61, 61, 61, 415, 63, 63, 63,
/* 470 */ 63, 64, 64, 65, 65, 65, 66, 210, 292, 542,
- /* 480 */ 335, 517, 504, 541, 456, 571, 302, 19, 331, 144,
+ /* 480 */ 335, 517, 504, 541, 456, 572, 302, 19, 331, 144,
/* 490 */ 317, 390, 317, 330, 2, 362, 457, 294, 483, 373,
- /* 500 */ 269, 268, 252, 570, 425, 431, 588, 391, 388, 458,
- /* 510 */ 208, 495, 414, 49, 414, 49, 303, 585, 892, 159,
- /* 520 */ 892, 496, 60, 59, 297, 435, 436, 432, 432, 62,
+ /* 500 */ 269, 268, 252, 571, 425, 431, 589, 391, 388, 458,
+ /* 510 */ 208, 495, 414, 49, 414, 49, 303, 586, 894, 230,
+ /* 520 */ 894, 496, 60, 59, 297, 435, 436, 432, 432, 62,
/* 530 */ 62, 61, 61, 61, 61, 201, 63, 63, 63, 63,
/* 540 */ 64, 64, 65, 65, 65, 66, 210, 292, 317, 181,
- /* 550 */ 439, 255, 345, 348, 349, 370, 153, 582, 308, 251,
+ /* 550 */ 439, 255, 345, 348, 349, 370, 153, 583, 308, 251,
/* 560 */ 309, 452, 76, 350, 78, 382, 211, 426, 427, 415,
- /* 570 */ 414, 27, 319, 425, 431, 440, 1, 22, 585, 891,
- /* 580 */ 396, 891, 544, 478, 320, 263, 438, 438, 429, 430,
+ /* 570 */ 414, 27, 319, 425, 431, 440, 1, 22, 586, 893,
+ /* 580 */ 396, 893, 544, 478, 320, 263, 438, 438, 429, 430,
/* 590 */ 415, 60, 59, 297, 435, 436, 432, 432, 62, 62,
- /* 600 */ 61, 61, 61, 61, 328, 63, 63, 63, 63, 64,
- /* 610 */ 64, 65, 65, 65, 66, 210, 292, 428, 582, 374,
- /* 620 */ 224, 93, 517, 9, 336, 396, 557, 396, 456, 67,
- /* 630 */ 396, 69, 154, 399, 400, 401, 320, 238, 438, 438,
- /* 640 */ 457, 318, 425, 431, 299, 397, 398, 320, 433, 438,
- /* 650 */ 438, 581, 291, 458, 225, 327, 5, 222, 546, 292,
+ /* 600 */ 61, 61, 61, 61, 237, 63, 63, 63, 63, 64,
+ /* 610 */ 64, 65, 65, 65, 66, 210, 292, 428, 583, 374,
+ /* 620 */ 224, 93, 517, 9, 159, 396, 557, 396, 456, 67,
+ /* 630 */ 396, 69, 154, 399, 400, 401, 320, 328, 438, 438,
+ /* 640 */ 457, 336, 425, 431, 361, 397, 398, 320, 433, 438,
+ /* 650 */ 438, 582, 291, 458, 238, 327, 318, 222, 546, 292,
/* 660 */ 60, 59, 297, 435, 436, 432, 432, 62, 62, 61,
- /* 670 */ 61, 61, 61, 395, 63, 63, 63, 63, 64, 64,
+ /* 670 */ 61, 61, 61, 225, 63, 63, 63, 63, 64, 64,
/* 680 */ 65, 65, 65, 66, 210, 425, 431, 482, 313, 392,
- /* 690 */ 397, 398, 397, 398, 207, 397, 398, 824, 273, 517,
+ /* 690 */ 397, 398, 397, 398, 207, 397, 398, 825, 273, 517,
/* 700 */ 251, 200, 292, 60, 59, 297, 435, 436, 432, 432,
/* 710 */ 62, 62, 61, 61, 61, 61, 470, 63, 63, 63,
/* 720 */ 63, 64, 64, 65, 65, 65, 66, 210, 425, 431,
- /* 730 */ 171, 160, 263, 263, 304, 415, 276, 119, 274, 263,
+ /* 730 */ 171, 160, 263, 263, 304, 415, 276, 395, 274, 263,
/* 740 */ 517, 517, 263, 517, 192, 292, 60, 70, 297, 435,
/* 750 */ 436, 432, 432, 62, 62, 61, 61, 61, 61, 379,
/* 760 */ 63, 63, 63, 63, 64, 64, 65, 65, 65, 66,
/* 770 */ 210, 425, 431, 384, 559, 305, 306, 251, 415, 320,
@@ -69367,60 +73147,60 @@
/* 790 */ 59, 297, 435, 436, 432, 432, 62, 62, 61, 61,
/* 800 */ 61, 61, 371, 63, 63, 63, 63, 64, 64, 65,
/* 810 */ 65, 65, 66, 210, 425, 431, 396, 275, 251, 251,
/* 820 */ 172, 250, 418, 415, 386, 367, 178, 179, 180, 469,
- /* 830 */ 311, 123, 156, 128, 297, 435, 436, 432, 432, 62,
+ /* 830 */ 311, 123, 156, 5, 297, 435, 436, 432, 432, 62,
/* 840 */ 62, 61, 61, 61, 61, 317, 63, 63, 63, 63,
- /* 850 */ 64, 64, 65, 65, 65, 66, 210, 72, 324, 177,
+ /* 850 */ 64, 64, 65, 65, 65, 66, 210, 72, 324, 194,
/* 860 */ 4, 317, 263, 317, 296, 263, 415, 414, 28, 317,
- /* 870 */ 263, 317, 321, 72, 324, 317, 4, 421, 445, 445,
+ /* 870 */ 257, 317, 321, 72, 324, 317, 4, 119, 165, 177,
/* 880 */ 296, 397, 398, 414, 23, 414, 32, 418, 321, 326,
- /* 890 */ 329, 414, 53, 414, 52, 317, 158, 414, 98, 451,
- /* 900 */ 317, 194, 317, 277, 317, 326, 378, 471, 502, 317,
- /* 910 */ 478, 279, 478, 165, 294, 451, 317, 414, 96, 75,
+ /* 890 */ 421, 414, 53, 414, 52, 317, 158, 414, 98, 451,
+ /* 900 */ 317, 263, 317, 277, 317, 326, 378, 471, 261, 317,
+ /* 910 */ 259, 18, 478, 445, 445, 451, 317, 414, 96, 75,
/* 920 */ 74, 469, 414, 101, 414, 102, 414, 112, 73, 315,
- /* 930 */ 316, 414, 114, 420, 448, 75, 74, 481, 414, 16,
- /* 940 */ 381, 317, 183, 467, 73, 315, 316, 72, 324, 420,
- /* 950 */ 4, 208, 317, 186, 296, 317, 499, 500, 476, 208,
- /* 960 */ 173, 341, 321, 414, 99, 422, 422, 422, 423, 424,
- /* 970 */ 11, 361, 380, 307, 414, 33, 415, 414, 97, 326,
- /* 980 */ 460, 422, 422, 422, 423, 424, 11, 415, 413, 451,
- /* 990 */ 413, 162, 412, 317, 412, 468, 226, 227, 228, 104,
- /* 1000 */ 84, 473, 317, 509, 508, 317, 622, 477, 317, 75,
- /* 1010 */ 74, 249, 205, 21, 281, 414, 24, 418, 73, 315,
- /* 1020 */ 316, 282, 317, 420, 414, 54, 507, 414, 115, 317,
- /* 1030 */ 414, 116, 506, 203, 147, 549, 244, 512, 526, 202,
- /* 1040 */ 317, 513, 204, 317, 414, 117, 317, 245, 317, 18,
- /* 1050 */ 317, 414, 25, 317, 256, 422, 422, 422, 423, 424,
- /* 1060 */ 11, 258, 414, 36, 260, 414, 37, 317, 414, 26,
- /* 1070 */ 414, 38, 414, 39, 262, 414, 40, 317, 514, 317,
- /* 1080 */ 128, 317, 418, 317, 189, 377, 278, 268, 267, 414,
- /* 1090 */ 42, 293, 317, 254, 317, 128, 208, 365, 8, 414,
- /* 1100 */ 43, 414, 44, 414, 29, 414, 30, 352, 368, 128,
- /* 1110 */ 317, 545, 317, 128, 414, 45, 414, 46, 317, 583,
- /* 1120 */ 383, 553, 317, 173, 554, 317, 91, 317, 564, 369,
- /* 1130 */ 91, 357, 414, 47, 414, 48, 580, 270, 290, 271,
- /* 1140 */ 414, 31, 272, 556, 414, 10, 566, 414, 50, 414,
- /* 1150 */ 51, 280, 283, 284, 577, 146, 463, 405, 584, 231,
- /* 1160 */ 325, 419, 444, 466, 446, 246, 505, 552, 563, 515,
- /* 1170 */ 516, 520, 163, 518, 394, 347, 7, 402, 403, 404,
- /* 1180 */ 314, 84, 232, 334, 332, 83, 79, 416, 170, 57,
- /* 1190 */ 213, 461, 125, 85, 337, 342, 492, 301, 233, 498,
- /* 1200 */ 497, 105, 502, 219, 354, 247, 521, 234, 501, 235,
- /* 1210 */ 287, 417, 503, 218, 527, 528, 529, 358, 240, 535,
- /* 1220 */ 475, 242, 288, 479, 356, 184, 185, 121, 187, 132,
- /* 1230 */ 188, 548, 537, 88, 190, 193, 364, 142, 375, 376,
- /* 1240 */ 555, 133, 220, 562, 134, 310, 135, 138, 136, 574,
- /* 1250 */ 575, 141, 576, 265, 579, 100, 538, 217, 393, 92,
- /* 1260 */ 103, 95, 406, 623, 624, 166, 434, 167, 437, 71,
- /* 1270 */ 453, 441, 450, 17, 143, 157, 169, 6, 111, 13,
- /* 1280 */ 454, 455, 459, 472, 126, 81, 12, 127, 161, 485,
- /* 1290 */ 486, 216, 86, 122, 106, 182, 253, 346, 312, 107,
- /* 1300 */ 120, 87, 351, 108, 245, 355, 145, 536, 359, 129,
- /* 1310 */ 173, 266, 191, 109, 289, 551, 130, 539, 195, 543,
- /* 1320 */ 131, 14, 197, 199, 198, 558, 137, 139, 140, 110,
- /* 1330 */ 15, 285, 572, 206, 389, 565, 385, 148, 586, 902,
- /* 1340 */ 902, 902, 902, 902, 902, 89, 90,
+ /* 930 */ 316, 414, 114, 420, 294, 75, 74, 481, 414, 16,
+ /* 940 */ 381, 317, 279, 467, 73, 315, 316, 72, 324, 420,
+ /* 950 */ 4, 208, 317, 183, 296, 317, 186, 128, 84, 208,
+ /* 960 */ 8, 341, 321, 414, 99, 422, 422, 422, 423, 424,
+ /* 970 */ 11, 623, 380, 307, 414, 33, 413, 414, 97, 326,
+ /* 980 */ 412, 422, 422, 422, 423, 424, 11, 415, 413, 451,
+ /* 990 */ 415, 162, 412, 317, 499, 500, 226, 227, 228, 104,
+ /* 1000 */ 448, 476, 317, 173, 507, 317, 509, 508, 317, 75,
+ /* 1010 */ 74, 329, 205, 21, 281, 414, 24, 418, 73, 315,
+ /* 1020 */ 316, 282, 317, 420, 414, 54, 460, 414, 115, 317,
+ /* 1030 */ 414, 116, 502, 203, 147, 549, 514, 468, 128, 202,
+ /* 1040 */ 317, 473, 204, 317, 414, 117, 317, 477, 317, 584,
+ /* 1050 */ 317, 414, 25, 317, 249, 422, 422, 422, 423, 424,
+ /* 1060 */ 11, 506, 414, 36, 512, 414, 37, 317, 414, 26,
+ /* 1070 */ 414, 38, 414, 39, 526, 414, 40, 317, 254, 317,
+ /* 1080 */ 128, 317, 418, 317, 256, 377, 278, 268, 585, 414,
+ /* 1090 */ 42, 293, 317, 352, 317, 128, 208, 513, 258, 414,
+ /* 1100 */ 43, 414, 44, 414, 29, 414, 30, 545, 260, 128,
+ /* 1110 */ 317, 553, 317, 173, 414, 45, 414, 46, 317, 262,
+ /* 1120 */ 383, 554, 317, 91, 564, 317, 91, 317, 581, 189,
+ /* 1130 */ 290, 357, 414, 47, 414, 48, 267, 365, 368, 369,
+ /* 1140 */ 414, 31, 270, 271, 414, 10, 272, 414, 50, 414,
+ /* 1150 */ 51, 556, 566, 280, 283, 284, 578, 146, 419, 405,
+ /* 1160 */ 231, 505, 444, 325, 516, 463, 163, 446, 552, 394,
+ /* 1170 */ 466, 563, 246, 515, 518, 520, 402, 403, 404, 7,
+ /* 1180 */ 314, 84, 232, 334, 347, 83, 332, 57, 170, 79,
+ /* 1190 */ 213, 461, 125, 85, 337, 342, 492, 502, 497, 301,
+ /* 1200 */ 498, 416, 105, 219, 247, 218, 503, 501, 233, 220,
+ /* 1210 */ 287, 234, 527, 528, 235, 529, 417, 521, 354, 288,
+ /* 1220 */ 184, 121, 185, 240, 535, 475, 242, 356, 187, 479,
+ /* 1230 */ 188, 358, 537, 88, 190, 548, 364, 193, 132, 376,
+ /* 1240 */ 555, 375, 133, 134, 135, 310, 562, 138, 136, 575,
+ /* 1250 */ 576, 577, 580, 100, 393, 406, 217, 142, 624, 625,
+ /* 1260 */ 103, 141, 265, 166, 167, 434, 71, 453, 441, 437,
+ /* 1270 */ 450, 143, 538, 157, 120, 454, 161, 472, 455, 169,
+ /* 1280 */ 459, 81, 6, 12, 13, 92, 95, 126, 216, 127,
+ /* 1290 */ 111, 485, 486, 17, 86, 346, 106, 122, 253, 107,
+ /* 1300 */ 87, 108, 182, 245, 355, 145, 351, 536, 129, 359,
+ /* 1310 */ 312, 130, 543, 173, 539, 266, 191, 109, 289, 551,
+ /* 1320 */ 195, 14, 131, 198, 197, 558, 137, 199, 139, 140,
+ /* 1330 */ 15, 565, 89, 90, 573, 110, 385, 206, 148, 389,
+ /* 1340 */ 285, 587,
};
static const YYCODETYPE yy_lookahead[] = {
/* 0 */ 16, 139, 140, 141, 168, 21, 144, 23, 69, 70,
/* 10 */ 71, 72, 176, 74, 75, 76, 77, 78, 79, 80,
@@ -69436,19 +73216,19 @@
/* 110 */ 125, 126, 16, 60, 61, 62, 63, 64, 65, 66,
/* 120 */ 67, 68, 69, 70, 71, 72, 147, 74, 75, 76,
/* 130 */ 77, 78, 79, 80, 81, 82, 83, 84, 42, 43,
/* 140 */ 44, 80, 81, 82, 83, 84, 23, 84, 169, 170,
- /* 150 */ 19, 164, 165, 166, 23, 169, 60, 61, 62, 63,
- /* 160 */ 64, 65, 66, 67, 68, 69, 70, 71, 72, 169,
+ /* 150 */ 19, 164, 165, 166, 23, 23, 60, 61, 62, 63,
+ /* 160 */ 64, 65, 66, 67, 68, 69, 70, 71, 72, 110,
/* 170 */ 74, 75, 76, 77, 78, 79, 80, 81, 82, 83,
- /* 180 */ 84, 16, 14, 147, 150, 147, 21, 167, 168, 58,
- /* 190 */ 211, 147, 156, 157, 23, 216, 176, 23, 181, 176,
- /* 200 */ 177, 78, 79, 165, 166, 110, 183, 42, 43, 78,
- /* 210 */ 79, 88, 89, 169, 170, 228, 180, 181, 123, 88,
- /* 220 */ 52, 98, 54, 92, 16, 60, 61, 62, 63, 64,
+ /* 180 */ 84, 16, 123, 147, 150, 147, 21, 167, 168, 58,
+ /* 190 */ 211, 147, 156, 157, 92, 216, 176, 23, 147, 176,
+ /* 200 */ 177, 78, 79, 165, 166, 103, 183, 42, 43, 78,
+ /* 210 */ 79, 88, 89, 169, 170, 228, 180, 181, 169, 88,
+ /* 220 */ 88, 98, 99, 92, 16, 60, 61, 62, 63, 64,
/* 230 */ 65, 66, 67, 68, 69, 70, 71, 72, 147, 74,
/* 240 */ 75, 76, 77, 78, 79, 80, 81, 82, 83, 84,
- /* 250 */ 42, 43, 78, 209, 210, 124, 125, 126, 224, 88,
+ /* 250 */ 42, 43, 78, 209, 210, 124, 125, 126, 224, 208,
/* 260 */ 169, 170, 88, 89, 230, 227, 228, 16, 60, 61,
/* 270 */ 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
/* 280 */ 72, 23, 74, 75, 76, 77, 78, 79, 80, 81,
/* 290 */ 82, 83, 84, 42, 43, 160, 16, 147, 161, 83,
@@ -69455,9 +73235,9 @@
/* 300 */ 84, 210, 161, 153, 169, 158, 156, 157, 161, 162,
/* 310 */ 163, 60, 61, 62, 63, 64, 65, 66, 67, 68,
/* 320 */ 69, 70, 71, 72, 161, 74, 75, 76, 77, 78,
/* 330 */ 79, 80, 81, 82, 83, 84, 192, 200, 147, 131,
- /* 340 */ 16, 200, 16, 199, 20, 190, 88, 89, 90, 185,
+ /* 340 */ 16, 200, 16, 199, 20, 169, 88, 89, 90, 185,
/* 350 */ 186, 93, 94, 95, 217, 22, 219, 220, 147, 147,
/* 360 */ 169, 170, 104, 200, 84, 147, 42, 43, 156, 157,
/* 370 */ 90, 91, 92, 93, 94, 95, 96, 164, 165, 166,
/* 380 */ 169, 170, 131, 103, 60, 61, 62, 63, 64, 65,
@@ -69465,16 +73245,16 @@
/* 400 */ 76, 77, 78, 79, 80, 81, 82, 83, 84, 16,
/* 410 */ 84, 11, 221, 20, 30, 16, 147, 91, 92, 93,
/* 420 */ 94, 95, 96, 90, 147, 181, 93, 94, 95, 103,
/* 430 */ 212, 189, 155, 27, 50, 42, 43, 104, 169, 170,
- /* 440 */ 34, 228, 43, 201, 202, 147, 169, 170, 206, 49,
+ /* 440 */ 34, 228, 43, 201, 202, 181, 169, 170, 206, 49,
/* 450 */ 161, 162, 163, 60, 61, 62, 63, 64, 65, 66,
/* 460 */ 67, 68, 69, 70, 71, 72, 189, 74, 75, 76,
/* 470 */ 77, 78, 79, 80, 81, 82, 83, 84, 16, 25,
/* 480 */ 211, 147, 20, 29, 12, 147, 102, 19, 211, 21,
/* 490 */ 147, 141, 147, 216, 144, 41, 24, 98, 20, 99,
/* 500 */ 100, 101, 103, 165, 42, 43, 0, 1, 2, 37,
- /* 510 */ 110, 39, 169, 170, 169, 170, 182, 19, 20, 147,
+ /* 510 */ 110, 39, 169, 170, 169, 170, 182, 19, 20, 190,
/* 520 */ 22, 49, 60, 61, 62, 63, 64, 65, 66, 67,
/* 530 */ 68, 69, 70, 71, 72, 155, 74, 75, 76, 77,
/* 540 */ 78, 79, 80, 81, 82, 83, 84, 16, 147, 90,
/* 550 */ 20, 20, 93, 94, 95, 147, 155, 59, 215, 225,
@@ -69481,16 +73261,16 @@
/* 560 */ 215, 20, 130, 104, 132, 227, 228, 42, 43, 189,
/* 570 */ 169, 170, 16, 42, 43, 20, 19, 22, 19, 20,
/* 580 */ 23, 22, 18, 147, 106, 147, 108, 109, 63, 64,
/* 590 */ 189, 60, 61, 62, 63, 64, 65, 66, 67, 68,
- /* 600 */ 69, 70, 71, 72, 186, 74, 75, 76, 77, 78,
+ /* 600 */ 69, 70, 71, 72, 147, 74, 75, 76, 77, 78,
/* 610 */ 79, 80, 81, 82, 83, 84, 16, 92, 59, 55,
/* 620 */ 212, 21, 147, 19, 147, 23, 188, 23, 12, 217,
- /* 630 */ 23, 219, 220, 7, 8, 9, 106, 147, 108, 109,
+ /* 630 */ 23, 219, 220, 7, 8, 9, 106, 186, 108, 109,
/* 640 */ 24, 147, 42, 43, 208, 88, 89, 106, 92, 108,
- /* 650 */ 109, 244, 245, 37, 145, 39, 191, 182, 94, 16,
+ /* 650 */ 109, 244, 245, 37, 147, 39, 147, 182, 94, 16,
/* 660 */ 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
- /* 670 */ 70, 71, 72, 147, 74, 75, 76, 77, 78, 79,
+ /* 670 */ 70, 71, 72, 145, 74, 75, 76, 77, 78, 79,
/* 680 */ 80, 81, 82, 83, 84, 42, 43, 80, 142, 143,
/* 690 */ 88, 89, 88, 89, 148, 88, 89, 133, 14, 147,
/* 700 */ 225, 155, 16, 60, 61, 62, 63, 64, 65, 66,
/* 710 */ 67, 68, 69, 70, 71, 72, 114, 74, 75, 76,
@@ -69504,67 +73284,67 @@
/* 790 */ 61, 62, 63, 64, 65, 66, 67, 68, 69, 70,
/* 800 */ 71, 72, 213, 74, 75, 76, 77, 78, 79, 80,
/* 810 */ 81, 82, 83, 84, 42, 43, 23, 133, 225, 225,
/* 820 */ 21, 225, 23, 189, 239, 236, 99, 100, 101, 22,
- /* 830 */ 242, 243, 155, 22, 62, 63, 64, 65, 66, 67,
+ /* 830 */ 242, 243, 155, 191, 62, 63, 64, 65, 66, 67,
/* 840 */ 68, 69, 70, 71, 72, 147, 74, 75, 76, 77,
- /* 850 */ 78, 79, 80, 81, 82, 83, 84, 16, 17, 43,
+ /* 850 */ 78, 79, 80, 81, 82, 83, 84, 16, 17, 22,
/* 860 */ 19, 147, 147, 147, 23, 147, 189, 169, 170, 147,
- /* 870 */ 147, 147, 31, 16, 17, 147, 19, 147, 124, 125,
+ /* 870 */ 14, 147, 31, 16, 17, 147, 19, 147, 19, 43,
/* 880 */ 23, 88, 89, 169, 170, 169, 170, 88, 31, 48,
/* 890 */ 147, 169, 170, 169, 170, 147, 89, 169, 170, 58,
- /* 900 */ 147, 22, 147, 188, 147, 48, 188, 114, 97, 147,
- /* 910 */ 147, 188, 147, 19, 98, 58, 147, 169, 170, 78,
+ /* 900 */ 147, 147, 147, 188, 147, 48, 188, 114, 52, 147,
+ /* 910 */ 54, 19, 147, 124, 125, 58, 147, 169, 170, 78,
/* 920 */ 79, 114, 169, 170, 169, 170, 169, 170, 87, 88,
- /* 930 */ 89, 169, 170, 92, 161, 78, 79, 80, 169, 170,
- /* 940 */ 91, 147, 155, 22, 87, 88, 89, 16, 17, 92,
- /* 950 */ 19, 110, 147, 155, 23, 147, 7, 8, 20, 110,
- /* 960 */ 22, 80, 31, 169, 170, 124, 125, 126, 127, 128,
- /* 970 */ 129, 208, 123, 208, 169, 170, 189, 169, 170, 48,
- /* 980 */ 147, 124, 125, 126, 127, 128, 129, 189, 107, 58,
- /* 990 */ 107, 5, 111, 147, 111, 203, 10, 11, 12, 13,
- /* 1000 */ 121, 147, 147, 91, 92, 147, 112, 147, 147, 78,
+ /* 930 */ 89, 169, 170, 92, 98, 78, 79, 80, 169, 170,
+ /* 940 */ 91, 147, 188, 22, 87, 88, 89, 16, 17, 92,
+ /* 950 */ 19, 110, 147, 155, 23, 147, 155, 22, 121, 110,
+ /* 960 */ 68, 80, 31, 169, 170, 124, 125, 126, 127, 128,
+ /* 970 */ 129, 112, 123, 208, 169, 170, 107, 169, 170, 48,
+ /* 980 */ 111, 124, 125, 126, 127, 128, 129, 189, 107, 58,
+ /* 990 */ 189, 5, 111, 147, 7, 8, 10, 11, 12, 13,
+ /* 1000 */ 161, 20, 147, 22, 178, 147, 91, 92, 147, 78,
/* 1010 */ 79, 147, 26, 19, 28, 169, 170, 23, 87, 88,
- /* 1020 */ 89, 35, 147, 92, 169, 170, 178, 169, 170, 147,
- /* 1030 */ 169, 170, 147, 47, 113, 49, 92, 178, 147, 53,
- /* 1040 */ 147, 178, 56, 147, 169, 170, 147, 103, 147, 19,
+ /* 1020 */ 89, 35, 147, 92, 169, 170, 147, 169, 170, 147,
+ /* 1030 */ 169, 170, 97, 47, 113, 49, 20, 203, 22, 53,
+ /* 1040 */ 147, 147, 56, 147, 169, 170, 147, 147, 147, 20,
/* 1050 */ 147, 169, 170, 147, 147, 124, 125, 126, 127, 128,
- /* 1060 */ 129, 147, 169, 170, 147, 169, 170, 147, 169, 170,
+ /* 1060 */ 129, 147, 169, 170, 178, 169, 170, 147, 169, 170,
/* 1070 */ 169, 170, 169, 170, 147, 169, 170, 147, 20, 147,
- /* 1080 */ 22, 147, 88, 147, 232, 99, 100, 101, 147, 169,
- /* 1090 */ 170, 105, 147, 20, 147, 22, 110, 147, 68, 169,
+ /* 1080 */ 22, 147, 88, 147, 147, 99, 100, 101, 59, 169,
+ /* 1090 */ 170, 105, 147, 20, 147, 22, 110, 178, 147, 169,
/* 1100 */ 170, 169, 170, 169, 170, 169, 170, 20, 147, 22,
- /* 1110 */ 147, 20, 147, 22, 169, 170, 169, 170, 147, 20,
- /* 1120 */ 134, 20, 147, 22, 20, 147, 22, 147, 20, 147,
- /* 1130 */ 22, 233, 169, 170, 169, 170, 20, 147, 22, 147,
+ /* 1110 */ 147, 20, 147, 22, 169, 170, 169, 170, 147, 147,
+ /* 1120 */ 134, 20, 147, 22, 20, 147, 22, 147, 20, 232,
+ /* 1130 */ 22, 233, 169, 170, 169, 170, 147, 147, 147, 147,
/* 1140 */ 169, 170, 147, 147, 169, 170, 147, 169, 170, 169,
- /* 1150 */ 170, 147, 147, 147, 147, 191, 172, 149, 59, 193,
- /* 1160 */ 223, 161, 229, 172, 229, 172, 177, 194, 194, 172,
- /* 1170 */ 161, 161, 6, 172, 146, 173, 22, 146, 146, 146,
- /* 1180 */ 154, 121, 194, 118, 116, 119, 130, 189, 112, 120,
- /* 1190 */ 222, 152, 152, 98, 115, 98, 171, 40, 195, 179,
- /* 1200 */ 171, 19, 97, 84, 15, 171, 179, 196, 173, 197,
- /* 1210 */ 174, 198, 171, 226, 171, 171, 171, 38, 204, 152,
- /* 1220 */ 205, 204, 174, 205, 152, 151, 151, 60, 151, 19,
- /* 1230 */ 152, 184, 152, 130, 151, 184, 152, 214, 152, 15,
- /* 1240 */ 194, 187, 226, 194, 187, 152, 187, 184, 187, 33,
- /* 1250 */ 152, 214, 152, 234, 137, 159, 235, 175, 1, 237,
- /* 1260 */ 175, 237, 20, 112, 112, 112, 92, 112, 107, 19,
- /* 1270 */ 11, 20, 20, 231, 19, 19, 22, 117, 240, 117,
- /* 1280 */ 20, 20, 20, 114, 19, 22, 22, 20, 112, 20,
- /* 1290 */ 20, 44, 19, 243, 19, 96, 20, 44, 246, 19,
- /* 1300 */ 32, 19, 44, 19, 103, 16, 21, 17, 36, 98,
- /* 1310 */ 22, 133, 98, 19, 5, 1, 45, 51, 122, 45,
- /* 1320 */ 102, 19, 113, 115, 14, 17, 113, 102, 122, 14,
- /* 1330 */ 19, 136, 20, 135, 3, 123, 57, 19, 4, 247,
- /* 1340 */ 247, 247, 247, 247, 247, 68, 68,
+ /* 1150 */ 170, 147, 147, 147, 147, 147, 147, 191, 161, 149,
+ /* 1160 */ 193, 177, 229, 223, 161, 172, 6, 229, 194, 146,
+ /* 1170 */ 172, 194, 172, 172, 172, 161, 146, 146, 146, 22,
+ /* 1180 */ 154, 121, 194, 118, 173, 119, 116, 120, 112, 130,
+ /* 1190 */ 222, 152, 152, 98, 115, 98, 171, 97, 171, 40,
+ /* 1200 */ 179, 189, 19, 84, 171, 226, 171, 173, 195, 226,
+ /* 1210 */ 174, 196, 171, 171, 197, 171, 198, 179, 15, 174,
+ /* 1220 */ 151, 60, 151, 204, 152, 205, 204, 152, 151, 205,
+ /* 1230 */ 152, 38, 152, 130, 151, 184, 152, 184, 19, 15,
+ /* 1240 */ 194, 152, 187, 187, 187, 152, 194, 184, 187, 33,
+ /* 1250 */ 152, 152, 137, 159, 1, 20, 175, 214, 112, 112,
+ /* 1260 */ 175, 214, 234, 112, 112, 92, 19, 11, 20, 107,
+ /* 1270 */ 20, 19, 235, 19, 32, 20, 112, 114, 20, 22,
+ /* 1280 */ 20, 22, 117, 22, 117, 237, 237, 19, 44, 20,
+ /* 1290 */ 240, 20, 20, 231, 19, 44, 19, 243, 20, 19,
+ /* 1300 */ 19, 19, 96, 103, 16, 21, 44, 17, 98, 36,
+ /* 1310 */ 246, 45, 45, 22, 51, 133, 98, 19, 5, 1,
+ /* 1320 */ 122, 19, 102, 14, 113, 17, 113, 115, 102, 122,
+ /* 1330 */ 19, 123, 68, 68, 20, 14, 57, 135, 19, 3,
+ /* 1340 */ 136, 4,
};
#define YY_SHIFT_USE_DFLT (-62)
#define YY_SHIFT_MAX 389
static const short yy_shift_ofst[] = {
/* 0 */ 39, 841, 986, -16, 841, 931, 931, 258, 123, -36,
/* 10 */ 96, 931, 931, 931, 931, 931, -45, 400, 174, 19,
- /* 20 */ 171, -54, -54, 53, 165, 208, 251, 324, 393, 462,
+ /* 20 */ 132, -54, -54, 53, 165, 208, 251, 324, 393, 462,
/* 30 */ 531, 600, 643, 686, 643, 643, 643, 643, 643, 643,
/* 40 */ 643, 643, 643, 643, 643, 643, 643, 643, 643, 643,
/* 50 */ 643, 643, 729, 772, 772, 857, 931, 931, 931, 931,
/* 60 */ 931, 931, 931, 931, 931, 931, 931, 931, 931, 931,
@@ -69571,36 +73351,36 @@
/* 70 */ 931, 931, 931, 931, 931, 931, 931, 931, 931, 931,
/* 80 */ 931, 931, 931, 931, 931, 931, 931, 931, 931, 931,
/* 90 */ 931, 931, 931, 931, 931, 931, -61, -61, 6, 6,
/* 100 */ 280, 22, 61, 399, 564, 19, 19, 19, 19, 19,
- /* 110 */ 19, 19, 216, 171, 63, -62, -62, -62, 131, 326,
+ /* 110 */ 19, 19, 216, 132, 63, -62, -62, -62, 131, 326,
/* 120 */ 472, 472, 498, 559, 506, 799, 19, 799, 19, 19,
/* 130 */ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- /* 140 */ 19, 849, 95, -36, -36, -36, -62, -62, -62, -15,
+ /* 140 */ 19, 849, 59, -36, -36, -36, -62, -62, -62, -15,
/* 150 */ -15, 333, 459, 478, 557, 530, 541, 616, 602, 793,
/* 160 */ 604, 607, 626, 19, 19, 881, 19, 19, 994, 19,
/* 170 */ 19, 807, 19, 19, 673, 807, 19, 19, 384, 384,
/* 180 */ 384, 19, 19, 673, 19, 19, 673, 19, 454, 685,
/* 190 */ 19, 19, 673, 19, 19, 19, 673, 19, 19, 19,
- /* 200 */ 673, 673, 19, 19, 19, 19, 19, 468, 883, 921,
- /* 210 */ 171, 754, 754, 432, 406, 406, 406, 816, 406, 171,
- /* 220 */ 406, 171, 811, 879, 879, 1166, 1166, 1166, 1166, 1154,
- /* 230 */ -36, 1060, 1065, 1066, 1068, 1069, 1056, 1076, 1076, 1095,
- /* 240 */ 1079, 1095, 1079, 1097, 1097, 1157, 1097, 1105, 1097, 1182,
- /* 250 */ 1119, 1119, 1157, 1097, 1097, 1097, 1182, 1189, 1076, 1189,
- /* 260 */ 1076, 1189, 1076, 1076, 1179, 1103, 1189, 1076, 1167, 1167,
- /* 270 */ 1210, 1060, 1076, 1224, 1224, 1224, 1224, 1060, 1167, 1210,
- /* 280 */ 1076, 1216, 1216, 1076, 1076, 1117, -62, -62, -62, -62,
- /* 290 */ -62, -62, 525, 684, 727, 168, 894, 556, 555, 938,
- /* 300 */ 944, 949, 912, 1058, 1073, 1087, 1091, 1101, 1104, 1108,
- /* 310 */ 1030, 1116, 1099, 1257, 1242, 1151, 1152, 1153, 1155, 1174,
- /* 320 */ 1161, 1250, 1251, 1252, 1255, 1259, 1256, 1260, 1254, 1261,
- /* 330 */ 1262, 1263, 1160, 1264, 1162, 1263, 1169, 1265, 1267, 1176,
- /* 340 */ 1269, 1270, 1268, 1247, 1273, 1253, 1275, 1276, 1280, 1282,
- /* 350 */ 1258, 1284, 1199, 1201, 1289, 1290, 1285, 1211, 1272, 1266,
- /* 360 */ 1271, 1288, 1274, 1178, 1214, 1294, 1309, 1314, 1218, 1277,
- /* 370 */ 1278, 1196, 1302, 1209, 1310, 1208, 1308, 1213, 1225, 1206,
- /* 380 */ 1311, 1212, 1312, 1315, 1279, 1198, 1195, 1318, 1331, 1334,
+ /* 200 */ 673, 673, 19, 19, 19, 19, 19, 468, 869, 921,
+ /* 210 */ 132, 789, 789, 432, 406, 406, 406, 836, 406, 132,
+ /* 220 */ 406, 132, 935, 837, 837, 1160, 1160, 1160, 1160, 1157,
+ /* 230 */ -36, 1060, 1065, 1066, 1070, 1067, 1059, 1076, 1076, 1095,
+ /* 240 */ 1079, 1095, 1079, 1097, 1097, 1159, 1097, 1100, 1097, 1183,
+ /* 250 */ 1119, 1119, 1159, 1097, 1097, 1097, 1183, 1203, 1076, 1203,
+ /* 260 */ 1076, 1203, 1076, 1076, 1193, 1103, 1203, 1076, 1161, 1161,
+ /* 270 */ 1219, 1060, 1076, 1224, 1224, 1224, 1224, 1060, 1161, 1219,
+ /* 280 */ 1076, 1216, 1216, 1076, 1076, 1115, -62, -62, -62, -62,
+ /* 290 */ -62, -62, 525, 684, 727, 856, 859, 556, 555, 981,
+ /* 300 */ 102, 987, 915, 1016, 1058, 1073, 1087, 1091, 1101, 1104,
+ /* 310 */ 892, 1108, 1029, 1253, 1235, 1146, 1147, 1151, 1152, 1173,
+ /* 320 */ 1162, 1247, 1248, 1250, 1252, 1256, 1254, 1255, 1257, 1258,
+ /* 330 */ 1260, 1259, 1165, 1261, 1167, 1259, 1163, 1268, 1269, 1164,
+ /* 340 */ 1271, 1272, 1242, 1244, 1275, 1251, 1277, 1278, 1280, 1281,
+ /* 350 */ 1262, 1282, 1206, 1200, 1288, 1290, 1284, 1210, 1273, 1263,
+ /* 360 */ 1266, 1291, 1267, 1182, 1218, 1298, 1313, 1318, 1220, 1264,
+ /* 370 */ 1265, 1198, 1302, 1211, 1309, 1212, 1308, 1213, 1226, 1207,
+ /* 380 */ 1311, 1208, 1314, 1321, 1279, 1202, 1204, 1319, 1336, 1337,
};
#define YY_REDUCE_USE_DFLT (-165)
#define YY_REDUCE_MAX 291
static const short yy_reduce_ofst[] = {
@@ -69615,87 +73395,87 @@
/* 80 */ 901, 903, 906, 920, 930, 932, 934, 936, 945, 947,
/* 90 */ 963, 965, 971, 975, 978, 980, 412, 412, 412, 412,
/* 100 */ 20, 412, 412, 23, 34, 334, 475, 552, 593, 594,
/* 110 */ 585, 212, 412, 289, 412, 412, 412, 412, 135, -164,
- /* 120 */ -115, 164, 407, 407, 350, 141, 436, 163, 596, -90,
- /* 130 */ 763, 218, 765, 438, 586, 592, 595, 715, 718, 408,
- /* 140 */ 723, 380, 634, 677, 787, 798, 144, 529, 588, -14,
- /* 150 */ 0, 17, 244, 155, 298, 155, 155, 418, 372, 477,
- /* 160 */ 490, 494, 509, 526, 590, 465, 494, 730, 773, 743,
- /* 170 */ 833, 792, 854, 860, 155, 792, 864, 885, 848, 859,
- /* 180 */ 863, 891, 907, 155, 914, 917, 155, 927, 852, 898,
- /* 190 */ 941, 950, 155, 961, 982, 990, 155, 992, 995, 996,
- /* 200 */ 155, 155, 999, 1004, 1005, 1006, 1007, 1008, 964, 966,
- /* 210 */ 1000, 933, 935, 937, 984, 991, 993, 989, 997, 1009,
- /* 220 */ 1001, 1010, 1002, 973, 974, 1028, 1031, 1032, 1033, 1026,
- /* 230 */ 998, 988, 1003, 1011, 1012, 1013, 968, 1039, 1040, 1014,
- /* 240 */ 1015, 1017, 1018, 1025, 1029, 1020, 1034, 1035, 1041, 1036,
- /* 250 */ 987, 1016, 1027, 1043, 1044, 1045, 1048, 1074, 1067, 1075,
- /* 260 */ 1072, 1077, 1078, 1080, 1019, 1021, 1083, 1084, 1047, 1051,
- /* 270 */ 1023, 1046, 1086, 1054, 1057, 1059, 1061, 1049, 1063, 1037,
- /* 280 */ 1093, 1022, 1024, 1098, 1100, 1038, 1096, 1082, 1085, 1042,
- /* 290 */ 1050, 1052,
+ /* 120 */ -115, 164, 407, 407, 350, 141, 51, 163, 596, -90,
+ /* 130 */ 436, 218, 765, 438, 586, 592, 595, 715, 718, 408,
+ /* 140 */ 754, 380, 634, 677, 798, 801, 144, 529, 588, 49,
+ /* 150 */ 176, 244, 264, 329, 457, 329, 329, 451, 477, 494,
+ /* 160 */ 507, 509, 528, 590, 730, 642, 509, 743, 839, 864,
+ /* 170 */ 879, 834, 894, 900, 329, 834, 907, 914, 826, 886,
+ /* 180 */ 919, 927, 937, 329, 951, 961, 329, 972, 897, 898,
+ /* 190 */ 989, 990, 329, 991, 992, 995, 329, 996, 999, 1004,
+ /* 200 */ 329, 329, 1005, 1006, 1007, 1008, 1009, 1010, 966, 967,
+ /* 210 */ 997, 933, 938, 940, 993, 998, 1000, 984, 1001, 1003,
+ /* 220 */ 1002, 1014, 1011, 974, 977, 1023, 1030, 1031, 1032, 1026,
+ /* 230 */ 1012, 988, 1013, 1015, 1017, 1018, 968, 1039, 1040, 1019,
+ /* 240 */ 1020, 1022, 1024, 1025, 1027, 1021, 1033, 1034, 1035, 1036,
+ /* 250 */ 979, 983, 1038, 1041, 1042, 1044, 1045, 1069, 1072, 1071,
+ /* 260 */ 1075, 1077, 1078, 1080, 1028, 1037, 1083, 1084, 1051, 1053,
+ /* 270 */ 1043, 1046, 1089, 1055, 1056, 1057, 1061, 1052, 1063, 1047,
+ /* 280 */ 1093, 1048, 1049, 1098, 1099, 1050, 1094, 1081, 1085, 1062,
+ /* 290 */ 1054, 1064,
};
static const YYACTIONTYPE yy_default[] = {
- /* 0 */ 594, 819, 900, 709, 900, 819, 900, 900, 846, 713,
- /* 10 */ 875, 817, 900, 900, 900, 900, 791, 900, 846, 900,
- /* 20 */ 625, 846, 846, 742, 900, 900, 900, 900, 900, 900,
- /* 30 */ 900, 900, 743, 900, 821, 816, 812, 814, 813, 820,
- /* 40 */ 744, 733, 740, 747, 725, 859, 749, 750, 756, 757,
- /* 50 */ 876, 874, 779, 778, 797, 900, 900, 900, 900, 900,
- /* 60 */ 900, 900, 900, 900, 900, 900, 900, 900, 900, 900,
- /* 70 */ 900, 900, 900, 900, 900, 900, 900, 900, 900, 900,
- /* 80 */ 900, 900, 900, 900, 900, 900, 900, 900, 900, 900,
- /* 90 */ 900, 900, 900, 900, 900, 900, 781, 803, 780, 790,
- /* 100 */ 618, 782, 783, 678, 613, 900, 900, 900, 900, 900,
- /* 110 */ 900, 900, 784, 900, 785, 798, 799, 800, 900, 900,
- /* 120 */ 900, 900, 900, 900, 594, 709, 900, 709, 900, 900,
- /* 130 */ 900, 900, 900, 900, 900, 900, 900, 900, 900, 900,
- /* 140 */ 900, 900, 900, 900, 900, 900, 703, 713, 893, 900,
- /* 150 */ 900, 669, 900, 900, 900, 900, 900, 900, 900, 900,
- /* 160 */ 900, 900, 601, 599, 900, 701, 900, 900, 627, 900,
- /* 170 */ 900, 711, 900, 900, 716, 717, 900, 900, 900, 900,
- /* 180 */ 900, 900, 900, 615, 900, 900, 690, 900, 852, 900,
- /* 190 */ 900, 900, 866, 900, 900, 900, 864, 900, 900, 900,
- /* 200 */ 692, 752, 833, 900, 879, 881, 900, 900, 701, 710,
- /* 210 */ 900, 900, 900, 815, 736, 736, 736, 648, 736, 900,
- /* 220 */ 736, 900, 651, 746, 746, 598, 598, 598, 598, 668,
- /* 230 */ 900, 746, 737, 739, 729, 741, 900, 718, 718, 726,
- /* 240 */ 728, 726, 728, 680, 680, 665, 680, 651, 680, 825,
- /* 250 */ 830, 830, 665, 680, 680, 680, 825, 610, 718, 610,
- /* 260 */ 718, 610, 718, 718, 856, 858, 610, 718, 682, 682,
- /* 270 */ 758, 746, 718, 689, 689, 689, 689, 746, 682, 758,
- /* 280 */ 718, 878, 878, 718, 718, 886, 635, 653, 653, 861,
- /* 290 */ 893, 898, 900, 900, 900, 900, 765, 900, 900, 900,
- /* 300 */ 900, 900, 900, 900, 900, 900, 900, 900, 900, 900,
- /* 310 */ 839, 900, 900, 900, 900, 770, 766, 900, 767, 900,
- /* 320 */ 695, 900, 900, 900, 900, 900, 900, 900, 900, 900,
- /* 330 */ 900, 818, 900, 730, 900, 738, 900, 900, 900, 900,
- /* 340 */ 900, 900, 900, 900, 900, 900, 900, 900, 900, 900,
- /* 350 */ 900, 900, 900, 900, 900, 900, 900, 900, 900, 900,
- /* 360 */ 854, 855, 900, 900, 900, 900, 900, 900, 900, 900,
- /* 370 */ 900, 900, 900, 900, 900, 900, 900, 900, 900, 900,
- /* 380 */ 900, 900, 900, 900, 885, 900, 900, 888, 595, 900,
- /* 390 */ 589, 592, 591, 593, 597, 600, 622, 623, 624, 602,
- /* 400 */ 603, 604, 605, 606, 607, 608, 614, 616, 634, 636,
- /* 410 */ 620, 638, 699, 700, 762, 693, 694, 698, 621, 773,
- /* 420 */ 764, 768, 769, 771, 772, 786, 787, 789, 795, 802,
- /* 430 */ 805, 788, 793, 794, 796, 801, 804, 696, 697, 808,
- /* 440 */ 628, 629, 632, 633, 842, 844, 843, 845, 631, 630,
- /* 450 */ 774, 777, 810, 811, 867, 868, 869, 870, 871, 806,
- /* 460 */ 719, 809, 792, 731, 734, 735, 732, 702, 712, 721,
- /* 470 */ 722, 723, 724, 707, 708, 714, 727, 760, 761, 715,
- /* 480 */ 704, 705, 706, 807, 763, 775, 776, 639, 640, 770,
- /* 490 */ 641, 642, 643, 681, 684, 685, 686, 644, 663, 666,
- /* 500 */ 667, 645, 652, 646, 647, 654, 655, 656, 659, 660,
- /* 510 */ 661, 662, 657, 658, 826, 827, 831, 829, 828, 649,
- /* 520 */ 650, 664, 637, 626, 619, 670, 673, 674, 675, 676,
- /* 530 */ 677, 679, 671, 672, 617, 609, 611, 720, 848, 857,
- /* 540 */ 853, 849, 850, 851, 612, 822, 823, 683, 754, 755,
- /* 550 */ 847, 860, 862, 759, 863, 865, 890, 687, 688, 691,
- /* 560 */ 832, 872, 745, 748, 751, 753, 834, 835, 836, 837,
- /* 570 */ 840, 841, 838, 873, 877, 880, 882, 883, 884, 887,
- /* 580 */ 889, 894, 895, 896, 899, 897, 596, 590,
+ /* 0 */ 595, 820, 902, 710, 902, 820, 902, 902, 848, 714,
+ /* 10 */ 877, 818, 902, 902, 902, 902, 792, 902, 848, 902,
+ /* 20 */ 626, 848, 848, 743, 902, 902, 902, 902, 902, 902,
+ /* 30 */ 902, 902, 744, 902, 822, 817, 813, 815, 814, 821,
+ /* 40 */ 745, 734, 741, 748, 726, 861, 750, 751, 757, 758,
+ /* 50 */ 878, 876, 780, 779, 798, 902, 902, 902, 902, 902,
+ /* 60 */ 902, 902, 902, 902, 902, 902, 902, 902, 902, 902,
+ /* 70 */ 902, 902, 902, 902, 902, 902, 902, 902, 902, 902,
+ /* 80 */ 902, 902, 902, 902, 902, 902, 902, 902, 902, 902,
+ /* 90 */ 902, 902, 902, 902, 902, 902, 782, 804, 781, 791,
+ /* 100 */ 619, 783, 784, 679, 614, 902, 902, 902, 902, 902,
+ /* 110 */ 902, 902, 785, 902, 786, 799, 800, 801, 902, 902,
+ /* 120 */ 902, 902, 902, 902, 595, 710, 902, 710, 902, 902,
+ /* 130 */ 902, 902, 902, 902, 902, 902, 902, 902, 902, 902,
+ /* 140 */ 902, 902, 902, 902, 902, 902, 704, 714, 895, 902,
+ /* 150 */ 902, 670, 902, 902, 902, 902, 902, 902, 902, 902,
+ /* 160 */ 902, 902, 602, 600, 902, 702, 902, 902, 628, 902,
+ /* 170 */ 902, 712, 902, 902, 717, 718, 902, 902, 902, 902,
+ /* 180 */ 902, 902, 902, 616, 902, 902, 691, 902, 854, 902,
+ /* 190 */ 902, 902, 868, 902, 902, 902, 866, 902, 902, 902,
+ /* 200 */ 693, 753, 834, 902, 881, 883, 902, 902, 702, 711,
+ /* 210 */ 902, 902, 902, 816, 737, 737, 737, 649, 737, 902,
+ /* 220 */ 737, 902, 652, 747, 747, 599, 599, 599, 599, 669,
+ /* 230 */ 902, 747, 738, 740, 730, 742, 902, 719, 719, 727,
+ /* 240 */ 729, 727, 729, 681, 681, 666, 681, 652, 681, 826,
+ /* 250 */ 831, 831, 666, 681, 681, 681, 826, 611, 719, 611,
+ /* 260 */ 719, 611, 719, 719, 858, 860, 611, 719, 683, 683,
+ /* 270 */ 759, 747, 719, 690, 690, 690, 690, 747, 683, 759,
+ /* 280 */ 719, 880, 880, 719, 719, 888, 636, 654, 654, 863,
+ /* 290 */ 895, 900, 902, 902, 902, 902, 766, 902, 902, 902,
+ /* 300 */ 902, 902, 902, 902, 902, 902, 902, 902, 902, 902,
+ /* 310 */ 841, 902, 902, 902, 902, 771, 767, 902, 768, 902,
+ /* 320 */ 696, 902, 902, 902, 902, 902, 902, 902, 902, 902,
+ /* 330 */ 902, 819, 902, 731, 902, 739, 902, 902, 902, 902,
+ /* 340 */ 902, 902, 902, 902, 902, 902, 902, 902, 902, 902,
+ /* 350 */ 902, 902, 902, 902, 902, 902, 902, 902, 902, 902,
+ /* 360 */ 856, 857, 902, 902, 902, 902, 902, 902, 902, 902,
+ /* 370 */ 902, 902, 902, 902, 902, 902, 902, 902, 902, 902,
+ /* 380 */ 902, 902, 902, 902, 887, 902, 902, 890, 596, 902,
+ /* 390 */ 590, 593, 592, 594, 598, 601, 623, 624, 625, 603,
+ /* 400 */ 604, 605, 606, 607, 608, 609, 615, 617, 635, 637,
+ /* 410 */ 621, 639, 700, 701, 763, 694, 695, 699, 622, 774,
+ /* 420 */ 765, 769, 770, 772, 773, 787, 788, 790, 796, 803,
+ /* 430 */ 806, 789, 794, 795, 797, 802, 805, 697, 698, 809,
+ /* 440 */ 629, 630, 633, 634, 844, 846, 845, 847, 632, 631,
+ /* 450 */ 775, 778, 811, 812, 869, 870, 871, 872, 873, 807,
+ /* 460 */ 720, 810, 793, 732, 735, 736, 733, 703, 713, 722,
+ /* 470 */ 723, 724, 725, 708, 709, 715, 728, 761, 762, 716,
+ /* 480 */ 705, 706, 707, 808, 764, 776, 777, 640, 641, 771,
+ /* 490 */ 642, 643, 644, 682, 685, 686, 687, 645, 664, 667,
+ /* 500 */ 668, 646, 653, 647, 648, 655, 656, 657, 660, 661,
+ /* 510 */ 662, 663, 658, 659, 827, 828, 832, 830, 829, 650,
+ /* 520 */ 651, 665, 638, 627, 620, 671, 674, 675, 676, 677,
+ /* 530 */ 678, 680, 672, 673, 618, 610, 612, 721, 850, 859,
+ /* 540 */ 855, 851, 852, 853, 613, 823, 824, 684, 755, 756,
+ /* 550 */ 849, 862, 864, 760, 865, 867, 892, 688, 689, 692,
+ /* 560 */ 833, 874, 746, 749, 752, 754, 835, 836, 837, 838,
+ /* 570 */ 839, 842, 843, 840, 875, 879, 882, 884, 885, 886,
+ /* 580 */ 889, 891, 896, 897, 898, 901, 899, 597, 591,
};
#define YY_SZ_ACTTAB (int)(sizeof(yy_action)/sizeof(yy_action[0]))
/* The next table maps tokens into fallback tokens. If a construct
@@ -70239,71 +74019,72 @@
/* 245 */ "cmd ::= VACUUM",
/* 246 */ "cmd ::= VACUUM nm",
/* 247 */ "cmd ::= PRAGMA nm dbnm EQ nmnum",
/* 248 */ "cmd ::= PRAGMA nm dbnm EQ ON",
- /* 249 */ "cmd ::= PRAGMA nm dbnm EQ minus_num",
- /* 250 */ "cmd ::= PRAGMA nm dbnm LP nmnum RP",
- /* 251 */ "cmd ::= PRAGMA nm dbnm",
- /* 252 */ "nmnum ::= plus_num",
- /* 253 */ "nmnum ::= nm",
- /* 254 */ "plus_num ::= plus_opt number",
- /* 255 */ "minus_num ::= MINUS number",
- /* 256 */ "number ::= INTEGER|FLOAT",
- /* 257 */ "plus_opt ::= PLUS",
- /* 258 */ "plus_opt ::=",
- /* 259 */ "cmd ::= CREATE trigger_decl BEGIN trigger_cmd_list END",
- /* 260 */ "trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause",
- /* 261 */ "trigger_time ::= BEFORE",
- /* 262 */ "trigger_time ::= AFTER",
- /* 263 */ "trigger_time ::= INSTEAD OF",
- /* 264 */ "trigger_time ::=",
- /* 265 */ "trigger_event ::= DELETE|INSERT",
- /* 266 */ "trigger_event ::= UPDATE",
- /* 267 */ "trigger_event ::= UPDATE OF inscollist",
- /* 268 */ "foreach_clause ::=",
- /* 269 */ "foreach_clause ::= FOR EACH ROW",
- /* 270 */ "when_clause ::=",
- /* 271 */ "when_clause ::= WHEN expr",
- /* 272 */ "trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI",
- /* 273 */ "trigger_cmd_list ::=",
- /* 274 */ "trigger_cmd ::= UPDATE orconf nm SET setlist where_opt",
- /* 275 */ "trigger_cmd ::= insert_cmd INTO nm inscollist_opt VALUES LP itemlist RP",
- /* 276 */ "trigger_cmd ::= insert_cmd INTO nm inscollist_opt select",
- /* 277 */ "trigger_cmd ::= DELETE FROM nm where_opt",
- /* 278 */ "trigger_cmd ::= select",
- /* 279 */ "expr ::= RAISE LP IGNORE RP",
- /* 280 */ "expr ::= RAISE LP raisetype COMMA nm RP",
- /* 281 */ "raisetype ::= ROLLBACK",
- /* 282 */ "raisetype ::= ABORT",
- /* 283 */ "raisetype ::= FAIL",
- /* 284 */ "cmd ::= DROP TRIGGER ifexists fullname",
- /* 285 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt",
- /* 286 */ "cmd ::= DETACH database_kw_opt expr",
- /* 287 */ "key_opt ::=",
- /* 288 */ "key_opt ::= KEY expr",
- /* 289 */ "database_kw_opt ::= DATABASE",
- /* 290 */ "database_kw_opt ::=",
- /* 291 */ "cmd ::= REINDEX",
- /* 292 */ "cmd ::= REINDEX nm dbnm",
- /* 293 */ "cmd ::= ANALYZE",
- /* 294 */ "cmd ::= ANALYZE nm dbnm",
- /* 295 */ "cmd ::= ALTER TABLE fullname RENAME TO nm",
- /* 296 */ "cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt column",
- /* 297 */ "add_column_fullname ::= fullname",
- /* 298 */ "kwcolumn_opt ::=",
- /* 299 */ "kwcolumn_opt ::= COLUMNKW",
- /* 300 */ "cmd ::= create_vtab",
- /* 301 */ "cmd ::= create_vtab LP vtabarglist RP",
- /* 302 */ "create_vtab ::= CREATE VIRTUAL TABLE nm dbnm USING nm",
- /* 303 */ "vtabarglist ::= vtabarg",
- /* 304 */ "vtabarglist ::= vtabarglist COMMA vtabarg",
- /* 305 */ "vtabarg ::=",
- /* 306 */ "vtabarg ::= vtabarg vtabargtoken",
- /* 307 */ "vtabargtoken ::= ANY",
- /* 308 */ "vtabargtoken ::= lp anylist RP",
- /* 309 */ "lp ::= LP",
- /* 310 */ "anylist ::=",
- /* 311 */ "anylist ::= anylist ANY",
+ /* 249 */ "cmd ::= PRAGMA nm dbnm EQ DELETE",
+ /* 250 */ "cmd ::= PRAGMA nm dbnm EQ minus_num",
+ /* 251 */ "cmd ::= PRAGMA nm dbnm LP nmnum RP",
+ /* 252 */ "cmd ::= PRAGMA nm dbnm",
+ /* 253 */ "nmnum ::= plus_num",
+ /* 254 */ "nmnum ::= nm",
+ /* 255 */ "plus_num ::= plus_opt number",
+ /* 256 */ "minus_num ::= MINUS number",
+ /* 257 */ "number ::= INTEGER|FLOAT",
+ /* 258 */ "plus_opt ::= PLUS",
+ /* 259 */ "plus_opt ::=",
+ /* 260 */ "cmd ::= CREATE trigger_decl BEGIN trigger_cmd_list END",
+ /* 261 */ "trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause",
+ /* 262 */ "trigger_time ::= BEFORE",
+ /* 263 */ "trigger_time ::= AFTER",
+ /* 264 */ "trigger_time ::= INSTEAD OF",
+ /* 265 */ "trigger_time ::=",
+ /* 266 */ "trigger_event ::= DELETE|INSERT",
+ /* 267 */ "trigger_event ::= UPDATE",
+ /* 268 */ "trigger_event ::= UPDATE OF inscollist",
+ /* 269 */ "foreach_clause ::=",
+ /* 270 */ "foreach_clause ::= FOR EACH ROW",
+ /* 271 */ "when_clause ::=",
+ /* 272 */ "when_clause ::= WHEN expr",
+ /* 273 */ "trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI",
+ /* 274 */ "trigger_cmd_list ::=",
+ /* 275 */ "trigger_cmd ::= UPDATE orconf nm SET setlist where_opt",
+ /* 276 */ "trigger_cmd ::= insert_cmd INTO nm inscollist_opt VALUES LP itemlist RP",
+ /* 277 */ "trigger_cmd ::= insert_cmd INTO nm inscollist_opt select",
+ /* 278 */ "trigger_cmd ::= DELETE FROM nm where_opt",
+ /* 279 */ "trigger_cmd ::= select",
+ /* 280 */ "expr ::= RAISE LP IGNORE RP",
+ /* 281 */ "expr ::= RAISE LP raisetype COMMA nm RP",
+ /* 282 */ "raisetype ::= ROLLBACK",
+ /* 283 */ "raisetype ::= ABORT",
+ /* 284 */ "raisetype ::= FAIL",
+ /* 285 */ "cmd ::= DROP TRIGGER ifexists fullname",
+ /* 286 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt",
+ /* 287 */ "cmd ::= DETACH database_kw_opt expr",
+ /* 288 */ "key_opt ::=",
+ /* 289 */ "key_opt ::= KEY expr",
+ /* 290 */ "database_kw_opt ::= DATABASE",
+ /* 291 */ "database_kw_opt ::=",
+ /* 292 */ "cmd ::= REINDEX",
+ /* 293 */ "cmd ::= REINDEX nm dbnm",
+ /* 294 */ "cmd ::= ANALYZE",
+ /* 295 */ "cmd ::= ANALYZE nm dbnm",
+ /* 296 */ "cmd ::= ALTER TABLE fullname RENAME TO nm",
+ /* 297 */ "cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt column",
+ /* 298 */ "add_column_fullname ::= fullname",
+ /* 299 */ "kwcolumn_opt ::=",
+ /* 300 */ "kwcolumn_opt ::= COLUMNKW",
+ /* 301 */ "cmd ::= create_vtab",
+ /* 302 */ "cmd ::= create_vtab LP vtabarglist RP",
+ /* 303 */ "create_vtab ::= CREATE VIRTUAL TABLE nm dbnm USING nm",
+ /* 304 */ "vtabarglist ::= vtabarg",
+ /* 305 */ "vtabarglist ::= vtabarglist COMMA vtabarg",
+ /* 306 */ "vtabarg ::=",
+ /* 307 */ "vtabarg ::= vtabarg vtabargtoken",
+ /* 308 */ "vtabargtoken ::= ANY",
+ /* 309 */ "vtabargtoken ::= lp anylist RP",
+ /* 310 */ "lp ::= LP",
+ /* 311 */ "anylist ::=",
+ /* 312 */ "anylist ::= anylist ANY",
};
#endif /* NDEBUG */
@@ -70371,56 +74152,186 @@
** which appear on the RHS of the rule, but which are not used
** inside the C code.
*/
case 155: /* select */
- case 189: /* oneselect */
- case 206: /* seltablist_paren */
-{sqlite3SelectDelete((yypminor->yy219));}
+{
+sqlite3SelectDelete((yypminor->yy219));
+}
break;
case 169: /* term */
+{
+sqlite3ExprDelete((yypminor->yy172));
+}
+ break;
case 170: /* expr */
- case 194: /* where_opt */
- case 196: /* having_opt */
- case 204: /* on_opt */
- case 210: /* sortitem */
- case 218: /* escape */
- case 221: /* case_operand */
- case 223: /* case_else */
- case 235: /* when_clause */
- case 238: /* key_opt */
-{sqlite3ExprDelete((yypminor->yy172));}
+{
+sqlite3ExprDelete((yypminor->yy172));
+}
break;
case 174: /* idxlist_opt */
+{
+sqlite3ExprListDelete((yypminor->yy174));
+}
+ break;
case 182: /* idxlist */
- case 192: /* selcollist */
- case 195: /* groupby_opt */
- case 197: /* orderby_opt */
- case 199: /* sclp */
- case 209: /* sortlist */
- case 211: /* nexprlist */
- case 212: /* setlist */
- case 215: /* itemlist */
- case 216: /* exprlist */
- case 222: /* case_exprlist */
-{sqlite3ExprListDelete((yypminor->yy174));}
+{
+sqlite3ExprListDelete((yypminor->yy174));
+}
break;
case 188: /* fullname */
+{
+sqlite3SrcListDelete((yypminor->yy373));
+}
+ break;
+ case 189: /* oneselect */
+{
+sqlite3SelectDelete((yypminor->yy219));
+}
+ break;
+ case 192: /* selcollist */
+{
+sqlite3ExprListDelete((yypminor->yy174));
+}
+ break;
case 193: /* from */
+{
+sqlite3SrcListDelete((yypminor->yy373));
+}
+ break;
+ case 194: /* where_opt */
+{
+sqlite3ExprDelete((yypminor->yy172));
+}
+ break;
+ case 195: /* groupby_opt */
+{
+sqlite3ExprListDelete((yypminor->yy174));
+}
+ break;
+ case 196: /* having_opt */
+{
+sqlite3ExprDelete((yypminor->yy172));
+}
+ break;
+ case 197: /* orderby_opt */
+{
+sqlite3ExprListDelete((yypminor->yy174));
+}
+ break;
+ case 199: /* sclp */
+{
+sqlite3ExprListDelete((yypminor->yy174));
+}
+ break;
case 201: /* seltablist */
+{
+sqlite3SrcListDelete((yypminor->yy373));
+}
+ break;
case 202: /* stl_prefix */
-{sqlite3SrcListDelete((yypminor->yy373));}
+{
+sqlite3SrcListDelete((yypminor->yy373));
+}
+ break;
+ case 204: /* on_opt */
+{
+sqlite3ExprDelete((yypminor->yy172));
+}
break;
case 205: /* using_opt */
+{
+sqlite3IdListDelete((yypminor->yy432));
+}
+ break;
+ case 206: /* seltablist_paren */
+{
+sqlite3SelectDelete((yypminor->yy219));
+}
+ break;
case 208: /* inscollist */
+{
+sqlite3IdListDelete((yypminor->yy432));
+}
+ break;
+ case 209: /* sortlist */
+{
+sqlite3ExprListDelete((yypminor->yy174));
+}
+ break;
+ case 210: /* sortitem */
+{
+sqlite3ExprDelete((yypminor->yy172));
+}
+ break;
+ case 211: /* nexprlist */
+{
+sqlite3ExprListDelete((yypminor->yy174));
+}
+ break;
+ case 212: /* setlist */
+{
+sqlite3ExprListDelete((yypminor->yy174));
+}
+ break;
case 214: /* inscollist_opt */
-{sqlite3IdListDelete((yypminor->yy432));}
+{
+sqlite3IdListDelete((yypminor->yy432));
+}
+ break;
+ case 215: /* itemlist */
+{
+sqlite3ExprListDelete((yypminor->yy174));
+}
+ break;
+ case 216: /* exprlist */
+{
+sqlite3ExprListDelete((yypminor->yy174));
+}
+ break;
+ case 218: /* escape */
+{
+sqlite3ExprDelete((yypminor->yy172));
+}
+ break;
+ case 221: /* case_operand */
+{
+sqlite3ExprDelete((yypminor->yy172));
+}
+ break;
+ case 222: /* case_exprlist */
+{
+sqlite3ExprListDelete((yypminor->yy174));
+}
+ break;
+ case 223: /* case_else */
+{
+sqlite3ExprDelete((yypminor->yy172));
+}
break;
case 231: /* trigger_cmd_list */
- case 236: /* trigger_cmd */
-{sqlite3DeleteTriggerStep((yypminor->yy243));}
+{
+sqlite3DeleteTriggerStep((yypminor->yy243));
+}
break;
case 233: /* trigger_event */
-{sqlite3IdListDelete((yypminor->yy370).b);}
+{
+sqlite3IdListDelete((yypminor->yy370).b);
+}
+ break;
+ case 235: /* when_clause */
+{
+sqlite3ExprDelete((yypminor->yy172));
+}
+ break;
+ case 236: /* trigger_cmd */
+{
+sqlite3DeleteTriggerStep((yypminor->yy243));
+}
+ break;
+ case 238: /* key_opt */
+{
+sqlite3ExprDelete((yypminor->yy172));
+}
break;
default: break; /* If no destructor action specified: do nothing */
}
}
@@ -70544,15 +74455,27 @@
int stateno, /* Current state number */
YYCODETYPE iLookAhead /* The look-ahead token */
){
int i;
+#ifdef YYERRORSYMBOL
+ if( stateno>YY_REDUCE_MAX ){
+ return yy_default[stateno];
+ }
+#else
assert( stateno<=YY_REDUCE_MAX );
+#endif
i = yy_reduce_ofst[stateno];
assert( i!=YY_REDUCE_USE_DFLT );
assert( iLookAhead!=YYNOCODE );
i += iLookAhead;
+#ifdef YYERRORSYMBOL
+ if( i<0 || i>=YY_SZ_ACTTAB || yy_lookahead[i]!=iLookAhead ){
+ return yy_default[stateno];
+ }
+#else
assert( i>=0 && i<YY_SZ_ACTTAB );
assert( yy_lookahead[i]==iLookAhead );
+#endif
return yy_action[i];
}
/*
@@ -70872,8 +74795,9 @@
{ 143, 2 },
{ 143, 5 },
{ 143, 5 },
{ 143, 5 },
+ { 143, 5 },
{ 143, 6 },
{ 143, 3 },
{ 227, 1 },
{ 227, 1 },
@@ -70975,9 +74899,10 @@
** parser is doing to make this happen. This is the second bug report
** from wireshark this week. Clearly they are stressing Lemon in ways
** that it has not been previously stressed... (SQLite ticket #2172)
*/
- memset(&yygotominor, 0, sizeof(yygotominor));
+ /*memset(&yygotominor, 0, sizeof(yygotominor));*/
+ yygotominor = yyzerominor;
switch( yyruleno ){
/* Beginning here are the reduction cases. A typical example
@@ -71010,20 +74935,20 @@
case 82: /* conslist ::= conslist COMMA tcons */
case 83: /* conslist ::= conslist tcons */
case 84: /* conslist ::= tcons */
case 85: /* tcons ::= CONSTRAINT nm */
- case 257: /* plus_opt ::= PLUS */
- case 258: /* plus_opt ::= */
- case 268: /* foreach_clause ::= */
- case 269: /* foreach_clause ::= FOR EACH ROW */
- case 289: /* database_kw_opt ::= DATABASE */
- case 290: /* database_kw_opt ::= */
- case 298: /* kwcolumn_opt ::= */
- case 299: /* kwcolumn_opt ::= COLUMNKW */
- case 303: /* vtabarglist ::= vtabarg */
- case 304: /* vtabarglist ::= vtabarglist COMMA vtabarg */
- case 306: /* vtabarg ::= vtabarg vtabargtoken */
- case 310: /* anylist ::= */
+ case 258: /* plus_opt ::= PLUS */
+ case 259: /* plus_opt ::= */
+ case 269: /* foreach_clause ::= */
+ case 270: /* foreach_clause ::= FOR EACH ROW */
+ case 290: /* database_kw_opt ::= DATABASE */
+ case 291: /* database_kw_opt ::= */
+ case 299: /* kwcolumn_opt ::= */
+ case 300: /* kwcolumn_opt ::= COLUMNKW */
+ case 304: /* vtabarglist ::= vtabarg */
+ case 305: /* vtabarglist ::= vtabarglist COMMA vtabarg */
+ case 307: /* vtabarg ::= vtabarg vtabargtoken */
+ case 311: /* anylist ::= */
{
}
break;
case 3: /* cmdx ::= cmd */
@@ -71113,9 +75038,9 @@
case 33: /* ids ::= ID|STRING */
case 34: /* nm ::= ID */
case 35: /* nm ::= STRING */
case 36: /* nm ::= JOIN_KW */
- case 256: /* number ::= INTEGER|FLOAT */
+ case 257: /* number ::= INTEGER|FLOAT */
{yygotominor.yy410 = yymsp[0].minor.yy0;}
break;
case 38: /* type ::= typetoken */
{sqlite3AddColumnType(pParse,&yymsp[0].minor.yy410);}
@@ -71126,12 +75051,12 @@
case 120: /* as ::= ids */
case 131: /* dbnm ::= DOT nm */
case 241: /* idxitem ::= nm */
case 243: /* collate ::= COLLATE ids */
- case 252: /* nmnum ::= plus_num */
- case 253: /* nmnum ::= nm */
- case 254: /* plus_num ::= plus_opt number */
- case 255: /* minus_num ::= MINUS number */
+ case 253: /* nmnum ::= plus_num */
+ case 254: /* nmnum ::= nm */
+ case 255: /* plus_num ::= plus_opt number */
+ case 256: /* minus_num ::= MINUS number */
{yygotominor.yy410 = yymsp[0].minor.yy410;}
break;
case 40: /* typetoken ::= typename LP signed RP */
{
@@ -71275,9 +75200,9 @@
}
break;
case 104: /* cmd ::= select */
{
- SelectDest dest = {SRT_Callback, 0, 0};
+ SelectDest dest = {SRT_Callback, 0, 0, 0, 0};
sqlite3Select(pParse, yymsp[0].minor.yy219, &dest, 0, 0, 0, 0);
sqlite3SelectDelete(yymsp[0].minor.yy219);
}
break;
@@ -71455,9 +75380,9 @@
{sqlite3DeleteFrom(pParse,yymsp[-1].minor.yy373,yymsp[0].minor.yy172);}
break;
case 160: /* cmd ::= UPDATE orconf fullname SET setlist where_opt */
{
- sqlite3ExprListCheckLength(pParse,yymsp[-1].minor.yy174,SQLITE_MAX_COLUMN,"set list");
+ sqlite3ExprListCheckLength(pParse,yymsp[-1].minor.yy174,"set list");
sqlite3Update(pParse,yymsp[-3].minor.yy373,yymsp[-1].minor.yy174,yymsp[0].minor.yy172,yymsp[-4].minor.yy46);
}
break;
case 161: /* setlist ::= setlist COMMA nm EQ expr */
@@ -71751,9 +75676,9 @@
&yymsp[-10].minor.yy0, &yymsp[0].minor.yy0, SQLITE_SO_ASC, yymsp[-7].minor.yy46);
}
break;
case 235: /* uniqueflag ::= UNIQUE */
- case 282: /* raisetype ::= ABORT */
+ case 283: /* raisetype ::= ABORT */
{yygotominor.yy46 = OE_Abort;}
break;
case 236: /* uniqueflag ::= */
{yygotominor.yy46 = OE_None;}
@@ -71765,9 +75690,9 @@
p = sqlite3PExpr(pParse, TK_COLUMN, 0, 0, 0);
sqlite3ExprSetColl(pParse, p, &yymsp[-1].minor.yy410);
}
yygotominor.yy174 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy174, p, &yymsp[-2].minor.yy410);
- sqlite3ExprListCheckLength(pParse, yygotominor.yy174, SQLITE_MAX_COLUMN, "index");
+ sqlite3ExprListCheckLength(pParse, yygotominor.yy174, "index");
if( yygotominor.yy174 ) yygotominor.yy174->a[yygotominor.yy174->nExpr-1].sortOrder = yymsp[0].minor.yy46;
}
break;
case 240: /* idxlist ::= idxitem collate sortorder */
@@ -71777,9 +75702,9 @@
p = sqlite3PExpr(pParse, TK_COLUMN, 0, 0, 0);
sqlite3ExprSetColl(pParse, p, &yymsp[-1].minor.yy410);
}
yygotominor.yy174 = sqlite3ExprListAppend(pParse,0, p, &yymsp[-2].minor.yy410);
- sqlite3ExprListCheckLength(pParse, yygotominor.yy174, SQLITE_MAX_COLUMN, "index");
+ sqlite3ExprListCheckLength(pParse, yygotominor.yy174, "index");
if( yygotominor.yy174 ) yygotominor.yy174->a[yygotominor.yy174->nExpr-1].sortOrder = yymsp[0].minor.yy46;
}
break;
case 242: /* collate ::= */
@@ -71795,61 +75720,62 @@
case 247: /* cmd ::= PRAGMA nm dbnm EQ nmnum */
{sqlite3Pragma(pParse,&yymsp[-3].minor.yy410,&yymsp[-2].minor.yy410,&yymsp[0].minor.yy410,0);}
break;
case 248: /* cmd ::= PRAGMA nm dbnm EQ ON */
+ case 249: /* cmd ::= PRAGMA nm dbnm EQ DELETE */
{sqlite3Pragma(pParse,&yymsp[-3].minor.yy410,&yymsp[-2].minor.yy410,&yymsp[0].minor.yy0,0);}
break;
- case 249: /* cmd ::= PRAGMA nm dbnm EQ minus_num */
+ case 250: /* cmd ::= PRAGMA nm dbnm EQ minus_num */
{
sqlite3Pragma(pParse,&yymsp[-3].minor.yy410,&yymsp[-2].minor.yy410,&yymsp[0].minor.yy410,1);
}
break;
- case 250: /* cmd ::= PRAGMA nm dbnm LP nmnum RP */
+ case 251: /* cmd ::= PRAGMA nm dbnm LP nmnum RP */
{sqlite3Pragma(pParse,&yymsp[-4].minor.yy410,&yymsp[-3].minor.yy410,&yymsp[-1].minor.yy410,0);}
break;
- case 251: /* cmd ::= PRAGMA nm dbnm */
+ case 252: /* cmd ::= PRAGMA nm dbnm */
{sqlite3Pragma(pParse,&yymsp[-1].minor.yy410,&yymsp[0].minor.yy410,0,0);}
break;
- case 259: /* cmd ::= CREATE trigger_decl BEGIN trigger_cmd_list END */
+ case 260: /* cmd ::= CREATE trigger_decl BEGIN trigger_cmd_list END */
{
Token all;
all.z = yymsp[-3].minor.yy410.z;
all.n = (yymsp[0].minor.yy0.z - yymsp[-3].minor.yy410.z) + yymsp[0].minor.yy0.n;
sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy243, &all);
}
break;
- case 260: /* trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */
+ case 261: /* trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */
{
sqlite3BeginTrigger(pParse, &yymsp[-7].minor.yy410, &yymsp[-6].minor.yy410, yymsp[-5].minor.yy46, yymsp[-4].minor.yy370.a, yymsp[-4].minor.yy370.b, yymsp[-2].minor.yy373, yymsp[0].minor.yy172, yymsp[-10].minor.yy46, yymsp[-8].minor.yy46);
yygotominor.yy410 = (yymsp[-6].minor.yy410.n==0?yymsp[-7].minor.yy410:yymsp[-6].minor.yy410);
}
break;
- case 261: /* trigger_time ::= BEFORE */
- case 264: /* trigger_time ::= */
+ case 262: /* trigger_time ::= BEFORE */
+ case 265: /* trigger_time ::= */
{ yygotominor.yy46 = TK_BEFORE; }
break;
- case 262: /* trigger_time ::= AFTER */
+ case 263: /* trigger_time ::= AFTER */
{ yygotominor.yy46 = TK_AFTER; }
break;
- case 263: /* trigger_time ::= INSTEAD OF */
+ case 264: /* trigger_time ::= INSTEAD OF */
{ yygotominor.yy46 = TK_INSTEAD;}
break;
- case 265: /* trigger_event ::= DELETE|INSERT */
- case 266: /* trigger_event ::= UPDATE */
+ case 266: /* trigger_event ::= DELETE|INSERT */
+ case 267: /* trigger_event ::= UPDATE */
{yygotominor.yy370.a = yymsp[0].major; yygotominor.yy370.b = 0;}
break;
- case 267: /* trigger_event ::= UPDATE OF inscollist */
+ case 268: /* trigger_event ::= UPDATE OF inscollist */
{yygotominor.yy370.a = TK_UPDATE; yygotominor.yy370.b = yymsp[0].minor.yy432;}
break;
- case 270: /* when_clause ::= */
- case 287: /* key_opt ::= */
+ case 271: /* when_clause ::= */
+ case 288: /* key_opt ::= */
{ yygotominor.yy172 = 0; }
break;
- case 271: /* when_clause ::= WHEN expr */
- case 288: /* key_opt ::= KEY expr */
+ case 272: /* when_clause ::= WHEN expr */
+ case 289: /* key_opt ::= KEY expr */
{ yygotominor.yy172 = yymsp[0].minor.yy172; }
break;
- case 272: /* trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */
+ case 273: /* trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */
{
if( yymsp[-2].minor.yy243 ){
yymsp[-2].minor.yy243->pLast->pNext = yymsp[-1].minor.yy243;
}else{
@@ -71858,27 +75784,27 @@
yymsp[-2].minor.yy243->pLast = yymsp[-1].minor.yy243;
yygotominor.yy243 = yymsp[-2].minor.yy243;
}
break;
- case 273: /* trigger_cmd_list ::= */
+ case 274: /* trigger_cmd_list ::= */
{ yygotominor.yy243 = 0; }
break;
- case 274: /* trigger_cmd ::= UPDATE orconf nm SET setlist where_opt */
+ case 275: /* trigger_cmd ::= UPDATE orconf nm SET setlist where_opt */
{ yygotominor.yy243 = sqlite3TriggerUpdateStep(pParse->db, &yymsp[-3].minor.yy410, yymsp[-1].minor.yy174, yymsp[0].minor.yy172, yymsp[-4].minor.yy46); }
break;
- case 275: /* trigger_cmd ::= insert_cmd INTO nm inscollist_opt VALUES LP itemlist RP */
+ case 276: /* trigger_cmd ::= insert_cmd INTO nm inscollist_opt VALUES LP itemlist RP */
{yygotominor.yy243 = sqlite3TriggerInsertStep(pParse->db, &yymsp[-5].minor.yy410, yymsp[-4].minor.yy432, yymsp[-1].minor.yy174, 0, yymsp[-7].minor.yy46);}
break;
- case 276: /* trigger_cmd ::= insert_cmd INTO nm inscollist_opt select */
+ case 277: /* trigger_cmd ::= insert_cmd INTO nm inscollist_opt select */
{yygotominor.yy243 = sqlite3TriggerInsertStep(pParse->db, &yymsp[-2].minor.yy410, yymsp[-1].minor.yy432, 0, yymsp[0].minor.yy219, yymsp[-4].minor.yy46);}
break;
- case 277: /* trigger_cmd ::= DELETE FROM nm where_opt */
+ case 278: /* trigger_cmd ::= DELETE FROM nm where_opt */
{yygotominor.yy243 = sqlite3TriggerDeleteStep(pParse->db, &yymsp[-1].minor.yy410, yymsp[0].minor.yy172);}
break;
- case 278: /* trigger_cmd ::= select */
+ case 279: /* trigger_cmd ::= select */
{yygotominor.yy243 = sqlite3TriggerSelectStep(pParse->db, yymsp[0].minor.yy219); }
break;
- case 279: /* expr ::= RAISE LP IGNORE RP */
+ case 280: /* expr ::= RAISE LP IGNORE RP */
{
yygotominor.yy172 = sqlite3PExpr(pParse, TK_RAISE, 0, 0, 0);
if( yygotominor.yy172 ){
yygotominor.yy172->iColumn = OE_Ignore;
@@ -71885,9 +75811,9 @@
sqlite3ExprSpan(yygotominor.yy172, &yymsp[-3].minor.yy0, &yymsp[0].minor.yy0);
}
}
break;
- case 280: /* expr ::= RAISE LP raisetype COMMA nm RP */
+ case 281: /* expr ::= RAISE LP raisetype COMMA nm RP */
{
yygotominor.yy172 = sqlite3PExpr(pParse, TK_RAISE, 0, 0, &yymsp[-1].minor.yy410);
if( yygotominor.yy172 ) {
yygotominor.yy172->iColumn = yymsp[-3].minor.yy46;
@@ -71894,74 +75820,74 @@
sqlite3ExprSpan(yygotominor.yy172, &yymsp[-5].minor.yy0, &yymsp[0].minor.yy0);
}
}
break;
- case 281: /* raisetype ::= ROLLBACK */
+ case 282: /* raisetype ::= ROLLBACK */
{yygotominor.yy46 = OE_Rollback;}
break;
- case 283: /* raisetype ::= FAIL */
+ case 284: /* raisetype ::= FAIL */
{yygotominor.yy46 = OE_Fail;}
break;
- case 284: /* cmd ::= DROP TRIGGER ifexists fullname */
+ case 285: /* cmd ::= DROP TRIGGER ifexists fullname */
{
sqlite3DropTrigger(pParse,yymsp[0].minor.yy373,yymsp[-1].minor.yy46);
}
break;
- case 285: /* cmd ::= ATTACH database_kw_opt expr AS expr key_opt */
+ case 286: /* cmd ::= ATTACH database_kw_opt expr AS expr key_opt */
{
sqlite3Attach(pParse, yymsp[-3].minor.yy172, yymsp[-1].minor.yy172, yymsp[0].minor.yy172);
}
break;
- case 286: /* cmd ::= DETACH database_kw_opt expr */
+ case 287: /* cmd ::= DETACH database_kw_opt expr */
{
sqlite3Detach(pParse, yymsp[0].minor.yy172);
}
break;
- case 291: /* cmd ::= REINDEX */
+ case 292: /* cmd ::= REINDEX */
{sqlite3Reindex(pParse, 0, 0);}
break;
- case 292: /* cmd ::= REINDEX nm dbnm */
+ case 293: /* cmd ::= REINDEX nm dbnm */
{sqlite3Reindex(pParse, &yymsp[-1].minor.yy410, &yymsp[0].minor.yy410);}
break;
- case 293: /* cmd ::= ANALYZE */
+ case 294: /* cmd ::= ANALYZE */
{sqlite3Analyze(pParse, 0, 0);}
break;
- case 294: /* cmd ::= ANALYZE nm dbnm */
+ case 295: /* cmd ::= ANALYZE nm dbnm */
{sqlite3Analyze(pParse, &yymsp[-1].minor.yy410, &yymsp[0].minor.yy410);}
break;
- case 295: /* cmd ::= ALTER TABLE fullname RENAME TO nm */
+ case 296: /* cmd ::= ALTER TABLE fullname RENAME TO nm */
{
sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy373,&yymsp[0].minor.yy410);
}
break;
- case 296: /* cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt column */
+ case 297: /* cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt column */
{
sqlite3AlterFinishAddColumn(pParse, &yymsp[0].minor.yy410);
}
break;
- case 297: /* add_column_fullname ::= fullname */
+ case 298: /* add_column_fullname ::= fullname */
{
sqlite3AlterBeginAddColumn(pParse, yymsp[0].minor.yy373);
}
break;
- case 300: /* cmd ::= create_vtab */
+ case 301: /* cmd ::= create_vtab */
{sqlite3VtabFinishParse(pParse,0);}
break;
- case 301: /* cmd ::= create_vtab LP vtabarglist RP */
+ case 302: /* cmd ::= create_vtab LP vtabarglist RP */
{sqlite3VtabFinishParse(pParse,&yymsp[0].minor.yy0);}
break;
- case 302: /* create_vtab ::= CREATE VIRTUAL TABLE nm dbnm USING nm */
+ case 303: /* create_vtab ::= CREATE VIRTUAL TABLE nm dbnm USING nm */
{
sqlite3VtabBeginParse(pParse, &yymsp[-3].minor.yy410, &yymsp[-2].minor.yy410, &yymsp[0].minor.yy410);
}
break;
- case 305: /* vtabarg ::= */
+ case 306: /* vtabarg ::= */
{sqlite3VtabArgInit(pParse);}
break;
- case 307: /* vtabargtoken ::= ANY */
- case 308: /* vtabargtoken ::= lp anylist RP */
- case 309: /* lp ::= LP */
- case 311: /* anylist ::= anylist ANY */
+ case 308: /* vtabargtoken ::= ANY */
+ case 309: /* vtabargtoken ::= lp anylist RP */
+ case 310: /* lp ::= LP */
+ case 312: /* anylist ::= anylist ANY */
{sqlite3VtabArgExtend(pParse,&yymsp[0].minor.yy0);}
break;
};
yygoto = yyRuleInfo[yyruleno].lhs;
@@ -72081,9 +76007,10 @@
yypParser = (yyParser*)yyp;
if( yypParser->yyidx<0 ){
#if YYSTACKDEPTH<=0
if( yypParser->yystksz <=0 ){
- memset(&yyminorunion, 0, sizeof(yyminorunion));
+ /*memset(&yyminorunion, 0, sizeof(yyminorunion));*/
+ yyminorunion = yyzerominor;
yyStackOverflow(yypParser, &yyminorunion);
return;
}
#endif
@@ -72219,9 +76146,9 @@
** This file contains C code that splits an SQL input string up into
** individual tokens and sends those tokens one-by-one over to the
** parser for analysis.
**
-** $Id: tokenize.c,v 1.138 2008/01/22 23:37:10 drh Exp $
+** $Id: tokenize.c,v 1.142 2008/04/28 18:46:43 drh Exp $
*/
/*
** The charMap() macro maps alphabetic characters into their
@@ -72437,9 +76364,9 @@
/*
** Return the length of the token that begins at z[0].
** Store the token type in *tokenType before returning.
*/
-static int getToken(const unsigned char *z, int *tokenType){
+SQLITE_PRIVATE int sqlite3GetToken(const unsigned char *z, int *tokenType){
int i, c;
switch( *z ){
case ' ': case '\t': case '\n': case '\f': case '\r': {
for(i=1; isspace(z[i]); i++){}
@@ -72687,11 +76614,8 @@
}
*tokenType = TK_ILLEGAL;
return 1;
}
-SQLITE_PRIVATE int sqlite3GetToken(const unsigned char *z, int *tokenType){
- return getToken(z, tokenType);
-}
/*
** Run the parser on the given SQL string. The parser structure is
** passed in. An SQLITE_ status code is returned. If an error occurs
@@ -72705,13 +76629,15 @@
void *pEngine;
int tokenType;
int lastTokenParsed = -1;
sqlite3 *db = pParse->db;
+ int mxSqlLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH];
if( db->activeVdbeCnt==0 ){
db->u1.isInterrupted = 0;
}
pParse->rc = SQLITE_OK;
+ pParse->zTail = pParse->zSql = zSql;
i = 0;
pEngine = sqlite3ParserAlloc((void*(*)(size_t))sqlite3_malloc);
if( pEngine==0 ){
db->mallocFailed = 1;
@@ -72723,16 +76649,15 @@
assert( pParse->nVar==0 );
assert( pParse->nVarExpr==0 );
assert( pParse->nVarExprAlloc==0 );
assert( pParse->apVarExpr==0 );
- pParse->zTail = pParse->zSql = zSql;
while( !db->mallocFailed && zSql[i]!=0 ){
assert( i>=0 );
pParse->sLastToken.z = (u8*)&zSql[i];
assert( pParse->sLastToken.dyn==0 );
- pParse->sLastToken.n = getToken((unsigned char*)&zSql[i],&tokenType);
+ pParse->sLastToken.n = sqlite3GetToken((unsigned char*)&zSql[i],&tokenType);
i += pParse->sLastToken.n;
- if( SQLITE_MAX_SQL_LENGTH>0 && i>SQLITE_MAX_SQL_LENGTH ){
+ if( i>mxSqlLen ){
pParse->rc = SQLITE_TOOBIG;
break;
}
switch( tokenType ){
@@ -72801,8 +76726,11 @@
sqlite3_free(pParse->aTableLock);
pParse->aTableLock = 0;
pParse->nTableLock = 0;
}
+#endif
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ sqlite3_free(pParse->apVtabLock);
#endif
if( !IN_DECLARE_VTAB ){
/* If the pParse->declareVtab flag is set, do not delete any table
@@ -73110,9 +77038,9 @@
** implement the programmer interface to the library. Routines in
** other files are for internal use by SQLite and should not be
** accessed by users of the library.
**
-** $Id: main.c,v 1.417 2008/01/31 15:31:02 danielk1977 Exp $
+** $Id: main.c,v 1.439 2008/05/13 13:27:34 drh Exp $
*/
#ifdef SQLITE_ENABLE_FTS3
/************** Include fts3.h in the middle of main.c ***********************/
/************** Begin file fts3.h ********************************************/
@@ -73153,15 +77081,17 @@
SQLITE_API const char *sqlite3_libversion(void){ return sqlite3_version; }
SQLITE_API int sqlite3_libversion_number(void){ return SQLITE_VERSION_NUMBER; }
SQLITE_API int sqlite3_threadsafe(void){ return SQLITE_THREADSAFE; }
+#if !defined(SQLITE_OMIT_TRACE) && defined(SQLITE_ENABLE_IOTRACE)
/*
** If the following function pointer is not NULL and if
** SQLITE_ENABLE_IOTRACE is enabled, then messages describing
** I/O active are written using this function. These messages
** are intended for debugging activity only.
*/
-SQLITE_API void (*sqlite3_io_trace)(const char*, ...) = 0;
+SQLITE_PRIVATE void (*sqlite3IoTrace)(const char*, ...) = 0;
+#endif
/*
** If the following global variable points to a string which is the
** name of a directory, then that directory will be used to store
@@ -73170,14 +77100,24 @@
** See also the "PRAGMA temp_store_directory" SQL command.
*/
SQLITE_API char *sqlite3_temp_directory = 0;
+/*
+** Routine needed to support the testcase() macro.
+*/
+#ifdef SQLITE_COVERAGE_TEST
+SQLITE_PRIVATE void sqlite3Coverage(int x){
+ static int dummy = 0;
+ dummy += x;
+}
+#endif
+
/*
** Return true if the buffer z[0..n-1] contains all spaces.
*/
static int allSpaces(const char *z, int n){
- while( n>0 && z[--n]==' ' ){}
+ while( n>0 && z[n-1]==' ' ){ n--; }
return n==0;
}
/*
@@ -73365,9 +77305,9 @@
SQLITE_PRIVATE void sqlite3RollbackAll(sqlite3 *db){
int i;
int inTrans = 0;
assert( sqlite3_mutex_held(db->mutex) );
- sqlite3FaultBenign(SQLITE_FAULTINJECTOR_MALLOC, 1);
+ sqlite3FaultBeginBenign(SQLITE_FAULTINJECTOR_MALLOC);
for(i=0; i<db->nDb; i++){
if( db->aDb[i].pBt ){
if( sqlite3BtreeIsInTrans(db->aDb[i].pBt) ){
inTrans = 1;
@@ -73376,9 +77316,9 @@
db->aDb[i].inTrans = 0;
}
}
sqlite3VtabRollback(db);
- sqlite3FaultBenign(SQLITE_FAULTINJECTOR_MALLOC, 0);
+ sqlite3FaultEndBenign(SQLITE_FAULTINJECTOR_MALLOC);
if( db->flags&SQLITE_InternChanges ){
sqlite3ExpirePreparedStatements(db);
sqlite3ResetInternalSchema(db, 0);
@@ -73417,9 +77357,9 @@
case SQLITE_TOOBIG: z = "String or BLOB exceeded size limit"; break;
case SQLITE_CONSTRAINT: z = "constraint failed"; break;
case SQLITE_MISMATCH: z = "datatype mismatch"; break;
case SQLITE_MISUSE: z = "library routine called out of sequence";break;
- case SQLITE_NOLFS: z = "kernel lacks large file support"; break;
+ case SQLITE_NOLFS: z = "large file support is disabled"; break;
case SQLITE_AUTH: z = "authorization denied"; break;
case SQLITE_FORMAT: z = "auxiliary database format error"; break;
case SQLITE_RANGE: z = "bind or column index out of range"; break;
case SQLITE_NOTADB: z = "file is encrypted or is not a database";break;
@@ -73664,9 +77604,8 @@
void (*xFinal)(sqlite3_context*)
){
int rc;
sqlite3_mutex_enter(db->mutex);
- assert( !db->mallocFailed );
rc = sqlite3CreateFunc(db, zFunctionName, nArg, enc, p, xFunc, xStep, xFinal);
rc = sqlite3ApiExit(db, rc);
sqlite3_mutex_leave(db->mutex);
return rc;
@@ -74053,8 +77992,83 @@
}
/*
+** This array defines hard upper bounds on limit values. The
+** initializer must be kept in sync with the SQLITE_LIMIT_*
+** #defines in sqlite3.h.
+*/
+static const int aHardLimit[] = {
+ SQLITE_MAX_LENGTH,
+ SQLITE_MAX_SQL_LENGTH,
+ SQLITE_MAX_COLUMN,
+ SQLITE_MAX_EXPR_DEPTH,
+ SQLITE_MAX_COMPOUND_SELECT,
+ SQLITE_MAX_VDBE_OP,
+ SQLITE_MAX_FUNCTION_ARG,
+ SQLITE_MAX_ATTACHED,
+ SQLITE_MAX_LIKE_PATTERN_LENGTH,
+ SQLITE_MAX_VARIABLE_NUMBER,
+};
+
+/*
+** Make sure the hard limits are set to reasonable values
+*/
+#if SQLITE_MAX_LENGTH<100
+# error SQLITE_MAX_LENGTH must be at least 100
+#endif
+#if SQLITE_MAX_SQL_LENGTH<100
+# error SQLITE_MAX_SQL_LENGTH must be at least 100
+#endif
+#if SQLITE_MAX_SQL_LENGTH>SQLITE_MAX_LENGTH
+# error SQLITE_MAX_SQL_LENGTH must not be greater than SQLITE_MAX_LENGTH
+#endif
+#if SQLITE_MAX_COMPOUND_SELECT<2
+# error SQLITE_MAX_COMPOUND_SELECT must be at least 2
+#endif
+#if SQLITE_MAX_VDBE_OP<40
+# error SQLITE_MAX_VDBE_OP must be at least 40
+#endif
+#if SQLITE_MAX_FUNCTION_ARG<0 || SQLITE_MAX_FUNCTION_ARG>255
+# error SQLITE_MAX_FUNCTION_ARG must be between 0 and 255
+#endif
+#if SQLITE_MAX_ATTACH<0 || SQLITE_MAX_ATTACH>30
+# error SQLITE_MAX_ATTACH must be between 0 and 30
+#endif
+#if SQLITE_MAX_LIKE_PATTERN_LENGTH<1
+# error SQLITE_MAX_LIKE_PATTERN_LENGTH must be at least 1
+#endif
+#if SQLITE_MAX_VARIABLE_NUMBER<1
+# error SQLITE_MAX_VARIABLE_NUMBER must be at least 1
+#endif
+
+
+/*
+** Change the value of a limit. Report the old value.
+** If an invalid limit index is supplied, report -1.
+** Make no changes but still report the old value if the
+** new limit is negative.
+**
+** A new lower limit does not shrink existing constructs.
+** It merely prevents new constructs that exceed the limit
+** from forming.
+*/
+SQLITE_API int sqlite3_limit(sqlite3 *db, int limitId, int newLimit){
+ int oldLimit;
+ if( limitId<0 || limitId>=SQLITE_N_LIMIT ){
+ return -1;
+ }
+ oldLimit = db->aLimit[limitId];
+ if( newLimit>=0 ){
+ if( newLimit>aHardLimit[limitId] ){
+ newLimit = aHardLimit[limitId];
+ }
+ db->aLimit[limitId] = newLimit;
+ }
+ return oldLimit;
+}
+
+/*
** This routine does the work of opening a database on behalf of
** sqlite3_open() and sqlite3_open16(). The database filename "zFilename"
** is UTF-8 encoded.
*/
@@ -74066,8 +78080,19 @@
){
sqlite3 *db;
int rc;
CollSeq *pColl;
+
+ /* Remove harmful bits from the flags parameter */
+ flags &= ~( SQLITE_OPEN_DELETEONCLOSE |
+ SQLITE_OPEN_MAIN_DB |
+ SQLITE_OPEN_TEMP_DB |
+ SQLITE_OPEN_TRANSIENT_DB |
+ SQLITE_OPEN_MAIN_JOURNAL |
+ SQLITE_OPEN_TEMP_JOURNAL |
+ SQLITE_OPEN_SUBJOURNAL |
+ SQLITE_OPEN_MASTER_JOURNAL
+ );
/* Allocate the sqlite data structure */
db = sqlite3MallocZero( sizeof(sqlite3) );
if( db==0 ) goto opendb_out;
@@ -74082,10 +78107,13 @@
db->priorNewRowid = 0;
db->nDb = 2;
db->magic = SQLITE_MAGIC_BUSY;
db->aDb = db->aDbStatic;
+ assert( sizeof(db->aLimit)==sizeof(aHardLimit) );
+ memcpy(db->aLimit, aHardLimit, sizeof(db->aLimit));
db->autoCommit = 1;
db->nextAutovac = -1;
+ db->nextPagesize = 0;
db->flags |= SQLITE_ShortColNames
#if SQLITE_DEFAULT_FILE_FORMAT<4
| SQLITE_LegacyFileFmt
#endif
@@ -74102,26 +78130,26 @@
db->pVfs = sqlite3_vfs_find(zVfs);
if( !db->pVfs ){
rc = SQLITE_ERROR;
db->magic = SQLITE_MAGIC_SICK;
- sqlite3Error(db, rc, "no such vfs: %s", (zVfs?zVfs:"(null)"));
+ sqlite3Error(db, rc, "no such vfs: %s", zVfs);
goto opendb_out;
}
/* Add the default collation sequence BINARY. BINARY works for both UTF-8
** and UTF-16, so add a version for each to avoid any unnecessary
** conversions. The only error that can occur here is a malloc() failure.
*/
- if( createCollation(db, "BINARY", SQLITE_UTF8, 0, binCollFunc, 0) ||
- createCollation(db, "BINARY", SQLITE_UTF16BE, 0, binCollFunc, 0) ||
- createCollation(db, "BINARY", SQLITE_UTF16LE, 0, binCollFunc, 0) ||
- createCollation(db, "RTRIM", SQLITE_UTF8, (void*)1, binCollFunc, 0) ||
- (db->pDfltColl = sqlite3FindCollSeq(db, SQLITE_UTF8, "BINARY", 6, 0))==0
- ){
- assert( db->mallocFailed );
+ createCollation(db, "BINARY", SQLITE_UTF8, 0, binCollFunc, 0);
+ createCollation(db, "BINARY", SQLITE_UTF16BE, 0, binCollFunc, 0);
+ createCollation(db, "BINARY", SQLITE_UTF16LE, 0, binCollFunc, 0);
+ createCollation(db, "RTRIM", SQLITE_UTF8, (void*)1, binCollFunc, 0);
+ if( db->mallocFailed ){
db->magic = SQLITE_MAGIC_SICK;
goto opendb_out;
}
+ db->pDfltColl = sqlite3FindCollSeq(db, SQLITE_UTF8, "BINARY", 6, 0);
+ assert( db->pDfltColl!=0 );
/* Also add a UTF-8 case-insensitive collation sequence. */
createCollation(db, "NOCASE", SQLITE_UTF8, 0, nocaseCollatingFunc, 0);
@@ -74214,9 +78242,10 @@
SQLITE_DEFAULT_LOCKING_MODE);
#endif
opendb_out:
- if( db && db->mutex ){
+ if( db ){
+ assert( db->mutex!=0 );
sqlite3_mutex_leave(db->mutex);
}
if( SQLITE_NOMEM==(rc = sqlite3_errcode(db)) ){
sqlite3_close(db);
@@ -74265,14 +78294,11 @@
zFilename8 = sqlite3ValueText(pVal, SQLITE_UTF8);
if( zFilename8 ){
rc = openDatabase(zFilename8, ppDb,
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, 0);
- if( rc==SQLITE_OK && *ppDb ){
- rc = sqlite3_exec(*ppDb, "PRAGMA encoding = 'UTF-16'", 0, 0, 0);
- if( rc!=SQLITE_OK ){
- sqlite3_close(*ppDb);
- *ppDb = 0;
- }
+ assert( *ppDb || rc==SQLITE_NOMEM );
+ if( rc==SQLITE_OK && !DbHasProperty(*ppDb, 0, DB_SchemaLoaded) ){
+ ENC(*ppDb) = SQLITE_UTF16NATIVE;
}
}
sqlite3ValueFree(pVal);
@@ -74452,11 +78478,13 @@
int primarykey = 0;
int autoinc = 0;
/* Ensure the database schema has been loaded */
- (void)sqlite3SafetyOn(db);
sqlite3_mutex_enter(db->mutex);
+ (void)sqlite3SafetyOn(db);
+ sqlite3BtreeEnterAll(db);
rc = sqlite3Init(db, &zErrMsg);
+ sqlite3BtreeLeaveAll(db);
if( SQLITE_OK!=rc ){
goto error_out;
}
@@ -74598,38 +78626,111 @@
/*
** Interface to the testing logic.
*/
SQLITE_API int sqlite3_test_control(int op, ...){
- va_list ap;
int rc = 0;
+#ifndef SQLITE_OMIT_BUILTIN_TEST
+ va_list ap;
va_start(ap, op);
switch( op ){
-#ifndef SQLITE_OMIT_FAULTINJECTOR
+ /*
+ ** sqlite3_test_control(FAULT_CONFIG, fault_id, nDelay, nRepeat)
+ **
+ ** Configure a fault injector. The specific fault injector is
+ ** identified by the fault_id argument. (ex: SQLITE_FAULTINJECTOR_MALLOC)
+ ** The fault will occur after a delay of nDelay calls. The fault
+ ** will repeat nRepeat times.
+ */
case SQLITE_TESTCTRL_FAULT_CONFIG: {
int id = va_arg(ap, int);
int nDelay = va_arg(ap, int);
int nRepeat = va_arg(ap, int);
sqlite3FaultConfig(id, nDelay, nRepeat);
break;
}
+
+ /*
+ ** sqlite3_test_control(FAULT_FAILURES, fault_id)
+ **
+ ** Return the number of faults (both hard and benign faults) that have
+ ** occurred since the injector identified by fault_id) was last configured.
+ */
case SQLITE_TESTCTRL_FAULT_FAILURES: {
int id = va_arg(ap, int);
rc = sqlite3FaultFailures(id);
break;
}
+
+ /*
+ ** sqlite3_test_control(FAULT_BENIGN_FAILURES, fault_id)
+ **
+ ** Return the number of benign faults that have occurred since the
+ ** injector identified by fault_id was last configured.
+ */
case SQLITE_TESTCTRL_FAULT_BENIGN_FAILURES: {
int id = va_arg(ap, int);
rc = sqlite3FaultBenignFailures(id);
break;
}
+
+ /*
+ ** sqlite3_test_control(FAULT_PENDING, fault_id)
+ **
+ ** Return the number of successes that will occur before the next
+ ** scheduled failure on fault injector fault_id.
+ ** If no failures are scheduled, return -1.
+ */
case SQLITE_TESTCTRL_FAULT_PENDING: {
int id = va_arg(ap, int);
rc = sqlite3FaultPending(id);
break;
}
-#endif /* SQLITE_OMIT_FAULTINJECTOR */
+
+ /*
+ ** Save the current state of the PRNG.
+ */
+ case SQLITE_TESTCTRL_PRNG_SAVE: {
+ sqlite3PrngSaveState();
+ break;
+ }
+
+ /*
+ ** Restore the state of the PRNG to the last state saved using
+ ** PRNG_SAVE. If PRNG_SAVE has never before been called, then
+ ** this verb acts like PRNG_RESET.
+ */
+ case SQLITE_TESTCTRL_PRNG_RESTORE: {
+ sqlite3PrngRestoreState();
+ break;
+ }
+
+ /*
+ ** Reset the PRNG back to its uninitialized state. The next call
+ ** to sqlite3_randomness() will reseed the PRNG using a single call
+ ** to the xRandomness method of the default VFS.
+ */
+ case SQLITE_TESTCTRL_PRNG_RESET: {
+ sqlite3PrngResetState();
+ break;
+ }
+
+ /*
+ ** sqlite3_test_control(BITVEC_TEST, size, program)
+ **
+ ** Run a test against a Bitvec object of size. The program argument
+ ** is an array of integers that defines the test. Return -1 on a
+ ** memory allocation error, 0 on success, or non-zero for an error.
+ ** See the sqlite3BitvecBuiltinTest() for additional information.
+ */
+ case SQLITE_TESTCTRL_BITVEC_TEST: {
+ int sz = va_arg(ap, int);
+ int *aProg = va_arg(ap, int*);
+ rc = sqlite3BitvecBuiltinTest(sz, aProg);
+ break;
+ }
}
va_end(ap);
+#endif /* SQLITE_OMIT_BUILTIN_TEST */
return rc;
}
/************** End of main.c ************************************************/
@@ -78262,10 +82363,10 @@
** trimSnippetOffsetsForNear() function for details). Ignore
** it in this case
*/
zBuf[0] = ' ';
- sprintf(&zBuf[cnt>0], "%d %d %d %d", pMatch->iCol,
- pMatch->iTerm, pMatch->iStart, pMatch->nByte);
+ sqlite3_snprintf(sizeof(zBuf)-1, &zBuf[cnt>0], "%d %d %d %d",
+ pMatch->iCol, pMatch->iTerm, pMatch->iStart, pMatch->nByte);
append(&sb, zBuf);
cnt++;
}
}